summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnatol Pomozov <anatol.pomozov@gmail.com>2012-03-28 09:12:55 -0700
committerAnatol Pomozov <anatol.pomozov@gmail.com>2012-03-28 12:02:47 -0700
commitb0b2b4d890cf3bfb274797a759642b4e733343d7 (patch)
tree12ad21cbad346f02d542aa4d672ffd76407d58a9
parent51f8eec23a2bcc2cc190373cdd1195972d9b8804 (diff)
parent5a5491c17d74bd2c80cf451c6ddbba22d5d5f08a (diff)
downloadframeworks_av-b0b2b4d890cf3bfb274797a759642b4e733343d7.zip
frameworks_av-b0b2b4d890cf3bfb274797a759642b4e733343d7.tar.gz
frameworks_av-b0b2b4d890cf3bfb274797a759642b4e733343d7.tar.bz2
Merge media files with history from frameworks/base.git
-rw-r--r--camera/Android.mk23
-rw-r--r--camera/Camera.cpp448
-rw-r--r--camera/CameraParameters.cpp479
-rw-r--r--camera/ICamera.cpp420
-rw-r--r--camera/ICameraClient.cpp132
-rw-r--r--camera/ICameraRecordingProxy.cpp109
-rw-r--r--camera/ICameraRecordingProxyListener.cpp75
-rw-r--r--camera/ICameraService.cpp113
-rw-r--r--cmds/stagefright/Android.mk167
-rw-r--r--cmds/stagefright/SimplePlayer.cpp645
-rw-r--r--cmds/stagefright/SimplePlayer.h109
-rw-r--r--cmds/stagefright/SineSource.cpp102
-rw-r--r--cmds/stagefright/SineSource.h39
-rw-r--r--cmds/stagefright/WaveWriter.h71
-rw-r--r--cmds/stagefright/audioloop.cpp101
-rw-r--r--cmds/stagefright/codec.cpp495
-rw-r--r--cmds/stagefright/jpeg.cpp91
-rw-r--r--cmds/stagefright/jpeg.h6
-rw-r--r--cmds/stagefright/record.cpp354
-rw-r--r--cmds/stagefright/recordvideo.cpp302
-rw-r--r--cmds/stagefright/sf2.cpp658
-rw-r--r--cmds/stagefright/stagefright.cpp1108
-rw-r--r--cmds/stagefright/stream.cpp375
-rw-r--r--drm/common/Android.mk43
-rw-r--r--drm/common/DrmConstraints.cpp113
-rw-r--r--drm/common/DrmConvertedStatus.cpp28
-rw-r--r--drm/common/DrmEngineBase.cpp166
-rw-r--r--drm/common/DrmInfo.cpp111
-rw-r--r--drm/common/DrmInfoEvent.cpp40
-rw-r--r--drm/common/DrmInfoRequest.cpp106
-rw-r--r--drm/common/DrmInfoStatus.cpp29
-rw-r--r--drm/common/DrmMetadata.cpp117
-rw-r--r--drm/common/DrmRights.cpp63
-rw-r--r--drm/common/DrmSupportInfo.cpp159
-rw-r--r--drm/common/IDrmManagerService.cpp1447
-rw-r--r--drm/common/IDrmServiceListener.cpp61
-rw-r--r--drm/common/ReadWriteUtils.cpp109
-rw-r--r--drm/drmserver/Android.mk41
-rw-r--r--drm/drmserver/DrmManager.cpp606
-rw-r--r--drm/drmserver/DrmManagerService.cpp308
-rw-r--r--drm/drmserver/main_drmserver.cpp38
-rw-r--r--drm/libdrmframework/Android.mk44
-rw-r--r--drm/libdrmframework/DrmManagerClient.cpp160
-rw-r--r--drm/libdrmframework/DrmManagerClientImpl.cpp351
-rw-r--r--drm/libdrmframework/include/DrmManager.h163
-rw-r--r--drm/libdrmframework/include/DrmManagerClientImpl.h432
-rw-r--r--drm/libdrmframework/include/DrmManagerService.h129
-rw-r--r--drm/libdrmframework/include/IDrmManagerService.h263
-rw-r--r--drm/libdrmframework/include/IDrmServiceListener.h71
-rw-r--r--drm/libdrmframework/include/PlugInManager.h269
-rw-r--r--drm/libdrmframework/include/ReadWriteUtils.h79
-rw-r--r--drm/libdrmframework/plugins/Android.mk16
-rw-r--r--drm/libdrmframework/plugins/common/Android.mk16
-rw-r--r--drm/libdrmframework/plugins/common/include/DrmEngineBase.h508
-rw-r--r--drm/libdrmframework/plugins/common/include/IDrmEngine.h420
-rw-r--r--drm/libdrmframework/plugins/common/util/Android.mk52
-rw-r--r--drm/libdrmframework/plugins/common/util/include/MimeTypeUtil.h46
-rw-r--r--drm/libdrmframework/plugins/common/util/include/SessionMap.h189
-rw-r--r--drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp166
-rw-r--r--drm/libdrmframework/plugins/forward-lock/Android.mk16
-rw-r--r--drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk70
-rw-r--r--drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h567
-rw-r--r--drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp695
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/Android.mk16
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk32
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.c191
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.h85
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk37
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c1347
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h282
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk37
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c454
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.h135
-rwxr-xr-xdrm/libdrmframework/plugins/forward-lock/internal-format/doc/FwdLock.html1039
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image001.gifbin0 -> 5571 bytes
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image002.gifbin0 -> 11149 bytes
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image003.gifbin0 -> 13873 bytes
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image004.gifbin0 -> 10779 bytes
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image005.gifbin0 -> 9351 bytes
-rw-r--r--drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image006.gifbin0 -> 9048 bytes
-rw-r--r--drm/libdrmframework/plugins/passthru/Android.mk42
-rw-r--r--drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h102
-rw-r--r--drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp305
-rw-r--r--include/camera/Camera.h196
-rw-r--r--include/camera/ICamera.h122
-rw-r--r--include/camera/ICameraClient.h53
-rw-r--r--include/camera/ICameraRecordingProxy.h101
-rw-r--r--include/camera/ICameraRecordingProxyListener.h52
-rw-r--r--include/camera/ICameraService.h61
-rw-r--r--include/common_time/ICommonClock.h108
-rw-r--r--include/common_time/ICommonTimeConfig.h73
-rw-r--r--include/common_time/cc_helper.h72
-rw-r--r--include/common_time/local_clock.h47
-rw-r--r--include/drm/DrmConstraints.h183
-rw-r--r--include/drm/DrmConvertedStatus.h67
-rw-r--r--include/drm/DrmInfo.h176
-rw-r--r--include/drm/DrmInfoEvent.h118
-rw-r--r--include/drm/DrmInfoRequest.h177
-rw-r--r--include/drm/DrmInfoStatus.h67
-rw-r--r--include/drm/DrmManagerClient.h379
-rw-r--r--include/drm/DrmMetadata.h111
-rw-r--r--include/drm/DrmRights.h106
-rw-r--r--include/drm/DrmSupportInfo.h191
-rw-r--r--include/drm/drm_framework_common.h337
-rw-r--r--include/media/AudioEffect.h459
-rw-r--r--include/media/AudioParameter.h72
-rw-r--r--include/media/AudioRecord.h397
-rw-r--r--include/media/AudioSystem.h261
-rw-r--r--include/media/AudioTrack.h553
-rw-r--r--include/media/EffectsFactoryApi.h177
-rw-r--r--include/media/IAudioFlinger.h199
-rw-r--r--include/media/IAudioFlingerClient.h56
-rw-r--r--include/media/IAudioPolicyService.h113
-rw-r--r--include/media/IAudioRecord.h69
-rw-r--r--include/media/IAudioTrack.h108
-rw-r--r--include/media/ICrypto.h63
-rw-r--r--include/media/IEffect.h60
-rw-r--r--include/media/IEffectClient.h54
-rw-r--r--include/media/IMediaDeathNotifier.h61
-rw-r--r--include/media/IMediaMetadataRetriever.h58
-rw-r--r--include/media/IMediaPlayer.h113
-rw-r--r--include/media/IMediaPlayerClient.h47
-rw-r--r--include/media/IMediaPlayerService.h91
-rw-r--r--include/media/IMediaRecorder.h74
-rw-r--r--include/media/IMediaRecorderClient.h47
-rw-r--r--include/media/IOMX.h195
-rw-r--r--include/media/IStreamSource.h90
-rw-r--r--include/media/JetPlayer.h127
-rw-r--r--include/media/MediaMetadataRetrieverInterface.h58
-rw-r--r--include/media/MediaPlayerInterface.h230
-rw-r--r--include/media/MediaProfiles.h518
-rw-r--r--include/media/MediaRecorderBase.h67
-rw-r--r--include/media/MemoryLeakTrackUtil.h27
-rw-r--r--include/media/Metadata.h133
-rw-r--r--include/media/ToneGenerator.h313
-rw-r--r--include/media/Visualizer.h159
-rw-r--r--include/media/mediametadataretriever.h100
-rw-r--r--include/media/mediaplayer.h268
-rw-r--r--include/media/mediarecorder.h257
-rw-r--r--include/media/mediascanner.h110
-rw-r--r--include/media/stagefright/AACWriter.h76
-rw-r--r--include/media/stagefright/ACodec.h229
-rw-r--r--include/media/stagefright/AMRWriter.h71
-rw-r--r--include/media/stagefright/AudioPlayer.h121
-rw-r--r--include/media/stagefright/AudioSource.h109
-rw-r--r--include/media/stagefright/CameraSource.h232
-rw-r--r--include/media/stagefright/CameraSourceTimeLapse.h162
-rw-r--r--include/media/stagefright/ColorConverter.h88
-rw-r--r--include/media/stagefright/DataSource.h108
-rw-r--r--include/media/stagefright/FileSource.h70
-rw-r--r--include/media/stagefright/JPEGSource.h58
-rw-r--r--include/media/stagefright/MPEG2TSWriter.h88
-rw-r--r--include/media/stagefright/MPEG4Writer.h195
-rw-r--r--include/media/stagefright/MediaBuffer.h123
-rw-r--r--include/media/stagefright/MediaBufferGroup.h58
-rw-r--r--include/media/stagefright/MediaCodec.h199
-rw-r--r--include/media/stagefright/MediaCodecList.h95
-rw-r--r--include/media/stagefright/MediaDefs.h61
-rw-r--r--include/media/stagefright/MediaErrors.h72
-rw-r--r--include/media/stagefright/MediaExtractor.h82
-rw-r--r--include/media/stagefright/MediaSource.h122
-rw-r--r--include/media/stagefright/MediaWriter.h69
-rw-r--r--include/media/stagefright/MetaData.h244
-rw-r--r--include/media/stagefright/NativeWindowWrapper.h50
-rw-r--r--include/media/stagefright/NuMediaExtractor.h88
-rw-r--r--include/media/stagefright/OMXClient.h45
-rw-r--r--include/media/stagefright/OMXCodec.h390
-rw-r--r--include/media/stagefright/SkipCutBuffer.h58
-rw-r--r--include/media/stagefright/StagefrightMediaScanner.h46
-rw-r--r--include/media/stagefright/SurfaceMediaSource.h371
-rw-r--r--include/media/stagefright/TimeSource.h51
-rw-r--r--include/media/stagefright/Utils.h41
-rw-r--r--include/media/stagefright/VideoSourceDownSampler.h97
-rw-r--r--include/media/stagefright/YUVCanvas.h79
-rw-r--r--include/media/stagefright/YUVImage.h178
-rw-r--r--include/media/stagefright/foundation/AAtomizer.h51
-rw-r--r--include/media/stagefright/foundation/ABase.h25
-rw-r--r--include/media/stagefright/foundation/ABitReader.h54
-rw-r--r--include/media/stagefright/foundation/ABuffer.h71
-rw-r--r--include/media/stagefright/foundation/ADebug.h86
-rw-r--r--include/media/stagefright/foundation/AHandler.h56
-rw-r--r--include/media/stagefright/foundation/AHandlerReflector.h48
-rw-r--r--include/media/stagefright/foundation/AHierarchicalStateMachine.h65
-rw-r--r--include/media/stagefright/foundation/ALooper.h86
-rw-r--r--include/media/stagefright/foundation/ALooperRoster.h65
-rw-r--r--include/media/stagefright/foundation/AMessage.h158
-rw-r--r--include/media/stagefright/foundation/AString.h95
-rw-r--r--include/media/stagefright/foundation/base64.h33
-rw-r--r--include/media/stagefright/foundation/hexdump.h29
-rw-r--r--include/media/stagefright/timedtext/TimedTextDriver.h81
-rw-r--r--include/private/README4
-rw-r--r--include/private/hwui/DrawGlInfo.h67
-rw-r--r--include/private/media/AudioEffectShared.h51
-rw-r--r--include/private/media/AudioTrackShared.h157
-rw-r--r--include/private/media/VideoFrame.h128
-rw-r--r--media/common_time/Android.mk21
-rw-r--r--media/common_time/ICommonClock.cpp432
-rw-r--r--media/common_time/ICommonTimeConfig.cpp508
-rw-r--r--media/common_time/cc_helper.cpp129
-rw-r--r--media/common_time/local_clock.cpp92
-rw-r--r--media/common_time/utils.cpp89
-rw-r--r--media/common_time/utils.h34
-rw-r--r--media/libaah_rtp/Android.mk40
-rw-r--r--media/libaah_rtp/aah_decoder_pump.cpp519
-rw-r--r--media/libaah_rtp/aah_decoder_pump.h107
-rw-r--r--media/libaah_rtp/aah_rx_player.cpp288
-rw-r--r--media/libaah_rtp/aah_rx_player.h318
-rw-r--r--media/libaah_rtp/aah_rx_player_core.cpp809
-rw-r--r--media/libaah_rtp/aah_rx_player_ring_buffer.cpp366
-rw-r--r--media/libaah_rtp/aah_rx_player_substream.cpp677
-rw-r--r--media/libaah_rtp/aah_tx_packet.cpp344
-rw-r--r--media/libaah_rtp/aah_tx_packet.h213
-rw-r--r--media/libaah_rtp/aah_tx_player.cpp1177
-rw-r--r--media/libaah_rtp/aah_tx_player.h176
-rw-r--r--media/libaah_rtp/aah_tx_sender.cpp603
-rw-r--r--media/libaah_rtp/aah_tx_sender.h162
-rw-r--r--media/libaah_rtp/pipe_event.cpp86
-rw-r--r--media/libaah_rtp/pipe_event.h51
-rw-r--r--media/libeffects/data/audio_effects.conf126
-rw-r--r--media/libeffects/downmix/Android.mk28
-rw-r--r--media/libeffects/downmix/EffectDownmix.c889
-rw-r--r--media/libeffects/downmix/EffectDownmix.h96
-rw-r--r--media/libeffects/factory/Android.mk20
-rw-r--r--media/libeffects/factory/EffectsFactory.c730
-rw-r--r--media/libeffects/factory/EffectsFactory.h55
-rw-r--r--media/libeffects/lvm/lib/Android.mk179
-rw-r--r--media/libeffects/lvm/lib/Bass/lib/LVDBE.h464
-rw-r--r--media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h518
-rw-r--r--media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c376
-rw-r--r--media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c284
-rw-r--r--media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h140
-rw-r--r--media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c207
-rw-r--r--media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c456
-rw-r--r--media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h85
-rw-r--r--media/libeffects/lvm/lib/Bundle/lib/LVM.h629
-rw-r--r--media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.c150
-rw-r--r--media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c870
-rw-r--r--media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h573
-rw-r--r--media/libeffects/lvm/lib/Bundle/src/LVM_Control.c1025
-rw-r--r--media/libeffects/lvm/lib/Bundle/src/LVM_Init.c995
-rw-r--r--media/libeffects/lvm/lib/Bundle/src/LVM_Private.h284
-rw-r--r--media/libeffects/lvm/lib/Bundle/src/LVM_Process.c275
-rw-r--r--media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c389
-rw-r--r--media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h59
-rw-r--r--media/libeffects/lvm/lib/Common/lib/AGC.h84
-rw-r--r--media/libeffects/lvm/lib/Common/lib/BIQUAD.h333
-rw-r--r--media/libeffects/lvm/lib/Common/lib/CompLim.h83
-rw-r--r--media/libeffects/lvm/lib/Common/lib/Filter.h62
-rw-r--r--media/libeffects/lvm/lib/Common/lib/InstAlloc.h92
-rw-r--r--media/libeffects/lvm/lib/Common/lib/LVM_Common.h61
-rw-r--r--media/libeffects/lvm/lib/Common/lib/LVM_Macros.h122
-rw-r--r--media/libeffects/lvm/lib/Common/lib/LVM_Timer.h82
-rw-r--r--media/libeffects/lvm/lib/Common/lib/LVM_Types.h187
-rw-r--r--media/libeffects/lvm/lib/Common/lib/Mixer.h127
-rw-r--r--media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h60
-rw-r--r--media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h181
-rw-r--r--media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c196
-rw-r--r--media/libeffects/lvm/lib/Common/src/Abs_32.c50
-rw-r--r--media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.c56
-rw-r--r--media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c60
-rw-r--r--media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c81
-rw-r--r--media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c54
-rw-r--r--media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h30
-rw-r--r--media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c83
-rw-r--r--media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c64
-rw-r--r--media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h30
-rw-r--r--media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c81
-rw-r--r--media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c55
-rw-r--r--media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h30
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c85
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c61
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h30
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c84
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h30
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c62
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c114
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c114
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c62
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h31
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c118
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c117
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c117
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h31
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c61
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c126
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c61
-rw-r--r--media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h32
-rw-r--r--media/libeffects/lvm/lib/Common/src/CompLim_private.h44
-rw-r--r--media/libeffects/lvm/lib/Common/src/Copy_16.c58
-rw-r--r--media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c60
-rw-r--r--media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c94
-rw-r--r--media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c103
-rw-r--r--media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c67
-rw-r--r--media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c27
-rw-r--r--media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h34
-rw-r--r--media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c104
-rw-r--r--media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c73
-rw-r--r--media/libeffects/lvm/lib/Common/src/DelayWrite_32.c57
-rw-r--r--media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c74
-rw-r--r--media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c58
-rw-r--r--media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h31
-rw-r--r--media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c74
-rw-r--r--media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c57
-rw-r--r--media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h32
-rw-r--r--media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c128
-rw-r--r--media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c60
-rw-r--r--media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h32
-rw-r--r--media/libeffects/lvm/lib/Common/src/Filters.h66
-rw-r--r--media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c57
-rw-r--r--media/libeffects/lvm/lib/Common/src/From2iToMono_16.c49
-rw-r--r--media/libeffects/lvm/lib/Common/src/From2iToMono_32.c50
-rw-r--r--media/libeffects/lvm/lib/Common/src/InstAlloc.c186
-rw-r--r--media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.c48
-rw-r--r--media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.c60
-rw-r--r--media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c54
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c69
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c59
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c128
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c143
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c106
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c112
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c152
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c111
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c70
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_Mixer.h136
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c41
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c42
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c67
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h128
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c66
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c75
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c95
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c100
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c97
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c70
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h91
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c156
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c96
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVM_Power10.c78
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVM_Timer.c48
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.c54
-rw-r--r--media/libeffects/lvm/lib/Common/src/LVM_Timer_Private.h52
-rw-r--r--media/libeffects/lvm/lib/Common/src/LoadConst_16.c43
-rw-r--r--media/libeffects/lvm/lib/Common/src/LoadConst_32.c43
-rw-r--r--media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c80
-rw-r--r--media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.c81
-rw-r--r--media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c71
-rw-r--r--media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c95
-rw-r--r--media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c95
-rw-r--r--media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c65
-rw-r--r--media/libeffects/lvm/lib/Common/src/Mixer_private.h36
-rw-r--r--media/libeffects/lvm/lib/Common/src/MonoTo2I_16.c49
-rw-r--r--media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c49
-rw-r--r--media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c51
-rw-r--r--media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c117
-rw-r--r--media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c121
-rw-r--r--media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c119
-rw-r--r--media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c38
-rw-r--r--media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h31
-rw-r--r--media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c37
-rw-r--r--media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h32
-rw-r--r--media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c81
-rw-r--r--media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c83
-rw-r--r--media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c109
-rw-r--r--media/libeffects/lvm/lib/Common/src/mult3s_16x16.c48
-rw-r--r--media/libeffects/lvm/lib/Eq/lib/LVEQNB.h476
-rw-r--r--media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c298
-rw-r--r--media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h106
-rw-r--r--media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c493
-rw-r--r--media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c321
-rw-r--r--media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h133
-rw-r--r--media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c200
-rw-r--r--media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c195
-rw-r--r--media/libeffects/lvm/lib/Reverb/lib/LVREV.h312
-rw-r--r--media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c642
-rw-r--r--media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.c104
-rw-r--r--media/libeffects/lvm/lib/Reverb/src/LVREV_GetControlParameters.c69
-rw-r--r--media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c322
-rw-r--r--media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c245
-rw-r--r--media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h189
-rw-r--r--media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c485
-rw-r--r--media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c119
-rw-r--r--media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c99
-rw-r--r--media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h50
-rw-r--r--media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h290
-rw-r--r--media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c707
-rw-r--r--media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c189
-rw-r--r--media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c169
-rw-r--r--media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h151
-rw-r--r--media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c252
-rw-r--r--media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h90
-rw-r--r--media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c42
-rw-r--r--media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c212
-rw-r--r--media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c241
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h388
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c293
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h81
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c260
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c160
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h58
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h398
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c212
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h166
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c333
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c264
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h90
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c260
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h80
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c448
-rw-r--r--media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.h152
-rw-r--r--media/libeffects/lvm/wrapper/Android.mk60
-rw-r--r--media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp3300
-rw-r--r--media/libeffects/lvm/wrapper/Bundle/EffectBundle.h196
-rwxr-xr-xmedia/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp2185
-rw-r--r--media/libeffects/lvm/wrapper/Reverb/EffectReverb.h46
-rwxr-xr-xmedia/libeffects/preprocessing/Android.mk32
-rwxr-xr-xmedia/libeffects/preprocessing/PreProcessing.cpp1666
-rw-r--r--media/libeffects/testlibs/Android.mk_68
-rw-r--r--media/libeffects/testlibs/AudioBiquadFilter.cpp258
-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.h93
-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.cpp119
-rw-r--r--media/libeffects/testlibs/AudioPeakingFilter.h151
-rw-r--r--media/libeffects/testlibs/AudioPeakingFilterCoef.inl2700
-rw-r--r--media/libeffects/testlibs/AudioShelvingFilter.cpp107
-rw-r--r--media/libeffects/testlibs/AudioShelvingFilter.h146
-rw-r--r--media/libeffects/testlibs/EffectEqualizer.cpp779
-rw-r--r--media/libeffects/testlibs/EffectReverb.c2230
-rw-r--r--media/libeffects/testlibs/EffectReverb.h452
-rw-r--r--media/libeffects/testlibs/EffectsMath.c143
-rw-r--r--media/libeffects/testlibs/EffectsMath.h424
-rw-r--r--media/libeffects/visualizer/Android.mk23
-rw-r--r--media/libeffects/visualizer/EffectVisualizer.cpp534
-rw-r--r--media/libmedia/Android.mk68
-rw-r--r--media/libmedia/AudioEffect.cpp482
-rw-r--r--media/libmedia/AudioParameter.cpp179
-rw-r--r--media/libmedia/AudioRecord.cpp844
-rw-r--r--media/libmedia/AudioSystem.cpp770
-rw-r--r--media/libmedia/AudioTrack.cpp1531
-rw-r--r--media/libmedia/IAudioFlinger.cpp1025
-rw-r--r--media/libmedia/IAudioFlingerClient.cpp101
-rw-r--r--media/libmedia/IAudioPolicyService.cpp630
-rw-r--r--media/libmedia/IAudioRecord.cpp107
-rw-r--r--media/libmedia/IAudioTrack.cpp245
-rw-r--r--media/libmedia/ICrypto.cpp293
-rw-r--r--media/libmedia/IEffect.cpp201
-rw-r--r--media/libmedia/IEffectClient.cpp144
-rw-r--r--media/libmedia/IMediaDeathNotifier.cpp111
-rw-r--r--media/libmedia/IMediaMetadataRetriever.cpp268
-rw-r--r--media/libmedia/IMediaPlayer.cpp515
-rw-r--r--media/libmedia/IMediaPlayerClient.cpp78
-rw-r--r--media/libmedia/IMediaPlayerService.cpp227
-rw-r--r--media/libmedia/IMediaRecorder.cpp463
-rw-r--r--media/libmedia/IMediaRecorderClient.cpp70
-rw-r--r--media/libmedia/IOMX.cpp788
-rw-r--r--media/libmedia/IStreamSource.cpp192
-rw-r--r--media/libmedia/JetPlayer.cpp480
-rw-r--r--media/libmedia/MODULE_LICENSE_APACHE20
-rw-r--r--media/libmedia/MediaProfiles.cpp1182
-rw-r--r--media/libmedia/MediaScanner.cpp240
-rw-r--r--media/libmedia/MediaScannerClient.cpp230
-rw-r--r--media/libmedia/MemoryLeakTrackUtil.cpp169
-rw-r--r--media/libmedia/Metadata.cpp167
-rw-r--r--media/libmedia/NOTICE190
-rw-r--r--media/libmedia/SoundPool.cpp908
-rw-r--r--media/libmedia/SoundPool.h238
-rw-r--r--media/libmedia/SoundPoolThread.cpp114
-rw-r--r--media/libmedia/SoundPoolThread.h66
-rw-r--r--media/libmedia/ToneGenerator.cpp1580
-rw-r--r--media/libmedia/Visualizer.cpp322
-rw-r--r--media/libmedia/autodetect.cpp885
-rw-r--r--media/libmedia/autodetect.h37
-rw-r--r--media/libmedia/mediametadataretriever.cpp174
-rw-r--r--media/libmedia/mediaplayer.cpp798
-rw-r--r--media/libmedia/mediarecorder.cpp682
-rw-r--r--media/libmedia_native/Android.mk11
-rw-r--r--media/libmediaplayerservice/Android.mk53
-rw-r--r--media/libmediaplayerservice/Crypto.cpp65
-rw-r--r--media/libmediaplayerservice/Crypto.h57
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp2168
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h430
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.cpp336
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.h76
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.cpp254
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.h73
-rw-r--r--media/libmediaplayerservice/MidiFile.cpp552
-rw-r--r--media/libmediaplayerservice/MidiFile.h113
-rw-r--r--media/libmediaplayerservice/MidiMetadataRetriever.cpp92
-rw-r--r--media/libmediaplayerservice/MidiMetadataRetriever.h51
-rw-r--r--media/libmediaplayerservice/StagefrightPlayer.cpp220
-rw-r--r--media/libmediaplayerservice/StagefrightPlayer.h76
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp1755
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h194
-rw-r--r--media/libmediaplayerservice/TestPlayerStub.cpp196
-rw-r--r--media/libmediaplayerservice/TestPlayerStub.h127
-rw-r--r--media/libmediaplayerservice/nuplayer/Android.mk27
-rw-r--r--media/libmediaplayerservice/nuplayer/GenericSource.cpp265
-rw-r--r--media/libmediaplayerservice/nuplayer/GenericSource.h79
-rw-r--r--media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp189
-rw-r--r--media/libmediaplayerservice/nuplayer/HTTPLiveSource.h72
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp905
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.h152
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp299
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h67
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp337
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.h107
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp658
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h133
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerSource.h64
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp164
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h74
-rw-r--r--media/libmediaplayerservice/nuplayer/RTSPSource.cpp387
-rw-r--r--media/libmediaplayerservice/nuplayer/RTSPSource.h115
-rw-r--r--media/libmediaplayerservice/nuplayer/StreamingSource.cpp145
-rw-r--r--media/libmediaplayerservice/nuplayer/StreamingSource.h53
-rw-r--r--media/libstagefright/AACExtractor.cpp386
-rw-r--r--media/libstagefright/AACWriter.cpp381
-rw-r--r--media/libstagefright/ACodec.cpp3492
-rw-r--r--media/libstagefright/AMRExtractor.cpp353
-rw-r--r--media/libstagefright/AMRWriter.cpp287
-rw-r--r--media/libstagefright/AVIExtractor.cpp1307
-rw-r--r--media/libstagefright/Android.mk127
-rw-r--r--media/libstagefright/AudioPlayer.cpp557
-rw-r--r--media/libstagefright/AudioSource.cpp372
-rw-r--r--media/libstagefright/AwesomePlayer.cpp2416
-rwxr-xr-xmedia/libstagefright/CameraSource.cpp843
-rw-r--r--media/libstagefright/CameraSourceTimeLapse.cpp296
-rw-r--r--media/libstagefright/DRMExtractor.cpp299
-rw-r--r--media/libstagefright/DataSource.cpp166
-rw-r--r--media/libstagefright/ESDS.cpp227
-rw-r--r--media/libstagefright/FLACExtractor.cpp813
-rw-r--r--media/libstagefright/FileSource.cpp187
-rw-r--r--media/libstagefright/HTTPBase.cpp154
-rw-r--r--media/libstagefright/JPEGSource.cpp234
-rw-r--r--media/libstagefright/MP3Extractor.cpp661
-rw-r--r--media/libstagefright/MPEG2TSWriter.cpp968
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp2477
-rwxr-xr-xmedia/libstagefright/MPEG4Writer.cpp2862
-rw-r--r--media/libstagefright/MediaBuffer.cpp203
-rw-r--r--media/libstagefright/MediaBufferGroup.cpp86
-rw-r--r--media/libstagefright/MediaCodec.cpp1325
-rw-r--r--media/libstagefright/MediaCodecList.cpp475
-rw-r--r--media/libstagefright/MediaDefs.cpp57
-rw-r--r--media/libstagefright/MediaExtractor.cpp134
-rw-r--r--media/libstagefright/MediaSource.cpp64
-rw-r--r--media/libstagefright/MetaData.cpp345
-rw-r--r--media/libstagefright/NuCachedSource2.cpp703
-rw-r--r--media/libstagefright/NuMediaExtractor.cpp482
-rw-r--r--media/libstagefright/OMXClient.cpp344
-rwxr-xr-xmedia/libstagefright/OMXCodec.cpp4582
-rw-r--r--media/libstagefright/OggExtractor.cpp1027
-rw-r--r--media/libstagefright/SampleIterator.cpp316
-rw-r--r--media/libstagefright/SampleTable.cpp831
-rwxr-xr-xmedia/libstagefright/SkipCutBuffer.cpp130
-rw-r--r--media/libstagefright/StagefrightMediaScanner.cpp217
-rw-r--r--media/libstagefright/StagefrightMetadataRetriever.cpp553
-rw-r--r--media/libstagefright/SurfaceMediaSource.cpp873
-rw-r--r--media/libstagefright/ThrottledSource.cpp84
-rw-r--r--media/libstagefright/TimeSource.cpp41
-rw-r--r--media/libstagefright/TimedEventQueue.cpp301
-rw-r--r--media/libstagefright/Utils.cpp57
-rw-r--r--media/libstagefright/VBRISeeker.cpp165
-rw-r--r--media/libstagefright/VideoSourceDownSampler.cpp142
-rw-r--r--media/libstagefright/WAVExtractor.cpp506
-rw-r--r--media/libstagefright/WVMExtractor.cpp161
-rw-r--r--media/libstagefright/XINGSeeker.cpp196
-rw-r--r--media/libstagefright/avc_utils.cpp633
-rw-r--r--media/libstagefright/chromium_http/Android.mk25
-rw-r--r--media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp335
-rw-r--r--media/libstagefright/chromium_http/DataUriSource.cpp68
-rw-r--r--media/libstagefright/chromium_http/support.cpp531
-rw-r--r--media/libstagefright/chromium_http/support.h164
-rw-r--r--media/libstagefright/codecs/Android.mk4
-rw-r--r--media/libstagefright/codecs/aacdec/Android.mk180
-rw-r--r--media/libstagefright/codecs/aacdec/SoftAAC.cpp520
-rw-r--r--media/libstagefright/codecs/aacdec/SoftAAC.h77
-rw-r--r--media/libstagefright/codecs/aacdec/aac_mem_funcs.h50
-rw-r--r--media/libstagefright/codecs/aacdec/analysis_sub_band.cpp289
-rw-r--r--media/libstagefright/codecs/aacdec/analysis_sub_band.h82
-rw-r--r--media/libstagefright/codecs/aacdec/apply_ms_synt.cpp454
-rw-r--r--media/libstagefright/codecs/aacdec/apply_ms_synt.h94
-rw-r--r--media/libstagefright/codecs/aacdec/apply_tns.cpp424
-rw-r--r--media/libstagefright/codecs/aacdec/apply_tns.h113
-rw-r--r--media/libstagefright/codecs/aacdec/bit_reversal_swap.h93
-rw-r--r--media/libstagefright/codecs/aacdec/buf_getbits.cpp167
-rw-r--r--media/libstagefright/codecs/aacdec/buf_getbits.h94
-rw-r--r--media/libstagefright/codecs/aacdec/buffer_normalization.h93
-rw-r--r--media/libstagefright/codecs/aacdec/byte_align.cpp179
-rw-r--r--media/libstagefright/codecs/aacdec/calc_auto_corr.cpp416
-rw-r--r--media/libstagefright/codecs/aacdec/calc_auto_corr.h122
-rw-r--r--media/libstagefright/codecs/aacdec/calc_gsfb_table.cpp267
-rw-r--r--media/libstagefright/codecs/aacdec/calc_sbr_anafilterbank.cpp360
-rw-r--r--media/libstagefright/codecs/aacdec/calc_sbr_anafilterbank.h113
-rw-r--r--media/libstagefright/codecs/aacdec/calc_sbr_envelope.cpp2203
-rw-r--r--media/libstagefright/codecs/aacdec/calc_sbr_envelope.h144
-rw-r--r--media/libstagefright/codecs/aacdec/calc_sbr_synfilterbank.cpp639
-rw-r--r--media/libstagefright/codecs/aacdec/calc_sbr_synfilterbank.h94
-rw-r--r--media/libstagefright/codecs/aacdec/chans.h107
-rw-r--r--media/libstagefright/codecs/aacdec/check_crc.cpp144
-rw-r--r--media/libstagefright/codecs/aacdec/check_crc.h124
-rw-r--r--media/libstagefright/codecs/aacdec/dct16.cpp266
-rw-r--r--media/libstagefright/codecs/aacdec/dct16.h68
-rw-r--r--media/libstagefright/codecs/aacdec/dct64.cpp569
-rw-r--r--media/libstagefright/codecs/aacdec/dct64.h81
-rw-r--r--media/libstagefright/codecs/aacdec/decode_huff_cw_binary.cpp708
-rw-r--r--media/libstagefright/codecs/aacdec/decode_noise_floorlevels.cpp163
-rw-r--r--media/libstagefright/codecs/aacdec/decode_noise_floorlevels.h92
-rw-r--r--media/libstagefright/codecs/aacdec/deinterleave.cpp287
-rw-r--r--media/libstagefright/codecs/aacdec/digit_reversal_tables.cpp279
-rw-r--r--media/libstagefright/codecs/aacdec/digit_reversal_tables.h86
-rw-r--r--media/libstagefright/codecs/aacdec/dst16.cpp172
-rw-r--r--media/libstagefright/codecs/aacdec/dst16.h68
-rw-r--r--media/libstagefright/codecs/aacdec/dst32.cpp200
-rw-r--r--media/libstagefright/codecs/aacdec/dst32.h69
-rw-r--r--media/libstagefright/codecs/aacdec/dst8.cpp179
-rw-r--r--media/libstagefright/codecs/aacdec/dst8.h68
-rw-r--r--media/libstagefright/codecs/aacdec/e_adif_const.h97
-rw-r--r--media/libstagefright/codecs/aacdec/e_blockswitching.h112
-rw-r--r--media/libstagefright/codecs/aacdec/e_coupling_mode.h88
-rw-r--r--media/libstagefright/codecs/aacdec/e_elementid.h99
-rw-r--r--media/libstagefright/codecs/aacdec/e_huffmanconst.h119
-rw-r--r--media/libstagefright/codecs/aacdec/e_infoinitconst.h96
-rw-r--r--media/libstagefright/codecs/aacdec/e_invf_mode.h91
-rw-r--r--media/libstagefright/codecs/aacdec/e_maskstatus.h91
-rw-r--r--media/libstagefright/codecs/aacdec/e_mp4ff_const.h105
-rw-r--r--media/libstagefright/codecs/aacdec/e_progconfigconst.h110
-rw-r--r--media/libstagefright/codecs/aacdec/e_rawbitstreamconst.h130
-rw-r--r--media/libstagefright/codecs/aacdec/e_sbr_element_id.h87
-rw-r--r--media/libstagefright/codecs/aacdec/e_sbr_error.h106
-rw-r--r--media/libstagefright/codecs/aacdec/e_sbr_header_status.h88
-rw-r--r--media/libstagefright/codecs/aacdec/e_sbr_master_status.h87
-rw-r--r--media/libstagefright/codecs/aacdec/e_sbr_sync_state.h88
-rw-r--r--media/libstagefright/codecs/aacdec/e_sr_mode.h88
-rw-r--r--media/libstagefright/codecs/aacdec/e_tmp4audioobjecttype.h118
-rw-r--r--media/libstagefright/codecs/aacdec/e_tns_const.h91
-rw-r--r--media/libstagefright/codecs/aacdec/e_window_sequence.h90
-rw-r--r--media/libstagefright/codecs/aacdec/e_window_shape.h89
-rw-r--r--media/libstagefright/codecs/aacdec/esc_iquant_scaling.cpp789
-rw-r--r--media/libstagefright/codecs/aacdec/esc_iquant_scaling.h102
-rw-r--r--media/libstagefright/codecs/aacdec/extractframeinfo.cpp487
-rw-r--r--media/libstagefright/codecs/aacdec/extractframeinfo.h96
-rw-r--r--media/libstagefright/codecs/aacdec/fft_rx4.h110
-rw-r--r--media/libstagefright/codecs/aacdec/fft_rx4_long.cpp428
-rw-r--r--media/libstagefright/codecs/aacdec/fft_rx4_short.cpp468
-rw-r--r--media/libstagefright/codecs/aacdec/fft_rx4_tables_fxp.cpp269
-rw-r--r--media/libstagefright/codecs/aacdec/find_adts_syncword.cpp305
-rw-r--r--media/libstagefright/codecs/aacdec/find_adts_syncword.h87
-rw-r--r--media/libstagefright/codecs/aacdec/fwd_long_complex_rot.cpp284
-rw-r--r--media/libstagefright/codecs/aacdec/fwd_long_complex_rot.h96
-rw-r--r--media/libstagefright/codecs/aacdec/fwd_short_complex_rot.cpp261
-rw-r--r--media/libstagefright/codecs/aacdec/fwd_short_complex_rot.h92
-rw-r--r--media/libstagefright/codecs/aacdec/fxp_mul32.h72
-rw-r--r--media/libstagefright/codecs/aacdec/fxp_mul32_arm_gcc.h547
-rw-r--r--media/libstagefright/codecs/aacdec/fxp_mul32_arm_v4.h429
-rwxr-xr-xmedia/libstagefright/codecs/aacdec/fxp_mul32_arm_v4_gcc.h630
-rw-r--r--media/libstagefright/codecs/aacdec/fxp_mul32_arm_v5.h450
-rw-r--r--media/libstagefright/codecs/aacdec/fxp_mul32_c_equivalent.h285
-rw-r--r--media/libstagefright/codecs/aacdec/fxp_mul32_c_msc_evc.h254
-rw-r--r--media/libstagefright/codecs/aacdec/fxp_mul32_c_msc_evc_armv5.h178
-rw-r--r--media/libstagefright/codecs/aacdec/fxp_mul32_pentium.h55
-rw-r--r--media/libstagefright/codecs/aacdec/gen_rand_vector.cpp512
-rw-r--r--media/libstagefright/codecs/aacdec/gen_rand_vector.h87
-rw-r--r--media/libstagefright/codecs/aacdec/get_adif_header.cpp443
-rw-r--r--media/libstagefright/codecs/aacdec/get_adif_header.h95
-rw-r--r--media/libstagefright/codecs/aacdec/get_adts_header.cpp672
-rw-r--r--media/libstagefright/codecs/aacdec/get_adts_header.h90
-rw-r--r--media/libstagefright/codecs/aacdec/get_audio_specific_config.cpp691
-rw-r--r--media/libstagefright/codecs/aacdec/get_audio_specific_config.h86
-rw-r--r--media/libstagefright/codecs/aacdec/get_dse.cpp215
-rw-r--r--media/libstagefright/codecs/aacdec/get_dse.h87
-rw-r--r--media/libstagefright/codecs/aacdec/get_ele_list.cpp243
-rw-r--r--media/libstagefright/codecs/aacdec/get_ele_list.h90
-rw-r--r--media/libstagefright/codecs/aacdec/get_ga_specific_config.cpp473
-rw-r--r--media/libstagefright/codecs/aacdec/get_ga_specific_config.h94
-rw-r--r--media/libstagefright/codecs/aacdec/get_ics_info.cpp608
-rw-r--r--media/libstagefright/codecs/aacdec/get_ics_info.h111
-rw-r--r--media/libstagefright/codecs/aacdec/get_prog_config.cpp739
-rw-r--r--media/libstagefright/codecs/aacdec/get_prog_config.h89
-rw-r--r--media/libstagefright/codecs/aacdec/get_pulse_data.cpp286
-rw-r--r--media/libstagefright/codecs/aacdec/get_pulse_data.h100
-rw-r--r--media/libstagefright/codecs/aacdec/get_sbr_bitstream.cpp183
-rw-r--r--media/libstagefright/codecs/aacdec/get_sbr_bitstream.h126
-rw-r--r--media/libstagefright/codecs/aacdec/get_sbr_startfreq.cpp183
-rw-r--r--media/libstagefright/codecs/aacdec/get_sbr_startfreq.h85
-rw-r--r--media/libstagefright/codecs/aacdec/get_sbr_stopfreq.cpp190
-rw-r--r--media/libstagefright/codecs/aacdec/get_sbr_stopfreq.h85
-rw-r--r--media/libstagefright/codecs/aacdec/get_sign_bits.h99
-rw-r--r--media/libstagefright/codecs/aacdec/get_tns.cpp573
-rw-r--r--media/libstagefright/codecs/aacdec/get_tns.h124
-rw-r--r--media/libstagefright/codecs/aacdec/getbits.h346
-rw-r--r--media/libstagefright/codecs/aacdec/getfill.cpp247
-rw-r--r--media/libstagefright/codecs/aacdec/getfill.h88
-rw-r--r--media/libstagefright/codecs/aacdec/getgroup.cpp255
-rw-r--r--media/libstagefright/codecs/aacdec/getics.cpp674
-rw-r--r--media/libstagefright/codecs/aacdec/getmask.cpp384
-rw-r--r--media/libstagefright/codecs/aacdec/hcbtables.h118
-rw-r--r--media/libstagefright/codecs/aacdec/hcbtables_binary.cpp1938
-rw-r--r--media/libstagefright/codecs/aacdec/huffcb.cpp381
-rw-r--r--media/libstagefright/codecs/aacdec/huffdecode.cpp528
-rw-r--r--media/libstagefright/codecs/aacdec/hufffac.cpp550
-rw-r--r--media/libstagefright/codecs/aacdec/huffman.h241
-rw-r--r--media/libstagefright/codecs/aacdec/huffspec_fxp.cpp671
-rw-r--r--media/libstagefright/codecs/aacdec/ibstream.h115
-rw-r--r--media/libstagefright/codecs/aacdec/idct16.cpp204
-rw-r--r--media/libstagefright/codecs/aacdec/idct16.h69
-rw-r--r--media/libstagefright/codecs/aacdec/idct32.cpp196
-rw-r--r--media/libstagefright/codecs/aacdec/idct32.h69
-rw-r--r--media/libstagefright/codecs/aacdec/idct8.cpp168
-rw-r--r--media/libstagefright/codecs/aacdec/idct8.h69
-rw-r--r--media/libstagefright/codecs/aacdec/imdct_fxp.cpp476
-rw-r--r--media/libstagefright/codecs/aacdec/imdct_fxp.h122
-rw-r--r--media/libstagefright/codecs/aacdec/infoinit.cpp355
-rw-r--r--media/libstagefright/codecs/aacdec/init_sbr_dec.cpp192
-rw-r--r--media/libstagefright/codecs/aacdec/init_sbr_dec.h115
-rw-r--r--media/libstagefright/codecs/aacdec/intensity_right.cpp457
-rw-r--r--media/libstagefright/codecs/aacdec/intensity_right.h97
-rw-r--r--media/libstagefright/codecs/aacdec/inv_long_complex_rot.cpp408
-rw-r--r--media/libstagefright/codecs/aacdec/inv_long_complex_rot.h99
-rw-r--r--media/libstagefright/codecs/aacdec/inv_short_complex_rot.cpp305
-rw-r--r--media/libstagefright/codecs/aacdec/inv_short_complex_rot.h88
-rw-r--r--media/libstagefright/codecs/aacdec/iquant_table.cpp1131
-rw-r--r--media/libstagefright/codecs/aacdec/iquant_table.h85
-rw-r--r--media/libstagefright/codecs/aacdec/long_term_prediction.cpp648
-rw-r--r--media/libstagefright/codecs/aacdec/long_term_prediction.h122
-rw-r--r--media/libstagefright/codecs/aacdec/long_term_synthesis.cpp1158
-rw-r--r--media/libstagefright/codecs/aacdec/long_term_synthesis.h105
-rw-r--r--media/libstagefright/codecs/aacdec/lt_decode.cpp507
-rw-r--r--media/libstagefright/codecs/aacdec/lt_decode.h96
-rw-r--r--media/libstagefright/codecs/aacdec/lt_prediction.h69
-rw-r--r--media/libstagefright/codecs/aacdec/ltp_common_internal.h115
-rw-r--r--media/libstagefright/codecs/aacdec/mdct_fxp.cpp450
-rw-r--r--media/libstagefright/codecs/aacdec/mdct_fxp.h107
-rw-r--r--media/libstagefright/codecs/aacdec/mdct_tables_fxp.cpp253
-rw-r--r--media/libstagefright/codecs/aacdec/mdst.cpp294
-rw-r--r--media/libstagefright/codecs/aacdec/mdst.h73
-rw-r--r--media/libstagefright/codecs/aacdec/mix_radix_fft.cpp319
-rw-r--r--media/libstagefright/codecs/aacdec/mix_radix_fft.h98
-rw-r--r--media/libstagefright/codecs/aacdec/ms_map_mask.h87
-rw-r--r--media/libstagefright/codecs/aacdec/ms_synt.cpp403
-rw-r--r--media/libstagefright/codecs/aacdec/ms_synt.h96
-rw-r--r--media/libstagefright/codecs/aacdec/pns_corr.cpp342
-rw-r--r--media/libstagefright/codecs/aacdec/pns_corr.h95
-rw-r--r--media/libstagefright/codecs/aacdec/pns_intensity_right.cpp653
-rw-r--r--media/libstagefright/codecs/aacdec/pns_intensity_right.h106
-rw-r--r--media/libstagefright/codecs/aacdec/pns_left.cpp431
-rw-r--r--media/libstagefright/codecs/aacdec/pns_left.h113
-rw-r--r--media/libstagefright/codecs/aacdec/ps_all_pass_filter_coeff.cpp311
-rw-r--r--media/libstagefright/codecs/aacdec/ps_all_pass_filter_coeff.h105
-rw-r--r--media/libstagefright/codecs/aacdec/ps_all_pass_fract_delay_filter.cpp391
-rw-r--r--media/libstagefright/codecs/aacdec/ps_all_pass_fract_delay_filter.h117
-rw-r--r--media/libstagefright/codecs/aacdec/ps_allocate_decoder.cpp341
-rw-r--r--media/libstagefright/codecs/aacdec/ps_allocate_decoder.h94
-rw-r--r--media/libstagefright/codecs/aacdec/ps_applied.cpp216
-rw-r--r--media/libstagefright/codecs/aacdec/ps_applied.h101
-rw-r--r--media/libstagefright/codecs/aacdec/ps_bstr_decoding.cpp304
-rw-r--r--media/libstagefright/codecs/aacdec/ps_bstr_decoding.h98
-rw-r--r--media/libstagefright/codecs/aacdec/ps_channel_filtering.cpp281
-rw-r--r--media/libstagefright/codecs/aacdec/ps_channel_filtering.h104
-rw-r--r--media/libstagefright/codecs/aacdec/ps_constants.h89
-rw-r--r--media/libstagefright/codecs/aacdec/ps_decode_bs_utils.cpp274
-rw-r--r--media/libstagefright/codecs/aacdec/ps_decode_bs_utils.h112
-rw-r--r--media/libstagefright/codecs/aacdec/ps_decorrelate.cpp499
-rw-r--r--media/libstagefright/codecs/aacdec/ps_decorrelate.h99
-rw-r--r--media/libstagefright/codecs/aacdec/ps_fft_rx8.cpp318
-rw-r--r--media/libstagefright/codecs/aacdec/ps_fft_rx8.h94
-rw-r--r--media/libstagefright/codecs/aacdec/ps_hybrid_analysis.cpp285
-rw-r--r--media/libstagefright/codecs/aacdec/ps_hybrid_analysis.h98
-rw-r--r--media/libstagefright/codecs/aacdec/ps_hybrid_filter_bank_allocation.cpp213
-rw-r--r--media/libstagefright/codecs/aacdec/ps_hybrid_filter_bank_allocation.h97
-rw-r--r--media/libstagefright/codecs/aacdec/ps_hybrid_synthesis.cpp192
-rw-r--r--media/libstagefright/codecs/aacdec/ps_hybrid_synthesis.h97
-rw-r--r--media/libstagefright/codecs/aacdec/ps_init_stereo_mixing.cpp496
-rw-r--r--media/libstagefright/codecs/aacdec/ps_init_stereo_mixing.h97
-rw-r--r--media/libstagefright/codecs/aacdec/ps_pwr_transient_detection.cpp340
-rw-r--r--media/libstagefright/codecs/aacdec/ps_pwr_transient_detection.h96
-rw-r--r--media/libstagefright/codecs/aacdec/ps_read_data.cpp388
-rw-r--r--media/libstagefright/codecs/aacdec/ps_read_data.h100
-rw-r--r--media/libstagefright/codecs/aacdec/ps_stereo_processing.cpp372
-rw-r--r--media/libstagefright/codecs/aacdec/ps_stereo_processing.h98
-rw-r--r--media/libstagefright/codecs/aacdec/pulse_nc.cpp298
-rw-r--r--media/libstagefright/codecs/aacdec/pulse_nc.h104
-rw-r--r--media/libstagefright/codecs/aacdec/pv_audio_type_defs.h183
-rw-r--r--media/libstagefright/codecs/aacdec/pv_div.cpp188
-rw-r--r--media/libstagefright/codecs/aacdec/pv_div.h74
-rw-r--r--media/libstagefright/codecs/aacdec/pv_log2.cpp168
-rw-r--r--media/libstagefright/codecs/aacdec/pv_log2.h69
-rw-r--r--media/libstagefright/codecs/aacdec/pv_normalize.cpp167
-rw-r--r--media/libstagefright/codecs/aacdec/pv_normalize.h105
-rw-r--r--media/libstagefright/codecs/aacdec/pv_pow2.cpp170
-rw-r--r--media/libstagefright/codecs/aacdec/pv_pow2.h68
-rw-r--r--media/libstagefright/codecs/aacdec/pv_sine.cpp182
-rw-r--r--media/libstagefright/codecs/aacdec/pv_sine.h68
-rw-r--r--media/libstagefright/codecs/aacdec/pv_sqrt.cpp218
-rw-r--r--media/libstagefright/codecs/aacdec/pv_sqrt.h74
-rw-r--r--media/libstagefright/codecs/aacdec/pvmp4audiodecoder_api.h376
-rw-r--r--media/libstagefright/codecs/aacdec/pvmp4audiodecoderconfig.cpp285
-rw-r--r--media/libstagefright/codecs/aacdec/pvmp4audiodecoderframe.cpp1458
-rw-r--r--media/libstagefright/codecs/aacdec/pvmp4audiodecodergetmemrequirements.cpp157
-rw-r--r--media/libstagefright/codecs/aacdec/pvmp4audiodecoderinitlibrary.cpp418
-rw-r--r--media/libstagefright/codecs/aacdec/pvmp4audiodecoderresetbuffer.cpp354
-rw-r--r--media/libstagefright/codecs/aacdec/pvmp4setaudioconfig.cpp368
-rw-r--r--media/libstagefright/codecs/aacdec/q_normalize.cpp388
-rw-r--r--media/libstagefright/codecs/aacdec/q_normalize.h103
-rw-r--r--media/libstagefright/codecs/aacdec/qmf_filterbank_coeff.cpp319
-rw-r--r--media/libstagefright/codecs/aacdec/qmf_filterbank_coeff.h99
-rw-r--r--media/libstagefright/codecs/aacdec/s_adif_header.h98
-rw-r--r--media/libstagefright/codecs/aacdec/s_bit_buffer.h93
-rw-r--r--media/libstagefright/codecs/aacdec/s_bits.h112
-rw-r--r--media/libstagefright/codecs/aacdec/s_ch_info.h103
-rw-r--r--media/libstagefright/codecs/aacdec/s_crc_buffer.h90
-rw-r--r--media/libstagefright/codecs/aacdec/s_elelist.h90
-rw-r--r--media/libstagefright/codecs/aacdec/s_frameinfo.h127
-rw-r--r--media/libstagefright/codecs/aacdec/s_hcb.h123
-rw-r--r--media/libstagefright/codecs/aacdec/s_huffman.h91
-rw-r--r--media/libstagefright/codecs/aacdec/s_hybrid.h100
-rw-r--r--media/libstagefright/codecs/aacdec/s_lt_pred_status.h174
-rw-r--r--media/libstagefright/codecs/aacdec/s_mc_info.h116
-rw-r--r--media/libstagefright/codecs/aacdec/s_mixdown.h88
-rw-r--r--media/libstagefright/codecs/aacdec/s_patch.h121
-rw-r--r--media/libstagefright/codecs/aacdec/s_progconfig.h108
-rw-r--r--media/libstagefright/codecs/aacdec/s_ps_dec.h154
-rw-r--r--media/libstagefright/codecs/aacdec/s_pulseinfo.h97
-rw-r--r--media/libstagefright/codecs/aacdec/s_sbr_channel.h115
-rw-r--r--media/libstagefright/codecs/aacdec/s_sbr_dec.h145
-rw-r--r--media/libstagefright/codecs/aacdec/s_sbr_element_stream.h92
-rw-r--r--media/libstagefright/codecs/aacdec/s_sbr_frame_data.h181
-rw-r--r--media/libstagefright/codecs/aacdec/s_sbr_header_data.h112
-rw-r--r--media/libstagefright/codecs/aacdec/s_sbrbitstream.h91
-rw-r--r--media/libstagefright/codecs/aacdec/s_sectinfo.h91
-rw-r--r--media/libstagefright/codecs/aacdec/s_sr_info.h91
-rw-r--r--media/libstagefright/codecs/aacdec/s_tdec_int_chan.h183
-rw-r--r--media/libstagefright/codecs/aacdec/s_tdec_int_file.h277
-rw-r--r--media/libstagefright/codecs/aacdec/s_tns_frame_info.h147
-rw-r--r--media/libstagefright/codecs/aacdec/s_tnsfilt.h132
-rw-r--r--media/libstagefright/codecs/aacdec/s_wnd_shape.h89
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_aliasing_reduction.cpp366
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_aliasing_reduction.h92
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_applied.cpp435
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_applied.h136
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_code_book_envlevel.cpp403
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_code_book_envlevel.h103
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_constants.h210
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_crc_check.cpp191
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_crc_check.h98
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_create_limiter_bands.cpp253
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_create_limiter_bands.h95
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_dec.cpp960
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_dec.h144
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_decode_envelope.cpp286
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_decode_envelope.h94
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_decode_huff_cw.cpp149
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_decode_huff_cw.h93
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_downsample_lo_res.cpp162
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_downsample_lo_res.h97
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_envelope_calc_tbl.cpp424
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_envelope_calc_tbl.h96
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_envelope_unmapping.cpp427
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_envelope_unmapping.h89
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_extract_extended_data.cpp223
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_extract_extended_data.h93
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_find_start_andstop_band.cpp198
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_find_start_andstop_band.h89
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_generate_high_freq.cpp1040
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_generate_high_freq.h144
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_additional_data.cpp145
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_additional_data.h87
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_cpe.cpp266
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_cpe.h88
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_dir_control_data.cpp153
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_dir_control_data.h87
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_envelope.cpp265
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_envelope.h93
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_header_data.cpp221
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_header_data.h89
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_noise_floor_data.cpp218
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_noise_floor_data.h94
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_sce.cpp202
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_get_sce.h102
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_inv_filt_levelemphasis.cpp214
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_inv_filt_levelemphasis.h91
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_open.cpp195
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_open.h116
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_read_data.cpp324
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_read_data.h127
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_requantize_envelope_data.cpp183
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_requantize_envelope_data.h83
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_reset_dec.cpp269
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_reset_dec.h118
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_update_freq_scale.cpp364
-rw-r--r--media/libstagefright/codecs/aacdec/sbr_update_freq_scale.h104
-rw-r--r--media/libstagefright/codecs/aacdec/set_mc_info.cpp309
-rw-r--r--media/libstagefright/codecs/aacdec/set_mc_info.h98
-rw-r--r--media/libstagefright/codecs/aacdec/sfb.cpp275
-rw-r--r--media/libstagefright/codecs/aacdec/sfb.h117
-rw-r--r--media/libstagefright/codecs/aacdec/shellsort.cpp138
-rw-r--r--media/libstagefright/codecs/aacdec/shellsort.h84
-rw-r--r--media/libstagefright/codecs/aacdec/stereo_2_mono.h97
-rw-r--r--media/libstagefright/codecs/aacdec/synthesis_sub_band.cpp483
-rw-r--r--media/libstagefright/codecs/aacdec/synthesis_sub_band.h78
-rw-r--r--media/libstagefright/codecs/aacdec/tns_ar_filter.cpp474
-rw-r--r--media/libstagefright/codecs/aacdec/tns_ar_filter.h104
-rw-r--r--media/libstagefright/codecs/aacdec/tns_decode_coef.cpp500
-rw-r--r--media/libstagefright/codecs/aacdec/tns_decode_coef.h115
-rw-r--r--media/libstagefright/codecs/aacdec/tns_inv_filter.cpp421
-rw-r--r--media/libstagefright/codecs/aacdec/tns_inv_filter.h99
-rw-r--r--media/libstagefright/codecs/aacdec/trans4m_freq_2_time_fxp.cpp2604
-rw-r--r--media/libstagefright/codecs/aacdec/trans4m_time_2_freq_fxp.cpp663
-rw-r--r--media/libstagefright/codecs/aacdec/unpack_idx.cpp660
-rw-r--r--media/libstagefright/codecs/aacdec/unpack_idx.h115
-rw-r--r--media/libstagefright/codecs/aacdec/window_block_fxp.h231
-rw-r--r--media/libstagefright/codecs/aacdec/window_tables_fxp.cpp730
-rw-r--r--media/libstagefright/codecs/aacdec/write_output.h138
-rw-r--r--media/libstagefright/codecs/aacenc/AACEncoder.cpp334
-rw-r--r--media/libstagefright/codecs/aacenc/Android.mk113
-rw-r--r--media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c283
-rw-r--r--media/libstagefright/codecs/aacenc/SampleCode/Android.mk25
-rw-r--r--media/libstagefright/codecs/aacenc/SoftAACEncoder.cpp560
-rw-r--r--media/libstagefright/codecs/aacenc/SoftAACEncoder.h82
-rw-r--r--media/libstagefright/codecs/aacenc/basic_op/basic_op.h1171
-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.h184
-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.c1225
-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.s146
-rw-r--r--media/libstagefright/codecs/aacenc/src/asm/ARMV7/R4R8First_v7.s157
-rw-r--r--media/libstagefright/codecs/aacenc/src/asm/ARMV7/Radix4FFT_v7.s148
-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.c173
-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.c112
-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.c811
-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.c678
-rw-r--r--media/libstagefright/codecs/amrnb/Android.mk4
-rw-r--r--media/libstagefright/codecs/amrnb/common/Android.mk74
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/abs_s.h113
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/add.h116
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/az_lsp.h120
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/basic_op.h448
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h543
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/basic_op_arm_v5.h440
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/basic_op_c_equivalent.h505
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/basicop_malloc.h115
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/bitno_tab.h146
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/bitreorder_tab.h125
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/bits2prm.h91
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/bytesused.h109
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/cnst.h129
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/cnst_vad.h133
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/copy.h88
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/d_gain_c.h125
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/d_gain_p.h80
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/d_plsf.h199
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/div_32.h116
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/div_s.h114
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/dtx_common_def.h103
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/extract_h.h114
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/extract_l.h114
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/frame.h114
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/frame_type_3gpp.h123
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/gc_pred.h176
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/gmed_n.h80
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/gsm_amr_typedefs.h133
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/int_lpc.h212
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/int_lsf.h113
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/inv_sqrt.h118
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_abs.h111
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_add.h171
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_add_c.h115
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_comp.h114
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_deposit_h.h114
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_deposit_l.h114
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_extract.h115
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_mac.h183
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_msu.h171
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_mult.h178
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_negate.h114
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_shl.h116
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_shr.h115
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_shr_r.h114
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/l_sub.h173
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/log2.h120
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/log2_norm.h119
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/lsfwt.h115
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/lsp.h186
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/lsp_az.h111
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/lsp_lsf.h121
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/lsp_tab.h111
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/mac_32.h150
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/mode.h82
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/mpy_32.h272
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/mpy_32_16.h206
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/mult.h190
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/mult_r.h121
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/n_proc.h31
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/negate.h113
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/norm_l.h153
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/norm_s.h153
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/oper_32b.h102
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/p_ol_wgh.h144
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/pow2.h115
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/pred_lt.h113
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/pvgsmamr.h63
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/q_plsf.h169
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/q_plsf_3_tbl.h136
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/q_plsf_5_tbl.h110
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/qgain475_tab.h107
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/qua_gain.h135
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/qua_gain_tbl.h108
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/reorder.h109
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/residu.h83
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/reverse_bits.h114
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/round.h115
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/set_zero.h79
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/shl.h118
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/shr.h115
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/shr_r.h115
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/sqrt_l.h118
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/sub.h115
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/syn_filt.h83
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/typedef.h73
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/vad.h76
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/vad1.h197
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/vad2.h203
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/weight_a.h81
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/window_tab.h109
-rw-r--r--media/libstagefright/codecs/amrnb/common/include/wmf_to_ets.h119
-rw-r--r--media/libstagefright/codecs/amrnb/common/pvgsmamrdecoderinterface.h183
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/add.cpp203
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp740
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/bitno_tab.cpp309
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/bitreorder_tab.cpp422
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/bits2prm.cpp292
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/bytesused.cpp208
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/c2_9pf_tab.cpp166
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/copy.cpp87
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/div_32.cpp209
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/div_s.cpp277
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/extract_h.cpp177
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/extract_l.cpp176
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/gains_tbl.cpp219
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/gc_pred.cpp1046
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/gmed_n.cpp218
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/gray_tbl.cpp162
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/grid_tbl.cpp181
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/int_lpc.cpp633
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/inv_sqrt.cpp270
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/inv_sqrt_tbl.cpp168
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/l_abs.cpp193
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/l_deposit_h.cpp177
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/l_deposit_l.cpp177
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/l_shr_r.cpp214
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/log2.cpp179
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/log2_norm.cpp238
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/log2_tbl.cpp165
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/lsfwt.cpp242
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/lsp.cpp530
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/lsp_az.cpp555
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/lsp_lsf.cpp384
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/lsp_lsf_tbl.cpp115
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/lsp_tab.cpp188
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/mult_r.cpp218
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/negate.cpp179
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/norm_l.cpp247
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/norm_s.cpp242
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/overflow_tbl.cpp174
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/ph_disp_tab.cpp192
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/pow2.cpp202
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/pow2_tbl.cpp164
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/pred_lt.cpp349
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/q_plsf.cpp144
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/q_plsf_3.cpp1226
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/q_plsf_3_tbl.cpp2096
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/q_plsf_5.cpp691
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/q_plsf_5_tbl.cpp1164
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/qua_gain_tbl.cpp391
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/reorder.cpp199
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/residu.cpp255
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/round.cpp195
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/set_zero.cpp74
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/shr.cpp258
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/shr_r.cpp226
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/sqrt_l.cpp266
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/sqrt_l_tbl.cpp171
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/sub.cpp218
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/syn_filt.cpp399
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/vad1.cpp2330
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/weight_a.cpp196
-rw-r--r--media/libstagefright/codecs/amrnb/common/src/window_tab.cpp281
-rw-r--r--media/libstagefright/codecs/amrnb/dec/Android.mk83
-rw-r--r--media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp446
-rw-r--r--media/libstagefright/codecs/amrnb/dec/SoftAMR.h87
-rw-r--r--media/libstagefright/codecs/amrnb/dec/include/pvamrnbdecoder_api.h122
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp313
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/a_refl.h124
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/agc.cpp1066
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/agc.h163
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/amrdecode.cpp544
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/amrdecode.h166
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/b_cn_cod.cpp516
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/b_cn_cod.h171
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/bgnscd.cpp589
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/bgnscd.h159
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/c_g_aver.cpp648
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/c_g_aver.h163
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d1035pf.cpp263
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d1035pf.h117
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d2_11pf.cpp224
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d2_11pf.h93
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d2_9pf.cpp248
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d2_9pf.h122
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d3_14pf.cpp233
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d3_14pf.h118
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d4_17pf.cpp271
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d4_17pf.h119
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d8_31pf.cpp626
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d8_31pf.h120
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d_gain_c.cpp254
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d_gain_p.cpp192
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d_plsf.cpp207
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d_plsf_3.cpp496
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/d_plsf_5.cpp539
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/dec_amr.cpp2374
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/dec_amr.h206
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/dec_gain.cpp305
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/dec_gain.h127
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/dec_input_format_tab.cpp233
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/dec_lag3.cpp407
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/dec_lag3.h127
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/dec_lag6.cpp337
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/dec_lag6.h124
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/dtx_dec.cpp1956
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/dtx_dec.h191
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/ec_gains.cpp842
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/ec_gains.h209
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/ex_ctrl.cpp219
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/ex_ctrl.h131
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h170
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/if2_to_ets.cpp196
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/if2_to_ets.h124
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/int_lsf.cpp315
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/lsp_avg.cpp317
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/lsp_avg.h136
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/ph_disp.cpp898
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/ph_disp.h192
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/post_pro.cpp395
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/post_pro.h140
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/preemph.cpp272
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/preemph.h140
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp578
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/pstfilt.h143
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/pvgsmamrdecoder.cpp77
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/qgain475_tab.cpp435
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/sp_dec.cpp699
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/sp_dec.h113
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/wmf_to_ets.cpp190
-rw-r--r--media/libstagefright/codecs/amrnb/enc/Android.mk102
-rw-r--r--media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp404
-rw-r--r--media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.h72
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/amrencode.cpp897
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/amrencode.h156
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/autocorr.cpp459
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/autocorr.h118
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/c1035pf.cpp676
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/c1035pf.h124
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/c2_11pf.cpp841
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/c2_11pf.h121
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/c2_9pf.cpp1219
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/c2_9pf.h125
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/c3_14pf.cpp817
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/c3_14pf.h123
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/c4_17pf.cpp891
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/c4_17pf.h123
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/c8_31pf.cpp828
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/c8_31pf.h122
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/calc_cor.cpp267
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/calc_cor.h87
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/calc_en.cpp825
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/calc_en.h192
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/cbsearch.cpp392
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/cbsearch.h136
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/cl_ltp.cpp763
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/cl_ltp.h163
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/cod_amr.cpp1608
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/cod_amr.h275
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/convolve.cpp245
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/convolve.h83
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/cor_h.cpp429
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/cor_h.h96
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/cor_h_x.cpp320
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/cor_h_x.h103
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.cpp282
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.h121
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/corrwght_tab.cpp199
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/dtx_enc.cpp1163
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/dtx_enc.h209
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/enc_lag3.cpp356
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/enc_lag3.h125
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/enc_lag6.cpp230
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/enc_lag6.h122
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/enc_output_format_tab.cpp232
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/ets_to_if2.cpp242
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/ets_to_if2.h121
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/ets_to_wmf.cpp244
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/ets_to_wmf.h123
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/g_adapt.cpp522
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/g_adapt.h159
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/g_code.cpp322
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/g_code.h116
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/g_pitch.cpp464
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/g_pitch.h119
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/gain_q.cpp747
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/gain_q.h182
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/gsmamr_enc.h193
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/hp_max.cpp332
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/hp_max.h116
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/inter_36.cpp250
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/inter_36.h117
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.cpp213
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.h113
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/l_comp.cpp162
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/l_extract.cpp174
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/l_negate.cpp166
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/lag_wind.cpp195
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/lag_wind.h117
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.cpp233
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.h112
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/levinson.cpp824
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/levinson.h143
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/lpc.cpp542
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/lpc.h147
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/ol_ltp.cpp246
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/ol_ltp.h125
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/p_ol_wgh.cpp989
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp1609
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/pitch_fr.h148
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/pitch_ol.cpp1213
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/pitch_ol.h122
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/pre_big.cpp210
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/pre_big.h131
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/pre_proc.cpp589
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/pre_proc.h114
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/prm2bits.cpp310
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/prm2bits.h81
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/q_gain_c.cpp293
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/q_gain_c.h136
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/q_gain_p.cpp267
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/q_gain_p.h124
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp1445
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/qgain475.h180
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/qgain795.cpp904
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/qgain795.h143
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/qua_gain.cpp400
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/s10_8pf.cpp990
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/s10_8pf.h128
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp609
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/set_sign.h127
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/sid_sync.cpp544
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/sid_sync.h147
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/sp_enc.cpp754
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/sp_enc.h154
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/spreproc.cpp234
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/spreproc.h135
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/spstproc.cpp314
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/spstproc.h136
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/ton_stab.cpp801
-rw-r--r--media/libstagefright/codecs/amrnb/enc/src/ton_stab.h155
-rw-r--r--media/libstagefright/codecs/amrnb/patent_disclaimer.txt9
-rw-r--r--media/libstagefright/codecs/amrwb/Android.mk55
-rw-r--r--media/libstagefright/codecs/amrwb/include/pvamrwbdecoder_api.h154
-rw-r--r--media/libstagefright/codecs/amrwb/patent_disclaimer.txt9
-rw-r--r--media/libstagefright/codecs/amrwb/src/agc2_amr_wb.cpp190
-rw-r--r--media/libstagefright/codecs/amrwb/src/band_pass_6k_7k.cpp240
-rw-r--r--media/libstagefright/codecs/amrwb/src/dec_acelp_2p_in_64.cpp157
-rw-r--r--media/libstagefright/codecs/amrwb/src/dec_acelp_4p_in_64.cpp265
-rw-r--r--media/libstagefright/codecs/amrwb/src/dec_alg_codebook.cpp392
-rw-r--r--media/libstagefright/codecs/amrwb/src/dec_gain2_amr_wb.cpp404
-rw-r--r--media/libstagefright/codecs/amrwb/src/deemphasis_32.cpp166
-rw-r--r--media/libstagefright/codecs/amrwb/src/dtx.h242
-rw-r--r--media/libstagefright/codecs/amrwb/src/dtx_decoder_amr_wb.cpp984
-rw-r--r--media/libstagefright/codecs/amrwb/src/e_pv_amrwbdec.h136
-rw-r--r--media/libstagefright/codecs/amrwb/src/get_amr_wb_bits.cpp164
-rw-r--r--media/libstagefright/codecs/amrwb/src/get_amr_wb_bits.h60
-rw-r--r--media/libstagefright/codecs/amrwb/src/highpass_400hz_at_12k8.cpp201
-rw-r--r--media/libstagefright/codecs/amrwb/src/highpass_50hz_at_12k8.cpp205
-rw-r--r--media/libstagefright/codecs/amrwb/src/homing_amr_wb_dec.cpp370
-rw-r--r--media/libstagefright/codecs/amrwb/src/interpolate_isp.cpp146
-rw-r--r--media/libstagefright/codecs/amrwb/src/isf_extrapolation.cpp274
-rw-r--r--media/libstagefright/codecs/amrwb/src/isp_az.cpp403
-rw-r--r--media/libstagefright/codecs/amrwb/src/isp_isf.cpp175
-rw-r--r--media/libstagefright/codecs/amrwb/src/lagconceal.cpp364
-rw-r--r--media/libstagefright/codecs/amrwb/src/low_pass_filt_7k.cpp220
-rw-r--r--media/libstagefright/codecs/amrwb/src/median5.cpp180
-rw-r--r--media/libstagefright/codecs/amrwb/src/mime_io.cpp729
-rw-r--r--media/libstagefright/codecs/amrwb/src/mime_io.h124
-rw-r--r--media/libstagefright/codecs/amrwb/src/noise_gen_amrwb.cpp118
-rw-r--r--media/libstagefright/codecs/amrwb/src/normalize_amr_wb.cpp183
-rw-r--r--media/libstagefright/codecs/amrwb/src/normalize_amr_wb.h120
-rw-r--r--media/libstagefright/codecs/amrwb/src/oversamp_12k8_to_16k.cpp342
-rw-r--r--media/libstagefright/codecs/amrwb/src/phase_dispersion.cpp261
-rw-r--r--media/libstagefright/codecs/amrwb/src/pit_shrp.cpp132
-rw-r--r--media/libstagefright/codecs/amrwb/src/pred_lt4.cpp267
-rw-r--r--media/libstagefright/codecs/amrwb/src/preemph_amrwb_dec.cpp130
-rw-r--r--media/libstagefright/codecs/amrwb/src/pv_amr_wb_type_defs.h173
-rw-r--r--media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.cpp627
-rw-r--r--media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.h132
-rw-r--r--media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp1149
-rw-r--r--media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.h158
-rw-r--r--media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_acelp.h329
-rw-r--r--media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op.h249
-rw-r--r--media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_armv5.h253
-rw-r--r--media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_cequivalent.h545
-rw-r--r--media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_gcc_armv5.h319
-rw-r--r--media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_cnst.h142
-rw-r--r--media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_mem_funcs.h67
-rw-r--r--media/libstagefright/codecs/amrwb/src/q_gain2_tab.cpp244
-rw-r--r--media/libstagefright/codecs/amrwb/src/q_pulse.h79
-rw-r--r--media/libstagefright/codecs/amrwb/src/qisf_ns.cpp145
-rw-r--r--media/libstagefright/codecs/amrwb/src/qisf_ns.h113
-rw-r--r--media/libstagefright/codecs/amrwb/src/qisf_ns_tab.cpp367
-rw-r--r--media/libstagefright/codecs/amrwb/src/qpisf_2s.cpp350
-rw-r--r--media/libstagefright/codecs/amrwb/src/qpisf_2s.h117
-rw-r--r--media/libstagefright/codecs/amrwb/src/qpisf_2s_tab.cpp1383
-rw-r--r--media/libstagefright/codecs/amrwb/src/scale_signal.cpp154
-rw-r--r--media/libstagefright/codecs/amrwb/src/synthesis_amr_wb.cpp440
-rw-r--r--media/libstagefright/codecs/amrwb/src/synthesis_amr_wb.h96
-rw-r--r--media/libstagefright/codecs/amrwb/src/voice_factor.cpp175
-rw-r--r--media/libstagefright/codecs/amrwb/src/wb_syn_filt.cpp307
-rw-r--r--media/libstagefright/codecs/amrwb/src/weight_amrwb_lpc.cpp135
-rw-r--r--media/libstagefright/codecs/amrwbenc/Android.mk141
-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/SoftAMRWBEncoder.cpp459
-rw-r--r--media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.h76
-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.h1090
-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/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.c112
-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/Android.mk4
-rw-r--r--media/libstagefright/codecs/avc/common/Android.mk19
-rw-r--r--media/libstagefright/codecs/avc/common/include/avc_types.h29
-rw-r--r--media/libstagefright/codecs/avc/common/include/avcapi_common.h274
-rw-r--r--media/libstagefright/codecs/avc/common/include/avcint_common.h882
-rw-r--r--media/libstagefright/codecs/avc/common/include/avclib_common.h557
-rw-r--r--media/libstagefright/codecs/avc/common/src/deblock.cpp1666
-rw-r--r--media/libstagefright/codecs/avc/common/src/dpb.cpp724
-rw-r--r--media/libstagefright/codecs/avc/common/src/fmo.cpp249
-rw-r--r--media/libstagefright/codecs/avc/common/src/mb_access.cpp471
-rw-r--r--media/libstagefright/codecs/avc/common/src/reflist.cpp596
-rw-r--r--media/libstagefright/codecs/avc/enc/AVCEncoder.cpp619
-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/avc/patent_disclaimer.txt9
-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.c71
-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/g711/Android.mk4
-rw-r--r--media/libstagefright/codecs/g711/dec/Android.mk17
-rw-r--r--media/libstagefright/codecs/g711/dec/SoftG711.cpp304
-rw-r--r--media/libstagefright/codecs/g711/dec/SoftG711.h63
-rw-r--r--media/libstagefright/codecs/m4v_h263/Android.mk4
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/Android.mk75
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp597
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h92
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h67
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/include/mp4dec_api.h181
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/include/visual_header.h51
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/adaptive_smooth_no_mmx.cpp421
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/bitstream.cpp1001
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/bitstream.h174
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/block_idct.cpp911
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp182
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/chv_filter.cpp654
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/chvr_filter.cpp565
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/combined_decode.cpp840
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp193
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/datapart_decode.cpp794
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/dcac_prediction.cpp368
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp75
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/deringing_chroma.cpp215
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/deringing_luma.cpp231
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/find_min_max.cpp176
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp1190
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/get_pred_outside.cpp514
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/idct.cpp579
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/idct.h118
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/idct_vca.cpp660
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/max_level.h149
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/mb_motion_comp.cpp623
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/mb_utils.cpp133
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/mbtype_mode.h37
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/motion_comp.h108
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/mp4dec_lib.h334
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/mp4def.h167
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/mp4lib_int.h296
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/packet_util.cpp252
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/post_filter.cpp585
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/post_proc.h75
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/post_proc_semaphore.cpp247
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/pp_semaphore_chroma_inter.cpp262
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/pp_semaphore_luma.cpp378
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp1702
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/scaling.h52
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/scaling_tab.cpp88
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/vlc_dec_tab.h215
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp1636
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.h122
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/vlc_dequant.cpp1152
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/vlc_tab.cpp835
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp1643
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/zigzag.h72
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/zigzag_tab.cpp110
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/Android.mk37
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp487
-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/m4v_h263/patent_disclaimer.txt9
-rw-r--r--media/libstagefright/codecs/mp3dec/Android.mk81
-rw-r--r--media/libstagefright/codecs/mp3dec/SoftMP3.cpp340
-rw-r--r--media/libstagefright/codecs/mp3dec/SoftMP3.h80
-rw-r--r--media/libstagefright/codecs/mp3dec/include/mp3_decoder_selection.h30
-rw-r--r--media/libstagefright/codecs/mp3dec/include/pvmp3_audio_type_defs.h77
-rw-r--r--media/libstagefright/codecs/mp3dec/include/pvmp3decoder_api.h259
-rw-r--r--media/libstagefright/codecs/mp3dec/patent_disclaimer.txt9
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s474
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_arm.s210
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s193
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_arm.s369
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s359
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_wm.asm366
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_arm.s237
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s230
-rw-r--r--media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_wm.asm231
-rw-r--r--media/libstagefright/codecs/mp3dec/src/mp3_mem_funcs.h81
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pv_mp3_huffman.h115
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op.h84
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h203
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h252
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h123
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h132
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp261
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.h100
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_crc.cpp161
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_crc.h110
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_dct_16.cpp410
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_dct_16.h102
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_dct_6.cpp152
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp167
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_dec_defs.h199
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp194
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.h101
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp758
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_decode_huff_cw.h114
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp452
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_dequantize_sample.h106
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_equalizer.cpp415
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_equalizer.h101
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp834
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.h115
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp180
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_get_main_data_size.h101
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp226
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_get_scale_factors.h104
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp285
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.h102
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp257
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h112
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp304
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp328
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_imdct_synth.cpp376
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_imdct_synth.h102
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_18.cpp289
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_18.h109
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_6.cpp165
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_6.h106
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp247
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h105
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp202
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h105
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp700
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h112
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.cpp173
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.h108
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp187
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h102
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp239
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h138
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.cpp197
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.h103
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_seek_synch.cpp308
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_seek_synch.h106
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.cpp676
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.h114
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_tables.cpp2934
-rw-r--r--media/libstagefright/codecs/mp3dec/src/pvmp3_tables.h124
-rw-r--r--media/libstagefright/codecs/mp3dec/src/s_huffcodetab.h98
-rw-r--r--media/libstagefright/codecs/mp3dec/src/s_mp3bits.h107
-rw-r--r--media/libstagefright/codecs/mp3dec/src/s_tmp3dec_chan.h110
-rw-r--r--media/libstagefright/codecs/mp3dec/src/s_tmp3dec_file.h118
-rw-r--r--media/libstagefright/codecs/on2/Android.mk4
-rw-r--r--media/libstagefright/codecs/on2/dec/Android.mk24
-rw-r--r--media/libstagefright/codecs/on2/dec/SoftVPX.cpp382
-rw-r--r--media/libstagefright/codecs/on2/dec/SoftVPX.h70
-rw-r--r--media/libstagefright/codecs/on2/h264dec/Android.mk127
-rw-r--r--media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp561
-rw-r--r--media/libstagefright/codecs/on2/h264dec/SoftAVC.h108
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/inc/H264SwDecApi.h192
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/inc/basetype.h52
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/ARM_DELIVERY.TXT63
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/ARM_MANIFEST.TXT91
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM.h785
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_BitDec_s.h670
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_Bitstream.h212
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCTTable.h40
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCT_s.h1445
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_MaskTable.h27
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_Version.h43
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_s.h1154
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armOMX.h274
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes.h252
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes_s.h77
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm11/build_vc.pl111
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/filelist_vc.txt74
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM.c936
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_Bitstream.c329
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_IDCTTable.c60
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_MaskTable.c45
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVC.h1153
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVCCOMM_s.h72
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/omxVC.h4381
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/omxVC_s.h129
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_Copy16x16_s.s148
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_Copy8x8_s.s72
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s189
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/api/armVCM4P10_CAVLCTables.h30
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s222
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_CAVLCTables.c327
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s20
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s366
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s325
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DequantTables_s.s123
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s236
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s149
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s178
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s296
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s276
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s239
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s185
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s273
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_QuantTables_s.s74
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s407
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s92
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c88
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c91
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c62
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c68
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s480
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s336
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s437
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s331
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s550
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c79
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s426
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s494
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s501
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s567
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s128
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s469
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h37
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h25
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Clip8_s.s75
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s398
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c211
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Lookup_Tables.c75
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_SetPredDir_s.s104
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c61
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c102
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c208
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s364
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s132
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s136
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s224
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s194
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s73
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s713
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s283
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s141
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s188
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/src/armVC_Version.c6
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/ARM_DELIVERY.TXT63
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/ARM_MANIFEST.TXT91
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h785
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_BitDec_s.h670
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Bitstream.h212
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCTTable.h40
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCT_s.h1451
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_MaskTable.h27
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Version.h43
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_s.h1157
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armOMX.h274
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h252
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes_s.h77
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/build_vc.pl113
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/filelist_vc.txt75
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM.c936
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_Bitstream.c329
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_IDCTTable.c60
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_MaskTable.c45
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVC.h1153
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVCCOMM_s.h72
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/omxVC.h4381
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/omxVC_s.h129
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_Copy16x16_s.s95
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_Copy8x8_s.s70
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s236
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/api/armVCM4P10_CAVLCTables.h30
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s222
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_CAVLCTables.c327
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s198
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s396
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s325
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DequantTables_s.s123
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s236
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s149
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s178
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s313
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s266
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s228
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s134
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s318
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_QuantTables_s.s74
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s186
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s92
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c88
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c91
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c62
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c68
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s396
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s202
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s282
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s288
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s436
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c79
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s553
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s436
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s424
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s531
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s140
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s264
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Average_4x_Align_unsafe_s.S134
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingChroma_unsafe_s.S54
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingLuma_unsafe_s.S102
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S272
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S103
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Align_unsafe_s.S123
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Copy_unsafe_s.S105
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.S107
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.S164
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.S119
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.S72
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.S58
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Interpolate_Chroma_s.S175
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_QuantTables_s.S68
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_TransformResidual4x4_s.S52
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_UnpackBlock4x4_s.S40
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DeblockLuma_I.S67
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S119
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.S87
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.S123
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.S107
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.S157
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_InterpolateLuma_s.S323
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntraChroma_8x8_s.S217
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_16x16_s.S239
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_4x4_s.S261
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S54
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantLumaDCFromPair_s.S76
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h37
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h25
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Clip8_s.s82
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s398
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c211
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Lookup_Tables.c75
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_SetPredDir_s.s104
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c61
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c102
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c214
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s364
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s132
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s136
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s224
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s194
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s73
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s444
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s320
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s162
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s210
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/src/armVC_Version.c6
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/ARM_DELIVERY.TXT63
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/ARM_MANIFEST.TXT140
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h785
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM_Bitstream.h212
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM_Version.h43
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armOMX.h274
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/omxtypes.h252
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/omxdl/reference/build_vc.pl111
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/filelist_vc.txt123
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM.c936
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM_Bitstream.c329
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/api/armVC.h1153
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/api/omxVC.h4381
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_Average.c78
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_SAD.c75
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_16x.c86
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_8x.c87
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock.c88
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock_SAD.c93
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy16x16.c79
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy8x8.c79
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ExpandFrame_I.c126
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_LimitMVToRect.c81
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_16x.c80
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_8x.c80
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/api/armVCM4P10_CAVLCTables.h34
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CAVLCTables.c703
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CompareMotionCostToMV.c133
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DeBlockPixel.c151
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair.c267
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DequantTables.c45
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_FwdTransformResidual4x4.c78
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfDiag_Luma.c106
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfHor_Luma.c82
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfVer_Luma.c84
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Chroma.c109
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Luma.c195
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_PredictIntraDC4x4.c88
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_QuantTables.c31
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_SADQuar.c84
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_TransformResidual4x4.c80
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock2x2.c78
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock4x4.c78
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_Average_4x.c84
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Half.c191
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Integer.c196
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Quarter.c199
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c107
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c109
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c86
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c117
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd.c145
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I.c130
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I.c131
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I.c125
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I.c128
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_GetVLCInfo.c192
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c99
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfHor_Luma.c124
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfVer_Luma.c123
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateLuma.c99
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_ChromaDC.c102
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_LumaDC.c128
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformResidualAndAdd.c124
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEGetBufSize.c70
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEInit.c92
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c1892
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8.c284
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16.c198
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4.c338
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_16x.c86
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_4x.c85
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_8x.c87
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SAD_4x.c77
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SATD_4x4.c132
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SubAndTransformQDQResidual.c220
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair.c131
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair.c148
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_ChromaDC.c97
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_LumaDC.c119
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_DCT_Table.h30
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h42
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h25
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_ACDCPredict.c253
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Half.c187
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Integer.c167
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CheckVLCEscapeMode.c156
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CompareMV.c71
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DCT_Table.c112
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_intra.c144
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_EncodeVLCZigzag_intra.c145
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLCBuffer.c153
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLDBuffer.c84
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_GetVLCBits.c278
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c495
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_PutVLCBits.c200
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_SetPredDir.c89
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c58
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_16x16.c111
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_8x8.c109
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_16x16.c114
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_8x8.c110
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DCT8x8blk.c87
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c115
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c225
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP.c243
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter.c120
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC.c103
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC.c170
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeMV.c212
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_Inter.c112
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraACVLC.c97
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraDCVLC.c160
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_FindMVpred.c188
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_IDCT8x8blk.c92
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MCReconBlock.c357
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEGetBufSize.c70
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEInit.c84
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MotionEstimationMB.c630
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra.c121
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInter_I.c117
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantIntra_I.c153
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvInter_I.c96
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I.c153
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_inter.c108
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_intra.c260
-rw-r--r--media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/src/armVC_Version.c6
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/DecTestBench.c761
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c350
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c567
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c531
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor.s298
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor_ver.s339
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_ver.s288
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_half.s251
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_quarter.s273
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_ver_quarter.s536
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_mid_hor.s163
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_half.s347
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_quarter.s374
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/arm11_asm/win_asm.bat15
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdClearMbLayer.s66
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdCountLeadingZeros.s49
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFillRow7.s180
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFlushBits.s82
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdWriteMacroblock.s152
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/asm_common.S41
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdClearMbLayer.S68
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdCountLeadingZeros.S48
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFillRow7.S143
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFlushBits.S78
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdWriteMacroblock.S157
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.c237
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.h54
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.c916
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.h58
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_cfg.h56
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c626
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.h54
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_container.h69
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.c2417
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.h56
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.c961
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.h83
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c1584
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.h149
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_image.c345
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_image.h68
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c1027
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.h56
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.c1937
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.h81
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.c1446
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.h212
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.c117
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.h76
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.c382
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.h78
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.c347
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.h68
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.c335
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.h77
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.c2315
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.h210
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.c1692
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.h252
-rw-r--r--media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.c577
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.h86
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c354
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.h59
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.c589
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.h60
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.c1511
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.h186
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c888
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.h174
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.c242
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.h67
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.c402
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.h54
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c286
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h178
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.c391
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.h63
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.c490
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.h130
-rw-r--r--media/libstagefright/codecs/vorbis/Android.mk4
-rw-r--r--media/libstagefright/codecs/vorbis/dec/Android.mk20
-rw-r--r--media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp445
-rw-r--r--media/libstagefright/codecs/vorbis/dec/SoftVorbis.h78
-rw-r--r--media/libstagefright/colorconversion/Android.mk14
-rw-r--r--media/libstagefright/colorconversion/ColorConverter.cpp524
-rw-r--r--media/libstagefright/colorconversion/SoftwareRenderer.cpp230
-rw-r--r--media/libstagefright/foundation/AAtomizer.cpp67
-rw-r--r--media/libstagefright/foundation/ABitReader.cpp102
-rw-r--r--media/libstagefright/foundation/ABuffer.cpp76
-rw-r--r--media/libstagefright/foundation/AHandler.cpp33
-rw-r--r--media/libstagefright/foundation/AHierarchicalStateMachine.cpp113
-rw-r--r--media/libstagefright/foundation/ALooper.cpp222
-rw-r--r--media/libstagefright/foundation/ALooperRoster.cpp189
-rw-r--r--media/libstagefright/foundation/AMessage.cpp586
-rw-r--r--media/libstagefright/foundation/AString.cpp341
-rw-r--r--media/libstagefright/foundation/Android.mk30
-rw-r--r--media/libstagefright/foundation/base64.cpp139
-rw-r--r--media/libstagefright/foundation/hexdump.cpp77
-rw-r--r--media/libstagefright/httplive/Android.mk21
-rw-r--r--media/libstagefright/httplive/LiveDataSource.cpp173
-rw-r--r--media/libstagefright/httplive/LiveDataSource.h64
-rw-r--r--media/libstagefright/httplive/LiveSession.cpp943
-rw-r--r--media/libstagefright/httplive/M3UParser.cpp542
-rw-r--r--media/libstagefright/id3/Android.mk28
-rw-r--r--media/libstagefright/id3/ID3.cpp850
-rw-r--r--media/libstagefright/id3/testid3.cpp164
-rw-r--r--media/libstagefright/include/AACEncoder.h81
-rw-r--r--media/libstagefright/include/AACExtractor.h61
-rw-r--r--media/libstagefright/include/AMRExtractor.h62
-rw-r--r--media/libstagefright/include/AVCEncoder.h91
-rw-r--r--media/libstagefright/include/AVIExtractor.h126
-rw-r--r--media/libstagefright/include/AwesomePlayer.h327
-rw-r--r--media/libstagefright/include/ChromiumHTTPDataSource.h121
-rw-r--r--media/libstagefright/include/DRMExtractor.h62
-rw-r--r--media/libstagefright/include/DataUriSource.h76
-rw-r--r--media/libstagefright/include/ESDS.h66
-rw-r--r--media/libstagefright/include/FLACExtractor.h64
-rw-r--r--media/libstagefright/include/HTTPBase.h92
-rw-r--r--media/libstagefright/include/ID3.h95
-rw-r--r--media/libstagefright/include/LiveSession.h144
-rw-r--r--media/libstagefright/include/M3UParser.h87
-rw-r--r--media/libstagefright/include/M4vH263Encoder.h81
-rw-r--r--media/libstagefright/include/MP3Extractor.h61
-rw-r--r--media/libstagefright/include/MP3Seeker.h46
-rw-r--r--media/libstagefright/include/MPEG2PSExtractor.h80
-rw-r--r--media/libstagefright/include/MPEG2TSExtractor.h76
-rw-r--r--media/libstagefright/include/MPEG4Extractor.h108
-rw-r--r--media/libstagefright/include/NuCachedSource2.h139
-rw-r--r--media/libstagefright/include/OMX.h150
-rw-r--r--media/libstagefright/include/OMXNodeInstance.h141
-rw-r--r--media/libstagefright/include/OggExtractor.h66
-rw-r--r--media/libstagefright/include/SampleIterator.h75
-rw-r--r--media/libstagefright/include/SampleTable.h153
-rw-r--r--media/libstagefright/include/SimpleSoftOMXComponent.h143
-rw-r--r--media/libstagefright/include/SoftOMXComponent.h173
-rw-r--r--media/libstagefright/include/SoftwareRenderer.h58
-rw-r--r--media/libstagefright/include/StagefrightMetadataRetriever.h64
-rw-r--r--media/libstagefright/include/ThrottledSource.h57
-rw-r--r--media/libstagefright/include/TimedEventQueue.h132
-rw-r--r--media/libstagefright/include/VBRISeeker.h50
-rw-r--r--media/libstagefright/include/WAVExtractor.h70
-rw-r--r--media/libstagefright/include/WVMExtractor.h86
-rw-r--r--media/libstagefright/include/XINGSeeker.h56
-rw-r--r--media/libstagefright/include/avc_utils.h73
-rw-r--r--media/libstagefright/matroska/Android.mk15
-rw-r--r--media/libstagefright/matroska/MatroskaExtractor.cpp898
-rw-r--r--media/libstagefright/matroska/MatroskaExtractor.h88
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.cpp1012
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.h114
-rw-r--r--media/libstagefright/mpeg2ts/Android.mk22
-rw-r--r--media/libstagefright/mpeg2ts/AnotherPacketSource.cpp222
-rw-r--r--media/libstagefright/mpeg2ts/AnotherPacketSource.h77
-rw-r--r--media/libstagefright/mpeg2ts/ESQueue.cpp954
-rw-r--r--media/libstagefright/mpeg2ts/ESQueue.h76
-rw-r--r--media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp715
-rw-r--r--media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp266
-rw-r--r--media/libstagefright/omx/Android.mk32
-rw-r--r--media/libstagefright/omx/OMX.cpp470
-rw-r--r--media/libstagefright/omx/OMXMaster.cpp202
-rw-r--r--media/libstagefright/omx/OMXMaster.h71
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp757
-rw-r--r--media/libstagefright/omx/SimpleSoftOMXComponent.cpp645
-rw-r--r--media/libstagefright/omx/SoftOMXComponent.cpp326
-rw-r--r--media/libstagefright/omx/SoftOMXPlugin.cpp177
-rw-r--r--media/libstagefright/omx/SoftOMXPlugin.h53
-rw-r--r--media/libstagefright/omx/tests/Android.mk18
-rw-r--r--media/libstagefright/omx/tests/OMXHarness.cpp855
-rw-r--r--media/libstagefright/omx/tests/OMXHarness.h105
-rw-r--r--media/libstagefright/rtsp/AAMRAssembler.cpp234
-rw-r--r--media/libstagefright/rtsp/AAMRAssembler.h59
-rw-r--r--media/libstagefright/rtsp/AAVCAssembler.cpp376
-rw-r--r--media/libstagefright/rtsp/AAVCAssembler.h62
-rw-r--r--media/libstagefright/rtsp/AH263Assembler.cpp187
-rw-r--r--media/libstagefright/rtsp/AH263Assembler.h57
-rw-r--r--media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp591
-rw-r--r--media/libstagefright/rtsp/AMPEG4AudioAssembler.h69
-rw-r--r--media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp399
-rw-r--r--media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h74
-rw-r--r--media/libstagefright/rtsp/APacketSource.cpp579
-rw-r--r--media/libstagefright/rtsp/APacketSource.h50
-rw-r--r--media/libstagefright/rtsp/ARTPAssembler.cpp77
-rw-r--r--media/libstagefright/rtsp/ARTPAssembler.h56
-rw-r--r--media/libstagefright/rtsp/ARTPConnection.cpp674
-rw-r--r--media/libstagefright/rtsp/ARTPConnection.h97
-rw-r--r--media/libstagefright/rtsp/ARTPSession.cpp242
-rw-r--r--media/libstagefright/rtsp/ARTPSession.h69
-rw-r--r--media/libstagefright/rtsp/ARTPSource.cpp275
-rw-r--r--media/libstagefright/rtsp/ARTPSource.h73
-rw-r--r--media/libstagefright/rtsp/ARTPWriter.cpp836
-rw-r--r--media/libstagefright/rtsp/ARTPWriter.h128
-rw-r--r--media/libstagefright/rtsp/ARTSPConnection.cpp1057
-rw-r--r--media/libstagefright/rtsp/ARTSPConnection.h132
-rw-r--r--media/libstagefright/rtsp/ARawAudioAssembler.cpp143
-rw-r--r--media/libstagefright/rtsp/ARawAudioAssembler.h60
-rw-r--r--media/libstagefright/rtsp/ASessionDescription.cpp336
-rw-r--r--media/libstagefright/rtsp/ASessionDescription.h83
-rw-r--r--media/libstagefright/rtsp/Android.mk56
-rw-r--r--media/libstagefright/rtsp/MyHandler.h1522
-rw-r--r--media/libstagefright/rtsp/MyTransmitter.h981
-rw-r--r--media/libstagefright/rtsp/UDPPusher.cpp150
-rw-r--r--media/libstagefright/rtsp/UDPPusher.h56
-rw-r--r--media/libstagefright/rtsp/VideoSource.h98
-rw-r--r--media/libstagefright/rtsp/rtp_test.cpp230
-rw-r--r--media/libstagefright/tests/Android.mk54
-rw-r--r--media/libstagefright/tests/DummyRecorder.cpp91
-rw-r--r--media/libstagefright/tests/DummyRecorder.h58
-rw-r--r--media/libstagefright/tests/SurfaceMediaSource_test.cpp937
-rw-r--r--media/libstagefright/timedtext/Android.mk19
-rw-r--r--media/libstagefright/timedtext/TextDescriptions.cpp385
-rw-r--r--media/libstagefright/timedtext/TextDescriptions.h84
-rw-r--r--media/libstagefright/timedtext/TimedText3GPPSource.cpp119
-rw-r--r--media/libstagefright/timedtext/TimedText3GPPSource.h57
-rw-r--r--media/libstagefright/timedtext/TimedTextDriver.cpp222
-rw-r--r--media/libstagefright/timedtext/TimedTextPlayer.cpp212
-rw-r--r--media/libstagefright/timedtext/TimedTextPlayer.h79
-rw-r--r--media/libstagefright/timedtext/TimedTextSRTSource.cpp286
-rw-r--r--media/libstagefright/timedtext/TimedTextSRTSource.h78
-rw-r--r--media/libstagefright/timedtext/TimedTextSource.cpp66
-rw-r--r--media/libstagefright/timedtext/TimedTextSource.h64
-rw-r--r--media/libstagefright/yuv/Android.mk15
-rw-r--r--media/libstagefright/yuv/YUVCanvas.cpp111
-rw-r--r--media/libstagefright/yuv/YUVImage.cpp413
-rw-r--r--media/mediaserver/Android.mk23
-rw-r--r--media/mediaserver/main_mediaserver.cpp45
-rw-r--r--media/mtp/Android.mk75
-rw-r--r--media/mtp/MtpDataPacket.cpp490
-rw-r--r--media/mtp/MtpDataPacket.h124
-rw-r--r--media/mtp/MtpDatabase.h113
-rw-r--r--media/mtp/MtpDebug.cpp402
-rw-r--r--media/mtp/MtpDebug.h37
-rw-r--r--media/mtp/MtpDevice.cpp835
-rw-r--r--media/mtp/MtpDevice.h116
-rw-r--r--media/mtp/MtpDeviceInfo.cpp97
-rw-r--r--media/mtp/MtpDeviceInfo.h54
-rw-r--r--media/mtp/MtpEventPacket.cpp70
-rw-r--r--media/mtp/MtpEventPacket.h48
-rw-r--r--media/mtp/MtpObjectInfo.cpp108
-rw-r--r--media/mtp/MtpObjectInfo.h60
-rw-r--r--media/mtp/MtpPacket.cpp166
-rw-r--r--media/mtp/MtpPacket.h72
-rw-r--r--media/mtp/MtpProperty.cpp534
-rw-r--r--media/mtp/MtpProperty.h114
-rw-r--r--media/mtp/MtpRequestPacket.cpp60
-rw-r--r--media/mtp/MtpRequestPacket.h50
-rw-r--r--media/mtp/MtpResponsePacket.cpp60
-rw-r--r--media/mtp/MtpResponsePacket.h48
-rw-r--r--media/mtp/MtpServer.cpp1210
-rw-r--r--media/mtp/MtpServer.h154
-rw-r--r--media/mtp/MtpStorage.cpp86
-rw-r--r--media/mtp/MtpStorage.h59
-rw-r--r--media/mtp/MtpStorageInfo.cpp72
-rw-r--r--media/mtp/MtpStorageInfo.h49
-rw-r--r--media/mtp/MtpStringBuffer.cpp171
-rw-r--r--media/mtp/MtpStringBuffer.h57
-rw-r--r--media/mtp/MtpTypes.h78
-rw-r--r--media/mtp/MtpUtils.cpp80
-rw-r--r--media/mtp/MtpUtils.h29
-rw-r--r--media/mtp/mtp.h492
-rw-r--r--services/audioflinger/Android.mk39
-rw-r--r--services/audioflinger/AudioBufferProvider.h55
-rw-r--r--services/audioflinger/AudioFlinger.cpp8144
-rw-r--r--services/audioflinger/AudioFlinger.h1689
-rw-r--r--services/audioflinger/AudioMixer.cpp1155
-rw-r--r--services/audioflinger/AudioMixer.h235
-rw-r--r--services/audioflinger/AudioPolicyService.cpp1510
-rw-r--r--services/audioflinger/AudioPolicyService.h324
-rw-r--r--services/audioflinger/AudioResampler.cpp624
-rw-r--r--services/audioflinger/AudioResampler.h102
-rw-r--r--services/audioflinger/AudioResamplerCubic.cpp185
-rw-r--r--services/audioflinger/AudioResamplerCubic.h68
-rw-r--r--services/audioflinger/AudioResamplerSinc.cpp357
-rw-r--r--services/audioflinger/AudioResamplerSinc.h88
-rw-r--r--services/audioflinger/ServiceUtilities.cpp55
-rw-r--r--services/audioflinger/ServiceUtilities.h27
-rw-r--r--services/camera/libcameraservice/Android.mk25
-rw-r--r--services/camera/libcameraservice/CameraHardwareInterface.h696
-rw-r--r--services/camera/libcameraservice/CameraHardwareStub.cpp410
-rw-r--r--services/camera/libcameraservice/CameraHardwareStub.h126
-rw-r--r--services/camera/libcameraservice/CameraService.cpp1380
-rw-r--r--services/camera/libcameraservice/CameraService.h231
-rw-r--r--services/camera/libcameraservice/CannedJpeg.h750
-rw-r--r--services/camera/libcameraservice/FakeCamera.cpp433
-rw-r--r--services/camera/libcameraservice/FakeCamera.h67
-rw-r--r--services/camera/tests/CameraServiceTest/Android.mk26
-rw-r--r--services/camera/tests/CameraServiceTest/CameraServiceTest.cpp924
2333 files changed, 657121 insertions, 0 deletions
diff --git a/camera/Android.mk b/camera/Android.mk
new file mode 100644
index 0000000..7286f92
--- /dev/null
+++ b/camera/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ Camera.cpp \
+ CameraParameters.cpp \
+ ICamera.cpp \
+ ICameraClient.cpp \
+ ICameraService.cpp \
+ ICameraRecordingProxy.cpp \
+ ICameraRecordingProxyListener.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libutils \
+ libbinder \
+ libhardware \
+ libui \
+ libgui
+
+LOCAL_MODULE:= libcamera_client
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
new file mode 100644
index 0000000..b81fe86
--- /dev/null
+++ b/camera/Camera.cpp
@@ -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.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Camera"
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/IMemory.h>
+
+#include <camera/Camera.h>
+#include <camera/ICameraRecordingProxyListener.h>
+#include <camera/ICameraService.h>
+
+#include <gui/ISurfaceTexture.h>
+#include <gui/Surface.h>
+
+namespace android {
+
+// client singleton for camera service binder interface
+Mutex Camera::mLock;
+sp<ICameraService> Camera::mCameraService;
+sp<Camera::DeathNotifier> Camera::mDeathNotifier;
+
+// establish binder interface to camera service
+const sp<ICameraService>& Camera::getCameraService()
+{
+ Mutex::Autolock _l(mLock);
+ if (mCameraService.get() == 0) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder;
+ do {
+ binder = sm->getService(String16("media.camera"));
+ if (binder != 0)
+ break;
+ ALOGW("CameraService not published, waiting...");
+ usleep(500000); // 0.5 s
+ } while(true);
+ if (mDeathNotifier == NULL) {
+ mDeathNotifier = new DeathNotifier();
+ }
+ binder->linkToDeath(mDeathNotifier);
+ mCameraService = interface_cast<ICameraService>(binder);
+ }
+ ALOGE_IF(mCameraService==0, "no CameraService!?");
+ return mCameraService;
+}
+
+// ---------------------------------------------------------------------------
+
+Camera::Camera()
+{
+ init();
+}
+
+// construct a camera client from an existing camera remote
+sp<Camera> Camera::create(const sp<ICamera>& camera)
+{
+ ALOGV("create");
+ if (camera == 0) {
+ ALOGE("camera remote is a NULL pointer");
+ return 0;
+ }
+
+ sp<Camera> c = new Camera();
+ if (camera->connect(c) == NO_ERROR) {
+ c->mStatus = NO_ERROR;
+ c->mCamera = camera;
+ camera->asBinder()->linkToDeath(c);
+ return c;
+ }
+ return 0;
+}
+
+void Camera::init()
+{
+ mStatus = UNKNOWN_ERROR;
+}
+
+Camera::~Camera()
+{
+ // We don't need to call disconnect() here because if the CameraService
+ // thinks we are the owner of the hardware, it will hold a (strong)
+ // reference to us, and we can't possibly be here. We also don't want to
+ // call disconnect() here if we are in the same process as mediaserver,
+ // because we may be invoked by CameraService::Client::connect() and will
+ // deadlock if we call any method of ICamera here.
+}
+
+int32_t Camera::getNumberOfCameras()
+{
+ const sp<ICameraService>& cs = getCameraService();
+ if (cs == 0) return 0;
+ return cs->getNumberOfCameras();
+}
+
+status_t Camera::getCameraInfo(int cameraId,
+ struct CameraInfo* cameraInfo) {
+ const sp<ICameraService>& cs = getCameraService();
+ if (cs == 0) return UNKNOWN_ERROR;
+ return cs->getCameraInfo(cameraId, cameraInfo);
+}
+
+sp<Camera> Camera::connect(int cameraId, bool force, bool keep)
+{
+ ALOGV("connect");
+ sp<Camera> c = new Camera();
+ const sp<ICameraService>& cs = getCameraService();
+ if (cs != 0) {
+ c->mCamera = cs->connect(c, cameraId, force, keep);
+ }
+ if (c->mCamera != 0) {
+ c->mCamera->asBinder()->linkToDeath(c);
+ c->mStatus = NO_ERROR;
+ } else {
+ c.clear();
+ }
+ return c;
+}
+
+void Camera::disconnect()
+{
+ ALOGV("disconnect");
+ if (mCamera != 0) {
+ mCamera->disconnect();
+ mCamera->asBinder()->unlinkToDeath(this);
+ mCamera = 0;
+ }
+}
+
+status_t Camera::reconnect()
+{
+ ALOGV("reconnect");
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->connect(this);
+}
+
+sp<ICamera> Camera::remote()
+{
+ return mCamera;
+}
+
+status_t Camera::lock()
+{
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->lock();
+}
+
+status_t Camera::unlock()
+{
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->unlock();
+}
+
+// pass the buffered Surface to the camera service
+status_t Camera::setPreviewDisplay(const sp<Surface>& surface)
+{
+ ALOGV("setPreviewDisplay(%p)", surface.get());
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ if (surface != 0) {
+ return c->setPreviewDisplay(surface);
+ } else {
+ ALOGD("app passed NULL surface");
+ return c->setPreviewDisplay(0);
+ }
+}
+
+// pass the buffered ISurfaceTexture to the camera service
+status_t Camera::setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture)
+{
+ ALOGV("setPreviewTexture(%p)", surfaceTexture.get());
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ if (surfaceTexture != 0) {
+ return c->setPreviewTexture(surfaceTexture);
+ } else {
+ ALOGD("app passed NULL surface");
+ return c->setPreviewTexture(0);
+ }
+}
+
+// start preview mode
+status_t Camera::startPreview()
+{
+ ALOGV("startPreview");
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->startPreview();
+}
+
+status_t Camera::storeMetaDataInBuffers(bool enabled)
+{
+ ALOGV("storeMetaDataInBuffers: %s",
+ enabled? "true": "false");
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->storeMetaDataInBuffers(enabled);
+}
+
+// start recording mode, must call setPreviewDisplay first
+status_t Camera::startRecording()
+{
+ ALOGV("startRecording");
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->startRecording();
+}
+
+// stop preview mode
+void Camera::stopPreview()
+{
+ ALOGV("stopPreview");
+ sp <ICamera> c = mCamera;
+ if (c == 0) return;
+ c->stopPreview();
+}
+
+// stop recording mode
+void Camera::stopRecording()
+{
+ ALOGV("stopRecording");
+ {
+ Mutex::Autolock _l(mLock);
+ mRecordingProxyListener.clear();
+ }
+ sp <ICamera> c = mCamera;
+ if (c == 0) return;
+ c->stopRecording();
+}
+
+// release a recording frame
+void Camera::releaseRecordingFrame(const sp<IMemory>& mem)
+{
+ ALOGV("releaseRecordingFrame");
+ sp <ICamera> c = mCamera;
+ if (c == 0) return;
+ c->releaseRecordingFrame(mem);
+}
+
+// get preview state
+bool Camera::previewEnabled()
+{
+ ALOGV("previewEnabled");
+ sp <ICamera> c = mCamera;
+ if (c == 0) return false;
+ return c->previewEnabled();
+}
+
+// get recording state
+bool Camera::recordingEnabled()
+{
+ ALOGV("recordingEnabled");
+ sp <ICamera> c = mCamera;
+ if (c == 0) return false;
+ return c->recordingEnabled();
+}
+
+status_t Camera::autoFocus()
+{
+ ALOGV("autoFocus");
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->autoFocus();
+}
+
+status_t Camera::cancelAutoFocus()
+{
+ ALOGV("cancelAutoFocus");
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->cancelAutoFocus();
+}
+
+// take a picture
+status_t Camera::takePicture(int msgType)
+{
+ ALOGV("takePicture: 0x%x", msgType);
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->takePicture(msgType);
+}
+
+// set preview/capture parameters - key/value pairs
+status_t Camera::setParameters(const String8& params)
+{
+ ALOGV("setParameters");
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->setParameters(params);
+}
+
+// get preview/capture parameters - key/value pairs
+String8 Camera::getParameters() const
+{
+ ALOGV("getParameters");
+ String8 params;
+ sp <ICamera> c = mCamera;
+ if (c != 0) params = mCamera->getParameters();
+ return params;
+}
+
+// send command to camera driver
+status_t Camera::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
+{
+ ALOGV("sendCommand");
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->sendCommand(cmd, arg1, arg2);
+}
+
+void Camera::setListener(const sp<CameraListener>& listener)
+{
+ Mutex::Autolock _l(mLock);
+ mListener = listener;
+}
+
+void Camera::setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener)
+{
+ Mutex::Autolock _l(mLock);
+ mRecordingProxyListener = listener;
+}
+
+void Camera::setPreviewCallbackFlags(int flag)
+{
+ ALOGV("setPreviewCallbackFlags");
+ sp <ICamera> c = mCamera;
+ if (c == 0) return;
+ mCamera->setPreviewCallbackFlag(flag);
+}
+
+// callback from camera service
+void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
+{
+ sp<CameraListener> listener;
+ {
+ Mutex::Autolock _l(mLock);
+ listener = mListener;
+ }
+ if (listener != NULL) {
+ listener->notify(msgType, ext1, ext2);
+ }
+}
+
+// callback from camera service when frame or image is ready
+void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata)
+{
+ sp<CameraListener> listener;
+ {
+ Mutex::Autolock _l(mLock);
+ listener = mListener;
+ }
+ if (listener != NULL) {
+ listener->postData(msgType, dataPtr, metadata);
+ }
+}
+
+// callback from camera service when timestamped frame is ready
+void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
+{
+ // If recording proxy listener is registered, forward the frame and return.
+ // The other listener (mListener) is ignored because the receiver needs to
+ // call releaseRecordingFrame.
+ sp<ICameraRecordingProxyListener> proxylistener;
+ {
+ Mutex::Autolock _l(mLock);
+ proxylistener = mRecordingProxyListener;
+ }
+ if (proxylistener != NULL) {
+ proxylistener->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+ return;
+ }
+
+ sp<CameraListener> listener;
+ {
+ Mutex::Autolock _l(mLock);
+ listener = mListener;
+ }
+ if (listener != NULL) {
+ listener->postDataTimestamp(timestamp, msgType, dataPtr);
+ } else {
+ ALOGW("No listener was set. Drop a recording frame.");
+ releaseRecordingFrame(dataPtr);
+ }
+}
+
+void Camera::binderDied(const wp<IBinder>& who) {
+ ALOGW("ICamera died");
+ notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0);
+}
+
+void Camera::DeathNotifier::binderDied(const wp<IBinder>& who) {
+ ALOGV("binderDied");
+ Mutex::Autolock _l(Camera::mLock);
+ Camera::mCameraService.clear();
+ ALOGW("Camera server died!");
+}
+
+sp<ICameraRecordingProxy> Camera::getRecordingProxy() {
+ ALOGV("getProxy");
+ return new RecordingProxy(this);
+}
+
+status_t Camera::RecordingProxy::startRecording(const sp<ICameraRecordingProxyListener>& listener)
+{
+ ALOGV("RecordingProxy::startRecording");
+ mCamera->setRecordingProxyListener(listener);
+ mCamera->reconnect();
+ return mCamera->startRecording();
+}
+
+void Camera::RecordingProxy::stopRecording()
+{
+ ALOGV("RecordingProxy::stopRecording");
+ mCamera->stopRecording();
+}
+
+void Camera::RecordingProxy::releaseRecordingFrame(const sp<IMemory>& mem)
+{
+ ALOGV("RecordingProxy::releaseRecordingFrame");
+ mCamera->releaseRecordingFrame(mem);
+}
+
+Camera::RecordingProxy::RecordingProxy(const sp<Camera>& camera)
+{
+ mCamera = camera;
+}
+
+}; // namespace android
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
new file mode 100644
index 0000000..059a8a5
--- /dev/null
+++ b/camera/CameraParameters.cpp
@@ -0,0 +1,479 @@
+/*
+**
+** 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.
+*/
+
+#define LOG_TAG "CameraParams"
+#include <utils/Log.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <camera/CameraParameters.h>
+
+namespace android {
+// Parameter keys to communicate between camera application and driver.
+const char CameraParameters::KEY_PREVIEW_SIZE[] = "preview-size";
+const char CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES[] = "preview-size-values";
+const char CameraParameters::KEY_PREVIEW_FORMAT[] = "preview-format";
+const char CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS[] = "preview-format-values";
+const char CameraParameters::KEY_PREVIEW_FRAME_RATE[] = "preview-frame-rate";
+const char CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES[] = "preview-frame-rate-values";
+const char CameraParameters::KEY_PREVIEW_FPS_RANGE[] = "preview-fps-range";
+const char CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE[] = "preview-fps-range-values";
+const char CameraParameters::KEY_PICTURE_SIZE[] = "picture-size";
+const char CameraParameters::KEY_SUPPORTED_PICTURE_SIZES[] = "picture-size-values";
+const char CameraParameters::KEY_PICTURE_FORMAT[] = "picture-format";
+const char CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS[] = "picture-format-values";
+const char CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH[] = "jpeg-thumbnail-width";
+const char CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT[] = "jpeg-thumbnail-height";
+const char CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES[] = "jpeg-thumbnail-size-values";
+const char CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY[] = "jpeg-thumbnail-quality";
+const char CameraParameters::KEY_JPEG_QUALITY[] = "jpeg-quality";
+const char CameraParameters::KEY_ROTATION[] = "rotation";
+const char CameraParameters::KEY_GPS_LATITUDE[] = "gps-latitude";
+const char CameraParameters::KEY_GPS_LONGITUDE[] = "gps-longitude";
+const char CameraParameters::KEY_GPS_ALTITUDE[] = "gps-altitude";
+const char CameraParameters::KEY_GPS_TIMESTAMP[] = "gps-timestamp";
+const char CameraParameters::KEY_GPS_PROCESSING_METHOD[] = "gps-processing-method";
+const char CameraParameters::KEY_WHITE_BALANCE[] = "whitebalance";
+const char CameraParameters::KEY_SUPPORTED_WHITE_BALANCE[] = "whitebalance-values";
+const char CameraParameters::KEY_EFFECT[] = "effect";
+const char CameraParameters::KEY_SUPPORTED_EFFECTS[] = "effect-values";
+const char CameraParameters::KEY_ANTIBANDING[] = "antibanding";
+const char CameraParameters::KEY_SUPPORTED_ANTIBANDING[] = "antibanding-values";
+const char CameraParameters::KEY_SCENE_MODE[] = "scene-mode";
+const char CameraParameters::KEY_SUPPORTED_SCENE_MODES[] = "scene-mode-values";
+const char CameraParameters::KEY_FLASH_MODE[] = "flash-mode";
+const char CameraParameters::KEY_SUPPORTED_FLASH_MODES[] = "flash-mode-values";
+const char CameraParameters::KEY_FOCUS_MODE[] = "focus-mode";
+const char CameraParameters::KEY_SUPPORTED_FOCUS_MODES[] = "focus-mode-values";
+const char CameraParameters::KEY_MAX_NUM_FOCUS_AREAS[] = "max-num-focus-areas";
+const char CameraParameters::KEY_FOCUS_AREAS[] = "focus-areas";
+const char CameraParameters::KEY_FOCAL_LENGTH[] = "focal-length";
+const char CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE[] = "horizontal-view-angle";
+const char CameraParameters::KEY_VERTICAL_VIEW_ANGLE[] = "vertical-view-angle";
+const char CameraParameters::KEY_EXPOSURE_COMPENSATION[] = "exposure-compensation";
+const char CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION[] = "max-exposure-compensation";
+const char CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION[] = "min-exposure-compensation";
+const char CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP[] = "exposure-compensation-step";
+const char CameraParameters::KEY_AUTO_EXPOSURE_LOCK[] = "auto-exposure-lock";
+const char CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED[] = "auto-exposure-lock-supported";
+const char CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK[] = "auto-whitebalance-lock";
+const char CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED[] = "auto-whitebalance-lock-supported";
+const char CameraParameters::KEY_MAX_NUM_METERING_AREAS[] = "max-num-metering-areas";
+const char CameraParameters::KEY_METERING_AREAS[] = "metering-areas";
+const char CameraParameters::KEY_ZOOM[] = "zoom";
+const char CameraParameters::KEY_MAX_ZOOM[] = "max-zoom";
+const char CameraParameters::KEY_ZOOM_RATIOS[] = "zoom-ratios";
+const char CameraParameters::KEY_ZOOM_SUPPORTED[] = "zoom-supported";
+const char CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED[] = "smooth-zoom-supported";
+const char CameraParameters::KEY_FOCUS_DISTANCES[] = "focus-distances";
+const char CameraParameters::KEY_VIDEO_FRAME_FORMAT[] = "video-frame-format";
+const char CameraParameters::KEY_VIDEO_SIZE[] = "video-size";
+const char CameraParameters::KEY_SUPPORTED_VIDEO_SIZES[] = "video-size-values";
+const char CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[] = "preferred-preview-size-for-video";
+const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW[] = "max-num-detected-faces-hw";
+const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW[] = "max-num-detected-faces-sw";
+const char CameraParameters::KEY_RECORDING_HINT[] = "recording-hint";
+const char CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED[] = "video-snapshot-supported";
+const char CameraParameters::KEY_VIDEO_STABILIZATION[] = "video-stabilization";
+const char CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED[] = "video-stabilization-supported";
+
+const char CameraParameters::TRUE[] = "true";
+const char CameraParameters::FALSE[] = "false";
+const char CameraParameters::FOCUS_DISTANCE_INFINITY[] = "Infinity";
+
+// Values for white balance settings.
+const char CameraParameters::WHITE_BALANCE_AUTO[] = "auto";
+const char CameraParameters::WHITE_BALANCE_INCANDESCENT[] = "incandescent";
+const char CameraParameters::WHITE_BALANCE_FLUORESCENT[] = "fluorescent";
+const char CameraParameters::WHITE_BALANCE_WARM_FLUORESCENT[] = "warm-fluorescent";
+const char CameraParameters::WHITE_BALANCE_DAYLIGHT[] = "daylight";
+const char CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT[] = "cloudy-daylight";
+const char CameraParameters::WHITE_BALANCE_TWILIGHT[] = "twilight";
+const char CameraParameters::WHITE_BALANCE_SHADE[] = "shade";
+
+// Values for effect settings.
+const char CameraParameters::EFFECT_NONE[] = "none";
+const char CameraParameters::EFFECT_MONO[] = "mono";
+const char CameraParameters::EFFECT_NEGATIVE[] = "negative";
+const char CameraParameters::EFFECT_SOLARIZE[] = "solarize";
+const char CameraParameters::EFFECT_SEPIA[] = "sepia";
+const char CameraParameters::EFFECT_POSTERIZE[] = "posterize";
+const char CameraParameters::EFFECT_WHITEBOARD[] = "whiteboard";
+const char CameraParameters::EFFECT_BLACKBOARD[] = "blackboard";
+const char CameraParameters::EFFECT_AQUA[] = "aqua";
+
+// Values for antibanding settings.
+const char CameraParameters::ANTIBANDING_AUTO[] = "auto";
+const char CameraParameters::ANTIBANDING_50HZ[] = "50hz";
+const char CameraParameters::ANTIBANDING_60HZ[] = "60hz";
+const char CameraParameters::ANTIBANDING_OFF[] = "off";
+
+// Values for flash mode settings.
+const char CameraParameters::FLASH_MODE_OFF[] = "off";
+const char CameraParameters::FLASH_MODE_AUTO[] = "auto";
+const char CameraParameters::FLASH_MODE_ON[] = "on";
+const char CameraParameters::FLASH_MODE_RED_EYE[] = "red-eye";
+const char CameraParameters::FLASH_MODE_TORCH[] = "torch";
+
+// Values for scene mode settings.
+const char CameraParameters::SCENE_MODE_AUTO[] = "auto";
+const char CameraParameters::SCENE_MODE_ACTION[] = "action";
+const char CameraParameters::SCENE_MODE_PORTRAIT[] = "portrait";
+const char CameraParameters::SCENE_MODE_LANDSCAPE[] = "landscape";
+const char CameraParameters::SCENE_MODE_NIGHT[] = "night";
+const char CameraParameters::SCENE_MODE_NIGHT_PORTRAIT[] = "night-portrait";
+const char CameraParameters::SCENE_MODE_THEATRE[] = "theatre";
+const char CameraParameters::SCENE_MODE_BEACH[] = "beach";
+const char CameraParameters::SCENE_MODE_SNOW[] = "snow";
+const char CameraParameters::SCENE_MODE_SUNSET[] = "sunset";
+const char CameraParameters::SCENE_MODE_STEADYPHOTO[] = "steadyphoto";
+const char CameraParameters::SCENE_MODE_FIREWORKS[] = "fireworks";
+const char CameraParameters::SCENE_MODE_SPORTS[] = "sports";
+const char CameraParameters::SCENE_MODE_PARTY[] = "party";
+const char CameraParameters::SCENE_MODE_CANDLELIGHT[] = "candlelight";
+const char CameraParameters::SCENE_MODE_BARCODE[] = "barcode";
+
+const char CameraParameters::PIXEL_FORMAT_YUV422SP[] = "yuv422sp";
+const char CameraParameters::PIXEL_FORMAT_YUV420SP[] = "yuv420sp";
+const char CameraParameters::PIXEL_FORMAT_YUV422I[] = "yuv422i-yuyv";
+const char CameraParameters::PIXEL_FORMAT_YUV420P[] = "yuv420p";
+const char CameraParameters::PIXEL_FORMAT_RGB565[] = "rgb565";
+const char CameraParameters::PIXEL_FORMAT_RGBA8888[] = "rgba8888";
+const char CameraParameters::PIXEL_FORMAT_JPEG[] = "jpeg";
+const char CameraParameters::PIXEL_FORMAT_BAYER_RGGB[] = "bayer-rggb";
+
+// Values for focus mode settings.
+const char CameraParameters::FOCUS_MODE_AUTO[] = "auto";
+const char CameraParameters::FOCUS_MODE_INFINITY[] = "infinity";
+const char CameraParameters::FOCUS_MODE_MACRO[] = "macro";
+const char CameraParameters::FOCUS_MODE_FIXED[] = "fixed";
+const char CameraParameters::FOCUS_MODE_EDOF[] = "edof";
+const char CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO[] = "continuous-video";
+const char CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE[] = "continuous-picture";
+
+CameraParameters::CameraParameters()
+ : mMap()
+{
+}
+
+CameraParameters::~CameraParameters()
+{
+}
+
+String8 CameraParameters::flatten() const
+{
+ String8 flattened("");
+ size_t size = mMap.size();
+
+ for (size_t i = 0; i < size; i++) {
+ String8 k, v;
+ k = mMap.keyAt(i);
+ v = mMap.valueAt(i);
+
+ flattened += k;
+ flattened += "=";
+ flattened += v;
+ if (i != size-1)
+ flattened += ";";
+ }
+
+ return flattened;
+}
+
+void CameraParameters::unflatten(const String8 &params)
+{
+ const char *a = params.string();
+ const char *b;
+
+ mMap.clear();
+
+ for (;;) {
+ // Find the bounds of the key name.
+ b = strchr(a, '=');
+ if (b == 0)
+ break;
+
+ // Create the key string.
+ String8 k(a, (size_t)(b-a));
+
+ // Find the value.
+ a = b+1;
+ b = strchr(a, ';');
+ if (b == 0) {
+ // If there's no semicolon, this is the last item.
+ String8 v(a);
+ mMap.add(k, v);
+ break;
+ }
+
+ String8 v(a, (size_t)(b-a));
+ mMap.add(k, v);
+ a = b+1;
+ }
+}
+
+
+void CameraParameters::set(const char *key, const char *value)
+{
+ // XXX i think i can do this with strspn()
+ if (strchr(key, '=') || strchr(key, ';')) {
+ //XXX ALOGE("Key \"%s\"contains invalid character (= or ;)", key);
+ return;
+ }
+
+ if (strchr(value, '=') || strchr(key, ';')) {
+ //XXX ALOGE("Value \"%s\"contains invalid character (= or ;)", value);
+ return;
+ }
+
+ mMap.replaceValueFor(String8(key), String8(value));
+}
+
+void CameraParameters::set(const char *key, int value)
+{
+ char str[16];
+ sprintf(str, "%d", value);
+ set(key, str);
+}
+
+void CameraParameters::setFloat(const char *key, float value)
+{
+ char str[16]; // 14 should be enough. We overestimate to be safe.
+ snprintf(str, sizeof(str), "%g", value);
+ set(key, str);
+}
+
+const char *CameraParameters::get(const char *key) const
+{
+ String8 v = mMap.valueFor(String8(key));
+ if (v.length() == 0)
+ return 0;
+ return v.string();
+}
+
+int CameraParameters::getInt(const char *key) const
+{
+ const char *v = get(key);
+ if (v == 0)
+ return -1;
+ return strtol(v, 0, 0);
+}
+
+float CameraParameters::getFloat(const char *key) const
+{
+ const char *v = get(key);
+ if (v == 0) return -1;
+ return strtof(v, 0);
+}
+
+void CameraParameters::remove(const char *key)
+{
+ mMap.removeItem(String8(key));
+}
+
+// Parse string like "640x480" or "10000,20000"
+static int parse_pair(const char *str, int *first, int *second, char delim,
+ char **endptr = NULL)
+{
+ // Find the first integer.
+ char *end;
+ int w = (int)strtol(str, &end, 10);
+ // If a delimeter does not immediately follow, give up.
+ if (*end != delim) {
+ ALOGE("Cannot find delimeter (%c) in str=%s", delim, str);
+ return -1;
+ }
+
+ // Find the second integer, immediately after the delimeter.
+ int h = (int)strtol(end+1, &end, 10);
+
+ *first = w;
+ *second = h;
+
+ if (endptr) {
+ *endptr = end;
+ }
+
+ return 0;
+}
+
+static void parseSizesList(const char *sizesStr, Vector<Size> &sizes)
+{
+ if (sizesStr == 0) {
+ return;
+ }
+
+ char *sizeStartPtr = (char *)sizesStr;
+
+ while (true) {
+ int width, height;
+ int success = parse_pair(sizeStartPtr, &width, &height, 'x',
+ &sizeStartPtr);
+ if (success == -1 || (*sizeStartPtr != ',' && *sizeStartPtr != '\0')) {
+ ALOGE("Picture sizes string \"%s\" contains invalid character.", sizesStr);
+ return;
+ }
+ sizes.push(Size(width, height));
+
+ if (*sizeStartPtr == '\0') {
+ return;
+ }
+ sizeStartPtr++;
+ }
+}
+
+void CameraParameters::setPreviewSize(int width, int height)
+{
+ char str[32];
+ sprintf(str, "%dx%d", width, height);
+ set(KEY_PREVIEW_SIZE, str);
+}
+
+void CameraParameters::getPreviewSize(int *width, int *height) const
+{
+ *width = *height = -1;
+ // Get the current string, if it doesn't exist, leave the -1x-1
+ const char *p = get(KEY_PREVIEW_SIZE);
+ if (p == 0) return;
+ parse_pair(p, width, height, 'x');
+}
+
+void CameraParameters::getPreferredPreviewSizeForVideo(int *width, int *height) const
+{
+ *width = *height = -1;
+ const char *p = get(KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO);
+ if (p == 0) return;
+ parse_pair(p, width, height, 'x');
+}
+
+void CameraParameters::getSupportedPreviewSizes(Vector<Size> &sizes) const
+{
+ const char *previewSizesStr = get(KEY_SUPPORTED_PREVIEW_SIZES);
+ parseSizesList(previewSizesStr, sizes);
+}
+
+void CameraParameters::setVideoSize(int width, int height)
+{
+ char str[32];
+ sprintf(str, "%dx%d", width, height);
+ set(KEY_VIDEO_SIZE, str);
+}
+
+void CameraParameters::getVideoSize(int *width, int *height) const
+{
+ *width = *height = -1;
+ const char *p = get(KEY_VIDEO_SIZE);
+ if (p == 0) return;
+ parse_pair(p, width, height, 'x');
+}
+
+void CameraParameters::getSupportedVideoSizes(Vector<Size> &sizes) const
+{
+ const char *videoSizesStr = get(KEY_SUPPORTED_VIDEO_SIZES);
+ parseSizesList(videoSizesStr, sizes);
+}
+
+void CameraParameters::setPreviewFrameRate(int fps)
+{
+ set(KEY_PREVIEW_FRAME_RATE, fps);
+}
+
+int CameraParameters::getPreviewFrameRate() const
+{
+ return getInt(KEY_PREVIEW_FRAME_RATE);
+}
+
+void CameraParameters::getPreviewFpsRange(int *min_fps, int *max_fps) const
+{
+ *min_fps = *max_fps = -1;
+ const char *p = get(KEY_PREVIEW_FPS_RANGE);
+ if (p == 0) return;
+ parse_pair(p, min_fps, max_fps, ',');
+}
+
+void CameraParameters::setPreviewFormat(const char *format)
+{
+ set(KEY_PREVIEW_FORMAT, format);
+}
+
+const char *CameraParameters::getPreviewFormat() const
+{
+ return get(KEY_PREVIEW_FORMAT);
+}
+
+void CameraParameters::setPictureSize(int width, int height)
+{
+ char str[32];
+ sprintf(str, "%dx%d", width, height);
+ set(KEY_PICTURE_SIZE, str);
+}
+
+void CameraParameters::getPictureSize(int *width, int *height) const
+{
+ *width = *height = -1;
+ // Get the current string, if it doesn't exist, leave the -1x-1
+ const char *p = get(KEY_PICTURE_SIZE);
+ if (p == 0) return;
+ parse_pair(p, width, height, 'x');
+}
+
+void CameraParameters::getSupportedPictureSizes(Vector<Size> &sizes) const
+{
+ const char *pictureSizesStr = get(KEY_SUPPORTED_PICTURE_SIZES);
+ parseSizesList(pictureSizesStr, sizes);
+}
+
+void CameraParameters::setPictureFormat(const char *format)
+{
+ set(KEY_PICTURE_FORMAT, format);
+}
+
+const char *CameraParameters::getPictureFormat() const
+{
+ return get(KEY_PICTURE_FORMAT);
+}
+
+void CameraParameters::dump() const
+{
+ ALOGD("dump: mMap.size = %d", mMap.size());
+ for (size_t i = 0; i < mMap.size(); i++) {
+ String8 k, v;
+ k = mMap.keyAt(i);
+ v = mMap.valueAt(i);
+ ALOGD("%s: %s\n", k.string(), v.string());
+ }
+}
+
+status_t CameraParameters::dump(int fd, const Vector<String16>& args) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ snprintf(buffer, 255, "CameraParameters::dump: mMap.size = %d\n", mMap.size());
+ result.append(buffer);
+ for (size_t i = 0; i < mMap.size(); i++) {
+ String8 k, v;
+ k = mMap.keyAt(i);
+ v = mMap.valueAt(i);
+ snprintf(buffer, 255, "\t%s: %s\n", k.string(), v.string());
+ result.append(buffer);
+ }
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp
new file mode 100644
index 0000000..8d8408c
--- /dev/null
+++ b/camera/ICamera.cpp
@@ -0,0 +1,420 @@
+/*
+**
+** 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.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ICamera"
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <camera/ICamera.h>
+#include <gui/ISurfaceTexture.h>
+#include <gui/Surface.h>
+
+namespace android {
+
+enum {
+ DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
+ SET_PREVIEW_DISPLAY,
+ SET_PREVIEW_TEXTURE,
+ SET_PREVIEW_CALLBACK_FLAG,
+ START_PREVIEW,
+ STOP_PREVIEW,
+ AUTO_FOCUS,
+ CANCEL_AUTO_FOCUS,
+ TAKE_PICTURE,
+ SET_PARAMETERS,
+ GET_PARAMETERS,
+ SEND_COMMAND,
+ CONNECT,
+ LOCK,
+ UNLOCK,
+ PREVIEW_ENABLED,
+ START_RECORDING,
+ STOP_RECORDING,
+ RECORDING_ENABLED,
+ RELEASE_RECORDING_FRAME,
+ STORE_META_DATA_IN_BUFFERS,
+};
+
+class BpCamera: public BpInterface<ICamera>
+{
+public:
+ BpCamera(const sp<IBinder>& impl)
+ : BpInterface<ICamera>(impl)
+ {
+ }
+
+ // disconnect from camera service
+ void disconnect()
+ {
+ ALOGV("disconnect");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ remote()->transact(DISCONNECT, data, &reply);
+ }
+
+ // pass the buffered Surface to the camera service
+ status_t setPreviewDisplay(const sp<Surface>& surface)
+ {
+ ALOGV("setPreviewDisplay");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ Surface::writeToParcel(surface, &data);
+ remote()->transact(SET_PREVIEW_DISPLAY, data, &reply);
+ return reply.readInt32();
+ }
+
+ // pass the buffered SurfaceTexture to the camera service
+ status_t setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture)
+ {
+ ALOGV("setPreviewTexture");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ sp<IBinder> b(surfaceTexture->asBinder());
+ data.writeStrongBinder(b);
+ remote()->transact(SET_PREVIEW_TEXTURE, data, &reply);
+ return reply.readInt32();
+ }
+
+ // set the preview callback flag to affect how the received frames from
+ // preview are handled. See Camera.h for details.
+ void setPreviewCallbackFlag(int flag)
+ {
+ ALOGV("setPreviewCallbackFlag(%d)", flag);
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ data.writeInt32(flag);
+ remote()->transact(SET_PREVIEW_CALLBACK_FLAG, data, &reply);
+ }
+
+ // start preview mode, must call setPreviewDisplay first
+ status_t startPreview()
+ {
+ ALOGV("startPreview");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ remote()->transact(START_PREVIEW, data, &reply);
+ return reply.readInt32();
+ }
+
+ // start recording mode, must call setPreviewDisplay first
+ status_t startRecording()
+ {
+ ALOGV("startRecording");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ remote()->transact(START_RECORDING, data, &reply);
+ return reply.readInt32();
+ }
+
+ // stop preview mode
+ void stopPreview()
+ {
+ ALOGV("stopPreview");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ remote()->transact(STOP_PREVIEW, data, &reply);
+ }
+
+ // stop recording mode
+ void stopRecording()
+ {
+ ALOGV("stopRecording");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ remote()->transact(STOP_RECORDING, data, &reply);
+ }
+
+ void releaseRecordingFrame(const sp<IMemory>& mem)
+ {
+ ALOGV("releaseRecordingFrame");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ data.writeStrongBinder(mem->asBinder());
+ remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
+ }
+
+ status_t storeMetaDataInBuffers(bool enabled)
+ {
+ ALOGV("storeMetaDataInBuffers: %s", enabled? "true": "false");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ data.writeInt32(enabled);
+ remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply);
+ return reply.readInt32();
+ }
+
+ // check preview state
+ bool previewEnabled()
+ {
+ ALOGV("previewEnabled");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ remote()->transact(PREVIEW_ENABLED, data, &reply);
+ return reply.readInt32();
+ }
+
+ // check recording state
+ bool recordingEnabled()
+ {
+ ALOGV("recordingEnabled");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ remote()->transact(RECORDING_ENABLED, data, &reply);
+ return reply.readInt32();
+ }
+
+ // auto focus
+ status_t autoFocus()
+ {
+ ALOGV("autoFocus");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ remote()->transact(AUTO_FOCUS, data, &reply);
+ status_t ret = reply.readInt32();
+ return ret;
+ }
+
+ // cancel focus
+ status_t cancelAutoFocus()
+ {
+ ALOGV("cancelAutoFocus");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ remote()->transact(CANCEL_AUTO_FOCUS, data, &reply);
+ status_t ret = reply.readInt32();
+ return ret;
+ }
+
+ // take a picture - returns an IMemory (ref-counted mmap)
+ status_t takePicture(int msgType)
+ {
+ ALOGV("takePicture: 0x%x", msgType);
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ data.writeInt32(msgType);
+ remote()->transact(TAKE_PICTURE, data, &reply);
+ status_t ret = reply.readInt32();
+ return ret;
+ }
+
+ // set preview/capture parameters - key/value pairs
+ status_t setParameters(const String8& params)
+ {
+ ALOGV("setParameters");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ data.writeString8(params);
+ remote()->transact(SET_PARAMETERS, data, &reply);
+ return reply.readInt32();
+ }
+
+ // get preview/capture parameters - key/value pairs
+ String8 getParameters() const
+ {
+ ALOGV("getParameters");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ remote()->transact(GET_PARAMETERS, data, &reply);
+ return reply.readString8();
+ }
+ virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
+ {
+ ALOGV("sendCommand");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ data.writeInt32(cmd);
+ data.writeInt32(arg1);
+ data.writeInt32(arg2);
+ remote()->transact(SEND_COMMAND, data, &reply);
+ return reply.readInt32();
+ }
+ virtual status_t connect(const sp<ICameraClient>& cameraClient)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ data.writeStrongBinder(cameraClient->asBinder());
+ remote()->transact(CONNECT, data, &reply);
+ return reply.readInt32();
+ }
+ virtual status_t lock()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ remote()->transact(LOCK, data, &reply);
+ return reply.readInt32();
+ }
+ virtual status_t unlock()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
+ remote()->transact(UNLOCK, data, &reply);
+ return reply.readInt32();
+ }
+};
+
+IMPLEMENT_META_INTERFACE(Camera, "android.hardware.ICamera");
+
+// ----------------------------------------------------------------------
+
+status_t BnCamera::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case DISCONNECT: {
+ ALOGV("DISCONNECT");
+ CHECK_INTERFACE(ICamera, data, reply);
+ disconnect();
+ return NO_ERROR;
+ } break;
+ case SET_PREVIEW_DISPLAY: {
+ ALOGV("SET_PREVIEW_DISPLAY");
+ CHECK_INTERFACE(ICamera, data, reply);
+ sp<Surface> surface = Surface::readFromParcel(data);
+ reply->writeInt32(setPreviewDisplay(surface));
+ return NO_ERROR;
+ } break;
+ case SET_PREVIEW_TEXTURE: {
+ ALOGV("SET_PREVIEW_TEXTURE");
+ CHECK_INTERFACE(ICamera, data, reply);
+ sp<ISurfaceTexture> st = interface_cast<ISurfaceTexture>(data.readStrongBinder());
+ reply->writeInt32(setPreviewTexture(st));
+ return NO_ERROR;
+ } break;
+ case SET_PREVIEW_CALLBACK_FLAG: {
+ ALOGV("SET_PREVIEW_CALLBACK_TYPE");
+ CHECK_INTERFACE(ICamera, data, reply);
+ int callback_flag = data.readInt32();
+ setPreviewCallbackFlag(callback_flag);
+ return NO_ERROR;
+ } break;
+ case START_PREVIEW: {
+ ALOGV("START_PREVIEW");
+ CHECK_INTERFACE(ICamera, data, reply);
+ reply->writeInt32(startPreview());
+ return NO_ERROR;
+ } break;
+ case START_RECORDING: {
+ ALOGV("START_RECORDING");
+ CHECK_INTERFACE(ICamera, data, reply);
+ reply->writeInt32(startRecording());
+ return NO_ERROR;
+ } break;
+ case STOP_PREVIEW: {
+ ALOGV("STOP_PREVIEW");
+ CHECK_INTERFACE(ICamera, data, reply);
+ stopPreview();
+ return NO_ERROR;
+ } break;
+ case STOP_RECORDING: {
+ ALOGV("STOP_RECORDING");
+ CHECK_INTERFACE(ICamera, data, reply);
+ stopRecording();
+ return NO_ERROR;
+ } break;
+ case RELEASE_RECORDING_FRAME: {
+ ALOGV("RELEASE_RECORDING_FRAME");
+ CHECK_INTERFACE(ICamera, data, reply);
+ sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder());
+ releaseRecordingFrame(mem);
+ return NO_ERROR;
+ } break;
+ case STORE_META_DATA_IN_BUFFERS: {
+ ALOGV("STORE_META_DATA_IN_BUFFERS");
+ CHECK_INTERFACE(ICamera, data, reply);
+ bool enabled = data.readInt32();
+ reply->writeInt32(storeMetaDataInBuffers(enabled));
+ return NO_ERROR;
+ } break;
+ case PREVIEW_ENABLED: {
+ ALOGV("PREVIEW_ENABLED");
+ CHECK_INTERFACE(ICamera, data, reply);
+ reply->writeInt32(previewEnabled());
+ return NO_ERROR;
+ } break;
+ case RECORDING_ENABLED: {
+ ALOGV("RECORDING_ENABLED");
+ CHECK_INTERFACE(ICamera, data, reply);
+ reply->writeInt32(recordingEnabled());
+ return NO_ERROR;
+ } break;
+ case AUTO_FOCUS: {
+ ALOGV("AUTO_FOCUS");
+ CHECK_INTERFACE(ICamera, data, reply);
+ reply->writeInt32(autoFocus());
+ return NO_ERROR;
+ } break;
+ case CANCEL_AUTO_FOCUS: {
+ ALOGV("CANCEL_AUTO_FOCUS");
+ CHECK_INTERFACE(ICamera, data, reply);
+ reply->writeInt32(cancelAutoFocus());
+ return NO_ERROR;
+ } break;
+ case TAKE_PICTURE: {
+ ALOGV("TAKE_PICTURE");
+ CHECK_INTERFACE(ICamera, data, reply);
+ int msgType = data.readInt32();
+ reply->writeInt32(takePicture(msgType));
+ return NO_ERROR;
+ } break;
+ case SET_PARAMETERS: {
+ ALOGV("SET_PARAMETERS");
+ CHECK_INTERFACE(ICamera, data, reply);
+ String8 params(data.readString8());
+ reply->writeInt32(setParameters(params));
+ return NO_ERROR;
+ } break;
+ case GET_PARAMETERS: {
+ ALOGV("GET_PARAMETERS");
+ CHECK_INTERFACE(ICamera, data, reply);
+ reply->writeString8(getParameters());
+ return NO_ERROR;
+ } break;
+ case SEND_COMMAND: {
+ ALOGV("SEND_COMMAND");
+ CHECK_INTERFACE(ICamera, data, reply);
+ int command = data.readInt32();
+ int arg1 = data.readInt32();
+ int arg2 = data.readInt32();
+ reply->writeInt32(sendCommand(command, arg1, arg2));
+ return NO_ERROR;
+ } break;
+ case CONNECT: {
+ CHECK_INTERFACE(ICamera, data, reply);
+ sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());
+ reply->writeInt32(connect(cameraClient));
+ return NO_ERROR;
+ } break;
+ case LOCK: {
+ CHECK_INTERFACE(ICamera, data, reply);
+ reply->writeInt32(lock());
+ return NO_ERROR;
+ } break;
+ case UNLOCK: {
+ CHECK_INTERFACE(ICamera, data, reply);
+ reply->writeInt32(unlock());
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
new file mode 100644
index 0000000..205c8ba
--- /dev/null
+++ b/camera/ICameraClient.cpp
@@ -0,0 +1,132 @@
+/*
+**
+** 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.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ICameraClient"
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <camera/ICameraClient.h>
+
+namespace android {
+
+enum {
+ NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
+ DATA_CALLBACK,
+ DATA_CALLBACK_TIMESTAMP,
+};
+
+class BpCameraClient: public BpInterface<ICameraClient>
+{
+public:
+ BpCameraClient(const sp<IBinder>& impl)
+ : BpInterface<ICameraClient>(impl)
+ {
+ }
+
+ // generic callback from camera service to app
+ void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
+ {
+ ALOGV("notifyCallback");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+ data.writeInt32(msgType);
+ data.writeInt32(ext1);
+ data.writeInt32(ext2);
+ remote()->transact(NOTIFY_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+
+ // generic data callback from camera service to app with image data
+ void dataCallback(int32_t msgType, const sp<IMemory>& imageData,
+ camera_frame_metadata_t *metadata)
+ {
+ ALOGV("dataCallback");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+ data.writeInt32(msgType);
+ data.writeStrongBinder(imageData->asBinder());
+ if (metadata) {
+ data.writeInt32(metadata->number_of_faces);
+ data.write(metadata->faces, sizeof(camera_face_t) * metadata->number_of_faces);
+ }
+ remote()->transact(DATA_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+
+ // generic data callback from camera service to app with image data
+ void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& imageData)
+ {
+ ALOGV("dataCallback");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+ data.writeInt64(timestamp);
+ data.writeInt32(msgType);
+ data.writeStrongBinder(imageData->asBinder());
+ remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(CameraClient, "android.hardware.ICameraClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnCameraClient::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case NOTIFY_CALLBACK: {
+ ALOGV("NOTIFY_CALLBACK");
+ CHECK_INTERFACE(ICameraClient, data, reply);
+ int32_t msgType = data.readInt32();
+ int32_t ext1 = data.readInt32();
+ int32_t ext2 = data.readInt32();
+ notifyCallback(msgType, ext1, ext2);
+ return NO_ERROR;
+ } break;
+ case DATA_CALLBACK: {
+ ALOGV("DATA_CALLBACK");
+ CHECK_INTERFACE(ICameraClient, data, reply);
+ int32_t msgType = data.readInt32();
+ sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+ camera_frame_metadata_t *metadata = NULL;
+ if (data.dataAvail() > 0) {
+ metadata = new camera_frame_metadata_t;
+ metadata->number_of_faces = data.readInt32();
+ metadata->faces = (camera_face_t *) data.readInplace(
+ sizeof(camera_face_t) * metadata->number_of_faces);
+ }
+ dataCallback(msgType, imageData, metadata);
+ if (metadata) delete metadata;
+ return NO_ERROR;
+ } break;
+ case DATA_CALLBACK_TIMESTAMP: {
+ ALOGV("DATA_CALLBACK_TIMESTAMP");
+ CHECK_INTERFACE(ICameraClient, data, reply);
+ nsecs_t timestamp = data.readInt64();
+ int32_t msgType = data.readInt32();
+ sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+ dataCallbackTimestamp(timestamp, msgType, imageData);
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/camera/ICameraRecordingProxy.cpp b/camera/ICameraRecordingProxy.cpp
new file mode 100644
index 0000000..7223b6d
--- /dev/null
+++ b/camera/ICameraRecordingProxy.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ICameraRecordingProxy"
+#include <camera/ICameraRecordingProxy.h>
+#include <camera/ICameraRecordingProxyListener.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <stdint.h>
+#include <utils/Log.h>
+
+namespace android {
+
+enum {
+ START_RECORDING = IBinder::FIRST_CALL_TRANSACTION,
+ STOP_RECORDING,
+ RELEASE_RECORDING_FRAME,
+};
+
+
+class BpCameraRecordingProxy: public BpInterface<ICameraRecordingProxy>
+{
+public:
+ BpCameraRecordingProxy(const sp<IBinder>& impl)
+ : BpInterface<ICameraRecordingProxy>(impl)
+ {
+ }
+
+ status_t startRecording(const sp<ICameraRecordingProxyListener>& listener)
+ {
+ ALOGV("startRecording");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+ data.writeStrongBinder(listener->asBinder());
+ remote()->transact(START_RECORDING, data, &reply);
+ return reply.readInt32();
+ }
+
+ void stopRecording()
+ {
+ ALOGV("stopRecording");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+ remote()->transact(STOP_RECORDING, data, &reply);
+ }
+
+ void releaseRecordingFrame(const sp<IMemory>& mem)
+ {
+ ALOGV("releaseRecordingFrame");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxy::getInterfaceDescriptor());
+ data.writeStrongBinder(mem->asBinder());
+ remote()->transact(RELEASE_RECORDING_FRAME, data, &reply);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(CameraRecordingProxy, "android.hardware.ICameraRecordingProxy");
+
+// ----------------------------------------------------------------------
+
+status_t BnCameraRecordingProxy::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case START_RECORDING: {
+ ALOGV("START_RECORDING");
+ CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+ sp<ICameraRecordingProxyListener> listener =
+ interface_cast<ICameraRecordingProxyListener>(data.readStrongBinder());
+ reply->writeInt32(startRecording(listener));
+ return NO_ERROR;
+ } break;
+ case STOP_RECORDING: {
+ ALOGV("STOP_RECORDING");
+ CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+ stopRecording();
+ return NO_ERROR;
+ } break;
+ case RELEASE_RECORDING_FRAME: {
+ ALOGV("RELEASE_RECORDING_FRAME");
+ CHECK_INTERFACE(ICameraRecordingProxy, data, reply);
+ sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder());
+ releaseRecordingFrame(mem);
+ return NO_ERROR;
+ } break;
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/camera/ICameraRecordingProxyListener.cpp b/camera/ICameraRecordingProxyListener.cpp
new file mode 100644
index 0000000..cb17f19
--- /dev/null
+++ b/camera/ICameraRecordingProxyListener.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ICameraRecordingProxyListener"
+#include <camera/ICameraRecordingProxyListener.h>
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <utils/Log.h>
+
+namespace android {
+
+enum {
+ DATA_CALLBACK_TIMESTAMP = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpCameraRecordingProxyListener: public BpInterface<ICameraRecordingProxyListener>
+{
+public:
+ BpCameraRecordingProxyListener(const sp<IBinder>& impl)
+ : BpInterface<ICameraRecordingProxyListener>(impl)
+ {
+ }
+
+ void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& imageData)
+ {
+ ALOGV("dataCallback");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraRecordingProxyListener::getInterfaceDescriptor());
+ data.writeInt64(timestamp);
+ data.writeInt32(msgType);
+ data.writeStrongBinder(imageData->asBinder());
+ remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(CameraRecordingProxyListener, "android.hardware.ICameraRecordingProxyListener");
+
+// ----------------------------------------------------------------------
+
+status_t BnCameraRecordingProxyListener::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case DATA_CALLBACK_TIMESTAMP: {
+ ALOGV("DATA_CALLBACK_TIMESTAMP");
+ CHECK_INTERFACE(ICameraRecordingProxyListener, data, reply);
+ nsecs_t timestamp = data.readInt64();
+ int32_t msgType = data.readInt32();
+ sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+ dataCallbackTimestamp(timestamp, msgType, imageData);
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
new file mode 100644
index 0000000..c74298a
--- /dev/null
+++ b/camera/ICameraService.cpp
@@ -0,0 +1,113 @@
+/*
+**
+** 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 <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <camera/ICameraService.h>
+
+namespace android {
+
+class BpCameraService: public BpInterface<ICameraService>
+{
+public:
+ BpCameraService(const sp<IBinder>& impl)
+ : BpInterface<ICameraService>(impl)
+ {
+ }
+
+ // get number of cameras available
+ virtual int32_t getNumberOfCameras()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
+ remote()->transact(BnCameraService::GET_NUMBER_OF_CAMERAS, data, &reply);
+ return reply.readInt32();
+ }
+
+ // get information about a camera
+ virtual status_t getCameraInfo(int cameraId,
+ struct CameraInfo* cameraInfo) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
+ data.writeInt32(cameraId);
+ remote()->transact(BnCameraService::GET_CAMERA_INFO, data, &reply);
+ cameraInfo->facing = reply.readInt32();
+ cameraInfo->orientation = reply.readInt32();
+ return reply.readInt32();
+ }
+
+ // connect to camera service
+ virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId,
+ bool force, bool keep)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
+ data.writeStrongBinder(cameraClient->asBinder());
+ data.writeInt32(cameraId);
+ data.writeInt32(force);
+ data.writeInt32(keep);
+ remote()->transact(BnCameraService::CONNECT, data, &reply);
+ return interface_cast<ICamera>(reply.readStrongBinder());
+ }
+};
+
+IMPLEMENT_META_INTERFACE(CameraService, "android.hardware.ICameraService");
+
+// ----------------------------------------------------------------------
+
+status_t BnCameraService::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case GET_NUMBER_OF_CAMERAS: {
+ CHECK_INTERFACE(ICameraService, data, reply);
+ reply->writeInt32(getNumberOfCameras());
+ return NO_ERROR;
+ } break;
+ case GET_CAMERA_INFO: {
+ CHECK_INTERFACE(ICameraService, data, reply);
+ CameraInfo cameraInfo;
+ memset(&cameraInfo, 0, sizeof(cameraInfo));
+ status_t result = getCameraInfo(data.readInt32(), &cameraInfo);
+ reply->writeInt32(cameraInfo.facing);
+ reply->writeInt32(cameraInfo.orientation);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ } break;
+ case CONNECT: {
+ CHECK_INTERFACE(ICameraService, data, reply);
+ sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());
+ const int cameraId = data.readInt32();
+ const int force = data.readInt32();
+ const int keep = data.readInt32();
+ sp<ICamera> camera = connect(cameraClient, cameraId, force, keep);
+ reply->writeStrongBinder(camera->asBinder());
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
new file mode 100644
index 0000000..52a9293
--- /dev/null
+++ b/cmds/stagefright/Android.mk
@@ -0,0 +1,167 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ stagefright.cpp \
+ jpeg.cpp \
+ SineSource.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright libmedia libmedia_native libutils libbinder libstagefright_foundation \
+ libjpeg libgui
+
+LOCAL_C_INCLUDES:= \
+ frameworks/base/media/libstagefright \
+ frameworks/base/media/libstagefright/include \
+ $(TOP)/frameworks/native/include/media/openmax \
+ external/jpeg \
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_MODULE:= stagefright
+
+include $(BUILD_EXECUTABLE)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ SineSource.cpp \
+ record.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright liblog libutils libbinder libstagefright_foundation
+
+LOCAL_C_INCLUDES:= \
+ frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_MODULE:= record
+
+include $(BUILD_EXECUTABLE)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ SineSource.cpp \
+ recordvideo.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright liblog libutils libbinder libstagefright_foundation
+
+LOCAL_C_INCLUDES:= \
+ frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_MODULE:= recordvideo
+
+include $(BUILD_EXECUTABLE)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ SineSource.cpp \
+ audioloop.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright liblog libutils libbinder libstagefright_foundation
+
+LOCAL_C_INCLUDES:= \
+ frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_MODULE:= audioloop
+
+include $(BUILD_EXECUTABLE)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ stream.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright liblog libutils libbinder libgui \
+ libstagefright_foundation libmedia libmedia_native
+
+LOCAL_C_INCLUDES:= \
+ frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_MODULE:= stream
+
+include $(BUILD_EXECUTABLE)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ sf2.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright liblog libutils libbinder libstagefright_foundation \
+ libmedia libmedia_native libgui libcutils libui
+
+LOCAL_C_INCLUDES:= \
+ frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_MODULE:= sf2
+
+include $(BUILD_EXECUTABLE)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ codec.cpp \
+ SimplePlayer.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright liblog libutils libbinder libstagefright_foundation \
+ libmedia libmedia_native libgui libcutils libui
+
+LOCAL_C_INCLUDES:= \
+ frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_MODULE:= codec
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
new file mode 100644
index 0000000..0cfeb3e
--- /dev/null
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -0,0 +1,645 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SimplePlayer"
+#include <utils/Log.h>
+
+#include "SimplePlayer.h"
+
+#include <gui/SurfaceTextureClient.h>
+#include <media/AudioTrack.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaCodec.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/NativeWindowWrapper.h>
+#include <media/stagefright/NuMediaExtractor.h>
+
+namespace android {
+
+SimplePlayer::SimplePlayer()
+ : mState(UNINITIALIZED),
+ mDoMoreStuffGeneration(0),
+ mStartTimeRealUs(-1ll) {
+}
+
+SimplePlayer::~SimplePlayer() {
+}
+
+// static
+status_t PostAndAwaitResponse(
+ const sp<AMessage> &msg, sp<AMessage> *response) {
+ status_t err = msg->postAndAwaitResponse(response);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (!(*response)->findInt32("err", &err)) {
+ err = OK;
+ }
+
+ return err;
+}
+status_t SimplePlayer::setDataSource(const char *path) {
+ sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
+ msg->setString("path", path);
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t SimplePlayer::setSurface(const sp<ISurfaceTexture> &surfaceTexture) {
+ sp<AMessage> msg = new AMessage(kWhatSetSurface, id());
+
+ sp<SurfaceTextureClient> surfaceTextureClient;
+ if (surfaceTexture != NULL) {
+ surfaceTextureClient = new SurfaceTextureClient(surfaceTexture);
+ }
+
+ msg->setObject(
+ "native-window", new NativeWindowWrapper(surfaceTextureClient));
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t SimplePlayer::prepare() {
+ sp<AMessage> msg = new AMessage(kWhatPrepare, id());
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t SimplePlayer::start() {
+ sp<AMessage> msg = new AMessage(kWhatStart, id());
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t SimplePlayer::stop() {
+ sp<AMessage> msg = new AMessage(kWhatStop, id());
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t SimplePlayer::reset() {
+ sp<AMessage> msg = new AMessage(kWhatReset, id());
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+void SimplePlayer::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatSetDataSource:
+ {
+ status_t err;
+ if (mState != UNINITIALIZED) {
+ err = INVALID_OPERATION;
+ } else {
+ CHECK(msg->findString("path", &mPath));
+ mState = UNPREPARED;
+ }
+
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", err);
+ response->postReply(replyID);
+ break;
+ }
+
+ case kWhatSetSurface:
+ {
+ status_t err;
+ if (mState != UNPREPARED) {
+ err = INVALID_OPERATION;
+ } else {
+ sp<RefBase> obj;
+ CHECK(msg->findObject("native-window", &obj));
+
+ mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get());
+
+ err = OK;
+ }
+
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", err);
+ response->postReply(replyID);
+ break;
+ }
+
+ case kWhatPrepare:
+ {
+ status_t err;
+ if (mState != UNPREPARED) {
+ err = INVALID_OPERATION;
+ } else {
+ err = onPrepare();
+
+ if (err == OK) {
+ mState = STOPPED;
+ }
+ }
+
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", err);
+ response->postReply(replyID);
+ break;
+ }
+
+ case kWhatStart:
+ {
+ status_t err = OK;
+
+ if (mState == UNPREPARED) {
+ err = onPrepare();
+
+ if (err == OK) {
+ mState = STOPPED;
+ }
+ }
+
+ if (err == OK) {
+ if (mState != STOPPED) {
+ err = INVALID_OPERATION;
+ } else {
+ err = onStart();
+
+ if (err == OK) {
+ mState = STARTED;
+ }
+ }
+ }
+
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", err);
+ response->postReply(replyID);
+ break;
+ }
+
+ case kWhatStop:
+ {
+ status_t err;
+
+ if (mState != STARTED) {
+ err = INVALID_OPERATION;
+ } else {
+ err = onStop();
+
+ if (err == OK) {
+ mState = STOPPED;
+ }
+ }
+
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", err);
+ response->postReply(replyID);
+ break;
+ }
+
+ case kWhatReset:
+ {
+ status_t err = OK;
+
+ if (mState == STARTED) {
+ CHECK_EQ(onStop(), (status_t)OK);
+ mState = STOPPED;
+ }
+
+ if (mState == STOPPED) {
+ err = onReset();
+ mState = UNINITIALIZED;
+ }
+
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", err);
+ response->postReply(replyID);
+ break;
+ }
+
+ case kWhatDoMoreStuff:
+ {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+
+ if (generation != mDoMoreStuffGeneration) {
+ break;
+ }
+
+ status_t err = onDoMoreStuff();
+
+ if (err == OK) {
+ msg->post(10000ll);
+ }
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+}
+
+status_t SimplePlayer::onPrepare() {
+ CHECK_EQ(mState, UNPREPARED);
+
+ mExtractor = new NuMediaExtractor;
+
+ status_t err = mExtractor->setDataSource(mPath.c_str());
+
+ if (err != OK) {
+ mExtractor.clear();
+ return err;
+ }
+
+ if (mCodecLooper == NULL) {
+ mCodecLooper = new ALooper;
+ mCodecLooper->start();
+ }
+
+ bool haveAudio = false;
+ bool haveVideo = false;
+ for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
+ sp<AMessage> format;
+ status_t err = mExtractor->getTrackFormat(i, &format);
+ CHECK_EQ(err, (status_t)OK);
+
+ AString mime;
+ CHECK(format->findString("mime", &mime));
+
+ if (!haveAudio && !strncasecmp(mime.c_str(), "audio/", 6)) {
+ haveAudio = true;
+ } else if (!haveVideo && !strncasecmp(mime.c_str(), "video/", 6)) {
+ haveVideo = true;
+ } else {
+ continue;
+ }
+
+ err = mExtractor->selectTrack(i);
+ CHECK_EQ(err, (status_t)OK);
+
+ CodecState *state =
+ &mStateByTrackIndex.editValueAt(
+ mStateByTrackIndex.add(i, CodecState()));
+
+ state->mNumFramesWritten = 0;
+ state->mCodec = MediaCodec::CreateByType(
+ mCodecLooper, mime.c_str(), false /* encoder */);
+
+ CHECK(state->mCodec != NULL);
+
+ err = state->mCodec->configure(
+ format, mNativeWindow->getSurfaceTextureClient(),
+ 0 /* flags */);
+
+ CHECK_EQ(err, (status_t)OK);
+
+ size_t j = 0;
+ sp<ABuffer> buffer;
+ while (format->findBuffer(StringPrintf("csd-%d", j).c_str(), &buffer)) {
+ state->mCSD.push_back(buffer);
+
+ ++j;
+ }
+ }
+
+ for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
+ CodecState *state = &mStateByTrackIndex.editValueAt(i);
+
+ status_t err = state->mCodec->start();
+ CHECK_EQ(err, (status_t)OK);
+
+ err = state->mCodec->getInputBuffers(&state->mBuffers[0]);
+ CHECK_EQ(err, (status_t)OK);
+
+ err = state->mCodec->getOutputBuffers(&state->mBuffers[1]);
+ CHECK_EQ(err, (status_t)OK);
+
+ for (size_t j = 0; j < state->mCSD.size(); ++j) {
+ const sp<ABuffer> &srcBuffer = state->mCSD.itemAt(j);
+
+ size_t index;
+ err = state->mCodec->dequeueInputBuffer(&index, -1ll);
+ CHECK_EQ(err, (status_t)OK);
+
+ const sp<ABuffer> &dstBuffer = state->mBuffers[0].itemAt(index);
+
+ CHECK_LE(srcBuffer->size(), dstBuffer->capacity());
+ dstBuffer->setRange(0, srcBuffer->size());
+ memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size());
+
+ err = state->mCodec->queueInputBuffer(
+ index,
+ 0,
+ dstBuffer->size(),
+ 0ll,
+ MediaCodec::BUFFER_FLAG_CODECCONFIG);
+ CHECK_EQ(err, (status_t)OK);
+ }
+ }
+
+ return OK;
+}
+
+status_t SimplePlayer::onStart() {
+ CHECK_EQ(mState, STOPPED);
+
+ mStartTimeRealUs = -1ll;
+
+ sp<AMessage> msg = new AMessage(kWhatDoMoreStuff, id());
+ msg->setInt32("generation", ++mDoMoreStuffGeneration);
+ msg->post();
+
+ return OK;
+}
+
+status_t SimplePlayer::onStop() {
+ CHECK_EQ(mState, STARTED);
+
+ ++mDoMoreStuffGeneration;
+
+ return OK;
+}
+
+status_t SimplePlayer::onReset() {
+ CHECK_EQ(mState, STOPPED);
+
+ for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
+ CodecState *state = &mStateByTrackIndex.editValueAt(i);
+
+ CHECK_EQ(state->mCodec->release(), (status_t)OK);
+ }
+
+ mStartTimeRealUs = -1ll;
+
+ mStateByTrackIndex.clear();
+ mCodecLooper.clear();
+ mExtractor.clear();
+ mNativeWindow.clear();
+ mPath.clear();
+
+ return OK;
+}
+
+status_t SimplePlayer::onDoMoreStuff() {
+ ALOGV("onDoMoreStuff");
+ for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
+ CodecState *state = &mStateByTrackIndex.editValueAt(i);
+
+ status_t err;
+ do {
+ size_t index;
+ err = state->mCodec->dequeueInputBuffer(&index);
+
+ if (err == OK) {
+ ALOGV("dequeued input buffer on track %d",
+ mStateByTrackIndex.keyAt(i));
+
+ state->mAvailInputBufferIndices.push_back(index);
+ } else {
+ ALOGV("dequeueInputBuffer on track %d returned %d",
+ mStateByTrackIndex.keyAt(i), err);
+ }
+ } while (err == OK);
+
+ do {
+ BufferInfo info;
+ err = state->mCodec->dequeueOutputBuffer(
+ &info.mIndex,
+ &info.mOffset,
+ &info.mSize,
+ &info.mPresentationTimeUs,
+ &info.mFlags);
+
+ if (err == OK) {
+ ALOGV("dequeued output buffer on track %d",
+ mStateByTrackIndex.keyAt(i));
+
+ state->mAvailOutputBufferInfos.push_back(info);
+ } else if (err == INFO_FORMAT_CHANGED) {
+ err = onOutputFormatChanged(mStateByTrackIndex.keyAt(i), state);
+ CHECK_EQ(err, (status_t)OK);
+ } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
+ err = state->mCodec->getOutputBuffers(&state->mBuffers[1]);
+ CHECK_EQ(err, (status_t)OK);
+ } else {
+ ALOGV("dequeueOutputBuffer on track %d returned %d",
+ mStateByTrackIndex.keyAt(i), err);
+ }
+ } while (err == OK
+ || err == INFO_FORMAT_CHANGED
+ || err == INFO_OUTPUT_BUFFERS_CHANGED);
+ }
+
+ for (;;) {
+ size_t trackIndex;
+ status_t err = mExtractor->getSampleTrackIndex(&trackIndex);
+
+ if (err != OK) {
+ ALOGI("encountered input EOS.");
+ break;
+ } else {
+ CodecState *state = &mStateByTrackIndex.editValueFor(trackIndex);
+
+ if (state->mAvailInputBufferIndices.empty()) {
+ break;
+ }
+
+ size_t index = *state->mAvailInputBufferIndices.begin();
+ state->mAvailInputBufferIndices.erase(
+ state->mAvailInputBufferIndices.begin());
+
+ const sp<ABuffer> &dstBuffer =
+ state->mBuffers[0].itemAt(index);
+
+ err = mExtractor->readSampleData(dstBuffer);
+ CHECK_EQ(err, (status_t)OK);
+
+ int64_t timeUs;
+ CHECK_EQ(mExtractor->getSampleTime(&timeUs), (status_t)OK);
+
+ err = state->mCodec->queueInputBuffer(
+ index,
+ dstBuffer->offset(),
+ dstBuffer->size(),
+ timeUs,
+ 0);
+ CHECK_EQ(err, (status_t)OK);
+
+ ALOGV("enqueued input data on track %d", trackIndex);
+
+ err = mExtractor->advance();
+ CHECK_EQ(err, (status_t)OK);
+ }
+ }
+
+ int64_t nowUs = ALooper::GetNowUs();
+
+ if (mStartTimeRealUs < 0ll) {
+ mStartTimeRealUs = nowUs + 1000000ll;
+ }
+
+ for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
+ CodecState *state = &mStateByTrackIndex.editValueAt(i);
+
+ while (!state->mAvailOutputBufferInfos.empty()) {
+ BufferInfo *info = &*state->mAvailOutputBufferInfos.begin();
+
+ int64_t whenRealUs = info->mPresentationTimeUs + mStartTimeRealUs;
+ int64_t lateByUs = nowUs - whenRealUs;
+
+ if (lateByUs > -10000ll) {
+ bool release = true;
+
+ if (lateByUs > 30000ll) {
+ ALOGI("track %d buffer late by %lld us, dropping.",
+ mStateByTrackIndex.keyAt(i), lateByUs);
+ state->mCodec->releaseOutputBuffer(info->mIndex);
+ } else {
+ if (state->mAudioTrack != NULL) {
+ const sp<ABuffer> &srcBuffer =
+ state->mBuffers[1].itemAt(info->mIndex);
+
+ renderAudio(state, info, srcBuffer);
+
+ if (info->mSize > 0) {
+ release = false;
+ }
+ }
+
+ if (release) {
+ state->mCodec->renderOutputBufferAndRelease(
+ info->mIndex);
+ }
+ }
+
+ if (release) {
+ state->mAvailOutputBufferInfos.erase(
+ state->mAvailOutputBufferInfos.begin());
+
+ info = NULL;
+ } else {
+ break;
+ }
+ } else {
+ ALOGV("track %d buffer early by %lld us.",
+ mStateByTrackIndex.keyAt(i), -lateByUs);
+ break;
+ }
+ }
+ }
+
+ return OK;
+}
+
+status_t SimplePlayer::onOutputFormatChanged(
+ size_t trackIndex, CodecState *state) {
+ sp<AMessage> format;
+ status_t err = state->mCodec->getOutputFormat(&format);
+
+ if (err != OK) {
+ return err;
+ }
+
+ AString mime;
+ CHECK(format->findString("mime", &mime));
+
+ if (!strncasecmp(mime.c_str(), "audio/", 6)) {
+ int32_t channelCount;
+ int32_t sampleRate;
+ CHECK(format->findInt32("channel-count", &channelCount));
+ CHECK(format->findInt32("sample-rate", &sampleRate));
+
+ state->mAudioTrack = new AudioTrack(
+ AUDIO_STREAM_MUSIC,
+ sampleRate,
+ AUDIO_FORMAT_PCM_16_BIT,
+ audio_channel_out_mask_from_count(channelCount),
+ 0);
+
+ state->mNumFramesWritten = 0;
+ }
+
+ return OK;
+}
+
+void SimplePlayer::renderAudio(
+ CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer) {
+ CHECK(state->mAudioTrack != NULL);
+
+ if (state->mAudioTrack->stopped()) {
+ state->mAudioTrack->start();
+ }
+
+ uint32_t numFramesPlayed;
+ CHECK_EQ(state->mAudioTrack->getPosition(&numFramesPlayed), (status_t)OK);
+
+ uint32_t numFramesAvailableToWrite =
+ state->mAudioTrack->frameCount()
+ - (state->mNumFramesWritten - numFramesPlayed);
+
+ size_t numBytesAvailableToWrite =
+ numFramesAvailableToWrite * state->mAudioTrack->frameSize();
+
+ size_t copy = info->mSize;
+ if (copy > numBytesAvailableToWrite) {
+ copy = numBytesAvailableToWrite;
+ }
+
+ if (copy == 0) {
+ return;
+ }
+
+ int64_t startTimeUs = ALooper::GetNowUs();
+
+ ssize_t nbytes = state->mAudioTrack->write(
+ buffer->base() + info->mOffset, copy);
+
+ CHECK_EQ(nbytes, (ssize_t)copy);
+
+ int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
+
+ uint32_t numFramesWritten = nbytes / state->mAudioTrack->frameSize();
+
+ if (delayUs > 2000ll) {
+ ALOGW("AudioTrack::write took %lld us, numFramesAvailableToWrite=%u, "
+ "numFramesWritten=%u",
+ delayUs, numFramesAvailableToWrite, numFramesWritten);
+ }
+
+ info->mOffset += nbytes;
+ info->mSize -= nbytes;
+
+ state->mNumFramesWritten += numFramesWritten;
+}
+
+} // namespace android
diff --git a/cmds/stagefright/SimplePlayer.h b/cmds/stagefright/SimplePlayer.h
new file mode 100644
index 0000000..2548252
--- /dev/null
+++ b/cmds/stagefright/SimplePlayer.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/AString.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+struct ABuffer;
+struct ALooper;
+struct AudioTrack;
+struct ISurfaceTexture;
+struct MediaCodec;
+struct NativeWindowWrapper;
+struct NuMediaExtractor;
+
+struct SimplePlayer : public AHandler {
+ SimplePlayer();
+
+ status_t setDataSource(const char *path);
+ status_t setSurface(const sp<ISurfaceTexture> &surfaceTexture);
+ status_t prepare();
+ status_t start();
+ status_t stop();
+ status_t reset();
+
+protected:
+ virtual ~SimplePlayer();
+
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+ enum State {
+ UNINITIALIZED,
+ UNPREPARED,
+ STOPPED,
+ STARTED
+ };
+
+ enum {
+ kWhatSetDataSource,
+ kWhatSetSurface,
+ kWhatPrepare,
+ kWhatStart,
+ kWhatStop,
+ kWhatReset,
+ kWhatDoMoreStuff,
+ };
+
+ struct BufferInfo {
+ size_t mIndex;
+ size_t mOffset;
+ size_t mSize;
+ int64_t mPresentationTimeUs;
+ uint32_t mFlags;
+ };
+
+ struct CodecState
+ {
+ sp<MediaCodec> mCodec;
+ Vector<sp<ABuffer> > mCSD;
+ Vector<sp<ABuffer> > mBuffers[2];
+
+ List<size_t> mAvailInputBufferIndices;
+ List<BufferInfo> mAvailOutputBufferInfos;
+
+ sp<AudioTrack> mAudioTrack;
+ uint32_t mNumFramesWritten;
+ };
+
+ State mState;
+ AString mPath;
+ sp<NativeWindowWrapper> mNativeWindow;
+
+ sp<NuMediaExtractor> mExtractor;
+ sp<ALooper> mCodecLooper;
+ KeyedVector<size_t, CodecState> mStateByTrackIndex;
+ int32_t mDoMoreStuffGeneration;
+
+ int64_t mStartTimeRealUs;
+
+ status_t onPrepare();
+ status_t onStart();
+ status_t onStop();
+ status_t onReset();
+ status_t onDoMoreStuff();
+ status_t onOutputFormatChanged(size_t trackIndex, CodecState *state);
+
+ void renderAudio(
+ CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer);
+
+ DISALLOW_EVIL_CONSTRUCTORS(SimplePlayer);
+};
+
+} // namespace android
diff --git a/cmds/stagefright/SineSource.cpp b/cmds/stagefright/SineSource.cpp
new file mode 100644
index 0000000..14b4306
--- /dev/null
+++ b/cmds/stagefright/SineSource.cpp
@@ -0,0 +1,102 @@
+#include "SineSource.h"
+
+#include <math.h>
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+SineSource::SineSource(int32_t sampleRate, int32_t numChannels)
+ : mStarted(false),
+ mSampleRate(sampleRate),
+ mNumChannels(numChannels),
+ mPhase(0),
+ mGroup(NULL) {
+ CHECK(numChannels == 1 || numChannels == 2);
+}
+
+SineSource::~SineSource() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t SineSource::start(MetaData *params) {
+ CHECK(!mStarted);
+
+ mGroup = new MediaBufferGroup;
+ mGroup->add_buffer(new MediaBuffer(kBufferSize));
+
+ mPhase = 0;
+ mStarted = true;
+
+ return OK;
+}
+
+status_t SineSource::stop() {
+ CHECK(mStarted);
+
+ delete mGroup;
+ mGroup = NULL;
+
+ mStarted = false;
+
+ return OK;
+}
+
+sp<MetaData> SineSource::getFormat() {
+ sp<MetaData> meta = new MetaData;
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+ meta->setInt32(kKeyChannelCount, mNumChannels);
+ meta->setInt32(kKeySampleRate, mSampleRate);
+ meta->setInt32(kKeyMaxInputSize, kBufferSize);
+
+ return meta;
+}
+
+status_t SineSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ MediaBuffer *buffer;
+ status_t err = mGroup->acquire_buffer(&buffer);
+
+ if (err != OK) {
+ return err;
+ }
+
+ size_t frameSize = mNumChannels * sizeof(int16_t);
+ size_t numFramesPerBuffer = buffer->size() / frameSize;
+
+ int16_t *ptr = (int16_t *)buffer->data();
+
+ const double k = kFrequency / mSampleRate * (2.0 * M_PI);
+
+ double x = mPhase * k;
+ for (size_t i = 0; i < numFramesPerBuffer; ++i) {
+ int16_t amplitude = (int16_t)(32767.0 * sin(x));
+
+ *ptr++ = amplitude;
+ if (mNumChannels == 2) {
+ *ptr++ = amplitude;
+ }
+
+ x += k;
+ }
+
+ buffer->meta_data()->setInt64(
+ kKeyTime, ((int64_t)mPhase * 1000000) / mSampleRate);
+
+ mPhase += numFramesPerBuffer;
+
+ buffer->set_range(0, numFramesPerBuffer * frameSize);
+
+ *out = buffer;
+
+ return OK;
+}
+
+} // namespace android
diff --git a/cmds/stagefright/SineSource.h b/cmds/stagefright/SineSource.h
new file mode 100644
index 0000000..76ab669
--- /dev/null
+++ b/cmds/stagefright/SineSource.h
@@ -0,0 +1,39 @@
+#ifndef SINE_SOURCE_H_
+
+#define SINE_SOURCE_H_
+
+#include <media/stagefright/MediaSource.h>
+
+namespace android {
+
+struct MediaBufferGroup;
+
+struct SineSource : public MediaSource {
+ SineSource(int32_t sampleRate, int32_t numChannels);
+
+ virtual status_t start(MetaData *params);
+ virtual status_t stop();
+
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **out, const ReadOptions *options = NULL);
+
+protected:
+ virtual ~SineSource();
+
+private:
+ enum { kBufferSize = 8192 };
+ static const double kFrequency = 500.0;
+
+ bool mStarted;
+ int32_t mSampleRate;
+ int32_t mNumChannels;
+ size_t mPhase;
+
+ MediaBufferGroup *mGroup;
+};
+
+} // namespace android
+
+#endif // SINE_SOURCE_H_
diff --git a/cmds/stagefright/WaveWriter.h b/cmds/stagefright/WaveWriter.h
new file mode 100644
index 0000000..a0eb66e
--- /dev/null
+++ b/cmds/stagefright/WaveWriter.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_WAVEWRITER_H_
+
+#define ANDROID_WAVEWRITER_H_
+
+namespace android {
+
+class WaveWriter {
+public:
+ WaveWriter(const char *filename,
+ uint16_t num_channels, uint32_t sampling_rate)
+ : mFile(fopen(filename, "wb")),
+ mTotalBytes(0) {
+ fwrite("RIFFxxxxWAVEfmt \x10\x00\x00\x00\x01\x00", 1, 22, mFile);
+ write_u16(num_channels);
+ write_u32(sampling_rate);
+ write_u32(sampling_rate * num_channels * 2);
+ write_u16(num_channels * 2);
+ write_u16(16);
+ fwrite("dataxxxx", 1, 8, mFile);
+ }
+
+ ~WaveWriter() {
+ fseek(mFile, 40, SEEK_SET);
+ write_u32(mTotalBytes);
+
+ fseek(mFile, 4, SEEK_SET);
+ write_u32(36 + mTotalBytes);
+
+ fclose(mFile);
+ mFile = NULL;
+ }
+
+ void Append(const void *data, size_t size) {
+ fwrite(data, 1, size, mFile);
+ mTotalBytes += size;
+ }
+
+private:
+ void write_u16(uint16_t x) {
+ fputc(x & 0xff, mFile);
+ fputc(x >> 8, mFile);
+ }
+
+ void write_u32(uint32_t x) {
+ write_u16(x & 0xffff);
+ write_u16(x >> 16);
+ }
+
+ FILE *mFile;
+ size_t mTotalBytes;
+};
+
+} // namespace android
+
+#endif // ANDROID_WAVEWRITER_H_
diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp
new file mode 100644
index 0000000..ed7d6cb
--- /dev/null
+++ b/cmds/stagefright/audioloop.cpp
@@ -0,0 +1,101 @@
+#include "SineSource.h"
+
+#include <binder/ProcessState.h>
+#include <media/mediarecorder.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/AMRWriter.h>
+#include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/AudioSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+
+#include <system/audio.h>
+
+using namespace android;
+
+int main() {
+ // We only have an AMR-WB encoder on sholes...
+ static bool outputWBAMR = false;
+ static const int32_t kSampleRate = outputWBAMR ? 16000 : 8000;
+ static const int32_t kNumChannels = 1;
+
+ android::ProcessState::self()->startThreadPool();
+
+ OMXClient client;
+ CHECK_EQ(client.connect(), (status_t)OK);
+
+#if 0
+ sp<MediaSource> source = new SineSource(kSampleRate, kNumChannels);
+#else
+ sp<MediaSource> source = new AudioSource(
+ AUDIO_SOURCE_DEFAULT,
+ kSampleRate,
+ audio_channel_in_mask_from_count(kNumChannels));
+#endif
+
+ sp<MetaData> meta = new MetaData;
+
+ meta->setCString(
+ kKeyMIMEType,
+ outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB
+ : MEDIA_MIMETYPE_AUDIO_AMR_NB);
+
+ meta->setInt32(kKeyChannelCount, kNumChannels);
+ meta->setInt32(kKeySampleRate, kSampleRate);
+
+ int32_t maxInputSize;
+ if (source->getFormat()->findInt32(kKeyMaxInputSize, &maxInputSize)) {
+ meta->setInt32(kKeyMaxInputSize, maxInputSize);
+ }
+
+ sp<MediaSource> encoder = OMXCodec::Create(
+ client.interface(),
+ meta, true /* createEncoder */,
+ source);
+
+#if 1
+ sp<AMRWriter> writer = new AMRWriter("/sdcard/out.amr");
+ writer->addSource(encoder);
+ writer->start();
+ sleep(10);
+ writer->stop();
+#else
+ sp<MediaSource> decoder = OMXCodec::Create(
+ client.interface(),
+ meta, false /* createEncoder */,
+ encoder);
+
+#if 0
+ AudioPlayer *player = new AudioPlayer(NULL);
+ player->setSource(decoder);
+
+ player->start();
+
+ sleep(10);
+
+ player->stop();
+
+ delete player;
+ player = NULL;
+#elif 0
+ CHECK_EQ(decoder->start(), (status_t)OK);
+
+ MediaBuffer *buffer;
+ while (decoder->read(&buffer) == OK) {
+ // do something with buffer
+
+ putchar('.');
+ fflush(stdout);
+
+ buffer->release();
+ buffer = NULL;
+ }
+
+ CHECK_EQ(decoder->stop(), (status_t)OK);
+#endif
+#endif
+
+ return 0;
+}
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
new file mode 100644
index 0000000..cf2909e
--- /dev/null
+++ b/cmds/stagefright/codec.cpp
@@ -0,0 +1,495 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "codec"
+#include <utils/Log.h>
+
+#include "SimplePlayer.h"
+
+#include <binder/ProcessState.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/DataSource.h>
+#include <media/stagefright/MediaCodec.h>
+#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/NuMediaExtractor.h>
+#include <gui/SurfaceComposerClient.h>
+
+static void usage(const char *me) {
+ fprintf(stderr, "usage: %s [-a] use audio\n"
+ "\t\t[-v] use video\n"
+ "\t\t[-p] playback\n"
+ "\t\t[-S] allocate buffers from a surface\n"
+ "\t\t[-D] decrypt input buffers\n",
+ me);
+
+ exit(1);
+}
+
+namespace android {
+
+struct CodecState {
+ sp<MediaCodec> mCodec;
+ Vector<sp<ABuffer> > mCSD;
+ size_t mCSDIndex;
+ Vector<sp<ABuffer> > mInBuffers;
+ Vector<sp<ABuffer> > mOutBuffers;
+ bool mSignalledInputEOS;
+ bool mSawOutputEOS;
+ int64_t mNumBuffersDecoded;
+ int64_t mNumBytesDecoded;
+ bool mIsAudio;
+};
+
+} // namespace android
+
+static int decode(
+ const android::sp<android::ALooper> &looper,
+ const char *path,
+ bool useAudio,
+ bool useVideo,
+ const android::sp<android::Surface> &surface,
+ bool decryptInputBuffers) {
+ using namespace android;
+
+ static int64_t kTimeout = 500ll;
+
+ sp<NuMediaExtractor> extractor = new NuMediaExtractor;
+ if (extractor->setDataSource(path) != OK) {
+ fprintf(stderr, "unable to instantiate extractor.\n");
+ return 1;
+ }
+
+ KeyedVector<size_t, CodecState> stateByTrack;
+
+ bool haveAudio = false;
+ bool haveVideo = false;
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ sp<AMessage> format;
+ status_t err = extractor->getTrackFormat(i, &format);
+ CHECK_EQ(err, (status_t)OK);
+
+ AString mime;
+ CHECK(format->findString("mime", &mime));
+
+ bool isAudio = !strncasecmp(mime.c_str(), "audio/", 6);
+ bool isVideo = !strncasecmp(mime.c_str(), "video/", 6);
+
+ if (useAudio && !haveAudio && isAudio) {
+ haveAudio = true;
+ } else if (useVideo && !haveVideo && isVideo) {
+ haveVideo = true;
+ } else {
+ continue;
+ }
+
+ ALOGV("selecting track %d", i);
+
+ err = extractor->selectTrack(i);
+ CHECK_EQ(err, (status_t)OK);
+
+ CodecState *state =
+ &stateByTrack.editValueAt(stateByTrack.add(i, CodecState()));
+
+ state->mNumBytesDecoded = 0;
+ state->mNumBuffersDecoded = 0;
+ state->mIsAudio = isAudio;
+
+ if (decryptInputBuffers && !isAudio) {
+ static const MediaCodecList *list = MediaCodecList::getInstance();
+
+ ssize_t index =
+ list->findCodecByType(mime.c_str(), false /* encoder */);
+
+ CHECK_GE(index, 0);
+
+ const char *componentName = list->getCodecName(index);
+
+ AString fullName = componentName;
+ fullName.append(".secure");
+
+ state->mCodec = MediaCodec::CreateByComponentName(
+ looper, fullName.c_str());
+ } else {
+ state->mCodec = MediaCodec::CreateByType(
+ looper, mime.c_str(), false /* encoder */);
+ }
+
+ CHECK(state->mCodec != NULL);
+
+ err = state->mCodec->configure(
+ format, isVideo ? surface : NULL,
+ decryptInputBuffers ? MediaCodec::CONFIGURE_FLAG_SECURE : 0);
+
+ CHECK_EQ(err, (status_t)OK);
+
+ size_t j = 0;
+ sp<ABuffer> buffer;
+ while (format->findBuffer(StringPrintf("csd-%d", j).c_str(), &buffer)) {
+ state->mCSD.push_back(buffer);
+
+ ++j;
+ }
+
+ state->mCSDIndex = 0;
+ state->mSignalledInputEOS = false;
+ state->mSawOutputEOS = false;
+
+ ALOGV("got %d pieces of codec specific data.", state->mCSD.size());
+ }
+
+ CHECK(!stateByTrack.isEmpty());
+
+ int64_t startTimeUs = ALooper::GetNowUs();
+
+ for (size_t i = 0; i < stateByTrack.size(); ++i) {
+ CodecState *state = &stateByTrack.editValueAt(i);
+
+ sp<MediaCodec> codec = state->mCodec;
+
+ CHECK_EQ((status_t)OK, codec->start());
+
+ CHECK_EQ((status_t)OK, codec->getInputBuffers(&state->mInBuffers));
+ CHECK_EQ((status_t)OK, codec->getOutputBuffers(&state->mOutBuffers));
+
+ ALOGV("got %d input and %d output buffers",
+ state->mInBuffers.size(), state->mOutBuffers.size());
+
+ while (state->mCSDIndex < state->mCSD.size()) {
+ size_t index;
+ status_t err = codec->dequeueInputBuffer(&index, -1ll);
+ CHECK_EQ(err, (status_t)OK);
+
+ const sp<ABuffer> &srcBuffer =
+ state->mCSD.itemAt(state->mCSDIndex++);
+
+ const sp<ABuffer> &buffer = state->mInBuffers.itemAt(index);
+
+ memcpy(buffer->data(), srcBuffer->data(), srcBuffer->size());
+
+ err = codec->queueInputBuffer(
+ index,
+ 0 /* offset */,
+ srcBuffer->size(),
+ 0ll /* timeUs */,
+ MediaCodec::BUFFER_FLAG_CODECCONFIG);
+
+ CHECK_EQ(err, (status_t)OK);
+ }
+ }
+
+ bool sawInputEOS = false;
+
+ for (;;) {
+ if (!sawInputEOS) {
+ size_t trackIndex;
+ status_t err = extractor->getSampleTrackIndex(&trackIndex);
+
+ if (err != OK) {
+ ALOGV("saw input eos");
+ sawInputEOS = true;
+ } else {
+ CodecState *state = &stateByTrack.editValueFor(trackIndex);
+
+ size_t index;
+ err = state->mCodec->dequeueInputBuffer(&index, kTimeout);
+
+ if (err == OK) {
+ ALOGV("filling input buffer %d", index);
+
+ const sp<ABuffer> &buffer = state->mInBuffers.itemAt(index);
+
+ err = extractor->readSampleData(buffer);
+ CHECK_EQ(err, (status_t)OK);
+
+ int64_t timeUs;
+ err = extractor->getSampleTime(&timeUs);
+ CHECK_EQ(err, (status_t)OK);
+
+ uint32_t bufferFlags = 0;
+
+ uint32_t sampleFlags;
+ err = extractor->getSampleFlags(&sampleFlags);
+ CHECK_EQ(err, (status_t)OK);
+
+ if (sampleFlags & NuMediaExtractor::SAMPLE_FLAG_ENCRYPTED) {
+ CHECK(decryptInputBuffers);
+
+ bufferFlags |= MediaCodec::BUFFER_FLAG_ENCRYPTED;
+ }
+
+ err = state->mCodec->queueInputBuffer(
+ index,
+ 0 /* offset */,
+ buffer->size(),
+ timeUs,
+ bufferFlags);
+
+ CHECK_EQ(err, (status_t)OK);
+
+ extractor->advance();
+ } else {
+ CHECK_EQ(err, -EAGAIN);
+ }
+ }
+ } else {
+ for (size_t i = 0; i < stateByTrack.size(); ++i) {
+ CodecState *state = &stateByTrack.editValueAt(i);
+
+ if (!state->mSignalledInputEOS) {
+ size_t index;
+ status_t err =
+ state->mCodec->dequeueInputBuffer(&index, kTimeout);
+
+ if (err == OK) {
+ ALOGV("signalling input EOS on track %d", i);
+
+ err = state->mCodec->queueInputBuffer(
+ index,
+ 0 /* offset */,
+ 0 /* size */,
+ 0ll /* timeUs */,
+ MediaCodec::BUFFER_FLAG_EOS);
+
+ CHECK_EQ(err, (status_t)OK);
+
+ state->mSignalledInputEOS = true;
+ } else {
+ CHECK_EQ(err, -EAGAIN);
+ }
+ }
+ }
+ }
+
+ bool sawOutputEOSOnAllTracks = true;
+ for (size_t i = 0; i < stateByTrack.size(); ++i) {
+ CodecState *state = &stateByTrack.editValueAt(i);
+ if (!state->mSawOutputEOS) {
+ sawOutputEOSOnAllTracks = false;
+ break;
+ }
+ }
+
+ if (sawOutputEOSOnAllTracks) {
+ break;
+ }
+
+ for (size_t i = 0; i < stateByTrack.size(); ++i) {
+ CodecState *state = &stateByTrack.editValueAt(i);
+
+ if (state->mSawOutputEOS) {
+ continue;
+ }
+
+ size_t index;
+ size_t offset;
+ size_t size;
+ int64_t presentationTimeUs;
+ uint32_t flags;
+ status_t err = state->mCodec->dequeueOutputBuffer(
+ &index, &offset, &size, &presentationTimeUs, &flags,
+ kTimeout);
+
+ if (err == OK) {
+ ALOGV("draining output buffer %d, time = %lld us",
+ index, presentationTimeUs);
+
+ ++state->mNumBuffersDecoded;
+ state->mNumBytesDecoded += size;
+
+ err = state->mCodec->releaseOutputBuffer(index);
+ CHECK_EQ(err, (status_t)OK);
+
+ if (flags & MediaCodec::BUFFER_FLAG_EOS) {
+ ALOGV("reached EOS on output.");
+
+ state->mSawOutputEOS = true;
+ }
+ } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
+ ALOGV("INFO_OUTPUT_BUFFERS_CHANGED");
+ CHECK_EQ((status_t)OK,
+ state->mCodec->getOutputBuffers(&state->mOutBuffers));
+
+ ALOGV("got %d output buffers", state->mOutBuffers.size());
+ } else if (err == INFO_FORMAT_CHANGED) {
+ sp<AMessage> format;
+ CHECK_EQ((status_t)OK, state->mCodec->getOutputFormat(&format));
+
+ ALOGV("INFO_FORMAT_CHANGED: %s", format->debugString().c_str());
+ } else {
+ CHECK_EQ(err, -EAGAIN);
+ }
+ }
+ }
+
+ int64_t elapsedTimeUs = ALooper::GetNowUs() - startTimeUs;
+
+ for (size_t i = 0; i < stateByTrack.size(); ++i) {
+ CodecState *state = &stateByTrack.editValueAt(i);
+
+ CHECK_EQ((status_t)OK, state->mCodec->release());
+
+ if (state->mIsAudio) {
+ printf("track %d: %lld bytes received. %.2f KB/sec\n",
+ i,
+ state->mNumBytesDecoded,
+ state->mNumBytesDecoded * 1E6 / 1024 / elapsedTimeUs);
+ } else {
+ printf("track %d: %lld frames decoded, %.2f fps. %lld bytes "
+ "received. %.2f KB/sec\n",
+ i,
+ state->mNumBuffersDecoded,
+ state->mNumBuffersDecoded * 1E6 / elapsedTimeUs,
+ state->mNumBytesDecoded,
+ state->mNumBytesDecoded * 1E6 / 1024 / elapsedTimeUs);
+ }
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ using namespace android;
+
+ const char *me = argv[0];
+
+ bool useAudio = false;
+ bool useVideo = false;
+ bool playback = false;
+ bool useSurface = false;
+ bool decryptInputBuffers = false;
+
+ int res;
+ while ((res = getopt(argc, argv, "havpSD")) >= 0) {
+ switch (res) {
+ case 'a':
+ {
+ useAudio = true;
+ break;
+ }
+
+ case 'v':
+ {
+ useVideo = true;
+ break;
+ }
+
+ case 'p':
+ {
+ playback = true;
+ break;
+ }
+
+ case 'S':
+ {
+ useSurface = true;
+ break;
+ }
+
+ case 'D':
+ {
+ decryptInputBuffers = true;
+ break;
+ }
+
+ case '?':
+ case 'h':
+ default:
+ {
+ usage(me);
+ }
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1) {
+ usage(me);
+ }
+
+ if (!useAudio && !useVideo) {
+ useAudio = useVideo = true;
+ }
+
+ ProcessState::self()->startThreadPool();
+
+ DataSource::RegisterDefaultSniffers();
+
+ sp<ALooper> looper = new ALooper;
+ looper->start();
+
+ sp<SurfaceComposerClient> composerClient;
+ sp<SurfaceControl> control;
+ sp<Surface> surface;
+
+ if (playback || (useSurface && useVideo)) {
+ composerClient = new SurfaceComposerClient;
+ CHECK_EQ(composerClient->initCheck(), (status_t)OK);
+
+ ssize_t displayWidth = composerClient->getDisplayWidth(0);
+ ssize_t displayHeight = composerClient->getDisplayHeight(0);
+
+ ALOGV("display is %ld x %ld\n", displayWidth, displayHeight);
+
+ control = composerClient->createSurface(
+ String8("A Surface"),
+ 0,
+ displayWidth,
+ displayHeight,
+ PIXEL_FORMAT_RGB_565,
+ 0);
+
+ CHECK(control != NULL);
+ CHECK(control->isValid());
+
+ SurfaceComposerClient::openGlobalTransaction();
+ CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK);
+ CHECK_EQ(control->show(), (status_t)OK);
+ SurfaceComposerClient::closeGlobalTransaction();
+
+ surface = control->getSurface();
+ CHECK(surface != NULL);
+ }
+
+ if (playback) {
+ sp<SimplePlayer> player = new SimplePlayer;
+ looper->registerHandler(player);
+
+ player->setDataSource(argv[0]);
+ player->setSurface(surface->getSurfaceTexture());
+ player->start();
+ sleep(60);
+ player->stop();
+ player->reset();
+ } else {
+ decode(looper, argv[0],
+ useAudio, useVideo, surface, decryptInputBuffers);
+ }
+
+ if (playback || (useSurface && useVideo)) {
+ composerClient->dispose();
+ }
+
+ looper->stop();
+
+ return 0;
+}
diff --git a/cmds/stagefright/jpeg.cpp b/cmds/stagefright/jpeg.cpp
new file mode 100644
index 0000000..7e859c3
--- /dev/null
+++ b/cmds/stagefright/jpeg.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <errno.h>
+#include <setjmp.h>
+#include <stdio.h>
+
+extern "C" {
+#include "jpeglib.h"
+}
+
+static inline uint8_t from565to8(uint16_t p, int start, int bits) {
+ uint8_t c = (p >> start) & ((1 << bits) - 1);
+ return (c << (8 - bits)) | (c >> (bits - (8 - bits)));
+}
+
+struct sf_jpeg_error_mgr {
+ struct jpeg_error_mgr jerr;
+ jmp_buf longjmp_buffer;
+};
+
+void sf_jpeg_error_exit(j_common_ptr cinfo) {
+ struct sf_jpeg_error_mgr *sf_err = (struct sf_jpeg_error_mgr *)cinfo->err;
+ longjmp(sf_err->longjmp_buffer, 0);
+}
+
+int writeJpegFile(const char *filename, uint8_t *frame, int width, int height) {
+ struct sf_jpeg_error_mgr sf_err;
+ struct jpeg_compress_struct cinfo;
+ uint8_t row_data[width * 3];
+ JSAMPROW row_pointer = row_data;
+ FILE *f;
+
+ f = fopen(filename, "w");
+ if (!f) {
+ return -errno;
+ }
+
+ cinfo.err = jpeg_std_error(&sf_err.jerr);
+ sf_err.jerr.error_exit = sf_jpeg_error_exit;
+ if (setjmp(sf_err.longjmp_buffer)) {
+ jpeg_destroy_compress(&cinfo);
+ fclose(f);
+ return -1;
+ }
+
+ jpeg_create_compress(&cinfo);
+ jpeg_stdio_dest(&cinfo, f);
+
+ cinfo.image_width = width;
+ cinfo.image_height = height;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, 80, TRUE);
+
+ jpeg_start_compress(&cinfo, TRUE);
+
+ for (int row = 0; row < height; row++) {
+ uint16_t *src = (uint16_t *)(frame + row * width * 2);
+ uint8_t *dst = row_data;
+ for (int col = 0; col < width; col++) {
+ dst[0] = from565to8(*src, 11, 5);
+ dst[1] = from565to8(*src, 5, 6);
+ dst[2] = from565to8(*src, 0, 5);
+ dst += 3;
+ src++;
+ }
+ jpeg_write_scanlines(&cinfo, &row_pointer, 1);
+ }
+
+ jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
+
+ fclose(f);
+ return 0;
+}
diff --git a/cmds/stagefright/jpeg.h b/cmds/stagefright/jpeg.h
new file mode 100644
index 0000000..ce86cf2
--- /dev/null
+++ b/cmds/stagefright/jpeg.h
@@ -0,0 +1,6 @@
+#ifndef _STAGEFRIGHT_JPEG_H_
+#define _STAGEFRIGHT_JPEG_H_
+
+int writeJpegFile(const char *filename, uint8_t *frame, int width, int height);
+
+#endif
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
new file mode 100644
index 0000000..45c3f7b
--- /dev/null
+++ b/cmds/stagefright/record.cpp
@@ -0,0 +1,354 @@
+/*
+ * 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 "SineSource.h"
+
+#include <binder/ProcessState.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/CameraSource.h>
+#include <media/stagefright/FileSource.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#include <media/MediaPlayerInterface.h>
+
+using namespace android;
+
+static const int32_t kFramerate = 24; // fps
+static const int32_t kIFramesIntervalSec = 1;
+static const int32_t kVideoBitRate = 512 * 1024;
+static const int32_t kAudioBitRate = 12200;
+static const int64_t kDurationUs = 10000000LL; // 10 seconds
+
+#if 0
+class DummySource : public MediaSource {
+
+public:
+ DummySource(int width, int height, int colorFormat)
+ : mWidth(width),
+ mHeight(height),
+ mColorFormat(colorFormat),
+ mSize((width * height * 3) / 2) {
+ mGroup.add_buffer(new MediaBuffer(mSize));
+
+ // Check the color format to make sure
+ // that the buffer size mSize it set correctly above.
+ CHECK(colorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
+ colorFormat == OMX_COLOR_FormatYUV420Planar);
+ }
+
+ virtual sp<MetaData> getFormat() {
+ sp<MetaData> meta = new MetaData;
+ meta->setInt32(kKeyWidth, mWidth);
+ meta->setInt32(kKeyHeight, mHeight);
+ meta->setInt32(kKeyColorFormat, mColorFormat);
+ 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 * 10) {
+ // Stop returning data after 10 secs.
+ return ERROR_END_OF_STREAM;
+ }
+
+ // printf("DummySource::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("DummySource::read - returning buffer\n");
+ // ALOGI("DummySource::read - returning buffer");
+ return OK;
+ }
+
+protected:
+ virtual ~DummySource() {}
+
+private:
+ MediaBufferGroup mGroup;
+ int mWidth, mHeight;
+ int mColorFormat;
+ size_t mSize;
+ int64_t mNumFramesOutput;;
+
+ DummySource(const DummySource &);
+ DummySource &operator=(const DummySource &);
+};
+
+sp<MediaSource> createSource(const char *filename) {
+ sp<MediaSource> source;
+
+ sp<MediaExtractor> extractor =
+ MediaExtractor::Create(new FileSource(filename));
+ if (extractor == NULL) {
+ return NULL;
+ }
+
+ size_t num_tracks = extractor->countTracks();
+
+ sp<MetaData> meta;
+ for (size_t i = 0; i < num_tracks; ++i) {
+ meta = extractor->getTrackMetaData(i);
+ CHECK(meta.get() != NULL);
+
+ const char *mime;
+ if (!meta->findCString(kKeyMIMEType, &mime)) {
+ continue;
+ }
+
+ if (strncasecmp(mime, "video/", 6)) {
+ continue;
+ }
+
+ source = extractor->getTrack(i);
+ break;
+ }
+
+ return source;
+}
+
+enum {
+ kYUV420SP = 0,
+ kYUV420P = 1,
+};
+
+// returns -1 if mapping of the given color is unsuccessful
+// returns an omx color enum value otherwise
+static int translateColorToOmxEnumValue(int color) {
+ switch (color) {
+ case kYUV420SP:
+ return OMX_COLOR_FormatYUV420SemiPlanar;
+ case kYUV420P:
+ return OMX_COLOR_FormatYUV420Planar;
+ default:
+ fprintf(stderr, "Unsupported color: %d\n", color);
+ return -1;
+ }
+}
+
+int main(int argc, char **argv) {
+ android::ProcessState::self()->startThreadPool();
+
+ DataSource::RegisterDefaultSniffers();
+
+#if 1
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s <filename> <input_color_format>\n", argv[0]);
+ fprintf(stderr, " <input_color_format>: 0 (YUV420SP) or 1 (YUV420P)\n");
+ return 1;
+ }
+
+ int colorFormat = translateColorToOmxEnumValue(atoi(argv[2]));
+ if (colorFormat == -1) {
+ fprintf(stderr, "input color format must be 0 (YUV420SP) or 1 (YUV420P)\n");
+ return 1;
+ }
+ OMXClient client;
+ CHECK_EQ(client.connect(), (status_t)OK);
+
+ status_t err = OK;
+
+#if 0
+ sp<MediaSource> source = createSource(argv[1]);
+
+ if (source == NULL) {
+ fprintf(stderr, "Unable to find a suitable video track.\n");
+ return 1;
+ }
+
+ sp<MetaData> meta = source->getFormat();
+
+ sp<MediaSource> decoder = OMXCodec::Create(
+ client.interface(), meta, false /* createEncoder */, source);
+
+ int width, height;
+ bool success = meta->findInt32(kKeyWidth, &width);
+ success = success && meta->findInt32(kKeyHeight, &height);
+ CHECK(success);
+#else
+ int width = 720;
+ int height = 480;
+ sp<MediaSource> decoder = new DummySource(width, height, colorFormat);
+#endif
+
+ sp<MetaData> enc_meta = new MetaData;
+ // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+ // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+ enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+ enc_meta->setInt32(kKeyWidth, width);
+ enc_meta->setInt32(kKeyHeight, height);
+ enc_meta->setInt32(kKeySampleRate, kFramerate);
+ enc_meta->setInt32(kKeyBitRate, kVideoBitRate);
+ enc_meta->setInt32(kKeyStride, width);
+ enc_meta->setInt32(kKeySliceHeight, height);
+ enc_meta->setInt32(kKeyIFramesInterval, kIFramesIntervalSec);
+ enc_meta->setInt32(kKeyColorFormat, colorFormat);
+
+ sp<MediaSource> encoder =
+ OMXCodec::Create(
+ client.interface(), enc_meta, true /* createEncoder */, decoder);
+
+#if 1
+ sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
+ writer->addSource(encoder);
+ writer->setMaxFileDuration(kDurationUs);
+ CHECK_EQ((status_t)OK, writer->start());
+ while (!writer->reachedEOS()) {
+ fprintf(stderr, ".");
+ usleep(100000);
+ }
+ err = writer->stop();
+#else
+ CHECK_EQ((status_t)OK, encoder->start());
+
+ MediaBuffer *buffer;
+ while (encoder->read(&buffer) == OK) {
+ printf(".");
+ fflush(stdout);
+ int32_t isSync;
+ if (!buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)) {
+ isSync = false;
+ }
+
+ printf("got an output frame of size %d%s\n", buffer->range_length(),
+ isSync ? " (SYNC)" : "");
+
+ buffer->release();
+ buffer = NULL;
+ }
+
+ err = encoder->stop();
+#endif
+
+ printf("$\n");
+ client.disconnect();
+#endif
+
+#if 0
+ CameraSource *source = CameraSource::Create();
+ source->start();
+
+ printf("source = %p\n", source);
+
+ for (int i = 0; i < 100; ++i) {
+ MediaBuffer *buffer;
+ status_t err = source->read(&buffer);
+ CHECK_EQ(err, (status_t)OK);
+
+ printf("got a frame, data=%p, size=%d\n",
+ buffer->data(), buffer->range_length());
+
+ buffer->release();
+ buffer = NULL;
+ }
+
+ err = source->stop();
+
+ delete source;
+ source = NULL;
+#endif
+
+ if (err != OK && err != ERROR_END_OF_STREAM) {
+ fprintf(stderr, "record failed: %d\n", err);
+ return 1;
+ }
+ return 0;
+}
+#else
+
+int main(int argc, char **argv) {
+ android::ProcessState::self()->startThreadPool();
+
+ OMXClient client;
+ CHECK_EQ(client.connect(), (status_t)OK);
+
+ const int32_t kSampleRate = 22050;
+ const int32_t kNumChannels = 2;
+ sp<MediaSource> audioSource = new SineSource(kSampleRate, kNumChannels);
+
+#if 0
+ sp<MediaPlayerBase::AudioSink> audioSink;
+ AudioPlayer *player = new AudioPlayer(audioSink);
+ player->setSource(audioSource);
+ player->start();
+
+ sleep(10);
+
+ player->stop();
+#endif
+
+ sp<MetaData> encMeta = new MetaData;
+ encMeta->setCString(kKeyMIMEType,
+ 0 ? MEDIA_MIMETYPE_AUDIO_AMR_WB : MEDIA_MIMETYPE_AUDIO_AAC);
+ encMeta->setInt32(kKeySampleRate, kSampleRate);
+ encMeta->setInt32(kKeyChannelCount, kNumChannels);
+ encMeta->setInt32(kKeyMaxInputSize, 8192);
+ encMeta->setInt32(kKeyBitRate, kAudioBitRate);
+
+ sp<MediaSource> encoder =
+ OMXCodec::Create(client.interface(), encMeta, true, audioSource);
+
+ encoder->start();
+
+ int32_t n = 0;
+ status_t err;
+ MediaBuffer *buffer;
+ while ((err = encoder->read(&buffer)) == OK) {
+ printf(".");
+ fflush(stdout);
+
+ buffer->release();
+ buffer = NULL;
+
+ if (++n == 100) {
+ break;
+ }
+ }
+ printf("$\n");
+
+ encoder->stop();
+
+ client.disconnect();
+
+ return 0;
+}
+#endif
diff --git a/cmds/stagefright/recordvideo.cpp b/cmds/stagefright/recordvideo.cpp
new file mode 100644
index 0000000..3bd1fe2
--- /dev/null
+++ b/cmds/stagefright/recordvideo.cpp
@@ -0,0 +1,302 @@
+/*
+ * 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 "SineSource.h"
+
+#include <binder/ProcessState.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#include <media/MediaPlayerInterface.h>
+
+using namespace android;
+
+// Print usage showing how to use this utility to record videos
+static void usage(const char *me) {
+ fprintf(stderr, "usage: %s\n", me);
+ fprintf(stderr, " -h(elp)\n");
+ fprintf(stderr, " -b bit rate in bits per second (default: 300000)\n");
+ fprintf(stderr, " -c YUV420 color format: [0] semi planar or [1] planar or other omx YUV420 color format (default: 1)\n");
+ fprintf(stderr, " -f frame rate in frames per second (default: 30)\n");
+ fprintf(stderr, " -i I frame interval in seconds (default: 1)\n");
+ fprintf(stderr, " -n number of frames to be recorded (default: 300)\n");
+ fprintf(stderr, " -w width in pixels (default: 176)\n");
+ fprintf(stderr, " -t height in pixels (default: 144)\n");
+ fprintf(stderr, " -l encoder level. see omx il header (default: encoder specific)\n");
+ fprintf(stderr, " -p encoder profile. see omx il header (default: encoder specific)\n");
+ fprintf(stderr, " -v video codec: [0] AVC [1] M4V [2] H263 (default: 0)\n");
+ fprintf(stderr, "The output file is /sdcard/output.mp4\n");
+ exit(1);
+}
+
+class DummySource : public MediaSource {
+
+public:
+ DummySource(int width, int height, int nFrames, int fps, int colorFormat)
+ : mWidth(width),
+ mHeight(height),
+ mMaxNumFrames(nFrames),
+ mFrameRate(fps),
+ mColorFormat(colorFormat),
+ 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->setInt32(kKeyColorFormat, mColorFormat);
+ 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 % 10 == 0) {
+ fprintf(stderr, ".");
+ }
+ if (mNumFramesOutput == mMaxNumFrames) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ status_t err = mGroup.acquire_buffer(buffer);
+ if (err != OK) {
+ return err;
+ }
+
+ // We don't care about the contents. we just test video encoder
+ // Also, by skipping the content generation, we can return from
+ // read() much faster.
+ //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) / mFrameRate);
+ ++mNumFramesOutput;
+
+ return OK;
+ }
+
+protected:
+ virtual ~DummySource() {}
+
+private:
+ MediaBufferGroup mGroup;
+ int mWidth, mHeight;
+ int mMaxNumFrames;
+ int mFrameRate;
+ int mColorFormat;
+ size_t mSize;
+ int64_t mNumFramesOutput;;
+
+ DummySource(const DummySource &);
+ DummySource &operator=(const DummySource &);
+};
+
+enum {
+ kYUV420SP = 0,
+ kYUV420P = 1,
+};
+
+// returns -1 if mapping of the given color is unsuccessful
+// returns an omx color enum value otherwise
+static int translateColorToOmxEnumValue(int color) {
+ switch (color) {
+ case kYUV420SP:
+ return OMX_COLOR_FormatYUV420SemiPlanar;
+ case kYUV420P:
+ return OMX_COLOR_FormatYUV420Planar;
+ default:
+ fprintf(stderr, "Custom OMX color format: %d\n", color);
+ if (color == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar ||
+ color == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
+ return color;
+ }
+ }
+ return -1;
+}
+
+int main(int argc, char **argv) {
+
+ // Default values for the program if not overwritten
+ int frameRateFps = 30;
+ int width = 176;
+ int height = 144;
+ int bitRateBps = 300000;
+ int iFramesIntervalSeconds = 1;
+ int colorFormat = OMX_COLOR_FormatYUV420Planar;
+ int nFrames = 300;
+ int level = -1; // Encoder specific default
+ int profile = -1; // Encoder specific default
+ int codec = 0;
+ const char *fileName = "/sdcard/output.mp4";
+
+ android::ProcessState::self()->startThreadPool();
+ int res;
+ while ((res = getopt(argc, argv, "b:c:f:i:n:w:t:l:p:v:h")) >= 0) {
+ switch (res) {
+ case 'b':
+ {
+ bitRateBps = atoi(optarg);
+ break;
+ }
+
+ case 'c':
+ {
+ colorFormat = translateColorToOmxEnumValue(atoi(optarg));
+ if (colorFormat == -1) {
+ usage(argv[0]);
+ }
+ break;
+ }
+
+ case 'f':
+ {
+ frameRateFps = atoi(optarg);
+ break;
+ }
+
+ case 'i':
+ {
+ iFramesIntervalSeconds = atoi(optarg);
+ break;
+ }
+
+ case 'n':
+ {
+ nFrames = atoi(optarg);
+ break;
+ }
+
+ case 'w':
+ {
+ width = atoi(optarg);
+ break;
+ }
+
+ case 't':
+ {
+ height = atoi(optarg);
+ break;
+ }
+
+ case 'l':
+ {
+ level = atoi(optarg);
+ break;
+ }
+
+ case 'p':
+ {
+ profile = atoi(optarg);
+ break;
+ }
+
+ case 'v':
+ {
+ codec = atoi(optarg);
+ if (codec < 0 || codec > 2) {
+ usage(argv[0]);
+ }
+ break;
+ }
+
+ case 'h':
+ default:
+ {
+ usage(argv[0]);
+ break;
+ }
+ }
+ }
+
+ OMXClient client;
+ CHECK_EQ(client.connect(), (status_t)OK);
+
+ status_t err = OK;
+ sp<MediaSource> source =
+ new DummySource(width, height, nFrames, frameRateFps, colorFormat);
+
+ sp<MetaData> enc_meta = new MetaData;
+ switch (codec) {
+ case 1:
+ enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+ break;
+ case 2:
+ enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+ break;
+ default:
+ enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+ break;
+ }
+ enc_meta->setInt32(kKeyWidth, width);
+ enc_meta->setInt32(kKeyHeight, height);
+ enc_meta->setInt32(kKeyFrameRate, frameRateFps);
+ enc_meta->setInt32(kKeyBitRate, bitRateBps);
+ enc_meta->setInt32(kKeyStride, width);
+ enc_meta->setInt32(kKeySliceHeight, height);
+ enc_meta->setInt32(kKeyIFramesInterval, iFramesIntervalSeconds);
+ enc_meta->setInt32(kKeyColorFormat, colorFormat);
+ if (level != -1) {
+ enc_meta->setInt32(kKeyVideoLevel, level);
+ }
+ if (profile != -1) {
+ enc_meta->setInt32(kKeyVideoProfile, profile);
+ }
+
+ sp<MediaSource> encoder =
+ OMXCodec::Create(
+ client.interface(), enc_meta, true /* createEncoder */, source);
+
+ sp<MPEG4Writer> writer = new MPEG4Writer(fileName);
+ writer->addSource(encoder);
+ int64_t start = systemTime();
+ CHECK_EQ((status_t)OK, writer->start());
+ while (!writer->reachedEOS()) {
+ }
+ err = writer->stop();
+ int64_t end = systemTime();
+
+ fprintf(stderr, "$\n");
+ client.disconnect();
+
+ if (err != OK && err != ERROR_END_OF_STREAM) {
+ fprintf(stderr, "record failed: %d\n", err);
+ return 1;
+ }
+ fprintf(stderr, "encoding %d frames in %lld us\n", nFrames, (end-start)/1000);
+ fprintf(stderr, "encoding speed is: %.2f fps\n", (nFrames * 1E9) / (end-start));
+ return 0;
+}
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
new file mode 100644
index 0000000..3bbfbdc
--- /dev/null
+++ b/cmds/stagefright/sf2.cpp
@@ -0,0 +1,658 @@
+/*
+ * 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 "sf2"
+#include <utils/Log.h>
+
+#include <binder/ProcessState.h>
+
+#include <media/stagefright/foundation/hexdump.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/ACodec.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/NativeWindowWrapper.h>
+#include <media/stagefright/Utils.h>
+
+#include <gui/SurfaceComposerClient.h>
+
+#include "include/ESDS.h"
+
+using namespace android;
+
+struct Controller : public AHandler {
+ Controller(const char *uri, bool decodeAudio,
+ const sp<Surface> &surface, bool renderToSurface)
+ : mURI(uri),
+ mDecodeAudio(decodeAudio),
+ mSurface(surface),
+ mRenderToSurface(renderToSurface),
+ mCodec(new ACodec),
+ mIsVorbis(false) {
+ CHECK(!mDecodeAudio || mSurface == NULL);
+ }
+
+ void startAsync() {
+ (new AMessage(kWhatStart, id()))->post();
+ }
+
+protected:
+ virtual ~Controller() {
+ }
+
+ virtual void onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatStart:
+ {
+#if 1
+ mDecodeLooper = looper();
+#else
+ mDecodeLooper = new ALooper;
+ mDecodeLooper->setName("sf2 decode looper");
+ mDecodeLooper->start();
+#endif
+
+ sp<DataSource> dataSource =
+ DataSource::CreateFromURI(mURI.c_str());
+
+ sp<MediaExtractor> extractor =
+ MediaExtractor::Create(dataSource);
+
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (!strncasecmp(mDecodeAudio ? "audio/" : "video/",
+ mime, 6)) {
+ mSource = extractor->getTrack(i);
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
+ mIsVorbis = true;
+ } else {
+ mIsVorbis = false;
+ }
+ break;
+ }
+ }
+ CHECK(mSource != NULL);
+
+ CHECK_EQ(mSource->start(), (status_t)OK);
+
+ mDecodeLooper->registerHandler(mCodec);
+
+ mCodec->setNotificationMessage(
+ new AMessage(kWhatCodecNotify, id()));
+
+ sp<AMessage> format = makeFormat(mSource->getFormat());
+
+ if (mSurface != NULL) {
+ format->setObject(
+ "native-window", new NativeWindowWrapper(mSurface));
+ }
+
+ mCodec->initiateSetup(format);
+
+ mCSDIndex = 0;
+ mStartTimeUs = ALooper::GetNowUs();
+ mNumOutputBuffersReceived = 0;
+ mTotalBytesReceived = 0;
+ mLeftOverBuffer = NULL;
+ mFinalResult = OK;
+ mSeekState = SEEK_NONE;
+
+ // (new AMessage(kWhatSeek, id()))->post(5000000ll);
+ break;
+ }
+
+ case kWhatSeek:
+ {
+ printf("+");
+ fflush(stdout);
+
+ CHECK(mSeekState == SEEK_NONE
+ || mSeekState == SEEK_FLUSH_COMPLETED);
+
+ if (mLeftOverBuffer != NULL) {
+ mLeftOverBuffer->release();
+ mLeftOverBuffer = NULL;
+ }
+
+ mSeekState = SEEK_FLUSHING;
+ mSeekTimeUs = 30000000ll;
+
+ mCodec->signalFlush();
+ break;
+ }
+
+ case kWhatStop:
+ {
+ if (mLeftOverBuffer != NULL) {
+ mLeftOverBuffer->release();
+ mLeftOverBuffer = NULL;
+ }
+
+ CHECK_EQ(mSource->stop(), (status_t)OK);
+ mSource.clear();
+
+ mCodec->initiateShutdown();
+ break;
+ }
+
+ case kWhatCodecNotify:
+ {
+ int32_t what;
+ CHECK(msg->findInt32("what", &what));
+
+ if (what == ACodec::kWhatFillThisBuffer) {
+ onFillThisBuffer(msg);
+ } else if (what == ACodec::kWhatDrainThisBuffer) {
+ if ((mNumOutputBuffersReceived++ % 16) == 0) {
+ printf(".");
+ fflush(stdout);
+ }
+
+ onDrainThisBuffer(msg);
+ } else if (what == ACodec::kWhatEOS
+ || what == ACodec::kWhatError) {
+ printf((what == ACodec::kWhatEOS) ? "$\n" : "E\n");
+
+ int64_t delayUs = ALooper::GetNowUs() - mStartTimeUs;
+
+ if (mDecodeAudio) {
+ printf("%lld bytes received. %.2f KB/sec\n",
+ mTotalBytesReceived,
+ mTotalBytesReceived * 1E6 / 1024 / delayUs);
+ } else {
+ printf("%d frames decoded, %.2f fps. %lld bytes "
+ "received. %.2f KB/sec\n",
+ mNumOutputBuffersReceived,
+ mNumOutputBuffersReceived * 1E6 / delayUs,
+ mTotalBytesReceived,
+ mTotalBytesReceived * 1E6 / 1024 / delayUs);
+ }
+
+ (new AMessage(kWhatStop, id()))->post();
+ } else if (what == ACodec::kWhatFlushCompleted) {
+ mSeekState = SEEK_FLUSH_COMPLETED;
+ mCodec->signalResume();
+
+ (new AMessage(kWhatSeek, id()))->post(5000000ll);
+ } else if (what == ACodec::kWhatOutputFormatChanged) {
+ } else if (what == ACodec::kWhatShutdownCompleted) {
+ mDecodeLooper->unregisterHandler(mCodec->id());
+
+ if (mDecodeLooper != looper()) {
+ mDecodeLooper->stop();
+ }
+
+ looper()->stop();
+ } else if (what == ACodec::kWhatError) {
+ ALOGE("something went wrong, codec reported an error.");
+
+ printf("E\n");
+
+ (new AMessage(kWhatStop, id()))->post();
+ }
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+ }
+
+private:
+ enum {
+ kWhatStart = 'strt',
+ kWhatStop = 'stop',
+ kWhatCodecNotify = 'noti',
+ kWhatSeek = 'seek',
+ };
+
+ sp<ALooper> mDecodeLooper;
+
+ AString mURI;
+ bool mDecodeAudio;
+ sp<Surface> mSurface;
+ bool mRenderToSurface;
+ sp<ACodec> mCodec;
+ sp<MediaSource> mSource;
+ bool mIsVorbis;
+
+ Vector<sp<ABuffer> > mCSD;
+ size_t mCSDIndex;
+
+ MediaBuffer *mLeftOverBuffer;
+ status_t mFinalResult;
+
+ int64_t mStartTimeUs;
+ int32_t mNumOutputBuffersReceived;
+ int64_t mTotalBytesReceived;
+
+ enum SeekState {
+ SEEK_NONE,
+ SEEK_FLUSHING,
+ SEEK_FLUSH_COMPLETED,
+ };
+ SeekState mSeekState;
+ int64_t mSeekTimeUs;
+
+ sp<AMessage> makeFormat(const sp<MetaData> &meta) {
+ CHECK(mCSD.isEmpty());
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ sp<AMessage> msg = new AMessage;
+ msg->setString("mime", mime);
+
+ if (!strncasecmp("video/", mime, 6)) {
+ int32_t width, height;
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+
+ msg->setInt32("width", width);
+ msg->setInt32("height", height);
+ } else {
+ CHECK(!strncasecmp("audio/", mime, 6));
+
+ int32_t numChannels, sampleRate;
+ CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
+ CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+
+ msg->setInt32("channel-count", numChannels);
+ msg->setInt32("sample-rate", sampleRate);
+
+ int32_t isADTS;
+ if (meta->findInt32(kKeyIsADTS, &isADTS) && isADTS != 0) {
+ msg->setInt32("is-adts", true);
+ }
+ }
+
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (meta->findData(kKeyAVCC, &type, &data, &size)) {
+ // Parse the AVCDecoderConfigurationRecord
+
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ CHECK(size >= 7);
+ CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
+ uint8_t profile = ptr[1];
+ uint8_t level = ptr[3];
+
+ // There is decodable content out there that fails the following
+ // assertion, let's be lenient for now...
+ // CHECK((ptr[4] >> 2) == 0x3f); // reserved
+
+ size_t lengthSize = 1 + (ptr[4] & 3);
+
+ // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
+ // violates it...
+ // CHECK((ptr[5] >> 5) == 7); // reserved
+
+ size_t numSeqParameterSets = ptr[5] & 31;
+
+ ptr += 6;
+ size -= 6;
+
+ sp<ABuffer> buffer = new ABuffer(1024);
+ buffer->setRange(0, 0);
+
+ for (size_t i = 0; i < numSeqParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ CHECK(size >= length);
+
+ memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
+ memcpy(buffer->data() + buffer->size() + 4, ptr, length);
+ buffer->setRange(0, buffer->size() + 4 + length);
+
+ ptr += length;
+ size -= length;
+ }
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
+
+ buffer = new ABuffer(1024);
+ buffer->setRange(0, 0);
+
+ CHECK(size >= 1);
+ size_t numPictureParameterSets = *ptr;
+ ++ptr;
+ --size;
+
+ for (size_t i = 0; i < numPictureParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ CHECK(size >= length);
+
+ memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
+ memcpy(buffer->data() + buffer->size() + 4, ptr, length);
+ buffer->setRange(0, buffer->size() + 4 + length);
+
+ ptr += length;
+ size -= length;
+ }
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
+
+ msg->setBuffer("csd", buffer);
+ } else if (meta->findData(kKeyESDS, &type, &data, &size)) {
+ ESDS esds((const char *)data, size);
+ CHECK_EQ(esds.InitCheck(), (status_t)OK);
+
+ const void *codec_specific_data;
+ size_t codec_specific_data_size;
+ esds.getCodecSpecificInfo(
+ &codec_specific_data, &codec_specific_data_size);
+
+ sp<ABuffer> buffer = new ABuffer(codec_specific_data_size);
+
+ memcpy(buffer->data(), codec_specific_data,
+ codec_specific_data_size);
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
+ } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
+ sp<ABuffer> buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
+
+ CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
+
+ buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
+ }
+
+ int32_t maxInputSize;
+ if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
+ msg->setInt32("max-input-size", maxInputSize);
+ }
+
+ return msg;
+ }
+
+ void onFillThisBuffer(const sp<AMessage> &msg) {
+ sp<AMessage> reply;
+ CHECK(msg->findMessage("reply", &reply));
+
+ if (mSource == NULL || mSeekState == SEEK_FLUSHING) {
+ reply->setInt32("err", ERROR_END_OF_STREAM);
+ reply->post();
+ return;
+ }
+
+ sp<ABuffer> outBuffer;
+ CHECK(msg->findBuffer("buffer", &outBuffer));
+
+ if (mCSDIndex < mCSD.size()) {
+ outBuffer = mCSD.editItemAt(mCSDIndex++);
+ outBuffer->meta()->setInt64("timeUs", 0);
+ } else {
+ size_t sizeLeft = outBuffer->capacity();
+ outBuffer->setRange(0, 0);
+
+ int32_t n = 0;
+
+ for (;;) {
+ MediaBuffer *inBuffer;
+
+ if (mLeftOverBuffer != NULL) {
+ inBuffer = mLeftOverBuffer;
+ mLeftOverBuffer = NULL;
+ } else if (mFinalResult != OK) {
+ break;
+ } else {
+ MediaSource::ReadOptions options;
+ if (mSeekState == SEEK_FLUSH_COMPLETED) {
+ options.setSeekTo(mSeekTimeUs);
+ mSeekState = SEEK_NONE;
+ }
+ status_t err = mSource->read(&inBuffer, &options);
+
+ if (err != OK) {
+ mFinalResult = err;
+ break;
+ }
+ }
+
+ size_t sizeNeeded = inBuffer->range_length();
+ if (mIsVorbis) {
+ // Vorbis data is suffixed with the number of
+ // valid samples on the page.
+ sizeNeeded += sizeof(int32_t);
+ }
+
+ if (sizeNeeded > sizeLeft) {
+ if (outBuffer->size() == 0) {
+ ALOGE("Unable to fit even a single input buffer of size %d.",
+ sizeNeeded);
+ }
+ CHECK_GT(outBuffer->size(), 0u);
+
+ mLeftOverBuffer = inBuffer;
+ break;
+ }
+
+ ++n;
+
+ if (outBuffer->size() == 0) {
+ int64_t timeUs;
+ CHECK(inBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+
+ outBuffer->meta()->setInt64("timeUs", timeUs);
+ }
+
+ memcpy(outBuffer->data() + outBuffer->size(),
+ (const uint8_t *)inBuffer->data()
+ + inBuffer->range_offset(),
+ inBuffer->range_length());
+
+ if (mIsVorbis) {
+ int32_t numPageSamples;
+ if (!inBuffer->meta_data()->findInt32(
+ kKeyValidSamples, &numPageSamples)) {
+ numPageSamples = -1;
+ }
+
+ memcpy(outBuffer->data()
+ + outBuffer->size() + inBuffer->range_length(),
+ &numPageSamples, sizeof(numPageSamples));
+ }
+
+ outBuffer->setRange(
+ 0, outBuffer->size() + sizeNeeded);
+
+ sizeLeft -= sizeNeeded;
+
+ inBuffer->release();
+ inBuffer = NULL;
+
+ break; // Don't coalesce
+ }
+
+ ALOGV("coalesced %d input buffers", n);
+
+ if (outBuffer->size() == 0) {
+ CHECK_NE(mFinalResult, (status_t)OK);
+
+ reply->setInt32("err", mFinalResult);
+ reply->post();
+ return;
+ }
+ }
+
+ reply->setBuffer("buffer", outBuffer);
+ reply->post();
+ }
+
+ void onDrainThisBuffer(const sp<AMessage> &msg) {
+ sp<ABuffer> buffer;
+ CHECK(msg->findBuffer("buffer", &buffer));
+
+ mTotalBytesReceived += buffer->size();
+
+ sp<AMessage> reply;
+ CHECK(msg->findMessage("reply", &reply));
+
+ if (mRenderToSurface) {
+ reply->setInt32("render", 1);
+ }
+
+ reply->post();
+ }
+
+ DISALLOW_EVIL_CONSTRUCTORS(Controller);
+};
+
+static void usage(const char *me) {
+ fprintf(stderr, "usage: %s\n", me);
+ fprintf(stderr, " -h(elp)\n");
+ fprintf(stderr, " -a(udio)\n");
+
+ fprintf(stderr,
+ " -S(urface) Allocate output buffers on a surface.\n"
+ " -R(ender) Render surface-allocated buffers.\n");
+}
+
+int main(int argc, char **argv) {
+ android::ProcessState::self()->startThreadPool();
+
+ bool decodeAudio = false;
+ bool useSurface = false;
+ bool renderToSurface = false;
+
+ int res;
+ while ((res = getopt(argc, argv, "haSR")) >= 0) {
+ switch (res) {
+ case 'a':
+ decodeAudio = true;
+ break;
+
+ case 'S':
+ useSurface = true;
+ break;
+
+ case 'R':
+ renderToSurface = true;
+ break;
+
+ case '?':
+ case 'h':
+ default:
+ {
+ usage(argv[0]);
+ return 1;
+ }
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1) {
+ usage(argv[-optind]);
+ return 1;
+ }
+
+ DataSource::RegisterDefaultSniffers();
+
+ sp<ALooper> looper = new ALooper;
+ looper->setName("sf2");
+
+ sp<SurfaceComposerClient> composerClient;
+ sp<SurfaceControl> control;
+ sp<Surface> surface;
+
+ if (!decodeAudio && useSurface) {
+ composerClient = new SurfaceComposerClient;
+ CHECK_EQ(composerClient->initCheck(), (status_t)OK);
+
+ control = composerClient->createSurface(
+ String8("A Surface"),
+ 0,
+ 1280,
+ 800,
+ PIXEL_FORMAT_RGB_565,
+ 0);
+
+ CHECK(control != NULL);
+ CHECK(control->isValid());
+
+ SurfaceComposerClient::openGlobalTransaction();
+ CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK);
+ CHECK_EQ(control->show(), (status_t)OK);
+ SurfaceComposerClient::closeGlobalTransaction();
+
+ surface = control->getSurface();
+ CHECK(surface != NULL);
+
+ CHECK_EQ((status_t)OK,
+ native_window_api_connect(
+ surface.get(), NATIVE_WINDOW_API_MEDIA));
+ }
+
+ sp<Controller> controller =
+ new Controller(argv[0], decodeAudio, surface, renderToSurface);
+
+ looper->registerHandler(controller);
+
+ controller->startAsync();
+
+ CHECK_EQ(looper->start(true /* runOnCallingThread */), (status_t)OK);
+
+ looper->unregisterHandler(controller->id());
+
+ if (!decodeAudio && useSurface) {
+ CHECK_EQ((status_t)OK,
+ native_window_api_disconnect(
+ surface.get(), NATIVE_WINDOW_API_MEDIA));
+
+ composerClient->dispose();
+ }
+
+ return 0;
+}
+
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
new file mode 100644
index 0000000..d70c862
--- /dev/null
+++ b/cmds/stagefright/stagefright.cpp
@@ -0,0 +1,1108 @@
+/*
+ * 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 "stagefright"
+#include <media/stagefright/foundation/ADebug.h>
+
+#include <sys/time.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "jpeg.h"
+#include "SineSource.h"
+
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <media/IMediaPlayerService.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include "include/LiveSession.h"
+#include "include/NuCachedSource2.h"
+#include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/JPEGSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#include <media/mediametadataretriever.h>
+
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MPEG2TSWriter.h>
+#include <media/stagefright/MPEG4Writer.h>
+
+#include <private/media/VideoFrame.h>
+
+#include <fcntl.h>
+
+#include <gui/SurfaceTextureClient.h>
+#include <gui/SurfaceComposerClient.h>
+
+using namespace android;
+
+static long gNumRepetitions;
+static long gMaxNumFrames; // 0 means decode all available.
+static long gReproduceBug; // if not -1.
+static bool gPreferSoftwareCodec;
+static bool gForceToUseHardwareCodec;
+static bool gPlaybackAudio;
+static bool gWriteMP4;
+static bool gDisplayHistogram;
+static String8 gWriteMP4Filename;
+
+static sp<ANativeWindow> gSurface;
+
+static int64_t getNowUs() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
+}
+
+static int CompareIncreasing(const int64_t *a, const int64_t *b) {
+ return (*a) < (*b) ? -1 : (*a) > (*b) ? 1 : 0;
+}
+
+static void displayDecodeHistogram(Vector<int64_t> *decodeTimesUs) {
+ printf("decode times:\n");
+
+ decodeTimesUs->sort(CompareIncreasing);
+
+ size_t n = decodeTimesUs->size();
+ int64_t minUs = decodeTimesUs->itemAt(0);
+ int64_t maxUs = decodeTimesUs->itemAt(n - 1);
+
+ printf("min decode time %lld us (%.2f secs)\n", minUs, minUs / 1E6);
+ printf("max decode time %lld us (%.2f secs)\n", maxUs, maxUs / 1E6);
+
+ size_t counts[100];
+ for (size_t i = 0; i < 100; ++i) {
+ counts[i] = 0;
+ }
+
+ for (size_t i = 0; i < n; ++i) {
+ int64_t x = decodeTimesUs->itemAt(i);
+
+ size_t slot = ((x - minUs) * 100) / (maxUs - minUs);
+ if (slot == 100) { slot = 99; }
+
+ ++counts[slot];
+ }
+
+ for (size_t i = 0; i < 100; ++i) {
+ int64_t slotUs = minUs + (i * (maxUs - minUs) / 100);
+
+ double fps = 1E6 / slotUs;
+ printf("[%.2f fps]: %d\n", fps, counts[i]);
+ }
+}
+
+static void displayAVCProfileLevelIfPossible(const sp<MetaData>& meta) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (meta->findData(kKeyAVCC, &type, &data, &size)) {
+ const uint8_t *ptr = (const uint8_t *)data;
+ CHECK(size >= 7);
+ CHECK(ptr[0] == 1); // configurationVersion == 1
+ uint8_t profile = ptr[1];
+ uint8_t level = ptr[3];
+ fprintf(stderr, "AVC video profile %d and level %d\n", profile, level);
+ }
+}
+
+static void dumpSource(const sp<MediaSource> &source, const String8 &filename) {
+ FILE *out = fopen(filename.string(), "wb");
+
+ CHECK_EQ((status_t)OK, source->start());
+
+ status_t err;
+ for (;;) {
+ MediaBuffer *mbuf;
+ err = source->read(&mbuf);
+
+ if (err == INFO_FORMAT_CHANGED) {
+ continue;
+ } else if (err != OK) {
+ break;
+ }
+
+ CHECK_EQ(
+ fwrite((const uint8_t *)mbuf->data() + mbuf->range_offset(),
+ 1,
+ mbuf->range_length(),
+ out),
+ (ssize_t)mbuf->range_length());
+
+ mbuf->release();
+ mbuf = NULL;
+ }
+
+ CHECK_EQ((status_t)OK, source->stop());
+
+ fclose(out);
+ out = NULL;
+}
+
+static void playSource(OMXClient *client, sp<MediaSource> &source) {
+ sp<MetaData> meta = source->getFormat();
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ sp<MediaSource> rawSource;
+ if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime)) {
+ rawSource = source;
+ } else {
+ int flags = 0;
+ if (gPreferSoftwareCodec) {
+ flags |= OMXCodec::kPreferSoftwareCodecs;
+ }
+ if (gForceToUseHardwareCodec) {
+ CHECK(!gPreferSoftwareCodec);
+ flags |= OMXCodec::kHardwareCodecsOnly;
+ }
+ rawSource = OMXCodec::Create(
+ client->interface(), meta, false /* createEncoder */, source,
+ NULL /* matchComponentName */,
+ flags,
+ gSurface);
+
+ if (rawSource == NULL) {
+ fprintf(stderr, "Failed to instantiate decoder for '%s'.\n", mime);
+ return;
+ }
+ displayAVCProfileLevelIfPossible(meta);
+ }
+
+ source.clear();
+
+ status_t err = rawSource->start();
+
+ if (err != OK) {
+ fprintf(stderr, "rawSource returned error %d (0x%08x)\n", err, err);
+ return;
+ }
+
+ if (gPlaybackAudio) {
+ AudioPlayer *player = new AudioPlayer(NULL);
+ player->setSource(rawSource);
+ rawSource.clear();
+
+ player->start(true /* sourceAlreadyStarted */);
+
+ status_t finalStatus;
+ while (!player->reachedEOS(&finalStatus)) {
+ usleep(100000ll);
+ }
+
+ delete player;
+ player = NULL;
+
+ return;
+ } else if (gReproduceBug >= 3 && gReproduceBug <= 5) {
+ int64_t durationUs;
+ CHECK(meta->findInt64(kKeyDuration, &durationUs));
+
+ status_t err;
+ MediaBuffer *buffer;
+ MediaSource::ReadOptions options;
+ int64_t seekTimeUs = -1;
+ for (;;) {
+ err = rawSource->read(&buffer, &options);
+ options.clearSeekTo();
+
+ bool shouldSeek = false;
+ if (err == INFO_FORMAT_CHANGED) {
+ CHECK(buffer == NULL);
+
+ printf("format changed.\n");
+ continue;
+ } else if (err != OK) {
+ printf("reached EOF.\n");
+
+ shouldSeek = true;
+ } else {
+ int64_t timestampUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
+
+ bool failed = false;
+
+ if (seekTimeUs >= 0) {
+ int64_t diff = timestampUs - seekTimeUs;
+
+ if (diff < 0) {
+ diff = -diff;
+ }
+
+ if ((gReproduceBug == 4 && diff > 500000)
+ || (gReproduceBug == 5 && timestampUs < 0)) {
+ printf("wanted: %.2f secs, got: %.2f secs\n",
+ seekTimeUs / 1E6, timestampUs / 1E6);
+
+ printf("ERROR: ");
+ failed = true;
+ }
+ }
+
+ printf("buffer has timestamp %lld us (%.2f secs)\n",
+ timestampUs, timestampUs / 1E6);
+
+ buffer->release();
+ buffer = NULL;
+
+ if (failed) {
+ break;
+ }
+
+ shouldSeek = ((double)rand() / RAND_MAX) < 0.1;
+
+ if (gReproduceBug == 3) {
+ shouldSeek = false;
+ }
+ }
+
+ seekTimeUs = -1;
+
+ if (shouldSeek) {
+ seekTimeUs = (rand() * (float)durationUs) / RAND_MAX;
+ options.setSeekTo(seekTimeUs);
+
+ printf("seeking to %lld us (%.2f secs)\n",
+ seekTimeUs, seekTimeUs / 1E6);
+ }
+ }
+
+ rawSource->stop();
+
+ return;
+ }
+
+ int n = 0;
+ int64_t startTime = getNowUs();
+
+ long numIterationsLeft = gNumRepetitions;
+ MediaSource::ReadOptions options;
+
+ int64_t sumDecodeUs = 0;
+ int64_t totalBytes = 0;
+
+ Vector<int64_t> decodeTimesUs;
+
+ while (numIterationsLeft-- > 0) {
+ long numFrames = 0;
+
+ MediaBuffer *buffer;
+
+ for (;;) {
+ int64_t startDecodeUs = getNowUs();
+ status_t err = rawSource->read(&buffer, &options);
+ int64_t delayDecodeUs = getNowUs() - startDecodeUs;
+
+ options.clearSeekTo();
+
+ if (err != OK) {
+ CHECK(buffer == NULL);
+
+ if (err == INFO_FORMAT_CHANGED) {
+ printf("format changed.\n");
+ continue;
+ }
+
+ break;
+ }
+
+ if (buffer->range_length() > 0) {
+ if (gDisplayHistogram && n > 0) {
+ // Ignore the first time since it includes some setup
+ // cost.
+ decodeTimesUs.push(delayDecodeUs);
+ }
+
+ if ((n++ % 16) == 0) {
+ printf(".");
+ fflush(stdout);
+ }
+ }
+
+ sumDecodeUs += delayDecodeUs;
+ totalBytes += buffer->range_length();
+
+ buffer->release();
+ buffer = NULL;
+
+ ++numFrames;
+ if (gMaxNumFrames > 0 && numFrames == gMaxNumFrames) {
+ break;
+ }
+
+ if (gReproduceBug == 1 && numFrames == 40) {
+ printf("seeking past the end now.");
+ options.setSeekTo(0x7fffffffL);
+ } else if (gReproduceBug == 2 && numFrames == 40) {
+ printf("seeking to 5 secs.");
+ options.setSeekTo(5000000);
+ }
+ }
+
+ printf("$");
+ fflush(stdout);
+
+ options.setSeekTo(0);
+ }
+
+ rawSource->stop();
+ printf("\n");
+
+ int64_t delay = getNowUs() - startTime;
+ if (!strncasecmp("video/", mime, 6)) {
+ printf("avg. %.2f fps\n", n * 1E6 / delay);
+
+ printf("avg. time to decode one buffer %.2f usecs\n",
+ (double)sumDecodeUs / n);
+
+ printf("decoded a total of %d frame(s).\n", n);
+
+ if (gDisplayHistogram) {
+ displayDecodeHistogram(&decodeTimesUs);
+ }
+ } else if (!strncasecmp("audio/", mime, 6)) {
+ // Frame count makes less sense for audio, as the output buffer
+ // sizes may be different across decoders.
+ printf("avg. %.2f KB/sec\n", totalBytes / 1024 * 1E6 / delay);
+
+ printf("decoded a total of %lld bytes\n", totalBytes);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct DetectSyncSource : public MediaSource {
+ DetectSyncSource(const sp<MediaSource> &source);
+
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop();
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options);
+
+private:
+ enum StreamType {
+ AVC,
+ MPEG4,
+ H263,
+ OTHER,
+ };
+
+ sp<MediaSource> mSource;
+ StreamType mStreamType;
+ bool mSawFirstIDRFrame;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DetectSyncSource);
+};
+
+DetectSyncSource::DetectSyncSource(const sp<MediaSource> &source)
+ : mSource(source),
+ mStreamType(OTHER),
+ mSawFirstIDRFrame(false) {
+ const char *mime;
+ CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ mStreamType = AVC;
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)) {
+ mStreamType = MPEG4;
+ CHECK(!"sync frame detection not implemented yet for MPEG4");
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) {
+ mStreamType = H263;
+ CHECK(!"sync frame detection not implemented yet for H.263");
+ }
+}
+
+status_t DetectSyncSource::start(MetaData *params) {
+ mSawFirstIDRFrame = false;
+
+ return mSource->start(params);
+}
+
+status_t DetectSyncSource::stop() {
+ return mSource->stop();
+}
+
+sp<MetaData> DetectSyncSource::getFormat() {
+ return mSource->getFormat();
+}
+
+static bool isIDRFrame(MediaBuffer *buffer) {
+ const uint8_t *data =
+ (const uint8_t *)buffer->data() + buffer->range_offset();
+ size_t size = buffer->range_length();
+ for (size_t i = 0; i + 3 < size; ++i) {
+ if (!memcmp("\x00\x00\x01", &data[i], 3)) {
+ uint8_t nalType = data[i + 3] & 0x1f;
+ if (nalType == 5) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+status_t DetectSyncSource::read(
+ MediaBuffer **buffer, const ReadOptions *options) {
+ for (;;) {
+ status_t err = mSource->read(buffer, options);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (mStreamType == AVC) {
+ bool isIDR = isIDRFrame(*buffer);
+ (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, isIDR);
+ if (isIDR) {
+ mSawFirstIDRFrame = true;
+ }
+ } else {
+ (*buffer)->meta_data()->setInt32(kKeyIsSyncFrame, true);
+ }
+
+ if (mStreamType != AVC || mSawFirstIDRFrame) {
+ break;
+ }
+
+ // Ignore everything up to the first IDR frame.
+ (*buffer)->release();
+ *buffer = NULL;
+ }
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+static void writeSourcesToMP4(
+ Vector<sp<MediaSource> > &sources, bool syncInfoPresent) {
+#if 0
+ sp<MPEG4Writer> writer =
+ new MPEG4Writer(gWriteMP4Filename.string());
+#else
+ sp<MPEG2TSWriter> writer =
+ new MPEG2TSWriter(gWriteMP4Filename.string());
+#endif
+
+ // at most one minute.
+ writer->setMaxFileDuration(60000000ll);
+
+ for (size_t i = 0; i < sources.size(); ++i) {
+ sp<MediaSource> source = sources.editItemAt(i);
+
+ CHECK_EQ(writer->addSource(
+ syncInfoPresent ? source : new DetectSyncSource(source)),
+ (status_t)OK);
+ }
+
+ sp<MetaData> params = new MetaData;
+ params->setInt32(kKeyNotRealTime, true);
+ CHECK_EQ(writer->start(params.get()), (status_t)OK);
+
+ while (!writer->reachedEOS()) {
+ usleep(100000);
+ }
+ writer->stop();
+}
+
+static void performSeekTest(const sp<MediaSource> &source) {
+ CHECK_EQ((status_t)OK, source->start());
+
+ int64_t durationUs;
+ CHECK(source->getFormat()->findInt64(kKeyDuration, &durationUs));
+
+ for (int64_t seekTimeUs = 0; seekTimeUs <= durationUs;
+ seekTimeUs += 60000ll) {
+ MediaSource::ReadOptions options;
+ options.setSeekTo(
+ seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
+
+ MediaBuffer *buffer;
+ status_t err;
+ for (;;) {
+ err = source->read(&buffer, &options);
+
+ options.clearSeekTo();
+
+ if (err == INFO_FORMAT_CHANGED) {
+ CHECK(buffer == NULL);
+ continue;
+ }
+
+ if (err != OK) {
+ CHECK(buffer == NULL);
+ break;
+ }
+
+ if (buffer->range_length() > 0) {
+ break;
+ }
+
+ CHECK(buffer != NULL);
+
+ buffer->release();
+ buffer = NULL;
+ }
+
+ if (err == OK) {
+ int64_t timeUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+
+ printf("%lld\t%lld\t%lld\n", seekTimeUs, timeUs, seekTimeUs - timeUs);
+
+ buffer->release();
+ buffer = NULL;
+ } else {
+ printf("ERROR\n");
+ break;
+ }
+ }
+
+ CHECK_EQ((status_t)OK, source->stop());
+}
+
+static void usage(const char *me) {
+ fprintf(stderr, "usage: %s\n", me);
+ fprintf(stderr, " -h(elp)\n");
+ fprintf(stderr, " -a(udio)\n");
+ fprintf(stderr, " -n repetitions\n");
+ fprintf(stderr, " -l(ist) components\n");
+ fprintf(stderr, " -m max-number-of-frames-to-decode in each pass\n");
+ fprintf(stderr, " -b bug to reproduce\n");
+ fprintf(stderr, " -p(rofiles) dump decoder profiles supported\n");
+ fprintf(stderr, " -t(humbnail) extract video thumbnail or album art\n");
+ fprintf(stderr, " -s(oftware) prefer software codec\n");
+ fprintf(stderr, " -r(hardware) force to use hardware codec\n");
+ fprintf(stderr, " -o playback audio\n");
+ fprintf(stderr, " -w(rite) filename (write to .mp4 file)\n");
+ fprintf(stderr, " -k seek test\n");
+ fprintf(stderr, " -x display a histogram of decoding times/fps "
+ "(video only)\n");
+ fprintf(stderr, " -S allocate buffers from a surface\n");
+ fprintf(stderr, " -T allocate buffers from a surface texture\n");
+ fprintf(stderr, " -d(ump) filename (raw stream data to a file)\n");
+}
+
+int main(int argc, char **argv) {
+ android::ProcessState::self()->startThreadPool();
+
+ bool audioOnly = false;
+ bool listComponents = false;
+ bool dumpProfiles = false;
+ bool extractThumbnail = false;
+ bool seekTest = false;
+ bool useSurfaceAlloc = false;
+ bool useSurfaceTexAlloc = false;
+ bool dumpStream = false;
+ String8 dumpStreamFilename;
+ gNumRepetitions = 1;
+ gMaxNumFrames = 0;
+ gReproduceBug = -1;
+ gPreferSoftwareCodec = false;
+ gForceToUseHardwareCodec = false;
+ gPlaybackAudio = false;
+ gWriteMP4 = false;
+ gDisplayHistogram = false;
+
+ sp<ALooper> looper;
+ sp<LiveSession> liveSession;
+
+ int res;
+ while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxSTd:")) >= 0) {
+ switch (res) {
+ case 'a':
+ {
+ audioOnly = true;
+ break;
+ }
+
+ case 'd':
+ {
+ dumpStream = true;
+ dumpStreamFilename.setTo(optarg);
+ break;
+ }
+
+ case 'l':
+ {
+ listComponents = true;
+ break;
+ }
+
+ case 'm':
+ case 'n':
+ case 'b':
+ {
+ char *end;
+ long x = strtol(optarg, &end, 10);
+
+ if (*end != '\0' || end == optarg || x <= 0) {
+ x = 1;
+ }
+
+ if (res == 'n') {
+ gNumRepetitions = x;
+ } else if (res == 'm') {
+ gMaxNumFrames = x;
+ } else {
+ CHECK_EQ(res, 'b');
+ gReproduceBug = x;
+ }
+ break;
+ }
+
+ case 'w':
+ {
+ gWriteMP4 = true;
+ gWriteMP4Filename.setTo(optarg);
+ break;
+ }
+
+ case 'p':
+ {
+ dumpProfiles = true;
+ break;
+ }
+
+ case 't':
+ {
+ extractThumbnail = true;
+ break;
+ }
+
+ case 's':
+ {
+ gPreferSoftwareCodec = true;
+ break;
+ }
+
+ case 'r':
+ {
+ gForceToUseHardwareCodec = true;
+ break;
+ }
+
+ case 'o':
+ {
+ gPlaybackAudio = true;
+ break;
+ }
+
+ case 'k':
+ {
+ seekTest = true;
+ break;
+ }
+
+ case 'x':
+ {
+ gDisplayHistogram = true;
+ break;
+ }
+
+ case 'S':
+ {
+ useSurfaceAlloc = true;
+ break;
+ }
+
+ case 'T':
+ {
+ useSurfaceTexAlloc = true;
+ break;
+ }
+
+ case '?':
+ case 'h':
+ default:
+ {
+ usage(argv[0]);
+ exit(1);
+ break;
+ }
+ }
+ }
+
+ if (gPlaybackAudio && !audioOnly) {
+ // This doesn't make any sense if we're decoding the video track.
+ gPlaybackAudio = false;
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (extractThumbnail) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.player"));
+ sp<IMediaPlayerService> service =
+ interface_cast<IMediaPlayerService>(binder);
+
+ CHECK(service.get() != NULL);
+
+ sp<IMediaMetadataRetriever> retriever =
+ service->createMetadataRetriever(getpid());
+
+ CHECK(retriever != NULL);
+
+ for (int k = 0; k < argc; ++k) {
+ const char *filename = argv[k];
+
+ bool failed = true;
+ CHECK_EQ(retriever->setDataSource(filename), (status_t)OK);
+ sp<IMemory> mem =
+ retriever->getFrameAtTime(-1,
+ MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
+
+ if (mem != NULL) {
+ failed = false;
+ printf("getFrameAtTime(%s) => OK\n", filename);
+
+ VideoFrame *frame = (VideoFrame *)mem->pointer();
+
+ CHECK_EQ(writeJpegFile("/sdcard/out.jpg",
+ (uint8_t *)frame + sizeof(VideoFrame),
+ frame->mWidth, frame->mHeight), 0);
+ }
+
+ {
+ mem = retriever->extractAlbumArt();
+
+ if (mem != NULL) {
+ failed = false;
+ printf("extractAlbumArt(%s) => OK\n", filename);
+ }
+ }
+
+ if (failed) {
+ printf("both getFrameAtTime and extractAlbumArt "
+ "failed on file '%s'.\n", filename);
+ }
+ }
+
+ return 0;
+ }
+
+ if (dumpProfiles) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.player"));
+ sp<IMediaPlayerService> service =
+ interface_cast<IMediaPlayerService>(binder);
+
+ CHECK(service.get() != NULL);
+
+ sp<IOMX> omx = service->getOMX();
+ CHECK(omx.get() != NULL);
+
+ const char *kMimeTypes[] = {
+ MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_MPEG4,
+ MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_AUDIO_AAC,
+ MEDIA_MIMETYPE_AUDIO_AMR_NB, MEDIA_MIMETYPE_AUDIO_AMR_WB,
+ MEDIA_MIMETYPE_AUDIO_MPEG, MEDIA_MIMETYPE_AUDIO_G711_MLAW,
+ MEDIA_MIMETYPE_AUDIO_G711_ALAW, MEDIA_MIMETYPE_AUDIO_VORBIS,
+ MEDIA_MIMETYPE_VIDEO_VPX
+ };
+
+ for (size_t k = 0; k < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]);
+ ++k) {
+ printf("type '%s':\n", kMimeTypes[k]);
+
+ Vector<CodecCapabilities> results;
+ // will retrieve hardware and software codecs
+ CHECK_EQ(QueryCodecs(omx, kMimeTypes[k],
+ true, // queryDecoders
+ &results), (status_t)OK);
+
+ for (size_t i = 0; i < results.size(); ++i) {
+ printf(" decoder '%s' supports ",
+ results[i].mComponentName.string());
+
+ if (results[i].mProfileLevels.size() == 0) {
+ printf("NOTHING.\n");
+ continue;
+ }
+
+ for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) {
+ const CodecProfileLevel &profileLevel =
+ results[i].mProfileLevels[j];
+
+ printf("%s%ld/%ld", j > 0 ? ", " : "",
+ profileLevel.mProfile, profileLevel.mLevel);
+ }
+
+ printf("\n");
+ }
+ }
+ }
+
+ if (listComponents) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.player"));
+ sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+
+ CHECK(service.get() != NULL);
+
+ sp<IOMX> omx = service->getOMX();
+ CHECK(omx.get() != NULL);
+
+ List<IOMX::ComponentInfo> list;
+ omx->listNodes(&list);
+
+ for (List<IOMX::ComponentInfo>::iterator it = list.begin();
+ it != list.end(); ++it) {
+ printf("%s\t Roles: ", (*it).mName.string());
+ for (List<String8>::iterator itRoles = (*it).mRoles.begin() ;
+ itRoles != (*it).mRoles.end() ; ++itRoles) {
+ printf("%s\t", (*itRoles).string());
+ }
+ printf("\n");
+ }
+ }
+
+ sp<SurfaceComposerClient> composerClient;
+ sp<SurfaceControl> control;
+
+ if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
+ if (useSurfaceAlloc) {
+ composerClient = new SurfaceComposerClient;
+ CHECK_EQ(composerClient->initCheck(), (status_t)OK);
+
+ control = composerClient->createSurface(
+ String8("A Surface"),
+ 0,
+ 1280,
+ 800,
+ PIXEL_FORMAT_RGB_565,
+ 0);
+
+ CHECK(control != NULL);
+ CHECK(control->isValid());
+
+ SurfaceComposerClient::openGlobalTransaction();
+ CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK);
+ CHECK_EQ(control->show(), (status_t)OK);
+ SurfaceComposerClient::closeGlobalTransaction();
+
+ gSurface = control->getSurface();
+ CHECK(gSurface != NULL);
+ } else {
+ CHECK(useSurfaceTexAlloc);
+
+ sp<SurfaceTexture> texture = new SurfaceTexture(0 /* tex */);
+ gSurface = new SurfaceTextureClient(texture);
+ }
+
+ CHECK_EQ((status_t)OK,
+ native_window_api_connect(
+ gSurface.get(), NATIVE_WINDOW_API_MEDIA));
+ }
+
+ DataSource::RegisterDefaultSniffers();
+
+ OMXClient client;
+ status_t err = client.connect();
+
+ for (int k = 0; k < argc; ++k) {
+ bool syncInfoPresent = true;
+
+ const char *filename = argv[k];
+
+ sp<DataSource> dataSource = DataSource::CreateFromURI(filename);
+
+ if (strncasecmp(filename, "sine:", 5)
+ && strncasecmp(filename, "httplive://", 11)
+ && dataSource == NULL) {
+ fprintf(stderr, "Unable to create data source.\n");
+ return 1;
+ }
+
+ bool isJPEG = false;
+
+ size_t len = strlen(filename);
+ if (len >= 4 && !strcasecmp(filename + len - 4, ".jpg")) {
+ isJPEG = true;
+ }
+
+ Vector<sp<MediaSource> > mediaSources;
+ sp<MediaSource> mediaSource;
+
+ if (isJPEG) {
+ mediaSource = new JPEGSource(dataSource);
+ if (gWriteMP4) {
+ mediaSources.push(mediaSource);
+ }
+ } else if (!strncasecmp("sine:", filename, 5)) {
+ char *end;
+ long sampleRate = strtol(filename + 5, &end, 10);
+
+ if (end == filename + 5) {
+ sampleRate = 44100;
+ }
+ mediaSource = new SineSource(sampleRate, 1);
+ if (gWriteMP4) {
+ mediaSources.push(mediaSource);
+ }
+ } else {
+ sp<MediaExtractor> extractor;
+
+ if (!strncasecmp("httplive://", filename, 11)) {
+ String8 uri("http://");
+ uri.append(filename + 11);
+
+ if (looper == NULL) {
+ looper = new ALooper;
+ looper->start();
+ }
+ liveSession = new LiveSession;
+ looper->registerHandler(liveSession);
+
+ liveSession->connect(uri.string());
+ dataSource = liveSession->getDataSource();
+
+ extractor =
+ MediaExtractor::Create(
+ dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+
+ syncInfoPresent = false;
+ } else {
+ extractor = MediaExtractor::Create(dataSource);
+
+ if (extractor == NULL) {
+ fprintf(stderr, "could not create extractor.\n");
+ return -1;
+ }
+
+ sp<MetaData> meta = extractor->getMetaData();
+
+ if (meta != NULL) {
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
+ syncInfoPresent = false;
+ }
+ }
+ }
+
+ size_t numTracks = extractor->countTracks();
+
+ if (gWriteMP4) {
+ bool haveAudio = false;
+ bool haveVideo = false;
+ for (size_t i = 0; i < numTracks; ++i) {
+ sp<MediaSource> source = extractor->getTrack(i);
+
+ const char *mime;
+ CHECK(source->getFormat()->findCString(
+ kKeyMIMEType, &mime));
+
+ bool useTrack = false;
+ if (!haveAudio && !strncasecmp("audio/", mime, 6)) {
+ haveAudio = true;
+ useTrack = true;
+ } else if (!haveVideo && !strncasecmp("video/", mime, 6)) {
+ haveVideo = true;
+ useTrack = true;
+ }
+
+ if (useTrack) {
+ mediaSources.push(source);
+
+ if (haveAudio && haveVideo) {
+ break;
+ }
+ }
+ }
+ } else {
+ sp<MetaData> meta;
+ size_t i;
+ for (i = 0; i < numTracks; ++i) {
+ meta = extractor->getTrackMetaData(
+ i, MediaExtractor::kIncludeExtensiveMetaData);
+
+ const char *mime;
+ meta->findCString(kKeyMIMEType, &mime);
+
+ if (audioOnly && !strncasecmp(mime, "audio/", 6)) {
+ break;
+ }
+
+ if (!audioOnly && !strncasecmp(mime, "video/", 6)) {
+ break;
+ }
+
+ meta = NULL;
+ }
+
+ if (meta == NULL) {
+ fprintf(stderr,
+ "No suitable %s track found. The '-a' option will "
+ "target audio tracks only, the default is to target "
+ "video tracks only.\n",
+ audioOnly ? "audio" : "video");
+ return -1;
+ }
+
+ int64_t thumbTimeUs;
+ if (meta->findInt64(kKeyThumbnailTime, &thumbTimeUs)) {
+ printf("thumbnailTime: %lld us (%.2f secs)\n",
+ thumbTimeUs, thumbTimeUs / 1E6);
+ }
+
+ mediaSource = extractor->getTrack(i);
+ }
+ }
+
+ if (gWriteMP4) {
+ writeSourcesToMP4(mediaSources, syncInfoPresent);
+ } else if (dumpStream) {
+ dumpSource(mediaSource, dumpStreamFilename);
+ } else if (seekTest) {
+ performSeekTest(mediaSource);
+ } else {
+ playSource(&client, mediaSource);
+ }
+ }
+
+ if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
+ CHECK_EQ((status_t)OK,
+ native_window_api_disconnect(
+ gSurface.get(), NATIVE_WINDOW_API_MEDIA));
+
+ gSurface.clear();
+
+ if (useSurfaceAlloc) {
+ composerClient->dispose();
+ }
+ }
+
+ client.disconnect();
+
+ return 0;
+}
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
new file mode 100644
index 0000000..efa1445
--- /dev/null
+++ b/cmds/stagefright/stream.cpp
@@ -0,0 +1,375 @@
+/*
+ * 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 "stream"
+#include "utils/Log.h"
+
+#include <binder/ProcessState.h>
+
+#include <media/IStreamSource.h>
+#include <media/mediaplayer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MPEG2TSWriter.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+#include <binder/IServiceManager.h>
+#include <media/IMediaPlayerService.h>
+#include <gui/SurfaceComposerClient.h>
+
+#include <fcntl.h>
+
+using namespace android;
+
+struct MyStreamSource : public BnStreamSource {
+ // Object assumes ownership of fd.
+ MyStreamSource(int fd);
+
+ virtual void setListener(const sp<IStreamListener> &listener);
+ virtual void setBuffers(const Vector<sp<IMemory> > &buffers);
+
+ virtual void onBufferAvailable(size_t index);
+
+protected:
+ virtual ~MyStreamSource();
+
+private:
+ int mFd;
+ off64_t mFileSize;
+ uint64_t mNumPacketsSent;
+
+ sp<IStreamListener> mListener;
+ Vector<sp<IMemory> > mBuffers;
+
+ DISALLOW_EVIL_CONSTRUCTORS(MyStreamSource);
+};
+
+MyStreamSource::MyStreamSource(int fd)
+ : mFd(fd),
+ mFileSize(0),
+ mNumPacketsSent(0) {
+ CHECK_GE(fd, 0);
+
+ mFileSize = lseek64(fd, 0, SEEK_END);
+ lseek64(fd, 0, SEEK_SET);
+}
+
+MyStreamSource::~MyStreamSource() {
+ close(mFd);
+ mFd = -1;
+}
+
+void MyStreamSource::setListener(const sp<IStreamListener> &listener) {
+ mListener = listener;
+}
+
+void MyStreamSource::setBuffers(const Vector<sp<IMemory> > &buffers) {
+ mBuffers = buffers;
+}
+
+void MyStreamSource::onBufferAvailable(size_t index) {
+ CHECK_LT(index, mBuffers.size());
+
+#if 0
+ if (mNumPacketsSent >= 20000) {
+ ALOGI("signalling discontinuity now");
+
+ off64_t offset = 0;
+ CHECK((offset % 188) == 0);
+
+ lseek(mFd, offset, SEEK_SET);
+
+ sp<AMessage> extra = new AMessage;
+ extra->setInt32(IStreamListener::kKeyFormatChange, 0);
+
+ mListener->issueCommand(
+ IStreamListener::DISCONTINUITY, false /* synchronous */, extra);
+
+ mNumPacketsSent = 0;
+ }
+#endif
+
+ sp<IMemory> mem = mBuffers.itemAt(index);
+
+ ssize_t n = read(mFd, mem->pointer(), mem->size());
+ if (n <= 0) {
+ mListener->issueCommand(IStreamListener::EOS, false /* synchronous */);
+ } else {
+ mListener->queueBuffer(index, n);
+
+ mNumPacketsSent += n / 188;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+
+struct MyConvertingStreamSource : public BnStreamSource {
+ MyConvertingStreamSource(const char *filename);
+
+ virtual void setListener(const sp<IStreamListener> &listener);
+ virtual void setBuffers(const Vector<sp<IMemory> > &buffers);
+
+ virtual void onBufferAvailable(size_t index);
+
+protected:
+ virtual ~MyConvertingStreamSource();
+
+private:
+ Mutex mLock;
+ Condition mCondition;
+
+ sp<IStreamListener> mListener;
+ Vector<sp<IMemory> > mBuffers;
+
+ sp<MPEG2TSWriter> mWriter;
+
+ ssize_t mCurrentBufferIndex;
+ size_t mCurrentBufferOffset;
+
+ List<size_t> mBufferQueue;
+
+ static ssize_t WriteDataWrapper(void *me, const void *data, size_t size);
+ ssize_t writeData(const void *data, size_t size);
+
+ DISALLOW_EVIL_CONSTRUCTORS(MyConvertingStreamSource);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+MyConvertingStreamSource::MyConvertingStreamSource(const char *filename)
+ : mCurrentBufferIndex(-1),
+ mCurrentBufferOffset(0) {
+ sp<DataSource> dataSource = DataSource::CreateFromURI(filename);
+ CHECK(dataSource != NULL);
+
+ sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+ CHECK(extractor != NULL);
+
+ mWriter = new MPEG2TSWriter(
+ this, &MyConvertingStreamSource::WriteDataWrapper);
+
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ const sp<MetaData> &meta = extractor->getTrackMetaData(i);
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (strncasecmp("video/", mime, 6) && strncasecmp("audio/", mime, 6)) {
+ continue;
+ }
+
+ CHECK_EQ(mWriter->addSource(extractor->getTrack(i)), (status_t)OK);
+ }
+
+ CHECK_EQ(mWriter->start(), (status_t)OK);
+}
+
+MyConvertingStreamSource::~MyConvertingStreamSource() {
+}
+
+void MyConvertingStreamSource::setListener(
+ const sp<IStreamListener> &listener) {
+ mListener = listener;
+}
+
+void MyConvertingStreamSource::setBuffers(
+ const Vector<sp<IMemory> > &buffers) {
+ mBuffers = buffers;
+}
+
+ssize_t MyConvertingStreamSource::WriteDataWrapper(
+ void *me, const void *data, size_t size) {
+ return static_cast<MyConvertingStreamSource *>(me)->writeData(data, size);
+}
+
+ssize_t MyConvertingStreamSource::writeData(const void *data, size_t size) {
+ size_t totalWritten = 0;
+
+ while (size > 0) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mCurrentBufferIndex < 0) {
+ while (mBufferQueue.empty()) {
+ mCondition.wait(mLock);
+ }
+
+ mCurrentBufferIndex = *mBufferQueue.begin();
+ mCurrentBufferOffset = 0;
+
+ mBufferQueue.erase(mBufferQueue.begin());
+ }
+
+ sp<IMemory> mem = mBuffers.itemAt(mCurrentBufferIndex);
+
+ size_t copy = size;
+ if (copy + mCurrentBufferOffset > mem->size()) {
+ copy = mem->size() - mCurrentBufferOffset;
+ }
+
+ memcpy((uint8_t *)mem->pointer() + mCurrentBufferOffset, data, copy);
+ mCurrentBufferOffset += copy;
+
+ if (mCurrentBufferOffset == mem->size()) {
+ mListener->queueBuffer(mCurrentBufferIndex, mCurrentBufferOffset);
+ mCurrentBufferIndex = -1;
+ }
+
+ data = (const uint8_t *)data + copy;
+ size -= copy;
+
+ totalWritten += copy;
+ }
+
+ return (ssize_t)totalWritten;
+}
+
+void MyConvertingStreamSource::onBufferAvailable(size_t index) {
+ Mutex::Autolock autoLock(mLock);
+
+ mBufferQueue.push_back(index);
+ mCondition.signal();
+
+ if (mWriter->reachedEOS()) {
+ if (mCurrentBufferIndex >= 0) {
+ mListener->queueBuffer(mCurrentBufferIndex, mCurrentBufferOffset);
+ mCurrentBufferIndex = -1;
+ }
+
+ mListener->issueCommand(IStreamListener::EOS, false /* synchronous */);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct MyClient : public BnMediaPlayerClient {
+ MyClient()
+ : mEOS(false) {
+ }
+
+ virtual void notify(int msg, int ext1, int ext2, const Parcel *obj) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (msg == MEDIA_ERROR || msg == MEDIA_PLAYBACK_COMPLETE) {
+ mEOS = true;
+ mCondition.signal();
+ }
+ }
+
+ void waitForEOS() {
+ Mutex::Autolock autoLock(mLock);
+ while (!mEOS) {
+ mCondition.wait(mLock);
+ }
+ }
+
+protected:
+ virtual ~MyClient() {
+ }
+
+private:
+ Mutex mLock;
+ Condition mCondition;
+
+ bool mEOS;
+
+ DISALLOW_EVIL_CONSTRUCTORS(MyClient);
+};
+
+int main(int argc, char **argv) {
+ android::ProcessState::self()->startThreadPool();
+
+ DataSource::RegisterDefaultSniffers();
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s filename\n", argv[0]);
+ return 1;
+ }
+
+ sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
+ CHECK_EQ(composerClient->initCheck(), (status_t)OK);
+
+ ssize_t displayWidth = composerClient->getDisplayWidth(0);
+ ssize_t displayHeight = composerClient->getDisplayHeight(0);
+
+ ALOGV("display is %d x %d\n", displayWidth, displayHeight);
+
+ sp<SurfaceControl> control =
+ composerClient->createSurface(
+ String8("A Surface"),
+ 0,
+ displayWidth,
+ displayHeight,
+ PIXEL_FORMAT_RGB_565,
+ 0);
+
+ CHECK(control != NULL);
+ CHECK(control->isValid());
+
+ SurfaceComposerClient::openGlobalTransaction();
+ CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK);
+ CHECK_EQ(control->show(), (status_t)OK);
+ SurfaceComposerClient::closeGlobalTransaction();
+
+ sp<Surface> surface = control->getSurface();
+ CHECK(surface != NULL);
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.player"));
+ sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+
+ CHECK(service.get() != NULL);
+
+ sp<MyClient> client = new MyClient;
+
+ sp<IStreamSource> source;
+
+ size_t len = strlen(argv[1]);
+ if (len >= 3 && !strcasecmp(".ts", &argv[1][len - 3])) {
+ int fd = open(argv[1], O_RDONLY);
+
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open file '%s'.", argv[1]);
+ return 1;
+ }
+
+ source = new MyStreamSource(fd);
+ } else {
+ printf("Converting file to transport stream for streaming...\n");
+
+ source = new MyConvertingStreamSource(argv[1]);
+ }
+
+ sp<IMediaPlayer> player =
+ service->create(getpid(), client, 0);
+
+ if (player != NULL && player->setDataSource(source) == NO_ERROR) {
+ player->setVideoSurfaceTexture(surface->getSurfaceTexture());
+ player->start();
+
+ client->waitForEOS();
+
+ player->stop();
+ } else {
+ fprintf(stderr, "failed to instantiate player.\n");
+ }
+
+ composerClient->dispose();
+
+ return 0;
+}
diff --git a/drm/common/Android.mk b/drm/common/Android.mk
new file mode 100644
index 0000000..f1136c9
--- /dev/null
+++ b/drm/common/Android.mk
@@ -0,0 +1,43 @@
+#
+# 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.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ DrmConstraints.cpp \
+ DrmMetadata.cpp \
+ DrmConvertedStatus.cpp \
+ DrmEngineBase.cpp \
+ DrmInfo.cpp \
+ DrmInfoRequest.cpp \
+ DrmInfoStatus.cpp \
+ DrmRights.cpp \
+ DrmSupportInfo.cpp \
+ IDrmManagerService.cpp \
+ IDrmServiceListener.cpp \
+ DrmInfoEvent.cpp \
+ ReadWriteUtils.cpp
+
+LOCAL_C_INCLUDES := \
+ $(TOP)/frameworks/base/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/plugins/common/include
+
+LOCAL_MODULE:= libdrmframeworkcommon
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/drm/common/DrmConstraints.cpp b/drm/common/DrmConstraints.cpp
new file mode 100644
index 0000000..4a4d798
--- /dev/null
+++ b/drm/common/DrmConstraints.cpp
@@ -0,0 +1,113 @@
+/*
+ * 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 <drm/DrmConstraints.h>
+
+using namespace android;
+
+const String8 DrmConstraints::MAX_REPEAT_COUNT("max_repeat_count");
+const String8 DrmConstraints::REMAINING_REPEAT_COUNT("remaining_repeat_count");
+const String8 DrmConstraints::LICENSE_START_TIME("license_start_time");
+const String8 DrmConstraints::LICENSE_EXPIRY_TIME("license_expiry_time");
+const String8 DrmConstraints::LICENSE_AVAILABLE_TIME("license_available_time");
+const String8 DrmConstraints::EXTENDED_METADATA("extended_metadata");
+
+int DrmConstraints::getCount(void) const {
+ return mConstraintMap.size();
+}
+
+status_t DrmConstraints::put(const String8* key, const char* value) {
+ int length = strlen(value);
+ char* charValue = new char[length + 1];
+ if (NULL != charValue) {
+ strncpy(charValue, value, length);
+ charValue[length] = '\0';
+ mConstraintMap.add(*key, charValue);
+ }
+ return DRM_NO_ERROR;
+}
+
+String8 DrmConstraints::get(const String8& key) const {
+ if (NULL != getValue(&key)) {
+ return String8(getValue(&key));
+ }
+ return String8("");
+}
+
+const char* DrmConstraints::getValue(const String8* key) const {
+ if (NAME_NOT_FOUND != mConstraintMap.indexOfKey(*key)) {
+ return mConstraintMap.valueFor(*key);
+ }
+ return NULL;
+}
+
+const char* DrmConstraints::getAsByteArray(const String8* key) const {
+ return getValue(key);
+}
+
+bool DrmConstraints::KeyIterator::hasNext() {
+ return mIndex < mDrmConstraints->mConstraintMap.size();
+}
+
+const String8& DrmConstraints::KeyIterator::next() {
+ const String8& key = mDrmConstraints->mConstraintMap.keyAt(mIndex);
+ mIndex++;
+ return key;
+}
+
+DrmConstraints::KeyIterator DrmConstraints::keyIterator() {
+ return KeyIterator(this);
+}
+
+DrmConstraints::KeyIterator::KeyIterator(const DrmConstraints::KeyIterator& keyIterator)
+ : mDrmConstraints(keyIterator.mDrmConstraints),
+ mIndex(keyIterator.mIndex) {
+}
+
+DrmConstraints::KeyIterator& DrmConstraints::KeyIterator::operator=(
+ const DrmConstraints::KeyIterator& keyIterator) {
+ mDrmConstraints = keyIterator.mDrmConstraints;
+ mIndex = keyIterator.mIndex;
+ return *this;
+}
+
+
+DrmConstraints::Iterator DrmConstraints::iterator() {
+ return Iterator(this);
+}
+
+DrmConstraints::Iterator::Iterator(const DrmConstraints::Iterator& iterator) :
+ mDrmConstraints(iterator.mDrmConstraints),
+ mIndex(iterator.mIndex) {
+}
+
+DrmConstraints::Iterator& DrmConstraints::Iterator::operator=(
+ const DrmConstraints::Iterator& iterator) {
+ mDrmConstraints = iterator.mDrmConstraints;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmConstraints::Iterator::hasNext() {
+ return mIndex < mDrmConstraints->mConstraintMap.size();
+}
+
+String8 DrmConstraints::Iterator::next() {
+ String8 value = String8(mDrmConstraints->mConstraintMap.editValueAt(mIndex));
+ mIndex++;
+ return value;
+}
+
diff --git a/drm/common/DrmConvertedStatus.cpp b/drm/common/DrmConvertedStatus.cpp
new file mode 100644
index 0000000..5d035f5
--- /dev/null
+++ b/drm/common/DrmConvertedStatus.cpp
@@ -0,0 +1,28 @@
+/*
+ * 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 <drm/DrmConvertedStatus.h>
+
+using namespace android;
+
+DrmConvertedStatus::DrmConvertedStatus(
+ int _statusCode, const DrmBuffer* _convertedData, int _offset) :
+ statusCode(_statusCode),
+ convertedData(_convertedData),
+ offset(_offset) {
+
+}
+
diff --git a/drm/common/DrmEngineBase.cpp b/drm/common/DrmEngineBase.cpp
new file mode 100644
index 0000000..1c345a2
--- /dev/null
+++ b/drm/common/DrmEngineBase.cpp
@@ -0,0 +1,166 @@
+/*
+ * 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 "DrmEngineBase.h"
+
+using namespace android;
+
+DrmEngineBase::DrmEngineBase() {
+
+}
+
+DrmEngineBase::~DrmEngineBase() {
+
+}
+
+DrmConstraints* DrmEngineBase::getConstraints(
+ int uniqueId, const String8* path, int action) {
+ return onGetConstraints(uniqueId, path, action);
+}
+
+DrmMetadata* DrmEngineBase::getMetadata(int uniqueId, const String8* path) {
+ return onGetMetadata(uniqueId, path);
+}
+
+status_t DrmEngineBase::initialize(int uniqueId) {
+ return onInitialize(uniqueId);
+}
+
+status_t DrmEngineBase::setOnInfoListener(
+ int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
+ return onSetOnInfoListener(uniqueId, infoListener);
+}
+
+status_t DrmEngineBase::terminate(int uniqueId) {
+ return onTerminate(uniqueId);
+}
+
+bool DrmEngineBase::canHandle(int uniqueId, const String8& path) {
+ return onCanHandle(uniqueId, path);
+}
+
+DrmInfoStatus* DrmEngineBase::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ return onProcessDrmInfo(uniqueId, drmInfo);
+}
+
+status_t DrmEngineBase::saveRights(
+ int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ return onSaveRights(uniqueId, drmRights, rightsPath, contentPath);
+}
+
+DrmInfo* DrmEngineBase::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ return onAcquireDrmInfo(uniqueId, drmInfoRequest);
+}
+
+String8 DrmEngineBase::getOriginalMimeType(int uniqueId, const String8& path) {
+ return onGetOriginalMimeType(uniqueId, path);
+}
+
+int DrmEngineBase::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) {
+ return onGetDrmObjectType(uniqueId, path, mimeType);
+}
+
+int DrmEngineBase::checkRightsStatus(int uniqueId, const String8& path, int action) {
+ return onCheckRightsStatus(uniqueId, path, action);
+}
+
+status_t DrmEngineBase::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ return onConsumeRights(uniqueId, decryptHandle, action, reserve);
+}
+
+status_t DrmEngineBase::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) {
+ return onSetPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
+}
+
+bool DrmEngineBase::validateAction(
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ return onValidateAction(uniqueId, path, action, description);
+}
+
+status_t DrmEngineBase::removeRights(int uniqueId, const String8& path) {
+ return onRemoveRights(uniqueId, path);
+}
+
+status_t DrmEngineBase::removeAllRights(int uniqueId) {
+ return onRemoveAllRights(uniqueId);
+}
+
+status_t DrmEngineBase::openConvertSession(int uniqueId, int convertId) {
+ return onOpenConvertSession(uniqueId, convertId);
+}
+
+DrmConvertedStatus* DrmEngineBase::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ return onConvertData(uniqueId, convertId, inputData);
+}
+
+DrmConvertedStatus* DrmEngineBase::closeConvertSession(int uniqueId, int convertId) {
+ return onCloseConvertSession(uniqueId, convertId);
+}
+
+DrmSupportInfo* DrmEngineBase::getSupportInfo(int uniqueId) {
+ return onGetSupportInfo(uniqueId);
+}
+
+status_t DrmEngineBase::openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle,
+ int fd, off64_t offset, off64_t length, const char* mime) {
+
+ if (!mime || mime[0] == '\0') {
+ return onOpenDecryptSession(uniqueId, decryptHandle, fd, offset, length);
+ }
+
+ return onOpenDecryptSession(uniqueId, decryptHandle, fd, offset, length, mime);
+}
+
+status_t DrmEngineBase::openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle,
+ const char* uri, const char* mime) {
+ if (!mime || mime[0] == '\0') {
+ return onOpenDecryptSession(uniqueId, decryptHandle, uri);
+ }
+ return onOpenDecryptSession(uniqueId, decryptHandle, uri, mime);
+}
+
+status_t DrmEngineBase::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ return onCloseDecryptSession(uniqueId, decryptHandle);
+}
+
+status_t DrmEngineBase::initializeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+ return onInitializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo);
+}
+
+status_t DrmEngineBase::decrypt(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ return onDecrypt(uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
+}
+
+status_t DrmEngineBase::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ return onFinalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+}
+
+ssize_t DrmEngineBase::pread(
+ int uniqueId, DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) {
+ return onPread(uniqueId, decryptHandle, buffer, numBytes, offset);
+}
+
diff --git a/drm/common/DrmInfo.cpp b/drm/common/DrmInfo.cpp
new file mode 100644
index 0000000..ddcab33
--- /dev/null
+++ b/drm/common/DrmInfo.cpp
@@ -0,0 +1,111 @@
+/*
+ * 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 <drm/DrmInfo.h>
+
+using namespace android;
+
+DrmInfo::DrmInfo(int infoType, const DrmBuffer& drmBuffer, const String8& mimeType) :
+ mInfoType(infoType),
+ mData(drmBuffer),
+ mMimeType(mimeType) {
+
+}
+
+int DrmInfo::getInfoType(void) const {
+ return mInfoType;
+}
+
+String8 DrmInfo::getMimeType(void) const {
+ return mMimeType;
+}
+
+const DrmBuffer& DrmInfo::getData(void) const {
+ return mData;
+}
+
+int DrmInfo::getCount(void) const {
+ return mAttributes.size();
+}
+
+status_t DrmInfo::put(const String8& key, const String8& value) {
+ mAttributes.add(key, value);
+ return DRM_NO_ERROR;
+}
+
+String8 DrmInfo::get(const String8& key) const {
+ if (NAME_NOT_FOUND != mAttributes.indexOfKey(key)) {
+ return mAttributes.valueFor(key);
+ }
+ return String8("");
+}
+
+int DrmInfo::indexOfKey(const String8& key) const {
+ return mAttributes.indexOfKey(key);
+}
+
+DrmInfo::KeyIterator DrmInfo::keyIterator() const {
+ return KeyIterator(this);
+}
+
+DrmInfo::Iterator DrmInfo::iterator() const {
+ return Iterator(this);
+}
+
+// KeyIterator implementation
+DrmInfo::KeyIterator::KeyIterator(const DrmInfo::KeyIterator& keyIterator) :
+ mDrmInfo(keyIterator.mDrmInfo), mIndex(keyIterator.mIndex) {
+
+}
+
+bool DrmInfo::KeyIterator::hasNext() {
+ return (mIndex < mDrmInfo->mAttributes.size());
+}
+
+const String8& DrmInfo::KeyIterator::next() {
+ const String8& key = mDrmInfo->mAttributes.keyAt(mIndex);
+ mIndex++;
+ return key;
+}
+
+DrmInfo::KeyIterator& DrmInfo::KeyIterator::operator=(const DrmInfo::KeyIterator& keyIterator) {
+ mDrmInfo = keyIterator.mDrmInfo;
+ mIndex = keyIterator.mIndex;
+ return *this;
+}
+
+// Iterator implementation
+DrmInfo::Iterator::Iterator(const DrmInfo::Iterator& iterator)
+ : mDrmInfo(iterator.mDrmInfo), mIndex(iterator.mIndex) {
+
+}
+
+DrmInfo::Iterator& DrmInfo::Iterator::operator=(const DrmInfo::Iterator& iterator) {
+ mDrmInfo = iterator.mDrmInfo;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmInfo::Iterator::hasNext() {
+ return mIndex < mDrmInfo->mAttributes.size();
+}
+
+String8& DrmInfo::Iterator::next() {
+ String8& value = mDrmInfo->mAttributes.editValueAt(mIndex);
+ mIndex++;
+ return value;
+}
+
diff --git a/drm/common/DrmInfoEvent.cpp b/drm/common/DrmInfoEvent.cpp
new file mode 100644
index 0000000..27a5a2d
--- /dev/null
+++ b/drm/common/DrmInfoEvent.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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 <utils/String8.h>
+#include <drm/DrmInfoEvent.h>
+
+using namespace android;
+
+DrmInfoEvent::DrmInfoEvent(int uniqueId, int infoType, const String8 message)
+ : mUniqueId(uniqueId),
+ mInfoType(infoType),
+ mMessage(message) {
+
+}
+
+int DrmInfoEvent::getUniqueId() const {
+ return mUniqueId;
+}
+
+int DrmInfoEvent::getType() const {
+ return mInfoType;
+}
+
+const String8 DrmInfoEvent::getMessage() const {
+ return mMessage;
+}
+
diff --git a/drm/common/DrmInfoRequest.cpp b/drm/common/DrmInfoRequest.cpp
new file mode 100644
index 0000000..a646859
--- /dev/null
+++ b/drm/common/DrmInfoRequest.cpp
@@ -0,0 +1,106 @@
+/*
+ * 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 <drm/DrmInfoRequest.h>
+
+using namespace android;
+
+const String8 DrmInfoRequest::ACCOUNT_ID("account_id");
+const String8 DrmInfoRequest::SUBSCRIPTION_ID("subscription_id");
+
+DrmInfoRequest::DrmInfoRequest(int infoType, const String8& mimeType) :
+ mInfoType(infoType), mMimeType(mimeType) {
+
+}
+
+String8 DrmInfoRequest::getMimeType(void) const {
+ return mMimeType;
+}
+
+int DrmInfoRequest::getInfoType(void) const {
+ return mInfoType;
+}
+
+int DrmInfoRequest::getCount(void) const {
+ return mRequestInformationMap.size();
+}
+
+status_t DrmInfoRequest::put(const String8& key, const String8& value) {
+ mRequestInformationMap.add(key, value);
+ return DRM_NO_ERROR;
+}
+
+String8 DrmInfoRequest::get(const String8& key) const {
+ if (NAME_NOT_FOUND != mRequestInformationMap.indexOfKey(key)) {
+ return mRequestInformationMap.valueFor(key);
+ }
+ return String8("");
+}
+
+DrmInfoRequest::KeyIterator DrmInfoRequest::keyIterator() const {
+ return KeyIterator(this);
+}
+
+DrmInfoRequest::Iterator DrmInfoRequest::iterator() const {
+ return Iterator(this);
+}
+
+// KeyIterator implementation
+DrmInfoRequest::KeyIterator::KeyIterator(const DrmInfoRequest::KeyIterator& keyIterator)
+ : mDrmInfoRequest(keyIterator.mDrmInfoRequest),
+ mIndex(keyIterator.mIndex) {
+
+}
+
+bool DrmInfoRequest::KeyIterator::hasNext() {
+ return (mIndex < mDrmInfoRequest->mRequestInformationMap.size());
+}
+
+const String8& DrmInfoRequest::KeyIterator::next() {
+ const String8& key = mDrmInfoRequest->mRequestInformationMap.keyAt(mIndex);
+ mIndex++;
+ return key;
+}
+
+DrmInfoRequest::KeyIterator& DrmInfoRequest::KeyIterator::operator=(
+ const DrmInfoRequest::KeyIterator& keyIterator) {
+ mDrmInfoRequest = keyIterator.mDrmInfoRequest;
+ mIndex = keyIterator.mIndex;
+ return *this;
+}
+
+// Iterator implementation
+DrmInfoRequest::Iterator::Iterator(const DrmInfoRequest::Iterator& iterator) :
+ mDrmInfoRequest(iterator.mDrmInfoRequest), mIndex(iterator.mIndex) {
+}
+
+DrmInfoRequest::Iterator& DrmInfoRequest::Iterator::operator=(
+ const DrmInfoRequest::Iterator& iterator) {
+ mDrmInfoRequest = iterator.mDrmInfoRequest;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmInfoRequest::Iterator::hasNext() {
+ return mIndex < mDrmInfoRequest->mRequestInformationMap.size();
+}
+
+String8& DrmInfoRequest::Iterator::next() {
+ String8& value = mDrmInfoRequest->mRequestInformationMap.editValueAt(mIndex);
+ mIndex++;
+ return value;
+}
+
diff --git a/drm/common/DrmInfoStatus.cpp b/drm/common/DrmInfoStatus.cpp
new file mode 100644
index 0000000..8ec7311
--- /dev/null
+++ b/drm/common/DrmInfoStatus.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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 <drm/DrmInfoStatus.h>
+
+using namespace android;
+
+DrmInfoStatus::DrmInfoStatus(
+ int _statusCode, int _infoType, const DrmBuffer* _drmBuffer, const String8& _mimeType) :
+ statusCode(_statusCode),
+ infoType(_infoType),
+ drmBuffer(_drmBuffer),
+ mimeType(_mimeType) {
+
+}
+
diff --git a/drm/common/DrmMetadata.cpp b/drm/common/DrmMetadata.cpp
new file mode 100644
index 0000000..2a4b8c8
--- /dev/null
+++ b/drm/common/DrmMetadata.cpp
@@ -0,0 +1,117 @@
+/*
+ * 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 <drm/DrmMetadata.h>
+
+using namespace android;
+
+int DrmMetadata::getCount(void) const {
+ return mMetadataMap.size();
+}
+
+status_t DrmMetadata::put(const String8* key,
+ const char* value) {
+ if((value != NULL) && (key != NULL)) {
+ int length = strlen(value);
+ char* charValue = new char[length + 1];
+
+ memcpy(charValue, value, length);
+ charValue[length] = '\0';
+ mMetadataMap.add(*key, charValue);
+ }
+ return NO_ERROR;
+}
+
+String8 DrmMetadata::get(const String8& key) const {
+ if (NULL != getValue(&key)) {
+ return String8(getValue(&key));
+ }
+ else {
+ return String8("");
+ }
+}
+
+const char* DrmMetadata::getValue(const String8* key) const {
+ if(key != NULL) {
+ if (NAME_NOT_FOUND != mMetadataMap.indexOfKey(*key)) {
+ return mMetadataMap.valueFor(*key);
+ }
+ else {
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+}
+
+const char* DrmMetadata::getAsByteArray(const String8* key) const {
+ return getValue(key);
+}
+
+bool DrmMetadata::KeyIterator::hasNext() {
+ return mIndex < mDrmMetadata->mMetadataMap.size();
+}
+
+const String8& DrmMetadata::KeyIterator::next() {
+ const String8& key = mDrmMetadata->mMetadataMap.keyAt(mIndex);
+ mIndex++;
+ return key;
+}
+
+DrmMetadata::KeyIterator DrmMetadata::keyIterator() {
+ return KeyIterator(this);
+}
+
+DrmMetadata::KeyIterator::KeyIterator(const DrmMetadata::KeyIterator& keyIterator) :
+ mDrmMetadata(keyIterator.mDrmMetadata),
+ mIndex(keyIterator.mIndex) {
+ ALOGV("DrmMetadata::KeyIterator::KeyIterator");
+}
+
+DrmMetadata::KeyIterator& DrmMetadata::KeyIterator::operator=(const DrmMetadata::KeyIterator& keyIterator) {
+ ALOGV("DrmMetadata::KeyIterator::operator=");
+ mDrmMetadata = keyIterator.mDrmMetadata;
+ mIndex = keyIterator.mIndex;
+ return *this;
+}
+
+
+DrmMetadata::Iterator DrmMetadata::iterator() {
+ return Iterator(this);
+}
+
+DrmMetadata::Iterator::Iterator(const DrmMetadata::Iterator& iterator) :
+ mDrmMetadata(iterator.mDrmMetadata),
+ mIndex(iterator.mIndex) {
+ ALOGV("DrmMetadata::Iterator::Iterator");
+}
+
+DrmMetadata::Iterator& DrmMetadata::Iterator::operator=(const DrmMetadata::Iterator& iterator) {
+ ALOGV("DrmMetadata::Iterator::operator=");
+ mDrmMetadata = iterator.mDrmMetadata;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmMetadata::Iterator::hasNext() {
+ return mIndex < mDrmMetadata->mMetadataMap.size();
+}
+
+String8 DrmMetadata::Iterator::next() {
+ String8 value = String8(mDrmMetadata->mMetadataMap.editValueAt(mIndex));
+ mIndex++;
+ return value;
+}
diff --git a/drm/common/DrmRights.cpp b/drm/common/DrmRights.cpp
new file mode 100644
index 0000000..3aecb3d
--- /dev/null
+++ b/drm/common/DrmRights.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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 <drm/DrmRights.h>
+#include <ReadWriteUtils.h>
+
+using namespace android;
+
+DrmRights::DrmRights(const String8& rightsFilePath, const String8& mimeType,
+ const String8& accountId, const String8& subscriptionId) :
+ mMimeType(mimeType),
+ mAccountId(accountId),
+ mSubscriptionId(subscriptionId),
+ mRightsFromFile(NULL) {
+ int rightsLength = 0;
+ if (String8("") != rightsFilePath) {
+ rightsLength = ReadWriteUtils::readBytes(rightsFilePath, &mRightsFromFile);
+ }
+ mData = DrmBuffer(mRightsFromFile, rightsLength);
+}
+
+DrmRights::DrmRights(const DrmBuffer& rightsData, const String8& mimeType,
+ const String8& accountId, const String8& subscriptionId) :
+ mData(rightsData),
+ mMimeType(mimeType),
+ mAccountId(accountId),
+ mSubscriptionId(subscriptionId),
+ mRightsFromFile(NULL) {
+}
+
+DrmRights::~DrmRights() {
+ delete[] mRightsFromFile; mRightsFromFile = NULL;
+}
+
+const DrmBuffer& DrmRights::getData(void) const {
+ return mData;
+}
+
+String8 DrmRights::getMimeType(void) const {
+ return mMimeType;
+}
+
+String8 DrmRights::getAccountId(void) const {
+ return mAccountId;
+}
+
+String8 DrmRights::getSubscriptionId(void) const {
+ return mSubscriptionId;
+}
+
diff --git a/drm/common/DrmSupportInfo.cpp b/drm/common/DrmSupportInfo.cpp
new file mode 100644
index 0000000..5400bdd
--- /dev/null
+++ b/drm/common/DrmSupportInfo.cpp
@@ -0,0 +1,159 @@
+/*
+ * 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 <drm/DrmSupportInfo.h>
+#include <strings.h>
+
+using namespace android;
+
+DrmSupportInfo::DrmSupportInfo() {
+
+}
+
+DrmSupportInfo::DrmSupportInfo(const DrmSupportInfo& drmSupportInfo):
+ mMimeTypeVector(drmSupportInfo.mMimeTypeVector),
+ mFileSuffixVector(drmSupportInfo.mFileSuffixVector),
+ mDescription(drmSupportInfo.mDescription) {
+
+}
+
+bool DrmSupportInfo::operator<(const DrmSupportInfo& drmSupportInfo) const {
+ // Do we need to check mMimeTypeVector & mFileSuffixVector ?
+ // Note Vector doesn't overrides "<" operator
+ return mDescription < drmSupportInfo.mDescription;
+}
+
+bool DrmSupportInfo::operator==(const DrmSupportInfo& drmSupportInfo) const {
+ // Do we need to check mMimeTypeVector & mFileSuffixVector ?
+ // Note Vector doesn't overrides "==" operator
+ return (mDescription == drmSupportInfo.mDescription);
+}
+
+bool DrmSupportInfo::isSupportedMimeType(const String8& mimeType) const {
+ if (String8("") == mimeType) {
+ return false;
+ }
+
+ for (unsigned int i = 0; i < mMimeTypeVector.size(); i++) {
+ const String8 item = mMimeTypeVector.itemAt(i);
+
+ if (!strcasecmp(item.string(), mimeType.string())) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool DrmSupportInfo::isSupportedFileSuffix(const String8& fileType) const {
+ for (unsigned int i = 0; i < mFileSuffixVector.size(); i++) {
+ const String8 item = mFileSuffixVector.itemAt(i);
+
+ if (!strcasecmp(item.string(), fileType.string())) {
+ return true;
+ }
+ }
+ return false;
+}
+
+DrmSupportInfo& DrmSupportInfo::operator=(const DrmSupportInfo& drmSupportInfo) {
+ mMimeTypeVector = drmSupportInfo.mMimeTypeVector;
+ mFileSuffixVector = drmSupportInfo.mFileSuffixVector;
+ mDescription = drmSupportInfo.mDescription;
+ return *this;
+}
+
+int DrmSupportInfo::getMimeTypeCount(void) const {
+ return mMimeTypeVector.size();
+}
+
+int DrmSupportInfo::getFileSuffixCount(void) const {
+ return mFileSuffixVector.size();
+}
+
+status_t DrmSupportInfo::addMimeType(const String8& mimeType) {
+ mMimeTypeVector.push(mimeType);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmSupportInfo::addFileSuffix(const String8& fileSuffix) {
+ mFileSuffixVector.push(fileSuffix);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmSupportInfo::setDescription(const String8& description) {
+ mDescription = description;
+ return DRM_NO_ERROR;
+}
+
+String8 DrmSupportInfo::getDescription() const {
+ return mDescription;
+}
+
+DrmSupportInfo::FileSuffixIterator DrmSupportInfo::getFileSuffixIterator() {
+ return FileSuffixIterator(this);
+}
+
+DrmSupportInfo::MimeTypeIterator DrmSupportInfo::getMimeTypeIterator() {
+ return MimeTypeIterator(this);
+}
+
+DrmSupportInfo::FileSuffixIterator::FileSuffixIterator(
+ const DrmSupportInfo::FileSuffixIterator& iterator) :
+ mDrmSupportInfo(iterator.mDrmSupportInfo),
+ mIndex(iterator.mIndex) {
+
+}
+
+DrmSupportInfo::FileSuffixIterator& DrmSupportInfo::FileSuffixIterator::operator=(
+ const DrmSupportInfo::FileSuffixIterator& iterator) {
+ mDrmSupportInfo = iterator.mDrmSupportInfo;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmSupportInfo::FileSuffixIterator::hasNext() {
+ return mIndex < mDrmSupportInfo->mFileSuffixVector.size();
+}
+
+String8& DrmSupportInfo::FileSuffixIterator::next() {
+ String8& value = mDrmSupportInfo->mFileSuffixVector.editItemAt(mIndex);
+ mIndex++;
+ return value;
+}
+
+DrmSupportInfo::MimeTypeIterator::MimeTypeIterator(
+ const DrmSupportInfo::MimeTypeIterator& iterator) :
+ mDrmSupportInfo(iterator.mDrmSupportInfo),
+ mIndex(iterator.mIndex) {
+
+}
+
+DrmSupportInfo::MimeTypeIterator& DrmSupportInfo::MimeTypeIterator::operator=(
+ const DrmSupportInfo::MimeTypeIterator& iterator) {
+ mDrmSupportInfo = iterator.mDrmSupportInfo;
+ mIndex = iterator.mIndex;
+ return *this;
+}
+
+bool DrmSupportInfo::MimeTypeIterator::hasNext() {
+ return mIndex < mDrmSupportInfo->mMimeTypeVector.size();
+}
+
+String8& DrmSupportInfo::MimeTypeIterator::next() {
+ String8& value = mDrmSupportInfo->mMimeTypeVector.editItemAt(mIndex);
+ mIndex++;
+ return value;
+}
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
new file mode 100644
index 0000000..43f64f2
--- /dev/null
+++ b/drm/common/IDrmManagerService.cpp
@@ -0,0 +1,1447 @@
+/*
+ * 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 "IDrmManagerService(Native)"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/IPCThreadState.h>
+
+#include <drm/DrmInfo.h>
+#include <drm/DrmConstraints.h>
+#include <drm/DrmMetadata.h>
+#include <drm/DrmRights.h>
+#include <drm/DrmInfoStatus.h>
+#include <drm/DrmConvertedStatus.h>
+#include <drm/DrmInfoRequest.h>
+#include <drm/DrmSupportInfo.h>
+
+#include "IDrmManagerService.h"
+
+#define INVALID_BUFFER_LENGTH -1
+
+using namespace android;
+
+static void writeDecryptHandleToParcelData(
+ const DecryptHandle* handle, Parcel* data) {
+ data->writeInt32(handle->decryptId);
+ data->writeString8(handle->mimeType);
+ data->writeInt32(handle->decryptApiType);
+ data->writeInt32(handle->status);
+
+ int size = handle->copyControlVector.size();
+ data->writeInt32(size);
+ for (int i = 0; i < size; i++) {
+ data->writeInt32(handle->copyControlVector.keyAt(i));
+ data->writeInt32(handle->copyControlVector.valueAt(i));
+ }
+
+ size = handle->extendedData.size();
+ data->writeInt32(size);
+ for (int i = 0; i < size; i++) {
+ data->writeString8(handle->extendedData.keyAt(i));
+ data->writeString8(handle->extendedData.valueAt(i));
+ }
+
+ if (NULL != handle->decryptInfo) {
+ data->writeInt32(handle->decryptInfo->decryptBufferLength);
+ } else {
+ data->writeInt32(INVALID_BUFFER_LENGTH);
+ }
+}
+
+static void readDecryptHandleFromParcelData(
+ DecryptHandle* handle, const Parcel& data) {
+ if (0 == data.dataAvail()) {
+ return;
+ }
+
+ handle->decryptId = data.readInt32();
+ handle->mimeType = data.readString8();
+ handle->decryptApiType = data.readInt32();
+ handle->status = data.readInt32();
+
+ int size = data.readInt32();
+ for (int i = 0; i < size; i++) {
+ DrmCopyControl key = (DrmCopyControl)data.readInt32();
+ int value = data.readInt32();
+ handle->copyControlVector.add(key, value);
+ }
+
+ size = data.readInt32();
+ for (int i = 0; i < size; i++) {
+ String8 key = data.readString8();
+ String8 value = data.readString8();
+ handle->extendedData.add(key, value);
+ }
+
+ handle->decryptInfo = NULL;
+ const int bufferLen = data.readInt32();
+ if (INVALID_BUFFER_LENGTH != bufferLen) {
+ handle->decryptInfo = new DecryptInfo();
+ handle->decryptInfo->decryptBufferLength = bufferLen;
+ }
+}
+
+static void clearDecryptHandle(DecryptHandle* handle) {
+ if (handle == NULL) {
+ return;
+ }
+ if (handle->decryptInfo) {
+ delete handle->decryptInfo;
+ handle->decryptInfo = NULL;
+ }
+ handle->copyControlVector.clear();
+ handle->extendedData.clear();
+}
+
+int BpDrmManagerService::addUniqueId(bool isNative) {
+ ALOGV("add uniqueid");
+ Parcel data, reply;
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(isNative);
+ remote()->transact(ADD_UNIQUEID, data, &reply);
+ return reply.readInt32();
+}
+
+void BpDrmManagerService::removeUniqueId(int uniqueId) {
+ ALOGV("remove uniqueid");
+ Parcel data, reply;
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ remote()->transact(REMOVE_UNIQUEID, data, &reply);
+}
+
+void BpDrmManagerService::addClient(int uniqueId) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ remote()->transact(ADD_CLIENT, data, &reply);
+}
+
+void BpDrmManagerService::removeClient(int uniqueId) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ remote()->transact(REMOVE_CLIENT, data, &reply);
+}
+
+status_t BpDrmManagerService::setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
+ ALOGV("setDrmServiceListener");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeStrongBinder(drmServiceListener->asBinder());
+ remote()->transact(SET_DRM_SERVICE_LISTENER, data, &reply);
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
+ ALOGV("Install DRM Engine");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(drmEngineFile);
+
+ remote()->transact(INSTALL_DRM_ENGINE, data, &reply);
+ return reply.readInt32();
+}
+
+DrmConstraints* BpDrmManagerService::getConstraints(
+ int uniqueId, const String8* path, const int action) {
+ ALOGV("Get Constraints");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(*path);
+ data.writeInt32(action);
+
+ remote()->transact(GET_CONSTRAINTS_FROM_CONTENT, data, &reply);
+
+ DrmConstraints* drmConstraints = NULL;
+ if (0 != reply.dataAvail()) {
+ //Filling Drm Constraints
+ drmConstraints = new DrmConstraints();
+
+ const int size = reply.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(reply.readString8());
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ drmConstraints->put(&key, data);
+ }
+ }
+ return drmConstraints;
+}
+
+DrmMetadata* BpDrmManagerService::getMetadata(int uniqueId, const String8* path) {
+ ALOGV("Get Metadata");
+ Parcel data, reply;
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ DrmMetadata* drmMetadata = NULL;
+ data.writeString8(*path);
+ remote()->transact(GET_METADATA_FROM_CONTENT, data, &reply);
+
+ if (0 != reply.dataAvail()) {
+ //Filling Drm Metadata
+ drmMetadata = new DrmMetadata();
+
+ const int size = reply.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(reply.readString8());
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ drmMetadata->put(&key, data);
+ }
+ }
+ return drmMetadata;
+}
+
+bool BpDrmManagerService::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+ ALOGV("Can Handle");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ data.writeString8(path);
+ data.writeString8(mimeType);
+
+ remote()->transact(CAN_HANDLE, data, &reply);
+
+ return static_cast<bool>(reply.readInt32());
+}
+
+DrmInfoStatus* BpDrmManagerService::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ ALOGV("Process DRM Info");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ //Filling DRM info
+ data.writeInt32(drmInfo->getInfoType());
+ const DrmBuffer dataBuffer = drmInfo->getData();
+ const int dataBufferSize = dataBuffer.length;
+ data.writeInt32(dataBufferSize);
+ if (0 < dataBufferSize) {
+ data.write(dataBuffer.data, dataBufferSize);
+ }
+ data.writeString8(drmInfo->getMimeType());
+
+ data.writeInt32(drmInfo->getCount());
+ DrmInfo::KeyIterator keyIt = drmInfo->keyIterator();
+
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ data.writeString8(key);
+ const String8 value = drmInfo->get(key);
+ data.writeString8((value == String8("")) ? String8("NULL") : value);
+ }
+
+ remote()->transact(PROCESS_DRM_INFO, data, &reply);
+
+ DrmInfoStatus* drmInfoStatus = NULL;
+ if (0 != reply.dataAvail()) {
+ //Filling DRM Info Status
+ const int statusCode = reply.readInt32();
+ const int infoType = reply.readInt32();
+ const String8 mimeType = reply.readString8();
+
+ DrmBuffer* drmBuffer = NULL;
+ if (0 != reply.dataAvail()) {
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ drmBuffer = new DrmBuffer(data, bufferSize);
+ }
+ drmInfoStatus = new DrmInfoStatus(statusCode, infoType, drmBuffer, mimeType);
+ }
+ return drmInfoStatus;
+}
+
+DrmInfo* BpDrmManagerService::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest) {
+ ALOGV("Acquire DRM Info");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ //Filling DRM Info Request
+ data.writeInt32(drmInforequest->getInfoType());
+ data.writeString8(drmInforequest->getMimeType());
+
+ data.writeInt32(drmInforequest->getCount());
+ DrmInfoRequest::KeyIterator keyIt = drmInforequest->keyIterator();
+
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ data.writeString8(key);
+ const String8 value = drmInforequest->get(key);
+ data.writeString8((value == String8("")) ? String8("NULL") : value);
+ }
+
+ remote()->transact(ACQUIRE_DRM_INFO, data, &reply);
+
+ DrmInfo* drmInfo = NULL;
+ if (0 != reply.dataAvail()) {
+ //Filling DRM Info
+ const int infoType = reply.readInt32();
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ drmInfo = new DrmInfo(infoType, DrmBuffer(data, bufferSize), reply.readString8());
+
+ const int size = reply.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(reply.readString8());
+ const String8 value(reply.readString8());
+ drmInfo->put(key, (value == String8("NULL")) ? String8("") : value);
+ }
+ }
+ return drmInfo;
+}
+
+status_t BpDrmManagerService::saveRights(
+ int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ ALOGV("Save Rights");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ //Filling Drm Rights
+ const DrmBuffer dataBuffer = drmRights.getData();
+ data.writeInt32(dataBuffer.length);
+ data.write(dataBuffer.data, dataBuffer.length);
+
+ const String8 mimeType = drmRights.getMimeType();
+ data.writeString8((mimeType == String8("")) ? String8("NULL") : mimeType);
+
+ const String8 accountId = drmRights.getAccountId();
+ data.writeString8((accountId == String8("")) ? String8("NULL") : accountId);
+
+ const String8 subscriptionId = drmRights.getSubscriptionId();
+ data.writeString8((subscriptionId == String8("")) ? String8("NULL") : subscriptionId);
+
+ data.writeString8((rightsPath == String8("")) ? String8("NULL") : rightsPath);
+ data.writeString8((contentPath == String8("")) ? String8("NULL") : contentPath);
+
+ remote()->transact(SAVE_RIGHTS, data, &reply);
+ return reply.readInt32();
+}
+
+String8 BpDrmManagerService::getOriginalMimeType(int uniqueId, const String8& path) {
+ ALOGV("Get Original MimeType");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+
+ remote()->transact(GET_ORIGINAL_MIMETYPE, data, &reply);
+ return reply.readString8();
+}
+
+int BpDrmManagerService::getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ ALOGV("Get Drm object type");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+ data.writeString8(mimeType);
+
+ remote()->transact(GET_DRM_OBJECT_TYPE, data, &reply);
+
+ return reply.readInt32();
+}
+
+int BpDrmManagerService::checkRightsStatus(int uniqueId, const String8& path, int action) {
+ ALOGV("checkRightsStatus");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+ data.writeInt32(action);
+
+ remote()->transact(CHECK_RIGHTS_STATUS, data, &reply);
+
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ ALOGV("consumeRights");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ writeDecryptHandleToParcelData(decryptHandle, &data);
+
+ data.writeInt32(action);
+ data.writeInt32(static_cast< int>(reserve));
+
+ remote()->transact(CONSUME_RIGHTS, data, &reply);
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) {
+ ALOGV("setPlaybackStatus");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ writeDecryptHandleToParcelData(decryptHandle, &data);
+
+ data.writeInt32(playbackStatus);
+ data.writeInt64(position);
+
+ remote()->transact(SET_PLAYBACK_STATUS, data, &reply);
+ return reply.readInt32();
+}
+
+bool BpDrmManagerService::validateAction(
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ ALOGV("validateAction");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+ data.writeInt32(action);
+ data.writeInt32(description.outputType);
+ data.writeInt32(description.configuration);
+
+ remote()->transact(VALIDATE_ACTION, data, &reply);
+
+ return static_cast<bool>(reply.readInt32());
+}
+
+status_t BpDrmManagerService::removeRights(int uniqueId, const String8& path) {
+ ALOGV("removeRights");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(path);
+
+ remote()->transact(REMOVE_RIGHTS, data, &reply);
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::removeAllRights(int uniqueId) {
+ ALOGV("removeAllRights");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ remote()->transact(REMOVE_ALL_RIGHTS, data, &reply);
+ return reply.readInt32();
+}
+
+int BpDrmManagerService::openConvertSession(int uniqueId, const String8& mimeType) {
+ ALOGV("openConvertSession");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(mimeType);
+
+ remote()->transact(OPEN_CONVERT_SESSION, data, &reply);
+ return reply.readInt32();
+}
+
+DrmConvertedStatus* BpDrmManagerService::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ ALOGV("convertData");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeInt32(convertId);
+ data.writeInt32(inputData->length);
+ data.write(inputData->data, inputData->length);
+
+ remote()->transact(CONVERT_DATA, data, &reply);
+
+ DrmConvertedStatus* drmConvertedStatus = NULL;
+
+ if (0 != reply.dataAvail()) {
+ //Filling DRM Converted Status
+ const int statusCode = reply.readInt32();
+ const off64_t offset = reply.readInt64();
+
+ DrmBuffer* convertedData = NULL;
+ if (0 != reply.dataAvail()) {
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ convertedData = new DrmBuffer(data, bufferSize);
+ }
+ drmConvertedStatus = new DrmConvertedStatus(statusCode, convertedData, offset);
+ }
+ return drmConvertedStatus;
+}
+
+DrmConvertedStatus* BpDrmManagerService::closeConvertSession(int uniqueId, int convertId) {
+ ALOGV("closeConvertSession");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeInt32(convertId);
+
+ remote()->transact(CLOSE_CONVERT_SESSION, data, &reply);
+
+ DrmConvertedStatus* drmConvertedStatus = NULL;
+
+ if (0 != reply.dataAvail()) {
+ //Filling DRM Converted Status
+ const int statusCode = reply.readInt32();
+ const off64_t offset = reply.readInt64();
+
+ DrmBuffer* convertedData = NULL;
+ if (0 != reply.dataAvail()) {
+ const int bufferSize = reply.readInt32();
+ char* data = NULL;
+ if (0 < bufferSize) {
+ data = new char[bufferSize];
+ reply.read(data, bufferSize);
+ }
+ convertedData = new DrmBuffer(data, bufferSize);
+ }
+ drmConvertedStatus = new DrmConvertedStatus(statusCode, convertedData, offset);
+ }
+ return drmConvertedStatus;
+}
+
+status_t BpDrmManagerService::getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+ ALOGV("Get All Support Info");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ remote()->transact(GET_ALL_SUPPORT_INFO, data, &reply);
+
+ //Filling DRM Support Info
+ const int arraySize = reply.readInt32();
+ if (0 < arraySize) {
+ *drmSupportInfoArray = new DrmSupportInfo[arraySize];
+
+ for (int index = 0; index < arraySize; ++index) {
+ DrmSupportInfo drmSupportInfo;
+
+ const int fileSuffixVectorSize = reply.readInt32();
+ for (int i = 0; i < fileSuffixVectorSize; ++i) {
+ drmSupportInfo.addFileSuffix(reply.readString8());
+ }
+
+ const int mimeTypeVectorSize = reply.readInt32();
+ for (int i = 0; i < mimeTypeVectorSize; ++i) {
+ drmSupportInfo.addMimeType(reply.readString8());
+ }
+
+ drmSupportInfo.setDescription(reply.readString8());
+ (*drmSupportInfoArray)[index] = drmSupportInfo;
+ }
+ }
+ *length = arraySize;
+ return reply.readInt32();
+}
+
+DecryptHandle* BpDrmManagerService::openDecryptSession(
+ int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) {
+ ALOGV("Entering BpDrmManagerService::openDecryptSession");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeFileDescriptor(fd);
+ data.writeInt64(offset);
+ data.writeInt64(length);
+ String8 mimeType;
+ if (mime) {
+ mimeType = mime;
+ }
+ data.writeString8(mimeType);
+
+ remote()->transact(OPEN_DECRYPT_SESSION, data, &reply);
+
+ DecryptHandle* handle = NULL;
+ if (0 != reply.dataAvail()) {
+ handle = new DecryptHandle();
+ readDecryptHandleFromParcelData(handle, reply);
+ }
+ return handle;
+}
+
+DecryptHandle* BpDrmManagerService::openDecryptSession(
+ int uniqueId, const char* uri, const char* mime) {
+
+ ALOGV("Entering BpDrmManagerService::openDecryptSession: mime=%s", mime? mime: "NULL");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+ data.writeString8(String8(uri));
+ String8 mimeType;
+ if (mime) {
+ mimeType = mime;
+ }
+ data.writeString8(mimeType);
+
+ remote()->transact(OPEN_DECRYPT_SESSION_FROM_URI, data, &reply);
+
+ DecryptHandle* handle = NULL;
+ if (0 != reply.dataAvail()) {
+ handle = new DecryptHandle();
+ readDecryptHandleFromParcelData(handle, reply);
+ } else {
+ ALOGV("no decryptHandle is generated in service side");
+ }
+ return handle;
+}
+
+status_t BpDrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ ALOGV("closeDecryptSession");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ writeDecryptHandleToParcelData(decryptHandle, &data);
+
+ remote()->transact(CLOSE_DECRYPT_SESSION, data, &reply);
+
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::initializeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ ALOGV("initializeDecryptUnit");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ writeDecryptHandleToParcelData(decryptHandle, &data);
+
+ data.writeInt32(decryptUnitId);
+
+ data.writeInt32(headerInfo->length);
+ data.write(headerInfo->data, headerInfo->length);
+
+ remote()->transact(INITIALIZE_DECRYPT_UNIT, data, &reply);
+ return reply.readInt32();
+}
+
+status_t BpDrmManagerService::decrypt(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ ALOGV("decrypt");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ writeDecryptHandleToParcelData(decryptHandle, &data);
+
+ data.writeInt32(decryptUnitId);
+ data.writeInt32((*decBuffer)->length);
+
+ data.writeInt32(encBuffer->length);
+ data.write(encBuffer->data, encBuffer->length);
+
+ if (NULL != IV) {
+ data.writeInt32(IV->length);
+ data.write(IV->data, IV->length);
+ }
+
+ remote()->transact(DECRYPT, data, &reply);
+
+ const status_t status = reply.readInt32();
+ ALOGV("Return value of decrypt() is %d", status);
+
+ const int size = reply.readInt32();
+ (*decBuffer)->length = size;
+ reply.read((void *)(*decBuffer)->data, size);
+
+ return status;
+}
+
+status_t BpDrmManagerService::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ ALOGV("finalizeDecryptUnit");
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ writeDecryptHandleToParcelData(decryptHandle, &data);
+
+ data.writeInt32(decryptUnitId);
+
+ remote()->transact(FINALIZE_DECRYPT_UNIT, data, &reply);
+ return reply.readInt32();
+}
+
+ssize_t BpDrmManagerService::pread(
+ int uniqueId, DecryptHandle* decryptHandle, void* buffer,
+ ssize_t numBytes, off64_t offset) {
+ ALOGV("read");
+ Parcel data, reply;
+ int result;
+
+ data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
+ data.writeInt32(uniqueId);
+
+ writeDecryptHandleToParcelData(decryptHandle, &data);
+
+ data.writeInt32(numBytes);
+ data.writeInt64(offset);
+
+ remote()->transact(PREAD, data, &reply);
+ result = reply.readInt32();
+ if (0 < result) {
+ reply.read(buffer, result);
+ }
+ return result;
+}
+
+IMPLEMENT_META_INTERFACE(DrmManagerService, "drm.IDrmManagerService");
+
+status_t BnDrmManagerService::onTransact(
+ uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags) {
+ ALOGV("Entering BnDrmManagerService::onTransact with code %d", code);
+
+ switch (code) {
+ case ADD_UNIQUEID:
+ {
+ ALOGV("BnDrmManagerService::onTransact :ADD_UNIQUEID");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+ int uniqueId = addUniqueId(data.readInt32());
+ reply->writeInt32(uniqueId);
+ return DRM_NO_ERROR;
+ }
+
+ case REMOVE_UNIQUEID:
+ {
+ ALOGV("BnDrmManagerService::onTransact :REMOVE_UNIQUEID");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+ removeUniqueId(data.readInt32());
+ return DRM_NO_ERROR;
+ }
+
+ case ADD_CLIENT:
+ {
+ ALOGV("BnDrmManagerService::onTransact :ADD_CLIENT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+ addClient(data.readInt32());
+ return DRM_NO_ERROR;
+ }
+
+ case REMOVE_CLIENT:
+ {
+ ALOGV("BnDrmManagerService::onTransact :REMOVE_CLIENT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+ removeClient(data.readInt32());
+ return DRM_NO_ERROR;
+ }
+
+ case SET_DRM_SERVICE_LISTENER:
+ {
+ ALOGV("BnDrmManagerService::onTransact :SET_DRM_SERVICE_LISTENER");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const sp<IDrmServiceListener> drmServiceListener
+ = interface_cast<IDrmServiceListener> (data.readStrongBinder());
+
+ status_t status = setDrmServiceListener(uniqueId, drmServiceListener);
+
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case INSTALL_DRM_ENGINE:
+ {
+ ALOGV("BnDrmManagerService::onTransact :INSTALL_DRM_ENGINE");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 engineFile = data.readString8();
+ status_t status = installDrmEngine(uniqueId, engineFile);
+
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case GET_CONSTRAINTS_FROM_CONTENT:
+ {
+ ALOGV("BnDrmManagerService::onTransact :GET_CONSTRAINTS_FROM_CONTENT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 path = data.readString8();
+
+ DrmConstraints* drmConstraints
+ = getConstraints(uniqueId, &path, data.readInt32());
+
+ if (NULL != drmConstraints) {
+ //Filling DRM Constraints contents
+ reply->writeInt32(drmConstraints->getCount());
+
+ DrmConstraints::KeyIterator keyIt = drmConstraints->keyIterator();
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ reply->writeString8(key);
+ const char* value = drmConstraints->getAsByteArray(&key);
+ int bufferSize = 0;
+ if (NULL != value) {
+ bufferSize = strlen(value);
+ }
+ reply->writeInt32(bufferSize + 1);
+ reply->write(value, bufferSize + 1);
+ }
+ }
+ delete drmConstraints; drmConstraints = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case GET_METADATA_FROM_CONTENT:
+ {
+ ALOGV("BnDrmManagerService::onTransact :GET_METADATA_FROM_CONTENT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 path = data.readString8();
+
+ DrmMetadata* drmMetadata = getMetadata(uniqueId, &path);
+ if (NULL != drmMetadata) {
+ //Filling DRM Metadata contents
+ reply->writeInt32(drmMetadata->getCount());
+
+ DrmMetadata::KeyIterator keyIt = drmMetadata->keyIterator();
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ reply->writeString8(key);
+ const char* value = drmMetadata->getAsByteArray(&key);
+ int bufferSize = 0;
+ if (NULL != value) {
+ bufferSize = strlen(value);
+ reply->writeInt32(bufferSize + 1);
+ reply->write(value, bufferSize + 1);
+ } else {
+ reply->writeInt32(0);
+ }
+ }
+ }
+ delete drmMetadata; drmMetadata = NULL;
+ return NO_ERROR;
+ }
+
+ case CAN_HANDLE:
+ {
+ ALOGV("BnDrmManagerService::onTransact :CAN_HANDLE");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 path = data.readString8();
+ const String8 mimeType = data.readString8();
+
+ bool result = canHandle(uniqueId, path, mimeType);
+
+ reply->writeInt32(result);
+ return DRM_NO_ERROR;
+ }
+
+ case PROCESS_DRM_INFO:
+ {
+ ALOGV("BnDrmManagerService::onTransact :PROCESS_DRM_INFO");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ //Filling DRM info
+ const int infoType = data.readInt32();
+ const int bufferSize = data.readInt32();
+ char* buffer = NULL;
+ if (0 < bufferSize) {
+ buffer = (char *)data.readInplace(bufferSize);
+ }
+ const DrmBuffer drmBuffer(buffer, bufferSize);
+ DrmInfo* drmInfo = new DrmInfo(infoType, drmBuffer, data.readString8());
+
+ const int size = data.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(data.readString8());
+ const String8 value(data.readString8());
+ drmInfo->put(key, (value == String8("NULL")) ? String8("") : value);
+ }
+
+ DrmInfoStatus* drmInfoStatus = processDrmInfo(uniqueId, drmInfo);
+
+ if (NULL != drmInfoStatus) {
+ //Filling DRM Info Status contents
+ reply->writeInt32(drmInfoStatus->statusCode);
+ reply->writeInt32(drmInfoStatus->infoType);
+ reply->writeString8(drmInfoStatus->mimeType);
+
+ if (NULL != drmInfoStatus->drmBuffer) {
+ const DrmBuffer* drmBuffer = drmInfoStatus->drmBuffer;
+ const int bufferSize = drmBuffer->length;
+ reply->writeInt32(bufferSize);
+ if (0 < bufferSize) {
+ reply->write(drmBuffer->data, bufferSize);
+ }
+ delete [] drmBuffer->data;
+ delete drmBuffer; drmBuffer = NULL;
+ }
+ }
+ delete drmInfo; drmInfo = NULL;
+ delete drmInfoStatus; drmInfoStatus = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case ACQUIRE_DRM_INFO:
+ {
+ ALOGV("BnDrmManagerService::onTransact :ACQUIRE_DRM_INFO");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ //Filling DRM info Request
+ const int infoType = data.readInt32();
+ const String8 mimeType = data.readString8();
+ DrmInfoRequest* drmInfoRequest = new DrmInfoRequest(infoType, mimeType);
+
+ const int size = data.readInt32();
+ for (int index = 0; index < size; ++index) {
+ const String8 key(data.readString8());
+ const String8 value(data.readString8());
+ drmInfoRequest->put(key, (value == String8("NULL")) ? String8("") : value);
+ }
+
+ DrmInfo* drmInfo = acquireDrmInfo(uniqueId, drmInfoRequest);
+
+ if (NULL != drmInfo) {
+ //Filling DRM Info
+ const DrmBuffer drmBuffer = drmInfo->getData();
+ reply->writeInt32(drmInfo->getInfoType());
+
+ const int bufferSize = drmBuffer.length;
+ reply->writeInt32(bufferSize);
+ if (0 < bufferSize) {
+ reply->write(drmBuffer.data, bufferSize);
+ }
+ reply->writeString8(drmInfo->getMimeType());
+ reply->writeInt32(drmInfo->getCount());
+
+ DrmInfo::KeyIterator keyIt = drmInfo->keyIterator();
+ while (keyIt.hasNext()) {
+ const String8 key = keyIt.next();
+ reply->writeString8(key);
+ const String8 value = drmInfo->get(key);
+ reply->writeString8((value == String8("")) ? String8("NULL") : value);
+ }
+ delete [] drmBuffer.data;
+ }
+ delete drmInfoRequest; drmInfoRequest = NULL;
+ delete drmInfo; drmInfo = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case SAVE_RIGHTS:
+ {
+ ALOGV("BnDrmManagerService::onTransact :SAVE_RIGHTS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ //Filling DRM Rights
+ const int bufferSize = data.readInt32();
+ const DrmBuffer drmBuffer((char *)data.readInplace(bufferSize), bufferSize);
+
+ const String8 mimeType(data.readString8());
+ const String8 accountId(data.readString8());
+ const String8 subscriptionId(data.readString8());
+ const String8 rightsPath(data.readString8());
+ const String8 contentPath(data.readString8());
+
+ DrmRights drmRights(drmBuffer,
+ ((mimeType == String8("NULL")) ? String8("") : mimeType),
+ ((accountId == String8("NULL")) ? String8("") : accountId),
+ ((subscriptionId == String8("NULL")) ? String8("") : subscriptionId));
+
+ const status_t status = saveRights(uniqueId, drmRights,
+ ((rightsPath == String8("NULL")) ? String8("") : rightsPath),
+ ((contentPath == String8("NULL")) ? String8("") : contentPath));
+
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case GET_ORIGINAL_MIMETYPE:
+ {
+ ALOGV("BnDrmManagerService::onTransact :GET_ORIGINAL_MIMETYPE");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 path = data.readString8();
+ const String8 originalMimeType = getOriginalMimeType(uniqueId, path);
+
+ reply->writeString8(originalMimeType);
+ return DRM_NO_ERROR;
+ }
+
+ case GET_DRM_OBJECT_TYPE:
+ {
+ ALOGV("BnDrmManagerService::onTransact :GET_DRM_OBJECT_TYPE");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 path = data.readString8();
+ const String8 mimeType = data.readString8();
+ const int drmObjectType = getDrmObjectType(uniqueId, path, mimeType);
+
+ reply->writeInt32(drmObjectType);
+ return DRM_NO_ERROR;
+ }
+
+ case CHECK_RIGHTS_STATUS:
+ {
+ ALOGV("BnDrmManagerService::onTransact :CHECK_RIGHTS_STATUS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 path = data.readString8();
+ const int action = data.readInt32();
+ const int result = checkRightsStatus(uniqueId, path, action);
+
+ reply->writeInt32(result);
+ return DRM_NO_ERROR;
+ }
+
+ case CONSUME_RIGHTS:
+ {
+ ALOGV("BnDrmManagerService::onTransact :CONSUME_RIGHTS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ readDecryptHandleFromParcelData(&handle, data);
+
+ const int action = data.readInt32();
+ const bool reserve = static_cast<bool>(data.readInt32());
+ const status_t status
+ = consumeRights(uniqueId, &handle, action, reserve);
+ reply->writeInt32(status);
+
+ clearDecryptHandle(&handle);
+ return DRM_NO_ERROR;
+ }
+
+ case SET_PLAYBACK_STATUS:
+ {
+ ALOGV("BnDrmManagerService::onTransact :SET_PLAYBACK_STATUS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ readDecryptHandleFromParcelData(&handle, data);
+
+ const int playbackStatus = data.readInt32();
+ const int64_t position = data.readInt64();
+ const status_t status
+ = setPlaybackStatus(uniqueId, &handle, playbackStatus, position);
+ reply->writeInt32(status);
+
+ clearDecryptHandle(&handle);
+ return DRM_NO_ERROR;
+ }
+
+ case VALIDATE_ACTION:
+ {
+ ALOGV("BnDrmManagerService::onTransact :VALIDATE_ACTION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 path = data.readString8();
+ const int action = data.readInt32();
+ const int outputType = data.readInt32();
+ const int configuration = data.readInt32();
+ bool result = validateAction(uniqueId, path, action,
+ ActionDescription(outputType, configuration));
+
+ reply->writeInt32(result);
+ return DRM_NO_ERROR;
+ }
+
+ case REMOVE_RIGHTS:
+ {
+ ALOGV("BnDrmManagerService::onTransact :REMOVE_RIGHTS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ int uniqueId = data.readInt32();
+ String8 path = data.readString8();
+ const status_t status = removeRights(uniqueId, path);
+ reply->writeInt32(status);
+
+ return DRM_NO_ERROR;
+ }
+
+ case REMOVE_ALL_RIGHTS:
+ {
+ ALOGV("BnDrmManagerService::onTransact :REMOVE_ALL_RIGHTS");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const status_t status = removeAllRights(data.readInt32());
+ reply->writeInt32(status);
+
+ return DRM_NO_ERROR;
+ }
+
+ case OPEN_CONVERT_SESSION:
+ {
+ ALOGV("BnDrmManagerService::onTransact :OPEN_CONVERT_SESSION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 mimeType = data.readString8();
+ const int convertId = openConvertSession(uniqueId, mimeType);
+
+ reply->writeInt32(convertId);
+ return DRM_NO_ERROR;
+ }
+
+ case CONVERT_DATA:
+ {
+ ALOGV("BnDrmManagerService::onTransact :CONVERT_DATA");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const int convertId = data.readInt32();
+
+ //Filling input data
+ const int bufferSize = data.readInt32();
+ DrmBuffer* inputData = new DrmBuffer((char *)data.readInplace(bufferSize), bufferSize);
+
+ DrmConvertedStatus* drmConvertedStatus = convertData(uniqueId, convertId, inputData);
+
+ if (NULL != drmConvertedStatus) {
+ //Filling Drm Converted Ststus
+ reply->writeInt32(drmConvertedStatus->statusCode);
+ reply->writeInt64(drmConvertedStatus->offset);
+
+ if (NULL != drmConvertedStatus->convertedData) {
+ const DrmBuffer* convertedData = drmConvertedStatus->convertedData;
+ const int bufferSize = convertedData->length;
+ reply->writeInt32(bufferSize);
+ if (0 < bufferSize) {
+ reply->write(convertedData->data, bufferSize);
+ }
+ delete [] convertedData->data;
+ delete convertedData; convertedData = NULL;
+ }
+ }
+ delete inputData; inputData = NULL;
+ delete drmConvertedStatus; drmConvertedStatus = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case CLOSE_CONVERT_SESSION:
+ {
+ ALOGV("BnDrmManagerService::onTransact :CLOSE_CONVERT_SESSION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const int convertId = data.readInt32();
+ DrmConvertedStatus* drmConvertedStatus
+ = closeConvertSession(uniqueId, convertId);
+
+ if (NULL != drmConvertedStatus) {
+ //Filling Drm Converted Ststus
+ reply->writeInt32(drmConvertedStatus->statusCode);
+ reply->writeInt64(drmConvertedStatus->offset);
+
+ if (NULL != drmConvertedStatus->convertedData) {
+ const DrmBuffer* convertedData = drmConvertedStatus->convertedData;
+ const int bufferSize = convertedData->length;
+ reply->writeInt32(bufferSize);
+ if (0 < bufferSize) {
+ reply->write(convertedData->data, bufferSize);
+ }
+ delete [] convertedData->data;
+ delete convertedData; convertedData = NULL;
+ }
+ }
+ delete drmConvertedStatus; drmConvertedStatus = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case GET_ALL_SUPPORT_INFO:
+ {
+ ALOGV("BnDrmManagerService::onTransact :GET_ALL_SUPPORT_INFO");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ int length = 0;
+ DrmSupportInfo* drmSupportInfoArray = NULL;
+
+ status_t status = getAllSupportInfo(uniqueId, &length, &drmSupportInfoArray);
+
+ reply->writeInt32(length);
+ for (int i = 0; i < length; ++i) {
+ DrmSupportInfo drmSupportInfo = drmSupportInfoArray[i];
+
+ reply->writeInt32(drmSupportInfo.getFileSuffixCount());
+ DrmSupportInfo::FileSuffixIterator fileSuffixIt
+ = drmSupportInfo.getFileSuffixIterator();
+ while (fileSuffixIt.hasNext()) {
+ reply->writeString8(fileSuffixIt.next());
+ }
+
+ reply->writeInt32(drmSupportInfo.getMimeTypeCount());
+ DrmSupportInfo::MimeTypeIterator mimeTypeIt = drmSupportInfo.getMimeTypeIterator();
+ while (mimeTypeIt.hasNext()) {
+ reply->writeString8(mimeTypeIt.next());
+ }
+ reply->writeString8(drmSupportInfo.getDescription());
+ }
+ delete [] drmSupportInfoArray; drmSupportInfoArray = NULL;
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case OPEN_DECRYPT_SESSION:
+ {
+ ALOGV("BnDrmManagerService::onTransact :OPEN_DECRYPT_SESSION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const int fd = data.readFileDescriptor();
+
+ const off64_t offset = data.readInt64();
+ const off64_t length = data.readInt64();
+ const String8 mime = data.readString8();
+
+ DecryptHandle* handle
+ = openDecryptSession(uniqueId, fd, offset, length, mime.string());
+
+ if (NULL != handle) {
+ writeDecryptHandleToParcelData(handle, reply);
+ clearDecryptHandle(handle);
+ delete handle; handle = NULL;
+ }
+ return DRM_NO_ERROR;
+ }
+
+ case OPEN_DECRYPT_SESSION_FROM_URI:
+ {
+ ALOGV("BnDrmManagerService::onTransact :OPEN_DECRYPT_SESSION_FROM_URI");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+ const String8 uri = data.readString8();
+ const String8 mime = data.readString8();
+
+ DecryptHandle* handle = openDecryptSession(uniqueId, uri.string(), mime.string());
+
+ if (NULL != handle) {
+ writeDecryptHandleToParcelData(handle, reply);
+
+ clearDecryptHandle(handle);
+ delete handle; handle = NULL;
+ } else {
+ ALOGV("NULL decryptHandle is returned");
+ }
+ return DRM_NO_ERROR;
+ }
+
+ case CLOSE_DECRYPT_SESSION:
+ {
+ ALOGV("BnDrmManagerService::onTransact :CLOSE_DECRYPT_SESSION");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle* handle = new DecryptHandle();
+ readDecryptHandleFromParcelData(handle, data);
+
+ const status_t status = closeDecryptSession(uniqueId, handle);
+ reply->writeInt32(status);
+ return DRM_NO_ERROR;
+ }
+
+ case INITIALIZE_DECRYPT_UNIT:
+ {
+ ALOGV("BnDrmManagerService::onTransact :INITIALIZE_DECRYPT_UNIT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ readDecryptHandleFromParcelData(&handle, data);
+
+ const int decryptUnitId = data.readInt32();
+
+ //Filling Header info
+ const int bufferSize = data.readInt32();
+ DrmBuffer* headerInfo = NULL;
+ headerInfo = new DrmBuffer((char *)data.readInplace(bufferSize), bufferSize);
+
+ const status_t status
+ = initializeDecryptUnit(uniqueId, &handle, decryptUnitId, headerInfo);
+ reply->writeInt32(status);
+
+ clearDecryptHandle(&handle);
+ delete headerInfo; headerInfo = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case DECRYPT:
+ {
+ ALOGV("BnDrmManagerService::onTransact :DECRYPT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ readDecryptHandleFromParcelData(&handle, data);
+
+ const int decryptUnitId = data.readInt32();
+ const int decBufferSize = data.readInt32();
+
+ const int encBufferSize = data.readInt32();
+ DrmBuffer* encBuffer
+ = new DrmBuffer((char *)data.readInplace(encBufferSize), encBufferSize);
+
+ char* buffer = NULL;
+ buffer = new char[decBufferSize];
+ DrmBuffer* decBuffer = new DrmBuffer(buffer, decBufferSize);
+
+ DrmBuffer* IV = NULL;
+ if (0 != data.dataAvail()) {
+ const int ivBufferlength = data.readInt32();
+ IV = new DrmBuffer((char *)data.readInplace(ivBufferlength), ivBufferlength);
+ }
+
+ const status_t status
+ = decrypt(uniqueId, &handle, decryptUnitId, encBuffer, &decBuffer, IV);
+
+ reply->writeInt32(status);
+
+ const int size = decBuffer->length;
+ reply->writeInt32(size);
+ reply->write(decBuffer->data, size);
+
+ clearDecryptHandle(&handle);
+ delete encBuffer; encBuffer = NULL;
+ delete decBuffer; decBuffer = NULL;
+ delete [] buffer; buffer = NULL;
+ delete IV; IV = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ case FINALIZE_DECRYPT_UNIT:
+ {
+ ALOGV("BnDrmManagerService::onTransact :FINALIZE_DECRYPT_UNIT");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ readDecryptHandleFromParcelData(&handle, data);
+
+ const status_t status = finalizeDecryptUnit(uniqueId, &handle, data.readInt32());
+ reply->writeInt32(status);
+
+ clearDecryptHandle(&handle);
+ return DRM_NO_ERROR;
+ }
+
+ case PREAD:
+ {
+ ALOGV("BnDrmManagerService::onTransact :READ");
+ CHECK_INTERFACE(IDrmManagerService, data, reply);
+
+ const int uniqueId = data.readInt32();
+
+ DecryptHandle handle;
+ readDecryptHandleFromParcelData(&handle, data);
+
+ const int numBytes = data.readInt32();
+ char* buffer = new char[numBytes];
+
+ const off64_t offset = data.readInt64();
+
+ ssize_t result = pread(uniqueId, &handle, buffer, numBytes, offset);
+ reply->writeInt32(result);
+ if (0 < result) {
+ reply->write(buffer, result);
+ }
+
+ clearDecryptHandle(&handle);
+ delete [] buffer, buffer = NULL;
+ return DRM_NO_ERROR;
+ }
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
diff --git a/drm/common/IDrmServiceListener.cpp b/drm/common/IDrmServiceListener.cpp
new file mode 100644
index 0000000..6eeea40
--- /dev/null
+++ b/drm/common/IDrmServiceListener.cpp
@@ -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.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <drm/drm_framework_common.h>
+#include <drm/DrmInfoEvent.h>
+#include "IDrmServiceListener.h"
+
+using namespace android;
+
+status_t BpDrmServiceListener::notify(const DrmInfoEvent& event) {
+ Parcel data, reply;
+
+ data.writeInterfaceToken(IDrmServiceListener::getInterfaceDescriptor());
+ data.writeInt32(event.getUniqueId());
+ data.writeInt32(event.getType());
+ data.writeString8(event.getMessage());
+
+ remote()->transact(NOTIFY, data, &reply);
+ return reply.readInt32();
+}
+
+IMPLEMENT_META_INTERFACE(DrmServiceListener, "drm.IDrmServiceListener");
+
+status_t BnDrmServiceListener::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+
+ switch (code) {
+ case NOTIFY:
+ {
+ CHECK_INTERFACE(IDrmServiceListener, data, reply);
+ int uniqueId = data.readInt32();
+ int type = data.readInt32();
+ const String8& message = data.readString8();
+
+ status_t status = notify(DrmInfoEvent(uniqueId, type, message));
+ reply->writeInt32(status);
+
+ return DRM_NO_ERROR;
+ }
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
diff --git a/drm/common/ReadWriteUtils.cpp b/drm/common/ReadWriteUtils.cpp
new file mode 100644
index 0000000..fd17e98
--- /dev/null
+++ b/drm/common/ReadWriteUtils.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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 "ReadWriteUtils"
+#include <utils/Log.h>
+
+#include <ReadWriteUtils.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <utils/String8.h>
+
+using namespace android;
+
+#define FAILURE -1
+
+String8 ReadWriteUtils::readBytes(const String8& filePath) {
+ FILE* file = NULL;
+ file = fopen(filePath.string(), "r");
+
+ String8 string("");
+ if (NULL != file) {
+ int fd = fileno(file);
+ struct stat sb;
+
+ if (fstat(fd, &sb) == 0 && sb.st_size > 0) {
+ off64_t length = sb.st_size;
+ char* bytes = new char[length];
+ if (length == read(fd, (void*) bytes, length)) {
+ string.append(bytes, length);
+ }
+ delete bytes;
+ }
+ fclose(file);
+ }
+ return string;
+}
+
+int ReadWriteUtils::readBytes(const String8& filePath, char** buffer) {
+ FILE* file = NULL;
+ file = fopen(filePath.string(), "r");
+ off64_t length = 0;
+
+ if (NULL != file) {
+ int fd = fileno(file);
+ struct stat sb;
+
+ if (fstat(fd, &sb) == 0 && sb.st_size > 0) {
+ length = sb.st_size;
+ *buffer = new char[length];
+ if (length != read(fd, (void*) *buffer, length)) {
+ length = FAILURE;
+ }
+ }
+ fclose(file);
+ }
+ return length;
+}
+
+void ReadWriteUtils::writeToFile(const String8& filePath, const String8& data) {
+ FILE* file = NULL;
+ file = fopen(filePath.string(), "w+");
+
+ if (NULL != file) {
+ int fd = fileno(file);
+
+ int size = data.size();
+ if (FAILURE != ftruncate(fd, size)) {
+ if (size != write(fd, data.string(), size)) {
+ ALOGE("Failed to write the data to: %s", filePath.string());
+ }
+ }
+ fclose(file);
+ }
+}
+
+void ReadWriteUtils::appendToFile(const String8& filePath, const String8& data) {
+ FILE* file = NULL;
+ file = fopen(filePath.string(), "a+");
+
+ if (NULL != file) {
+ int fd = fileno(file);
+
+ int size = data.size();
+ if (size != write(fd, data.string(), size)) {
+ ALOGE("Failed to write the data to: %s", filePath.string());
+ }
+ fclose(file);
+ }
+}
+
diff --git a/drm/drmserver/Android.mk b/drm/drmserver/Android.mk
new file mode 100644
index 0000000..fd417cb
--- /dev/null
+++ b/drm/drmserver/Android.mk
@@ -0,0 +1,41 @@
+#
+# 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.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ main_drmserver.cpp \
+ DrmManager.cpp \
+ DrmManagerService.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libmedia \
+ libutils \
+ libbinder \
+ libdl
+
+LOCAL_STATIC_LIBRARIES := libdrmframeworkcommon
+
+LOCAL_C_INCLUDES := \
+ $(TOP)/frameworks/base/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/plugins/common/include
+
+LOCAL_MODULE:= drmserver
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
new file mode 100644
index 0000000..999295a
--- /dev/null
+++ b/drm/drmserver/DrmManager.cpp
@@ -0,0 +1,606 @@
+/*
+ * 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 "DrmManager(Native)"
+#include "utils/Log.h"
+
+#include <utils/String8.h>
+#include <drm/DrmInfo.h>
+#include <drm/DrmInfoEvent.h>
+#include <drm/DrmRights.h>
+#include <drm/DrmConstraints.h>
+#include <drm/DrmMetadata.h>
+#include <drm/DrmInfoStatus.h>
+#include <drm/DrmInfoRequest.h>
+#include <drm/DrmSupportInfo.h>
+#include <drm/DrmConvertedStatus.h>
+#include <IDrmEngine.h>
+
+#include "DrmManager.h"
+#include "ReadWriteUtils.h"
+
+#define DECRYPT_FILE_ERROR -1
+
+using namespace android;
+
+const String8 DrmManager::EMPTY_STRING("");
+
+DrmManager::DrmManager() :
+ mDecryptSessionId(0),
+ mConvertId(0) {
+
+}
+
+DrmManager::~DrmManager() {
+
+}
+
+int DrmManager::addUniqueId(bool isNative) {
+ Mutex::Autolock _l(mLock);
+
+ int temp = 0;
+ bool foundUniqueId = false;
+ const int size = mUniqueIdVector.size();
+ const int uniqueIdRange = 0xfff;
+ int maxLoopTimes = (uniqueIdRange - 1) / 2;
+ srand(time(NULL));
+
+ while (!foundUniqueId) {
+ temp = rand() & uniqueIdRange;
+
+ if (isNative) {
+ // set a flag to differentiate DrmManagerClient
+ // created from native side and java side
+ temp |= 0x1000;
+ }
+
+ int index = 0;
+ for (; index < size; ++index) {
+ if (mUniqueIdVector.itemAt(index) == temp) {
+ foundUniqueId = false;
+ break;
+ }
+ }
+ if (index == size) {
+ foundUniqueId = true;
+ }
+
+ maxLoopTimes --;
+ LOG_FATAL_IF(maxLoopTimes <= 0, "cannot find an unique ID for this session");
+ }
+
+ mUniqueIdVector.push(temp);
+ return temp;
+}
+
+void DrmManager::removeUniqueId(int uniqueId) {
+ Mutex::Autolock _l(mLock);
+ for (unsigned int i = 0; i < mUniqueIdVector.size(); i++) {
+ if (uniqueId == mUniqueIdVector.itemAt(i)) {
+ mUniqueIdVector.removeAt(i);
+ break;
+ }
+ }
+}
+
+status_t DrmManager::loadPlugIns() {
+
+ String8 vendorPluginDirPath("/vendor/lib/drm");
+ loadPlugIns(vendorPluginDirPath);
+
+ String8 pluginDirPath("/system/lib/drm");
+ loadPlugIns(pluginDirPath);
+ return DRM_NO_ERROR;
+
+}
+
+status_t DrmManager::loadPlugIns(const String8& plugInDirPath) {
+ mPlugInManager.loadPlugIns(plugInDirPath);
+ Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
+ for (unsigned int i = 0; i < plugInPathList.size(); ++i) {
+ String8 plugInPath = plugInPathList[i];
+ DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
+ if (NULL != info) {
+ if (mSupportInfoToPlugInIdMap.indexOfKey(*info) < 0) {
+ mSupportInfoToPlugInIdMap.add(*info, plugInPath);
+ }
+ delete info;
+ }
+ }
+ return DRM_NO_ERROR;
+}
+
+status_t DrmManager::unloadPlugIns() {
+ Mutex::Autolock _l(mLock);
+ mConvertSessionMap.clear();
+ mDecryptSessionMap.clear();
+ mPlugInManager.unloadPlugIns();
+ mSupportInfoToPlugInIdMap.clear();
+ return DRM_NO_ERROR;
+}
+
+status_t DrmManager::setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
+ Mutex::Autolock _l(mListenerLock);
+ if (NULL != drmServiceListener.get()) {
+ mServiceListeners.add(uniqueId, drmServiceListener);
+ } else {
+ mServiceListeners.removeItem(uniqueId);
+ }
+ return DRM_NO_ERROR;
+}
+
+void DrmManager::addClient(int uniqueId) {
+ Mutex::Autolock _l(mLock);
+ if (!mSupportInfoToPlugInIdMap.isEmpty()) {
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
+ rDrmEngine.initialize(uniqueId);
+ rDrmEngine.setOnInfoListener(uniqueId, this);
+ }
+ }
+}
+
+void DrmManager::removeClient(int uniqueId) {
+ Mutex::Autolock _l(mLock);
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
+ rDrmEngine.terminate(uniqueId);
+ }
+}
+
+DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, const int action) {
+ Mutex::Autolock _l(mLock);
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.getConstraints(uniqueId, path, action);
+ }
+ return NULL;
+}
+
+DrmMetadata* DrmManager::getMetadata(int uniqueId, const String8* path) {
+ Mutex::Autolock _l(mLock);
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.getMetadata(uniqueId, path);
+ }
+ return NULL;
+}
+
+status_t DrmManager::installDrmEngine(int uniqueId, const String8& absolutePath) {
+ Mutex::Autolock _l(mLock);
+ mPlugInManager.loadPlugIn(absolutePath);
+
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(absolutePath);
+ rDrmEngine.initialize(uniqueId);
+ rDrmEngine.setOnInfoListener(uniqueId, this);
+
+ DrmSupportInfo* info = rDrmEngine.getSupportInfo(0);
+ mSupportInfoToPlugInIdMap.add(*info, absolutePath);
+ delete info;
+
+ return DRM_NO_ERROR;
+}
+
+bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+ Mutex::Autolock _l(mLock);
+ const String8 plugInId = getSupportedPlugInId(mimeType);
+ bool result = (EMPTY_STRING != plugInId) ? true : false;
+
+ if (0 < path.length()) {
+ if (result) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ result = rDrmEngine.canHandle(uniqueId, path);
+ } else {
+ String8 extension = path.getPathExtension();
+ if (String8("") != extension) {
+ result = canHandle(uniqueId, path);
+ }
+ }
+ }
+ return result;
+}
+
+DrmInfoStatus* DrmManager::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ Mutex::Autolock _l(mLock);
+ const String8 plugInId = getSupportedPlugInId(drmInfo->getMimeType());
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.processDrmInfo(uniqueId, drmInfo);
+ }
+ return NULL;
+}
+
+bool DrmManager::canHandle(int uniqueId, const String8& path) {
+ bool result = false;
+ Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
+
+ for (unsigned int i = 0; i < plugInPathList.size(); ++i) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInPathList[i]);
+ result = rDrmEngine.canHandle(uniqueId, path);
+
+ if (result) {
+ break;
+ }
+ }
+ return result;
+}
+
+DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ Mutex::Autolock _l(mLock);
+ const String8 plugInId = getSupportedPlugInId(drmInfoRequest->getMimeType());
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
+ }
+ return NULL;
+}
+
+status_t DrmManager::saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ Mutex::Autolock _l(mLock);
+ const String8 plugInId = getSupportedPlugInId(drmRights.getMimeType());
+ status_t result = DRM_ERROR_UNKNOWN;
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath);
+ }
+ return result;
+}
+
+String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path) {
+ Mutex::Autolock _l(mLock);
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.getOriginalMimeType(uniqueId, path);
+ }
+ return EMPTY_STRING;
+}
+
+int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) {
+ Mutex::Autolock _l(mLock);
+ const String8 plugInId = getSupportedPlugInId(uniqueId, path, mimeType);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
+ }
+ return DrmObjectType::UNKNOWN;
+}
+
+int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action) {
+ Mutex::Autolock _l(mLock);
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.checkRightsStatus(uniqueId, path, action);
+ }
+ return RightsStatus::RIGHTS_INVALID;
+}
+
+status_t DrmManager::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ status_t result = DRM_ERROR_UNKNOWN;
+ Mutex::Autolock _l(mDecryptLock);
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->consumeRights(uniqueId, decryptHandle, action, reserve);
+ }
+ return result;
+}
+
+status_t DrmManager::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) {
+ status_t result = DRM_ERROR_UNKNOWN;
+ Mutex::Autolock _l(mDecryptLock);
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
+ }
+ return result;
+}
+
+bool DrmManager::validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description) {
+ Mutex::Autolock _l(mLock);
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ return rDrmEngine.validateAction(uniqueId, path, action, description);
+ }
+ return false;
+}
+
+status_t DrmManager::removeRights(int uniqueId, const String8& path) {
+ Mutex::Autolock _l(mLock);
+ const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ status_t result = DRM_ERROR_UNKNOWN;
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ result = rDrmEngine.removeRights(uniqueId, path);
+ }
+ return result;
+}
+
+status_t DrmManager::removeAllRights(int uniqueId) {
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+ status_t result = DRM_ERROR_UNKNOWN;
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
+ result = rDrmEngine.removeAllRights(uniqueId);
+ if (DRM_NO_ERROR != result) {
+ break;
+ }
+ }
+ return result;
+}
+
+int DrmManager::openConvertSession(int uniqueId, const String8& mimeType) {
+ Mutex::Autolock _l(mConvertLock);
+ int convertId = -1;
+
+ const String8 plugInId = getSupportedPlugInId(mimeType);
+ if (EMPTY_STRING != plugInId) {
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+
+ if (DRM_NO_ERROR == rDrmEngine.openConvertSession(uniqueId, mConvertId + 1)) {
+ ++mConvertId;
+ convertId = mConvertId;
+ mConvertSessionMap.add(convertId, &rDrmEngine);
+ }
+ }
+ return convertId;
+}
+
+DrmConvertedStatus* DrmManager::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ DrmConvertedStatus *drmConvertedStatus = NULL;
+
+ Mutex::Autolock _l(mConvertLock);
+ if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId);
+ drmConvertedStatus = drmEngine->convertData(uniqueId, convertId, inputData);
+ }
+ return drmConvertedStatus;
+}
+
+DrmConvertedStatus* DrmManager::closeConvertSession(int uniqueId, int convertId) {
+ Mutex::Autolock _l(mConvertLock);
+ DrmConvertedStatus *drmConvertedStatus = NULL;
+
+ if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId);
+ drmConvertedStatus = drmEngine->closeConvertSession(uniqueId, convertId);
+ mConvertSessionMap.removeItem(convertId);
+ }
+ return drmConvertedStatus;
+}
+
+status_t DrmManager::getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+ Mutex::Autolock _l(mLock);
+ Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
+ int size = plugInPathList.size();
+ int validPlugins = 0;
+
+ if (0 < size) {
+ Vector<DrmSupportInfo> drmSupportInfoList;
+
+ for (int i = 0; i < size; ++i) {
+ String8 plugInPath = plugInPathList[i];
+ DrmSupportInfo* drmSupportInfo
+ = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
+ if (NULL != drmSupportInfo) {
+ drmSupportInfoList.add(*drmSupportInfo);
+ delete drmSupportInfo; drmSupportInfo = NULL;
+ }
+ }
+
+ validPlugins = drmSupportInfoList.size();
+ if (0 < validPlugins) {
+ *drmSupportInfoArray = new DrmSupportInfo[validPlugins];
+ for (int i = 0; i < validPlugins; ++i) {
+ (*drmSupportInfoArray)[i] = drmSupportInfoList[i];
+ }
+ }
+ }
+ *length = validPlugins;
+ return DRM_NO_ERROR;
+}
+
+DecryptHandle* DrmManager::openDecryptSession(
+ int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) {
+
+ Mutex::Autolock _l(mDecryptLock);
+ status_t result = DRM_ERROR_CANNOT_HANDLE;
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+
+ DecryptHandle* handle = new DecryptHandle();
+ if (NULL != handle) {
+ handle->decryptId = mDecryptSessionId + 1;
+
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ String8 plugInId = plugInIdList.itemAt(index);
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ result = rDrmEngine.openDecryptSession(uniqueId, handle, fd, offset, length, mime);
+
+ if (DRM_NO_ERROR == result) {
+ ++mDecryptSessionId;
+ mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
+ break;
+ }
+ }
+ }
+ if (DRM_NO_ERROR != result) {
+ delete handle; handle = NULL;
+ }
+ return handle;
+}
+
+DecryptHandle* DrmManager::openDecryptSession(
+ int uniqueId, const char* uri, const char* mime) {
+ Mutex::Autolock _l(mDecryptLock);
+ status_t result = DRM_ERROR_CANNOT_HANDLE;
+ Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
+
+ DecryptHandle* handle = new DecryptHandle();
+ if (NULL != handle) {
+ handle->decryptId = mDecryptSessionId + 1;
+
+ for (unsigned int index = 0; index < plugInIdList.size(); index++) {
+ String8 plugInId = plugInIdList.itemAt(index);
+ IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
+ result = rDrmEngine.openDecryptSession(uniqueId, handle, uri, mime);
+
+ if (DRM_NO_ERROR == result) {
+ ++mDecryptSessionId;
+ mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
+ break;
+ }
+ }
+ }
+ if (DRM_NO_ERROR != result) {
+ delete handle; handle = NULL;
+ ALOGV("DrmManager::openDecryptSession: no capable plug-in found");
+ }
+ return handle;
+}
+
+status_t DrmManager::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ Mutex::Autolock _l(mDecryptLock);
+ status_t result = DRM_ERROR_UNKNOWN;
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->closeDecryptSession(uniqueId, decryptHandle);
+ if (DRM_NO_ERROR == result) {
+ mDecryptSessionMap.removeItem(decryptHandle->decryptId);
+ }
+ }
+ return result;
+}
+
+status_t DrmManager::initializeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+ status_t result = DRM_ERROR_UNKNOWN;
+ Mutex::Autolock _l(mDecryptLock);
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->initializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo);
+ }
+ return result;
+}
+
+status_t DrmManager::decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ status_t result = DRM_ERROR_UNKNOWN;
+
+ Mutex::Autolock _l(mDecryptLock);
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->decrypt(
+ uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
+ }
+ return result;
+}
+
+status_t DrmManager::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ status_t result = DRM_ERROR_UNKNOWN;
+ Mutex::Autolock _l(mDecryptLock);
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+ }
+ return result;
+}
+
+ssize_t DrmManager::pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset) {
+ ssize_t result = DECRYPT_FILE_ERROR;
+
+ Mutex::Autolock _l(mDecryptLock);
+ if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
+ IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
+ result = drmEngine->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
+ }
+ return result;
+}
+
+String8 DrmManager::getSupportedPlugInId(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ String8 plugInId("");
+
+ if (EMPTY_STRING != mimeType) {
+ plugInId = getSupportedPlugInId(mimeType);
+ } else {
+ plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
+ }
+ return plugInId;
+}
+
+String8 DrmManager::getSupportedPlugInId(const String8& mimeType) {
+ String8 plugInId("");
+
+ if (EMPTY_STRING != mimeType) {
+ for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
+ const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
+
+ if (drmSupportInfo.isSupportedMimeType(mimeType)) {
+ plugInId = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo);
+ break;
+ }
+ }
+ }
+ return plugInId;
+}
+
+String8 DrmManager::getSupportedPlugInIdFromPath(int uniqueId, const String8& path) {
+ String8 plugInId("");
+ const String8 fileSuffix = path.getPathExtension();
+
+ for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
+ const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
+
+ if (drmSupportInfo.isSupportedFileSuffix(fileSuffix)) {
+ String8 key = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo);
+ IDrmEngine& drmEngine = mPlugInManager.getPlugIn(key);
+
+ if (drmEngine.canHandle(uniqueId, path)) {
+ plugInId = key;
+ break;
+ }
+ }
+ }
+ return plugInId;
+}
+
+void DrmManager::onInfo(const DrmInfoEvent& event) {
+ Mutex::Autolock _l(mListenerLock);
+ for (unsigned int index = 0; index < mServiceListeners.size(); index++) {
+ int uniqueId = mServiceListeners.keyAt(index);
+
+ if (uniqueId == event.getUniqueId()) {
+ sp<IDrmServiceListener> serviceListener = mServiceListeners.valueFor(uniqueId);
+ serviceListener->notify(event);
+ }
+ }
+}
+
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
new file mode 100644
index 0000000..8ba0203
--- /dev/null
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -0,0 +1,308 @@
+/*
+ * 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 "DrmManagerService(Native)"
+#include <utils/Log.h>
+
+#include <private/android_filesystem_config.h>
+#include <media/MemoryLeakTrackUtil.h>
+
+#include <errno.h>
+#include <utils/threads.h>
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <sys/stat.h>
+#include "DrmManagerService.h"
+#include "DrmManager.h"
+
+using namespace android;
+
+static Vector<uid_t> trustedUids;
+
+static bool isProtectedCallAllowed() {
+ // TODO
+ // Following implementation is just for reference.
+ // Each OEM manufacturer should implement/replace with their own solutions.
+ bool result = false;
+
+ IPCThreadState* ipcState = IPCThreadState::self();
+ uid_t uid = ipcState->getCallingUid();
+
+ for (unsigned int i = 0; i < trustedUids.size(); ++i) {
+ if (trustedUids[i] == uid) {
+ result = true;
+ break;
+ }
+ }
+ return result;
+}
+
+void DrmManagerService::instantiate() {
+ ALOGV("instantiate");
+ defaultServiceManager()->addService(String16("drm.drmManager"), new DrmManagerService());
+
+ if (0 >= trustedUids.size()) {
+ // TODO
+ // Following implementation is just for reference.
+ // Each OEM manufacturer should implement/replace with their own solutions.
+
+ // Add trusted uids here
+ trustedUids.push(AID_MEDIA);
+ }
+}
+
+DrmManagerService::DrmManagerService() :
+ mDrmManager(NULL) {
+ ALOGV("created");
+ mDrmManager = new DrmManager();
+ mDrmManager->loadPlugIns();
+}
+
+DrmManagerService::~DrmManagerService() {
+ ALOGV("Destroyed");
+ mDrmManager->unloadPlugIns();
+ delete mDrmManager; mDrmManager = NULL;
+}
+
+int DrmManagerService::addUniqueId(bool isNative) {
+ return mDrmManager->addUniqueId(isNative);
+}
+
+void DrmManagerService::removeUniqueId(int uniqueId) {
+ mDrmManager->removeUniqueId(uniqueId);
+}
+
+void DrmManagerService::addClient(int uniqueId) {
+ mDrmManager->addClient(uniqueId);
+}
+
+void DrmManagerService::removeClient(int uniqueId) {
+ mDrmManager->removeClient(uniqueId);
+}
+
+status_t DrmManagerService::setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
+ ALOGV("Entering setDrmServiceListener");
+ mDrmManager->setDrmServiceListener(uniqueId, drmServiceListener);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmManagerService::installDrmEngine(int uniqueId, const String8& drmEngineFile) {
+ ALOGV("Entering installDrmEngine");
+ return mDrmManager->installDrmEngine(uniqueId, drmEngineFile);
+}
+
+DrmConstraints* DrmManagerService::getConstraints(
+ int uniqueId, const String8* path, const int action) {
+ ALOGV("Entering getConstraints from content");
+ return mDrmManager->getConstraints(uniqueId, path, action);
+}
+
+DrmMetadata* DrmManagerService::getMetadata(int uniqueId, const String8* path) {
+ ALOGV("Entering getMetadata from content");
+ return mDrmManager->getMetadata(uniqueId, path);
+}
+
+bool DrmManagerService::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
+ ALOGV("Entering canHandle");
+ return mDrmManager->canHandle(uniqueId, path, mimeType);
+}
+
+DrmInfoStatus* DrmManagerService::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ ALOGV("Entering processDrmInfo");
+ return mDrmManager->processDrmInfo(uniqueId, drmInfo);
+}
+
+DrmInfo* DrmManagerService::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ ALOGV("Entering acquireDrmInfo");
+ return mDrmManager->acquireDrmInfo(uniqueId, drmInfoRequest);
+}
+
+status_t DrmManagerService::saveRights(
+ int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ ALOGV("Entering saveRights");
+ return mDrmManager->saveRights(uniqueId, drmRights, rightsPath, contentPath);
+}
+
+String8 DrmManagerService::getOriginalMimeType(int uniqueId, const String8& path) {
+ ALOGV("Entering getOriginalMimeType");
+ return mDrmManager->getOriginalMimeType(uniqueId, path);
+}
+
+int DrmManagerService::getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ ALOGV("Entering getDrmObjectType");
+ return mDrmManager->getDrmObjectType(uniqueId, path, mimeType);
+}
+
+int DrmManagerService::checkRightsStatus(
+ int uniqueId, const String8& path, int action) {
+ ALOGV("Entering checkRightsStatus");
+ return mDrmManager->checkRightsStatus(uniqueId, path, action);
+}
+
+status_t DrmManagerService::consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
+ ALOGV("Entering consumeRights");
+ if (!isProtectedCallAllowed()) {
+ return DRM_ERROR_NO_PERMISSION;
+ }
+ return mDrmManager->consumeRights(uniqueId, decryptHandle, action, reserve);
+}
+
+status_t DrmManagerService::setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) {
+ ALOGV("Entering setPlaybackStatus");
+ if (!isProtectedCallAllowed()) {
+ return DRM_ERROR_NO_PERMISSION;
+ }
+ return mDrmManager->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
+}
+
+bool DrmManagerService::validateAction(
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ ALOGV("Entering validateAction");
+ return mDrmManager->validateAction(uniqueId, path, action, description);
+}
+
+status_t DrmManagerService::removeRights(int uniqueId, const String8& path) {
+ ALOGV("Entering removeRights");
+ return mDrmManager->removeRights(uniqueId, path);
+}
+
+status_t DrmManagerService::removeAllRights(int uniqueId) {
+ ALOGV("Entering removeAllRights");
+ return mDrmManager->removeAllRights(uniqueId);
+}
+
+int DrmManagerService::openConvertSession(int uniqueId, const String8& mimeType) {
+ ALOGV("Entering openConvertSession");
+ return mDrmManager->openConvertSession(uniqueId, mimeType);
+}
+
+DrmConvertedStatus* DrmManagerService::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ ALOGV("Entering convertData");
+ return mDrmManager->convertData(uniqueId, convertId, inputData);
+}
+
+DrmConvertedStatus* DrmManagerService::closeConvertSession(int uniqueId, int convertId) {
+ ALOGV("Entering closeConvertSession");
+ return mDrmManager->closeConvertSession(uniqueId, convertId);
+}
+
+status_t DrmManagerService::getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+ ALOGV("Entering getAllSupportInfo");
+ return mDrmManager->getAllSupportInfo(uniqueId, length, drmSupportInfoArray);
+}
+
+DecryptHandle* DrmManagerService::openDecryptSession(
+ int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) {
+ ALOGV("Entering DrmManagerService::openDecryptSession");
+ if (isProtectedCallAllowed()) {
+ return mDrmManager->openDecryptSession(uniqueId, fd, offset, length, mime);
+ }
+
+ return NULL;
+}
+
+DecryptHandle* DrmManagerService::openDecryptSession(
+ int uniqueId, const char* uri, const char* mime) {
+ ALOGV("Entering DrmManagerService::openDecryptSession with uri");
+ if (isProtectedCallAllowed()) {
+ return mDrmManager->openDecryptSession(uniqueId, uri, mime);
+ }
+
+ return NULL;
+}
+
+status_t DrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ ALOGV("Entering closeDecryptSession");
+ if (!isProtectedCallAllowed()) {
+ return DRM_ERROR_NO_PERMISSION;
+ }
+ return mDrmManager->closeDecryptSession(uniqueId, decryptHandle);
+}
+
+status_t DrmManagerService::initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ ALOGV("Entering initializeDecryptUnit");
+ if (!isProtectedCallAllowed()) {
+ return DRM_ERROR_NO_PERMISSION;
+ }
+ return mDrmManager->initializeDecryptUnit(uniqueId,decryptHandle, decryptUnitId, headerInfo);
+}
+
+status_t DrmManagerService::decrypt(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ ALOGV("Entering decrypt");
+ if (!isProtectedCallAllowed()) {
+ return DRM_ERROR_NO_PERMISSION;
+ }
+ return mDrmManager->decrypt(uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
+}
+
+status_t DrmManagerService::finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ ALOGV("Entering finalizeDecryptUnit");
+ if (!isProtectedCallAllowed()) {
+ return DRM_ERROR_NO_PERMISSION;
+ }
+ return mDrmManager->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
+}
+
+ssize_t DrmManagerService::pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset) {
+ ALOGV("Entering pread");
+ if (!isProtectedCallAllowed()) {
+ return DRM_ERROR_NO_PERMISSION;
+ }
+ return mDrmManager->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
+}
+
+status_t DrmManagerService::dump(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+ snprintf(buffer, SIZE, "Permission Denial: "
+ "can't dump DrmManagerService from pid=%d, uid=%d\n",
+ IPCThreadState::self()->getCallingPid(),
+ IPCThreadState::self()->getCallingUid());
+ result.append(buffer);
+ } else {
+#if DRM_MEMORY_LEAK_TRACK
+ bool dumpMem = false;
+ for (size_t i = 0; i < args.size(); i++) {
+ if (args[i] == String16("-m")) {
+ dumpMem = true;
+ }
+ }
+ if (dumpMem) {
+ dumpMemoryAddresses(fd);
+ }
+#endif
+ }
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
diff --git a/drm/drmserver/main_drmserver.cpp b/drm/drmserver/main_drmserver.cpp
new file mode 100644
index 0000000..434d561
--- /dev/null
+++ b/drm/drmserver/main_drmserver.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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 "drmserver"
+//#define LOG_NDEBUG 0
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+#include <DrmManagerService.h>
+
+using namespace android;
+
+int main(int argc, char** argv)
+{
+ sp<ProcessState> proc(ProcessState::self());
+ sp<IServiceManager> sm = defaultServiceManager();
+ ALOGV("ServiceManager: %p", sm.get());
+ DrmManagerService::instantiate();
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+}
+
diff --git a/drm/libdrmframework/Android.mk b/drm/libdrmframework/Android.mk
new file mode 100644
index 0000000..c534402
--- /dev/null
+++ b/drm/libdrmframework/Android.mk
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ DrmManagerClientImpl.cpp \
+ DrmManagerClient.cpp
+
+LOCAL_MODULE:= libdrmframework
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libbinder \
+ libdl
+
+LOCAL_STATIC_LIBRARIES := \
+ libdrmframeworkcommon
+
+LOCAL_C_INCLUDES += \
+ $(TOP)/frameworks/base/drm/libdrmframework/include \
+ $(TOP)/frameworks/base/include
+
+
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
new file mode 100644
index 0000000..8768c08
--- /dev/null
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -0,0 +1,160 @@
+/*
+ * 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 <utils/String8.h>
+#include <binder/IServiceManager.h>
+#include <drm/DrmManagerClient.h>
+
+#include "DrmManagerClientImpl.h"
+
+using namespace android;
+
+DrmManagerClient::DrmManagerClient():
+ mUniqueId(0), mDrmManagerClientImpl(NULL) {
+ mDrmManagerClientImpl = DrmManagerClientImpl::create(&mUniqueId, true);
+ mDrmManagerClientImpl->addClient(mUniqueId);
+}
+
+DrmManagerClient::~DrmManagerClient() {
+ DrmManagerClientImpl::remove(mUniqueId);
+ mDrmManagerClientImpl->removeClient(mUniqueId);
+ mDrmManagerClientImpl->setOnInfoListener(mUniqueId, NULL);
+}
+
+status_t DrmManagerClient::setOnInfoListener(
+ const sp<DrmManagerClient::OnInfoListener>& infoListener) {
+ return mDrmManagerClientImpl->setOnInfoListener(mUniqueId, infoListener);
+}
+
+DrmConstraints* DrmManagerClient::getConstraints(const String8* path, const int action) {
+ return mDrmManagerClientImpl->getConstraints(mUniqueId, path, action);
+}
+
+DrmMetadata* DrmManagerClient::getMetadata(const String8* path) {
+ return mDrmManagerClientImpl->getMetadata(mUniqueId, path);
+}
+
+bool DrmManagerClient::canHandle(const String8& path, const String8& mimeType) {
+ return mDrmManagerClientImpl->canHandle(mUniqueId, path, mimeType);
+}
+
+DrmInfoStatus* DrmManagerClient::processDrmInfo(const DrmInfo* drmInfo) {
+ return mDrmManagerClientImpl->processDrmInfo(mUniqueId, drmInfo);
+}
+
+DrmInfo* DrmManagerClient::acquireDrmInfo(const DrmInfoRequest* drmInfoRequest) {
+ return mDrmManagerClientImpl->acquireDrmInfo(mUniqueId, drmInfoRequest);
+}
+
+status_t DrmManagerClient::saveRights(
+ const DrmRights& drmRights, const String8& rightsPath, const String8& contentPath) {
+ return mDrmManagerClientImpl->saveRights(mUniqueId, drmRights, rightsPath, contentPath);
+}
+
+String8 DrmManagerClient::getOriginalMimeType(const String8& path) {
+ return mDrmManagerClientImpl->getOriginalMimeType(mUniqueId, path);
+}
+
+int DrmManagerClient::getDrmObjectType(const String8& path, const String8& mimeType) {
+ return mDrmManagerClientImpl->getDrmObjectType( mUniqueId, path, mimeType);
+}
+
+int DrmManagerClient::checkRightsStatus(const String8& path, int action) {
+ return mDrmManagerClientImpl->checkRightsStatus(mUniqueId, path, action);
+}
+
+status_t DrmManagerClient::consumeRights(
+ sp<DecryptHandle> &decryptHandle, int action, bool reserve) {
+ return mDrmManagerClientImpl->consumeRights(mUniqueId, decryptHandle, action, reserve);
+}
+
+status_t DrmManagerClient::setPlaybackStatus(
+ sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position) {
+ return mDrmManagerClientImpl
+ ->setPlaybackStatus(mUniqueId, decryptHandle, playbackStatus, position);
+}
+
+bool DrmManagerClient::validateAction(
+ const String8& path, int action, const ActionDescription& description) {
+ return mDrmManagerClientImpl->validateAction(mUniqueId, path, action, description);
+}
+
+status_t DrmManagerClient::removeRights(const String8& path) {
+ return mDrmManagerClientImpl->removeRights(mUniqueId, path);
+}
+
+status_t DrmManagerClient::removeAllRights() {
+ return mDrmManagerClientImpl->removeAllRights(mUniqueId);
+}
+
+int DrmManagerClient::openConvertSession(const String8& mimeType) {
+ return mDrmManagerClientImpl->openConvertSession(mUniqueId, mimeType);
+}
+
+DrmConvertedStatus* DrmManagerClient::convertData(int convertId, const DrmBuffer* inputData) {
+ return mDrmManagerClientImpl->convertData(mUniqueId, convertId, inputData);
+}
+
+DrmConvertedStatus* DrmManagerClient::closeConvertSession(int convertId) {
+ return mDrmManagerClientImpl->closeConvertSession(mUniqueId, convertId);
+}
+
+status_t DrmManagerClient::getAllSupportInfo(int* length, DrmSupportInfo** drmSupportInfoArray) {
+ return mDrmManagerClientImpl->getAllSupportInfo(mUniqueId, length, drmSupportInfoArray);
+}
+
+sp<DecryptHandle> DrmManagerClient::openDecryptSession(
+ int fd, off64_t offset, off64_t length, const char* mime) {
+
+ return mDrmManagerClientImpl->openDecryptSession(
+ mUniqueId, fd, offset, length, mime);
+}
+
+sp<DecryptHandle> DrmManagerClient::openDecryptSession(
+ const char* uri, const char* mime) {
+
+ return mDrmManagerClientImpl->openDecryptSession(
+ mUniqueId, uri, mime);
+}
+
+status_t DrmManagerClient::closeDecryptSession(sp<DecryptHandle> &decryptHandle) {
+ return mDrmManagerClientImpl->closeDecryptSession(mUniqueId, decryptHandle);
+}
+
+status_t DrmManagerClient::initializeDecryptUnit(
+ sp<DecryptHandle> &decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
+ return mDrmManagerClientImpl->initializeDecryptUnit(
+ mUniqueId, decryptHandle, decryptUnitId, headerInfo);
+}
+
+status_t DrmManagerClient::decrypt(
+ sp<DecryptHandle> &decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ return mDrmManagerClientImpl->decrypt(
+ mUniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
+}
+
+status_t DrmManagerClient::finalizeDecryptUnit(
+ sp<DecryptHandle> &decryptHandle, int decryptUnitId) {
+ return mDrmManagerClientImpl->finalizeDecryptUnit(mUniqueId,
+ decryptHandle, decryptUnitId);
+}
+
+ssize_t DrmManagerClient::pread(
+ sp<DecryptHandle> &decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) {
+ return mDrmManagerClientImpl->pread(mUniqueId, decryptHandle, buffer, numBytes, offset);
+}
+
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
new file mode 100644
index 0000000..fb0439e
--- /dev/null
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -0,0 +1,351 @@
+/*
+ * 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 "DrmManagerClientImpl(Native)"
+#include <utils/Log.h>
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <binder/IServiceManager.h>
+
+#include "DrmManagerClientImpl.h"
+
+using namespace android;
+
+#define INVALID_VALUE -1
+
+Mutex DrmManagerClientImpl::sMutex;
+sp<IDrmManagerService> DrmManagerClientImpl::sDrmManagerService;
+sp<DrmManagerClientImpl::DeathNotifier> DrmManagerClientImpl::sDeathNotifier;
+const String8 DrmManagerClientImpl::EMPTY_STRING("");
+
+DrmManagerClientImpl* DrmManagerClientImpl::create(
+ int* pUniqueId, bool isNative) {
+ *pUniqueId = getDrmManagerService()->addUniqueId(isNative);
+
+ return new DrmManagerClientImpl();
+}
+
+void DrmManagerClientImpl::remove(int uniqueId) {
+ getDrmManagerService()->removeUniqueId(uniqueId);
+}
+
+const sp<IDrmManagerService>& DrmManagerClientImpl::getDrmManagerService() {
+ Mutex::Autolock lock(sMutex);
+ if (NULL == sDrmManagerService.get()) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder;
+ do {
+ binder = sm->getService(String16("drm.drmManager"));
+ if (binder != 0) {
+ break;
+ }
+ ALOGW("DrmManagerService not published, waiting...");
+ struct timespec reqt;
+ reqt.tv_sec = 0;
+ reqt.tv_nsec = 500000000; //0.5 sec
+ nanosleep(&reqt, NULL);
+ } while (true);
+ if (NULL == sDeathNotifier.get()) {
+ sDeathNotifier = new DeathNotifier();
+ }
+ binder->linkToDeath(sDeathNotifier);
+ sDrmManagerService = interface_cast<IDrmManagerService>(binder);
+ }
+ return sDrmManagerService;
+}
+
+void DrmManagerClientImpl::addClient(int uniqueId) {
+ getDrmManagerService()->addClient(uniqueId);
+}
+
+void DrmManagerClientImpl::removeClient(int uniqueId) {
+ getDrmManagerService()->removeClient(uniqueId);
+}
+
+status_t DrmManagerClientImpl::setOnInfoListener(
+ int uniqueId,
+ const sp<DrmManagerClient::OnInfoListener>& infoListener) {
+ Mutex::Autolock _l(mLock);
+ mOnInfoListener = infoListener;
+ return getDrmManagerService()->setDrmServiceListener(uniqueId,
+ (NULL != infoListener.get()) ? this : NULL);
+}
+
+status_t DrmManagerClientImpl::installDrmEngine(
+ int uniqueId, const String8& drmEngineFile) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (EMPTY_STRING != drmEngineFile) {
+ status = getDrmManagerService()->installDrmEngine(uniqueId, drmEngineFile);
+ }
+ return status;
+}
+
+DrmConstraints* DrmManagerClientImpl::getConstraints(
+ int uniqueId, const String8* path, const int action) {
+ DrmConstraints *drmConstraints = NULL;
+ if ((NULL != path) && (EMPTY_STRING != *path)) {
+ drmConstraints =
+ getDrmManagerService()->getConstraints(uniqueId, path, action);
+ }
+ return drmConstraints;
+}
+
+DrmMetadata* DrmManagerClientImpl::getMetadata(int uniqueId, const String8* path) {
+ DrmMetadata *drmMetadata = NULL;
+ if ((NULL != path) && (EMPTY_STRING != *path)) {
+ drmMetadata = getDrmManagerService()->getMetadata(uniqueId, path);
+ }
+ return drmMetadata;
+}
+
+bool DrmManagerClientImpl::canHandle(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ bool retCode = false;
+ if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) {
+ retCode = getDrmManagerService()->canHandle(uniqueId, path, mimeType);
+ }
+ return retCode;
+}
+
+DrmInfoStatus* DrmManagerClientImpl::processDrmInfo(
+ int uniqueId, const DrmInfo* drmInfo) {
+ DrmInfoStatus *drmInfoStatus = NULL;
+ if (NULL != drmInfo) {
+ drmInfoStatus = getDrmManagerService()->processDrmInfo(uniqueId, drmInfo);
+ }
+ return drmInfoStatus;
+}
+
+DrmInfo* DrmManagerClientImpl::acquireDrmInfo(
+ int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ DrmInfo* drmInfo = NULL;
+ if (NULL != drmInfoRequest) {
+ drmInfo = getDrmManagerService()->acquireDrmInfo(uniqueId, drmInfoRequest);
+ }
+ return drmInfo;
+}
+
+status_t DrmManagerClientImpl::saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ return getDrmManagerService()->saveRights(
+ uniqueId, drmRights, rightsPath, contentPath);
+}
+
+String8 DrmManagerClientImpl::getOriginalMimeType(
+ int uniqueId, const String8& path) {
+ String8 mimeType = EMPTY_STRING;
+ if (EMPTY_STRING != path) {
+ mimeType = getDrmManagerService()->getOriginalMimeType(uniqueId, path);
+ }
+ return mimeType;
+}
+
+int DrmManagerClientImpl::getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ int drmOjectType = DrmObjectType::UNKNOWN;
+ if ((EMPTY_STRING != path) || (EMPTY_STRING != mimeType)) {
+ drmOjectType =
+ getDrmManagerService()->getDrmObjectType(uniqueId, path, mimeType);
+ }
+ return drmOjectType;
+}
+
+int DrmManagerClientImpl::checkRightsStatus(
+ int uniqueId, const String8& path, int action) {
+ int rightsStatus = RightsStatus::RIGHTS_INVALID;
+ if (EMPTY_STRING != path) {
+ rightsStatus =
+ getDrmManagerService()->checkRightsStatus(uniqueId, path, action);
+ }
+ return rightsStatus;
+}
+
+status_t DrmManagerClientImpl::consumeRights(
+ int uniqueId, sp<DecryptHandle> &decryptHandle,
+ int action, bool reserve) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (NULL != decryptHandle.get()) {
+ status = getDrmManagerService()->consumeRights(
+ uniqueId, decryptHandle.get(), action, reserve);
+ }
+ return status;
+}
+
+status_t DrmManagerClientImpl::setPlaybackStatus(
+ int uniqueId, sp<DecryptHandle> &decryptHandle,
+ int playbackStatus, int64_t position) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (NULL != decryptHandle.get()) {
+ status = getDrmManagerService()->setPlaybackStatus(
+ uniqueId, decryptHandle.get(), playbackStatus, position);
+ }
+ return status;
+}
+
+bool DrmManagerClientImpl::validateAction(
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ bool retCode = false;
+ if (EMPTY_STRING != path) {
+ retCode = getDrmManagerService()->validateAction(
+ uniqueId, path, action, description);
+ }
+ return retCode;
+}
+
+status_t DrmManagerClientImpl::removeRights(int uniqueId, const String8& path) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (EMPTY_STRING != path) {
+ status = getDrmManagerService()->removeRights(uniqueId, path);
+ }
+ return status;
+}
+
+status_t DrmManagerClientImpl::removeAllRights(int uniqueId) {
+ return getDrmManagerService()->removeAllRights(uniqueId);
+}
+
+int DrmManagerClientImpl::openConvertSession(
+ int uniqueId, const String8& mimeType) {
+ int retCode = INVALID_VALUE;
+ if (EMPTY_STRING != mimeType) {
+ retCode = getDrmManagerService()->openConvertSession(uniqueId, mimeType);
+ }
+ return retCode;
+}
+
+DrmConvertedStatus* DrmManagerClientImpl::convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ DrmConvertedStatus* drmConvertedStatus = NULL;
+ if (NULL != inputData) {
+ drmConvertedStatus =
+ getDrmManagerService()->convertData(uniqueId, convertId, inputData);
+ }
+ return drmConvertedStatus;
+}
+
+DrmConvertedStatus* DrmManagerClientImpl::closeConvertSession(
+ int uniqueId, int convertId) {
+ return getDrmManagerService()->closeConvertSession(uniqueId, convertId);
+}
+
+status_t DrmManagerClientImpl::getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if ((NULL != drmSupportInfoArray) && (NULL != length)) {
+ status = getDrmManagerService()->getAllSupportInfo(
+ uniqueId, length, drmSupportInfoArray);
+ }
+ return status;
+}
+
+sp<DecryptHandle> DrmManagerClientImpl::openDecryptSession(
+ int uniqueId, int fd, off64_t offset,
+ off64_t length, const char* mime) {
+
+ return getDrmManagerService()->openDecryptSession(
+ uniqueId, fd, offset, length, mime);
+}
+
+sp<DecryptHandle> DrmManagerClientImpl::openDecryptSession(
+ int uniqueId, const char* uri, const char* mime) {
+
+ DecryptHandle* handle = NULL;
+ if (NULL != uri) {
+ handle = getDrmManagerService()->openDecryptSession(uniqueId, uri, mime);
+ }
+ return handle;
+}
+
+status_t DrmManagerClientImpl::closeDecryptSession(
+ int uniqueId, sp<DecryptHandle> &decryptHandle) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (NULL != decryptHandle.get()) {
+ status = getDrmManagerService()->closeDecryptSession(
+ uniqueId, decryptHandle.get());
+ }
+ return status;
+}
+
+status_t DrmManagerClientImpl::initializeDecryptUnit(
+ int uniqueId, sp<DecryptHandle> &decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if ((NULL != decryptHandle.get()) && (NULL != headerInfo)) {
+ status = getDrmManagerService()->initializeDecryptUnit(
+ uniqueId, decryptHandle.get(), decryptUnitId, headerInfo);
+ }
+ return status;
+}
+
+status_t DrmManagerClientImpl::decrypt(
+ int uniqueId, sp<DecryptHandle> &decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer,
+ DrmBuffer** decBuffer, DrmBuffer* IV) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if ((NULL != decryptHandle.get()) && (NULL != encBuffer)
+ && (NULL != decBuffer) && (NULL != *decBuffer)) {
+ status = getDrmManagerService()->decrypt(
+ uniqueId, decryptHandle.get(), decryptUnitId,
+ encBuffer, decBuffer, IV);
+ }
+ return status;
+}
+
+status_t DrmManagerClientImpl::finalizeDecryptUnit(
+ int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId) {
+ status_t status = DRM_ERROR_UNKNOWN;
+ if (NULL != decryptHandle.get()) {
+ status = getDrmManagerService()->finalizeDecryptUnit(
+ uniqueId, decryptHandle.get(), decryptUnitId);
+ }
+ return status;
+}
+
+ssize_t DrmManagerClientImpl::pread(int uniqueId, sp<DecryptHandle> &decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset) {
+ ssize_t retCode = INVALID_VALUE;
+ if ((NULL != decryptHandle.get()) && (NULL != buffer) && (0 < numBytes)) {
+ retCode = getDrmManagerService()->pread(
+ uniqueId, decryptHandle.get(), buffer, numBytes, offset);
+ }
+ return retCode;
+}
+
+status_t DrmManagerClientImpl::notify(const DrmInfoEvent& event) {
+ if (NULL != mOnInfoListener.get()) {
+ Mutex::Autolock _l(mLock);
+ sp<DrmManagerClient::OnInfoListener> listener = mOnInfoListener;
+ listener->onInfo(event);
+ }
+ return DRM_NO_ERROR;
+}
+
+DrmManagerClientImpl::DeathNotifier::~DeathNotifier() {
+ Mutex::Autolock lock(sMutex);
+ if (NULL != sDrmManagerService.get()) {
+ sDrmManagerService->asBinder()->unlinkToDeath(this);
+ }
+}
+
+void DrmManagerClientImpl::DeathNotifier::binderDied(const wp<IBinder>& who) {
+ Mutex::Autolock lock(sMutex);
+ DrmManagerClientImpl::sDrmManagerService.clear();
+ ALOGW("DrmManager server died!");
+}
+
diff --git a/drm/libdrmframework/include/DrmManager.h b/drm/libdrmframework/include/DrmManager.h
new file mode 100644
index 0000000..c9167d4
--- /dev/null
+++ b/drm/libdrmframework/include/DrmManager.h
@@ -0,0 +1,163 @@
+/*
+ * 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 __DRM_MANAGER_H__
+#define __DRM_MANAGER_H__
+
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <drm/drm_framework_common.h>
+#include "IDrmEngine.h"
+#include "PlugInManager.h"
+#include "IDrmServiceListener.h"
+
+namespace android {
+
+class IDrmManager;
+class DrmRegistrationInfo;
+class DrmUnregistrationInfo;
+class DrmRightsAcquisitionInfo;
+class DrmConstraints;
+class DrmMetadata;
+class DrmRights;
+class DrmInfo;
+class DrmInfoStatus;
+class DrmConvertedStatus;
+class DrmInfoRequest;
+class DrmSupportInfo;
+class ActionDescription;
+
+/**
+ * This is implementation class for DRM Manager. This class delegates the
+ * functionality to corresponding DRM Engine.
+ *
+ * The DrmManagerService class creates an instance of this class.
+ *
+ */
+class DrmManager : public IDrmEngine::OnInfoListener {
+public:
+ DrmManager();
+ virtual ~DrmManager();
+
+public:
+ int addUniqueId(bool isNative);
+
+ void removeUniqueId(int uniqueId);
+
+ void addClient(int uniqueId);
+
+ void removeClient(int uniqueId);
+
+ status_t loadPlugIns();
+
+ status_t loadPlugIns(const String8& plugInDirPath);
+
+ status_t unloadPlugIns();
+
+ status_t setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener);
+
+ status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
+
+ DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
+
+ DrmMetadata* getMetadata(int uniqueId, const String8* path);
+
+ bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
+
+ DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+
+ status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ int checkRightsStatus(int uniqueId, const String8& path, int action);
+
+ status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ status_t setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position);
+
+ bool validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ status_t removeRights(int uniqueId, const String8& path);
+
+ status_t removeAllRights(int uniqueId);
+
+ int openConvertSession(int uniqueId, const String8& mimeType);
+
+ DrmConvertedStatus* convertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
+
+ DecryptHandle* openDecryptSession(
+ int uniqueId, int fd, off64_t offset, off64_t length, const char* mime);
+
+ DecryptHandle* openDecryptSession(int uniqueId, const char* uri, const char* mime);
+
+ status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+
+ status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset);
+
+ void onInfo(const DrmInfoEvent& event);
+
+private:
+ String8 getSupportedPlugInId(int uniqueId, const String8& path, const String8& mimeType);
+
+ String8 getSupportedPlugInId(const String8& mimeType);
+
+ String8 getSupportedPlugInIdFromPath(int uniqueId, const String8& path);
+
+ bool canHandle(int uniqueId, const String8& path);
+
+private:
+ Vector<int> mUniqueIdVector;
+ static const String8 EMPTY_STRING;
+
+ int mDecryptSessionId;
+ int mConvertId;
+ Mutex mLock;
+ Mutex mListenerLock;
+ Mutex mDecryptLock;
+ Mutex mConvertLock;
+ TPlugInManager<IDrmEngine> mPlugInManager;
+ KeyedVector< DrmSupportInfo, String8 > mSupportInfoToPlugInIdMap;
+ KeyedVector< int, IDrmEngine*> mConvertSessionMap;
+ KeyedVector< int, sp<IDrmServiceListener> > mServiceListeners;
+ KeyedVector< int, IDrmEngine*> mDecryptSessionMap;
+};
+
+};
+
+#endif /* __DRM_MANAGER_H__ */
+
diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h
new file mode 100644
index 0000000..2aa493f
--- /dev/null
+++ b/drm/libdrmframework/include/DrmManagerClientImpl.h
@@ -0,0 +1,432 @@
+/*
+ * 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 __DRM_MANAGER_CLIENT_IMPL_H__
+#define __DRM_MANAGER_CLIENT_IMPL_H__
+
+#include <binder/IMemory.h>
+#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
+
+#include "IDrmManagerService.h"
+
+namespace android {
+
+class DrmInfoEvent;
+/**
+ * This is implementation class for DrmManagerClient class.
+ *
+ * Only the JNI layer creates an instance of this class to delegate
+ * functionality to Native later.
+ *
+ */
+class DrmManagerClientImpl : public BnDrmServiceListener {
+private:
+ DrmManagerClientImpl() { }
+
+public:
+ static DrmManagerClientImpl* create(int* pUniqueId, bool isNative);
+
+ static void remove(int uniqueId);
+
+ virtual ~DrmManagerClientImpl() { }
+
+public:
+ /**
+ * Adds the client respective to given unique id.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ */
+ void addClient(int uniqueId);
+
+ /**
+ * Removes the client respective to given unique id.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ */
+ void removeClient(int uniqueId);
+
+ /**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] infoListener Listener
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t setOnInfoListener(
+ int uniqueId, const sp<DrmManagerClient::OnInfoListener>& infoListener);
+
+ /**
+ * Get constraint information associated with input content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Actions defined such as,
+ * Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ * key-value pairs of constraint are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
+
+ /**
+ * Get metadata information associated with input content.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return DrmMetadata
+ * key-value pairs of metadata are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ DrmMetadata* getMetadata(int uniqueId, const String8* path);
+
+ /**
+ * Check whether the given mimetype or path can be handled
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the content needs to be handled
+ * @param[in] mimetype Mimetype of the content needs to be handled
+ * @return
+ * True if DrmManager can handle given path or mime type.
+ */
+ bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
+
+ /**
+ * Executes given drm information based on its type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfo Information needs to be processed
+ * @return DrmInfoStatus
+ * instance as a result of processing given input
+ */
+ DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ /**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ * instance as a result of processing given input
+ */
+ DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+
+ /**
+ * Save DRM rights to specified rights path
+ * and make association with content path
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmRights DrmRights to be saved
+ * @param[in] rightsPath File path where rights to be saved
+ * @param[in] contentPath File path where content was saved
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ /**
+ * Retrieves the mime type embedded inside the original content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path the path of the protected content
+ * @return String8
+ * Returns mime-type of the original content, such as "video/mpeg"
+ */
+ String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ /**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the content or null.
+ * @param[in] mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+ int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ /**
+ * Check whether the given content has valid rights or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to perform (Action::DEFAULT, Action::PLAY, etc)
+ * @return the status of the rights for the protected content,
+ * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+ int checkRightsStatus(int uniqueId, const String8& path, int action);
+
+ /**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights is reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] reserve True if the rights should be reserved.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t consumeRights(int uniqueId, sp<DecryptHandle> &decryptHandle, int action, bool reserve);
+
+ /**
+ * Informs the DRM engine about the playback actions performed on the DRM files.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param[in] position Position in the file (in milliseconds) where the start occurs.
+ * Only valid together with Playback::START.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t setPlaybackStatus(
+ int uniqueId, sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position);
+
+ /**
+ * Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to validate (Action::PLAY, Action::TRANSFER, etc)
+ * @param[in] description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+ bool validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ /**
+ * Removes the rights associated with the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t removeRights(int uniqueId, const String8& path);
+
+ /**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t removeAllRights(int uniqueId);
+
+ /**
+ * This API is for Forward Lock based DRM scheme.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] mimeType Description/MIME type of the input data packet
+ * @return Return handle for the convert session
+ */
+ int openConvertSession(int uniqueId, const String8& mimeType);
+
+ /**
+ * Accepts and converts the input data which is part of DRM file.
+ * The resultant converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there are new block
+ * of data received by the application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @param[in] inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+ DrmConvertedStatus* convertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ /**
+ * Informs the Drm Agent when there is no more data which need to be converted
+ * or when an error occurs. Upon successful conversion of the complete data,
+ * the agent will inform that where the header and body signature
+ * should be added. This signature appending is needed to integrity
+ * protect the converted file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application on which offset these signature data
+ * should be appended.
+ */
+ DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ /**
+ * Retrieves all DrmSupportInfo instance that native DRM framework can handle.
+ * This interface is meant to be used by JNI layer
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[out] length Number of elements in drmSupportInfoArray
+ * @param[out] drmSupportInfoArray Array contains all DrmSupportInfo
+ * that native DRM framework can handle
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] fd File descriptor of the protected content to be decrypted
+ * @param[in] offset Start position of the content
+ * @param[in] length The length of the protected content
+ * @param[in] mime The mime type of the protected content if it is not NULL or empty
+ * @return
+ * Handle for the decryption session
+ */
+ sp<DecryptHandle> openDecryptSession(
+ int uniqueId, int fd, off64_t offset, off64_t length, const char* mime);
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] uri Path of the protected content to be decrypted
+ * @param[in] mime The mime type of the protected content if it is not NULL or empty
+ * @return
+ * Handle for the decryption session
+ */
+ sp<DecryptHandle> openDecryptSession(
+ int uniqueId, const char* uri, const char* mime);
+
+ /**
+ * Close the decrypt session for the given handle
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t closeDecryptSession(int uniqueId, sp<DecryptHandle> &decryptHandle);
+
+ /**
+ * Initialize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] headerInfo Information for initializing decryption of this decrypUnit
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ /**
+ * Decrypt the protected content buffers for the given unit
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] encBuffer Encrypted data block
+ * @param[out] decBuffer Decrypted data block
+ * @param[in] IV Optional buffer
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+ status_t decrypt(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+
+ /**
+ * Finalize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t finalizeDecryptUnit(int uniqueId, sp<DecryptHandle> &decryptHandle, int decryptUnitId);
+
+ /**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[out] buffer Reference to the buffer that should receive the read data.
+ * @param[in] numBytes Number of bytes to read.
+ * @param[in] offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+ ssize_t pread(int uniqueId, sp<DecryptHandle> &decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset);
+
+ /**
+ * Notify the event to the registered listener
+ *
+ * @param[in] event The event to be notified
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t notify(const DrmInfoEvent& event);
+
+private:
+ /**
+ * Install new DRM Engine Plug-in at the runtime
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmEngine Shared Object(so) File in which DRM Engine defined
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
+
+private:
+ Mutex mLock;
+ sp<DrmManagerClient::OnInfoListener> mOnInfoListener;
+
+ class DeathNotifier: public IBinder::DeathRecipient {
+ public:
+ DeathNotifier() {}
+ virtual ~DeathNotifier();
+ virtual void binderDied(const wp<IBinder>& who);
+ };
+
+private:
+ static Mutex sMutex;
+ static sp<DeathNotifier> sDeathNotifier;
+ static sp<IDrmManagerService> sDrmManagerService;
+ static const sp<IDrmManagerService>& getDrmManagerService();
+ static const String8 EMPTY_STRING;
+};
+
+};
+
+#endif /* __DRM_MANAGER_CLIENT_IMPL_H__ */
+
diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h
new file mode 100644
index 0000000..1a8c2ae
--- /dev/null
+++ b/drm/libdrmframework/include/DrmManagerService.h
@@ -0,0 +1,129 @@
+/*
+ * 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 __DRM_MANAGER_SERVICE_H__
+#define __DRM_MANAGER_SERVICE_H__
+
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include "IDrmManagerService.h"
+#include "IDrmServiceListener.h"
+
+namespace android {
+
+class DrmManager;
+class String8;
+class Mutex;
+
+/**
+ * This is the implementation class for DRM manager service. This delegates
+ * the responsibility to DrmManager.
+ *
+ * The instance of this class is created while starting the DRM manager service.
+ *
+ */
+class DrmManagerService : public BnDrmManagerService {
+public:
+ static void instantiate();
+
+private:
+ DrmManagerService();
+ virtual ~DrmManagerService();
+
+public:
+ int addUniqueId(bool isNative);
+
+ void removeUniqueId(int uniqueId);
+
+ void addClient(int uniqueId);
+
+ void removeClient(int uniqueId);
+
+ status_t setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& drmServiceListener);
+
+ status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
+
+ DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
+
+ DrmMetadata* getMetadata(int uniqueId, const String8* path);
+
+ bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
+
+ DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest);
+
+ status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ int checkRightsStatus(int uniqueId, const String8& path,int action);
+
+ status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ status_t setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position);
+
+ bool validateAction(int uniqueId, const String8& path,
+ int action, const ActionDescription& description);
+
+ status_t removeRights(int uniqueId, const String8& path);
+
+ status_t removeAllRights(int uniqueId);
+
+ int openConvertSession(int uniqueId, const String8& mimeType);
+
+ DrmConvertedStatus* convertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
+
+ DecryptHandle* openDecryptSession(
+ int uniqueId, int fd, off64_t offset, off64_t length, const char *mime);
+
+ DecryptHandle* openDecryptSession(
+ int uniqueId, const char* uri, const char* mime);
+
+ status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+
+ status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset);
+
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+private:
+ DrmManager* mDrmManager;
+};
+
+};
+
+#endif /* __DRM_MANAGER_SERVICE_H__ */
+
diff --git a/drm/libdrmframework/include/IDrmManagerService.h b/drm/libdrmframework/include/IDrmManagerService.h
new file mode 100644
index 0000000..a7d21c5
--- /dev/null
+++ b/drm/libdrmframework/include/IDrmManagerService.h
@@ -0,0 +1,263 @@
+/*
+ * 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 __IDRM_MANAGER_SERVICE_H__
+#define __IDRM_MANAGER_SERVICE_H__
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <drm/drm_framework_common.h>
+#include "IDrmServiceListener.h"
+
+namespace android {
+
+class DrmConstraints;
+class DrmMetadata;
+class DrmRights;
+class DrmInfo;
+class DrmInfoStatus;
+class DrmInfoRequest;
+class DrmSupportInfo;
+class DrmConvertedStatus;
+class String8;
+class ActionDescription;
+
+/**
+ * This is the interface class for DRM Manager service.
+ *
+ */
+class IDrmManagerService : public IInterface
+{
+public:
+ enum {
+ ADD_UNIQUEID = IBinder::FIRST_CALL_TRANSACTION,
+ REMOVE_UNIQUEID,
+ ADD_CLIENT,
+ REMOVE_CLIENT,
+ SET_DRM_SERVICE_LISTENER,
+ INSTALL_DRM_ENGINE,
+ GET_CONSTRAINTS_FROM_CONTENT,
+ GET_METADATA_FROM_CONTENT,
+ CAN_HANDLE,
+ PROCESS_DRM_INFO,
+ ACQUIRE_DRM_INFO,
+ SAVE_RIGHTS,
+ GET_ORIGINAL_MIMETYPE,
+ GET_DRM_OBJECT_TYPE,
+ CHECK_RIGHTS_STATUS,
+ CONSUME_RIGHTS,
+ SET_PLAYBACK_STATUS,
+ VALIDATE_ACTION,
+ REMOVE_RIGHTS,
+ REMOVE_ALL_RIGHTS,
+ OPEN_CONVERT_SESSION,
+ CONVERT_DATA,
+ CLOSE_CONVERT_SESSION,
+ GET_ALL_SUPPORT_INFO,
+ OPEN_DECRYPT_SESSION,
+ OPEN_DECRYPT_SESSION_FROM_URI,
+ CLOSE_DECRYPT_SESSION,
+ INITIALIZE_DECRYPT_UNIT,
+ DECRYPT,
+ FINALIZE_DECRYPT_UNIT,
+ PREAD
+ };
+
+public:
+ DECLARE_META_INTERFACE(DrmManagerService);
+
+public:
+ virtual int addUniqueId(bool isNative) = 0;
+
+ virtual void removeUniqueId(int uniqueId) = 0;
+
+ virtual void addClient(int uniqueId) = 0;
+
+ virtual void removeClient(int uniqueId) = 0;
+
+ virtual status_t setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& infoListener) = 0;
+
+ virtual status_t installDrmEngine(int uniqueId, const String8& drmEngineFile) = 0;
+
+ virtual DrmConstraints* getConstraints(
+ int uniqueId, const String8* path, const int action) = 0;
+
+ virtual DrmMetadata* getMetadata(int uniqueId, const String8* path) = 0;
+
+ virtual bool canHandle(int uniqueId, const String8& path, const String8& mimeType) = 0;
+
+ virtual DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo) = 0;
+
+ virtual DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest) = 0;
+
+ virtual status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) = 0;
+
+ virtual String8 getOriginalMimeType(int uniqueId, const String8& path) = 0;
+
+ virtual int getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) = 0;
+
+ virtual int checkRightsStatus(int uniqueId, const String8& path, int action) = 0;
+
+ virtual status_t consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) = 0;
+
+ virtual status_t setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) = 0;
+
+ virtual bool validateAction(
+ int uniqueId, const String8& path,
+ int action, const ActionDescription& description) = 0;
+
+ virtual status_t removeRights(int uniqueId, const String8& path) = 0;
+
+ virtual status_t removeAllRights(int uniqueId) = 0;
+
+ virtual int openConvertSession(int uniqueId, const String8& mimeType) = 0;
+
+ virtual DrmConvertedStatus* convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) = 0;
+
+ virtual DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId) = 0;
+
+ virtual status_t getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) = 0;
+
+ virtual DecryptHandle* openDecryptSession(
+ int uniqueId, int fd, off64_t offset,
+ off64_t length, const char* mime) = 0;
+
+ virtual DecryptHandle* openDecryptSession(
+ int uniqueId, const char* uri, const char* mime) = 0;
+
+ virtual status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) = 0;
+
+ virtual status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) = 0;
+
+ virtual status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) = 0;
+
+ virtual status_t finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) = 0;
+
+ virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes,off64_t offset) = 0;
+};
+
+/**
+ * This is the Binder implementation class for DRM Manager service.
+ */
+class BpDrmManagerService: public BpInterface<IDrmManagerService>
+{
+public:
+ BpDrmManagerService(const sp<IBinder>& impl)
+ : BpInterface<IDrmManagerService>(impl) {}
+
+ virtual int addUniqueId(bool isNative);
+
+ virtual void removeUniqueId(int uniqueId);
+
+ virtual void addClient(int uniqueId);
+
+ virtual void removeClient(int uniqueId);
+
+ virtual status_t setDrmServiceListener(
+ int uniqueId, const sp<IDrmServiceListener>& infoListener);
+
+ virtual status_t installDrmEngine(int uniqueId, const String8& drmEngineFile);
+
+ virtual DrmConstraints* getConstraints(int uniqueId, const String8* path, const int action);
+
+ virtual DrmMetadata* getMetadata(int uniqueId, const String8* path);
+
+ virtual bool canHandle(int uniqueId, const String8& path, const String8& mimeType);
+
+ virtual DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ virtual DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest);
+
+ virtual status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ virtual String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ virtual int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ virtual int checkRightsStatus(int uniqueId, const String8& path, int action);
+
+ virtual status_t consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ virtual status_t setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position);
+
+ virtual bool validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ virtual status_t removeRights(int uniqueId, const String8& path);
+
+ virtual status_t removeAllRights(int uniqueId);
+
+ virtual int openConvertSession(int uniqueId, const String8& mimeType);
+
+ virtual DrmConvertedStatus* convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ virtual DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ virtual status_t getAllSupportInfo(
+ int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray);
+
+ virtual DecryptHandle* openDecryptSession(
+ int uniqueId, int fd, off64_t offset, off64_t length,
+ const char* mime);
+
+ virtual DecryptHandle* openDecryptSession(
+ int uniqueId, const char* uri, const char* mime);
+
+ virtual status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ virtual status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ virtual status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+
+ virtual status_t finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset);
+};
+
+/**
+ * This is the Binder implementation class for DRM Manager service.
+ */
+class BnDrmManagerService: public BnInterface<IDrmManagerService>
+{
+public:
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
+};
+
+};
+
+#endif /* __IDRM_MANAGER_SERVICE_H__ */
+
diff --git a/drm/libdrmframework/include/IDrmServiceListener.h b/drm/libdrmframework/include/IDrmServiceListener.h
new file mode 100644
index 0000000..7f7109f
--- /dev/null
+++ b/drm/libdrmframework/include/IDrmServiceListener.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 __IDRM_SERVICE_LISTENER_H__
+#define __IDRM_SERVICE_LISTENER_H__
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class DrmInfoEvent;
+
+/**
+ * This is the interface class for DRM service listener.
+ *
+ */
+class IDrmServiceListener : public IInterface
+{
+public:
+ enum {
+ NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
+ };
+
+public:
+ DECLARE_META_INTERFACE(DrmServiceListener);
+
+public:
+ virtual status_t notify(const DrmInfoEvent& event) = 0;
+};
+
+/**
+ * This is the Binder implementation class for DRM service listener.
+ */
+class BpDrmServiceListener: public BpInterface<IDrmServiceListener>
+{
+public:
+ BpDrmServiceListener(const sp<IBinder>& impl)
+ : BpInterface<IDrmServiceListener>(impl) {}
+
+ virtual status_t notify(const DrmInfoEvent& event);
+};
+
+/**
+ * This is the Binder implementation class for DRM service listener.
+ */
+class BnDrmServiceListener: public BnInterface<IDrmServiceListener>
+{
+public:
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
+};
+
+};
+
+#endif /* __IDRM_SERVICE_LISTENER_H__ */
+
diff --git a/drm/libdrmframework/include/PlugInManager.h b/drm/libdrmframework/include/PlugInManager.h
new file mode 100644
index 0000000..7bb143f
--- /dev/null
+++ b/drm/libdrmframework/include/PlugInManager.h
@@ -0,0 +1,269 @@
+/*
+ * 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 __PLUGIN_MANAGER_H__
+#define __PLUGIN_MANAGER_H__
+
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+const char* const PLUGIN_MANAGER_CREATE = "create";
+const char* const PLUGIN_MANAGER_DESTROY = "destroy";
+const char* const PLUGIN_EXTENSION = ".so";
+
+/**
+ * This is the template class for Plugin manager.
+ *
+ * The DrmManager uses this class to handle the plugins.
+ *
+ */
+template<typename Type>
+class TPlugInManager {
+private:
+ typedef void* HANDLE;
+ typedef Type* create_t(void);
+ typedef void destroy_t(Type*);
+ typedef create_t* FPCREATE;
+ typedef destroy_t* FPDESTORY;
+
+ typedef struct _PlugInContainer {
+ String8 sPath;
+ HANDLE hHandle;
+ FPCREATE fpCreate;
+ FPDESTORY fpDestory;
+ Type* pInstance;
+
+ _PlugInContainer():
+ sPath("")
+ ,hHandle(NULL)
+ ,fpCreate(NULL)
+ ,fpDestory(NULL)
+ ,pInstance(NULL)
+ {}
+ } PlugInContainer;
+
+ typedef KeyedVector<String8, PlugInContainer*> PlugInMap;
+ PlugInMap m_plugInMap;
+
+ typedef Vector<String8> PlugInIdList;
+ PlugInIdList m_plugInIdList;
+
+public:
+ /**
+ * Load all the plug-ins in the specified directory
+ *
+ * @param[in] rsPlugInDirPath
+ * Directory path which plug-ins (dynamic library) are stored
+ * @note Plug-ins should be implemented according to the specification
+ */
+ void loadPlugIns(const String8& rsPlugInDirPath) {
+ Vector<String8> plugInFileList = getPlugInPathList(rsPlugInDirPath);
+
+ if (!plugInFileList.isEmpty()) {
+ for (unsigned int i = 0; i < plugInFileList.size(); ++i) {
+ loadPlugIn(plugInFileList[i]);
+ }
+ }
+ }
+
+ /**
+ * Unload all the plug-ins
+ *
+ */
+ void unloadPlugIns() {
+ for (unsigned int i = 0; i < m_plugInIdList.size(); ++i) {
+ unloadPlugIn(m_plugInIdList[i]);
+ }
+ m_plugInIdList.clear();
+ }
+
+ /**
+ * Get all the IDs of available plug-ins
+ *
+ * @return[in] plugInIdList
+ * String type Vector in which all plug-in IDs are stored
+ */
+ Vector<String8> getPlugInIdList() const {
+ return m_plugInIdList;
+ }
+
+ /**
+ * Get a plug-in reference of specified ID
+ *
+ * @param[in] rsPlugInId
+ * Plug-in ID to be used
+ * @return plugIn
+ * Reference of specified plug-in instance
+ */
+ Type& getPlugIn(const String8& rsPlugInId) {
+ if (!contains(rsPlugInId)) {
+ // This error case never happens
+ }
+ return *(m_plugInMap.valueFor(rsPlugInId)->pInstance);
+ }
+
+public:
+ /**
+ * Load a plug-in stored in the specified path
+ *
+ * @param[in] rsPlugInPath
+ * Plug-in (dynamic library) file path
+ * @note Plug-in should be implemented according to the specification
+ */
+ void loadPlugIn(const String8& rsPlugInPath) {
+ if (contains(rsPlugInPath)) {
+ return;
+ }
+
+ PlugInContainer* pPlugInContainer = new PlugInContainer();
+
+ pPlugInContainer->hHandle = dlopen(rsPlugInPath.string(), RTLD_LAZY);
+
+ if (NULL == pPlugInContainer->hHandle) {
+ delete pPlugInContainer;
+ pPlugInContainer = NULL;
+ return;
+ }
+
+ pPlugInContainer->sPath = rsPlugInPath;
+ pPlugInContainer->fpCreate
+ = (FPCREATE)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_CREATE);
+ pPlugInContainer->fpDestory
+ = (FPDESTORY)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_DESTROY);
+
+ if (NULL != pPlugInContainer->fpCreate && NULL != pPlugInContainer->fpDestory) {
+ pPlugInContainer->pInstance = (Type*)pPlugInContainer->fpCreate();
+ m_plugInIdList.add(rsPlugInPath);
+ m_plugInMap.add(rsPlugInPath, pPlugInContainer);
+ } else {
+ dlclose(pPlugInContainer->hHandle);
+ delete pPlugInContainer;
+ pPlugInContainer = NULL;
+ return;
+ }
+ }
+
+ /**
+ * Unload a plug-in stored in the specified path
+ *
+ * @param[in] rsPlugInPath
+ * Plug-in (dynamic library) file path
+ */
+ void unloadPlugIn(const String8& rsPlugInPath) {
+ if (!contains(rsPlugInPath)) {
+ return;
+ }
+
+ PlugInContainer* pPlugInContainer = m_plugInMap.valueFor(rsPlugInPath);
+ pPlugInContainer->fpDestory(pPlugInContainer->pInstance);
+ dlclose(pPlugInContainer->hHandle);
+
+ m_plugInMap.removeItem(rsPlugInPath);
+ delete pPlugInContainer;
+ pPlugInContainer = NULL;
+ }
+
+private:
+ /**
+ * True if TPlugInManager contains rsPlugInId
+ */
+ bool contains(const String8& rsPlugInId) {
+ return m_plugInMap.indexOfKey(rsPlugInId) != NAME_NOT_FOUND;
+ }
+
+ /**
+ * Return file path list of plug-ins stored in the specified directory
+ *
+ * @param[in] rsDirPath
+ * Directory path in which plug-ins are stored
+ * @return plugInFileList
+ * String type Vector in which file path of plug-ins are stored
+ */
+ Vector<String8> getPlugInPathList(const String8& rsDirPath) {
+ Vector<String8> fileList;
+ DIR* pDir = opendir(rsDirPath.string());
+ struct dirent* pEntry;
+
+ while (NULL != pDir && NULL != (pEntry = readdir(pDir))) {
+ if (!isPlugIn(pEntry)) {
+ continue;
+ }
+ String8 plugInPath;
+ plugInPath += rsDirPath;
+ plugInPath += "/";
+ plugInPath += pEntry->d_name;
+
+ fileList.add(plugInPath);
+ }
+
+ if (NULL != pDir) {
+ closedir(pDir);
+ }
+
+ return fileList;
+ }
+
+ /**
+ * True if the input name denotes plug-in
+ */
+ bool isPlugIn(const struct dirent* pEntry) const {
+ String8 sName(pEntry->d_name);
+ String8 extension(sName.getPathExtension());
+ // Note that the plug-in extension must exactly match case
+ return extension == String8(PLUGIN_EXTENSION);
+ }
+
+ /**
+ * True if the input entry is "." or ".."
+ */
+ bool isDotOrDDot(const struct dirent* pEntry) const {
+ String8 sName(pEntry->d_name);
+ return "." == sName || ".." == sName;
+ }
+
+ /**
+ * True if input entry is directory
+ */
+ bool isDirectory(const struct dirent* pEntry) const {
+ return DT_DIR == pEntry->d_type;
+ }
+
+ /**
+ * True if input entry is regular file
+ */
+ bool isRegularFile(const struct dirent* pEntry) const {
+ return DT_REG == pEntry->d_type;
+ }
+
+ /**
+ * True if input entry is link
+ */
+ bool isLink(const struct dirent* pEntry) const {
+ return DT_LNK == pEntry->d_type;
+ }
+};
+
+};
+
+#endif /* __PLUGIN_MANAGER_H__ */
+
diff --git a/drm/libdrmframework/include/ReadWriteUtils.h b/drm/libdrmframework/include/ReadWriteUtils.h
new file mode 100644
index 0000000..529b342
--- /dev/null
+++ b/drm/libdrmframework/include/ReadWriteUtils.h
@@ -0,0 +1,79 @@
+/*
+ * 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 __READ_WRITE_UTILS_H__
+#define __READ_WRITE_UTILS_H__
+
+#include <utils/FileMap.h>
+#include <drm/drm_framework_common.h>
+
+namespace android {
+
+/**
+ * This is an utility class which performs IO operations.
+ *
+ */
+class ReadWriteUtils {
+public:
+ /**
+ * Constructor for ReadWriteUtils
+ */
+ ReadWriteUtils() {}
+
+ /**
+ * Destructor for ReadWriteUtils
+ */
+ virtual ~ReadWriteUtils();
+
+public:
+ /**
+ * Reads the data from the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @return Data read from the file
+ */
+ static String8 readBytes(const String8& filePath);
+ /**
+ * Reads the data into the given buffer from the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @param[out] buffer Data read from the file
+ * @return Length of the data read from the file
+ */
+ static int readBytes(const String8& filePath, char** buffer);
+ /**
+ * Writes the data into the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @param[in] dataBuffer Data to write
+ */
+ static void writeToFile(const String8& filePath, const String8& data);
+ /**
+ * Appends the data into the file path provided
+ *
+ * @param[in] filePath Path of the file
+ * @param[in] dataBuffer Data to append
+ */
+ static void appendToFile(const String8& filePath, const String8& data);
+
+private:
+ FileMap* mFileMap;
+};
+
+};
+
+#endif /* __READ_WRITE_UTILS_H__ */
+
diff --git a/drm/libdrmframework/plugins/Android.mk b/drm/libdrmframework/plugins/Android.mk
new file mode 100644
index 0000000..9ee7961
--- /dev/null
+++ b/drm/libdrmframework/plugins/Android.mk
@@ -0,0 +1,16 @@
+#
+# 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 $(call all-subdir-makefiles)
diff --git a/drm/libdrmframework/plugins/common/Android.mk b/drm/libdrmframework/plugins/common/Android.mk
new file mode 100644
index 0000000..9ee7961
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/Android.mk
@@ -0,0 +1,16 @@
+#
+# 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 $(call all-subdir-makefiles)
diff --git a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
new file mode 100644
index 0000000..08f6e6d
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
@@ -0,0 +1,508 @@
+/*
+ * 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 __DRM_ENGINE_BASE_H__
+#define __DRM_ENGINE_BASE_H__
+
+#include <drm/drm_framework_common.h>
+#include "IDrmEngine.h"
+
+namespace android {
+
+/**
+ * This class is an interface for plug-in developers
+ *
+ * Responsibility of this class is control the sequence of actual plug-in.
+ * All each plug-in developer has to do is implement onXXX() type virtual interfaces.
+ */
+class DrmEngineBase : public IDrmEngine {
+public:
+ DrmEngineBase();
+ virtual ~DrmEngineBase();
+
+public:
+ DrmConstraints* getConstraints(int uniqueId, const String8* path, int action);
+
+ DrmMetadata* getMetadata(int uniqueId, const String8* path);
+
+ status_t initialize(int uniqueId);
+
+ status_t setOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener);
+
+ status_t terminate(int uniqueId);
+
+ bool canHandle(int uniqueId, const String8& path);
+
+ DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+
+ String8 getOriginalMimeType(int uniqueId, const String8& path);
+
+ int getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ int checkRightsStatus(int uniqueId, const String8& path, int action);
+
+ status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ status_t setPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position);
+
+ bool validateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ status_t removeRights(int uniqueId, const String8& path);
+
+ status_t removeAllRights(int uniqueId);
+
+ status_t openConvertSession(int uniqueId, int convertId);
+
+ DrmConvertedStatus* convertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ DrmConvertedStatus* closeConvertSession(int uniqueId, int convertId);
+
+ DrmSupportInfo* getSupportInfo(int uniqueId);
+
+ status_t openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle,
+ int fd, off64_t offset, off64_t length, const char* mime);
+
+ status_t openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle,
+ const char* uri, const char* mime);
+
+ status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+
+ status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset);
+
+protected:
+ /////////////////////////////////////////////////////
+ // Interface for plug-in developers //
+ // each plug-in has to implement following method //
+ /////////////////////////////////////////////////////
+ /**
+ * Get constraint information associated with input content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Actions defined such as,
+ * Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ * key-value pairs of constraint are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ virtual DrmConstraints* onGetConstraints(
+ int uniqueId, const String8* path, int action) = 0;
+
+ /**
+ * Get metadata information associated with input content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return DrmMetadata
+ * key-value pairs of metadata
+ * @note
+ * In case of error, return NULL
+ */
+ virtual DrmMetadata* onGetMetadata(int uniqueId, const String8* path) = 0;
+
+ /**
+ * Initialize plug-in
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onInitialize(int uniqueId) = 0;
+
+ /**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information
+ *
+ * @param[in] uniqueId Unique identifier for a session. uniqueId is a random
+ * number generated in the DRM service. If the DrmManagerClient
+ * is created in native code, uniqueId will be a number ranged
+ * from 0x1000 to 0x1fff. If it comes from Java code, the uniqueId
+ * will be a number ranged from 0x00 to 0xfff. So bit 0x1000 in
+ * uniqueId could be used in DRM plugins to differentiate native
+ * OnInfoListener and Java OnInfoListener.
+ * @param[in] infoListener Listener
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onSetOnInfoListener(
+ int uniqueId, const IDrmEngine::OnInfoListener* infoListener) = 0;
+
+ /**
+ * Terminate the plug-in
+ * and release resource bound to plug-in
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onTerminate(int uniqueId) = 0;
+
+ /**
+ * Get whether the given content can be handled by this plugin or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path the protected object
+ * @return bool
+ * Returns true if this plugin can handle , false in case of not able to handle
+ */
+ virtual bool onCanHandle(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Executes given drm information based on its type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfo Information needs to be processed
+ * @return DrmInfoStatus
+ * instance as a result of processing given input
+ */
+ virtual DrmInfoStatus* onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) = 0;
+
+ /**
+ * Save DRM rights to specified rights path
+ * and make association with content path
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmRights DrmRights to be saved
+ * @param[in] rightsPath File path where rights to be saved
+ * @param[in] contentPath File path where content was saved
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onSaveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightspath, const String8& contentPath) = 0;
+
+ /**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ * instance as a result of processing given input
+ */
+ virtual DrmInfo* onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInforequest) = 0;
+
+ /**
+ * Retrieves the mime type embedded inside the original content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return String8
+ * Returns mime-type of the original content, such as "video/mpeg"
+ */
+ virtual String8 onGetOriginalMimeType(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the content or null.
+ * @param[in] mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+ virtual int onGetDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) = 0;
+
+ /**
+ * Check whether the given content has valid rights or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to perform (Action::DEFAULT, Action::PLAY, etc)
+ * @return the status of the rights for the protected content,
+ * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+ virtual int onCheckRightsStatus(int uniqueId, const String8& path, int action) = 0;
+
+ /**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights is reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] reserve True if the rights should be reserved.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onConsumeRights(int uniqueId, DecryptHandle* decryptHandle,
+ int action, bool reserve) = 0;
+
+ /**
+ * Informs the DRM Engine about the playback actions performed on the DRM files.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param[in] position Position in the file (in milliseconds) where the start occurs.
+ * Only valid together with Playback::START.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onSetPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) = 0;
+
+ /**
+ * Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to validate (Action::PLAY, Action::TRANSFER, etc)
+ * @param[in] description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+ virtual bool onValidateAction(int uniqueId, const String8& path,
+ int action, const ActionDescription& description) = 0;
+
+ /**
+ * Removes the rights associated with the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onRemoveRights(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onRemoveAllRights(int uniqueId) = 0;
+
+ /**
+ * This API is for Forward Lock based DRM scheme.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onOpenConvertSession(int uniqueId, int convertId) = 0;
+
+ /**
+ * Accepts and converts the input data which is part of DRM file.
+ * The resultant converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there are new block
+ * of data received by the application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @param[in] inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+ virtual DrmConvertedStatus* onConvertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) = 0;
+
+ /**
+ * Informs the Drm Agent when there is no more data which need to be converted
+ * or when an error occurs. Upon successful conversion of the complete data,
+ * the agent will inform that where the header and body signature
+ * should be added. This signature appending is needed to integrity
+ * protect the converted file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application on which offset these signature data
+ * should be appended.
+ */
+ virtual DrmConvertedStatus* onCloseConvertSession(int uniqueId, int convertId) = 0;
+
+ /**
+ * Returns the information about the Drm Engine capabilities which includes
+ * supported MimeTypes and file suffixes.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return DrmSupportInfo
+ * instance which holds the capabilities of a plug-in
+ */
+ virtual DrmSupportInfo* onGetSupportInfo(int uniqueId) = 0;
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the current decryption session
+ * @param[in] fd File descriptor of the protected content to be decrypted
+ * @param[in] offset Start position of the content
+ * @param[in] length The length of the protected content
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+ virtual status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle,
+ int fd, off64_t offset, off64_t length) = 0;
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the current decryption session
+ * @param[in] fd File descriptor of the protected content to be decrypted
+ * @param[in] offset Start position of the content
+ * @param[in] length The length of the protected content
+ * @param[in] mime Mime type of the protected content
+ * drm plugin may do some optimization since the mime type is known.
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+ virtual status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle,
+ int fd, off64_t offset, off64_t length,
+ const char* mime) {
+
+ return DRM_ERROR_CANNOT_HANDLE;
+ }
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the current decryption session
+ * @param[in] uri Path of the protected content to be decrypted
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+ virtual status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle,
+ const char* uri) = 0;
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the current decryption session
+ * @param[in] uri Path of the protected content to be decrypted
+ * @param[in] mime Mime type of the protected content. The corresponding
+ * drm plugin may do some optimization since the mime type is known.
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+ virtual status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle,
+ const char* uri, const char* mime) {
+
+ return DRM_ERROR_CANNOT_HANDLE;
+ }
+
+ /**
+ * Close the decrypt session for the given handle
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) = 0;
+
+ /**
+ * Initialize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptId Handle for the decryption session
+ * @param[in] decryptUnitId ID Specifies decryption unit, such as track ID
+ * @param[in] headerInfo Information for initializing decryption of this decrypUnit
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) = 0;
+
+ /**
+ * Decrypt the protected content buffers for the given unit
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptId Handle for the decryption session
+ * @param[in] decryptUnitId ID Specifies decryption unit, such as track ID
+ * @param[in] encBuffer Encrypted data block
+ * @param[out] decBuffer Decrypted data block
+ * @param[in] IV Optional buffer
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+ virtual status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) = 0;
+
+ /**
+ * Finalize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID Specifies decryption unit, such as track ID
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t onFinalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) = 0;
+
+ /**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[out] buffer Reference to the buffer that should receive the read data.
+ * @param[in] numBytes Number of bytes to read.
+ * @param[in] offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+ virtual ssize_t onPread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset) = 0;
+};
+
+};
+
+#endif /* __DRM_ENGINE_BASE_H__ */
+
diff --git a/drm/libdrmframework/plugins/common/include/IDrmEngine.h b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
new file mode 100644
index 0000000..dcf5977
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/include/IDrmEngine.h
@@ -0,0 +1,420 @@
+/*
+ * 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 __IDRM_ENGINE_H__
+#define __IDRM_ENGINE_H__
+
+#include <drm/drm_framework_common.h>
+
+namespace android {
+
+class DrmConstraints;
+class DrmMetadata;
+class DrmRights;
+class DrmInfo;
+class DrmInfoStatus;
+class DrmConvertedStatus;
+class DrmInfoRequest;
+class DrmSupportInfo;
+class DrmInfoEvent;
+
+/**
+ * This class is an interface for plug-in user
+ *
+ * Responsibility of this class is provide generic interface to DRM Engine Manager.
+ * Each interface need to be as abstract as possible.
+ */
+class IDrmEngine {
+public:
+ virtual ~IDrmEngine() {
+ }
+
+public:
+ class OnInfoListener {
+
+ public:
+ virtual void onInfo(const DrmInfoEvent& event) = 0;
+
+ virtual ~OnInfoListener() { }
+ };
+
+public:
+
+ //////////////////////////////////
+ // Implementation of IDrmEngine //
+ //////////////////////////////////
+
+ /**
+ * Initialize plug-in
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t initialize(int uniqueId) = 0;
+
+ /**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] infoListener Listener
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t setOnInfoListener(
+ int uniqueId, const IDrmEngine::OnInfoListener* infoListener) = 0;
+
+ /**
+ * Terminate the plug-in
+ * and release resource bound to plug-in
+ * e.g.) release native resource
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t terminate(int uniqueId) = 0;
+
+ /**
+ * Get constraint information associated with input content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Actions defined such as,
+ * Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ * key-value pairs of constraint are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ virtual DrmConstraints* getConstraints(
+ int uniqueId, const String8* path, int action) = 0;
+
+ /**
+ * Get metadata information associated with input content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return DrmMetadata
+ * key-value pairs of metadata
+ * @note
+ * In case of error, return NULL
+ */
+ virtual DrmMetadata* getMetadata(int uniqueId, const String8* path) = 0;
+
+ /**
+ * Get whether the given content can be handled by this plugin or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path the protected object
+ * @return bool
+ * true if this plugin can handle , false in case of not able to handle
+ */
+ virtual bool canHandle(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Executes given drm information based on its type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfo Information needs to be processed
+ * @return DrmInfoStatus
+ * instance as a result of processing given input
+ */
+ virtual DrmInfoStatus* processDrmInfo(int uniqueId, const DrmInfo* drmInfo) = 0;
+
+ /**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ * instance as a result of processing given input
+ */
+ virtual DrmInfo* acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) = 0;
+
+ /**
+ * Save DRM rights to specified rights path
+ * and make association with content path
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] drmRights DrmRights to be saved
+ * @param[in] rightsPath File path where rights to be saved
+ * @param[in] contentPath File path where content was saved
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t saveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) = 0;
+
+ /**
+ * Retrieves the mime type embedded inside the original content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return String8
+ * Returns mime-type of the original content, such as "video/mpeg"
+ */
+ virtual String8 getOriginalMimeType(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the content or null.
+ * @param[in] mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+ virtual int getDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) = 0;
+
+ /**
+ * Check whether the given content has valid rights or not
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to perform (Action::DEFAULT, Action::PLAY, etc)
+ * @return the status of the rights for the protected content,
+ * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+ virtual int checkRightsStatus(int uniqueId, const String8& path, int action) = 0;
+
+ /**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights is reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] reserve True if the rights should be reserved.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t consumeRights(
+ int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) = 0;
+
+ /**
+ * Informs the DRM Engine about the playback actions performed on the DRM files.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param[in] position Position in the file (in milliseconds) where the start occurs.
+ * Only valid together with Playback::START.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t setPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
+ int playbackStatus, int64_t position) = 0;
+
+ /**
+ * Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to validate (Action::PLAY, Action::TRANSFER, etc)
+ * @param[in] description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+ virtual bool validateAction(int uniqueId, const String8& path,
+ int action, const ActionDescription& description) = 0;
+
+ /**
+ * Removes the rights associated with the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] path Path of the protected content
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t removeRights(int uniqueId, const String8& path) = 0;
+
+ /**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t removeAllRights(int uniqueId) = 0;
+
+ /**
+ * This API is for Forward Lock based DRM scheme.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t openConvertSession(int uniqueId, int convertId) = 0;
+
+ /**
+ * Accepts and converts the input data which is part of DRM file.
+ * The resultant converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there are new block
+ * of data received by the application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @param[in] inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+ virtual DrmConvertedStatus* convertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) = 0;
+
+ /**
+ * Informs the Drm Agent when there is no more data which need to be converted
+ * or when an error occurs. Upon successful conversion of the complete data,
+ * the agent will inform that where the header and body signature
+ * should be added. This signature appending is needed to integrity
+ * protect the converted file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application on which offset these signature data
+ * should be appended.
+ */
+ virtual DrmConvertedStatus* closeConvertSession( int uniqueId, int convertId) = 0;
+
+ /**
+ * Returns the information about the Drm Engine capabilities which includes
+ * supported MimeTypes and file suffixes.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @return DrmSupportInfo
+ * instance which holds the capabilities of a plug-in
+ */
+ virtual DrmSupportInfo* getSupportInfo(int uniqueId) = 0;
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the current decryption session
+ * @param[in] fd File descriptor of the protected content to be decrypted
+ * @param[in] offset Start position of the content
+ * @param[in] length The length of the protected content
+ * @param[in] mime Mime type of the protected content if it is
+ * not NULL or empty
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+ virtual status_t openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle,
+ int fd, off64_t offset, off64_t length, const char* mime) = 0;
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the current decryption session
+ * @param[in] uri Path of the protected content to be decrypted
+ * @param[in] mime Mime type of the protected content if it is
+ * not NULL or empty
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+ virtual status_t openDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle,
+ const char* uri, const char* mime) = 0;
+
+ /**
+ * Close the decrypt session for the given handle
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) = 0;
+
+ /**
+ * Initialize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] headerInfo Information for initializing decryption of this decrypUnit
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) = 0;
+
+ /**
+ * Decrypt the protected content buffers for the given unit
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] encBuffer Encrypted data block
+ * @param[out] decBuffer Decrypted data block
+ * @param[in] IV Optional buffer
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+ virtual status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) = 0;
+
+ /**
+ * Finalize decryption for the given unit of the protected content
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ virtual status_t finalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) = 0;
+
+ /**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param[in] uniqueId Unique identifier for a session
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[out] buffer Reference to the buffer that should receive the read data.
+ * @param[in] numBytes Number of bytes to read.
+ * @param[in] offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+ virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset) = 0;
+};
+
+};
+
+#endif /* __IDRM_ENGINE_H__ */
+
diff --git a/drm/libdrmframework/plugins/common/util/Android.mk b/drm/libdrmframework/plugins/common/util/Android.mk
new file mode 100644
index 0000000..15dda80
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/util/Android.mk
@@ -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.
+#
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ src/MimeTypeUtil.cpp
+
+LOCAL_MODULE := libdrmutility
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libdl \
+ libdvm \
+ libandroid_runtime \
+ libnativehelper \
+ liblog
+
+
+base := frameworks/base
+
+LOCAL_C_INCLUDES += \
+ $(JNI_H_INCLUDE) \
+ $(base)/include \
+ $(base)/include/drm \
+ $(base)/include/drm/plugins \
+ $(LOCAL_PATH)/include
+
+
+ifneq ($(TARGET_BUILD_VARIANT),user)
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/tools
+
+endif
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/drm/libdrmframework/plugins/common/util/include/MimeTypeUtil.h b/drm/libdrmframework/plugins/common/util/include/MimeTypeUtil.h
new file mode 100644
index 0000000..4d12a61
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/util/include/MimeTypeUtil.h
@@ -0,0 +1,46 @@
+/*
+ * 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 __MIMETYPEUTIL_H__
+#define __MIMETYPEUTIL_H__
+
+#include <utils/String8.h>
+
+namespace android {
+
+class MimeTypeUtil {
+
+public:
+
+ MimeTypeUtil() {}
+
+ virtual ~MimeTypeUtil() {}
+
+/**
+ * May convert the mimetype if there is a well known
+ * replacement mimetype otherwise the original mimetype
+ * is returned.
+ *
+ * @param mimeType - mimetype in lower case to convert.
+ *
+ * @return mimetype or null.
+ */
+static String8 convertMimeType(String8& mimeType);
+
+};
+};
+
+#endif /* __MIMETYPEUTIL_H__ */
diff --git a/drm/libdrmframework/plugins/common/util/include/SessionMap.h b/drm/libdrmframework/plugins/common/util/include/SessionMap.h
new file mode 100644
index 0000000..e563894
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/util/include/SessionMap.h
@@ -0,0 +1,189 @@
+/*
+ * 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 __SESSIONMAP_H__
+#define __SESSIONMAP_H__
+
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+
+namespace android {
+
+/**
+ * A thread safe wrapper template class for session handlings for Drm Engines. It wraps a
+ * pointer type over KeyedVector. It keeps pointer as data in the vector and free up memory
+ * allocated pointer can be of any type of structure/class meant for keeping session data.
+ * so session object here means pointer to the session data.
+ */
+template <typename TValue>
+class SessionMap {
+
+public:
+ SessionMap() {}
+
+ virtual ~SessionMap() {
+ Mutex::Autolock lock(mLock);
+ destroyMap();
+ }
+
+ /**
+ * Adds a new value in the session map table. It expects memory to be allocated already
+ * for the session object
+ *
+ * @param key - key or Session ID
+ * @param value - session object to add
+ *
+ * @return boolean result of adding value. returns false if key is already exist.
+ */
+ bool addValue(int key, TValue value) {
+ Mutex::Autolock lock(mLock);
+ if (!isCreatedInternal(key)) {
+ map.add(key, value);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * returns the session object by the key
+ *
+ * @param key - key or Session ID
+ *
+ * @return session object as per the key
+ */
+ TValue getValue(int key) {
+ Mutex::Autolock lock(mLock);
+ return getValueInternal(key);
+ }
+
+ /**
+ * returns the number of objects in the session map table
+ *
+ * @return count of number of session objects.
+ */
+ int getSize() {
+ Mutex::Autolock lock(mLock);
+ return map.size();
+ }
+
+ /**
+ * returns the session object by the index in the session map table
+ *
+ * @param index - index of the value required
+ *
+ * @return session object as per the index
+ */
+ TValue getValueAt(unsigned int index) {
+ TValue value = NULL;
+ Mutex::Autolock lock(mLock);
+
+ if (map.size() > index) {
+ value = map.valueAt(index);
+ }
+ return value;
+ }
+
+ /**
+ * deletes the object from session map. It also frees up memory for the session object.
+ *
+ * @param key - key of the value to be deleted
+ *
+ */
+ void removeValue(int key) {
+ Mutex::Autolock lock(mLock);
+ deleteValue(getValueInternal(key));
+ map.removeItem(key);
+ }
+
+ /**
+ * decides if session is already created.
+ *
+ * @param key - key of the value for the session
+ *
+ * @return boolean result of whether session is created
+ */
+ bool isCreated(int key) {
+ Mutex::Autolock lock(mLock);
+ return isCreatedInternal(key);
+ }
+
+ SessionMap<TValue> & operator=(const SessionMap<TValue> & objectCopy) {
+ Mutex::Autolock lock(mLock);
+
+ destroyMap();
+ map = objectCopy.map;
+ return *this;
+ }
+
+private:
+ KeyedVector<int, TValue> map;
+ Mutex mLock;
+
+ /**
+ * free up the memory for the session object.
+ * Make sure if any reference to the session object anywhere, otherwise it will be a
+ * dangle pointer after this call.
+ *
+ * @param value - session object to free
+ *
+ */
+ void deleteValue(TValue value) {
+ delete value;
+ }
+
+ /**
+ * free up the memory for the entire map.
+ * free up any resources in the sessions before calling this funtion.
+ *
+ */
+ void destroyMap() {
+ int size = map.size();
+
+ for (int i = 0; i < size; i++) {
+ deleteValue(map.valueAt(i));
+ }
+ map.clear();
+ }
+
+ /**
+ * decides if session is already created.
+ *
+ * @param key - key of the value for the session
+ *
+ * @return boolean result of whether session is created
+ */
+ bool isCreatedInternal(int key) {
+ return(0 <= map.indexOfKey(key));
+ }
+
+ /**
+ * returns the session object by the key
+ *
+ * @param key - key or Session ID
+ *
+ * @return session object as per the key
+ */
+ TValue getValueInternal(int key) {
+ TValue value = NULL;
+ if (isCreatedInternal(key)) {
+ value = (TValue) map.valueFor(key);
+ }
+ return value;
+ }
+};
+
+};
+
+#endif /* __SESSIONMAP_H__ */
diff --git a/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
new file mode 100644
index 0000000..576ed15
--- /dev/null
+++ b/drm/libdrmframework/plugins/common/util/src/MimeTypeUtil.cpp
@@ -0,0 +1,166 @@
+/*
+ * 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 <MimeTypeUtil.h>
+#include <utils/Log.h>
+
+namespace android {
+
+#undef LOG_TAG
+#define LOG_TAG "MimeTypeUtil"
+
+#ifdef DRM_OMA_FL_ENGINE_DEBUG
+#define LOG_NDEBUG 0
+#define LOG_DEBUG(...) ALOGD(__VA_ARGS__)
+#else
+#define LOG_DEBUG(...)
+#endif
+
+enum {
+ MIMETYPE_AUDIO = 0,
+ MIMETYPE_APPLICATION = 1,
+ MIMETYPE_IMAGE = 2,
+ MIMETYPE_VIDEO = 3,
+ MIMETYPE_LAST = -1,
+};
+
+struct MimeGroup{
+ int type; // Audio, video,.. use the enum values
+ const char* pGroup; // "audio/", "video/",.. should contain the last "/"
+ int size; // Number of bytes. e.g. "audio/" = 6 bytes
+};
+
+struct MimeTypeList{
+ int type;
+ const char* pMimeExt; // Everything after the '/' e.g. audio/x-mpeg -> "x-mpeg"
+ int size; // Number of bytes. e.g. "x-mpeg" = 6 bytes
+ const char* pMimeType; // Mimetype that should be returned
+};
+
+
+// Known mimetypes by android
+static const char mime_type_audio_mpeg[] = "audio/mpeg";
+static const char mime_type_audio_3gpp[] = "audio/3gpp";
+static const char mime_type_audio_amr[] = "audio/amr-wb";
+static const char mime_type_audio_aac[] = "audio/mp4a-latm";
+static const char mime_type_audio_wav[] = "audio/wav";
+
+static const char mime_type_video_mpeg4[] = "video/mpeg4";
+static const char mime_type_video_3gpp[] = "video/3gpp";
+
+// Known mimetype groups
+static const char mime_group_audio[] = "audio/";
+static const char mime_group_application[] = "application/";
+static const char mime_group_image[] = "image/";
+static const char mime_group_video[] = "video/";
+static const char mime_type_unsupported[] = "unsupported/drm.mimetype";
+
+static struct MimeGroup mimeGroup[] = {
+ {MIMETYPE_AUDIO, mime_group_audio, sizeof(mime_group_audio)-1},
+ {MIMETYPE_APPLICATION, mime_group_application, sizeof(mime_group_application)-1},
+ {MIMETYPE_IMAGE, mime_group_image, sizeof(mime_group_image)-1},
+ {MIMETYPE_VIDEO, mime_group_video, sizeof(mime_group_video)-1},
+ {MIMETYPE_LAST, NULL, 0} // Must be last entry
+};
+
+// List of all mimetypes that should be converted.
+static struct MimeTypeList mimeTypeList[] = {
+ // Mp3 mime types
+ {MIMETYPE_AUDIO, "mp3", sizeof("mp3")-1, mime_type_audio_mpeg},
+ {MIMETYPE_AUDIO, "x-mpeg", sizeof("x-mpeg")-1, mime_type_audio_mpeg},
+ {MIMETYPE_AUDIO, "x-mp3", sizeof("x-mp3")-1, mime_type_audio_mpeg},
+ {MIMETYPE_AUDIO, "mpg", sizeof("mpg")-1, mime_type_audio_mpeg},
+ {MIMETYPE_AUDIO, "mpg3", sizeof("mpg")-1, mime_type_audio_mpeg},
+ {MIMETYPE_AUDIO, "x-mpg", sizeof("x-mpg")-1, mime_type_audio_mpeg},
+ {MIMETYPE_AUDIO, "x-mpegaudio", sizeof("x-mpegaudio")-1, mime_type_audio_mpeg},
+
+ // 3gpp audio mime types
+ {MIMETYPE_AUDIO, "3gp", sizeof("3gp")-1, mime_type_audio_3gpp},
+
+ // Amr audio mime types
+ {MIMETYPE_AUDIO, "amr", sizeof("amr")-1, mime_type_audio_amr},
+
+ // Aac audio mime types
+ {MIMETYPE_AUDIO, "aac", sizeof("aac")-1, mime_type_audio_aac},
+
+ // Wav audio mime types
+ {MIMETYPE_AUDIO, "x-wav", sizeof("x-wav")-1, mime_type_audio_wav},
+
+ // Mpeg4 video mime types
+ {MIMETYPE_VIDEO, "mpg4", sizeof("mpg4")-1, mime_type_video_mpeg4},
+ {MIMETYPE_VIDEO, "mp4v-es", sizeof("mp4v-es")-1, mime_type_video_mpeg4},
+
+ // 3gpp video mime types
+ {MIMETYPE_VIDEO, "3gp", sizeof("3gp")-1, mime_type_video_3gpp},
+
+ // Must be last entry
+ {MIMETYPE_LAST, NULL, 0, NULL}
+};
+
+/**
+ * May convert the mimetype if there is a well known
+ * replacement mimetype otherwise the original mimetype
+ * is returned.
+ *
+ * If the mimetype is of unsupported group i.e. application/*
+ * then "unsupported/drm.mimetype" will be returned.
+ *
+ * @param mimeType - mimetype in lower case to convert.
+ *
+ * @return mimetype or "unsupported/drm.mimetype".
+ */
+String8 MimeTypeUtil::convertMimeType(String8& mimeType) {
+ String8 result = mimeType;
+ const char* pMimeType;
+ struct MimeGroup* pGroup;
+ struct MimeTypeList* pMimeItem;
+ int len;
+ pMimeType = mimeType.string();
+ if (NULL != pMimeType) {
+ if ((0 == strncmp(pMimeType, mime_group_audio, (sizeof mime_group_audio) - 1)) ||
+ (0 == strncmp(pMimeType, mime_group_video, (sizeof mime_group_video) - 1))) {
+ /* Check which group the mimetype is */
+ pGroup = mimeGroup;
+ while (MIMETYPE_LAST != pGroup->type) {
+ if (0 == strncmp(pMimeType, pGroup->pGroup, pGroup->size)) {
+ break;
+ }
+ pGroup++;
+ }
+
+ /* Go through the mimetype list. Only check items of the correct group */
+ if (MIMETYPE_LAST != pGroup->type) {
+ pMimeItem = mimeTypeList;
+ len = strlen (pMimeType+pGroup->size);
+ while (MIMETYPE_LAST != pMimeItem->type) {
+ if ((pGroup->type == pMimeItem->type) &&
+ (len == pMimeItem->size) &&
+ (0 == strcmp(pMimeType+pGroup->size, pMimeItem->pMimeExt))) {
+ result = String8(pMimeItem->pMimeType);
+ break;
+ }
+ pMimeItem++;
+ }
+ }
+ } else {
+ result = String8(mime_type_unsupported);
+ }
+ LOG_DEBUG("convertMimeType got mimetype %s, converted into mimetype %s",
+ pMimeType, result.string());
+ }
+ return result;
+}
+};
diff --git a/drm/libdrmframework/plugins/forward-lock/Android.mk b/drm/libdrmframework/plugins/forward-lock/Android.mk
new file mode 100644
index 0000000..9ee7961
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/Android.mk
@@ -0,0 +1,16 @@
+#
+# 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 $(call all-subdir-makefiles)
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
new file mode 100644
index 0000000..e359dbd
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk
@@ -0,0 +1,70 @@
+#
+# 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.
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# The flag below turns on local debug printouts
+#LOCAL_CFLAGS += -DDRM_OMA_FL_ENGINE_DEBUG
+
+base := frameworks/base
+
+# Determine whether the DRM framework uses 64-bit data types for file offsets and do the same.
+ifneq ($(shell grep -c 'off64_t offset' $(base)/drm/libdrmframework/plugins/common/include/IDrmEngine.h), 0)
+LOCAL_CFLAGS += -DUSE_64BIT_DRM_API
+endif
+
+LOCAL_SRC_FILES:= \
+ src/FwdLockEngine.cpp
+
+LOCAL_MODULE := libfwdlockengine
+
+LOCAL_SHARED_LIBRARIES := \
+ libicui18n \
+ libicuuc \
+ libutils \
+ libdl \
+ libandroid_runtime \
+ libnativehelper \
+ libcrypto \
+ libssl \
+ libdrmframework
+
+LOCAL_STATIC_LIBRARIES := \
+ libdrmutility \
+ libdrmframeworkcommon \
+ libfwdlock-common \
+ libfwdlock-converter \
+ libfwdlock-decoder
+
+
+
+LOCAL_C_INCLUDES += \
+ $(JNI_H_INCLUDE) \
+ $(base)/include/drm \
+ $(base)/drm/libdrmframework/plugins/common/include \
+ $(base)/drm/libdrmframework/plugins/common/util/include \
+ $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/common \
+ $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/converter \
+ $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/decoder \
+ $(LOCAL_PATH)/include \
+ external/openssl/include
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/drm
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h
new file mode 100644
index 0000000..c0e408e
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h
@@ -0,0 +1,567 @@
+/*
+ * 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 __FWDLOCKENGINE_H__
+#define __FWDLOCKENGINE_H__
+
+#include <DrmEngineBase.h>
+#include <DrmConstraints.h>
+#include <DrmRights.h>
+#include <DrmInfo.h>
+#include <DrmInfoStatus.h>
+#include <DrmConvertedStatus.h>
+#include <DrmInfoRequest.h>
+#include <DrmSupportInfo.h>
+#include <DrmInfoEvent.h>
+
+#include "SessionMap.h"
+#include "FwdLockConv.h"
+
+namespace android {
+
+/**
+ * Forward Lock Engine class.
+ */
+class FwdLockEngine : public android::DrmEngineBase {
+
+public:
+ FwdLockEngine();
+ virtual ~FwdLockEngine();
+
+protected:
+/**
+ * Get constraint information associated with input content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the protected content
+ * @param action Actions defined such as,
+ * Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ * key-value pairs of constraint are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+DrmConstraints* onGetConstraints(int uniqueId, const String8* path, int action);
+
+/**
+ * Get metadata information associated with input content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the protected content
+ * @return DrmMetadata
+ * For Forward Lock engine, it returns an empty object
+ * @note
+ * In case of error, returns NULL
+ */
+DrmMetadata* onGetMetadata(int uniqueId, const String8* path);
+
+/**
+ * Initialize plug-in.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onInitialize(int uniqueId);
+
+/**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param infoListener Listener
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener);
+
+/**
+ * Terminate the plug-in and release resources bound to it.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onTerminate(int uniqueId);
+
+/**
+ * Get whether the given content can be handled by this plugin or not.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path to the protected object
+ * @return bool
+ * Returns true if this plugin can handle , false in case of not able to handle
+ */
+bool onCanHandle(int uniqueId, const String8& path);
+
+/**
+ * Processes the given DRM information as appropriate for its type.
+ * Not used for Forward Lock Engine.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param drmInfo Information that needs to be processed
+ * @return DrmInfoStatus
+ * instance as a result of processing given input
+ */
+DrmInfoStatus* onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+/**
+ * Save DRM rights to specified rights path
+ * and make association with content path.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param drmRights DrmRights to be saved
+ * @param rightsPath File path where rights to be saved
+ * @param contentPath File path where content was saved
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onSaveRights(int uniqueId,
+ const DrmRights& drmRights,
+ const String8& rightsPath,
+ const String8& contentPath);
+
+/**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ * instance as a result of processing given input
+ */
+DrmInfo* onAcquireDrmInfo(int uniqueId,
+ const DrmInfoRequest* drmInfoRequest);
+
+/**
+ * Retrieves the mime type embedded inside the original content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the protected content
+ * @return String8
+ * Returns mime-type of the original content, such as "video/mpeg"
+ */
+String8 onGetOriginalMimeType(int uniqueId, const String8& path);
+
+/**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the content or null.
+ * @param mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+int onGetDrmObjectType(int uniqueId,
+ const String8& path,
+ const String8& mimeType);
+
+/**
+ * Check whether the given content has valid rights or not.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the protected content
+ * @param action Action to perform (Action::DEFAULT, Action::PLAY, etc)
+ * @return the status of the rights for the protected content,
+ * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+int onCheckRightsStatus(int uniqueId,
+ const String8& path,
+ int action);
+
+/**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights are reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param reserve True if the rights should be reserved.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onConsumeRights(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int action,
+ bool reserve);
+
+/**
+ * Informs the DRM Engine about the playback actions performed on the DRM files.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param position Position in the file (in milliseconds) where the start occurs.
+ * Only valid together with Playback::START.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+#ifdef USE_64BIT_DRM_API
+status_t onSetPlaybackStatus(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int playbackStatus,
+ int64_t position);
+#else
+status_t onSetPlaybackStatus(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int playbackStatus,
+ int position);
+#endif
+
+/**
+ * Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the protected content
+ * @param action Action to validate (Action::PLAY, Action::TRANSFER, etc)
+ * @param description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+bool onValidateAction(int uniqueId,
+ const String8& path,
+ int action,
+ const ActionDescription& description);
+
+/**
+ * Removes the rights associated with the given protected content.
+ * Not used for Forward Lock Engine.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param path Path of the protected content
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onRemoveRights(int uniqueId, const String8& path);
+
+/**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset but does nothing for
+ * Forward Lock Engine.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onRemoveAllRights(int uniqueId);
+
+/**
+ * Starts the Forward Lock file conversion session.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API. The convertId is used as the conversion session key
+ * and must not be the same for different convert sessions.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param convertId Handle for the convert session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onOpenConvertSession(int uniqueId, int convertId);
+
+/**
+ * Accepts and converts the input data which is part of DRM file.
+ * The resultant converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there is a new block
+ * of data received by the application.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param convertId Handle for the convert session
+ * @param inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+DrmConvertedStatus* onConvertData(int uniqueId,
+ int convertId,
+ const DrmBuffer* inputData);
+
+/**
+ * Closes the convert session in case of data supply completed or error occurred.
+ * Upon successful conversion of the complete data, it returns signature calculated over
+ * the entire data used over a conversion session. This signature must be copied to the offset
+ * mentioned in the DrmConvertedStatus. Signature is used for data integrity protection.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application about the file offset at which this
+ * signature data should be written.
+ */
+DrmConvertedStatus* onCloseConvertSession(int uniqueId, int convertId);
+
+/**
+ * Returns the information about the Drm Engine capabilities which includes
+ * supported MimeTypes and file suffixes.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @return DrmSupportInfo
+ * instance which holds the capabilities of a plug-in
+ */
+DrmSupportInfo* onGetSupportInfo(int uniqueId);
+
+/**
+ * Open the decrypt session to decrypt the given protected content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the current decryption session
+ * @param fd File descriptor of the protected content to be decrypted
+ * @param offset Start position of the content
+ * @param length The length of the protected content
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+#ifdef USE_64BIT_DRM_API
+status_t onOpenDecryptSession(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int fd, off64_t offset, off64_t length);
+#else
+status_t onOpenDecryptSession(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int fd, int offset, int length);
+#endif
+
+/**
+ * Open the decrypt session to decrypt the given protected content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the current decryption session
+ * @param uri Path of the protected content to be decrypted
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+status_t onOpenDecryptSession(int uniqueId,
+ DecryptHandle* decryptHandle,
+ const char* uri);
+
+/**
+ * Close the decrypt session for the given handle.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+status_t onCloseDecryptSession(int uniqueId,
+ DecryptHandle* decryptHandle);
+
+/**
+ * Initialize decryption for the given unit of the protected content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param headerInfo Information for initializing decryption of this decrypUnit
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+status_t onInitializeDecryptUnit(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int decryptUnitId,
+ const DrmBuffer* headerInfo);
+
+/**
+ * Decrypt the protected content buffers for the given unit.
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param encBuffer Encrypted data block
+ * @param decBuffer Decrypted data block
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+status_t onDecrypt(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int decryptUnitId,
+ const DrmBuffer* encBuffer,
+ DrmBuffer** decBuffer);
+
+/**
+ * Decrypt the protected content buffers for the given unit.
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptId Handle for the decryption session
+ * @param decryptUnitId ID Specifies decryption unit, such as track ID
+ * @param encBuffer Encrypted data block
+ * @param decBuffer Decrypted data block
+ * @param IV Optional buffer
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer,
+ DrmBuffer** decBuffer, DrmBuffer* IV);
+
+/**
+ * Finalize decryption for the given unit of the protected content.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param decryptUnitId ID Specifies decryption unit, such as track ID
+ * @return
+ * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success
+ */
+status_t onFinalizeDecryptUnit(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int decryptUnitId);
+
+/**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param buffer Reference to the buffer that should receive the read data.
+ * @param numBytes Number of bytes to read.
+ *
+ * @return Number of bytes read.
+ * @retval -1 Failure.
+ */
+ssize_t onRead(int uniqueId,
+ DecryptHandle* decryptHandle,
+ void* pBuffer,
+ int numBytes);
+
+/**
+ * Updates the file position within an open DRM file.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param offset Offset with which to update the file position.
+ * @param whence One of SEEK_SET, SEEK_CUR, and SEEK_END.
+ * These constants are defined in unistd.h.
+ *
+ * @return New file position.
+ * @retval ((off_t)-1) Failure.
+ */
+#ifdef USE_64BIT_DRM_API
+off64_t onLseek(int uniqueId,
+ DecryptHandle* decryptHandle,
+ off64_t offset,
+ int whence);
+#else
+off_t onLseek(int uniqueId,
+ DecryptHandle* decryptHandle,
+ off_t offset,
+ int whence);
+#endif
+
+/**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param uniqueId Unique identifier for a session
+ * @param decryptHandle Handle for the decryption session
+ * @param buffer Reference to the buffer that should receive the read data.
+ * @param numBytes Number of bytes to read.
+ * @param offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+#ifdef USE_64BIT_DRM_API
+ssize_t onPread(int uniqueId,
+ DecryptHandle* decryptHandle,
+ void* buffer,
+ ssize_t numBytes,
+ off64_t offset);
+#else
+ssize_t onPread(int uniqueId,
+ DecryptHandle* decryptHandle,
+ void* buffer,
+ ssize_t numBytes,
+ off_t offset);
+#endif
+
+private:
+
+ static const String8 Description;
+ static const String8 FileSuffixes[];
+ static const String8 MimeTypes[];
+ static bool IsFileSuffixSupported(const String8& suffix);
+ static bool IsMimeTypeSupported(const String8& mime);
+ static void AddSupportedMimeTypes(DrmSupportInfo *info);
+ static void AddSupportedFileSuffixes(DrmSupportInfo *info);
+
+/**
+ * Session Class for Forward Lock Conversion. An object of this class is created
+ * for every conversion.
+ */
+class ConvertSession {
+ public :
+ int uniqueId;
+ FwdLockConv_Output_t output;
+
+ ConvertSession() {
+ uniqueId = 0;
+ memset(&output, 0, sizeof(FwdLockConv_Output_t));
+ }
+
+ virtual ~ConvertSession() {}
+};
+
+/**
+ * Session Class for Forward Lock decoder. An object of this class is created
+ * for every decoding session.
+ */
+class DecodeSession {
+ public :
+ int fileDesc;
+ off_t offset;
+
+ DecodeSession() {
+ fileDesc = -1;
+ offset = 0;
+ }
+
+ DecodeSession(int fd) {
+ fileDesc = fd;
+ offset = 0;
+ }
+
+ virtual ~DecodeSession() {}
+};
+
+/**
+ * Session Map Tables for Conversion and Decoding of forward lock files.
+ */
+SessionMap<ConvertSession*> convertSessionMap;
+SessionMap<DecodeSession*> decodeSessionMap;
+
+/**
+ * Converts the error code from Forward Lock Converter to DrmConvertStatus error code.
+ *
+ * @param Forward Lock Converter error code
+ *
+ * @return Status code from DrmConvertStatus.
+ */
+static int getConvertedStatus(FwdLockConv_Status_t status);
+};
+
+};
+
+#endif /* __FWDLOCKENGINE_H__ */
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
new file mode 100644
index 0000000..4b1b40e
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
@@ -0,0 +1,695 @@
+/*
+ * 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 "SessionMap.h"
+#include "FwdLockEngine.h"
+#include <utils/Log.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "drm_framework_common.h"
+#include <fcntl.h>
+#include <limits.h>
+#include <DrmRights.h>
+#include <DrmConstraints.h>
+#include <DrmMetadata.h>
+#include <DrmInfo.h>
+#include <DrmInfoStatus.h>
+#include <DrmInfoRequest.h>
+#include <DrmSupportInfo.h>
+#include <DrmConvertedStatus.h>
+#include <utils/String8.h>
+#include "FwdLockConv.h"
+#include "FwdLockFile.h"
+#include "FwdLockGlue.h"
+#include "MimeTypeUtil.h"
+
+#undef LOG_TAG
+#define LOG_TAG "FwdLockEngine"
+
+#ifdef DRM_OMA_FL_ENGINE_DEBUG
+#define LOG_NDEBUG 0
+#define LOG_VERBOSE(...) ALOGV(__VA_ARGS__)
+#else
+#define LOG_VERBOSE(...)
+#endif
+
+using namespace android;
+// This extern "C" is mandatory to be managed by TPlugInManager
+extern "C" IDrmEngine* create() {
+ return new FwdLockEngine();
+}
+
+// This extern "C" is mandatory to be managed by TPlugInManager
+extern "C" void destroy(IDrmEngine* plugIn) {
+ delete plugIn;
+}
+
+FwdLockEngine::FwdLockEngine() {
+ LOG_VERBOSE("FwdLockEngine Construction");
+}
+
+FwdLockEngine::~FwdLockEngine() {
+ LOG_VERBOSE("FwdLockEngine Destruction");
+
+ int size = decodeSessionMap.getSize();
+
+ for (int i = 0; i < size; i++) {
+ DecodeSession *session = (DecodeSession*) decodeSessionMap.getValueAt(i);
+ FwdLockFile_detach(session->fileDesc);
+ ::close(session->fileDesc);
+ }
+
+ size = convertSessionMap.getSize();
+ for (int i = 0; i < size; i++) {
+ ConvertSession *convSession = (ConvertSession*) convertSessionMap.getValueAt(i);
+ FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output));
+ }
+}
+
+int FwdLockEngine::getConvertedStatus(FwdLockConv_Status_t status) {
+ int retStatus = DrmConvertedStatus::STATUS_ERROR;
+
+ switch(status) {
+ case FwdLockConv_Status_OK:
+ retStatus = DrmConvertedStatus::STATUS_OK;
+ break;
+ case FwdLockConv_Status_SyntaxError:
+ case FwdLockConv_Status_InvalidArgument:
+ case FwdLockConv_Status_UnsupportedFileFormat:
+ case FwdLockConv_Status_UnsupportedContentTransferEncoding:
+ ALOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. "
+ "Returning STATUS_INPUTDATA_ERROR", status);
+ retStatus = DrmConvertedStatus::STATUS_INPUTDATA_ERROR;
+ break;
+ default:
+ ALOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. "
+ "Returning STATUS_ERROR", status);
+ retStatus = DrmConvertedStatus::STATUS_ERROR;
+ break;
+ }
+
+ return retStatus;
+}
+
+DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* path, int action) {
+ DrmConstraints* drmConstraints = NULL;
+
+ LOG_VERBOSE("FwdLockEngine::onGetConstraints");
+
+ if (NULL != path &&
+ (RightsStatus::RIGHTS_VALID == onCheckRightsStatus(uniqueId, *path, action))) {
+ // Return the empty constraints to show no error condition.
+ drmConstraints = new DrmConstraints();
+ }
+
+ return drmConstraints;
+}
+
+DrmMetadata* FwdLockEngine::onGetMetadata(int uniqueId, const String8* path) {
+ DrmMetadata* drmMetadata = NULL;
+
+ LOG_VERBOSE("FwdLockEngine::onGetMetadata");
+
+ if (NULL != path) {
+ // Returns empty metadata to show no error condition.
+ drmMetadata = new DrmMetadata();
+ }
+
+ return drmMetadata;
+}
+
+android::status_t FwdLockEngine::onInitialize(int uniqueId) {
+ LOG_VERBOSE("FwdLockEngine::onInitialize");
+
+ if (FwdLockGlue_InitializeKeyEncryption()) {
+ LOG_VERBOSE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
+ } else {
+ ALOGE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:"
+ "errno = %d", errno);
+ }
+
+ return DRM_NO_ERROR;
+}
+
+android::status_t
+FwdLockEngine::onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
+ // Not used
+ LOG_VERBOSE("FwdLockEngine::onSetOnInfoListener");
+
+ return DRM_NO_ERROR;
+}
+
+android::status_t FwdLockEngine::onTerminate(int uniqueId) {
+ LOG_VERBOSE("FwdLockEngine::onTerminate");
+
+ return DRM_NO_ERROR;
+}
+
+// make sure that lower-case letters are used.
+const String8 FwdLockEngine::FileSuffixes[] = {
+ String8(".fl"),
+ String8(".dm"),
+};
+
+// make sure that lower-case letters are used.
+const String8 FwdLockEngine::MimeTypes[] = {
+ String8("application/x-android-drm-fl"),
+ String8("application/vnd.oma.drm.message"),
+};
+
+const String8 FwdLockEngine::Description("OMA V1 Forward Lock");
+
+void FwdLockEngine::AddSupportedMimeTypes(DrmSupportInfo *info) {
+ for (size_t i = 0, n = sizeof(MimeTypes)/sizeof(MimeTypes[0]); i < n; ++i) {
+ info->addMimeType(MimeTypes[i]);
+ }
+}
+
+void FwdLockEngine::AddSupportedFileSuffixes(DrmSupportInfo *info) {
+ for (size_t i = 0, n = sizeof(FileSuffixes)/sizeof(FileSuffixes[0]); i < n; ++i) {
+ info->addFileSuffix(FileSuffixes[i]);
+ }
+}
+
+bool FwdLockEngine::IsMimeTypeSupported(const String8& mime) {
+ String8 tmp(mime);
+ tmp.toLower();
+ for (size_t i = 0, n = sizeof(MimeTypes)/sizeof(MimeTypes[0]); i < n; ++i) {
+ if (tmp == MimeTypes[i]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool FwdLockEngine::IsFileSuffixSupported(const String8& suffix) {
+ String8 tmp(suffix);
+ tmp.toLower();
+ for (size_t i = 0, n = sizeof(FileSuffixes)/sizeof(FileSuffixes[0]); i < n; ++i) {
+ if (tmp == FileSuffixes[i]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int uniqueId) {
+ DrmSupportInfo* pSupportInfo = new DrmSupportInfo();
+
+ LOG_VERBOSE("FwdLockEngine::onGetSupportInfo");
+
+ // fill all Forward Lock mimetypes and extensions
+ if (NULL != pSupportInfo) {
+ AddSupportedMimeTypes(pSupportInfo);
+ AddSupportedFileSuffixes(pSupportInfo);
+ pSupportInfo->setDescription(Description);
+ }
+
+ return pSupportInfo;
+}
+
+bool FwdLockEngine::onCanHandle(int uniqueId, const String8& path) {
+ bool result = false;
+
+ String8 extString = path.getPathExtension();
+ return IsFileSuffixSupported(extString);
+}
+
+DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ DrmInfoStatus *drmInfoStatus = NULL;
+
+ // Nothing to process
+
+ drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8(""));
+
+ LOG_VERBOSE("FwdLockEngine::onProcessDrmInfo");
+
+ return drmInfoStatus;
+}
+
+status_t FwdLockEngine::onSaveRights(
+ int uniqueId,
+ const DrmRights& drmRights,
+ const String8& rightsPath,
+ const String8& contentPath) {
+ // No rights to save. Return
+ LOG_VERBOSE("FwdLockEngine::onSaveRights");
+ return DRM_ERROR_UNKNOWN;
+}
+
+DrmInfo* FwdLockEngine::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ DrmInfo* drmInfo = NULL;
+
+ // Nothing to be done for Forward Lock file
+ LOG_VERBOSE("FwdLockEngine::onAcquireDrmInfo");
+
+ return drmInfo;
+}
+
+int FwdLockEngine::onCheckRightsStatus(int uniqueId,
+ const String8& path,
+ int action) {
+ int result = RightsStatus::RIGHTS_INVALID;
+
+ LOG_VERBOSE("FwdLockEngine::onCheckRightsStatus");
+
+ // Only Transfer action is not allowed for forward Lock files.
+ if (onCanHandle(uniqueId, path)) {
+ switch(action) {
+ case Action::DEFAULT:
+ case Action::PLAY:
+ case Action::RINGTONE:
+ case Action::OUTPUT:
+ case Action::PREVIEW:
+ case Action::EXECUTE:
+ case Action::DISPLAY:
+ result = RightsStatus::RIGHTS_VALID;
+ break;
+
+ case Action::TRANSFER:
+ default:
+ result = RightsStatus::RIGHTS_INVALID;
+ break;
+ }
+ }
+
+ return result;
+}
+
+status_t FwdLockEngine::onConsumeRights(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int action,
+ bool reserve) {
+ // No rights consumption
+ LOG_VERBOSE("FwdLockEngine::onConsumeRights");
+ return DRM_NO_ERROR;
+}
+
+bool FwdLockEngine::onValidateAction(int uniqueId,
+ const String8& path,
+ int action,
+ const ActionDescription& description) {
+ LOG_VERBOSE("FwdLockEngine::onValidateAction");
+
+ // For the forwardlock engine checkRights and ValidateAction are the same.
+ return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID);
+}
+
+String8 FwdLockEngine::onGetOriginalMimeType(int uniqueId, const String8& path) {
+ LOG_VERBOSE("FwdLockEngine::onGetOriginalMimeType");
+ String8 mimeString = String8("");
+ int fileDesc = FwdLockFile_open(path.string());
+
+ if (-1 < fileDesc) {
+ const char* pMimeType = FwdLockFile_GetContentType(fileDesc);
+
+ if (NULL != pMimeType) {
+ String8 contentType = String8(pMimeType);
+ contentType.toLower();
+ mimeString = MimeTypeUtil::convertMimeType(contentType);
+ }
+
+ FwdLockFile_close(fileDesc);
+ }
+
+ return mimeString;
+}
+
+int FwdLockEngine::onGetDrmObjectType(int uniqueId,
+ const String8& path,
+ const String8& mimeType) {
+ String8 mimeStr = String8(mimeType);
+
+ LOG_VERBOSE("FwdLockEngine::onGetDrmObjectType");
+
+ /* Checks whether
+ * 1. path and mime type both are not empty strings (meaning unavailable) else content is unknown
+ * 2. if one of them is empty string and if other is known then its a DRM Content Object.
+ * 3. if both of them are available, then both may be of known type
+ * (regardless of the relation between them to make it compatible with other DRM Engines)
+ */
+ if (((0 == path.length()) || onCanHandle(uniqueId, path)) &&
+ ((0 == mimeType.length()) || IsMimeTypeSupported(mimeType)) && (mimeType != path) ) {
+ return DrmObjectType::CONTENT;
+ }
+
+ return DrmObjectType::UNKNOWN;
+}
+
+status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) {
+ // No Rights to remove
+ LOG_VERBOSE("FwdLockEngine::onRemoveRights");
+ return DRM_NO_ERROR;
+}
+
+status_t FwdLockEngine::onRemoveAllRights(int uniqueId) {
+ // No rights to remove
+ LOG_VERBOSE("FwdLockEngine::onRemoveAllRights");
+ return DRM_NO_ERROR;
+}
+
+#ifdef USE_64BIT_DRM_API
+status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
+ int playbackStatus, int64_t position) {
+#else
+status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
+ int playbackStatus, int position) {
+#endif
+ // Not used
+ LOG_VERBOSE("FwdLockEngine::onSetPlaybackStatus");
+ return DRM_NO_ERROR;
+}
+
+status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
+ int convertId) {
+ status_t result = DRM_ERROR_UNKNOWN;
+ LOG_VERBOSE("FwdLockEngine::onOpenConvertSession");
+ if (!convertSessionMap.isCreated(convertId)) {
+ ConvertSession *newSession = new ConvertSession();
+ if (FwdLockConv_Status_OK ==
+ FwdLockConv_OpenSession(&(newSession->uniqueId), &(newSession->output))) {
+ convertSessionMap.addValue(convertId, newSession);
+ result = DRM_NO_ERROR;
+ } else {
+ ALOGE("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed.");
+ delete newSession;
+ }
+ }
+ return result;
+}
+
+DrmConvertedStatus* FwdLockEngine::onConvertData(int uniqueId,
+ int convertId,
+ const DrmBuffer* inputData) {
+ FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
+ DrmBuffer *convResult = new DrmBuffer(NULL, 0);
+ int offset = -1;
+
+ if (NULL != inputData && convertSessionMap.isCreated(convertId)) {
+ ConvertSession *convSession = convertSessionMap.getValue(convertId);
+
+ if (NULL != convSession) {
+ retStatus = FwdLockConv_ConvertData(convSession->uniqueId,
+ inputData->data,
+ inputData->length,
+ &(convSession->output));
+
+ if (FwdLockConv_Status_OK == retStatus) {
+ // return bytes from conversion if available
+ if (convSession->output.fromConvertData.numBytes > 0) {
+ convResult->data = new char[convSession->output.fromConvertData.numBytes];
+
+ if (NULL != convResult->data) {
+ convResult->length = convSession->output.fromConvertData.numBytes;
+ memcpy(convResult->data,
+ (char *)convSession->output.fromConvertData.pBuffer,
+ convResult->length);
+ }
+ }
+ } else {
+ offset = convSession->output.fromConvertData.errorPos;
+ }
+ }
+ }
+ return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
+}
+
+DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int uniqueId,
+ int convertId) {
+ FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
+ DrmBuffer *convResult = new DrmBuffer(NULL, 0);
+ int offset = -1;
+
+ LOG_VERBOSE("FwdLockEngine::onCloseConvertSession");
+
+ if (convertSessionMap.isCreated(convertId)) {
+ ConvertSession *convSession = convertSessionMap.getValue(convertId);
+
+ if (NULL != convSession) {
+ retStatus = FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output));
+
+ if (FwdLockConv_Status_OK == retStatus) {
+ offset = convSession->output.fromCloseSession.fileOffset;
+ convResult->data = new char[FWD_LOCK_SIGNATURES_SIZE];
+
+ if (NULL != convResult->data) {
+ convResult->length = FWD_LOCK_SIGNATURES_SIZE;
+ memcpy(convResult->data,
+ (char *)convSession->output.fromCloseSession.signatures,
+ convResult->length);
+ }
+ }
+ }
+ convertSessionMap.removeValue(convertId);
+ }
+ return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
+}
+
+#ifdef USE_64BIT_DRM_API
+status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int fd,
+ off64_t offset,
+ off64_t length) {
+#else
+status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int fd,
+ int offset,
+ int length) {
+#endif
+ status_t result = DRM_ERROR_CANNOT_HANDLE;
+ int fileDesc = -1;
+
+ LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession");
+
+ if ((-1 < fd) &&
+ (NULL != decryptHandle) &&
+ (!decodeSessionMap.isCreated(decryptHandle->decryptId))) {
+ fileDesc = dup(fd);
+ } else {
+ ALOGE("FwdLockEngine::onOpenDecryptSession parameter error");
+ return result;
+ }
+
+ if (-1 < fileDesc &&
+ -1 < ::lseek(fileDesc, offset, SEEK_SET) &&
+ -1 < FwdLockFile_attach(fileDesc)) {
+ // check for file integrity. This must be done to protect the content mangling.
+ int retVal = FwdLockFile_CheckHeaderIntegrity(fileDesc);
+ DecodeSession* decodeSession = new DecodeSession(fileDesc);
+
+ if (retVal && NULL != decodeSession) {
+ decodeSessionMap.addValue(decryptHandle->decryptId, decodeSession);
+ const char *pmime= FwdLockFile_GetContentType(fileDesc);
+ String8 contentType = String8(pmime == NULL ? "" : pmime);
+ contentType.toLower();
+ decryptHandle->mimeType = MimeTypeUtil::convertMimeType(contentType);
+ decryptHandle->decryptApiType = DecryptApiType::CONTAINER_BASED;
+ decryptHandle->status = RightsStatus::RIGHTS_VALID;
+ decryptHandle->decryptInfo = NULL;
+ result = DRM_NO_ERROR;
+ } else {
+ LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
+ FwdLockFile_detach(fileDesc);
+ delete decodeSession;
+ }
+ }
+
+ if (DRM_NO_ERROR != result && -1 < fileDesc) {
+ ::close(fileDesc);
+ }
+
+ LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
+
+ return result;
+}
+
+status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
+ DecryptHandle* decryptHandle,
+ const char* uri) {
+ status_t result = DRM_ERROR_CANNOT_HANDLE;
+ const char fileTag [] = "file://";
+
+ if (NULL != decryptHandle && NULL != uri && strlen(uri) > sizeof(fileTag)) {
+ String8 uriTag = String8(uri);
+ uriTag.toLower();
+
+ if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) {
+ const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/');
+ if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) {
+ int fd = open(filePath, O_RDONLY);
+
+ if (-1 < fd) {
+ // offset is always 0 and length is not used. so any positive size.
+ result = onOpenDecryptSession(uniqueId, decryptHandle, fd, 0, 1);
+
+ // fd is duplicated already if success. closing the file
+ close(fd);
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
+ DecryptHandle* decryptHandle) {
+ status_t result = DRM_ERROR_UNKNOWN;
+ LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession");
+
+ if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
+ DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
+ if (NULL != session && session->fileDesc > -1) {
+ FwdLockFile_detach(session->fileDesc);
+ ::close(session->fileDesc);
+ decodeSessionMap.removeValue(decryptHandle->decryptId);
+ result = DRM_NO_ERROR;
+ }
+ }
+
+ if (NULL != decryptHandle) {
+ if (NULL != decryptHandle->decryptInfo) {
+ delete decryptHandle->decryptInfo;
+ decryptHandle->decryptInfo = NULL;
+ }
+
+ decryptHandle->copyControlVector.clear();
+ decryptHandle->extendedData.clear();
+
+ delete decryptHandle;
+ decryptHandle = NULL;
+ }
+
+ LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession Exit");
+ return result;
+}
+
+status_t FwdLockEngine::onInitializeDecryptUnit(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int decryptUnitId,
+ const DrmBuffer* headerInfo) {
+ ALOGE("FwdLockEngine::onInitializeDecryptUnit is not supported for this DRM scheme");
+ return DRM_ERROR_UNKNOWN;
+}
+
+status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
+ return DRM_ERROR_UNKNOWN;
+}
+
+status_t FwdLockEngine::onDecrypt(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int decryptUnitId,
+ const DrmBuffer* encBuffer,
+ DrmBuffer** decBuffer) {
+ ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
+ return DRM_ERROR_UNKNOWN;
+}
+
+status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId,
+ DecryptHandle* decryptHandle,
+ int decryptUnitId) {
+ ALOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme");
+ return DRM_ERROR_UNKNOWN;
+}
+
+ssize_t FwdLockEngine::onRead(int uniqueId,
+ DecryptHandle* decryptHandle,
+ void* buffer,
+ int numBytes) {
+ ssize_t size = -1;
+
+ if (NULL != decryptHandle &&
+ decodeSessionMap.isCreated(decryptHandle->decryptId) &&
+ NULL != buffer &&
+ numBytes > -1) {
+ DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
+ if (NULL != session && session->fileDesc > -1) {
+ size = FwdLockFile_read(session->fileDesc, buffer, numBytes);
+
+ if (0 > size) {
+ session->offset = ((off_t)-1);
+ } else {
+ session->offset += size;
+ }
+ }
+ }
+
+ return size;
+}
+
+#ifdef USE_64BIT_DRM_API
+off64_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
+ off64_t offset, int whence) {
+#else
+off_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
+ off_t offset, int whence) {
+#endif
+ off_t offval = -1;
+
+ if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
+ DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
+ if (NULL != session && session->fileDesc > -1) {
+ offval = FwdLockFile_lseek(session->fileDesc, offset, whence);
+ session->offset = offval;
+ }
+ }
+
+ return offval;
+}
+
+#ifdef USE_64BIT_DRM_API
+ssize_t FwdLockEngine::onPread(int uniqueId,
+ DecryptHandle* decryptHandle,
+ void* buffer,
+ ssize_t numBytes,
+ off64_t offset) {
+#else
+ssize_t FwdLockEngine::onPread(int uniqueId,
+ DecryptHandle* decryptHandle,
+ void* buffer,
+ ssize_t numBytes,
+ off_t offset) {
+#endif
+ ssize_t bytesRead = -1;
+
+ DecodeSession* decoderSession = NULL;
+
+ if ((NULL != decryptHandle) &&
+ (NULL != (decoderSession = decodeSessionMap.getValue(decryptHandle->decryptId))) &&
+ (NULL != buffer) &&
+ (numBytes > -1) &&
+ (offset > -1)) {
+ if (offset != decoderSession->offset) {
+ decoderSession->offset = onLseek(uniqueId, decryptHandle, offset, SEEK_SET);
+ }
+
+ if (((off_t)-1) != decoderSession->offset) {
+ bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes);
+ if (bytesRead < 0) {
+ ALOGE("FwdLockEngine::onPread error reading");
+ }
+ }
+ } else {
+ ALOGE("FwdLockEngine::onPread decryptId not found");
+ }
+
+ return bytesRead;
+}
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/Android.mk
new file mode 100644
index 0000000..9ee7961
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/Android.mk
@@ -0,0 +1,16 @@
+#
+# 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 $(call all-subdir-makefiles)
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk
new file mode 100644
index 0000000..6c5d3cf
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/common/Android.mk
@@ -0,0 +1,32 @@
+#
+# 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.
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ FwdLockGlue.c
+
+LOCAL_C_INCLUDES := \
+ external/openssl/include
+
+LOCAL_SHARED_LIBRARIES := libcrypto
+
+LOCAL_MODULE := libfwdlock-common
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.c b/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.c
new file mode 100644
index 0000000..92bda8f
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.c
@@ -0,0 +1,191 @@
+/*
+ * 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 <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <openssl/aes.h>
+
+#include "FwdLockGlue.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define KEY_SIZE 16
+#define KEY_SIZE_IN_BITS (KEY_SIZE * 8)
+
+static int isInitialized = FALSE;
+
+static const char strKeyFilename[] = "/data/drm/fwdlock/kek.dat";
+
+static AES_KEY encryptionRoundKeys;
+static AES_KEY decryptionRoundKeys;
+
+/**
+ * Creates all directories along the fully qualified path of the given file.
+ *
+ * @param[in] path A reference to the fully qualified path of a file.
+ * @param[in] mode The access mode to use for the directories being created.
+ *
+ * @return A Boolean value indicating whether the operation was successful.
+ */
+static int FwdLockGlue_CreateDirectories(const char *path, mode_t mode) {
+ int result = TRUE;
+ size_t partialPathLength = strlen(path);
+ char *partialPath = malloc(partialPathLength + 1);
+ if (partialPath == NULL) {
+ result = FALSE;
+ } else {
+ size_t i;
+ for (i = 0; i < partialPathLength; ++i) {
+ if (path[i] == '/' && i > 0) {
+ partialPath[i] = '\0';
+ if (mkdir(partialPath, mode) != 0 && errno != EEXIST) {
+ result = FALSE;
+ break;
+ }
+ }
+ partialPath[i] = path[i];
+ }
+ free(partialPath);
+ }
+ return result;
+}
+
+/**
+ * Initializes the round keys used for encryption and decryption of session keys. First creates a
+ * device-unique key-encryption key if none exists yet.
+ */
+static void FwdLockGlue_InitializeRoundKeys() {
+ unsigned char keyEncryptionKey[KEY_SIZE];
+ int fileDesc = open(strKeyFilename, O_RDONLY);
+ if (fileDesc >= 0) {
+ if (read(fileDesc, keyEncryptionKey, KEY_SIZE) == KEY_SIZE) {
+ isInitialized = TRUE;
+ }
+ (void)close(fileDesc);
+ } else if (errno == ENOENT &&
+ FwdLockGlue_GetRandomNumber(keyEncryptionKey, KEY_SIZE) &&
+ FwdLockGlue_CreateDirectories(strKeyFilename, S_IRWXU)) {
+ fileDesc = open(strKeyFilename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR);
+ if (fileDesc >= 0) {
+ if (write(fileDesc, keyEncryptionKey, KEY_SIZE) == KEY_SIZE) {
+ isInitialized = TRUE;
+ }
+ (void)close(fileDesc);
+ }
+ }
+ if (isInitialized) {
+ if (AES_set_encrypt_key(keyEncryptionKey, KEY_SIZE_IN_BITS, &encryptionRoundKeys) != 0 ||
+ AES_set_decrypt_key(keyEncryptionKey, KEY_SIZE_IN_BITS, &decryptionRoundKeys) != 0) {
+ isInitialized = FALSE;
+ }
+ }
+ memset(keyEncryptionKey, 0, KEY_SIZE); // Zero out key data.
+}
+
+/**
+ * Validates the padding of a decrypted key.
+ *
+ * @param[in] pData A reference to the buffer containing the decrypted key and padding.
+ * @param[in] decryptedKeyLength The length in bytes of the decrypted key.
+ *
+ * @return A Boolean value indicating whether the padding was valid.
+ */
+static int FwdLockGlue_ValidatePadding(const unsigned char *pData, size_t decryptedKeyLength) {
+ size_t i;
+ size_t padding = AES_BLOCK_SIZE - (decryptedKeyLength % AES_BLOCK_SIZE);
+ pData += decryptedKeyLength;
+ for (i = 0; i < padding; ++i) {
+ if ((size_t)*pData != padding) {
+ return FALSE;
+ }
+ ++pData;
+ }
+ return TRUE;
+}
+
+int FwdLockGlue_GetRandomNumber(void *pBuffer, size_t numBytes) {
+ // Generate 'cryptographically secure' random bytes by reading them from "/dev/urandom" (the
+ // non-blocking version of "/dev/random").
+ ssize_t numBytesRead = 0;
+ int fileDesc = open("/dev/urandom", O_RDONLY);
+ if (fileDesc >= 0) {
+ numBytesRead = read(fileDesc, pBuffer, numBytes);
+ (void)close(fileDesc);
+ }
+ return numBytesRead >= 0 && (size_t)numBytesRead == numBytes;
+}
+
+int FwdLockGlue_InitializeKeyEncryption() {
+ static pthread_once_t once = PTHREAD_ONCE_INIT;
+ pthread_once(&once, FwdLockGlue_InitializeRoundKeys);
+ return isInitialized;
+}
+
+size_t FwdLockGlue_GetEncryptedKeyLength(size_t plaintextKeyLength) {
+ return ((plaintextKeyLength / AES_BLOCK_SIZE) + 2) * AES_BLOCK_SIZE;
+}
+
+int FwdLockGlue_EncryptKey(const void *pPlaintextKey,
+ size_t plaintextKeyLength,
+ void *pEncryptedKey,
+ size_t encryptedKeyLength) {
+ int result = FALSE;
+ assert(encryptedKeyLength == FwdLockGlue_GetEncryptedKeyLength(plaintextKeyLength));
+ if (FwdLockGlue_InitializeKeyEncryption()) {
+ unsigned char initVector[AES_BLOCK_SIZE];
+ if (FwdLockGlue_GetRandomNumber(initVector, AES_BLOCK_SIZE)) {
+ size_t padding = AES_BLOCK_SIZE - (plaintextKeyLength % AES_BLOCK_SIZE);
+ size_t dataLength = encryptedKeyLength - AES_BLOCK_SIZE;
+ memcpy(pEncryptedKey, pPlaintextKey, plaintextKeyLength);
+ memset((unsigned char *)pEncryptedKey + plaintextKeyLength, (int)padding, padding);
+ memcpy((unsigned char *)pEncryptedKey + dataLength, initVector, AES_BLOCK_SIZE);
+ AES_cbc_encrypt(pEncryptedKey, pEncryptedKey, dataLength, &encryptionRoundKeys,
+ initVector, AES_ENCRYPT);
+ result = TRUE;
+ }
+ }
+ return result;
+}
+
+int FwdLockGlue_DecryptKey(const void *pEncryptedKey,
+ size_t encryptedKeyLength,
+ void *pDecryptedKey,
+ size_t decryptedKeyLength) {
+ int result = FALSE;
+ assert(encryptedKeyLength == FwdLockGlue_GetEncryptedKeyLength(decryptedKeyLength));
+ if (FwdLockGlue_InitializeKeyEncryption()) {
+ size_t dataLength = encryptedKeyLength - AES_BLOCK_SIZE;
+ unsigned char *pData = malloc(dataLength);
+ if (pData != NULL) {
+ unsigned char initVector[AES_BLOCK_SIZE];
+ memcpy(pData, pEncryptedKey, dataLength);
+ memcpy(initVector, (const unsigned char *)pEncryptedKey + dataLength, AES_BLOCK_SIZE);
+ AES_cbc_encrypt(pData, pData, dataLength, &decryptionRoundKeys, initVector,
+ AES_DECRYPT);
+ memcpy(pDecryptedKey, pData, decryptedKeyLength);
+ result = FwdLockGlue_ValidatePadding(pData, decryptedKeyLength);
+ free(pData);
+ }
+ }
+ return result;
+}
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.h b/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.h
new file mode 100644
index 0000000..f36f6ea
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/common/FwdLockGlue.h
@@ -0,0 +1,85 @@
+/*
+ * 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 __FWDLOCKGLUE_H__
+#define __FWDLOCKGLUE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Generates the specified number of cryptographically secure random bytes.
+ *
+ * @param[out] pBuffer A reference to the buffer that should receive the random data.
+ * @param[in] numBytes The number of random bytes to generate.
+ *
+ * @return A Boolean value indicating whether the operation was successful.
+ */
+int FwdLockGlue_GetRandomNumber(void *pBuffer, size_t numBytes);
+
+/**
+ * Performs initialization of the key-encryption key. Should be called once during startup to
+ * facilitate encryption and decryption of session keys.
+ *
+ * @return A Boolean value indicating whether the operation was successful.
+ */
+int FwdLockGlue_InitializeKeyEncryption();
+
+/**
+ * Returns the length of the encrypted key, given the length of the plaintext key.
+ *
+ * @param[in] plaintextKeyLength The length in bytes of the plaintext key.
+ *
+ * @return The length in bytes of the encrypted key.
+ */
+size_t FwdLockGlue_GetEncryptedKeyLength(size_t plaintextKeyLength);
+
+/**
+ * Encrypts the given session key using a key-encryption key unique to this device.
+ *
+ * @param[in] pPlaintextKey A reference to the buffer containing the plaintext key.
+ * @param[in] plaintextKeyLength The length in bytes of the plaintext key.
+ * @param[out] pEncryptedKey A reference to the buffer containing the encrypted key.
+ * @param[in] encryptedKeyLength The length in bytes of the encrypted key.
+ *
+ * @return A Boolean value indicating whether the operation was successful.
+ */
+int FwdLockGlue_EncryptKey(const void *pPlaintextKey,
+ size_t plaintextKeyLength,
+ void *pEncryptedKey,
+ size_t encryptedKeyLength);
+
+/**
+ * Decrypts the given session key using a key-encryption key unique to this device.
+ *
+ * @param[in] pEncryptedKey A reference to the buffer containing the encrypted key.
+ * @param[in] encryptedKeyLength The length in bytes of the encrypted key.
+ * @param[out] pDecryptedKey A reference to the buffer containing the decrypted key.
+ * @param[in] decryptedKeyLength The length in bytes of the decrypted key.
+ *
+ * @return A Boolean value indicating whether the operation was successful.
+ */
+int FwdLockGlue_DecryptKey(const void *pEncryptedKey,
+ size_t encryptedKeyLength,
+ void *pDecryptedKey,
+ size_t decryptedKeyLength);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __FWDLOCKGLUE_H__
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk
new file mode 100644
index 0000000..00bb788
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/Android.mk
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ FwdLockConv.c
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/drm/libdrmframework/plugins/forward-lock/internal-format/common \
+ external/openssl/include
+
+LOCAL_SHARED_LIBRARIES := libcrypto
+
+LOCAL_WHOLE_STATIC_LIBRARIES := libfwdlock-common
+
+LOCAL_STATIC_LIBRARIES := libfwdlock-common
+
+LOCAL_MODULE := libfwdlock-converter
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
new file mode 100644
index 0000000..299116d
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
@@ -0,0 +1,1347 @@
+/*
+ * 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 <assert.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <openssl/aes.h>
+#include <openssl/hmac.h>
+
+#include "FwdLockConv.h"
+#include "FwdLockGlue.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define INVALID_OFFSET ((off64_t)-1)
+
+#define MAX_NUM_SESSIONS 32
+
+#define OUTPUT_BUFFER_SIZE_INCREMENT 1024
+#define READ_BUFFER_SIZE 1024
+
+#define MAX_BOUNDARY_LENGTH 70
+#define MAX_DELIMITER_LENGTH (MAX_BOUNDARY_LENGTH + 4)
+
+#define STRING_LENGTH_INCREMENT 25
+
+#define KEY_SIZE AES_BLOCK_SIZE
+#define KEY_SIZE_IN_BITS (KEY_SIZE * 8)
+
+#define SHA1_HASH_SIZE 20
+
+#define FWD_LOCK_VERSION 0
+#define FWD_LOCK_SUBFORMAT 0
+#define USAGE_RESTRICTION_FLAGS 0
+#define CONTENT_TYPE_LENGTH_POS 7
+#define TOP_HEADER_SIZE 8
+
+/**
+ * Data type for the parser states of the converter.
+ */
+typedef enum FwdLockConv_ParserState {
+ FwdLockConv_ParserState_WantsOpenDelimiter,
+ FwdLockConv_ParserState_WantsMimeHeaders,
+ FwdLockConv_ParserState_WantsBinaryEncodedData,
+ FwdLockConv_ParserState_WantsBase64EncodedData,
+ FwdLockConv_ParserState_Done
+} FwdLockConv_ParserState_t;
+
+/**
+ * Data type for the scanner states of the converter.
+ */
+typedef enum FwdLockConv_ScannerState {
+ FwdLockConv_ScannerState_WantsFirstDash,
+ FwdLockConv_ScannerState_WantsSecondDash,
+ FwdLockConv_ScannerState_WantsCR,
+ FwdLockConv_ScannerState_WantsLF,
+ FwdLockConv_ScannerState_WantsBoundary,
+ FwdLockConv_ScannerState_WantsBoundaryEnd,
+ FwdLockConv_ScannerState_WantsMimeHeaderNameStart,
+ FwdLockConv_ScannerState_WantsMimeHeaderName,
+ FwdLockConv_ScannerState_WantsMimeHeaderNameEnd,
+ FwdLockConv_ScannerState_WantsContentTypeStart,
+ FwdLockConv_ScannerState_WantsContentType,
+ FwdLockConv_ScannerState_WantsContentTransferEncodingStart,
+ FwdLockConv_ScannerState_Wants_A_OR_I,
+ FwdLockConv_ScannerState_Wants_N,
+ FwdLockConv_ScannerState_Wants_A,
+ FwdLockConv_ScannerState_Wants_R,
+ FwdLockConv_ScannerState_Wants_Y,
+ FwdLockConv_ScannerState_Wants_S,
+ FwdLockConv_ScannerState_Wants_E,
+ FwdLockConv_ScannerState_Wants_6,
+ FwdLockConv_ScannerState_Wants_4,
+ FwdLockConv_ScannerState_Wants_B,
+ FwdLockConv_ScannerState_Wants_I,
+ FwdLockConv_ScannerState_Wants_T,
+ FwdLockConv_ScannerState_WantsContentTransferEncodingEnd,
+ FwdLockConv_ScannerState_WantsMimeHeaderValueEnd,
+ FwdLockConv_ScannerState_WantsMimeHeadersEnd,
+ FwdLockConv_ScannerState_WantsByte1,
+ FwdLockConv_ScannerState_WantsByte1_AfterCRLF,
+ FwdLockConv_ScannerState_WantsByte2,
+ FwdLockConv_ScannerState_WantsByte3,
+ FwdLockConv_ScannerState_WantsByte4,
+ FwdLockConv_ScannerState_WantsPadding,
+ FwdLockConv_ScannerState_WantsWhitespace,
+ FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF,
+ FwdLockConv_ScannerState_WantsDelimiter
+} FwdLockConv_ScannerState_t;
+
+/**
+ * Data type for the content transfer encoding.
+ */
+typedef enum FwdLockConv_ContentTransferEncoding {
+ FwdLockConv_ContentTransferEncoding_Undefined,
+ FwdLockConv_ContentTransferEncoding_Binary,
+ FwdLockConv_ContentTransferEncoding_Base64
+} FwdLockConv_ContentTransferEncoding_t;
+
+/**
+ * Data type for a dynamically growing string.
+ */
+typedef struct FwdLockConv_String {
+ char *ptr;
+ size_t length;
+ size_t maxLength;
+ size_t lengthIncrement;
+} FwdLockConv_String_t;
+
+/**
+ * Data type for the per-file state information needed by the converter.
+ */
+typedef struct FwdLockConv_Session {
+ FwdLockConv_ParserState_t parserState;
+ FwdLockConv_ScannerState_t scannerState;
+ FwdLockConv_ScannerState_t savedScannerState;
+ off64_t numCharsConsumed;
+ char delimiter[MAX_DELIMITER_LENGTH];
+ size_t delimiterLength;
+ size_t delimiterMatchPos;
+ FwdLockConv_String_t mimeHeaderName;
+ FwdLockConv_String_t contentType;
+ FwdLockConv_ContentTransferEncoding_t contentTransferEncoding;
+ unsigned char sessionKey[KEY_SIZE];
+ void *pEncryptedSessionKey;
+ size_t encryptedSessionKeyLength;
+ AES_KEY encryptionRoundKeys;
+ HMAC_CTX signingContext;
+ unsigned char topHeader[TOP_HEADER_SIZE];
+ unsigned char counter[AES_BLOCK_SIZE];
+ unsigned char keyStream[AES_BLOCK_SIZE];
+ int keyStreamIndex;
+ unsigned char ch;
+ size_t outputBufferSize;
+ size_t dataOffset;
+ size_t numDataBytes;
+} FwdLockConv_Session_t;
+
+static FwdLockConv_Session_t *sessionPtrs[MAX_NUM_SESSIONS] = { NULL };
+
+static pthread_mutex_t sessionAcquisitionMutex = PTHREAD_MUTEX_INITIALIZER;
+
+static const FwdLockConv_String_t nullString = { NULL, 0, 0, STRING_LENGTH_INCREMENT };
+
+static const unsigned char topHeaderTemplate[] =
+ { 'F', 'W', 'L', 'K', FWD_LOCK_VERSION, FWD_LOCK_SUBFORMAT, USAGE_RESTRICTION_FLAGS };
+
+static const char strContent[] = "content-";
+static const char strType[] = "type";
+static const char strTransferEncoding[] = "transfer-encoding";
+static const char strTextPlain[] = "text/plain";
+static const char strApplicationVndOmaDrmRightsXml[] = "application/vnd.oma.drm.rights+xml";
+static const char strApplicationVndOmaDrmContent[] = "application/vnd.oma.drm.content";
+
+static const size_t strlenContent = sizeof strContent - 1;
+static const size_t strlenTextPlain = sizeof strTextPlain - 1;
+
+static const signed char base64Values[] = {
+ -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, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
+ -1, 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, -1, -1, -1, -1, -1,
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+};
+
+/**
+ * Acquires an unused converter session.
+ *
+ * @return A session ID.
+ */
+static int FwdLockConv_AcquireSession() {
+ int sessionId = -1;
+ int i;
+ pthread_mutex_lock(&sessionAcquisitionMutex);
+ for (i = 0; i < MAX_NUM_SESSIONS; ++i) {
+ if (sessionPtrs[i] == NULL) {
+ sessionPtrs[i] = malloc(sizeof *sessionPtrs[i]);
+ if (sessionPtrs[i] != NULL) {
+ sessionId = i;
+ }
+ break;
+ }
+ }
+ pthread_mutex_unlock(&sessionAcquisitionMutex);
+ return sessionId;
+}
+
+/**
+ * Checks whether a session ID is in range and currently in use.
+ *
+ * @param[in] sessionID A session ID.
+ *
+ * @return A Boolean value indicating whether the session ID is in range and currently in use.
+ */
+static int FwdLockConv_IsValidSession(int sessionId) {
+ return 0 <= sessionId && sessionId < MAX_NUM_SESSIONS && sessionPtrs[sessionId] != NULL;
+}
+
+/**
+ * Releases a converter session.
+ *
+ * @param[in] sessionID A session ID.
+ */
+static void FwdLockConv_ReleaseSession(int sessionId) {
+ pthread_mutex_lock(&sessionAcquisitionMutex);
+ assert(FwdLockConv_IsValidSession(sessionId));
+ memset(sessionPtrs[sessionId], 0, sizeof *sessionPtrs[sessionId]); // Zero out key data.
+ free(sessionPtrs[sessionId]);
+ sessionPtrs[sessionId] = NULL;
+ pthread_mutex_unlock(&sessionAcquisitionMutex);
+}
+
+/**
+ * Derives cryptographically independent keys for encryption and signing from the session key.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ *
+ * @return A status code.
+ */
+static int FwdLockConv_DeriveKeys(FwdLockConv_Session_t *pSession) {
+ FwdLockConv_Status_t status;
+ struct FwdLockConv_DeriveKeys_Data {
+ AES_KEY sessionRoundKeys;
+ unsigned char value[KEY_SIZE];
+ unsigned char key[KEY_SIZE];
+ } *pData = malloc(sizeof *pData);
+ if (pData == NULL) {
+ status = FwdLockConv_Status_OutOfMemory;
+ } else {
+ if (AES_set_encrypt_key(pSession->sessionKey, KEY_SIZE_IN_BITS,
+ &pData->sessionRoundKeys) != 0) {
+ status = FwdLockConv_Status_ProgramError;
+ } else {
+ // Encrypt the 16-byte value {0, 0, ..., 0} to produce the encryption key.
+ memset(pData->value, 0, KEY_SIZE);
+ AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys);
+ if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS,
+ &pSession->encryptionRoundKeys) != 0) {
+ status = FwdLockConv_Status_ProgramError;
+ } else {
+ // Encrypt the 16-byte value {1, 0, ..., 0} to produce the signing key.
+ ++pData->value[0];
+ AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys);
+ HMAC_CTX_init(&pSession->signingContext);
+ HMAC_Init_ex(&pSession->signingContext, pData->key, KEY_SIZE, EVP_sha1(), NULL);
+ status = FwdLockConv_Status_OK;
+ }
+ }
+ memset(pData, 0, sizeof pData); // Zero out key data.
+ free(pData);
+ }
+ return status;
+}
+
+/**
+ * Checks whether a given character is valid in a boundary. Allows some non-standard characters that
+ * are invalid according to RFC 2046 but nevertheless used by one vendor's DRM packager. Note that
+ * the boundary may contain leading and internal spaces.
+ *
+ * @param[in] ch The character to check.
+ *
+ * @return A Boolean value indicating whether the given character is valid in a boundary.
+ */
+static int FwdLockConv_IsBoundaryChar(int ch) {
+ return isalnum(ch) || ch == '\'' || ch == '(' || ch == ')' || ch == '+' || ch == '_' ||
+ ch == ',' || ch == '-' || ch == '.' || ch == '/' || ch == ':' || ch == '=' ||
+ ch == '?' || ch == ' ' || ch == '%' || ch == '[' || ch == '&' || ch == '*' || ch == '^';
+}
+
+/**
+ * Checks whether a given character should be considered whitespace, using a narrower definition
+ * than the standard-library isspace() function.
+ *
+ * @param[in] ch The character to check.
+ *
+ * @return A Boolean value indicating whether the given character should be considered whitespace.
+ */
+static int FwdLockConv_IsWhitespace(int ch) {
+ return ch == ' ' || ch == '\t';
+}
+
+/**
+ * Removes trailing spaces from the delimiter.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_RightTrimDelimiter(FwdLockConv_Session_t *pSession) {
+ while (pSession->delimiterLength > 4 &&
+ pSession->delimiter[pSession->delimiterLength - 1] == ' ') {
+ --pSession->delimiterLength;
+ }
+ if (pSession->delimiterLength > 4) {
+ return FwdLockConv_Status_OK;
+ }
+ return FwdLockConv_Status_SyntaxError;
+}
+
+/**
+ * Matches the open delimiter.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[in] ch A character.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_MatchOpenDelimiter(FwdLockConv_Session_t *pSession,
+ int ch) {
+ FwdLockConv_Status_t status = FwdLockConv_Status_OK;
+ switch (pSession->scannerState) {
+ case FwdLockConv_ScannerState_WantsFirstDash:
+ if (ch == '-') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsSecondDash;
+ } else if (ch == '\r') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+ } else {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsSecondDash:
+ if (ch == '-') {
+ // The delimiter starts with "\r\n--" (the open delimiter may omit the initial "\r\n").
+ // The rest is the user-defined boundary that should come next.
+ pSession->delimiter[0] = '\r';
+ pSession->delimiter[1] = '\n';
+ pSession->delimiter[2] = '-';
+ pSession->delimiter[3] = '-';
+ pSession->delimiterLength = 4;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsBoundary;
+ } else if (ch == '\r') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+ } else {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsCR:
+ if (ch == '\r') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsLF:
+ if (ch == '\n') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash;
+ } else if (ch != '\r') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsBoundary:
+ if (FwdLockConv_IsBoundaryChar(ch)) {
+ // The boundary may contain leading and internal spaces, so trailing spaces will also be
+ // matched here. These will be removed later.
+ if (pSession->delimiterLength < MAX_DELIMITER_LENGTH) {
+ pSession->delimiter[pSession->delimiterLength++] = ch;
+ } else if (ch != ' ') {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ } else if (ch == '\r') {
+ status = FwdLockConv_RightTrimDelimiter(pSession);
+ if (status == FwdLockConv_Status_OK) {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsBoundaryEnd;
+ }
+ } else if (ch == '\t') {
+ status = FwdLockConv_RightTrimDelimiter(pSession);
+ if (status == FwdLockConv_Status_OK) {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace;
+ }
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsWhitespace:
+ if (ch == '\r') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsBoundaryEnd;
+ } else if (!FwdLockConv_IsWhitespace(ch)) {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsBoundaryEnd:
+ if (ch == '\n') {
+ pSession->parserState = FwdLockConv_ParserState_WantsMimeHeaders;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderNameStart;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ default:
+ status = FwdLockConv_Status_ProgramError;
+ break;
+ }
+ return status;
+}
+
+/**
+ * Checks whether a given character is valid in a MIME header name.
+ *
+ * @param[in] ch The character to check.
+ *
+ * @return A Boolean value indicating whether the given character is valid in a MIME header name.
+ */
+static int FwdLockConv_IsMimeHeaderNameChar(int ch) {
+ return isgraph(ch) && ch != ':';
+}
+
+/**
+ * Checks whether a given character is valid in a MIME header value.
+ *
+ * @param[in] ch The character to check.
+ *
+ * @return A Boolean value indicating whether the given character is valid in a MIME header value.
+ */
+static int FwdLockConv_IsMimeHeaderValueChar(int ch) {
+ return isgraph(ch) && ch != ';';
+}
+
+/**
+ * Appends a character to the specified dynamically growing string.
+ *
+ * @param[in,out] pString A reference to a dynamically growing string.
+ * @param[in] ch The character to append.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_StringAppend(FwdLockConv_String_t *pString, int ch) {
+ if (pString->length == pString->maxLength) {
+ size_t newMaxLength = pString->maxLength + pString->lengthIncrement;
+ char *newPtr = realloc(pString->ptr, newMaxLength + 1);
+ if (newPtr == NULL) {
+ return FwdLockConv_Status_OutOfMemory;
+ }
+ pString->ptr = newPtr;
+ pString->maxLength = newMaxLength;
+ }
+ pString->ptr[pString->length++] = ch;
+ pString->ptr[pString->length] = '\0';
+ return FwdLockConv_Status_OK;
+}
+
+/**
+ * Attempts to recognize the MIME header name and changes the scanner state accordingly.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_RecognizeMimeHeaderName(FwdLockConv_Session_t *pSession) {
+ FwdLockConv_Status_t status = FwdLockConv_Status_OK;
+ if (strncmp(pSession->mimeHeaderName.ptr, strContent, strlenContent) == 0) {
+ if (strcmp(pSession->mimeHeaderName.ptr + strlenContent, strType) == 0) {
+ if (pSession->contentType.ptr == NULL) {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsContentTypeStart;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ } else if (strcmp(pSession->mimeHeaderName.ptr + strlenContent, strTransferEncoding) == 0) {
+ if (pSession->contentTransferEncoding ==
+ FwdLockConv_ContentTransferEncoding_Undefined) {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingStart;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ } else {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+ }
+ } else {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+ }
+ return status;
+}
+
+/**
+ * Applies defaults to missing MIME header values.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_ApplyDefaults(FwdLockConv_Session_t *pSession) {
+ if (pSession->contentType.ptr == NULL) {
+ // Content type is missing: default to "text/plain".
+ pSession->contentType.ptr = malloc(sizeof strTextPlain);
+ if (pSession->contentType.ptr == NULL) {
+ return FwdLockConv_Status_OutOfMemory;
+ }
+ memcpy(pSession->contentType.ptr, strTextPlain, sizeof strTextPlain);
+ pSession->contentType.length = strlenTextPlain;
+ pSession->contentType.maxLength = strlenTextPlain;
+ }
+ if (pSession->contentTransferEncoding == FwdLockConv_ContentTransferEncoding_Undefined) {
+ // Content transfer encoding is missing: default to binary.
+ pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Binary;
+ }
+ return FwdLockConv_Status_OK;
+}
+
+/**
+ * Verifies that the content type is supported.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_VerifyContentType(FwdLockConv_Session_t *pSession) {
+ FwdLockConv_Status_t status;
+ if (pSession->contentType.ptr == NULL) {
+ status = FwdLockConv_Status_ProgramError;
+ } else if (strcmp(pSession->contentType.ptr, strApplicationVndOmaDrmRightsXml) == 0 ||
+ strcmp(pSession->contentType.ptr, strApplicationVndOmaDrmContent) == 0) {
+ status = FwdLockConv_Status_UnsupportedFileFormat;
+ } else {
+ status = FwdLockConv_Status_OK;
+ }
+ return status;
+}
+
+/**
+ * Writes the header of the output file.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[out] pOutput The output from the conversion process.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_WriteHeader(FwdLockConv_Session_t *pSession,
+ FwdLockConv_Output_t *pOutput) {
+ FwdLockConv_Status_t status;
+ if (pSession->contentType.length > UCHAR_MAX) {
+ status = FwdLockConv_Status_SyntaxError;
+ } else {
+ pSession->outputBufferSize = OUTPUT_BUFFER_SIZE_INCREMENT;
+ pOutput->fromConvertData.pBuffer = malloc(pSession->outputBufferSize);
+ if (pOutput->fromConvertData.pBuffer == NULL) {
+ status = FwdLockConv_Status_OutOfMemory;
+ } else {
+ size_t encryptedSessionKeyPos = TOP_HEADER_SIZE + pSession->contentType.length;
+ size_t dataSignaturePos = encryptedSessionKeyPos + pSession->encryptedSessionKeyLength;
+ size_t headerSignaturePos = dataSignaturePos + SHA1_HASH_SIZE;
+ pSession->dataOffset = headerSignaturePos + SHA1_HASH_SIZE;
+ memcpy(pSession->topHeader, topHeaderTemplate, sizeof topHeaderTemplate);
+ pSession->topHeader[CONTENT_TYPE_LENGTH_POS] =
+ (unsigned char)pSession->contentType.length;
+ memcpy(pOutput->fromConvertData.pBuffer, pSession->topHeader, TOP_HEADER_SIZE);
+ memcpy((char *)pOutput->fromConvertData.pBuffer + TOP_HEADER_SIZE,
+ pSession->contentType.ptr, pSession->contentType.length);
+ memcpy((char *)pOutput->fromConvertData.pBuffer + encryptedSessionKeyPos,
+ pSession->pEncryptedSessionKey, pSession->encryptedSessionKeyLength);
+
+ // Set the signatures to all zeros for now; they will have to be updated later.
+ memset((char *)pOutput->fromConvertData.pBuffer + dataSignaturePos, 0,
+ SHA1_HASH_SIZE);
+ memset((char *)pOutput->fromConvertData.pBuffer + headerSignaturePos, 0,
+ SHA1_HASH_SIZE);
+
+ pOutput->fromConvertData.numBytes = pSession->dataOffset;
+ status = FwdLockConv_Status_OK;
+ }
+ }
+ return status;
+}
+
+/**
+ * Matches the MIME headers.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[in] ch A character.
+ * @param[out] pOutput The output from the conversion process.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_MatchMimeHeaders(FwdLockConv_Session_t *pSession,
+ int ch,
+ FwdLockConv_Output_t *pOutput) {
+ FwdLockConv_Status_t status = FwdLockConv_Status_OK;
+ switch (pSession->scannerState) {
+ case FwdLockConv_ScannerState_WantsMimeHeaderNameStart:
+ if (FwdLockConv_IsMimeHeaderNameChar(ch)) {
+ pSession->mimeHeaderName.length = 0;
+ status = FwdLockConv_StringAppend(&pSession->mimeHeaderName, tolower(ch));
+ if (status == FwdLockConv_Status_OK) {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderName;
+ }
+ } else if (ch == '\r') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeadersEnd;
+ } else if (!FwdLockConv_IsWhitespace(ch)) {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsMimeHeaderName:
+ if (FwdLockConv_IsMimeHeaderNameChar(ch)) {
+ status = FwdLockConv_StringAppend(&pSession->mimeHeaderName, tolower(ch));
+ } else if (ch == ':') {
+ status = FwdLockConv_RecognizeMimeHeaderName(pSession);
+ } else if (FwdLockConv_IsWhitespace(ch)) {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderNameEnd;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsMimeHeaderNameEnd:
+ if (ch == ':') {
+ status = FwdLockConv_RecognizeMimeHeaderName(pSession);
+ } else if (!FwdLockConv_IsWhitespace(ch)) {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsContentTypeStart:
+ if (FwdLockConv_IsMimeHeaderValueChar(ch)) {
+ status = FwdLockConv_StringAppend(&pSession->contentType, tolower(ch));
+ if (status == FwdLockConv_Status_OK) {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsContentType;
+ }
+ } else if (!FwdLockConv_IsWhitespace(ch)) {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsContentType:
+ if (FwdLockConv_IsMimeHeaderValueChar(ch)) {
+ status = FwdLockConv_StringAppend(&pSession->contentType, tolower(ch));
+ } else if (ch == ';') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+ } else if (ch == '\r') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+ } else if (FwdLockConv_IsWhitespace(ch)) {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderValueEnd;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsContentTransferEncodingStart:
+ if (ch == 'b' || ch == 'B') {
+ pSession->scannerState = FwdLockConv_ScannerState_Wants_A_OR_I;
+ } else if (ch == '7' || ch == '8') {
+ pSession->scannerState = FwdLockConv_ScannerState_Wants_B;
+ } else if (!FwdLockConv_IsWhitespace(ch)) {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_Wants_A_OR_I:
+ if (ch == 'i' || ch == 'I') {
+ pSession->scannerState = FwdLockConv_ScannerState_Wants_N;
+ } else if (ch == 'a' || ch == 'A') {
+ pSession->scannerState = FwdLockConv_ScannerState_Wants_S;
+ } else {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_Wants_N:
+ if (ch == 'n' || ch == 'N') {
+ pSession->scannerState = FwdLockConv_ScannerState_Wants_A;
+ } else {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_Wants_A:
+ if (ch == 'a' || ch == 'A') {
+ pSession->scannerState = FwdLockConv_ScannerState_Wants_R;
+ } else {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_Wants_R:
+ if (ch == 'r' || ch == 'R') {
+ pSession->scannerState = FwdLockConv_ScannerState_Wants_Y;
+ } else {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_Wants_Y:
+ if (ch == 'y' || ch == 'Y') {
+ pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Binary;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingEnd;
+ } else {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_Wants_S:
+ if (ch == 's' || ch == 'S') {
+ pSession->scannerState = FwdLockConv_ScannerState_Wants_E;
+ } else {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_Wants_E:
+ if (ch == 'e' || ch == 'E') {
+ pSession->scannerState = FwdLockConv_ScannerState_Wants_6;
+ } else {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_Wants_6:
+ if (ch == '6') {
+ pSession->scannerState = FwdLockConv_ScannerState_Wants_4;
+ } else {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_Wants_4:
+ if (ch == '4') {
+ pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Base64;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingEnd;
+ } else {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_Wants_B:
+ if (ch == 'b' || ch == 'B') {
+ pSession->scannerState = FwdLockConv_ScannerState_Wants_I;
+ } else {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_Wants_I:
+ if (ch == 'i' || ch == 'I') {
+ pSession->scannerState = FwdLockConv_ScannerState_Wants_T;
+ } else {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_Wants_T:
+ if (ch == 't' || ch == 'T') {
+ pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Binary;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingEnd;
+ } else {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsContentTransferEncodingEnd:
+ if (ch == ';') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+ } else if (ch == '\r') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+ } else if (FwdLockConv_IsWhitespace(ch)) {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderValueEnd;
+ } else {
+ status = FwdLockConv_Status_UnsupportedContentTransferEncoding;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsMimeHeaderValueEnd:
+ if (ch == ';') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsCR;
+ } else if (ch == '\r') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+ } else if (!FwdLockConv_IsWhitespace(ch)) {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsCR:
+ if (ch == '\r') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsLF:
+ if (ch == '\n') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderNameStart;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsMimeHeadersEnd:
+ if (ch == '\n') {
+ status = FwdLockConv_ApplyDefaults(pSession);
+ if (status == FwdLockConv_Status_OK) {
+ status = FwdLockConv_VerifyContentType(pSession);
+ }
+ if (status == FwdLockConv_Status_OK) {
+ status = FwdLockConv_WriteHeader(pSession, pOutput);
+ }
+ if (status == FwdLockConv_Status_OK) {
+ if (pSession->contentTransferEncoding ==
+ FwdLockConv_ContentTransferEncoding_Binary) {
+ pSession->parserState = FwdLockConv_ParserState_WantsBinaryEncodedData;
+ } else {
+ pSession->parserState = FwdLockConv_ParserState_WantsBase64EncodedData;
+ }
+ pSession->scannerState = FwdLockConv_ScannerState_WantsByte1;
+ }
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ default:
+ status = FwdLockConv_Status_ProgramError;
+ break;
+ }
+ return status;
+}
+
+/**
+ * Increments the counter, treated as a 16-byte little-endian number, by one.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ */
+static void FwdLockConv_IncrementCounter(FwdLockConv_Session_t *pSession) {
+ size_t i = 0;
+ while ((++pSession->counter[i] == 0) && (++i < AES_BLOCK_SIZE))
+ ;
+}
+
+/**
+ * Encrypts the given character and writes it to the output buffer.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[in] ch The character to encrypt and write.
+ * @param[in,out] pOutput The output from the conversion process.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_WriteEncryptedChar(FwdLockConv_Session_t *pSession,
+ unsigned char ch,
+ FwdLockConv_Output_t *pOutput) {
+ if (pOutput->fromConvertData.numBytes == pSession->outputBufferSize) {
+ void *pBuffer;
+ pSession->outputBufferSize += OUTPUT_BUFFER_SIZE_INCREMENT;
+ pBuffer = realloc(pOutput->fromConvertData.pBuffer, pSession->outputBufferSize);
+ if (pBuffer == NULL) {
+ return FwdLockConv_Status_OutOfMemory;
+ }
+ pOutput->fromConvertData.pBuffer = pBuffer;
+ }
+ if (++pSession->keyStreamIndex == AES_BLOCK_SIZE) {
+ FwdLockConv_IncrementCounter(pSession);
+ pSession->keyStreamIndex = 0;
+ }
+ if (pSession->keyStreamIndex == 0) {
+ AES_encrypt(pSession->counter, pSession->keyStream, &pSession->encryptionRoundKeys);
+ }
+ ch ^= pSession->keyStream[pSession->keyStreamIndex];
+ ((unsigned char *)pOutput->fromConvertData.pBuffer)[pOutput->fromConvertData.numBytes++] = ch;
+ ++pSession->numDataBytes;
+ return FwdLockConv_Status_OK;
+}
+
+/**
+ * Matches binary-encoded content data and encrypts it, while looking out for the close delimiter.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[in] ch A character.
+ * @param[in,out] pOutput The output from the conversion process.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_MatchBinaryEncodedData(FwdLockConv_Session_t *pSession,
+ int ch,
+ FwdLockConv_Output_t *pOutput) {
+ FwdLockConv_Status_t status = FwdLockConv_Status_OK;
+ switch (pSession->scannerState) {
+ case FwdLockConv_ScannerState_WantsByte1:
+ if (ch != pSession->delimiter[pSession->delimiterMatchPos]) {
+ // The partial match of the delimiter turned out to be spurious. Flush the matched bytes
+ // to the output buffer and start over.
+ size_t i;
+ for (i = 0; i < pSession->delimiterMatchPos; ++i) {
+ status = FwdLockConv_WriteEncryptedChar(pSession, pSession->delimiter[i], pOutput);
+ if (status != FwdLockConv_Status_OK) {
+ return status;
+ }
+ }
+ pSession->delimiterMatchPos = 0;
+ }
+ if (ch != pSession->delimiter[pSession->delimiterMatchPos]) {
+ // The current character isn't part of the delimiter. Write it to the output buffer.
+ status = FwdLockConv_WriteEncryptedChar(pSession, ch, pOutput);
+ } else if (++pSession->delimiterMatchPos == pSession->delimiterLength) {
+ // The entire delimiter has been matched. The only valid characters now are the "--"
+ // that complete the close delimiter (no more message parts are expected).
+ pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsFirstDash:
+ if (ch == '-') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsSecondDash;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsSecondDash:
+ if (ch == '-') {
+ pSession->parserState = FwdLockConv_ParserState_Done;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ default:
+ status = FwdLockConv_Status_ProgramError;
+ break;
+ }
+ return status;
+}
+
+/**
+ * Checks whether a given character is valid in base64-encoded data.
+ *
+ * @param[in] ch The character to check.
+ *
+ * @return A Boolean value indicating whether the given character is valid in base64-encoded data.
+ */
+static int FwdLockConv_IsBase64Char(int ch) {
+ return 0 <= ch && ch <= 'z' && base64Values[ch] >= 0;
+}
+
+/**
+ * Matches base64-encoded content data and encrypts it, while looking out for the close delimiter.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[in] ch A character.
+ * @param[in,out] pOutput The output from the conversion process.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_MatchBase64EncodedData(FwdLockConv_Session_t *pSession,
+ int ch,
+ FwdLockConv_Output_t *pOutput) {
+ FwdLockConv_Status_t status = FwdLockConv_Status_OK;
+ switch (pSession->scannerState) {
+ case FwdLockConv_ScannerState_WantsByte1:
+ case FwdLockConv_ScannerState_WantsByte1_AfterCRLF:
+ if (FwdLockConv_IsBase64Char(ch)) {
+ pSession->ch = base64Values[ch] << 2;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsByte2;
+ } else if (ch == '\r') {
+ pSession->savedScannerState = FwdLockConv_ScannerState_WantsByte1_AfterCRLF;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+ } else if (ch == '-') {
+ if (pSession->scannerState == FwdLockConv_ScannerState_WantsByte1_AfterCRLF) {
+ pSession->delimiterMatchPos = 3;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsDelimiter;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ } else if (!FwdLockConv_IsWhitespace(ch)) {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsByte2:
+ if (FwdLockConv_IsBase64Char(ch)) {
+ pSession->ch |= base64Values[ch] >> 4;
+ status = FwdLockConv_WriteEncryptedChar(pSession, pSession->ch, pOutput);
+ if (status == FwdLockConv_Status_OK) {
+ pSession->ch = base64Values[ch] << 4;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsByte3;
+ }
+ } else if (ch == '\r') {
+ pSession->savedScannerState = pSession->scannerState;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+ } else if (!FwdLockConv_IsWhitespace(ch)) {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsByte3:
+ if (FwdLockConv_IsBase64Char(ch)) {
+ pSession->ch |= base64Values[ch] >> 2;
+ status = FwdLockConv_WriteEncryptedChar(pSession, pSession->ch, pOutput);
+ if (status == FwdLockConv_Status_OK) {
+ pSession->ch = base64Values[ch] << 6;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsByte4;
+ }
+ } else if (ch == '\r') {
+ pSession->savedScannerState = pSession->scannerState;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+ } else if (ch == '=') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsPadding;
+ } else if (!FwdLockConv_IsWhitespace(ch)) {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsByte4:
+ if (FwdLockConv_IsBase64Char(ch)) {
+ pSession->ch |= base64Values[ch];
+ status = FwdLockConv_WriteEncryptedChar(pSession, pSession->ch, pOutput);
+ if (status == FwdLockConv_Status_OK) {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsByte1;
+ }
+ } else if (ch == '\r') {
+ pSession->savedScannerState = pSession->scannerState;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+ } else if (ch == '=') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace;
+ } else if (!FwdLockConv_IsWhitespace(ch)) {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsLF:
+ if (ch == '\n') {
+ pSession->scannerState = pSession->savedScannerState;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsPadding:
+ if (ch == '=') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsWhitespace:
+ case FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF:
+ if (ch == '\r') {
+ pSession->savedScannerState = FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsLF;
+ } else if (ch == '-') {
+ if (pSession->scannerState == FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF) {
+ pSession->delimiterMatchPos = 3;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsDelimiter;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ } else if (FwdLockConv_IsWhitespace(ch)) {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsDelimiter:
+ if (ch != pSession->delimiter[pSession->delimiterMatchPos]) {
+ status = FwdLockConv_Status_SyntaxError;
+ } else if (++pSession->delimiterMatchPos == pSession->delimiterLength) {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsFirstDash:
+ if (ch == '-') {
+ pSession->scannerState = FwdLockConv_ScannerState_WantsSecondDash;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ case FwdLockConv_ScannerState_WantsSecondDash:
+ if (ch == '-') {
+ pSession->parserState = FwdLockConv_ParserState_Done;
+ } else {
+ status = FwdLockConv_Status_SyntaxError;
+ }
+ break;
+ default:
+ status = FwdLockConv_Status_ProgramError;
+ break;
+ }
+ return status;
+}
+
+/**
+ * Pushes a single character into the converter's state machine.
+ *
+ * @param[in,out] pSession A reference to a converter session.
+ * @param[in] ch A character.
+ * @param[in,out] pOutput The output from the conversion process.
+ *
+ * @return A status code.
+ */
+static FwdLockConv_Status_t FwdLockConv_PushChar(FwdLockConv_Session_t *pSession,
+ int ch,
+ FwdLockConv_Output_t *pOutput) {
+ FwdLockConv_Status_t status;
+ ++pSession->numCharsConsumed;
+ switch (pSession->parserState) {
+ case FwdLockConv_ParserState_WantsOpenDelimiter:
+ status = FwdLockConv_MatchOpenDelimiter(pSession, ch);
+ break;
+ case FwdLockConv_ParserState_WantsMimeHeaders:
+ status = FwdLockConv_MatchMimeHeaders(pSession, ch, pOutput);
+ break;
+ case FwdLockConv_ParserState_WantsBinaryEncodedData:
+ status = FwdLockConv_MatchBinaryEncodedData(pSession, ch, pOutput);
+ break;
+ case FwdLockConv_ParserState_WantsBase64EncodedData:
+ if (ch == '\n' && pSession->scannerState != FwdLockConv_ScannerState_WantsLF) {
+ // Repair base64-encoded data that doesn't have carriage returns in its line breaks.
+ status = FwdLockConv_MatchBase64EncodedData(pSession, '\r', pOutput);
+ if (status != FwdLockConv_Status_OK) {
+ break;
+ }
+ }
+ status = FwdLockConv_MatchBase64EncodedData(pSession, ch, pOutput);
+ break;
+ case FwdLockConv_ParserState_Done:
+ status = FwdLockConv_Status_OK;
+ break;
+ default:
+ status = FwdLockConv_Status_ProgramError;
+ break;
+ }
+ return status;
+}
+
+FwdLockConv_Status_t FwdLockConv_OpenSession(int *pSessionId, FwdLockConv_Output_t *pOutput) {
+ FwdLockConv_Status_t status;
+ if (pSessionId == NULL || pOutput == NULL) {
+ status = FwdLockConv_Status_InvalidArgument;
+ } else {
+ *pSessionId = FwdLockConv_AcquireSession();
+ if (*pSessionId < 0) {
+ status = FwdLockConv_Status_TooManySessions;
+ } else {
+ FwdLockConv_Session_t *pSession = sessionPtrs[*pSessionId];
+ pSession->encryptedSessionKeyLength = FwdLockGlue_GetEncryptedKeyLength(KEY_SIZE);
+ if (pSession->encryptedSessionKeyLength < AES_BLOCK_SIZE) {
+ // The encrypted session key is used as the CTR-mode nonce, so it must be at least
+ // the size of a single AES block.
+ status = FwdLockConv_Status_ProgramError;
+ } else {
+ pSession->pEncryptedSessionKey = malloc(pSession->encryptedSessionKeyLength);
+ if (pSession->pEncryptedSessionKey == NULL) {
+ status = FwdLockConv_Status_OutOfMemory;
+ } else {
+ if (!FwdLockGlue_GetRandomNumber(pSession->sessionKey, KEY_SIZE)) {
+ status = FwdLockConv_Status_RandomNumberGenerationFailed;
+ } else if (!FwdLockGlue_EncryptKey(pSession->sessionKey, KEY_SIZE,
+ pSession->pEncryptedSessionKey,
+ pSession->encryptedSessionKeyLength)) {
+ status = FwdLockConv_Status_KeyEncryptionFailed;
+ } else {
+ status = FwdLockConv_DeriveKeys(pSession);
+ }
+ if (status == FwdLockConv_Status_OK) {
+ memset(pSession->sessionKey, 0, KEY_SIZE); // Zero out key data.
+ memcpy(pSession->counter, pSession->pEncryptedSessionKey, AES_BLOCK_SIZE);
+ pSession->parserState = FwdLockConv_ParserState_WantsOpenDelimiter;
+ pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash;
+ pSession->numCharsConsumed = 0;
+ pSession->delimiterMatchPos = 0;
+ pSession->mimeHeaderName = nullString;
+ pSession->contentType = nullString;
+ pSession->contentTransferEncoding =
+ FwdLockConv_ContentTransferEncoding_Undefined;
+ pSession->keyStreamIndex = -1;
+ pOutput->fromConvertData.pBuffer = NULL;
+ pOutput->fromConvertData.errorPos = INVALID_OFFSET;
+ } else {
+ free(pSession->pEncryptedSessionKey);
+ }
+ }
+ }
+ if (status != FwdLockConv_Status_OK) {
+ FwdLockConv_ReleaseSession(*pSessionId);
+ *pSessionId = -1;
+ }
+ }
+ }
+ return status;
+}
+
+FwdLockConv_Status_t FwdLockConv_ConvertData(int sessionId,
+ const void *pBuffer,
+ size_t numBytes,
+ FwdLockConv_Output_t *pOutput) {
+ FwdLockConv_Status_t status;
+ if (!FwdLockConv_IsValidSession(sessionId) || pBuffer == NULL || pOutput == NULL) {
+ status = FwdLockConv_Status_InvalidArgument;
+ } else {
+ size_t i;
+ FwdLockConv_Session_t *pSession = sessionPtrs[sessionId];
+ pSession->dataOffset = 0;
+ pSession->numDataBytes = 0;
+ pOutput->fromConvertData.numBytes = 0;
+ status = FwdLockConv_Status_OK;
+
+ for (i = 0; i < numBytes; ++i) {
+ status = FwdLockConv_PushChar(pSession, ((char *)pBuffer)[i], pOutput);
+ if (status != FwdLockConv_Status_OK) {
+ break;
+ }
+ }
+ if (status == FwdLockConv_Status_OK) {
+ // Update the data signature.
+ HMAC_Update(&pSession->signingContext,
+ &((unsigned char *)pOutput->fromConvertData.pBuffer)[pSession->dataOffset],
+ pSession->numDataBytes);
+ } else if (status == FwdLockConv_Status_SyntaxError) {
+ pOutput->fromConvertData.errorPos = pSession->numCharsConsumed;
+ }
+ }
+ return status;
+}
+
+FwdLockConv_Status_t FwdLockConv_CloseSession(int sessionId, FwdLockConv_Output_t *pOutput) {
+ FwdLockConv_Status_t status;
+ if (!FwdLockConv_IsValidSession(sessionId) || pOutput == NULL) {
+ status = FwdLockConv_Status_InvalidArgument;
+ } else {
+ FwdLockConv_Session_t *pSession = sessionPtrs[sessionId];
+ free(pOutput->fromConvertData.pBuffer);
+ if (pSession->parserState != FwdLockConv_ParserState_Done) {
+ pOutput->fromCloseSession.errorPos = pSession->numCharsConsumed;
+ status = FwdLockConv_Status_SyntaxError;
+ } else {
+ // Finalize the data signature.
+ unsigned int signatureSize = SHA1_HASH_SIZE;
+ HMAC_Final(&pSession->signingContext, pOutput->fromCloseSession.signatures,
+ &signatureSize);
+ if (signatureSize != SHA1_HASH_SIZE) {
+ status = FwdLockConv_Status_ProgramError;
+ } else {
+ // Calculate the header signature, which is a signature of the rest of the header
+ // including the data signature.
+ HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL);
+ HMAC_Update(&pSession->signingContext, pSession->topHeader, TOP_HEADER_SIZE);
+ HMAC_Update(&pSession->signingContext, (unsigned char *)pSession->contentType.ptr,
+ pSession->contentType.length);
+ HMAC_Update(&pSession->signingContext, pSession->pEncryptedSessionKey,
+ pSession->encryptedSessionKeyLength);
+ HMAC_Update(&pSession->signingContext, pOutput->fromCloseSession.signatures,
+ SHA1_HASH_SIZE);
+ HMAC_Final(&pSession->signingContext,
+ &pOutput->fromCloseSession.signatures[SHA1_HASH_SIZE], &signatureSize);
+ if (signatureSize != SHA1_HASH_SIZE) {
+ status = FwdLockConv_Status_ProgramError;
+ } else {
+ pOutput->fromCloseSession.fileOffset = TOP_HEADER_SIZE +
+ pSession->contentType.length + pSession->encryptedSessionKeyLength;
+ status = FwdLockConv_Status_OK;
+ }
+ }
+ pOutput->fromCloseSession.errorPos = INVALID_OFFSET;
+ }
+ free(pSession->mimeHeaderName.ptr);
+ free(pSession->contentType.ptr);
+ free(pSession->pEncryptedSessionKey);
+ HMAC_CTX_cleanup(&pSession->signingContext);
+ FwdLockConv_ReleaseSession(sessionId);
+ }
+ return status;
+}
+
+FwdLockConv_Status_t FwdLockConv_ConvertOpenFile(int inputFileDesc,
+ FwdLockConv_ReadFunc_t *fpReadFunc,
+ int outputFileDesc,
+ FwdLockConv_WriteFunc_t *fpWriteFunc,
+ FwdLockConv_LSeekFunc_t *fpLSeekFunc,
+ off64_t *pErrorPos) {
+ FwdLockConv_Status_t status;
+ if (pErrorPos != NULL) {
+ *pErrorPos = INVALID_OFFSET;
+ }
+ if (fpReadFunc == NULL || fpWriteFunc == NULL || fpLSeekFunc == NULL || inputFileDesc < 0 ||
+ outputFileDesc < 0) {
+ status = FwdLockConv_Status_InvalidArgument;
+ } else {
+ char *pReadBuffer = malloc(READ_BUFFER_SIZE);
+ if (pReadBuffer == NULL) {
+ status = FwdLockConv_Status_OutOfMemory;
+ } else {
+ int sessionId;
+ FwdLockConv_Output_t output;
+ status = FwdLockConv_OpenSession(&sessionId, &output);
+ if (status == FwdLockConv_Status_OK) {
+ ssize_t numBytesRead;
+ FwdLockConv_Status_t closeStatus;
+ while ((numBytesRead =
+ fpReadFunc(inputFileDesc, pReadBuffer, READ_BUFFER_SIZE)) > 0) {
+ status = FwdLockConv_ConvertData(sessionId, pReadBuffer, (size_t)numBytesRead,
+ &output);
+ if (status == FwdLockConv_Status_OK) {
+ if (output.fromConvertData.pBuffer != NULL &&
+ output.fromConvertData.numBytes > 0) {
+ ssize_t numBytesWritten = fpWriteFunc(outputFileDesc,
+ output.fromConvertData.pBuffer,
+ output.fromConvertData.numBytes);
+ if (numBytesWritten != (ssize_t)output.fromConvertData.numBytes) {
+ status = FwdLockConv_Status_FileWriteError;
+ break;
+ }
+ }
+ } else {
+ if (status == FwdLockConv_Status_SyntaxError && pErrorPos != NULL) {
+ *pErrorPos = output.fromConvertData.errorPos;
+ }
+ break;
+ }
+ } // end while
+ if (numBytesRead < 0) {
+ status = FwdLockConv_Status_FileReadError;
+ }
+ closeStatus = FwdLockConv_CloseSession(sessionId, &output);
+ if (status == FwdLockConv_Status_OK) {
+ if (closeStatus != FwdLockConv_Status_OK) {
+ if (closeStatus == FwdLockConv_Status_SyntaxError && pErrorPos != NULL) {
+ *pErrorPos = output.fromCloseSession.errorPos;
+ }
+ status = closeStatus;
+ } else if (fpLSeekFunc(outputFileDesc, output.fromCloseSession.fileOffset,
+ SEEK_SET) < 0) {
+ status = FwdLockConv_Status_FileSeekError;
+ } else if (fpWriteFunc(outputFileDesc, output.fromCloseSession.signatures,
+ FWD_LOCK_SIGNATURES_SIZE) != FWD_LOCK_SIGNATURES_SIZE) {
+ status = FwdLockConv_Status_FileWriteError;
+ }
+ }
+ }
+ free(pReadBuffer);
+ }
+ }
+ return status;
+}
+
+FwdLockConv_Status_t FwdLockConv_ConvertFile(const char *pInputFilename,
+ const char *pOutputFilename,
+ off64_t *pErrorPos) {
+ FwdLockConv_Status_t status;
+ if (pErrorPos != NULL) {
+ *pErrorPos = INVALID_OFFSET;
+ }
+ if (pInputFilename == NULL || pOutputFilename == NULL) {
+ status = FwdLockConv_Status_InvalidArgument;
+ } else {
+ int inputFileDesc = open(pInputFilename, O_RDONLY);
+ if (inputFileDesc < 0) {
+ status = FwdLockConv_Status_FileNotFound;
+ } else {
+ int outputFileDesc = open(pOutputFilename, O_CREAT | O_TRUNC | O_WRONLY,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (outputFileDesc < 0) {
+ status = FwdLockConv_Status_FileCreationFailed;
+ } else {
+ status = FwdLockConv_ConvertOpenFile(inputFileDesc, read, outputFileDesc, write,
+ lseek64, pErrorPos);
+ if (close(outputFileDesc) == 0 && status != FwdLockConv_Status_OK) {
+ remove(pOutputFilename);
+ }
+ }
+ (void)close(inputFileDesc);
+ }
+ }
+ return status;
+}
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h
new file mode 100644
index 0000000..e20c0c3
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.h
@@ -0,0 +1,282 @@
+/*
+ * 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 __FWDLOCKCONV_H__
+#define __FWDLOCKCONV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+/**
+ * The size of the data and header signatures combined. The signatures are adjacent to each other in
+ * the produced output file.
+ */
+#define FWD_LOCK_SIGNATURES_SIZE (2 * 20)
+
+/**
+ * Data type for the output from FwdLockConv_ConvertData.
+ */
+typedef struct FwdLockConv_ConvertData_Output {
+ /// The converted data.
+ void *pBuffer;
+
+ /// The size of the converted data.
+ size_t numBytes;
+
+ /// The file position where the error occurred, in the case of a syntax error.
+ off64_t errorPos;
+} FwdLockConv_ConvertData_Output_t;
+
+/**
+ * Data type for the output from FwdLockConv_CloseSession.
+ */
+typedef struct FwdLockConv_CloseSession_Output {
+ /// The final set of signatures.
+ unsigned char signatures[FWD_LOCK_SIGNATURES_SIZE];
+
+ /// The offset in the produced output file where the signatures are located.
+ off64_t fileOffset;
+
+ /// The file position where the error occurred, in the case of a syntax error.
+ off64_t errorPos;
+} FwdLockConv_CloseSession_Output_t;
+
+/**
+ * Data type for the output from the conversion process.
+ */
+typedef union FwdLockConv_Output {
+ FwdLockConv_ConvertData_Output_t fromConvertData;
+ FwdLockConv_CloseSession_Output_t fromCloseSession;
+} FwdLockConv_Output_t;
+
+/**
+ * Data type for the Posix-style read function used by the converter in pull mode.
+ *
+ * @param[in] fileDesc The file descriptor of a file opened for reading.
+ * @param[out] pBuffer A reference to the buffer that should receive the read data.
+ * @param[in] numBytes The number of bytes to read.
+ *
+ * @return The number of bytes read.
+ * @retval -1 Failure.
+ */
+typedef ssize_t FwdLockConv_ReadFunc_t(int fileDesc, void *pBuffer, size_t numBytes);
+
+/**
+ * Data type for the Posix-style write function used by the converter in pull mode.
+ *
+ * @param[in] fileDesc The file descriptor of a file opened for writing.
+ * @param[in] pBuffer A reference to the buffer containing the data to be written.
+ * @param[in] numBytes The number of bytes to write.
+ *
+ * @return The number of bytes written.
+ * @retval -1 Failure.
+ */
+typedef ssize_t FwdLockConv_WriteFunc_t(int fileDesc, const void *pBuffer, size_t numBytes);
+
+/**
+ * Data type for the Posix-style lseek function used by the converter in pull mode.
+ *
+ * @param[in] fileDesc The file descriptor of a file opened for writing.
+ * @param[in] offset The offset with which to update the file position.
+ * @param[in] whence One of SEEK_SET, SEEK_CUR, and SEEK_END.
+ *
+ * @return The new file position.
+ * @retval ((off64_t)-1) Failure.
+ */
+typedef off64_t FwdLockConv_LSeekFunc_t(int fileDesc, off64_t offset, int whence);
+
+/**
+ * The status codes returned by the converter functions.
+ */
+typedef enum FwdLockConv_Status {
+ /// The operation was successful.
+ FwdLockConv_Status_OK = 0,
+
+ /// An actual argument to the function is invalid (a program error on the caller's part).
+ FwdLockConv_Status_InvalidArgument = 1,
+
+ /// There is not enough free dynamic memory to complete the operation.
+ FwdLockConv_Status_OutOfMemory = 2,
+
+ /// An error occurred while opening the input file.
+ FwdLockConv_Status_FileNotFound = 3,
+
+ /// An error occurred while creating the output file.
+ FwdLockConv_Status_FileCreationFailed = 4,
+
+ /// An error occurred while reading from the input file.
+ FwdLockConv_Status_FileReadError = 5,
+
+ /// An error occurred while writing to the output file.
+ FwdLockConv_Status_FileWriteError = 6,
+
+ /// An error occurred while seeking to a new file position within the output file.
+ FwdLockConv_Status_FileSeekError = 7,
+
+ /// The input file is not a syntactically correct OMA DRM v1 Forward Lock file.
+ FwdLockConv_Status_SyntaxError = 8,
+
+ /// Support for this DRM file format has been disabled in the current product configuration.
+ FwdLockConv_Status_UnsupportedFileFormat = 9,
+
+ /// The content transfer encoding is not one of "binary", "base64", "7bit", or "8bit"
+ /// (case-insensitive).
+ FwdLockConv_Status_UnsupportedContentTransferEncoding = 10,
+
+ /// The generation of a random number failed.
+ FwdLockConv_Status_RandomNumberGenerationFailed = 11,
+
+ /// Key encryption failed.
+ FwdLockConv_Status_KeyEncryptionFailed = 12,
+
+ /// The calculation of a keyed hash for integrity protection failed.
+ FwdLockConv_Status_IntegrityProtectionFailed = 13,
+
+ /// There are too many ongoing sessions for another one to be opened.
+ FwdLockConv_Status_TooManySessions = 14,
+
+ /// An unexpected error occurred.
+ FwdLockConv_Status_ProgramError = 15
+} FwdLockConv_Status_t;
+
+/**
+ * Opens a session for converting an OMA DRM v1 Forward Lock file to the internal Forward Lock file
+ * format.
+ *
+ * @param[out] pSessionId The session ID.
+ * @param[out] pOutput The output from the conversion process (initialized).
+ *
+ * @return A status code.
+ * @retval FwdLockConv_Status_OK
+ * @retval FwdLockConv_Status_InvalidArgument
+ * @retval FwdLockConv_Status_TooManySessions
+ */
+FwdLockConv_Status_t FwdLockConv_OpenSession(int *pSessionId, FwdLockConv_Output_t *pOutput);
+
+/**
+ * Supplies the converter with data to convert. The caller is expected to write the converted data
+ * to file. Can be called an arbitrary number of times.
+ *
+ * @param[in] sessionId The session ID.
+ * @param[in] pBuffer A reference to a buffer containing the data to convert.
+ * @param[in] numBytes The number of bytes to convert.
+ * @param[in,out] pOutput The output from the conversion process (allocated/reallocated).
+ *
+ * @return A status code.
+ * @retval FwdLockConv_Status_OK
+ * @retval FwdLockConv_Status_InvalidArgument
+ * @retval FwdLockConv_Status_OutOfMemory
+ * @retval FwdLockConv_Status_SyntaxError
+ * @retval FwdLockConv_Status_UnsupportedFileFormat
+ * @retval FwdLockConv_Status_UnsupportedContentTransferEncoding
+ * @retval FwdLockConv_Status_RandomNumberGenerationFailed
+ * @retval FwdLockConv_Status_KeyEncryptionFailed
+ * @retval FwdLockConv_Status_DataEncryptionFailed
+ */
+FwdLockConv_Status_t FwdLockConv_ConvertData(int sessionId,
+ const void *pBuffer,
+ size_t numBytes,
+ FwdLockConv_Output_t *pOutput);
+
+/**
+ * Closes a session for converting an OMA DRM v1 Forward Lock file to the internal Forward Lock
+ * file format. The caller must update the produced output file at the indicated file offset with
+ * the final set of signatures.
+ *
+ * @param[in] sessionId The session ID.
+ * @param[in,out] pOutput The output from the conversion process (deallocated and overwritten).
+ *
+ * @return A status code.
+ * @retval FwdLockConv_Status_OK
+ * @retval FwdLockConv_Status_InvalidArgument
+ * @retval FwdLockConv_Status_OutOfMemory
+ * @retval FwdLockConv_Status_IntegrityProtectionFailed
+ */
+FwdLockConv_Status_t FwdLockConv_CloseSession(int sessionId, FwdLockConv_Output_t *pOutput);
+
+/**
+ * Converts an open OMA DRM v1 Forward Lock file to the internal Forward Lock file format in pull
+ * mode.
+ *
+ * @param[in] inputFileDesc The file descriptor of the open input file.
+ * @param[in] fpReadFunc A reference to a read function that can operate on the open input file.
+ * @param[in] outputFileDesc The file descriptor of the open output file.
+ * @param[in] fpWriteFunc A reference to a write function that can operate on the open output file.
+ * @param[in] fpLSeekFunc A reference to an lseek function that can operate on the open output file.
+ * @param[out] pErrorPos
+ * The file position where the error occurred, in the case of a syntax error. May be NULL.
+ *
+ * @return A status code.
+ * @retval FwdLockConv_Status_OK
+ * @retval FwdLockConv_Status_InvalidArgument
+ * @retval FwdLockConv_Status_OutOfMemory
+ * @retval FwdLockConv_Status_FileReadError
+ * @retval FwdLockConv_Status_FileWriteError
+ * @retval FwdLockConv_Status_FileSeekError
+ * @retval FwdLockConv_Status_SyntaxError
+ * @retval FwdLockConv_Status_UnsupportedFileFormat
+ * @retval FwdLockConv_Status_UnsupportedContentTransferEncoding
+ * @retval FwdLockConv_Status_RandomNumberGenerationFailed
+ * @retval FwdLockConv_Status_KeyEncryptionFailed
+ * @retval FwdLockConv_Status_DataEncryptionFailed
+ * @retval FwdLockConv_Status_IntegrityProtectionFailed
+ * @retval FwdLockConv_Status_TooManySessions
+ */
+FwdLockConv_Status_t FwdLockConv_ConvertOpenFile(int inputFileDesc,
+ FwdLockConv_ReadFunc_t *fpReadFunc,
+ int outputFileDesc,
+ FwdLockConv_WriteFunc_t *fpWriteFunc,
+ FwdLockConv_LSeekFunc_t *fpLSeekFunc,
+ off64_t *pErrorPos);
+
+/**
+ * Converts an OMA DRM v1 Forward Lock file to the internal Forward Lock file format in pull mode.
+ *
+ * @param[in] pInputFilename A reference to the input filename.
+ * @param[in] pOutputFilename A reference to the output filename.
+ * @param[out] pErrorPos
+ * The file position where the error occurred, in the case of a syntax error. May be NULL.
+ *
+ * @return A status code.
+ * @retval FwdLockConv_Status_OK
+ * @retval FwdLockConv_Status_InvalidArgument
+ * @retval FwdLockConv_Status_OutOfMemory
+ * @retval FwdLockConv_Status_FileNotFound
+ * @retval FwdLockConv_Status_FileCreationFailed
+ * @retval FwdLockConv_Status_FileReadError
+ * @retval FwdLockConv_Status_FileWriteError
+ * @retval FwdLockConv_Status_FileSeekError
+ * @retval FwdLockConv_Status_SyntaxError
+ * @retval FwdLockConv_Status_UnsupportedFileFormat
+ * @retval FwdLockConv_Status_UnsupportedContentTransferEncoding
+ * @retval FwdLockConv_Status_RandomNumberGenerationFailed
+ * @retval FwdLockConv_Status_KeyEncryptionFailed
+ * @retval FwdLockConv_Status_DataEncryptionFailed
+ * @retval FwdLockConv_Status_IntegrityProtectionFailed
+ * @retval FwdLockConv_Status_TooManySessions
+ */
+FwdLockConv_Status_t FwdLockConv_ConvertFile(const char *pInputFilename,
+ const char *pOutputFilename,
+ off64_t *pErrorPos);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __FWDLOCKCONV_H__
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk
new file mode 100644
index 0000000..b625edf
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/Android.mk
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ FwdLockFile.c
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/drm/libdrmframework/plugins/forward-lock/internal-format/common \
+ external/openssl/include
+
+LOCAL_SHARED_LIBRARIES := libcrypto
+
+LOCAL_WHOLE_STATIC_LIBRARIES := libfwdlock-common
+
+LOCAL_STATIC_LIBRARIES := libfwdlock-common
+
+LOCAL_MODULE := libfwdlock-decoder
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c
new file mode 100644
index 0000000..365bdec
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.c
@@ -0,0 +1,454 @@
+/*
+ * 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 <utils/Log.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <openssl/aes.h>
+#include <openssl/hmac.h>
+
+#include "FwdLockFile.h"
+#include "FwdLockGlue.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define INVALID_OFFSET ((off64_t)-1)
+
+#define INVALID_BLOCK_INDEX ((uint64_t)-1)
+
+#define MAX_NUM_SESSIONS 128
+
+#define KEY_SIZE AES_BLOCK_SIZE
+#define KEY_SIZE_IN_BITS (KEY_SIZE * 8)
+
+#define SHA1_HASH_SIZE 20
+#define SHA1_BLOCK_SIZE 64
+
+#define FWD_LOCK_VERSION 0
+#define FWD_LOCK_SUBFORMAT 0
+#define USAGE_RESTRICTION_FLAGS 0
+#define CONTENT_TYPE_LENGTH_POS 7
+#define TOP_HEADER_SIZE 8
+
+#define SIG_CALC_BUFFER_SIZE (16 * SHA1_BLOCK_SIZE)
+
+/**
+ * Data type for the per-file state information needed by the decoder.
+ */
+typedef struct FwdLockFile_Session {
+ int fileDesc;
+ unsigned char topHeader[TOP_HEADER_SIZE];
+ char *pContentType;
+ size_t contentTypeLength;
+ void *pEncryptedSessionKey;
+ size_t encryptedSessionKeyLength;
+ unsigned char dataSignature[SHA1_HASH_SIZE];
+ unsigned char headerSignature[SHA1_HASH_SIZE];
+ off64_t dataOffset;
+ off64_t filePos;
+ AES_KEY encryptionRoundKeys;
+ HMAC_CTX signingContext;
+ unsigned char keyStream[AES_BLOCK_SIZE];
+ uint64_t blockIndex;
+} FwdLockFile_Session_t;
+
+static FwdLockFile_Session_t *sessionPtrs[MAX_NUM_SESSIONS] = { NULL };
+
+static pthread_mutex_t sessionAcquisitionMutex = PTHREAD_MUTEX_INITIALIZER;
+
+static const unsigned char topHeaderTemplate[] =
+ { 'F', 'W', 'L', 'K', FWD_LOCK_VERSION, FWD_LOCK_SUBFORMAT, USAGE_RESTRICTION_FLAGS };
+
+/**
+ * Acquires an unused file session for the given file descriptor.
+ *
+ * @param[in] fileDesc A file descriptor.
+ *
+ * @return A session ID.
+ */
+static int FwdLockFile_AcquireSession(int fileDesc) {
+ int sessionId = -1;
+ if (fileDesc < 0) {
+ errno = EBADF;
+ } else {
+ int i;
+ pthread_mutex_lock(&sessionAcquisitionMutex);
+ for (i = 0; i < MAX_NUM_SESSIONS; ++i) {
+ int candidateSessionId = (fileDesc + i) % MAX_NUM_SESSIONS;
+ if (sessionPtrs[candidateSessionId] == NULL) {
+ sessionPtrs[candidateSessionId] = malloc(sizeof **sessionPtrs);
+ if (sessionPtrs[candidateSessionId] != NULL) {
+ sessionPtrs[candidateSessionId]->fileDesc = fileDesc;
+ sessionPtrs[candidateSessionId]->pContentType = NULL;
+ sessionPtrs[candidateSessionId]->pEncryptedSessionKey = NULL;
+ sessionId = candidateSessionId;
+ }
+ break;
+ }
+ }
+ pthread_mutex_unlock(&sessionAcquisitionMutex);
+ if (i == MAX_NUM_SESSIONS) {
+ ALOGE("Too many sessions opened at the same time");
+ errno = ENFILE;
+ }
+ }
+ return sessionId;
+}
+
+/**
+ * Finds the file session associated with the given file descriptor.
+ *
+ * @param[in] fileDesc A file descriptor.
+ *
+ * @return A session ID.
+ */
+static int FwdLockFile_FindSession(int fileDesc) {
+ int sessionId = -1;
+ if (fileDesc < 0) {
+ errno = EBADF;
+ } else {
+ int i;
+ pthread_mutex_lock(&sessionAcquisitionMutex);
+ for (i = 0; i < MAX_NUM_SESSIONS; ++i) {
+ int candidateSessionId = (fileDesc + i) % MAX_NUM_SESSIONS;
+ if (sessionPtrs[candidateSessionId] != NULL &&
+ sessionPtrs[candidateSessionId]->fileDesc == fileDesc) {
+ sessionId = candidateSessionId;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&sessionAcquisitionMutex);
+ if (i == MAX_NUM_SESSIONS) {
+ errno = EBADF;
+ }
+ }
+ return sessionId;
+}
+
+/**
+ * Releases a file session.
+ *
+ * @param[in] sessionID A session ID.
+ */
+static void FwdLockFile_ReleaseSession(int sessionId) {
+ pthread_mutex_lock(&sessionAcquisitionMutex);
+ assert(0 <= sessionId && sessionId < MAX_NUM_SESSIONS && sessionPtrs[sessionId] != NULL);
+ free(sessionPtrs[sessionId]->pContentType);
+ free(sessionPtrs[sessionId]->pEncryptedSessionKey);
+ memset(sessionPtrs[sessionId], 0, sizeof *sessionPtrs[sessionId]); // Zero out key data.
+ free(sessionPtrs[sessionId]);
+ sessionPtrs[sessionId] = NULL;
+ pthread_mutex_unlock(&sessionAcquisitionMutex);
+}
+
+/**
+ * Derives keys for encryption and signing from the encrypted session key.
+ *
+ * @param[in,out] pSession A reference to a file session.
+ *
+ * @return A Boolean value indicating whether key derivation was successful.
+ */
+static int FwdLockFile_DeriveKeys(FwdLockFile_Session_t * pSession) {
+ int result;
+ struct FwdLockFile_DeriveKeys_Data {
+ AES_KEY sessionRoundKeys;
+ unsigned char value[KEY_SIZE];
+ unsigned char key[KEY_SIZE];
+ } *pData = malloc(sizeof *pData);
+ if (pData == NULL) {
+ result = FALSE;
+ } else {
+ result = FwdLockGlue_DecryptKey(pSession->pEncryptedSessionKey,
+ pSession->encryptedSessionKeyLength, pData->key, KEY_SIZE);
+ if (result) {
+ if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS, &pData->sessionRoundKeys) != 0) {
+ result = FALSE;
+ } else {
+ // Encrypt the 16-byte value {0, 0, ..., 0} to produce the encryption key.
+ memset(pData->value, 0, KEY_SIZE);
+ AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys);
+ if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS,
+ &pSession->encryptionRoundKeys) != 0) {
+ result = FALSE;
+ } else {
+ // Encrypt the 16-byte value {1, 0, ..., 0} to produce the signing key.
+ ++pData->value[0];
+ AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys);
+ HMAC_CTX_init(&pSession->signingContext);
+ HMAC_Init_ex(&pSession->signingContext, pData->key, KEY_SIZE, EVP_sha1(), NULL);
+ }
+ }
+ }
+ if (!result) {
+ errno = ENOSYS;
+ }
+ memset(pData, 0, sizeof pData); // Zero out key data.
+ free(pData);
+ }
+ return result;
+}
+
+/**
+ * Calculates the counter, treated as a 16-byte little-endian number, used to generate the keystream
+ * for the given block.
+ *
+ * @param[in] pNonce A reference to the nonce.
+ * @param[in] blockIndex The index number of the block.
+ * @param[out] pCounter A reference to the counter.
+ */
+static void FwdLockFile_CalculateCounter(const unsigned char *pNonce,
+ uint64_t blockIndex,
+ unsigned char *pCounter) {
+ unsigned char carry = 0;
+ size_t i = 0;
+ for (; i < sizeof blockIndex; ++i) {
+ unsigned char part = pNonce[i] + (unsigned char)(blockIndex >> (i * CHAR_BIT));
+ pCounter[i] = part + carry;
+ carry = (part < pNonce[i] || pCounter[i] < part) ? 1 : 0;
+ }
+ for (; i < AES_BLOCK_SIZE; ++i) {
+ pCounter[i] = pNonce[i] + carry;
+ carry = (pCounter[i] < pNonce[i]) ? 1 : 0;
+ }
+}
+
+/**
+ * Decrypts the byte at the current file position using AES-128-CTR. In CTR (or "counter") mode,
+ * encryption and decryption are performed using the same algorithm.
+ *
+ * @param[in,out] pSession A reference to a file session.
+ * @param[in] pByte The byte to decrypt.
+ */
+void FwdLockFile_DecryptByte(FwdLockFile_Session_t * pSession, unsigned char *pByte) {
+ uint64_t blockIndex = pSession->filePos / AES_BLOCK_SIZE;
+ uint64_t blockOffset = pSession->filePos % AES_BLOCK_SIZE;
+ if (blockIndex != pSession->blockIndex) {
+ // The first 16 bytes of the encrypted session key is used as the nonce.
+ unsigned char counter[AES_BLOCK_SIZE];
+ FwdLockFile_CalculateCounter(pSession->pEncryptedSessionKey, blockIndex, counter);
+ AES_encrypt(counter, pSession->keyStream, &pSession->encryptionRoundKeys);
+ pSession->blockIndex = blockIndex;
+ }
+ *pByte ^= pSession->keyStream[blockOffset];
+}
+
+int FwdLockFile_attach(int fileDesc) {
+ int sessionId = FwdLockFile_AcquireSession(fileDesc);
+ if (sessionId >= 0) {
+ FwdLockFile_Session_t *pSession = sessionPtrs[sessionId];
+ int isSuccess = FALSE;
+ if (read(fileDesc, pSession->topHeader, TOP_HEADER_SIZE) == TOP_HEADER_SIZE &&
+ memcmp(pSession->topHeader, topHeaderTemplate, sizeof topHeaderTemplate) == 0) {
+ pSession->contentTypeLength = pSession->topHeader[CONTENT_TYPE_LENGTH_POS];
+ assert(pSession->contentTypeLength <= UCHAR_MAX); // Untaint scalar for code checkers.
+ pSession->pContentType = malloc(pSession->contentTypeLength + 1);
+ if (pSession->pContentType != NULL &&
+ read(fileDesc, pSession->pContentType, pSession->contentTypeLength) ==
+ (ssize_t)pSession->contentTypeLength) {
+ pSession->pContentType[pSession->contentTypeLength] = '\0';
+ pSession->encryptedSessionKeyLength = FwdLockGlue_GetEncryptedKeyLength(KEY_SIZE);
+ pSession->pEncryptedSessionKey = malloc(pSession->encryptedSessionKeyLength);
+ if (pSession->pEncryptedSessionKey != NULL &&
+ read(fileDesc, pSession->pEncryptedSessionKey,
+ pSession->encryptedSessionKeyLength) ==
+ (ssize_t)pSession->encryptedSessionKeyLength &&
+ read(fileDesc, pSession->dataSignature, SHA1_HASH_SIZE) ==
+ SHA1_HASH_SIZE &&
+ read(fileDesc, pSession->headerSignature, SHA1_HASH_SIZE) ==
+ SHA1_HASH_SIZE) {
+ isSuccess = FwdLockFile_DeriveKeys(pSession);
+ }
+ }
+ }
+ if (isSuccess) {
+ pSession->dataOffset = pSession->contentTypeLength +
+ pSession->encryptedSessionKeyLength + TOP_HEADER_SIZE + 2 * SHA1_HASH_SIZE;
+ pSession->filePos = 0;
+ pSession->blockIndex = INVALID_BLOCK_INDEX;
+ } else {
+ FwdLockFile_ReleaseSession(sessionId);
+ sessionId = -1;
+ }
+ }
+ return (sessionId >= 0) ? 0 : -1;
+}
+
+int FwdLockFile_open(const char *pFilename) {
+ int fileDesc = open(pFilename, O_RDONLY);
+ if (fileDesc < 0) {
+ ALOGE("failed to open file '%s': %s", pFilename, strerror(errno));
+ return fileDesc;
+ }
+
+ if (FwdLockFile_attach(fileDesc) < 0) {
+ (void)close(fileDesc);
+ fileDesc = -1;
+ }
+ return fileDesc;
+}
+
+ssize_t FwdLockFile_read(int fileDesc, void *pBuffer, size_t numBytes) {
+ ssize_t numBytesRead;
+ int sessionId = FwdLockFile_FindSession(fileDesc);
+ if (sessionId < 0) {
+ numBytesRead = -1;
+ } else {
+ FwdLockFile_Session_t *pSession = sessionPtrs[sessionId];
+ ssize_t i;
+ numBytesRead = read(pSession->fileDesc, pBuffer, numBytes);
+ for (i = 0; i < numBytesRead; ++i) {
+ FwdLockFile_DecryptByte(pSession, &((unsigned char *)pBuffer)[i]);
+ ++pSession->filePos;
+ }
+ }
+ return numBytesRead;
+}
+
+off64_t FwdLockFile_lseek(int fileDesc, off64_t offset, int whence) {
+ off64_t newFilePos;
+ int sessionId = FwdLockFile_FindSession(fileDesc);
+ if (sessionId < 0) {
+ newFilePos = INVALID_OFFSET;
+ } else {
+ FwdLockFile_Session_t *pSession = sessionPtrs[sessionId];
+ switch (whence) {
+ case SEEK_SET:
+ newFilePos = lseek64(pSession->fileDesc, pSession->dataOffset + offset, whence);
+ break;
+ case SEEK_CUR:
+ case SEEK_END:
+ newFilePos = lseek64(pSession->fileDesc, offset, whence);
+ break;
+ default:
+ errno = EINVAL;
+ newFilePos = INVALID_OFFSET;
+ break;
+ }
+ if (newFilePos != INVALID_OFFSET) {
+ if (newFilePos < pSession->dataOffset) {
+ // The new file position is illegal for an internal Forward Lock file. Restore the
+ // original file position.
+ (void)lseek64(pSession->fileDesc, pSession->dataOffset + pSession->filePos,
+ SEEK_SET);
+ errno = EINVAL;
+ newFilePos = INVALID_OFFSET;
+ } else {
+ // The return value should be the file position that lseek64() would have returned
+ // for the embedded content file.
+ pSession->filePos = newFilePos - pSession->dataOffset;
+ newFilePos = pSession->filePos;
+ }
+ }
+ }
+ return newFilePos;
+}
+
+int FwdLockFile_detach(int fileDesc) {
+ int sessionId = FwdLockFile_FindSession(fileDesc);
+ if (sessionId < 0) {
+ return -1;
+ }
+ HMAC_CTX_cleanup(&sessionPtrs[sessionId]->signingContext);
+ FwdLockFile_ReleaseSession(sessionId);
+ return 0;
+}
+
+int FwdLockFile_close(int fileDesc) {
+ return (FwdLockFile_detach(fileDesc) == 0) ? close(fileDesc) : -1;
+}
+
+int FwdLockFile_CheckDataIntegrity(int fileDesc) {
+ int result;
+ int sessionId = FwdLockFile_FindSession(fileDesc);
+ if (sessionId < 0) {
+ result = FALSE;
+ } else {
+ struct FwdLockFile_CheckDataIntegrity_Data {
+ unsigned char signature[SHA1_HASH_SIZE];
+ unsigned char buffer[SIG_CALC_BUFFER_SIZE];
+ } *pData = malloc(sizeof *pData);
+ if (pData == NULL) {
+ result = FALSE;
+ } else {
+ FwdLockFile_Session_t *pSession = sessionPtrs[sessionId];
+ if (lseek64(pSession->fileDesc, pSession->dataOffset, SEEK_SET) !=
+ pSession->dataOffset) {
+ result = FALSE;
+ } else {
+ ssize_t numBytesRead;
+ unsigned int signatureSize = SHA1_HASH_SIZE;
+ while ((numBytesRead =
+ read(pSession->fileDesc, pData->buffer, SIG_CALC_BUFFER_SIZE)) > 0) {
+ HMAC_Update(&pSession->signingContext, pData->buffer, (size_t)numBytesRead);
+ }
+ if (numBytesRead < 0) {
+ result = FALSE;
+ } else {
+ HMAC_Final(&pSession->signingContext, pData->signature, &signatureSize);
+ assert(signatureSize == SHA1_HASH_SIZE);
+ result = memcmp(pData->signature, pSession->dataSignature, SHA1_HASH_SIZE) == 0;
+ }
+ HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL);
+ (void)lseek64(pSession->fileDesc, pSession->dataOffset + pSession->filePos,
+ SEEK_SET);
+ }
+ free(pData);
+ }
+ }
+ return result;
+}
+
+int FwdLockFile_CheckHeaderIntegrity(int fileDesc) {
+ int result;
+ int sessionId = FwdLockFile_FindSession(fileDesc);
+ if (sessionId < 0) {
+ result = FALSE;
+ } else {
+ FwdLockFile_Session_t *pSession = sessionPtrs[sessionId];
+ unsigned char signature[SHA1_HASH_SIZE];
+ unsigned int signatureSize = SHA1_HASH_SIZE;
+ HMAC_Update(&pSession->signingContext, pSession->topHeader, TOP_HEADER_SIZE);
+ HMAC_Update(&pSession->signingContext, (unsigned char *)pSession->pContentType,
+ pSession->contentTypeLength);
+ HMAC_Update(&pSession->signingContext, pSession->pEncryptedSessionKey,
+ pSession->encryptedSessionKeyLength);
+ HMAC_Update(&pSession->signingContext, pSession->dataSignature, SHA1_HASH_SIZE);
+ HMAC_Final(&pSession->signingContext, signature, &signatureSize);
+ assert(signatureSize == SHA1_HASH_SIZE);
+ result = memcmp(signature, pSession->headerSignature, SHA1_HASH_SIZE) == 0;
+ HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL);
+ }
+ return result;
+}
+
+int FwdLockFile_CheckIntegrity(int fileDesc) {
+ return FwdLockFile_CheckHeaderIntegrity(fileDesc) && FwdLockFile_CheckDataIntegrity(fileDesc);
+}
+
+const char *FwdLockFile_GetContentType(int fileDesc) {
+ int sessionId = FwdLockFile_FindSession(fileDesc);
+ if (sessionId < 0) {
+ return NULL;
+ }
+ return sessionPtrs[sessionId]->pContentType;
+}
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.h b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.h
new file mode 100644
index 0000000..fc64050
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/decoder/FwdLockFile.h
@@ -0,0 +1,135 @@
+/*
+ * 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 __FWDLOCKFILE_H__
+#define __FWDLOCKFILE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+/**
+ * Attaches to an open Forward Lock file. The file position is assumed to be at the beginning of the
+ * file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return A status code.
+ * @retval 0 Success.
+ * @retval -1 Failure.
+ */
+int FwdLockFile_attach(int fileDesc);
+
+/**
+ * Opens a Forward Lock file for reading.
+ *
+ * @param[in] pFilename A reference to a filename.
+ *
+ * @return A file descriptor.
+ * @retval -1 Failure.
+ */
+int FwdLockFile_open(const char *pFilename);
+
+/**
+ * Reads the specified number of bytes from an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ * @param[out] pBuffer A reference to the buffer that should receive the read data.
+ * @param[in] numBytes The number of bytes to read.
+ *
+ * @return The number of bytes read.
+ * @retval -1 Failure.
+ */
+ssize_t FwdLockFile_read(int fileDesc, void *pBuffer, size_t numBytes);
+
+/**
+ * Updates the file position within an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ * @param[in] offset The offset with which to update the file position.
+ * @param[in] whence One of SEEK_SET, SEEK_CUR, and SEEK_END.
+ *
+ * @return The new file position.
+ * @retval ((off64_t)-1) Failure.
+ */
+off64_t FwdLockFile_lseek(int fileDesc, off64_t offset, int whence);
+
+/**
+ * Detaches from an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return A status code.
+ * @retval 0 Success.
+ * @retval -1 Failure.
+ */
+int FwdLockFile_detach(int fileDesc);
+
+/**
+ * Closes an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return A status code.
+ * @retval 0 Success.
+ * @retval -1 Failure.
+ */
+int FwdLockFile_close(int fileDesc);
+
+/**
+ * Checks the data integrity of an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return A Boolean value indicating whether the integrity check was successful.
+ */
+int FwdLockFile_CheckDataIntegrity(int fileDesc);
+
+/**
+ * Checks the header integrity of an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return A Boolean value indicating whether the integrity check was successful.
+ */
+int FwdLockFile_CheckHeaderIntegrity(int fileDesc);
+
+/**
+ * Checks both the data and header integrity of an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return A Boolean value indicating whether the integrity check was successful.
+ */
+int FwdLockFile_CheckIntegrity(int fileDesc);
+
+/**
+ * Returns the content type of an open Forward Lock file.
+ *
+ * @param[in] fileDesc The file descriptor of an open Forward Lock file.
+ *
+ * @return
+ * A reference to the content type. The reference remains valid as long as the file is kept open.
+ */
+const char *FwdLockFile_GetContentType(int fileDesc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __FWDLOCKFILE_H__
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/FwdLock.html b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/FwdLock.html
new file mode 100755
index 0000000..8f95cd2
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/FwdLock.html
@@ -0,0 +1,1039 @@
+<html>
+
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
+<meta name=Generator content="Microsoft Word 12 (filtered)">
+<title>Forward Lock Converter and Decoder</title>
+<style>
+<!--
+ /* Font Definitions */
+ @font-face
+ {font-family:SimSun;
+ panose-1:2 1 6 0 3 1 1 1 1 1;}
+@font-face
+ {font-family:"Cambria Math";
+ panose-1:2 4 5 3 5 4 6 3 2 4;}
+@font-face
+ {font-family:Tahoma;
+ panose-1:2 11 6 4 3 5 4 4 2 4;}
+@font-face
+ {font-family:"Lucida Console","DejaVu Sans Mono";
+ panose-1:2 11 6 9 4 5 4 2 2 4;}
+@font-face
+ {font-family:"\@SimSun";
+ panose-1:2 1 6 0 3 1 1 1 1 1;}
+ /* Style Definitions */
+ p.MsoNormal, li.MsoNormal, div.MsoNormal
+ {margin:0cm;
+ margin-bottom:.0001pt;
+ font-size:12.0pt;
+ font-family:"Times New Roman","serif";}
+h1
+ {margin-right:0cm;
+ margin-left:21.6pt;
+ text-indent:-21.6pt;
+ page-break-after:avoid;
+ font-size:16.0pt;
+ font-family:"Arial","sans-serif";}
+h2
+ {margin-top:12.0pt;
+ margin-right:0cm;
+ margin-bottom:3.0pt;
+ margin-left:28.8pt;
+ text-indent:-28.8pt;
+ page-break-after:avoid;
+ font-size:14.0pt;
+ font-family:"Arial","sans-serif";
+ font-style:italic;}
+h3
+ {margin-top:12.0pt;
+ margin-right:0cm;
+ margin-bottom:3.0pt;
+ margin-left:36.0pt;
+ text-indent:-36.0pt;
+ page-break-after:avoid;
+ font-size:13.0pt;
+ font-family:"Arial","sans-serif";}
+h4
+ {margin-top:12.0pt;
+ margin-right:0cm;
+ margin-bottom:3.0pt;
+ margin-left:43.2pt;
+ text-indent:-43.2pt;
+ page-break-after:avoid;
+ font-size:14.0pt;
+ font-family:"Times New Roman","serif";}
+h5
+ {margin-top:12.0pt;
+ margin-right:0cm;
+ margin-bottom:3.0pt;
+ margin-left:50.4pt;
+ text-indent:-50.4pt;
+ font-size:13.0pt;
+ font-family:"Times New Roman","serif";
+ font-style:italic;}
+h6
+ {margin-top:12.0pt;
+ margin-right:0cm;
+ margin-bottom:3.0pt;
+ margin-left:57.6pt;
+ text-indent:-57.6pt;
+ font-size:11.0pt;
+ font-family:"Times New Roman","serif";}
+p.MsoHeading7, li.MsoHeading7, div.MsoHeading7
+ {margin-top:12.0pt;
+ margin-right:0cm;
+ margin-bottom:3.0pt;
+ margin-left:64.8pt;
+ text-indent:-64.8pt;
+ font-size:12.0pt;
+ font-family:"Times New Roman","serif";}
+p.MsoHeading8, li.MsoHeading8, div.MsoHeading8
+ {margin-top:12.0pt;
+ margin-right:0cm;
+ margin-bottom:3.0pt;
+ margin-left:72.0pt;
+ text-indent:-72.0pt;
+ font-size:12.0pt;
+ font-family:"Times New Roman","serif";
+ font-style:italic;}
+p.MsoHeading9, li.MsoHeading9, div.MsoHeading9
+ {margin-top:12.0pt;
+ margin-right:0cm;
+ margin-bottom:3.0pt;
+ margin-left:79.2pt;
+ text-indent:-79.2pt;
+ font-size:11.0pt;
+ font-family:"Arial","sans-serif";}
+p.MsoToc1, li.MsoToc1, div.MsoToc1
+ {margin-top:6.0pt;
+ margin-right:0cm;
+ margin-bottom:6.0pt;
+ margin-left:0cm;
+ line-height:150%;
+ font-size:10.5pt;
+ font-family:"Times New Roman","serif";
+ text-transform:uppercase;
+ font-weight:bold;}
+p.MsoToc2, li.MsoToc2, div.MsoToc2
+ {margin-top:0cm;
+ margin-right:0cm;
+ margin-bottom:0cm;
+ margin-left:12.0pt;
+ margin-bottom:.0001pt;
+ line-height:150%;
+ font-size:10.5pt;
+ font-family:"Times New Roman","serif";
+ font-variant:small-caps;}
+p.MsoToc3, li.MsoToc3, div.MsoToc3
+ {margin-top:0cm;
+ margin-right:0cm;
+ margin-bottom:0cm;
+ margin-left:24.0pt;
+ margin-bottom:.0001pt;
+ line-height:150%;
+ font-size:10.5pt;
+ font-family:"Times New Roman","serif";
+ font-style:italic;}
+p.MsoToc4, li.MsoToc4, div.MsoToc4
+ {margin-top:0cm;
+ margin-right:0cm;
+ margin-bottom:0cm;
+ margin-left:36.0pt;
+ margin-bottom:.0001pt;
+ font-size:9.0pt;
+ font-family:"Times New Roman","serif";}
+p.MsoToc5, li.MsoToc5, div.MsoToc5
+ {margin-top:0cm;
+ margin-right:0cm;
+ margin-bottom:0cm;
+ margin-left:48.0pt;
+ margin-bottom:.0001pt;
+ font-size:9.0pt;
+ font-family:"Times New Roman","serif";}
+p.MsoToc6, li.MsoToc6, div.MsoToc6
+ {margin-top:0cm;
+ margin-right:0cm;
+ margin-bottom:0cm;
+ margin-left:60.0pt;
+ margin-bottom:.0001pt;
+ font-size:9.0pt;
+ font-family:"Times New Roman","serif";}
+p.MsoToc7, li.MsoToc7, div.MsoToc7
+ {margin-top:0cm;
+ margin-right:0cm;
+ margin-bottom:0cm;
+ margin-left:72.0pt;
+ margin-bottom:.0001pt;
+ font-size:9.0pt;
+ font-family:"Times New Roman","serif";}
+p.MsoToc8, li.MsoToc8, div.MsoToc8
+ {margin-top:0cm;
+ margin-right:0cm;
+ margin-bottom:0cm;
+ margin-left:84.0pt;
+ margin-bottom:.0001pt;
+ font-size:9.0pt;
+ font-family:"Times New Roman","serif";}
+p.MsoToc9, li.MsoToc9, div.MsoToc9
+ {margin-top:0cm;
+ margin-right:0cm;
+ margin-bottom:0cm;
+ margin-left:96.0pt;
+ margin-bottom:.0001pt;
+ font-size:9.0pt;
+ font-family:"Times New Roman","serif";}
+p.MsoFootnoteText, li.MsoFootnoteText, div.MsoFootnoteText
+ {margin:0cm;
+ margin-bottom:.0001pt;
+ font-size:10.0pt;
+ font-family:"Times New Roman","serif";}
+p.MsoHeader, li.MsoHeader, div.MsoHeader
+ {margin:0cm;
+ margin-bottom:.0001pt;
+ font-size:12.0pt;
+ font-family:"Times New Roman","serif";}
+p.MsoFooter, li.MsoFooter, div.MsoFooter
+ {margin:0cm;
+ margin-bottom:.0001pt;
+ font-size:12.0pt;
+ font-family:"Times New Roman","serif";}
+p.MsoCaption, li.MsoCaption, div.MsoCaption
+ {margin:0cm;
+ margin-bottom:.0001pt;
+ font-size:11.0pt;
+ font-family:"Times New Roman","serif";
+ font-weight:bold;}
+span.MsoFootnoteReference
+ {vertical-align:super;}
+p.MsoTitle, li.MsoTitle, div.MsoTitle
+ {margin-top:12.0pt;
+ margin-right:0cm;
+ margin-bottom:120.0pt;
+ margin-left:0cm;
+ text-align:center;
+ font-size:16.0pt;
+ font-family:"Arial","sans-serif";
+ font-weight:bold;}
+p.MsoBodyText, li.MsoBodyText, div.MsoBodyText
+ {mso-style-link:"Body Text Char";
+ margin-top:0cm;
+ margin-right:0cm;
+ margin-bottom:6.0pt;
+ margin-left:0cm;
+ font-size:12.0pt;
+ font-family:"Times New Roman","serif";}
+a:link, span.MsoHyperlink
+ {color:blue;
+ text-decoration:underline;}
+a:visited, span.MsoHyperlinkFollowed
+ {color:purple;
+ text-decoration:underline;}
+p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
+ {margin:0cm;
+ margin-bottom:.0001pt;
+ font-size:8.0pt;
+ font-family:"Tahoma","sans-serif";}
+span.BodyTextChar
+ {mso-style-name:"Body Text Char";
+ mso-style-link:"Body Text";}
+ /* Page Definitions */
+ @page WordSection1
+ {size:595.45pt 841.7pt;
+ margin:72.0pt 90.0pt 72.0pt 90.0pt;}
+div.WordSection1
+ {page:WordSection1;}
+@page WordSection2
+ {size:595.45pt 841.7pt;
+ margin:72.0pt 90.0pt 72.0pt 90.0pt;}
+div.WordSection2
+ {page:WordSection2;}
+ /* List Definitions */
+ ol
+ {margin-bottom:0cm;}
+ul
+ {margin-bottom:0cm;}
+-->
+</style>
+
+</head>
+
+<body lang=EN-US link=blue vlink=purple>
+
+<div class=WordSection1>
+
+<p class=MsoTitle>Forward Lock Converter And Decoder</p>
+
+<p class=MsoToc1><span
+class=MsoHyperlink><a href="#_Toc276471422">1<span style='font-size:12.0pt;
+line-height:150%;color:windowtext;text-transform:none;font-weight:normal;
+text-decoration:none'>      </span>Introduction<span style='color:windowtext;
+display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>3</span></a></span></p>
+
+<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471423">2<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none;
+font-weight:normal;text-decoration:none'>      </span>Overview<span
+style='color:windowtext;display:none;text-decoration:none'>... </span><span
+style='color:windowtext;display:none;text-decoration:none'>3</span></a></span></p>
+
+<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471424">3<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none;
+font-weight:normal;text-decoration:none'>      </span>Use Cases<span
+style='color:windowtext;display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>4</span></a></span></p>
+
+<p class=MsoToc2><span class=MsoHyperlink><span style='font-variant:normal !important;
+text-transform:uppercase'><a href="#_Toc276471425">3.1<span style='font-size:
+12.0pt;line-height:150%;color:windowtext;text-transform:none;text-decoration:
+none'>        </span>Converter<span style='color:windowtext;display:none;
+text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>4</span></a></span></span></p>
+
+<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471426">3.1.1<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal;
+text-decoration:none'>     </span>Convert Data (Push-Mode Conversion)<span
+style='color:windowtext;display:none;text-decoration:none'> </span><span
+style='color:windowtext;display:none;text-decoration:none'>4</span></a></span></p>
+
+<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471427">3.1.2<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal;
+text-decoration:none'>     </span>Convert File (Pull-Mode Conversion)<span
+style='color:windowtext;display:none;text-decoration:none'> </span><span
+style='color:windowtext;display:none;text-decoration:none'>6</span></a></span></p>
+
+<p class=MsoToc2><span class=MsoHyperlink><span style='font-variant:normal !important;
+text-transform:uppercase'><a href="#_Toc276471428">3.2<span style='font-size:
+12.0pt;line-height:150%;color:windowtext;text-transform:none;text-decoration:
+none'>        </span>Decoder<span style='color:windowtext;display:none;
+text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>7</span></a></span></span></p>
+
+<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471429">3.2.1<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal;
+text-decoration:none'>     </span>Check Integrity<span style='color:windowtext;
+display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>8</span></a></span></p>
+
+<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471430">3.2.2<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal;
+text-decoration:none'>     </span>Get Content Type<span style='color:windowtext;
+display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>9</span></a></span></p>
+
+<p class=MsoToc3><span class=MsoHyperlink><a href="#_Toc276471431">3.2.3<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;font-style:normal;
+text-decoration:none'>     </span>Decode File<span style='color:windowtext;
+display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>10</span></a></span></p>
+
+<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471432">4<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none;
+font-weight:normal;text-decoration:none'>      </span>Definition of the
+Internal Forward Lock File Format<span style='color:windowtext;display:none;
+text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>11</span></a></span></p>
+
+<p class=MsoToc2><span class=MsoHyperlink><span style='font-variant:normal !important;
+text-transform:uppercase'><a href="#_Toc276471433">4.1<span style='font-size:
+12.0pt;line-height:150%;color:windowtext;text-transform:none;text-decoration:
+none'>        </span>Key Derivation<span style='color:windowtext;display:none;
+text-decoration:none'>.. </span><span
+style='color:windowtext;display:none;text-decoration:none'>11</span></a></span></span></p>
+
+<p class=MsoToc2><span class=MsoHyperlink><span style='font-variant:normal !important;
+text-transform:uppercase'><a href="#_Toc276471434">4.2<span style='font-size:
+12.0pt;line-height:150%;color:windowtext;text-transform:none;text-decoration:
+none'>        </span>Calculation of the Counters<span style='color:windowtext;
+display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>12</span></a></span></span></p>
+
+<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471435">5<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none;
+font-weight:normal;text-decoration:none'>      </span>Unit Test Cases<span
+style='color:windowtext;display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>12</span></a></span></p>
+
+<p class=MsoToc1><span class=MsoHyperlink><a href="#_Toc276471436">6<span
+style='font-size:12.0pt;line-height:150%;color:windowtext;text-transform:none;
+font-weight:normal;text-decoration:none'>      </span>References<span
+style='color:windowtext;display:none;text-decoration:none'>. </span><span
+style='color:windowtext;display:none;text-decoration:none'>12</span></a></span></p>
+
+<p class=MsoBodyText></p>
+
+</div>
+
+<span style='font-size:12.0pt;font-family:"Times New Roman","serif"'><br
+clear=all style='page-break-before:right'>
+</span>
+
+<div class=WordSection2>
+
+<h1><a name="_Toc276471422"></a><a name="_Ref263085474">1<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Introduction</a></h1>
+
+<p class=MsoBodyText>The internal Forward Lock file format is used for encrypting
+inherently unencrypted OMA DRM version 1 Forward Lock and Combined Delivery
+files so they can be securely stored on externally accessible file system partitions
+such as memory stick.</p>
+
+<p class=MsoBodyText>Our general strategy is to convert such <i>OMA DRM Message</i>
+(‘.dm’) files to internal Forward Lock (‘.fl’) files as soon as they are
+downloaded or otherwise transferred to the phone, and not actually provide any
+decoders for ‘.dm’ files.</p>
+
+<h1><a name="_Toc276471423">2<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</span>Overview</a></h1>
+
+<p class=MsoBodyText>The <i>Forward Lock Converter</i> converts OMA DRM Message
+files to the internal file format. The <i>Forward Lock Decoder</i> provides a
+POSIX-level API for transparent reading and seeking through such a converted
+file as if it were unencrypted. The API also includes functions for checking a
+file’s integrity and getting the MIME type of its embedded content.</p>
+
+<p class=MsoBodyText style='margin-bottom:24.0pt'>The converter and decoder are
+built into two separate libraries, which share common code for random number
+generation and key encryption in a third library. For test purposes there is
+also a unit test application. See Figure 1.</p>
+
+<p class=MsoBodyText style='page-break-after:avoid'><img width=288 height=364
+src="images/image001.gif"></p>
+
+<p class=MsoCaption style='margin-top:12.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm'><a name="_Ref262730885">Figure </a>1. Block diagram illustrating the dependencies between the executable modules.</p>
+
+<b><span style='font-size:16.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></b>
+
+<h1><a name="_Toc276471424">3<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</span>Use Cases</a></h1>
+
+<p class=MsoBodyText>This section describes all the use cases for the converter
+and decoder. It shows the sequence of API calls that should be used to solve
+these use cases.</p>
+
+<h2><a name="_Toc276471425">3.1<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;
+</span>Converter</a></h2>
+
+<p class=MsoBodyText>Through the converter API, conversion can be performed in one
+of two ways:</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><i>Push-mode
+conversion</i> is when the client progressively feeds data to the converter as
+it arrives. This is appropriate when data arrives gradually in chunks, with
+idle time in between. Consequently, push mode is used for converting files
+being downloaded through HTTP. See section 3.1.1.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><i>Pull-mode
+conversion</i> is when the converter drives the process and consumes data from
+the client as it needs it. This is appropriate when the entire file to be
+converted is readily available. Hence, pull mode is used by the unit test application.
+See section 3.1.2.</p>
+
+<p class=MsoBodyText>Internally, pull-mode conversion is implemented in terms
+of the API for push-mode conversion.</p>
+
+<h3><a name="_Toc276471426"></a><a name="_Ref263085478">3.1.1<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span>Convert Data
+(Push-Mode Conversion)</a></h3>
+
+<p class=MsoBodyText>Push-mode conversion is performed as follows (see also Figure 2):</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockConv_OpenSession</span>
+initializes the output parameter and returns a <i>session ID</i> to be used in
+subsequent calls to the API. The output parameter is a union of return values
+whose correct use at any given moment is determined by the API function last
+called.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockConv_ConvertData</span>
+is called repeatedly until no more input data remains. Each call converts the
+maximum amount of data possible and writes it to the output buffer. The client then
+writes this data to file.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>3.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockConv_CloseSession</span>
+cleans up the session and deallocates the output buffer. If all has gone well, a
+two-part cryptographic signature of the output file is calculated. The client
+must go back and rewrite part of the file header with this updated signature
+information.</p>
+
+<p class=MsoBodyText>Every time a file is being converted, the converter calls <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_GetRandomNumber</span>
+to generate a new, unique session key. No two converted files look alike, even
+if the original files are the same.</p>
+
+<p class=MsoBodyText><b>Note:</b> The random bytes cannot come from any bare-minimum
+implementation of the C-library <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>rand</span>
+function—they must be cryptographically secure. Otherwise, security will be
+compromised.</p>
+
+<p class=MsoBodyText>The session key is encrypted and stored within the
+converted file. Key encryption is performed using <span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_GetEncryptedKeyLength</span> and <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_EncryptKey</span>.
+These two functions, together with the corresponding decryption function (<span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_DecryptKey</span>),
+are the integration points where an OEM manufacturer may implement their own
+key-encryption scheme.</p>
+
+<p class=MsoBodyText><b>Note:</b> The key-encryption key must be unique to each
+device; this is what makes the files forward lock–protected. Ideally, it should
+be derived from secret hardware parameters, but at the very least it should be
+persistent from one master reset to the next.</p>
+
+<div style='margin-bottom:24.0pt;border:solid windowtext 1.0pt;padding:1.0pt 4.0pt 1.0pt 4.0pt;
+background:#F2F2F2'>
+
+<p class=MsoBodyText style='background:#F2F2F2;border:
+none;padding:0cm'><b>Note:</b> In the open-source implementation of the <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>libfwdlock-common</span>
+library, a random key-encryption key is generated and stored in plaintext in
+the file system, without being obfuscated in any way (doing so would be futile
+since the source code is openly available). This key must be kept secret from
+the user, and shouldn’t be possible to extract through backup-and-restore
+functionality or the like. OEM manufacturers will probably want to implement a
+truly hardware-based device-unique key.</p>
+
+</div>
+
+<p class=MsoBodyText style='page-break-after:avoid'><img width=531 height=563
+src="images/image002.gif"></p>
+
+<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm'><a name="_Ref263085187">Figure </a>2. Converter UC: Convert Data.</p>
+
+<b><span style='font-size:13.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></b>
+
+<h3><a name="_Toc276471427"></a><a name="_Ref263163082">3.1.2<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span>Convert File
+(Pull-Mode Conversion)</a></h3>
+
+<p class=MsoBodyText>Pull-mode conversion is performed by calling <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_ConvertFile</span>
+with the filename, unless there is need for a specialized <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>read</span> function, in
+which case <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_ConvertOpenFile</span>
+should be used directly instead. See Figure 3.</p>
+
+<p class=MsoBodyText style='margin-bottom:24.0pt'>Internally, <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_ConvertFile</span>
+calls <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_ConvertOpenFile</span>.
+The latter then proceeds with the conversion using the push-mode API, acting as
+the client in the previous use case; see section 3.1.1.</p>
+
+<p class=MsoBodyText style='page-break-after:avoid'><img width=531 height=731
+src="images/image003.gif"></p>
+
+<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm'><a name="_Ref263085208">Figure </a>3. Converter UC: Convert File.</p>
+
+<b><i><span style='font-size:14.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></i></b>
+
+<h2><a name="_Toc276471428">3.2<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;
+</span>Decoder</a></h2>
+
+<p class=MsoBodyText>The decoder API allows the client to do the following:</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Check
+the integrity of an internal Forward Lock file, i.e., detect whether it has
+been manipulated in any way; see section 3.2.1.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Get
+the MIME type of the embedded content (the “original” MIME type before DRM protection
+was applied); see section 3.2.2.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>3.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Decode
+the file by random access, i.e., read and seek through it in an arbitrary
+manner; see section 3.2.3.</p>
+
+<p class=MsoBodyText>All subsequent operations on a file first require it to be
+opened. Opening a file returns a <i>file descriptor</i>—a handle to be used in
+these subsequent operations.</p>
+
+<p class=MsoBodyText>If the filename is known, an internal Forward Lock file
+can be opened using <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span>.
+If only the file descriptor of an already open file is available, a decoding
+session can instead be initialized using <span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span>.</p>
+
+<p class=MsoBodyText>Internally, <span style='font-size:10.0pt;font-family:
+"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span> calls <span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span>. For efficiency
+reasons, <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span>
+therefore assumes that the file position is at the beginning of the file when
+the function gets called. A client who calls it directly must make sure that
+this assumption holds.</p>
+
+<p class=MsoBodyText>When a file is being attached, the session key stored in
+the file during conversion is decrypted using <span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_GetEncryptedKeyLength</span> and <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockGlue_DecryptKey</span>,
+in order to set up for decoding and integrity checking.</p>
+
+<p class=MsoBodyText>For just getting the content type, however, retrieving the
+session key would strictly speaking not be necessary, so there is an
+opportunity here to optimize for that if it proves necessary later.</p>
+
+<p class=MsoBodyText>Symmetrical to <span style='font-size:10.0pt;font-family:
+"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span> and <span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span>, there are also functions
+for closing a file or detaching from it:</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>If
+it was opened with <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span>
+it should be closed with <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_close</span>.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>If
+it was attached with <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_attach</span>
+it should be detached with <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_detach</span>.</p>
+
+<b><span style='font-size:13.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></b>
+
+<h3><a name="_Ref263163099"></a><a name="_Toc276471429">3.2.1<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span>Check Integrity</a></h3>
+
+<p class=MsoBodyText>There are three methods for checking the integrity of an
+internal Forward Lock file, in whole or in part (see also Figure 4):</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckDataIntegrity</span>,
+which checks the integrity of the encrypted content data.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckHeaderIntegrity</span>,
+which checks the integrity of the file header, including the content type and
+other fields not currently supported but reserved for future use.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>3.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckIntegrity</span>,
+which internally calls first <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckHeaderIntegrity</span>
+and then <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckDataIntegrity</span>.</p>
+
+<p class=MsoBodyText style='margin-bottom:24.0pt'><span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckHeaderIntegrity</span> is
+generally much faster than <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_CheckDataIntegrity</span>,
+whose running time is directly proportional to the size of the file.</p>
+
+<p class=MsoBodyText style='page-break-after:avoid'><img width=543 height=575
+src="images/image004.gif"></p>
+
+<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm'><a name="_Ref263163308">Figure </a>4. Decoder UC: Check Integrity.</p>
+
+<b><span style='font-size:13.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></b>
+
+<h3><a name="_Toc276471430"></a><a name="_Ref263163117">3.2.2<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span>Get Content Type</a></h3>
+
+<p class=MsoBodyText style='margin-bottom:24.0pt'><span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_GetContentType</span> returns a
+read-only reference to an ASCII string containing the MIME type of the
+embedded content. This reference is valid as long as the file is kept open.
+Clients who need access to the content type after closing the file should make
+a copy of the string. See Figure 5 below.</p>
+
+<p class=MsoBodyText style='page-break-after:avoid'><img width=543 height=488
+src="images/image005.gif"></p>
+
+<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm'><a name="_Ref263163392">Figure </a>5. Decoder UC: Get Content Type.</p>
+
+<b><span style='font-size:13.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></b>
+
+<h3><a name="_Toc276471431"></a><a name="_Ref263163137">3.2.3<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp; </span>Decode File</a></h3>
+
+<p class=MsoBodyText>After opening an internal Forward Lock file (or attaching
+to an already open one), it can be transparently read from as if it were
+unencrypted. Any number of calls to read data from the current file position or
+set it to a new one (which is what <span style='font-size:10.0pt;font-family:
+"Lucida Console","DejaVu Sans Mono"'>lseek</span> does) can be made in any order; this is what we
+call <i>random access</i>. See Figure 6.</p>
+
+<p class=MsoBodyText>The Forward Lock Decoder versions of the <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>read</span>, <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>lseek</span>, and <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>close</span> functions
+have the exact same signatures as their POSIX counterparts. So, for example,
+the call <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_lseek(fd,
+0, SEEK_END)</span> returns the size of the embedded content data, i.e., the
+size of the original file before DRM protection.</p>
+
+<p class=MsoBodyText style='margin-bottom:24.0pt'>Moreover, <span
+style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>FwdLockFile_open</span>
+is like regular POSIX <span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>open</span>
+except it takes only the filename as a parameter—access is always read-only.</p>
+
+<p class=MsoBodyText style='page-break-after:avoid'><img width=543 height=522
+src="images/image006.gif"></p>
+
+<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm'><a name="_Ref263166303">Figure </a>6. Decoder UC: Decode File.</p>
+
+<b><span style='font-size:16.0pt;font-family:"Arial","sans-serif"'><br
+clear=all style='page-break-before:always'>
+</span></b>
+
+<h1><a name="_Toc276471432">4<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</span>Definition of the Internal Forward Lock File Format</a></h1>
+
+<p class=MsoBodyText style='margin-bottom:12.0pt'>The inner structure of an internal
+Forward Lock file is defined in Table 1 below.</p>
+
+<table class=MsoNormalTable border=1 cellspacing=0 cellpadding=0
+ style='border-collapse:collapse;border:none'>
+ <tr>
+ <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'><b>Offset [bytes]</b></p>
+ </td>
+ <td width=96 valign=top style='width:72.0pt;border:solid windowtext 1.0pt;
+ border-left:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'><b>Size [bytes]</b></p>
+ </td>
+ <td width=361 valign=top style='width:270.85pt;border:solid windowtext 1.0pt;
+ border-left:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'><b>Description</b></p>
+ </td>
+ </tr>
+ <tr>
+ <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+ border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>0</p>
+ </td>
+ <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+ border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>4</p>
+ </td>
+ <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+ none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>The file signature (so-called
+ <i>magic number</i>): a four-character code consisting of the letters
+ F-W-L-K.</p>
+ </td>
+ </tr>
+ <tr>
+ <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+ border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>4</p>
+ </td>
+ <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+ border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>1</p>
+ </td>
+ <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+ none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>Version number (0 for the
+ first version).</p>
+ </td>
+ </tr>
+ <tr>
+ <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+ border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>5</p>
+ </td>
+ <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+ border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>1</p>
+ </td>
+ <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+ none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>Indicates the subformat:</p>
+ <p class=MsoNormal style='page-break-after:avoid'><i>0x00 Forward Lock</i></p>
+ <p class=MsoNormal style='page-break-after:avoid'><i>0x01 Combined Delivery</i></p>
+ </td>
+ </tr>
+ <tr>
+ <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+ border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>6</p>
+ </td>
+ <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+ border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>1</p>
+ </td>
+ <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+ none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>Usage restriction flags (prohibitions
+ against usage as ringtone or as wallpaper and screen saver). Also indicates
+ if the file is bound to a specific SIM card.</p>
+ <p class=MsoNormal style='page-break-after:avoid'><i>0x00 No usage
+ restrictions</i></p>
+ <p class=MsoNormal style='page-break-after:avoid'><i>0x01 Ringtone usage
+ prohibited</i></p>
+ <p class=MsoNormal style='page-break-after:avoid'><i>0x02 Screen usage
+ prohibited</i></p>
+ <p class=MsoNormal style='page-break-after:avoid'><i>0x80 Bound to SIM</i></p>
+ <p class=MsoNormal style='page-break-after:avoid'>(Any number of these may be
+ OR-ed together.)</p>
+ </td>
+ </tr>
+ <tr>
+ <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+ border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>7</p>
+ </td>
+ <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+ border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>1</p>
+ </td>
+ <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+ none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>Length of the MIME content
+ type (<i>k</i>).</p>
+ </td>
+ </tr>
+ <tr>
+ <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+ border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>8</p>
+ </td>
+ <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+ border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'><i>k</i></p>
+ </td>
+ <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+ none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>The MIME content type
+ (ASCII-encoded without null-character termination).</p>
+ </td>
+ </tr>
+ <tr>
+ <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+ border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>8+<i>k</i></p>
+ </td>
+ <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+ border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'><i>l </i>= 0 or 16</p>
+ </td>
+ <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+ none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>If the subformat is
+ Combined Delivery, this field contains the auto-generated content ID (16&nbsp;bytes).
+ If not, this field is zero-size.</p>
+ </td>
+ </tr>
+ <tr>
+ <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+ border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>8+<i>k</i>+<i>l</i></p>
+ </td>
+ <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+ border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'><i>m </i>= 0 or 9</p>
+ </td>
+ <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+ none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>If the file is bound to a
+ specific SIM card, this field contains the 9-byte packed IMSI number. If not,
+ this field is zero-size.</p>
+ </td>
+ </tr>
+ <tr>
+ <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+ border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>8+<i>k</i>+<i>l</i>+<i>m</i></p>
+ </td>
+ <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+ border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'><i>n</i> &#8805; 16</p>
+ </td>
+ <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+ none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>The encrypted session key, the
+ first sixteen bytes of which are also used as the CTR-mode <i>nonce</i> (similar
+ to the CBC-mode <i>initialization vector</i>).</p>
+ </td>
+ </tr>
+ <tr>
+ <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+ border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>8+<i>k</i>+<i>l</i>+<i>m</i>+<i>n</i></p>
+ </td>
+ <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+ border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>20</p>
+ </td>
+ <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+ none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>Data signature—the SHA-1
+ HMAC of the encrypted content data.</p>
+ </td>
+ </tr>
+ <tr>
+ <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+ border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>28+<i>k</i>+<i>l</i>+<i>m</i>+<i>n</i></p>
+ </td>
+ <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+ border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>20</p>
+ </td>
+ <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+ none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>Header signature—the SHA-1
+ HMAC of all the fields above, including the encrypted session key and data
+ signature.</p>
+ </td>
+ </tr>
+ <tr>
+ <td width=111 valign=top style='width:83.4pt;border:solid windowtext 1.0pt;
+ border-top:none;padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>48+<i>k</i>+<i>l</i>+<i>m</i>+<i>n</i></p>
+ </td>
+ <td width=96 valign=top style='width:72.0pt;border-top:none;border-left:none;
+ border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'><i>&lt;to the end of the
+ file&gt;</i></p>
+ </td>
+ <td width=361 valign=top style='width:270.85pt;border-top:none;border-left:
+ none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;
+ padding:0cm 5.4pt 0cm 5.4pt'>
+ <p class=MsoNormal style='page-break-after:avoid'>The content data encrypted
+ using 128-bit AES in CTR mode.</p>
+ </td>
+ </tr>
+</table>
+
+<p class=MsoCaption style='margin-top:6.0pt;margin-right:0cm;margin-bottom:
+12.0pt;margin-left:0cm;page-break-after:avoid'><a name="_Ref151269206">Table </a>1. Definition of the fields of an internal Forward Lock file.</p>
+
+<p class=MsoBodyText>As of now, neither Combined Delivery nor usage
+restrictions (including SIM binding) are supported. These fields are reserved
+for future use.</p>
+
+<h2><a name="_Toc276471433">4.1<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;
+</span>Key Derivation</a></h2>
+
+<p class=MsoBodyText>The session key consists of sixteen bytes fetched from a
+cryptographically secure random number generator. From the session key, two
+separate keys are derived: one used for encryption, the other for signing.</p>
+
+<p class=MsoBodyText>The encryption key is the output from encrypting the
+16-byte all-zero input block {0, 0, …, 0} using 128-bit AES with the random session
+key as the key. The signing key is the output from encrypting the 16-byte input
+block {1, 0, …, 0} the same way. The keys so derived will be cryptographically
+independent from each other.</p>
+
+<p class=MsoBodyText>The session key is encrypted using a hardware-dependent
+key-encryption key unique to each device. The encrypted session key is stored
+inside the file, and its first sixteen bytes are also used as the <i>nonce</i>
+for the CTR-mode encryption of the content data.</p>
+
+<h2><a name="_Toc276471434">4.2<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;
+</span>Calculation of the Counters</a></h2>
+
+<p class=MsoBodyText>Using CTR (“counter”) mode, a block cipher such as AES can
+be turned into a stream cipher. The process of encryption and decryption is
+well defined in [1], except for the specifics of the calculation of the
+counters. For the internal Forward Lock file format, the counters are
+calculated as follows:</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>The
+nonce is interpreted as a 128-bit unsigned integer in little-endian format.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>The
+zero-based block sequence number (also a little-endian unsigned integer) is
+added modulo 2<sup>128</sup> to the nonce to produce the counter for a given
+block.</p>
+
+<h1><a name="_Toc276471435">5<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</span>Unit Test Cases</a></h1>
+
+<p class=MsoBodyText>Unit test cases for the converter and decoder come in two
+varieties:</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>1.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><i>Black-box</i>
+test cases aim to verify that you get sensible results from malformed or
+“tricky” input data.</p>
+
+<p class=MsoBodyText style='margin-left:36.0pt;text-indent:-18.0pt'>2.<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><i>White-box</i>
+test cases aim to maximize code coverage using knowledge of code internals.</p>
+
+<p class=MsoBodyText>The black-box test cases are dependent on a specifically
+designed set of input files found in the <span style='font-size:10.0pt;
+font-family:"Lucida Console","DejaVu Sans Mono"'>forward-lock/internal-format/test/res</span>
+directory in the repository. For ‘tests’ variants of the software, these input
+files will be automatically installed in the file system image during build.</p>
+
+<p class=MsoBodyText>Run the test cases from the ADB shell command line as
+follows:</p>
+
+<p class=MsoNormal style='margin-top:0cm;margin-right:0cm;margin-bottom:6.0pt;
+margin-left:21.55pt'><span style='font-size:10.0pt;font-family:"Lucida Console","DejaVu Sans Mono"'>#
+gtest_fwdlock</span></p>
+
+<p class=MsoBodyText>If all black-box but no white-box test cases fail, the
+input files probably can’t be found in the working directory.</p>
+
+<h1><a name="_Toc276471436">6<span style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</span>References</a></h1>
+
+<p class=MsoBodyText style='margin-left:28.9pt;text-indent:-28.9pt'>[1]<span
+style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+</span><a
+href="http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf">Dworkin,
+Morris: “Recommendation for Block Cipher Modes of Operation—Methods and
+Techniques,” NIST Special Publication 800-38A, December 2001.</a><a
+name="_Ref151269073"></a></p>
+
+</div>
+
+</body>
+
+</html>
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image001.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image001.gif
new file mode 100644
index 0000000..ee94513
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image001.gif
Binary files differ
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image002.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image002.gif
new file mode 100644
index 0000000..8c12f46
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image002.gif
Binary files differ
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image003.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image003.gif
new file mode 100644
index 0000000..9e019ca
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image003.gif
Binary files differ
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image004.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image004.gif
new file mode 100644
index 0000000..cae1d01
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image004.gif
Binary files differ
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image005.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image005.gif
new file mode 100644
index 0000000..0d87be9
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image005.gif
Binary files differ
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image006.gif b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image006.gif
new file mode 100644
index 0000000..9445b6b
--- /dev/null
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/doc/images/image006.gif
Binary files differ
diff --git a/drm/libdrmframework/plugins/passthru/Android.mk b/drm/libdrmframework/plugins/passthru/Android.mk
new file mode 100644
index 0000000..d0d1439
--- /dev/null
+++ b/drm/libdrmframework/plugins/passthru/Android.mk
@@ -0,0 +1,42 @@
+#
+# 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.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ src/DrmPassthruPlugIn.cpp
+
+LOCAL_MODULE := libdrmpassthruplugin
+
+LOCAL_STATIC_LIBRARIES := libdrmframeworkcommon
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libdl
+
+
+LOCAL_C_INCLUDES += \
+ $(TOP)/frameworks/base/drm/libdrmframework/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/plugins/passthru/include \
+ $(TOP)/frameworks/base/drm/libdrmframework/plugins/common/include \
+ $(TOP)/frameworks/base/include
+
+# Set the following flag to enable the decryption passthru flow
+#LOCAL_CFLAGS += -DENABLE_PASSTHRU_DECRYPTION
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h
new file mode 100644
index 0000000..f941f70
--- /dev/null
+++ b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h
@@ -0,0 +1,102 @@
+/*
+ * 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 __DRM_PASSTHRU_PLUGIN_H__
+#define __DRM_PASSTHRU_PLUGIN_H__
+
+#include <DrmEngineBase.h>
+
+namespace android {
+
+class DrmPassthruPlugIn : public DrmEngineBase {
+
+public:
+ DrmPassthruPlugIn();
+ virtual ~DrmPassthruPlugIn();
+
+protected:
+ DrmConstraints* onGetConstraints(int uniqueId, const String8* path, int action);
+
+ DrmMetadata* onGetMetadata(int uniqueId, const String8* path);
+
+ status_t onInitialize(int uniqueId);
+
+ status_t onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener);
+
+ status_t onTerminate(int uniqueId);
+
+ bool onCanHandle(int uniqueId, const String8& path);
+
+ DrmInfoStatus* onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo);
+
+ status_t onSaveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath);
+
+ DrmInfo* onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest);
+
+ String8 onGetOriginalMimeType(int uniqueId, const String8& path);
+
+ int onGetDrmObjectType(int uniqueId, const String8& path, const String8& mimeType);
+
+ int onCheckRightsStatus(int uniqueId, const String8& path, int action);
+
+ status_t onConsumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve);
+
+ status_t onSetPlaybackStatus(
+ int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position);
+
+ bool onValidateAction(
+ int uniqueId, const String8& path, int action, const ActionDescription& description);
+
+ status_t onRemoveRights(int uniqueId, const String8& path);
+
+ status_t onRemoveAllRights(int uniqueId);
+
+ status_t onOpenConvertSession(int uniqueId, int convertId);
+
+ DrmConvertedStatus* onConvertData(int uniqueId, int convertId, const DrmBuffer* inputData);
+
+ DrmConvertedStatus* onCloseConvertSession(int uniqueId, int convertId);
+
+ DrmSupportInfo* onGetSupportInfo(int uniqueId);
+
+ status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, off64_t offset, off64_t length);
+
+ status_t onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, const char* uri);
+
+ status_t onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle);
+
+ status_t onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo);
+
+ status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV);
+
+ status_t onFinalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId);
+
+ ssize_t onPread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset);
+
+private:
+ DecryptHandle* openDecryptSessionImpl();
+};
+
+};
+
+#endif /* __DRM_PASSTHRU_PLUGIN_H__ */
+
diff --git a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
new file mode 100644
index 0000000..a3eac3e
--- /dev/null
+++ b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp
@@ -0,0 +1,305 @@
+/*
+ * 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 "DrmPassthruPlugIn"
+#include <utils/Log.h>
+
+#include <drm/DrmRights.h>
+#include <drm/DrmConstraints.h>
+#include <drm/DrmMetadata.h>
+#include <drm/DrmInfo.h>
+#include <drm/DrmInfoEvent.h>
+#include <drm/DrmInfoStatus.h>
+#include <drm/DrmConvertedStatus.h>
+#include <drm/DrmInfoRequest.h>
+#include <drm/DrmSupportInfo.h>
+#include <DrmPassthruPlugIn.h>
+
+using namespace android;
+
+
+// This extern "C" is mandatory to be managed by TPlugInManager
+extern "C" IDrmEngine* create() {
+ return new DrmPassthruPlugIn();
+}
+
+// This extern "C" is mandatory to be managed by TPlugInManager
+extern "C" void destroy(IDrmEngine* pPlugIn) {
+ delete pPlugIn;
+ pPlugIn = NULL;
+}
+
+DrmPassthruPlugIn::DrmPassthruPlugIn()
+ : DrmEngineBase() {
+
+}
+
+DrmPassthruPlugIn::~DrmPassthruPlugIn() {
+
+}
+
+DrmMetadata* DrmPassthruPlugIn::onGetMetadata(int uniqueId, const String8* path) {
+ return NULL;
+}
+
+DrmConstraints* DrmPassthruPlugIn::onGetConstraints(
+ int uniqueId, const String8* path, int action) {
+ ALOGV("DrmPassthruPlugIn::onGetConstraints From Path: %d", uniqueId);
+ DrmConstraints* drmConstraints = new DrmConstraints();
+
+ String8 value("dummy_available_time");
+ char* charValue = NULL;
+ charValue = new char[value.length() + 1];
+ strncpy(charValue, value.string(), value.length());
+
+ //Just add dummy available time for verification
+ drmConstraints->put(&(DrmConstraints::LICENSE_AVAILABLE_TIME), charValue);
+
+ return drmConstraints;
+}
+
+DrmInfoStatus* DrmPassthruPlugIn::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
+ ALOGV("DrmPassthruPlugIn::onProcessDrmInfo - Enter : %d", uniqueId);
+ DrmInfoStatus* drmInfoStatus = NULL;
+ if (NULL != drmInfo) {
+ switch (drmInfo->getInfoType()) {
+ case DrmInfoRequest::TYPE_REGISTRATION_INFO: {
+ const DrmBuffer* emptyBuffer = new DrmBuffer();
+ drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK,
+ DrmInfoRequest::TYPE_REGISTRATION_INFO, emptyBuffer, drmInfo->getMimeType());
+ break;
+ }
+ case DrmInfoRequest::TYPE_UNREGISTRATION_INFO: {
+ const DrmBuffer* emptyBuffer = new DrmBuffer();
+ drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK,
+ DrmInfoRequest::TYPE_UNREGISTRATION_INFO, emptyBuffer, drmInfo->getMimeType());
+ break;
+ }
+ case DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO: {
+ String8 licenseString("dummy_license_string");
+ const int bufferSize = licenseString.size();
+ char* data = NULL;
+ data = new char[bufferSize];
+ memcpy(data, licenseString.string(), bufferSize);
+ const DrmBuffer* buffer = new DrmBuffer(data, bufferSize);
+ drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK,
+ DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO, buffer, drmInfo->getMimeType());
+ break;
+ }
+ }
+ }
+ ALOGV("DrmPassthruPlugIn::onProcessDrmInfo - Exit");
+ return drmInfoStatus;
+}
+
+status_t DrmPassthruPlugIn::onSetOnInfoListener(
+ int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
+ ALOGV("DrmPassthruPlugIn::onSetOnInfoListener : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onInitialize(int uniqueId) {
+ ALOGV("DrmPassthruPlugIn::onInitialize : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onTerminate(int uniqueId) {
+ ALOGV("DrmPassthruPlugIn::onTerminate : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+DrmSupportInfo* DrmPassthruPlugIn::onGetSupportInfo(int uniqueId) {
+ ALOGV("DrmPassthruPlugIn::onGetSupportInfo : %d", uniqueId);
+ DrmSupportInfo* drmSupportInfo = new DrmSupportInfo();
+ // Add mimetype's
+ drmSupportInfo->addMimeType(String8("application/vnd.passthru.drm"));
+ // Add File Suffixes
+ drmSupportInfo->addFileSuffix(String8(".passthru"));
+ // Add plug-in description
+ drmSupportInfo->setDescription(String8("Passthru plug-in"));
+ return drmSupportInfo;
+}
+
+status_t DrmPassthruPlugIn::onSaveRights(int uniqueId, const DrmRights& drmRights,
+ const String8& rightsPath, const String8& contentPath) {
+ ALOGV("DrmPassthruPlugIn::onSaveRights : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+DrmInfo* DrmPassthruPlugIn::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
+ ALOGV("DrmPassthruPlugIn::onAcquireDrmInfo : %d", uniqueId);
+ DrmInfo* drmInfo = NULL;
+
+ if (NULL != drmInfoRequest) {
+ String8 dataString("dummy_acquistion_string");
+ int length = dataString.length();
+ char* data = NULL;
+ data = new char[length];
+ memcpy(data, dataString.string(), length);
+ drmInfo = new DrmInfo(drmInfoRequest->getInfoType(),
+ DrmBuffer(data, length), drmInfoRequest->getMimeType());
+ }
+ return drmInfo;
+}
+
+bool DrmPassthruPlugIn::onCanHandle(int uniqueId, const String8& path) {
+ ALOGV("DrmPassthruPlugIn::canHandle: %s ", path.string());
+ String8 extension = path.getPathExtension();
+ extension.toLower();
+ return (String8(".passthru") == extension);
+}
+
+String8 DrmPassthruPlugIn::onGetOriginalMimeType(int uniqueId, const String8& path) {
+ ALOGV("DrmPassthruPlugIn::onGetOriginalMimeType() : %d", uniqueId);
+ return String8("video/passthru");
+}
+
+int DrmPassthruPlugIn::onGetDrmObjectType(
+ int uniqueId, const String8& path, const String8& mimeType) {
+ ALOGV("DrmPassthruPlugIn::onGetDrmObjectType() : %d", uniqueId);
+ return DrmObjectType::UNKNOWN;
+}
+
+int DrmPassthruPlugIn::onCheckRightsStatus(int uniqueId, const String8& path, int action) {
+ ALOGV("DrmPassthruPlugIn::onCheckRightsStatus() : %d", uniqueId);
+ int rightsStatus = RightsStatus::RIGHTS_VALID;
+ return rightsStatus;
+}
+
+status_t DrmPassthruPlugIn::onConsumeRights(int uniqueId, DecryptHandle* decryptHandle,
+ int action, bool reserve) {
+ ALOGV("DrmPassthruPlugIn::onConsumeRights() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
+ int playbackStatus, int64_t position) {
+ ALOGV("DrmPassthruPlugIn::onSetPlaybackStatus() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+bool DrmPassthruPlugIn::onValidateAction(int uniqueId, const String8& path,
+ int action, const ActionDescription& description) {
+ ALOGV("DrmPassthruPlugIn::onValidateAction() : %d", uniqueId);
+ return true;
+}
+
+status_t DrmPassthruPlugIn::onRemoveRights(int uniqueId, const String8& path) {
+ ALOGV("DrmPassthruPlugIn::onRemoveRights() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onRemoveAllRights(int uniqueId) {
+ ALOGV("DrmPassthruPlugIn::onRemoveAllRights() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onOpenConvertSession(int uniqueId, int convertId) {
+ ALOGV("DrmPassthruPlugIn::onOpenConvertSession() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+DrmConvertedStatus* DrmPassthruPlugIn::onConvertData(
+ int uniqueId, int convertId, const DrmBuffer* inputData) {
+ ALOGV("DrmPassthruPlugIn::onConvertData() : %d", uniqueId);
+ DrmBuffer* convertedData = NULL;
+
+ if (NULL != inputData && 0 < inputData->length) {
+ int length = inputData->length;
+ char* data = NULL;
+ data = new char[length];
+ convertedData = new DrmBuffer(data, length);
+ memcpy(convertedData->data, inputData->data, length);
+ }
+ return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, convertedData, 0 /*offset*/);
+}
+
+DrmConvertedStatus* DrmPassthruPlugIn::onCloseConvertSession(int uniqueId, int convertId) {
+ ALOGV("DrmPassthruPlugIn::onCloseConvertSession() : %d", uniqueId);
+ return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, NULL, 0 /*offset*/);
+}
+
+status_t DrmPassthruPlugIn::onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, int fd, off64_t offset, off64_t length) {
+ ALOGV("DrmPassthruPlugIn::onOpenDecryptSession() : %d", uniqueId);
+
+#ifdef ENABLE_PASSTHRU_DECRYPTION
+ decryptHandle->mimeType = String8("video/passthru");
+ decryptHandle->decryptApiType = DecryptApiType::ELEMENTARY_STREAM_BASED;
+ decryptHandle->status = DRM_NO_ERROR;
+ decryptHandle->decryptInfo = NULL;
+ return DRM_NO_ERROR;
+#endif
+
+ return DRM_ERROR_CANNOT_HANDLE;
+}
+
+status_t DrmPassthruPlugIn::onOpenDecryptSession(
+ int uniqueId, DecryptHandle* decryptHandle, const char* uri) {
+ return DRM_ERROR_CANNOT_HANDLE;
+}
+
+status_t DrmPassthruPlugIn::onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
+ ALOGV("DrmPassthruPlugIn::onCloseDecryptSession() : %d", uniqueId);
+ if (NULL != decryptHandle) {
+ if (NULL != decryptHandle->decryptInfo) {
+ delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL;
+ }
+ delete decryptHandle; decryptHandle = NULL;
+ }
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* headerInfo) {
+ ALOGV("DrmPassthruPlugIn::onInitializeDecryptUnit() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onDecrypt(int uniqueId, DecryptHandle* decryptHandle,
+ int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
+ ALOGV("DrmPassthruPlugIn::onDecrypt() : %d", uniqueId);
+ /**
+ * As a workaround implementation passthru would copy the given
+ * encrypted buffer as it is to decrypted buffer. Note, decBuffer
+ * memory has to be allocated by the caller.
+ */
+ if (NULL != (*decBuffer) && 0 < (*decBuffer)->length) {
+ if ((*decBuffer)->length >= encBuffer->length) {
+ memcpy((*decBuffer)->data, encBuffer->data, encBuffer->length);
+ (*decBuffer)->length = encBuffer->length;
+ } else {
+ ALOGE("decBuffer size (%d) too small to hold %d bytes",
+ (*decBuffer)->length, encBuffer->length);
+ return DRM_ERROR_UNKNOWN;
+ }
+ }
+ return DRM_NO_ERROR;
+}
+
+status_t DrmPassthruPlugIn::onFinalizeDecryptUnit(
+ int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
+ ALOGV("DrmPassthruPlugIn::onFinalizeDecryptUnit() : %d", uniqueId);
+ return DRM_NO_ERROR;
+}
+
+ssize_t DrmPassthruPlugIn::onPread(int uniqueId, DecryptHandle* decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset) {
+ ALOGV("DrmPassthruPlugIn::onPread() : %d", uniqueId);
+ return 0;
+}
+
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
new file mode 100644
index 0000000..3fedea0
--- /dev/null
+++ b/include/camera/Camera.h
@@ -0,0 +1,196 @@
+/*
+ * 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_HARDWARE_CAMERA_H
+#define ANDROID_HARDWARE_CAMERA_H
+
+#include <utils/Timers.h>
+#include <gui/ISurfaceTexture.h>
+#include <system/camera.h>
+#include <camera/ICameraClient.h>
+#include <camera/ICameraRecordingProxy.h>
+#include <camera/ICameraRecordingProxyListener.h>
+
+namespace android {
+
+struct CameraInfo {
+ /**
+ * The direction that the camera faces to. It should be CAMERA_FACING_BACK
+ * or CAMERA_FACING_FRONT.
+ */
+ int facing;
+
+ /**
+ * The orientation of the camera image. The value is the angle that the
+ * camera image needs to be rotated clockwise so it shows correctly on the
+ * display in its natural orientation. It should be 0, 90, 180, or 270.
+ *
+ * For example, suppose a device has a naturally tall screen. The
+ * back-facing camera sensor is mounted in landscape. You are looking at
+ * the screen. If the top side of the camera sensor is aligned with the
+ * right edge of the screen in natural orientation, the value should be
+ * 90. If the top side of a front-facing camera sensor is aligned with the
+ * right of the screen, the value should be 270.
+ */
+ int orientation;
+};
+
+class ICameraService;
+class ICamera;
+class Surface;
+class Mutex;
+class String8;
+
+// ref-counted object for callbacks
+class CameraListener: virtual public RefBase
+{
+public:
+ virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
+ virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata) = 0;
+ virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) = 0;
+};
+
+class Camera : public BnCameraClient, public IBinder::DeathRecipient
+{
+public:
+ // construct a camera client from an existing remote
+ static sp<Camera> create(const sp<ICamera>& camera);
+ static int32_t getNumberOfCameras();
+ static status_t getCameraInfo(int cameraId,
+ struct CameraInfo* cameraInfo);
+ static sp<Camera> connect(int cameraId, bool force, bool keep);
+ virtual ~Camera();
+ void init();
+
+ status_t reconnect();
+ void disconnect();
+ status_t lock();
+ status_t unlock();
+
+ status_t getStatus() { return mStatus; }
+
+ // pass the buffered Surface to the camera service
+ status_t setPreviewDisplay(const sp<Surface>& surface);
+
+ // pass the buffered ISurfaceTexture to the camera service
+ status_t setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture);
+
+ // start preview mode, must call setPreviewDisplay first
+ status_t startPreview();
+
+ // stop preview mode
+ void stopPreview();
+
+ // get preview state
+ bool previewEnabled();
+
+ // start recording mode, must call setPreviewDisplay first
+ status_t startRecording();
+
+ // stop recording mode
+ void stopRecording();
+
+ // get recording state
+ bool recordingEnabled();
+
+ // release a recording frame
+ void releaseRecordingFrame(const sp<IMemory>& mem);
+
+ // autoFocus - status returned from callback
+ status_t autoFocus();
+
+ // cancel auto focus
+ status_t cancelAutoFocus();
+
+ // take a picture - picture returned from callback
+ status_t takePicture(int msgType);
+
+ // set preview/capture parameters - key/value pairs
+ status_t setParameters(const String8& params);
+
+ // get preview/capture parameters - key/value pairs
+ String8 getParameters() const;
+
+ // send command to camera driver
+ status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+
+ // tell camera hal to store meta data or real YUV in video buffers.
+ status_t storeMetaDataInBuffers(bool enabled);
+
+ void setListener(const sp<CameraListener>& listener);
+ void setRecordingProxyListener(const sp<ICameraRecordingProxyListener>& listener);
+ void setPreviewCallbackFlags(int preview_callback_flag);
+
+ sp<ICameraRecordingProxy> getRecordingProxy();
+
+ // ICameraClient interface
+ virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2);
+ virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata);
+ virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
+
+ sp<ICamera> remote();
+
+ class RecordingProxy : public BnCameraRecordingProxy
+ {
+ public:
+ RecordingProxy(const sp<Camera>& camera);
+
+ // ICameraRecordingProxy interface
+ virtual status_t startRecording(const sp<ICameraRecordingProxyListener>& listener);
+ virtual void stopRecording();
+ virtual void releaseRecordingFrame(const sp<IMemory>& mem);
+
+ private:
+ sp<Camera> mCamera;
+ };
+
+private:
+ Camera();
+ Camera(const Camera&);
+ Camera& operator=(const Camera);
+ virtual void binderDied(const wp<IBinder>& who);
+
+ class DeathNotifier: public IBinder::DeathRecipient
+ {
+ public:
+ DeathNotifier() {
+ }
+
+ virtual void binderDied(const wp<IBinder>& who);
+ };
+
+ static sp<DeathNotifier> mDeathNotifier;
+
+ // helper function to obtain camera service handle
+ static const sp<ICameraService>& getCameraService();
+
+ sp<ICamera> mCamera;
+ status_t mStatus;
+
+ sp<CameraListener> mListener;
+ sp<ICameraRecordingProxyListener> mRecordingProxyListener;
+
+ friend class DeathNotifier;
+
+ static Mutex mLock;
+ static sp<ICameraService> mCameraService;
+};
+
+}; // namespace android
+
+#endif
diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h
new file mode 100644
index 0000000..3d18837
--- /dev/null
+++ b/include/camera/ICamera.h
@@ -0,0 +1,122 @@
+/*
+ * 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_HARDWARE_ICAMERA_H
+#define ANDROID_HARDWARE_ICAMERA_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+#include <utils/String8.h>
+#include <camera/Camera.h>
+
+namespace android {
+
+class ICameraClient;
+class ISurfaceTexture;
+class Surface;
+
+class ICamera: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(Camera);
+
+ virtual void disconnect() = 0;
+
+ // connect new client with existing camera remote
+ virtual status_t connect(const sp<ICameraClient>& client) = 0;
+
+ // prevent other processes from using this ICamera interface
+ virtual status_t lock() = 0;
+
+ // allow other processes to use this ICamera interface
+ virtual status_t unlock() = 0;
+
+ // pass the buffered Surface to the camera service
+ virtual status_t setPreviewDisplay(const sp<Surface>& surface) = 0;
+
+ // pass the buffered ISurfaceTexture to the camera service
+ virtual status_t setPreviewTexture(
+ const sp<ISurfaceTexture>& surfaceTexture) = 0;
+
+ // set the preview callback flag to affect how the received frames from
+ // preview are handled.
+ virtual void setPreviewCallbackFlag(int flag) = 0;
+
+ // start preview mode, must call setPreviewDisplay first
+ virtual status_t startPreview() = 0;
+
+ // stop preview mode
+ virtual void stopPreview() = 0;
+
+ // get preview state
+ virtual bool previewEnabled() = 0;
+
+ // start recording mode
+ virtual status_t startRecording() = 0;
+
+ // stop recording mode
+ virtual void stopRecording() = 0;
+
+ // get recording state
+ virtual bool recordingEnabled() = 0;
+
+ // release a recording frame
+ virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0;
+
+ // auto focus
+ virtual status_t autoFocus() = 0;
+
+ // cancel auto focus
+ virtual status_t cancelAutoFocus() = 0;
+
+ /*
+ * take a picture.
+ * @param msgType the message type an application selectively turn on/off
+ * on a photo-by-photo basis. The supported message types are:
+ * CAMERA_MSG_SHUTTER, CAMERA_MSG_RAW_IMAGE, CAMERA_MSG_COMPRESSED_IMAGE,
+ * and CAMERA_MSG_POSTVIEW_FRAME. Any other message types will be ignored.
+ */
+ virtual status_t takePicture(int msgType) = 0;
+
+ // set preview/capture parameters - key/value pairs
+ virtual status_t setParameters(const String8& params) = 0;
+
+ // get preview/capture parameters - key/value pairs
+ virtual String8 getParameters() const = 0;
+
+ // send command to camera driver
+ virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
+
+ // tell the camera hal to store meta data or real YUV data in video buffers.
+ virtual status_t storeMetaDataInBuffers(bool enabled) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnCamera: public BnInterface<ICamera>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif
diff --git a/include/camera/ICameraClient.h b/include/camera/ICameraClient.h
new file mode 100644
index 0000000..b30aa7a
--- /dev/null
+++ b/include/camera/ICameraClient.h
@@ -0,0 +1,53 @@
+/*
+ * 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_HARDWARE_ICAMERA_APP_H
+#define ANDROID_HARDWARE_ICAMERA_APP_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+#include <utils/Timers.h>
+#include <system/camera.h>
+
+namespace android {
+
+class ICameraClient: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(CameraClient);
+
+ virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
+ virtual void dataCallback(int32_t msgType, const sp<IMemory>& data,
+ camera_frame_metadata_t *metadata) = 0;
+ virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnCameraClient: public BnInterface<ICameraClient>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif
diff --git a/include/camera/ICameraRecordingProxy.h b/include/camera/ICameraRecordingProxy.h
new file mode 100644
index 0000000..2aac284
--- /dev/null
+++ b/include/camera/ICameraRecordingProxy.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_HARDWARE_ICAMERA_RECORDING_PROXY_H
+#define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_H
+
+#include <binder/IInterface.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class ICameraRecordingProxyListener;
+class IMemory;
+class Parcel;
+
+/*
+ * The purpose of ICameraRecordingProxy and ICameraRecordingProxyListener is to
+ * allow applications using the camera during recording.
+ *
+ * Camera service allows only one client at a time. Since camcorder application
+ * needs to own the camera to do things like zoom, the media recorder cannot
+ * access the camera directly during recording. So ICameraRecordingProxy is a
+ * proxy of ICamera, which allows the media recorder to start/stop the recording
+ * and release recording frames. ICameraRecordingProxyListener is an interface
+ * that allows the recorder to receive video frames during recording.
+ *
+ * ICameraRecordingProxy
+ * startRecording()
+ * stopRecording()
+ * releaseRecordingFrame()
+ *
+ * ICameraRecordingProxyListener
+ * dataCallbackTimestamp()
+
+ * The camcorder app opens the camera and starts the preview. The app passes
+ * ICamera and ICameraRecordingProxy to the media recorder by
+ * MediaRecorder::setCamera(). The recorder uses ICamera to setup the camera in
+ * MediaRecorder::start(). After setup, the recorder disconnects from camera
+ * service. The recorder calls ICameraRecordingProxy::startRecording() and
+ * passes a ICameraRecordingProxyListener to the app. The app connects back to
+ * camera service and starts the recording. The app owns the camera and can do
+ * things like zoom. The media recorder receives the video frames from the
+ * listener and releases them by ICameraRecordingProxy::releaseRecordingFrame.
+ * The recorder calls ICameraRecordingProxy::stopRecording() to stop the
+ * recording.
+ *
+ * The call sequences are as follows:
+ * 1. The app: Camera.unlock().
+ * 2. The app: MediaRecorder.setCamera().
+ * 3. Start recording
+ * (1) The app: MediaRecorder.start().
+ * (2) The recorder: ICamera.unlock() and ICamera.disconnect().
+ * (3) The recorder: ICameraRecordingProxy.startRecording().
+ * (4) The app: ICamera.reconnect().
+ * (5) The app: ICamera.startRecording().
+ * 4. During recording
+ * (1) The recorder: receive frames from ICameraRecordingProxyListener.dataCallbackTimestamp()
+ * (2) The recorder: release frames by ICameraRecordingProxy.releaseRecordingFrame().
+ * 5. Stop recording
+ * (1) The app: MediaRecorder.stop()
+ * (2) The recorder: ICameraRecordingProxy.stopRecording().
+ * (3) The app: ICamera.stopRecording().
+ */
+
+class ICameraRecordingProxy: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(CameraRecordingProxy);
+
+ virtual status_t startRecording(const sp<ICameraRecordingProxyListener>& listener) = 0;
+ virtual void stopRecording() = 0;
+ virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnCameraRecordingProxy: public BnInterface<ICameraRecordingProxy>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif
diff --git a/include/camera/ICameraRecordingProxyListener.h b/include/camera/ICameraRecordingProxyListener.h
new file mode 100644
index 0000000..b6c0624
--- /dev/null
+++ b/include/camera/ICameraRecordingProxyListener.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_HARDWARE_ICAMERA_RECORDING_PROXY_LISTENER_H
+#define ANDROID_HARDWARE_ICAMERA_RECORDING_PROXY_LISTENER_H
+
+#include <binder/IInterface.h>
+#include <stdint.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+namespace android {
+
+class Parcel;
+class IMemory;
+
+class ICameraRecordingProxyListener: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(CameraRecordingProxyListener);
+
+ virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+ const sp<IMemory>& data) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnCameraRecordingProxyListener: public BnInterface<ICameraRecordingProxyListener>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
new file mode 100644
index 0000000..97e3169
--- /dev/null
+++ b/include/camera/ICameraService.h
@@ -0,0 +1,61 @@
+/*
+ * 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_HARDWARE_ICAMERASERVICE_H
+#define ANDROID_HARDWARE_ICAMERASERVICE_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+#include <camera/ICameraClient.h>
+#include <camera/ICamera.h>
+
+namespace android {
+
+class ICameraService : public IInterface
+{
+public:
+ enum {
+ GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION,
+ GET_CAMERA_INFO,
+ CONNECT
+ };
+
+public:
+ DECLARE_META_INTERFACE(CameraService);
+
+ virtual int32_t getNumberOfCameras() = 0;
+ virtual status_t getCameraInfo(int cameraId,
+ struct CameraInfo* cameraInfo) = 0;
+ virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient,
+ int cameraId, bool force, bool keep) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnCameraService: public BnInterface<ICameraService>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif
diff --git a/include/common_time/ICommonClock.h b/include/common_time/ICommonClock.h
new file mode 100644
index 0000000..d7073f1
--- /dev/null
+++ b/include/common_time/ICommonClock.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_ICOMMONCLOCK_H
+#define ANDROID_ICOMMONCLOCK_H
+
+#include <stdint.h>
+#include <linux/socket.h>
+
+#include <binder/IInterface.h>
+#include <binder/IServiceManager.h>
+
+namespace android {
+
+class ICommonClockListener : public IInterface {
+ public:
+ DECLARE_META_INTERFACE(CommonClockListener);
+
+ virtual void onTimelineChanged(uint64_t timelineID) = 0;
+};
+
+class BnCommonClockListener : public BnInterface<ICommonClockListener> {
+ public:
+ virtual status_t onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags = 0);
+};
+
+class ICommonClock : public IInterface {
+ public:
+ DECLARE_META_INTERFACE(CommonClock);
+
+ // Name of the ICommonClock service registered with the service manager.
+ static const String16 kServiceName;
+
+ // a reserved invalid timeline ID
+ static const uint64_t kInvalidTimelineID;
+
+ // a reserved invalid error estimate
+ static const int32_t kErrorEstimateUnknown;
+
+ enum State {
+ // the device just came up and is trying to discover the master
+ STATE_INITIAL,
+
+ // the device is a client of a master
+ STATE_CLIENT,
+
+ // the device is acting as master
+ STATE_MASTER,
+
+ // the device has lost contact with its master and needs to participate
+ // in the election of a new master
+ STATE_RONIN,
+
+ // the device is waiting for announcement of the newly elected master
+ STATE_WAIT_FOR_ELECTION,
+ };
+
+ virtual status_t isCommonTimeValid(bool* valid, uint32_t* timelineID) = 0;
+ virtual status_t commonTimeToLocalTime(int64_t commonTime,
+ int64_t* localTime) = 0;
+ virtual status_t localTimeToCommonTime(int64_t localTime,
+ int64_t* commonTime) = 0;
+ virtual status_t getCommonTime(int64_t* commonTime) = 0;
+ virtual status_t getCommonFreq(uint64_t* freq) = 0;
+ virtual status_t getLocalTime(int64_t* localTime) = 0;
+ virtual status_t getLocalFreq(uint64_t* freq) = 0;
+ virtual status_t getEstimatedError(int32_t* estimate) = 0;
+ virtual status_t getTimelineID(uint64_t* id) = 0;
+ virtual status_t getState(State* state) = 0;
+ virtual status_t getMasterAddr(struct sockaddr_storage* addr) = 0;
+
+ virtual status_t registerListener(
+ const sp<ICommonClockListener>& listener) = 0;
+ virtual status_t unregisterListener(
+ const sp<ICommonClockListener>& listener) = 0;
+
+ // Simple helper to make it easier to connect to the CommonClock service.
+ static inline sp<ICommonClock> getInstance() {
+ sp<IBinder> binder = defaultServiceManager()->checkService(
+ ICommonClock::kServiceName);
+ sp<ICommonClock> clk = interface_cast<ICommonClock>(binder);
+ return clk;
+ }
+};
+
+class BnCommonClock : public BnInterface<ICommonClock> {
+ public:
+ virtual status_t onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_ICOMMONCLOCK_H
diff --git a/include/common_time/ICommonTimeConfig.h b/include/common_time/ICommonTimeConfig.h
new file mode 100644
index 0000000..497b666
--- /dev/null
+++ b/include/common_time/ICommonTimeConfig.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_ICOMMONTIMECONFIG_H
+#define ANDROID_ICOMMONTIMECONFIG_H
+
+#include <stdint.h>
+#include <linux/socket.h>
+
+#include <binder/IInterface.h>
+#include <binder/IServiceManager.h>
+
+namespace android {
+
+class String16;
+
+class ICommonTimeConfig : public IInterface {
+ public:
+ DECLARE_META_INTERFACE(CommonTimeConfig);
+
+ // Name of the ICommonTimeConfig service registered with the service
+ // manager.
+ static const String16 kServiceName;
+
+ virtual status_t getMasterElectionPriority(uint8_t *priority) = 0;
+ virtual status_t setMasterElectionPriority(uint8_t priority) = 0;
+ virtual status_t getMasterElectionEndpoint(struct sockaddr_storage *addr) = 0;
+ virtual status_t setMasterElectionEndpoint(const struct sockaddr_storage *addr) = 0;
+ virtual status_t getMasterElectionGroupId(uint64_t *id) = 0;
+ virtual status_t setMasterElectionGroupId(uint64_t id) = 0;
+ virtual status_t getInterfaceBinding(String16& ifaceName) = 0;
+ virtual status_t setInterfaceBinding(const String16& ifaceName) = 0;
+ virtual status_t getMasterAnnounceInterval(int *interval) = 0;
+ virtual status_t setMasterAnnounceInterval(int interval) = 0;
+ virtual status_t getClientSyncInterval(int *interval) = 0;
+ virtual status_t setClientSyncInterval(int interval) = 0;
+ virtual status_t getPanicThreshold(int *threshold) = 0;
+ virtual status_t setPanicThreshold(int threshold) = 0;
+ virtual status_t getAutoDisable(bool *autoDisable) = 0;
+ virtual status_t setAutoDisable(bool autoDisable) = 0;
+ virtual status_t forceNetworklessMasterMode() = 0;
+
+ // Simple helper to make it easier to connect to the CommonTimeConfig service.
+ static inline sp<ICommonTimeConfig> getInstance() {
+ sp<IBinder> binder = defaultServiceManager()->checkService(
+ ICommonTimeConfig::kServiceName);
+ sp<ICommonTimeConfig> clk = interface_cast<ICommonTimeConfig>(binder);
+ return clk;
+ }
+};
+
+class BnCommonTimeConfig : public BnInterface<ICommonTimeConfig> {
+ public:
+ virtual status_t onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_ICOMMONTIMECONFIG_H
diff --git a/include/common_time/cc_helper.h b/include/common_time/cc_helper.h
new file mode 100644
index 0000000..8c4d5c0
--- /dev/null
+++ b/include/common_time/cc_helper.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 __CC_HELPER_H__
+#define __CC_HELPER_H__
+
+#include <stdint.h>
+#include <common_time/ICommonClock.h>
+#include <utils/threads.h>
+
+namespace android {
+
+// CCHelper is a simple wrapper class to help with centralizing access to the
+// Common Clock service and implementing lifetime managment, as well as to
+// implement a simple policy of making a basic attempt to reconnect to the
+// common clock service when things go wrong.
+//
+// On platforms which run the native common_time service in auto-disable mode,
+// the service will go into networkless mode whenever it has no active clients.
+// It tracks active clients using registered CommonClockListeners (the callback
+// interface for onTimelineChanged) since this provides a convienent death
+// handler notification for when the service's clients die unexpectedly. This
+// means that users of the common time service should really always have a
+// CommonClockListener, unless they know that the time service is not running in
+// auto disabled mode, or that there is at least one other registered listener
+// active in the system. The CCHelper makes this a little easier by sharing a
+// ref counted ICommonClock interface across all clients and automatically
+// registering and unregistering a listener whenever there are CCHelper
+// instances active in the process.
+class CCHelper {
+ public:
+ CCHelper();
+ ~CCHelper();
+
+ status_t isCommonTimeValid(bool* valid, uint32_t* timelineID);
+ status_t commonTimeToLocalTime(int64_t commonTime, int64_t* localTime);
+ status_t localTimeToCommonTime(int64_t localTime, int64_t* commonTime);
+ status_t getCommonTime(int64_t* commonTime);
+ status_t getCommonFreq(uint64_t* freq);
+ status_t getLocalTime(int64_t* localTime);
+ status_t getLocalFreq(uint64_t* freq);
+
+ private:
+ class CommonClockListener : public BnCommonClockListener {
+ public:
+ void onTimelineChanged(uint64_t timelineID);
+ };
+
+ static bool verifyClock_l();
+
+ static Mutex lock_;
+ static sp<ICommonClock> common_clock_;
+ static sp<ICommonClockListener> common_clock_listener_;
+ static uint32_t ref_count_;
+};
+
+
+} // namespace android
+#endif // __CC_HELPER_H__
diff --git a/include/common_time/local_clock.h b/include/common_time/local_clock.h
new file mode 100644
index 0000000..384c3de
--- /dev/null
+++ b/include/common_time/local_clock.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 __LOCAL_CLOCK_H__
+#define __LOCAL_CLOCK_H__
+
+#include <stdint.h>
+
+#include <hardware/local_time_hal.h>
+#include <utils/Errors.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class LocalClock {
+ public:
+ LocalClock();
+
+ bool initCheck();
+
+ int64_t getLocalTime();
+ uint64_t getLocalFreq();
+ status_t setLocalSlew(int16_t rate);
+ int32_t getDebugLog(struct local_time_debug_event* records,
+ int max_records);
+
+ private:
+ static Mutex dev_lock_;
+ static local_time_hw_device_t* dev_;
+};
+
+} // namespace android
+#endif // __LOCAL_CLOCK_H__
diff --git a/include/drm/DrmConstraints.h b/include/drm/DrmConstraints.h
new file mode 100644
index 0000000..a9ec942
--- /dev/null
+++ b/include/drm/DrmConstraints.h
@@ -0,0 +1,183 @@
+/*
+ * 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 __DRM_CONSTRAINTS_H__
+#define __DRM_CONSTRAINTS_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which contains the constraints information.
+ *
+ * As a result of DrmManagerClient::getConstraints(const String8*, const int)
+ * an instance of DrmConstraints would be returned.
+ *
+ */
+class DrmConstraints {
+public:
+ /**
+ * The following variables are replica of android.drm.DrmStore.ConstraintsColumns
+ * Any changes should also be incorporated with Java Layer as well
+ */
+ /**
+ * The max repeat count
+ */
+ static const String8 MAX_REPEAT_COUNT;
+ /**
+ * The remaining repeat count
+ */
+ static const String8 REMAINING_REPEAT_COUNT;
+
+ /**
+ * The time before which the protected file can not be played/viewed
+ */
+ static const String8 LICENSE_START_TIME;
+
+ /**
+ * The time after which the protected file can not be played/viewed
+ */
+ static const String8 LICENSE_EXPIRY_TIME;
+
+ /**
+ * The available time for license
+ */
+ static const String8 LICENSE_AVAILABLE_TIME;
+
+ /**
+ * The data stream for extended metadata
+ */
+ static const String8 EXTENDED_METADATA;
+
+public:
+ /**
+ * Iterator for key
+ */
+ class KeyIterator {
+ friend class DrmConstraints;
+ private:
+ KeyIterator(DrmConstraints* drmConstraints)
+ : mDrmConstraints(drmConstraints), mIndex(0) {}
+
+ public:
+ KeyIterator(const KeyIterator& keyIterator);
+ KeyIterator& operator=(const KeyIterator& keyIterator);
+ virtual ~KeyIterator() {}
+
+ public:
+ bool hasNext();
+ const String8& next();
+
+ private:
+ DrmConstraints* mDrmConstraints;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator for constraints
+ */
+ class Iterator {
+ friend class DrmConstraints;
+ private:
+ Iterator(DrmConstraints* drmConstraints)
+ : mDrmConstraints(drmConstraints), mIndex(0) {}
+
+ public:
+ Iterator(const Iterator& iterator);
+ Iterator& operator=(const Iterator& iterator);
+ virtual ~Iterator() {}
+
+ public:
+ bool hasNext();
+ String8 next();
+
+ private:
+ DrmConstraints* mDrmConstraints;
+ unsigned int mIndex;
+ };
+
+public:
+ DrmConstraints() {}
+ virtual ~DrmConstraints() {
+ DrmConstraints::KeyIterator keyIt = this->keyIterator();
+
+ while (keyIt.hasNext()) {
+ String8 key = keyIt.next();
+ const char* value = this->getAsByteArray(&key);
+ if (NULL != value) {
+ delete[] value;
+ value = NULL;
+ }
+ }
+ mConstraintMap.clear();
+ }
+public:
+ /**
+ * Returns the number of constraints contained in this instance
+ *
+ * @return Number of constraints
+ */
+ int getCount(void) const;
+
+ /**
+ * Adds constraint information as <key, value> pair to this instance
+ *
+ * @param[in] key Key to add
+ * @param[in] value Value to add
+ * @return Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t put(const String8* key, const char* value);
+
+ /**
+ * Retrieves the value of given key
+ *
+ * @param key Key whose value to be retrieved
+ * @return The value
+ */
+ String8 get(const String8& key) const;
+
+ /**
+ * Retrieves the value as byte array of given key
+ * @param key Key whose value to be retrieved as byte array
+ * @return The byte array value
+ */
+ const char* getAsByteArray(const String8* key) const;
+
+ /**
+ * Returns KeyIterator object to walk through the keys associated with this instance
+ *
+ * @return KeyIterator object
+ */
+ KeyIterator keyIterator();
+
+ /**
+ * Returns Iterator object to walk through the values associated with this instance
+ *
+ * @return Iterator object
+ */
+ Iterator iterator();
+private:
+ const char* getValue(const String8* key) const;
+private:
+ typedef KeyedVector<String8, const char*> DrmConstraintsMap;
+ DrmConstraintsMap mConstraintMap;
+};
+
+};
+
+#endif /* __DRM_CONSTRAINTS_H__ */
+
diff --git a/include/drm/DrmConvertedStatus.h b/include/drm/DrmConvertedStatus.h
new file mode 100644
index 0000000..679e48d
--- /dev/null
+++ b/include/drm/DrmConvertedStatus.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 __DRM_CONVERTED_STATUS_H__
+#define __DRM_CONVERTED_STATUS_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which wraps the status of the conversion, the converted
+ * data/checksum data and the offset. Offset is going to be used in the case of close
+ * session where the agent will inform where the header and body signature should be added
+ *
+ * As a result of DrmManagerClient::convertData(int, const DrmBuffer*) and
+ * DrmManagerClient::closeConvertSession(int) an instance of DrmConvertedStatus
+ * would be returned.
+ *
+ */
+class DrmConvertedStatus {
+public:
+ // Should be in sync with DrmConvertedStatus.java
+ static const int STATUS_OK = 1;
+ static const int STATUS_INPUTDATA_ERROR = 2;
+ static const int STATUS_ERROR = 3;
+
+public:
+ /**
+ * Constructor for DrmConvertedStatus
+ *
+ * @param[in] _statusCode Status of the conversion
+ * @param[in] _convertedData Converted data/checksum data
+ * @param[in] _offset Offset value
+ */
+ DrmConvertedStatus(int _statusCode, const DrmBuffer* _convertedData, int _offset);
+
+ /**
+ * Destructor for DrmConvertedStatus
+ */
+ virtual ~DrmConvertedStatus() {
+
+ }
+
+public:
+ int statusCode;
+ const DrmBuffer* convertedData;
+ int offset;
+};
+
+};
+
+#endif /* __DRM_CONVERTED_STATUS_H__ */
+
diff --git a/include/drm/DrmInfo.h b/include/drm/DrmInfo.h
new file mode 100644
index 0000000..7b48541
--- /dev/null
+++ b/include/drm/DrmInfo.h
@@ -0,0 +1,176 @@
+/*
+ * 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 __DRM_INFO_H__
+#define __DRM_INFO_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class in which necessary information required to transact
+ * between device and online DRM server is described. DRM Framework achieves
+ * server registration, license acquisition and any other server related transaction
+ * by passing an instance of this class to DrmManagerClient::processDrmInfo(const DrmInfo*).
+ *
+ * The Caller can retrieve the DrmInfo instance by using
+ * DrmManagerClient::acquireDrmInfo(const DrmInfoRequest*) by passing DrmInfoRequest instance.
+ *
+ */
+class DrmInfo {
+public:
+ /**
+ * Constructor for DrmInfo
+ *
+ * @param[in] infoType Type of information
+ * @param[in] drmBuffer Trigger data
+ * @param[in] mimeType MIME type
+ */
+ DrmInfo(int infoType, const DrmBuffer& drmBuffer, const String8& mimeType);
+
+ /**
+ * Destructor for DrmInfo
+ */
+ virtual ~DrmInfo() {}
+
+public:
+ /**
+ * Iterator for key
+ */
+ class KeyIterator {
+ friend class DrmInfo;
+
+ private:
+ KeyIterator(const DrmInfo* drmInfo)
+ : mDrmInfo(const_cast <DrmInfo*> (drmInfo)), mIndex(0) {}
+
+ public:
+ KeyIterator(const KeyIterator& keyIterator);
+ KeyIterator& operator=(const KeyIterator& keyIterator);
+ virtual ~KeyIterator() {}
+
+ public:
+ bool hasNext();
+ const String8& next();
+
+ private:
+ DrmInfo* mDrmInfo;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator
+ */
+ class Iterator {
+ friend class DrmInfo;
+
+ private:
+ Iterator(const DrmInfo* drmInfo)
+ : mDrmInfo(const_cast <DrmInfo*> (drmInfo)), mIndex(0) {}
+
+ public:
+ Iterator(const Iterator& iterator);
+ Iterator& operator=(const Iterator& iterator);
+ virtual ~Iterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ DrmInfo* mDrmInfo;
+ unsigned int mIndex;
+ };
+
+public:
+ /**
+ * Returns information type associated with this instance
+ *
+ * @return Information type
+ */
+ int getInfoType(void) const;
+
+ /**
+ * Returns MIME type associated with this instance
+ *
+ * @return MIME type
+ */
+ String8 getMimeType(void) const;
+
+ /**
+ * Returns the trigger data associated with this instance
+ *
+ * @return Trigger data
+ */
+ const DrmBuffer& getData(void) const;
+
+ /**
+ * Returns the number of attributes contained in this instance
+ *
+ * @return Number of attributes
+ */
+ int getCount(void) const;
+
+ /**
+ * Adds optional information as <key, value> pair to this instance
+ *
+ * @param[in] key Key to add
+ * @param[in] value Value to add
+ * @return Returns the error code
+ */
+ status_t put(const String8& key, const String8& value);
+
+ /**
+ * Retrieves the value of given key
+ *
+ * @param key Key whose value to be retrieved
+ * @return The value
+ */
+ String8 get(const String8& key) const;
+
+ /**
+ * Returns KeyIterator object to walk through the keys associated with this instance
+ *
+ * @return KeyIterator object
+ */
+ KeyIterator keyIterator() const;
+
+ /**
+ * Returns Iterator object to walk through the values associated with this instance
+ *
+ * @return Iterator object
+ */
+ Iterator iterator() const;
+
+ /**
+ * Returns index of the given key
+ *
+ * @return index
+ */
+ int indexOfKey(const String8& key) const;
+
+protected:
+ int mInfoType;
+ DrmBuffer mData;
+ String8 mMimeType;
+ KeyedVector<String8, String8> mAttributes;
+};
+
+};
+
+#endif /* __DRM_INFO_H__ */
+
diff --git a/include/drm/DrmInfoEvent.h b/include/drm/DrmInfoEvent.h
new file mode 100644
index 0000000..dfca228
--- /dev/null
+++ b/include/drm/DrmInfoEvent.h
@@ -0,0 +1,118 @@
+/*
+ * 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 __DRM_INFO_EVENT_H__
+#define __DRM_INFO_EVENT_H__
+
+namespace android {
+
+class String8;
+
+/**
+ * This is an entity class which would be passed to caller in
+ * DrmManagerClient::OnInfoListener::onInfo(const DrmInfoEvent&).
+ */
+class DrmInfoEvent {
+public:
+ /**
+ * The following constant values should be in sync with DrmInfoEvent.java
+ */
+ //! TYPE_ALREADY_REGISTERED_BY_ANOTHER_ACCOUNT, when registration has been
+ //! already done by another account ID.
+ static const int TYPE_ALREADY_REGISTERED_BY_ANOTHER_ACCOUNT = 1;
+ //! TYPE_REMOVE_RIGHTS, when the rights needs to be removed completely.
+ static const int TYPE_REMOVE_RIGHTS = 2;
+ //! TYPE_RIGHTS_INSTALLED, when the rights are downloaded and installed ok.
+ static const int TYPE_RIGHTS_INSTALLED = 3;
+ //! TYPE_WAIT_FOR_RIGHTS, rights object is on it's way to phone,
+ //! wait before calling checkRights again
+ static const int TYPE_WAIT_FOR_RIGHTS = 4;
+ //! TYPE_ACCOUNT_ALREADY_REGISTERED, when registration has been
+ //! already done for the given account.
+ static const int TYPE_ACCOUNT_ALREADY_REGISTERED = 5;
+ //! TYPE_RIGHTS_REMOVED, when the rights has been removed.
+ static const int TYPE_RIGHTS_REMOVED = 6;
+
+ /**
+ * The following constant values should be in sync with DrmErrorEvent.java
+ */
+ //! TYPE_RIGHTS_NOT_INSTALLED, when something went wrong installing the rights
+ static const int TYPE_RIGHTS_NOT_INSTALLED = 2001;
+ //! TYPE_RIGHTS_RENEWAL_NOT_ALLOWED, when the server rejects renewal of rights
+ static const int TYPE_RIGHTS_RENEWAL_NOT_ALLOWED = 2002;
+ //! TYPE_NOT_SUPPORTED, when answer from server can not be handled by the native agent
+ static const int TYPE_NOT_SUPPORTED = 2003;
+ //! TYPE_OUT_OF_MEMORY, when memory allocation fail during renewal.
+ //! Can in the future perhaps be used to trigger garbage collector
+ static const int TYPE_OUT_OF_MEMORY = 2004;
+ //! TYPE_NO_INTERNET_CONNECTION, when the Internet connection is missing and no attempt
+ //! can be made to renew rights
+ static const int TYPE_NO_INTERNET_CONNECTION = 2005;
+ //! TYPE_PROCESS_DRM_INFO_FAILED, when failed to process DrmInfo.
+ static const int TYPE_PROCESS_DRM_INFO_FAILED = 2006;
+ //! TYPE_REMOVE_ALL_RIGHTS_FAILED, when failed to remove all the rights objects
+ //! associated with all DRM schemes.
+ static const int TYPE_REMOVE_ALL_RIGHTS_FAILED = 2007;
+ //! TYPE_ACQUIRE_DRM_INFO_FAILED, when failed to acquire DrmInfo.
+ static const int TYPE_ACQUIRE_DRM_INFO_FAILED = 2008;
+
+public:
+ /**
+ * Constructor for DrmInfoEvent
+ *
+ * @param[in] uniqueId Unique session identifier
+ * @param[in] infoType Type of information
+ * @param[in] message Message description
+ */
+ DrmInfoEvent(int uniqueId, int infoType, const String8 message);
+
+ /**
+ * Destructor for DrmInfoEvent
+ */
+ virtual ~DrmInfoEvent() {}
+
+public:
+ /**
+ * Returns the Unique Id associated with this instance
+ *
+ * @return Unique Id
+ */
+ int getUniqueId() const;
+
+ /**
+ * Returns the Type of information associated with this object
+ *
+ * @return Type of information
+ */
+ int getType() const;
+
+ /**
+ * Returns the message description associated with this object
+ *
+ * @return Message description
+ */
+ const String8 getMessage() const;
+
+private:
+ int mUniqueId;
+ int mInfoType;
+ const String8 mMessage;
+};
+
+};
+
+#endif /* __DRM_INFO_EVENT_H__ */
+
diff --git a/include/drm/DrmInfoRequest.h b/include/drm/DrmInfoRequest.h
new file mode 100644
index 0000000..3e48ecc
--- /dev/null
+++ b/include/drm/DrmInfoRequest.h
@@ -0,0 +1,177 @@
+/*
+ * 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 __DRM_INFO_REQUEST_H__
+#define __DRM_INFO_REQUEST_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class used to pass required parameters to get
+ * the necessary information to communicate with online DRM server
+ *
+ * An instance of this class is passed to
+ * DrmManagerClient::acquireDrmInfo(const DrmInfoRequest*) to get the
+ * instance of DrmInfo.
+ *
+ */
+class DrmInfoRequest {
+public:
+ // Changes in following constants should be in sync with DrmInfoRequest.java
+ static const int TYPE_REGISTRATION_INFO = 1;
+ static const int TYPE_UNREGISTRATION_INFO = 2;
+ static const int TYPE_RIGHTS_ACQUISITION_INFO = 3;
+ static const int TYPE_RIGHTS_ACQUISITION_PROGRESS_INFO = 4;
+
+ /**
+ * Key to pass the unique id for the account or the user
+ */
+ static const String8 ACCOUNT_ID;
+ /**
+ * Key to pass the subscription id
+ */
+ static const String8 SUBSCRIPTION_ID;
+
+public:
+ /**
+ * Constructor for DrmInfoRequest
+ *
+ * @param[in] infoType Type of information
+ * @param[in] mimeType MIME type
+ */
+ DrmInfoRequest(int infoType, const String8& mimeType);
+
+ /**
+ * Destructor for DrmInfoRequest
+ */
+ virtual ~DrmInfoRequest() {}
+
+public:
+ /**
+ * Iterator for key
+ */
+ class KeyIterator {
+ friend class DrmInfoRequest;
+
+ private:
+ KeyIterator(const DrmInfoRequest* drmInfoRequest)
+ : mDrmInfoRequest(const_cast <DrmInfoRequest*> (drmInfoRequest)), mIndex(0) {}
+
+ public:
+ KeyIterator(const KeyIterator& keyIterator);
+ KeyIterator& operator=(const KeyIterator& keyIterator);
+ virtual ~KeyIterator() {}
+
+ public:
+ bool hasNext();
+ const String8& next();
+
+ private:
+ DrmInfoRequest* mDrmInfoRequest;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator
+ */
+ class Iterator {
+ friend class DrmInfoRequest;
+
+ private:
+ Iterator(const DrmInfoRequest* drmInfoRequest)
+ : mDrmInfoRequest(const_cast <DrmInfoRequest*> (drmInfoRequest)), mIndex(0) {}
+
+ public:
+ Iterator(const Iterator& iterator);
+ Iterator& operator=(const Iterator& iterator);
+ virtual ~Iterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ DrmInfoRequest* mDrmInfoRequest;
+ unsigned int mIndex;
+ };
+
+public:
+ /**
+ * Returns information type associated with this instance
+ *
+ * @return Information type
+ */
+ int getInfoType(void) const;
+
+ /**
+ * Returns MIME type associated with this instance
+ *
+ * @return MIME type
+ */
+ String8 getMimeType(void) const;
+
+ /**
+ * Returns the number of entries in DrmRequestInfoMap
+ *
+ * @return Number of entries
+ */
+ int getCount(void) const;
+
+ /**
+ * Adds optional information as <key, value> pair to this instance
+ *
+ * @param[in] key Key to add
+ * @param[in] value Value to add
+ * @return Returns the error code
+ */
+ status_t put(const String8& key, const String8& value);
+
+ /**
+ * Retrieves the value of given key
+ *
+ * @param key Key whose value to be retrieved
+ * @return The value
+ */
+ String8 get(const String8& key) const;
+
+ /**
+ * Returns KeyIterator object to walk through the keys associated with this instance
+ *
+ * @return KeyIterator object
+ */
+ KeyIterator keyIterator() const;
+
+ /**
+ * Returns Iterator object to walk through the values associated with this instance
+ *
+ * @return Iterator object
+ */
+ Iterator iterator() const;
+
+private:
+ int mInfoType;
+ String8 mMimeType;
+
+ typedef KeyedVector<String8, String8> DrmRequestInfoMap;
+ DrmRequestInfoMap mRequestInformationMap;
+};
+
+};
+
+#endif /* __DRM_INFO_REQUEST_H__ */
+
diff --git a/include/drm/DrmInfoStatus.h b/include/drm/DrmInfoStatus.h
new file mode 100644
index 0000000..88c0f40
--- /dev/null
+++ b/include/drm/DrmInfoStatus.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 __DRM_INFO_STATUS_H__
+#define __DRM_INFO_STATUS_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which wraps the result of communication between device
+ * and online DRM server.
+ *
+ * As a result of DrmManagerClient::processDrmInfo(const DrmInfo*) an instance of
+ * DrmInfoStatus would be returned. This class holds DrmBuffer which could be
+ * used to instantiate DrmRights in license acquisition.
+ *
+ */
+class DrmInfoStatus {
+public:
+ // Should be in sync with DrmInfoStatus.java
+ static const int STATUS_OK = 1;
+ static const int STATUS_ERROR = 2;
+
+public:
+ /**
+ * Constructor for DrmInfoStatus
+ *
+ * @param[in] _statusCode Status of the communication
+ * @param[in] _infoType Type of the DRM information processed
+ * @param[in] _drmBuffer Rights information
+ * @param[in] _mimeType MIME type
+ */
+ DrmInfoStatus(int _statusCode, int _infoType, const DrmBuffer* _drmBuffer, const String8& _mimeType);
+
+ /**
+ * Destructor for DrmInfoStatus
+ */
+ virtual ~DrmInfoStatus() {
+
+ }
+
+public:
+ int statusCode;
+ int infoType;
+ const DrmBuffer* drmBuffer;
+ String8 mimeType;
+};
+
+};
+
+#endif /* __DRM_INFO_STATUS_H__ */
+
diff --git a/include/drm/DrmManagerClient.h b/include/drm/DrmManagerClient.h
new file mode 100644
index 0000000..c47bbfb
--- /dev/null
+++ b/include/drm/DrmManagerClient.h
@@ -0,0 +1,379 @@
+/*
+ * 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 __DRM_MANAGER_CLIENT_H__
+#define __DRM_MANAGER_CLIENT_H__
+
+#include <utils/threads.h>
+#include <binder/IInterface.h>
+#include "drm_framework_common.h"
+
+namespace android {
+
+class DrmInfo;
+class DrmRights;
+class DrmMetadata;
+class DrmInfoEvent;
+class DrmInfoStatus;
+class DrmInfoRequest;
+class DrmSupportInfo;
+class DrmConstraints;
+class DrmConvertedStatus;
+class DrmManagerClientImpl;
+
+/**
+ * The Native application will instantiate this class and access DRM Framework
+ * services through this class.
+ *
+ */
+class DrmManagerClient {
+public:
+ DrmManagerClient();
+
+ virtual ~DrmManagerClient();
+
+public:
+ class OnInfoListener: virtual public RefBase {
+
+ public:
+ virtual ~OnInfoListener() {}
+
+ public:
+ virtual void onInfo(const DrmInfoEvent& event) = 0;
+ };
+
+/**
+ * APIs which will be used by native modules (e.g. StageFright)
+ *
+ */
+public:
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] fd File descriptor of the protected content to be decrypted
+ * @param[in] offset Start position of the content
+ * @param[in] length The length of the protected content
+ * @param[in] mime Mime type of the protected content if it is not NULL or empty
+ * @return
+ * Handle for the decryption session
+ */
+ sp<DecryptHandle> openDecryptSession(int fd, off64_t offset, off64_t length, const char* mime);
+
+ /**
+ * Open the decrypt session to decrypt the given protected content
+ *
+ * @param[in] uri Path of the protected content to be decrypted
+ * @param[in] mime Mime type of the protected content if it is not NULL or empty
+ * @return
+ * Handle for the decryption session
+ */
+ sp<DecryptHandle> openDecryptSession(const char* uri, const char* mime);
+
+ /**
+ * Close the decrypt session for the given handle
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t closeDecryptSession(sp<DecryptHandle> &decryptHandle);
+
+ /**
+ * Consumes the rights for a content.
+ * If the reserve parameter is true the rights is reserved until the same
+ * application calls this api again with the reserve parameter set to false.
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] action Action to perform. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] reserve True if the rights should be reserved.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure.
+ * In case license has been expired, DRM_ERROR_LICENSE_EXPIRED will be returned.
+ */
+ status_t consumeRights(sp<DecryptHandle> &decryptHandle, int action, bool reserve);
+
+ /**
+ * Informs the DRM engine about the playback actions performed on the DRM files.
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE)
+ * @param[in] position Position in the file (in milliseconds) where the start occurs.
+ * Only valid together with Playback::START.
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t setPlaybackStatus(
+ sp<DecryptHandle> &decryptHandle, int playbackStatus, int64_t position);
+
+ /**
+ * Initialize decryption for the given unit of the protected content
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] headerInfo Information for initializing decryption of this decrypUnit
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t initializeDecryptUnit(
+ sp<DecryptHandle> &decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo);
+
+ /**
+ * Decrypt the protected content buffers for the given unit
+ * This method will be called any number of times, based on number of
+ * encrypted streams received from application.
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @param[in] encBuffer Encrypted data block
+ * @param[out] decBuffer Decrypted data block
+ * @param[in] IV Optional buffer
+ * @return status_t
+ * Returns the error code for this API
+ * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED
+ * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED,
+ * DRM_ERROR_DECRYPT for failure.
+ */
+ status_t decrypt(
+ sp<DecryptHandle> &decryptHandle, int decryptUnitId,
+ const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV = NULL);
+
+ /**
+ * Finalize decryption for the given unit of the protected content
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[in] decryptUnitId ID which specifies decryption unit, such as track ID
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t finalizeDecryptUnit(
+ sp<DecryptHandle> &decryptHandle, int decryptUnitId);
+
+ /**
+ * Reads the specified number of bytes from an open DRM file.
+ *
+ * @param[in] decryptHandle Handle for the decryption session
+ * @param[out] buffer Reference to the buffer that should receive the read data.
+ * @param[in] numBytes Number of bytes to read.
+ * @param[in] offset Offset with which to update the file position.
+ *
+ * @return Number of bytes read. Returns -1 for Failure.
+ */
+ ssize_t pread(sp<DecryptHandle> &decryptHandle,
+ void* buffer, ssize_t numBytes, off64_t offset);
+
+ /**
+ * Validates whether an action on the DRM content is allowed or not.
+ *
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to validate. (Action::DEFAULT, Action::PLAY, etc)
+ * @param[in] description Detailed description of the action
+ * @return true if the action is allowed.
+ */
+ bool validateAction(const String8& path, int action, const ActionDescription& description);
+
+/**
+ * APIs which are just the underlying implementation for the Java API
+ *
+ */
+public:
+ /**
+ * Register a callback to be invoked when the caller required to
+ * receive necessary information
+ *
+ * @param[in] infoListener Listener
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t setOnInfoListener(const sp<DrmManagerClient::OnInfoListener>& infoListener);
+
+ /**
+ * Get constraint information associated with input content
+ *
+ * @param[in] path Path of the protected content
+ * @param[in] action Actions defined such as,
+ * Action::DEFAULT, Action::PLAY, etc
+ * @return DrmConstraints
+ * key-value pairs of constraint are embedded in it
+ * @note
+ * In case of error, return NULL
+ */
+ DrmConstraints* getConstraints(const String8* path, const int action);
+
+ /**
+ * Get metadata information associated with input content
+ *
+ * @param[in] path Path of the protected content
+ * @return DrmMetadata
+ * key-value pairs of metadata
+ * @note
+ * In case of error, return NULL
+ */
+ DrmMetadata* getMetadata(const String8* path);
+
+ /**
+ * Check whether the given mimetype or path can be handled
+ *
+ * @param[in] path Path of the content needs to be handled
+ * @param[in] mimetype Mimetype of the content needs to be handled
+ * @return
+ * True if DrmManager can handle given path or mime type.
+ */
+ bool canHandle(const String8& path, const String8& mimeType);
+
+ /**
+ * Executes given drm information based on its type
+ *
+ * @param[in] drmInfo Information needs to be processed
+ * @return DrmInfoStatus
+ * instance as a result of processing given input
+ */
+ DrmInfoStatus* processDrmInfo(const DrmInfo* drmInfo);
+
+ /**
+ * Retrieves necessary information for registration, unregistration or rights
+ * acquisition information.
+ *
+ * @param[in] drmInfoRequest Request information to retrieve drmInfo
+ * @return DrmInfo
+ * instance as a result of processing given input
+ */
+ DrmInfo* acquireDrmInfo(const DrmInfoRequest* drmInfoRequest);
+
+ /**
+ * Save DRM rights to specified rights path
+ * and make association with content path
+ *
+ * @param[in] drmRights DrmRights to be saved
+ * @param[in] rightsPath File path where rights to be saved
+ * @param[in] contentPath File path where content was saved
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t saveRights(
+ const DrmRights& drmRights, const String8& rightsPath, const String8& contentPath);
+
+ /**
+ * Retrieves the mime type embedded inside the original content
+ *
+ * @param[in] path the path of the protected content
+ * @return String8
+ * Returns mime-type of the original content, such as "video/mpeg"
+ */
+ String8 getOriginalMimeType(const String8& path);
+
+ /**
+ * Retrieves the type of the protected object (content, rights, etc..)
+ * by using specified path or mimetype. At least one parameter should be non null
+ * to retrieve DRM object type
+ *
+ * @param[in] path Path of the content or null.
+ * @param[in] mimeType Mime type of the content or null.
+ * @return type of the DRM content,
+ * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT
+ */
+ int getDrmObjectType(const String8& path, const String8& mimeType);
+
+ /**
+ * Check whether the given content has valid rights or not
+ *
+ * @param[in] path Path of the protected content
+ * @param[in] action Action to perform
+ * @return the status of the rights for the protected content,
+ * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc.
+ */
+ int checkRightsStatus(const String8& path, int action);
+
+ /**
+ * Removes the rights associated with the given protected content
+ *
+ * @param[in] path Path of the protected content
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t removeRights(const String8& path);
+
+ /**
+ * Removes all the rights information of each plug-in associated with
+ * DRM framework. Will be used in master reset
+ *
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t removeAllRights();
+
+ /**
+ * This API is for Forward Lock DRM.
+ * Each time the application tries to download a new DRM file
+ * which needs to be converted, then the application has to
+ * begin with calling this API.
+ *
+ * @param[in] convertId Handle for the convert session
+ * @param[in] mimeType Description/MIME type of the input data packet
+ * @return Return handle for the convert session
+ */
+ int openConvertSession(const String8& mimeType);
+
+ /**
+ * Passes the input data which need to be converted. The resultant
+ * converted data and the status is returned in the DrmConvertedInfo
+ * object. This method will be called each time there are new block
+ * of data received by the application.
+ *
+ * @param[in] convertId Handle for the convert session
+ * @param[in] inputData Input Data which need to be converted
+ * @return Return object contains the status of the data conversion,
+ * the output converted data and offset. In this case the
+ * application will ignore the offset information.
+ */
+ DrmConvertedStatus* convertData(int convertId, const DrmBuffer* inputData);
+
+ /**
+ * When there is no more data which need to be converted or when an
+ * error occurs that time the application has to inform the Drm agent
+ * via this API. Upon successful conversion of the complete data,
+ * the agent will inform that where the header and body signature
+ * should be added. This signature appending is needed to integrity
+ * protect the converted file.
+ *
+ * @param[in] convertId Handle for the convert session
+ * @return Return object contains the status of the data conversion,
+ * the header and body signature data. It also informs
+ * the application on which offset these signature data
+ * should be appended.
+ */
+ DrmConvertedStatus* closeConvertSession(int convertId);
+
+ /**
+ * Retrieves all DrmSupportInfo instance that native DRM framework can handle.
+ * This interface is meant to be used by JNI layer
+ *
+ * @param[out] length Number of elements in drmSupportInfoArray
+ * @param[out] drmSupportInfoArray Array contains all DrmSupportInfo
+ * that native DRM framework can handle
+ * @return status_t
+ * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t getAllSupportInfo(int* length, DrmSupportInfo** drmSupportInfoArray);
+
+private:
+ int mUniqueId;
+ sp<DrmManagerClientImpl> mDrmManagerClientImpl;
+};
+
+};
+
+#endif /* __DRM_MANAGER_CLIENT_H__ */
+
diff --git a/include/drm/DrmMetadata.h b/include/drm/DrmMetadata.h
new file mode 100644
index 0000000..2c7538a
--- /dev/null
+++ b/include/drm/DrmMetadata.h
@@ -0,0 +1,111 @@
+/*
+ * 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 __DRM_METADATA_H__
+#define __DRM_METADATA_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which contains the constraints information.
+ *
+ * As a result of DrmManagerClient::getMetadata(const String8*)
+ * an instance of DrmMetadata would be returned.
+ */
+class DrmMetadata {
+public:
+ /**
+ * Iterator for key
+ */
+ class KeyIterator {
+ friend class DrmMetadata;
+ private:
+ KeyIterator(DrmMetadata* drmMetadata) : mDrmMetadata(drmMetadata), mIndex(0) {}
+
+ public:
+ KeyIterator(const KeyIterator& keyIterator);
+ KeyIterator& operator=(const KeyIterator& keyIterator);
+ virtual ~KeyIterator() {}
+
+ public:
+ bool hasNext();
+ const String8& next();
+
+ private:
+ DrmMetadata* mDrmMetadata;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator for constraints
+ */
+ class Iterator {
+ friend class DrmMetadata;
+ private:
+ Iterator(DrmMetadata* drmMetadata) : mDrmMetadata(drmMetadata), mIndex(0) {}
+
+ public:
+ Iterator(const Iterator& iterator);
+ Iterator& operator=(const Iterator& iterator);
+ virtual ~Iterator() {}
+
+ public:
+ bool hasNext();
+ String8 next();
+
+ private:
+ DrmMetadata* mDrmMetadata;
+ unsigned int mIndex;
+ };
+
+public:
+ DrmMetadata() {}
+ virtual ~DrmMetadata() {
+ DrmMetadata::KeyIterator keyIt = this->keyIterator();
+
+ while (keyIt.hasNext()) {
+ String8 key = keyIt.next();
+ const char* value = this->getAsByteArray(&key);
+ if (NULL != value) {
+ delete[] value;
+ value = NULL;
+ }
+ }
+ mMetadataMap.clear();
+ }
+
+public:
+ int getCount(void) const;
+ status_t put(const String8* key, const char* value);
+ String8 get(const String8& key) const;
+ const char* getAsByteArray(const String8* key) const;
+ KeyIterator keyIterator();
+ Iterator iterator();
+
+private:
+ const char* getValue(const String8* key) const;
+
+private:
+ typedef KeyedVector<String8, const char*> DrmMetadataMap;
+ DrmMetadataMap mMetadataMap;
+};
+
+};
+
+#endif /* __DRM_METADATA_H__ */
+
diff --git a/include/drm/DrmRights.h b/include/drm/DrmRights.h
new file mode 100644
index 0000000..11f8f78
--- /dev/null
+++ b/include/drm/DrmRights.h
@@ -0,0 +1,106 @@
+/*
+ * 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 __DRM_RIGHTS_H__
+#define __DRM_RIGHTS_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which wraps the license information which was
+ * retrieved from the online DRM server.
+ *
+ * Caller can instantiate DrmRights by invoking DrmRights(const DrmBuffer&, String)
+ * constructor by using the result of DrmManagerClient::ProcessDrmInfo(const DrmInfo*) API.
+ * Caller can also instantiate DrmRights using the file path which contains rights information.
+ *
+ */
+class DrmRights {
+public:
+ /**
+ * Constructor for DrmRights
+ *
+ * @param[in] rightsFilePath Path of the file containing rights data
+ * @param[in] mimeType MIME type
+ * @param[in] accountId Account Id of the user
+ * @param[in] subscriptionId Subscription Id of the user
+ */
+ DrmRights(
+ const String8& rightsFilePath, const String8& mimeType,
+ const String8& accountId = String8("_NO_USER"),
+ const String8& subscriptionId = String8(""));
+
+ /**
+ * Constructor for DrmRights
+ *
+ * @param[in] rightsData Rights data
+ * @param[in] mimeType MIME type
+ * @param[in] accountId Account Id of the user
+ * @param[in] subscriptionId Subscription Id of the user
+ */
+ DrmRights(
+ const DrmBuffer& rightsData, const String8& mimeType,
+ const String8& accountId = String8("_NO_USER"),
+ const String8& subscriptionId = String8(""));
+
+ /**
+ * Destructor for DrmRights
+ */
+ virtual ~DrmRights();
+
+public:
+ /**
+ * Returns the rights data associated with this instance
+ *
+ * @return Rights data
+ */
+ const DrmBuffer& getData(void) const;
+
+ /**
+ * Returns MIME type associated with this instance
+ *
+ * @return MIME type
+ */
+ String8 getMimeType(void) const;
+
+ /**
+ * Returns the account-id associated with this instance
+ *
+ * @return Account Id
+ */
+ String8 getAccountId(void) const;
+
+ /**
+ * Returns the subscription-id associated with this object
+ *
+ * @return Subscription Id
+ */
+ String8 getSubscriptionId(void) const;
+
+private:
+ DrmBuffer mData;
+ String8 mMimeType;
+ String8 mAccountId;
+ String8 mSubscriptionId;
+ char* mRightsFromFile;
+};
+
+};
+
+#endif /* __DRM_RIGHTS_H__ */
+
diff --git a/include/drm/DrmSupportInfo.h b/include/drm/DrmSupportInfo.h
new file mode 100644
index 0000000..bf12b0b
--- /dev/null
+++ b/include/drm/DrmSupportInfo.h
@@ -0,0 +1,191 @@
+/*
+ * 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 __DRM_SUPPORT_INFO_H__
+#define __DRM_SUPPORT_INFO_H__
+
+#include "drm_framework_common.h"
+
+namespace android {
+
+/**
+ * This is an utility class which wraps the capability of each plug-in,
+ * such as mimetype's and file suffixes it could handle.
+ *
+ * Plug-in developer could return the capability of the plugin by passing
+ * DrmSupportInfo instance.
+ *
+ */
+class DrmSupportInfo {
+public:
+ /**
+ * Iterator for mMimeTypeVector
+ */
+ class MimeTypeIterator {
+ friend class DrmSupportInfo;
+ private:
+ MimeTypeIterator(DrmSupportInfo* drmSupportInfo)
+ : mDrmSupportInfo(drmSupportInfo), mIndex(0) {}
+ public:
+ MimeTypeIterator(const MimeTypeIterator& iterator);
+ MimeTypeIterator& operator=(const MimeTypeIterator& iterator);
+ virtual ~MimeTypeIterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ DrmSupportInfo* mDrmSupportInfo;
+ unsigned int mIndex;
+ };
+
+ /**
+ * Iterator for mFileSuffixVector
+ */
+ class FileSuffixIterator {
+ friend class DrmSupportInfo;
+
+ private:
+ FileSuffixIterator(DrmSupportInfo* drmSupportInfo)
+ : mDrmSupportInfo(drmSupportInfo), mIndex(0) {}
+ public:
+ FileSuffixIterator(const FileSuffixIterator& iterator);
+ FileSuffixIterator& operator=(const FileSuffixIterator& iterator);
+ virtual ~FileSuffixIterator() {}
+
+ public:
+ bool hasNext();
+ String8& next();
+
+ private:
+ DrmSupportInfo* mDrmSupportInfo;
+ unsigned int mIndex;
+ };
+
+public:
+ /**
+ * Constructor for DrmSupportInfo
+ */
+ DrmSupportInfo();
+
+ /**
+ * Copy constructor for DrmSupportInfo
+ */
+ DrmSupportInfo(const DrmSupportInfo& drmSupportInfo);
+
+ /**
+ * Destructor for DrmSupportInfo
+ */
+ virtual ~DrmSupportInfo() {}
+
+ DrmSupportInfo& operator=(const DrmSupportInfo& drmSupportInfo);
+ bool operator<(const DrmSupportInfo& drmSupportInfo) const;
+ bool operator==(const DrmSupportInfo& drmSupportInfo) const;
+
+ /**
+ * Returns FileSuffixIterator object to walk through file suffix values
+ * associated with this instance
+ *
+ * @return FileSuffixIterator object
+ */
+ FileSuffixIterator getFileSuffixIterator();
+
+ /**
+ * Returns MimeTypeIterator object to walk through mimetype values
+ * associated with this instance
+ *
+ * @return MimeTypeIterator object
+ */
+ MimeTypeIterator getMimeTypeIterator();
+
+public:
+ /**
+ * Returns the number of mimetypes supported.
+ *
+ * @return Number of mimetypes supported
+ */
+ int getMimeTypeCount(void) const;
+
+ /**
+ * Returns the number of file types supported.
+ *
+ * @return Number of file types supported
+ */
+ int getFileSuffixCount(void) const;
+
+ /**
+ * Adds the mimetype to the list of supported mimetypes
+ *
+ * @param[in] mimeType mimetype to be added
+ * @return Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t addMimeType(const String8& mimeType);
+
+ /**
+ * Adds the filesuffix to the list of supported file types
+ *
+ * @param[in] filesuffix file suffix to be added
+ * @return Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t addFileSuffix(const String8& fileSuffix);
+
+ /**
+ * Set the unique description about the plugin
+ *
+ * @param[in] description Unique description
+ * @return Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
+ */
+ status_t setDescription(const String8& description);
+
+ /**
+ * Returns the unique description associated with the plugin
+ *
+ * @return Unique description
+ */
+ String8 getDescription() const;
+
+ /**
+ * Returns whether given mimetype is supported or not
+ *
+ * @param[in] mimeType MIME type
+ * @return
+ * true - if mime-type is supported
+ * false - if mime-type is not supported
+ */
+ bool isSupportedMimeType(const String8& mimeType) const;
+
+ /**
+ * Returns whether given file type is supported or not
+ *
+ * @param[in] fileType File type
+ * @return
+ * true if file type is supported
+ * false if file type is not supported
+ */
+ bool isSupportedFileSuffix(const String8& fileType) const;
+
+private:
+ Vector<String8> mMimeTypeVector;
+ Vector<String8> mFileSuffixVector;
+
+ String8 mDescription;
+};
+
+};
+
+#endif /* __DRM_SUPPORT_INFO_H__ */
+
diff --git a/include/drm/drm_framework_common.h b/include/drm/drm_framework_common.h
new file mode 100644
index 0000000..637409c
--- /dev/null
+++ b/include/drm/drm_framework_common.h
@@ -0,0 +1,337 @@
+/*
+ * 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 __DRM_FRAMEWORK_COMMON_H__
+#define __DRM_FRAMEWORK_COMMON_H__
+
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Errors.h>
+
+#define INVALID_VALUE -1
+
+namespace android {
+
+/**
+ * Error code for DRM Frameowrk
+ */
+enum {
+ // The following constant values should be in sync with
+ // media/stagefright/MediaErrors.h
+ ERROR_BASE = -2000,
+
+ DRM_ERROR_UNKNOWN = ERROR_BASE,
+ DRM_ERROR_NO_LICENSE = ERROR_BASE - 1,
+ DRM_ERROR_LICENSE_EXPIRED = ERROR_BASE - 2,
+ DRM_ERROR_SESSION_NOT_OPENED = ERROR_BASE - 3,
+ DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED = ERROR_BASE - 4,
+ DRM_ERROR_DECRYPT = ERROR_BASE - 5,
+ DRM_ERROR_CANNOT_HANDLE = ERROR_BASE - 6,
+ DRM_ERROR_TAMPER_DETECTED = ERROR_BASE - 7,
+ DRM_ERROR_NO_PERMISSION = ERROR_BASE - 8,
+
+ DRM_NO_ERROR = NO_ERROR
+};
+
+/**
+ * copy control settings used in DecryptHandle::copyControlVector
+ */
+enum DrmCopyControl {
+ DRM_COPY_CONTROL_BASE = 1000,
+ // the key used to set the value for HDCP
+ // if the associated value is 1, then HDCP is required
+ // otherwise, HDCP is not required
+ DRM_COPY_CONTROL_HDCP = DRM_COPY_CONTROL_BASE
+};
+
+/**
+ * Defines DRM Buffer
+ */
+class DrmBuffer {
+public:
+ char* data;
+ int length;
+
+ DrmBuffer() :
+ data(NULL),
+ length(0) {
+ }
+
+ DrmBuffer(char* dataBytes, int dataLength) :
+ data(dataBytes),
+ length(dataLength) {
+ }
+
+};
+
+/**
+ * Defines detailed description of the action
+ */
+class ActionDescription {
+public:
+ ActionDescription(int _outputType, int _configuration) :
+ outputType(_outputType),
+ configuration(_configuration) {
+ }
+
+public:
+ int outputType; /* BLUETOOTH , HDMI*/
+ int configuration; /* RESOLUTION_720_480 , RECORDABLE etc.*/
+};
+
+/**
+ * Defines constants related to DRM types
+ */
+class DrmObjectType {
+private:
+ DrmObjectType();
+
+public:
+ /**
+ * Field specifies the unknown type
+ */
+ static const int UNKNOWN = 0x00;
+ /**
+ * Field specifies the protected content type
+ */
+ static const int CONTENT = 0x01;
+ /**
+ * Field specifies the rights information
+ */
+ static const int RIGHTS_OBJECT = 0x02;
+ /**
+ * Field specifies the trigger information
+ */
+ static const int TRIGGER_OBJECT = 0x03;
+};
+
+/**
+ * Defines constants related to play back
+ */
+class Playback {
+private:
+ Playback();
+
+public:
+ /**
+ * Constant field signifies playback start
+ */
+ static const int START = 0x00;
+ /**
+ * Constant field signifies playback stop
+ */
+ static const int STOP = 0x01;
+ /**
+ * Constant field signifies playback paused
+ */
+ static const int PAUSE = 0x02;
+ /**
+ * Constant field signifies playback resumed
+ */
+ static const int RESUME = 0x03;
+};
+
+/**
+ * Defines actions that can be performed on protected content
+ */
+class Action {
+private:
+ Action();
+
+public:
+ /**
+ * Constant field signifies that the default action
+ */
+ static const int DEFAULT = 0x00;
+ /**
+ * Constant field signifies that the content can be played
+ */
+ static const int PLAY = 0x01;
+ /**
+ * Constant field signifies that the content can be set as ring tone
+ */
+ static const int RINGTONE = 0x02;
+ /**
+ * Constant field signifies that the content can be transfered
+ */
+ static const int TRANSFER = 0x03;
+ /**
+ * Constant field signifies that the content can be set as output
+ */
+ static const int OUTPUT = 0x04;
+ /**
+ * Constant field signifies that preview is allowed
+ */
+ static const int PREVIEW = 0x05;
+ /**
+ * Constant field signifies that the content can be executed
+ */
+ static const int EXECUTE = 0x06;
+ /**
+ * Constant field signifies that the content can displayed
+ */
+ static const int DISPLAY = 0x07;
+};
+
+/**
+ * Defines constants related to status of the rights
+ */
+class RightsStatus {
+private:
+ RightsStatus();
+
+public:
+ /**
+ * Constant field signifies that the rights are valid
+ */
+ static const int RIGHTS_VALID = 0x00;
+ /**
+ * Constant field signifies that the rights are invalid
+ */
+ static const int RIGHTS_INVALID = 0x01;
+ /**
+ * Constant field signifies that the rights are expired for the content
+ */
+ static const int RIGHTS_EXPIRED = 0x02;
+ /**
+ * Constant field signifies that the rights are not acquired for the content
+ */
+ static const int RIGHTS_NOT_ACQUIRED = 0x03;
+};
+
+/**
+ * Defines API set for decryption
+ */
+class DecryptApiType {
+private:
+ DecryptApiType();
+
+public:
+ /**
+ * Decrypt API set for non encrypted content
+ */
+ static const int NON_ENCRYPTED = 0x00;
+ /**
+ * Decrypt API set for ES based DRM
+ */
+ static const int ELEMENTARY_STREAM_BASED = 0x01;
+ /**
+ * POSIX based Decrypt API set for container based DRM
+ */
+ static const int CONTAINER_BASED = 0x02;
+ /**
+ * Decrypt API for Widevine streams
+ */
+ static const int WV_BASED = 0x3;
+};
+
+/**
+ * Defines decryption information
+ */
+class DecryptInfo {
+public:
+ /**
+ * size of memory to be allocated to get the decrypted content.
+ */
+ int decryptBufferLength;
+ /**
+ * reserved for future purpose
+ */
+};
+
+/**
+ * Defines decryption handle
+ */
+class DecryptHandle : public RefBase {
+public:
+ /**
+ * Decryption session Handle
+ */
+ int decryptId;
+ /**
+ * Mimetype of the content to be used to select the media extractor
+ * For e.g., "video/mpeg" or "audio/mp3"
+ */
+ String8 mimeType;
+ /**
+ * Defines which decryption pattern should be used to decrypt the given content
+ * DrmFramework provides two different set of decryption APIs.
+ * 1. Decrypt APIs for elementary stream based DRM
+ * (file format is not encrypted but ES is encrypted)
+ * e.g., Marlin DRM (MP4 file format), WM-DRM (asf file format)
+ *
+ * DecryptApiType::ELEMENTARY_STREAM_BASED
+ * Decryption API set for ES based DRM
+ * initializeDecryptUnit(), decrypt(), and finalizeDecryptUnit()
+ * 2. Decrypt APIs for container based DRM (file format itself is encrypted)
+ * e.g., OMA DRM (dcf file format)
+ *
+ * DecryptApiType::CONTAINER_BASED
+ * POSIX based Decryption API set for container based DRM
+ * pread()
+ */
+ int decryptApiType;
+ /**
+ * Defines the status of the rights like
+ * RIGHTS_VALID, RIGHTS_INVALID, RIGHTS_EXPIRED or RIGHTS_NOT_ACQUIRED
+ */
+ int status;
+ /**
+ * Information required to decrypt content
+ * e.g. size of memory to be allocated to get the decrypted content.
+ */
+ DecryptInfo* decryptInfo;
+ /**
+ * Defines a vector for the copy control settings sent from the DRM plugin
+ * to the player
+ */
+ KeyedVector<DrmCopyControl, int> copyControlVector;
+
+ /**
+ * Defines a vector for any extra data the DRM plugin wants to send
+ * to the native code
+ */
+ KeyedVector<String8, String8> extendedData;
+
+public:
+ DecryptHandle():
+ decryptId(INVALID_VALUE),
+ mimeType(""),
+ decryptApiType(INVALID_VALUE),
+ status(INVALID_VALUE),
+ decryptInfo(NULL) {
+
+ }
+
+ ~DecryptHandle() {
+ delete decryptInfo; decryptInfo = NULL;
+ }
+
+ bool operator<(const DecryptHandle& handle) const {
+ return (decryptId < handle.decryptId);
+ }
+
+ bool operator==(const DecryptHandle& handle) const {
+ return (decryptId == handle.decryptId);
+ }
+};
+
+};
+
+#endif /* __DRM_FRAMEWORK_COMMON_H__ */
+
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
new file mode 100644
index 0000000..02dfc1b
--- /dev/null
+++ b/include/media/AudioEffect.h
@@ -0,0 +1,459 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_AUDIOEFFECT_H
+#define ANDROID_AUDIOEFFECT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <media/IAudioFlinger.h>
+#include <media/IAudioPolicyService.h>
+#include <media/IEffect.h>
+#include <media/IEffectClient.h>
+#include <hardware/audio_effect.h>
+#include <media/AudioSystem.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class effect_param_cblk_t;
+
+// ----------------------------------------------------------------------------
+
+class AudioEffect : public RefBase
+{
+public:
+
+ /*
+ * Static methods for effects enumeration.
+ */
+
+ /*
+ * Returns the number of effects available. This method together
+ * with queryEffect() is used to enumerate all effects:
+ * The enumeration sequence is:
+ * queryNumberEffects(&num_effects);
+ * for (i = 0; i < num_effects; i++)
+ * queryEffect(i,...);
+ *
+ * Parameters:
+ * numEffects: address where the number of effects should be returned.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * NO_ERROR successful operation.
+ * PERMISSION_DENIED could not get AudioFlinger interface
+ * NO_INIT effect library failed to initialize
+ * BAD_VALUE invalid numEffects pointer
+ *
+ * Returned value
+ * *numEffects: updated with number of effects available
+ */
+ static status_t queryNumberEffects(uint32_t *numEffects);
+
+ /*
+ * Returns an effect descriptor during effect
+ * enumeration.
+ *
+ * Parameters:
+ * index: index of the queried effect.
+ * descriptor: address where the effect descriptor should be returned.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * NO_ERROR successful operation.
+ * PERMISSION_DENIED could not get AudioFlinger interface
+ * NO_INIT effect library failed to initialize
+ * BAD_VALUE invalid descriptor pointer or index
+ * INVALID_OPERATION effect list has changed since last execution of queryNumberEffects()
+ *
+ * Returned value
+ * *descriptor: updated with effect descriptor
+ */
+ static status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor);
+
+
+ /*
+ * Returns the descriptor for the specified effect uuid.
+ *
+ * Parameters:
+ * uuid: pointer to effect uuid.
+ * descriptor: address where the effect descriptor should be returned.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * NO_ERROR successful operation.
+ * PERMISSION_DENIED could not get AudioFlinger interface
+ * NO_INIT effect library failed to initialize
+ * BAD_VALUE invalid uuid or descriptor pointers
+ * NAME_NOT_FOUND no effect with this uuid found
+ *
+ * Returned value
+ * *descriptor updated with effect descriptor
+ */
+ static status_t getEffectDescriptor(const effect_uuid_t *uuid,
+ effect_descriptor_t *descriptor) /*const*/;
+
+
+ /*
+ * Returns a list of descriptors corresponding to the pre processings enabled by default
+ * on an AudioRecord with the supplied audio session ID.
+ *
+ * Parameters:
+ * audioSession: audio session ID.
+ * descriptors: address where the effect descriptors should be returned.
+ * count: as input, the maximum number of descriptor than should be returned
+ * as output, the number of descriptor returned if status is NO_ERROR or the actual
+ * number of enabled pre processings if status is NO_MEMORY
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * NO_ERROR successful operation.
+ * NO_MEMORY the number of descriptor to return is more than the maximum number
+ * indicated by count.
+ * PERMISSION_DENIED could not get AudioFlinger interface
+ * NO_INIT effect library failed to initialize
+ * BAD_VALUE invalid audio session or descriptor pointers
+ *
+ * Returned value
+ * *descriptor updated with descriptors of pre processings enabled by default
+ * *count number of descriptors returned if returned status is N_ERROR.
+ * total number of pre processing enabled by default if returned status is
+ * NO_MEMORY. This happens if the count passed as input is less than the number
+ * of descriptors to return
+ */
+ static status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count);
+
+ /*
+ * Events used by callback function (effect_callback_t).
+ */
+ enum event_type {
+ EVENT_CONTROL_STATUS_CHANGED = 0,
+ EVENT_ENABLE_STATUS_CHANGED = 1,
+ EVENT_PARAMETER_CHANGED = 2,
+ EVENT_ERROR = 3
+ };
+
+ /* Callback function notifying client application of a change in effect engine state or
+ * configuration.
+ * An effect engine can be shared by several applications but only one has the control
+ * of the engine activity and configuration at a time.
+ * The EVENT_CONTROL_STATUS_CHANGED event is received when an application loses or
+ * retrieves the control of the effect engine. Loss of control happens
+ * if another application requests the use of the engine by creating an AudioEffect for
+ * the same effect type but with a higher priority. Control is returned when the
+ * application having the control deletes its AudioEffect object.
+ * The EVENT_ENABLE_STATUS_CHANGED event is received by all applications not having the
+ * control of the effect engine when the effect is enabled or disabled.
+ * The EVENT_PARAMETER_CHANGED event is received by all applications not having the
+ * control of the effect engine when an effect parameter is changed.
+ * The EVENT_ERROR event is received when the media server process dies.
+ *
+ * Parameters:
+ *
+ * event: type of event notified (see enum AudioEffect::event_type).
+ * user: Pointer to context for use by the callback receiver.
+ * info: Pointer to optional parameter according to event type:
+ * - EVENT_CONTROL_STATUS_CHANGED: boolean indicating if control is granted (true)
+ * or stolen (false).
+ * - EVENT_ENABLE_STATUS_CHANGED: boolean indicating if effect is now enabled (true)
+ * or disabled (false).
+ * - EVENT_PARAMETER_CHANGED: pointer to a effect_param_t structure.
+ * - EVENT_ERROR: status_t indicating the error (DEAD_OBJECT when media server dies).
+ */
+
+ typedef void (*effect_callback_t)(int32_t event, void* user, void *info);
+
+
+ /* Constructor.
+ * AudioEffect is the base class for creating and controlling an effect engine from
+ * the application process. Creating an AudioEffect object will create the effect engine
+ * in the AudioFlinger if no engine of the specified type exists. If one exists, this engine
+ * will be used. The application creating the AudioEffect object (or a derived class like
+ * Reverb for instance) will either receive control of the effect engine or not, depending
+ * on the priority parameter. If priority is higher than the priority used by the current
+ * effect engine owner, the control will be transfered to the new application. Otherwise
+ * control will remain to the previous application. In this case, the new application will be
+ * notified of changes in effect engine state or control ownership by the effect callback.
+ * After creating the AudioEffect, the application must call the initCheck() method and
+ * check the creation status before trying to control the effect engine (see initCheck()).
+ * If the effect is to be applied to an AudioTrack or MediaPlayer only the application
+ * must specify the audio session ID corresponding to this player.
+ */
+
+ /* Simple Constructor.
+ */
+ AudioEffect();
+
+
+ /* Constructor.
+ *
+ * Parameters:
+ *
+ * type: type of effect created: can be null if uuid is specified. This corresponds to
+ * the OpenSL ES interface implemented by this effect.
+ * uuid: Uuid of effect created: can be null if type is specified. This uuid corresponds to
+ * a particular implementation of an effect type.
+ * priority: requested priority for effect control: the priority level corresponds to the
+ * value of priority parameter: negative values indicate lower priorities, positive values
+ * higher priorities, 0 being the normal priority.
+ * cbf: optional callback function (see effect_callback_t)
+ * user: pointer to context for use by the callback receiver.
+ * sessionID: audio session this effect is associated to. If 0, the effect will be global to
+ * the output mix. If not 0, the effect will be applied to all players
+ * (AudioTrack or MediaPLayer) within the same audio session.
+ * io: HAL audio output or input stream to which this effect must be attached. Leave at 0 for
+ * automatic output selection by AudioFlinger.
+ */
+
+ AudioEffect(const effect_uuid_t *type,
+ const effect_uuid_t *uuid = NULL,
+ int32_t priority = 0,
+ effect_callback_t cbf = NULL,
+ void* user = NULL,
+ int sessionId = 0,
+ audio_io_handle_t io = 0
+ );
+
+ /* Constructor.
+ * Same as above but with type and uuid specified by character strings
+ */
+ AudioEffect(const char *typeStr,
+ const char *uuidStr = NULL,
+ int32_t priority = 0,
+ effect_callback_t cbf = NULL,
+ void* user = NULL,
+ int sessionId = 0,
+ audio_io_handle_t io = 0
+ );
+
+ /* Terminates the AudioEffect and unregisters it from AudioFlinger.
+ * The effect engine is also destroyed if this AudioEffect was the last controlling
+ * the engine.
+ */
+ ~AudioEffect();
+
+ /* Initialize an uninitialized AudioEffect.
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR or ALREADY_EXISTS: successful initialization
+ * - INVALID_OPERATION: AudioEffect is already initialized
+ * - BAD_VALUE: invalid parameter
+ * - NO_INIT: audio flinger or audio hardware not initialized
+ * */
+ status_t set(const effect_uuid_t *type,
+ const effect_uuid_t *uuid = NULL,
+ int32_t priority = 0,
+ effect_callback_t cbf = NULL,
+ void* user = NULL,
+ int sessionId = 0,
+ audio_io_handle_t io = 0
+ );
+
+ /* Result of constructing the AudioEffect. This must be checked
+ * before using any AudioEffect API.
+ * initCheck() can return:
+ * - NO_ERROR: the effect engine is successfully created and the application has control.
+ * - ALREADY_EXISTS: the effect engine is successfully created but the application does not
+ * have control.
+ * - NO_INIT: the effect creation failed.
+ *
+ */
+ status_t initCheck() const;
+
+
+ /* Returns the unique effect Id for the controlled effect engine. This ID is unique
+ * system wide and is used for instance in the case of auxiliary effects to attach
+ * the effect to an AudioTrack or MediaPlayer.
+ *
+ */
+ int32_t id() const { return mId; }
+
+ /* Returns a descriptor for the effect (see effect_descriptor_t in audio_effect.h).
+ */
+ effect_descriptor_t descriptor() const;
+
+ /* Returns effect control priority of this AudioEffect object.
+ */
+ int32_t priority() const { return mPriority; }
+
+
+ /* Enables or disables the effect engine.
+ *
+ * Parameters:
+ * enabled: requested enable state.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - INVALID_OPERATION: the application does not have control of the effect engine or the
+ * effect is already in the requested state.
+ */
+ virtual status_t setEnabled(bool enabled);
+ bool getEnabled() const;
+
+ /* Sets a parameter value.
+ *
+ * Parameters:
+ * param: pointer to effect_param_t structure containing the parameter
+ * and its value (See audio_effect.h).
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation.
+ * - INVALID_OPERATION: the application does not have control of the effect engine.
+ * - BAD_VALUE: invalid parameter identifier or value.
+ * - DEAD_OBJECT: the effect engine has been deleted.
+ */
+ virtual status_t setParameter(effect_param_t *param);
+
+ /* Prepare a new parameter value that will be set by next call to
+ * setParameterCommit(). This method can be used to set multiple parameters
+ * in a synchronous manner or to avoid multiple binder calls for each
+ * parameter.
+ *
+ * Parameters:
+ * param: pointer to effect_param_t structure containing the parameter
+ * and its value (See audio_effect.h).
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation.
+ * - INVALID_OPERATION: the application does not have control of the effect engine.
+ * - NO_MEMORY: no more space available in shared memory used for deferred parameter
+ * setting.
+ */
+ virtual status_t setParameterDeferred(effect_param_t *param);
+
+ /* Commit all parameter values previously prepared by setParameterDeferred().
+ *
+ * Parameters:
+ * none
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation.
+ * - INVALID_OPERATION: No new parameter values ready for commit.
+ * - BAD_VALUE: invalid parameter identifier or value: there is no indication
+ * as to which of the parameters caused this error.
+ * - DEAD_OBJECT: the effect engine has been deleted.
+ */
+ virtual status_t setParameterCommit();
+
+ /* Gets a parameter value.
+ *
+ * Parameters:
+ * param: pointer to effect_param_t structure containing the parameter
+ * and the returned value (See audio_effect.h).
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation.
+ * - INVALID_OPERATION: the AudioEffect was not successfully initialized.
+ * - BAD_VALUE: invalid parameter identifier.
+ * - DEAD_OBJECT: the effect engine has been deleted.
+ */
+ virtual status_t getParameter(effect_param_t *param);
+
+ /* Sends a command and receives a response to/from effect engine.
+ * See audio_effect.h for details on effect command() function, valid command codes
+ * and formats.
+ */
+ virtual status_t command(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *cmdData,
+ uint32_t *replySize,
+ void *replyData);
+
+
+ /*
+ * Utility functions.
+ */
+
+ /* Converts the string passed as first argument to the effect_uuid_t
+ * pointed to by second argument
+ */
+ static status_t stringToGuid(const char *str, effect_uuid_t *guid);
+ /* Converts the effect_uuid_t pointed to by first argument to the
+ * string passed as second argument
+ */
+ static status_t guidToString(const effect_uuid_t *guid, char *str, size_t maxLen);
+
+protected:
+ bool mEnabled; // enable state
+ int32_t mSessionId; // audio session ID
+ int32_t mPriority; // priority for effect control
+ status_t mStatus; // effect status
+ effect_callback_t mCbf; // callback function for status, control and
+ // parameter changes notifications
+ void* mUserData; // client context for callback function
+ effect_descriptor_t mDescriptor; // effect descriptor
+ int32_t mId; // system wide unique effect engine instance ID
+ Mutex mLock; // Mutex for mEnabled access
+
+private:
+
+ // Implements the IEffectClient interface
+ class EffectClient : public android::BnEffectClient, public android::IBinder::DeathRecipient
+ {
+ public:
+
+ EffectClient(AudioEffect *effect) : mEffect(effect){}
+
+ // IEffectClient
+ virtual void controlStatusChanged(bool controlGranted) {
+ mEffect->controlStatusChanged(controlGranted);
+ }
+ virtual void enableStatusChanged(bool enabled) {
+ mEffect->enableStatusChanged(enabled);
+ }
+ virtual void commandExecuted(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t replySize,
+ void *pReplyData) {
+ mEffect->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+ }
+
+ // IBinder::DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who) {mEffect->binderDied();}
+
+ private:
+ AudioEffect *mEffect;
+ };
+
+
+ friend class EffectClient;
+
+ // IEffectClient
+ void controlStatusChanged(bool controlGranted);
+ void enableStatusChanged(bool enabled);
+ void commandExecuted(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t replySize,
+ void *pReplyData);
+ void binderDied();
+
+
+ sp<IEffect> mIEffect; // IEffect binder interface
+ sp<EffectClient> mIEffectClient; // IEffectClient implementation
+ sp<IMemory> mCblkMemory; // shared memory for deferred parameter setting
+ effect_param_cblk_t* mCblk; // control block for deferred parameter setting
+};
+
+
+}; // namespace android
+
+#endif // ANDROID_AUDIOEFFECT_H
diff --git a/include/media/AudioParameter.h b/include/media/AudioParameter.h
new file mode 100644
index 0000000..79d5d82
--- /dev/null
+++ b/include/media/AudioParameter.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2008-2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_AUDIOPARAMETER_H_
+#define ANDROID_AUDIOPARAMETER_H_
+
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class AudioParameter {
+
+public:
+ AudioParameter() {}
+ AudioParameter(const String8& keyValuePairs);
+ virtual ~AudioParameter();
+
+ // reserved parameter keys for changing standard parameters with setParameters() function.
+ // Using these keys is mandatory for AudioFlinger to properly monitor audio output/input
+ // configuration changes and act accordingly.
+ // keyRouting: to change audio routing, value is an int in audio_devices_t
+ // keySamplingRate: to change sampling rate routing, value is an int
+ // keyFormat: to change audio format, value is an int in audio_format_t
+ // keyChannels: to change audio channel configuration, value is an int in audio_channels_t
+ // keyFrameCount: to change audio output frame count, value is an int
+ // keyInputSource: to change audio input source, value is an int in audio_source_t
+ // (defined in media/mediarecorder.h)
+ static const char *keyRouting;
+ static const char *keySamplingRate;
+ static const char *keyFormat;
+ static const char *keyChannels;
+ static const char *keyFrameCount;
+ static const char *keyInputSource;
+
+ String8 toString();
+
+ status_t add(const String8& key, const String8& value);
+ status_t addInt(const String8& key, const int value);
+ status_t addFloat(const String8& key, const float value);
+
+ status_t remove(const String8& key);
+
+ status_t get(const String8& key, String8& value);
+ status_t getInt(const String8& key, int& value);
+ status_t getFloat(const String8& key, float& value);
+ status_t getAt(size_t index, String8& key, String8& value);
+
+ size_t size() { return mParameters.size(); }
+
+private:
+ String8 mKeyValuePairs;
+ KeyedVector <String8, String8> mParameters;
+};
+
+}; // namespace android
+
+#endif /*ANDROID_AUDIOPARAMETER_H_*/
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
new file mode 100644
index 0000000..5bfb65b
--- /dev/null
+++ b/include/media/AudioRecord.h
@@ -0,0 +1,397 @@
+/*
+ * 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 AUDIORECORD_H_
+#define AUDIORECORD_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <media/IAudioFlinger.h>
+#include <media/IAudioRecord.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+#include <utils/threads.h>
+
+#include <system/audio.h>
+
+namespace android {
+
+class audio_track_cblk_t;
+
+// ----------------------------------------------------------------------------
+
+class AudioRecord
+{
+public:
+
+ static const int DEFAULT_SAMPLE_RATE = 8000;
+
+ /* Events used by AudioRecord callback function (callback_t).
+ *
+ * to keep in sync with frameworks/base/media/java/android/media/AudioRecord.java
+ */
+ enum event_type {
+ EVENT_MORE_DATA = 0, // Request to reqd more data from PCM buffer.
+ EVENT_OVERRUN = 1, // PCM buffer overrun occured.
+ EVENT_MARKER = 2, // Record head is at the specified marker position
+ // (See setMarkerPosition()).
+ EVENT_NEW_POS = 3, // Record head is at a new position
+ // (See setPositionUpdatePeriod()).
+ };
+
+ /* Create Buffer on the stack and pass it to obtainBuffer()
+ * and releaseBuffer().
+ */
+
+ class Buffer
+ {
+ public:
+ enum {
+ MUTE = 0x00000001
+ };
+ uint32_t flags;
+ int channelCount;
+ audio_format_t format;
+ size_t frameCount;
+ size_t size;
+ union {
+ void* raw;
+ short* i16;
+ int8_t* i8;
+ };
+ };
+
+ /* These are static methods to control the system-wide AudioFlinger
+ * only privileged processes can have access to them
+ */
+
+// static status_t setMasterMute(bool mute);
+
+ /* As a convenience, if a callback is supplied, a handler thread
+ * is automatically created with the appropriate priority. This thread
+ * invokes the callback when a new buffer becomes ready or an overrun condition occurs.
+ * Parameters:
+ *
+ * event: type of event notified (see enum AudioRecord::event_type).
+ * user: Pointer to context for use by the callback receiver.
+ * info: Pointer to optional parameter according to event type:
+ * - EVENT_MORE_DATA: pointer to AudioRecord::Buffer struct. The callback must not read
+ * more bytes than indicated by 'size' field and update 'size' if less bytes are
+ * read.
+ * - EVENT_OVERRUN: unused.
+ * - EVENT_MARKER: pointer to an uin32_t containing the marker position in frames.
+ * - EVENT_NEW_POS: pointer to an uin32_t containing the new position in frames.
+ */
+
+ typedef void (*callback_t)(int event, void* user, void *info);
+
+ /* Returns the minimum frame count required for the successful creation of
+ * an AudioRecord object.
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - NO_INIT: audio server or audio hardware not initialized
+ * - BAD_VALUE: unsupported configuration
+ */
+
+ static status_t getMinFrameCount(int* frameCount,
+ uint32_t sampleRate,
+ audio_format_t format,
+ int channelCount);
+
+ /* Constructs an uninitialized AudioRecord. No connection with
+ * AudioFlinger takes place.
+ */
+ AudioRecord();
+
+ /* Creates an AudioRecord track and registers it with AudioFlinger.
+ * Once created, the track needs to be started before it can be used.
+ * Unspecified values are set to the audio hardware's current
+ * values.
+ *
+ * Parameters:
+ *
+ * inputSource: Select the audio input to record to (e.g. AUDIO_SOURCE_DEFAULT).
+ * sampleRate: Track sampling rate in Hz.
+ * format: Audio format (e.g AUDIO_FORMAT_PCM_16_BIT for signed
+ * 16 bits per sample).
+ * channelMask: Channel mask: see audio_channels_t.
+ * frameCount: Total size of track PCM buffer in frames. This defines the
+ * latency of the track.
+ * flags: A bitmask of acoustic values from enum record_flags. It enables
+ * AGC, NS, and IIR.
+ * cbf: Callback function. If not null, this function is called periodically
+ * to provide new PCM data.
+ * notificationFrames: The callback function is called each time notificationFrames PCM
+ * frames are ready in record track output buffer.
+ * user Context for use by the callback receiver.
+ */
+
+ // FIXME consider removing this alias and replacing it by audio_in_acoustics_t
+ // or removing the parameter entirely if it is unused
+ enum record_flags {
+ RECORD_AGC_ENABLE = AUDIO_IN_ACOUSTICS_AGC_ENABLE,
+ RECORD_NS_ENABLE = AUDIO_IN_ACOUSTICS_NS_ENABLE,
+ RECORD_IIR_ENABLE = AUDIO_IN_ACOUSTICS_TX_IIR_ENABLE,
+ };
+
+ AudioRecord(audio_source_t inputSource,
+ uint32_t sampleRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ uint32_t channelMask = AUDIO_CHANNEL_IN_MONO,
+ int frameCount = 0,
+ record_flags flags = (record_flags) 0,
+ callback_t cbf = NULL,
+ void* user = NULL,
+ int notificationFrames = 0,
+ int sessionId = 0);
+
+
+ /* Terminates the AudioRecord and unregisters it from AudioFlinger.
+ * Also destroys all resources assotiated with the AudioRecord.
+ */
+ ~AudioRecord();
+
+
+ /* Initialize an uninitialized AudioRecord.
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful intialization
+ * - INVALID_OPERATION: AudioRecord is already intitialized or record device is already in use
+ * - BAD_VALUE: invalid parameter (channels, format, sampleRate...)
+ * - NO_INIT: audio server or audio hardware not initialized
+ * - PERMISSION_DENIED: recording is not allowed for the requesting process
+ * */
+ status_t set(audio_source_t inputSource = AUDIO_SOURCE_DEFAULT,
+ uint32_t sampleRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ uint32_t channelMask = AUDIO_CHANNEL_IN_MONO,
+ int frameCount = 0,
+ record_flags flags = (record_flags) 0,
+ callback_t cbf = NULL,
+ void* user = NULL,
+ int notificationFrames = 0,
+ bool threadCanCallJava = false,
+ int sessionId = 0);
+
+
+ /* Result of constructing the AudioRecord. This must be checked
+ * before using any AudioRecord API (except for set()), using
+ * an uninitialized AudioRecord produces undefined results.
+ * See set() method above for possible return codes.
+ */
+ status_t initCheck() const;
+
+ /* Returns this track's latency in milliseconds.
+ * This includes the latency due to AudioRecord buffer size
+ * and audio hardware driver.
+ */
+ uint32_t latency() const;
+
+ /* getters, see constructor */
+
+ audio_format_t format() const;
+ int channelCount() const;
+ int channels() const;
+ uint32_t frameCount() const;
+ size_t frameSize() const;
+ audio_source_t inputSource() const;
+
+
+ /* After it's created the track is not active. Call start() to
+ * make it active. If set, the callback will start being called.
+ */
+ status_t start();
+
+ /* Stop a track. If set, the callback will cease being called and
+ * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
+ * and will fill up buffers until the pool is exhausted.
+ */
+ status_t stop();
+ bool stopped() const;
+
+ /* get sample rate for this record track
+ */
+ uint32_t getSampleRate() const;
+
+ /* Sets marker position. When record reaches the number of frames specified,
+ * a callback with event type EVENT_MARKER is called. Calling setMarkerPosition
+ * with marker == 0 cancels marker notification callback.
+ * If the AudioRecord has been opened with no callback function associated,
+ * the operation will fail.
+ *
+ * Parameters:
+ *
+ * marker: marker position expressed in frames.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - INVALID_OPERATION: the AudioRecord has no callback installed.
+ */
+ status_t setMarkerPosition(uint32_t marker);
+ status_t getMarkerPosition(uint32_t *marker) const;
+
+
+ /* Sets position update period. Every time the number of frames specified has been recorded,
+ * a callback with event type EVENT_NEW_POS is called.
+ * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification
+ * callback.
+ * If the AudioRecord has been opened with no callback function associated,
+ * the operation will fail.
+ *
+ * Parameters:
+ *
+ * updatePeriod: position update notification period expressed in frames.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - INVALID_OPERATION: the AudioRecord has no callback installed.
+ */
+ status_t setPositionUpdatePeriod(uint32_t updatePeriod);
+ status_t getPositionUpdatePeriod(uint32_t *updatePeriod) const;
+
+
+ /* Gets record head position. The position is the total number of frames
+ * recorded since record start.
+ *
+ * Parameters:
+ *
+ * position: Address where to return record head position within AudioRecord buffer.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - BAD_VALUE: position is NULL
+ */
+ status_t getPosition(uint32_t *position) const;
+
+ /* returns a handle on the audio input used by this AudioRecord.
+ *
+ * Parameters:
+ * none.
+ *
+ * Returned value:
+ * handle on audio hardware input
+ */
+ audio_io_handle_t getInput() const;
+
+ /* returns the audio session ID associated to this AudioRecord.
+ *
+ * Parameters:
+ * none.
+ *
+ * Returned value:
+ * AudioRecord session ID.
+ */
+ int getSessionId() const;
+
+ /* obtains a buffer of "frameCount" frames. The buffer must be
+ * filled entirely. If the track is stopped, obtainBuffer() returns
+ * STOPPED instead of NO_ERROR as long as there are buffers available,
+ * at which point NO_MORE_BUFFERS is returned.
+ * Buffers will be returned until the pool (buffercount())
+ * is exhausted, at which point obtainBuffer() will either block
+ * or return WOULD_BLOCK depending on the value of the "blocking"
+ * parameter.
+ */
+
+ enum {
+ NO_MORE_BUFFERS = 0x80000001,
+ STOPPED = 1
+ };
+
+ status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount);
+ void releaseBuffer(Buffer* audioBuffer);
+
+
+ /* As a convenience we provide a read() interface to the audio buffer.
+ * This is implemented on top of obtainBuffer/releaseBuffer.
+ */
+ ssize_t read(void* buffer, size_t size);
+
+ /* Return the amount of input frames lost in the audio driver since the last call of this
+ * function. Audio driver is expected to reset the value to 0 and restart counting upon
+ * returning the current value by this function call. Such loss typically occurs when the
+ * user space process is blocked longer than the capacity of audio driver buffers.
+ * Unit: the number of input audio frames
+ */
+ unsigned int getInputFramesLost() const;
+
+private:
+ /* copying audio tracks is not allowed */
+ AudioRecord(const AudioRecord& other);
+ AudioRecord& operator = (const AudioRecord& other);
+
+ /* a small internal class to handle the callback */
+ class ClientRecordThread : public Thread
+ {
+ public:
+ ClientRecordThread(AudioRecord& receiver, bool bCanCallJava = false);
+ private:
+ friend class AudioRecord;
+ virtual bool threadLoop();
+ virtual status_t readyToRun();
+ virtual void onFirstRef() {}
+ AudioRecord& mReceiver;
+ };
+
+ bool processAudioBuffer(const sp<ClientRecordThread>& thread);
+ status_t openRecord_l(uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ audio_io_handle_t input);
+ audio_io_handle_t getInput_l();
+ status_t restoreRecord_l(audio_track_cblk_t*& cblk);
+
+ sp<IAudioRecord> mAudioRecord;
+ sp<IMemory> mCblkMemory;
+ sp<ClientRecordThread> mClientRecordThread;
+ status_t mReadyToRun;
+ mutable Mutex mLock;
+ Condition mCondition;
+
+ uint32_t mFrameCount;
+
+ audio_track_cblk_t* mCblk;
+ audio_format_t mFormat;
+ uint8_t mChannelCount;
+ audio_source_t mInputSource;
+ status_t mStatus;
+ uint32_t mLatency;
+
+ volatile int32_t mActive;
+
+ callback_t mCbf;
+ void* mUserData;
+ uint32_t mNotificationFrames;
+ uint32_t mRemainingFrames;
+ uint32_t mMarkerPosition;
+ bool mMarkerReached;
+ uint32_t mNewPosition;
+ uint32_t mUpdatePeriod;
+ record_flags mFlags;
+ uint32_t mChannelMask;
+ audio_io_handle_t mInput;
+ int mSessionId;
+ int mPreviousPriority; // before start()
+ int mPreviousSchedulingGroup;
+};
+
+}; // namespace android
+
+#endif /*AUDIORECORD_H_*/
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
new file mode 100644
index 0000000..cc0a594
--- /dev/null
+++ b/include/media/AudioSystem.h
@@ -0,0 +1,261 @@
+/*
+ * 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_AUDIOSYSTEM_H_
+#define ANDROID_AUDIOSYSTEM_H_
+
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+#include <media/IAudioFlinger.h>
+
+#include <system/audio.h>
+#include <system/audio_policy.h>
+
+/* XXX: Should be include by all the users instead */
+#include <media/AudioParameter.h>
+
+namespace android {
+
+typedef void (*audio_error_callback)(status_t err);
+
+class IAudioPolicyService;
+class String8;
+
+class AudioSystem
+{
+public:
+
+ /* These are static methods to control the system-wide AudioFlinger
+ * only privileged processes can have access to them
+ */
+
+ // mute/unmute microphone
+ static status_t muteMicrophone(bool state);
+ static status_t isMicrophoneMuted(bool *state);
+
+ // set/get master volume
+ static status_t setMasterVolume(float value);
+ static status_t getMasterVolume(float* volume);
+
+ // mute/unmute audio outputs
+ static status_t setMasterMute(bool mute);
+ static status_t getMasterMute(bool* mute);
+
+ // set/get stream volume on specified output
+ static status_t setStreamVolume(audio_stream_type_t stream, float value,
+ audio_io_handle_t output);
+ static status_t getStreamVolume(audio_stream_type_t stream, float* volume,
+ audio_io_handle_t output);
+
+ // mute/unmute stream
+ static status_t setStreamMute(audio_stream_type_t stream, bool mute);
+ static status_t getStreamMute(audio_stream_type_t stream, bool* mute);
+
+ // set audio mode in audio hardware
+ static status_t setMode(audio_mode_t mode);
+
+ // returns true in *state if tracks are active on the specified stream or has been active
+ // in the past inPastMs milliseconds
+ static status_t isStreamActive(audio_stream_type_t stream, bool *state, uint32_t inPastMs = 0);
+
+ // set/get audio hardware parameters. The function accepts a list of parameters
+ // key value pairs in the form: key1=value1;key2=value2;...
+ // Some keys are reserved for standard parameters (See AudioParameter class).
+ static status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
+ static String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
+
+ static void setErrorCallback(audio_error_callback cb);
+
+ // helper function to obtain AudioFlinger service handle
+ static const sp<IAudioFlinger>& get_audio_flinger();
+
+ static float linearToLog(int volume);
+ static int logToLinear(float volume);
+
+ static status_t getOutputSamplingRate(int* samplingRate, audio_stream_type_t stream = AUDIO_STREAM_DEFAULT);
+ static status_t getOutputFrameCount(int* frameCount, audio_stream_type_t stream = AUDIO_STREAM_DEFAULT);
+ static status_t getOutputLatency(uint32_t* latency, audio_stream_type_t stream = AUDIO_STREAM_DEFAULT);
+
+ // DEPRECATED
+ static status_t getOutputSamplingRate(int* samplingRate, int stream = AUDIO_STREAM_DEFAULT);
+
+ // DEPRECATED
+ static status_t getOutputFrameCount(int* frameCount, int stream = AUDIO_STREAM_DEFAULT);
+
+ static bool routedToA2dpOutput(audio_stream_type_t streamType);
+
+ static status_t getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount,
+ size_t* buffSize);
+
+ static status_t setVoiceVolume(float volume);
+
+ // return the number of audio frames written by AudioFlinger to audio HAL and
+ // audio dsp to DAC since the output on which the specified stream is playing
+ // has exited standby.
+ // returned status (from utils/Errors.h) can be:
+ // - NO_ERROR: successful operation, halFrames and dspFrames point to valid data
+ // - INVALID_OPERATION: Not supported on current hardware platform
+ // - BAD_VALUE: invalid parameter
+ // NOTE: this feature is not supported on all hardware platforms and it is
+ // necessary to check returned status before using the returned values.
+ static status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, audio_stream_type_t stream = AUDIO_STREAM_DEFAULT);
+
+ static unsigned int getInputFramesLost(audio_io_handle_t ioHandle);
+
+ static int newAudioSessionId();
+ static void acquireAudioSessionId(int audioSession);
+ static void releaseAudioSessionId(int audioSession);
+
+ // types of io configuration change events received with ioConfigChanged()
+ enum io_config_event {
+ OUTPUT_OPENED,
+ OUTPUT_CLOSED,
+ OUTPUT_CONFIG_CHANGED,
+ INPUT_OPENED,
+ INPUT_CLOSED,
+ INPUT_CONFIG_CHANGED,
+ STREAM_CONFIG_CHANGED,
+ NUM_CONFIG_EVENTS
+ };
+
+ // audio output descriptor used to cache output configurations in client process to avoid frequent calls
+ // through IAudioFlinger
+ class OutputDescriptor {
+ public:
+ OutputDescriptor()
+ : samplingRate(0), format(AUDIO_FORMAT_DEFAULT), channels(0), frameCount(0), latency(0) {}
+
+ uint32_t samplingRate;
+ int32_t format;
+ int32_t channels;
+ size_t frameCount;
+ uint32_t latency;
+ };
+
+ //
+ // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
+ //
+ static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address);
+ static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device, const char *device_address);
+ static status_t setPhoneState(audio_mode_t state);
+ static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
+ static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
+ static audio_io_handle_t getOutput(audio_stream_type_t stream,
+ uint32_t samplingRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ uint32_t channels = AUDIO_CHANNEL_OUT_STEREO,
+ audio_policy_output_flags_t flags = AUDIO_POLICY_OUTPUT_FLAG_NONE);
+ static status_t startOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int session = 0);
+ static status_t stopOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int session = 0);
+ static void releaseOutput(audio_io_handle_t output);
+ static audio_io_handle_t getInput(audio_source_t inputSource,
+ uint32_t samplingRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ uint32_t channels = AUDIO_CHANNEL_IN_MONO,
+ audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0,
+ int sessionId = 0);
+ static status_t startInput(audio_io_handle_t input);
+ static status_t stopInput(audio_io_handle_t input);
+ static void releaseInput(audio_io_handle_t input);
+ static status_t initStreamVolume(audio_stream_type_t stream,
+ int indexMin,
+ int indexMax);
+ static status_t setStreamVolumeIndex(audio_stream_type_t stream,
+ int index,
+ audio_devices_t device);
+ static status_t getStreamVolumeIndex(audio_stream_type_t stream,
+ int *index,
+ audio_devices_t device);
+
+ static uint32_t getStrategyForStream(audio_stream_type_t stream);
+ static audio_devices_t getDevicesForStream(audio_stream_type_t stream);
+
+ static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
+ static status_t registerEffect(effect_descriptor_t *desc,
+ audio_io_handle_t io,
+ uint32_t strategy,
+ int session,
+ int id);
+ static status_t unregisterEffect(int id);
+ static status_t setEffectEnabled(int id, bool enabled);
+
+ // clear stream to output mapping cache (gStreamOutputMap)
+ // and output configuration cache (gOutputs)
+ static void clearAudioConfigCache();
+
+ static const sp<IAudioPolicyService>& get_audio_policy_service();
+
+ // ----------------------------------------------------------------------------
+
+private:
+
+ class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient
+ {
+ public:
+ AudioFlingerClient() {
+ }
+
+ // DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+
+ // IAudioFlingerClient
+
+ // indicate a change in the configuration of an output or input: keeps the cached
+ // values for output/input parameters up-to-date in client process
+ virtual void ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2);
+ };
+
+ class AudioPolicyServiceClient: public IBinder::DeathRecipient
+ {
+ public:
+ AudioPolicyServiceClient() {
+ }
+
+ // DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+ };
+
+ static sp<AudioFlingerClient> gAudioFlingerClient;
+ static sp<AudioPolicyServiceClient> gAudioPolicyServiceClient;
+ friend class AudioFlingerClient;
+ friend class AudioPolicyServiceClient;
+
+ static Mutex gLock;
+ static sp<IAudioFlinger> gAudioFlinger;
+ static audio_error_callback gAudioErrorCallback;
+
+ static size_t gInBuffSize;
+ // previous parameters for recording buffer size queries
+ static uint32_t gPrevInSamplingRate;
+ static audio_format_t gPrevInFormat;
+ static int gPrevInChannelCount;
+
+ static sp<IAudioPolicyService> gAudioPolicyService;
+
+ // mapping between stream types and outputs
+ static DefaultKeyedVector<audio_stream_type_t, audio_io_handle_t> gStreamOutputMap;
+ // list of output descriptors containing cached parameters
+ // (sampling rate, framecount, channel count...)
+ static DefaultKeyedVector<audio_io_handle_t, OutputDescriptor *> gOutputs;
+};
+
+}; // namespace android
+
+#endif /*ANDROID_AUDIOSYSTEM_H_*/
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
new file mode 100644
index 0000000..7d5d772
--- /dev/null
+++ b/include/media/AudioTrack.h
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 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_AUDIOTRACK_H
+#define ANDROID_AUDIOTRACK_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <media/IAudioFlinger.h>
+#include <media/IAudioTrack.h>
+#include <media/AudioSystem.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+#include <utils/threads.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class audio_track_cblk_t;
+
+// ----------------------------------------------------------------------------
+
+class AudioTrack : virtual public RefBase
+{
+public:
+ enum channel_index {
+ MONO = 0,
+ LEFT = 0,
+ RIGHT = 1
+ };
+
+ /* Events used by AudioTrack callback function (audio_track_cblk_t).
+ */
+ enum event_type {
+ EVENT_MORE_DATA = 0, // Request to write more data to PCM buffer.
+ EVENT_UNDERRUN = 1, // PCM buffer underrun occured.
+ EVENT_LOOP_END = 2, // Sample loop end was reached; playback restarted from loop start if loop count was not 0.
+ EVENT_MARKER = 3, // Playback head is at the specified marker position (See setMarkerPosition()).
+ EVENT_NEW_POS = 4, // Playback head is at a new position (See setPositionUpdatePeriod()).
+ EVENT_BUFFER_END = 5 // Playback head is at the end of the buffer.
+ };
+
+ /* Client should declare Buffer on the stack and pass address to obtainBuffer()
+ * and releaseBuffer(). See also callback_t for EVENT_MORE_DATA.
+ */
+
+ class Buffer
+ {
+ public:
+ enum {
+ MUTE = 0x00000001
+ };
+ uint32_t flags; // 0 or MUTE
+ audio_format_t format; // but AUDIO_FORMAT_PCM_8_BIT -> AUDIO_FORMAT_PCM_16_BIT
+ // accessed directly by WebKit ANP callback
+ int channelCount; // will be removed in the future, do not use
+
+ size_t frameCount; // number of sample frames corresponding to size;
+ // on input it is the number of frames desired,
+ // on output is the number of frames actually filled
+
+ size_t size; // input/output in byte units
+ union {
+ void* raw;
+ short* i16; // signed 16-bit
+ int8_t* i8; // unsigned 8-bit, offset by 0x80
+ };
+ };
+
+
+ /* As a convenience, if a callback is supplied, a handler thread
+ * is automatically created with the appropriate priority. This thread
+ * invokes the callback when a new buffer becomes available or various conditions occur.
+ * Parameters:
+ *
+ * event: type of event notified (see enum AudioTrack::event_type).
+ * user: Pointer to context for use by the callback receiver.
+ * info: Pointer to optional parameter according to event type:
+ * - EVENT_MORE_DATA: pointer to AudioTrack::Buffer struct. The callback must not write
+ * more bytes than indicated by 'size' field and update 'size' if fewer bytes are
+ * written.
+ * - EVENT_UNDERRUN: unused.
+ * - EVENT_LOOP_END: pointer to an int indicating the number of loops remaining.
+ * - EVENT_MARKER: pointer to an uint32_t containing the marker position in frames.
+ * - EVENT_NEW_POS: pointer to an uint32_t containing the new position in frames.
+ * - EVENT_BUFFER_END: unused.
+ */
+
+ typedef void (*callback_t)(int event, void* user, void *info);
+
+ /* Returns the minimum frame count required for the successful creation of
+ * an AudioTrack object.
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - NO_INIT: audio server or audio hardware not initialized
+ */
+
+ static status_t getMinFrameCount(int* frameCount,
+ audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT,
+ uint32_t sampleRate = 0);
+
+ /* Constructs an uninitialized AudioTrack. No connection with
+ * AudioFlinger takes place.
+ */
+ AudioTrack();
+
+ /* Creates an audio track and registers it with AudioFlinger.
+ * Once created, the track needs to be started before it can be used.
+ * Unspecified values are set to the audio hardware's current
+ * values.
+ *
+ * Parameters:
+ *
+ * streamType: Select the type of audio stream this track is attached to
+ * (e.g. AUDIO_STREAM_MUSIC).
+ * sampleRate: Track sampling rate in Hz.
+ * format: Audio format (e.g AUDIO_FORMAT_PCM_16_BIT for signed
+ * 16 bits per sample).
+ * channelMask: Channel mask: see audio_channels_t.
+ * frameCount: Minimum size of track PCM buffer in frames. This defines the
+ * latency of the track. The actual size selected by the AudioTrack could be
+ * larger if the requested size is not compatible with current audio HAL
+ * latency.
+ * flags: Reserved for future use.
+ * cbf: Callback function. If not null, this function is called periodically
+ * to request new PCM data.
+ * user: Context for use by the callback receiver.
+ * notificationFrames: The callback function is called each time notificationFrames PCM
+ * frames have been consumed from track input buffer.
+ * sessionId: Specific session ID, or zero to use default.
+ */
+
+ AudioTrack( audio_stream_type_t streamType,
+ uint32_t sampleRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ int channelMask = 0,
+ int frameCount = 0,
+ audio_policy_output_flags_t flags = AUDIO_POLICY_OUTPUT_FLAG_NONE,
+ callback_t cbf = NULL,
+ void* user = NULL,
+ int notificationFrames = 0,
+ int sessionId = 0);
+
+ // DEPRECATED
+ explicit AudioTrack( int streamType,
+ uint32_t sampleRate = 0,
+ int format = AUDIO_FORMAT_DEFAULT,
+ int channelMask = 0,
+ int frameCount = 0,
+ uint32_t flags = (uint32_t) AUDIO_POLICY_OUTPUT_FLAG_NONE,
+ callback_t cbf = 0,
+ void* user = 0,
+ int notificationFrames = 0,
+ int sessionId = 0);
+
+ /* Creates an audio track and registers it with AudioFlinger. With this constructor,
+ * the PCM data to be rendered by AudioTrack is passed in a shared memory buffer
+ * identified by the argument sharedBuffer. This prototype is for static buffer playback.
+ * PCM data must be present in memory before the AudioTrack is started.
+ * The write() and flush() methods are not supported in this case.
+ * It is recommended to pass a callback function to be notified of playback end by an
+ * EVENT_UNDERRUN event.
+ */
+
+ AudioTrack( audio_stream_type_t streamType,
+ uint32_t sampleRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ int channelMask = 0,
+ const sp<IMemory>& sharedBuffer = 0,
+ audio_policy_output_flags_t flags = AUDIO_POLICY_OUTPUT_FLAG_NONE,
+ callback_t cbf = NULL,
+ void* user = NULL,
+ int notificationFrames = 0,
+ int sessionId = 0);
+
+ /* Terminates the AudioTrack and unregisters it from AudioFlinger.
+ * Also destroys all resources associated with the AudioTrack.
+ */
+ ~AudioTrack();
+
+
+ /* Initialize an uninitialized AudioTrack.
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful initialization
+ * - INVALID_OPERATION: AudioTrack is already initialized
+ * - BAD_VALUE: invalid parameter (channels, format, sampleRate...)
+ * - NO_INIT: audio server or audio hardware not initialized
+ * */
+ status_t set(audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT,
+ uint32_t sampleRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ int channelMask = 0,
+ int frameCount = 0,
+ audio_policy_output_flags_t flags = AUDIO_POLICY_OUTPUT_FLAG_NONE,
+ callback_t cbf = NULL,
+ void* user = NULL,
+ int notificationFrames = 0,
+ const sp<IMemory>& sharedBuffer = 0,
+ bool threadCanCallJava = false,
+ int sessionId = 0);
+
+
+ /* Result of constructing the AudioTrack. This must be checked
+ * before using any AudioTrack API (except for set()), because using
+ * an uninitialized AudioTrack produces undefined results.
+ * See set() method above for possible return codes.
+ */
+ status_t initCheck() const;
+
+ /* Returns this track's estimated latency in milliseconds.
+ * This includes the latency due to AudioTrack buffer size, AudioMixer (if any)
+ * and audio hardware driver.
+ */
+ uint32_t latency() const;
+
+ /* getters, see constructors and set() */
+
+ audio_stream_type_t streamType() const;
+ audio_format_t format() const;
+ int channelCount() const;
+ uint32_t frameCount() const;
+
+ /* Return channelCount * (bit depth per channel / 8).
+ * channelCount is determined from channelMask, and bit depth comes from format.
+ */
+ size_t frameSize() const;
+
+ sp<IMemory>& sharedBuffer();
+
+
+ /* After it's created the track is not active. Call start() to
+ * make it active. If set, the callback will start being called.
+ */
+ void start();
+
+ /* Stop a track. If set, the callback will cease being called and
+ * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
+ * and will fill up buffers until the pool is exhausted.
+ */
+ void stop();
+ bool stopped() const;
+
+ /* Flush a stopped track. All pending buffers are discarded.
+ * This function has no effect if the track is not stopped.
+ */
+ void flush();
+
+ /* Pause a track. If set, the callback will cease being called and
+ * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
+ * and will fill up buffers until the pool is exhausted.
+ */
+ void pause();
+
+ /* Mute or unmute this track.
+ * While muted, the callback, if set, is still called.
+ */
+ void mute(bool);
+ bool muted() const;
+
+ /* Set volume for this track, mostly used for games' sound effects
+ * left and right volumes. Levels must be >= 0.0 and <= 1.0.
+ */
+ status_t setVolume(float left, float right);
+ void getVolume(float* left, float* right) const;
+
+ /* Set the send level for this track. An auxiliary effect should be attached
+ * to the track with attachEffect(). Level must be >= 0.0 and <= 1.0.
+ */
+ status_t setAuxEffectSendLevel(float level);
+ void getAuxEffectSendLevel(float* level) const;
+
+ /* Set sample rate for this track, mostly used for games' sound effects
+ */
+ status_t setSampleRate(int sampleRate);
+ uint32_t getSampleRate() const;
+
+ /* Enables looping and sets the start and end points of looping.
+ *
+ * Parameters:
+ *
+ * loopStart: loop start expressed as the number of PCM frames played since AudioTrack start.
+ * loopEnd: loop end expressed as the number of PCM frames played since AudioTrack start.
+ * loopCount: number of loops to execute. Calling setLoop() with loopCount == 0 cancels any
+ * pending or active loop. loopCount = -1 means infinite looping.
+ *
+ * For proper operation the following condition must be respected:
+ * (loopEnd-loopStart) <= framecount()
+ */
+ status_t setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount);
+
+ /* Sets marker position. When playback reaches the number of frames specified, a callback with
+ * event type EVENT_MARKER is called. Calling setMarkerPosition with marker == 0 cancels marker
+ * notification callback.
+ * If the AudioTrack has been opened with no callback function associated, the operation will fail.
+ *
+ * Parameters:
+ *
+ * marker: marker position expressed in frames.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - INVALID_OPERATION: the AudioTrack has no callback installed.
+ */
+ status_t setMarkerPosition(uint32_t marker);
+ status_t getMarkerPosition(uint32_t *marker) const;
+
+
+ /* Sets position update period. Every time the number of frames specified has been played,
+ * a callback with event type EVENT_NEW_POS is called.
+ * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification
+ * callback.
+ * If the AudioTrack has been opened with no callback function associated, the operation will fail.
+ *
+ * Parameters:
+ *
+ * updatePeriod: position update notification period expressed in frames.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - INVALID_OPERATION: the AudioTrack has no callback installed.
+ */
+ status_t setPositionUpdatePeriod(uint32_t updatePeriod);
+ status_t getPositionUpdatePeriod(uint32_t *updatePeriod) const;
+
+ /* Sets playback head position within AudioTrack buffer. The new position is specified
+ * in number of frames.
+ * This method must be called with the AudioTrack in paused or stopped state.
+ * Note that the actual position set is <position> modulo the AudioTrack buffer size in frames.
+ * Therefore using this method makes sense only when playing a "static" audio buffer
+ * as opposed to streaming.
+ * The getPosition() method on the other hand returns the total number of frames played since
+ * playback start.
+ *
+ * Parameters:
+ *
+ * position: New playback head position within AudioTrack buffer.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - INVALID_OPERATION: the AudioTrack is not stopped.
+ * - BAD_VALUE: The specified position is beyond the number of frames present in AudioTrack buffer
+ */
+ status_t setPosition(uint32_t position);
+ status_t getPosition(uint32_t *position);
+
+ /* Forces AudioTrack buffer full condition. When playing a static buffer, this method avoids
+ * rewriting the buffer before restarting playback after a stop.
+ * This method must be called with the AudioTrack in paused or stopped state.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - INVALID_OPERATION: the AudioTrack is not stopped.
+ */
+ status_t reload();
+
+ /* Returns a handle on the audio output used by this AudioTrack.
+ *
+ * Parameters:
+ * none.
+ *
+ * Returned value:
+ * handle on audio hardware output
+ */
+ audio_io_handle_t getOutput();
+
+ /* Returns the unique session ID associated with this track.
+ *
+ * Parameters:
+ * none.
+ *
+ * Returned value:
+ * AudioTrack session ID.
+ */
+ int getSessionId() const;
+
+ /* Attach track auxiliary output to specified effect. Use effectId = 0
+ * to detach track from effect.
+ *
+ * Parameters:
+ *
+ * effectId: effectId obtained from AudioEffect::id().
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - INVALID_OPERATION: the effect is not an auxiliary effect.
+ * - BAD_VALUE: The specified effect ID is invalid
+ */
+ status_t attachAuxEffect(int effectId);
+
+ /* Obtains a buffer of "frameCount" frames. The buffer must be
+ * filled entirely, and then released with releaseBuffer().
+ * If the track is stopped, obtainBuffer() returns
+ * STOPPED instead of NO_ERROR as long as there are buffers available,
+ * at which point NO_MORE_BUFFERS is returned.
+ * Buffers will be returned until the pool (buffercount())
+ * is exhausted, at which point obtainBuffer() will either block
+ * or return WOULD_BLOCK depending on the value of the "blocking"
+ * parameter.
+ *
+ * Interpretation of waitCount:
+ * +n limits wait time to n * WAIT_PERIOD_MS,
+ * -1 causes an (almost) infinite wait time,
+ * 0 non-blocking.
+ */
+
+ enum {
+ NO_MORE_BUFFERS = 0x80000001, // same name in AudioFlinger.h, ok to be different value
+ STOPPED = 1
+ };
+
+ status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount);
+
+ /* Release a filled buffer of "frameCount" frames for AudioFlinger to process. */
+ void releaseBuffer(Buffer* audioBuffer);
+
+ /* As a convenience we provide a write() interface to the audio buffer.
+ * This is implemented on top of obtainBuffer/releaseBuffer. For best
+ * performance use callbacks. Returns actual number of bytes written >= 0,
+ * or one of the following negative status codes:
+ * INVALID_OPERATION AudioTrack is configured for shared buffer mode
+ * BAD_VALUE size is invalid
+ * STOPPED AudioTrack was stopped during the write
+ * NO_MORE_BUFFERS when obtainBuffer() returns same
+ * or any other error code returned by IAudioTrack::start() or restoreTrack_l().
+ */
+ ssize_t write(const void* buffer, size_t size);
+
+ /*
+ * Dumps the state of an audio track.
+ */
+ status_t dump(int fd, const Vector<String16>& args) const;
+
+protected:
+ /* copying audio tracks is not allowed */
+ AudioTrack(const AudioTrack& other);
+ AudioTrack& operator = (const AudioTrack& other);
+
+ /* a small internal class to handle the callback */
+ class AudioTrackThread : public Thread
+ {
+ public:
+ AudioTrackThread(AudioTrack& receiver, bool bCanCallJava = false);
+ private:
+ friend class AudioTrack;
+ virtual bool threadLoop();
+ virtual status_t readyToRun();
+ virtual void onFirstRef();
+ AudioTrack& mReceiver;
+ };
+
+ // body of AudioTrackThread::threadLoop()
+ bool processAudioBuffer(const sp<AudioTrackThread>& thread);
+
+ status_t createTrack_l(audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ audio_policy_output_flags_t flags,
+ const sp<IMemory>& sharedBuffer,
+ audio_io_handle_t output);
+ void flush_l();
+ status_t setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount);
+ audio_io_handle_t getOutput_l();
+ status_t restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart);
+ bool stopped_l() const { return !mActive; }
+
+ sp<IAudioTrack> mAudioTrack;
+ sp<IMemory> mCblkMemory;
+ sp<AudioTrackThread> mAudioTrackThread;
+
+ float mVolume[2];
+ float mSendLevel;
+ uint32_t mFrameCount;
+
+ audio_track_cblk_t* mCblk;
+ audio_format_t mFormat;
+ audio_stream_type_t mStreamType;
+ uint8_t mChannelCount;
+ uint8_t mMuted;
+ uint8_t mReserved;
+ uint32_t mChannelMask;
+ status_t mStatus;
+ uint32_t mLatency;
+
+ bool mActive; // protected by mLock
+
+ callback_t mCbf; // callback handler for events, or NULL
+ void* mUserData;
+ uint32_t mNotificationFramesReq; // requested number of frames between each notification callback
+ uint32_t mNotificationFramesAct; // actual number of frames between each notification callback
+ sp<IMemory> mSharedBuffer;
+ int mLoopCount;
+ uint32_t mRemainingFrames;
+ uint32_t mMarkerPosition;
+ bool mMarkerReached;
+ uint32_t mNewPosition;
+ uint32_t mUpdatePeriod;
+ bool mFlushed; // FIXME will be made obsolete by making flush() synchronous
+ audio_policy_output_flags_t mFlags;
+ int mSessionId;
+ int mAuxEffectId;
+ mutable Mutex mLock;
+ status_t mRestoreStatus;
+ bool mIsTimed;
+ int mPreviousPriority; // before start()
+ int mPreviousSchedulingGroup;
+};
+
+class TimedAudioTrack : public AudioTrack
+{
+public:
+ TimedAudioTrack();
+
+ /* allocate a shared memory buffer that can be passed to queueTimedBuffer */
+ status_t allocateTimedBuffer(size_t size, sp<IMemory>* buffer);
+
+ /* queue a buffer obtained via allocateTimedBuffer for playback at the
+ given timestamp. PTS units a microseconds on the media time timeline.
+ The media time transform (set with setMediaTimeTransform) set by the
+ audio producer will handle converting from media time to local time
+ (perhaps going through the common time timeline in the case of
+ synchronized multiroom audio case) */
+ status_t queueTimedBuffer(const sp<IMemory>& buffer, int64_t pts);
+
+ /* define a transform between media time and either common time or
+ local time */
+ enum TargetTimeline {LOCAL_TIME, COMMON_TIME};
+ status_t setMediaTimeTransform(const LinearTransform& xform,
+ TargetTimeline target);
+};
+
+}; // namespace android
+
+#endif // ANDROID_AUDIOTRACK_H
diff --git a/include/media/EffectsFactoryApi.h b/include/media/EffectsFactoryApi.h
new file mode 100644
index 0000000..65c26f4
--- /dev/null
+++ b/include/media/EffectsFactoryApi.h
@@ -0,0 +1,177 @@
+/*
+ * 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_EFFECTSFACTORYAPI_H_
+#define ANDROID_EFFECTSFACTORYAPI_H_
+
+#include <errno.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <hardware/audio_effect.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/////////////////////////////////////////////////
+// Effect factory interface
+/////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: EffectQueryNumberEffects
+//
+// Description: Returns the number of different effects in all loaded libraries.
+// Each effect must have a different effect uuid (see
+// effect_descriptor_t). This function together with EffectQueryEffect()
+// is used to enumerate all effects present in all loaded libraries.
+// Each time EffectQueryNumberEffects() is called, the factory must
+// reset the index of the effect descriptor returned by next call to
+// EffectQueryEffect() to restart enumeration from the beginning.
+//
+// Input/Output:
+// pNumEffects: address where the number of effects should be returned.
+//
+// Output:
+// returned value: 0 successful operation.
+// -ENODEV factory failed to initialize
+// -EINVAL invalid pNumEffects
+// *pNumEffects: updated with number of effects in factory
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectQueryNumberEffects(uint32_t *pNumEffects);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: EffectQueryEffect
+//
+// Description: Returns a descriptor of the next available effect.
+// See effect_descriptor_t for a details on effect descriptor.
+// This function together with EffectQueryNumberEffects() is used to enumerate all
+// effects present in all loaded libraries. The enumeration sequence is:
+// EffectQueryNumberEffects(&num_effects);
+// for (i = 0; i < num_effects; i++)
+// EffectQueryEffect(i,...);
+//
+// Input/Output:
+// pDescriptor: address where to return the effect descriptor.
+//
+// Output:
+// returned value: 0 successful operation.
+// -ENOENT no more effect available
+// -ENODEV factory failed to initialize
+// -EINVAL invalid pDescriptor
+// -ENOSYS effect list has changed since last execution of EffectQueryNumberEffects()
+// *pDescriptor: updated with the effect descriptor.
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: EffectCreate
+//
+// Description: Creates an effect engine of the specified type and returns an
+// effect control interface on this engine. The function will allocate the
+// resources for an instance of the requested effect engine and return
+// a handle on the effect control interface.
+//
+// Input:
+// pEffectUuid: pointer to the effect uuid.
+// sessionId: audio session to which this effect instance will be attached. All effects created
+// with the same session ID are connected in series and process the same signal stream.
+// Knowing that two effects are part of the same effect chain can help the library implement
+// some kind of optimizations.
+// ioId: identifies the output or input stream this effect is directed to at audio HAL. For future
+// use especially with tunneled HW accelerated effects
+//
+// Input/Output:
+// pHandle: address where to return the effect handle.
+//
+// Output:
+// returned value: 0 successful operation.
+// -ENODEV factory failed to initialize
+// -EINVAL invalid pEffectUuid or pHandle
+// -ENOENT no effect with this uuid found
+// *pHandle: updated with the effect handle.
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectCreate(const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t ioId, effect_handle_t *pHandle);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: EffectRelease
+//
+// Description: Releases the effect engine whose handle is given as argument.
+// All resources allocated to this particular instance of the effect are
+// released.
+//
+// Input:
+// handle: handle on the effect interface to be released.
+//
+// Output:
+// returned value: 0 successful operation.
+// -ENODEV factory failed to initialize
+// -EINVAL invalid interface handle
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectRelease(effect_handle_t handle);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: EffectGetDescriptor
+//
+// Description: Returns the descriptor of the effect which uuid is pointed
+// to by first argument.
+//
+// Input:
+// pEffectUuid: pointer to the effect uuid.
+//
+// Input/Output:
+// pDescriptor: address where to return the effect descriptor.
+//
+// Output:
+// returned value: 0 successful operation.
+// -ENODEV factory failed to initialize
+// -EINVAL invalid pEffectUuid or pDescriptor
+// -ENOENT no effect with this uuid found
+// *pDescriptor: updated with the effect descriptor.
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectGetDescriptor(const effect_uuid_t *pEffectUuid, effect_descriptor_t *pDescriptor);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Function: EffectIsNullUuid
+//
+// Description: Helper function to compare effect uuid to EFFECT_UUID_NULL
+//
+// Input:
+// pEffectUuid: pointer to effect uuid to compare to EFFECT_UUID_NULL.
+//
+// Output:
+// returned value: 0 if uuid is different from EFFECT_UUID_NULL.
+// 1 if uuid is equal to EFFECT_UUID_NULL.
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectIsNullUuid(const effect_uuid_t *pEffectUuid);
+
+#if __cplusplus
+} // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTSFACTORYAPI_H_*/
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
new file mode 100644
index 0000000..8239b0e
--- /dev/null
+++ b/include/media/IAudioFlinger.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 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_IAUDIOFLINGER_H
+#define ANDROID_IAUDIOFLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+#include <media/IAudioTrack.h>
+#include <media/IAudioRecord.h>
+#include <media/IAudioFlingerClient.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+#include <hardware/audio_effect.h>
+#include <media/IEffect.h>
+#include <media/IEffectClient.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioFlinger : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(AudioFlinger);
+
+ // or-able bits shared by createTrack and openRecord, but not all combinations make sense
+ enum {
+ TRACK_DEFAULT = 0, // client requests a default AudioTrack
+ TRACK_TIMED = 1, // client requests a TimedAudioTrack
+ TRACK_FAST = 2, // client requests a fast AudioTrack
+ };
+ typedef uint32_t track_flags_t;
+
+ /* create an audio track and registers it with AudioFlinger.
+ * return null if the track cannot be created.
+ */
+ virtual sp<IAudioTrack> createTrack(
+ pid_t pid,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ track_flags_t flags,
+ const sp<IMemory>& sharedBuffer,
+ audio_io_handle_t output,
+ int *sessionId,
+ status_t *status) = 0;
+
+ virtual sp<IAudioRecord> openRecord(
+ pid_t pid,
+ audio_io_handle_t input,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ track_flags_t flags,
+ int *sessionId,
+ status_t *status) = 0;
+
+ /* query the audio hardware state. This state never changes,
+ * and therefore can be cached.
+ */
+ virtual uint32_t sampleRate(audio_io_handle_t output) const = 0;
+ virtual int channelCount(audio_io_handle_t output) const = 0;
+ virtual audio_format_t format(audio_io_handle_t output) const = 0;
+ virtual size_t frameCount(audio_io_handle_t output) const = 0;
+
+ // return estimated latency in milliseconds
+ virtual uint32_t latency(audio_io_handle_t output) const = 0;
+
+ /* set/get the audio hardware state. This will probably be used by
+ * the preference panel, mostly.
+ */
+ virtual status_t setMasterVolume(float value) = 0;
+ virtual status_t setMasterMute(bool muted) = 0;
+
+ virtual float masterVolume() const = 0;
+ virtual bool masterMute() const = 0;
+
+ /* set/get stream type state. This will probably be used by
+ * the preference panel, mostly.
+ */
+ virtual status_t setStreamVolume(audio_stream_type_t stream, float value,
+ audio_io_handle_t output) = 0;
+ virtual status_t setStreamMute(audio_stream_type_t stream, bool muted) = 0;
+
+ virtual float streamVolume(audio_stream_type_t stream,
+ audio_io_handle_t output) const = 0;
+ virtual bool streamMute(audio_stream_type_t stream) const = 0;
+
+ // set audio mode
+ virtual status_t setMode(audio_mode_t mode) = 0;
+
+ // mic mute/state
+ virtual status_t setMicMute(bool state) = 0;
+ virtual bool getMicMute() const = 0;
+
+ virtual status_t setParameters(audio_io_handle_t ioHandle,
+ const String8& keyValuePairs) = 0;
+ virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const = 0;
+
+ // register a current process for audio output change notifications
+ virtual void registerClient(const sp<IAudioFlingerClient>& client) = 0;
+
+ // retrieve the audio recording buffer size
+ virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount) const = 0;
+
+ virtual audio_io_handle_t openOutput(uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ audio_format_t *pFormat,
+ uint32_t *pChannels,
+ uint32_t *pLatencyMs,
+ audio_policy_output_flags_t flags) = 0;
+ virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
+ audio_io_handle_t output2) = 0;
+ virtual status_t closeOutput(audio_io_handle_t output) = 0;
+ virtual status_t suspendOutput(audio_io_handle_t output) = 0;
+ virtual status_t restoreOutput(audio_io_handle_t output) = 0;
+
+ virtual audio_io_handle_t openInput(uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ audio_format_t *pFormat,
+ uint32_t *pChannels,
+ audio_in_acoustics_t acoustics) = 0;
+ virtual status_t closeInput(audio_io_handle_t input) = 0;
+
+ virtual status_t setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output) = 0;
+
+ virtual status_t setVoiceVolume(float volume) = 0;
+
+ virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
+ audio_io_handle_t output) const = 0;
+
+ virtual unsigned int getInputFramesLost(audio_io_handle_t ioHandle) const = 0;
+
+ virtual int newAudioSessionId() = 0;
+
+ virtual void acquireAudioSessionId(int audioSession) = 0;
+ virtual void releaseAudioSessionId(int audioSession) = 0;
+
+ virtual status_t queryNumberEffects(uint32_t *numEffects) const = 0;
+
+ virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor) const = 0;
+
+ virtual status_t getEffectDescriptor(const effect_uuid_t *pEffectUUID,
+ effect_descriptor_t *pDescriptor) const = 0;
+
+ virtual sp<IEffect> createEffect(pid_t pid,
+ effect_descriptor_t *pDesc,
+ const sp<IEffectClient>& client,
+ int32_t priority,
+ audio_io_handle_t output,
+ int sessionId,
+ status_t *status,
+ int *id,
+ int *enabled) = 0;
+
+ virtual status_t moveEffects(int session, audio_io_handle_t srcOutput,
+ audio_io_handle_t dstOutput) = 0;
+};
+
+
+// ----------------------------------------------------------------------------
+
+class BnAudioFlinger : public BnInterface<IAudioFlinger>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOFLINGER_H
diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h
new file mode 100644
index 0000000..75a9971
--- /dev/null
+++ b/include/media/IAudioFlingerClient.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_IAUDIOFLINGERCLIENT_H
+#define ANDROID_IAUDIOFLINGERCLIENT_H
+
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <utils/KeyedVector.h>
+#include <system/audio.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioFlingerClient : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(AudioFlingerClient);
+
+ // Notifies a change of audio input/output configuration.
+ virtual void ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2) = 0;
+
+};
+
+
+// ----------------------------------------------------------------------------
+
+class BnAudioFlingerClient : public BnInterface<IAudioFlingerClient>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOFLINGERCLIENT_H
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
new file mode 100644
index 0000000..04c927a
--- /dev/null
+++ b/include/media/IAudioPolicyService.h
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_IAUDIOPOLICYSERVICE_H
+#define ANDROID_IAUDIOPOLICYSERVICE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+#include <media/AudioSystem.h>
+
+#include <system/audio_policy.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioPolicyService : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(AudioPolicyService);
+
+ //
+ // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
+ //
+ virtual status_t setDeviceConnectionState(audio_devices_t device,
+ audio_policy_dev_state_t state,
+ const char *device_address) = 0;
+ virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
+ const char *device_address) = 0;
+ virtual status_t setPhoneState(audio_mode_t state) = 0;
+ virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) = 0;
+ virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) = 0;
+ virtual audio_io_handle_t getOutput(audio_stream_type_t stream,
+ uint32_t samplingRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ uint32_t channels = 0,
+ audio_policy_output_flags_t flags = AUDIO_POLICY_OUTPUT_FLAG_NONE) = 0;
+ virtual status_t startOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int session = 0) = 0;
+ virtual status_t stopOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int session = 0) = 0;
+ virtual void releaseOutput(audio_io_handle_t output) = 0;
+ virtual audio_io_handle_t getInput(audio_source_t inputSource,
+ uint32_t samplingRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ uint32_t channels = 0,
+ audio_in_acoustics_t acoustics = (audio_in_acoustics_t)0,
+ int audioSession = 0) = 0;
+ virtual status_t startInput(audio_io_handle_t input) = 0;
+ virtual status_t stopInput(audio_io_handle_t input) = 0;
+ virtual void releaseInput(audio_io_handle_t input) = 0;
+ virtual status_t initStreamVolume(audio_stream_type_t stream,
+ int indexMin,
+ int indexMax) = 0;
+ virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
+ int index,
+ audio_devices_t device) = 0;
+ virtual status_t getStreamVolumeIndex(audio_stream_type_t stream,
+ int *index,
+ audio_devices_t device) = 0;
+ virtual uint32_t getStrategyForStream(audio_stream_type_t stream) = 0;
+ virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream) = 0;
+ virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc) = 0;
+ virtual status_t registerEffect(effect_descriptor_t *desc,
+ audio_io_handle_t io,
+ uint32_t strategy,
+ int session,
+ int id) = 0;
+ virtual status_t unregisterEffect(int id) = 0;
+ virtual status_t setEffectEnabled(int id, bool enabled) = 0;
+ virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const = 0;
+ virtual status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count) = 0;
+};
+
+
+// ----------------------------------------------------------------------------
+
+class BnAudioPolicyService : public BnInterface<IAudioPolicyService>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOPOLICYSERVICE_H
diff --git a/include/media/IAudioRecord.h b/include/media/IAudioRecord.h
new file mode 100644
index 0000000..089be3b
--- /dev/null
+++ b/include/media/IAudioRecord.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 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 IAUDIORECORD_H_
+#define IAUDIORECORD_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioRecord : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(AudioRecord);
+
+ /* After it's created the track is not active. Call start() to
+ * make it active. If set, the callback will start being called.
+ * tid identifies the client callback thread, or 0 if not needed.
+ */
+ virtual status_t start(pid_t tid) = 0;
+
+ /* Stop a track. If set, the callback will cease being called and
+ * obtainBuffer will return an error. Buffers that are already released
+ * will be processed, unless flush() is called.
+ */
+ virtual void stop() = 0;
+
+ /* get this tracks control block */
+ virtual sp<IMemory> getCblk() const = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnAudioRecord : public BnInterface<IAudioRecord>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif /*IAUDIORECORD_H_*/
diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h
new file mode 100644
index 0000000..577b095
--- /dev/null
+++ b/include/media/IAudioTrack.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 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_IAUDIOTRACK_H
+#define ANDROID_IAUDIOTRACK_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+#include <binder/IMemory.h>
+#include <utils/LinearTransform.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioTrack : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(AudioTrack);
+
+ /* Get this track's control block */
+ virtual sp<IMemory> getCblk() const = 0;
+
+ /* After it's created the track is not active. Call start() to
+ * make it active. If set, the callback will start being called.
+ * tid identifies the client callback thread, or 0 if not needed.
+ */
+ virtual status_t start(pid_t tid) = 0;
+
+ /* Stop a track. If set, the callback will cease being called and
+ * obtainBuffer will return an error. Buffers that are already released
+ * will continue to be processed, unless/until flush() is called.
+ */
+ virtual void stop() = 0;
+
+ /* Flush a stopped or paused track. All pending/released buffers are discarded.
+ * This function has no effect if the track is not stopped or paused.
+ */
+ virtual void flush() = 0;
+
+ /* Mute or unmute this track.
+ * While muted, the callback, if set, is still called.
+ */
+ virtual void mute(bool) = 0;
+
+ /* Pause a track. If set, the callback will cease being called and
+ * obtainBuffer will return an error. Buffers that are already released
+ * will continue to be processed, unless/until flush() is called.
+ */
+ virtual void pause() = 0;
+
+ /* Attach track auxiliary output to specified effect. Use effectId = 0
+ * to detach track from effect.
+ */
+ virtual status_t attachAuxEffect(int effectId) = 0;
+
+
+ /* Allocate a shared memory buffer suitable for holding timed audio
+ samples */
+ virtual status_t allocateTimedBuffer(size_t size,
+ sp<IMemory>* buffer) = 0;
+
+ /* Queue a buffer obtained via allocateTimedBuffer for playback at the given
+ timestamp */
+ virtual status_t queueTimedBuffer(const sp<IMemory>& buffer,
+ int64_t pts) = 0;
+
+ /* Define the linear transform that will be applied to the timestamps
+ given to queueTimedBuffer (which are expressed in media time).
+ Target specifies whether this transform converts media time to local time
+ or Tungsten time. The values for target are defined in AudioTrack.h */
+ virtual status_t setMediaTimeTransform(const LinearTransform& xform,
+ int target) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnAudioTrack : public BnInterface<IAudioTrack>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOTRACK_H
diff --git a/include/media/ICrypto.h b/include/media/ICrypto.h
new file mode 100644
index 0000000..916abe0
--- /dev/null
+++ b/include/media/ICrypto.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <binder/IInterface.h>
+#include <media/stagefright/foundation/ABase.h>
+
+#ifndef ANDROID_ICRYPTO_H_
+
+#define ANDROID_ICRYPTO_H_
+
+namespace android {
+
+struct ICrypto : public IInterface {
+ DECLARE_META_INTERFACE(Crypto);
+
+ virtual status_t initialize() = 0;
+ virtual status_t terminate() = 0;
+
+ virtual status_t setEntitlementKey(
+ const void *key, size_t keyLength) = 0;
+
+ virtual status_t setEntitlementControlMessage(
+ const void *msg, size_t msgLength) = 0;
+
+ // "dstData" is in media_server's address space (but inaccessible).
+ virtual ssize_t decryptVideo(
+ const void *iv, size_t ivLength,
+ const void *srcData, size_t srcDataSize,
+ void *dstData, size_t dstDataOffset) = 0;
+
+ // "dstData" is in the calling process' address space.
+ virtual ssize_t decryptAudio(
+ const void *iv, size_t ivLength,
+ const void *srcData, size_t srcDataSize,
+ void *dstData, size_t dstDataSize) = 0;
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(ICrypto);
+};
+
+struct BnCrypto : public BnInterface<ICrypto> {
+ virtual status_t onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply,
+ uint32_t flags = 0);
+};
+
+} // namespace android
+
+#endif // ANDROID_ICRYPTO_H_
+
diff --git a/include/media/IEffect.h b/include/media/IEffect.h
new file mode 100644
index 0000000..ff04869
--- /dev/null
+++ b/include/media/IEffect.h
@@ -0,0 +1,60 @@
+/*
+ * 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_IEFFECT_H
+#define ANDROID_IEFFECT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+
+namespace android {
+
+class IEffect: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(Effect);
+
+ virtual status_t enable() = 0;
+
+ virtual status_t disable() = 0;
+
+ virtual status_t command(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *pReplySize,
+ void *pReplyData) = 0;
+
+ virtual void disconnect() = 0;
+
+ virtual sp<IMemory> getCblk() const = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnEffect: public BnInterface<IEffect>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IEFFECT_H
diff --git a/include/media/IEffectClient.h b/include/media/IEffectClient.h
new file mode 100644
index 0000000..2f78c98
--- /dev/null
+++ b/include/media/IEffectClient.h
@@ -0,0 +1,54 @@
+/*
+ * 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_IEFFECTCLIENT_H
+#define ANDROID_IEFFECTCLIENT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+
+namespace android {
+
+class IEffectClient: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(EffectClient);
+
+ virtual void controlStatusChanged(bool controlGranted) = 0;
+ virtual void enableStatusChanged(bool enabled) = 0;
+ virtual void commandExecuted(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t replySize,
+ void *pReplyData) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnEffectClient: public BnInterface<IEffectClient>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IEFFECTCLIENT_H
diff --git a/include/media/IMediaDeathNotifier.h b/include/media/IMediaDeathNotifier.h
new file mode 100644
index 0000000..bb3d0d8
--- /dev/null
+++ b/include/media/IMediaDeathNotifier.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 ANDROID_IMEDIADEATHNOTIFIER_H
+#define ANDROID_IMEDIADEATHNOTIFIER_H
+
+#include <utils/threads.h>
+#include <media/IMediaPlayerService.h>
+#include <utils/SortedVector.h>
+
+namespace android {
+
+class IMediaDeathNotifier: virtual public RefBase
+{
+public:
+ IMediaDeathNotifier() { addObitRecipient(this); }
+ virtual ~IMediaDeathNotifier() { removeObitRecipient(this); }
+
+ virtual void died() = 0;
+ static const sp<IMediaPlayerService>& getMediaPlayerService();
+
+private:
+ IMediaDeathNotifier &operator=(const IMediaDeathNotifier &);
+ IMediaDeathNotifier(const IMediaDeathNotifier &);
+
+ static void addObitRecipient(const wp<IMediaDeathNotifier>& recipient);
+ static void removeObitRecipient(const wp<IMediaDeathNotifier>& recipient);
+
+ class DeathNotifier: public IBinder::DeathRecipient
+ {
+ public:
+ DeathNotifier() {}
+ virtual ~DeathNotifier();
+
+ virtual void binderDied(const wp<IBinder>& who);
+ };
+
+ friend class DeathNotifier;
+
+ static Mutex sServiceLock;
+ static sp<IMediaPlayerService> sMediaPlayerService;
+ static sp<DeathNotifier> sDeathNotifier;
+ static SortedVector< wp<IMediaDeathNotifier> > sObitRecipients;
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIADEATHNOTIFIER_H
diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h
new file mode 100644
index 0000000..6dbb2d7
--- /dev/null
+++ b/include/media/IMediaMetadataRetriever.h
@@ -0,0 +1,58 @@
+/*
+**
+** 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_IMEDIAMETADATARETRIEVER_H
+#define ANDROID_IMEDIAMETADATARETRIEVER_H
+
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class IMediaMetadataRetriever: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(MediaMetadataRetriever);
+ virtual void disconnect() = 0;
+
+ virtual status_t setDataSource(
+ const char *srcUrl,
+ const KeyedVector<String8, String8> *headers = NULL) = 0;
+
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
+ virtual sp<IMemory> getFrameAtTime(int64_t timeUs, int option) = 0;
+ virtual sp<IMemory> extractAlbumArt() = 0;
+ virtual const char* extractMetadata(int keyCode) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMediaMetadataRetriever: public BnInterface<IMediaMetadataRetriever>
+{
+public:
+ virtual status_t onTransact(uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIAMETADATARETRIEVER_H
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
new file mode 100644
index 0000000..00facc5
--- /dev/null
+++ b/include/media/IMediaPlayer.h
@@ -0,0 +1,113 @@
+/*
+ * 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_IMEDIAPLAYER_H
+#define ANDROID_IMEDIAPLAYER_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <utils/KeyedVector.h>
+#include <system/audio.h>
+
+// Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
+// global, and not in android::
+struct sockaddr_in;
+
+namespace android {
+
+class Parcel;
+class Surface;
+class IStreamSource;
+class ISurfaceTexture;
+
+class IMediaPlayer: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(MediaPlayer);
+
+ virtual void disconnect() = 0;
+
+ virtual status_t setDataSource(const char *url,
+ const KeyedVector<String8, String8>* headers) = 0;
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
+ virtual status_t setDataSource(const sp<IStreamSource>& source) = 0;
+ virtual status_t setVideoSurfaceTexture(
+ const sp<ISurfaceTexture>& surfaceTexture) = 0;
+ virtual status_t prepareAsync() = 0;
+ virtual status_t start() = 0;
+ virtual status_t stop() = 0;
+ virtual status_t pause() = 0;
+ virtual status_t isPlaying(bool* state) = 0;
+ virtual status_t seekTo(int msec) = 0;
+ virtual status_t getCurrentPosition(int* msec) = 0;
+ virtual status_t getDuration(int* msec) = 0;
+ virtual status_t reset() = 0;
+ virtual status_t setAudioStreamType(audio_stream_type_t type) = 0;
+ virtual status_t setLooping(int loop) = 0;
+ virtual status_t setVolume(float leftVolume, float rightVolume) = 0;
+ virtual status_t setAuxEffectSendLevel(float level) = 0;
+ virtual status_t attachAuxEffect(int effectId) = 0;
+ virtual status_t setParameter(int key, const Parcel& request) = 0;
+ virtual status_t getParameter(int key, Parcel* reply) = 0;
+ virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) = 0;
+ virtual status_t setNextPlayer(const sp<IMediaPlayer>& next) = 0;
+
+ // Invoke a generic method on the player by using opaque parcels
+ // for the request and reply.
+ // @param request Parcel that must start with the media player
+ // interface token.
+ // @param[out] reply Parcel to hold the reply data. Cannot be null.
+ // @return OK if the invocation was made successfully.
+ virtual status_t invoke(const Parcel& request, Parcel *reply) = 0;
+
+ // Set a new metadata filter.
+ // @param filter A set of allow and drop rules serialized in a Parcel.
+ // @return OK if the invocation was made successfully.
+ virtual status_t setMetadataFilter(const Parcel& filter) = 0;
+
+ // Retrieve a set of metadata.
+ // @param update_only Include only the metadata that have changed
+ // since the last invocation of getMetadata.
+ // The set is built using the unfiltered
+ // notifications the native player sent to the
+ // MediaPlayerService during that period of
+ // time. If false, all the metadatas are considered.
+ // @param apply_filter If true, once the metadata set has been built based
+ // on the value update_only, the current filter is
+ // applied.
+ // @param[out] metadata On exit contains a set (possibly empty) of metadata.
+ // Valid only if the call returned OK.
+ // @return OK if the invocation was made successfully.
+ virtual status_t getMetadata(bool update_only,
+ bool apply_filter,
+ Parcel *metadata) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMediaPlayer: public BnInterface<IMediaPlayer>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIAPLAYER_H
diff --git a/include/media/IMediaPlayerClient.h b/include/media/IMediaPlayerClient.h
new file mode 100644
index 0000000..8f1843e
--- /dev/null
+++ b/include/media/IMediaPlayerClient.h
@@ -0,0 +1,47 @@
+/*
+ * 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_IMEDIAPLAYERCLIENT_H
+#define ANDROID_IMEDIAPLAYERCLIENT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class IMediaPlayerClient: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(MediaPlayerClient);
+
+ virtual void notify(int msg, int ext1, int ext2, const Parcel *obj) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMediaPlayerClient: public BnInterface<IMediaPlayerClient>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIAPLAYERCLIENT_H
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
new file mode 100644
index 0000000..76c45a0
--- /dev/null
+++ b/include/media/IMediaPlayerService.h
@@ -0,0 +1,91 @@
+/*
+ * 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_IMEDIAPLAYERSERVICE_H
+#define ANDROID_IMEDIAPLAYERSERVICE_H
+
+#include <utils/Errors.h> // for status_t
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <system/audio.h>
+
+#include <media/IMediaPlayerClient.h>
+#include <media/IMediaPlayer.h>
+#include <media/IMediaMetadataRetriever.h>
+
+namespace android {
+
+struct ICrypto;
+class IMediaRecorder;
+class IOMX;
+struct IStreamSource;
+
+class IMediaPlayerService: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(MediaPlayerService);
+
+ virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid) = 0;
+ virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0;
+ virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId = 0) = 0;
+
+ virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat) = 0;
+ virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat) = 0;
+ virtual sp<IOMX> getOMX() = 0;
+ virtual sp<ICrypto> makeCrypto() = 0;
+
+ // codecs and audio devices usage tracking for the battery app
+ enum BatteryDataBits {
+ // tracking audio codec
+ kBatteryDataTrackAudio = 0x1,
+ // tracking video codec
+ kBatteryDataTrackVideo = 0x2,
+ // codec is started, otherwise codec is paused
+ kBatteryDataCodecStarted = 0x4,
+ // tracking decoder (for media player),
+ // otherwise tracking encoder (for media recorder)
+ kBatteryDataTrackDecoder = 0x8,
+ // start to play an audio on an audio device
+ kBatteryDataAudioFlingerStart = 0x10,
+ // stop/pause the audio playback
+ kBatteryDataAudioFlingerStop = 0x20,
+ // audio is rounted to speaker
+ kBatteryDataSpeakerOn = 0x40,
+ // audio is rounted to devices other than speaker
+ kBatteryDataOtherAudioDeviceOn = 0x80,
+ };
+
+ virtual void addBatteryData(uint32_t params) = 0;
+ virtual status_t pullBatteryData(Parcel* reply) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMediaPlayerService: public BnInterface<IMediaPlayerService>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIAPLAYERSERVICE_H
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
new file mode 100644
index 0000000..ec84e25
--- /dev/null
+++ b/include/media/IMediaRecorder.h
@@ -0,0 +1,74 @@
+/*
+ **
+ ** 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_IMEDIARECORDER_H
+#define ANDROID_IMEDIARECORDER_H
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+class Surface;
+class ICamera;
+class ICameraRecordingProxy;
+class IMediaRecorderClient;
+class ISurfaceTexture;
+
+class IMediaRecorder: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(MediaRecorder);
+
+ virtual status_t setCamera(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy) = 0;
+ virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
+ virtual status_t setVideoSource(int vs) = 0;
+ virtual status_t setAudioSource(int as) = 0;
+ virtual status_t setOutputFormat(int of) = 0;
+ virtual status_t setVideoEncoder(int ve) = 0;
+ virtual status_t setAudioEncoder(int ae) = 0;
+ virtual status_t setOutputFile(const char* path) = 0;
+ virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
+ virtual status_t setVideoSize(int width, int height) = 0;
+ virtual status_t setVideoFrameRate(int frames_per_second) = 0;
+ virtual status_t setParameters(const String8& params) = 0;
+ virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0;
+ virtual status_t prepare() = 0;
+ virtual status_t getMaxAmplitude(int* max) = 0;
+ virtual status_t start() = 0;
+ virtual status_t stop() = 0;
+ virtual status_t reset() = 0;
+ virtual status_t init() = 0;
+ virtual status_t close() = 0;
+ virtual status_t release() = 0;
+ virtual sp<ISurfaceTexture> querySurfaceMediaSource() = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMediaRecorder: public BnInterface<IMediaRecorder>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIARECORDER_H
diff --git a/include/media/IMediaRecorderClient.h b/include/media/IMediaRecorderClient.h
new file mode 100644
index 0000000..e7d0229
--- /dev/null
+++ b/include/media/IMediaRecorderClient.h
@@ -0,0 +1,47 @@
+/*
+ * 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_IMEDIARECORDERCLIENT_H
+#define ANDROID_IMEDIARECORDERCLIENT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class IMediaRecorderClient: public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(MediaRecorderClient);
+
+ virtual void notify(int msg, int ext1, int ext2) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMediaRecorderClient: public BnInterface<IMediaRecorderClient>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIARECORDERCLIENT_H
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
new file mode 100644
index 0000000..be1b2fc
--- /dev/null
+++ b/include/media/IOMX.h
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_IOMX_H_
+
+#define ANDROID_IOMX_H_
+
+#include <binder/IInterface.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/List.h>
+#include <utils/String8.h>
+
+#include <OMX_Core.h>
+#include <OMX_Video.h>
+
+namespace android {
+
+class IMemory;
+class IOMXObserver;
+class IOMXRenderer;
+class Surface;
+
+class IOMX : public IInterface {
+public:
+ DECLARE_META_INTERFACE(OMX);
+
+ typedef void *buffer_id;
+ typedef void *node_id;
+
+ // Given a node_id and the calling process' pid, returns true iff
+ // the implementation of the OMX interface lives in the same
+ // process.
+ virtual bool livesLocally(node_id node, pid_t pid) = 0;
+
+ struct ComponentInfo {
+ String8 mName;
+ List<String8> mRoles;
+ };
+ virtual status_t listNodes(List<ComponentInfo> *list) = 0;
+
+ virtual status_t allocateNode(
+ const char *name, const sp<IOMXObserver> &observer,
+ node_id *node) = 0;
+
+ virtual status_t freeNode(node_id node) = 0;
+
+ virtual status_t sendCommand(
+ node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) = 0;
+
+ virtual status_t getParameter(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size) = 0;
+
+ virtual status_t setParameter(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size) = 0;
+
+ virtual status_t getConfig(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size) = 0;
+
+ virtual status_t setConfig(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size) = 0;
+
+ virtual status_t getState(
+ node_id node, OMX_STATETYPE* state) = 0;
+
+ virtual status_t storeMetaDataInBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) = 0;
+
+ virtual status_t enableGraphicBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) = 0;
+
+ virtual status_t getGraphicBufferUsage(
+ node_id node, OMX_U32 port_index, OMX_U32* usage) = 0;
+
+ virtual status_t useBuffer(
+ node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+ buffer_id *buffer) = 0;
+
+ virtual status_t useGraphicBuffer(
+ node_id node, OMX_U32 port_index,
+ const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) = 0;
+
+ // This API clearly only makes sense if the caller lives in the
+ // same process as the callee, i.e. is the media_server, as the
+ // returned "buffer_data" pointer is just that, a pointer into local
+ // address space.
+ virtual status_t allocateBuffer(
+ node_id node, OMX_U32 port_index, size_t size,
+ buffer_id *buffer, void **buffer_data) = 0;
+
+ virtual status_t allocateBufferWithBackup(
+ node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+ buffer_id *buffer) = 0;
+
+ virtual status_t freeBuffer(
+ node_id node, OMX_U32 port_index, buffer_id buffer) = 0;
+
+ virtual status_t fillBuffer(node_id node, buffer_id buffer) = 0;
+
+ virtual status_t emptyBuffer(
+ node_id node,
+ buffer_id buffer,
+ OMX_U32 range_offset, OMX_U32 range_length,
+ OMX_U32 flags, OMX_TICKS timestamp) = 0;
+
+ virtual status_t getExtensionIndex(
+ node_id node,
+ const char *parameter_name,
+ OMX_INDEXTYPE *index) = 0;
+};
+
+struct omx_message {
+ enum {
+ EVENT,
+ EMPTY_BUFFER_DONE,
+ FILL_BUFFER_DONE,
+
+ } type;
+
+ IOMX::node_id node;
+
+ union {
+ // if type == EVENT
+ struct {
+ OMX_EVENTTYPE event;
+ OMX_U32 data1;
+ OMX_U32 data2;
+ } event_data;
+
+ // if type == EMPTY_BUFFER_DONE
+ struct {
+ IOMX::buffer_id buffer;
+ } buffer_data;
+
+ // if type == FILL_BUFFER_DONE
+ struct {
+ IOMX::buffer_id buffer;
+ OMX_U32 range_offset;
+ OMX_U32 range_length;
+ OMX_U32 flags;
+ OMX_TICKS timestamp;
+ OMX_PTR platform_private;
+ OMX_PTR data_ptr;
+ } extended_buffer_data;
+
+ } u;
+};
+
+class IOMXObserver : public IInterface {
+public:
+ DECLARE_META_INTERFACE(OMXObserver);
+
+ virtual void onMessage(const omx_message &msg) = 0;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+class BnOMX : public BnInterface<IOMX> {
+public:
+ virtual status_t onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply,
+ uint32_t flags = 0);
+};
+
+class BnOMXObserver : public BnInterface<IOMXObserver> {
+public:
+ virtual status_t onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply,
+ uint32_t flags = 0);
+};
+
+struct CodecProfileLevel {
+ OMX_U32 mProfile;
+ OMX_U32 mLevel;
+};
+
+} // namespace android
+
+#endif // ANDROID_IOMX_H_
diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h
new file mode 100644
index 0000000..19646b0
--- /dev/null
+++ b/include/media/IStreamSource.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 ANDROID_ISTREAMSOURCE_H_
+
+#define ANDROID_ISTREAMSOURCE_H_
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+struct AMessage;
+struct IMemory;
+struct IStreamListener;
+
+struct IStreamSource : public IInterface {
+ DECLARE_META_INTERFACE(StreamSource);
+
+ virtual void setListener(const sp<IStreamListener> &listener) = 0;
+ virtual void setBuffers(const Vector<sp<IMemory> > &buffers) = 0;
+
+ virtual void onBufferAvailable(size_t index) = 0;
+};
+
+struct IStreamListener : public IInterface {
+ DECLARE_META_INTERFACE(StreamListener);
+
+ enum Command {
+ EOS,
+ DISCONTINUITY,
+ };
+
+ virtual void queueBuffer(size_t index, size_t size) = 0;
+
+ // When signalling a discontinuity you can optionally
+ // specify an int64_t PTS timestamp in "msg".
+ // If present, rendering of data following the discontinuity
+ // will be suppressed until media time reaches this timestamp.
+ static const char *const kKeyResumeAtPTS;
+
+ // When signalling a discontinuity you can optionally
+ // specify the type(s) of discontinuity, i.e. if the
+ // audio format has changed, the video format has changed,
+ // time has jumped or any combination thereof.
+ // To do so, include a non-zero int32_t value
+ // under the key "kKeyDiscontinuityMask" when issuing the DISCONTINUITY
+ // command.
+ // If there is a change in audio/video format, The new logical stream
+ // must start with proper codec initialization
+ // information for playback to continue, i.e. SPS and PPS in the case
+ // of AVC video etc.
+ // If this key is not present, only a time discontinuity is assumed.
+ // The value should be a bitmask of values from
+ // ATSParser::DiscontinuityType.
+ static const char *const kKeyDiscontinuityMask;
+
+ virtual void issueCommand(
+ Command cmd, bool synchronous, const sp<AMessage> &msg = NULL) = 0;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct BnStreamSource : public BnInterface<IStreamSource> {
+ virtual status_t onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply,
+ uint32_t flags = 0);
+};
+
+struct BnStreamListener : public BnInterface<IStreamListener> {
+ virtual status_t onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply,
+ uint32_t flags = 0);
+};
+
+} // namespace android
+
+#endif // ANDROID_ISTREAMSOURCE_H_
diff --git a/include/media/JetPlayer.h b/include/media/JetPlayer.h
new file mode 100644
index 0000000..0616bf0
--- /dev/null
+++ b/include/media/JetPlayer.h
@@ -0,0 +1,127 @@
+/*
+ * 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 JETPLAYER_H_
+#define JETPLAYER_H_
+
+#include <utils/threads.h>
+
+#include <libsonivox/jet.h>
+#include <libsonivox/eas_types.h>
+#include <media/AudioTrack.h>
+
+
+namespace android {
+
+typedef void (*jetevent_callback)(int eventType, int val1, int val2, void *cookie);
+
+class JetPlayer {
+
+public:
+
+ // to keep in sync with the JetPlayer class constants
+ // defined in frameworks/base/media/java/android/media/JetPlayer.java
+ static const int JET_EVENT = 1;
+ static const int JET_USERID_UPDATE = 2;
+ static const int JET_NUMQUEUEDSEGMENT_UPDATE = 3;
+ static const int JET_PAUSE_UPDATE = 4;
+
+ JetPlayer(void *javaJetPlayer,
+ int maxTracks = 32,
+ int trackBufferSize = 1200);
+ ~JetPlayer();
+ int init();
+ int release();
+
+ int loadFromFile(const char* url);
+ int loadFromFD(const int fd, const long long offset, const long long length);
+ int closeFile();
+ int play();
+ int pause();
+ int queueSegment(int segmentNum, int libNum, int repeatCount, int transpose,
+ EAS_U32 muteFlags, EAS_U8 userID);
+ int setMuteFlags(EAS_U32 muteFlags, bool sync);
+ int setMuteFlag(int trackNum, bool muteFlag, bool sync);
+ int triggerClip(int clipId);
+ int clearQueue();
+
+ void setEventCallback(jetevent_callback callback);
+
+ int getMaxTracks() { return mMaxTracks; };
+
+
+private:
+ int render();
+ void fireUpdateOnStatusChange();
+ void fireEventsFromJetQueue();
+
+ JetPlayer() {} // no default constructor
+ void dump();
+ void dumpJetStatus(S_JET_STATUS* pJetStatus);
+
+ jetevent_callback mEventCallback;
+
+ void* mJavaJetPlayerRef;
+ Mutex mMutex; // mutex to sync the render and playback thread with the JET calls
+ pid_t mTid;
+ Condition mCondition;
+ volatile bool mRender;
+ bool mPaused;
+
+ EAS_STATE mState;
+ int* mMemFailedVar;
+
+ int mMaxTracks; // max number of MIDI tracks, usually 32
+ EAS_DATA_HANDLE mEasData;
+ EAS_FILE_LOCATOR mEasJetFileLoc;
+ EAS_PCM* mAudioBuffer;// EAS renders the MIDI data into this buffer,
+ AudioTrack* mAudioTrack; // and we play it in this audio track
+ int mTrackBufferSize;
+ S_JET_STATUS mJetStatus;
+ S_JET_STATUS mPreviousJetStatus;
+
+ char mJetFilePath[PATH_MAX];
+
+ class JetPlayerThread : public Thread {
+ public:
+ JetPlayerThread(JetPlayer *player) : mPlayer(player) {
+ }
+
+ protected:
+ virtual ~JetPlayerThread() {}
+
+ private:
+ JetPlayer *mPlayer;
+
+ bool threadLoop() {
+ int result;
+ result = mPlayer->render();
+ return false;
+ }
+
+ JetPlayerThread(const JetPlayerThread &);
+ JetPlayerThread &operator=(const JetPlayerThread &);
+ };
+
+ sp<JetPlayerThread> mThread;
+
+}; // end class JetPlayer
+
+} // end namespace android
+
+
+
+#endif /*JETPLAYER_H_*/
diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h
new file mode 100644
index 0000000..ecc3b65
--- /dev/null
+++ b/include/media/MediaMetadataRetrieverInterface.h
@@ -0,0 +1,58 @@
+/*
+**
+** 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_MEDIAMETADATARETRIEVERINTERFACE_H
+#define ANDROID_MEDIAMETADATARETRIEVERINTERFACE_H
+
+#include <utils/RefBase.h>
+#include <media/mediametadataretriever.h>
+#include <private/media/VideoFrame.h>
+
+namespace android {
+
+// Abstract base class
+class MediaMetadataRetrieverBase : public RefBase
+{
+public:
+ MediaMetadataRetrieverBase() {}
+ virtual ~MediaMetadataRetrieverBase() {}
+
+ virtual status_t setDataSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers = NULL) = 0;
+
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
+ virtual VideoFrame* getFrameAtTime(int64_t timeUs, int option) = 0;
+ virtual MediaAlbumArt* extractAlbumArt() = 0;
+ virtual const char* extractMetadata(int keyCode) = 0;
+};
+
+// MediaMetadataRetrieverInterface
+class MediaMetadataRetrieverInterface : public MediaMetadataRetrieverBase
+{
+public:
+ MediaMetadataRetrieverInterface() {}
+
+ virtual ~MediaMetadataRetrieverInterface() {}
+ virtual VideoFrame* getFrameAtTime(int64_t timeUs, int option) { return NULL; }
+ virtual MediaAlbumArt* extractAlbumArt() { return NULL; }
+ virtual const char* extractMetadata(int keyCode) { return NULL; }
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIAMETADATARETRIEVERINTERFACE_H
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
new file mode 100644
index 0000000..d4aa233
--- /dev/null
+++ b/include/media/MediaPlayerInterface.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 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_MEDIAPLAYERINTERFACE_H
+#define ANDROID_MEDIAPLAYERINTERFACE_H
+
+#ifdef __cplusplus
+
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include <utils/RefBase.h>
+
+#include <media/mediaplayer.h>
+#include <media/AudioSystem.h>
+#include <media/Metadata.h>
+
+// Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
+// global, and not in android::
+struct sockaddr_in;
+
+namespace android {
+
+class Parcel;
+class Surface;
+class ISurfaceTexture;
+
+template<typename T> class SortedVector;
+
+enum player_type {
+ PV_PLAYER = 1,
+ SONIVOX_PLAYER = 2,
+ STAGEFRIGHT_PLAYER = 3,
+ NU_PLAYER = 4,
+ // Test players are available only in the 'test' and 'eng' builds.
+ // The shared library with the test player is passed passed as an
+ // argument to the 'test:' url in the setDataSource call.
+ TEST_PLAYER = 5,
+
+ AAH_RX_PLAYER = 100,
+ AAH_TX_PLAYER = 101,
+};
+
+
+#define DEFAULT_AUDIOSINK_BUFFERCOUNT 4
+#define DEFAULT_AUDIOSINK_BUFFERSIZE 1200
+#define DEFAULT_AUDIOSINK_SAMPLERATE 44100
+
+// when the channel mask isn't known, use the channel count to derive a mask in AudioSink::open()
+#define CHANNEL_MASK_USE_CHANNEL_ORDER 0
+
+// callback mechanism for passing messages to MediaPlayer object
+typedef void (*notify_callback_f)(void* cookie,
+ int msg, int ext1, int ext2, const Parcel *obj);
+
+// abstract base class - use MediaPlayerInterface
+class MediaPlayerBase : public RefBase
+{
+public:
+ // AudioSink: abstraction layer for audio output
+ class AudioSink : public RefBase {
+ public:
+ // Callback returns the number of bytes actually written to the buffer.
+ typedef size_t (*AudioCallback)(
+ AudioSink *audioSink, void *buffer, size_t size, void *cookie);
+
+ virtual ~AudioSink() {}
+ virtual bool ready() const = 0; // audio output is open and ready
+ virtual bool realtime() const = 0; // audio output is real-time output
+ virtual ssize_t bufferSize() const = 0;
+ virtual ssize_t frameCount() const = 0;
+ virtual ssize_t channelCount() const = 0;
+ virtual ssize_t frameSize() const = 0;
+ virtual uint32_t latency() const = 0;
+ virtual float msecsPerFrame() const = 0;
+ virtual status_t getPosition(uint32_t *position) = 0;
+ virtual int getSessionId() = 0;
+
+ // If no callback is specified, use the "write" API below to submit
+ // audio data.
+ virtual status_t open(
+ uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
+ audio_format_t format=AUDIO_FORMAT_PCM_16_BIT,
+ int bufferCount=DEFAULT_AUDIOSINK_BUFFERCOUNT,
+ AudioCallback cb = NULL,
+ void *cookie = NULL) = 0;
+
+ virtual void start() = 0;
+ virtual ssize_t write(const void* buffer, size_t size) = 0;
+ virtual void stop() = 0;
+ virtual void flush() = 0;
+ virtual void pause() = 0;
+ virtual void close() = 0;
+
+ virtual status_t setPlaybackRatePermille(int32_t rate) { return INVALID_OPERATION; }
+ virtual bool needsTrailingPadding() { return true; }
+ };
+
+ MediaPlayerBase() : mCookie(0), mNotify(0) {}
+ virtual ~MediaPlayerBase() {}
+ virtual status_t initCheck() = 0;
+ virtual bool hardwareOutput() = 0;
+
+ virtual status_t setUID(uid_t uid) {
+ return INVALID_OPERATION;
+ }
+
+ virtual status_t setDataSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers = NULL) = 0;
+
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
+
+ virtual status_t setDataSource(const sp<IStreamSource> &source) {
+ return INVALID_OPERATION;
+ }
+
+ // pass the buffered ISurfaceTexture to the media player service
+ virtual status_t setVideoSurfaceTexture(
+ const sp<ISurfaceTexture>& surfaceTexture) = 0;
+
+ virtual status_t prepare() = 0;
+ virtual status_t prepareAsync() = 0;
+ virtual status_t start() = 0;
+ virtual status_t stop() = 0;
+ virtual status_t pause() = 0;
+ virtual bool isPlaying() = 0;
+ virtual status_t seekTo(int msec) = 0;
+ virtual status_t getCurrentPosition(int *msec) = 0;
+ virtual status_t getDuration(int *msec) = 0;
+ virtual status_t reset() = 0;
+ virtual status_t setLooping(int loop) = 0;
+ virtual player_type playerType() = 0;
+ virtual status_t setParameter(int key, const Parcel &request) = 0;
+ virtual status_t getParameter(int key, Parcel *reply) = 0;
+
+ // Right now, only the AAX TX player supports this functionality. For now,
+ // provide a default implementation which indicates a lack of support for
+ // this functionality to make life easier for all of the other media player
+ // maintainers out there.
+ virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) {
+ return INVALID_OPERATION;
+ }
+
+ // Invoke a generic method on the player by using opaque parcels
+ // for the request and reply.
+ //
+ // @param request Parcel that is positioned at the start of the
+ // data sent by the java layer.
+ // @param[out] reply Parcel to hold the reply data. Cannot be null.
+ // @return OK if the call was successful.
+ virtual status_t invoke(const Parcel& request, Parcel *reply) = 0;
+
+ // The Client in the MetadataPlayerService calls this method on
+ // the native player to retrieve all or a subset of metadata.
+ //
+ // @param ids SortedList of metadata ID to be fetch. If empty, all
+ // the known metadata should be returned.
+ // @param[inout] records Parcel where the player appends its metadata.
+ // @return OK if the call was successful.
+ virtual status_t getMetadata(const media::Metadata::Filter& ids,
+ Parcel *records) {
+ return INVALID_OPERATION;
+ };
+
+ void setNotifyCallback(
+ void* cookie, notify_callback_f notifyFunc) {
+ Mutex::Autolock autoLock(mNotifyLock);
+ mCookie = cookie; mNotify = notifyFunc;
+ }
+
+ void sendEvent(int msg, int ext1=0, int ext2=0,
+ const Parcel *obj=NULL) {
+ Mutex::Autolock autoLock(mNotifyLock);
+ if (mNotify) mNotify(mCookie, msg, ext1, ext2, obj);
+ }
+
+ virtual status_t dump(int fd, const Vector<String16> &args) const {
+ return INVALID_OPERATION;
+ }
+
+private:
+ friend class MediaPlayerService;
+
+ Mutex mNotifyLock;
+ void* mCookie;
+ notify_callback_f mNotify;
+};
+
+// Implement this class for media players that use the AudioFlinger software mixer
+class MediaPlayerInterface : public MediaPlayerBase
+{
+public:
+ virtual ~MediaPlayerInterface() { }
+ virtual bool hardwareOutput() { return false; }
+ virtual void setAudioSink(const sp<AudioSink>& audioSink) { mAudioSink = audioSink; }
+protected:
+ sp<AudioSink> mAudioSink;
+};
+
+// Implement this class for media players that output audio directly to hardware
+class MediaPlayerHWInterface : public MediaPlayerBase
+{
+public:
+ virtual ~MediaPlayerHWInterface() {}
+ virtual bool hardwareOutput() { return true; }
+ virtual status_t setVolume(float leftVolume, float rightVolume) = 0;
+ virtual status_t setAudioStreamType(audio_stream_type_t streamType) = 0;
+};
+
+}; // namespace android
+
+#endif // __cplusplus
+
+
+#endif // ANDROID_MEDIAPLAYERINTERFACE_H
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h
new file mode 100644
index 0000000..9fc962c
--- /dev/null
+++ b/include/media/MediaProfiles.h
@@ -0,0 +1,518 @@
+/*
+ **
+ ** 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.
+ */
+
+#ifndef ANDROID_MEDIAPROFILES_H
+#define ANDROID_MEDIAPROFILES_H
+
+#include <utils/threads.h>
+#include <media/mediarecorder.h>
+
+namespace android {
+
+enum camcorder_quality {
+ CAMCORDER_QUALITY_LIST_START = 0,
+ CAMCORDER_QUALITY_LOW = 0,
+ CAMCORDER_QUALITY_HIGH = 1,
+ CAMCORDER_QUALITY_QCIF = 2,
+ CAMCORDER_QUALITY_CIF = 3,
+ CAMCORDER_QUALITY_480P = 4,
+ CAMCORDER_QUALITY_720P = 5,
+ CAMCORDER_QUALITY_1080P = 6,
+ CAMCORDER_QUALITY_QVGA = 7,
+ CAMCORDER_QUALITY_LIST_END = 7,
+
+ CAMCORDER_QUALITY_TIME_LAPSE_LIST_START = 1000,
+ CAMCORDER_QUALITY_TIME_LAPSE_LOW = 1000,
+ CAMCORDER_QUALITY_TIME_LAPSE_HIGH = 1001,
+ CAMCORDER_QUALITY_TIME_LAPSE_QCIF = 1002,
+ CAMCORDER_QUALITY_TIME_LAPSE_CIF = 1003,
+ CAMCORDER_QUALITY_TIME_LAPSE_480P = 1004,
+ CAMCORDER_QUALITY_TIME_LAPSE_720P = 1005,
+ CAMCORDER_QUALITY_TIME_LAPSE_1080P = 1006,
+ CAMCORDER_QUALITY_TIME_LAPSE_QVGA = 1007,
+ CAMCORDER_QUALITY_TIME_LAPSE_LIST_END = 1007,
+};
+
+/**
+ * Set CIF as default maximum import and export resolution of video editor.
+ * The maximum import and export resolutions are platform specific,
+ * which should be defined in media_profiles.xml.
+ * Set default maximum prefetch YUV frames to 6, which means video editor can
+ * queue up to 6 YUV frames in the video encoder source.
+ * This value is used to limit the amount of memory used by video editor
+ * engine when the encoder consumes YUV frames at a lower speed
+ * than video editor engine produces.
+ */
+enum videoeditor_capability {
+ VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH = 352,
+ VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT = 288,
+ VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH = 352,
+ VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT = 288,
+ VIDEOEDITOR_DEFAULT_MAX_PREFETCH_YUV_FRAMES = 6
+};
+
+enum video_decoder {
+ VIDEO_DECODER_WMV,
+};
+
+enum audio_decoder {
+ AUDIO_DECODER_WMA,
+};
+
+
+class MediaProfiles
+{
+public:
+
+ /**
+ * Returns the singleton instance for subsequence queries.
+ * or NULL if error.
+ */
+ static MediaProfiles* getInstance();
+
+ /**
+ * Returns the value for the given param name for the given camera at
+ * the given quality level, or -1 if error.
+ *
+ * Supported param name are:
+ * duration - the recording duration.
+ * file.format - output file format. see mediarecorder.h for details
+ * vid.codec - video encoder. see mediarecorder.h for details.
+ * aud.codec - audio encoder. see mediarecorder.h for details.
+ * vid.width - video frame width
+ * vid.height - video frame height
+ * vid.fps - video frame rate
+ * vid.bps - video bit rate
+ * aud.bps - audio bit rate
+ * aud.hz - audio sample rate
+ * aud.ch - number of audio channels
+ */
+ int getCamcorderProfileParamByName(const char *name, int cameraId,
+ camcorder_quality quality) const;
+
+ /**
+ * Returns true if a profile for the given camera at the given quality exists,
+ * or false if not.
+ */
+ bool hasCamcorderProfile(int cameraId, camcorder_quality quality) const;
+
+ /**
+ * Returns the output file formats supported.
+ */
+ Vector<output_format> getOutputFileFormats() const;
+
+ /**
+ * Returns the video encoders supported.
+ */
+ Vector<video_encoder> getVideoEncoders() const;
+
+ /**
+ * Returns the value for the given param name for the given video encoder
+ * returned from getVideoEncoderByIndex or -1 if error.
+ *
+ * Supported param name are:
+ * enc.vid.width.min - min video frame width
+ * enc.vid.width.max - max video frame width
+ * enc.vid.height.min - min video frame height
+ * enc.vid.height.max - max video frame height
+ * enc.vid.bps.min - min bit rate in bits per second
+ * enc.vid.bps.max - max bit rate in bits per second
+ * enc.vid.fps.min - min frame rate in frames per second
+ * enc.vid.fps.max - max frame rate in frames per second
+ */
+ int getVideoEncoderParamByName(const char *name, video_encoder codec) const;
+
+ /**
+ * Returns the value for the given param name for the video editor cap
+ * param or -1 if error.
+ * Supported param name are:
+ * videoeditor.input.width.max - max input video frame width
+ * videoeditor.input.height.max - max input video frame height
+ * videoeditor.output.width.max - max output video frame width
+ * videoeditor.output.height.max - max output video frame height
+ * maxPrefetchYUVFrames - max prefetch YUV frames in video editor engine. This value is used
+ * to limit the memory consumption.
+ */
+ int getVideoEditorCapParamByName(const char *name) const;
+
+ /**
+ * Returns the value for the given param name for the video editor export codec format
+ * param or -1 if error.
+ * Supported param name are:
+ * videoeditor.export.profile - export video profile
+ * videoeditor.export.level - export video level
+ * Supported param codec are:
+ * 1 for h263
+ * 2 for h264
+ * 3 for mpeg4
+ */
+ int getVideoEditorExportParamByName(const char *name, int codec) const;
+
+ /**
+ * Returns the audio encoders supported.
+ */
+ Vector<audio_encoder> getAudioEncoders() const;
+
+ /**
+ * Returns the value for the given param name for the given audio encoder
+ * returned from getAudioEncoderByIndex or -1 if error.
+ *
+ * Supported param name are:
+ * enc.aud.ch.min - min number of channels
+ * enc.aud.ch.max - max number of channels
+ * enc.aud.bps.min - min bit rate in bits per second
+ * enc.aud.bps.max - max bit rate in bits per second
+ * enc.aud.hz.min - min sample rate in samples per second
+ * enc.aud.hz.max - max sample rate in samples per second
+ */
+ int getAudioEncoderParamByName(const char *name, audio_encoder codec) const;
+
+ /**
+ * Returns the video decoders supported.
+ */
+ Vector<video_decoder> getVideoDecoders() const;
+
+ /**
+ * Returns the audio decoders supported.
+ */
+ Vector<audio_decoder> getAudioDecoders() const;
+
+ /**
+ * Returns the number of image encoding quality levels supported.
+ */
+ Vector<int> getImageEncodingQualityLevels(int cameraId) const;
+
+ /**
+ * Returns the start time offset (in ms) for the given camera Id.
+ * If the given camera Id does not exist, -1 will be returned.
+ */
+ int getStartTimeOffsetMs(int cameraId) const;
+
+private:
+ enum {
+ // Camcorder profiles (high/low) and timelapse profiles (high/low)
+ kNumRequiredProfiles = 4,
+ };
+
+ MediaProfiles& operator=(const MediaProfiles&); // Don't call me
+ MediaProfiles(const MediaProfiles&); // Don't call me
+ MediaProfiles() { mVideoEditorCap = NULL; } // Dummy default constructor
+ ~MediaProfiles(); // Don't delete me
+
+ struct VideoCodec {
+ VideoCodec(video_encoder codec, int bitRate, int frameWidth, int frameHeight, int frameRate)
+ : mCodec(codec),
+ mBitRate(bitRate),
+ mFrameWidth(frameWidth),
+ mFrameHeight(frameHeight),
+ mFrameRate(frameRate) {}
+
+ VideoCodec(const VideoCodec& copy) {
+ mCodec = copy.mCodec;
+ mBitRate = copy.mBitRate;
+ mFrameWidth = copy.mFrameWidth;
+ mFrameHeight = copy.mFrameHeight;
+ mFrameRate = copy.mFrameRate;
+ }
+
+ ~VideoCodec() {}
+
+ video_encoder mCodec;
+ int mBitRate;
+ int mFrameWidth;
+ int mFrameHeight;
+ int mFrameRate;
+ };
+
+ struct AudioCodec {
+ AudioCodec(audio_encoder codec, int bitRate, int sampleRate, int channels)
+ : mCodec(codec),
+ mBitRate(bitRate),
+ mSampleRate(sampleRate),
+ mChannels(channels) {}
+
+ AudioCodec(const AudioCodec& copy) {
+ mCodec = copy.mCodec;
+ mBitRate = copy.mBitRate;
+ mSampleRate = copy.mSampleRate;
+ mChannels = copy.mChannels;
+ }
+
+ ~AudioCodec() {}
+
+ audio_encoder mCodec;
+ int mBitRate;
+ int mSampleRate;
+ int mChannels;
+ };
+
+ struct CamcorderProfile {
+ CamcorderProfile()
+ : mCameraId(0),
+ mFileFormat(OUTPUT_FORMAT_THREE_GPP),
+ mQuality(CAMCORDER_QUALITY_HIGH),
+ mDuration(0),
+ mVideoCodec(0),
+ mAudioCodec(0) {}
+
+ CamcorderProfile(const CamcorderProfile& copy) {
+ mCameraId = copy.mCameraId;
+ mFileFormat = copy.mFileFormat;
+ mQuality = copy.mQuality;
+ mDuration = copy.mDuration;
+ mVideoCodec = new VideoCodec(*copy.mVideoCodec);
+ mAudioCodec = new AudioCodec(*copy.mAudioCodec);
+ }
+
+ ~CamcorderProfile() {
+ delete mVideoCodec;
+ delete mAudioCodec;
+ }
+
+ int mCameraId;
+ output_format mFileFormat;
+ camcorder_quality mQuality;
+ int mDuration;
+ VideoCodec *mVideoCodec;
+ AudioCodec *mAudioCodec;
+ };
+
+ struct VideoEncoderCap {
+ // Ugly constructor
+ VideoEncoderCap(video_encoder codec,
+ int minBitRate, int maxBitRate,
+ int minFrameWidth, int maxFrameWidth,
+ int minFrameHeight, int maxFrameHeight,
+ int minFrameRate, int maxFrameRate)
+ : mCodec(codec),
+ mMinBitRate(minBitRate), mMaxBitRate(maxBitRate),
+ mMinFrameWidth(minFrameWidth), mMaxFrameWidth(maxFrameWidth),
+ mMinFrameHeight(minFrameHeight), mMaxFrameHeight(maxFrameHeight),
+ mMinFrameRate(minFrameRate), mMaxFrameRate(maxFrameRate) {}
+
+ ~VideoEncoderCap() {}
+
+ video_encoder mCodec;
+ int mMinBitRate, mMaxBitRate;
+ int mMinFrameWidth, mMaxFrameWidth;
+ int mMinFrameHeight, mMaxFrameHeight;
+ int mMinFrameRate, mMaxFrameRate;
+ };
+
+ struct AudioEncoderCap {
+ // Ugly constructor
+ AudioEncoderCap(audio_encoder codec,
+ int minBitRate, int maxBitRate,
+ int minSampleRate, int maxSampleRate,
+ int minChannels, int maxChannels)
+ : mCodec(codec),
+ mMinBitRate(minBitRate), mMaxBitRate(maxBitRate),
+ mMinSampleRate(minSampleRate), mMaxSampleRate(maxSampleRate),
+ mMinChannels(minChannels), mMaxChannels(maxChannels) {}
+
+ ~AudioEncoderCap() {}
+
+ audio_encoder mCodec;
+ int mMinBitRate, mMaxBitRate;
+ int mMinSampleRate, mMaxSampleRate;
+ int mMinChannels, mMaxChannels;
+ };
+
+ struct VideoDecoderCap {
+ VideoDecoderCap(video_decoder codec): mCodec(codec) {}
+ ~VideoDecoderCap() {}
+
+ video_decoder mCodec;
+ };
+
+ struct AudioDecoderCap {
+ AudioDecoderCap(audio_decoder codec): mCodec(codec) {}
+ ~AudioDecoderCap() {}
+
+ audio_decoder mCodec;
+ };
+
+ struct NameToTagMap {
+ const char* name;
+ int tag;
+ };
+
+ struct ImageEncodingQualityLevels {
+ int mCameraId;
+ Vector<int> mLevels;
+ };
+ struct ExportVideoProfile {
+ ExportVideoProfile(int codec, int profile, int level)
+ :mCodec(codec),mProfile(profile),mLevel(level) {}
+ ~ExportVideoProfile() {}
+ int mCodec;
+ int mProfile;
+ int mLevel;
+ };
+ struct VideoEditorCap {
+ VideoEditorCap(int inFrameWidth, int inFrameHeight,
+ int outFrameWidth, int outFrameHeight, int frames)
+ : mMaxInputFrameWidth(inFrameWidth),
+ mMaxInputFrameHeight(inFrameHeight),
+ mMaxOutputFrameWidth(outFrameWidth),
+ mMaxOutputFrameHeight(outFrameHeight),
+ mMaxPrefetchYUVFrames(frames) {}
+
+ ~VideoEditorCap() {}
+
+ int mMaxInputFrameWidth;
+ int mMaxInputFrameHeight;
+ int mMaxOutputFrameWidth;
+ int mMaxOutputFrameHeight;
+ int mMaxPrefetchYUVFrames;
+ };
+
+ int getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const;
+ void initRequiredProfileRefs(const Vector<int>& cameraIds);
+ int getRequiredProfileRefIndex(int cameraId);
+
+ // Debug
+ static void logVideoCodec(const VideoCodec& codec);
+ static void logAudioCodec(const AudioCodec& codec);
+ static void logVideoEncoderCap(const VideoEncoderCap& cap);
+ static void logAudioEncoderCap(const AudioEncoderCap& cap);
+ static void logVideoDecoderCap(const VideoDecoderCap& cap);
+ static void logAudioDecoderCap(const AudioDecoderCap& cap);
+ static void logVideoEditorCap(const VideoEditorCap& cap);
+
+ // If the xml configuration file does exist, use the settings
+ // from the xml
+ static MediaProfiles* createInstanceFromXmlFile(const char *xml);
+ static output_format createEncoderOutputFileFormat(const char **atts);
+ static VideoCodec* createVideoCodec(const char **atts, MediaProfiles *profiles);
+ static AudioCodec* createAudioCodec(const char **atts, MediaProfiles *profiles);
+ static AudioDecoderCap* createAudioDecoderCap(const char **atts);
+ static VideoDecoderCap* createVideoDecoderCap(const char **atts);
+ static VideoEncoderCap* createVideoEncoderCap(const char **atts);
+ static AudioEncoderCap* createAudioEncoderCap(const char **atts);
+ static VideoEditorCap* createVideoEditorCap(
+ const char **atts, MediaProfiles *profiles);
+ static ExportVideoProfile* createExportVideoProfile(const char **atts);
+
+ static CamcorderProfile* createCamcorderProfile(
+ int cameraId, const char **atts, Vector<int>& cameraIds);
+
+ static int getCameraId(const char **atts);
+
+ void addStartTimeOffset(int cameraId, const char **atts);
+
+ ImageEncodingQualityLevels* findImageEncodingQualityLevels(int cameraId) const;
+ void addImageEncodingQualityLevel(int cameraId, const char** atts);
+
+ // Customized element tag handler for parsing the xml configuration file.
+ static void startElementHandler(void *userData, const char *name, const char **atts);
+
+ // If the xml configuration file does not exist, use hard-coded values
+ static MediaProfiles* createDefaultInstance();
+
+ static CamcorderProfile *createDefaultCamcorderQcifProfile(camcorder_quality quality);
+ static CamcorderProfile *createDefaultCamcorderCifProfile(camcorder_quality quality);
+ static void createDefaultCamcorderLowProfiles(
+ MediaProfiles::CamcorderProfile **lowProfile,
+ MediaProfiles::CamcorderProfile **lowSpecificProfile);
+ static void createDefaultCamcorderHighProfiles(
+ MediaProfiles::CamcorderProfile **highProfile,
+ MediaProfiles::CamcorderProfile **highSpecificProfile);
+
+ static CamcorderProfile *createDefaultCamcorderTimeLapseQcifProfile(camcorder_quality quality);
+ static CamcorderProfile *createDefaultCamcorderTimeLapse480pProfile(camcorder_quality quality);
+ static void createDefaultCamcorderTimeLapseLowProfiles(
+ MediaProfiles::CamcorderProfile **lowTimeLapseProfile,
+ MediaProfiles::CamcorderProfile **lowSpecificTimeLapseProfile);
+ static void createDefaultCamcorderTimeLapseHighProfiles(
+ MediaProfiles::CamcorderProfile **highTimeLapseProfile,
+ MediaProfiles::CamcorderProfile **highSpecificTimeLapseProfile);
+
+ static void createDefaultCamcorderProfiles(MediaProfiles *profiles);
+ static void createDefaultVideoEncoders(MediaProfiles *profiles);
+ static void createDefaultAudioEncoders(MediaProfiles *profiles);
+ static void createDefaultVideoDecoders(MediaProfiles *profiles);
+ static void createDefaultAudioDecoders(MediaProfiles *profiles);
+ static void createDefaultEncoderOutputFileFormats(MediaProfiles *profiles);
+ static void createDefaultImageEncodingQualityLevels(MediaProfiles *profiles);
+ static void createDefaultImageDecodingMaxMemory(MediaProfiles *profiles);
+ static void createDefaultVideoEditorCap(MediaProfiles *profiles);
+ static void createDefaultExportVideoProfiles(MediaProfiles *profiles);
+
+ static VideoEncoderCap* createDefaultH263VideoEncoderCap();
+ static VideoEncoderCap* createDefaultM4vVideoEncoderCap();
+ static AudioEncoderCap* createDefaultAmrNBEncoderCap();
+
+ static int findTagForName(const NameToTagMap *map, size_t nMappings, const char *name);
+
+ /**
+ * Check on existing profiles with the following criteria:
+ * 1. Low quality profile must have the lowest video
+ * resolution product (width x height)
+ * 2. High quality profile must have the highest video
+ * resolution product (width x height)
+ *
+ * and add required low/high quality camcorder/timelapse
+ * profiles if they are not found. This allows to remove
+ * duplicate profile definitions in the media_profiles.xml
+ * file.
+ */
+ void checkAndAddRequiredProfilesIfNecessary();
+
+
+ // Mappings from name (for instance, codec name) to enum value
+ static const NameToTagMap sVideoEncoderNameMap[];
+ static const NameToTagMap sAudioEncoderNameMap[];
+ static const NameToTagMap sFileFormatMap[];
+ static const NameToTagMap sVideoDecoderNameMap[];
+ static const NameToTagMap sAudioDecoderNameMap[];
+ static const NameToTagMap sCamcorderQualityNameMap[];
+
+ static bool sIsInitialized;
+ static MediaProfiles *sInstance;
+ static Mutex sLock;
+ int mCurrentCameraId;
+
+ Vector<CamcorderProfile*> mCamcorderProfiles;
+ Vector<AudioEncoderCap*> mAudioEncoders;
+ Vector<VideoEncoderCap*> mVideoEncoders;
+ Vector<AudioDecoderCap*> mAudioDecoders;
+ Vector<VideoDecoderCap*> mVideoDecoders;
+ Vector<output_format> mEncoderOutputFileFormats;
+ Vector<ImageEncodingQualityLevels *> mImageEncodingQualityLevels;
+ KeyedVector<int, int> mStartTimeOffsets;
+
+ typedef struct {
+ bool mHasRefProfile; // Refers to an existing profile
+ int mRefProfileIndex; // Reference profile index
+ int mResolutionProduct; // width x height
+ } RequiredProfileRefInfo; // Required low and high profiles
+
+ typedef struct {
+ RequiredProfileRefInfo mRefs[kNumRequiredProfiles];
+ int mCameraId;
+ } RequiredProfiles;
+
+ RequiredProfiles *mRequiredProfileRefs;
+ Vector<int> mCameraIds;
+ VideoEditorCap* mVideoEditorCap;
+ Vector<ExportVideoProfile*> mVideoEditorExportProfiles;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIAPROFILES_H
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
new file mode 100644
index 0000000..ef799f5
--- /dev/null
+++ b/include/media/MediaRecorderBase.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#ifndef MEDIA_RECORDER_BASE_H_
+
+#define MEDIA_RECORDER_BASE_H_
+
+#include <media/mediarecorder.h>
+
+#include <system/audio.h>
+
+namespace android {
+
+class ICameraRecordingProxy;
+class Surface;
+class ISurfaceTexture;
+
+struct MediaRecorderBase {
+ MediaRecorderBase() {}
+ virtual ~MediaRecorderBase() {}
+
+ virtual status_t init() = 0;
+ virtual status_t setAudioSource(audio_source_t as) = 0;
+ virtual status_t setVideoSource(video_source vs) = 0;
+ virtual status_t setOutputFormat(output_format of) = 0;
+ virtual status_t setAudioEncoder(audio_encoder ae) = 0;
+ virtual status_t setVideoEncoder(video_encoder ve) = 0;
+ virtual status_t setVideoSize(int width, int height) = 0;
+ virtual status_t setVideoFrameRate(int frames_per_second) = 0;
+ virtual status_t setCamera(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy) = 0;
+ virtual status_t setPreviewSurface(const sp<Surface>& surface) = 0;
+ virtual status_t setOutputFile(const char *path) = 0;
+ virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
+ virtual status_t setOutputFileAuxiliary(int fd) {return INVALID_OPERATION;}
+ virtual status_t setParameters(const String8& params) = 0;
+ virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0;
+ virtual status_t prepare() = 0;
+ virtual status_t start() = 0;
+ virtual status_t stop() = 0;
+ virtual status_t close() = 0;
+ virtual status_t reset() = 0;
+ virtual status_t getMaxAmplitude(int *max) = 0;
+ virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
+ virtual sp<ISurfaceTexture> querySurfaceMediaSource() const = 0;
+
+private:
+ MediaRecorderBase(const MediaRecorderBase &);
+ MediaRecorderBase &operator=(const MediaRecorderBase &);
+};
+
+} // namespace android
+
+#endif // MEDIA_RECORDER_BASE_H_
diff --git a/include/media/MemoryLeakTrackUtil.h b/include/media/MemoryLeakTrackUtil.h
new file mode 100644
index 0000000..d2618aa
--- /dev/null
+++ b/include/media/MemoryLeakTrackUtil.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 MEMORY_LEAK_TRACK_UTIL_H
+#define MEMORY_LEAK_TRACK_UTIL_H
+
+namespace android {
+/*
+ * Dump the memory address of the calling process to the given fd.
+ */
+extern void dumpMemoryAddresses(int fd);
+
+};
+
+#endif // MEMORY_LEAK_TRACK_UTIL_H
diff --git a/include/media/Metadata.h b/include/media/Metadata.h
new file mode 100644
index 0000000..07567eb
--- /dev/null
+++ b/include/media/Metadata.h
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_MEDIA_METADATA_H__
+#define ANDROID_MEDIA_METADATA_H__
+
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+
+namespace android {
+class Parcel;
+
+namespace media {
+
+// Metadata is a class to build/serialize a set of metadata in a Parcel.
+//
+// This class should be kept in sync with android/media/Metadata.java.
+// It provides all the metadata ids available and methods to build the
+// header, add records and adjust the set size header field.
+//
+// Typical Usage:
+// ==============
+// Parcel p;
+// media::Metadata data(&p);
+//
+// data.appendHeader();
+// data.appendBool(Metadata::kPauseAvailable, true);
+// ... more append ...
+// data.updateLength();
+//
+
+class Metadata {
+ public:
+ typedef int32_t Type;
+ typedef SortedVector<Type> Filter;
+
+ static const Type kAny = 0;
+
+ // Playback capabilities.
+ static const Type kPauseAvailable = 1; // Boolean
+ static const Type kSeekBackwardAvailable = 2; // Boolean
+ static const Type kSeekForwardAvailable = 3; // Boolean
+ static const Type kSeekAvailable = 4; // Boolean
+
+ // Keep in sync with android/media/Metadata.java
+ static const Type kTitle = 5; // String
+ static const Type kComment = 6; // String
+ static const Type kCopyright = 7; // String
+ static const Type kAlbum = 8; // String
+ static const Type kArtist = 9; // String
+ static const Type kAuthor = 10; // String
+ static const Type kComposer = 11; // String
+ static const Type kGenre = 12; // String
+ static const Type kDate = 13; // Date
+ static const Type kDuration = 14; // Integer(millisec)
+ static const Type kCdTrackNum = 15; // Integer 1-based
+ static const Type kCdTrackMax = 16; // Integer
+ static const Type kRating = 17; // String
+ static const Type kAlbumArt = 18; // byte[]
+ static const Type kVideoFrame = 19; // Bitmap
+
+ static const Type kBitRate = 20; // Integer, Aggregate rate of
+ // all the streams in bps.
+
+ static const Type kAudioBitRate = 21; // Integer, bps
+ static const Type kVideoBitRate = 22; // Integer, bps
+ static const Type kAudioSampleRate = 23; // Integer, Hz
+ static const Type kVideoframeRate = 24; // Integer, Hz
+
+ // See RFC2046 and RFC4281.
+ static const Type kMimeType = 25; // String
+ static const Type kAudioCodec = 26; // String
+ static const Type kVideoCodec = 27; // String
+
+ static const Type kVideoHeight = 28; // Integer
+ static const Type kVideoWidth = 29; // Integer
+ static const Type kNumTracks = 30; // Integer
+ static const Type kDrmCrippled = 31; // Boolean
+
+ // @param p[inout] The parcel to append the metadata records
+ // to. The global metadata header should have been set already.
+ explicit Metadata(Parcel *p);
+ ~Metadata();
+
+ // Rewind the underlying parcel, undoing all the changes.
+ void resetParcel();
+
+ // Append the size and 'META' marker.
+ bool appendHeader();
+
+ // Once all the records have been added, call this to update the
+ // lenght field in the header.
+ void updateLength();
+
+ // append* are methods to append metadata.
+ // @param key Is the metadata Id.
+ // @param val Is the value of the metadata.
+ // @return true if successful, false otherwise.
+ // TODO: add more as needed to handle other types.
+ bool appendBool(Type key, bool val);
+ bool appendInt32(Type key, int32_t val);
+
+ private:
+ Metadata(const Metadata&);
+ Metadata& operator=(const Metadata&);
+
+
+ // Checks the key is valid and not already present.
+ bool checkKey(Type key);
+
+ Parcel *mData;
+ size_t mBegin;
+};
+
+} // namespace android::media
+} // namespace android
+
+#endif // ANDROID_MEDIA_METADATA_H__
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
new file mode 100644
index 0000000..df0c97e
--- /dev/null
+++ b/include/media/ToneGenerator.h
@@ -0,0 +1,313 @@
+/*
+ * 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_TONEGENERATOR_H_
+#define ANDROID_TONEGENERATOR_H_
+
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+#include <media/AudioSystem.h>
+#include <media/AudioTrack.h>
+
+namespace android {
+
+class ToneGenerator {
+public:
+
+ // List of all available tones
+ // This enum must be kept consistant with constants in ToneGenerator JAVA class
+ enum tone_type {
+ // DTMF tones ITU-T Recommendation Q.23
+ TONE_DTMF_0 = 0, // 0 key: 1336Hz, 941Hz
+ TONE_DTMF_1, // 1 key: 1209Hz, 697Hz
+ TONE_DTMF_2, // 2 key: 1336Hz, 697Hz
+ TONE_DTMF_3, // 3 key: 1477Hz, 697Hz
+ TONE_DTMF_4, // 4 key: 1209Hz, 770Hz
+ TONE_DTMF_5, // 5 key: 1336Hz, 770Hz
+ TONE_DTMF_6, // 6 key: 1477Hz, 770Hz
+ TONE_DTMF_7, // 7 key: 1209Hz, 852Hz
+ TONE_DTMF_8, // 8 key: 1336Hz, 852Hz
+ TONE_DTMF_9, // 9 key: 1477Hz, 852Hz
+ TONE_DTMF_S, // * key: 1209Hz, 941Hz
+ TONE_DTMF_P, // # key: 1477Hz, 941Hz
+ TONE_DTMF_A, // A key: 1633Hz, 697Hz
+ TONE_DTMF_B, // B key: 1633Hz, 770Hz
+ TONE_DTMF_C, // C key: 1633Hz, 852Hz
+ TONE_DTMF_D, // D key: 1633Hz, 941Hz
+ // Call supervisory tones: 3GPP TS 22.001 (CEPT)
+ TONE_SUP_DIAL, // Dial tone: CEPT: 425Hz, continuous
+ FIRST_SUP_TONE = TONE_SUP_DIAL,
+ TONE_SUP_BUSY, // Busy tone, CEPT: 425Hz, 500ms ON, 500ms OFF...
+ TONE_SUP_CONGESTION, // Congestion tone CEPT, JAPAN: 425Hz, 200ms ON, 200ms OFF...
+ TONE_SUP_RADIO_ACK, // Radio path acknowlegment, CEPT, ANSI: 425Hz, 200ms ON
+ TONE_SUP_RADIO_NOTAVAIL, // Radio path not available: 425Hz, 200ms ON, 200 OFF 3 bursts
+ TONE_SUP_ERROR, // Error/Special info: 950Hz+1400Hz+1800Hz, 330ms ON, 1s OFF...
+ TONE_SUP_CALL_WAITING, // Call Waiting CEPT,JAPAN: 425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF...
+ TONE_SUP_RINGTONE, // Ring Tone CEPT, JAPAN: 425Hz, 1s ON, 4s OFF...
+ LAST_SUP_TONE = TONE_SUP_RINGTONE,
+ // Proprietary tones: 3GPP TS 31.111
+ TONE_PROP_BEEP, // General beep: 400Hz+1200Hz, 35ms ON
+ TONE_PROP_ACK, // Positive Acknowlgement: 1200Hz, 100ms ON, 100ms OFF 2 bursts
+ TONE_PROP_NACK, // Negative Acknowlgement: 300Hz+400Hz+500Hz, 400ms ON
+ TONE_PROP_PROMPT, // Prompt tone: 400Hz+1200Hz, 200ms ON
+ TONE_PROP_BEEP2, // General double beep: 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms on
+ // Additional call supervisory tones: specified by IS-95 only
+ TONE_SUP_INTERCEPT, // Intercept tone: alternating 440 Hz and 620 Hz tones, each on for 250 ms.
+ TONE_SUP_INTERCEPT_ABBREV, // Abbreviated intercept: intercept tone limited to 4 seconds
+ TONE_SUP_CONGESTION_ABBREV, // Abbreviated congestion: congestion tone limited to 4 seconds
+ TONE_SUP_CONFIRM, // Confirm tone: a 350 Hz tone added to a 440 Hz tone repeated 3 times in a 100 ms on, 100 ms off cycle.
+ TONE_SUP_PIP, // Pip tone: four bursts of 480 Hz tone (0.1 s on, 0.1 s off).
+
+ // CDMA Tones
+ TONE_CDMA_DIAL_TONE_LITE,
+ TONE_CDMA_NETWORK_USA_RINGBACK,
+ TONE_CDMA_INTERCEPT,
+ TONE_CDMA_ABBR_INTERCEPT,
+ TONE_CDMA_REORDER,
+ TONE_CDMA_ABBR_REORDER,
+ TONE_CDMA_NETWORK_BUSY,
+ TONE_CDMA_CONFIRM,
+ TONE_CDMA_ANSWER,
+ TONE_CDMA_NETWORK_CALLWAITING,
+ TONE_CDMA_PIP,
+
+ // ISDN
+ TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL, // ISDN Alert Normal
+ TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP, // ISDN Intergroup
+ TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI, // ISDN SP PRI
+ TONE_CDMA_CALL_SIGNAL_ISDN_PAT3, // ISDN Alert PAT3
+ TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING, // ISDN Alert PING RING
+ TONE_CDMA_CALL_SIGNAL_ISDN_PAT5, // ISDN Alert PAT5
+ TONE_CDMA_CALL_SIGNAL_ISDN_PAT6, // ISDN Alert PAT6
+ TONE_CDMA_CALL_SIGNAL_ISDN_PAT7, // ISDN Alert PAT7
+ // ISDN end
+
+ // IS54
+ TONE_CDMA_HIGH_L, // IS54 High Pitch Long
+ TONE_CDMA_MED_L, // IS54 Med Pitch Long
+ TONE_CDMA_LOW_L, // IS54 Low Pitch Long
+ TONE_CDMA_HIGH_SS, // IS54 High Pitch Short Short
+ TONE_CDMA_MED_SS, // IS54 Medium Pitch Short Short
+ TONE_CDMA_LOW_SS, // IS54 Low Pitch Short Short
+ TONE_CDMA_HIGH_SSL, // IS54 High Pitch Short Short Long
+ TONE_CDMA_MED_SSL, // IS54 Medium Pitch Short Short Long
+ TONE_CDMA_LOW_SSL, // IS54 Low Pitch Short Short Long
+ TONE_CDMA_HIGH_SS_2, // IS54 High Pitch Short Short 2
+ TONE_CDMA_MED_SS_2, // IS54 Med Pitch Short Short 2
+ TONE_CDMA_LOW_SS_2, // IS54 Low Pitch Short Short 2
+ TONE_CDMA_HIGH_SLS, // IS54 High Pitch Short Long Short
+ TONE_CDMA_MED_SLS, // IS54 Med Pitch Short Long Short
+ TONE_CDMA_LOW_SLS, // IS54 Low Pitch Short Long Short
+ TONE_CDMA_HIGH_S_X4, // IS54 High Pitch Short Short Short Short
+ TONE_CDMA_MED_S_X4, // IS54 Med Pitch Short Short Short Short
+ TONE_CDMA_LOW_S_X4, // IS54 Low Pitch Short Short Short Short
+ TONE_CDMA_HIGH_PBX_L, // PBX High Pitch Long
+ TONE_CDMA_MED_PBX_L, // PBX Med Pitch Long
+ TONE_CDMA_LOW_PBX_L, // PBX Low Pitch Long
+ TONE_CDMA_HIGH_PBX_SS, // PBX High Short Short
+ TONE_CDMA_MED_PBX_SS, // PBX Med Short Short
+ TONE_CDMA_LOW_PBX_SS, // PBX Low Short Short
+ TONE_CDMA_HIGH_PBX_SSL, // PBX High Short Short Long
+ TONE_CDMA_MED_PBX_SSL, // PBX Med Short Short Long
+ TONE_CDMA_LOW_PBX_SSL, // PBX Low Short Short Long
+ TONE_CDMA_HIGH_PBX_SLS, // PBX High SLS
+ TONE_CDMA_MED_PBX_SLS, // PBX Med SLS
+ TONE_CDMA_LOW_PBX_SLS, // PBX Low SLS
+ TONE_CDMA_HIGH_PBX_S_X4, // PBX High SSSS
+ TONE_CDMA_MED_PBX_S_X4, // PBX Med SSSS
+ TONE_CDMA_LOW_PBX_S_X4, // PBX LOW SSSS
+ //IS54 end
+ // proprietary
+ TONE_CDMA_ALERT_NETWORK_LITE,
+ TONE_CDMA_ALERT_AUTOREDIAL_LITE,
+ TONE_CDMA_ONE_MIN_BEEP,
+ TONE_CDMA_KEYPAD_VOLUME_KEY_LITE,
+ TONE_CDMA_PRESSHOLDKEY_LITE,
+ TONE_CDMA_ALERT_INCALL_LITE,
+ TONE_CDMA_EMERGENCY_RINGBACK,
+ TONE_CDMA_ALERT_CALL_GUARD,
+ TONE_CDMA_SOFT_ERROR_LITE,
+ TONE_CDMA_CALLDROP_LITE,
+ // proprietary end
+ TONE_CDMA_NETWORK_BUSY_ONE_SHOT,
+ TONE_CDMA_ABBR_ALERT,
+ TONE_CDMA_SIGNAL_OFF,
+ //CDMA end
+ NUM_TONES,
+ NUM_SUP_TONES = LAST_SUP_TONE-FIRST_SUP_TONE+1
+ };
+
+ ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava = false);
+ ~ToneGenerator();
+
+ bool startTone(tone_type toneType, int durationMs = -1);
+ void stopTone();
+
+ bool isInited() { return (mState == TONE_IDLE)?false:true;}
+
+private:
+
+ enum tone_state {
+ TONE_IDLE, // ToneGenerator is being initialized or initialization failed
+ TONE_INIT, // ToneGenerator has been successfully initialized and is not playing
+ TONE_STARTING, // ToneGenerator is starting playing
+ TONE_PLAYING, // ToneGenerator is playing
+ TONE_STOPPING, // ToneGenerator is stoping
+ TONE_STOPPED, // ToneGenerator is stopped: the AudioTrack will be stopped
+ TONE_RESTARTING // A start request was received in active state (playing or stopping)
+ };
+
+
+ // Region specific tones.
+ // These supervisory tones are different depending on the region (USA/CANADA, JAPAN, rest of the world).
+ // When a tone in the range [FIRST_SUP_TONE, LAST_SUP_TONE] is requested, the region is determined
+ // from system property gsm.operator.iso-country and the proper tone descriptor is selected with the
+ // help of sToneMappingTable[]
+ enum regional_tone_type {
+ // ANSI supervisory tones
+ TONE_ANSI_DIAL = NUM_TONES, // Dial tone: a continuous 350 Hz + 440 Hz tone.
+ TONE_ANSI_BUSY, // Busy tone on: a 480 Hz + 620 Hz tone repeated in a 500 ms on, 500 ms off cycle.
+ TONE_ANSI_CONGESTION, // Network congestion (reorder) tone on: a 480 Hz + 620 Hz tone repeated in a 250 ms on, 250 ms off cycle.
+ TONE_ANSI_CALL_WAITING, // Call waiting tone on: 440 Hz, on for 300 ms, 9,7 s off followed by
+ // (440 Hz, on for 100 ms off for 100 ms, on for 100 ms, 9,7s off and repeated as necessary).
+ TONE_ANSI_RINGTONE, // Ring Tone: a 440 Hz + 480 Hz tone repeated in a 2 s on, 4 s off pattern.
+ // JAPAN Supervisory tones
+ TONE_JAPAN_DIAL, // Dial tone: 400Hz, continuous
+ TONE_JAPAN_BUSY, // Busy tone: 400Hz, 500ms ON, 500ms OFF...
+ TONE_JAPAN_RADIO_ACK, // Radio path acknowlegment: 400Hz, 1s ON, 2s OFF...
+ NUM_ALTERNATE_TONES
+ };
+
+ enum region {
+ ANSI,
+ JAPAN,
+ CEPT,
+ NUM_REGIONS
+ };
+
+ static const unsigned char sToneMappingTable[NUM_REGIONS-1][NUM_SUP_TONES];
+
+ static const unsigned int TONEGEN_MAX_WAVES = 3; // Maximun number of sine waves in a tone segment
+ static const unsigned int TONEGEN_MAX_SEGMENTS = 12; // Maximun number of segments in a tone descriptor
+ static const unsigned int TONEGEN_INF = 0xFFFFFFFF; // Represents infinite time duration
+ static const float TONEGEN_GAIN = 0.9; // Default gain passed to WaveGenerator().
+
+ // ToneDescriptor class contains all parameters needed to generate a tone:
+ // - The array waveFreq[]:
+ // 1 for static tone descriptors: contains the frequencies of all individual waves making the multi-tone.
+ // 2 for active tone descritors: contains the indexes of the WaveGenerator objects in mWaveGens
+ // The number of sine waves varies from 1 to TONEGEN_MAX_WAVES.
+ // The first null value indicates that no more waves are needed.
+ // - The array segments[] is used to generate the tone pulses. A segment is a period of time
+ // during which the tone is ON or OFF. Segments with even index (starting from 0)
+ // correspond to tone ON state and segments with odd index to OFF state.
+ // The data stored in segments[] is the duration of the corresponding period in ms.
+ // The first segment encountered with a 0 duration indicates that no more segment follows.
+ // - loopCnt - Number of times to repeat a sequence of seqments after playing this
+ // - loopIndx - The segment index to go back and play is loopcnt > 0
+ // - repeatCnt indicates the number of times the sequence described by segments[] array must be repeated.
+ // When the tone generator encounters the first 0 duration segment, it will compare repeatCnt to mCurCount.
+ // If mCurCount > repeatCnt, the tone is stopped automatically. Otherwise, tone sequence will be
+ // restarted from segment repeatSegment.
+ // - repeatSegment number of the first repeated segment when repeatCnt is not null
+
+ class ToneSegment {
+ public:
+ unsigned int duration;
+ unsigned short waveFreq[TONEGEN_MAX_WAVES+1];
+ unsigned short loopCnt;
+ unsigned short loopIndx;
+ };
+
+ class ToneDescriptor {
+ public:
+ ToneSegment segments[TONEGEN_MAX_SEGMENTS+1];
+ unsigned long repeatCnt;
+ unsigned long repeatSegment;
+ };
+
+ static const ToneDescriptor sToneDescriptors[];
+
+ bool mThreadCanCallJava;
+ unsigned int mTotalSmp; // Total number of audio samples played (gives current time)
+ unsigned int mNextSegSmp; // Position of next segment transition expressed in samples
+ // NOTE: because mTotalSmp, mNextSegSmp are stored on 32 bit, current design will operate properly
+ // only if tone duration is less than about 27 Hours(@44100Hz sampling rate). If this time is exceeded,
+ // no crash will occur but tone sequence will show a glitch.
+ unsigned int mMaxSmp; // Maximum number of audio samples played (maximun tone duration)
+ int mDurationMs; // Maximum tone duration in ms
+
+ unsigned short mCurSegment; // Current segment index in ToneDescriptor segments[]
+ unsigned short mCurCount; // Current sequence repeat count
+ volatile unsigned short mState; // ToneGenerator state (tone_state)
+ unsigned short mRegion;
+ const ToneDescriptor *mpToneDesc; // pointer to active tone descriptor
+ const ToneDescriptor *mpNewToneDesc; // pointer to next active tone descriptor
+
+ unsigned short mLoopCounter; // Current tone loopback count
+
+ int mSamplingRate; // AudioFlinger Sampling rate
+ AudioTrack *mpAudioTrack; // Pointer to audio track used for playback
+ Mutex mLock; // Mutex to control concurent access to ToneGenerator object from audio callback and application API
+ Mutex mCbkCondLock; // Mutex associated to mWaitCbkCond
+ Condition mWaitCbkCond; // condition enabling interface to wait for audio callback completion after a change is requested
+ float mVolume; // Volume applied to audio track
+ audio_stream_type_t mStreamType; // Audio stream used for output
+ unsigned int mProcessSize; // Size of audio blocks generated at a time by audioCallback() (in PCM frames).
+
+ bool initAudioTrack();
+ static void audioCallback(int event, void* user, void *info);
+ bool prepareWave();
+ unsigned int numWaves(unsigned int segmentIdx);
+ void clearWaveGens();
+ tone_type getToneForRegion(tone_type toneType);
+
+ // WaveGenerator generates a single sine wave
+ class WaveGenerator {
+ public:
+ enum gen_command {
+ WAVEGEN_START, // Start/restart wave from phase 0
+ WAVEGEN_CONT, // Continue wave from current phase
+ WAVEGEN_STOP // Stop wave on zero crossing
+ };
+
+ WaveGenerator(unsigned short samplingRate, unsigned short frequency,
+ float volume);
+ ~WaveGenerator();
+
+ void getSamples(short *outBuffer, unsigned int count,
+ unsigned int command);
+
+ private:
+ static const short GEN_AMP = 32000; // amplitude of generator
+ static const short S_Q14 = 14; // shift for Q14
+ static const short S_Q15 = 15; // shift for Q15
+
+ short mA1_Q14; // Q14 coefficient
+ // delay line of full amplitude generator
+ short mS1, mS2; // delay line S2 oldest
+ short mS2_0; // saved value for reinitialisation
+ short mAmplitude_Q15; // Q15 amplitude
+ };
+
+ KeyedVector<unsigned short, WaveGenerator *> mWaveGens; // list of active wave generators.
+};
+
+}
+; // namespace android
+
+#endif /*ANDROID_TONEGENERATOR_H_*/
diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h
new file mode 100644
index 0000000..60fa15b
--- /dev/null
+++ b/include/media/Visualizer.h
@@ -0,0 +1,159 @@
+/*
+ * 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_MEDIA_VISUALIZER_H
+#define ANDROID_MEDIA_VISUALIZER_H
+
+#include <media/AudioEffect.h>
+#include <audio_effects/effect_visualizer.h>
+#include <string.h>
+
+/**
+ * The Visualizer class enables application to retrieve part of the currently playing audio for
+ * visualization purpose. It is not an audio recording interface and only returns partial and low
+ * quality audio content. However, to protect privacy of certain audio data (e.g voice mail) the use
+ * of the visualizer requires the permission android.permission.RECORD_AUDIO.
+ * The audio session ID passed to the constructor indicates which audio content should be
+ * visualized:
+ * - If the session is 0, the audio output mix is visualized
+ * - If the session is not 0, the audio from a particular MediaPlayer or AudioTrack
+ * using this audio session is visualized
+ * Two types of representation of audio content can be captured:
+ * - Waveform data: consecutive 8-bit (unsigned) mono samples by using the getWaveForm() method
+ * - Frequency data: 8-bit magnitude FFT by using the getFft() method
+ *
+ * The length of the capture can be retrieved or specified by calling respectively
+ * getCaptureSize() and setCaptureSize() methods. Note that the size of the FFT
+ * is half of the specified capture size but both sides of the spectrum are returned yielding in a
+ * number of bytes equal to the capture size. The capture size must be a power of 2 in the range
+ * returned by getMinCaptureSize() and getMaxCaptureSize().
+ * In addition to the polling capture mode, a callback mode is also available by installing a
+ * callback function by use of the setCaptureCallBack() method. The rate at which the callback
+ * is called as well as the type of data returned is specified.
+ * Before capturing data, the Visualizer must be enabled by calling the setEnabled() method.
+ * When data capture is not needed any more, the Visualizer should be disabled.
+ */
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class Visualizer: public AudioEffect {
+public:
+
+ enum callback_flags {
+ CAPTURE_WAVEFORM = 0x00000001, // capture callback returns a PCM wave form
+ CAPTURE_FFT = 0x00000002, // apture callback returns a frequency representation
+ CAPTURE_CALL_JAVA = 0x00000004 // the callback thread can call java
+ };
+
+
+ /* Constructor.
+ * See AudioEffect constructor for details on parameters.
+ */
+ Visualizer(int32_t priority = 0,
+ effect_callback_t cbf = NULL,
+ void* user = NULL,
+ int sessionId = 0);
+
+ ~Visualizer();
+
+ virtual status_t setEnabled(bool enabled);
+
+ // maximum capture size in samples
+ static uint32_t getMaxCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MAX; }
+ // minimum capture size in samples
+ static uint32_t getMinCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MIN; }
+ // maximum capture rate in millihertz
+ static uint32_t getMaxCaptureRate() { return CAPTURE_RATE_MAX; }
+
+ // callback used to return periodic PCM or FFT captures to the application. Either one or both
+ // types of data are returned (PCM and FFT) according to flags indicated when installing the
+ // callback. When a type of data is not present, the corresponding size (waveformSize or
+ // fftSize) is 0.
+ typedef void (*capture_cbk_t)(void* user,
+ uint32_t waveformSize,
+ uint8_t *waveform,
+ uint32_t fftSize,
+ uint8_t *fft,
+ uint32_t samplingrate);
+
+ // install a callback to receive periodic captures. The capture rate is specified in milliHertz
+ // and the capture format is according to flags (see callback_flags).
+ status_t setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, uint32_t rate);
+
+ // set the capture size capture size must be a power of two in the range
+ // [VISUALIZER_CAPTURE_SIZE_MAX. VISUALIZER_CAPTURE_SIZE_MIN]
+ // must be called when the visualizer is not enabled
+ status_t setCaptureSize(uint32_t size);
+ uint32_t getCaptureSize() { return mCaptureSize; }
+
+ // returns the capture rate indicated when installing the callback
+ uint32_t getCaptureRate() { return mCaptureRate; }
+
+ // returns the sampling rate of the audio being captured
+ uint32_t getSamplingRate() { return mSampleRate; }
+
+ // return a capture in PCM 8 bit unsigned format. The size of the capture is equal to
+ // getCaptureSize()
+ status_t getWaveForm(uint8_t *waveform);
+
+ // return a capture in FFT 8 bit signed format. The size of the capture is equal to
+ // getCaptureSize() but the length of the FFT is half of the size (both parts of the spectrum
+ // are returned
+ status_t getFft(uint8_t *fft);
+
+private:
+
+ static const uint32_t CAPTURE_RATE_MAX = 20000;
+ static const uint32_t CAPTURE_RATE_DEF = 10000;
+ static const uint32_t CAPTURE_SIZE_DEF = VISUALIZER_CAPTURE_SIZE_MAX;
+
+ /* internal class to handle the callback */
+ class CaptureThread : public Thread
+ {
+ public:
+ CaptureThread(Visualizer& receiver, uint32_t captureRate, bool bCanCallJava = false);
+
+ private:
+ friend class Visualizer;
+ virtual bool threadLoop();
+ virtual status_t readyToRun();
+ virtual void onFirstRef();
+ Visualizer& mReceiver;
+ Mutex mLock;
+ uint32_t mSleepTimeUs;
+ };
+
+ status_t doFft(uint8_t *fft, uint8_t *waveform);
+ void periodicCapture();
+ uint32_t initCaptureSize();
+
+ Mutex mCaptureLock;
+ uint32_t mCaptureRate;
+ uint32_t mCaptureSize;
+ uint32_t mSampleRate;
+ capture_cbk_t mCaptureCallBack;
+ void *mCaptureCbkUser;
+ sp<CaptureThread> mCaptureThread;
+ uint32_t mCaptureFlags;
+};
+
+
+}; // namespace android
+
+#endif // ANDROID_MEDIA_VISUALIZER_H
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
new file mode 100644
index 0000000..534afce
--- /dev/null
+++ b/include/media/mediametadataretriever.h
@@ -0,0 +1,100 @@
+/*
+ * 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 MEDIAMETADATARETRIEVER_H
+#define MEDIAMETADATARETRIEVER_H
+
+#include <utils/Errors.h> // for status_t
+#include <utils/threads.h>
+#include <binder/IMemory.h>
+#include <media/IMediaMetadataRetriever.h>
+
+namespace android {
+
+class IMediaPlayerService;
+class IMediaMetadataRetriever;
+
+// Keep these in synch with the constants defined in MediaMetadataRetriever.java
+// class.
+enum {
+ METADATA_KEY_CD_TRACK_NUMBER = 0,
+ METADATA_KEY_ALBUM = 1,
+ METADATA_KEY_ARTIST = 2,
+ METADATA_KEY_AUTHOR = 3,
+ METADATA_KEY_COMPOSER = 4,
+ METADATA_KEY_DATE = 5,
+ METADATA_KEY_GENRE = 6,
+ METADATA_KEY_TITLE = 7,
+ METADATA_KEY_YEAR = 8,
+ METADATA_KEY_DURATION = 9,
+ METADATA_KEY_NUM_TRACKS = 10,
+ METADATA_KEY_WRITER = 11,
+ METADATA_KEY_MIMETYPE = 12,
+ METADATA_KEY_ALBUMARTIST = 13,
+ METADATA_KEY_DISC_NUMBER = 14,
+ METADATA_KEY_COMPILATION = 15,
+ METADATA_KEY_HAS_AUDIO = 16,
+ METADATA_KEY_HAS_VIDEO = 17,
+ METADATA_KEY_VIDEO_WIDTH = 18,
+ METADATA_KEY_VIDEO_HEIGHT = 19,
+ METADATA_KEY_BITRATE = 20,
+ METADATA_KEY_TIMED_TEXT_LANGUAGES = 21,
+ METADATA_KEY_IS_DRM = 22,
+ METADATA_KEY_LOCATION = 23,
+
+ // Add more here...
+};
+
+class MediaMetadataRetriever: public RefBase
+{
+public:
+ MediaMetadataRetriever();
+ ~MediaMetadataRetriever();
+ void disconnect();
+
+ status_t setDataSource(
+ const char *dataSourceUrl,
+ const KeyedVector<String8, String8> *headers = NULL);
+
+ status_t setDataSource(int fd, int64_t offset, int64_t length);
+ sp<IMemory> getFrameAtTime(int64_t timeUs, int option);
+ sp<IMemory> extractAlbumArt();
+ const char* extractMetadata(int keyCode);
+
+private:
+ static const sp<IMediaPlayerService>& getService();
+
+ class DeathNotifier: public IBinder::DeathRecipient
+ {
+ public:
+ DeathNotifier() {}
+ virtual ~DeathNotifier();
+ virtual void binderDied(const wp<IBinder>& who);
+ };
+
+ static sp<DeathNotifier> sDeathNotifier;
+ static Mutex sServiceLock;
+ static sp<IMediaPlayerService> sService;
+
+ Mutex mLock;
+ sp<IMediaMetadataRetriever> mRetriever;
+
+};
+
+}; // namespace android
+
+#endif // MEDIAMETADATARETRIEVER_H
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
new file mode 100644
index 0000000..a68ab4e
--- /dev/null
+++ b/include/media/mediaplayer.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 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_MEDIAPLAYER_H
+#define ANDROID_MEDIAPLAYER_H
+
+#include <arpa/inet.h>
+
+#include <binder/IMemory.h>
+#include <media/IMediaPlayerClient.h>
+#include <media/IMediaPlayer.h>
+#include <media/IMediaDeathNotifier.h>
+#include <media/IStreamSource.h>
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+class ANativeWindow;
+
+namespace android {
+
+class Surface;
+class ISurfaceTexture;
+
+enum media_event_type {
+ MEDIA_NOP = 0, // interface test message
+ MEDIA_PREPARED = 1,
+ MEDIA_PLAYBACK_COMPLETE = 2,
+ MEDIA_BUFFERING_UPDATE = 3,
+ MEDIA_SEEK_COMPLETE = 4,
+ MEDIA_SET_VIDEO_SIZE = 5,
+ MEDIA_TIMED_TEXT = 99,
+ MEDIA_ERROR = 100,
+ MEDIA_INFO = 200,
+};
+
+// Generic error codes for the media player framework. Errors are fatal, the
+// playback must abort.
+//
+// Errors are communicated back to the client using the
+// MediaPlayerListener::notify method defined below.
+// In this situation, 'notify' is invoked with the following:
+// 'msg' is set to MEDIA_ERROR.
+// 'ext1' should be a value from the enum media_error_type.
+// 'ext2' contains an implementation dependant error code to provide
+// more details. Should default to 0 when not used.
+//
+// The codes are distributed as follow:
+// 0xx: Reserved
+// 1xx: Android Player errors. Something went wrong inside the MediaPlayer.
+// 2xx: Media errors (e.g Codec not supported). There is a problem with the
+// media itself.
+// 3xx: Runtime errors. Some extraordinary condition arose making the playback
+// impossible.
+//
+enum media_error_type {
+ // 0xx
+ MEDIA_ERROR_UNKNOWN = 1,
+ // 1xx
+ MEDIA_ERROR_SERVER_DIED = 100,
+ // 2xx
+ MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200,
+ // 3xx
+};
+
+
+// Info and warning codes for the media player framework. These are non fatal,
+// the playback is going on but there might be some user visible issues.
+//
+// Info and warning messages are communicated back to the client using the
+// MediaPlayerListener::notify method defined below. In this situation,
+// 'notify' is invoked with the following:
+// 'msg' is set to MEDIA_INFO.
+// 'ext1' should be a value from the enum media_info_type.
+// 'ext2' contains an implementation dependant info code to provide
+// more details. Should default to 0 when not used.
+//
+// The codes are distributed as follow:
+// 0xx: Reserved
+// 7xx: Android Player info/warning (e.g player lagging behind.)
+// 8xx: Media info/warning (e.g media badly interleaved.)
+//
+enum media_info_type {
+ // 0xx
+ MEDIA_INFO_UNKNOWN = 1,
+ // The player was started because it was used as the next player for another
+ // player, which just completed playback
+ MEDIA_INFO_STARTED_AS_NEXT = 2,
+ // 7xx
+ // The video is too complex for the decoder: it can't decode frames fast
+ // enough. Possibly only the audio plays fine at this stage.
+ MEDIA_INFO_VIDEO_TRACK_LAGGING = 700,
+ // MediaPlayer is temporarily pausing playback internally in order to
+ // buffer more data.
+ MEDIA_INFO_BUFFERING_START = 701,
+ // MediaPlayer is resuming playback after filling buffers.
+ MEDIA_INFO_BUFFERING_END = 702,
+ // Bandwidth in recent past
+ MEDIA_INFO_NETWORK_BANDWIDTH = 703,
+
+ // 8xx
+ // Bad interleaving means that a media has been improperly interleaved or not
+ // interleaved at all, e.g has all the video samples first then all the audio
+ // ones. Video is playing but a lot of disk seek may be happening.
+ MEDIA_INFO_BAD_INTERLEAVING = 800,
+ // The media is not seekable (e.g live stream).
+ MEDIA_INFO_NOT_SEEKABLE = 801,
+ // New media metadata is available.
+ MEDIA_INFO_METADATA_UPDATE = 802,
+
+ //9xx
+ MEDIA_INFO_TIMED_TEXT_ERROR = 900,
+};
+
+
+
+enum media_player_states {
+ MEDIA_PLAYER_STATE_ERROR = 0,
+ MEDIA_PLAYER_IDLE = 1 << 0,
+ MEDIA_PLAYER_INITIALIZED = 1 << 1,
+ MEDIA_PLAYER_PREPARING = 1 << 2,
+ MEDIA_PLAYER_PREPARED = 1 << 3,
+ MEDIA_PLAYER_STARTED = 1 << 4,
+ MEDIA_PLAYER_PAUSED = 1 << 5,
+ MEDIA_PLAYER_STOPPED = 1 << 6,
+ MEDIA_PLAYER_PLAYBACK_COMPLETE = 1 << 7
+};
+
+// Keep KEY_PARAMETER_* in sync with MediaPlayer.java.
+// The same enum space is used for both set and get, in case there are future keys that
+// can be both set and get. But as of now, all parameters are either set only or get only.
+enum media_parameter_keys {
+ // Streaming/buffering parameters
+ KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100, // set only
+
+ // Return a Parcel containing a single int, which is the channel count of the
+ // audio track, or zero for error (e.g. no audio track) or unknown.
+ KEY_PARAMETER_AUDIO_CHANNEL_COUNT = 1200, // get only
+
+ // Playback rate expressed in permille (1000 is normal speed), saved as int32_t, with negative
+ // values used for rewinding or reverse playback.
+ KEY_PARAMETER_PLAYBACK_RATE_PERMILLE = 1300, // set only
+};
+
+// Keep INVOKE_ID_* in sync with MediaPlayer.java.
+enum media_player_invoke_ids {
+ INVOKE_ID_GET_TRACK_INFO = 1,
+ INVOKE_ID_ADD_EXTERNAL_SOURCE = 2,
+ INVOKE_ID_ADD_EXTERNAL_SOURCE_FD = 3,
+ INVOKE_ID_SELECT_TRACK = 4,
+ INVOKE_ID_UNSELECT_TRACK = 5,
+};
+
+// Keep MEDIA_TRACK_TYPE_* in sync with MediaPlayer.java.
+enum media_track_type {
+ MEDIA_TRACK_TYPE_UNKNOWN = 0,
+ MEDIA_TRACK_TYPE_VIDEO = 1,
+ MEDIA_TRACK_TYPE_AUDIO = 2,
+ MEDIA_TRACK_TYPE_TIMEDTEXT = 3,
+};
+
+// ----------------------------------------------------------------------------
+// ref-counted object for callbacks
+class MediaPlayerListener: virtual public RefBase
+{
+public:
+ virtual void notify(int msg, int ext1, int ext2, const Parcel *obj) = 0;
+};
+
+class MediaPlayer : public BnMediaPlayerClient,
+ public virtual IMediaDeathNotifier
+{
+public:
+ MediaPlayer();
+ ~MediaPlayer();
+ void died();
+ void disconnect();
+
+ status_t setDataSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers);
+
+ status_t setDataSource(int fd, int64_t offset, int64_t length);
+ status_t setDataSource(const sp<IStreamSource> &source);
+ status_t setVideoSurfaceTexture(
+ const sp<ISurfaceTexture>& surfaceTexture);
+ status_t setListener(const sp<MediaPlayerListener>& listener);
+ status_t prepare();
+ status_t prepareAsync();
+ status_t start();
+ status_t stop();
+ status_t pause();
+ bool isPlaying();
+ status_t getVideoWidth(int *w);
+ status_t getVideoHeight(int *h);
+ status_t seekTo(int msec);
+ status_t getCurrentPosition(int *msec);
+ status_t getDuration(int *msec);
+ status_t reset();
+ status_t setAudioStreamType(audio_stream_type_t type);
+ status_t setLooping(int loop);
+ bool isLooping();
+ status_t setVolume(float leftVolume, float rightVolume);
+ void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
+ static sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat);
+ static sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat);
+ status_t invoke(const Parcel& request, Parcel *reply);
+ status_t setMetadataFilter(const Parcel& filter);
+ status_t getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
+ status_t setAudioSessionId(int sessionId);
+ int getAudioSessionId();
+ status_t setAuxEffectSendLevel(float level);
+ status_t attachAuxEffect(int effectId);
+ status_t setParameter(int key, const Parcel& request);
+ status_t getParameter(int key, Parcel* reply);
+ status_t setRetransmitEndpoint(const char* addrString, uint16_t port);
+ status_t setNextMediaPlayer(const sp<MediaPlayer>& player);
+
+private:
+ void clear_l();
+ status_t seekTo_l(int msec);
+ status_t prepareAsync_l();
+ status_t getDuration_l(int *msec);
+ status_t attachNewPlayer(const sp<IMediaPlayer>& player);
+ status_t reset_l();
+ status_t doSetRetransmitEndpoint(const sp<IMediaPlayer>& player);
+
+ sp<IMediaPlayer> mPlayer;
+ thread_id_t mLockThreadId;
+ Mutex mLock;
+ Mutex mNotifyLock;
+ Condition mSignal;
+ sp<MediaPlayerListener> mListener;
+ void* mCookie;
+ media_player_states mCurrentState;
+ int mDuration;
+ int mCurrentPosition;
+ int mSeekPosition;
+ bool mPrepareSync;
+ status_t mPrepareStatus;
+ audio_stream_type_t mStreamType;
+ bool mLoop;
+ float mLeftVolume;
+ float mRightVolume;
+ int mVideoWidth;
+ int mVideoHeight;
+ int mAudioSessionId;
+ float mSendLevel;
+ struct sockaddr_in mRetransmitEndpoint;
+ bool mRetransmitEndpointValid;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIAPLAYER_H
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
new file mode 100644
index 0000000..30db642
--- /dev/null
+++ b/include/media/mediarecorder.h
@@ -0,0 +1,257 @@
+/*
+ ** 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_MEDIARECORDER_H
+#define ANDROID_MEDIARECORDER_H
+
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <utils/List.h>
+#include <utils/Errors.h>
+#include <media/IMediaRecorderClient.h>
+#include <media/IMediaDeathNotifier.h>
+
+namespace android {
+
+class Surface;
+class IMediaRecorder;
+class ICamera;
+class ICameraRecordingProxy;
+class ISurfaceTexture;
+class SurfaceTextureClient;
+
+typedef void (*media_completion_f)(status_t status, void *cookie);
+
+enum video_source {
+ VIDEO_SOURCE_DEFAULT = 0,
+ VIDEO_SOURCE_CAMERA = 1,
+ VIDEO_SOURCE_GRALLOC_BUFFER = 2,
+
+ VIDEO_SOURCE_LIST_END // must be last - used to validate audio source type
+};
+
+//Please update media/java/android/media/MediaRecorder.java if the following is updated.
+enum output_format {
+ OUTPUT_FORMAT_DEFAULT = 0,
+ OUTPUT_FORMAT_THREE_GPP = 1,
+ OUTPUT_FORMAT_MPEG_4 = 2,
+
+
+ OUTPUT_FORMAT_AUDIO_ONLY_START = 3, // Used in validating the output format. Should be the
+ // at the start of the audio only output formats.
+
+ /* These are audio only file formats */
+ OUTPUT_FORMAT_RAW_AMR = 3, //to be backward compatible
+ OUTPUT_FORMAT_AMR_NB = 3,
+ OUTPUT_FORMAT_AMR_WB = 4,
+ OUTPUT_FORMAT_AAC_ADIF = 5,
+ OUTPUT_FORMAT_AAC_ADTS = 6,
+
+ /* Stream over a socket, limited to a single stream */
+ OUTPUT_FORMAT_RTP_AVP = 7,
+
+ /* H.264/AAC data encapsulated in MPEG2/TS */
+ OUTPUT_FORMAT_MPEG2TS = 8,
+
+ OUTPUT_FORMAT_LIST_END // must be last - used to validate format type
+};
+
+enum audio_encoder {
+ AUDIO_ENCODER_DEFAULT = 0,
+ AUDIO_ENCODER_AMR_NB = 1,
+ AUDIO_ENCODER_AMR_WB = 2,
+ AUDIO_ENCODER_AAC = 3,
+ AUDIO_ENCODER_AAC_PLUS = 4,
+ AUDIO_ENCODER_EAAC_PLUS = 5,
+
+ AUDIO_ENCODER_LIST_END // must be the last - used to validate the audio encoder type
+};
+
+enum video_encoder {
+ VIDEO_ENCODER_DEFAULT = 0,
+ VIDEO_ENCODER_H263 = 1,
+ VIDEO_ENCODER_H264 = 2,
+ VIDEO_ENCODER_MPEG_4_SP = 3,
+
+ VIDEO_ENCODER_LIST_END // must be the last - used to validate the video encoder type
+};
+
+/*
+ * The state machine of the media_recorder.
+ */
+enum media_recorder_states {
+ // Error state.
+ MEDIA_RECORDER_ERROR = 0,
+
+ // Recorder was just created.
+ MEDIA_RECORDER_IDLE = 1 << 0,
+
+ // Recorder has been initialized.
+ MEDIA_RECORDER_INITIALIZED = 1 << 1,
+
+ // Configuration of the recorder has been completed.
+ MEDIA_RECORDER_DATASOURCE_CONFIGURED = 1 << 2,
+
+ // Recorder is ready to start.
+ MEDIA_RECORDER_PREPARED = 1 << 3,
+
+ // Recording is in progress.
+ MEDIA_RECORDER_RECORDING = 1 << 4,
+};
+
+// The "msg" code passed to the listener in notify.
+enum media_recorder_event_type {
+ MEDIA_RECORDER_EVENT_LIST_START = 1,
+ MEDIA_RECORDER_EVENT_ERROR = 1,
+ MEDIA_RECORDER_EVENT_INFO = 2,
+ MEDIA_RECORDER_EVENT_LIST_END = 99,
+
+ // Track related event types
+ MEDIA_RECORDER_TRACK_EVENT_LIST_START = 100,
+ MEDIA_RECORDER_TRACK_EVENT_ERROR = 100,
+ MEDIA_RECORDER_TRACK_EVENT_INFO = 101,
+ MEDIA_RECORDER_TRACK_EVENT_LIST_END = 1000,
+};
+
+/*
+ * The (part of) "what" code passed to the listener in notify.
+ * When the error or info type is track specific, the what has
+ * the following layout:
+ * the left-most 16-bit is meant for error or info type.
+ * the right-most 4-bit is meant for track id.
+ * the rest is reserved.
+ *
+ * | track id | reserved | error or info type |
+ * 31 28 16 0
+ *
+ */
+enum media_recorder_error_type {
+ MEDIA_RECORDER_ERROR_UNKNOWN = 1,
+
+ // Track related error type
+ MEDIA_RECORDER_TRACK_ERROR_LIST_START = 100,
+ MEDIA_RECORDER_TRACK_ERROR_GENERAL = 100,
+ MEDIA_RECORDER_ERROR_VIDEO_NO_SYNC_FRAME = 200,
+ MEDIA_RECORDER_TRACK_ERROR_LIST_END = 1000,
+};
+
+// The codes are distributed as follow:
+// 0xx: Reserved
+// 8xx: General info/warning
+//
+enum media_recorder_info_type {
+ MEDIA_RECORDER_INFO_UNKNOWN = 1,
+
+ MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800,
+ MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801,
+
+ // All track related informtional events start here
+ MEDIA_RECORDER_TRACK_INFO_LIST_START = 1000,
+ MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS = 1000,
+ MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME = 1001,
+ MEDIA_RECORDER_TRACK_INFO_TYPE = 1002,
+ MEDIA_RECORDER_TRACK_INFO_DURATION_MS = 1003,
+
+ // The time to measure the max chunk duration
+ MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS = 1004,
+
+ MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES = 1005,
+
+ // The time to measure how well the audio and video
+ // track data is interleaved.
+ MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS = 1006,
+
+ // The time to measure system response. Note that
+ // the delay does not include the intentional delay
+ // we use to eliminate the recording sound.
+ MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS = 1007,
+
+ // The time used to compensate for initial A/V sync.
+ MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS = 1008,
+
+ // Total number of bytes of the media data.
+ MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES = 1009,
+
+ MEDIA_RECORDER_TRACK_INFO_LIST_END = 2000,
+};
+
+// ----------------------------------------------------------------------------
+// ref-counted object for callbacks
+class MediaRecorderListener: virtual public RefBase
+{
+public:
+ virtual void notify(int msg, int ext1, int ext2) = 0;
+};
+
+class MediaRecorder : public BnMediaRecorderClient,
+ public virtual IMediaDeathNotifier
+{
+public:
+ MediaRecorder();
+ ~MediaRecorder();
+
+ void died();
+ status_t initCheck();
+ status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
+ status_t setPreviewSurface(const sp<Surface>& surface);
+ status_t setVideoSource(int vs);
+ status_t setAudioSource(int as);
+ status_t setOutputFormat(int of);
+ status_t setVideoEncoder(int ve);
+ status_t setAudioEncoder(int ae);
+ status_t setOutputFile(const char* path);
+ status_t setOutputFile(int fd, int64_t offset, int64_t length);
+ status_t setVideoSize(int width, int height);
+ status_t setVideoFrameRate(int frames_per_second);
+ status_t setParameters(const String8& params);
+ status_t setListener(const sp<MediaRecorderListener>& listener);
+ status_t prepare();
+ status_t getMaxAmplitude(int* max);
+ status_t start();
+ status_t stop();
+ status_t reset();
+ status_t init();
+ status_t close();
+ status_t release();
+ void notify(int msg, int ext1, int ext2);
+ sp<ISurfaceTexture> querySurfaceMediaSourceFromMediaServer();
+
+private:
+ void doCleanUp();
+ status_t doReset();
+
+ sp<IMediaRecorder> mMediaRecorder;
+ sp<MediaRecorderListener> mListener;
+
+ // Reference toISurfaceTexture
+ // for encoding GL Frames. That is useful only when the
+ // video source is set to VIDEO_SOURCE_GRALLOC_BUFFER
+ sp<ISurfaceTexture> mSurfaceMediaSource;
+
+ media_recorder_states mCurrentState;
+ bool mIsAudioSourceSet;
+ bool mIsVideoSourceSet;
+ bool mIsAudioEncoderSet;
+ bool mIsVideoEncoderSet;
+ bool mIsOutputFileSet;
+ Mutex mLock;
+ Mutex mNotifyLock;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIARECORDER_H
diff --git a/include/media/mediascanner.h b/include/media/mediascanner.h
new file mode 100644
index 0000000..a73403b
--- /dev/null
+++ b/include/media/mediascanner.h
@@ -0,0 +1,110 @@
+/*
+ * 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 MEDIASCANNER_H
+#define MEDIASCANNER_H
+
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <utils/List.h>
+#include <utils/Errors.h>
+#include <pthread.h>
+
+struct dirent;
+
+namespace android {
+
+class MediaScannerClient;
+class StringArray;
+
+enum MediaScanResult {
+ // This file or directory was scanned successfully.
+ MEDIA_SCAN_RESULT_OK,
+ // This file or directory was skipped because it was not found, could
+ // not be opened, was of an unsupported type, or was malfored in some way.
+ MEDIA_SCAN_RESULT_SKIPPED,
+ // The scan should be aborted due to a fatal error such as out of memory
+ // or an exception.
+ MEDIA_SCAN_RESULT_ERROR,
+};
+
+struct MediaScanner {
+ MediaScanner();
+ virtual ~MediaScanner();
+
+ virtual MediaScanResult processFile(
+ const char *path, const char *mimeType, MediaScannerClient &client) = 0;
+
+ virtual MediaScanResult processDirectory(
+ const char *path, MediaScannerClient &client);
+
+ void setLocale(const char *locale);
+
+ // extracts album art as a block of data
+ virtual char *extractAlbumArt(int fd) = 0;
+
+protected:
+ const char *locale() const;
+
+private:
+ // current locale (like "ja_JP"), created/destroyed with strdup()/free()
+ char *mLocale;
+ char *mSkipList;
+ int *mSkipIndex;
+
+ MediaScanResult doProcessDirectory(
+ char *path, int pathRemaining, MediaScannerClient &client, bool noMedia);
+ MediaScanResult doProcessDirectoryEntry(
+ char *path, int pathRemaining, MediaScannerClient &client, bool noMedia,
+ struct dirent* entry, char* fileSpot);
+ void loadSkipList();
+ bool shouldSkipDirectory(char *path);
+
+
+ MediaScanner(const MediaScanner &);
+ MediaScanner &operator=(const MediaScanner &);
+};
+
+class MediaScannerClient
+{
+public:
+ MediaScannerClient();
+ virtual ~MediaScannerClient();
+ void setLocale(const char* locale);
+ void beginFile();
+ status_t addStringTag(const char* name, const char* value);
+ void endFile();
+
+ virtual status_t scanFile(const char* path, long long lastModified,
+ long long fileSize, bool isDirectory, bool noMedia) = 0;
+ virtual status_t handleStringTag(const char* name, const char* value) = 0;
+ virtual status_t setMimeType(const char* mimeType) = 0;
+
+protected:
+ void convertValues(uint32_t encoding);
+
+protected:
+ // cached name and value strings, for native encoding support.
+ StringArray* mNames;
+ StringArray* mValues;
+
+ // default encoding based on MediaScanner::mLocale string
+ uint32_t mLocaleEncoding;
+};
+
+}; // namespace android
+
+#endif // MEDIASCANNER_H
diff --git a/include/media/stagefright/AACWriter.h b/include/media/stagefright/AACWriter.h
new file mode 100644
index 0000000..49397ee
--- /dev/null
+++ b/include/media/stagefright/AACWriter.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_WRITER_H_
+#define AAC_WRITER_H_
+
+#include <media/stagefright/MediaWriter.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct MediaSource;
+struct MetaData;
+
+struct AACWriter : public MediaWriter {
+ AACWriter(const char *filename);
+ AACWriter(int fd);
+
+ status_t initCheck() const;
+
+ virtual status_t addSource(const sp<MediaSource> &source);
+ virtual bool reachedEOS();
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop() { return reset(); }
+ virtual status_t pause();
+
+protected:
+ virtual ~AACWriter();
+
+private:
+ enum {
+ kAdtsHeaderLength = 7, // # of bytes for the adts header
+ kSamplesPerFrame = 1024, // # of samples in a frame
+ };
+
+ int mFd;
+ status_t mInitCheck;
+ sp<MediaSource> mSource;
+ bool mStarted;
+ volatile bool mPaused;
+ volatile bool mResumed;
+ volatile bool mDone;
+ volatile bool mReachedEOS;
+ pthread_t mThread;
+ int64_t mEstimatedSizeBytes;
+ int64_t mEstimatedDurationUs;
+ int32_t mChannelCount;
+ int32_t mSampleRate;
+ int32_t mFrameDurationUs;
+
+ static void *ThreadWrapper(void *);
+ status_t threadFunc();
+ bool exceedsFileSizeLimit();
+ bool exceedsFileDurationLimit();
+ status_t writeAdtsHeader(uint32_t frameLength);
+ status_t reset();
+
+ DISALLOW_EVIL_CONSTRUCTORS(AACWriter);
+};
+
+} // namespace android
+
+#endif // AAC_WRITER_H_
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
new file mode 100644
index 0000000..7d7af63
--- /dev/null
+++ b/include/media/stagefright/ACodec.h
@@ -0,0 +1,229 @@
+/*
+ * 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_CODEC_H_
+
+#define A_CODEC_H_
+
+#include <stdint.h>
+#include <android/native_window.h>
+#include <media/IOMX.h>
+#include <media/stagefright/foundation/AHierarchicalStateMachine.h>
+#include <OMX_Audio.h>
+
+namespace android {
+
+struct ABuffer;
+struct MemoryDealer;
+
+struct ACodec : public AHierarchicalStateMachine {
+ enum {
+ kWhatFillThisBuffer = 'fill',
+ kWhatDrainThisBuffer = 'drai',
+ kWhatEOS = 'eos ',
+ kWhatShutdownCompleted = 'scom',
+ kWhatFlushCompleted = 'fcom',
+ kWhatOutputFormatChanged = 'outC',
+ kWhatError = 'erro',
+ kWhatComponentAllocated = 'cAll',
+ kWhatComponentConfigured = 'cCon',
+ kWhatBuffersAllocated = 'allc',
+ };
+
+ ACodec();
+
+ void setNotificationMessage(const sp<AMessage> &msg);
+ void initiateSetup(const sp<AMessage> &msg);
+ void signalFlush();
+ void signalResume();
+ void initiateShutdown(bool keepComponentAllocated = false);
+
+ void initiateAllocateComponent(const sp<AMessage> &msg);
+ void initiateConfigureComponent(const sp<AMessage> &msg);
+ void initiateStart();
+
+protected:
+ virtual ~ACodec();
+
+private:
+ struct BaseState;
+ struct UninitializedState;
+ struct LoadedState;
+ struct LoadedToIdleState;
+ struct IdleToExecutingState;
+ struct ExecutingState;
+ struct OutputPortSettingsChangedState;
+ struct ExecutingToIdleState;
+ struct IdleToLoadedState;
+ struct FlushingState;
+
+ enum {
+ kWhatSetup = 'setu',
+ kWhatOMXMessage = 'omx ',
+ kWhatInputBufferFilled = 'inpF',
+ kWhatOutputBufferDrained = 'outD',
+ kWhatShutdown = 'shut',
+ kWhatFlush = 'flus',
+ kWhatResume = 'resm',
+ kWhatDrainDeferredMessages = 'drai',
+ kWhatAllocateComponent = 'allo',
+ kWhatConfigureComponent = 'conf',
+ kWhatStart = 'star',
+ };
+
+ enum {
+ kPortIndexInput = 0,
+ kPortIndexOutput = 1
+ };
+
+ enum {
+ kFlagIsSecure = 1,
+ };
+
+ struct BufferInfo {
+ enum Status {
+ OWNED_BY_US,
+ OWNED_BY_COMPONENT,
+ OWNED_BY_UPSTREAM,
+ OWNED_BY_DOWNSTREAM,
+ OWNED_BY_NATIVE_WINDOW,
+ };
+
+ IOMX::buffer_id mBufferID;
+ Status mStatus;
+
+ sp<ABuffer> mData;
+ sp<GraphicBuffer> mGraphicBuffer;
+ };
+
+ sp<AMessage> mNotify;
+
+ sp<UninitializedState> mUninitializedState;
+ sp<LoadedState> mLoadedState;
+ sp<LoadedToIdleState> mLoadedToIdleState;
+ sp<IdleToExecutingState> mIdleToExecutingState;
+ sp<ExecutingState> mExecutingState;
+ sp<OutputPortSettingsChangedState> mOutputPortSettingsChangedState;
+ sp<ExecutingToIdleState> mExecutingToIdleState;
+ sp<IdleToLoadedState> mIdleToLoadedState;
+ sp<FlushingState> mFlushingState;
+
+ AString mComponentName;
+ uint32_t mFlags;
+ uint32_t mQuirks;
+ sp<IOMX> mOMX;
+ IOMX::node_id mNode;
+ sp<MemoryDealer> mDealer[2];
+
+ sp<ANativeWindow> mNativeWindow;
+
+ Vector<BufferInfo> mBuffers[2];
+ bool mPortEOS[2];
+ status_t mInputEOSResult;
+
+ List<sp<AMessage> > mDeferredQueue;
+
+ bool mSentFormat;
+ bool mIsEncoder;
+
+ bool mShutdownInProgress;
+
+ // If "mKeepComponentAllocated" we only transition back to Loaded state
+ // and do not release the component instance.
+ bool mKeepComponentAllocated;
+
+ status_t allocateBuffersOnPort(OMX_U32 portIndex);
+ status_t freeBuffersOnPort(OMX_U32 portIndex);
+ status_t freeBuffer(OMX_U32 portIndex, size_t i);
+
+ status_t allocateOutputBuffersFromNativeWindow();
+ status_t cancelBufferToNativeWindow(BufferInfo *info);
+ status_t freeOutputBuffersNotOwnedByComponent();
+ BufferInfo *dequeueBufferFromNativeWindow();
+
+ BufferInfo *findBufferByID(
+ uint32_t portIndex, IOMX::buffer_id bufferID,
+ ssize_t *index = NULL);
+
+ status_t setComponentRole(bool isEncoder, const char *mime);
+ status_t configureCodec(const char *mime, const sp<AMessage> &msg);
+
+ status_t setVideoPortFormatType(
+ OMX_U32 portIndex,
+ OMX_VIDEO_CODINGTYPE compressionFormat,
+ OMX_COLOR_FORMATTYPE colorFormat);
+
+ status_t setSupportedOutputFormat();
+
+ status_t setupVideoDecoder(
+ const char *mime, int32_t width, int32_t height);
+
+ status_t setupVideoEncoder(
+ const char *mime, const sp<AMessage> &msg);
+
+ status_t setVideoFormatOnPort(
+ OMX_U32 portIndex,
+ int32_t width, int32_t height,
+ OMX_VIDEO_CODINGTYPE compressionFormat);
+
+ status_t setupAACCodec(
+ bool encoder,
+ int32_t numChannels, int32_t sampleRate, int32_t bitRate,
+ bool isADTS);
+
+ status_t selectAudioPortFormat(
+ OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat);
+
+ status_t setupAMRCodec(bool encoder, bool isWAMR, int32_t bitRate);
+ status_t setupG711Codec(bool encoder, int32_t numChannels);
+
+ status_t setupRawAudioFormat(
+ OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels);
+
+ status_t setMinBufferSize(OMX_U32 portIndex, size_t size);
+
+ status_t setupMPEG4EncoderParameters(const sp<AMessage> &msg);
+ status_t setupH263EncoderParameters(const sp<AMessage> &msg);
+ status_t setupAVCEncoderParameters(const sp<AMessage> &msg);
+
+ status_t verifySupportForProfileAndLevel(int32_t profile, int32_t level);
+ status_t configureBitrate(int32_t bitrate);
+ status_t setupErrorCorrectionParameters();
+
+ status_t initNativeWindow();
+
+ // Returns true iff all buffers on the given port have status OWNED_BY_US.
+ bool allYourBuffersAreBelongToUs(OMX_U32 portIndex);
+
+ bool allYourBuffersAreBelongToUs();
+
+ size_t countBuffersOwnedByComponent(OMX_U32 portIndex) const;
+
+ void deferMessage(const sp<AMessage> &msg);
+ void processDeferredMessages();
+
+ void sendFormatChange();
+
+ void signalError(
+ OMX_ERRORTYPE error = OMX_ErrorUndefined,
+ status_t internalError = UNKNOWN_ERROR);
+
+ DISALLOW_EVIL_CONSTRUCTORS(ACodec);
+};
+
+} // namespace android
+
+#endif // A_CODEC_H_
diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h
new file mode 100644
index 0000000..392f968
--- /dev/null
+++ b/include/media/stagefright/AMRWriter.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 AMR_WRITER_H_
+
+#define AMR_WRITER_H_
+
+#include <stdio.h>
+
+#include <media/stagefright/MediaWriter.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct MediaSource;
+struct MetaData;
+
+struct AMRWriter : public MediaWriter {
+ AMRWriter(const char *filename);
+ AMRWriter(int fd);
+
+ status_t initCheck() const;
+
+ virtual status_t addSource(const sp<MediaSource> &source);
+ virtual bool reachedEOS();
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop() { return reset(); }
+ virtual status_t pause();
+
+protected:
+ virtual ~AMRWriter();
+
+private:
+ int mFd;
+ status_t mInitCheck;
+ sp<MediaSource> mSource;
+ bool mStarted;
+ volatile bool mPaused;
+ volatile bool mResumed;
+ volatile bool mDone;
+ volatile bool mReachedEOS;
+ pthread_t mThread;
+ int64_t mEstimatedSizeBytes;
+ int64_t mEstimatedDurationUs;
+
+ static void *ThreadWrapper(void *);
+ status_t threadFunc();
+ bool exceedsFileSizeLimit();
+ bool exceedsFileDurationLimit();
+ status_t reset();
+
+ AMRWriter(const AMRWriter &);
+ AMRWriter &operator=(const AMRWriter &);
+};
+
+} // namespace android
+
+#endif // AMR_WRITER_H_
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
new file mode 100644
index 0000000..70c47ae
--- /dev/null
+++ b/include/media/stagefright/AudioPlayer.h
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#ifndef AUDIO_PLAYER_H_
+
+#define AUDIO_PLAYER_H_
+
+#include <media/MediaPlayerInterface.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/TimeSource.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class MediaSource;
+class AudioTrack;
+class AwesomePlayer;
+
+class AudioPlayer : public TimeSource {
+public:
+ enum {
+ REACHED_EOS,
+ SEEK_COMPLETE
+ };
+
+ AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink,
+ AwesomePlayer *audioObserver = NULL);
+
+ virtual ~AudioPlayer();
+
+ // Caller retains ownership of "source".
+ void setSource(const sp<MediaSource> &source);
+
+ // Return time in us.
+ virtual int64_t getRealTimeUs();
+
+ status_t start(bool sourceAlreadyStarted = false);
+
+ void pause(bool playPendingSamples = false);
+ void resume();
+
+ // Returns the timestamp of the last buffer played (in us).
+ int64_t getMediaTimeUs();
+
+ // Returns true iff a mapping is established, i.e. the AudioPlayer
+ // has played at least one frame of audio.
+ bool getMediaTimeMapping(int64_t *realtime_us, int64_t *mediatime_us);
+
+ status_t seekTo(int64_t time_us);
+
+ bool isSeeking();
+ bool reachedEOS(status_t *finalStatus);
+
+ status_t setPlaybackRatePermille(int32_t ratePermille);
+
+private:
+ friend class VideoEditorAudioPlayer;
+ sp<MediaSource> mSource;
+ AudioTrack *mAudioTrack;
+
+ MediaBuffer *mInputBuffer;
+
+ int mSampleRate;
+ int64_t mLatencyUs;
+ size_t mFrameSize;
+
+ Mutex mLock;
+ int64_t mNumFramesPlayed;
+
+ int64_t mPositionTimeMediaUs;
+ int64_t mPositionTimeRealUs;
+
+ bool mSeeking;
+ bool mReachedEOS;
+ status_t mFinalStatus;
+ int64_t mSeekTimeUs;
+
+ bool mStarted;
+
+ bool mIsFirstBuffer;
+ status_t mFirstBufferResult;
+ MediaBuffer *mFirstBuffer;
+
+ sp<MediaPlayerBase::AudioSink> mAudioSink;
+ AwesomePlayer *mObserver;
+
+ static void AudioCallback(int event, void *user, void *info);
+ void AudioCallback(int event, void *info);
+
+ static size_t AudioSinkCallback(
+ MediaPlayerBase::AudioSink *audioSink,
+ void *data, size_t size, void *me);
+
+ size_t fillBuffer(void *data, size_t size);
+
+ int64_t getRealTimeUsLocked() const;
+
+ void reset();
+
+ uint32_t getNumFramesPendingPlayout() const;
+
+ AudioPlayer(const AudioPlayer &);
+ AudioPlayer &operator=(const AudioPlayer &);
+};
+
+} // namespace android
+
+#endif // AUDIO_PLAYER_H_
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
new file mode 100644
index 0000000..f5466e8
--- /dev/null
+++ b/include/media/stagefright/AudioSource.h
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+#ifndef AUDIO_SOURCE_H_
+
+#define AUDIO_SOURCE_H_
+
+#include <media/AudioRecord.h>
+#include <media/AudioSystem.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <utils/List.h>
+
+#include <system/audio.h>
+
+namespace android {
+
+class AudioRecord;
+
+struct AudioSource : public MediaSource, public MediaBufferObserver {
+ // Note that the "channels" parameter is _not_ the number of channels,
+ // but a bitmask of audio_channels_t constants.
+ AudioSource(
+ audio_source_t inputSource, uint32_t sampleRate,
+ uint32_t channels = AUDIO_CHANNEL_IN_MONO);
+
+ status_t initCheck() const;
+
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop() { return reset(); }
+ virtual sp<MetaData> getFormat();
+
+ // Returns the maximum amplitude since last call.
+ int16_t getMaxAmplitude();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+ status_t dataCallbackTimestamp(const AudioRecord::Buffer& buffer, int64_t timeUs);
+ virtual void signalBufferReturned(MediaBuffer *buffer);
+
+protected:
+ virtual ~AudioSource();
+
+private:
+ enum {
+ kMaxBufferSize = 2048,
+
+ // After the initial mute, we raise the volume linearly
+ // over kAutoRampDurationUs.
+ kAutoRampDurationUs = 300000,
+
+ // This is the initial mute duration to suppress
+ // the video recording signal tone
+ kAutoRampStartUs = 0,
+ };
+
+ Mutex mLock;
+ Condition mFrameAvailableCondition;
+ Condition mFrameEncodingCompletionCondition;
+
+ AudioRecord *mRecord;
+ status_t mInitCheck;
+ bool mStarted;
+ int32_t mSampleRate;
+
+ bool mTrackMaxAmplitude;
+ int64_t mStartTimeUs;
+ int16_t mMaxAmplitude;
+ int64_t mPrevSampleTimeUs;
+ int64_t mInitialReadTimeUs;
+ int64_t mNumFramesReceived;
+ int64_t mNumClientOwnedBuffers;
+
+ List<MediaBuffer * > mBuffersReceived;
+
+ void trackMaxAmplitude(int16_t *data, int nSamples);
+
+ // This is used to raise the volume from mute to the
+ // actual level linearly.
+ void rampVolume(
+ int32_t startFrame, int32_t rampDurationFrames,
+ uint8_t *data, size_t bytes);
+
+ void queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs);
+ void releaseQueuedFrames_l();
+ void waitOutstandingEncodingFrames_l();
+ status_t reset();
+
+ AudioSource(const AudioSource &);
+ AudioSource &operator=(const AudioSource &);
+};
+
+} // namespace android
+
+#endif // AUDIO_SOURCE_H_
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
new file mode 100644
index 0000000..5a35358
--- /dev/null
+++ b/include/media/stagefright/CameraSource.h
@@ -0,0 +1,232 @@
+/*
+ * 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.
+ */
+
+#ifndef CAMERA_SOURCE_H_
+
+#define CAMERA_SOURCE_H_
+
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+#include <camera/ICamera.h>
+#include <camera/ICameraRecordingProxyListener.h>
+#include <camera/CameraParameters.h>
+#include <utils/List.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class IMemory;
+class Camera;
+class Surface;
+
+class CameraSource : public MediaSource, public MediaBufferObserver {
+public:
+ /**
+ * Factory method to create a new CameraSource using the current
+ * settings (such as video size, frame rate, color format, etc)
+ * from the default camera.
+ *
+ * @return NULL on error.
+ */
+ static CameraSource *Create();
+
+ /**
+ * Factory method to create a new CameraSource.
+ *
+ * @param camera the video input frame data source. If it is NULL,
+ * we will try to connect to the camera with the given
+ * cameraId.
+ *
+ * @param cameraId the id of the camera that the source will connect
+ * to if camera is NULL; otherwise ignored.
+ *
+ * @param videoSize the dimension (in pixels) of the video frame
+ * @param frameRate the target frames per second
+ * @param surface the preview surface for display where preview
+ * frames are sent to
+ * @param storeMetaDataInVideoBuffers true to request the camera
+ * source to store meta data in video buffers; false to
+ * request the camera source to store real YUV frame data
+ * in the video buffers. The camera source may not support
+ * storing meta data in video buffers, if so, a request
+ * to do that will NOT be honored. To find out whether
+ * meta data is actually being stored in video buffers
+ * during recording, call isMetaDataStoredInVideoBuffers().
+ *
+ * @return NULL on error.
+ */
+ static CameraSource *CreateFromCamera(const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
+ int32_t cameraId,
+ Size videoSize,
+ int32_t frameRate,
+ const sp<Surface>& surface,
+ bool storeMetaDataInVideoBuffers = false);
+
+ virtual ~CameraSource();
+
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop() { return reset(); }
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+ /**
+ * Check whether a CameraSource object is properly initialized.
+ * Must call this method before stop().
+ * @return OK if initialization has successfully completed.
+ */
+ virtual status_t initCheck() const;
+
+ /**
+ * Returns the MetaData associated with the CameraSource,
+ * including:
+ * kKeyColorFormat: YUV color format of the video frames
+ * kKeyWidth, kKeyHeight: dimension (in pixels) of the video frames
+ * kKeySampleRate: frame rate in frames per second
+ * kKeyMIMEType: always fixed to be MEDIA_MIMETYPE_VIDEO_RAW
+ */
+ virtual sp<MetaData> getFormat();
+
+ /**
+ * Tell whether this camera source stores meta data or real YUV
+ * frame data in video buffers.
+ *
+ * @return true if meta data is stored in the video
+ * buffers; false if real YUV data is stored in
+ * the video buffers.
+ */
+ bool isMetaDataStoredInVideoBuffers() const;
+
+ virtual void signalBufferReturned(MediaBuffer* buffer);
+
+protected:
+ class ProxyListener: public BnCameraRecordingProxyListener {
+ public:
+ ProxyListener(const sp<CameraSource>& source);
+ virtual void dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
+ const sp<IMemory> &data);
+
+ private:
+ sp<CameraSource> mSource;
+ };
+
+ // isBinderAlive needs linkToDeath to work.
+ class DeathNotifier: public IBinder::DeathRecipient {
+ public:
+ DeathNotifier() {}
+ virtual void binderDied(const wp<IBinder>& who);
+ };
+
+ enum CameraFlags {
+ FLAGS_SET_CAMERA = 1L << 0,
+ FLAGS_HOT_CAMERA = 1L << 1,
+ };
+
+ int32_t mCameraFlags;
+ Size mVideoSize;
+ int32_t mVideoFrameRate;
+ int32_t mColorFormat;
+ status_t mInitCheck;
+
+ sp<Camera> mCamera;
+ sp<ICameraRecordingProxy> mCameraRecordingProxy;
+ sp<DeathNotifier> mDeathNotifier;
+ sp<Surface> mSurface;
+ sp<MetaData> mMeta;
+
+ int64_t mStartTimeUs;
+ int32_t mNumFramesReceived;
+ int64_t mLastFrameTimestampUs;
+ bool mStarted;
+ int32_t mNumFramesEncoded;
+
+ // Time between capture of two frames.
+ int64_t mTimeBetweenFrameCaptureUs;
+
+ CameraSource(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId,
+ Size videoSize, int32_t frameRate,
+ const sp<Surface>& surface,
+ bool storeMetaDataInVideoBuffers);
+
+ virtual void startCameraRecording();
+ virtual void releaseRecordingFrame(const sp<IMemory>& frame);
+
+ // Returns true if need to skip the current frame.
+ // Called from dataCallbackTimestamp.
+ virtual bool skipCurrentFrame(int64_t timestampUs) {return false;}
+
+ // Callback called when still camera raw data is available.
+ virtual void dataCallback(int32_t msgType, const sp<IMemory> &data) {}
+
+ virtual void dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
+ const sp<IMemory> &data);
+
+private:
+ friend class CameraSourceListener;
+
+ Mutex mLock;
+ Condition mFrameAvailableCondition;
+ Condition mFrameCompleteCondition;
+ List<sp<IMemory> > mFramesReceived;
+ List<sp<IMemory> > mFramesBeingEncoded;
+ List<int64_t> mFrameTimes;
+
+ int64_t mFirstFrameTimeUs;
+ int32_t mNumFramesDropped;
+ int32_t mNumGlitches;
+ int64_t mGlitchDurationThresholdUs;
+ bool mCollectStats;
+ bool mIsMetaDataStoredInVideoBuffers;
+
+ void releaseQueuedFrames();
+ void releaseOneRecordingFrame(const sp<IMemory>& frame);
+
+
+ status_t init(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId, Size videoSize, int32_t frameRate,
+ bool storeMetaDataInVideoBuffers);
+
+ status_t initWithCameraAccess(
+ const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId, Size videoSize, int32_t frameRate,
+ bool storeMetaDataInVideoBuffers);
+
+ status_t isCameraAvailable(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId);
+ status_t isCameraColorFormatSupported(const CameraParameters& params);
+ status_t configureCamera(CameraParameters* params,
+ int32_t width, int32_t height,
+ int32_t frameRate);
+
+ status_t checkVideoSize(const CameraParameters& params,
+ int32_t width, int32_t height);
+
+ status_t checkFrameRate(const CameraParameters& params,
+ int32_t frameRate);
+
+ void stopCameraRecording();
+ void releaseCamera();
+ status_t reset();
+
+ CameraSource(const CameraSource &);
+ CameraSource &operator=(const CameraSource &);
+};
+
+} // namespace android
+
+#endif // CAMERA_SOURCE_H_
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
new file mode 100644
index 0000000..0936da2
--- /dev/null
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -0,0 +1,162 @@
+/*
+ * 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 CAMERA_SOURCE_TIME_LAPSE_H_
+
+#define CAMERA_SOURCE_TIME_LAPSE_H_
+
+#include <pthread.h>
+
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class ICamera;
+class IMemory;
+class Camera;
+
+class CameraSourceTimeLapse : public CameraSource {
+public:
+ static CameraSourceTimeLapse *CreateFromCamera(
+ const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
+ int32_t cameraId,
+ Size videoSize,
+ int32_t videoFrameRate,
+ const sp<Surface>& surface,
+ int64_t timeBetweenTimeLapseFrameCaptureUs);
+
+ virtual ~CameraSourceTimeLapse();
+
+ // If the frame capture interval is large, read will block for a long time.
+ // Due to the way the mediaRecorder framework works, a stop() call from
+ // mediaRecorder waits until the read returns, causing a long wait for
+ // stop() to return. To avoid this, we can make read() return a copy of the
+ // last read frame with the same time stamp frequently. This keeps the
+ // read() call from blocking too long. Calling this function quickly
+ // captures another frame, keeps its copy, and enables this mode of read()
+ // returning quickly.
+ void startQuickReadReturns();
+
+private:
+ // size of the encoded video.
+ int32_t mVideoWidth;
+ int32_t mVideoHeight;
+
+ // Time between two frames in final video (1/frameRate)
+ int64_t mTimeBetweenTimeLapseVideoFramesUs;
+
+ // Real timestamp of the last encoded time lapse frame
+ int64_t mLastTimeLapseFrameRealTimestampUs;
+
+ // Variable set in dataCallbackTimestamp() to help skipCurrentFrame()
+ // to know if current frame needs to be skipped.
+ bool mSkipCurrentFrame;
+
+ // Lock for accessing mCameraIdle
+ Mutex mCameraIdleLock;
+
+ // Condition variable to wait on if camera is is not yet idle. Once the
+ // camera gets idle, this variable will be signalled.
+ Condition mCameraIdleCondition;
+
+ // True if camera is in preview mode and ready for takePicture().
+ // False after a call to takePicture() but before the final compressed
+ // data callback has been called and preview has been restarted.
+ volatile bool mCameraIdle;
+
+ // True if stop() is waiting for camera to get idle, i.e. for the last
+ // takePicture() to complete. This is needed so that dataCallbackTimestamp()
+ // can return immediately.
+ volatile bool mStopWaitingForIdleCamera;
+
+ // Lock for accessing quick stop variables.
+ Mutex mQuickStopLock;
+
+ // mQuickStop is set to true if we use quick read() returns, otherwise it is set
+ // to false. Once in this mode read() return a copy of the last read frame
+ // with the same time stamp. See startQuickReadReturns().
+ volatile bool mQuickStop;
+
+ // Forces the next frame passed to dataCallbackTimestamp() to be read
+ // as a time lapse frame. Used by startQuickReadReturns() so that the next
+ // frame wakes up any blocking read.
+ volatile bool mForceRead;
+
+ // Stores a copy of the MediaBuffer read in the last read() call after
+ // mQuickStop was true.
+ MediaBuffer* mLastReadBufferCopy;
+
+ // Status code for last read.
+ status_t mLastReadStatus;
+
+ CameraSourceTimeLapse(
+ const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
+ int32_t cameraId,
+ Size videoSize,
+ int32_t videoFrameRate,
+ const sp<Surface>& surface,
+ int64_t timeBetweenTimeLapseFrameCaptureUs);
+
+ // Wrapper over CameraSource::signalBufferReturned() to implement quick stop.
+ // It only handles the case when mLastReadBufferCopy is signalled. Otherwise
+ // it calls the base class' function.
+ virtual void signalBufferReturned(MediaBuffer* buffer);
+
+ // Wrapper over CameraSource::read() to implement quick stop.
+ virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+ // mSkipCurrentFrame is set to true in dataCallbackTimestamp() if the current
+ // frame needs to be skipped and this function just returns the value of mSkipCurrentFrame.
+ virtual bool skipCurrentFrame(int64_t timestampUs);
+
+ // In the video camera case calls skipFrameAndModifyTimeStamp() to modify
+ // timestamp and set mSkipCurrentFrame.
+ // Then it calls the base CameraSource::dataCallbackTimestamp()
+ virtual void dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
+ const sp<IMemory> &data);
+
+ // Convenience function to fill mLastReadBufferCopy from the just read
+ // buffer.
+ void fillLastReadBufferCopy(MediaBuffer& sourceBuffer);
+
+ // If the passed in size (width x height) is a supported video/preview size,
+ // the function sets the camera's video/preview size to it and returns true.
+ // Otherwise returns false.
+ bool trySettingVideoSize(int32_t width, int32_t height);
+
+ // When video camera is used for time lapse capture, returns true
+ // until enough time has passed for the next time lapse frame. When
+ // the frame needs to be encoded, it returns false and also modifies
+ // the time stamp to be one frame time ahead of the last encoded
+ // frame's time stamp.
+ bool skipFrameAndModifyTimeStamp(int64_t *timestampUs);
+
+ // Wrapper to enter threadTimeLapseEntry()
+ static void *ThreadTimeLapseWrapper(void *me);
+
+ // Creates a copy of source_data into a new memory of final type MemoryBase.
+ sp<IMemory> createIMemoryCopy(const sp<IMemory> &source_data);
+
+ CameraSourceTimeLapse(const CameraSourceTimeLapse &);
+ CameraSourceTimeLapse &operator=(const CameraSourceTimeLapse &);
+};
+
+} // namespace android
+
+#endif // CAMERA_SOURCE_TIME_LAPSE_H_
diff --git a/include/media/stagefright/ColorConverter.h b/include/media/stagefright/ColorConverter.h
new file mode 100644
index 0000000..85ba920
--- /dev/null
+++ b/include/media/stagefright/ColorConverter.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+#ifndef COLOR_CONVERTER_H_
+
+#define COLOR_CONVERTER_H_
+
+#include <sys/types.h>
+
+#include <stdint.h>
+#include <utils/Errors.h>
+
+#include <OMX_Video.h>
+
+namespace android {
+
+struct ColorConverter {
+ ColorConverter(OMX_COLOR_FORMATTYPE from, OMX_COLOR_FORMATTYPE to);
+ ~ColorConverter();
+
+ bool isValid() const;
+
+ status_t convert(
+ const void *srcBits,
+ size_t srcWidth, size_t srcHeight,
+ size_t srcCropLeft, size_t srcCropTop,
+ size_t srcCropRight, size_t srcCropBottom,
+ void *dstBits,
+ size_t dstWidth, size_t dstHeight,
+ size_t dstCropLeft, size_t dstCropTop,
+ size_t dstCropRight, size_t dstCropBottom);
+
+private:
+ struct BitmapParams {
+ BitmapParams(
+ void *bits,
+ size_t width, size_t height,
+ size_t cropLeft, size_t cropTop,
+ size_t cropRight, size_t cropBottom);
+
+ size_t cropWidth() const;
+ size_t cropHeight() const;
+
+ void *mBits;
+ size_t mWidth, mHeight;
+ size_t mCropLeft, mCropTop, mCropRight, mCropBottom;
+ };
+
+ OMX_COLOR_FORMATTYPE mSrcFormat, mDstFormat;
+ uint8_t *mClip;
+
+ uint8_t *initClip();
+
+ status_t convertCbYCrY(
+ const BitmapParams &src, const BitmapParams &dst);
+
+ status_t convertYUV420Planar(
+ const BitmapParams &src, const BitmapParams &dst);
+
+ status_t convertQCOMYUV420SemiPlanar(
+ const BitmapParams &src, const BitmapParams &dst);
+
+ status_t convertYUV420SemiPlanar(
+ const BitmapParams &src, const BitmapParams &dst);
+
+ status_t convertTIYUV420PackedSemiPlanar(
+ const BitmapParams &src, const BitmapParams &dst);
+
+ ColorConverter(const ColorConverter &);
+ ColorConverter &operator=(const ColorConverter &);
+};
+
+} // namespace android
+
+#endif // COLOR_CONVERTER_H_
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
new file mode 100644
index 0000000..00d583e
--- /dev/null
+++ b/include/media/stagefright/DataSource.h
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+#ifndef DATA_SOURCE_H_
+
+#define DATA_SOURCE_H_
+
+#include <sys/types.h>
+
+#include <media/stagefright/MediaErrors.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/List.h>
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
+
+namespace android {
+
+struct AMessage;
+class String8;
+
+class DataSource : public RefBase {
+public:
+ enum Flags {
+ kWantsPrefetching = 1,
+ kStreamedFromLocalHost = 2,
+ kIsCachingDataSource = 4,
+ kIsHTTPBasedSource = 8,
+ };
+
+ static sp<DataSource> CreateFromURI(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers = NULL);
+
+ DataSource() {}
+
+ virtual status_t initCheck() const = 0;
+
+ virtual ssize_t readAt(off64_t offset, void *data, size_t size) = 0;
+
+ // Convenience methods:
+ bool getUInt16(off64_t offset, uint16_t *x);
+
+ // May return ERROR_UNSUPPORTED.
+ virtual status_t getSize(off64_t *size);
+
+ virtual uint32_t flags() {
+ return 0;
+ }
+
+ virtual status_t reconnectAtOffset(off64_t offset) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ bool sniff(String8 *mimeType, float *confidence, sp<AMessage> *meta);
+
+ // The sniffer can optionally fill in "meta" with an AMessage containing
+ // a dictionary of values that helps the corresponding extractor initialize
+ // its state without duplicating effort already exerted by the sniffer.
+ typedef bool (*SnifferFunc)(
+ const sp<DataSource> &source, String8 *mimeType,
+ float *confidence, sp<AMessage> *meta);
+
+ static void RegisterSniffer(SnifferFunc func);
+ static void RegisterDefaultSniffers();
+
+ // for DRM
+ virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL) {
+ return NULL;
+ }
+ virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {};
+
+ virtual String8 getUri() {
+ return String8();
+ }
+
+ virtual String8 getMIMEType() const;
+
+protected:
+ virtual ~DataSource() {}
+
+private:
+ static Mutex gSnifferMutex;
+ static List<SnifferFunc> gSniffers;
+
+ DataSource(const DataSource &);
+ DataSource &operator=(const DataSource &);
+};
+
+} // namespace android
+
+#endif // DATA_SOURCE_H_
diff --git a/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h
new file mode 100644
index 0000000..d994cb3
--- /dev/null
+++ b/include/media/stagefright/FileSource.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#ifndef FILE_SOURCE_H_
+
+#define FILE_SOURCE_H_
+
+#include <stdio.h>
+
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
+
+namespace android {
+
+class FileSource : public DataSource {
+public:
+ FileSource(const char *filename);
+ FileSource(int fd, int64_t offset, int64_t length);
+
+ virtual status_t initCheck() const;
+
+ virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+
+ virtual status_t getSize(off64_t *size);
+
+ virtual sp<DecryptHandle> DrmInitialization(const char *mime);
+
+ virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
+
+protected:
+ virtual ~FileSource();
+
+private:
+ int mFd;
+ int64_t mOffset;
+ int64_t mLength;
+ Mutex mLock;
+
+ /*for DRM*/
+ sp<DecryptHandle> mDecryptHandle;
+ DrmManagerClient *mDrmManagerClient;
+ int64_t mDrmBufOffset;
+ int64_t mDrmBufSize;
+ unsigned char *mDrmBuf;
+
+ ssize_t readAtDRM(off64_t offset, void *data, size_t size);
+
+ FileSource(const FileSource &);
+ FileSource &operator=(const FileSource &);
+};
+
+} // namespace android
+
+#endif // FILE_SOURCE_H_
+
diff --git a/include/media/stagefright/JPEGSource.h b/include/media/stagefright/JPEGSource.h
new file mode 100644
index 0000000..1b7e91b
--- /dev/null
+++ b/include/media/stagefright/JPEGSource.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef JPEG_SOURCE_H_
+
+#define JPEG_SOURCE_H_
+
+#include <media/stagefright/MediaSource.h>
+
+namespace android {
+
+class DataSource;
+class MediaBufferGroup;
+
+struct JPEGSource : public MediaSource {
+ JPEGSource(const sp<DataSource> &source);
+
+ 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);
+
+protected:
+ virtual ~JPEGSource();
+
+private:
+ sp<DataSource> mSource;
+ MediaBufferGroup *mGroup;
+ bool mStarted;
+ off64_t mSize;
+ int32_t mWidth, mHeight;
+ off64_t mOffset;
+
+ status_t parseJPEG();
+
+ JPEGSource(const JPEGSource &);
+ JPEGSource &operator=(const JPEGSource &);
+};
+
+} // namespace android
+
+#endif // JPEG_SOURCE_H_
+
diff --git a/include/media/stagefright/MPEG2TSWriter.h b/include/media/stagefright/MPEG2TSWriter.h
new file mode 100644
index 0000000..a7c9ecf
--- /dev/null
+++ b/include/media/stagefright/MPEG2TSWriter.h
@@ -0,0 +1,88 @@
+/*
+ * 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 MPEG2TS_WRITER_H_
+
+#define MPEG2TS_WRITER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AHandlerReflector.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MediaWriter.h>
+
+namespace android {
+
+struct ABuffer;
+
+struct MPEG2TSWriter : public MediaWriter {
+ MPEG2TSWriter(int fd);
+ MPEG2TSWriter(const char *filename);
+
+ MPEG2TSWriter(
+ void *cookie,
+ ssize_t (*write)(void *cookie, const void *data, size_t size));
+
+ virtual status_t addSource(const sp<MediaSource> &source);
+ virtual status_t start(MetaData *param = NULL);
+ virtual status_t stop() { return reset(); }
+ virtual status_t pause();
+ virtual bool reachedEOS();
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ void onMessageReceived(const sp<AMessage> &msg);
+
+protected:
+ virtual ~MPEG2TSWriter();
+
+private:
+ enum {
+ kWhatSourceNotify = 'noti'
+ };
+
+ struct SourceInfo;
+
+ FILE *mFile;
+
+ void *mWriteCookie;
+ ssize_t (*mWriteFunc)(void *cookie, const void *data, size_t size);
+
+ sp<ALooper> mLooper;
+ sp<AHandlerReflector<MPEG2TSWriter> > mReflector;
+
+ bool mStarted;
+
+ Vector<sp<SourceInfo> > mSources;
+ size_t mNumSourcesDone;
+
+ int64_t mNumTSPacketsWritten;
+ int64_t mNumTSPacketsBeforeMeta;
+
+ void init();
+
+ void writeTS();
+ void writeProgramAssociationTable();
+ void writeProgramMap();
+ void writeAccessUnit(int32_t sourceIndex, const sp<ABuffer> &buffer);
+
+ ssize_t internalWrite(const void *data, size_t size);
+ status_t reset();
+
+ DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSWriter);
+};
+
+} // namespace android
+
+#endif // MPEG2TS_WRITER_H_
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
new file mode 100644
index 0000000..0409b30
--- /dev/null
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ */
+
+#ifndef MPEG4_WRITER_H_
+
+#define MPEG4_WRITER_H_
+
+#include <stdio.h>
+
+#include <media/stagefright/MediaWriter.h>
+#include <utils/List.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class MediaBuffer;
+class MediaSource;
+class MetaData;
+
+class MPEG4Writer : public MediaWriter {
+public:
+ MPEG4Writer(const char *filename);
+ MPEG4Writer(int fd);
+
+ virtual status_t addSource(const sp<MediaSource> &source);
+ virtual status_t start(MetaData *param = NULL);
+ virtual status_t stop() { return reset(); }
+ virtual status_t pause();
+ virtual bool reachedEOS();
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ void beginBox(const char *fourcc);
+ void writeInt8(int8_t x);
+ void writeInt16(int16_t x);
+ void writeInt32(int32_t x);
+ void writeInt64(int64_t x);
+ void writeCString(const char *s);
+ void writeFourcc(const char *fourcc);
+ void write(const void *data, size_t size);
+ void endBox();
+ uint32_t interleaveDuration() const { return mInterleaveDurationUs; }
+ status_t setInterleaveDuration(uint32_t duration);
+ int32_t getTimeScale() const { return mTimeScale; }
+
+ status_t setGeoData(int latitudex10000, int longitudex10000);
+ void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; }
+ int32_t getStartTimeOffsetMs() const { return mStartTimeOffsetMs; }
+
+protected:
+ virtual ~MPEG4Writer();
+
+private:
+ class Track;
+
+ int mFd;
+ status_t mInitCheck;
+ bool mUse4ByteNalLength;
+ bool mUse32BitOffset;
+ bool mIsFileSizeLimitExplicitlyRequested;
+ bool mPaused;
+ bool mStarted; // Writer thread + track threads started successfully
+ bool mWriterThreadStarted; // Only writer thread started successfully
+ off64_t mOffset;
+ off_t mMdatOffset;
+ uint8_t *mMoovBoxBuffer;
+ off64_t mMoovBoxBufferOffset;
+ bool mWriteMoovBoxToMemory;
+ off64_t mFreeBoxOffset;
+ bool mStreamableFile;
+ off64_t mEstimatedMoovBoxSize;
+ uint32_t mInterleaveDurationUs;
+ int32_t mTimeScale;
+ int64_t mStartTimestampUs;
+ int mLatitudex10000;
+ int mLongitudex10000;
+ bool mAreGeoTagsAvailable;
+ int32_t mStartTimeOffsetMs;
+
+ Mutex mLock;
+
+ List<Track *> mTracks;
+
+ List<off64_t> mBoxes;
+
+ void setStartTimestampUs(int64_t timeUs);
+ int64_t getStartTimestampUs(); // Not const
+ status_t startTracks(MetaData *params);
+ size_t numTracks();
+ int64_t estimateMoovBoxSize(int32_t bitRate);
+
+ struct Chunk {
+ Track *mTrack; // Owner
+ int64_t mTimeStampUs; // Timestamp of the 1st sample
+ List<MediaBuffer *> mSamples; // Sample data
+
+ // Convenient constructor
+ Chunk(): mTrack(NULL), mTimeStampUs(0) {}
+
+ Chunk(Track *track, int64_t timeUs, List<MediaBuffer *> samples)
+ : mTrack(track), mTimeStampUs(timeUs), mSamples(samples) {
+ }
+
+ };
+ struct ChunkInfo {
+ Track *mTrack; // Owner
+ List<Chunk> mChunks; // Remaining chunks to be written
+
+ // Previous chunk timestamp that has been written
+ int64_t mPrevChunkTimestampUs;
+
+ // Max time interval between neighboring chunks
+ int64_t mMaxInterChunkDurUs;
+
+ };
+
+ bool mIsFirstChunk;
+ volatile bool mDone; // Writer thread is done?
+ pthread_t mThread; // Thread id for the writer
+ List<ChunkInfo> mChunkInfos; // Chunk infos
+ Condition mChunkReadyCondition; // Signal that chunks are available
+
+ // Writer thread handling
+ status_t startWriterThread();
+ void stopWriterThread();
+ static void *ThreadWrapper(void *me);
+ void threadFunc();
+
+ // Buffer a single chunk to be written out later.
+ void bufferChunk(const Chunk& chunk);
+
+ // Write all buffered chunks from all tracks
+ void writeAllChunks();
+
+ // Retrieve the proper chunk to write if there is one
+ // Return true if a chunk is found; otherwise, return false.
+ bool findChunkToWrite(Chunk *chunk);
+
+ // Actually write the given chunk to the file.
+ void writeChunkToFile(Chunk* chunk);
+
+ // Adjust other track media clock (presumably wall clock)
+ // based on audio track media clock with the drift time.
+ int64_t mDriftTimeUs;
+ void setDriftTimeUs(int64_t driftTimeUs);
+ int64_t getDriftTimeUs();
+
+ // Return whether the nal length is 4 bytes or 2 bytes
+ // Only makes sense for H.264/AVC
+ bool useNalLengthFour();
+
+ void lock();
+ void unlock();
+
+ // Acquire lock before calling these methods
+ off64_t addSample_l(MediaBuffer *buffer);
+ off64_t addLengthPrefixedSample_l(MediaBuffer *buffer);
+
+ inline size_t write(const void *ptr, size_t size, size_t nmemb);
+ bool exceedsFileSizeLimit();
+ bool use32BitFileOffset() const;
+ bool exceedsFileDurationLimit();
+ bool isFileStreamable() const;
+ void trackProgressStatus(size_t trackId, int64_t timeUs, status_t err = OK);
+ void writeCompositionMatrix(int32_t degrees);
+ void writeMvhdBox(int64_t durationUs);
+ void writeMoovBox(int64_t durationUs);
+ void writeFtypBox(MetaData *param);
+ void writeUdtaBox();
+ void writeGeoDataBox();
+ void writeLatitude(int degreex10000);
+ void writeLongitude(int degreex10000);
+ void sendSessionSummary();
+ void release();
+ status_t reset();
+
+ MPEG4Writer(const MPEG4Writer &);
+ MPEG4Writer &operator=(const MPEG4Writer &);
+};
+
+} // namespace android
+
+#endif // MPEG4_WRITER_H_
diff --git a/include/media/stagefright/MediaBuffer.h b/include/media/stagefright/MediaBuffer.h
new file mode 100644
index 0000000..3d79596
--- /dev/null
+++ b/include/media/stagefright/MediaBuffer.h
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#ifndef MEDIA_BUFFER_H_
+
+#define MEDIA_BUFFER_H_
+
+#include <pthread.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABuffer;
+class GraphicBuffer;
+class MediaBuffer;
+class MediaBufferObserver;
+class MetaData;
+
+class MediaBufferObserver {
+public:
+ MediaBufferObserver() {}
+ virtual ~MediaBufferObserver() {}
+
+ virtual void signalBufferReturned(MediaBuffer *buffer) = 0;
+
+private:
+ MediaBufferObserver(const MediaBufferObserver &);
+ MediaBufferObserver &operator=(const MediaBufferObserver &);
+};
+
+class MediaBuffer {
+public:
+ // The underlying data remains the responsibility of the caller!
+ MediaBuffer(void *data, size_t size);
+
+ MediaBuffer(size_t size);
+
+ MediaBuffer(const sp<GraphicBuffer>& graphicBuffer);
+
+ MediaBuffer(const sp<ABuffer> &buffer);
+
+ // Decrements the reference count and returns the buffer to its
+ // associated MediaBufferGroup if the reference count drops to 0.
+ void release();
+
+ // Increments the reference count.
+ void add_ref();
+
+ void *data() const;
+ size_t size() const;
+
+ size_t range_offset() const;
+ size_t range_length() const;
+
+ void set_range(size_t offset, size_t length);
+
+ sp<GraphicBuffer> graphicBuffer() const;
+
+ sp<MetaData> meta_data();
+
+ // Clears meta data and resets the range to the full extent.
+ void reset();
+
+ void setObserver(MediaBufferObserver *group);
+
+ // Returns a clone of this MediaBuffer increasing its reference count.
+ // The clone references the same data but has its own range and
+ // MetaData.
+ MediaBuffer *clone();
+
+ int refcount() const;
+
+protected:
+ virtual ~MediaBuffer();
+
+private:
+ friend class MediaBufferGroup;
+ friend class OMXDecoder;
+
+ // For use by OMXDecoder, reference count must be 1, drop reference
+ // count to 0 without signalling the observer.
+ void claim();
+
+ MediaBufferObserver *mObserver;
+ MediaBuffer *mNextBuffer;
+ int mRefCount;
+
+ void *mData;
+ size_t mSize, mRangeOffset, mRangeLength;
+ sp<GraphicBuffer> mGraphicBuffer;
+ sp<ABuffer> mBuffer;
+
+ bool mOwnsData;
+
+ sp<MetaData> mMetaData;
+
+ MediaBuffer *mOriginal;
+
+ void setNextBuffer(MediaBuffer *buffer);
+ MediaBuffer *nextBuffer();
+
+ MediaBuffer(const MediaBuffer &);
+ MediaBuffer &operator=(const MediaBuffer &);
+};
+
+} // namespace android
+
+#endif // MEDIA_BUFFER_H_
diff --git a/include/media/stagefright/MediaBufferGroup.h b/include/media/stagefright/MediaBufferGroup.h
new file mode 100644
index 0000000..0488292
--- /dev/null
+++ b/include/media/stagefright/MediaBufferGroup.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef MEDIA_BUFFER_GROUP_H_
+
+#define MEDIA_BUFFER_GROUP_H_
+
+#include <media/stagefright/MediaBuffer.h>
+#include <utils/Errors.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class MediaBuffer;
+class MetaData;
+
+class MediaBufferGroup : public MediaBufferObserver {
+public:
+ MediaBufferGroup();
+ ~MediaBufferGroup();
+
+ void add_buffer(MediaBuffer *buffer);
+
+ // Blocks until a buffer is available and returns it to the caller,
+ // the returned buffer will have a reference count of 1.
+ status_t acquire_buffer(MediaBuffer **buffer);
+
+protected:
+ virtual void signalBufferReturned(MediaBuffer *buffer);
+
+private:
+ friend class MediaBuffer;
+
+ Mutex mLock;
+ Condition mCondition;
+
+ MediaBuffer *mFirstBuffer, *mLastBuffer;
+
+ MediaBufferGroup(const MediaBufferGroup &);
+ MediaBufferGroup &operator=(const MediaBufferGroup &);
+};
+
+} // namespace android
+
+#endif // MEDIA_BUFFER_GROUP_H_
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
new file mode 100644
index 0000000..0fc88e1
--- /dev/null
+++ b/include/media/stagefright/MediaCodec.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 MEDIA_CODEC_H_
+
+#define MEDIA_CODEC_H_
+
+#include <gui/ISurfaceTexture.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct ABuffer;
+struct ACodec;
+struct AMessage;
+struct ICrypto;
+struct SoftwareRenderer;
+struct SurfaceTextureClient;
+
+struct MediaCodec : public AHandler {
+ enum ConfigureFlags {
+ CONFIGURE_FLAG_ENCODE = 1,
+ CONFIGURE_FLAG_SECURE = 2,
+ };
+
+ enum BufferFlags {
+ BUFFER_FLAG_SYNCFRAME = 1,
+ BUFFER_FLAG_CODECCONFIG = 2,
+ BUFFER_FLAG_EOS = 4,
+ BUFFER_FLAG_ENCRYPTED = 8,
+ };
+
+ static sp<MediaCodec> CreateByType(
+ const sp<ALooper> &looper, const char *mime, bool encoder);
+
+ static sp<MediaCodec> CreateByComponentName(
+ const sp<ALooper> &looper, const char *name);
+
+ status_t configure(
+ const sp<AMessage> &format,
+ const sp<SurfaceTextureClient> &nativeWindow,
+ uint32_t flags);
+
+ status_t start();
+
+ // Returns to a state in which the component remains allocated but
+ // unconfigured.
+ status_t stop();
+
+ // Client MUST call release before releasing final reference to this
+ // object.
+ status_t release();
+
+ status_t flush();
+
+ status_t queueInputBuffer(
+ size_t index,
+ size_t offset,
+ size_t size,
+ int64_t presentationTimeUs,
+ uint32_t flags);
+
+ status_t dequeueInputBuffer(size_t *index, int64_t timeoutUs = 0ll);
+
+ status_t dequeueOutputBuffer(
+ size_t *index,
+ size_t *offset,
+ size_t *size,
+ int64_t *presentationTimeUs,
+ uint32_t *flags,
+ int64_t timeoutUs = 0ll);
+
+ status_t renderOutputBufferAndRelease(size_t index);
+ status_t releaseOutputBuffer(size_t index);
+
+ status_t getOutputFormat(sp<AMessage> *format) const;
+
+ status_t getInputBuffers(Vector<sp<ABuffer> > *buffers) const;
+ status_t getOutputBuffers(Vector<sp<ABuffer> > *buffers) const;
+
+protected:
+ virtual ~MediaCodec();
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+ enum State {
+ UNINITIALIZED,
+ INITIALIZING,
+ INITIALIZED,
+ CONFIGURING,
+ CONFIGURED,
+ STARTING,
+ STARTED,
+ FLUSHING,
+ STOPPING,
+ RELEASING,
+ };
+
+ enum {
+ kPortIndexInput = 0,
+ kPortIndexOutput = 1,
+ };
+
+ enum {
+ kWhatInit = 'init',
+ kWhatConfigure = 'conf',
+ kWhatStart = 'strt',
+ kWhatStop = 'stop',
+ kWhatRelease = 'rele',
+ kWhatDequeueInputBuffer = 'deqI',
+ kWhatQueueInputBuffer = 'queI',
+ kWhatDequeueOutputBuffer = 'deqO',
+ kWhatReleaseOutputBuffer = 'relO',
+ kWhatGetBuffers = 'getB',
+ kWhatFlush = 'flus',
+ kWhatGetOutputFormat = 'getO',
+ kWhatDequeueInputTimedOut = 'dITO',
+ kWhatDequeueOutputTimedOut = 'dOTO',
+ kWhatCodecNotify = 'codc',
+ };
+
+ enum {
+ kFlagIsSoftwareCodec = 1,
+ kFlagOutputFormatChanged = 2,
+ kFlagOutputBuffersChanged = 4,
+ kFlagStickyError = 8,
+ kFlagDequeueInputPending = 16,
+ kFlagDequeueOutputPending = 32,
+ kFlagIsSecure = 64,
+ };
+
+ struct BufferInfo {
+ void *mBufferID;
+ sp<ABuffer> mData;
+ sp<ABuffer> mEncryptedData;
+ sp<AMessage> mNotify;
+ bool mOwnedByClient;
+ };
+
+ State mState;
+ sp<ALooper> mLooper;
+ sp<ALooper> mCodecLooper;
+ sp<ACodec> mCodec;
+ uint32_t mReplyID;
+ uint32_t mFlags;
+ sp<SurfaceTextureClient> mNativeWindow;
+ SoftwareRenderer *mSoftRenderer;
+ sp<AMessage> mOutputFormat;
+
+ List<size_t> mAvailPortBuffers[2];
+ Vector<BufferInfo> mPortBuffers[2];
+
+ int32_t mDequeueInputTimeoutGeneration;
+ uint32_t mDequeueInputReplyID;
+
+ int32_t mDequeueOutputTimeoutGeneration;
+ uint32_t mDequeueOutputReplyID;
+
+ sp<ICrypto> mCrypto;
+
+ MediaCodec(const sp<ALooper> &looper);
+
+ static status_t PostAndAwaitResponse(
+ const sp<AMessage> &msg, sp<AMessage> *response);
+
+ status_t init(const char *name, bool nameIsType, bool encoder);
+
+ void setState(State newState);
+ void returnBuffersToCodec();
+ void returnBuffersToCodecOnPort(int32_t portIndex);
+ size_t updateBuffers(int32_t portIndex, const sp<AMessage> &msg);
+ status_t onQueueInputBuffer(const sp<AMessage> &msg);
+ status_t onReleaseOutputBuffer(const sp<AMessage> &msg);
+ ssize_t dequeuePortBuffer(int32_t portIndex);
+
+ bool handleDequeueInputBuffer(uint32_t replyID, bool newRequest = false);
+ bool handleDequeueOutputBuffer(uint32_t replyID, bool newRequest = false);
+ void cancelPendingDequeueOperations();
+
+ DISALLOW_EVIL_CONSTRUCTORS(MediaCodec);
+};
+
+} // namespace android
+
+#endif // MEDIA_CODEC_H_
diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h
new file mode 100644
index 0000000..14dc1b8
--- /dev/null
+++ b/include/media/stagefright/MediaCodecList.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 MEDIA_CODEC_LIST_H_
+
+#define MEDIA_CODEC_LIST_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AString.h>
+
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct MediaCodecList {
+ static const MediaCodecList *getInstance();
+
+ ssize_t findCodecByType(
+ const char *type, bool encoder, size_t startIndex = 0) const;
+
+ ssize_t findCodecByName(const char *name) const;
+
+ const char *getCodecName(size_t index) const;
+ bool codecHasQuirk(size_t index, const char *quirkName) const;
+
+private:
+ enum Section {
+ SECTION_TOPLEVEL,
+ SECTION_DECODERS,
+ SECTION_DECODER,
+ SECTION_ENCODERS,
+ SECTION_ENCODER,
+ };
+
+ struct CodecInfo {
+ AString mName;
+ bool mIsEncoder;
+ uint32_t mTypes;
+ uint32_t mQuirks;
+ };
+
+ static MediaCodecList *sCodecList;
+
+ status_t mInitCheck;
+ Section mCurrentSection;
+ int32_t mDepth;
+
+ Vector<CodecInfo> mCodecInfos;
+ KeyedVector<AString, size_t> mCodecQuirks;
+ KeyedVector<AString, size_t> mTypes;
+
+ MediaCodecList();
+ ~MediaCodecList();
+
+ status_t initCheck() const;
+ void parseXMLFile(FILE *file);
+
+ static void StartElementHandlerWrapper(
+ void *me, const char *name, const char **attrs);
+
+ static void EndElementHandlerWrapper(void *me, const char *name);
+
+ void startElementHandler(const char *name, const char **attrs);
+ void endElementHandler(const char *name);
+
+ status_t addMediaCodecFromAttributes(bool encoder, const char **attrs);
+ void addMediaCodec(bool encoder, const char *name, const char *type = NULL);
+
+ status_t addQuirk(const char **attrs);
+ status_t addTypeFromAttributes(const char **attrs);
+ void addType(const char *name);
+
+ DISALLOW_EVIL_CONSTRUCTORS(MediaCodecList);
+};
+
+} // namespace android
+
+#endif // MEDIA_CODEC_LIST_H_
+
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
new file mode 100644
index 0000000..457d5d7
--- /dev/null
+++ b/include/media/stagefright/MediaDefs.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+#ifndef MEDIA_DEFS_H_
+
+#define MEDIA_DEFS_H_
+
+namespace android {
+
+extern const char *MEDIA_MIMETYPE_IMAGE_JPEG;
+
+extern const char *MEDIA_MIMETYPE_VIDEO_VPX;
+extern const char *MEDIA_MIMETYPE_VIDEO_AVC;
+extern const char *MEDIA_MIMETYPE_VIDEO_MPEG4;
+extern const char *MEDIA_MIMETYPE_VIDEO_H263;
+extern const char *MEDIA_MIMETYPE_VIDEO_MPEG2;
+extern const char *MEDIA_MIMETYPE_VIDEO_RAW;
+
+extern const char *MEDIA_MIMETYPE_AUDIO_AMR_NB;
+extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB;
+extern const char *MEDIA_MIMETYPE_AUDIO_MPEG; // layer III
+extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I;
+extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II;
+extern const char *MEDIA_MIMETYPE_AUDIO_AAC;
+extern const char *MEDIA_MIMETYPE_AUDIO_QCELP;
+extern const char *MEDIA_MIMETYPE_AUDIO_VORBIS;
+extern const char *MEDIA_MIMETYPE_AUDIO_G711_ALAW;
+extern const char *MEDIA_MIMETYPE_AUDIO_G711_MLAW;
+extern const char *MEDIA_MIMETYPE_AUDIO_RAW;
+extern const char *MEDIA_MIMETYPE_AUDIO_FLAC;
+extern const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS;
+
+extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4;
+extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;
+extern const char *MEDIA_MIMETYPE_CONTAINER_OGG;
+extern const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA;
+extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2TS;
+extern const char *MEDIA_MIMETYPE_CONTAINER_AVI;
+extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2PS;
+
+extern const char *MEDIA_MIMETYPE_CONTAINER_WVM;
+
+extern const char *MEDIA_MIMETYPE_TEXT_3GPP;
+extern const char *MEDIA_MIMETYPE_TEXT_SUBRIP;
+
+} // namespace android
+
+#endif // MEDIA_DEFS_H_
diff --git a/include/media/stagefright/MediaErrors.h b/include/media/stagefright/MediaErrors.h
new file mode 100644
index 0000000..dd3bf28
--- /dev/null
+++ b/include/media/stagefright/MediaErrors.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#ifndef MEDIA_ERRORS_H_
+
+#define MEDIA_ERRORS_H_
+
+#include <utils/Errors.h>
+
+namespace android {
+
+enum {
+ MEDIA_ERROR_BASE = -1000,
+
+ ERROR_ALREADY_CONNECTED = MEDIA_ERROR_BASE,
+ ERROR_NOT_CONNECTED = MEDIA_ERROR_BASE - 1,
+ ERROR_UNKNOWN_HOST = MEDIA_ERROR_BASE - 2,
+ ERROR_CANNOT_CONNECT = MEDIA_ERROR_BASE - 3,
+ ERROR_IO = MEDIA_ERROR_BASE - 4,
+ ERROR_CONNECTION_LOST = MEDIA_ERROR_BASE - 5,
+ ERROR_MALFORMED = MEDIA_ERROR_BASE - 7,
+ ERROR_OUT_OF_RANGE = MEDIA_ERROR_BASE - 8,
+ ERROR_BUFFER_TOO_SMALL = MEDIA_ERROR_BASE - 9,
+ ERROR_UNSUPPORTED = MEDIA_ERROR_BASE - 10,
+ ERROR_END_OF_STREAM = MEDIA_ERROR_BASE - 11,
+
+ // Not technically an error.
+ INFO_FORMAT_CHANGED = MEDIA_ERROR_BASE - 12,
+ INFO_DISCONTINUITY = MEDIA_ERROR_BASE - 13,
+ INFO_OUTPUT_BUFFERS_CHANGED = MEDIA_ERROR_BASE - 14,
+
+ // The following constant values should be in sync with
+ // drm/drm_framework_common.h
+ DRM_ERROR_BASE = -2000,
+
+ ERROR_DRM_UNKNOWN = DRM_ERROR_BASE,
+ ERROR_DRM_NO_LICENSE = DRM_ERROR_BASE - 1,
+ ERROR_DRM_LICENSE_EXPIRED = DRM_ERROR_BASE - 2,
+ ERROR_DRM_SESSION_NOT_OPENED = DRM_ERROR_BASE - 3,
+ ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED = DRM_ERROR_BASE - 4,
+ ERROR_DRM_DECRYPT = DRM_ERROR_BASE - 5,
+ ERROR_DRM_CANNOT_HANDLE = DRM_ERROR_BASE - 6,
+ ERROR_DRM_TAMPER_DETECTED = DRM_ERROR_BASE - 7,
+
+ // Heartbeat Error Codes
+ HEARTBEAT_ERROR_BASE = -3000,
+
+ ERROR_HEARTBEAT_AUTHENTICATION_FAILURE = HEARTBEAT_ERROR_BASE,
+ ERROR_HEARTBEAT_NO_ACTIVE_PURCHASE_AGREEMENT = HEARTBEAT_ERROR_BASE - 1,
+ ERROR_HEARTBEAT_CONCURRENT_PLAYBACK = HEARTBEAT_ERROR_BASE - 2,
+ ERROR_HEARTBEAT_UNUSUAL_ACTIVITY = HEARTBEAT_ERROR_BASE - 3,
+ ERROR_HEARTBEAT_STREAMING_UNAVAILABLE = HEARTBEAT_ERROR_BASE - 4,
+ ERROR_HEARTBEAT_CANNOT_ACTIVATE_RENTAL = HEARTBEAT_ERROR_BASE - 5,
+ ERROR_HEARTBEAT_TERMINATE_REQUESTED = HEARTBEAT_ERROR_BASE - 6,
+};
+
+} // namespace android
+
+#endif // MEDIA_ERRORS_H_
diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
new file mode 100644
index 0000000..94090ee
--- /dev/null
+++ b/include/media/stagefright/MediaExtractor.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#ifndef MEDIA_EXTRACTOR_H_
+
+#define MEDIA_EXTRACTOR_H_
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+class DataSource;
+class MediaSource;
+class MetaData;
+
+class MediaExtractor : public RefBase {
+public:
+ static sp<MediaExtractor> Create(
+ const sp<DataSource> &source, const char *mime = NULL);
+
+ virtual size_t countTracks() = 0;
+ virtual sp<MediaSource> getTrack(size_t index) = 0;
+
+ enum GetTrackMetaDataFlags {
+ kIncludeExtensiveMetaData = 1
+ };
+ virtual sp<MetaData> getTrackMetaData(
+ size_t index, uint32_t flags = 0) = 0;
+
+ // Return container specific meta-data. The default implementation
+ // returns an empty metadata object.
+ virtual sp<MetaData> getMetaData();
+
+ enum Flags {
+ CAN_SEEK_BACKWARD = 1, // the "seek 10secs back button"
+ CAN_SEEK_FORWARD = 2, // the "seek 10secs forward button"
+ CAN_PAUSE = 4,
+ CAN_SEEK = 8, // the "seek bar"
+ };
+
+ // If subclasses do _not_ override this, the default is
+ // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
+ virtual uint32_t flags() const;
+
+ // for DRM
+ void setDrmFlag(bool flag) {
+ mIsDrm = flag;
+ };
+ bool getDrmFlag() {
+ return mIsDrm;
+ }
+ virtual char* getDrmTrackInfo(size_t trackID, int *len) {
+ return NULL;
+ }
+
+protected:
+ MediaExtractor() {}
+ virtual ~MediaExtractor() {}
+
+private:
+ bool mIsDrm;
+
+ MediaExtractor(const MediaExtractor &);
+ MediaExtractor &operator=(const MediaExtractor &);
+};
+
+} // namespace android
+
+#endif // MEDIA_EXTRACTOR_H_
diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h
new file mode 100644
index 0000000..3818e63
--- /dev/null
+++ b/include/media/stagefright/MediaSource.h
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+#ifndef MEDIA_SOURCE_H_
+
+#define MEDIA_SOURCE_H_
+
+#include <sys/types.h>
+
+#include <media/stagefright/MediaErrors.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+class MediaBuffer;
+class MetaData;
+
+struct MediaSource : public virtual RefBase {
+ MediaSource();
+
+ // To be called before any other methods on this object, except
+ // getFormat().
+ virtual status_t start(MetaData *params = NULL) = 0;
+
+ // Any blocking read call returns immediately with a result of NO_INIT.
+ // It is an error to call any methods other than start after this call
+ // returns. Any buffers the object may be holding onto at the time of
+ // the stop() call are released.
+ // Also, it is imperative that any buffers output by this object and
+ // held onto by callers be released before a call to stop() !!!
+ virtual status_t stop() = 0;
+
+ // Returns the format of the data output by this media source.
+ virtual sp<MetaData> getFormat() = 0;
+
+ struct ReadOptions;
+
+ // Returns a new buffer of data. Call blocks until a
+ // buffer is available, an error is encountered of the end of the stream
+ // is reached.
+ // End of stream is signalled by a result of ERROR_END_OF_STREAM.
+ // A result of INFO_FORMAT_CHANGED indicates that the format of this
+ // MediaSource has changed mid-stream, the client can continue reading
+ // but should be prepared for buffers of the new configuration.
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL) = 0;
+
+ // Options that modify read() behaviour. The default is to
+ // a) not request a seek
+ // b) not be late, i.e. lateness_us = 0
+ struct ReadOptions {
+ enum SeekMode {
+ SEEK_PREVIOUS_SYNC,
+ SEEK_NEXT_SYNC,
+ SEEK_CLOSEST_SYNC,
+ SEEK_CLOSEST,
+ };
+
+ ReadOptions();
+
+ // Reset everything back to defaults.
+ void reset();
+
+ void setSeekTo(int64_t time_us, SeekMode mode = SEEK_CLOSEST_SYNC);
+ void clearSeekTo();
+ bool getSeekTo(int64_t *time_us, SeekMode *mode) const;
+
+ void setLateBy(int64_t lateness_us);
+ int64_t getLateBy() const;
+
+ private:
+ enum Options {
+ kSeekTo_Option = 1,
+ };
+
+ uint32_t mOptions;
+ int64_t mSeekTimeUs;
+ SeekMode mSeekMode;
+ int64_t mLatenessUs;
+ };
+
+ // Causes this source to suspend pulling data from its upstream source
+ // until a subsequent read-with-seek. Currently only supported by
+ // OMXCodec.
+ virtual status_t pause() {
+ return ERROR_UNSUPPORTED;
+ }
+
+ // The consumer of this media source requests that the given buffers
+ // are to be returned exclusively in response to read calls.
+ // This will be called after a successful start() and before the
+ // first read() call.
+ // Callee assumes ownership of the buffers if no error is returned.
+ virtual status_t setBuffers(const Vector<MediaBuffer *> &buffers) {
+ return ERROR_UNSUPPORTED;
+ }
+
+protected:
+ virtual ~MediaSource();
+
+private:
+ MediaSource(const MediaSource &);
+ MediaSource &operator=(const MediaSource &);
+};
+
+} // namespace android
+
+#endif // MEDIA_SOURCE_H_
diff --git a/include/media/stagefright/MediaWriter.h b/include/media/stagefright/MediaWriter.h
new file mode 100644
index 0000000..5cc8dcf
--- /dev/null
+++ b/include/media/stagefright/MediaWriter.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 MEDIA_WRITER_H_
+
+#define MEDIA_WRITER_H_
+
+#include <utils/RefBase.h>
+#include <media/IMediaRecorderClient.h>
+
+namespace android {
+
+struct MediaSource;
+struct MetaData;
+
+struct MediaWriter : public RefBase {
+ MediaWriter()
+ : mMaxFileSizeLimitBytes(0),
+ mMaxFileDurationLimitUs(0) {
+ }
+
+ virtual status_t addSource(const sp<MediaSource> &source) = 0;
+ virtual bool reachedEOS() = 0;
+ virtual status_t start(MetaData *params = NULL) = 0;
+ virtual status_t stop() = 0;
+ virtual status_t pause() = 0;
+
+ virtual void setMaxFileSize(int64_t bytes) { mMaxFileSizeLimitBytes = bytes; }
+ virtual void setMaxFileDuration(int64_t durationUs) { mMaxFileDurationLimitUs = durationUs; }
+ virtual void setListener(const sp<IMediaRecorderClient>& listener) {
+ mListener = listener;
+ }
+
+ virtual status_t dump(int fd, const Vector<String16>& args) {
+ return OK;
+ }
+
+protected:
+ virtual ~MediaWriter() {}
+ int64_t mMaxFileSizeLimitBytes;
+ int64_t mMaxFileDurationLimitUs;
+ sp<IMediaRecorderClient> mListener;
+
+ void notify(int msg, int ext1, int ext2) {
+ if (mListener != NULL) {
+ mListener->notify(msg, ext1, ext2);
+ }
+ }
+private:
+ MediaWriter(const MediaWriter &);
+ MediaWriter &operator=(const MediaWriter &);
+};
+
+} // namespace android
+
+#endif // MEDIA_WRITER_H_
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
new file mode 100644
index 0000000..639446e
--- /dev/null
+++ b/include/media/stagefright/MetaData.h
@@ -0,0 +1,244 @@
+/*
+ * 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.
+ */
+
+#ifndef META_DATA_H_
+
+#define META_DATA_H_
+
+#include <sys/types.h>
+
+#include <stdint.h>
+
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// The following keys map to int32_t data unless indicated otherwise.
+enum {
+ kKeyMIMEType = 'mime', // cstring
+ kKeyWidth = 'widt', // int32_t, image pixel
+ kKeyHeight = 'heig', // int32_t, image pixel
+ kKeyDisplayWidth = 'dWid', // int32_t, display/presentation
+ kKeyDisplayHeight = 'dHgt', // int32_t, display/presentation
+
+ // a rectangle, if absent assumed to be (0, 0, width - 1, height - 1)
+ kKeyCropRect = 'crop',
+
+ kKeyRotation = 'rotA', // int32_t (angle in degrees)
+ kKeyIFramesInterval = 'ifiv', // int32_t
+ kKeyStride = 'strd', // int32_t
+ kKeySliceHeight = 'slht', // int32_t
+ kKeyChannelCount = '#chn', // int32_t
+ kKeyChannelMask = 'chnm', // int32_t
+ kKeySampleRate = 'srte', // int32_t (audio sampling rate Hz)
+ kKeyFrameRate = 'frmR', // int32_t (video frame rate fps)
+ kKeyBitRate = 'brte', // int32_t (bps)
+ kKeyESDS = 'esds', // raw data
+ kKeyAVCC = 'avcc', // raw data
+ kKeyD263 = 'd263', // raw data
+ kKeyVorbisInfo = 'vinf', // raw data
+ kKeyVorbisBooks = 'vboo', // raw data
+ kKeyWantsNALFragments = 'NALf',
+ kKeyIsSyncFrame = 'sync', // int32_t (bool)
+ kKeyIsCodecConfig = 'conf', // int32_t (bool)
+ kKeyTime = 'time', // int64_t (usecs)
+ kKeyDecodingTime = 'decT', // int64_t (decoding timestamp in usecs)
+ kKeyNTPTime = 'ntpT', // uint64_t (ntp-timestamp)
+ kKeyTargetTime = 'tarT', // int64_t (usecs)
+ kKeyDriftTime = 'dftT', // int64_t (usecs)
+ kKeyAnchorTime = 'ancT', // int64_t (usecs)
+ kKeyDuration = 'dura', // int64_t (usecs)
+ kKeyColorFormat = 'colf',
+ kKeyPlatformPrivate = 'priv', // pointer
+ kKeyDecoderComponent = 'decC', // cstring
+ kKeyBufferID = 'bfID',
+ kKeyMaxInputSize = 'inpS',
+ kKeyThumbnailTime = 'thbT', // int64_t (usecs)
+ kKeyTrackID = 'trID',
+ kKeyIsDRM = 'idrm', // int32_t (bool)
+ kKeyEncoderDelay = 'encd', // int32_t (frames)
+ kKeyEncoderPadding = 'encp', // int32_t (frames)
+
+ kKeyAlbum = 'albu', // cstring
+ kKeyArtist = 'arti', // cstring
+ kKeyAlbumArtist = 'aart', // cstring
+ kKeyComposer = 'comp', // cstring
+ kKeyGenre = 'genr', // cstring
+ kKeyTitle = 'titl', // cstring
+ kKeyYear = 'year', // cstring
+ kKeyAlbumArt = 'albA', // compressed image data
+ kKeyAlbumArtMIME = 'alAM', // cstring
+ kKeyAuthor = 'auth', // cstring
+ kKeyCDTrackNumber = 'cdtr', // cstring
+ kKeyDiscNumber = 'dnum', // cstring
+ kKeyDate = 'date', // cstring
+ kKeyWriter = 'writ', // cstring
+ kKeyCompilation = 'cpil', // cstring
+ kKeyLocation = 'loc ', // cstring
+ kKeyTimeScale = 'tmsl', // int32_t
+
+ // video profile and level
+ kKeyVideoProfile = 'vprf', // int32_t
+ kKeyVideoLevel = 'vlev', // int32_t
+
+ // Set this key to enable authoring files in 64-bit offset
+ kKey64BitFileOffset = 'fobt', // int32_t (bool)
+ kKey2ByteNalLength = '2NAL', // int32_t (bool)
+
+ // Identify the file output format for authoring
+ // Please see <media/mediarecorder.h> for the supported
+ // file output formats.
+ kKeyFileType = 'ftyp', // int32_t
+
+ // Track authoring progress status
+ // kKeyTrackTimeStatus is used to track progress in elapsed time
+ kKeyTrackTimeStatus = 'tktm', // int64_t
+
+ kKeyNotRealTime = 'ntrt', // bool (int32_t)
+
+ // Ogg files can be tagged to be automatically looping...
+ kKeyAutoLoop = 'autL', // bool (int32_t)
+
+ kKeyValidSamples = 'valD', // int32_t
+
+ kKeyIsUnreadable = 'unre', // bool (int32_t)
+
+ // An indication that a video buffer has been rendered.
+ kKeyRendered = 'rend', // bool (int32_t)
+
+ // The language code for this media
+ kKeyMediaLanguage = 'lang', // cstring
+
+ // To store the timed text format data
+ kKeyTextFormatData = 'text', // raw data
+
+ kKeyRequiresSecureBuffers = 'secu', // bool (int32_t)
+
+ kKeyScrambling = 'scrm', // int32_t
+ kKeyEMM = 'emm ', // raw data
+ kKeyECM = 'ecm ', // raw data
+
+ kKeyIsADTS = 'adts', // bool (int32_t)
+};
+
+enum {
+ kTypeESDS = 'esds',
+ kTypeAVCC = 'avcc',
+ kTypeD263 = 'd263',
+};
+
+class MetaData : public RefBase {
+public:
+ MetaData();
+ MetaData(const MetaData &from);
+
+ enum Type {
+ TYPE_NONE = 'none',
+ TYPE_C_STRING = 'cstr',
+ TYPE_INT32 = 'in32',
+ TYPE_INT64 = 'in64',
+ TYPE_FLOAT = 'floa',
+ TYPE_POINTER = 'ptr ',
+ TYPE_RECT = 'rect',
+ };
+
+ void clear();
+ bool remove(uint32_t key);
+
+ bool setCString(uint32_t key, const char *value);
+ bool setInt32(uint32_t key, int32_t value);
+ bool setInt64(uint32_t key, int64_t value);
+ bool setFloat(uint32_t key, float value);
+ bool setPointer(uint32_t key, void *value);
+
+ bool setRect(
+ uint32_t key,
+ int32_t left, int32_t top,
+ int32_t right, int32_t bottom);
+
+ bool findCString(uint32_t key, const char **value);
+ bool findInt32(uint32_t key, int32_t *value);
+ bool findInt64(uint32_t key, int64_t *value);
+ bool findFloat(uint32_t key, float *value);
+ bool findPointer(uint32_t key, void **value);
+
+ bool findRect(
+ uint32_t key,
+ int32_t *left, int32_t *top,
+ int32_t *right, int32_t *bottom);
+
+ bool setData(uint32_t key, uint32_t type, const void *data, size_t size);
+
+ bool findData(uint32_t key, uint32_t *type,
+ const void **data, size_t *size) const;
+
+ void dumpToLog() const;
+
+protected:
+ virtual ~MetaData();
+
+private:
+ struct typed_data {
+ typed_data();
+ ~typed_data();
+
+ typed_data(const MetaData::typed_data &);
+ typed_data &operator=(const MetaData::typed_data &);
+
+ void clear();
+ void setData(uint32_t type, const void *data, size_t size);
+ void getData(uint32_t *type, const void **data, size_t *size) const;
+ String8 asString() const;
+
+ private:
+ uint32_t mType;
+ size_t mSize;
+
+ union {
+ void *ext_data;
+ float reservoir;
+ } u;
+
+ bool usesReservoir() const {
+ return mSize <= sizeof(u.reservoir);
+ }
+
+ void allocateStorage(size_t size);
+ void freeStorage();
+
+ void *storage() {
+ return usesReservoir() ? &u.reservoir : u.ext_data;
+ }
+
+ const void *storage() const {
+ return usesReservoir() ? &u.reservoir : u.ext_data;
+ }
+ };
+
+ struct Rect {
+ int32_t mLeft, mTop, mRight, mBottom;
+ };
+
+ KeyedVector<uint32_t, typed_data> mItems;
+
+ // MetaData &operator=(const MetaData &);
+};
+
+} // namespace android
+
+#endif // META_DATA_H_
diff --git a/include/media/stagefright/NativeWindowWrapper.h b/include/media/stagefright/NativeWindowWrapper.h
new file mode 100644
index 0000000..97cc0ce
--- /dev/null
+++ b/include/media/stagefright/NativeWindowWrapper.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 NATIVE_WINDOW_WRAPPER_H_
+
+#define NATIVE_WINDOW_WRAPPER_H_
+
+#include <gui/SurfaceTextureClient.h>
+
+namespace android {
+
+// SurfaceTextureClient derives from ANativeWindow which derives from multiple
+// base classes, in order to carry it in AMessages, we'll temporarily wrap it
+// into a NativeWindowWrapper.
+
+struct NativeWindowWrapper : RefBase {
+ NativeWindowWrapper(
+ const sp<SurfaceTextureClient> &surfaceTextureClient) :
+ mSurfaceTextureClient(surfaceTextureClient) { }
+
+ sp<ANativeWindow> getNativeWindow() const {
+ return mSurfaceTextureClient;
+ }
+
+ sp<SurfaceTextureClient> getSurfaceTextureClient() const {
+ return mSurfaceTextureClient;
+ }
+
+private:
+ const sp<SurfaceTextureClient> mSurfaceTextureClient;
+
+ DISALLOW_EVIL_CONSTRUCTORS(NativeWindowWrapper);
+};
+
+} // namespace android
+
+#endif // NATIVE_WINDOW_WRAPPER_H_
diff --git a/include/media/stagefright/NuMediaExtractor.h b/include/media/stagefright/NuMediaExtractor.h
new file mode 100644
index 0000000..07c7be5
--- /dev/null
+++ b/include/media/stagefright/NuMediaExtractor.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_MEDIA_EXTRACTOR_H_
+#define NU_MEDIA_EXTRACTOR_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct ABuffer;
+struct AMessage;
+struct MediaBuffer;
+struct MediaExtractor;
+struct MediaSource;
+
+struct NuMediaExtractor : public RefBase {
+ enum SampleFlags {
+ SAMPLE_FLAG_SYNC = 1,
+ SAMPLE_FLAG_ENCRYPTED = 2,
+ };
+
+ NuMediaExtractor();
+
+ status_t setDataSource(const char *path);
+
+ size_t countTracks() const;
+ status_t getTrackFormat(size_t index, sp<AMessage> *format) const;
+
+ status_t selectTrack(size_t index);
+
+ status_t seekTo(int64_t timeUs);
+
+ status_t advance();
+ status_t readSampleData(const sp<ABuffer> &buffer);
+ status_t getSampleTrackIndex(size_t *trackIndex);
+ status_t getSampleTime(int64_t *sampleTimeUs);
+ status_t getSampleFlags(uint32_t *sampleFlags);
+
+protected:
+ virtual ~NuMediaExtractor();
+
+private:
+ enum TrackFlags {
+ kIsVorbis = 1,
+ };
+
+ struct TrackInfo {
+ sp<MediaSource> mSource;
+ size_t mTrackIndex;
+ status_t mFinalResult;
+ MediaBuffer *mSample;
+ int64_t mSampleTimeUs;
+ uint32_t mSampleFlags;
+
+ uint32_t mTrackFlags; // bitmask of "TrackFlags"
+ };
+
+ sp<MediaExtractor> mImpl;
+
+ Vector<TrackInfo> mSelectedTracks;
+
+ ssize_t fetchTrackSamples(int64_t seekTimeUs = -1ll);
+ void releaseTrackSamples();
+
+ DISALLOW_EVIL_CONSTRUCTORS(NuMediaExtractor);
+};
+
+} // namespace android
+
+#endif // NU_MEDIA_EXTRACTOR_H_
+
diff --git a/include/media/stagefright/OMXClient.h b/include/media/stagefright/OMXClient.h
new file mode 100644
index 0000000..2f14d06
--- /dev/null
+++ b/include/media/stagefright/OMXClient.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef OMX_CLIENT_H_
+
+#define OMX_CLIENT_H_
+
+#include <media/IOMX.h>
+
+namespace android {
+
+class OMXClient {
+public:
+ OMXClient();
+
+ status_t connect();
+ void disconnect();
+
+ sp<IOMX> interface() {
+ return mOMX;
+ }
+
+private:
+ sp<IOMX> mOMX;
+
+ OMXClient(const OMXClient &);
+ OMXClient &operator=(const OMXClient &);
+};
+
+} // namespace android
+
+#endif // OMX_CLIENT_H_
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
new file mode 100644
index 0000000..7d51dee
--- /dev/null
+++ b/include/media/stagefright/OMXCodec.h
@@ -0,0 +1,390 @@
+/*
+ * 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.
+ */
+
+#ifndef OMX_CODEC_H_
+
+#define OMX_CODEC_H_
+
+#include <android/native_window.h>
+#include <media/IOMX.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct MediaCodecList;
+class MemoryDealer;
+struct OMXCodecObserver;
+struct CodecProfileLevel;
+class SkipCutBuffer;
+
+struct OMXCodec : public MediaSource,
+ public MediaBufferObserver {
+ enum CreationFlags {
+ kPreferSoftwareCodecs = 1,
+ kIgnoreCodecSpecificData = 2,
+
+ // The client wants to access the output buffer's video
+ // data for example for thumbnail extraction.
+ kClientNeedsFramebuffer = 4,
+
+ // Request for software or hardware codecs. If request
+ // can not be fullfilled, Create() returns NULL.
+ kSoftwareCodecsOnly = 8,
+ kHardwareCodecsOnly = 16,
+
+ // Store meta data in video buffers
+ kStoreMetaDataInVideoBuffers = 32,
+
+ // Only submit one input buffer at one time.
+ kOnlySubmitOneInputBufferAtOneTime = 64,
+
+ // Enable GRALLOC_USAGE_PROTECTED for output buffers from native window
+ kEnableGrallocUsageProtected = 128,
+
+ // Secure decoding mode
+ kUseSecureInputBuffers = 256,
+ };
+ static sp<MediaSource> Create(
+ const sp<IOMX> &omx,
+ const sp<MetaData> &meta, bool createEncoder,
+ const sp<MediaSource> &source,
+ const char *matchComponentName = NULL,
+ uint32_t flags = 0,
+ const sp<ANativeWindow> &nativeWindow = NULL);
+
+ static void setComponentRole(
+ const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder,
+ const char *mime);
+
+ 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);
+
+ virtual status_t pause();
+
+ // from MediaBufferObserver
+ virtual void signalBufferReturned(MediaBuffer *buffer);
+
+ enum Quirks {
+ kNeedsFlushBeforeDisable = 1,
+ kWantsNALFragments = 2,
+ kRequiresLoadedToIdleAfterAllocation = 4,
+ kRequiresAllocateBufferOnInputPorts = 8,
+ kRequiresFlushCompleteEmulation = 16,
+ kRequiresAllocateBufferOnOutputPorts = 32,
+ kRequiresFlushBeforeShutdown = 64,
+ kDefersOutputBufferAllocation = 128,
+ kDecoderLiesAboutNumberOfChannels = 256,
+ kInputBufferSizesAreBogus = 512,
+ kSupportsMultipleFramesPerInputBuffer = 1024,
+ kAvoidMemcopyInputRecordingFrames = 2048,
+ kRequiresLargerEncoderOutputBuffer = 4096,
+ kOutputBuffersAreUnreadable = 8192,
+ };
+
+ // for use by ACodec
+ static void findMatchingCodecs(
+ const char *mime,
+ bool createEncoder, const char *matchComponentName,
+ uint32_t flags,
+ Vector<String8> *matchingCodecs,
+ Vector<uint32_t> *matchingCodecQuirks = NULL);
+
+ static uint32_t getComponentQuirks(
+ const MediaCodecList *list, size_t index);
+
+ static bool findCodecQuirks(const char *componentName, uint32_t *quirks);
+
+protected:
+ virtual ~OMXCodec();
+
+private:
+
+ // Make sure mLock is accessible to OMXCodecObserver
+ friend class OMXCodecObserver;
+
+ // Call this with mLock hold
+ void on_message(const omx_message &msg);
+
+ enum State {
+ DEAD,
+ LOADED,
+ LOADED_TO_IDLE,
+ IDLE_TO_EXECUTING,
+ EXECUTING,
+ EXECUTING_TO_IDLE,
+ IDLE_TO_LOADED,
+ RECONFIGURING,
+ ERROR
+ };
+
+ enum {
+ kPortIndexInput = 0,
+ kPortIndexOutput = 1
+ };
+
+ enum PortStatus {
+ ENABLED,
+ DISABLING,
+ DISABLED,
+ ENABLING,
+ SHUTTING_DOWN,
+ };
+
+ enum BufferStatus {
+ OWNED_BY_US,
+ OWNED_BY_COMPONENT,
+ OWNED_BY_NATIVE_WINDOW,
+ OWNED_BY_CLIENT,
+ };
+
+ struct BufferInfo {
+ IOMX::buffer_id mBuffer;
+ BufferStatus mStatus;
+ sp<IMemory> mMem;
+ size_t mSize;
+ void *mData;
+ MediaBuffer *mMediaBuffer;
+ };
+
+ struct CodecSpecificData {
+ size_t mSize;
+ uint8_t mData[1];
+ };
+
+ sp<IOMX> mOMX;
+ bool mOMXLivesLocally;
+ IOMX::node_id mNode;
+ uint32_t mQuirks;
+
+ // Flags specified in the creation of the codec.
+ uint32_t mFlags;
+
+ bool mIsEncoder;
+ bool mIsVideo;
+ char *mMIME;
+ char *mComponentName;
+ sp<MetaData> mOutputFormat;
+ sp<MediaSource> mSource;
+ Vector<CodecSpecificData *> mCodecSpecificData;
+ size_t mCodecSpecificDataIndex;
+
+ sp<MemoryDealer> mDealer[2];
+
+ State mState;
+ Vector<BufferInfo> mPortBuffers[2];
+ PortStatus mPortStatus[2];
+ bool mInitialBufferSubmit;
+ bool mSignalledEOS;
+ status_t mFinalStatus;
+ bool mNoMoreOutputData;
+ bool mOutputPortSettingsHaveChanged;
+ int64_t mSeekTimeUs;
+ ReadOptions::SeekMode mSeekMode;
+ int64_t mTargetTimeUs;
+ bool mOutputPortSettingsChangedPending;
+ SkipCutBuffer *mSkipCutBuffer;
+
+ MediaBuffer *mLeftOverBuffer;
+
+ Mutex mLock;
+ Condition mAsyncCompletion;
+
+ bool mPaused;
+
+ sp<ANativeWindow> mNativeWindow;
+
+ // The index in each of the mPortBuffers arrays of the buffer that will be
+ // submitted to OMX next. This only applies when using buffers from a
+ // native window.
+ size_t mNextNativeBufferIndex[2];
+
+ // A list of indices into mPortStatus[kPortIndexOutput] filled with data.
+ List<size_t> mFilledBuffers;
+ Condition mBufferFilled;
+
+ // Used to record the decoding time for an output picture from
+ // a video encoder.
+ List<int64_t> mDecodingTimeList;
+
+ OMXCodec(const sp<IOMX> &omx, IOMX::node_id node,
+ uint32_t quirks, uint32_t flags,
+ bool isEncoder, const char *mime, const char *componentName,
+ const sp<MediaSource> &source,
+ const sp<ANativeWindow> &nativeWindow);
+
+ void addCodecSpecificData(const void *data, size_t size);
+ void clearCodecSpecificData();
+
+ void setComponentRole();
+
+ void setAMRFormat(bool isWAMR, int32_t bitRate);
+
+ status_t setAACFormat(
+ int32_t numChannels, int32_t sampleRate, int32_t bitRate,
+ bool isADTS);
+
+ void setG711Format(int32_t numChannels);
+
+ status_t setVideoPortFormatType(
+ OMX_U32 portIndex,
+ OMX_VIDEO_CODINGTYPE compressionFormat,
+ OMX_COLOR_FORMATTYPE colorFormat);
+
+ void setVideoInputFormat(
+ const char *mime, const sp<MetaData>& meta);
+
+ status_t setupBitRate(int32_t bitRate);
+ status_t setupErrorCorrectionParameters();
+ status_t setupH263EncoderParameters(const sp<MetaData>& meta);
+ status_t setupMPEG4EncoderParameters(const sp<MetaData>& meta);
+ status_t setupAVCEncoderParameters(const sp<MetaData>& meta);
+ status_t findTargetColorFormat(
+ const sp<MetaData>& meta, OMX_COLOR_FORMATTYPE *colorFormat);
+
+ status_t isColorFormatSupported(
+ OMX_COLOR_FORMATTYPE colorFormat, int portIndex);
+
+ // If profile/level is set in the meta data, its value in the meta
+ // data will be used; otherwise, the default value will be used.
+ status_t getVideoProfileLevel(const sp<MetaData>& meta,
+ const CodecProfileLevel& defaultProfileLevel,
+ CodecProfileLevel& profileLevel);
+
+ status_t setVideoOutputFormat(
+ const char *mime, OMX_U32 width, OMX_U32 height);
+
+ void setImageOutputFormat(
+ OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height);
+
+ void setJPEGInputFormat(
+ OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize);
+
+ void setMinBufferSize(OMX_U32 portIndex, OMX_U32 size);
+
+ void setRawAudioFormat(
+ OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels);
+
+ status_t allocateBuffers();
+ status_t allocateBuffersOnPort(OMX_U32 portIndex);
+ status_t allocateOutputBuffersFromNativeWindow();
+
+ status_t queueBufferToNativeWindow(BufferInfo *info);
+ status_t cancelBufferToNativeWindow(BufferInfo *info);
+ BufferInfo* dequeueBufferFromNativeWindow();
+ status_t pushBlankBuffersToNativeWindow();
+
+ status_t freeBuffersOnPort(
+ OMX_U32 portIndex, bool onlyThoseWeOwn = false);
+
+ status_t freeBuffer(OMX_U32 portIndex, size_t bufIndex);
+
+ bool drainInputBuffer(IOMX::buffer_id buffer);
+ void fillOutputBuffer(IOMX::buffer_id buffer);
+ bool drainInputBuffer(BufferInfo *info);
+ void fillOutputBuffer(BufferInfo *info);
+
+ void drainInputBuffers();
+ void fillOutputBuffers();
+
+ bool drainAnyInputBuffer();
+ BufferInfo *findInputBufferByDataPointer(void *ptr);
+ BufferInfo *findEmptyInputBuffer();
+
+ // Returns true iff a flush was initiated and a completion event is
+ // upcoming, false otherwise (A flush was not necessary as we own all
+ // the buffers on that port).
+ // This method will ONLY ever return false for a component with quirk
+ // "kRequiresFlushCompleteEmulation".
+ bool flushPortAsync(OMX_U32 portIndex);
+
+ void disablePortAsync(OMX_U32 portIndex);
+ status_t enablePortAsync(OMX_U32 portIndex);
+
+ static size_t countBuffersWeOwn(const Vector<BufferInfo> &buffers);
+ static bool isIntermediateState(State state);
+
+ void onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
+ void onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data);
+ void onStateChange(OMX_STATETYPE newState);
+ void onPortSettingsChanged(OMX_U32 portIndex);
+
+ void setState(State newState);
+
+ status_t init();
+ void initOutputFormat(const sp<MetaData> &inputFormat);
+ status_t initNativeWindow();
+
+ void initNativeWindowCrop();
+
+ void dumpPortStatus(OMX_U32 portIndex);
+
+ status_t configureCodec(const sp<MetaData> &meta);
+
+ void restorePatchedDataPointer(BufferInfo *info);
+
+ status_t applyRotation();
+ status_t waitForBufferFilled_l();
+
+ int64_t getDecodingTimeUs();
+
+ status_t parseAVCCodecSpecificData(
+ const void *data, size_t size,
+ unsigned *profile, unsigned *level);
+
+ OMXCodec(const OMXCodec &);
+ OMXCodec &operator=(const OMXCodec &);
+};
+
+struct CodecCapabilities {
+ String8 mComponentName;
+ Vector<CodecProfileLevel> mProfileLevels;
+ Vector<OMX_U32> mColorFormats;
+};
+
+// Return a vector of componentNames with supported profile/level pairs
+// supporting the given mime type, if queryDecoders==true, returns components
+// that decode content of the given type, otherwise returns components
+// that encode content of the given type.
+// profile and level indications only make sense for h.263, mpeg4 and avc
+// video.
+// If hwCodecOnly==true, only returns hardware-based components, software and
+// hardware otherwise.
+// The profile/level values correspond to
+// OMX_VIDEO_H263PROFILETYPE, OMX_VIDEO_MPEG4PROFILETYPE,
+// OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263LEVELTYPE, OMX_VIDEO_MPEG4LEVELTYPE
+// and OMX_VIDEO_AVCLEVELTYPE respectively.
+
+status_t QueryCodecs(
+ const sp<IOMX> &omx,
+ const char *mimeType, bool queryDecoders, bool hwCodecOnly,
+ Vector<CodecCapabilities> *results);
+
+status_t QueryCodecs(
+ const sp<IOMX> &omx,
+ const char *mimeType, bool queryDecoders,
+ Vector<CodecCapabilities> *results);
+
+
+} // namespace android
+
+#endif // OMX_CODEC_H_
diff --git a/include/media/stagefright/SkipCutBuffer.h b/include/media/stagefright/SkipCutBuffer.h
new file mode 100644
index 0000000..5c7cd47
--- /dev/null
+++ b/include/media/stagefright/SkipCutBuffer.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SKIP_CUT_BUFFER_H_
+
+#define SKIP_CUT_BUFFER_H_
+
+#include <media/stagefright/MediaBuffer.h>
+
+namespace android {
+
+/**
+ * utility class to cut the start and end off a stream of data in MediaBuffers
+ *
+ */
+class SkipCutBuffer {
+ public:
+ // 'skip' is the number of bytes to skip from the beginning
+ // 'cut' is the number of bytes to cut from the end
+ // 'output_size' is the size in bytes of the MediaBuffers that will be used
+ SkipCutBuffer(int32_t skip, int32_t cut, int32_t output_size);
+ virtual ~SkipCutBuffer();
+
+ // Submit one MediaBuffer for skipping and cutting. This may consume all or
+ // some of the data in the buffer, or it may add data to it.
+ // After this, the caller should continue processing the buffer as usual.
+ void submit(MediaBuffer *buffer);
+ void clear();
+ size_t size(); // how many bytes are currently stored in the buffer
+
+ private:
+ void write(const char *src, size_t num);
+ size_t read(char *dst, size_t num);
+ int32_t mFrontPadding;
+ int32_t mBackPadding;
+ int32_t mWriteHead;
+ int32_t mReadHead;
+ int32_t mCapacity;
+ char* mCutBuffer;
+ DISALLOW_EVIL_CONSTRUCTORS(SkipCutBuffer);
+};
+
+} // namespace android
+
+#endif // OMX_CODEC_H_
diff --git a/include/media/stagefright/StagefrightMediaScanner.h b/include/media/stagefright/StagefrightMediaScanner.h
new file mode 100644
index 0000000..6510a59
--- /dev/null
+++ b/include/media/stagefright/StagefrightMediaScanner.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#ifndef STAGEFRIGHT_MEDIA_SCANNER_H_
+
+#define STAGEFRIGHT_MEDIA_SCANNER_H_
+
+#include <media/mediascanner.h>
+
+namespace android {
+
+struct StagefrightMediaScanner : public MediaScanner {
+ StagefrightMediaScanner();
+ virtual ~StagefrightMediaScanner();
+
+ virtual MediaScanResult processFile(
+ const char *path, const char *mimeType,
+ MediaScannerClient &client);
+
+ virtual char *extractAlbumArt(int fd);
+
+private:
+ StagefrightMediaScanner(const StagefrightMediaScanner &);
+ StagefrightMediaScanner &operator=(const StagefrightMediaScanner &);
+
+ MediaScanResult processFileInternal(
+ const char *path, const char *mimeType,
+ MediaScannerClient &client);
+};
+
+} // namespace android
+
+#endif // STAGEFRIGHT_MEDIA_SCANNER_H_
diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h
new file mode 100644
index 0000000..936b057
--- /dev/null
+++ b/include/media/stagefright/SurfaceMediaSource.h
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_GUI_SURFACEMEDIASOURCE_H
+#define ANDROID_GUI_SURFACEMEDIASOURCE_H
+
+#include <gui/ISurfaceTexture.h>
+
+#include <utils/threads.h>
+#include <utils/Vector.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaBuffer.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class IGraphicBufferAlloc;
+class String8;
+class GraphicBuffer;
+
+class SurfaceMediaSource : public BnSurfaceTexture, public MediaSource,
+ public MediaBufferObserver {
+public:
+ enum { MIN_UNDEQUEUED_BUFFERS = 4 };
+ enum {
+ MIN_ASYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS + 1,
+ MIN_SYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS
+ };
+ enum { NUM_BUFFER_SLOTS = 32 };
+ enum { NO_CONNECTED_API = 0 };
+
+ struct FrameAvailableListener : public virtual RefBase {
+ // onFrameAvailable() is called from queueBuffer() is the FIFO is
+ // empty. You can use SurfaceMediaSource::getQueuedCount() to
+ // figure out if there are more frames waiting.
+ // This is called without any lock held can be called concurrently by
+ // multiple threads.
+ virtual void onFrameAvailable() = 0;
+ };
+
+ SurfaceMediaSource(uint32_t bufW, uint32_t bufH);
+
+ virtual ~SurfaceMediaSource();
+
+
+ // For the MediaSource interface for use by StageFrightRecorder:
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop() { return reset(); }
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL);
+ virtual sp<MetaData> getFormat();
+
+ // Pass the metadata over to the buffer, call when you have the lock
+ void passMetadataBufferLocked(MediaBuffer **buffer);
+ bool checkBufferMatchesSlot(int slot, MediaBuffer *buffer);
+
+ // Get / Set the frame rate used for encoding. Default fps = 30
+ status_t setFrameRate(int32_t fps) ;
+ int32_t getFrameRate( ) const;
+
+ // The call for the StageFrightRecorder to tell us that
+ // it is done using the MediaBuffer data so that its state
+ // can be set to FREE for dequeuing
+ virtual void signalBufferReturned(MediaBuffer* buffer);
+ // end of MediaSource interface
+
+ uint32_t getBufferCount( ) const { return mBufferCount;}
+
+
+ // setBufferCount updates the number of available buffer slots. After
+ // calling this all buffer slots are both unallocated and owned by the
+ // SurfaceMediaSource object (i.e. they are not owned by the client).
+ virtual status_t setBufferCount(int bufferCount);
+
+ virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
+
+ // dequeueBuffer gets the next buffer slot index for the client to use. If a
+ // buffer slot is available then that slot index is written to the location
+ // pointed to by the buf argument and a status of OK is returned. If no
+ // slot is available then a status of -EBUSY is returned and buf is
+ // unmodified.
+ virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
+ uint32_t format, uint32_t usage);
+
+ // queueBuffer returns a filled buffer to the SurfaceMediaSource. In addition, a
+ // timestamp must be provided for the buffer. The timestamp is in
+ // nanoseconds, and must be monotonically increasing. Its other semantics
+ // (zero point, etc) are client-dependent and should be documented by the
+ // client.
+ virtual status_t queueBuffer(int buf, int64_t timestamp,
+ uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
+ virtual void cancelBuffer(int buf);
+
+ // onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder)
+ // or listeners that a frame has been received
+ // The buffer is not made available for dequeueing immediately. We need to
+ // wait to hear from StageFrightRecorder to set the buffer FREE
+ // Make sure this is called when the mutex is locked
+ virtual status_t onFrameReceivedLocked();
+
+ virtual status_t setScalingMode(int mode) { return OK; } // no op for encoding
+ virtual int query(int what, int* value);
+
+ // Just confirming to the ISurfaceTexture interface as of now
+ virtual status_t setCrop(const Rect& reg) { return OK; }
+ virtual status_t setTransform(uint32_t transform) {return OK;}
+
+ // setSynchronousMode set whether dequeueBuffer is synchronous or
+ // asynchronous. In synchronous mode, dequeueBuffer blocks until
+ // a buffer is available, the currently bound buffer can be dequeued and
+ // queued buffers will be retired in order.
+ // The default mode is synchronous.
+ // TODO: Clarify the minute differences bet sycn /async
+ // modes (S.Encoder vis-a-vis SurfaceTexture)
+ virtual status_t setSynchronousMode(bool enabled);
+
+ // connect attempts to connect a client API to the SurfaceMediaSource. This
+ // must be called before any other ISurfaceTexture methods are called except
+ // for getAllocator.
+ //
+ // This method will fail if the connect was previously called on the
+ // SurfaceMediaSource and no corresponding disconnect call was made.
+ virtual status_t connect(int api,
+ uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
+
+ // disconnect attempts to disconnect a client API from the SurfaceMediaSource.
+ // Calling this method will cause any subsequent calls to other
+ // ISurfaceTexture methods to fail except for getAllocator and connect.
+ // Successfully calling connect after this will allow the other methods to
+ // succeed again.
+ //
+ // This method will fail if the the SurfaceMediaSource is not currently
+ // connected to the specified client API.
+ virtual status_t disconnect(int api);
+
+ // getqueuedCount returns the number of queued frames waiting in the
+ // FIFO. In asynchronous mode, this always returns 0 or 1 since
+ // frames are not accumulating in the FIFO.
+ size_t getQueuedCount() const;
+
+ // setBufferCountServer set the buffer count. If the client has requested
+ // a buffer count using setBufferCount, the server-buffer count will
+ // take effect once the client sets the count back to zero.
+ status_t setBufferCountServer(int bufferCount);
+
+ // getTimestamp retrieves the timestamp associated with the image
+ // set by the most recent call to read()
+ //
+ // The timestamp is in nanoseconds, and is monotonically increasing. Its
+ // other semantics (zero point, etc) are source-dependent and should be
+ // documented by the source.
+ int64_t getTimestamp();
+
+ // setFrameAvailableListener sets the listener object that will be notified
+ // when a new frame becomes available.
+ void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
+
+ // getCurrentBuffer returns the buffer associated with the current image.
+ sp<GraphicBuffer> getCurrentBuffer() const;
+
+ // dump our state in a String
+ void dump(String8& result) const;
+ void dump(String8& result, const char* prefix, char* buffer,
+ size_t SIZE) const;
+
+ // isMetaDataStoredInVideoBuffers tells the encoder whether we will
+ // pass metadata through the buffers. Currently, it is force set to true
+ bool isMetaDataStoredInVideoBuffers() const;
+
+protected:
+
+ // freeAllBuffersLocked frees the resources (both GraphicBuffer and EGLImage) for
+ // all slots.
+ void freeAllBuffersLocked();
+ static bool isExternalFormat(uint32_t format);
+
+private:
+
+ status_t setBufferCountServerLocked(int bufferCount);
+
+ enum { INVALID_BUFFER_SLOT = -1 };
+
+ struct BufferSlot {
+
+ BufferSlot()
+ : mBufferState(BufferSlot::FREE),
+ mRequestBufferCalled(false),
+ mTimestamp(0) {
+ }
+
+ // mGraphicBuffer points to the buffer allocated for this slot or is
+ // NULL if no buffer has been allocated.
+ sp<GraphicBuffer> mGraphicBuffer;
+
+ // BufferState represents the different states in which a buffer slot
+ // can be.
+ enum BufferState {
+ // FREE indicates that the buffer is not currently being used and
+ // will not be used in the future until it gets dequeued and
+ // subseqently queued by the client.
+ FREE = 0,
+
+ // DEQUEUED indicates that the buffer has been dequeued by the
+ // client, but has not yet been queued or canceled. The buffer is
+ // considered 'owned' by the client, and the server should not use
+ // it for anything.
+ //
+ // Note that when in synchronous-mode (mSynchronousMode == true),
+ // the buffer that's currently attached to the texture may be
+ // dequeued by the client. That means that the current buffer can
+ // be in either the DEQUEUED or QUEUED state. In asynchronous mode,
+ // however, the current buffer is always in the QUEUED state.
+ DEQUEUED = 1,
+
+ // QUEUED indicates that the buffer has been queued by the client,
+ // and has not since been made available for the client to dequeue.
+ // Attaching the buffer to the texture does NOT transition the
+ // buffer away from the QUEUED state. However, in Synchronous mode
+ // the current buffer may be dequeued by the client under some
+ // circumstances. See the note about the current buffer in the
+ // documentation for DEQUEUED.
+ QUEUED = 2,
+ };
+
+ // mBufferState is the current state of this buffer slot.
+ BufferState mBufferState;
+
+ // mRequestBufferCalled is used for validating that the client did
+ // call requestBuffer() when told to do so. Technically this is not
+ // needed but useful for debugging and catching client bugs.
+ bool mRequestBufferCalled;
+
+ // mTimestamp is the current timestamp for this buffer slot. This gets
+ // to set by queueBuffer each time this slot is queued.
+ int64_t mTimestamp;
+ };
+
+ // mSlots is the array of buffer slots that must be mirrored on the client
+ // side. This allows buffer ownership to be transferred between the client
+ // and server without sending a GraphicBuffer over binder. The entire array
+ // is initialized to NULL at construction time, and buffers are allocated
+ // for a slot when requestBuffer is called with that slot's index.
+ BufferSlot mSlots[NUM_BUFFER_SLOTS];
+
+ // mDefaultWidth holds the default width of allocated buffers. It is used
+ // in requestBuffers() if a width and height of zero is specified.
+ uint32_t mDefaultWidth;
+
+ // mDefaultHeight holds the default height of allocated buffers. It is used
+ // in requestBuffers() if a width and height of zero is specified.
+ uint32_t mDefaultHeight;
+
+ // mPixelFormat holds the pixel format of allocated buffers. It is used
+ // in requestBuffers() if a format of zero is specified.
+ uint32_t mPixelFormat;
+
+ // mBufferCount is the number of buffer slots that the client and server
+ // must maintain. It defaults to MIN_ASYNC_BUFFER_SLOTS and can be changed
+ // by calling setBufferCount or setBufferCountServer
+ int mBufferCount;
+
+ // mClientBufferCount is the number of buffer slots requested by the
+ // client. The default is zero, which means the client doesn't care how
+ // many buffers there are
+ int mClientBufferCount;
+
+ // mServerBufferCount buffer count requested by the server-side
+ int mServerBufferCount;
+
+ // mCurrentSlot is the buffer slot index of the buffer that is currently
+ // being used by buffer consumer
+ // (e.g. StageFrightRecorder in the case of SurfaceMediaSource or GLTexture
+ // in the case of SurfaceTexture).
+ // It is initialized to INVALID_BUFFER_SLOT,
+ // indicating that no buffer slot is currently bound to the texture. Note,
+ // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
+ // that no buffer is bound to the texture. A call to setBufferCount will
+ // reset mCurrentTexture to INVALID_BUFFER_SLOT.
+ int mCurrentSlot;
+
+
+ // mCurrentBuf is the graphic buffer of the current slot to be used by
+ // buffer consumer. It's possible that this buffer is not associated
+ // with any buffer slot, so we must track it separately in order to
+ // properly use IGraphicBufferAlloc::freeAllGraphicBuffersExcept.
+ sp<GraphicBuffer> mCurrentBuf;
+
+
+ // mCurrentTimestamp is the timestamp for the current texture. It
+ // gets set to mLastQueuedTimestamp each time updateTexImage is called.
+ int64_t mCurrentTimestamp;
+
+ // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
+ // allocate new GraphicBuffer objects.
+ sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
+
+ // mFrameAvailableListener is the listener object that will be called when a
+ // new frame becomes available. If it is not NULL it will be called from
+ // queueBuffer.
+ sp<FrameAvailableListener> mFrameAvailableListener;
+
+ // mSynchronousMode whether we're in synchronous mode or not
+ bool mSynchronousMode;
+
+ // mConnectedApi indicates the API that is currently connected to this
+ // SurfaceTexture. It defaults to NO_CONNECTED_API (= 0), and gets updated
+ // by the connect and disconnect methods.
+ int mConnectedApi;
+
+ // mDequeueCondition condition used for dequeueBuffer in synchronous mode
+ mutable Condition mDequeueCondition;
+
+
+ // mQueue is a FIFO of queued buffers used in synchronous mode
+ typedef Vector<int> Fifo;
+ Fifo mQueue;
+
+ // mMutex is the mutex used to prevent concurrent access to the member
+ // variables of SurfaceMediaSource objects. It must be locked whenever the
+ // member variables are accessed.
+ mutable Mutex mMutex;
+
+ ////////////////////////// For MediaSource
+ // Set to a default of 30 fps if not specified by the client side
+ int32_t mFrameRate;
+
+ // mStopped is a flag to check if the recording is going on
+ bool mStopped;
+
+ // mNumFramesReceived indicates the number of frames recieved from
+ // the client side
+ int mNumFramesReceived;
+ // mNumFramesEncoded indicates the number of frames passed on to the
+ // encoder
+ int mNumFramesEncoded;
+
+ // mFirstFrameTimestamp is the timestamp of the first received frame.
+ // It is used to offset the output timestamps so recording starts at time 0.
+ int64_t mFirstFrameTimestamp;
+ // mStartTimeNs is the start time passed into the source at start, used to
+ // offset timestamps.
+ int64_t mStartTimeNs;
+
+ // mFrameAvailableCondition condition used to indicate whether there
+ // is a frame available for dequeuing
+ Condition mFrameAvailableCondition;
+ Condition mFrameCompleteCondition;
+
+ status_t reset();
+
+ // Avoid copying and equating and default constructor
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SurfaceMediaSource);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GUI_SURFACEMEDIASOURCE_H
diff --git a/include/media/stagefright/TimeSource.h b/include/media/stagefright/TimeSource.h
new file mode 100644
index 0000000..443673d
--- /dev/null
+++ b/include/media/stagefright/TimeSource.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#ifndef TIME_SOURCE_H_
+
+#define TIME_SOURCE_H_
+
+#include <stdint.h>
+
+namespace android {
+
+class TimeSource {
+public:
+ TimeSource() {}
+ virtual ~TimeSource() {}
+
+ virtual int64_t getRealTimeUs() = 0;
+
+private:
+ TimeSource(const TimeSource &);
+ TimeSource &operator=(const TimeSource &);
+};
+
+class SystemTimeSource : public TimeSource {
+public:
+ SystemTimeSource();
+
+ virtual int64_t getRealTimeUs();
+
+private:
+ static int64_t GetSystemTimeUs();
+
+ int64_t mStartTimeUs;
+};
+
+} // namespace android
+
+#endif // TIME_SOURCE_H_
diff --git a/include/media/stagefright/Utils.h b/include/media/stagefright/Utils.h
new file mode 100644
index 0000000..498b525
--- /dev/null
+++ b/include/media/stagefright/Utils.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#ifndef UTILS_H_
+
+#define UTILS_H_
+
+#include <stdint.h>
+
+namespace android {
+
+#define FOURCC(c1, c2, c3, c4) \
+ (c1 << 24 | c2 << 16 | c3 << 8 | c4)
+
+uint16_t U16_AT(const uint8_t *ptr);
+uint32_t U32_AT(const uint8_t *ptr);
+uint64_t U64_AT(const uint8_t *ptr);
+
+uint16_t U16LE_AT(const uint8_t *ptr);
+uint32_t U32LE_AT(const uint8_t *ptr);
+uint64_t U64LE_AT(const uint8_t *ptr);
+
+uint64_t ntoh64(uint64_t x);
+uint64_t hton64(uint64_t x);
+
+} // namespace android
+
+#endif // UTILS_H_
diff --git a/include/media/stagefright/VideoSourceDownSampler.h b/include/media/stagefright/VideoSourceDownSampler.h
new file mode 100644
index 0000000..439918c
--- /dev/null
+++ b/include/media/stagefright/VideoSourceDownSampler.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.
+ */
+
+// VideoSourceDownSampler implements the MediaSource interface,
+// downsampling frames provided from a real video source.
+
+#ifndef VIDEO_SOURCE_DOWN_SAMPLER_H_
+
+#define VIDEO_SOURCE_DOWN_SAMPLER_H_
+
+#include <media/stagefright/MediaSource.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class IMemory;
+class MediaBuffer;
+class MetaData;
+
+class VideoSourceDownSampler : public MediaSource {
+public:
+ virtual ~VideoSourceDownSampler();
+
+ // Constructor:
+ // videoSource: The real video source which provides the original frames.
+ // width, height: The desired width, height. These should be less than or equal
+ // to those of the real video source. We then downsample the original frames to
+ // this size.
+ VideoSourceDownSampler(const sp<MediaSource> &videoSource,
+ int32_t width, int32_t height);
+
+ // MediaSource interface
+ 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);
+
+ virtual status_t pause();
+
+private:
+ // Reference to the real video source.
+ sp<MediaSource> mRealVideoSource;
+
+ // Size of frames to be provided by this source.
+ int32_t mWidth;
+ int32_t mHeight;
+
+ // Size of frames provided by the real source.
+ int32_t mRealSourceWidth;
+ int32_t mRealSourceHeight;
+
+ // Down sampling paramters.
+ int32_t mDownSampleOffsetX;
+ int32_t mDownSampleOffsetY;
+ int32_t mDownSampleSkipX;
+ int32_t mDownSampleSkipY;
+
+ // True if we need to crop the still video image to get the video frame.
+ bool mNeedDownSampling;
+
+ // Meta data. This is a copy of the real source except for the width and
+ // height parameters.
+ sp<MetaData> mMeta;
+
+ // Computes the offset, skip parameters for downsampling the original frame
+ // to the desired size.
+ void computeDownSamplingParameters();
+
+ // Downsamples the frame in sourceBuffer to size (mWidth x mHeight). A new
+ // buffer is created which stores the downsampled image.
+ void downSampleYUVImage(const MediaBuffer &sourceBuffer, MediaBuffer **buffer) const;
+
+ // Disallow these.
+ VideoSourceDownSampler(const VideoSourceDownSampler &);
+ VideoSourceDownSampler &operator=(const VideoSourceDownSampler &);
+};
+
+} // namespace android
+
+#endif // VIDEO_SOURCE_DOWN_SAMPLER_H_
diff --git a/include/media/stagefright/YUVCanvas.h b/include/media/stagefright/YUVCanvas.h
new file mode 100644
index 0000000..ff70923
--- /dev/null
+++ b/include/media/stagefright/YUVCanvas.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+// YUVCanvas holds a reference to a YUVImage on which it can do various
+// drawing operations. It provides various utility functions for filling,
+// cropping, etc.
+
+
+#ifndef YUV_CANVAS_H_
+
+#define YUV_CANVAS_H_
+
+#include <stdint.h>
+
+namespace android {
+
+class YUVImage;
+class Rect;
+
+class YUVCanvas {
+public:
+
+ // Constructor takes in reference to a yuvImage on which it can do
+ // various drawing opreations.
+ YUVCanvas(YUVImage &yuvImage);
+ ~YUVCanvas();
+
+ // Fills the entire image with the given YUV values.
+ void FillYUV(uint8_t yValue, uint8_t uValue, uint8_t vValue);
+
+ // Fills the rectangular region [startX,endX]x[startY,endY] with the given YUV values.
+ void FillYUVRectangle(const Rect& rect,
+ uint8_t yValue, uint8_t uValue, uint8_t vValue);
+
+ // Copies the region [startX,endX]x[startY,endY] from srcImage into the
+ // canvas' target image (mYUVImage) starting at
+ // (destinationStartX,destinationStartY).
+ // Note that undefined behavior may occur if srcImage is same as the canvas'
+ // target image.
+ void CopyImageRect(
+ const Rect& srcRect,
+ int32_t destStartX, int32_t destStartY,
+ const YUVImage &srcImage);
+
+ // Downsamples the srcImage into the canvas' target image (mYUVImage)
+ // The downsampling copies pixels from the source image starting at
+ // (srcOffsetX, srcOffsetY) to the target image, starting at (0, 0).
+ // For each X increment in the target image, skipX pixels are skipped
+ // in the source image.
+ // Similarly for each Y increment in the target image, skipY pixels
+ // are skipped in the source image.
+ void downsample(
+ int32_t srcOffsetX, int32_t srcOffsetY,
+ int32_t skipX, int32_t skipY,
+ const YUVImage &srcImage);
+
+private:
+ YUVImage& mYUVImage;
+
+ YUVCanvas(const YUVCanvas &);
+ YUVCanvas &operator=(const YUVCanvas &);
+};
+
+} // namespace android
+
+#endif // YUV_CANVAS_H_
diff --git a/include/media/stagefright/YUVImage.h b/include/media/stagefright/YUVImage.h
new file mode 100644
index 0000000..4e98618
--- /dev/null
+++ b/include/media/stagefright/YUVImage.h
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+// A container class to hold YUV data and provide various utilities,
+// e.g. to set/get pixel values.
+// Supported formats:
+// - YUV420 Planar
+// - YUV420 Semi Planar
+//
+// Currently does not support variable strides.
+//
+// Implementation: Two simple abstractions are done to simplify access
+// to YUV channels for different formats:
+// - initializeYUVPointers() sets up pointers (mYdata, mUdata, mVdata) to
+// point to the right start locations of the different channel data depending
+// on the format.
+// - getOffsets() returns the correct offset for the different channels
+// depending on the format.
+// Location of any pixel's YUV channels can then be easily computed using these.
+//
+
+#ifndef YUV_IMAGE_H_
+
+#define YUV_IMAGE_H_
+
+#include <stdint.h>
+#include <cstring>
+
+namespace android {
+
+class Rect;
+
+class YUVImage {
+public:
+ // Supported YUV formats
+ enum YUVFormat {
+ YUV420Planar,
+ YUV420SemiPlanar
+ };
+
+ // Constructs an image with the given size, format. Also allocates and owns
+ // the required memory.
+ YUVImage(YUVFormat yuvFormat, int32_t width, int32_t height);
+
+ // Constructs an image with the given size, format. The memory is provided
+ // by the caller and we don't own it.
+ YUVImage(YUVFormat yuvFormat, int32_t width, int32_t height, uint8_t *buffer);
+
+ // Destructor to delete the memory if it owns it.
+ ~YUVImage();
+
+ // Returns the size of the buffer required to store the YUV data for the given
+ // format and geometry. Useful when the caller wants to allocate the requisite
+ // memory.
+ static size_t bufferSize(YUVFormat yuvFormat, int32_t width, int32_t height);
+
+ int32_t width() const {return mWidth;}
+ int32_t height() const {return mHeight;}
+
+ // Returns true if pixel is the range [0, width-1] x [0, height-1]
+ // and false otherwise.
+ bool validPixel(int32_t x, int32_t y) const;
+
+ // Get the pixel YUV value at pixel (x,y).
+ // Note that the range of x is [0, width-1] and the range of y is [0, height-1].
+ // Returns true if get was successful and false otherwise.
+ bool getPixelValue(int32_t x, int32_t y,
+ uint8_t *yPtr, uint8_t *uPtr, uint8_t *vPtr) const;
+
+ // Set the pixel YUV value at pixel (x,y).
+ // Note that the range of x is [0, width-1] and the range of y is [0, height-1].
+ // Returns true if set was successful and false otherwise.
+ bool setPixelValue(int32_t x, int32_t y,
+ uint8_t yValue, uint8_t uValue, uint8_t vValue);
+
+ // Uses memcpy to copy an entire row of data
+ static void fastCopyRectangle420Planar(
+ const Rect& srcRect,
+ int32_t destStartX, int32_t destStartY,
+ const YUVImage &srcImage, YUVImage &destImage);
+
+ // Uses memcpy to copy an entire row of data
+ static void fastCopyRectangle420SemiPlanar(
+ const Rect& srcRect,
+ int32_t destStartX, int32_t destStartY,
+ const YUVImage &srcImage, YUVImage &destImage);
+
+ // Tries to use memcopy to copy entire rows of data.
+ // Returns false if fast copy is not possible for the passed image formats.
+ static bool fastCopyRectangle(
+ const Rect& srcRect,
+ int32_t destStartX, int32_t destStartY,
+ const YUVImage &srcImage, YUVImage &destImage);
+
+ // Convert the given YUV value to RGB.
+ void yuv2rgb(uint8_t yValue, uint8_t uValue, uint8_t vValue,
+ uint8_t *r, uint8_t *g, uint8_t *b) const;
+
+ // Write the image to a human readable PPM file.
+ // Returns true if write was succesful and false otherwise.
+ bool writeToPPM(const char *filename) const;
+
+private:
+ // YUV Format of the image.
+ YUVFormat mYUVFormat;
+
+ int32_t mWidth;
+ int32_t mHeight;
+
+ // Pointer to the memory buffer.
+ uint8_t *mBuffer;
+
+ // Boolean telling whether we own the memory buffer.
+ bool mOwnBuffer;
+
+ // Pointer to start of the Y data plane.
+ uint8_t *mYdata;
+
+ // Pointer to start of the U data plane. Note that in case of interleaved formats like
+ // YUV420 semiplanar, mUdata points to the start of the U data in the UV plane.
+ uint8_t *mUdata;
+
+ // Pointer to start of the V data plane. Note that in case of interleaved formats like
+ // YUV420 semiplanar, mVdata points to the start of the V data in the UV plane.
+ uint8_t *mVdata;
+
+ // Initialize the pointers mYdata, mUdata, mVdata to point to the right locations for
+ // the given format and geometry.
+ // Returns true if initialize was succesful and false otherwise.
+ bool initializeYUVPointers();
+
+ // For the given pixel location, this returns the offset of the location of y, u and v
+ // data from the corresponding base pointers -- mYdata, mUdata, mVdata.
+ // Note that the range of x is [0, width-1] and the range of y is [0, height-1].
+ // Returns true if getting offsets was succesful and false otherwise.
+ bool getOffsets(int32_t x, int32_t y,
+ int32_t *yOffset, int32_t *uOffset, int32_t *vOffset) const;
+
+ // Returns the offset increments incurred in going from one data row to the next data row
+ // for the YUV channels. Note that this corresponds to data rows and not pixel rows.
+ // E.g. depending on formats, U/V channels may have only one data row corresponding
+ // to two pixel rows.
+ bool getOffsetIncrementsPerDataRow(
+ int32_t *yDataOffsetIncrement,
+ int32_t *uDataOffsetIncrement,
+ int32_t *vDataOffsetIncrement) const;
+
+ // Given the offset return the address of the corresponding channel's data.
+ uint8_t* getYAddress(int32_t offset) const;
+ uint8_t* getUAddress(int32_t offset) const;
+ uint8_t* getVAddress(int32_t offset) const;
+
+ // Given the pixel location, returns the address of the corresponding channel's data.
+ // Note that the range of x is [0, width-1] and the range of y is [0, height-1].
+ bool getYUVAddresses(int32_t x, int32_t y,
+ uint8_t **yAddr, uint8_t **uAddr, uint8_t **vAddr) const;
+
+ // Disallow implicit casting and copying.
+ YUVImage(const YUVImage &);
+ YUVImage &operator=(const YUVImage &);
+};
+
+} // namespace android
+
+#endif // YUV_IMAGE_H_
diff --git a/include/media/stagefright/foundation/AAtomizer.h b/include/media/stagefright/foundation/AAtomizer.h
new file mode 100644
index 0000000..5f3a678
--- /dev/null
+++ b/include/media/stagefright/foundation/AAtomizer.h
@@ -0,0 +1,51 @@
+/*
+ * 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_ATOMIZER_H_
+
+#define A_ATOMIZER_H_
+
+#include <stdint.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AString.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct AAtomizer {
+ static const char *Atomize(const char *name);
+
+private:
+ static AAtomizer gAtomizer;
+
+ Mutex mLock;
+ Vector<List<AString> > mAtoms;
+
+ AAtomizer();
+
+ const char *atomize(const char *name);
+
+ static uint32_t Hash(const char *s);
+
+ DISALLOW_EVIL_CONSTRUCTORS(AAtomizer);
+};
+
+} // namespace android
+
+#endif // A_ATOMIZER_H_
diff --git a/include/media/stagefright/foundation/ABase.h b/include/media/stagefright/foundation/ABase.h
new file mode 100644
index 0000000..9eceea3
--- /dev/null
+++ b/include/media/stagefright/foundation/ABase.h
@@ -0,0 +1,25 @@
+/*
+ * 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_BASE_H_
+
+#define A_BASE_H_
+
+#define DISALLOW_EVIL_CONSTRUCTORS(name) \
+ name(const name &); \
+ name &operator=(const name &)
+
+#endif // A_BASE_H_
diff --git a/include/media/stagefright/foundation/ABitReader.h b/include/media/stagefright/foundation/ABitReader.h
new file mode 100644
index 0000000..5510b12
--- /dev/null
+++ b/include/media/stagefright/foundation/ABitReader.h
@@ -0,0 +1,54 @@
+/*
+ * 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);
+
+ void putBits(uint32_t x, 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();
+
+ DISALLOW_EVIL_CONSTRUCTORS(ABitReader);
+};
+
+} // namespace android
+
+#endif // A_BIT_READER_H_
diff --git a/include/media/stagefright/foundation/ABuffer.h b/include/media/stagefright/foundation/ABuffer.h
new file mode 100644
index 0000000..28f0aed
--- /dev/null
+++ b/include/media/stagefright/foundation/ABuffer.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 A_BUFFER_H_
+
+#define A_BUFFER_H_
+
+#include <sys/types.h>
+#include <stdint.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct AMessage;
+
+struct ABuffer : public RefBase {
+ ABuffer(size_t capacity);
+ ABuffer(void *data, size_t capacity);
+
+ void setFarewellMessage(const sp<AMessage> msg);
+
+ uint8_t *base() { return (uint8_t *)mData; }
+ uint8_t *data() { return (uint8_t *)mData + mRangeOffset; }
+ size_t capacity() const { return mCapacity; }
+ size_t size() const { return mRangeLength; }
+ size_t offset() const { return mRangeOffset; }
+
+ void setRange(size_t offset, size_t size);
+
+ void setInt32Data(int32_t data) { mInt32Data = data; }
+ int32_t int32Data() const { return mInt32Data; }
+
+ sp<AMessage> meta();
+
+protected:
+ virtual ~ABuffer();
+
+private:
+ sp<AMessage> mFarewell;
+ sp<AMessage> mMeta;
+
+ void *mData;
+ size_t mCapacity;
+ size_t mRangeOffset;
+ size_t mRangeLength;
+
+ int32_t mInt32Data;
+
+ bool mOwnsData;
+
+ DISALLOW_EVIL_CONSTRUCTORS(ABuffer);
+};
+
+} // namespace android
+
+#endif // A_BUFFER_H_
diff --git a/include/media/stagefright/foundation/ADebug.h b/include/media/stagefright/foundation/ADebug.h
new file mode 100644
index 0000000..450dcfe
--- /dev/null
+++ b/include/media/stagefright/foundation/ADebug.h
@@ -0,0 +1,86 @@
+/*
+ * 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_DEBUG_H_
+
+#define A_DEBUG_H_
+
+#include <string.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AString.h>
+#include <utils/Log.h>
+
+namespace android {
+
+#define LITERAL_TO_STRING_INTERNAL(x) #x
+#define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x)
+
+#define CHECK(condition) \
+ LOG_ALWAYS_FATAL_IF( \
+ !(condition), \
+ "%s", \
+ __FILE__ ":" LITERAL_TO_STRING(__LINE__) \
+ " CHECK(" #condition ") failed.")
+
+#define MAKE_COMPARATOR(suffix,op) \
+ template<class A, class B> \
+ AString Compare_##suffix(const A &a, const B &b) { \
+ AString res; \
+ if (!(a op b)) { \
+ res.append(a); \
+ res.append(" vs. "); \
+ res.append(b); \
+ } \
+ return res; \
+ }
+
+MAKE_COMPARATOR(EQ,==)
+MAKE_COMPARATOR(NE,!=)
+MAKE_COMPARATOR(LE,<=)
+MAKE_COMPARATOR(GE,>=)
+MAKE_COMPARATOR(LT,<)
+MAKE_COMPARATOR(GT,>)
+
+#define CHECK_OP(x,y,suffix,op) \
+ do { \
+ AString ___res = Compare_##suffix(x, y); \
+ if (!___res.empty()) { \
+ AString ___full = \
+ __FILE__ ":" LITERAL_TO_STRING(__LINE__) \
+ " CHECK_" #suffix "( " #x "," #y ") failed: "; \
+ ___full.append(___res); \
+ \
+ LOG_ALWAYS_FATAL("%s", ___full.c_str()); \
+ } \
+ } while (false)
+
+#define CHECK_EQ(x,y) CHECK_OP(x,y,EQ,==)
+#define CHECK_NE(x,y) CHECK_OP(x,y,NE,!=)
+#define CHECK_LE(x,y) CHECK_OP(x,y,LE,<=)
+#define CHECK_LT(x,y) CHECK_OP(x,y,LT,<)
+#define CHECK_GE(x,y) CHECK_OP(x,y,GE,>=)
+#define CHECK_GT(x,y) CHECK_OP(x,y,GT,>)
+
+#define TRESPASS() \
+ LOG_ALWAYS_FATAL( \
+ __FILE__ ":" LITERAL_TO_STRING(__LINE__) \
+ " Should not be here.");
+
+} // namespace android
+
+#endif // A_DEBUG_H_
+
diff --git a/include/media/stagefright/foundation/AHandler.h b/include/media/stagefright/foundation/AHandler.h
new file mode 100644
index 0000000..b008b54
--- /dev/null
+++ b/include/media/stagefright/foundation/AHandler.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_HANDLER_H_
+
+#define A_HANDLER_H_
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct AMessage;
+
+struct AHandler : public RefBase {
+ AHandler()
+ : mID(0) {
+ }
+
+ ALooper::handler_id id() const {
+ return mID;
+ }
+
+ sp<ALooper> looper();
+
+protected:
+ virtual void onMessageReceived(const sp<AMessage> &msg) = 0;
+
+private:
+ friend struct ALooperRoster;
+
+ ALooper::handler_id mID;
+
+ void setID(ALooper::handler_id id) {
+ mID = id;
+ }
+
+ DISALLOW_EVIL_CONSTRUCTORS(AHandler);
+};
+
+} // namespace android
+
+#endif // A_HANDLER_H_
diff --git a/include/media/stagefright/foundation/AHandlerReflector.h b/include/media/stagefright/foundation/AHandlerReflector.h
new file mode 100644
index 0000000..9d201b5
--- /dev/null
+++ b/include/media/stagefright/foundation/AHandlerReflector.h
@@ -0,0 +1,48 @@
+/*
+ * 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_HANDLER_REFLECTOR_H_
+
+#define A_HANDLER_REFLECTOR_H_
+
+#include <media/stagefright/foundation/AHandler.h>
+
+namespace android {
+
+template<class T>
+struct AHandlerReflector : public AHandler {
+ AHandlerReflector(T *target)
+ : mTarget(target) {
+ }
+
+protected:
+ virtual void onMessageReceived(const sp<AMessage> &msg) {
+ sp<T> target = mTarget.promote();
+ if (target != NULL) {
+ target->onMessageReceived(msg);
+ }
+ }
+
+private:
+ wp<T> mTarget;
+
+ AHandlerReflector(const AHandlerReflector<T> &);
+ AHandlerReflector<T> &operator=(const AHandlerReflector<T> &);
+};
+
+} // namespace android
+
+#endif // A_HANDLER_REFLECTOR_H_
diff --git a/include/media/stagefright/foundation/AHierarchicalStateMachine.h b/include/media/stagefright/foundation/AHierarchicalStateMachine.h
new file mode 100644
index 0000000..d2e6b28
--- /dev/null
+++ b/include/media/stagefright/foundation/AHierarchicalStateMachine.h
@@ -0,0 +1,65 @@
+/*
+ * 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_HIERARCHICAL_STATE_MACHINE_H_
+
+#define A_HIERARCHICAL_STATE_MACHINE_H_
+
+#include <media/stagefright/foundation/AHandler.h>
+
+namespace android {
+
+struct AState : public RefBase {
+ AState(const sp<AState> &parentState = NULL);
+
+ sp<AState> parentState();
+
+protected:
+ virtual ~AState();
+
+ virtual void stateEntered();
+ virtual void stateExited();
+
+ virtual bool onMessageReceived(const sp<AMessage> &msg) = 0;
+
+private:
+ friend struct AHierarchicalStateMachine;
+
+ sp<AState> mParentState;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AState);
+};
+
+struct AHierarchicalStateMachine : public AHandler {
+ AHierarchicalStateMachine();
+
+protected:
+ virtual ~AHierarchicalStateMachine();
+
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+ // Only to be called in response to a message.
+ void changeState(const sp<AState> &state);
+
+private:
+ sp<AState> mState;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AHierarchicalStateMachine);
+};
+
+} // namespace android
+
+#endif // A_HIERARCHICAL_STATE_MACHINE_H_
diff --git a/include/media/stagefright/foundation/ALooper.h b/include/media/stagefright/foundation/ALooper.h
new file mode 100644
index 0000000..70e0c5e
--- /dev/null
+++ b/include/media/stagefright/foundation/ALooper.h
@@ -0,0 +1,86 @@
+/*
+ * 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_LOOPER_H_
+
+#define A_LOOPER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AString.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/List.h>
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct AHandler;
+struct AMessage;
+
+struct ALooper : public RefBase {
+ typedef int32_t event_id;
+ typedef int32_t handler_id;
+
+ ALooper();
+
+ // Takes effect in a subsequent call to start().
+ void setName(const char *name);
+
+ handler_id registerHandler(const sp<AHandler> &handler);
+ void unregisterHandler(handler_id handlerID);
+
+ status_t start(
+ bool runOnCallingThread = false,
+ bool canCallJava = false,
+ int32_t priority = PRIORITY_DEFAULT
+ );
+
+ status_t stop();
+
+ static int64_t GetNowUs();
+
+protected:
+ virtual ~ALooper();
+
+private:
+ friend struct ALooperRoster;
+
+ struct Event {
+ int64_t mWhenUs;
+ sp<AMessage> mMessage;
+ };
+
+ Mutex mLock;
+ Condition mQueueChangedCondition;
+
+ AString mName;
+
+ List<Event> mEventQueue;
+
+ struct LooperThread;
+ sp<LooperThread> mThread;
+ bool mRunningLocally;
+
+ void post(const sp<AMessage> &msg, int64_t delayUs);
+ bool loop();
+
+ DISALLOW_EVIL_CONSTRUCTORS(ALooper);
+};
+
+} // namespace android
+
+#endif // A_LOOPER_H_
diff --git a/include/media/stagefright/foundation/ALooperRoster.h b/include/media/stagefright/foundation/ALooperRoster.h
new file mode 100644
index 0000000..2e5fd73
--- /dev/null
+++ b/include/media/stagefright/foundation/ALooperRoster.h
@@ -0,0 +1,65 @@
+/*
+ * 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_LOOPER_ROSTER_H_
+
+#define A_LOOPER_ROSTER_H_
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+struct ALooperRoster {
+ ALooperRoster();
+
+ ALooper::handler_id registerHandler(
+ const sp<ALooper> looper, const sp<AHandler> &handler);
+
+ void unregisterHandler(ALooper::handler_id handlerID);
+
+ status_t postMessage(const sp<AMessage> &msg, int64_t delayUs = 0);
+ void deliverMessage(const sp<AMessage> &msg);
+
+ status_t postAndAwaitResponse(
+ const sp<AMessage> &msg, sp<AMessage> *response);
+
+ void postReply(uint32_t replyID, const sp<AMessage> &reply);
+
+ sp<ALooper> findLooper(ALooper::handler_id handlerID);
+
+private:
+ struct HandlerInfo {
+ wp<ALooper> mLooper;
+ wp<AHandler> mHandler;
+ };
+
+ Mutex mLock;
+ KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers;
+ ALooper::handler_id mNextHandlerID;
+ uint32_t mNextReplyID;
+ Condition mRepliesCondition;
+
+ KeyedVector<uint32_t, sp<AMessage> > mReplies;
+
+ status_t postMessage_l(const sp<AMessage> &msg, int64_t delayUs);
+
+ DISALLOW_EVIL_CONSTRUCTORS(ALooperRoster);
+};
+
+} // namespace android
+
+#endif // A_LOOPER_ROSTER_H_
diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h
new file mode 100644
index 0000000..e5416e4
--- /dev/null
+++ b/include/media/stagefright/foundation/AMessage.h
@@ -0,0 +1,158 @@
+/*
+ * 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_MESSAGE_H_
+
+#define A_MESSAGE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABuffer;
+struct AString;
+struct Parcel;
+
+struct AMessage : public RefBase {
+ AMessage(uint32_t what = 0, ALooper::handler_id target = 0);
+
+ static sp<AMessage> FromParcel(const Parcel &parcel);
+ void writeToParcel(Parcel *parcel) const;
+
+ void setWhat(uint32_t what);
+ uint32_t what() const;
+
+ void setTarget(ALooper::handler_id target);
+ ALooper::handler_id target() const;
+
+ void clear();
+
+ void setInt32(const char *name, int32_t value);
+ void setInt64(const char *name, int64_t value);
+ void setSize(const char *name, size_t value);
+ void setFloat(const char *name, float value);
+ void setDouble(const char *name, double value);
+ void setPointer(const char *name, void *value);
+ void setString(const char *name, const char *s, ssize_t len = -1);
+ void setObject(const char *name, const sp<RefBase> &obj);
+ void setBuffer(const char *name, const sp<ABuffer> &buffer);
+ void setMessage(const char *name, const sp<AMessage> &obj);
+
+ void setRect(
+ const char *name,
+ int32_t left, int32_t top, int32_t right, int32_t bottom);
+
+ bool findInt32(const char *name, int32_t *value) const;
+ bool findInt64(const char *name, int64_t *value) const;
+ bool findSize(const char *name, size_t *value) const;
+ bool findFloat(const char *name, float *value) const;
+ bool findDouble(const char *name, double *value) const;
+ bool findPointer(const char *name, void **value) const;
+ bool findString(const char *name, AString *value) const;
+ bool findObject(const char *name, sp<RefBase> *obj) const;
+ bool findBuffer(const char *name, sp<ABuffer> *buffer) const;
+ bool findMessage(const char *name, sp<AMessage> *obj) const;
+
+ bool findRect(
+ const char *name,
+ int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const;
+
+ void post(int64_t delayUs = 0);
+
+ // Posts the message to its target and waits for a response (or error)
+ // before returning.
+ status_t postAndAwaitResponse(sp<AMessage> *response);
+
+ // If this returns true, the sender of this message is synchronously
+ // awaiting a response, the "replyID" can be used to send the response
+ // via "postReply" below.
+ bool senderAwaitsResponse(uint32_t *replyID) const;
+
+ void postReply(uint32_t replyID);
+
+ // Performs a deep-copy of "this", contained messages are in turn "dup'ed".
+ // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
+ // their refcount incremented.
+ sp<AMessage> dup() const;
+
+ AString debugString(int32_t indent = 0) const;
+
+ enum Type {
+ kTypeInt32,
+ kTypeInt64,
+ kTypeSize,
+ kTypeFloat,
+ kTypeDouble,
+ kTypePointer,
+ kTypeString,
+ kTypeObject,
+ kTypeMessage,
+ kTypeRect,
+ kTypeBuffer,
+ };
+
+ size_t countEntries() const;
+ const char *getEntryNameAt(size_t index, Type *type) const;
+
+protected:
+ virtual ~AMessage();
+
+private:
+ uint32_t mWhat;
+ ALooper::handler_id mTarget;
+
+ struct Rect {
+ int32_t mLeft, mTop, mRight, mBottom;
+ };
+
+ struct Item {
+ union {
+ int32_t int32Value;
+ int64_t int64Value;
+ size_t sizeValue;
+ float floatValue;
+ double doubleValue;
+ void *ptrValue;
+ RefBase *refValue;
+ AString *stringValue;
+ Rect rectValue;
+ } u;
+ const char *mName;
+ Type mType;
+ };
+
+ enum {
+ kMaxNumItems = 32
+ };
+ Item mItems[kMaxNumItems];
+ size_t mNumItems;
+
+ Item *allocateItem(const char *name);
+ void freeItem(Item *item);
+ const Item *findItem(const char *name, Type type) const;
+
+ void setObjectInternal(
+ const char *name, const sp<RefBase> &obj, Type type);
+
+ DISALLOW_EVIL_CONSTRUCTORS(AMessage);
+};
+
+} // namespace android
+
+#endif // A_MESSAGE_H_
diff --git a/include/media/stagefright/foundation/AString.h b/include/media/stagefright/foundation/AString.h
new file mode 100644
index 0000000..0f8f1e1
--- /dev/null
+++ b/include/media/stagefright/foundation/AString.h
@@ -0,0 +1,95 @@
+/*
+ * 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_STRING_H_
+
+#define A_STRING_H_
+
+#include <sys/types.h>
+
+namespace android {
+
+struct AString {
+ AString();
+ AString(const char *s);
+ AString(const char *s, size_t size);
+ AString(const AString &from);
+ AString(const AString &from, size_t offset, size_t n);
+ ~AString();
+
+ AString &operator=(const AString &from);
+ void setTo(const char *s);
+ void setTo(const char *s, size_t size);
+ void setTo(const AString &from, size_t offset, size_t n);
+
+ size_t size() const;
+ const char *c_str() const;
+
+ bool empty() const;
+
+ void clear();
+ void trim();
+ void erase(size_t start, size_t n);
+
+ void append(char c) { append(&c, 1); }
+ void append(const char *s);
+ void append(const char *s, size_t size);
+ void append(const AString &from);
+ void append(const AString &from, size_t offset, size_t n);
+ void append(int x);
+ void append(unsigned x);
+ void append(long x);
+ void append(unsigned long x);
+ void append(long long x);
+ void append(unsigned long long x);
+ void append(float x);
+ void append(double x);
+ void append(void *x);
+
+ void insert(const AString &from, size_t insertionPos);
+ void insert(const char *from, size_t size, size_t insertionPos);
+
+ ssize_t find(const char *substring, size_t start = 0) const;
+
+ size_t hash() const;
+
+ bool operator==(const AString &other) const;
+ bool operator<(const AString &other) const;
+ bool operator>(const AString &other) const;
+
+ int compare(const AString &other) const;
+
+ bool startsWith(const char *prefix) const;
+ bool endsWith(const char *suffix) const;
+
+ void tolower();
+
+private:
+ static const char *kEmptyString;
+
+ char *mData;
+ size_t mSize;
+ size_t mAllocSize;
+
+ void makeMutable();
+};
+
+AString StringPrintf(const char *format, ...);
+
+} // namespace android
+
+#endif // A_STRING_H_
+
diff --git a/include/media/stagefright/foundation/base64.h b/include/media/stagefright/foundation/base64.h
new file mode 100644
index 0000000..e340b89
--- /dev/null
+++ b/include/media/stagefright/foundation/base64.h
@@ -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.
+ */
+
+#ifndef BASE_64_H_
+
+#define BASE_64_H_
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABuffer;
+struct AString;
+
+sp<ABuffer> decodeBase64(const AString &s);
+void encodeBase64(const void *data, size_t size, AString *out);
+
+} // namespace android
+
+#endif // BASE_64_H_
diff --git a/include/media/stagefright/foundation/hexdump.h b/include/media/stagefright/foundation/hexdump.h
new file mode 100644
index 0000000..f6083a9
--- /dev/null
+++ b/include/media/stagefright/foundation/hexdump.h
@@ -0,0 +1,29 @@
+/*
+ * 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 HEXDUMP_H_
+
+#define HEXDUMP_H_
+
+#include <sys/types.h>
+
+namespace android {
+
+void hexdump(const void *_data, size_t size);
+
+} // namespace android
+
+#endif // HEXDUMP_H_
diff --git a/include/media/stagefright/timedtext/TimedTextDriver.h b/include/media/stagefright/timedtext/TimedTextDriver.h
new file mode 100644
index 0000000..b9752df
--- /dev/null
+++ b/include/media/stagefright/timedtext/TimedTextDriver.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 TIMED_TEXT_DRIVER_H_
+#define TIMED_TEXT_DRIVER_H_
+
+#include <media/stagefright/foundation/ABase.h> // for DISALLOW_* macro
+#include <utils/Errors.h> // for status_t
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class ALooper;
+class MediaPlayerBase;
+class MediaSource;
+class Parcel;
+class TimedTextPlayer;
+class TimedTextSource;
+
+class TimedTextDriver {
+public:
+ TimedTextDriver(const wp<MediaPlayerBase> &listener);
+
+ ~TimedTextDriver();
+
+ status_t start();
+ status_t pause();
+ status_t selectTrack(int32_t index);
+ status_t unselectTrack(int32_t index);
+
+ status_t seekToAsync(int64_t timeUs);
+
+ status_t addInBandTextSource(const sp<MediaSource>& source);
+ status_t addOutOfBandTextSource(const char *uri, const char *mimeType);
+ // Caller owns the file desriptor and caller is responsible for closing it.
+ status_t addOutOfBandTextSource(
+ int fd, off64_t offset, size_t length, const char *mimeType);
+
+ void getTrackInfo(Parcel *parcel);
+
+private:
+ Mutex mLock;
+
+ enum State {
+ UNINITIALIZED,
+ PLAYING,
+ PAUSED,
+ };
+
+ sp<ALooper> mLooper;
+ sp<TimedTextPlayer> mPlayer;
+ wp<MediaPlayerBase> mListener;
+
+ // Variables to be guarded by mLock.
+ State mState;
+ int32_t mCurrentTrackIndex;
+ Vector<sp<TimedTextSource> > mTextSourceVector;
+ // -- End of variables to be guarded by mLock
+
+ status_t selectTrack_l(int32_t index);
+
+ DISALLOW_EVIL_CONSTRUCTORS(TimedTextDriver);
+};
+
+} // namespace android
+
+#endif // TIMED_TEXT_DRIVER_H_
diff --git a/include/private/README b/include/private/README
new file mode 100644
index 0000000..ee41492
--- /dev/null
+++ b/include/private/README
@@ -0,0 +1,4 @@
+This folder contains private include files.
+
+These include files are part of the private implementation details of
+various framework components. Use at your peril.
diff --git a/include/private/hwui/DrawGlInfo.h b/include/private/hwui/DrawGlInfo.h
new file mode 100644
index 0000000..abcf41d
--- /dev/null
+++ b/include/private/hwui/DrawGlInfo.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_HWUI_DRAW_GL_INFO_H
+#define ANDROID_HWUI_DRAW_GL_INFO_H
+
+namespace android {
+namespace uirenderer {
+
+/**
+ * Structure used by OpenGLRenderer::callDrawGLFunction() to pass and
+ * receive data from OpenGL functors.
+ */
+struct DrawGlInfo {
+ // Input: current clip rect
+ int clipLeft;
+ int clipTop;
+ int clipRight;
+ int clipBottom;
+
+ // Input: is the render target an FBO
+ bool isLayer;
+
+ // Input: current transform matrix, in OpenGL format
+ float transform[16];
+
+ // Output: dirty region to redraw
+ float dirtyLeft;
+ float dirtyTop;
+ float dirtyRight;
+ float dirtyBottom;
+
+ /**
+ * Values used by OpenGL functors to tell the framework
+ * what to do next.
+ */
+ enum Status {
+ // The functor is done
+ kStatusDone,
+ // The functor is requesting a redraw (the clip rect
+ // used by the redraw is specified by DrawGlInfo.)
+ // The rest of the UI might redraw too.
+ kStatusDraw,
+ // The functor needs to be invoked again but will
+ // not redraw. Only the functor is invoked again
+ // (unless another functor requests a redraw.)
+ kStatusInvoke
+ };
+}; // struct DrawGlInfo
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_DRAW_GL_INFO_H
diff --git a/include/private/media/AudioEffectShared.h b/include/private/media/AudioEffectShared.h
new file mode 100644
index 0000000..a3a99a4
--- /dev/null
+++ b/include/private/media/AudioEffectShared.h
@@ -0,0 +1,51 @@
+/*
+ * 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_EFFECTCBASESHARED_H
+#define ANDROID_EFFECTCBASESHARED_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// Size of buffer used to exchange parameters between application and mediaserver processes.
+#define EFFECT_PARAM_BUFFER_SIZE 1024
+
+
+// Shared memory area used to exchange parameters between application and mediaserver
+// process.
+struct effect_param_cblk_t
+{
+ Mutex lock;
+ volatile uint32_t clientIndex; // Current read/write index for application
+ volatile uint32_t serverIndex; // Current read/write index for mediaserver
+ uint8_t* buffer; // start of parameter buffer
+
+ effect_param_cblk_t()
+ : lock(Mutex::SHARED), clientIndex(0), serverIndex(0) {}
+};
+
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_EFFECTCBASESHARED_H
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
new file mode 100644
index 0000000..af2db93
--- /dev/null
+++ b/include/private/media/AudioTrackShared.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 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_TRACK_SHARED_H
+#define ANDROID_AUDIO_TRACK_SHARED_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// Maximum cumulated timeout milliseconds before restarting audioflinger thread
+#define MAX_STARTUP_TIMEOUT_MS 3000 // Longer timeout period at startup to cope with A2DP init time
+#define MAX_RUN_TIMEOUT_MS 1000
+#define WAIT_PERIOD_MS 10
+#define RESTORE_TIMEOUT_MS 5000 // Maximum waiting time for a track to be restored
+
+#define CBLK_UNDERRUN_MSK 0x0001
+#define CBLK_UNDERRUN_ON 0x0001 // underrun (out) or overrrun (in) indication
+#define CBLK_UNDERRUN_OFF 0x0000 // no underrun
+#define CBLK_DIRECTION_MSK 0x0002
+#define CBLK_DIRECTION_OUT 0x0002 // this cblk is for an AudioTrack
+#define CBLK_DIRECTION_IN 0x0000 // this cblk is for an AudioRecord
+#define CBLK_FORCEREADY_MSK 0x0004
+#define CBLK_FORCEREADY_ON 0x0004 // track is considered ready immediately by AudioFlinger
+#define CBLK_FORCEREADY_OFF 0x0000 // track is ready when buffer full
+#define CBLK_INVALID_MSK 0x0008
+#define CBLK_INVALID_ON 0x0008 // track buffer is invalidated by AudioFlinger:
+#define CBLK_INVALID_OFF 0x0000 // must be re-created
+#define CBLK_DISABLED_MSK 0x0010
+#define CBLK_DISABLED_ON 0x0010 // track disabled by AudioFlinger due to underrun:
+#define CBLK_DISABLED_OFF 0x0000 // must be re-started
+#define CBLK_RESTORING_MSK 0x0020
+#define CBLK_RESTORING_ON 0x0020 // track is being restored after invalidation
+#define CBLK_RESTORING_OFF 0x0000 // by AudioFlinger
+#define CBLK_RESTORED_MSK 0x0040
+#define CBLK_RESTORED_ON 0x0040 // track has been restored after invalidation
+#define CBLK_RESTORED_OFF 0x0040 // by AudioFlinger
+
+// Important: do not add any virtual methods, including ~
+struct audio_track_cblk_t
+{
+
+ // The data members are grouped so that members accessed frequently and in the same context
+ // are in the same line of data cache.
+ Mutex lock; // sizeof(int)
+ Condition cv; // sizeof(int)
+
+ // next 4 are offsets within "buffers"
+ volatile uint32_t user;
+ volatile uint32_t server;
+ uint32_t userBase;
+ uint32_t serverBase;
+
+ // if there is a shared buffer, "buffers" is the value of pointer() for the shared
+ // buffer, otherwise "buffers" points immediately after the control block
+ void* buffers;
+ uint32_t frameCount;
+
+ // Cache line boundary
+
+ uint32_t loopStart;
+ uint32_t loopEnd; // read-only for server, read/write for client
+ int loopCount; // read/write for client
+
+ // Channel volumes are fixed point U4.12, so 0x1000 means 1.0.
+ // Left channel is in [0:15], right channel is in [16:31].
+ // Always read and write the combined pair atomically.
+ // For AudioTrack only, not used by AudioRecord.
+private:
+ uint32_t mVolumeLR;
+public:
+
+ uint32_t sampleRate;
+
+ // NOTE: audio_track_cblk_t::frameSize is not equal to AudioTrack::frameSize() for
+ // 8 bit PCM data: in this case, mCblk->frameSize is based on a sample size of
+ // 16 bit because data is converted to 16 bit before being stored in buffer
+
+ // read-only for client, server writes once at initialization and is then read-only
+ uint8_t frameSize; // would normally be size_t, but 8 bits is plenty
+
+ // never used
+ uint8_t pad1;
+
+ // used by client only
+ uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
+
+ uint16_t waitTimeMs; // Cumulated wait time, used by client only
+private:
+ // client write-only, server read-only
+ uint16_t mSendLevel; // Fixed point U4.12 so 0x1000 means 1.0
+public:
+ volatile int32_t flags;
+
+ // Cache line boundary (32 bytes)
+
+ // Since the control block is always located in shared memory, this constructor
+ // is only used for placement new(). It is never used for regular new() or stack.
+ audio_track_cblk_t();
+ uint32_t stepUser(uint32_t frameCount); // called by client only, where
+ // client includes regular AudioTrack and AudioFlinger::PlaybackThread::OutputTrack
+ bool stepServer(uint32_t frameCount); // called by server only
+ void* buffer(uint32_t offset) const;
+ uint32_t framesAvailable();
+ uint32_t framesAvailable_l();
+ uint32_t framesReady(); // called by server only
+ bool tryLock();
+
+ // No barriers on the following operations, so the ordering of loads/stores
+ // with respect to other parameters is UNPREDICTABLE. That's considered safe.
+
+ // for AudioTrack client only, caller must limit to 0.0 <= sendLevel <= 1.0
+ void setSendLevel(float sendLevel) {
+ mSendLevel = uint16_t(sendLevel * 0x1000);
+ }
+
+ // for AudioFlinger only; the return value must be validated by the caller
+ uint16_t getSendLevel_U4_12() const {
+ return mSendLevel;
+ }
+
+ // for AudioTrack client only, caller must limit to 0 <= volumeLR <= 0x10001000
+ void setVolumeLR(uint32_t volumeLR) {
+ mVolumeLR = volumeLR;
+ }
+
+ // for AudioFlinger only; the return value must be validated by the caller
+ uint32_t getVolumeLR() const {
+ return mVolumeLR;
+ }
+
+};
+
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_AUDIO_TRACK_SHARED_H
diff --git a/include/private/media/VideoFrame.h b/include/private/media/VideoFrame.h
new file mode 100644
index 0000000..0ecc348
--- /dev/null
+++ b/include/private/media/VideoFrame.h
@@ -0,0 +1,128 @@
+/*
+**
+** 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_VIDEO_FRAME_H
+#define ANDROID_VIDEO_FRAME_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <utils/Log.h>
+
+namespace android {
+
+// A simple buffer to hold binary data
+class MediaAlbumArt
+{
+public:
+ MediaAlbumArt(): mSize(0), mData(0) {}
+
+ explicit MediaAlbumArt(const char* url) {
+ mSize = 0;
+ mData = NULL;
+ FILE *in = fopen(url, "r");
+ if (!in) {
+ return;
+ }
+ fseek(in, 0, SEEK_END);
+ mSize = ftell(in); // Allocating buffer of size equals to the external file size.
+ if (mSize == 0 || (mData = new uint8_t[mSize]) == NULL) {
+ fclose(in);
+ if (mSize != 0) {
+ mSize = 0;
+ }
+ return;
+ }
+ rewind(in);
+ if (fread(mData, 1, mSize, in) != mSize) { // Read failed.
+ delete[] mData;
+ mData = NULL;
+ mSize = 0;
+ return;
+ }
+ fclose(in);
+ }
+
+ MediaAlbumArt(const MediaAlbumArt& copy) {
+ mSize = copy.mSize;
+ mData = NULL; // initialize it first
+ if (mSize > 0 && copy.mData != NULL) {
+ mData = new uint8_t[copy.mSize];
+ if (mData != NULL) {
+ memcpy(mData, copy.mData, mSize);
+ } else {
+ mSize = 0;
+ }
+ }
+ }
+
+ ~MediaAlbumArt() {
+ if (mData != 0) {
+ delete[] mData;
+ }
+ }
+
+ // Intentional public access modifier:
+ // We have to know the internal structure in order to share it between
+ // processes?
+ uint32_t mSize; // Number of bytes in mData
+ uint8_t* mData; // Actual binary data
+};
+
+// Represents a color converted (RGB-based) video frame
+// with bitmap pixels stored in FrameBuffer
+class VideoFrame
+{
+public:
+ VideoFrame(): mWidth(0), mHeight(0), mDisplayWidth(0), mDisplayHeight(0), mSize(0), mData(0) {}
+
+ VideoFrame(const VideoFrame& copy) {
+ mWidth = copy.mWidth;
+ mHeight = copy.mHeight;
+ mDisplayWidth = copy.mDisplayWidth;
+ mDisplayHeight = copy.mDisplayHeight;
+ mSize = copy.mSize;
+ mData = NULL; // initialize it first
+ if (mSize > 0 && copy.mData != NULL) {
+ mData = new uint8_t[mSize];
+ if (mData != NULL) {
+ memcpy(mData, copy.mData, mSize);
+ } else {
+ mSize = 0;
+ }
+ }
+ }
+
+ ~VideoFrame() {
+ if (mData != 0) {
+ delete[] mData;
+ }
+ }
+
+ // Intentional public access modifier:
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint32_t mDisplayWidth;
+ uint32_t mDisplayHeight;
+ uint32_t mSize; // Number of bytes in mData
+ uint8_t* mData; // Actual binary data
+ int32_t mRotationAngle; // rotation angle, clockwise
+};
+
+}; // namespace android
+
+#endif // ANDROID_VIDEO_FRAME_H
diff --git a/media/common_time/Android.mk b/media/common_time/Android.mk
new file mode 100644
index 0000000..526f17b
--- /dev/null
+++ b/media/common_time/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH:= $(call my-dir)
+#
+# libcommon_time_client
+# (binder marshalers for ICommonClock as well as common clock and local clock
+# helper code)
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libcommon_time_client
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := cc_helper.cpp \
+ local_clock.cpp \
+ ICommonClock.cpp \
+ ICommonTimeConfig.cpp \
+ utils.cpp
+LOCAL_SHARED_LIBRARIES := libbinder \
+ libhardware \
+ libutils
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/common_time/ICommonClock.cpp b/media/common_time/ICommonClock.cpp
new file mode 100644
index 0000000..28b43ac
--- /dev/null
+++ b/media/common_time/ICommonClock.cpp
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <linux/socket.h>
+
+#include <common_time/ICommonClock.h>
+#include <binder/Parcel.h>
+
+#include "utils.h"
+
+namespace android {
+
+/***** ICommonClock *****/
+
+enum {
+ IS_COMMON_TIME_VALID = IBinder::FIRST_CALL_TRANSACTION,
+ COMMON_TIME_TO_LOCAL_TIME,
+ LOCAL_TIME_TO_COMMON_TIME,
+ GET_COMMON_TIME,
+ GET_COMMON_FREQ,
+ GET_LOCAL_TIME,
+ GET_LOCAL_FREQ,
+ GET_ESTIMATED_ERROR,
+ GET_TIMELINE_ID,
+ GET_STATE,
+ GET_MASTER_ADDRESS,
+ REGISTER_LISTENER,
+ UNREGISTER_LISTENER,
+};
+
+const String16 ICommonClock::kServiceName("common_time.clock");
+const uint64_t ICommonClock::kInvalidTimelineID = 0;
+const int32_t ICommonClock::kErrorEstimateUnknown = 0x7FFFFFFF;
+
+class BpCommonClock : public BpInterface<ICommonClock>
+{
+ public:
+ BpCommonClock(const sp<IBinder>& impl)
+ : BpInterface<ICommonClock>(impl) {}
+
+ virtual status_t isCommonTimeValid(bool* valid, uint32_t* timelineID) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+ status_t status = remote()->transact(IS_COMMON_TIME_VALID,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *valid = reply.readInt32();
+ *timelineID = reply.readInt32();
+ }
+ }
+ return status;
+ }
+
+ virtual status_t commonTimeToLocalTime(int64_t commonTime,
+ int64_t* localTime) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+ data.writeInt64(commonTime);
+ status_t status = remote()->transact(COMMON_TIME_TO_LOCAL_TIME,
+ data, &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *localTime = reply.readInt64();
+ }
+ }
+ return status;
+ }
+
+ virtual status_t localTimeToCommonTime(int64_t localTime,
+ int64_t* commonTime) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+ data.writeInt64(localTime);
+ status_t status = remote()->transact(LOCAL_TIME_TO_COMMON_TIME,
+ data, &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *commonTime = reply.readInt64();
+ }
+ }
+ return status;
+ }
+
+ virtual status_t getCommonTime(int64_t* commonTime) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_COMMON_TIME, data, &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *commonTime = reply.readInt64();
+ }
+ }
+ return status;
+ }
+
+ virtual status_t getCommonFreq(uint64_t* freq) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_COMMON_FREQ, data, &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *freq = reply.readInt64();
+ }
+ }
+ return status;
+ }
+
+ virtual status_t getLocalTime(int64_t* localTime) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_LOCAL_TIME, data, &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *localTime = reply.readInt64();
+ }
+ }
+ return status;
+ }
+
+ virtual status_t getLocalFreq(uint64_t* freq) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_LOCAL_FREQ, data, &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *freq = reply.readInt64();
+ }
+ }
+ return status;
+ }
+
+ virtual status_t getEstimatedError(int32_t* estimate) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_ESTIMATED_ERROR, data, &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *estimate = reply.readInt32();
+ }
+ }
+ return status;
+ }
+
+ virtual status_t getTimelineID(uint64_t* id) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_TIMELINE_ID, data, &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *id = static_cast<uint64_t>(reply.readInt64());
+ }
+ }
+ return status;
+ }
+
+ virtual status_t getState(State* state) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_STATE, data, &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *state = static_cast<State>(reply.readInt32());
+ }
+ }
+ return status;
+ }
+
+ virtual status_t getMasterAddr(struct sockaddr_storage* addr) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_MASTER_ADDRESS, data, &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK)
+ deserializeSockaddr(&reply, addr);
+ }
+ return status;
+ }
+
+ virtual status_t registerListener(
+ const sp<ICommonClockListener>& listener) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+ data.writeStrongBinder(listener->asBinder());
+
+ status_t status = remote()->transact(REGISTER_LISTENER, data, &reply);
+
+ if (status == OK) {
+ status = reply.readInt32();
+ }
+
+ return status;
+ }
+
+ virtual status_t unregisterListener(
+ const sp<ICommonClockListener>& listener) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonClock::getInterfaceDescriptor());
+ data.writeStrongBinder(listener->asBinder());
+ status_t status = remote()->transact(UNREGISTER_LISTENER, data, &reply);
+
+ if (status == OK) {
+ status = reply.readInt32();
+ }
+
+ return status;
+ }
+};
+
+IMPLEMENT_META_INTERFACE(CommonClock, "android.os.ICommonClock");
+
+status_t BnCommonClock::onTransact(uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags) {
+ switch(code) {
+ case IS_COMMON_TIME_VALID: {
+ CHECK_INTERFACE(ICommonClock, data, reply);
+ bool valid;
+ uint32_t timelineID;
+ status_t status = isCommonTimeValid(&valid, &timelineID);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt32(valid);
+ reply->writeInt32(timelineID);
+ }
+ return OK;
+ } break;
+
+ case COMMON_TIME_TO_LOCAL_TIME: {
+ CHECK_INTERFACE(ICommonClock, data, reply);
+ int64_t commonTime = data.readInt64();
+ int64_t localTime;
+ status_t status = commonTimeToLocalTime(commonTime, &localTime);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt64(localTime);
+ }
+ return OK;
+ } break;
+
+ case LOCAL_TIME_TO_COMMON_TIME: {
+ CHECK_INTERFACE(ICommonClock, data, reply);
+ int64_t localTime = data.readInt64();
+ int64_t commonTime;
+ status_t status = localTimeToCommonTime(localTime, &commonTime);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt64(commonTime);
+ }
+ return OK;
+ } break;
+
+ case GET_COMMON_TIME: {
+ CHECK_INTERFACE(ICommonClock, data, reply);
+ int64_t commonTime;
+ status_t status = getCommonTime(&commonTime);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt64(commonTime);
+ }
+ return OK;
+ } break;
+
+ case GET_COMMON_FREQ: {
+ CHECK_INTERFACE(ICommonClock, data, reply);
+ uint64_t freq;
+ status_t status = getCommonFreq(&freq);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt64(freq);
+ }
+ return OK;
+ } break;
+
+ case GET_LOCAL_TIME: {
+ CHECK_INTERFACE(ICommonClock, data, reply);
+ int64_t localTime;
+ status_t status = getLocalTime(&localTime);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt64(localTime);
+ }
+ return OK;
+ } break;
+
+ case GET_LOCAL_FREQ: {
+ CHECK_INTERFACE(ICommonClock, data, reply);
+ uint64_t freq;
+ status_t status = getLocalFreq(&freq);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt64(freq);
+ }
+ return OK;
+ } break;
+
+ case GET_ESTIMATED_ERROR: {
+ CHECK_INTERFACE(ICommonClock, data, reply);
+ int32_t error;
+ status_t status = getEstimatedError(&error);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt32(error);
+ }
+ return OK;
+ } break;
+
+ case GET_TIMELINE_ID: {
+ CHECK_INTERFACE(ICommonClock, data, reply);
+ uint64_t id;
+ status_t status = getTimelineID(&id);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt64(static_cast<int64_t>(id));
+ }
+ return OK;
+ } break;
+
+ case GET_STATE: {
+ CHECK_INTERFACE(ICommonClock, data, reply);
+ State state;
+ status_t status = getState(&state);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt32(static_cast<int32_t>(state));
+ }
+ return OK;
+ } break;
+
+ case GET_MASTER_ADDRESS: {
+ CHECK_INTERFACE(ICommonClock, data, reply);
+ struct sockaddr_storage addr;
+ status_t status = getMasterAddr(&addr);
+
+ if ((status == OK) && !canSerializeSockaddr(&addr)) {
+ status = UNKNOWN_ERROR;
+ }
+
+ reply->writeInt32(status);
+
+ if (status == OK) {
+ serializeSockaddr(reply, &addr);
+ }
+
+ return OK;
+ } break;
+
+ case REGISTER_LISTENER: {
+ CHECK_INTERFACE(ICommonClock, data, reply);
+ sp<ICommonClockListener> listener =
+ interface_cast<ICommonClockListener>(data.readStrongBinder());
+ status_t status = registerListener(listener);
+ reply->writeInt32(status);
+ return OK;
+ } break;
+
+ case UNREGISTER_LISTENER: {
+ CHECK_INTERFACE(ICommonClock, data, reply);
+ sp<ICommonClockListener> listener =
+ interface_cast<ICommonClockListener>(data.readStrongBinder());
+ status_t status = unregisterListener(listener);
+ reply->writeInt32(status);
+ return OK;
+ } break;
+ }
+ return BBinder::onTransact(code, data, reply, flags);
+}
+
+/***** ICommonClockListener *****/
+
+enum {
+ ON_TIMELINE_CHANGED = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpCommonClockListener : public BpInterface<ICommonClockListener>
+{
+ public:
+ BpCommonClockListener(const sp<IBinder>& impl)
+ : BpInterface<ICommonClockListener>(impl) {}
+
+ virtual void onTimelineChanged(uint64_t timelineID) {
+ Parcel data, reply;
+ data.writeInterfaceToken(
+ ICommonClockListener::getInterfaceDescriptor());
+ data.writeInt64(timelineID);
+ remote()->transact(ON_TIMELINE_CHANGED, data, &reply);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(CommonClockListener,
+ "android.os.ICommonClockListener");
+
+status_t BnCommonClockListener::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+ switch(code) {
+ case ON_TIMELINE_CHANGED: {
+ CHECK_INTERFACE(ICommonClockListener, data, reply);
+ uint32_t timelineID = data.readInt64();
+ onTimelineChanged(timelineID);
+ return NO_ERROR;
+ } break;
+ }
+
+ return BBinder::onTransact(code, data, reply, flags);
+}
+
+}; // namespace android
diff --git a/media/common_time/ICommonTimeConfig.cpp b/media/common_time/ICommonTimeConfig.cpp
new file mode 100644
index 0000000..8eb37cb
--- /dev/null
+++ b/media/common_time/ICommonTimeConfig.cpp
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <linux/socket.h>
+
+#include <common_time/ICommonTimeConfig.h>
+#include <binder/Parcel.h>
+
+#include "utils.h"
+
+namespace android {
+
+/***** ICommonTimeConfig *****/
+
+enum {
+ GET_MASTER_ELECTION_PRIORITY = IBinder::FIRST_CALL_TRANSACTION,
+ SET_MASTER_ELECTION_PRIORITY,
+ GET_MASTER_ELECTION_ENDPOINT,
+ SET_MASTER_ELECTION_ENDPOINT,
+ GET_MASTER_ELECTION_GROUP_ID,
+ SET_MASTER_ELECTION_GROUP_ID,
+ GET_INTERFACE_BINDING,
+ SET_INTERFACE_BINDING,
+ GET_MASTER_ANNOUNCE_INTERVAL,
+ SET_MASTER_ANNOUNCE_INTERVAL,
+ GET_CLIENT_SYNC_INTERVAL,
+ SET_CLIENT_SYNC_INTERVAL,
+ GET_PANIC_THRESHOLD,
+ SET_PANIC_THRESHOLD,
+ GET_AUTO_DISABLE,
+ SET_AUTO_DISABLE,
+ FORCE_NETWORKLESS_MASTER_MODE,
+};
+
+const String16 ICommonTimeConfig::kServiceName("common_time.config");
+
+class BpCommonTimeConfig : public BpInterface<ICommonTimeConfig>
+{
+ public:
+ BpCommonTimeConfig(const sp<IBinder>& impl)
+ : BpInterface<ICommonTimeConfig>(impl) {}
+
+ virtual status_t getMasterElectionPriority(uint8_t *priority) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_MASTER_ELECTION_PRIORITY,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *priority = static_cast<uint8_t>(reply.readInt32());
+ }
+ }
+
+ return status;
+ }
+
+ virtual status_t setMasterElectionPriority(uint8_t priority) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ data.writeInt32(static_cast<int32_t>(priority));
+ status_t status = remote()->transact(SET_MASTER_ELECTION_PRIORITY,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ }
+
+ return status;
+ }
+
+ virtual status_t getMasterElectionEndpoint(struct sockaddr_storage *addr) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_MASTER_ELECTION_ENDPOINT,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ deserializeSockaddr(&reply, addr);
+ }
+ }
+
+ return status;
+ }
+
+ virtual status_t setMasterElectionEndpoint(
+ const struct sockaddr_storage *addr) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ if (!canSerializeSockaddr(addr))
+ return BAD_VALUE;
+ if (NULL == addr) {
+ data.writeInt32(0);
+ } else {
+ data.writeInt32(1);
+ serializeSockaddr(&data, addr);
+ }
+ status_t status = remote()->transact(SET_MASTER_ELECTION_ENDPOINT,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ }
+
+ return status;
+ }
+
+ virtual status_t getMasterElectionGroupId(uint64_t *id) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_MASTER_ELECTION_GROUP_ID,
+ data,
+ &reply);
+
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *id = static_cast<uint64_t>(reply.readInt64());
+ }
+ }
+
+ return status;
+ }
+
+ virtual status_t setMasterElectionGroupId(uint64_t id) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ data.writeInt64(id);
+ status_t status = remote()->transact(SET_MASTER_ELECTION_GROUP_ID,
+ data,
+ &reply);
+
+ if (status == OK) {
+ status = reply.readInt32();
+ }
+
+ return status;
+ }
+
+ virtual status_t getInterfaceBinding(String16& ifaceName) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_INTERFACE_BINDING,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ ifaceName = reply.readString16();
+ }
+ }
+
+ return status;
+ }
+
+ virtual status_t setInterfaceBinding(const String16& ifaceName) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ data.writeString16(ifaceName);
+ status_t status = remote()->transact(SET_INTERFACE_BINDING,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ }
+
+ return status;
+ }
+
+ virtual status_t getMasterAnnounceInterval(int *interval) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_MASTER_ANNOUNCE_INTERVAL,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *interval = reply.readInt32();
+ }
+ }
+
+ return status;
+ }
+
+ virtual status_t setMasterAnnounceInterval(int interval) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ data.writeInt32(interval);
+ status_t status = remote()->transact(SET_MASTER_ANNOUNCE_INTERVAL,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ }
+
+ return status;
+ }
+
+ virtual status_t getClientSyncInterval(int *interval) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_CLIENT_SYNC_INTERVAL,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *interval = reply.readInt32();
+ }
+ }
+
+ return status;
+ }
+
+ virtual status_t setClientSyncInterval(int interval) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ data.writeInt32(interval);
+ status_t status = remote()->transact(SET_CLIENT_SYNC_INTERVAL,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ }
+
+ return status;
+ }
+
+ virtual status_t getPanicThreshold(int *threshold) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_PANIC_THRESHOLD,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *threshold = reply.readInt32();
+ }
+ }
+
+ return status;
+ }
+
+ virtual status_t setPanicThreshold(int threshold) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ data.writeInt32(threshold);
+ status_t status = remote()->transact(SET_PANIC_THRESHOLD,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ }
+
+ return status;
+ }
+
+ virtual status_t getAutoDisable(bool *autoDisable) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_AUTO_DISABLE,
+ data,
+ &reply);
+ if (status == OK) {
+ status = reply.readInt32();
+ if (status == OK) {
+ *autoDisable = (0 != reply.readInt32());
+ }
+ }
+
+ return status;
+ }
+
+ virtual status_t setAutoDisable(bool autoDisable) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ data.writeInt32(autoDisable ? 1 : 0);
+ status_t status = remote()->transact(SET_AUTO_DISABLE,
+ data,
+ &reply);
+
+ if (status == OK) {
+ status = reply.readInt32();
+ }
+
+ return status;
+ }
+
+ virtual status_t forceNetworklessMasterMode() {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICommonTimeConfig::getInterfaceDescriptor());
+ status_t status = remote()->transact(FORCE_NETWORKLESS_MASTER_MODE,
+ data,
+ &reply);
+
+ if (status == OK) {
+ status = reply.readInt32();
+ }
+
+ return status;
+ }
+};
+
+IMPLEMENT_META_INTERFACE(CommonTimeConfig, "android.os.ICommonTimeConfig");
+
+status_t BnCommonTimeConfig::onTransact(uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags) {
+ switch(code) {
+ case GET_MASTER_ELECTION_PRIORITY: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ uint8_t priority;
+ status_t status = getMasterElectionPriority(&priority);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt32(static_cast<int32_t>(priority));
+ }
+ return OK;
+ } break;
+
+ case SET_MASTER_ELECTION_PRIORITY: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ uint8_t priority = static_cast<uint8_t>(data.readInt32());
+ status_t status = setMasterElectionPriority(priority);
+ reply->writeInt32(status);
+ return OK;
+ } break;
+
+ case GET_MASTER_ELECTION_ENDPOINT: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ struct sockaddr_storage addr;
+ status_t status = getMasterElectionEndpoint(&addr);
+
+ if ((status == OK) && !canSerializeSockaddr(&addr)) {
+ status = UNKNOWN_ERROR;
+ }
+
+ reply->writeInt32(status);
+
+ if (status == OK) {
+ serializeSockaddr(reply, &addr);
+ }
+
+ return OK;
+ } break;
+
+ case SET_MASTER_ELECTION_ENDPOINT: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ struct sockaddr_storage addr;
+ int hasAddr = data.readInt32();
+
+ status_t status;
+ if (hasAddr) {
+ deserializeSockaddr(&data, &addr);
+ status = setMasterElectionEndpoint(&addr);
+ } else {
+ status = setMasterElectionEndpoint(&addr);
+ }
+
+ reply->writeInt32(status);
+ return OK;
+ } break;
+
+ case GET_MASTER_ELECTION_GROUP_ID: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ uint64_t id;
+ status_t status = getMasterElectionGroupId(&id);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt64(id);
+ }
+ return OK;
+ } break;
+
+ case SET_MASTER_ELECTION_GROUP_ID: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ uint64_t id = static_cast<uint64_t>(data.readInt64());
+ status_t status = setMasterElectionGroupId(id);
+ reply->writeInt32(status);
+ return OK;
+ } break;
+
+ case GET_INTERFACE_BINDING: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ String16 ret;
+ status_t status = getInterfaceBinding(ret);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeString16(ret);
+ }
+ return OK;
+ } break;
+
+ case SET_INTERFACE_BINDING: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ String16 ifaceName;
+ ifaceName = data.readString16();
+ status_t status = setInterfaceBinding(ifaceName);
+ reply->writeInt32(status);
+ return OK;
+ } break;
+
+ case GET_MASTER_ANNOUNCE_INTERVAL: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ int interval;
+ status_t status = getMasterAnnounceInterval(&interval);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt32(interval);
+ }
+ return OK;
+ } break;
+
+ case SET_MASTER_ANNOUNCE_INTERVAL: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ int interval = data.readInt32();
+ status_t status = setMasterAnnounceInterval(interval);
+ reply->writeInt32(status);
+ return OK;
+ } break;
+
+ case GET_CLIENT_SYNC_INTERVAL: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ int interval;
+ status_t status = getClientSyncInterval(&interval);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt32(interval);
+ }
+ return OK;
+ } break;
+
+ case SET_CLIENT_SYNC_INTERVAL: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ int interval = data.readInt32();
+ status_t status = setClientSyncInterval(interval);
+ reply->writeInt32(status);
+ return OK;
+ } break;
+
+ case GET_PANIC_THRESHOLD: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ int threshold;
+ status_t status = getPanicThreshold(&threshold);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt32(threshold);
+ }
+ return OK;
+ } break;
+
+ case SET_PANIC_THRESHOLD: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ int threshold = data.readInt32();
+ status_t status = setPanicThreshold(threshold);
+ reply->writeInt32(status);
+ return OK;
+ } break;
+
+ case GET_AUTO_DISABLE: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ bool autoDisable;
+ status_t status = getAutoDisable(&autoDisable);
+ reply->writeInt32(status);
+ if (status == OK) {
+ reply->writeInt32(autoDisable ? 1 : 0);
+ }
+ return OK;
+ } break;
+
+ case SET_AUTO_DISABLE: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ bool autoDisable = (0 != data.readInt32());
+ status_t status = setAutoDisable(autoDisable);
+ reply->writeInt32(status);
+ return OK;
+ } break;
+
+ case FORCE_NETWORKLESS_MASTER_MODE: {
+ CHECK_INTERFACE(ICommonTimeConfig, data, reply);
+ status_t status = forceNetworklessMasterMode();
+ reply->writeInt32(status);
+ return OK;
+ } break;
+ }
+ return BBinder::onTransact(code, data, reply, flags);
+}
+
+}; // namespace android
+
diff --git a/media/common_time/cc_helper.cpp b/media/common_time/cc_helper.cpp
new file mode 100644
index 0000000..8d8556c
--- /dev/null
+++ b/media/common_time/cc_helper.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <stdint.h>
+
+#include <common_time/cc_helper.h>
+#include <common_time/ICommonClock.h>
+#include <utils/threads.h>
+
+namespace android {
+
+Mutex CCHelper::lock_;
+sp<ICommonClock> CCHelper::common_clock_;
+sp<ICommonClockListener> CCHelper::common_clock_listener_;
+uint32_t CCHelper::ref_count_ = 0;
+
+bool CCHelper::verifyClock_l() {
+ bool ret = false;
+
+ if (common_clock_ == NULL) {
+ common_clock_ = ICommonClock::getInstance();
+ if (common_clock_ == NULL)
+ goto bailout;
+ }
+
+ if (ref_count_ > 0) {
+ if (common_clock_listener_ == NULL) {
+ common_clock_listener_ = new CommonClockListener();
+ if (common_clock_listener_ == NULL)
+ goto bailout;
+
+ if (OK != common_clock_->registerListener(common_clock_listener_))
+ goto bailout;
+ }
+ }
+
+ ret = true;
+
+bailout:
+ if (!ret) {
+ common_clock_listener_ = NULL;
+ common_clock_ = NULL;
+ }
+ return ret;
+}
+
+CCHelper::CCHelper() {
+ Mutex::Autolock lock(&lock_);
+ ref_count_++;
+ verifyClock_l();
+}
+
+CCHelper::~CCHelper() {
+ Mutex::Autolock lock(&lock_);
+
+ assert(ref_count_ > 0);
+ ref_count_--;
+
+ // If we were the last CCHelper instance in the system, and we had
+ // previously register a listener, unregister it now so that the common time
+ // service has the chance to go into auto-disabled mode.
+ if (!ref_count_ &&
+ (common_clock_ != NULL) &&
+ (common_clock_listener_ != NULL)) {
+ common_clock_->unregisterListener(common_clock_listener_);
+ common_clock_listener_ = NULL;
+ }
+}
+
+void CCHelper::CommonClockListener::onTimelineChanged(uint64_t timelineID) {
+ // do nothing; listener is only really used as a token so the server can
+ // find out when clients die.
+}
+
+// Helper methods which attempts to make calls to the common time binder
+// service. If the first attempt fails with DEAD_OBJECT, the helpers will
+// attempt to make a connection to the service again (assuming that the process
+// hosting the service had crashed and the client proxy we are holding is dead)
+// If the second attempt fails, or no connection can be made, the we let the
+// error propagate up the stack and let the caller deal with the situation as
+// best they can.
+#define CCHELPER_METHOD(decl, call) \
+ status_t CCHelper::decl { \
+ Mutex::Autolock lock(&lock_); \
+ \
+ if (!verifyClock_l()) \
+ return DEAD_OBJECT; \
+ \
+ status_t status = common_clock_->call; \
+ if (DEAD_OBJECT == status) { \
+ if (!verifyClock_l()) \
+ return DEAD_OBJECT; \
+ status = common_clock_->call; \
+ } \
+ \
+ return status; \
+ }
+
+#define VERIFY_CLOCK()
+
+CCHELPER_METHOD(isCommonTimeValid(bool* valid, uint32_t* timelineID),
+ isCommonTimeValid(valid, timelineID))
+CCHELPER_METHOD(commonTimeToLocalTime(int64_t commonTime, int64_t* localTime),
+ commonTimeToLocalTime(commonTime, localTime))
+CCHELPER_METHOD(localTimeToCommonTime(int64_t localTime, int64_t* commonTime),
+ localTimeToCommonTime(localTime, commonTime))
+CCHELPER_METHOD(getCommonTime(int64_t* commonTime),
+ getCommonTime(commonTime))
+CCHELPER_METHOD(getCommonFreq(uint64_t* freq),
+ getCommonFreq(freq))
+CCHELPER_METHOD(getLocalTime(int64_t* localTime),
+ getLocalTime(localTime))
+CCHELPER_METHOD(getLocalFreq(uint64_t* freq),
+ getLocalFreq(freq))
+
+} // namespace android
diff --git a/media/common_time/local_clock.cpp b/media/common_time/local_clock.cpp
new file mode 100644
index 0000000..a7c61fc
--- /dev/null
+++ b/media/common_time/local_clock.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "common_time"
+#include <utils/Log.h>
+
+#include <assert.h>
+#include <stdint.h>
+
+#include <common_time/local_clock.h>
+#include <hardware/hardware.h>
+#include <hardware/local_time_hal.h>
+#include <utils/Errors.h>
+#include <utils/threads.h>
+
+namespace android {
+
+Mutex LocalClock::dev_lock_;
+local_time_hw_device_t* LocalClock::dev_ = NULL;
+
+LocalClock::LocalClock() {
+ int res;
+ const hw_module_t* mod;
+
+ AutoMutex lock(&dev_lock_);
+
+ if (dev_ != NULL)
+ return;
+
+ res = hw_get_module_by_class(LOCAL_TIME_HARDWARE_MODULE_ID, NULL, &mod);
+ if (res) {
+ ALOGE("Failed to open local time HAL module (res = %d)", res);
+ } else {
+ res = local_time_hw_device_open(mod, &dev_);
+ if (res) {
+ ALOGE("Failed to open local time HAL device (res = %d)", res);
+ dev_ = NULL;
+ }
+ }
+}
+
+bool LocalClock::initCheck() {
+ return (NULL != dev_);
+}
+
+int64_t LocalClock::getLocalTime() {
+ assert(NULL != dev_);
+ assert(NULL != dev_->get_local_time);
+
+ return dev_->get_local_time(dev_);
+}
+
+uint64_t LocalClock::getLocalFreq() {
+ assert(NULL != dev_);
+ assert(NULL != dev_->get_local_freq);
+
+ return dev_->get_local_freq(dev_);
+}
+
+status_t LocalClock::setLocalSlew(int16_t rate) {
+ assert(NULL != dev_);
+
+ if (!dev_->set_local_slew)
+ return INVALID_OPERATION;
+
+ return static_cast<status_t>(dev_->set_local_slew(dev_, rate));
+}
+
+int32_t LocalClock::getDebugLog(struct local_time_debug_event* records,
+ int max_records) {
+ assert(NULL != dev_);
+
+ if (!dev_->get_debug_log)
+ return INVALID_OPERATION;
+
+ return dev_->get_debug_log(dev_, records, max_records);
+}
+
+} // namespace android
diff --git a/media/common_time/utils.cpp b/media/common_time/utils.cpp
new file mode 100644
index 0000000..6539171
--- /dev/null
+++ b/media/common_time/utils.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <arpa/inet.h>
+#include <linux/socket.h>
+
+#include <binder/Parcel.h>
+
+namespace android {
+
+bool canSerializeSockaddr(const struct sockaddr_storage* addr) {
+ switch (addr->ss_family) {
+ case AF_INET:
+ case AF_INET6:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void serializeSockaddr(Parcel* p, const struct sockaddr_storage* addr) {
+ switch (addr->ss_family) {
+ case AF_INET: {
+ const struct sockaddr_in* s =
+ reinterpret_cast<const struct sockaddr_in*>(addr);
+ p->writeInt32(AF_INET);
+ p->writeInt32(ntohl(s->sin_addr.s_addr));
+ p->writeInt32(static_cast<int32_t>(ntohs(s->sin_port)));
+ } break;
+
+ case AF_INET6: {
+ const struct sockaddr_in6* s =
+ reinterpret_cast<const struct sockaddr_in6*>(addr);
+ const int32_t* a =
+ reinterpret_cast<const int32_t*>(s->sin6_addr.s6_addr);
+ p->writeInt32(AF_INET6);
+ p->writeInt32(ntohl(a[0]));
+ p->writeInt32(ntohl(a[1]));
+ p->writeInt32(ntohl(a[2]));
+ p->writeInt32(ntohl(a[3]));
+ p->writeInt32(static_cast<int32_t>(ntohs(s->sin6_port)));
+ p->writeInt32(ntohl(s->sin6_flowinfo));
+ p->writeInt32(ntohl(s->sin6_scope_id));
+ } break;
+ }
+}
+
+void deserializeSockaddr(const Parcel* p, struct sockaddr_storage* addr) {
+ memset(addr, 0, sizeof(addr));
+
+ addr->ss_family = p->readInt32();
+ switch(addr->ss_family) {
+ case AF_INET: {
+ struct sockaddr_in* s =
+ reinterpret_cast<struct sockaddr_in*>(addr);
+ s->sin_addr.s_addr = htonl(p->readInt32());
+ s->sin_port = htons(static_cast<uint16_t>(p->readInt32()));
+ } break;
+
+ case AF_INET6: {
+ struct sockaddr_in6* s =
+ reinterpret_cast<struct sockaddr_in6*>(addr);
+ int32_t* a = reinterpret_cast<int32_t*>(s->sin6_addr.s6_addr);
+
+ a[0] = htonl(p->readInt32());
+ a[1] = htonl(p->readInt32());
+ a[2] = htonl(p->readInt32());
+ a[3] = htonl(p->readInt32());
+ s->sin6_port = htons(static_cast<uint16_t>(p->readInt32()));
+ s->sin6_flowinfo = htonl(p->readInt32());
+ s->sin6_scope_id = htonl(p->readInt32());
+ } break;
+ }
+}
+
+} // namespace android
diff --git a/media/common_time/utils.h b/media/common_time/utils.h
new file mode 100644
index 0000000..ce79d0d
--- /dev/null
+++ b/media/common_time/utils.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_LIBCOMMONCLOCK_UTILS_H
+#define ANDROID_LIBCOMMONCLOCK_UTILS_H
+
+#include <linux/socket.h>
+
+#include <binder/Parcel.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+extern bool canSerializeSockaddr(const struct sockaddr_storage* addr);
+extern void serializeSockaddr(Parcel* p, const struct sockaddr_storage* addr);
+extern status_t deserializeSockaddr(const Parcel* p,
+ struct sockaddr_storage* addr);
+
+}; // namespace android
+
+#endif // ANDROID_LIBCOMMONCLOCK_UTILS_H
diff --git a/media/libaah_rtp/Android.mk b/media/libaah_rtp/Android.mk
new file mode 100644
index 0000000..6c927ba
--- /dev/null
+++ b/media/libaah_rtp/Android.mk
@@ -0,0 +1,40 @@
+LOCAL_PATH:= $(call my-dir)
+#
+# libaah_rtp
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libaah_rtp
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+ aah_decoder_pump.cpp \
+ aah_rx_player.cpp \
+ aah_rx_player_core.cpp \
+ aah_rx_player_ring_buffer.cpp \
+ aah_rx_player_substream.cpp \
+ aah_tx_packet.cpp \
+ aah_tx_player.cpp \
+ aah_tx_sender.cpp \
+ pipe_event.cpp
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/include \
+ frameworks/base/media \
+ frameworks/base/media/libstagefright \
+ frameworks/native/include/media/openmax
+
+LOCAL_SHARED_LIBRARIES := \
+ libcommon_time_client \
+ libbinder \
+ libmedia \
+ libmedia_native \
+ libstagefright \
+ libstagefright_foundation \
+ libutils
+
+LOCAL_LDLIBS := \
+ -lpthread
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libaah_rtp/aah_decoder_pump.cpp b/media/libaah_rtp/aah_decoder_pump.cpp
new file mode 100644
index 0000000..bebba54
--- /dev/null
+++ b/media/libaah_rtp/aah_decoder_pump.cpp
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "LibAAH_RTP"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <poll.h>
+#include <pthread.h>
+
+#include <common_time/cc_helper.h>
+#include <media/AudioSystem.h>
+#include <media/AudioTrack.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/Utils.h>
+#include <utils/Timers.h>
+#include <utils/threads.h>
+
+#include "aah_decoder_pump.h"
+
+namespace android {
+
+static const long long kLongDecodeErrorThreshold = 1000000ll;
+static const uint32_t kMaxLongErrorsBeforeFatal = 3;
+static const uint32_t kMaxErrorsBeforeFatal = 60;
+
+AAH_DecoderPump::AAH_DecoderPump(OMXClient& omx)
+ : omx_(omx)
+ , thread_status_(OK)
+ , renderer_(NULL)
+ , last_queued_pts_valid_(false)
+ , last_queued_pts_(0)
+ , last_ts_transform_valid_(false)
+ , last_volume_(0xFF) {
+ thread_ = new ThreadWrapper(this);
+}
+
+AAH_DecoderPump::~AAH_DecoderPump() {
+ shutdown();
+}
+
+status_t AAH_DecoderPump::initCheck() {
+ if (thread_ == NULL) {
+ ALOGE("Failed to allocate thread");
+ return NO_MEMORY;
+ }
+
+ return OK;
+}
+
+status_t AAH_DecoderPump::queueForDecode(MediaBuffer* buf) {
+ if (NULL == buf) {
+ return BAD_VALUE;
+ }
+
+ if (OK != thread_status_) {
+ return thread_status_;
+ }
+
+ { // Explicit scope for AutoMutex pattern.
+ AutoMutex lock(&thread_lock_);
+ in_queue_.push_back(buf);
+ }
+
+ thread_cond_.signal();
+
+ return OK;
+}
+
+void AAH_DecoderPump::queueToRenderer(MediaBuffer* decoded_sample) {
+ Mutex::Autolock lock(&render_lock_);
+ sp<MetaData> meta;
+ int64_t ts;
+ status_t res;
+
+ // Fetch the metadata and make sure the sample has a timestamp. We
+ // cannot render samples which are missing PTSs.
+ meta = decoded_sample->meta_data();
+ if ((meta == NULL) || (!meta->findInt64(kKeyTime, &ts))) {
+ ALOGV("Decoded sample missing timestamp, cannot render.");
+ CHECK(false);
+ } else {
+ // If we currently are not holding on to a renderer, go ahead and
+ // make one now.
+ if (NULL == renderer_) {
+ renderer_ = new TimedAudioTrack();
+ if (NULL != renderer_) {
+ int frameCount;
+ AudioTrack::getMinFrameCount(&frameCount,
+ AUDIO_STREAM_DEFAULT,
+ static_cast<int>(format_sample_rate_));
+ audio_channel_mask_t ch_format =
+ audio_channel_out_mask_from_count(format_channels_);
+
+ res = renderer_->set(AUDIO_STREAM_DEFAULT,
+ format_sample_rate_,
+ AUDIO_FORMAT_PCM_16_BIT,
+ ch_format,
+ frameCount);
+ if (res != OK) {
+ ALOGE("Failed to setup audio renderer. (res = %d)", res);
+ delete renderer_;
+ renderer_ = NULL;
+ } else {
+ CHECK(last_ts_transform_valid_);
+
+ res = renderer_->setMediaTimeTransform(
+ last_ts_transform_, TimedAudioTrack::COMMON_TIME);
+ if (res != NO_ERROR) {
+ ALOGE("Failed to set media time transform on AudioTrack"
+ " (res = %d)", res);
+ delete renderer_;
+ renderer_ = NULL;
+ } else {
+ float volume = static_cast<float>(last_volume_)
+ / 255.0f;
+ if (renderer_->setVolume(volume, volume) != OK) {
+ ALOGW("%s: setVolume failed", __FUNCTION__);
+ }
+
+ renderer_->start();
+ }
+ }
+ } else {
+ ALOGE("Failed to allocate AudioTrack to use as a renderer.");
+ }
+ }
+
+ if (NULL != renderer_) {
+ uint8_t* decoded_data =
+ reinterpret_cast<uint8_t*>(decoded_sample->data());
+ uint32_t decoded_amt = decoded_sample->range_length();
+ decoded_data += decoded_sample->range_offset();
+
+ sp<IMemory> pcm_payload;
+ res = renderer_->allocateTimedBuffer(decoded_amt, &pcm_payload);
+ if (res != OK) {
+ ALOGE("Failed to allocate %d byte audio track buffer."
+ " (res = %d)", decoded_amt, res);
+ } else {
+ memcpy(pcm_payload->pointer(), decoded_data, decoded_amt);
+
+ res = renderer_->queueTimedBuffer(pcm_payload, ts);
+ if (res != OK) {
+ ALOGE("Failed to queue %d byte audio track buffer with"
+ " media PTS %lld. (res = %d)", decoded_amt, ts, res);
+ } else {
+ last_queued_pts_valid_ = true;
+ last_queued_pts_ = ts;
+ }
+ }
+
+ } else {
+ ALOGE("No renderer, dropping audio payload.");
+ }
+ }
+}
+
+void AAH_DecoderPump::stopAndCleanupRenderer() {
+ if (NULL == renderer_) {
+ return;
+ }
+
+ renderer_->stop();
+ delete renderer_;
+ renderer_ = NULL;
+}
+
+void AAH_DecoderPump::setRenderTSTransform(const LinearTransform& trans) {
+ Mutex::Autolock lock(&render_lock_);
+
+ if (last_ts_transform_valid_ && !memcmp(&trans,
+ &last_ts_transform_,
+ sizeof(trans))) {
+ return;
+ }
+
+ last_ts_transform_ = trans;
+ last_ts_transform_valid_ = true;
+
+ if (NULL != renderer_) {
+ status_t res = renderer_->setMediaTimeTransform(
+ last_ts_transform_, TimedAudioTrack::COMMON_TIME);
+ if (res != NO_ERROR) {
+ ALOGE("Failed to set media time transform on AudioTrack"
+ " (res = %d)", res);
+ }
+ }
+}
+
+void AAH_DecoderPump::setRenderVolume(uint8_t volume) {
+ Mutex::Autolock lock(&render_lock_);
+
+ if (volume == last_volume_) {
+ return;
+ }
+
+ last_volume_ = volume;
+ if (renderer_ != NULL) {
+ float volume = static_cast<float>(last_volume_) / 255.0f;
+ if (renderer_->setVolume(volume, volume) != OK) {
+ ALOGW("%s: setVolume failed", __FUNCTION__);
+ }
+ }
+}
+
+// isAboutToUnderflow is something of a hack used to figure out when it might be
+// time to give up on trying to fill in a gap in the RTP sequence and simply
+// move on with a discontinuity. If we had perfect knowledge of when we were
+// going to underflow, it would not be a hack, but unfortunately we do not.
+// Right now, we just take the PTS of the last sample queued, and check to see
+// if its presentation time is within kAboutToUnderflowThreshold from now. If
+// it is, then we say that we are about to underflow. This decision is based on
+// two (possibly invalid) assumptions.
+//
+// 1) The transmitter is leading the clock by more than
+// kAboutToUnderflowThreshold.
+// 2) The delta between the PTS of the last sample queued and the next sample
+// is less than the transmitter's clock lead amount.
+//
+// Right now, the default transmitter lead time is 1 second, which is a pretty
+// large number and greater than the 50mSec that kAboutToUnderflowThreshold is
+// currently set to. This should satisfy assumption #1 for now, but changes to
+// the transmitter clock lead time could effect this.
+//
+// For non-sparse streams with a homogeneous sample rate (the vast majority of
+// streams in the world), the delta between any two adjacent PTSs will always be
+// the homogeneous sample period. It is very uncommon to see a sample period
+// greater than the 1 second clock lead we are currently using, and you
+// certainly will not see it in an MP3 file which should satisfy assumption #2.
+// Sparse audio streams (where no audio is transmitted for long periods of
+// silence) and extremely low framerate video stream (like an MPEG-2 slideshow
+// or the video stream for a pay TV audio channel) are examples of streams which
+// might violate assumption #2.
+bool AAH_DecoderPump::isAboutToUnderflow(int64_t threshold) {
+ Mutex::Autolock lock(&render_lock_);
+
+ // If we have never queued anything to the decoder, we really don't know if
+ // we are going to underflow or not.
+ if (!last_queued_pts_valid_ || !last_ts_transform_valid_) {
+ return false;
+ }
+
+ // Don't have access to Common Time? If so, then things are Very Bad
+ // elsewhere in the system; it pretty much does not matter what we do here.
+ // Since we cannot really tell if we are about to underflow or not, its
+ // probably best to assume that we are not and proceed accordingly.
+ int64_t tt_now;
+ if (OK != cc_helper_.getCommonTime(&tt_now)) {
+ return false;
+ }
+
+ // Transform from media time to common time.
+ int64_t last_queued_pts_tt;
+ if (!last_ts_transform_.doForwardTransform(last_queued_pts_,
+ &last_queued_pts_tt)) {
+ return false;
+ }
+
+ // Check to see if we are underflowing.
+ return ((tt_now + threshold - last_queued_pts_tt) > 0);
+}
+
+void* AAH_DecoderPump::workThread() {
+ // No need to lock when accessing decoder_ from the thread. The
+ // implementation of init and shutdown ensure that other threads never touch
+ // decoder_ while the work thread is running.
+ CHECK(decoder_ != NULL);
+ CHECK(format_ != NULL);
+
+ // Start the decoder and note its result code. If something goes horribly
+ // wrong, callers of queueForDecode and getOutput will be able to detect
+ // that the thread encountered a fatal error and shut down by examining
+ // thread_status_.
+ thread_status_ = decoder_->start(format_.get());
+ if (OK != thread_status_) {
+ ALOGE("AAH_DecoderPump's work thread failed to start decoder"
+ " (res = %d)", thread_status_);
+ return NULL;
+ }
+
+ DurationTimer decode_timer;
+ uint32_t consecutive_long_errors = 0;
+ uint32_t consecutive_errors = 0;
+
+ while (!thread_->exitPending()) {
+ status_t res;
+ MediaBuffer* bufOut = NULL;
+
+ decode_timer.start();
+ res = decoder_->read(&bufOut);
+ decode_timer.stop();
+
+ if (res == INFO_FORMAT_CHANGED) {
+ // Format has changed. Destroy our current renderer so that a new
+ // one can be created during queueToRenderer with the proper format.
+ //
+ // TODO : In order to transition seamlessly, we should change this
+ // to put the old renderer in a queue to play out completely before
+ // we destroy it. We can still create a new renderer, the timed
+ // nature of the renderer should ensure a seamless splice.
+ stopAndCleanupRenderer();
+ res = OK;
+ }
+
+ // Try to be a little nuanced in our handling of actual decode errors.
+ // Errors could happen because of minor stream corruption or because of
+ // transient resource limitations. In these cases, we would rather drop
+ // a little bit of output and ride out the unpleasantness then throw up
+ // our hands and abort everything.
+ //
+ // OTOH - When things are really bad (like we have a non-transient
+ // resource or bookkeeping issue, or the stream being fed to us is just
+ // complete and total garbage) we really want to terminate playback and
+ // raise an error condition all the way up to the application level so
+ // they can deal with it.
+ //
+ // Unfortunately, the error codes returned by the decoder can be a
+ // little non-specific. For example, if an OMXCodec times out
+ // attempting to obtain an output buffer, the error we get back is a
+ // generic -1. Try to distinguish between this resource timeout error
+ // and ES corruption error by timing how long the decode operation
+ // takes. Maintain accounting for both errors and "long errors". If we
+ // get more than a certain number consecutive errors of either type,
+ // consider it fatal and shutdown (which will cause the error to
+ // propagate all of the way up to the application level). The threshold
+ // for "long errors" is deliberately much lower than that of normal
+ // decode errors, both because of how long they take to happen and
+ // because they generally indicate resource limitation errors which are
+ // unlikely to go away in pathologically bad cases (in contrast to
+ // stream corruption errors which might happen 20 times in a row and
+ // then be suddenly OK again)
+ if (res != OK) {
+ consecutive_errors++;
+ if (decode_timer.durationUsecs() >= kLongDecodeErrorThreshold)
+ consecutive_long_errors++;
+
+ CHECK(NULL == bufOut);
+
+ ALOGW("%s: Failed to decode data (res = %d)",
+ __PRETTY_FUNCTION__, res);
+
+ if ((consecutive_errors >= kMaxErrorsBeforeFatal) ||
+ (consecutive_long_errors >= kMaxLongErrorsBeforeFatal)) {
+ ALOGE("%s: Maximum decode error threshold has been reached."
+ " There have been %d consecutive decode errors, and %d"
+ " consecutive decode operations which resulted in errors"
+ " and took more than %lld uSec to process. The last"
+ " decode operation took %lld uSec.",
+ __PRETTY_FUNCTION__,
+ consecutive_errors, consecutive_long_errors,
+ kLongDecodeErrorThreshold, decode_timer.durationUsecs());
+ thread_status_ = res;
+ break;
+ }
+
+ continue;
+ }
+
+ if (NULL == bufOut) {
+ ALOGW("%s: Successful decode, but no buffer produced",
+ __PRETTY_FUNCTION__);
+ continue;
+ }
+
+ // Successful decode (with actual output produced). Clear the error
+ // counters.
+ consecutive_errors = 0;
+ consecutive_long_errors = 0;
+
+ queueToRenderer(bufOut);
+ bufOut->release();
+ }
+
+ decoder_->stop();
+ stopAndCleanupRenderer();
+
+ return NULL;
+}
+
+status_t AAH_DecoderPump::init(const sp<MetaData>& params) {
+ Mutex::Autolock lock(&init_lock_);
+
+ if (decoder_ != NULL) {
+ // already inited
+ return OK;
+ }
+
+ if (params == NULL) {
+ return BAD_VALUE;
+ }
+
+ if (!params->findInt32(kKeyChannelCount, &format_channels_)) {
+ return BAD_VALUE;
+ }
+
+ if (!params->findInt32(kKeySampleRate, &format_sample_rate_)) {
+ return BAD_VALUE;
+ }
+
+ CHECK(OK == thread_status_);
+ CHECK(decoder_ == NULL);
+
+ status_t ret_val = UNKNOWN_ERROR;
+
+ // Cache the format and attempt to create the decoder.
+ format_ = params;
+ decoder_ = OMXCodec::Create(
+ omx_.interface(), // IOMX Handle
+ format_, // Metadata for substream (indicates codec)
+ false, // Make a decoder, not an encoder
+ sp<MediaSource>(this)); // We will be the source for this codec.
+
+ if (decoder_ == NULL) {
+ ALOGE("Failed to allocate decoder in %s", __PRETTY_FUNCTION__);
+ goto bailout;
+ }
+
+ // Fire up the pump thread. It will take care of starting and stopping the
+ // decoder.
+ ret_val = thread_->run("aah_decode_pump", ANDROID_PRIORITY_AUDIO);
+ if (OK != ret_val) {
+ ALOGE("Failed to start work thread in %s (res = %d)",
+ __PRETTY_FUNCTION__, ret_val);
+ goto bailout;
+ }
+
+bailout:
+ if (OK != ret_val) {
+ decoder_ = NULL;
+ format_ = NULL;
+ }
+
+ return OK;
+}
+
+status_t AAH_DecoderPump::shutdown() {
+ Mutex::Autolock lock(&init_lock_);
+ return shutdown_l();
+}
+
+status_t AAH_DecoderPump::shutdown_l() {
+ thread_->requestExit();
+ thread_cond_.signal();
+ thread_->requestExitAndWait();
+
+ for (MBQueue::iterator iter = in_queue_.begin();
+ iter != in_queue_.end();
+ ++iter) {
+ (*iter)->release();
+ }
+ in_queue_.clear();
+
+ last_queued_pts_valid_ = false;
+ last_ts_transform_valid_ = false;
+ last_volume_ = 0xFF;
+ thread_status_ = OK;
+
+ decoder_ = NULL;
+ format_ = NULL;
+
+ return OK;
+}
+
+status_t AAH_DecoderPump::read(MediaBuffer **buffer,
+ const ReadOptions *options) {
+ if (!buffer) {
+ return BAD_VALUE;
+ }
+
+ *buffer = NULL;
+
+ // While its not time to shut down, and we have no data to process, wait.
+ AutoMutex lock(&thread_lock_);
+ while (!thread_->exitPending() && in_queue_.empty())
+ thread_cond_.wait(thread_lock_);
+
+ // At this point, if its not time to shutdown then we must have something to
+ // process. Go ahead and pop the front of the queue for processing.
+ if (!thread_->exitPending()) {
+ CHECK(!in_queue_.empty());
+
+ *buffer = *(in_queue_.begin());
+ in_queue_.erase(in_queue_.begin());
+ }
+
+ // If we managed to get a buffer, then everything must be OK. If not, then
+ // we must be shutting down.
+ return (NULL == *buffer) ? INVALID_OPERATION : OK;
+}
+
+AAH_DecoderPump::ThreadWrapper::ThreadWrapper(AAH_DecoderPump* owner)
+ : Thread(false /* canCallJava*/ )
+ , owner_(owner) {
+}
+
+bool AAH_DecoderPump::ThreadWrapper::threadLoop() {
+ CHECK(NULL != owner_);
+ owner_->workThread();
+ return false;
+}
+
+} // namespace android
diff --git a/media/libaah_rtp/aah_decoder_pump.h b/media/libaah_rtp/aah_decoder_pump.h
new file mode 100644
index 0000000..4d57e49
--- /dev/null
+++ b/media/libaah_rtp/aah_decoder_pump.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 __DECODER_PUMP_H__
+#define __DECODER_PUMP_H__
+
+#include <pthread.h>
+
+#include <common_time/cc_helper.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/LinearTransform.h>
+#include <utils/List.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class MetaData;
+class OMXClient;
+class TimedAudioTrack;
+
+class AAH_DecoderPump : public MediaSource {
+ public:
+ explicit AAH_DecoderPump(OMXClient& omx);
+ status_t initCheck();
+
+ status_t queueForDecode(MediaBuffer* buf);
+
+ status_t init(const sp<MetaData>& params);
+ status_t shutdown();
+
+ void setRenderTSTransform(const LinearTransform& trans);
+ void setRenderVolume(uint8_t volume);
+ bool isAboutToUnderflow(int64_t threshold);
+ bool getStatus() const { return thread_status_; }
+
+ // MediaSource methods
+ virtual status_t start(MetaData *params) { return OK; }
+ virtual sp<MetaData> getFormat() { return format_; }
+ virtual status_t stop() { return OK; }
+ virtual status_t read(MediaBuffer **buffer,
+ const ReadOptions *options);
+
+ protected:
+ virtual ~AAH_DecoderPump();
+
+ private:
+ class ThreadWrapper : public Thread {
+ public:
+ friend class AAH_DecoderPump;
+ explicit ThreadWrapper(AAH_DecoderPump* owner);
+
+ private:
+ virtual bool threadLoop();
+ AAH_DecoderPump* owner_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(ThreadWrapper);
+ };
+
+ void* workThread();
+ virtual status_t shutdown_l();
+ void queueToRenderer(MediaBuffer* decoded_sample);
+ void stopAndCleanupRenderer();
+
+ sp<MetaData> format_;
+ int32_t format_channels_; // channel count, not channel mask
+ int32_t format_sample_rate_;
+
+ sp<MediaSource> decoder_;
+ OMXClient& omx_;
+ Mutex init_lock_;
+
+ sp<ThreadWrapper> thread_;
+ Condition thread_cond_;
+ Mutex thread_lock_;
+ status_t thread_status_;
+
+ Mutex render_lock_;
+ TimedAudioTrack* renderer_;
+ bool last_queued_pts_valid_;
+ int64_t last_queued_pts_;
+ bool last_ts_transform_valid_;
+ LinearTransform last_ts_transform_;
+ uint8_t last_volume_;
+ CCHelper cc_helper_;
+
+ // protected by the thread_lock_
+ typedef List<MediaBuffer*> MBQueue;
+ MBQueue in_queue_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AAH_DecoderPump);
+};
+
+} // namespace android
+#endif // __DECODER_PUMP_H__
diff --git a/media/libaah_rtp/aah_rx_player.cpp b/media/libaah_rtp/aah_rx_player.cpp
new file mode 100644
index 0000000..9dd79fd
--- /dev/null
+++ b/media/libaah_rtp/aah_rx_player.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "LibAAH_RTP"
+//#define LOG_NDEBUG 0
+
+#include <binder/IServiceManager.h>
+#include <media/MediaPlayerInterface.h>
+#include <utils/Log.h>
+
+#include "aah_rx_player.h"
+
+namespace android {
+
+const uint32_t AAH_RXPlayer::kRTPRingBufferSize = 1 << 10;
+
+sp<MediaPlayerBase> createAAH_RXPlayer() {
+ sp<MediaPlayerBase> ret = new AAH_RXPlayer();
+ return ret;
+}
+
+AAH_RXPlayer::AAH_RXPlayer()
+ : ring_buffer_(kRTPRingBufferSize)
+ , substreams_(NULL) {
+ thread_wrapper_ = new ThreadWrapper(*this);
+
+ is_playing_ = false;
+ multicast_joined_ = false;
+ transmitter_known_ = false;
+ current_epoch_known_ = false;
+ data_source_set_ = false;
+ sock_fd_ = -1;
+
+ substreams_.setCapacity(4);
+
+ memset(&listen_addr_, 0, sizeof(listen_addr_));
+ memset(&transmitter_addr_, 0, sizeof(transmitter_addr_));
+
+ fetchAudioFlinger();
+}
+
+AAH_RXPlayer::~AAH_RXPlayer() {
+ reset_l();
+ CHECK(substreams_.size() == 0);
+ omx_.disconnect();
+}
+
+status_t AAH_RXPlayer::initCheck() {
+ if (thread_wrapper_ == NULL) {
+ ALOGE("Failed to allocate thread wrapper!");
+ return NO_MEMORY;
+ }
+
+ if (!ring_buffer_.initCheck()) {
+ ALOGE("Failed to allocate reassembly ring buffer!");
+ return NO_MEMORY;
+ }
+
+ // Check for the presense of the common time service by attempting to query
+ // for CommonTime's frequency. If we get an error back, we cannot talk to
+ // the service at all and should abort now.
+ status_t res;
+ uint64_t freq;
+ res = cc_helper_.getCommonFreq(&freq);
+ if (OK != res) {
+ ALOGE("Failed to connect to common time service!");
+ return res;
+ }
+
+ return omx_.connect();
+}
+
+status_t AAH_RXPlayer::setDataSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers) {
+ AutoMutex api_lock(&api_lock_);
+ uint32_t a, b, c, d;
+ uint16_t port;
+
+ if (data_source_set_) {
+ return INVALID_OPERATION;
+ }
+
+ if (NULL == url) {
+ return BAD_VALUE;
+ }
+
+ if (5 != sscanf(url, "%*[^:/]://%u.%u.%u.%u:%hu", &a, &b, &c, &d, &port)) {
+ ALOGE("Failed to parse URL \"%s\"", url);
+ return BAD_VALUE;
+ }
+
+ if ((a > 255) || (b > 255) || (c > 255) || (d > 255) || (port == 0)) {
+ ALOGE("Bad multicast address \"%s\"", url);
+ return BAD_VALUE;
+ }
+
+ ALOGI("setDataSource :: %u.%u.%u.%u:%hu", a, b, c, d, port);
+
+ a = (a << 24) | (b << 16) | (c << 8) | d;
+
+ memset(&listen_addr_, 0, sizeof(listen_addr_));
+ listen_addr_.sin_family = AF_INET;
+ listen_addr_.sin_port = htons(port);
+ listen_addr_.sin_addr.s_addr = htonl(a);
+ data_source_set_ = true;
+
+ return OK;
+}
+
+status_t AAH_RXPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
+ return INVALID_OPERATION;
+}
+
+status_t AAH_RXPlayer::setVideoSurface(const sp<Surface>& surface) {
+ return OK;
+}
+
+status_t AAH_RXPlayer::setVideoSurfaceTexture(
+ const sp<ISurfaceTexture>& surfaceTexture) {
+ return OK;
+}
+
+status_t AAH_RXPlayer::prepare() {
+ return OK;
+}
+
+status_t AAH_RXPlayer::prepareAsync() {
+ sendEvent(MEDIA_PREPARED);
+ return OK;
+}
+
+status_t AAH_RXPlayer::start() {
+ AutoMutex api_lock(&api_lock_);
+
+ if (is_playing_) {
+ return OK;
+ }
+
+ status_t res = startWorkThread();
+ is_playing_ = (res == OK);
+ return res;
+}
+
+status_t AAH_RXPlayer::stop() {
+ return pause();
+}
+
+status_t AAH_RXPlayer::pause() {
+ AutoMutex api_lock(&api_lock_);
+ stopWorkThread();
+ CHECK(sock_fd_ < 0);
+ is_playing_ = false;
+ return OK;
+}
+
+bool AAH_RXPlayer::isPlaying() {
+ AutoMutex api_lock(&api_lock_);
+ return is_playing_;
+}
+
+status_t AAH_RXPlayer::seekTo(int msec) {
+ sendEvent(MEDIA_SEEK_COMPLETE);
+ return OK;
+}
+
+status_t AAH_RXPlayer::getCurrentPosition(int *msec) {
+ if (NULL != msec) {
+ *msec = 0;
+ }
+ return OK;
+}
+
+status_t AAH_RXPlayer::getDuration(int *msec) {
+ if (NULL != msec) {
+ *msec = 1;
+ }
+ return OK;
+}
+
+status_t AAH_RXPlayer::reset() {
+ AutoMutex api_lock(&api_lock_);
+ reset_l();
+ return OK;
+}
+
+void AAH_RXPlayer::reset_l() {
+ stopWorkThread();
+ CHECK(sock_fd_ < 0);
+ CHECK(!multicast_joined_);
+ is_playing_ = false;
+ data_source_set_ = false;
+ transmitter_known_ = false;
+ memset(&listen_addr_, 0, sizeof(listen_addr_));
+}
+
+status_t AAH_RXPlayer::setLooping(int loop) {
+ return OK;
+}
+
+player_type AAH_RXPlayer::playerType() {
+ return AAH_RX_PLAYER;
+}
+
+status_t AAH_RXPlayer::setParameter(int key, const Parcel &request) {
+ return ERROR_UNSUPPORTED;
+}
+
+status_t AAH_RXPlayer::getParameter(int key, Parcel *reply) {
+ return ERROR_UNSUPPORTED;
+}
+
+status_t AAH_RXPlayer::invoke(const Parcel& request, Parcel *reply) {
+ if (!reply) {
+ return BAD_VALUE;
+ }
+
+ int32_t magic;
+ status_t err = request.readInt32(&magic);
+ if (err != OK) {
+ reply->writeInt32(err);
+ return OK;
+ }
+
+ if (magic != 0x12345) {
+ reply->writeInt32(BAD_VALUE);
+ return OK;
+ }
+
+ int32_t methodID;
+ err = request.readInt32(&methodID);
+ if (err != OK) {
+ reply->writeInt32(err);
+ return OK;
+ }
+
+ switch (methodID) {
+ // Get Volume
+ case INVOKE_GET_MASTER_VOLUME: {
+ if (audio_flinger_ != NULL) {
+ reply->writeInt32(OK);
+ reply->writeFloat(audio_flinger_->masterVolume());
+ } else {
+ reply->writeInt32(UNKNOWN_ERROR);
+ }
+ } break;
+
+ // Set Volume
+ case INVOKE_SET_MASTER_VOLUME: {
+ float targetVol = request.readFloat();
+ reply->writeInt32(audio_flinger_->setMasterVolume(targetVol));
+ } break;
+
+ default: return BAD_VALUE;
+ }
+
+ return OK;
+}
+
+void AAH_RXPlayer::fetchAudioFlinger() {
+ if (audio_flinger_ == NULL) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder;
+ binder = sm->getService(String16("media.audio_flinger"));
+
+ if (binder == NULL) {
+ ALOGW("AAH_RXPlayer failed to fetch handle to audio flinger."
+ " Master volume control will not be possible.");
+ }
+
+ audio_flinger_ = interface_cast<IAudioFlinger>(binder);
+ }
+}
+
+} // namespace android
diff --git a/media/libaah_rtp/aah_rx_player.h b/media/libaah_rtp/aah_rx_player.h
new file mode 100644
index 0000000..ba5617e
--- /dev/null
+++ b/media/libaah_rtp/aah_rx_player.h
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 __AAH_RX_PLAYER_H__
+#define __AAH_RX_PLAYER_H__
+
+#include <common_time/cc_helper.h>
+#include <media/MediaPlayerInterface.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+#include <netinet/in.h>
+#include <utils/KeyedVector.h>
+#include <utils/LinearTransform.h>
+#include <utils/threads.h>
+
+#include "aah_decoder_pump.h"
+#include "pipe_event.h"
+
+namespace android {
+
+class AAH_RXPlayer : public MediaPlayerInterface {
+ public:
+ AAH_RXPlayer();
+
+ virtual status_t initCheck();
+ virtual status_t setDataSource(const char *url,
+ const KeyedVector<String8, String8>*
+ headers);
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
+ virtual status_t setVideoSurface(const sp<Surface>& surface);
+ virtual status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>&
+ surfaceTexture);
+ virtual status_t prepare();
+ virtual status_t prepareAsync();
+ virtual status_t start();
+ virtual status_t stop();
+ virtual status_t pause();
+ virtual bool isPlaying();
+ virtual status_t seekTo(int msec);
+ virtual status_t getCurrentPosition(int *msec);
+ virtual status_t getDuration(int *msec);
+ virtual status_t reset();
+ virtual status_t setLooping(int loop);
+ virtual player_type playerType();
+ virtual status_t setParameter(int key, const Parcel &request);
+ virtual status_t getParameter(int key, Parcel *reply);
+ virtual status_t invoke(const Parcel& request, Parcel *reply);
+
+ protected:
+ virtual ~AAH_RXPlayer();
+
+ private:
+ class ThreadWrapper : public Thread {
+ public:
+ friend class AAH_RXPlayer;
+ explicit ThreadWrapper(AAH_RXPlayer& player)
+ : Thread(false /* canCallJava */ )
+ , player_(player) { }
+
+ virtual bool threadLoop() { return player_.threadLoop(); }
+
+ private:
+ AAH_RXPlayer& player_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(ThreadWrapper);
+ };
+
+#pragma pack(push, 1)
+ // PacketBuffers are structures used by the RX ring buffer. The ring buffer
+ // is a ring of pointers to PacketBuffer structures which act as variable
+ // length byte arrays and hold the contents of received UDP packets. Rather
+ // than make this a structure which hold a length and a pointer to another
+ // allocated structure (which would require two allocations), this struct
+ // uses a structure overlay pattern where allocation for the byte array
+ // consists of allocating (arrayLen + sizeof(ssize_t)) bytes of data from
+ // whatever pool/heap the packet buffer pulls from, and then overlaying the
+ // packed PacketBuffer structure on top of the allocation. The one-byte
+ // array at the end of the structure serves as an offset to the the data
+ // portion of the allocation; packet buffers are never allocated on the
+ // stack or using the new operator. Instead, the static allocate-byte-array
+ // and destroy methods handle the allocate and overlay pattern. They also
+ // allow for a potential future optimization where instead of just
+ // allocating blocks from the process global heap and overlaying, the
+ // allocator is replaced with a different implementation (private heap,
+ // free-list, circular buffer, etc) which reduces potential heap
+ // fragmentation issues which might arise from the frequent allocation and
+ // destruction of the received UDP traffic.
+ struct PacketBuffer {
+ ssize_t length_;
+ uint8_t data_[1];
+
+ // TODO : consider changing this to be some form of ring buffer or free
+ // pool system instead of just using the heap in order to avoid heap
+ // fragmentation.
+ static PacketBuffer* allocate(ssize_t length);
+ static void destroy(PacketBuffer* pb);
+
+ private:
+ // Force people to use allocate/destroy instead of new/delete.
+ PacketBuffer() { }
+ ~PacketBuffer() { }
+ };
+
+ struct RetransRequest {
+ uint32_t magic_;
+ uint32_t mcast_ip_;
+ uint16_t mcast_port_;
+ uint16_t start_seq_;
+ uint16_t end_seq_;
+ };
+#pragma pack(pop)
+
+ enum GapStatus {
+ kGS_NoGap = 0,
+ kGS_NormalGap,
+ kGS_FastStartGap,
+ };
+
+ struct SeqNoGap {
+ uint16_t start_seq_;
+ uint16_t end_seq_;
+ };
+
+ class RXRingBuffer {
+ public:
+ explicit RXRingBuffer(uint32_t capacity);
+ ~RXRingBuffer();
+
+ bool initCheck() const { return (ring_ != NULL); }
+ void reset();
+
+ // Push a packet buffer with a given sequence number into the ring
+ // buffer. pushBuffer will always consume the buffer pushed to it,
+ // either destroying it because it was a duplicate or overflow, or
+ // holding on to it in the ring. Callers should not hold any references
+ // to PacketBuffers after they have been pushed to the ring. Returns
+ // false in the case of a serious error (such as ring overflow).
+ // Callers should consider resetting the pipeline entirely in the event
+ // of a serious error.
+ bool pushBuffer(PacketBuffer* buf, uint16_t seq);
+
+ // Fetch the next buffer in the RTP sequence. Returns NULL if there is
+ // no buffer to fetch. If a non-NULL PacketBuffer is returned,
+ // is_discon will be set to indicate whether or not this PacketBuffer is
+ // discontiuous with any previously returned packet buffers. Packet
+ // buffers returned by fetchBuffer are the caller's responsibility; they
+ // must be certain to destroy the buffers when they are done.
+ PacketBuffer* fetchBuffer(bool* is_discon);
+
+ // Returns true and fills out the gap structure if the read pointer of
+ // the ring buffer is currently pointing to a gap which would stall a
+ // fetchBuffer operation. Returns false if the read pointer is not
+ // pointing to a gap in the sequence currently.
+ GapStatus fetchCurrentGap(SeqNoGap* gap);
+
+ // Causes the read pointer to skip over any portion of a gap indicated
+ // by nak. If nak is NULL, any gap currently blocking the read pointer
+ // will be completely skipped. If any portion of a gap is skipped, the
+ // next successful read from fetch buffer will indicate a discontinuity.
+ void processNAK(const SeqNoGap* nak = NULL);
+
+ // Compute the number of milliseconds until the inactivity timer for
+ // this RTP stream. Returns -1 if there is no active timeout, or 0 if
+ // the system has already timed out.
+ int computeInactivityTimeout();
+
+ private:
+ Mutex lock_;
+ PacketBuffer** ring_;
+ uint32_t capacity_;
+ uint32_t rd_;
+ uint32_t wr_;
+
+ uint16_t rd_seq_;
+ bool rd_seq_known_;
+ bool waiting_for_fast_start_;
+ bool fetched_first_packet_;
+
+ uint64_t rtp_activity_timeout_;
+ bool rtp_activity_timeout_valid_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(RXRingBuffer);
+ };
+
+ class Substream : public virtual RefBase {
+ public:
+ Substream(uint32_t ssrc, OMXClient& omx);
+
+ void cleanupBufferInProgress();
+ void shutdown();
+ void processPayloadStart(uint8_t* buf,
+ uint32_t amt,
+ int32_t ts_lower);
+ void processPayloadCont (uint8_t* buf,
+ uint32_t amt);
+ void processTSTransform(const LinearTransform& trans);
+
+ bool isAboutToUnderflow();
+ uint32_t getSSRC() const { return ssrc_; }
+ uint16_t getProgramID() const { return (ssrc_ >> 5) & 0x1F; }
+ status_t getStatus() const { return status_; }
+
+ protected:
+ virtual ~Substream();
+
+ private:
+ void cleanupDecoder();
+ bool shouldAbort(const char* log_tag);
+ void processCompletedBuffer();
+ bool setupSubstreamMeta();
+ bool setupMP3SubstreamMeta();
+ bool setupAACSubstreamMeta();
+ bool setupSubstreamType(uint8_t substream_type,
+ uint8_t codec_type);
+
+ uint32_t ssrc_;
+ bool waiting_for_rap_;
+ status_t status_;
+
+ bool substream_details_known_;
+ uint8_t substream_type_;
+ uint8_t codec_type_;
+ const char* codec_mime_type_;
+ sp<MetaData> substream_meta_;
+
+ MediaBuffer* buffer_in_progress_;
+ uint32_t expected_buffer_size_;
+ uint32_t buffer_filled_;
+
+ Vector<uint8_t> aux_data_in_progress_;
+ uint32_t aux_data_expected_size_;
+
+ sp<AAH_DecoderPump> decoder_;
+
+ static int64_t kAboutToUnderflowThreshold;
+
+ DISALLOW_EVIL_CONSTRUCTORS(Substream);
+ };
+
+ typedef DefaultKeyedVector< uint32_t, sp<Substream> > SubstreamVec;
+
+ status_t startWorkThread();
+ void stopWorkThread();
+ virtual bool threadLoop();
+ bool setupSocket();
+ void cleanupSocket();
+ void resetPipeline();
+ void reset_l();
+ bool processRX(PacketBuffer* pb);
+ void processRingBuffer();
+ void processCommandPacket(PacketBuffer* pb);
+ bool processGaps();
+ int computeNextGapRetransmitTimeout();
+ void fetchAudioFlinger();
+
+ PipeEvent wakeup_work_thread_evt_;
+ sp<ThreadWrapper> thread_wrapper_;
+ Mutex api_lock_;
+ bool is_playing_;
+ bool data_source_set_;
+
+ struct sockaddr_in listen_addr_;
+ int sock_fd_;
+ bool multicast_joined_;
+
+ struct sockaddr_in transmitter_addr_;
+ bool transmitter_known_;
+
+ uint32_t current_epoch_;
+ bool current_epoch_known_;
+
+ SeqNoGap current_gap_;
+ GapStatus current_gap_status_;
+ uint64_t next_retrans_req_time_;
+
+ RXRingBuffer ring_buffer_;
+ SubstreamVec substreams_;
+ OMXClient omx_;
+ CCHelper cc_helper_;
+
+ // Connection to audio flinger used to hack a path to setMasterVolume.
+ sp<IAudioFlinger> audio_flinger_;
+
+ static const uint32_t kRTPRingBufferSize;
+ static const uint32_t kRetransRequestMagic;
+ static const uint32_t kFastStartRequestMagic;
+ static const uint32_t kRetransNAKMagic;
+ static const uint32_t kGapRerequestTimeoutUSec;
+ static const uint32_t kFastStartTimeoutUSec;
+ static const uint32_t kRTPActivityTimeoutUSec;
+
+ static const uint32_t INVOKE_GET_MASTER_VOLUME = 3;
+ static const uint32_t INVOKE_SET_MASTER_VOLUME = 4;
+
+ static uint64_t monotonicUSecNow();
+
+ DISALLOW_EVIL_CONSTRUCTORS(AAH_RXPlayer);
+};
+
+} // namespace android
+
+#endif // __AAH_RX_PLAYER_H__
diff --git a/media/libaah_rtp/aah_rx_player_core.cpp b/media/libaah_rtp/aah_rx_player_core.cpp
new file mode 100644
index 0000000..d6b31fd
--- /dev/null
+++ b/media/libaah_rtp/aah_rx_player_core.cpp
@@ -0,0 +1,809 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "LibAAH_RTP"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <fcntl.h>
+#include <poll.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <utils/misc.h>
+
+#include <media/stagefright/Utils.h>
+
+#include "aah_rx_player.h"
+#include "aah_tx_packet.h"
+
+namespace android {
+
+const uint32_t AAH_RXPlayer::kRetransRequestMagic =
+ FOURCC('T','r','e','q');
+const uint32_t AAH_RXPlayer::kRetransNAKMagic =
+ FOURCC('T','n','a','k');
+const uint32_t AAH_RXPlayer::kFastStartRequestMagic =
+ FOURCC('T','f','s','t');
+const uint32_t AAH_RXPlayer::kGapRerequestTimeoutUSec = 75000;
+const uint32_t AAH_RXPlayer::kFastStartTimeoutUSec = 800000;
+const uint32_t AAH_RXPlayer::kRTPActivityTimeoutUSec = 10000000;
+
+static inline int16_t fetchInt16(uint8_t* data) {
+ return static_cast<int16_t>(U16_AT(data));
+}
+
+static inline int32_t fetchInt32(uint8_t* data) {
+ return static_cast<int32_t>(U32_AT(data));
+}
+
+static inline int64_t fetchInt64(uint8_t* data) {
+ return static_cast<int64_t>(U64_AT(data));
+}
+
+uint64_t AAH_RXPlayer::monotonicUSecNow() {
+ struct timespec now;
+ int res = clock_gettime(CLOCK_MONOTONIC, &now);
+ CHECK(res >= 0);
+
+ uint64_t ret = static_cast<uint64_t>(now.tv_sec) * 1000000;
+ ret += now.tv_nsec / 1000;
+
+ return ret;
+}
+
+status_t AAH_RXPlayer::startWorkThread() {
+ status_t res;
+ stopWorkThread();
+ res = thread_wrapper_->run("TRX_Player", PRIORITY_AUDIO);
+
+ if (res != OK) {
+ ALOGE("Failed to start work thread (res = %d)", res);
+ }
+
+ return res;
+}
+
+void AAH_RXPlayer::stopWorkThread() {
+ thread_wrapper_->requestExit(); // set the exit pending flag
+ wakeup_work_thread_evt_.setEvent();
+
+ status_t res;
+ res = thread_wrapper_->requestExitAndWait(); // block until thread exit.
+ if (res != OK) {
+ ALOGE("Failed to stop work thread (res = %d)", res);
+ }
+
+ wakeup_work_thread_evt_.clearPendingEvents();
+}
+
+void AAH_RXPlayer::cleanupSocket() {
+ if (sock_fd_ >= 0) {
+ if (multicast_joined_) {
+ int res;
+ struct ip_mreq mreq;
+ mreq.imr_multiaddr = listen_addr_.sin_addr;
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ res = setsockopt(sock_fd_,
+ IPPROTO_IP,
+ IP_DROP_MEMBERSHIP,
+ &mreq, sizeof(mreq));
+ if (res < 0) {
+ ALOGW("Failed to leave multicast group. (%d, %d)", res, errno);
+ }
+ multicast_joined_ = false;
+ }
+
+ close(sock_fd_);
+ sock_fd_ = -1;
+ }
+
+ resetPipeline();
+}
+
+void AAH_RXPlayer::resetPipeline() {
+ ring_buffer_.reset();
+
+ // Explicitly shudown all of the active substreams, then call clear out the
+ // collection. Failure to clear out a substream can result in its decoder
+ // holding a reference to itself and therefor not going away when the
+ // collection is cleared.
+ for (size_t i = 0; i < substreams_.size(); ++i)
+ substreams_.valueAt(i)->shutdown();
+
+ substreams_.clear();
+
+ current_gap_status_ = kGS_NoGap;
+}
+
+bool AAH_RXPlayer::setupSocket() {
+ long flags;
+ int res, buf_size;
+ socklen_t opt_size;
+
+ cleanupSocket();
+ CHECK(sock_fd_ < 0);
+
+ // Make the socket
+ sock_fd_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock_fd_ < 0) {
+ ALOGE("Failed to create listen socket (errno %d)", errno);
+ goto bailout;
+ }
+
+ // Set non-blocking operation
+ flags = fcntl(sock_fd_, F_GETFL);
+ res = fcntl(sock_fd_, F_SETFL, flags | O_NONBLOCK);
+ if (res < 0) {
+ ALOGE("Failed to set socket (%d) to non-blocking mode (errno %d)",
+ sock_fd_, errno);
+ goto bailout;
+ }
+
+ // Bind to our port
+ struct sockaddr_in bind_addr;
+ memset(&bind_addr, 0, sizeof(bind_addr));
+ bind_addr.sin_family = AF_INET;
+ bind_addr.sin_addr.s_addr = INADDR_ANY;
+ bind_addr.sin_port = listen_addr_.sin_port;
+ res = bind(sock_fd_,
+ reinterpret_cast<const sockaddr*>(&bind_addr),
+ sizeof(bind_addr));
+ if (res < 0) {
+ uint32_t a = ntohl(bind_addr.sin_addr.s_addr);
+ uint16_t p = ntohs(bind_addr.sin_port);
+ ALOGE("Failed to bind socket (%d) to %d.%d.%d.%d:%hd. (errno %d)",
+ sock_fd_,
+ (a >> 24) & 0xFF,
+ (a >> 16) & 0xFF,
+ (a >> 8) & 0xFF,
+ (a ) & 0xFF,
+ p,
+ errno);
+
+ goto bailout;
+ }
+
+ buf_size = 1 << 16; // 64k
+ res = setsockopt(sock_fd_,
+ SOL_SOCKET, SO_RCVBUF,
+ &buf_size, sizeof(buf_size));
+ if (res < 0) {
+ ALOGW("Failed to increase socket buffer size to %d. (errno %d)",
+ buf_size, errno);
+ }
+
+ buf_size = 0;
+ opt_size = sizeof(buf_size);
+ res = getsockopt(sock_fd_,
+ SOL_SOCKET, SO_RCVBUF,
+ &buf_size, &opt_size);
+ if (res < 0) {
+ ALOGW("Failed to fetch socket buffer size. (errno %d)", errno);
+ } else {
+ ALOGI("RX socket buffer size is now %d bytes", buf_size);
+ }
+
+ if (listen_addr_.sin_addr.s_addr) {
+ // Join the multicast group and we should be good to go.
+ struct ip_mreq mreq;
+ mreq.imr_multiaddr = listen_addr_.sin_addr;
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ res = setsockopt(sock_fd_,
+ IPPROTO_IP,
+ IP_ADD_MEMBERSHIP,
+ &mreq, sizeof(mreq));
+ if (res < 0) {
+ ALOGE("Failed to join multicast group. (errno %d)", errno);
+ goto bailout;
+ }
+ multicast_joined_ = true;
+ }
+
+ return true;
+
+bailout:
+ cleanupSocket();
+ return false;
+}
+
+bool AAH_RXPlayer::threadLoop() {
+ struct pollfd poll_fds[2];
+ bool process_more_right_now = false;
+
+ if (!setupSocket()) {
+ sendEvent(MEDIA_ERROR);
+ goto bailout;
+ }
+
+ while (!thread_wrapper_->exitPending()) {
+ // Step 1: Wait until there is something to do.
+ int gap_timeout = computeNextGapRetransmitTimeout();
+ int ring_timeout = ring_buffer_.computeInactivityTimeout();
+ int timeout = -1;
+
+ if (!ring_timeout) {
+ ALOGW("RTP inactivity timeout reached, resetting pipeline.");
+ resetPipeline();
+ timeout = gap_timeout;
+ } else {
+ if (gap_timeout < 0) {
+ timeout = ring_timeout;
+ } else if (ring_timeout < 0) {
+ timeout = gap_timeout;
+ } else {
+ timeout = (gap_timeout < ring_timeout) ? gap_timeout
+ : ring_timeout;
+ }
+ }
+
+ if ((0 != timeout) && (!process_more_right_now)) {
+ // Set up the events to wait on. Start with the wakeup pipe.
+ memset(&poll_fds, 0, sizeof(poll_fds));
+ poll_fds[0].fd = wakeup_work_thread_evt_.getWakeupHandle();
+ poll_fds[0].events = POLLIN;
+
+ // Add the RX socket.
+ poll_fds[1].fd = sock_fd_;
+ poll_fds[1].events = POLLIN;
+
+ // Wait for something interesing to happen.
+ int poll_res = poll(poll_fds, NELEM(poll_fds), timeout);
+ if (poll_res < 0) {
+ ALOGE("Fatal error (%d,%d) while waiting on events",
+ poll_res, errno);
+ sendEvent(MEDIA_ERROR);
+ goto bailout;
+ }
+ }
+
+ if (thread_wrapper_->exitPending()) {
+ break;
+ }
+
+ wakeup_work_thread_evt_.clearPendingEvents();
+ process_more_right_now = false;
+
+ // Step 2: Do we have data waiting in the socket? If so, drain the
+ // socket moving valid RTP information into the ring buffer to be
+ // processed.
+ if (poll_fds[1].revents) {
+ struct sockaddr_in from;
+ socklen_t from_len;
+
+ ssize_t res = 0;
+ while (!thread_wrapper_->exitPending()) {
+ // Check the size of any pending packet.
+ res = recv(sock_fd_, NULL, 0, MSG_PEEK | MSG_TRUNC);
+
+ // Error?
+ if (res < 0) {
+ // If the error is anything other than would block,
+ // something has gone very wrong.
+ if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) {
+ ALOGE("Fatal socket error during recvfrom (%d, %d)",
+ (int)res, errno);
+ goto bailout;
+ }
+
+ // Socket is out of data, just break out of processing and
+ // wait for more.
+ break;
+ }
+
+ // Allocate a payload.
+ PacketBuffer* pb = PacketBuffer::allocate(res);
+ if (NULL == pb) {
+ ALOGE("Fatal error, failed to allocate packet buffer of"
+ " length %u", static_cast<uint32_t>(res));
+ goto bailout;
+ }
+
+ // Fetch the data.
+ from_len = sizeof(from);
+ res = recvfrom(sock_fd_, pb->data_, pb->length_, 0,
+ reinterpret_cast<struct sockaddr*>(&from),
+ &from_len);
+ if (res != pb->length_) {
+ ALOGE("Fatal error, fetched packet length (%d) does not"
+ " match peeked packet length (%u). This should never"
+ " happen. (errno = %d)",
+ static_cast<int>(res),
+ static_cast<uint32_t>(pb->length_),
+ errno);
+ }
+
+ bool drop_packet = false;
+ if (transmitter_known_) {
+ if (from.sin_addr.s_addr !=
+ transmitter_addr_.sin_addr.s_addr) {
+ uint32_t a = ntohl(from.sin_addr.s_addr);
+ uint16_t p = ntohs(from.sin_port);
+ ALOGV("Dropping packet from unknown transmitter"
+ " %u.%u.%u.%u:%hu",
+ ((a >> 24) & 0xFF),
+ ((a >> 16) & 0xFF),
+ ((a >> 8) & 0xFF),
+ ( a & 0xFF),
+ p);
+
+ drop_packet = true;
+ } else {
+ transmitter_addr_.sin_port = from.sin_port;
+ }
+ } else {
+ memcpy(&transmitter_addr_, &from, sizeof(from));
+ transmitter_known_ = true;
+ }
+
+ if (!drop_packet) {
+ bool serious_error = !processRX(pb);
+
+ if (serious_error) {
+ // Something went "seriously wrong". Currently, the
+ // only trigger for this should be a ring buffer
+ // overflow. The current failsafe behavior for when
+ // something goes seriously wrong is to just reset the
+ // pipeline. The system should behave as if this
+ // AAH_RXPlayer was just set up for the first time.
+ ALOGE("Something just went seriously wrong with the"
+ " pipeline. Resetting.");
+ resetPipeline();
+ }
+ } else {
+ PacketBuffer::destroy(pb);
+ }
+ }
+ }
+
+ // Step 3: Process any data we mave have accumulated in the ring buffer
+ // so far.
+ if (!thread_wrapper_->exitPending()) {
+ processRingBuffer();
+ }
+
+ // Step 4: At this point in time, the ring buffer should either be
+ // empty, or stalled in front of a gap caused by some dropped packets.
+ // Check on the current gap situation and deal with it in an appropriate
+ // fashion. If processGaps returns true, it means that it has given up
+ // on a gap and that we should try to process some more data
+ // immediately.
+ if (!thread_wrapper_->exitPending()) {
+ process_more_right_now = processGaps();
+ }
+
+ // Step 5: Check for fatal errors. If any of our substreams has
+ // encountered a fatal, unrecoverable, error, then propagate the error
+ // up to user level and shut down.
+ for (size_t i = 0; i < substreams_.size(); ++i) {
+ status_t status;
+ CHECK(substreams_.valueAt(i) != NULL);
+
+ status = substreams_.valueAt(i)->getStatus();
+ if (OK != status) {
+ ALOGE("Substream index %d has encountered an unrecoverable"
+ " error (%d). Signalling application level and shutting"
+ " down.", i, status);
+ sendEvent(MEDIA_ERROR);
+ goto bailout;
+ }
+ }
+ }
+
+bailout:
+ cleanupSocket();
+ return false;
+}
+
+bool AAH_RXPlayer::processRX(PacketBuffer* pb) {
+ CHECK(NULL != pb);
+
+ uint8_t* data = pb->data_;
+ ssize_t amt = pb->length_;
+ uint32_t nak_magic;
+ uint16_t seq_no;
+ uint32_t epoch;
+
+ // Every packet either starts with an RTP header which is at least 12 bytes
+ // long or is a retry NAK which is 14 bytes long. If there are fewer than
+ // 12 bytes here, this cannot be a proper RTP packet.
+ if (amt < 12) {
+ ALOGV("Dropping packet, too short to contain RTP header (%u bytes)",
+ static_cast<uint32_t>(amt));
+ goto drop_packet;
+ }
+
+ // Check to see if this is the special case of a NAK packet.
+ nak_magic = ntohl(*(reinterpret_cast<uint32_t*>(data)));
+ if (nak_magic == kRetransNAKMagic) {
+ // Looks like a NAK packet; make sure its long enough.
+
+ if (amt < static_cast<ssize_t>(sizeof(RetransRequest))) {
+ ALOGV("Dropping packet, too short to contain NAK payload"
+ " (%u bytes)", static_cast<uint32_t>(amt));
+ goto drop_packet;
+ }
+
+ SeqNoGap gap;
+ RetransRequest* rtr = reinterpret_cast<RetransRequest*>(data);
+ gap.start_seq_ = ntohs(rtr->start_seq_);
+ gap.end_seq_ = ntohs(rtr->end_seq_);
+
+ ALOGV("Process NAK for gap at [%hu, %hu]",
+ gap.start_seq_, gap.end_seq_);
+ ring_buffer_.processNAK(&gap);
+
+ return true;
+ }
+
+ // According to the TRTP spec, version should be 2, padding should be 0,
+ // extension should be 0 and CSRCCnt should be 0. If any of these tests
+ // fail, we chuck the packet.
+ if (data[0] != 0x80) {
+ ALOGV("Dropping packet, bad V/P/X/CSRCCnt field (0x%02x)",
+ data[0]);
+ goto drop_packet;
+ }
+
+ // Check the payload type. For TRTP, it should always be 100.
+ if ((data[1] & 0x7F) != 100) {
+ ALOGV("Dropping packet, bad payload type. (%u)",
+ data[1] & 0x7F);
+ goto drop_packet;
+ }
+
+ // Check whether the transmitter has begun a new epoch.
+ epoch = (U32_AT(data + 8) >> 10) & 0x3FFFFF;
+ if (current_epoch_known_) {
+ if (epoch != current_epoch_) {
+ ALOGV("%s: new epoch %u", __PRETTY_FUNCTION__, epoch);
+ current_epoch_ = epoch;
+ resetPipeline();
+ }
+ } else {
+ current_epoch_ = epoch;
+ current_epoch_known_ = true;
+ }
+
+ // Extract the sequence number and hand the packet off to the ring buffer
+ // for dropped packet detection and later processing.
+ seq_no = U16_AT(data + 2);
+ return ring_buffer_.pushBuffer(pb, seq_no);
+
+drop_packet:
+ PacketBuffer::destroy(pb);
+ return true;
+}
+
+void AAH_RXPlayer::processRingBuffer() {
+ PacketBuffer* pb;
+ bool is_discon;
+ sp<Substream> substream;
+ LinearTransform trans;
+ bool foundTrans = false;
+
+ while (NULL != (pb = ring_buffer_.fetchBuffer(&is_discon))) {
+ if (is_discon) {
+ // Abort all partially assembled payloads.
+ for (size_t i = 0; i < substreams_.size(); ++i) {
+ CHECK(substreams_.valueAt(i) != NULL);
+ substreams_.valueAt(i)->cleanupBufferInProgress();
+ }
+ }
+
+ uint8_t* data = pb->data_;
+ ssize_t amt = pb->length_;
+
+ // Should not have any non-RTP packets in the ring buffer. RTP packets
+ // must be at least 12 bytes long.
+ CHECK(amt >= 12);
+
+ // Extract the marker bit and the SSRC field.
+ bool marker = (data[1] & 0x80) != 0;
+ uint32_t ssrc = U32_AT(data + 8);
+
+ // Is this the start of a new TRTP payload? If so, the marker bit
+ // should be set and there are some things we should be checking for.
+ if (marker) {
+ // TRTP headers need to have at least a byte for version, a byte for
+ // payload type and flags, and 4 bytes for length.
+ if (amt < 18) {
+ ALOGV("Dropping packet, too short to contain TRTP header"
+ " (%u bytes)", static_cast<uint32_t>(amt));
+ goto process_next_packet;
+ }
+
+ // Check the TRTP version and extract the payload type/flags.
+ uint8_t trtp_version = data[12];
+ uint8_t payload_type = (data[13] >> 4) & 0xF;
+ uint8_t trtp_flags = data[13] & 0xF;
+
+ if (1 != trtp_version) {
+ ALOGV("Dropping packet, bad trtp version %hhu", trtp_version);
+ goto process_next_packet;
+ }
+
+ // Is there a timestamp transformation present on this packet? If
+ // so, extract it and pass it to the appropriate substreams.
+ if (trtp_flags & 0x02) {
+ ssize_t offset = 18 + ((trtp_flags & 0x01) ? 4 : 0);
+ if (amt < (offset + 24)) {
+ ALOGV("Dropping packet, too short to contain TRTP Timestamp"
+ " Transformation (%u bytes)",
+ static_cast<uint32_t>(amt));
+ goto process_next_packet;
+ }
+
+ trans.a_zero = fetchInt64(data + offset);
+ trans.b_zero = fetchInt64(data + offset + 16);
+ trans.a_to_b_numer = static_cast<int32_t>(
+ fetchInt32 (data + offset + 8));
+ trans.a_to_b_denom = U32_AT(data + offset + 12);
+ foundTrans = true;
+
+ uint32_t program_id = (ssrc >> 5) & 0x1F;
+ for (size_t i = 0; i < substreams_.size(); ++i) {
+ sp<Substream> iter = substreams_.valueAt(i);
+ CHECK(iter != NULL);
+
+ if (iter->getProgramID() == program_id) {
+ iter->processTSTransform(trans);
+ }
+ }
+ }
+
+ // Is this a command packet? If so, its not necessarily associate
+ // with one particular substream. Just give it to the command
+ // packet handler and then move on.
+ if (4 == payload_type) {
+ processCommandPacket(pb);
+ goto process_next_packet;
+ }
+ }
+
+ // If we got to here, then we are a normal packet. Find (or allocate)
+ // the substream we belong to and send the packet off to be processed.
+ substream = substreams_.valueFor(ssrc);
+ if (substream == NULL) {
+ substream = new Substream(ssrc, omx_);
+ if (substream == NULL) {
+ ALOGE("Failed to allocate substream for SSRC 0x%08x", ssrc);
+ goto process_next_packet;
+ }
+ substreams_.add(ssrc, substream);
+
+ if (foundTrans) {
+ substream->processTSTransform(trans);
+ }
+ }
+
+ CHECK(substream != NULL);
+
+ if (marker) {
+ // Start of a new TRTP payload for this substream. Extract the
+ // lower 32 bits of the timestamp and hand the buffer to the
+ // substream for processing.
+ uint32_t ts_lower = U32_AT(data + 4);
+ substream->processPayloadStart(data + 12, amt - 12, ts_lower);
+ } else {
+ // Continuation of an existing TRTP payload. Just hand it off to
+ // the substream for processing.
+ substream->processPayloadCont(data + 12, amt - 12);
+ }
+
+process_next_packet:
+ PacketBuffer::destroy(pb);
+ } // end of main processing while loop.
+}
+
+void AAH_RXPlayer::processCommandPacket(PacketBuffer* pb) {
+ CHECK(NULL != pb);
+
+ uint8_t* data = pb->data_;
+ ssize_t amt = pb->length_;
+
+ // verify that this packet meets the minimum length of a command packet
+ if (amt < 20) {
+ return;
+ }
+
+ uint8_t trtp_version = data[12];
+ uint8_t trtp_flags = data[13] & 0xF;
+
+ if (1 != trtp_version) {
+ ALOGV("Dropping packet, bad trtp version %hhu", trtp_version);
+ return;
+ }
+
+ // calculate the start of the command payload
+ ssize_t offset = 18;
+ if (trtp_flags & 0x01) {
+ // timestamp is present (4 bytes)
+ offset += 4;
+ }
+ if (trtp_flags & 0x02) {
+ // transform is present (24 bytes)
+ offset += 24;
+ }
+
+ // the packet must contain 2 bytes of command payload beyond the TRTP header
+ if (amt < offset + 2) {
+ return;
+ }
+
+ uint16_t command_id = U16_AT(data + offset);
+
+ switch (command_id) {
+ case TRTPControlPacket::kCommandNop:
+ break;
+
+ case TRTPControlPacket::kCommandEOS:
+ case TRTPControlPacket::kCommandFlush: {
+ uint16_t program_id = (U32_AT(data + 8) >> 5) & 0x1F;
+ ALOGI("*** %s flushing program_id=%d",
+ __PRETTY_FUNCTION__, program_id);
+
+ Vector<uint32_t> substreams_to_remove;
+ for (size_t i = 0; i < substreams_.size(); ++i) {
+ sp<Substream> iter = substreams_.valueAt(i);
+ if (iter->getProgramID() == program_id) {
+ iter->shutdown();
+ substreams_to_remove.add(iter->getSSRC());
+ }
+ }
+
+ for (size_t i = 0; i < substreams_to_remove.size(); ++i) {
+ substreams_.removeItem(substreams_to_remove[i]);
+ }
+ } break;
+ }
+}
+
+bool AAH_RXPlayer::processGaps() {
+ // Deal with the current gap situation. Specifically...
+ //
+ // 1) If a new gap has shown up, send a retransmit request to the
+ // transmitter.
+ // 2) If a gap we were working on has had a packet in the middle or at
+ // the end filled in, send another retransmit request for the begining
+ // portion of the gap. TRTP was designed for LANs where packet
+ // re-ordering is very unlikely; so see the middle or end of a gap
+ // filled in before the begining is an almost certain indication that
+ // a retransmission packet was also dropped.
+ // 3) If we have been working on a gap for a while and it still has not
+ // been filled in, send another retransmit request.
+ // 4) If the are no more gaps in the ring, clear the current_gap_status_
+ // flag to indicate that all is well again.
+
+ // Start by fetching the active gap status.
+ SeqNoGap gap;
+ bool send_retransmit_request = false;
+ bool ret_val = false;
+ GapStatus gap_status;
+ if (kGS_NoGap != (gap_status = ring_buffer_.fetchCurrentGap(&gap))) {
+ // Note: checking for a change in the end sequence number should cover
+ // moving on to an entirely new gap for case #1 as well as resending the
+ // begining of a gap range for case #2.
+ send_retransmit_request = (kGS_NoGap == current_gap_status_) ||
+ (current_gap_.end_seq_ != gap.end_seq_);
+
+ // If this is the same gap we have been working on, and it has timed
+ // out, then check to see if our substreams are about to underflow. If
+ // so, instead of sending another retransmit request, just give up on
+ // this gap and move on.
+ if (!send_retransmit_request &&
+ (kGS_NoGap != current_gap_status_) &&
+ (0 == computeNextGapRetransmitTimeout())) {
+
+ // If out current gap is the fast-start gap, don't bother to skip it
+ // because substreams look like the are about to underflow.
+ if ((kGS_FastStartGap != gap_status) ||
+ (current_gap_.end_seq_ != gap.end_seq_)) {
+ for (size_t i = 0; i < substreams_.size(); ++i) {
+ if (substreams_.valueAt(i)->isAboutToUnderflow()) {
+ ALOGV("About to underflow, giving up on gap [%hu, %hu]",
+ gap.start_seq_, gap.end_seq_);
+ ring_buffer_.processNAK();
+ current_gap_status_ = kGS_NoGap;
+ return true;
+ }
+ }
+ }
+
+ // Looks like no one is about to underflow. Just go ahead and send
+ // the request.
+ send_retransmit_request = true;
+ }
+ } else {
+ current_gap_status_ = kGS_NoGap;
+ }
+
+ if (send_retransmit_request) {
+ // If we have been working on a fast start, and it is still not filled
+ // in, even after the extended retransmit time out, give up and skip it.
+ // The system should fall back into its normal slow-start behavior.
+ if ((kGS_FastStartGap == current_gap_status_) &&
+ (current_gap_.end_seq_ == gap.end_seq_)) {
+ ALOGV("Fast start is taking forever; giving up.");
+ ring_buffer_.processNAK();
+ current_gap_status_ = kGS_NoGap;
+ return true;
+ }
+
+ // Send the request.
+ RetransRequest req;
+ uint32_t magic = (kGS_FastStartGap == gap_status)
+ ? kFastStartRequestMagic
+ : kRetransRequestMagic;
+ req.magic_ = htonl(magic);
+ req.mcast_ip_ = listen_addr_.sin_addr.s_addr;
+ req.mcast_port_ = listen_addr_.sin_port;
+ req.start_seq_ = htons(gap.start_seq_);
+ req.end_seq_ = htons(gap.end_seq_);
+
+ {
+ uint32_t a = ntohl(transmitter_addr_.sin_addr.s_addr);
+ uint16_t p = ntohs(transmitter_addr_.sin_port);
+ ALOGV("Sending to transmitter %u.%u.%u.%u:%hu",
+ ((a >> 24) & 0xFF),
+ ((a >> 16) & 0xFF),
+ ((a >> 8) & 0xFF),
+ ( a & 0xFF),
+ p);
+ }
+
+ int res = sendto(sock_fd_, &req, sizeof(req), 0,
+ reinterpret_cast<struct sockaddr*>(&transmitter_addr_),
+ sizeof(transmitter_addr_));
+ if (res < 0) {
+ ALOGE("Error when sending retransmit request (%d)", errno);
+ } else {
+ ALOGV("%s request for range [%hu, %hu] sent",
+ (kGS_FastStartGap == gap_status) ? "Fast Start"
+ : "Retransmit",
+ gap.start_seq_, gap.end_seq_);
+ }
+
+ // Update the current gap info.
+ current_gap_ = gap;
+ current_gap_status_ = gap_status;
+ next_retrans_req_time_ = monotonicUSecNow() +
+ ((kGS_FastStartGap == current_gap_status_)
+ ? kFastStartTimeoutUSec
+ : kGapRerequestTimeoutUSec);
+ }
+
+ return false;
+}
+
+// Compute when its time to send the next gap retransmission in milliseconds.
+// Returns < 0 for an infinite timeout (no gap) and 0 if its time to retransmit
+// right now.
+int AAH_RXPlayer::computeNextGapRetransmitTimeout() {
+ if (kGS_NoGap == current_gap_status_) {
+ return -1;
+ }
+
+ int64_t timeout_delta = next_retrans_req_time_ - monotonicUSecNow();
+
+ timeout_delta /= 1000;
+ if (timeout_delta <= 0) {
+ return 0;
+ }
+
+ return static_cast<uint32_t>(timeout_delta);
+}
+
+} // namespace android
diff --git a/media/libaah_rtp/aah_rx_player_ring_buffer.cpp b/media/libaah_rtp/aah_rx_player_ring_buffer.cpp
new file mode 100644
index 0000000..779405e
--- /dev/null
+++ b/media/libaah_rtp/aah_rx_player_ring_buffer.cpp
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "LibAAH_RTP"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "aah_rx_player.h"
+
+namespace android {
+
+AAH_RXPlayer::RXRingBuffer::RXRingBuffer(uint32_t capacity) {
+ capacity_ = capacity;
+ rd_ = wr_ = 0;
+ ring_ = new PacketBuffer*[capacity];
+ memset(ring_, 0, sizeof(PacketBuffer*) * capacity);
+ reset();
+}
+
+AAH_RXPlayer::RXRingBuffer::~RXRingBuffer() {
+ reset();
+ delete[] ring_;
+}
+
+void AAH_RXPlayer::RXRingBuffer::reset() {
+ AutoMutex lock(&lock_);
+
+ if (NULL != ring_) {
+ while (rd_ != wr_) {
+ CHECK(rd_ < capacity_);
+ if (NULL != ring_[rd_]) {
+ PacketBuffer::destroy(ring_[rd_]);
+ ring_[rd_] = NULL;
+ }
+ rd_ = (rd_ + 1) % capacity_;
+ }
+ }
+
+ rd_ = wr_ = 0;
+ rd_seq_known_ = false;
+ waiting_for_fast_start_ = true;
+ fetched_first_packet_ = false;
+ rtp_activity_timeout_valid_ = false;
+}
+
+bool AAH_RXPlayer::RXRingBuffer::pushBuffer(PacketBuffer* buf,
+ uint16_t seq) {
+ AutoMutex lock(&lock_);
+ CHECK(NULL != ring_);
+ CHECK(NULL != buf);
+
+ rtp_activity_timeout_valid_ = true;
+ rtp_activity_timeout_ = monotonicUSecNow() + kRTPActivityTimeoutUSec;
+
+ // If the ring buffer is totally reset (we have never received a single
+ // payload) then we don't know the rd sequence number and this should be
+ // simple. We just store the payload, advance the wr pointer and record the
+ // initial sequence number.
+ if (!rd_seq_known_) {
+ CHECK(rd_ == wr_);
+ CHECK(NULL == ring_[wr_]);
+ CHECK(wr_ < capacity_);
+
+ ring_[wr_] = buf;
+ wr_ = (wr_ + 1) % capacity_;
+ rd_seq_ = seq;
+ rd_seq_known_ = true;
+ return true;
+ }
+
+ // Compute the seqence number of this payload and of the write pointer,
+ // normalized around the read pointer. IOW - transform the payload seq no
+ // and the wr pointer seq no into a space where the rd pointer seq no is
+ // zero. This will define 4 cases we can consider...
+ //
+ // 1) norm_seq == norm_wr_seq
+ // This payload is contiguous with the last. All is good.
+ //
+ // 2) ((norm_seq < norm_wr_seq) && (norm_seq >= norm_rd_seq)
+ // aka ((norm_seq < norm_wr_seq) && (norm_seq >= 0)
+ // This payload is in the past, in the unprocessed region of the ring
+ // buffer. It is probably a retransmit intended to fill in a dropped
+ // payload; it may be a duplicate.
+ //
+ // 3) ((norm_seq - norm_wr_seq) & 0x8000) != 0
+ // This payload is in the past compared to the write pointer (or so very
+ // far in the future that it has wrapped the seq no space), but not in
+ // the unprocessed region of the ring buffer. This could be a duplicate
+ // retransmit; we just drop these payloads unless we are waiting for our
+ // first fast start packet. If we are waiting for fast start, than this
+ // packet is probably the first packet of the fast start retransmission.
+ // If it will fit in the buffer, back up the read pointer to its position
+ // and clear the fast start flag, otherwise just drop it.
+ //
+ // 4) ((norm_seq - norm_wr_seq) & 0x8000) == 0
+ // This payload which is ahead of the next write pointer. This indicates
+ // that we have missed some payloads and need to request a retransmit.
+ // If norm_seq >= (capacity - 1), then the gap is so large that it would
+ // overflow the ring buffer and we should probably start to panic.
+
+ uint16_t norm_wr_seq = ((wr_ + capacity_ - rd_) % capacity_);
+ uint16_t norm_seq = seq - rd_seq_;
+
+ // Check for overflow first.
+ if ((!(norm_seq & 0x8000)) && (norm_seq >= (capacity_ - 1))) {
+ ALOGW("Ring buffer overflow; cap = %u, [rd, wr] = [%hu, %hu],"
+ " seq = %hu", capacity_, rd_seq_, norm_wr_seq + rd_seq_, seq);
+ PacketBuffer::destroy(buf);
+ return false;
+ }
+
+ // Check for case #1
+ if (norm_seq == norm_wr_seq) {
+ CHECK(wr_ < capacity_);
+ CHECK(NULL == ring_[wr_]);
+
+ ring_[wr_] = buf;
+ wr_ = (wr_ + 1) % capacity_;
+
+ CHECK(wr_ != rd_);
+ return true;
+ }
+
+ // Check case #2
+ uint32_t ring_pos = (rd_ + norm_seq) % capacity_;
+ if ((norm_seq < norm_wr_seq) && (!(norm_seq & 0x8000))) {
+ // Do we already have a payload for this slot? If so, then this looks
+ // like a duplicate retransmit. Just ignore it.
+ if (NULL != ring_[ring_pos]) {
+ ALOGD("RXed duplicate retransmit, seq = %hu", seq);
+ PacketBuffer::destroy(buf);
+ } else {
+ // Looks like we were missing this payload. Go ahead and store it.
+ ring_[ring_pos] = buf;
+ }
+
+ return true;
+ }
+
+ // Check case #3
+ if ((norm_seq - norm_wr_seq) & 0x8000) {
+ if (!waiting_for_fast_start_) {
+ ALOGD("RXed duplicate retransmit from before rd pointer, seq = %hu",
+ seq);
+ PacketBuffer::destroy(buf);
+ } else {
+ // Looks like a fast start fill-in. Go ahead and store it, assuming
+ // that we can fit it in the buffer.
+ uint32_t implied_ring_size = static_cast<uint32_t>(norm_wr_seq)
+ + (rd_seq_ - seq);
+
+ if (implied_ring_size >= (capacity_ - 1)) {
+ ALOGD("RXed what looks like a fast start packet (seq = %hu),"
+ " but packet is too far in the past to fit into the ring"
+ " buffer. Dropping.", seq);
+ PacketBuffer::destroy(buf);
+ } else {
+ ring_pos = (rd_ + capacity_ + seq - rd_seq_) % capacity_;
+ rd_seq_ = seq;
+ rd_ = ring_pos;
+ waiting_for_fast_start_ = false;
+
+ CHECK(ring_pos < capacity_);
+ CHECK(NULL == ring_[ring_pos]);
+ ring_[ring_pos] = buf;
+ }
+
+ }
+ return true;
+ }
+
+ // Must be in case #4 with no overflow. This packet fits in the current
+ // ring buffer, but is discontiuguous. Advance the write pointer leaving a
+ // gap behind.
+ uint32_t gap_len = (ring_pos + capacity_ - wr_) % capacity_;
+ ALOGD("Drop detected; %u packets, seq_range [%hu, %hu]",
+ gap_len,
+ rd_seq_ + norm_wr_seq,
+ rd_seq_ + norm_wr_seq + gap_len - 1);
+
+ CHECK(NULL == ring_[ring_pos]);
+ ring_[ring_pos] = buf;
+ wr_ = (ring_pos + 1) % capacity_;
+ CHECK(wr_ != rd_);
+
+ return true;
+}
+
+AAH_RXPlayer::PacketBuffer*
+AAH_RXPlayer::RXRingBuffer::fetchBuffer(bool* is_discon) {
+ AutoMutex lock(&lock_);
+ CHECK(NULL != ring_);
+ CHECK(NULL != is_discon);
+
+ // If the read seqence number is not known, then this ring buffer has not
+ // received a packet since being reset and there cannot be any packets to
+ // return. If we are still waiting for the first fast start packet to show
+ // up, we don't want to let any buffer be consumed yet because we expect to
+ // see a packet before the initial read sequence number show up shortly.
+ if (!rd_seq_known_ || waiting_for_fast_start_) {
+ *is_discon = false;
+ return NULL;
+ }
+
+ PacketBuffer* ret = NULL;
+ *is_discon = !fetched_first_packet_;
+
+ while ((rd_ != wr_) && (NULL == ret)) {
+ CHECK(rd_ < capacity_);
+
+ // If we hit a gap, stall and do not advance the read pointer. Let the
+ // higher level code deal with requesting retries and/or deciding to
+ // skip the current gap.
+ ret = ring_[rd_];
+ if (NULL == ret) {
+ break;
+ }
+
+ ring_[rd_] = NULL;
+ rd_ = (rd_ + 1) % capacity_;
+ ++rd_seq_;
+ }
+
+ if (NULL != ret) {
+ fetched_first_packet_ = true;
+ }
+
+ return ret;
+}
+
+AAH_RXPlayer::GapStatus
+AAH_RXPlayer::RXRingBuffer::fetchCurrentGap(SeqNoGap* gap) {
+ AutoMutex lock(&lock_);
+ CHECK(NULL != ring_);
+ CHECK(NULL != gap);
+
+ // If the read seqence number is not known, then this ring buffer has not
+ // received a packet since being reset and there cannot be any gaps.
+ if (!rd_seq_known_) {
+ return kGS_NoGap;
+ }
+
+ // If we are waiting for fast start, then the current gap is a fast start
+ // gap and it includes all packets before the read sequence number.
+ if (waiting_for_fast_start_) {
+ gap->start_seq_ =
+ gap->end_seq_ = rd_seq_ - 1;
+ return kGS_FastStartGap;
+ }
+
+ // If rd == wr, then the buffer is empty and there cannot be any gaps.
+ if (rd_ == wr_) {
+ return kGS_NoGap;
+ }
+
+ // If rd_ is currently pointing at an unprocessed packet, then there is no
+ // current gap.
+ CHECK(rd_ < capacity_);
+ if (NULL != ring_[rd_]) {
+ return kGS_NoGap;
+ }
+
+ // Looks like there must be a gap here. The start of the gap is the current
+ // rd sequence number, all we need to do now is determine its length in
+ // order to compute the end sequence number.
+ gap->start_seq_ = rd_seq_;
+ uint16_t end = rd_seq_;
+ uint32_t tmp = (rd_ + 1) % capacity_;
+ while ((tmp != wr_) && (NULL == ring_[tmp])) {
+ ++end;
+ tmp = (tmp + 1) % capacity_;
+ }
+ gap->end_seq_ = end;
+
+ return kGS_NormalGap;
+}
+
+void AAH_RXPlayer::RXRingBuffer::processNAK(const SeqNoGap* nak) {
+ AutoMutex lock(&lock_);
+ CHECK(NULL != ring_);
+
+ // If we were waiting for our first fast start fill-in packet, and we
+ // received a NAK, then apparantly we are not getting our fast start. Just
+ // clear the waiting flag and go back to normal behavior.
+ if (waiting_for_fast_start_) {
+ waiting_for_fast_start_ = false;
+ }
+
+ // If we have not received a packet since last reset, or there is no data in
+ // the ring, then there is nothing to skip.
+ if ((!rd_seq_known_) || (rd_ == wr_)) {
+ return;
+ }
+
+ // If rd_ is currently pointing at an unprocessed packet, then there is no
+ // gap to skip.
+ CHECK(rd_ < capacity_);
+ if (NULL != ring_[rd_]) {
+ return;
+ }
+
+ // Looks like there must be a gap here. Advance rd until we have passed
+ // over the portion of it indicated by nak (or all of the gap if nak is
+ // NULL). Then reset fetched_first_packet_ so that the next read will show
+ // up as being discontiguous.
+ uint16_t seq_after_gap = (NULL == nak) ? 0 : nak->end_seq_ + 1;
+ while ((rd_ != wr_) &&
+ (NULL == ring_[rd_]) &&
+ ((NULL == nak) || (seq_after_gap != rd_seq_))) {
+ rd_ = (rd_ + 1) % capacity_;
+ ++rd_seq_;
+ }
+ fetched_first_packet_ = false;
+}
+
+int AAH_RXPlayer::RXRingBuffer::computeInactivityTimeout() {
+ AutoMutex lock(&lock_);
+
+ if (!rtp_activity_timeout_valid_) {
+ return -1;
+ }
+
+ uint64_t now = monotonicUSecNow();
+ if (rtp_activity_timeout_ <= now) {
+ return 0;
+ }
+
+ return (rtp_activity_timeout_ - now) / 1000;
+}
+
+AAH_RXPlayer::PacketBuffer*
+AAH_RXPlayer::PacketBuffer::allocate(ssize_t length) {
+ if (length <= 0) {
+ return NULL;
+ }
+
+ uint32_t alloc_len = sizeof(PacketBuffer) + length;
+ PacketBuffer* ret = reinterpret_cast<PacketBuffer*>(
+ new uint8_t[alloc_len]);
+
+ if (NULL != ret) {
+ ret->length_ = length;
+ }
+
+ return ret;
+}
+
+void AAH_RXPlayer::PacketBuffer::destroy(PacketBuffer* pb) {
+ uint8_t* kill_me = reinterpret_cast<uint8_t*>(pb);
+ delete[] kill_me;
+}
+
+} // namespace android
diff --git a/media/libaah_rtp/aah_rx_player_substream.cpp b/media/libaah_rtp/aah_rx_player_substream.cpp
new file mode 100644
index 0000000..18b0e2b
--- /dev/null
+++ b/media/libaah_rtp/aah_rx_player_substream.cpp
@@ -0,0 +1,677 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "LibAAH_RTP"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+
+#include <include/avc_utils.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/Utils.h>
+
+#include "aah_rx_player.h"
+#include "aah_tx_packet.h"
+
+inline uint32_t min(uint32_t a, uint32_t b) {
+ return (a < b ? a : b);
+}
+
+namespace android {
+
+int64_t AAH_RXPlayer::Substream::kAboutToUnderflowThreshold =
+ 50ull * 1000;
+
+AAH_RXPlayer::Substream::Substream(uint32_t ssrc, OMXClient& omx) {
+ ssrc_ = ssrc;
+ substream_details_known_ = false;
+ buffer_in_progress_ = NULL;
+ status_ = OK;
+ codec_mime_type_ = "";
+
+ decoder_ = new AAH_DecoderPump(omx);
+ if (decoder_ == NULL) {
+ ALOGE("%s failed to allocate decoder pump!", __PRETTY_FUNCTION__);
+ }
+ if (OK != decoder_->initCheck()) {
+ ALOGE("%s failed to initialize decoder pump!", __PRETTY_FUNCTION__);
+ }
+
+ // cleanupBufferInProgress will reset most of the internal state variables.
+ // Just need to make sure that buffer_in_progress_ is NULL before calling.
+ cleanupBufferInProgress();
+}
+
+AAH_RXPlayer::Substream::~Substream() {
+ shutdown();
+}
+
+void AAH_RXPlayer::Substream::shutdown() {
+ substream_meta_ = NULL;
+ status_ = OK;
+ cleanupBufferInProgress();
+ cleanupDecoder();
+}
+
+void AAH_RXPlayer::Substream::cleanupBufferInProgress() {
+ if (NULL != buffer_in_progress_) {
+ buffer_in_progress_->release();
+ buffer_in_progress_ = NULL;
+ }
+
+ expected_buffer_size_ = 0;
+ buffer_filled_ = 0;
+ waiting_for_rap_ = true;
+
+ aux_data_in_progress_.clear();
+ aux_data_expected_size_ = 0;
+}
+
+void AAH_RXPlayer::Substream::cleanupDecoder() {
+ if (decoder_ != NULL) {
+ decoder_->shutdown();
+ }
+}
+
+bool AAH_RXPlayer::Substream::shouldAbort(const char* log_tag) {
+ // If we have already encountered a fatal error, do nothing. We are just
+ // waiting for our owner to shut us down now.
+ if (OK != status_) {
+ ALOGV("Skipping %s, substream has encountered fatal error (%d).",
+ log_tag, status_);
+ return true;
+ }
+
+ return false;
+}
+
+void AAH_RXPlayer::Substream::processPayloadStart(uint8_t* buf,
+ uint32_t amt,
+ int32_t ts_lower) {
+ uint32_t min_length = 6;
+
+ if (shouldAbort(__PRETTY_FUNCTION__)) {
+ return;
+ }
+
+ // Do we have a buffer in progress already? If so, abort the buffer. In
+ // theory, this should never happen. If there were a discontinutity in the
+ // stream, the discon in the seq_nos at the RTP level should have already
+ // triggered a cleanup of the buffer in progress. To see a problem at this
+ // level is an indication either of a bug in the transmitter, or some form
+ // of terrible corruption/tampering on the wire.
+ if (NULL != buffer_in_progress_) {
+ ALOGE("processPayloadStart is aborting payload already in progress.");
+ cleanupBufferInProgress();
+ }
+
+ // Parse enough of the header to know where we stand. Since this is a
+ // payload start, it should begin with a TRTP header which has to be at
+ // least 6 bytes long.
+ if (amt < min_length) {
+ ALOGV("Discarding payload too short to contain TRTP header (len = %u)",
+ amt);
+ return;
+ }
+
+ // Check the TRTP version number.
+ if (0x01 != buf[0]) {
+ ALOGV("Unexpected TRTP version (%u) in header. Expected %u.",
+ buf[0], 1);
+ return;
+ }
+
+ // Extract the substream type field and make sure its one we understand (and
+ // one that does not conflict with any previously received substream type.
+ uint8_t header_type = (buf[1] >> 4) & 0xF;
+ switch (header_type) {
+ case TRTPPacket::kHeaderTypeAudio:
+ // Audio, yay! Just break. We understand audio payloads.
+ break;
+ case TRTPPacket::kHeaderTypeVideo:
+ ALOGV("RXed packet with unhandled TRTP header type (Video).");
+ return;
+ case TRTPPacket::kHeaderTypeSubpicture:
+ ALOGV("RXed packet with unhandled TRTP header type (Subpicture).");
+ return;
+ case TRTPPacket::kHeaderTypeControl:
+ ALOGV("RXed packet with unhandled TRTP header type (Control).");
+ return;
+ default:
+ ALOGV("RXed packet with unhandled TRTP header type (%u).",
+ header_type);
+ return;
+ }
+
+ if (substream_details_known_ && (header_type != substream_type_)) {
+ ALOGV("RXed TRTP Payload for SSRC=0x%08x where header type (%u) does"
+ " not match previously received header type (%u)",
+ ssrc_, header_type, substream_type_);
+ return;
+ }
+
+ // Check the flags to see if there is another 32 bits of timestamp present.
+ uint32_t trtp_header_len = 6;
+ bool ts_valid = buf[1] & TRTPPacket::kFlag_TSValid;
+ if (ts_valid) {
+ min_length += 4;
+ trtp_header_len += 4;
+ if (amt < min_length) {
+ ALOGV("Discarding payload too short to contain TRTP timestamp"
+ " (len = %u)", amt);
+ return;
+ }
+ }
+
+ // Extract the TRTP length field and sanity check it.
+ uint32_t trtp_len = U32_AT(buf + 2);
+ if (trtp_len < min_length) {
+ ALOGV("TRTP length (%u) is too short to be valid. Must be at least %u"
+ " bytes.", trtp_len, min_length);
+ return;
+ }
+
+ // Extract the rest of the timestamp field if valid.
+ int64_t ts = 0;
+ uint32_t parse_offset = 6;
+ if (ts_valid) {
+ uint32_t ts_upper = U32_AT(buf + parse_offset);
+ parse_offset += 4;
+ ts = (static_cast<int64_t>(ts_upper) << 32) | ts_lower;
+ }
+
+ // Check the flags to see if there is another 24 bytes of timestamp
+ // transformation present.
+ if (buf[1] & TRTPPacket::kFlag_TSTransformPresent) {
+ min_length += 24;
+ parse_offset += 24;
+ trtp_header_len += 24;
+ if (amt < min_length) {
+ ALOGV("Discarding payload too short to contain TRTP timestamp"
+ " transformation (len = %u)", amt);
+ return;
+ }
+ }
+
+ // TODO : break the parsing into individual parsers for the different
+ // payload types (audio, video, etc).
+ //
+ // At this point in time, we know that this is audio. Go ahead and parse
+ // the basic header, check the codec type, and find the payload portion of
+ // the packet.
+ min_length += 3;
+ if (trtp_len < min_length) {
+ ALOGV("TRTP length (%u) is too short to be a valid audio payload. Must"
+ " be at least %u bytes.", trtp_len, min_length);
+ return;
+ }
+
+ if (amt < min_length) {
+ ALOGV("TRTP porttion of RTP payload (%u bytes) too small to contain"
+ " entire TRTP header. TRTP does not currently support"
+ " fragmenting TRTP headers across RTP payloads", amt);
+ return;
+ }
+
+ uint8_t codec_type = buf[parse_offset ];
+ uint8_t flags = buf[parse_offset + 1];
+ uint8_t volume = buf[parse_offset + 2];
+ parse_offset += 3;
+ trtp_header_len += 3;
+
+ if (!setupSubstreamType(header_type, codec_type)) {
+ return;
+ }
+
+ if (decoder_ != NULL) {
+ decoder_->setRenderVolume(volume);
+ }
+
+ if (waiting_for_rap_ && !(flags & TRTPAudioPacket::kFlag_RandomAccessPoint)) {
+ ALOGV("Dropping non-RAP TRTP Audio Payload while waiting for RAP.");
+ return;
+ }
+
+ // Check for the presence of codec aux data.
+ if (flags & TRTPAudioPacket::kFlag_AuxLengthPresent) {
+ min_length += 4;
+ trtp_header_len += 4;
+
+ if (trtp_len < min_length) {
+ ALOGV("TRTP length (%u) is too short to be a valid audio payload. "
+ "Must be at least %u bytes.", trtp_len, min_length);
+ return;
+ }
+
+ if (amt < min_length) {
+ ALOGV("TRTP porttion of RTP payload (%u bytes) too small to contain"
+ " entire TRTP header. TRTP does not currently support"
+ " fragmenting TRTP headers across RTP payloads", amt);
+ return;
+ }
+
+ aux_data_expected_size_ = U32_AT(buf + parse_offset);
+ aux_data_in_progress_.clear();
+ if (aux_data_in_progress_.capacity() < aux_data_expected_size_) {
+ aux_data_in_progress_.setCapacity(aux_data_expected_size_);
+ }
+ } else {
+ aux_data_expected_size_ = 0;
+ }
+
+ if ((aux_data_expected_size_ + trtp_header_len) > trtp_len) {
+ ALOGV("Expected codec aux data length (%u) and TRTP header overhead"
+ " (%u) too large for total TRTP payload length (%u).",
+ aux_data_expected_size_, trtp_header_len, trtp_len);
+ return;
+ }
+
+ // OK - everything left is just payload. Compute the payload size, start
+ // the buffer in progress and pack as much payload as we can into it. If
+ // the payload is finished once we are done, go ahead and send the payload
+ // to the decoder.
+ expected_buffer_size_ = trtp_len
+ - trtp_header_len
+ - aux_data_expected_size_;
+ if (!expected_buffer_size_) {
+ ALOGV("Dropping TRTP Audio Payload with 0 Access Unit length");
+ return;
+ }
+
+ CHECK(amt >= trtp_header_len);
+ uint32_t todo = amt - trtp_header_len;
+ if ((expected_buffer_size_ + aux_data_expected_size_) < todo) {
+ ALOGV("Extra data (%u > %u) present in initial TRTP Audio Payload;"
+ " dropping payload.", todo,
+ expected_buffer_size_ + aux_data_expected_size_);
+ return;
+ }
+
+ buffer_filled_ = 0;
+ buffer_in_progress_ = new MediaBuffer(expected_buffer_size_);
+ if ((NULL == buffer_in_progress_) ||
+ (NULL == buffer_in_progress_->data())) {
+ ALOGV("Failed to allocate MediaBuffer of length %u",
+ expected_buffer_size_);
+ cleanupBufferInProgress();
+ return;
+ }
+
+ sp<MetaData> meta = buffer_in_progress_->meta_data();
+ if (meta == NULL) {
+ ALOGV("Missing metadata structure in allocated MediaBuffer; dropping"
+ " payload");
+ cleanupBufferInProgress();
+ return;
+ }
+
+ meta->setCString(kKeyMIMEType, codec_mime_type_);
+ if (ts_valid) {
+ meta->setInt64(kKeyTime, ts);
+ }
+
+ // Skip over the header we have already extracted.
+ amt -= trtp_header_len;
+ buf += trtp_header_len;
+
+ // Extract as much of the expected aux data as we can.
+ todo = min(aux_data_expected_size_, amt);
+ if (todo) {
+ aux_data_in_progress_.appendArray(buf, todo);
+ buf += todo;
+ amt -= todo;
+ }
+
+ // Extract as much of the expected payload as we can.
+ todo = min(expected_buffer_size_, amt);
+ if (todo > 0) {
+ uint8_t* tgt =
+ reinterpret_cast<uint8_t*>(buffer_in_progress_->data());
+ memcpy(tgt, buf, todo);
+ buffer_filled_ = amt;
+ buf += todo;
+ amt -= todo;
+ }
+
+ if (buffer_filled_ >= expected_buffer_size_) {
+ processCompletedBuffer();
+ }
+}
+
+void AAH_RXPlayer::Substream::processPayloadCont(uint8_t* buf,
+ uint32_t amt) {
+ if (shouldAbort(__PRETTY_FUNCTION__)) {
+ return;
+ }
+
+ if (NULL == buffer_in_progress_) {
+ ALOGV("TRTP Receiver skipping payload continuation; no buffer currently"
+ " in progress.");
+ return;
+ }
+
+ CHECK(aux_data_in_progress_.size() <= aux_data_expected_size_);
+ uint32_t aux_left = aux_data_expected_size_ - aux_data_in_progress_.size();
+ if (aux_left) {
+ uint32_t todo = min(aux_left, amt);
+ aux_data_in_progress_.appendArray(buf, todo);
+ amt -= todo;
+ buf += todo;
+
+ if (!amt)
+ return;
+ }
+
+ CHECK(buffer_filled_ < expected_buffer_size_);
+ uint32_t buffer_left = expected_buffer_size_ - buffer_filled_;
+ if (amt > buffer_left) {
+ ALOGV("Extra data (%u > %u) present in continued TRTP Audio Payload;"
+ " dropping payload.", amt, buffer_left);
+ cleanupBufferInProgress();
+ return;
+ }
+
+ if (amt > 0) {
+ uint8_t* tgt =
+ reinterpret_cast<uint8_t*>(buffer_in_progress_->data());
+ memcpy(tgt + buffer_filled_, buf, amt);
+ buffer_filled_ += amt;
+ }
+
+ if (buffer_filled_ >= expected_buffer_size_) {
+ processCompletedBuffer();
+ }
+}
+
+void AAH_RXPlayer::Substream::processCompletedBuffer() {
+ status_t res;
+
+ CHECK(NULL != buffer_in_progress_);
+
+ if (decoder_ == NULL) {
+ ALOGV("Dropping complete buffer, no decoder pump allocated");
+ goto bailout;
+ }
+
+ // Make sure our metadata used to initialize the decoder has been properly
+ // set up.
+ if (!setupSubstreamMeta())
+ goto bailout;
+
+ // If our decoder has not be set up, do so now.
+ res = decoder_->init(substream_meta_);
+ if (OK != res) {
+ ALOGE("Failed to init decoder (res = %d)", res);
+ cleanupDecoder();
+ substream_meta_ = NULL;
+ goto bailout;
+ }
+
+ // Queue the payload for decode.
+ res = decoder_->queueForDecode(buffer_in_progress_);
+
+ if (res != OK) {
+ ALOGD("Failed to queue payload for decode, resetting decoder pump!"
+ " (res = %d)", res);
+ status_ = res;
+ cleanupDecoder();
+ cleanupBufferInProgress();
+ }
+
+ // NULL out buffer_in_progress before calling the cleanup helper.
+ //
+ // MediaBuffers use something of a hybrid ref-counting pattern which prevent
+ // the AAH_DecoderPump's input queue from adding their own reference to the
+ // MediaBuffer. MediaBuffers start life with a reference count of 0, as
+ // well as an observer which starts as NULL. Before being given an
+ // observer, the ref count cannot be allowed to become non-zero as it will
+ // cause calls to release() to assert. Basically, before a MediaBuffer has
+ // an observer, they behave like non-ref counted obects where release()
+ // serves the roll of delete. After a MediaBuffer has an observer, they
+ // become more like ref counted objects where add ref and release can be
+ // used, and when the ref count hits zero, the MediaBuffer is handed off to
+ // the observer.
+ //
+ // Given all of this, when we give the buffer to the decoder pump to wait in
+ // the to-be-processed queue, the decoder cannot add a ref to the buffer as
+ // it would in a traditional ref counting system. Instead it needs to
+ // "steal" the non-existent ref. In the case of queue failure, we need to
+ // make certain to release this non-existent reference so that the buffer is
+ // cleaned up during the cleanupBufferInProgress helper. In the case of a
+ // successful queue operation, we need to make certain that the
+ // cleanupBufferInProgress helper does not release the buffer since it needs
+ // to remain alive in the queue. We acomplish this by NULLing out the
+ // buffer pointer before calling the cleanup helper.
+ buffer_in_progress_ = NULL;
+
+bailout:
+ cleanupBufferInProgress();
+}
+
+bool AAH_RXPlayer::Substream::setupSubstreamMeta() {
+ switch (codec_type_) {
+ case TRTPAudioPacket::kCodecMPEG1Audio:
+ codec_mime_type_ = MEDIA_MIMETYPE_AUDIO_MPEG;
+ return setupMP3SubstreamMeta();
+
+ case TRTPAudioPacket::kCodecAACAudio:
+ codec_mime_type_ = MEDIA_MIMETYPE_AUDIO_AAC;
+ return setupAACSubstreamMeta();
+
+ default:
+ ALOGV("Failed to setup substream metadata for unsupported codec"
+ " type (%u)", codec_type_);
+ break;
+ }
+
+ return false;
+}
+
+bool AAH_RXPlayer::Substream::setupMP3SubstreamMeta() {
+ const uint8_t* buffer_data = NULL;
+ int sample_rate;
+ int channel_count;
+ size_t frame_size;
+ status_t res;
+
+ buffer_data = reinterpret_cast<const uint8_t*>(buffer_in_progress_->data());
+ if (buffer_in_progress_->size() < 4) {
+ ALOGV("MP3 payload too short to contain header, dropping payload.");
+ return false;
+ }
+
+ // Extract the channel count and the sample rate from the MP3 header. The
+ // stagefright MP3 requires that these be delivered before decoing can
+ // begin.
+ if (!GetMPEGAudioFrameSize(U32_AT(buffer_data),
+ &frame_size,
+ &sample_rate,
+ &channel_count,
+ NULL,
+ NULL)) {
+ ALOGV("Failed to parse MP3 header in payload, droping payload.");
+ return false;
+ }
+
+
+ // Make sure that our substream metadata is set up properly. If there has
+ // been a format change, be sure to reset the underlying decoder. In
+ // stagefright, it seems like the only way to do this is to destroy and
+ // recreate the decoder.
+ if (substream_meta_ == NULL) {
+ substream_meta_ = new MetaData();
+
+ if (substream_meta_ == NULL) {
+ ALOGE("Failed to allocate MetaData structure for MP3 substream");
+ return false;
+ }
+
+ substream_meta_->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+ substream_meta_->setInt32 (kKeyChannelCount, channel_count);
+ substream_meta_->setInt32 (kKeySampleRate, sample_rate);
+ } else {
+ int32_t prev_sample_rate;
+ int32_t prev_channel_count;
+ substream_meta_->findInt32(kKeySampleRate, &prev_sample_rate);
+ substream_meta_->findInt32(kKeyChannelCount, &prev_channel_count);
+
+ if ((prev_channel_count != channel_count) ||
+ (prev_sample_rate != sample_rate)) {
+ ALOGW("MP3 format change detected, forcing decoder reset.");
+ cleanupDecoder();
+
+ substream_meta_->setInt32(kKeyChannelCount, channel_count);
+ substream_meta_->setInt32(kKeySampleRate, sample_rate);
+ }
+ }
+
+ return true;
+}
+
+bool AAH_RXPlayer::Substream::setupAACSubstreamMeta() {
+ int32_t sample_rate, channel_cnt;
+ static const size_t overhead = sizeof(sample_rate)
+ + sizeof(channel_cnt);
+
+ if (aux_data_in_progress_.size() < overhead) {
+ ALOGE("Not enough aux data (%u) to initialize AAC substream decoder",
+ aux_data_in_progress_.size());
+ return false;
+ }
+
+ const uint8_t* aux_data = aux_data_in_progress_.array();
+ size_t aux_data_size = aux_data_in_progress_.size();
+ sample_rate = U32_AT(aux_data);
+ channel_cnt = U32_AT(aux_data + sizeof(sample_rate));
+
+ const uint8_t* esds_data = NULL;
+ size_t esds_data_size = 0;
+ if (aux_data_size > overhead) {
+ esds_data = aux_data + overhead;
+ esds_data_size = aux_data_size - overhead;
+ }
+
+ // Do we already have metadata? If so, has it changed at all? If not, then
+ // there should be nothing else to do. Otherwise, release our old stream
+ // metadata and make new metadata.
+ if (substream_meta_ != NULL) {
+ uint32_t type;
+ const void* data;
+ size_t size;
+ int32_t prev_sample_rate;
+ int32_t prev_channel_count;
+ bool res;
+
+ res = substream_meta_->findInt32(kKeySampleRate, &prev_sample_rate);
+ CHECK(res);
+ res = substream_meta_->findInt32(kKeyChannelCount, &prev_channel_count);
+ CHECK(res);
+
+ // If nothing has changed about the codec aux data (esds, sample rate,
+ // channel count), then we can just do nothing and get out. Otherwise,
+ // we will need to reset the decoder and make a new metadata object to
+ // deal with the format change.
+ bool hasData = (esds_data != NULL);
+ bool hadData = substream_meta_->findData(kKeyESDS, &type, &data, &size);
+ bool esds_change = (hadData != hasData);
+
+ if (!esds_change && hasData)
+ esds_change = ((size != esds_data_size) ||
+ memcmp(data, esds_data, size));
+
+ if (!esds_change &&
+ (prev_sample_rate == sample_rate) &&
+ (prev_channel_count == channel_cnt)) {
+ return true; // no change, just get out.
+ }
+
+ ALOGW("AAC format change detected, forcing decoder reset.");
+ cleanupDecoder();
+ substream_meta_ = NULL;
+ }
+
+ CHECK(substream_meta_ == NULL);
+
+ substream_meta_ = new MetaData();
+ if (substream_meta_ == NULL) {
+ ALOGE("Failed to allocate MetaData structure for AAC substream");
+ return false;
+ }
+
+ substream_meta_->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+ substream_meta_->setInt32 (kKeySampleRate, sample_rate);
+ substream_meta_->setInt32 (kKeyChannelCount, channel_cnt);
+
+ if (esds_data) {
+ substream_meta_->setData(kKeyESDS, kTypeESDS,
+ esds_data, esds_data_size);
+ }
+
+ return true;
+}
+
+void AAH_RXPlayer::Substream::processTSTransform(const LinearTransform& trans) {
+ if (decoder_ != NULL) {
+ decoder_->setRenderTSTransform(trans);
+ }
+}
+
+bool AAH_RXPlayer::Substream::isAboutToUnderflow() {
+ if (decoder_ == NULL) {
+ return false;
+ }
+
+ return decoder_->isAboutToUnderflow(kAboutToUnderflowThreshold);
+}
+
+bool AAH_RXPlayer::Substream::setupSubstreamType(uint8_t substream_type,
+ uint8_t codec_type) {
+ // Sanity check the codec type. Right now we only support MP3 and AAC.
+ // Also check for conflicts with previously delivered codec types.
+ if (substream_details_known_) {
+ if (codec_type != codec_type_) {
+ ALOGV("RXed TRTP Payload for SSRC=0x%08x where codec type (%u) does"
+ " not match previously received codec type (%u)",
+ ssrc_, codec_type, codec_type_);
+ return false;
+ }
+
+ return true;
+ }
+
+ switch (codec_type) {
+ // MP3 and AAC are all we support right now.
+ case TRTPAudioPacket::kCodecMPEG1Audio:
+ case TRTPAudioPacket::kCodecAACAudio:
+ break;
+
+ default:
+ ALOGV("RXed TRTP Audio Payload for SSRC=0x%08x with unsupported"
+ " codec type (%u)", ssrc_, codec_type);
+ return false;
+ }
+
+ substream_type_ = substream_type;
+ codec_type_ = codec_type;
+ substream_details_known_ = true;
+
+ return true;
+}
+
+} // namespace android
diff --git a/media/libaah_rtp/aah_tx_packet.cpp b/media/libaah_rtp/aah_tx_packet.cpp
new file mode 100644
index 0000000..4cd6e47
--- /dev/null
+++ b/media/libaah_rtp/aah_tx_packet.cpp
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "LibAAH_RTP"
+#include <utils/Log.h>
+
+#include <arpa/inet.h>
+#include <string.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+
+#include "aah_tx_packet.h"
+
+namespace android {
+
+const int TRTPPacket::kRTPHeaderLen;
+const uint32_t TRTPPacket::kTRTPEpochMask;
+
+TRTPPacket::~TRTPPacket() {
+ delete mPacket;
+}
+
+/*** TRTP packet properties ***/
+
+void TRTPPacket::setSeqNumber(uint16_t val) {
+ mSeqNumber = val;
+
+ if (mIsPacked) {
+ const int kTRTPSeqNumberOffset = 2;
+ uint16_t* buf = reinterpret_cast<uint16_t*>(
+ mPacket + kTRTPSeqNumberOffset);
+ *buf = htons(mSeqNumber);
+ }
+}
+
+uint16_t TRTPPacket::getSeqNumber() const {
+ return mSeqNumber;
+}
+
+void TRTPPacket::setPTS(int64_t val) {
+ CHECK(!mIsPacked);
+ mPTS = val;
+ mPTSValid = true;
+}
+
+int64_t TRTPPacket::getPTS() const {
+ return mPTS;
+}
+
+void TRTPPacket::setEpoch(uint32_t val) {
+ mEpoch = val;
+
+ if (mIsPacked) {
+ const int kTRTPEpochOffset = 8;
+ uint32_t* buf = reinterpret_cast<uint32_t*>(
+ mPacket + kTRTPEpochOffset);
+ uint32_t val = ntohl(*buf);
+ val &= ~(kTRTPEpochMask << kTRTPEpochShift);
+ val |= (mEpoch & kTRTPEpochMask) << kTRTPEpochShift;
+ *buf = htonl(val);
+ }
+}
+
+void TRTPPacket::setProgramID(uint16_t val) {
+ CHECK(!mIsPacked);
+ mProgramID = val;
+}
+
+void TRTPPacket::setSubstreamID(uint16_t val) {
+ CHECK(!mIsPacked);
+ mSubstreamID = val;
+}
+
+
+void TRTPPacket::setClockTransform(const LinearTransform& trans) {
+ CHECK(!mIsPacked);
+ mClockTranform = trans;
+ mClockTranformValid = true;
+}
+
+uint8_t* TRTPPacket::getPacket() const {
+ CHECK(mIsPacked);
+ return mPacket;
+}
+
+int TRTPPacket::getPacketLen() const {
+ CHECK(mIsPacked);
+ return mPacketLen;
+}
+
+void TRTPPacket::setExpireTime(nsecs_t val) {
+ CHECK(!mIsPacked);
+ mExpireTime = val;
+}
+
+nsecs_t TRTPPacket::getExpireTime() const {
+ return mExpireTime;
+}
+
+/*** TRTP audio packet properties ***/
+
+void TRTPAudioPacket::setCodecType(TRTPAudioCodecType val) {
+ CHECK(!mIsPacked);
+ mCodecType = val;
+}
+
+void TRTPAudioPacket::setRandomAccessPoint(bool val) {
+ CHECK(!mIsPacked);
+ mRandomAccessPoint = val;
+}
+
+void TRTPAudioPacket::setDropable(bool val) {
+ CHECK(!mIsPacked);
+ mDropable = val;
+}
+
+void TRTPAudioPacket::setDiscontinuity(bool val) {
+ CHECK(!mIsPacked);
+ mDiscontinuity = val;
+}
+
+void TRTPAudioPacket::setEndOfStream(bool val) {
+ CHECK(!mIsPacked);
+ mEndOfStream = val;
+}
+
+void TRTPAudioPacket::setVolume(uint8_t val) {
+ CHECK(!mIsPacked);
+ mVolume = val;
+}
+
+void TRTPAudioPacket::setAccessUnitData(const void* data, size_t len) {
+ CHECK(!mIsPacked);
+ mAccessUnitData = data;
+ mAccessUnitLen = len;
+}
+
+void TRTPAudioPacket::setAuxData(const void* data, size_t len) {
+ CHECK(!mIsPacked);
+ mAuxData = data;
+ mAuxDataLen = len;
+}
+
+/*** TRTP control packet properties ***/
+
+void TRTPControlPacket::setCommandID(TRTPCommandID val) {
+ CHECK(!mIsPacked);
+ mCommandID = val;
+}
+
+/*** TRTP packet serializers ***/
+
+void TRTPPacket::writeU8(uint8_t*& buf, uint8_t val) {
+ *buf = val;
+ buf++;
+}
+
+void TRTPPacket::writeU16(uint8_t*& buf, uint16_t val) {
+ *reinterpret_cast<uint16_t*>(buf) = htons(val);
+ buf += 2;
+}
+
+void TRTPPacket::writeU32(uint8_t*& buf, uint32_t val) {
+ *reinterpret_cast<uint32_t*>(buf) = htonl(val);
+ buf += 4;
+}
+
+void TRTPPacket::writeU64(uint8_t*& buf, uint64_t val) {
+ buf[0] = static_cast<uint8_t>(val >> 56);
+ buf[1] = static_cast<uint8_t>(val >> 48);
+ buf[2] = static_cast<uint8_t>(val >> 40);
+ buf[3] = static_cast<uint8_t>(val >> 32);
+ buf[4] = static_cast<uint8_t>(val >> 24);
+ buf[5] = static_cast<uint8_t>(val >> 16);
+ buf[6] = static_cast<uint8_t>(val >> 8);
+ buf[7] = static_cast<uint8_t>(val);
+ buf += 8;
+}
+
+void TRTPPacket::writeTRTPHeader(uint8_t*& buf,
+ bool isFirstFragment,
+ int totalPacketLen) {
+ // RTP header
+ writeU8(buf,
+ ((mVersion & 0x03) << 6) |
+ (static_cast<int>(mPadding) << 5) |
+ (static_cast<int>(mExtension) << 4) |
+ (mCsrcCount & 0x0F));
+ writeU8(buf,
+ (static_cast<int>(isFirstFragment) << 7) |
+ (mPayloadType & 0x7F));
+ writeU16(buf, mSeqNumber);
+ if (isFirstFragment && mPTSValid) {
+ writeU32(buf, mPTS & 0xFFFFFFFF);
+ } else {
+ writeU32(buf, 0);
+ }
+ writeU32(buf,
+ ((mEpoch & kTRTPEpochMask) << kTRTPEpochShift) |
+ ((mProgramID & 0x1F) << 5) |
+ (mSubstreamID & 0x1F));
+
+ // TRTP header
+ writeU8(buf, mTRTPVersion);
+ writeU8(buf,
+ ((mTRTPHeaderType & 0x0F) << 4) |
+ (mClockTranformValid ? 0x02 : 0x00) |
+ (mPTSValid ? 0x01 : 0x00));
+ writeU32(buf, totalPacketLen - kRTPHeaderLen);
+ if (mPTSValid) {
+ writeU32(buf, mPTS >> 32);
+ }
+
+ if (mClockTranformValid) {
+ writeU64(buf, mClockTranform.a_zero);
+ writeU32(buf, mClockTranform.a_to_b_numer);
+ writeU32(buf, mClockTranform.a_to_b_denom);
+ writeU64(buf, mClockTranform.b_zero);
+ }
+}
+
+bool TRTPAudioPacket::pack() {
+ if (mIsPacked) {
+ return false;
+ }
+
+ int packetLen = kRTPHeaderLen +
+ mAuxDataLen +
+ mAccessUnitLen +
+ TRTPHeaderLen();
+
+ // TODO : support multiple fragments
+ const int kMaxUDPPayloadLen = 65507;
+ if (packetLen > kMaxUDPPayloadLen) {
+ return false;
+ }
+
+ mPacket = new uint8_t[packetLen];
+ if (!mPacket) {
+ return false;
+ }
+
+ mPacketLen = packetLen;
+
+ uint8_t* cur = mPacket;
+ bool hasAux = mAuxData && mAuxDataLen;
+ uint8_t flags = (static_cast<int>(hasAux) << 4) |
+ (static_cast<int>(mRandomAccessPoint) << 3) |
+ (static_cast<int>(mDropable) << 2) |
+ (static_cast<int>(mDiscontinuity) << 1) |
+ (static_cast<int>(mEndOfStream));
+
+ writeTRTPHeader(cur, true, packetLen);
+ writeU8(cur, mCodecType);
+ writeU8(cur, flags);
+ writeU8(cur, mVolume);
+
+ if (hasAux) {
+ writeU32(cur, mAuxDataLen);
+ memcpy(cur, mAuxData, mAuxDataLen);
+ cur += mAuxDataLen;
+ }
+
+ memcpy(cur, mAccessUnitData, mAccessUnitLen);
+
+ mIsPacked = true;
+ return true;
+}
+
+int TRTPPacket::TRTPHeaderLen() const {
+ // 6 bytes for version, payload type, flags and length. An additional 4 if
+ // there are upper timestamp bits present and another 24 if there is a clock
+ // transformation present.
+ return 6 +
+ (mClockTranformValid ? 24 : 0) +
+ (mPTSValid ? 4 : 0);
+}
+
+int TRTPAudioPacket::TRTPHeaderLen() const {
+ // TRTPPacket::TRTPHeaderLen() for the base TRTPHeader. 3 bytes for audio's
+ // codec type, flags and volume field. Another 5 bytes if the codec type is
+ // PCM and we are sending sample rate/channel count. as well as however long
+ // the aux data (if present) is.
+
+ int pcmParamLength;
+ switch(mCodecType) {
+ case kCodecPCMBigEndian:
+ case kCodecPCMLittleEndian:
+ pcmParamLength = 5;
+ break;
+
+ default:
+ pcmParamLength = 0;
+ break;
+ }
+
+
+ int auxDataLenField = (NULL != mAuxData) ? sizeof(uint32_t) : 0;
+ return TRTPPacket::TRTPHeaderLen() +
+ 3 +
+ auxDataLenField +
+ pcmParamLength;
+}
+
+bool TRTPControlPacket::pack() {
+ if (mIsPacked) {
+ return false;
+ }
+
+ // command packets contain a 2-byte command ID
+ int packetLen = kRTPHeaderLen +
+ TRTPHeaderLen() +
+ 2;
+
+ mPacket = new uint8_t[packetLen];
+ if (!mPacket) {
+ return false;
+ }
+
+ mPacketLen = packetLen;
+
+ uint8_t* cur = mPacket;
+
+ writeTRTPHeader(cur, true, packetLen);
+ writeU16(cur, mCommandID);
+
+ mIsPacked = true;
+ return true;
+}
+
+} // namespace android
diff --git a/media/libaah_rtp/aah_tx_packet.h b/media/libaah_rtp/aah_tx_packet.h
new file mode 100644
index 0000000..7f78ea0
--- /dev/null
+++ b/media/libaah_rtp/aah_tx_packet.h
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 __AAH_TX_PACKET_H__
+#define __AAH_TX_PACKET_H__
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/LinearTransform.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+namespace android {
+
+class TRTPPacket : public RefBase {
+ public:
+ enum TRTPHeaderType {
+ kHeaderTypeAudio = 1,
+ kHeaderTypeVideo = 2,
+ kHeaderTypeSubpicture = 3,
+ kHeaderTypeControl = 4,
+ };
+
+ enum TRTPPayloadFlags {
+ kFlag_TSTransformPresent = 0x02,
+ kFlag_TSValid = 0x01,
+ };
+
+ protected:
+ TRTPPacket(TRTPHeaderType headerType)
+ : mIsPacked(false)
+ , mVersion(2)
+ , mPadding(false)
+ , mExtension(false)
+ , mCsrcCount(0)
+ , mPayloadType(100)
+ , mSeqNumber(0)
+ , mPTSValid(false)
+ , mPTS(0)
+ , mEpoch(0)
+ , mProgramID(0)
+ , mSubstreamID(0)
+ , mClockTranformValid(false)
+ , mTRTPVersion(1)
+ , mTRTPLength(0)
+ , mTRTPHeaderType(headerType)
+ , mPacket(NULL)
+ , mPacketLen(0) { }
+
+ public:
+ virtual ~TRTPPacket();
+
+ void setSeqNumber(uint16_t val);
+ uint16_t getSeqNumber() const;
+
+ void setPTS(int64_t val);
+ int64_t getPTS() const;
+
+ void setEpoch(uint32_t val);
+ void setProgramID(uint16_t val);
+ void setSubstreamID(uint16_t val);
+ void setClockTransform(const LinearTransform& trans);
+
+ uint8_t* getPacket() const;
+ int getPacketLen() const;
+
+ void setExpireTime(nsecs_t val);
+ nsecs_t getExpireTime() const;
+
+ virtual bool pack() = 0;
+
+ // mask for the number of bits in a TRTP epoch
+ static const uint32_t kTRTPEpochMask = (1 << 22) - 1;
+ static const int kTRTPEpochShift = 10;
+
+ protected:
+ static const int kRTPHeaderLen = 12;
+ virtual int TRTPHeaderLen() const;
+
+ void writeTRTPHeader(uint8_t*& buf,
+ bool isFirstFragment,
+ int totalPacketLen);
+
+ void writeU8(uint8_t*& buf, uint8_t val);
+ void writeU16(uint8_t*& buf, uint16_t val);
+ void writeU32(uint8_t*& buf, uint32_t val);
+ void writeU64(uint8_t*& buf, uint64_t val);
+
+ bool mIsPacked;
+
+ uint8_t mVersion;
+ bool mPadding;
+ bool mExtension;
+ uint8_t mCsrcCount;
+ uint8_t mPayloadType;
+ uint16_t mSeqNumber;
+ bool mPTSValid;
+ int64_t mPTS;
+ uint32_t mEpoch;
+ uint16_t mProgramID;
+ uint16_t mSubstreamID;
+ LinearTransform mClockTranform;
+ bool mClockTranformValid;
+ uint8_t mTRTPVersion;
+ uint32_t mTRTPLength;
+ TRTPHeaderType mTRTPHeaderType;
+
+ uint8_t* mPacket;
+ int mPacketLen;
+
+ nsecs_t mExpireTime;
+
+ DISALLOW_EVIL_CONSTRUCTORS(TRTPPacket);
+};
+
+class TRTPAudioPacket : public TRTPPacket {
+ public:
+ enum AudioPayloadFlags {
+ kFlag_AuxLengthPresent = 0x10,
+ kFlag_RandomAccessPoint = 0x08,
+ kFlag_Dropable = 0x04,
+ kFlag_Discontinuity = 0x02,
+ kFlag_EndOfStream = 0x01,
+ };
+
+ TRTPAudioPacket()
+ : TRTPPacket(kHeaderTypeAudio)
+ , mCodecType(kCodecInvalid)
+ , mRandomAccessPoint(false)
+ , mDropable(false)
+ , mDiscontinuity(false)
+ , mEndOfStream(false)
+ , mVolume(0)
+ , mAccessUnitData(NULL)
+ , mAccessUnitLen(0)
+ , mAuxData(NULL)
+ , mAuxDataLen(0) { }
+
+ enum TRTPAudioCodecType {
+ kCodecInvalid = 0,
+ kCodecPCMBigEndian = 1,
+ kCodecPCMLittleEndian = 2,
+ kCodecMPEG1Audio = 3,
+ kCodecAACAudio = 4,
+ };
+
+ void setCodecType(TRTPAudioCodecType val);
+ void setRandomAccessPoint(bool val);
+ void setDropable(bool val);
+ void setDiscontinuity(bool val);
+ void setEndOfStream(bool val);
+ void setVolume(uint8_t val);
+ void setAccessUnitData(const void* data, size_t len);
+ void setAuxData(const void* data, size_t len);
+
+ virtual bool pack();
+
+ protected:
+ virtual int TRTPHeaderLen() const;
+
+ private:
+ TRTPAudioCodecType mCodecType;
+ bool mRandomAccessPoint;
+ bool mDropable;
+ bool mDiscontinuity;
+ bool mEndOfStream;
+ uint8_t mVolume;
+
+ const void* mAccessUnitData;
+ size_t mAccessUnitLen;
+ const void* mAuxData;
+ size_t mAuxDataLen;
+
+ DISALLOW_EVIL_CONSTRUCTORS(TRTPAudioPacket);
+};
+
+class TRTPControlPacket : public TRTPPacket {
+ public:
+ TRTPControlPacket()
+ : TRTPPacket(kHeaderTypeControl)
+ , mCommandID(kCommandNop) {}
+
+ enum TRTPCommandID {
+ kCommandNop = 1,
+ kCommandFlush = 2,
+ kCommandEOS = 3,
+ };
+
+ void setCommandID(TRTPCommandID val);
+
+ virtual bool pack();
+
+ private:
+ TRTPCommandID mCommandID;
+
+ DISALLOW_EVIL_CONSTRUCTORS(TRTPControlPacket);
+};
+
+} // namespace android
+
+#endif // __AAH_TX_PLAYER_H__
diff --git a/media/libaah_rtp/aah_tx_player.cpp b/media/libaah_rtp/aah_tx_player.cpp
new file mode 100644
index 0000000..974805b
--- /dev/null
+++ b/media/libaah_rtp/aah_tx_player.cpp
@@ -0,0 +1,1177 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "LibAAH_RTP"
+#include <utils/Log.h>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <netdb.h>
+#include <netinet/ip.h>
+
+#include <common_time/cc_helper.h>
+#include <media/IMediaPlayer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/FileSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/Timers.h>
+
+#include "aah_tx_packet.h"
+#include "aah_tx_player.h"
+
+namespace android {
+
+static int64_t kLowWaterMarkUs = 2000000ll; // 2secs
+static int64_t kHighWaterMarkUs = 10000000ll; // 10secs
+static const size_t kLowWaterMarkBytes = 40000;
+static const size_t kHighWaterMarkBytes = 200000;
+
+// When we start up, how much lead time should we put on the first access unit?
+static const int64_t kAAHStartupLeadTimeUs = 300000LL;
+
+// How much time do we attempt to lead the clock by in steady state?
+static const int64_t kAAHBufferTimeUs = 1000000LL;
+
+// how long do we keep data in our retransmit buffer after sending it.
+const int64_t AAH_TXPlayer::kAAHRetryKeepAroundTimeNs =
+ kAAHBufferTimeUs * 1100;
+
+sp<MediaPlayerBase> createAAH_TXPlayer() {
+ sp<MediaPlayerBase> ret = new AAH_TXPlayer();
+ return ret;
+}
+
+template <typename T> static T clamp(T val, T min, T max) {
+ if (val < min) {
+ return min;
+ } else if (val > max) {
+ return max;
+ } else {
+ return val;
+ }
+}
+
+struct AAH_TXEvent : public TimedEventQueue::Event {
+ AAH_TXEvent(AAH_TXPlayer *player,
+ void (AAH_TXPlayer::*method)()) : mPlayer(player)
+ , mMethod(method) {}
+
+ protected:
+ virtual ~AAH_TXEvent() {}
+
+ virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
+ (mPlayer->*mMethod)();
+ }
+
+ private:
+ AAH_TXPlayer *mPlayer;
+ void (AAH_TXPlayer::*mMethod)();
+
+ AAH_TXEvent(const AAH_TXEvent &);
+ AAH_TXEvent& operator=(const AAH_TXEvent &);
+};
+
+AAH_TXPlayer::AAH_TXPlayer()
+ : mQueueStarted(false)
+ , mFlags(0)
+ , mExtractorFlags(0) {
+ DataSource::RegisterDefaultSniffers();
+
+ mBufferingEvent = new AAH_TXEvent(this, &AAH_TXPlayer::onBufferingUpdate);
+ mBufferingEventPending = false;
+
+ mPumpAudioEvent = new AAH_TXEvent(this, &AAH_TXPlayer::onPumpAudio);
+ mPumpAudioEventPending = false;
+
+ mAudioCodecData = NULL;
+
+ reset_l();
+}
+
+AAH_TXPlayer::~AAH_TXPlayer() {
+ if (mQueueStarted) {
+ mQueue.stop();
+ }
+
+ reset_l();
+}
+
+void AAH_TXPlayer::cancelPlayerEvents(bool keepBufferingGoing) {
+ if (!keepBufferingGoing) {
+ mQueue.cancelEvent(mBufferingEvent->eventID());
+ mBufferingEventPending = false;
+
+ mQueue.cancelEvent(mPumpAudioEvent->eventID());
+ mPumpAudioEventPending = false;
+ }
+}
+
+status_t AAH_TXPlayer::initCheck() {
+ // Check for the presense of the common time service by attempting to query
+ // for CommonTime's frequency. If we get an error back, we cannot talk to
+ // the service at all and should abort now.
+ status_t res;
+ uint64_t freq;
+ res = mCCHelper.getCommonFreq(&freq);
+ if (OK != res) {
+ ALOGE("Failed to connect to common time service! (res %d)", res);
+ return res;
+ }
+
+ return OK;
+}
+
+status_t AAH_TXPlayer::setDataSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers) {
+ Mutex::Autolock autoLock(mLock);
+ return setDataSource_l(url, headers);
+}
+
+status_t AAH_TXPlayer::setDataSource_l(
+ const char *url,
+ const KeyedVector<String8, String8> *headers) {
+ reset_l();
+
+ mUri.setTo(url);
+
+ if (headers) {
+ mUriHeaders = *headers;
+
+ ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log"));
+ if (index >= 0) {
+ // Browser is in "incognito" mode, suppress logging URLs.
+
+ // This isn't something that should be passed to the server.
+ mUriHeaders.removeItemsAt(index);
+
+ mFlags |= INCOGNITO;
+ }
+ }
+
+ // The URL may optionally contain a "#" character followed by a Skyjam
+ // cookie. Ideally the cookie header should just be passed in the headers
+ // argument, but the Java API for supplying headers is apparently not yet
+ // exposed in the SDK used by application developers.
+ const char kSkyjamCookieDelimiter = '#';
+ char* skyjamCookie = strrchr(mUri.string(), kSkyjamCookieDelimiter);
+ if (skyjamCookie) {
+ skyjamCookie++;
+ mUriHeaders.add(String8("Cookie"), String8(skyjamCookie));
+ mUri = String8(mUri.string(), skyjamCookie - mUri.string());
+ }
+
+ return OK;
+}
+
+status_t AAH_TXPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
+ Mutex::Autolock autoLock(mLock);
+
+ reset_l();
+
+ sp<DataSource> dataSource = new FileSource(dup(fd), offset, length);
+
+ status_t err = dataSource->initCheck();
+
+ if (err != OK) {
+ return err;
+ }
+
+ mFileSource = dataSource;
+
+ sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+
+ if (extractor == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ return setDataSource_l(extractor);
+}
+
+status_t AAH_TXPlayer::setVideoSurface(const sp<Surface>& surface) {
+ return OK;
+}
+
+status_t AAH_TXPlayer::setVideoSurfaceTexture(
+ const sp<ISurfaceTexture>& surfaceTexture) {
+ return OK;
+}
+
+status_t AAH_TXPlayer::prepare() {
+ return INVALID_OPERATION;
+}
+
+status_t AAH_TXPlayer::prepareAsync() {
+ Mutex::Autolock autoLock(mLock);
+
+ return prepareAsync_l();
+}
+
+status_t AAH_TXPlayer::prepareAsync_l() {
+ if (mFlags & PREPARING) {
+ return UNKNOWN_ERROR; // async prepare already pending
+ }
+
+ mAAH_Sender = AAH_TXSender::GetInstance();
+ if (mAAH_Sender == NULL) {
+ return NO_MEMORY;
+ }
+
+ if (!mQueueStarted) {
+ mQueue.start();
+ mQueueStarted = true;
+ }
+
+ mFlags |= PREPARING;
+ mAsyncPrepareEvent = new AAH_TXEvent(
+ this, &AAH_TXPlayer::onPrepareAsyncEvent);
+
+ mQueue.postEvent(mAsyncPrepareEvent);
+
+ return OK;
+}
+
+status_t AAH_TXPlayer::finishSetDataSource_l() {
+ sp<DataSource> dataSource;
+
+ if (!strncasecmp("http://", mUri.string(), 7) ||
+ !strncasecmp("https://", mUri.string(), 8)) {
+
+ mConnectingDataSource = HTTPBase::Create(
+ (mFlags & INCOGNITO)
+ ? HTTPBase::kFlagIncognito
+ : 0);
+
+ mLock.unlock();
+ status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
+ mLock.lock();
+
+ if (err != OK) {
+ mConnectingDataSource.clear();
+
+ ALOGI("mConnectingDataSource->connect() returned %d", err);
+ return err;
+ }
+
+ mCachedSource = new NuCachedSource2(mConnectingDataSource);
+ mConnectingDataSource.clear();
+
+ dataSource = mCachedSource;
+
+ // We're going to prefill the cache before trying to instantiate
+ // the extractor below, as the latter is an operation that otherwise
+ // could block on the datasource for a significant amount of time.
+ // During that time we'd be unable to abort the preparation phase
+ // without this prefill.
+
+ mLock.unlock();
+
+ for (;;) {
+ status_t finalStatus;
+ size_t cachedDataRemaining =
+ mCachedSource->approxDataRemaining(&finalStatus);
+
+ if (finalStatus != OK ||
+ cachedDataRemaining >= kHighWaterMarkBytes ||
+ (mFlags & PREPARE_CANCELLED)) {
+ break;
+ }
+
+ usleep(200000);
+ }
+
+ mLock.lock();
+
+ if (mFlags & PREPARE_CANCELLED) {
+ ALOGI("Prepare cancelled while waiting for initial cache fill.");
+ return UNKNOWN_ERROR;
+ }
+ } else {
+ dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
+ }
+
+ if (dataSource == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+
+ if (extractor == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ return setDataSource_l(extractor);
+}
+
+status_t AAH_TXPlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
+ // Attempt to approximate overall stream bitrate by summing all
+ // tracks' individual bitrates, if not all of them advertise bitrate,
+ // we have to fail.
+
+ int64_t totalBitRate = 0;
+
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+ int32_t bitrate;
+ if (!meta->findInt32(kKeyBitRate, &bitrate)) {
+ totalBitRate = -1;
+ break;
+ }
+
+ totalBitRate += bitrate;
+ }
+
+ mBitrate = totalBitRate;
+
+ ALOGV("mBitrate = %lld bits/sec", mBitrate);
+
+ bool haveAudio = false;
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (!strncasecmp(mime, "audio/", 6)) {
+ mAudioSource = extractor->getTrack(i);
+ CHECK(mAudioSource != NULL);
+ haveAudio = true;
+ break;
+ }
+ }
+
+ if (!haveAudio) {
+ return UNKNOWN_ERROR;
+ }
+
+ mExtractorFlags = extractor->flags();
+
+ return OK;
+}
+
+void AAH_TXPlayer::abortPrepare(status_t err) {
+ CHECK(err != OK);
+
+ notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+
+ mPrepareResult = err;
+ mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
+ mPreparedCondition.broadcast();
+}
+
+void AAH_TXPlayer::onPrepareAsyncEvent() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mFlags & PREPARE_CANCELLED) {
+ ALOGI("prepare was cancelled before doing anything");
+ abortPrepare(UNKNOWN_ERROR);
+ return;
+ }
+
+ if (mUri.size() > 0) {
+ status_t err = finishSetDataSource_l();
+
+ if (err != OK) {
+ abortPrepare(err);
+ return;
+ }
+ }
+
+ mAudioFormat = mAudioSource->getFormat();
+ if (!mAudioFormat->findInt64(kKeyDuration, &mDurationUs))
+ mDurationUs = 1;
+
+ const char* mime_type = NULL;
+ if (!mAudioFormat->findCString(kKeyMIMEType, &mime_type)) {
+ ALOGE("Failed to find audio substream MIME type during prepare.");
+ abortPrepare(BAD_VALUE);
+ return;
+ }
+
+ if (!strcmp(mime_type, MEDIA_MIMETYPE_AUDIO_MPEG)) {
+ mAudioCodec = TRTPAudioPacket::kCodecMPEG1Audio;
+ } else
+ if (!strcmp(mime_type, MEDIA_MIMETYPE_AUDIO_AAC)) {
+ mAudioCodec = TRTPAudioPacket::kCodecAACAudio;
+
+ uint32_t type;
+ int32_t sample_rate;
+ int32_t channel_count;
+ const void* esds_data;
+ size_t esds_len;
+
+ if (!mAudioFormat->findInt32(kKeySampleRate, &sample_rate)) {
+ ALOGE("Failed to find sample rate for AAC substream.");
+ abortPrepare(BAD_VALUE);
+ return;
+ }
+
+ if (!mAudioFormat->findInt32(kKeyChannelCount, &channel_count)) {
+ ALOGE("Failed to find channel count for AAC substream.");
+ abortPrepare(BAD_VALUE);
+ return;
+ }
+
+ if (!mAudioFormat->findData(kKeyESDS, &type, &esds_data, &esds_len)) {
+ ALOGE("Failed to find codec init data for AAC substream.");
+ abortPrepare(BAD_VALUE);
+ return;
+ }
+
+ CHECK(NULL == mAudioCodecData);
+ mAudioCodecDataSize = esds_len
+ + sizeof(sample_rate)
+ + sizeof(channel_count);
+ mAudioCodecData = new uint8_t[mAudioCodecDataSize];
+ if (NULL == mAudioCodecData) {
+ ALOGE("Failed to allocate %u bytes for AAC substream codec aux"
+ " data.", mAudioCodecDataSize);
+ mAudioCodecDataSize = 0;
+ abortPrepare(BAD_VALUE);
+ return;
+ }
+
+ uint8_t* tmp = mAudioCodecData;
+ tmp[0] = static_cast<uint8_t>((sample_rate >> 24) & 0xFF);
+ tmp[1] = static_cast<uint8_t>((sample_rate >> 16) & 0xFF);
+ tmp[2] = static_cast<uint8_t>((sample_rate >> 8) & 0xFF);
+ tmp[3] = static_cast<uint8_t>((sample_rate ) & 0xFF);
+ tmp[4] = static_cast<uint8_t>((channel_count >> 24) & 0xFF);
+ tmp[5] = static_cast<uint8_t>((channel_count >> 16) & 0xFF);
+ tmp[6] = static_cast<uint8_t>((channel_count >> 8) & 0xFF);
+ tmp[7] = static_cast<uint8_t>((channel_count ) & 0xFF);
+
+ memcpy(tmp + 8, esds_data, esds_len);
+ } else {
+ ALOGE("Unsupported MIME type \"%s\" in audio substream", mime_type);
+ abortPrepare(BAD_VALUE);
+ return;
+ }
+
+ status_t err = mAudioSource->start();
+ if (err != OK) {
+ ALOGI("failed to start audio source, err=%d", err);
+ abortPrepare(err);
+ return;
+ }
+
+ mFlags |= PREPARING_CONNECTED;
+
+ if (mCachedSource != NULL) {
+ postBufferingEvent_l();
+ } else {
+ finishAsyncPrepare_l();
+ }
+}
+
+void AAH_TXPlayer::finishAsyncPrepare_l() {
+ notifyListener_l(MEDIA_PREPARED);
+
+ mPrepareResult = OK;
+ mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
+ mFlags |= PREPARED;
+ mPreparedCondition.broadcast();
+}
+
+status_t AAH_TXPlayer::start() {
+ Mutex::Autolock autoLock(mLock);
+
+ mFlags &= ~CACHE_UNDERRUN;
+
+ return play_l();
+}
+
+status_t AAH_TXPlayer::play_l() {
+ if (mFlags & PLAYING) {
+ return OK;
+ }
+
+ if (!(mFlags & PREPARED)) {
+ return INVALID_OPERATION;
+ }
+
+ {
+ Mutex::Autolock lock(mEndpointLock);
+ if (!mEndpointValid) {
+ return INVALID_OPERATION;
+ }
+ if (!mEndpointRegistered) {
+ mProgramID = mAAH_Sender->registerEndpoint(mEndpoint);
+ mEndpointRegistered = true;
+ }
+ }
+
+ mFlags |= PLAYING;
+
+ updateClockTransform_l(false);
+
+ postPumpAudioEvent_l(-1);
+
+ return OK;
+}
+
+status_t AAH_TXPlayer::stop() {
+ status_t ret = pause();
+ sendEOS_l();
+ return ret;
+}
+
+status_t AAH_TXPlayer::pause() {
+ Mutex::Autolock autoLock(mLock);
+
+ mFlags &= ~CACHE_UNDERRUN;
+
+ return pause_l();
+}
+
+status_t AAH_TXPlayer::pause_l(bool doClockUpdate) {
+ if (!(mFlags & PLAYING)) {
+ return OK;
+ }
+
+ cancelPlayerEvents(true /* keepBufferingGoing */);
+
+ mFlags &= ~PLAYING;
+
+ if (doClockUpdate) {
+ updateClockTransform_l(true);
+ }
+
+ return OK;
+}
+
+void AAH_TXPlayer::updateClockTransform_l(bool pause) {
+ // record the new pause status so that onPumpAudio knows what rate to apply
+ // when it initializes the transform
+ mPlayRateIsPaused = pause;
+
+ // if we haven't yet established a valid clock transform, then we can't
+ // do anything here
+ if (!mCurrentClockTransformValid) {
+ return;
+ }
+
+ // sample the current common time
+ int64_t commonTimeNow;
+ if (OK != mCCHelper.getCommonTime(&commonTimeNow)) {
+ ALOGE("updateClockTransform_l get common time failed");
+ mCurrentClockTransformValid = false;
+ return;
+ }
+
+ // convert the current common time to media time using the old
+ // transform
+ int64_t mediaTimeNow;
+ if (!mCurrentClockTransform.doReverseTransform(
+ commonTimeNow, &mediaTimeNow)) {
+ ALOGE("updateClockTransform_l reverse transform failed");
+ mCurrentClockTransformValid = false;
+ return;
+ }
+
+ // calculate a new transform that preserves the old transform's
+ // result for the current time
+ mCurrentClockTransform.a_zero = mediaTimeNow;
+ mCurrentClockTransform.b_zero = commonTimeNow;
+ mCurrentClockTransform.a_to_b_numer = 1;
+ mCurrentClockTransform.a_to_b_denom = pause ? 0 : 1;
+
+ // send a packet announcing the new transform
+ sp<TRTPControlPacket> packet = new TRTPControlPacket();
+ packet->setClockTransform(mCurrentClockTransform);
+ packet->setCommandID(TRTPControlPacket::kCommandNop);
+ queuePacketToSender_l(packet);
+}
+
+void AAH_TXPlayer::sendEOS_l() {
+ sp<TRTPControlPacket> packet = new TRTPControlPacket();
+ packet->setCommandID(TRTPControlPacket::kCommandEOS);
+ queuePacketToSender_l(packet);
+}
+
+bool AAH_TXPlayer::isPlaying() {
+ return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
+}
+
+status_t AAH_TXPlayer::seekTo(int msec) {
+ if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
+ Mutex::Autolock autoLock(mLock);
+ return seekTo_l(static_cast<int64_t>(msec) * 1000);
+ }
+
+ notifyListener_l(MEDIA_SEEK_COMPLETE);
+ return OK;
+}
+
+status_t AAH_TXPlayer::seekTo_l(int64_t timeUs) {
+ mIsSeeking = true;
+ mSeekTimeUs = timeUs;
+
+ mCurrentClockTransformValid = false;
+ mLastQueuedMediaTimePTSValid = false;
+
+ // send a flush command packet
+ sp<TRTPControlPacket> packet = new TRTPControlPacket();
+ packet->setCommandID(TRTPControlPacket::kCommandFlush);
+ queuePacketToSender_l(packet);
+
+ return OK;
+}
+
+status_t AAH_TXPlayer::getCurrentPosition(int *msec) {
+ if (!msec) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mLock);
+
+ int position;
+
+ if (mIsSeeking) {
+ position = mSeekTimeUs / 1000;
+ } else if (mCurrentClockTransformValid) {
+ // sample the current common time
+ int64_t commonTimeNow;
+ if (OK != mCCHelper.getCommonTime(&commonTimeNow)) {
+ ALOGE("getCurrentPosition get common time failed");
+ return INVALID_OPERATION;
+ }
+
+ int64_t mediaTimeNow;
+ if (!mCurrentClockTransform.doReverseTransform(commonTimeNow,
+ &mediaTimeNow)) {
+ ALOGE("getCurrentPosition reverse transform failed");
+ return INVALID_OPERATION;
+ }
+
+ position = static_cast<int>(mediaTimeNow / 1000);
+ } else {
+ position = 0;
+ }
+
+ int duration;
+ if (getDuration_l(&duration) == OK) {
+ *msec = clamp(position, 0, duration);
+ } else {
+ *msec = (position >= 0) ? position : 0;
+ }
+
+ return OK;
+}
+
+status_t AAH_TXPlayer::getDuration(int* msec) {
+ if (!msec) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mLock);
+
+ return getDuration_l(msec);
+}
+
+status_t AAH_TXPlayer::getDuration_l(int* msec) {
+ if (mDurationUs < 0) {
+ return UNKNOWN_ERROR;
+ }
+
+ *msec = (mDurationUs + 500) / 1000;
+
+ return OK;
+}
+
+status_t AAH_TXPlayer::reset() {
+ Mutex::Autolock autoLock(mLock);
+ reset_l();
+ return OK;
+}
+
+void AAH_TXPlayer::reset_l() {
+ if (mFlags & PREPARING) {
+ mFlags |= PREPARE_CANCELLED;
+ if (mConnectingDataSource != NULL) {
+ ALOGI("interrupting the connection process");
+ mConnectingDataSource->disconnect();
+ }
+
+ if (mFlags & PREPARING_CONNECTED) {
+ // We are basically done preparing, we're just buffering
+ // enough data to start playback, we can safely interrupt that.
+ finishAsyncPrepare_l();
+ }
+ }
+
+ while (mFlags & PREPARING) {
+ mPreparedCondition.wait(mLock);
+ }
+
+ cancelPlayerEvents();
+
+ sendEOS_l();
+
+ mCachedSource.clear();
+
+ if (mAudioSource != NULL) {
+ mAudioSource->stop();
+ }
+ mAudioSource.clear();
+ mAudioCodec = TRTPAudioPacket::kCodecInvalid;
+ mAudioFormat = NULL;
+ delete[] mAudioCodecData;
+ mAudioCodecData = NULL;
+ mAudioCodecDataSize = 0;
+
+ mFlags = 0;
+ mExtractorFlags = 0;
+
+ mDurationUs = -1;
+ mIsSeeking = false;
+ mSeekTimeUs = 0;
+
+ mUri.setTo("");
+ mUriHeaders.clear();
+
+ mFileSource.clear();
+
+ mBitrate = -1;
+
+ {
+ Mutex::Autolock lock(mEndpointLock);
+ if (mAAH_Sender != NULL && mEndpointRegistered) {
+ mAAH_Sender->unregisterEndpoint(mEndpoint);
+ }
+ mEndpointRegistered = false;
+ mEndpointValid = false;
+ }
+
+ mProgramID = 0;
+
+ mAAH_Sender.clear();
+ mLastQueuedMediaTimePTSValid = false;
+ mCurrentClockTransformValid = false;
+ mPlayRateIsPaused = false;
+
+ mTRTPVolume = 255;
+}
+
+status_t AAH_TXPlayer::setLooping(int loop) {
+ return OK;
+}
+
+player_type AAH_TXPlayer::playerType() {
+ return AAH_TX_PLAYER;
+}
+
+status_t AAH_TXPlayer::setParameter(int key, const Parcel &request) {
+ return ERROR_UNSUPPORTED;
+}
+
+status_t AAH_TXPlayer::getParameter(int key, Parcel *reply) {
+ return ERROR_UNSUPPORTED;
+}
+
+status_t AAH_TXPlayer::invoke(const Parcel& request, Parcel *reply) {
+ return INVALID_OPERATION;
+}
+
+status_t AAH_TXPlayer::getMetadata(const media::Metadata::Filter& ids,
+ Parcel* records) {
+ using media::Metadata;
+
+ Metadata metadata(records);
+
+ metadata.appendBool(Metadata::kPauseAvailable, true);
+ metadata.appendBool(Metadata::kSeekBackwardAvailable, false);
+ metadata.appendBool(Metadata::kSeekForwardAvailable, false);
+ metadata.appendBool(Metadata::kSeekAvailable, false);
+
+ return OK;
+}
+
+status_t AAH_TXPlayer::setVolume(float leftVolume, float rightVolume) {
+ if (leftVolume != rightVolume) {
+ ALOGE("%s does not support per channel volume: %f, %f",
+ __PRETTY_FUNCTION__, leftVolume, rightVolume);
+ }
+
+ float volume = clamp(leftVolume, 0.0f, 1.0f);
+
+ Mutex::Autolock lock(mLock);
+ mTRTPVolume = static_cast<uint8_t>((leftVolume * 255.0) + 0.5);
+
+ return OK;
+}
+
+status_t AAH_TXPlayer::setAudioStreamType(audio_stream_type_t streamType) {
+ return OK;
+}
+
+status_t AAH_TXPlayer::setRetransmitEndpoint(
+ const struct sockaddr_in* endpoint) {
+ Mutex::Autolock lock(mLock);
+
+ if (NULL == endpoint)
+ return BAD_VALUE;
+
+ // Once the endpoint has been registered, it may not be changed.
+ if (mEndpointRegistered)
+ return INVALID_OPERATION;
+
+ mEndpoint.addr = endpoint->sin_addr.s_addr;
+ mEndpoint.port = endpoint->sin_port;
+ mEndpointValid = true;
+
+ return OK;
+}
+
+void AAH_TXPlayer::notifyListener_l(int msg, int ext1, int ext2) {
+ sendEvent(msg, ext1, ext2);
+}
+
+bool AAH_TXPlayer::getBitrate_l(int64_t *bitrate) {
+ off64_t size;
+ if (mDurationUs >= 0 &&
+ mCachedSource != NULL &&
+ mCachedSource->getSize(&size) == OK) {
+ *bitrate = size * 8000000ll / mDurationUs; // in bits/sec
+ return true;
+ }
+
+ if (mBitrate >= 0) {
+ *bitrate = mBitrate;
+ return true;
+ }
+
+ *bitrate = 0;
+
+ return false;
+}
+
+// Returns true iff cached duration is available/applicable.
+bool AAH_TXPlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
+ int64_t bitrate;
+
+ if (mCachedSource != NULL && getBitrate_l(&bitrate)) {
+ status_t finalStatus;
+ size_t cachedDataRemaining = mCachedSource->approxDataRemaining(
+ &finalStatus);
+ *durationUs = cachedDataRemaining * 8000000ll / bitrate;
+ *eos = (finalStatus != OK);
+ return true;
+ }
+
+ return false;
+}
+
+void AAH_TXPlayer::ensureCacheIsFetching_l() {
+ if (mCachedSource != NULL) {
+ mCachedSource->resumeFetchingIfNecessary();
+ }
+}
+
+void AAH_TXPlayer::postBufferingEvent_l() {
+ if (mBufferingEventPending) {
+ return;
+ }
+ mBufferingEventPending = true;
+ mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
+}
+
+void AAH_TXPlayer::postPumpAudioEvent_l(int64_t delayUs) {
+ if (mPumpAudioEventPending) {
+ return;
+ }
+ mPumpAudioEventPending = true;
+ mQueue.postEventWithDelay(mPumpAudioEvent, delayUs < 0 ? 10000 : delayUs);
+}
+
+void AAH_TXPlayer::onBufferingUpdate() {
+ Mutex::Autolock autoLock(mLock);
+ if (!mBufferingEventPending) {
+ return;
+ }
+ mBufferingEventPending = false;
+
+ if (mCachedSource != NULL) {
+ status_t finalStatus;
+ size_t cachedDataRemaining = mCachedSource->approxDataRemaining(
+ &finalStatus);
+ bool eos = (finalStatus != OK);
+
+ if (eos) {
+ if (finalStatus == ERROR_END_OF_STREAM) {
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
+ }
+ if (mFlags & PREPARING) {
+ ALOGV("cache has reached EOS, prepare is done.");
+ finishAsyncPrepare_l();
+ }
+ } else {
+ int64_t bitrate;
+ if (getBitrate_l(&bitrate)) {
+ size_t cachedSize = mCachedSource->cachedSize();
+ int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
+
+ int percentage = (100.0 * (double) cachedDurationUs)
+ / mDurationUs;
+ if (percentage > 100) {
+ percentage = 100;
+ }
+
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
+ } else {
+ // We don't know the bitrate of the stream, use absolute size
+ // limits to maintain the cache.
+
+ if ((mFlags & PLAYING) &&
+ !eos &&
+ (cachedDataRemaining < kLowWaterMarkBytes)) {
+ ALOGI("cache is running low (< %d) , pausing.",
+ kLowWaterMarkBytes);
+ mFlags |= CACHE_UNDERRUN;
+ pause_l();
+ ensureCacheIsFetching_l();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
+ } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
+ if (mFlags & CACHE_UNDERRUN) {
+ ALOGI("cache has filled up (> %d), resuming.",
+ kHighWaterMarkBytes);
+ mFlags &= ~CACHE_UNDERRUN;
+ play_l();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
+ } else if (mFlags & PREPARING) {
+ ALOGV("cache has filled up (> %d), prepare is done",
+ kHighWaterMarkBytes);
+ finishAsyncPrepare_l();
+ }
+ }
+ }
+ }
+ }
+
+ int64_t cachedDurationUs;
+ bool eos;
+ if (getCachedDuration_l(&cachedDurationUs, &eos)) {
+ ALOGV("cachedDurationUs = %.2f secs, eos=%d",
+ cachedDurationUs / 1E6, eos);
+
+ if ((mFlags & PLAYING) &&
+ !eos &&
+ (cachedDurationUs < kLowWaterMarkUs)) {
+ ALOGI("cache is running low (%.2f secs) , pausing.",
+ cachedDurationUs / 1E6);
+ mFlags |= CACHE_UNDERRUN;
+ pause_l();
+ ensureCacheIsFetching_l();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
+ } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
+ if (mFlags & CACHE_UNDERRUN) {
+ ALOGI("cache has filled up (%.2f secs), resuming.",
+ cachedDurationUs / 1E6);
+ mFlags &= ~CACHE_UNDERRUN;
+ play_l();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
+ } else if (mFlags & PREPARING) {
+ ALOGV("cache has filled up (%.2f secs), prepare is done",
+ cachedDurationUs / 1E6);
+ finishAsyncPrepare_l();
+ }
+ }
+ }
+
+ postBufferingEvent_l();
+}
+
+void AAH_TXPlayer::onPumpAudio() {
+ while (true) {
+ Mutex::Autolock autoLock(mLock);
+ // If this flag is clear, its because someone has externally canceled
+ // this pump operation (probably because we a resetting/shutting down).
+ // Get out immediately, do not reschedule ourselves.
+ if (!mPumpAudioEventPending) {
+ return;
+ }
+
+ // Start by checking if there is still work to be doing. If we have
+ // never queued a payload (so we don't know what the last queued PTS is)
+ // or we have never established a MediaTime->CommonTime transformation,
+ // then we have work to do (one time through this loop should establish
+ // both). Otherwise, we want to keep a fixed amt of presentation time
+ // worth of data buffered. If we cannot get common time (service is
+ // unavailable, or common time is undefined)) then we don't have a lot
+ // of good options here. For now, signal an error up to the app level
+ // and shut down the transmission pump.
+ int64_t commonTimeNow;
+ if (OK != mCCHelper.getCommonTime(&commonTimeNow)) {
+ // Failed to get common time; either the service is down or common
+ // time is not synced. Raise an error and shutdown the player.
+ ALOGE("*** Cannot pump audio, unable to fetch common time."
+ " Shutting down.");
+ notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, UNKNOWN_ERROR);
+ mPumpAudioEventPending = false;
+ break;
+ }
+
+ if (mCurrentClockTransformValid && mLastQueuedMediaTimePTSValid) {
+ int64_t mediaTimeNow;
+ bool conversionResult = mCurrentClockTransform.doReverseTransform(
+ commonTimeNow,
+ &mediaTimeNow);
+ CHECK(conversionResult);
+
+ if ((mediaTimeNow +
+ kAAHBufferTimeUs -
+ mLastQueuedMediaTimePTS) <= 0) {
+ break;
+ }
+ }
+
+ MediaSource::ReadOptions options;
+ if (mIsSeeking) {
+ options.setSeekTo(mSeekTimeUs);
+ }
+
+ MediaBuffer* mediaBuffer;
+ status_t err = mAudioSource->read(&mediaBuffer, &options);
+ if (err != NO_ERROR) {
+ if (err == ERROR_END_OF_STREAM) {
+ ALOGI("*** %s reached end of stream", __PRETTY_FUNCTION__);
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
+ notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
+ pause_l(false);
+ sendEOS_l();
+ } else {
+ ALOGE("*** %s read failed err=%d", __PRETTY_FUNCTION__, err);
+ }
+ return;
+ }
+
+ if (mIsSeeking) {
+ mIsSeeking = false;
+ notifyListener_l(MEDIA_SEEK_COMPLETE);
+ }
+
+ uint8_t* data = (static_cast<uint8_t*>(mediaBuffer->data()) +
+ mediaBuffer->range_offset());
+ ALOGV("*** %s got media buffer data=[%02hhx %02hhx %02hhx %02hhx]"
+ " offset=%d length=%d", __PRETTY_FUNCTION__,
+ data[0], data[1], data[2], data[3],
+ mediaBuffer->range_offset(), mediaBuffer->range_length());
+
+ int64_t mediaTimeUs;
+ CHECK(mediaBuffer->meta_data()->findInt64(kKeyTime, &mediaTimeUs));
+ ALOGV("*** timeUs=%lld", mediaTimeUs);
+
+ if (!mCurrentClockTransformValid) {
+ if (OK == mCCHelper.getCommonTime(&commonTimeNow)) {
+ mCurrentClockTransform.a_zero = mediaTimeUs;
+ mCurrentClockTransform.b_zero = commonTimeNow +
+ kAAHStartupLeadTimeUs;
+ mCurrentClockTransform.a_to_b_numer = 1;
+ mCurrentClockTransform.a_to_b_denom = mPlayRateIsPaused ? 0 : 1;
+ mCurrentClockTransformValid = true;
+ } else {
+ // Failed to get common time; either the service is down or
+ // common time is not synced. Raise an error and shutdown the
+ // player.
+ ALOGE("*** Cannot begin transmission, unable to fetch common"
+ " time. Dropping sample with pts=%lld", mediaTimeUs);
+ notifyListener_l(MEDIA_ERROR,
+ MEDIA_ERROR_UNKNOWN,
+ UNKNOWN_ERROR);
+ mPumpAudioEventPending = false;
+ break;
+ }
+ }
+
+ ALOGV("*** transmitting packet with pts=%lld", mediaTimeUs);
+
+ sp<TRTPAudioPacket> packet = new TRTPAudioPacket();
+ packet->setPTS(mediaTimeUs);
+ packet->setSubstreamID(1);
+
+ packet->setCodecType(mAudioCodec);
+ packet->setVolume(mTRTPVolume);
+ // TODO : introduce a throttle for this so we can control the
+ // frequency with which transforms get sent.
+ packet->setClockTransform(mCurrentClockTransform);
+ packet->setAccessUnitData(data, mediaBuffer->range_length());
+
+ // TODO : while its pretty much universally true that audio ES payloads
+ // are all RAPs across all codecs, it might be a good idea to throttle
+ // the frequency with which we send codec out of band data to the RXers.
+ // If/when we do, we need to flag only those payloads which have
+ // required out of band data attached to them as RAPs.
+ packet->setRandomAccessPoint(true);
+
+ if (mAudioCodecData && mAudioCodecDataSize) {
+ packet->setAuxData(mAudioCodecData, mAudioCodecDataSize);
+ }
+
+ queuePacketToSender_l(packet);
+ mediaBuffer->release();
+
+ mLastQueuedMediaTimePTSValid = true;
+ mLastQueuedMediaTimePTS = mediaTimeUs;
+ }
+
+ { // Explicit scope for the autolock pattern.
+ Mutex::Autolock autoLock(mLock);
+
+ // If someone externally has cleared this flag, its because we should be
+ // shutting down. Do not reschedule ourselves.
+ if (!mPumpAudioEventPending) {
+ return;
+ }
+
+ // Looks like no one canceled us explicitly. Clear our flag and post a
+ // new event to ourselves.
+ mPumpAudioEventPending = false;
+ postPumpAudioEvent_l(10000);
+ }
+}
+
+void AAH_TXPlayer::queuePacketToSender_l(const sp<TRTPPacket>& packet) {
+ if (mAAH_Sender == NULL) {
+ return;
+ }
+
+ sp<AMessage> message = new AMessage(AAH_TXSender::kWhatSendPacket,
+ mAAH_Sender->handlerID());
+
+ {
+ Mutex::Autolock lock(mEndpointLock);
+ if (!mEndpointValid) {
+ return;
+ }
+
+ message->setInt32(AAH_TXSender::kSendPacketIPAddr, mEndpoint.addr);
+ message->setInt32(AAH_TXSender::kSendPacketPort, mEndpoint.port);
+ }
+
+ packet->setProgramID(mProgramID);
+ packet->setExpireTime(systemTime() + kAAHRetryKeepAroundTimeNs);
+ packet->pack();
+
+ message->setObject(AAH_TXSender::kSendPacketTRTPPacket, packet);
+
+ message->post();
+}
+
+} // namespace android
diff --git a/media/libaah_rtp/aah_tx_player.h b/media/libaah_rtp/aah_tx_player.h
new file mode 100644
index 0000000..2e4b1f7
--- /dev/null
+++ b/media/libaah_rtp/aah_tx_player.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 __AAH_TX_PLAYER_H__
+#define __AAH_TX_PLAYER_H__
+
+#include <common_time/cc_helper.h>
+#include <libstagefright/include/HTTPBase.h>
+#include <libstagefright/include/NuCachedSource2.h>
+#include <libstagefright/include/TimedEventQueue.h>
+#include <media/MediaPlayerInterface.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/LinearTransform.h>
+#include <utils/String8.h>
+#include <utils/threads.h>
+
+#include "aah_tx_sender.h"
+
+namespace android {
+
+class AAH_TXPlayer : public MediaPlayerHWInterface {
+ public:
+ AAH_TXPlayer();
+
+ virtual status_t initCheck();
+ virtual status_t setDataSource(const char *url,
+ const KeyedVector<String8, String8>*
+ headers);
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
+ virtual status_t setVideoSurface(const sp<Surface>& surface);
+ virtual status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>&
+ surfaceTexture);
+ virtual status_t prepare();
+ virtual status_t prepareAsync();
+ virtual status_t start();
+ virtual status_t stop();
+ virtual status_t pause();
+ virtual bool isPlaying();
+ virtual status_t seekTo(int msec);
+ virtual status_t getCurrentPosition(int *msec);
+ virtual status_t getDuration(int *msec);
+ virtual status_t reset();
+ virtual status_t setLooping(int loop);
+ virtual player_type playerType();
+ virtual status_t setParameter(int key, const Parcel &request);
+ virtual status_t getParameter(int key, Parcel *reply);
+ virtual status_t invoke(const Parcel& request, Parcel *reply);
+ virtual status_t getMetadata(const media::Metadata::Filter& ids,
+ Parcel* records);
+ virtual status_t setVolume(float leftVolume, float rightVolume);
+ virtual status_t setAudioStreamType(audio_stream_type_t streamType);
+ virtual status_t setRetransmitEndpoint(
+ const struct sockaddr_in* endpoint);
+
+ static const int64_t kAAHRetryKeepAroundTimeNs;
+
+ protected:
+ virtual ~AAH_TXPlayer();
+
+ private:
+ friend struct AwesomeEvent;
+
+ enum {
+ PLAYING = 1,
+ PREPARING = 8,
+ PREPARED = 16,
+ PREPARE_CANCELLED = 64,
+ CACHE_UNDERRUN = 128,
+
+ // We are basically done preparing but are currently buffering
+ // sufficient data to begin playback and finish the preparation
+ // phase for good.
+ PREPARING_CONNECTED = 2048,
+
+ INCOGNITO = 32768,
+ };
+
+ status_t setDataSource_l(const char *url,
+ const KeyedVector<String8, String8> *headers);
+ status_t setDataSource_l(const sp<MediaExtractor>& extractor);
+ status_t finishSetDataSource_l();
+ status_t prepareAsync_l();
+ void onPrepareAsyncEvent();
+ void finishAsyncPrepare_l();
+ void abortPrepare(status_t err);
+ status_t play_l();
+ status_t pause_l(bool doClockUpdate = true);
+ status_t seekTo_l(int64_t timeUs);
+ void updateClockTransform_l(bool pause);
+ void sendEOS_l();
+ void cancelPlayerEvents(bool keepBufferingGoing = false);
+ void reset_l();
+ void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0);
+ bool getBitrate_l(int64_t* bitrate);
+ status_t getDuration_l(int* msec);
+ bool getCachedDuration_l(int64_t* durationUs, bool* eos);
+ void ensureCacheIsFetching_l();
+ void postBufferingEvent_l();
+ void postPumpAudioEvent_l(int64_t delayUs);
+ void onBufferingUpdate();
+ void onPumpAudio();
+ void queuePacketToSender_l(const sp<TRTPPacket>& packet);
+
+ Mutex mLock;
+
+ TimedEventQueue mQueue;
+ bool mQueueStarted;
+
+ sp<TimedEventQueue::Event> mBufferingEvent;
+ bool mBufferingEventPending;
+
+ uint32_t mFlags;
+ uint32_t mExtractorFlags;
+
+ String8 mUri;
+ KeyedVector<String8, String8> mUriHeaders;
+
+ sp<DataSource> mFileSource;
+
+ sp<TimedEventQueue::Event> mAsyncPrepareEvent;
+ Condition mPreparedCondition;
+ status_t mPrepareResult;
+
+ bool mIsSeeking;
+ int64_t mSeekTimeUs;
+
+ sp<TimedEventQueue::Event> mPumpAudioEvent;
+ bool mPumpAudioEventPending;
+
+ sp<HTTPBase> mConnectingDataSource;
+ sp<NuCachedSource2> mCachedSource;
+
+ sp<MediaSource> mAudioSource;
+ TRTPAudioPacket::TRTPAudioCodecType mAudioCodec;
+ sp<MetaData> mAudioFormat;
+ uint8_t* mAudioCodecData;
+ size_t mAudioCodecDataSize;
+
+ int64_t mDurationUs;
+ int64_t mBitrate;
+
+ sp<AAH_TXSender> mAAH_Sender;
+ LinearTransform mCurrentClockTransform;
+ bool mCurrentClockTransformValid;
+ int64_t mLastQueuedMediaTimePTS;
+ bool mLastQueuedMediaTimePTSValid;
+ bool mPlayRateIsPaused;
+ CCHelper mCCHelper;
+
+ Mutex mEndpointLock;
+ AAH_TXSender::Endpoint mEndpoint;
+ bool mEndpointValid;
+ bool mEndpointRegistered;
+ uint16_t mProgramID;
+ uint8_t mTRTPVolume;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AAH_TXPlayer);
+};
+
+} // namespace android
+
+#endif // __AAH_TX_PLAYER_H__
diff --git a/media/libaah_rtp/aah_tx_sender.cpp b/media/libaah_rtp/aah_tx_sender.cpp
new file mode 100644
index 0000000..08e32d2
--- /dev/null
+++ b/media/libaah_rtp/aah_tx_sender.cpp
@@ -0,0 +1,603 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "LibAAH_RTP"
+#include <media/stagefright/foundation/ADebug.h>
+
+#include <netinet/in.h>
+#include <poll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <media/stagefright/foundation/AMessage.h>
+#include <utils/misc.h>
+
+#include "aah_tx_player.h"
+#include "aah_tx_sender.h"
+
+namespace android {
+
+const char* AAH_TXSender::kSendPacketIPAddr = "ipaddr";
+const char* AAH_TXSender::kSendPacketPort = "port";
+const char* AAH_TXSender::kSendPacketTRTPPacket = "trtp";
+
+const int AAH_TXSender::kRetryTrimIntervalUs = 100000;
+const int AAH_TXSender::kHeartbeatIntervalUs = 1000000;
+const int AAH_TXSender::kRetryBufferCapacity = 100;
+const nsecs_t AAH_TXSender::kHeartbeatTimeout = 600ull * 1000000000ull;
+
+Mutex AAH_TXSender::sLock;
+wp<AAH_TXSender> AAH_TXSender::sInstance;
+uint32_t AAH_TXSender::sNextEpoch;
+bool AAH_TXSender::sNextEpochValid = false;
+
+AAH_TXSender::AAH_TXSender() : mSocket(-1) {
+ mLastSentPacketTime = systemTime();
+}
+
+sp<AAH_TXSender> AAH_TXSender::GetInstance() {
+ Mutex::Autolock autoLock(sLock);
+
+ sp<AAH_TXSender> sender = sInstance.promote();
+
+ if (sender == NULL) {
+ sender = new AAH_TXSender();
+ if (sender == NULL) {
+ return NULL;
+ }
+
+ sender->mLooper = new ALooper();
+ if (sender->mLooper == NULL) {
+ return NULL;
+ }
+
+ sender->mReflector = new AHandlerReflector<AAH_TXSender>(sender.get());
+ if (sender->mReflector == NULL) {
+ return NULL;
+ }
+
+ sender->mSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sender->mSocket == -1) {
+ ALOGW("%s unable to create socket", __PRETTY_FUNCTION__);
+ return NULL;
+ }
+
+ struct sockaddr_in bind_addr;
+ memset(&bind_addr, 0, sizeof(bind_addr));
+ bind_addr.sin_family = AF_INET;
+ if (bind(sender->mSocket,
+ reinterpret_cast<const sockaddr*>(&bind_addr),
+ sizeof(bind_addr)) < 0) {
+ ALOGW("%s unable to bind socket (errno %d)",
+ __PRETTY_FUNCTION__, errno);
+ return NULL;
+ }
+
+ sender->mRetryReceiver = new RetryReceiver(sender.get());
+ if (sender->mRetryReceiver == NULL) {
+ return NULL;
+ }
+
+ sender->mLooper->setName("AAH_TXSender");
+ sender->mLooper->registerHandler(sender->mReflector);
+ sender->mLooper->start(false, false, PRIORITY_AUDIO);
+
+ if (sender->mRetryReceiver->run("AAH_TXSenderRetry", PRIORITY_AUDIO)
+ != OK) {
+ ALOGW("%s unable to start retry thread", __PRETTY_FUNCTION__);
+ return NULL;
+ }
+
+ sInstance = sender;
+ }
+
+ return sender;
+}
+
+AAH_TXSender::~AAH_TXSender() {
+ mLooper->stop();
+ mLooper->unregisterHandler(mReflector->id());
+
+ if (mRetryReceiver != NULL) {
+ mRetryReceiver->requestExit();
+ mRetryReceiver->mWakeupEvent.setEvent();
+ if (mRetryReceiver->requestExitAndWait() != OK) {
+ ALOGW("%s shutdown of retry receiver failed", __PRETTY_FUNCTION__);
+ }
+ mRetryReceiver->mSender = NULL;
+ mRetryReceiver.clear();
+ }
+
+ if (mSocket != -1) {
+ close(mSocket);
+ }
+}
+
+// Return the next epoch number usable for a newly instantiated endpoint.
+uint32_t AAH_TXSender::getNextEpoch() {
+ Mutex::Autolock autoLock(sLock);
+
+ if (sNextEpochValid) {
+ sNextEpoch = (sNextEpoch + 1) & TRTPPacket::kTRTPEpochMask;
+ } else {
+ sNextEpoch = ns2ms(systemTime()) & TRTPPacket::kTRTPEpochMask;
+ sNextEpochValid = true;
+ }
+
+ return sNextEpoch;
+}
+
+// Notify the sender that a player has started sending to this endpoint.
+// Returns a program ID for use by the calling player.
+uint16_t AAH_TXSender::registerEndpoint(const Endpoint& endpoint) {
+ Mutex::Autolock lock(mEndpointLock);
+
+ EndpointState* eps = mEndpointMap.valueFor(endpoint);
+ if (eps) {
+ eps->playerRefCount++;
+ } else {
+ eps = new EndpointState(getNextEpoch());
+ mEndpointMap.add(endpoint, eps);
+ }
+
+ // if this is the first registered endpoint, then send a message to start
+ // trimming retry buffers and a message to start sending heartbeats.
+ if (mEndpointMap.size() == 1) {
+ sp<AMessage> trimMessage = new AMessage(kWhatTrimRetryBuffers,
+ handlerID());
+ trimMessage->post(kRetryTrimIntervalUs);
+
+ sp<AMessage> heartbeatMessage = new AMessage(kWhatSendHeartbeats,
+ handlerID());
+ heartbeatMessage->post(kHeartbeatIntervalUs);
+ }
+
+ eps->nextProgramID++;
+ return eps->nextProgramID;
+}
+
+// Notify the sender that a player has ceased sending to this endpoint.
+// An endpoint's state can not be deleted until all of the endpoint's
+// registered players have called unregisterEndpoint.
+void AAH_TXSender::unregisterEndpoint(const Endpoint& endpoint) {
+ Mutex::Autolock lock(mEndpointLock);
+
+ EndpointState* eps = mEndpointMap.valueFor(endpoint);
+ if (eps) {
+ eps->playerRefCount--;
+ CHECK(eps->playerRefCount >= 0);
+ }
+}
+
+void AAH_TXSender::onMessageReceived(const sp<AMessage>& msg) {
+ switch (msg->what()) {
+ case kWhatSendPacket:
+ onSendPacket(msg);
+ break;
+
+ case kWhatTrimRetryBuffers:
+ trimRetryBuffers();
+ break;
+
+ case kWhatSendHeartbeats:
+ sendHeartbeats();
+ break;
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+void AAH_TXSender::onSendPacket(const sp<AMessage>& msg) {
+ sp<RefBase> obj;
+ CHECK(msg->findObject(kSendPacketTRTPPacket, &obj));
+ sp<TRTPPacket> packet = static_cast<TRTPPacket*>(obj.get());
+
+ uint32_t ipAddr;
+ CHECK(msg->findInt32(kSendPacketIPAddr,
+ reinterpret_cast<int32_t*>(&ipAddr)));
+
+ int32_t port32;
+ CHECK(msg->findInt32(kSendPacketPort, &port32));
+ uint16_t port = port32;
+
+ Mutex::Autolock lock(mEndpointLock);
+ doSendPacket_l(packet, Endpoint(ipAddr, port));
+ mLastSentPacketTime = systemTime();
+}
+
+void AAH_TXSender::doSendPacket_l(const sp<TRTPPacket>& packet,
+ const Endpoint& endpoint) {
+ EndpointState* eps = mEndpointMap.valueFor(endpoint);
+ if (!eps) {
+ // the endpoint state has disappeared, so the player that sent this
+ // packet must be dead.
+ return;
+ }
+
+ // assign the packet's sequence number
+ packet->setEpoch(eps->epoch);
+ packet->setSeqNumber(eps->trtpSeqNumber++);
+
+ // add the packet to the retry buffer
+ RetryBuffer& retry = eps->retry;
+ retry.push_back(packet);
+
+ // send the packet
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = endpoint.addr;
+ addr.sin_port = endpoint.port;
+
+ ssize_t result = sendto(mSocket,
+ packet->getPacket(),
+ packet->getPacketLen(),
+ 0,
+ (const struct sockaddr *) &addr,
+ sizeof(addr));
+ if (result == -1) {
+ ALOGW("%s sendto failed", __PRETTY_FUNCTION__);
+ }
+}
+
+void AAH_TXSender::trimRetryBuffers() {
+ Mutex::Autolock lock(mEndpointLock);
+
+ nsecs_t localTimeNow = systemTime();
+
+ Vector<Endpoint> endpointsToRemove;
+
+ for (size_t i = 0; i < mEndpointMap.size(); i++) {
+ EndpointState* eps = mEndpointMap.editValueAt(i);
+ RetryBuffer& retry = eps->retry;
+
+ while (!retry.isEmpty()) {
+ if (retry[0]->getExpireTime() < localTimeNow) {
+ retry.pop_front();
+ } else {
+ break;
+ }
+ }
+
+ if (retry.isEmpty() && eps->playerRefCount == 0) {
+ endpointsToRemove.add(mEndpointMap.keyAt(i));
+ }
+ }
+
+ // remove the state for any endpoints that are no longer in use
+ for (size_t i = 0; i < endpointsToRemove.size(); i++) {
+ Endpoint& e = endpointsToRemove.editItemAt(i);
+ ALOGD("*** %s removing endpoint addr=%08x",
+ __PRETTY_FUNCTION__, e.addr);
+ size_t index = mEndpointMap.indexOfKey(e);
+ delete mEndpointMap.valueAt(index);
+ mEndpointMap.removeItemsAt(index);
+ }
+
+ // schedule the next trim
+ if (mEndpointMap.size()) {
+ sp<AMessage> trimMessage = new AMessage(kWhatTrimRetryBuffers,
+ handlerID());
+ trimMessage->post(kRetryTrimIntervalUs);
+ }
+}
+
+void AAH_TXSender::sendHeartbeats() {
+ Mutex::Autolock lock(mEndpointLock);
+
+ if (shouldSendHeartbeats_l()) {
+ for (size_t i = 0; i < mEndpointMap.size(); i++) {
+ EndpointState* eps = mEndpointMap.editValueAt(i);
+ const Endpoint& ep = mEndpointMap.keyAt(i);
+
+ sp<TRTPControlPacket> packet = new TRTPControlPacket();
+ packet->setCommandID(TRTPControlPacket::kCommandNop);
+
+ packet->setExpireTime(systemTime() +
+ AAH_TXPlayer::kAAHRetryKeepAroundTimeNs);
+ packet->pack();
+
+ doSendPacket_l(packet, ep);
+ }
+ }
+
+ // schedule the next heartbeat
+ if (mEndpointMap.size()) {
+ sp<AMessage> heartbeatMessage = new AMessage(kWhatSendHeartbeats,
+ handlerID());
+ heartbeatMessage->post(kHeartbeatIntervalUs);
+ }
+}
+
+bool AAH_TXSender::shouldSendHeartbeats_l() {
+ // assert(holding endpoint lock)
+ return (systemTime() < (mLastSentPacketTime + kHeartbeatTimeout));
+}
+
+// Receiver
+
+// initial 4-byte ID of a retry request packet
+const uint32_t AAH_TXSender::RetryReceiver::kRetryRequestID = 'Treq';
+
+// initial 4-byte ID of a retry NAK packet
+const uint32_t AAH_TXSender::RetryReceiver::kRetryNakID = 'Tnak';
+
+// initial 4-byte ID of a fast start request packet
+const uint32_t AAH_TXSender::RetryReceiver::kFastStartRequestID = 'Tfst';
+
+AAH_TXSender::RetryReceiver::RetryReceiver(AAH_TXSender* sender)
+ : Thread(false),
+ mSender(sender) {}
+
+ AAH_TXSender::RetryReceiver::~RetryReceiver() {
+ mWakeupEvent.clearPendingEvents();
+ }
+
+// Returns true if val is within the interval bounded inclusively by
+// start and end. Also handles the case where there is a rollover of the
+// range between start and end.
+template <typename T>
+static inline bool withinIntervalWithRollover(T val, T start, T end) {
+ return ((start <= end && val >= start && val <= end) ||
+ (start > end && (val >= start || val <= end)));
+}
+
+bool AAH_TXSender::RetryReceiver::threadLoop() {
+ struct pollfd pollFds[2];
+ pollFds[0].fd = mSender->mSocket;
+ pollFds[0].events = POLLIN;
+ pollFds[0].revents = 0;
+ pollFds[1].fd = mWakeupEvent.getWakeupHandle();
+ pollFds[1].events = POLLIN;
+ pollFds[1].revents = 0;
+
+ int pollResult = poll(pollFds, NELEM(pollFds), -1);
+ if (pollResult == -1) {
+ ALOGE("%s poll failed", __PRETTY_FUNCTION__);
+ return false;
+ }
+
+ if (exitPending()) {
+ ALOGI("*** %s exiting", __PRETTY_FUNCTION__);
+ return false;
+ }
+
+ if (pollFds[0].revents) {
+ handleRetryRequest();
+ }
+
+ return true;
+}
+
+void AAH_TXSender::RetryReceiver::handleRetryRequest() {
+ ALOGV("*** RX %s start", __PRETTY_FUNCTION__);
+
+ RetryPacket request;
+ struct sockaddr requestSrcAddr;
+ socklen_t requestSrcAddrLen = sizeof(requestSrcAddr);
+
+ ssize_t result = recvfrom(mSender->mSocket, &request, sizeof(request), 0,
+ &requestSrcAddr, &requestSrcAddrLen);
+ if (result == -1) {
+ ALOGE("%s recvfrom failed, errno=%d", __PRETTY_FUNCTION__, errno);
+ return;
+ }
+
+ if (static_cast<size_t>(result) < sizeof(RetryPacket)) {
+ ALOGW("%s short packet received", __PRETTY_FUNCTION__);
+ return;
+ }
+
+ uint32_t host_request_id = ntohl(request.id);
+ if ((host_request_id != kRetryRequestID) &&
+ (host_request_id != kFastStartRequestID)) {
+ ALOGW("%s received retry request with bogus ID (%08x)",
+ __PRETTY_FUNCTION__, host_request_id);
+ return;
+ }
+
+ Endpoint endpoint(request.endpointIP, request.endpointPort);
+
+ Mutex::Autolock lock(mSender->mEndpointLock);
+
+ EndpointState* eps = mSender->mEndpointMap.valueFor(endpoint);
+
+ if (eps == NULL || eps->retry.isEmpty()) {
+ // we have no retry buffer or an empty retry buffer for this endpoint,
+ // so NAK the entire request
+ RetryPacket nak = request;
+ nak.id = htonl(kRetryNakID);
+ result = sendto(mSender->mSocket, &nak, sizeof(nak), 0,
+ &requestSrcAddr, requestSrcAddrLen);
+ if (result == -1) {
+ ALOGW("%s sendto failed", __PRETTY_FUNCTION__);
+ }
+ return;
+ }
+
+ RetryBuffer& retry = eps->retry;
+
+ uint16_t startSeq = ntohs(request.seqStart);
+ uint16_t endSeq = ntohs(request.seqEnd);
+
+ uint16_t retryFirstSeq = retry[0]->getSeqNumber();
+ uint16_t retryLastSeq = retry[retry.size() - 1]->getSeqNumber();
+
+ // If this is a fast start, then force the start of the retry to match the
+ // start of the retransmit ring buffer (unless the end of the retransmit
+ // ring buffer is already past the point of fast start)
+ if ((host_request_id == kFastStartRequestID) &&
+ !((startSeq - retryFirstSeq) & 0x8000)) {
+ startSeq = retryFirstSeq;
+ }
+
+ int startIndex;
+ if (withinIntervalWithRollover(startSeq, retryFirstSeq, retryLastSeq)) {
+ startIndex = static_cast<uint16_t>(startSeq - retryFirstSeq);
+ } else {
+ startIndex = -1;
+ }
+
+ int endIndex;
+ if (withinIntervalWithRollover(endSeq, retryFirstSeq, retryLastSeq)) {
+ endIndex = static_cast<uint16_t>(endSeq - retryFirstSeq);
+ } else {
+ endIndex = -1;
+ }
+
+ if (startIndex == -1 && endIndex == -1) {
+ // no part of the request range is found in the retry buffer
+ RetryPacket nak = request;
+ nak.id = htonl(kRetryNakID);
+ result = sendto(mSender->mSocket, &nak, sizeof(nak), 0,
+ &requestSrcAddr, requestSrcAddrLen);
+ if (result == -1) {
+ ALOGW("%s sendto failed", __PRETTY_FUNCTION__);
+ }
+ return;
+ }
+
+ if (startIndex == -1) {
+ // NAK a subrange at the front of the request range
+ RetryPacket nak = request;
+ nak.id = htonl(kRetryNakID);
+ nak.seqEnd = htons(retryFirstSeq - 1);
+ result = sendto(mSender->mSocket, &nak, sizeof(nak), 0,
+ &requestSrcAddr, requestSrcAddrLen);
+ if (result == -1) {
+ ALOGW("%s sendto failed", __PRETTY_FUNCTION__);
+ }
+
+ startIndex = 0;
+ } else if (endIndex == -1) {
+ // NAK a subrange at the back of the request range
+ RetryPacket nak = request;
+ nak.id = htonl(kRetryNakID);
+ nak.seqStart = htons(retryLastSeq + 1);
+ result = sendto(mSender->mSocket, &nak, sizeof(nak), 0,
+ &requestSrcAddr, requestSrcAddrLen);
+ if (result == -1) {
+ ALOGW("%s sendto failed", __PRETTY_FUNCTION__);
+ }
+
+ endIndex = retry.size() - 1;
+ }
+
+ // send the retry packets
+ for (int i = startIndex; i <= endIndex; i++) {
+ const sp<TRTPPacket>& replyPacket = retry[i];
+
+ result = sendto(mSender->mSocket,
+ replyPacket->getPacket(),
+ replyPacket->getPacketLen(),
+ 0,
+ &requestSrcAddr,
+ requestSrcAddrLen);
+
+ if (result == -1) {
+ ALOGW("%s sendto failed", __PRETTY_FUNCTION__);
+ }
+ }
+}
+
+// Endpoint
+
+AAH_TXSender::Endpoint::Endpoint()
+ : addr(0)
+ , port(0) { }
+
+AAH_TXSender::Endpoint::Endpoint(uint32_t a, uint16_t p)
+ : addr(a)
+ , port(p) {}
+
+bool AAH_TXSender::Endpoint::operator<(const Endpoint& other) const {
+ return ((addr < other.addr) ||
+ (addr == other.addr && port < other.port));
+}
+
+// EndpointState
+
+AAH_TXSender::EndpointState::EndpointState(uint32_t _epoch)
+ : retry(kRetryBufferCapacity)
+ , playerRefCount(1)
+ , trtpSeqNumber(0)
+ , nextProgramID(0)
+ , epoch(_epoch) { }
+
+// CircularBuffer
+
+template <typename T>
+CircularBuffer<T>::CircularBuffer(size_t capacity)
+ : mCapacity(capacity)
+ , mHead(0)
+ , mTail(0)
+ , mFillCount(0) {
+ mBuffer = new T[capacity];
+}
+
+template <typename T>
+CircularBuffer<T>::~CircularBuffer() {
+ delete [] mBuffer;
+}
+
+template <typename T>
+void CircularBuffer<T>::push_back(const T& item) {
+ if (this->isFull()) {
+ this->pop_front();
+ }
+ mBuffer[mHead] = item;
+ mHead = (mHead + 1) % mCapacity;
+ mFillCount++;
+}
+
+template <typename T>
+void CircularBuffer<T>::pop_front() {
+ CHECK(!isEmpty());
+ mBuffer[mTail] = T();
+ mTail = (mTail + 1) % mCapacity;
+ mFillCount--;
+}
+
+template <typename T>
+size_t CircularBuffer<T>::size() const {
+ return mFillCount;
+}
+
+template <typename T>
+bool CircularBuffer<T>::isFull() const {
+ return (mFillCount == mCapacity);
+}
+
+template <typename T>
+bool CircularBuffer<T>::isEmpty() const {
+ return (mFillCount == 0);
+}
+
+template <typename T>
+const T& CircularBuffer<T>::itemAt(size_t index) const {
+ CHECK(index < mFillCount);
+ return mBuffer[(mTail + index) % mCapacity];
+}
+
+template <typename T>
+const T& CircularBuffer<T>::operator[](size_t index) const {
+ return itemAt(index);
+}
+
+} // namespace android
diff --git a/media/libaah_rtp/aah_tx_sender.h b/media/libaah_rtp/aah_tx_sender.h
new file mode 100644
index 0000000..74206c4
--- /dev/null
+++ b/media/libaah_rtp/aah_tx_sender.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 __AAH_TX_SENDER_H__
+#define __AAH_TX_SENDER_H__
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AHandlerReflector.h>
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+#include "aah_tx_packet.h"
+#include "pipe_event.h"
+
+namespace android {
+
+template <typename T> class CircularBuffer {
+ public:
+ CircularBuffer(size_t capacity);
+ ~CircularBuffer();
+ void push_back(const T& item);;
+ void pop_front();
+ size_t size() const;
+ bool isFull() const;
+ bool isEmpty() const;
+ const T& itemAt(size_t index) const;
+ const T& operator[](size_t index) const;
+
+ private:
+ T* mBuffer;
+ size_t mCapacity;
+ size_t mHead;
+ size_t mTail;
+ size_t mFillCount;
+
+ DISALLOW_EVIL_CONSTRUCTORS(CircularBuffer);
+};
+
+class AAH_TXSender : public virtual RefBase {
+ public:
+ ~AAH_TXSender();
+
+ static sp<AAH_TXSender> GetInstance();
+
+ ALooper::handler_id handlerID() { return mReflector->id(); }
+
+ // an IP address and port
+ struct Endpoint {
+ Endpoint();
+ Endpoint(uint32_t a, uint16_t p);
+ bool operator<(const Endpoint& other) const;
+
+ uint32_t addr;
+ uint16_t port;
+ };
+
+ uint16_t registerEndpoint(const Endpoint& endpoint);
+ void unregisterEndpoint(const Endpoint& endpoint);
+
+ enum {
+ kWhatSendPacket,
+ kWhatTrimRetryBuffers,
+ kWhatSendHeartbeats,
+ };
+
+ // fields for SendPacket messages
+ static const char* kSendPacketIPAddr;
+ static const char* kSendPacketPort;
+ static const char* kSendPacketTRTPPacket;
+
+ private:
+ AAH_TXSender();
+
+ static Mutex sLock;
+ static wp<AAH_TXSender> sInstance;
+ static uint32_t sNextEpoch;
+ static bool sNextEpochValid;
+
+ static uint32_t getNextEpoch();
+
+ typedef CircularBuffer<sp<TRTPPacket> > RetryBuffer;
+
+ // state maintained on a per-endpoint basis
+ struct EndpointState {
+ EndpointState(uint32_t epoch);
+ RetryBuffer retry;
+ int playerRefCount;
+ uint16_t trtpSeqNumber;
+ uint16_t nextProgramID;
+ uint32_t epoch;
+ };
+
+ friend class AHandlerReflector<AAH_TXSender>;
+ void onMessageReceived(const sp<AMessage>& msg);
+ void onSendPacket(const sp<AMessage>& msg);
+ void doSendPacket_l(const sp<TRTPPacket>& packet,
+ const Endpoint& endpoint);
+ void trimRetryBuffers();
+ void sendHeartbeats();
+ bool shouldSendHeartbeats_l();
+
+ sp<ALooper> mLooper;
+ sp<AHandlerReflector<AAH_TXSender> > mReflector;
+
+ int mSocket;
+ nsecs_t mLastSentPacketTime;
+
+ DefaultKeyedVector<Endpoint, EndpointState*> mEndpointMap;
+ Mutex mEndpointLock;
+
+ static const int kRetryTrimIntervalUs;
+ static const int kHeartbeatIntervalUs;
+ static const int kRetryBufferCapacity;
+ static const nsecs_t kHeartbeatTimeout;
+
+ class RetryReceiver : public Thread {
+ private:
+ friend class AAH_TXSender;
+
+ RetryReceiver(AAH_TXSender* sender);
+ virtual ~RetryReceiver();
+ virtual bool threadLoop();
+ void handleRetryRequest();
+
+ static const int kMaxReceiverPacketLen;
+ static const uint32_t kRetryRequestID;
+ static const uint32_t kFastStartRequestID;
+ static const uint32_t kRetryNakID;
+
+ AAH_TXSender* mSender;
+ PipeEvent mWakeupEvent;
+ };
+
+ sp<RetryReceiver> mRetryReceiver;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AAH_TXSender);
+};
+
+struct RetryPacket {
+ uint32_t id;
+ uint32_t endpointIP;
+ uint16_t endpointPort;
+ uint16_t seqStart;
+ uint16_t seqEnd;
+} __attribute__((packed));
+
+} // namespace android
+
+#endif // __AAH_TX_SENDER_H__
diff --git a/media/libaah_rtp/pipe_event.cpp b/media/libaah_rtp/pipe_event.cpp
new file mode 100644
index 0000000..b8e6960
--- /dev/null
+++ b/media/libaah_rtp/pipe_event.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "LibAAH_RTP"
+#include <utils/Log.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <unistd.h>
+
+#include "pipe_event.h"
+
+namespace android {
+
+PipeEvent::PipeEvent() {
+ pipe_[0] = -1;
+ pipe_[1] = -1;
+
+ // Create the pipe.
+ if (pipe(pipe_) >= 0) {
+ // Set non-blocking mode on the read side of the pipe so we can
+ // easily drain it whenever we wakeup.
+ fcntl(pipe_[0], F_SETFL, O_NONBLOCK);
+ } else {
+ ALOGE("Failed to create pipe event %d %d %d",
+ pipe_[0], pipe_[1], errno);
+ pipe_[0] = -1;
+ pipe_[1] = -1;
+ }
+}
+
+PipeEvent::~PipeEvent() {
+ if (pipe_[0] >= 0) {
+ close(pipe_[0]);
+ }
+
+ if (pipe_[1] >= 0) {
+ close(pipe_[1]);
+ }
+}
+
+void PipeEvent::clearPendingEvents() {
+ char drain_buffer[16];
+ while (read(pipe_[0], drain_buffer, sizeof(drain_buffer)) > 0) {
+ // No body.
+ }
+}
+
+bool PipeEvent::wait(int timeout) {
+ struct pollfd wait_fd;
+
+ wait_fd.fd = getWakeupHandle();
+ wait_fd.events = POLLIN;
+ wait_fd.revents = 0;
+
+ int res = poll(&wait_fd, 1, timeout);
+
+ if (res < 0) {
+ ALOGE("Wait error in PipeEvent; sleeping to prevent overload!");
+ usleep(1000);
+ }
+
+ return (res > 0);
+}
+
+void PipeEvent::setEvent() {
+ char foo = 'q';
+ write(pipe_[1], &foo, 1);
+}
+
+} // namespace android
+
diff --git a/media/libaah_rtp/pipe_event.h b/media/libaah_rtp/pipe_event.h
new file mode 100644
index 0000000..e53b0fd
--- /dev/null
+++ b/media/libaah_rtp/pipe_event.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 __PIPE_EVENT_H__
+#define __PIPE_EVENT_H__
+
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+
+class PipeEvent {
+ public:
+ PipeEvent();
+ ~PipeEvent();
+
+ bool initCheck() const {
+ return ((pipe_[0] >= 0) && (pipe_[1] >= 0));
+ }
+
+ int getWakeupHandle() const { return pipe_[0]; }
+
+ // block until the event fires; returns true if the event fired and false if
+ // the wait timed out. Timeout is expressed in milliseconds; negative
+ // values mean wait forever.
+ bool wait(int timeout = -1);
+
+ void clearPendingEvents();
+ void setEvent();
+
+ private:
+ int pipe_[2];
+
+ DISALLOW_EVIL_CONSTRUCTORS(PipeEvent);
+};
+
+} // namespace android
+
+#endif // __PIPE_EVENT_H__
diff --git a/media/libeffects/data/audio_effects.conf b/media/libeffects/data/audio_effects.conf
new file mode 100644
index 0000000..ce25bc8
--- /dev/null
+++ b/media/libeffects/data/audio_effects.conf
@@ -0,0 +1,126 @@
+# List of effect libraries to load. Each library element must contain a "path" element
+# giving the full path of the library .so file.
+# libraries {
+# <lib name> {
+# path <lib path>
+# }
+# }
+libraries {
+ bundle {
+ path /system/lib/soundfx/libbundlewrapper.so
+ }
+ reverb {
+ path /system/lib/soundfx/libreverbwrapper.so
+ }
+ visualizer {
+ path /system/lib/soundfx/libvisualizer.so
+ }
+ pre_processing {
+ path /system/lib/soundfx/libaudiopreprocessing.so
+ }
+}
+
+# list of effects to load. Each effect element must contain a "library" and a "uuid" element.
+# The value of the "library" element must correspond to the name of one library element in the
+# "libraries" element.
+# The name of the effect element is indicative, only the value of the "uuid" element
+# designates the effect.
+# The uuid is the implementation specific UUID as specified by the effect vendor. This is not the
+# generic effect type UUID.
+# effects {
+# <fx name> {
+# library <lib name>
+# uuid <effect uuid>
+# }
+# ...
+# }
+
+effects {
+ bassboost {
+ library bundle
+ uuid 8631f300-72e2-11df-b57e-0002a5d5c51b
+ }
+ virtualizer {
+ library bundle
+ uuid 1d4033c0-8557-11df-9f2d-0002a5d5c51b
+ }
+ equalizer {
+ library bundle
+ uuid ce772f20-847d-11df-bb17-0002a5d5c51b
+ }
+ volume {
+ library bundle
+ uuid 119341a0-8469-11df-81f9-0002a5d5c51b
+ }
+ reverb_env_aux {
+ library reverb
+ uuid 4a387fc0-8ab3-11df-8bad-0002a5d5c51b
+ }
+ reverb_env_ins {
+ library reverb
+ uuid c7a511a0-a3bb-11df-860e-0002a5d5c51b
+ }
+ reverb_pre_aux {
+ library reverb
+ uuid f29a1400-a3bb-11df-8ddc-0002a5d5c51b
+ }
+ reverb_pre_ins {
+ library reverb
+ uuid 172cdf00-a3bc-11df-a72f-0002a5d5c51b
+ }
+ visualizer {
+ library visualizer
+ uuid d069d9e0-8329-11df-9168-0002a5d5c51b
+ }
+ agc {
+ library pre_processing
+ uuid aa8130e0-66fc-11e0-bad0-0002a5d5c51b
+ }
+ aec {
+ library pre_processing
+ uuid bb392ec0-8d4d-11e0-a896-0002a5d5c51b
+ }
+ ns {
+ library pre_processing
+ uuid c06c8400-8e06-11e0-9cb6-0002a5d5c51b
+ }
+}
+# Audio preprocessor configurations.
+# The pre processor configuration consists in a list of elements each describing
+# pre processor settings for a given input source. Valid input source names are:
+# "mic", "camcorder", "voice_recognition", "voice_communication"
+# Each input source element contains a list of effects elements. The name of the effect
+# element must be the name of one of the effects in the "effects" list of the file.
+# Each effect element may optionally contain a list of parameters and their
+# default value to apply when the pre processor effect is created.
+# A parameter is defined by a "param" element and a "value" element. Each of these elements
+# consists in one or more elements specifying a type followed by a value.
+# The types defined are: "int", "short", "float", "bool" and "string"
+# When both "param" and "value" are a single int, a simple form is allowed where just
+# the param and value pair is present in the parameter description
+# pre_processing {
+# <input source name> {
+# <fx name> {
+# <param 1 name> {
+# param {
+# int|short|float|bool|string <value>
+# [ int|short|float|bool|string <value> ]
+# ...
+# }
+# value {
+# int|short|float|bool|string <value>
+# [ int|short|float|bool|string <value> ]
+# ...
+# }
+# }
+# <param 2 name > {<param> <value>}
+# ...
+# }
+# ...
+# }
+# ...
+# }
+
+#
+# TODO: add default audio pre processor configurations after debug and tuning phase
+#
diff --git a/media/libeffects/downmix/Android.mk b/media/libeffects/downmix/Android.mk
new file mode 100644
index 0000000..95ca6fd
--- /dev/null
+++ b/media/libeffects/downmix/Android.mk
@@ -0,0 +1,28 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Multichannel downmix effect library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ EffectDownmix.c
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils
+
+LOCAL_MODULE:= libdownmix
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, audio-effects) \
+ $(call include-path-for, audio-utils)
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
new file mode 100644
index 0000000..a325172
--- /dev/null
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -0,0 +1,889 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "EffectDownmix"
+#define LOG_NDEBUG 0
+#include <cutils/log.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include "EffectDownmix.h"
+
+#define MINUS_3_DB_IN_Q19_12 2896 // -3dB = 0.707 * 2^12 = 2896
+
+// effect_handle_t interface implementation for downmix effect
+const struct effect_interface_s gDownmixInterface = {
+ Downmix_Process,
+ Downmix_Command,
+ Downmix_GetDescriptor,
+ NULL /* no process_reverse function, no reference stream needed */
+};
+
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
+ tag : AUDIO_EFFECT_LIBRARY_TAG,
+ version : EFFECT_LIBRARY_API_VERSION,
+ name : "Downmix Library",
+ implementor : "The Android Open Source Project",
+ query_num_effects : DownmixLib_QueryNumberEffects,
+ query_effect : DownmixLib_QueryEffect,
+ create_effect : DownmixLib_Create,
+ release_effect : DownmixLib_Release,
+ get_descriptor : DownmixLib_GetDescriptor,
+};
+
+
+// AOSP insert downmix UUID: 93f04452-e4fe-41cc-91f9-e475b6d1d69f
+static const effect_descriptor_t gDownmixDescriptor = {
+ EFFECT_UIID_DOWNMIX__, //type
+ {0x93f04452, 0xe4fe, 0x41cc, 0x91f9, {0xe4, 0x75, 0xb6, 0xd1, 0xd6, 0x9f}}, // uuid
+ EFFECT_CONTROL_API_VERSION,
+ EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+ 0, //FIXME what value should be reported? // cpu load
+ 0, //FIXME what value should be reported? // memory usage
+ "Multichannel Downmix To Stereo", // human readable effect name
+ "The Android Open Source Project" // human readable effect implementor name
+};
+
+// gDescriptors contains pointers to all defined effect descriptor in this library
+static const effect_descriptor_t * const gDescriptors[] = {
+ &gDownmixDescriptor
+};
+
+// number of effects in this library
+const int kNbEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
+
+
+/*----------------------------------------------------------------------------
+ * Effect API implementation
+ *--------------------------------------------------------------------------*/
+
+/*--- Effect Library Interface Implementation ---*/
+
+int32_t DownmixLib_QueryNumberEffects(uint32_t *pNumEffects) {
+ ALOGV("DownmixLib_QueryNumberEffects()");
+ *pNumEffects = kNbEffects;
+ return 0;
+}
+
+int32_t DownmixLib_QueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) {
+ ALOGV("DownmixLib_QueryEffect() index=%d", index);
+ if (pDescriptor == NULL) {
+ return -EINVAL;
+ }
+ if (index >= (uint32_t)kNbEffects) {
+ return -EINVAL;
+ }
+ memcpy(pDescriptor, gDescriptors[index], sizeof(effect_descriptor_t));
+ return 0;
+}
+
+
+int32_t DownmixLib_Create(const effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_handle_t *pHandle) {
+ int ret;
+ int i;
+ downmix_module_t *module;
+ const effect_descriptor_t *desc;
+
+ ALOGV("DownmixLib_Create()");
+
+ if (pHandle == NULL || uuid == NULL) {
+ return -EINVAL;
+ }
+
+ for (i = 0 ; i < kNbEffects ; i++) {
+ desc = gDescriptors[i];
+ if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t)) == 0) {
+ break;
+ }
+ }
+
+ if (i == kNbEffects) {
+ return -ENOENT;
+ }
+
+ module = malloc(sizeof(downmix_module_t));
+
+ module->itfe = &gDownmixInterface;
+
+ module->context.state = DOWNMIX_STATE_UNINITIALIZED;
+
+ ret = Downmix_Init(module);
+ if (ret < 0) {
+ ALOGW("DownmixLib_Create() init failed");
+ free(module);
+ return ret;
+ }
+
+ *pHandle = (effect_handle_t) module;
+
+ ALOGV("DownmixLib_Create() %p , size %d", module, sizeof(downmix_module_t));
+
+ return 0;
+}
+
+
+int32_t DownmixLib_Release(effect_handle_t handle) {
+ downmix_module_t *pDwmModule = (downmix_module_t *)handle;
+
+ ALOGV("DownmixLib_Release() %p", handle);
+ if (handle == NULL) {
+ return -EINVAL;
+ }
+
+ pDwmModule->context.state = DOWNMIX_STATE_UNINITIALIZED;
+
+ free(pDwmModule);
+ return 0;
+}
+
+
+int32_t DownmixLib_GetDescriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) {
+ ALOGV("DownmixLib_GetDescriptor()");
+ int i;
+
+ if (pDescriptor == NULL || uuid == NULL){
+ ALOGE("DownmixLib_Create() called with NULL pointer");
+ return -EINVAL;
+ }
+ ALOGV("DownmixLib_GetDescriptor() nb effects=%d", kNbEffects);
+ for (i = 0; i < kNbEffects; i++) {
+ ALOGV("DownmixLib_GetDescriptor() i=%d", i);
+ if (memcmp(uuid, &gDescriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
+ memcpy(pDescriptor, gDescriptors[i], sizeof(effect_descriptor_t));
+ ALOGV("EffectGetDescriptor - UUID matched downmix type %d, UUID = %x",
+ i, gDescriptors[i]->uuid.timeLow);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+
+/*--- Effect Control Interface Implementation ---*/
+
+static int Downmix_Process(effect_handle_t self,
+ audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
+
+ downmix_object_t *pDownmixer;
+ int16_t *pSrc, *pDst;
+ downmix_module_t *pDwmModule = (downmix_module_t *)self;
+
+ if (pDwmModule == NULL) {
+ return -EINVAL;
+ }
+
+ if (inBuffer == NULL || inBuffer->raw == NULL ||
+ outBuffer == NULL || outBuffer->raw == NULL ||
+ inBuffer->frameCount != outBuffer->frameCount) {
+ return -EINVAL;
+ }
+
+ pDownmixer = (downmix_object_t*) &pDwmModule->context;
+
+ if (pDownmixer->state == DOWNMIX_STATE_UNINITIALIZED) {
+ ALOGE("Downmix_Process error: trying to use an uninitialized downmixer");
+ return -EINVAL;
+ } else if (pDownmixer->state == DOWNMIX_STATE_INITIALIZED) {
+ ALOGE("Downmix_Process error: trying to use a non-configured downmixer");
+ return -ENODATA;
+ }
+
+ pSrc = inBuffer->s16;
+ pDst = outBuffer->s16;
+ size_t numFrames = outBuffer->frameCount;
+
+ const bool accumulate =
+ (pDwmModule->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
+
+ switch(pDownmixer->type) {
+
+ case DOWNMIX_TYPE_STRIP:
+ if (accumulate) {
+ while (numFrames) {
+ pDst[0] = clamp16(pDst[0] + pSrc[0]);
+ pDst[1] = clamp16(pDst[1] + pSrc[1]);
+ pSrc += pDownmixer->input_channel_count;
+ pDst += 2;
+ numFrames--;
+ }
+ } else {
+ while (numFrames) {
+ pDst[0] = pSrc[0];
+ pDst[1] = pSrc[1];
+ pSrc += pDownmixer->input_channel_count;
+ pDst += 2;
+ numFrames--;
+ }
+ }
+ break;
+
+ case DOWNMIX_TYPE_FOLD:
+ // optimize for the common formats
+ switch(pDwmModule->config.inputCfg.channels) {
+ case AUDIO_CHANNEL_OUT_QUAD:
+ Downmix_foldFromQuad(pSrc, pDst, numFrames, accumulate);
+ break;
+ case AUDIO_CHANNEL_OUT_SURROUND:
+ Downmix_foldFromSurround(pSrc, pDst, numFrames, accumulate);
+ break;
+ case AUDIO_CHANNEL_OUT_5POINT1:
+ Downmix_foldFrom5Point1(pSrc, pDst, numFrames, accumulate);
+ break;
+ case AUDIO_CHANNEL_OUT_7POINT1:
+ Downmix_foldFrom7Point1(pSrc, pDst, numFrames, accumulate);
+ break;
+ default:
+ // FIXME implement generic downmix
+ ALOGE("Multichannel configurations other than quad, 4.0, 5.1 and 7.1 are not supported");
+ break;
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+static int Downmix_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
+ void *pCmdData, uint32_t *replySize, void *pReplyData) {
+
+ downmix_module_t *pDwmModule = (downmix_module_t *) self;
+ downmix_object_t *pDownmixer;
+ int retsize;
+
+ if (pDwmModule == NULL || pDwmModule->context.state == DOWNMIX_STATE_UNINITIALIZED) {
+ return -EINVAL;
+ }
+
+ pDownmixer = (downmix_object_t*) &pDwmModule->context;
+
+ ALOGV("Downmix_Command command %d cmdSize %d",cmdCode, cmdSize);
+
+ switch (cmdCode) {
+ case EFFECT_CMD_INIT:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Downmix_Init(pDwmModule);
+ break;
+
+ case EFFECT_CMD_SET_CONFIG:
+ if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+ || pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Downmix_Configure(pDwmModule,
+ (effect_config_t *)pCmdData, false);
+ break;
+
+ case EFFECT_CMD_RESET:
+ Downmix_Reset(pDownmixer, false);
+ break;
+
+ case EFFECT_CMD_GET_PARAM:
+ ALOGV("Downmix_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) + 2 * sizeof(int32_t)) {
+ return -EINVAL;
+ }
+ effect_param_t *rep = (effect_param_t *) pReplyData;
+ memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(int32_t));
+ ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM param %d, replySize %d",
+ *(int32_t *)rep->data, rep->vsize);
+ rep->status = Downmix_getParameter(pDownmixer, *(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:
+ ALOGV("Downmix_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 = Downmix_setParameter(pDownmixer, *(int32_t *)cmd->data,
+ cmd->vsize, cmd->data + sizeof(int32_t));
+ break;
+
+ case EFFECT_CMD_SET_PARAM_DEFERRED:
+ //FIXME implement
+ ALOGW("Downmix_Command command EFFECT_CMD_SET_PARAM_DEFERRED not supported, FIXME");
+ break;
+
+ case EFFECT_CMD_SET_PARAM_COMMIT:
+ //FIXME implement
+ ALOGW("Downmix_Command command EFFECT_CMD_SET_PARAM_COMMIT not supported, FIXME");
+ break;
+
+ case EFFECT_CMD_ENABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ if (pDownmixer->state != DOWNMIX_STATE_INITIALIZED) {
+ return -ENOSYS;
+ }
+ pDownmixer->state = DOWNMIX_STATE_ACTIVE;
+ ALOGV("EFFECT_CMD_ENABLE() OK");
+ *(int *)pReplyData = 0;
+ break;
+
+ case EFFECT_CMD_DISABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ if (pDownmixer->state != DOWNMIX_STATE_ACTIVE) {
+ return -ENOSYS;
+ }
+ pDownmixer->state = DOWNMIX_STATE_INITIALIZED;
+ ALOGV("EFFECT_CMD_DISABLE() OK");
+ *(int *)pReplyData = 0;
+ break;
+
+ case EFFECT_CMD_SET_DEVICE:
+ if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
+ return -EINVAL;
+ }
+ // FIXME change type if playing on headset vs speaker
+ ALOGV("Downmix_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;
+ }
+ // FIXME change volume
+ ALOGW("Downmix_Command command EFFECT_CMD_SET_VOLUME not supported, FIXME");
+ float left = (float)(*(uint32_t *)pCmdData) / (1 << 24);
+ float right = (float)(*((uint32_t *)pCmdData + 1)) / (1 << 24);
+ ALOGV("Downmix_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;
+ }
+ ALOGV("Downmix_Command EFFECT_CMD_SET_AUDIO_MODE: %d", *(uint32_t *)pCmdData);
+ break;
+
+ case EFFECT_CMD_SET_CONFIG_REVERSE:
+ case EFFECT_CMD_SET_INPUT_DEVICE:
+ // these commands are ignored by a downmix effect
+ break;
+
+ default:
+ ALOGW("Downmix_Command invalid command %d",cmdCode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+int Downmix_GetDescriptor(effect_handle_t self, effect_descriptor_t *pDescriptor)
+{
+ downmix_module_t *pDwnmxModule = (downmix_module_t *) self;
+
+ if (pDwnmxModule == NULL ||
+ pDwnmxModule->context.state == DOWNMIX_STATE_UNINITIALIZED) {
+ return -EINVAL;
+ }
+
+ memcpy(pDescriptor, &gDownmixDescriptor, sizeof(effect_descriptor_t));
+
+ return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix internal functions
+ *--------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Downmix_Init()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initialize downmix context and apply default parameters
+ *
+ * Inputs:
+ * pDwmModule pointer to downmix effect module
+ *
+ * Outputs:
+ *
+ * Returns:
+ * 0 indicates success
+ *
+ * Side Effects:
+ * updates:
+ * pDwmModule->context.type
+ * pDwmModule->context.apply_volume_correction
+ * pDwmModule->config.inputCfg
+ * pDwmModule->config.outputCfg
+ * pDwmModule->config.inputCfg.samplingRate
+ * pDwmModule->config.outputCfg.samplingRate
+ * pDwmModule->context.state
+ * doesn't set:
+ * pDwmModule->itfe
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int Downmix_Init(downmix_module_t *pDwmModule) {
+
+ ALOGV("Downmix_Init module %p", pDwmModule);
+ int ret = 0;
+
+ memset(&pDwmModule->context, 0, sizeof(downmix_object_t));
+
+ pDwmModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+ pDwmModule->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ pDwmModule->config.inputCfg.channels = AUDIO_CHANNEL_OUT_7POINT1;
+ pDwmModule->config.inputCfg.bufferProvider.getBuffer = NULL;
+ pDwmModule->config.inputCfg.bufferProvider.releaseBuffer = NULL;
+ pDwmModule->config.inputCfg.bufferProvider.cookie = NULL;
+ pDwmModule->config.inputCfg.mask = EFFECT_CONFIG_ALL;
+
+ pDwmModule->config.inputCfg.samplingRate = 44100;
+ pDwmModule->config.outputCfg.samplingRate = pDwmModule->config.inputCfg.samplingRate;
+
+ // set a default value for the access mode, but should be overwritten by caller
+ pDwmModule->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+ pDwmModule->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ pDwmModule->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ pDwmModule->config.outputCfg.bufferProvider.getBuffer = NULL;
+ pDwmModule->config.outputCfg.bufferProvider.releaseBuffer = NULL;
+ pDwmModule->config.outputCfg.bufferProvider.cookie = NULL;
+ pDwmModule->config.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+ ret = Downmix_Configure(pDwmModule, &pDwmModule->config, true);
+ if (ret != 0) {
+ ALOGV("Downmix_Init error %d on module %p", ret, pDwmModule);
+ } else {
+ pDwmModule->context.state = DOWNMIX_STATE_INITIALIZED;
+ }
+
+ return ret;
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_Configure()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set input and output audio configuration.
+ *
+ * Inputs:
+ * pDwmModule pointer to downmix effect module
+ * pConfig pointer to effect_config_t structure containing input
+ * and output audio parameters configuration
+ * init true if called from init function
+ *
+ * Outputs:
+ *
+ * Returns:
+ * 0 indicates success
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int Downmix_Configure(downmix_module_t *pDwmModule, effect_config_t *pConfig, bool init) {
+
+ downmix_object_t *pDownmixer = &pDwmModule->context;
+
+ // Check configuration compatibility with build options, and effect capabilities
+ if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate
+ || pConfig->outputCfg.channels != DOWNMIX_OUTPUT_CHANNELS
+ || pConfig->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT
+ || pConfig->outputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
+ ALOGE("Downmix_Configure error: invalid config");
+ return -EINVAL;
+ }
+
+ memcpy(&pDwmModule->config, pConfig, sizeof(effect_config_t));
+
+ if (init) {
+ pDownmixer->type = DOWNMIX_TYPE_FOLD;
+ pDownmixer->apply_volume_correction = false;
+ pDownmixer->input_channel_count = 8; // matches default input of AUDIO_CHANNEL_OUT_7POINT1
+ } else {
+ // when configuring the effect, do not allow a blank channel mask
+ if (pConfig->inputCfg.channels == 0) {
+ ALOGE("Downmix_Configure error: input channel mask can't be 0");
+ return -EINVAL;
+ }
+ pDownmixer->input_channel_count = popcount(pConfig->inputCfg.channels);
+ }
+
+ Downmix_Reset(pDownmixer, init);
+
+ return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_Reset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Reset internal states.
+ *
+ * Inputs:
+ * pDownmixer pointer to downmix context
+ * init true if called from init function
+ *
+ * Outputs:
+*
+ * Returns:
+ * 0 indicates success
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int Downmix_Reset(downmix_object_t *pDownmixer, bool init) {
+ // nothing to do here
+ return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_setParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set a Downmix parameter
+ *
+ * Inputs:
+ * pDownmixer handle to instance data
+ * param parameter
+ * pValue pointer to parameter value
+ * size value size
+ *
+ * Outputs:
+ *
+ * Returns:
+ * 0 indicates success
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t size, void *pValue) {
+
+ int16_t value16;
+ ALOGV("Downmix_setParameter, context %p, param %d, value16 %d, value32 %d",
+ pDownmixer, param, *(int16_t *)pValue, *(int32_t *)pValue);
+
+ switch (param) {
+
+ case DOWNMIX_PARAM_TYPE:
+ if (size != sizeof(downmix_type_t)) {
+ ALOGE("Downmix_setParameter(DOWNMIX_PARAM_TYPE) invalid size %d, should be %d",
+ size, sizeof(downmix_type_t));
+ return -EINVAL;
+ }
+ value16 = *(int16_t *)pValue;
+ ALOGV("set DOWNMIX_PARAM_TYPE, type %d", value16);
+ if (!((value16 > DOWNMIX_TYPE_INVALID) && (value16 < DOWNMIX_TYPE_LAST))) {
+ ALOGE("Downmix_setParameter invalid DOWNMIX_PARAM_TYPE value %d", value16);
+ return -EINVAL;
+ } else {
+ pDownmixer->type = (downmix_type_t) value16;
+ break;
+
+ default:
+ ALOGE("Downmix_setParameter unknown parameter %d", param);
+ return -EINVAL;
+ }
+}
+
+ return 0;
+} /* end Downmix_setParameter */
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_getParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Get a Downmix parameter
+ *
+ * Inputs:
+ * pDownmixer 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
+ *
+ * Returns:
+ * 0 indicates success
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, size_t *pSize, void *pValue) {
+ int16_t *pValue16;
+
+ switch (param) {
+
+ case DOWNMIX_PARAM_TYPE:
+ if (*pSize < sizeof(int16_t)) {
+ ALOGE("Downmix_getParameter invalid parameter size %d for DOWNMIX_PARAM_TYPE", *pSize);
+ return -EINVAL;
+ }
+ pValue16 = (int16_t *)pValue;
+ *pValue16 = (int16_t) pDownmixer->type;
+ *pSize = sizeof(int16_t);
+ ALOGV("Downmix_getParameter DOWNMIX_PARAM_TYPE is %d", *pValue16);
+ break;
+
+ default:
+ ALOGE("Downmix_getParameter unknown parameter %d", param);
+ return -EINVAL;
+ }
+
+ return 0;
+} /* end Downmix_getParameter */
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_foldFromQuad()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * downmix a quad signal to stereo
+ *
+ * Inputs:
+ * pSrc quad audio samples to downmix
+ * numFrames the number of quad frames to downmix
+ *
+ * Outputs:
+ * pDst downmixed stereo audio samples
+ *
+ *----------------------------------------------------------------------------
+ */
+void Downmix_foldFromQuad(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
+ // sample at index 0 is FL
+ // sample at index 1 is FR
+ // sample at index 2 is RL
+ // sample at index 3 is RR
+ if (accumulate) {
+ while (numFrames) {
+ // FL + RL
+ pDst[0] = clamp16(pDst[0] + pSrc[0] + pSrc[2]);
+ // FR + RR
+ pDst[1] = clamp16(pDst[1] + pSrc[1] + pSrc[3]);
+ pSrc += 4;
+ pDst += 2;
+ numFrames--;
+ }
+ } else { // same code as above but without adding and clamping pDst[i] to itself
+ while (numFrames) {
+ // FL + RL
+ pDst[0] = clamp16(pSrc[0] + pSrc[2]);
+ // FR + RR
+ pDst[1] = clamp16(pSrc[1] + pSrc[3]);
+ pSrc += 4;
+ pDst += 2;
+ numFrames--;
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_foldFromSurround()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * downmix a "surround sound" (mono rear) signal to stereo
+ *
+ * Inputs:
+ * pSrc surround signal to downmix
+ * numFrames the number of surround frames to downmix
+ *
+ * Outputs:
+ * pDst downmixed stereo audio samples
+ *
+ *----------------------------------------------------------------------------
+ */
+void Downmix_foldFromSurround(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
+ int32_t lt, rt, centerPlusRearContrib; // samples in Q19.12 format
+ // sample at index 0 is FL
+ // sample at index 1 is FR
+ // sample at index 2 is FC
+ // sample at index 3 is RC
+ if (accumulate) {
+ while (numFrames) {
+ // centerPlusRearContrib = FC(-3dB) + RC(-3dB)
+ centerPlusRearContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12) + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+ // FL + centerPlusRearContrib
+ lt = (pSrc[0] << 12) + centerPlusRearContrib;
+ // FR + centerPlusRearContrib
+ rt = (pSrc[1] << 12) + centerPlusRearContrib;
+ pDst[0] = clamp16(pDst[0] + (lt >> 12));
+ pDst[1] = clamp16(pDst[1] + (rt >> 12));
+ pSrc += 4;
+ pDst += 2;
+ numFrames--;
+ }
+ } else { // same code as above but without adding and clamping pDst[i] to itself
+ while (numFrames) {
+ // centerPlusRearContrib = FC(-3dB) + RC(-3dB)
+ centerPlusRearContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12) + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+ // FL + centerPlusRearContrib
+ lt = (pSrc[0] << 12) + centerPlusRearContrib;
+ // FR + centerPlusRearContrib
+ rt = (pSrc[1] << 12) + centerPlusRearContrib;
+ pDst[0] = clamp16(lt >> 12);
+ pDst[1] = clamp16(rt >> 12);
+ pSrc += 4;
+ pDst += 2;
+ numFrames--;
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_foldFrom5Point1()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * downmix a 5.1 signal to stereo
+ *
+ * Inputs:
+ * pSrc 5.1 audio samples to downmix
+ * numFrames the number of 5.1 frames to downmix
+ *
+ * Outputs:
+ * pDst downmixed stereo audio samples
+ *
+ *----------------------------------------------------------------------------
+ */
+void Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
+ int32_t lt, rt, centerPlusLfeContrib; // samples in Q19.12 format
+ // sample at index 0 is FL
+ // sample at index 1 is FR
+ // sample at index 2 is FC
+ // sample at index 3 is LFE
+ // sample at index 4 is RL
+ // sample at index 5 is RR
+ if (accumulate) {
+ while (numFrames) {
+ // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
+ centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
+ + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+ // FL + centerPlusLfeContrib + RL
+ lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[4] << 12);
+ // FR + centerPlusLfeContrib + RR
+ rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[5] << 12);
+ pDst[0] = clamp16(pDst[0] + (lt >> 12));
+ pDst[1] = clamp16(pDst[1] + (rt >> 12));
+ pSrc += 6;
+ pDst += 2;
+ numFrames--;
+ }
+ } else { // same code as above but without adding and clamping pDst[i] to itself
+ while (numFrames) {
+ // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
+ centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
+ + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+ // FL + centerPlusLfeContrib + RL
+ lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[4] << 12);
+ // FR + centerPlusLfeContrib + RR
+ rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[5] << 12);
+ pDst[0] = clamp16(lt >> 12);
+ pDst[1] = clamp16(rt >> 12);
+ pSrc += 6;
+ pDst += 2;
+ numFrames--;
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_foldFrom7Point1()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * downmix a 7.1 signal to stereo
+ *
+ * Inputs:
+ * pSrc 7.1 audio samples to downmix
+ * numFrames the number of 7.1 frames to downmix
+ *
+ * Outputs:
+ * pDst downmixed stereo audio samples
+ *
+ *----------------------------------------------------------------------------
+ */
+void Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
+ int32_t lt, rt, centerPlusLfeContrib; // samples in Q19.12 format
+ // sample at index 0 is FL
+ // sample at index 1 is FR
+ // sample at index 2 is FC
+ // sample at index 3 is LFE
+ // sample at index 4 is RL
+ // sample at index 5 is RR
+ // sample at index 6 is SL
+ // sample at index 7 is SR
+ if (accumulate) {
+ while (numFrames) {
+ // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
+ centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
+ + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+ // FL + centerPlusLfeContrib + SL + RL
+ lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[6] << 12) + (pSrc[4] << 12);
+ // FR + centerPlusLfeContrib + SR + RR
+ rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[7] << 12) + (pSrc[5] << 12);
+ pDst[0] = clamp16(lt >> 12);
+ pDst[1] = clamp16(rt >> 12);
+ pSrc += 8;
+ pDst += 2;
+ numFrames--;
+ }
+ } else { // same code as above but without adding and clamping pDst[i] to itself
+ while (numFrames) {
+ // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
+ centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
+ + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+ // FL + centerPlusLfeContrib + SL + RL
+ lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[6] << 12) + (pSrc[4] << 12);
+ // FR + centerPlusLfeContrib + SR + RR
+ rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[7] << 12) + (pSrc[5] << 12);
+ pDst[0] = clamp16(pDst[0] + (lt >> 12));
+ pDst[1] = clamp16(pDst[1] + (rt >> 12));
+ pSrc += 8;
+ pDst += 2;
+ numFrames--;
+ }
+ }
+}
+
diff --git a/media/libeffects/downmix/EffectDownmix.h b/media/libeffects/downmix/EffectDownmix.h
new file mode 100644
index 0000000..4176b5a
--- /dev/null
+++ b/media/libeffects/downmix/EffectDownmix.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_EFFECTDOWNMIX_H_
+#define ANDROID_EFFECTDOWNMIX_H_
+
+#include <audio_effects/effect_downmix.h>
+#include <audio_utils/primitives.h>
+#include <system/audio.h>
+
+/*------------------------------------
+ * definitions
+ *------------------------------------
+*/
+
+#define DOWNMIX_OUTPUT_CHANNELS AUDIO_CHANNEL_OUT_STEREO
+
+typedef enum {
+ DOWNMIX_STATE_UNINITIALIZED,
+ DOWNMIX_STATE_INITIALIZED,
+ DOWNMIX_STATE_ACTIVE,
+} downmix_state_t;
+
+/* parameters for each downmixer */
+typedef struct {
+ downmix_state_t state;
+ downmix_type_t type;
+ bool apply_volume_correction;
+ uint8_t input_channel_count;
+} downmix_object_t;
+
+
+typedef struct downmix_module_s {
+ const struct effect_interface_s *itfe;
+ effect_config_t config;
+ downmix_object_t context;
+} downmix_module_t;
+
+
+/*------------------------------------
+ * Effect API
+ *------------------------------------
+*/
+int32_t DownmixLib_QueryNumberEffects(uint32_t *pNumEffects);
+int32_t DownmixLib_QueryEffect(uint32_t index,
+ effect_descriptor_t *pDescriptor);
+int32_t DownmixLib_Create(const effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_handle_t *pHandle);
+int32_t DownmixLib_Release(effect_handle_t handle);
+int32_t DownmixLib_GetDescriptor(const effect_uuid_t *uuid,
+ effect_descriptor_t *pDescriptor);
+
+static int Downmix_Process(effect_handle_t self,
+ audio_buffer_t *inBuffer,
+ audio_buffer_t *outBuffer);
+static int Downmix_Command(effect_handle_t self,
+ uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData);
+static int Downmix_GetDescriptor(effect_handle_t self,
+ effect_descriptor_t *pDescriptor);
+
+
+/*------------------------------------
+ * internal functions
+ *------------------------------------
+*/
+int Downmix_Init(downmix_module_t *pDwmModule);
+int Downmix_Configure(downmix_module_t *pDwmModule, effect_config_t *pConfig, bool init);
+int Downmix_Reset(downmix_object_t *pDownmixer, bool init);
+int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t size, void *pValue);
+int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, size_t *pSize, void *pValue);
+
+void Downmix_foldFromQuad(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
+void Downmix_foldFromSurround(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
+void Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
+void Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
+
+#endif /*ANDROID_EFFECTDOWNMIX_H_*/
diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk
new file mode 100644
index 0000000..6e69151
--- /dev/null
+++ b/media/libeffects/factory/Android.mk
@@ -0,0 +1,20 @@
+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
+
+LOCAL_SHARED_LIBRARIES += libdl
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, audio-effects)
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
new file mode 100644
index 0000000..59cd9e3
--- /dev/null
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -0,0 +1,730 @@
+/*
+ * 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>
+
+#include <cutils/misc.h>
+#include <cutils/config_utils.h>
+#include <audio_effects/audio_effects_conf.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
+static lib_entry_t *gCachedLibrary; // last library accessed by getLibrary()
+
+static int gInitDone; // true is global initialization has been preformed
+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 loadEffectConfigFile(const char *path);
+static int loadLibraries(cnode *root);
+static int loadLibrary(cnode *root, const char *name);
+static int loadEffects(cnode *root);
+static int loadEffect(cnode *node);
+static lib_entry_t *getLibrary(const char *path);
+static void resetEffectEnumeration();
+static uint32_t updateNumEffects();
+static int findEffect(const effect_uuid_t *type,
+ const effect_uuid_t *uuid,
+ lib_entry_t **lib,
+ effect_descriptor_t **desc);
+static void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len);
+static int stringToUuid(const char *str, effect_uuid_t *uuid);
+static int uuidToString(const effect_uuid_t *uuid, char *str, size_t maxLen);
+
+/////////////////////////////////////////////////
+// Effect Control Interface functions
+/////////////////////////////////////////////////
+
+int Effect_Process(effect_handle_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_handle_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;
+}
+
+int Effect_GetDescriptor(effect_handle_t self,
+ effect_descriptor_t *desc)
+{
+ 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)->get_descriptor(fx->subItfe, desc);
+ pthread_mutex_unlock(&fx->lib->lock);
+ return ret;
+}
+
+int Effect_ProcessReverse(effect_handle_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);
+
+ if ((*fx->subItfe)->process_reverse != NULL) {
+ ret = (*fx->subItfe)->process_reverse(fx->subItfe, inBuffer, outBuffer);
+ } else {
+ ret = -ENOSYS;
+ }
+ pthread_mutex_unlock(&fx->lib->lock);
+ return ret;
+}
+
+
+const struct effect_interface_s gInterface = {
+ Effect_Process,
+ Effect_Command,
+ Effect_GetDescriptor,
+ NULL
+};
+
+const struct effect_interface_s gInterfaceWithReverse = {
+ Effect_Process,
+ Effect_Command,
+ Effect_GetDescriptor,
+ Effect_ProcessReverse
+};
+
+/////////////////////////////////////////////////
+// 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);
+ ALOGV("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);
+ ALOGV("EffectQueryEffect() desc:%s", str);
+#endif
+ pthread_mutex_unlock(&gLibLock);
+ return ret;
+}
+
+int EffectGetDescriptor(const 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(NULL, uuid, &l, &d);
+ if (ret == 0) {
+ memcpy(pDescriptor, d, sizeof(effect_descriptor_t));
+ }
+ pthread_mutex_unlock(&gLibLock);
+ return ret;
+}
+
+int EffectCreate(const effect_uuid_t *uuid, int32_t sessionId, int32_t ioId, effect_handle_t *pHandle)
+{
+ list_elem_t *e = gLibraryList;
+ lib_entry_t *l = NULL;
+ effect_descriptor_t *d = NULL;
+ effect_handle_t itfe;
+ effect_entry_t *fx;
+ int found = 0;
+ int ret;
+
+ if (uuid == NULL || pHandle == NULL) {
+ return -EINVAL;
+ }
+
+ ALOGV("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) {
+ ALOGW("EffectCreate() init error: %d", ret);
+ return ret;
+ }
+
+ pthread_mutex_lock(&gLibLock);
+
+ ret = findEffect(NULL, uuid, &l, &d);
+ if (ret < 0){
+ goto exit;
+ }
+
+ // create effect in library
+ ret = l->desc->create_effect(uuid, sessionId, ioId, &itfe);
+ if (ret != 0) {
+ ALOGW("EffectCreate() library %s: could not create fx %s, error %d", l->name, d->name, ret);
+ goto exit;
+ }
+
+ // add entry to effect list
+ fx = (effect_entry_t *)malloc(sizeof(effect_entry_t));
+ fx->subItfe = itfe;
+ if ((*itfe)->process_reverse != NULL) {
+ fx->itfe = (struct effect_interface_s *)&gInterfaceWithReverse;
+ ALOGV("EffectCreate() gInterfaceWithReverse");
+ } else {
+ fx->itfe = (struct effect_interface_s *)&gInterface;
+ ALOGV("EffectCreate() gInterface");
+ }
+ fx->lib = l;
+
+ e = (list_elem_t *)malloc(sizeof(list_elem_t));
+ e->object = fx;
+ e->next = gEffectList;
+ gEffectList = e;
+
+ *pHandle = (effect_handle_t)fx;
+
+ ALOGV("EffectCreate() created entry %p with sub itfe %p in library %s", *pHandle, itfe, l->name);
+
+exit:
+ pthread_mutex_unlock(&gLibLock);
+ return ret;
+}
+
+int EffectRelease(effect_handle_t handle)
+{
+ 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 == handle) {
+ 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) {
+ ALOGW("EffectRelease() fx %p library already unloaded", handle);
+ } else {
+ pthread_mutex_lock(&fx->lib->lock);
+ fx->lib->desc->release_effect(fx->subItfe);
+ pthread_mutex_unlock(&fx->lib->lock);
+ }
+ free(fx);
+
+exit:
+ pthread_mutex_unlock(&gLibLock);
+ return ret;
+}
+
+int EffectIsNullUuid(const effect_uuid_t *uuid)
+{
+ if (memcmp(uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t))) {
+ return 0;
+ }
+ return 1;
+}
+
+/////////////////////////////////////////////////
+// Local functions
+/////////////////////////////////////////////////
+
+int init() {
+ int hdl;
+
+ if (gInitDone) {
+ return 0;
+ }
+
+ pthread_mutex_init(&gLibLock, NULL);
+
+ if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
+ loadEffectConfigFile(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
+ } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
+ loadEffectConfigFile(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
+ }
+
+ updateNumEffects();
+ gInitDone = 1;
+ ALOGV("init() done");
+ return 0;
+}
+
+int loadEffectConfigFile(const char *path)
+{
+ cnode *root;
+ char *data;
+
+ data = load_file(path, NULL);
+ if (data == NULL) {
+ return -ENODEV;
+ }
+ root = config_node("", "");
+ config_load(root, data);
+ loadLibraries(root);
+ loadEffects(root);
+ config_free(root);
+ free(root);
+ free(data);
+
+ return 0;
+}
+
+int loadLibraries(cnode *root)
+{
+ cnode *node;
+
+ node = config_find(root, LIBRARIES_TAG);
+ if (node == NULL) {
+ return -ENOENT;
+ }
+ node = node->first_child;
+ while (node) {
+ loadLibrary(node, node->name);
+ node = node->next;
+ }
+ return 0;
+}
+
+int loadLibrary(cnode *root, const char *name)
+{
+ cnode *node;
+ void *hdl;
+ audio_effect_library_t *desc;
+ list_elem_t *e;
+ lib_entry_t *l;
+
+ node = config_find(root, PATH_TAG);
+ if (node == NULL) {
+ return -EINVAL;
+ }
+
+ hdl = dlopen(node->value, RTLD_NOW);
+ if (hdl == NULL) {
+ ALOGW("loadLibrary() failed to open %s", node->value);
+ goto error;
+ }
+
+ desc = (audio_effect_library_t *)dlsym(hdl, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
+ if (desc == NULL) {
+ ALOGW("loadLibrary() could not find symbol %s", AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
+ goto error;
+ }
+
+ if (AUDIO_EFFECT_LIBRARY_TAG != desc->tag) {
+ ALOGW("getLibrary() bad tag %08x in lib info struct", desc->tag);
+ goto error;
+ }
+
+ if (EFFECT_API_VERSION_MAJOR(desc->version) !=
+ EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION)) {
+ ALOGW("loadLibrary() bad lib version %08x", desc->version);
+ goto error;
+ }
+
+ // add entry for library in gLibraryList
+ l = malloc(sizeof(lib_entry_t));
+ l->name = strndup(name, PATH_MAX);
+ l->path = strndup(node->value, PATH_MAX);
+ l->handle = hdl;
+ l->desc = desc;
+ l->effects = NULL;
+ pthread_mutex_init(&l->lock, NULL);
+
+ e = malloc(sizeof(list_elem_t));
+ e->object = l;
+ pthread_mutex_lock(&gLibLock);
+ e->next = gLibraryList;
+ gLibraryList = e;
+ pthread_mutex_unlock(&gLibLock);
+ ALOGV("getLibrary() linked library %p for path %s", l, node->value);
+
+ return 0;
+
+error:
+ if (hdl != NULL) {
+ dlclose(hdl);
+ }
+ return -EINVAL;
+}
+
+int loadEffects(cnode *root)
+{
+ cnode *node;
+
+ node = config_find(root, EFFECTS_TAG);
+ if (node == NULL) {
+ return -ENOENT;
+ }
+ node = node->first_child;
+ while (node) {
+ loadEffect(node);
+ node = node->next;
+ }
+ return 0;
+}
+
+int loadEffect(cnode *root)
+{
+ cnode *node;
+ effect_uuid_t uuid;
+ lib_entry_t *l;
+ effect_descriptor_t *d;
+ list_elem_t *e;
+
+ node = config_find(root, LIBRARY_TAG);
+ if (node == NULL) {
+ return -EINVAL;
+ }
+
+ l = getLibrary(node->value);
+ if (l == NULL) {
+ ALOGW("loadEffect() could not get library %s", node->value);
+ return -EINVAL;
+ }
+
+ node = config_find(root, UUID_TAG);
+ if (node == NULL) {
+ return -EINVAL;
+ }
+ if (stringToUuid(node->value, &uuid) != 0) {
+ ALOGW("loadEffect() invalid uuid %s", node->value);
+ return -EINVAL;
+ }
+
+ d = malloc(sizeof(effect_descriptor_t));
+ if (l->desc->get_descriptor(&uuid, d) != 0) {
+ char s[40];
+ uuidToString(&uuid, s, 40);
+ ALOGW("Error querying effect %s on lib %s", s, l->name);
+ free(d);
+ return -EINVAL;
+ }
+#if (LOG_NDEBUG==0)
+ char s[256];
+ dumpEffectDescriptor(d, s, 256);
+ ALOGV("loadEffect() read descriptor %p:%s",d, s);
+#endif
+ if (EFFECT_API_VERSION_MAJOR(d->apiVersion) !=
+ EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION)) {
+ ALOGW("Bad API version %08x on lib %s", d->apiVersion, l->name);
+ free(d);
+ return -EINVAL;
+ }
+ e = malloc(sizeof(list_elem_t));
+ e->object = d;
+ e->next = l->effects;
+ l->effects = e;
+
+ return 0;
+}
+
+lib_entry_t *getLibrary(const char *name)
+{
+ list_elem_t *e;
+
+ if (gCachedLibrary &&
+ !strncmp(gCachedLibrary->name, name, PATH_MAX)) {
+ return gCachedLibrary;
+ }
+
+ e = gLibraryList;
+ while (e) {
+ lib_entry_t *l = (lib_entry_t *)e->object;
+ if (!strcmp(l->name, name)) {
+ gCachedLibrary = l;
+ return l;
+ }
+ e = e->next;
+ }
+
+ return NULL;
+}
+
+
+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(const effect_uuid_t *type,
+ const 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 (type != NULL && memcmp(&d->type, type, sizeof(effect_uuid_t)) == 0) {
+ found = 1;
+ break;
+ }
+ if (uuid != NULL && memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
+ found = 1;
+ break;
+ }
+ efx = efx->next;
+ }
+ e = e->next;
+ }
+ if (!found) {
+ ALOGV("findEffect() effect not found");
+ ret = -ENOENT;
+ } else {
+ ALOGV("findEffect() found effect: %s in lib %s", d->name, l->name);
+ *lib = l;
+ if (desc) {
+ *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);
+ strncat(str, "- TYPE: ", len);
+ uuidToString(&desc->uuid, s, 256);
+ snprintf(str, len, "- UUID: %s\n", s);
+ uuidToString(&desc->type, s, 256);
+ snprintf(str, len, "- TYPE: %s\n", s);
+ sprintf(s, "- apiVersion: %08X\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);
+}
+
+int stringToUuid(const char *str, effect_uuid_t *uuid)
+{
+ 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 -EINVAL;
+ }
+ uuid->timeLow = (uint32_t)tmp[0];
+ uuid->timeMid = (uint16_t)tmp[1];
+ uuid->timeHiAndVersion = (uint16_t)tmp[2];
+ uuid->clockSeq = (uint16_t)tmp[3];
+ uuid->node[0] = (uint8_t)tmp[4];
+ uuid->node[1] = (uint8_t)tmp[5];
+ uuid->node[2] = (uint8_t)tmp[6];
+ uuid->node[3] = (uint8_t)tmp[7];
+ uuid->node[4] = (uint8_t)tmp[8];
+ uuid->node[5] = (uint8_t)tmp[9];
+
+ return 0;
+}
+
+int uuidToString(const effect_uuid_t *uuid, char *str, size_t maxLen)
+{
+
+ snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ 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]);
+
+ return 0;
+}
+
diff --git a/media/libeffects/factory/EffectsFactory.h b/media/libeffects/factory/EffectsFactory.h
new file mode 100644
index 0000000..c1d4319
--- /dev/null
+++ b/media/libeffects/factory/EffectsFactory.h
@@ -0,0 +1,55 @@
+/*
+ * 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 {
+ audio_effect_library_t *desc;
+ char *name;
+ char *path;
+ void *handle;
+ 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_handle_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..f49267e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Android.mk
@@ -0,0 +1,179 @@
+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_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)
+
+# Reverb library
+include $(CLEAR_VARS)
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_SRC_FILES:= \
+ Reverb/src/LVREV_ApplyNewSettings.c \
+ Reverb/src/LVREV_ClearAudioBuffers.c \
+ Reverb/src/LVREV_GetControlParameters.c \
+ Reverb/src/LVREV_GetInstanceHandle.c \
+ Reverb/src/LVREV_GetMemoryTable.c \
+ Reverb/src/LVREV_Process.c \
+ Reverb/src/LVREV_SetControlParameters.c \
+ Reverb/src/LVREV_Tables.c \
+ Common/src/Abs_32.c \
+ Common/src/InstAlloc.c \
+ Common/src/LoadConst_16.c \
+ Common/src/LoadConst_32.c \
+ Common/src/From2iToMono_32.c \
+ Common/src/Mult3s_32x16.c \
+ Common/src/FO_1I_D32F32C31_TRC_WRA_01.c \
+ Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c \
+ Common/src/DelayAllPass_Sat_32x16To32.c \
+ Common/src/Copy_16.c \
+ Common/src/Mac3s_Sat_32x16.c \
+ Common/src/DelayWrite_32.c \
+ Common/src/Shift_Sat_v32xv32.c \
+ Common/src/Add2_Sat_32x32.c \
+ Common/src/JoinTo2i_32x32.c \
+ Common/src/MonoTo2I_32.c \
+ Common/src/LVM_FO_HPF.c \
+ Common/src/LVM_FO_LPF.c \
+ Common/src/LVM_Polynomial.c \
+ Common/src/LVM_Power10.c \
+ Common/src/LVM_GetOmega.c \
+ Common/src/MixSoft_2St_D32C31_SAT.c \
+ Common/src/MixSoft_1St_D32C31_WRA.c \
+ Common/src/MixInSoft_D32C31_SAT.c \
+ Common/src/LVM_Mixer_TimeConstant.c \
+ Common/src/Core_MixHard_2St_D32C31_SAT.c \
+ Common/src/Core_MixSoft_1St_D32C31_WRA.c \
+ Common/src/Core_MixInSoft_D32C31_SAT.c
+
+LOCAL_MODULE:= libreverb
+
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/Reverb/lib \
+ $(LOCAL_PATH)/Reverb/src \
+ $(LOCAL_PATH)/Common/lib \
+ $(LOCAL_PATH)/Common/src
+
+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 100644
index 0000000..228977d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
@@ -0,0 +1,464 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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 100644
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 100644
index 0000000..ab2a832
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
@@ -0,0 +1,376 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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;
+ LVMixer3_2St_st *pBypassMixer_Instance = &pInstance->pData->BypassMixer;
+
+
+ /*
+ * 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 */
+
+ LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
+ LVDBE_BYPASS_MIXER_TC,pParams->SampleRate,2);
+
+ LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
+ LVDBE_BYPASS_MIXER_TC,pParams->SampleRate,2);
+
+
+ }
+
+
+ /*
+ * 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)
+ {
+ LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0);
+ LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0x00007FFF);
+ }
+ if (pInstance->Params.OperatingMode==LVDBE_OFF && pParams->OperatingMode==LVDBE_ON)
+ {
+ LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0x00007FFF);
+ LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0);
+ }
+
+ /*
+ * 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 100644
index 0000000..3b3c07c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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;
+ LVMixer3_2St_st *pBypassMixer_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 BypassMixer
+ */
+
+ pBypassMixer_Instance = &pInstance->pData->BypassMixer;
+
+ /*
+ * Setup the mixer gain for the processed path
+ */
+ pBypassMixer_Instance->MixerStream[0].CallbackParam = 0;
+ pBypassMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
+ pBypassMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
+ pBypassMixer_Instance->MixerStream[0].CallbackSet=0;
+ LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[0],0,0);
+ LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
+ LVDBE_BYPASS_MIXER_TC,pInstance->Params.SampleRate,2);
+ /*
+ * Setup the mixer gain for the unprocessed path
+ */
+ pBypassMixer_Instance->MixerStream[1].CallbackParam = 0;
+ pBypassMixer_Instance->MixerStream[1].pCallbackHandle = LVM_NULL;
+ pBypassMixer_Instance->MixerStream[1].pCallBack = LVM_NULL;
+ pBypassMixer_Instance->MixerStream[1].CallbackSet=0;
+ LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[1],0x00007FFF,0x00007FFF);
+ LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
+ LVDBE_BYPASS_MIXER_TC,pInstance->Params.SampleRate,2);
+
+ 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 100644
index 0000000..8339d3c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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 6 /* Number of buffers required for inplace processing */
+
+#define LVDBE_MIXER_TC 5 /* Mixer time */
+#define LVDBE_BYPASS_MIXER_TC 100 /* Bypass 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 */
+ LVMixer3_2St_st BypassMixer; /* Bypass Mixer for Click Removal */
+
+} 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 */
+} 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 100644
index 0000000..69d79d2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
@@ -0,0 +1,207 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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_INT16 *pInput = (LVM_INT16 *)pInData;
+
+
+ /* Scratch for Volume Control starts at offset of 2*NumSamples short values from pScratch */
+ LVM_INT16 *pScratchVol = (LVM_INT16 *)(&pScratch[NumSamples]);
+
+ /* Scratch for Mono path starts at offset of 2*NumSamples 32-bit values from pScratch */
+ pMono = &pScratch[2*NumSamples];
+
+ /*
+ * Check the number of samples is not too large
+ */
+ if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+ {
+ return(LVDBE_TOOMANYSAMPLES);
+ }
+
+ /*
+ * Check if the algorithm is enabled
+ */
+ /* DBE path is processed when DBE is ON or during On/Off transitions */
+ if ((pInstance->Params.OperatingMode == LVDBE_ON)||
+ (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[0])
+ !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[0])))
+ {
+
+ /*
+ * 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, /* Dest. 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 */
+
+ /*
+ * Convert 32-bit samples to 16-bit and saturate
+ * (Not required for 16-bit implemenations)
+ */
+ Int32RShiftToInt16_Sat_32x16(pScratch, /* Source 32-bit data */
+ (LVM_INT16 *)pScratch, /* Dest. 16-bit data */
+ (LVM_INT16)(2*NumSamples), /* Left and right */
+ LVDBE_SCALESHIFT); /* Shift scale */
+
+ }
+
+ /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
+ if ((pInstance->Params.OperatingMode == LVDBE_OFF)||
+ (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[1])
+ !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[1])))
+ {
+
+ /*
+ * 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,
+ pScratchVol,
+ (LVM_INT16)(2*NumSamples)); /* Left and right */
+
+ }
+
+ /*
+ * Mix DBE processed path and bypass volume path
+ */
+ LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
+ (LVM_INT16 *) pScratch,
+ pScratchVol,
+ pOutData,
+ (LVM_INT16)(2*NumSamples));
+
+ 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 100644
index 0000000..f5d229e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_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.
+ */
+
+
+/************************************************************************************/
+/* */
+/* 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 100644
index 0000000..476e6a0
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+
+/************************************************************************************/
+/* */
+/* 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 100644
index 0000000..1ff2a2c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/lib/LVM.h
@@ -0,0 +1,629 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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 100644
index 0000000..07b7f0e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.c
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+
+/****************************************************************************************/
+/* */
+/* 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 100644
index 0000000..6cbee7d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
@@ -0,0 +1,870 @@
+/*
+ * 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.
+ */
+
+
+/****************************************************************************************/
+/* */
+/* 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 100644
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 100644
index 0000000..72564d4
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
@@ -0,0 +1,1025 @@
+/*
+ * 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.
+ */
+
+
+/****************************************************************************************/
+/* */
+/* 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;
+
+ 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->NoSmoothVolume = LVM_FALSE;
+ 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 100644
index 0000000..20370b7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
@@ -0,0 +1,995 @@
+/*
+ * 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.
+ */
+
+/************************************************************************************/
+/* */
+/* 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 100644
index 0000000..2d1cf42
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+/************************************************************************************/
+/* */
+/* 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 100644
index 0000000..794271b
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
@@ -0,0 +1,275 @@
+/*
+ * 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.
+ */
+
+
+/****************************************************************************************/
+/* */
+/* 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 100644
index 0000000..e14f909
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c
@@ -0,0 +1,389 @@
+/*
+ * 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.
+ */
+
+/************************************************************************************/
+/* */
+/* 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 100644
index 0000000..a7601ff
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h
@@ -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.
+ */
+
+#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 100644
index 0000000..2080d64
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/AGC.h
@@ -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.
+ */
+
+#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 100644
index 0000000..7ac7fbd
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
@@ -0,0 +1,333 @@
+/*
+ * 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 _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 100644
index 0000000..4cb8aa2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/CompLim.h
@@ -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.
+ */
+
+#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 100644
index 0000000..229701a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/Filter.h
@@ -0,0 +1,62 @@
+/*
+ * 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 _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 100644
index 0000000..c6954f2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/InstAlloc.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.
+ */
+
+#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 100644
index 0000000..ceccd7b
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Common.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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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 100644
index 0000000..97d13a5
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Macros.h
@@ -0,0 +1,122 @@
+/*
+ * 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_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 100644
index 0000000..81e288c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h
@@ -0,0 +1,82 @@
+/*
+ * 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__
+
+#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 100644
index 0000000..81655dd
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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 100644
index 0000000..89deb0d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/Mixer.h
@@ -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.
+ */
+
+#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 100644
index 0000000..3d62704
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
@@ -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.
+ */
+
+#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 100644
index 0000000..2b791bd
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
@@ -0,0 +1,181 @@
+/*
+ * 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 _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 100644
index 0000000..920b515
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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 100644
index 0000000..9128b82
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Abs_32.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.
+ */
+
+/*######################################################################################*/
+/* 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 100644
index 0000000..6978fe7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Add2_Sat_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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..69d357e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..f4c5757
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.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.
+ */
+
+#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 100644
index 0000000..88914ad
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+/*-------------------------------------------------------------------------*/
+#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 100644
index 0000000..980539c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -0,0 +1,30 @@
+/*
+ * 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_
+
+/* 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 100644
index 0000000..ba1a42f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_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.
+ */
+
+#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 100644
index 0000000..e833218
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.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.
+ */
+
+/*-------------------------------------------------------------------------*/
+#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 100644
index 0000000..9cca627
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
@@ -0,0 +1,30 @@
+/*
+ * 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_
+
+/* 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 100644
index 0000000..b09c1aa
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.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.
+ */
+
+#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 100644
index 0000000..9367912
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+/*-------------------------------------------------------------------------*/
+#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 100644
index 0000000..5cc1ce2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
@@ -0,0 +1,30 @@
+/*
+ * 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_
+
+/* 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 100644
index 0000000..f2f8c6b
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..baf0c1a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c
@@ -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.
+ */
+
+/*-------------------------------------------------------------------------*/
+#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 100644
index 0000000..909c699
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -0,0 +1,30 @@
+/*
+ * 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_
+
+/* 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 100644
index 0000000..92f6caf
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.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.
+ */
+
+#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 100644
index 0000000..aea10f0
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
@@ -0,0 +1,30 @@
+/*
+ * 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_
+
+/* 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 100644
index 0000000..1d6be4e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+/*-------------------------------------------------------------------------*/
+#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 100644
index 0000000..972e704
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.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.
+ */
+
+#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 100644
index 0000000..e056373
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.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.
+ */
+
+#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 100644
index 0000000..0a8ac35
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+/*-------------------------------------------------------------------------*/
+#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 100644
index 0000000..7d42ced
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
@@ -0,0 +1,31 @@
+/*
+ * 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_
+
+/* 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 100644
index 0000000..4a0cce4
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..052e2a0
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..8c741e1
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..4f0cf67
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
@@ -0,0 +1,31 @@
+/*
+ * 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_
+
+/* 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 100644
index 0000000..4591ee0
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c
@@ -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.
+ */
+
+#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 100644
index 0000000..fd8212e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_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.
+ */
+
+#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 100644
index 0000000..1709f71
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c
@@ -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.
+ */
+
+/*-------------------------------------------------------------------------*/
+#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 100644
index 0000000..747af6a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
@@ -0,0 +1,32 @@
+/*
+ * 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_
+
+
+/* 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 100644
index 0000000..06a21c3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/CompLim_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.
+ */
+
+#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 100644
index 0000000..20404ad
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Copy_16.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..bf69e35
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..3471f05
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..709c304
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..49fa184
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.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.
+ */
+
+#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 100644
index 0000000..468a88d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..89a4e68
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+
+/* 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 100644
index 0000000..2e20d79
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..7e3182d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..809cddc
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DelayWrite_32.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..de77361
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.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.
+ */
+
+#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 100644
index 0000000..96252cc
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.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.
+ */
+
+/*-------------------------------------------------------------------------*/
+#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 100644
index 0000000..516ca83
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -0,0 +1,31 @@
+/*
+ * 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_
+
+/* 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 100644
index 0000000..0f1d5bc
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.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.
+ */
+
+#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 100644
index 0000000..136e4f6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.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.
+ */
+
+#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 100644
index 0000000..94ad48c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
@@ -0,0 +1,32 @@
+/*
+ * 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_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 100644
index 0000000..8388050
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_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.
+ */
+
+#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 100644
index 0000000..a19c32c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_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.
+ */
+
+/*-------------------------------------------------------------------------*/
+#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 100644
index 0000000..4640743
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
@@ -0,0 +1,32 @@
+/*
+ * 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_
+
+/* 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 100644
index 0000000..4d32df1
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Filters.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.
+ */
+
+#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 100644
index 0000000..7975e8b
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..b758ee7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMono_16.c
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..8bb292f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..481df84
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/InstAlloc.c
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..9f09e4d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.c
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..8c9980d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..9b938bd
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..3d39b93
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..2daf74a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..caa0951
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..09ec427
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..f1a9ca3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..0052dd7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..f443c8f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..c8dcad7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..7240705
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..980c783
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.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.
+ */
+
+#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 100644
index 0000000..b5ae264
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c
@@ -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.
+ */
+
+#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 100644
index 0000000..dc2f8e9
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..449e7b1
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_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.
+ */
+
+#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 100644
index 0000000..294e05c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
@@ -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.
+ */
+
+#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 100644
index 0000000..5efa501
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.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.
+ */
+
+#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 100644
index 0000000..4c1c8b2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.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.
+ */
+
+#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 100644
index 0000000..8d5304e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..6d8fe46
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c
@@ -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.
+ */
+
+#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 100644
index 0000000..86ec951
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..f3b9b3c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..6846d49
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.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.
+ */
+
+/************************************************************************************/
+/* */
+/* 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 100644
index 0000000..809d904
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..a6d7db2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..6ca1077
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Power10.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.
+ */
+
+#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 100644
index 0000000..5995f54
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Timer.c
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* 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 100644
index 0000000..a935cfe
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.c
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* 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 100644
index 0000000..480944f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Timer_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.
+ */
+
+#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 100644
index 0000000..f88ca0e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LoadConst_16.c
@@ -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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..2f1e591
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LoadConst_32.c
@@ -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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..26297e7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.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.
+ */
+
+/**********************************************************************************
+ 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 100644
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 100644
index 0000000..f28f366
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c
@@ -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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..73c26ed
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..ca88b04
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..2e0a099
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..607073c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mixer_private.h
@@ -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.
+ */
+
+#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 100644
index 0000000..ead798d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.c
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..c09ec0f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..a5dc50f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..73343cd
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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 100644
index 0000000..c8c1527
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..67a570b
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.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.
+ */
+
+#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 100644
index 0000000..1d6142c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c
@@ -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.
+ */
+
+#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 100644
index 0000000..c5f9c7c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h
@@ -0,0 +1,31 @@
+/*
+ * 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_
+
+/* 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 100644
index 0000000..b9f64e6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..e2050e0
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
@@ -0,0 +1,32 @@
+/*
+ * 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_
+
+
+/* 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 100644
index 0000000..8363270
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..fbd132e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.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.
+ */
+
+/**********************************************************************************
+ 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 100644
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 100644
index 0000000..4092560
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/mult3s_16x16.c
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+/**********************************************************************************
+ 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 100644
index 0000000..db6aabe
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
@@ -0,0 +1,476 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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 100644
index 0000000..fddedb9
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c
@@ -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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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 100644
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 100644
index 0000000..10e7d74
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c
@@ -0,0 +1,493 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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 100644
index 0000000..e83e515
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c
@@ -0,0 +1,321 @@
+/*
+ * 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.
+ */
+
+
+/****************************************************************************************/
+/* */
+/* 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 100644
index 0000000..9df980c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
@@ -0,0 +1,133 @@
+/*
+ * 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_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 100644
index 0000000..ac3c740
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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 100644
index 0000000..8e2e0e8
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c
@@ -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.
+ */
+
+
+/************************************************************************************/
+/* */
+/* 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/Reverb/lib/LVREV.h b/media/libeffects/lvm/lib/Reverb/lib/LVREV.h
new file mode 100644
index 0000000..28e3369
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/lib/LVREV.h
@@ -0,0 +1,312 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Header file for the application layer interface of the LVREV module */
+/* */
+/* This files includes all definitions, types, structures and function prototypes */
+/* required by the calling layer. All other types, structures and functions are */
+/* private. */
+/* */
+/****************************************************************************************/
+
+#ifndef __LVREV_H__
+#define __LVREV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVM_Types.h"
+
+
+/****************************************************************************************/
+/* */
+/* Definitions */
+/* */
+/****************************************************************************************/
+/* General */
+#define LVREV_BLOCKSIZE_MULTIPLE 1 /* Processing block size multiple */
+#define LVREV_MAX_T60 7000 /* Maximum decay time is 7000ms */
+
+/* Memory table*/
+#define LVREV_NR_MEMORY_REGIONS 4 /* Number of memory regions */
+
+
+/****************************************************************************************/
+/* */
+/* Types */
+/* */
+/****************************************************************************************/
+/* Instance handle */
+typedef void *LVREV_Handle_t;
+
+
+/* Status return values */
+typedef enum
+{
+ LVREV_SUCCESS = 0, /* Successful return from a routine */
+ LVREV_NULLADDRESS = 1, /* NULL allocation address */
+ LVREV_OUTOFRANGE = 2, /* Out of range control parameter */
+ LVREV_INVALIDNUMSAMPLES = 3, /* Invalid number of samples */
+ LVREV_RETURNSTATUS_DUMMY = LVM_MAXENUM
+} LVREV_ReturnStatus_en;
+
+
+/* Reverb delay lines */
+typedef enum
+{
+ LVREV_DELAYLINES_1 = 1, /* One delay line */
+ LVREV_DELAYLINES_2 = 2, /* Two delay lines */
+ LVREV_DELAYLINES_4 = 4, /* Four delay lines */
+ LVREV_DELAYLINES_DUMMY = LVM_MAXENUM
+} LVREV_NumDelayLines_en;
+
+
+/****************************************************************************************/
+/* */
+/* Structures */
+/* */
+/****************************************************************************************/
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+ LVM_MemoryRegion_st Region[LVREV_NR_MEMORY_REGIONS]; /* One definition for each region */
+} LVREV_MemoryTable_st;
+
+
+/* Control Parameter structure */
+typedef struct
+{
+ /* General parameters */
+ LVM_Mode_en OperatingMode; /* Operating mode */
+ LVM_Fs_en SampleRate; /* Sample rate */
+ LVM_Format_en SourceFormat; /* Source data format */
+
+ /* Parameters for REV */
+ LVM_UINT16 Level; /* Level, 0 to 100 representing percentage of reverb */
+ LVM_UINT16 LPF; /* Low pass filter, in Hz */
+ LVM_UINT16 HPF; /* High pass filter, in Hz */
+ LVM_UINT16 T60; /* Decay time constant, in ms */
+ LVM_UINT16 Density; /* Echo density, 0 to 100 for minimum to maximum density */
+ LVM_UINT16 Damping; /* Damping */
+ LVM_UINT16 RoomSize; /* Simulated room size, 1 to 100 for minimum to maximum size */
+
+} LVREV_ControlParams_st;
+
+
+/* Instance Parameter structure */
+typedef struct
+{
+ /* General */
+ LVM_UINT16 MaxBlockSize; /* Maximum processing block size */
+
+ /* Reverb */
+ LVM_Format_en SourceFormat; /* Source data formats to support */
+ LVREV_NumDelayLines_en NumDelays; /* The number of delay lines, 1, 2 or 4 */
+
+} LVREV_InstanceParams_st;
+
+
+/****************************************************************************************/
+/* */
+/* Function Prototypes */
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_GetMemoryTable */
+/* */
+/* DESCRIPTION: */
+/* This function is used to obtain the LVREV module memory requirements to support */
+/* memory allocation. It can also be used to return the memory base address provided */
+/* during memory allocation to support freeing of memory when the LVREV module is no */
+/* longer required. It is called in two ways: */
+/* */
+/* hInstance = NULL Returns the memory requirements */
+/* hInstance = Instance handle Returns the memory requirements and allocated */
+/* base addresses. */
+/* */
+/* When this function is called with hInstance = NULL the memory base address pointers */
+/* will be NULL on return. */
+/* */
+/* When the function is called for freeing memory, 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 table */
+/* pInstanceParams Pointer to the instance parameters */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Succeeded */
+/* LVREV_NULLADDRESS When pMemoryTable is NULL */
+/* LVREV_NULLADDRESS When requesting memory requirements and pInstanceParams */
+/* is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetMemoryTable(LVREV_Handle_t hInstance,
+ LVREV_MemoryTable_st *pMemoryTable,
+ LVREV_InstanceParams_st *pInstanceParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_GetInstanceHandle */
+/* */
+/* DESCRIPTION: */
+/* This function is used to create a LVREV module instance. It returns the created */
+/* instance handle through phInstance. All parameters are set to invalid values, the */
+/* LVREV_SetControlParameters function must be called with a set of valid control */
+/* parameters before the LVREV_Process function can be called. */
+/* */
+/* The memory allocation must be provided by the application by filling in the memory */
+/* region base addresses in the memory table before calling this function. */
+/* */
+/* PARAMETERS: */
+/* phInstance Pointer to the instance handle */
+/* pMemoryTable Pointer to the memory definition table */
+/* pInstanceParams Pointer to the instance parameters */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Succeeded */
+/* LVREV_NULLADDRESS When phInstance or pMemoryTable or pInstanceParams is NULL */
+/* LVREV_NULLADDRESS When one of the memory regions has a NULL pointer */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetInstanceHandle(LVREV_Handle_t *phInstance,
+ LVREV_MemoryTable_st *pMemoryTable,
+ LVREV_InstanceParams_st *pInstanceParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVXX_GetControlParameters */
+/* */
+/* DESCRIPTION: */
+/* Request the LVREV module control parameters. The current parameter set is returned */
+/* via the parameter pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pControlParams Pointer to an empty parameter structure */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Succeeded */
+/* LVREV_NULLADDRESS When hInstance or pControlParams is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetControlParameters(LVREV_Handle_t hInstance,
+ LVREV_ControlParams_st *pControlParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_SetControlParameters */
+/* */
+/* DESCRIPTION: */
+/* Sets or changes the LVREV module parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pNewParams Pointer to a parameter structure */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Succeeded */
+/* LVREV_NULLADDRESS When hInstance or pNewParams is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_SetControlParameters(LVREV_Handle_t hInstance,
+ LVREV_ControlParams_st *pNewParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_ClearAudioBuffers */
+/* */
+/* DESCRIPTION: */
+/* This function is used to clear the internal audio buffers of the module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Initialisation succeeded */
+/* LVREV_NULLADDRESS Instance is NULL */
+/* */
+/* NOTES: */
+/* 1. This function must not be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_ClearAudioBuffers(LVREV_Handle_t hInstance);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_Process */
+/* */
+/* DESCRIPTION: */
+/* Process function for the LVREV 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: */
+/* LVREV_SUCCESS Succeeded */
+/* LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size */
+/* */
+/* NOTES: */
+/* 1. The input and output buffers must be 32-bit aligned */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t hInstance,
+ const LVM_INT32 *pInData,
+ LVM_INT32 *pOutData,
+ const LVM_UINT16 NumSamples);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVREV_H__ */
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c
new file mode 100644
index 0000000..ac2ef9d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.c
@@ -0,0 +1,642 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "Filter.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_ApplyNewSettings */
+/* */
+/* DESCRIPTION: */
+/* Applies the new control parameters */
+/* */
+/* PARAMETERS: */
+/* pPrivate Pointer to the instance private parameters */
+/* */
+/* RETURNS: */
+/* LVREV_Success Succeeded */
+/* LVREV_NULLADDRESS When pPrivate is NULL */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+LVREV_ReturnStatus_en LVREV_ApplyNewSettings (LVREV_Instance_st *pPrivate)
+{
+
+ LVM_Mode_en OperatingMode;
+ LVM_INT32 NumberOfDelayLines;
+
+
+ /* Check for NULL pointer */
+ if(pPrivate == LVM_NULL)
+ {
+ return LVREV_NULLADDRESS;
+ }
+
+ OperatingMode = pPrivate->NewParams.OperatingMode;
+
+ if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+ {
+ NumberOfDelayLines = 4;
+ }
+ else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
+ {
+ NumberOfDelayLines = 2;
+ }
+ else
+ {
+ NumberOfDelayLines = 1;
+ }
+
+ /*
+ * Update the high pass filter coefficients
+ */
+ if((pPrivate->NewParams.HPF != pPrivate->CurrentParams.HPF) ||
+ (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+ LVM_INT32 Omega;
+ FO_C32_Coefs_t Coeffs;
+
+ Omega = LVM_GetOmega(pPrivate->NewParams.HPF, pPrivate->NewParams.SampleRate);
+ LVM_FO_HPF(Omega, &Coeffs);
+ FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->HPCoefs, &pPrivate->pFastData->HPTaps, &Coeffs);
+ LoadConst_32(0,
+ (void *)&pPrivate->pFastData->HPTaps, /* Destination Cast to void: no dereferencing in function*/
+ sizeof(Biquad_1I_Order1_Taps_t)/sizeof(LVM_INT32));
+ }
+
+
+ /*
+ * Update the low pass filter coefficients
+ */
+ if((pPrivate->NewParams.LPF != pPrivate->CurrentParams.LPF) ||
+ (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+ LVM_INT32 Omega;
+ FO_C32_Coefs_t Coeffs;
+
+
+ Coeffs.A0 = 0x7FFFFFFF;
+ Coeffs.A1 = 0;
+ Coeffs.B1 = 0;
+ if(pPrivate->NewParams.LPF <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
+ {
+ Omega = LVM_GetOmega(pPrivate->NewParams.LPF, pPrivate->NewParams.SampleRate);
+
+ /*
+ * Do not apply filter if w =2*pi*fc/fs >= 2.9
+ */
+ if(Omega<=LVREV_2_9_INQ29)
+ {
+ LVM_FO_LPF(Omega, &Coeffs);
+ }
+ }
+ FO_1I_D32F32Cll_TRC_WRA_01_Init( &pPrivate->pFastCoef->LPCoefs, &pPrivate->pFastData->LPTaps, &Coeffs);
+ LoadConst_32(0,
+ (void *)&pPrivate->pFastData->LPTaps, /* Destination Cast to void: no dereferencing in function*/
+ sizeof(Biquad_1I_Order1_Taps_t)/sizeof(LVM_INT32));
+ }
+
+
+ /*
+ * Calculate the room size parameter
+ */
+ if( pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize)
+ {
+ /* Room size range is 10ms to 200ms
+ * 0% -- 10ms
+ * 50% -- 65ms
+ * 100% -- 120ms
+ */
+ pPrivate->RoomSizeInms = 10 + (((pPrivate->NewParams.RoomSize*11) + 5)/10);
+ }
+
+
+ /*
+ * Update the T delay number of samples and the all pass delay number of samples
+ */
+ if( (pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
+ (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+
+ LVM_UINT32 Temp;
+ LVM_INT32 APDelaySize;
+ LVM_INT32 Fs = LVM_GetFsFromTable(pPrivate->NewParams.SampleRate);
+ LVM_UINT32 DelayLengthSamples = (LVM_UINT32)(Fs * pPrivate->RoomSizeInms);
+ LVM_INT16 i;
+ LVM_INT16 ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
+ LVM_INT16 MaxT_Delay[] = {LVREV_MAX_T0_DELAY, LVREV_MAX_T1_DELAY, LVREV_MAX_T2_DELAY, LVREV_MAX_T3_DELAY};
+ LVM_INT16 MaxAP_Delay[] = {LVREV_MAX_AP0_DELAY, LVREV_MAX_AP1_DELAY, LVREV_MAX_AP2_DELAY, LVREV_MAX_AP3_DELAY};
+
+
+ /*
+ * For each delay line
+ */
+ for (i=0; i<NumberOfDelayLines; i++)
+ {
+ if (i != 0)
+ {
+ LVM_INT32 Temp1; /* to avoid QAC warning on type conversion */
+ LVM_INT32 Temp2; /* to avoid QAC warning on type conversion */
+
+ Temp2=(LVM_INT32)DelayLengthSamples;
+ MUL32x16INTO32(Temp2, ScaleTable[i], Temp1, 15)
+ Temp=(LVM_UINT32)Temp1;
+ }
+ else
+ {
+ Temp = DelayLengthSamples;
+ }
+ APDelaySize = Temp / 1500;
+
+
+ /*
+ * Set the fixed delay
+ */
+ Temp = (MaxT_Delay[i] - MaxAP_Delay[i]) * Fs / 48000;
+ pPrivate->Delay_AP[i] = pPrivate->T[i] - Temp;
+
+
+ /*
+ * Set the tap selection
+ */
+ if (pPrivate->AB_Selection)
+ {
+ /* Smooth from tap A to tap B */
+ pPrivate->pOffsetB[i] = &pPrivate->pDelay_T[i][pPrivate->T[i] - Temp - APDelaySize];
+ pPrivate->B_DelaySize[i] = APDelaySize;
+ pPrivate->Mixer_APTaps[i].Target1 = 0;
+ pPrivate->Mixer_APTaps[i].Target2 = 0x7fffffff;
+ }
+ else
+ {
+ /* Smooth from tap B to tap A */
+ pPrivate->pOffsetA[i] = &pPrivate->pDelay_T[i][pPrivate->T[i] - Temp - APDelaySize];
+ pPrivate->A_DelaySize[i] = APDelaySize;
+ pPrivate->Mixer_APTaps[i].Target2 = 0;
+ pPrivate->Mixer_APTaps[i].Target1 = 0x7fffffff;
+ }
+
+ /*
+ * Set the maximum block size to the smallest delay size
+ */
+ pPrivate->MaxBlkLen = Temp;
+ if (pPrivate->MaxBlkLen > pPrivate->A_DelaySize[i])
+ {
+ pPrivate->MaxBlkLen = pPrivate->A_DelaySize[i];
+ }
+ if (pPrivate->MaxBlkLen > pPrivate->B_DelaySize[i])
+ {
+ pPrivate->MaxBlkLen = pPrivate->B_DelaySize[i];
+ }
+ }
+ if (pPrivate->AB_Selection)
+ {
+ pPrivate->AB_Selection = 0;
+ }
+ else
+ {
+ pPrivate->AB_Selection = 1;
+ }
+
+
+ /*
+ * Limit the maximum block length
+ */
+ pPrivate->MaxBlkLen=pPrivate->MaxBlkLen-2; /* Just as a precausion, but no problem if we remove this line */
+ if(pPrivate->MaxBlkLen > pPrivate->InstanceParams.MaxBlockSize)
+ {
+ pPrivate->MaxBlkLen = (LVM_INT32)pPrivate->InstanceParams.MaxBlockSize;
+ }
+ }
+
+
+ /*
+ * Update the low pass filter coefficient
+ */
+ if( (pPrivate->NewParams.Damping != pPrivate->CurrentParams.Damping) ||
+ (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+
+ LVM_INT32 Temp;
+ LVM_INT32 Omega;
+ FO_C32_Coefs_t Coeffs;
+ LVM_INT16 i;
+ LVM_INT16 Damping = (LVM_INT16)((pPrivate->NewParams.Damping * 100) + 1000);
+ LVM_INT32 ScaleTable[] = {LVREV_T_3_Power_0_on_4, LVREV_T_3_Power_1_on_4, LVREV_T_3_Power_2_on_4, LVREV_T_3_Power_3_on_4};
+
+
+ /*
+ * For each filter
+ */
+ for (i=0; i<NumberOfDelayLines; i++)
+ {
+ if (i != 0)
+ {
+ MUL32x16INTO32(ScaleTable[i], Damping, Temp, 15)
+ }
+ else
+ {
+ Temp = Damping;
+ }
+ if(Temp <= (LVM_FsTable[pPrivate->NewParams.SampleRate] >> 1))
+ {
+ Omega = LVM_GetOmega((LVM_UINT16)Temp, pPrivate->NewParams.SampleRate);
+ LVM_FO_LPF(Omega, &Coeffs);
+ }
+ else
+ {
+ Coeffs.A0 = 0x7FF00000;
+ Coeffs.A1 = 0;
+ Coeffs.B1 = 0;
+ }
+ FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->RevLPCoefs[i], &pPrivate->pFastData->RevLPTaps[i], &Coeffs);
+ }
+ }
+
+
+ /*
+ * Update All-pass filter mixer time constants
+ */
+ if( (pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
+ (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->NewParams.Density != pPrivate->CurrentParams.Density))
+ {
+ LVM_INT16 i;
+ LVM_INT32 Alpha = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_ALLPASS_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), 1);
+ LVM_INT32 AlphaTap = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_ALLPASS_TAP_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), 1);
+
+ for (i=0; i<4; i++)
+ {
+ pPrivate->Mixer_APTaps[i].Alpha1 = AlphaTap;
+ pPrivate->Mixer_APTaps[i].Alpha2 = AlphaTap;
+ pPrivate->Mixer_SGFeedback[i].Alpha = Alpha;
+ pPrivate->Mixer_SGFeedforward[i].Alpha = Alpha;
+ }
+ }
+
+
+ /*
+ * Update the feed back gain
+ */
+ if( (pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
+ (pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->NewParams.T60 != pPrivate->CurrentParams.T60) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+
+ LVM_INT32 G[4]; /* Feedback gain (Q7.24) */
+
+ if(pPrivate->NewParams.T60 == 0)
+ {
+ G[3] = 0;
+ G[2] = 0;
+ G[1] = 0;
+ G[0] = 0;
+ }
+ else
+ {
+ LVM_INT32 Temp1;
+ LVM_INT32 Temp2;
+ LVM_INT16 i;
+ LVM_INT16 ScaleTable[] = {LVREV_T_3_Power_minus0_on_4, LVREV_T_3_Power_minus1_on_4, LVREV_T_3_Power_minus2_on_4, LVREV_T_3_Power_minus3_on_4};
+
+
+ /*
+ * For each delay line
+ */
+ for (i=0; i<NumberOfDelayLines; i++)
+ {
+ Temp1 = (3 * pPrivate->RoomSizeInms * ScaleTable[i]) / pPrivate->NewParams.T60;
+ if(Temp1 >= (4 << 15))
+ {
+ G[i] = 0;
+ }
+ else if((Temp1 >= (2 << 15)))
+ {
+ Temp2 = LVM_Power10(-(Temp1 << 14));
+ Temp1 = LVM_Power10(-(Temp1 << 14));
+ MUL32x32INTO32(Temp1,Temp2,Temp1,24)
+ }
+ else
+ {
+ Temp1 = LVM_Power10(-(Temp1 << 15));
+ }
+ if (NumberOfDelayLines == 1)
+ {
+ G[i] = Temp1;
+ }
+ else
+ {
+ LVM_INT32 TempG;
+ MUL32x16INTO32(Temp1,ONE_OVER_SQRT_TWO,TempG,15)
+ G[i]=TempG;
+ }
+ }
+ }
+
+ /* Set up the feedback mixers for four delay lines */
+ pPrivate->FeedbackMixer[0].Target=G[0]<<7;
+ pPrivate->FeedbackMixer[1].Target=G[1]<<7;
+ pPrivate->FeedbackMixer[2].Target=G[2]<<7;
+ pPrivate->FeedbackMixer[3].Target=G[3]<<7;
+ }
+
+
+ /*
+ * Calculate the gain correction
+ */
+ if((pPrivate->NewParams.RoomSize != pPrivate->CurrentParams.RoomSize) ||
+ (pPrivate->NewParams.Level != pPrivate->CurrentParams.Level) ||
+ (pPrivate->NewParams.T60 != pPrivate->CurrentParams.T60) )
+ {
+ LVM_INT32 Index=0;
+ LVM_INT32 i=0;
+ LVM_INT32 Gain=0;
+ LVM_INT32 RoomSize=0;
+ LVM_INT32 T60;
+ LVM_INT32 Coefs[5];
+
+ if(pPrivate->NewParams.RoomSize==0)
+ {
+ RoomSize=1;
+ }
+ else
+ {
+ RoomSize=(LVM_INT32)pPrivate->NewParams.RoomSize;
+ }
+
+ if(pPrivate->NewParams.T60<100)
+ {
+ T60 = 100 * LVREV_T60_SCALE;
+ }
+ else
+ {
+ T60 = pPrivate->NewParams.T60 * LVREV_T60_SCALE;
+ }
+
+ /* Find the nearest room size in table */
+ for(i=0;i<24;i++)
+ {
+ if(RoomSize<= LVREV_GainPolyTable[i][0])
+ {
+ Index=i;
+ break;
+ }
+ }
+
+
+ if(RoomSize==LVREV_GainPolyTable[Index][0])
+ {
+ /* Take table values if the room size is in table */
+ for(i=1;i<5;i++)
+ {
+ Coefs[i-1]=LVREV_GainPolyTable[Index][i];
+ }
+ Coefs[4]=0;
+ Gain=LVM_Polynomial(3,Coefs,T60); /* Q.24 result */
+ }
+ else
+ {
+ /* Interpolate the gain between nearest room sizes */
+
+ LVM_INT32 Gain1,Gain2;
+ LVM_INT32 Tot_Dist,Dist;
+
+ Tot_Dist=LVREV_GainPolyTable[Index][0]-LVREV_GainPolyTable[Index-1][0];
+ Dist=RoomSize-LVREV_GainPolyTable[Index-1][0];
+
+
+ /* Get gain for first */
+ for(i=1;i<5;i++)
+ {
+ Coefs[i-1]=LVREV_GainPolyTable[Index-1][i];
+ }
+ Coefs[4]=0;
+
+ Gain1=LVM_Polynomial(3,Coefs,T60); /* Q.24 result */
+
+ /* Get gain for second */
+ for(i=1;i<5;i++)
+ {
+ Coefs[i-1]=LVREV_GainPolyTable[Index][i];
+ }
+ Coefs[4]=0;
+
+ Gain2=LVM_Polynomial(3,Coefs,T60); /* Q.24 result */
+
+ /* Linear Interpolate the gain */
+ Gain = Gain1+ (((Gain2-Gain1)*Dist)/(Tot_Dist));
+ }
+
+
+ /*
+ * Get the inverse of gain: Q.15
+ * Gain is mostly above one except few cases, take only gains above 1
+ */
+ if(Gain < 16777216L)
+ {
+ pPrivate->Gain= 32767;
+ }
+ else
+ {
+ pPrivate->Gain=(LVM_INT16)(LVM_MAXINT_32/(Gain>>8));
+ }
+
+
+ Index=((32767*100)/(100+pPrivate->NewParams.Level));
+ pPrivate->Gain=(LVM_INT16)((pPrivate->Gain*Index)>>15);
+ pPrivate->GainMixer.Target = pPrivate->Gain*Index;
+ }
+
+
+ /*
+ * Update the all pass comb filter coefficient
+ */
+ if( (pPrivate->NewParams.Density != pPrivate->CurrentParams.Density) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+ LVM_INT16 i;
+ LVM_INT32 b = pPrivate->NewParams.Density * LVREV_B_8_on_1000;
+
+ for (i=0;i<4; i++)
+ {
+ pPrivate->Mixer_SGFeedback[i].Target = b;
+ pPrivate->Mixer_SGFeedforward[i].Target = b;
+ }
+ }
+
+
+ /*
+ * Update the bypass mixer time constant
+ */
+ if((pPrivate->NewParams.SampleRate != pPrivate->CurrentParams.SampleRate) ||
+ (pPrivate->bFirstControl == LVM_TRUE))
+ {
+ LVM_UINT16 NumChannels = 1; /* Assume MONO format */
+ LVM_INT32 Alpha;
+
+ Alpha = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_FEEDBACKMIXER_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
+ pPrivate->FeedbackMixer[0].Alpha=Alpha;
+ pPrivate->FeedbackMixer[1].Alpha=Alpha;
+ pPrivate->FeedbackMixer[2].Alpha=Alpha;
+ pPrivate->FeedbackMixer[3].Alpha=Alpha;
+
+ NumChannels = 2; /* Always stereo output */
+ pPrivate->BypassMixer.Alpha1 = (LVM_INT32)LVM_Mixer_TimeConstant(LVREV_BYPASSMIXER_TC, LVM_GetFsFromTable(pPrivate->NewParams.SampleRate), NumChannels);
+ pPrivate->BypassMixer.Alpha2 = pPrivate->BypassMixer.Alpha1;
+ pPrivate->GainMixer.Alpha = pPrivate->BypassMixer.Alpha1;
+ }
+
+
+ /*
+ * Update the bypass mixer targets
+ */
+ if( (pPrivate->NewParams.Level != pPrivate->CurrentParams.Level) &&
+ (pPrivate->NewParams.OperatingMode == LVM_MODE_ON))
+ {
+ pPrivate->BypassMixer.Target2 = ((LVM_INT32)(pPrivate->NewParams.Level * 32767)/100)<<16;
+ pPrivate->BypassMixer.Target1 = 0x00000000;
+ if ((pPrivate->NewParams.Level == 0) && (pPrivate->bFirstControl == LVM_FALSE))
+ {
+ pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
+ }
+ if (pPrivate->NewParams.Level != 0)
+ {
+ pPrivate->bDisableReverb = LVM_FALSE;
+ }
+ }
+
+ if(pPrivate->NewParams.OperatingMode != pPrivate->CurrentParams.OperatingMode)
+ {
+ if(pPrivate->NewParams.OperatingMode == LVM_MODE_ON)
+ {
+ pPrivate->BypassMixer.Target2 = ((LVM_INT32)(pPrivate->NewParams.Level * 32767)/100)<<16;
+ pPrivate->BypassMixer.Target1 = 0x00000000;
+
+ pPrivate->BypassMixer.CallbackSet2 = LVM_FALSE;
+ OperatingMode = LVM_MODE_ON;
+ if (pPrivate->NewParams.Level == 0)
+ {
+ pPrivate->bDisableReverb = LVM_TRUE;
+ }
+ else
+ {
+ pPrivate->bDisableReverb = LVM_FALSE;
+ }
+ }
+ else if (pPrivate->bFirstControl == LVM_FALSE)
+ {
+ pPrivate->BypassMixer.Target2 = 0x00000000;
+ pPrivate->BypassMixer.Target1 = 0x00000000;
+ pPrivate->BypassMixer.CallbackSet2 = LVM_TRUE;
+ pPrivate->GainMixer.Target = 0x03FFFFFF;
+ OperatingMode = LVM_MODE_ON;
+ }
+ else
+ {
+ OperatingMode = LVM_MODE_OFF;
+ }
+ }
+
+
+ /*
+ * If it is the first call to ApplyNew settings force the current to the target to begin immediate playback of the effect
+ */
+ if(pPrivate->bFirstControl == LVM_TRUE)
+ {
+ pPrivate->BypassMixer.Current1 = pPrivate->BypassMixer.Target1;
+ pPrivate->BypassMixer.Current2 = pPrivate->BypassMixer.Target2;
+ }
+
+
+ /*
+ * Copy the new parameters
+ */
+ pPrivate->CurrentParams = pPrivate->NewParams;
+ pPrivate->CurrentParams.OperatingMode = OperatingMode;
+
+
+ /*
+ * Update flag
+ */
+ if(pPrivate->bFirstControl == LVM_TRUE)
+ {
+ pPrivate->bFirstControl = LVM_FALSE;
+ }
+
+
+ return LVREV_SUCCESS;
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: BypassMixer_Callback */
+/* */
+/* DESCRIPTION: */
+/* Controls the On to Off operating mode transition */
+/* */
+/* PARAMETERS: */
+/* pPrivate Pointer to the instance private parameters */
+/* */
+/* RETURNS: */
+/* LVREV_Success Succeeded */
+/* LVREV_NULLADDRESS When pPrivate is NULL */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+LVM_INT32 BypassMixer_Callback (void *pCallbackData,
+ void *pGeneralPurpose,
+ LVM_INT16 GeneralPurpose )
+{
+
+ LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)pCallbackData;
+
+
+ /*
+ * Avoid build warnings
+ */
+ (void)pGeneralPurpose;
+ (void)GeneralPurpose;
+
+
+ /*
+ * Turn off
+ */
+ pLVREV_Private->CurrentParams.OperatingMode = LVM_MODE_OFF;
+ pLVREV_Private->bDisableReverb = LVM_TRUE;
+ LVREV_ClearAudioBuffers((LVREV_Handle_t)pCallbackData);
+
+
+ return 0;
+}
+
+/* End of file */
+
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.c
new file mode 100644
index 0000000..6bb1e88
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "VectorArithmetic.h"
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_ClearAudioBuffers */
+/* */
+/* DESCRIPTION: */
+/* This function is used to clear the internal audio buffers of the module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Initialisation succeeded */
+/* LVREV_NULLADDRESS Instance is NULL */
+/* */
+/* NOTES: */
+/* 1. This function must not be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_ClearAudioBuffers(LVREV_Handle_t hInstance)
+{
+
+ LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+
+
+ /*
+ * Check for error conditions
+ */
+ /* Check for NULL pointers */
+ if(hInstance == LVM_NULL)
+ {
+ return LVREV_NULLADDRESS;
+ }
+
+ /*
+ * Clear all filter tap data, delay-lines and other signal related data
+ */
+
+
+ LoadConst_32(0,
+ (void *)&pLVREV_Private->pFastData->HPTaps, /* Destination Cast to void: no dereferencing in function*/
+ 2);
+ LoadConst_32(0,
+ (void *)&pLVREV_Private->pFastData->LPTaps, /* Destination Cast to void: no dereferencing in function*/
+ 2);
+
+ if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+ {
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[3], 2);
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[2], 2);
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+
+ LoadConst_32(0,pLVREV_Private->pDelay_T[3], (LVM_INT16)LVREV_MAX_T3_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[2], (LVM_INT16)LVREV_MAX_T2_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+
+ }
+
+ if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_2)
+ {
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+
+ LoadConst_32(0,pLVREV_Private->pDelay_T[1], (LVM_INT16)LVREV_MAX_T1_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+ }
+
+ if((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_1)
+ {
+ LoadConst_32(0, (LVM_INT32 *)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[0], (LVM_INT16)LVREV_MAX_T0_DELAY);
+ }
+
+ return LVREV_SUCCESS;
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetControlParameters.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetControlParameters.c
new file mode 100644
index 0000000..7cee26d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetControlParameters.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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_GetControlParameters */
+/* */
+/* DESCRIPTION: */
+/* Request the LVREV module control parameters. The current parameter set is returned */
+/* via the parameter pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pControlParams Pointer to an empty parameter structure */
+/* */
+/* RETURNS: */
+/* LVREV_Success Succeeded */
+/* LVREV_NULLADDRESS When hInstance or pControlParams is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetControlParameters(LVREV_Handle_t hInstance,
+ LVREV_ControlParams_st *pControlParams)
+{
+
+ LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+
+
+ /*
+ * Check for error conditions
+ */
+ if((hInstance == LVM_NULL) || (pControlParams == LVM_NULL))
+ {
+ return LVREV_NULLADDRESS;
+ }
+
+ /*
+ * Return the current parameters
+ */
+ *pControlParams = pLVREV_Private->NewParams;
+
+ return LVREV_SUCCESS;
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c
new file mode 100644
index 0000000..ffa5138
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.c
@@ -0,0 +1,322 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "InstAlloc.h"
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_GetInstanceHandle */
+/* */
+/* DESCRIPTION: */
+/* This function is used to create a LVREV module 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 */
+/* pInstanceParams Pointer to the instance parameters */
+/* */
+/* RETURNS: */
+/* LVREV_SUCCESS Succeeded */
+/* LVREV_NULLADDRESS When phInstance or pMemoryTable or pInstanceParams is NULL */
+/* LVREV_NULLADDRESS When one of the memory regions has a NULL pointer */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetInstanceHandle(LVREV_Handle_t *phInstance,
+ LVREV_MemoryTable_st *pMemoryTable,
+ LVREV_InstanceParams_st *pInstanceParams)
+{
+
+ INST_ALLOC SlowData;
+ INST_ALLOC FastData;
+ INST_ALLOC FastCoef;
+ INST_ALLOC Temporary;
+ LVREV_Instance_st *pLVREV_Private;
+ LVM_INT16 i;
+ LVM_UINT16 MaxBlockSize;
+
+
+ /*
+ * Check for error conditions
+ */
+ /* Check for NULL pointers */
+ if((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pInstanceParams == LVM_NULL))
+ {
+ return LVREV_NULLADDRESS;
+ }
+ /* Check the memory table for NULL pointers */
+ for (i = 0; i < LVREV_NR_MEMORY_REGIONS; i++)
+ {
+ if (pMemoryTable->Region[i].Size!=0)
+ {
+ if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
+ {
+ return(LVREV_NULLADDRESS);
+ }
+ }
+ }
+
+ /*
+ * Check all instance parameters are in range
+ */
+ /* Check for a non-zero block size */
+ if (pInstanceParams->MaxBlockSize == 0)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ /* Check for a valid number of delay lines */
+ if ((pInstanceParams->NumDelays != LVREV_DELAYLINES_1)&&
+ (pInstanceParams->NumDelays != LVREV_DELAYLINES_2)&&
+ (pInstanceParams->NumDelays != LVREV_DELAYLINES_4))
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ /*
+ * Initialise the InstAlloc instances
+ */
+ InstAlloc_Init(&SlowData, pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress);
+ InstAlloc_Init(&FastData, pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress);
+ InstAlloc_Init(&FastCoef, pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress);
+ InstAlloc_Init(&Temporary, pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress);
+
+ /*
+ * Zero all memory regions
+ */
+ LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size)/sizeof(LVM_INT16)));
+ LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size)/sizeof(LVM_INT16)));
+ LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size)/sizeof(LVM_INT16)));
+ LoadConst_16(0, (LVM_INT16 *)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress, (LVM_INT16)((pMemoryTable->Region[LVM_TEMPORARY_FAST].Size)/sizeof(LVM_INT16)));
+
+ /*
+ * Set the instance handle if not already initialised
+ */
+ if (*phInstance == LVM_NULL)
+ {
+ *phInstance = InstAlloc_AddMember(&SlowData, sizeof(LVREV_Instance_st));
+ }
+ pLVREV_Private =(LVREV_Instance_st *)*phInstance;
+ pLVREV_Private->MemoryTable = *pMemoryTable;
+
+ if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_4)
+ {
+ MaxBlockSize = LVREV_MAX_AP3_DELAY;
+ }
+ else if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_2)
+ {
+ MaxBlockSize = LVREV_MAX_AP1_DELAY;
+ }
+ else
+ {
+ MaxBlockSize = LVREV_MAX_AP0_DELAY;
+ }
+
+ if(MaxBlockSize>pInstanceParams->MaxBlockSize)
+ {
+ MaxBlockSize=pInstanceParams->MaxBlockSize;
+ }
+
+
+ /*
+ * Set the data, coefficient and temporary memory pointers
+ */
+ pLVREV_Private->pFastData = InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st)); /* Fast data memory base address */
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
+ {
+ pLVREV_Private->pDelay_T[3] = InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_INT32));
+ pLVREV_Private->pDelay_T[2] = InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_INT32));
+ pLVREV_Private->pDelay_T[1] = InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
+ pLVREV_Private->pDelay_T[0] = InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+
+ for( i = 0; i < 4; i++)
+ {
+ pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* Scratch for each delay line output */
+ }
+
+ LoadConst_32(0,pLVREV_Private->pDelay_T[3] ,(LVM_INT16)LVREV_MAX_T3_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[2] ,(LVM_INT16)LVREV_MAX_T2_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[1] ,(LVM_INT16)LVREV_MAX_T1_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[0] ,(LVM_INT16)LVREV_MAX_T0_DELAY);
+ }
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
+ {
+ pLVREV_Private->pDelay_T[1] = InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
+ pLVREV_Private->pDelay_T[0] = InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+
+ for( i = 0; i < 2; i++)
+ {
+ pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* Scratch for each delay line output */
+ }
+
+ LoadConst_32(0,pLVREV_Private->pDelay_T[1] , (LVM_INT16)LVREV_MAX_T1_DELAY);
+ LoadConst_32(0,pLVREV_Private->pDelay_T[0] , (LVM_INT16)LVREV_MAX_T0_DELAY);
+ }
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
+ {
+ pLVREV_Private->pDelay_T[0] = InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+
+ for( i = 0; i < 1; i++)
+ {
+ pLVREV_Private->pScratchDelayLine[i] = InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* Scratch for each delay line output */
+ }
+
+ LoadConst_32(0,pLVREV_Private->pDelay_T[0] , (LVM_INT16)LVREV_MAX_T0_DELAY);
+ }
+
+ /* All-pass delay buffer addresses and sizes */
+ pLVREV_Private->T[0] = LVREV_MAX_T0_DELAY;
+ pLVREV_Private->T[1] = LVREV_MAX_T1_DELAY;
+ pLVREV_Private->T[2] = LVREV_MAX_T2_DELAY;
+ pLVREV_Private->T[3] = LVREV_MAX_T3_DELAY;
+ pLVREV_Private->AB_Selection = 1; /* Select smoothing A to B */
+
+
+ pLVREV_Private->pFastCoef = InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st)); /* Fast coefficient memory base address */
+ pLVREV_Private->pScratch = InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* General purpose scratch */
+ pLVREV_Private->pInputSave = InstAlloc_AddMember(&Temporary, 2 * sizeof(LVM_INT32) * MaxBlockSize); /* Mono->stereo input save for end mix */
+ LoadConst_32(0, pLVREV_Private->pInputSave, (LVM_INT16)(MaxBlockSize*2));
+
+
+ /*
+ * Save the instance parameters in the instance structure
+ */
+ pLVREV_Private->InstanceParams = *pInstanceParams;
+
+
+ /*
+ * Set the parameters to invalid
+ */
+ pLVREV_Private->CurrentParams.SampleRate = LVM_FS_INVALID;
+ pLVREV_Private->CurrentParams.OperatingMode = LVM_MODE_DUMMY;
+ pLVREV_Private->CurrentParams.SourceFormat = LVM_SOURCE_DUMMY;
+
+ pLVREV_Private->bControlPending = LVM_FALSE;
+ pLVREV_Private->bFirstControl = LVM_TRUE;
+ pLVREV_Private->bDisableReverb = LVM_FALSE;
+
+
+ /*
+ * Set mixer parameters
+ */
+ pLVREV_Private->BypassMixer.CallbackParam2 = 0;
+ pLVREV_Private->BypassMixer.pCallbackHandle2 = pLVREV_Private;
+ pLVREV_Private->BypassMixer.pGeneralPurpose2 = LVM_NULL;
+ pLVREV_Private->BypassMixer.pCallBack2 = BypassMixer_Callback;
+ pLVREV_Private->BypassMixer.CallbackSet2 = LVM_FALSE;
+ pLVREV_Private->BypassMixer.Current2 = 0;
+ pLVREV_Private->BypassMixer.Target2 = 0;
+ pLVREV_Private->BypassMixer.CallbackParam1 = 0;
+ pLVREV_Private->BypassMixer.pCallbackHandle1 = LVM_NULL;
+ pLVREV_Private->BypassMixer.pGeneralPurpose1 = LVM_NULL;
+ pLVREV_Private->BypassMixer.pCallBack1 = LVM_NULL;
+ pLVREV_Private->BypassMixer.CallbackSet1 = LVM_FALSE;
+ pLVREV_Private->BypassMixer.Current1 = 0x00000000;
+ pLVREV_Private->BypassMixer.Target1 = 0x00000000;
+
+ pLVREV_Private->RoomSizeInms = 100; // 100 msec
+
+
+ /*
+ * Set the output gain mixer parameters
+ */
+ pLVREV_Private->GainMixer.CallbackParam = 0;
+ pLVREV_Private->GainMixer.pCallbackHandle = LVM_NULL;
+ pLVREV_Private->GainMixer.pGeneralPurpose = LVM_NULL;
+ pLVREV_Private->GainMixer.pCallBack = LVM_NULL;
+ pLVREV_Private->GainMixer.CallbackSet = LVM_FALSE;
+ pLVREV_Private->GainMixer.Current = 0x03ffffff;
+ pLVREV_Private->GainMixer.Target = 0x03ffffff;
+
+
+ /*
+ * Set the All-Pass Filter mixers
+ */
+ for (i=0; i<4; i++)
+ {
+ pLVREV_Private->pOffsetA[i] = pLVREV_Private->pDelay_T[i];
+ pLVREV_Private->pOffsetB[i] = pLVREV_Private->pDelay_T[i];
+ /* Delay tap selection mixer */
+ pLVREV_Private->Mixer_APTaps[i].CallbackParam2 = 0;
+ pLVREV_Private->Mixer_APTaps[i].pCallbackHandle2 = LVM_NULL;
+ pLVREV_Private->Mixer_APTaps[i].pGeneralPurpose2 = LVM_NULL;
+ pLVREV_Private->Mixer_APTaps[i].pCallBack2 = LVM_NULL;
+ pLVREV_Private->Mixer_APTaps[i].CallbackSet2 = LVM_FALSE;
+ pLVREV_Private->Mixer_APTaps[i].Current2 = 0;
+ pLVREV_Private->Mixer_APTaps[i].Target2 = 0;
+ pLVREV_Private->Mixer_APTaps[i].CallbackParam1 = 0;
+ pLVREV_Private->Mixer_APTaps[i].pCallbackHandle1 = LVM_NULL;
+ pLVREV_Private->Mixer_APTaps[i].pGeneralPurpose1 = LVM_NULL;
+ pLVREV_Private->Mixer_APTaps[i].pCallBack1 = LVM_NULL;
+ pLVREV_Private->Mixer_APTaps[i].CallbackSet1 = LVM_FALSE;
+ pLVREV_Private->Mixer_APTaps[i].Current1 = 0;
+ pLVREV_Private->Mixer_APTaps[i].Target1 = 0x7fffffff;
+ /* Feedforward mixer */
+ pLVREV_Private->Mixer_SGFeedforward[i].CallbackParam = 0;
+ pLVREV_Private->Mixer_SGFeedforward[i].pCallbackHandle = LVM_NULL;
+ pLVREV_Private->Mixer_SGFeedforward[i].pGeneralPurpose = LVM_NULL;
+ pLVREV_Private->Mixer_SGFeedforward[i].pCallBack = LVM_NULL;
+ pLVREV_Private->Mixer_SGFeedforward[i].CallbackSet = LVM_FALSE;
+ pLVREV_Private->Mixer_SGFeedforward[i].Current = 0;
+ pLVREV_Private->Mixer_SGFeedforward[i].Target = 0;
+ /* Feedback mixer */
+ pLVREV_Private->Mixer_SGFeedback[i].CallbackParam = 0;
+ pLVREV_Private->Mixer_SGFeedback[i].pCallbackHandle = LVM_NULL;
+ pLVREV_Private->Mixer_SGFeedback[i].pGeneralPurpose = LVM_NULL;
+ pLVREV_Private->Mixer_SGFeedback[i].pCallBack = LVM_NULL;
+ pLVREV_Private->Mixer_SGFeedback[i].CallbackSet = LVM_FALSE;
+ pLVREV_Private->Mixer_SGFeedback[i].Current = 0;
+ pLVREV_Private->Mixer_SGFeedback[i].Target = 0;
+ /* Feedback gain mixer */
+ pLVREV_Private->FeedbackMixer[i].CallbackParam = 0;
+ pLVREV_Private->FeedbackMixer[i].pCallbackHandle = LVM_NULL;
+ pLVREV_Private->FeedbackMixer[i].pGeneralPurpose = LVM_NULL;
+ pLVREV_Private->FeedbackMixer[i].pCallBack = LVM_NULL;
+ pLVREV_Private->FeedbackMixer[i].CallbackSet = LVM_FALSE;
+ pLVREV_Private->FeedbackMixer[i].Current = 0;
+ pLVREV_Private->FeedbackMixer[i].Target = 0;
+ }
+ /* Delay tap index */
+ pLVREV_Private->A_DelaySize[0] = LVREV_MAX_AP0_DELAY;
+ pLVREV_Private->B_DelaySize[0] = LVREV_MAX_AP0_DELAY;
+ pLVREV_Private->A_DelaySize[1] = LVREV_MAX_AP1_DELAY;
+ pLVREV_Private->B_DelaySize[1] = LVREV_MAX_AP1_DELAY;
+ pLVREV_Private->A_DelaySize[2] = LVREV_MAX_AP2_DELAY;
+ pLVREV_Private->B_DelaySize[2] = LVREV_MAX_AP2_DELAY;
+ pLVREV_Private->A_DelaySize[3] = LVREV_MAX_AP3_DELAY;
+ pLVREV_Private->B_DelaySize[3] = LVREV_MAX_AP3_DELAY;
+
+
+ LVREV_ClearAudioBuffers(*phInstance);
+
+ return LVREV_SUCCESS;
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c
new file mode 100644
index 0000000..2012432
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.c
@@ -0,0 +1,245 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "InstAlloc.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_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. */
+/* */
+/* 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 table */
+/* pInstanceParams Pointer to the instance parameters */
+/* */
+/* RETURNS: */
+/* LVREV_Success Succeeded */
+/* LVREV_NULLADDRESS When pMemoryTable is NULL */
+/* LVREV_NULLADDRESS When requesting memory requirements and pInstanceParams */
+/* is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_GetMemoryTable(LVREV_Handle_t hInstance,
+ LVREV_MemoryTable_st *pMemoryTable,
+ LVREV_InstanceParams_st *pInstanceParams)
+{
+
+ INST_ALLOC SlowData;
+ INST_ALLOC FastData;
+ INST_ALLOC FastCoef;
+ INST_ALLOC Temporary;
+ LVM_INT16 i;
+ LVM_UINT16 MaxBlockSize;
+
+
+ /*
+ * Check for error conditions
+ */
+ /* Check for NULL pointer */
+ if (pMemoryTable == LVM_NULL)
+ {
+ return(LVREV_NULLADDRESS);
+ }
+
+ /*
+ * Check all instance parameters are in range
+ */
+ if (pInstanceParams != LVM_NULL)
+ {
+ /*
+ * Call for memory allocation, so check the parameters
+ */
+ /* Check for a non-zero block size */
+ if (pInstanceParams->MaxBlockSize == 0)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ /* Check for a valid number of delay lines */
+ if ((pInstanceParams->NumDelays != LVREV_DELAYLINES_1) &&
+ (pInstanceParams->NumDelays != LVREV_DELAYLINES_2) &&
+ (pInstanceParams->NumDelays != LVREV_DELAYLINES_4))
+ {
+ return LVREV_OUTOFRANGE;
+ }
+ }
+
+ /*
+ * Initialise the InstAlloc instances
+ */
+ InstAlloc_Init(&SlowData, (void *)LVM_NULL);
+ InstAlloc_Init(&FastData, (void *)LVM_NULL);
+ InstAlloc_Init(&FastCoef, (void *)LVM_NULL);
+ InstAlloc_Init(&Temporary, (void *)LVM_NULL);
+
+
+ /*
+ * Fill in the memory table
+ */
+ if (hInstance == LVM_NULL)
+ {
+ /*
+ * Check for null pointers
+ */
+ if (pInstanceParams == LVM_NULL)
+ {
+ return(LVREV_NULLADDRESS);
+ }
+
+
+ /*
+ * Select the maximum internal block size
+ */
+ if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_4)
+ {
+ MaxBlockSize = LVREV_MAX_AP3_DELAY;
+ }
+ else if(pInstanceParams->NumDelays ==LVREV_DELAYLINES_2)
+ {
+ MaxBlockSize = LVREV_MAX_AP1_DELAY;
+ }
+ else
+ {
+ MaxBlockSize = LVREV_MAX_AP0_DELAY;
+ }
+
+ if(MaxBlockSize>pInstanceParams->MaxBlockSize)
+ {
+ MaxBlockSize=pInstanceParams->MaxBlockSize;
+ }
+
+
+ /*
+ * Slow data memory
+ */
+ InstAlloc_AddMember(&SlowData, sizeof(LVREV_Instance_st));
+ pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size = InstAlloc_GetTotal(&SlowData);
+ pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Type = LVM_PERSISTENT_SLOW_DATA;
+ pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
+
+
+ /*
+ * Persistent fast data memory
+ */
+ InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
+ {
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_INT32));
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_INT32));
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+ }
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
+ {
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T1_DELAY * sizeof(LVM_INT32));
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+ }
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
+ {
+ InstAlloc_AddMember(&FastData, LVREV_MAX_T0_DELAY * sizeof(LVM_INT32));
+ }
+
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size = InstAlloc_GetTotal(&FastData);
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Type = LVM_PERSISTENT_FAST_DATA;
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
+
+
+ /*
+ * Persistent fast coefficient memory
+ */
+ InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size = InstAlloc_GetTotal(&FastCoef);
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Type = LVM_PERSISTENT_FAST_COEF;
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
+
+
+ /*
+ * Temporary fast memory
+ */
+ InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* General purpose scratch memory */
+ InstAlloc_AddMember(&Temporary, 2*sizeof(LVM_INT32) * MaxBlockSize); /* Mono->stereo input saved for end mix */
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_4)
+ {
+ for(i=0; i<4; i++)
+ {
+ InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* A Scratch buffer for each delay line */
+ }
+ }
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_2)
+ {
+ for(i=0; i<2; i++)
+ {
+ InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* A Scratch buffer for each delay line */
+ }
+ }
+
+ if(pInstanceParams->NumDelays == LVREV_DELAYLINES_1)
+ {
+ for(i=0; i<1; i++)
+ {
+ InstAlloc_AddMember(&Temporary, sizeof(LVM_INT32) * MaxBlockSize); /* A Scratch buffer for each delay line */
+ }
+ }
+
+ pMemoryTable->Region[LVM_TEMPORARY_FAST].Size = InstAlloc_GetTotal(&Temporary);
+ pMemoryTable->Region[LVM_TEMPORARY_FAST].Type = LVM_TEMPORARY_FAST;
+ pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress = LVM_NULL;
+
+ }
+ else
+ {
+ LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+
+
+ /*
+ * Read back memory allocation table
+ */
+ *pMemoryTable = pLVREV_Private->MemoryTable;
+ }
+
+
+ return(LVREV_SUCCESS);
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
new file mode 100644
index 0000000..fbfa437
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.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.
+ */
+
+#ifndef __LVREV_PRIVATE_H__
+#define __LVREV_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV.h"
+#include "LVREV_Tables.h"
+#include "BIQUAD.h"
+#include "Filter.h"
+#include "VectorArithmetic.h"
+#include "Mixer.h"
+#include "LVM_Macros.h"
+
+
+/****************************************************************************************/
+/* */
+/* Defines */
+/* */
+/****************************************************************************************/
+/* General */
+#define ONE_OVER_SQRT_TWO 23170 /* 1/sqrt(2) * 2^15 */
+#define LVREV_B_8_on_1000 17179869 /* 0.8 * 2^31 */
+#define LVREV_HEADROOM 8192 /* -12dB * 2^15 */
+#define LVREV_2_9_INQ29 1583769190L /* 2.9 in Q29 format */
+#define LVREV_MIN3DB 0x5A82 /* -3dB in Q15 format */
+
+/* Intenal constants */
+#define LVREV_LP_Poly_Order 4
+#define LVREV_LP_Poly_Shift 5
+#define LVREV_T_3_Power_0_on_4 32768
+#define LVREV_T_3_Power_1_on_4 43125
+#define LVREV_T_3_Power_2_on_4 56755
+#define LVREV_T_3_Power_3_on_4 74694
+#define LVREV_T60_SCALE 306774 /*(32767/7000)<<16 */
+#define LVREV_T_3_Power_minus0_on_4 32767 /* 3^(-0/4) * 2^15 */
+#define LVREV_T_3_Power_minus1_on_4 24898 /* 3^(-1/4) * 2^15 */
+#define LVREV_T_3_Power_minus2_on_4 18919 /* 3^(-2/4) * 2^15 */
+#define LVREV_T_3_Power_minus3_on_4 14375 /* 3^(-3/4) * 2^15 */
+#define LVREV_MAX_T3_DELAY 2527 /* ((48000 * 120 * LVREV_T_3_Power_minus3_on_4) >> 15) / 1000 */
+#define LVREV_MAX_T2_DELAY 3326 /* ((48000 * 120 * LVREV_T_3_Power_minus2_on_4) >> 15) / 1000 */
+#define LVREV_MAX_T1_DELAY 4377 /* ((48000 * 120 * LVREV_T_3_Power_minus1_on_4) >> 15) / 1000 */
+#define LVREV_MAX_T0_DELAY 5760 /* ((48000 * 120 * LVREV_T_3_Power_minus0_on_4) >> 15) / 1000 */
+#define LVREV_MAX_AP3_DELAY 1685 /* ((48000 * 120 * LVREV_T_3_Power_minus3_on_4) >> 15) / 1500 */
+#define LVREV_MAX_AP2_DELAY 2218 /* ((48000 * 120 * LVREV_T_3_Power_minus2_on_4) >> 15) / 1500 */
+#define LVREV_MAX_AP1_DELAY 2918 /* ((48000 * 120 * LVREV_T_3_Power_minus1_on_4) >> 15) / 1500 */
+#define LVREV_MAX_AP0_DELAY 3840 /* ((48000 * 120 * LVREV_T_3_Power_minus0_on_4) >> 15) / 1500 */
+#define LVREV_BYPASSMIXER_TC 1000 /* Bypass mixer time constant*/
+#define LVREV_ALLPASS_TC 1000 /* All-pass filter time constant */
+#define LVREV_ALLPASS_TAP_TC 10000 /* All-pass filter dely tap change */
+#define LVREV_FEEDBACKMIXER_TC 100 /* Feedback mixer time constant*/
+#define LVREV_OUTPUTGAIN_SHIFT 5 /* Bits shift for output gain correction */
+
+/* Parameter limits */
+#define LVREV_NUM_FS 9 /* Number of supported sample rates */
+#define LVREV_MAXBLKSIZE_LIMIT 64 /* Maximum block size low limit */
+#define LVREV_MAX_LEVEL 100 /* Maximum level, 100% */
+#define LVREV_MIN_LPF_CORNER 50 /* Low pass filter limits */
+#define LVREV_MAX_LPF_CORNER 23999
+#define LVREV_MIN_HPF_CORNER 20 /* High pass filrer limits */
+#define LVREV_MAX_HPF_CORNER 1000
+#define LVREV_MAX_T60 7000 /* Maximum T60 time in ms */
+#define LVREV_MAX_DENSITY 100 /* Maximum density, 100% */
+#define LVREV_MAX_DAMPING 100 /* Maximum damping, 100% */
+#define LVREV_MAX_ROOMSIZE 100 /* Maximum room size, 100% */
+
+
+
+/****************************************************************************************/
+/* */
+/* Structures */
+/* */
+/****************************************************************************************/
+/* Fast data structure */
+typedef struct
+{
+
+ Biquad_1I_Order1_Taps_t HPTaps; /* High pass filter taps */
+ Biquad_1I_Order1_Taps_t LPTaps; /* Low pass filter taps */
+ Biquad_1I_Order1_Taps_t RevLPTaps[4]; /* Reverb low pass filters taps */
+
+} LVREV_FastData_st;
+
+
+/* Fast coefficient structure */
+typedef struct
+{
+
+ Biquad_Instance_t HPCoefs; /* High pass filter coefficients */
+ Biquad_Instance_t LPCoefs; /* Low pass filter coefficients */
+ Biquad_Instance_t RevLPCoefs[4]; /* Reverb low pass filters coefficients */
+
+} LVREV_FastCoef_st;
+
+
+/* Instance parameter structure */
+typedef struct
+{
+ /* General */
+ LVREV_InstanceParams_st InstanceParams; /* Initialisation time instance parameters */
+ LVREV_MemoryTable_st MemoryTable; /* Memory table */
+ LVREV_ControlParams_st CurrentParams; /* Parameters being used */
+ LVREV_ControlParams_st NewParams; /* New parameters from the calling application */
+ LVM_CHAR bControlPending; /* Flag to indicate new parameters are available */
+ LVM_CHAR bFirstControl; /* Flag to indicate that the control function is called for the first time */
+ LVM_CHAR bDisableReverb; /* Flag to indicate that the mix level is 0% and the reverb can be disabled */
+ LVM_INT32 RoomSizeInms; /* Room size in msec */
+ LVM_INT32 MaxBlkLen; /* Maximum block size for internal processing */
+
+ /* Aligned memory pointers */
+ LVREV_FastData_st *pFastData; /* Fast data memory base address */
+ LVREV_FastCoef_st *pFastCoef; /* Fast coefficient memory base address */
+ LVM_INT32 *pScratchDelayLine[4]; /* Delay line scratch memory */
+ LVM_INT32 *pScratch; /* Multi ussge scratch */
+ LVM_INT32 *pInputSave; /* Reverb block input save for dry/wet mixing*/
+
+ /* Feedback matrix */
+ Mix_1St_Cll_t FeedbackMixer[4]; /* Mixer for Pop and Click Supression caused by feedback Gain */
+
+ /* All-Pass Filter */
+ LVM_INT32 T[4]; /* Maximum delay size of buffer */
+ LVM_INT32 *pDelay_T[4]; /* Pointer to delay buffers */
+ LVM_INT32 Delay_AP[4]; /* Offset to AP delay buffer start */
+ LVM_INT16 AB_Selection; /* Smooth from tap A to B when 1 otherwise B to A */
+ LVM_INT32 A_DelaySize[4]; /* A delay length in samples */
+ LVM_INT32 B_DelaySize[4]; /* B delay length in samples */
+ LVM_INT32 *pOffsetA[4]; /* Offset for the A delay tap */
+ LVM_INT32 *pOffsetB[4]; /* Offset for the B delay tap */
+ Mix_2St_Cll_t Mixer_APTaps[4]; /* Smoothed AP delay mixer */
+ Mix_1St_Cll_t Mixer_SGFeedback[4]; /* Smoothed SAfeedback gain */
+ Mix_1St_Cll_t Mixer_SGFeedforward[4]; /* Smoothed AP feedforward gain */
+
+ /* Output gain */
+ Mix_2St_Cll_t BypassMixer; /* Dry/wet mixer */
+ LVM_INT16 Gain; /* Gain applied to output to maintain average signal power */
+ Mix_1St_Cll_t GainMixer; /* Gain smoothing */
+
+} LVREV_Instance_st;
+
+
+/****************************************************************************************/
+/* */
+/* Function prototypes */
+/* */
+/****************************************************************************************/
+
+LVREV_ReturnStatus_en LVREV_ApplyNewSettings(LVREV_Instance_st *pPrivate);
+
+void ReverbBlock(LVM_INT32 *pInput,
+ LVM_INT32 *pOutput,
+ LVREV_Instance_st *pPrivate,
+ LVM_UINT16 NumSamples);
+
+LVM_INT32 BypassMixer_Callback(void *pCallbackData,
+ void *pGeneralPurpose,
+ LVM_INT16 GeneralPurpose );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** __LVREV_PRIVATE_H__ **/
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
new file mode 100644
index 0000000..5c7a8a0
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
@@ -0,0 +1,485 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "VectorArithmetic.h"
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_Process */
+/* */
+/* DESCRIPTION: */
+/* Process function for the LVREV 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: */
+/* LVREV_Success Succeeded */
+/* LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size */
+/* LVREV_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */
+/* */
+/* NOTES: */
+/* 1. The input and output buffers must be 32-bit aligned */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t hInstance,
+ const LVM_INT32 *pInData,
+ LVM_INT32 *pOutData,
+ const LVM_UINT16 NumSamples)
+{
+ LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+ LVM_INT32 *pInput = (LVM_INT32 *)pInData;
+ LVM_INT32 *pOutput = pOutData;
+ LVM_INT32 SamplesToProcess, RemainingSamples;
+ LVM_INT32 format = 1;
+
+ /*
+ * Check for error conditions
+ */
+
+ /* Check for NULL pointers */
+ if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
+ {
+ return LVREV_NULLADDRESS;
+ }
+
+ /*
+ * Apply the new controls settings if required
+ */
+ if(pLVREV_Private->bControlPending == LVM_TRUE)
+ {
+ LVREV_ReturnStatus_en errorCode;
+
+ /*
+ * Clear the pending flag and update the control settings
+ */
+ pLVREV_Private->bControlPending = LVM_FALSE;
+
+ errorCode = LVREV_ApplyNewSettings (pLVREV_Private);
+
+ if(errorCode != LVREV_SUCCESS)
+ {
+ return errorCode;
+ }
+ }
+
+ /*
+ * Trap the case where the number of samples is zero.
+ */
+ if (NumSamples == 0)
+ {
+ return LVREV_SUCCESS;
+ }
+
+ /*
+ * If OFF copy and reformat the data as necessary
+ */
+ if (pLVREV_Private->CurrentParams.OperatingMode == LVM_MODE_OFF)
+ {
+ if(pInput != pOutput)
+ {
+ /*
+ * Copy the data to the output buffer, convert to stereo is required
+ */
+
+ if(pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO){
+ MonoTo2I_32(pInput, pOutput, NumSamples);
+ } else {
+ Copy_16((LVM_INT16 *)pInput,
+ (LVM_INT16 *)pOutput,
+ (LVM_INT16)(NumSamples << 2)); // 32 bit data, stereo
+ }
+ }
+
+ return LVREV_SUCCESS;
+ }
+
+ RemainingSamples = (LVM_INT32)NumSamples;
+
+ if (pLVREV_Private->CurrentParams.SourceFormat != LVM_MONO)
+ {
+ format = 2;
+ }
+
+ while (RemainingSamples!=0)
+ {
+ /*
+ * Process the data
+ */
+
+ if(RemainingSamples > pLVREV_Private->MaxBlkLen)
+ {
+ SamplesToProcess = pLVREV_Private->MaxBlkLen;
+ RemainingSamples = (LVM_INT16)(RemainingSamples - SamplesToProcess);
+ }
+ else
+ {
+ SamplesToProcess = RemainingSamples;
+ RemainingSamples = 0;
+ }
+
+ ReverbBlock(pInput, pOutput, pLVREV_Private, (LVM_UINT16)SamplesToProcess);
+
+ pInput = (LVM_INT32 *)(pInput +(SamplesToProcess*format));
+ pOutput = (LVM_INT32 *)(pOutput+(SamplesToProcess*2)); // Always stereo output
+ }
+
+ return LVREV_SUCCESS;
+}
+
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: ReverbBlock */
+/* */
+/* DESCRIPTION: */
+/* Process function for the LVREV 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: */
+/* LVREV_Success Succeeded */
+/* LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size */
+/* LVREV_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */
+/* */
+/* NOTES: */
+/* 1. The input and output buffers must be 32-bit aligned */
+/* */
+/****************************************************************************************/
+
+void ReverbBlock(LVM_INT32 *pInput, LVM_INT32 *pOutput, LVREV_Instance_st *pPrivate, LVM_UINT16 NumSamples)
+{
+ LVM_INT16 j, size;
+ LVM_INT32 *pDelayLine;
+ LVM_INT32 *pDelayLineInput = pPrivate->pScratch;
+ LVM_INT32 *pScratch = pPrivate->pScratch;
+ LVM_INT32 *pIn;
+ LVM_INT32 *pTemp = pPrivate->pInputSave;
+ LVM_INT32 NumberOfDelayLines;
+
+ /******************************************************************************
+ * All calculations will go into the buffer pointed to by pTemp, this will *
+ * then be mixed with the original input to create the final output. *
+ * *
+ * When INPLACE processing is selected this must be a temporary buffer and *
+ * hence this is the worst case, so for simplicity this will ALWAYS be so *
+ * *
+ * The input buffer will remain untouched until the output of the mixer if *
+ * INPLACE processing is selected. *
+ * *
+ * The temp buffer will always be NumSamples in size regardless of MONO or *
+ * STEREO input. In the case of stereo input all processing is done in MONO *
+ * and the final output is converted to STEREO after the mixer *
+ ******************************************************************************/
+
+ if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4 )
+ {
+ NumberOfDelayLines = 4;
+ }
+ else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2 )
+ {
+ NumberOfDelayLines = 2;
+ }
+ else
+ {
+ NumberOfDelayLines = 1;
+ }
+
+ if(pPrivate->CurrentParams.SourceFormat == LVM_MONO)
+ {
+ pIn = pInput;
+ }
+ else
+ {
+ /*
+ * Stereo to mono conversion
+ */
+
+ From2iToMono_32( pInput,
+ pTemp,
+ (LVM_INT16)NumSamples);
+
+ pIn = pTemp;
+ }
+
+ Mult3s_32x16(pIn,
+ (LVM_INT16)LVREV_HEADROOM,
+ pTemp,
+ (LVM_INT16)NumSamples);
+
+ /*
+ * High pass filter
+ */
+ FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->HPCoefs,
+ pTemp,
+ pTemp,
+ (LVM_INT16)NumSamples);
+ /*
+ * Low pass filter
+ */
+ FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->LPCoefs,
+ pTemp,
+ pTemp,
+ (LVM_INT16)NumSamples);
+
+ /*
+ * Process all delay lines
+ */
+
+ for(j = 0; j < NumberOfDelayLines; j++)
+ {
+ pDelayLine = pPrivate->pScratchDelayLine[j];
+
+ /*
+ * All-pass filter with pop and click suppression
+ */
+ /* Get the smoothed, delayed output. Put it in the output buffer */
+ MixSoft_2St_D32C31_SAT(&pPrivate->Mixer_APTaps[j],
+ pPrivate->pOffsetA[j],
+ pPrivate->pOffsetB[j],
+ pDelayLine,
+ (LVM_INT16)NumSamples);
+ /* Re-align the all pass filter delay buffer and copying the fixed delay data to the AP delay in the process */
+ Copy_16((LVM_INT16 *)&pPrivate->pDelay_T[j][NumSamples],
+ (LVM_INT16 *)pPrivate->pDelay_T[j],
+ (LVM_INT16)((pPrivate->T[j]-NumSamples) << 1)); /* 32-bit data */
+ /* Apply the smoothed feedback and save to fixed delay input (currently empty) */
+ MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedback[j],
+ pDelayLine,
+ &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ (LVM_INT16)NumSamples);
+ /* Sum into the AP delay line */
+ Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ -0x7fff, /* Invert since the feedback coefficient is negative */
+ &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples],
+ (LVM_INT16)NumSamples);
+ /* Apply smoothed feedforward sand save to fixed delay input (currently empty) */
+ MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedforward[j],
+ &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples],
+ &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ (LVM_INT16)NumSamples);
+ /* Sum into the AP output */
+ Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ 0x7fff,
+ pDelayLine,
+ (LVM_INT16)NumSamples);
+
+ /*
+ * Feedback gain
+ */
+ MixSoft_1St_D32C31_WRA(&pPrivate->FeedbackMixer[j], pDelayLine, pDelayLine, NumSamples);
+
+ /*
+ * Low pass filter
+ */
+ FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->RevLPCoefs[j],
+ pDelayLine,
+ pDelayLine,
+ (LVM_INT16)NumSamples);
+ }
+
+ /*
+ * Apply rotation matrix and delay samples
+ */
+ for(j = 0; j < NumberOfDelayLines; j++)
+ {
+
+ Copy_16( (LVM_INT16*)(pTemp),
+ (LVM_INT16*)(pDelayLineInput),
+ (LVM_INT16)(NumSamples << 1));
+
+ /*
+ * Rotation matrix mix
+ */
+ switch(j)
+ {
+ case 3:
+ /*
+ * Add delay line 1 and 2 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[2], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+
+ break;
+ case 2:
+
+ /*
+ * Add delay line 0 and 3 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[3], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+
+ break;
+ case 1:
+ if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+ {
+ /*
+ * Add delay line 0 and 3 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[3], pDelayLineInput, (LVM_INT16)NumSamples);
+
+ }
+ else
+ {
+ /*
+ * Add delay line 0 and 1 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+
+ }
+ break;
+ case 0:
+ if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+ {
+ /*
+ * Add delay line 1 and 2 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[2], pDelayLineInput, (LVM_INT16)NumSamples);
+
+ }
+ else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
+ {
+ /*
+ * Add delay line 0 and 1 contribution
+ */
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples);
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+
+ }
+ else
+ {
+ /*
+ * Add delay line 0 contribution
+ */
+
+ /* SOURCE DESTINATION*/
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Delay samples
+ */
+ Copy_16((LVM_INT16 *)pDelayLineInput,
+ (LVM_INT16 *)&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ (LVM_INT16)(NumSamples << 1)); /* 32-bit data */
+
+ }
+
+
+ /*
+ * Create stereo output
+ */
+ switch(pPrivate->InstanceParams.NumDelays)
+ {
+ case LVREV_DELAYLINES_4:
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[3],
+ pPrivate->pScratchDelayLine[0],
+ (LVM_INT16)NumSamples);
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[2],
+ pPrivate->pScratchDelayLine[1],
+ (LVM_INT16)NumSamples);
+
+
+ JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
+ pPrivate->pScratchDelayLine[1],
+ pTemp,
+ (LVM_INT16)NumSamples);
+
+
+ break;
+ case LVREV_DELAYLINES_2:
+
+ Copy_16( (LVM_INT16*)pPrivate->pScratchDelayLine[1],
+ (LVM_INT16*)pScratch,
+ (LVM_INT16)(NumSamples << 1));
+
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0],
+ -0x8000,
+ pScratch,
+ (LVM_INT16)NumSamples);
+
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[1],
+ pPrivate->pScratchDelayLine[0],
+ (LVM_INT16)NumSamples);
+
+
+ JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
+ pScratch,
+ pTemp,
+ (LVM_INT16)NumSamples);
+ break;
+ case LVREV_DELAYLINES_1:
+ MonoTo2I_32(pPrivate->pScratchDelayLine[0],
+ pTemp,
+ (LVM_INT16)NumSamples);
+ break;
+ default:
+ break;
+ }
+
+
+ /*
+ * Dry/wet mixer
+ */
+
+ size = (LVM_INT16)(NumSamples << 1);
+ MixSoft_2St_D32C31_SAT(&pPrivate->BypassMixer,
+ pTemp,
+ pTemp,
+ pOutput,
+ size);
+
+ /* Apply Gain*/
+
+ Shift_Sat_v32xv32 (LVREV_OUTPUTGAIN_SHIFT,
+ pOutput,
+ pOutput,
+ size);
+
+ MixSoft_1St_D32C31_WRA(&pPrivate->GainMixer,
+ pOutput,
+ pOutput,
+ size);
+
+ return;
+}
+
+
+/* End of file */
+
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
new file mode 100644
index 0000000..f5895a7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_SetControlParameters */
+/* */
+/* DESCRIPTION: */
+/* Sets or changes the LVREV module parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pNewParams Pointer to a parameter structure */
+/* */
+/* RETURNS: */
+/* LVM_Success Succeeded */
+/* LVREV_NULLADDRESS When hInstance or pNewParams is NULL */
+/* LVREV_OUTOFRANGE When any of the new parameters is out of range */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVREV_Process function */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_SetControlParameters(LVREV_Handle_t hInstance,
+ LVREV_ControlParams_st *pNewParams)
+{
+
+ LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+
+
+ /*
+ * Check for error conditions
+ */
+ if((hInstance == LVM_NULL) || (pNewParams == LVM_NULL))
+ {
+ return LVREV_NULLADDRESS;
+ }
+
+ /*
+ * Check all new control parameters are in range
+ */
+ if( ((pNewParams->OperatingMode != LVM_MODE_OFF) && (pNewParams->OperatingMode != LVM_MODE_ON)) ||
+ ((pNewParams->SampleRate != LVM_FS_8000) && (pNewParams->SampleRate != LVM_FS_11025) && (pNewParams->SampleRate != LVM_FS_12000) &&
+ (pNewParams->SampleRate != LVM_FS_16000) && (pNewParams->SampleRate != LVM_FS_22050) && (pNewParams->SampleRate != LVM_FS_24000) &&
+ (pNewParams->SampleRate != LVM_FS_32000) && (pNewParams->SampleRate != LVM_FS_44100) && (pNewParams->SampleRate != LVM_FS_48000)) ||
+ ((pNewParams->SourceFormat != LVM_STEREO) && (pNewParams->SourceFormat != LVM_MONOINSTEREO) && (pNewParams->SourceFormat != LVM_MONO)) )
+ {
+ return (LVREV_OUTOFRANGE);
+ }
+
+
+ if (pNewParams->Level > LVREV_MAX_LEVEL)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ if ((pNewParams->LPF < LVREV_MIN_LPF_CORNER) || (pNewParams->LPF > LVREV_MAX_LPF_CORNER))
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ if ((pNewParams->HPF < LVREV_MIN_HPF_CORNER) || (pNewParams->HPF > LVREV_MAX_HPF_CORNER))
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ if (pNewParams->T60 > LVREV_MAX_T60)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ if (pNewParams->Density > LVREV_MAX_DENSITY)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ if (pNewParams->Damping > LVREV_MAX_DAMPING)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+ if (pNewParams->RoomSize > LVREV_MAX_ROOMSIZE)
+ {
+ return LVREV_OUTOFRANGE;
+ }
+
+
+
+ /*
+ * Copy the new parameters and set the flag to indicate they are available
+ */
+ pLVREV_Private->NewParams = *pNewParams;
+ pLVREV_Private->bControlPending = LVM_TRUE;
+
+ return LVREV_SUCCESS;
+}
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c
new file mode 100644
index 0000000..5a6d43d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.c
@@ -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.
+ */
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV.h"
+
+/****************************************************************************************/
+/* */
+/* Tables */
+/* */
+/****************************************************************************************/
+
+/* Table with supported sampling rates. The table can be indexed using LVM_Fs_en */
+const LVM_UINT16 LVM_FsTable[] = {
+ 8000 ,
+ 11025,
+ 12000,
+ 16000,
+ 22050,
+ 24000,
+ 32000,
+ 44100,
+ 48000
+};
+
+/* Table with supported sampling rates. The table can be indexed using LVM_Fs_en */
+LVM_UINT16 LVM_GetFsFromTable(LVM_Fs_en FsIndex){
+ if (FsIndex > LVM_FS_48000)
+ return 0;
+
+ return (LVM_FsTable[FsIndex]);
+}
+
+/* In order to maintain consistant input and out put signal strengths
+ output gain/attenuation is applied. This gain depends on T60 and Rooms
+ size parameters. These polynomial coefficients are calculated experimentally.
+ First value in the table is room size
+ second value is A0
+ third value is A1
+ fourth value is A2
+ fifth value is A3
+ sixth value is A4
+
+ shift value is to be added array (to use LVM_Polynomial function)
+
+ The gain is calculated using variable x=(T60*32767/7000)*32768;
+
+ first values is used to get polynomial set for given room size,
+ For room sizes which are not in the table, linear interpolation can be used.
+
+ */
+
+/* Normalizing output including Reverb Level part (only shift up)*/
+const LVM_INT32 LVREV_GainPolyTable[24][5]={{1,17547434,128867434,-120988896,50761228,},
+ {2,18256869,172666902,-193169292,88345744,},
+ {3,16591311,139250151,-149667234,66770059,},
+ {4,17379977,170835131,-173579321,76278163,},
+ {5,18963512,210364934,-228623519,103435022,},
+ {6,17796318,135756417,-144084053,64327698,},
+ {7,17454695,174593214,-187513064,85146582,},
+ {8,17229257,140715570,-145790588,65361740,},
+ {9,17000547,163195946,-176733969,79562130,},
+ {10,16711699,142476304,-133339887,58366547,},
+ {13,18108419,149223697,-161762020,74397589,},
+ {15,16682043,124844884,-134284487,60082180,},
+ {17,16627346,120936430,-121766674,53146421,},
+ {20,17338325,125432694,-126616983,56534237,},
+ {25,16489146,99218217,-94597467,40616506,},
+ {30,15582373,84479043,-75365006,30952348,},
+ {40,16000669,84896611,-75031127,30696306,},
+ {50,15087054,71695031,-59349268,23279669,},
+ {60,15830714,68672971,-58211201,23671158,},
+ {70,15536061,66657972,-55901437,22560153,},
+ {75,15013145,48179917,-24138354,5232074,},
+ {80,15688738,50195036,-34206760,11515792,},
+ {90,16003322,48323661,-35607378,13153872,},
+ {100,15955223,48558201,-33706865,11715792,},
+ };
+
+/* End of file */
+
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
new file mode 100644
index 0000000..5f993bd
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Tables.h
@@ -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.
+ */
+
+
+#ifndef _LVREV_TABLES_H_
+#define _LVREV_TABLES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+
+/****************************************************************************************/
+/* */
+/* Definitions */
+/* */
+/****************************************************************************************/
+
+extern const LVM_UINT16 LVM_FsTable[];
+extern LVM_UINT16 LVM_GetFsFromTable(LVM_Fs_en FsIndex);
+extern LVM_INT32 LVREV_GainPolyTable[24][5];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** _LVREV_TABLES_H_ **/
+
+/* End of file */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h
new file mode 100644
index 0000000..a675cb2
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h
@@ -0,0 +1,290 @@
+/*
+ * 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 _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 100644
index 0000000..cd5f69c
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c
@@ -0,0 +1,707 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..27a4bc3
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c
@@ -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.
+ */
+
+#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 100644
index 0000000..0984b10
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c
@@ -0,0 +1,169 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..1d8bedd
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
@@ -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.
+ */
+
+#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 100644
index 0000000..9e29f68
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
@@ -0,0 +1,252 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..836bfd7
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h
@@ -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.
+ */
+
+#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 100644
index 0000000..50e0a80
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..67197c1
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+
+#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 100644
index 0000000..21a5d8d
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
@@ -0,0 +1,241 @@
+/*
+ * 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.
+ */
+
+
+/************************************************************************************/
+/* */
+/* 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 100644
index 0000000..0d62274
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
@@ -0,0 +1,388 @@
+/*
+ * 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.
+ */
+
+/****************************************************************************************/
+/* */
+/* 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 100644
index 0000000..3e48c7e
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ */
+
+/************************************************************************************/
+/* */
+/* 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 100644
index 0000000..d1ef70a
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h
@@ -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.
+ */
+
+#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 100644
index 0000000..ce6d410
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.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.
+ */
+
+/************************************************************************************/
+/* */
+/* 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];
+
+ pInstance->CompressGain = pInstance->VolCorrect.CompMin;
+
+ 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 100644
index 0000000..25b0d86
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.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.
+ */
+
+/************************************************************************************/
+/* */
+/* 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 100644
index 0000000..cf96f5b
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
@@ -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.
+ */
+
+#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 100644
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 100644
index 0000000..1904e46
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+
+/************************************************************************************/
+/* */
+/* 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 100644
index 0000000..f3adb8d
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+
+/************************************************************************************/
+/* */
+/* 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 */
+#define LVCS_COMPGAINFRAME 64 /* Compressor gain update interval */
+
+/* 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 */
+ LVM_INT16 CompressGain; /* Last used compressor 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 100644
index 0000000..5d99461
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c
@@ -0,0 +1,333 @@
+/*
+ * 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.
+ */
+
+
+/************************************************************************************/
+/* */
+/* 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) );
+
+ if(NumSamples < LVCS_COMPGAINFRAME)
+ {
+ NonLinComp_D16(Gain, /* Compressor gain setting */
+ pOutData,
+ pOutData,
+ (LVM_INT32)(2*NumSamples));
+ }
+ else
+ {
+ LVM_INT16 GainStep;
+ LVM_INT16 FinalGain;
+ LVM_INT16 SampleToProcess = NumSamples;
+ LVM_INT16 *pOutPtr;
+
+ /* Large changes in Gain can cause clicks in output
+ Split data into small blocks and use interpolated gain values */
+
+ GainStep = (LVM_INT16)(((Gain-pInstance->CompressGain) * LVCS_COMPGAINFRAME)/NumSamples);
+
+ if((GainStep ==0)&&(pInstance->CompressGain < Gain))
+ {
+ GainStep=1;
+ }
+ else
+ {
+ if((GainStep ==0)&&(pInstance->CompressGain > Gain))
+ {
+ GainStep=-1;
+ }
+ }
+
+ FinalGain = Gain;
+ Gain = pInstance->CompressGain;
+ pOutPtr = pOutData;
+
+ while(SampleToProcess > 0)
+ {
+ Gain = (LVM_INT16)(Gain + GainStep);
+ if((GainStep > 0)&& (FinalGain <= Gain))
+ {
+ Gain = FinalGain;
+ GainStep =0;
+ }
+
+ if((GainStep < 0)&& (FinalGain > Gain))
+ {
+ Gain = FinalGain;
+ GainStep =0;
+ }
+
+ if(SampleToProcess > LVCS_COMPGAINFRAME)
+ {
+ NonLinComp_D16(Gain, /* Compressor gain setting */
+ pOutPtr,
+ pOutPtr,
+ (LVM_INT32)(2*LVCS_COMPGAINFRAME));
+ pOutPtr +=(2*LVCS_COMPGAINFRAME);
+ SampleToProcess = (LVM_INT16)(SampleToProcess-LVCS_COMPGAINFRAME);
+ }
+ else
+ {
+ NonLinComp_D16(Gain, /* Compressor gain setting */
+ pOutPtr,
+ pOutPtr,
+ (LVM_INT32)(2*SampleToProcess));
+
+ SampleToProcess = 0;
+ }
+
+ }
+ }
+
+ /* Store gain value*/
+ pInstance->CompressGain = Gain;
+ }
+
+
+ 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 100644
index 0000000..ee257b8
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.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.
+ */
+
+/************************************************************************************/
+/* */
+/* 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 100644
index 0000000..6e026ff
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
@@ -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.
+ */
+
+#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 100644
index 0000000..b9b8b05
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.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.
+ */
+
+/************************************************************************************/
+/* */
+/* 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 100644
index 0000000..15bc407
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
@@ -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.
+ */
+
+#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 100644
index 0000000..974de21
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
@@ -0,0 +1,448 @@
+/*
+ * 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.
+ */
+
+
+/************************************************************************************/
+/* */
+/* 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 100644
index 0000000..3f6c4c8
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.h
@@ -0,0 +1,152 @@
+/*
+ * 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_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..4313424
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Android.mk
@@ -0,0 +1,60 @@
+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_STATIC_LIBRARIES += libmusicbundle
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libdl
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/Bundle \
+ $(LOCAL_PATH)/../lib/Common/lib/ \
+ $(LOCAL_PATH)/../lib/Bundle/lib/ \
+ $(call include-path-for, audio-effects)
+
+
+include $(BUILD_SHARED_LIBRARY)
+
+# reverb wrapper
+include $(CLEAR_VARS)
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_SRC_FILES:= \
+ Reverb/EffectReverb.cpp
+
+LOCAL_MODULE:= libreverbwrapper
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+
+
+
+LOCAL_STATIC_LIBRARIES += libreverb
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libdl
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/Reverb \
+ $(LOCAL_PATH)/../lib/Common/lib/ \
+ $(LOCAL_PATH)/../lib/Reverb/lib/ \
+ $(call include-path-for, audio-effects)
+
+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..40dffd4
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -0,0 +1,3300 @@
+/*
+ * 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"
+
+
+// effect_handle_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){\
+ ALOGV("\tLVM_ERROR : Parameter error - "\
+ "null pointer returned by %s in %s\n\n\n\n", callingFunc, calledFunc);\
+ }\
+ if (LvmStatus == LVM_ALIGNMENTERROR){\
+ ALOGV("\tLVM_ERROR : Parameter error - "\
+ "bad alignment returned by %s in %s\n\n\n\n", callingFunc, calledFunc);\
+ }\
+ if (LvmStatus == LVM_INVALIDNUMSAMPLES){\
+ ALOGV("\tLVM_ERROR : Parameter error - "\
+ "bad number of samples returned by %s in %s\n\n\n\n", callingFunc, calledFunc);\
+ }\
+ if (LvmStatus == LVM_OUTOFRANGE){\
+ ALOGV("\tLVM_ERROR : Parameter error - "\
+ "out of range returned by %s in %s\n", callingFunc, calledFunc);\
+ }\
+ }
+
+
+static inline int16_t clamp16(int32_t sample)
+{
+ // check overflow for both positive and negative values:
+ // all bits above short range must me equal to sign bit
+ if ((sample>>15) ^ (sample>>31))
+ sample = 0x7FFF ^ (sample>>31);
+ return sample;
+}
+
+// Namespaces
+namespace android {
+namespace {
+
+// Flag to allow a one time init of global memory, only happens on first call ever
+int LvmInitFlag = LVM_FALSE;
+SessionContext GlobalSessionMemory[LVM_MAX_SESSIONS];
+int SessionIndex[LVM_MAX_SESSIONS];
+
+/* local functions */
+#define CHECK_ARG(cond) { \
+ if (!(cond)) { \
+ ALOGV("\tLVM_ERROR : Invalid argument: "#cond); \
+ return -EINVAL; \
+ } \
+}
+
+
+// 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_CONTROL_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_DEVICE_IND
+ | EFFECT_FLAG_VOLUME_CTRL),
+ BASS_BOOST_CUP_LOAD_ARM9E,
+ BUNDLE_MEM_USAGE,
+ "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_CONTROL_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_DEVICE_IND
+ | EFFECT_FLAG_VOLUME_CTRL),
+ VIRTUALIZER_CUP_LOAD_ARM9E,
+ BUNDLE_MEM_USAGE,
+ "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_CONTROL_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_VOLUME_CTRL),
+ EQUALIZER_CUP_LOAD_ARM9E,
+ BUNDLE_MEM_USAGE,
+ "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_CONTROL_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_VOLUME_CTRL),
+ VOLUME_CUP_LOAD_ARM9E,
+ BUNDLE_MEM_USAGE,
+ "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_setConfig (EffectContext *pContext, effect_config_t *pConfig);
+void Effect_getConfig (EffectContext *pContext, effect_config_t *pConfig);
+int BassBoost_setParameter (EffectContext *pContext, void *pParam, void *pValue);
+int BassBoost_getParameter (EffectContext *pContext,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue);
+int Virtualizer_setParameter (EffectContext *pContext, void *pParam, void *pValue);
+int Virtualizer_getParameter (EffectContext *pContext,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue);
+int Equalizer_setParameter (EffectContext *pContext, void *pParam, void *pValue);
+int Equalizer_getParameter (EffectContext *pContext,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue);
+int Volume_setParameter (EffectContext *pContext, void *pParam, void *pValue);
+int Volume_getParameter (EffectContext *pContext,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue);
+int Effect_setEnabled(EffectContext *pContext, bool enabled);
+
+/* Effect Library Interface Implementation */
+extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects){
+ ALOGV("\n\tEffectQueryNumberEffects start");
+ *pNumEffects = 4;
+ ALOGV("\tEffectQueryNumberEffects creating %d effects", *pNumEffects);
+ ALOGV("\tEffectQueryNumberEffects end\n");
+ return 0;
+} /* end EffectQueryNumberEffects */
+
+extern "C" int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor){
+ ALOGV("\n\tEffectQueryEffect start");
+ ALOGV("\tEffectQueryEffect processing index %d", index);
+
+ if (pDescriptor == NULL){
+ ALOGV("\tLVM_ERROR : EffectQueryEffect was passed NULL pointer");
+ return -EINVAL;
+ }
+ if (index > 3){
+ ALOGV("\tLVM_ERROR : EffectQueryEffect index out of range %d", index);
+ return -ENOENT;
+ }
+ if(index == LVM_BASS_BOOST){
+ ALOGV("\tEffectQueryEffect processing LVM_BASS_BOOST");
+ memcpy(pDescriptor, &gBassBoostDescriptor, sizeof(effect_descriptor_t));
+ }else if(index == LVM_VIRTUALIZER){
+ ALOGV("\tEffectQueryEffect processing LVM_VIRTUALIZER");
+ memcpy(pDescriptor, &gVirtualizerDescriptor, sizeof(effect_descriptor_t));
+ } else if(index == LVM_EQUALIZER){
+ ALOGV("\tEffectQueryEffect processing LVM_EQUALIZER");
+ memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t));
+ } else if(index == LVM_VOLUME){
+ ALOGV("\tEffectQueryEffect processing LVM_VOLUME");
+ memcpy(pDescriptor, &gVolumeDescriptor, sizeof(effect_descriptor_t));
+ }
+ ALOGV("\tEffectQueryEffect end\n");
+ return 0;
+} /* end EffectQueryEffect */
+
+extern "C" int EffectCreate(const effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_handle_t *pHandle){
+ int ret = 0;
+ int sessionNo;
+ int i;
+ EffectContext *pContext = NULL;
+ bool newBundle = false;
+ SessionContext *pSessionContext;
+
+ ALOGV("\n\tEffectCreate start session %d", sessionId);
+
+ if (pHandle == NULL || uuid == NULL){
+ ALOGV("\tLVM_ERROR : EffectCreate() called with NULL pointer");
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ if(LvmInitFlag == LVM_FALSE){
+ LvmInitFlag = LVM_TRUE;
+ ALOGV("\tEffectCreate - Initializing all global memory");
+ LvmGlobalBundle_init();
+ }
+
+ // Find next available sessionNo
+ for(i=0; i<LVM_MAX_SESSIONS; i++){
+ if((SessionIndex[i] == LVM_UNUSED_SESSION)||(SessionIndex[i] == sessionId)){
+ sessionNo = i;
+ SessionIndex[i] = sessionId;
+ ALOGV("\tEffectCreate: Allocating SessionNo %d for SessionId %d\n", sessionNo,sessionId);
+ break;
+ }
+ }
+
+ if(i==LVM_MAX_SESSIONS){
+ ALOGV("\tLVM_ERROR : Cannot find memory to allocate for current session");
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ pContext = new EffectContext;
+
+ // If this is the first create in this session
+ if(GlobalSessionMemory[sessionNo].bBundledEffectsEnabled == LVM_FALSE){
+ ALOGV("\tEffectCreate - This is the first effect in current sessionId %d sessionNo %d",
+ sessionId, sessionNo);
+
+ GlobalSessionMemory[sessionNo].bBundledEffectsEnabled = LVM_TRUE;
+ GlobalSessionMemory[sessionNo].pBundledContext = new BundledEffectContext;
+ newBundle = true;
+
+ pContext->pBundledContext = GlobalSessionMemory[sessionNo].pBundledContext;
+ pContext->pBundledContext->SessionNo = sessionNo;
+ pContext->pBundledContext->SessionId = 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->firstVolume = LVM_TRUE;
+
+ #ifdef LVM_PCM
+ char fileName[256];
+ snprintf(fileName, 256, "/data/tmp/bundle_%p_pcm_in.pcm", pContext->pBundledContext);
+ pContext->pBundledContext->PcmInPtr = fopen(fileName, "w");
+ if (pContext->pBundledContext->PcmInPtr == NULL) {
+ ALOGV("cannot open %s", fileName);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ snprintf(fileName, 256, "/data/tmp/bundle_%p_pcm_out.pcm", pContext->pBundledContext);
+ pContext->pBundledContext->PcmOutPtr = fopen(fileName, "w");
+ if (pContext->pBundledContext->PcmOutPtr == NULL) {
+ ALOGV("cannot open %s", fileName);
+ fclose(pContext->pBundledContext->PcmInPtr);
+ pContext->pBundledContext->PcmInPtr = NULL;
+ ret = -EINVAL;
+ goto exit;
+ }
+ #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;
+ pContext->pBundledContext->workBuffer = NULL;
+ pContext->pBundledContext->frameCount = -1;
+ pContext->pBundledContext->SamplesToExitCountVirt = 0;
+ pContext->pBundledContext->SamplesToExitCountBb = 0;
+ pContext->pBundledContext->SamplesToExitCountEq = 0;
+
+ ALOGV("\tEffectCreate - Calling LvmBundle_init");
+ ret = LvmBundle_init(pContext);
+
+ if (ret < 0){
+ ALOGV("\tLVM_ERROR : EffectCreate() Bundle init failed");
+ goto exit;
+ }
+ }
+ else{
+ ALOGV("\tEffectCreate - Assigning memory for previously created effect on sessionNo %d",
+ sessionNo);
+ pContext->pBundledContext =
+ GlobalSessionMemory[sessionNo].pBundledContext;
+ }
+ ALOGV("\tEffectCreate - pBundledContext is %p", pContext->pBundledContext);
+
+ pSessionContext = &GlobalSessionMemory[pContext->pBundledContext->SessionNo];
+
+ // Create each Effect
+ if (memcmp(uuid, &gBassBoostDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
+ // Create Bass Boost
+ ALOGV("\tEffectCreate - Effect to be created is LVM_BASS_BOOST");
+ pSessionContext->bBassInstantiated = LVM_TRUE;
+ pContext->pBundledContext->SamplesToExitCountBb = 0;
+
+ pContext->itfe = &gLvmEffectInterface;
+ pContext->EffectType = LVM_BASS_BOOST;
+ } else if (memcmp(uuid, &gVirtualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
+ // Create Virtualizer
+ ALOGV("\tEffectCreate - Effect to be created is LVM_VIRTUALIZER");
+ pSessionContext->bVirtualizerInstantiated=LVM_TRUE;
+ pContext->pBundledContext->SamplesToExitCountVirt = 0;
+
+ pContext->itfe = &gLvmEffectInterface;
+ pContext->EffectType = LVM_VIRTUALIZER;
+ } else if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
+ // Create Equalizer
+ ALOGV("\tEffectCreate - Effect to be created is LVM_EQUALIZER");
+ pSessionContext->bEqualizerInstantiated = LVM_TRUE;
+ pContext->pBundledContext->SamplesToExitCountEq = 0;
+
+ pContext->itfe = &gLvmEffectInterface;
+ pContext->EffectType = LVM_EQUALIZER;
+ } else if (memcmp(uuid, &gVolumeDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
+ // Create Volume
+ ALOGV("\tEffectCreate - Effect to be created is LVM_VOLUME");
+ pSessionContext->bVolumeInstantiated = LVM_TRUE;
+
+ pContext->itfe = &gLvmEffectInterface;
+ pContext->EffectType = LVM_VOLUME;
+ }
+ else{
+ ALOGV("\tLVM_ERROR : EffectCreate() invalid UUID");
+ ret = -EINVAL;
+ goto exit;
+ }
+
+exit:
+ if (ret != 0) {
+ if (pContext != NULL) {
+ if (newBundle) {
+ GlobalSessionMemory[sessionNo].bBundledEffectsEnabled = LVM_FALSE;
+ SessionIndex[sessionNo] = LVM_UNUSED_SESSION;
+ delete pContext->pBundledContext;
+ }
+ delete pContext;
+ }
+ *pHandle = (effect_handle_t)NULL;
+ } else {
+ *pHandle = (effect_handle_t)pContext;
+ }
+ ALOGV("\tEffectCreate end..\n\n");
+ return ret;
+} /* end EffectCreate */
+
+extern "C" int EffectRelease(effect_handle_t handle){
+ ALOGV("\n\tEffectRelease start %p", handle);
+ EffectContext * pContext = (EffectContext *)handle;
+
+ ALOGV("\tEffectRelease start handle: %p, context %p", handle, pContext->pBundledContext);
+ if (pContext == NULL){
+ ALOGV("\tLVM_ERROR : EffectRelease called with NULL pointer");
+ return -EINVAL;
+ }
+
+ SessionContext *pSessionContext = &GlobalSessionMemory[pContext->pBundledContext->SessionNo];
+
+ // Clear the instantiated flag for the effect
+ // protect agains the case where an effect is un-instantiated without being disabled
+ if(pContext->EffectType == LVM_BASS_BOOST) {
+ ALOGV("\tEffectRelease LVM_BASS_BOOST Clearing global intstantiated flag");
+ pSessionContext->bBassInstantiated = LVM_FALSE;
+ if(pContext->pBundledContext->SamplesToExitCountBb > 0){
+ pContext->pBundledContext->NumberEffectsEnabled--;
+ }
+ pContext->pBundledContext->SamplesToExitCountBb = 0;
+ } else if(pContext->EffectType == LVM_VIRTUALIZER) {
+ ALOGV("\tEffectRelease LVM_VIRTUALIZER Clearing global intstantiated flag");
+ pSessionContext->bVirtualizerInstantiated = LVM_FALSE;
+ if(pContext->pBundledContext->SamplesToExitCountVirt > 0){
+ pContext->pBundledContext->NumberEffectsEnabled--;
+ }
+ pContext->pBundledContext->SamplesToExitCountVirt = 0;
+ } else if(pContext->EffectType == LVM_EQUALIZER) {
+ ALOGV("\tEffectRelease LVM_EQUALIZER Clearing global intstantiated flag");
+ pSessionContext->bEqualizerInstantiated =LVM_FALSE;
+ if(pContext->pBundledContext->SamplesToExitCountEq > 0){
+ pContext->pBundledContext->NumberEffectsEnabled--;
+ }
+ pContext->pBundledContext->SamplesToExitCountEq = 0;
+ } else if(pContext->EffectType == LVM_VOLUME) {
+ ALOGV("\tEffectRelease LVM_VOLUME Clearing global intstantiated flag");
+ pSessionContext->bVolumeInstantiated = LVM_FALSE;
+ if (pContext->pBundledContext->bVolumeEnabled == LVM_TRUE){
+ pContext->pBundledContext->NumberEffectsEnabled--;
+ }
+ } else {
+ ALOGV("\tLVM_ERROR : EffectRelease : Unsupported effect\n\n\n\n\n\n\n");
+ }
+
+ // Disable effect, in this case ignore errors (return codes)
+ // if an effect has already been disabled
+ Effect_setEnabled(pContext, LVM_FALSE);
+
+ // if all effects are no longer instantiaed free the lvm memory and delete BundledEffectContext
+ if ((pSessionContext->bBassInstantiated == LVM_FALSE) &&
+ (pSessionContext->bVolumeInstantiated == LVM_FALSE) &&
+ (pSessionContext->bEqualizerInstantiated ==LVM_FALSE) &&
+ (pSessionContext->bVirtualizerInstantiated==LVM_FALSE))
+ {
+ #ifdef LVM_PCM
+ if (pContext->pBundledContext->PcmInPtr != NULL) {
+ fclose(pContext->pBundledContext->PcmInPtr);
+ pContext->pBundledContext->PcmInPtr = NULL;
+ }
+ if (pContext->pBundledContext->PcmOutPtr != NULL) {
+ fclose(pContext->pBundledContext->PcmOutPtr);
+ pContext->pBundledContext->PcmOutPtr = NULL;
+ }
+ #endif
+
+
+ // Clear the SessionIndex
+ for(int i=0; i<LVM_MAX_SESSIONS; i++){
+ if(SessionIndex[i] == pContext->pBundledContext->SessionId){
+ SessionIndex[i] = LVM_UNUSED_SESSION;
+ ALOGV("\tEffectRelease: Clearing SessionIndex SessionNo %d for SessionId %d\n",
+ i, pContext->pBundledContext->SessionId);
+ break;
+ }
+ }
+
+ ALOGV("\tEffectRelease: All effects are no longer instantiated\n");
+ pSessionContext->bBundledEffectsEnabled = LVM_FALSE;
+ pSessionContext->pBundledContext = LVM_NULL;
+ ALOGV("\tEffectRelease: Freeing LVM Bundle memory\n");
+ LvmEffect_free(pContext);
+ ALOGV("\tEffectRelease: Deleting LVM Bundle context %p\n", pContext->pBundledContext);
+ if (pContext->pBundledContext->workBuffer != NULL) {
+ free(pContext->pBundledContext->workBuffer);
+ }
+ delete pContext->pBundledContext;
+ pContext->pBundledContext = LVM_NULL;
+ }
+ // free the effect context for current effect
+ delete pContext;
+
+ ALOGV("\tEffectRelease end\n");
+ return 0;
+
+} /* end EffectRelease */
+
+extern "C" int EffectGetDescriptor(const effect_uuid_t *uuid,
+ effect_descriptor_t *pDescriptor) {
+ const effect_descriptor_t *desc = NULL;
+
+ if (pDescriptor == NULL || uuid == NULL){
+ ALOGV("EffectGetDescriptor() called with NULL pointer");
+ return -EINVAL;
+ }
+
+ if (memcmp(uuid, &gBassBoostDescriptor.uuid, sizeof(effect_uuid_t)) == 0) {
+ desc = &gBassBoostDescriptor;
+ } else if (memcmp(uuid, &gVirtualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0) {
+ desc = &gVirtualizerDescriptor;
+ } else if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0) {
+ desc = &gEqualizerDescriptor;
+ } else if (memcmp(uuid, &gVolumeDescriptor.uuid, sizeof(effect_uuid_t)) == 0) {
+ desc = &gVolumeDescriptor;
+ }
+
+ if (desc == NULL) {
+ return -EINVAL;
+ }
+
+ memcpy(pDescriptor, desc, sizeof(effect_descriptor_t));
+
+ return 0;
+} /* end EffectGetDescriptor */
+
+void LvmGlobalBundle_init(){
+ ALOGV("\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;
+
+ SessionIndex[i] = LVM_UNUSED_SESSION;
+ }
+ 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;
+
+ ALOGV("\tLvmBundle_init start");
+
+ pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+ pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ pContext->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ 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 = AUDIO_CHANNEL_OUT_STEREO;
+ pContext->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ 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){
+ ALOGV("\tLvmBundle_init pContext->pBassBoost != NULL "
+ "-> Calling pContext->pBassBoost->free()");
+
+ LvmEffect_free(pContext);
+
+ ALOGV("\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;
+
+ ALOGV("\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){
+ ALOGV("\tLVM_ERROR :LvmBundle_init CreateInstance Failed to allocate %ld bytes "
+ "for region %u\n", MemTab.Region[i].Size, i );
+ bMallocFailure = LVM_TRUE;
+ }else{
+ ALOGV("\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){
+ ALOGV("\tLVM_ERROR :LvmBundle_init CreateInstance Failed to allocate %ld bytes "
+ "for region %u Not freeing\n", MemTab.Region[i].Size, i );
+ }else{
+ ALOGV("\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;
+ }
+ ALOGV("\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;
+
+ ALOGV("\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_NONE;
+
+ /* 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;
+
+ /* TE Control parameters */
+ params.TE_OperatingMode = LVM_TE_OFF;
+ params.TE_EffectLevel = 0;
+
+ /* 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;
+
+ ALOGV("\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;
+
+ ALOGV("\tLvmBundle_init CreateInstance Succesfully called LVM_SetHeadroomParams\n");
+ ALOGV("\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){
+ if (pContext->pBundledContext->frameCount != frameCount) {
+ if (pContext->pBundledContext->workBuffer != NULL) {
+ free(pContext->pBundledContext->workBuffer);
+ }
+ pContext->pBundledContext->workBuffer =
+ (LVM_INT16 *)malloc(frameCount * sizeof(LVM_INT16) * 2);
+ pContext->pBundledContext->frameCount = frameCount;
+ }
+ pOutTmp = pContext->pBundledContext->workBuffer;
+ }else{
+ ALOGV("LVM_ERROR : LvmBundle_process invalid access mode");
+ return -EINVAL;
+ }
+
+ #ifdef LVM_PCM
+ fwrite(pIn, frameCount*sizeof(LVM_INT16)*2, 1, pContext->pBundledContext->PcmInPtr);
+ fflush(pContext->pBundledContext->PcmInPtr);
+ #endif
+
+ //ALOGV("Calling LVM_Process");
+
+ /* 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] = clamp16((LVM_INT32)pOut[i] + (LVM_INT32)pOutTmp[i]);
+ }
+ }
+ 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){
+ //ALOGV("\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;
+ //ALOGV("\tLvmEffect_enable Succesfully called LVM_GetControlParameters\n");
+
+ if(pContext->EffectType == LVM_BASS_BOOST) {
+ ALOGV("\tLvmEffect_enable : Enabling LVM_BASS_BOOST");
+ ActiveParams.BE_OperatingMode = LVM_BE_ON;
+ }
+ if(pContext->EffectType == LVM_VIRTUALIZER) {
+ ALOGV("\tLvmEffect_enable : Enabling LVM_VIRTUALIZER");
+ ActiveParams.VirtualizerOperatingMode = LVM_MODE_ON;
+ }
+ if(pContext->EffectType == LVM_EQUALIZER) {
+ ALOGV("\tLvmEffect_enable : Enabling LVM_EQUALIZER");
+ ActiveParams.EQNB_OperatingMode = LVM_EQNB_ON;
+ }
+ if(pContext->EffectType == LVM_VOLUME) {
+ ALOGV("\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;
+
+ //ALOGV("\tLvmEffect_enable Succesfully called LVM_SetControlParameters\n");
+ //ALOGV("\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){
+ //ALOGV("\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;
+ //ALOGV("\tLvmEffect_disable Succesfully called LVM_GetControlParameters\n");
+
+ if(pContext->EffectType == LVM_BASS_BOOST) {
+ ALOGV("\tLvmEffect_disable : Disabling LVM_BASS_BOOST");
+ ActiveParams.BE_OperatingMode = LVM_BE_OFF;
+ }
+ if(pContext->EffectType == LVM_VIRTUALIZER) {
+ ALOGV("\tLvmEffect_disable : Disabling LVM_VIRTUALIZER");
+ ActiveParams.VirtualizerOperatingMode = LVM_MODE_OFF;
+ }
+ if(pContext->EffectType == LVM_EQUALIZER) {
+ ALOGV("\tLvmEffect_disable : Disabling LVM_EQUALIZER");
+ ActiveParams.EQNB_OperatingMode = LVM_EQNB_OFF;
+ }
+ if(pContext->EffectType == LVM_VOLUME) {
+ ALOGV("\tLvmEffect_disable : Disabling LVM_VOLUME");
+ }
+
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmEffect_disable")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //ALOGV("\tLvmEffect_disable Succesfully called LVM_SetControlParameters\n");
+ //ALOGV("\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){
+ ALOGV("\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);
+
+ ALOGV("\tLvmEffect_free - END freeing %ld bytes for region %u at %p\n",
+ MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+ }else{
+ ALOGV("\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_setConfig()
+//----------------------------------------------------------------------------
+// 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_setConfig(EffectContext *pContext, effect_config_t *pConfig){
+ LVM_Fs_en SampleRate;
+ //ALOGV("\tEffect_setConfig 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 == AUDIO_CHANNEL_OUT_STEREO);
+ CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
+ || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
+ CHECK_ARG(pConfig->inputCfg.format == AUDIO_FORMAT_PCM_16_BIT);
+
+ memcpy(&pContext->config, pConfig, sizeof(effect_config_t));
+
+ switch (pConfig->inputCfg.samplingRate) {
+ case 8000:
+ SampleRate = LVM_FS_8000;
+ pContext->pBundledContext->SamplesPerSecond = 8000*2; // 2 secs Stereo
+ break;
+ case 16000:
+ SampleRate = LVM_FS_16000;
+ pContext->pBundledContext->SamplesPerSecond = 16000*2; // 2 secs Stereo
+ break;
+ case 22050:
+ SampleRate = LVM_FS_22050;
+ pContext->pBundledContext->SamplesPerSecond = 22050*2; // 2 secs Stereo
+ break;
+ case 32000:
+ SampleRate = LVM_FS_32000;
+ pContext->pBundledContext->SamplesPerSecond = 32000*2; // 2 secs Stereo
+ break;
+ case 44100:
+ SampleRate = LVM_FS_44100;
+ pContext->pBundledContext->SamplesPerSecond = 44100*2; // 2 secs Stereo
+ break;
+ case 48000:
+ SampleRate = LVM_FS_48000;
+ pContext->pBundledContext->SamplesPerSecond = 48000*2; // 2 secs Stereo
+ break;
+ default:
+ ALOGV("\tEffect_setConfig invalid sampling rate %d", pConfig->inputCfg.samplingRate);
+ return -EINVAL;
+ }
+
+ if(pContext->pBundledContext->SampleRate != SampleRate){
+
+ LVM_ControlParams_t ActiveParams;
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS;
+
+ ALOGV("\tEffect_setConfig change sampling rate to %d", SampleRate);
+
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+ &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "Effect_setConfig")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "Effect_setConfig")
+ ALOGV("\tEffect_setConfig Succesfully called LVM_SetControlParameters\n");
+ pContext->pBundledContext->SampleRate = SampleRate;
+
+ }else{
+ //ALOGV("\tEffect_setConfig keep sampling rate at %d", SampleRate);
+ }
+
+ //ALOGV("\tEffect_setConfig End....");
+ return 0;
+} /* end Effect_setConfig */
+
+//----------------------------------------------------------------------------
+// Effect_getConfig()
+//----------------------------------------------------------------------------
+// Purpose: Get input and output audio configuration.
+//
+// Inputs:
+// pContext: effect engine context
+// pConfig: pointer to effect_config_t structure holding input and output
+// configuration parameters
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+void Effect_getConfig(EffectContext *pContext, effect_config_t *pConfig)
+{
+ memcpy(pConfig, &pContext->config, sizeof(effect_config_t));
+} /* end Effect_getConfig */
+
+//----------------------------------------------------------------------------
+// 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){
+ //ALOGV("\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;
+
+ //ALOGV("\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)){
+ ALOGV("\tLVM_ERROR : BassGetStrength module strength does not match savedStrength %d %d\n",
+ ActiveParams.BE_EffectLevel, pContext->pBundledContext->BassStrengthSaved);
+ return -EINVAL;
+ }
+
+ //ALOGV("\tBassGetStrength() (0-15) -> %d\n", ActiveParams.BE_EffectLevel );
+ //ALOGV("\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){
+ //ALOGV("\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")
+ //ALOGV("\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;
+
+ //ALOGV("\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")
+ //ALOGV("\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){
+ //ALOGV("\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;
+
+ //ALOGV("\tVirtualizerGetStrength Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tVirtualizerGetStrength() (0-100) -> %d\n", ActiveParams.VirtualizerReverbLevel*10);
+ return pContext->pBundledContext->VirtStrengthSaved;
+} /* 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){
+ //ALOGV("\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")
+ //ALOGV("\tVirtualizerSetStrength Succesfully returned from LVM_GetControlParameters\n");
+
+ /* Virtualizer parameters */
+ ActiveParams.CS_EffectLevel = (int)((strength*32767)/1000);
+
+ //ALOGV("\tVirtualizerSetStrength() (0-1000) -> %d\n", strength );
+ //ALOGV("\tVirtualizerSetStrength() (0- 100) -> %d\n", ActiveParams.CS_EffectLevel );
+
+ /* Activate the initial settings */
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VirtualizerSetStrength")
+ //ALOGV("\tVirtualizerSetStrength Succesfully called LVM_SetControlParameters\n\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
+
+ //ALOGV("\tEqualizerGetBandLevel -> %d\n", Gain );
+ //ALOGV("\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, short Gain){
+ int gainRounded;
+ if(Gain > 0){
+ gainRounded = (int)((Gain+50)/100);
+ }else{
+ gainRounded = (int)((Gain-50)/100);
+ }
+ //ALOGV("\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")
+ //ALOGV("\tEqualizerSetBandLevel Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\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")
+ //ALOGV("\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
+
+ //ALOGV("\tEqualizerGetCentreFrequency -> %d\n", Frequency );
+ //ALOGV("\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){
+
+ //ALOGV("\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")
+ //ALOGV("\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")
+
+ //ALOGV("\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){
+ //ALOGV("\tEqualizerGetPresetName start(%d)", preset);
+ if (preset == PRESET_CUSTOM) {
+ return "Custom";
+ } else {
+ return gEqualizerPresets[preset].name;
+ }
+ //ALOGV("\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 */
+
+ //ALOGV("\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;
+ //ALOGV("\tVolumeSetVolumeLevel Succesfully returned from LVM_GetControlParameters got: %d\n",
+ //ActiveParams.VC_EffectLevel);
+
+ /* Volume parameters */
+ ActiveParams.VC_EffectLevel = (LVM_INT16)(level/100);
+ //ALOGV("\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;
+
+ //ALOGV("\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;
+
+ //ALOGV("\tVolumeSetVolumeLevel just set (-96dB -> 0dB) -> %d\n",ActiveParams.VC_EffectLevel );
+ if(pContext->pBundledContext->firstVolume == LVM_TRUE){
+ LvmStatus = LVM_SetVolumeNoSmoothing(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetVolumeNoSmoothing", "LvmBundle_process")
+ ALOGV("\tLVM_VOLUME: Disabling Smoothing for first volume change to remove spikes/clicks");
+ pContext->pBundledContext->firstVolume = LVM_FALSE;
+ }
+ return 0;
+} /* end VolumeSetVolumeLevel */
+
+//----------------------------------------------------------------------------
+// VolumeGetVolumeLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int VolumeGetVolumeLevel(EffectContext *pContext, int16_t *level){
+
+ //ALOGV("\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;
+
+ //ALOGV("\tVolumeGetVolumeLevel() (-96dB -> 0dB) -> %d\n", ActiveParams.VC_EffectLevel );
+ //ALOGV("\tVolumeGetVolumeLevel Succesfully returned from LVM_GetControlParameters\n");
+
+ *level = ActiveParams.VC_EffectLevel*100; // Convert dB to millibels
+ //ALOGV("\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){
+ //ALOGV("\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;
+
+ //ALOGV("\tVolumeSetMute Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\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;
+
+ //ALOGV("\tVolumeSetMute Succesfully called LVM_SetControlParameters\n");
+ //ALOGV("\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){
+ //ALOGV("\tVolumeGetMute start");
+ if((pContext->pBundledContext->bMuteEnabled == LVM_FALSE)||
+ (pContext->pBundledContext->bMuteEnabled == LVM_TRUE)){
+ *mute = pContext->pBundledContext->bMuteEnabled;
+ return 0;
+ }else{
+ ALOGV("\tLVM_ERROR : VolumeGetMute read an invalid value from context %d",
+ pContext->pBundledContext->bMuteEnabled);
+ return -EINVAL;
+ }
+ //ALOGV("\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);
+
+ //ALOGV("\tVolumeSetStereoPosition start pContext->pBundledContext->positionSaved = %d",
+ //pContext->pBundledContext->positionSaved);
+
+ if(pContext->pBundledContext->bStereoPositionEnabled == LVM_TRUE){
+
+ //ALOGV("\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;
+ //ALOGV("\tVolumeSetStereoPosition Succesfully returned from LVM_GetControlParameters got:"
+ // " %d\n", ActiveParams.VC_Balance);
+
+ /* Volume parameters */
+ ActiveParams.VC_Balance = Balance;
+ //ALOGV("\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;
+
+ //ALOGV("\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;
+ //ALOGV("\tVolumeSetStereoPosition Succesfully returned from LVM_GetControlParameters got: "
+ // "%d\n", ActiveParams.VC_Balance);
+ }
+ else{
+ //ALOGV("\tVolumeSetStereoPosition Position attempting to set, but not enabled %d %d\n",
+ //position, Balance);
+ }
+ //ALOGV("\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){
+ //ALOGV("\tVolumeGetStereoPosition start");
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
+ LVM_INT16 balance;
+
+ //ALOGV("\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;
+
+ //ALOGV("\tVolumeGetStereoPosition -> %d\n", ActiveParams.VC_Balance);
+ //ALOGV("\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
+ //ALOGV("\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){
+ //ALOGV("\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;
+
+ //ALOGV("\tVolumeEnableStereoPosition Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\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;
+
+ //ALOGV("\tVolumeEnableStereoPosition Succesfully called LVM_SetControlParameters\n");
+ //ALOGV("\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,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue){
+ int status = 0;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
+ int32_t param2;
+ char *name;
+
+ //ALOGV("\tBassBoost_getParameter start");
+
+ switch (param){
+ case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
+ if (*pValueSize != sizeof(uint32_t)){
+ ALOGV("\tLVM_ERROR : BassBoost_getParameter() invalid pValueSize1 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(uint32_t);
+ break;
+ case BASSBOOST_PARAM_STRENGTH:
+ if (*pValueSize != sizeof(int16_t)){
+ ALOGV("\tLVM_ERROR : BassBoost_getParameter() invalid pValueSize2 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+
+ default:
+ ALOGV("\tLVM_ERROR : BassBoost_getParameter() invalid param %d", param);
+ return -EINVAL;
+ }
+
+ switch (param){
+ case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
+ *(uint32_t *)pValue = 1;
+
+ //ALOGV("\tBassBoost_getParameter() BASSBOOST_PARAM_STRENGTH_SUPPORTED Value is %d",
+ // *(uint32_t *)pValue);
+ break;
+
+ case BASSBOOST_PARAM_STRENGTH:
+ *(int16_t *)pValue = BassGetStrength(pContext);
+
+ //ALOGV("\tBassBoost_getParameter() BASSBOOST_PARAM_STRENGTH Value is %d",
+ // *(int16_t *)pValue);
+ break;
+
+ default:
+ ALOGV("\tLVM_ERROR : BassBoost_getParameter() invalid param %d", param);
+ status = -EINVAL;
+ break;
+ }
+
+ //ALOGV("\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, void *pParam, void *pValue){
+ int status = 0;
+ int16_t strength;
+ int32_t *pParamTemp = (int32_t *)pParam;
+
+ //ALOGV("\tBassBoost_setParameter start");
+
+ switch (*pParamTemp){
+ case BASSBOOST_PARAM_STRENGTH:
+ strength = *(int16_t *)pValue;
+ //ALOGV("\tBassBoost_setParameter() BASSBOOST_PARAM_STRENGTH value is %d", strength);
+ //ALOGV("\tBassBoost_setParameter() Calling pBassBoost->BassSetStrength");
+ BassSetStrength(pContext, (int32_t)strength);
+ //ALOGV("\tBassBoost_setParameter() Called pBassBoost->BassSetStrength");
+ break;
+ default:
+ ALOGV("\tLVM_ERROR : BassBoost_setParameter() invalid param %d", *pParamTemp);
+ break;
+ }
+
+ //ALOGV("\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,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue){
+ int status = 0;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
+ int32_t param2;
+ char *name;
+
+ //ALOGV("\tVirtualizer_getParameter start");
+
+ switch (param){
+ case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED:
+ if (*pValueSize != sizeof(uint32_t)){
+ ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize %d",*pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(uint32_t);
+ break;
+ case VIRTUALIZER_PARAM_STRENGTH:
+ if (*pValueSize != sizeof(int16_t)){
+ ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize2 %d",*pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+
+ default:
+ ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid param %d", param);
+ return -EINVAL;
+ }
+
+ switch (param){
+ case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED:
+ *(uint32_t *)pValue = 1;
+
+ //ALOGV("\tVirtualizer_getParameter() VIRTUALIZER_PARAM_STRENGTH_SUPPORTED Value is %d",
+ // *(uint32_t *)pValue);
+ break;
+
+ case VIRTUALIZER_PARAM_STRENGTH:
+ *(int16_t *)pValue = VirtualizerGetStrength(pContext);
+
+ //ALOGV("\tVirtualizer_getParameter() VIRTUALIZER_PARAM_STRENGTH Value is %d",
+ // *(int16_t *)pValue);
+ break;
+
+ default:
+ ALOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid param %d", param);
+ status = -EINVAL;
+ break;
+ }
+
+ //ALOGV("\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, void *pParam, void *pValue){
+ int status = 0;
+ int16_t strength;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
+
+ //ALOGV("\tVirtualizer_setParameter start");
+
+ switch (param){
+ case VIRTUALIZER_PARAM_STRENGTH:
+ strength = *(int16_t *)pValue;
+ //ALOGV("\tVirtualizer_setParameter() VIRTUALIZER_PARAM_STRENGTH value is %d", strength);
+ //ALOGV("\tVirtualizer_setParameter() Calling pVirtualizer->setStrength");
+ VirtualizerSetStrength(pContext, (int32_t)strength);
+ //ALOGV("\tVirtualizer_setParameter() Called pVirtualizer->setStrength");
+ break;
+ default:
+ ALOGV("\tLVM_ERROR : Virtualizer_setParameter() invalid param %d", param);
+ break;
+ }
+
+ //ALOGV("\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,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue){
+ int status = 0;
+ int bMute = 0;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
+ int32_t param2;
+ char *name;
+
+ //ALOGV("\tEqualizer_getParameter start");
+
+ switch (param) {
+ case EQ_PARAM_NUM_BANDS:
+ case EQ_PARAM_CUR_PRESET:
+ case EQ_PARAM_GET_NUM_OF_PRESETS:
+ case EQ_PARAM_BAND_LEVEL:
+ case EQ_PARAM_GET_BAND:
+ if (*pValueSize < sizeof(int16_t)) {
+ ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 1 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+
+ case EQ_PARAM_LEVEL_RANGE:
+ if (*pValueSize < 2 * sizeof(int16_t)) {
+ ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 2 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = 2 * sizeof(int16_t);
+ break;
+ case EQ_PARAM_BAND_FREQ_RANGE:
+ if (*pValueSize < 2 * sizeof(int32_t)) {
+ ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 3 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = 2 * sizeof(int32_t);
+ break;
+
+ case EQ_PARAM_CENTER_FREQ:
+ if (*pValueSize < sizeof(int32_t)) {
+ ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 5 %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)) {
+ ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 1 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = (2 + FIVEBAND_NUMBANDS) * sizeof(uint16_t);
+ break;
+
+ default:
+ ALOGV("\tLVM_ERROR : Equalizer_getParameter unknown param %d", param);
+ return -EINVAL;
+ }
+
+ switch (param) {
+ case EQ_PARAM_NUM_BANDS:
+ *(uint16_t *)pValue = (uint16_t)FIVEBAND_NUMBANDS;
+ //ALOGV("\tEqualizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
+ break;
+
+ case EQ_PARAM_LEVEL_RANGE:
+ *(int16_t *)pValue = -1500;
+ *((int16_t *)pValue + 1) = 1500;
+ //ALOGV("\tEqualizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d",
+ // *(int16_t *)pValue, *((int16_t *)pValue + 1));
+ break;
+
+ case EQ_PARAM_BAND_LEVEL:
+ param2 = *pParamTemp;
+ if (param2 >= FIVEBAND_NUMBANDS) {
+ status = -EINVAL;
+ break;
+ }
+ *(int16_t *)pValue = (int16_t)EqualizerGetBandLevel(pContext, param2);
+ //ALOGV("\tEqualizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d",
+ // param2, *(int32_t *)pValue);
+ break;
+
+ case EQ_PARAM_CENTER_FREQ:
+ param2 = *pParamTemp;
+ if (param2 >= FIVEBAND_NUMBANDS) {
+ status = -EINVAL;
+ break;
+ }
+ *(int32_t *)pValue = EqualizerGetCentreFrequency(pContext, param2);
+ //ALOGV("\tEqualizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d",
+ // param2, *(int32_t *)pValue);
+ break;
+
+ case EQ_PARAM_BAND_FREQ_RANGE:
+ param2 = *pParamTemp;
+ if (param2 >= FIVEBAND_NUMBANDS) {
+ status = -EINVAL;
+ break;
+ }
+ EqualizerGetBandFreqRange(pContext, param2, (uint32_t *)pValue, ((uint32_t *)pValue + 1));
+ //ALOGV("\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 = *pParamTemp;
+ *(uint16_t *)pValue = (uint16_t)EqualizerGetBand(pContext, param2);
+ //ALOGV("\tEqualizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d",
+ // param2, *(uint16_t *)pValue);
+ break;
+
+ case EQ_PARAM_CUR_PRESET:
+ *(uint16_t *)pValue = (uint16_t)EqualizerGetPreset(pContext);
+ //ALOGV("\tEqualizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
+ break;
+
+ case EQ_PARAM_GET_NUM_OF_PRESETS:
+ *(uint16_t *)pValue = (uint16_t)EqualizerGetNumPresets();
+ //ALOGV("\tEqualizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
+ break;
+
+ case EQ_PARAM_GET_PRESET_NAME:
+ param2 = *pParamTemp;
+ 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;
+ //ALOGV("\tEqualizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d",
+ // param2, gEqualizerPresets[param2].name, *pValueSize);
+ break;
+
+ case EQ_PARAM_PROPERTIES: {
+ int16_t *p = (int16_t *)pValue;
+ ALOGV("\tEqualizer_getParameter() EQ_PARAM_PROPERTIES");
+ p[0] = (int16_t)EqualizerGetPreset(pContext);
+ p[1] = (int16_t)FIVEBAND_NUMBANDS;
+ for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
+ p[2 + i] = (int16_t)EqualizerGetBandLevel(pContext, i);
+ }
+ } break;
+
+ default:
+ ALOGV("\tLVM_ERROR : Equalizer_getParameter() invalid param %d", param);
+ status = -EINVAL;
+ break;
+ }
+
+ //GV("\tEqualizer_getParameter end\n");
+ 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, void *pParam, void *pValue){
+ int status = 0;
+ int32_t preset;
+ int32_t band;
+ int32_t level;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
+
+
+ //ALOGV("\tEqualizer_setParameter start");
+ switch (param) {
+ case EQ_PARAM_CUR_PRESET:
+ preset = (int32_t)(*(uint16_t *)pValue);
+
+ //ALOGV("\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 = *pParamTemp;
+ level = (int32_t)(*(int16_t *)pValue);
+ //ALOGV("\tEqualizer_setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
+ if (band >= FIVEBAND_NUMBANDS) {
+ status = -EINVAL;
+ break;
+ }
+ EqualizerSetBandLevel(pContext, band, level);
+ break;
+ case EQ_PARAM_PROPERTIES: {
+ //ALOGV("\tEqualizer_setParameter() EQ_PARAM_PROPERTIES");
+ int16_t *p = (int16_t *)pValue;
+ if ((int)p[0] >= EqualizerGetNumPresets()) {
+ status = -EINVAL;
+ break;
+ }
+ if (p[0] >= 0) {
+ EqualizerSetPreset(pContext, (int)p[0]);
+ } else {
+ if ((int)p[1] != FIVEBAND_NUMBANDS) {
+ status = -EINVAL;
+ break;
+ }
+ for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
+ EqualizerSetBandLevel(pContext, i, (int)p[2 + i]);
+ }
+ }
+ } break;
+ default:
+ ALOGV("\tLVM_ERROR : Equalizer_setParameter() invalid param %d", param);
+ status = -EINVAL;
+ break;
+ }
+
+ //ALOGV("\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,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue){
+ int status = 0;
+ int bMute = 0;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;;
+ char *name;
+
+ //ALOGV("\tVolume_getParameter start");
+
+ switch (param){
+ case VOLUME_PARAM_LEVEL:
+ case VOLUME_PARAM_MAXLEVEL:
+ case VOLUME_PARAM_STEREOPOSITION:
+ if (*pValueSize != sizeof(int16_t)){
+ ALOGV("\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)){
+ ALOGV("\tLVM_ERROR : Volume_getParameter() invalid pValueSize 2 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int32_t);
+ break;
+
+ default:
+ ALOGV("\tLVM_ERROR : Volume_getParameter unknown param %d", param);
+ return -EINVAL;
+ }
+
+ switch (param){
+ case VOLUME_PARAM_LEVEL:
+ status = VolumeGetVolumeLevel(pContext, (int16_t *)(pValue));
+ //ALOGV("\tVolume_getParameter() VOLUME_PARAM_LEVEL Value is %d",
+ // *(int16_t *)pValue);
+ break;
+
+ case VOLUME_PARAM_MAXLEVEL:
+ *(int16_t *)pValue = 0;
+ //ALOGV("\tVolume_getParameter() VOLUME_PARAM_MAXLEVEL Value is %d",
+ // *(int16_t *)pValue);
+ break;
+
+ case VOLUME_PARAM_STEREOPOSITION:
+ VolumeGetStereoPosition(pContext, (int16_t *)pValue);
+ //ALOGV("\tVolume_getParameter() VOLUME_PARAM_STEREOPOSITION Value is %d",
+ // *(int16_t *)pValue);
+ break;
+
+ case VOLUME_PARAM_MUTE:
+ status = VolumeGetMute(pContext, (uint32_t *)pValue);
+ ALOGV("\tVolume_getParameter() VOLUME_PARAM_MUTE Value is %d",
+ *(uint32_t *)pValue);
+ break;
+
+ case VOLUME_PARAM_ENABLESTEREOPOSITION:
+ *(int32_t *)pValue = pContext->pBundledContext->bStereoPositionEnabled;
+ //ALOGV("\tVolume_getParameter() VOLUME_PARAM_ENABLESTEREOPOSITION Value is %d",
+ // *(uint32_t *)pValue);
+ break;
+
+ default:
+ ALOGV("\tLVM_ERROR : Volume_getParameter() invalid param %d", param);
+ status = -EINVAL;
+ break;
+ }
+
+ //ALOGV("\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, void *pParam, void *pValue){
+ int status = 0;
+ int16_t level;
+ int16_t position;
+ uint32_t mute;
+ uint32_t positionEnabled;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
+
+ //ALOGV("\tVolume_setParameter start");
+
+ switch (param){
+ case VOLUME_PARAM_LEVEL:
+ level = *(int16_t *)pValue;
+ //ALOGV("\tVolume_setParameter() VOLUME_PARAM_LEVEL value is %d", level);
+ //ALOGV("\tVolume_setParameter() Calling pVolume->setVolumeLevel");
+ status = VolumeSetVolumeLevel(pContext, (int16_t)level);
+ //ALOGV("\tVolume_setParameter() Called pVolume->setVolumeLevel");
+ break;
+
+ case VOLUME_PARAM_MUTE:
+ mute = *(uint32_t *)pValue;
+ //ALOGV("\tVolume_setParameter() Calling pVolume->setMute, mute is %d", mute);
+ //ALOGV("\tVolume_setParameter() Calling pVolume->setMute");
+ status = VolumeSetMute(pContext, mute);
+ //ALOGV("\tVolume_setParameter() Called pVolume->setMute");
+ break;
+
+ case VOLUME_PARAM_ENABLESTEREOPOSITION:
+ positionEnabled = *(uint32_t *)pValue;
+ status = VolumeEnableStereoPosition(pContext, positionEnabled);
+ status = VolumeSetStereoPosition(pContext, pContext->pBundledContext->positionSaved);
+ //ALOGV("\tVolume_setParameter() VOLUME_PARAM_ENABLESTEREOPOSITION called");
+ break;
+
+ case VOLUME_PARAM_STEREOPOSITION:
+ position = *(int16_t *)pValue;
+ //ALOGV("\tVolume_setParameter() VOLUME_PARAM_STEREOPOSITION value is %d", position);
+ //ALOGV("\tVolume_setParameter() Calling pVolume->VolumeSetStereoPosition");
+ status = VolumeSetStereoPosition(pContext, (int16_t)position);
+ //ALOGV("\tVolume_setParameter() Called pVolume->VolumeSetStereoPosition");
+ break;
+
+ default:
+ ALOGV("\tLVM_ERROR : Volume_setParameter() invalid param %d", param);
+ break;
+ }
+
+ //ALOGV("\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;
+}
+
+//----------------------------------------------------------------------------
+// Effect_setEnabled()
+//----------------------------------------------------------------------------
+// Purpose:
+// Enable or disable effect
+//
+// Inputs:
+// pContext - pointer to effect context
+// enabled - true if enabling the effect, false otherwise
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Effect_setEnabled(EffectContext *pContext, bool enabled)
+{
+ ALOGV("\tEffect_setEnabled() type %d, enabled %d", pContext->EffectType, enabled);
+
+ if (enabled) {
+ // Bass boost or Virtualizer can be temporarily disabled if playing over device speaker due
+ // to their nature.
+ bool tempDisabled = false;
+ switch (pContext->EffectType) {
+ case LVM_BASS_BOOST:
+ if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
+ ALOGV("\tEffect_setEnabled() LVM_BASS_BOOST is already enabled");
+ return -EINVAL;
+ }
+ if(pContext->pBundledContext->SamplesToExitCountBb <= 0){
+ pContext->pBundledContext->NumberEffectsEnabled++;
+ }
+ pContext->pBundledContext->SamplesToExitCountBb =
+ (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
+ pContext->pBundledContext->bBassEnabled = LVM_TRUE;
+ tempDisabled = pContext->pBundledContext->bBassTempDisabled;
+ break;
+ case LVM_EQUALIZER:
+ if (pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE) {
+ ALOGV("\tEffect_setEnabled() LVM_EQUALIZER is already enabled");
+ return -EINVAL;
+ }
+ if(pContext->pBundledContext->SamplesToExitCountEq <= 0){
+ pContext->pBundledContext->NumberEffectsEnabled++;
+ }
+ pContext->pBundledContext->SamplesToExitCountEq =
+ (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
+ pContext->pBundledContext->bEqualizerEnabled = LVM_TRUE;
+ break;
+ case LVM_VIRTUALIZER:
+ if (pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE) {
+ ALOGV("\tEffect_setEnabled() LVM_VIRTUALIZER is already enabled");
+ return -EINVAL;
+ }
+ if(pContext->pBundledContext->SamplesToExitCountVirt <= 0){
+ pContext->pBundledContext->NumberEffectsEnabled++;
+ }
+ pContext->pBundledContext->SamplesToExitCountVirt =
+ (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
+ pContext->pBundledContext->bVirtualizerEnabled = LVM_TRUE;
+ tempDisabled = pContext->pBundledContext->bVirtualizerTempDisabled;
+ break;
+ case LVM_VOLUME:
+ if (pContext->pBundledContext->bVolumeEnabled == LVM_TRUE) {
+ ALOGV("\tEffect_setEnabled() LVM_VOLUME is already enabled");
+ return -EINVAL;
+ }
+ pContext->pBundledContext->NumberEffectsEnabled++;
+ pContext->pBundledContext->bVolumeEnabled = LVM_TRUE;
+ break;
+ default:
+ ALOGV("\tEffect_setEnabled() invalid effect type");
+ return -EINVAL;
+ }
+ if (!tempDisabled) {
+ LvmEffect_enable(pContext);
+ }
+ } else {
+ switch (pContext->EffectType) {
+ case LVM_BASS_BOOST:
+ if (pContext->pBundledContext->bBassEnabled == LVM_FALSE) {
+ ALOGV("\tEffect_setEnabled() LVM_BASS_BOOST is already disabled");
+ return -EINVAL;
+ }
+ pContext->pBundledContext->bBassEnabled = LVM_FALSE;
+ break;
+ case LVM_EQUALIZER:
+ if (pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE) {
+ ALOGV("\tEffect_setEnabled() LVM_EQUALIZER is already disabled");
+ return -EINVAL;
+ }
+ pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE;
+ break;
+ case LVM_VIRTUALIZER:
+ if (pContext->pBundledContext->bVirtualizerEnabled == LVM_FALSE) {
+ ALOGV("\tEffect_setEnabled() LVM_VIRTUALIZER is already disabled");
+ return -EINVAL;
+ }
+ pContext->pBundledContext->bVirtualizerEnabled = LVM_FALSE;
+ break;
+ case LVM_VOLUME:
+ if (pContext->pBundledContext->bVolumeEnabled == LVM_FALSE) {
+ ALOGV("\tEffect_setEnabled() LVM_VOLUME is already disabled");
+ return -EINVAL;
+ }
+ pContext->pBundledContext->bVolumeEnabled = LVM_FALSE;
+ break;
+ default:
+ ALOGV("\tEffect_setEnabled() invalid effect type");
+ return -EINVAL;
+ }
+ LvmEffect_disable(pContext);
+ }
+
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// LVC_Convert_VolToDb()
+//----------------------------------------------------------------------------
+// Purpose:
+// Convery volume in Q24 to dB
+//
+// Inputs:
+// vol: Q.24 volume dB
+//
+//-----------------------------------------------------------------------
+
+int16_t LVC_Convert_VolToDb(uint32_t vol){
+ int16_t dB;
+
+ dB = LVC_ToDB_s32Tos16(vol <<7);
+ dB = (dB +8)>>4;
+ dB = (dB <-96) ? -96 : dB ;
+
+ return dB;
+}
+
+} // namespace
+} // namespace
+
+extern "C" {
+/* Effect Control Interface Implementation: Process */
+int Effect_process(effect_handle_t self,
+ audio_buffer_t *inBuffer,
+ audio_buffer_t *outBuffer){
+ EffectContext * pContext = (EffectContext *) self;
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
+ int status = 0;
+ int lvmStatus = 0;
+ LVM_INT16 *in = (LVM_INT16 *)inBuffer->raw;
+ LVM_INT16 *out = (LVM_INT16 *)outBuffer->raw;
+
+//ALOGV("\tEffect_process Start : Enabled = %d Called = %d (%8d %8d %8d)",
+//pContext->pBundledContext->NumberEffectsEnabled,pContext->pBundledContext->NumberEffectsCalled,
+// pContext->pBundledContext->SamplesToExitCountBb,
+// pContext->pBundledContext->SamplesToExitCountVirt,
+// pContext->pBundledContext->SamplesToExitCountEq);
+
+ if (pContext == NULL){
+ ALOGV("\tLVM_ERROR : Effect_process() ERROR pContext == NULL");
+ return -EINVAL;
+ }
+
+ //if(pContext->EffectType == LVM_BASS_BOOST){
+ // ALOGV("\tEffect_process: Effect type is BASS_BOOST");
+ //}else if(pContext->EffectType == LVM_EQUALIZER){
+ // ALOGV("\tEffect_process: Effect type is LVM_EQUALIZER");
+ //}else if(pContext->EffectType == LVM_VIRTUALIZER){
+ // ALOGV("\tEffect_process: Effect type is LVM_VIRTUALIZER");
+ //}
+
+ if (inBuffer == NULL || inBuffer->raw == NULL ||
+ outBuffer == NULL || outBuffer->raw == NULL ||
+ inBuffer->frameCount != outBuffer->frameCount){
+ ALOGV("\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)){
+ //ALOGV("\tEffect_process() LVM_BASS_BOOST Effect is not enabled");
+ if(pContext->pBundledContext->SamplesToExitCountBb > 0){
+ pContext->pBundledContext->SamplesToExitCountBb -= outBuffer->frameCount * 2; // STEREO
+ //ALOGV("\tEffect_process: Waiting to turn off BASS_BOOST, %d samples left",
+ // pContext->pBundledContext->SamplesToExitCountBb);
+ }
+ if(pContext->pBundledContext->SamplesToExitCountBb <= 0) {
+ status = -ENODATA;
+ pContext->pBundledContext->NumberEffectsEnabled--;
+ ALOGV("\tEffect_process() this is the last frame for LVM_BASS_BOOST");
+ }
+ }
+ if ((pContext->pBundledContext->bVolumeEnabled == LVM_FALSE)&&
+ (pContext->EffectType == LVM_VOLUME)){
+ //ALOGV("\tEffect_process() LVM_VOLUME Effect is not enabled");
+ status = -ENODATA;
+ pContext->pBundledContext->NumberEffectsEnabled--;
+ }
+ if ((pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE)&&
+ (pContext->EffectType == LVM_EQUALIZER)){
+ //ALOGV("\tEffect_process() LVM_EQUALIZER Effect is not enabled");
+ if(pContext->pBundledContext->SamplesToExitCountEq > 0){
+ pContext->pBundledContext->SamplesToExitCountEq -= outBuffer->frameCount * 2; // STEREO
+ //ALOGV("\tEffect_process: Waiting to turn off EQUALIZER, %d samples left",
+ // pContext->pBundledContext->SamplesToExitCountEq);
+ }
+ if(pContext->pBundledContext->SamplesToExitCountEq <= 0) {
+ status = -ENODATA;
+ pContext->pBundledContext->NumberEffectsEnabled--;
+ ALOGV("\tEffect_process() this is the last frame for LVM_EQUALIZER");
+ }
+ }
+ if ((pContext->pBundledContext->bVirtualizerEnabled == LVM_FALSE)&&
+ (pContext->EffectType == LVM_VIRTUALIZER)){
+ //ALOGV("\tEffect_process() LVM_VIRTUALIZER Effect is not enabled");
+ if(pContext->pBundledContext->SamplesToExitCountVirt > 0){
+ pContext->pBundledContext->SamplesToExitCountVirt -= outBuffer->frameCount * 2;// STEREO
+ //ALOGV("\tEffect_process: Waiting for to turn off VIRTUALIZER, %d samples left",
+ // pContext->pBundledContext->SamplesToExitCountVirt);
+ }
+ if(pContext->pBundledContext->SamplesToExitCountVirt <= 0) {
+ status = -ENODATA;
+ pContext->pBundledContext->NumberEffectsEnabled--;
+ ALOGV("\tEffect_process() this is the last frame for LVM_VIRTUALIZER");
+ }
+ }
+
+ if(status != -ENODATA){
+ pContext->pBundledContext->NumberEffectsCalled++;
+ }
+
+ if(pContext->pBundledContext->NumberEffectsCalled ==
+ pContext->pBundledContext->NumberEffectsEnabled){
+ //ALOGV("\tEffect_process Calling process with %d effects enabled, %d called: Effect %d",
+ //pContext->pBundledContext->NumberEffectsEnabled,
+ //pContext->pBundledContext->NumberEffectsCalled, pContext->EffectType);
+
+ if(status == -ENODATA){
+ ALOGV("\tEffect_process() 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){
+ ALOGV("\tLVM_ERROR : LvmBundle_process returned error %d", lvmStatus);
+ return lvmStatus;
+ }
+ } else {
+ //ALOGV("\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
+ if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+ for (size_t i=0; i < outBuffer->frameCount*2; i++){
+ outBuffer->s16[i] =
+ clamp16((LVM_INT32)outBuffer->s16[i] + (LVM_INT32)inBuffer->s16[i]);
+ }
+ } else {
+ memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount*sizeof(LVM_INT16)*2);
+ }
+ }
+
+ return status;
+} /* end Effect_process */
+
+/* Effect Control Interface Implementation: Command */
+int Effect_command(effect_handle_t self,
+ uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData){
+ EffectContext * pContext = (EffectContext *) self;
+ int retsize;
+
+ //ALOGV("\t\nEffect_command start");
+
+ if(pContext->EffectType == LVM_BASS_BOOST){
+ //ALOGV("\tEffect_command setting command for LVM_BASS_BOOST");
+ }
+ if(pContext->EffectType == LVM_VIRTUALIZER){
+ //ALOGV("\tEffect_command setting command for LVM_VIRTUALIZER");
+ }
+ if(pContext->EffectType == LVM_EQUALIZER){
+ //ALOGV("\tEffect_command setting command for LVM_EQUALIZER");
+ }
+ if(pContext->EffectType == LVM_VOLUME){
+ //ALOGV("\tEffect_command setting command for LVM_VOLUME");
+ }
+
+ if (pContext == NULL){
+ ALOGV("\tLVM_ERROR : Effect_command ERROR pContext == NULL");
+ return -EINVAL;
+ }
+
+ //ALOGV("\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;
+
+ //ALOGV("\tEffect_command NumberEffectsCalled = %d, NumberEffectsEnabled = %d",
+ // pContext->pBundledContext->NumberEffectsCalled,
+ // pContext->pBundledContext->NumberEffectsEnabled);
+
+ switch (cmdCode){
+ case EFFECT_CMD_INIT:
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ ALOGV("\tLVM_ERROR, EFFECT_CMD_INIT: ERROR for effect type %d",
+ pContext->EffectType);
+ return -EINVAL;
+ }
+ *(int *) pReplyData = 0;
+ //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_INIT start");
+ if(pContext->EffectType == LVM_BASS_BOOST){
+ //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_INIT for LVM_BASS_BOOST");
+ android::BassSetStrength(pContext, 0);
+ }
+ if(pContext->EffectType == LVM_VIRTUALIZER){
+ //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_INIT for LVM_VIRTUALIZER");
+ android::VirtualizerSetStrength(pContext, 0);
+ }
+ if(pContext->EffectType == LVM_EQUALIZER){
+ //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_INIT for LVM_EQUALIZER");
+ android::EqualizerSetPreset(pContext, 0);
+ }
+ if(pContext->EffectType == LVM_VOLUME){
+ //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_INIT for LVM_VOLUME");
+ *(int *) pReplyData = android::VolumeSetVolumeLevel(pContext, 0);
+ }
+ break;
+
+ case EFFECT_CMD_SET_CONFIG:
+ //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_CONFIG start");
+ if (pCmdData == NULL||
+ cmdSize != sizeof(effect_config_t)||
+ pReplyData == NULL||
+ *replySize != sizeof(int)){
+ ALOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
+ "EFFECT_CMD_SET_CONFIG: ERROR");
+ return -EINVAL;
+ }
+ *(int *) pReplyData = android::Effect_setConfig(pContext, (effect_config_t *) pCmdData);
+ //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_CONFIG end");
+ break;
+
+ case EFFECT_CMD_GET_CONFIG:
+ if (pReplyData == NULL ||
+ *replySize != sizeof(effect_config_t)) {
+ ALOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
+ "EFFECT_CMD_GET_CONFIG: ERROR");
+ return -EINVAL;
+ }
+
+ android::Effect_getConfig(pContext, (effect_config_t *)pReplyData);
+ break;
+
+ case EFFECT_CMD_RESET:
+ //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_RESET start");
+ android::Effect_setConfig(pContext, &pContext->config);
+ //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_RESET end");
+ break;
+
+ case EFFECT_CMD_GET_PARAM:{
+ //ALOGV("\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))){
+ ALOGV("\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,
+ p->data,
+ (size_t *)&p->vsize,
+ p->data + voffset);
+
+ *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+ //ALOGV("\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))){
+ ALOGV("\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,
+ (void *)p->data,
+ (size_t *)&p->vsize,
+ p->data + voffset);
+
+ *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+ //ALOGV("\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){
+ //ALOGV("\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))) {
+ ALOGV("\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,
+ p->data,
+ &p->vsize,
+ p->data + voffset);
+
+ *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+ //ALOGV("\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){
+ //ALOGV("\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))){
+ ALOGV("\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,
+ (void *)p->data,
+ (size_t *)&p->vsize,
+ p->data + voffset);
+
+ *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+ //ALOGV("\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));
+ }
+ //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_GET_PARAM end");
+ } break;
+ case EFFECT_CMD_SET_PARAM:{
+ //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_PARAM start");
+ if(pContext->EffectType == LVM_BASS_BOOST){
+ //ALOGV("\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)){
+ ALOGV("\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)){
+ ALOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
+ return -EINVAL;
+ }
+
+ //ALOGV("\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,
+ (void *)p->data,
+ p->data + p->psize);
+ }
+ if(pContext->EffectType == LVM_VIRTUALIZER){
+ //ALOGV("\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)){
+ ALOGV("\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)){
+ ALOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
+ return -EINVAL;
+ }
+
+ //ALOGV("\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,
+ (void *)p->data,
+ p->data + p->psize);
+ }
+ if(pContext->EffectType == LVM_EQUALIZER){
+ //ALOGV("\tEqualizer_command cmdCode Case: "
+ // "EFFECT_CMD_SET_PARAM start");
+ //ALOGV("\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)) {
+ ALOGV("\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,
+ (void *)p->data,
+ p->data + p->psize);
+ }
+ if(pContext->EffectType == LVM_VOLUME){
+ //ALOGV("\tVolume_command cmdCode Case: EFFECT_CMD_SET_PARAM start");
+ //ALOGV("\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)){
+ ALOGV("\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,
+ (void *)p->data,
+ p->data + p->psize);
+ }
+ //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_PARAM end");
+ } break;
+
+ case EFFECT_CMD_ENABLE:
+ ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE start");
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ ALOGV("\tLVM_ERROR : Effect_command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
+ return -EINVAL;
+ }
+
+ *(int *)pReplyData = android::Effect_setEnabled(pContext, LVM_TRUE);
+ break;
+
+ case EFFECT_CMD_DISABLE:
+ //ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_DISABLE start");
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ ALOGV("\tLVM_ERROR : Effect_command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
+ return -EINVAL;
+ }
+ *(int *)pReplyData = android::Effect_setEnabled(pContext, LVM_FALSE);
+ break;
+
+ case EFFECT_CMD_SET_DEVICE:
+ {
+ ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_DEVICE start");
+ uint32_t device = *(uint32_t *)pCmdData;
+
+ if (pContext->EffectType == LVM_BASS_BOOST) {
+ if((device == AUDIO_DEVICE_OUT_SPEAKER) ||
+ (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) ||
+ (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)){
+ ALOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_BASS_BOOST %d",
+ *(int32_t *)pCmdData);
+ ALOGV("\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) {
+ ALOGV("\tEFFECT_CMD_SET_DEVICE disable LVM_BASS_BOOST %d",
+ *(int32_t *)pCmdData);
+ android::LvmEffect_disable(pContext);
+ }
+ pContext->pBundledContext->bBassTempDisabled = LVM_TRUE;
+ } else {
+ ALOGV("\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->bBassEnabled == LVM_TRUE) {
+ ALOGV("\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 == AUDIO_DEVICE_OUT_SPEAKER)||
+ (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT)||
+ (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)){
+ ALOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_VIRTUALIZER %d",
+ *(int32_t *)pCmdData);
+ ALOGV("\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) {
+ ALOGV("\tEFFECT_CMD_SET_DEVICE disable LVM_VIRTUALIZER %d",
+ *(int32_t *)pCmdData);
+ android::LvmEffect_disable(pContext);
+ }
+ pContext->pBundledContext->bVirtualizerTempDisabled = LVM_TRUE;
+ } else {
+ ALOGV("\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->bVirtualizerEnabled == LVM_TRUE){
+ ALOGV("\tEFFECT_CMD_SET_DEVICE re-enable LVM_VIRTUALIZER %d",
+ *(int32_t *)pCmdData);
+ android::LvmEffect_enable(pContext);
+ }
+ pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
+ }
+ }
+ ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_DEVICE end");
+ break;
+ }
+ case EFFECT_CMD_SET_VOLUME:
+ {
+ uint32_t leftVolume, rightVolume;
+ int16_t leftdB, rightdB;
+ int16_t maxdB, pandB;
+ int32_t vol_ret[2] = {1<<24,1<<24}; // Apply no volume
+ int status = 0;
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
+
+ // if pReplyData is NULL, VOL_CTRL is delegated to another effect
+ if(pReplyData == LVM_NULL){
+ break;
+ }
+
+ if (pCmdData == NULL ||
+ cmdSize != 2 * sizeof(uint32_t)) {
+ ALOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
+ "EFFECT_CMD_SET_VOLUME: ERROR");
+ return -EINVAL;
+ }
+
+ leftVolume = ((*(uint32_t *)pCmdData));
+ rightVolume = ((*((uint32_t *)pCmdData + 1)));
+
+ if(leftVolume == 0x1000000){
+ leftVolume -= 1;
+ }
+ if(rightVolume == 0x1000000){
+ rightVolume -= 1;
+ }
+
+ // Convert volume to dB
+ leftdB = android::LVC_Convert_VolToDb(leftVolume);
+ rightdB = android::LVC_Convert_VolToDb(rightVolume);
+
+ pandB = rightdB - leftdB;
+
+ // Calculate max volume in dB
+ maxdB = leftdB;
+ if(rightdB > maxdB){
+ maxdB = rightdB;
+ }
+ //ALOGV("\tEFFECT_CMD_SET_VOLUME Session: %d, SessionID: %d VOLUME is %d dB (%d), "
+ // "effect is %d",
+ //pContext->pBundledContext->SessionNo, pContext->pBundledContext->SessionId,
+ //(int32_t)maxdB, maxVol<<7, pContext->EffectType);
+ //ALOGV("\tEFFECT_CMD_SET_VOLUME: Left is %d, Right is %d", leftVolume, rightVolume);
+ //ALOGV("\tEFFECT_CMD_SET_VOLUME: Left %ddB, Right %ddB, Position %ddB",
+ // leftdB, rightdB, pandB);
+
+ memcpy(pReplyData, vol_ret, sizeof(int32_t)*2);
+ android::VolumeSetVolumeLevel(pContext, (int16_t)(maxdB*100));
+
+ /* Get the current settings */
+ LvmStatus =LVM_GetControlParameters(pContext->pBundledContext->hInstance,&ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetStereoPosition")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ /* Volume parameters */
+ ActiveParams.VC_Balance = pandB;
+ ALOGV("\t\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;
+ break;
+ }
+ case EFFECT_CMD_SET_AUDIO_MODE:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ //ALOGV("\tEffect_command end...\n\n");
+ return 0;
+} /* end Effect_command */
+
+/* Effect Control Interface Implementation: get_descriptor */
+int Effect_getDescriptor(effect_handle_t self,
+ effect_descriptor_t *pDescriptor)
+{
+ EffectContext * pContext = (EffectContext *) self;
+ const effect_descriptor_t *desc;
+
+ if (pContext == NULL || pDescriptor == NULL) {
+ ALOGV("Effect_getDescriptor() invalid param");
+ return -EINVAL;
+ }
+
+ switch(pContext->EffectType) {
+ case LVM_BASS_BOOST:
+ desc = &android::gBassBoostDescriptor;
+ break;
+ case LVM_VIRTUALIZER:
+ desc = &android::gVirtualizerDescriptor;
+ break;
+ case LVM_EQUALIZER:
+ desc = &android::gEqualizerDescriptor;
+ break;
+ case LVM_VOLUME:
+ desc = &android::gVolumeDescriptor;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ memcpy(pDescriptor, desc, sizeof(effect_descriptor_t));
+
+ return 0;
+} /* end Effect_getDescriptor */
+
+// effect_handle_t interface implementation for effect
+const struct effect_interface_s gLvmEffectInterface = {
+ Effect_process,
+ Effect_command,
+ Effect_getDescriptor,
+ NULL,
+}; /* end gLvmEffectInterface */
+
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
+ tag : AUDIO_EFFECT_LIBRARY_TAG,
+ version : EFFECT_LIBRARY_API_VERSION,
+ name : "Effect Bundle Library",
+ implementor : "NXP Software Ltd.",
+ query_num_effects : android::EffectQueryNumberEffects,
+ query_effect : android::EffectQueryEffect,
+ create_effect : android::EffectCreate,
+ release_effect : android::EffectRelease,
+ get_descriptor : android::EffectGetDescriptor,
+};
+
+}
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
new file mode 100644
index 0000000..5634ca1
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -0,0 +1,196 @@
+/*
+ * 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 <audio_effects/effect_bassboost.h>
+#include <audio_effects/effect_equalizer.h>
+#include <audio_effects/effect_virtualizer.h>
+#include <LVM.h>
+#include <limits.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#define FIVEBAND_NUMBANDS 5
+#define MAX_NUM_BANDS 5
+#define MAX_CALL_SIZE 256
+#define LVM_MAX_SESSIONS 32
+#define LVM_UNUSED_SESSION INT_MAX
+#define BASS_BOOST_CUP_LOAD_ARM9E 150 // Expressed in 0.1 MIPS
+#define VIRTUALIZER_CUP_LOAD_ARM9E 120 // Expressed in 0.1 MIPS
+#define EQUALIZER_CUP_LOAD_ARM9E 220 // Expressed in 0.1 MIPS
+#define VOLUME_CUP_LOAD_ARM9E 0 // Expressed in 0.1 MIPS
+#define BUNDLE_MEM_USAGE 25 // Expressed in kB
+//#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 */
+ int SessionId; /* Current session id */
+ 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 */
+ bool firstVolume; /* No smoothing on first Vol change */
+ // 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;
+ LVM_Fs_en SampleRate;
+ int SamplesPerSecond;
+ int SamplesToExitCountEq;
+ int SamplesToExitCountBb;
+ int SamplesToExitCountVirt;
+ LVM_INT16 *workBuffer;
+ int frameCount;
+ #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/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
new file mode 100755
index 0000000..9599dcc
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -0,0 +1,2185 @@
+/*
+ * 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 "Reverb"
+#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 "EffectReverb.h"
+// from Reverb/lib
+#include "LVREV.h"
+
+// effect_handle_t interface implementation for reverb
+extern "C" const struct effect_interface_s gReverbInterface;
+
+#define LVM_ERROR_CHECK(LvmStatus, callingFunc, calledFunc){\
+ if (LvmStatus == LVREV_NULLADDRESS){\
+ ALOGV("\tLVREV_ERROR : Parameter error - "\
+ "null pointer returned by %s in %s\n\n\n\n", callingFunc, calledFunc);\
+ }\
+ if (LvmStatus == LVREV_INVALIDNUMSAMPLES){\
+ ALOGV("\tLVREV_ERROR : Parameter error - "\
+ "bad number of samples returned by %s in %s\n\n\n\n", callingFunc, calledFunc);\
+ }\
+ if (LvmStatus == LVREV_OUTOFRANGE){\
+ ALOGV("\tLVREV_ERROR : Parameter error - "\
+ "out of range returned by %s in %s\n", callingFunc, calledFunc);\
+ }\
+ }
+
+// Namespaces
+namespace android {
+namespace {
+
+/************************************************************************************/
+/* */
+/* Preset definitions */
+/* */
+/************************************************************************************/
+
+const static t_reverb_settings sReverbPresets[] = {
+ // REVERB_PRESET_NONE: values are unused
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ // REVERB_PRESET_SMALLROOM
+ {-400, -600, 1100, 830, -400, 5, 500, 10, 1000, 1000},
+ // REVERB_PRESET_MEDIUMROOM
+ {-400, -600, 1300, 830, -1000, 20, -200, 20, 1000, 1000},
+ // REVERB_PRESET_LARGEROOM
+ {-400, -600, 1500, 830, -1600, 5, -1000, 40, 1000, 1000},
+ // REVERB_PRESET_MEDIUMHALL
+ {-400, -600, 1800, 700, -1300, 15, -800, 30, 1000, 1000},
+ // REVERB_PRESET_LARGEHALL
+ {-400, -600, 1800, 700, -2000, 30, -1400, 60, 1000, 1000},
+ // REVERB_PRESET_PLATE
+ {-400, -200, 1300, 900, 0, 2, 0, 10, 1000, 750},
+};
+
+
+// NXP SW auxiliary environmental reverb
+const effect_descriptor_t gAuxEnvReverbDescriptor = {
+ { 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, { 0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e } },
+ { 0x4a387fc0, 0x8ab3, 0x11df, 0x8bad, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } },
+ EFFECT_CONTROL_API_VERSION,
+ EFFECT_FLAG_TYPE_AUXILIARY,
+ LVREV_CUP_LOAD_ARM9E,
+ LVREV_MEM_USAGE,
+ "Auxiliary Environmental Reverb",
+ "NXP Software Ltd.",
+};
+
+// NXP SW insert environmental reverb
+static const effect_descriptor_t gInsertEnvReverbDescriptor = {
+ {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
+ {0xc7a511a0, 0xa3bb, 0x11df, 0x860e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ EFFECT_CONTROL_API_VERSION,
+ EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST | EFFECT_FLAG_VOLUME_CTRL,
+ LVREV_CUP_LOAD_ARM9E,
+ LVREV_MEM_USAGE,
+ "Insert Environmental Reverb",
+ "NXP Software Ltd.",
+};
+
+// NXP SW auxiliary preset reverb
+static const effect_descriptor_t gAuxPresetReverbDescriptor = {
+ {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ {0xf29a1400, 0xa3bb, 0x11df, 0x8ddc, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ EFFECT_CONTROL_API_VERSION,
+ EFFECT_FLAG_TYPE_AUXILIARY,
+ LVREV_CUP_LOAD_ARM9E,
+ LVREV_MEM_USAGE,
+ "Auxiliary Preset Reverb",
+ "NXP Software Ltd.",
+};
+
+// NXP SW insert preset reverb
+static const effect_descriptor_t gInsertPresetReverbDescriptor = {
+ {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ {0x172cdf00, 0xa3bc, 0x11df, 0xa72f, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ EFFECT_CONTROL_API_VERSION,
+ EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST | EFFECT_FLAG_VOLUME_CTRL,
+ LVREV_CUP_LOAD_ARM9E,
+ LVREV_MEM_USAGE,
+ "Insert Preset Reverb",
+ "NXP Software Ltd.",
+};
+
+// gDescriptors contains pointers to all defined effect descriptor in this library
+static const effect_descriptor_t * const gDescriptors[] = {
+ &gAuxEnvReverbDescriptor,
+ &gInsertEnvReverbDescriptor,
+ &gAuxPresetReverbDescriptor,
+ &gInsertPresetReverbDescriptor
+};
+
+struct ReverbContext{
+ const struct effect_interface_s *itfe;
+ effect_config_t config;
+ LVREV_Handle_t hInstance;
+ int16_t SavedRoomLevel;
+ int16_t SavedHfLevel;
+ int16_t SavedDecayTime;
+ int16_t SavedDecayHfRatio;
+ int16_t SavedReverbLevel;
+ int16_t SavedDiffusion;
+ int16_t SavedDensity;
+ bool bEnabled;
+ #ifdef LVM_PCM
+ FILE *PcmInPtr;
+ FILE *PcmOutPtr;
+ #endif
+ LVM_Fs_en SampleRate;
+ LVM_INT32 *InFrames32;
+ LVM_INT32 *OutFrames32;
+ bool auxiliary;
+ bool preset;
+ uint16_t curPreset;
+ uint16_t nextPreset;
+ int SamplesToExitCount;
+ LVM_INT16 leftVolume;
+ LVM_INT16 rightVolume;
+ LVM_INT16 prevLeftVolume;
+ LVM_INT16 prevRightVolume;
+ int volumeMode;
+};
+
+enum {
+ REVERB_VOLUME_OFF,
+ REVERB_VOLUME_FLAT,
+ REVERB_VOLUME_RAMP,
+};
+
+#define REVERB_DEFAULT_PRESET REVERB_PRESET_NONE
+
+
+#define REVERB_SEND_LEVEL (0x0C00) // 0.75 in 4.12 format
+#define REVERB_UNIT_VOLUME (0x1000) // 1.0 in 4.12 format
+
+//--- local function prototypes
+int Reverb_init (ReverbContext *pContext);
+void Reverb_free (ReverbContext *pContext);
+int Reverb_setConfig (ReverbContext *pContext, effect_config_t *pConfig);
+void Reverb_getConfig (ReverbContext *pContext, effect_config_t *pConfig);
+int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue);
+int Reverb_getParameter (ReverbContext *pContext,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue);
+int Reverb_LoadPreset (ReverbContext *pContext);
+
+/* Effect Library Interface Implementation */
+extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects){
+ ALOGV("\n\tEffectQueryNumberEffects start");
+ *pNumEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
+ ALOGV("\tEffectQueryNumberEffects creating %d effects", *pNumEffects);
+ ALOGV("\tEffectQueryNumberEffects end\n");
+ return 0;
+} /* end EffectQueryNumberEffects */
+
+extern "C" int EffectQueryEffect(uint32_t index,
+ effect_descriptor_t *pDescriptor){
+ ALOGV("\n\tEffectQueryEffect start");
+ ALOGV("\tEffectQueryEffect processing index %d", index);
+ if (pDescriptor == NULL){
+ ALOGV("\tLVM_ERROR : EffectQueryEffect was passed NULL pointer");
+ return -EINVAL;
+ }
+ if (index >= sizeof(gDescriptors) / sizeof(const effect_descriptor_t *)) {
+ ALOGV("\tLVM_ERROR : EffectQueryEffect index out of range %d", index);
+ return -ENOENT;
+ }
+ memcpy(pDescriptor, gDescriptors[index], sizeof(effect_descriptor_t));
+ ALOGV("\tEffectQueryEffect end\n");
+ return 0;
+} /* end EffectQueryEffect */
+
+extern "C" int EffectCreate(const effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_handle_t *pHandle){
+ int ret;
+ int i;
+ int length = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
+ const effect_descriptor_t *desc;
+
+ ALOGV("\t\nEffectCreate start");
+
+ if (pHandle == NULL || uuid == NULL){
+ ALOGV("\tLVM_ERROR : EffectCreate() called with NULL pointer");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < length; i++) {
+ desc = gDescriptors[i];
+ if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t))
+ == 0) {
+ ALOGV("\tEffectCreate - UUID matched Reverb type %d, UUID = %x", i, desc->uuid.timeLow);
+ break;
+ }
+ }
+
+ if (i == length) {
+ return -ENOENT;
+ }
+
+ ReverbContext *pContext = new ReverbContext;
+
+ pContext->itfe = &gReverbInterface;
+ pContext->hInstance = NULL;
+
+ pContext->auxiliary = false;
+ if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY){
+ pContext->auxiliary = true;
+ ALOGV("\tEffectCreate - AUX");
+ }else{
+ ALOGV("\tEffectCreate - INS");
+ }
+
+ pContext->preset = false;
+ if (memcmp(&desc->type, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
+ pContext->preset = true;
+ // force reloading preset at first call to process()
+ pContext->curPreset = REVERB_PRESET_LAST + 1;
+ pContext->nextPreset = REVERB_DEFAULT_PRESET;
+ ALOGV("\tEffectCreate - PRESET");
+ }else{
+ ALOGV("\tEffectCreate - ENVIRONMENTAL");
+ }
+
+ ALOGV("\tEffectCreate - Calling Reverb_init");
+ ret = Reverb_init(pContext);
+
+ if (ret < 0){
+ ALOGV("\tLVM_ERROR : EffectCreate() init failed");
+ delete pContext;
+ return ret;
+ }
+
+ *pHandle = (effect_handle_t)pContext;
+
+ #ifdef LVM_PCM
+ pContext->PcmInPtr = NULL;
+ pContext->PcmOutPtr = NULL;
+
+ pContext->PcmInPtr = fopen("/data/tmp/reverb_pcm_in.pcm", "w");
+ pContext->PcmOutPtr = fopen("/data/tmp/reverb_pcm_out.pcm", "w");
+
+ if((pContext->PcmInPtr == NULL)||
+ (pContext->PcmOutPtr == NULL)){
+ return -EINVAL;
+ }
+ #endif
+
+
+ // Allocate memory for reverb process (*2 is for STEREO)
+ pContext->InFrames32 = (LVM_INT32 *)malloc(LVREV_MAX_FRAME_SIZE * sizeof(LVM_INT32) * 2);
+ pContext->OutFrames32 = (LVM_INT32 *)malloc(LVREV_MAX_FRAME_SIZE * sizeof(LVM_INT32) * 2);
+
+ ALOGV("\tEffectCreate %p, size %d", pContext, sizeof(ReverbContext));
+ ALOGV("\tEffectCreate end\n");
+ return 0;
+} /* end EffectCreate */
+
+extern "C" int EffectRelease(effect_handle_t handle){
+ ReverbContext * pContext = (ReverbContext *)handle;
+
+ ALOGV("\tEffectRelease %p", handle);
+ if (pContext == NULL){
+ ALOGV("\tLVM_ERROR : EffectRelease called with NULL pointer");
+ return -EINVAL;
+ }
+
+ #ifdef LVM_PCM
+ fclose(pContext->PcmInPtr);
+ fclose(pContext->PcmOutPtr);
+ #endif
+ free(pContext->InFrames32);
+ free(pContext->OutFrames32);
+ Reverb_free(pContext);
+ delete pContext;
+ return 0;
+} /* end EffectRelease */
+
+extern "C" int EffectGetDescriptor(const effect_uuid_t *uuid,
+ effect_descriptor_t *pDescriptor) {
+ int i;
+ int length = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
+
+ if (pDescriptor == NULL || uuid == NULL){
+ ALOGV("EffectGetDescriptor() called with NULL pointer");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < length; i++) {
+ if (memcmp(uuid, &gDescriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
+ memcpy(pDescriptor, gDescriptors[i], sizeof(effect_descriptor_t));
+ ALOGV("EffectGetDescriptor - UUID matched Reverb type %d, UUID = %x",
+ i, gDescriptors[i]->uuid.timeLow);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+} /* end EffectGetDescriptor */
+
+/* local functions */
+#define CHECK_ARG(cond) { \
+ if (!(cond)) { \
+ ALOGV("\tLVM_ERROR : Invalid argument: "#cond); \
+ return -EINVAL; \
+ } \
+}
+
+//----------------------------------------------------------------------------
+// MonoTo2I_32()
+//----------------------------------------------------------------------------
+// Purpose:
+// Convert MONO to STEREO
+//
+//----------------------------------------------------------------------------
+
+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;
+}
+
+//----------------------------------------------------------------------------
+// From2iToMono_32()
+//----------------------------------------------------------------------------
+// Purpose:
+// Convert STEREO to MONO
+//
+//----------------------------------------------------------------------------
+
+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;
+}
+
+static inline int16_t clamp16(int32_t sample)
+{
+ if ((sample>>15) ^ (sample>>31))
+ sample = 0x7FFF ^ (sample>>31);
+ return sample;
+}
+
+//----------------------------------------------------------------------------
+// process()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the Reverb
+//
+// Inputs:
+// pIn: pointer to stereo/mono 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 process( LVM_INT16 *pIn,
+ LVM_INT16 *pOut,
+ int frameCount,
+ ReverbContext *pContext){
+
+ LVM_INT16 samplesPerFrame = 1;
+ LVREV_ReturnStatus_en LvmStatus = LVREV_SUCCESS; /* Function call status */
+ LVM_INT16 *OutFrames16;
+
+
+ // Check that the input is either mono or stereo
+ if (pContext->config.inputCfg.channels == AUDIO_CHANNEL_OUT_STEREO) {
+ samplesPerFrame = 2;
+ } else if (pContext->config.inputCfg.channels != AUDIO_CHANNEL_OUT_MONO) {
+ ALOGV("\tLVREV_ERROR : process invalid PCM format");
+ return -EINVAL;
+ }
+
+ OutFrames16 = (LVM_INT16 *)pContext->OutFrames32;
+
+ // Check for NULL pointers
+ if((pContext->InFrames32 == NULL)||(pContext->OutFrames32 == NULL)){
+ ALOGV("\tLVREV_ERROR : process failed to allocate memory for temporary buffers ");
+ return -EINVAL;
+ }
+
+ #ifdef LVM_PCM
+ fwrite(pIn, frameCount*sizeof(LVM_INT16)*samplesPerFrame, 1, pContext->PcmInPtr);
+ fflush(pContext->PcmInPtr);
+ #endif
+
+ if (pContext->preset && pContext->nextPreset != pContext->curPreset) {
+ Reverb_LoadPreset(pContext);
+ }
+
+
+
+ // Convert to Input 32 bits
+ if (pContext->auxiliary) {
+ for(int i=0; i<frameCount*samplesPerFrame; i++){
+ pContext->InFrames32[i] = (LVM_INT32)pIn[i]<<8;
+ }
+ } else {
+ // insert reverb input is always stereo
+ for (int i = 0; i < frameCount; i++) {
+ pContext->InFrames32[2*i] = (pIn[2*i] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
+ pContext->InFrames32[2*i+1] = (pIn[2*i+1] * REVERB_SEND_LEVEL) >> 4; // <<8 + >>12
+ }
+ }
+
+ if (pContext->preset && pContext->curPreset == REVERB_PRESET_NONE) {
+ memset(pContext->OutFrames32, 0, frameCount * sizeof(LVM_INT32) * 2); //always stereo here
+ } else {
+ if(pContext->bEnabled == LVM_FALSE && pContext->SamplesToExitCount > 0) {
+ memset(pContext->InFrames32,0,frameCount * sizeof(LVM_INT32) * samplesPerFrame);
+ ALOGV("\tZeroing %d samples per frame at the end of call", samplesPerFrame);
+ }
+
+ /* Process the samples, producing a stereo output */
+ LvmStatus = LVREV_Process(pContext->hInstance, /* Instance handle */
+ pContext->InFrames32, /* Input buffer */
+ pContext->OutFrames32, /* Output buffer */
+ frameCount); /* Number of samples to read */
+ }
+
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_Process", "process")
+ if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
+
+ // Convert to 16 bits
+ if (pContext->auxiliary) {
+ for (int i=0; i < frameCount*2; i++) { //always stereo here
+ OutFrames16[i] = clamp16(pContext->OutFrames32[i]>>8);
+ }
+ } else {
+ for (int i=0; i < frameCount*2; i++) { //always stereo here
+ OutFrames16[i] = clamp16((pContext->OutFrames32[i]>>8) + (LVM_INT32)pIn[i]);
+ }
+
+ // apply volume with ramp if needed
+ if ((pContext->leftVolume != pContext->prevLeftVolume ||
+ pContext->rightVolume != pContext->prevRightVolume) &&
+ pContext->volumeMode == REVERB_VOLUME_RAMP) {
+ LVM_INT32 vl = (LVM_INT32)pContext->prevLeftVolume << 16;
+ LVM_INT32 incl = (((LVM_INT32)pContext->leftVolume << 16) - vl) / frameCount;
+ LVM_INT32 vr = (LVM_INT32)pContext->prevRightVolume << 16;
+ LVM_INT32 incr = (((LVM_INT32)pContext->rightVolume << 16) - vr) / frameCount;
+
+ for (int i = 0; i < frameCount; i++) {
+ OutFrames16[2*i] =
+ clamp16((LVM_INT32)((vl >> 16) * OutFrames16[2*i]) >> 12);
+ OutFrames16[2*i+1] =
+ clamp16((LVM_INT32)((vr >> 16) * OutFrames16[2*i+1]) >> 12);
+
+ vl += incl;
+ vr += incr;
+ }
+
+ pContext->prevLeftVolume = pContext->leftVolume;
+ pContext->prevRightVolume = pContext->rightVolume;
+ } else if (pContext->volumeMode != REVERB_VOLUME_OFF) {
+ if (pContext->leftVolume != REVERB_UNIT_VOLUME ||
+ pContext->rightVolume != REVERB_UNIT_VOLUME) {
+ for (int i = 0; i < frameCount; i++) {
+ OutFrames16[2*i] =
+ clamp16((LVM_INT32)(pContext->leftVolume * OutFrames16[2*i]) >> 12);
+ OutFrames16[2*i+1] =
+ clamp16((LVM_INT32)(pContext->rightVolume * OutFrames16[2*i+1]) >> 12);
+ }
+ }
+ pContext->prevLeftVolume = pContext->leftVolume;
+ pContext->prevRightVolume = pContext->rightVolume;
+ pContext->volumeMode = REVERB_VOLUME_RAMP;
+ }
+ }
+
+ #ifdef LVM_PCM
+ fwrite(OutFrames16, frameCount*sizeof(LVM_INT16)*2, 1, pContext->PcmOutPtr);
+ fflush(pContext->PcmOutPtr);
+ #endif
+
+ // Accumulate if required
+ if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
+ //ALOGV("\tBuffer access is ACCUMULATE");
+ for (int i=0; i<frameCount*2; i++){ //always stereo here
+ pOut[i] = clamp16((int32_t)pOut[i] + (int32_t)OutFrames16[i]);
+ }
+ }else{
+ //ALOGV("\tBuffer access is WRITE");
+ memcpy(pOut, OutFrames16, frameCount*sizeof(LVM_INT16)*2);
+ }
+
+ return 0;
+} /* end process */
+
+//----------------------------------------------------------------------------
+// Reverb_free()
+//----------------------------------------------------------------------------
+// Purpose: Free all memory associated with the Bundle.
+//
+// Inputs:
+// pContext: effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+void Reverb_free(ReverbContext *pContext){
+
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVREV_ControlParams_st params; /* Control Parameters */
+ LVREV_MemoryTable_st MemTab;
+
+ /* Free the algorithm memory */
+ LvmStatus = LVREV_GetMemoryTable(pContext->hInstance,
+ &MemTab,
+ LVM_NULL);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetMemoryTable", "Reverb_free")
+
+ for (int i=0; i<LVM_NR_MEMORY_REGIONS; i++){
+ if (MemTab.Region[i].Size != 0){
+ if (MemTab.Region[i].pBaseAddress != NULL){
+ ALOGV("\tfree() - START freeing %ld bytes for region %u at %p\n",
+ MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+
+ free(MemTab.Region[i].pBaseAddress);
+
+ ALOGV("\tfree() - END freeing %ld bytes for region %u at %p\n",
+ MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+ }else{
+ ALOGV("\tLVM_ERROR : 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 Reverb_free */
+
+//----------------------------------------------------------------------------
+// Reverb_setConfig()
+//----------------------------------------------------------------------------
+// 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 Reverb_setConfig(ReverbContext *pContext, effect_config_t *pConfig){
+ LVM_Fs_en SampleRate;
+ //ALOGV("\tReverb_setConfig start");
+
+ CHECK_ARG(pContext != NULL);
+ CHECK_ARG(pConfig != NULL);
+
+ CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
+ CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
+ CHECK_ARG((pContext->auxiliary && pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_MONO) ||
+ ((!pContext->auxiliary) && pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_STEREO));
+ CHECK_ARG(pConfig->outputCfg.channels == AUDIO_CHANNEL_OUT_STEREO);
+ CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
+ || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
+ CHECK_ARG(pConfig->inputCfg.format == AUDIO_FORMAT_PCM_16_BIT);
+
+ if(pConfig->inputCfg.samplingRate != 44100){
+ return -EINVAL;
+ }
+
+ //ALOGV("\tReverb_setConfig calling memcpy");
+ 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:
+ ALOGV("\rReverb_setConfig invalid sampling rate %d", pConfig->inputCfg.samplingRate);
+ return -EINVAL;
+ }
+
+ if(pContext->SampleRate != SampleRate){
+
+ LVREV_ControlParams_st ActiveParams;
+ LVREV_ReturnStatus_en LvmStatus = LVREV_SUCCESS;
+
+ //ALOGV("\tReverb_setConfig change sampling rate to %d", SampleRate);
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance,
+ &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "Reverb_setConfig")
+ if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
+
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "Reverb_setConfig")
+ //ALOGV("\tReverb_setConfig Succesfully called LVREV_SetControlParameters\n");
+
+ }else{
+ //ALOGV("\tReverb_setConfig keep sampling rate at %d", SampleRate);
+ }
+
+ //ALOGV("\tReverb_setConfig End");
+ return 0;
+} /* end Reverb_setConfig */
+
+//----------------------------------------------------------------------------
+// Reverb_getConfig()
+//----------------------------------------------------------------------------
+// Purpose: Get input and output audio configuration.
+//
+// Inputs:
+// pContext: effect engine context
+// pConfig: pointer to effect_config_t structure holding input and output
+// configuration parameters
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+void Reverb_getConfig(ReverbContext *pContext, effect_config_t *pConfig)
+{
+ memcpy(pConfig, &pContext->config, sizeof(effect_config_t));
+} /* end Reverb_getConfig */
+
+//----------------------------------------------------------------------------
+// Reverb_init()
+//----------------------------------------------------------------------------
+// Purpose: Initialize engine with default configuration
+//
+// Inputs:
+// pContext: effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Reverb_init(ReverbContext *pContext){
+ int status;
+
+ ALOGV("\tReverb_init start");
+
+ CHECK_ARG(pContext != NULL);
+
+ if (pContext->hInstance != NULL){
+ Reverb_free(pContext);
+ }
+
+ pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+ if (pContext->auxiliary) {
+ pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
+ } else {
+ pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ }
+
+ pContext->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ 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 = AUDIO_CHANNEL_OUT_STEREO;
+ pContext->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ 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->leftVolume = REVERB_UNIT_VOLUME;
+ pContext->rightVolume = REVERB_UNIT_VOLUME;
+ pContext->prevLeftVolume = REVERB_UNIT_VOLUME;
+ pContext->prevRightVolume = REVERB_UNIT_VOLUME;
+ pContext->volumeMode = REVERB_VOLUME_FLAT;
+
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVREV_ControlParams_st params; /* Control Parameters */
+ LVREV_InstanceParams_st InstParams; /* Instance parameters */
+ LVREV_MemoryTable_st MemTab; /* Memory allocation table */
+ bool bMallocFailure = LVM_FALSE;
+
+ /* Set the capabilities */
+ InstParams.MaxBlockSize = MAX_CALL_SIZE;
+ InstParams.SourceFormat = LVM_STEREO; // Max format, could be mono during process
+ InstParams.NumDelays = LVREV_DELAYLINES_4;
+
+ /* Allocate memory, forcing alignment */
+ LvmStatus = LVREV_GetMemoryTable(LVM_NULL,
+ &MemTab,
+ &InstParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetMemoryTable", "Reverb_init")
+ if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
+
+ ALOGV("\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){
+ ALOGV("\tLVREV_ERROR :Reverb_init CreateInstance Failed to allocate %ld "
+ "bytes for region %u\n", MemTab.Region[i].Size, i );
+ bMallocFailure = LVM_TRUE;
+ }else{
+ ALOGV("\tReverb_init CreateInstance allocate %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){
+ ALOGV("\tLVM_ERROR :Reverb_init CreateInstance Failed to allocate %ld bytes "
+ "for region %u - Not freeing\n", MemTab.Region[i].Size, i );
+ }else{
+ ALOGV("\tLVM_ERROR :Reverb_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;
+ }
+ ALOGV("\tReverb_init CreateInstance Succesfully malloc'd memory\n");
+
+ /* Initialise */
+ pContext->hInstance = LVM_NULL;
+
+ /* Init sets the instance handle */
+ LvmStatus = LVREV_GetInstanceHandle(&pContext->hInstance,
+ &MemTab,
+ &InstParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetInstanceHandle", "Reverb_init")
+ if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
+
+ ALOGV("\tReverb_init CreateInstance Succesfully called LVM_GetInstanceHandle\n");
+
+ /* Set the initial process parameters */
+ /* General parameters */
+ params.OperatingMode = LVM_MODE_ON;
+ params.SampleRate = LVM_FS_44100;
+
+ if(pContext->config.inputCfg.channels == AUDIO_CHANNEL_OUT_MONO){
+ params.SourceFormat = LVM_MONO;
+ } else {
+ params.SourceFormat = LVM_STEREO;
+ }
+
+ /* Reverb parameters */
+ params.Level = 0;
+ params.LPF = 23999;
+ params.HPF = 50;
+ params.T60 = 1490;
+ params.Density = 100;
+ params.Damping = 21;
+ params.RoomSize = 100;
+
+ pContext->SamplesToExitCount = (params.T60 * pContext->config.inputCfg.samplingRate)/1000;
+
+ /* 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->SavedRoomLevel = -6000;
+ pContext->SavedHfLevel = 0;
+ pContext->bEnabled = LVM_FALSE;
+ pContext->SavedDecayTime = params.T60;
+ pContext->SavedDecayHfRatio = params.Damping*20;
+ pContext->SavedDensity = params.RoomSize*10;
+ pContext->SavedDiffusion = params.Density*10;
+ pContext->SavedReverbLevel = -6000;
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance,
+ &params);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "Reverb_init")
+ if(LvmStatus != LVREV_SUCCESS) return -EINVAL;
+
+ ALOGV("\tReverb_init CreateInstance Succesfully called LVREV_SetControlParameters\n");
+ ALOGV("\tReverb_init End");
+ return 0;
+} /* end Reverb_init */
+
+//----------------------------------------------------------------------------
+// ReverbConvertLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Convert level from OpenSL ES format to LVM format
+//
+// Inputs:
+// level level to be applied
+//
+//----------------------------------------------------------------------------
+
+int16_t ReverbConvertLevel(int16_t level){
+ static int16_t LevelArray[101] =
+ {
+ -12000, -4000, -3398, -3046, -2796, -2603, -2444, -2310, -2194, -2092,
+ -2000, -1918, -1842, -1773, -1708, -1648, -1592, -1540, -1490, -1443,
+ -1398, -1356, -1316, -1277, -1240, -1205, -1171, -1138, -1106, -1076,
+ -1046, -1018, -990, -963, -938, -912, -888, -864, -841, -818,
+ -796, -775, -754, -734, -714, -694, -675, -656, -638, -620,
+ -603, -585, -568, -552, -536, -520, -504, -489, -474, -459,
+ -444, -430, -416, -402, -388, -375, -361, -348, -335, -323,
+ -310, -298, -286, -274, -262, -250, -239, -228, -216, -205,
+ -194, -184, -173, -162, -152, -142, -132, -121, -112, -102,
+ -92, -82, -73, -64, -54, -45, -36, -27, -18, -9,
+ 0
+ };
+ int16_t i;
+
+ for(i = 0; i < 101; i++)
+ {
+ if(level <= LevelArray[i])
+ break;
+ }
+ return i;
+}
+
+//----------------------------------------------------------------------------
+// ReverbConvertHFLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Convert level from OpenSL ES format to LVM format
+//
+// Inputs:
+// level level to be applied
+//
+//----------------------------------------------------------------------------
+
+int16_t ReverbConvertHfLevel(int16_t Hflevel){
+ int16_t i;
+
+ static LPFPair_t LPFArray[97] =
+ { // Limit range to 50 for LVREV parameter range
+ {-10000, 50}, { -5000, 50 }, { -4000, 50}, { -3000, 158}, { -2000, 502},
+ {-1000, 1666},{ -900, 1897}, { -800, 2169}, { -700, 2496}, { -600, 2895},
+ {-500, 3400}, { -400, 4066}, { -300, 5011}, { -200, 6537}, { -100, 9826},
+ {-99, 9881 }, { -98, 9937 }, { -97, 9994 }, { -96, 10052}, { -95, 10111},
+ {-94, 10171}, { -93, 10231}, { -92, 10293}, { -91, 10356}, { -90, 10419},
+ {-89, 10484}, { -88, 10549}, { -87, 10616}, { -86, 10684}, { -85, 10753},
+ {-84, 10823}, { -83, 10895}, { -82, 10968}, { -81, 11042}, { -80, 11117},
+ {-79, 11194}, { -78, 11272}, { -77, 11352}, { -76, 11433}, { -75, 11516},
+ {-74, 11600}, { -73, 11686}, { -72, 11774}, { -71, 11864}, { -70, 11955},
+ {-69, 12049}, { -68, 12144}, { -67, 12242}, { -66, 12341}, { -65, 12443},
+ {-64, 12548}, { -63, 12654}, { -62, 12763}, { -61, 12875}, { -60, 12990},
+ {-59, 13107}, { -58, 13227}, { -57, 13351}, { -56, 13477}, { -55, 13607},
+ {-54, 13741}, { -53, 13878}, { -52, 14019}, { -51, 14164}, { -50, 14313},
+ {-49, 14467}, { -48, 14626}, { -47, 14789}, { -46, 14958}, { -45, 15132},
+ {-44, 15312}, { -43, 15498}, { -42, 15691}, { -41, 15890}, { -40, 16097},
+ {-39, 16311}, { -38, 16534}, { -37, 16766}, { -36, 17007}, { -35, 17259},
+ {-34, 17521}, { -33, 17795}, { -32, 18081}, { -31, 18381}, { -30, 18696},
+ {-29, 19027}, { -28, 19375}, { -27, 19742}, { -26, 20129}, { -25, 20540},
+ {-24, 20976}, { -23, 21439}, { -22, 21934}, { -21, 22463}, { -20, 23031},
+ {-19, 23643}, { -18, 23999}
+ };
+
+ for(i = 0; i < 96; i++)
+ {
+ if(Hflevel <= LPFArray[i].Room_HF)
+ break;
+ }
+ return LPFArray[i].LPF;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetRoomHfLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the HF level to the Reverb. Must first be converted to LVM format
+//
+// Inputs:
+// pContext: effect engine context
+// level level to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetRoomHfLevel(ReverbContext *pContext, int16_t level){
+ //ALOGV("\tReverbSetRoomHfLevel start (%d)", level);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetRoomHfLevel")
+ //ALOGV("\tReverbSetRoomHfLevel Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbSetRoomHfLevel() just Got -> %d\n", ActiveParams.LPF);
+
+ ActiveParams.LPF = ReverbConvertHfLevel(level);
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetRoomHfLevel")
+ //ALOGV("\tReverbSetRoomhfLevel() just Set -> %d\n", ActiveParams.LPF);
+ pContext->SavedHfLevel = level;
+ //ALOGV("\tReverbSetHfRoomLevel end.. saving %d", pContext->SavedHfLevel);
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetRoomHfLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the level applied to the Revervb. Must first be converted to LVM format
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int16_t ReverbGetRoomHfLevel(ReverbContext *pContext){
+ int16_t level;
+ //ALOGV("\tReverbGetRoomHfLevel start, saved level is %d", pContext->SavedHfLevel);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetRoomHfLevel")
+ //ALOGV("\tReverbGetRoomHfLevel Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbGetRoomHfLevel() just Got -> %d\n", ActiveParams.LPF);
+
+ level = ReverbConvertHfLevel(pContext->SavedHfLevel);
+
+ //ALOGV("\tReverbGetRoomHfLevel() ActiveParams.LPFL %d, pContext->SavedHfLevel: %d, "
+ // "converted level: %d\n", ActiveParams.LPF, pContext->SavedHfLevel, level);
+
+ if(ActiveParams.LPF != level){
+ ALOGV("\tLVM_ERROR : (ignore at start up) ReverbGetRoomHfLevel() has wrong level -> %d %d\n",
+ ActiveParams.Level, level);
+ }
+
+ //ALOGV("\tReverbGetRoomHfLevel end");
+ return pContext->SavedHfLevel;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetReverbLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the level to the Reverb. Must first be converted to LVM format
+//
+// Inputs:
+// pContext: effect engine context
+// level level to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetReverbLevel(ReverbContext *pContext, int16_t level){
+ //ALOGV("\n\tReverbSetReverbLevel start (%d)", level);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVM_INT32 CombinedLevel; // Sum of room and reverb level controls
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetReverbLevel")
+ //ALOGV("\tReverbSetReverbLevel Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbSetReverbLevel just Got -> %d\n", ActiveParams.Level);
+
+ // needs to subtract max levels for both RoomLevel and ReverbLevel
+ CombinedLevel = (level + pContext->SavedRoomLevel)-LVREV_MAX_REVERB_LEVEL;
+ //ALOGV("\tReverbSetReverbLevel() CombinedLevel is %d = %d + %d\n",
+ // CombinedLevel, level, pContext->SavedRoomLevel);
+
+ ActiveParams.Level = ReverbConvertLevel(CombinedLevel);
+
+ //ALOGV("\tReverbSetReverbLevel() Trying to set -> %d\n", ActiveParams.Level);
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetReverbLevel")
+ //ALOGV("\tReverbSetReverbLevel() just Set -> %d\n", ActiveParams.Level);
+
+ pContext->SavedReverbLevel = level;
+ //ALOGV("\tReverbSetReverbLevel end pContext->SavedReverbLevel is %d\n\n",
+ // pContext->SavedReverbLevel);
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetReverbLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the level applied to the Revervb. Must first be converted to LVM format
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int16_t ReverbGetReverbLevel(ReverbContext *pContext){
+ int16_t level;
+ //ALOGV("\tReverbGetReverbLevel start");
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVM_INT32 CombinedLevel; // Sum of room and reverb level controls
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetReverbLevel")
+ //ALOGV("\tReverbGetReverbLevel Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbGetReverbLevel() just Got -> %d\n", ActiveParams.Level);
+
+ // needs to subtract max levels for both RoomLevel and ReverbLevel
+ CombinedLevel = (pContext->SavedReverbLevel + pContext->SavedRoomLevel)-LVREV_MAX_REVERB_LEVEL;
+
+ //ALOGV("\tReverbGetReverbLevel() CombinedLevel is %d = %d + %d\n",
+ //CombinedLevel, pContext->SavedReverbLevel, pContext->SavedRoomLevel);
+ level = ReverbConvertLevel(CombinedLevel);
+
+ //ALOGV("\tReverbGetReverbLevel(): ActiveParams.Level: %d, pContext->SavedReverbLevel: %d, "
+ //"pContext->SavedRoomLevel: %d, CombinedLevel: %d, converted level: %d\n",
+ //ActiveParams.Level, pContext->SavedReverbLevel,pContext->SavedRoomLevel, CombinedLevel,level);
+
+ if(ActiveParams.Level != level){
+ ALOGV("\tLVM_ERROR : (ignore at start up) ReverbGetReverbLevel() has wrong level -> %d %d\n",
+ ActiveParams.Level, level);
+ }
+
+ //ALOGV("\tReverbGetReverbLevel end\n");
+
+ return pContext->SavedReverbLevel;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetRoomLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the level to the Reverb. Must first be converted to LVM format
+//
+// Inputs:
+// pContext: effect engine context
+// level level to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetRoomLevel(ReverbContext *pContext, int16_t level){
+ //ALOGV("\tReverbSetRoomLevel start (%d)", level);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVM_INT32 CombinedLevel; // Sum of room and reverb level controls
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetRoomLevel")
+ //ALOGV("\tReverbSetRoomLevel Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbSetRoomLevel() just Got -> %d\n", ActiveParams.Level);
+
+ // needs to subtract max levels for both RoomLevel and ReverbLevel
+ CombinedLevel = (level + pContext->SavedReverbLevel)-LVREV_MAX_REVERB_LEVEL;
+ ActiveParams.Level = ReverbConvertLevel(CombinedLevel);
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetRoomLevel")
+ //ALOGV("\tReverbSetRoomLevel() just Set -> %d\n", ActiveParams.Level);
+
+ pContext->SavedRoomLevel = level;
+ //ALOGV("\tReverbSetRoomLevel end");
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetRoomLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the level applied to the Revervb. Must first be converted to LVM format
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int16_t ReverbGetRoomLevel(ReverbContext *pContext){
+ int16_t level;
+ //ALOGV("\tReverbGetRoomLevel start");
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVM_INT32 CombinedLevel; // Sum of room and reverb level controls
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetRoomLevel")
+ //ALOGV("\tReverbGetRoomLevel Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbGetRoomLevel() just Got -> %d\n", ActiveParams.Level);
+
+ // needs to subtract max levels for both RoomLevel and ReverbLevel
+ CombinedLevel = (pContext->SavedRoomLevel + pContext->SavedReverbLevel-LVREV_MAX_REVERB_LEVEL);
+ level = ReverbConvertLevel(CombinedLevel);
+
+ //ALOGV("\tReverbGetRoomLevel, Level = %d, pContext->SavedRoomLevel = %d, "
+ // "pContext->SavedReverbLevel = %d, CombinedLevel = %d, level = %d",
+ // ActiveParams.Level, pContext->SavedRoomLevel,
+ // pContext->SavedReverbLevel, CombinedLevel, level);
+
+ if(ActiveParams.Level != level){
+ ALOGV("\tLVM_ERROR : (ignore at start up) ReverbGetRoomLevel() has wrong level -> %d %d\n",
+ ActiveParams.Level, level);
+ }
+
+ //ALOGV("\tReverbGetRoomLevel end");
+ return pContext->SavedRoomLevel;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetDecayTime()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the decay time to the Reverb.
+//
+// Inputs:
+// pContext: effect engine context
+// time decay to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetDecayTime(ReverbContext *pContext, uint32_t time){
+ //ALOGV("\tReverbSetDecayTime start (%d)", time);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetDecayTime")
+ //ALOGV("\tReverbSetDecayTime Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbSetDecayTime() just Got -> %d\n", ActiveParams.T60);
+
+ if (time <= LVREV_MAX_T60) {
+ ActiveParams.T60 = (LVM_UINT16)time;
+ }
+ else {
+ ActiveParams.T60 = LVREV_MAX_T60;
+ }
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetDecayTime")
+ //ALOGV("\tReverbSetDecayTime() just Set -> %d\n", ActiveParams.T60);
+
+ pContext->SamplesToExitCount = (ActiveParams.T60 * pContext->config.inputCfg.samplingRate)/1000;
+ //ALOGV("\tReverbSetDecayTime() just Set SamplesToExitCount-> %d\n",pContext->SamplesToExitCount);
+ pContext->SavedDecayTime = (int16_t)time;
+ //ALOGV("\tReverbSetDecayTime end");
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetDecayTime()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the decay time applied to the Revervb.
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+uint32_t ReverbGetDecayTime(ReverbContext *pContext){
+ //ALOGV("\tReverbGetDecayTime start");
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetDecayTime")
+ //ALOGV("\tReverbGetDecayTime Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbGetDecayTime() just Got -> %d\n", ActiveParams.T60);
+
+ if(ActiveParams.T60 != pContext->SavedDecayTime){
+ // This will fail if the decay time is set to more than 7000
+ ALOGV("\tLVM_ERROR : ReverbGetDecayTime() has wrong level -> %d %d\n",
+ ActiveParams.T60, pContext->SavedDecayTime);
+ }
+
+ //ALOGV("\tReverbGetDecayTime end");
+ return (uint32_t)ActiveParams.T60;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetDecayHfRatio()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the HF decay ratio to the Reverb.
+//
+// Inputs:
+// pContext: effect engine context
+// ratio ratio to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetDecayHfRatio(ReverbContext *pContext, int16_t ratio){
+ //ALOGV("\tReverbSetDecayHfRatioe start (%d)", ratio);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetDecayHfRatio")
+ //ALOGV("\tReverbSetDecayHfRatio Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbSetDecayHfRatio() just Got -> %d\n", ActiveParams.Damping);
+
+ ActiveParams.Damping = (LVM_INT16)(ratio/20);
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetDecayHfRatio")
+ //ALOGV("\tReverbSetDecayHfRatio() just Set -> %d\n", ActiveParams.Damping);
+
+ pContext->SavedDecayHfRatio = ratio;
+ //ALOGV("\tReverbSetDecayHfRatio end");
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetDecayHfRatio()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the HF decay ratio applied to the Revervb.
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int32_t ReverbGetDecayHfRatio(ReverbContext *pContext){
+ //ALOGV("\tReverbGetDecayHfRatio start");
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetDecayHfRatio")
+ //ALOGV("\tReverbGetDecayHfRatio Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbGetDecayHfRatio() just Got -> %d\n", ActiveParams.Damping);
+
+ if(ActiveParams.Damping != (LVM_INT16)(pContext->SavedDecayHfRatio / 20)){
+ ALOGV("\tLVM_ERROR : ReverbGetDecayHfRatio() has wrong level -> %d %d\n",
+ ActiveParams.Damping, pContext->SavedDecayHfRatio);
+ }
+
+ //ALOGV("\tReverbGetDecayHfRatio end");
+ return pContext->SavedDecayHfRatio;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetDiffusion()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the diffusion to the Reverb.
+//
+// Inputs:
+// pContext: effect engine context
+// level decay to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetDiffusion(ReverbContext *pContext, int16_t level){
+ //ALOGV("\tReverbSetDiffusion start (%d)", level);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetDiffusion")
+ //ALOGV("\tReverbSetDiffusion Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbSetDiffusion() just Got -> %d\n", ActiveParams.Density);
+
+ ActiveParams.Density = (LVM_INT16)(level/10);
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetDiffusion")
+ //ALOGV("\tReverbSetDiffusion() just Set -> %d\n", ActiveParams.Density);
+
+ pContext->SavedDiffusion = level;
+ //ALOGV("\tReverbSetDiffusion end");
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetDiffusion()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the decay time applied to the Revervb.
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int32_t ReverbGetDiffusion(ReverbContext *pContext){
+ //ALOGV("\tReverbGetDiffusion start");
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVM_INT16 Temp;
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetDiffusion")
+ //ALOGV("\tReverbGetDiffusion Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbGetDiffusion just Got -> %d\n", ActiveParams.Density);
+
+ Temp = (LVM_INT16)(pContext->SavedDiffusion/10);
+
+ if(ActiveParams.Density != Temp){
+ ALOGV("\tLVM_ERROR : ReverbGetDiffusion invalid value %d %d", Temp, ActiveParams.Density);
+ }
+
+ //ALOGV("\tReverbGetDiffusion end");
+ return pContext->SavedDiffusion;
+}
+
+//----------------------------------------------------------------------------
+// ReverbSetDensity()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the density level the Reverb.
+//
+// Inputs:
+// pContext: effect engine context
+// level decay to be applied
+//
+//----------------------------------------------------------------------------
+
+void ReverbSetDensity(ReverbContext *pContext, int16_t level){
+ //ALOGV("\tReverbSetDensity start (%d)", level);
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbSetDensity")
+ //ALOGV("\tReverbSetDensity Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbSetDensity just Got -> %d\n", ActiveParams.RoomSize);
+
+ ActiveParams.RoomSize = (LVM_INT16)(((level * 99) / 1000) + 1);
+
+ /* Activate the initial settings */
+ LvmStatus = LVREV_SetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_SetControlParameters", "ReverbSetDensity")
+ //ALOGV("\tReverbSetDensity just Set -> %d\n", ActiveParams.RoomSize);
+
+ pContext->SavedDensity = level;
+ //ALOGV("\tReverbSetDensity end");
+ return;
+}
+
+//----------------------------------------------------------------------------
+// ReverbGetDensity()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get the density level applied to the Revervb.
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int32_t ReverbGetDensity(ReverbContext *pContext){
+ //ALOGV("\tReverbGetDensity start");
+
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+ LVM_INT16 Temp;
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "ReverbGetDensity")
+ //ALOGV("\tReverbGetDensity Succesfully returned from LVM_GetControlParameters\n");
+ //ALOGV("\tReverbGetDensity() just Got -> %d\n", ActiveParams.RoomSize);
+
+
+ Temp = (LVM_INT16)(((pContext->SavedDensity * 99) / 1000) + 1);
+
+ if(Temp != ActiveParams.RoomSize){
+ ALOGV("\tLVM_ERROR : ReverbGetDensity invalid value %d %d", Temp, ActiveParams.RoomSize);
+ }
+
+ //ALOGV("\tReverbGetDensity end");
+ return pContext->SavedDensity;
+}
+
+//----------------------------------------------------------------------------
+// Reverb_LoadPreset()
+//----------------------------------------------------------------------------
+// Purpose:
+// Load a the next preset
+//
+// Inputs:
+// pContext - handle to instance data
+//
+// Outputs:
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+int Reverb_LoadPreset(ReverbContext *pContext)
+{
+ //TODO: add reflections delay, level and reverb delay when early reflections are
+ // implemented
+ pContext->curPreset = pContext->nextPreset;
+
+ if (pContext->curPreset != REVERB_PRESET_NONE) {
+ const t_reverb_settings *preset = &sReverbPresets[pContext->curPreset];
+ ReverbSetRoomLevel(pContext, preset->roomLevel);
+ ReverbSetRoomHfLevel(pContext, preset->roomHFLevel);
+ ReverbSetDecayTime(pContext, preset->decayTime);
+ ReverbSetDecayHfRatio(pContext, preset->decayHFRatio);
+ //reflectionsLevel
+ //reflectionsDelay
+ ReverbSetReverbLevel(pContext, preset->reverbLevel);
+ // reverbDelay
+ ReverbSetDiffusion(pContext, preset->diffusion);
+ ReverbSetDensity(pContext, preset->density);
+ }
+
+ return 0;
+}
+
+
+//----------------------------------------------------------------------------
+// Reverb_getParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get a Reverb parameter
+//
+// Inputs:
+// pContext - 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 Reverb_getParameter(ReverbContext *pContext,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue){
+ int status = 0;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
+ char *name;
+ t_reverb_settings *pProperties;
+
+ //ALOGV("\tReverb_getParameter start");
+ if (pContext->preset) {
+ if (param != REVERB_PARAM_PRESET || *pValueSize < sizeof(uint16_t)) {
+ return -EINVAL;
+ }
+
+ *(uint16_t *)pValue = pContext->nextPreset;
+ ALOGV("get REVERB_PARAM_PRESET, preset %d", pContext->nextPreset);
+ return 0;
+ }
+
+ switch (param){
+ case REVERB_PARAM_ROOM_LEVEL:
+ if (*pValueSize != sizeof(int16_t)){
+ ALOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize1 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_ROOM_HF_LEVEL:
+ if (*pValueSize != sizeof(int16_t)){
+ ALOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize12 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_DECAY_TIME:
+ if (*pValueSize != sizeof(uint32_t)){
+ ALOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize3 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(uint32_t);
+ break;
+ case REVERB_PARAM_DECAY_HF_RATIO:
+ if (*pValueSize != sizeof(int16_t)){
+ ALOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize4 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_REFLECTIONS_LEVEL:
+ if (*pValueSize != sizeof(int16_t)){
+ ALOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize5 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_REFLECTIONS_DELAY:
+ if (*pValueSize != sizeof(uint32_t)){
+ ALOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize6 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(uint32_t);
+ break;
+ case REVERB_PARAM_REVERB_LEVEL:
+ if (*pValueSize != sizeof(int16_t)){
+ ALOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize7 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_REVERB_DELAY:
+ if (*pValueSize != sizeof(uint32_t)){
+ ALOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize8 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(uint32_t);
+ break;
+ case REVERB_PARAM_DIFFUSION:
+ if (*pValueSize != sizeof(int16_t)){
+ ALOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize9 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_DENSITY:
+ if (*pValueSize != sizeof(int16_t)){
+ ALOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize10 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+ case REVERB_PARAM_PROPERTIES:
+ if (*pValueSize != sizeof(t_reverb_settings)){
+ ALOGV("\tLVM_ERROR : Reverb_getParameter() invalid pValueSize11 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(t_reverb_settings);
+ break;
+
+ default:
+ ALOGV("\tLVM_ERROR : Reverb_getParameter() invalid param %d", param);
+ return -EINVAL;
+ }
+
+ pProperties = (t_reverb_settings *) pValue;
+
+ switch (param){
+ case REVERB_PARAM_PROPERTIES:
+ pProperties->roomLevel = ReverbGetRoomLevel(pContext);
+ pProperties->roomHFLevel = ReverbGetRoomHfLevel(pContext);
+ pProperties->decayTime = ReverbGetDecayTime(pContext);
+ pProperties->decayHFRatio = ReverbGetDecayHfRatio(pContext);
+ pProperties->reflectionsLevel = 0;
+ pProperties->reflectionsDelay = 0;
+ pProperties->reverbDelay = 0;
+ pProperties->reverbLevel = ReverbGetReverbLevel(pContext);
+ pProperties->diffusion = ReverbGetDiffusion(pContext);
+ pProperties->density = ReverbGetDensity(pContext);
+
+ ALOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is roomLevel %d",
+ pProperties->roomLevel);
+ ALOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is roomHFLevel %d",
+ pProperties->roomHFLevel);
+ ALOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is decayTime %d",
+ pProperties->decayTime);
+ ALOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is decayHFRatio %d",
+ pProperties->decayHFRatio);
+ ALOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is reflectionsLevel %d",
+ pProperties->reflectionsLevel);
+ ALOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is reflectionsDelay %d",
+ pProperties->reflectionsDelay);
+ ALOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is reverbDelay %d",
+ pProperties->reverbDelay);
+ ALOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is reverbLevel %d",
+ pProperties->reverbLevel);
+ ALOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is diffusion %d",
+ pProperties->diffusion);
+ ALOGV("\tReverb_getParameter() REVERB_PARAM_PROPERTIES Value is density %d",
+ pProperties->density);
+ break;
+
+ case REVERB_PARAM_ROOM_LEVEL:
+ *(int16_t *)pValue = ReverbGetRoomLevel(pContext);
+
+ //ALOGV("\tReverb_getParameter() REVERB_PARAM_ROOM_LEVEL Value is %d",
+ // *(int16_t *)pValue);
+ break;
+ case REVERB_PARAM_ROOM_HF_LEVEL:
+ *(int16_t *)pValue = ReverbGetRoomHfLevel(pContext);
+
+ //ALOGV("\tReverb_getParameter() REVERB_PARAM_ROOM_HF_LEVEL Value is %d",
+ // *(int16_t *)pValue);
+ break;
+ case REVERB_PARAM_DECAY_TIME:
+ *(uint32_t *)pValue = ReverbGetDecayTime(pContext);
+
+ //ALOGV("\tReverb_getParameter() REVERB_PARAM_DECAY_TIME Value is %d",
+ // *(int32_t *)pValue);
+ break;
+ case REVERB_PARAM_DECAY_HF_RATIO:
+ *(int16_t *)pValue = ReverbGetDecayHfRatio(pContext);
+
+ //ALOGV("\tReverb_getParameter() REVERB_PARAM_DECAY_HF_RATION Value is %d",
+ // *(int16_t *)pValue);
+ break;
+ case REVERB_PARAM_REVERB_LEVEL:
+ *(int16_t *)pValue = ReverbGetReverbLevel(pContext);
+
+ //ALOGV("\tReverb_getParameter() REVERB_PARAM_REVERB_LEVEL Value is %d",
+ // *(int16_t *)pValue);
+ break;
+ case REVERB_PARAM_DIFFUSION:
+ *(int16_t *)pValue = ReverbGetDiffusion(pContext);
+
+ //ALOGV("\tReverb_getParameter() REVERB_PARAM_DECAY_DIFFUSION Value is %d",
+ // *(int16_t *)pValue);
+ break;
+ case REVERB_PARAM_DENSITY:
+ *(uint16_t *)pValue = 0;
+ *(int16_t *)pValue = ReverbGetDensity(pContext);
+ //ALOGV("\tReverb_getParameter() REVERB_PARAM_DENSITY Value is %d",
+ // *(uint32_t *)pValue);
+ break;
+ case REVERB_PARAM_REFLECTIONS_LEVEL:
+ *(uint16_t *)pValue = 0;
+ case REVERB_PARAM_REFLECTIONS_DELAY:
+ *(uint32_t *)pValue = 0;
+ case REVERB_PARAM_REVERB_DELAY:
+ *(uint32_t *)pValue = 0;
+ break;
+
+ default:
+ ALOGV("\tLVM_ERROR : Reverb_getParameter() invalid param %d", param);
+ status = -EINVAL;
+ break;
+ }
+
+ //ALOGV("\tReverb_getParameter end");
+ return status;
+} /* end Reverb_getParameter */
+
+//----------------------------------------------------------------------------
+// Reverb_setParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Set a Reverb parameter
+//
+// Inputs:
+// pContext - handle to instance data
+// pParam - pointer to parameter
+// pValue - pointer to value
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue){
+ int status = 0;
+ int16_t level;
+ int16_t ratio;
+ uint32_t time;
+ t_reverb_settings *pProperties;
+ int32_t *pParamTemp = (int32_t *)pParam;
+ int32_t param = *pParamTemp++;
+
+ //ALOGV("\tReverb_setParameter start");
+ if (pContext->preset) {
+ if (param != REVERB_PARAM_PRESET) {
+ return -EINVAL;
+ }
+
+ uint16_t preset = *(uint16_t *)pValue;
+ ALOGV("set REVERB_PARAM_PRESET, preset %d", preset);
+ if (preset > REVERB_PRESET_LAST) {
+ return -EINVAL;
+ }
+ pContext->nextPreset = preset;
+ return 0;
+ }
+
+ switch (param){
+ case REVERB_PARAM_PROPERTIES:
+ ALOGV("\tReverb_setParameter() REVERB_PARAM_PROPERTIES");
+ pProperties = (t_reverb_settings *) pValue;
+ ReverbSetRoomLevel(pContext, pProperties->roomLevel);
+ ReverbSetRoomHfLevel(pContext, pProperties->roomHFLevel);
+ ReverbSetDecayTime(pContext, pProperties->decayTime);
+ ReverbSetDecayHfRatio(pContext, pProperties->decayHFRatio);
+ ReverbSetReverbLevel(pContext, pProperties->reverbLevel);
+ ReverbSetDiffusion(pContext, pProperties->diffusion);
+ ReverbSetDensity(pContext, pProperties->density);
+ break;
+ case REVERB_PARAM_ROOM_LEVEL:
+ level = *(int16_t *)pValue;
+ //ALOGV("\tReverb_setParameter() REVERB_PARAM_ROOM_LEVEL value is %d", level);
+ //ALOGV("\tReverb_setParameter() Calling ReverbSetRoomLevel");
+ ReverbSetRoomLevel(pContext, level);
+ //ALOGV("\tReverb_setParameter() Called ReverbSetRoomLevel");
+ break;
+ case REVERB_PARAM_ROOM_HF_LEVEL:
+ level = *(int16_t *)pValue;
+ //ALOGV("\tReverb_setParameter() REVERB_PARAM_ROOM_HF_LEVEL value is %d", level);
+ //ALOGV("\tReverb_setParameter() Calling ReverbSetRoomHfLevel");
+ ReverbSetRoomHfLevel(pContext, level);
+ //ALOGV("\tReverb_setParameter() Called ReverbSetRoomHfLevel");
+ break;
+ case REVERB_PARAM_DECAY_TIME:
+ time = *(uint32_t *)pValue;
+ //ALOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_TIME value is %d", time);
+ //ALOGV("\tReverb_setParameter() Calling ReverbSetDecayTime");
+ ReverbSetDecayTime(pContext, time);
+ //ALOGV("\tReverb_setParameter() Called ReverbSetDecayTime");
+ break;
+ case REVERB_PARAM_DECAY_HF_RATIO:
+ ratio = *(int16_t *)pValue;
+ //ALOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_HF_RATIO value is %d", ratio);
+ //ALOGV("\tReverb_setParameter() Calling ReverbSetDecayHfRatio");
+ ReverbSetDecayHfRatio(pContext, ratio);
+ //ALOGV("\tReverb_setParameter() Called ReverbSetDecayHfRatio");
+ break;
+ case REVERB_PARAM_REVERB_LEVEL:
+ level = *(int16_t *)pValue;
+ //ALOGV("\tReverb_setParameter() REVERB_PARAM_REVERB_LEVEL value is %d", level);
+ //ALOGV("\tReverb_setParameter() Calling ReverbSetReverbLevel");
+ ReverbSetReverbLevel(pContext, level);
+ //ALOGV("\tReverb_setParameter() Called ReverbSetReverbLevel");
+ break;
+ case REVERB_PARAM_DIFFUSION:
+ ratio = *(int16_t *)pValue;
+ //ALOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DIFFUSION value is %d", ratio);
+ //ALOGV("\tReverb_setParameter() Calling ReverbSetDiffusion");
+ ReverbSetDiffusion(pContext, ratio);
+ //ALOGV("\tReverb_setParameter() Called ReverbSetDiffusion");
+ break;
+ case REVERB_PARAM_DENSITY:
+ ratio = *(int16_t *)pValue;
+ //ALOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DENSITY value is %d", ratio);
+ //ALOGV("\tReverb_setParameter() Calling ReverbSetDensity");
+ ReverbSetDensity(pContext, ratio);
+ //ALOGV("\tReverb_setParameter() Called ReverbSetDensity");
+ break;
+ break;
+ case REVERB_PARAM_REFLECTIONS_LEVEL:
+ case REVERB_PARAM_REFLECTIONS_DELAY:
+ case REVERB_PARAM_REVERB_DELAY:
+ break;
+ default:
+ ALOGV("\tLVM_ERROR : Reverb_setParameter() invalid param %d", param);
+ break;
+ }
+
+ //ALOGV("\tReverb_setParameter end");
+ return status;
+} /* end Reverb_setParameter */
+
+} // namespace
+} // namespace
+
+extern "C" {
+/* Effect Control Interface Implementation: Process */
+int Reverb_process(effect_handle_t self,
+ audio_buffer_t *inBuffer,
+ audio_buffer_t *outBuffer){
+ android::ReverbContext * pContext = (android::ReverbContext *) self;
+ int status = 0;
+
+ if (pContext == NULL){
+ ALOGV("\tLVM_ERROR : Reverb_process() ERROR pContext == NULL");
+ return -EINVAL;
+ }
+ if (inBuffer == NULL || inBuffer->raw == NULL ||
+ outBuffer == NULL || outBuffer->raw == NULL ||
+ inBuffer->frameCount != outBuffer->frameCount){
+ ALOGV("\tLVM_ERROR : Reverb_process() ERROR NULL INPUT POINTER OR FRAME COUNT IS WRONG");
+ return -EINVAL;
+ }
+ //ALOGV("\tReverb_process() Calling process with %d frames", outBuffer->frameCount);
+ /* Process all the available frames, block processing is handled internalLY by the LVM bundle */
+ status = process( (LVM_INT16 *)inBuffer->raw,
+ (LVM_INT16 *)outBuffer->raw,
+ outBuffer->frameCount,
+ pContext);
+
+ if (pContext->bEnabled == LVM_FALSE) {
+ if (pContext->SamplesToExitCount > 0) {
+ pContext->SamplesToExitCount -= outBuffer->frameCount;
+ } else {
+ status = -ENODATA;
+ }
+ }
+
+ return status;
+} /* end Reverb_process */
+
+/* Effect Control Interface Implementation: Command */
+int Reverb_command(effect_handle_t self,
+ uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData){
+ android::ReverbContext * pContext = (android::ReverbContext *) self;
+ int retsize;
+ LVREV_ControlParams_st ActiveParams; /* Current control Parameters */
+ LVREV_ReturnStatus_en LvmStatus=LVREV_SUCCESS; /* Function call status */
+
+
+ if (pContext == NULL){
+ ALOGV("\tLVM_ERROR : Reverb_command ERROR pContext == NULL");
+ return -EINVAL;
+ }
+
+ //ALOGV("\tReverb_command INPUTS are: command %d cmdSize %d",cmdCode, cmdSize);
+
+ switch (cmdCode){
+ case EFFECT_CMD_INIT:
+ //ALOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_INIT start");
+
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_INIT: ERROR");
+ return -EINVAL;
+ }
+ *(int *) pReplyData = 0;
+ break;
+
+ case EFFECT_CMD_SET_CONFIG:
+ //ALOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_SET_CONFIG start");
+ if (pCmdData == NULL ||
+ cmdSize != sizeof(effect_config_t) ||
+ pReplyData == NULL ||
+ *replySize != sizeof(int)) {
+ ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_SET_CONFIG: ERROR");
+ return -EINVAL;
+ }
+ *(int *) pReplyData = android::Reverb_setConfig(pContext,
+ (effect_config_t *) pCmdData);
+ break;
+
+ case EFFECT_CMD_GET_CONFIG:
+ if (pReplyData == NULL ||
+ *replySize != sizeof(effect_config_t)) {
+ ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_GET_CONFIG: ERROR");
+ return -EINVAL;
+ }
+
+ android::Reverb_getConfig(pContext, (effect_config_t *)pReplyData);
+ break;
+
+ case EFFECT_CMD_RESET:
+ //ALOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_RESET start");
+ Reverb_setConfig(pContext, &pContext->config);
+ break;
+
+ case EFFECT_CMD_GET_PARAM:{
+ //ALOGV("\tReverb_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))){
+ ALOGV("\tLVM_ERROR : Reverb_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::Reverb_getParameter(pContext,
+ (void *)p->data,
+ (size_t *)&p->vsize,
+ p->data + voffset);
+
+ *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+ //ALOGV("\tReverb_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));
+
+ } break;
+ case EFFECT_CMD_SET_PARAM:{
+
+ //ALOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_SET_PARAM start");
+ //ALOGV("\tReverb_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 != (int)sizeof(int32_t)) {
+ ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR");
+ return -EINVAL;
+ }
+
+ effect_param_t *p = (effect_param_t *) pCmdData;
+
+ if (p->psize != sizeof(int32_t)){
+ ALOGV("\t4LVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
+ return -EINVAL;
+ }
+
+ //ALOGV("\tn5Reverb_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::Reverb_setParameter(pContext,
+ (void *)p->data,
+ p->data + p->psize);
+ } break;
+
+ case EFFECT_CMD_ENABLE:
+ //ALOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_ENABLE start");
+
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_ENABLE: ERROR");
+ return -EINVAL;
+ }
+ if(pContext->bEnabled == LVM_TRUE){
+ ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
+ return -EINVAL;
+ }
+ *(int *)pReplyData = 0;
+ pContext->bEnabled = LVM_TRUE;
+ /* Get the current settings */
+ LvmStatus = LVREV_GetControlParameters(pContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVREV_GetControlParameters", "EFFECT_CMD_ENABLE")
+ pContext->SamplesToExitCount =
+ (ActiveParams.T60 * pContext->config.inputCfg.samplingRate)/1000;
+ // force no volume ramp for first buffer processed after enabling the effect
+ pContext->volumeMode = android::REVERB_VOLUME_FLAT;
+ //ALOGV("\tEFFECT_CMD_ENABLE SamplesToExitCount = %d", pContext->SamplesToExitCount);
+ break;
+ case EFFECT_CMD_DISABLE:
+ //ALOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_DISABLE start");
+
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_DISABLE: ERROR");
+ return -EINVAL;
+ }
+ if(pContext->bEnabled == LVM_FALSE){
+ ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
+ return -EINVAL;
+ }
+ *(int *)pReplyData = 0;
+ pContext->bEnabled = LVM_FALSE;
+ break;
+
+ case EFFECT_CMD_SET_VOLUME:
+ if (pCmdData == NULL ||
+ cmdSize != 2 * sizeof(uint32_t)) {
+ ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "EFFECT_CMD_SET_VOLUME: ERROR");
+ return -EINVAL;
+ }
+
+
+ if (pReplyData != NULL) { // we have volume control
+ pContext->leftVolume = (LVM_INT16)((*(uint32_t *)pCmdData + (1 << 11)) >> 12);
+ pContext->rightVolume = (LVM_INT16)((*((uint32_t *)pCmdData + 1) + (1 << 11)) >> 12);
+ *(uint32_t *)pReplyData = (1 << 24);
+ *((uint32_t *)pReplyData + 1) = (1 << 24);
+ if (pContext->volumeMode == android::REVERB_VOLUME_OFF) {
+ // force no volume ramp for first buffer processed after getting volume control
+ pContext->volumeMode = android::REVERB_VOLUME_FLAT;
+ }
+ } else { // we don't have volume control
+ pContext->leftVolume = REVERB_UNIT_VOLUME;
+ pContext->rightVolume = REVERB_UNIT_VOLUME;
+ pContext->volumeMode = android::REVERB_VOLUME_OFF;
+ }
+ ALOGV("EFFECT_CMD_SET_VOLUME left %d, right %d mode %d",
+ pContext->leftVolume, pContext->rightVolume, pContext->volumeMode);
+ break;
+
+ case EFFECT_CMD_SET_DEVICE:
+ case EFFECT_CMD_SET_AUDIO_MODE:
+ //ALOGV("\tReverb_command cmdCode Case: "
+ // "EFFECT_CMD_SET_DEVICE/EFFECT_CMD_SET_VOLUME/EFFECT_CMD_SET_AUDIO_MODE start");
+ break;
+
+ default:
+ ALOGV("\tLVM_ERROR : Reverb_command cmdCode Case: "
+ "DEFAULT start %d ERROR",cmdCode);
+ return -EINVAL;
+ }
+
+ //ALOGV("\tReverb_command end\n\n");
+ return 0;
+} /* end Reverb_command */
+
+/* Effect Control Interface Implementation: get_descriptor */
+int Reverb_getDescriptor(effect_handle_t self,
+ effect_descriptor_t *pDescriptor)
+{
+ android::ReverbContext * pContext = (android::ReverbContext *)self;
+ const effect_descriptor_t *desc;
+
+ if (pContext == NULL || pDescriptor == NULL) {
+ ALOGV("Reverb_getDescriptor() invalid param");
+ return -EINVAL;
+ }
+
+ if (pContext->auxiliary) {
+ if (pContext->preset) {
+ desc = &android::gAuxPresetReverbDescriptor;
+ } else {
+ desc = &android::gAuxEnvReverbDescriptor;
+ }
+ } else {
+ if (pContext->preset) {
+ desc = &android::gInsertPresetReverbDescriptor;
+ } else {
+ desc = &android::gInsertEnvReverbDescriptor;
+ }
+ }
+
+ memcpy(pDescriptor, desc, sizeof(effect_descriptor_t));
+
+ return 0;
+} /* end Reverb_getDescriptor */
+
+// effect_handle_t interface implementation for Reverb effect
+const struct effect_interface_s gReverbInterface = {
+ Reverb_process,
+ Reverb_command,
+ Reverb_getDescriptor,
+ NULL,
+}; /* end gReverbInterface */
+
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
+ tag : AUDIO_EFFECT_LIBRARY_TAG,
+ version : EFFECT_LIBRARY_API_VERSION,
+ name : "Reverb Library",
+ implementor : "NXP Software Ltd.",
+ query_num_effects : android::EffectQueryNumberEffects,
+ query_effect : android::EffectQueryEffect,
+ create_effect : android::EffectCreate,
+ release_effect : android::EffectRelease,
+ get_descriptor : android::EffectGetDescriptor,
+};
+
+}
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h
new file mode 100644
index 0000000..7c15b18
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.h
@@ -0,0 +1,46 @@
+/*
+ * 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_EFFECTREVERB_H_
+#define ANDROID_EFFECTREVERB_H_
+
+#include <audio_effects/effect_environmentalreverb.h>
+#include <audio_effects/effect_presetreverb.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#define MAX_NUM_BANDS 5
+#define MAX_CALL_SIZE 256
+#define LVREV_MAX_T60 7000
+#define LVREV_MAX_REVERB_LEVEL 2000
+#define LVREV_MAX_FRAME_SIZE 2560
+#define LVREV_CUP_LOAD_ARM9E 470 // Expressed in 0.1 MIPS
+#define LVREV_MEM_USAGE 71+(LVREV_MAX_FRAME_SIZE>>7) // Expressed in kB
+//#define LVM_PCM
+
+typedef struct _LPFPair_t
+{
+ int16_t Room_HF;
+ int16_t LPF;
+} LPFPair_t;
+#if __cplusplus
+} // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTREVERB_H_*/
diff --git a/media/libeffects/preprocessing/Android.mk b/media/libeffects/preprocessing/Android.mk
new file mode 100755
index 0000000..c13b9d4
--- /dev/null
+++ b/media/libeffects/preprocessing/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH:= $(call my-dir)
+
+# audio preprocessing wrapper
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= libaudiopreprocessing
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+
+LOCAL_SRC_FILES:= \
+ PreProcessing.cpp
+
+LOCAL_C_INCLUDES += \
+ external/webrtc/src \
+ external/webrtc/src/modules/interface \
+ external/webrtc/src/modules/audio_processing/interface \
+ $(call include-path-for, audio-effects)
+
+LOCAL_C_INCLUDES += $(call include-path-for, speex)
+
+LOCAL_SHARED_LIBRARIES := \
+ libwebrtc_audio_preprocessing \
+ libspeexresampler \
+ libutils
+
+ifeq ($(TARGET_SIMULATOR),true)
+LOCAL_LDLIBS += -ldl
+else
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
new file mode 100755
index 0000000..1d76f62
--- /dev/null
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -0,0 +1,1666 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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>
+#define LOG_TAG "PreProcessing"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+#include <utils/Timers.h>
+#include <hardware/audio_effect.h>
+#include <audio_effects/effect_aec.h>
+#include <audio_effects/effect_agc.h>
+#include <audio_effects/effect_ns.h>
+#include <module_common_types.h>
+#include <audio_processing.h>
+#include "speex/speex_resampler.h"
+
+
+//------------------------------------------------------------------------------
+// local definitions
+//------------------------------------------------------------------------------
+
+// maximum number of sessions
+#define PREPROC_NUM_SESSIONS 8
+
+// types of pre processing modules
+enum preproc_id
+{
+ PREPROC_AGC, // Automatic Gain Control
+ PREPROC_AEC, // Acoustic Echo Canceler
+ PREPROC_NS, // Noise Suppressor
+ PREPROC_NUM_EFFECTS
+};
+
+// Session state
+enum preproc_session_state {
+ PREPROC_SESSION_STATE_INIT, // initialized
+ PREPROC_SESSION_STATE_CONFIG // configuration received
+};
+
+// Effect/Preprocessor state
+enum preproc_effect_state {
+ PREPROC_EFFECT_STATE_INIT, // initialized
+ PREPROC_EFFECT_STATE_CREATED, // webRTC engine created
+ PREPROC_EFFECT_STATE_CONFIG, // configuration received/disabled
+ PREPROC_EFFECT_STATE_ACTIVE // active/enabled
+};
+
+// handle on webRTC engine
+typedef void* preproc_fx_handle_t;
+
+typedef struct preproc_session_s preproc_session_t;
+typedef struct preproc_effect_s preproc_effect_t;
+typedef struct preproc_ops_s preproc_ops_t;
+
+// Effect operation table. Functions for all pre processors are declared in sPreProcOps[] table.
+// Function pointer can be null if no action required.
+struct preproc_ops_s {
+ int (* create)(preproc_effect_t *fx);
+ int (* init)(preproc_effect_t *fx);
+ int (* reset)(preproc_effect_t *fx);
+ void (* enable)(preproc_effect_t *fx);
+ void (* disable)(preproc_effect_t *fx);
+ int (* set_parameter)(preproc_effect_t *fx, void *param, void *value);
+ int (* get_parameter)(preproc_effect_t *fx, void *param, size_t *size, void *value);
+ int (* set_device)(preproc_effect_t *fx, uint32_t device);
+};
+
+// Effect context
+struct preproc_effect_s {
+ const struct effect_interface_s *itfe;
+ uint32_t procId; // type of pre processor (enum preproc_id)
+ uint32_t state; // current state (enum preproc_effect_state)
+ preproc_session_t *session; // session the effect is on
+ const preproc_ops_t *ops; // effect ops table
+ preproc_fx_handle_t engine; // handle on webRTC engine
+};
+
+// Session context
+struct preproc_session_s {
+ struct preproc_effect_s effects[PREPROC_NUM_EFFECTS]; // effects in this session
+ uint32_t state; // current state (enum preproc_session_state)
+ int id; // audio session ID
+ int io; // handle of input stream this session is on
+ webrtc::AudioProcessing* apm; // handle on webRTC audio processing module (APM)
+ size_t apmFrameCount; // buffer size for webRTC process (10 ms)
+ uint32_t apmSamplingRate; // webRTC APM sampling rate (8/16 or 32 kHz)
+ size_t frameCount; // buffer size before input resampler ( <=> apmFrameCount)
+ uint32_t samplingRate; // sampling rate at effect process interface
+ uint32_t inChannelCount; // input channel count
+ uint32_t outChannelCount; // output channel count
+ uint32_t createdMsk; // bit field containing IDs of crested pre processors
+ uint32_t enabledMsk; // bit field containing IDs of enabled pre processors
+ uint32_t processedMsk; // bit field containing IDs of pre processors already
+ // processed in current round
+ webrtc::AudioFrame *procFrame; // audio frame passed to webRTC AMP ProcessStream()
+ int16_t *inBuf; // input buffer used when resampling
+ size_t inBufSize; // input buffer size in frames
+ size_t framesIn; // number of frames in input buffer
+ SpeexResamplerState *inResampler; // handle on input speex resampler
+ int16_t *outBuf; // output buffer used when resampling
+ size_t outBufSize; // output buffer size in frames
+ size_t framesOut; // number of frames in output buffer
+ SpeexResamplerState *outResampler; // handle on output speex resampler
+ uint32_t revChannelCount; // number of channels on reverse stream
+ uint32_t revEnabledMsk; // bit field containing IDs of enabled pre processors
+ // with reverse channel
+ uint32_t revProcessedMsk; // bit field containing IDs of pre processors with reverse
+ // channel already processed in current round
+ webrtc::AudioFrame *revFrame; // audio frame passed to webRTC AMP AnalyzeReverseStream()
+ int16_t *revBuf; // reverse channel input buffer
+ size_t revBufSize; // reverse channel input buffer size
+ size_t framesRev; // number of frames in reverse channel input buffer
+ SpeexResamplerState *revResampler; // handle on reverse channel input speex resampler
+};
+
+//------------------------------------------------------------------------------
+// Effect descriptors
+//------------------------------------------------------------------------------
+
+// UUIDs for effect types have been generated from http://www.itu.int/ITU-T/asn1/uuid.html
+// as the pre processing effects are not defined by OpenSL ES
+
+// Automatic Gain Control
+static const effect_descriptor_t sAgcDescriptor = {
+ { 0x0a8abfe0, 0x654c, 0x11e0, 0xba26, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
+ { 0xaa8130e0, 0x66fc, 0x11e0, 0xbad0, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
+ EFFECT_CONTROL_API_VERSION,
+ (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
+ 0, //FIXME indicate CPU load
+ 0, //FIXME indicate memory usage
+ "Automatic Gain Control",
+ "The Android Open Source Project"
+};
+
+// Acoustic Echo Cancellation
+static const effect_descriptor_t sAecDescriptor = {
+ { 0x7b491460, 0x8d4d, 0x11e0, 0xbd61, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
+ { 0xbb392ec0, 0x8d4d, 0x11e0, 0xa896, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
+ EFFECT_CONTROL_API_VERSION,
+ (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
+ 0, //FIXME indicate CPU load
+ 0, //FIXME indicate memory usage
+ "Acoustic Echo Canceler",
+ "The Android Open Source Project"
+};
+
+// Noise suppression
+static const effect_descriptor_t sNsDescriptor = {
+ { 0x58b4b260, 0x8e06, 0x11e0, 0xaa8e, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // type
+ { 0xc06c8400, 0x8e06, 0x11e0, 0x9cb6, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } }, // uuid
+ EFFECT_CONTROL_API_VERSION,
+ (EFFECT_FLAG_TYPE_PRE_PROC|EFFECT_FLAG_DEVICE_IND),
+ 0, //FIXME indicate CPU load
+ 0, //FIXME indicate memory usage
+ "Noise Suppression",
+ "The Android Open Source Project"
+};
+
+
+static const effect_descriptor_t *sDescriptors[PREPROC_NUM_EFFECTS] = {
+ &sAgcDescriptor,
+ &sAecDescriptor,
+ &sNsDescriptor
+};
+
+//------------------------------------------------------------------------------
+// Helper functions
+//------------------------------------------------------------------------------
+
+const effect_uuid_t * const sUuidToPreProcTable[PREPROC_NUM_EFFECTS] = {
+ FX_IID_AGC,
+ FX_IID_AEC,
+ FX_IID_NS
+};
+
+
+const effect_uuid_t * ProcIdToUuid(int procId)
+{
+ if (procId >= PREPROC_NUM_EFFECTS) {
+ return EFFECT_UUID_NULL;
+ }
+ return sUuidToPreProcTable[procId];
+}
+
+uint32_t UuidToProcId(const effect_uuid_t * uuid)
+{
+ size_t i;
+ for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
+ if (memcmp(uuid, sUuidToPreProcTable[i], sizeof(*uuid)) == 0) {
+ break;
+ }
+ }
+ return i;
+}
+
+bool HasReverseStream(uint32_t procId)
+{
+ if (procId == PREPROC_AEC) {
+ return true;
+ }
+ return false;
+}
+
+
+//------------------------------------------------------------------------------
+// Automatic Gain Control (AGC)
+//------------------------------------------------------------------------------
+
+static const int kAgcDefaultTargetLevel = 3;
+static const int kAgcDefaultCompGain = 9;
+static const bool kAgcDefaultLimiter = true;
+
+int AgcInit (preproc_effect_t *effect)
+{
+ ALOGV("AgcInit");
+ webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
+ agc->set_mode(webrtc::GainControl::kFixedDigital);
+ agc->set_target_level_dbfs(kAgcDefaultTargetLevel);
+ agc->set_compression_gain_db(kAgcDefaultCompGain);
+ agc->enable_limiter(kAgcDefaultLimiter);
+ return 0;
+}
+
+int AgcCreate(preproc_effect_t *effect)
+{
+ webrtc::GainControl *agc = effect->session->apm->gain_control();
+ ALOGV("AgcCreate got agc %p", agc);
+ if (agc == NULL) {
+ ALOGW("AgcCreate Error");
+ return -ENOMEM;
+ }
+ effect->engine = static_cast<preproc_fx_handle_t>(agc);
+ AgcInit(effect);
+ return 0;
+}
+
+int AgcGetParameter(preproc_effect_t *effect,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue)
+{
+ int status = 0;
+ uint32_t param = *(uint32_t *)pParam;
+ t_agc_settings *pProperties = (t_agc_settings *)pValue;
+ webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
+
+ switch (param) {
+ case AGC_PARAM_TARGET_LEVEL:
+ case AGC_PARAM_COMP_GAIN:
+ if (*pValueSize < sizeof(int16_t)) {
+ *pValueSize = 0;
+ return -EINVAL;
+ }
+ break;
+ case AGC_PARAM_LIMITER_ENA:
+ if (*pValueSize < sizeof(bool)) {
+ *pValueSize = 0;
+ return -EINVAL;
+ }
+ break;
+ case AGC_PARAM_PROPERTIES:
+ if (*pValueSize < sizeof(t_agc_settings)) {
+ *pValueSize = 0;
+ return -EINVAL;
+ }
+ break;
+
+ default:
+ ALOGW("AgcGetParameter() unknown param %08x", param);
+ status = -EINVAL;
+ break;
+ }
+
+ switch (param) {
+ case AGC_PARAM_TARGET_LEVEL:
+ *(int16_t *) pValue = (int16_t)(agc->target_level_dbfs() * -100);
+ ALOGV("AgcGetParameter() target level %d milliBels", *(int16_t *) pValue);
+ break;
+ case AGC_PARAM_COMP_GAIN:
+ *(int16_t *) pValue = (int16_t)(agc->compression_gain_db() * 100);
+ ALOGV("AgcGetParameter() comp gain %d milliBels", *(int16_t *) pValue);
+ break;
+ case AGC_PARAM_LIMITER_ENA:
+ *(bool *) pValue = (bool)agc->is_limiter_enabled();
+ ALOGV("AgcGetParameter() limiter enabled %s",
+ (*(int16_t *) pValue != 0) ? "true" : "false");
+ break;
+ case AGC_PARAM_PROPERTIES:
+ pProperties->targetLevel = (int16_t)(agc->target_level_dbfs() * -100);
+ pProperties->compGain = (int16_t)(agc->compression_gain_db() * 100);
+ pProperties->limiterEnabled = (bool)agc->is_limiter_enabled();
+ break;
+ default:
+ ALOGW("AgcGetParameter() unknown param %d", param);
+ status = -EINVAL;
+ break;
+ }
+ return status;
+}
+
+int AgcSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
+{
+ int status = 0;
+ uint32_t param = *(uint32_t *)pParam;
+ t_agc_settings *pProperties = (t_agc_settings *)pValue;
+ webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
+
+ switch (param) {
+ case AGC_PARAM_TARGET_LEVEL:
+ ALOGV("AgcSetParameter() target level %d milliBels", *(int16_t *)pValue);
+ status = agc->set_target_level_dbfs(-(*(int16_t *)pValue / 100));
+ break;
+ case AGC_PARAM_COMP_GAIN:
+ ALOGV("AgcSetParameter() comp gain %d milliBels", *(int16_t *)pValue);
+ status = agc->set_compression_gain_db(*(int16_t *)pValue / 100);
+ break;
+ case AGC_PARAM_LIMITER_ENA:
+ ALOGV("AgcSetParameter() limiter enabled %s", *(bool *)pValue ? "true" : "false");
+ status = agc->enable_limiter(*(bool *)pValue);
+ break;
+ case AGC_PARAM_PROPERTIES:
+ ALOGV("AgcSetParameter() properties level %d, gain %d limiter %d",
+ pProperties->targetLevel,
+ pProperties->compGain,
+ pProperties->limiterEnabled);
+ status = agc->set_target_level_dbfs(-(pProperties->targetLevel / 100));
+ if (status != 0) break;
+ status = agc->set_compression_gain_db(pProperties->compGain / 100);
+ if (status != 0) break;
+ status = agc->enable_limiter(pProperties->limiterEnabled);
+ break;
+ default:
+ ALOGW("AgcSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
+ status = -EINVAL;
+ break;
+ }
+
+ ALOGV("AgcSetParameter() done status %d", status);
+
+ return status;
+}
+
+void AgcEnable(preproc_effect_t *effect)
+{
+ webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
+ ALOGV("AgcEnable agc %p", agc);
+ agc->Enable(true);
+}
+
+void AgcDisable(preproc_effect_t *effect)
+{
+ ALOGV("AgcDisable");
+ webrtc::GainControl *agc = static_cast<webrtc::GainControl *>(effect->engine);
+ agc->Enable(false);
+}
+
+
+static const preproc_ops_t sAgcOps = {
+ AgcCreate,
+ AgcInit,
+ NULL,
+ AgcEnable,
+ AgcDisable,
+ AgcSetParameter,
+ AgcGetParameter,
+ NULL
+};
+
+
+//------------------------------------------------------------------------------
+// Acoustic Echo Canceler (AEC)
+//------------------------------------------------------------------------------
+
+static const webrtc::EchoControlMobile::RoutingMode kAecDefaultMode =
+ webrtc::EchoControlMobile::kEarpiece;
+static const bool kAecDefaultComfortNoise = true;
+
+int AecInit (preproc_effect_t *effect)
+{
+ ALOGV("AecInit");
+ webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
+ aec->set_routing_mode(kAecDefaultMode);
+ aec->enable_comfort_noise(kAecDefaultComfortNoise);
+ return 0;
+}
+
+int AecCreate(preproc_effect_t *effect)
+{
+ webrtc::EchoControlMobile *aec = effect->session->apm->echo_control_mobile();
+ ALOGV("AecCreate got aec %p", aec);
+ if (aec == NULL) {
+ ALOGW("AgcCreate Error");
+ return -ENOMEM;
+ }
+ effect->engine = static_cast<preproc_fx_handle_t>(aec);
+ AecInit (effect);
+ return 0;
+}
+
+int AecGetParameter(preproc_effect_t *effect,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue)
+{
+ int status = 0;
+ uint32_t param = *(uint32_t *)pParam;
+
+ if (*pValueSize < sizeof(uint32_t)) {
+ return -EINVAL;
+ }
+ switch (param) {
+ case AEC_PARAM_ECHO_DELAY:
+ case AEC_PARAM_PROPERTIES:
+ *(uint32_t *)pValue = 1000 * effect->session->apm->stream_delay_ms();
+ ALOGV("AecGetParameter() echo delay %d us", *(uint32_t *)pValue);
+ break;
+ default:
+ ALOGW("AecGetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
+ status = -EINVAL;
+ break;
+ }
+ return status;
+}
+
+int AecSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
+{
+ int status = 0;
+ uint32_t param = *(uint32_t *)pParam;
+ uint32_t value = *(uint32_t *)pValue;
+
+ switch (param) {
+ case AEC_PARAM_ECHO_DELAY:
+ case AEC_PARAM_PROPERTIES:
+ status = effect->session->apm->set_stream_delay_ms(value/1000);
+ ALOGV("AecSetParameter() echo delay %d us, status %d", value, status);
+ break;
+ default:
+ ALOGW("AecSetParameter() unknown param %08x value %08x", param, *(uint32_t *)pValue);
+ status = -EINVAL;
+ break;
+ }
+ return status;
+}
+
+void AecEnable(preproc_effect_t *effect)
+{
+ webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
+ ALOGV("AecEnable aec %p", aec);
+ aec->Enable(true);
+}
+
+void AecDisable(preproc_effect_t *effect)
+{
+ ALOGV("AecDisable");
+ webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
+ aec->Enable(false);
+}
+
+int AecSetDevice(preproc_effect_t *effect, uint32_t device)
+{
+ ALOGV("AecSetDevice %08x", device);
+ webrtc::EchoControlMobile *aec = static_cast<webrtc::EchoControlMobile *>(effect->engine);
+ webrtc::EchoControlMobile::RoutingMode mode = webrtc::EchoControlMobile::kQuietEarpieceOrHeadset;
+
+ switch(device) {
+ case AUDIO_DEVICE_OUT_EARPIECE:
+ mode = webrtc::EchoControlMobile::kEarpiece;
+ break;
+ case AUDIO_DEVICE_OUT_SPEAKER:
+ mode = webrtc::EchoControlMobile::kSpeakerphone;
+ break;
+ case AUDIO_DEVICE_OUT_WIRED_HEADSET:
+ case AUDIO_DEVICE_OUT_WIRED_HEADPHONE:
+ default:
+ break;
+ }
+ aec->set_routing_mode(mode);
+ return 0;
+}
+
+static const preproc_ops_t sAecOps = {
+ AecCreate,
+ AecInit,
+ NULL,
+ AecEnable,
+ AecDisable,
+ AecSetParameter,
+ AecGetParameter,
+ AecSetDevice
+};
+
+//------------------------------------------------------------------------------
+// Noise Suppression (NS)
+//------------------------------------------------------------------------------
+
+static const webrtc::NoiseSuppression::Level kNsDefaultLevel = webrtc::NoiseSuppression::kModerate;
+
+int NsInit (preproc_effect_t *effect)
+{
+ ALOGV("NsInit");
+ webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
+ ns->set_level(kNsDefaultLevel);
+ return 0;
+}
+
+int NsCreate(preproc_effect_t *effect)
+{
+ webrtc::NoiseSuppression *ns = effect->session->apm->noise_suppression();
+ ALOGV("NsCreate got ns %p", ns);
+ if (ns == NULL) {
+ ALOGW("AgcCreate Error");
+ return -ENOMEM;
+ }
+ effect->engine = static_cast<preproc_fx_handle_t>(ns);
+ NsInit (effect);
+ return 0;
+}
+
+int NsGetParameter(preproc_effect_t *effect,
+ void *pParam,
+ size_t *pValueSize,
+ void *pValue)
+{
+ int status = 0;
+ return status;
+}
+
+int NsSetParameter (preproc_effect_t *effect, void *pParam, void *pValue)
+{
+ int status = 0;
+ return status;
+}
+
+void NsEnable(preproc_effect_t *effect)
+{
+ webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
+ ALOGV("NsEnable ns %p", ns);
+ ns->Enable(true);
+}
+
+void NsDisable(preproc_effect_t *effect)
+{
+ ALOGV("NsDisable");
+ webrtc::NoiseSuppression *ns = static_cast<webrtc::NoiseSuppression *>(effect->engine);
+ ns->Enable(false);
+}
+
+static const preproc_ops_t sNsOps = {
+ NsCreate,
+ NsInit,
+ NULL,
+ NsEnable,
+ NsDisable,
+ NsSetParameter,
+ NsGetParameter,
+ NULL
+};
+
+
+static const preproc_ops_t *sPreProcOps[PREPROC_NUM_EFFECTS] = {
+ &sAgcOps,
+ &sAecOps,
+ &sNsOps
+};
+
+
+//------------------------------------------------------------------------------
+// Effect functions
+//------------------------------------------------------------------------------
+
+void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled);
+
+extern "C" const struct effect_interface_s sEffectInterface;
+extern "C" const struct effect_interface_s sEffectInterfaceReverse;
+
+#define BAD_STATE_ABORT(from, to) \
+ LOG_ALWAYS_FATAL("Bad state transition from %d to %d", from, to);
+
+int Effect_SetState(preproc_effect_t *effect, uint32_t state)
+{
+ int status = 0;
+ ALOGV("Effect_SetState proc %d, new %d old %d", effect->procId, state, effect->state);
+ switch(state) {
+ case PREPROC_EFFECT_STATE_INIT:
+ switch(effect->state) {
+ case PREPROC_EFFECT_STATE_ACTIVE:
+ effect->ops->disable(effect);
+ Session_SetProcEnabled(effect->session, effect->procId, false);
+ case PREPROC_EFFECT_STATE_CONFIG:
+ case PREPROC_EFFECT_STATE_CREATED:
+ case PREPROC_EFFECT_STATE_INIT:
+ break;
+ default:
+ BAD_STATE_ABORT(effect->state, state);
+ }
+ break;
+ case PREPROC_EFFECT_STATE_CREATED:
+ switch(effect->state) {
+ case PREPROC_EFFECT_STATE_INIT:
+ status = effect->ops->create(effect);
+ break;
+ case PREPROC_EFFECT_STATE_CREATED:
+ case PREPROC_EFFECT_STATE_ACTIVE:
+ case PREPROC_EFFECT_STATE_CONFIG:
+ ALOGE("Effect_SetState invalid transition");
+ status = -ENOSYS;
+ break;
+ default:
+ BAD_STATE_ABORT(effect->state, state);
+ }
+ break;
+ case PREPROC_EFFECT_STATE_CONFIG:
+ switch(effect->state) {
+ case PREPROC_EFFECT_STATE_INIT:
+ ALOGE("Effect_SetState invalid transition");
+ status = -ENOSYS;
+ break;
+ case PREPROC_EFFECT_STATE_ACTIVE:
+ effect->ops->disable(effect);
+ Session_SetProcEnabled(effect->session, effect->procId, false);
+ break;
+ case PREPROC_EFFECT_STATE_CREATED:
+ case PREPROC_EFFECT_STATE_CONFIG:
+ break;
+ default:
+ BAD_STATE_ABORT(effect->state, state);
+ }
+ break;
+ case PREPROC_EFFECT_STATE_ACTIVE:
+ switch(effect->state) {
+ case PREPROC_EFFECT_STATE_INIT:
+ case PREPROC_EFFECT_STATE_CREATED:
+ case PREPROC_EFFECT_STATE_ACTIVE:
+ ALOGE("Effect_SetState invalid transition");
+ status = -ENOSYS;
+ break;
+ case PREPROC_EFFECT_STATE_CONFIG:
+ effect->ops->enable(effect);
+ Session_SetProcEnabled(effect->session, effect->procId, true);
+ break;
+ default:
+ BAD_STATE_ABORT(effect->state, state);
+ }
+ break;
+ default:
+ BAD_STATE_ABORT(effect->state, state);
+ }
+ if (status == 0) {
+ effect->state = state;
+ }
+ return status;
+}
+
+int Effect_Init(preproc_effect_t *effect, uint32_t procId)
+{
+ if (HasReverseStream(procId)) {
+ effect->itfe = &sEffectInterfaceReverse;
+ } else {
+ effect->itfe = &sEffectInterface;
+ }
+ effect->ops = sPreProcOps[procId];
+ effect->procId = procId;
+ effect->state = PREPROC_EFFECT_STATE_INIT;
+ return 0;
+}
+
+int Effect_Create(preproc_effect_t *effect,
+ preproc_session_t *session,
+ effect_handle_t *interface)
+{
+ effect->session = session;
+ *interface = (effect_handle_t)&effect->itfe;
+ return Effect_SetState(effect, PREPROC_EFFECT_STATE_CREATED);
+}
+
+int Effect_Release(preproc_effect_t *effect)
+{
+ return Effect_SetState(effect, PREPROC_EFFECT_STATE_INIT);
+}
+
+
+//------------------------------------------------------------------------------
+// Session functions
+//------------------------------------------------------------------------------
+
+#define RESAMPLER_QUALITY SPEEX_RESAMPLER_QUALITY_VOIP
+
+static const int kPreprocDefaultSr = 16000;
+static const int kPreProcDefaultCnl = 1;
+
+int Session_Init(preproc_session_t *session)
+{
+ size_t i;
+ int status = 0;
+
+ session->state = PREPROC_SESSION_STATE_INIT;
+ session->id = 0;
+ session->io = 0;
+ session->createdMsk = 0;
+ session->apm = NULL;
+ for (i = 0; i < PREPROC_NUM_EFFECTS && status == 0; i++) {
+ status = Effect_Init(&session->effects[i], i);
+ }
+ return status;
+}
+
+
+extern "C" int Session_CreateEffect(preproc_session_t *session,
+ int32_t procId,
+ effect_handle_t *interface)
+{
+ int status = -ENOMEM;
+
+ ALOGV("Session_CreateEffect procId %d, createdMsk %08x", procId, session->createdMsk);
+
+ if (session->createdMsk == 0) {
+ session->apm = webrtc::AudioProcessing::Create(session->io);
+ if (session->apm == NULL) {
+ ALOGW("Session_CreateEffect could not get apm engine");
+ goto error;
+ }
+ session->apm->set_sample_rate_hz(kPreprocDefaultSr);
+ session->apm->set_num_channels(kPreProcDefaultCnl, kPreProcDefaultCnl);
+ session->apm->set_num_reverse_channels(kPreProcDefaultCnl);
+ session->procFrame = new webrtc::AudioFrame();
+ if (session->procFrame == NULL) {
+ ALOGW("Session_CreateEffect could not allocate audio frame");
+ goto error;
+ }
+ session->revFrame = new webrtc::AudioFrame();
+ if (session->revFrame == NULL) {
+ ALOGW("Session_CreateEffect could not allocate reverse audio frame");
+ goto error;
+ }
+ session->apmSamplingRate = kPreprocDefaultSr;
+ session->apmFrameCount = (kPreprocDefaultSr) / 100;
+ session->frameCount = session->apmFrameCount;
+ session->samplingRate = kPreprocDefaultSr;
+ session->inChannelCount = kPreProcDefaultCnl;
+ session->outChannelCount = kPreProcDefaultCnl;
+ session->procFrame->_frequencyInHz = kPreprocDefaultSr;
+ session->procFrame->_audioChannel = kPreProcDefaultCnl;
+ session->revChannelCount = kPreProcDefaultCnl;
+ session->revFrame->_frequencyInHz = kPreprocDefaultSr;
+ session->revFrame->_audioChannel = kPreProcDefaultCnl;
+ session->enabledMsk = 0;
+ session->processedMsk = 0;
+ session->revEnabledMsk = 0;
+ session->revProcessedMsk = 0;
+ session->inResampler = NULL;
+ session->inBuf = NULL;
+ session->inBufSize = 0;
+ session->outResampler = NULL;
+ session->outBuf = NULL;
+ session->outBufSize = 0;
+ session->revResampler = NULL;
+ session->revBuf = NULL;
+ session->revBufSize = 0;
+ }
+ status = Effect_Create(&session->effects[procId], session, interface);
+ if (status < 0) {
+ goto error;
+ }
+ ALOGV("Session_CreateEffect OK");
+ session->createdMsk |= (1<<procId);
+ return status;
+
+error:
+ if (session->createdMsk == 0) {
+ delete session->revFrame;
+ session->revFrame = NULL;
+ delete session->procFrame;
+ session->procFrame = NULL;
+ webrtc::AudioProcessing::Destroy(session->apm);
+ session->apm = NULL;
+ }
+ return status;
+}
+
+int Session_ReleaseEffect(preproc_session_t *session,
+ preproc_effect_t *fx)
+{
+ ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
+ session->createdMsk &= ~(1<<fx->procId);
+ if (session->createdMsk == 0) {
+ webrtc::AudioProcessing::Destroy(session->apm);
+ session->apm = NULL;
+ delete session->procFrame;
+ session->procFrame = NULL;
+ delete session->revFrame;
+ session->revFrame = NULL;
+ if (session->inResampler != NULL) {
+ speex_resampler_destroy(session->inResampler);
+ session->inResampler = NULL;
+ }
+ if (session->outResampler != NULL) {
+ speex_resampler_destroy(session->outResampler);
+ session->outResampler = NULL;
+ }
+ if (session->revResampler != NULL) {
+ speex_resampler_destroy(session->revResampler);
+ session->revResampler = NULL;
+ }
+ delete session->inBuf;
+ session->inBuf = NULL;
+ delete session->outBuf;
+ session->outBuf = NULL;
+ delete session->revBuf;
+ session->revBuf = NULL;
+
+ session->io = 0;
+ }
+
+ return 0;
+}
+
+
+int Session_SetConfig(preproc_session_t *session, effect_config_t *config)
+{
+ uint32_t sr;
+ uint32_t inCnl = popcount(config->inputCfg.channels);
+ uint32_t outCnl = popcount(config->outputCfg.channels);
+
+ if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
+ config->inputCfg.format != config->outputCfg.format ||
+ config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
+ return -EINVAL;
+ }
+
+ ALOGV("Session_SetConfig sr %d cnl %08x",
+ config->inputCfg.samplingRate, config->inputCfg.channels);
+ int status;
+
+ // if at least one process is enabled, do not accept configuration changes
+ if (session->enabledMsk) {
+ if (session->samplingRate != config->inputCfg.samplingRate ||
+ session->inChannelCount != inCnl ||
+ session->outChannelCount != outCnl) {
+ return -ENOSYS;
+ } else {
+ return 0;
+ }
+ }
+
+ // AEC implementation is limited to 16kHz
+ if (config->inputCfg.samplingRate >= 32000 && !(session->createdMsk & (1 << PREPROC_AEC))) {
+ session->apmSamplingRate = 32000;
+ } else
+ if (config->inputCfg.samplingRate >= 16000) {
+ session->apmSamplingRate = 16000;
+ } else if (config->inputCfg.samplingRate >= 8000) {
+ session->apmSamplingRate = 8000;
+ }
+ status = session->apm->set_sample_rate_hz(session->apmSamplingRate);
+ if (status < 0) {
+ return -EINVAL;
+ }
+ status = session->apm->set_num_channels(inCnl, outCnl);
+ if (status < 0) {
+ return -EINVAL;
+ }
+ status = session->apm->set_num_reverse_channels(inCnl);
+ if (status < 0) {
+ return -EINVAL;
+ }
+
+ session->samplingRate = config->inputCfg.samplingRate;
+ session->apmFrameCount = session->apmSamplingRate / 100;
+ if (session->samplingRate == session->apmSamplingRate) {
+ session->frameCount = session->apmFrameCount;
+ } else {
+ session->frameCount = (session->apmFrameCount * session->samplingRate) /
+ session->apmSamplingRate + 1;
+ }
+ session->inChannelCount = inCnl;
+ session->outChannelCount = outCnl;
+ session->procFrame->_audioChannel = inCnl;
+ session->procFrame->_frequencyInHz = session->apmSamplingRate;
+
+ session->revChannelCount = inCnl;
+ session->revFrame->_audioChannel = inCnl;
+ session->revFrame->_frequencyInHz = session->apmSamplingRate;
+
+ if (session->inResampler != NULL) {
+ speex_resampler_destroy(session->inResampler);
+ session->inResampler = NULL;
+ }
+ if (session->outResampler != NULL) {
+ speex_resampler_destroy(session->outResampler);
+ session->outResampler = NULL;
+ }
+ if (session->revResampler != NULL) {
+ speex_resampler_destroy(session->revResampler);
+ session->revResampler = NULL;
+ }
+ if (session->samplingRate != session->apmSamplingRate) {
+ int error;
+ session->inResampler = speex_resampler_init(session->inChannelCount,
+ session->samplingRate,
+ session->apmSamplingRate,
+ RESAMPLER_QUALITY,
+ &error);
+ if (session->inResampler == NULL) {
+ ALOGW("Session_SetConfig Cannot create speex resampler: %s",
+ speex_resampler_strerror(error));
+ return -EINVAL;
+ }
+ session->outResampler = speex_resampler_init(session->outChannelCount,
+ session->apmSamplingRate,
+ session->samplingRate,
+ RESAMPLER_QUALITY,
+ &error);
+ if (session->outResampler == NULL) {
+ ALOGW("Session_SetConfig Cannot create speex resampler: %s",
+ speex_resampler_strerror(error));
+ speex_resampler_destroy(session->inResampler);
+ session->inResampler = NULL;
+ return -EINVAL;
+ }
+ session->revResampler = speex_resampler_init(session->inChannelCount,
+ session->samplingRate,
+ session->apmSamplingRate,
+ RESAMPLER_QUALITY,
+ &error);
+ if (session->revResampler == NULL) {
+ ALOGW("Session_SetConfig Cannot create speex resampler: %s",
+ speex_resampler_strerror(error));
+ speex_resampler_destroy(session->inResampler);
+ session->inResampler = NULL;
+ speex_resampler_destroy(session->outResampler);
+ session->outResampler = NULL;
+ return -EINVAL;
+ }
+ }
+
+ session->state = PREPROC_SESSION_STATE_CONFIG;
+ return 0;
+}
+
+void Session_GetConfig(preproc_session_t *session, effect_config_t *config)
+{
+ memset(config, 0, sizeof(effect_config_t));
+ config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
+ config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ config->inputCfg.channels = audio_channel_in_mask_from_count(session->inChannelCount);
+ // "out" doesn't mean output device, so this is the correct API to convert channel count to mask
+ config->outputCfg.channels = audio_channel_in_mask_from_count(session->outChannelCount);
+ config->inputCfg.mask = config->outputCfg.mask =
+ (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
+}
+
+int Session_SetReverseConfig(preproc_session_t *session, effect_config_t *config)
+{
+ if (config->inputCfg.samplingRate != config->outputCfg.samplingRate ||
+ config->inputCfg.format != config->outputCfg.format ||
+ config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
+ return -EINVAL;
+ }
+
+ ALOGV("Session_SetReverseConfig sr %d cnl %08x",
+ config->inputCfg.samplingRate, config->inputCfg.channels);
+
+ if (session->state < PREPROC_SESSION_STATE_CONFIG) {
+ return -ENOSYS;
+ }
+ if (config->inputCfg.samplingRate != session->samplingRate ||
+ config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
+ return -EINVAL;
+ }
+ uint32_t inCnl = popcount(config->inputCfg.channels);
+ int status = session->apm->set_num_reverse_channels(inCnl);
+ if (status < 0) {
+ return -EINVAL;
+ }
+ session->revChannelCount = inCnl;
+ session->revFrame->_audioChannel = inCnl;
+ session->revFrame->_frequencyInHz = session->apmSamplingRate;
+ return 0;
+}
+
+void Session_GetReverseConfig(preproc_session_t *session, effect_config_t *config)
+{
+ memset(config, 0, sizeof(effect_config_t));
+ config->inputCfg.samplingRate = config->outputCfg.samplingRate = session->samplingRate;
+ config->inputCfg.format = config->outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ config->inputCfg.channels = config->outputCfg.channels =
+ audio_channel_in_mask_from_count(session->revChannelCount);
+ config->inputCfg.mask = config->outputCfg.mask =
+ (EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT);
+}
+
+void Session_SetProcEnabled(preproc_session_t *session, uint32_t procId, bool enabled)
+{
+ if (enabled) {
+ if(session->enabledMsk == 0) {
+ session->framesIn = 0;
+ if (session->inResampler != NULL) {
+ speex_resampler_reset_mem(session->inResampler);
+ }
+ session->framesOut = 0;
+ if (session->outResampler != NULL) {
+ speex_resampler_reset_mem(session->outResampler);
+ }
+ }
+ session->enabledMsk |= (1 << procId);
+ if (HasReverseStream(procId)) {
+ session->framesRev = 0;
+ if (session->revResampler != NULL) {
+ speex_resampler_reset_mem(session->revResampler);
+ }
+ session->revEnabledMsk |= (1 << procId);
+ }
+ } else {
+ session->enabledMsk &= ~(1 << procId);
+ if (HasReverseStream(procId)) {
+ session->revEnabledMsk &= ~(1 << procId);
+ }
+ }
+ ALOGV("Session_SetProcEnabled proc %d, enabled %d enabledMsk %08x revEnabledMsk %08x",
+ procId, enabled, session->enabledMsk, session->revEnabledMsk);
+ session->processedMsk = 0;
+ if (HasReverseStream(procId)) {
+ session->revProcessedMsk = 0;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Bundle functions
+//------------------------------------------------------------------------------
+
+static int sInitStatus = 1;
+static preproc_session_t sSessions[PREPROC_NUM_SESSIONS];
+
+preproc_session_t *PreProc_GetSession(int32_t procId, int32_t sessionId, int32_t ioId)
+{
+ size_t i;
+ int free = -1;
+ for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
+ if (sSessions[i].io == ioId) {
+ if (sSessions[i].createdMsk & (1 << procId)) {
+ return NULL;
+ }
+ return &sSessions[i];
+ }
+ }
+ for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
+ if (sSessions[i].io == 0) {
+ sSessions[i].id = sessionId;
+ sSessions[i].io = ioId;
+ return &sSessions[i];
+ }
+ }
+ return NULL;
+}
+
+
+int PreProc_Init() {
+ size_t i;
+ int status = 0;
+
+ if (sInitStatus <= 0) {
+ return sInitStatus;
+ }
+ for (i = 0; i < PREPROC_NUM_SESSIONS && status == 0; i++) {
+ status = Session_Init(&sSessions[i]);
+ }
+ sInitStatus = status;
+ return sInitStatus;
+}
+
+const effect_descriptor_t *PreProc_GetDescriptor(const effect_uuid_t *uuid)
+{
+ size_t i;
+ for (i = 0; i < PREPROC_NUM_EFFECTS; i++) {
+ if (memcmp(&sDescriptors[i]->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
+ return sDescriptors[i];
+ }
+ }
+ return NULL;
+}
+
+
+extern "C" {
+
+//------------------------------------------------------------------------------
+// Effect Control Interface Implementation
+//------------------------------------------------------------------------------
+
+int PreProcessingFx_Process(effect_handle_t self,
+ audio_buffer_t *inBuffer,
+ audio_buffer_t *outBuffer)
+{
+ preproc_effect_t * effect = (preproc_effect_t *)self;
+ int status = 0;
+
+ if (effect == NULL){
+ ALOGV("PreProcessingFx_Process() ERROR effect == NULL");
+ return -EINVAL;
+ }
+ preproc_session_t * session = (preproc_session_t *)effect->session;
+
+ if (inBuffer == NULL || inBuffer->raw == NULL ||
+ outBuffer == NULL || outBuffer->raw == NULL){
+ ALOGW("PreProcessingFx_Process() ERROR bad pointer");
+ return -EINVAL;
+ }
+
+ session->processedMsk |= (1<<effect->procId);
+
+// ALOGV("PreProcessingFx_Process In %d frames enabledMsk %08x processedMsk %08x",
+// inBuffer->frameCount, session->enabledMsk, session->processedMsk);
+
+ if ((session->processedMsk & session->enabledMsk) == session->enabledMsk) {
+ effect->session->processedMsk = 0;
+ size_t framesRq = outBuffer->frameCount;
+ size_t framesWr = 0;
+ if (session->framesOut) {
+ size_t fr = session->framesOut;
+ if (outBuffer->frameCount < fr) {
+ fr = outBuffer->frameCount;
+ }
+ memcpy(outBuffer->s16,
+ session->outBuf,
+ fr * session->outChannelCount * sizeof(int16_t));
+ memcpy(session->outBuf,
+ session->outBuf + fr * session->outChannelCount,
+ (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
+ session->framesOut -= fr;
+ framesWr += fr;
+ }
+ outBuffer->frameCount = framesWr;
+ if (framesWr == framesRq) {
+ inBuffer->frameCount = 0;
+ return 0;
+ }
+
+ if (session->inResampler != NULL) {
+ size_t fr = session->frameCount - session->framesIn;
+ if (inBuffer->frameCount < fr) {
+ fr = inBuffer->frameCount;
+ }
+ if (session->inBufSize < session->framesIn + fr) {
+ session->inBufSize = session->framesIn + fr;
+ session->inBuf = (int16_t *)realloc(session->inBuf,
+ session->inBufSize * session->inChannelCount * sizeof(int16_t));
+ }
+ memcpy(session->inBuf + session->framesIn * session->inChannelCount,
+ inBuffer->s16,
+ fr * session->inChannelCount * sizeof(int16_t));
+
+ session->framesIn += fr;
+ inBuffer->frameCount = fr;
+ if (session->framesIn < session->frameCount) {
+ return 0;
+ }
+ size_t frIn = session->framesIn;
+ size_t frOut = session->apmFrameCount;
+ if (session->inChannelCount == 1) {
+ speex_resampler_process_int(session->inResampler,
+ 0,
+ session->inBuf,
+ &frIn,
+ session->procFrame->_payloadData,
+ &frOut);
+ } else {
+ speex_resampler_process_interleaved_int(session->inResampler,
+ session->inBuf,
+ &frIn,
+ session->procFrame->_payloadData,
+ &frOut);
+ }
+ memcpy(session->inBuf,
+ session->inBuf + frIn * session->inChannelCount,
+ (session->framesIn - frIn) * session->inChannelCount * sizeof(int16_t));
+ session->framesIn -= frIn;
+ } else {
+ size_t fr = session->frameCount - session->framesIn;
+ if (inBuffer->frameCount < fr) {
+ fr = inBuffer->frameCount;
+ }
+ memcpy(session->procFrame->_payloadData + session->framesIn * session->inChannelCount,
+ inBuffer->s16,
+ fr * session->inChannelCount * sizeof(int16_t));
+ session->framesIn += fr;
+ inBuffer->frameCount = fr;
+ if (session->framesIn < session->frameCount) {
+ return 0;
+ }
+ session->framesIn = 0;
+ }
+ session->procFrame->_payloadDataLengthInSamples =
+ session->apmFrameCount * session->inChannelCount;
+
+ effect->session->apm->ProcessStream(session->procFrame);
+
+ if (session->outBufSize < session->framesOut + session->frameCount) {
+ session->outBufSize = session->framesOut + session->frameCount;
+ session->outBuf = (int16_t *)realloc(session->outBuf,
+ session->outBufSize * session->outChannelCount * sizeof(int16_t));
+ }
+
+ if (session->outResampler != NULL) {
+ size_t frIn = session->apmFrameCount;
+ size_t frOut = session->frameCount;
+ if (session->inChannelCount == 1) {
+ speex_resampler_process_int(session->outResampler,
+ 0,
+ session->procFrame->_payloadData,
+ &frIn,
+ session->outBuf + session->framesOut * session->outChannelCount,
+ &frOut);
+ } else {
+ speex_resampler_process_interleaved_int(session->outResampler,
+ session->procFrame->_payloadData,
+ &frIn,
+ session->outBuf + session->framesOut * session->outChannelCount,
+ &frOut);
+ }
+ session->framesOut += frOut;
+ } else {
+ memcpy(session->outBuf + session->framesOut * session->outChannelCount,
+ session->procFrame->_payloadData,
+ session->frameCount * session->outChannelCount * sizeof(int16_t));
+ session->framesOut += session->frameCount;
+ }
+ size_t fr = session->framesOut;
+ if (framesRq - framesWr < fr) {
+ fr = framesRq - framesWr;
+ }
+ memcpy(outBuffer->s16 + framesWr * session->outChannelCount,
+ session->outBuf,
+ fr * session->outChannelCount * sizeof(int16_t));
+ memcpy(session->outBuf,
+ session->outBuf + fr * session->outChannelCount,
+ (session->framesOut - fr) * session->outChannelCount * sizeof(int16_t));
+ session->framesOut -= fr;
+ outBuffer->frameCount += fr;
+
+ return 0;
+ } else {
+ return -ENODATA;
+ }
+}
+
+int PreProcessingFx_Command(effect_handle_t self,
+ uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData)
+{
+ preproc_effect_t * effect = (preproc_effect_t *) self;
+ int retsize;
+ int status;
+
+ if (effect == NULL){
+ return -EINVAL;
+ }
+
+ //ALOGV("PreProcessingFx_Command: command %d cmdSize %d",cmdCode, cmdSize);
+
+ switch (cmdCode){
+ case EFFECT_CMD_INIT:
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ return -EINVAL;
+ }
+ if (effect->ops->init) {
+ effect->ops->init(effect);
+ }
+ *(int *)pReplyData = 0;
+ break;
+
+ case EFFECT_CMD_SET_CONFIG:
+ if (pCmdData == NULL||
+ cmdSize != sizeof(effect_config_t)||
+ pReplyData == NULL||
+ *replySize != sizeof(int)){
+ ALOGV("PreProcessingFx_Command cmdCode Case: "
+ "EFFECT_CMD_SET_CONFIG: ERROR");
+ return -EINVAL;
+ }
+ *(int *)pReplyData = Session_SetConfig(effect->session, (effect_config_t *)pCmdData);
+ if (*(int *)pReplyData != 0) {
+ break;
+ }
+ if (effect->state != PREPROC_EFFECT_STATE_ACTIVE) {
+ *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
+ }
+ break;
+
+ case EFFECT_CMD_GET_CONFIG:
+ if (pReplyData == NULL ||
+ *replySize != sizeof(effect_config_t)) {
+ ALOGV("\tLVM_ERROR : PreProcessingFx_Command cmdCode Case: "
+ "EFFECT_CMD_GET_CONFIG: ERROR");
+ return -EINVAL;
+ }
+
+ Session_GetConfig(effect->session, (effect_config_t *)pReplyData);
+ break;
+
+ case EFFECT_CMD_SET_CONFIG_REVERSE:
+ if (pCmdData == NULL ||
+ cmdSize != sizeof(effect_config_t) ||
+ pReplyData == NULL ||
+ *replySize != sizeof(int)) {
+ ALOGV("PreProcessingFx_Command cmdCode Case: "
+ "EFFECT_CMD_SET_CONFIG_REVERSE: ERROR");
+ return -EINVAL;
+ }
+ *(int *)pReplyData = Session_SetReverseConfig(effect->session,
+ (effect_config_t *)pCmdData);
+ if (*(int *)pReplyData != 0) {
+ break;
+ }
+ break;
+
+ case EFFECT_CMD_GET_CONFIG_REVERSE:
+ if (pReplyData == NULL ||
+ *replySize != sizeof(effect_config_t)){
+ ALOGV("PreProcessingFx_Command cmdCode Case: "
+ "EFFECT_CMD_GET_CONFIG_REVERSE: ERROR");
+ return -EINVAL;
+ }
+ Session_GetReverseConfig(effect->session, (effect_config_t *)pCmdData);
+ break;
+
+ case EFFECT_CMD_RESET:
+ if (effect->ops->reset) {
+ effect->ops->reset(effect);
+ }
+ break;
+
+ case EFFECT_CMD_GET_PARAM:{
+ if (pCmdData == NULL ||
+ cmdSize < (int)sizeof(effect_param_t) ||
+ pReplyData == NULL ||
+ *replySize < (int)sizeof(effect_param_t)){
+ ALOGV("PreProcessingFx_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);
+
+ if (effect->ops->get_parameter) {
+ p->status = effect->ops->get_parameter(effect, p->data,
+ (size_t *)&p->vsize,
+ p->data + voffset);
+ *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+ }
+ } break;
+
+ case EFFECT_CMD_SET_PARAM:{
+ if (pCmdData == NULL||
+ cmdSize < (int)sizeof(effect_param_t) ||
+ pReplyData == NULL ||
+ *replySize != sizeof(int32_t)){
+ ALOGV("PreProcessingFx_Command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR");
+ return -EINVAL;
+ }
+ effect_param_t *p = (effect_param_t *) pCmdData;
+
+ if (p->psize != sizeof(int32_t)){
+ ALOGV("PreProcessingFx_Command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
+ return -EINVAL;
+ }
+ if (effect->ops->set_parameter) {
+ *(int *)pReplyData = effect->ops->set_parameter(effect,
+ (void *)p->data,
+ p->data + p->psize);
+ }
+ } break;
+
+ case EFFECT_CMD_ENABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
+ return -EINVAL;
+ }
+ *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_ACTIVE);
+ break;
+
+ case EFFECT_CMD_DISABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
+ return -EINVAL;
+ }
+ *(int *)pReplyData = Effect_SetState(effect, PREPROC_EFFECT_STATE_CONFIG);
+ break;
+
+ case EFFECT_CMD_SET_DEVICE:
+ case EFFECT_CMD_SET_INPUT_DEVICE:
+ if (pCmdData == NULL ||
+ cmdSize != sizeof(uint32_t)) {
+ ALOGV("PreProcessingFx_Command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
+ return -EINVAL;
+ }
+
+ if (effect->ops->set_device) {
+ effect->ops->set_device(effect, *(uint32_t *)pCmdData);
+ }
+ break;
+
+ case EFFECT_CMD_SET_VOLUME:
+ case EFFECT_CMD_SET_AUDIO_MODE:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
+int PreProcessingFx_GetDescriptor(effect_handle_t self,
+ effect_descriptor_t *pDescriptor)
+{
+ preproc_effect_t * effect = (preproc_effect_t *) self;
+
+ if (effect == NULL || pDescriptor == NULL) {
+ return -EINVAL;
+ }
+
+ memcpy(pDescriptor, sDescriptors[effect->procId], sizeof(effect_descriptor_t));
+
+ return 0;
+}
+
+int PreProcessingFx_ProcessReverse(effect_handle_t self,
+ audio_buffer_t *inBuffer,
+ audio_buffer_t *outBuffer)
+{
+ preproc_effect_t * effect = (preproc_effect_t *)self;
+ int status = 0;
+
+ if (effect == NULL){
+ ALOGW("PreProcessingFx_ProcessReverse() ERROR effect == NULL");
+ return -EINVAL;
+ }
+ preproc_session_t * session = (preproc_session_t *)effect->session;
+
+ if (inBuffer == NULL || inBuffer->raw == NULL){
+ ALOGW("PreProcessingFx_ProcessReverse() ERROR bad pointer");
+ return -EINVAL;
+ }
+
+ session->revProcessedMsk |= (1<<effect->procId);
+
+// ALOGV("PreProcessingFx_ProcessReverse In %d frames revEnabledMsk %08x revProcessedMsk %08x",
+// inBuffer->frameCount, session->revEnabledMsk, session->revProcessedMsk);
+
+
+ if ((session->revProcessedMsk & session->revEnabledMsk) == session->revEnabledMsk) {
+ effect->session->revProcessedMsk = 0;
+ if (session->revResampler != NULL) {
+ size_t fr = session->frameCount - session->framesRev;
+ if (inBuffer->frameCount < fr) {
+ fr = inBuffer->frameCount;
+ }
+ if (session->revBufSize < session->framesRev + fr) {
+ session->revBufSize = session->framesRev + fr;
+ session->revBuf = (int16_t *)realloc(session->revBuf,
+ session->revBufSize * session->inChannelCount * sizeof(int16_t));
+ }
+ memcpy(session->revBuf + session->framesRev * session->inChannelCount,
+ inBuffer->s16,
+ fr * session->inChannelCount * sizeof(int16_t));
+
+ session->framesRev += fr;
+ inBuffer->frameCount = fr;
+ if (session->framesRev < session->frameCount) {
+ return 0;
+ }
+ size_t frIn = session->framesRev;
+ size_t frOut = session->apmFrameCount;
+ if (session->inChannelCount == 1) {
+ speex_resampler_process_int(session->revResampler,
+ 0,
+ session->revBuf,
+ &frIn,
+ session->revFrame->_payloadData,
+ &frOut);
+ } else {
+ speex_resampler_process_interleaved_int(session->revResampler,
+ session->revBuf,
+ &frIn,
+ session->revFrame->_payloadData,
+ &frOut);
+ }
+ memcpy(session->revBuf,
+ session->revBuf + frIn * session->inChannelCount,
+ (session->framesRev - frIn) * session->inChannelCount * sizeof(int16_t));
+ session->framesRev -= frIn;
+ } else {
+ size_t fr = session->frameCount - session->framesRev;
+ if (inBuffer->frameCount < fr) {
+ fr = inBuffer->frameCount;
+ }
+ memcpy(session->revFrame->_payloadData + session->framesRev * session->inChannelCount,
+ inBuffer->s16,
+ fr * session->inChannelCount * sizeof(int16_t));
+ session->framesRev += fr;
+ inBuffer->frameCount = fr;
+ if (session->framesRev < session->frameCount) {
+ return 0;
+ }
+ session->framesRev = 0;
+ }
+ session->revFrame->_payloadDataLengthInSamples =
+ session->apmFrameCount * session->inChannelCount;
+ effect->session->apm->AnalyzeReverseStream(session->revFrame);
+ return 0;
+ } else {
+ return -ENODATA;
+ }
+}
+
+
+// effect_handle_t interface implementation for effect
+const struct effect_interface_s sEffectInterface = {
+ PreProcessingFx_Process,
+ PreProcessingFx_Command,
+ PreProcessingFx_GetDescriptor,
+ NULL
+};
+
+const struct effect_interface_s sEffectInterfaceReverse = {
+ PreProcessingFx_Process,
+ PreProcessingFx_Command,
+ PreProcessingFx_GetDescriptor,
+ PreProcessingFx_ProcessReverse
+};
+
+//------------------------------------------------------------------------------
+// Effect Library Interface Implementation
+//------------------------------------------------------------------------------
+
+int PreProcessingLib_QueryNumberEffects(uint32_t *pNumEffects)
+{
+ if (PreProc_Init() != 0) {
+ return sInitStatus;
+ }
+ if (pNumEffects == NULL) {
+ return -EINVAL;
+ }
+ *pNumEffects = PREPROC_NUM_EFFECTS;
+ return sInitStatus;
+}
+
+int PreProcessingLib_QueryEffect(uint32_t index, effect_descriptor_t *pDescriptor)
+{
+ if (PreProc_Init() != 0) {
+ return sInitStatus;
+ }
+ if (index >= PREPROC_NUM_EFFECTS) {
+ return -EINVAL;
+ }
+ memcpy(pDescriptor, sDescriptors[index], sizeof(effect_descriptor_t));
+ return 0;
+}
+
+int PreProcessingLib_Create(const effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_handle_t *pInterface)
+{
+ ALOGV("EffectCreate: uuid: %08x session %d IO: %d", uuid->timeLow, sessionId, ioId);
+
+ int status;
+ const effect_descriptor_t *desc;
+ preproc_session_t *session;
+ uint32_t procId;
+
+ if (PreProc_Init() != 0) {
+ return sInitStatus;
+ }
+ desc = PreProc_GetDescriptor(uuid);
+ if (desc == NULL) {
+ ALOGW("EffectCreate: fx not found uuid: %08x", uuid->timeLow);
+ return -EINVAL;
+ }
+ procId = UuidToProcId(&desc->type);
+
+ session = PreProc_GetSession(procId, sessionId, ioId);
+ if (session == NULL) {
+ ALOGW("EffectCreate: no more session available");
+ return -EINVAL;
+ }
+
+ status = Session_CreateEffect(session, procId, pInterface);
+
+ if (status < 0 && session->createdMsk == 0) {
+ session->io = 0;
+ }
+ return status;
+}
+
+int PreProcessingLib_Release(effect_handle_t interface)
+{
+ int status;
+ ALOGV("EffectRelease start %p", interface);
+ if (PreProc_Init() != 0) {
+ return sInitStatus;
+ }
+
+ preproc_effect_t *fx = (preproc_effect_t *)interface;
+
+ if (fx->session->io == 0) {
+ return -EINVAL;
+ }
+ return Session_ReleaseEffect(fx->session, fx);
+}
+
+int PreProcessingLib_GetDescriptor(const effect_uuid_t *uuid,
+ effect_descriptor_t *pDescriptor) {
+
+ if (pDescriptor == NULL || uuid == NULL){
+ return -EINVAL;
+ }
+
+ const effect_descriptor_t *desc = PreProc_GetDescriptor(uuid);
+ if (desc == NULL) {
+ ALOGV("PreProcessingLib_GetDescriptor() not found");
+ return -EINVAL;
+ }
+
+ ALOGV("PreProcessingLib_GetDescriptor() got fx %s", desc->name);
+
+ memcpy(pDescriptor, desc, sizeof(effect_descriptor_t));
+ return 0;
+}
+
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
+ tag : AUDIO_EFFECT_LIBRARY_TAG,
+ version : EFFECT_LIBRARY_API_VERSION,
+ name : "Audio Preprocessing Library",
+ implementor : "The Android Open Source Project",
+ query_num_effects : PreProcessingLib_QueryNumberEffects,
+ query_effect : PreProcessingLib_QueryEffect,
+ create_effect : PreProcessingLib_Create,
+ release_effect : PreProcessingLib_Release,
+ get_descriptor : PreProcessingLib_GetDescriptor
+};
+
+}; // extern "C"
diff --git a/media/libeffects/testlibs/Android.mk_ b/media/libeffects/testlibs/Android.mk_
new file mode 100644
index 0000000..2954908
--- /dev/null
+++ b/media/libeffects/testlibs/Android.mk_
@@ -0,0 +1,68 @@
+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, audio-effects) \
+ $(call include-path-for, graphics corecg)
+
+LOCAL_MODULE_TAGS := optional
+
+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) \
+ $(call include-path-for, audio-effects)
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/media/libeffects/testlibs/AudioBiquadFilter.cpp b/media/libeffects/testlibs/AudioBiquadFilter.cpp
new file mode 100644
index 0000000..16dd1c5
--- /dev/null
+++ b/media/libeffects/testlibs/AudioBiquadFilter.cpp
@@ -0,0 +1,258 @@
+/* //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 <cutils/compiler.h>
+
+#include "AudioBiquadFilter.h"
+
+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 (CC_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 (CC_UNLIKELY(immediate)) {
+ memcpy(mCoefs, mTargetCoefs, sizeof(mCoefs));
+ setState(STATE_NORMAL);
+ } else {
+ setState(STATE_TRANSITION_TO_NORMAL);
+ }
+}
+
+void AudioBiquadFilter::disable(bool immediate) {
+ if (CC_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 (CC_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..6b56922
--- /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 <cutils/compiler.h>
+
+#include "AudioCoefInterpolator.h"
+
+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 (CC_UNLIKELY(intCoord[dim] < 0)) {
+ fracCoord[dim] = 0;
+ } else if (CC_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 (CC_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..e8080dc
--- /dev/null
+++ b/media/libeffects/testlibs/AudioCommon.h
@@ -0,0 +1,93 @@
+/*
+**
+** 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>
+#include <cutils/compiler.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 (CC_UNLIKELY(sample >= (0x7FFF << 9))) {
+ return 0x7FFF;
+ } else if (CC_UNLIKELY(sample <= -(0x8000 << 9))) {
+ 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..4f3a308
--- /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) {
+ ALOGV("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) {
+ ALOGV("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() {
+ ALOGV("AudioEqualizer::clear()");
+ mpLowShelf->clear();
+ for (int i = 0; i < mNumPeaking; ++i) {
+ mpPeakingFilters[i].clear();
+ }
+ mpHighShelf->clear();
+}
+
+void AudioEqualizer::free() {
+ ALOGV("AudioEqualizer::free()");
+ if (mpMem != NULL) {
+ ::free(mpMem);
+ }
+}
+
+void AudioEqualizer::reset() {
+ ALOGV("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) {
+ ALOGV("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) {
+ ALOGV("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) {
+ ALOGV("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) {
+ ALOGV("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) {
+ ALOGV("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) {
+// ALOGV("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) {
+ ALOGV("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) {
+ ALOGV("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..41f1810
--- /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 <hardware/audio_effect.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 == AUDIO_FORMAT_PCM_8_24_BIT) {
+ 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 == AUDIO_FORMAT_PCM_16_BIT) {
+ 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 == AUDIO_FORMAT_PCM_16_BIT) {
+ 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..99323ac
--- /dev/null
+++ b/media/libeffects/testlibs/AudioPeakingFilter.cpp
@@ -0,0 +1,119 @@
+/* //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>
+#include <cutils/compiler.h>
+
+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 (CC_UNLIKELY(millihertz > mNiquistFreq / 2)) {
+ millihertz = mNiquistFreq / 2;
+ }
+ uint32_t normFreq = static_cast<uint32_t>(
+ (static_cast<uint64_t>(millihertz) * mFrequencyFactor) >> 10);
+ if (CC_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 (CC_UNLIKELY(halfBW >= (16 << 15))) {
+ high = mNiquistFreq;
+ } else {
+ high = static_cast<uint32_t>((static_cast<uint64_t>(mNominalFrequency) * Effects_exp2(halfBW + (16 << 15))) >> 16);
+ if (CC_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..e031287
--- /dev/null
+++ b/media/libeffects/testlibs/AudioShelvingFilter.cpp
@@ -0,0 +1,107 @@
+/* /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>
+#include <cutils/compiler.h>
+
+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 (CC_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 (CC_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..35a4a61
--- /dev/null
+++ b/media/libeffects/testlibs/EffectEqualizer.cpp
@@ -0,0 +1,779 @@
+/*
+ * 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 <audio_effects/effect_equalizer.h>
+
+
+// effect_handle_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_CONTROL_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST),
+ 0, // TODO
+ 1,
+ "Graphic Equalizer",
+ "The Android Open Source Project",
+};
+
+/////////////////// 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_setConfig(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(const effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_handle_t *pHandle) {
+ int ret;
+ int i;
+
+ ALOGV("EffectLibCreateEffect start");
+
+ if (pHandle == 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) {
+ ALOGW("EffectLibCreateEffect() init failed");
+ delete pContext;
+ return ret;
+ }
+
+ *pHandle = (effect_handle_t)pContext;
+ pContext->state = EQUALIZER_STATE_INITIALIZED;
+
+ ALOGV("EffectLibCreateEffect %p, size %d",
+ pContext, AudioEqualizer::GetInstanceSize(kNumBands)+sizeof(EqualizerContext));
+
+ return 0;
+
+} /* end EffectCreate */
+
+extern "C" int EffectRelease(effect_handle_t handle) {
+ EqualizerContext * pContext = (EqualizerContext *)handle;
+
+ ALOGV("EffectLibReleaseEffect %p", handle);
+ if (pContext == NULL) {
+ return -EINVAL;
+ }
+
+ pContext->state = EQUALIZER_STATE_UNINITIALIZED;
+ pContext->pEqualizer->free();
+ delete pContext;
+
+ return 0;
+} /* end EffectRelease */
+
+extern "C" int EffectGetDescriptor(const effect_uuid_t *uuid,
+ effect_descriptor_t *pDescriptor) {
+
+ if (pDescriptor == NULL || uuid == NULL){
+ ALOGV("EffectGetDescriptor() called with NULL pointer");
+ return -EINVAL;
+ }
+
+ if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0) {
+ memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t));
+ return 0;
+ }
+
+ return -EINVAL;
+} /* end EffectGetDescriptor */
+
+
+//
+//--- local functions
+//
+
+#define CHECK_ARG(cond) { \
+ if (!(cond)) { \
+ ALOGV("Invalid argument: "#cond); \
+ return -EINVAL; \
+ } \
+}
+
+//----------------------------------------------------------------------------
+// Equalizer_setConfig()
+//----------------------------------------------------------------------------
+// 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_setConfig(EqualizerContext *pContext, effect_config_t *pConfig)
+{
+ ALOGV("Equalizer_setConfig 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 == AUDIO_CHANNEL_OUT_MONO) ||
+ (pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_STEREO));
+ CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
+ || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
+ CHECK_ARG(pConfig->inputCfg.format == AUDIO_FORMAT_PCM_8_24_BIT
+ || pConfig->inputCfg.format == AUDIO_FORMAT_PCM_16_BIT);
+
+ int channelCount;
+ if (pConfig->inputCfg.channels == AUDIO_CHANNEL_OUT_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_setConfig
+
+//----------------------------------------------------------------------------
+// Equalizer_getConfig()
+//----------------------------------------------------------------------------
+// Purpose: Get input and output audio configuration.
+//
+// Inputs:
+// pContext: effect engine context
+// pConfig: pointer to effect_config_t structure holding input and output
+// configuration parameters
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+void Equalizer_getConfig(EqualizerContext *pContext, effect_config_t *pConfig)
+{
+ memcpy(pConfig, &pContext->config, sizeof(effect_config_t));
+} // end Equalizer_getConfig
+
+
+//----------------------------------------------------------------------------
+// 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;
+
+ ALOGV("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 = AUDIO_CHANNEL_OUT_STEREO;
+ pContext->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ 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 = AUDIO_CHANNEL_OUT_STEREO;
+ pContext->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ 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_setConfig(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:
+ case EQ_PARAM_BAND_LEVEL:
+ case EQ_PARAM_GET_BAND:
+ if (*pValueSize < sizeof(int16_t)) {
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+
+ case EQ_PARAM_LEVEL_RANGE:
+ if (*pValueSize < 2 * sizeof(int16_t)) {
+ return -EINVAL;
+ }
+ *pValueSize = 2 * sizeof(int16_t);
+ break;
+
+ case EQ_PARAM_BAND_FREQ_RANGE:
+ if (*pValueSize < 2 * sizeof(int32_t)) {
+ return -EINVAL;
+ }
+ *pValueSize = 2 * sizeof(int32_t);
+ break;
+
+ case EQ_PARAM_CENTER_FREQ:
+ if (*pValueSize < sizeof(int32_t)) {
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int32_t);
+ break;
+
+ case EQ_PARAM_GET_PRESET_NAME:
+ break;
+
+ case EQ_PARAM_PROPERTIES:
+ if (*pValueSize < (2 + kNumBands) * sizeof(uint16_t)) {
+ return -EINVAL;
+ }
+ *pValueSize = (2 + kNumBands) * sizeof(uint16_t);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ switch (param) {
+ case EQ_PARAM_NUM_BANDS:
+ *(uint16_t *)pValue = (uint16_t)kNumBands;
+ ALOGV("Equalizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
+ break;
+
+ case EQ_PARAM_LEVEL_RANGE:
+ *(int16_t *)pValue = -9600;
+ *((int16_t *)pValue + 1) = 4800;
+ ALOGV("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;
+ }
+ *(int16_t *)pValue = (int16_t)pEqualizer->getGain(param2);
+ ALOGV("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);
+ ALOGV("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));
+ ALOGV("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;
+ *(uint16_t *)pValue = (uint16_t)pEqualizer->getMostRelevantBand(param2);
+ ALOGV("Equalizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d",
+ param2, *(int32_t *)pValue);
+ break;
+
+ case EQ_PARAM_CUR_PRESET:
+ *(uint16_t *)pValue = (uint16_t)pEqualizer->getPreset();
+ ALOGV("Equalizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
+ break;
+
+ case EQ_PARAM_GET_NUM_OF_PRESETS:
+ *(uint16_t *)pValue = (uint16_t)pEqualizer->getNumPresets();
+ ALOGV("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;
+ ALOGV("Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d",
+ param2, gEqualizerPresets[param2].name, *pValueSize);
+ break;
+
+ case EQ_PARAM_PROPERTIES: {
+ int16_t *p = (int16_t *)pValue;
+ ALOGV("Equalizer_getParameter() EQ_PARAM_PROPERTIES");
+ p[0] = (int16_t)pEqualizer->getPreset();
+ p[1] = (int16_t)kNumBands;
+ for (int i = 0; i < kNumBands; i++) {
+ p[2 + i] = (int16_t)pEqualizer->getGain(i);
+ }
+ } break;
+
+ default:
+ ALOGV("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 = (int32_t)(*(uint16_t *)pValue);
+
+ ALOGV("setParameter() EQ_PARAM_CUR_PRESET %d", preset);
+ if (preset < 0 || preset >= pEqualizer->getNumPresets()) {
+ status = -EINVAL;
+ break;
+ }
+ pEqualizer->setPreset(preset);
+ pEqualizer->commit(true);
+ break;
+ case EQ_PARAM_BAND_LEVEL:
+ band = *pParam;
+ level = (int32_t)(*(int16_t *)pValue);
+ ALOGV("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;
+ case EQ_PARAM_PROPERTIES: {
+ ALOGV("setParameter() EQ_PARAM_PROPERTIES");
+ int16_t *p = (int16_t *)pValue;
+ if ((int)p[0] >= pEqualizer->getNumPresets()) {
+ status = -EINVAL;
+ break;
+ }
+ if (p[0] >= 0) {
+ pEqualizer->setPreset((int)p[0]);
+ } else {
+ if ((int)p[1] != kNumBands) {
+ status = -EINVAL;
+ break;
+ }
+ for (int i = 0; i < kNumBands; i++) {
+ pEqualizer->setGain(i, (int32_t)p[2 + i]);
+ }
+ }
+ pEqualizer->commit(true);
+ } break;
+ default:
+ ALOGV("setParameter() invalid param %d", param);
+ status = -EINVAL;
+ break;
+ }
+
+ return status;
+} // end Equalizer_setParameter
+
+} // namespace
+} // namespace
+
+
+//
+//--- Effect Control Interface Implementation
+//
+
+extern "C" int Equalizer_process(effect_handle_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_handle_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;
+
+ ALOGV("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_SET_CONFIG:
+ if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+ || pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Equalizer_setConfig(pContext,
+ (effect_config_t *) pCmdData);
+ break;
+ case EFFECT_CMD_GET_CONFIG:
+ if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
+ return -EINVAL;
+ }
+ Equalizer_getConfig(pContext, (effect_config_t *) pCmdData);
+ break;
+ case EFFECT_CMD_RESET:
+ Equalizer_setConfig(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;
+ ALOGV("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: {
+ ALOGV("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;
+ ALOGV("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;
+ ALOGV("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:
+ ALOGW("Equalizer_command invalid command %d",cmdCode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+extern "C" int Equalizer_getDescriptor(effect_handle_t self,
+ effect_descriptor_t *pDescriptor)
+{
+ android::EqualizerContext * pContext = (android::EqualizerContext *) self;
+
+ if (pContext == NULL || pDescriptor == NULL) {
+ ALOGV("Equalizer_getDescriptor() invalid param");
+ return -EINVAL;
+ }
+
+ memcpy(pDescriptor, &android::gEqualizerDescriptor, sizeof(effect_descriptor_t));
+
+ return 0;
+}
+
+// effect_handle_t interface implementation for equalizer effect
+const struct effect_interface_s gEqualizerInterface = {
+ Equalizer_process,
+ Equalizer_command,
+ Equalizer_getDescriptor,
+ NULL
+};
+
+
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
+ tag : AUDIO_EFFECT_LIBRARY_TAG,
+ version : EFFECT_LIBRARY_API_VERSION,
+ name : "Test Equalizer Library",
+ implementor : "The Android Open Source Project",
+ query_num_effects : android::EffectQueryNumberEffects,
+ query_effect : android::EffectQueryEffect,
+ create_effect : android::EffectCreate,
+ release_effect : android::EffectRelease,
+ get_descriptor : android::EffectGetDescriptor,
+};
diff --git a/media/libeffects/testlibs/EffectReverb.c b/media/libeffects/testlibs/EffectReverb.c
new file mode 100644
index 0000000..8351712
--- /dev/null
+++ b/media/libeffects/testlibs/EffectReverb.c
@@ -0,0 +1,2230 @@
+/*
+ * 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_handle_t interface implementation for reverb effect
+const struct effect_interface_s gReverbInterface = {
+ Reverb_Process,
+ Reverb_Command,
+ Reverb_GetDescriptor,
+ NULL
+};
+
+// 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_CONTROL_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",
+ "The Android Open Source Project"
+};
+
+// 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_CONTROL_API_VERSION,
+ EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+ 0, // TODO
+ 33,
+ "Insert Environmental reverb",
+ "The Android Open Source Project"
+};
+
+// 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_CONTROL_API_VERSION,
+ EFFECT_FLAG_TYPE_AUXILIARY,
+ 0, // TODO
+ 33,
+ "Aux Preset Reverb",
+ "The Android Open Source Project"
+};
+
+// 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_CONTROL_API_VERSION,
+ EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+ 0, // TODO
+ 33,
+ "Insert Preset Reverb",
+ "The Android Open Source Project"
+};
+
+// 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(const effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_handle_t *pHandle) {
+ int ret;
+ int i;
+ reverb_module_t *module;
+ const effect_descriptor_t *desc;
+ int aux = 0;
+ int preset = 0;
+
+ ALOGV("EffectLibCreateEffect start");
+
+ if (pHandle == 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) {
+ ALOGW("EffectLibCreateEffect() init failed");
+ free(module);
+ return ret;
+ }
+
+ *pHandle = (effect_handle_t) module;
+
+ module->context.mState = REVERB_STATE_INITIALIZED;
+
+ ALOGV("EffectLibCreateEffect %p ,size %d", module, sizeof(reverb_module_t));
+
+ return 0;
+}
+
+int EffectRelease(effect_handle_t handle) {
+ reverb_module_t *pRvbModule = (reverb_module_t *)handle;
+
+ ALOGV("EffectLibReleaseEffect %p", handle);
+ if (handle == NULL) {
+ return -EINVAL;
+ }
+
+ pRvbModule->context.mState = REVERB_STATE_UNINITIALIZED;
+
+ free(pRvbModule);
+ return 0;
+}
+
+int EffectGetDescriptor(const effect_uuid_t *uuid,
+ effect_descriptor_t *pDescriptor) {
+ int i;
+ int length = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
+
+ if (pDescriptor == NULL || uuid == NULL){
+ ALOGV("EffectGetDescriptor() called with NULL pointer");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < length; i++) {
+ if (memcmp(uuid, &gDescriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
+ memcpy(pDescriptor, gDescriptors[i], sizeof(effect_descriptor_t));
+ ALOGV("EffectGetDescriptor - UUID matched Reverb type %d, UUID = %x",
+ i, gDescriptors[i]->uuid.timeLow);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+} /* end EffectGetDescriptor */
+
+/*--- Effect Control Interface Implementation ---*/
+
+static int Reverb_Process(effect_handle_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_handle_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;
+
+ ALOGV("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_SET_CONFIG:
+ if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+ || pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Reverb_setConfig(pRvbModule,
+ (effect_config_t *)pCmdData, false);
+ break;
+ case EFFECT_CMD_GET_CONFIG:
+ if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
+ return -EINVAL;
+ }
+ Reverb_getConfig(pRvbModule, (effect_config_t *) pCmdData);
+ break;
+ case EFFECT_CMD_RESET:
+ Reverb_Reset(pReverb, false);
+ break;
+ case EFFECT_CMD_GET_PARAM:
+ ALOGV("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));
+ ALOGV("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:
+ ALOGV("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;
+ ALOGV("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;
+ ALOGV("EFFECT_CMD_DISABLE() OK");
+ *(int *)pReplyData = 0;
+ break;
+ case EFFECT_CMD_SET_DEVICE:
+ if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
+ return -EINVAL;
+ }
+ ALOGV("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);
+ ALOGV("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;
+ }
+ ALOGV("Reverb_Command EFFECT_CMD_SET_AUDIO_MODE: %d", *(uint32_t *)pCmdData);
+ break;
+ default:
+ ALOGW("Reverb_Command invalid command %d",cmdCode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int Reverb_GetDescriptor(effect_handle_t self,
+ effect_descriptor_t *pDescriptor)
+{
+ reverb_module_t *pRvbModule = (reverb_module_t *) self;
+ reverb_object_t *pReverb;
+ const effect_descriptor_t *desc;
+
+ if (pRvbModule == NULL ||
+ pRvbModule->context.mState == REVERB_STATE_UNINITIALIZED) {
+ return -EINVAL;
+ }
+
+ pReverb = (reverb_object_t*) &pRvbModule->context;
+
+ if (pReverb->m_Aux) {
+ if (pReverb->m_Preset) {
+ desc = &gAuxPresetReverbDescriptor;
+ } else {
+ desc = &gAuxEnvReverbDescriptor;
+ }
+ } else {
+ if (pReverb->m_Preset) {
+ desc = &gInsertPresetReverbDescriptor;
+ } else {
+ desc = &gInsertEnvReverbDescriptor;
+ }
+ }
+
+ memcpy(pDescriptor, desc, sizeof(effect_descriptor_t));
+
+ return 0;
+} /* end Reverb_getDescriptor */
+
+/*----------------------------------------------------------------------------
+ * 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;
+
+ ALOGV("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 = AUDIO_CHANNEL_OUT_MONO;
+ } else {
+ pRvbModule->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ }
+ pRvbModule->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ 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 = AUDIO_CHANNEL_OUT_STEREO;
+ pRvbModule->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ 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_setConfig(pRvbModule, &pRvbModule->config, true);
+ if (ret < 0) {
+ ALOGV("Reverb_Init error %d on module %p", ret, pRvbModule);
+ }
+
+ return ret;
+}
+
+/*----------------------------------------------------------------------------
+ * Reverb_setConfig()
+ *----------------------------------------------------------------------------
+ * 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_setConfig(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 != AUDIO_FORMAT_PCM_16_BIT
+ || pConfig->outputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
+ ALOGV("Reverb_setConfig invalid config");
+ return -EINVAL;
+ }
+ if ((pReverb->m_Aux && (pConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_MONO)) ||
+ (!pReverb->m_Aux && (pConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO))) {
+ ALOGV("Reverb_setConfig 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:
+ ALOGV("Reverb_setConfig 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_getConfig()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Get 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
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void Reverb_getConfig(reverb_module_t *pRvbModule, effect_config_t *pConfig)
+{
+ memcpy(pConfig, &pRvbModule->config, sizeof(effect_config_t));
+}
+
+/*----------------------------------------------------------------------------
+ * 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);
+ }
+ ALOGV("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);
+
+ ALOGV("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);
+ ALOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 %d", temp);
+ temp2 = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nCosWT_5KHz)
+ << 1;
+ ALOGV("get REVERB_PARAM_ROOM_HF_LEVEL, 2 Cos a1 %d", temp2);
+ temp = 32767 + temp - temp2;
+ ALOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 + 2 Cos a1 + 1 %d", temp);
+ temp = Effects_Sqrt(temp) * 181;
+ ALOGV("get REVERB_PARAM_ROOM_HF_LEVEL, SQRT(a1^2 + 2 Cos a1 + 1) %d", temp);
+ temp = ((32767 - pReverb->m_nRoomLpfFbk) << 15) / temp;
+
+ ALOGV("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 = (int32_t *)&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;
+
+ ALOGV("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;
+ ALOGV("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);
+ ALOGV("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;
+ ALOGV("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);
+
+ ALOGV("get REVERB_PARAM_REFLECTIONS_LEVEL, %d", *pValue16);
+ if (param == REVERB_PARAM_REFLECTIONS_LEVEL) {
+ break;
+ }
+ pValue32 = (int32_t *)&pProperties->reflectionsDelay;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_REFLECTIONS_DELAY:
+ // convert samples to ms
+ *pValue32 = (pReverb->m_nEarlyDelay * 1000) / pReverb->m_nSamplingRate;
+
+ ALOGV("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);
+
+ ALOGV("get REVERB_PARAM_REVERB_LEVEL %d", *pValue16);
+
+ if (param == REVERB_PARAM_REVERB_LEVEL) {
+ break;
+ }
+ pValue32 = (int32_t *)&pProperties->reverbDelay;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_REVERB_DELAY:
+ // convert samples to ms
+ *pValue32 = (pReverb->m_nLateDelay * 1000) / pReverb->m_nSamplingRate;
+
+ ALOGV("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;
+ ALOGV("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;
+
+ ALOGV("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;
+
+ ALOGV("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;
+
+ ALOGV("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;
+ ALOGV("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));
+
+ ALOGV("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);
+ ALOGV("REVERB_PARAM_ROOM_HF_LEVEL, HF gain %d", temp);
+ temp = (1 << 30) / temp;
+ ALOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain %d", temp);
+ dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15);
+ ALOGV("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)));
+
+ ALOGV_IF(delta > (1<<30), " delta overflow %d", delta);
+
+ ALOGV("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;
+ }
+ ALOGV("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));
+ ALOGV("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;
+ ALOGV("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));
+
+ ALOGV("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;
+ ALOGV("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) {
+ ALOGV("REVERB_PARAM_DECAY_HF_RATIO HF gain overflow %d mB", temp);
+ temp = -4000;
+ }
+
+ temp = Effects_MillibelsToLinear16(temp);
+ ALOGV("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;
+
+ ALOGV("REVERB_PARAM_DECAY_HF_RATIO, dG2 %d, b %d, delta %d", dG2, b, delta);
+
+ }
+
+ ALOGV("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;
+ ALOGV("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;
+
+ ALOGV("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;
+
+ ALOGV("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;
+
+ ALOGV("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;
+
+ ALOGV("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);
+
+ ALOGV("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);
+
+ ALOGV("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;
+}
+
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
+ .tag = AUDIO_EFFECT_LIBRARY_TAG,
+ .version = EFFECT_LIBRARY_API_VERSION,
+ .name = "Test Equalizer Library",
+ .implementor = "The Android Open Source Project",
+ .query_num_effects = EffectQueryNumberEffects,
+ .query_effect = EffectQueryEffect,
+ .create_effect = EffectCreate,
+ .release_effect = EffectRelease,
+ .get_descriptor = EffectGetDescriptor,
+};
diff --git a/media/libeffects/testlibs/EffectReverb.h b/media/libeffects/testlibs/EffectReverb.h
new file mode 100644
index 0000000..1fb14a7
--- /dev/null
+++ b/media/libeffects/testlibs/EffectReverb.h
@@ -0,0 +1,452 @@
+/*
+ * 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 <audio_effects/effect_environmentalreverb.h>
+#include <audio_effects/effect_presetreverb.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 AUDIO_CHANNEL_OUT_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(const effect_uuid_t *effectUID,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_handle_t *pHandle);
+int EffectRelease(effect_handle_t handle);
+int EffectGetDescriptor(const effect_uuid_t *uuid,
+ effect_descriptor_t *pDescriptor);
+
+static int Reverb_Process(effect_handle_t self,
+ audio_buffer_t *inBuffer,
+ audio_buffer_t *outBuffer);
+static int Reverb_Command(effect_handle_t self,
+ uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData);
+static int Reverb_GetDescriptor(effect_handle_t self,
+ effect_descriptor_t *pDescriptor);
+
+/*------------------------------------
+ * internal functions
+ *------------------------------------
+*/
+
+int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset);
+int Reverb_setConfig(reverb_module_t *pRvbModule, effect_config_t *pConfig, bool init);
+void Reverb_getConfig(reverb_module_t *pRvbModule, effect_config_t *pConfig);
+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..76b5110
--- /dev/null
+++ b/media/libeffects/visualizer/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Visualizer library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ EffectVisualizer.cpp
+
+LOCAL_CFLAGS+= -O2
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libdl
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+LOCAL_MODULE:= libvisualizer
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, graphics corecg) \
+ $(call include-path-for, audio-effects)
+
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
new file mode 100644
index 0000000..bdb1a1c
--- /dev/null
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -0,0 +1,534 @@
+/*
+ * 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 <time.h>
+#include <audio_effects/effect_visualizer.h>
+
+
+extern "C" {
+
+// effect_handle_t interface implementation for visualizer effect
+extern 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_CONTROL_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST),
+ 0, // TODO
+ 1,
+ "Visualizer",
+ "The Android Open Source Project",
+};
+
+enum visualizer_state_e {
+ VISUALIZER_STATE_UNINITIALIZED,
+ VISUALIZER_STATE_INITIALIZED,
+ VISUALIZER_STATE_ACTIVE,
+};
+
+// maximum time since last capture buffer update before resetting capture buffer. This means
+// that the framework has stopped playing audio and we must start returning silence
+#define MAX_STALL_TIME_MS 1000
+
+struct VisualizerContext {
+ const struct effect_interface_s *mItfe;
+ effect_config_t mConfig;
+ uint32_t mCaptureIdx;
+ uint32_t mCaptureSize;
+ uint8_t mState;
+ uint8_t mCurrentBuf;
+ uint8_t mLastBuf;
+ struct timespec mBufferUpdateTime;
+ uint8_t mCaptureBuf[2][VISUALIZER_CAPTURE_SIZE_MAX];
+};
+
+//
+//--- Local functions
+//
+
+void Visualizer_reset(VisualizerContext *pContext)
+{
+ pContext->mCaptureIdx = 0;
+ pContext->mCurrentBuf = 0;
+ pContext->mLastBuf = 1;
+ pContext->mBufferUpdateTime.tv_sec = 0;
+ memset(pContext->mCaptureBuf[0], 0x80, VISUALIZER_CAPTURE_SIZE_MAX);
+ memset(pContext->mCaptureBuf[1], 0x80, VISUALIZER_CAPTURE_SIZE_MAX);
+}
+
+//----------------------------------------------------------------------------
+// Visualizer_setConfig()
+//----------------------------------------------------------------------------
+// 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_setConfig(VisualizerContext *pContext, effect_config_t *pConfig)
+{
+ ALOGV("Visualizer_setConfig 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 != AUDIO_CHANNEL_OUT_STEREO) return -EINVAL;
+ if (pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_WRITE &&
+ pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_ACCUMULATE) return -EINVAL;
+ if (pConfig->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
+
+ memcpy(&pContext->mConfig, pConfig, sizeof(effect_config_t));
+
+ Visualizer_reset(pContext);
+
+ return 0;
+}
+
+
+//----------------------------------------------------------------------------
+// Visualizer_getConfig()
+//----------------------------------------------------------------------------
+// Purpose: Get input and output audio configuration.
+//
+// Inputs:
+// pContext: effect engine context
+// pConfig: pointer to effect_config_t structure holding input and output
+// configuration parameters
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+void Visualizer_getConfig(VisualizerContext *pContext, effect_config_t *pConfig)
+{
+ memcpy(pConfig, &pContext->mConfig, sizeof(effect_config_t));
+}
+
+
+//----------------------------------------------------------------------------
+// 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 = AUDIO_CHANNEL_OUT_STEREO;
+ pContext->mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ 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 = AUDIO_CHANNEL_OUT_STEREO;
+ pContext->mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ 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_setConfig(pContext, &pContext->mConfig);
+
+ return 0;
+}
+
+//
+//--- Effect Library Interface Implementation
+//
+
+int VisualizerLib_QueryNumberEffects(uint32_t *pNumEffects) {
+ *pNumEffects = 1;
+ return 0;
+}
+
+int VisualizerLib_QueryEffect(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;
+}
+
+int VisualizerLib_Create(const effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_handle_t *pHandle) {
+ int ret;
+ int i;
+
+ if (pHandle == 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) {
+ ALOGW("VisualizerLib_Create() init failed");
+ delete pContext;
+ return ret;
+ }
+
+ *pHandle = (effect_handle_t)pContext;
+
+ pContext->mState = VISUALIZER_STATE_INITIALIZED;
+
+ ALOGV("VisualizerLib_Create %p", pContext);
+
+ return 0;
+
+}
+
+int VisualizerLib_Release(effect_handle_t handle) {
+ VisualizerContext * pContext = (VisualizerContext *)handle;
+
+ ALOGV("VisualizerLib_Release %p", handle);
+ if (pContext == NULL) {
+ return -EINVAL;
+ }
+ pContext->mState = VISUALIZER_STATE_UNINITIALIZED;
+ delete pContext;
+
+ return 0;
+}
+
+int VisualizerLib_GetDescriptor(const effect_uuid_t *uuid,
+ effect_descriptor_t *pDescriptor) {
+
+ if (pDescriptor == NULL || uuid == NULL){
+ ALOGV("VisualizerLib_GetDescriptor() called with NULL pointer");
+ return -EINVAL;
+ }
+
+ if (memcmp(uuid, &gVisualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0) {
+ memcpy(pDescriptor, &gVisualizerDescriptor, sizeof(effect_descriptor_t));
+ return 0;
+ }
+
+ return -EINVAL;
+} /* end VisualizerLib_GetDescriptor */
+
+//
+//--- Effect Control Interface Implementation
+//
+
+static inline int16_t clamp16(int32_t sample)
+{
+ if ((sample>>15) ^ (sample>>31))
+ sample = 0x7FFF ^ (sample>>31);
+ return sample;
+}
+
+int Visualizer_process(
+ effect_handle_t self,audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
+{
+ VisualizerContext * pContext = (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
+
+ // derive capture scaling factor from peak value in current buffer
+ // this gives more interesting captures for display.
+ int32_t shift = 32;
+ int len = inBuffer->frameCount * 2;
+ for (int i = 0; i < len; i++) {
+ int32_t smp = inBuffer->s16[i];
+ if (smp < 0) smp = -smp - 1; // take care to keep the max negative in range
+ int32_t clz = __builtin_clz(smp);
+ if (shift > clz) shift = clz;
+ }
+ // A maximum amplitude signal will have 17 leading zeros, which we want to
+ // translate to a shift of 8 (for converting 16 bit to 8 bit)
+ shift = 25 - shift;
+ // Never scale by less than 8 to avoid returning unaltered PCM signal.
+ if (shift < 3) {
+ shift = 3;
+ }
+ // add one to combine the division by 2 needed after summing left and right channels below
+ shift++;
+
+ 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 >> shift;
+ 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;
+
+ // update last buffer update time stamp
+ if (clock_gettime(CLOCK_MONOTONIC, &pContext->mBufferUpdateTime) < 0) {
+ pContext->mBufferUpdateTime.tv_sec = 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
+
+int Visualizer_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
+ void *pCmdData, uint32_t *replySize, void *pReplyData) {
+
+ VisualizerContext * pContext = (VisualizerContext *)self;
+ int retsize;
+
+ if (pContext == NULL || pContext->mState == VISUALIZER_STATE_UNINITIALIZED) {
+ return -EINVAL;
+ }
+
+// ALOGV("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_SET_CONFIG:
+ if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+ || pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Visualizer_setConfig(pContext,
+ (effect_config_t *) pCmdData);
+ break;
+ case EFFECT_CMD_GET_CONFIG:
+ if (pReplyData == NULL ||
+ *replySize != sizeof(effect_config_t)) {
+ return -EINVAL;
+ }
+ Visualizer_getConfig(pContext, (effect_config_t *)pReplyData);
+ 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;
+ ALOGV("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;
+ ALOGV("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 != VISUALIZER_PARAM_CAPTURE_SIZE) {
+ p->status = -EINVAL;
+ break;
+ }
+ ALOGV("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 != VISUALIZER_PARAM_CAPTURE_SIZE) {
+ *(int32_t *)pReplyData = -EINVAL;
+ break;;
+ }
+ pContext->mCaptureSize = *((uint32_t *)p->data + 1);
+ ALOGV("set mCaptureSize = %d", pContext->mCaptureSize);
+ } break;
+ case EFFECT_CMD_SET_DEVICE:
+ case EFFECT_CMD_SET_VOLUME:
+ case EFFECT_CMD_SET_AUDIO_MODE:
+ break;
+
+
+ case VISUALIZER_CMD_CAPTURE:
+ if (pReplyData == NULL || *replySize != pContext->mCaptureSize) {
+ ALOGV("VISUALIZER_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);
+ // if audio framework has stopped playing audio although the effect is still
+ // active we must clear the capture buffer to return silence
+ if ((pContext->mLastBuf == pContext->mCurrentBuf) &&
+ (pContext->mBufferUpdateTime.tv_sec != 0)) {
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
+ time_t secs = ts.tv_sec - pContext->mBufferUpdateTime.tv_sec;
+ long nsec = ts.tv_nsec - pContext->mBufferUpdateTime.tv_nsec;
+ if (nsec < 0) {
+ --secs;
+ nsec += 1000000000;
+ }
+ uint32_t deltaMs = secs * 1000 + nsec / 1000000;
+ if (deltaMs > MAX_STALL_TIME_MS) {
+ ALOGV("capture going to idle");
+ pContext->mBufferUpdateTime.tv_sec = 0;
+ memset(pContext->mCaptureBuf[pContext->mCurrentBuf ^ 1],
+ 0x80,
+ pContext->mCaptureSize);
+ }
+ }
+ }
+ pContext->mLastBuf = pContext->mCurrentBuf;
+ } else {
+ memset(pReplyData, 0x80, pContext->mCaptureSize);
+ }
+
+ break;
+
+ default:
+ ALOGW("Visualizer_command invalid command %d",cmdCode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Effect Control Interface Implementation: get_descriptor */
+int Visualizer_getDescriptor(effect_handle_t self,
+ effect_descriptor_t *pDescriptor)
+{
+ VisualizerContext * pContext = (VisualizerContext *) self;
+
+ if (pContext == NULL || pDescriptor == NULL) {
+ ALOGV("Visualizer_getDescriptor() invalid param");
+ return -EINVAL;
+ }
+
+ memcpy(pDescriptor, &gVisualizerDescriptor, sizeof(effect_descriptor_t));
+
+ return 0;
+} /* end Visualizer_getDescriptor */
+
+// effect_handle_t interface implementation for visualizer effect
+const struct effect_interface_s gVisualizerInterface = {
+ Visualizer_process,
+ Visualizer_command,
+ Visualizer_getDescriptor,
+ NULL,
+};
+
+
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
+ tag : AUDIO_EFFECT_LIBRARY_TAG,
+ version : EFFECT_LIBRARY_API_VERSION,
+ name : "Visualizer Library",
+ implementor : "The Android Open Source Project",
+ query_num_effects : VisualizerLib_QueryNumberEffects,
+ query_effect : VisualizerLib_QueryEffect,
+ create_effect : VisualizerLib_Create,
+ release_effect : VisualizerLib_Release,
+ get_descriptor : VisualizerLib_GetDescriptor,
+};
+
+}; // extern "C"
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
new file mode 100644
index 0000000..c8e1dc7
--- /dev/null
+++ b/media/libmedia/Android.mk
@@ -0,0 +1,68 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ AudioParameter.cpp
+LOCAL_MODULE:= libmedia_helper
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ AudioTrack.cpp \
+ IAudioFlinger.cpp \
+ IAudioFlingerClient.cpp \
+ IAudioTrack.cpp \
+ IAudioRecord.cpp \
+ ICrypto.cpp \
+ AudioRecord.cpp \
+ AudioSystem.cpp \
+ mediaplayer.cpp \
+ IMediaPlayerService.cpp \
+ IMediaPlayerClient.cpp \
+ IMediaRecorderClient.cpp \
+ IMediaPlayer.cpp \
+ IMediaRecorder.cpp \
+ IStreamSource.cpp \
+ Metadata.cpp \
+ mediarecorder.cpp \
+ IMediaMetadataRetriever.cpp \
+ mediametadataretriever.cpp \
+ ToneGenerator.cpp \
+ JetPlayer.cpp \
+ IOMX.cpp \
+ IAudioPolicyService.cpp \
+ MediaScanner.cpp \
+ MediaScannerClient.cpp \
+ autodetect.cpp \
+ IMediaDeathNotifier.cpp \
+ MediaProfiles.cpp \
+ IEffect.cpp \
+ IEffectClient.cpp \
+ AudioEffect.cpp \
+ Visualizer.cpp \
+ MemoryLeakTrackUtil.cpp \
+ SoundPool.cpp \
+ SoundPoolThread.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libui libcutils libutils libbinder libsonivox libicuuc libexpat \
+ libcamera_client libstagefright_foundation \
+ libgui libdl libaudioutils libmedia_native
+
+LOCAL_WHOLE_STATIC_LIBRARY := libmedia_helper
+
+LOCAL_MODULE:= libmedia
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, graphics corecg) \
+ $(TOP)/frameworks/native/include/media/openmax \
+ external/icu4c/common \
+ external/expat/lib \
+ $(call include-path-for, audio-effects) \
+ $(call include-path-for, audio-utils)
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
new file mode 100644
index 0000000..34451ca
--- /dev/null
+++ b/media/libmedia/AudioEffect.cpp
@@ -0,0 +1,482 @@
+/*
+**
+** 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 <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 io
+ )
+ : mStatus(NO_INIT)
+{
+ mStatus = set(type, uuid, priority, cbf, user, sessionId, io);
+}
+
+AudioEffect::AudioEffect(const char *typeStr,
+ const char *uuidStr,
+ int32_t priority,
+ effect_callback_t cbf,
+ void* user,
+ int sessionId,
+ audio_io_handle_t io
+ )
+ : mStatus(NO_INIT)
+{
+ effect_uuid_t type;
+ effect_uuid_t *pType = NULL;
+ effect_uuid_t uuid;
+ effect_uuid_t *pUuid = NULL;
+
+ ALOGV("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, io);
+}
+
+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 io)
+{
+ sp<IEffect> iEffect;
+ sp<IMemory> cblk;
+ int enabled;
+
+ ALOGV("set %p mUserData: %p uuid: %p timeLow %08x", this, user, type, type ? type->timeLow : 0);
+
+ if (mIEffect != 0) {
+ ALOGW("Effect already in use");
+ return INVALID_OPERATION;
+ }
+
+ const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+ if (audioFlinger == 0) {
+ ALOGE("set(): Could not get audioflinger");
+ return NO_INIT;
+ }
+
+ if (type == NULL && uuid == NULL) {
+ ALOGW("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, io, mSessionId, &mStatus, &mId, &enabled);
+
+ if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
+ ALOGE("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;
+ ALOGE("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);
+ ALOGV("set() %p OK effect: %s id: %d status %d enabled %d", this, mDescriptor.name, mId, mStatus, mEnabled);
+
+ return mStatus;
+}
+
+
+AudioEffect::~AudioEffect()
+{
+ ALOGV("Destructor %p", this);
+
+ if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
+ 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 (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
+ }
+
+ status_t status = NO_ERROR;
+
+ AutoMutex lock(mLock);
+ if (enabled != mEnabled) {
+ if (enabled) {
+ ALOGV("enable %p", this);
+ status = mIEffect->enable();
+ } else {
+ ALOGV("disable %p", this);
+ status = mIEffect->disable();
+ }
+ if (status == NO_ERROR) {
+ mEnabled = enabled;
+ }
+ }
+ return status;
+}
+
+status_t AudioEffect::command(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *cmdData,
+ uint32_t *replySize,
+ void *replyData)
+{
+ if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
+ ALOGV("command() bad status %d", mStatus);
+ return mStatus;
+ }
+
+ if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
+ if (mEnabled == (cmdCode == EFFECT_CMD_ENABLE)) {
+ return NO_ERROR;
+ }
+ if (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL) {
+ return BAD_VALUE;
+ }
+ mLock.lock();
+ }
+
+ status_t status = mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData);
+
+ if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
+ if (status == NO_ERROR) {
+ status = *(status_t *)replyData;
+ }
+ if (status == NO_ERROR) {
+ mEnabled = (cmdCode == EFFECT_CMD_ENABLE);
+ }
+ mLock.unlock();
+ }
+
+ return status;
+}
+
+
+status_t AudioEffect::setParameter(effect_param_t *param)
+{
+ if (mStatus != NO_ERROR) {
+ return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
+ }
+
+ 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;
+
+ ALOGV("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 (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
+ }
+
+ 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 (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
+ }
+
+ 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 mStatus;
+ }
+
+ if (param == NULL || param->psize == 0 || param->vsize == 0) {
+ return BAD_VALUE;
+ }
+
+ ALOGV("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()
+{
+ ALOGW("IEffect died");
+ mStatus = DEAD_OBJECT;
+ if (mCbf != NULL) {
+ status_t status = DEAD_OBJECT;
+ mCbf(EVENT_ERROR, mUserData, &status);
+ }
+ mIEffect.clear();
+}
+
+// -------------------------------------------------------------------------
+
+void AudioEffect::controlStatusChanged(bool controlGranted)
+{
+ ALOGV("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 != NULL) {
+ mCbf(EVENT_CONTROL_STATUS_CHANGED, mUserData, &controlGranted);
+ }
+}
+
+void AudioEffect::enableStatusChanged(bool enabled)
+{
+ ALOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf);
+ if (mStatus == ALREADY_EXISTS) {
+ mEnabled = enabled;
+ if (mCbf != NULL) {
+ 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 != NULL && 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::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(const effect_uuid_t *uuid,
+ effect_descriptor_t *descriptor) /*const*/
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->getEffectDescriptor(uuid, descriptor);
+}
+
+
+status_t AudioEffect::queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->queryDefaultPreProcessing(audioSession, descriptors, count);
+}
+// -------------------------------------------------------------------------
+
+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/AudioParameter.cpp b/media/libmedia/AudioParameter.cpp
new file mode 100644
index 0000000..abc7b3f
--- /dev/null
+++ b/media/libmedia/AudioParameter.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2006-2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "AudioParameter"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+
+#include <media/AudioParameter.h>
+
+namespace android {
+
+const char *AudioParameter::keyRouting = "routing";
+const char *AudioParameter::keySamplingRate = "sampling_rate";
+const char *AudioParameter::keyFormat = "format";
+const char *AudioParameter::keyChannels = "channels";
+const char *AudioParameter::keyFrameCount = "frame_count";
+const char *AudioParameter::keyInputSource = "input_source";
+
+AudioParameter::AudioParameter(const String8& keyValuePairs)
+{
+ char *str = new char[keyValuePairs.length()+1];
+ mKeyValuePairs = keyValuePairs;
+
+ strcpy(str, keyValuePairs.string());
+ char *pair = strtok(str, ";");
+ while (pair != NULL) {
+ if (strlen(pair) != 0) {
+ size_t eqIdx = strcspn(pair, "=");
+ String8 key = String8(pair, eqIdx);
+ String8 value;
+ if (eqIdx == strlen(pair)) {
+ value = String8("");
+ } else {
+ value = String8(pair + eqIdx + 1);
+ }
+ if (mParameters.indexOfKey(key) < 0) {
+ mParameters.add(key, value);
+ } else {
+ mParameters.replaceValueFor(key, value);
+ }
+ } else {
+ ALOGV("AudioParameter() cstor empty key value pair");
+ }
+ pair = strtok(NULL, ";");
+ }
+
+ delete[] str;
+}
+
+AudioParameter::~AudioParameter()
+{
+ mParameters.clear();
+}
+
+String8 AudioParameter::toString()
+{
+ String8 str = String8("");
+
+ size_t size = mParameters.size();
+ for (size_t i = 0; i < size; i++) {
+ str += mParameters.keyAt(i);
+ str += "=";
+ str += mParameters.valueAt(i);
+ if (i < (size - 1)) str += ";";
+ }
+ return str;
+}
+
+status_t AudioParameter::add(const String8& key, const String8& value)
+{
+ if (mParameters.indexOfKey(key) < 0) {
+ mParameters.add(key, value);
+ return NO_ERROR;
+ } else {
+ mParameters.replaceValueFor(key, value);
+ return ALREADY_EXISTS;
+ }
+}
+
+status_t AudioParameter::addInt(const String8& key, const int value)
+{
+ char str[12];
+ if (snprintf(str, 12, "%d", value) > 0) {
+ String8 str8 = String8(str);
+ return add(key, str8);
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+status_t AudioParameter::addFloat(const String8& key, const float value)
+{
+ char str[23];
+ if (snprintf(str, 23, "%.10f", value) > 0) {
+ String8 str8 = String8(str);
+ return add(key, str8);
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+status_t AudioParameter::remove(const String8& key)
+{
+ if (mParameters.indexOfKey(key) >= 0) {
+ mParameters.removeItem(key);
+ return NO_ERROR;
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+status_t AudioParameter::get(const String8& key, String8& value)
+{
+ if (mParameters.indexOfKey(key) >= 0) {
+ value = mParameters.valueFor(key);
+ return NO_ERROR;
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+status_t AudioParameter::getInt(const String8& key, int& value)
+{
+ String8 str8;
+ status_t result = get(key, str8);
+ value = 0;
+ if (result == NO_ERROR) {
+ int val;
+ if (sscanf(str8.string(), "%d", &val) == 1) {
+ value = val;
+ } else {
+ result = INVALID_OPERATION;
+ }
+ }
+ return result;
+}
+
+status_t AudioParameter::getFloat(const String8& key, float& value)
+{
+ String8 str8;
+ status_t result = get(key, str8);
+ value = 0;
+ if (result == NO_ERROR) {
+ float val;
+ if (sscanf(str8.string(), "%f", &val) == 1) {
+ value = val;
+ } else {
+ result = INVALID_OPERATION;
+ }
+ }
+ return result;
+}
+
+status_t AudioParameter::getAt(size_t index, String8& key, String8& value)
+{
+ if (mParameters.size() > index) {
+ key = mParameters.keyAt(index);
+ value = mParameters.valueAt(index);
+ return NO_ERROR;
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+}; // namespace android
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
new file mode 100644
index 0000000..70ec593
--- /dev/null
+++ b/media/libmedia/AudioRecord.cpp
@@ -0,0 +1,844 @@
+/*
+**
+** 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.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AudioRecord"
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <sched.h>
+#include <sys/resource.h>
+
+#include <private/media/AudioTrackShared.h>
+
+#include <media/AudioSystem.h>
+#include <media/AudioRecord.h>
+#include <media/mediarecorder.h>
+
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <utils/Timers.h>
+#include <utils/Atomic.h>
+
+#include <system/audio.h>
+#include <cutils/bitops.h>
+#include <cutils/compiler.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+// static
+status_t AudioRecord::getMinFrameCount(
+ int* frameCount,
+ uint32_t sampleRate,
+ audio_format_t format,
+ int channelCount)
+{
+ size_t size = 0;
+ if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &size)
+ != NO_ERROR) {
+ ALOGE("AudioSystem could not query the input buffer size.");
+ return NO_INIT;
+ }
+
+ if (size == 0) {
+ ALOGE("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 (audio_is_linear_pcm(format)) {
+ size /= channelCount * audio_bytes_per_sample(format);
+ }
+
+ *frameCount = size;
+ return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+
+AudioRecord::AudioRecord()
+ : mStatus(NO_INIT), mSessionId(0),
+ mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT)
+{
+}
+
+AudioRecord::AudioRecord(
+ audio_source_t inputSource,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ record_flags flags,
+ callback_t cbf,
+ void* user,
+ int notificationFrames,
+ int sessionId)
+ : mStatus(NO_INIT), mSessionId(0),
+ mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT)
+{
+ mStatus = set(inputSource, sampleRate, format, channelMask,
+ frameCount, flags, cbf, user, notificationFrames, sessionId);
+}
+
+AudioRecord::~AudioRecord()
+{
+ if (mStatus == NO_ERROR) {
+ // Make sure that callback function exits in the case where
+ // it is looping on buffer empty condition in obtainBuffer().
+ // Otherwise the callback thread will never exit.
+ stop();
+ if (mClientRecordThread != 0) {
+ mClientRecordThread->requestExitAndWait();
+ mClientRecordThread.clear();
+ }
+ mAudioRecord.clear();
+ IPCThreadState::self()->flushCommands();
+ AudioSystem::releaseAudioSessionId(mSessionId);
+ }
+}
+
+status_t AudioRecord::set(
+ audio_source_t inputSource,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ record_flags flags,
+ callback_t cbf,
+ void* user,
+ int notificationFrames,
+ bool threadCanCallJava,
+ int sessionId)
+{
+
+ ALOGV("set(): sampleRate %d, channelMask %d, frameCount %d",sampleRate, channelMask, frameCount);
+
+ AutoMutex lock(mLock);
+
+ if (mAudioRecord != 0) {
+ return INVALID_OPERATION;
+ }
+
+ if (inputSource == AUDIO_SOURCE_DEFAULT) {
+ inputSource = AUDIO_SOURCE_MIC;
+ }
+
+ if (sampleRate == 0) {
+ sampleRate = DEFAULT_SAMPLE_RATE;
+ }
+ // these below should probably come from the audioFlinger too...
+ if (format == AUDIO_FORMAT_DEFAULT) {
+ format = AUDIO_FORMAT_PCM_16_BIT;
+ }
+ // validate parameters
+ if (!audio_is_valid_format(format)) {
+ ALOGE("Invalid format");
+ return BAD_VALUE;
+ }
+
+ if (!audio_is_input_channel(channelMask)) {
+ return BAD_VALUE;
+ }
+
+ int channelCount = popcount(channelMask);
+
+ if (sessionId == 0 ) {
+ mSessionId = AudioSystem::newAudioSessionId();
+ } else {
+ mSessionId = sessionId;
+ }
+ ALOGV("set(): mSessionId %d", mSessionId);
+
+ audio_io_handle_t input = AudioSystem::getInput(inputSource,
+ sampleRate,
+ format,
+ channelMask,
+ (audio_in_acoustics_t)flags,
+ mSessionId);
+ if (input == 0) {
+ ALOGE("Could not get audio input for record source %d", inputSource);
+ return BAD_VALUE;
+ }
+
+ // validate framecount
+ int minFrameCount = 0;
+ status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelCount);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
+
+ if (frameCount == 0) {
+ frameCount = minFrameCount;
+ } else if (frameCount < minFrameCount) {
+ return BAD_VALUE;
+ }
+
+ if (notificationFrames == 0) {
+ notificationFrames = frameCount/2;
+ }
+
+ // create the IAudioRecord
+ status = openRecord_l(sampleRate, format, channelMask,
+ frameCount, input);
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ if (cbf != NULL) {
+ mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava);
+ }
+
+ mStatus = NO_ERROR;
+
+ mFormat = format;
+ // Update buffer size in case it has been limited by AudioFlinger during track creation
+ mFrameCount = mCblk->frameCount;
+ mChannelCount = (uint8_t)channelCount;
+ mChannelMask = channelMask;
+ mActive = 0;
+ mCbf = cbf;
+ mNotificationFrames = notificationFrames;
+ mRemainingFrames = notificationFrames;
+ mUserData = user;
+ // TODO: add audio hardware input latency here
+ mLatency = (1000*mFrameCount) / sampleRate;
+ mMarkerPosition = 0;
+ mMarkerReached = false;
+ mNewPosition = 0;
+ mUpdatePeriod = 0;
+ mInputSource = inputSource;
+ mFlags = flags;
+ mInput = input;
+ AudioSystem::acquireAudioSessionId(mSessionId);
+
+ return NO_ERROR;
+}
+
+status_t AudioRecord::initCheck() const
+{
+ return mStatus;
+}
+
+// -------------------------------------------------------------------------
+
+uint32_t AudioRecord::latency() const
+{
+ return mLatency;
+}
+
+audio_format_t AudioRecord::format() const
+{
+ return mFormat;
+}
+
+int AudioRecord::channelCount() const
+{
+ return mChannelCount;
+}
+
+uint32_t AudioRecord::frameCount() const
+{
+ return mFrameCount;
+}
+
+size_t AudioRecord::frameSize() const
+{
+ if (audio_is_linear_pcm(mFormat)) {
+ return channelCount()*audio_bytes_per_sample(mFormat);
+ } else {
+ return sizeof(uint8_t);
+ }
+}
+
+audio_source_t AudioRecord::inputSource() const
+{
+ return mInputSource;
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioRecord::start()
+{
+ status_t ret = NO_ERROR;
+ sp<ClientRecordThread> t = mClientRecordThread;
+
+ ALOGV("start");
+
+ if (t != 0) {
+ if (t->exitPending()) {
+ if (t->requestExitAndWait() == WOULD_BLOCK) {
+ ALOGE("AudioRecord::start called from thread");
+ return WOULD_BLOCK;
+ }
+ }
+ }
+
+ AutoMutex lock(mLock);
+ // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
+ // while we are accessing the cblk
+ sp<IAudioRecord> audioRecord = mAudioRecord;
+ sp<IMemory> iMem = mCblkMemory;
+ audio_track_cblk_t* cblk = mCblk;
+ if (mActive == 0) {
+ mActive = 1;
+
+ pid_t tid;
+ if (t != 0) {
+ mReadyToRun = WOULD_BLOCK;
+ t->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
+ tid = t->getTid(); // pid_t is unknown until run()
+ ALOGV("getTid=%d", tid);
+ if (tid == -1) {
+ tid = 0;
+ }
+ // thread blocks in readyToRun()
+ } else {
+ tid = 0; // not gettid()
+ }
+
+ cblk->lock.lock();
+ if (!(cblk->flags & CBLK_INVALID_MSK)) {
+ cblk->lock.unlock();
+ ALOGV("mAudioRecord->start(tid=%d)", tid);
+ ret = mAudioRecord->start(tid);
+ cblk->lock.lock();
+ if (ret == DEAD_OBJECT) {
+ android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
+ }
+ }
+ if (cblk->flags & CBLK_INVALID_MSK) {
+ ret = restoreRecord_l(cblk);
+ }
+ cblk->lock.unlock();
+ if (ret == NO_ERROR) {
+ mNewPosition = cblk->user + mUpdatePeriod;
+ cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+ cblk->waitTimeMs = 0;
+ if (t != 0) {
+ // thread unblocks in readyToRun() and returns NO_ERROR
+ mReadyToRun = NO_ERROR;
+ mCondition.signal();
+ } else {
+ mPreviousPriority = getpriority(PRIO_PROCESS, 0);
+ mPreviousSchedulingGroup = androidGetThreadSchedulingGroup(0);
+ androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
+ }
+ } else {
+ mActive = 0;
+ // thread unblocks in readyToRun() and returns NO_INIT
+ mReadyToRun = NO_INIT;
+ mCondition.signal();
+ }
+ }
+
+ return ret;
+}
+
+status_t AudioRecord::stop()
+{
+ sp<ClientRecordThread> t = mClientRecordThread;
+
+ ALOGV("stop");
+
+ AutoMutex lock(mLock);
+ if (mActive == 1) {
+ mActive = 0;
+ mCblk->cv.signal();
+ mAudioRecord->stop();
+ // the record head position will reset to 0, so if a marker is set, we need
+ // to activate it again
+ mMarkerReached = false;
+ if (t != 0) {
+ t->requestExit();
+ } else {
+ setpriority(PRIO_PROCESS, 0, mPreviousPriority);
+ androidSetThreadSchedulingGroup(0, mPreviousSchedulingGroup);
+ }
+ }
+
+ return NO_ERROR;
+}
+
+bool AudioRecord::stopped() const
+{
+ return !mActive;
+}
+
+uint32_t AudioRecord::getSampleRate() const
+{
+ AutoMutex lock(mLock);
+ return mCblk->sampleRate;
+}
+
+status_t AudioRecord::setMarkerPosition(uint32_t marker)
+{
+ if (mCbf == NULL) return INVALID_OPERATION;
+
+ mMarkerPosition = marker;
+ mMarkerReached = false;
+
+ return NO_ERROR;
+}
+
+status_t AudioRecord::getMarkerPosition(uint32_t *marker) const
+{
+ if (marker == NULL) return BAD_VALUE;
+
+ *marker = mMarkerPosition;
+
+ return NO_ERROR;
+}
+
+status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
+{
+ if (mCbf == NULL) return INVALID_OPERATION;
+
+ uint32_t curPosition;
+ getPosition(&curPosition);
+ mNewPosition = curPosition + updatePeriod;
+ mUpdatePeriod = updatePeriod;
+
+ return NO_ERROR;
+}
+
+status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const
+{
+ if (updatePeriod == NULL) return BAD_VALUE;
+
+ *updatePeriod = mUpdatePeriod;
+
+ return NO_ERROR;
+}
+
+status_t AudioRecord::getPosition(uint32_t *position) const
+{
+ if (position == NULL) return BAD_VALUE;
+
+ AutoMutex lock(mLock);
+ *position = mCblk->user;
+
+ return NO_ERROR;
+}
+
+unsigned int AudioRecord::getInputFramesLost() const
+{
+ if (mActive)
+ return AudioSystem::getInputFramesLost(mInput);
+ else
+ return 0;
+}
+
+// -------------------------------------------------------------------------
+
+// must be called with mLock held
+status_t AudioRecord::openRecord_l(
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ audio_io_handle_t input)
+{
+ status_t status;
+ const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+ if (audioFlinger == 0) {
+ return NO_INIT;
+ }
+
+ sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input,
+ sampleRate, format,
+ channelMask,
+ frameCount,
+ IAudioFlinger::TRACK_DEFAULT,
+ &mSessionId,
+ &status);
+
+ if (record == 0) {
+ ALOGE("AudioFlinger could not create record track, status: %d", status);
+ return status;
+ }
+ sp<IMemory> cblk = record->getCblk();
+ if (cblk == 0) {
+ ALOGE("Could not get control block");
+ return NO_INIT;
+ }
+ mAudioRecord.clear();
+ mAudioRecord = record;
+ mCblkMemory.clear();
+ mCblkMemory = cblk;
+ mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
+ mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
+ android_atomic_and(~CBLK_DIRECTION_MSK, &mCblk->flags);
+ mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+ mCblk->waitTimeMs = 0;
+ return NO_ERROR;
+}
+
+status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
+{
+ AutoMutex lock(mLock);
+ int active;
+ status_t result = NO_ERROR;
+ audio_track_cblk_t* cblk = mCblk;
+ uint32_t framesReq = audioBuffer->frameCount;
+ uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
+
+ audioBuffer->frameCount = 0;
+ audioBuffer->size = 0;
+
+ uint32_t framesReady = cblk->framesReady();
+
+ if (framesReady == 0) {
+ cblk->lock.lock();
+ goto start_loop_here;
+ while (framesReady == 0) {
+ active = mActive;
+ if (CC_UNLIKELY(!active)) {
+ cblk->lock.unlock();
+ return NO_MORE_BUFFERS;
+ }
+ if (CC_UNLIKELY(!waitCount)) {
+ cblk->lock.unlock();
+ return WOULD_BLOCK;
+ }
+ if (!(cblk->flags & CBLK_INVALID_MSK)) {
+ mLock.unlock();
+ result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
+ cblk->lock.unlock();
+ mLock.lock();
+ if (mActive == 0) {
+ return status_t(STOPPED);
+ }
+ cblk->lock.lock();
+ }
+ if (cblk->flags & CBLK_INVALID_MSK) {
+ goto create_new_record;
+ }
+ if (CC_UNLIKELY(result != NO_ERROR)) {
+ cblk->waitTimeMs += waitTimeMs;
+ if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
+ ALOGW( "obtainBuffer timed out (is the CPU pegged?) "
+ "user=%08x, server=%08x", cblk->user, cblk->server);
+ cblk->lock.unlock();
+ result = mAudioRecord->start(0); // callback thread hasn't changed
+ cblk->lock.lock();
+ if (result == DEAD_OBJECT) {
+ android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
+create_new_record:
+ result = AudioRecord::restoreRecord_l(cblk);
+ }
+ if (result != NO_ERROR) {
+ ALOGW("obtainBuffer create Track error %d", result);
+ cblk->lock.unlock();
+ return result;
+ }
+ cblk->waitTimeMs = 0;
+ }
+ if (--waitCount == 0) {
+ cblk->lock.unlock();
+ return TIMED_OUT;
+ }
+ }
+ // read the server count again
+ start_loop_here:
+ framesReady = cblk->framesReady();
+ }
+ cblk->lock.unlock();
+ }
+
+ cblk->waitTimeMs = 0;
+
+ if (framesReq > framesReady) {
+ framesReq = framesReady;
+ }
+
+ uint32_t u = cblk->user;
+ uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
+
+ if (u + framesReq > bufferEnd) {
+ framesReq = bufferEnd - u;
+ }
+
+ audioBuffer->flags = 0;
+ audioBuffer->channelCount= mChannelCount;
+ audioBuffer->format = mFormat;
+ audioBuffer->frameCount = framesReq;
+ audioBuffer->size = framesReq*cblk->frameSize;
+ audioBuffer->raw = (int8_t*)cblk->buffer(u);
+ active = mActive;
+ return active ? status_t(NO_ERROR) : status_t(STOPPED);
+}
+
+void AudioRecord::releaseBuffer(Buffer* audioBuffer)
+{
+ AutoMutex lock(mLock);
+ mCblk->stepUser(audioBuffer->frameCount);
+}
+
+audio_io_handle_t AudioRecord::getInput() const
+{
+ AutoMutex lock(mLock);
+ return mInput;
+}
+
+// must be called with mLock held
+audio_io_handle_t AudioRecord::getInput_l()
+{
+ mInput = AudioSystem::getInput(mInputSource,
+ mCblk->sampleRate,
+ mFormat,
+ mChannelMask,
+ (audio_in_acoustics_t)mFlags,
+ mSessionId);
+ return mInput;
+}
+
+int AudioRecord::getSessionId() const
+{
+ return mSessionId;
+}
+
+// -------------------------------------------------------------------------
+
+ssize_t AudioRecord::read(void* buffer, size_t userSize)
+{
+ ssize_t read = 0;
+ Buffer audioBuffer;
+ int8_t *dst = static_cast<int8_t*>(buffer);
+
+ if (ssize_t(userSize) < 0) {
+ // sanity-check. user is most-likely passing an error code.
+ ALOGE("AudioRecord::read(buffer=%p, size=%u (%d)",
+ buffer, userSize, userSize);
+ return BAD_VALUE;
+ }
+
+ mLock.lock();
+ // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
+ // while we are accessing the cblk
+ sp<IAudioRecord> audioRecord = mAudioRecord;
+ sp<IMemory> iMem = mCblkMemory;
+ mLock.unlock();
+
+ do {
+
+ audioBuffer.frameCount = userSize/frameSize();
+
+ // By using a wait count corresponding to twice the timeout period in
+ // obtainBuffer() we give a chance to recover once for a read timeout
+ // (if media_server crashed for instance) before returning a length of
+ // 0 bytes read to the client
+ status_t err = obtainBuffer(&audioBuffer, ((2 * MAX_RUN_TIMEOUT_MS) / WAIT_PERIOD_MS));
+ if (err < 0) {
+ // out of buffers, return #bytes written
+ if (err == status_t(NO_MORE_BUFFERS))
+ break;
+ if (err == status_t(TIMED_OUT))
+ err = 0;
+ return ssize_t(err);
+ }
+
+ size_t bytesRead = audioBuffer.size;
+ memcpy(dst, audioBuffer.i8, bytesRead);
+
+ dst += bytesRead;
+ userSize -= bytesRead;
+ read += bytesRead;
+
+ releaseBuffer(&audioBuffer);
+ } while (userSize);
+
+ return read;
+}
+
+// -------------------------------------------------------------------------
+
+bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
+{
+ Buffer audioBuffer;
+ uint32_t frames = mRemainingFrames;
+ size_t readSize;
+
+ mLock.lock();
+ // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
+ // while we are accessing the cblk
+ sp<IAudioRecord> audioRecord = mAudioRecord;
+ sp<IMemory> iMem = mCblkMemory;
+ audio_track_cblk_t* cblk = mCblk;
+ mLock.unlock();
+
+ // Manage marker callback
+ if (!mMarkerReached && (mMarkerPosition > 0)) {
+ if (cblk->user >= mMarkerPosition) {
+ mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition);
+ mMarkerReached = true;
+ }
+ }
+
+ // Manage new position callback
+ if (mUpdatePeriod > 0) {
+ while (cblk->user >= mNewPosition) {
+ mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition);
+ mNewPosition += mUpdatePeriod;
+ }
+ }
+
+ do {
+ audioBuffer.frameCount = frames;
+ // Calling obtainBuffer() with a wait count of 1
+ // limits wait time to WAIT_PERIOD_MS. This prevents from being
+ // stuck here not being able to handle timed events (position, markers).
+ status_t err = obtainBuffer(&audioBuffer, 1);
+ if (err < NO_ERROR) {
+ if (err != TIMED_OUT) {
+ ALOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
+ return false;
+ }
+ break;
+ }
+ if (err == status_t(STOPPED)) return false;
+
+ size_t reqSize = audioBuffer.size;
+ mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
+ readSize = audioBuffer.size;
+
+ // Sanity check on returned size
+ if (ssize_t(readSize) <= 0) {
+ // The callback is done filling buffers
+ // Keep this thread going to handle timed events and
+ // still try to get more data in intervals of WAIT_PERIOD_MS
+ // but don't just loop and block the CPU, so wait
+ usleep(WAIT_PERIOD_MS*1000);
+ break;
+ }
+ if (readSize > reqSize) readSize = reqSize;
+
+ audioBuffer.size = readSize;
+ audioBuffer.frameCount = readSize/frameSize();
+ frames -= audioBuffer.frameCount;
+
+ releaseBuffer(&audioBuffer);
+
+ } while (frames);
+
+
+ // Manage overrun callback
+ if (mActive && (cblk->framesAvailable() == 0)) {
+ ALOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
+ if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) {
+ mCbf(EVENT_OVERRUN, mUserData, 0);
+ }
+ }
+
+ if (frames == 0) {
+ mRemainingFrames = mNotificationFrames;
+ } else {
+ mRemainingFrames = frames;
+ }
+ return true;
+}
+
+// must be called with mLock and cblk.lock held. Callers must also hold strong references on
+// the IAudioRecord and IMemory in case they are recreated here.
+// If the IAudioRecord is successfully restored, the cblk pointer is updated
+status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
+{
+ status_t result;
+
+ if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) {
+ ALOGW("dead IAudioRecord, creating a new one");
+ // signal old cblk condition so that other threads waiting for available buffers stop
+ // waiting now
+ cblk->cv.broadcast();
+ cblk->lock.unlock();
+
+ // if the new IAudioRecord is created, openRecord_l() will modify the
+ // following member variables: mAudioRecord, mCblkMemory and mCblk.
+ // It will also delete the strong references on previous IAudioRecord and IMemory
+ result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask,
+ mFrameCount, getInput_l());
+ if (result == NO_ERROR) {
+ result = mAudioRecord->start(0); // callback thread hasn't changed
+ }
+ if (result != NO_ERROR) {
+ mActive = false;
+ }
+
+ // signal old cblk condition for other threads waiting for restore completion
+ android_atomic_or(CBLK_RESTORED_ON, &cblk->flags);
+ cblk->cv.broadcast();
+ } else {
+ if (!(cblk->flags & CBLK_RESTORED_MSK)) {
+ ALOGW("dead IAudioRecord, waiting for a new one to be created");
+ mLock.unlock();
+ result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS));
+ cblk->lock.unlock();
+ mLock.lock();
+ } else {
+ ALOGW("dead IAudioRecord, already restored");
+ result = NO_ERROR;
+ cblk->lock.unlock();
+ }
+ if (result != NO_ERROR || mActive == 0) {
+ result = status_t(STOPPED);
+ }
+ }
+ ALOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x",
+ result, mActive, mCblk, cblk, mCblk->flags, cblk->flags);
+
+ if (result == NO_ERROR) {
+ // from now on we switch to the newly created cblk
+ cblk = mCblk;
+ }
+ cblk->lock.lock();
+
+ ALOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result);
+
+ return result;
+}
+
+// =========================================================================
+
+AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava)
+ : Thread(bCanCallJava), mReceiver(receiver)
+{
+}
+
+bool AudioRecord::ClientRecordThread::threadLoop()
+{
+ return mReceiver.processAudioBuffer(this);
+}
+
+status_t AudioRecord::ClientRecordThread::readyToRun()
+{
+ AutoMutex(mReceiver.mLock);
+ while (mReceiver.mReadyToRun == WOULD_BLOCK) {
+ mReceiver.mCondition.wait(mReceiver.mLock);
+ }
+ return mReceiver.mReadyToRun;
+}
+
+// -------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
new file mode 100644
index 0000000..33c7d03
--- /dev/null
+++ b/media/libmedia/AudioSystem.cpp
@@ -0,0 +1,770 @@
+/*
+ * Copyright (C) 2006-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_TAG "AudioSystem"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <binder/IServiceManager.h>
+#include <media/AudioSystem.h>
+#include <media/IAudioPolicyService.h>
+#include <math.h>
+
+#include <system/audio.h>
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+// client singleton for AudioFlinger binder interface
+Mutex AudioSystem::gLock;
+sp<IAudioFlinger> AudioSystem::gAudioFlinger;
+sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
+audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
+// Cached values
+
+DefaultKeyedVector<audio_stream_type_t, audio_io_handle_t> AudioSystem::gStreamOutputMap(0);
+DefaultKeyedVector<audio_io_handle_t, AudioSystem::OutputDescriptor *> AudioSystem::gOutputs(0);
+
+// Cached values for recording queries, all protected by gLock
+uint32_t AudioSystem::gPrevInSamplingRate = 16000;
+audio_format_t AudioSystem::gPrevInFormat = AUDIO_FORMAT_PCM_16_BIT;
+int AudioSystem::gPrevInChannelCount = 1;
+size_t AudioSystem::gInBuffSize = 0;
+
+
+// establish binder interface to AudioFlinger service
+const sp<IAudioFlinger>& AudioSystem::get_audio_flinger()
+{
+ Mutex::Autolock _l(gLock);
+ if (gAudioFlinger == 0) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder;
+ do {
+ binder = sm->getService(String16("media.audio_flinger"));
+ if (binder != 0)
+ break;
+ ALOGW("AudioFlinger not published, waiting...");
+ usleep(500000); // 0.5 s
+ } while (true);
+ if (gAudioFlingerClient == NULL) {
+ gAudioFlingerClient = new AudioFlingerClient();
+ } else {
+ if (gAudioErrorCallback) {
+ gAudioErrorCallback(NO_ERROR);
+ }
+ }
+ binder->linkToDeath(gAudioFlingerClient);
+ gAudioFlinger = interface_cast<IAudioFlinger>(binder);
+ gAudioFlinger->registerClient(gAudioFlingerClient);
+ }
+ ALOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");
+
+ return gAudioFlinger;
+}
+
+status_t AudioSystem::muteMicrophone(bool state) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->setMicMute(state);
+}
+
+status_t AudioSystem::isMicrophoneMuted(bool* state) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ *state = af->getMicMute();
+ return NO_ERROR;
+}
+
+status_t AudioSystem::setMasterVolume(float value)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ af->setMasterVolume(value);
+ return NO_ERROR;
+}
+
+status_t AudioSystem::setMasterMute(bool mute)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ af->setMasterMute(mute);
+ return NO_ERROR;
+}
+
+status_t AudioSystem::getMasterVolume(float* volume)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ *volume = af->masterVolume();
+ return NO_ERROR;
+}
+
+status_t AudioSystem::getMasterMute(bool* mute)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ *mute = af->masterMute();
+ return NO_ERROR;
+}
+
+status_t AudioSystem::setStreamVolume(audio_stream_type_t stream, float value,
+ audio_io_handle_t output)
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ af->setStreamVolume(stream, value, output);
+ return NO_ERROR;
+}
+
+status_t AudioSystem::setStreamMute(audio_stream_type_t stream, bool mute)
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ af->setStreamMute(stream, mute);
+ return NO_ERROR;
+}
+
+status_t AudioSystem::getStreamVolume(audio_stream_type_t stream, float* volume,
+ audio_io_handle_t output)
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ *volume = af->streamVolume(stream, output);
+ return NO_ERROR;
+}
+
+status_t AudioSystem::getStreamMute(audio_stream_type_t stream, bool* mute)
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) return BAD_VALUE;
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ *mute = af->streamMute(stream);
+ return NO_ERROR;
+}
+
+status_t AudioSystem::setMode(audio_mode_t mode)
+{
+ if (uint32_t(mode) >= AUDIO_MODE_CNT) return BAD_VALUE;
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->setMode(mode);
+}
+
+status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->setParameters(ioHandle, keyValuePairs);
+}
+
+String8 AudioSystem::getParameters(audio_io_handle_t ioHandle, const String8& keys) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ String8 result = String8("");
+ if (af == 0) return result;
+
+ result = af->getParameters(ioHandle, keys);
+ return result;
+}
+
+// convert volume steps to natural log scale
+
+// change this value to change volume scaling
+static const float dBPerStep = 0.5f;
+// shouldn't need to touch these
+static const float dBConvert = -dBPerStep * 2.302585093f / 20.0f;
+static const float dBConvertInverse = 1.0f / dBConvert;
+
+float AudioSystem::linearToLog(int volume)
+{
+ // float v = volume ? exp(float(100 - volume) * dBConvert) : 0;
+ // ALOGD("linearToLog(%d)=%f", volume, v);
+ // return v;
+ return volume ? exp(float(100 - volume) * dBConvert) : 0;
+}
+
+int AudioSystem::logToLinear(float volume)
+{
+ // int v = volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;
+ // ALOGD("logTolinear(%d)=%f", v, volume);
+ // return v;
+ return volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;
+}
+
+// DEPRECATED
+status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType) {
+ return getOutputSamplingRate(samplingRate, (audio_stream_type_t)streamType);
+}
+
+status_t AudioSystem::getOutputSamplingRate(int* samplingRate, audio_stream_type_t streamType)
+{
+ OutputDescriptor *outputDesc;
+ audio_io_handle_t output;
+
+ if (streamType == AUDIO_STREAM_DEFAULT) {
+ streamType = AUDIO_STREAM_MUSIC;
+ }
+
+ output = getOutput(streamType);
+ if (output == 0) {
+ return PERMISSION_DENIED;
+ }
+
+ gLock.lock();
+ outputDesc = AudioSystem::gOutputs.valueFor(output);
+ if (outputDesc == NULL) {
+ ALOGV("getOutputSamplingRate() no output descriptor for output %d in gOutputs", output);
+ gLock.unlock();
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ *samplingRate = af->sampleRate(output);
+ } else {
+ ALOGV("getOutputSamplingRate() reading from output desc");
+ *samplingRate = outputDesc->samplingRate;
+ gLock.unlock();
+ }
+
+ ALOGV("getOutputSamplingRate() streamType %d, output %d, sampling rate %d", streamType, output, *samplingRate);
+
+ return NO_ERROR;
+}
+
+// DEPRECATED
+status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType) {
+ return getOutputFrameCount(frameCount, (audio_stream_type_t)streamType);
+}
+
+status_t AudioSystem::getOutputFrameCount(int* frameCount, audio_stream_type_t streamType)
+{
+ OutputDescriptor *outputDesc;
+ audio_io_handle_t output;
+
+ if (streamType == AUDIO_STREAM_DEFAULT) {
+ streamType = AUDIO_STREAM_MUSIC;
+ }
+
+ output = getOutput(streamType);
+ if (output == 0) {
+ return PERMISSION_DENIED;
+ }
+
+ gLock.lock();
+ outputDesc = AudioSystem::gOutputs.valueFor(output);
+ if (outputDesc == NULL) {
+ gLock.unlock();
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ *frameCount = af->frameCount(output);
+ } else {
+ *frameCount = outputDesc->frameCount;
+ gLock.unlock();
+ }
+
+ ALOGV("getOutputFrameCount() streamType %d, output %d, frameCount %d", streamType, output, *frameCount);
+
+ return NO_ERROR;
+}
+
+status_t AudioSystem::getOutputLatency(uint32_t* latency, audio_stream_type_t streamType)
+{
+ OutputDescriptor *outputDesc;
+ audio_io_handle_t output;
+
+ if (streamType == AUDIO_STREAM_DEFAULT) {
+ streamType = AUDIO_STREAM_MUSIC;
+ }
+
+ output = getOutput(streamType);
+ if (output == 0) {
+ return PERMISSION_DENIED;
+ }
+
+ gLock.lock();
+ outputDesc = AudioSystem::gOutputs.valueFor(output);
+ if (outputDesc == NULL) {
+ gLock.unlock();
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ *latency = af->latency(output);
+ } else {
+ *latency = outputDesc->latency;
+ gLock.unlock();
+ }
+
+ ALOGV("getOutputLatency() streamType %d, output %d, latency %d", streamType, output, *latency);
+
+ return NO_ERROR;
+}
+
+status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount,
+ size_t* buffSize)
+{
+ gLock.lock();
+ // Do we have a stale gInBufferSize or are we requesting the input buffer size for new values
+ size_t inBuffSize = gInBuffSize;
+ if ((inBuffSize == 0) || (sampleRate != gPrevInSamplingRate) || (format != gPrevInFormat)
+ || (channelCount != gPrevInChannelCount)) {
+ gLock.unlock();
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) {
+ return PERMISSION_DENIED;
+ }
+ inBuffSize = af->getInputBufferSize(sampleRate, format, channelCount);
+ gLock.lock();
+ // save the request params
+ gPrevInSamplingRate = sampleRate;
+ gPrevInFormat = format;
+ gPrevInChannelCount = channelCount;
+
+ gInBuffSize = inBuffSize;
+ }
+ gLock.unlock();
+ *buffSize = inBuffSize;
+
+ return NO_ERROR;
+}
+
+status_t AudioSystem::setVoiceVolume(float value)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->setVoiceVolume(value);
+}
+
+status_t AudioSystem::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, audio_stream_type_t stream)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+
+ if (stream == AUDIO_STREAM_DEFAULT) {
+ stream = AUDIO_STREAM_MUSIC;
+ }
+
+ return af->getRenderPosition(halFrames, dspFrames, getOutput(stream));
+}
+
+unsigned int AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ unsigned int result = 0;
+ if (af == 0) return result;
+ if (ioHandle == 0) return result;
+
+ result = af->getInputFramesLost(ioHandle);
+ return result;
+}
+
+int AudioSystem::newAudioSessionId() {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return 0;
+ return af->newAudioSessionId();
+}
+
+void AudioSystem::acquireAudioSessionId(int audioSession) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af != 0) {
+ af->acquireAudioSessionId(audioSession);
+ }
+}
+
+void AudioSystem::releaseAudioSessionId(int audioSession) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af != 0) {
+ af->releaseAudioSessionId(audioSession);
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
+ Mutex::Autolock _l(AudioSystem::gLock);
+
+ AudioSystem::gAudioFlinger.clear();
+ // clear output handles and stream to output map caches
+ AudioSystem::gStreamOutputMap.clear();
+ AudioSystem::gOutputs.clear();
+
+ if (gAudioErrorCallback) {
+ gAudioErrorCallback(DEAD_OBJECT);
+ }
+ ALOGW("AudioFlinger server died!");
+}
+
+void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, audio_io_handle_t ioHandle,
+ const void *param2) {
+ ALOGV("ioConfigChanged() event %d", event);
+ const OutputDescriptor *desc;
+ audio_stream_type_t stream;
+
+ if (ioHandle == 0) return;
+
+ Mutex::Autolock _l(AudioSystem::gLock);
+
+ switch (event) {
+ case STREAM_CONFIG_CHANGED:
+ if (param2 == NULL) break;
+ stream = *(const audio_stream_type_t *)param2;
+ ALOGV("ioConfigChanged() STREAM_CONFIG_CHANGED stream %d, output %d", stream, ioHandle);
+ if (gStreamOutputMap.indexOfKey(stream) >= 0) {
+ gStreamOutputMap.replaceValueFor(stream, ioHandle);
+ }
+ break;
+ case OUTPUT_OPENED: {
+ if (gOutputs.indexOfKey(ioHandle) >= 0) {
+ ALOGV("ioConfigChanged() opening already existing output! %d", ioHandle);
+ break;
+ }
+ if (param2 == NULL) break;
+ desc = (const OutputDescriptor *)param2;
+
+ OutputDescriptor *outputDesc = new OutputDescriptor(*desc);
+ gOutputs.add(ioHandle, outputDesc);
+ ALOGV("ioConfigChanged() new output samplingRate %d, format %d channels %d frameCount %d latency %d",
+ outputDesc->samplingRate, outputDesc->format, outputDesc->channels, outputDesc->frameCount, outputDesc->latency);
+ } break;
+ case OUTPUT_CLOSED: {
+ if (gOutputs.indexOfKey(ioHandle) < 0) {
+ ALOGW("ioConfigChanged() closing unknow output! %d", ioHandle);
+ break;
+ }
+ ALOGV("ioConfigChanged() output %d closed", ioHandle);
+
+ gOutputs.removeItem(ioHandle);
+ for (int i = gStreamOutputMap.size() - 1; i >= 0 ; i--) {
+ if (gStreamOutputMap.valueAt(i) == ioHandle) {
+ gStreamOutputMap.removeItemsAt(i);
+ }
+ }
+ } break;
+
+ case OUTPUT_CONFIG_CHANGED: {
+ int index = gOutputs.indexOfKey(ioHandle);
+ if (index < 0) {
+ ALOGW("ioConfigChanged() modifying unknow output! %d", ioHandle);
+ break;
+ }
+ if (param2 == NULL) break;
+ desc = (const OutputDescriptor *)param2;
+
+ ALOGV("ioConfigChanged() new config for output %d samplingRate %d, format %d channels %d frameCount %d latency %d",
+ ioHandle, desc->samplingRate, desc->format,
+ desc->channels, desc->frameCount, desc->latency);
+ OutputDescriptor *outputDesc = gOutputs.valueAt(index);
+ delete outputDesc;
+ outputDesc = new OutputDescriptor(*desc);
+ gOutputs.replaceValueFor(ioHandle, outputDesc);
+ } break;
+ case INPUT_OPENED:
+ case INPUT_CLOSED:
+ case INPUT_CONFIG_CHANGED:
+ break;
+
+ }
+}
+
+void AudioSystem::setErrorCallback(audio_error_callback cb) {
+ Mutex::Autolock _l(gLock);
+ gAudioErrorCallback = cb;
+}
+
+bool AudioSystem::routedToA2dpOutput(audio_stream_type_t streamType) {
+ switch (streamType) {
+ case AUDIO_STREAM_MUSIC:
+ case AUDIO_STREAM_VOICE_CALL:
+ case AUDIO_STREAM_BLUETOOTH_SCO:
+ case AUDIO_STREAM_SYSTEM:
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+// client singleton for AudioPolicyService binder interface
+sp<IAudioPolicyService> AudioSystem::gAudioPolicyService;
+sp<AudioSystem::AudioPolicyServiceClient> AudioSystem::gAudioPolicyServiceClient;
+
+
+// establish binder interface to AudioFlinger service
+const sp<IAudioPolicyService>& AudioSystem::get_audio_policy_service()
+{
+ gLock.lock();
+ if (gAudioPolicyService == 0) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder;
+ do {
+ binder = sm->getService(String16("media.audio_policy"));
+ if (binder != 0)
+ break;
+ ALOGW("AudioPolicyService not published, waiting...");
+ usleep(500000); // 0.5 s
+ } while (true);
+ if (gAudioPolicyServiceClient == NULL) {
+ gAudioPolicyServiceClient = new AudioPolicyServiceClient();
+ }
+ binder->linkToDeath(gAudioPolicyServiceClient);
+ gAudioPolicyService = interface_cast<IAudioPolicyService>(binder);
+ gLock.unlock();
+ } else {
+ gLock.unlock();
+ }
+ return gAudioPolicyService;
+}
+
+status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
+ audio_policy_dev_state_t state,
+ const char *device_address)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ const char *address = "";
+
+ if (aps == 0) return PERMISSION_DENIED;
+
+ if (device_address != NULL) {
+ address = device_address;
+ }
+
+ return aps->setDeviceConnectionState(device, state, address);
+}
+
+audio_policy_dev_state_t AudioSystem::getDeviceConnectionState(audio_devices_t device,
+ const char *device_address)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
+
+ return aps->getDeviceConnectionState(device, device_address);
+}
+
+status_t AudioSystem::setPhoneState(audio_mode_t state)
+{
+ if (uint32_t(state) >= AUDIO_MODE_CNT) return BAD_VALUE;
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+
+ return aps->setPhoneState(state);
+}
+
+status_t AudioSystem::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->setForceUse(usage, config);
+}
+
+audio_policy_forced_cfg_t AudioSystem::getForceUse(audio_policy_force_use_t usage)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return AUDIO_POLICY_FORCE_NONE;
+ return aps->getForceUse(usage);
+}
+
+
+audio_io_handle_t AudioSystem::getOutput(audio_stream_type_t stream,
+ uint32_t samplingRate,
+ audio_format_t format,
+ uint32_t channels,
+ audio_policy_output_flags_t flags)
+{
+ audio_io_handle_t output = 0;
+ // Do not use stream to output map cache if the direct output
+ // flag is set or if we are likely to use a direct output
+ // (e.g voice call stream @ 8kHz could use BT SCO device and be routed to
+ // a direct output on some platforms).
+ // TODO: the output cache and stream to output mapping implementation needs to
+ // be reworked for proper operation with direct outputs. This code is too specific
+ // to the first use case we want to cover (Voice Recognition and Voice Dialer over
+ // Bluetooth SCO
+ if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) == 0 &&
+ ((stream != AUDIO_STREAM_VOICE_CALL && stream != AUDIO_STREAM_BLUETOOTH_SCO) ||
+ channels != AUDIO_CHANNEL_OUT_MONO ||
+ (samplingRate != 8000 && samplingRate != 16000))) {
+ Mutex::Autolock _l(gLock);
+ output = AudioSystem::gStreamOutputMap.valueFor(stream);
+ ALOGV_IF((output != 0), "getOutput() read %d from cache for stream %d", output, stream);
+ }
+ if (output == 0) {
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return 0;
+ output = aps->getOutput(stream, samplingRate, format, channels, flags);
+ if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) == 0) {
+ Mutex::Autolock _l(gLock);
+ AudioSystem::gStreamOutputMap.add(stream, output);
+ }
+ }
+ return output;
+}
+
+status_t AudioSystem::startOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int session)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->startOutput(output, stream, session);
+}
+
+status_t AudioSystem::stopOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int session)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->stopOutput(output, stream, session);
+}
+
+void AudioSystem::releaseOutput(audio_io_handle_t output)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return;
+ aps->releaseOutput(output);
+}
+
+audio_io_handle_t AudioSystem::getInput(audio_source_t inputSource,
+ uint32_t samplingRate,
+ audio_format_t format,
+ uint32_t channels,
+ audio_in_acoustics_t acoustics,
+ int sessionId)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return 0;
+ return aps->getInput(inputSource, samplingRate, format, channels, acoustics, sessionId);
+}
+
+status_t AudioSystem::startInput(audio_io_handle_t input)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->startInput(input);
+}
+
+status_t AudioSystem::stopInput(audio_io_handle_t input)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->stopInput(input);
+}
+
+void AudioSystem::releaseInput(audio_io_handle_t input)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return;
+ aps->releaseInput(input);
+}
+
+status_t AudioSystem::initStreamVolume(audio_stream_type_t stream,
+ int indexMin,
+ int indexMax)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->initStreamVolume(stream, indexMin, indexMax);
+}
+
+status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream,
+ int index,
+ audio_devices_t device)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->setStreamVolumeIndex(stream, index, device);
+}
+
+status_t AudioSystem::getStreamVolumeIndex(audio_stream_type_t stream,
+ int *index,
+ audio_devices_t device)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->getStreamVolumeIndex(stream, index, device);
+}
+
+uint32_t AudioSystem::getStrategyForStream(audio_stream_type_t stream)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return 0;
+ return aps->getStrategyForStream(stream);
+}
+
+audio_devices_t AudioSystem::getDevicesForStream(audio_stream_type_t stream)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return (audio_devices_t)0;
+ return aps->getDevicesForStream(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 io,
+ 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, io, 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);
+}
+
+status_t AudioSystem::setEffectEnabled(int id, bool enabled)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->setEffectEnabled(id, enabled);
+}
+
+status_t AudioSystem::isStreamActive(audio_stream_type_t stream, bool* state, uint32_t inPastMs)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ if (state == NULL) return BAD_VALUE;
+ *state = aps->isStreamActive(stream, inPastMs);
+ return NO_ERROR;
+}
+
+
+void AudioSystem::clearAudioConfigCache()
+{
+ Mutex::Autolock _l(gLock);
+ ALOGV("clearAudioConfigCache()");
+ gStreamOutputMap.clear();
+ gOutputs.clear();
+}
+
+// ---------------------------------------------------------------------------
+
+void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who) {
+ Mutex::Autolock _l(AudioSystem::gLock);
+ AudioSystem::gAudioPolicyService.clear();
+
+ ALOGW("AudioPolicyService server died!");
+}
+
+}; // namespace android
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
new file mode 100644
index 0000000..bafde3a
--- /dev/null
+++ b/media/libmedia/AudioTrack.cpp
@@ -0,0 +1,1531 @@
+/*
+**
+** 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 "AudioTrack"
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include <sched.h>
+#include <sys/resource.h>
+
+#include <private/media/AudioTrackShared.h>
+
+#include <media/AudioSystem.h>
+#include <media/AudioTrack.h>
+
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <utils/Timers.h>
+#include <utils/Atomic.h>
+
+#include <cutils/bitops.h>
+#include <cutils/compiler.h>
+
+#include <system/audio.h>
+#include <system/audio_policy.h>
+
+#include <audio_utils/primitives.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+// static
+status_t AudioTrack::getMinFrameCount(
+ int* frameCount,
+ audio_stream_type_t 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;
+}
+
+// ---------------------------------------------------------------------------
+
+AudioTrack::AudioTrack()
+ : mStatus(NO_INIT),
+ mIsTimed(false),
+ mPreviousPriority(ANDROID_PRIORITY_NORMAL),
+ mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT)
+{
+}
+
+AudioTrack::AudioTrack(
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ int channelMask,
+ int frameCount,
+ audio_policy_output_flags_t flags,
+ callback_t cbf,
+ void* user,
+ int notificationFrames,
+ int sessionId)
+ : mStatus(NO_INIT),
+ mIsTimed(false),
+ mPreviousPriority(ANDROID_PRIORITY_NORMAL),
+ mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT)
+{
+ mStatus = set(streamType, sampleRate, format, channelMask,
+ frameCount, flags, cbf, user, notificationFrames,
+ 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId);
+}
+
+// DEPRECATED
+AudioTrack::AudioTrack(
+ int streamType,
+ uint32_t sampleRate,
+ int format,
+ int channelMask,
+ int frameCount,
+ uint32_t flags,
+ callback_t cbf,
+ void* user,
+ int notificationFrames,
+ int sessionId)
+ : mStatus(NO_INIT),
+ mIsTimed(false),
+ mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT)
+{
+ mStatus = set((audio_stream_type_t)streamType, sampleRate, (audio_format_t)format, channelMask,
+ frameCount, (audio_policy_output_flags_t)flags, cbf, user, notificationFrames,
+ 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId);
+}
+
+AudioTrack::AudioTrack(
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ int channelMask,
+ const sp<IMemory>& sharedBuffer,
+ audio_policy_output_flags_t flags,
+ callback_t cbf,
+ void* user,
+ int notificationFrames,
+ int sessionId)
+ : mStatus(NO_INIT),
+ mIsTimed(false),
+ mPreviousPriority(ANDROID_PRIORITY_NORMAL),
+ mPreviousSchedulingGroup(ANDROID_TGROUP_DEFAULT)
+{
+ mStatus = set(streamType, sampleRate, format, channelMask,
+ 0 /*frameCount*/, flags, cbf, user, notificationFrames,
+ sharedBuffer, false /*threadCanCallJava*/, sessionId);
+}
+
+AudioTrack::~AudioTrack()
+{
+ ALOGV_IF(mSharedBuffer != 0, "Destructor sharedBuffer: %p", mSharedBuffer->pointer());
+
+ if (mStatus == NO_ERROR) {
+ // Make sure that callback function exits in the case where
+ // it is looping on buffer full condition in obtainBuffer().
+ // Otherwise the callback thread will never exit.
+ stop();
+ if (mAudioTrackThread != 0) {
+ mAudioTrackThread->requestExitAndWait();
+ mAudioTrackThread.clear();
+ }
+ mAudioTrack.clear();
+ IPCThreadState::self()->flushCommands();
+ AudioSystem::releaseAudioSessionId(mSessionId);
+ }
+}
+
+status_t AudioTrack::set(
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ int channelMask,
+ int frameCount,
+ audio_policy_output_flags_t flags,
+ callback_t cbf,
+ void* user,
+ int notificationFrames,
+ const sp<IMemory>& sharedBuffer,
+ bool threadCanCallJava,
+ int sessionId)
+{
+
+ ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
+
+ AutoMutex lock(mLock);
+ if (mAudioTrack != 0) {
+ ALOGE("Track already in use");
+ return INVALID_OPERATION;
+ }
+
+ int afSampleRate;
+ if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
+ return NO_INIT;
+ }
+
+ uint32_t afLatency;
+ if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
+ return NO_INIT;
+ }
+
+ // handle default values first.
+ if (streamType == AUDIO_STREAM_DEFAULT) {
+ streamType = AUDIO_STREAM_MUSIC;
+ }
+
+ if (sampleRate == 0) {
+ sampleRate = afSampleRate;
+ }
+
+ // these below should probably come from the audioFlinger too...
+ if (format == AUDIO_FORMAT_DEFAULT) {
+ format = AUDIO_FORMAT_PCM_16_BIT;
+ }
+ if (channelMask == 0) {
+ channelMask = AUDIO_CHANNEL_OUT_STEREO;
+ }
+
+ // validate parameters
+ if (!audio_is_valid_format(format)) {
+ ALOGE("Invalid format");
+ return BAD_VALUE;
+ }
+
+ // force direct flag if format is not linear PCM
+ if (!audio_is_linear_pcm(format)) {
+ flags = (audio_policy_output_flags_t) (flags | AUDIO_POLICY_OUTPUT_FLAG_DIRECT);
+ }
+
+ if (!audio_is_output_channel(channelMask)) {
+ ALOGE("Invalid channel mask");
+ return BAD_VALUE;
+ }
+ uint32_t channelCount = popcount(channelMask);
+
+ audio_io_handle_t output = AudioSystem::getOutput(
+ streamType,
+ sampleRate, format, channelMask,
+ flags);
+
+ if (output == 0) {
+ ALOGE("Could not get audio output for stream type %d", streamType);
+ return BAD_VALUE;
+ }
+
+ mVolume[LEFT] = 1.0f;
+ mVolume[RIGHT] = 1.0f;
+ mSendLevel = 0.0f;
+ mFrameCount = frameCount;
+ mNotificationFramesReq = notificationFrames;
+ mSessionId = sessionId;
+ mAuxEffectId = 0;
+
+ // create the IAudioTrack
+ status_t status = createTrack_l(streamType,
+ sampleRate,
+ format,
+ (uint32_t)channelMask,
+ frameCount,
+ flags,
+ sharedBuffer,
+ output);
+
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ if (cbf != NULL) {
+ mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
+ }
+
+ mStatus = NO_ERROR;
+
+ mStreamType = streamType;
+ mFormat = format;
+ mChannelMask = (uint32_t)channelMask;
+ mChannelCount = channelCount;
+ mSharedBuffer = sharedBuffer;
+ mMuted = false;
+ mActive = false;
+ mCbf = cbf;
+ mUserData = user;
+ mLoopCount = 0;
+ mMarkerPosition = 0;
+ mMarkerReached = false;
+ mNewPosition = 0;
+ mUpdatePeriod = 0;
+ mFlushed = false;
+ mFlags = flags;
+ AudioSystem::acquireAudioSessionId(mSessionId);
+ mRestoreStatus = NO_ERROR;
+ return NO_ERROR;
+}
+
+status_t AudioTrack::initCheck() const
+{
+ return mStatus;
+}
+
+// -------------------------------------------------------------------------
+
+uint32_t AudioTrack::latency() const
+{
+ return mLatency;
+}
+
+audio_stream_type_t AudioTrack::streamType() const
+{
+ return mStreamType;
+}
+
+audio_format_t AudioTrack::format() const
+{
+ return mFormat;
+}
+
+int AudioTrack::channelCount() const
+{
+ return mChannelCount;
+}
+
+uint32_t AudioTrack::frameCount() const
+{
+ return mCblk->frameCount;
+}
+
+size_t AudioTrack::frameSize() const
+{
+ if (audio_is_linear_pcm(mFormat)) {
+ return channelCount()*audio_bytes_per_sample(mFormat);
+ } else {
+ return sizeof(uint8_t);
+ }
+}
+
+sp<IMemory>& AudioTrack::sharedBuffer()
+{
+ return mSharedBuffer;
+}
+
+// -------------------------------------------------------------------------
+
+void AudioTrack::start()
+{
+ sp<AudioTrackThread> t = mAudioTrackThread;
+ status_t status = NO_ERROR;
+
+ ALOGV("start %p", this);
+ if (t != 0) {
+ if (t->exitPending()) {
+ if (t->requestExitAndWait() == WOULD_BLOCK) {
+ ALOGE("AudioTrack::start called from thread");
+ return;
+ }
+ }
+ }
+
+ AutoMutex lock(mLock);
+ // acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed
+ // while we are accessing the cblk
+ sp<IAudioTrack> audioTrack = mAudioTrack;
+ sp<IMemory> iMem = mCblkMemory;
+ audio_track_cblk_t* cblk = mCblk;
+
+ if (!mActive) {
+ mFlushed = false;
+ mActive = true;
+ mNewPosition = cblk->server + mUpdatePeriod;
+ cblk->lock.lock();
+ cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
+ cblk->waitTimeMs = 0;
+ android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
+ pid_t tid;
+ if (t != 0) {
+ t->run("AudioTrack", ANDROID_PRIORITY_AUDIO);
+ tid = t->getTid(); // pid_t is unknown until run()
+ ALOGV("getTid=%d", tid);
+ if (tid == -1) {
+ tid = 0;
+ }
+ } else {
+ mPreviousPriority = getpriority(PRIO_PROCESS, 0);
+ mPreviousSchedulingGroup = androidGetThreadSchedulingGroup(0);
+ androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
+ tid = 0; // not gettid()
+ }
+
+ ALOGV("start %p before lock cblk %p", this, mCblk);
+ if (!(cblk->flags & CBLK_INVALID_MSK)) {
+ cblk->lock.unlock();
+ ALOGV("mAudioTrack->start(tid=%d)", tid);
+ status = mAudioTrack->start(tid);
+ cblk->lock.lock();
+ if (status == DEAD_OBJECT) {
+ android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
+ }
+ }
+ if (cblk->flags & CBLK_INVALID_MSK) {
+ status = restoreTrack_l(cblk, true);
+ }
+ cblk->lock.unlock();
+ if (status != NO_ERROR) {
+ ALOGV("start() failed");
+ mActive = false;
+ if (t != 0) {
+ t->requestExit();
+ } else {
+ setpriority(PRIO_PROCESS, 0, mPreviousPriority);
+ androidSetThreadSchedulingGroup(0, mPreviousSchedulingGroup);
+ }
+ }
+ }
+
+}
+
+void AudioTrack::stop()
+{
+ sp<AudioTrackThread> t = mAudioTrackThread;
+
+ ALOGV("stop %p", this);
+
+ AutoMutex lock(mLock);
+ if (mActive) {
+ mActive = false;
+ mCblk->cv.signal();
+ mAudioTrack->stop();
+ // Cancel loops (If we are in the middle of a loop, playback
+ // would not stop until loopCount reaches 0).
+ setLoop_l(0, 0, 0);
+ // the playback head position will reset to 0, so if a marker is set, we need
+ // to activate it again
+ mMarkerReached = false;
+ // Force flush if a shared buffer is used otherwise audioflinger
+ // will not stop before end of buffer is reached.
+ if (mSharedBuffer != 0) {
+ flush_l();
+ }
+ if (t != 0) {
+ t->requestExit();
+ } else {
+ setpriority(PRIO_PROCESS, 0, mPreviousPriority);
+ androidSetThreadSchedulingGroup(0, mPreviousSchedulingGroup);
+ }
+ }
+
+}
+
+bool AudioTrack::stopped() const
+{
+ AutoMutex lock(mLock);
+ return stopped_l();
+}
+
+void AudioTrack::flush()
+{
+ AutoMutex lock(mLock);
+ flush_l();
+}
+
+// must be called with mLock held
+void AudioTrack::flush_l()
+{
+ ALOGV("flush");
+
+ // clear playback marker and periodic update counter
+ mMarkerPosition = 0;
+ mMarkerReached = false;
+ mUpdatePeriod = 0;
+
+ if (!mActive) {
+ mFlushed = true;
+ mAudioTrack->flush();
+ // Release AudioTrack callback thread in case it was waiting for new buffers
+ // in AudioTrack::obtainBuffer()
+ mCblk->cv.signal();
+ }
+}
+
+void AudioTrack::pause()
+{
+ ALOGV("pause");
+ AutoMutex lock(mLock);
+ if (mActive) {
+ mActive = false;
+ mAudioTrack->pause();
+ }
+}
+
+void AudioTrack::mute(bool e)
+{
+ mAudioTrack->mute(e);
+ mMuted = e;
+}
+
+bool AudioTrack::muted() const
+{
+ return mMuted;
+}
+
+status_t AudioTrack::setVolume(float left, float right)
+{
+ if (left < 0.0f || left > 1.0f || right < 0.0f || right > 1.0f) {
+ return BAD_VALUE;
+ }
+
+ AutoMutex lock(mLock);
+ mVolume[LEFT] = left;
+ mVolume[RIGHT] = right;
+
+ mCblk->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000));
+
+ return NO_ERROR;
+}
+
+void AudioTrack::getVolume(float* left, float* right) const
+{
+ if (left != NULL) {
+ *left = mVolume[LEFT];
+ }
+ if (right != NULL) {
+ *right = mVolume[RIGHT];
+ }
+}
+
+status_t AudioTrack::setAuxEffectSendLevel(float level)
+{
+ ALOGV("setAuxEffectSendLevel(%f)", level);
+ if (level < 0.0f || level > 1.0f) {
+ return BAD_VALUE;
+ }
+ AutoMutex lock(mLock);
+
+ mSendLevel = level;
+
+ mCblk->setSendLevel(level);
+
+ return NO_ERROR;
+}
+
+void AudioTrack::getAuxEffectSendLevel(float* level) const
+{
+ if (level != NULL) {
+ *level = mSendLevel;
+ }
+}
+
+status_t AudioTrack::setSampleRate(int rate)
+{
+ int afSamplingRate;
+
+ if (mIsTimed) {
+ return INVALID_OPERATION;
+ }
+
+ if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) {
+ return NO_INIT;
+ }
+ // Resampler implementation limits input sampling rate to 2 x output sampling rate.
+ if (rate <= 0 || rate > afSamplingRate*2 ) return BAD_VALUE;
+
+ AutoMutex lock(mLock);
+ mCblk->sampleRate = rate;
+ return NO_ERROR;
+}
+
+uint32_t AudioTrack::getSampleRate() const
+{
+ if (mIsTimed) {
+ return INVALID_OPERATION;
+ }
+
+ AutoMutex lock(mLock);
+ return mCblk->sampleRate;
+}
+
+status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount)
+{
+ AutoMutex lock(mLock);
+ return setLoop_l(loopStart, loopEnd, loopCount);
+}
+
+// must be called with mLock held
+status_t AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount)
+{
+ audio_track_cblk_t* cblk = mCblk;
+
+ Mutex::Autolock _l(cblk->lock);
+
+ if (loopCount == 0) {
+ cblk->loopStart = UINT_MAX;
+ cblk->loopEnd = UINT_MAX;
+ cblk->loopCount = 0;
+ mLoopCount = 0;
+ return NO_ERROR;
+ }
+
+ if (mIsTimed) {
+ return INVALID_OPERATION;
+ }
+
+ if (loopStart >= loopEnd ||
+ loopEnd - loopStart > cblk->frameCount ||
+ cblk->server > loopStart) {
+ ALOGE("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 > cblk->frameCount)) {
+ ALOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
+ loopStart, loopEnd, cblk->frameCount);
+ return BAD_VALUE;
+ }
+
+ cblk->loopStart = loopStart;
+ cblk->loopEnd = loopEnd;
+ cblk->loopCount = loopCount;
+ mLoopCount = loopCount;
+
+ return NO_ERROR;
+}
+
+status_t AudioTrack::setMarkerPosition(uint32_t marker)
+{
+ if (mCbf == NULL) return INVALID_OPERATION;
+
+ mMarkerPosition = marker;
+ mMarkerReached = false;
+
+ return NO_ERROR;
+}
+
+status_t AudioTrack::getMarkerPosition(uint32_t *marker) const
+{
+ if (marker == NULL) return BAD_VALUE;
+
+ *marker = mMarkerPosition;
+
+ return NO_ERROR;
+}
+
+status_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod)
+{
+ if (mCbf == NULL) return INVALID_OPERATION;
+
+ uint32_t curPosition;
+ getPosition(&curPosition);
+ mNewPosition = curPosition + updatePeriod;
+ mUpdatePeriod = updatePeriod;
+
+ return NO_ERROR;
+}
+
+status_t AudioTrack::getPositionUpdatePeriod(uint32_t *updatePeriod) const
+{
+ if (updatePeriod == NULL) return BAD_VALUE;
+
+ *updatePeriod = mUpdatePeriod;
+
+ return NO_ERROR;
+}
+
+status_t AudioTrack::setPosition(uint32_t position)
+{
+ if (mIsTimed) return INVALID_OPERATION;
+
+ AutoMutex lock(mLock);
+
+ if (!stopped_l()) return INVALID_OPERATION;
+
+ Mutex::Autolock _l(mCblk->lock);
+
+ if (position > mCblk->user) return BAD_VALUE;
+
+ mCblk->server = position;
+ android_atomic_or(CBLK_FORCEREADY_ON, &mCblk->flags);
+
+ return NO_ERROR;
+}
+
+status_t AudioTrack::getPosition(uint32_t *position)
+{
+ if (position == NULL) return BAD_VALUE;
+ AutoMutex lock(mLock);
+ *position = mFlushed ? 0 : mCblk->server;
+
+ return NO_ERROR;
+}
+
+status_t AudioTrack::reload()
+{
+ AutoMutex lock(mLock);
+
+ if (!stopped_l()) return INVALID_OPERATION;
+
+ flush_l();
+
+ mCblk->stepUser(mCblk->frameCount);
+
+ return NO_ERROR;
+}
+
+audio_io_handle_t AudioTrack::getOutput()
+{
+ AutoMutex lock(mLock);
+ return getOutput_l();
+}
+
+// must be called with mLock held
+audio_io_handle_t AudioTrack::getOutput_l()
+{
+ return AudioSystem::getOutput(mStreamType,
+ mCblk->sampleRate, mFormat, mChannelMask, mFlags);
+}
+
+int AudioTrack::getSessionId() const
+{
+ return mSessionId;
+}
+
+status_t AudioTrack::attachAuxEffect(int effectId)
+{
+ ALOGV("attachAuxEffect(%d)", effectId);
+ status_t status = mAudioTrack->attachAuxEffect(effectId);
+ if (status == NO_ERROR) {
+ mAuxEffectId = effectId;
+ }
+ return status;
+}
+
+// -------------------------------------------------------------------------
+
+// must be called with mLock held
+status_t AudioTrack::createTrack_l(
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ audio_policy_output_flags_t flags,
+ const sp<IMemory>& sharedBuffer,
+ audio_io_handle_t output)
+{
+ status_t status;
+ const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+ if (audioFlinger == 0) {
+ ALOGE("Could not get audioflinger");
+ 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 (!audio_is_linear_pcm(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) {
+ // not ALOGW because it happens all the time when playing key clicks over A2DP
+ ALOGV("Minimum buffer size corrected from %d to %d",
+ frameCount, minFrameCount);
+ frameCount = minFrameCount;
+ }
+ } else {
+ // Ensure that buffer alignment matches channelCount
+ int channelCount = popcount(channelMask);
+ if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
+ ALOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
+ return BAD_VALUE;
+ }
+ frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
+ }
+ }
+
+ IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT;
+ if (mIsTimed) {
+ trackFlags |= IAudioFlinger::TRACK_TIMED;
+ }
+ sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
+ streamType,
+ sampleRate,
+ format,
+ channelMask,
+ frameCount,
+ trackFlags,
+ sharedBuffer,
+ output,
+ &mSessionId,
+ &status);
+
+ if (track == 0) {
+ ALOGE("AudioFlinger could not create track, status: %d", status);
+ return status;
+ }
+ sp<IMemory> cblk = track->getCblk();
+ if (cblk == 0) {
+ ALOGE("Could not get control block");
+ return NO_INIT;
+ }
+ mAudioTrack = track;
+ mCblkMemory = cblk;
+ mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
+ android_atomic_or(CBLK_DIRECTION_OUT, &mCblk->flags);
+ 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(mCblk->frameCount);
+ }
+
+ mCblk->setVolumeLR((uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | uint16_t(mVolume[LEFT] * 0x1000));
+ mCblk->setSendLevel(mSendLevel);
+ mAudioTrack->attachAuxEffect(mAuxEffectId);
+ mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
+ mCblk->waitTimeMs = 0;
+ mRemainingFrames = mNotificationFramesAct;
+ mLatency = afLatency + (1000*mCblk->frameCount) / sampleRate;
+ return NO_ERROR;
+}
+
+status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
+{
+ AutoMutex lock(mLock);
+ bool active;
+ status_t result = NO_ERROR;
+ audio_track_cblk_t* cblk = mCblk;
+ uint32_t framesReq = audioBuffer->frameCount;
+ uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
+
+ audioBuffer->frameCount = 0;
+ audioBuffer->size = 0;
+
+ uint32_t framesAvail = cblk->framesAvailable();
+
+ cblk->lock.lock();
+ if (cblk->flags & CBLK_INVALID_MSK) {
+ goto create_new_track;
+ }
+ cblk->lock.unlock();
+
+ if (framesAvail == 0) {
+ cblk->lock.lock();
+ goto start_loop_here;
+ while (framesAvail == 0) {
+ active = mActive;
+ if (CC_UNLIKELY(!active)) {
+ ALOGV("Not active and NO_MORE_BUFFERS");
+ cblk->lock.unlock();
+ return NO_MORE_BUFFERS;
+ }
+ if (CC_UNLIKELY(!waitCount)) {
+ cblk->lock.unlock();
+ return WOULD_BLOCK;
+ }
+ if (!(cblk->flags & CBLK_INVALID_MSK)) {
+ mLock.unlock();
+ result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
+ cblk->lock.unlock();
+ mLock.lock();
+ if (!mActive) {
+ return status_t(STOPPED);
+ }
+ cblk->lock.lock();
+ }
+
+ if (cblk->flags & CBLK_INVALID_MSK) {
+ goto create_new_track;
+ }
+ if (CC_UNLIKELY(result != NO_ERROR)) {
+ cblk->waitTimeMs += waitTimeMs;
+ if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
+ // timing out when a loop has been set and we have already written upto loop end
+ // is a normal condition: no need to wake AudioFlinger up.
+ if (cblk->user < cblk->loopEnd) {
+ ALOGW( "obtainBuffer timed out (is the CPU pegged?) %p "
+ "user=%08x, server=%08x", this, cblk->user, cblk->server);
+ //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
+ cblk->lock.unlock();
+ result = mAudioTrack->start(0); // callback thread hasn't changed
+ cblk->lock.lock();
+ if (result == DEAD_OBJECT) {
+ android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
+create_new_track:
+ result = restoreTrack_l(cblk, false);
+ }
+ if (result != NO_ERROR) {
+ ALOGW("obtainBuffer create Track error %d", result);
+ cblk->lock.unlock();
+ return result;
+ }
+ }
+ cblk->waitTimeMs = 0;
+ }
+
+ if (--waitCount == 0) {
+ cblk->lock.unlock();
+ return TIMED_OUT;
+ }
+ }
+ // read the server count again
+ start_loop_here:
+ framesAvail = cblk->framesAvailable_l();
+ }
+ cblk->lock.unlock();
+ }
+
+ // restart track if it was disabled by audioflinger due to previous underrun
+ if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) {
+ android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
+ ALOGW("obtainBuffer() track %p disabled, restarting", this);
+ mAudioTrack->start(0); // callback thread hasn't changed
+ }
+
+ cblk->waitTimeMs = 0;
+
+ if (framesReq > framesAvail) {
+ framesReq = framesAvail;
+ }
+
+ uint32_t u = cblk->user;
+ uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
+
+ if (u + framesReq > bufferEnd) {
+ framesReq = bufferEnd - u;
+ }
+
+ audioBuffer->flags = mMuted ? Buffer::MUTE : 0;
+ audioBuffer->channelCount = mChannelCount;
+ audioBuffer->frameCount = framesReq;
+ audioBuffer->size = framesReq * cblk->frameSize;
+ if (audio_is_linear_pcm(mFormat)) {
+ audioBuffer->format = AUDIO_FORMAT_PCM_16_BIT;
+ } else {
+ audioBuffer->format = mFormat;
+ }
+ audioBuffer->raw = (int8_t *)cblk->buffer(u);
+ active = mActive;
+ return active ? status_t(NO_ERROR) : status_t(STOPPED);
+}
+
+void AudioTrack::releaseBuffer(Buffer* audioBuffer)
+{
+ AutoMutex lock(mLock);
+ mCblk->stepUser(audioBuffer->frameCount);
+}
+
+// -------------------------------------------------------------------------
+
+ssize_t AudioTrack::write(const void* buffer, size_t userSize)
+{
+
+ if (mSharedBuffer != 0) return INVALID_OPERATION;
+ if (mIsTimed) return INVALID_OPERATION;
+
+ if (ssize_t(userSize) < 0) {
+ // Sanity-check: user is most-likely passing an error code, and it would
+ // make the return value ambiguous (actualSize vs error).
+ ALOGE("AudioTrack::write(buffer=%p, size=%u (%d)",
+ buffer, userSize, userSize);
+ return BAD_VALUE;
+ }
+
+ ALOGV("write %p: %d bytes, mActive=%d", this, userSize, mActive);
+
+ // acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed
+ // while we are accessing the cblk
+ mLock.lock();
+ sp<IAudioTrack> audioTrack = mAudioTrack;
+ sp<IMemory> iMem = mCblkMemory;
+ mLock.unlock();
+
+ ssize_t written = 0;
+ const int8_t *src = (const int8_t *)buffer;
+ Buffer audioBuffer;
+ size_t frameSz = frameSize();
+
+ do {
+ audioBuffer.frameCount = userSize/frameSz;
+
+ status_t err = obtainBuffer(&audioBuffer, -1);
+ if (err < 0) {
+ // out of buffers, return #bytes written
+ if (err == status_t(NO_MORE_BUFFERS))
+ break;
+ return ssize_t(err);
+ }
+
+ size_t toWrite;
+
+ if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT)) {
+ // Divide capacity by 2 to take expansion into account
+ toWrite = audioBuffer.size>>1;
+ memcpy_to_i16_from_u8(audioBuffer.i16, (const uint8_t *) src, toWrite);
+ } else {
+ toWrite = audioBuffer.size;
+ memcpy(audioBuffer.i8, src, toWrite);
+ src += toWrite;
+ }
+ userSize -= toWrite;
+ written += toWrite;
+
+ releaseBuffer(&audioBuffer);
+ } while (userSize >= frameSz);
+
+ return written;
+}
+
+// -------------------------------------------------------------------------
+
+TimedAudioTrack::TimedAudioTrack() {
+ mIsTimed = true;
+}
+
+status_t TimedAudioTrack::allocateTimedBuffer(size_t size, sp<IMemory>* buffer)
+{
+ status_t result = UNKNOWN_ERROR;
+
+ // If the track is not invalid already, try to allocate a buffer. alloc
+ // fails indicating that the server is dead, flag the track as invalid so
+ // we can attempt to restore in in just a bit.
+ if (!(mCblk->flags & CBLK_INVALID_MSK)) {
+ result = mAudioTrack->allocateTimedBuffer(size, buffer);
+ if (result == DEAD_OBJECT) {
+ android_atomic_or(CBLK_INVALID_ON, &mCblk->flags);
+ }
+ }
+
+ // If the track is invalid at this point, attempt to restore it. and try the
+ // allocation one more time.
+ if (mCblk->flags & CBLK_INVALID_MSK) {
+ mCblk->lock.lock();
+ result = restoreTrack_l(mCblk, false);
+ mCblk->lock.unlock();
+
+ if (result == OK)
+ result = mAudioTrack->allocateTimedBuffer(size, buffer);
+ }
+
+ return result;
+}
+
+status_t TimedAudioTrack::queueTimedBuffer(const sp<IMemory>& buffer,
+ int64_t pts)
+{
+ // restart track if it was disabled by audioflinger due to previous underrun
+ if (mActive && (mCblk->flags & CBLK_DISABLED_MSK)) {
+ android_atomic_and(~CBLK_DISABLED_ON, &mCblk->flags);
+ ALOGW("queueTimedBuffer() track %p disabled, restarting", this);
+ mAudioTrack->start(0);
+ }
+
+ return mAudioTrack->queueTimedBuffer(buffer, pts);
+}
+
+status_t TimedAudioTrack::setMediaTimeTransform(const LinearTransform& xform,
+ TargetTimeline target)
+{
+ return mAudioTrack->setMediaTimeTransform(xform, target);
+}
+
+// -------------------------------------------------------------------------
+
+bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
+{
+ Buffer audioBuffer;
+ uint32_t frames;
+ size_t writtenSize;
+
+ mLock.lock();
+ // acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed
+ // while we are accessing the cblk
+ sp<IAudioTrack> audioTrack = mAudioTrack;
+ sp<IMemory> iMem = mCblkMemory;
+ audio_track_cblk_t* cblk = mCblk;
+ bool active = mActive;
+ mLock.unlock();
+
+ // Manage underrun callback
+ if (active && (cblk->framesAvailable() == cblk->frameCount)) {
+ ALOGV("Underrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
+ if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) {
+ mCbf(EVENT_UNDERRUN, mUserData, 0);
+ if (cblk->server == cblk->frameCount) {
+ mCbf(EVENT_BUFFER_END, mUserData, 0);
+ }
+ if (mSharedBuffer != 0) return false;
+ }
+ }
+
+ // Manage loop end callback
+ while (mLoopCount > cblk->loopCount) {
+ int loopCount = -1;
+ mLoopCount--;
+ if (mLoopCount >= 0) loopCount = mLoopCount;
+
+ mCbf(EVENT_LOOP_END, mUserData, (void *)&loopCount);
+ }
+
+ // Manage marker callback
+ if (!mMarkerReached && (mMarkerPosition > 0)) {
+ if (cblk->server >= mMarkerPosition) {
+ mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition);
+ mMarkerReached = true;
+ }
+ }
+
+ // Manage new position callback
+ if (mUpdatePeriod > 0) {
+ while (cblk->server >= mNewPosition) {
+ mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition);
+ mNewPosition += mUpdatePeriod;
+ }
+ }
+
+ // If Shared buffer is used, no data is requested from client.
+ if (mSharedBuffer != 0) {
+ frames = 0;
+ } else {
+ frames = mRemainingFrames;
+ }
+
+ // See description of waitCount parameter at declaration of obtainBuffer().
+ // The logic below prevents us from being stuck below at obtainBuffer()
+ // not being able to handle timed events (position, markers, loops).
+ int32_t waitCount = -1;
+ if (mUpdatePeriod || (!mMarkerReached && mMarkerPosition) || mLoopCount) {
+ waitCount = 1;
+ }
+
+ do {
+
+ audioBuffer.frameCount = frames;
+
+ status_t err = obtainBuffer(&audioBuffer, waitCount);
+ if (err < NO_ERROR) {
+ if (err != TIMED_OUT) {
+ ALOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
+ return false;
+ }
+ break;
+ }
+ if (err == status_t(STOPPED)) return false;
+
+ // Divide buffer size by 2 to take into account the expansion
+ // due to 8 to 16 bit conversion: the callback must fill only half
+ // of the destination buffer
+ if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT)) {
+ audioBuffer.size >>= 1;
+ }
+
+ size_t reqSize = audioBuffer.size;
+ mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
+ writtenSize = audioBuffer.size;
+
+ // Sanity check on returned size
+ if (ssize_t(writtenSize) <= 0) {
+ // The callback is done filling buffers
+ // Keep this thread going to handle timed events and
+ // still try to get more data in intervals of WAIT_PERIOD_MS
+ // but don't just loop and block the CPU, so wait
+ usleep(WAIT_PERIOD_MS*1000);
+ break;
+ }
+ if (writtenSize > reqSize) writtenSize = reqSize;
+
+ if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT)) {
+ // 8 to 16 bit conversion, note that source and destination are the same address
+ memcpy_to_i16_from_u8(audioBuffer.i16, (const uint8_t *) audioBuffer.i8, writtenSize);
+ writtenSize <<= 1;
+ }
+
+ audioBuffer.size = writtenSize;
+ // NOTE: mCblk->frameSize is not equal to AudioTrack::frameSize() for
+ // 8 bit PCM data: in this case, mCblk->frameSize is based on a sample size of
+ // 16 bit.
+ audioBuffer.frameCount = writtenSize/mCblk->frameSize;
+
+ frames -= audioBuffer.frameCount;
+
+ releaseBuffer(&audioBuffer);
+ }
+ while (frames);
+
+ if (frames == 0) {
+ mRemainingFrames = mNotificationFramesAct;
+ } else {
+ mRemainingFrames = frames;
+ }
+ return true;
+}
+
+// must be called with mLock and cblk.lock held. Callers must also hold strong references on
+// the IAudioTrack and IMemory in case they are recreated here.
+// If the IAudioTrack is successfully restored, the cblk pointer is updated
+status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart)
+{
+ status_t result;
+
+ if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) {
+ ALOGW("dead IAudioTrack, creating a new one from %s TID %d",
+ fromStart ? "start()" : "obtainBuffer()", gettid());
+
+ // signal old cblk condition so that other threads waiting for available buffers stop
+ // waiting now
+ cblk->cv.broadcast();
+ cblk->lock.unlock();
+
+ // refresh the audio configuration cache in this process to make sure we get new
+ // output parameters in getOutput_l() and createTrack_l()
+ AudioSystem::clearAudioConfigCache();
+
+ // if the new IAudioTrack is created, createTrack_l() will modify the
+ // following member variables: mAudioTrack, mCblkMemory and mCblk.
+ // It will also delete the strong references on previous IAudioTrack and IMemory
+ result = createTrack_l(mStreamType,
+ cblk->sampleRate,
+ mFormat,
+ mChannelMask,
+ mFrameCount,
+ mFlags,
+ mSharedBuffer,
+ getOutput_l());
+
+ if (result == NO_ERROR) {
+ uint32_t user = cblk->user;
+ uint32_t server = cblk->server;
+ // restore write index and set other indexes to reflect empty buffer status
+ mCblk->user = user;
+ mCblk->server = user;
+ mCblk->userBase = user;
+ mCblk->serverBase = user;
+ // restore loop: this is not guaranteed to succeed if new frame count is not
+ // compatible with loop length
+ setLoop_l(cblk->loopStart, cblk->loopEnd, cblk->loopCount);
+ if (!fromStart) {
+ mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+ // Make sure that a client relying on callback events indicating underrun or
+ // the actual amount of audio frames played (e.g SoundPool) receives them.
+ if (mSharedBuffer == 0) {
+ uint32_t frames = 0;
+ if (user > server) {
+ frames = ((user - server) > mCblk->frameCount) ?
+ mCblk->frameCount : (user - server);
+ memset(mCblk->buffers, 0, frames * mCblk->frameSize);
+ }
+ // restart playback even if buffer is not completely filled.
+ android_atomic_or(CBLK_FORCEREADY_ON, &mCblk->flags);
+ // stepUser() clears CBLK_UNDERRUN_ON flag enabling underrun callbacks to
+ // the client
+ mCblk->stepUser(frames);
+ }
+ }
+ if (mActive) {
+ result = mAudioTrack->start(0); // callback thread hasn't changed
+ ALOGW_IF(result != NO_ERROR, "restoreTrack_l() start() failed status %d", result);
+ }
+ if (fromStart && result == NO_ERROR) {
+ mNewPosition = mCblk->server + mUpdatePeriod;
+ }
+ }
+ if (result != NO_ERROR) {
+ android_atomic_and(~CBLK_RESTORING_ON, &cblk->flags);
+ ALOGW_IF(result != NO_ERROR, "restoreTrack_l() failed status %d", result);
+ }
+ mRestoreStatus = result;
+ // signal old cblk condition for other threads waiting for restore completion
+ android_atomic_or(CBLK_RESTORED_ON, &cblk->flags);
+ cblk->cv.broadcast();
+ } else {
+ if (!(cblk->flags & CBLK_RESTORED_MSK)) {
+ ALOGW("dead IAudioTrack, waiting for a new one TID %d", gettid());
+ mLock.unlock();
+ result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS));
+ if (result == NO_ERROR) {
+ result = mRestoreStatus;
+ }
+ cblk->lock.unlock();
+ mLock.lock();
+ } else {
+ ALOGW("dead IAudioTrack, already restored TID %d", gettid());
+ result = mRestoreStatus;
+ cblk->lock.unlock();
+ }
+ }
+ ALOGV("restoreTrack_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x",
+ result, mActive, mCblk, cblk, mCblk->flags, cblk->flags);
+
+ if (result == NO_ERROR) {
+ // from now on we switch to the newly created cblk
+ cblk = mCblk;
+ }
+ cblk->lock.lock();
+
+ ALOGW_IF(result != NO_ERROR, "restoreTrack_l() error %d TID %d", result, gettid());
+
+ return result;
+}
+
+status_t AudioTrack::dump(int fd, const Vector<String16>& args) const
+{
+
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ 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, 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);
+ snprintf(buffer, 255, " active(%d), latency (%d)\n", mActive, mLatency);
+ result.append(buffer);
+ ::write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+// =========================================================================
+
+AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava)
+ : Thread(bCanCallJava), mReceiver(receiver)
+{
+}
+
+bool AudioTrack::AudioTrackThread::threadLoop()
+{
+ return mReceiver.processAudioBuffer(this);
+}
+
+status_t AudioTrack::AudioTrackThread::readyToRun()
+{
+ return NO_ERROR;
+}
+
+void AudioTrack::AudioTrackThread::onFirstRef()
+{
+}
+
+// =========================================================================
+
+
+audio_track_cblk_t::audio_track_cblk_t()
+ : lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0),
+ userBase(0), serverBase(0), buffers(NULL), frameCount(0),
+ loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), mVolumeLR(0x10001000),
+ mSendLevel(0), flags(0)
+{
+}
+
+uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount)
+{
+ uint32_t u = user;
+
+ u += frameCount;
+ // Ensure that user is never ahead of server for AudioRecord
+ 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;
+ }
+ } else if (u > server) {
+ ALOGW("stepServer occurred after track reset");
+ u = server;
+ }
+
+ if (u >= userBase + this->frameCount) {
+ userBase += this->frameCount;
+ }
+
+ user = u;
+
+ // Clear flow control error condition as new data has been written/read to/from buffer.
+ if (flags & CBLK_UNDERRUN_MSK) {
+ android_atomic_and(~CBLK_UNDERRUN_MSK, &flags);
+ }
+
+ return u;
+}
+
+bool audio_track_cblk_t::stepServer(uint32_t frameCount)
+{
+ if (!tryLock()) {
+ ALOGW("stepServer() could not lock cblk");
+ return false;
+ }
+
+ uint32_t s = server;
+
+ s += frameCount;
+ 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) {
+ bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS - 1;
+ }
+ // It is possible that we receive a flush()
+ // while the mixer is processing a block: in this case,
+ // stepServer() is called After the flush() has reset u & s and
+ // we have s > u
+ if (s > user) {
+ ALOGW("stepServer occurred after track reset");
+ s = user;
+ }
+ }
+
+ if (s >= loopEnd) {
+ ALOGW_IF(s > loopEnd, "stepServer: s %u > loopEnd %u", s, loopEnd);
+ s = loopStart;
+ if (--loopCount == 0) {
+ loopEnd = UINT_MAX;
+ loopStart = UINT_MAX;
+ }
+ }
+ if (s >= serverBase + this->frameCount) {
+ serverBase += this->frameCount;
+ }
+
+ server = s;
+
+ if (!(flags & CBLK_INVALID_MSK)) {
+ cv.signal();
+ }
+ lock.unlock();
+ return true;
+}
+
+void* audio_track_cblk_t::buffer(uint32_t offset) const
+{
+ return (int8_t *)buffers + (offset - userBase) * frameSize;
+}
+
+uint32_t audio_track_cblk_t::framesAvailable()
+{
+ Mutex::Autolock _l(lock);
+ return framesAvailable_l();
+}
+
+uint32_t audio_track_cblk_t::framesAvailable_l()
+{
+ uint32_t u = user;
+ uint32_t s = server;
+
+ if (flags & CBLK_DIRECTION_MSK) {
+ uint32_t limit = (s < loopStart) ? s : loopStart;
+ return limit + frameCount - u;
+ } else {
+ return frameCount + u - s;
+ }
+}
+
+uint32_t audio_track_cblk_t::framesReady()
+{
+ uint32_t u = user;
+ uint32_t s = server;
+
+ if (flags & CBLK_DIRECTION_MSK) {
+ if (u < loopEnd) {
+ return u - s;
+ } else {
+ // do not block on mutex shared with client on AudioFlinger side
+ if (!tryLock()) {
+ ALOGW("framesReady() could not lock cblk");
+ return 0;
+ }
+ uint32_t frames = UINT_MAX;
+ if (loopCount >= 0) {
+ frames = (loopEnd - loopStart)*loopCount + u - s;
+ }
+ lock.unlock();
+ return frames;
+ }
+ } else {
+ return s - u;
+ }
+}
+
+bool audio_track_cblk_t::tryLock()
+{
+ // the code below simulates lock-with-timeout
+ // we MUST do this to protect the AudioFlinger server
+ // as this lock is shared with the client.
+ status_t err;
+
+ err = lock.tryLock();
+ if (err == -EBUSY) { // just wait a bit
+ usleep(1000);
+ err = lock.tryLock();
+ }
+ if (err != NO_ERROR) {
+ // probably, the client just died.
+ return false;
+ }
+ return true;
+}
+
+// -------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
new file mode 100644
index 0000000..ce10c8e
--- /dev/null
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -0,0 +1,1025 @@
+/*
+**
+** 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_TAG "IAudioFlinger"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <media/IAudioFlinger.h>
+
+namespace android {
+
+enum {
+ CREATE_TRACK = IBinder::FIRST_CALL_TRANSACTION,
+ OPEN_RECORD,
+ SAMPLE_RATE,
+ CHANNEL_COUNT,
+ FORMAT,
+ FRAME_COUNT,
+ LATENCY,
+ SET_MASTER_VOLUME,
+ SET_MASTER_MUTE,
+ MASTER_VOLUME,
+ MASTER_MUTE,
+ SET_STREAM_VOLUME,
+ SET_STREAM_MUTE,
+ STREAM_VOLUME,
+ STREAM_MUTE,
+ SET_MODE,
+ SET_MIC_MUTE,
+ GET_MIC_MUTE,
+ SET_PARAMETERS,
+ GET_PARAMETERS,
+ REGISTER_CLIENT,
+ GET_INPUTBUFFERSIZE,
+ OPEN_OUTPUT,
+ OPEN_DUPLICATE_OUTPUT,
+ CLOSE_OUTPUT,
+ SUSPEND_OUTPUT,
+ RESTORE_OUTPUT,
+ OPEN_INPUT,
+ CLOSE_INPUT,
+ SET_STREAM_OUTPUT,
+ SET_VOICE_VOLUME,
+ GET_RENDER_POSITION,
+ GET_INPUT_FRAMES_LOST,
+ NEW_AUDIO_SESSION_ID,
+ ACQUIRE_AUDIO_SESSION_ID,
+ RELEASE_AUDIO_SESSION_ID,
+ QUERY_NUM_EFFECTS,
+ QUERY_EFFECT,
+ GET_EFFECT_DESCRIPTOR,
+ CREATE_EFFECT,
+ MOVE_EFFECTS
+};
+
+class BpAudioFlinger : public BpInterface<IAudioFlinger>
+{
+public:
+ BpAudioFlinger(const sp<IBinder>& impl)
+ : BpInterface<IAudioFlinger>(impl)
+ {
+ }
+
+ virtual sp<IAudioTrack> createTrack(
+ pid_t pid,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ track_flags_t flags,
+ const sp<IMemory>& sharedBuffer,
+ audio_io_handle_t output,
+ int *sessionId,
+ status_t *status)
+ {
+ Parcel data, reply;
+ sp<IAudioTrack> track;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(pid);
+ data.writeInt32((int32_t) streamType);
+ data.writeInt32(sampleRate);
+ data.writeInt32(format);
+ data.writeInt32(channelMask);
+ data.writeInt32(frameCount);
+ data.writeInt32((int32_t) flags);
+ data.writeStrongBinder(sharedBuffer->asBinder());
+ data.writeInt32((int32_t) 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) {
+ ALOGE("createTrack error: %s", strerror(-lStatus));
+ } else {
+ lSessionId = reply.readInt32();
+ if (sessionId != NULL) {
+ *sessionId = lSessionId;
+ }
+ lStatus = reply.readInt32();
+ track = interface_cast<IAudioTrack>(reply.readStrongBinder());
+ }
+ if (status) {
+ *status = lStatus;
+ }
+ return track;
+ }
+
+ virtual sp<IAudioRecord> openRecord(
+ pid_t pid,
+ audio_io_handle_t input,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ track_flags_t flags,
+ int *sessionId,
+ status_t *status)
+ {
+ Parcel data, reply;
+ sp<IAudioRecord> record;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(pid);
+ data.writeInt32((int32_t) input);
+ data.writeInt32(sampleRate);
+ data.writeInt32(format);
+ data.writeInt32(channelMask);
+ 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) {
+ ALOGE("openRecord error: %s", strerror(-lStatus));
+ } else {
+ lSessionId = reply.readInt32();
+ if (sessionId != NULL) {
+ *sessionId = lSessionId;
+ }
+ lStatus = reply.readInt32();
+ record = interface_cast<IAudioRecord>(reply.readStrongBinder());
+ }
+ if (status) {
+ *status = lStatus;
+ }
+ return record;
+ }
+
+ virtual uint32_t sampleRate(audio_io_handle_t output) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) output);
+ remote()->transact(SAMPLE_RATE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual int channelCount(audio_io_handle_t output) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) output);
+ remote()->transact(CHANNEL_COUNT, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual audio_format_t format(audio_io_handle_t output) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) output);
+ remote()->transact(FORMAT, data, &reply);
+ return (audio_format_t) reply.readInt32();
+ }
+
+ virtual size_t frameCount(audio_io_handle_t output) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) output);
+ remote()->transact(FRAME_COUNT, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual uint32_t latency(audio_io_handle_t output) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) output);
+ remote()->transact(LATENCY, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t setMasterVolume(float value)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeFloat(value);
+ remote()->transact(SET_MASTER_VOLUME, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t setMasterMute(bool muted)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(muted);
+ remote()->transact(SET_MASTER_MUTE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual float masterVolume() const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ remote()->transact(MASTER_VOLUME, data, &reply);
+ return reply.readFloat();
+ }
+
+ virtual bool masterMute() const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ remote()->transact(MASTER_MUTE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t setStreamVolume(audio_stream_type_t stream, float value,
+ audio_io_handle_t output)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) stream);
+ data.writeFloat(value);
+ data.writeInt32((int32_t) output);
+ remote()->transact(SET_STREAM_VOLUME, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t setStreamMute(audio_stream_type_t stream, bool muted)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) stream);
+ data.writeInt32(muted);
+ remote()->transact(SET_STREAM_MUTE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual float streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) stream);
+ data.writeInt32((int32_t) output);
+ remote()->transact(STREAM_VOLUME, data, &reply);
+ return reply.readFloat();
+ }
+
+ virtual bool streamMute(audio_stream_type_t stream) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) stream);
+ remote()->transact(STREAM_MUTE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t setMode(audio_mode_t mode)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(mode);
+ remote()->transact(SET_MODE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t setMicMute(bool state)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(state);
+ remote()->transact(SET_MIC_MUTE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual bool getMicMute() const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ remote()->transact(GET_MIC_MUTE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) ioHandle);
+ data.writeString8(keyValuePairs);
+ remote()->transact(SET_PARAMETERS, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) ioHandle);
+ data.writeString8(keys);
+ remote()->transact(GET_PARAMETERS, data, &reply);
+ return reply.readString8();
+ }
+
+ virtual void registerClient(const sp<IAudioFlingerClient>& client)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeStrongBinder(client->asBinder());
+ remote()->transact(REGISTER_CLIENT, data, &reply);
+ }
+
+ virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(sampleRate);
+ data.writeInt32(format);
+ data.writeInt32(channelCount);
+ remote()->transact(GET_INPUTBUFFERSIZE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual audio_io_handle_t openOutput(uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ audio_format_t *pFormat,
+ uint32_t *pChannels,
+ uint32_t *pLatencyMs,
+ audio_policy_output_flags_t flags)
+ {
+ Parcel data, reply;
+ uint32_t devices = pDevices ? *pDevices : 0;
+ uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+ audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT;
+ uint32_t channels = pChannels ? *pChannels : 0;
+ uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
+
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(devices);
+ data.writeInt32(samplingRate);
+ data.writeInt32(format);
+ data.writeInt32(channels);
+ data.writeInt32(latency);
+ data.writeInt32((int32_t) flags);
+ remote()->transact(OPEN_OUTPUT, data, &reply);
+ audio_io_handle_t output = (audio_io_handle_t) reply.readInt32();
+ ALOGV("openOutput() returned output, %d", output);
+ devices = reply.readInt32();
+ if (pDevices) *pDevices = devices;
+ samplingRate = reply.readInt32();
+ if (pSamplingRate) *pSamplingRate = samplingRate;
+ format = (audio_format_t) reply.readInt32();
+ if (pFormat) *pFormat = format;
+ channels = reply.readInt32();
+ if (pChannels) *pChannels = channels;
+ latency = reply.readInt32();
+ if (pLatencyMs) *pLatencyMs = latency;
+ return output;
+ }
+
+ virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
+ audio_io_handle_t output2)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) output1);
+ data.writeInt32((int32_t) output2);
+ remote()->transact(OPEN_DUPLICATE_OUTPUT, data, &reply);
+ return (audio_io_handle_t) reply.readInt32();
+ }
+
+ virtual status_t closeOutput(audio_io_handle_t output)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) output);
+ remote()->transact(CLOSE_OUTPUT, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t suspendOutput(audio_io_handle_t output)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) output);
+ remote()->transact(SUSPEND_OUTPUT, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t restoreOutput(audio_io_handle_t output)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) output);
+ remote()->transact(RESTORE_OUTPUT, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual audio_io_handle_t openInput(uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ audio_format_t *pFormat,
+ uint32_t *pChannels,
+ audio_in_acoustics_t acoustics)
+ {
+ Parcel data, reply;
+ uint32_t devices = pDevices ? *pDevices : 0;
+ uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+ audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT;
+ uint32_t channels = pChannels ? *pChannels : 0;
+
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(devices);
+ data.writeInt32(samplingRate);
+ data.writeInt32(format);
+ data.writeInt32(channels);
+ data.writeInt32((int32_t) acoustics);
+ remote()->transact(OPEN_INPUT, data, &reply);
+ audio_io_handle_t input = (audio_io_handle_t) reply.readInt32();
+ devices = reply.readInt32();
+ if (pDevices) *pDevices = devices;
+ samplingRate = reply.readInt32();
+ if (pSamplingRate) *pSamplingRate = samplingRate;
+ format = (audio_format_t) reply.readInt32();
+ if (pFormat) *pFormat = format;
+ channels = reply.readInt32();
+ if (pChannels) *pChannels = channels;
+ return input;
+ }
+
+ virtual status_t closeInput(int input)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(input);
+ remote()->transact(CLOSE_INPUT, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) stream);
+ data.writeInt32((int32_t) output);
+ remote()->transact(SET_STREAM_OUTPUT, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t setVoiceVolume(float volume)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeFloat(volume);
+ remote()->transact(SET_VOICE_VOLUME, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
+ audio_io_handle_t output) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) output);
+ remote()->transact(GET_RENDER_POSITION, data, &reply);
+ status_t status = reply.readInt32();
+ if (status == NO_ERROR) {
+ uint32_t tmp = reply.readInt32();
+ if (halFrames) {
+ *halFrames = tmp;
+ }
+ tmp = reply.readInt32();
+ if (dspFrames) {
+ *dspFrames = tmp;
+ }
+ }
+ return status;
+ }
+
+ virtual unsigned int getInputFramesLost(audio_io_handle_t ioHandle) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) ioHandle);
+ 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 void acquireAudioSessionId(int audioSession)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(audioSession);
+ remote()->transact(ACQUIRE_AUDIO_SESSION_ID, data, &reply);
+ }
+
+ virtual void releaseAudioSessionId(int audioSession)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(audioSession);
+ remote()->transact(RELEASE_AUDIO_SESSION_ID, data, &reply);
+ }
+
+ virtual status_t queryNumberEffects(uint32_t *numEffects) const
+ {
+ 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 != NULL) {
+ *numEffects = (uint32_t)reply.readInt32();
+ }
+ return NO_ERROR;
+ }
+
+ virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor) const
+ {
+ 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(const effect_uuid_t *pUuid,
+ effect_descriptor_t *pDescriptor) const
+ {
+ 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,
+ audio_io_handle_t 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((int32_t) output);
+ data.writeInt32(sessionId);
+
+ status_t lStatus = remote()->transact(CREATE_EFFECT, data, &reply);
+ if (lStatus != NO_ERROR) {
+ ALOGE("createEffect error: %s", strerror(-lStatus));
+ } else {
+ lStatus = reply.readInt32();
+ int tmp = reply.readInt32();
+ if (id) {
+ *id = tmp;
+ }
+ tmp = reply.readInt32();
+ if (enabled != NULL) {
+ *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, audio_io_handle_t srcOutput,
+ audio_io_handle_t dstOutput)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(session);
+ data.writeInt32((int32_t) srcOutput);
+ data.writeInt32((int32_t) dstOutput);
+ remote()->transact(MOVE_EFFECTS, data, &reply);
+ return reply.readInt32();
+ }
+};
+
+IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
+
+// ----------------------------------------------------------------------
+
+status_t BnAudioFlinger::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case CREATE_TRACK: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ pid_t pid = data.readInt32();
+ int streamType = data.readInt32();
+ uint32_t sampleRate = data.readInt32();
+ audio_format_t format = (audio_format_t) data.readInt32();
+ int channelCount = data.readInt32();
+ size_t bufferCount = data.readInt32();
+ track_flags_t flags = (track_flags_t) data.readInt32();
+ sp<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder());
+ audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
+ int sessionId = data.readInt32();
+ status_t status;
+ sp<IAudioTrack> track = createTrack(pid,
+ (audio_stream_type_t) streamType, sampleRate, format,
+ channelCount, bufferCount, flags, buffer, output, &sessionId, &status);
+ reply->writeInt32(sessionId);
+ reply->writeInt32(status);
+ reply->writeStrongBinder(track->asBinder());
+ return NO_ERROR;
+ } break;
+ case OPEN_RECORD: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ pid_t pid = data.readInt32();
+ audio_io_handle_t input = (audio_io_handle_t) data.readInt32();
+ uint32_t sampleRate = data.readInt32();
+ audio_format_t format = (audio_format_t) data.readInt32();
+ int channelCount = data.readInt32();
+ size_t bufferCount = data.readInt32();
+ track_flags_t flags = (track_flags_t) data.readInt32();
+ int sessionId = data.readInt32();
+ status_t status;
+ sp<IAudioRecord> record = openRecord(pid, input,
+ sampleRate, format, channelCount, bufferCount, flags, &sessionId, &status);
+ reply->writeInt32(sessionId);
+ reply->writeInt32(status);
+ reply->writeStrongBinder(record->asBinder());
+ return NO_ERROR;
+ } break;
+ case SAMPLE_RATE: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32( sampleRate((audio_io_handle_t) data.readInt32()) );
+ return NO_ERROR;
+ } break;
+ case CHANNEL_COUNT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32( channelCount((audio_io_handle_t) data.readInt32()) );
+ return NO_ERROR;
+ } break;
+ case FORMAT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32( format((audio_io_handle_t) data.readInt32()) );
+ return NO_ERROR;
+ } break;
+ case FRAME_COUNT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32( frameCount((audio_io_handle_t) data.readInt32()) );
+ return NO_ERROR;
+ } break;
+ case LATENCY: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32( latency((audio_io_handle_t) data.readInt32()) );
+ return NO_ERROR;
+ } break;
+ case SET_MASTER_VOLUME: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32( setMasterVolume(data.readFloat()) );
+ return NO_ERROR;
+ } break;
+ case SET_MASTER_MUTE: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32( setMasterMute(data.readInt32()) );
+ return NO_ERROR;
+ } break;
+ case MASTER_VOLUME: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeFloat( masterVolume() );
+ return NO_ERROR;
+ } break;
+ case MASTER_MUTE: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32( masterMute() );
+ return NO_ERROR;
+ } break;
+ case SET_STREAM_VOLUME: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int stream = data.readInt32();
+ float volume = data.readFloat();
+ audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
+ reply->writeInt32( setStreamVolume((audio_stream_type_t) stream, volume, output) );
+ return NO_ERROR;
+ } break;
+ case SET_STREAM_MUTE: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int stream = data.readInt32();
+ reply->writeInt32( setStreamMute((audio_stream_type_t) stream, data.readInt32()) );
+ return NO_ERROR;
+ } break;
+ case STREAM_VOLUME: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int stream = data.readInt32();
+ int output = data.readInt32();
+ reply->writeFloat( streamVolume((audio_stream_type_t) stream, output) );
+ return NO_ERROR;
+ } break;
+ case STREAM_MUTE: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int stream = data.readInt32();
+ reply->writeInt32( streamMute((audio_stream_type_t) stream) );
+ return NO_ERROR;
+ } break;
+ case SET_MODE: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ audio_mode_t mode = (audio_mode_t) data.readInt32();
+ reply->writeInt32( setMode(mode) );
+ return NO_ERROR;
+ } break;
+ case SET_MIC_MUTE: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int state = data.readInt32();
+ reply->writeInt32( setMicMute(state) );
+ return NO_ERROR;
+ } break;
+ case GET_MIC_MUTE: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32( getMicMute() );
+ return NO_ERROR;
+ } break;
+ case SET_PARAMETERS: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ audio_io_handle_t ioHandle = (audio_io_handle_t) data.readInt32();
+ String8 keyValuePairs(data.readString8());
+ reply->writeInt32(setParameters(ioHandle, keyValuePairs));
+ return NO_ERROR;
+ } break;
+ case GET_PARAMETERS: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ audio_io_handle_t ioHandle = (audio_io_handle_t) data.readInt32();
+ String8 keys(data.readString8());
+ reply->writeString8(getParameters(ioHandle, keys));
+ return NO_ERROR;
+ } break;
+
+ case REGISTER_CLIENT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient>(data.readStrongBinder());
+ registerClient(client);
+ return NO_ERROR;
+ } break;
+ case GET_INPUTBUFFERSIZE: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ uint32_t sampleRate = data.readInt32();
+ audio_format_t format = (audio_format_t) data.readInt32();
+ int channelCount = data.readInt32();
+ reply->writeInt32( getInputBufferSize(sampleRate, format, channelCount) );
+ return NO_ERROR;
+ } break;
+ case OPEN_OUTPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ uint32_t devices = data.readInt32();
+ uint32_t samplingRate = data.readInt32();
+ audio_format_t format = (audio_format_t) data.readInt32();
+ uint32_t channels = data.readInt32();
+ uint32_t latency = data.readInt32();
+ audio_policy_output_flags_t flags = (audio_policy_output_flags_t) data.readInt32();
+ audio_io_handle_t output = openOutput(&devices,
+ &samplingRate,
+ &format,
+ &channels,
+ &latency,
+ flags);
+ ALOGV("OPEN_OUTPUT output, %p", output);
+ reply->writeInt32((int32_t) output);
+ reply->writeInt32(devices);
+ reply->writeInt32(samplingRate);
+ reply->writeInt32(format);
+ reply->writeInt32(channels);
+ reply->writeInt32(latency);
+ return NO_ERROR;
+ } break;
+ case OPEN_DUPLICATE_OUTPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ audio_io_handle_t output1 = (audio_io_handle_t) data.readInt32();
+ audio_io_handle_t output2 = (audio_io_handle_t) data.readInt32();
+ reply->writeInt32((int32_t) openDuplicateOutput(output1, output2));
+ return NO_ERROR;
+ } break;
+ case CLOSE_OUTPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32(closeOutput((audio_io_handle_t) data.readInt32()));
+ return NO_ERROR;
+ } break;
+ case SUSPEND_OUTPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32(suspendOutput((audio_io_handle_t) data.readInt32()));
+ return NO_ERROR;
+ } break;
+ case RESTORE_OUTPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32(restoreOutput((audio_io_handle_t) data.readInt32()));
+ return NO_ERROR;
+ } break;
+ case OPEN_INPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ uint32_t devices = data.readInt32();
+ uint32_t samplingRate = data.readInt32();
+ audio_format_t format = (audio_format_t) data.readInt32();
+ uint32_t channels = data.readInt32();
+ audio_in_acoustics_t acoustics = (audio_in_acoustics_t) data.readInt32();
+
+ audio_io_handle_t input = openInput(&devices,
+ &samplingRate,
+ &format,
+ &channels,
+ acoustics);
+ reply->writeInt32((int32_t) input);
+ reply->writeInt32(devices);
+ reply->writeInt32(samplingRate);
+ reply->writeInt32(format);
+ reply->writeInt32(channels);
+ return NO_ERROR;
+ } break;
+ case CLOSE_INPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32(closeInput((audio_io_handle_t) data.readInt32()));
+ return NO_ERROR;
+ } break;
+ case SET_STREAM_OUTPUT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ uint32_t stream = data.readInt32();
+ audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
+ reply->writeInt32(setStreamOutput((audio_stream_type_t) stream, output));
+ return NO_ERROR;
+ } break;
+ case SET_VOICE_VOLUME: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ float volume = data.readFloat();
+ reply->writeInt32( setVoiceVolume(volume) );
+ return NO_ERROR;
+ } break;
+ case GET_RENDER_POSITION: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
+ uint32_t halFrames;
+ uint32_t dspFrames;
+ status_t status = getRenderPosition(&halFrames, &dspFrames, output);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->writeInt32(halFrames);
+ reply->writeInt32(dspFrames);
+ }
+ return NO_ERROR;
+ }
+ case GET_INPUT_FRAMES_LOST: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ audio_io_handle_t ioHandle = (audio_io_handle_t) data.readInt32();
+ 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 ACQUIRE_AUDIO_SESSION_ID: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int audioSession = data.readInt32();
+ acquireAudioSessionId(audioSession);
+ return NO_ERROR;
+ } break;
+ case RELEASE_AUDIO_SESSION_ID: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int audioSession = data.readInt32();
+ releaseAudioSessionId(audioSession);
+ return NO_ERROR;
+ } break;
+ 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();
+ audio_io_handle_t output = (audio_io_handle_t) 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();
+ audio_io_handle_t srcOutput = (audio_io_handle_t) data.readInt32();
+ audio_io_handle_t dstOutput = (audio_io_handle_t) data.readInt32();
+ reply->writeInt32(moveEffects(session, srcOutput, dstOutput));
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
new file mode 100644
index 0000000..4178b29
--- /dev/null
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -0,0 +1,101 @@
+/*
+ * 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 "IAudioFlingerClient"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <media/IAudioFlingerClient.h>
+#include <media/AudioSystem.h>
+
+namespace android {
+
+enum {
+ IO_CONFIG_CHANGED = IBinder::FIRST_CALL_TRANSACTION
+};
+
+class BpAudioFlingerClient : public BpInterface<IAudioFlingerClient>
+{
+public:
+ BpAudioFlingerClient(const sp<IBinder>& impl)
+ : BpInterface<IAudioFlingerClient>(impl)
+ {
+ }
+
+ void ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
+ data.writeInt32(event);
+ data.writeInt32((int32_t) ioHandle);
+ if (event == AudioSystem::STREAM_CONFIG_CHANGED) {
+ uint32_t stream = *(const uint32_t *)param2;
+ ALOGV("ioConfigChanged stream %d", stream);
+ data.writeInt32(stream);
+ } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED) {
+ const AudioSystem::OutputDescriptor *desc = (const AudioSystem::OutputDescriptor *)param2;
+ data.writeInt32(desc->samplingRate);
+ data.writeInt32(desc->format);
+ data.writeInt32(desc->channels);
+ data.writeInt32(desc->frameCount);
+ data.writeInt32(desc->latency);
+ }
+ remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(AudioFlingerClient, "android.media.IAudioFlingerClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnAudioFlingerClient::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case IO_CONFIG_CHANGED: {
+ CHECK_INTERFACE(IAudioFlingerClient, data, reply);
+ int event = data.readInt32();
+ audio_io_handle_t ioHandle = (audio_io_handle_t) data.readInt32();
+ const void *param2 = NULL;
+ AudioSystem::OutputDescriptor desc;
+ uint32_t stream;
+ if (event == AudioSystem::STREAM_CONFIG_CHANGED) {
+ stream = data.readInt32();
+ param2 = &stream;
+ ALOGV("STREAM_CONFIG_CHANGED stream %d", stream);
+ } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED) {
+ desc.samplingRate = data.readInt32();
+ desc.format = data.readInt32();
+ desc.channels = data.readInt32();
+ desc.frameCount = data.readInt32();
+ desc.latency = data.readInt32();
+ param2 = &desc;
+ }
+ ioConfigChanged(event, ioHandle, param2);
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
new file mode 100644
index 0000000..5040bd9
--- /dev/null
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -0,0 +1,630 @@
+/*
+**
+** 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 "IAudioPolicyService"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <media/IAudioPolicyService.h>
+
+#include <system/audio.h>
+
+namespace android {
+
+enum {
+ SET_DEVICE_CONNECTION_STATE = IBinder::FIRST_CALL_TRANSACTION,
+ GET_DEVICE_CONNECTION_STATE,
+ SET_PHONE_STATE,
+ SET_RINGER_MODE, // reserved, no longer used
+ SET_FORCE_USE,
+ GET_FORCE_USE,
+ GET_OUTPUT,
+ START_OUTPUT,
+ STOP_OUTPUT,
+ RELEASE_OUTPUT,
+ GET_INPUT,
+ START_INPUT,
+ STOP_INPUT,
+ RELEASE_INPUT,
+ INIT_STREAM_VOLUME,
+ SET_STREAM_VOLUME,
+ GET_STREAM_VOLUME,
+ GET_STRATEGY_FOR_STREAM,
+ GET_OUTPUT_FOR_EFFECT,
+ REGISTER_EFFECT,
+ UNREGISTER_EFFECT,
+ IS_STREAM_ACTIVE,
+ GET_DEVICES_FOR_STREAM,
+ QUERY_DEFAULT_PRE_PROCESSING,
+ SET_EFFECT_ENABLED
+};
+
+class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
+{
+public:
+ BpAudioPolicyService(const sp<IBinder>& impl)
+ : BpInterface<IAudioPolicyService>(impl)
+ {
+ }
+
+ virtual status_t setDeviceConnectionState(
+ audio_devices_t device,
+ audio_policy_dev_state_t state,
+ const char *device_address)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(device));
+ data.writeInt32(static_cast <uint32_t>(state));
+ data.writeCString(device_address);
+ remote()->transact(SET_DEVICE_CONNECTION_STATE, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual audio_policy_dev_state_t getDeviceConnectionState(
+ audio_devices_t device,
+ const char *device_address)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(device));
+ data.writeCString(device_address);
+ remote()->transact(GET_DEVICE_CONNECTION_STATE, data, &reply);
+ return static_cast <audio_policy_dev_state_t>(reply.readInt32());
+ }
+
+ virtual status_t setPhoneState(audio_mode_t state)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(state);
+ remote()->transact(SET_PHONE_STATE, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(usage));
+ data.writeInt32(static_cast <uint32_t>(config));
+ remote()->transact(SET_FORCE_USE, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(usage));
+ remote()->transact(GET_FORCE_USE, data, &reply);
+ return static_cast <audio_policy_forced_cfg_t> (reply.readInt32());
+ }
+
+ virtual audio_io_handle_t getOutput(
+ audio_stream_type_t stream,
+ uint32_t samplingRate,
+ audio_format_t format,
+ uint32_t channels,
+ audio_policy_output_flags_t flags)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(stream));
+ data.writeInt32(samplingRate);
+ data.writeInt32(static_cast <uint32_t>(format));
+ data.writeInt32(channels);
+ data.writeInt32(static_cast <uint32_t>(flags));
+ remote()->transact(GET_OUTPUT, data, &reply);
+ return static_cast <audio_io_handle_t> (reply.readInt32());
+ }
+
+ virtual status_t startOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int session)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(output);
+ data.writeInt32((int32_t) 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,
+ audio_stream_type_t stream,
+ int session)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(output);
+ data.writeInt32((int32_t) stream);
+ data.writeInt32(session);
+ remote()->transact(STOP_OUTPUT, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual void releaseOutput(audio_io_handle_t output)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(output);
+ remote()->transact(RELEASE_OUTPUT, data, &reply);
+ }
+
+ virtual audio_io_handle_t getInput(
+ audio_source_t inputSource,
+ uint32_t samplingRate,
+ audio_format_t format,
+ uint32_t channels,
+ audio_in_acoustics_t acoustics,
+ int audioSession)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32((int32_t) inputSource);
+ data.writeInt32(samplingRate);
+ data.writeInt32(static_cast <uint32_t>(format));
+ data.writeInt32(channels);
+ data.writeInt32(static_cast <uint32_t>(acoustics));
+ data.writeInt32(audioSession);
+ remote()->transact(GET_INPUT, data, &reply);
+ return static_cast <audio_io_handle_t> (reply.readInt32());
+ }
+
+ virtual status_t startInput(audio_io_handle_t input)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(input);
+ remote()->transact(START_INPUT, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual status_t stopInput(audio_io_handle_t input)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(input);
+ remote()->transact(STOP_INPUT, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual void releaseInput(audio_io_handle_t input)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(input);
+ remote()->transact(RELEASE_INPUT, data, &reply);
+ }
+
+ virtual status_t initStreamVolume(audio_stream_type_t stream,
+ int indexMin,
+ int indexMax)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(stream));
+ data.writeInt32(indexMin);
+ data.writeInt32(indexMax);
+ remote()->transact(INIT_STREAM_VOLUME, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
+ int index,
+ audio_devices_t device)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(stream));
+ data.writeInt32(index);
+ data.writeInt32(static_cast <uint32_t>(device));
+ remote()->transact(SET_STREAM_VOLUME, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual status_t getStreamVolumeIndex(audio_stream_type_t stream,
+ int *index,
+ audio_devices_t device)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(stream));
+ data.writeInt32(static_cast <uint32_t>(device));
+
+ remote()->transact(GET_STREAM_VOLUME, data, &reply);
+ int lIndex = reply.readInt32();
+ if (index) *index = lIndex;
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual uint32_t getStrategyForStream(audio_stream_type_t 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_devices_t getDevicesForStream(audio_stream_type_t stream)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(stream));
+ remote()->transact(GET_DEVICES_FOR_STREAM, data, &reply);
+ return (audio_devices_t) 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 io,
+ uint32_t strategy,
+ int session,
+ int id)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(desc, sizeof(effect_descriptor_t));
+ data.writeInt32(io);
+ 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());
+ }
+
+ virtual status_t setEffectEnabled(int id, bool enabled)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(id);
+ data.writeInt32(enabled);
+ remote()->transact(SET_EFFECT_ENABLED, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32((int32_t) stream);
+ data.writeInt32(inPastMs);
+ remote()->transact(IS_STREAM_ACTIVE, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count)
+ {
+ if (descriptors == NULL || count == NULL) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(audioSession);
+ data.writeInt32(*count);
+ status_t status = remote()->transact(QUERY_DEFAULT_PRE_PROCESSING, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = static_cast <status_t> (reply.readInt32());
+ uint32_t retCount = reply.readInt32();
+ if (retCount != 0) {
+ uint32_t numDesc = (retCount < *count) ? retCount : *count;
+ reply.read(descriptors, sizeof(effect_descriptor_t) * numDesc);
+ }
+ *count = retCount;
+ return status;
+ }
+};
+
+IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
+
+// ----------------------------------------------------------------------
+
+
+status_t BnAudioPolicyService::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case SET_DEVICE_CONNECTION_STATE: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_devices_t device =
+ static_cast <audio_devices_t>(data.readInt32());
+ audio_policy_dev_state_t state =
+ static_cast <audio_policy_dev_state_t>(data.readInt32());
+ const char *device_address = data.readCString();
+ 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);
+ audio_devices_t device =
+ static_cast<audio_devices_t> (data.readInt32());
+ const char *device_address = data.readCString();
+ reply->writeInt32(static_cast<uint32_t> (getDeviceConnectionState(device,
+ device_address)));
+ return NO_ERROR;
+ } break;
+
+ case SET_PHONE_STATE: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ reply->writeInt32(static_cast <uint32_t>(setPhoneState((audio_mode_t) data.readInt32())));
+ return NO_ERROR;
+ } break;
+
+ case SET_FORCE_USE: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_policy_force_use_t usage = static_cast <audio_policy_force_use_t>(data.readInt32());
+ audio_policy_forced_cfg_t config =
+ static_cast <audio_policy_forced_cfg_t>(data.readInt32());
+ reply->writeInt32(static_cast <uint32_t>(setForceUse(usage, config)));
+ return NO_ERROR;
+ } break;
+
+ case GET_FORCE_USE: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_policy_force_use_t usage = static_cast <audio_policy_force_use_t>(data.readInt32());
+ reply->writeInt32(static_cast <uint32_t>(getForceUse(usage)));
+ return NO_ERROR;
+ } break;
+
+ case GET_OUTPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_stream_type_t stream =
+ static_cast <audio_stream_type_t>(data.readInt32());
+ uint32_t samplingRate = data.readInt32();
+ audio_format_t format = (audio_format_t) data.readInt32();
+ uint32_t channels = data.readInt32();
+ audio_policy_output_flags_t flags =
+ static_cast <audio_policy_output_flags_t>(data.readInt32());
+
+ audio_io_handle_t output = getOutput(stream,
+ samplingRate,
+ format,
+ channels,
+ flags);
+ reply->writeInt32(static_cast <int>(output));
+ return NO_ERROR;
+ } break;
+
+ case START_OUTPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
+ uint32_t stream = data.readInt32();
+ int session = data.readInt32();
+ reply->writeInt32(static_cast <uint32_t>(startOutput(output,
+ (audio_stream_type_t)stream,
+ session)));
+ return NO_ERROR;
+ } break;
+
+ case STOP_OUTPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
+ uint32_t stream = data.readInt32();
+ int session = data.readInt32();
+ reply->writeInt32(static_cast <uint32_t>(stopOutput(output,
+ (audio_stream_type_t)stream,
+ session)));
+ return NO_ERROR;
+ } break;
+
+ case RELEASE_OUTPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
+ releaseOutput(output);
+ return NO_ERROR;
+ } break;
+
+ case GET_INPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_source_t inputSource = (audio_source_t) data.readInt32();
+ uint32_t samplingRate = data.readInt32();
+ audio_format_t format = (audio_format_t) data.readInt32();
+ uint32_t channels = data.readInt32();
+ audio_in_acoustics_t acoustics =
+ static_cast <audio_in_acoustics_t>(data.readInt32());
+ int audioSession = data.readInt32();
+ audio_io_handle_t input = getInput(inputSource,
+ samplingRate,
+ format,
+ channels,
+ acoustics,
+ audioSession);
+ reply->writeInt32(static_cast <int>(input));
+ return NO_ERROR;
+ } break;
+
+ case START_INPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_io_handle_t input = static_cast <audio_io_handle_t>(data.readInt32());
+ reply->writeInt32(static_cast <uint32_t>(startInput(input)));
+ return NO_ERROR;
+ } break;
+
+ case STOP_INPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_io_handle_t input = static_cast <audio_io_handle_t>(data.readInt32());
+ reply->writeInt32(static_cast <uint32_t>(stopInput(input)));
+ return NO_ERROR;
+ } break;
+
+ case RELEASE_INPUT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_io_handle_t input = static_cast <audio_io_handle_t>(data.readInt32());
+ releaseInput(input);
+ return NO_ERROR;
+ } break;
+
+ case INIT_STREAM_VOLUME: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_stream_type_t stream =
+ static_cast <audio_stream_type_t>(data.readInt32());
+ int indexMin = data.readInt32();
+ int indexMax = data.readInt32();
+ reply->writeInt32(static_cast <uint32_t>(initStreamVolume(stream, indexMin,indexMax)));
+ return NO_ERROR;
+ } break;
+
+ case SET_STREAM_VOLUME: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_stream_type_t stream =
+ static_cast <audio_stream_type_t>(data.readInt32());
+ int index = data.readInt32();
+ audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
+ reply->writeInt32(static_cast <uint32_t>(setStreamVolumeIndex(stream,
+ index,
+ device)));
+ return NO_ERROR;
+ } break;
+
+ case GET_STREAM_VOLUME: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_stream_type_t stream =
+ static_cast <audio_stream_type_t>(data.readInt32());
+ audio_devices_t device = static_cast <audio_devices_t>(data.readInt32());
+ int index;
+ status_t status = getStreamVolumeIndex(stream, &index, device);
+ reply->writeInt32(index);
+ reply->writeInt32(static_cast <uint32_t>(status));
+ return NO_ERROR;
+ } break;
+
+ case GET_STRATEGY_FOR_STREAM: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_stream_type_t stream =
+ static_cast <audio_stream_type_t>(data.readInt32());
+ reply->writeInt32(getStrategyForStream(stream));
+ return NO_ERROR;
+ } break;
+
+ case GET_DEVICES_FOR_STREAM: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_stream_type_t stream =
+ static_cast <audio_stream_type_t>(data.readInt32());
+ reply->writeInt32(static_cast <int>(getDevicesForStream(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 io = data.readInt32();
+ uint32_t strategy = data.readInt32();
+ int session = data.readInt32();
+ int id = data.readInt32();
+ reply->writeInt32(static_cast <int32_t>(registerEffect(&desc,
+ io,
+ 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;
+
+ case SET_EFFECT_ENABLED: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ int id = data.readInt32();
+ bool enabled = static_cast <bool>(data.readInt32());
+ reply->writeInt32(static_cast <int32_t>(setEffectEnabled(id, enabled)));
+ return NO_ERROR;
+ } break;
+
+ case IS_STREAM_ACTIVE: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ audio_stream_type_t stream = (audio_stream_type_t) data.readInt32();
+ uint32_t inPastMs = (uint32_t)data.readInt32();
+ reply->writeInt32( isStreamActive((audio_stream_type_t) stream, inPastMs) );
+ return NO_ERROR;
+ } break;
+
+ case QUERY_DEFAULT_PRE_PROCESSING: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ int audioSession = data.readInt32();
+ uint32_t count = data.readInt32();
+ uint32_t retCount = count;
+ effect_descriptor_t *descriptors =
+ (effect_descriptor_t *)new char[count * sizeof(effect_descriptor_t)];
+ status_t status = queryDefaultPreProcessing(audioSession, descriptors, &retCount);
+ reply->writeInt32(status);
+ if (status != NO_ERROR && status != NO_MEMORY) {
+ retCount = 0;
+ }
+ reply->writeInt32(retCount);
+ if (retCount) {
+ if (retCount < count) {
+ count = retCount;
+ }
+ reply->write(descriptors, sizeof(effect_descriptor_t) * count);
+ }
+ delete[] descriptors;
+ return status;
+ }
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp
new file mode 100644
index 0000000..377b9a8
--- /dev/null
+++ b/media/libmedia/IAudioRecord.cpp
@@ -0,0 +1,107 @@
+/*
+**
+** 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_TAG "IAudioRecord"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <media/IAudioRecord.h>
+
+namespace android {
+
+enum {
+ GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
+ START,
+ STOP
+};
+
+class BpAudioRecord : public BpInterface<IAudioRecord>
+{
+public:
+ BpAudioRecord(const sp<IBinder>& impl)
+ : BpInterface<IAudioRecord>(impl)
+ {
+ }
+
+ virtual status_t start(pid_t tid)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
+ data.writeInt32(tid);
+ status_t status = remote()->transact(START, data, &reply);
+ if (status == NO_ERROR) {
+ status = reply.readInt32();
+ } else {
+ ALOGW("start() error: %s", strerror(-status));
+ }
+ return status;
+ }
+
+ virtual void stop()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
+ remote()->transact(STOP, data, &reply);
+ }
+
+ virtual sp<IMemory> getCblk() const
+ {
+ Parcel data, reply;
+ sp<IMemory> cblk;
+ data.writeInterfaceToken(IAudioRecord::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(AudioRecord, "android.media.IAudioRecord");
+
+// ----------------------------------------------------------------------
+
+status_t BnAudioRecord::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case GET_CBLK: {
+ CHECK_INTERFACE(IAudioRecord, data, reply);
+ reply->writeStrongBinder(getCblk()->asBinder());
+ return NO_ERROR;
+ } break;
+ case START: {
+ CHECK_INTERFACE(IAudioRecord, data, reply);
+ reply->writeInt32(start(data.readInt32()));
+ return NO_ERROR;
+ } break;
+ case STOP: {
+ CHECK_INTERFACE(IAudioRecord, data, reply);
+ stop();
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+}; // namespace android
diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp
new file mode 100644
index 0000000..09f31a7
--- /dev/null
+++ b/media/libmedia/IAudioTrack.cpp
@@ -0,0 +1,245 @@
+/*
+**
+** 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_TAG "IAudioTrack"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <media/IAudioTrack.h>
+
+namespace android {
+
+enum {
+ GET_CBLK = IBinder::FIRST_CALL_TRANSACTION,
+ START,
+ STOP,
+ FLUSH,
+ MUTE,
+ PAUSE,
+ ATTACH_AUX_EFFECT,
+ ALLOCATE_TIMED_BUFFER,
+ QUEUE_TIMED_BUFFER,
+ SET_MEDIA_TIME_TRANSFORM,
+};
+
+class BpAudioTrack : public BpInterface<IAudioTrack>
+{
+public:
+ BpAudioTrack(const sp<IBinder>& impl)
+ : BpInterface<IAudioTrack>(impl)
+ {
+ }
+
+ virtual sp<IMemory> getCblk() const
+ {
+ Parcel data, reply;
+ sp<IMemory> cblk;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_CBLK, data, &reply);
+ if (status == NO_ERROR) {
+ cblk = interface_cast<IMemory>(reply.readStrongBinder());
+ }
+ return cblk;
+ }
+
+ virtual status_t start(pid_t tid)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeInt32(tid);
+ status_t status = remote()->transact(START, data, &reply);
+ if (status == NO_ERROR) {
+ status = reply.readInt32();
+ } else {
+ ALOGW("start() error: %s", strerror(-status));
+ }
+ return status;
+ }
+
+ virtual void stop()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ remote()->transact(STOP, data, &reply);
+ }
+
+ virtual void flush()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ remote()->transact(FLUSH, data, &reply);
+ }
+
+ virtual void mute(bool e)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeInt32(e);
+ remote()->transact(MUTE, data, &reply);
+ }
+
+ virtual void pause()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ remote()->transact(PAUSE, data, &reply);
+ }
+
+ 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 {
+ ALOGW("attachAuxEffect() error: %s", strerror(-status));
+ }
+ return status;
+ }
+
+ virtual status_t allocateTimedBuffer(size_t size, sp<IMemory>* buffer) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeInt32(size);
+ status_t status = remote()->transact(ALLOCATE_TIMED_BUFFER,
+ data, &reply);
+ if (status == NO_ERROR) {
+ status = reply.readInt32();
+ if (status == NO_ERROR) {
+ *buffer = interface_cast<IMemory>(reply.readStrongBinder());
+ }
+ }
+ return status;
+ }
+
+ virtual status_t queueTimedBuffer(const sp<IMemory>& buffer,
+ int64_t pts) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeStrongBinder(buffer->asBinder());
+ data.writeInt64(pts);
+ status_t status = remote()->transact(QUEUE_TIMED_BUFFER,
+ data, &reply);
+ if (status == NO_ERROR) {
+ status = reply.readInt32();
+ }
+ return status;
+ }
+
+ virtual status_t setMediaTimeTransform(const LinearTransform& xform,
+ int target) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeInt64(xform.a_zero);
+ data.writeInt64(xform.b_zero);
+ data.writeInt32(xform.a_to_b_numer);
+ data.writeInt32(xform.a_to_b_denom);
+ data.writeInt32(target);
+ status_t status = remote()->transact(SET_MEDIA_TIME_TRANSFORM,
+ data, &reply);
+ if (status == NO_ERROR) {
+ status = reply.readInt32();
+ }
+ return status;
+ }
+};
+
+IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
+
+// ----------------------------------------------------------------------
+
+status_t BnAudioTrack::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case GET_CBLK: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ reply->writeStrongBinder(getCblk()->asBinder());
+ return NO_ERROR;
+ } break;
+ case START: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ reply->writeInt32(start(data.readInt32()));
+ return NO_ERROR;
+ } break;
+ case STOP: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ stop();
+ return NO_ERROR;
+ } break;
+ case FLUSH: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ flush();
+ return NO_ERROR;
+ } break;
+ case MUTE: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ mute( data.readInt32() );
+ return NO_ERROR;
+ } break;
+ case PAUSE: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ pause();
+ return NO_ERROR;
+ }
+ case ATTACH_AUX_EFFECT: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ reply->writeInt32(attachAuxEffect(data.readInt32()));
+ return NO_ERROR;
+ } break;
+ case ALLOCATE_TIMED_BUFFER: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ sp<IMemory> buffer;
+ status_t status = allocateTimedBuffer(data.readInt32(), &buffer);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->writeStrongBinder(buffer->asBinder());
+ }
+ return NO_ERROR;
+ } break;
+ case QUEUE_TIMED_BUFFER: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ sp<IMemory> buffer = interface_cast<IMemory>(
+ data.readStrongBinder());
+ uint64_t pts = data.readInt64();
+ reply->writeInt32(queueTimedBuffer(buffer, pts));
+ return NO_ERROR;
+ } break;
+ case SET_MEDIA_TIME_TRANSFORM: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ LinearTransform xform;
+ xform.a_zero = data.readInt64();
+ xform.b_zero = data.readInt64();
+ xform.a_to_b_numer = data.readInt32();
+ xform.a_to_b_denom = data.readInt32();
+ int target = data.readInt32();
+ reply->writeInt32(setMediaTimeTransform(xform, target));
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+}; // namespace android
diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp
new file mode 100644
index 0000000..827d7af
--- /dev/null
+++ b/media/libmedia/ICrypto.cpp
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ICrypto"
+#include <utils/Log.h>
+
+#include <binder/Parcel.h>
+#include <media/ICrypto.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+enum {
+ INITIALIZE = IBinder::FIRST_CALL_TRANSACTION,
+ TERMINATE,
+ SET_ENTITLEMENT_KEY,
+ SET_ECM,
+ DECRYPT_VIDEO,
+ DECRYPT_AUDIO,
+};
+
+struct BpCrypto : public BpInterface<ICrypto> {
+ BpCrypto(const sp<IBinder> &impl)
+ : BpInterface<ICrypto>(impl) {
+ }
+
+ virtual status_t initialize() {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
+ remote()->transact(INITIALIZE, data, &reply);
+
+ return reply.readInt32();
+ }
+
+ virtual status_t terminate() {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
+ remote()->transact(TERMINATE, data, &reply);
+
+ return reply.readInt32();
+ }
+
+ virtual status_t setEntitlementKey(
+ const void *key, size_t keyLength) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
+ data.writeInt32(keyLength);
+ data.write(key, keyLength);
+ remote()->transact(SET_ENTITLEMENT_KEY, data, &reply);
+
+ return reply.readInt32();
+ }
+
+ virtual status_t setEntitlementControlMessage(
+ const void *msg, size_t msgLength) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
+ data.writeInt32(msgLength);
+ data.write(msg, msgLength);
+ remote()->transact(SET_ECM, data, &reply);
+
+ return reply.readInt32();
+ }
+
+ virtual ssize_t decryptVideo(
+ const void *iv, size_t ivLength,
+ const void *srcData, size_t srcDataSize,
+ void *dstData, size_t dstDataOffset) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
+ if (iv == NULL) {
+ if (ivLength > 0) {
+ return -EINVAL;
+ }
+
+ data.writeInt32(-1);
+ } else {
+ data.writeInt32(ivLength);
+ data.write(iv, ivLength);
+ }
+
+ data.writeInt32(srcDataSize);
+ data.write(srcData, srcDataSize);
+
+ data.writeIntPtr((intptr_t)dstData);
+ data.writeInt32(dstDataOffset);
+
+ remote()->transact(DECRYPT_VIDEO, data, &reply);
+
+ return reply.readInt32();
+ }
+
+ virtual ssize_t decryptAudio(
+ const void *iv, size_t ivLength,
+ const void *srcData, size_t srcDataSize,
+ void *dstData, size_t dstDataSize) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
+ if (iv == NULL) {
+ if (ivLength > 0) {
+ return -EINVAL;
+ }
+
+ data.writeInt32(-1);
+ } else {
+ data.writeInt32(ivLength);
+ data.write(iv, ivLength);
+ }
+
+ data.writeInt32(srcDataSize);
+ data.write(srcData, srcDataSize);
+ data.writeInt32(dstDataSize);
+
+ remote()->transact(DECRYPT_AUDIO, data, &reply);
+
+ ssize_t res = reply.readInt32();
+
+ if (res <= 0) {
+ return res;
+ }
+
+ reply.read(dstData, res);
+
+ return res;
+ }
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(BpCrypto);
+};
+
+IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
+
+////////////////////////////////////////////////////////////////////////////////
+
+status_t BnCrypto::onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+ switch (code) {
+ case INITIALIZE:
+ {
+ CHECK_INTERFACE(ICrypto, data, reply);
+ reply->writeInt32(initialize());
+
+ return OK;
+ }
+
+ case TERMINATE:
+ {
+ CHECK_INTERFACE(ICrypto, data, reply);
+ reply->writeInt32(terminate());
+
+ return OK;
+ }
+
+ case SET_ENTITLEMENT_KEY:
+ {
+ CHECK_INTERFACE(ICrypto, data, reply);
+
+ size_t keyLength = data.readInt32();
+ void *key = malloc(keyLength);
+ data.read(key, keyLength);
+
+ reply->writeInt32(setEntitlementKey(key, keyLength));
+
+ free(key);
+ key = NULL;
+
+ return OK;
+ }
+
+ case SET_ECM:
+ {
+ CHECK_INTERFACE(ICrypto, data, reply);
+
+ size_t msgLength = data.readInt32();
+ void *msg = malloc(msgLength);
+ data.read(msg, msgLength);
+
+ reply->writeInt32(setEntitlementControlMessage(msg, msgLength));
+
+ free(msg);
+ msg = NULL;
+
+ return OK;
+ }
+
+ case DECRYPT_VIDEO:
+ {
+ CHECK_INTERFACE(ICrypto, data, reply);
+
+ void *iv = NULL;
+
+ int32_t ivLength = data.readInt32();
+ if (ivLength >= 0) {
+ iv = malloc(ivLength);
+ data.read(iv, ivLength);
+ }
+
+ size_t srcDataSize = data.readInt32();
+ void *srcData = malloc(srcDataSize);
+ data.read(srcData, srcDataSize);
+
+ void *dstData = (void *)data.readIntPtr();
+ size_t dstDataOffset = data.readInt32();
+
+ reply->writeInt32(
+ decryptVideo(
+ iv,
+ ivLength < 0 ? 0 : ivLength,
+ srcData,
+ srcDataSize,
+ dstData,
+ dstDataOffset));
+
+ free(srcData);
+ srcData = NULL;
+
+ if (iv != NULL) {
+ free(iv);
+ iv = NULL;
+ }
+
+ return OK;
+ }
+
+ case DECRYPT_AUDIO:
+ {
+ CHECK_INTERFACE(ICrypto, data, reply);
+
+ void *iv = NULL;
+
+ int32_t ivLength = data.readInt32();
+ if (ivLength >= 0) {
+ iv = malloc(ivLength);
+ data.read(iv, ivLength);
+ }
+
+ size_t srcDataSize = data.readInt32();
+ void *srcData = malloc(srcDataSize);
+ data.read(srcData, srcDataSize);
+
+ size_t dstDataSize = data.readInt32();
+ void *dstData = malloc(dstDataSize);
+
+ ssize_t res =
+ decryptAudio(
+ iv,
+ ivLength < 0 ? 0 : ivLength,
+ srcData,
+ srcDataSize,
+ dstData,
+ dstDataSize);
+
+ reply->writeInt32(res);
+
+ if (res > 0) {
+ reply->write(dstData, res);
+ }
+
+ free(dstData);
+ dstData = NULL;
+
+ free(srcData);
+ srcData = NULL;
+
+ if (iv != NULL) {
+ free(iv);
+ iv = NULL;
+ }
+
+ return OK;
+ }
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+} // namespace android
+
diff --git a/media/libmedia/IEffect.cpp b/media/libmedia/IEffect.cpp
new file mode 100644
index 0000000..a303a8f
--- /dev/null
+++ b/media/libmedia/IEffect.cpp
@@ -0,0 +1,201 @@
+/*
+**
+** 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()
+ {
+ ALOGV("enable");
+ Parcel data, reply;
+ data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+ remote()->transact(ENABLE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t disable()
+ {
+ ALOGV("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)
+ {
+ ALOGV("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);
+
+ status_t status = remote()->transact(COMMAND, data, &reply);
+ if (status != NO_ERROR) {
+ if (pReplySize != NULL)
+ *pReplySize = 0;
+ return status;
+ }
+
+ status = reply.readInt32();
+ size = reply.readInt32();
+ if (size != 0 && pReplyData != NULL && pReplySize != NULL) {
+ reply.read(pReplyData, size);
+ *pReplySize = size;
+ }
+ return status;
+ }
+
+ void disconnect()
+ {
+ ALOGV("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: {
+ ALOGV("ENABLE");
+ CHECK_INTERFACE(IEffect, data, reply);
+ reply->writeInt32(enable());
+ return NO_ERROR;
+ } break;
+
+ case DISABLE: {
+ ALOGV("DISABLE");
+ CHECK_INTERFACE(IEffect, data, reply);
+ reply->writeInt32(disable());
+ return NO_ERROR;
+ } break;
+
+ case COMMAND: {
+ ALOGV("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: {
+ ALOGV("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..aef4371
--- /dev/null
+++ b/media/libmedia/IEffectClient.cpp
@@ -0,0 +1,144 @@
+/*
+**
+** 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)
+ {
+ ALOGV("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)
+ {
+ ALOGV("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)
+ {
+ ALOGV("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: {
+ ALOGV("CONTROL_STATUS_CHANGED");
+ CHECK_INTERFACE(IEffectClient, data, reply);
+ bool hasControl = (bool)data.readInt32();
+ controlStatusChanged(hasControl);
+ return NO_ERROR;
+ } break;
+ case ENABLE_STATUS_CHANGED: {
+ ALOGV("ENABLE_STATUS_CHANGED");
+ CHECK_INTERFACE(IEffectClient, data, reply);
+ bool enabled = (bool)data.readInt32();
+ enableStatusChanged(enabled);
+ return NO_ERROR;
+ } break;
+ case COMMAND_EXECUTED: {
+ ALOGV("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/IMediaDeathNotifier.cpp b/media/libmedia/IMediaDeathNotifier.cpp
new file mode 100644
index 0000000..9199db6
--- /dev/null
+++ b/media/libmedia/IMediaDeathNotifier.cpp
@@ -0,0 +1,111 @@
+/*
+** 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 "IMediaDeathNotifier"
+#include <utils/Log.h>
+
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <media/IMediaDeathNotifier.h>
+
+namespace android {
+
+// client singleton for binder interface to services
+Mutex IMediaDeathNotifier::sServiceLock;
+sp<IMediaPlayerService> IMediaDeathNotifier::sMediaPlayerService;
+sp<IMediaDeathNotifier::DeathNotifier> IMediaDeathNotifier::sDeathNotifier;
+SortedVector< wp<IMediaDeathNotifier> > IMediaDeathNotifier::sObitRecipients;
+
+// establish binder interface to MediaPlayerService
+/*static*/const sp<IMediaPlayerService>&
+IMediaDeathNotifier::getMediaPlayerService()
+{
+ ALOGV("getMediaPlayerService");
+ Mutex::Autolock _l(sServiceLock);
+ if (sMediaPlayerService == 0) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder;
+ do {
+ binder = sm->getService(String16("media.player"));
+ if (binder != 0) {
+ break;
+ }
+ ALOGW("Media player service not published, waiting...");
+ usleep(500000); // 0.5 s
+ } while (true);
+
+ if (sDeathNotifier == NULL) {
+ sDeathNotifier = new DeathNotifier();
+ }
+ binder->linkToDeath(sDeathNotifier);
+ sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
+ }
+ ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
+ return sMediaPlayerService;
+}
+
+/*static*/ void
+IMediaDeathNotifier::addObitRecipient(const wp<IMediaDeathNotifier>& recipient)
+{
+ ALOGV("addObitRecipient");
+ Mutex::Autolock _l(sServiceLock);
+ sObitRecipients.add(recipient);
+}
+
+/*static*/ void
+IMediaDeathNotifier::removeObitRecipient(const wp<IMediaDeathNotifier>& recipient)
+{
+ ALOGV("removeObitRecipient");
+ Mutex::Autolock _l(sServiceLock);
+ sObitRecipients.remove(recipient);
+}
+
+void
+IMediaDeathNotifier::DeathNotifier::binderDied(const wp<IBinder>& who) {
+ ALOGW("media server died");
+
+ // Need to do this with the lock held
+ SortedVector< wp<IMediaDeathNotifier> > list;
+ {
+ Mutex::Autolock _l(sServiceLock);
+ sMediaPlayerService.clear();
+ list = sObitRecipients;
+ }
+
+ // Notify application when media server dies.
+ // Don't hold the static lock during callback in case app
+ // makes a call that needs the lock.
+ size_t count = list.size();
+ for (size_t iter = 0; iter < count; ++iter) {
+ sp<IMediaDeathNotifier> notifier = list[iter].promote();
+ if (notifier != 0) {
+ notifier->died();
+ }
+ }
+}
+
+IMediaDeathNotifier::DeathNotifier::~DeathNotifier()
+{
+ ALOGV("DeathNotifier::~DeathNotifier");
+ Mutex::Autolock _l(sServiceLock);
+ sObitRecipients.clear();
+ if (sMediaPlayerService != 0) {
+ sMediaPlayerService->asBinder()->unlinkToDeath(this);
+ }
+}
+
+}; // namespace android
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
new file mode 100644
index 0000000..7e6d54b
--- /dev/null
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -0,0 +1,268 @@
+/*
+**
+** 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.
+*/
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <media/IMediaMetadataRetriever.h>
+#include <utils/String8.h>
+
+// The binder is supposed to propagate the scheduler group across
+// the binder interface so that remote calls are executed with
+// the same priority as local calls. This is currently not working
+// so this change puts in a temporary hack to fix the issue with
+// metadata retrieval which can be a huge CPU hit if done on a
+// foreground thread.
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+
+#undef LOG_TAG
+#define LOG_TAG "IMediaMetadataRetriever"
+#include <utils/Log.h>
+#include <cutils/sched_policy.h>
+
+namespace android {
+
+static void sendSchedPolicy(Parcel& data)
+{
+ SchedPolicy policy;
+ get_sched_policy(gettid(), &policy);
+ data.writeInt32(policy);
+}
+
+static void setSchedPolicy(const Parcel& data)
+{
+ SchedPolicy policy = (SchedPolicy) data.readInt32();
+ set_sched_policy(gettid(), policy);
+}
+static void restoreSchedPolicy()
+{
+ set_sched_policy(gettid(), SP_FOREGROUND);
+}
+}; // end namespace android
+#endif
+
+namespace android {
+
+enum {
+ DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
+ SET_DATA_SOURCE_URL,
+ SET_DATA_SOURCE_FD,
+ GET_FRAME_AT_TIME,
+ EXTRACT_ALBUM_ART,
+ EXTRACT_METADATA,
+};
+
+class BpMediaMetadataRetriever: public BpInterface<IMediaMetadataRetriever>
+{
+public:
+ BpMediaMetadataRetriever(const sp<IBinder>& impl)
+ : BpInterface<IMediaMetadataRetriever>(impl)
+ {
+ }
+
+ // disconnect from media metadata retriever service
+ void disconnect()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+ remote()->transact(DISCONNECT, data, &reply);
+ }
+
+ status_t setDataSource(
+ const char *srcUrl, const KeyedVector<String8, String8> *headers)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+ data.writeCString(srcUrl);
+
+ if (headers == NULL) {
+ data.writeInt32(0);
+ } else {
+ // serialize the headers
+ data.writeInt32(headers->size());
+ for (size_t i = 0; i < headers->size(); ++i) {
+ data.writeString8(headers->keyAt(i));
+ data.writeString8(headers->valueAt(i));
+ }
+ }
+
+ remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setDataSource(int fd, int64_t offset, int64_t length)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+ data.writeFileDescriptor(fd);
+ data.writeInt64(offset);
+ data.writeInt64(length);
+ remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
+ return reply.readInt32();
+ }
+
+ sp<IMemory> getFrameAtTime(int64_t timeUs, int option)
+ {
+ ALOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option);
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+ data.writeInt64(timeUs);
+ data.writeInt32(option);
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+ sendSchedPolicy(data);
+#endif
+ remote()->transact(GET_FRAME_AT_TIME, data, &reply);
+ status_t ret = reply.readInt32();
+ if (ret != NO_ERROR) {
+ return NULL;
+ }
+ return interface_cast<IMemory>(reply.readStrongBinder());
+ }
+
+ sp<IMemory> extractAlbumArt()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+ sendSchedPolicy(data);
+#endif
+ remote()->transact(EXTRACT_ALBUM_ART, data, &reply);
+ status_t ret = reply.readInt32();
+ if (ret != NO_ERROR) {
+ return NULL;
+ }
+ return interface_cast<IMemory>(reply.readStrongBinder());
+ }
+
+ const char* extractMetadata(int keyCode)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+ sendSchedPolicy(data);
+#endif
+ data.writeInt32(keyCode);
+ remote()->transact(EXTRACT_METADATA, data, &reply);
+ status_t ret = reply.readInt32();
+ if (ret != NO_ERROR) {
+ return NULL;
+ }
+ return reply.readCString();
+ }
+};
+
+IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.media.IMediaMetadataRetriever");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaMetadataRetriever::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case DISCONNECT: {
+ CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+ disconnect();
+ return NO_ERROR;
+ } break;
+ case SET_DATA_SOURCE_URL: {
+ CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+ const char* srcUrl = data.readCString();
+
+ KeyedVector<String8, String8> headers;
+ int32_t numHeaders = data.readInt32();
+ for (int i = 0; i < numHeaders; ++i) {
+ String8 key = data.readString8();
+ String8 value = data.readString8();
+ headers.add(key, value);
+ }
+
+ reply->writeInt32(
+ setDataSource(srcUrl, numHeaders > 0 ? &headers : NULL));
+
+ return NO_ERROR;
+ } break;
+ case SET_DATA_SOURCE_FD: {
+ CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+ int fd = dup(data.readFileDescriptor());
+ int64_t offset = data.readInt64();
+ int64_t length = data.readInt64();
+ reply->writeInt32(setDataSource(fd, offset, length));
+ return NO_ERROR;
+ } break;
+ case GET_FRAME_AT_TIME: {
+ CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+ int64_t timeUs = data.readInt64();
+ int option = data.readInt32();
+ ALOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option);
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+ setSchedPolicy(data);
+#endif
+ sp<IMemory> bitmap = getFrameAtTime(timeUs, option);
+ if (bitmap != 0) { // Don't send NULL across the binder interface
+ reply->writeInt32(NO_ERROR);
+ reply->writeStrongBinder(bitmap->asBinder());
+ } else {
+ reply->writeInt32(UNKNOWN_ERROR);
+ }
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+ restoreSchedPolicy();
+#endif
+ return NO_ERROR;
+ } break;
+ case EXTRACT_ALBUM_ART: {
+ CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+ setSchedPolicy(data);
+#endif
+ sp<IMemory> albumArt = extractAlbumArt();
+ if (albumArt != 0) { // Don't send NULL across the binder interface
+ reply->writeInt32(NO_ERROR);
+ reply->writeStrongBinder(albumArt->asBinder());
+ } else {
+ reply->writeInt32(UNKNOWN_ERROR);
+ }
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+ restoreSchedPolicy();
+#endif
+ return NO_ERROR;
+ } break;
+ case EXTRACT_METADATA: {
+ CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+ setSchedPolicy(data);
+#endif
+ int keyCode = data.readInt32();
+ const char* value = extractMetadata(keyCode);
+ if (value != NULL) { // Don't send NULL across the binder interface
+ reply->writeInt32(NO_ERROR);
+ reply->writeCString(value);
+ } else {
+ reply->writeInt32(UNKNOWN_ERROR);
+ }
+#ifndef DISABLE_GROUP_SCHEDULE_HACK
+ restoreSchedPolicy();
+#endif
+ 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
new file mode 100644
index 0000000..0bb237d
--- /dev/null
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -0,0 +1,515 @@
+/*
+**
+** 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 <arpa/inet.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+
+#include <media/IMediaPlayer.h>
+#include <media/IStreamSource.h>
+
+#include <gui/ISurfaceTexture.h>
+#include <utils/String8.h>
+
+namespace android {
+
+enum {
+ DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
+ SET_DATA_SOURCE_URL,
+ SET_DATA_SOURCE_FD,
+ SET_DATA_SOURCE_STREAM,
+ PREPARE_ASYNC,
+ START,
+ STOP,
+ IS_PLAYING,
+ PAUSE,
+ SEEK_TO,
+ GET_CURRENT_POSITION,
+ GET_DURATION,
+ RESET,
+ SET_AUDIO_STREAM_TYPE,
+ SET_LOOPING,
+ SET_VOLUME,
+ INVOKE,
+ SET_METADATA_FILTER,
+ GET_METADATA,
+ SET_AUX_EFFECT_SEND_LEVEL,
+ ATTACH_AUX_EFFECT,
+ SET_VIDEO_SURFACETEXTURE,
+ SET_PARAMETER,
+ GET_PARAMETER,
+ SET_RETRANSMIT_ENDPOINT,
+ SET_NEXT_PLAYER,
+};
+
+class BpMediaPlayer: public BpInterface<IMediaPlayer>
+{
+public:
+ BpMediaPlayer(const sp<IBinder>& impl)
+ : BpInterface<IMediaPlayer>(impl)
+ {
+ }
+
+ // disconnect from media player service
+ void disconnect()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ remote()->transact(DISCONNECT, data, &reply);
+ }
+
+ status_t setDataSource(const char* url,
+ const KeyedVector<String8, String8>* headers)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeCString(url);
+ if (headers == NULL) {
+ data.writeInt32(0);
+ } else {
+ // serialize the headers
+ data.writeInt32(headers->size());
+ for (size_t i = 0; i < headers->size(); ++i) {
+ data.writeString8(headers->keyAt(i));
+ data.writeString8(headers->valueAt(i));
+ }
+ }
+ remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setDataSource(int fd, int64_t offset, int64_t length) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeFileDescriptor(fd);
+ data.writeInt64(offset);
+ data.writeInt64(length);
+ remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setDataSource(const sp<IStreamSource> &source) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeStrongBinder(source->asBinder());
+ remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply);
+ return reply.readInt32();
+ }
+
+ // pass the buffered ISurfaceTexture to the media player service
+ status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ sp<IBinder> b(surfaceTexture->asBinder());
+ data.writeStrongBinder(b);
+ remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t prepareAsync()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ remote()->transact(PREPARE_ASYNC, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t start()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ remote()->transact(START, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t stop()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ remote()->transact(STOP, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t isPlaying(bool* state)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ remote()->transact(IS_PLAYING, data, &reply);
+ *state = reply.readInt32();
+ return reply.readInt32();
+ }
+
+ status_t pause()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ remote()->transact(PAUSE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t seekTo(int msec)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeInt32(msec);
+ remote()->transact(SEEK_TO, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t getCurrentPosition(int* msec)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ remote()->transact(GET_CURRENT_POSITION, data, &reply);
+ *msec = reply.readInt32();
+ return reply.readInt32();
+ }
+
+ status_t getDuration(int* msec)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ remote()->transact(GET_DURATION, data, &reply);
+ *msec = reply.readInt32();
+ return reply.readInt32();
+ }
+
+ status_t reset()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ remote()->transact(RESET, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setAudioStreamType(audio_stream_type_t stream)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeInt32((int32_t) stream);
+ remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setLooping(int loop)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeInt32(loop);
+ remote()->transact(SET_LOOPING, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setVolume(float leftVolume, float rightVolume)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeFloat(leftVolume);
+ data.writeFloat(rightVolume);
+ remote()->transact(SET_VOLUME, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t invoke(const Parcel& request, Parcel *reply)
+ {
+ // Avoid doing any extra copy. The interface descriptor should
+ // have been set by MediaPlayer.java.
+ return remote()->transact(INVOKE, request, reply);
+ }
+
+ status_t setMetadataFilter(const Parcel& request)
+ {
+ Parcel reply;
+ // Avoid doing any extra copy of the request. The interface
+ // descriptor should have been set by MediaPlayer.java.
+ remote()->transact(SET_METADATA_FILTER, request, &reply);
+ return reply.readInt32();
+ }
+
+ status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply)
+ {
+ Parcel request;
+ request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here.
+ request.writeInt32(update_only);
+ request.writeInt32(apply_filter);
+ remote()->transact(GET_METADATA, request, reply);
+ 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();
+ }
+
+ status_t setParameter(int key, const Parcel& request)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeInt32(key);
+ if (request.dataSize() > 0) {
+ data.appendFrom(const_cast<Parcel *>(&request), 0, request.dataSize());
+ }
+ remote()->transact(SET_PARAMETER, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t getParameter(int key, Parcel *reply)
+ {
+ Parcel data;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeInt32(key);
+ return remote()->transact(GET_PARAMETER, data, reply);
+ }
+
+ status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) {
+ Parcel data, reply;
+ status_t err;
+
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ if (NULL != endpoint) {
+ data.writeInt32(sizeof(*endpoint));
+ data.write(endpoint, sizeof(*endpoint));
+ } else {
+ data.writeInt32(0);
+ }
+
+ err = remote()->transact(SET_RETRANSMIT_ENDPOINT, data, &reply);
+ if (OK != err) {
+ return err;
+ }
+ return reply.readInt32();
+ }
+
+ status_t setNextPlayer(const sp<IMediaPlayer>& player) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ sp<IBinder> b(player->asBinder());
+ data.writeStrongBinder(b);
+ remote()->transact(SET_NEXT_PLAYER, data, &reply);
+ return reply.readInt32();
+ }
+};
+
+IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaPlayer::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case DISCONNECT: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ disconnect();
+ return NO_ERROR;
+ } break;
+ case SET_DATA_SOURCE_URL: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ const char* url = data.readCString();
+ KeyedVector<String8, String8> headers;
+ int32_t numHeaders = data.readInt32();
+ for (int i = 0; i < numHeaders; ++i) {
+ String8 key = data.readString8();
+ String8 value = data.readString8();
+ headers.add(key, value);
+ }
+ reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers : NULL));
+ return NO_ERROR;
+ } break;
+ case SET_DATA_SOURCE_FD: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ int fd = data.readFileDescriptor();
+ int64_t offset = data.readInt64();
+ int64_t length = data.readInt64();
+ reply->writeInt32(setDataSource(fd, offset, length));
+ return NO_ERROR;
+ }
+ case SET_DATA_SOURCE_STREAM: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ sp<IStreamSource> source =
+ interface_cast<IStreamSource>(data.readStrongBinder());
+ reply->writeInt32(setDataSource(source));
+ return NO_ERROR;
+ }
+ case SET_VIDEO_SURFACETEXTURE: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ sp<ISurfaceTexture> surfaceTexture =
+ interface_cast<ISurfaceTexture>(data.readStrongBinder());
+ reply->writeInt32(setVideoSurfaceTexture(surfaceTexture));
+ return NO_ERROR;
+ } break;
+ case PREPARE_ASYNC: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(prepareAsync());
+ return NO_ERROR;
+ } break;
+ case START: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(start());
+ return NO_ERROR;
+ } break;
+ case STOP: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(stop());
+ return NO_ERROR;
+ } break;
+ case IS_PLAYING: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ bool state;
+ status_t ret = isPlaying(&state);
+ reply->writeInt32(state);
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case PAUSE: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(pause());
+ return NO_ERROR;
+ } break;
+ case SEEK_TO: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(seekTo(data.readInt32()));
+ return NO_ERROR;
+ } break;
+ case GET_CURRENT_POSITION: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ int msec;
+ status_t ret = getCurrentPosition(&msec);
+ reply->writeInt32(msec);
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case GET_DURATION: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ int msec;
+ status_t ret = getDuration(&msec);
+ reply->writeInt32(msec);
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case RESET: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(reset());
+ return NO_ERROR;
+ } break;
+ case SET_AUDIO_STREAM_TYPE: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(setAudioStreamType((audio_stream_type_t) data.readInt32()));
+ return NO_ERROR;
+ } break;
+ case SET_LOOPING: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(setLooping(data.readInt32()));
+ return NO_ERROR;
+ } break;
+ case SET_VOLUME: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ float leftVolume = data.readFloat();
+ float rightVolume = data.readFloat();
+ reply->writeInt32(setVolume(leftVolume, rightVolume));
+ return NO_ERROR;
+ } break;
+ case INVOKE: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ status_t result = invoke(data, reply);
+ return result;
+ } break;
+ case SET_METADATA_FILTER: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(setMetadataFilter(data));
+ return NO_ERROR;
+ } break;
+ case GET_METADATA: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ bool update_only = static_cast<bool>(data.readInt32());
+ bool apply_filter = static_cast<bool>(data.readInt32());
+ const status_t retcode = getMetadata(update_only, apply_filter, reply);
+ reply->setDataPosition(0);
+ reply->writeInt32(retcode);
+ 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;
+ case SET_PARAMETER: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ int key = data.readInt32();
+
+ Parcel request;
+ if (data.dataAvail() > 0) {
+ request.appendFrom(
+ const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
+ }
+ request.setDataPosition(0);
+ reply->writeInt32(setParameter(key, request));
+ return NO_ERROR;
+ } break;
+ case GET_PARAMETER: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ return getParameter(data.readInt32(), reply);
+ } break;
+ case SET_RETRANSMIT_ENDPOINT: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+
+ struct sockaddr_in endpoint;
+ int amt = data.readInt32();
+ if (amt == sizeof(endpoint)) {
+ data.read(&endpoint, sizeof(struct sockaddr_in));
+ reply->writeInt32(setRetransmitEndpoint(&endpoint));
+ } else {
+ reply->writeInt32(setRetransmitEndpoint(NULL));
+ }
+ return NO_ERROR;
+ } break;
+ case SET_NEXT_PLAYER: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(setNextPlayer(interface_cast<IMediaPlayer>(data.readStrongBinder())));
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/IMediaPlayerClient.cpp b/media/libmedia/IMediaPlayerClient.cpp
new file mode 100644
index 0000000..a670c96
--- /dev/null
+++ b/media/libmedia/IMediaPlayerClient.cpp
@@ -0,0 +1,78 @@
+/*
+**
+** 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 <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+#include <media/IMediaPlayerClient.h>
+
+namespace android {
+
+enum {
+ NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpMediaPlayerClient: public BpInterface<IMediaPlayerClient>
+{
+public:
+ BpMediaPlayerClient(const sp<IBinder>& impl)
+ : BpInterface<IMediaPlayerClient>(impl)
+ {
+ }
+
+ virtual void notify(int msg, int ext1, int ext2, const Parcel *obj)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayerClient::getInterfaceDescriptor());
+ data.writeInt32(msg);
+ data.writeInt32(ext1);
+ data.writeInt32(ext2);
+ if (obj && obj->dataSize() > 0) {
+ data.appendFrom(const_cast<Parcel *>(obj), 0, obj->dataSize());
+ }
+ remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(MediaPlayerClient, "android.media.IMediaPlayerClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaPlayerClient::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case NOTIFY: {
+ CHECK_INTERFACE(IMediaPlayerClient, data, reply);
+ int msg = data.readInt32();
+ int ext1 = data.readInt32();
+ int ext2 = data.readInt32();
+ Parcel obj;
+ if (data.dataAvail() > 0) {
+ obj.appendFrom(const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail());
+ }
+
+ notify(msg, ext1, ext2, &obj);
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+}; // namespace android
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
new file mode 100644
index 0000000..9120617
--- /dev/null
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -0,0 +1,227 @@
+/*
+**
+** 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 <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+#include <media/ICrypto.h>
+#include <media/IMediaPlayerService.h>
+#include <media/IMediaRecorder.h>
+#include <media/IOMX.h>
+#include <media/IStreamSource.h>
+
+#include <utils/Errors.h> // for status_t
+
+namespace android {
+
+enum {
+ CREATE = IBinder::FIRST_CALL_TRANSACTION,
+ DECODE_URL,
+ DECODE_FD,
+ CREATE_MEDIA_RECORDER,
+ CREATE_METADATA_RETRIEVER,
+ GET_OMX,
+ MAKE_CRYPTO,
+ ADD_BATTERY_DATA,
+ PULL_BATTERY_DATA
+};
+
+class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
+{
+public:
+ BpMediaPlayerService(const sp<IBinder>& impl)
+ : BpInterface<IMediaPlayerService>(impl)
+ {
+ }
+
+ virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+ data.writeInt32(pid);
+ remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply);
+ return interface_cast<IMediaMetadataRetriever>(reply.readStrongBinder());
+ }
+
+ virtual sp<IMediaPlayer> create(
+ pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+ data.writeInt32(pid);
+ data.writeStrongBinder(client->asBinder());
+ data.writeInt32(audioSessionId);
+
+ remote()->transact(CREATE, data, &reply);
+ return interface_cast<IMediaPlayer>(reply.readStrongBinder());
+ }
+
+ virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+ data.writeInt32(pid);
+ remote()->transact(CREATE_MEDIA_RECORDER, data, &reply);
+ return interface_cast<IMediaRecorder>(reply.readStrongBinder());
+ }
+
+ virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+ data.writeCString(url);
+ remote()->transact(DECODE_URL, data, &reply);
+ *pSampleRate = uint32_t(reply.readInt32());
+ *pNumChannels = reply.readInt32();
+ *pFormat = (audio_format_t) reply.readInt32();
+ return interface_cast<IMemory>(reply.readStrongBinder());
+ }
+
+ virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+ data.writeFileDescriptor(fd);
+ data.writeInt64(offset);
+ data.writeInt64(length);
+ remote()->transact(DECODE_FD, data, &reply);
+ *pSampleRate = uint32_t(reply.readInt32());
+ *pNumChannels = reply.readInt32();
+ *pFormat = (audio_format_t) reply.readInt32();
+ return interface_cast<IMemory>(reply.readStrongBinder());
+ }
+
+ virtual sp<IOMX> getOMX() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+ remote()->transact(GET_OMX, data, &reply);
+ return interface_cast<IOMX>(reply.readStrongBinder());
+ }
+
+ virtual sp<ICrypto> makeCrypto() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+ remote()->transact(MAKE_CRYPTO, data, &reply);
+ return interface_cast<ICrypto>(reply.readStrongBinder());
+ }
+
+ virtual void addBatteryData(uint32_t params) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+ data.writeInt32(params);
+ remote()->transact(ADD_BATTERY_DATA, data, &reply);
+ }
+
+ virtual status_t pullBatteryData(Parcel* reply) {
+ Parcel data;
+ data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+ return remote()->transact(PULL_BATTERY_DATA, data, reply);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaPlayerService::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case CREATE: {
+ CHECK_INTERFACE(IMediaPlayerService, data, reply);
+ pid_t pid = data.readInt32();
+ sp<IMediaPlayerClient> client =
+ interface_cast<IMediaPlayerClient>(data.readStrongBinder());
+ int audioSessionId = data.readInt32();
+ sp<IMediaPlayer> player = create(pid, client, audioSessionId);
+ reply->writeStrongBinder(player->asBinder());
+ return NO_ERROR;
+ } break;
+ case DECODE_URL: {
+ CHECK_INTERFACE(IMediaPlayerService, data, reply);
+ const char* url = data.readCString();
+ uint32_t sampleRate;
+ int numChannels;
+ audio_format_t format;
+ sp<IMemory> player = decode(url, &sampleRate, &numChannels, &format);
+ reply->writeInt32(sampleRate);
+ reply->writeInt32(numChannels);
+ reply->writeInt32((int32_t) format);
+ reply->writeStrongBinder(player->asBinder());
+ return NO_ERROR;
+ } break;
+ case DECODE_FD: {
+ CHECK_INTERFACE(IMediaPlayerService, data, reply);
+ int fd = dup(data.readFileDescriptor());
+ int64_t offset = data.readInt64();
+ int64_t length = data.readInt64();
+ uint32_t sampleRate;
+ int numChannels;
+ audio_format_t format;
+ sp<IMemory> player = decode(fd, offset, length, &sampleRate, &numChannels, &format);
+ reply->writeInt32(sampleRate);
+ reply->writeInt32(numChannels);
+ reply->writeInt32((int32_t) format);
+ reply->writeStrongBinder(player->asBinder());
+ return NO_ERROR;
+ } break;
+ case CREATE_MEDIA_RECORDER: {
+ CHECK_INTERFACE(IMediaPlayerService, data, reply);
+ pid_t pid = data.readInt32();
+ sp<IMediaRecorder> recorder = createMediaRecorder(pid);
+ reply->writeStrongBinder(recorder->asBinder());
+ return NO_ERROR;
+ } break;
+ case CREATE_METADATA_RETRIEVER: {
+ CHECK_INTERFACE(IMediaPlayerService, data, reply);
+ pid_t pid = data.readInt32();
+ sp<IMediaMetadataRetriever> retriever = createMetadataRetriever(pid);
+ reply->writeStrongBinder(retriever->asBinder());
+ return NO_ERROR;
+ } break;
+ case GET_OMX: {
+ CHECK_INTERFACE(IMediaPlayerService, data, reply);
+ sp<IOMX> omx = getOMX();
+ reply->writeStrongBinder(omx->asBinder());
+ return NO_ERROR;
+ } break;
+ case MAKE_CRYPTO: {
+ CHECK_INTERFACE(IMediaPlayerService, data, reply);
+ sp<ICrypto> crypto = makeCrypto();
+ reply->writeStrongBinder(crypto->asBinder());
+ return NO_ERROR;
+ } break;
+ case ADD_BATTERY_DATA: {
+ CHECK_INTERFACE(IMediaPlayerService, data, reply);
+ uint32_t params = data.readInt32();
+ addBatteryData(params);
+ return NO_ERROR;
+ } break;
+ case PULL_BATTERY_DATA: {
+ CHECK_INTERFACE(IMediaPlayerService, data, reply);
+ pullBatteryData(reply);
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
new file mode 100644
index 0000000..a710fd7
--- /dev/null
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -0,0 +1,463 @@
+/*
+ **
+ ** 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "IMediaRecorder"
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include <camera/ICamera.h>
+#include <media/IMediaRecorderClient.h>
+#include <media/IMediaRecorder.h>
+#include <gui/Surface.h>
+#include <gui/ISurfaceTexture.h>
+#include <unistd.h>
+
+
+namespace android {
+
+enum {
+ RELEASE = IBinder::FIRST_CALL_TRANSACTION,
+ INIT,
+ CLOSE,
+ QUERY_SURFACE_MEDIASOURCE,
+ RESET,
+ STOP,
+ START,
+ PREPARE,
+ GET_MAX_AMPLITUDE,
+ SET_VIDEO_SOURCE,
+ SET_AUDIO_SOURCE,
+ SET_OUTPUT_FORMAT,
+ SET_VIDEO_ENCODER,
+ SET_AUDIO_ENCODER,
+ SET_OUTPUT_FILE_PATH,
+ SET_OUTPUT_FILE_FD,
+ SET_VIDEO_SIZE,
+ SET_VIDEO_FRAMERATE,
+ SET_PARAMETERS,
+ SET_PREVIEW_SURFACE,
+ SET_CAMERA,
+ SET_LISTENER
+};
+
+class BpMediaRecorder: public BpInterface<IMediaRecorder>
+{
+public:
+ BpMediaRecorder(const sp<IBinder>& impl)
+ : BpInterface<IMediaRecorder>(impl)
+ {
+ }
+
+ status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy)
+ {
+ ALOGV("setCamera(%p,%p)", camera.get(), proxy.get());
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeStrongBinder(camera->asBinder());
+ data.writeStrongBinder(proxy->asBinder());
+ remote()->transact(SET_CAMERA, data, &reply);
+ return reply.readInt32();
+ }
+
+ sp<ISurfaceTexture> querySurfaceMediaSource()
+ {
+ ALOGV("Query SurfaceMediaSource");
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ remote()->transact(QUERY_SURFACE_MEDIASOURCE, data, &reply);
+ int returnedNull = reply.readInt32();
+ if (returnedNull) {
+ return NULL;
+ }
+ return interface_cast<ISurfaceTexture>(reply.readStrongBinder());
+ }
+
+ status_t setPreviewSurface(const sp<Surface>& surface)
+ {
+ ALOGV("setPreviewSurface(%p)", surface.get());
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ Surface::writeToParcel(surface, &data);
+ remote()->transact(SET_PREVIEW_SURFACE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t init()
+ {
+ ALOGV("init");
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ remote()->transact(INIT, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setVideoSource(int vs)
+ {
+ ALOGV("setVideoSource(%d)", vs);
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeInt32(vs);
+ remote()->transact(SET_VIDEO_SOURCE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setAudioSource(int as)
+ {
+ ALOGV("setAudioSource(%d)", as);
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeInt32(as);
+ remote()->transact(SET_AUDIO_SOURCE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setOutputFormat(int of)
+ {
+ ALOGV("setOutputFormat(%d)", of);
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeInt32(of);
+ remote()->transact(SET_OUTPUT_FORMAT, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setVideoEncoder(int ve)
+ {
+ ALOGV("setVideoEncoder(%d)", ve);
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeInt32(ve);
+ remote()->transact(SET_VIDEO_ENCODER, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setAudioEncoder(int ae)
+ {
+ ALOGV("setAudioEncoder(%d)", ae);
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeInt32(ae);
+ remote()->transact(SET_AUDIO_ENCODER, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setOutputFile(const char* path)
+ {
+ ALOGV("setOutputFile(%s)", path);
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeCString(path);
+ remote()->transact(SET_OUTPUT_FILE_PATH, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setOutputFile(int fd, int64_t offset, int64_t length) {
+ ALOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeFileDescriptor(fd);
+ data.writeInt64(offset);
+ data.writeInt64(length);
+ remote()->transact(SET_OUTPUT_FILE_FD, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setVideoSize(int width, int height)
+ {
+ ALOGV("setVideoSize(%dx%d)", width, height);
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeInt32(width);
+ data.writeInt32(height);
+ remote()->transact(SET_VIDEO_SIZE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setVideoFrameRate(int frames_per_second)
+ {
+ ALOGV("setVideoFrameRate(%d)", frames_per_second);
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeInt32(frames_per_second);
+ remote()->transact(SET_VIDEO_FRAMERATE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setParameters(const String8& params)
+ {
+ ALOGV("setParameter(%s)", params.string());
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeString8(params);
+ remote()->transact(SET_PARAMETERS, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t setListener(const sp<IMediaRecorderClient>& listener)
+ {
+ ALOGV("setListener(%p)", listener.get());
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ data.writeStrongBinder(listener->asBinder());
+ remote()->transact(SET_LISTENER, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t prepare()
+ {
+ ALOGV("prepare");
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ remote()->transact(PREPARE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t getMaxAmplitude(int* max)
+ {
+ ALOGV("getMaxAmplitude");
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ remote()->transact(GET_MAX_AMPLITUDE, data, &reply);
+ *max = reply.readInt32();
+ return reply.readInt32();
+ }
+
+ status_t start()
+ {
+ ALOGV("start");
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ remote()->transact(START, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t stop()
+ {
+ ALOGV("stop");
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ remote()->transact(STOP, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t reset()
+ {
+ ALOGV("reset");
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ remote()->transact(RESET, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t close()
+ {
+ ALOGV("close");
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ remote()->transact(CLOSE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t release()
+ {
+ ALOGV("release");
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+ remote()->transact(RELEASE, data, &reply);
+ return reply.readInt32();
+ }
+};
+
+IMPLEMENT_META_INTERFACE(MediaRecorder, "android.media.IMediaRecorder");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaRecorder::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case RELEASE: {
+ ALOGV("RELEASE");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ reply->writeInt32(release());
+ return NO_ERROR;
+ } break;
+ case INIT: {
+ ALOGV("INIT");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ reply->writeInt32(init());
+ return NO_ERROR;
+ } break;
+ case CLOSE: {
+ ALOGV("CLOSE");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ reply->writeInt32(close());
+ return NO_ERROR;
+ } break;
+ case RESET: {
+ ALOGV("RESET");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ reply->writeInt32(reset());
+ return NO_ERROR;
+ } break;
+ case STOP: {
+ ALOGV("STOP");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ reply->writeInt32(stop());
+ return NO_ERROR;
+ } break;
+ case START: {
+ ALOGV("START");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ reply->writeInt32(start());
+ return NO_ERROR;
+ } break;
+ case PREPARE: {
+ ALOGV("PREPARE");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ reply->writeInt32(prepare());
+ return NO_ERROR;
+ } break;
+ case GET_MAX_AMPLITUDE: {
+ ALOGV("GET_MAX_AMPLITUDE");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ int max = 0;
+ status_t ret = getMaxAmplitude(&max);
+ reply->writeInt32(max);
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ } break;
+ case SET_VIDEO_SOURCE: {
+ ALOGV("SET_VIDEO_SOURCE");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ int vs = data.readInt32();
+ reply->writeInt32(setVideoSource(vs));
+ return NO_ERROR;
+ } break;
+ case SET_AUDIO_SOURCE: {
+ ALOGV("SET_AUDIO_SOURCE");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ int as = data.readInt32();
+ reply->writeInt32(setAudioSource(as));
+ return NO_ERROR;
+ } break;
+ case SET_OUTPUT_FORMAT: {
+ ALOGV("SET_OUTPUT_FORMAT");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ int of = data.readInt32();
+ reply->writeInt32(setOutputFormat(of));
+ return NO_ERROR;
+ } break;
+ case SET_VIDEO_ENCODER: {
+ ALOGV("SET_VIDEO_ENCODER");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ int ve = data.readInt32();
+ reply->writeInt32(setVideoEncoder(ve));
+ return NO_ERROR;
+ } break;
+ case SET_AUDIO_ENCODER: {
+ ALOGV("SET_AUDIO_ENCODER");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ int ae = data.readInt32();
+ reply->writeInt32(setAudioEncoder(ae));
+ return NO_ERROR;
+
+ } break;
+ case SET_OUTPUT_FILE_PATH: {
+ ALOGV("SET_OUTPUT_FILE_PATH");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ const char* path = data.readCString();
+ reply->writeInt32(setOutputFile(path));
+ return NO_ERROR;
+ } break;
+ case SET_OUTPUT_FILE_FD: {
+ ALOGV("SET_OUTPUT_FILE_FD");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ int fd = dup(data.readFileDescriptor());
+ int64_t offset = data.readInt64();
+ int64_t length = data.readInt64();
+ reply->writeInt32(setOutputFile(fd, offset, length));
+ ::close(fd);
+ return NO_ERROR;
+ } break;
+ case SET_VIDEO_SIZE: {
+ ALOGV("SET_VIDEO_SIZE");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ int width = data.readInt32();
+ int height = data.readInt32();
+ reply->writeInt32(setVideoSize(width, height));
+ return NO_ERROR;
+ } break;
+ case SET_VIDEO_FRAMERATE: {
+ ALOGV("SET_VIDEO_FRAMERATE");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ int frames_per_second = data.readInt32();
+ reply->writeInt32(setVideoFrameRate(frames_per_second));
+ return NO_ERROR;
+ } break;
+ case SET_PARAMETERS: {
+ ALOGV("SET_PARAMETER");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ reply->writeInt32(setParameters(data.readString8()));
+ return NO_ERROR;
+ } break;
+ case SET_LISTENER: {
+ ALOGV("SET_LISTENER");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ sp<IMediaRecorderClient> listener =
+ interface_cast<IMediaRecorderClient>(data.readStrongBinder());
+ reply->writeInt32(setListener(listener));
+ return NO_ERROR;
+ } break;
+ case SET_PREVIEW_SURFACE: {
+ ALOGV("SET_PREVIEW_SURFACE");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ sp<Surface> surface = Surface::readFromParcel(data);
+ reply->writeInt32(setPreviewSurface(surface));
+ return NO_ERROR;
+ } break;
+ case SET_CAMERA: {
+ ALOGV("SET_CAMERA");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ sp<ICamera> camera = interface_cast<ICamera>(data.readStrongBinder());
+ sp<ICameraRecordingProxy> proxy =
+ interface_cast<ICameraRecordingProxy>(data.readStrongBinder());
+ reply->writeInt32(setCamera(camera, proxy));
+ return NO_ERROR;
+ } break;
+ case QUERY_SURFACE_MEDIASOURCE: {
+ ALOGV("QUERY_SURFACE_MEDIASOURCE");
+ CHECK_INTERFACE(IMediaRecorder, data, reply);
+ // call the mediaserver side to create
+ // a surfacemediasource
+ sp<ISurfaceTexture> surfaceMediaSource = querySurfaceMediaSource();
+ // The mediaserver might have failed to create a source
+ int returnedNull= (surfaceMediaSource == NULL) ? 1 : 0 ;
+ reply->writeInt32(returnedNull);
+ if (!returnedNull) {
+ reply->writeStrongBinder(surfaceMediaSource->asBinder());
+ }
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/media/libmedia/IMediaRecorderClient.cpp b/media/libmedia/IMediaRecorderClient.cpp
new file mode 100644
index 0000000..e7907e3
--- /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
new file mode 100644
index 0000000..48e427a
--- /dev/null
+++ b/media/libmedia/IOMX.cpp
@@ -0,0 +1,788 @@
+/*
+ * 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 "IOMX"
+#include <utils/Log.h>
+
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+#include <media/IOMX.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+enum {
+ CONNECT = IBinder::FIRST_CALL_TRANSACTION,
+ LIVES_LOCALLY,
+ LIST_NODES,
+ ALLOCATE_NODE,
+ FREE_NODE,
+ SEND_COMMAND,
+ GET_PARAMETER,
+ SET_PARAMETER,
+ GET_CONFIG,
+ SET_CONFIG,
+ GET_STATE,
+ ENABLE_GRAPHIC_BUFFERS,
+ USE_BUFFER,
+ USE_GRAPHIC_BUFFER,
+ STORE_META_DATA_IN_BUFFERS,
+ ALLOC_BUFFER,
+ ALLOC_BUFFER_WITH_BACKUP,
+ FREE_BUFFER,
+ FILL_BUFFER,
+ EMPTY_BUFFER,
+ GET_EXTENSION_INDEX,
+ OBSERVER_ON_MSG,
+ GET_GRAPHIC_BUFFER_USAGE,
+};
+
+class BpOMX : public BpInterface<IOMX> {
+public:
+ BpOMX(const sp<IBinder> &impl)
+ : BpInterface<IOMX>(impl) {
+ }
+
+ virtual bool livesLocally(node_id node, pid_t pid) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(pid);
+ remote()->transact(LIVES_LOCALLY, data, &reply);
+
+ return reply.readInt32() != 0;
+ }
+
+ virtual status_t listNodes(List<ComponentInfo> *list) {
+ list->clear();
+
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ remote()->transact(LIST_NODES, data, &reply);
+
+ int32_t n = reply.readInt32();
+ for (int32_t i = 0; i < n; ++i) {
+ list->push_back(ComponentInfo());
+ ComponentInfo &info = *--list->end();
+
+ info.mName = reply.readString8();
+ int32_t numRoles = reply.readInt32();
+ for (int32_t j = 0; j < numRoles; ++j) {
+ info.mRoles.push_back(reply.readString8());
+ }
+ }
+
+ return OK;
+ }
+
+ virtual status_t allocateNode(
+ const char *name, const sp<IOMXObserver> &observer, node_id *node) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeCString(name);
+ data.writeStrongBinder(observer->asBinder());
+ remote()->transact(ALLOCATE_NODE, data, &reply);
+
+ status_t err = reply.readInt32();
+ if (err == OK) {
+ *node = (void*)reply.readIntPtr();
+ } else {
+ *node = 0;
+ }
+
+ return err;
+ }
+
+ virtual status_t freeNode(node_id node) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ remote()->transact(FREE_NODE, data, &reply);
+
+ return reply.readInt32();
+ }
+
+ virtual status_t sendCommand(
+ node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(cmd);
+ data.writeInt32(param);
+ remote()->transact(SEND_COMMAND, data, &reply);
+
+ return reply.readInt32();
+ }
+
+ virtual status_t getParameter(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(index);
+ data.writeInt32(size);
+ data.write(params, size);
+ remote()->transact(GET_PARAMETER, data, &reply);
+
+ status_t err = reply.readInt32();
+ if (err != OK) {
+ return err;
+ }
+
+ reply.read(params, size);
+
+ return OK;
+ }
+
+ virtual status_t setParameter(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(index);
+ data.writeInt32(size);
+ data.write(params, size);
+ remote()->transact(SET_PARAMETER, data, &reply);
+
+ return reply.readInt32();
+ }
+
+ virtual status_t getConfig(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(index);
+ data.writeInt32(size);
+ data.write(params, size);
+ remote()->transact(GET_CONFIG, data, &reply);
+
+ status_t err = reply.readInt32();
+ if (err != OK) {
+ return err;
+ }
+
+ reply.read(params, size);
+
+ return OK;
+ }
+
+ virtual status_t setConfig(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(index);
+ data.writeInt32(size);
+ data.write(params, size);
+ remote()->transact(SET_CONFIG, data, &reply);
+
+ return reply.readInt32();
+ }
+
+ virtual status_t getState(
+ node_id node, OMX_STATETYPE* state) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ remote()->transact(GET_STATE, data, &reply);
+
+ *state = static_cast<OMX_STATETYPE>(reply.readInt32());
+ return reply.readInt32();
+ }
+
+ virtual status_t enableGraphicBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(port_index);
+ data.writeInt32((uint32_t)enable);
+ remote()->transact(ENABLE_GRAPHIC_BUFFERS, data, &reply);
+
+ status_t err = reply.readInt32();
+ return err;
+ }
+
+ virtual status_t getGraphicBufferUsage(
+ node_id node, OMX_U32 port_index, OMX_U32* usage) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(port_index);
+ remote()->transact(GET_GRAPHIC_BUFFER_USAGE, data, &reply);
+
+ status_t err = reply.readInt32();
+ *usage = reply.readInt32();
+ return err;
+ }
+
+ virtual status_t useBuffer(
+ node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+ buffer_id *buffer) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(port_index);
+ data.writeStrongBinder(params->asBinder());
+ remote()->transact(USE_BUFFER, data, &reply);
+
+ status_t err = reply.readInt32();
+ if (err != OK) {
+ *buffer = 0;
+
+ return err;
+ }
+
+ *buffer = (void*)reply.readIntPtr();
+
+ return err;
+ }
+
+
+ virtual status_t useGraphicBuffer(
+ node_id node, OMX_U32 port_index,
+ const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(port_index);
+ data.write(*graphicBuffer);
+ remote()->transact(USE_GRAPHIC_BUFFER, data, &reply);
+
+ status_t err = reply.readInt32();
+ if (err != OK) {
+ *buffer = 0;
+
+ return err;
+ }
+
+ *buffer = (void*)reply.readIntPtr();
+
+ return err;
+ }
+
+ virtual status_t storeMetaDataInBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(port_index);
+ data.writeInt32((uint32_t)enable);
+ remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply);
+
+ status_t err = reply.readInt32();
+ return err;
+ }
+
+ virtual status_t allocateBuffer(
+ node_id node, OMX_U32 port_index, size_t size,
+ buffer_id *buffer, void **buffer_data) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(port_index);
+ data.writeInt32(size);
+ remote()->transact(ALLOC_BUFFER, data, &reply);
+
+ status_t err = reply.readInt32();
+ if (err != OK) {
+ *buffer = 0;
+
+ return err;
+ }
+
+ *buffer = (void *)reply.readIntPtr();
+ *buffer_data = (void *)reply.readIntPtr();
+
+ return err;
+ }
+
+ virtual status_t allocateBufferWithBackup(
+ node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+ buffer_id *buffer) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(port_index);
+ data.writeStrongBinder(params->asBinder());
+ remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
+
+ status_t err = reply.readInt32();
+ if (err != OK) {
+ *buffer = 0;
+
+ return err;
+ }
+
+ *buffer = (void*)reply.readIntPtr();
+
+ return err;
+ }
+
+ virtual status_t freeBuffer(
+ node_id node, OMX_U32 port_index, buffer_id buffer) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(port_index);
+ data.writeIntPtr((intptr_t)buffer);
+ remote()->transact(FREE_BUFFER, data, &reply);
+
+ return reply.readInt32();
+ }
+
+ virtual status_t fillBuffer(node_id node, buffer_id buffer) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeIntPtr((intptr_t)buffer);
+ remote()->transact(FILL_BUFFER, data, &reply);
+
+ return reply.readInt32();
+ }
+
+ virtual status_t emptyBuffer(
+ node_id node,
+ buffer_id buffer,
+ OMX_U32 range_offset, OMX_U32 range_length,
+ OMX_U32 flags, OMX_TICKS timestamp) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeIntPtr((intptr_t)buffer);
+ data.writeInt32(range_offset);
+ data.writeInt32(range_length);
+ data.writeInt32(flags);
+ data.writeInt64(timestamp);
+ remote()->transact(EMPTY_BUFFER, data, &reply);
+
+ return reply.readInt32();
+ }
+
+ virtual status_t getExtensionIndex(
+ node_id node,
+ const char *parameter_name,
+ OMX_INDEXTYPE *index) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeCString(parameter_name);
+
+ remote()->transact(GET_EXTENSION_INDEX, data, &reply);
+
+ status_t err = reply.readInt32();
+ if (err == OK) {
+ *index = static_cast<OMX_INDEXTYPE>(reply.readInt32());
+ } else {
+ *index = OMX_IndexComponentStartUnused;
+ }
+
+ return err;
+ }
+};
+
+IMPLEMENT_META_INTERFACE(OMX, "android.hardware.IOMX");
+
+////////////////////////////////////////////////////////////////////////////////
+
+#define CHECK_INTERFACE(interface, data, reply) \
+ do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
+ ALOGW("Call incorrectly routed to " #interface); \
+ return PERMISSION_DENIED; \
+ } } while (0)
+
+status_t BnOMX::onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+ switch (code) {
+ case LIVES_LOCALLY:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+ node_id node = (void *)data.readIntPtr();
+ pid_t pid = (pid_t)data.readInt32();
+ reply->writeInt32(livesLocally(node, pid));
+
+ return OK;
+ }
+
+ case LIST_NODES:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ List<ComponentInfo> list;
+ listNodes(&list);
+
+ reply->writeInt32(list.size());
+ for (List<ComponentInfo>::iterator it = list.begin();
+ it != list.end(); ++it) {
+ ComponentInfo &cur = *it;
+
+ reply->writeString8(cur.mName);
+ reply->writeInt32(cur.mRoles.size());
+ for (List<String8>::iterator role_it = cur.mRoles.begin();
+ role_it != cur.mRoles.end(); ++role_it) {
+ reply->writeString8(*role_it);
+ }
+ }
+
+ return NO_ERROR;
+ }
+
+ case ALLOCATE_NODE:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ const char *name = data.readCString();
+
+ sp<IOMXObserver> observer =
+ interface_cast<IOMXObserver>(data.readStrongBinder());
+
+ node_id node;
+
+ status_t err = allocateNode(name, observer, &node);
+ reply->writeInt32(err);
+ if (err == OK) {
+ reply->writeIntPtr((intptr_t)node);
+ }
+
+ return NO_ERROR;
+ }
+
+ case FREE_NODE:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+
+ reply->writeInt32(freeNode(node));
+
+ return NO_ERROR;
+ }
+
+ case SEND_COMMAND:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+
+ OMX_COMMANDTYPE cmd =
+ static_cast<OMX_COMMANDTYPE>(data.readInt32());
+
+ OMX_S32 param = data.readInt32();
+ reply->writeInt32(sendCommand(node, cmd, param));
+
+ return NO_ERROR;
+ }
+
+ case GET_PARAMETER:
+ case SET_PARAMETER:
+ case GET_CONFIG:
+ case SET_CONFIG:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
+
+ size_t size = data.readInt32();
+
+ void *params = malloc(size);
+ data.read(params, size);
+
+ status_t err;
+ switch (code) {
+ case GET_PARAMETER:
+ err = getParameter(node, index, params, size);
+ break;
+ case SET_PARAMETER:
+ err = setParameter(node, index, params, size);
+ break;
+ case GET_CONFIG:
+ err = getConfig(node, index, params, size);
+ break;
+ case SET_CONFIG:
+ err = setConfig(node, index, params, size);
+ break;
+ default:
+ TRESPASS();
+ }
+
+ reply->writeInt32(err);
+
+ if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) {
+ reply->write(params, size);
+ }
+
+ free(params);
+ params = NULL;
+
+ return NO_ERROR;
+ }
+
+ case GET_STATE:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_STATETYPE state = OMX_StateInvalid;
+
+ status_t err = getState(node, &state);
+ reply->writeInt32(state);
+ reply->writeInt32(err);
+
+ return NO_ERROR;
+ }
+
+ case ENABLE_GRAPHIC_BUFFERS:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_U32 port_index = data.readInt32();
+ OMX_BOOL enable = (OMX_BOOL)data.readInt32();
+
+ status_t err = enableGraphicBuffers(node, port_index, enable);
+ reply->writeInt32(err);
+
+ return NO_ERROR;
+ }
+
+ case GET_GRAPHIC_BUFFER_USAGE:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_U32 port_index = data.readInt32();
+
+ OMX_U32 usage = 0;
+ status_t err = getGraphicBufferUsage(node, port_index, &usage);
+ reply->writeInt32(err);
+ reply->writeInt32(usage);
+
+ return NO_ERROR;
+ }
+
+ case USE_BUFFER:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_U32 port_index = data.readInt32();
+ sp<IMemory> params =
+ interface_cast<IMemory>(data.readStrongBinder());
+
+ buffer_id buffer;
+ status_t err = useBuffer(node, port_index, params, &buffer);
+ reply->writeInt32(err);
+
+ if (err == OK) {
+ reply->writeIntPtr((intptr_t)buffer);
+ }
+
+ return NO_ERROR;
+ }
+
+ case USE_GRAPHIC_BUFFER:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_U32 port_index = data.readInt32();
+ sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
+ data.read(*graphicBuffer);
+
+ buffer_id buffer;
+ status_t err = useGraphicBuffer(
+ node, port_index, graphicBuffer, &buffer);
+ reply->writeInt32(err);
+
+ if (err == OK) {
+ reply->writeIntPtr((intptr_t)buffer);
+ }
+
+ return NO_ERROR;
+ }
+
+ case STORE_META_DATA_IN_BUFFERS:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_U32 port_index = data.readInt32();
+ OMX_BOOL enable = (OMX_BOOL)data.readInt32();
+
+ status_t err = storeMetaDataInBuffers(node, port_index, enable);
+ reply->writeInt32(err);
+
+ return NO_ERROR;
+ }
+
+ case ALLOC_BUFFER:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_U32 port_index = data.readInt32();
+ size_t size = data.readInt32();
+
+ buffer_id buffer;
+ void *buffer_data;
+ status_t err = allocateBuffer(
+ node, port_index, size, &buffer, &buffer_data);
+ reply->writeInt32(err);
+
+ if (err == OK) {
+ reply->writeIntPtr((intptr_t)buffer);
+ reply->writeIntPtr((intptr_t)buffer_data);
+ }
+
+ return NO_ERROR;
+ }
+
+ case ALLOC_BUFFER_WITH_BACKUP:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_U32 port_index = data.readInt32();
+ sp<IMemory> params =
+ interface_cast<IMemory>(data.readStrongBinder());
+
+ buffer_id buffer;
+ status_t err = allocateBufferWithBackup(
+ node, port_index, params, &buffer);
+
+ reply->writeInt32(err);
+
+ if (err == OK) {
+ reply->writeIntPtr((intptr_t)buffer);
+ }
+
+ return NO_ERROR;
+ }
+
+ case FREE_BUFFER:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_U32 port_index = data.readInt32();
+ buffer_id buffer = (void*)data.readIntPtr();
+ reply->writeInt32(freeBuffer(node, port_index, buffer));
+
+ return NO_ERROR;
+ }
+
+ case FILL_BUFFER:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ buffer_id buffer = (void*)data.readIntPtr();
+ reply->writeInt32(fillBuffer(node, buffer));
+
+ return NO_ERROR;
+ }
+
+ case EMPTY_BUFFER:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ buffer_id buffer = (void*)data.readIntPtr();
+ OMX_U32 range_offset = data.readInt32();
+ OMX_U32 range_length = data.readInt32();
+ OMX_U32 flags = data.readInt32();
+ OMX_TICKS timestamp = data.readInt64();
+
+ reply->writeInt32(
+ emptyBuffer(
+ node, buffer, range_offset, range_length,
+ flags, timestamp));
+
+ return NO_ERROR;
+ }
+
+ case GET_EXTENSION_INDEX:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ const char *parameter_name = data.readCString();
+
+ OMX_INDEXTYPE index;
+ status_t err = getExtensionIndex(node, parameter_name, &index);
+
+ reply->writeInt32(err);
+
+ if (err == OK) {
+ reply->writeInt32(index);
+ }
+
+ return OK;
+ }
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+class BpOMXObserver : public BpInterface<IOMXObserver> {
+public:
+ BpOMXObserver(const sp<IBinder> &impl)
+ : BpInterface<IOMXObserver>(impl) {
+ }
+
+ virtual void onMessage(const omx_message &msg) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
+ data.write(&msg, sizeof(msg));
+
+ remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(OMXObserver, "android.hardware.IOMXObserver");
+
+status_t BnOMXObserver::onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+ switch (code) {
+ case OBSERVER_ON_MSG:
+ {
+ CHECK_INTERFACE(IOMXObserver, data, reply);
+
+ omx_message msg;
+ data.read(&msg, sizeof(msg));
+
+ // XXX Could use readInplace maybe?
+ onMessage(msg);
+
+ return NO_ERROR;
+ }
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+} // namespace android
diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp
new file mode 100644
index 0000000..078be94
--- /dev/null
+++ b/media/libmedia/IStreamSource.cpp
@@ -0,0 +1,192 @@
+/*
+ * 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 "IStreamSource"
+#include <utils/Log.h>
+
+#include <media/IStreamSource.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <binder/IMemory.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+// static
+const char *const IStreamListener::kKeyResumeAtPTS = "resume-at-PTS";
+
+// static
+const char *const IStreamListener::kKeyDiscontinuityMask = "discontinuity-mask";
+
+enum {
+ // IStreamSource
+ SET_LISTENER = IBinder::FIRST_CALL_TRANSACTION,
+ SET_BUFFERS,
+ ON_BUFFER_AVAILABLE,
+
+ // IStreamListener
+ QUEUE_BUFFER,
+ ISSUE_COMMAND,
+};
+
+struct BpStreamSource : public BpInterface<IStreamSource> {
+ BpStreamSource(const sp<IBinder> &impl)
+ : BpInterface<IStreamSource>(impl) {
+ }
+
+ virtual void setListener(const sp<IStreamListener> &listener) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor());
+ data.writeStrongBinder(listener->asBinder());
+ remote()->transact(SET_LISTENER, data, &reply);
+ }
+
+ virtual void setBuffers(const Vector<sp<IMemory> > &buffers) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor());
+ data.writeInt32(static_cast<int32_t>(buffers.size()));
+ for (size_t i = 0; i < buffers.size(); ++i) {
+ data.writeStrongBinder(buffers.itemAt(i)->asBinder());
+ }
+ remote()->transact(SET_BUFFERS, data, &reply);
+ }
+
+ virtual void onBufferAvailable(size_t index) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IStreamSource::getInterfaceDescriptor());
+ data.writeInt32(static_cast<int32_t>(index));
+ remote()->transact(
+ ON_BUFFER_AVAILABLE, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(StreamSource, "android.hardware.IStreamSource");
+
+status_t BnStreamSource::onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+ switch (code) {
+ case SET_LISTENER:
+ {
+ CHECK_INTERFACE(IStreamSource, data, reply);
+ setListener(
+ interface_cast<IStreamListener>(data.readStrongBinder()));
+ break;
+ }
+
+ case SET_BUFFERS:
+ {
+ CHECK_INTERFACE(IStreamSource, data, reply);
+ size_t n = static_cast<size_t>(data.readInt32());
+ Vector<sp<IMemory> > buffers;
+ for (size_t i = 0; i < n; ++i) {
+ sp<IMemory> mem =
+ interface_cast<IMemory>(data.readStrongBinder());
+
+ buffers.push(mem);
+ }
+ setBuffers(buffers);
+ break;
+ }
+
+ case ON_BUFFER_AVAILABLE:
+ {
+ CHECK_INTERFACE(IStreamSource, data, reply);
+ onBufferAvailable(static_cast<size_t>(data.readInt32()));
+ break;
+ }
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct BpStreamListener : public BpInterface<IStreamListener> {
+ BpStreamListener(const sp<IBinder> &impl)
+ : BpInterface<IStreamListener>(impl) {
+ }
+
+ virtual void queueBuffer(size_t index, size_t size) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor());
+ data.writeInt32(static_cast<int32_t>(index));
+ data.writeInt32(static_cast<int32_t>(size));
+
+ remote()->transact(QUEUE_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+
+ virtual void issueCommand(
+ Command cmd, bool synchronous, const sp<AMessage> &msg) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IStreamListener::getInterfaceDescriptor());
+ data.writeInt32(static_cast<int32_t>(cmd));
+ data.writeInt32(static_cast<int32_t>(synchronous));
+
+ if (msg != NULL) {
+ data.writeInt32(1);
+ msg->writeToParcel(&data);
+ } else {
+ data.writeInt32(0);
+ }
+
+ remote()->transact(ISSUE_COMMAND, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(StreamListener, "android.hardware.IStreamListener");
+
+status_t BnStreamListener::onTransact(
+ uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+ switch (code) {
+ case QUEUE_BUFFER:
+ {
+ CHECK_INTERFACE(IStreamListener, data, reply);
+ size_t index = static_cast<size_t>(data.readInt32());
+ size_t size = static_cast<size_t>(data.readInt32());
+
+ queueBuffer(index, size);
+ break;
+ }
+
+ case ISSUE_COMMAND:
+ {
+ CHECK_INTERFACE(IStreamListener, data, reply);
+ Command cmd = static_cast<Command>(data.readInt32());
+
+ bool synchronous = static_cast<bool>(data.readInt32());
+
+ sp<AMessage> msg;
+
+ if (data.readInt32()) {
+ msg = AMessage::FromParcel(data);
+ }
+
+ issueCommand(cmd, synchronous, msg);
+ break;
+ }
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
new file mode 100644
index 0000000..52aee49
--- /dev/null
+++ b/media/libmedia/JetPlayer.cpp
@@ -0,0 +1,480 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "JetPlayer-C"
+
+#include <utils/Log.h>
+#include <utils/threads.h>
+
+#include <media/JetPlayer.h>
+
+
+namespace android
+{
+
+static const int MIX_NUM_BUFFERS = 4;
+static const S_EAS_LIB_CONFIG* pLibConfig = NULL;
+
+//-------------------------------------------------------------------------------------------------
+JetPlayer::JetPlayer(void *javaJetPlayer, int maxTracks, int trackBufferSize) :
+ mEventCallback(NULL),
+ mJavaJetPlayerRef(javaJetPlayer),
+ mTid(-1),
+ mRender(false),
+ mPaused(false),
+ mMaxTracks(maxTracks),
+ mEasData(NULL),
+ mEasJetFileLoc(NULL),
+ mAudioTrack(NULL),
+ mTrackBufferSize(trackBufferSize)
+{
+ ALOGV("JetPlayer constructor");
+ mPreviousJetStatus.currentUserID = -1;
+ mPreviousJetStatus.segmentRepeatCount = -1;
+ mPreviousJetStatus.numQueuedSegments = -1;
+ mPreviousJetStatus.paused = true;
+}
+
+//-------------------------------------------------------------------------------------------------
+JetPlayer::~JetPlayer()
+{
+ ALOGV("~JetPlayer");
+ release();
+
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::init()
+{
+ //Mutex::Autolock lock(&mMutex);
+
+ EAS_RESULT result;
+
+ // retrieve the EAS library settings
+ if (pLibConfig == NULL)
+ pLibConfig = EAS_Config();
+ if (pLibConfig == NULL) {
+ ALOGE("JetPlayer::init(): EAS library configuration could not be retrieved, aborting.");
+ return EAS_FAILURE;
+ }
+
+ // init the EAS library
+ result = EAS_Init(&mEasData);
+ if (result != EAS_SUCCESS) {
+ ALOGE("JetPlayer::init(): Error initializing Sonivox EAS library, aborting.");
+ mState = EAS_STATE_ERROR;
+ return result;
+ }
+ // init the JET library with the default app event controller range
+ result = JET_Init(mEasData, NULL, sizeof(S_JET_CONFIG));
+ if (result != EAS_SUCCESS) {
+ ALOGE("JetPlayer::init(): Error initializing JET library, aborting.");
+ mState = EAS_STATE_ERROR;
+ return result;
+ }
+
+ // create the output AudioTrack
+ mAudioTrack = new AudioTrack();
+ mAudioTrack->set(AUDIO_STREAM_MUSIC, //TODO parameterize this
+ pLibConfig->sampleRate,
+ AUDIO_FORMAT_PCM_16_BIT,
+ audio_channel_out_mask_from_count(pLibConfig->numChannels),
+ mTrackBufferSize,
+ AUDIO_POLICY_OUTPUT_FLAG_NONE);
+
+ // create render and playback thread
+ {
+ Mutex::Autolock l(mMutex);
+ ALOGV("JetPlayer::init(): trying to start render thread");
+ mThread = new JetPlayerThread(this);
+ mThread->run("jetRenderThread", ANDROID_PRIORITY_AUDIO);
+ mCondition.wait(mMutex);
+ }
+ if (mTid > 0) {
+ // render thread started, we're ready
+ ALOGV("JetPlayer::init(): render thread(%d) successfully started.", mTid);
+ mState = EAS_STATE_READY;
+ } else {
+ ALOGE("JetPlayer::init(): failed to start render thread.");
+ mState = EAS_STATE_ERROR;
+ return EAS_FAILURE;
+ }
+
+ return EAS_SUCCESS;
+}
+
+void JetPlayer::setEventCallback(jetevent_callback eventCallback)
+{
+ Mutex::Autolock l(mMutex);
+ mEventCallback = eventCallback;
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::release()
+{
+ ALOGV("JetPlayer::release()");
+ Mutex::Autolock lock(mMutex);
+ mPaused = true;
+ mRender = false;
+ if (mEasData) {
+ JET_Pause(mEasData);
+ JET_CloseFile(mEasData);
+ JET_Shutdown(mEasData);
+ EAS_Shutdown(mEasData);
+ }
+ if (mEasJetFileLoc) {
+ free(mEasJetFileLoc);
+ mEasJetFileLoc = NULL;
+ }
+ if (mAudioTrack) {
+ mAudioTrack->stop();
+ mAudioTrack->flush();
+ delete mAudioTrack;
+ mAudioTrack = NULL;
+ }
+ if (mAudioBuffer) {
+ delete mAudioBuffer;
+ mAudioBuffer = NULL;
+ }
+ mEasData = NULL;
+
+ return EAS_SUCCESS;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::render() {
+ EAS_RESULT result = EAS_FAILURE;
+ EAS_I32 count;
+ int temp;
+ bool audioStarted = false;
+
+ ALOGV("JetPlayer::render(): entering");
+
+ // allocate render buffer
+ mAudioBuffer =
+ new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * MIX_NUM_BUFFERS];
+
+ // signal main thread that we started
+ {
+ Mutex::Autolock l(mMutex);
+ mTid = gettid();
+ ALOGV("JetPlayer::render(): render thread(%d) signal", mTid);
+ mCondition.signal();
+ }
+
+ while (1) {
+
+ mMutex.lock(); // [[[[[[[[ LOCK ---------------------------------------
+
+ if (mEasData == NULL) {
+ mMutex.unlock();
+ ALOGV("JetPlayer::render(): NULL EAS data, exiting render.");
+ goto threadExit;
+ }
+
+ // nothing to render, wait for client thread to wake us up
+ while (!mRender)
+ {
+ ALOGV("JetPlayer::render(): signal wait");
+ if (audioStarted) {
+ mAudioTrack->pause();
+ // we have to restart the playback once we start rendering again
+ audioStarted = false;
+ }
+ mCondition.wait(mMutex);
+ ALOGV("JetPlayer::render(): signal rx'd");
+ }
+
+ // render midi data into the input buffer
+ int num_output = 0;
+ EAS_PCM* p = mAudioBuffer;
+ for (int i = 0; i < MIX_NUM_BUFFERS; i++) {
+ result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
+ if (result != EAS_SUCCESS) {
+ ALOGE("JetPlayer::render(): EAS_Render returned error %ld", result);
+ }
+ p += count * pLibConfig->numChannels;
+ num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
+
+ // send events that were generated (if any) to the event callback
+ fireEventsFromJetQueue();
+ }
+
+ // update playback state
+ //ALOGV("JetPlayer::render(): updating state");
+ JET_Status(mEasData, &mJetStatus);
+ fireUpdateOnStatusChange();
+ mPaused = mJetStatus.paused;
+
+ mMutex.unlock(); // UNLOCK ]]]]]]]] -----------------------------------
+
+ // check audio output track
+ if (mAudioTrack == NULL) {
+ ALOGE("JetPlayer::render(): output AudioTrack was not created");
+ goto threadExit;
+ }
+
+ // Write data to the audio hardware
+ //ALOGV("JetPlayer::render(): writing to audio output");
+ if ((temp = mAudioTrack->write(mAudioBuffer, num_output)) < 0) {
+ ALOGE("JetPlayer::render(): Error in writing:%d",temp);
+ return temp;
+ }
+
+ // start audio output if necessary
+ if (!audioStarted) {
+ ALOGV("JetPlayer::render(): starting audio playback");
+ mAudioTrack->start();
+ audioStarted = true;
+ }
+
+ }//while (1)
+
+threadExit:
+ if (mAudioTrack != NULL) {
+ mAudioTrack->stop();
+ mAudioTrack->flush();
+ }
+ delete [] mAudioBuffer;
+ mAudioBuffer = NULL;
+ mMutex.lock();
+ mTid = -1;
+ mCondition.signal();
+ mMutex.unlock();
+ return result;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+// fire up an update if any of the status fields has changed
+// precondition: mMutex locked
+void JetPlayer::fireUpdateOnStatusChange()
+{
+ if ( (mJetStatus.currentUserID != mPreviousJetStatus.currentUserID)
+ ||(mJetStatus.segmentRepeatCount != mPreviousJetStatus.segmentRepeatCount) ) {
+ if (mEventCallback) {
+ mEventCallback(
+ JetPlayer::JET_USERID_UPDATE,
+ mJetStatus.currentUserID,
+ mJetStatus.segmentRepeatCount,
+ mJavaJetPlayerRef);
+ }
+ mPreviousJetStatus.currentUserID = mJetStatus.currentUserID;
+ mPreviousJetStatus.segmentRepeatCount = mJetStatus.segmentRepeatCount;
+ }
+
+ if (mJetStatus.numQueuedSegments != mPreviousJetStatus.numQueuedSegments) {
+ if (mEventCallback) {
+ mEventCallback(
+ JetPlayer::JET_NUMQUEUEDSEGMENT_UPDATE,
+ mJetStatus.numQueuedSegments,
+ -1,
+ mJavaJetPlayerRef);
+ }
+ mPreviousJetStatus.numQueuedSegments = mJetStatus.numQueuedSegments;
+ }
+
+ if (mJetStatus.paused != mPreviousJetStatus.paused) {
+ if (mEventCallback) {
+ mEventCallback(JetPlayer::JET_PAUSE_UPDATE,
+ mJetStatus.paused,
+ -1,
+ mJavaJetPlayerRef);
+ }
+ mPreviousJetStatus.paused = mJetStatus.paused;
+ }
+
+}
+
+
+//-------------------------------------------------------------------------------------------------
+// fire up all the JET events in the JET engine queue (until the queue is empty)
+// precondition: mMutex locked
+void JetPlayer::fireEventsFromJetQueue()
+{
+ if (!mEventCallback) {
+ // no callback, just empty the event queue
+ while (JET_GetEvent(mEasData, NULL, NULL)) { }
+ return;
+ }
+
+ EAS_U32 rawEvent;
+ while (JET_GetEvent(mEasData, &rawEvent, NULL)) {
+ mEventCallback(
+ JetPlayer::JET_EVENT,
+ rawEvent,
+ -1,
+ mJavaJetPlayerRef);
+ }
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::loadFromFile(const char* path)
+{
+ ALOGV("JetPlayer::loadFromFile(): path=%s", path);
+
+ Mutex::Autolock lock(mMutex);
+
+ mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE));
+ strncpy(mJetFilePath, path, sizeof(mJetFilePath));
+ mJetFilePath[sizeof(mJetFilePath) - 1] = '\0';
+ mEasJetFileLoc->path = mJetFilePath;
+
+ mEasJetFileLoc->fd = 0;
+ mEasJetFileLoc->length = 0;
+ mEasJetFileLoc->offset = 0;
+
+ EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc);
+ if (result != EAS_SUCCESS)
+ mState = EAS_STATE_ERROR;
+ else
+ mState = EAS_STATE_OPEN;
+ return( result );
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::loadFromFD(const int fd, const long long offset, const long long length)
+{
+ ALOGV("JetPlayer::loadFromFD(): fd=%d offset=%lld length=%lld", fd, offset, length);
+
+ Mutex::Autolock lock(mMutex);
+
+ mEasJetFileLoc = (EAS_FILE_LOCATOR) malloc(sizeof(EAS_FILE));
+ mEasJetFileLoc->fd = fd;
+ mEasJetFileLoc->offset = offset;
+ mEasJetFileLoc->length = length;
+ mEasJetFileLoc->path = NULL;
+
+ EAS_RESULT result = JET_OpenFile(mEasData, mEasJetFileLoc);
+ if (result != EAS_SUCCESS)
+ mState = EAS_STATE_ERROR;
+ else
+ mState = EAS_STATE_OPEN;
+ return( result );
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::closeFile()
+{
+ Mutex::Autolock lock(mMutex);
+ return JET_CloseFile(mEasData);
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::play()
+{
+ ALOGV("JetPlayer::play(): entering");
+ Mutex::Autolock lock(mMutex);
+
+ EAS_RESULT result = JET_Play(mEasData);
+
+ mPaused = false;
+ mRender = true;
+
+ JET_Status(mEasData, &mJetStatus);
+ this->dumpJetStatus(&mJetStatus);
+
+ fireUpdateOnStatusChange();
+
+ // wake up render thread
+ ALOGV("JetPlayer::play(): wakeup render thread");
+ mCondition.signal();
+
+ return result;
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::pause()
+{
+ Mutex::Autolock lock(mMutex);
+ mPaused = true;
+ EAS_RESULT result = JET_Pause(mEasData);
+
+ mRender = false;
+
+ JET_Status(mEasData, &mJetStatus);
+ this->dumpJetStatus(&mJetStatus);
+ fireUpdateOnStatusChange();
+
+
+ return result;
+}
+
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::queueSegment(int segmentNum, int libNum, int repeatCount, int transpose,
+ EAS_U32 muteFlags, EAS_U8 userID)
+{
+ ALOGV("JetPlayer::queueSegment segmentNum=%d, libNum=%d, repeatCount=%d, transpose=%d",
+ segmentNum, libNum, repeatCount, transpose);
+ Mutex::Autolock lock(mMutex);
+ return JET_QueueSegment(mEasData, segmentNum, libNum, repeatCount, transpose, muteFlags, userID);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::setMuteFlags(EAS_U32 muteFlags, bool sync)
+{
+ Mutex::Autolock lock(mMutex);
+ return JET_SetMuteFlags(mEasData, muteFlags, sync);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::setMuteFlag(int trackNum, bool muteFlag, bool sync)
+{
+ Mutex::Autolock lock(mMutex);
+ return JET_SetMuteFlag(mEasData, trackNum, muteFlag, sync);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::triggerClip(int clipId)
+{
+ ALOGV("JetPlayer::triggerClip clipId=%d", clipId);
+ Mutex::Autolock lock(mMutex);
+ return JET_TriggerClip(mEasData, clipId);
+}
+
+//-------------------------------------------------------------------------------------------------
+int JetPlayer::clearQueue()
+{
+ ALOGV("JetPlayer::clearQueue");
+ Mutex::Autolock lock(mMutex);
+ return JET_Clear_Queue(mEasData);
+}
+
+//-------------------------------------------------------------------------------------------------
+void JetPlayer::dump()
+{
+ ALOGE("JetPlayer dump: JET file=%s", mEasJetFileLoc->path);
+}
+
+void JetPlayer::dumpJetStatus(S_JET_STATUS* pJetStatus)
+{
+ if (pJetStatus!=NULL)
+ ALOGV(">> current JET player status: userID=%d segmentRepeatCount=%d numQueuedSegments=%d paused=%d",
+ pJetStatus->currentUserID, pJetStatus->segmentRepeatCount,
+ pJetStatus->numQueuedSegments, pJetStatus->paused);
+ else
+ ALOGE(">> JET player status is NULL");
+}
+
+
+} // end namespace android
diff --git a/media/libmedia/MODULE_LICENSE_APACHE2 b/media/libmedia/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/media/libmedia/MODULE_LICENSE_APACHE2
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
new file mode 100644
index 0000000..c224f06
--- /dev/null
+++ b/media/libmedia/MediaProfiles.cpp
@@ -0,0 +1,1182 @@
+/*
+**
+** 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 "MediaProfiles"
+
+#include <stdlib.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
+#include <cutils/properties.h>
+#include <expat.h>
+#include <media/MediaProfiles.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <OMX_Video.h>
+
+namespace android {
+
+Mutex MediaProfiles::sLock;
+bool MediaProfiles::sIsInitialized = false;
+MediaProfiles *MediaProfiles::sInstance = NULL;
+
+const MediaProfiles::NameToTagMap MediaProfiles::sVideoEncoderNameMap[] = {
+ {"h263", VIDEO_ENCODER_H263},
+ {"h264", VIDEO_ENCODER_H264},
+ {"m4v", VIDEO_ENCODER_MPEG_4_SP}
+};
+
+const MediaProfiles::NameToTagMap MediaProfiles::sAudioEncoderNameMap[] = {
+ {"amrnb", AUDIO_ENCODER_AMR_NB},
+ {"amrwb", AUDIO_ENCODER_AMR_WB},
+ {"aac", AUDIO_ENCODER_AAC},
+};
+
+const MediaProfiles::NameToTagMap MediaProfiles::sFileFormatMap[] = {
+ {"3gp", OUTPUT_FORMAT_THREE_GPP},
+ {"mp4", OUTPUT_FORMAT_MPEG_4}
+};
+
+const MediaProfiles::NameToTagMap MediaProfiles::sVideoDecoderNameMap[] = {
+ {"wmv", VIDEO_DECODER_WMV}
+};
+
+const MediaProfiles::NameToTagMap MediaProfiles::sAudioDecoderNameMap[] = {
+ {"wma", AUDIO_DECODER_WMA}
+};
+
+const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = {
+ {"low", CAMCORDER_QUALITY_LOW},
+ {"high", CAMCORDER_QUALITY_HIGH},
+ {"qcif", CAMCORDER_QUALITY_QCIF},
+ {"cif", CAMCORDER_QUALITY_CIF},
+ {"480p", CAMCORDER_QUALITY_480P},
+ {"720p", CAMCORDER_QUALITY_720P},
+ {"1080p", CAMCORDER_QUALITY_1080P},
+ {"qvga", CAMCORDER_QUALITY_QVGA},
+
+ {"timelapselow", CAMCORDER_QUALITY_TIME_LAPSE_LOW},
+ {"timelapsehigh", CAMCORDER_QUALITY_TIME_LAPSE_HIGH},
+ {"timelapseqcif", CAMCORDER_QUALITY_TIME_LAPSE_QCIF},
+ {"timelapsecif", CAMCORDER_QUALITY_TIME_LAPSE_CIF},
+ {"timelapse480p", CAMCORDER_QUALITY_TIME_LAPSE_480P},
+ {"timelapse720p", CAMCORDER_QUALITY_TIME_LAPSE_720P},
+ {"timelapse1080p", CAMCORDER_QUALITY_TIME_LAPSE_1080P},
+ {"timelapseqvga", CAMCORDER_QUALITY_TIME_LAPSE_QVGA},
+};
+
+/*static*/ void
+MediaProfiles::logVideoCodec(const MediaProfiles::VideoCodec& codec)
+{
+ ALOGV("video codec:");
+ ALOGV("codec = %d", codec.mCodec);
+ ALOGV("bit rate: %d", codec.mBitRate);
+ ALOGV("frame width: %d", codec.mFrameWidth);
+ ALOGV("frame height: %d", codec.mFrameHeight);
+ ALOGV("frame rate: %d", codec.mFrameRate);
+}
+
+/*static*/ void
+MediaProfiles::logAudioCodec(const MediaProfiles::AudioCodec& codec)
+{
+ ALOGV("audio codec:");
+ ALOGV("codec = %d", codec.mCodec);
+ ALOGV("bit rate: %d", codec.mBitRate);
+ ALOGV("sample rate: %d", codec.mSampleRate);
+ ALOGV("number of channels: %d", codec.mChannels);
+}
+
+/*static*/ void
+MediaProfiles::logVideoEncoderCap(const MediaProfiles::VideoEncoderCap& cap)
+{
+ ALOGV("video encoder cap:");
+ ALOGV("codec = %d", cap.mCodec);
+ ALOGV("bit rate: min = %d and max = %d", cap.mMinBitRate, cap.mMaxBitRate);
+ ALOGV("frame width: min = %d and max = %d", cap.mMinFrameWidth, cap.mMaxFrameWidth);
+ ALOGV("frame height: min = %d and max = %d", cap.mMinFrameHeight, cap.mMaxFrameHeight);
+ ALOGV("frame rate: min = %d and max = %d", cap.mMinFrameRate, cap.mMaxFrameRate);
+}
+
+/*static*/ void
+MediaProfiles::logAudioEncoderCap(const MediaProfiles::AudioEncoderCap& cap)
+{
+ ALOGV("audio encoder cap:");
+ ALOGV("codec = %d", cap.mCodec);
+ ALOGV("bit rate: min = %d and max = %d", cap.mMinBitRate, cap.mMaxBitRate);
+ ALOGV("sample rate: min = %d and max = %d", cap.mMinSampleRate, cap.mMaxSampleRate);
+ ALOGV("number of channels: min = %d and max = %d", cap.mMinChannels, cap.mMaxChannels);
+}
+
+/*static*/ void
+MediaProfiles::logVideoDecoderCap(const MediaProfiles::VideoDecoderCap& cap)
+{
+ ALOGV("video decoder cap:");
+ ALOGV("codec = %d", cap.mCodec);
+}
+
+/*static*/ void
+MediaProfiles::logAudioDecoderCap(const MediaProfiles::AudioDecoderCap& cap)
+{
+ ALOGV("audio codec cap:");
+ ALOGV("codec = %d", cap.mCodec);
+}
+
+/*static*/ void
+MediaProfiles::logVideoEditorCap(const MediaProfiles::VideoEditorCap& cap)
+{
+ ALOGV("videoeditor cap:");
+ ALOGV("mMaxInputFrameWidth = %d", cap.mMaxInputFrameWidth);
+ ALOGV("mMaxInputFrameHeight = %d", cap.mMaxInputFrameHeight);
+ ALOGV("mMaxOutputFrameWidth = %d", cap.mMaxOutputFrameWidth);
+ ALOGV("mMaxOutputFrameHeight = %d", cap.mMaxOutputFrameHeight);
+}
+
+/*static*/ int
+MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings, const char *name)
+{
+ int tag = -1;
+ for (size_t i = 0; i < nMappings; ++i) {
+ if (!strcmp(map[i].name, name)) {
+ tag = map[i].tag;
+ break;
+ }
+ }
+ return tag;
+}
+
+/*static*/ MediaProfiles::VideoCodec*
+MediaProfiles::createVideoCodec(const char **atts, MediaProfiles *profiles)
+{
+ CHECK(!strcmp("codec", atts[0]) &&
+ !strcmp("bitRate", atts[2]) &&
+ !strcmp("width", atts[4]) &&
+ !strcmp("height", atts[6]) &&
+ !strcmp("frameRate", atts[8]));
+
+ const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
+ const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
+ CHECK(codec != -1);
+
+ MediaProfiles::VideoCodec *videoCodec =
+ new MediaProfiles::VideoCodec(static_cast<video_encoder>(codec),
+ atoi(atts[3]), atoi(atts[5]), atoi(atts[7]), atoi(atts[9]));
+ logVideoCodec(*videoCodec);
+
+ size_t nCamcorderProfiles;
+ CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1);
+ profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mVideoCodec = videoCodec;
+ return videoCodec;
+}
+
+/*static*/ MediaProfiles::AudioCodec*
+MediaProfiles::createAudioCodec(const char **atts, MediaProfiles *profiles)
+{
+ CHECK(!strcmp("codec", atts[0]) &&
+ !strcmp("bitRate", atts[2]) &&
+ !strcmp("sampleRate", atts[4]) &&
+ !strcmp("channels", atts[6]));
+ const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]);
+ const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]);
+ CHECK(codec != -1);
+
+ MediaProfiles::AudioCodec *audioCodec =
+ new MediaProfiles::AudioCodec(static_cast<audio_encoder>(codec),
+ atoi(atts[3]), atoi(atts[5]), atoi(atts[7]));
+ logAudioCodec(*audioCodec);
+
+ size_t nCamcorderProfiles;
+ CHECK((nCamcorderProfiles = profiles->mCamcorderProfiles.size()) >= 1);
+ profiles->mCamcorderProfiles[nCamcorderProfiles - 1]->mAudioCodec = audioCodec;
+ return audioCodec;
+}
+/*static*/ MediaProfiles::AudioDecoderCap*
+MediaProfiles::createAudioDecoderCap(const char **atts)
+{
+ CHECK(!strcmp("name", atts[0]) &&
+ !strcmp("enabled", atts[2]));
+
+ const size_t nMappings = sizeof(sAudioDecoderNameMap)/sizeof(sAudioDecoderNameMap[0]);
+ const int codec = findTagForName(sAudioDecoderNameMap, nMappings, atts[1]);
+ CHECK(codec != -1);
+
+ MediaProfiles::AudioDecoderCap *cap =
+ new MediaProfiles::AudioDecoderCap(static_cast<audio_decoder>(codec));
+ logAudioDecoderCap(*cap);
+ return cap;
+}
+
+/*static*/ MediaProfiles::VideoDecoderCap*
+MediaProfiles::createVideoDecoderCap(const char **atts)
+{
+ CHECK(!strcmp("name", atts[0]) &&
+ !strcmp("enabled", atts[2]));
+
+ const size_t nMappings = sizeof(sVideoDecoderNameMap)/sizeof(sVideoDecoderNameMap[0]);
+ const int codec = findTagForName(sVideoDecoderNameMap, nMappings, atts[1]);
+ CHECK(codec != -1);
+
+ MediaProfiles::VideoDecoderCap *cap =
+ new MediaProfiles::VideoDecoderCap(static_cast<video_decoder>(codec));
+ logVideoDecoderCap(*cap);
+ return cap;
+}
+
+/*static*/ MediaProfiles::VideoEncoderCap*
+MediaProfiles::createVideoEncoderCap(const char **atts)
+{
+ CHECK(!strcmp("name", atts[0]) &&
+ !strcmp("enabled", atts[2]) &&
+ !strcmp("minBitRate", atts[4]) &&
+ !strcmp("maxBitRate", atts[6]) &&
+ !strcmp("minFrameWidth", atts[8]) &&
+ !strcmp("maxFrameWidth", atts[10]) &&
+ !strcmp("minFrameHeight", atts[12]) &&
+ !strcmp("maxFrameHeight", atts[14]) &&
+ !strcmp("minFrameRate", atts[16]) &&
+ !strcmp("maxFrameRate", atts[18]));
+
+ const size_t nMappings = sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
+ const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
+ CHECK(codec != -1);
+
+ MediaProfiles::VideoEncoderCap *cap =
+ new MediaProfiles::VideoEncoderCap(static_cast<video_encoder>(codec),
+ atoi(atts[5]), atoi(atts[7]), atoi(atts[9]), atoi(atts[11]), atoi(atts[13]),
+ atoi(atts[15]), atoi(atts[17]), atoi(atts[19]));
+ logVideoEncoderCap(*cap);
+ return cap;
+}
+
+/*static*/ MediaProfiles::AudioEncoderCap*
+MediaProfiles::createAudioEncoderCap(const char **atts)
+{
+ CHECK(!strcmp("name", atts[0]) &&
+ !strcmp("enabled", atts[2]) &&
+ !strcmp("minBitRate", atts[4]) &&
+ !strcmp("maxBitRate", atts[6]) &&
+ !strcmp("minSampleRate", atts[8]) &&
+ !strcmp("maxSampleRate", atts[10]) &&
+ !strcmp("minChannels", atts[12]) &&
+ !strcmp("maxChannels", atts[14]));
+
+ const size_t nMappings = sizeof(sAudioEncoderNameMap)/sizeof(sAudioEncoderNameMap[0]);
+ const int codec = findTagForName(sAudioEncoderNameMap, nMappings, atts[1]);
+ CHECK(codec != -1);
+
+ MediaProfiles::AudioEncoderCap *cap =
+ new MediaProfiles::AudioEncoderCap(static_cast<audio_encoder>(codec), atoi(atts[5]), atoi(atts[7]),
+ atoi(atts[9]), atoi(atts[11]), atoi(atts[13]),
+ atoi(atts[15]));
+ logAudioEncoderCap(*cap);
+ return cap;
+}
+
+/*static*/ output_format
+MediaProfiles::createEncoderOutputFileFormat(const char **atts)
+{
+ CHECK(!strcmp("name", atts[0]));
+
+ const size_t nMappings =sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]);
+ const int format = findTagForName(sFileFormatMap, nMappings, atts[1]);
+ CHECK(format != -1);
+
+ return static_cast<output_format>(format);
+}
+
+static bool isCameraIdFound(int cameraId, const Vector<int>& cameraIds) {
+ for (int i = 0, n = cameraIds.size(); i < n; ++i) {
+ if (cameraId == cameraIds[i]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*static*/ MediaProfiles::CamcorderProfile*
+MediaProfiles::createCamcorderProfile(int cameraId, const char **atts, Vector<int>& cameraIds)
+{
+ CHECK(!strcmp("quality", atts[0]) &&
+ !strcmp("fileFormat", atts[2]) &&
+ !strcmp("duration", atts[4]));
+
+ const size_t nProfileMappings = sizeof(sCamcorderQualityNameMap)/sizeof(sCamcorderQualityNameMap[0]);
+ const int quality = findTagForName(sCamcorderQualityNameMap, nProfileMappings, atts[1]);
+ CHECK(quality != -1);
+
+ const size_t nFormatMappings = sizeof(sFileFormatMap)/sizeof(sFileFormatMap[0]);
+ const int fileFormat = findTagForName(sFileFormatMap, nFormatMappings, atts[3]);
+ CHECK(fileFormat != -1);
+
+ MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+ profile->mCameraId = cameraId;
+ if (!isCameraIdFound(cameraId, cameraIds)) {
+ cameraIds.add(cameraId);
+ }
+ profile->mFileFormat = static_cast<output_format>(fileFormat);
+ profile->mQuality = static_cast<camcorder_quality>(quality);
+ profile->mDuration = atoi(atts[5]);
+ return profile;
+}
+
+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]);
+ ALOGV("%s: cameraId=%d, quality=%d", __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]);
+}
+
+void MediaProfiles::addStartTimeOffset(int cameraId, const char** atts)
+{
+ int offsetTimeMs = 700;
+ if (atts[2]) {
+ CHECK(!strcmp("startOffsetMs", atts[2]));
+ offsetTimeMs = atoi(atts[3]);
+ }
+
+ ALOGV("%s: cameraId=%d, offset=%d ms", __func__, cameraId, offsetTimeMs);
+ mStartTimeOffsets.replaceValueFor(cameraId, offsetTimeMs);
+}
+/*static*/ MediaProfiles::ExportVideoProfile*
+MediaProfiles::createExportVideoProfile(const char **atts)
+{
+ CHECK(!strcmp("name", atts[0]) &&
+ !strcmp("profile", atts[2]) &&
+ !strcmp("level", atts[4]));
+
+ const size_t nMappings =
+ sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
+ const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
+ CHECK(codec != -1);
+
+ MediaProfiles::ExportVideoProfile *profile =
+ new MediaProfiles::ExportVideoProfile(
+ codec, atoi(atts[3]), atoi(atts[5]));
+
+ return profile;
+}
+/*static*/ MediaProfiles::VideoEditorCap*
+MediaProfiles::createVideoEditorCap(const char **atts, MediaProfiles *profiles)
+{
+ CHECK(!strcmp("maxInputFrameWidth", atts[0]) &&
+ !strcmp("maxInputFrameHeight", atts[2]) &&
+ !strcmp("maxOutputFrameWidth", atts[4]) &&
+ !strcmp("maxOutputFrameHeight", atts[6]) &&
+ !strcmp("maxPrefetchYUVFrames", atts[8]));
+
+ MediaProfiles::VideoEditorCap *pVideoEditorCap =
+ new MediaProfiles::VideoEditorCap(atoi(atts[1]), atoi(atts[3]),
+ atoi(atts[5]), atoi(atts[7]), atoi(atts[9]));
+
+ logVideoEditorCap(*pVideoEditorCap);
+ profiles->mVideoEditorCap = pVideoEditorCap;
+
+ return pVideoEditorCap;
+}
+
+/*static*/ void
+MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts)
+{
+ MediaProfiles *profiles = (MediaProfiles *) userData;
+ if (strcmp("Video", name) == 0) {
+ createVideoCodec(atts, profiles);
+ } else if (strcmp("Audio", name) == 0) {
+ createAudioCodec(atts, profiles);
+ } else if (strcmp("VideoEncoderCap", name) == 0 &&
+ strcmp("true", atts[3]) == 0) {
+ profiles->mVideoEncoders.add(createVideoEncoderCap(atts));
+ } else if (strcmp("AudioEncoderCap", name) == 0 &&
+ strcmp("true", atts[3]) == 0) {
+ profiles->mAudioEncoders.add(createAudioEncoderCap(atts));
+ } else if (strcmp("VideoDecoderCap", name) == 0 &&
+ strcmp("true", atts[3]) == 0) {
+ profiles->mVideoDecoders.add(createVideoDecoderCap(atts));
+ } else if (strcmp("AudioDecoderCap", name) == 0 &&
+ strcmp("true", atts[3]) == 0) {
+ 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);
+ profiles->addStartTimeOffset(profiles->mCurrentCameraId, atts);
+ } else if (strcmp("EncoderProfile", name) == 0) {
+ profiles->mCamcorderProfiles.add(
+ createCamcorderProfile(profiles->mCurrentCameraId, atts, profiles->mCameraIds));
+ } else if (strcmp("ImageEncoding", name) == 0) {
+ profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts);
+ } else if (strcmp("VideoEditorCap", name) == 0) {
+ createVideoEditorCap(atts, profiles);
+ } else if (strcmp("ExportVideoProfile", name) == 0) {
+ profiles->mVideoEditorExportProfiles.add(createExportVideoProfile(atts));
+ }
+}
+
+static bool isCamcorderProfile(camcorder_quality quality) {
+ return quality >= CAMCORDER_QUALITY_LIST_START &&
+ quality <= CAMCORDER_QUALITY_LIST_END;
+}
+
+static bool isTimelapseProfile(camcorder_quality quality) {
+ return quality >= CAMCORDER_QUALITY_TIME_LAPSE_LIST_START &&
+ quality <= CAMCORDER_QUALITY_TIME_LAPSE_LIST_END;
+}
+
+void MediaProfiles::initRequiredProfileRefs(const Vector<int>& cameraIds) {
+ ALOGV("Number of camera ids: %d", cameraIds.size());
+ CHECK(cameraIds.size() > 0);
+ mRequiredProfileRefs = new RequiredProfiles[cameraIds.size()];
+ for (size_t i = 0, n = cameraIds.size(); i < n; ++i) {
+ mRequiredProfileRefs[i].mCameraId = cameraIds[i];
+ for (size_t j = 0; j < kNumRequiredProfiles; ++j) {
+ mRequiredProfileRefs[i].mRefs[j].mHasRefProfile = false;
+ mRequiredProfileRefs[i].mRefs[j].mRefProfileIndex = -1;
+ if ((j & 1) == 0) { // low resolution
+ mRequiredProfileRefs[i].mRefs[j].mResolutionProduct = 0x7FFFFFFF;
+ } else { // high resolution
+ mRequiredProfileRefs[i].mRefs[j].mResolutionProduct = 0;
+ }
+ }
+ }
+}
+
+int MediaProfiles::getRequiredProfileRefIndex(int cameraId) {
+ for (size_t i = 0, n = mCameraIds.size(); i < n; ++i) {
+ if (mCameraIds[i] == cameraId) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void MediaProfiles::checkAndAddRequiredProfilesIfNecessary() {
+ if (sIsInitialized) {
+ return;
+ }
+
+ initRequiredProfileRefs(mCameraIds);
+
+ for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) {
+ int product = mCamcorderProfiles[i]->mVideoCodec->mFrameWidth *
+ mCamcorderProfiles[i]->mVideoCodec->mFrameHeight;
+
+ camcorder_quality quality = mCamcorderProfiles[i]->mQuality;
+ int cameraId = mCamcorderProfiles[i]->mCameraId;
+ int index = -1;
+ int refIndex = getRequiredProfileRefIndex(cameraId);
+ CHECK(refIndex != -1);
+ RequiredProfileRefInfo *info;
+ camcorder_quality refQuality;
+ VideoCodec *codec = NULL;
+
+ // Check high and low from either camcorder profile or timelapse profile
+ // but not both. Default, check camcorder profile
+ size_t j = 0;
+ size_t n = 2;
+ if (isTimelapseProfile(quality)) {
+ // Check timelapse profile instead.
+ j = 2;
+ n = kNumRequiredProfiles;
+ } else {
+ // Must be camcorder profile.
+ CHECK(isCamcorderProfile(quality));
+ }
+ for (; j < n; ++j) {
+ info = &(mRequiredProfileRefs[refIndex].mRefs[j]);
+ if ((j % 2 == 0 && product > info->mResolutionProduct) || // low
+ (j % 2 != 0 && product < info->mResolutionProduct)) { // high
+ continue;
+ }
+ switch (j) {
+ case 0:
+ refQuality = CAMCORDER_QUALITY_LOW;
+ break;
+ case 1:
+ refQuality = CAMCORDER_QUALITY_HIGH;
+ break;
+ case 2:
+ refQuality = CAMCORDER_QUALITY_TIME_LAPSE_LOW;
+ break;
+ case 3:
+ refQuality = CAMCORDER_QUALITY_TIME_LAPSE_HIGH;
+ break;
+ default:
+ CHECK(!"Should never reach here");
+ }
+
+ if (!info->mHasRefProfile) {
+ index = getCamcorderProfileIndex(cameraId, refQuality);
+ }
+ if (index == -1) {
+ // New high or low quality profile is found.
+ // Update its reference.
+ info->mHasRefProfile = true;
+ info->mRefProfileIndex = i;
+ info->mResolutionProduct = product;
+ }
+ }
+ }
+
+ for (size_t cameraId = 0; cameraId < mCameraIds.size(); ++cameraId) {
+ for (size_t j = 0; j < kNumRequiredProfiles; ++j) {
+ int refIndex = getRequiredProfileRefIndex(cameraId);
+ CHECK(refIndex != -1);
+ RequiredProfileRefInfo *info =
+ &mRequiredProfileRefs[refIndex].mRefs[j];
+
+ if (info->mHasRefProfile) {
+
+ CamcorderProfile *profile =
+ new CamcorderProfile(
+ *mCamcorderProfiles[info->mRefProfileIndex]);
+
+ // Overwrite the quality
+ switch (j % kNumRequiredProfiles) {
+ case 0:
+ profile->mQuality = CAMCORDER_QUALITY_LOW;
+ break;
+ case 1:
+ profile->mQuality = CAMCORDER_QUALITY_HIGH;
+ break;
+ case 2:
+ profile->mQuality = CAMCORDER_QUALITY_TIME_LAPSE_LOW;
+ break;
+ case 3:
+ profile->mQuality = CAMCORDER_QUALITY_TIME_LAPSE_HIGH;
+ break;
+ default:
+ CHECK(!"Should never come here");
+ }
+
+ int index = getCamcorderProfileIndex(cameraId, profile->mQuality);
+ if (index != -1) {
+ ALOGV("Profile quality %d for camera %d already exists",
+ profile->mQuality, cameraId);
+ CHECK(index == refIndex);
+ continue;
+ }
+
+ // Insert the new profile
+ ALOGV("Add a profile: quality %d=>%d for camera %d",
+ mCamcorderProfiles[info->mRefProfileIndex]->mQuality,
+ profile->mQuality, cameraId);
+
+ mCamcorderProfiles.add(profile);
+ }
+ }
+ }
+}
+
+/*static*/ MediaProfiles*
+MediaProfiles::getInstance()
+{
+ ALOGV("getInstance");
+ Mutex::Autolock lock(sLock);
+ if (!sIsInitialized) {
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.settings.xml", value, NULL) <= 0) {
+ const char *defaultXmlFile = "/etc/media_profiles.xml";
+ FILE *fp = fopen(defaultXmlFile, "r");
+ if (fp == NULL) {
+ ALOGW("could not find media config xml file");
+ sInstance = createDefaultInstance();
+ } else {
+ fclose(fp); // close the file first.
+ sInstance = createInstanceFromXmlFile(defaultXmlFile);
+ }
+ } else {
+ sInstance = createInstanceFromXmlFile(value);
+ }
+ CHECK(sInstance != NULL);
+ sInstance->checkAndAddRequiredProfilesIfNecessary();
+ sIsInitialized = true;
+ }
+
+ return sInstance;
+}
+
+/*static*/ MediaProfiles::VideoEncoderCap*
+MediaProfiles::createDefaultH263VideoEncoderCap()
+{
+ return new MediaProfiles::VideoEncoderCap(
+ VIDEO_ENCODER_H263, 192000, 420000, 176, 352, 144, 288, 1, 20);
+}
+
+/*static*/ MediaProfiles::VideoEncoderCap*
+MediaProfiles::createDefaultM4vVideoEncoderCap()
+{
+ return new MediaProfiles::VideoEncoderCap(
+ VIDEO_ENCODER_MPEG_4_SP, 192000, 420000, 176, 352, 144, 288, 1, 20);
+}
+
+
+/*static*/ void
+MediaProfiles::createDefaultVideoEncoders(MediaProfiles *profiles)
+{
+ profiles->mVideoEncoders.add(createDefaultH263VideoEncoderCap());
+ profiles->mVideoEncoders.add(createDefaultM4vVideoEncoderCap());
+}
+
+/*static*/ MediaProfiles::CamcorderProfile*
+MediaProfiles::createDefaultCamcorderTimeLapseQcifProfile(camcorder_quality quality)
+{
+ MediaProfiles::VideoCodec *videoCodec =
+ new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 1000000, 176, 144, 20);
+
+ AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
+ CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+ profile->mCameraId = 0;
+ profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
+ profile->mQuality = quality;
+ profile->mDuration = 60;
+ profile->mVideoCodec = videoCodec;
+ profile->mAudioCodec = audioCodec;
+ return profile;
+}
+
+/*static*/ MediaProfiles::CamcorderProfile*
+MediaProfiles::createDefaultCamcorderTimeLapse480pProfile(camcorder_quality quality)
+{
+ MediaProfiles::VideoCodec *videoCodec =
+ new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 20000000, 720, 480, 20);
+
+ AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
+ CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+ profile->mCameraId = 0;
+ profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
+ profile->mQuality = quality;
+ profile->mDuration = 60;
+ profile->mVideoCodec = videoCodec;
+ profile->mAudioCodec = audioCodec;
+ return profile;
+}
+
+/*static*/ void
+MediaProfiles::createDefaultCamcorderTimeLapseLowProfiles(
+ MediaProfiles::CamcorderProfile **lowTimeLapseProfile,
+ MediaProfiles::CamcorderProfile **lowSpecificTimeLapseProfile) {
+ *lowTimeLapseProfile = createDefaultCamcorderTimeLapseQcifProfile(CAMCORDER_QUALITY_TIME_LAPSE_LOW);
+ *lowSpecificTimeLapseProfile = createDefaultCamcorderTimeLapseQcifProfile(CAMCORDER_QUALITY_TIME_LAPSE_QCIF);
+}
+
+/*static*/ void
+MediaProfiles::createDefaultCamcorderTimeLapseHighProfiles(
+ MediaProfiles::CamcorderProfile **highTimeLapseProfile,
+ MediaProfiles::CamcorderProfile **highSpecificTimeLapseProfile) {
+ *highTimeLapseProfile = createDefaultCamcorderTimeLapse480pProfile(CAMCORDER_QUALITY_TIME_LAPSE_HIGH);
+ *highSpecificTimeLapseProfile = createDefaultCamcorderTimeLapse480pProfile(CAMCORDER_QUALITY_TIME_LAPSE_480P);
+}
+
+/*static*/ MediaProfiles::CamcorderProfile*
+MediaProfiles::createDefaultCamcorderQcifProfile(camcorder_quality quality)
+{
+ MediaProfiles::VideoCodec *videoCodec =
+ new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 192000, 176, 144, 20);
+
+ MediaProfiles::AudioCodec *audioCodec =
+ 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 = quality;
+ profile->mDuration = 30;
+ profile->mVideoCodec = videoCodec;
+ profile->mAudioCodec = audioCodec;
+ return profile;
+}
+
+/*static*/ MediaProfiles::CamcorderProfile*
+MediaProfiles::createDefaultCamcorderCifProfile(camcorder_quality quality)
+{
+ MediaProfiles::VideoCodec *videoCodec =
+ new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 360000, 352, 288, 20);
+
+ AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
+ CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+ profile->mCameraId = 0;
+ profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
+ profile->mQuality = quality;
+ profile->mDuration = 60;
+ profile->mVideoCodec = videoCodec;
+ profile->mAudioCodec = audioCodec;
+ return profile;
+}
+
+/*static*/ void
+MediaProfiles::createDefaultCamcorderLowProfiles(
+ MediaProfiles::CamcorderProfile **lowProfile,
+ MediaProfiles::CamcorderProfile **lowSpecificProfile) {
+ *lowProfile = createDefaultCamcorderQcifProfile(CAMCORDER_QUALITY_LOW);
+ *lowSpecificProfile = createDefaultCamcorderQcifProfile(CAMCORDER_QUALITY_QCIF);
+}
+
+/*static*/ void
+MediaProfiles::createDefaultCamcorderHighProfiles(
+ MediaProfiles::CamcorderProfile **highProfile,
+ MediaProfiles::CamcorderProfile **highSpecificProfile) {
+ *highProfile = createDefaultCamcorderCifProfile(CAMCORDER_QUALITY_HIGH);
+ *highSpecificProfile = createDefaultCamcorderCifProfile(CAMCORDER_QUALITY_CIF);
+}
+
+/*static*/ void
+MediaProfiles::createDefaultCamcorderProfiles(MediaProfiles *profiles)
+{
+ // low camcorder profiles.
+ MediaProfiles::CamcorderProfile *lowProfile, *lowSpecificProfile;
+ createDefaultCamcorderLowProfiles(&lowProfile, &lowSpecificProfile);
+ profiles->mCamcorderProfiles.add(lowProfile);
+ profiles->mCamcorderProfiles.add(lowSpecificProfile);
+
+ // high camcorder profiles.
+ MediaProfiles::CamcorderProfile* highProfile, *highSpecificProfile;
+ createDefaultCamcorderHighProfiles(&highProfile, &highSpecificProfile);
+ profiles->mCamcorderProfiles.add(highProfile);
+ profiles->mCamcorderProfiles.add(highSpecificProfile);
+
+ // low camcorder time lapse profiles.
+ MediaProfiles::CamcorderProfile *lowTimeLapseProfile, *lowSpecificTimeLapseProfile;
+ createDefaultCamcorderTimeLapseLowProfiles(&lowTimeLapseProfile, &lowSpecificTimeLapseProfile);
+ profiles->mCamcorderProfiles.add(lowTimeLapseProfile);
+ profiles->mCamcorderProfiles.add(lowSpecificTimeLapseProfile);
+
+ // high camcorder time lapse profiles.
+ MediaProfiles::CamcorderProfile *highTimeLapseProfile, *highSpecificTimeLapseProfile;
+ createDefaultCamcorderTimeLapseHighProfiles(&highTimeLapseProfile, &highSpecificTimeLapseProfile);
+ profiles->mCamcorderProfiles.add(highTimeLapseProfile);
+ profiles->mCamcorderProfiles.add(highSpecificTimeLapseProfile);
+
+ // For emulator and other legacy devices which does not have a
+ // media_profiles.xml file, We assume that the default camera id
+ // is 0 and that is the only camera available.
+ profiles->mCameraIds.push(0);
+}
+
+/*static*/ void
+MediaProfiles::createDefaultAudioEncoders(MediaProfiles *profiles)
+{
+ profiles->mAudioEncoders.add(createDefaultAmrNBEncoderCap());
+}
+
+/*static*/ void
+MediaProfiles::createDefaultVideoDecoders(MediaProfiles *profiles)
+{
+ MediaProfiles::VideoDecoderCap *cap =
+ new MediaProfiles::VideoDecoderCap(VIDEO_DECODER_WMV);
+
+ profiles->mVideoDecoders.add(cap);
+}
+
+/*static*/ void
+MediaProfiles::createDefaultAudioDecoders(MediaProfiles *profiles)
+{
+ MediaProfiles::AudioDecoderCap *cap =
+ new MediaProfiles::AudioDecoderCap(AUDIO_DECODER_WMA);
+
+ profiles->mAudioDecoders.add(cap);
+}
+
+/*static*/ void
+MediaProfiles::createDefaultEncoderOutputFileFormats(MediaProfiles *profiles)
+{
+ profiles->mEncoderOutputFileFormats.add(OUTPUT_FORMAT_THREE_GPP);
+ profiles->mEncoderOutputFileFormats.add(OUTPUT_FORMAT_MPEG_4);
+}
+
+/*static*/ MediaProfiles::AudioEncoderCap*
+MediaProfiles::createDefaultAmrNBEncoderCap()
+{
+ return new MediaProfiles::AudioEncoderCap(
+ AUDIO_ENCODER_AMR_NB, 5525, 12200, 8000, 8000, 1, 1);
+}
+
+/*static*/ void
+MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles)
+{
+ ImageEncodingQualityLevels *levels = new ImageEncodingQualityLevels();
+ levels->mCameraId = 0;
+ levels->mLevels.add(70);
+ levels->mLevels.add(80);
+ levels->mLevels.add(90);
+ profiles->mImageEncodingQualityLevels.add(levels);
+}
+
+/*static*/ void
+MediaProfiles::createDefaultVideoEditorCap(MediaProfiles *profiles)
+{
+ profiles->mVideoEditorCap =
+ new MediaProfiles::VideoEditorCap(
+ VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH,
+ VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT,
+ VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH,
+ VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT,
+ VIDEOEDITOR_DEFAULT_MAX_PREFETCH_YUV_FRAMES);
+}
+/*static*/ void
+MediaProfiles::createDefaultExportVideoProfiles(MediaProfiles *profiles)
+{
+ // Create default video export profiles
+ profiles->mVideoEditorExportProfiles.add(
+ new ExportVideoProfile(VIDEO_ENCODER_H263,
+ OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level10));
+ profiles->mVideoEditorExportProfiles.add(
+ new ExportVideoProfile(VIDEO_ENCODER_MPEG_4_SP,
+ OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level1));
+ profiles->mVideoEditorExportProfiles.add(
+ new ExportVideoProfile(VIDEO_ENCODER_H264,
+ OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13));
+}
+
+/*static*/ MediaProfiles*
+MediaProfiles::createDefaultInstance()
+{
+ MediaProfiles *profiles = new MediaProfiles;
+ createDefaultCamcorderProfiles(profiles);
+ createDefaultVideoEncoders(profiles);
+ createDefaultAudioEncoders(profiles);
+ createDefaultVideoDecoders(profiles);
+ createDefaultAudioDecoders(profiles);
+ createDefaultEncoderOutputFileFormats(profiles);
+ createDefaultImageEncodingQualityLevels(profiles);
+ createDefaultVideoEditorCap(profiles);
+ createDefaultExportVideoProfiles(profiles);
+ return profiles;
+}
+
+/*static*/ MediaProfiles*
+MediaProfiles::createInstanceFromXmlFile(const char *xml)
+{
+ FILE *fp = NULL;
+ CHECK((fp = fopen(xml, "r")));
+
+ XML_Parser parser = ::XML_ParserCreate(NULL);
+ CHECK(parser != NULL);
+
+ MediaProfiles *profiles = new MediaProfiles();
+ ::XML_SetUserData(parser, profiles);
+ ::XML_SetElementHandler(parser, startElementHandler, NULL);
+
+ /*
+ FIXME:
+ expat is not compiled with -DXML_DTD. We don't have DTD parsing support.
+
+ if (!::XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS)) {
+ ALOGE("failed to enable DTD support in the xml file");
+ return UNKNOWN_ERROR;
+ }
+
+ */
+
+ const int BUFF_SIZE = 512;
+ for (;;) {
+ void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
+ if (buff == NULL) {
+ ALOGE("failed to in call to XML_GetBuffer()");
+ delete profiles;
+ profiles = NULL;
+ goto exit;
+ }
+
+ int bytes_read = ::fread(buff, 1, BUFF_SIZE, fp);
+ if (bytes_read < 0) {
+ ALOGE("failed in call to read");
+ delete profiles;
+ profiles = NULL;
+ goto exit;
+ }
+
+ CHECK(::XML_ParseBuffer(parser, bytes_read, bytes_read == 0));
+
+ if (bytes_read == 0) break; // done parsing the xml file
+ }
+
+exit:
+ ::XML_ParserFree(parser);
+ ::fclose(fp);
+ return profiles;
+}
+
+Vector<output_format> MediaProfiles::getOutputFileFormats() const
+{
+ return mEncoderOutputFileFormats; // copy out
+}
+
+Vector<video_encoder> MediaProfiles::getVideoEncoders() const
+{
+ Vector<video_encoder> encoders;
+ for (size_t i = 0; i < mVideoEncoders.size(); ++i) {
+ encoders.add(mVideoEncoders[i]->mCodec);
+ }
+ return encoders; // copy out
+}
+
+int MediaProfiles::getVideoEncoderParamByName(const char *name, video_encoder codec) const
+{
+ ALOGV("getVideoEncoderParamByName: %s for codec %d", name, codec);
+ int index = -1;
+ for (size_t i = 0, n = mVideoEncoders.size(); i < n; ++i) {
+ if (mVideoEncoders[i]->mCodec == codec) {
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) {
+ ALOGE("The given video encoder %d is not found", codec);
+ return -1;
+ }
+
+ if (!strcmp("enc.vid.width.min", name)) return mVideoEncoders[index]->mMinFrameWidth;
+ if (!strcmp("enc.vid.width.max", name)) return mVideoEncoders[index]->mMaxFrameWidth;
+ if (!strcmp("enc.vid.height.min", name)) return mVideoEncoders[index]->mMinFrameHeight;
+ if (!strcmp("enc.vid.height.max", name)) return mVideoEncoders[index]->mMaxFrameHeight;
+ if (!strcmp("enc.vid.bps.min", name)) return mVideoEncoders[index]->mMinBitRate;
+ if (!strcmp("enc.vid.bps.max", name)) return mVideoEncoders[index]->mMaxBitRate;
+ if (!strcmp("enc.vid.fps.min", name)) return mVideoEncoders[index]->mMinFrameRate;
+ if (!strcmp("enc.vid.fps.max", name)) return mVideoEncoders[index]->mMaxFrameRate;
+
+ ALOGE("The given video encoder param name %s is not found", name);
+ return -1;
+}
+int MediaProfiles::getVideoEditorExportParamByName(
+ const char *name, int codec) const
+{
+ ALOGV("getVideoEditorExportParamByName: name %s codec %d", name, codec);
+ ExportVideoProfile *exportProfile = NULL;
+ int index = -1;
+ for (size_t i =0; i < mVideoEditorExportProfiles.size(); i++) {
+ exportProfile = mVideoEditorExportProfiles[i];
+ if (exportProfile->mCodec == codec) {
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) {
+ ALOGE("The given video decoder %d is not found", codec);
+ return -1;
+ }
+ if (!strcmp("videoeditor.export.profile", name))
+ return exportProfile->mProfile;
+ if (!strcmp("videoeditor.export.level", name))
+ return exportProfile->mLevel;
+
+ ALOGE("The given video editor export param name %s is not found", name);
+ return -1;
+}
+int MediaProfiles::getVideoEditorCapParamByName(const char *name) const
+{
+ ALOGV("getVideoEditorCapParamByName: %s", name);
+
+ if (mVideoEditorCap == NULL) {
+ ALOGE("The mVideoEditorCap is not created, then create default cap.");
+ createDefaultVideoEditorCap(sInstance);
+ }
+
+ if (!strcmp("videoeditor.input.width.max", name))
+ return mVideoEditorCap->mMaxInputFrameWidth;
+ if (!strcmp("videoeditor.input.height.max", name))
+ return mVideoEditorCap->mMaxInputFrameHeight;
+ if (!strcmp("videoeditor.output.width.max", name))
+ return mVideoEditorCap->mMaxOutputFrameWidth;
+ if (!strcmp("videoeditor.output.height.max", name))
+ return mVideoEditorCap->mMaxOutputFrameHeight;
+ if (!strcmp("maxPrefetchYUVFrames", name))
+ return mVideoEditorCap->mMaxPrefetchYUVFrames;
+
+ ALOGE("The given video editor param name %s is not found", name);
+ return -1;
+}
+
+Vector<audio_encoder> MediaProfiles::getAudioEncoders() const
+{
+ Vector<audio_encoder> encoders;
+ for (size_t i = 0; i < mAudioEncoders.size(); ++i) {
+ encoders.add(mAudioEncoders[i]->mCodec);
+ }
+ return encoders; // copy out
+}
+
+int MediaProfiles::getAudioEncoderParamByName(const char *name, audio_encoder codec) const
+{
+ ALOGV("getAudioEncoderParamByName: %s for codec %d", name, codec);
+ int index = -1;
+ for (size_t i = 0, n = mAudioEncoders.size(); i < n; ++i) {
+ if (mAudioEncoders[i]->mCodec == codec) {
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) {
+ ALOGE("The given audio encoder %d is not found", codec);
+ return -1;
+ }
+
+ if (!strcmp("enc.aud.ch.min", name)) return mAudioEncoders[index]->mMinChannels;
+ if (!strcmp("enc.aud.ch.max", name)) return mAudioEncoders[index]->mMaxChannels;
+ if (!strcmp("enc.aud.bps.min", name)) return mAudioEncoders[index]->mMinBitRate;
+ if (!strcmp("enc.aud.bps.max", name)) return mAudioEncoders[index]->mMaxBitRate;
+ if (!strcmp("enc.aud.hz.min", name)) return mAudioEncoders[index]->mMinSampleRate;
+ if (!strcmp("enc.aud.hz.max", name)) return mAudioEncoders[index]->mMaxSampleRate;
+
+ ALOGE("The given audio encoder param name %s is not found", name);
+ return -1;
+}
+
+Vector<video_decoder> MediaProfiles::getVideoDecoders() const
+{
+ Vector<video_decoder> decoders;
+ for (size_t i = 0; i < mVideoDecoders.size(); ++i) {
+ decoders.add(mVideoDecoders[i]->mCodec);
+ }
+ return decoders; // copy out
+}
+
+Vector<audio_decoder> MediaProfiles::getAudioDecoders() const
+{
+ Vector<audio_decoder> decoders;
+ for (size_t i = 0; i < mAudioDecoders.size(); ++i) {
+ decoders.add(mAudioDecoders[i]->mCodec);
+ }
+ return decoders; // copy out
+}
+
+int MediaProfiles::getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const
+{
+ int index = -1;
+ for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) {
+ if (mCamcorderProfiles[i]->mCameraId == cameraId &&
+ mCamcorderProfiles[i]->mQuality == quality) {
+ index = i;
+ break;
+ }
+ }
+ return index;
+}
+
+int MediaProfiles::getCamcorderProfileParamByName(const char *name,
+ int cameraId,
+ camcorder_quality quality) const
+{
+ ALOGV("getCamcorderProfileParamByName: %s for camera %d, quality %d",
+ name, cameraId, quality);
+
+ int index = getCamcorderProfileIndex(cameraId, quality);
+ if (index == -1) {
+ ALOGE("The given camcorder profile camera %d quality %d is not found",
+ cameraId, quality);
+ return -1;
+ }
+
+ if (!strcmp("duration", name)) return mCamcorderProfiles[index]->mDuration;
+ if (!strcmp("file.format", name)) return mCamcorderProfiles[index]->mFileFormat;
+ if (!strcmp("vid.codec", name)) return mCamcorderProfiles[index]->mVideoCodec->mCodec;
+ if (!strcmp("vid.width", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameWidth;
+ if (!strcmp("vid.height", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameHeight;
+ if (!strcmp("vid.bps", name)) return mCamcorderProfiles[index]->mVideoCodec->mBitRate;
+ if (!strcmp("vid.fps", name)) return mCamcorderProfiles[index]->mVideoCodec->mFrameRate;
+ if (!strcmp("aud.codec", name)) return mCamcorderProfiles[index]->mAudioCodec->mCodec;
+ if (!strcmp("aud.bps", name)) return mCamcorderProfiles[index]->mAudioCodec->mBitRate;
+ if (!strcmp("aud.ch", name)) return mCamcorderProfiles[index]->mAudioCodec->mChannels;
+ if (!strcmp("aud.hz", name)) return mCamcorderProfiles[index]->mAudioCodec->mSampleRate;
+
+ ALOGE("The given camcorder profile param id %d name %s is not found", cameraId, name);
+ return -1;
+}
+
+bool MediaProfiles::hasCamcorderProfile(int cameraId, camcorder_quality quality) const
+{
+ return (getCamcorderProfileIndex(cameraId, quality) != -1);
+}
+
+Vector<int> MediaProfiles::getImageEncodingQualityLevels(int cameraId) const
+{
+ Vector<int> result;
+ ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId);
+ if (levels != NULL) {
+ result = levels->mLevels; // copy out
+ }
+ return result;
+}
+
+int MediaProfiles::getStartTimeOffsetMs(int cameraId) const {
+ int offsetTimeMs = -1;
+ ssize_t index = mStartTimeOffsets.indexOfKey(cameraId);
+ if (index >= 0) {
+ offsetTimeMs = mStartTimeOffsets.valueFor(cameraId);
+ }
+ ALOGV("offsetTime=%d ms and cameraId=%d", offsetTimeMs, cameraId);
+ return offsetTimeMs;
+}
+
+MediaProfiles::~MediaProfiles()
+{
+ CHECK("destructor should never be called" == 0);
+#if 0
+ for (size_t i = 0; i < mAudioEncoders.size(); ++i) {
+ delete mAudioEncoders[i];
+ }
+ mAudioEncoders.clear();
+
+ for (size_t i = 0; i < mVideoEncoders.size(); ++i) {
+ delete mVideoEncoders[i];
+ }
+ mVideoEncoders.clear();
+
+ for (size_t i = 0; i < mVideoDecoders.size(); ++i) {
+ delete mVideoDecoders[i];
+ }
+ mVideoDecoders.clear();
+
+ for (size_t i = 0; i < mAudioDecoders.size(); ++i) {
+ delete mAudioDecoders[i];
+ }
+ mAudioDecoders.clear();
+
+ for (size_t i = 0; i < mCamcorderProfiles.size(); ++i) {
+ delete mCamcorderProfiles[i];
+ }
+ mCamcorderProfiles.clear();
+#endif
+}
+} // namespace android
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
new file mode 100644
index 0000000..28b5aa7
--- /dev/null
+++ b/media/libmedia/MediaScanner.cpp
@@ -0,0 +1,240 @@
+/*
+ * 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 "MediaScanner"
+#include <cutils/properties.h>
+#include <utils/Log.h>
+
+#include <media/mediascanner.h>
+
+#include <sys/stat.h>
+#include <dirent.h>
+
+namespace android {
+
+MediaScanner::MediaScanner()
+ : mLocale(NULL), mSkipList(NULL), mSkipIndex(NULL) {
+ loadSkipList();
+}
+
+MediaScanner::~MediaScanner() {
+ setLocale(NULL);
+ free(mSkipList);
+ free(mSkipIndex);
+}
+
+void MediaScanner::setLocale(const char *locale) {
+ if (mLocale) {
+ free(mLocale);
+ mLocale = NULL;
+ }
+ if (locale) {
+ mLocale = strdup(locale);
+ }
+}
+
+const char *MediaScanner::locale() const {
+ return mLocale;
+}
+
+void MediaScanner::loadSkipList() {
+ mSkipList = (char *)malloc(PROPERTY_VALUE_MAX * sizeof(char));
+ if (mSkipList) {
+ property_get("testing.mediascanner.skiplist", mSkipList, "");
+ }
+ if (!mSkipList || (strlen(mSkipList) == 0)) {
+ free(mSkipList);
+ mSkipList = NULL;
+ return;
+ }
+ mSkipIndex = (int *)malloc(PROPERTY_VALUE_MAX * sizeof(int));
+ if (mSkipIndex) {
+ // dup it because strtok will modify the string
+ char *skipList = strdup(mSkipList);
+ if (skipList) {
+ char * path = strtok(skipList, ",");
+ int i = 0;
+ while (path) {
+ mSkipIndex[i++] = strlen(path);
+ path = strtok(NULL, ",");
+ }
+ mSkipIndex[i] = -1;
+ free(skipList);
+ }
+ }
+}
+
+MediaScanResult MediaScanner::processDirectory(
+ const char *path, MediaScannerClient &client) {
+ int pathLength = strlen(path);
+ if (pathLength >= PATH_MAX) {
+ return MEDIA_SCAN_RESULT_SKIPPED;
+ }
+ char* pathBuffer = (char *)malloc(PATH_MAX + 1);
+ if (!pathBuffer) {
+ return MEDIA_SCAN_RESULT_ERROR;
+ }
+
+ int pathRemaining = PATH_MAX - pathLength;
+ strcpy(pathBuffer, path);
+ if (pathLength > 0 && pathBuffer[pathLength - 1] != '/') {
+ pathBuffer[pathLength] = '/';
+ pathBuffer[pathLength + 1] = 0;
+ --pathRemaining;
+ }
+
+ client.setLocale(locale());
+
+ MediaScanResult result = doProcessDirectory(pathBuffer, pathRemaining, client, false);
+
+ free(pathBuffer);
+
+ return result;
+}
+
+bool MediaScanner::shouldSkipDirectory(char *path) {
+ if (path && mSkipList && mSkipIndex) {
+ int len = strlen(path);
+ int idx = 0;
+ // track the start position of next path in the comma
+ // separated list obtained from getprop
+ int startPos = 0;
+ while (mSkipIndex[idx] != -1) {
+ // no point to match path name if strlen mismatch
+ if ((len == mSkipIndex[idx])
+ // pick out the path segment from comma separated list
+ // to compare against current path parameter
+ && (strncmp(path, &mSkipList[startPos], len) == 0)) {
+ return true;
+ }
+ startPos += mSkipIndex[idx] + 1; // extra char for the delimiter
+ idx++;
+ }
+ }
+ return false;
+}
+
+MediaScanResult MediaScanner::doProcessDirectory(
+ char *path, int pathRemaining, MediaScannerClient &client, bool noMedia) {
+ // place to copy file or directory name
+ char* fileSpot = path + strlen(path);
+ struct dirent* entry;
+
+ if (shouldSkipDirectory(path)) {
+ ALOGD("Skipping: %s", path);
+ return MEDIA_SCAN_RESULT_OK;
+ }
+
+ // Treat all files as non-media in directories that contain a ".nomedia" file
+ if (pathRemaining >= 8 /* strlen(".nomedia") */ ) {
+ strcpy(fileSpot, ".nomedia");
+ if (access(path, F_OK) == 0) {
+ ALOGV("found .nomedia, setting noMedia flag");
+ noMedia = true;
+ }
+
+ // restore path
+ fileSpot[0] = 0;
+ }
+
+ DIR* dir = opendir(path);
+ if (!dir) {
+ ALOGW("Error opening directory '%s', skipping: %s.", path, strerror(errno));
+ return MEDIA_SCAN_RESULT_SKIPPED;
+ }
+
+ MediaScanResult result = MEDIA_SCAN_RESULT_OK;
+ while ((entry = readdir(dir))) {
+ if (doProcessDirectoryEntry(path, pathRemaining, client, noMedia, entry, fileSpot)
+ == MEDIA_SCAN_RESULT_ERROR) {
+ result = MEDIA_SCAN_RESULT_ERROR;
+ break;
+ }
+ }
+ closedir(dir);
+ return result;
+}
+
+MediaScanResult MediaScanner::doProcessDirectoryEntry(
+ char *path, int pathRemaining, MediaScannerClient &client, bool noMedia,
+ struct dirent* entry, char* fileSpot) {
+ struct stat statbuf;
+ const char* name = entry->d_name;
+
+ // ignore "." and ".."
+ if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
+ return MEDIA_SCAN_RESULT_SKIPPED;
+ }
+
+ int nameLength = strlen(name);
+ if (nameLength + 1 > pathRemaining) {
+ // path too long!
+ return MEDIA_SCAN_RESULT_SKIPPED;
+ }
+ strcpy(fileSpot, name);
+
+ int type = entry->d_type;
+ if (type == DT_UNKNOWN) {
+ // If the type is unknown, stat() the file instead.
+ // This is sometimes necessary when accessing NFS mounted filesystems, but
+ // could be needed in other cases well.
+ if (stat(path, &statbuf) == 0) {
+ if (S_ISREG(statbuf.st_mode)) {
+ type = DT_REG;
+ } else if (S_ISDIR(statbuf.st_mode)) {
+ type = DT_DIR;
+ }
+ } else {
+ ALOGD("stat() failed for %s: %s", path, strerror(errno) );
+ }
+ }
+ if (type == DT_DIR) {
+ bool childNoMedia = noMedia;
+ // set noMedia flag on directories with a name that starts with '.'
+ // for example, the Mac ".Trashes" directory
+ if (name[0] == '.')
+ childNoMedia = true;
+
+ // report the directory to the client
+ if (stat(path, &statbuf) == 0) {
+ status_t status = client.scanFile(path, statbuf.st_mtime, 0,
+ true /*isDirectory*/, childNoMedia);
+ if (status) {
+ return MEDIA_SCAN_RESULT_ERROR;
+ }
+ }
+
+ // and now process its contents
+ strcat(fileSpot, "/");
+ MediaScanResult result = doProcessDirectory(path, pathRemaining - nameLength - 1,
+ client, childNoMedia);
+ if (result == MEDIA_SCAN_RESULT_ERROR) {
+ return MEDIA_SCAN_RESULT_ERROR;
+ }
+ } else if (type == DT_REG) {
+ stat(path, &statbuf);
+ status_t status = client.scanFile(path, statbuf.st_mtime, statbuf.st_size,
+ false /*isDirectory*/, noMedia);
+ if (status) {
+ return MEDIA_SCAN_RESULT_ERROR;
+ }
+ }
+
+ return MEDIA_SCAN_RESULT_OK;
+}
+
+} // namespace android
diff --git a/media/libmedia/MediaScannerClient.cpp b/media/libmedia/MediaScannerClient.cpp
new file mode 100644
index 0000000..e1e3348
--- /dev/null
+++ b/media/libmedia/MediaScannerClient.cpp
@@ -0,0 +1,230 @@
+/*
+ * 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 <media/mediascanner.h>
+
+#include <utils/StringArray.h>
+
+#include "autodetect.h"
+#include "unicode/ucnv.h"
+#include "unicode/ustring.h"
+
+namespace android {
+
+MediaScannerClient::MediaScannerClient()
+ : mNames(NULL),
+ mValues(NULL),
+ mLocaleEncoding(kEncodingNone)
+{
+}
+
+MediaScannerClient::~MediaScannerClient()
+{
+ delete mNames;
+ delete mValues;
+}
+
+void MediaScannerClient::setLocale(const char* locale)
+{
+ if (!locale) return;
+
+ if (!strncmp(locale, "ja", 2))
+ mLocaleEncoding = kEncodingShiftJIS;
+ else if (!strncmp(locale, "ko", 2))
+ mLocaleEncoding = kEncodingEUCKR;
+ else if (!strncmp(locale, "zh", 2)) {
+ if (!strcmp(locale, "zh_CN")) {
+ // simplified chinese for mainland China
+ mLocaleEncoding = kEncodingGBK;
+ } else {
+ // assume traditional for non-mainland Chinese locales (Taiwan, Hong Kong, Singapore)
+ mLocaleEncoding = kEncodingBig5;
+ }
+ }
+}
+
+void MediaScannerClient::beginFile()
+{
+ mNames = new StringArray;
+ mValues = new StringArray;
+}
+
+status_t MediaScannerClient::addStringTag(const char* name, const char* value)
+{
+ if (mLocaleEncoding != kEncodingNone) {
+ // don't bother caching strings that are all ASCII.
+ // call handleStringTag directly instead.
+ // check to see if value (which should be utf8) has any non-ASCII characters
+ bool nonAscii = false;
+ const char* chp = value;
+ char ch;
+ while ((ch = *chp++)) {
+ if (ch & 0x80) {
+ nonAscii = true;
+ break;
+ }
+ }
+
+ if (nonAscii) {
+ // save the strings for later so they can be used for native encoding detection
+ mNames->push_back(name);
+ mValues->push_back(value);
+ return OK;
+ }
+ // else fall through
+ }
+
+ // autodetection is not necessary, so no need to cache the values
+ // pass directly to the client instead
+ return handleStringTag(name, value);
+}
+
+static uint32_t possibleEncodings(const char* s)
+{
+ uint32_t result = kEncodingAll;
+ // if s contains a native encoding, then it was mistakenly encoded in utf8 as if it were latin-1
+ // so we need to reverse the latin-1 -> utf8 conversion to get the native chars back
+ uint8_t ch1, ch2;
+ uint8_t* chp = (uint8_t *)s;
+
+ while ((ch1 = *chp++)) {
+ if (ch1 & 0x80) {
+ ch2 = *chp++;
+ ch1 = ((ch1 << 6) & 0xC0) | (ch2 & 0x3F);
+ // ch1 is now the first byte of the potential native char
+
+ ch2 = *chp++;
+ if (ch2 & 0x80)
+ ch2 = ((ch2 << 6) & 0xC0) | (*chp++ & 0x3F);
+ // ch2 is now the second byte of the potential native char
+ int ch = (int)ch1 << 8 | (int)ch2;
+ result &= findPossibleEncodings(ch);
+ }
+ // else ASCII character, which could be anything
+ }
+
+ return result;
+}
+
+void MediaScannerClient::convertValues(uint32_t encoding)
+{
+ const char* enc = NULL;
+ switch (encoding) {
+ case kEncodingShiftJIS:
+ enc = "shift-jis";
+ break;
+ case kEncodingGBK:
+ enc = "gbk";
+ break;
+ case kEncodingBig5:
+ enc = "Big5";
+ break;
+ case kEncodingEUCKR:
+ enc = "EUC-KR";
+ break;
+ }
+
+ if (enc) {
+ UErrorCode status = U_ZERO_ERROR;
+
+ UConverter *conv = ucnv_open(enc, &status);
+ if (U_FAILURE(status)) {
+ ALOGE("could not create UConverter for %s", enc);
+ return;
+ }
+ UConverter *utf8Conv = ucnv_open("UTF-8", &status);
+ if (U_FAILURE(status)) {
+ ALOGE("could not create UConverter for UTF-8");
+ ucnv_close(conv);
+ return;
+ }
+
+ // for each value string, convert from native encoding to UTF-8
+ for (int i = 0; i < mNames->size(); i++) {
+ // first we need to untangle the utf8 and convert it back to the original bytes
+ // since we are reducing the length of the string, we can do this in place
+ uint8_t* src = (uint8_t *)mValues->getEntry(i);
+ int len = strlen((char *)src);
+ uint8_t* dest = src;
+
+ uint8_t uch;
+ while ((uch = *src++)) {
+ if (uch & 0x80)
+ *dest++ = ((uch << 6) & 0xC0) | (*src++ & 0x3F);
+ else
+ *dest++ = uch;
+ }
+ *dest = 0;
+
+ // now convert from native encoding to UTF-8
+ const char* source = mValues->getEntry(i);
+ int targetLength = len * 3 + 1;
+ char* buffer = new char[targetLength];
+ // don't normally check for NULL, but in this case targetLength may be large
+ if (!buffer)
+ break;
+ char* target = buffer;
+
+ ucnv_convertEx(utf8Conv, conv, &target, target + targetLength,
+ &source, (const char *)dest, NULL, NULL, NULL, NULL, TRUE, TRUE, &status);
+ if (U_FAILURE(status)) {
+ ALOGE("ucnv_convertEx failed: %d", status);
+ mValues->setEntry(i, "???");
+ } else {
+ // zero terminate
+ *target = 0;
+ mValues->setEntry(i, buffer);
+ }
+
+ delete[] buffer;
+ }
+
+ ucnv_close(conv);
+ ucnv_close(utf8Conv);
+ }
+}
+
+void MediaScannerClient::endFile()
+{
+ if (mLocaleEncoding != kEncodingNone) {
+ int size = mNames->size();
+ uint32_t encoding = kEncodingAll;
+
+ // compute a bit mask containing all possible encodings
+ for (int i = 0; i < mNames->size(); i++)
+ encoding &= possibleEncodings(mValues->getEntry(i));
+
+ // if the locale encoding matches, then assume we have a native encoding.
+ if (encoding & mLocaleEncoding)
+ convertValues(mLocaleEncoding);
+
+ // finally, push all name/value pairs to the client
+ for (int i = 0; i < mNames->size(); i++) {
+ status_t status = handleStringTag(mNames->getEntry(i), mValues->getEntry(i));
+ if (status) {
+ break;
+ }
+ }
+ }
+ // else addStringTag() has done all the work so we have nothing to do
+
+ delete mNames;
+ delete mValues;
+ mNames = NULL;
+ mValues = NULL;
+}
+
+} // namespace android
diff --git a/media/libmedia/MemoryLeakTrackUtil.cpp b/media/libmedia/MemoryLeakTrackUtil.cpp
new file mode 100644
index 0000000..6a108ae
--- /dev/null
+++ b/media/libmedia/MemoryLeakTrackUtil.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <media/MemoryLeakTrackUtil.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/*
+ * The code here originally resided in MediaPlayerService.cpp and was
+ * shamelessly copied over to support memory leak tracking from
+ * multiple places.
+ */
+namespace android {
+
+#if defined(__arm__)
+
+extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
+ size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
+
+extern "C" void free_malloc_leak_info(uint8_t* info);
+
+// Use the String-class below instead of String8 to allocate all memory
+// beforehand and not reenter the heap while we are examining it...
+struct MyString8 {
+ static const size_t MAX_SIZE = 256 * 1024;
+
+ MyString8()
+ : mPtr((char *)malloc(MAX_SIZE)) {
+ *mPtr = '\0';
+ }
+
+ ~MyString8() {
+ free(mPtr);
+ }
+
+ void append(const char *s) {
+ strcat(mPtr, s);
+ }
+
+ const char *string() const {
+ return mPtr;
+ }
+
+ size_t size() const {
+ return strlen(mPtr);
+ }
+
+private:
+ char *mPtr;
+
+ MyString8(const MyString8 &);
+ MyString8 &operator=(const MyString8 &);
+};
+
+void dumpMemoryAddresses(int fd)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ MyString8 result;
+
+ typedef struct {
+ size_t size;
+ size_t dups;
+ intptr_t * backtrace;
+ } AllocEntry;
+
+ uint8_t *info = NULL;
+ size_t overallSize = 0;
+ size_t infoSize = 0;
+ size_t totalMemory = 0;
+ size_t backtraceSize = 0;
+
+ get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
+ if (info) {
+ uint8_t *ptr = info;
+ size_t count = overallSize / infoSize;
+
+ snprintf(buffer, SIZE, " Allocation count %i\n", count);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Total memory %i\n", totalMemory);
+ result.append(buffer);
+
+ AllocEntry * entries = new AllocEntry[count];
+
+ for (size_t i = 0; i < count; i++) {
+ // Each entry should be size_t, size_t, intptr_t[backtraceSize]
+ AllocEntry *e = &entries[i];
+
+ e->size = *reinterpret_cast<size_t *>(ptr);
+ ptr += sizeof(size_t);
+
+ e->dups = *reinterpret_cast<size_t *>(ptr);
+ ptr += sizeof(size_t);
+
+ e->backtrace = reinterpret_cast<intptr_t *>(ptr);
+ ptr += sizeof(intptr_t) * backtraceSize;
+ }
+
+ // Now we need to sort the entries. They come sorted by size but
+ // not by stack trace which causes problems using diff.
+ bool moved;
+ do {
+ moved = false;
+ for (size_t i = 0; i < (count - 1); i++) {
+ AllocEntry *e1 = &entries[i];
+ AllocEntry *e2 = &entries[i+1];
+
+ bool swap = e1->size < e2->size;
+ if (e1->size == e2->size) {
+ for(size_t j = 0; j < backtraceSize; j++) {
+ if (e1->backtrace[j] == e2->backtrace[j]) {
+ continue;
+ }
+ swap = e1->backtrace[j] < e2->backtrace[j];
+ break;
+ }
+ }
+ if (swap) {
+ AllocEntry t = entries[i];
+ entries[i] = entries[i+1];
+ entries[i+1] = t;
+ moved = true;
+ }
+ }
+ } while (moved);
+
+ for (size_t i = 0; i < count; i++) {
+ AllocEntry *e = &entries[i];
+
+ snprintf(buffer, SIZE, "size %8i, dup %4i, ", e->size, e->dups);
+ result.append(buffer);
+ for (size_t ct = 0; (ct < backtraceSize) && e->backtrace[ct]; ct++) {
+ if (ct) {
+ result.append(", ");
+ }
+ snprintf(buffer, SIZE, "0x%08x", e->backtrace[ct]);
+ result.append(buffer);
+ }
+ result.append("\n");
+ }
+
+ delete[] entries;
+ free_malloc_leak_info(info);
+ }
+
+ write(fd, result.string(), result.size());
+}
+
+#else
+// Does nothing
+void dumpMemoryAddresses(int fd) {}
+
+#endif
+} // namespace android
diff --git a/media/libmedia/Metadata.cpp b/media/libmedia/Metadata.cpp
new file mode 100644
index 0000000..ef8a9ed
--- /dev/null
+++ b/media/libmedia/Metadata.cpp
@@ -0,0 +1,167 @@
+/*
+ * 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 "Metadata"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <media/Metadata.h>
+#include <binder/Parcel.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+// This file contains code to serialize Metadata triples (key, type,
+// value) into a parcel. The Parcel is destinated to be decoded by the
+// Metadata.java class.
+
+namespace {
+// All these constants below must be kept in sync with Metadata.java.
+enum MetadataId {
+ FIRST_SYSTEM_ID = 1,
+ LAST_SYSTEM_ID = 31,
+ FIRST_CUSTOM_ID = 8192
+};
+
+// Types
+enum Types {
+ STRING_VAL = 1,
+ INTEGER_VAL,
+ BOOLEAN_VAL,
+ LONG_VAL,
+ DOUBLE_VAL,
+ DATE_VAL,
+ BYTE_ARRAY_VAL,
+};
+
+const size_t kRecordHeaderSize = 3 * sizeof(int32_t);
+const int32_t kMetaMarker = 0x4d455441; // 'M' 'E' 'T' 'A'
+
+} // anonymous namespace
+
+namespace android {
+namespace media {
+
+Metadata::Metadata(Parcel *p)
+ :mData(p),
+ mBegin(p->dataPosition()) { }
+
+Metadata::~Metadata() { }
+
+void Metadata::resetParcel()
+{
+ mData->setDataPosition(mBegin);
+}
+
+// Update the 4 bytes int at the beginning of the parcel which holds
+// the number of bytes written so far.
+void Metadata::updateLength()
+{
+ const size_t end = mData->dataPosition();
+
+ mData->setDataPosition(mBegin);
+ mData->writeInt32(end - mBegin);
+ mData->setDataPosition(end);
+}
+
+// Write the header. The java layer will look for the marker.
+bool Metadata::appendHeader()
+{
+ bool ok = true;
+
+ // Placeholder for the length of the metadata
+ ok = ok && mData->writeInt32(-1) == OK;
+ ok = ok && mData->writeInt32(kMetaMarker) == OK;
+ return ok;
+}
+
+bool Metadata::appendBool(int key, bool val)
+{
+ if (!checkKey(key)) {
+ return false;
+ }
+
+ const size_t begin = mData->dataPosition();
+ bool ok = true;
+
+ // 4 int32s: size, key, type, value.
+ ok = ok && mData->writeInt32(4 * sizeof(int32_t)) == OK;
+ ok = ok && mData->writeInt32(key) == OK;
+ ok = ok && mData->writeInt32(BOOLEAN_VAL) == OK;
+ ok = ok && mData->writeInt32(val ? 1 : 0) == OK;
+ if (!ok) {
+ mData->setDataPosition(begin);
+ }
+ return ok;
+}
+
+bool Metadata::appendInt32(int key, int32_t val)
+{
+ if (!checkKey(key)) {
+ return false;
+ }
+
+ const size_t begin = mData->dataPosition();
+ bool ok = true;
+
+ // 4 int32s: size, key, type, value.
+ ok = ok && mData->writeInt32(4 * sizeof(int32_t)) == OK;
+ ok = ok && mData->writeInt32(key) == OK;
+ ok = ok && mData->writeInt32(INTEGER_VAL) == OK;
+ ok = ok && mData->writeInt32(val) == OK;
+ if (!ok) {
+ mData->setDataPosition(begin);
+ }
+ return ok;
+}
+
+// Check the key (i.e metadata id) is valid if it is a system one.
+// Loop over all the exiting ones in the Parcel to check for duplicate
+// (not allowed).
+bool Metadata::checkKey(int key)
+{
+ if (key < FIRST_SYSTEM_ID ||
+ (LAST_SYSTEM_ID < key && key < FIRST_CUSTOM_ID)) {
+ ALOGE("Bad key %d", key);
+ return false;
+ }
+ size_t curr = mData->dataPosition();
+ // Loop over the keys to check if it has been used already.
+ mData->setDataPosition(mBegin);
+
+ bool error = false;
+ size_t left = curr - mBegin;
+ while (left > 0) {
+ size_t pos = mData->dataPosition();
+ size_t size = mData->readInt32();
+ if (size < kRecordHeaderSize || size > left) {
+ error = true;
+ break;
+ }
+ if (mData->readInt32() == key) {
+ ALOGE("Key exists already %d", key);
+ error = true;
+ break;
+ }
+ mData->setDataPosition(pos + size);
+ left -= size;
+ }
+ mData->setDataPosition(curr);
+ return !error;
+}
+
+} // namespace android::media
+} // namespace android
diff --git a/media/libmedia/NOTICE b/media/libmedia/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/media/libmedia/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2005-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.
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/media/libmedia/SoundPool.cpp b/media/libmedia/SoundPool.cpp
new file mode 100644
index 0000000..306c57d
--- /dev/null
+++ b/media/libmedia/SoundPool.cpp
@@ -0,0 +1,908 @@
+/*
+ * Copyright (C) 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 "SoundPool"
+#include <utils/Log.h>
+
+//#define USE_SHARED_MEM_BUFFER
+
+// XXX needed for timing latency
+#include <utils/Timers.h>
+
+#include <media/AudioTrack.h>
+#include <media/mediaplayer.h>
+
+#include <system/audio.h>
+
+#include "SoundPool.h"
+#include "SoundPoolThread.h"
+
+namespace android
+{
+
+int kDefaultBufferCount = 4;
+uint32_t kMaxSampleRate = 48000;
+uint32_t kDefaultSampleRate = 44100;
+uint32_t kDefaultFrameCount = 1200;
+
+SoundPool::SoundPool(int maxChannels, audio_stream_type_t streamType, int srcQuality)
+{
+ ALOGV("SoundPool constructor: maxChannels=%d, streamType=%d, srcQuality=%d",
+ maxChannels, streamType, srcQuality);
+
+ // check limits
+ mMaxChannels = maxChannels;
+ if (mMaxChannels < 1) {
+ mMaxChannels = 1;
+ }
+ else if (mMaxChannels > 32) {
+ mMaxChannels = 32;
+ }
+ ALOGW_IF(maxChannels != mMaxChannels, "App requested %d channels", maxChannels);
+
+ mQuit = false;
+ mDecodeThread = 0;
+ mStreamType = streamType;
+ mSrcQuality = srcQuality;
+ mAllocated = 0;
+ mNextSampleID = 0;
+ mNextChannelID = 0;
+
+ mCallback = 0;
+ mUserData = 0;
+
+ mChannelPool = new SoundChannel[mMaxChannels];
+ for (int i = 0; i < mMaxChannels; ++i) {
+ mChannelPool[i].init(this);
+ mChannels.push_back(&mChannelPool[i]);
+ }
+
+ // start decode thread
+ startThreads();
+}
+
+SoundPool::~SoundPool()
+{
+ ALOGV("SoundPool destructor");
+ mDecodeThread->quit();
+ quit();
+
+ Mutex::Autolock lock(&mLock);
+
+ mChannels.clear();
+ if (mChannelPool)
+ delete [] mChannelPool;
+ // clean up samples
+ ALOGV("clear samples");
+ mSamples.clear();
+
+ if (mDecodeThread)
+ delete mDecodeThread;
+}
+
+void SoundPool::addToRestartList(SoundChannel* channel)
+{
+ Mutex::Autolock lock(&mRestartLock);
+ if (!mQuit) {
+ mRestart.push_back(channel);
+ mCondition.signal();
+ }
+}
+
+void SoundPool::addToStopList(SoundChannel* channel)
+{
+ Mutex::Autolock lock(&mRestartLock);
+ if (!mQuit) {
+ mStop.push_back(channel);
+ mCondition.signal();
+ }
+}
+
+int SoundPool::beginThread(void* arg)
+{
+ SoundPool* p = (SoundPool*)arg;
+ return p->run();
+}
+
+int SoundPool::run()
+{
+ mRestartLock.lock();
+ while (!mQuit) {
+ mCondition.wait(mRestartLock);
+ ALOGV("awake");
+ if (mQuit) break;
+
+ while (!mStop.empty()) {
+ SoundChannel* channel;
+ ALOGV("Getting channel from stop list");
+ List<SoundChannel* >::iterator iter = mStop.begin();
+ channel = *iter;
+ mStop.erase(iter);
+ mRestartLock.unlock();
+ if (channel != 0) {
+ Mutex::Autolock lock(&mLock);
+ channel->stop();
+ }
+ mRestartLock.lock();
+ if (mQuit) break;
+ }
+
+ while (!mRestart.empty()) {
+ SoundChannel* channel;
+ ALOGV("Getting channel from list");
+ List<SoundChannel*>::iterator iter = mRestart.begin();
+ channel = *iter;
+ mRestart.erase(iter);
+ mRestartLock.unlock();
+ if (channel != 0) {
+ Mutex::Autolock lock(&mLock);
+ channel->nextEvent();
+ }
+ mRestartLock.lock();
+ if (mQuit) break;
+ }
+ }
+
+ mStop.clear();
+ mRestart.clear();
+ mCondition.signal();
+ mRestartLock.unlock();
+ ALOGV("goodbye");
+ return 0;
+}
+
+void SoundPool::quit()
+{
+ mRestartLock.lock();
+ mQuit = true;
+ mCondition.signal();
+ mCondition.wait(mRestartLock);
+ ALOGV("return from quit");
+ mRestartLock.unlock();
+}
+
+bool SoundPool::startThreads()
+{
+ createThreadEtc(beginThread, this, "SoundPool");
+ if (mDecodeThread == NULL)
+ mDecodeThread = new SoundPoolThread(this);
+ return mDecodeThread != NULL;
+}
+
+SoundChannel* SoundPool::findChannel(int channelID)
+{
+ for (int i = 0; i < mMaxChannels; ++i) {
+ if (mChannelPool[i].channelID() == channelID) {
+ return &mChannelPool[i];
+ }
+ }
+ return NULL;
+}
+
+SoundChannel* SoundPool::findNextChannel(int channelID)
+{
+ for (int i = 0; i < mMaxChannels; ++i) {
+ if (mChannelPool[i].nextChannelID() == channelID) {
+ return &mChannelPool[i];
+ }
+ }
+ return NULL;
+}
+
+int SoundPool::load(const char* path, int priority)
+{
+ ALOGV("load: path=%s, priority=%d", path, priority);
+ Mutex::Autolock lock(&mLock);
+ sp<Sample> sample = new Sample(++mNextSampleID, path);
+ mSamples.add(sample->sampleID(), sample);
+ doLoad(sample);
+ return sample->sampleID();
+}
+
+int SoundPool::load(int fd, int64_t offset, int64_t length, int priority)
+{
+ ALOGV("load: fd=%d, offset=%lld, length=%lld, priority=%d",
+ fd, offset, length, priority);
+ Mutex::Autolock lock(&mLock);
+ sp<Sample> sample = new Sample(++mNextSampleID, fd, offset, length);
+ mSamples.add(sample->sampleID(), sample);
+ doLoad(sample);
+ return sample->sampleID();
+}
+
+void SoundPool::doLoad(sp<Sample>& sample)
+{
+ ALOGV("doLoad: loading sample sampleID=%d", sample->sampleID());
+ sample->startLoad();
+ mDecodeThread->loadSample(sample->sampleID());
+}
+
+bool SoundPool::unload(int sampleID)
+{
+ ALOGV("unload: sampleID=%d", sampleID);
+ Mutex::Autolock lock(&mLock);
+ return mSamples.removeItem(sampleID);
+}
+
+int SoundPool::play(int sampleID, float leftVolume, float rightVolume,
+ int priority, int loop, float rate)
+{
+ ALOGV("play sampleID=%d, leftVolume=%f, rightVolume=%f, priority=%d, loop=%d, rate=%f",
+ sampleID, leftVolume, rightVolume, priority, loop, rate);
+ sp<Sample> sample;
+ SoundChannel* channel;
+ int channelID;
+
+ Mutex::Autolock lock(&mLock);
+
+ if (mQuit) {
+ return 0;
+ }
+ // is sample ready?
+ sample = findSample(sampleID);
+ if ((sample == 0) || (sample->state() != Sample::READY)) {
+ ALOGW(" sample %d not READY", sampleID);
+ return 0;
+ }
+
+ dump();
+
+ // allocate a channel
+ channel = allocateChannel_l(priority);
+
+ // no channel allocated - return 0
+ if (!channel) {
+ ALOGV("No channel allocated");
+ return 0;
+ }
+
+ channelID = ++mNextChannelID;
+
+ ALOGV("play channel %p state = %d", channel, channel->state());
+ channel->play(sample, channelID, leftVolume, rightVolume, priority, loop, rate);
+ return channelID;
+}
+
+SoundChannel* SoundPool::allocateChannel_l(int priority)
+{
+ List<SoundChannel*>::iterator iter;
+ SoundChannel* channel = NULL;
+
+ // allocate a channel
+ if (!mChannels.empty()) {
+ iter = mChannels.begin();
+ if (priority >= (*iter)->priority()) {
+ channel = *iter;
+ mChannels.erase(iter);
+ ALOGV("Allocated active channel");
+ }
+ }
+
+ // update priority and put it back in the list
+ if (channel) {
+ channel->setPriority(priority);
+ for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
+ if (priority < (*iter)->priority()) {
+ break;
+ }
+ }
+ mChannels.insert(iter, channel);
+ }
+ return channel;
+}
+
+// move a channel from its current position to the front of the list
+void SoundPool::moveToFront_l(SoundChannel* channel)
+{
+ for (List<SoundChannel*>::iterator iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
+ if (*iter == channel) {
+ mChannels.erase(iter);
+ mChannels.push_front(channel);
+ break;
+ }
+ }
+}
+
+void SoundPool::pause(int channelID)
+{
+ ALOGV("pause(%d)", channelID);
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->pause();
+ }
+}
+
+void SoundPool::autoPause()
+{
+ ALOGV("autoPause()");
+ Mutex::Autolock lock(&mLock);
+ for (int i = 0; i < mMaxChannels; ++i) {
+ SoundChannel* channel = &mChannelPool[i];
+ channel->autoPause();
+ }
+}
+
+void SoundPool::resume(int channelID)
+{
+ ALOGV("resume(%d)", channelID);
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->resume();
+ }
+}
+
+void SoundPool::autoResume()
+{
+ ALOGV("autoResume()");
+ Mutex::Autolock lock(&mLock);
+ for (int i = 0; i < mMaxChannels; ++i) {
+ SoundChannel* channel = &mChannelPool[i];
+ channel->autoResume();
+ }
+}
+
+void SoundPool::stop(int channelID)
+{
+ ALOGV("stop(%d)", channelID);
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->stop();
+ } else {
+ channel = findNextChannel(channelID);
+ if (channel)
+ channel->clearNextEvent();
+ }
+}
+
+void SoundPool::setVolume(int channelID, float leftVolume, float rightVolume)
+{
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->setVolume(leftVolume, rightVolume);
+ }
+}
+
+void SoundPool::setPriority(int channelID, int priority)
+{
+ ALOGV("setPriority(%d, %d)", channelID, priority);
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->setPriority(priority);
+ }
+}
+
+void SoundPool::setLoop(int channelID, int loop)
+{
+ ALOGV("setLoop(%d, %d)", channelID, loop);
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->setLoop(loop);
+ }
+}
+
+void SoundPool::setRate(int channelID, float rate)
+{
+ ALOGV("setRate(%d, %f)", channelID, rate);
+ Mutex::Autolock lock(&mLock);
+ SoundChannel* channel = findChannel(channelID);
+ if (channel) {
+ channel->setRate(rate);
+ }
+}
+
+// call with lock held
+void SoundPool::done_l(SoundChannel* channel)
+{
+ ALOGV("done_l(%d)", channel->channelID());
+ // if "stolen", play next event
+ if (channel->nextChannelID() != 0) {
+ ALOGV("add to restart list");
+ addToRestartList(channel);
+ }
+
+ // return to idle state
+ else {
+ ALOGV("move to front");
+ moveToFront_l(channel);
+ }
+}
+
+void SoundPool::setCallback(SoundPoolCallback* callback, void* user)
+{
+ Mutex::Autolock lock(&mCallbackLock);
+ mCallback = callback;
+ mUserData = user;
+}
+
+void SoundPool::notify(SoundPoolEvent event)
+{
+ Mutex::Autolock lock(&mCallbackLock);
+ if (mCallback != NULL) {
+ mCallback(event, this, mUserData);
+ }
+}
+
+void SoundPool::dump()
+{
+ for (int i = 0; i < mMaxChannels; ++i) {
+ mChannelPool[i].dump();
+ }
+}
+
+
+Sample::Sample(int sampleID, const char* url)
+{
+ init();
+ mSampleID = sampleID;
+ mUrl = strdup(url);
+ ALOGV("create sampleID=%d, url=%s", mSampleID, mUrl);
+}
+
+Sample::Sample(int sampleID, int fd, int64_t offset, int64_t length)
+{
+ init();
+ mSampleID = sampleID;
+ mFd = dup(fd);
+ mOffset = offset;
+ mLength = length;
+ ALOGV("create sampleID=%d, fd=%d, offset=%lld, length=%lld", mSampleID, mFd, mLength, mOffset);
+}
+
+void Sample::init()
+{
+ mData = 0;
+ mSize = 0;
+ mRefCount = 0;
+ mSampleID = 0;
+ mState = UNLOADED;
+ mFd = -1;
+ mOffset = 0;
+ mLength = 0;
+ mUrl = 0;
+}
+
+Sample::~Sample()
+{
+ ALOGV("Sample::destructor sampleID=%d, fd=%d", mSampleID, mFd);
+ if (mFd > 0) {
+ ALOGV("close(%d)", mFd);
+ ::close(mFd);
+ }
+ mData.clear();
+ delete mUrl;
+}
+
+status_t Sample::doLoad()
+{
+ uint32_t sampleRate;
+ int numChannels;
+ audio_format_t format;
+ sp<IMemory> p;
+ ALOGV("Start decode");
+ if (mUrl) {
+ p = MediaPlayer::decode(mUrl, &sampleRate, &numChannels, &format);
+ } else {
+ p = MediaPlayer::decode(mFd, mOffset, mLength, &sampleRate, &numChannels, &format);
+ ALOGV("close(%d)", mFd);
+ ::close(mFd);
+ mFd = -1;
+ }
+ if (p == 0) {
+ ALOGE("Unable to load sample: %s", mUrl);
+ return -1;
+ }
+ ALOGV("pointer = %p, size = %u, sampleRate = %u, numChannels = %d",
+ p->pointer(), p->size(), sampleRate, numChannels);
+
+ if (sampleRate > kMaxSampleRate) {
+ ALOGE("Sample rate (%u) out of range", sampleRate);
+ return - 1;
+ }
+
+ if ((numChannels < 1) || (numChannels > 2)) {
+ ALOGE("Sample channel count (%d) out of range", numChannels);
+ return - 1;
+ }
+
+ //_dumpBuffer(p->pointer(), p->size());
+ uint8_t* q = static_cast<uint8_t*>(p->pointer()) + p->size() - 10;
+ //_dumpBuffer(q, 10, 10, false);
+
+ mData = p;
+ mSize = p->size();
+ mSampleRate = sampleRate;
+ mNumChannels = numChannels;
+ mFormat = format;
+ mState = READY;
+ return 0;
+}
+
+
+void SoundChannel::init(SoundPool* soundPool)
+{
+ mSoundPool = soundPool;
+}
+
+// call with sound pool lock held
+void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftVolume,
+ float rightVolume, int priority, int loop, float rate)
+{
+ AudioTrack* oldTrack;
+ AudioTrack* newTrack;
+ status_t status;
+
+ { // scope for the lock
+ Mutex::Autolock lock(&mLock);
+
+ ALOGV("SoundChannel::play %p: sampleID=%d, channelID=%d, leftVolume=%f, rightVolume=%f,"
+ " priority=%d, loop=%d, rate=%f",
+ this, sample->sampleID(), nextChannelID, leftVolume, rightVolume,
+ priority, loop, rate);
+
+ // if not idle, this voice is being stolen
+ if (mState != IDLE) {
+ ALOGV("channel %d stolen - event queued for channel %d", channelID(), nextChannelID);
+ mNextEvent.set(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
+ stop_l();
+ return;
+ }
+
+ // initialize track
+ int afFrameCount;
+ int afSampleRate;
+ audio_stream_type_t streamType = mSoundPool->streamType();
+ if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
+ afFrameCount = kDefaultFrameCount;
+ }
+ if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
+ afSampleRate = kDefaultSampleRate;
+ }
+ int numChannels = sample->numChannels();
+ uint32_t sampleRate = uint32_t(float(sample->sampleRate()) * rate + 0.5);
+ uint32_t totalFrames = (kDefaultBufferCount * afFrameCount * sampleRate) / afSampleRate;
+ uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
+ uint32_t frameCount = 0;
+
+ if (loop) {
+ frameCount = sample->size()/numChannels/
+ ((sample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
+ }
+
+#ifndef USE_SHARED_MEM_BUFFER
+ // Ensure minimum audio buffer size in case of short looped sample
+ if(frameCount < totalFrames) {
+ frameCount = totalFrames;
+ }
+#endif
+
+ // mToggle toggles each time a track is started on a given channel.
+ // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
+ // as callback user data. This enables the detection of callbacks received from the old
+ // audio track while the new one is being started and avoids processing them with
+ // wrong audio audio buffer size (mAudioBufferSize)
+ unsigned long toggle = mToggle ^ 1;
+ void *userData = (void *)((unsigned long)this | toggle);
+ uint32_t channels = (numChannels == 2) ?
+ AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO;
+
+ // do not create a new audio track if current track is compatible with sample parameters
+#ifdef USE_SHARED_MEM_BUFFER
+ newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
+ channels, sample->getIMemory(), AUDIO_POLICY_OUTPUT_FLAG_NONE, callback, userData);
+#else
+ newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
+ channels, frameCount, AUDIO_POLICY_OUTPUT_FLAG_NONE, callback, userData,
+ bufferFrames);
+#endif
+ oldTrack = mAudioTrack;
+ status = newTrack->initCheck();
+ if (status != NO_ERROR) {
+ ALOGE("Error creating AudioTrack");
+ goto exit;
+ }
+ ALOGV("setVolume %p", newTrack);
+ newTrack->setVolume(leftVolume, rightVolume);
+ newTrack->setLoop(0, frameCount, loop);
+
+ // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
+ mToggle = toggle;
+ mAudioTrack = newTrack;
+ mPos = 0;
+ mSample = sample;
+ mChannelID = nextChannelID;
+ mPriority = priority;
+ mLoop = loop;
+ mLeftVolume = leftVolume;
+ mRightVolume = rightVolume;
+ mNumChannels = numChannels;
+ mRate = rate;
+ clearNextEvent();
+ mState = PLAYING;
+ mAudioTrack->start();
+ mAudioBufferSize = newTrack->frameCount()*newTrack->frameSize();
+ }
+
+exit:
+ ALOGV("delete oldTrack %p", oldTrack);
+ delete oldTrack;
+ if (status != NO_ERROR) {
+ delete newTrack;
+ mAudioTrack = NULL;
+ }
+}
+
+void SoundChannel::nextEvent()
+{
+ sp<Sample> sample;
+ int nextChannelID;
+ float leftVolume;
+ float rightVolume;
+ int priority;
+ int loop;
+ float rate;
+
+ // check for valid event
+ {
+ Mutex::Autolock lock(&mLock);
+ nextChannelID = mNextEvent.channelID();
+ if (nextChannelID == 0) {
+ ALOGV("stolen channel has no event");
+ return;
+ }
+
+ sample = mNextEvent.sample();
+ leftVolume = mNextEvent.leftVolume();
+ rightVolume = mNextEvent.rightVolume();
+ priority = mNextEvent.priority();
+ loop = mNextEvent.loop();
+ rate = mNextEvent.rate();
+ }
+
+ ALOGV("Starting stolen channel %d -> %d", channelID(), nextChannelID);
+ play(sample, nextChannelID, leftVolume, rightVolume, priority, loop, rate);
+}
+
+void SoundChannel::callback(int event, void* user, void *info)
+{
+ SoundChannel* channel = static_cast<SoundChannel*>((void *)((unsigned long)user & ~1));
+
+ channel->process(event, info, (unsigned long)user & 1);
+}
+
+void SoundChannel::process(int event, void *info, unsigned long toggle)
+{
+ //ALOGV("process(%d)", mChannelID);
+
+ Mutex::Autolock lock(&mLock);
+
+ AudioTrack::Buffer* b = NULL;
+ if (event == AudioTrack::EVENT_MORE_DATA) {
+ b = static_cast<AudioTrack::Buffer *>(info);
+ }
+
+ if (mToggle != toggle) {
+ ALOGV("process wrong toggle %p channel %d", this, mChannelID);
+ if (b != NULL) {
+ b->size = 0;
+ }
+ return;
+ }
+
+ sp<Sample> sample = mSample;
+
+// ALOGV("SoundChannel::process event %d", event);
+
+ if (event == AudioTrack::EVENT_MORE_DATA) {
+
+ // check for stop state
+ if (b->size == 0) return;
+
+ if (mState == IDLE) {
+ b->size = 0;
+ return;
+ }
+
+ if (sample != 0) {
+ // fill buffer
+ uint8_t* q = (uint8_t*) b->i8;
+ size_t count = 0;
+
+ if (mPos < (int)sample->size()) {
+ uint8_t* p = sample->data() + mPos;
+ count = sample->size() - mPos;
+ if (count > b->size) {
+ count = b->size;
+ }
+ memcpy(q, p, count);
+// ALOGV("fill: q=%p, p=%p, mPos=%u, b->size=%u, count=%d", q, p, mPos, b->size, count);
+ } else if (mPos < mAudioBufferSize) {
+ count = mAudioBufferSize - mPos;
+ if (count > b->size) {
+ count = b->size;
+ }
+ memset(q, 0, count);
+// ALOGV("fill extra: q=%p, mPos=%u, b->size=%u, count=%d", q, mPos, b->size, count);
+ }
+
+ mPos += count;
+ b->size = count;
+ //ALOGV("buffer=%p, [0]=%d", b->i16, b->i16[0]);
+ }
+ } else if (event == AudioTrack::EVENT_UNDERRUN) {
+ ALOGV("process %p channel %d EVENT_UNDERRUN", this, mChannelID);
+ mSoundPool->addToStopList(this);
+ } else if (event == AudioTrack::EVENT_LOOP_END) {
+ ALOGV("End loop %p channel %d count %d", this, mChannelID, *(int *)info);
+ }
+}
+
+
+// call with lock held
+bool SoundChannel::doStop_l()
+{
+ if (mState != IDLE) {
+ setVolume_l(0, 0);
+ ALOGV("stop");
+ mAudioTrack->stop();
+ mSample.clear();
+ mState = IDLE;
+ mPriority = IDLE_PRIORITY;
+ return true;
+ }
+ return false;
+}
+
+// call with lock held and sound pool lock held
+void SoundChannel::stop_l()
+{
+ if (doStop_l()) {
+ mSoundPool->done_l(this);
+ }
+}
+
+// call with sound pool lock held
+void SoundChannel::stop()
+{
+ bool stopped;
+ {
+ Mutex::Autolock lock(&mLock);
+ stopped = doStop_l();
+ }
+
+ if (stopped) {
+ mSoundPool->done_l(this);
+ }
+}
+
+//FIXME: Pause is a little broken right now
+void SoundChannel::pause()
+{
+ Mutex::Autolock lock(&mLock);
+ if (mState == PLAYING) {
+ ALOGV("pause track");
+ mState = PAUSED;
+ mAudioTrack->pause();
+ }
+}
+
+void SoundChannel::autoPause()
+{
+ Mutex::Autolock lock(&mLock);
+ if (mState == PLAYING) {
+ ALOGV("pause track");
+ mState = PAUSED;
+ mAutoPaused = true;
+ mAudioTrack->pause();
+ }
+}
+
+void SoundChannel::resume()
+{
+ Mutex::Autolock lock(&mLock);
+ if (mState == PAUSED) {
+ ALOGV("resume track");
+ mState = PLAYING;
+ mAutoPaused = false;
+ mAudioTrack->start();
+ }
+}
+
+void SoundChannel::autoResume()
+{
+ Mutex::Autolock lock(&mLock);
+ if (mAutoPaused && (mState == PAUSED)) {
+ ALOGV("resume track");
+ mState = PLAYING;
+ mAutoPaused = false;
+ mAudioTrack->start();
+ }
+}
+
+void SoundChannel::setRate(float rate)
+{
+ Mutex::Autolock lock(&mLock);
+ if (mAudioTrack != NULL && mSample != 0) {
+ uint32_t sampleRate = uint32_t(float(mSample->sampleRate()) * rate + 0.5);
+ mAudioTrack->setSampleRate(sampleRate);
+ mRate = rate;
+ }
+}
+
+// call with lock held
+void SoundChannel::setVolume_l(float leftVolume, float rightVolume)
+{
+ mLeftVolume = leftVolume;
+ mRightVolume = rightVolume;
+ if (mAudioTrack != NULL)
+ mAudioTrack->setVolume(leftVolume, rightVolume);
+}
+
+void SoundChannel::setVolume(float leftVolume, float rightVolume)
+{
+ Mutex::Autolock lock(&mLock);
+ setVolume_l(leftVolume, rightVolume);
+}
+
+void SoundChannel::setLoop(int loop)
+{
+ Mutex::Autolock lock(&mLock);
+ if (mAudioTrack != NULL && mSample != 0) {
+ uint32_t loopEnd = mSample->size()/mNumChannels/
+ ((mSample->format() == AUDIO_FORMAT_PCM_16_BIT) ? sizeof(int16_t) : sizeof(uint8_t));
+ mAudioTrack->setLoop(0, loopEnd, loop);
+ mLoop = loop;
+ }
+}
+
+SoundChannel::~SoundChannel()
+{
+ ALOGV("SoundChannel destructor %p", this);
+ {
+ Mutex::Autolock lock(&mLock);
+ clearNextEvent();
+ doStop_l();
+ }
+ // do not call AudioTrack destructor with mLock held as it will wait for the AudioTrack
+ // callback thread to exit which may need to execute process() and acquire the mLock.
+ delete mAudioTrack;
+}
+
+void SoundChannel::dump()
+{
+ ALOGV("mState = %d mChannelID=%d, mNumChannels=%d, mPos = %d, mPriority=%d, mLoop=%d",
+ mState, mChannelID, mNumChannels, mPos, mPriority, mLoop);
+}
+
+void SoundEvent::set(const sp<Sample>& sample, int channelID, float leftVolume,
+ float rightVolume, int priority, int loop, float rate)
+{
+ mSample = sample;
+ mChannelID = channelID;
+ mLeftVolume = leftVolume;
+ mRightVolume = rightVolume;
+ mPriority = priority;
+ mLoop = loop;
+ mRate =rate;
+}
+
+} // end namespace android
diff --git a/media/libmedia/SoundPool.h b/media/libmedia/SoundPool.h
new file mode 100644
index 0000000..002b045
--- /dev/null
+++ b/media/libmedia/SoundPool.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 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 SOUNDPOOL_H_
+#define SOUNDPOOL_H_
+
+#include <utils/threads.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <media/AudioTrack.h>
+
+namespace android {
+
+static const int IDLE_PRIORITY = -1;
+
+// forward declarations
+class SoundEvent;
+class SoundPoolThread;
+class SoundPool;
+
+// for queued events
+class SoundPoolEvent {
+public:
+ SoundPoolEvent(int msg, int arg1=0, int arg2=0) :
+ mMsg(msg), mArg1(arg1), mArg2(arg2) {}
+ int mMsg;
+ int mArg1;
+ int mArg2;
+ enum MessageType { INVALID, SAMPLE_LOADED };
+};
+
+// callback function prototype
+typedef void SoundPoolCallback(SoundPoolEvent event, SoundPool* soundPool, void* user);
+
+// tracks samples used by application
+class Sample : public RefBase {
+public:
+ enum sample_state { UNLOADED, LOADING, READY, UNLOADING };
+ Sample(int sampleID, const char* url);
+ Sample(int sampleID, int fd, int64_t offset, int64_t length);
+ ~Sample();
+ int sampleID() { return mSampleID; }
+ int numChannels() { return mNumChannels; }
+ int sampleRate() { return mSampleRate; }
+ audio_format_t format() { return mFormat; }
+ size_t size() { return mSize; }
+ int state() { return mState; }
+ uint8_t* data() { return static_cast<uint8_t*>(mData->pointer()); }
+ status_t doLoad();
+ void startLoad() { mState = LOADING; }
+ sp<IMemory> getIMemory() { return mData; }
+
+ // hack
+ void init(int numChannels, int sampleRate, audio_format_t format, size_t size, sp<IMemory> data ) {
+ mNumChannels = numChannels; mSampleRate = sampleRate; mFormat = format; mSize = size; mData = data; }
+
+private:
+ void init();
+
+ size_t mSize;
+ volatile int32_t mRefCount;
+ uint16_t mSampleID;
+ uint16_t mSampleRate;
+ uint8_t mState : 3;
+ uint8_t mNumChannels : 2;
+ audio_format_t mFormat;
+ int mFd;
+ int64_t mOffset;
+ int64_t mLength;
+ char* mUrl;
+ sp<IMemory> mData;
+};
+
+// stores pending events for stolen channels
+class SoundEvent
+{
+public:
+ SoundEvent() : mChannelID(0), mLeftVolume(0), mRightVolume(0),
+ mPriority(IDLE_PRIORITY), mLoop(0), mRate(0) {}
+ void set(const sp<Sample>& sample, int channelID, float leftVolume,
+ float rightVolume, int priority, int loop, float rate);
+ sp<Sample> sample() { return mSample; }
+ int channelID() { return mChannelID; }
+ float leftVolume() { return mLeftVolume; }
+ float rightVolume() { return mRightVolume; }
+ int priority() { return mPriority; }
+ int loop() { return mLoop; }
+ float rate() { return mRate; }
+ void clear() { mChannelID = 0; mSample.clear(); }
+
+protected:
+ sp<Sample> mSample;
+ int mChannelID;
+ float mLeftVolume;
+ float mRightVolume;
+ int mPriority;
+ int mLoop;
+ float mRate;
+};
+
+// for channels aka AudioTracks
+class SoundChannel : public SoundEvent {
+public:
+ enum state { IDLE, RESUMING, STOPPING, PAUSED, PLAYING };
+ SoundChannel() : mAudioTrack(NULL), mState(IDLE), mNumChannels(1),
+ mPos(0), mToggle(0), mAutoPaused(false) {}
+ ~SoundChannel();
+ void init(SoundPool* soundPool);
+ void play(const sp<Sample>& sample, int channelID, float leftVolume, float rightVolume,
+ int priority, int loop, float rate);
+ void setVolume_l(float leftVolume, float rightVolume);
+ void setVolume(float leftVolume, float rightVolume);
+ void stop_l();
+ void stop();
+ void pause();
+ void autoPause();
+ void resume();
+ void autoResume();
+ void setRate(float rate);
+ int state() { return mState; }
+ void setPriority(int priority) { mPriority = priority; }
+ void setLoop(int loop);
+ int numChannels() { return mNumChannels; }
+ void clearNextEvent() { mNextEvent.clear(); }
+ void nextEvent();
+ int nextChannelID() { return mNextEvent.channelID(); }
+ void dump();
+
+private:
+ static void callback(int event, void* user, void *info);
+ void process(int event, void *info, unsigned long toggle);
+ bool doStop_l();
+
+ SoundPool* mSoundPool;
+ AudioTrack* mAudioTrack;
+ SoundEvent mNextEvent;
+ Mutex mLock;
+ int mState;
+ int mNumChannels;
+ int mPos;
+ int mAudioBufferSize;
+ unsigned long mToggle;
+ bool mAutoPaused;
+};
+
+// application object for managing a pool of sounds
+class SoundPool {
+ friend class SoundPoolThread;
+ friend class SoundChannel;
+public:
+ SoundPool(int maxChannels, audio_stream_type_t streamType, int srcQuality);
+ ~SoundPool();
+ int load(const char* url, int priority);
+ int load(int fd, int64_t offset, int64_t length, int priority);
+ bool unload(int sampleID);
+ int play(int sampleID, float leftVolume, float rightVolume, int priority,
+ int loop, float rate);
+ void pause(int channelID);
+ void autoPause();
+ void resume(int channelID);
+ void autoResume();
+ void stop(int channelID);
+ void setVolume(int channelID, float leftVolume, float rightVolume);
+ void setPriority(int channelID, int priority);
+ void setLoop(int channelID, int loop);
+ void setRate(int channelID, float rate);
+ audio_stream_type_t streamType() const { return mStreamType; }
+ int srcQuality() const { return mSrcQuality; }
+
+ // called from SoundPoolThread
+ void sampleLoaded(int sampleID);
+
+ // called from AudioTrack thread
+ void done_l(SoundChannel* channel);
+
+ // callback function
+ void setCallback(SoundPoolCallback* callback, void* user);
+ void* getUserData() { return mUserData; }
+
+private:
+ SoundPool() {} // no default constructor
+ bool startThreads();
+ void doLoad(sp<Sample>& sample);
+ sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); }
+ SoundChannel* findChannel (int channelID);
+ SoundChannel* findNextChannel (int channelID);
+ SoundChannel* allocateChannel_l(int priority);
+ void moveToFront_l(SoundChannel* channel);
+ void notify(SoundPoolEvent event);
+ void dump();
+
+ // restart thread
+ void addToRestartList(SoundChannel* channel);
+ void addToStopList(SoundChannel* channel);
+ static int beginThread(void* arg);
+ int run();
+ void quit();
+
+ Mutex mLock;
+ Mutex mRestartLock;
+ Condition mCondition;
+ SoundPoolThread* mDecodeThread;
+ SoundChannel* mChannelPool;
+ List<SoundChannel*> mChannels;
+ List<SoundChannel*> mRestart;
+ List<SoundChannel*> mStop;
+ DefaultKeyedVector< int, sp<Sample> > mSamples;
+ int mMaxChannels;
+ audio_stream_type_t mStreamType;
+ int mSrcQuality;
+ int mAllocated;
+ int mNextSampleID;
+ int mNextChannelID;
+ bool mQuit;
+
+ // callback
+ Mutex mCallbackLock;
+ SoundPoolCallback* mCallback;
+ void* mUserData;
+};
+
+} // end namespace android
+
+#endif /*SOUNDPOOL_H_*/
diff --git a/media/libmedia/SoundPoolThread.cpp b/media/libmedia/SoundPoolThread.cpp
new file mode 100644
index 0000000..ba3b482
--- /dev/null
+++ b/media/libmedia/SoundPoolThread.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 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 "SoundPoolThread"
+#include "utils/Log.h"
+
+#include "SoundPoolThread.h"
+
+namespace android {
+
+void SoundPoolThread::write(SoundPoolMsg msg) {
+ Mutex::Autolock lock(&mLock);
+ while (mMsgQueue.size() >= maxMessages) {
+ mCondition.wait(mLock);
+ }
+
+ // if thread is quitting, don't add to queue
+ if (mRunning) {
+ mMsgQueue.push(msg);
+ mCondition.signal();
+ }
+}
+
+const SoundPoolMsg SoundPoolThread::read() {
+ Mutex::Autolock lock(&mLock);
+ while (mMsgQueue.size() == 0) {
+ mCondition.wait(mLock);
+ }
+ SoundPoolMsg msg = mMsgQueue[0];
+ mMsgQueue.removeAt(0);
+ mCondition.signal();
+ return msg;
+}
+
+void SoundPoolThread::quit() {
+ Mutex::Autolock lock(&mLock);
+ if (mRunning) {
+ mRunning = false;
+ mMsgQueue.clear();
+ mMsgQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0));
+ mCondition.signal();
+ mCondition.wait(mLock);
+ }
+ ALOGV("return from quit");
+}
+
+SoundPoolThread::SoundPoolThread(SoundPool* soundPool) :
+ mSoundPool(soundPool)
+{
+ mMsgQueue.setCapacity(maxMessages);
+ if (createThreadEtc(beginThread, this, "SoundPoolThread")) {
+ mRunning = true;
+ }
+}
+
+SoundPoolThread::~SoundPoolThread()
+{
+ quit();
+}
+
+int SoundPoolThread::beginThread(void* arg) {
+ ALOGV("beginThread");
+ SoundPoolThread* soundPoolThread = (SoundPoolThread*)arg;
+ return soundPoolThread->run();
+}
+
+int SoundPoolThread::run() {
+ ALOGV("run");
+ for (;;) {
+ SoundPoolMsg msg = read();
+ ALOGV("Got message m=%d, mData=%d", msg.mMessageType, msg.mData);
+ switch (msg.mMessageType) {
+ case SoundPoolMsg::KILL:
+ ALOGV("goodbye");
+ return NO_ERROR;
+ case SoundPoolMsg::LOAD_SAMPLE:
+ doLoadSample(msg.mData);
+ break;
+ default:
+ ALOGW("run: Unrecognized message %d\n",
+ msg.mMessageType);
+ break;
+ }
+ }
+}
+
+void SoundPoolThread::loadSample(int sampleID) {
+ write(SoundPoolMsg(SoundPoolMsg::LOAD_SAMPLE, sampleID));
+}
+
+void SoundPoolThread::doLoadSample(int sampleID) {
+ sp <Sample> sample = mSoundPool->findSample(sampleID);
+ status_t status = -1;
+ if (sample != 0) {
+ status = sample->doLoad();
+ }
+ mSoundPool->notify(SoundPoolEvent(SoundPoolEvent::SAMPLE_LOADED, sampleID, status));
+}
+
+} // end namespace android
diff --git a/media/libmedia/SoundPoolThread.h b/media/libmedia/SoundPoolThread.h
new file mode 100644
index 0000000..d388388
--- /dev/null
+++ b/media/libmedia/SoundPoolThread.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 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 SOUNDPOOLTHREAD_H_
+#define SOUNDPOOLTHREAD_H_
+
+#include <utils/threads.h>
+#include <utils/Vector.h>
+#include <media/AudioTrack.h>
+
+#include "SoundPool.h"
+
+namespace android {
+
+class SoundPoolMsg {
+public:
+ enum MessageType { INVALID, KILL, LOAD_SAMPLE };
+ SoundPoolMsg() : mMessageType(INVALID), mData(0) {}
+ SoundPoolMsg(MessageType MessageType, int data) :
+ mMessageType(MessageType), mData(data) {}
+ uint16_t mMessageType;
+ uint16_t mData;
+};
+
+/*
+ * This class handles background requests from the SoundPool
+ */
+class SoundPoolThread {
+public:
+ SoundPoolThread(SoundPool* SoundPool);
+ ~SoundPoolThread();
+ void loadSample(int sampleID);
+ void quit();
+ void write(SoundPoolMsg msg);
+
+private:
+ static const size_t maxMessages = 5;
+
+ static int beginThread(void* arg);
+ int run();
+ void doLoadSample(int sampleID);
+ const SoundPoolMsg read();
+
+ Mutex mLock;
+ Condition mCondition;
+ Vector<SoundPoolMsg> mMsgQueue;
+ SoundPool* mSoundPool;
+ bool mRunning;
+};
+
+} // end namespace android
+
+#endif /*SOUNDPOOLTHREAD_H_*/
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
new file mode 100644
index 0000000..717d316
--- /dev/null
+++ b/media/libmedia/ToneGenerator.cpp
@@ -0,0 +1,1580 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "ToneGenerator"
+#include <utils/threads.h>
+
+#include <stdio.h>
+#include <math.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+#include <cutils/properties.h>
+#include "media/ToneGenerator.h"
+
+
+namespace android {
+
+
+// Descriptors for all available tones (See ToneGenerator::ToneDescriptor class declaration for details)
+const ToneGenerator::ToneDescriptor ToneGenerator::sToneDescriptors[] = {
+ { segments: {{ duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 941, 0 }, 0, 0},
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_0
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 697, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_1
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 697, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_2
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 697, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_3
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 770, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_4
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 770, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_5
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 770, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_6
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 852, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_7
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 852, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_8
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 852, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_9
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 941, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_S
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 941, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_P
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 697, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_A
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 770, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_B
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 852, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_C
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 941, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_DTMF_D
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 425, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_DIAL
+ { segments: { { duration: 500 , waveFreq: { 425, 0 }, 0, 0},
+ { duration: 500, waveFreq: { 0 }, 0, 0},
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_BUSY
+ { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_CONGESTION
+ { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_SUP_RADIO_ACK
+ { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0},
+ { duration: 200, waveFreq: { 0 }, 0, 0},
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 2,
+ repeatSegment: 0 }, // TONE_SUP_RADIO_NOTAVAIL
+ { segments: { { duration: 330, waveFreq: { 950, 1400, 1800, 0 }, 0, 0},
+ { duration: 1000, waveFreq: { 0 }, 0, 0},
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_ERROR
+ { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
+ { duration: 600, waveFreq: { 0 }, 0, 0 },
+ { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
+ { duration: 3000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_CALL_WAITING
+ { segments: { { duration: 1000, waveFreq: { 425, 0 }, 0, 0 },
+ { duration: 4000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_RINGTONE
+ { segments: { { duration: 40, waveFreq: { 400, 1200, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_PROP_BEEP
+ { segments: { { duration: 100, waveFreq: { 1200, 0 }, 0, 0 },
+ { duration: 100, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 1,
+ repeatSegment: 0 }, // TONE_PROP_ACK
+ { segments: { { duration: 400, waveFreq: { 300, 400, 500, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_PROP_NACK
+ { segments: { { duration: 200, waveFreq: { 400, 1200, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_PROP_PROMPT
+ { segments: { { duration: 40, waveFreq: { 400, 1200, 0 }, 0, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 40, waveFreq: { 400, 1200, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_PROP_BEEP2
+ { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
+ { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_SUP_INTERCEPT
+ { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
+ { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 7,
+ repeatSegment: 0 }, // TONE_SUP_INTERCEPT_ABBREV
+ { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
+ { duration: 250, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 7,
+ repeatSegment: 0 }, // TONE_SUP_CONGESTION_ABBREV
+ { segments: { { duration: 100, waveFreq: { 350, 440, 0 }, 0, 0 },
+ { duration: 100, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 2,
+ repeatSegment: 0 }, // TONE_SUP_CONFIRM
+ { segments: { { duration: 100, waveFreq: { 480, 0 }, 0, 0 },
+ { duration: 100, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 3,
+ repeatSegment: 0 }, // TONE_SUP_PIP
+ { segments: {{ duration: ToneGenerator::TONEGEN_INF, waveFreq: { 425, 0 }, 0, 0},
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_DIAL_TONE_LITE
+ { segments: { { duration: 2000, waveFreq: { 440, 480, 0 }, 0, 0 },
+ { duration: 4000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_NETWORK_USA_RINGBACK
+ { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
+ { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_INTERCEPT
+ { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
+ { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_ABBR_INTERCEPT
+ { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
+ { duration: 250, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_REORDER
+ { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
+ { duration: 250, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 7,
+ repeatSegment: 0 }, // TONE_CDMA_ABBR_REORDER
+ { segments: { { duration: 500, waveFreq: { 480, 620, 0 }, 0, 0 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_NETWORK_BUSY
+ { segments: { { duration: 100, waveFreq: { 350, 440, 0 }, 0, 0 },
+ { duration: 100, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 2,
+ repeatSegment: 0 }, // TONE_CDMA_CONFIRM
+ { segments: { { duration: 500, waveFreq: { 660, 1000, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_ANSWER
+ { segments: { { duration: 300, waveFreq: { 440, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_NETWORK_CALLWAITING
+ { segments: { { duration: 100, waveFreq: { 480, 0 }, 0, 0 },
+ { duration: 100, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 3,
+ repeatSegment: 0 }, // TONE_CDMA_PIP
+
+ { segments: { { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
+ { duration: 64, waveFreq: { 2556, 0}, 19, 0},
+ { duration: 32, waveFreq: { 2091, 0}, 0, 0},
+ { duration: 48, waveFreq: { 2556, 0}, 0, 0},
+ { duration: 4000, waveFreq: { 0 }, 0, 0},
+ { duration: 0, waveFreq: { 0 }, 0, 0}},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL
+ { segments: { { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
+ { duration: 64, waveFreq: { 2556, 0}, 7, 0 },
+ { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
+ { duration: 400, waveFreq: { 0 }, 0, 0 },
+ { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
+ { duration: 64, waveFreq: { 2556, 0}, 7, 4 },
+ { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
+ { duration: 4000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP
+ { segments: { { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
+ { duration: 64, waveFreq: { 2556, 0}, 3, 0 },
+ { duration: 16, waveFreq: { 2091, 0}, 0, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
+ { duration: 64, waveFreq: { 2556, 0}, 3, 4 },
+ { duration: 16, waveFreq: { 2091, 0}, 0, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI
+ { segments: { { duration: 0, waveFreq: { 0 }, 0, 0} },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_PAT3
+ { segments: { { duration: 32, waveFreq: { 2091, 0 }, 0, 0 },
+ { duration: 64, waveFreq: { 2556, 0 }, 4, 0 },
+ { duration: 20, waveFreq: { 2091, 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 } , 0, 0 } },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING
+ { segments: { { duration: 0, waveFreq: { 0 }, 0, 0} },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_PAT5
+ { segments: { { duration: 0, waveFreq: { 0 }, 0, 0} },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_PAT6
+ { segments: { { duration: 0, waveFreq: { 0 }, 0, 0} },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_CALL_SIGNAL_ISDN_PAT7
+
+ { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 39, 0 },
+ { duration: 4000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_HIGH_L
+ { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 39, 0 },
+ { duration: 4000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_MED_L
+ { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 39, 0 },
+ { duration: 4000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_LOW_L
+ { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 15, 0 },
+ { duration: 400, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_HIGH_SS
+ { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 15, 0 },
+ { duration: 400, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_MED_SS
+ { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 15, 0 },
+ { duration: 400, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_LOW_SS
+ { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 15, 6 },
+ { duration: 4000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_HIGH_SSL
+ { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 15, 6 },
+ { duration: 4000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_MED_SSL
+ { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 15, 6 },
+ { duration: 4000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_LOW_SSL
+ { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 19, 0 },
+ { duration: 1000, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 19, 3 },
+ { duration: 3000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_HIGH_SS_2
+ { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 19, 0 },
+ { duration: 1000, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 19, 3 },
+ { duration: 3000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_MED_SS_2
+ { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 19, 0 },
+ { duration: 1000, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 19, 3 },
+ { duration: 3000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_LOW_SS_2
+ { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 9, 0 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 19, 3 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 9, 6 },
+ { duration: 3000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_HIGH_SLS
+ { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 9, 0 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 19, 3 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 9, 6 },
+ { duration: 3000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_MED_SLS
+ { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 9, 0 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 19, 3 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 9, 6 },
+ { duration: 3000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_LOW_SLS
+ { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 9, 0 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 9, 3 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 9, 6 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 9, 9 },
+ { duration: 2500, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_HIGH_S_X4
+ { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 9, 0 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 9, 3 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 9, 6 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 9, 9 },
+ { duration: 2500, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_MED_S_X4
+ { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 9, 0 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 9, 3 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 9, 6 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 9, 9 },
+ { duration: 2500, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_LOW_S_X4
+ { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 19, 0 },
+ { duration: 2000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_HIGH_PBX_L
+ { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 19, 0 },
+ { duration: 2000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_MED_PBX_L
+ { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 19, 0 },
+ { duration: 2000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_LOW_PBX_L
+ { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
+ { duration: 2000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_HIGH_PBX_SS
+ { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
+ { duration: 2000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_MED_PBX_SS
+ { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
+ { duration: 2000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_LOW_PBX_SS
+ { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 15, 6 },
+ { duration: 1000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_HIGH_PBX_SSL
+ { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 15, 6 },
+ { duration: 1000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_MED_PBX_SSL
+ { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 15, 6 },
+ { duration: 1000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_LOW_PBX_SSL
+ { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 15, 3 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 7, 6 },
+ { duration: 1000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_HIGH_PBX_SLS
+ { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 15, 3 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 7, 6 },
+ { duration: 1000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_MED_PBX_SLS
+ { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 15, 3 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 7, 6 },
+ { duration: 1000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_LOW_PBX_SLS
+ { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 7, 6 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 4000, 0 }, 7, 9 },
+ { duration: 800, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_HIGH_PBX_S_X4
+ { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 7, 6 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 2900, 0 }, 7, 9 },
+ { duration: 800, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_MED_PBX_S_X4
+ { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 7, 6 },
+ { duration: 200, waveFreq: { 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+ { duration: 25, waveFreq: { 1450, 0 }, 7, 9 },
+ { duration: 800, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_LOW_PBX_S_X4
+
+ { segments: { { duration: 62, waveFreq: { 1109, 0 }, 0, 0 },
+ { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
+ { duration: 62, waveFreq: { 740, 0 }, 0, 0 },
+ { duration: 62, waveFreq: { 622, 0 }, 0, 0 },
+ { duration: 62, waveFreq: { 1109, 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_ALERT_NETWORK_LITE
+ { segments: { { duration: 62, waveFreq: { 1245, 0 }, 0, 0 },
+ { duration: 62, waveFreq: { 659, 0 }, 2, 0 },
+ { duration: 62, waveFreq: { 1245, 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_ALERT_AUTOREDIAL_LITE
+ { segments: { { duration: 400, waveFreq: { 1150, 770, 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_ONE_MIN_BEEP
+ { segments: { { duration: 120, waveFreq: { 941, 1477, 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_KEYPAD_VOLUME_KEY_LITE
+ { segments: { { duration: 375, waveFreq: { 587, 0 }, 0, 0 },
+ { duration: 125, waveFreq: { 1175, 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_PRESSHOLDKEY_LITE
+ { segments: { { duration: 62, waveFreq: { 587, 0 }, 0, 0 },
+ { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
+ { duration: 62, waveFreq: { 831, 0 }, 0, 0 },
+ { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
+ { duration: 62, waveFreq: { 1109, 0 }, 0, 0 },
+ { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
+ { duration: 62, waveFreq: { 831, 0 }, 0, 0 },
+ { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_ALERT_INCALL_LITE
+ { segments: { { duration: 125, waveFreq: { 941, 0 }, 0, 0 },
+ { duration: 10, waveFreq: { 0 }, 2, 0 },
+ { duration: 4990, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_CDMA_EMERGENCY_RINGBACK
+ { segments: { { duration: 125, waveFreq: { 1319, 0 }, 0, 0 },
+ { duration: 125, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: 2,
+ repeatSegment: 0 }, // TONE_CDMA_ALERT_CALL_GUARD
+ { segments: { { duration: 125, waveFreq: { 1047, 0 }, 0, 0 },
+ { duration: 125, waveFreq: { 370, 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_SOFT_ERROR_LITE
+ { segments: { { duration: 125, waveFreq: { 1480, 0 }, 0, 0 },
+ { duration: 125, waveFreq: { 1397, 0 }, 0, 0 },
+ { duration: 125, waveFreq: { 784, 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 } },
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_CALLDROP_LITE
+
+ { segments: { { duration: 500, waveFreq: { 425, 0 }, 0, 0 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_NETWORK_BUSY_ONE_SHOT
+ { segments: { { duration: 400, waveFreq: { 1150, 770 }, 0, 0 },
+ { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_ABBR_ALERT
+ { segments: { { duration: 0, waveFreq: { 0 }, 0, 0 }},
+ repeatCnt: 0,
+ repeatSegment: 0 }, // TONE_CDMA_SIGNAL_OFF
+
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 350, 440, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_ANSI_DIAL
+ { segments: { { duration: 500, waveFreq: { 480, 620, 0 }, 0, 0 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_ANSI_BUSY
+ { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
+ { duration: 250, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_ANSI_CONGESTION
+ { segments: { { duration: 300, waveFreq: { 440, 0 }, 0, 0 },
+ { duration: 9700, waveFreq: { 0 }, 0, 0 },
+ { duration: 100, waveFreq: { 440, 0 }, 0, 0 },
+ { duration: 100, waveFreq: { 0 }, 0, 0 },
+ { duration: 100, waveFreq: { 440, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 1 }, // TONE_ANSI_CALL_WAITING
+ { segments: { { duration: 2000, waveFreq: { 440, 480, 0 }, 0, 0 },
+ { duration: 4000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_ANSI_RINGTONE
+ { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 400, 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_JAPAN_DIAL
+ { segments: { { duration: 500, waveFreq: { 400, 0 }, 0, 0 },
+ { duration: 500, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_JAPAN_BUSY
+ { segments: { { duration: 1000, waveFreq: { 400, 0 }, 0, 0 },
+ { duration: 2000, waveFreq: { 0 }, 0, 0 },
+ { duration: 0 , waveFreq: { 0 }, 0, 0}},
+ repeatCnt: ToneGenerator::TONEGEN_INF,
+ repeatSegment: 0 }, // TONE_JAPAN_RADIO_ACK
+
+
+
+};
+
+// Used by ToneGenerator::getToneForRegion() to convert user specified supervisory tone type
+// to actual tone for current region.
+const unsigned char /*tone_type*/ ToneGenerator::sToneMappingTable[NUM_REGIONS-1][NUM_SUP_TONES] = {
+ { // ANSI
+ TONE_ANSI_DIAL, // TONE_SUP_DIAL
+ TONE_ANSI_BUSY, // TONE_SUP_BUSY
+ TONE_ANSI_CONGESTION, // TONE_SUP_CONGESTION
+ TONE_SUP_RADIO_ACK, // TONE_SUP_RADIO_ACK
+ TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
+ TONE_SUP_ERROR, // TONE_SUP_ERROR
+ TONE_ANSI_CALL_WAITING, // TONE_SUP_CALL_WAITING
+ TONE_ANSI_RINGTONE // TONE_SUP_RINGTONE
+ },
+ { // JAPAN
+ TONE_JAPAN_DIAL, // TONE_SUP_DIAL
+ TONE_JAPAN_BUSY, // TONE_SUP_BUSY
+ TONE_SUP_CONGESTION, // TONE_SUP_CONGESTION
+ TONE_JAPAN_RADIO_ACK, // TONE_SUP_RADIO_ACK
+ TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
+ TONE_SUP_ERROR, // TONE_SUP_ERROR
+ TONE_SUP_CALL_WAITING, // TONE_SUP_CALL_WAITING
+ TONE_SUP_RINGTONE // TONE_SUP_RINGTONE
+ }
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// ToneGenerator class Implementation
+////////////////////////////////////////////////////////////////////////////////
+
+
+//---------------------------------- public methods ----------------------------
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: ToneGenerator::ToneGenerator()
+//
+// Description: Constructor. Initializes the tone sequencer, intantiates required sine wave
+// generators, instantiates output audio track.
+//
+// Input:
+// streamType: Type of stream used for tone playback
+// volume: volume applied to tone (0.0 to 1.0)
+//
+// Output:
+// none
+//
+////////////////////////////////////////////////////////////////////////////////
+ToneGenerator::ToneGenerator(audio_stream_type_t streamType, float volume, bool threadCanCallJava) {
+
+ ALOGV("ToneGenerator constructor: streamType=%d, volume=%f", streamType, volume);
+
+ mState = TONE_IDLE;
+
+ if (AudioSystem::getOutputSamplingRate(&mSamplingRate, streamType) != NO_ERROR) {
+ ALOGE("Unable to marshal AudioFlinger");
+ return;
+ }
+ mThreadCanCallJava = threadCanCallJava;
+ mStreamType = streamType;
+ mVolume = volume;
+ mpAudioTrack = NULL;
+ mpToneDesc = NULL;
+ mpNewToneDesc = NULL;
+ // Generate tone by chunks of 20 ms to keep cadencing precision
+ mProcessSize = (mSamplingRate * 20) / 1000;
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("gsm.operator.iso-country", value, "");
+ if (strcmp(value,"us") == 0 ||
+ strcmp(value,"ca") == 0) {
+ mRegion = ANSI;
+ } else if (strcmp(value,"jp") == 0) {
+ mRegion = JAPAN;
+ } else {
+ mRegion = CEPT;
+ }
+
+ if (initAudioTrack()) {
+ ALOGV("ToneGenerator INIT OK, time: %d", (unsigned int)(systemTime()/1000000));
+ } else {
+ ALOGV("!!!ToneGenerator INIT FAILED!!!");
+ }
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: ToneGenerator::~ToneGenerator()
+//
+// Description: Destructor. Stop sound playback and delete audio track if
+// needed and delete sine wave generators.
+//
+// Input:
+// none
+//
+// Output:
+// none
+//
+////////////////////////////////////////////////////////////////////////////////
+ToneGenerator::~ToneGenerator() {
+ ALOGV("ToneGenerator destructor");
+
+ if (mpAudioTrack != NULL) {
+ stopTone();
+ ALOGV("Delete Track: %p", mpAudioTrack);
+ delete mpAudioTrack;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: ToneGenerator::startTone()
+//
+// Description: Starts tone playback.
+//
+// Input:
+// toneType: Type of tone generated (values in enum tone_type)
+// durationMs: The tone duration in milliseconds. If the tone is limited in time by definition,
+// the actual duration will be the minimum of durationMs and the defined tone duration.
+// Ommiting or setting durationMs to -1 does not limit tone duration.
+//
+// Output:
+// none
+//
+////////////////////////////////////////////////////////////////////////////////
+bool ToneGenerator::startTone(tone_type toneType, int durationMs) {
+ bool lResult = false;
+ status_t lStatus;
+
+ if ((toneType < 0) || (toneType >= NUM_TONES))
+ return lResult;
+
+ if (mState == TONE_IDLE) {
+ ALOGV("startTone: try to re-init AudioTrack");
+ if (!initAudioTrack()) {
+ return lResult;
+ }
+ }
+
+ ALOGV("startTone");
+
+ mLock.lock();
+
+ // Get descriptor for requested tone
+ toneType = getToneForRegion(toneType);
+ mpNewToneDesc = &sToneDescriptors[toneType];
+
+ mDurationMs = durationMs;
+
+ if (mState == TONE_STOPPED) {
+ ALOGV("Start waiting for previous tone to stop");
+ lStatus = mWaitCbkCond.waitRelative(mLock, seconds(3));
+ if (lStatus != NO_ERROR) {
+ ALOGE("--- start wait for stop timed out, status %d", lStatus);
+ mState = TONE_IDLE;
+ mLock.unlock();
+ return lResult;
+ }
+ }
+
+ if (mState == TONE_INIT) {
+ if (prepareWave()) {
+ ALOGV("Immediate start, time %d", (unsigned int)(systemTime()/1000000));
+ lResult = true;
+ mState = TONE_STARTING;
+ mLock.unlock();
+ mpAudioTrack->start();
+ mLock.lock();
+ if (mState == TONE_STARTING) {
+ ALOGV("Wait for start callback");
+ lStatus = mWaitCbkCond.waitRelative(mLock, seconds(3));
+ if (lStatus != NO_ERROR) {
+ ALOGE("--- Immediate start timed out, status %d", lStatus);
+ mState = TONE_IDLE;
+ lResult = false;
+ }
+ }
+ } else {
+ mState = TONE_IDLE;
+ }
+ } else {
+ ALOGV("Delayed start");
+ mState = TONE_RESTARTING;
+ lStatus = mWaitCbkCond.waitRelative(mLock, seconds(3));
+ if (lStatus == NO_ERROR) {
+ if (mState != TONE_IDLE) {
+ lResult = true;
+ }
+ ALOGV("cond received");
+ } else {
+ ALOGE("--- Delayed start timed out, status %d", lStatus);
+ mState = TONE_IDLE;
+ }
+ }
+ mLock.unlock();
+
+ ALOGV_IF(lResult, "Tone started, time %d", (unsigned int)(systemTime()/1000000));
+ ALOGW_IF(!lResult, "Tone start failed!!!, time %d", (unsigned int)(systemTime()/1000000));
+
+ return lResult;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: ToneGenerator::stopTone()
+//
+// Description: Stops tone playback.
+//
+// Input:
+// none
+//
+// Output:
+// none
+//
+////////////////////////////////////////////////////////////////////////////////
+void ToneGenerator::stopTone() {
+ ALOGV("stopTone");
+
+ mLock.lock();
+ if (mState == TONE_PLAYING || mState == TONE_STARTING || mState == TONE_RESTARTING) {
+ mState = TONE_STOPPING;
+ ALOGV("waiting cond");
+ status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(3));
+ if (lStatus == NO_ERROR) {
+ ALOGV("track stop complete, time %d", (unsigned int)(systemTime()/1000000));
+ } else {
+ ALOGE("--- Stop timed out");
+ mState = TONE_IDLE;
+ mpAudioTrack->stop();
+ }
+ }
+
+ clearWaveGens();
+
+ mLock.unlock();
+}
+
+//---------------------------------- private methods ---------------------------
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: ToneGenerator::initAudioTrack()
+//
+// Description: Allocates and configures AudioTrack used for PCM output.
+//
+// Input:
+// none
+//
+// Output:
+// none
+//
+////////////////////////////////////////////////////////////////////////////////
+bool ToneGenerator::initAudioTrack() {
+
+ if (mpAudioTrack) {
+ delete mpAudioTrack;
+ mpAudioTrack = NULL;
+ }
+
+ // Open audio track in mono, PCM 16bit, default sampling rate, default buffer size
+ mpAudioTrack = new AudioTrack();
+ ALOGV("Create Track: %p", mpAudioTrack);
+
+ mpAudioTrack->set(mStreamType,
+ 0,
+ AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_OUT_MONO,
+ 0,
+ AUDIO_POLICY_OUTPUT_FLAG_NONE,
+ audioCallback,
+ this,
+ 0,
+ 0,
+ mThreadCanCallJava);
+
+ if (mpAudioTrack->initCheck() != NO_ERROR) {
+ ALOGE("AudioTrack->initCheck failed");
+ goto initAudioTrack_exit;
+ }
+
+ mpAudioTrack->setVolume(mVolume, mVolume);
+
+ mState = TONE_INIT;
+
+ return true;
+
+initAudioTrack_exit:
+
+ // Cleanup
+ if (mpAudioTrack != NULL) {
+ ALOGV("Delete Track I: %p", mpAudioTrack);
+ delete mpAudioTrack;
+ mpAudioTrack = NULL;
+ }
+
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: ToneGenerator::audioCallback()
+//
+// Description: AudioTrack callback implementation. Generates a block of
+// PCM samples
+// and manages tone generator sequencer: tones pulses, tone duration...
+//
+// Input:
+// user reference (pointer to our ToneGenerator)
+// info audio buffer descriptor
+//
+// Output:
+// returned value: always true.
+//
+////////////////////////////////////////////////////////////////////////////////
+void ToneGenerator::audioCallback(int event, void* user, void *info) {
+
+ if (event != AudioTrack::EVENT_MORE_DATA) return;
+
+ AudioTrack::Buffer *buffer = static_cast<AudioTrack::Buffer *>(info);
+ ToneGenerator *lpToneGen = static_cast<ToneGenerator *>(user);
+ short *lpOut = buffer->i16;
+ unsigned int lNumSmp = buffer->size/sizeof(short);
+ const ToneDescriptor *lpToneDesc = lpToneGen->mpToneDesc;
+
+ if (buffer->size == 0) return;
+
+
+ // Clear output buffer: WaveGenerator accumulates into lpOut buffer
+ memset(lpOut, 0, buffer->size);
+
+ while (lNumSmp) {
+ unsigned int lReqSmp = lNumSmp < lpToneGen->mProcessSize*2 ? lNumSmp : lpToneGen->mProcessSize;
+ unsigned int lGenSmp;
+ unsigned int lWaveCmd = WaveGenerator::WAVEGEN_CONT;
+ bool lSignal = false;
+
+ lpToneGen->mLock.lock();
+
+
+ // Update pcm frame count and end time (current time at the end of this process)
+ lpToneGen->mTotalSmp += lReqSmp;
+
+ // Update tone gen state machine and select wave gen command
+ switch (lpToneGen->mState) {
+ case TONE_PLAYING:
+ lWaveCmd = WaveGenerator::WAVEGEN_CONT;
+ break;
+ case TONE_STARTING:
+ ALOGV("Starting Cbk");
+
+ lWaveCmd = WaveGenerator::WAVEGEN_START;
+ break;
+ case TONE_STOPPING:
+ case TONE_RESTARTING:
+ ALOGV("Stop/restart Cbk");
+
+ lWaveCmd = WaveGenerator::WAVEGEN_STOP;
+ lpToneGen->mNextSegSmp = TONEGEN_INF; // forced to skip state machine management below
+ break;
+ case TONE_STOPPED:
+ ALOGV("Stopped Cbk");
+ goto audioCallback_EndLoop;
+ default:
+ ALOGV("Extra Cbk");
+ goto audioCallback_EndLoop;
+ }
+
+ // Exit if tone sequence is over
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0 ||
+ lpToneGen->mTotalSmp > lpToneGen->mMaxSmp) {
+ if (lpToneGen->mState == TONE_PLAYING) {
+ lpToneGen->mState = TONE_STOPPING;
+ }
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0) {
+ goto audioCallback_EndLoop;
+ }
+ // fade out before stopping if maximum duration reached
+ lWaveCmd = WaveGenerator::WAVEGEN_STOP;
+ lpToneGen->mNextSegSmp = TONEGEN_INF; // forced to skip state machine management below
+ }
+
+ if (lpToneGen->mTotalSmp > lpToneGen->mNextSegSmp) {
+ // Time to go to next sequence segment
+
+ ALOGV("End Segment, time: %d", (unsigned int)(systemTime()/1000000));
+
+ lGenSmp = lReqSmp;
+
+ // If segment, ON -> OFF transition : ramp volume down
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] != 0) {
+ lWaveCmd = WaveGenerator::WAVEGEN_STOP;
+ unsigned int lFreqIdx = 0;
+ unsigned short lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[lFreqIdx];
+
+ while (lFrequency != 0) {
+ WaveGenerator *lpWaveGen = lpToneGen->mWaveGens.valueFor(lFrequency);
+ lpWaveGen->getSamples(lpOut, lGenSmp, lWaveCmd);
+ lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[++lFreqIdx];
+ }
+ ALOGV("ON->OFF, lGenSmp: %d, lReqSmp: %d", lGenSmp, lReqSmp);
+ }
+
+ // check if we need to loop and loop for the reqd times
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt) {
+ if (lpToneGen->mLoopCounter < lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt) {
+ ALOGV ("in if loop loopCnt(%d) loopctr(%d), CurSeg(%d)",
+ lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt,
+ lpToneGen->mLoopCounter,
+ lpToneGen->mCurSegment);
+ lpToneGen->mCurSegment = lpToneDesc->segments[lpToneGen->mCurSegment].loopIndx;
+ ++lpToneGen->mLoopCounter;
+ } else {
+ // completed loop. go to next segment
+ lpToneGen->mLoopCounter = 0;
+ lpToneGen->mCurSegment++;
+ ALOGV ("in else loop loopCnt(%d) loopctr(%d), CurSeg(%d)",
+ lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt,
+ lpToneGen->mLoopCounter,
+ lpToneGen->mCurSegment);
+ }
+ } else {
+ lpToneGen->mCurSegment++;
+ ALOGV ("Goto next seg loopCnt(%d) loopctr(%d), CurSeg(%d)",
+ lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt,
+ lpToneGen->mLoopCounter,
+ lpToneGen->mCurSegment);
+
+ }
+
+ // Handle loop if last segment reached
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0) {
+ ALOGV("Last Seg: %d", lpToneGen->mCurSegment);
+
+ // Pre increment loop count and restart if total count not reached. Stop sequence otherwise
+ if (++lpToneGen->mCurCount <= lpToneDesc->repeatCnt) {
+ ALOGV("Repeating Count: %d", lpToneGen->mCurCount);
+
+ lpToneGen->mCurSegment = lpToneDesc->repeatSegment;
+ if (lpToneDesc->segments[lpToneDesc->repeatSegment].waveFreq[0] != 0) {
+ lWaveCmd = WaveGenerator::WAVEGEN_START;
+ }
+
+ ALOGV("New segment %d, Next Time: %d", lpToneGen->mCurSegment,
+ (lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate);
+
+ } else {
+ lGenSmp = 0;
+ ALOGV("End repeat, time: %d", (unsigned int)(systemTime()/1000000));
+ }
+ } else {
+ ALOGV("New segment %d, Next Time: %d", lpToneGen->mCurSegment,
+ (lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate);
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] != 0) {
+ // If next segment is not silent, OFF -> ON transition : reset wave generator
+ lWaveCmd = WaveGenerator::WAVEGEN_START;
+
+ ALOGV("OFF->ON, lGenSmp: %d, lReqSmp: %d", lGenSmp, lReqSmp);
+ } else {
+ lGenSmp = 0;
+ }
+ }
+
+ // Update next segment transition position. No harm to do it also for last segment as lpToneGen->mNextSegSmp won't be used any more
+ lpToneGen->mNextSegSmp
+ += (lpToneDesc->segments[lpToneGen->mCurSegment].duration * lpToneGen->mSamplingRate) / 1000;
+
+ } else {
+ // Inside a segment keep tone ON or OFF
+ if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] == 0) {
+ lGenSmp = 0; // If odd segment, tone is currently OFF
+ } else {
+ lGenSmp = lReqSmp; // If event segment, tone is currently ON
+ }
+ }
+
+ if (lGenSmp) {
+ // If samples must be generated, call all active wave generators and acumulate waves in lpOut
+ unsigned int lFreqIdx = 0;
+ unsigned short lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[lFreqIdx];
+
+ while (lFrequency != 0) {
+ WaveGenerator *lpWaveGen = lpToneGen->mWaveGens.valueFor(lFrequency);
+ lpWaveGen->getSamples(lpOut, lGenSmp, lWaveCmd);
+ lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[++lFreqIdx];
+ }
+ }
+
+ lNumSmp -= lReqSmp;
+ lpOut += lReqSmp;
+
+audioCallback_EndLoop:
+
+ switch (lpToneGen->mState) {
+ case TONE_RESTARTING:
+ ALOGV("Cbk restarting track");
+ if (lpToneGen->prepareWave()) {
+ lpToneGen->mState = TONE_STARTING;
+ // must reload lpToneDesc as prepareWave() may change mpToneDesc
+ lpToneDesc = lpToneGen->mpToneDesc;
+ } else {
+ ALOGW("Cbk restarting prepareWave() failed");
+ lpToneGen->mState = TONE_IDLE;
+ lpToneGen->mpAudioTrack->stop();
+ // Force loop exit
+ lNumSmp = 0;
+ }
+ lSignal = true;
+ break;
+ case TONE_STOPPING:
+ ALOGV("Cbk Stopping");
+ lpToneGen->mState = TONE_STOPPED;
+ // Force loop exit
+ lNumSmp = 0;
+ break;
+ case TONE_STOPPED:
+ lpToneGen->mState = TONE_INIT;
+ ALOGV("Cbk Stopped track");
+ lpToneGen->mpAudioTrack->stop();
+ // Force loop exit
+ lNumSmp = 0;
+ buffer->size = 0;
+ lSignal = true;
+ break;
+ case TONE_STARTING:
+ ALOGV("Cbk starting track");
+ lpToneGen->mState = TONE_PLAYING;
+ lSignal = true;
+ break;
+ case TONE_PLAYING:
+ break;
+ default:
+ // Force loop exit
+ lNumSmp = 0;
+ buffer->size = 0;
+ break;
+ }
+
+ if (lSignal)
+ lpToneGen->mWaitCbkCond.signal();
+ lpToneGen->mLock.unlock();
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: ToneGenerator::prepareWave()
+//
+// Description: Prepare wave generators and reset tone sequencer state machine.
+// mpNewToneDesc must have been initialized before calling this function.
+// Input:
+// none
+//
+// Output:
+// returned value: true if wave generators have been created, false otherwise
+//
+////////////////////////////////////////////////////////////////////////////////
+bool ToneGenerator::prepareWave() {
+ unsigned int segmentIdx = 0;
+
+ if (mpNewToneDesc == NULL) {
+ return false;
+ }
+
+ // Remove existing wave generators if any
+ clearWaveGens();
+
+ mpToneDesc = mpNewToneDesc;
+
+ if (mDurationMs == -1) {
+ mMaxSmp = TONEGEN_INF;
+ } else {
+ if (mDurationMs > (int)(TONEGEN_INF / mSamplingRate)) {
+ mMaxSmp = (mDurationMs / 1000) * mSamplingRate;
+ } else {
+ mMaxSmp = (mDurationMs * mSamplingRate) / 1000;
+ }
+ ALOGV("prepareWave, duration limited to %d ms", mDurationMs);
+ }
+
+ while (mpToneDesc->segments[segmentIdx].duration) {
+ // Get total number of sine waves: needed to adapt sine wave gain.
+ unsigned int lNumWaves = numWaves(segmentIdx);
+ unsigned int freqIdx = 0;
+ unsigned int frequency = mpToneDesc->segments[segmentIdx].waveFreq[freqIdx];
+ while (frequency) {
+ // Instantiate a wave generator if ot already done for this frequency
+ if (mWaveGens.indexOfKey(frequency) == NAME_NOT_FOUND) {
+ ToneGenerator::WaveGenerator *lpWaveGen =
+ new ToneGenerator::WaveGenerator((unsigned short)mSamplingRate,
+ frequency,
+ TONEGEN_GAIN/lNumWaves);
+ mWaveGens.add(frequency, lpWaveGen);
+ }
+ frequency = mpNewToneDesc->segments[segmentIdx].waveFreq[++freqIdx];
+ }
+ segmentIdx++;
+ }
+
+ // Initialize tone sequencer
+ mTotalSmp = 0;
+ mCurSegment = 0;
+ mCurCount = 0;
+ mLoopCounter = 0;
+ if (mpToneDesc->segments[0].duration == TONEGEN_INF) {
+ mNextSegSmp = TONEGEN_INF;
+ } else{
+ mNextSegSmp = (mpToneDesc->segments[0].duration * mSamplingRate) / 1000;
+ }
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: ToneGenerator::numWaves()
+//
+// Description: Count number of sine waves needed to generate a tone segment (e.g 2 for DTMF).
+//
+// Input:
+// segmentIdx tone segment index
+//
+// Output:
+// returned value: nummber of sine waves
+//
+////////////////////////////////////////////////////////////////////////////////
+unsigned int ToneGenerator::numWaves(unsigned int segmentIdx) {
+ unsigned int lCnt = 0;
+
+ if (mpToneDesc->segments[segmentIdx].duration) {
+ while (mpToneDesc->segments[segmentIdx].waveFreq[lCnt]) {
+ lCnt++;
+ }
+ lCnt++;
+ }
+
+ return lCnt;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: ToneGenerator::clearWaveGens()
+//
+// Description: Removes all wave generators.
+//
+// Input:
+// none
+//
+// Output:
+// none
+//
+////////////////////////////////////////////////////////////////////////////////
+void ToneGenerator::clearWaveGens() {
+ ALOGV("Clearing mWaveGens:");
+
+ for (size_t lIdx = 0; lIdx < mWaveGens.size(); lIdx++) {
+ delete mWaveGens.valueAt(lIdx);
+ }
+ mWaveGens.clear();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: ToneGenerator::getToneForRegion()
+//
+// Description: Get correct ringtone type according to current region.
+// The corrected ring tone type is the tone descriptor index in sToneDescriptors[].
+//
+// Input:
+// none
+//
+// Output:
+// none
+//
+////////////////////////////////////////////////////////////////////////////////
+ToneGenerator::tone_type ToneGenerator::getToneForRegion(tone_type toneType) {
+ tone_type regionTone;
+
+ if (mRegion == CEPT || toneType < FIRST_SUP_TONE || toneType > LAST_SUP_TONE) {
+ regionTone = toneType;
+ } else {
+ regionTone = (tone_type) sToneMappingTable[mRegion][toneType - FIRST_SUP_TONE];
+ }
+
+ ALOGV("getToneForRegion, tone %d, region %d, regionTone %d", toneType, mRegion, regionTone);
+
+ return regionTone;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// WaveGenerator::WaveGenerator class Implementation
+////////////////////////////////////////////////////////////////////////////////
+
+//---------------------------------- public methods ----------------------------
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: WaveGenerator::WaveGenerator()
+//
+// Description: Constructor.
+//
+// Input:
+// samplingRate: Output sampling rate in Hz
+// frequency: Frequency of the sine wave to generate in Hz
+// volume: volume (0.0 to 1.0)
+//
+// Output:
+// none
+//
+////////////////////////////////////////////////////////////////////////////////
+ToneGenerator::WaveGenerator::WaveGenerator(unsigned short samplingRate,
+ unsigned short frequency, float volume) {
+ double d0;
+ double F_div_Fs; // frequency / samplingRate
+
+ F_div_Fs = frequency / (double)samplingRate;
+ d0 = - (float)GEN_AMP * sin(2 * M_PI * F_div_Fs);
+ mS2_0 = (short)d0;
+ mS1 = 0;
+ mS2 = mS2_0;
+
+ mAmplitude_Q15 = (short)(32767. * 32767. * volume / GEN_AMP);
+ // take some margin for amplitude fluctuation
+ if (mAmplitude_Q15 > 32500)
+ mAmplitude_Q15 = 32500;
+
+ d0 = 32768.0 * cos(2 * M_PI * F_div_Fs); // Q14*2*cos()
+ if (d0 > 32767)
+ d0 = 32767;
+ mA1_Q14 = (short) d0;
+
+ ALOGV("WaveGenerator init, mA1_Q14: %d, mS2_0: %d, mAmplitude_Q15: %d",
+ mA1_Q14, mS2_0, mAmplitude_Q15);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: WaveGenerator::~WaveGenerator()
+//
+// Description: Destructor.
+//
+// Input:
+// none
+//
+// Output:
+// none
+//
+////////////////////////////////////////////////////////////////////////////////
+ToneGenerator::WaveGenerator::~WaveGenerator() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Method: WaveGenerator::getSamples()
+//
+// Description: Generates count samples of a sine wave and accumulates
+// result in outBuffer.
+//
+// Input:
+// outBuffer: Output buffer where to accumulate samples.
+// count: number of samples to produce.
+// command: special action requested (see enum gen_command).
+//
+// Output:
+// none
+//
+////////////////////////////////////////////////////////////////////////////////
+void ToneGenerator::WaveGenerator::getSamples(short *outBuffer,
+ unsigned int count, unsigned int command) {
+ long lS1, lS2;
+ long lA1, lAmplitude;
+ long Sample; // current sample
+
+ // init local
+ if (command == WAVEGEN_START) {
+ lS1 = (long)0;
+ lS2 = (long)mS2_0;
+ } else {
+ lS1 = (long)mS1;
+ lS2 = (long)mS2;
+ }
+ lA1 = (long)mA1_Q14;
+ lAmplitude = (long)mAmplitude_Q15;
+
+ if (command == WAVEGEN_STOP) {
+ lAmplitude <<= 16;
+ if (count == 0) {
+ return;
+ }
+ long dec = lAmplitude/count;
+ // loop generation
+ while (count--) {
+ Sample = ((lA1 * lS1) >> S_Q14) - lS2;
+ // shift delay
+ lS2 = lS1;
+ lS1 = Sample;
+ Sample = ((lAmplitude>>16) * Sample) >> S_Q15;
+ *(outBuffer++) += (short)Sample; // put result in buffer
+ lAmplitude -= dec;
+ }
+ } else {
+ // loop generation
+ while (count--) {
+ Sample = ((lA1 * lS1) >> S_Q14) - lS2;
+ // shift delay
+ lS2 = lS1;
+ lS1 = Sample;
+ Sample = (lAmplitude * Sample) >> S_Q15;
+ *(outBuffer++) += (short)Sample; // put result in buffer
+ }
+ }
+
+ // save status
+ mS1 = (short)lS1;
+ mS2 = (short)lS2;
+}
+
+} // end namespace android
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
new file mode 100644
index 0000000..bcd6ae4
--- /dev/null
+++ b/media/libmedia/Visualizer.cpp
@@ -0,0 +1,322 @@
+/*
+**
+** 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 <cutils/bitops.h>
+
+#include <media/Visualizer.h>
+#include <audio_utils/fixedfft.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();
+}
+
+Visualizer::~Visualizer()
+{
+}
+
+status_t Visualizer::setEnabled(bool enabled)
+{
+ Mutex::Autolock _l(mCaptureLock);
+
+ sp<CaptureThread> t = mCaptureThread;
+ if (t != 0) {
+ if (enabled) {
+ if (t->exitPending()) {
+ if (t->requestExitAndWait() == WOULD_BLOCK) {
+ ALOGE("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("Visualizer");
+ } 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(mCaptureLock);
+
+ 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));
+ }
+ ALOGV("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 ||
+ popcount(size) != 1) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock _l(mCaptureLock);
+ 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 = VISUALIZER_PARAM_CAPTURE_SIZE;
+ *((int32_t *)p->data + 1)= size;
+ status_t status = setParameter(p);
+
+ ALOGV("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;
+ }
+
+ 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 = command(VISUALIZER_CMD_CAPTURE, 0, NULL, &replySize, waveform);
+ ALOGV("getWaveForm() command returned %d", status);
+ if ((status == NO_ERROR) && (replySize == 0)) {
+ status = NOT_ENOUGH_DATA;
+ }
+ } else {
+ ALOGV("getWaveForm() disabled");
+ 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 = 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)
+{
+ int32_t workspace[mCaptureSize >> 1];
+ int32_t nonzero = 0;
+
+ for (uint32_t i = 0; i < mCaptureSize; i += 2) {
+ workspace[i >> 1] =
+ ((waveform[i] ^ 0x80) << 24) | ((waveform[i + 1] ^ 0x80) << 8);
+ nonzero |= workspace[i >> 1];
+ }
+
+ if (nonzero) {
+ fixed_fft_real(mCaptureSize >> 1, workspace);
+ }
+
+ for (uint32_t i = 0; i < mCaptureSize; i += 2) {
+ short tmp = workspace[i >> 1] >> 21;
+ while (tmp > 127 || tmp < -128) tmp >>= 1;
+ fft[i] = tmp;
+ tmp = workspace[i >> 1];
+ tmp >>= 5;
+ while (tmp > 127 || tmp < -128) tmp >>= 1;
+ fft[i + 1] = tmp;
+ }
+
+ return NO_ERROR;
+}
+
+void Visualizer::periodicCapture()
+{
+ Mutex::Autolock _l(mCaptureLock);
+ ALOGV("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 = VISUALIZER_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;
+
+ ALOGV("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;
+ ALOGV("CaptureThread cstor %p captureRate %d mSleepTimeUs %d", this, captureRate, mSleepTimeUs);
+}
+
+bool Visualizer::CaptureThread::threadLoop()
+{
+ ALOGV("CaptureThread %p enter", this);
+ while (!exitPending())
+ {
+ usleep(mSleepTimeUs);
+ mReceiver.periodicCapture();
+ }
+ ALOGV("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/autodetect.cpp b/media/libmedia/autodetect.cpp
new file mode 100644
index 0000000..be5c3b2
--- /dev/null
+++ b/media/libmedia/autodetect.cpp
@@ -0,0 +1,885 @@
+/*
+ * 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.
+ */
+
+#include "autodetect.h"
+
+struct CharRange {
+ uint16_t first;
+ uint16_t last;
+};
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
+
+// generated from http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP932.TXT
+static const CharRange kShiftJISRanges[] = {
+ { 0x8140, 0x817E },
+ { 0x8180, 0x81AC },
+ { 0x81B8, 0x81BF },
+ { 0x81C8, 0x81CE },
+ { 0x81DA, 0x81E8 },
+ { 0x81F0, 0x81F7 },
+ { 0x81FC, 0x81FC },
+ { 0x824F, 0x8258 },
+ { 0x8260, 0x8279 },
+ { 0x8281, 0x829A },
+ { 0x829F, 0x82F1 },
+ { 0x8340, 0x837E },
+ { 0x8380, 0x8396 },
+ { 0x839F, 0x83B6 },
+ { 0x83BF, 0x83D6 },
+ { 0x8440, 0x8460 },
+ { 0x8470, 0x847E },
+ { 0x8480, 0x8491 },
+ { 0x849F, 0x84BE },
+ { 0x8740, 0x875D },
+ { 0x875F, 0x8775 },
+ { 0x877E, 0x877E },
+ { 0x8780, 0x879C },
+ { 0x889F, 0x88FC },
+ { 0x8940, 0x897E },
+ { 0x8980, 0x89FC },
+ { 0x8A40, 0x8A7E },
+ { 0x8A80, 0x8AFC },
+ { 0x8B40, 0x8B7E },
+ { 0x8B80, 0x8BFC },
+ { 0x8C40, 0x8C7E },
+ { 0x8C80, 0x8CFC },
+ { 0x8D40, 0x8D7E },
+ { 0x8D80, 0x8DFC },
+ { 0x8E40, 0x8E7E },
+ { 0x8E80, 0x8EFC },
+ { 0x8F40, 0x8F7E },
+ { 0x8F80, 0x8FFC },
+ { 0x9040, 0x907E },
+ { 0x9080, 0x90FC },
+ { 0x9140, 0x917E },
+ { 0x9180, 0x91FC },
+ { 0x9240, 0x927E },
+ { 0x9280, 0x92FC },
+ { 0x9340, 0x937E },
+ { 0x9380, 0x93FC },
+ { 0x9440, 0x947E },
+ { 0x9480, 0x94FC },
+ { 0x9540, 0x957E },
+ { 0x9580, 0x95FC },
+ { 0x9640, 0x967E },
+ { 0x9680, 0x96FC },
+ { 0x9740, 0x977E },
+ { 0x9780, 0x97FC },
+ { 0x9840, 0x9872 },
+ { 0x989F, 0x98FC },
+ { 0x9940, 0x997E },
+ { 0x9980, 0x99FC },
+ { 0x9A40, 0x9A7E },
+ { 0x9A80, 0x9AFC },
+ { 0x9B40, 0x9B7E },
+ { 0x9B80, 0x9BFC },
+ { 0x9C40, 0x9C7E },
+ { 0x9C80, 0x9CFC },
+ { 0x9D40, 0x9D7E },
+ { 0x9D80, 0x9DFC },
+ { 0x9E40, 0x9E7E },
+ { 0x9E80, 0x9EFC },
+ { 0x9F40, 0x9F7E },
+ { 0x9F80, 0x9FFC },
+ { 0xE040, 0xE07E },
+ { 0xE080, 0xE0FC },
+ { 0xE140, 0xE17E },
+ { 0xE180, 0xE1FC },
+ { 0xE240, 0xE27E },
+ { 0xE280, 0xE2FC },
+ { 0xE340, 0xE37E },
+ { 0xE380, 0xE3FC },
+ { 0xE440, 0xE47E },
+ { 0xE480, 0xE4FC },
+ { 0xE540, 0xE57E },
+ { 0xE580, 0xE5FC },
+ { 0xE640, 0xE67E },
+ { 0xE680, 0xE6FC },
+ { 0xE740, 0xE77E },
+ { 0xE780, 0xE7FC },
+ { 0xE840, 0xE87E },
+ { 0xE880, 0xE8FC },
+ { 0xE940, 0xE97E },
+ { 0xE980, 0xE9FC },
+ { 0xEA40, 0xEA7E },
+ { 0xEA80, 0xEAA4 },
+ { 0xED40, 0xED7E },
+ { 0xED80, 0xEDFC },
+ { 0xEE40, 0xEE7E },
+ { 0xEE80, 0xEEEC },
+ { 0xEEEF, 0xEEFC },
+ { 0xFA40, 0xFA7E },
+ { 0xFA80, 0xFAFC },
+ { 0xFB40, 0xFB7E },
+ { 0xFB80, 0xFBFC },
+ { 0xFC40, 0xFC4B },
+};
+
+// generated from http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT
+static const CharRange kGBKRanges[] = {
+ { 0x8140, 0x817E },
+ { 0x8180, 0x81FE },
+ { 0x8240, 0x827E },
+ { 0x8280, 0x82FE },
+ { 0x8340, 0x837E },
+ { 0x8380, 0x83FE },
+ { 0x8440, 0x847E },
+ { 0x8480, 0x84FE },
+ { 0x8540, 0x857E },
+ { 0x8580, 0x85FE },
+ { 0x8640, 0x867E },
+ { 0x8680, 0x86FE },
+ { 0x8740, 0x877E },
+ { 0x8780, 0x87FE },
+ { 0x8840, 0x887E },
+ { 0x8880, 0x88FE },
+ { 0x8940, 0x897E },
+ { 0x8980, 0x89FE },
+ { 0x8A40, 0x8A7E },
+ { 0x8A80, 0x8AFE },
+ { 0x8B40, 0x8B7E },
+ { 0x8B80, 0x8BFE },
+ { 0x8C40, 0x8C7E },
+ { 0x8C80, 0x8CFE },
+ { 0x8D40, 0x8D7E },
+ { 0x8D80, 0x8DFE },
+ { 0x8E40, 0x8E7E },
+ { 0x8E80, 0x8EFE },
+ { 0x8F40, 0x8F7E },
+ { 0x8F80, 0x8FFE },
+ { 0x9040, 0x907E },
+ { 0x9080, 0x90FE },
+ { 0x9140, 0x917E },
+ { 0x9180, 0x91FE },
+ { 0x9240, 0x927E },
+ { 0x9280, 0x92FE },
+ { 0x9340, 0x937E },
+ { 0x9380, 0x93FE },
+ { 0x9440, 0x947E },
+ { 0x9480, 0x94FE },
+ { 0x9540, 0x957E },
+ { 0x9580, 0x95FE },
+ { 0x9640, 0x967E },
+ { 0x9680, 0x96FE },
+ { 0x9740, 0x977E },
+ { 0x9780, 0x97FE },
+ { 0x9840, 0x987E },
+ { 0x9880, 0x98FE },
+ { 0x9940, 0x997E },
+ { 0x9980, 0x99FE },
+ { 0x9A40, 0x9A7E },
+ { 0x9A80, 0x9AFE },
+ { 0x9B40, 0x9B7E },
+ { 0x9B80, 0x9BFE },
+ { 0x9C40, 0x9C7E },
+ { 0x9C80, 0x9CFE },
+ { 0x9D40, 0x9D7E },
+ { 0x9D80, 0x9DFE },
+ { 0x9E40, 0x9E7E },
+ { 0x9E80, 0x9EFE },
+ { 0x9F40, 0x9F7E },
+ { 0x9F80, 0x9FFE },
+ { 0xA040, 0xA07E },
+ { 0xA080, 0xA0FE },
+ { 0xA1A1, 0xA1FE },
+ { 0xA2A1, 0xA2AA },
+ { 0xA2B1, 0xA2E2 },
+ { 0xA2E5, 0xA2EE },
+ { 0xA2F1, 0xA2FC },
+ { 0xA3A1, 0xA3FE },
+ { 0xA4A1, 0xA4F3 },
+ { 0xA5A1, 0xA5F6 },
+ { 0xA6A1, 0xA6B8 },
+ { 0xA6C1, 0xA6D8 },
+ { 0xA6E0, 0xA6EB },
+ { 0xA6EE, 0xA6F2 },
+ { 0xA6F4, 0xA6F5 },
+ { 0xA7A1, 0xA7C1 },
+ { 0xA7D1, 0xA7F1 },
+ { 0xA840, 0xA87E },
+ { 0xA880, 0xA895 },
+ { 0xA8A1, 0xA8BB },
+ { 0xA8BD, 0xA8BE },
+ { 0xA8C0, 0xA8C0 },
+ { 0xA8C5, 0xA8E9 },
+ { 0xA940, 0xA957 },
+ { 0xA959, 0xA95A },
+ { 0xA95C, 0xA95C },
+ { 0xA960, 0xA97E },
+ { 0xA980, 0xA988 },
+ { 0xA996, 0xA996 },
+ { 0xA9A4, 0xA9EF },
+ { 0xAA40, 0xAA7E },
+ { 0xAA80, 0xAAA0 },
+ { 0xAB40, 0xAB7E },
+ { 0xAB80, 0xABA0 },
+ { 0xAC40, 0xAC7E },
+ { 0xAC80, 0xACA0 },
+ { 0xAD40, 0xAD7E },
+ { 0xAD80, 0xADA0 },
+ { 0xAE40, 0xAE7E },
+ { 0xAE80, 0xAEA0 },
+ { 0xAF40, 0xAF7E },
+ { 0xAF80, 0xAFA0 },
+ { 0xB040, 0xB07E },
+ { 0xB080, 0xB0FE },
+ { 0xB140, 0xB17E },
+ { 0xB180, 0xB1FE },
+ { 0xB240, 0xB27E },
+ { 0xB280, 0xB2FE },
+ { 0xB340, 0xB37E },
+ { 0xB380, 0xB3FE },
+ { 0xB440, 0xB47E },
+ { 0xB480, 0xB4FE },
+ { 0xB540, 0xB57E },
+ { 0xB580, 0xB5FE },
+ { 0xB640, 0xB67E },
+ { 0xB680, 0xB6FE },
+ { 0xB740, 0xB77E },
+ { 0xB780, 0xB7FE },
+ { 0xB840, 0xB87E },
+ { 0xB880, 0xB8FE },
+ { 0xB940, 0xB97E },
+ { 0xB980, 0xB9FE },
+ { 0xBA40, 0xBA7E },
+ { 0xBA80, 0xBAFE },
+ { 0xBB40, 0xBB7E },
+ { 0xBB80, 0xBBFE },
+ { 0xBC40, 0xBC7E },
+ { 0xBC80, 0xBCFE },
+ { 0xBD40, 0xBD7E },
+ { 0xBD80, 0xBDFE },
+ { 0xBE40, 0xBE7E },
+ { 0xBE80, 0xBEFE },
+ { 0xBF40, 0xBF7E },
+ { 0xBF80, 0xBFFE },
+ { 0xC040, 0xC07E },
+ { 0xC080, 0xC0FE },
+ { 0xC140, 0xC17E },
+ { 0xC180, 0xC1FE },
+ { 0xC240, 0xC27E },
+ { 0xC280, 0xC2FE },
+ { 0xC340, 0xC37E },
+ { 0xC380, 0xC3FE },
+ { 0xC440, 0xC47E },
+ { 0xC480, 0xC4FE },
+ { 0xC540, 0xC57E },
+ { 0xC580, 0xC5FE },
+ { 0xC640, 0xC67E },
+ { 0xC680, 0xC6FE },
+ { 0xC740, 0xC77E },
+ { 0xC780, 0xC7FE },
+ { 0xC840, 0xC87E },
+ { 0xC880, 0xC8FE },
+ { 0xC940, 0xC97E },
+ { 0xC980, 0xC9FE },
+ { 0xCA40, 0xCA7E },
+ { 0xCA80, 0xCAFE },
+ { 0xCB40, 0xCB7E },
+ { 0xCB80, 0xCBFE },
+ { 0xCC40, 0xCC7E },
+ { 0xCC80, 0xCCFE },
+ { 0xCD40, 0xCD7E },
+ { 0xCD80, 0xCDFE },
+ { 0xCE40, 0xCE7E },
+ { 0xCE80, 0xCEFE },
+ { 0xCF40, 0xCF7E },
+ { 0xCF80, 0xCFFE },
+ { 0xD040, 0xD07E },
+ { 0xD080, 0xD0FE },
+ { 0xD140, 0xD17E },
+ { 0xD180, 0xD1FE },
+ { 0xD240, 0xD27E },
+ { 0xD280, 0xD2FE },
+ { 0xD340, 0xD37E },
+ { 0xD380, 0xD3FE },
+ { 0xD440, 0xD47E },
+ { 0xD480, 0xD4FE },
+ { 0xD540, 0xD57E },
+ { 0xD580, 0xD5FE },
+ { 0xD640, 0xD67E },
+ { 0xD680, 0xD6FE },
+ { 0xD740, 0xD77E },
+ { 0xD780, 0xD7F9 },
+ { 0xD840, 0xD87E },
+ { 0xD880, 0xD8FE },
+ { 0xD940, 0xD97E },
+ { 0xD980, 0xD9FE },
+ { 0xDA40, 0xDA7E },
+ { 0xDA80, 0xDAFE },
+ { 0xDB40, 0xDB7E },
+ { 0xDB80, 0xDBFE },
+ { 0xDC40, 0xDC7E },
+ { 0xDC80, 0xDCFE },
+ { 0xDD40, 0xDD7E },
+ { 0xDD80, 0xDDFE },
+ { 0xDE40, 0xDE7E },
+ { 0xDE80, 0xDEFE },
+ { 0xDF40, 0xDF7E },
+ { 0xDF80, 0xDFFE },
+ { 0xE040, 0xE07E },
+ { 0xE080, 0xE0FE },
+ { 0xE140, 0xE17E },
+ { 0xE180, 0xE1FE },
+ { 0xE240, 0xE27E },
+ { 0xE280, 0xE2FE },
+ { 0xE340, 0xE37E },
+ { 0xE380, 0xE3FE },
+ { 0xE440, 0xE47E },
+ { 0xE480, 0xE4FE },
+ { 0xE540, 0xE57E },
+ { 0xE580, 0xE5FE },
+ { 0xE640, 0xE67E },
+ { 0xE680, 0xE6FE },
+ { 0xE740, 0xE77E },
+ { 0xE780, 0xE7FE },
+ { 0xE840, 0xE87E },
+ { 0xE880, 0xE8FE },
+ { 0xE940, 0xE97E },
+ { 0xE980, 0xE9FE },
+ { 0xEA40, 0xEA7E },
+ { 0xEA80, 0xEAFE },
+ { 0xEB40, 0xEB7E },
+ { 0xEB80, 0xEBFE },
+ { 0xEC40, 0xEC7E },
+ { 0xEC80, 0xECFE },
+ { 0xED40, 0xED7E },
+ { 0xED80, 0xEDFE },
+ { 0xEE40, 0xEE7E },
+ { 0xEE80, 0xEEFE },
+ { 0xEF40, 0xEF7E },
+ { 0xEF80, 0xEFFE },
+ { 0xF040, 0xF07E },
+ { 0xF080, 0xF0FE },
+ { 0xF140, 0xF17E },
+ { 0xF180, 0xF1FE },
+ { 0xF240, 0xF27E },
+ { 0xF280, 0xF2FE },
+ { 0xF340, 0xF37E },
+ { 0xF380, 0xF3FE },
+ { 0xF440, 0xF47E },
+ { 0xF480, 0xF4FE },
+ { 0xF540, 0xF57E },
+ { 0xF580, 0xF5FE },
+ { 0xF640, 0xF67E },
+ { 0xF680, 0xF6FE },
+ { 0xF740, 0xF77E },
+ { 0xF780, 0xF7FE },
+ { 0xF840, 0xF87E },
+ { 0xF880, 0xF8A0 },
+ { 0xF940, 0xF97E },
+ { 0xF980, 0xF9A0 },
+ { 0xFA40, 0xFA7E },
+ { 0xFA80, 0xFAA0 },
+ { 0xFB40, 0xFB7E },
+ { 0xFB80, 0xFBA0 },
+ { 0xFC40, 0xFC7E },
+ { 0xFC80, 0xFCA0 },
+ { 0xFD40, 0xFD7E },
+ { 0xFD80, 0xFDA0 },
+ { 0xFE40, 0xFE4F },
+};
+
+// generated from http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP949.TXT
+static const CharRange kEUCKRRanges[] = {
+ { 0x8141, 0x815A },
+ { 0x8161, 0x817A },
+ { 0x8181, 0x81FE },
+ { 0x8241, 0x825A },
+ { 0x8261, 0x827A },
+ { 0x8281, 0x82FE },
+ { 0x8341, 0x835A },
+ { 0x8361, 0x837A },
+ { 0x8381, 0x83FE },
+ { 0x8441, 0x845A },
+ { 0x8461, 0x847A },
+ { 0x8481, 0x84FE },
+ { 0x8541, 0x855A },
+ { 0x8561, 0x857A },
+ { 0x8581, 0x85FE },
+ { 0x8641, 0x865A },
+ { 0x8661, 0x867A },
+ { 0x8681, 0x86FE },
+ { 0x8741, 0x875A },
+ { 0x8761, 0x877A },
+ { 0x8781, 0x87FE },
+ { 0x8841, 0x885A },
+ { 0x8861, 0x887A },
+ { 0x8881, 0x88FE },
+ { 0x8941, 0x895A },
+ { 0x8961, 0x897A },
+ { 0x8981, 0x89FE },
+ { 0x8A41, 0x8A5A },
+ { 0x8A61, 0x8A7A },
+ { 0x8A81, 0x8AFE },
+ { 0x8B41, 0x8B5A },
+ { 0x8B61, 0x8B7A },
+ { 0x8B81, 0x8BFE },
+ { 0x8C41, 0x8C5A },
+ { 0x8C61, 0x8C7A },
+ { 0x8C81, 0x8CFE },
+ { 0x8D41, 0x8D5A },
+ { 0x8D61, 0x8D7A },
+ { 0x8D81, 0x8DFE },
+ { 0x8E41, 0x8E5A },
+ { 0x8E61, 0x8E7A },
+ { 0x8E81, 0x8EFE },
+ { 0x8F41, 0x8F5A },
+ { 0x8F61, 0x8F7A },
+ { 0x8F81, 0x8FFE },
+ { 0x9041, 0x905A },
+ { 0x9061, 0x907A },
+ { 0x9081, 0x90FE },
+ { 0x9141, 0x915A },
+ { 0x9161, 0x917A },
+ { 0x9181, 0x91FE },
+ { 0x9241, 0x925A },
+ { 0x9261, 0x927A },
+ { 0x9281, 0x92FE },
+ { 0x9341, 0x935A },
+ { 0x9361, 0x937A },
+ { 0x9381, 0x93FE },
+ { 0x9441, 0x945A },
+ { 0x9461, 0x947A },
+ { 0x9481, 0x94FE },
+ { 0x9541, 0x955A },
+ { 0x9561, 0x957A },
+ { 0x9581, 0x95FE },
+ { 0x9641, 0x965A },
+ { 0x9661, 0x967A },
+ { 0x9681, 0x96FE },
+ { 0x9741, 0x975A },
+ { 0x9761, 0x977A },
+ { 0x9781, 0x97FE },
+ { 0x9841, 0x985A },
+ { 0x9861, 0x987A },
+ { 0x9881, 0x98FE },
+ { 0x9941, 0x995A },
+ { 0x9961, 0x997A },
+ { 0x9981, 0x99FE },
+ { 0x9A41, 0x9A5A },
+ { 0x9A61, 0x9A7A },
+ { 0x9A81, 0x9AFE },
+ { 0x9B41, 0x9B5A },
+ { 0x9B61, 0x9B7A },
+ { 0x9B81, 0x9BFE },
+ { 0x9C41, 0x9C5A },
+ { 0x9C61, 0x9C7A },
+ { 0x9C81, 0x9CFE },
+ { 0x9D41, 0x9D5A },
+ { 0x9D61, 0x9D7A },
+ { 0x9D81, 0x9DFE },
+ { 0x9E41, 0x9E5A },
+ { 0x9E61, 0x9E7A },
+ { 0x9E81, 0x9EFE },
+ { 0x9F41, 0x9F5A },
+ { 0x9F61, 0x9F7A },
+ { 0x9F81, 0x9FFE },
+ { 0xA041, 0xA05A },
+ { 0xA061, 0xA07A },
+ { 0xA081, 0xA0FE },
+ { 0xA141, 0xA15A },
+ { 0xA161, 0xA17A },
+ { 0xA181, 0xA1FE },
+ { 0xA241, 0xA25A },
+ { 0xA261, 0xA27A },
+ { 0xA281, 0xA2E7 },
+ { 0xA341, 0xA35A },
+ { 0xA361, 0xA37A },
+ { 0xA381, 0xA3FE },
+ { 0xA441, 0xA45A },
+ { 0xA461, 0xA47A },
+ { 0xA481, 0xA4FE },
+ { 0xA541, 0xA55A },
+ { 0xA561, 0xA57A },
+ { 0xA581, 0xA5AA },
+ { 0xA5B0, 0xA5B9 },
+ { 0xA5C1, 0xA5D8 },
+ { 0xA5E1, 0xA5F8 },
+ { 0xA641, 0xA65A },
+ { 0xA661, 0xA67A },
+ { 0xA681, 0xA6E4 },
+ { 0xA741, 0xA75A },
+ { 0xA761, 0xA77A },
+ { 0xA781, 0xA7EF },
+ { 0xA841, 0xA85A },
+ { 0xA861, 0xA87A },
+ { 0xA881, 0xA8A4 },
+ { 0xA8A6, 0xA8A6 },
+ { 0xA8A8, 0xA8AF },
+ { 0xA8B1, 0xA8FE },
+ { 0xA941, 0xA95A },
+ { 0xA961, 0xA97A },
+ { 0xA981, 0xA9FE },
+ { 0xAA41, 0xAA5A },
+ { 0xAA61, 0xAA7A },
+ { 0xAA81, 0xAAF3 },
+ { 0xAB41, 0xAB5A },
+ { 0xAB61, 0xAB7A },
+ { 0xAB81, 0xABF6 },
+ { 0xAC41, 0xAC5A },
+ { 0xAC61, 0xAC7A },
+ { 0xAC81, 0xACC1 },
+ { 0xACD1, 0xACF1 },
+ { 0xAD41, 0xAD5A },
+ { 0xAD61, 0xAD7A },
+ { 0xAD81, 0xADA0 },
+ { 0xAE41, 0xAE5A },
+ { 0xAE61, 0xAE7A },
+ { 0xAE81, 0xAEA0 },
+ { 0xAF41, 0xAF5A },
+ { 0xAF61, 0xAF7A },
+ { 0xAF81, 0xAFA0 },
+ { 0xB041, 0xB05A },
+ { 0xB061, 0xB07A },
+ { 0xB081, 0xB0FE },
+ { 0xB141, 0xB15A },
+ { 0xB161, 0xB17A },
+ { 0xB181, 0xB1FE },
+ { 0xB241, 0xB25A },
+ { 0xB261, 0xB27A },
+ { 0xB281, 0xB2FE },
+ { 0xB341, 0xB35A },
+ { 0xB361, 0xB37A },
+ { 0xB381, 0xB3FE },
+ { 0xB441, 0xB45A },
+ { 0xB461, 0xB47A },
+ { 0xB481, 0xB4FE },
+ { 0xB541, 0xB55A },
+ { 0xB561, 0xB57A },
+ { 0xB581, 0xB5FE },
+ { 0xB641, 0xB65A },
+ { 0xB661, 0xB67A },
+ { 0xB681, 0xB6FE },
+ { 0xB741, 0xB75A },
+ { 0xB761, 0xB77A },
+ { 0xB781, 0xB7FE },
+ { 0xB841, 0xB85A },
+ { 0xB861, 0xB87A },
+ { 0xB881, 0xB8FE },
+ { 0xB941, 0xB95A },
+ { 0xB961, 0xB97A },
+ { 0xB981, 0xB9FE },
+ { 0xBA41, 0xBA5A },
+ { 0xBA61, 0xBA7A },
+ { 0xBA81, 0xBAFE },
+ { 0xBB41, 0xBB5A },
+ { 0xBB61, 0xBB7A },
+ { 0xBB81, 0xBBFE },
+ { 0xBC41, 0xBC5A },
+ { 0xBC61, 0xBC7A },
+ { 0xBC81, 0xBCFE },
+ { 0xBD41, 0xBD5A },
+ { 0xBD61, 0xBD7A },
+ { 0xBD81, 0xBDFE },
+ { 0xBE41, 0xBE5A },
+ { 0xBE61, 0xBE7A },
+ { 0xBE81, 0xBEFE },
+ { 0xBF41, 0xBF5A },
+ { 0xBF61, 0xBF7A },
+ { 0xBF81, 0xBFFE },
+ { 0xC041, 0xC05A },
+ { 0xC061, 0xC07A },
+ { 0xC081, 0xC0FE },
+ { 0xC141, 0xC15A },
+ { 0xC161, 0xC17A },
+ { 0xC181, 0xC1FE },
+ { 0xC241, 0xC25A },
+ { 0xC261, 0xC27A },
+ { 0xC281, 0xC2FE },
+ { 0xC341, 0xC35A },
+ { 0xC361, 0xC37A },
+ { 0xC381, 0xC3FE },
+ { 0xC441, 0xC45A },
+ { 0xC461, 0xC47A },
+ { 0xC481, 0xC4FE },
+ { 0xC541, 0xC55A },
+ { 0xC561, 0xC57A },
+ { 0xC581, 0xC5FE },
+ { 0xC641, 0xC652 },
+ { 0xC6A1, 0xC6FE },
+ { 0xC7A1, 0xC7FE },
+ { 0xC8A1, 0xC8FE },
+ { 0xCAA1, 0xCAFE },
+ { 0xCBA1, 0xCBFE },
+ { 0xCCA1, 0xCCFE },
+ { 0xCDA1, 0xCDFE },
+ { 0xCEA1, 0xCEFE },
+ { 0xCFA1, 0xCFFE },
+ { 0xD0A1, 0xD0FE },
+ { 0xD1A1, 0xD1FE },
+ { 0xD2A1, 0xD2FE },
+ { 0xD3A1, 0xD3FE },
+ { 0xD4A1, 0xD4FE },
+ { 0xD5A1, 0xD5FE },
+ { 0xD6A1, 0xD6FE },
+ { 0xD7A1, 0xD7FE },
+ { 0xD8A1, 0xD8FE },
+ { 0xD9A1, 0xD9FE },
+ { 0xDAA1, 0xDAFE },
+ { 0xDBA1, 0xDBFE },
+ { 0xDCA1, 0xDCFE },
+ { 0xDDA1, 0xDDFE },
+ { 0xDEA1, 0xDEFE },
+ { 0xDFA1, 0xDFFE },
+ { 0xE0A1, 0xE0FE },
+ { 0xE1A1, 0xE1FE },
+ { 0xE2A1, 0xE2FE },
+ { 0xE3A1, 0xE3FE },
+ { 0xE4A1, 0xE4FE },
+ { 0xE5A1, 0xE5FE },
+ { 0xE6A1, 0xE6FE },
+ { 0xE7A1, 0xE7FE },
+ { 0xE8A1, 0xE8FE },
+ { 0xE9A1, 0xE9FE },
+ { 0xEAA1, 0xEAFE },
+ { 0xEBA1, 0xEBFE },
+ { 0xECA1, 0xECFE },
+ { 0xEDA1, 0xEDFE },
+ { 0xEEA1, 0xEEFE },
+ { 0xEFA1, 0xEFFE },
+ { 0xF0A1, 0xF0FE },
+ { 0xF1A1, 0xF1FE },
+ { 0xF2A1, 0xF2FE },
+ { 0xF3A1, 0xF3FE },
+ { 0xF4A1, 0xF4FE },
+ { 0xF5A1, 0xF5FE },
+ { 0xF6A1, 0xF6FE },
+ { 0xF7A1, 0xF7FE },
+ { 0xF8A1, 0xF8FE },
+ { 0xF9A1, 0xF9FE },
+ { 0xFAA1, 0xFAFE },
+ { 0xFBA1, 0xFBFE },
+ { 0xFCA1, 0xFCFE },
+ { 0xFDA1, 0xFDFE },
+};
+
+// generated from http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP950.TXT
+static const CharRange kBig5Ranges[] = {
+ { 0xA140, 0xA17E },
+ { 0xA1A1, 0xA1FE },
+ { 0xA240, 0xA27E },
+ { 0xA2A1, 0xA2FE },
+ { 0xA340, 0xA37E },
+ { 0xA3A1, 0xA3BF },
+ { 0xA3E1, 0xA3E1 },
+ { 0xA440, 0xA47E },
+ { 0xA4A1, 0xA4FE },
+ { 0xA540, 0xA57E },
+ { 0xA5A1, 0xA5FE },
+ { 0xA640, 0xA67E },
+ { 0xA6A1, 0xA6FE },
+ { 0xA740, 0xA77E },
+ { 0xA7A1, 0xA7FE },
+ { 0xA840, 0xA87E },
+ { 0xA8A1, 0xA8FE },
+ { 0xA940, 0xA97E },
+ { 0xA9A1, 0xA9FE },
+ { 0xAA40, 0xAA7E },
+ { 0xAAA1, 0xAAFE },
+ { 0xAB40, 0xAB7E },
+ { 0xABA1, 0xABFE },
+ { 0xAC40, 0xAC7E },
+ { 0xACA1, 0xACFE },
+ { 0xAD40, 0xAD7E },
+ { 0xADA1, 0xADFE },
+ { 0xAE40, 0xAE7E },
+ { 0xAEA1, 0xAEFE },
+ { 0xAF40, 0xAF7E },
+ { 0xAFA1, 0xAFFE },
+ { 0xB040, 0xB07E },
+ { 0xB0A1, 0xB0FE },
+ { 0xB140, 0xB17E },
+ { 0xB1A1, 0xB1FE },
+ { 0xB240, 0xB27E },
+ { 0xB2A1, 0xB2FE },
+ { 0xB340, 0xB37E },
+ { 0xB3A1, 0xB3FE },
+ { 0xB440, 0xB47E },
+ { 0xB4A1, 0xB4FE },
+ { 0xB540, 0xB57E },
+ { 0xB5A1, 0xB5FE },
+ { 0xB640, 0xB67E },
+ { 0xB6A1, 0xB6FE },
+ { 0xB740, 0xB77E },
+ { 0xB7A1, 0xB7FE },
+ { 0xB840, 0xB87E },
+ { 0xB8A1, 0xB8FE },
+ { 0xB940, 0xB97E },
+ { 0xB9A1, 0xB9FE },
+ { 0xBA40, 0xBA7E },
+ { 0xBAA1, 0xBAFE },
+ { 0xBB40, 0xBB7E },
+ { 0xBBA1, 0xBBFE },
+ { 0xBC40, 0xBC7E },
+ { 0xBCA1, 0xBCFE },
+ { 0xBD40, 0xBD7E },
+ { 0xBDA1, 0xBDFE },
+ { 0xBE40, 0xBE7E },
+ { 0xBEA1, 0xBEFE },
+ { 0xBF40, 0xBF7E },
+ { 0xBFA1, 0xBFFE },
+ { 0xC040, 0xC07E },
+ { 0xC0A1, 0xC0FE },
+ { 0xC140, 0xC17E },
+ { 0xC1A1, 0xC1FE },
+ { 0xC240, 0xC27E },
+ { 0xC2A1, 0xC2FE },
+ { 0xC340, 0xC37E },
+ { 0xC3A1, 0xC3FE },
+ { 0xC440, 0xC47E },
+ { 0xC4A1, 0xC4FE },
+ { 0xC540, 0xC57E },
+ { 0xC5A1, 0xC5FE },
+ { 0xC640, 0xC67E },
+ { 0xC940, 0xC97E },
+ { 0xC9A1, 0xC9FE },
+ { 0xCA40, 0xCA7E },
+ { 0xCAA1, 0xCAFE },
+ { 0xCB40, 0xCB7E },
+ { 0xCBA1, 0xCBFE },
+ { 0xCC40, 0xCC7E },
+ { 0xCCA1, 0xCCFE },
+ { 0xCD40, 0xCD7E },
+ { 0xCDA1, 0xCDFE },
+ { 0xCE40, 0xCE7E },
+ { 0xCEA1, 0xCEFE },
+ { 0xCF40, 0xCF7E },
+ { 0xCFA1, 0xCFFE },
+ { 0xD040, 0xD07E },
+ { 0xD0A1, 0xD0FE },
+ { 0xD140, 0xD17E },
+ { 0xD1A1, 0xD1FE },
+ { 0xD240, 0xD27E },
+ { 0xD2A1, 0xD2FE },
+ { 0xD340, 0xD37E },
+ { 0xD3A1, 0xD3FE },
+ { 0xD440, 0xD47E },
+ { 0xD4A1, 0xD4FE },
+ { 0xD540, 0xD57E },
+ { 0xD5A1, 0xD5FE },
+ { 0xD640, 0xD67E },
+ { 0xD6A1, 0xD6FE },
+ { 0xD740, 0xD77E },
+ { 0xD7A1, 0xD7FE },
+ { 0xD840, 0xD87E },
+ { 0xD8A1, 0xD8FE },
+ { 0xD940, 0xD97E },
+ { 0xD9A1, 0xD9FE },
+ { 0xDA40, 0xDA7E },
+ { 0xDAA1, 0xDAFE },
+ { 0xDB40, 0xDB7E },
+ { 0xDBA1, 0xDBFE },
+ { 0xDC40, 0xDC7E },
+ { 0xDCA1, 0xDCFE },
+ { 0xDD40, 0xDD7E },
+ { 0xDDA1, 0xDDFE },
+ { 0xDE40, 0xDE7E },
+ { 0xDEA1, 0xDEFE },
+ { 0xDF40, 0xDF7E },
+ { 0xDFA1, 0xDFFE },
+ { 0xE040, 0xE07E },
+ { 0xE0A1, 0xE0FE },
+ { 0xE140, 0xE17E },
+ { 0xE1A1, 0xE1FE },
+ { 0xE240, 0xE27E },
+ { 0xE2A1, 0xE2FE },
+ { 0xE340, 0xE37E },
+ { 0xE3A1, 0xE3FE },
+ { 0xE440, 0xE47E },
+ { 0xE4A1, 0xE4FE },
+ { 0xE540, 0xE57E },
+ { 0xE5A1, 0xE5FE },
+ { 0xE640, 0xE67E },
+ { 0xE6A1, 0xE6FE },
+ { 0xE740, 0xE77E },
+ { 0xE7A1, 0xE7FE },
+ { 0xE840, 0xE87E },
+ { 0xE8A1, 0xE8FE },
+ { 0xE940, 0xE97E },
+ { 0xE9A1, 0xE9FE },
+ { 0xEA40, 0xEA7E },
+ { 0xEAA1, 0xEAFE },
+ { 0xEB40, 0xEB7E },
+ { 0xEBA1, 0xEBFE },
+ { 0xEC40, 0xEC7E },
+ { 0xECA1, 0xECFE },
+ { 0xED40, 0xED7E },
+ { 0xEDA1, 0xEDFE },
+ { 0xEE40, 0xEE7E },
+ { 0xEEA1, 0xEEFE },
+ { 0xEF40, 0xEF7E },
+ { 0xEFA1, 0xEFFE },
+ { 0xF040, 0xF07E },
+ { 0xF0A1, 0xF0FE },
+ { 0xF140, 0xF17E },
+ { 0xF1A1, 0xF1FE },
+ { 0xF240, 0xF27E },
+ { 0xF2A1, 0xF2FE },
+ { 0xF340, 0xF37E },
+ { 0xF3A1, 0xF3FE },
+ { 0xF440, 0xF47E },
+ { 0xF4A1, 0xF4FE },
+ { 0xF540, 0xF57E },
+ { 0xF5A1, 0xF5FE },
+ { 0xF640, 0xF67E },
+ { 0xF6A1, 0xF6FE },
+ { 0xF740, 0xF77E },
+ { 0xF7A1, 0xF7FE },
+ { 0xF840, 0xF87E },
+ { 0xF8A1, 0xF8FE },
+ { 0xF940, 0xF97E },
+ { 0xF9A1, 0xF9FE },
+};
+
+static bool charMatchesEncoding(int ch, const CharRange* encodingRanges, int rangeCount) {
+ // Use binary search to see if the character is contained in the encoding
+ int low = 0;
+ int high = rangeCount;
+
+ while (low < high) {
+ int i = (low + high) / 2;
+ const CharRange* range = &encodingRanges[i];
+ if (ch >= range->first && ch <= range->last)
+ return true;
+ if (ch > range->last)
+ low = i + 1;
+ else
+ high = i;
+ }
+
+ return false;
+}
+
+extern uint32_t findPossibleEncodings(int ch)
+{
+ // ASCII matches everything
+ if (ch < 256) return kEncodingAll;
+
+ int result = kEncodingNone;
+
+ if (charMatchesEncoding(ch, kShiftJISRanges, ARRAY_SIZE(kShiftJISRanges)))
+ result |= kEncodingShiftJIS;
+ if (charMatchesEncoding(ch, kGBKRanges, ARRAY_SIZE(kGBKRanges)))
+ result |= kEncodingGBK;
+ if (charMatchesEncoding(ch, kBig5Ranges, ARRAY_SIZE(kBig5Ranges)))
+ result |= kEncodingBig5;
+ if (charMatchesEncoding(ch, kEUCKRRanges, ARRAY_SIZE(kEUCKRRanges)))
+ result |= kEncodingEUCKR;
+
+ return result;
+}
diff --git a/media/libmedia/autodetect.h b/media/libmedia/autodetect.h
new file mode 100644
index 0000000..9675db3
--- /dev/null
+++ b/media/libmedia/autodetect.h
@@ -0,0 +1,37 @@
+/*
+ * 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 AUTODETECT_H
+#define AUTODETECT_H
+
+#include <inttypes.h>
+
+// flags used for native encoding detection
+enum {
+ kEncodingNone = 0,
+ kEncodingShiftJIS = (1 << 0),
+ kEncodingGBK = (1 << 1),
+ kEncodingBig5 = (1 << 2),
+ kEncodingEUCKR = (1 << 3),
+
+ kEncodingAll = (kEncodingShiftJIS | kEncodingGBK | kEncodingBig5 | kEncodingEUCKR),
+};
+
+
+// returns a bitfield containing the possible native encodings for the given character
+extern uint32_t findPossibleEncodings(int ch);
+
+#endif // AUTODETECT_H
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
new file mode 100644
index 0000000..b0241aa
--- /dev/null
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -0,0 +1,174 @@
+/*
+**
+** 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.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaMetadataRetriever"
+
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <media/mediametadataretriever.h>
+#include <media/IMediaPlayerService.h>
+#include <utils/Log.h>
+#include <dlfcn.h>
+
+namespace android {
+
+// client singleton for binder interface to service
+Mutex MediaMetadataRetriever::sServiceLock;
+sp<IMediaPlayerService> MediaMetadataRetriever::sService;
+sp<MediaMetadataRetriever::DeathNotifier> MediaMetadataRetriever::sDeathNotifier;
+
+const sp<IMediaPlayerService>& MediaMetadataRetriever::getService()
+{
+ Mutex::Autolock lock(sServiceLock);
+ if (sService == 0) {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder;
+ do {
+ binder = sm->getService(String16("media.player"));
+ if (binder != 0) {
+ break;
+ }
+ ALOGW("MediaPlayerService not published, waiting...");
+ usleep(500000); // 0.5 s
+ } while (true);
+ if (sDeathNotifier == NULL) {
+ sDeathNotifier = new DeathNotifier();
+ }
+ binder->linkToDeath(sDeathNotifier);
+ sService = interface_cast<IMediaPlayerService>(binder);
+ }
+ ALOGE_IF(sService == 0, "no MediaPlayerService!?");
+ return sService;
+}
+
+MediaMetadataRetriever::MediaMetadataRetriever()
+{
+ ALOGV("constructor");
+ const sp<IMediaPlayerService>& service(getService());
+ if (service == 0) {
+ ALOGE("failed to obtain MediaMetadataRetrieverService");
+ return;
+ }
+ sp<IMediaMetadataRetriever> retriever(service->createMetadataRetriever(getpid()));
+ if (retriever == 0) {
+ ALOGE("failed to create IMediaMetadataRetriever object from server");
+ }
+ mRetriever = retriever;
+}
+
+MediaMetadataRetriever::~MediaMetadataRetriever()
+{
+ ALOGV("destructor");
+ disconnect();
+ IPCThreadState::self()->flushCommands();
+}
+
+void MediaMetadataRetriever::disconnect()
+{
+ ALOGV("disconnect");
+ sp<IMediaMetadataRetriever> retriever;
+ {
+ Mutex::Autolock _l(mLock);
+ retriever = mRetriever;
+ mRetriever.clear();
+ }
+ if (retriever != 0) {
+ retriever->disconnect();
+ }
+}
+
+status_t MediaMetadataRetriever::setDataSource(
+ const char *srcUrl, const KeyedVector<String8, String8> *headers)
+{
+ ALOGV("setDataSource");
+ Mutex::Autolock _l(mLock);
+ if (mRetriever == 0) {
+ ALOGE("retriever is not initialized");
+ return INVALID_OPERATION;
+ }
+ if (srcUrl == NULL) {
+ ALOGE("data source is a null pointer");
+ return UNKNOWN_ERROR;
+ }
+ ALOGV("data source (%s)", srcUrl);
+ return mRetriever->setDataSource(srcUrl, headers);
+}
+
+status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
+{
+ ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
+ Mutex::Autolock _l(mLock);
+ if (mRetriever == 0) {
+ ALOGE("retriever is not initialized");
+ return INVALID_OPERATION;
+ }
+ if (fd < 0 || offset < 0 || length < 0) {
+ ALOGE("Invalid negative argument");
+ return UNKNOWN_ERROR;
+ }
+ return mRetriever->setDataSource(fd, offset, length);
+}
+
+sp<IMemory> MediaMetadataRetriever::getFrameAtTime(int64_t timeUs, int option)
+{
+ ALOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option);
+ Mutex::Autolock _l(mLock);
+ if (mRetriever == 0) {
+ ALOGE("retriever is not initialized");
+ return NULL;
+ }
+ return mRetriever->getFrameAtTime(timeUs, option);
+}
+
+const char* MediaMetadataRetriever::extractMetadata(int keyCode)
+{
+ ALOGV("extractMetadata(%d)", keyCode);
+ Mutex::Autolock _l(mLock);
+ if (mRetriever == 0) {
+ ALOGE("retriever is not initialized");
+ return NULL;
+ }
+ return mRetriever->extractMetadata(keyCode);
+}
+
+sp<IMemory> MediaMetadataRetriever::extractAlbumArt()
+{
+ ALOGV("extractAlbumArt");
+ Mutex::Autolock _l(mLock);
+ if (mRetriever == 0) {
+ ALOGE("retriever is not initialized");
+ return NULL;
+ }
+ return mRetriever->extractAlbumArt();
+}
+
+void MediaMetadataRetriever::DeathNotifier::binderDied(const wp<IBinder>& who) {
+ Mutex::Autolock lock(MediaMetadataRetriever::sServiceLock);
+ MediaMetadataRetriever::sService.clear();
+ ALOGW("MediaMetadataRetriever server died!");
+}
+
+MediaMetadataRetriever::DeathNotifier::~DeathNotifier()
+{
+ Mutex::Autolock lock(sServiceLock);
+ if (sService != 0) {
+ sService->asBinder()->unlinkToDeath(this);
+ }
+}
+
+}; // namespace android
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
new file mode 100644
index 0000000..b52a37d
--- /dev/null
+++ b/media/libmedia/mediaplayer.cpp
@@ -0,0 +1,798 @@
+/*
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT 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 "MediaPlayer"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+
+#include <gui/SurfaceTextureClient.h>
+
+#include <media/mediaplayer.h>
+#include <media/AudioSystem.h>
+
+#include <binder/MemoryBase.h>
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+#include <system/audio.h>
+#include <system/window.h>
+
+namespace android {
+
+MediaPlayer::MediaPlayer()
+{
+ ALOGV("constructor");
+ mListener = NULL;
+ mCookie = NULL;
+ mDuration = -1;
+ mStreamType = AUDIO_STREAM_MUSIC;
+ mCurrentPosition = -1;
+ mSeekPosition = -1;
+ mCurrentState = MEDIA_PLAYER_IDLE;
+ mPrepareSync = false;
+ mPrepareStatus = NO_ERROR;
+ mLoop = false;
+ mLeftVolume = mRightVolume = 1.0;
+ mVideoWidth = mVideoHeight = 0;
+ mLockThreadId = 0;
+ mAudioSessionId = AudioSystem::newAudioSessionId();
+ AudioSystem::acquireAudioSessionId(mAudioSessionId);
+ mSendLevel = 0;
+ mRetransmitEndpointValid = false;
+}
+
+MediaPlayer::~MediaPlayer()
+{
+ ALOGV("destructor");
+ AudioSystem::releaseAudioSessionId(mAudioSessionId);
+ disconnect();
+ IPCThreadState::self()->flushCommands();
+}
+
+void MediaPlayer::disconnect()
+{
+ ALOGV("disconnect");
+ sp<IMediaPlayer> p;
+ {
+ Mutex::Autolock _l(mLock);
+ p = mPlayer;
+ mPlayer.clear();
+ }
+
+ if (p != 0) {
+ p->disconnect();
+ }
+}
+
+// always call with lock held
+void MediaPlayer::clear_l()
+{
+ mDuration = -1;
+ mCurrentPosition = -1;
+ mSeekPosition = -1;
+ mVideoWidth = mVideoHeight = 0;
+ mRetransmitEndpointValid = false;
+}
+
+status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)
+{
+ ALOGV("setListener");
+ Mutex::Autolock _l(mLock);
+ mListener = listener;
+ return NO_ERROR;
+}
+
+
+status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
+{
+ status_t err = UNKNOWN_ERROR;
+ sp<IMediaPlayer> p;
+ { // scope for the lock
+ Mutex::Autolock _l(mLock);
+
+ if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
+ (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
+ ALOGE("attachNewPlayer called in state %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ clear_l();
+ p = mPlayer;
+ mPlayer = player;
+ if (player != 0) {
+ mCurrentState = MEDIA_PLAYER_INITIALIZED;
+ err = NO_ERROR;
+ } else {
+ ALOGE("Unable to to create media player");
+ }
+ }
+
+ if (p != 0) {
+ p->disconnect();
+ }
+
+ return err;
+}
+
+status_t MediaPlayer::setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers)
+{
+ ALOGV("setDataSource(%s)", url);
+ status_t err = BAD_VALUE;
+ if (url != NULL) {
+ const sp<IMediaPlayerService>& service(getMediaPlayerService());
+ if (service != 0) {
+ sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
+ if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
+ (NO_ERROR != player->setDataSource(url, headers))) {
+ player.clear();
+ }
+ err = attachNewPlayer(player);
+ }
+ }
+ return err;
+}
+
+status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
+{
+ ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
+ status_t err = UNKNOWN_ERROR;
+ const sp<IMediaPlayerService>& service(getMediaPlayerService());
+ if (service != 0) {
+ sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
+ if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
+ (NO_ERROR != player->setDataSource(fd, offset, length))) {
+ player.clear();
+ }
+ err = attachNewPlayer(player);
+ }
+ return err;
+}
+
+status_t MediaPlayer::setDataSource(const sp<IStreamSource> &source)
+{
+ ALOGV("setDataSource");
+ status_t err = UNKNOWN_ERROR;
+ const sp<IMediaPlayerService>& service(getMediaPlayerService());
+ if (service != 0) {
+ sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
+ if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
+ (NO_ERROR != player->setDataSource(source))) {
+ player.clear();
+ }
+ err = attachNewPlayer(player);
+ }
+ return err;
+}
+
+status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply)
+{
+ Mutex::Autolock _l(mLock);
+ const bool hasBeenInitialized =
+ (mCurrentState != MEDIA_PLAYER_STATE_ERROR) &&
+ ((mCurrentState & MEDIA_PLAYER_IDLE) != MEDIA_PLAYER_IDLE);
+ if ((mPlayer != NULL) && hasBeenInitialized) {
+ ALOGV("invoke %d", request.dataSize());
+ return mPlayer->invoke(request, reply);
+ }
+ ALOGE("invoke failed: wrong state %X", mCurrentState);
+ return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::setMetadataFilter(const Parcel& filter)
+{
+ ALOGD("setMetadataFilter");
+ Mutex::Autolock lock(mLock);
+ if (mPlayer == NULL) {
+ return NO_INIT;
+ }
+ return mPlayer->setMetadataFilter(filter);
+}
+
+status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *metadata)
+{
+ ALOGD("getMetadata");
+ Mutex::Autolock lock(mLock);
+ if (mPlayer == NULL) {
+ return NO_INIT;
+ }
+ return mPlayer->getMetadata(update_only, apply_filter, metadata);
+}
+
+status_t MediaPlayer::setVideoSurfaceTexture(
+ const sp<ISurfaceTexture>& surfaceTexture)
+{
+ ALOGV("setVideoSurfaceTexture");
+ Mutex::Autolock _l(mLock);
+ if (mPlayer == 0) return NO_INIT;
+ return mPlayer->setVideoSurfaceTexture(surfaceTexture);
+}
+
+// must call with lock held
+status_t MediaPlayer::prepareAsync_l()
+{
+ if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
+ mPlayer->setAudioStreamType(mStreamType);
+ mCurrentState = MEDIA_PLAYER_PREPARING;
+ return mPlayer->prepareAsync();
+ }
+ ALOGE("prepareAsync called in state %d", mCurrentState);
+ return INVALID_OPERATION;
+}
+
+// TODO: In case of error, prepareAsync provides the caller with 2 error codes,
+// one defined in the Android framework and one provided by the implementation
+// that generated the error. The sync version of prepare returns only 1 error
+// code.
+status_t MediaPlayer::prepare()
+{
+ ALOGV("prepare");
+ Mutex::Autolock _l(mLock);
+ mLockThreadId = getThreadId();
+ if (mPrepareSync) {
+ mLockThreadId = 0;
+ return -EALREADY;
+ }
+ mPrepareSync = true;
+ status_t ret = prepareAsync_l();
+ if (ret != NO_ERROR) {
+ mLockThreadId = 0;
+ return ret;
+ }
+
+ if (mPrepareSync) {
+ mSignal.wait(mLock); // wait for prepare done
+ mPrepareSync = false;
+ }
+ ALOGV("prepare complete - status=%d", mPrepareStatus);
+ mLockThreadId = 0;
+ return mPrepareStatus;
+}
+
+status_t MediaPlayer::prepareAsync()
+{
+ ALOGV("prepareAsync");
+ Mutex::Autolock _l(mLock);
+ return prepareAsync_l();
+}
+
+status_t MediaPlayer::start()
+{
+ ALOGV("start");
+ Mutex::Autolock _l(mLock);
+ if (mCurrentState & MEDIA_PLAYER_STARTED)
+ return NO_ERROR;
+ if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED |
+ 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) {
+ mCurrentState = MEDIA_PLAYER_STATE_ERROR;
+ } else {
+ if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) {
+ ALOGV("playback completed immediately following start()");
+ }
+ }
+ return ret;
+ }
+ ALOGE("start called in state %d", mCurrentState);
+ return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::stop()
+{
+ ALOGV("stop");
+ Mutex::Autolock _l(mLock);
+ if (mCurrentState & MEDIA_PLAYER_STOPPED) return NO_ERROR;
+ if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED |
+ MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) ) {
+ status_t ret = mPlayer->stop();
+ if (ret != NO_ERROR) {
+ mCurrentState = MEDIA_PLAYER_STATE_ERROR;
+ } else {
+ mCurrentState = MEDIA_PLAYER_STOPPED;
+ }
+ return ret;
+ }
+ ALOGE("stop called in state %d", mCurrentState);
+ return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::pause()
+{
+ ALOGV("pause");
+ Mutex::Autolock _l(mLock);
+ if (mCurrentState & (MEDIA_PLAYER_PAUSED|MEDIA_PLAYER_PLAYBACK_COMPLETE))
+ return NO_ERROR;
+ if ((mPlayer != 0) && (mCurrentState & MEDIA_PLAYER_STARTED)) {
+ status_t ret = mPlayer->pause();
+ if (ret != NO_ERROR) {
+ mCurrentState = MEDIA_PLAYER_STATE_ERROR;
+ } else {
+ mCurrentState = MEDIA_PLAYER_PAUSED;
+ }
+ return ret;
+ }
+ ALOGE("pause called in state %d", mCurrentState);
+ return INVALID_OPERATION;
+}
+
+bool MediaPlayer::isPlaying()
+{
+ Mutex::Autolock _l(mLock);
+ if (mPlayer != 0) {
+ bool temp = false;
+ mPlayer->isPlaying(&temp);
+ ALOGV("isPlaying: %d", temp);
+ if ((mCurrentState & MEDIA_PLAYER_STARTED) && ! temp) {
+ ALOGE("internal/external state mismatch corrected");
+ mCurrentState = MEDIA_PLAYER_PAUSED;
+ }
+ return temp;
+ }
+ ALOGV("isPlaying: no active player");
+ return false;
+}
+
+status_t MediaPlayer::getVideoWidth(int *w)
+{
+ ALOGV("getVideoWidth");
+ Mutex::Autolock _l(mLock);
+ if (mPlayer == 0) return INVALID_OPERATION;
+ *w = mVideoWidth;
+ return NO_ERROR;
+}
+
+status_t MediaPlayer::getVideoHeight(int *h)
+{
+ ALOGV("getVideoHeight");
+ Mutex::Autolock _l(mLock);
+ if (mPlayer == 0) return INVALID_OPERATION;
+ *h = mVideoHeight;
+ return NO_ERROR;
+}
+
+status_t MediaPlayer::getCurrentPosition(int *msec)
+{
+ ALOGV("getCurrentPosition");
+ Mutex::Autolock _l(mLock);
+ if (mPlayer != 0) {
+ if (mCurrentPosition >= 0) {
+ ALOGV("Using cached seek position: %d", mCurrentPosition);
+ *msec = mCurrentPosition;
+ return NO_ERROR;
+ }
+ return mPlayer->getCurrentPosition(msec);
+ }
+ return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::getDuration_l(int *msec)
+{
+ ALOGV("getDuration");
+ bool isValidState = (mCurrentState & (MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_STOPPED | MEDIA_PLAYER_PLAYBACK_COMPLETE));
+ if (mPlayer != 0 && isValidState) {
+ status_t ret = NO_ERROR;
+ if (mDuration <= 0)
+ ret = mPlayer->getDuration(&mDuration);
+ if (msec)
+ *msec = mDuration;
+ return ret;
+ }
+ ALOGE("Attempt to call getDuration without a valid mediaplayer");
+ return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::getDuration(int *msec)
+{
+ Mutex::Autolock _l(mLock);
+ return getDuration_l(msec);
+}
+
+status_t MediaPlayer::seekTo_l(int msec)
+{
+ ALOGV("seekTo %d", msec);
+ if ((mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_STARTED | MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE) ) ) {
+ if ( msec < 0 ) {
+ ALOGW("Attempt to seek to invalid position: %d", msec);
+ msec = 0;
+ } else if ((mDuration > 0) && (msec > mDuration)) {
+ ALOGW("Attempt to seek to past end of file: request = %d, EOF = %d", msec, mDuration);
+ msec = mDuration;
+ }
+ // cache duration
+ mCurrentPosition = msec;
+ if (mSeekPosition < 0) {
+ getDuration_l(NULL);
+ mSeekPosition = msec;
+ return mPlayer->seekTo(msec);
+ }
+ else {
+ ALOGV("Seek in progress - queue up seekTo[%d]", msec);
+ return NO_ERROR;
+ }
+ }
+ ALOGE("Attempt to perform seekTo in wrong state: mPlayer=%p, mCurrentState=%u", mPlayer.get(), mCurrentState);
+ return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::seekTo(int msec)
+{
+ mLockThreadId = getThreadId();
+ Mutex::Autolock _l(mLock);
+ status_t result = seekTo_l(msec);
+ mLockThreadId = 0;
+
+ return result;
+}
+
+status_t MediaPlayer::reset_l()
+{
+ mLoop = false;
+ if (mCurrentState == MEDIA_PLAYER_IDLE) return NO_ERROR;
+ mPrepareSync = false;
+ if (mPlayer != 0) {
+ status_t ret = mPlayer->reset();
+ if (ret != NO_ERROR) {
+ ALOGE("reset() failed with return code (%d)", ret);
+ mCurrentState = MEDIA_PLAYER_STATE_ERROR;
+ } else {
+ mCurrentState = MEDIA_PLAYER_IDLE;
+ }
+ // setDataSource has to be called again to create a
+ // new mediaplayer.
+ mPlayer = 0;
+ return ret;
+ }
+ clear_l();
+ return NO_ERROR;
+}
+
+status_t MediaPlayer::doSetRetransmitEndpoint(const sp<IMediaPlayer>& player) {
+ Mutex::Autolock _l(mLock);
+
+ if (player == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (mRetransmitEndpointValid) {
+ return player->setRetransmitEndpoint(&mRetransmitEndpoint);
+ }
+
+ return OK;
+}
+
+status_t MediaPlayer::reset()
+{
+ ALOGV("reset");
+ Mutex::Autolock _l(mLock);
+ return reset_l();
+}
+
+status_t MediaPlayer::setAudioStreamType(audio_stream_type_t type)
+{
+ ALOGV("MediaPlayer::setAudioStreamType");
+ Mutex::Autolock _l(mLock);
+ if (mStreamType == type) return NO_ERROR;
+ if (mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_STARTED |
+ MEDIA_PLAYER_PAUSED | MEDIA_PLAYER_PLAYBACK_COMPLETE ) ) {
+ // Can't change the stream type after prepare
+ ALOGE("setAudioStream called in state %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+ // cache
+ mStreamType = type;
+ return OK;
+}
+
+status_t MediaPlayer::setLooping(int loop)
+{
+ ALOGV("MediaPlayer::setLooping");
+ Mutex::Autolock _l(mLock);
+ mLoop = (loop != 0);
+ if (mPlayer != 0) {
+ return mPlayer->setLooping(loop);
+ }
+ return OK;
+}
+
+bool MediaPlayer::isLooping() {
+ ALOGV("isLooping");
+ Mutex::Autolock _l(mLock);
+ if (mPlayer != 0) {
+ return mLoop;
+ }
+ ALOGV("isLooping: no active player");
+ return false;
+}
+
+status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
+{
+ ALOGV("MediaPlayer::setVolume(%f, %f)", leftVolume, rightVolume);
+ Mutex::Autolock _l(mLock);
+ mLeftVolume = leftVolume;
+ mRightVolume = rightVolume;
+ if (mPlayer != 0) {
+ return mPlayer->setVolume(leftVolume, rightVolume);
+ }
+ return OK;
+}
+
+status_t MediaPlayer::setAudioSessionId(int sessionId)
+{
+ ALOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
+ Mutex::Autolock _l(mLock);
+ if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
+ ALOGE("setAudioSessionId called in state %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+ if (sessionId < 0) {
+ return BAD_VALUE;
+ }
+ if (sessionId != mAudioSessionId) {
+ AudioSystem::releaseAudioSessionId(mAudioSessionId);
+ AudioSystem::acquireAudioSessionId(sessionId);
+ mAudioSessionId = sessionId;
+ }
+ return NO_ERROR;
+}
+
+int MediaPlayer::getAudioSessionId()
+{
+ Mutex::Autolock _l(mLock);
+ return mAudioSessionId;
+}
+
+status_t MediaPlayer::setAuxEffectSendLevel(float level)
+{
+ ALOGV("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)
+{
+ ALOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
+ Mutex::Autolock _l(mLock);
+ if (mPlayer == 0 ||
+ (mCurrentState & MEDIA_PLAYER_IDLE) ||
+ (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
+ ALOGE("attachAuxEffect called in state %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ return mPlayer->attachAuxEffect(effectId);
+}
+
+status_t MediaPlayer::setParameter(int key, const Parcel& request)
+{
+ ALOGV("MediaPlayer::setParameter(%d)", key);
+ Mutex::Autolock _l(mLock);
+ if (mPlayer != NULL) {
+ return mPlayer->setParameter(key, request);
+ }
+ ALOGV("setParameter: no active player");
+ return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::getParameter(int key, Parcel *reply)
+{
+ ALOGV("MediaPlayer::getParameter(%d)", key);
+ Mutex::Autolock _l(mLock);
+ if (mPlayer != NULL) {
+ return mPlayer->getParameter(key, reply);
+ }
+ ALOGV("getParameter: no active player");
+ return INVALID_OPERATION;
+}
+
+status_t MediaPlayer::setRetransmitEndpoint(const char* addrString,
+ uint16_t port) {
+ ALOGV("MediaPlayer::setRetransmitEndpoint(%s:%hu)",
+ addrString ? addrString : "(null)", port);
+
+ Mutex::Autolock _l(mLock);
+ if ((mPlayer != NULL) || (mCurrentState != MEDIA_PLAYER_IDLE))
+ return INVALID_OPERATION;
+
+ if (NULL == addrString) {
+ mRetransmitEndpointValid = false;
+ return OK;
+ }
+
+ struct in_addr saddr;
+ if(!inet_aton(addrString, &saddr)) {
+ return BAD_VALUE;
+ }
+
+ memset(&mRetransmitEndpoint, 0, sizeof(&mRetransmitEndpoint));
+ mRetransmitEndpoint.sin_family = AF_INET;
+ mRetransmitEndpoint.sin_addr = saddr;
+ mRetransmitEndpoint.sin_port = htons(port);
+ mRetransmitEndpointValid = true;
+
+ return OK;
+}
+
+void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
+{
+ ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
+ bool send = true;
+ bool locked = false;
+
+ // TODO: In the future, we might be on the same thread if the app is
+ // running in the same process as the media server. In that case,
+ // this will deadlock.
+ //
+ // The threadId hack below works around this for the care of prepare
+ // and seekTo within the same process.
+ // FIXME: Remember, this is a hack, it's not even a hack that is applied
+ // consistently for all use-cases, this needs to be revisited.
+ if (mLockThreadId != getThreadId()) {
+ mLock.lock();
+ locked = true;
+ }
+
+ // Allows calls from JNI in idle state to notify errors
+ if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
+ ALOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
+ if (locked) mLock.unlock(); // release the lock when done.
+ return;
+ }
+
+ switch (msg) {
+ case MEDIA_NOP: // interface test message
+ break;
+ case MEDIA_PREPARED:
+ ALOGV("prepared");
+ mCurrentState = MEDIA_PLAYER_PREPARED;
+ if (mPrepareSync) {
+ ALOGV("signal application thread");
+ mPrepareSync = false;
+ mPrepareStatus = NO_ERROR;
+ mSignal.signal();
+ }
+ break;
+ case MEDIA_PLAYBACK_COMPLETE:
+ ALOGV("playback complete");
+ if (mCurrentState == MEDIA_PLAYER_IDLE) {
+ ALOGE("playback complete in idle state");
+ }
+ if (!mLoop) {
+ mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
+ }
+ break;
+ case MEDIA_ERROR:
+ // Always log errors.
+ // ext1: Media framework error code.
+ // ext2: Implementation dependant error code.
+ ALOGE("error (%d, %d)", ext1, ext2);
+ mCurrentState = MEDIA_PLAYER_STATE_ERROR;
+ if (mPrepareSync)
+ {
+ ALOGV("signal application thread");
+ mPrepareSync = false;
+ mPrepareStatus = ext1;
+ mSignal.signal();
+ send = false;
+ }
+ break;
+ case MEDIA_INFO:
+ // ext1: Media framework error code.
+ // ext2: Implementation dependant error code.
+ if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
+ ALOGW("info/warning (%d, %d)", ext1, ext2);
+ }
+ break;
+ case MEDIA_SEEK_COMPLETE:
+ ALOGV("Received seek complete");
+ if (mSeekPosition != mCurrentPosition) {
+ ALOGV("Executing queued seekTo(%d)", mSeekPosition);
+ mSeekPosition = -1;
+ seekTo_l(mCurrentPosition);
+ }
+ else {
+ ALOGV("All seeks complete - return to regularly scheduled program");
+ mCurrentPosition = mSeekPosition = -1;
+ }
+ break;
+ case MEDIA_BUFFERING_UPDATE:
+ ALOGV("buffering %d", ext1);
+ break;
+ case MEDIA_SET_VIDEO_SIZE:
+ ALOGV("New video size %d x %d", ext1, ext2);
+ mVideoWidth = ext1;
+ mVideoHeight = ext2;
+ break;
+ case MEDIA_TIMED_TEXT:
+ ALOGV("Received timed text message");
+ break;
+ default:
+ ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
+ break;
+ }
+
+ sp<MediaPlayerListener> listener = mListener;
+ if (locked) mLock.unlock();
+
+ // this prevents re-entrant calls into client code
+ if ((listener != 0) && send) {
+ Mutex::Autolock _l(mNotifyLock);
+ ALOGV("callback application");
+ listener->notify(msg, ext1, ext2, obj);
+ ALOGV("back from callback");
+ }
+}
+
+/*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
+{
+ ALOGV("decode(%s)", url);
+ sp<IMemory> p;
+ const sp<IMediaPlayerService>& service = getMediaPlayerService();
+ if (service != 0) {
+ p = service->decode(url, pSampleRate, pNumChannels, pFormat);
+ } else {
+ ALOGE("Unable to locate media service");
+ }
+ return p;
+
+}
+
+void MediaPlayer::died()
+{
+ ALOGV("died");
+ notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
+}
+
+/*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
+{
+ ALOGV("decode(%d, %lld, %lld)", fd, offset, length);
+ sp<IMemory> p;
+ const sp<IMediaPlayerService>& service = getMediaPlayerService();
+ if (service != 0) {
+ p = service->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat);
+ } else {
+ ALOGE("Unable to locate media service");
+ }
+ return p;
+
+}
+
+status_t MediaPlayer::setNextMediaPlayer(const sp<MediaPlayer>& next) {
+ if (mPlayer == NULL) {
+ return NO_INIT;
+ }
+ return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
+}
+
+}; // namespace android
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
new file mode 100644
index 0000000..9541015
--- /dev/null
+++ b/media/libmedia/mediarecorder.cpp
@@ -0,0 +1,682 @@
+/*
+ **
+ ** 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_NDEBUG 0
+#define LOG_TAG "MediaRecorder"
+#include <utils/Log.h>
+#include <media/mediarecorder.h>
+#include <binder/IServiceManager.h>
+#include <utils/String8.h>
+#include <media/IMediaPlayerService.h>
+#include <media/IMediaRecorder.h>
+#include <media/mediaplayer.h> // for MEDIA_ERROR_SERVER_DIED
+#include <gui/ISurfaceTexture.h>
+
+namespace android {
+
+status_t MediaRecorder::setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy)
+{
+ ALOGV("setCamera(%p,%p)", camera.get(), proxy.get());
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_IDLE)) {
+ ALOGE("setCamera called in an invalid state(%d)", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->setCamera(camera, proxy);
+ if (OK != ret) {
+ ALOGV("setCamera failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+ return ret;
+}
+
+status_t MediaRecorder::setPreviewSurface(const sp<Surface>& surface)
+{
+ ALOGV("setPreviewSurface(%p)", surface.get());
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+ ALOGE("setPreviewSurface called in an invalid state(%d)", mCurrentState);
+ return INVALID_OPERATION;
+ }
+ if (!mIsVideoSourceSet) {
+ ALOGE("try to set preview surface without setting the video source first");
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->setPreviewSurface(surface);
+ if (OK != ret) {
+ ALOGV("setPreviewSurface failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+ return ret;
+}
+
+status_t MediaRecorder::init()
+{
+ ALOGV("init");
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_IDLE)) {
+ ALOGE("init called in an invalid state(%d)", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->init();
+ if (OK != ret) {
+ ALOGV("init failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+
+ ret = mMediaRecorder->setListener(this);
+ if (OK != ret) {
+ ALOGV("setListener failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+
+ mCurrentState = MEDIA_RECORDER_INITIALIZED;
+ return ret;
+}
+
+status_t MediaRecorder::setVideoSource(int vs)
+{
+ ALOGV("setVideoSource(%d)", vs);
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (mIsVideoSourceSet) {
+ ALOGE("video source has already been set");
+ return INVALID_OPERATION;
+ }
+ if (mCurrentState & MEDIA_RECORDER_IDLE) {
+ ALOGV("Call init() since the media recorder is not initialized yet");
+ status_t ret = init();
+ if (OK != ret) {
+ return ret;
+ }
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) {
+ ALOGE("setVideoSource called in an invalid state(%d)", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ // following call is made over the Binder Interface
+ status_t ret = mMediaRecorder->setVideoSource(vs);
+
+ if (OK != ret) {
+ ALOGV("setVideoSource failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+ mIsVideoSourceSet = true;
+ return ret;
+}
+
+status_t MediaRecorder::setAudioSource(int as)
+{
+ ALOGV("setAudioSource(%d)", as);
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (mCurrentState & MEDIA_RECORDER_IDLE) {
+ ALOGV("Call init() since the media recorder is not initialized yet");
+ status_t ret = init();
+ if (OK != ret) {
+ return ret;
+ }
+ }
+ if (mIsAudioSourceSet) {
+ ALOGE("audio source has already been set");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) {
+ ALOGE("setAudioSource called in an invalid state(%d)", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->setAudioSource(as);
+ if (OK != ret) {
+ ALOGV("setAudioSource failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+ mIsAudioSourceSet = true;
+ return ret;
+}
+
+status_t MediaRecorder::setOutputFormat(int of)
+{
+ ALOGV("setOutputFormat(%d)", of);
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) {
+ ALOGE("setOutputFormat called in an invalid state: %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+ if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_AUDIO_ONLY_START && of != OUTPUT_FORMAT_RTP_AVP && of != OUTPUT_FORMAT_MPEG2TS) { //first non-video output format
+ ALOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of);
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->setOutputFormat(of);
+ if (OK != ret) {
+ ALOGE("setOutputFormat failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+ mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED;
+ return ret;
+}
+
+status_t MediaRecorder::setVideoEncoder(int ve)
+{
+ ALOGV("setVideoEncoder(%d)", ve);
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (!mIsVideoSourceSet) {
+ ALOGE("try to set the video encoder without setting the video source first");
+ return INVALID_OPERATION;
+ }
+ if (mIsVideoEncoderSet) {
+ ALOGE("video encoder has already been set");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+ ALOGE("setVideoEncoder called in an invalid state(%d)", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->setVideoEncoder(ve);
+ if (OK != ret) {
+ ALOGV("setVideoEncoder failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+ mIsVideoEncoderSet = true;
+ return ret;
+}
+
+status_t MediaRecorder::setAudioEncoder(int ae)
+{
+ ALOGV("setAudioEncoder(%d)", ae);
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (!mIsAudioSourceSet) {
+ ALOGE("try to set the audio encoder without setting the audio source first");
+ return INVALID_OPERATION;
+ }
+ if (mIsAudioEncoderSet) {
+ ALOGE("audio encoder has already been set");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+ ALOGE("setAudioEncoder called in an invalid state(%d)", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->setAudioEncoder(ae);
+ if (OK != ret) {
+ ALOGV("setAudioEncoder failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+ mIsAudioEncoderSet = true;
+ return ret;
+}
+
+status_t MediaRecorder::setOutputFile(const char* path)
+{
+ ALOGV("setOutputFile(%s)", path);
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (mIsOutputFileSet) {
+ ALOGE("output file has already been set");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+ ALOGE("setOutputFile called in an invalid state(%d)", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->setOutputFile(path);
+ if (OK != ret) {
+ ALOGV("setOutputFile failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+ mIsOutputFileSet = true;
+ return ret;
+}
+
+status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length)
+{
+ ALOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (mIsOutputFileSet) {
+ ALOGE("output file has already been set");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+ ALOGE("setOutputFile called in an invalid state(%d)", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ // It appears that if an invalid file descriptor is passed through
+ // binder calls, the server-side of the inter-process function call
+ // is skipped. As a result, the check at the server-side to catch
+ // the invalid file descritpor never gets invoked. This is to workaround
+ // this issue by checking the file descriptor first before passing
+ // it through binder call.
+ if (fd < 0) {
+ ALOGE("Invalid file descriptor: %d", fd);
+ return BAD_VALUE;
+ }
+
+ status_t ret = mMediaRecorder->setOutputFile(fd, offset, length);
+ if (OK != ret) {
+ ALOGV("setOutputFile failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+ mIsOutputFileSet = true;
+ return ret;
+}
+
+status_t MediaRecorder::setVideoSize(int width, int height)
+{
+ ALOGV("setVideoSize(%d, %d)", width, height);
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+ ALOGE("setVideoSize called in an invalid state: %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+ if (!mIsVideoSourceSet) {
+ ALOGE("Cannot set video size without setting video source first");
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->setVideoSize(width, height);
+ if (OK != ret) {
+ ALOGE("setVideoSize failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+
+ return ret;
+}
+
+// Query a SurfaceMediaSurface through the Mediaserver, over the
+// binder interface. This is used by the Filter Framework (MeidaEncoder)
+// to get an <ISurfaceTexture> object to hook up to ANativeWindow.
+sp<ISurfaceTexture> MediaRecorder::
+ querySurfaceMediaSourceFromMediaServer()
+{
+ Mutex::Autolock _l(mLock);
+ mSurfaceMediaSource =
+ mMediaRecorder->querySurfaceMediaSource();
+ if (mSurfaceMediaSource == NULL) {
+ ALOGE("SurfaceMediaSource could not be initialized!");
+ }
+ return mSurfaceMediaSource;
+}
+
+
+
+status_t MediaRecorder::setVideoFrameRate(int frames_per_second)
+{
+ ALOGV("setVideoFrameRate(%d)", frames_per_second);
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+ ALOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+ if (!mIsVideoSourceSet) {
+ ALOGE("Cannot set video frame rate without setting video source first");
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->setVideoFrameRate(frames_per_second);
+ if (OK != ret) {
+ ALOGE("setVideoFrameRate failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+ return ret;
+}
+
+status_t MediaRecorder::setParameters(const String8& params) {
+ ALOGV("setParameters(%s)", params.string());
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+
+ bool isInvalidState = (mCurrentState &
+ (MEDIA_RECORDER_PREPARED |
+ MEDIA_RECORDER_RECORDING |
+ MEDIA_RECORDER_ERROR));
+ if (isInvalidState) {
+ ALOGE("setParameters is called in an invalid state: %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->setParameters(params);
+ if (OK != ret) {
+ ALOGE("setParameters(%s) failed: %d", params.string(), ret);
+ // Do not change our current state to MEDIA_RECORDER_ERROR, failures
+ // of the only currently supported parameters, "max-duration" and
+ // "max-filesize" are _not_ fatal.
+ }
+
+ return ret;
+}
+
+status_t MediaRecorder::prepare()
+{
+ ALOGV("prepare");
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+ ALOGE("prepare called in an invalid state: %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+ if (mIsAudioSourceSet != mIsAudioEncoderSet) {
+ if (mIsAudioSourceSet) {
+ ALOGE("audio source is set, but audio encoder is not set");
+ } else { // must not happen, since setAudioEncoder checks this already
+ ALOGE("audio encoder is set, but audio source is not set");
+ }
+ return INVALID_OPERATION;
+ }
+
+ if (mIsVideoSourceSet != mIsVideoEncoderSet) {
+ if (mIsVideoSourceSet) {
+ ALOGE("video source is set, but video encoder is not set");
+ } else { // must not happen, since setVideoEncoder checks this already
+ ALOGE("video encoder is set, but video source is not set");
+ }
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->prepare();
+ if (OK != ret) {
+ ALOGE("prepare failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+ mCurrentState = MEDIA_RECORDER_PREPARED;
+ return ret;
+}
+
+status_t MediaRecorder::getMaxAmplitude(int* max)
+{
+ ALOGV("getMaxAmplitude");
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (mCurrentState & MEDIA_RECORDER_ERROR) {
+ ALOGE("getMaxAmplitude called in an invalid state: %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->getMaxAmplitude(max);
+ if (OK != ret) {
+ ALOGE("getMaxAmplitude failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+ return ret;
+}
+
+status_t MediaRecorder::start()
+{
+ ALOGV("start");
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_PREPARED)) {
+ ALOGE("start called in an invalid state: %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->start();
+ if (OK != ret) {
+ ALOGE("start failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+ mCurrentState = MEDIA_RECORDER_RECORDING;
+ return ret;
+}
+
+status_t MediaRecorder::stop()
+{
+ ALOGV("stop");
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+ if (!(mCurrentState & MEDIA_RECORDER_RECORDING)) {
+ ALOGE("stop called in an invalid state: %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ status_t ret = mMediaRecorder->stop();
+ if (OK != ret) {
+ ALOGE("stop failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ }
+
+ // FIXME:
+ // stop and reset are semantically different.
+ // We treat them the same for now, and will change this in the future.
+ doCleanUp();
+ mCurrentState = MEDIA_RECORDER_IDLE;
+ return ret;
+}
+
+// Reset should be OK in any state
+status_t MediaRecorder::reset()
+{
+ ALOGV("reset");
+ if (mMediaRecorder == NULL) {
+ ALOGE("media recorder is not initialized yet");
+ return INVALID_OPERATION;
+ }
+
+ doCleanUp();
+ status_t ret = UNKNOWN_ERROR;
+ switch (mCurrentState) {
+ case MEDIA_RECORDER_IDLE:
+ ret = OK;
+ break;
+
+ case MEDIA_RECORDER_RECORDING:
+ case MEDIA_RECORDER_DATASOURCE_CONFIGURED:
+ case MEDIA_RECORDER_PREPARED:
+ case MEDIA_RECORDER_ERROR: {
+ ret = doReset();
+ if (OK != ret) {
+ return ret; // No need to continue
+ }
+ } // Intentional fall through
+ case MEDIA_RECORDER_INITIALIZED:
+ ret = close();
+ break;
+
+ default: {
+ ALOGE("Unexpected non-existing state: %d", mCurrentState);
+ break;
+ }
+ }
+ return ret;
+}
+
+status_t MediaRecorder::close()
+{
+ ALOGV("close");
+ if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) {
+ ALOGE("close called in an invalid state: %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+ status_t ret = mMediaRecorder->close();
+ if (OK != ret) {
+ ALOGE("close failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return UNKNOWN_ERROR;
+ } else {
+ mCurrentState = MEDIA_RECORDER_IDLE;
+ }
+ return ret;
+}
+
+status_t MediaRecorder::doReset()
+{
+ ALOGV("doReset");
+ status_t ret = mMediaRecorder->reset();
+ if (OK != ret) {
+ ALOGE("doReset failed: %d", ret);
+ mCurrentState = MEDIA_RECORDER_ERROR;
+ return ret;
+ } else {
+ mCurrentState = MEDIA_RECORDER_INITIALIZED;
+ }
+ return ret;
+}
+
+void MediaRecorder::doCleanUp()
+{
+ ALOGV("doCleanUp");
+ mIsAudioSourceSet = false;
+ mIsVideoSourceSet = false;
+ mIsAudioEncoderSet = false;
+ mIsVideoEncoderSet = false;
+ mIsOutputFileSet = false;
+}
+
+// Release should be OK in any state
+status_t MediaRecorder::release()
+{
+ ALOGV("release");
+ if (mMediaRecorder != NULL) {
+ return mMediaRecorder->release();
+ }
+ return INVALID_OPERATION;
+}
+
+MediaRecorder::MediaRecorder() : mSurfaceMediaSource(NULL)
+{
+ ALOGV("constructor");
+
+ const sp<IMediaPlayerService>& service(getMediaPlayerService());
+ if (service != NULL) {
+ mMediaRecorder = service->createMediaRecorder(getpid());
+ }
+ if (mMediaRecorder != NULL) {
+ mCurrentState = MEDIA_RECORDER_IDLE;
+ }
+
+
+ doCleanUp();
+}
+
+status_t MediaRecorder::initCheck()
+{
+ return mMediaRecorder != 0 ? NO_ERROR : NO_INIT;
+}
+
+MediaRecorder::~MediaRecorder()
+{
+ ALOGV("destructor");
+ if (mMediaRecorder != NULL) {
+ mMediaRecorder.clear();
+ }
+
+ if (mSurfaceMediaSource != NULL) {
+ mSurfaceMediaSource.clear();
+ }
+}
+
+status_t MediaRecorder::setListener(const sp<MediaRecorderListener>& listener)
+{
+ ALOGV("setListener");
+ Mutex::Autolock _l(mLock);
+ mListener = listener;
+
+ return NO_ERROR;
+}
+
+void MediaRecorder::notify(int msg, int ext1, int ext2)
+{
+ ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
+
+ sp<MediaRecorderListener> listener;
+ mLock.lock();
+ listener = mListener;
+ mLock.unlock();
+
+ if (listener != NULL) {
+ Mutex::Autolock _l(mNotifyLock);
+ ALOGV("callback application");
+ listener->notify(msg, ext1, ext2);
+ ALOGV("back from callback");
+ }
+}
+
+void MediaRecorder::died()
+{
+ ALOGV("died");
+ notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
+}
+
+}; // namespace android
diff --git a/media/libmedia_native/Android.mk b/media/libmedia_native/Android.mk
new file mode 100644
index 0000000..065a90f
--- /dev/null
+++ b/media/libmedia_native/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES :=
+
+LOCAL_MODULE:= libmedia_native
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
new file mode 100644
index 0000000..675c563
--- /dev/null
+++ b/media/libmediaplayerservice/Android.mk
@@ -0,0 +1,53 @@
+LOCAL_PATH:= $(call my-dir)
+
+#
+# libmediaplayerservice
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ Crypto.cpp \
+ MediaRecorderClient.cpp \
+ MediaPlayerService.cpp \
+ MetadataRetrieverClient.cpp \
+ TestPlayerStub.cpp \
+ MidiMetadataRetriever.cpp \
+ MidiFile.cpp \
+ StagefrightPlayer.cpp \
+ StagefrightRecorder.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libutils \
+ libbinder \
+ libvorbisidec \
+ libsonivox \
+ libmedia \
+ libmedia_native \
+ libcamera_client \
+ libandroid_runtime \
+ libstagefright \
+ libstagefright_omx \
+ libstagefright_foundation \
+ libgui \
+ libdl \
+ libaah_rtp
+
+LOCAL_STATIC_LIBRARIES := \
+ libstagefright_nuplayer \
+ libstagefright_rtsp \
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, graphics corecg) \
+ $(TOP)/frameworks/base/media/libstagefright/include \
+ $(TOP)/frameworks/base/media/libstagefright/rtsp \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/external/tremolo/Tremolo \
+
+LOCAL_MODULE:= libmediaplayerservice
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/media/libmediaplayerservice/Crypto.cpp b/media/libmediaplayerservice/Crypto.cpp
new file mode 100644
index 0000000..e02035f
--- /dev/null
+++ b/media/libmediaplayerservice/Crypto.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "Crypto"
+#include <utils/Log.h>
+
+#include "Crypto.h"
+
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+Crypto::Crypto() {
+}
+
+Crypto::~Crypto() {
+}
+
+status_t Crypto::initialize() {
+ return ERROR_UNSUPPORTED;
+}
+
+status_t Crypto::terminate() {
+ return ERROR_UNSUPPORTED;
+}
+
+status_t Crypto::setEntitlementKey(
+ const void *key, size_t keyLength) {
+ return ERROR_UNSUPPORTED;
+}
+
+status_t Crypto::setEntitlementControlMessage(
+ const void *msg, size_t msgLength) {
+ return ERROR_UNSUPPORTED;
+}
+
+ssize_t Crypto::decryptVideo(
+ const void *iv, size_t ivLength,
+ const void *srcData, size_t srcDataSize,
+ void *dstData, size_t dstDataOffset) {
+ return ERROR_UNSUPPORTED;
+}
+
+ssize_t Crypto::decryptAudio(
+ const void *iv, size_t ivLength,
+ const void *srcData, size_t srcDataSize,
+ void *dstData, size_t dstDataSize) {
+ return ERROR_UNSUPPORTED;
+}
+
+} // namespace android
diff --git a/media/libmediaplayerservice/Crypto.h b/media/libmediaplayerservice/Crypto.h
new file mode 100644
index 0000000..9855496
--- /dev/null
+++ b/media/libmediaplayerservice/Crypto.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 CRYPTO_H_
+
+#define CRYPTO_H_
+
+#include <media/ICrypto.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct Crypto : public BnCrypto {
+ Crypto();
+
+ virtual status_t initialize();
+ virtual status_t terminate();
+
+ virtual status_t setEntitlementKey(
+ const void *key, size_t keyLength);
+
+ virtual status_t setEntitlementControlMessage(
+ const void *msg, size_t msgLength);
+
+ virtual ssize_t decryptVideo(
+ const void *iv, size_t ivLength,
+ const void *srcData, size_t srcDataSize,
+ void *dstData, size_t dstDataOffset);
+
+ virtual ssize_t decryptAudio(
+ const void *iv, size_t ivLength,
+ const void *srcData, size_t srcDataSize,
+ void *dstData, size_t dstDataSize);
+
+protected:
+ virtual ~Crypto();
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(Crypto);
+};
+
+} // namespace android
+
+#endif // CRYPTO_H_
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
new file mode 100644
index 0000000..123d07f
--- /dev/null
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -0,0 +1,2168 @@
+/*
+**
+** 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.
+*/
+
+// Proxy for media player implementations
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaPlayerService"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include <string.h>
+
+#include <cutils/atomic.h>
+#include <cutils/properties.h> // for property_get
+
+#include <utils/misc.h>
+
+#include <android_runtime/ActivityManager.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/MemoryBase.h>
+#include <gui/SurfaceTextureClient.h>
+#include <utils/Errors.h> // for status_t
+#include <utils/String8.h>
+#include <utils/SystemClock.h>
+#include <utils/Vector.h>
+#include <cutils/properties.h>
+
+#include <media/MediaPlayerInterface.h>
+#include <media/mediarecorder.h>
+#include <media/MediaMetadataRetrieverInterface.h>
+#include <media/Metadata.h>
+#include <media/AudioTrack.h>
+#include <media/MemoryLeakTrackUtil.h>
+#include <media/stagefright/MediaErrors.h>
+
+#include <system/audio.h>
+
+#include <private/android_filesystem_config.h>
+
+#include "MediaRecorderClient.h"
+#include "MediaPlayerService.h"
+#include "MetadataRetrieverClient.h"
+
+#include "MidiFile.h"
+#include "TestPlayerStub.h"
+#include "StagefrightPlayer.h"
+#include "nuplayer/NuPlayerDriver.h"
+
+#include <OMX.h>
+
+#include "Crypto.h"
+
+namespace android {
+sp<MediaPlayerBase> createAAH_TXPlayer();
+sp<MediaPlayerBase> createAAH_RXPlayer();
+}
+
+namespace {
+using android::media::Metadata;
+using android::status_t;
+using android::OK;
+using android::BAD_VALUE;
+using android::NOT_ENOUGH_DATA;
+using android::Parcel;
+
+// Max number of entries in the filter.
+const int kMaxFilterSize = 64; // I pulled that out of thin air.
+
+// FIXME: Move all the metadata related function in the Metadata.cpp
+
+
+// Unmarshall a filter from a Parcel.
+// Filter format in a parcel:
+//
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | number of entries (n) |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | metadata type 1 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | metadata type 2 |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// ....
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | metadata type n |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//
+// @param p Parcel that should start with a filter.
+// @param[out] filter On exit contains the list of metadata type to be
+// filtered.
+// @param[out] status On exit contains the status code to be returned.
+// @return true if the parcel starts with a valid filter.
+bool unmarshallFilter(const Parcel& p,
+ Metadata::Filter *filter,
+ status_t *status)
+{
+ int32_t val;
+ if (p.readInt32(&val) != OK)
+ {
+ ALOGE("Failed to read filter's length");
+ *status = NOT_ENOUGH_DATA;
+ return false;
+ }
+
+ if( val > kMaxFilterSize || val < 0)
+ {
+ ALOGE("Invalid filter len %d", val);
+ *status = BAD_VALUE;
+ return false;
+ }
+
+ const size_t num = val;
+
+ filter->clear();
+ filter->setCapacity(num);
+
+ size_t size = num * sizeof(Metadata::Type);
+
+
+ if (p.dataAvail() < size)
+ {
+ ALOGE("Filter too short expected %d but got %d", size, p.dataAvail());
+ *status = NOT_ENOUGH_DATA;
+ return false;
+ }
+
+ const Metadata::Type *data =
+ static_cast<const Metadata::Type*>(p.readInplace(size));
+
+ if (NULL == data)
+ {
+ ALOGE("Filter had no data");
+ *status = BAD_VALUE;
+ return false;
+ }
+
+ // TODO: The stl impl of vector would be more efficient here
+ // because it degenerates into a memcpy on pod types. Try to
+ // replace later or use stl::set.
+ for (size_t i = 0; i < num; ++i)
+ {
+ filter->add(*data);
+ ++data;
+ }
+ *status = OK;
+ return true;
+}
+
+// @param filter Of metadata type.
+// @param val To be searched.
+// @return true if a match was found.
+bool findMetadata(const Metadata::Filter& filter, const int32_t val)
+{
+ // Deal with empty and ANY right away
+ if (filter.isEmpty()) return false;
+ if (filter[0] == Metadata::kAny) return true;
+
+ return filter.indexOf(val) >= 0;
+}
+
+} // anonymous namespace
+
+
+namespace android {
+
+static bool checkPermission(const char* permissionString) {
+#ifndef HAVE_ANDROID_OS
+ return true;
+#endif
+ if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
+ bool ok = checkCallingPermission(String16(permissionString));
+ if (!ok) ALOGE("Request requires %s", permissionString);
+ return ok;
+}
+
+// TODO: Temp hack until we can register players
+typedef struct {
+ const char *extension;
+ const player_type playertype;
+} extmap;
+extmap FILE_EXTS [] = {
+ {".mid", SONIVOX_PLAYER},
+ {".midi", SONIVOX_PLAYER},
+ {".smf", SONIVOX_PLAYER},
+ {".xmf", SONIVOX_PLAYER},
+ {".imy", SONIVOX_PLAYER},
+ {".rtttl", SONIVOX_PLAYER},
+ {".rtx", SONIVOX_PLAYER},
+ {".ota", SONIVOX_PLAYER},
+};
+
+// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
+/* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
+/* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
+
+void MediaPlayerService::instantiate() {
+ defaultServiceManager()->addService(
+ String16("media.player"), new MediaPlayerService());
+}
+
+MediaPlayerService::MediaPlayerService()
+{
+ ALOGV("MediaPlayerService created");
+ mNextConnId = 1;
+
+ mBatteryAudio.refCount = 0;
+ for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+ mBatteryAudio.deviceOn[i] = 0;
+ mBatteryAudio.lastTime[i] = 0;
+ mBatteryAudio.totalTime[i] = 0;
+ }
+ // speaker is on by default
+ mBatteryAudio.deviceOn[SPEAKER] = 1;
+}
+
+MediaPlayerService::~MediaPlayerService()
+{
+ ALOGV("MediaPlayerService destroyed");
+}
+
+sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(pid_t pid)
+{
+ sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid);
+ wp<MediaRecorderClient> w = recorder;
+ Mutex::Autolock lock(mLock);
+ mMediaRecorderClients.add(w);
+ ALOGV("Create new media recorder client from pid %d", pid);
+ return recorder;
+}
+
+void MediaPlayerService::removeMediaRecorderClient(wp<MediaRecorderClient> client)
+{
+ Mutex::Autolock lock(mLock);
+ mMediaRecorderClients.remove(client);
+ ALOGV("Delete media recorder client");
+}
+
+sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pid)
+{
+ sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
+ ALOGV("Create new media retriever from pid %d", pid);
+ return retriever;
+}
+
+sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
+ int audioSessionId)
+{
+ int32_t connId = android_atomic_inc(&mNextConnId);
+
+ sp<Client> c = new Client(
+ this, pid, connId, client, audioSessionId,
+ IPCThreadState::self()->getCallingUid());
+
+ ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
+ IPCThreadState::self()->getCallingUid());
+
+ wp<Client> w = c;
+ {
+ Mutex::Autolock lock(mLock);
+ mClients.add(w);
+ }
+ return c;
+}
+
+sp<IOMX> MediaPlayerService::getOMX() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mOMX.get() == NULL) {
+ mOMX = new OMX;
+ }
+
+ return mOMX;
+}
+
+sp<ICrypto> MediaPlayerService::makeCrypto() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mCrypto == NULL) {
+ mCrypto = new Crypto;
+ }
+
+ return mCrypto;
+}
+
+status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& args) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ result.append(" AudioCache\n");
+ if (mHeap != 0) {
+ snprintf(buffer, 255, " heap base(%p), size(%d), flags(%d), device(%s)\n",
+ mHeap->getBase(), mHeap->getSize(), mHeap->getFlags(), mHeap->getDevice());
+ result.append(buffer);
+ }
+ snprintf(buffer, 255, " msec per frame(%f), channel count(%d), format(%d), frame count(%ld)\n",
+ mMsecsPerFrame, mChannelCount, mFormat, mFrameCount);
+ result.append(buffer);
+ snprintf(buffer, 255, " sample rate(%d), size(%d), error(%d), command complete(%s)\n",
+ mSampleRate, mSize, mError, mCommandComplete?"true":"false");
+ result.append(buffer);
+ ::write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& args) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ result.append(" AudioOutput\n");
+ snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n",
+ mStreamType, mLeftVolume, mRightVolume);
+ result.append(buffer);
+ snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
+ mMsecsPerFrame, (mTrack != 0) ? mTrack->latency() : -1);
+ 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);
+ }
+ return NO_ERROR;
+}
+
+status_t MediaPlayerService::Client::dump(int fd, const Vector<String16>& args) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ result.append(" Client\n");
+ snprintf(buffer, 255, " pid(%d), connId(%d), status(%d), looping(%s)\n",
+ mPid, mConnId, mStatus, mLoop?"true": "false");
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+ if (mPlayer != NULL) {
+ mPlayer->dump(fd, args);
+ }
+ if (mAudioOutput != 0) {
+ mAudioOutput->dump(fd, args);
+ }
+ write(fd, "\n", 1);
+ return NO_ERROR;
+}
+
+status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+ snprintf(buffer, SIZE, "Permission Denial: "
+ "can't dump MediaPlayerService from pid=%d, uid=%d\n",
+ IPCThreadState::self()->getCallingPid(),
+ IPCThreadState::self()->getCallingUid());
+ result.append(buffer);
+ } else {
+ Mutex::Autolock lock(mLock);
+ for (int i = 0, n = mClients.size(); i < n; ++i) {
+ sp<Client> c = mClients[i].promote();
+ if (c != 0) c->dump(fd, args);
+ }
+ 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();
+ if (c != 0) {
+ 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");
+ snprintf(buffer, SIZE, "/proc/%d/maps", gettid());
+ FILE *f = fopen(buffer, "r");
+ if (f) {
+ while (!feof(f)) {
+ fgets(buffer, SIZE, f);
+ if (strstr(buffer, " /mnt/sdcard/") ||
+ strstr(buffer, " /system/sounds/") ||
+ strstr(buffer, " /data/") ||
+ strstr(buffer, " /system/media/")) {
+ result.append(" ");
+ result.append(buffer);
+ }
+ }
+ fclose(f);
+ } else {
+ result.append("couldn't open ");
+ result.append(buffer);
+ result.append("\n");
+ }
+
+ snprintf(buffer, SIZE, "/proc/%d/fd", gettid());
+ DIR *d = opendir(buffer);
+ if (d) {
+ struct dirent *ent;
+ while((ent = readdir(d)) != NULL) {
+ if (strcmp(ent->d_name,".") && strcmp(ent->d_name,"..")) {
+ snprintf(buffer, SIZE, "/proc/%d/fd/%s", gettid(), ent->d_name);
+ struct stat s;
+ if (lstat(buffer, &s) == 0) {
+ if ((s.st_mode & S_IFMT) == S_IFLNK) {
+ char linkto[256];
+ int len = readlink(buffer, linkto, sizeof(linkto));
+ if(len > 0) {
+ if(len > 255) {
+ linkto[252] = '.';
+ linkto[253] = '.';
+ linkto[254] = '.';
+ linkto[255] = 0;
+ } else {
+ linkto[len] = 0;
+ }
+ if (strstr(linkto, "/mnt/sdcard/") == linkto ||
+ strstr(linkto, "/system/sounds/") == linkto ||
+ strstr(linkto, "/data/") == linkto ||
+ strstr(linkto, "/system/media/") == linkto) {
+ result.append(" ");
+ result.append(buffer);
+ result.append(" -> ");
+ result.append(linkto);
+ result.append("\n");
+ }
+ }
+ } else {
+ result.append(" unexpected type for ");
+ result.append(buffer);
+ result.append("\n");
+ }
+ }
+ }
+ }
+ closedir(d);
+ } else {
+ result.append("couldn't open ");
+ result.append(buffer);
+ result.append("\n");
+ }
+
+ bool dumpMem = false;
+ for (size_t i = 0; i < args.size(); i++) {
+ if (args[i] == String16("-m")) {
+ dumpMem = true;
+ }
+ }
+ if (dumpMem) {
+ dumpMemoryAddresses(fd);
+ }
+ }
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+void MediaPlayerService::removeClient(wp<Client> client)
+{
+ Mutex::Autolock lock(mLock);
+ mClients.remove(client);
+}
+
+MediaPlayerService::Client::Client(
+ const sp<MediaPlayerService>& service, pid_t pid,
+ int32_t connId, const sp<IMediaPlayerClient>& client,
+ int audioSessionId, uid_t uid)
+{
+ ALOGV("Client(%d) constructor", connId);
+ mPid = pid;
+ mConnId = connId;
+ mService = service;
+ mClient = client;
+ mLoop = false;
+ mStatus = NO_INIT;
+ mAudioSessionId = audioSessionId;
+ mUID = uid;
+ mRetransmitEndpointValid = false;
+
+#if CALLBACK_ANTAGONIZER
+ ALOGD("create Antagonizer");
+ mAntagonizer = new Antagonizer(notify, this);
+#endif
+}
+
+MediaPlayerService::Client::~Client()
+{
+ ALOGV("Client(%d) destructor pid = %d", mConnId, mPid);
+ mAudioOutput.clear();
+ wp<Client> client(this);
+ disconnect();
+ mService->removeClient(client);
+}
+
+void MediaPlayerService::Client::disconnect()
+{
+ ALOGV("disconnect(%d) from pid %d", mConnId, mPid);
+ // grab local reference and clear main reference to prevent future
+ // access to object
+ sp<MediaPlayerBase> p;
+ {
+ Mutex::Autolock l(mLock);
+ p = mPlayer;
+ }
+ mClient.clear();
+
+ mPlayer.clear();
+
+ // clear the notification to prevent callbacks to dead client
+ // and reset the player. We assume the player will serialize
+ // access to itself if necessary.
+ if (p != 0) {
+ p->setNotifyCallback(0, 0);
+#if CALLBACK_ANTAGONIZER
+ ALOGD("kill Antagonizer");
+ mAntagonizer->kill();
+#endif
+ p->reset();
+ }
+
+ disconnectNativeWindow();
+
+ IPCThreadState::self()->flushCommands();
+}
+
+static player_type getDefaultPlayerType() {
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.stagefright.use-nuplayer", value, NULL)
+ && (!strcmp("1", value) || !strcasecmp("true", value))) {
+ return NU_PLAYER;
+ }
+
+ return STAGEFRIGHT_PLAYER;
+}
+
+player_type getPlayerType(int fd, int64_t offset, int64_t length)
+{
+ char buf[20];
+ lseek(fd, offset, SEEK_SET);
+ read(fd, buf, sizeof(buf));
+ lseek(fd, offset, SEEK_SET);
+
+ long ident = *((long*)buf);
+
+ // Ogg vorbis?
+ if (ident == 0x5367674f) // 'OggS'
+ return STAGEFRIGHT_PLAYER;
+
+ // Some kind of MIDI?
+ EAS_DATA_HANDLE easdata;
+ if (EAS_Init(&easdata) == EAS_SUCCESS) {
+ EAS_FILE locator;
+ locator.path = NULL;
+ locator.fd = fd;
+ locator.offset = offset;
+ locator.length = length;
+ EAS_HANDLE eashandle;
+ if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
+ EAS_CloseFile(easdata, eashandle);
+ EAS_Shutdown(easdata);
+ return SONIVOX_PLAYER;
+ }
+ EAS_Shutdown(easdata);
+ }
+
+ return getDefaultPlayerType();
+}
+
+player_type getPlayerType(const char* url)
+{
+ if (TestPlayerStub::canBeUsed(url)) {
+ return TEST_PLAYER;
+ }
+
+ if (!strncasecmp("http://", url, 7)
+ || !strncasecmp("https://", url, 8)) {
+ size_t len = strlen(url);
+ if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
+ return NU_PLAYER;
+ }
+
+ if (strstr(url,"m3u8")) {
+ return NU_PLAYER;
+ }
+ }
+
+ if (!strncasecmp("rtsp://", url, 7)) {
+ return NU_PLAYER;
+ }
+
+ if (!strncasecmp("aahRX://", url, 8)) {
+ return AAH_RX_PLAYER;
+ }
+
+ // use MidiFile for MIDI extensions
+ int lenURL = strlen(url);
+ for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
+ int len = strlen(FILE_EXTS[i].extension);
+ int start = lenURL - len;
+ if (start > 0) {
+ if (!strncasecmp(url + start, FILE_EXTS[i].extension, len)) {
+ return FILE_EXTS[i].playertype;
+ }
+ }
+ }
+
+ return getDefaultPlayerType();
+}
+
+player_type MediaPlayerService::Client::getPlayerType(int fd,
+ int64_t offset,
+ int64_t length)
+{
+ // Until re-transmit functionality is added to the existing core android
+ // players, we use the special AAH TX player whenever we were configured
+ // for retransmission.
+ if (mRetransmitEndpointValid) {
+ return AAH_TX_PLAYER;
+ }
+
+ return android::getPlayerType(fd, offset, length);
+}
+
+player_type MediaPlayerService::Client::getPlayerType(const char* url)
+{
+ // Until re-transmit functionality is added to the existing core android
+ // players, we use the special AAH TX player whenever we were configured
+ // for retransmission.
+ if (mRetransmitEndpointValid) {
+ return AAH_TX_PLAYER;
+ }
+
+ return android::getPlayerType(url);
+}
+
+player_type MediaPlayerService::Client::getPlayerType(
+ const sp<IStreamSource> &source) {
+ // Until re-transmit functionality is added to the existing core android
+ // players, we use the special AAH TX player whenever we were configured
+ // for retransmission.
+ if (mRetransmitEndpointValid) {
+ return AAH_TX_PLAYER;
+ }
+
+ return NU_PLAYER;
+}
+
+static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,
+ notify_callback_f notifyFunc)
+{
+ sp<MediaPlayerBase> p;
+ switch (playerType) {
+ case SONIVOX_PLAYER:
+ ALOGV(" create MidiFile");
+ p = new MidiFile();
+ break;
+ case STAGEFRIGHT_PLAYER:
+ ALOGV(" create StagefrightPlayer");
+ p = new StagefrightPlayer;
+ break;
+ case NU_PLAYER:
+ ALOGV(" create NuPlayer");
+ p = new NuPlayerDriver;
+ break;
+ case TEST_PLAYER:
+ ALOGV("Create Test Player stub");
+ p = new TestPlayerStub();
+ break;
+ case AAH_RX_PLAYER:
+ ALOGV(" create A@H RX Player");
+ p = createAAH_RXPlayer();
+ break;
+ case AAH_TX_PLAYER:
+ ALOGV(" create A@H TX Player");
+ p = createAAH_TXPlayer();
+ break;
+ default:
+ ALOGE("Unknown player type: %d", playerType);
+ return NULL;
+ }
+ if (p != NULL) {
+ if (p->initCheck() == NO_ERROR) {
+ p->setNotifyCallback(cookie, notifyFunc);
+ } else {
+ p.clear();
+ }
+ }
+ if (p == NULL) {
+ ALOGE("Failed to create player object");
+ }
+ return p;
+}
+
+sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
+{
+ // determine if we have the right player type
+ sp<MediaPlayerBase> p = mPlayer;
+ if ((p != NULL) && (p->playerType() != playerType)) {
+ ALOGV("delete player");
+ p.clear();
+ }
+ if (p == NULL) {
+ p = android::createPlayer(playerType, this, notify);
+ }
+
+ if (p != NULL) {
+ p->setUID(mUID);
+ }
+
+ return p;
+}
+
+sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
+ player_type playerType)
+{
+ ALOGV("player type = %d", playerType);
+
+ // create the right type of player
+ sp<MediaPlayerBase> p = createPlayer(playerType);
+ if (p == NULL) {
+ return p;
+ }
+
+ if (!p->hardwareOutput()) {
+ mAudioOutput = new AudioOutput(mAudioSessionId);
+ static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
+ }
+
+ return p;
+}
+
+void MediaPlayerService::Client::setDataSource_post(
+ const sp<MediaPlayerBase>& p,
+ status_t status)
+{
+ ALOGV(" setDataSource");
+ mStatus = status;
+ if (mStatus != OK) {
+ ALOGE(" error: %d", mStatus);
+ return;
+ }
+
+ // Set the re-transmission endpoint if one was chosen.
+ if (mRetransmitEndpointValid) {
+ mStatus = p->setRetransmitEndpoint(&mRetransmitEndpoint);
+ if (mStatus != NO_ERROR) {
+ ALOGE("setRetransmitEndpoint error: %d", mStatus);
+ }
+ }
+
+ if (mStatus == OK) {
+ mPlayer = p;
+ }
+}
+
+status_t MediaPlayerService::Client::setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers)
+{
+ ALOGV("setDataSource(%s)", url);
+ if (url == NULL)
+ return UNKNOWN_ERROR;
+
+ if ((strncmp(url, "http://", 7) == 0) ||
+ (strncmp(url, "https://", 8) == 0) ||
+ (strncmp(url, "rtsp://", 7) == 0)) {
+ if (!checkPermission("android.permission.INTERNET")) {
+ return PERMISSION_DENIED;
+ }
+ }
+
+ if (strncmp(url, "content://", 10) == 0) {
+ // get a filedescriptor for the content Uri and
+ // pass it to the setDataSource(fd) method
+
+ String16 url16(url);
+ int fd = android::openContentProviderFile(url16);
+ if (fd < 0)
+ {
+ ALOGE("Couldn't open fd for %s", url);
+ return UNKNOWN_ERROR;
+ }
+ setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
+ close(fd);
+ return mStatus;
+ } else {
+ player_type playerType = getPlayerType(url);
+ sp<MediaPlayerBase> p = setDataSource_pre(playerType);
+ if (p == NULL) {
+ return NO_INIT;
+ }
+
+ setDataSource_post(p, p->setDataSource(url, headers));
+ return mStatus;
+ }
+}
+
+status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
+{
+ ALOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
+ struct stat sb;
+ int ret = fstat(fd, &sb);
+ if (ret != 0) {
+ ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
+ return UNKNOWN_ERROR;
+ }
+
+ ALOGV("st_dev = %llu", sb.st_dev);
+ ALOGV("st_mode = %u", sb.st_mode);
+ ALOGV("st_uid = %lu", sb.st_uid);
+ ALOGV("st_gid = %lu", sb.st_gid);
+ ALOGV("st_size = %llu", sb.st_size);
+
+ if (offset >= sb.st_size) {
+ ALOGE("offset error");
+ ::close(fd);
+ return UNKNOWN_ERROR;
+ }
+ if (offset + length > sb.st_size) {
+ length = sb.st_size - offset;
+ ALOGV("calculated length = %lld", length);
+ }
+
+ // Until re-transmit functionality is added to the existing core android
+ // players, we use the special AAH TX player whenever we were configured for
+ // retransmission.
+ player_type playerType = getPlayerType(fd, offset, length);
+ sp<MediaPlayerBase> p = setDataSource_pre(playerType);
+ if (p == NULL) {
+ return NO_INIT;
+ }
+
+ // now set data source
+ setDataSource_post(p, p->setDataSource(fd, offset, length));
+ return mStatus;
+}
+
+status_t MediaPlayerService::Client::setDataSource(
+ const sp<IStreamSource> &source) {
+ // create the right type of player
+ // Until re-transmit functionality is added to the existing core android
+ // players, we use the special AAH TX player whenever we were configured for
+ // retransmission.
+ player_type playerType = getPlayerType(source);
+ sp<MediaPlayerBase> p = setDataSource_pre(playerType);
+ if (p == NULL) {
+ return NO_INIT;
+ }
+
+ // now set data source
+ setDataSource_post(p, p->setDataSource(source));
+ return mStatus;
+}
+
+void MediaPlayerService::Client::disconnectNativeWindow() {
+ if (mConnectedWindow != NULL) {
+ status_t err = native_window_api_disconnect(mConnectedWindow.get(),
+ NATIVE_WINDOW_API_MEDIA);
+
+ if (err != OK) {
+ ALOGW("native_window_api_disconnect returned an error: %s (%d)",
+ strerror(-err), err);
+ }
+ }
+ mConnectedWindow.clear();
+}
+
+status_t MediaPlayerService::Client::setVideoSurfaceTexture(
+ const sp<ISurfaceTexture>& surfaceTexture)
+{
+ ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, surfaceTexture.get());
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+
+ sp<IBinder> binder(surfaceTexture == NULL ? NULL :
+ surfaceTexture->asBinder());
+ if (mConnectedWindowBinder == binder) {
+ return OK;
+ }
+
+ sp<ANativeWindow> anw;
+ if (surfaceTexture != NULL) {
+ anw = new SurfaceTextureClient(surfaceTexture);
+ status_t err = native_window_api_connect(anw.get(),
+ NATIVE_WINDOW_API_MEDIA);
+
+ if (err != OK) {
+ ALOGE("setVideoSurfaceTexture failed: %d", err);
+ // Note that we must do the reset before disconnecting from the ANW.
+ // Otherwise queue/dequeue calls could be made on the disconnected
+ // ANW, which may result in errors.
+ reset();
+
+ disconnectNativeWindow();
+
+ return err;
+ }
+ }
+
+ // Note that we must set the player's new SurfaceTexture before
+ // disconnecting the old one. Otherwise queue/dequeue calls could be made
+ // on the disconnected ANW, which may result in errors.
+ status_t err = p->setVideoSurfaceTexture(surfaceTexture);
+
+ disconnectNativeWindow();
+
+ mConnectedWindow = anw;
+
+ if (err == OK) {
+ mConnectedWindowBinder = binder;
+ } else {
+ disconnectNativeWindow();
+ }
+
+ return err;
+}
+
+status_t MediaPlayerService::Client::invoke(const Parcel& request,
+ Parcel *reply)
+{
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == NULL) return UNKNOWN_ERROR;
+ return p->invoke(request, reply);
+}
+
+// This call doesn't need to access the native player.
+status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
+{
+ status_t status;
+ media::Metadata::Filter allow, drop;
+
+ if (unmarshallFilter(filter, &allow, &status) &&
+ unmarshallFilter(filter, &drop, &status)) {
+ Mutex::Autolock lock(mLock);
+
+ mMetadataAllow = allow;
+ mMetadataDrop = drop;
+ }
+ return status;
+}
+
+status_t MediaPlayerService::Client::getMetadata(
+ bool update_only, bool apply_filter, Parcel *reply)
+{
+ sp<MediaPlayerBase> player = getPlayer();
+ if (player == 0) return UNKNOWN_ERROR;
+
+ status_t status;
+ // Placeholder for the return code, updated by the caller.
+ reply->writeInt32(-1);
+
+ media::Metadata::Filter ids;
+
+ // We don't block notifications while we fetch the data. We clear
+ // mMetadataUpdated first so we don't lose notifications happening
+ // during the rest of this call.
+ {
+ Mutex::Autolock lock(mLock);
+ if (update_only) {
+ ids = mMetadataUpdated;
+ }
+ mMetadataUpdated.clear();
+ }
+
+ media::Metadata metadata(reply);
+
+ metadata.appendHeader();
+ status = player->getMetadata(ids, reply);
+
+ if (status != OK) {
+ metadata.resetParcel();
+ ALOGE("getMetadata failed %d", status);
+ return status;
+ }
+
+ // FIXME: Implement filtering on the result. Not critical since
+ // filtering takes place on the update notifications already. This
+ // would be when all the metadata are fetch and a filter is set.
+
+ // Everything is fine, update the metadata length.
+ metadata.updateLength();
+ return OK;
+}
+
+status_t MediaPlayerService::Client::prepareAsync()
+{
+ ALOGV("[%d] prepareAsync", mConnId);
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ status_t ret = p->prepareAsync();
+#if CALLBACK_ANTAGONIZER
+ ALOGD("start Antagonizer");
+ if (ret == NO_ERROR) mAntagonizer->start();
+#endif
+ return ret;
+}
+
+status_t MediaPlayerService::Client::start()
+{
+ ALOGV("[%d] start", mConnId);
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ p->setLooping(mLoop);
+ return p->start();
+}
+
+status_t MediaPlayerService::Client::stop()
+{
+ ALOGV("[%d] stop", mConnId);
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ return p->stop();
+}
+
+status_t MediaPlayerService::Client::pause()
+{
+ ALOGV("[%d] pause", mConnId);
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ return p->pause();
+}
+
+status_t MediaPlayerService::Client::isPlaying(bool* state)
+{
+ *state = false;
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ *state = p->isPlaying();
+ ALOGV("[%d] isPlaying: %d", mConnId, *state);
+ return NO_ERROR;
+}
+
+status_t MediaPlayerService::Client::getCurrentPosition(int *msec)
+{
+ ALOGV("getCurrentPosition");
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ status_t ret = p->getCurrentPosition(msec);
+ if (ret == NO_ERROR) {
+ ALOGV("[%d] getCurrentPosition = %d", mConnId, *msec);
+ } else {
+ ALOGE("getCurrentPosition returned %d", ret);
+ }
+ return ret;
+}
+
+status_t MediaPlayerService::Client::getDuration(int *msec)
+{
+ ALOGV("getDuration");
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ status_t ret = p->getDuration(msec);
+ if (ret == NO_ERROR) {
+ ALOGV("[%d] getDuration = %d", mConnId, *msec);
+ } else {
+ ALOGE("getDuration returned %d", ret);
+ }
+ return ret;
+}
+
+status_t MediaPlayerService::Client::setNextPlayer(const sp<IMediaPlayer>& player) {
+ ALOGV("setNextPlayer");
+ Mutex::Autolock l(mLock);
+ sp<Client> c = static_cast<Client*>(player.get());
+ mNextClient = c;
+ if (mAudioOutput != NULL && c != NULL) {
+ mAudioOutput->setNextOutput(c->mAudioOutput);
+ } else {
+ ALOGE("no current audio output");
+ }
+ return OK;
+}
+
+
+status_t MediaPlayerService::Client::seekTo(int msec)
+{
+ ALOGV("[%d] seekTo(%d)", mConnId, msec);
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ return p->seekTo(msec);
+}
+
+status_t MediaPlayerService::Client::reset()
+{
+ ALOGV("[%d] reset", mConnId);
+ mRetransmitEndpointValid = false;
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ return p->reset();
+}
+
+status_t MediaPlayerService::Client::setAudioStreamType(audio_stream_type_t type)
+{
+ ALOGV("[%d] setAudioStreamType(%d)", mConnId, type);
+ // TODO: for hardware output, call player instead
+ Mutex::Autolock l(mLock);
+ if (mAudioOutput != 0) mAudioOutput->setAudioStreamType(type);
+ return NO_ERROR;
+}
+
+status_t MediaPlayerService::Client::setLooping(int loop)
+{
+ ALOGV("[%d] setLooping(%d)", mConnId, loop);
+ mLoop = loop;
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p != 0) return p->setLooping(loop);
+ return NO_ERROR;
+}
+
+status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolume)
+{
+ ALOGV("[%d] setVolume(%f, %f)", mConnId, leftVolume, rightVolume);
+
+ // for hardware output, call player instead
+ sp<MediaPlayerBase> p = getPlayer();
+ {
+ Mutex::Autolock l(mLock);
+ if (p != 0 && p->hardwareOutput()) {
+ MediaPlayerHWInterface* hwp =
+ reinterpret_cast<MediaPlayerHWInterface*>(p.get());
+ return hwp->setVolume(leftVolume, rightVolume);
+ } else {
+ if (mAudioOutput != 0) mAudioOutput->setVolume(leftVolume, rightVolume);
+ return NO_ERROR;
+ }
+ }
+
+ return NO_ERROR;
+}
+
+status_t MediaPlayerService::Client::setAuxEffectSendLevel(float level)
+{
+ ALOGV("[%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)
+{
+ ALOGV("[%d] attachAuxEffect(%d)", mConnId, effectId);
+ Mutex::Autolock l(mLock);
+ if (mAudioOutput != 0) return mAudioOutput->attachAuxEffect(effectId);
+ return NO_ERROR;
+}
+
+status_t MediaPlayerService::Client::setParameter(int key, const Parcel &request) {
+ ALOGV("[%d] setParameter(%d)", mConnId, key);
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ return p->setParameter(key, request);
+}
+
+status_t MediaPlayerService::Client::getParameter(int key, Parcel *reply) {
+ ALOGV("[%d] getParameter(%d)", mConnId, key);
+ sp<MediaPlayerBase> p = getPlayer();
+ if (p == 0) return UNKNOWN_ERROR;
+ return p->getParameter(key, reply);
+}
+
+status_t MediaPlayerService::Client::setRetransmitEndpoint(
+ const struct sockaddr_in* endpoint) {
+
+ if (NULL != endpoint) {
+ uint32_t a = ntohl(endpoint->sin_addr.s_addr);
+ uint16_t p = ntohs(endpoint->sin_port);
+ ALOGV("[%d] setRetransmitEndpoint(%u.%u.%u.%u:%hu)", mConnId,
+ (a >> 24), (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a & 0xFF), p);
+ } else {
+ ALOGV("[%d] setRetransmitEndpoint = <none>", mConnId);
+ }
+
+ sp<MediaPlayerBase> p = getPlayer();
+
+ // Right now, the only valid time to set a retransmit endpoint is before
+ // player selection has been made (since the presence or absence of a
+ // retransmit endpoint is going to determine which player is selected during
+ // setDataSource).
+ if (p != 0) return INVALID_OPERATION;
+
+ if (NULL != endpoint) {
+ mRetransmitEndpoint = *endpoint;
+ mRetransmitEndpointValid = true;
+ } else {
+ mRetransmitEndpointValid = false;
+ }
+
+ return NO_ERROR;
+}
+
+void MediaPlayerService::Client::notify(
+ void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
+{
+ Client* client = static_cast<Client*>(cookie);
+
+ {
+ Mutex::Autolock l(client->mLock);
+ if (msg == MEDIA_PLAYBACK_COMPLETE && client->mNextClient != NULL) {
+ client->mAudioOutput->switchToNextOutput();
+ client->mNextClient->start();
+ client->mNextClient->mClient->notify(MEDIA_INFO, MEDIA_INFO_STARTED_AS_NEXT, 0, obj);
+ }
+ }
+
+ if (MEDIA_INFO == msg &&
+ MEDIA_INFO_METADATA_UPDATE == ext1) {
+ const media::Metadata::Type metadata_type = ext2;
+
+ if(client->shouldDropMetadata(metadata_type)) {
+ return;
+ }
+
+ // Update the list of metadata that have changed. getMetadata
+ // also access mMetadataUpdated and clears it.
+ client->addNewMetadataUpdate(metadata_type);
+ }
+ ALOGV("[%d] notify (%p, %d, %d, %d)", client->mConnId, cookie, msg, ext1, ext2);
+ client->mClient->notify(msg, ext1, ext2, obj);
+}
+
+
+bool MediaPlayerService::Client::shouldDropMetadata(media::Metadata::Type code) const
+{
+ Mutex::Autolock lock(mLock);
+
+ if (findMetadata(mMetadataDrop, code)) {
+ return true;
+ }
+
+ if (mMetadataAllow.isEmpty() || findMetadata(mMetadataAllow, code)) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+
+void MediaPlayerService::Client::addNewMetadataUpdate(media::Metadata::Type metadata_type) {
+ Mutex::Autolock lock(mLock);
+ if (mMetadataUpdated.indexOf(metadata_type) < 0) {
+ mMetadataUpdated.add(metadata_type);
+ }
+}
+
+#if CALLBACK_ANTAGONIZER
+const int Antagonizer::interval = 10000; // 10 msecs
+
+Antagonizer::Antagonizer(notify_callback_f cb, void* client) :
+ mExit(false), mActive(false), mClient(client), mCb(cb)
+{
+ createThread(callbackThread, this);
+}
+
+void Antagonizer::kill()
+{
+ Mutex::Autolock _l(mLock);
+ mActive = false;
+ mExit = true;
+ mCondition.wait(mLock);
+}
+
+int Antagonizer::callbackThread(void* user)
+{
+ ALOGD("Antagonizer started");
+ Antagonizer* p = reinterpret_cast<Antagonizer*>(user);
+ while (!p->mExit) {
+ if (p->mActive) {
+ ALOGV("send event");
+ p->mCb(p->mClient, 0, 0, 0);
+ }
+ usleep(interval);
+ }
+ Mutex::Autolock _l(p->mLock);
+ p->mCondition.signal();
+ ALOGD("Antagonizer stopped");
+ return 0;
+}
+#endif
+
+static size_t kDefaultHeapSize = 1024 * 1024; // 1MB
+
+sp<IMemory> MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
+{
+ ALOGV("decode(%s)", url);
+ sp<MemoryBase> mem;
+ sp<MediaPlayerBase> player;
+
+ // Protect our precious, precious DRMd ringtones by only allowing
+ // decoding of http, but not filesystem paths or content Uris.
+ // If the application wants to decode those, it should open a
+ // filedescriptor for them and use that.
+ if (url != NULL && strncmp(url, "http://", 7) != 0) {
+ ALOGD("Can't decode %s by path, use filedescriptor instead", url);
+ return mem;
+ }
+
+ player_type playerType = getPlayerType(url);
+ ALOGV("player type = %d", playerType);
+
+ // create the right type of player
+ sp<AudioCache> cache = new AudioCache(url);
+ player = android::createPlayer(playerType, cache.get(), cache->notify);
+ if (player == NULL) goto Exit;
+ if (player->hardwareOutput()) goto Exit;
+
+ static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
+
+ // set data source
+ if (player->setDataSource(url) != NO_ERROR) goto Exit;
+
+ ALOGV("prepare");
+ player->prepareAsync();
+
+ ALOGV("wait for prepare");
+ if (cache->wait() != NO_ERROR) goto Exit;
+
+ ALOGV("start");
+ player->start();
+
+ ALOGV("wait for playback complete");
+ cache->wait();
+ // in case of error, return what was successfully decoded.
+ if (cache->size() == 0) {
+ goto Exit;
+ }
+
+ mem = new MemoryBase(cache->getHeap(), 0, cache->size());
+ *pSampleRate = cache->sampleRate();
+ *pNumChannels = cache->channelCount();
+ *pFormat = cache->format();
+ ALOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
+
+Exit:
+ if (player != 0) player->reset();
+ return mem;
+}
+
+sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
+{
+ ALOGV("decode(%d, %lld, %lld)", fd, offset, length);
+ sp<MemoryBase> mem;
+ sp<MediaPlayerBase> player;
+
+ player_type playerType = getPlayerType(fd, offset, length);
+ ALOGV("player type = %d", playerType);
+
+ // create the right type of player
+ sp<AudioCache> cache = new AudioCache("decode_fd");
+ player = android::createPlayer(playerType, cache.get(), cache->notify);
+ if (player == NULL) goto Exit;
+ if (player->hardwareOutput()) goto Exit;
+
+ static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache);
+
+ // set data source
+ if (player->setDataSource(fd, offset, length) != NO_ERROR) goto Exit;
+
+ ALOGV("prepare");
+ player->prepareAsync();
+
+ ALOGV("wait for prepare");
+ if (cache->wait() != NO_ERROR) goto Exit;
+
+ ALOGV("start");
+ player->start();
+
+ ALOGV("wait for playback complete");
+ cache->wait();
+ // in case of error, return what was successfully decoded.
+ if (cache->size() == 0) {
+ goto Exit;
+ }
+
+ mem = new MemoryBase(cache->getHeap(), 0, cache->size());
+ *pSampleRate = cache->sampleRate();
+ *pNumChannels = cache->channelCount();
+ *pFormat = cache->format();
+ ALOGV("return memory @ %p, sampleRate=%u, channelCount = %d, format = %d", mem->pointer(), *pSampleRate, *pNumChannels, *pFormat);
+
+Exit:
+ if (player != 0) player->reset();
+ ::close(fd);
+ return mem;
+}
+
+
+#undef LOG_TAG
+#define LOG_TAG "AudioSink"
+MediaPlayerService::AudioOutput::AudioOutput(int sessionId)
+ : mCallback(NULL),
+ mCallbackCookie(NULL),
+ mCallbackData(NULL),
+ mSessionId(sessionId) {
+ ALOGV("AudioOutput(%d)", sessionId);
+ mTrack = 0;
+ mRecycledTrack = 0;
+ mStreamType = AUDIO_STREAM_MUSIC;
+ mLeftVolume = 1.0;
+ mRightVolume = 1.0;
+ mPlaybackRatePermille = 1000;
+ mSampleRateHz = 0;
+ mMsecsPerFrame = 0;
+ mAuxEffectId = 0;
+ mSendLevel = 0.0;
+ setMinBufferCount();
+}
+
+MediaPlayerService::AudioOutput::~AudioOutput()
+{
+ close();
+ delete mRecycledTrack;
+ delete mCallbackData;
+}
+
+void MediaPlayerService::AudioOutput::setMinBufferCount()
+{
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("ro.kernel.qemu", value, 0)) {
+ mIsOnEmulator = true;
+ mMinBufferCount = 12; // to prevent systematic buffer underrun for emulator
+ }
+}
+
+bool MediaPlayerService::AudioOutput::isOnEmulator()
+{
+ setMinBufferCount();
+ return mIsOnEmulator;
+}
+
+int MediaPlayerService::AudioOutput::getMinBufferCount()
+{
+ setMinBufferCount();
+ return mMinBufferCount;
+}
+
+ssize_t MediaPlayerService::AudioOutput::bufferSize() const
+{
+ if (mTrack == 0) return NO_INIT;
+ return mTrack->frameCount() * frameSize();
+}
+
+ssize_t MediaPlayerService::AudioOutput::frameCount() const
+{
+ if (mTrack == 0) return NO_INIT;
+ return mTrack->frameCount();
+}
+
+ssize_t MediaPlayerService::AudioOutput::channelCount() const
+{
+ if (mTrack == 0) return NO_INIT;
+ return mTrack->channelCount();
+}
+
+ssize_t MediaPlayerService::AudioOutput::frameSize() const
+{
+ if (mTrack == 0) return NO_INIT;
+ return mTrack->frameSize();
+}
+
+uint32_t MediaPlayerService::AudioOutput::latency () const
+{
+ if (mTrack == 0) return 0;
+ return mTrack->latency();
+}
+
+float MediaPlayerService::AudioOutput::msecsPerFrame() const
+{
+ return mMsecsPerFrame;
+}
+
+status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position)
+{
+ if (mTrack == 0) return NO_INIT;
+ return mTrack->getPosition(position);
+}
+
+status_t MediaPlayerService::AudioOutput::open(
+ uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
+ audio_format_t format, int bufferCount,
+ AudioCallback cb, void *cookie)
+{
+ mCallback = cb;
+ mCallbackCookie = cookie;
+
+ // Check argument "bufferCount" against the mininum buffer count
+ if (bufferCount < mMinBufferCount) {
+ ALOGD("bufferCount (%d) is too small and increased to %d", bufferCount, mMinBufferCount);
+ bufferCount = mMinBufferCount;
+
+ }
+ ALOGV("open(%u, %d, 0x%x, %d, %d, %d)", sampleRate, channelCount, channelMask,
+ format, bufferCount, mSessionId);
+ int afSampleRate;
+ int afFrameCount;
+ int frameCount;
+
+ if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
+ return NO_INIT;
+ }
+ if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
+ return NO_INIT;
+ }
+
+ frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate;
+
+ if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
+ channelMask = audio_channel_out_mask_from_count(channelCount);
+ if (0 == channelMask) {
+ ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
+ return NO_INIT;
+ }
+ }
+ if (mRecycledTrack) {
+ // check if the existing track can be reused as-is, or if a new track needs to be created.
+
+ bool reuse = true;
+ if ((mCallbackData == NULL && mCallback != NULL) ||
+ (mCallbackData != NULL && mCallback == NULL)) {
+ // recycled track uses callbacks but the caller wants to use writes, or vice versa
+ ALOGV("can't chain callback and write");
+ reuse = false;
+ } else if ((mRecycledTrack->getSampleRate() != sampleRate) ||
+ (mRecycledTrack->channelCount() != channelCount) ||
+ (mRecycledTrack->frameCount() != frameCount)) {
+ ALOGV("samplerate, channelcount or framecount differ");
+ reuse = false;
+ }
+ if (reuse) {
+ ALOGV("chaining to next output");
+ close();
+ mTrack = mRecycledTrack;
+ mRecycledTrack = NULL;
+ if (mCallbackData != NULL) {
+ mCallbackData->setOutput(this);
+ }
+ return OK;
+ }
+
+ // if we're not going to reuse the track, unblock and flush it
+ if (mCallbackData != NULL) {
+ mCallbackData->setOutput(NULL);
+ mCallbackData->endTrackSwitch();
+ }
+ mRecycledTrack->flush();
+ delete mRecycledTrack;
+ mRecycledTrack = NULL;
+ delete mCallbackData;
+ mCallbackData = NULL;
+ close();
+ }
+
+ AudioTrack *t;
+ if (mCallback != NULL) {
+ mCallbackData = new CallbackData(this);
+ t = new AudioTrack(
+ mStreamType,
+ sampleRate,
+ format,
+ channelMask,
+ frameCount,
+ AUDIO_POLICY_OUTPUT_FLAG_NONE,
+ CallbackWrapper,
+ mCallbackData,
+ 0, // notification frames
+ mSessionId);
+ } else {
+ t = new AudioTrack(
+ mStreamType,
+ sampleRate,
+ format,
+ channelMask,
+ frameCount,
+ AUDIO_POLICY_OUTPUT_FLAG_NONE,
+ NULL,
+ NULL,
+ 0,
+ mSessionId);
+ }
+
+ if ((t == 0) || (t->initCheck() != NO_ERROR)) {
+ ALOGE("Unable to create audio track");
+ delete t;
+ return NO_INIT;
+ }
+
+ ALOGV("setVolume");
+ t->setVolume(mLeftVolume, mRightVolume);
+
+ mSampleRateHz = sampleRate;
+ mMsecsPerFrame = mPlaybackRatePermille / (float) sampleRate;
+ mTrack = t;
+
+ status_t res = t->setSampleRate(mPlaybackRatePermille * mSampleRateHz / 1000);
+ if (res != NO_ERROR) {
+ return res;
+ }
+ t->setAuxEffectSendLevel(mSendLevel);
+ return t->attachAuxEffect(mAuxEffectId);;
+}
+
+void MediaPlayerService::AudioOutput::start()
+{
+ ALOGV("start");
+ if (mCallbackData != NULL) {
+ mCallbackData->endTrackSwitch();
+ }
+ if (mTrack) {
+ mTrack->setVolume(mLeftVolume, mRightVolume);
+ mTrack->setAuxEffectSendLevel(mSendLevel);
+ mTrack->start();
+ }
+}
+
+void MediaPlayerService::AudioOutput::setNextOutput(const sp<AudioOutput>& nextOutput) {
+ mNextOutput = nextOutput;
+}
+
+
+void MediaPlayerService::AudioOutput::switchToNextOutput() {
+ ALOGV("switchToNextOutput");
+ if (mNextOutput != NULL) {
+ if (mCallbackData != NULL) {
+ mCallbackData->beginTrackSwitch();
+ }
+ delete mNextOutput->mCallbackData;
+ mNextOutput->mCallbackData = mCallbackData;
+ mCallbackData = NULL;
+ mNextOutput->mRecycledTrack = mTrack;
+ mTrack = NULL;
+ mNextOutput->mSampleRateHz = mSampleRateHz;
+ mNextOutput->mMsecsPerFrame = mMsecsPerFrame;
+ }
+}
+
+ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
+{
+ LOG_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback.");
+
+ //ALOGV("write(%p, %u)", buffer, size);
+ if (mTrack) {
+ ssize_t ret = mTrack->write(buffer, size);
+ return ret;
+ }
+ return NO_INIT;
+}
+
+void MediaPlayerService::AudioOutput::stop()
+{
+ ALOGV("stop");
+ if (mTrack) mTrack->stop();
+}
+
+void MediaPlayerService::AudioOutput::flush()
+{
+ ALOGV("flush");
+ if (mTrack) mTrack->flush();
+}
+
+void MediaPlayerService::AudioOutput::pause()
+{
+ ALOGV("pause");
+ if (mTrack) mTrack->pause();
+}
+
+void MediaPlayerService::AudioOutput::close()
+{
+ ALOGV("close");
+ delete mTrack;
+ mTrack = 0;
+}
+
+void MediaPlayerService::AudioOutput::setVolume(float left, float right)
+{
+ ALOGV("setVolume(%f, %f)", left, right);
+ mLeftVolume = left;
+ mRightVolume = right;
+ if (mTrack) {
+ mTrack->setVolume(left, right);
+ }
+}
+
+status_t MediaPlayerService::AudioOutput::setPlaybackRatePermille(int32_t ratePermille)
+{
+ ALOGV("setPlaybackRatePermille(%d)", ratePermille);
+ status_t res = NO_ERROR;
+ if (mTrack) {
+ res = mTrack->setSampleRate(ratePermille * mSampleRateHz / 1000);
+ } else {
+ res = NO_INIT;
+ }
+ mPlaybackRatePermille = ratePermille;
+ if (mSampleRateHz != 0) {
+ mMsecsPerFrame = mPlaybackRatePermille / (float) mSampleRateHz;
+ }
+ return res;
+}
+
+status_t MediaPlayerService::AudioOutput::setAuxEffectSendLevel(float level)
+{
+ ALOGV("setAuxEffectSendLevel(%f)", level);
+ mSendLevel = level;
+ if (mTrack) {
+ return mTrack->setAuxEffectSendLevel(level);
+ }
+ return NO_ERROR;
+}
+
+status_t MediaPlayerService::AudioOutput::attachAuxEffect(int effectId)
+{
+ ALOGV("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) {
+ //ALOGV("callbackwrapper");
+ if (event != AudioTrack::EVENT_MORE_DATA) {
+ return;
+ }
+
+ CallbackData *data = (CallbackData*)cookie;
+ data->lock();
+ AudioOutput *me = data->getOutput();
+ AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
+ if (me == NULL) {
+ // no output set, likely because the track was scheduled to be reused
+ // by another player, but the format turned out to be incompatible.
+ data->unlock();
+ buffer->size = 0;
+ return;
+ }
+
+ size_t actualSize = (*me->mCallback)(
+ me, buffer->raw, buffer->size, me->mCallbackCookie);
+
+ if (actualSize == 0 && buffer->size > 0 && me->mNextOutput == NULL) {
+ // We've reached EOS but the audio track is not stopped yet,
+ // keep playing silence.
+
+ memset(buffer->raw, 0, buffer->size);
+ actualSize = buffer->size;
+ }
+
+ buffer->size = actualSize;
+ data->unlock();
+}
+
+int MediaPlayerService::AudioOutput::getSessionId()
+{
+ return mSessionId;
+}
+
+#undef LOG_TAG
+#define LOG_TAG "AudioCache"
+MediaPlayerService::AudioCache::AudioCache(const char* name) :
+ mChannelCount(0), mFrameCount(1024), mSampleRate(0), mSize(0),
+ mError(NO_ERROR), mCommandComplete(false)
+{
+ // create ashmem heap
+ mHeap = new MemoryHeapBase(kDefaultHeapSize, 0, name);
+}
+
+uint32_t MediaPlayerService::AudioCache::latency () const
+{
+ return 0;
+}
+
+float MediaPlayerService::AudioCache::msecsPerFrame() const
+{
+ return mMsecsPerFrame;
+}
+
+status_t MediaPlayerService::AudioCache::getPosition(uint32_t *position)
+{
+ if (position == 0) return BAD_VALUE;
+ *position = mSize;
+ return NO_ERROR;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct CallbackThread : public Thread {
+ CallbackThread(const wp<MediaPlayerBase::AudioSink> &sink,
+ MediaPlayerBase::AudioSink::AudioCallback cb,
+ void *cookie);
+
+protected:
+ virtual ~CallbackThread();
+
+ virtual bool threadLoop();
+
+private:
+ wp<MediaPlayerBase::AudioSink> mSink;
+ MediaPlayerBase::AudioSink::AudioCallback mCallback;
+ void *mCookie;
+ void *mBuffer;
+ size_t mBufferSize;
+
+ CallbackThread(const CallbackThread &);
+ CallbackThread &operator=(const CallbackThread &);
+};
+
+CallbackThread::CallbackThread(
+ const wp<MediaPlayerBase::AudioSink> &sink,
+ MediaPlayerBase::AudioSink::AudioCallback cb,
+ void *cookie)
+ : mSink(sink),
+ mCallback(cb),
+ mCookie(cookie),
+ mBuffer(NULL),
+ mBufferSize(0) {
+}
+
+CallbackThread::~CallbackThread() {
+ if (mBuffer) {
+ free(mBuffer);
+ mBuffer = NULL;
+ }
+}
+
+bool CallbackThread::threadLoop() {
+ sp<MediaPlayerBase::AudioSink> sink = mSink.promote();
+ if (sink == NULL) {
+ return false;
+ }
+
+ if (mBuffer == NULL) {
+ mBufferSize = sink->bufferSize();
+ mBuffer = malloc(mBufferSize);
+ }
+
+ size_t actualSize =
+ (*mCallback)(sink.get(), mBuffer, mBufferSize, mCookie);
+
+ if (actualSize > 0) {
+ sink->write(mBuffer, actualSize);
+ }
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+status_t MediaPlayerService::AudioCache::open(
+ uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
+ audio_format_t format, int bufferCount,
+ AudioCallback cb, void *cookie)
+{
+ ALOGV("open(%u, %d, 0x%x, %d, %d)", sampleRate, channelCount, channelMask, format, bufferCount);
+ if (mHeap->getHeapID() < 0) {
+ return NO_INIT;
+ }
+
+ mSampleRate = sampleRate;
+ mChannelCount = (uint16_t)channelCount;
+ mFormat = format;
+ mMsecsPerFrame = 1.e3 / (float) sampleRate;
+
+ if (cb != NULL) {
+ mCallbackThread = new CallbackThread(this, cb, cookie);
+ }
+ return NO_ERROR;
+}
+
+void MediaPlayerService::AudioCache::start() {
+ if (mCallbackThread != NULL) {
+ mCallbackThread->run("AudioCache callback");
+ }
+}
+
+void MediaPlayerService::AudioCache::stop() {
+ if (mCallbackThread != NULL) {
+ mCallbackThread->requestExitAndWait();
+ }
+}
+
+ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
+{
+ ALOGV("write(%p, %u)", buffer, size);
+ if ((buffer == 0) || (size == 0)) return size;
+
+ uint8_t* p = static_cast<uint8_t*>(mHeap->getBase());
+ if (p == NULL) return NO_INIT;
+ p += mSize;
+ ALOGV("memcpy(%p, %p, %u)", p, buffer, size);
+ if (mSize + size > mHeap->getSize()) {
+ ALOGE("Heap size overflow! req size: %d, max size: %d", (mSize + size), mHeap->getSize());
+ size = mHeap->getSize() - mSize;
+ }
+ memcpy(p, buffer, size);
+ mSize += size;
+ return size;
+}
+
+// call with lock held
+status_t MediaPlayerService::AudioCache::wait()
+{
+ Mutex::Autolock lock(mLock);
+ while (!mCommandComplete) {
+ mSignal.wait(mLock);
+ }
+ mCommandComplete = false;
+
+ if (mError == NO_ERROR) {
+ ALOGV("wait - success");
+ } else {
+ ALOGV("wait - error");
+ }
+ return mError;
+}
+
+void MediaPlayerService::AudioCache::notify(
+ void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
+{
+ ALOGV("notify(%p, %d, %d, %d)", cookie, msg, ext1, ext2);
+ AudioCache* p = static_cast<AudioCache*>(cookie);
+
+ // ignore buffering messages
+ switch (msg)
+ {
+ case MEDIA_ERROR:
+ ALOGE("Error %d, %d occurred", ext1, ext2);
+ p->mError = ext1;
+ break;
+ case MEDIA_PREPARED:
+ ALOGV("prepared");
+ break;
+ case MEDIA_PLAYBACK_COMPLETE:
+ ALOGV("playback complete");
+ break;
+ default:
+ ALOGV("ignored");
+ return;
+ }
+
+ // wake up thread
+ Mutex::Autolock lock(p->mLock);
+ p->mCommandComplete = true;
+ p->mSignal.signal();
+}
+
+int MediaPlayerService::AudioCache::getSessionId()
+{
+ return 0;
+}
+
+void MediaPlayerService::addBatteryData(uint32_t params)
+{
+ Mutex::Autolock lock(mLock);
+
+ int32_t time = systemTime() / 1000000L;
+
+ // change audio output devices. This notification comes from AudioFlinger
+ if ((params & kBatteryDataSpeakerOn)
+ || (params & kBatteryDataOtherAudioDeviceOn)) {
+
+ int deviceOn[NUM_AUDIO_DEVICES];
+ for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+ deviceOn[i] = 0;
+ }
+
+ if ((params & kBatteryDataSpeakerOn)
+ && (params & kBatteryDataOtherAudioDeviceOn)) {
+ deviceOn[SPEAKER_AND_OTHER] = 1;
+ } else if (params & kBatteryDataSpeakerOn) {
+ deviceOn[SPEAKER] = 1;
+ } else {
+ deviceOn[OTHER_AUDIO_DEVICE] = 1;
+ }
+
+ for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+ if (mBatteryAudio.deviceOn[i] != deviceOn[i]){
+
+ if (mBatteryAudio.refCount > 0) { // if playing audio
+ if (!deviceOn[i]) {
+ mBatteryAudio.lastTime[i] += time;
+ mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
+ mBatteryAudio.lastTime[i] = 0;
+ } else {
+ mBatteryAudio.lastTime[i] = 0 - time;
+ }
+ }
+
+ mBatteryAudio.deviceOn[i] = deviceOn[i];
+ }
+ }
+ return;
+ }
+
+ // an sudio stream is started
+ if (params & kBatteryDataAudioFlingerStart) {
+ // record the start time only if currently no other audio
+ // is being played
+ if (mBatteryAudio.refCount == 0) {
+ for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+ if (mBatteryAudio.deviceOn[i]) {
+ mBatteryAudio.lastTime[i] -= time;
+ }
+ }
+ }
+
+ mBatteryAudio.refCount ++;
+ return;
+
+ } else if (params & kBatteryDataAudioFlingerStop) {
+ if (mBatteryAudio.refCount <= 0) {
+ ALOGW("Battery track warning: refCount is <= 0");
+ return;
+ }
+
+ // record the stop time only if currently this is the only
+ // audio being played
+ if (mBatteryAudio.refCount == 1) {
+ for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+ if (mBatteryAudio.deviceOn[i]) {
+ mBatteryAudio.lastTime[i] += time;
+ mBatteryAudio.totalTime[i] += mBatteryAudio.lastTime[i];
+ mBatteryAudio.lastTime[i] = 0;
+ }
+ }
+ }
+
+ mBatteryAudio.refCount --;
+ return;
+ }
+
+ int uid = IPCThreadState::self()->getCallingUid();
+ if (uid == AID_MEDIA) {
+ return;
+ }
+ int index = mBatteryData.indexOfKey(uid);
+
+ if (index < 0) { // create a new entry for this UID
+ BatteryUsageInfo info;
+ info.audioTotalTime = 0;
+ info.videoTotalTime = 0;
+ info.audioLastTime = 0;
+ info.videoLastTime = 0;
+ info.refCount = 0;
+
+ if (mBatteryData.add(uid, info) == NO_MEMORY) {
+ ALOGE("Battery track error: no memory for new app");
+ return;
+ }
+ }
+
+ BatteryUsageInfo &info = mBatteryData.editValueFor(uid);
+
+ if (params & kBatteryDataCodecStarted) {
+ if (params & kBatteryDataTrackAudio) {
+ info.audioLastTime -= time;
+ info.refCount ++;
+ }
+ if (params & kBatteryDataTrackVideo) {
+ info.videoLastTime -= time;
+ info.refCount ++;
+ }
+ } else {
+ if (info.refCount == 0) {
+ ALOGW("Battery track warning: refCount is already 0");
+ return;
+ } else if (info.refCount < 0) {
+ ALOGE("Battery track error: refCount < 0");
+ mBatteryData.removeItem(uid);
+ return;
+ }
+
+ if (params & kBatteryDataTrackAudio) {
+ info.audioLastTime += time;
+ info.refCount --;
+ }
+ if (params & kBatteryDataTrackVideo) {
+ info.videoLastTime += time;
+ info.refCount --;
+ }
+
+ // no stream is being played by this UID
+ if (info.refCount == 0) {
+ info.audioTotalTime += info.audioLastTime;
+ info.audioLastTime = 0;
+ info.videoTotalTime += info.videoLastTime;
+ info.videoLastTime = 0;
+ }
+ }
+}
+
+status_t MediaPlayerService::pullBatteryData(Parcel* reply) {
+ Mutex::Autolock lock(mLock);
+
+ // audio output devices usage
+ int32_t time = systemTime() / 1000000L; //in ms
+ int32_t totalTime;
+
+ for (int i = 0; i < NUM_AUDIO_DEVICES; i++) {
+ totalTime = mBatteryAudio.totalTime[i];
+
+ if (mBatteryAudio.deviceOn[i]
+ && (mBatteryAudio.lastTime[i] != 0)) {
+ int32_t tmpTime = mBatteryAudio.lastTime[i] + time;
+ totalTime += tmpTime;
+ }
+
+ reply->writeInt32(totalTime);
+ // reset the total time
+ mBatteryAudio.totalTime[i] = 0;
+ }
+
+ // codec usage
+ BatteryUsageInfo info;
+ int size = mBatteryData.size();
+
+ reply->writeInt32(size);
+ int i = 0;
+
+ while (i < size) {
+ info = mBatteryData.valueAt(i);
+
+ reply->writeInt32(mBatteryData.keyAt(i)); //UID
+ reply->writeInt32(info.audioTotalTime);
+ reply->writeInt32(info.videoTotalTime);
+
+ info.audioTotalTime = 0;
+ info.videoTotalTime = 0;
+
+ // remove the UID entry where no stream is being played
+ if (info.refCount <= 0) {
+ mBatteryData.removeItemsAt(i);
+ size --;
+ i --;
+ }
+ i++;
+ }
+ return NO_ERROR;
+}
+} // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
new file mode 100644
index 0000000..b08dd6c
--- /dev/null
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -0,0 +1,430 @@
+/*
+**
+** 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_MEDIAPLAYERSERVICE_H
+#define ANDROID_MEDIAPLAYERSERVICE_H
+
+#include <arpa/inet.h>
+
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <utils/List.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include <media/IMediaPlayerService.h>
+#include <media/MediaPlayerInterface.h>
+#include <media/Metadata.h>
+#include <media/stagefright/foundation/ABase.h>
+
+#include <system/audio.h>
+
+namespace android {
+
+class AudioTrack;
+class IMediaRecorder;
+class IMediaMetadataRetriever;
+class IOMX;
+class MediaRecorderClient;
+
+#define CALLBACK_ANTAGONIZER 0
+#if CALLBACK_ANTAGONIZER
+class Antagonizer {
+public:
+ Antagonizer(notify_callback_f cb, void* client);
+ void start() { mActive = true; }
+ void stop() { mActive = false; }
+ void kill();
+private:
+ static const int interval;
+ Antagonizer();
+ static int callbackThread(void* cookie);
+ Mutex mLock;
+ Condition mCondition;
+ bool mExit;
+ bool mActive;
+ void* mClient;
+ notify_callback_f mCb;
+};
+#endif
+
+class MediaPlayerService : public BnMediaPlayerService
+{
+ class Client;
+
+ class AudioOutput : public MediaPlayerBase::AudioSink
+ {
+ class CallbackData;
+
+ public:
+ AudioOutput(int sessionId);
+ virtual ~AudioOutput();
+
+ virtual bool ready() const { return mTrack != NULL; }
+ virtual bool realtime() const { return true; }
+ virtual ssize_t bufferSize() const;
+ virtual ssize_t frameCount() const;
+ virtual ssize_t channelCount() const;
+ virtual ssize_t frameSize() const;
+ virtual uint32_t latency() const;
+ virtual float msecsPerFrame() const;
+ virtual status_t getPosition(uint32_t *position);
+ virtual int getSessionId();
+
+ virtual status_t open(
+ uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
+ audio_format_t format, int bufferCount,
+ AudioCallback cb, void *cookie);
+
+ virtual void start();
+ virtual ssize_t write(const void* buffer, size_t size);
+ virtual void stop();
+ virtual void flush();
+ virtual void pause();
+ virtual void close();
+ void setAudioStreamType(audio_stream_type_t streamType) { mStreamType = streamType; }
+ void setVolume(float left, float right);
+ virtual status_t setPlaybackRatePermille(int32_t ratePermille);
+ status_t setAuxEffectSendLevel(float level);
+ status_t attachAuxEffect(int effectId);
+ virtual status_t dump(int fd, const Vector<String16>& args) const;
+
+ static bool isOnEmulator();
+ static int getMinBufferCount();
+ void setNextOutput(const sp<AudioOutput>& nextOutput);
+ void switchToNextOutput();
+ virtual bool needsTrailingPadding() { return mNextOutput == NULL; }
+
+ private:
+ static void setMinBufferCount();
+ static void CallbackWrapper(
+ int event, void *me, void *info);
+
+ AudioTrack* mTrack;
+ AudioTrack* mRecycledTrack;
+ sp<AudioOutput> mNextOutput;
+ AudioCallback mCallback;
+ void * mCallbackCookie;
+ CallbackData * mCallbackData;
+ audio_stream_type_t mStreamType;
+ float mLeftVolume;
+ float mRightVolume;
+ int32_t mPlaybackRatePermille;
+ uint32_t mSampleRateHz; // sample rate of the content, as set in open()
+ float mMsecsPerFrame;
+ int mSessionId;
+ float mSendLevel;
+ int mAuxEffectId;
+ static bool mIsOnEmulator;
+ static int mMinBufferCount; // 12 for emulator; otherwise 4
+
+ // CallbackData is what is passed to the AudioTrack as the "user" data.
+ // We need to be able to target this to a different Output on the fly,
+ // so we can't use the Output itself for this.
+ class CallbackData {
+ public:
+ CallbackData(AudioOutput *cookie) {
+ mData = cookie;
+ mSwitching = false;
+ }
+ AudioOutput * getOutput() { return mData;}
+ void setOutput(AudioOutput* newcookie) { mData = newcookie; }
+ // lock/unlock are used by the callback before accessing the payload of this object
+ void lock() { mLock.lock(); }
+ void unlock() { mLock.unlock(); }
+ // beginTrackSwitch/endTrackSwitch are used when this object is being handed over
+ // to the next sink.
+ void beginTrackSwitch() { mLock.lock(); mSwitching = true; }
+ void endTrackSwitch() {
+ if (mSwitching) {
+ mLock.unlock();
+ }
+ mSwitching = false;
+ }
+ private:
+ AudioOutput * mData;
+ mutable Mutex mLock;
+ bool mSwitching;
+ DISALLOW_EVIL_CONSTRUCTORS(CallbackData);
+ };
+
+ }; // AudioOutput
+
+
+ class AudioCache : public MediaPlayerBase::AudioSink
+ {
+ public:
+ AudioCache(const char* name);
+ virtual ~AudioCache() {}
+
+ virtual bool ready() const { return (mChannelCount > 0) && (mHeap->getHeapID() > 0); }
+ virtual bool realtime() const { return false; }
+ virtual ssize_t bufferSize() const { return frameSize() * mFrameCount; }
+ virtual ssize_t frameCount() const { return mFrameCount; }
+ virtual ssize_t channelCount() const { return (ssize_t)mChannelCount; }
+ virtual ssize_t frameSize() const { return ssize_t(mChannelCount * ((mFormat == AUDIO_FORMAT_PCM_16_BIT)?sizeof(int16_t):sizeof(u_int8_t))); }
+ virtual uint32_t latency() const;
+ virtual float msecsPerFrame() const;
+ virtual status_t getPosition(uint32_t *position);
+ virtual int getSessionId();
+
+ virtual status_t open(
+ uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
+ audio_format_t format, int bufferCount = 1,
+ AudioCallback cb = NULL, void *cookie = NULL);
+
+ virtual void start();
+ virtual ssize_t write(const void* buffer, size_t size);
+ virtual void stop();
+ virtual void flush() {}
+ virtual void pause() {}
+ virtual void close() {}
+ void setAudioStreamType(audio_stream_type_t streamType) {}
+ void setVolume(float left, float right) {}
+ virtual status_t setPlaybackRatePermille(int32_t ratePermille) { return INVALID_OPERATION; }
+ uint32_t sampleRate() const { return mSampleRate; }
+ audio_format_t format() const { return mFormat; }
+ size_t size() const { return mSize; }
+ status_t wait();
+
+ sp<IMemoryHeap> getHeap() const { return mHeap; }
+
+ static void notify(void* cookie, int msg,
+ int ext1, int ext2, const Parcel *obj);
+ virtual status_t dump(int fd, const Vector<String16>& args) const;
+
+ private:
+ AudioCache();
+
+ Mutex mLock;
+ Condition mSignal;
+ sp<MemoryHeapBase> mHeap;
+ float mMsecsPerFrame;
+ uint16_t mChannelCount;
+ audio_format_t mFormat;
+ ssize_t mFrameCount;
+ uint32_t mSampleRate;
+ uint32_t mSize;
+ int mError;
+ bool mCommandComplete;
+
+ sp<Thread> mCallbackThread;
+ }; // AudioCache
+
+public:
+ static void instantiate();
+
+ // IMediaPlayerService interface
+ virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid);
+ void removeMediaRecorderClient(wp<MediaRecorderClient> client);
+ virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid);
+
+ virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId);
+
+ virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat);
+ virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat);
+ virtual sp<IOMX> getOMX();
+ virtual sp<ICrypto> makeCrypto();
+
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ void removeClient(wp<Client> client);
+
+ // For battery usage tracking purpose
+ struct BatteryUsageInfo {
+ // how many streams are being played by one UID
+ int refCount;
+ // a temp variable to store the duration(ms) of audio codecs
+ // when we start a audio codec, we minus the system time from audioLastTime
+ // when we pause it, we add the system time back to the audioLastTime
+ // so after the pause, audioLastTime = pause time - start time
+ // if multiple audio streams are played (or recorded), then audioLastTime
+ // = the total playing time of all the streams
+ int32_t audioLastTime;
+ // when all the audio streams are being paused, we assign audioLastTime to
+ // this variable, so this value could be provided to the battery app
+ // in the next pullBatteryData call
+ int32_t audioTotalTime;
+
+ int32_t videoLastTime;
+ int32_t videoTotalTime;
+ };
+ KeyedVector<int, BatteryUsageInfo> mBatteryData;
+
+ enum {
+ SPEAKER,
+ OTHER_AUDIO_DEVICE,
+ SPEAKER_AND_OTHER,
+ NUM_AUDIO_DEVICES
+ };
+
+ struct BatteryAudioFlingerUsageInfo {
+ int refCount; // how many audio streams are being played
+ int deviceOn[NUM_AUDIO_DEVICES]; // whether the device is currently used
+ int32_t lastTime[NUM_AUDIO_DEVICES]; // in ms
+ // totalTime[]: total time of audio output devices usage
+ int32_t totalTime[NUM_AUDIO_DEVICES]; // in ms
+ };
+
+ // This varialble is used to record the usage of audio output device
+ // for battery app
+ BatteryAudioFlingerUsageInfo mBatteryAudio;
+
+ // Collect info of the codec usage from media player and media recorder
+ virtual void addBatteryData(uint32_t params);
+ // API for the Battery app to pull the data of codecs usage
+ virtual status_t pullBatteryData(Parcel* reply);
+private:
+
+ class Client : public BnMediaPlayer {
+
+ // IMediaPlayer interface
+ virtual void disconnect();
+ virtual status_t setVideoSurfaceTexture(
+ const sp<ISurfaceTexture>& surfaceTexture);
+ virtual status_t prepareAsync();
+ virtual status_t start();
+ virtual status_t stop();
+ virtual status_t pause();
+ virtual status_t isPlaying(bool* state);
+ virtual status_t seekTo(int msec);
+ virtual status_t getCurrentPosition(int* msec);
+ virtual status_t getDuration(int* msec);
+ virtual status_t reset();
+ virtual status_t setAudioStreamType(audio_stream_type_t type);
+ virtual status_t setLooping(int loop);
+ virtual status_t setVolume(float leftVolume, float rightVolume);
+ virtual status_t invoke(const Parcel& request, Parcel *reply);
+ virtual status_t setMetadataFilter(const Parcel& filter);
+ virtual status_t getMetadata(bool update_only,
+ bool apply_filter,
+ Parcel *reply);
+ virtual status_t setAuxEffectSendLevel(float level);
+ virtual status_t attachAuxEffect(int effectId);
+ virtual status_t setParameter(int key, const Parcel &request);
+ virtual status_t getParameter(int key, Parcel *reply);
+ virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint);
+ virtual status_t setNextPlayer(const sp<IMediaPlayer>& player);
+
+ sp<MediaPlayerBase> createPlayer(player_type playerType);
+
+ virtual status_t setDataSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers);
+
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
+
+ virtual status_t setDataSource(const sp<IStreamSource> &source);
+
+ sp<MediaPlayerBase> setDataSource_pre(player_type playerType);
+ void setDataSource_post(const sp<MediaPlayerBase>& p,
+ status_t status);
+
+ player_type getPlayerType(int fd, int64_t offset, int64_t length);
+ player_type getPlayerType(const char* url);
+ player_type getPlayerType(const sp<IStreamSource> &source);
+
+ static void notify(void* cookie, int msg,
+ int ext1, int ext2, const Parcel *obj);
+
+ 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,
+ int audioSessionId,
+ uid_t uid);
+ Client();
+ virtual ~Client();
+
+ void deletePlayer();
+
+ sp<MediaPlayerBase> getPlayer() const { Mutex::Autolock lock(mLock); return mPlayer; }
+
+
+
+ // @param type Of the metadata to be tested.
+ // @return true if the metadata should be dropped according to
+ // the filters.
+ bool shouldDropMetadata(media::Metadata::Type type) const;
+
+ // Add a new element to the set of metadata updated. Noop if
+ // the element exists already.
+ // @param type Of the metadata to be recorded.
+ void addNewMetadataUpdate(media::Metadata::Type type);
+
+ // Disconnect from the currently connected ANativeWindow.
+ void disconnectNativeWindow();
+
+ mutable Mutex mLock;
+ sp<MediaPlayerBase> mPlayer;
+ sp<MediaPlayerService> mService;
+ sp<IMediaPlayerClient> mClient;
+ sp<AudioOutput> mAudioOutput;
+ pid_t mPid;
+ status_t mStatus;
+ bool mLoop;
+ int32_t mConnId;
+ int mAudioSessionId;
+ uid_t mUID;
+ sp<ANativeWindow> mConnectedWindow;
+ sp<IBinder> mConnectedWindowBinder;
+ struct sockaddr_in mRetransmitEndpoint;
+ bool mRetransmitEndpointValid;
+ sp<Client> mNextClient;
+
+ // Metadata filters.
+ media::Metadata::Filter mMetadataAllow; // protected by mLock
+ media::Metadata::Filter mMetadataDrop; // protected by mLock
+
+ // Metadata updated. For each MEDIA_INFO_METADATA_UPDATE
+ // notification we try to update mMetadataUpdated which is a
+ // set: no duplicate.
+ // getMetadata clears this set.
+ media::Metadata::Filter mMetadataUpdated; // protected by mLock
+
+#if CALLBACK_ANTAGONIZER
+ Antagonizer* mAntagonizer;
+#endif
+ }; // Client
+
+// ----------------------------------------------------------------------------
+
+ MediaPlayerService();
+ virtual ~MediaPlayerService();
+
+ mutable Mutex mLock;
+ SortedVector< wp<Client> > mClients;
+ SortedVector< wp<MediaRecorderClient> > mMediaRecorderClients;
+ int32_t mNextConnId;
+ sp<IOMX> mOMX;
+ sp<ICrypto> mCrypto;
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_MEDIAPLAYERSERVICE_H
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
new file mode 100644
index 0000000..beda945
--- /dev/null
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -0,0 +1,336 @@
+/*
+ ** 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaRecorderService"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <string.h>
+#include <cutils/atomic.h>
+#include <cutils/properties.h> // for property_get
+#include <android_runtime/ActivityManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/MemoryBase.h>
+
+#include <utils/String16.h>
+
+#include <system/audio.h>
+
+#include "MediaRecorderClient.h"
+#include "MediaPlayerService.h"
+
+#include "StagefrightRecorder.h"
+#include <gui/ISurfaceTexture.h>
+
+namespace android {
+
+const char* cameraPermission = "android.permission.CAMERA";
+const char* recordAudioPermission = "android.permission.RECORD_AUDIO";
+
+static bool checkPermission(const char* permissionString) {
+#ifndef HAVE_ANDROID_OS
+ return true;
+#endif
+ if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
+ bool ok = checkCallingPermission(String16(permissionString));
+ if (!ok) ALOGE("Request requires %s", permissionString);
+ return ok;
+}
+
+
+sp<ISurfaceTexture> MediaRecorderClient::querySurfaceMediaSource()
+{
+ ALOGV("Query SurfaceMediaSource");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NULL;
+ }
+ return mRecorder->querySurfaceMediaSource();
+}
+
+
+
+status_t MediaRecorderClient::setCamera(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy)
+{
+ ALOGV("setCamera");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setCamera(camera, proxy);
+}
+
+status_t MediaRecorderClient::setPreviewSurface(const sp<Surface>& surface)
+{
+ ALOGV("setPreviewSurface");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setPreviewSurface(surface);
+}
+
+status_t MediaRecorderClient::setVideoSource(int vs)
+{
+ ALOGV("setVideoSource(%d)", vs);
+ if (!checkPermission(cameraPermission)) {
+ return PERMISSION_DENIED;
+ }
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setVideoSource((video_source)vs);
+}
+
+status_t MediaRecorderClient::setAudioSource(int as)
+{
+ ALOGV("setAudioSource(%d)", as);
+ if (!checkPermission(recordAudioPermission)) {
+ return PERMISSION_DENIED;
+ }
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setAudioSource((audio_source_t)as);
+}
+
+status_t MediaRecorderClient::setOutputFormat(int of)
+{
+ ALOGV("setOutputFormat(%d)", of);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setOutputFormat((output_format)of);
+}
+
+status_t MediaRecorderClient::setVideoEncoder(int ve)
+{
+ ALOGV("setVideoEncoder(%d)", ve);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setVideoEncoder((video_encoder)ve);
+}
+
+status_t MediaRecorderClient::setAudioEncoder(int ae)
+{
+ ALOGV("setAudioEncoder(%d)", ae);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setAudioEncoder((audio_encoder)ae);
+}
+
+status_t MediaRecorderClient::setOutputFile(const char* path)
+{
+ ALOGV("setOutputFile(%s)", path);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setOutputFile(path);
+}
+
+status_t MediaRecorderClient::setOutputFile(int fd, int64_t offset, int64_t length)
+{
+ ALOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setOutputFile(fd, offset, length);
+}
+
+status_t MediaRecorderClient::setVideoSize(int width, int height)
+{
+ ALOGV("setVideoSize(%dx%d)", width, height);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setVideoSize(width, height);
+}
+
+status_t MediaRecorderClient::setVideoFrameRate(int frames_per_second)
+{
+ ALOGV("setVideoFrameRate(%d)", frames_per_second);
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setVideoFrameRate(frames_per_second);
+}
+
+status_t MediaRecorderClient::setParameters(const String8& params) {
+ ALOGV("setParameters(%s)", params.string());
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->setParameters(params);
+}
+
+status_t MediaRecorderClient::prepare()
+{
+ ALOGV("prepare");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->prepare();
+}
+
+
+status_t MediaRecorderClient::getMaxAmplitude(int* max)
+{
+ ALOGV("getMaxAmplitude");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->getMaxAmplitude(max);
+}
+
+status_t MediaRecorderClient::start()
+{
+ ALOGV("start");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->start();
+
+}
+
+status_t MediaRecorderClient::stop()
+{
+ ALOGV("stop");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->stop();
+}
+
+status_t MediaRecorderClient::init()
+{
+ ALOGV("init");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->init();
+}
+
+status_t MediaRecorderClient::close()
+{
+ ALOGV("close");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->close();
+}
+
+
+status_t MediaRecorderClient::reset()
+{
+ ALOGV("reset");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ return mRecorder->reset();
+}
+
+status_t MediaRecorderClient::release()
+{
+ ALOGV("release");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder != NULL) {
+ delete mRecorder;
+ mRecorder = NULL;
+ wp<MediaRecorderClient> client(this);
+ mMediaPlayerService->removeMediaRecorderClient(client);
+ }
+ return NO_ERROR;
+}
+
+MediaRecorderClient::MediaRecorderClient(const sp<MediaPlayerService>& service, pid_t pid)
+{
+ ALOGV("Client constructor");
+ mPid = pid;
+ mRecorder = new StagefrightRecorder;
+ mMediaPlayerService = service;
+}
+
+MediaRecorderClient::~MediaRecorderClient()
+{
+ ALOGV("Client destructor");
+ release();
+}
+
+status_t MediaRecorderClient::setListener(const sp<IMediaRecorderClient>& listener)
+{
+ ALOGV("setListener");
+ Mutex::Autolock lock(mLock);
+ if (mRecorder == NULL) {
+ ALOGE("recorder is not initialized");
+ return NO_INIT;
+ }
+ 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
new file mode 100644
index 0000000..c9ccf22
--- /dev/null
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -0,0 +1,76 @@
+/*
+ **
+ ** 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_MEDIARECORDERCLIENT_H
+#define ANDROID_MEDIARECORDERCLIENT_H
+
+#include <media/IMediaRecorder.h>
+
+namespace android {
+
+class MediaRecorderBase;
+class MediaPlayerService;
+class ICameraRecordingProxy;
+class ISurfaceTexture;
+
+class MediaRecorderClient : public BnMediaRecorder
+{
+public:
+ virtual status_t setCamera(const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy);
+ virtual status_t setPreviewSurface(const sp<Surface>& surface);
+ virtual status_t setVideoSource(int vs);
+ virtual status_t setAudioSource(int as);
+ virtual status_t setOutputFormat(int of);
+ virtual status_t setVideoEncoder(int ve);
+ virtual status_t setAudioEncoder(int ae);
+ virtual status_t setOutputFile(const char* path);
+ virtual status_t setOutputFile(int fd, int64_t offset,
+ int64_t length);
+ 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<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 init();
+ virtual status_t close();
+ virtual status_t release();
+ virtual status_t dump(int fd, const Vector<String16>& args) const;
+ virtual sp<ISurfaceTexture> querySurfaceMediaSource();
+
+private:
+ friend class MediaPlayerService; // for accessing private constructor
+
+ MediaRecorderClient(
+ const sp<MediaPlayerService>& service,
+ pid_t pid);
+ virtual ~MediaRecorderClient();
+
+ pid_t mPid;
+ Mutex mLock;
+ MediaRecorderBase *mRecorder;
+ sp<MediaPlayerService> mMediaPlayerService;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIARECORDERCLIENT_H
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
new file mode 100644
index 0000000..776d288
--- /dev/null
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -0,0 +1,254 @@
+/*
+**
+** 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_NDEBUG 0
+#define LOG_TAG "MetadataRetrieverClient"
+#include <utils/Log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include <string.h>
+#include <cutils/atomic.h>
+#include <cutils/properties.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <android_runtime/ActivityManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <media/MediaMetadataRetrieverInterface.h>
+#include <media/MediaPlayerInterface.h>
+#include <private/media/VideoFrame.h>
+#include "MidiMetadataRetriever.h"
+#include "MetadataRetrieverClient.h"
+#include "StagefrightMetadataRetriever.h"
+
+namespace android {
+
+extern player_type getPlayerType(const char* url);
+extern player_type getPlayerType(int fd, int64_t offset, int64_t length);
+
+MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid)
+{
+ ALOGV("MetadataRetrieverClient constructor pid(%d)", pid);
+ mPid = pid;
+ mThumbnail = NULL;
+ mAlbumArt = NULL;
+ mRetriever = NULL;
+}
+
+MetadataRetrieverClient::~MetadataRetrieverClient()
+{
+ ALOGV("MetadataRetrieverClient destructor");
+ disconnect();
+}
+
+status_t MetadataRetrieverClient::dump(int fd, const Vector<String16>& args) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ result.append(" MetadataRetrieverClient\n");
+ snprintf(buffer, 255, " pid(%d)\n", mPid);
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+ write(fd, "\n", 1);
+ return NO_ERROR;
+}
+
+void MetadataRetrieverClient::disconnect()
+{
+ ALOGV("disconnect from pid %d", mPid);
+ Mutex::Autolock lock(mLock);
+ mRetriever.clear();
+ mThumbnail.clear();
+ mAlbumArt.clear();
+ IPCThreadState::self()->flushCommands();
+}
+
+static sp<MediaMetadataRetrieverBase> createRetriever(player_type playerType)
+{
+ sp<MediaMetadataRetrieverBase> p;
+ switch (playerType) {
+ case STAGEFRIGHT_PLAYER:
+ case NU_PLAYER:
+ {
+ p = new StagefrightMetadataRetriever;
+ break;
+ }
+ case SONIVOX_PLAYER:
+ ALOGV("create midi metadata retriever");
+ p = new MidiMetadataRetriever();
+ break;
+ default:
+ // TODO:
+ // support for TEST_PLAYER
+ ALOGE("player type %d is not supported", playerType);
+ break;
+ }
+ if (p == NULL) {
+ ALOGE("failed to create a retriever object");
+ }
+ return p;
+}
+
+status_t MetadataRetrieverClient::setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers)
+{
+ ALOGV("setDataSource(%s)", url);
+ Mutex::Autolock lock(mLock);
+ if (url == NULL) {
+ return UNKNOWN_ERROR;
+ }
+ player_type playerType = getPlayerType(url);
+ ALOGV("player type = %d", playerType);
+ sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
+ if (p == NULL) return NO_INIT;
+ status_t ret = p->setDataSource(url, headers);
+ if (ret == NO_ERROR) mRetriever = p;
+ return ret;
+}
+
+status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t length)
+{
+ ALOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
+ Mutex::Autolock lock(mLock);
+ struct stat sb;
+ int ret = fstat(fd, &sb);
+ if (ret != 0) {
+ ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
+ return BAD_VALUE;
+ }
+ ALOGV("st_dev = %llu", sb.st_dev);
+ ALOGV("st_mode = %u", sb.st_mode);
+ ALOGV("st_uid = %lu", sb.st_uid);
+ ALOGV("st_gid = %lu", sb.st_gid);
+ ALOGV("st_size = %llu", sb.st_size);
+
+ if (offset >= sb.st_size) {
+ ALOGE("offset (%lld) bigger than file size (%llu)", offset, sb.st_size);
+ ::close(fd);
+ return BAD_VALUE;
+ }
+ if (offset + length > sb.st_size) {
+ length = sb.st_size - offset;
+ ALOGV("calculated length = %lld", length);
+ }
+
+ player_type playerType = getPlayerType(fd, offset, length);
+ ALOGV("player type = %d", playerType);
+ sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
+ if (p == NULL) {
+ ::close(fd);
+ return NO_INIT;
+ }
+ status_t status = p->setDataSource(fd, offset, length);
+ if (status == NO_ERROR) mRetriever = p;
+ ::close(fd);
+ return status;
+}
+
+sp<IMemory> MetadataRetrieverClient::getFrameAtTime(int64_t timeUs, int option)
+{
+ ALOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option);
+ Mutex::Autolock lock(mLock);
+ mThumbnail.clear();
+ if (mRetriever == NULL) {
+ ALOGE("retriever is not initialized");
+ return NULL;
+ }
+ VideoFrame *frame = mRetriever->getFrameAtTime(timeUs, option);
+ if (frame == NULL) {
+ ALOGE("failed to capture a video frame");
+ return NULL;
+ }
+ size_t size = sizeof(VideoFrame) + frame->mSize;
+ sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient");
+ if (heap == NULL) {
+ ALOGE("failed to create MemoryDealer");
+ delete frame;
+ return NULL;
+ }
+ mThumbnail = new MemoryBase(heap, 0, size);
+ if (mThumbnail == NULL) {
+ ALOGE("not enough memory for VideoFrame size=%u", size);
+ delete frame;
+ return NULL;
+ }
+ VideoFrame *frameCopy = static_cast<VideoFrame *>(mThumbnail->pointer());
+ frameCopy->mWidth = frame->mWidth;
+ frameCopy->mHeight = frame->mHeight;
+ frameCopy->mDisplayWidth = frame->mDisplayWidth;
+ frameCopy->mDisplayHeight = frame->mDisplayHeight;
+ frameCopy->mSize = frame->mSize;
+ frameCopy->mRotationAngle = frame->mRotationAngle;
+ ALOGV("rotation: %d", frameCopy->mRotationAngle);
+ frameCopy->mData = (uint8_t *)frameCopy + sizeof(VideoFrame);
+ memcpy(frameCopy->mData, frame->mData, frame->mSize);
+ delete frame; // Fix memory leakage
+ return mThumbnail;
+}
+
+sp<IMemory> MetadataRetrieverClient::extractAlbumArt()
+{
+ ALOGV("extractAlbumArt");
+ Mutex::Autolock lock(mLock);
+ mAlbumArt.clear();
+ if (mRetriever == NULL) {
+ ALOGE("retriever is not initialized");
+ return NULL;
+ }
+ MediaAlbumArt *albumArt = mRetriever->extractAlbumArt();
+ if (albumArt == NULL) {
+ ALOGE("failed to extract an album art");
+ return NULL;
+ }
+ size_t size = sizeof(MediaAlbumArt) + albumArt->mSize;
+ sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient");
+ if (heap == NULL) {
+ ALOGE("failed to create MemoryDealer object");
+ delete albumArt;
+ return NULL;
+ }
+ mAlbumArt = new MemoryBase(heap, 0, size);
+ if (mAlbumArt == NULL) {
+ ALOGE("not enough memory for MediaAlbumArt size=%u", size);
+ delete albumArt;
+ return NULL;
+ }
+ MediaAlbumArt *albumArtCopy = static_cast<MediaAlbumArt *>(mAlbumArt->pointer());
+ albumArtCopy->mSize = albumArt->mSize;
+ albumArtCopy->mData = (uint8_t *)albumArtCopy + sizeof(MediaAlbumArt);
+ memcpy(albumArtCopy->mData, albumArt->mData, albumArt->mSize);
+ delete albumArt; // Fix memory leakage
+ return mAlbumArt;
+}
+
+const char* MetadataRetrieverClient::extractMetadata(int keyCode)
+{
+ ALOGV("extractMetadata");
+ Mutex::Autolock lock(mLock);
+ if (mRetriever == NULL) {
+ ALOGE("retriever is not initialized");
+ return NULL;
+ }
+ return mRetriever->extractMetadata(keyCode);
+}
+
+}; // namespace android
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h
new file mode 100644
index 0000000..f08f933
--- /dev/null
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.h
@@ -0,0 +1,73 @@
+/*
+**
+** 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_MEDIAMETADATARETRIEVERSERVICE_H
+#define ANDROID_MEDIAMETADATARETRIEVERSERVICE_H
+
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <utils/List.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <binder/IMemory.h>
+
+#include <media/MediaMetadataRetrieverInterface.h>
+
+
+namespace android {
+
+class IMediaPlayerService;
+class MemoryDealer;
+
+class MetadataRetrieverClient : public BnMediaMetadataRetriever
+{
+public:
+ MetadataRetrieverClient(const sp<IMediaPlayerService>& service, pid_t pid, int32_t connId);
+
+ // Implements IMediaMetadataRetriever interface
+ // These methods are called in IMediaMetadataRetriever.cpp?
+ virtual void disconnect();
+
+ virtual status_t setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers);
+
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
+ virtual sp<IMemory> getFrameAtTime(int64_t timeUs, int option);
+ virtual sp<IMemory> extractAlbumArt();
+ virtual const char* extractMetadata(int keyCode);
+
+ virtual status_t dump(int fd, const Vector<String16>& args) const;
+
+private:
+ friend class MediaPlayerService;
+
+ explicit MetadataRetrieverClient(pid_t pid);
+ virtual ~MetadataRetrieverClient();
+
+ mutable Mutex mLock;
+ sp<MediaMetadataRetrieverBase> mRetriever;
+ pid_t mPid;
+
+ // Keep the shared memory copy of album art and capture frame (for thumbnail)
+ sp<IMemory> mAlbumArt;
+ sp<IMemory> mThumbnail;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MEDIAMETADATARETRIEVERSERVICE_H
+
diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp
new file mode 100644
index 0000000..8db5b9b
--- /dev/null
+++ b/media/libmediaplayerservice/MidiFile.cpp
@@ -0,0 +1,552 @@
+/* MidiFile.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.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MidiFile"
+#include "utils/Log.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <utils/threads.h>
+#include <libsonivox/eas_reverb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <system/audio.h>
+
+#include "MidiFile.h"
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// The midi engine buffers are a bit small (128 frames), so we batch them up
+static const int NUM_BUFFERS = 4;
+
+// TODO: Determine appropriate return codes
+static status_t ERROR_NOT_OPEN = -1;
+static status_t ERROR_OPEN_FAILED = -2;
+static status_t ERROR_EAS_FAILURE = -3;
+static status_t ERROR_ALLOCATE_FAILED = -4;
+
+static const S_EAS_LIB_CONFIG* pLibConfig = NULL;
+
+MidiFile::MidiFile() :
+ mEasData(NULL), mEasHandle(NULL), mAudioBuffer(NULL),
+ mPlayTime(-1), mDuration(-1), mState(EAS_STATE_ERROR),
+ mStreamType(AUDIO_STREAM_MUSIC), mLoop(false), mExit(false),
+ mPaused(false), mRender(false), mTid(-1)
+{
+ ALOGV("constructor");
+
+ mFileLocator.path = NULL;
+ mFileLocator.fd = -1;
+ mFileLocator.offset = 0;
+ mFileLocator.length = 0;
+
+ // get the library configuration and do sanity check
+ if (pLibConfig == NULL)
+ pLibConfig = EAS_Config();
+ if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) {
+ ALOGE("EAS library/header mismatch");
+ goto Failed;
+ }
+
+ // initialize EAS library
+ if (EAS_Init(&mEasData) != EAS_SUCCESS) {
+ ALOGE("EAS_Init failed");
+ goto Failed;
+ }
+
+ // select reverb preset and enable
+ EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER);
+ EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE);
+
+ // create playback thread
+ {
+ Mutex::Autolock l(mMutex);
+ mThread = new MidiFileThread(this);
+ mThread->run("midithread", ANDROID_PRIORITY_AUDIO);
+ mCondition.wait(mMutex);
+ ALOGV("thread started");
+ }
+
+ // indicate success
+ if (mTid > 0) {
+ ALOGV(" render thread(%d) started", mTid);
+ mState = EAS_STATE_READY;
+ }
+
+Failed:
+ return;
+}
+
+status_t MidiFile::initCheck()
+{
+ if (mState == EAS_STATE_ERROR) return ERROR_EAS_FAILURE;
+ return NO_ERROR;
+}
+
+MidiFile::~MidiFile() {
+ ALOGV("MidiFile destructor");
+ release();
+}
+
+status_t MidiFile::setDataSource(
+ const char* path, const KeyedVector<String8, String8> *) {
+ ALOGV("MidiFile::setDataSource url=%s", path);
+ Mutex::Autolock lock(mMutex);
+
+ // file still open?
+ if (mEasHandle) {
+ reset_nosync();
+ }
+
+ // open file and set paused state
+ mFileLocator.path = strdup(path);
+ mFileLocator.fd = -1;
+ mFileLocator.offset = 0;
+ mFileLocator.length = 0;
+ EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
+ if (result == EAS_SUCCESS) {
+ updateState();
+ }
+
+ if (result != EAS_SUCCESS) {
+ ALOGE("EAS_OpenFile failed: [%d]", (int)result);
+ mState = EAS_STATE_ERROR;
+ return ERROR_OPEN_FAILED;
+ }
+
+ mState = EAS_STATE_OPEN;
+ mPlayTime = 0;
+ return NO_ERROR;
+}
+
+status_t MidiFile::setDataSource(int fd, int64_t offset, int64_t length)
+{
+ ALOGV("MidiFile::setDataSource fd=%d", fd);
+ Mutex::Autolock lock(mMutex);
+
+ // file still open?
+ if (mEasHandle) {
+ reset_nosync();
+ }
+
+ // open file and set paused state
+ mFileLocator.fd = dup(fd);
+ mFileLocator.offset = offset;
+ mFileLocator.length = length;
+ EAS_RESULT result = EAS_OpenFile(mEasData, &mFileLocator, &mEasHandle);
+ updateState();
+
+ if (result != EAS_SUCCESS) {
+ ALOGE("EAS_OpenFile failed: [%d]", (int)result);
+ mState = EAS_STATE_ERROR;
+ return ERROR_OPEN_FAILED;
+ }
+
+ mState = EAS_STATE_OPEN;
+ mPlayTime = 0;
+ return NO_ERROR;
+}
+
+status_t MidiFile::prepare()
+{
+ ALOGV("MidiFile::prepare");
+ Mutex::Autolock lock(mMutex);
+ if (!mEasHandle) {
+ return ERROR_NOT_OPEN;
+ }
+ EAS_RESULT result;
+ if ((result = EAS_Prepare(mEasData, mEasHandle)) != EAS_SUCCESS) {
+ ALOGE("EAS_Prepare failed: [%ld]", result);
+ return ERROR_EAS_FAILURE;
+ }
+ updateState();
+ return NO_ERROR;
+}
+
+status_t MidiFile::prepareAsync()
+{
+ ALOGV("MidiFile::prepareAsync");
+ status_t ret = prepare();
+
+ // don't hold lock during callback
+ if (ret == NO_ERROR) {
+ sendEvent(MEDIA_PREPARED);
+ } else {
+ sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ret);
+ }
+ return ret;
+}
+
+status_t MidiFile::start()
+{
+ ALOGV("MidiFile::start");
+ Mutex::Autolock lock(mMutex);
+ if (!mEasHandle) {
+ return ERROR_NOT_OPEN;
+ }
+
+ // resuming after pause?
+ if (mPaused) {
+ if (EAS_Resume(mEasData, mEasHandle) != EAS_SUCCESS) {
+ return ERROR_EAS_FAILURE;
+ }
+ mPaused = false;
+ updateState();
+ }
+
+ mRender = true;
+
+ // wake up render thread
+ ALOGV(" wakeup render thread");
+ mCondition.signal();
+ return NO_ERROR;
+}
+
+status_t MidiFile::stop()
+{
+ ALOGV("MidiFile::stop");
+ Mutex::Autolock lock(mMutex);
+ if (!mEasHandle) {
+ return ERROR_NOT_OPEN;
+ }
+ if (!mPaused && (mState != EAS_STATE_STOPPED)) {
+ EAS_RESULT result = EAS_Pause(mEasData, mEasHandle);
+ if (result != EAS_SUCCESS) {
+ ALOGE("EAS_Pause returned error %ld", result);
+ return ERROR_EAS_FAILURE;
+ }
+ }
+ mPaused = false;
+ return NO_ERROR;
+}
+
+status_t MidiFile::seekTo(int position)
+{
+ ALOGV("MidiFile::seekTo %d", position);
+ // hold lock during EAS calls
+ {
+ Mutex::Autolock lock(mMutex);
+ if (!mEasHandle) {
+ return ERROR_NOT_OPEN;
+ }
+ EAS_RESULT result;
+ if ((result = EAS_Locate(mEasData, mEasHandle, position, false))
+ != EAS_SUCCESS)
+ {
+ ALOGE("EAS_Locate returned %ld", result);
+ return ERROR_EAS_FAILURE;
+ }
+ EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
+ }
+ sendEvent(MEDIA_SEEK_COMPLETE);
+ return NO_ERROR;
+}
+
+status_t MidiFile::pause()
+{
+ ALOGV("MidiFile::pause");
+ Mutex::Autolock lock(mMutex);
+ if (!mEasHandle) {
+ return ERROR_NOT_OPEN;
+ }
+ if ((mState == EAS_STATE_PAUSING) || (mState == EAS_STATE_PAUSED)) return NO_ERROR;
+ if (EAS_Pause(mEasData, mEasHandle) != EAS_SUCCESS) {
+ return ERROR_EAS_FAILURE;
+ }
+ mPaused = true;
+ return NO_ERROR;
+}
+
+bool MidiFile::isPlaying()
+{
+ ALOGV("MidiFile::isPlaying, mState=%d", int(mState));
+ if (!mEasHandle || mPaused) return false;
+ return (mState == EAS_STATE_PLAY);
+}
+
+status_t MidiFile::getCurrentPosition(int* position)
+{
+ ALOGV("MidiFile::getCurrentPosition");
+ if (!mEasHandle) {
+ ALOGE("getCurrentPosition(): file not open");
+ return ERROR_NOT_OPEN;
+ }
+ if (mPlayTime < 0) {
+ ALOGE("getCurrentPosition(): mPlayTime = %ld", mPlayTime);
+ return ERROR_EAS_FAILURE;
+ }
+ *position = mPlayTime;
+ return NO_ERROR;
+}
+
+status_t MidiFile::getDuration(int* duration)
+{
+
+ ALOGV("MidiFile::getDuration");
+ {
+ Mutex::Autolock lock(mMutex);
+ if (!mEasHandle) return ERROR_NOT_OPEN;
+ *duration = mDuration;
+ }
+
+ // if no duration cached, get the duration
+ // don't need a lock here because we spin up a new engine
+ if (*duration < 0) {
+ EAS_I32 temp;
+ EAS_DATA_HANDLE easData = NULL;
+ EAS_HANDLE easHandle = NULL;
+ EAS_RESULT result = EAS_Init(&easData);
+ if (result == EAS_SUCCESS) {
+ result = EAS_OpenFile(easData, &mFileLocator, &easHandle);
+ }
+ if (result == EAS_SUCCESS) {
+ result = EAS_Prepare(easData, easHandle);
+ }
+ if (result == EAS_SUCCESS) {
+ result = EAS_ParseMetaData(easData, easHandle, &temp);
+ }
+ if (easHandle) {
+ EAS_CloseFile(easData, easHandle);
+ }
+ if (easData) {
+ EAS_Shutdown(easData);
+ }
+
+ if (result != EAS_SUCCESS) {
+ return ERROR_EAS_FAILURE;
+ }
+
+ // cache successful result
+ mDuration = *duration = int(temp);
+ }
+
+ return NO_ERROR;
+}
+
+status_t MidiFile::release()
+{
+ ALOGV("MidiFile::release");
+ Mutex::Autolock l(mMutex);
+ reset_nosync();
+
+ // wait for render thread to exit
+ mExit = true;
+ mCondition.signal();
+
+ // wait for thread to exit
+ if (mAudioBuffer) {
+ mCondition.wait(mMutex);
+ }
+
+ // release resources
+ if (mEasData) {
+ EAS_Shutdown(mEasData);
+ mEasData = NULL;
+ }
+ return NO_ERROR;
+}
+
+status_t MidiFile::reset()
+{
+ ALOGV("MidiFile::reset");
+ Mutex::Autolock lock(mMutex);
+ return reset_nosync();
+}
+
+// call only with mutex held
+status_t MidiFile::reset_nosync()
+{
+ ALOGV("MidiFile::reset_nosync");
+ // close file
+ if (mEasHandle) {
+ EAS_CloseFile(mEasData, mEasHandle);
+ mEasHandle = NULL;
+ }
+ if (mFileLocator.path) {
+ free((void*)mFileLocator.path);
+ mFileLocator.path = NULL;
+ }
+ if (mFileLocator.fd >= 0) {
+ close(mFileLocator.fd);
+ }
+ mFileLocator.fd = -1;
+ mFileLocator.offset = 0;
+ mFileLocator.length = 0;
+
+ mPlayTime = -1;
+ mDuration = -1;
+ mLoop = false;
+ mPaused = false;
+ mRender = false;
+ return NO_ERROR;
+}
+
+status_t MidiFile::setLooping(int loop)
+{
+ ALOGV("MidiFile::setLooping");
+ Mutex::Autolock lock(mMutex);
+ if (!mEasHandle) {
+ return ERROR_NOT_OPEN;
+ }
+ loop = loop ? -1 : 0;
+ if (EAS_SetRepeat(mEasData, mEasHandle, loop) != EAS_SUCCESS) {
+ return ERROR_EAS_FAILURE;
+ }
+ return NO_ERROR;
+}
+
+status_t MidiFile::createOutputTrack() {
+ if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels,
+ CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT, 2) != NO_ERROR) {
+ ALOGE("mAudioSink open failed");
+ return ERROR_OPEN_FAILED;
+ }
+ return NO_ERROR;
+}
+
+int MidiFile::render() {
+ EAS_RESULT result = EAS_FAILURE;
+ EAS_I32 count;
+ int temp;
+ bool audioStarted = false;
+
+ ALOGV("MidiFile::render");
+
+ // allocate render buffer
+ mAudioBuffer = new EAS_PCM[pLibConfig->mixBufferSize * pLibConfig->numChannels * NUM_BUFFERS];
+ if (!mAudioBuffer) {
+ ALOGE("mAudioBuffer allocate failed");
+ goto threadExit;
+ }
+
+ // signal main thread that we started
+ {
+ Mutex::Autolock l(mMutex);
+ mTid = gettid();
+ ALOGV("render thread(%d) signal", mTid);
+ mCondition.signal();
+ }
+
+ while (1) {
+ mMutex.lock();
+
+ // nothing to render, wait for client thread to wake us up
+ while (!mRender && !mExit)
+ {
+ ALOGV("MidiFile::render - signal wait");
+ mCondition.wait(mMutex);
+ ALOGV("MidiFile::render - signal rx'd");
+ }
+ if (mExit) {
+ mMutex.unlock();
+ break;
+ }
+
+ // render midi data into the input buffer
+ //ALOGV("MidiFile::render - rendering audio");
+ int num_output = 0;
+ EAS_PCM* p = mAudioBuffer;
+ for (int i = 0; i < NUM_BUFFERS; i++) {
+ result = EAS_Render(mEasData, p, pLibConfig->mixBufferSize, &count);
+ if (result != EAS_SUCCESS) {
+ ALOGE("EAS_Render returned %ld", result);
+ }
+ p += count * pLibConfig->numChannels;
+ num_output += count * pLibConfig->numChannels * sizeof(EAS_PCM);
+ }
+
+ // update playback state and position
+ // ALOGV("MidiFile::render - updating state");
+ EAS_GetLocation(mEasData, mEasHandle, &mPlayTime);
+ EAS_State(mEasData, mEasHandle, &mState);
+ mMutex.unlock();
+
+ // create audio output track if necessary
+ if (!mAudioSink->ready()) {
+ ALOGV("MidiFile::render - create output track");
+ if (createOutputTrack() != NO_ERROR)
+ goto threadExit;
+ }
+
+ // Write data to the audio hardware
+ // ALOGV("MidiFile::render - writing to audio output");
+ if ((temp = mAudioSink->write(mAudioBuffer, num_output)) < 0) {
+ ALOGE("Error in writing:%d",temp);
+ return temp;
+ }
+
+ // start audio output if necessary
+ if (!audioStarted) {
+ //ALOGV("MidiFile::render - starting audio");
+ mAudioSink->start();
+ audioStarted = true;
+ }
+
+ // still playing?
+ if ((mState == EAS_STATE_STOPPED) || (mState == EAS_STATE_ERROR) ||
+ (mState == EAS_STATE_PAUSED))
+ {
+ switch(mState) {
+ case EAS_STATE_STOPPED:
+ {
+ ALOGV("MidiFile::render - stopped");
+ sendEvent(MEDIA_PLAYBACK_COMPLETE);
+ break;
+ }
+ case EAS_STATE_ERROR:
+ {
+ ALOGE("MidiFile::render - error");
+ sendEvent(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN);
+ break;
+ }
+ case EAS_STATE_PAUSED:
+ ALOGV("MidiFile::render - paused");
+ break;
+ default:
+ break;
+ }
+ mAudioSink->stop();
+ audioStarted = false;
+ mRender = false;
+ }
+ }
+
+threadExit:
+ mAudioSink.clear();
+ if (mAudioBuffer) {
+ delete [] mAudioBuffer;
+ mAudioBuffer = NULL;
+ }
+ mMutex.lock();
+ mTid = -1;
+ mCondition.signal();
+ mMutex.unlock();
+ return result;
+}
+
+} // end namespace android
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
new file mode 100644
index 0000000..f6f8f7b
--- /dev/null
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -0,0 +1,113 @@
+/*
+**
+** 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_MIDIFILE_H
+#define ANDROID_MIDIFILE_H
+
+#include <media/MediaPlayerInterface.h>
+#include <libsonivox/eas.h>
+
+namespace android {
+
+// Note that the name MidiFile is misleading; this actually represents a MIDI file player
+class MidiFile : public MediaPlayerInterface {
+public:
+ MidiFile();
+ ~MidiFile();
+
+ virtual status_t initCheck();
+
+ virtual status_t setDataSource(
+ const char* path, const KeyedVector<String8, String8> *headers);
+
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
+ virtual status_t setVideoSurfaceTexture(
+ const sp<ISurfaceTexture>& surfaceTexture)
+ { 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 SONIVOX_PLAYER; }
+ virtual status_t invoke(const Parcel& request, Parcel *reply) {
+ return INVALID_OPERATION;
+ }
+ virtual status_t setParameter(int key, const Parcel &request) {
+ return INVALID_OPERATION;
+ }
+ virtual status_t getParameter(int key, Parcel *reply) {
+ return INVALID_OPERATION;
+ }
+
+
+private:
+ status_t createOutputTrack();
+ status_t reset_nosync();
+ int render();
+ void updateState(){ EAS_State(mEasData, mEasHandle, &mState); }
+
+ Mutex mMutex;
+ Condition mCondition;
+ EAS_DATA_HANDLE mEasData;
+ EAS_HANDLE mEasHandle;
+ EAS_PCM* mAudioBuffer;
+ EAS_I32 mPlayTime;
+ EAS_I32 mDuration;
+ EAS_STATE mState;
+ EAS_FILE mFileLocator;
+ audio_stream_type_t mStreamType;
+ bool mLoop;
+ volatile bool mExit;
+ bool mPaused;
+ volatile bool mRender;
+ pid_t mTid;
+
+ class MidiFileThread : public Thread {
+ public:
+ MidiFileThread(MidiFile *midiPlayer) : mMidiFile(midiPlayer) {
+ }
+
+ protected:
+ virtual ~MidiFileThread() {}
+
+ private:
+ MidiFile *mMidiFile;
+
+ bool threadLoop() {
+ int result;
+ result = mMidiFile->render();
+ return false;
+ }
+
+ MidiFileThread(const MidiFileThread &);
+ MidiFileThread &operator=(const MidiFileThread &);
+ };
+
+ sp<MidiFileThread> mThread;
+};
+
+}; // namespace android
+
+#endif // ANDROID_MIDIFILE_H
diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.cpp b/media/libmediaplayerservice/MidiMetadataRetriever.cpp
new file mode 100644
index 0000000..465209f
--- /dev/null
+++ b/media/libmediaplayerservice/MidiMetadataRetriever.cpp
@@ -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.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MidiMetadataRetriever"
+#include <utils/Log.h>
+
+#include "MidiMetadataRetriever.h"
+#include <media/mediametadataretriever.h>
+
+namespace android {
+
+static status_t ERROR_NOT_OPEN = -1;
+static status_t ERROR_OPEN_FAILED = -2;
+static status_t ERROR_EAS_FAILURE = -3;
+static status_t ERROR_ALLOCATE_FAILED = -4;
+
+void MidiMetadataRetriever::clearMetadataValues()
+{
+ ALOGV("clearMetadataValues");
+ mMetadataValues[0][0] = '\0';
+}
+
+status_t MidiMetadataRetriever::setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers)
+{
+ ALOGV("setDataSource: %s", url? url: "NULL pointer");
+ Mutex::Autolock lock(mLock);
+ clearMetadataValues();
+ if (mMidiPlayer == 0) {
+ mMidiPlayer = new MidiFile();
+ }
+ return mMidiPlayer->setDataSource(url, headers);
+}
+
+status_t MidiMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
+{
+ ALOGV("setDataSource: fd(%d), offset(%lld), and length(%lld)", fd, offset, length);
+ Mutex::Autolock lock(mLock);
+ clearMetadataValues();
+ if (mMidiPlayer == 0) {
+ mMidiPlayer = new MidiFile();
+ }
+ return mMidiPlayer->setDataSource(fd, offset, length);;
+}
+
+const char* MidiMetadataRetriever::extractMetadata(int keyCode)
+{
+ ALOGV("extractMetdata: key(%d)", keyCode);
+ Mutex::Autolock lock(mLock);
+ if (mMidiPlayer == 0 || mMidiPlayer->initCheck() != NO_ERROR) {
+ ALOGE("Midi player is not initialized yet");
+ return NULL;
+ }
+ switch (keyCode) {
+ case METADATA_KEY_DURATION:
+ {
+ if (mMetadataValues[0][0] == '\0') {
+ int duration = -1;
+ if (mMidiPlayer->getDuration(&duration) != NO_ERROR) {
+ ALOGE("failed to get duration");
+ return NULL;
+ }
+ snprintf(mMetadataValues[0], MAX_METADATA_STRING_LENGTH, "%d", duration);
+ }
+
+ ALOGV("duration: %s ms", mMetadataValues[0]);
+ return mMetadataValues[0];
+ }
+ default:
+ ALOGE("Unsupported key code (%d)", keyCode);
+ return NULL;
+ }
+ return NULL;
+}
+
+};
+
diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.h b/media/libmediaplayerservice/MidiMetadataRetriever.h
new file mode 100644
index 0000000..4cee42d
--- /dev/null
+++ b/media/libmediaplayerservice/MidiMetadataRetriever.h
@@ -0,0 +1,51 @@
+/*
+**
+** 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_MIDIMETADATARETRIEVER_H
+#define ANDROID_MIDIMETADATARETRIEVER_H
+
+#include <utils/threads.h>
+#include <utils/Errors.h>
+#include <media/MediaMetadataRetrieverInterface.h>
+
+#include "MidiFile.h"
+
+namespace android {
+
+class MidiMetadataRetriever : public MediaMetadataRetrieverInterface {
+public:
+ MidiMetadataRetriever() {}
+ ~MidiMetadataRetriever() {}
+
+ virtual status_t setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers);
+
+ 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<MidiFile> mMidiPlayer;
+ char mMetadataValues[1][MAX_METADATA_STRING_LENGTH];
+};
+
+}; // namespace android
+
+#endif // ANDROID_MIDIMETADATARETRIEVER_H
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
new file mode 100644
index 0000000..619c149
--- /dev/null
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -0,0 +1,220 @@
+/*
+ * 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 "StagefrightPlayer"
+#include <utils/Log.h>
+
+#include "StagefrightPlayer.h"
+
+#include "AwesomePlayer.h"
+
+#include <media/Metadata.h>
+#include <media/stagefright/MediaExtractor.h>
+
+namespace android {
+
+StagefrightPlayer::StagefrightPlayer()
+ : mPlayer(new AwesomePlayer) {
+ ALOGV("StagefrightPlayer");
+
+ mPlayer->setListener(this);
+}
+
+StagefrightPlayer::~StagefrightPlayer() {
+ ALOGV("~StagefrightPlayer");
+ reset();
+
+ delete mPlayer;
+ mPlayer = NULL;
+}
+
+status_t StagefrightPlayer::initCheck() {
+ ALOGV("initCheck");
+ return OK;
+}
+
+status_t StagefrightPlayer::setUID(uid_t uid) {
+ mPlayer->setUID(uid);
+
+ return OK;
+}
+
+status_t StagefrightPlayer::setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers) {
+ return mPlayer->setDataSource(url, headers);
+}
+
+// Warning: The filedescriptor passed into this method will only be valid until
+// the method returns, if you want to keep it, dup it!
+status_t StagefrightPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
+ ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
+ return mPlayer->setDataSource(dup(fd), offset, length);
+}
+
+status_t StagefrightPlayer::setDataSource(const sp<IStreamSource> &source) {
+ return mPlayer->setDataSource(source);
+}
+
+status_t StagefrightPlayer::setVideoSurfaceTexture(
+ const sp<ISurfaceTexture> &surfaceTexture) {
+ ALOGV("setVideoSurfaceTexture");
+
+ return mPlayer->setSurfaceTexture(surfaceTexture);
+}
+
+status_t StagefrightPlayer::prepare() {
+ return mPlayer->prepare();
+}
+
+status_t StagefrightPlayer::prepareAsync() {
+ return mPlayer->prepareAsync();
+}
+
+status_t StagefrightPlayer::start() {
+ ALOGV("start");
+
+ return mPlayer->play();
+}
+
+status_t StagefrightPlayer::stop() {
+ ALOGV("stop");
+
+ return pause(); // what's the difference?
+}
+
+status_t StagefrightPlayer::pause() {
+ ALOGV("pause");
+
+ return mPlayer->pause();
+}
+
+bool StagefrightPlayer::isPlaying() {
+ ALOGV("isPlaying");
+ return mPlayer->isPlaying();
+}
+
+status_t StagefrightPlayer::seekTo(int msec) {
+ ALOGV("seekTo %.2f secs", msec / 1E3);
+
+ status_t err = mPlayer->seekTo((int64_t)msec * 1000);
+
+ return err;
+}
+
+status_t StagefrightPlayer::getCurrentPosition(int *msec) {
+ ALOGV("getCurrentPosition");
+
+ int64_t positionUs;
+ status_t err = mPlayer->getPosition(&positionUs);
+
+ if (err != OK) {
+ return err;
+ }
+
+ *msec = (positionUs + 500) / 1000;
+
+ return OK;
+}
+
+status_t StagefrightPlayer::getDuration(int *msec) {
+ ALOGV("getDuration");
+
+ int64_t durationUs;
+ status_t err = mPlayer->getDuration(&durationUs);
+
+ if (err != OK) {
+ *msec = 0;
+ return OK;
+ }
+
+ *msec = (durationUs + 500) / 1000;
+
+ return OK;
+}
+
+status_t StagefrightPlayer::reset() {
+ ALOGV("reset");
+
+ mPlayer->reset();
+
+ return OK;
+}
+
+status_t StagefrightPlayer::setLooping(int loop) {
+ ALOGV("setLooping");
+
+ return mPlayer->setLooping(loop);
+}
+
+player_type StagefrightPlayer::playerType() {
+ ALOGV("playerType");
+ return STAGEFRIGHT_PLAYER;
+}
+
+status_t StagefrightPlayer::invoke(const Parcel &request, Parcel *reply) {
+ ALOGV("invoke()");
+ return mPlayer->invoke(request, reply);
+}
+
+void StagefrightPlayer::setAudioSink(const sp<AudioSink> &audioSink) {
+ MediaPlayerInterface::setAudioSink(audioSink);
+
+ mPlayer->setAudioSink(audioSink);
+}
+
+status_t StagefrightPlayer::setParameter(int key, const Parcel &request) {
+ ALOGV("setParameter(key=%d)", key);
+ return mPlayer->setParameter(key, request);
+}
+
+status_t StagefrightPlayer::getParameter(int key, Parcel *reply) {
+ ALOGV("getParameter");
+ return mPlayer->getParameter(key, reply);
+}
+
+status_t StagefrightPlayer::getMetadata(
+ const media::Metadata::Filter& ids, Parcel *records) {
+ using media::Metadata;
+
+ uint32_t flags = mPlayer->flags();
+
+ Metadata metadata(records);
+
+ metadata.appendBool(
+ Metadata::kPauseAvailable,
+ flags & MediaExtractor::CAN_PAUSE);
+
+ metadata.appendBool(
+ Metadata::kSeekBackwardAvailable,
+ flags & MediaExtractor::CAN_SEEK_BACKWARD);
+
+ metadata.appendBool(
+ Metadata::kSeekForwardAvailable,
+ flags & MediaExtractor::CAN_SEEK_FORWARD);
+
+ metadata.appendBool(
+ Metadata::kSeekAvailable,
+ flags & MediaExtractor::CAN_SEEK);
+
+ return OK;
+}
+
+status_t StagefrightPlayer::dump(int fd, const Vector<String16> &args) const {
+ return mPlayer->dump(fd, args);
+}
+
+} // namespace android
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
new file mode 100644
index 0000000..e89e18a
--- /dev/null
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -0,0 +1,76 @@
+/*
+**
+** 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_STAGEFRIGHTPLAYER_H
+#define ANDROID_STAGEFRIGHTPLAYER_H
+
+#include <media/MediaPlayerInterface.h>
+
+namespace android {
+
+struct AwesomePlayer;
+
+class StagefrightPlayer : public MediaPlayerInterface {
+public:
+ StagefrightPlayer();
+ virtual ~StagefrightPlayer();
+
+ virtual status_t initCheck();
+
+ virtual status_t setUID(uid_t uid);
+
+ virtual status_t setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers);
+
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
+
+ virtual status_t setDataSource(const sp<IStreamSource> &source);
+
+ virtual status_t setVideoSurfaceTexture(
+ const sp<ISurfaceTexture> &surfaceTexture);
+ virtual status_t prepare();
+ virtual status_t prepareAsync();
+ virtual status_t start();
+ virtual status_t stop();
+ virtual status_t pause();
+ virtual bool isPlaying();
+ virtual status_t seekTo(int msec);
+ virtual status_t getCurrentPosition(int *msec);
+ virtual status_t getDuration(int *msec);
+ virtual status_t reset();
+ virtual status_t setLooping(int loop);
+ virtual player_type playerType();
+ virtual status_t invoke(const Parcel &request, Parcel *reply);
+ virtual void setAudioSink(const sp<AudioSink> &audioSink);
+ virtual status_t setParameter(int key, const Parcel &request);
+ virtual status_t getParameter(int key, Parcel *reply);
+
+ virtual status_t getMetadata(
+ const media::Metadata::Filter& ids, Parcel *records);
+
+ virtual status_t dump(int fd, const Vector<String16> &args) const;
+
+private:
+ AwesomePlayer *mPlayer;
+
+ StagefrightPlayer(const StagefrightPlayer &);
+ StagefrightPlayer &operator=(const StagefrightPlayer &);
+};
+
+} // namespace android
+
+#endif // ANDROID_STAGEFRIGHTPLAYER_H
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
new file mode 100644
index 0000000..ca79657
--- /dev/null
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -0,0 +1,1755 @@
+/*
+ * 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 "StagefrightRecorder"
+#include <utils/Log.h>
+
+#include "StagefrightRecorder.h"
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+
+#include <media/IMediaPlayerService.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/AudioSource.h>
+#include <media/stagefright/AMRWriter.h>
+#include <media/stagefright/AACWriter.h>
+#include <media/stagefright/CameraSource.h>
+#include <media/stagefright/CameraSourceTimeLapse.h>
+#include <media/stagefright/MPEG2TSWriter.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/SurfaceMediaSource.h>
+#include <media/MediaProfiles.h>
+#include <camera/ICamera.h>
+#include <camera/CameraParameters.h>
+#include <gui/Surface.h>
+
+#include <utils/Errors.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include <system/audio.h>
+
+#include "ARTPWriter.h"
+
+namespace android {
+
+// To collect the encoder usage for the battery app
+static void addBatteryData(uint32_t params) {
+ sp<IBinder> binder =
+ defaultServiceManager()->getService(String16("media.player"));
+ sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+ CHECK(service.get() != NULL);
+
+ service->addBatteryData(params);
+}
+
+
+StagefrightRecorder::StagefrightRecorder()
+ : mWriter(NULL),
+ mOutputFd(-1),
+ mAudioSource(AUDIO_SOURCE_CNT),
+ mVideoSource(VIDEO_SOURCE_LIST_END),
+ mStarted(false), mSurfaceMediaSource(NULL) {
+
+ ALOGV("Constructor");
+ reset();
+}
+
+StagefrightRecorder::~StagefrightRecorder() {
+ ALOGV("Destructor");
+ stop();
+}
+
+status_t StagefrightRecorder::init() {
+ ALOGV("init");
+ return OK;
+}
+
+// The client side of mediaserver asks it to creat a SurfaceMediaSource
+// and return a interface reference. The client side will use that
+// while encoding GL Frames
+sp<ISurfaceTexture> StagefrightRecorder::querySurfaceMediaSource() const {
+ ALOGV("Get SurfaceMediaSource");
+ return mSurfaceMediaSource;
+}
+
+status_t StagefrightRecorder::setAudioSource(audio_source_t as) {
+ ALOGV("setAudioSource: %d", as);
+ if (as < AUDIO_SOURCE_DEFAULT ||
+ as >= AUDIO_SOURCE_CNT) {
+ ALOGE("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) {
+ ALOGV("setVideoSource: %d", vs);
+ if (vs < VIDEO_SOURCE_DEFAULT ||
+ vs >= VIDEO_SOURCE_LIST_END) {
+ ALOGE("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) {
+ ALOGV("setOutputFormat: %d", of);
+ if (of < OUTPUT_FORMAT_DEFAULT ||
+ of >= OUTPUT_FORMAT_LIST_END) {
+ ALOGE("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) {
+ ALOGV("setAudioEncoder: %d", ae);
+ if (ae < AUDIO_ENCODER_DEFAULT ||
+ ae >= AUDIO_ENCODER_LIST_END) {
+ ALOGE("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) {
+ ALOGV("setVideoEncoder: %d", ve);
+ if (ve < VIDEO_ENCODER_DEFAULT ||
+ ve >= VIDEO_ENCODER_LIST_END) {
+ ALOGE("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) {
+ ALOGV("setVideoSize: %dx%d", width, height);
+ if (width <= 0 || height <= 0) {
+ ALOGE("Invalid video size: %dx%d", width, height);
+ return BAD_VALUE;
+ }
+
+ // Additional check on the dimension will be performed later
+ mVideoWidth = width;
+ mVideoHeight = height;
+
+ return OK;
+}
+
+status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
+ ALOGV("setVideoFrameRate: %d", frames_per_second);
+ if ((frames_per_second <= 0 && frames_per_second != -1) ||
+ frames_per_second > 120) {
+ ALOGE("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,
+ const sp<ICameraRecordingProxy> &proxy) {
+ ALOGV("setCamera");
+ if (camera == 0) {
+ ALOGE("camera is NULL");
+ return BAD_VALUE;
+ }
+ if (proxy == 0) {
+ ALOGE("camera proxy is NULL");
+ return BAD_VALUE;
+ }
+
+ mCamera = camera;
+ mCameraProxy = proxy;
+ return OK;
+}
+
+status_t StagefrightRecorder::setPreviewSurface(const sp<Surface> &surface) {
+ ALOGV("setPreviewSurface: %p", surface.get());
+ mPreviewSurface = surface;
+
+ return OK;
+}
+
+status_t StagefrightRecorder::setOutputFile(const char *path) {
+ ALOGE("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 -EPERM;
+}
+
+status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) {
+ ALOGV("setOutputFile: %d, %lld, %lld", fd, offset, length);
+ // These don't make any sense, do they?
+ CHECK_EQ(offset, 0ll);
+ CHECK_EQ(length, 0ll);
+
+ if (fd < 0) {
+ ALOGE("Invalid file descriptor: %d", fd);
+ return -EBADF;
+ }
+
+ if (mOutputFd >= 0) {
+ ::close(mOutputFd);
+ }
+ mOutputFd = dup(fd);
+
+ return OK;
+}
+
+// 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;
+
+ // It is lame, but according to man page, we have to set errno to 0
+ // before calling strtoll().
+ errno = 0;
+ *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) {
+ ALOGV("setParamAudioSamplingRate: %d", sampleRate);
+ if (sampleRate <= 0) {
+ ALOGE("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) {
+ ALOGV("setParamAudioNumberOfChannels: %d", channels);
+ if (channels <= 0 || channels >= 3) {
+ ALOGE("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) {
+ ALOGV("setParamAudioEncodingBitRate: %d", bitRate);
+ if (bitRate <= 0) {
+ ALOGE("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) {
+ ALOGV("setParamVideoEncodingBitRate: %d", bitRate);
+ if (bitRate <= 0) {
+ ALOGE("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;
+}
+
+// Always rotate clockwise, and only support 0, 90, 180 and 270 for now.
+status_t StagefrightRecorder::setParamVideoRotation(int32_t degrees) {
+ ALOGV("setParamVideoRotation: %d", degrees);
+ if (degrees < 0 || degrees % 90 != 0) {
+ ALOGE("Unsupported video rotation angle: %d", degrees);
+ return BAD_VALUE;
+ }
+ mRotationDegrees = degrees % 360;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
+ ALOGV("setParamMaxFileDurationUs: %lld us", timeUs);
+
+ // This is meant for backward compatibility for MediaRecorder.java
+ if (timeUs <= 0) {
+ ALOGW("Max file duration is not positive: %lld us. Disabling duration limit.", timeUs);
+ timeUs = 0; // Disable the duration limit for zero or negative values.
+ } else if (timeUs <= 100000LL) { // XXX: 100 milli-seconds
+ ALOGE("Max file duration is too short: %lld us", timeUs);
+ return BAD_VALUE;
+ }
+
+ if (timeUs <= 15 * 1000000LL) {
+ ALOGW("Target duration (%lld us) too short to be respected", timeUs);
+ }
+ mMaxFileDurationUs = timeUs;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
+ ALOGV("setParamMaxFileSizeBytes: %lld bytes", bytes);
+
+ // This is meant for backward compatibility for MediaRecorder.java
+ if (bytes <= 0) {
+ ALOGW("Max file size is not positive: %lld bytes. "
+ "Disabling file size limit.", bytes);
+ bytes = 0; // Disable the file size limit for zero or negative values.
+ } else if (bytes <= 1024) { // XXX: 1 kB
+ ALOGE("Max file size is too small: %lld bytes", bytes);
+ return BAD_VALUE;
+ }
+
+ if (bytes <= 100 * 1024) {
+ ALOGW("Target file size (%lld bytes) is too small to be respected", bytes);
+ }
+
+ mMaxFileSizeBytes = bytes;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) {
+ ALOGV("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
+ ALOGE("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
+ ALOGE("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) {
+ ALOGV("setParamVideoIFramesInterval: %d seconds", seconds);
+ mIFramesIntervalSec = seconds;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit) {
+ ALOGV("setParam64BitFileOffset: %s",
+ use64Bit? "use 64 bit file offset": "use 32 bit file offset");
+ mUse64BitFileOffset = use64Bit;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) {
+ ALOGV("setParamVideoCameraId: %d", cameraId);
+ if (cameraId < 0) {
+ return BAD_VALUE;
+ }
+ mCameraId = cameraId;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) {
+ ALOGV("setParamTrackTimeStatus: %lld", timeDurationUs);
+ if (timeDurationUs < 20000) { // Infeasible if shorter than 20 ms?
+ ALOGE("Tracking time duration too short: %lld us", timeDurationUs);
+ return BAD_VALUE;
+ }
+ mTrackEveryTimeDurationUs = timeDurationUs;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoEncoderProfile(int32_t profile) {
+ ALOGV("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) {
+ ALOGV("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) {
+ ALOGV("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) {
+ ALOGE("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) {
+ ALOGV("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) {
+ ALOGE("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) {
+ ALOGV("setParamAudioTimeScale: %d", timeScale);
+
+ // 96000 Hz is the highest sampling rate support in AAC.
+ if (timeScale < 600 || timeScale > 96000) {
+ ALOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale);
+ return BAD_VALUE;
+ }
+ mAudioTimeScale = timeScale;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamTimeLapseEnable(int32_t timeLapseEnable) {
+ ALOGV("setParamTimeLapseEnable: %d", timeLapseEnable);
+
+ if(timeLapseEnable == 0) {
+ mCaptureTimeLapse = false;
+ } else if (timeLapseEnable == 1) {
+ mCaptureTimeLapse = true;
+ } else {
+ return BAD_VALUE;
+ }
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs) {
+ ALOGV("setParamTimeBetweenTimeLapseFrameCapture: %lld us", timeUs);
+
+ // Not allowing time more than a day
+ if (timeUs <= 0 || timeUs > 86400*1E6) {
+ ALOGE("Time between time lapse frame capture (%lld) is out of range [0, 1 Day]", timeUs);
+ return BAD_VALUE;
+ }
+
+ mTimeBetweenTimeLapseFrameCaptureUs = timeUs;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamGeoDataLongitude(
+ int64_t longitudex10000) {
+
+ if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
+ return BAD_VALUE;
+ }
+ mLongitudex10000 = longitudex10000;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamGeoDataLatitude(
+ int64_t latitudex10000) {
+
+ if (latitudex10000 > 900000 || latitudex10000 < -900000) {
+ return BAD_VALUE;
+ }
+ mLatitudex10000 = latitudex10000;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParameter(
+ const String8 &key, const String8 &value) {
+ ALOGV("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-geotag-longitude") {
+ int64_t longitudex10000;
+ if (safe_strtoi64(value.string(), &longitudex10000)) {
+ return setParamGeoDataLongitude(longitudex10000);
+ }
+ } else if (key == "param-geotag-latitude") {
+ int64_t latitudex10000;
+ if (safe_strtoi64(value.string(), &latitudex10000)) {
+ return setParamGeoDataLatitude(latitudex10000);
+ }
+ } 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-rotation-angle-degrees") {
+ int32_t degrees;
+ if (safe_strtoi32(value.string(), &degrees)) {
+ return setParamVideoRotation(degrees);
+ }
+ } 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 if (key == "time-lapse-enable") {
+ int32_t timeLapseEnable;
+ if (safe_strtoi32(value.string(), &timeLapseEnable)) {
+ return setParamTimeLapseEnable(timeLapseEnable);
+ }
+ } else if (key == "time-between-time-lapse-frame-capture") {
+ int64_t timeBetweenTimeLapseFrameCaptureMs;
+ if (safe_strtoi64(value.string(), &timeBetweenTimeLapseFrameCaptureMs)) {
+ return setParamTimeBetweenTimeLapseFrameCapture(
+ 1000LL * timeBetweenTimeLapseFrameCaptureMs);
+ }
+ } else {
+ ALOGE("setParameter: failed to find key %s", key.string());
+ }
+ return BAD_VALUE;
+}
+
+status_t StagefrightRecorder::setParameters(const String8 &params) {
+ ALOGV("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) {
+ ALOGE("Parameters %s miss a value", cparams);
+ return BAD_VALUE;
+ }
+ String8 key(key_start, equal_pos - key_start);
+ TrimString(&key);
+ if (key.length() == 0) {
+ ALOGE("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;
+}
+
+status_t StagefrightRecorder::prepare() {
+ return OK;
+}
+
+status_t StagefrightRecorder::start() {
+ CHECK_GE(mOutputFd, 0);
+
+ if (mWriter != NULL) {
+ ALOGE("File writer is not avaialble");
+ return UNKNOWN_ERROR;
+ }
+
+ status_t status = OK;
+
+ switch (mOutputFormat) {
+ case OUTPUT_FORMAT_DEFAULT:
+ case OUTPUT_FORMAT_THREE_GPP:
+ case OUTPUT_FORMAT_MPEG_4:
+ status = startMPEG4Recording();
+ break;
+
+ case OUTPUT_FORMAT_AMR_NB:
+ case OUTPUT_FORMAT_AMR_WB:
+ status = startAMRRecording();
+ break;
+
+ case OUTPUT_FORMAT_AAC_ADIF:
+ case OUTPUT_FORMAT_AAC_ADTS:
+ status = startAACRecording();
+ break;
+
+ case OUTPUT_FORMAT_RTP_AVP:
+ status = startRTPRecording();
+ break;
+
+ case OUTPUT_FORMAT_MPEG2TS:
+ status = startMPEG2TSRecording();
+ break;
+
+ default:
+ ALOGE("Unsupported output file format: %d", mOutputFormat);
+ status = UNKNOWN_ERROR;
+ break;
+ }
+
+ if ((status == OK) && (!mStarted)) {
+ mStarted = true;
+
+ uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted;
+ if (mAudioSource != AUDIO_SOURCE_CNT) {
+ params |= IMediaPlayerService::kBatteryDataTrackAudio;
+ }
+ if (mVideoSource != VIDEO_SOURCE_LIST_END) {
+ params |= IMediaPlayerService::kBatteryDataTrackVideo;
+ }
+
+ addBatteryData(params);
+ }
+
+ return status;
+}
+
+sp<MediaSource> StagefrightRecorder::createAudioSource() {
+ sp<AudioSource> audioSource =
+ new AudioSource(
+ mAudioSource,
+ mSampleRate,
+ mAudioChannels);
+
+ status_t err = audioSource->initCheck();
+
+ if (err != OK) {
+ ALOGE("audio source is not initialized");
+ return NULL;
+ }
+
+ sp<MetaData> encMeta = new MetaData;
+ 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:
+ ALOGE("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, mAudioChannels);
+ encMeta->setInt32(kKeySampleRate, mSampleRate);
+ encMeta->setInt32(kKeyBitRate, mAudioBitRate);
+ if (mAudioTimeScale > 0) {
+ encMeta->setInt32(kKeyTimeScale, mAudioTimeScale);
+ }
+
+ OMXClient client;
+ CHECK_EQ(client.connect(), (status_t)OK);
+
+ sp<MediaSource> audioEncoder =
+ OMXCodec::Create(client.interface(), encMeta,
+ true /* createEncoder */, audioSource);
+ mAudioSourceNode = audioSource;
+
+ return audioEncoder;
+}
+
+status_t StagefrightRecorder::startAACRecording() {
+ // FIXME:
+ // Add support for OUTPUT_FORMAT_AAC_ADIF
+ CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_AAC_ADTS);
+
+ CHECK_EQ(mAudioEncoder, AUDIO_ENCODER_AAC);
+ CHECK(mAudioSource != AUDIO_SOURCE_CNT);
+
+ mWriter = new AACWriter(mOutputFd);
+ status_t status = startRawAudioRecording();
+ if (status != OK) {
+ mWriter.clear();
+ mWriter = NULL;
+ }
+
+ return status;
+}
+
+status_t StagefrightRecorder::startAMRRecording() {
+ 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) {
+ ALOGE("Invalid encoder %d used for AMRNB recording",
+ mAudioEncoder);
+ return BAD_VALUE;
+ }
+ } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
+ if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
+ ALOGE("Invlaid encoder %d used for AMRWB recording",
+ mAudioEncoder);
+ return BAD_VALUE;
+ }
+ }
+
+ mWriter = new AMRWriter(mOutputFd);
+ status_t status = startRawAudioRecording();
+ if (status != OK) {
+ mWriter.clear();
+ mWriter = NULL;
+ }
+ return status;
+}
+
+status_t StagefrightRecorder::startRawAudioRecording() {
+ if (mAudioSource >= AUDIO_SOURCE_CNT) {
+ ALOGE("Invalid audio source: %d", mAudioSource);
+ return BAD_VALUE;
+ }
+
+ status_t status = BAD_VALUE;
+ if (OK != (status = checkAudioEncoderCapabilities())) {
+ return status;
+ }
+
+ sp<MediaSource> audioEncoder = createAudioSource();
+ if (audioEncoder == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ CHECK(mWriter != 0);
+ 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::startRTPRecording() {
+ CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_RTP_AVP);
+
+ if ((mAudioSource != AUDIO_SOURCE_CNT
+ && mVideoSource != VIDEO_SOURCE_LIST_END)
+ || (mAudioSource == AUDIO_SOURCE_CNT
+ && mVideoSource == VIDEO_SOURCE_LIST_END)) {
+ // Must have exactly one source.
+ return BAD_VALUE;
+ }
+
+ if (mOutputFd < 0) {
+ return BAD_VALUE;
+ }
+
+ sp<MediaSource> source;
+
+ if (mAudioSource != AUDIO_SOURCE_CNT) {
+ source = createAudioSource();
+ } else {
+
+ sp<MediaSource> mediaSource;
+ status_t err = setupMediaSource(&mediaSource);
+ if (err != OK) {
+ return err;
+ }
+
+ err = setupVideoEncoder(mediaSource, mVideoBitRate, &source);
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ mWriter = new ARTPWriter(mOutputFd);
+ mWriter->addSource(source);
+ mWriter->setListener(mListener);
+
+ return mWriter->start();
+}
+
+status_t StagefrightRecorder::startMPEG2TSRecording() {
+ CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_MPEG2TS);
+
+ sp<MediaWriter> writer = new MPEG2TSWriter(mOutputFd);
+
+ if (mAudioSource != AUDIO_SOURCE_CNT) {
+ if (mAudioEncoder != AUDIO_ENCODER_AAC) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ status_t err = setupAudioEncoder(writer);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ if (mVideoSource < VIDEO_SOURCE_LIST_END) {
+ if (mVideoEncoder != VIDEO_ENCODER_H264) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ sp<MediaSource> mediaSource;
+ status_t err = setupMediaSource(&mediaSource);
+ if (err != OK) {
+ return err;
+ }
+
+ sp<MediaSource> encoder;
+ err = setupVideoEncoder(mediaSource, mVideoBitRate, &encoder);
+
+ if (err != OK) {
+ return err;
+ }
+
+ writer->addSource(encoder);
+ }
+
+ if (mMaxFileDurationUs != 0) {
+ writer->setMaxFileDuration(mMaxFileDurationUs);
+ }
+
+ if (mMaxFileSizeBytes != 0) {
+ writer->setMaxFileSize(mMaxFileSizeBytes);
+ }
+
+ mWriter = writer;
+
+ return mWriter->start();
+}
+
+void StagefrightRecorder::clipVideoFrameRate() {
+ ALOGV("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 && mFrameRate != -1) {
+ ALOGW("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) {
+ ALOGW("Intended video encoding frame rate (%d fps) is too large"
+ " and will be set to (%d fps)", mFrameRate, maxFrameRate);
+ mFrameRate = maxFrameRate;
+ }
+}
+
+void StagefrightRecorder::clipVideoBitRate() {
+ ALOGV("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) {
+ ALOGW("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) {
+ ALOGW("Intended video encoding bit rate (%d bps) is too large"
+ " and will be set to (%d bps)", mVideoBitRate, maxBitRate);
+ mVideoBitRate = maxBitRate;
+ }
+}
+
+void StagefrightRecorder::clipVideoFrameWidth() {
+ ALOGV("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) {
+ ALOGW("Intended video encoding frame width (%d) is too small"
+ " and will be set to (%d)", mVideoWidth, minFrameWidth);
+ mVideoWidth = minFrameWidth;
+ } else if (mVideoWidth > maxFrameWidth) {
+ ALOGW("Intended video encoding frame width (%d) is too large"
+ " and will be set to (%d)", mVideoWidth, maxFrameWidth);
+ mVideoWidth = maxFrameWidth;
+ }
+}
+
+status_t StagefrightRecorder::checkVideoEncoderCapabilities() {
+ if (!mCaptureTimeLapse) {
+ // Dont clip for time lapse capture as encoder will have enough
+ // time to encode because of slow capture rate of time lapse.
+ clipVideoBitRate();
+ clipVideoFrameRate();
+ clipVideoFrameWidth();
+ clipVideoFrameHeight();
+ setDefaultProfileIfNecessary();
+ }
+ return OK;
+}
+
+// Set to use AVC baseline profile if the encoding parameters matches
+// CAMCORDER_QUALITY_LOW profile; this is for the sake of MMS service.
+void StagefrightRecorder::setDefaultProfileIfNecessary() {
+ ALOGV("setDefaultProfileIfNecessary");
+
+ camcorder_quality quality = CAMCORDER_QUALITY_LOW;
+
+ int64_t durationUs = mEncoderProfiles->getCamcorderProfileParamByName(
+ "duration", mCameraId, quality) * 1000000LL;
+
+ int fileFormat = mEncoderProfiles->getCamcorderProfileParamByName(
+ "file.format", mCameraId, quality);
+
+ int videoCodec = mEncoderProfiles->getCamcorderProfileParamByName(
+ "vid.codec", mCameraId, quality);
+
+ int videoBitRate = mEncoderProfiles->getCamcorderProfileParamByName(
+ "vid.bps", mCameraId, quality);
+
+ int videoFrameRate = mEncoderProfiles->getCamcorderProfileParamByName(
+ "vid.fps", mCameraId, quality);
+
+ int videoFrameWidth = mEncoderProfiles->getCamcorderProfileParamByName(
+ "vid.width", mCameraId, quality);
+
+ int videoFrameHeight = mEncoderProfiles->getCamcorderProfileParamByName(
+ "vid.height", mCameraId, quality);
+
+ int audioCodec = mEncoderProfiles->getCamcorderProfileParamByName(
+ "aud.codec", mCameraId, quality);
+
+ int audioBitRate = mEncoderProfiles->getCamcorderProfileParamByName(
+ "aud.bps", mCameraId, quality);
+
+ int audioSampleRate = mEncoderProfiles->getCamcorderProfileParamByName(
+ "aud.hz", mCameraId, quality);
+
+ int audioChannels = mEncoderProfiles->getCamcorderProfileParamByName(
+ "aud.ch", mCameraId, quality);
+
+ if (durationUs == mMaxFileDurationUs &&
+ fileFormat == mOutputFormat &&
+ videoCodec == mVideoEncoder &&
+ videoBitRate == mVideoBitRate &&
+ videoFrameRate == mFrameRate &&
+ videoFrameWidth == mVideoWidth &&
+ videoFrameHeight == mVideoHeight &&
+ audioCodec == mAudioEncoder &&
+ audioBitRate == mAudioBitRate &&
+ audioSampleRate == mSampleRate &&
+ audioChannels == mAudioChannels) {
+ if (videoCodec == VIDEO_ENCODER_H264) {
+ ALOGI("Force to use AVC baseline profile");
+ setParamVideoEncoderProfile(OMX_VIDEO_AVCProfileBaseline);
+ }
+ }
+}
+
+status_t StagefrightRecorder::checkAudioEncoderCapabilities() {
+ clipAudioBitRate();
+ clipAudioSampleRate();
+ clipNumberOfAudioChannels();
+ return OK;
+}
+
+void StagefrightRecorder::clipAudioBitRate() {
+ ALOGV("clipAudioBitRate: encoder %d", mAudioEncoder);
+
+ int minAudioBitRate =
+ mEncoderProfiles->getAudioEncoderParamByName(
+ "enc.aud.bps.min", mAudioEncoder);
+ if (mAudioBitRate < minAudioBitRate) {
+ ALOGW("Intended audio encoding bit rate (%d) is too small"
+ " and will be set to (%d)", mAudioBitRate, minAudioBitRate);
+ mAudioBitRate = minAudioBitRate;
+ }
+
+ int maxAudioBitRate =
+ mEncoderProfiles->getAudioEncoderParamByName(
+ "enc.aud.bps.max", mAudioEncoder);
+ if (mAudioBitRate > maxAudioBitRate) {
+ ALOGW("Intended audio encoding bit rate (%d) is too large"
+ " and will be set to (%d)", mAudioBitRate, maxAudioBitRate);
+ mAudioBitRate = maxAudioBitRate;
+ }
+}
+
+void StagefrightRecorder::clipAudioSampleRate() {
+ ALOGV("clipAudioSampleRate: encoder %d", mAudioEncoder);
+
+ int minSampleRate =
+ mEncoderProfiles->getAudioEncoderParamByName(
+ "enc.aud.hz.min", mAudioEncoder);
+ if (mSampleRate < minSampleRate) {
+ ALOGW("Intended audio sample rate (%d) is too small"
+ " and will be set to (%d)", mSampleRate, minSampleRate);
+ mSampleRate = minSampleRate;
+ }
+
+ int maxSampleRate =
+ mEncoderProfiles->getAudioEncoderParamByName(
+ "enc.aud.hz.max", mAudioEncoder);
+ if (mSampleRate > maxSampleRate) {
+ ALOGW("Intended audio sample rate (%d) is too large"
+ " and will be set to (%d)", mSampleRate, maxSampleRate);
+ mSampleRate = maxSampleRate;
+ }
+}
+
+void StagefrightRecorder::clipNumberOfAudioChannels() {
+ ALOGV("clipNumberOfAudioChannels: encoder %d", mAudioEncoder);
+
+ int minChannels =
+ mEncoderProfiles->getAudioEncoderParamByName(
+ "enc.aud.ch.min", mAudioEncoder);
+ if (mAudioChannels < minChannels) {
+ ALOGW("Intended number of audio channels (%d) is too small"
+ " and will be set to (%d)", mAudioChannels, minChannels);
+ mAudioChannels = minChannels;
+ }
+
+ int maxChannels =
+ mEncoderProfiles->getAudioEncoderParamByName(
+ "enc.aud.ch.max", mAudioEncoder);
+ if (mAudioChannels > maxChannels) {
+ ALOGW("Intended number of audio channels (%d) is too large"
+ " and will be set to (%d)", mAudioChannels, maxChannels);
+ mAudioChannels = maxChannels;
+ }
+}
+
+void StagefrightRecorder::clipVideoFrameHeight() {
+ ALOGV("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) {
+ ALOGW("Intended video encoding frame height (%d) is too small"
+ " and will be set to (%d)", mVideoHeight, minFrameHeight);
+ mVideoHeight = minFrameHeight;
+ } else if (mVideoHeight > maxFrameHeight) {
+ ALOGW("Intended video encoding frame height (%d) is too large"
+ " and will be set to (%d)", mVideoHeight, maxFrameHeight);
+ mVideoHeight = maxFrameHeight;
+ }
+}
+
+// Set up the appropriate MediaSource depending on the chosen option
+status_t StagefrightRecorder::setupMediaSource(
+ sp<MediaSource> *mediaSource) {
+ if (mVideoSource == VIDEO_SOURCE_DEFAULT
+ || mVideoSource == VIDEO_SOURCE_CAMERA) {
+ sp<CameraSource> cameraSource;
+ status_t err = setupCameraSource(&cameraSource);
+ if (err != OK) {
+ return err;
+ }
+ *mediaSource = cameraSource;
+ } else if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) {
+ // If using GRAlloc buffers, setup surfacemediasource.
+ // Later a handle to that will be passed
+ // to the client side when queried
+ status_t err = setupSurfaceMediaSource();
+ if (err != OK) {
+ return err;
+ }
+ *mediaSource = mSurfaceMediaSource;
+ } else {
+ return INVALID_OPERATION;
+ }
+ return OK;
+}
+
+// setupSurfaceMediaSource creates a source with the given
+// width and height and framerate.
+// TODO: This could go in a static function inside SurfaceMediaSource
+// similar to that in CameraSource
+status_t StagefrightRecorder::setupSurfaceMediaSource() {
+ status_t err = OK;
+ mSurfaceMediaSource = new SurfaceMediaSource(mVideoWidth, mVideoHeight);
+ if (mSurfaceMediaSource == NULL) {
+ return NO_INIT;
+ }
+
+ if (mFrameRate == -1) {
+ int32_t frameRate = 0;
+ CHECK (mSurfaceMediaSource->getFormat()->findInt32(
+ kKeyFrameRate, &frameRate));
+ ALOGI("Frame rate is not explicitly set. Use the current frame "
+ "rate (%d fps)", frameRate);
+ mFrameRate = frameRate;
+ } else {
+ err = mSurfaceMediaSource->setFrameRate(mFrameRate);
+ }
+ CHECK(mFrameRate != -1);
+
+ mIsMetaDataStoredInVideoBuffers =
+ mSurfaceMediaSource->isMetaDataStoredInVideoBuffers();
+ return err;
+}
+
+status_t StagefrightRecorder::setupCameraSource(
+ sp<CameraSource> *cameraSource) {
+ status_t err = OK;
+ if ((err = checkVideoEncoderCapabilities()) != OK) {
+ return err;
+ }
+ Size videoSize;
+ videoSize.width = mVideoWidth;
+ videoSize.height = mVideoHeight;
+ if (mCaptureTimeLapse) {
+ if (mTimeBetweenTimeLapseFrameCaptureUs < 0) {
+ ALOGE("Invalid mTimeBetweenTimeLapseFrameCaptureUs value: %lld",
+ mTimeBetweenTimeLapseFrameCaptureUs);
+ return BAD_VALUE;
+ }
+
+ mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(
+ mCamera, mCameraProxy, mCameraId,
+ videoSize, mFrameRate, mPreviewSurface,
+ mTimeBetweenTimeLapseFrameCaptureUs);
+ *cameraSource = mCameraSourceTimeLapse;
+ } else {
+ *cameraSource = CameraSource::CreateFromCamera(
+ mCamera, mCameraProxy, mCameraId, videoSize, mFrameRate,
+ mPreviewSurface, true /*storeMetaDataInVideoBuffers*/);
+ }
+ mCamera.clear();
+ mCameraProxy.clear();
+ if (*cameraSource == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ if ((*cameraSource)->initCheck() != OK) {
+ (*cameraSource).clear();
+ *cameraSource = NULL;
+ return NO_INIT;
+ }
+
+ // When frame rate is not set, the actual frame rate will be set to
+ // the current frame rate being used.
+ if (mFrameRate == -1) {
+ int32_t frameRate = 0;
+ CHECK ((*cameraSource)->getFormat()->findInt32(
+ kKeyFrameRate, &frameRate));
+ ALOGI("Frame rate is not explicitly set. Use the current frame "
+ "rate (%d fps)", frameRate);
+ mFrameRate = frameRate;
+ }
+
+ CHECK(mFrameRate != -1);
+
+ mIsMetaDataStoredInVideoBuffers =
+ (*cameraSource)->isMetaDataStoredInVideoBuffers();
+
+ return OK;
+}
+
+status_t StagefrightRecorder::setupVideoEncoder(
+ sp<MediaSource> cameraSource,
+ int32_t videoBitRate,
+ sp<MediaSource> *source) {
+ source->clear();
+
+ sp<MetaData> enc_meta = new MetaData;
+ enc_meta->setInt32(kKeyBitRate, videoBitRate);
+ enc_meta->setInt32(kKeyFrameRate, mFrameRate);
+
+ switch (mVideoEncoder) {
+ case VIDEO_ENCODER_H263:
+ enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+ break;
+
+ case VIDEO_ENCODER_MPEG_4_SP:
+ enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+ break;
+
+ case VIDEO_ENCODER_H264:
+ enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+ break;
+
+ default:
+ CHECK(!"Should not be here, unsupported video encoding.");
+ break;
+ }
+
+ 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);
+ if (mVideoTimeScale > 0) {
+ enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale);
+ }
+ if (mVideoEncoderProfile != -1) {
+ enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile);
+ }
+ if (mVideoEncoderLevel != -1) {
+ enc_meta->setInt32(kKeyVideoLevel, mVideoEncoderLevel);
+ }
+
+ OMXClient client;
+ CHECK_EQ(client.connect(), (status_t)OK);
+
+ uint32_t encoder_flags = 0;
+ if (mIsMetaDataStoredInVideoBuffers) {
+ encoder_flags |= OMXCodec::kHardwareCodecsOnly;
+ encoder_flags |= OMXCodec::kStoreMetaDataInVideoBuffers;
+ }
+
+ // Do not wait for all the input buffers to become available.
+ // This give timelapse video recording faster response in
+ // receiving output from video encoder component.
+ if (mCaptureTimeLapse) {
+ encoder_flags |= OMXCodec::kOnlySubmitOneInputBufferAtOneTime;
+ }
+
+ sp<MediaSource> encoder = OMXCodec::Create(
+ client.interface(), enc_meta,
+ true /* createEncoder */, cameraSource,
+ NULL, encoder_flags);
+ if (encoder == NULL) {
+ ALOGW("Failed to create the encoder");
+ // When the encoder fails to be created, we need
+ // release the camera source due to the camera's lock
+ // and unlock mechanism.
+ cameraSource->stop();
+ return UNKNOWN_ERROR;
+ }
+
+ *source = encoder;
+
+ return OK;
+}
+
+status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
+ status_t status = BAD_VALUE;
+ if (OK != (status = checkAudioEncoderCapabilities())) {
+ return status;
+ }
+
+ switch(mAudioEncoder) {
+ case AUDIO_ENCODER_AMR_NB:
+ case AUDIO_ENCODER_AMR_WB:
+ case AUDIO_ENCODER_AAC:
+ break;
+
+ default:
+ ALOGE("Unsupported audio encoder: %d", mAudioEncoder);
+ return UNKNOWN_ERROR;
+ }
+
+ sp<MediaSource> audioEncoder = createAudioSource();
+ if (audioEncoder == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ writer->addSource(audioEncoder);
+ return OK;
+}
+
+status_t StagefrightRecorder::setupMPEG4Recording(
+ int outputFd,
+ int32_t videoWidth, int32_t videoHeight,
+ int32_t videoBitRate,
+ int32_t *totalBitRate,
+ sp<MediaWriter> *mediaWriter) {
+ mediaWriter->clear();
+ *totalBitRate = 0;
+ status_t err = OK;
+ sp<MediaWriter> writer = new MPEG4Writer(outputFd);
+
+ if (mVideoSource < VIDEO_SOURCE_LIST_END) {
+
+ sp<MediaSource> mediaSource;
+ err = setupMediaSource(&mediaSource);
+ if (err != OK) {
+ return err;
+ }
+
+ sp<MediaSource> encoder;
+ err = setupVideoEncoder(mediaSource, videoBitRate, &encoder);
+ if (err != OK) {
+ return err;
+ }
+
+ writer->addSource(encoder);
+ *totalBitRate += videoBitRate;
+ }
+
+ // Audio source is added at the end if it exists.
+ // This help make sure that the "recoding" sound is suppressed for
+ // camcorder applications in the recorded files.
+ if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_CNT)) {
+ err = setupAudioEncoder(writer);
+ if (err != OK) return err;
+ *totalBitRate += mAudioBitRate;
+ }
+
+ if (mInterleaveDurationUs > 0) {
+ reinterpret_cast<MPEG4Writer *>(writer.get())->
+ setInterleaveDuration(mInterleaveDurationUs);
+ }
+ if (mLongitudex10000 > -3600000 && mLatitudex10000 > -3600000) {
+ reinterpret_cast<MPEG4Writer *>(writer.get())->
+ setGeoData(mLatitudex10000, mLongitudex10000);
+ }
+ if (mMaxFileDurationUs != 0) {
+ writer->setMaxFileDuration(mMaxFileDurationUs);
+ }
+ if (mMaxFileSizeBytes != 0) {
+ writer->setMaxFileSize(mMaxFileSizeBytes);
+ }
+
+ mStartTimeOffsetMs = mEncoderProfiles->getStartTimeOffsetMs(mCameraId);
+ if (mStartTimeOffsetMs > 0) {
+ reinterpret_cast<MPEG4Writer *>(writer.get())->
+ setStartTimeOffsetMs(mStartTimeOffsetMs);
+ }
+
+ writer->setListener(mListener);
+ *mediaWriter = writer;
+ return OK;
+}
+
+void StagefrightRecorder::setupMPEG4MetaData(int64_t startTimeUs, int32_t totalBitRate,
+ sp<MetaData> *meta) {
+ (*meta)->setInt64(kKeyTime, startTimeUs);
+ (*meta)->setInt32(kKeyFileType, mOutputFormat);
+ (*meta)->setInt32(kKeyBitRate, totalBitRate);
+ (*meta)->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
+ if (mMovieTimeScale > 0) {
+ (*meta)->setInt32(kKeyTimeScale, mMovieTimeScale);
+ }
+ if (mTrackEveryTimeDurationUs > 0) {
+ (*meta)->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
+ }
+ if (mRotationDegrees != 0) {
+ (*meta)->setInt32(kKeyRotation, mRotationDegrees);
+ }
+}
+
+status_t StagefrightRecorder::startMPEG4Recording() {
+ int32_t totalBitRate;
+ status_t err = setupMPEG4Recording(
+ mOutputFd, mVideoWidth, mVideoHeight,
+ mVideoBitRate, &totalBitRate, &mWriter);
+ if (err != OK) {
+ return err;
+ }
+
+ int64_t startTimeUs = systemTime() / 1000;
+ sp<MetaData> meta = new MetaData;
+ setupMPEG4MetaData(startTimeUs, totalBitRate, &meta);
+
+ err = mWriter->start(meta.get());
+ if (err != OK) {
+ return err;
+ }
+
+ return OK;
+}
+
+status_t StagefrightRecorder::pause() {
+ ALOGV("pause");
+ if (mWriter == NULL) {
+ return UNKNOWN_ERROR;
+ }
+ mWriter->pause();
+
+ if (mStarted) {
+ mStarted = false;
+
+ uint32_t params = 0;
+ if (mAudioSource != AUDIO_SOURCE_CNT) {
+ params |= IMediaPlayerService::kBatteryDataTrackAudio;
+ }
+ if (mVideoSource != VIDEO_SOURCE_LIST_END) {
+ params |= IMediaPlayerService::kBatteryDataTrackVideo;
+ }
+
+ addBatteryData(params);
+ }
+
+
+ return OK;
+}
+
+status_t StagefrightRecorder::stop() {
+ ALOGV("stop");
+ status_t err = OK;
+
+ if (mCaptureTimeLapse && mCameraSourceTimeLapse != NULL) {
+ mCameraSourceTimeLapse->startQuickReadReturns();
+ mCameraSourceTimeLapse = NULL;
+ }
+
+ if (mWriter != NULL) {
+ err = mWriter->stop();
+ mWriter.clear();
+ }
+
+ if (mOutputFd >= 0) {
+ ::close(mOutputFd);
+ mOutputFd = -1;
+ }
+
+ if (mStarted) {
+ mStarted = false;
+
+ uint32_t params = 0;
+ if (mAudioSource != AUDIO_SOURCE_CNT) {
+ params |= IMediaPlayerService::kBatteryDataTrackAudio;
+ }
+ if (mVideoSource != VIDEO_SOURCE_LIST_END) {
+ params |= IMediaPlayerService::kBatteryDataTrackVideo;
+ }
+
+ addBatteryData(params);
+ }
+
+
+ return err;
+}
+
+status_t StagefrightRecorder::close() {
+ ALOGV("close");
+ stop();
+
+ return OK;
+}
+
+status_t StagefrightRecorder::reset() {
+ ALOGV("reset");
+ stop();
+
+ // No audio or video source by default
+ mAudioSource = AUDIO_SOURCE_CNT;
+ mVideoSource = VIDEO_SOURCE_LIST_END;
+
+ // Default parameters
+ mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
+ mAudioEncoder = AUDIO_ENCODER_AMR_NB;
+ mVideoEncoder = VIDEO_ENCODER_H263;
+ mVideoWidth = 176;
+ mVideoHeight = 144;
+ mFrameRate = -1;
+ mVideoBitRate = 192000;
+ mSampleRate = 8000;
+ mAudioChannels = 1;
+ mAudioBitRate = 12200;
+ mInterleaveDurationUs = 0;
+ mIFramesIntervalSec = 1;
+ mAudioSourceNode = 0;
+ mUse64BitFileOffset = false;
+ mMovieTimeScale = -1;
+ mAudioTimeScale = -1;
+ mVideoTimeScale = -1;
+ mCameraId = 0;
+ mStartTimeOffsetMs = -1;
+ mVideoEncoderProfile = -1;
+ mVideoEncoderLevel = -1;
+ mMaxFileDurationUs = 0;
+ mMaxFileSizeBytes = 0;
+ mTrackEveryTimeDurationUs = 0;
+ mCaptureTimeLapse = false;
+ mTimeBetweenTimeLapseFrameCaptureUs = -1;
+ mCameraSourceTimeLapse = NULL;
+ mIsMetaDataStoredInVideoBuffers = false;
+ mEncoderProfiles = MediaProfiles::getInstance();
+ mRotationDegrees = 0;
+ mLatitudex10000 = -3600000;
+ mLongitudex10000 = -3600000;
+
+ mOutputFd = -1;
+
+ return OK;
+}
+
+status_t StagefrightRecorder::getMaxAmplitude(int *max) {
+ ALOGV("getMaxAmplitude");
+
+ if (max == NULL) {
+ ALOGE("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 {
+ ALOGV("dump");
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ if (mWriter != 0) {
+ mWriter->dump(fd, args);
+ } else {
+ snprintf(buffer, SIZE, " No file writer\n");
+ result.append(buffer);
+ }
+ snprintf(buffer, SIZE, " Recorder: %p\n", 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, " Start time offset (ms): %d\n", mStartTimeOffsetMs);
+ 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
new file mode 100644
index 0000000..ec5ce7e
--- /dev/null
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -0,0 +1,194 @@
+/*
+ * 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.
+ */
+
+#ifndef STAGEFRIGHT_RECORDER_H_
+
+#define STAGEFRIGHT_RECORDER_H_
+
+#include <media/MediaRecorderBase.h>
+#include <camera/CameraParameters.h>
+#include <utils/String8.h>
+
+#include <system/audio.h>
+
+namespace android {
+
+class Camera;
+class ICameraRecordingProxy;
+class CameraSource;
+class CameraSourceTimeLapse;
+struct MediaSource;
+struct MediaWriter;
+class MetaData;
+struct AudioSource;
+class MediaProfiles;
+class ISurfaceTexture;
+class SurfaceMediaSource;
+
+struct StagefrightRecorder : public MediaRecorderBase {
+ StagefrightRecorder();
+ virtual ~StagefrightRecorder();
+
+ virtual status_t init();
+ virtual status_t setAudioSource(audio_source_t as);
+ virtual status_t setVideoSource(video_source vs);
+ virtual status_t setOutputFormat(output_format of);
+ virtual status_t setAudioEncoder(audio_encoder ae);
+ virtual status_t setVideoEncoder(video_encoder ve);
+ virtual status_t setVideoSize(int width, int height);
+ virtual status_t setVideoFrameRate(int frames_per_second);
+ virtual status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
+ virtual status_t setPreviewSurface(const sp<Surface>& surface);
+ 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<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;
+ // Querying a SurfaceMediaSourcer
+ virtual sp<ISurfaceTexture> querySurfaceMediaSource() const;
+
+private:
+ sp<ICamera> mCamera;
+ sp<ICameraRecordingProxy> mCameraProxy;
+ sp<Surface> mPreviewSurface;
+ sp<IMediaRecorderClient> mListener;
+ sp<MediaWriter> mWriter;
+ int mOutputFd;
+ sp<AudioSource> mAudioSourceNode;
+
+ audio_source_t mAudioSource;
+ video_source mVideoSource;
+ output_format mOutputFormat;
+ audio_encoder mAudioEncoder;
+ video_encoder mVideoEncoder;
+ 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;
+ int32_t mRotationDegrees; // Clockwise
+ int32_t mLatitudex10000;
+ int32_t mLongitudex10000;
+ int32_t mStartTimeOffsetMs;
+
+ bool mCaptureTimeLapse;
+ int64_t mTimeBetweenTimeLapseFrameCaptureUs;
+ sp<CameraSourceTimeLapse> mCameraSourceTimeLapse;
+
+
+ String8 mParams;
+
+ bool mIsMetaDataStoredInVideoBuffers;
+ MediaProfiles *mEncoderProfiles;
+
+ bool mStarted;
+ // Needed when GLFrames are encoded.
+ // An <ISurfaceTexture> pointer
+ // will be sent to the client side using which the
+ // frame buffers will be queued and dequeued
+ sp<SurfaceMediaSource> mSurfaceMediaSource;
+
+ status_t setupMPEG4Recording(
+ int outputFd,
+ int32_t videoWidth, int32_t videoHeight,
+ int32_t videoBitRate,
+ int32_t *totalBitRate,
+ sp<MediaWriter> *mediaWriter);
+ void setupMPEG4MetaData(int64_t startTimeUs, int32_t totalBitRate,
+ sp<MetaData> *meta);
+ status_t startMPEG4Recording();
+ status_t startAMRRecording();
+ status_t startAACRecording();
+ status_t startRawAudioRecording();
+ status_t startRTPRecording();
+ status_t startMPEG2TSRecording();
+ sp<MediaSource> createAudioSource();
+ status_t checkVideoEncoderCapabilities();
+ status_t checkAudioEncoderCapabilities();
+ // Generic MediaSource set-up. Returns the appropriate
+ // source (CameraSource or SurfaceMediaSource)
+ // depending on the videosource type
+ status_t setupMediaSource(sp<MediaSource> *mediaSource);
+ status_t setupCameraSource(sp<CameraSource> *cameraSource);
+ // setup the surfacemediasource for the encoder
+ status_t setupSurfaceMediaSource();
+
+ status_t setupAudioEncoder(const sp<MediaWriter>& writer);
+ status_t setupVideoEncoder(
+ sp<MediaSource> cameraSource,
+ int32_t videoBitRate,
+ sp<MediaSource> *source);
+
+ // 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 setParamTimeLapseEnable(int32_t timeLapseEnable);
+ status_t setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs);
+ 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 setParamVideoRotation(int32_t degrees);
+ 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);
+ status_t setParamGeoDataLongitude(int64_t longitudex10000);
+ status_t setParamGeoDataLatitude(int64_t latitudex10000);
+ void clipVideoBitRate();
+ void clipVideoFrameRate();
+ void clipVideoFrameWidth();
+ void clipVideoFrameHeight();
+ void clipAudioBitRate();
+ void clipAudioSampleRate();
+ void clipNumberOfAudioChannels();
+ void setDefaultProfileIfNecessary();
+
+
+ StagefrightRecorder(const StagefrightRecorder &);
+ StagefrightRecorder &operator=(const StagefrightRecorder &);
+};
+
+} // namespace android
+
+#endif // STAGEFRIGHT_RECORDER_H_
diff --git a/media/libmediaplayerservice/TestPlayerStub.cpp b/media/libmediaplayerservice/TestPlayerStub.cpp
new file mode 100644
index 0000000..5d9728a
--- /dev/null
+++ b/media/libmediaplayerservice/TestPlayerStub.cpp
@@ -0,0 +1,196 @@
+/*
+ * 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 "TestPlayerStub"
+#include "utils/Log.h"
+
+#include "TestPlayerStub.h"
+
+#include <dlfcn.h> // for dlopen/dlclose
+#include <stdlib.h>
+#include <string.h>
+#include <cutils/properties.h>
+#include <utils/Errors.h> // for status_t
+
+#include "media/MediaPlayerInterface.h"
+
+
+namespace {
+using android::status_t;
+using android::MediaPlayerBase;
+
+const char *kTestUrlScheme = "test:";
+const char *kUrlParam = "url=";
+
+const char *kBuildTypePropName = "ro.build.type";
+const char *kEngBuild = "eng";
+const char *kTestBuild = "test";
+
+// @return true if the current build is 'eng' or 'test'.
+bool isTestBuild()
+{
+ char prop[PROPERTY_VALUE_MAX] = { '\0', };
+
+ property_get(kBuildTypePropName, prop, '\0');
+ return strcmp(prop, kEngBuild) == 0 || strcmp(prop, kTestBuild) == 0;
+}
+
+// @return true if the url scheme is 'test:'
+bool isTestUrl(const char *url)
+{
+ return url && strncmp(url, kTestUrlScheme, strlen(kTestUrlScheme)) == 0;
+}
+
+} // anonymous namespace
+
+namespace android {
+
+TestPlayerStub::TestPlayerStub()
+ :mUrl(NULL), mFilename(NULL), mContentUrl(NULL),
+ mHandle(NULL), mNewPlayer(NULL), mDeletePlayer(NULL),
+ mPlayer(NULL) { }
+
+TestPlayerStub::~TestPlayerStub()
+{
+ resetInternal();
+}
+
+status_t TestPlayerStub::initCheck()
+{
+ return isTestBuild() ? OK : INVALID_OPERATION;
+}
+
+// Parse mUrl to get:
+// * The library to be dlopened.
+// * The url to be passed to the real setDataSource impl.
+//
+// mUrl is expected to be in following format:
+//
+// test:<name of the .so>?url=<url for setDataSource>
+//
+// The value of the url parameter is treated as a string (no
+// unescaping of illegal charaters).
+status_t TestPlayerStub::parseUrl()
+{
+ if (strlen(mUrl) < strlen(kTestUrlScheme)) {
+ resetInternal();
+ return BAD_VALUE;
+ }
+
+ char *i = mUrl + strlen(kTestUrlScheme);
+
+ mFilename = i;
+
+ while (*i != '\0' && *i != '?') {
+ ++i;
+ }
+
+ if (*i == '\0' || strncmp(i + 1, kUrlParam, strlen(kUrlParam)) != 0) {
+ resetInternal();
+ return BAD_VALUE;
+ }
+ *i = '\0'; // replace '?' to nul-terminate mFilename
+
+ mContentUrl = i + 1 + strlen(kUrlParam);
+ return OK;
+}
+
+// Load the dynamic library.
+// Create the test player.
+// Call setDataSource on the test player with the url in param.
+status_t TestPlayerStub::setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers) {
+ if (!isTestUrl(url) || NULL != mHandle) {
+ return INVALID_OPERATION;
+ }
+
+ mUrl = strdup(url);
+
+ status_t status = parseUrl();
+
+ if (OK != status) {
+ resetInternal();
+ return status;
+ }
+
+ ::dlerror(); // Clears any pending error.
+
+ // Load the test player from the url. dlopen will fail if the lib
+ // is not there. dls are under /system/lib
+ // None of the entry points should be NULL.
+ mHandle = ::dlopen(mFilename, RTLD_NOW | RTLD_GLOBAL);
+ if (!mHandle) {
+ ALOGE("dlopen failed: %s", ::dlerror());
+ resetInternal();
+ return UNKNOWN_ERROR;
+ }
+
+ // Load the 2 entry points to create and delete instances.
+ const char *err;
+ mNewPlayer = reinterpret_cast<NEW_PLAYER>(dlsym(mHandle,
+ "newPlayer"));
+ err = ::dlerror();
+ if (err || mNewPlayer == NULL) {
+ // if err is NULL the string <null> is inserted in the logs =>
+ // mNewPlayer was NULL.
+ ALOGE("dlsym for newPlayer failed %s", err);
+ resetInternal();
+ return UNKNOWN_ERROR;
+ }
+
+ mDeletePlayer = reinterpret_cast<DELETE_PLAYER>(dlsym(mHandle,
+ "deletePlayer"));
+ err = ::dlerror();
+ if (err || mDeletePlayer == NULL) {
+ ALOGE("dlsym for deletePlayer failed %s", err);
+ resetInternal();
+ return UNKNOWN_ERROR;
+ }
+
+ mPlayer = (*mNewPlayer)();
+ return mPlayer->setDataSource(mContentUrl, headers);
+}
+
+// Internal cleanup.
+status_t TestPlayerStub::resetInternal()
+{
+ if(mUrl) {
+ free(mUrl);
+ mUrl = NULL;
+ }
+ mFilename = NULL;
+ mContentUrl = NULL;
+
+ if (mPlayer) {
+ ALOG_ASSERT(mDeletePlayer != NULL, "mDeletePlayer is null");
+ (*mDeletePlayer)(mPlayer);
+ mPlayer = NULL;
+ }
+
+ if (mHandle) {
+ ::dlclose(mHandle);
+ mHandle = NULL;
+ }
+ return OK;
+}
+
+/* static */ bool TestPlayerStub::canBeUsed(const char *url)
+{
+ return isTestBuild() && isTestUrl(url);
+}
+
+} // namespace android
diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h
new file mode 100644
index 0000000..91ffa7d
--- /dev/null
+++ b/media/libmediaplayerservice/TestPlayerStub.h
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_FRAMEWORKS_BASE_MEDIA_LIBMEDIAPLAYERSERVICE_TESTPLAYERSTUB_H__
+#define ANDROID_FRAMEWORKS_BASE_MEDIA_LIBMEDIAPLAYERSERVICE_TESTPLAYERSTUB_H__
+
+#include <media/MediaPlayerInterface.h>
+#include <utils/Errors.h>
+
+namespace android {
+class MediaPlayerBase; // in media/MediaPlayerInterface.h
+
+// Wrapper around a test media player that gets dynamically loaded.
+//
+// The URL passed to setDataSource has this format:
+//
+// test:<name of the .so>?url=<url for the real setDataSource impl.>
+//
+// e.g:
+// test:invoke_test_media_player.so?url=http://youtube.com/
+// test:invoke_test_media_player.so?url=speedtest
+//
+// TestPlayerStub::setDataSource loads the library in the test url. 2
+// entry points with C linkage are expected. One to create the test
+// player and one to destroy it.
+//
+// extern "C" android::MediaPlayerBase* newPlayer();
+// extern "C" android::status_t deletePlayer(android::MediaPlayerBase *p);
+//
+// Once the test player has been loaded, its setDataSource
+// implementation is called with the value of the 'url' parameter.
+//
+// typical usage in a java test:
+// ============================
+//
+// MediaPlayer p = new MediaPlayer();
+// p.setDataSource("test:invoke_mock_media_player.so?url=http://youtube.com");
+// p.prepare();
+// ...
+// p.release();
+
+class TestPlayerStub : public MediaPlayerInterface {
+ public:
+ typedef MediaPlayerBase* (*NEW_PLAYER)();
+ typedef status_t (*DELETE_PLAYER)(MediaPlayerBase *);
+
+ TestPlayerStub();
+ virtual ~TestPlayerStub();
+
+ // Called right after the constructor. Check if the current build
+ // allows test players.
+ virtual status_t initCheck();
+
+ // @param url Should be a test url. See class comment.
+ virtual status_t setDataSource(
+ const char* url, const KeyedVector<String8, String8> *headers);
+
+ // Test player for a file descriptor source is not supported.
+ virtual status_t setDataSource(int, int64_t, int64_t) {
+ return INVALID_OPERATION;
+ }
+
+
+ // All the methods below wrap the mPlayer instance.
+ virtual status_t setVideoSurfaceTexture(
+ const android::sp<android::ISurfaceTexture>& st) {
+ return mPlayer->setVideoSurfaceTexture(st);
+ }
+ virtual status_t prepare() {return mPlayer->prepare();}
+ virtual status_t prepareAsync() {return mPlayer->prepareAsync();}
+ virtual status_t start() {return mPlayer->start();}
+ virtual status_t stop() {return mPlayer->stop();}
+ virtual status_t pause() {return mPlayer->pause();}
+ virtual bool isPlaying() {return mPlayer->isPlaying();}
+ virtual status_t seekTo(int msec) {return mPlayer->seekTo(msec);}
+ virtual status_t getCurrentPosition(int *p) {
+ return mPlayer->getCurrentPosition(p);
+ }
+ virtual status_t getDuration(int *d) {return mPlayer->getDuration(d);}
+ virtual status_t reset() {return mPlayer->reset();}
+ virtual status_t setLooping(int b) {return mPlayer->setLooping(b);}
+ virtual player_type playerType() {return mPlayer->playerType();}
+ virtual status_t invoke(const android::Parcel& in, android::Parcel *out) {
+ return mPlayer->invoke(in, out);
+ }
+ virtual status_t setParameter(int key, const Parcel &request) {
+ return mPlayer->setParameter(key, request);
+ }
+ virtual status_t getParameter(int key, Parcel *reply) {
+ return mPlayer->getParameter(key, reply);
+ }
+
+
+ // @return true if the current build is 'eng' or 'test' and the
+ // url's scheme is 'test:'
+ static bool canBeUsed(const char *url);
+
+ private:
+ // Release the player, dlclose the library.
+ status_t resetInternal();
+ status_t parseUrl();
+
+ char *mUrl; // test:foo.so?url=http://bar
+ char *mFilename; // foo.so
+ char *mContentUrl; // http://bar
+ void *mHandle; // returned by dlopen
+ NEW_PLAYER mNewPlayer;
+ DELETE_PLAYER mDeletePlayer;
+ MediaPlayerBase *mPlayer; // wrapped player
+};
+
+} // namespace android
+
+#endif
diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk
new file mode 100644
index 0000000..73336ef
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/Android.mk
@@ -0,0 +1,27 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ GenericSource.cpp \
+ HTTPLiveSource.cpp \
+ NuPlayer.cpp \
+ NuPlayerDecoder.cpp \
+ NuPlayerDriver.cpp \
+ NuPlayerRenderer.cpp \
+ NuPlayerStreamListener.cpp \
+ RTSPSource.cpp \
+ StreamingSource.cpp \
+
+LOCAL_C_INCLUDES := \
+ $(TOP)/frameworks/base/media/libstagefright/httplive \
+ $(TOP)/frameworks/base/media/libstagefright/include \
+ $(TOP)/frameworks/base/media/libstagefright/mpeg2ts \
+ $(TOP)/frameworks/base/media/libstagefright/rtsp \
+ $(TOP)/frameworks/native/include/media/openmax
+
+LOCAL_MODULE:= libstagefright_nuplayer
+
+LOCAL_MODULE_TAGS := eng
+
+include $(BUILD_STATIC_LIBRARY)
+
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
new file mode 100644
index 0000000..99569c9
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenericSource.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/DataSource.h>
+#include <media/stagefright/FileSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+NuPlayer::GenericSource::GenericSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers,
+ bool uidValid,
+ uid_t uid)
+ : mDurationUs(0ll),
+ mAudioIsVorbis(false) {
+ DataSource::RegisterDefaultSniffers();
+
+ sp<DataSource> dataSource =
+ DataSource::CreateFromURI(url, headers);
+ CHECK(dataSource != NULL);
+
+ initFromDataSource(dataSource);
+}
+
+NuPlayer::GenericSource::GenericSource(
+ int fd, int64_t offset, int64_t length)
+ : mDurationUs(0ll),
+ mAudioIsVorbis(false) {
+ DataSource::RegisterDefaultSniffers();
+
+ sp<DataSource> dataSource = new FileSource(dup(fd), offset, length);
+
+ initFromDataSource(dataSource);
+}
+
+void NuPlayer::GenericSource::initFromDataSource(
+ const sp<DataSource> &dataSource) {
+ sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+
+ CHECK(extractor != NULL);
+
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ sp<MediaSource> track;
+
+ if (!strncasecmp(mime, "audio/", 6)) {
+ if (mAudioTrack.mSource == NULL) {
+ mAudioTrack.mSource = track = extractor->getTrack(i);
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
+ mAudioIsVorbis = true;
+ } else {
+ mAudioIsVorbis = false;
+ }
+ }
+ } else if (!strncasecmp(mime, "video/", 6)) {
+ if (mVideoTrack.mSource == NULL) {
+ mVideoTrack.mSource = track = extractor->getTrack(i);
+ }
+ }
+
+ if (track != NULL) {
+ int64_t durationUs;
+ if (meta->findInt64(kKeyDuration, &durationUs)) {
+ if (durationUs > mDurationUs) {
+ mDurationUs = durationUs;
+ }
+ }
+ }
+ }
+}
+
+NuPlayer::GenericSource::~GenericSource() {
+}
+
+void NuPlayer::GenericSource::start() {
+ ALOGI("start");
+
+ if (mAudioTrack.mSource != NULL) {
+ CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK);
+
+ mAudioTrack.mPackets =
+ new AnotherPacketSource(mAudioTrack.mSource->getFormat());
+
+ readBuffer(true /* audio */);
+ }
+
+ if (mVideoTrack.mSource != NULL) {
+ CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK);
+
+ mVideoTrack.mPackets =
+ new AnotherPacketSource(mVideoTrack.mSource->getFormat());
+
+ readBuffer(false /* audio */);
+ }
+}
+
+status_t NuPlayer::GenericSource::feedMoreTSData() {
+ return OK;
+}
+
+sp<MetaData> NuPlayer::GenericSource::getFormat(bool audio) {
+ sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
+
+ if (source == NULL) {
+ return NULL;
+ }
+
+ return source->getFormat();
+}
+
+status_t NuPlayer::GenericSource::dequeueAccessUnit(
+ bool audio, sp<ABuffer> *accessUnit) {
+ Track *track = audio ? &mAudioTrack : &mVideoTrack;
+
+ if (track->mSource == NULL) {
+ return -EWOULDBLOCK;
+ }
+
+ status_t finalResult;
+ if (!track->mPackets->hasBufferAvailable(&finalResult)) {
+ return finalResult == OK ? -EWOULDBLOCK : finalResult;
+ }
+
+ status_t result = track->mPackets->dequeueAccessUnit(accessUnit);
+
+ readBuffer(audio, -1ll);
+
+ return result;
+}
+
+status_t NuPlayer::GenericSource::getDuration(int64_t *durationUs) {
+ *durationUs = mDurationUs;
+ return OK;
+}
+
+status_t NuPlayer::GenericSource::seekTo(int64_t seekTimeUs) {
+ if (mVideoTrack.mSource != NULL) {
+ int64_t actualTimeUs;
+ readBuffer(false /* audio */, seekTimeUs, &actualTimeUs);
+
+ seekTimeUs = actualTimeUs;
+ }
+
+ if (mAudioTrack.mSource != NULL) {
+ readBuffer(true /* audio */, seekTimeUs);
+ }
+
+ return OK;
+}
+
+void NuPlayer::GenericSource::readBuffer(
+ bool audio, int64_t seekTimeUs, int64_t *actualTimeUs) {
+ Track *track = audio ? &mAudioTrack : &mVideoTrack;
+ CHECK(track->mSource != NULL);
+
+ if (actualTimeUs) {
+ *actualTimeUs = seekTimeUs;
+ }
+
+ MediaSource::ReadOptions options;
+
+ bool seeking = false;
+
+ if (seekTimeUs >= 0) {
+ options.setSeekTo(seekTimeUs);
+ seeking = true;
+ }
+
+ for (;;) {
+ MediaBuffer *mbuf;
+ status_t err = track->mSource->read(&mbuf, &options);
+
+ options.clearSeekTo();
+
+ if (err == OK) {
+ size_t outLength = mbuf->range_length();
+
+ if (audio && mAudioIsVorbis) {
+ outLength += sizeof(int32_t);
+ }
+
+ sp<ABuffer> buffer = new ABuffer(outLength);
+
+ memcpy(buffer->data(),
+ (const uint8_t *)mbuf->data() + mbuf->range_offset(),
+ mbuf->range_length());
+
+ if (audio && mAudioIsVorbis) {
+ int32_t numPageSamples;
+ if (!mbuf->meta_data()->findInt32(
+ kKeyValidSamples, &numPageSamples)) {
+ numPageSamples = -1;
+ }
+
+ memcpy(buffer->data() + mbuf->range_length(),
+ &numPageSamples,
+ sizeof(numPageSamples));
+ }
+
+ int64_t timeUs;
+ CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
+
+ buffer->meta()->setInt64("timeUs", timeUs);
+
+ if (actualTimeUs) {
+ *actualTimeUs = timeUs;
+ }
+
+ mbuf->release();
+ mbuf = NULL;
+
+ if (seeking) {
+ track->mPackets->queueDiscontinuity(
+ ATSParser::DISCONTINUITY_SEEK, NULL);
+ }
+
+ track->mPackets->queueAccessUnit(buffer);
+ break;
+ } else if (err == INFO_FORMAT_CHANGED) {
+#if 0
+ track->mPackets->queueDiscontinuity(
+ ATSParser::DISCONTINUITY_FORMATCHANGE, NULL);
+#endif
+ } else {
+ track->mPackets->signalEOS(err);
+ break;
+ }
+ }
+}
+
+bool NuPlayer::GenericSource::isSeekable() {
+ return true;
+}
+
+} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
new file mode 100644
index 0000000..aaa5876
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 GENERIC_SOURCE_H_
+
+#define GENERIC_SOURCE_H_
+
+#include "NuPlayer.h"
+#include "NuPlayerSource.h"
+
+#include "ATSParser.h"
+
+namespace android {
+
+struct AnotherPacketSource;
+struct ARTSPController;
+struct DataSource;
+struct MediaSource;
+
+struct NuPlayer::GenericSource : public NuPlayer::Source {
+ GenericSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers,
+ bool uidValid = false,
+ uid_t uid = 0);
+
+ GenericSource(int fd, int64_t offset, int64_t length);
+
+ virtual void start();
+
+ virtual status_t feedMoreTSData();
+
+ virtual sp<MetaData> getFormat(bool audio);
+ virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+
+ virtual status_t getDuration(int64_t *durationUs);
+ virtual status_t seekTo(int64_t seekTimeUs);
+ virtual bool isSeekable();
+
+protected:
+ virtual ~GenericSource();
+
+private:
+ struct Track {
+ sp<MediaSource> mSource;
+ sp<AnotherPacketSource> mPackets;
+ };
+
+ Track mAudioTrack;
+ Track mVideoTrack;
+
+ int64_t mDurationUs;
+ bool mAudioIsVorbis;
+
+ void initFromDataSource(const sp<DataSource> &dataSource);
+
+ void readBuffer(
+ bool audio,
+ int64_t seekTimeUs = -1ll, int64_t *actualTimeUs = NULL);
+
+ DISALLOW_EVIL_CONSTRUCTORS(GenericSource);
+};
+
+} // namespace android
+
+#endif // GENERIC_SOURCE_H_
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
new file mode 100644
index 0000000..22b8847
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -0,0 +1,189 @@
+/*
+ * 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 "HTTPLiveSource"
+#include <utils/Log.h>
+
+#include "HTTPLiveSource.h"
+
+#include "ATSParser.h"
+#include "AnotherPacketSource.h"
+#include "LiveDataSource.h"
+#include "LiveSession.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+NuPlayer::HTTPLiveSource::HTTPLiveSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers,
+ bool uidValid, uid_t uid)
+ : mURL(url),
+ mUIDValid(uidValid),
+ mUID(uid),
+ mFlags(0),
+ mFinalResult(OK),
+ mOffset(0) {
+ if (headers) {
+ mExtraHeaders = *headers;
+
+ ssize_t index =
+ mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
+
+ if (index >= 0) {
+ mFlags |= kFlagIncognito;
+
+ mExtraHeaders.removeItemsAt(index);
+ }
+ }
+}
+
+NuPlayer::HTTPLiveSource::~HTTPLiveSource() {
+ if (mLiveSession != NULL) {
+ mLiveSession->disconnect();
+ mLiveLooper->stop();
+ }
+}
+
+void NuPlayer::HTTPLiveSource::start() {
+ mLiveLooper = new ALooper;
+ mLiveLooper->setName("http live");
+ mLiveLooper->start();
+
+ mLiveSession = new LiveSession(
+ (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0,
+ mUIDValid, mUID);
+
+ mLiveLooper->registerHandler(mLiveSession);
+
+ mLiveSession->connect(
+ mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
+
+ mTSParser = new ATSParser;
+}
+
+sp<MetaData> NuPlayer::HTTPLiveSource::getFormat(bool audio) {
+ ATSParser::SourceType type =
+ audio ? ATSParser::AUDIO : ATSParser::VIDEO;
+
+ sp<AnotherPacketSource> source =
+ static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+
+ if (source == NULL) {
+ return NULL;
+ }
+
+ return source->getFormat();
+}
+
+status_t NuPlayer::HTTPLiveSource::feedMoreTSData() {
+ if (mFinalResult != OK) {
+ return mFinalResult;
+ }
+
+ sp<LiveDataSource> source =
+ static_cast<LiveDataSource *>(mLiveSession->getDataSource().get());
+
+ for (int32_t i = 0; i < 50; ++i) {
+ char buffer[188];
+ ssize_t n = source->readAtNonBlocking(mOffset, buffer, sizeof(buffer));
+
+ if (n == -EWOULDBLOCK) {
+ break;
+ } else if (n < 0) {
+ if (n != ERROR_END_OF_STREAM) {
+ ALOGI("input data EOS reached, error %ld", n);
+ } else {
+ ALOGI("input data EOS reached.");
+ }
+ mTSParser->signalEOS(n);
+ mFinalResult = n;
+ break;
+ } else {
+ if (buffer[0] == 0x00) {
+ // XXX legacy
+ sp<AMessage> extra;
+ mTSParser->signalDiscontinuity(
+ buffer[1] == 0x00
+ ? ATSParser::DISCONTINUITY_SEEK
+ : ATSParser::DISCONTINUITY_FORMATCHANGE,
+ extra);
+ } else {
+ status_t err = mTSParser->feedTSPacket(buffer, sizeof(buffer));
+
+ if (err != OK) {
+ ALOGE("TS Parser returned error %d", err);
+ mTSParser->signalEOS(err);
+ mFinalResult = err;
+ break;
+ }
+ }
+
+ mOffset += n;
+ }
+ }
+
+ return OK;
+}
+
+status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit(
+ bool audio, sp<ABuffer> *accessUnit) {
+ ATSParser::SourceType type =
+ audio ? ATSParser::AUDIO : ATSParser::VIDEO;
+
+ sp<AnotherPacketSource> source =
+ static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+
+ if (source == NULL) {
+ return -EWOULDBLOCK;
+ }
+
+ status_t finalResult;
+ if (!source->hasBufferAvailable(&finalResult)) {
+ return finalResult == OK ? -EWOULDBLOCK : finalResult;
+ }
+
+ return source->dequeueAccessUnit(accessUnit);
+}
+
+status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) {
+ return mLiveSession->getDuration(durationUs);
+}
+
+status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) {
+ // We need to make sure we're not seeking until we have seen the very first
+ // PTS timestamp in the whole stream (from the beginning of the stream).
+ while (!mTSParser->PTSTimeDeltaEstablished() && feedMoreTSData() == OK) {
+ usleep(100000);
+ }
+
+ mLiveSession->seekTo(seekTimeUs);
+
+ return OK;
+}
+
+bool NuPlayer::HTTPLiveSource::isSeekable() {
+ return mLiveSession->isSeekable();
+}
+
+} // namespace android
+
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
new file mode 100644
index 0000000..f22af5b
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.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 HTTP_LIVE_SOURCE_H_
+
+#define HTTP_LIVE_SOURCE_H_
+
+#include "NuPlayer.h"
+#include "NuPlayerSource.h"
+
+namespace android {
+
+struct ATSParser;
+struct LiveSession;
+
+struct NuPlayer::HTTPLiveSource : public NuPlayer::Source {
+ HTTPLiveSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers,
+ bool uidValid = false,
+ uid_t uid = 0);
+
+ virtual void start();
+
+ virtual status_t feedMoreTSData();
+
+ virtual sp<MetaData> getFormat(bool audio);
+ virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+
+ virtual status_t getDuration(int64_t *durationUs);
+ virtual status_t seekTo(int64_t seekTimeUs);
+ virtual bool isSeekable();
+
+protected:
+ virtual ~HTTPLiveSource();
+
+private:
+ enum Flags {
+ // Don't log any URLs.
+ kFlagIncognito = 1,
+ };
+
+ AString mURL;
+ KeyedVector<String8, String8> mExtraHeaders;
+ bool mUIDValid;
+ uid_t mUID;
+ uint32_t mFlags;
+ status_t mFinalResult;
+ off64_t mOffset;
+ sp<ALooper> mLiveLooper;
+ sp<LiveSession> mLiveSession;
+ sp<ATSParser> mTSParser;
+
+ DISALLOW_EVIL_CONSTRUCTORS(HTTPLiveSource);
+};
+
+} // namespace android
+
+#endif // HTTP_LIVE_SOURCE_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
new file mode 100644
index 0000000..544d501
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -0,0 +1,905 @@
+/*
+ * 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 "NuPlayer"
+#include <utils/Log.h>
+
+#include "NuPlayer.h"
+
+#include "HTTPLiveSource.h"
+#include "NuPlayerDecoder.h"
+#include "NuPlayerDriver.h"
+#include "NuPlayerRenderer.h"
+#include "NuPlayerSource.h"
+#include "RTSPSource.h"
+#include "StreamingSource.h"
+#include "GenericSource.h"
+
+#include "ATSParser.h"
+
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/ACodec.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <gui/ISurfaceTexture.h>
+
+#include "avc_utils.h"
+
+namespace android {
+
+////////////////////////////////////////////////////////////////////////////////
+
+NuPlayer::NuPlayer()
+ : mUIDValid(false),
+ mVideoIsAVC(false),
+ mAudioEOS(false),
+ mVideoEOS(false),
+ mScanSourcesPending(false),
+ mScanSourcesGeneration(0),
+ mTimeDiscontinuityPending(false),
+ mFlushingAudio(NONE),
+ mFlushingVideo(NONE),
+ mResetInProgress(false),
+ mResetPostponed(false),
+ mSkipRenderingAudioUntilMediaTimeUs(-1ll),
+ mSkipRenderingVideoUntilMediaTimeUs(-1ll),
+ mVideoLateByUs(0ll),
+ mNumFramesTotal(0ll),
+ mNumFramesDropped(0ll) {
+}
+
+NuPlayer::~NuPlayer() {
+}
+
+void NuPlayer::setUID(uid_t uid) {
+ mUIDValid = true;
+ mUID = uid;
+}
+
+void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
+ mDriver = driver;
+}
+
+void NuPlayer::setDataSource(const sp<IStreamSource> &source) {
+ sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
+
+ msg->setObject("source", new StreamingSource(source));
+ msg->post();
+}
+
+static bool IsHTTPLiveURL(const char *url) {
+ if (!strncasecmp("http://", url, 7)
+ || !strncasecmp("https://", url, 8)) {
+ size_t len = strlen(url);
+ if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
+ return true;
+ }
+
+ if (strstr(url,"m3u8")) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void NuPlayer::setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers) {
+ sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
+
+ sp<Source> source;
+ if (IsHTTPLiveURL(url)) {
+ source = new HTTPLiveSource(url, headers, mUIDValid, mUID);
+ } else if (!strncasecmp(url, "rtsp://", 7)) {
+ source = new RTSPSource(url, headers, mUIDValid, mUID);
+ } else {
+ source = new GenericSource(url, headers, mUIDValid, mUID);
+ }
+
+ msg->setObject("source", source);
+ msg->post();
+}
+
+void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
+ sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
+
+ sp<Source> source = new GenericSource(fd, offset, length);
+ msg->setObject("source", source);
+ msg->post();
+}
+
+void NuPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
+ sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
+ sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ?
+ new SurfaceTextureClient(surfaceTexture) : NULL);
+ msg->setObject("native-window", new NativeWindowWrapper(surfaceTextureClient));
+ msg->post();
+}
+
+void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
+ sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id());
+ msg->setObject("sink", sink);
+ msg->post();
+}
+
+void NuPlayer::start() {
+ (new AMessage(kWhatStart, id()))->post();
+}
+
+void NuPlayer::pause() {
+ (new AMessage(kWhatPause, id()))->post();
+}
+
+void NuPlayer::resume() {
+ (new AMessage(kWhatResume, id()))->post();
+}
+
+void NuPlayer::resetAsync() {
+ (new AMessage(kWhatReset, id()))->post();
+}
+
+void NuPlayer::seekToAsync(int64_t seekTimeUs) {
+ sp<AMessage> msg = new AMessage(kWhatSeek, id());
+ msg->setInt64("seekTimeUs", seekTimeUs);
+ msg->post();
+}
+
+// static
+bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
+ switch (state) {
+ case FLUSHING_DECODER:
+ if (needShutdown != NULL) {
+ *needShutdown = false;
+ }
+ return true;
+
+ case FLUSHING_DECODER_SHUTDOWN:
+ if (needShutdown != NULL) {
+ *needShutdown = true;
+ }
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatSetDataSource:
+ {
+ ALOGV("kWhatSetDataSource");
+
+ CHECK(mSource == NULL);
+
+ sp<RefBase> obj;
+ CHECK(msg->findObject("source", &obj));
+
+ mSource = static_cast<Source *>(obj.get());
+ break;
+ }
+
+ case kWhatSetVideoNativeWindow:
+ {
+ ALOGV("kWhatSetVideoNativeWindow");
+
+ sp<RefBase> obj;
+ CHECK(msg->findObject("native-window", &obj));
+
+ mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get());
+ break;
+ }
+
+ case kWhatSetAudioSink:
+ {
+ ALOGV("kWhatSetAudioSink");
+
+ sp<RefBase> obj;
+ CHECK(msg->findObject("sink", &obj));
+
+ mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
+ break;
+ }
+
+ case kWhatStart:
+ {
+ ALOGV("kWhatStart");
+
+ mVideoIsAVC = false;
+ mAudioEOS = false;
+ mVideoEOS = false;
+ mSkipRenderingAudioUntilMediaTimeUs = -1;
+ mSkipRenderingVideoUntilMediaTimeUs = -1;
+ mVideoLateByUs = 0;
+ mNumFramesTotal = 0;
+ mNumFramesDropped = 0;
+
+ mSource->start();
+
+ mRenderer = new Renderer(
+ mAudioSink,
+ new AMessage(kWhatRendererNotify, id()));
+
+ looper()->registerHandler(mRenderer);
+
+ postScanSources();
+ break;
+ }
+
+ case kWhatScanSources:
+ {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+ if (generation != mScanSourcesGeneration) {
+ // Drop obsolete msg.
+ break;
+ }
+
+ mScanSourcesPending = false;
+
+ ALOGV("scanning sources haveAudio=%d, haveVideo=%d",
+ mAudioDecoder != NULL, mVideoDecoder != NULL);
+
+ instantiateDecoder(false, &mVideoDecoder);
+
+ if (mAudioSink != NULL) {
+ instantiateDecoder(true, &mAudioDecoder);
+ }
+
+ status_t err;
+ if ((err = mSource->feedMoreTSData()) != OK) {
+ if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
+ // We're not currently decoding anything (no audio or
+ // video tracks found) and we just ran out of input data.
+
+ if (err == ERROR_END_OF_STREAM) {
+ notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
+ } else {
+ notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+ }
+ }
+ break;
+ }
+
+ if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
+ msg->post(100000ll);
+ mScanSourcesPending = true;
+ }
+ break;
+ }
+
+ case kWhatVideoNotify:
+ case kWhatAudioNotify:
+ {
+ bool audio = msg->what() == kWhatAudioNotify;
+
+ sp<AMessage> codecRequest;
+ CHECK(msg->findMessage("codec-request", &codecRequest));
+
+ int32_t what;
+ CHECK(codecRequest->findInt32("what", &what));
+
+ if (what == ACodec::kWhatFillThisBuffer) {
+ status_t err = feedDecoderInputData(
+ audio, codecRequest);
+
+ if (err == -EWOULDBLOCK) {
+ if (mSource->feedMoreTSData() == OK) {
+ msg->post(10000ll);
+ }
+ }
+ } else if (what == ACodec::kWhatEOS) {
+ int32_t err;
+ CHECK(codecRequest->findInt32("err", &err));
+
+ if (err == ERROR_END_OF_STREAM) {
+ ALOGV("got %s decoder EOS", audio ? "audio" : "video");
+ } else {
+ ALOGV("got %s decoder EOS w/ error %d",
+ audio ? "audio" : "video",
+ err);
+ }
+
+ mRenderer->queueEOS(audio, err);
+ } else if (what == ACodec::kWhatFlushCompleted) {
+ bool needShutdown;
+
+ if (audio) {
+ CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
+ mFlushingAudio = FLUSHED;
+ } else {
+ CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
+ mFlushingVideo = FLUSHED;
+
+ mVideoLateByUs = 0;
+ }
+
+ ALOGV("decoder %s flush completed", audio ? "audio" : "video");
+
+ if (needShutdown) {
+ ALOGV("initiating %s decoder shutdown",
+ audio ? "audio" : "video");
+
+ (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
+
+ if (audio) {
+ mFlushingAudio = SHUTTING_DOWN_DECODER;
+ } else {
+ mFlushingVideo = SHUTTING_DOWN_DECODER;
+ }
+ }
+
+ finishFlushIfPossible();
+ } else if (what == ACodec::kWhatOutputFormatChanged) {
+ if (audio) {
+ int32_t numChannels;
+ CHECK(codecRequest->findInt32("channel-count", &numChannels));
+
+ int32_t sampleRate;
+ CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
+
+ ALOGV("Audio output format changed to %d Hz, %d channels",
+ sampleRate, numChannels);
+
+ mAudioSink->close();
+ CHECK_EQ(mAudioSink->open(
+ sampleRate,
+ numChannels,
+ CHANNEL_MASK_USE_CHANNEL_ORDER,
+ AUDIO_FORMAT_PCM_16_BIT,
+ 8 /* bufferCount */),
+ (status_t)OK);
+ mAudioSink->start();
+
+ mRenderer->signalAudioSinkChanged();
+ } else {
+ // video
+
+ int32_t width, height;
+ CHECK(codecRequest->findInt32("width", &width));
+ CHECK(codecRequest->findInt32("height", &height));
+
+ int32_t cropLeft, cropTop, cropRight, cropBottom;
+ CHECK(codecRequest->findRect(
+ "crop",
+ &cropLeft, &cropTop, &cropRight, &cropBottom));
+
+ ALOGV("Video output format changed to %d x %d "
+ "(crop: %d x %d @ (%d, %d))",
+ width, height,
+ (cropRight - cropLeft + 1),
+ (cropBottom - cropTop + 1),
+ cropLeft, cropTop);
+
+ notifyListener(
+ MEDIA_SET_VIDEO_SIZE,
+ cropRight - cropLeft + 1,
+ cropBottom - cropTop + 1);
+ }
+ } else if (what == ACodec::kWhatShutdownCompleted) {
+ ALOGV("%s shutdown completed", audio ? "audio" : "video");
+ if (audio) {
+ mAudioDecoder.clear();
+
+ CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
+ mFlushingAudio = SHUT_DOWN;
+ } else {
+ mVideoDecoder.clear();
+
+ CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
+ mFlushingVideo = SHUT_DOWN;
+ }
+
+ finishFlushIfPossible();
+ } else if (what == ACodec::kWhatError) {
+ ALOGE("Received error from %s decoder, aborting playback.",
+ audio ? "audio" : "video");
+
+ mRenderer->queueEOS(audio, UNKNOWN_ERROR);
+ } else if (what == ACodec::kWhatDrainThisBuffer) {
+ renderBuffer(audio, codecRequest);
+ } else {
+ ALOGV("Unhandled codec notification %d.", what);
+ }
+
+ break;
+ }
+
+ case kWhatRendererNotify:
+ {
+ int32_t what;
+ CHECK(msg->findInt32("what", &what));
+
+ if (what == Renderer::kWhatEOS) {
+ int32_t audio;
+ CHECK(msg->findInt32("audio", &audio));
+
+ int32_t finalResult;
+ CHECK(msg->findInt32("finalResult", &finalResult));
+
+ if (audio) {
+ mAudioEOS = true;
+ } else {
+ mVideoEOS = true;
+ }
+
+ if (finalResult == ERROR_END_OF_STREAM) {
+ ALOGV("reached %s EOS", audio ? "audio" : "video");
+ } else {
+ ALOGE("%s track encountered an error (%d)",
+ audio ? "audio" : "video", finalResult);
+
+ notifyListener(
+ MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
+ }
+
+ if ((mAudioEOS || mAudioDecoder == NULL)
+ && (mVideoEOS || mVideoDecoder == NULL)) {
+ notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
+ }
+ } else if (what == Renderer::kWhatPosition) {
+ int64_t positionUs;
+ CHECK(msg->findInt64("positionUs", &positionUs));
+
+ CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
+
+ if (mDriver != NULL) {
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ driver->notifyPosition(positionUs);
+
+ driver->notifyFrameStats(
+ mNumFramesTotal, mNumFramesDropped);
+ }
+ }
+ } else if (what == Renderer::kWhatFlushComplete) {
+ CHECK_EQ(what, (int32_t)Renderer::kWhatFlushComplete);
+
+ int32_t audio;
+ CHECK(msg->findInt32("audio", &audio));
+
+ ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
+ }
+ break;
+ }
+
+ case kWhatMoreDataQueued:
+ {
+ break;
+ }
+
+ case kWhatReset:
+ {
+ ALOGV("kWhatReset");
+
+ if (mRenderer != NULL) {
+ // There's an edge case where the renderer owns all output
+ // buffers and is paused, therefore the decoder will not read
+ // more input data and will never encounter the matching
+ // discontinuity. To avoid this, we resume the renderer.
+
+ if (mFlushingAudio == AWAITING_DISCONTINUITY
+ || mFlushingVideo == AWAITING_DISCONTINUITY) {
+ mRenderer->resume();
+ }
+ }
+
+ if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
+ // We're currently flushing, postpone the reset until that's
+ // completed.
+
+ ALOGV("postponing reset mFlushingAudio=%d, mFlushingVideo=%d",
+ mFlushingAudio, mFlushingVideo);
+
+ mResetPostponed = true;
+ break;
+ }
+
+ if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
+ finishReset();
+ break;
+ }
+
+ mTimeDiscontinuityPending = true;
+
+ if (mAudioDecoder != NULL) {
+ flushDecoder(true /* audio */, true /* needShutdown */);
+ }
+
+ if (mVideoDecoder != NULL) {
+ flushDecoder(false /* audio */, true /* needShutdown */);
+ }
+
+ mResetInProgress = true;
+ break;
+ }
+
+ case kWhatSeek:
+ {
+ int64_t seekTimeUs;
+ CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
+
+ ALOGV("kWhatSeek seekTimeUs=%lld us (%.2f secs)",
+ seekTimeUs, seekTimeUs / 1E6);
+
+ mSource->seekTo(seekTimeUs);
+
+ if (mDriver != NULL) {
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ driver->notifySeekComplete();
+ }
+ }
+
+ break;
+ }
+
+ case kWhatPause:
+ {
+ CHECK(mRenderer != NULL);
+ mRenderer->pause();
+ break;
+ }
+
+ case kWhatResume:
+ {
+ CHECK(mRenderer != NULL);
+ mRenderer->resume();
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+void NuPlayer::finishFlushIfPossible() {
+ if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
+ return;
+ }
+
+ if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
+ return;
+ }
+
+ ALOGV("both audio and video are flushed now.");
+
+ if (mTimeDiscontinuityPending) {
+ mRenderer->signalTimeDiscontinuity();
+ mTimeDiscontinuityPending = false;
+ }
+
+ if (mAudioDecoder != NULL) {
+ mAudioDecoder->signalResume();
+ }
+
+ if (mVideoDecoder != NULL) {
+ mVideoDecoder->signalResume();
+ }
+
+ mFlushingAudio = NONE;
+ mFlushingVideo = NONE;
+
+ if (mResetInProgress) {
+ ALOGV("reset completed");
+
+ mResetInProgress = false;
+ finishReset();
+ } else if (mResetPostponed) {
+ (new AMessage(kWhatReset, id()))->post();
+ mResetPostponed = false;
+ } else if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
+ postScanSources();
+ }
+}
+
+void NuPlayer::finishReset() {
+ CHECK(mAudioDecoder == NULL);
+ CHECK(mVideoDecoder == NULL);
+
+ ++mScanSourcesGeneration;
+ mScanSourcesPending = false;
+
+ mRenderer.clear();
+
+ if (mSource != NULL) {
+ mSource->stop();
+ mSource.clear();
+ }
+
+ if (mDriver != NULL) {
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ driver->notifyResetComplete();
+ }
+ }
+}
+
+void NuPlayer::postScanSources() {
+ if (mScanSourcesPending) {
+ return;
+ }
+
+ sp<AMessage> msg = new AMessage(kWhatScanSources, id());
+ msg->setInt32("generation", mScanSourcesGeneration);
+ msg->post();
+
+ mScanSourcesPending = true;
+}
+
+status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
+ if (*decoder != NULL) {
+ return OK;
+ }
+
+ sp<MetaData> meta = mSource->getFormat(audio);
+
+ if (meta == NULL) {
+ return -EWOULDBLOCK;
+ }
+
+ if (!audio) {
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+ mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime);
+ }
+
+ sp<AMessage> notify =
+ new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
+ id());
+
+ *decoder = audio ? new Decoder(notify) :
+ new Decoder(notify, mNativeWindow);
+ looper()->registerHandler(*decoder);
+
+ (*decoder)->configure(meta);
+
+ int64_t durationUs;
+ if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
+ sp<NuPlayerDriver> driver = mDriver.promote();
+ if (driver != NULL) {
+ driver->notifyDuration(durationUs);
+ }
+ }
+
+ return OK;
+}
+
+status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
+ sp<AMessage> reply;
+ CHECK(msg->findMessage("reply", &reply));
+
+ if ((audio && IsFlushingState(mFlushingAudio))
+ || (!audio && IsFlushingState(mFlushingVideo))) {
+ reply->setInt32("err", INFO_DISCONTINUITY);
+ reply->post();
+ return OK;
+ }
+
+ sp<ABuffer> accessUnit;
+
+ bool dropAccessUnit;
+ do {
+ status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
+
+ if (err == -EWOULDBLOCK) {
+ return err;
+ } else if (err != OK) {
+ if (err == INFO_DISCONTINUITY) {
+ int32_t type;
+ CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
+
+ bool formatChange =
+ (audio &&
+ (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
+ || (!audio &&
+ (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
+
+ bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
+
+ ALOGI("%s discontinuity (formatChange=%d, time=%d)",
+ audio ? "audio" : "video", formatChange, timeChange);
+
+ if (audio) {
+ mSkipRenderingAudioUntilMediaTimeUs = -1;
+ } else {
+ mSkipRenderingVideoUntilMediaTimeUs = -1;
+ }
+
+ if (timeChange) {
+ sp<AMessage> extra;
+ if (accessUnit->meta()->findMessage("extra", &extra)
+ && extra != NULL) {
+ int64_t resumeAtMediaTimeUs;
+ if (extra->findInt64(
+ "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
+ ALOGI("suppressing rendering of %s until %lld us",
+ audio ? "audio" : "video", resumeAtMediaTimeUs);
+
+ if (audio) {
+ mSkipRenderingAudioUntilMediaTimeUs =
+ resumeAtMediaTimeUs;
+ } else {
+ mSkipRenderingVideoUntilMediaTimeUs =
+ resumeAtMediaTimeUs;
+ }
+ }
+ }
+ }
+
+ mTimeDiscontinuityPending =
+ mTimeDiscontinuityPending || timeChange;
+
+ if (formatChange || timeChange) {
+ flushDecoder(audio, formatChange);
+ } else {
+ // This stream is unaffected by the discontinuity
+
+ if (audio) {
+ mFlushingAudio = FLUSHED;
+ } else {
+ mFlushingVideo = FLUSHED;
+ }
+
+ finishFlushIfPossible();
+
+ return -EWOULDBLOCK;
+ }
+ }
+
+ reply->setInt32("err", err);
+ reply->post();
+ return OK;
+ }
+
+ if (!audio) {
+ ++mNumFramesTotal;
+ }
+
+ dropAccessUnit = false;
+ if (!audio
+ && mVideoLateByUs > 100000ll
+ && mVideoIsAVC
+ && !IsAVCReferenceFrame(accessUnit)) {
+ dropAccessUnit = true;
+ ++mNumFramesDropped;
+ }
+ } while (dropAccessUnit);
+
+ // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
+
+#if 0
+ int64_t mediaTimeUs;
+ CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
+ ALOGV("feeding %s input buffer at media time %.2f secs",
+ audio ? "audio" : "video",
+ mediaTimeUs / 1E6);
+#endif
+
+ reply->setBuffer("buffer", accessUnit);
+ reply->post();
+
+ return OK;
+}
+
+void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
+ // ALOGV("renderBuffer %s", audio ? "audio" : "video");
+
+ sp<AMessage> reply;
+ CHECK(msg->findMessage("reply", &reply));
+
+ if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
+ // We're currently attempting to flush the decoder, in order
+ // to complete this, the decoder wants all its buffers back,
+ // so we don't want any output buffers it sent us (from before
+ // we initiated the flush) to be stuck in the renderer's queue.
+
+ ALOGV("we're still flushing the %s decoder, sending its output buffer"
+ " right back.", audio ? "audio" : "video");
+
+ reply->post();
+ return;
+ }
+
+ sp<ABuffer> buffer;
+ CHECK(msg->findBuffer("buffer", &buffer));
+
+ int64_t &skipUntilMediaTimeUs =
+ audio
+ ? mSkipRenderingAudioUntilMediaTimeUs
+ : mSkipRenderingVideoUntilMediaTimeUs;
+
+ if (skipUntilMediaTimeUs >= 0) {
+ int64_t mediaTimeUs;
+ CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
+
+ if (mediaTimeUs < skipUntilMediaTimeUs) {
+ ALOGV("dropping %s buffer at time %lld as requested.",
+ audio ? "audio" : "video",
+ mediaTimeUs);
+
+ reply->post();
+ return;
+ }
+
+ skipUntilMediaTimeUs = -1;
+ }
+
+ mRenderer->queueBuffer(audio, buffer, reply);
+}
+
+void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
+ if (mDriver == NULL) {
+ return;
+ }
+
+ sp<NuPlayerDriver> driver = mDriver.promote();
+
+ if (driver == NULL) {
+ return;
+ }
+
+ driver->notifyListener(msg, ext1, ext2);
+}
+
+void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
+ if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
+ ALOGI("flushDecoder %s without decoder present",
+ audio ? "audio" : "video");
+ }
+
+ // Make sure we don't continue to scan sources until we finish flushing.
+ ++mScanSourcesGeneration;
+ mScanSourcesPending = false;
+
+ (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
+ mRenderer->flush(audio);
+
+ FlushStatus newStatus =
+ needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
+
+ if (audio) {
+ CHECK(mFlushingAudio == NONE
+ || mFlushingAudio == AWAITING_DISCONTINUITY);
+
+ mFlushingAudio = newStatus;
+
+ if (mFlushingVideo == NONE) {
+ mFlushingVideo = (mVideoDecoder != NULL)
+ ? AWAITING_DISCONTINUITY
+ : FLUSHED;
+ }
+ } else {
+ CHECK(mFlushingVideo == NONE
+ || mFlushingVideo == AWAITING_DISCONTINUITY);
+
+ mFlushingVideo = newStatus;
+
+ if (mFlushingAudio == NONE) {
+ mFlushingAudio = (mAudioDecoder != NULL)
+ ? AWAITING_DISCONTINUITY
+ : FLUSHED;
+ }
+ }
+}
+
+} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
new file mode 100644
index 0000000..25766e0
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -0,0 +1,152 @@
+/*
+ * 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_PLAYER_H_
+
+#define NU_PLAYER_H_
+
+#include <media/MediaPlayerInterface.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/NativeWindowWrapper.h>
+
+namespace android {
+
+struct ACodec;
+struct MetaData;
+struct NuPlayerDriver;
+
+struct NuPlayer : public AHandler {
+ NuPlayer();
+
+ void setUID(uid_t uid);
+
+ void setDriver(const wp<NuPlayerDriver> &driver);
+
+ void setDataSource(const sp<IStreamSource> &source);
+
+ void setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers);
+
+ void setDataSource(int fd, int64_t offset, int64_t length);
+
+ void setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture);
+ void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink);
+ void start();
+
+ void pause();
+ void resume();
+
+ // Will notify the driver through "notifyResetComplete" once finished.
+ void resetAsync();
+
+ // Will notify the driver through "notifySeekComplete" once finished.
+ void seekToAsync(int64_t seekTimeUs);
+
+protected:
+ virtual ~NuPlayer();
+
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+ struct Decoder;
+ struct GenericSource;
+ struct HTTPLiveSource;
+ struct NuPlayerStreamListener;
+ struct Renderer;
+ struct RTSPSource;
+ struct Source;
+ struct StreamingSource;
+
+ enum {
+ kWhatSetDataSource = '=DaS',
+ kWhatSetVideoNativeWindow = '=NaW',
+ kWhatSetAudioSink = '=AuS',
+ kWhatMoreDataQueued = 'more',
+ kWhatStart = 'strt',
+ kWhatScanSources = 'scan',
+ kWhatVideoNotify = 'vidN',
+ kWhatAudioNotify = 'audN',
+ kWhatRendererNotify = 'renN',
+ kWhatReset = 'rset',
+ kWhatSeek = 'seek',
+ kWhatPause = 'paus',
+ kWhatResume = 'rsme',
+ };
+
+ wp<NuPlayerDriver> mDriver;
+ bool mUIDValid;
+ uid_t mUID;
+ sp<Source> mSource;
+ sp<NativeWindowWrapper> mNativeWindow;
+ sp<MediaPlayerBase::AudioSink> mAudioSink;
+ sp<Decoder> mVideoDecoder;
+ bool mVideoIsAVC;
+ sp<Decoder> mAudioDecoder;
+ sp<Renderer> mRenderer;
+
+ bool mAudioEOS;
+ bool mVideoEOS;
+
+ bool mScanSourcesPending;
+ int32_t mScanSourcesGeneration;
+
+ enum FlushStatus {
+ NONE,
+ AWAITING_DISCONTINUITY,
+ FLUSHING_DECODER,
+ FLUSHING_DECODER_SHUTDOWN,
+ SHUTTING_DOWN_DECODER,
+ FLUSHED,
+ SHUT_DOWN,
+ };
+
+ // Once the current flush is complete this indicates whether the
+ // notion of time has changed.
+ bool mTimeDiscontinuityPending;
+
+ FlushStatus mFlushingAudio;
+ FlushStatus mFlushingVideo;
+ bool mResetInProgress;
+ bool mResetPostponed;
+
+ int64_t mSkipRenderingAudioUntilMediaTimeUs;
+ int64_t mSkipRenderingVideoUntilMediaTimeUs;
+
+ int64_t mVideoLateByUs;
+ int64_t mNumFramesTotal, mNumFramesDropped;
+
+ status_t instantiateDecoder(bool audio, sp<Decoder> *decoder);
+
+ status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg);
+ void renderBuffer(bool audio, const sp<AMessage> &msg);
+
+ void notifyListener(int msg, int ext1, int ext2);
+
+ void finishFlushIfPossible();
+
+ void flushDecoder(bool audio, bool needShutdown);
+
+ static bool IsFlushingState(FlushStatus state, bool *needShutdown = NULL);
+
+ void finishReset();
+ void postScanSources();
+
+ DISALLOW_EVIL_CONSTRUCTORS(NuPlayer);
+};
+
+} // namespace android
+
+#endif // NU_PLAYER_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
new file mode 100644
index 0000000..5733229
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.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 "NuPlayerDecoder"
+#include <utils/Log.h>
+
+#include "NuPlayerDecoder.h"
+
+#include "ESDS.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/ACodec.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+NuPlayer::Decoder::Decoder(
+ const sp<AMessage> &notify,
+ const sp<NativeWindowWrapper> &nativeWindow)
+ : mNotify(notify),
+ mNativeWindow(nativeWindow) {
+}
+
+NuPlayer::Decoder::~Decoder() {
+}
+
+void NuPlayer::Decoder::configure(const sp<MetaData> &meta) {
+ CHECK(mCodec == NULL);
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ sp<AMessage> notifyMsg =
+ new AMessage(kWhatCodecNotify, id());
+
+ sp<AMessage> format = makeFormat(meta);
+
+ if (mNativeWindow != NULL) {
+ format->setObject("native-window", mNativeWindow);
+ }
+
+ // Current video decoders do not return from OMX_FillThisBuffer
+ // quickly, violating the OpenMAX specs, until that is remedied
+ // we need to invest in an extra looper to free the main event
+ // queue.
+ bool needDedicatedLooper = !strncasecmp(mime, "video/", 6);
+
+ mCodec = new ACodec;
+
+ if (needDedicatedLooper && mCodecLooper == NULL) {
+ mCodecLooper = new ALooper;
+ mCodecLooper->setName("NuPlayerDecoder");
+ mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
+ }
+
+ (needDedicatedLooper ? mCodecLooper : looper())->registerHandler(mCodec);
+
+ mCodec->setNotificationMessage(notifyMsg);
+ mCodec->initiateSetup(format);
+}
+
+void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatCodecNotify:
+ {
+ int32_t what;
+ CHECK(msg->findInt32("what", &what));
+
+ if (what == ACodec::kWhatFillThisBuffer) {
+ onFillThisBuffer(msg);
+ } else {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setMessage("codec-request", msg);
+ notify->post();
+ }
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+sp<AMessage> NuPlayer::Decoder::makeFormat(const sp<MetaData> &meta) {
+ CHECK(mCSD.isEmpty());
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ sp<AMessage> msg = new AMessage;
+ msg->setString("mime", mime);
+
+ if (!strncasecmp("video/", mime, 6)) {
+ int32_t width, height;
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+
+ msg->setInt32("width", width);
+ msg->setInt32("height", height);
+ } else {
+ CHECK(!strncasecmp("audio/", mime, 6));
+
+ int32_t numChannels, sampleRate;
+ CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
+ CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+
+ msg->setInt32("channel-count", numChannels);
+ msg->setInt32("sample-rate", sampleRate);
+
+ int32_t isADTS;
+ if (meta->findInt32(kKeyIsADTS, &isADTS) && isADTS != 0) {
+ msg->setInt32("is-adts", true);
+ }
+ }
+
+ int32_t maxInputSize;
+ if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
+ msg->setInt32("max-input-size", maxInputSize);
+ }
+
+ mCSDIndex = 0;
+
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (meta->findData(kKeyAVCC, &type, &data, &size)) {
+ // Parse the AVCDecoderConfigurationRecord
+
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ CHECK(size >= 7);
+ CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
+ uint8_t profile = ptr[1];
+ uint8_t level = ptr[3];
+
+ // There is decodable content out there that fails the following
+ // assertion, let's be lenient for now...
+ // CHECK((ptr[4] >> 2) == 0x3f); // reserved
+
+ size_t lengthSize = 1 + (ptr[4] & 3);
+
+ // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
+ // violates it...
+ // CHECK((ptr[5] >> 5) == 7); // reserved
+
+ size_t numSeqParameterSets = ptr[5] & 31;
+
+ ptr += 6;
+ size -= 6;
+
+ sp<ABuffer> buffer = new ABuffer(1024);
+ buffer->setRange(0, 0);
+
+ for (size_t i = 0; i < numSeqParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ CHECK(size >= length);
+
+ memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
+ memcpy(buffer->data() + buffer->size() + 4, ptr, length);
+ buffer->setRange(0, buffer->size() + 4 + length);
+
+ ptr += length;
+ size -= length;
+ }
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
+
+ buffer = new ABuffer(1024);
+ buffer->setRange(0, 0);
+
+ CHECK(size >= 1);
+ size_t numPictureParameterSets = *ptr;
+ ++ptr;
+ --size;
+
+ for (size_t i = 0; i < numPictureParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ CHECK(size >= length);
+
+ memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
+ memcpy(buffer->data() + buffer->size() + 4, ptr, length);
+ buffer->setRange(0, buffer->size() + 4 + length);
+
+ ptr += length;
+ size -= length;
+ }
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
+ } else if (meta->findData(kKeyESDS, &type, &data, &size)) {
+ ESDS esds((const char *)data, size);
+ CHECK_EQ(esds.InitCheck(), (status_t)OK);
+
+ const void *codec_specific_data;
+ size_t codec_specific_data_size;
+ esds.getCodecSpecificInfo(
+ &codec_specific_data, &codec_specific_data_size);
+
+ sp<ABuffer> buffer = new ABuffer(codec_specific_data_size);
+
+ memcpy(buffer->data(), codec_specific_data,
+ codec_specific_data_size);
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
+ } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
+ sp<ABuffer> buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
+
+ CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
+
+ buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+
+ buffer->meta()->setInt32("csd", true);
+ mCSD.push(buffer);
+ }
+
+ return msg;
+}
+
+void NuPlayer::Decoder::onFillThisBuffer(const sp<AMessage> &msg) {
+ sp<AMessage> reply;
+ CHECK(msg->findMessage("reply", &reply));
+
+#if 0
+ sp<ABuffer> outBuffer;
+ CHECK(msg->findBuffer("buffer", &outBuffer));
+#else
+ sp<ABuffer> outBuffer;
+#endif
+
+ if (mCSDIndex < mCSD.size()) {
+ outBuffer = mCSD.editItemAt(mCSDIndex++);
+ outBuffer->meta()->setInt64("timeUs", 0);
+
+ reply->setBuffer("buffer", outBuffer);
+ reply->post();
+ return;
+ }
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setMessage("codec-request", msg);
+ notify->post();
+}
+
+void NuPlayer::Decoder::signalFlush() {
+ if (mCodec != NULL) {
+ mCodec->signalFlush();
+ }
+}
+
+void NuPlayer::Decoder::signalResume() {
+ if (mCodec != NULL) {
+ mCodec->signalResume();
+ }
+}
+
+void NuPlayer::Decoder::initiateShutdown() {
+ if (mCodec != NULL) {
+ mCodec->initiateShutdown();
+ }
+}
+
+} // namespace android
+
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
new file mode 100644
index 0000000..3ab1fcf
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.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 NUPLAYER_DECODER_H_
+
+#define NUPLAYER_DECODER_H_
+
+#include "NuPlayer.h"
+
+#include <media/stagefright/foundation/AHandler.h>
+
+namespace android {
+
+struct ABuffer;
+
+struct NuPlayer::Decoder : public AHandler {
+ Decoder(const sp<AMessage> &notify,
+ const sp<NativeWindowWrapper> &nativeWindow = NULL);
+
+ void configure(const sp<MetaData> &meta);
+
+ void signalFlush();
+ void signalResume();
+ void initiateShutdown();
+
+protected:
+ virtual ~Decoder();
+
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+ enum {
+ kWhatCodecNotify = 'cdcN',
+ };
+
+ sp<AMessage> mNotify;
+ sp<NativeWindowWrapper> mNativeWindow;
+
+ sp<ACodec> mCodec;
+ sp<ALooper> mCodecLooper;
+
+ Vector<sp<ABuffer> > mCSD;
+ size_t mCSDIndex;
+
+ sp<AMessage> makeFormat(const sp<MetaData> &meta);
+
+ void onFillThisBuffer(const sp<AMessage> &msg);
+
+ DISALLOW_EVIL_CONSTRUCTORS(Decoder);
+};
+
+} // namespace android
+
+#endif // NUPLAYER_DECODER_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
new file mode 100644
index 0000000..253bc2f
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -0,0 +1,337 @@
+/*
+ * 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 "NuPlayerDriver"
+#include <utils/Log.h>
+
+#include "NuPlayerDriver.h"
+
+#include "NuPlayer.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+
+namespace android {
+
+NuPlayerDriver::NuPlayerDriver()
+ : mResetInProgress(false),
+ mDurationUs(-1),
+ mPositionUs(-1),
+ mNumFramesTotal(0),
+ mNumFramesDropped(0),
+ mLooper(new ALooper),
+ mState(UNINITIALIZED),
+ mAtEOS(false),
+ mStartupSeekTimeUs(-1) {
+ mLooper->setName("NuPlayerDriver Looper");
+
+ mLooper->start(
+ false, /* runOnCallingThread */
+ true, /* canCallJava */
+ PRIORITY_AUDIO);
+
+ mPlayer = new NuPlayer;
+ mLooper->registerHandler(mPlayer);
+
+ mPlayer->setDriver(this);
+}
+
+NuPlayerDriver::~NuPlayerDriver() {
+ mLooper->stop();
+}
+
+status_t NuPlayerDriver::initCheck() {
+ return OK;
+}
+
+status_t NuPlayerDriver::setUID(uid_t uid) {
+ mPlayer->setUID(uid);
+
+ return OK;
+}
+
+status_t NuPlayerDriver::setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers) {
+ CHECK_EQ((int)mState, (int)UNINITIALIZED);
+
+ mPlayer->setDataSource(url, headers);
+
+ mState = STOPPED;
+
+ return OK;
+}
+
+status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
+ CHECK_EQ((int)mState, (int)UNINITIALIZED);
+
+ mPlayer->setDataSource(fd, offset, length);
+
+ mState = STOPPED;
+
+ return OK;
+}
+
+status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) {
+ CHECK_EQ((int)mState, (int)UNINITIALIZED);
+
+ mPlayer->setDataSource(source);
+
+ mState = STOPPED;
+
+ return OK;
+}
+
+status_t NuPlayerDriver::setVideoSurfaceTexture(
+ const sp<ISurfaceTexture> &surfaceTexture) {
+ mPlayer->setVideoSurfaceTexture(surfaceTexture);
+
+ return OK;
+}
+
+status_t NuPlayerDriver::prepare() {
+ sendEvent(MEDIA_SET_VIDEO_SIZE, 320, 240);
+ return OK;
+}
+
+status_t NuPlayerDriver::prepareAsync() {
+ status_t err = prepare();
+
+ notifyListener(MEDIA_PREPARED);
+
+ return err;
+}
+
+status_t NuPlayerDriver::start() {
+ switch (mState) {
+ case UNINITIALIZED:
+ return INVALID_OPERATION;
+ case STOPPED:
+ {
+ mAtEOS = false;
+ mPlayer->start();
+
+ if (mStartupSeekTimeUs >= 0) {
+ if (mStartupSeekTimeUs == 0) {
+ notifySeekComplete();
+ } else {
+ mPlayer->seekToAsync(mStartupSeekTimeUs);
+ }
+
+ mStartupSeekTimeUs = -1;
+ }
+
+ break;
+ }
+ case PLAYING:
+ return OK;
+ default:
+ {
+ CHECK_EQ((int)mState, (int)PAUSED);
+
+ mPlayer->resume();
+ break;
+ }
+ }
+
+ mState = PLAYING;
+
+ return OK;
+}
+
+status_t NuPlayerDriver::stop() {
+ return pause();
+}
+
+status_t NuPlayerDriver::pause() {
+ switch (mState) {
+ case UNINITIALIZED:
+ return INVALID_OPERATION;
+ case STOPPED:
+ return OK;
+ case PLAYING:
+ mPlayer->pause();
+ break;
+ default:
+ {
+ CHECK_EQ((int)mState, (int)PAUSED);
+ return OK;
+ }
+ }
+
+ mState = PAUSED;
+
+ return OK;
+}
+
+bool NuPlayerDriver::isPlaying() {
+ return mState == PLAYING && !mAtEOS;
+}
+
+status_t NuPlayerDriver::seekTo(int msec) {
+ int64_t seekTimeUs = msec * 1000ll;
+
+ switch (mState) {
+ case UNINITIALIZED:
+ return INVALID_OPERATION;
+ case STOPPED:
+ {
+ mStartupSeekTimeUs = seekTimeUs;
+ break;
+ }
+ case PLAYING:
+ case PAUSED:
+ {
+ mAtEOS = false;
+ mPlayer->seekToAsync(seekTimeUs);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+
+ return OK;
+}
+
+status_t NuPlayerDriver::getCurrentPosition(int *msec) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mPositionUs < 0) {
+ *msec = 0;
+ } else {
+ *msec = (mPositionUs + 500ll) / 1000;
+ }
+
+ return OK;
+}
+
+status_t NuPlayerDriver::getDuration(int *msec) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mDurationUs < 0) {
+ *msec = 0;
+ } else {
+ *msec = (mDurationUs + 500ll) / 1000;
+ }
+
+ return OK;
+}
+
+status_t NuPlayerDriver::reset() {
+ Mutex::Autolock autoLock(mLock);
+ mResetInProgress = true;
+
+ mPlayer->resetAsync();
+
+ while (mResetInProgress) {
+ mCondition.wait(mLock);
+ }
+
+ mDurationUs = -1;
+ mPositionUs = -1;
+ mState = UNINITIALIZED;
+ mStartupSeekTimeUs = -1;
+
+ return OK;
+}
+
+status_t NuPlayerDriver::setLooping(int loop) {
+ return INVALID_OPERATION;
+}
+
+player_type NuPlayerDriver::playerType() {
+ return NU_PLAYER;
+}
+
+status_t NuPlayerDriver::invoke(const Parcel &request, Parcel *reply) {
+ return INVALID_OPERATION;
+}
+
+void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) {
+ mPlayer->setAudioSink(audioSink);
+}
+
+status_t NuPlayerDriver::setParameter(int key, const Parcel &request) {
+ return INVALID_OPERATION;
+}
+
+status_t NuPlayerDriver::getParameter(int key, Parcel *reply) {
+ return INVALID_OPERATION;
+}
+
+status_t NuPlayerDriver::getMetadata(
+ const media::Metadata::Filter& ids, Parcel *records) {
+ return INVALID_OPERATION;
+}
+
+void NuPlayerDriver::notifyResetComplete() {
+ Mutex::Autolock autoLock(mLock);
+ CHECK(mResetInProgress);
+ mResetInProgress = false;
+ mCondition.broadcast();
+}
+
+void NuPlayerDriver::notifyDuration(int64_t durationUs) {
+ Mutex::Autolock autoLock(mLock);
+ mDurationUs = durationUs;
+}
+
+void NuPlayerDriver::notifyPosition(int64_t positionUs) {
+ Mutex::Autolock autoLock(mLock);
+ mPositionUs = positionUs;
+}
+
+void NuPlayerDriver::notifySeekComplete() {
+ notifyListener(MEDIA_SEEK_COMPLETE);
+}
+
+void NuPlayerDriver::notifyFrameStats(
+ int64_t numFramesTotal, int64_t numFramesDropped) {
+ Mutex::Autolock autoLock(mLock);
+ mNumFramesTotal = numFramesTotal;
+ mNumFramesDropped = numFramesDropped;
+}
+
+status_t NuPlayerDriver::dump(int fd, const Vector<String16> &args) const {
+ Mutex::Autolock autoLock(mLock);
+
+ FILE *out = fdopen(dup(fd), "w");
+
+ fprintf(out, " NuPlayer\n");
+ fprintf(out, " numFramesTotal(%lld), numFramesDropped(%lld), "
+ "percentageDropped(%.2f)\n",
+ mNumFramesTotal,
+ mNumFramesDropped,
+ mNumFramesTotal == 0
+ ? 0.0 : (double)mNumFramesDropped / mNumFramesTotal);
+
+ fclose(out);
+ out = NULL;
+
+ return OK;
+}
+
+void NuPlayerDriver::notifyListener(int msg, int ext1, int ext2) {
+ if (msg == MEDIA_PLAYBACK_COMPLETE || msg == MEDIA_ERROR) {
+ mAtEOS = true;
+ }
+
+ sendEvent(msg, ext1, ext2);
+}
+
+} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
new file mode 100644
index 0000000..4a0026c
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -0,0 +1,107 @@
+/*
+ * 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 <media/MediaPlayerInterface.h>
+
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+
+struct ALooper;
+struct NuPlayer;
+
+struct NuPlayerDriver : public MediaPlayerInterface {
+ NuPlayerDriver();
+
+ virtual status_t initCheck();
+
+ virtual status_t setUID(uid_t uid);
+
+ virtual status_t setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers);
+
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
+
+ virtual status_t setDataSource(const sp<IStreamSource> &source);
+
+ virtual status_t setVideoSurfaceTexture(
+ const sp<ISurfaceTexture> &surfaceTexture);
+ virtual status_t prepare();
+ virtual status_t prepareAsync();
+ virtual status_t start();
+ virtual status_t stop();
+ virtual status_t pause();
+ virtual bool isPlaying();
+ virtual status_t seekTo(int msec);
+ virtual status_t getCurrentPosition(int *msec);
+ virtual status_t getDuration(int *msec);
+ virtual status_t reset();
+ virtual status_t setLooping(int loop);
+ virtual player_type playerType();
+ virtual status_t invoke(const Parcel &request, Parcel *reply);
+ virtual void setAudioSink(const sp<AudioSink> &audioSink);
+ virtual status_t setParameter(int key, const Parcel &request);
+ virtual status_t getParameter(int key, Parcel *reply);
+
+ virtual status_t getMetadata(
+ const media::Metadata::Filter& ids, Parcel *records);
+
+ virtual status_t dump(int fd, const Vector<String16> &args) const;
+
+ void notifyResetComplete();
+ void notifyDuration(int64_t durationUs);
+ void notifyPosition(int64_t positionUs);
+ void notifySeekComplete();
+ void notifyFrameStats(int64_t numFramesTotal, int64_t numFramesDropped);
+ void notifyListener(int msg, int ext1 = 0, int ext2 = 0);
+
+protected:
+ virtual ~NuPlayerDriver();
+
+private:
+ mutable Mutex mLock;
+ Condition mCondition;
+
+ // The following are protected through "mLock"
+ // >>>
+ bool mResetInProgress;
+ int64_t mDurationUs;
+ int64_t mPositionUs;
+ int64_t mNumFramesTotal;
+ int64_t mNumFramesDropped;
+ // <<<
+
+ sp<ALooper> mLooper;
+ sp<NuPlayer> mPlayer;
+
+ enum State {
+ UNINITIALIZED,
+ STOPPED,
+ PLAYING,
+ PAUSED
+ };
+
+ State mState;
+ bool mAtEOS;
+
+ int64_t mStartupSeekTimeUs;
+
+ DISALLOW_EVIL_CONSTRUCTORS(NuPlayerDriver);
+};
+
+} // namespace android
+
+
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
new file mode 100644
index 0000000..ecbc428
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -0,0 +1,658 @@
+/*
+ * 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 "NuPlayerRenderer"
+#include <utils/Log.h>
+
+#include "NuPlayerRenderer.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+namespace android {
+
+// static
+const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
+
+NuPlayer::Renderer::Renderer(
+ const sp<MediaPlayerBase::AudioSink> &sink,
+ const sp<AMessage> &notify)
+ : mAudioSink(sink),
+ mNotify(notify),
+ mNumFramesWritten(0),
+ mDrainAudioQueuePending(false),
+ mDrainVideoQueuePending(false),
+ mAudioQueueGeneration(0),
+ mVideoQueueGeneration(0),
+ mAnchorTimeMediaUs(-1),
+ mAnchorTimeRealUs(-1),
+ mFlushingAudio(false),
+ mFlushingVideo(false),
+ mHasAudio(false),
+ mHasVideo(false),
+ mSyncQueues(false),
+ mPaused(false),
+ mLastPositionUpdateUs(-1ll),
+ mVideoLateByUs(0ll) {
+}
+
+NuPlayer::Renderer::~Renderer() {
+}
+
+void NuPlayer::Renderer::queueBuffer(
+ bool audio,
+ const sp<ABuffer> &buffer,
+ const sp<AMessage> &notifyConsumed) {
+ sp<AMessage> msg = new AMessage(kWhatQueueBuffer, id());
+ msg->setInt32("audio", static_cast<int32_t>(audio));
+ msg->setBuffer("buffer", buffer);
+ msg->setMessage("notifyConsumed", notifyConsumed);
+ msg->post();
+}
+
+void NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
+ CHECK_NE(finalResult, (status_t)OK);
+
+ sp<AMessage> msg = new AMessage(kWhatQueueEOS, id());
+ msg->setInt32("audio", static_cast<int32_t>(audio));
+ msg->setInt32("finalResult", finalResult);
+ msg->post();
+}
+
+void NuPlayer::Renderer::flush(bool audio) {
+ {
+ Mutex::Autolock autoLock(mFlushLock);
+ if (audio) {
+ CHECK(!mFlushingAudio);
+ mFlushingAudio = true;
+ } else {
+ CHECK(!mFlushingVideo);
+ mFlushingVideo = true;
+ }
+ }
+
+ sp<AMessage> msg = new AMessage(kWhatFlush, id());
+ msg->setInt32("audio", static_cast<int32_t>(audio));
+ msg->post();
+}
+
+void NuPlayer::Renderer::signalTimeDiscontinuity() {
+ CHECK(mAudioQueue.empty());
+ CHECK(mVideoQueue.empty());
+ mAnchorTimeMediaUs = -1;
+ mAnchorTimeRealUs = -1;
+ mSyncQueues = mHasAudio && mHasVideo;
+}
+
+void NuPlayer::Renderer::pause() {
+ (new AMessage(kWhatPause, id()))->post();
+}
+
+void NuPlayer::Renderer::resume() {
+ (new AMessage(kWhatResume, id()))->post();
+}
+
+void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatDrainAudioQueue:
+ {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+ if (generation != mAudioQueueGeneration) {
+ break;
+ }
+
+ mDrainAudioQueuePending = false;
+
+ if (onDrainAudioQueue()) {
+ uint32_t numFramesPlayed;
+ CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
+ (status_t)OK);
+
+ uint32_t numFramesPendingPlayout =
+ mNumFramesWritten - numFramesPlayed;
+
+ // This is how long the audio sink will have data to
+ // play back.
+ int64_t delayUs =
+ mAudioSink->msecsPerFrame()
+ * numFramesPendingPlayout * 1000ll;
+
+ // Let's give it more data after about half that time
+ // has elapsed.
+ postDrainAudioQueue(delayUs / 2);
+ }
+ break;
+ }
+
+ case kWhatDrainVideoQueue:
+ {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+ if (generation != mVideoQueueGeneration) {
+ break;
+ }
+
+ mDrainVideoQueuePending = false;
+
+ onDrainVideoQueue();
+
+ postDrainVideoQueue();
+ break;
+ }
+
+ case kWhatQueueBuffer:
+ {
+ onQueueBuffer(msg);
+ break;
+ }
+
+ case kWhatQueueEOS:
+ {
+ onQueueEOS(msg);
+ break;
+ }
+
+ case kWhatFlush:
+ {
+ onFlush(msg);
+ break;
+ }
+
+ case kWhatAudioSinkChanged:
+ {
+ onAudioSinkChanged();
+ break;
+ }
+
+ case kWhatPause:
+ {
+ onPause();
+ break;
+ }
+
+ case kWhatResume:
+ {
+ onResume();
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+void NuPlayer::Renderer::postDrainAudioQueue(int64_t delayUs) {
+ if (mDrainAudioQueuePending || mSyncQueues || mPaused) {
+ return;
+ }
+
+ if (mAudioQueue.empty()) {
+ return;
+ }
+
+ mDrainAudioQueuePending = true;
+ sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, id());
+ msg->setInt32("generation", mAudioQueueGeneration);
+ msg->post(delayUs);
+}
+
+void NuPlayer::Renderer::signalAudioSinkChanged() {
+ (new AMessage(kWhatAudioSinkChanged, id()))->post();
+}
+
+bool NuPlayer::Renderer::onDrainAudioQueue() {
+ uint32_t numFramesPlayed;
+ if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
+ return false;
+ }
+
+ ssize_t numFramesAvailableToWrite =
+ mAudioSink->frameCount() - (mNumFramesWritten - numFramesPlayed);
+
+#if 0
+ if (numFramesAvailableToWrite == mAudioSink->frameCount()) {
+ ALOGI("audio sink underrun");
+ } else {
+ ALOGV("audio queue has %d frames left to play",
+ mAudioSink->frameCount() - numFramesAvailableToWrite);
+ }
+#endif
+
+ size_t numBytesAvailableToWrite =
+ numFramesAvailableToWrite * mAudioSink->frameSize();
+
+ while (numBytesAvailableToWrite > 0 && !mAudioQueue.empty()) {
+ QueueEntry *entry = &*mAudioQueue.begin();
+
+ if (entry->mBuffer == NULL) {
+ // EOS
+
+ notifyEOS(true /* audio */, entry->mFinalResult);
+
+ mAudioQueue.erase(mAudioQueue.begin());
+ entry = NULL;
+ return false;
+ }
+
+ if (entry->mOffset == 0) {
+ int64_t mediaTimeUs;
+ CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
+
+ ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
+
+ mAnchorTimeMediaUs = mediaTimeUs;
+
+ uint32_t numFramesPlayed;
+ CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
+
+ uint32_t numFramesPendingPlayout =
+ mNumFramesWritten - numFramesPlayed;
+
+ int64_t realTimeOffsetUs =
+ (mAudioSink->latency() / 2 /* XXX */
+ + numFramesPendingPlayout
+ * mAudioSink->msecsPerFrame()) * 1000ll;
+
+ // ALOGI("realTimeOffsetUs = %lld us", realTimeOffsetUs);
+
+ mAnchorTimeRealUs =
+ ALooper::GetNowUs() + realTimeOffsetUs;
+ }
+
+ size_t copy = entry->mBuffer->size() - entry->mOffset;
+ if (copy > numBytesAvailableToWrite) {
+ copy = numBytesAvailableToWrite;
+ }
+
+ CHECK_EQ(mAudioSink->write(
+ entry->mBuffer->data() + entry->mOffset, copy),
+ (ssize_t)copy);
+
+ entry->mOffset += copy;
+ if (entry->mOffset == entry->mBuffer->size()) {
+ entry->mNotifyConsumed->post();
+ mAudioQueue.erase(mAudioQueue.begin());
+
+ entry = NULL;
+ }
+
+ numBytesAvailableToWrite -= copy;
+ size_t copiedFrames = copy / mAudioSink->frameSize();
+ mNumFramesWritten += copiedFrames;
+ }
+
+ notifyPosition();
+
+ return !mAudioQueue.empty();
+}
+
+void NuPlayer::Renderer::postDrainVideoQueue() {
+ if (mDrainVideoQueuePending || mSyncQueues || mPaused) {
+ return;
+ }
+
+ if (mVideoQueue.empty()) {
+ return;
+ }
+
+ QueueEntry &entry = *mVideoQueue.begin();
+
+ sp<AMessage> msg = new AMessage(kWhatDrainVideoQueue, id());
+ msg->setInt32("generation", mVideoQueueGeneration);
+
+ int64_t delayUs;
+
+ if (entry.mBuffer == NULL) {
+ // EOS doesn't carry a timestamp.
+ delayUs = 0;
+ } else {
+ int64_t mediaTimeUs;
+ CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
+
+ if (mAnchorTimeMediaUs < 0) {
+ delayUs = 0;
+
+ if (!mHasAudio) {
+ mAnchorTimeMediaUs = mediaTimeUs;
+ mAnchorTimeRealUs = ALooper::GetNowUs();
+ }
+ } else {
+ int64_t realTimeUs =
+ (mediaTimeUs - mAnchorTimeMediaUs) + mAnchorTimeRealUs;
+
+ delayUs = realTimeUs - ALooper::GetNowUs();
+ }
+ }
+
+ msg->post(delayUs);
+
+ mDrainVideoQueuePending = true;
+}
+
+void NuPlayer::Renderer::onDrainVideoQueue() {
+ if (mVideoQueue.empty()) {
+ return;
+ }
+
+ QueueEntry *entry = &*mVideoQueue.begin();
+
+ if (entry->mBuffer == NULL) {
+ // EOS
+
+ notifyEOS(false /* audio */, entry->mFinalResult);
+
+ mVideoQueue.erase(mVideoQueue.begin());
+ entry = NULL;
+
+ mVideoLateByUs = 0ll;
+
+ notifyPosition();
+ return;
+ }
+
+ int64_t mediaTimeUs;
+ CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
+
+ int64_t realTimeUs = mediaTimeUs - mAnchorTimeMediaUs + mAnchorTimeRealUs;
+ mVideoLateByUs = ALooper::GetNowUs() - realTimeUs;
+
+ bool tooLate = (mVideoLateByUs > 40000);
+
+ if (tooLate) {
+ ALOGV("video late by %lld us (%.2f secs)",
+ mVideoLateByUs, mVideoLateByUs / 1E6);
+ } else {
+ ALOGV("rendering video at media time %.2f secs", mediaTimeUs / 1E6);
+ }
+
+ entry->mNotifyConsumed->setInt32("render", !tooLate);
+ entry->mNotifyConsumed->post();
+ mVideoQueue.erase(mVideoQueue.begin());
+ entry = NULL;
+
+ notifyPosition();
+}
+
+void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult) {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatEOS);
+ notify->setInt32("audio", static_cast<int32_t>(audio));
+ notify->setInt32("finalResult", finalResult);
+ notify->post();
+}
+
+void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
+ int32_t audio;
+ CHECK(msg->findInt32("audio", &audio));
+
+ if (audio) {
+ mHasAudio = true;
+ } else {
+ mHasVideo = true;
+ }
+
+ if (dropBufferWhileFlushing(audio, msg)) {
+ return;
+ }
+
+ sp<ABuffer> buffer;
+ CHECK(msg->findBuffer("buffer", &buffer));
+
+ sp<AMessage> notifyConsumed;
+ CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
+
+ QueueEntry entry;
+ entry.mBuffer = buffer;
+ entry.mNotifyConsumed = notifyConsumed;
+ entry.mOffset = 0;
+ entry.mFinalResult = OK;
+
+ if (audio) {
+ mAudioQueue.push_back(entry);
+ postDrainAudioQueue();
+ } else {
+ mVideoQueue.push_back(entry);
+ postDrainVideoQueue();
+ }
+
+ if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
+ return;
+ }
+
+ sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
+ sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
+
+ if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
+ // EOS signalled on either queue.
+ syncQueuesDone();
+ return;
+ }
+
+ int64_t firstAudioTimeUs;
+ int64_t firstVideoTimeUs;
+ CHECK(firstAudioBuffer->meta()
+ ->findInt64("timeUs", &firstAudioTimeUs));
+ CHECK(firstVideoBuffer->meta()
+ ->findInt64("timeUs", &firstVideoTimeUs));
+
+ int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
+
+ ALOGV("queueDiff = %.2f secs", diff / 1E6);
+
+ if (diff > 100000ll) {
+ // Audio data starts More than 0.1 secs before video.
+ // Drop some audio.
+
+ (*mAudioQueue.begin()).mNotifyConsumed->post();
+ mAudioQueue.erase(mAudioQueue.begin());
+ return;
+ }
+
+ syncQueuesDone();
+}
+
+void NuPlayer::Renderer::syncQueuesDone() {
+ if (!mSyncQueues) {
+ return;
+ }
+
+ mSyncQueues = false;
+
+ if (!mAudioQueue.empty()) {
+ postDrainAudioQueue();
+ }
+
+ if (!mVideoQueue.empty()) {
+ postDrainVideoQueue();
+ }
+}
+
+void NuPlayer::Renderer::onQueueEOS(const sp<AMessage> &msg) {
+ int32_t audio;
+ CHECK(msg->findInt32("audio", &audio));
+
+ if (dropBufferWhileFlushing(audio, msg)) {
+ return;
+ }
+
+ int32_t finalResult;
+ CHECK(msg->findInt32("finalResult", &finalResult));
+
+ QueueEntry entry;
+ entry.mOffset = 0;
+ entry.mFinalResult = finalResult;
+
+ if (audio) {
+ mAudioQueue.push_back(entry);
+ postDrainAudioQueue();
+ } else {
+ mVideoQueue.push_back(entry);
+ postDrainVideoQueue();
+ }
+}
+
+void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
+ int32_t audio;
+ CHECK(msg->findInt32("audio", &audio));
+
+ // If we're currently syncing the queues, i.e. dropping audio while
+ // aligning the first audio/video buffer times and only one of the
+ // two queues has data, we may starve that queue by not requesting
+ // more buffers from the decoder. If the other source then encounters
+ // a discontinuity that leads to flushing, we'll never find the
+ // corresponding discontinuity on the other queue.
+ // Therefore we'll stop syncing the queues if at least one of them
+ // is flushed.
+ syncQueuesDone();
+
+ if (audio) {
+ flushQueue(&mAudioQueue);
+
+ Mutex::Autolock autoLock(mFlushLock);
+ mFlushingAudio = false;
+
+ mDrainAudioQueuePending = false;
+ ++mAudioQueueGeneration;
+ } else {
+ flushQueue(&mVideoQueue);
+
+ Mutex::Autolock autoLock(mFlushLock);
+ mFlushingVideo = false;
+
+ mDrainVideoQueuePending = false;
+ ++mVideoQueueGeneration;
+ }
+
+ notifyFlushComplete(audio);
+}
+
+void NuPlayer::Renderer::flushQueue(List<QueueEntry> *queue) {
+ while (!queue->empty()) {
+ QueueEntry *entry = &*queue->begin();
+
+ if (entry->mBuffer != NULL) {
+ entry->mNotifyConsumed->post();
+ }
+
+ queue->erase(queue->begin());
+ entry = NULL;
+ }
+}
+
+void NuPlayer::Renderer::notifyFlushComplete(bool audio) {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatFlushComplete);
+ notify->setInt32("audio", static_cast<int32_t>(audio));
+ notify->post();
+}
+
+bool NuPlayer::Renderer::dropBufferWhileFlushing(
+ bool audio, const sp<AMessage> &msg) {
+ bool flushing = false;
+
+ {
+ Mutex::Autolock autoLock(mFlushLock);
+ if (audio) {
+ flushing = mFlushingAudio;
+ } else {
+ flushing = mFlushingVideo;
+ }
+ }
+
+ if (!flushing) {
+ return false;
+ }
+
+ sp<AMessage> notifyConsumed;
+ if (msg->findMessage("notifyConsumed", &notifyConsumed)) {
+ notifyConsumed->post();
+ }
+
+ return true;
+}
+
+void NuPlayer::Renderer::onAudioSinkChanged() {
+ CHECK(!mDrainAudioQueuePending);
+ mNumFramesWritten = 0;
+}
+
+void NuPlayer::Renderer::notifyPosition() {
+ if (mAnchorTimeRealUs < 0 || mAnchorTimeMediaUs < 0) {
+ return;
+ }
+
+ int64_t nowUs = ALooper::GetNowUs();
+
+ if (mLastPositionUpdateUs >= 0
+ && nowUs < mLastPositionUpdateUs + kMinPositionUpdateDelayUs) {
+ return;
+ }
+ mLastPositionUpdateUs = nowUs;
+
+ int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatPosition);
+ notify->setInt64("positionUs", positionUs);
+ notify->setInt64("videoLateByUs", mVideoLateByUs);
+ notify->post();
+}
+
+void NuPlayer::Renderer::onPause() {
+ CHECK(!mPaused);
+
+ mDrainAudioQueuePending = false;
+ ++mAudioQueueGeneration;
+
+ mDrainVideoQueuePending = false;
+ ++mVideoQueueGeneration;
+
+ if (mHasAudio) {
+ mAudioSink->pause();
+ }
+
+ ALOGV("now paused audio queue has %d entries, video has %d entries",
+ mAudioQueue.size(), mVideoQueue.size());
+
+ mPaused = true;
+}
+
+void NuPlayer::Renderer::onResume() {
+ if (!mPaused) {
+ return;
+ }
+
+ if (mHasAudio) {
+ mAudioSink->start();
+ }
+
+ mPaused = false;
+
+ if (!mAudioQueue.empty()) {
+ postDrainAudioQueue();
+ }
+
+ if (!mVideoQueue.empty()) {
+ postDrainVideoQueue();
+ }
+}
+
+} // namespace android
+
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
new file mode 100644
index 0000000..268628b
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -0,0 +1,133 @@
+/*
+ * 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 NUPLAYER_RENDERER_H_
+
+#define NUPLAYER_RENDERER_H_
+
+#include "NuPlayer.h"
+
+namespace android {
+
+struct ABuffer;
+
+struct NuPlayer::Renderer : public AHandler {
+ Renderer(const sp<MediaPlayerBase::AudioSink> &sink,
+ const sp<AMessage> &notify);
+
+ void queueBuffer(
+ bool audio,
+ const sp<ABuffer> &buffer,
+ const sp<AMessage> &notifyConsumed);
+
+ void queueEOS(bool audio, status_t finalResult);
+
+ void flush(bool audio);
+
+ void signalTimeDiscontinuity();
+
+ void signalAudioSinkChanged();
+
+ void pause();
+ void resume();
+
+ enum {
+ kWhatEOS = 'eos ',
+ kWhatFlushComplete = 'fluC',
+ kWhatPosition = 'posi',
+ };
+
+protected:
+ virtual ~Renderer();
+
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+ enum {
+ kWhatDrainAudioQueue = 'draA',
+ kWhatDrainVideoQueue = 'draV',
+ kWhatQueueBuffer = 'queB',
+ kWhatQueueEOS = 'qEOS',
+ kWhatFlush = 'flus',
+ kWhatAudioSinkChanged = 'auSC',
+ kWhatPause = 'paus',
+ kWhatResume = 'resm',
+ };
+
+ struct QueueEntry {
+ sp<ABuffer> mBuffer;
+ sp<AMessage> mNotifyConsumed;
+ size_t mOffset;
+ status_t mFinalResult;
+ };
+
+ static const int64_t kMinPositionUpdateDelayUs;
+
+ sp<MediaPlayerBase::AudioSink> mAudioSink;
+ sp<AMessage> mNotify;
+ List<QueueEntry> mAudioQueue;
+ List<QueueEntry> mVideoQueue;
+ uint32_t mNumFramesWritten;
+
+ bool mDrainAudioQueuePending;
+ bool mDrainVideoQueuePending;
+ int32_t mAudioQueueGeneration;
+ int32_t mVideoQueueGeneration;
+
+ int64_t mAnchorTimeMediaUs;
+ int64_t mAnchorTimeRealUs;
+
+ Mutex mFlushLock; // protects the following 2 member vars.
+ bool mFlushingAudio;
+ bool mFlushingVideo;
+
+ bool mHasAudio;
+ bool mHasVideo;
+ bool mSyncQueues;
+
+ bool mPaused;
+
+ int64_t mLastPositionUpdateUs;
+ int64_t mVideoLateByUs;
+
+ bool onDrainAudioQueue();
+ void postDrainAudioQueue(int64_t delayUs = 0);
+
+ void onDrainVideoQueue();
+ void postDrainVideoQueue();
+
+ void onQueueBuffer(const sp<AMessage> &msg);
+ void onQueueEOS(const sp<AMessage> &msg);
+ void onFlush(const sp<AMessage> &msg);
+ void onAudioSinkChanged();
+ void onPause();
+ void onResume();
+
+ void notifyEOS(bool audio, status_t finalResult);
+ void notifyFlushComplete(bool audio);
+ void notifyPosition();
+ void notifyVideoLateBy(int64_t lateByUs);
+
+ void flushQueue(List<QueueEntry> *queue);
+ bool dropBufferWhileFlushing(bool audio, const sp<AMessage> &msg);
+ void syncQueuesDone();
+
+ DISALLOW_EVIL_CONSTRUCTORS(Renderer);
+};
+
+} // namespace android
+
+#endif // NUPLAYER_RENDERER_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
new file mode 100644
index 0000000..531b29f
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -0,0 +1,64 @@
+/*
+ * 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 NUPLAYER_SOURCE_H_
+
+#define NUPLAYER_SOURCE_H_
+
+#include "NuPlayer.h"
+
+namespace android {
+
+struct ABuffer;
+
+struct NuPlayer::Source : public RefBase {
+ Source() {}
+
+ virtual void start() = 0;
+ virtual void stop() {}
+
+ // Returns OK iff more data was available,
+ // an error or ERROR_END_OF_STREAM if not.
+ virtual status_t feedMoreTSData() = 0;
+
+ virtual sp<MetaData> getFormat(bool audio) = 0;
+
+ virtual status_t dequeueAccessUnit(
+ bool audio, sp<ABuffer> *accessUnit) = 0;
+
+ virtual status_t getDuration(int64_t *durationUs) {
+ return INVALID_OPERATION;
+ }
+
+ virtual status_t seekTo(int64_t seekTimeUs) {
+ return INVALID_OPERATION;
+ }
+
+ virtual bool isSeekable() {
+ return false;
+ }
+
+protected:
+ virtual ~Source() {}
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(Source);
+};
+
+} // namespace android
+
+#endif // NUPLAYER_SOURCE_H_
+
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
new file mode 100644
index 0000000..885ebe4
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
@@ -0,0 +1,164 @@
+/*
+ * 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 "NuPlayerStreamListener"
+#include <utils/Log.h>
+
+#include "NuPlayerStreamListener.h"
+
+#include <binder/MemoryDealer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+NuPlayer::NuPlayerStreamListener::NuPlayerStreamListener(
+ const sp<IStreamSource> &source,
+ ALooper::handler_id id)
+ : mSource(source),
+ mTargetID(id),
+ mEOS(false),
+ mSendDataNotification(true) {
+ mSource->setListener(this);
+
+ mMemoryDealer = new MemoryDealer(kNumBuffers * kBufferSize);
+ for (size_t i = 0; i < kNumBuffers; ++i) {
+ sp<IMemory> mem = mMemoryDealer->allocate(kBufferSize);
+ CHECK(mem != NULL);
+
+ mBuffers.push(mem);
+ }
+ mSource->setBuffers(mBuffers);
+}
+
+void NuPlayer::NuPlayerStreamListener::start() {
+ for (size_t i = 0; i < kNumBuffers; ++i) {
+ mSource->onBufferAvailable(i);
+ }
+}
+
+void NuPlayer::NuPlayerStreamListener::queueBuffer(size_t index, size_t size) {
+ QueueEntry entry;
+ entry.mIsCommand = false;
+ entry.mIndex = index;
+ entry.mSize = size;
+ entry.mOffset = 0;
+
+ Mutex::Autolock autoLock(mLock);
+ mQueue.push_back(entry);
+
+ if (mSendDataNotification) {
+ mSendDataNotification = false;
+
+ if (mTargetID != 0) {
+ (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
+ }
+ }
+}
+
+void NuPlayer::NuPlayerStreamListener::issueCommand(
+ Command cmd, bool synchronous, const sp<AMessage> &extra) {
+ CHECK(!synchronous);
+
+ QueueEntry entry;
+ entry.mIsCommand = true;
+ entry.mCommand = cmd;
+ entry.mExtra = extra;
+
+ Mutex::Autolock autoLock(mLock);
+ mQueue.push_back(entry);
+
+ if (mSendDataNotification) {
+ mSendDataNotification = false;
+
+ if (mTargetID != 0) {
+ (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
+ }
+ }
+}
+
+ssize_t NuPlayer::NuPlayerStreamListener::read(
+ void *data, size_t size, sp<AMessage> *extra) {
+ CHECK_GT(size, 0u);
+
+ extra->clear();
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (mEOS) {
+ return 0;
+ }
+
+ if (mQueue.empty()) {
+ mSendDataNotification = true;
+
+ return -EWOULDBLOCK;
+ }
+
+ QueueEntry *entry = &*mQueue.begin();
+
+ if (entry->mIsCommand) {
+ switch (entry->mCommand) {
+ case EOS:
+ {
+ mQueue.erase(mQueue.begin());
+ entry = NULL;
+
+ mEOS = true;
+ return 0;
+ }
+
+ case DISCONTINUITY:
+ {
+ *extra = entry->mExtra;
+
+ mQueue.erase(mQueue.begin());
+ entry = NULL;
+
+ return INFO_DISCONTINUITY;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+ }
+
+ size_t copy = entry->mSize;
+ if (copy > size) {
+ copy = size;
+ }
+
+ memcpy(data,
+ (const uint8_t *)mBuffers.editItemAt(entry->mIndex)->pointer()
+ + entry->mOffset,
+ copy);
+
+ entry->mOffset += copy;
+ entry->mSize -= copy;
+
+ if (entry->mSize == 0) {
+ mSource->onBufferAvailable(entry->mIndex);
+ mQueue.erase(mQueue.begin());
+ entry = NULL;
+ }
+
+ return copy;
+}
+
+} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h
new file mode 100644
index 0000000..1874d80
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.h
@@ -0,0 +1,74 @@
+/*
+ * 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 NUPLAYER_STREAM_LISTENER_H_
+
+#define NUPLAYER_STREAM_LISTENER_H_
+
+#include "NuPlayer.h"
+
+#include <media/IStreamSource.h>
+
+namespace android {
+
+struct MemoryDealer;
+
+struct NuPlayer::NuPlayerStreamListener : public BnStreamListener {
+ NuPlayerStreamListener(
+ const sp<IStreamSource> &source,
+ ALooper::handler_id targetID);
+
+ virtual void queueBuffer(size_t index, size_t size);
+
+ virtual void issueCommand(
+ Command cmd, bool synchronous, const sp<AMessage> &extra);
+
+ void start();
+ ssize_t read(void *data, size_t size, sp<AMessage> *extra);
+
+private:
+ enum {
+ kNumBuffers = 8,
+ kBufferSize = 188 * 10
+ };
+
+ struct QueueEntry {
+ bool mIsCommand;
+
+ size_t mIndex;
+ size_t mSize;
+ size_t mOffset;
+
+ Command mCommand;
+ sp<AMessage> mExtra;
+ };
+
+ Mutex mLock;
+
+ sp<IStreamSource> mSource;
+ ALooper::handler_id mTargetID;
+ sp<MemoryDealer> mMemoryDealer;
+ Vector<sp<IMemory> > mBuffers;
+ List<QueueEntry> mQueue;
+ bool mEOS;
+ bool mSendDataNotification;
+
+ DISALLOW_EVIL_CONSTRUCTORS(NuPlayerStreamListener);
+};
+
+} // namespace android
+
+#endif // NUPLAYER_STREAM_LISTENER_H_
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
new file mode 100644
index 0000000..4c65b65
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -0,0 +1,387 @@
+/*
+ * 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 "RTSPSource"
+#include <utils/Log.h>
+
+#include "RTSPSource.h"
+
+#include "AnotherPacketSource.h"
+#include "MyHandler.h"
+
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+NuPlayer::RTSPSource::RTSPSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers,
+ bool uidValid,
+ uid_t uid)
+ : mURL(url),
+ mUIDValid(uidValid),
+ mUID(uid),
+ mFlags(0),
+ mState(DISCONNECTED),
+ mFinalResult(OK),
+ mDisconnectReplyID(0),
+ mSeekGeneration(0) {
+ if (headers) {
+ mExtraHeaders = *headers;
+
+ ssize_t index =
+ mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log"));
+
+ if (index >= 0) {
+ mFlags |= kFlagIncognito;
+
+ mExtraHeaders.removeItemsAt(index);
+ }
+ }
+}
+
+NuPlayer::RTSPSource::~RTSPSource() {
+ if (mLooper != NULL) {
+ mLooper->stop();
+ }
+}
+
+void NuPlayer::RTSPSource::start() {
+ if (mLooper == NULL) {
+ mLooper = new ALooper;
+ mLooper->setName("rtsp");
+ mLooper->start();
+
+ mReflector = new AHandlerReflector<RTSPSource>(this);
+ mLooper->registerHandler(mReflector);
+ }
+
+ CHECK(mHandler == NULL);
+
+ sp<AMessage> notify = new AMessage(kWhatNotify, mReflector->id());
+
+ mHandler = new MyHandler(mURL.c_str(), notify, mUIDValid, mUID);
+ mLooper->registerHandler(mHandler);
+
+ CHECK_EQ(mState, (int)DISCONNECTED);
+ mState = CONNECTING;
+
+ mHandler->connect();
+}
+
+void NuPlayer::RTSPSource::stop() {
+ sp<AMessage> msg = new AMessage(kWhatDisconnect, mReflector->id());
+
+ sp<AMessage> dummy;
+ msg->postAndAwaitResponse(&dummy);
+}
+
+status_t NuPlayer::RTSPSource::feedMoreTSData() {
+ return mFinalResult;
+}
+
+sp<MetaData> NuPlayer::RTSPSource::getFormat(bool audio) {
+ sp<AnotherPacketSource> source = getSource(audio);
+
+ if (source == NULL) {
+ return NULL;
+ }
+
+ return source->getFormat();
+}
+
+status_t NuPlayer::RTSPSource::dequeueAccessUnit(
+ bool audio, sp<ABuffer> *accessUnit) {
+ sp<AnotherPacketSource> source = getSource(audio);
+
+ if (source == NULL) {
+ return -EWOULDBLOCK;
+ }
+
+ status_t finalResult;
+ if (!source->hasBufferAvailable(&finalResult)) {
+ return finalResult == OK ? -EWOULDBLOCK : finalResult;
+ }
+
+ return source->dequeueAccessUnit(accessUnit);
+}
+
+sp<AnotherPacketSource> NuPlayer::RTSPSource::getSource(bool audio) {
+ return audio ? mAudioTrack : mVideoTrack;
+}
+
+status_t NuPlayer::RTSPSource::getDuration(int64_t *durationUs) {
+ *durationUs = 0ll;
+
+ int64_t audioDurationUs;
+ if (mAudioTrack != NULL
+ && mAudioTrack->getFormat()->findInt64(
+ kKeyDuration, &audioDurationUs)
+ && audioDurationUs > *durationUs) {
+ *durationUs = audioDurationUs;
+ }
+
+ int64_t videoDurationUs;
+ if (mVideoTrack != NULL
+ && mVideoTrack->getFormat()->findInt64(
+ kKeyDuration, &videoDurationUs)
+ && videoDurationUs > *durationUs) {
+ *durationUs = videoDurationUs;
+ }
+
+ return OK;
+}
+
+status_t NuPlayer::RTSPSource::seekTo(int64_t seekTimeUs) {
+ sp<AMessage> msg = new AMessage(kWhatPerformSeek, mReflector->id());
+ msg->setInt32("generation", ++mSeekGeneration);
+ msg->setInt64("timeUs", seekTimeUs);
+ msg->post(200000ll);
+
+ return OK;
+}
+
+void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
+ if (mState != CONNECTED) {
+ return;
+ }
+
+ mState = SEEKING;
+ mHandler->seek(seekTimeUs);
+}
+
+bool NuPlayer::RTSPSource::isSeekable() {
+ return true;
+}
+
+void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
+ if (msg->what() == kWhatDisconnect) {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ mDisconnectReplyID = replyID;
+ finishDisconnectIfPossible();
+ return;
+ } else if (msg->what() == kWhatPerformSeek) {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+
+ if (generation != mSeekGeneration) {
+ // obsolete.
+ return;
+ }
+
+ int64_t seekTimeUs;
+ CHECK(msg->findInt64("timeUs", &seekTimeUs));
+
+ performSeek(seekTimeUs);
+ return;
+ }
+
+ CHECK_EQ(msg->what(), (int)kWhatNotify);
+
+ int32_t what;
+ CHECK(msg->findInt32("what", &what));
+
+ switch (what) {
+ case MyHandler::kWhatConnected:
+ onConnected();
+ break;
+
+ case MyHandler::kWhatDisconnected:
+ onDisconnected(msg);
+ break;
+
+ case MyHandler::kWhatSeekDone:
+ {
+ mState = CONNECTED;
+ break;
+ }
+
+ case MyHandler::kWhatAccessUnit:
+ {
+ size_t trackIndex;
+ CHECK(msg->findSize("trackIndex", &trackIndex));
+ CHECK_LT(trackIndex, mTracks.size());
+
+ sp<ABuffer> accessUnit;
+ CHECK(msg->findBuffer("accessUnit", &accessUnit));
+
+ int32_t damaged;
+ if (accessUnit->meta()->findInt32("damaged", &damaged)
+ && damaged) {
+ ALOGI("dropping damaged access unit.");
+ break;
+ }
+
+ TrackInfo *info = &mTracks.editItemAt(trackIndex);
+
+ sp<AnotherPacketSource> source = info->mSource;
+ if (source != NULL) {
+ uint32_t rtpTime;
+ CHECK(accessUnit->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+ if (!info->mNPTMappingValid) {
+ // This is a live stream, we didn't receive any normal
+ // playtime mapping. Assume the first packets correspond
+ // to time 0.
+
+ ALOGV("This is a live stream, assuming time = 0");
+
+ info->mRTPTime = rtpTime;
+ info->mNormalPlaytimeUs = 0ll;
+ info->mNPTMappingValid = true;
+ }
+
+ int64_t nptUs =
+ ((double)rtpTime - (double)info->mRTPTime)
+ / info->mTimeScale
+ * 1000000ll
+ + info->mNormalPlaytimeUs;
+
+ accessUnit->meta()->setInt64("timeUs", nptUs);
+
+ source->queueAccessUnit(accessUnit);
+ }
+ break;
+ }
+
+ case MyHandler::kWhatEOS:
+ {
+ size_t trackIndex;
+ CHECK(msg->findSize("trackIndex", &trackIndex));
+ CHECK_LT(trackIndex, mTracks.size());
+
+ int32_t finalResult;
+ CHECK(msg->findInt32("finalResult", &finalResult));
+ CHECK_NE(finalResult, (status_t)OK);
+
+ TrackInfo *info = &mTracks.editItemAt(trackIndex);
+ sp<AnotherPacketSource> source = info->mSource;
+ if (source != NULL) {
+ source->signalEOS(finalResult);
+ }
+
+ break;
+ }
+
+ case MyHandler::kWhatSeekDiscontinuity:
+ {
+ size_t trackIndex;
+ CHECK(msg->findSize("trackIndex", &trackIndex));
+ CHECK_LT(trackIndex, mTracks.size());
+
+ TrackInfo *info = &mTracks.editItemAt(trackIndex);
+ sp<AnotherPacketSource> source = info->mSource;
+ if (source != NULL) {
+ source->queueDiscontinuity(ATSParser::DISCONTINUITY_SEEK, NULL);
+ }
+
+ break;
+ }
+
+ case MyHandler::kWhatNormalPlayTimeMapping:
+ {
+ size_t trackIndex;
+ CHECK(msg->findSize("trackIndex", &trackIndex));
+ CHECK_LT(trackIndex, mTracks.size());
+
+ uint32_t rtpTime;
+ CHECK(msg->findInt32("rtpTime", (int32_t *)&rtpTime));
+
+ int64_t nptUs;
+ CHECK(msg->findInt64("nptUs", &nptUs));
+
+ TrackInfo *info = &mTracks.editItemAt(trackIndex);
+ info->mRTPTime = rtpTime;
+ info->mNormalPlaytimeUs = nptUs;
+ info->mNPTMappingValid = true;
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+}
+
+void NuPlayer::RTSPSource::onConnected() {
+ CHECK(mAudioTrack == NULL);
+ CHECK(mVideoTrack == NULL);
+
+ size_t numTracks = mHandler->countTracks();
+ for (size_t i = 0; i < numTracks; ++i) {
+ int32_t timeScale;
+ sp<MetaData> format = mHandler->getTrackFormat(i, &timeScale);
+
+ const char *mime;
+ CHECK(format->findCString(kKeyMIMEType, &mime));
+
+ bool isAudio = !strncasecmp(mime, "audio/", 6);
+ bool isVideo = !strncasecmp(mime, "video/", 6);
+
+ TrackInfo info;
+ info.mTimeScale = timeScale;
+ info.mRTPTime = 0;
+ info.mNormalPlaytimeUs = 0ll;
+ info.mNPTMappingValid = false;
+
+ if ((isAudio && mAudioTrack == NULL)
+ || (isVideo && mVideoTrack == NULL)) {
+ sp<AnotherPacketSource> source = new AnotherPacketSource(format);
+
+ if (isAudio) {
+ mAudioTrack = source;
+ } else {
+ mVideoTrack = source;
+ }
+
+ info.mSource = source;
+ }
+
+ mTracks.push(info);
+ }
+
+ mState = CONNECTED;
+}
+
+void NuPlayer::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
+ status_t err;
+ CHECK(msg->findInt32("result", &err));
+ CHECK_NE(err, (status_t)OK);
+
+ mLooper->unregisterHandler(mHandler->id());
+ mHandler.clear();
+
+ mState = DISCONNECTED;
+ mFinalResult = err;
+
+ if (mDisconnectReplyID != 0) {
+ finishDisconnectIfPossible();
+ }
+}
+
+void NuPlayer::RTSPSource::finishDisconnectIfPossible() {
+ if (mState != DISCONNECTED) {
+ mHandler->disconnect();
+ return;
+ }
+
+ (new AMessage)->postReply(mDisconnectReplyID);
+ mDisconnectReplyID = 0;
+}
+
+} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
new file mode 100644
index 0000000..59d06ad
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -0,0 +1,115 @@
+/*
+ * 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 RTSP_SOURCE_H_
+
+#define RTSP_SOURCE_H_
+
+#include "NuPlayerSource.h"
+
+#include <media/stagefright/foundation/AHandlerReflector.h>
+
+namespace android {
+
+struct ALooper;
+struct AnotherPacketSource;
+struct MyHandler;
+
+struct NuPlayer::RTSPSource : public NuPlayer::Source {
+ RTSPSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers,
+ bool uidValid = false,
+ uid_t uid = 0);
+
+ virtual void start();
+ virtual void stop();
+
+ virtual status_t feedMoreTSData();
+
+ virtual sp<MetaData> getFormat(bool audio);
+ virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+
+ virtual status_t getDuration(int64_t *durationUs);
+ virtual status_t seekTo(int64_t seekTimeUs);
+ virtual bool isSeekable();
+
+ void onMessageReceived(const sp<AMessage> &msg);
+
+protected:
+ virtual ~RTSPSource();
+
+private:
+ enum {
+ kWhatNotify = 'noti',
+ kWhatDisconnect = 'disc',
+ kWhatPerformSeek = 'seek',
+ };
+
+ enum State {
+ DISCONNECTED,
+ CONNECTING,
+ CONNECTED,
+ SEEKING,
+ };
+
+ enum Flags {
+ // Don't log any URLs.
+ kFlagIncognito = 1,
+ };
+
+ struct TrackInfo {
+ sp<AnotherPacketSource> mSource;
+
+ int32_t mTimeScale;
+ uint32_t mRTPTime;
+ int64_t mNormalPlaytimeUs;
+ bool mNPTMappingValid;
+ };
+
+ AString mURL;
+ KeyedVector<String8, String8> mExtraHeaders;
+ bool mUIDValid;
+ uid_t mUID;
+ uint32_t mFlags;
+ State mState;
+ status_t mFinalResult;
+ uint32_t mDisconnectReplyID;
+
+ sp<ALooper> mLooper;
+ sp<AHandlerReflector<RTSPSource> > mReflector;
+ sp<MyHandler> mHandler;
+
+ Vector<TrackInfo> mTracks;
+ sp<AnotherPacketSource> mAudioTrack;
+ sp<AnotherPacketSource> mVideoTrack;
+
+ int32_t mSeekGeneration;
+
+ sp<AnotherPacketSource> getSource(bool audio);
+
+ void onConnected();
+ void onDisconnected(const sp<AMessage> &msg);
+ void finishDisconnectIfPossible();
+
+ void performSeek(int64_t seekTimeUs);
+
+ DISALLOW_EVIL_CONSTRUCTORS(RTSPSource);
+};
+
+} // namespace android
+
+#endif // RTSP_SOURCE_H_
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
new file mode 100644
index 0000000..7c9bc5e
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -0,0 +1,145 @@
+/*
+ * 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 "StreamingSource"
+#include <utils/Log.h>
+
+#include "StreamingSource.h"
+
+#include "ATSParser.h"
+#include "AnotherPacketSource.h"
+#include "NuPlayerStreamListener.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+NuPlayer::StreamingSource::StreamingSource(const sp<IStreamSource> &source)
+ : mSource(source),
+ mFinalResult(OK) {
+}
+
+NuPlayer::StreamingSource::~StreamingSource() {
+}
+
+void NuPlayer::StreamingSource::start() {
+ mStreamListener = new NuPlayerStreamListener(mSource, 0);
+ mTSParser = new ATSParser(ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE);
+
+ mStreamListener->start();
+}
+
+status_t NuPlayer::StreamingSource::feedMoreTSData() {
+ if (mFinalResult != OK) {
+ return mFinalResult;
+ }
+
+ for (int32_t i = 0; i < 50; ++i) {
+ char buffer[188];
+ sp<AMessage> extra;
+ ssize_t n = mStreamListener->read(buffer, sizeof(buffer), &extra);
+
+ if (n == 0) {
+ ALOGI("input data EOS reached.");
+ mTSParser->signalEOS(ERROR_END_OF_STREAM);
+ mFinalResult = ERROR_END_OF_STREAM;
+ break;
+ } else if (n == INFO_DISCONTINUITY) {
+ int32_t type = ATSParser::DISCONTINUITY_SEEK;
+
+ int32_t mask;
+ if (extra != NULL
+ && extra->findInt32(
+ IStreamListener::kKeyDiscontinuityMask, &mask)) {
+ if (mask == 0) {
+ ALOGE("Client specified an illegal discontinuity type.");
+ return ERROR_UNSUPPORTED;
+ }
+
+ type = mask;
+ }
+
+ mTSParser->signalDiscontinuity(
+ (ATSParser::DiscontinuityType)type, extra);
+ } else if (n < 0) {
+ CHECK_EQ(n, -EWOULDBLOCK);
+ break;
+ } else {
+ if (buffer[0] == 0x00) {
+ // XXX legacy
+ mTSParser->signalDiscontinuity(
+ buffer[1] == 0x00
+ ? ATSParser::DISCONTINUITY_SEEK
+ : ATSParser::DISCONTINUITY_FORMATCHANGE,
+ extra);
+ } else {
+ status_t err = mTSParser->feedTSPacket(buffer, sizeof(buffer));
+
+ if (err != OK) {
+ ALOGE("TS Parser returned error %d", err);
+
+ mTSParser->signalEOS(err);
+ mFinalResult = err;
+ break;
+ }
+ }
+ }
+ }
+
+ return OK;
+}
+
+sp<MetaData> NuPlayer::StreamingSource::getFormat(bool audio) {
+ ATSParser::SourceType type =
+ audio ? ATSParser::AUDIO : ATSParser::VIDEO;
+
+ sp<AnotherPacketSource> source =
+ static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+
+ if (source == NULL) {
+ return NULL;
+ }
+
+ return source->getFormat();
+}
+
+status_t NuPlayer::StreamingSource::dequeueAccessUnit(
+ bool audio, sp<ABuffer> *accessUnit) {
+ ATSParser::SourceType type =
+ audio ? ATSParser::AUDIO : ATSParser::VIDEO;
+
+ sp<AnotherPacketSource> source =
+ static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+
+ if (source == NULL) {
+ return -EWOULDBLOCK;
+ }
+
+ status_t finalResult;
+ if (!source->hasBufferAvailable(&finalResult)) {
+ return finalResult == OK ? -EWOULDBLOCK : finalResult;
+ }
+
+ return source->dequeueAccessUnit(accessUnit);
+}
+
+} // namespace android
+
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.h b/media/libmediaplayerservice/nuplayer/StreamingSource.h
new file mode 100644
index 0000000..ca00ef9
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.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 STREAMING_SOURCE_H_
+
+#define STREAMING_SOURCE_H_
+
+#include "NuPlayer.h"
+#include "NuPlayerSource.h"
+
+namespace android {
+
+struct ABuffer;
+struct ATSParser;
+
+struct NuPlayer::StreamingSource : public NuPlayer::Source {
+ StreamingSource(const sp<IStreamSource> &source);
+
+ virtual void start();
+
+ virtual status_t feedMoreTSData();
+
+ virtual sp<MetaData> getFormat(bool audio);
+ virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+
+protected:
+ virtual ~StreamingSource();
+
+private:
+ sp<IStreamSource> mSource;
+ status_t mFinalResult;
+ sp<NuPlayerStreamListener> mStreamListener;
+ sp<ATSParser> mTSParser;
+
+ DISALLOW_EVIL_CONSTRUCTORS(StreamingSource);
+};
+
+} // namespace android
+
+#endif // STREAMING_SOURCE_H_
diff --git a/media/libstagefright/AACExtractor.cpp b/media/libstagefright/AACExtractor.cpp
new file mode 100644
index 0000000..4d1072f
--- /dev/null
+++ b/media/libstagefright/AACExtractor.cpp
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "AACExtractor"
+#include <utils/Log.h>
+
+#include "include/AACExtractor.h"
+#include "include/avc_utils.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBufferGroup.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 {
+
+class AACSource : public MediaSource {
+public:
+ AACSource(const sp<DataSource> &source,
+ const sp<MetaData> &meta,
+ const Vector<uint64_t> &offset_vector,
+ int64_t frame_duration_us);
+
+ 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);
+
+protected:
+ virtual ~AACSource();
+
+private:
+ static const size_t kMaxFrameSize;
+ sp<DataSource> mDataSource;
+ sp<MetaData> mMeta;
+
+ off64_t mOffset;
+ int64_t mCurrentTimeUs;
+ bool mStarted;
+ MediaBufferGroup *mGroup;
+
+ Vector<uint64_t> mOffsetVector;
+ int64_t mFrameDurationUs;
+
+ AACSource(const AACSource &);
+ AACSource &operator=(const AACSource &);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Returns the sample rate based on the sampling frequency index
+uint32_t get_sample_rate(const uint8_t sf_index)
+{
+ static const uint32_t sample_rates[] =
+ {
+ 96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000
+ };
+
+ if (sf_index < sizeof(sample_rates) / sizeof(sample_rates[0])) {
+ return sample_rates[sf_index];
+ }
+
+ return 0;
+}
+
+// Returns the frame length in bytes as described in an ADTS header starting at the given offset,
+// or 0 if the size can't be read due to an error in the header or a read failure.
+// The returned value is the AAC frame size with the ADTS header length (regardless of
+// the presence of the CRC).
+// If headerSize is non-NULL, it will be used to return the size of the header of this ADTS frame.
+static size_t getAdtsFrameLength(const sp<DataSource> &source, off64_t offset, size_t* headerSize) {
+
+ const size_t kAdtsHeaderLengthNoCrc = 7;
+ const size_t kAdtsHeaderLengthWithCrc = 9;
+
+ size_t frameSize = 0;
+
+ uint8_t syncword[2];
+ if (source->readAt(offset, &syncword, 2) != 2) {
+ return 0;
+ }
+ if ((syncword[0] != 0xff) || ((syncword[1] & 0xf6) != 0xf0)) {
+ return 0;
+ }
+
+ uint8_t protectionAbsent;
+ if (source->readAt(offset + 1, &protectionAbsent, 1) < 1) {
+ return 0;
+ }
+ protectionAbsent &= 0x1;
+
+ uint8_t header[3];
+ if (source->readAt(offset + 3, &header, 3) < 3) {
+ return 0;
+ }
+
+ frameSize = (header[0] & 0x3) << 11 | header[1] << 3 | header[2] >> 5;
+
+ // protectionAbsent is 0 if there is CRC
+ size_t headSize = protectionAbsent ? kAdtsHeaderLengthNoCrc : kAdtsHeaderLengthWithCrc;
+ if (headSize > frameSize) {
+ return 0;
+ }
+ if (headerSize != NULL) {
+ *headerSize = headSize;
+ }
+
+ return frameSize;
+}
+
+AACExtractor::AACExtractor(
+ const sp<DataSource> &source, const sp<AMessage> &_meta)
+ : mDataSource(source),
+ mInitCheck(NO_INIT),
+ mFrameDurationUs(0) {
+ sp<AMessage> meta = _meta;
+
+ if (meta == NULL) {
+ String8 mimeType;
+ float confidence;
+ sp<AMessage> _meta;
+
+ if (!SniffAAC(mDataSource, &mimeType, &confidence, &meta)) {
+ return;
+ }
+ }
+
+ int64_t offset;
+ CHECK(meta->findInt64("offset", &offset));
+
+ uint8_t profile, sf_index, channel, header[2];
+ if (mDataSource->readAt(offset + 2, &header, 2) < 2) {
+ return;
+ }
+
+ profile = (header[0] >> 6) & 0x3;
+ sf_index = (header[0] >> 2) & 0xf;
+ uint32_t sr = get_sample_rate(sf_index);
+ if (sr == 0) {
+ return;
+ }
+ channel = (header[0] & 0x1) << 2 | (header[1] >> 6);
+
+ mMeta = MakeAACCodecSpecificData(profile, sf_index, channel);
+
+ off64_t streamSize, numFrames = 0;
+ size_t frameSize = 0;
+ int64_t duration = 0;
+
+ if (mDataSource->getSize(&streamSize) == OK) {
+ while (offset < streamSize) {
+ if ((frameSize = getAdtsFrameLength(source, offset, NULL)) == 0) {
+ return;
+ }
+
+ mOffsetVector.push(offset);
+
+ offset += frameSize;
+ numFrames ++;
+ }
+
+ // Round up and get the duration
+ mFrameDurationUs = (1024 * 1000000ll + (sr - 1)) / sr;
+ duration = numFrames * mFrameDurationUs;
+ mMeta->setInt64(kKeyDuration, duration);
+ }
+
+ mInitCheck = OK;
+}
+
+AACExtractor::~AACExtractor() {
+}
+
+sp<MetaData> AACExtractor::getMetaData() {
+ sp<MetaData> meta = new MetaData;
+
+ if (mInitCheck != OK) {
+ return meta;
+ }
+
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC_ADTS);
+
+ return meta;
+}
+
+size_t AACExtractor::countTracks() {
+ return mInitCheck == OK ? 1 : 0;
+}
+
+sp<MediaSource> AACExtractor::getTrack(size_t index) {
+ if (mInitCheck != OK || index != 0) {
+ return NULL;
+ }
+
+ return new AACSource(mDataSource, mMeta, mOffsetVector, mFrameDurationUs);
+}
+
+sp<MetaData> AACExtractor::getTrackMetaData(size_t index, uint32_t flags) {
+ if (mInitCheck != OK || index != 0) {
+ return NULL;
+ }
+
+ return mMeta;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// 8192 = 2^13, 13bit AAC frame size (in bytes)
+const size_t AACSource::kMaxFrameSize = 8192;
+
+AACSource::AACSource(
+ const sp<DataSource> &source, const sp<MetaData> &meta,
+ const Vector<uint64_t> &offset_vector,
+ int64_t frame_duration_us)
+ : mDataSource(source),
+ mMeta(meta),
+ mOffset(0),
+ mCurrentTimeUs(0),
+ mStarted(false),
+ mGroup(NULL),
+ mOffsetVector(offset_vector),
+ mFrameDurationUs(frame_duration_us) {
+}
+
+AACSource::~AACSource() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t AACSource::start(MetaData *params) {
+ CHECK(!mStarted);
+
+ if (mOffsetVector.empty()) {
+ mOffset = 0;
+ } else {
+ mOffset = mOffsetVector.itemAt(0);
+ }
+
+ mCurrentTimeUs = 0;
+ mGroup = new MediaBufferGroup;
+ mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
+ mStarted = true;
+
+ return OK;
+}
+
+status_t AACSource::stop() {
+ CHECK(mStarted);
+
+ delete mGroup;
+ mGroup = NULL;
+
+ mStarted = false;
+ return OK;
+}
+
+sp<MetaData> AACSource::getFormat() {
+ return mMeta;
+}
+
+status_t AACSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+ if (mFrameDurationUs > 0) {
+ int64_t seekFrame = seekTimeUs / mFrameDurationUs;
+ mCurrentTimeUs = seekFrame * mFrameDurationUs;
+
+ mOffset = mOffsetVector.itemAt(seekFrame);
+ }
+ }
+
+ size_t frameSize, frameSizeWithoutHeader, headerSize;
+ if ((frameSize = getAdtsFrameLength(mDataSource, mOffset, &headerSize)) == 0) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ MediaBuffer *buffer;
+ status_t err = mGroup->acquire_buffer(&buffer);
+ if (err != OK) {
+ return err;
+ }
+
+ frameSizeWithoutHeader = frameSize - headerSize;
+ if (mDataSource->readAt(mOffset + headerSize, buffer->data(),
+ frameSizeWithoutHeader) != (ssize_t)frameSizeWithoutHeader) {
+ buffer->release();
+ buffer = NULL;
+
+ return ERROR_IO;
+ }
+
+ buffer->set_range(0, frameSizeWithoutHeader);
+ buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
+ buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+
+ mOffset += frameSize;
+ mCurrentTimeUs += mFrameDurationUs;
+
+ *out = buffer;
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool SniffAAC(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *meta) {
+ off64_t pos = 0;
+
+ for (;;) {
+ uint8_t id3header[10];
+ if (source->readAt(pos, id3header, sizeof(id3header))
+ < (ssize_t)sizeof(id3header)) {
+ return false;
+ }
+
+ if (memcmp("ID3", id3header, 3)) {
+ break;
+ }
+
+ // Skip the ID3v2 header.
+
+ size_t len =
+ ((id3header[6] & 0x7f) << 21)
+ | ((id3header[7] & 0x7f) << 14)
+ | ((id3header[8] & 0x7f) << 7)
+ | (id3header[9] & 0x7f);
+
+ len += 10;
+
+ pos += len;
+
+ ALOGV("skipped ID3 tag, new starting offset is %lld (0x%016llx)",
+ pos, pos);
+ }
+
+ uint8_t header[2];
+
+ if (source->readAt(pos, &header, 2) != 2) {
+ return false;
+ }
+
+ // ADTS syncword
+ if ((header[0] == 0xff) && ((header[1] & 0xf6) == 0xf0)) {
+ *mimeType = MEDIA_MIMETYPE_AUDIO_AAC_ADTS;
+ *confidence = 0.2;
+
+ *meta = new AMessage;
+ (*meta)->setInt64("offset", pos);
+
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace android
diff --git a/media/libstagefright/AACWriter.cpp b/media/libstagefright/AACWriter.cpp
new file mode 100644
index 0000000..9cdb463
--- /dev/null
+++ b/media/libstagefright/AACWriter.cpp
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "AACWriter"
+#include <utils/Log.h>
+
+#include <media/stagefright/AACWriter.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/mediarecorder.h>
+#include <sys/prctl.h>
+#include <fcntl.h>
+
+namespace android {
+
+AACWriter::AACWriter(const char *filename)
+ : mFd(-1),
+ mInitCheck(NO_INIT),
+ mStarted(false),
+ mPaused(false),
+ mResumed(false),
+ mChannelCount(-1),
+ mSampleRate(-1) {
+
+ ALOGV("AACWriter Constructor");
+
+ mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR);
+ if (mFd >= 0) {
+ mInitCheck = OK;
+ }
+}
+
+AACWriter::AACWriter(int fd)
+ : mFd(dup(fd)),
+ mInitCheck(mFd < 0? NO_INIT: OK),
+ mStarted(false),
+ mPaused(false),
+ mResumed(false),
+ mChannelCount(-1),
+ mSampleRate(-1) {
+}
+
+AACWriter::~AACWriter() {
+ if (mStarted) {
+ reset();
+ }
+
+ if (mFd != -1) {
+ close(mFd);
+ mFd = -1;
+ }
+}
+
+status_t AACWriter::initCheck() const {
+ return mInitCheck;
+}
+
+static int writeInt8(int fd, uint8_t x) {
+ return ::write(fd, &x, 1);
+}
+
+
+status_t AACWriter::addSource(const sp<MediaSource> &source) {
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mSource != NULL) {
+ ALOGE("AAC files only support a single track of audio.");
+ return UNKNOWN_ERROR;
+ }
+
+ sp<MetaData> meta = source->getFormat();
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC));
+ CHECK(meta->findInt32(kKeyChannelCount, &mChannelCount));
+ CHECK(meta->findInt32(kKeySampleRate, &mSampleRate));
+ CHECK(mChannelCount >= 1 && mChannelCount <= 2);
+
+ mSource = source;
+ return OK;
+}
+
+status_t AACWriter::start(MetaData *params) {
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mSource == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (mStarted && mPaused) {
+ mPaused = false;
+ mResumed = true;
+ return OK;
+ } else if (mStarted) {
+ // Already started, does nothing
+ return OK;
+ }
+
+ mFrameDurationUs = (kSamplesPerFrame * 1000000LL + (mSampleRate >> 1))
+ / mSampleRate;
+
+ status_t err = mSource->start();
+
+ if (err != OK) {
+ return err;
+ }
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+ mReachedEOS = false;
+ mDone = false;
+
+ pthread_create(&mThread, &attr, ThreadWrapper, this);
+ pthread_attr_destroy(&attr);
+
+ mStarted = true;
+
+ return OK;
+}
+
+status_t AACWriter::pause() {
+ if (!mStarted) {
+ return OK;
+ }
+ mPaused = true;
+ return OK;
+}
+
+status_t AACWriter::reset() {
+ if (!mStarted) {
+ return OK;
+ }
+
+ mDone = true;
+
+ void *dummy;
+ pthread_join(mThread, &dummy);
+
+ status_t err = (status_t) dummy;
+ {
+ status_t status = mSource->stop();
+ if (err == OK &&
+ (status != OK && status != ERROR_END_OF_STREAM)) {
+ err = status;
+ }
+ }
+
+ mStarted = false;
+ return err;
+}
+
+bool AACWriter::exceedsFileSizeLimit() {
+ if (mMaxFileSizeLimitBytes == 0) {
+ return false;
+ }
+ return mEstimatedSizeBytes >= mMaxFileSizeLimitBytes;
+}
+
+bool AACWriter::exceedsFileDurationLimit() {
+ if (mMaxFileDurationLimitUs == 0) {
+ return false;
+ }
+ return mEstimatedDurationUs >= mMaxFileDurationLimitUs;
+}
+
+// static
+void *AACWriter::ThreadWrapper(void *me) {
+ return (void *) static_cast<AACWriter *>(me)->threadFunc();
+}
+
+/*
+* Returns an index into the sample rate table if the
+* given sample rate is found; otherwise, returns -1.
+*/
+static bool getSampleRateTableIndex(int sampleRate, uint8_t* tableIndex) {
+ static const int kSampleRateTable[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000
+ };
+ const int tableSize =
+ sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]);
+
+ *tableIndex = 0;
+ for (int index = 0; index < tableSize; ++index) {
+ if (sampleRate == kSampleRateTable[index]) {
+ ALOGV("Sample rate: %d and index: %d",
+ sampleRate, index);
+ *tableIndex = index;
+ return true;
+ }
+ }
+
+ ALOGE("Sampling rate %d bps is not supported", sampleRate);
+ return false;
+}
+
+/*
+ * ADTS (Audio data transport stream) header structure.
+ * It consists of 7 or 9 bytes (with or without CRC):
+ * 12 bits of syncword 0xFFF, all bits must be 1
+ * 1 bit of field ID. 0 for MPEG-4, and 1 for MPEG-2
+ * 2 bits of MPEG layer. If in MPEG-TS, set to 0
+ * 1 bit of protection absense. Set to 1 if no CRC.
+ * 2 bits of profile code. Set to 1 (The MPEG-4 Audio
+ * object type minus 1. We are using AAC-LC = 2)
+ * 4 bits of sampling frequency index code (15 is not allowed)
+ * 1 bit of private stream. Set to 0.
+ * 3 bits of channel configuration code. 0 resevered for inband PCM
+ * 1 bit of originality. Set to 0.
+ * 1 bit of home. Set to 0.
+ * 1 bit of copyrighted steam. Set to 0.
+ * 1 bit of copyright start. Set to 0.
+ * 13 bits of frame length. It included 7 ot 9 bytes header length.
+ * it is set to (protection absense? 7: 9) + size(AAC frame)
+ * 11 bits of buffer fullness. 0x7FF for VBR.
+ * 2 bits of frames count in one packet. Set to 0.
+ */
+status_t AACWriter::writeAdtsHeader(uint32_t frameLength) {
+ uint8_t data = 0xFF;
+ write(mFd, &data, 1);
+
+ const uint8_t kFieldId = 0;
+ const uint8_t kMpegLayer = 0;
+ const uint8_t kProtectionAbsense = 1; // 1: kAdtsHeaderLength = 7
+ data = 0xF0;
+ data |= (kFieldId << 3);
+ data |= (kMpegLayer << 1);
+ data |= kProtectionAbsense;
+ write(mFd, &data, 1);
+
+ const uint8_t kProfileCode = 1; // AAC-LC
+ uint8_t kSampleFreqIndex;
+ CHECK(getSampleRateTableIndex(mSampleRate, &kSampleFreqIndex));
+ const uint8_t kPrivateStream = 0;
+ const uint8_t kChannelConfigCode = mChannelCount;
+ data = (kProfileCode << 6);
+ data |= (kSampleFreqIndex << 2);
+ data |= (kPrivateStream << 1);
+ data |= (kChannelConfigCode >> 2);
+ write(mFd, &data, 1);
+
+ // 4 bits from originality to copyright start
+ const uint8_t kCopyright = 0;
+ const uint32_t kFrameLength = frameLength;
+ data = ((kChannelConfigCode & 3) << 6);
+ data |= (kCopyright << 2);
+ data |= ((kFrameLength & 0x1800) >> 11);
+ write(mFd, &data, 1);
+
+ data = ((kFrameLength & 0x07F8) >> 3);
+ write(mFd, &data, 1);
+
+ const uint32_t kBufferFullness = 0x7FF; // VBR
+ data = ((kFrameLength & 0x07) << 5);
+ data |= ((kBufferFullness & 0x07C0) >> 6);
+ write(mFd, &data, 1);
+
+ const uint8_t kFrameCount = 0;
+ data = ((kBufferFullness & 0x03F) << 2);
+ data |= kFrameCount;
+ write(mFd, &data, 1);
+
+ return OK;
+}
+
+status_t AACWriter::threadFunc() {
+ mEstimatedDurationUs = 0;
+ mEstimatedSizeBytes = 0;
+ int64_t previousPausedDurationUs = 0;
+ int64_t maxTimestampUs = 0;
+ status_t err = OK;
+
+ prctl(PR_SET_NAME, (unsigned long)"AACWriterThread", 0, 0, 0);
+
+ while (!mDone && err == OK) {
+ MediaBuffer *buffer;
+ err = mSource->read(&buffer);
+
+ if (err != OK) {
+ break;
+ }
+
+ if (mPaused) {
+ buffer->release();
+ buffer = NULL;
+ continue;
+ }
+
+ mEstimatedSizeBytes += kAdtsHeaderLength + buffer->range_length();
+ if (exceedsFileSizeLimit()) {
+ buffer->release();
+ buffer = NULL;
+ notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
+ break;
+ }
+
+ int32_t isCodecSpecific = 0;
+ if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecSpecific) && isCodecSpecific) {
+ ALOGV("Drop codec specific info buffer");
+ buffer->release();
+ buffer = NULL;
+ continue;
+ }
+
+ int64_t timestampUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
+ if (timestampUs > mEstimatedDurationUs) {
+ mEstimatedDurationUs = timestampUs;
+ }
+ if (mResumed) {
+ previousPausedDurationUs += (timestampUs - maxTimestampUs - mFrameDurationUs);
+ mResumed = false;
+ }
+ timestampUs -= previousPausedDurationUs;
+ ALOGV("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;
+ }
+
+ // Each output AAC audio frame to the file contains
+ // 1. an ADTS header, followed by
+ // 2. the compressed audio data.
+ ssize_t dataLength = buffer->range_length();
+ uint8_t *data = (uint8_t *)buffer->data() + buffer->range_offset();
+ if (writeAdtsHeader(kAdtsHeaderLength + dataLength) != OK ||
+ dataLength != write(mFd, data, dataLength)) {
+ err = ERROR_IO;
+ }
+
+ buffer->release();
+ buffer = NULL;
+ }
+
+ close(mFd);
+ mFd = -1;
+ mReachedEOS = true;
+ if (err == ERROR_END_OF_STREAM) {
+ return OK;
+ }
+ return err;
+}
+
+bool AACWriter::reachedEOS() {
+ return mReachedEOS;
+}
+
+} // namespace android
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
new file mode 100644
index 0000000..db2beda
--- /dev/null
+++ b/media/libstagefright/ACodec.cpp
@@ -0,0 +1,3492 @@
+/*
+ * 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 "ACodec"
+
+#include <media/stagefright/ACodec.h>
+
+#include <binder/MemoryDealer.h>
+
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/NativeWindowWrapper.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+
+#include <OMX_Component.h>
+
+namespace android {
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+struct CodecObserver : public BnOMXObserver {
+ CodecObserver() {}
+
+ void setNotificationMessage(const sp<AMessage> &msg) {
+ mNotify = msg;
+ }
+
+ // from IOMXObserver
+ virtual void onMessage(const omx_message &omx_msg) {
+ sp<AMessage> msg = mNotify->dup();
+
+ msg->setInt32("type", omx_msg.type);
+ msg->setPointer("node", omx_msg.node);
+
+ switch (omx_msg.type) {
+ case omx_message::EVENT:
+ {
+ msg->setInt32("event", omx_msg.u.event_data.event);
+ msg->setInt32("data1", omx_msg.u.event_data.data1);
+ msg->setInt32("data2", omx_msg.u.event_data.data2);
+ break;
+ }
+
+ case omx_message::EMPTY_BUFFER_DONE:
+ {
+ msg->setPointer("buffer", omx_msg.u.buffer_data.buffer);
+ break;
+ }
+
+ case omx_message::FILL_BUFFER_DONE:
+ {
+ msg->setPointer(
+ "buffer", omx_msg.u.extended_buffer_data.buffer);
+ msg->setInt32(
+ "range_offset",
+ omx_msg.u.extended_buffer_data.range_offset);
+ msg->setInt32(
+ "range_length",
+ omx_msg.u.extended_buffer_data.range_length);
+ msg->setInt32(
+ "flags",
+ omx_msg.u.extended_buffer_data.flags);
+ msg->setInt64(
+ "timestamp",
+ omx_msg.u.extended_buffer_data.timestamp);
+ msg->setPointer(
+ "platform_private",
+ omx_msg.u.extended_buffer_data.platform_private);
+ msg->setPointer(
+ "data_ptr",
+ omx_msg.u.extended_buffer_data.data_ptr);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+
+ msg->post();
+ }
+
+protected:
+ virtual ~CodecObserver() {}
+
+private:
+ sp<AMessage> mNotify;
+
+ DISALLOW_EVIL_CONSTRUCTORS(CodecObserver);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct ACodec::BaseState : public AState {
+ BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
+
+protected:
+ enum PortMode {
+ KEEP_BUFFERS,
+ RESUBMIT_BUFFERS,
+ FREE_BUFFERS,
+ };
+
+ ACodec *mCodec;
+
+ virtual PortMode getPortMode(OMX_U32 portIndex);
+
+ virtual bool onMessageReceived(const sp<AMessage> &msg);
+
+ virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
+
+ virtual void onOutputBufferDrained(const sp<AMessage> &msg);
+ virtual void onInputBufferFilled(const sp<AMessage> &msg);
+
+ void postFillThisBuffer(BufferInfo *info);
+
+private:
+ bool onOMXMessage(const sp<AMessage> &msg);
+
+ bool onOMXEmptyBufferDone(IOMX::buffer_id bufferID);
+
+ bool onOMXFillBufferDone(
+ IOMX::buffer_id bufferID,
+ size_t rangeOffset, size_t rangeLength,
+ OMX_U32 flags,
+ int64_t timeUs,
+ void *platformPrivate,
+ void *dataPtr);
+
+ void getMoreInputDataIfPossible();
+
+ DISALLOW_EVIL_CONSTRUCTORS(BaseState);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct ACodec::UninitializedState : public ACodec::BaseState {
+ UninitializedState(ACodec *codec);
+
+protected:
+ virtual bool onMessageReceived(const sp<AMessage> &msg);
+ virtual void stateEntered();
+
+private:
+ void onSetup(const sp<AMessage> &msg);
+ bool onAllocateComponent(const sp<AMessage> &msg);
+
+ DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct ACodec::LoadedState : public ACodec::BaseState {
+ LoadedState(ACodec *codec);
+
+protected:
+ virtual bool onMessageReceived(const sp<AMessage> &msg);
+ virtual void stateEntered();
+
+private:
+ friend struct ACodec::UninitializedState;
+
+ bool onConfigureComponent(const sp<AMessage> &msg);
+ void onStart();
+ void onShutdown(bool keepComponentAllocated);
+
+ DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct ACodec::LoadedToIdleState : public ACodec::BaseState {
+ LoadedToIdleState(ACodec *codec);
+
+protected:
+ virtual bool onMessageReceived(const sp<AMessage> &msg);
+ virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
+ virtual void stateEntered();
+
+private:
+ status_t allocateBuffers();
+
+ DISALLOW_EVIL_CONSTRUCTORS(LoadedToIdleState);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct ACodec::IdleToExecutingState : public ACodec::BaseState {
+ IdleToExecutingState(ACodec *codec);
+
+protected:
+ virtual bool onMessageReceived(const sp<AMessage> &msg);
+ virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
+ virtual void stateEntered();
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(IdleToExecutingState);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct ACodec::ExecutingState : public ACodec::BaseState {
+ ExecutingState(ACodec *codec);
+
+ void submitOutputBuffers();
+
+ // Submit output buffers to the decoder, submit input buffers to client
+ // to fill with data.
+ void resume();
+
+ // Returns true iff input and output buffers are in play.
+ bool active() const { return mActive; }
+
+protected:
+ virtual PortMode getPortMode(OMX_U32 portIndex);
+ virtual bool onMessageReceived(const sp<AMessage> &msg);
+ virtual void stateEntered();
+
+ virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
+
+private:
+ bool mActive;
+
+ DISALLOW_EVIL_CONSTRUCTORS(ExecutingState);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct ACodec::OutputPortSettingsChangedState : public ACodec::BaseState {
+ OutputPortSettingsChangedState(ACodec *codec);
+
+protected:
+ virtual PortMode getPortMode(OMX_U32 portIndex);
+ virtual bool onMessageReceived(const sp<AMessage> &msg);
+ virtual void stateEntered();
+
+ virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(OutputPortSettingsChangedState);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct ACodec::ExecutingToIdleState : public ACodec::BaseState {
+ ExecutingToIdleState(ACodec *codec);
+
+protected:
+ virtual bool onMessageReceived(const sp<AMessage> &msg);
+ virtual void stateEntered();
+
+ virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
+
+ virtual void onOutputBufferDrained(const sp<AMessage> &msg);
+ virtual void onInputBufferFilled(const sp<AMessage> &msg);
+
+private:
+ void changeStateIfWeOwnAllBuffers();
+
+ bool mComponentNowIdle;
+
+ DISALLOW_EVIL_CONSTRUCTORS(ExecutingToIdleState);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct ACodec::IdleToLoadedState : public ACodec::BaseState {
+ IdleToLoadedState(ACodec *codec);
+
+protected:
+ virtual bool onMessageReceived(const sp<AMessage> &msg);
+ virtual void stateEntered();
+
+ virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(IdleToLoadedState);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct ACodec::FlushingState : public ACodec::BaseState {
+ FlushingState(ACodec *codec);
+
+protected:
+ virtual bool onMessageReceived(const sp<AMessage> &msg);
+ virtual void stateEntered();
+
+ virtual bool onOMXEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
+
+ virtual void onOutputBufferDrained(const sp<AMessage> &msg);
+ virtual void onInputBufferFilled(const sp<AMessage> &msg);
+
+private:
+ bool mFlushComplete[2];
+
+ void changeStateIfWeOwnAllBuffers();
+
+ DISALLOW_EVIL_CONSTRUCTORS(FlushingState);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::ACodec()
+ : mQuirks(0),
+ mNode(NULL),
+ mSentFormat(false),
+ mIsEncoder(false),
+ mShutdownInProgress(false) {
+ mUninitializedState = new UninitializedState(this);
+ mLoadedState = new LoadedState(this);
+ mLoadedToIdleState = new LoadedToIdleState(this);
+ mIdleToExecutingState = new IdleToExecutingState(this);
+ mExecutingState = new ExecutingState(this);
+
+ mOutputPortSettingsChangedState =
+ new OutputPortSettingsChangedState(this);
+
+ mExecutingToIdleState = new ExecutingToIdleState(this);
+ mIdleToLoadedState = new IdleToLoadedState(this);
+ mFlushingState = new FlushingState(this);
+
+ mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
+ mInputEOSResult = OK;
+
+ changeState(mUninitializedState);
+}
+
+ACodec::~ACodec() {
+}
+
+void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
+ mNotify = msg;
+}
+
+void ACodec::initiateSetup(const sp<AMessage> &msg) {
+ msg->setWhat(kWhatSetup);
+ msg->setTarget(id());
+ msg->post();
+}
+
+void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
+ msg->setWhat(kWhatAllocateComponent);
+ msg->setTarget(id());
+ msg->post();
+}
+
+void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
+ msg->setWhat(kWhatConfigureComponent);
+ msg->setTarget(id());
+ msg->post();
+}
+
+void ACodec::initiateStart() {
+ (new AMessage(kWhatStart, id()))->post();
+}
+
+void ACodec::signalFlush() {
+ ALOGV("[%s] signalFlush", mComponentName.c_str());
+ (new AMessage(kWhatFlush, id()))->post();
+}
+
+void ACodec::signalResume() {
+ (new AMessage(kWhatResume, id()))->post();
+}
+
+void ACodec::initiateShutdown(bool keepComponentAllocated) {
+ sp<AMessage> msg = new AMessage(kWhatShutdown, id());
+ msg->setInt32("keepComponentAllocated", keepComponentAllocated);
+ msg->post();
+}
+
+status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
+ CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
+
+ CHECK(mDealer[portIndex] == NULL);
+ CHECK(mBuffers[portIndex].isEmpty());
+
+ status_t err;
+ if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
+ err = allocateOutputBuffersFromNativeWindow();
+ } else {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = portIndex;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err == OK) {
+ ALOGV("[%s] Allocating %lu buffers of size %lu on %s port",
+ mComponentName.c_str(),
+ def.nBufferCountActual, def.nBufferSize,
+ portIndex == kPortIndexInput ? "input" : "output");
+
+ size_t totalSize = def.nBufferCountActual * def.nBufferSize;
+ mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
+
+ for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
+ sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
+ CHECK(mem.get() != NULL);
+
+ BufferInfo info;
+ info.mStatus = BufferInfo::OWNED_BY_US;
+
+ uint32_t requiresAllocateBufferBit =
+ (portIndex == kPortIndexInput)
+ ? OMXCodec::kRequiresAllocateBufferOnInputPorts
+ : OMXCodec::kRequiresAllocateBufferOnOutputPorts;
+
+ if (portIndex == kPortIndexInput && (mFlags & kFlagIsSecure)) {
+ mem.clear();
+
+ void *ptr;
+ err = mOMX->allocateBuffer(
+ mNode, portIndex, def.nBufferSize, &info.mBufferID,
+ &ptr);
+
+ info.mData = new ABuffer(ptr, def.nBufferSize);
+ } else if (mQuirks & requiresAllocateBufferBit) {
+ err = mOMX->allocateBufferWithBackup(
+ mNode, portIndex, mem, &info.mBufferID);
+ } else {
+ err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID);
+ }
+
+ if (mem != NULL) {
+ info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
+ }
+
+ mBuffers[portIndex].push(info);
+ }
+ }
+ }
+
+ if (err != OK) {
+ return err;
+ }
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatBuffersAllocated);
+
+ notify->setInt32("portIndex", portIndex);
+ for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
+ AString name = StringPrintf("buffer-id_%d", i);
+ notify->setPointer(name.c_str(), mBuffers[portIndex][i].mBufferID);
+
+ name = StringPrintf("data_%d", i);
+ notify->setBuffer(name.c_str(), mBuffers[portIndex][i].mData);
+ }
+
+ notify->post();
+
+ return OK;
+}
+
+status_t ACodec::allocateOutputBuffersFromNativeWindow() {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = native_window_set_scaling_mode(mNativeWindow.get(),
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = native_window_set_buffers_geometry(
+ mNativeWindow.get(),
+ def.format.video.nFrameWidth,
+ def.format.video.nFrameHeight,
+ def.format.video.eColorFormat);
+
+ if (err != 0) {
+ ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
+ strerror(-err), -err);
+ return err;
+ }
+
+ // Set up the native window.
+ OMX_U32 usage = 0;
+ err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
+ if (err != 0) {
+ ALOGW("querying usage flags from OMX IL component failed: %d", err);
+ // XXX: Currently this error is logged, but not fatal.
+ usage = 0;
+ }
+
+ err = native_window_set_usage(
+ mNativeWindow.get(),
+ usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
+
+ if (err != 0) {
+ ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
+ return err;
+ }
+
+ int minUndequeuedBufs = 0;
+ err = mNativeWindow->query(
+ mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+ &minUndequeuedBufs);
+
+ if (err != 0) {
+ ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
+ strerror(-err), -err);
+ return err;
+ }
+
+ // XXX: Is this the right logic to use? It's not clear to me what the OMX
+ // buffer counts refer to - how do they account for the renderer holding on
+ // to buffers?
+ if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
+ OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
+ def.nBufferCountActual = newBufferCount;
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ ALOGE("[%s] setting nBufferCountActual to %lu failed: %d",
+ mComponentName.c_str(), newBufferCount, err);
+ return err;
+ }
+ }
+
+ err = native_window_set_buffer_count(
+ mNativeWindow.get(), def.nBufferCountActual);
+
+ if (err != 0) {
+ ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
+ -err);
+ return err;
+ }
+
+ ALOGV("[%s] Allocating %lu buffers from a native window of size %lu on "
+ "output port",
+ mComponentName.c_str(), def.nBufferCountActual, def.nBufferSize);
+
+ // Dequeue buffers and send them to OMX
+ for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
+ ANativeWindowBuffer *buf;
+ err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
+ if (err != 0) {
+ ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
+ break;
+ }
+
+ sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
+ BufferInfo info;
+ info.mStatus = BufferInfo::OWNED_BY_US;
+ info.mData = new ABuffer(0);
+ info.mGraphicBuffer = graphicBuffer;
+ mBuffers[kPortIndexOutput].push(info);
+
+ IOMX::buffer_id bufferId;
+ err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
+ &bufferId);
+ if (err != 0) {
+ ALOGE("registering GraphicBuffer %lu with OMX IL component failed: "
+ "%d", i, err);
+ break;
+ }
+
+ mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
+
+ ALOGV("[%s] Registered graphic buffer with ID %p (pointer = %p)",
+ mComponentName.c_str(),
+ bufferId, graphicBuffer.get());
+ }
+
+ OMX_U32 cancelStart;
+ OMX_U32 cancelEnd;
+
+ if (err != 0) {
+ // If an error occurred while dequeuing we need to cancel any buffers
+ // that were dequeued.
+ cancelStart = 0;
+ cancelEnd = mBuffers[kPortIndexOutput].size();
+ } else {
+ // Return the last two buffers to the native window.
+ cancelStart = def.nBufferCountActual - minUndequeuedBufs;
+ cancelEnd = def.nBufferCountActual;
+ }
+
+ for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
+ BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
+ cancelBufferToNativeWindow(info);
+ }
+
+ return err;
+}
+
+status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
+ CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
+
+ ALOGV("[%s] Calling cancelBuffer on buffer %p",
+ mComponentName.c_str(), info->mBufferID);
+
+ int err = mNativeWindow->cancelBuffer(
+ mNativeWindow.get(), info->mGraphicBuffer.get());
+
+ CHECK_EQ(err, 0);
+
+ info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
+
+ return OK;
+}
+
+ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
+ ANativeWindowBuffer *buf;
+ if (mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf) != 0) {
+ ALOGE("dequeueBuffer failed.");
+ return NULL;
+ }
+
+ for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
+ BufferInfo *info =
+ &mBuffers[kPortIndexOutput].editItemAt(i);
+
+ if (info->mGraphicBuffer->handle == buf->handle) {
+ CHECK_EQ((int)info->mStatus,
+ (int)BufferInfo::OWNED_BY_NATIVE_WINDOW);
+
+ info->mStatus = BufferInfo::OWNED_BY_US;
+
+ return info;
+ }
+ }
+
+ TRESPASS();
+
+ return NULL;
+}
+
+status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
+ for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
+ CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
+ }
+
+ mDealer[portIndex].clear();
+
+ return OK;
+}
+
+status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
+ for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
+ BufferInfo *info =
+ &mBuffers[kPortIndexOutput].editItemAt(i);
+
+ if (info->mStatus !=
+ BufferInfo::OWNED_BY_COMPONENT) {
+ // We shouldn't have sent out any buffers to the client at this
+ // point.
+ CHECK_NE((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
+
+ CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
+ }
+ }
+
+ return OK;
+}
+
+status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
+ BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
+
+ CHECK(info->mStatus == BufferInfo::OWNED_BY_US
+ || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
+
+ if (portIndex == kPortIndexOutput && mNativeWindow != NULL
+ && info->mStatus == BufferInfo::OWNED_BY_US) {
+ CHECK_EQ((status_t)OK, cancelBufferToNativeWindow(info));
+ }
+
+ CHECK_EQ(mOMX->freeBuffer(
+ mNode, portIndex, info->mBufferID),
+ (status_t)OK);
+
+ mBuffers[portIndex].removeAt(i);
+
+ return OK;
+}
+
+ACodec::BufferInfo *ACodec::findBufferByID(
+ uint32_t portIndex, IOMX::buffer_id bufferID,
+ ssize_t *index) {
+ for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
+ BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
+
+ if (info->mBufferID == bufferID) {
+ if (index != NULL) {
+ *index = i;
+ }
+ return info;
+ }
+ }
+
+ TRESPASS();
+
+ return NULL;
+}
+
+status_t ACodec::setComponentRole(
+ bool isEncoder, const char *mime) {
+ struct MimeToRole {
+ const char *mime;
+ const char *decoderRole;
+ const char *encoderRole;
+ };
+
+ static const MimeToRole kMimeToRole[] = {
+ { MEDIA_MIMETYPE_AUDIO_MPEG,
+ "audio_decoder.mp3", "audio_encoder.mp3" },
+ { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
+ "audio_decoder.mp1", "audio_encoder.mp1" },
+ { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
+ "audio_decoder.mp2", "audio_encoder.mp2" },
+ { MEDIA_MIMETYPE_AUDIO_AMR_NB,
+ "audio_decoder.amrnb", "audio_encoder.amrnb" },
+ { MEDIA_MIMETYPE_AUDIO_AMR_WB,
+ "audio_decoder.amrwb", "audio_encoder.amrwb" },
+ { MEDIA_MIMETYPE_AUDIO_AAC,
+ "audio_decoder.aac", "audio_encoder.aac" },
+ { MEDIA_MIMETYPE_AUDIO_VORBIS,
+ "audio_decoder.vorbis", "audio_encoder.vorbis" },
+ { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
+ "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
+ { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
+ "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
+ { MEDIA_MIMETYPE_VIDEO_AVC,
+ "video_decoder.avc", "video_encoder.avc" },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4,
+ "video_decoder.mpeg4", "video_encoder.mpeg4" },
+ { MEDIA_MIMETYPE_VIDEO_H263,
+ "video_decoder.h263", "video_encoder.h263" },
+ { MEDIA_MIMETYPE_VIDEO_VPX,
+ "video_decoder.vpx", "video_encoder.vpx" },
+ };
+
+ static const size_t kNumMimeToRole =
+ sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
+
+ size_t i;
+ for (i = 0; i < kNumMimeToRole; ++i) {
+ if (!strcasecmp(mime, kMimeToRole[i].mime)) {
+ break;
+ }
+ }
+
+ if (i == kNumMimeToRole) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ const char *role =
+ isEncoder ? kMimeToRole[i].encoderRole
+ : kMimeToRole[i].decoderRole;
+
+ if (role != NULL) {
+ OMX_PARAM_COMPONENTROLETYPE roleParams;
+ InitOMXParams(&roleParams);
+
+ strncpy((char *)roleParams.cRole,
+ role, OMX_MAX_STRINGNAME_SIZE - 1);
+
+ roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
+
+ status_t err = mOMX->setParameter(
+ mNode, OMX_IndexParamStandardComponentRole,
+ &roleParams, sizeof(roleParams));
+
+ if (err != OK) {
+ ALOGW("[%s] Failed to set standard component role '%s'.",
+ mComponentName.c_str(), role);
+
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+status_t ACodec::configureCodec(
+ const char *mime, const sp<AMessage> &msg) {
+ int32_t encoder;
+ if (!msg->findInt32("encoder", &encoder)) {
+ encoder = false;
+ }
+
+ mIsEncoder = encoder;
+
+ status_t err = setComponentRole(encoder /* isEncoder */, mime);
+
+ if (err != OK) {
+ return err;
+ }
+
+ int32_t bitRate = 0;
+ if (encoder && !msg->findInt32("bitrate", &bitRate)) {
+ return INVALID_OPERATION;
+ }
+
+ if (!strncasecmp(mime, "video/", 6)) {
+ if (encoder) {
+ err = setupVideoEncoder(mime, msg);
+ } else {
+ int32_t width, height;
+ if (!msg->findInt32("width", &width)
+ || !msg->findInt32("height", &height)) {
+ err = INVALID_OPERATION;
+ } else {
+ err = setupVideoDecoder(mime, width, height);
+ }
+ }
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+ int32_t numChannels, sampleRate;
+ if (!msg->findInt32("channel-count", &numChannels)
+ || !msg->findInt32("sample-rate", &sampleRate)) {
+ err = INVALID_OPERATION;
+ } else {
+ int32_t isADTS;
+ if (!msg->findInt32("is-adts", &isADTS)) {
+ isADTS = 0;
+ }
+
+ err = setupAACCodec(
+ encoder, numChannels, sampleRate, bitRate, isADTS != 0);
+ }
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
+ err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
+ err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
+ || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
+ // These are PCM-like formats with a fixed sample rate but
+ // a variable number of channels.
+
+ int32_t numChannels;
+ if (!msg->findInt32("channel-count", &numChannels)) {
+ err = INVALID_OPERATION;
+ } else {
+ err = setupG711Codec(encoder, numChannels);
+ }
+ }
+
+ int32_t maxInputSize;
+ if (msg->findInt32("max-input-size", &maxInputSize)) {
+ err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
+ } else if (!strcmp("OMX.Nvidia.aac.decoder", mComponentName.c_str())) {
+ err = setMinBufferSize(kPortIndexInput, 8192); // XXX
+ }
+
+ return err;
+}
+
+status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = portIndex;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (def.nBufferSize >= size) {
+ return OK;
+ }
+
+ def.nBufferSize = size;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ CHECK(def.nBufferSize >= size);
+
+ return OK;
+}
+
+status_t ACodec::selectAudioPortFormat(
+ OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE desiredFormat) {
+ OMX_AUDIO_PARAM_PORTFORMATTYPE format;
+ InitOMXParams(&format);
+
+ format.nPortIndex = portIndex;
+ for (OMX_U32 index = 0;; ++index) {
+ format.nIndex = index;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioPortFormat,
+ &format, sizeof(format));
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (format.eEncoding == desiredFormat) {
+ break;
+ }
+ }
+
+ return mOMX->setParameter(
+ mNode, OMX_IndexParamAudioPortFormat, &format, sizeof(format));
+}
+
+status_t ACodec::setupAACCodec(
+ bool encoder,
+ int32_t numChannels, int32_t sampleRate, int32_t bitRate, bool isADTS) {
+ if (encoder && isADTS) {
+ return -EINVAL;
+ }
+
+ status_t err = setupRawAudioFormat(
+ encoder ? kPortIndexInput : kPortIndexOutput,
+ sampleRate,
+ numChannels);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (encoder) {
+ err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);
+
+ if (err != OK) {
+ return err;
+ }
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexOutput;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ def.format.audio.bFlagErrorConcealment = OMX_TRUE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ OMX_AUDIO_PARAM_AACPROFILETYPE profile;
+ InitOMXParams(&profile);
+ profile.nPortIndex = kPortIndexOutput;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+
+ if (err != OK) {
+ return err;
+ }
+
+ 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;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+
+ if (err != OK) {
+ return err;
+ }
+
+ return err;
+ }
+
+ OMX_AUDIO_PARAM_AACPROFILETYPE profile;
+ InitOMXParams(&profile);
+ profile.nPortIndex = kPortIndexInput;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+
+ if (err != OK) {
+ return err;
+ }
+
+ profile.nChannels = numChannels;
+ profile.nSampleRate = sampleRate;
+
+ profile.eAACStreamFormat =
+ isADTS
+ ? OMX_AUDIO_AACStreamFormatMP4ADTS
+ : OMX_AUDIO_AACStreamFormatMP4FF;
+
+ return mOMX->setParameter(
+ mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+}
+
+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;
+ }
+}
+
+status_t ACodec::setupAMRCodec(bool encoder, bool isWAMR, int32_t bitrate) {
+ OMX_AUDIO_PARAM_AMRTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = encoder ? kPortIndexOutput : kPortIndexInput;
+
+ status_t err =
+ mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
+ def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitrate);
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ return setupRawAudioFormat(
+ encoder ? kPortIndexInput : kPortIndexOutput,
+ isWAMR ? 16000 : 8000 /* sampleRate */,
+ 1 /* numChannels */);
+}
+
+status_t ACodec::setupG711Codec(bool encoder, int32_t numChannels) {
+ CHECK(!encoder); // XXX TODO
+
+ return setupRawAudioFormat(
+ kPortIndexInput, 8000 /* sampleRate */, numChannels);
+}
+
+status_t ACodec::setupRawAudioFormat(
+ OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = portIndex;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
+ InitOMXParams(&pcmParams);
+ pcmParams.nPortIndex = portIndex;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+
+ if (err != OK) {
+ return err;
+ }
+
+ pcmParams.nChannels = numChannels;
+ pcmParams.eNumData = OMX_NumericalDataSigned;
+ pcmParams.bInterleaved = OMX_TRUE;
+ pcmParams.nBitPerSample = 16;
+ pcmParams.nSamplingRate = sampleRate;
+ pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
+
+ if (numChannels == 1) {
+ pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
+ } else {
+ CHECK_EQ(numChannels, 2);
+
+ pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+ pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+ }
+
+ return mOMX->setParameter(
+ mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+}
+
+status_t ACodec::setVideoPortFormatType(
+ OMX_U32 portIndex,
+ OMX_VIDEO_CODINGTYPE compressionFormat,
+ OMX_COLOR_FORMATTYPE colorFormat) {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+ InitOMXParams(&format);
+ format.nPortIndex = portIndex;
+ format.nIndex = 0;
+ bool found = false;
+
+ OMX_U32 index = 0;
+ for (;;) {
+ format.nIndex = index;
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+
+ if (err != OK) {
+ return err;
+ }
+
+ // The following assertion is violated by TI's video decoder.
+ // CHECK_EQ(format.nIndex, index);
+
+ if (!strcmp("OMX.TI.Video.encoder", mComponentName.c_str())) {
+ if (portIndex == kPortIndexInput
+ && colorFormat == format.eColorFormat) {
+ // eCompressionFormat does not seem right.
+ found = true;
+ break;
+ }
+ if (portIndex == kPortIndexOutput
+ && compressionFormat == format.eCompressionFormat) {
+ // eColorFormat does not seem right.
+ found = true;
+ break;
+ }
+ }
+
+ if (format.eCompressionFormat == compressionFormat
+ && format.eColorFormat == colorFormat) {
+ found = true;
+ break;
+ }
+
+ ++index;
+ }
+
+ if (!found) {
+ return UNKNOWN_ERROR;
+ }
+
+ status_t err = mOMX->setParameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+
+ return err;
+}
+
+status_t ACodec::setSupportedOutputFormat() {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+ InitOMXParams(&format);
+ format.nPortIndex = kPortIndexOutput;
+ format.nIndex = 0;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+ CHECK_EQ(err, (status_t)OK);
+ CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
+
+ CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
+ || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
+ || format.eColorFormat == OMX_COLOR_FormatCbYCrY
+ || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
+ || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
+
+ return mOMX->setParameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+}
+
+static status_t GetVideoCodingTypeFromMime(
+ const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
+ if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
+ *codingType = OMX_VIDEO_CodingAVC;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
+ *codingType = OMX_VIDEO_CodingMPEG4;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
+ *codingType = OMX_VIDEO_CodingH263;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
+ *codingType = OMX_VIDEO_CodingMPEG2;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) {
+ *codingType = OMX_VIDEO_CodingVPX;
+ } else {
+ *codingType = OMX_VIDEO_CodingUnused;
+ return ERROR_UNSUPPORTED;
+ }
+
+ return OK;
+}
+
+status_t ACodec::setupVideoDecoder(
+ const char *mime, int32_t width, int32_t height) {
+ OMX_VIDEO_CODINGTYPE compressionFormat;
+ status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = setVideoPortFormatType(
+ kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = setSupportedOutputFormat();
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = setVideoFormatOnPort(
+ kPortIndexInput, width, height, compressionFormat);
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = setVideoFormatOnPort(
+ kPortIndexOutput, width, height, OMX_VIDEO_CodingUnused);
+
+ if (err != OK) {
+ return err;
+ }
+
+ return OK;
+}
+
+status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
+ int32_t tmp;
+ if (!msg->findInt32("color-format", &tmp)) {
+ return INVALID_OPERATION;
+ }
+
+ OMX_COLOR_FORMATTYPE colorFormat =
+ static_cast<OMX_COLOR_FORMATTYPE>(tmp);
+
+ status_t err = setVideoPortFormatType(
+ kPortIndexInput, OMX_VIDEO_CodingUnused, colorFormat);
+
+ if (err != OK) {
+ ALOGE("[%s] does not support color format %d",
+ mComponentName.c_str(), colorFormat);
+
+ return err;
+ }
+
+ /* Input port configuration */
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+
+ OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
+
+ def.nPortIndex = kPortIndexInput;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ int32_t width, height, bitrate;
+ if (!msg->findInt32("width", &width)
+ || !msg->findInt32("height", &height)
+ || !msg->findInt32("bitrate", &bitrate)) {
+ return INVALID_OPERATION;
+ }
+
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+
+ int32_t stride;
+ if (!msg->findInt32("stride", &stride)) {
+ stride = width;
+ }
+
+ video_def->nStride = stride;
+
+ int32_t sliceHeight;
+ if (!msg->findInt32("slice-height", &sliceHeight)) {
+ sliceHeight = height;
+ }
+
+ video_def->nSliceHeight = sliceHeight;
+
+ def.nBufferSize = (video_def->nStride * video_def->nSliceHeight * 3) / 2;
+
+ float frameRate;
+ if (!msg->findFloat("frame-rate", &frameRate)) {
+ int32_t tmp;
+ if (!msg->findInt32("frame-rate", &tmp)) {
+ return INVALID_OPERATION;
+ }
+ frameRate = (float)tmp;
+ }
+
+ video_def->xFramerate = (OMX_U32)(frameRate * 65536.0f);
+ video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
+ video_def->eColorFormat = colorFormat;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ ALOGE("[%s] failed to set input port definition parameters.",
+ mComponentName.c_str());
+
+ return err;
+ }
+
+ /* Output port configuration */
+
+ OMX_VIDEO_CODINGTYPE compressionFormat;
+ err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = setVideoPortFormatType(
+ kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
+
+ if (err != OK) {
+ ALOGE("[%s] does not support compression format %d",
+ mComponentName.c_str(), compressionFormat);
+
+ return err;
+ }
+
+ def.nPortIndex = kPortIndexOutput;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+ video_def->xFramerate = 0;
+ video_def->nBitrate = bitrate;
+ video_def->eCompressionFormat = compressionFormat;
+ video_def->eColorFormat = OMX_COLOR_FormatUnused;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ ALOGE("[%s] failed to set output port definition parameters.",
+ mComponentName.c_str());
+
+ return err;
+ }
+
+ switch (compressionFormat) {
+ case OMX_VIDEO_CodingMPEG4:
+ err = setupMPEG4EncoderParameters(msg);
+ break;
+
+ case OMX_VIDEO_CodingH263:
+ err = setupH263EncoderParameters(msg);
+ break;
+
+ case OMX_VIDEO_CodingAVC:
+ err = setupAVCEncoderParameters(msg);
+ break;
+
+ default:
+ break;
+ }
+
+ ALOGI("setupVideoEncoder succeeded");
+
+ return err;
+}
+
+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 ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
+ int32_t bitrate, iFrameInterval;
+ if (!msg->findInt32("bitrate", &bitrate)
+ || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
+ return INVALID_OPERATION;
+ }
+
+ float frameRate;
+ if (!msg->findFloat("frame-rate", &frameRate)) {
+ int32_t tmp;
+ if (!msg->findInt32("frame-rate", &tmp)) {
+ return INVALID_OPERATION;
+ }
+ frameRate = (float)tmp;
+ }
+
+ OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
+ InitOMXParams(&mpeg4type);
+ mpeg4type.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
+
+ if (err != OK) {
+ return err;
+ }
+
+ mpeg4type.nSliceHeaderSpacing = 0;
+ mpeg4type.bSVH = OMX_FALSE;
+ mpeg4type.bGov = OMX_FALSE;
+
+ mpeg4type.nAllowedPictureTypes =
+ OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
+
+ mpeg4type.nPFrames = setPFramesSpacing(iFrameInterval, 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;
+
+ int32_t profile;
+ if (msg->findInt32("profile", &profile)) {
+ int32_t level;
+ if (!msg->findInt32("level", &level)) {
+ return INVALID_OPERATION;
+ }
+
+ err = verifySupportForProfileAndLevel(profile, level);
+
+ if (err != OK) {
+ return err;
+ }
+
+ mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile);
+ mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
+ }
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = configureBitrate(bitrate);
+
+ if (err != OK) {
+ return err;
+ }
+
+ return setupErrorCorrectionParameters();
+}
+
+status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
+ int32_t bitrate, iFrameInterval;
+ if (!msg->findInt32("bitrate", &bitrate)
+ || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
+ return INVALID_OPERATION;
+ }
+
+ float frameRate;
+ if (!msg->findFloat("frame-rate", &frameRate)) {
+ int32_t tmp;
+ if (!msg->findInt32("frame-rate", &tmp)) {
+ return INVALID_OPERATION;
+ }
+ frameRate = (float)tmp;
+ }
+
+ OMX_VIDEO_PARAM_H263TYPE h263type;
+ InitOMXParams(&h263type);
+ h263type.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
+
+ if (err != OK) {
+ return err;
+ }
+
+ h263type.nAllowedPictureTypes =
+ OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
+
+ h263type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
+ if (h263type.nPFrames == 0) {
+ h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+ }
+ h263type.nBFrames = 0;
+
+ int32_t profile;
+ if (msg->findInt32("profile", &profile)) {
+ int32_t level;
+ if (!msg->findInt32("level", &level)) {
+ return INVALID_OPERATION;
+ }
+
+ err = verifySupportForProfileAndLevel(profile, level);
+
+ if (err != OK) {
+ return err;
+ }
+
+ h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profile);
+ h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(level);
+ }
+
+ h263type.bPLUSPTYPEAllowed = OMX_FALSE;
+ h263type.bForceRoundingTypeToZero = OMX_FALSE;
+ h263type.nPictureHeaderRepetition = 0;
+ h263type.nGOBHeaderInterval = 0;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = configureBitrate(bitrate);
+
+ if (err != OK) {
+ return err;
+ }
+
+ return setupErrorCorrectionParameters();
+}
+
+status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
+ int32_t bitrate, iFrameInterval;
+ if (!msg->findInt32("bitrate", &bitrate)
+ || !msg->findInt32("i-frame-interval", &iFrameInterval)) {
+ return INVALID_OPERATION;
+ }
+
+ float frameRate;
+ if (!msg->findFloat("frame-rate", &frameRate)) {
+ int32_t tmp;
+ if (!msg->findInt32("frame-rate", &tmp)) {
+ return INVALID_OPERATION;
+ }
+ frameRate = (float)tmp;
+ }
+
+ OMX_VIDEO_PARAM_AVCTYPE h264type;
+ InitOMXParams(&h264type);
+ h264type.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
+
+ if (err != OK) {
+ return err;
+ }
+
+ h264type.nAllowedPictureTypes =
+ OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
+
+ int32_t profile;
+ if (msg->findInt32("profile", &profile)) {
+ int32_t level;
+ if (!msg->findInt32("level", &level)) {
+ return INVALID_OPERATION;
+ }
+
+ err = verifySupportForProfileAndLevel(profile, level);
+
+ if (err != OK) {
+ return err;
+ }
+
+ h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile);
+ h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
+ }
+
+ // XXX
+ if (!strncmp(mComponentName.c_str(), "OMX.TI.DUCATI1", 14)) {
+ h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
+ }
+
+ if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
+ h264type.nSliceHeaderSpacing = 0;
+ h264type.bUseHadamard = OMX_TRUE;
+ h264type.nRefFrames = 1;
+ h264type.nBFrames = 0;
+ h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
+ if (h264type.nPFrames == 0) {
+ h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+ }
+ 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.bFrameMBsOnly = OMX_TRUE;
+ h264type.bMBAFF = OMX_FALSE;
+ h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
+
+ if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName.c_str())) {
+ h264type.eLevel = OMX_VIDEO_AVCLevelMax;
+ }
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
+
+ if (err != OK) {
+ return err;
+ }
+
+ return configureBitrate(bitrate);
+}
+
+status_t ACodec::verifySupportForProfileAndLevel(
+ int32_t profile, int32_t level) {
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = kPortIndexOutput;
+
+ for (params.nProfileIndex = 0;; ++params.nProfileIndex) {
+ status_t err = mOMX->getParameter(
+ mNode,
+ OMX_IndexParamVideoProfileLevelQuerySupported,
+ &params,
+ sizeof(params));
+
+ if (err != OK) {
+ return err;
+ }
+
+ int32_t supportedProfile = static_cast<int32_t>(params.eProfile);
+ int32_t supportedLevel = static_cast<int32_t>(params.eLevel);
+
+ if (profile == supportedProfile && level <= supportedLevel) {
+ return OK;
+ }
+ }
+}
+
+status_t ACodec::configureBitrate(int32_t bitrate) {
+ OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
+ InitOMXParams(&bitrateType);
+ bitrateType.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoBitrate,
+ &bitrateType, sizeof(bitrateType));
+
+ if (err != OK) {
+ return err;
+ }
+
+ bitrateType.eControlRate = OMX_Video_ControlRateVariable;
+ bitrateType.nTargetBitrate = bitrate;
+
+ return mOMX->setParameter(
+ mNode, OMX_IndexParamVideoBitrate,
+ &bitrateType, sizeof(bitrateType));
+}
+
+status_t ACodec::setupErrorCorrectionParameters() {
+ OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
+ InitOMXParams(&errorCorrectionType);
+ errorCorrectionType.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoErrorCorrection,
+ &errorCorrectionType, sizeof(errorCorrectionType));
+
+ if (err != OK) {
+ return OK; // Optional feature. Ignore this failure
+ }
+
+ errorCorrectionType.bEnableHEC = OMX_FALSE;
+ errorCorrectionType.bEnableResync = OMX_TRUE;
+ errorCorrectionType.nResynchMarkerSpacing = 256;
+ errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
+ errorCorrectionType.bEnableRVLC = OMX_FALSE;
+
+ return mOMX->setParameter(
+ mNode, OMX_IndexParamVideoErrorCorrection,
+ &errorCorrectionType, sizeof(errorCorrectionType));
+}
+
+status_t ACodec::setVideoFormatOnPort(
+ OMX_U32 portIndex,
+ int32_t width, int32_t height, OMX_VIDEO_CODINGTYPE compressionFormat) {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = portIndex;
+
+ OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ CHECK_EQ(err, (status_t)OK);
+
+ if (portIndex == kPortIndexInput) {
+ // XXX Need a (much) better heuristic to compute input buffer sizes.
+ const size_t X = 64 * 1024;
+ if (def.nBufferSize < X) {
+ def.nBufferSize = X;
+ }
+ }
+
+ CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
+
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+
+ if (portIndex == kPortIndexInput) {
+ video_def->eCompressionFormat = compressionFormat;
+ video_def->eColorFormat = OMX_COLOR_FormatUnused;
+ }
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ return err;
+}
+
+status_t ACodec::initNativeWindow() {
+ if (mNativeWindow != NULL) {
+ return mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
+ }
+
+ mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_FALSE);
+ return OK;
+}
+
+size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
+ size_t n = 0;
+
+ for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
+ const BufferInfo &info = mBuffers[portIndex].itemAt(i);
+
+ if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
+ ++n;
+ }
+ }
+
+ return n;
+}
+
+bool ACodec::allYourBuffersAreBelongToUs(
+ OMX_U32 portIndex) {
+ for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
+ BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
+
+ if (info->mStatus != BufferInfo::OWNED_BY_US
+ && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
+ ALOGV("[%s] Buffer %p on port %ld still has status %d",
+ mComponentName.c_str(),
+ info->mBufferID, portIndex, info->mStatus);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ACodec::allYourBuffersAreBelongToUs() {
+ return allYourBuffersAreBelongToUs(kPortIndexInput)
+ && allYourBuffersAreBelongToUs(kPortIndexOutput);
+}
+
+void ACodec::deferMessage(const sp<AMessage> &msg) {
+ bool wasEmptyBefore = mDeferredQueue.empty();
+ mDeferredQueue.push_back(msg);
+}
+
+void ACodec::processDeferredMessages() {
+ List<sp<AMessage> > queue = mDeferredQueue;
+ mDeferredQueue.clear();
+
+ List<sp<AMessage> >::iterator it = queue.begin();
+ while (it != queue.end()) {
+ onMessageReceived(*it++);
+ }
+}
+
+void ACodec::sendFormatChange() {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatOutputFormatChanged);
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexOutput;
+
+ CHECK_EQ(mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
+ (status_t)OK);
+
+ CHECK_EQ((int)def.eDir, (int)OMX_DirOutput);
+
+ switch (def.eDomain) {
+ case OMX_PortDomainVideo:
+ {
+ OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
+
+ notify->setString("mime", MEDIA_MIMETYPE_VIDEO_RAW);
+ notify->setInt32("width", videoDef->nFrameWidth);
+ notify->setInt32("height", videoDef->nFrameHeight);
+ notify->setInt32("stride", videoDef->nStride);
+ notify->setInt32("slice-height", videoDef->nSliceHeight);
+ notify->setInt32("color-format", videoDef->eColorFormat);
+
+ OMX_CONFIG_RECTTYPE rect;
+ InitOMXParams(&rect);
+ rect.nPortIndex = kPortIndexOutput;
+
+ if (mOMX->getConfig(
+ mNode, OMX_IndexConfigCommonOutputCrop,
+ &rect, sizeof(rect)) != OK) {
+ rect.nLeft = 0;
+ rect.nTop = 0;
+ rect.nWidth = videoDef->nFrameWidth;
+ rect.nHeight = videoDef->nFrameHeight;
+ }
+
+ CHECK_GE(rect.nLeft, 0);
+ CHECK_GE(rect.nTop, 0);
+ CHECK_GE(rect.nWidth, 0u);
+ CHECK_GE(rect.nHeight, 0u);
+ CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
+ CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
+
+ notify->setRect(
+ "crop",
+ rect.nLeft,
+ rect.nTop,
+ rect.nLeft + rect.nWidth - 1,
+ rect.nTop + rect.nHeight - 1);
+
+ if (mNativeWindow != NULL) {
+ android_native_rect_t crop;
+ crop.left = rect.nLeft;
+ crop.top = rect.nTop;
+ crop.right = rect.nLeft + rect.nWidth;
+ crop.bottom = rect.nTop + rect.nHeight;
+
+ CHECK_EQ(0, native_window_set_crop(
+ mNativeWindow.get(), &crop));
+ }
+ break;
+ }
+
+ case OMX_PortDomainAudio:
+ {
+ OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
+ CHECK_EQ((int)audioDef->eEncoding, (int)OMX_AUDIO_CodingPCM);
+
+ OMX_AUDIO_PARAM_PCMMODETYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = kPortIndexOutput;
+
+ CHECK_EQ(mOMX->getParameter(
+ mNode, OMX_IndexParamAudioPcm,
+ &params, sizeof(params)),
+ (status_t)OK);
+
+ CHECK(params.nChannels == 1 || params.bInterleaved);
+ CHECK_EQ(params.nBitPerSample, 16u);
+ CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
+ CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
+
+ notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
+ notify->setInt32("channel-count", params.nChannels);
+ notify->setInt32("sample-rate", params.nSamplingRate);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+
+ notify->post();
+
+ mSentFormat = true;
+}
+
+void ACodec::signalError(OMX_ERRORTYPE error, status_t internalError) {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatError);
+ notify->setInt32("omx-error", error);
+ notify->setInt32("err", internalError);
+ notify->post();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
+ : AState(parentState),
+ mCodec(codec) {
+}
+
+ACodec::BaseState::PortMode ACodec::BaseState::getPortMode(OMX_U32 portIndex) {
+ return KEEP_BUFFERS;
+}
+
+bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatInputBufferFilled:
+ {
+ onInputBufferFilled(msg);
+ break;
+ }
+
+ case kWhatOutputBufferDrained:
+ {
+ onOutputBufferDrained(msg);
+ break;
+ }
+
+ case ACodec::kWhatOMXMessage:
+ {
+ return onOMXMessage(msg);
+ }
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
+ int32_t type;
+ CHECK(msg->findInt32("type", &type));
+
+ IOMX::node_id nodeID;
+ CHECK(msg->findPointer("node", &nodeID));
+ CHECK_EQ(nodeID, mCodec->mNode);
+
+ switch (type) {
+ case omx_message::EVENT:
+ {
+ int32_t event, data1, data2;
+ CHECK(msg->findInt32("event", &event));
+ CHECK(msg->findInt32("data1", &data1));
+ CHECK(msg->findInt32("data2", &data2));
+
+ if (event == OMX_EventCmdComplete
+ && data1 == OMX_CommandFlush
+ && data2 == (int32_t)OMX_ALL) {
+ // Use of this notification is not consistent across
+ // implementations. We'll drop this notification and rely
+ // on flush-complete notifications on the individual port
+ // indices instead.
+
+ return true;
+ }
+
+ return onOMXEvent(
+ static_cast<OMX_EVENTTYPE>(event),
+ static_cast<OMX_U32>(data1),
+ static_cast<OMX_U32>(data2));
+ }
+
+ case omx_message::EMPTY_BUFFER_DONE:
+ {
+ IOMX::buffer_id bufferID;
+ CHECK(msg->findPointer("buffer", &bufferID));
+
+ return onOMXEmptyBufferDone(bufferID);
+ }
+
+ case omx_message::FILL_BUFFER_DONE:
+ {
+ IOMX::buffer_id bufferID;
+ CHECK(msg->findPointer("buffer", &bufferID));
+
+ int32_t rangeOffset, rangeLength, flags;
+ int64_t timeUs;
+ void *platformPrivate;
+ void *dataPtr;
+
+ CHECK(msg->findInt32("range_offset", &rangeOffset));
+ CHECK(msg->findInt32("range_length", &rangeLength));
+ CHECK(msg->findInt32("flags", &flags));
+ CHECK(msg->findInt64("timestamp", &timeUs));
+ CHECK(msg->findPointer("platform_private", &platformPrivate));
+ CHECK(msg->findPointer("data_ptr", &dataPtr));
+
+ return onOMXFillBufferDone(
+ bufferID,
+ (size_t)rangeOffset, (size_t)rangeLength,
+ (OMX_U32)flags,
+ timeUs,
+ platformPrivate,
+ dataPtr);
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+bool ACodec::BaseState::onOMXEvent(
+ OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+ if (event != OMX_EventError) {
+ ALOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
+ mCodec->mComponentName.c_str(), event, data1, data2);
+
+ return false;
+ }
+
+ ALOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
+
+ mCodec->signalError((OMX_ERRORTYPE)data1);
+
+ return true;
+}
+
+bool ACodec::BaseState::onOMXEmptyBufferDone(IOMX::buffer_id bufferID) {
+ ALOGV("[%s] onOMXEmptyBufferDone %p",
+ mCodec->mComponentName.c_str(), bufferID);
+
+ BufferInfo *info =
+ mCodec->findBufferByID(kPortIndexInput, bufferID);
+
+ CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
+ info->mStatus = BufferInfo::OWNED_BY_US;
+
+ PortMode mode = getPortMode(kPortIndexInput);
+
+ switch (mode) {
+ case KEEP_BUFFERS:
+ break;
+
+ case RESUBMIT_BUFFERS:
+ postFillThisBuffer(info);
+ break;
+
+ default:
+ {
+ CHECK_EQ((int)mode, (int)FREE_BUFFERS);
+ TRESPASS(); // Not currently used
+ break;
+ }
+ }
+
+ return true;
+}
+
+void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
+ if (mCodec->mPortEOS[kPortIndexInput]) {
+ return;
+ }
+
+ CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
+
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatFillThisBuffer);
+ notify->setPointer("buffer-id", info->mBufferID);
+
+ info->mData->meta()->clear();
+ notify->setBuffer("buffer", info->mData);
+
+ sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());
+ reply->setPointer("buffer-id", info->mBufferID);
+
+ notify->setMessage("reply", reply);
+
+ notify->post();
+
+ info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
+}
+
+void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
+ IOMX::buffer_id bufferID;
+ CHECK(msg->findPointer("buffer-id", &bufferID));
+
+ sp<ABuffer> buffer;
+ int32_t err = OK;
+ bool eos = false;
+
+ if (!msg->findBuffer("buffer", &buffer)) {
+ CHECK(msg->findInt32("err", &err));
+
+ ALOGV("[%s] saw error %d instead of an input buffer",
+ mCodec->mComponentName.c_str(), err);
+
+ buffer.clear();
+
+ eos = true;
+ }
+
+ int32_t tmp;
+ if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
+ eos = true;
+ err = ERROR_END_OF_STREAM;
+ }
+
+ BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
+ CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
+
+ info->mStatus = BufferInfo::OWNED_BY_US;
+
+ PortMode mode = getPortMode(kPortIndexInput);
+
+ switch (mode) {
+ case KEEP_BUFFERS:
+ {
+ if (eos) {
+ if (!mCodec->mPortEOS[kPortIndexInput]) {
+ mCodec->mPortEOS[kPortIndexInput] = true;
+ mCodec->mInputEOSResult = err;
+ }
+ }
+ break;
+ }
+
+ case RESUBMIT_BUFFERS:
+ {
+ if (buffer != NULL && !mCodec->mPortEOS[kPortIndexInput]) {
+ int64_t timeUs;
+ CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
+
+ OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
+
+ int32_t isCSD;
+ if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
+ flags |= OMX_BUFFERFLAG_CODECCONFIG;
+ }
+
+ if (eos) {
+ flags |= OMX_BUFFERFLAG_EOS;
+ }
+
+ if (buffer != info->mData) {
+ if (0 && !(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
+ ALOGV("[%s] Needs to copy input data.",
+ mCodec->mComponentName.c_str());
+ }
+
+ CHECK_LE(buffer->size(), info->mData->capacity());
+ memcpy(info->mData->data(), buffer->data(), buffer->size());
+ }
+
+ if (flags & OMX_BUFFERFLAG_CODECCONFIG) {
+ ALOGV("[%s] calling emptyBuffer %p w/ codec specific data",
+ mCodec->mComponentName.c_str(), bufferID);
+ } else if (flags & OMX_BUFFERFLAG_EOS) {
+ ALOGV("[%s] calling emptyBuffer %p w/ EOS",
+ mCodec->mComponentName.c_str(), bufferID);
+ } else {
+ ALOGV("[%s] calling emptyBuffer %p w/ time %lld us",
+ mCodec->mComponentName.c_str(), bufferID, timeUs);
+ }
+
+ CHECK_EQ(mCodec->mOMX->emptyBuffer(
+ mCodec->mNode,
+ bufferID,
+ 0,
+ buffer->size(),
+ flags,
+ timeUs),
+ (status_t)OK);
+
+ info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
+
+ if (!eos) {
+ getMoreInputDataIfPossible();
+ } else {
+ ALOGV("[%s] Signalled EOS on the input port",
+ mCodec->mComponentName.c_str());
+
+ mCodec->mPortEOS[kPortIndexInput] = true;
+ mCodec->mInputEOSResult = err;
+ }
+ } else if (!mCodec->mPortEOS[kPortIndexInput]) {
+ if (err != ERROR_END_OF_STREAM) {
+ ALOGV("[%s] Signalling EOS on the input port "
+ "due to error %d",
+ mCodec->mComponentName.c_str(), err);
+ } else {
+ ALOGV("[%s] Signalling EOS on the input port",
+ mCodec->mComponentName.c_str());
+ }
+
+ ALOGV("[%s] calling emptyBuffer %p signalling EOS",
+ mCodec->mComponentName.c_str(), bufferID);
+
+ CHECK_EQ(mCodec->mOMX->emptyBuffer(
+ mCodec->mNode,
+ bufferID,
+ 0,
+ 0,
+ OMX_BUFFERFLAG_EOS,
+ 0),
+ (status_t)OK);
+
+ info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
+
+ mCodec->mPortEOS[kPortIndexInput] = true;
+ mCodec->mInputEOSResult = err;
+ }
+ break;
+
+ default:
+ CHECK_EQ((int)mode, (int)FREE_BUFFERS);
+ break;
+ }
+ }
+}
+
+void ACodec::BaseState::getMoreInputDataIfPossible() {
+ if (mCodec->mPortEOS[kPortIndexInput]) {
+ return;
+ }
+
+ BufferInfo *eligible = NULL;
+
+ for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
+ BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
+
+#if 0
+ if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
+ // There's already a "read" pending.
+ return;
+ }
+#endif
+
+ if (info->mStatus == BufferInfo::OWNED_BY_US) {
+ eligible = info;
+ }
+ }
+
+ if (eligible == NULL) {
+ return;
+ }
+
+ postFillThisBuffer(eligible);
+}
+
+bool ACodec::BaseState::onOMXFillBufferDone(
+ IOMX::buffer_id bufferID,
+ size_t rangeOffset, size_t rangeLength,
+ OMX_U32 flags,
+ int64_t timeUs,
+ void *platformPrivate,
+ void *dataPtr) {
+ ALOGV("[%s] onOMXFillBufferDone %p time %lld us, flags = 0x%08lx",
+ mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
+
+ ssize_t index;
+ BufferInfo *info =
+ mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
+
+ CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
+
+ info->mStatus = BufferInfo::OWNED_BY_US;
+
+ PortMode mode = getPortMode(kPortIndexOutput);
+
+ switch (mode) {
+ case KEEP_BUFFERS:
+ break;
+
+ case RESUBMIT_BUFFERS:
+ {
+ if (rangeLength == 0 && !(flags & OMX_BUFFERFLAG_EOS)) {
+ ALOGV("[%s] calling fillBuffer %p",
+ mCodec->mComponentName.c_str(), info->mBufferID);
+
+ CHECK_EQ(mCodec->mOMX->fillBuffer(
+ mCodec->mNode, info->mBufferID),
+ (status_t)OK);
+
+ info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
+ break;
+ }
+
+ if (!mCodec->mIsEncoder && !mCodec->mSentFormat) {
+ mCodec->sendFormatChange();
+ }
+
+ if (mCodec->mNativeWindow == NULL) {
+ info->mData->setRange(rangeOffset, rangeLength);
+ }
+
+ info->mData->meta()->setInt64("timeUs", timeUs);
+
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatDrainThisBuffer);
+ notify->setPointer("buffer-id", info->mBufferID);
+ notify->setBuffer("buffer", info->mData);
+ notify->setInt32("flags", flags);
+
+ sp<AMessage> reply =
+ new AMessage(kWhatOutputBufferDrained, mCodec->id());
+
+ reply->setPointer("buffer-id", info->mBufferID);
+
+ notify->setMessage("reply", reply);
+
+ notify->post();
+
+ info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
+
+ if (flags & OMX_BUFFERFLAG_EOS) {
+ ALOGV("[%s] saw output EOS", mCodec->mComponentName.c_str());
+
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatEOS);
+ notify->setInt32("err", mCodec->mInputEOSResult);
+ notify->post();
+
+ mCodec->mPortEOS[kPortIndexOutput] = true;
+ }
+ break;
+ }
+
+ default:
+ {
+ CHECK_EQ((int)mode, (int)FREE_BUFFERS);
+
+ CHECK_EQ((status_t)OK,
+ mCodec->freeBuffer(kPortIndexOutput, index));
+ break;
+ }
+ }
+
+ return true;
+}
+
+void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
+ IOMX::buffer_id bufferID;
+ CHECK(msg->findPointer("buffer-id", &bufferID));
+
+ ssize_t index;
+ BufferInfo *info =
+ mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
+ CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
+
+ int32_t render;
+ if (mCodec->mNativeWindow != NULL
+ && msg->findInt32("render", &render) && render != 0) {
+ // The client wants this buffer to be rendered.
+
+ status_t err;
+ if ((err = mCodec->mNativeWindow->queueBuffer(
+ mCodec->mNativeWindow.get(),
+ info->mGraphicBuffer.get())) == OK) {
+ info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
+ } else {
+ mCodec->signalError(OMX_ErrorUndefined, err);
+ info->mStatus = BufferInfo::OWNED_BY_US;
+ }
+ } else {
+ info->mStatus = BufferInfo::OWNED_BY_US;
+ }
+
+ PortMode mode = getPortMode(kPortIndexOutput);
+
+ switch (mode) {
+ case KEEP_BUFFERS:
+ {
+ // XXX fishy, revisit!!! What about the FREE_BUFFERS case below?
+
+ if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
+ // We cannot resubmit the buffer we just rendered, dequeue
+ // the spare instead.
+
+ info = mCodec->dequeueBufferFromNativeWindow();
+ }
+ break;
+ }
+
+ case RESUBMIT_BUFFERS:
+ {
+ if (!mCodec->mPortEOS[kPortIndexOutput]) {
+ if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
+ // We cannot resubmit the buffer we just rendered, dequeue
+ // the spare instead.
+
+ info = mCodec->dequeueBufferFromNativeWindow();
+ }
+
+ if (info != NULL) {
+ ALOGV("[%s] calling fillBuffer %p",
+ mCodec->mComponentName.c_str(), info->mBufferID);
+
+ CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
+ (status_t)OK);
+
+ info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ CHECK_EQ((int)mode, (int)FREE_BUFFERS);
+
+ CHECK_EQ((status_t)OK,
+ mCodec->freeBuffer(kPortIndexOutput, index));
+ break;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::UninitializedState::UninitializedState(ACodec *codec)
+ : BaseState(codec) {
+}
+
+void ACodec::UninitializedState::stateEntered() {
+ ALOGV("Now uninitialized");
+}
+
+bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
+ bool handled = false;
+
+ switch (msg->what()) {
+ case ACodec::kWhatSetup:
+ {
+ onSetup(msg);
+
+ handled = true;
+ break;
+ }
+
+ case ACodec::kWhatAllocateComponent:
+ {
+ onAllocateComponent(msg);
+ handled = true;
+ break;
+ }
+
+ case ACodec::kWhatShutdown:
+ {
+ int32_t keepComponentAllocated;
+ CHECK(msg->findInt32(
+ "keepComponentAllocated", &keepComponentAllocated));
+ CHECK(!keepComponentAllocated);
+
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatShutdownCompleted);
+ notify->post();
+
+ handled = true;
+ break;
+ }
+
+ case ACodec::kWhatFlush:
+ {
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatFlushCompleted);
+ notify->post();
+
+ handled = true;
+ break;
+ }
+
+ default:
+ return BaseState::onMessageReceived(msg);
+ }
+
+ return handled;
+}
+
+void ACodec::UninitializedState::onSetup(
+ const sp<AMessage> &msg) {
+ if (onAllocateComponent(msg)
+ && mCodec->mLoadedState->onConfigureComponent(msg)) {
+ mCodec->mLoadedState->onStart();
+ }
+}
+
+bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
+ ALOGV("onAllocateComponent");
+
+ CHECK(mCodec->mNode == NULL);
+
+ OMXClient client;
+ CHECK_EQ(client.connect(), (status_t)OK);
+
+ sp<IOMX> omx = client.interface();
+
+ Vector<String8> matchingCodecs;
+ Vector<uint32_t> matchingCodecQuirks;
+
+ AString mime;
+
+ AString componentName;
+ uint32_t quirks;
+ if (msg->findString("componentName", &componentName)) {
+ matchingCodecs.push_back(String8(componentName.c_str()));
+
+ if (!OMXCodec::findCodecQuirks(componentName.c_str(), &quirks)) {
+ quirks = 0;
+ }
+ matchingCodecQuirks.push_back(quirks);
+ } else {
+ CHECK(msg->findString("mime", &mime));
+
+ int32_t encoder;
+ if (!msg->findInt32("encoder", &encoder)) {
+ encoder = false;
+ }
+
+ OMXCodec::findMatchingCodecs(
+ mime.c_str(),
+ encoder, // createEncoder
+ NULL, // matchComponentName
+ 0, // flags
+ &matchingCodecs,
+ &matchingCodecQuirks);
+ }
+
+ sp<CodecObserver> observer = new CodecObserver;
+ IOMX::node_id node = NULL;
+
+ for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
+ ++matchIndex) {
+ componentName = matchingCodecs.itemAt(matchIndex).string();
+ quirks = matchingCodecQuirks.itemAt(matchIndex);
+
+ pid_t tid = androidGetTid();
+ int prevPriority = androidGetThreadPriority(tid);
+ androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
+ status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
+ androidSetThreadPriority(tid, prevPriority);
+
+ if (err == OK) {
+ break;
+ }
+
+ node = NULL;
+ }
+
+ if (node == NULL) {
+ if (!mime.empty()) {
+ ALOGE("Unable to instantiate a decoder for type '%s'.",
+ mime.c_str());
+ } else {
+ ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str());
+ }
+
+ mCodec->signalError(OMX_ErrorComponentNotFound);
+ return false;
+ }
+
+ sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
+ observer->setNotificationMessage(notify);
+
+ mCodec->mComponentName = componentName;
+ mCodec->mFlags = 0;
+
+ if (componentName.endsWith(".secure")) {
+ mCodec->mFlags |= kFlagIsSecure;
+ }
+
+ mCodec->mQuirks = quirks;
+ mCodec->mOMX = omx;
+ mCodec->mNode = node;
+
+ mCodec->mPortEOS[kPortIndexInput] =
+ mCodec->mPortEOS[kPortIndexOutput] = false;
+
+ mCodec->mInputEOSResult = OK;
+
+ {
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatComponentAllocated);
+ notify->setString("componentName", mCodec->mComponentName.c_str());
+ notify->post();
+ }
+
+ mCodec->changeState(mCodec->mLoadedState);
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::LoadedState::LoadedState(ACodec *codec)
+ : BaseState(codec) {
+}
+
+void ACodec::LoadedState::stateEntered() {
+ ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
+
+ if (mCodec->mShutdownInProgress) {
+ bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
+
+ mCodec->mShutdownInProgress = false;
+ mCodec->mKeepComponentAllocated = false;
+
+ onShutdown(keepComponentAllocated);
+ }
+}
+
+void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
+ if (!keepComponentAllocated) {
+ CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
+
+ mCodec->mNativeWindow.clear();
+ mCodec->mNode = NULL;
+ mCodec->mOMX.clear();
+ mCodec->mQuirks = 0;
+ mCodec->mFlags = 0;
+ mCodec->mComponentName.clear();
+
+ mCodec->changeState(mCodec->mUninitializedState);
+ }
+
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatShutdownCompleted);
+ notify->post();
+}
+
+bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
+ bool handled = false;
+
+ switch (msg->what()) {
+ case ACodec::kWhatConfigureComponent:
+ {
+ onConfigureComponent(msg);
+ handled = true;
+ break;
+ }
+
+ case ACodec::kWhatStart:
+ {
+ onStart();
+ handled = true;
+ break;
+ }
+
+ case ACodec::kWhatShutdown:
+ {
+ int32_t keepComponentAllocated;
+ CHECK(msg->findInt32(
+ "keepComponentAllocated", &keepComponentAllocated));
+
+ onShutdown(keepComponentAllocated);
+
+ handled = true;
+ break;
+ }
+
+ case ACodec::kWhatFlush:
+ {
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatFlushCompleted);
+ notify->post();
+
+ handled = true;
+ break;
+ }
+
+ default:
+ return BaseState::onMessageReceived(msg);
+ }
+
+ return handled;
+}
+
+bool ACodec::LoadedState::onConfigureComponent(
+ const sp<AMessage> &msg) {
+ ALOGV("onConfigureComponent");
+
+ CHECK(mCodec->mNode != NULL);
+
+ AString mime;
+ CHECK(msg->findString("mime", &mime));
+
+ status_t err = mCodec->configureCodec(mime.c_str(), msg);
+
+ if (err != OK) {
+ ALOGE("[%s] configureCodec returning error %d",
+ mCodec->mComponentName.c_str(), err);
+
+ mCodec->signalError(OMX_ErrorUndefined, err);
+ return false;
+ }
+
+ sp<RefBase> obj;
+ if (msg->findObject("native-window", &obj)
+ && strncmp("OMX.google.", mCodec->mComponentName.c_str(), 11)) {
+ sp<NativeWindowWrapper> nativeWindow(
+ static_cast<NativeWindowWrapper *>(obj.get()));
+ CHECK(nativeWindow != NULL);
+ mCodec->mNativeWindow = nativeWindow->getNativeWindow();
+ }
+ CHECK_EQ((status_t)OK, mCodec->initNativeWindow());
+
+ {
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatComponentConfigured);
+ notify->post();
+ }
+
+ return true;
+}
+
+void ACodec::LoadedState::onStart() {
+ ALOGV("onStart");
+
+ CHECK_EQ(mCodec->mOMX->sendCommand(
+ mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
+ (status_t)OK);
+
+ mCodec->changeState(mCodec->mLoadedToIdleState);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
+ : BaseState(codec) {
+}
+
+void ACodec::LoadedToIdleState::stateEntered() {
+ ALOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
+
+ status_t err;
+ if ((err = allocateBuffers()) != OK) {
+ ALOGE("Failed to allocate buffers after transitioning to IDLE state "
+ "(error 0x%08x)",
+ err);
+
+ mCodec->signalError(OMX_ErrorUndefined, err);
+ }
+}
+
+status_t ACodec::LoadedToIdleState::allocateBuffers() {
+ status_t err = mCodec->allocateBuffersOnPort(kPortIndexInput);
+
+ if (err != OK) {
+ return err;
+ }
+
+ return mCodec->allocateBuffersOnPort(kPortIndexOutput);
+}
+
+bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatShutdown:
+ {
+ mCodec->deferMessage(msg);
+ return true;
+ }
+
+ default:
+ return BaseState::onMessageReceived(msg);
+ }
+}
+
+bool ACodec::LoadedToIdleState::onOMXEvent(
+ OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+ switch (event) {
+ case OMX_EventCmdComplete:
+ {
+ CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
+ CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
+
+ CHECK_EQ(mCodec->mOMX->sendCommand(
+ mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
+ (status_t)OK);
+
+ mCodec->changeState(mCodec->mIdleToExecutingState);
+
+ return true;
+ }
+
+ default:
+ return BaseState::onOMXEvent(event, data1, data2);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
+ : BaseState(codec) {
+}
+
+void ACodec::IdleToExecutingState::stateEntered() {
+ ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
+}
+
+bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatShutdown:
+ {
+ mCodec->deferMessage(msg);
+ return true;
+ }
+
+ default:
+ return BaseState::onMessageReceived(msg);
+ }
+}
+
+bool ACodec::IdleToExecutingState::onOMXEvent(
+ OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+ switch (event) {
+ case OMX_EventCmdComplete:
+ {
+ CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
+ CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
+
+ mCodec->mExecutingState->resume();
+ mCodec->changeState(mCodec->mExecutingState);
+
+ return true;
+ }
+
+ default:
+ return BaseState::onOMXEvent(event, data1, data2);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::ExecutingState::ExecutingState(ACodec *codec)
+ : BaseState(codec),
+ mActive(false) {
+}
+
+ACodec::BaseState::PortMode ACodec::ExecutingState::getPortMode(
+ OMX_U32 portIndex) {
+ return RESUBMIT_BUFFERS;
+}
+
+void ACodec::ExecutingState::submitOutputBuffers() {
+ for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
+ BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
+
+ if (mCodec->mNativeWindow != NULL) {
+ CHECK(info->mStatus == BufferInfo::OWNED_BY_US
+ || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
+
+ if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
+ continue;
+ }
+
+ status_t err = mCodec->mNativeWindow->lockBuffer(
+ mCodec->mNativeWindow.get(),
+ info->mGraphicBuffer.get());
+ CHECK_EQ(err, (status_t)OK);
+ } else {
+ CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
+ }
+
+ ALOGV("[%s] calling fillBuffer %p",
+ mCodec->mComponentName.c_str(), info->mBufferID);
+
+ CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
+ (status_t)OK);
+
+ info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
+ }
+}
+
+void ACodec::ExecutingState::resume() {
+ if (mActive) {
+ ALOGV("[%s] We're already active, no need to resume.",
+ mCodec->mComponentName.c_str());
+
+ return;
+ }
+
+ submitOutputBuffers();
+
+ // Post the first input buffer.
+ CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
+ BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
+
+ postFillThisBuffer(info);
+
+ mActive = true;
+}
+
+void ACodec::ExecutingState::stateEntered() {
+ ALOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
+
+ mCodec->processDeferredMessages();
+}
+
+bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
+ bool handled = false;
+
+ switch (msg->what()) {
+ case kWhatShutdown:
+ {
+ int32_t keepComponentAllocated;
+ CHECK(msg->findInt32(
+ "keepComponentAllocated", &keepComponentAllocated));
+
+ mCodec->mShutdownInProgress = true;
+ mCodec->mKeepComponentAllocated = keepComponentAllocated;
+
+ mActive = false;
+
+ CHECK_EQ(mCodec->mOMX->sendCommand(
+ mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
+ (status_t)OK);
+
+ mCodec->changeState(mCodec->mExecutingToIdleState);
+
+ handled = true;
+ break;
+ }
+
+ case kWhatFlush:
+ {
+ ALOGV("[%s] ExecutingState flushing now "
+ "(codec owns %d/%d input, %d/%d output).",
+ mCodec->mComponentName.c_str(),
+ mCodec->countBuffersOwnedByComponent(kPortIndexInput),
+ mCodec->mBuffers[kPortIndexInput].size(),
+ mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
+ mCodec->mBuffers[kPortIndexOutput].size());
+
+ mActive = false;
+
+ CHECK_EQ(mCodec->mOMX->sendCommand(
+ mCodec->mNode, OMX_CommandFlush, OMX_ALL),
+ (status_t)OK);
+
+ mCodec->changeState(mCodec->mFlushingState);
+
+ handled = true;
+ break;
+ }
+
+ case kWhatResume:
+ {
+ resume();
+
+ handled = true;
+ break;
+ }
+
+ default:
+ handled = BaseState::onMessageReceived(msg);
+ break;
+ }
+
+ return handled;
+}
+
+bool ACodec::ExecutingState::onOMXEvent(
+ OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+ switch (event) {
+ case OMX_EventPortSettingsChanged:
+ {
+ CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
+
+ if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
+ CHECK_EQ(mCodec->mOMX->sendCommand(
+ mCodec->mNode,
+ OMX_CommandPortDisable, kPortIndexOutput),
+ (status_t)OK);
+
+ mCodec->freeOutputBuffersNotOwnedByComponent();
+
+ mCodec->changeState(mCodec->mOutputPortSettingsChangedState);
+ } else if (data2 == OMX_IndexConfigCommonOutputCrop) {
+ mCodec->mSentFormat = false;
+ } else {
+ ALOGV("[%s] OMX_EventPortSettingsChanged 0x%08lx",
+ mCodec->mComponentName.c_str(), data2);
+ }
+
+ return true;
+ }
+
+ case OMX_EventBufferFlag:
+ {
+ return true;
+ }
+
+ default:
+ return BaseState::onOMXEvent(event, data1, data2);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::OutputPortSettingsChangedState::OutputPortSettingsChangedState(
+ ACodec *codec)
+ : BaseState(codec) {
+}
+
+ACodec::BaseState::PortMode ACodec::OutputPortSettingsChangedState::getPortMode(
+ OMX_U32 portIndex) {
+ if (portIndex == kPortIndexOutput) {
+ return FREE_BUFFERS;
+ }
+
+ CHECK_EQ(portIndex, (OMX_U32)kPortIndexInput);
+
+ return RESUBMIT_BUFFERS;
+}
+
+bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
+ const sp<AMessage> &msg) {
+ bool handled = false;
+
+ switch (msg->what()) {
+ case kWhatFlush:
+ case kWhatShutdown:
+ case kWhatResume:
+ {
+ if (msg->what() == kWhatResume) {
+ ALOGV("[%s] Deferring resume", mCodec->mComponentName.c_str());
+ }
+
+ mCodec->deferMessage(msg);
+ handled = true;
+ break;
+ }
+
+ default:
+ handled = BaseState::onMessageReceived(msg);
+ break;
+ }
+
+ return handled;
+}
+
+void ACodec::OutputPortSettingsChangedState::stateEntered() {
+ ALOGV("[%s] Now handling output port settings change",
+ mCodec->mComponentName.c_str());
+}
+
+bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
+ OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+ switch (event) {
+ case OMX_EventCmdComplete:
+ {
+ if (data1 == (OMX_U32)OMX_CommandPortDisable) {
+ CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
+
+ ALOGV("[%s] Output port now disabled.",
+ mCodec->mComponentName.c_str());
+
+ CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
+ mCodec->mDealer[kPortIndexOutput].clear();
+
+ CHECK_EQ(mCodec->mOMX->sendCommand(
+ mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
+ (status_t)OK);
+
+ status_t err;
+ if ((err = mCodec->allocateBuffersOnPort(
+ kPortIndexOutput)) != OK) {
+ ALOGE("Failed to allocate output port buffers after "
+ "port reconfiguration (error 0x%08x)",
+ err);
+
+ mCodec->signalError(OMX_ErrorUndefined, err);
+
+ // This is technically not correct, since we were unable
+ // to allocate output buffers and therefore the output port
+ // remains disabled. It is necessary however to allow us
+ // to shutdown the codec properly.
+ mCodec->changeState(mCodec->mExecutingState);
+ }
+
+ return true;
+ } else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
+ CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
+
+ mCodec->mSentFormat = false;
+
+ ALOGV("[%s] Output port now reenabled.",
+ mCodec->mComponentName.c_str());
+
+ if (mCodec->mExecutingState->active()) {
+ mCodec->mExecutingState->submitOutputBuffers();
+ }
+
+ mCodec->changeState(mCodec->mExecutingState);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ default:
+ return false;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::ExecutingToIdleState::ExecutingToIdleState(ACodec *codec)
+ : BaseState(codec),
+ mComponentNowIdle(false) {
+}
+
+bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
+ bool handled = false;
+
+ switch (msg->what()) {
+ case kWhatFlush:
+ {
+ // Don't send me a flush request if you previously wanted me
+ // to shutdown.
+ TRESPASS();
+ break;
+ }
+
+ case kWhatShutdown:
+ {
+ // We're already doing that...
+
+ handled = true;
+ break;
+ }
+
+ default:
+ handled = BaseState::onMessageReceived(msg);
+ break;
+ }
+
+ return handled;
+}
+
+void ACodec::ExecutingToIdleState::stateEntered() {
+ ALOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
+
+ mComponentNowIdle = false;
+ mCodec->mSentFormat = false;
+}
+
+bool ACodec::ExecutingToIdleState::onOMXEvent(
+ OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+ switch (event) {
+ case OMX_EventCmdComplete:
+ {
+ CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
+ CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
+
+ mComponentNowIdle = true;
+
+ changeStateIfWeOwnAllBuffers();
+
+ return true;
+ }
+
+ case OMX_EventPortSettingsChanged:
+ case OMX_EventBufferFlag:
+ {
+ // We're shutting down and don't care about this anymore.
+ return true;
+ }
+
+ default:
+ return BaseState::onOMXEvent(event, data1, data2);
+ }
+}
+
+void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
+ if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
+ CHECK_EQ(mCodec->mOMX->sendCommand(
+ mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
+ (status_t)OK);
+
+ CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
+ CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
+
+ mCodec->changeState(mCodec->mIdleToLoadedState);
+ }
+}
+
+void ACodec::ExecutingToIdleState::onInputBufferFilled(
+ const sp<AMessage> &msg) {
+ BaseState::onInputBufferFilled(msg);
+
+ changeStateIfWeOwnAllBuffers();
+}
+
+void ACodec::ExecutingToIdleState::onOutputBufferDrained(
+ const sp<AMessage> &msg) {
+ BaseState::onOutputBufferDrained(msg);
+
+ changeStateIfWeOwnAllBuffers();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::IdleToLoadedState::IdleToLoadedState(ACodec *codec)
+ : BaseState(codec) {
+}
+
+bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
+ bool handled = false;
+
+ switch (msg->what()) {
+ case kWhatShutdown:
+ {
+ // We're already doing that...
+
+ handled = true;
+ break;
+ }
+
+ case kWhatFlush:
+ {
+ // Don't send me a flush request if you previously wanted me
+ // to shutdown.
+ TRESPASS();
+ break;
+ }
+
+ default:
+ handled = BaseState::onMessageReceived(msg);
+ break;
+ }
+
+ return handled;
+}
+
+void ACodec::IdleToLoadedState::stateEntered() {
+ ALOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
+}
+
+bool ACodec::IdleToLoadedState::onOMXEvent(
+ OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+ switch (event) {
+ case OMX_EventCmdComplete:
+ {
+ CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
+ CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
+
+ mCodec->changeState(mCodec->mLoadedState);
+
+ return true;
+ }
+
+ default:
+ return BaseState::onOMXEvent(event, data1, data2);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::FlushingState::FlushingState(ACodec *codec)
+ : BaseState(codec) {
+}
+
+void ACodec::FlushingState::stateEntered() {
+ ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
+
+ mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
+}
+
+bool ACodec::FlushingState::onMessageReceived(const sp<AMessage> &msg) {
+ bool handled = false;
+
+ switch (msg->what()) {
+ case kWhatShutdown:
+ {
+ mCodec->deferMessage(msg);
+ break;
+ }
+
+ case kWhatFlush:
+ {
+ // We're already doing this right now.
+ handled = true;
+ break;
+ }
+
+ default:
+ handled = BaseState::onMessageReceived(msg);
+ break;
+ }
+
+ return handled;
+}
+
+bool ACodec::FlushingState::onOMXEvent(
+ OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+ ALOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
+ mCodec->mComponentName.c_str(), event, data1);
+
+ switch (event) {
+ case OMX_EventCmdComplete:
+ {
+ CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
+
+ if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
+ CHECK(!mFlushComplete[data2]);
+ mFlushComplete[data2] = true;
+
+ if (mFlushComplete[kPortIndexInput]
+ && mFlushComplete[kPortIndexOutput]) {
+ changeStateIfWeOwnAllBuffers();
+ }
+ } else {
+ CHECK_EQ(data2, OMX_ALL);
+ CHECK(mFlushComplete[kPortIndexInput]);
+ CHECK(mFlushComplete[kPortIndexOutput]);
+
+ changeStateIfWeOwnAllBuffers();
+ }
+
+ return true;
+ }
+
+ case OMX_EventPortSettingsChanged:
+ {
+ sp<AMessage> msg = new AMessage(kWhatOMXMessage, mCodec->id());
+ msg->setInt32("type", omx_message::EVENT);
+ msg->setPointer("node", mCodec->mNode);
+ msg->setInt32("event", event);
+ msg->setInt32("data1", data1);
+ msg->setInt32("data2", data2);
+
+ ALOGV("[%s] Deferring OMX_EventPortSettingsChanged",
+ mCodec->mComponentName.c_str());
+
+ mCodec->deferMessage(msg);
+
+ return true;
+ }
+
+ default:
+ return BaseState::onOMXEvent(event, data1, data2);
+ }
+
+ return true;
+}
+
+void ACodec::FlushingState::onOutputBufferDrained(const sp<AMessage> &msg) {
+ BaseState::onOutputBufferDrained(msg);
+
+ changeStateIfWeOwnAllBuffers();
+}
+
+void ACodec::FlushingState::onInputBufferFilled(const sp<AMessage> &msg) {
+ BaseState::onInputBufferFilled(msg);
+
+ changeStateIfWeOwnAllBuffers();
+}
+
+void ACodec::FlushingState::changeStateIfWeOwnAllBuffers() {
+ if (mFlushComplete[kPortIndexInput]
+ && mFlushComplete[kPortIndexOutput]
+ && mCodec->allYourBuffersAreBelongToUs()) {
+ sp<AMessage> notify = mCodec->mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatFlushCompleted);
+ notify->post();
+
+ mCodec->mPortEOS[kPortIndexInput] =
+ mCodec->mPortEOS[kPortIndexOutput] = false;
+
+ mCodec->mInputEOSResult = OK;
+
+ mCodec->changeState(mCodec->mExecutingState);
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp
new file mode 100644
index 0000000..03dcbf9
--- /dev/null
+++ b/media/libstagefright/AMRExtractor.cpp
@@ -0,0 +1,353 @@
+/*
+ * 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 "AMRExtractor"
+#include <utils/Log.h>
+
+#include "include/AMRExtractor.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBufferGroup.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 {
+
+class AMRSource : public MediaSource {
+public:
+ AMRSource(const sp<DataSource> &source,
+ const sp<MetaData> &meta,
+ bool isWide,
+ const off64_t *offset_table,
+ size_t offset_table_length);
+
+ 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);
+
+protected:
+ virtual ~AMRSource();
+
+private:
+ sp<DataSource> mDataSource;
+ sp<MetaData> mMeta;
+ bool mIsWide;
+
+ off64_t mOffset;
+ int64_t mCurrentTimeUs;
+ bool mStarted;
+ MediaBufferGroup *mGroup;
+
+ off64_t mOffsetTable[OFFSET_TABLE_LEN];
+ size_t mOffsetTableLength;
+
+ AMRSource(const AMRSource &);
+ AMRSource &operator=(const AMRSource &);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+static size_t getFrameSize(bool isWide, unsigned FT) {
+ static const size_t kFrameSizeNB[16] = {
+ 95, 103, 118, 134, 148, 159, 204, 244,
+ 39, 43, 38, 37, // SID
+ 0, 0, 0, // future use
+ 0 // no data
+ };
+ static const size_t kFrameSizeWB[16] = {
+ 132, 177, 253, 285, 317, 365, 397, 461, 477,
+ 40, // SID
+ 0, 0, 0, 0, // future use
+ 0, // speech lost
+ 0 // no data
+ };
+
+ if (FT > 15 || (isWide && FT > 9 && FT < 14) || (!isWide && FT > 11 && FT < 15)) {
+ ALOGE("illegal AMR frame type %d", FT);
+ return 0;
+ }
+
+ size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
+
+ // Round up bits to bytes and add 1 for the header byte.
+ frameSize = (frameSize + 7) / 8 + 1;
+
+ return frameSize;
+}
+
+static status_t getFrameSizeByOffset(const sp<DataSource> &source,
+ off64_t offset, bool isWide, size_t *frameSize) {
+ uint8_t header;
+ if (source->readAt(offset, &header, 1) < 1) {
+ return ERROR_IO;
+ }
+
+ unsigned FT = (header >> 3) & 0x0f;
+
+ *frameSize = getFrameSize(isWide, FT);
+ if (*frameSize == 0) {
+ return ERROR_MALFORMED;
+ }
+ return OK;
+}
+
+AMRExtractor::AMRExtractor(const sp<DataSource> &source)
+ : mDataSource(source),
+ mInitCheck(NO_INIT),
+ mOffsetTableLength(0) {
+ String8 mimeType;
+ float confidence;
+ if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) {
+ return;
+ }
+
+ mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB);
+
+ mMeta = new MetaData;
+ mMeta->setCString(
+ kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB
+ : MEDIA_MIMETYPE_AUDIO_AMR_NB);
+
+ mMeta->setInt32(kKeyChannelCount, 1);
+ mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000);
+
+ off64_t offset = mIsWide ? 9 : 6;
+ off64_t streamSize;
+ size_t frameSize, numFrames = 0;
+ int64_t duration = 0;
+
+ if (mDataSource->getSize(&streamSize) == OK) {
+ while (offset < streamSize) {
+ if (getFrameSizeByOffset(source, offset, mIsWide, &frameSize) != OK) {
+ return;
+ }
+
+ if ((numFrames % 50 == 0) && (numFrames / 50 < OFFSET_TABLE_LEN)) {
+ CHECK_EQ(mOffsetTableLength, numFrames / 50);
+ mOffsetTable[mOffsetTableLength] = offset - (mIsWide ? 9: 6);
+ mOffsetTableLength ++;
+ }
+
+ offset += frameSize;
+ duration += 20000; // Each frame is 20ms
+ numFrames ++;
+ }
+
+ mMeta->setInt64(kKeyDuration, duration);
+ }
+
+ mInitCheck = OK;
+}
+
+AMRExtractor::~AMRExtractor() {
+}
+
+sp<MetaData> AMRExtractor::getMetaData() {
+ sp<MetaData> meta = new MetaData;
+
+ if (mInitCheck != OK) {
+ return meta;
+ }
+
+ meta->setCString(kKeyMIMEType, mIsWide ? "audio/amr-wb" : "audio/amr");
+
+ return meta;
+}
+
+size_t AMRExtractor::countTracks() {
+ return mInitCheck == OK ? 1 : 0;
+}
+
+sp<MediaSource> AMRExtractor::getTrack(size_t index) {
+ if (mInitCheck != OK || index != 0) {
+ return NULL;
+ }
+
+ return new AMRSource(mDataSource, mMeta, mIsWide,
+ mOffsetTable, mOffsetTableLength);
+}
+
+sp<MetaData> AMRExtractor::getTrackMetaData(size_t index, uint32_t flags) {
+ if (mInitCheck != OK || index != 0) {
+ return NULL;
+ }
+
+ return mMeta;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+AMRSource::AMRSource(
+ const sp<DataSource> &source, const sp<MetaData> &meta,
+ bool isWide, const off64_t *offset_table, size_t offset_table_length)
+ : mDataSource(source),
+ mMeta(meta),
+ mIsWide(isWide),
+ mOffset(mIsWide ? 9 : 6),
+ mCurrentTimeUs(0),
+ mStarted(false),
+ mGroup(NULL),
+ mOffsetTableLength(offset_table_length) {
+ if (mOffsetTableLength > 0 && mOffsetTableLength <= OFFSET_TABLE_LEN) {
+ memcpy ((char*)mOffsetTable, (char*)offset_table, sizeof(off64_t) * mOffsetTableLength);
+ }
+}
+
+AMRSource::~AMRSource() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t AMRSource::start(MetaData *params) {
+ CHECK(!mStarted);
+
+ mOffset = mIsWide ? 9 : 6;
+ mCurrentTimeUs = 0;
+ mGroup = new MediaBufferGroup;
+ mGroup->add_buffer(new MediaBuffer(128));
+ mStarted = true;
+
+ return OK;
+}
+
+status_t AMRSource::stop() {
+ CHECK(mStarted);
+
+ delete mGroup;
+ mGroup = NULL;
+
+ mStarted = false;
+ return OK;
+}
+
+sp<MetaData> AMRSource::getFormat() {
+ return mMeta;
+}
+
+status_t AMRSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+ size_t size;
+ int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame.
+ mCurrentTimeUs = seekFrame * 20000ll;
+
+ int index = seekFrame / 50;
+ if (index >= mOffsetTableLength) {
+ index = mOffsetTableLength - 1;
+ }
+
+ mOffset = mOffsetTable[index] + (mIsWide ? 9 : 6);
+
+ for (int i = 0; i< seekFrame - index * 50; i++) {
+ status_t err;
+ if ((err = getFrameSizeByOffset(mDataSource, mOffset,
+ mIsWide, &size)) != OK) {
+ return err;
+ }
+ mOffset += size;
+ }
+ }
+
+ uint8_t header;
+ ssize_t n = mDataSource->readAt(mOffset, &header, 1);
+
+ if (n < 1) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ if (header & 0x83) {
+ // Padding bits must be 0.
+
+ ALOGE("padding bits must be 0, header is 0x%02x", header);
+
+ return ERROR_MALFORMED;
+ }
+
+ unsigned FT = (header >> 3) & 0x0f;
+
+ size_t frameSize = getFrameSize(mIsWide, FT);
+ if (frameSize == 0) {
+ return ERROR_MALFORMED;
+ }
+
+ MediaBuffer *buffer;
+ status_t err = mGroup->acquire_buffer(&buffer);
+ if (err != OK) {
+ return err;
+ }
+
+ n = mDataSource->readAt(mOffset, buffer->data(), frameSize);
+
+ if (n != (ssize_t)frameSize) {
+ buffer->release();
+ buffer = NULL;
+
+ return ERROR_IO;
+ }
+
+ buffer->set_range(0, frameSize);
+ buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
+ buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+
+ mOffset += frameSize;
+ mCurrentTimeUs += 20000; // Each frame is 20ms
+
+ *out = buffer;
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool SniffAMR(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
+ char header[9];
+
+ if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
+ return false;
+ }
+
+ if (!memcmp(header, "#!AMR\n", 6)) {
+ *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_NB;
+ *confidence = 0.5;
+
+ return true;
+ } else if (!memcmp(header, "#!AMR-WB\n", 9)) {
+ *mimeType = MEDIA_MIMETYPE_AUDIO_AMR_WB;
+ *confidence = 0.5;
+
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace android
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
new file mode 100644
index 0000000..ca85640
--- /dev/null
+++ b/media/libstagefright/AMRWriter.cpp
@@ -0,0 +1,287 @@
+/*
+ * 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 <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/AMRWriter.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/mediarecorder.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+namespace android {
+
+AMRWriter::AMRWriter(const char *filename)
+ : mFd(-1),
+ mInitCheck(NO_INIT),
+ mStarted(false),
+ mPaused(false),
+ mResumed(false) {
+
+ mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR);
+ if (mFd >= 0) {
+ mInitCheck = OK;
+ }
+}
+
+AMRWriter::AMRWriter(int fd)
+ : mFd(dup(fd)),
+ mInitCheck(mFd < 0? NO_INIT: OK),
+ mStarted(false),
+ mPaused(false),
+ mResumed(false) {
+}
+
+AMRWriter::~AMRWriter() {
+ if (mStarted) {
+ reset();
+ }
+
+ if (mFd != -1) {
+ close(mFd);
+ mFd = -1;
+ }
+}
+
+status_t AMRWriter::initCheck() const {
+ return mInitCheck;
+}
+
+status_t AMRWriter::addSource(const sp<MediaSource> &source) {
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mSource != NULL) {
+ // AMR files only support a single track of audio.
+ return UNKNOWN_ERROR;
+ }
+
+ sp<MetaData> meta = source->getFormat();
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ bool isWide = false;
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
+ isWide = true;
+ } else if (strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ int32_t channelCount;
+ int32_t sampleRate;
+ CHECK(meta->findInt32(kKeyChannelCount, &channelCount));
+ CHECK_EQ(channelCount, 1);
+ CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+ CHECK_EQ(sampleRate, (isWide ? 16000 : 8000));
+
+ mSource = source;
+
+ const char *kHeader = isWide ? "#!AMR-WB\n" : "#!AMR\n";
+ ssize_t n = strlen(kHeader);
+ if (write(mFd, kHeader, n) != n) {
+ return ERROR_IO;
+ }
+
+ return OK;
+}
+
+status_t AMRWriter::start(MetaData *params) {
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ 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) {
+ return err;
+ }
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+ mReachedEOS = false;
+ mDone = false;
+
+ pthread_create(&mThread, &attr, ThreadWrapper, this);
+ pthread_attr_destroy(&attr);
+
+ mStarted = true;
+
+ return OK;
+}
+
+status_t AMRWriter::pause() {
+ if (!mStarted) {
+ return OK;
+ }
+ mPaused = true;
+ return OK;
+}
+
+status_t AMRWriter::reset() {
+ if (!mStarted) {
+ return OK;
+ }
+
+ mDone = true;
+
+ void *dummy;
+ pthread_join(mThread, &dummy);
+
+ status_t err = (status_t) dummy;
+ {
+ status_t status = mSource->stop();
+ if (err == OK &&
+ (status != OK && status != ERROR_END_OF_STREAM)) {
+ err = status;
+ }
+ }
+
+ mStarted = false;
+ return err;
+}
+
+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) {
+ return (void *) static_cast<AMRWriter *>(me)->threadFunc();
+}
+
+status_t AMRWriter::threadFunc() {
+ mEstimatedDurationUs = 0;
+ mEstimatedSizeBytes = 0;
+ bool stoppedPrematurely = true;
+ int64_t previousPausedDurationUs = 0;
+ int64_t maxTimestampUs = 0;
+ status_t err = OK;
+
+ prctl(PR_SET_NAME, (unsigned long)"AMRWriter", 0, 0, 0);
+ while (!mDone) {
+ MediaBuffer *buffer;
+ err = mSource->read(&buffer);
+
+ if (err != OK) {
+ 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;
+ ALOGV("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 = write(mFd,
+ (const uint8_t *)buffer->data() + buffer->range_offset(),
+ buffer->range_length());
+
+ if (n < (ssize_t)buffer->range_length()) {
+ buffer->release();
+ buffer = NULL;
+
+ break;
+ }
+
+ // XXX: How to tell it is stopped prematurely?
+ if (stoppedPrematurely) {
+ stoppedPrematurely = false;
+ }
+
+ buffer->release();
+ buffer = NULL;
+ }
+
+ if (stoppedPrematurely) {
+ notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
+ }
+
+ close(mFd);
+ mFd = -1;
+ mReachedEOS = true;
+ if (err == ERROR_END_OF_STREAM) {
+ return OK;
+ }
+ return err;
+}
+
+bool AMRWriter::reachedEOS() {
+ return mReachedEOS;
+}
+
+} // namespace android
diff --git a/media/libstagefright/AVIExtractor.cpp b/media/libstagefright/AVIExtractor.cpp
new file mode 100644
index 0000000..5a6211e
--- /dev/null
+++ b/media/libstagefright/AVIExtractor.cpp
@@ -0,0 +1,1307 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "AVIExtractor"
+#include <utils/Log.h>
+
+#include "include/avc_utils.h"
+#include "include/AVIExtractor.h"
+
+#include <binder/ProcessState.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+struct AVIExtractor::AVISource : public MediaSource {
+ AVISource(const sp<AVIExtractor> &extractor, size_t trackIndex);
+
+ 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 ~AVISource();
+
+private:
+ sp<AVIExtractor> mExtractor;
+ size_t mTrackIndex;
+ const AVIExtractor::Track &mTrack;
+ MediaBufferGroup *mBufferGroup;
+ size_t mSampleIndex;
+
+ sp<MP3Splitter> mSplitter;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AVISource);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct AVIExtractor::MP3Splitter : public RefBase {
+ MP3Splitter();
+
+ void clear();
+ void append(MediaBuffer *buffer);
+ status_t read(MediaBuffer **buffer);
+
+protected:
+ virtual ~MP3Splitter();
+
+private:
+ bool mFindSync;
+ int64_t mBaseTimeUs;
+ int64_t mNumSamplesRead;
+ sp<ABuffer> mBuffer;
+
+ bool resync();
+
+ DISALLOW_EVIL_CONSTRUCTORS(MP3Splitter);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+AVIExtractor::AVISource::AVISource(
+ const sp<AVIExtractor> &extractor, size_t trackIndex)
+ : mExtractor(extractor),
+ mTrackIndex(trackIndex),
+ mTrack(mExtractor->mTracks.itemAt(trackIndex)),
+ mBufferGroup(NULL) {
+}
+
+AVIExtractor::AVISource::~AVISource() {
+ if (mBufferGroup) {
+ stop();
+ }
+}
+
+status_t AVIExtractor::AVISource::start(MetaData *params) {
+ CHECK(!mBufferGroup);
+
+ mBufferGroup = new MediaBufferGroup;
+
+ mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
+ mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
+ mSampleIndex = 0;
+
+ const char *mime;
+ CHECK(mTrack.mMeta->findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
+ mSplitter = new MP3Splitter;
+ } else {
+ mSplitter.clear();
+ }
+
+ return OK;
+}
+
+status_t AVIExtractor::AVISource::stop() {
+ CHECK(mBufferGroup);
+
+ delete mBufferGroup;
+ mBufferGroup = NULL;
+
+ mSplitter.clear();
+
+ return OK;
+}
+
+sp<MetaData> AVIExtractor::AVISource::getFormat() {
+ return mTrack.mMeta;
+}
+
+status_t AVIExtractor::AVISource::read(
+ MediaBuffer **buffer, const ReadOptions *options) {
+ CHECK(mBufferGroup);
+
+ *buffer = NULL;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode seekMode;
+ if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
+ status_t err =
+ mExtractor->getSampleIndexAtTime(
+ mTrackIndex, seekTimeUs, seekMode, &mSampleIndex);
+
+ if (err != OK) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ if (mSplitter != NULL) {
+ mSplitter->clear();
+ }
+ }
+
+ for (;;) {
+ if (mSplitter != NULL) {
+ status_t err = mSplitter->read(buffer);
+
+ if (err == OK) {
+ break;
+ } else if (err != -EAGAIN) {
+ return err;
+ }
+ }
+
+ off64_t offset;
+ size_t size;
+ bool isKey;
+ int64_t timeUs;
+ status_t err = mExtractor->getSampleInfo(
+ mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs);
+
+ ++mSampleIndex;
+
+ if (err != OK) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ MediaBuffer *out;
+ CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK);
+
+ ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size);
+
+ if (n < (ssize_t)size) {
+ return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
+ }
+
+ out->set_range(0, size);
+
+ out->meta_data()->setInt64(kKeyTime, timeUs);
+
+ if (isKey) {
+ out->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ }
+
+ if (mSplitter == NULL) {
+ *buffer = out;
+ break;
+ }
+
+ mSplitter->append(out);
+ out->release();
+ out = NULL;
+ }
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+AVIExtractor::MP3Splitter::MP3Splitter()
+ : mFindSync(true),
+ mBaseTimeUs(-1ll),
+ mNumSamplesRead(0) {
+}
+
+AVIExtractor::MP3Splitter::~MP3Splitter() {
+}
+
+void AVIExtractor::MP3Splitter::clear() {
+ mFindSync = true;
+ mBaseTimeUs = -1ll;
+ mNumSamplesRead = 0;
+
+ if (mBuffer != NULL) {
+ mBuffer->setRange(0, 0);
+ }
+}
+
+void AVIExtractor::MP3Splitter::append(MediaBuffer *buffer) {
+ size_t prevCapacity = (mBuffer != NULL) ? mBuffer->capacity() : 0;
+
+ if (mBaseTimeUs < 0) {
+ CHECK(mBuffer == NULL || mBuffer->size() == 0);
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &mBaseTimeUs));
+ mNumSamplesRead = 0;
+ }
+
+ if (mBuffer != NULL && mBuffer->offset() > 0) {
+ memmove(mBuffer->base(), mBuffer->data(), mBuffer->size());
+ mBuffer->setRange(0, mBuffer->size());
+ }
+
+ if (mBuffer == NULL
+ || mBuffer->size() + buffer->range_length() > prevCapacity) {
+ size_t newCapacity =
+ (prevCapacity + buffer->range_length() + 1023) & ~1023;
+
+ sp<ABuffer> newBuffer = new ABuffer(newCapacity);
+ if (mBuffer != NULL) {
+ memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
+ newBuffer->setRange(0, mBuffer->size());
+ } else {
+ newBuffer->setRange(0, 0);
+ }
+ mBuffer = newBuffer;
+ }
+
+ memcpy(mBuffer->data() + mBuffer->size(),
+ (const uint8_t *)buffer->data() + buffer->range_offset(),
+ buffer->range_length());
+
+ mBuffer->setRange(0, mBuffer->size() + buffer->range_length());
+}
+
+bool AVIExtractor::MP3Splitter::resync() {
+ if (mBuffer == NULL) {
+ return false;
+ }
+
+ bool foundSync = false;
+ for (size_t offset = 0; offset + 3 < mBuffer->size(); ++offset) {
+ uint32_t firstHeader = U32_AT(mBuffer->data() + offset);
+
+ size_t frameSize;
+ if (!GetMPEGAudioFrameSize(firstHeader, &frameSize)) {
+ continue;
+ }
+
+ size_t subsequentOffset = offset + frameSize;
+ size_t i = 3;
+ while (i > 0) {
+ if (subsequentOffset + 3 >= mBuffer->size()) {
+ break;
+ }
+
+ static const uint32_t kMask = 0xfffe0c00;
+
+ uint32_t header = U32_AT(mBuffer->data() + subsequentOffset);
+ if ((header & kMask) != (firstHeader & kMask)) {
+ break;
+ }
+
+ if (!GetMPEGAudioFrameSize(header, &frameSize)) {
+ break;
+ }
+
+ subsequentOffset += frameSize;
+ --i;
+ }
+
+ if (i == 0) {
+ foundSync = true;
+ memmove(mBuffer->data(),
+ mBuffer->data() + offset,
+ mBuffer->size() - offset);
+
+ mBuffer->setRange(0, mBuffer->size() - offset);
+ break;
+ }
+ }
+
+ return foundSync;
+}
+
+status_t AVIExtractor::MP3Splitter::read(MediaBuffer **out) {
+ *out = NULL;
+
+ if (mFindSync) {
+ if (!resync()) {
+ return -EAGAIN;
+ }
+
+ mFindSync = false;
+ }
+
+ if (mBuffer->size() < 4) {
+ return -EAGAIN;
+ }
+
+ uint32_t header = U32_AT(mBuffer->data());
+ size_t frameSize;
+ int sampleRate;
+ int numSamples;
+ if (!GetMPEGAudioFrameSize(
+ header, &frameSize, &sampleRate, NULL, NULL, &numSamples)) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mBuffer->size() < frameSize) {
+ return -EAGAIN;
+ }
+
+ MediaBuffer *mbuf = new MediaBuffer(frameSize);
+ memcpy(mbuf->data(), mBuffer->data(), frameSize);
+
+ int64_t timeUs = mBaseTimeUs + (mNumSamplesRead * 1000000ll) / sampleRate;
+ mNumSamplesRead += numSamples;
+
+ mbuf->meta_data()->setInt64(kKeyTime, timeUs);
+
+ mBuffer->setRange(
+ mBuffer->offset() + frameSize, mBuffer->size() - frameSize);
+
+ *out = mbuf;
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+AVIExtractor::AVIExtractor(const sp<DataSource> &dataSource)
+ : mDataSource(dataSource) {
+ mInitCheck = parseHeaders();
+
+ if (mInitCheck != OK) {
+ mTracks.clear();
+ }
+}
+
+AVIExtractor::~AVIExtractor() {
+}
+
+size_t AVIExtractor::countTracks() {
+ return mTracks.size();
+}
+
+sp<MediaSource> AVIExtractor::getTrack(size_t index) {
+ return index < mTracks.size() ? new AVISource(this, index) : NULL;
+}
+
+sp<MetaData> AVIExtractor::getTrackMetaData(
+ size_t index, uint32_t flags) {
+ return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL;
+}
+
+sp<MetaData> AVIExtractor::getMetaData() {
+ sp<MetaData> meta = new MetaData;
+
+ if (mInitCheck == OK) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI);
+ }
+
+ return meta;
+}
+
+status_t AVIExtractor::parseHeaders() {
+ mTracks.clear();
+ mMovieOffset = 0;
+ mFoundIndex = false;
+ mOffsetsAreAbsolute = false;
+
+ ssize_t res = parseChunk(0ll, -1ll);
+
+ if (res < 0) {
+ return (status_t)res;
+ }
+
+ if (mMovieOffset == 0ll || !mFoundIndex) {
+ return ERROR_MALFORMED;
+ }
+
+ return OK;
+}
+
+ssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) {
+ if (size >= 0 && size < 8) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t tmp[12];
+ ssize_t n = mDataSource->readAt(offset, tmp, 8);
+
+ if (n < 8) {
+ return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
+ }
+
+ uint32_t fourcc = U32_AT(tmp);
+ uint32_t chunkSize = U32LE_AT(&tmp[4]);
+
+ if (size >= 0 && chunkSize + 8 > size) {
+ return ERROR_MALFORMED;
+ }
+
+ static const char kPrefix[] = " ";
+ const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth];
+
+ if (fourcc == FOURCC('L', 'I', 'S', 'T')
+ || fourcc == FOURCC('R', 'I', 'F', 'F')) {
+ // It's a list of chunks
+
+ if (size >= 0 && size < 12) {
+ return ERROR_MALFORMED;
+ }
+
+ n = mDataSource->readAt(offset + 8, &tmp[8], 4);
+
+ if (n < 4) {
+ return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
+ }
+
+ uint32_t subFourcc = U32_AT(&tmp[8]);
+
+ ALOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d",
+ prefix,
+ offset,
+ (char)(subFourcc >> 24),
+ (char)((subFourcc >> 16) & 0xff),
+ (char)((subFourcc >> 8) & 0xff),
+ (char)(subFourcc & 0xff),
+ chunkSize - 4);
+
+ if (subFourcc == FOURCC('m', 'o', 'v', 'i')) {
+ // We're not going to parse this, but will take note of the
+ // offset.
+
+ mMovieOffset = offset;
+ } else {
+ off64_t subOffset = offset + 12;
+ off64_t subOffsetLimit = subOffset + chunkSize - 4;
+ while (subOffset < subOffsetLimit) {
+ ssize_t res =
+ parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1);
+
+ if (res < 0) {
+ return res;
+ }
+
+ subOffset += res;
+ }
+ }
+ } else {
+ ALOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'",
+ prefix,
+ offset,
+ (char)(fourcc >> 24),
+ (char)((fourcc >> 16) & 0xff),
+ (char)((fourcc >> 8) & 0xff),
+ (char)(fourcc & 0xff));
+
+ status_t err = OK;
+
+ switch (fourcc) {
+ case FOURCC('s', 't', 'r', 'h'):
+ {
+ err = parseStreamHeader(offset + 8, chunkSize);
+ break;
+ }
+
+ case FOURCC('s', 't', 'r', 'f'):
+ {
+ err = parseStreamFormat(offset + 8, chunkSize);
+ break;
+ }
+
+ case FOURCC('i', 'd', 'x', '1'):
+ {
+ err = parseIndex(offset + 8, chunkSize);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ if (chunkSize & 1) {
+ ++chunkSize;
+ }
+
+ return chunkSize + 8;
+}
+
+static const char *GetMIMETypeForHandler(uint32_t handler) {
+ switch (handler) {
+ // Wow... shamelessly copied from
+ // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4
+
+ case FOURCC('3', 'I', 'V', '2'):
+ case FOURCC('3', 'i', 'v', '2'):
+ case FOURCC('B', 'L', 'Z', '0'):
+ case FOURCC('D', 'I', 'G', 'I'):
+ case FOURCC('D', 'I', 'V', '1'):
+ case FOURCC('d', 'i', 'v', '1'):
+ case FOURCC('D', 'I', 'V', 'X'):
+ case FOURCC('d', 'i', 'v', 'x'):
+ case FOURCC('D', 'X', '5', '0'):
+ case FOURCC('d', 'x', '5', '0'):
+ case FOURCC('D', 'X', 'G', 'M'):
+ case FOURCC('E', 'M', '4', 'A'):
+ case FOURCC('E', 'P', 'H', 'V'):
+ case FOURCC('F', 'M', 'P', '4'):
+ case FOURCC('f', 'm', 'p', '4'):
+ case FOURCC('F', 'V', 'F', 'W'):
+ case FOURCC('H', 'D', 'X', '4'):
+ case FOURCC('h', 'd', 'x', '4'):
+ case FOURCC('M', '4', 'C', 'C'):
+ case FOURCC('M', '4', 'S', '2'):
+ case FOURCC('m', '4', 's', '2'):
+ case FOURCC('M', 'P', '4', 'S'):
+ case FOURCC('m', 'p', '4', 's'):
+ case FOURCC('M', 'P', '4', 'V'):
+ case FOURCC('m', 'p', '4', 'v'):
+ case FOURCC('M', 'V', 'X', 'M'):
+ case FOURCC('R', 'M', 'P', '4'):
+ case FOURCC('S', 'E', 'D', 'G'):
+ case FOURCC('S', 'M', 'P', '4'):
+ case FOURCC('U', 'M', 'P', '4'):
+ case FOURCC('W', 'V', '1', 'F'):
+ case FOURCC('X', 'V', 'I', 'D'):
+ case FOURCC('X', 'v', 'i', 'D'):
+ case FOURCC('x', 'v', 'i', 'd'):
+ case FOURCC('X', 'V', 'I', 'X'):
+ return MEDIA_MIMETYPE_VIDEO_MPEG4;
+
+ // from http://wiki.multimedia.cx/index.php?title=H264
+ case FOURCC('a', 'v', 'c', '1'):
+ case FOURCC('d', 'a', 'v', 'c'):
+ case FOURCC('x', '2', '6', '4'):
+ case FOURCC('H', '2', '6', '4'):
+ case FOURCC('v', 's', 's', 'h'):
+ return MEDIA_MIMETYPE_VIDEO_AVC;
+
+ default:
+ return NULL;
+ }
+}
+
+status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
+ if (size != 56) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mTracks.size() > 99) {
+ return -ERANGE;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(size);
+ ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
+
+ if (n < (ssize_t)size) {
+ return n < 0 ? (status_t)n : ERROR_MALFORMED;
+ }
+
+ const uint8_t *data = buffer->data();
+
+ uint32_t type = U32_AT(data);
+ uint32_t handler = U32_AT(&data[4]);
+ uint32_t flags = U32LE_AT(&data[8]);
+
+ sp<MetaData> meta = new MetaData;
+
+ uint32_t rate = U32LE_AT(&data[20]);
+ uint32_t scale = U32LE_AT(&data[24]);
+
+ uint32_t sampleSize = U32LE_AT(&data[44]);
+
+ const char *mime = NULL;
+ Track::Kind kind = Track::OTHER;
+
+ if (type == FOURCC('v', 'i', 'd', 's')) {
+ mime = GetMIMETypeForHandler(handler);
+
+ if (mime && strncasecmp(mime, "video/", 6)) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mime == NULL) {
+ ALOGW("Unsupported video format '%c%c%c%c'",
+ (char)(handler >> 24),
+ (char)((handler >> 16) & 0xff),
+ (char)((handler >> 8) & 0xff),
+ (char)(handler & 0xff));
+ }
+
+ kind = Track::VIDEO;
+ } else if (type == FOURCC('a', 'u', 'd', 's')) {
+ if (mime && strncasecmp(mime, "audio/", 6)) {
+ return ERROR_MALFORMED;
+ }
+
+ kind = Track::AUDIO;
+ }
+
+ if (!mime) {
+ mime = "application/octet-stream";
+ }
+
+ meta->setCString(kKeyMIMEType, mime);
+
+ mTracks.push();
+ Track *track = &mTracks.editItemAt(mTracks.size() - 1);
+
+ track->mMeta = meta;
+ track->mRate = rate;
+ track->mScale = scale;
+ track->mBytesPerSample = sampleSize;
+ track->mKind = kind;
+ track->mNumSyncSamples = 0;
+ track->mThumbnailSampleSize = 0;
+ track->mThumbnailSampleIndex = -1;
+ track->mMaxSampleSize = 0;
+ track->mAvgChunkSize = 1.0;
+ track->mFirstChunkSize = 0;
+
+ return OK;
+}
+
+status_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) {
+ if (mTracks.isEmpty()) {
+ return ERROR_MALFORMED;
+ }
+
+ Track *track = &mTracks.editItemAt(mTracks.size() - 1);
+
+ if (track->mKind == Track::OTHER) {
+ // We don't support this content, but that's not a parsing error.
+ return OK;
+ }
+
+ bool isVideo = (track->mKind == Track::VIDEO);
+
+ if ((isVideo && size < 40) || (!isVideo && size < 16)) {
+ // Expected a BITMAPINFO or WAVEFORMAT(EX) structure, respectively.
+ return ERROR_MALFORMED;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(size);
+ ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
+
+ if (n < (ssize_t)size) {
+ return n < 0 ? (status_t)n : ERROR_MALFORMED;
+ }
+
+ const uint8_t *data = buffer->data();
+
+ if (isVideo) {
+ uint32_t width = U32LE_AT(&data[4]);
+ uint32_t height = U32LE_AT(&data[8]);
+
+ track->mMeta->setInt32(kKeyWidth, width);
+ track->mMeta->setInt32(kKeyHeight, height);
+ } else {
+ uint32_t format = U16LE_AT(data);
+
+ if (format == 0x55) {
+ track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+ } else {
+ ALOGW("Unsupported audio format = 0x%04x", format);
+ }
+
+ uint32_t numChannels = U16LE_AT(&data[2]);
+ uint32_t sampleRate = U32LE_AT(&data[4]);
+
+ track->mMeta->setInt32(kKeyChannelCount, numChannels);
+ track->mMeta->setInt32(kKeySampleRate, sampleRate);
+ }
+
+ return OK;
+}
+
+// static
+bool AVIExtractor::IsCorrectChunkType(
+ ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) {
+ uint32_t chunkBase = chunkType & 0xffff;
+
+ switch (kind) {
+ case Track::VIDEO:
+ {
+ if (chunkBase != FOURCC(0, 0, 'd', 'c')
+ && chunkBase != FOURCC(0, 0, 'd', 'b')) {
+ return false;
+ }
+ break;
+ }
+
+ case Track::AUDIO:
+ {
+ if (chunkBase != FOURCC(0, 0, 'w', 'b')) {
+ return false;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (trackIndex < 0) {
+ return true;
+ }
+
+ uint8_t hi = chunkType >> 24;
+ uint8_t lo = (chunkType >> 16) & 0xff;
+
+ if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
+ return false;
+ }
+
+ if (trackIndex != (10 * (hi - '0') + (lo - '0'))) {
+ return false;
+ }
+
+ return true;
+}
+
+status_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
+ if ((size % 16) != 0) {
+ return ERROR_MALFORMED;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(size);
+ ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
+
+ if (n < (ssize_t)size) {
+ return n < 0 ? (status_t)n : ERROR_MALFORMED;
+ }
+
+ const uint8_t *data = buffer->data();
+
+ while (size > 0) {
+ uint32_t chunkType = U32_AT(data);
+
+ uint8_t hi = chunkType >> 24;
+ uint8_t lo = (chunkType >> 16) & 0xff;
+
+ if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
+ return ERROR_MALFORMED;
+ }
+
+ size_t trackIndex = 10 * (hi - '0') + (lo - '0');
+
+ if (trackIndex >= mTracks.size()) {
+ return ERROR_MALFORMED;
+ }
+
+ Track *track = &mTracks.editItemAt(trackIndex);
+
+ if (!IsCorrectChunkType(-1, track->mKind, chunkType)) {
+ return ERROR_MALFORMED;
+ }
+
+ if (track->mKind == Track::OTHER) {
+ data += 16;
+ size -= 16;
+ continue;
+ }
+
+ uint32_t flags = U32LE_AT(&data[4]);
+ uint32_t offset = U32LE_AT(&data[8]);
+ uint32_t chunkSize = U32LE_AT(&data[12]);
+
+ if (chunkSize > track->mMaxSampleSize) {
+ track->mMaxSampleSize = chunkSize;
+ }
+
+ track->mSamples.push();
+
+ SampleInfo *info =
+ &track->mSamples.editItemAt(track->mSamples.size() - 1);
+
+ info->mOffset = offset;
+ info->mIsKey = (flags & 0x10) != 0;
+
+ if (info->mIsKey) {
+ static const size_t kMaxNumSyncSamplesToScan = 20;
+
+ if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) {
+ if (chunkSize > track->mThumbnailSampleSize) {
+ track->mThumbnailSampleSize = chunkSize;
+
+ track->mThumbnailSampleIndex =
+ track->mSamples.size() - 1;
+ }
+ }
+
+ ++track->mNumSyncSamples;
+ }
+
+ data += 16;
+ size -= 16;
+ }
+
+ if (!mTracks.isEmpty()) {
+ off64_t offset;
+ size_t size;
+ bool isKey;
+ int64_t timeUs;
+ status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
+
+ if (err != OK) {
+ mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
+ err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ ALOGV("Chunk offsets are %s",
+ mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative");
+ }
+
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ Track *track = &mTracks.editItemAt(i);
+
+ if (track->mBytesPerSample > 0) {
+ // Assume all chunks are roughly the same size for now.
+
+ // Compute the avg. size of the first 128 chunks (if there are
+ // that many), but exclude the size of the first one, since
+ // it may be an outlier.
+ size_t numSamplesToAverage = track->mSamples.size();
+ if (numSamplesToAverage > 256) {
+ numSamplesToAverage = 256;
+ }
+
+ double avgChunkSize = 0;
+ size_t j;
+ for (j = 0; j <= numSamplesToAverage; ++j) {
+ off64_t offset;
+ size_t size;
+ bool isKey;
+ int64_t dummy;
+
+ status_t err =
+ getSampleInfo(
+ i, j,
+ &offset, &size, &isKey, &dummy);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (j == 0) {
+ track->mFirstChunkSize = size;
+ continue;
+ }
+
+ avgChunkSize += size;
+ }
+
+ avgChunkSize /= numSamplesToAverage;
+
+ track->mAvgChunkSize = avgChunkSize;
+ }
+
+ int64_t durationUs;
+ CHECK_EQ((status_t)OK,
+ getSampleTime(i, track->mSamples.size() - 1, &durationUs));
+
+ ALOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
+
+ track->mMeta->setInt64(kKeyDuration, durationUs);
+ track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize);
+
+ const char *tmp;
+ CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp));
+
+ AString mime = tmp;
+
+ if (!strncasecmp("video/", mime.c_str(), 6)) {
+ if (track->mThumbnailSampleIndex >= 0) {
+ int64_t thumbnailTimeUs;
+ CHECK_EQ((status_t)OK,
+ getSampleTime(i, track->mThumbnailSampleIndex,
+ &thumbnailTimeUs));
+
+ track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
+ }
+
+ status_t err = OK;
+
+ if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
+ err = addMPEG4CodecSpecificData(i);
+ } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
+ err = addH264CodecSpecificData(i);
+ }
+
+ if (err != OK) {
+ return err;
+ }
+ }
+ }
+
+ mFoundIndex = true;
+
+ return OK;
+}
+
+static size_t GetSizeWidth(size_t x) {
+ size_t n = 1;
+ while (x > 127) {
+ ++n;
+ x >>= 7;
+ }
+ return n;
+}
+
+static uint8_t *EncodeSize(uint8_t *dst, size_t x) {
+ while (x > 127) {
+ *dst++ = (x & 0x7f) | 0x80;
+ x >>= 7;
+ }
+ *dst++ = x;
+ return dst;
+}
+
+sp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) {
+ size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
+ size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
+ size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
+
+ sp<ABuffer> csd = new ABuffer(len3);
+ uint8_t *dst = csd->data();
+ *dst++ = 0x03;
+ dst = EncodeSize(dst, len2 + 3);
+ *dst++ = 0x00; // ES_ID
+ *dst++ = 0x00;
+ *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+ *dst++ = 0x04;
+ dst = EncodeSize(dst, len1 + 13);
+ *dst++ = 0x01; // Video ISO/IEC 14496-2 Simple Profile
+ for (size_t i = 0; i < 12; ++i) {
+ *dst++ = 0x00;
+ }
+
+ *dst++ = 0x05;
+ dst = EncodeSize(dst, config->size());
+ memcpy(dst, config->data(), config->size());
+ dst += config->size();
+
+ // hexdump(csd->data(), csd->size());
+
+ return csd;
+}
+
+status_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
+ Track *track = &mTracks.editItemAt(trackIndex);
+
+ off64_t offset;
+ size_t size;
+ bool isKey;
+ int64_t timeUs;
+ status_t err =
+ getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs);
+
+ if (err != OK) {
+ return err;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(size);
+ ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
+
+ if (n < (ssize_t)size) {
+ return n < 0 ? (status_t)n : ERROR_MALFORMED;
+ }
+
+ // Extract everything up to the first VOP start code from the first
+ // frame's encoded data and use it to construct an ESDS with the
+ // codec specific data.
+
+ size_t i = 0;
+ bool found = false;
+ while (i + 3 < buffer->size()) {
+ if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) {
+ found = true;
+ break;
+ }
+
+ ++i;
+ }
+
+ if (!found) {
+ return ERROR_MALFORMED;
+ }
+
+ buffer->setRange(0, i);
+
+ sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer);
+ track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size());
+
+ return OK;
+}
+
+status_t AVIExtractor::addH264CodecSpecificData(size_t trackIndex) {
+ Track *track = &mTracks.editItemAt(trackIndex);
+
+ off64_t offset;
+ size_t size;
+ bool isKey;
+ int64_t timeUs;
+
+ // Extract codec specific data from the first non-empty sample.
+
+ size_t sampleIndex = 0;
+ for (;;) {
+ status_t err =
+ getSampleInfo(
+ trackIndex, sampleIndex, &offset, &size, &isKey, &timeUs);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (size > 0) {
+ break;
+ }
+
+ ++sampleIndex;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(size);
+ ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
+
+ if (n < (ssize_t)size) {
+ return n < 0 ? (status_t)n : ERROR_MALFORMED;
+ }
+
+ sp<MetaData> meta = MakeAVCCodecSpecificData(buffer);
+
+ if (meta == NULL) {
+ ALOGE("Unable to extract AVC codec specific data");
+ return ERROR_MALFORMED;
+ }
+
+ int32_t width, height;
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+
+ uint32_t type;
+ const void *csd;
+ size_t csdSize;
+ CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize));
+
+ track->mMeta->setInt32(kKeyWidth, width);
+ track->mMeta->setInt32(kKeyHeight, height);
+ track->mMeta->setData(kKeyAVCC, type, csd, csdSize);
+
+ return OK;
+}
+
+status_t AVIExtractor::getSampleInfo(
+ size_t trackIndex, size_t sampleIndex,
+ off64_t *offset, size_t *size, bool *isKey,
+ int64_t *sampleTimeUs) {
+ if (trackIndex >= mTracks.size()) {
+ return -ERANGE;
+ }
+
+ const Track &track = mTracks.itemAt(trackIndex);
+
+ if (sampleIndex >= track.mSamples.size()) {
+ return -ERANGE;
+ }
+
+ const SampleInfo &info = track.mSamples.itemAt(sampleIndex);
+
+ if (!mOffsetsAreAbsolute) {
+ *offset = info.mOffset + mMovieOffset + 8;
+ } else {
+ *offset = info.mOffset;
+ }
+
+ *size = 0;
+
+ uint8_t tmp[8];
+ ssize_t n = mDataSource->readAt(*offset, tmp, 8);
+
+ if (n < 8) {
+ return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
+ }
+
+ uint32_t chunkType = U32_AT(tmp);
+
+ if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) {
+ return ERROR_MALFORMED;
+ }
+
+ *offset += 8;
+ *size = U32LE_AT(&tmp[4]);
+
+ *isKey = info.mIsKey;
+
+ if (track.mBytesPerSample > 0) {
+ size_t sampleStartInBytes;
+ if (sampleIndex == 0) {
+ sampleStartInBytes = 0;
+ } else {
+ sampleStartInBytes =
+ track.mFirstChunkSize + track.mAvgChunkSize * (sampleIndex - 1);
+ }
+
+ sampleIndex = sampleStartInBytes / track.mBytesPerSample;
+ }
+
+ *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale;
+
+ return OK;
+}
+
+status_t AVIExtractor::getSampleTime(
+ size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) {
+ off64_t offset;
+ size_t size;
+ bool isKey;
+ return getSampleInfo(
+ trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs);
+}
+
+status_t AVIExtractor::getSampleIndexAtTime(
+ size_t trackIndex,
+ int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
+ size_t *sampleIndex) const {
+ if (trackIndex >= mTracks.size()) {
+ return -ERANGE;
+ }
+
+ const Track &track = mTracks.itemAt(trackIndex);
+
+ ssize_t closestSampleIndex;
+
+ if (track.mBytesPerSample > 0) {
+ size_t closestByteOffset =
+ (timeUs * track.mBytesPerSample)
+ / track.mRate * track.mScale / 1000000ll;
+
+ if (closestByteOffset <= track.mFirstChunkSize) {
+ closestSampleIndex = 0;
+ } else {
+ closestSampleIndex =
+ (closestByteOffset - track.mFirstChunkSize)
+ / track.mAvgChunkSize;
+ }
+ } else {
+ // Each chunk contains a single sample.
+ closestSampleIndex = timeUs / track.mRate * track.mScale / 1000000ll;
+ }
+
+ ssize_t numSamples = track.mSamples.size();
+
+ if (closestSampleIndex < 0) {
+ closestSampleIndex = 0;
+ } else if (closestSampleIndex >= numSamples) {
+ closestSampleIndex = numSamples - 1;
+ }
+
+ if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) {
+ *sampleIndex = closestSampleIndex;
+
+ return OK;
+ }
+
+ ssize_t prevSyncSampleIndex = closestSampleIndex;
+ while (prevSyncSampleIndex >= 0) {
+ const SampleInfo &info =
+ track.mSamples.itemAt(prevSyncSampleIndex);
+
+ if (info.mIsKey) {
+ break;
+ }
+
+ --prevSyncSampleIndex;
+ }
+
+ ssize_t nextSyncSampleIndex = closestSampleIndex;
+ while (nextSyncSampleIndex < numSamples) {
+ const SampleInfo &info =
+ track.mSamples.itemAt(nextSyncSampleIndex);
+
+ if (info.mIsKey) {
+ break;
+ }
+
+ ++nextSyncSampleIndex;
+ }
+
+ switch (mode) {
+ case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC:
+ {
+ *sampleIndex = prevSyncSampleIndex;
+
+ return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR;
+ }
+
+ case MediaSource::ReadOptions::SEEK_NEXT_SYNC:
+ {
+ *sampleIndex = nextSyncSampleIndex;
+
+ return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR;
+ }
+
+ case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC:
+ {
+ if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (prevSyncSampleIndex < 0) {
+ *sampleIndex = nextSyncSampleIndex;
+ return OK;
+ }
+
+ if (nextSyncSampleIndex >= numSamples) {
+ *sampleIndex = prevSyncSampleIndex;
+ return OK;
+ }
+
+ size_t dist1 = closestSampleIndex - prevSyncSampleIndex;
+ size_t dist2 = nextSyncSampleIndex - closestSampleIndex;
+
+ *sampleIndex =
+ (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex;
+
+ return OK;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+bool SniffAVI(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
+ char tmp[12];
+ if (source->readAt(0, tmp, 12) < 12) {
+ return false;
+ }
+
+ if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) {
+ mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI);
+
+ // Just a tad over the mp3 extractor's confidence, since
+ // these .avi files may contain .mp3 content that otherwise would
+ // mistakenly lead to us identifying the entire file as a .mp3 file.
+ *confidence = 0.21;
+
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace android
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
new file mode 100644
index 0000000..8948abb
--- /dev/null
+++ b/media/libstagefright/Android.mk
@@ -0,0 +1,127 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+include frameworks/base/media/libstagefright/codecs/common/Config.mk
+
+LOCAL_SRC_FILES:= \
+ ACodec.cpp \
+ AACExtractor.cpp \
+ AACWriter.cpp \
+ AMRExtractor.cpp \
+ AMRWriter.cpp \
+ AVIExtractor.cpp \
+ AudioPlayer.cpp \
+ AudioSource.cpp \
+ AwesomePlayer.cpp \
+ CameraSource.cpp \
+ CameraSourceTimeLapse.cpp \
+ VideoSourceDownSampler.cpp \
+ DataSource.cpp \
+ DRMExtractor.cpp \
+ ESDS.cpp \
+ FileSource.cpp \
+ FLACExtractor.cpp \
+ HTTPBase.cpp \
+ JPEGSource.cpp \
+ MP3Extractor.cpp \
+ MPEG2TSWriter.cpp \
+ MPEG4Extractor.cpp \
+ MPEG4Writer.cpp \
+ MediaBuffer.cpp \
+ MediaBufferGroup.cpp \
+ MediaCodec.cpp \
+ MediaCodecList.cpp \
+ MediaDefs.cpp \
+ MediaExtractor.cpp \
+ MediaSource.cpp \
+ MetaData.cpp \
+ NuCachedSource2.cpp \
+ NuMediaExtractor.cpp \
+ OMXClient.cpp \
+ OMXCodec.cpp \
+ OggExtractor.cpp \
+ SampleIterator.cpp \
+ SampleTable.cpp \
+ SkipCutBuffer.cpp \
+ StagefrightMediaScanner.cpp \
+ StagefrightMetadataRetriever.cpp \
+ SurfaceMediaSource.cpp \
+ ThrottledSource.cpp \
+ TimeSource.cpp \
+ TimedEventQueue.cpp \
+ Utils.cpp \
+ VBRISeeker.cpp \
+ WAVExtractor.cpp \
+ WVMExtractor.cpp \
+ XINGSeeker.cpp \
+ avc_utils.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/base/include/media/stagefright/timedtext \
+ $(TOP)/frameworks/native/include/media/hardware \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/external/expat/lib \
+ $(TOP)/external/flac/include \
+ $(TOP)/external/tremolo \
+ $(TOP)/external/openssl/include \
+
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libcamera_client \
+ libcrypto \
+ libcutils \
+ libdl \
+ libdrmframework \
+ libexpat \
+ libgui \
+ libicui18n \
+ libicuuc \
+ liblog \
+ libmedia \
+ libmedia_native \
+ libsonivox \
+ libssl \
+ libstagefright_omx \
+ libstagefright_yuv \
+ libui \
+ libutils \
+ libvorbisidec \
+ libz \
+
+LOCAL_STATIC_LIBRARIES := \
+ libstagefright_color_conversion \
+ libstagefright_aacenc \
+ libstagefright_avcenc \
+ libstagefright_m4vh263enc \
+ libstagefright_matroska \
+ libstagefright_timedtext \
+ libvpx \
+ libstagefright_mpeg2ts \
+ libstagefright_httplive \
+ libstagefright_id3 \
+ libFLAC \
+
+ifneq ($(TARGET_BUILD_PDK), true)
+LOCAL_STATIC_LIBRARIES += \
+ libstagefright_chromium_http
+LOCAL_SHARED_LIBRARIES += \
+ libchromium_net
+LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1
+endif
+
+LOCAL_SHARED_LIBRARIES += libstlport
+include external/stlport/libstlport.mk
+
+LOCAL_SHARED_LIBRARIES += \
+ libstagefright_enc_common \
+ libstagefright_avc_common \
+ libstagefright_foundation \
+ libdl
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE:= libstagefright
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
new file mode 100644
index 0000000..0f816e7
--- /dev/null
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -0,0 +1,557 @@
+/*
+ * 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 "AudioPlayer"
+#include <utils/Log.h>
+
+#include <binder/IPCThreadState.h>
+#include <media/AudioTrack.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+#include "include/AwesomePlayer.h"
+
+namespace android {
+
+AudioPlayer::AudioPlayer(
+ const sp<MediaPlayerBase::AudioSink> &audioSink,
+ AwesomePlayer *observer)
+ : mAudioTrack(NULL),
+ mInputBuffer(NULL),
+ mSampleRate(0),
+ mLatencyUs(0),
+ mFrameSize(0),
+ mNumFramesPlayed(0),
+ mPositionTimeMediaUs(-1),
+ mPositionTimeRealUs(-1),
+ mSeeking(false),
+ mReachedEOS(false),
+ mFinalStatus(OK),
+ mStarted(false),
+ mIsFirstBuffer(false),
+ mFirstBufferResult(OK),
+ mFirstBuffer(NULL),
+ mAudioSink(audioSink),
+ mObserver(observer) {
+}
+
+AudioPlayer::~AudioPlayer() {
+ if (mStarted) {
+ reset();
+ }
+}
+
+void AudioPlayer::setSource(const sp<MediaSource> &source) {
+ CHECK(mSource == NULL);
+ mSource = source;
+}
+
+status_t AudioPlayer::start(bool sourceAlreadyStarted) {
+ CHECK(!mStarted);
+ CHECK(mSource != NULL);
+
+ status_t err;
+ if (!sourceAlreadyStarted) {
+ err = mSource->start();
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ // 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);
+
+ MediaSource::ReadOptions options;
+ if (mSeeking) {
+ options.setSeekTo(mSeekTimeUs);
+ mSeeking = false;
+ }
+
+ mFirstBufferResult = mSource->read(&mFirstBuffer, &options);
+ if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
+ ALOGV("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);
+ CHECK(success);
+ CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
+
+ success = format->findInt32(kKeySampleRate, &mSampleRate);
+ CHECK(success);
+
+ int32_t numChannels, channelMask;
+ success = format->findInt32(kKeyChannelCount, &numChannels);
+ CHECK(success);
+
+ if(!format->findInt32(kKeyChannelMask, &channelMask)) {
+ ALOGW("source format didn't specify channel mask, using channel order");
+ channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
+ }
+
+ if (mAudioSink.get() != NULL) {
+ status_t err = mAudioSink->open(
+ mSampleRate, numChannels, channelMask, AUDIO_FORMAT_PCM_16_BIT,
+ DEFAULT_AUDIOSINK_BUFFERCOUNT,
+ &AudioPlayer::AudioSinkCallback, this);
+ if (err != OK) {
+ if (mFirstBuffer != NULL) {
+ mFirstBuffer->release();
+ mFirstBuffer = NULL;
+ }
+
+ if (!sourceAlreadyStarted) {
+ mSource->stop();
+ }
+
+ return err;
+ }
+
+ mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
+ mFrameSize = mAudioSink->frameSize();
+
+ mAudioSink->start();
+ } else {
+ // playing to an AudioTrack, set up mask if necessary
+ audio_channel_mask_t audioMask = channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER ?
+ audio_channel_out_mask_from_count(numChannels) : channelMask;
+ if (0 == audioMask) {
+ return BAD_VALUE;
+ }
+
+ mAudioTrack = new AudioTrack(
+ AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask,
+ 0, AUDIO_POLICY_OUTPUT_FLAG_NONE, &AudioCallback, this, 0);
+
+ if ((err = mAudioTrack->initCheck()) != OK) {
+ delete mAudioTrack;
+ mAudioTrack = NULL;
+
+ if (mFirstBuffer != NULL) {
+ mFirstBuffer->release();
+ mFirstBuffer = NULL;
+ }
+
+ if (!sourceAlreadyStarted) {
+ mSource->stop();
+ }
+
+ return err;
+ }
+
+ mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
+ mFrameSize = mAudioTrack->frameSize();
+
+ mAudioTrack->start();
+ }
+
+ mStarted = true;
+
+ return OK;
+}
+
+void AudioPlayer::pause(bool playPendingSamples) {
+ CHECK(mStarted);
+
+ if (playPendingSamples) {
+ if (mAudioSink.get() != NULL) {
+ mAudioSink->stop();
+ } else {
+ mAudioTrack->stop();
+ }
+
+ mNumFramesPlayed = 0;
+ } else {
+ if (mAudioSink.get() != NULL) {
+ mAudioSink->pause();
+ } else {
+ mAudioTrack->pause();
+ }
+ }
+}
+
+void AudioPlayer::resume() {
+ CHECK(mStarted);
+
+ if (mAudioSink.get() != NULL) {
+ mAudioSink->start();
+ } else {
+ mAudioTrack->start();
+ }
+}
+
+void AudioPlayer::reset() {
+ CHECK(mStarted);
+
+ if (mAudioSink.get() != NULL) {
+ mAudioSink->stop();
+ mAudioSink->close();
+ } else {
+ mAudioTrack->stop();
+
+ delete mAudioTrack;
+ mAudioTrack = NULL;
+ }
+
+ // 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) {
+ ALOGV("AudioPlayer releasing input buffer.");
+
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ }
+
+ mSource->stop();
+
+ // The following hack is necessary to ensure that the OMX
+ // component is completely released by the time we may try
+ // to instantiate it again.
+ wp<MediaSource> tmp = mSource;
+ mSource.clear();
+ while (tmp.promote() != NULL) {
+ usleep(1000);
+ }
+ IPCThreadState::self()->flushCommands();
+
+ mNumFramesPlayed = 0;
+ mPositionTimeMediaUs = -1;
+ mPositionTimeRealUs = -1;
+ mSeeking = false;
+ mReachedEOS = false;
+ mFinalStatus = OK;
+ mStarted = false;
+}
+
+// static
+void AudioPlayer::AudioCallback(int event, void *user, void *info) {
+ static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
+}
+
+bool AudioPlayer::isSeeking() {
+ Mutex::Autolock autoLock(mLock);
+ return mSeeking;
+}
+
+bool AudioPlayer::reachedEOS(status_t *finalStatus) {
+ *finalStatus = OK;
+
+ Mutex::Autolock autoLock(mLock);
+ *finalStatus = mFinalStatus;
+ return mReachedEOS;
+}
+
+status_t AudioPlayer::setPlaybackRatePermille(int32_t ratePermille) {
+ if (mAudioSink.get() != NULL) {
+ return mAudioSink->setPlaybackRatePermille(ratePermille);
+ } else if (mAudioTrack != NULL){
+ return mAudioTrack->setSampleRate(ratePermille * mSampleRate / 1000);
+ } else {
+ return NO_INIT;
+ }
+}
+
+// static
+size_t AudioPlayer::AudioSinkCallback(
+ MediaPlayerBase::AudioSink *audioSink,
+ void *buffer, size_t size, void *cookie) {
+ AudioPlayer *me = (AudioPlayer *)cookie;
+
+ return me->fillBuffer(buffer, size);
+}
+
+void AudioPlayer::AudioCallback(int event, void *info) {
+ if (event != AudioTrack::EVENT_MORE_DATA) {
+ return;
+ }
+
+ AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
+ size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
+
+ buffer->size = numBytesWritten;
+}
+
+uint32_t AudioPlayer::getNumFramesPendingPlayout() const {
+ uint32_t numFramesPlayedOut;
+ status_t err;
+
+ if (mAudioSink != NULL) {
+ err = mAudioSink->getPosition(&numFramesPlayedOut);
+ } else {
+ err = mAudioTrack->getPosition(&numFramesPlayedOut);
+ }
+
+ if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
+ return 0;
+ }
+
+ // mNumFramesPlayed is the number of frames submitted
+ // to the audio sink for playback, but not all of them
+ // may have played out by now.
+ return mNumFramesPlayed - numFramesPlayedOut;
+}
+
+size_t AudioPlayer::fillBuffer(void *data, size_t size) {
+ if (mNumFramesPlayed == 0) {
+ ALOGV("AudioCallback");
+ }
+
+ if (mReachedEOS) {
+ return 0;
+ }
+
+ bool postSeekComplete = false;
+ bool postEOS = false;
+ int64_t postEOSDelayUs = 0;
+
+ size_t size_done = 0;
+ size_t size_remaining = size;
+ while (size_remaining > 0) {
+ MediaSource::ReadOptions options;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mSeeking) {
+ if (mIsFirstBuffer) {
+ if (mFirstBuffer != NULL) {
+ mFirstBuffer->release();
+ mFirstBuffer = NULL;
+ }
+ mIsFirstBuffer = false;
+ }
+
+ options.setSeekTo(mSeekTimeUs);
+
+ if (mInputBuffer != NULL) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ }
+
+ mSeeking = false;
+ if (mObserver) {
+ postSeekComplete = true;
+ }
+ }
+ }
+
+ if (mInputBuffer == NULL) {
+ 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));
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (err != OK) {
+ if (mObserver && !mReachedEOS) {
+ // We don't want to post EOS right away but only
+ // after all frames have actually been played out.
+
+ // These are the number of frames submitted to the
+ // AudioTrack that you haven't heard yet.
+ uint32_t numFramesPendingPlayout =
+ getNumFramesPendingPlayout();
+
+ // These are the number of frames we're going to
+ // submit to the AudioTrack by returning from this
+ // callback.
+ uint32_t numAdditionalFrames = size_done / mFrameSize;
+
+ numFramesPendingPlayout += numAdditionalFrames;
+
+ int64_t timeToCompletionUs =
+ (1000000ll * numFramesPendingPlayout) / mSampleRate;
+
+ ALOGV("total number of frames played: %lld (%lld us)",
+ (mNumFramesPlayed + numAdditionalFrames),
+ 1000000ll * (mNumFramesPlayed + numAdditionalFrames)
+ / mSampleRate);
+
+ ALOGV("%d frames left to play, %lld us (%.2f secs)",
+ numFramesPendingPlayout,
+ timeToCompletionUs, timeToCompletionUs / 1E6);
+
+ postEOS = true;
+ if (mAudioSink->needsTrailingPadding()) {
+ postEOSDelayUs = timeToCompletionUs + mLatencyUs;
+ } else {
+ postEOSDelayUs = 0;
+ }
+ }
+
+ mReachedEOS = true;
+ mFinalStatus = err;
+ break;
+ }
+
+ if (mAudioSink != NULL) {
+ mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
+ } else {
+ mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
+ }
+
+ CHECK(mInputBuffer->meta_data()->findInt64(
+ kKeyTime, &mPositionTimeMediaUs));
+
+ mPositionTimeRealUs =
+ -mLatencyUs + ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
+ / mSampleRate;
+ if (mPositionTimeRealUs < 0) {
+ mPositionTimeRealUs = 0;
+ }
+
+ ALOGV("buffer->size() = %d, "
+ "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
+ mInputBuffer->range_length(),
+ mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
+ }
+
+ if (mInputBuffer->range_length() == 0) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+
+ continue;
+ }
+
+ size_t copy = size_remaining;
+ if (copy > mInputBuffer->range_length()) {
+ copy = mInputBuffer->range_length();
+ }
+
+ memcpy((char *)data + size_done,
+ (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
+ copy);
+
+ mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
+ mInputBuffer->range_length() - copy);
+
+ size_done += copy;
+ size_remaining -= copy;
+ }
+
+ {
+ Mutex::Autolock autoLock(mLock);
+ mNumFramesPlayed += size_done / mFrameSize;
+ }
+
+ if (postEOS) {
+ mObserver->postAudioEOS(postEOSDelayUs);
+ }
+
+ if (postSeekComplete) {
+ mObserver->postAudioSeekComplete();
+ }
+
+ return size_done;
+}
+
+int64_t AudioPlayer::getRealTimeUs() {
+ Mutex::Autolock autoLock(mLock);
+ return getRealTimeUsLocked();
+}
+
+int64_t AudioPlayer::getRealTimeUsLocked() const {
+ CHECK(mStarted);
+ CHECK_NE(mSampleRate, 0);
+ int64_t t = -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
+ if (t < 0) return 0;
+ return t;
+}
+
+int64_t AudioPlayer::getMediaTimeUs() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
+ if (mSeeking) {
+ return mSeekTimeUs;
+ }
+
+ return 0;
+ }
+
+ int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
+ if (realTimeOffset < 0) {
+ realTimeOffset = 0;
+ }
+
+ return mPositionTimeMediaUs + realTimeOffset;
+}
+
+bool AudioPlayer::getMediaTimeMapping(
+ int64_t *realtime_us, int64_t *mediatime_us) {
+ Mutex::Autolock autoLock(mLock);
+
+ *realtime_us = mPositionTimeRealUs;
+ *mediatime_us = mPositionTimeMediaUs;
+
+ return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
+}
+
+status_t AudioPlayer::seekTo(int64_t time_us) {
+ Mutex::Autolock autoLock(mLock);
+
+ mSeeking = true;
+ mPositionTimeRealUs = mPositionTimeMediaUs = -1;
+ mReachedEOS = false;
+ mSeekTimeUs = time_us;
+
+ // Flush resets the number of played frames
+ mNumFramesPlayed = 0;
+
+ if (mAudioSink != NULL) {
+ mAudioSink->flush();
+ } else {
+ mAudioTrack->flush();
+ }
+
+ return OK;
+}
+
+}
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
new file mode 100644
index 0000000..0f1d841
--- /dev/null
+++ b/media/libstagefright/AudioSource.cpp
@@ -0,0 +1,372 @@
+/*
+ * 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 "AudioSource"
+#include <utils/Log.h>
+
+#include <media/AudioRecord.h>
+#include <media/stagefright/AudioSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <cutils/properties.h>
+#include <stdlib.h>
+
+namespace android {
+
+static void AudioRecordCallbackFunction(int event, void *user, void *info) {
+ AudioSource *source = (AudioSource *) user;
+ switch (event) {
+ case AudioRecord::EVENT_MORE_DATA: {
+ source->dataCallbackTimestamp(*((AudioRecord::Buffer *) info), systemTime() / 1000);
+ break;
+ }
+ case AudioRecord::EVENT_OVERRUN: {
+ ALOGW("AudioRecord reported overrun!");
+ break;
+ }
+ default:
+ // does nothing
+ break;
+ }
+}
+
+AudioSource::AudioSource(
+ audio_source_t inputSource, uint32_t sampleRate, uint32_t channelCount)
+ : mStarted(false),
+ mSampleRate(sampleRate),
+ mPrevSampleTimeUs(0),
+ mNumFramesReceived(0),
+ mNumClientOwnedBuffers(0) {
+
+ ALOGV("sampleRate: %d, channelCount: %d", sampleRate, channelCount);
+ CHECK(channelCount == 1 || channelCount == 2);
+ AudioRecord::record_flags flags = (AudioRecord::record_flags)
+ (AudioRecord::RECORD_AGC_ENABLE |
+ AudioRecord::RECORD_NS_ENABLE |
+ AudioRecord::RECORD_IIR_ENABLE);
+ mRecord = new AudioRecord(
+ inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT,
+ audio_channel_in_mask_from_count(channelCount),
+ 4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */
+ flags,
+ AudioRecordCallbackFunction,
+ this);
+
+ mInitCheck = mRecord->initCheck();
+}
+
+AudioSource::~AudioSource() {
+ if (mStarted) {
+ reset();
+ }
+
+ delete mRecord;
+ mRecord = NULL;
+}
+
+status_t AudioSource::initCheck() const {
+ return mInitCheck;
+}
+
+status_t AudioSource::start(MetaData *params) {
+ Mutex::Autolock autoLock(mLock);
+ if (mStarted) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (mInitCheck != OK) {
+ return NO_INIT;
+ }
+
+ mTrackMaxAmplitude = false;
+ mMaxAmplitude = 0;
+ mInitialReadTimeUs = 0;
+ mStartTimeUs = 0;
+ int64_t startTimeUs;
+ if (params && params->findInt64(kKeyTime, &startTimeUs)) {
+ mStartTimeUs = startTimeUs;
+ }
+ status_t err = mRecord->start();
+ if (err == OK) {
+ mStarted = true;
+ } else {
+ delete mRecord;
+ mRecord = NULL;
+ }
+
+
+ return err;
+}
+
+void AudioSource::releaseQueuedFrames_l() {
+ ALOGV("releaseQueuedFrames_l");
+ List<MediaBuffer *>::iterator it;
+ while (!mBuffersReceived.empty()) {
+ it = mBuffersReceived.begin();
+ (*it)->release();
+ mBuffersReceived.erase(it);
+ }
+}
+
+void AudioSource::waitOutstandingEncodingFrames_l() {
+ ALOGV("waitOutstandingEncodingFrames_l: %lld", mNumClientOwnedBuffers);
+ while (mNumClientOwnedBuffers > 0) {
+ mFrameEncodingCompletionCondition.wait(mLock);
+ }
+}
+
+status_t AudioSource::reset() {
+ Mutex::Autolock autoLock(mLock);
+ if (!mStarted) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (mInitCheck != OK) {
+ return NO_INIT;
+ }
+
+ mStarted = false;
+ mRecord->stop();
+ waitOutstandingEncodingFrames_l();
+ releaseQueuedFrames_l();
+
+ return OK;
+}
+
+sp<MetaData> AudioSource::getFormat() {
+ Mutex::Autolock autoLock(mLock);
+ if (mInitCheck != OK) {
+ return 0;
+ }
+
+ sp<MetaData> meta = new MetaData;
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+ meta->setInt32(kKeySampleRate, mSampleRate);
+ meta->setInt32(kKeyChannelCount, mRecord->channelCount());
+ meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
+
+ return meta;
+}
+
+void AudioSource::rampVolume(
+ int32_t startFrame, int32_t rampDurationFrames,
+ uint8_t *data, size_t bytes) {
+
+ const int32_t kShift = 14;
+ int32_t fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
+ const int32_t nChannels = mRecord->channelCount();
+ int32_t stopFrame = startFrame + bytes / sizeof(int16_t);
+ int16_t *frame = (int16_t *) data;
+ if (stopFrame > rampDurationFrames) {
+ stopFrame = rampDurationFrames;
+ }
+
+ while (startFrame < stopFrame) {
+ if (nChannels == 1) { // mono
+ frame[0] = (frame[0] * fixedMultiplier) >> kShift;
+ ++frame;
+ ++startFrame;
+ } else { // stereo
+ frame[0] = (frame[0] * fixedMultiplier) >> kShift;
+ frame[1] = (frame[1] * fixedMultiplier) >> kShift;
+ frame += 2;
+ startFrame += 2;
+ }
+
+ // Update the multiplier every 4 frames
+ if ((startFrame & 3) == 0) {
+ fixedMultiplier = (startFrame << kShift) / rampDurationFrames;
+ }
+ }
+}
+
+status_t AudioSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ Mutex::Autolock autoLock(mLock);
+ *out = NULL;
+
+ if (mInitCheck != OK) {
+ return NO_INIT;
+ }
+
+ while (mStarted && mBuffersReceived.empty()) {
+ mFrameAvailableCondition.wait(mLock);
+ }
+ if (!mStarted) {
+ return OK;
+ }
+ MediaBuffer *buffer = *mBuffersReceived.begin();
+ mBuffersReceived.erase(mBuffersReceived.begin());
+ ++mNumClientOwnedBuffers;
+ buffer->setObserver(this);
+ buffer->add_ref();
+
+ // Mute/suppress the recording sound
+ int64_t timeUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ int64_t elapsedTimeUs = timeUs - mStartTimeUs;
+ if (elapsedTimeUs < kAutoRampStartUs) {
+ memset((uint8_t *) buffer->data(), 0, buffer->range_length());
+ } else if (elapsedTimeUs < kAutoRampStartUs + kAutoRampDurationUs) {
+ int32_t autoRampDurationFrames =
+ (kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL;
+
+ int32_t autoRampStartFrames =
+ (kAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL;
+
+ int32_t nFrames = mNumFramesReceived - autoRampStartFrames;
+ rampVolume(nFrames, autoRampDurationFrames,
+ (uint8_t *) buffer->data(), buffer->range_length());
+ }
+
+ // Track the max recording signal amplitude.
+ if (mTrackMaxAmplitude) {
+ trackMaxAmplitude(
+ (int16_t *) buffer->data(), buffer->range_length() >> 1);
+ }
+
+ *out = buffer;
+ return OK;
+}
+
+void AudioSource::signalBufferReturned(MediaBuffer *buffer) {
+ ALOGV("signalBufferReturned: %p", buffer->data());
+ Mutex::Autolock autoLock(mLock);
+ --mNumClientOwnedBuffers;
+ buffer->setObserver(0);
+ buffer->release();
+ mFrameEncodingCompletionCondition.signal();
+ return;
+}
+
+status_t AudioSource::dataCallbackTimestamp(
+ const AudioRecord::Buffer& audioBuffer, int64_t timeUs) {
+ ALOGV("dataCallbackTimestamp: %lld us", timeUs);
+ Mutex::Autolock autoLock(mLock);
+ if (!mStarted) {
+ ALOGW("Spurious callback from AudioRecord. Drop the audio data.");
+ return OK;
+ }
+
+ // Drop retrieved and previously lost audio data.
+ if (mNumFramesReceived == 0 && timeUs < mStartTimeUs) {
+ mRecord->getInputFramesLost();
+ ALOGV("Drop audio data at %lld/%lld us", timeUs, mStartTimeUs);
+ return OK;
+ }
+
+ if (mNumFramesReceived == 0 && mPrevSampleTimeUs == 0) {
+ mInitialReadTimeUs = timeUs;
+ // Initial delay
+ if (mStartTimeUs > 0) {
+ mStartTimeUs = timeUs - mStartTimeUs;
+ } else {
+ // Assume latency is constant.
+ mStartTimeUs += mRecord->latency() * 1000;
+ }
+ mPrevSampleTimeUs = mStartTimeUs;
+ }
+
+ size_t numLostBytes = 0;
+ if (mNumFramesReceived > 0) { // Ignore earlier frame lost
+ // getInputFramesLost() returns the number of lost frames.
+ // Convert number of frames lost to number of bytes lost.
+ numLostBytes = mRecord->getInputFramesLost() * mRecord->frameSize();
+ }
+
+ CHECK_EQ(numLostBytes & 1, 0u);
+ CHECK_EQ(audioBuffer.size & 1, 0u);
+ if (numLostBytes > 0) {
+ // Loss of audio frames should happen rarely; thus the LOGW should
+ // not cause a logging spam
+ ALOGW("Lost audio record data: %d bytes", numLostBytes);
+ }
+
+ while (numLostBytes > 0) {
+ size_t bufferSize = numLostBytes;
+ if (numLostBytes > kMaxBufferSize) {
+ numLostBytes -= kMaxBufferSize;
+ bufferSize = kMaxBufferSize;
+ } else {
+ numLostBytes = 0;
+ }
+ MediaBuffer *lostAudioBuffer = new MediaBuffer(bufferSize);
+ memset(lostAudioBuffer->data(), 0, bufferSize);
+ lostAudioBuffer->set_range(0, bufferSize);
+ queueInputBuffer_l(lostAudioBuffer, timeUs);
+ }
+
+ if (audioBuffer.size == 0) {
+ ALOGW("Nothing is available from AudioRecord callback buffer");
+ return OK;
+ }
+
+ const size_t bufferSize = audioBuffer.size;
+ MediaBuffer *buffer = new MediaBuffer(bufferSize);
+ memcpy((uint8_t *) buffer->data(),
+ audioBuffer.i16, audioBuffer.size);
+ buffer->set_range(0, bufferSize);
+ queueInputBuffer_l(buffer, timeUs);
+ return OK;
+}
+
+void AudioSource::queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs) {
+ const size_t bufferSize = buffer->range_length();
+ const size_t frameSize = mRecord->frameSize();
+ const int64_t timestampUs =
+ mPrevSampleTimeUs +
+ ((1000000LL * (bufferSize / frameSize)) +
+ (mSampleRate >> 1)) / mSampleRate;
+
+ if (mNumFramesReceived == 0) {
+ buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
+ }
+
+ buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
+ buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs);
+ mPrevSampleTimeUs = timestampUs;
+ mNumFramesReceived += bufferSize / frameSize;
+ mBuffersReceived.push_back(buffer);
+ mFrameAvailableCondition.signal();
+}
+
+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;
+ }
+ }
+}
+
+int16_t AudioSource::getMaxAmplitude() {
+ // First call activates the tracking.
+ if (!mTrackMaxAmplitude) {
+ mTrackMaxAmplitude = true;
+ }
+ int16_t value = mMaxAmplitude;
+ mMaxAmplitude = 0;
+ ALOGV("max amplitude since last call: %d", value);
+ return value;
+}
+
+} // namespace android
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
new file mode 100644
index 0000000..f96a4df
--- /dev/null
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -0,0 +1,2416 @@
+/*
+ * 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.
+ */
+
+#undef DEBUG_HDCP
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AwesomePlayer"
+#include <utils/Log.h>
+
+#include <dlfcn.h>
+
+#include "include/AwesomePlayer.h"
+#include "include/DRMExtractor.h"
+#include "include/SoftwareRenderer.h"
+#include "include/NuCachedSource2.h"
+#include "include/ThrottledSource.h"
+#include "include/MPEG2TSExtractor.h"
+#include "include/WVMExtractor.h"
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <media/IMediaPlayerService.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/timedtext/TimedTextDriver.h>
+#include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXCodec.h>
+
+#include <gui/ISurfaceTexture.h>
+#include <gui/SurfaceTextureClient.h>
+
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <cutils/properties.h>
+
+#define USE_SURFACE_ALLOC 1
+#define FRAME_DROP_FREQ 0
+
+namespace android {
+
+static int64_t kLowWaterMarkUs = 2000000ll; // 2secs
+static int64_t kHighWaterMarkUs = 5000000ll; // 5secs
+static const size_t kLowWaterMarkBytes = 40000;
+static const size_t kHighWaterMarkBytes = 200000;
+
+struct AwesomeEvent : public TimedEventQueue::Event {
+ AwesomeEvent(
+ AwesomePlayer *player,
+ void (AwesomePlayer::*method)())
+ : mPlayer(player),
+ mMethod(method) {
+ }
+
+protected:
+ virtual ~AwesomeEvent() {}
+
+ virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
+ (mPlayer->*mMethod)();
+ }
+
+private:
+ AwesomePlayer *mPlayer;
+ void (AwesomePlayer::*mMethod)();
+
+ AwesomeEvent(const AwesomeEvent &);
+ AwesomeEvent &operator=(const AwesomeEvent &);
+};
+
+struct AwesomeLocalRenderer : public AwesomeRenderer {
+ AwesomeLocalRenderer(
+ const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta)
+ : mTarget(new SoftwareRenderer(nativeWindow, meta)) {
+ }
+
+ virtual void render(MediaBuffer *buffer) {
+ render((const uint8_t *)buffer->data() + buffer->range_offset(),
+ buffer->range_length());
+ }
+
+ void render(const void *data, size_t size) {
+ mTarget->render(data, size, NULL);
+ }
+
+protected:
+ virtual ~AwesomeLocalRenderer() {
+ delete mTarget;
+ mTarget = NULL;
+ }
+
+private:
+ SoftwareRenderer *mTarget;
+
+ AwesomeLocalRenderer(const AwesomeLocalRenderer &);
+ AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
+};
+
+struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
+ AwesomeNativeWindowRenderer(
+ const sp<ANativeWindow> &nativeWindow,
+ int32_t rotationDegrees)
+ : mNativeWindow(nativeWindow) {
+ applyRotation(rotationDegrees);
+ }
+
+ virtual void render(MediaBuffer *buffer) {
+ int64_t timeUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ native_window_set_buffers_timestamp(mNativeWindow.get(), timeUs * 1000);
+ status_t err = mNativeWindow->queueBuffer(
+ mNativeWindow.get(), buffer->graphicBuffer().get());
+ if (err != 0) {
+ ALOGE("queueBuffer failed with error %s (%d)", strerror(-err),
+ -err);
+ return;
+ }
+
+ sp<MetaData> metaData = buffer->meta_data();
+ metaData->setInt32(kKeyRendered, 1);
+ }
+
+protected:
+ virtual ~AwesomeNativeWindowRenderer() {}
+
+private:
+ sp<ANativeWindow> mNativeWindow;
+
+ void applyRotation(int32_t rotationDegrees) {
+ uint32_t transform;
+ switch (rotationDegrees) {
+ case 0: transform = 0; break;
+ case 90: transform = HAL_TRANSFORM_ROT_90; break;
+ case 180: transform = HAL_TRANSFORM_ROT_180; break;
+ case 270: transform = HAL_TRANSFORM_ROT_270; break;
+ default: transform = 0; break;
+ }
+
+ if (transform) {
+ CHECK_EQ(0, native_window_set_buffers_transform(
+ mNativeWindow.get(), transform));
+ }
+ }
+
+ AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
+ AwesomeNativeWindowRenderer &operator=(
+ const AwesomeNativeWindowRenderer &);
+};
+
+// To collect the decoder usage
+void addBatteryData(uint32_t params) {
+ sp<IBinder> binder =
+ defaultServiceManager()->getService(String16("media.player"));
+ sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+ CHECK(service.get() != NULL);
+
+ service->addBatteryData(params);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+AwesomePlayer::AwesomePlayer()
+ : mQueueStarted(false),
+ mUIDValid(false),
+ mTimeSource(NULL),
+ mVideoRendererIsPreview(false),
+ mAudioPlayer(NULL),
+ mDisplayWidth(0),
+ mDisplayHeight(0),
+ mFlags(0),
+ mExtractorFlags(0),
+ mVideoBuffer(NULL),
+ mDecryptHandle(NULL),
+ mLastVideoTimeUs(-1),
+ mTextDriver(NULL) {
+ CHECK_EQ(mClient.connect(), (status_t)OK);
+
+ DataSource::RegisterDefaultSniffers();
+
+ mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
+ mVideoEventPending = false;
+ mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
+ mStreamDoneEventPending = false;
+ mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
+ mBufferingEventPending = false;
+ mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);
+ mVideoEventPending = false;
+
+ mCheckAudioStatusEvent = new AwesomeEvent(
+ this, &AwesomePlayer::onCheckAudioStatus);
+
+ mAudioStatusEventPending = false;
+
+ reset();
+}
+
+AwesomePlayer::~AwesomePlayer() {
+ if (mQueueStarted) {
+ mQueue.stop();
+ }
+
+ reset();
+
+ mClient.disconnect();
+}
+
+void AwesomePlayer::cancelPlayerEvents(bool keepNotifications) {
+ mQueue.cancelEvent(mVideoEvent->eventID());
+ mVideoEventPending = false;
+ mQueue.cancelEvent(mVideoLagEvent->eventID());
+ mVideoLagEventPending = false;
+
+ if (!keepNotifications) {
+ mQueue.cancelEvent(mStreamDoneEvent->eventID());
+ mStreamDoneEventPending = false;
+ mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
+ mAudioStatusEventPending = false;
+
+ mQueue.cancelEvent(mBufferingEvent->eventID());
+ mBufferingEventPending = false;
+ }
+}
+
+void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
+ Mutex::Autolock autoLock(mLock);
+ mListener = listener;
+}
+
+void AwesomePlayer::setUID(uid_t uid) {
+ ALOGV("AwesomePlayer running on behalf of uid %d", uid);
+
+ mUID = uid;
+ mUIDValid = true;
+}
+
+status_t AwesomePlayer::setDataSource(
+ const char *uri, const KeyedVector<String8, String8> *headers) {
+ Mutex::Autolock autoLock(mLock);
+ return setDataSource_l(uri, headers);
+}
+
+status_t AwesomePlayer::setDataSource_l(
+ const char *uri, const KeyedVector<String8, String8> *headers) {
+ reset_l();
+
+ mUri = uri;
+
+ if (headers) {
+ mUriHeaders = *headers;
+
+ ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log"));
+ if (index >= 0) {
+ // Browser is in "incognito" mode, suppress logging URLs.
+
+ // This isn't something that should be passed to the server.
+ mUriHeaders.removeItemsAt(index);
+
+ modifyFlags(INCOGNITO, SET);
+ }
+ }
+
+ if (!(mFlags & INCOGNITO)) {
+ ALOGI("setDataSource_l('%s')", mUri.string());
+ } else {
+ ALOGI("setDataSource_l(URL suppressed)");
+ }
+
+ // The actual work will be done during preparation in the call to
+ // ::finishSetDataSource_l to avoid blocking the calling thread in
+ // setDataSource for any significant time.
+
+ {
+ Mutex::Autolock autoLock(mStatsLock);
+ mStats.mFd = -1;
+ mStats.mURI = mUri;
+ }
+
+ return OK;
+}
+
+status_t AwesomePlayer::setDataSource(
+ int fd, int64_t offset, int64_t length) {
+ Mutex::Autolock autoLock(mLock);
+
+ reset_l();
+
+ sp<DataSource> dataSource = new FileSource(fd, offset, length);
+
+ status_t err = dataSource->initCheck();
+
+ if (err != OK) {
+ return err;
+ }
+
+ mFileSource = dataSource;
+
+ {
+ Mutex::Autolock autoLock(mStatsLock);
+ mStats.mFd = fd;
+ mStats.mURI = String8();
+ }
+
+ return setDataSource_l(dataSource);
+}
+
+status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
+ return INVALID_OPERATION;
+}
+
+status_t AwesomePlayer::setDataSource_l(
+ const sp<DataSource> &dataSource) {
+ sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+
+ if (extractor == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (extractor->getDrmFlag()) {
+ checkDrmStatus(dataSource);
+ }
+
+ return setDataSource_l(extractor);
+}
+
+void AwesomePlayer::checkDrmStatus(const sp<DataSource>& dataSource) {
+ dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
+ if (mDecryptHandle != NULL) {
+ CHECK(mDrmManagerClient);
+ if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
+ notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
+ }
+ }
+}
+
+status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
+ // Attempt to approximate overall stream bitrate by summing all
+ // tracks' individual bitrates, if not all of them advertise bitrate,
+ // we have to fail.
+
+ int64_t totalBitRate = 0;
+
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+ int32_t bitrate;
+ if (!meta->findInt32(kKeyBitRate, &bitrate)) {
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+ ALOGV("track of type '%s' does not publish bitrate", mime);
+
+ totalBitRate = -1;
+ break;
+ }
+
+ totalBitRate += bitrate;
+ }
+
+ mBitrate = totalBitRate;
+
+ ALOGV("mBitrate = %lld bits/sec", mBitrate);
+
+ {
+ Mutex::Autolock autoLock(mStatsLock);
+ mStats.mBitrate = mBitrate;
+ mStats.mTracks.clear();
+ mStats.mAudioTrackIndex = -1;
+ mStats.mVideoTrackIndex = -1;
+ }
+
+ bool haveAudio = false;
+ bool haveVideo = false;
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+ const char *_mime;
+ CHECK(meta->findCString(kKeyMIMEType, &_mime));
+
+ String8 mime = String8(_mime);
+
+ if (!haveVideo && !strncasecmp(mime.string(), "video/", 6)) {
+ setVideoSource(extractor->getTrack(i));
+ haveVideo = true;
+
+ // Set the presentation/display size
+ int32_t displayWidth, displayHeight;
+ bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
+ if (success) {
+ success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
+ }
+ if (success) {
+ mDisplayWidth = displayWidth;
+ mDisplayHeight = displayHeight;
+ }
+
+ {
+ Mutex::Autolock autoLock(mStatsLock);
+ mStats.mVideoTrackIndex = mStats.mTracks.size();
+ mStats.mTracks.push();
+ TrackStat *stat =
+ &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
+ stat->mMIME = mime.string();
+ }
+ } else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) {
+ setAudioSource(extractor->getTrack(i));
+ haveAudio = true;
+
+ {
+ Mutex::Autolock autoLock(mStatsLock);
+ mStats.mAudioTrackIndex = mStats.mTracks.size();
+ mStats.mTracks.push();
+ TrackStat *stat =
+ &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
+ stat->mMIME = mime.string();
+ }
+
+ if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_AUDIO_VORBIS)) {
+ // Only do this for vorbis audio, none of the other audio
+ // formats even support this ringtone specific hack and
+ // retrieving the metadata on some extractors may turn out
+ // to be very expensive.
+ sp<MetaData> fileMeta = extractor->getMetaData();
+ int32_t loop;
+ if (fileMeta != NULL
+ && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
+ modifyFlags(AUTO_LOOPING, SET);
+ }
+ }
+ } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
+ addTextSource(extractor->getTrack(i));
+ }
+ }
+
+ if (!haveAudio && !haveVideo) {
+ return UNKNOWN_ERROR;
+ }
+
+ mExtractorFlags = extractor->flags();
+
+ return OK;
+}
+
+void AwesomePlayer::reset() {
+ Mutex::Autolock autoLock(mLock);
+ reset_l();
+}
+
+void AwesomePlayer::reset_l() {
+ mDisplayWidth = 0;
+ mDisplayHeight = 0;
+
+ if (mDecryptHandle != NULL) {
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::STOP, 0);
+ mDecryptHandle = NULL;
+ mDrmManagerClient = NULL;
+ }
+
+ if (mFlags & PLAYING) {
+ uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
+ if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
+ params |= IMediaPlayerService::kBatteryDataTrackAudio;
+ }
+ if (mVideoSource != NULL) {
+ params |= IMediaPlayerService::kBatteryDataTrackVideo;
+ }
+ addBatteryData(params);
+ }
+
+ if (mFlags & PREPARING) {
+ modifyFlags(PREPARE_CANCELLED, SET);
+ if (mConnectingDataSource != NULL) {
+ ALOGI("interrupting the connection process");
+ mConnectingDataSource->disconnect();
+ }
+
+ if (mFlags & PREPARING_CONNECTED) {
+ // We are basically done preparing, we're just buffering
+ // enough data to start playback, we can safely interrupt that.
+ finishAsyncPrepare_l();
+ }
+ }
+
+ while (mFlags & PREPARING) {
+ mPreparedCondition.wait(mLock);
+ }
+
+ cancelPlayerEvents();
+
+ mWVMExtractor.clear();
+ mCachedSource.clear();
+ mAudioTrack.clear();
+ mVideoTrack.clear();
+
+ // Shutdown audio first, so that the respone to the reset request
+ // appears to happen instantaneously as far as the user is concerned
+ // If we did this later, audio would continue playing while we
+ // shutdown the video-related resources and the player appear to
+ // not be as responsive to a reset request.
+ if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
+ && mAudioSource != NULL) {
+ // If we had an audio player, it would have effectively
+ // taken possession of the audio source and stopped it when
+ // _it_ is stopped. Otherwise this is still our responsibility.
+ mAudioSource->stop();
+ }
+ mAudioSource.clear();
+
+ mTimeSource = NULL;
+
+ delete mAudioPlayer;
+ mAudioPlayer = NULL;
+
+ if (mTextDriver != NULL) {
+ delete mTextDriver;
+ mTextDriver = NULL;
+ }
+
+ mVideoRenderer.clear();
+
+ if (mVideoSource != NULL) {
+ shutdownVideoDecoder_l();
+ }
+
+ mDurationUs = -1;
+ modifyFlags(0, ASSIGN);
+ mExtractorFlags = 0;
+ mTimeSourceDeltaUs = 0;
+ mVideoTimeUs = 0;
+
+ mSeeking = NO_SEEK;
+ mSeekNotificationSent = true;
+ mSeekTimeUs = 0;
+
+ mUri.setTo("");
+ mUriHeaders.clear();
+
+ mFileSource.clear();
+
+ mBitrate = -1;
+ mLastVideoTimeUs = -1;
+
+ {
+ Mutex::Autolock autoLock(mStatsLock);
+ mStats.mFd = -1;
+ mStats.mURI = String8();
+ mStats.mBitrate = -1;
+ mStats.mAudioTrackIndex = -1;
+ mStats.mVideoTrackIndex = -1;
+ mStats.mNumVideoFramesDecoded = 0;
+ mStats.mNumVideoFramesDropped = 0;
+ mStats.mVideoWidth = -1;
+ mStats.mVideoHeight = -1;
+ mStats.mFlags = 0;
+ mStats.mTracks.clear();
+ }
+
+ mWatchForAudioSeekComplete = false;
+ mWatchForAudioEOS = false;
+}
+
+void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
+ if (mListener != NULL) {
+ sp<MediaPlayerBase> listener = mListener.promote();
+
+ if (listener != NULL) {
+ listener->sendEvent(msg, ext1, ext2);
+ }
+ }
+}
+
+bool AwesomePlayer::getBitrate(int64_t *bitrate) {
+ off64_t size;
+ if (mDurationUs >= 0 && mCachedSource != NULL
+ && mCachedSource->getSize(&size) == OK) {
+ *bitrate = size * 8000000ll / mDurationUs; // in bits/sec
+ return true;
+ }
+
+ if (mBitrate >= 0) {
+ *bitrate = mBitrate;
+ return true;
+ }
+
+ *bitrate = 0;
+
+ return false;
+}
+
+// Returns true iff cached duration is available/applicable.
+bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
+ int64_t bitrate;
+
+ if (mCachedSource != NULL && getBitrate(&bitrate)) {
+ status_t finalStatus;
+ size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
+ *durationUs = cachedDataRemaining * 8000000ll / bitrate;
+ *eos = (finalStatus != OK);
+ return true;
+ } else if (mWVMExtractor != NULL) {
+ status_t finalStatus;
+ *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus);
+ *eos = (finalStatus != OK);
+ return true;
+ }
+
+ return false;
+}
+
+void AwesomePlayer::ensureCacheIsFetching_l() {
+ if (mCachedSource != NULL) {
+ mCachedSource->resumeFetchingIfNecessary();
+ }
+}
+
+void AwesomePlayer::onVideoLagUpdate() {
+ Mutex::Autolock autoLock(mLock);
+ if (!mVideoLagEventPending) {
+ return;
+ }
+ mVideoLagEventPending = false;
+
+ int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
+ int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
+
+ if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
+ ALOGV("video late by %lld ms.", videoLateByUs / 1000ll);
+
+ notifyListener_l(
+ MEDIA_INFO,
+ MEDIA_INFO_VIDEO_TRACK_LAGGING,
+ videoLateByUs / 1000ll);
+ }
+
+ postVideoLagEvent_l();
+}
+
+void AwesomePlayer::onBufferingUpdate() {
+ Mutex::Autolock autoLock(mLock);
+ if (!mBufferingEventPending) {
+ return;
+ }
+ mBufferingEventPending = false;
+
+ if (mCachedSource != NULL) {
+ status_t finalStatus;
+ size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
+ bool eos = (finalStatus != OK);
+
+ if (eos) {
+ if (finalStatus == ERROR_END_OF_STREAM) {
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
+ }
+ if (mFlags & PREPARING) {
+ ALOGV("cache has reached EOS, prepare is done.");
+ finishAsyncPrepare_l();
+ }
+ } else {
+ int64_t bitrate;
+ if (getBitrate(&bitrate)) {
+ size_t cachedSize = mCachedSource->cachedSize();
+ int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
+
+ int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
+ if (percentage > 100) {
+ percentage = 100;
+ }
+
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
+ } else {
+ // We don't know the bitrate of the stream, use absolute size
+ // limits to maintain the cache.
+
+ if ((mFlags & PLAYING) && !eos
+ && (cachedDataRemaining < kLowWaterMarkBytes)) {
+ ALOGI("cache is running low (< %d) , pausing.",
+ kLowWaterMarkBytes);
+ modifyFlags(CACHE_UNDERRUN, SET);
+ pause_l();
+ ensureCacheIsFetching_l();
+ sendCacheStats();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
+ } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
+ if (mFlags & CACHE_UNDERRUN) {
+ ALOGI("cache has filled up (> %d), resuming.",
+ kHighWaterMarkBytes);
+ modifyFlags(CACHE_UNDERRUN, CLEAR);
+ play_l();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
+ } else if (mFlags & PREPARING) {
+ ALOGV("cache has filled up (> %d), prepare is done",
+ kHighWaterMarkBytes);
+ finishAsyncPrepare_l();
+ }
+ }
+ }
+ }
+ } else if (mWVMExtractor != NULL) {
+ status_t finalStatus;
+
+ int64_t cachedDurationUs
+ = mWVMExtractor->getCachedDurationUs(&finalStatus);
+
+ bool eos = (finalStatus != OK);
+
+ if (eos) {
+ if (finalStatus == ERROR_END_OF_STREAM) {
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
+ }
+ if (mFlags & PREPARING) {
+ ALOGV("cache has reached EOS, prepare is done.");
+ finishAsyncPrepare_l();
+ }
+ } else {
+ int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
+ if (percentage > 100) {
+ percentage = 100;
+ }
+
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
+ }
+ }
+
+ int64_t cachedDurationUs;
+ bool eos;
+ if (getCachedDuration_l(&cachedDurationUs, &eos)) {
+ ALOGV("cachedDurationUs = %.2f secs, eos=%d",
+ cachedDurationUs / 1E6, eos);
+
+ if ((mFlags & PLAYING) && !eos
+ && (cachedDurationUs < kLowWaterMarkUs)) {
+ ALOGI("cache is running low (%.2f secs) , pausing.",
+ cachedDurationUs / 1E6);
+ modifyFlags(CACHE_UNDERRUN, SET);
+ pause_l();
+ ensureCacheIsFetching_l();
+ sendCacheStats();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
+ } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
+ if (mFlags & CACHE_UNDERRUN) {
+ ALOGI("cache has filled up (%.2f secs), resuming.",
+ cachedDurationUs / 1E6);
+ modifyFlags(CACHE_UNDERRUN, CLEAR);
+ play_l();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
+ } else if (mFlags & PREPARING) {
+ ALOGV("cache has filled up (%.2f secs), prepare is done",
+ cachedDurationUs / 1E6);
+ finishAsyncPrepare_l();
+ }
+ }
+ }
+
+ postBufferingEvent_l();
+}
+
+void AwesomePlayer::sendCacheStats() {
+ sp<MediaPlayerBase> listener = mListener.promote();
+ if (listener != NULL && mCachedSource != NULL) {
+ int32_t kbps = 0;
+ status_t err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
+ if (err == OK) {
+ listener->sendEvent(
+ MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
+ }
+ }
+}
+
+void AwesomePlayer::onStreamDone() {
+ // Posted whenever any stream finishes playing.
+
+ Mutex::Autolock autoLock(mLock);
+ if (!mStreamDoneEventPending) {
+ return;
+ }
+ mStreamDoneEventPending = false;
+
+ if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
+ ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
+
+ notifyListener_l(
+ MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
+
+ pause_l(true /* at eos */);
+
+ modifyFlags(AT_EOS, SET);
+ return;
+ }
+
+ const bool allDone =
+ (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
+ && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
+
+ if (!allDone) {
+ return;
+ }
+
+ if ((mFlags & LOOPING)
+ || ((mFlags & AUTO_LOOPING)
+ && (mAudioSink == NULL || mAudioSink->realtime()))) {
+ // Don't AUTO_LOOP if we're being recorded, since that cannot be
+ // turned off and recording would go on indefinitely.
+
+ seekTo_l(0);
+
+ if (mVideoSource != NULL) {
+ postVideoEvent_l();
+ }
+ } else {
+ ALOGV("MEDIA_PLAYBACK_COMPLETE");
+ notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
+
+ pause_l(true /* at eos */);
+
+ modifyFlags(AT_EOS, SET);
+ }
+}
+
+status_t AwesomePlayer::play() {
+ Mutex::Autolock autoLock(mLock);
+
+ modifyFlags(CACHE_UNDERRUN, CLEAR);
+
+ return play_l();
+}
+
+status_t AwesomePlayer::play_l() {
+ modifyFlags(SEEK_PREVIEW, CLEAR);
+
+ if (mFlags & PLAYING) {
+ return OK;
+ }
+
+ if (!(mFlags & PREPARED)) {
+ status_t err = prepare_l();
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ modifyFlags(PLAYING, SET);
+ modifyFlags(FIRST_FRAME, SET);
+
+ if (mDecryptHandle != NULL) {
+ int64_t position;
+ getPosition(&position);
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::START, position / 1000);
+ }
+
+ if (mAudioSource != NULL) {
+ if (mAudioPlayer == NULL) {
+ if (mAudioSink != NULL) {
+ mAudioPlayer = new AudioPlayer(mAudioSink, this);
+ mAudioPlayer->setSource(mAudioSource);
+
+ mTimeSource = mAudioPlayer;
+
+ // If there was a seek request before we ever started,
+ // honor the request now.
+ // Make sure to do this before starting the audio player
+ // to avoid a race condition.
+ seekAudioIfNecessary_l();
+ }
+ }
+
+ CHECK(!(mFlags & AUDIO_RUNNING));
+
+ if (mVideoSource == NULL) {
+ // We don't want to post an error notification at this point,
+ // the error returned from MediaPlayer::start() will suffice.
+
+ status_t err = startAudioPlayer_l(
+ false /* sendErrorNotification */);
+
+ if (err != OK) {
+ delete mAudioPlayer;
+ mAudioPlayer = NULL;
+
+ modifyFlags((PLAYING | FIRST_FRAME), CLEAR);
+
+ if (mDecryptHandle != NULL) {
+ mDrmManagerClient->setPlaybackStatus(
+ mDecryptHandle, Playback::STOP, 0);
+ }
+
+ return err;
+ }
+ }
+ }
+
+ if (mTimeSource == NULL && mAudioPlayer == NULL) {
+ mTimeSource = &mSystemTimeSource;
+ }
+
+ if (mVideoSource != NULL) {
+ // Kick off video playback
+ postVideoEvent_l();
+
+ if (mAudioSource != NULL && mVideoSource != NULL) {
+ postVideoLagEvent_l();
+ }
+ }
+
+ if (mFlags & AT_EOS) {
+ // Legacy behaviour, if a stream finishes playing and then
+ // is started again, we play from the start...
+ seekTo_l(0);
+ }
+
+ uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
+ | IMediaPlayerService::kBatteryDataTrackDecoder;
+ if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
+ params |= IMediaPlayerService::kBatteryDataTrackAudio;
+ }
+ if (mVideoSource != NULL) {
+ params |= IMediaPlayerService::kBatteryDataTrackVideo;
+ }
+ addBatteryData(params);
+
+ return OK;
+}
+
+status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {
+ CHECK(!(mFlags & AUDIO_RUNNING));
+
+ if (mAudioSource == NULL || mAudioPlayer == NULL) {
+ return OK;
+ }
+
+ if (!(mFlags & AUDIOPLAYER_STARTED)) {
+ modifyFlags(AUDIOPLAYER_STARTED, SET);
+
+ bool wasSeeking = mAudioPlayer->isSeeking();
+
+ // We've already started the MediaSource in order to enable
+ // the prefetcher to read its data.
+ status_t err = mAudioPlayer->start(
+ true /* sourceAlreadyStarted */);
+
+ if (err != OK) {
+ if (sendErrorNotification) {
+ notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+ }
+
+ return err;
+ }
+
+ if (wasSeeking) {
+ CHECK(!mAudioPlayer->isSeeking());
+
+ // We will have finished the seek while starting the audio player.
+ postAudioSeekComplete();
+ }
+ } else {
+ mAudioPlayer->resume();
+ }
+
+ modifyFlags(AUDIO_RUNNING, SET);
+
+ mWatchForAudioEOS = true;
+
+ return OK;
+}
+
+void AwesomePlayer::notifyVideoSize_l() {
+ sp<MetaData> meta = mVideoSource->getFormat();
+
+ int32_t cropLeft, cropTop, cropRight, cropBottom;
+ if (!meta->findRect(
+ kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
+ int32_t width, height;
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+
+ cropLeft = cropTop = 0;
+ cropRight = width - 1;
+ cropBottom = height - 1;
+
+ ALOGV("got dimensions only %d x %d", width, height);
+ } else {
+ ALOGV("got crop rect %d, %d, %d, %d",
+ cropLeft, cropTop, cropRight, cropBottom);
+ }
+
+ int32_t displayWidth;
+ if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
+ ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
+ mDisplayWidth = displayWidth;
+ }
+ int32_t displayHeight;
+ if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
+ ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
+ mDisplayHeight = displayHeight;
+ }
+
+ int32_t usableWidth = cropRight - cropLeft + 1;
+ int32_t usableHeight = cropBottom - cropTop + 1;
+ if (mDisplayWidth != 0) {
+ usableWidth = mDisplayWidth;
+ }
+ if (mDisplayHeight != 0) {
+ usableHeight = mDisplayHeight;
+ }
+
+ {
+ Mutex::Autolock autoLock(mStatsLock);
+ mStats.mVideoWidth = usableWidth;
+ mStats.mVideoHeight = usableHeight;
+ }
+
+ int32_t rotationDegrees;
+ if (!mVideoTrack->getFormat()->findInt32(
+ kKeyRotation, &rotationDegrees)) {
+ rotationDegrees = 0;
+ }
+
+ if (rotationDegrees == 90 || rotationDegrees == 270) {
+ notifyListener_l(
+ MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
+ } else {
+ notifyListener_l(
+ MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
+ }
+}
+
+void AwesomePlayer::initRenderer_l() {
+ if (mNativeWindow == NULL) {
+ return;
+ }
+
+ sp<MetaData> meta = mVideoSource->getFormat();
+
+ int32_t format;
+ const char *component;
+ int32_t decodedWidth, decodedHeight;
+ CHECK(meta->findInt32(kKeyColorFormat, &format));
+ CHECK(meta->findCString(kKeyDecoderComponent, &component));
+ CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
+ CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
+
+ int32_t rotationDegrees;
+ if (!mVideoTrack->getFormat()->findInt32(
+ kKeyRotation, &rotationDegrees)) {
+ rotationDegrees = 0;
+ }
+
+ mVideoRenderer.clear();
+
+ // Must ensure that mVideoRenderer's destructor is actually executed
+ // before creating a new one.
+ IPCThreadState::self()->flushCommands();
+
+ if (USE_SURFACE_ALLOC
+ && !strncmp(component, "OMX.", 4)
+ && strncmp(component, "OMX.google.", 11)
+ && strcmp(component, "OMX.Nvidia.mpeg2v.decode")) {
+ // Hardware decoders avoid the CPU color conversion by decoding
+ // directly to ANativeBuffers, so we must use a renderer that
+ // just pushes those buffers to the ANativeWindow.
+ mVideoRenderer =
+ new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
+ } else {
+ // Other decoders are instantiated locally and as a consequence
+ // allocate their buffers in local address space. This renderer
+ // then performs a color conversion and copy to get the data
+ // into the ANativeBuffer.
+ mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
+ }
+}
+
+status_t AwesomePlayer::pause() {
+ Mutex::Autolock autoLock(mLock);
+
+ modifyFlags(CACHE_UNDERRUN, CLEAR);
+
+ return pause_l();
+}
+
+status_t AwesomePlayer::pause_l(bool at_eos) {
+ if (!(mFlags & PLAYING)) {
+ return OK;
+ }
+
+ cancelPlayerEvents(true /* keepNotifications */);
+
+ if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
+ if (at_eos) {
+ // If we played the audio stream to completion we
+ // want to make sure that all samples remaining in the audio
+ // track's queue are played out.
+ mAudioPlayer->pause(true /* playPendingSamples */);
+ } else {
+ mAudioPlayer->pause();
+ }
+
+ modifyFlags(AUDIO_RUNNING, CLEAR);
+ }
+
+ if (mFlags & TEXTPLAYER_INITIALIZED) {
+ mTextDriver->pause();
+ modifyFlags(TEXT_RUNNING, CLEAR);
+ }
+
+ modifyFlags(PLAYING, CLEAR);
+
+ if (mDecryptHandle != NULL) {
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::PAUSE, 0);
+ }
+
+ uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
+ if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
+ params |= IMediaPlayerService::kBatteryDataTrackAudio;
+ }
+ if (mVideoSource != NULL) {
+ params |= IMediaPlayerService::kBatteryDataTrackVideo;
+ }
+
+ addBatteryData(params);
+
+ return OK;
+}
+
+bool AwesomePlayer::isPlaying() const {
+ return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
+}
+
+status_t AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
+ Mutex::Autolock autoLock(mLock);
+
+ status_t err;
+ if (surfaceTexture != NULL) {
+ err = setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
+ } else {
+ err = setNativeWindow_l(NULL);
+ }
+
+ return err;
+}
+
+void AwesomePlayer::shutdownVideoDecoder_l() {
+ if (mVideoBuffer) {
+ mVideoBuffer->release();
+ mVideoBuffer = NULL;
+ }
+
+ mVideoSource->stop();
+
+ // The following hack is necessary to ensure that the OMX
+ // component is completely released by the time we may try
+ // to instantiate it again.
+ wp<MediaSource> tmp = mVideoSource;
+ mVideoSource.clear();
+ while (tmp.promote() != NULL) {
+ usleep(1000);
+ }
+ IPCThreadState::self()->flushCommands();
+ ALOGV("video decoder shutdown completed");
+}
+
+status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
+ mNativeWindow = native;
+
+ if (mVideoSource == NULL) {
+ return OK;
+ }
+
+ ALOGV("attempting to reconfigure to use new surface");
+
+ bool wasPlaying = (mFlags & PLAYING) != 0;
+
+ pause_l();
+ mVideoRenderer.clear();
+
+ shutdownVideoDecoder_l();
+
+ status_t err = initVideoDecoder();
+
+ if (err != OK) {
+ ALOGE("failed to reinstantiate video decoder after surface change.");
+ return err;
+ }
+
+ if (mLastVideoTimeUs >= 0) {
+ mSeeking = SEEK;
+ mSeekTimeUs = mLastVideoTimeUs;
+ modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
+ }
+
+ if (wasPlaying) {
+ play_l();
+ }
+
+ return OK;
+}
+
+void AwesomePlayer::setAudioSink(
+ const sp<MediaPlayerBase::AudioSink> &audioSink) {
+ Mutex::Autolock autoLock(mLock);
+
+ mAudioSink = audioSink;
+}
+
+status_t AwesomePlayer::setLooping(bool shouldLoop) {
+ Mutex::Autolock autoLock(mLock);
+
+ modifyFlags(LOOPING, CLEAR);
+
+ if (shouldLoop) {
+ modifyFlags(LOOPING, SET);
+ }
+
+ return OK;
+}
+
+status_t AwesomePlayer::getDuration(int64_t *durationUs) {
+ Mutex::Autolock autoLock(mMiscStateLock);
+
+ if (mDurationUs < 0) {
+ return UNKNOWN_ERROR;
+ }
+
+ *durationUs = mDurationUs;
+
+ return OK;
+}
+
+status_t AwesomePlayer::getPosition(int64_t *positionUs) {
+ if (mSeeking != NO_SEEK) {
+ *positionUs = mSeekTimeUs;
+ } else if (mVideoSource != NULL
+ && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
+ Mutex::Autolock autoLock(mMiscStateLock);
+ *positionUs = mVideoTimeUs;
+ } else if (mAudioPlayer != NULL) {
+ *positionUs = mAudioPlayer->getMediaTimeUs();
+ } else {
+ *positionUs = 0;
+ }
+
+ return OK;
+}
+
+status_t AwesomePlayer::seekTo(int64_t timeUs) {
+ if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
+ Mutex::Autolock autoLock(mLock);
+ return seekTo_l(timeUs);
+ }
+
+ return OK;
+}
+
+status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
+ if (mFlags & CACHE_UNDERRUN) {
+ modifyFlags(CACHE_UNDERRUN, CLEAR);
+ play_l();
+ }
+
+ if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
+ // Video playback completed before, there's no pending
+ // video event right now. In order for this new seek
+ // to be honored, we need to post one.
+
+ postVideoEvent_l();
+ }
+
+ mSeeking = SEEK;
+ mSeekNotificationSent = false;
+ mSeekTimeUs = timeUs;
+ modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
+
+ seekAudioIfNecessary_l();
+
+ if (mFlags & TEXTPLAYER_INITIALIZED) {
+ mTextDriver->seekToAsync(mSeekTimeUs);
+ }
+
+ if (!(mFlags & PLAYING)) {
+ ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
+ " immediately.");
+
+ notifyListener_l(MEDIA_SEEK_COMPLETE);
+ mSeekNotificationSent = true;
+
+ if ((mFlags & PREPARED) && mVideoSource != NULL) {
+ modifyFlags(SEEK_PREVIEW, SET);
+ postVideoEvent_l();
+ }
+ }
+
+ return OK;
+}
+
+void AwesomePlayer::seekAudioIfNecessary_l() {
+ if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
+ mAudioPlayer->seekTo(mSeekTimeUs);
+
+ mWatchForAudioSeekComplete = true;
+ mWatchForAudioEOS = true;
+
+ if (mDecryptHandle != NULL) {
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::PAUSE, 0);
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::START, mSeekTimeUs / 1000);
+ }
+ }
+}
+
+void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
+ CHECK(source != NULL);
+
+ mAudioTrack = source;
+}
+
+void AwesomePlayer::addTextSource(const sp<MediaSource>& source) {
+ Mutex::Autolock autoLock(mTimedTextLock);
+ CHECK(source != NULL);
+
+ if (mTextDriver == NULL) {
+ mTextDriver = new TimedTextDriver(mListener);
+ }
+
+ mTextDriver->addInBandTextSource(source);
+}
+
+status_t AwesomePlayer::initAudioDecoder() {
+ sp<MetaData> meta = mAudioTrack->getFormat();
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
+ mAudioSource = mAudioTrack;
+ } else {
+ mAudioSource = OMXCodec::Create(
+ mClient.interface(), mAudioTrack->getFormat(),
+ false, // createEncoder
+ mAudioTrack);
+ }
+
+ if (mAudioSource != NULL) {
+ int64_t durationUs;
+ if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
+ Mutex::Autolock autoLock(mMiscStateLock);
+ if (mDurationUs < 0 || durationUs > mDurationUs) {
+ mDurationUs = durationUs;
+ }
+ }
+
+ status_t err = mAudioSource->start();
+
+ if (err != OK) {
+ mAudioSource.clear();
+ return err;
+ }
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
+ // For legacy reasons we're simply going to ignore the absence
+ // of an audio decoder for QCELP instead of aborting playback
+ // altogether.
+ return OK;
+ }
+
+ if (mAudioSource != NULL) {
+ Mutex::Autolock autoLock(mStatsLock);
+ TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
+
+ const char *component;
+ if (!mAudioSource->getFormat()
+ ->findCString(kKeyDecoderComponent, &component)) {
+ component = "none";
+ }
+
+ stat->mDecoderName = component;
+ }
+
+ return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
+}
+
+void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
+ CHECK(source != NULL);
+
+ mVideoTrack = source;
+}
+
+status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
+
+ // Either the application or the DRM system can independently say
+ // that there must be a hardware-protected path to an external video sink.
+ // For now we always require a hardware-protected path to external video sink
+ // if content is DRMed, but eventually this could be optional per DRM agent.
+ // When the application wants protection, then
+ // (USE_SURFACE_ALLOC && (mSurface != 0) &&
+ // (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
+ // will be true, but that part is already handled by SurfaceFlinger.
+
+#ifdef DEBUG_HDCP
+ // For debugging, we allow a system property to control the protected usage.
+ // In case of uninitialized or unexpected property, we default to "DRM only".
+ bool setProtectionBit = false;
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("persist.sys.hdcp_checking", value, NULL)) {
+ if (!strcmp(value, "never")) {
+ // nop
+ } else if (!strcmp(value, "always")) {
+ setProtectionBit = true;
+ } else if (!strcmp(value, "drm-only")) {
+ if (mDecryptHandle != NULL) {
+ setProtectionBit = true;
+ }
+ // property value is empty, or unexpected value
+ } else {
+ if (mDecryptHandle != NULL) {
+ setProtectionBit = true;
+ }
+ }
+ // can' read property value
+ } else {
+ if (mDecryptHandle != NULL) {
+ setProtectionBit = true;
+ }
+ }
+ // note that usage bit is already cleared, so no need to clear it in the "else" case
+ if (setProtectionBit) {
+ flags |= OMXCodec::kEnableGrallocUsageProtected;
+ }
+#else
+ if (mDecryptHandle != NULL) {
+ flags |= OMXCodec::kEnableGrallocUsageProtected;
+ }
+#endif
+ ALOGV("initVideoDecoder flags=0x%x", flags);
+ mVideoSource = OMXCodec::Create(
+ mClient.interface(), mVideoTrack->getFormat(),
+ false, // createEncoder
+ mVideoTrack,
+ NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
+
+ if (mVideoSource != NULL) {
+ int64_t durationUs;
+ if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
+ Mutex::Autolock autoLock(mMiscStateLock);
+ if (mDurationUs < 0 || durationUs > mDurationUs) {
+ mDurationUs = durationUs;
+ }
+ }
+
+ status_t err = mVideoSource->start();
+
+ if (err != OK) {
+ mVideoSource.clear();
+ return err;
+ }
+ }
+
+ if (mVideoSource != NULL) {
+ const char *componentName;
+ CHECK(mVideoSource->getFormat()
+ ->findCString(kKeyDecoderComponent, &componentName));
+
+ {
+ Mutex::Autolock autoLock(mStatsLock);
+ TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
+
+ stat->mDecoderName = componentName;
+ }
+
+ static const char *kPrefix = "OMX.Nvidia.";
+ static const char *kSuffix = ".decode";
+ static const size_t kSuffixLength = strlen(kSuffix);
+
+ size_t componentNameLength = strlen(componentName);
+
+ if (!strncmp(componentName, kPrefix, strlen(kPrefix))
+ && componentNameLength >= kSuffixLength
+ && !strcmp(&componentName[
+ componentNameLength - kSuffixLength], kSuffix)) {
+ modifyFlags(SLOW_DECODER_HACK, SET);
+ }
+ }
+
+ return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
+}
+
+void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
+ if (mSeeking == SEEK_VIDEO_ONLY) {
+ mSeeking = NO_SEEK;
+ return;
+ }
+
+ if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
+ return;
+ }
+
+ if (mAudioPlayer != NULL) {
+ ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
+
+ // If we don't have a video time, seek audio to the originally
+ // requested seek time instead.
+
+ mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
+ mWatchForAudioSeekComplete = true;
+ mWatchForAudioEOS = true;
+ } else if (!mSeekNotificationSent) {
+ // If we're playing video only, report seek complete now,
+ // otherwise audio player will notify us later.
+ notifyListener_l(MEDIA_SEEK_COMPLETE);
+ mSeekNotificationSent = true;
+ }
+
+ modifyFlags(FIRST_FRAME, SET);
+ mSeeking = NO_SEEK;
+
+ if (mDecryptHandle != NULL) {
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::PAUSE, 0);
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::START, videoTimeUs / 1000);
+ }
+}
+
+void AwesomePlayer::onVideoEvent() {
+ Mutex::Autolock autoLock(mLock);
+ if (!mVideoEventPending) {
+ // The event has been cancelled in reset_l() but had already
+ // been scheduled for execution at that time.
+ return;
+ }
+ mVideoEventPending = false;
+
+ if (mSeeking != NO_SEEK) {
+ if (mVideoBuffer) {
+ mVideoBuffer->release();
+ mVideoBuffer = NULL;
+ }
+
+ if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
+ && !(mFlags & SEEK_PREVIEW)) {
+ // 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 && (mFlags & AUDIO_RUNNING)) {
+ mAudioPlayer->pause();
+
+ modifyFlags(AUDIO_RUNNING, CLEAR);
+ }
+ mAudioSource->pause();
+ }
+ }
+
+ if (!mVideoBuffer) {
+ MediaSource::ReadOptions options;
+ if (mSeeking != NO_SEEK) {
+ ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
+
+ options.setSeekTo(
+ mSeekTimeUs,
+ mSeeking == SEEK_VIDEO_ONLY
+ ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
+ : MediaSource::ReadOptions::SEEK_CLOSEST);
+ }
+ for (;;) {
+ status_t err = mVideoSource->read(&mVideoBuffer, &options);
+ options.clearSeekTo();
+
+ if (err != OK) {
+ CHECK(mVideoBuffer == NULL);
+
+ if (err == INFO_FORMAT_CHANGED) {
+ ALOGV("VideoSource signalled format change.");
+
+ notifyVideoSize_l();
+
+ if (mVideoRenderer != NULL) {
+ mVideoRendererIsPreview = false;
+ initRenderer_l();
+ }
+ continue;
+ }
+
+ // So video playback is complete, but we may still have
+ // a seek request pending that needs to be applied
+ // to the audio track.
+ if (mSeeking != NO_SEEK) {
+ ALOGV("video stream ended while seeking!");
+ }
+ finishSeekIfNecessary(-1);
+
+ if (mAudioPlayer != NULL
+ && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
+ startAudioPlayer_l();
+ }
+
+ modifyFlags(VIDEO_AT_EOS, SET);
+ postStreamDoneEvent_l(err);
+ return;
+ }
+
+ if (mVideoBuffer->range_length() == 0) {
+ // Some decoders, notably the PV AVC software decoder
+ // return spurious empty buffers that we just want to ignore.
+
+ mVideoBuffer->release();
+ mVideoBuffer = NULL;
+ continue;
+ }
+
+ break;
+ }
+
+ {
+ Mutex::Autolock autoLock(mStatsLock);
+ ++mStats.mNumVideoFramesDecoded;
+ }
+ }
+
+ int64_t timeUs;
+ CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+
+ mLastVideoTimeUs = timeUs;
+
+ if (mSeeking == SEEK_VIDEO_ONLY) {
+ if (mSeekTimeUs > timeUs) {
+ ALOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
+ mSeekTimeUs, timeUs);
+ }
+ }
+
+ {
+ Mutex::Autolock autoLock(mMiscStateLock);
+ mVideoTimeUs = timeUs;
+ }
+
+ SeekType wasSeeking = mSeeking;
+ finishSeekIfNecessary(timeUs);
+
+ if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
+ status_t err = startAudioPlayer_l();
+ if (err != OK) {
+ ALOGE("Starting the audio player failed w/ err %d", err);
+ return;
+ }
+ }
+
+ if ((mFlags & TEXTPLAYER_INITIALIZED) && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
+ mTextDriver->start();
+ modifyFlags(TEXT_RUNNING, SET);
+ }
+
+ TimeSource *ts =
+ ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
+ ? &mSystemTimeSource : mTimeSource;
+
+ if (mFlags & FIRST_FRAME) {
+ modifyFlags(FIRST_FRAME, CLEAR);
+ mSinceLastDropped = 0;
+ mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
+ }
+
+ int64_t realTimeUs, mediaTimeUs;
+ if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
+ && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
+ mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
+ }
+
+ if (wasSeeking == SEEK_VIDEO_ONLY) {
+ int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
+
+ int64_t latenessUs = nowUs - timeUs;
+
+ if (latenessUs > 0) {
+ ALOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
+ }
+ }
+
+ if (wasSeeking == NO_SEEK) {
+ // Let's display the first frame after seeking right away.
+
+ int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
+
+ int64_t latenessUs = nowUs - timeUs;
+
+ if (latenessUs > 500000ll
+ && mAudioPlayer != NULL
+ && mAudioPlayer->getMediaTimeMapping(
+ &realTimeUs, &mediaTimeUs)) {
+ ALOGI("we're much too late (%.2f secs), video skipping ahead",
+ latenessUs / 1E6);
+
+ mVideoBuffer->release();
+ mVideoBuffer = NULL;
+
+ mSeeking = SEEK_VIDEO_ONLY;
+ mSeekTimeUs = mediaTimeUs;
+
+ postVideoEvent_l();
+ return;
+ }
+
+ if (latenessUs > 40000) {
+ // We're more than 40ms late.
+ ALOGV("we're late by %lld us (%.2f secs)",
+ latenessUs, latenessUs / 1E6);
+
+ if (!(mFlags & SLOW_DECODER_HACK)
+ || mSinceLastDropped > FRAME_DROP_FREQ)
+ {
+ ALOGV("we're late by %lld us (%.2f secs) dropping "
+ "one after %d frames",
+ latenessUs, latenessUs / 1E6, mSinceLastDropped);
+
+ mSinceLastDropped = 0;
+ mVideoBuffer->release();
+ mVideoBuffer = NULL;
+
+ {
+ Mutex::Autolock autoLock(mStatsLock);
+ ++mStats.mNumVideoFramesDropped;
+ }
+
+ postVideoEvent_l();
+ return;
+ }
+ }
+
+ if (latenessUs < -10000) {
+ // We're more than 10ms early.
+
+ postVideoEvent_l(10000);
+ return;
+ }
+ }
+
+ if ((mNativeWindow != NULL)
+ && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
+ mVideoRendererIsPreview = false;
+
+ initRenderer_l();
+ }
+
+ if (mVideoRenderer != NULL) {
+ mSinceLastDropped++;
+ mVideoRenderer->render(mVideoBuffer);
+ }
+
+ mVideoBuffer->release();
+ mVideoBuffer = NULL;
+
+ if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
+ modifyFlags(SEEK_PREVIEW, CLEAR);
+ return;
+ }
+
+ postVideoEvent_l();
+}
+
+void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
+ if (mVideoEventPending) {
+ return;
+ }
+
+ mVideoEventPending = true;
+ mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
+}
+
+void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
+ if (mStreamDoneEventPending) {
+ return;
+ }
+ mStreamDoneEventPending = true;
+
+ mStreamDoneStatus = status;
+ mQueue.postEvent(mStreamDoneEvent);
+}
+
+void AwesomePlayer::postBufferingEvent_l() {
+ if (mBufferingEventPending) {
+ return;
+ }
+ mBufferingEventPending = true;
+ mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
+}
+
+void AwesomePlayer::postVideoLagEvent_l() {
+ if (mVideoLagEventPending) {
+ return;
+ }
+ mVideoLagEventPending = true;
+ mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
+}
+
+void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) {
+ Mutex::Autolock autoLock(mAudioLock);
+ if (mAudioStatusEventPending) {
+ return;
+ }
+ mAudioStatusEventPending = true;
+ // Do not honor delay when looping in order to limit audio gap
+ if (mFlags & (LOOPING | AUTO_LOOPING)) {
+ delayUs = 0;
+ }
+ mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
+}
+
+void AwesomePlayer::onCheckAudioStatus() {
+ {
+ Mutex::Autolock autoLock(mAudioLock);
+ if (!mAudioStatusEventPending) {
+ // Event was dispatched and while we were blocking on the mutex,
+ // has already been cancelled.
+ return;
+ }
+
+ mAudioStatusEventPending = false;
+ }
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
+ mWatchForAudioSeekComplete = false;
+
+ if (!mSeekNotificationSent) {
+ notifyListener_l(MEDIA_SEEK_COMPLETE);
+ mSeekNotificationSent = true;
+ }
+
+ mSeeking = NO_SEEK;
+ }
+
+ status_t finalStatus;
+ if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
+ mWatchForAudioEOS = false;
+ modifyFlags(AUDIO_AT_EOS, SET);
+ modifyFlags(FIRST_FRAME, SET);
+ postStreamDoneEvent_l(finalStatus);
+ }
+}
+
+status_t AwesomePlayer::prepare() {
+ Mutex::Autolock autoLock(mLock);
+ return prepare_l();
+}
+
+status_t AwesomePlayer::prepare_l() {
+ if (mFlags & PREPARED) {
+ return OK;
+ }
+
+ if (mFlags & PREPARING) {
+ return UNKNOWN_ERROR;
+ }
+
+ mIsAsyncPrepare = false;
+ status_t err = prepareAsync_l();
+
+ if (err != OK) {
+ return err;
+ }
+
+ while (mFlags & PREPARING) {
+ mPreparedCondition.wait(mLock);
+ }
+
+ return mPrepareResult;
+}
+
+status_t AwesomePlayer::prepareAsync() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mFlags & PREPARING) {
+ return UNKNOWN_ERROR; // async prepare already pending
+ }
+
+ mIsAsyncPrepare = true;
+ return prepareAsync_l();
+}
+
+status_t AwesomePlayer::prepareAsync_l() {
+ if (mFlags & PREPARING) {
+ return UNKNOWN_ERROR; // async prepare already pending
+ }
+
+ if (!mQueueStarted) {
+ mQueue.start();
+ mQueueStarted = true;
+ }
+
+ modifyFlags(PREPARING, SET);
+ mAsyncPrepareEvent = new AwesomeEvent(
+ this, &AwesomePlayer::onPrepareAsyncEvent);
+
+ mQueue.postEvent(mAsyncPrepareEvent);
+
+ return OK;
+}
+
+status_t AwesomePlayer::finishSetDataSource_l() {
+ sp<DataSource> dataSource;
+
+ bool isWidevineStreaming = false;
+ if (!strncasecmp("widevine://", mUri.string(), 11)) {
+ isWidevineStreaming = true;
+
+ String8 newURI = String8("http://");
+ newURI.append(mUri.string() + 11);
+
+ mUri = newURI;
+ }
+
+ AString sniffedMIME;
+
+ if (!strncasecmp("http://", mUri.string(), 7)
+ || !strncasecmp("https://", mUri.string(), 8)
+ || isWidevineStreaming) {
+ mConnectingDataSource = HTTPBase::Create(
+ (mFlags & INCOGNITO)
+ ? HTTPBase::kFlagIncognito
+ : 0);
+
+ if (mUIDValid) {
+ mConnectingDataSource->setUID(mUID);
+ }
+
+ String8 cacheConfig;
+ bool disconnectAtHighwatermark;
+ NuCachedSource2::RemoveCacheSpecificHeaders(
+ &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
+
+ mLock.unlock();
+ status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
+ mLock.lock();
+
+ if (err != OK) {
+ mConnectingDataSource.clear();
+
+ ALOGI("mConnectingDataSource->connect() returned %d", err);
+ return err;
+ }
+
+ if (!isWidevineStreaming) {
+ // The widevine extractor does its own caching.
+
+#if 0
+ mCachedSource = new NuCachedSource2(
+ new ThrottledSource(
+ mConnectingDataSource, 50 * 1024 /* bytes/sec */));
+#else
+ mCachedSource = new NuCachedSource2(
+ mConnectingDataSource,
+ cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
+ disconnectAtHighwatermark);
+#endif
+
+ dataSource = mCachedSource;
+ } else {
+ dataSource = mConnectingDataSource;
+ }
+
+ mConnectingDataSource.clear();
+
+ String8 contentType = dataSource->getMIMEType();
+
+ if (strncasecmp(contentType.string(), "audio/", 6)) {
+ // We're not doing this for streams that appear to be audio-only
+ // streams to ensure that even low bandwidth streams start
+ // playing back fairly instantly.
+
+ // We're going to prefill the cache before trying to instantiate
+ // the extractor below, as the latter is an operation that otherwise
+ // could block on the datasource for a significant amount of time.
+ // During that time we'd be unable to abort the preparation phase
+ // without this prefill.
+ if (mCachedSource != NULL) {
+ // We're going to prefill the cache before trying to instantiate
+ // the extractor below, as the latter is an operation that otherwise
+ // could block on the datasource for a significant amount of time.
+ // During that time we'd be unable to abort the preparation phase
+ // without this prefill.
+
+ mLock.unlock();
+
+ // Initially make sure we have at least 192 KB for the sniff
+ // to complete without blocking.
+ static const size_t kMinBytesForSniffing = 192 * 1024;
+
+ off64_t metaDataSize = -1ll;
+ for (;;) {
+ status_t finalStatus;
+ size_t cachedDataRemaining =
+ mCachedSource->approxDataRemaining(&finalStatus);
+
+ if (finalStatus != OK
+ || (metaDataSize >= 0
+ && cachedDataRemaining >= metaDataSize)
+ || (mFlags & PREPARE_CANCELLED)) {
+ break;
+ }
+
+ ALOGV("now cached %d bytes of data", cachedDataRemaining);
+
+ if (metaDataSize < 0
+ && cachedDataRemaining >= kMinBytesForSniffing) {
+ String8 tmp;
+ float confidence;
+ sp<AMessage> meta;
+ if (!dataSource->sniff(&tmp, &confidence, &meta)) {
+ mLock.lock();
+ return UNKNOWN_ERROR;
+ }
+
+ // We successfully identified the file's extractor to
+ // be, remember this mime type so we don't have to
+ // sniff it again when we call MediaExtractor::Create()
+ // below.
+ sniffedMIME = tmp.string();
+
+ if (meta == NULL
+ || !meta->findInt64(
+ "meta-data-size", &metaDataSize)) {
+ metaDataSize = kHighWaterMarkBytes;
+ }
+
+ CHECK_GE(metaDataSize, 0ll);
+ ALOGV("metaDataSize = %lld bytes", metaDataSize);
+ }
+
+ usleep(200000);
+ }
+
+ mLock.lock();
+ }
+
+ if (mFlags & PREPARE_CANCELLED) {
+ ALOGI("Prepare cancelled while waiting for initial cache fill.");
+ return UNKNOWN_ERROR;
+ }
+ }
+ } else {
+ dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
+ }
+
+ if (dataSource == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ sp<MediaExtractor> extractor;
+
+ if (isWidevineStreaming) {
+ String8 mimeType;
+ float confidence;
+ sp<AMessage> dummy;
+ bool success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
+
+ if (!success
+ || strcasecmp(
+ mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ mWVMExtractor = new WVMExtractor(dataSource);
+ mWVMExtractor->setAdaptiveStreamingMode(true);
+ if (mUIDValid)
+ mWVMExtractor->setUID(mUID);
+ extractor = mWVMExtractor;
+ } else {
+ extractor = MediaExtractor::Create(
+ dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
+
+ if (extractor == NULL) {
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ if (extractor->getDrmFlag()) {
+ checkDrmStatus(dataSource);
+ }
+
+ status_t err = setDataSource_l(extractor);
+
+ if (err != OK) {
+ mWVMExtractor.clear();
+
+ return err;
+ }
+
+ return OK;
+}
+
+void AwesomePlayer::abortPrepare(status_t err) {
+ CHECK(err != OK);
+
+ if (mIsAsyncPrepare) {
+ notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+ }
+
+ mPrepareResult = err;
+ modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
+ mAsyncPrepareEvent = NULL;
+ mPreparedCondition.broadcast();
+}
+
+// static
+bool AwesomePlayer::ContinuePreparation(void *cookie) {
+ AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
+
+ return (me->mFlags & PREPARE_CANCELLED) == 0;
+}
+
+void AwesomePlayer::onPrepareAsyncEvent() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mFlags & PREPARE_CANCELLED) {
+ ALOGI("prepare was cancelled before doing anything");
+ abortPrepare(UNKNOWN_ERROR);
+ return;
+ }
+
+ if (mUri.size() > 0) {
+ status_t err = finishSetDataSource_l();
+
+ if (err != OK) {
+ abortPrepare(err);
+ return;
+ }
+ }
+
+ if (mVideoTrack != NULL && mVideoSource == NULL) {
+ status_t err = initVideoDecoder();
+
+ if (err != OK) {
+ abortPrepare(err);
+ return;
+ }
+ }
+
+ if (mAudioTrack != NULL && mAudioSource == NULL) {
+ status_t err = initAudioDecoder();
+
+ if (err != OK) {
+ abortPrepare(err);
+ return;
+ }
+ }
+
+ modifyFlags(PREPARING_CONNECTED, SET);
+
+ if (isStreamingHTTP()) {
+ postBufferingEvent_l();
+ } else {
+ finishAsyncPrepare_l();
+ }
+}
+
+void AwesomePlayer::finishAsyncPrepare_l() {
+ if (mIsAsyncPrepare) {
+ if (mVideoSource == NULL) {
+ notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
+ } else {
+ notifyVideoSize_l();
+ }
+
+ notifyListener_l(MEDIA_PREPARED);
+ }
+
+ mPrepareResult = OK;
+ modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
+ modifyFlags(PREPARED, SET);
+ mAsyncPrepareEvent = NULL;
+ mPreparedCondition.broadcast();
+}
+
+uint32_t AwesomePlayer::flags() const {
+ return mExtractorFlags;
+}
+
+void AwesomePlayer::postAudioEOS(int64_t delayUs) {
+ postCheckAudioStatusEvent(delayUs);
+}
+
+void AwesomePlayer::postAudioSeekComplete() {
+ postCheckAudioStatusEvent(0);
+}
+
+status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
+ switch (key) {
+ case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
+ {
+ return setCacheStatCollectFreq(request);
+ }
+ case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE:
+ {
+ if (mAudioPlayer != NULL) {
+ return mAudioPlayer->setPlaybackRatePermille(request.readInt32());
+ } else {
+ return NO_INIT;
+ }
+ }
+ default:
+ {
+ return ERROR_UNSUPPORTED;
+ }
+ }
+}
+
+status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
+ if (mCachedSource != NULL) {
+ int32_t freqMs = request.readInt32();
+ ALOGD("Request to keep cache stats in the past %d ms",
+ freqMs);
+ return mCachedSource->setCacheStatCollectFreq(freqMs);
+ }
+ return ERROR_UNSUPPORTED;
+}
+
+status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
+ switch (key) {
+ case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
+ {
+ int32_t channelCount;
+ if (mAudioTrack == 0 ||
+ !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
+ channelCount = 0;
+ }
+ reply->writeInt32(channelCount);
+ }
+ return OK;
+ default:
+ {
+ return ERROR_UNSUPPORTED;
+ }
+ }
+}
+
+status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
+ if (NULL == reply) {
+ return android::BAD_VALUE;
+ }
+ int32_t methodId;
+ status_t ret = request.readInt32(&methodId);
+ if (ret != android::OK) {
+ return ret;
+ }
+ switch(methodId) {
+ case INVOKE_ID_GET_TRACK_INFO:
+ {
+ Mutex::Autolock autoLock(mTimedTextLock);
+ if (mTextDriver == NULL) {
+ return INVALID_OPERATION;
+ }
+ mTextDriver->getTrackInfo(reply);
+ return OK;
+ }
+ case INVOKE_ID_ADD_EXTERNAL_SOURCE:
+ {
+ Mutex::Autolock autoLock(mTimedTextLock);
+ if (mTextDriver == NULL) {
+ mTextDriver = new TimedTextDriver(mListener);
+ }
+ // String values written in Parcel are UTF-16 values.
+ String8 uri(request.readString16());
+ String8 mimeType(request.readString16());
+ return mTextDriver->addOutOfBandTextSource(uri, mimeType);
+ }
+ case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD:
+ {
+ Mutex::Autolock autoLock(mTimedTextLock);
+ if (mTextDriver == NULL) {
+ mTextDriver = new TimedTextDriver(mListener);
+ }
+ int fd = request.readFileDescriptor();
+ off64_t offset = request.readInt64();
+ size_t length = request.readInt64();
+ String8 mimeType(request.readString16());
+ return mTextDriver->addOutOfBandTextSource(
+ fd, offset, length, mimeType);
+ }
+ case INVOKE_ID_SELECT_TRACK:
+ {
+ Mutex::Autolock autoLock(mTimedTextLock);
+ if (mTextDriver == NULL) {
+ return INVALID_OPERATION;
+ }
+
+ status_t err = mTextDriver->selectTrack(
+ request.readInt32());
+ if (err == OK) {
+ modifyFlags(TEXTPLAYER_INITIALIZED, SET);
+ if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) {
+ mTextDriver->start();
+ modifyFlags(TEXT_RUNNING, SET);
+ }
+ }
+ return err;
+ }
+ case INVOKE_ID_UNSELECT_TRACK:
+ {
+ Mutex::Autolock autoLock(mTimedTextLock);
+ if (mTextDriver == NULL) {
+ return INVALID_OPERATION;
+ }
+ status_t err = mTextDriver->unselectTrack(
+ request.readInt32());
+ if (err == OK) {
+ modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR);
+ modifyFlags(TEXT_RUNNING, CLEAR);
+ }
+ return err;
+ }
+ default:
+ {
+ return ERROR_UNSUPPORTED;
+ }
+ }
+ // It will not reach here.
+ return OK;
+}
+
+bool AwesomePlayer::isStreamingHTTP() const {
+ return mCachedSource != NULL || mWVMExtractor != NULL;
+}
+
+status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const {
+ Mutex::Autolock autoLock(mStatsLock);
+
+ FILE *out = fdopen(dup(fd), "w");
+
+ fprintf(out, " AwesomePlayer\n");
+ if (mStats.mFd < 0) {
+ fprintf(out, " URI(%s)", mStats.mURI.string());
+ } else {
+ fprintf(out, " fd(%d)", mStats.mFd);
+ }
+
+ fprintf(out, ", flags(0x%08x)", mStats.mFlags);
+
+ if (mStats.mBitrate >= 0) {
+ fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate);
+ }
+
+ fprintf(out, "\n");
+
+ for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
+ const TrackStat &stat = mStats.mTracks.itemAt(i);
+
+ fprintf(out, " Track %d\n", i + 1);
+ fprintf(out, " MIME(%s)", stat.mMIME.string());
+
+ if (!stat.mDecoderName.isEmpty()) {
+ fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
+ }
+
+ fprintf(out, "\n");
+
+ if ((ssize_t)i == mStats.mVideoTrackIndex) {
+ fprintf(out,
+ " videoDimensions(%d x %d), "
+ "numVideoFramesDecoded(%lld), "
+ "numVideoFramesDropped(%lld)\n",
+ mStats.mVideoWidth,
+ mStats.mVideoHeight,
+ mStats.mNumVideoFramesDecoded,
+ mStats.mNumVideoFramesDropped);
+ }
+ }
+
+ fclose(out);
+ out = NULL;
+
+ return OK;
+}
+
+void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
+ switch (mode) {
+ case SET:
+ mFlags |= value;
+ break;
+ case CLEAR:
+ mFlags &= ~value;
+ break;
+ case ASSIGN:
+ mFlags = value;
+ break;
+ default:
+ TRESPASS();
+ }
+
+ {
+ Mutex::Autolock autoLock(mStatsLock);
+ mStats.mFlags = mFlags;
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
new file mode 100755
index 0000000..fd3f892
--- /dev/null
+++ b/media/libstagefright/CameraSource.cpp
@@ -0,0 +1,843 @@
+/*
+ * 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 "CameraSource"
+#include <utils/Log.h>
+
+#include <OMX_Component.h>
+#include <binder/IPCThreadState.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/CameraSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
+#include <gui/Surface.h>
+#include <utils/String8.h>
+#include <cutils/properties.h>
+
+namespace android {
+
+static const int64_t CAMERA_SOURCE_TIMEOUT_NS = 3000000000LL;
+
+struct CameraSourceListener : public CameraListener {
+ CameraSourceListener(const sp<CameraSource> &source);
+
+ virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
+ virtual void postData(int32_t msgType, const sp<IMemory> &dataPtr,
+ camera_frame_metadata_t *metadata);
+
+ virtual void postDataTimestamp(
+ nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
+
+protected:
+ virtual ~CameraSourceListener();
+
+private:
+ wp<CameraSource> mSource;
+
+ CameraSourceListener(const CameraSourceListener &);
+ CameraSourceListener &operator=(const CameraSourceListener &);
+};
+
+CameraSourceListener::CameraSourceListener(const sp<CameraSource> &source)
+ : mSource(source) {
+}
+
+CameraSourceListener::~CameraSourceListener() {
+}
+
+void CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
+ ALOGV("notify(%d, %d, %d)", msgType, ext1, ext2);
+}
+
+void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr,
+ camera_frame_metadata_t *metadata) {
+ ALOGV("postData(%d, ptr:%p, size:%d)",
+ msgType, dataPtr->pointer(), dataPtr->size());
+
+ sp<CameraSource> source = mSource.promote();
+ if (source.get() != NULL) {
+ source->dataCallback(msgType, dataPtr);
+ }
+}
+
+void CameraSourceListener::postDataTimestamp(
+ nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
+
+ sp<CameraSource> source = mSource.promote();
+ if (source.get() != NULL) {
+ source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
+ }
+}
+
+static int32_t getColorFormat(const char* colorFormat) {
+ if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) {
+ return OMX_COLOR_FormatYUV420Planar;
+ }
+
+ 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;
+ }
+
+ if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) {
+ return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
+ }
+
+ ALOGE("Uknown color format (%s), please add it to "
+ "CameraSource::getColorFormat", colorFormat);
+
+ CHECK(!"Unknown color format");
+}
+
+CameraSource *CameraSource::Create() {
+ Size size;
+ size.width = -1;
+ size.height = -1;
+
+ sp<ICamera> camera;
+ return new CameraSource(camera, NULL, 0, size, -1, NULL, false);
+}
+
+// static
+CameraSource *CameraSource::CreateFromCamera(
+ const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId,
+ Size videoSize,
+ int32_t frameRate,
+ const sp<Surface>& surface,
+ bool storeMetaDataInVideoBuffers) {
+
+ CameraSource *source = new CameraSource(camera, proxy, cameraId,
+ videoSize, frameRate, surface,
+ storeMetaDataInVideoBuffers);
+ return source;
+}
+
+CameraSource::CameraSource(
+ const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId,
+ Size videoSize,
+ int32_t frameRate,
+ const sp<Surface>& surface,
+ bool storeMetaDataInVideoBuffers)
+ : mCameraFlags(0),
+ mVideoFrameRate(-1),
+ mCamera(0),
+ mSurface(surface),
+ mNumFramesReceived(0),
+ mLastFrameTimestampUs(0),
+ mStarted(false),
+ mNumFramesEncoded(0),
+ mTimeBetweenFrameCaptureUs(0),
+ mFirstFrameTimeUs(0),
+ mNumFramesDropped(0),
+ mNumGlitches(0),
+ mGlitchDurationThresholdUs(200000),
+ mCollectStats(false) {
+ mVideoSize.width = -1;
+ mVideoSize.height = -1;
+
+ mInitCheck = init(camera, proxy, cameraId,
+ videoSize, frameRate,
+ storeMetaDataInVideoBuffers);
+ if (mInitCheck != OK) releaseCamera();
+}
+
+status_t CameraSource::initCheck() const {
+ return mInitCheck;
+}
+
+status_t CameraSource::isCameraAvailable(
+ const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId) {
+
+ if (camera == 0) {
+ mCamera = Camera::connect(cameraId, false, false);
+ if (mCamera == 0) return -EBUSY;
+ mCameraFlags &= ~FLAGS_HOT_CAMERA;
+ } else {
+ // We get the proxy from Camera, not ICamera. We need to get the proxy
+ // to the remote Camera owned by the application. Here mCamera is a
+ // local Camera object created by us. We cannot use the proxy from
+ // mCamera here.
+ mCamera = Camera::create(camera);
+ if (mCamera == 0) return -EBUSY;
+ mCameraRecordingProxy = proxy;
+ mCameraFlags |= FLAGS_HOT_CAMERA;
+ mDeathNotifier = new DeathNotifier();
+ // isBinderAlive needs linkToDeath to work.
+ mCameraRecordingProxy->asBinder()->linkToDeath(mDeathNotifier);
+ }
+
+ mCamera->lock();
+
+ return OK;
+}
+
+
+/*
+ * Check to see whether the requested video width and height is one
+ * of the supported sizes.
+ * @param width the video frame width in pixels
+ * @param height the video frame height in pixels
+ * @param suppportedSizes the vector of sizes that we check against
+ * @return true if the dimension (width and height) is supported.
+ */
+static bool isVideoSizeSupported(
+ int32_t width, int32_t height,
+ const Vector<Size>& supportedSizes) {
+
+ ALOGV("isVideoSizeSupported");
+ for (size_t i = 0; i < supportedSizes.size(); ++i) {
+ if (width == supportedSizes[i].width &&
+ height == supportedSizes[i].height) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+ * If the preview and video output is separate, we only set the
+ * the video size, and applications should set the preview size
+ * to some proper value, and the recording framework will not
+ * change the preview size; otherwise, if the video and preview
+ * output is the same, we need to set the preview to be the same
+ * as the requested video size.
+ *
+ */
+/*
+ * Query the camera to retrieve the supported video frame sizes
+ * and also to see whether CameraParameters::setVideoSize()
+ * is supported or not.
+ * @param params CameraParameters to retrieve the information
+ * @@param isSetVideoSizeSupported retunrs whether method
+ * CameraParameters::setVideoSize() is supported or not.
+ * @param sizes returns the vector of Size objects for the
+ * supported video frame sizes advertised by the camera.
+ */
+static void getSupportedVideoSizes(
+ const CameraParameters& params,
+ bool *isSetVideoSizeSupported,
+ Vector<Size>& sizes) {
+
+ *isSetVideoSizeSupported = true;
+ params.getSupportedVideoSizes(sizes);
+ if (sizes.size() == 0) {
+ ALOGD("Camera does not support setVideoSize()");
+ params.getSupportedPreviewSizes(sizes);
+ *isSetVideoSizeSupported = false;
+ }
+}
+
+/*
+ * Check whether the camera has the supported color format
+ * @param params CameraParameters to retrieve the information
+ * @return OK if no error.
+ */
+status_t CameraSource::isCameraColorFormatSupported(
+ const CameraParameters& params) {
+ mColorFormat = getColorFormat(params.get(
+ CameraParameters::KEY_VIDEO_FRAME_FORMAT));
+ if (mColorFormat == -1) {
+ return BAD_VALUE;
+ }
+ return OK;
+}
+
+/*
+ * Configure the camera to use the requested video size
+ * (width and height) and/or frame rate. If both width and
+ * height are -1, configuration on the video size is skipped.
+ * if frameRate is -1, configuration on the frame rate
+ * is skipped. Skipping the configuration allows one to
+ * use the current camera setting without the need to
+ * actually know the specific values (see Create() method).
+ *
+ * @param params the CameraParameters to be configured
+ * @param width the target video frame width in pixels
+ * @param height the target video frame height in pixels
+ * @param frameRate the target frame rate in frames per second.
+ * @return OK if no error.
+ */
+status_t CameraSource::configureCamera(
+ CameraParameters* params,
+ int32_t width, int32_t height,
+ int32_t frameRate) {
+ ALOGV("configureCamera");
+ Vector<Size> sizes;
+ bool isSetVideoSizeSupportedByCamera = true;
+ getSupportedVideoSizes(*params, &isSetVideoSizeSupportedByCamera, sizes);
+ bool isCameraParamChanged = false;
+ if (width != -1 && height != -1) {
+ if (!isVideoSizeSupported(width, height, sizes)) {
+ ALOGE("Video dimension (%dx%d) is unsupported", width, height);
+ return BAD_VALUE;
+ }
+ if (isSetVideoSizeSupportedByCamera) {
+ params->setVideoSize(width, height);
+ } else {
+ params->setPreviewSize(width, height);
+ }
+ isCameraParamChanged = true;
+ } else if ((width == -1 && height != -1) ||
+ (width != -1 && height == -1)) {
+ // If one and only one of the width and height is -1
+ // we reject such a request.
+ ALOGE("Requested video size (%dx%d) is not supported", width, height);
+ return BAD_VALUE;
+ } else { // width == -1 && height == -1
+ // Do not configure the camera.
+ // Use the current width and height value setting from the camera.
+ }
+
+ if (frameRate != -1) {
+ CHECK(frameRate > 0 && frameRate <= 120);
+ const char* supportedFrameRates =
+ params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
+ CHECK(supportedFrameRates != NULL);
+ ALOGV("Supported frame rates: %s", supportedFrameRates);
+ char buf[4];
+ snprintf(buf, 4, "%d", frameRate);
+ if (strstr(supportedFrameRates, buf) == NULL) {
+ ALOGE("Requested frame rate (%d) is not supported: %s",
+ frameRate, supportedFrameRates);
+ return BAD_VALUE;
+ }
+
+ // The frame rate is supported, set the camera to the requested value.
+ params->setPreviewFrameRate(frameRate);
+ isCameraParamChanged = true;
+ } else { // frameRate == -1
+ // Do not configure the camera.
+ // Use the current frame rate value setting from the camera
+ }
+
+ if (isCameraParamChanged) {
+ // Either frame rate or frame size needs to be changed.
+ String8 s = params->flatten();
+ if (OK != mCamera->setParameters(s)) {
+ ALOGE("Could not change settings."
+ " Someone else is using camera %p?", mCamera.get());
+ return -EBUSY;
+ }
+ }
+ return OK;
+}
+
+/*
+ * Check whether the requested video frame size
+ * has been successfully configured or not. If both width and height
+ * are -1, check on the current width and height value setting
+ * is performed.
+ *
+ * @param params CameraParameters to retrieve the information
+ * @param the target video frame width in pixels to check against
+ * @param the target video frame height in pixels to check against
+ * @return OK if no error
+ */
+status_t CameraSource::checkVideoSize(
+ const CameraParameters& params,
+ int32_t width, int32_t height) {
+
+ ALOGV("checkVideoSize");
+ // The actual video size is the same as the preview size
+ // if the camera hal does not support separate video and
+ // preview output. In this case, we retrieve the video
+ // size from preview.
+ int32_t frameWidthActual = -1;
+ int32_t frameHeightActual = -1;
+ Vector<Size> sizes;
+ params.getSupportedVideoSizes(sizes);
+ if (sizes.size() == 0) {
+ // video size is the same as preview size
+ params.getPreviewSize(&frameWidthActual, &frameHeightActual);
+ } else {
+ // video size may not be the same as preview
+ params.getVideoSize(&frameWidthActual, &frameHeightActual);
+ }
+ if (frameWidthActual < 0 || frameHeightActual < 0) {
+ ALOGE("Failed to retrieve video frame size (%dx%d)",
+ frameWidthActual, frameHeightActual);
+ return UNKNOWN_ERROR;
+ }
+
+ // Check the actual video frame size against the target/requested
+ // video frame size.
+ if (width != -1 && height != -1) {
+ if (frameWidthActual != width || frameHeightActual != height) {
+ ALOGE("Failed to set video frame size to %dx%d. "
+ "The actual video size is %dx%d ", width, height,
+ frameWidthActual, frameHeightActual);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ // Good now.
+ mVideoSize.width = frameWidthActual;
+ mVideoSize.height = frameHeightActual;
+ return OK;
+}
+
+/*
+ * Check the requested frame rate has been successfully configured or not.
+ * If the target frameRate is -1, check on the current frame rate value
+ * setting is performed.
+ *
+ * @param params CameraParameters to retrieve the information
+ * @param the target video frame rate to check against
+ * @return OK if no error.
+ */
+status_t CameraSource::checkFrameRate(
+ const CameraParameters& params,
+ int32_t frameRate) {
+
+ ALOGV("checkFrameRate");
+ int32_t frameRateActual = params.getPreviewFrameRate();
+ if (frameRateActual < 0) {
+ ALOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
+ return UNKNOWN_ERROR;
+ }
+
+ // Check the actual video frame rate against the target/requested
+ // video frame rate.
+ if (frameRate != -1 && (frameRateActual - frameRate) != 0) {
+ ALOGE("Failed to set preview frame rate to %d fps. The actual "
+ "frame rate is %d", frameRate, frameRateActual);
+ return UNKNOWN_ERROR;
+ }
+
+ // Good now.
+ mVideoFrameRate = frameRateActual;
+ return OK;
+}
+
+/*
+ * Initialize the CameraSource to so that it becomes
+ * ready for providing the video input streams as requested.
+ * @param camera the camera object used for the video source
+ * @param cameraId if camera == 0, use camera with this id
+ * as the video source
+ * @param videoSize the target video frame size. If both
+ * width and height in videoSize is -1, use the current
+ * width and heigth settings by the camera
+ * @param frameRate the target frame rate in frames per second.
+ * if it is -1, use the current camera frame rate setting.
+ * @param storeMetaDataInVideoBuffers request to store meta
+ * data or real YUV data in video buffers. Request to
+ * store meta data in video buffers may not be honored
+ * if the source does not support this feature.
+ *
+ * @return OK if no error.
+ */
+status_t CameraSource::init(
+ const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId,
+ Size videoSize,
+ int32_t frameRate,
+ bool storeMetaDataInVideoBuffers) {
+
+ ALOGV("init");
+ status_t err = OK;
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ err = initWithCameraAccess(camera, proxy, cameraId,
+ videoSize, frameRate,
+ storeMetaDataInVideoBuffers);
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ return err;
+}
+
+status_t CameraSource::initWithCameraAccess(
+ const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId,
+ Size videoSize,
+ int32_t frameRate,
+ bool storeMetaDataInVideoBuffers) {
+ ALOGV("initWithCameraAccess");
+ status_t err = OK;
+
+ if ((err = isCameraAvailable(camera, proxy, cameraId)) != OK) {
+ ALOGE("Camera connection could not be established.");
+ return err;
+ }
+ CameraParameters params(mCamera->getParameters());
+ if ((err = isCameraColorFormatSupported(params)) != OK) {
+ return err;
+ }
+
+ // Set the camera to use the requested video frame size
+ // and/or frame rate.
+ if ((err = configureCamera(&params,
+ videoSize.width, videoSize.height,
+ frameRate))) {
+ return err;
+ }
+
+ // Check on video frame size and frame rate.
+ CameraParameters newCameraParams(mCamera->getParameters());
+ if ((err = checkVideoSize(newCameraParams,
+ videoSize.width, videoSize.height)) != OK) {
+ return err;
+ }
+ if ((err = checkFrameRate(newCameraParams, frameRate)) != OK) {
+ return err;
+ }
+
+ // Set the preview display. Skip this if mSurface is null because
+ // applications may already set a surface to the camera.
+ if (mSurface != NULL) {
+ // This CHECK is good, since we just passed the lock/unlock
+ // check earlier by calling mCamera->setParameters().
+ CHECK_EQ((status_t)OK, mCamera->setPreviewDisplay(mSurface));
+ }
+
+ // By default, do not store metadata in video buffers
+ mIsMetaDataStoredInVideoBuffers = false;
+ mCamera->storeMetaDataInBuffers(false);
+ if (storeMetaDataInVideoBuffers) {
+ if (OK == mCamera->storeMetaDataInBuffers(true)) {
+ mIsMetaDataStoredInVideoBuffers = true;
+ }
+ }
+
+ int64_t glitchDurationUs = (1000000LL / mVideoFrameRate);
+ if (glitchDurationUs > mGlitchDurationThresholdUs) {
+ mGlitchDurationThresholdUs = glitchDurationUs;
+ }
+
+ // XXX: query camera for the stride and slice height
+ // when the capability becomes available.
+ mMeta = new MetaData;
+ mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+ mMeta->setInt32(kKeyColorFormat, mColorFormat);
+ mMeta->setInt32(kKeyWidth, mVideoSize.width);
+ mMeta->setInt32(kKeyHeight, mVideoSize.height);
+ mMeta->setInt32(kKeyStride, mVideoSize.width);
+ mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
+ mMeta->setInt32(kKeyFrameRate, mVideoFrameRate);
+ return OK;
+}
+
+CameraSource::~CameraSource() {
+ if (mStarted) {
+ reset();
+ } else if (mInitCheck == OK) {
+ // Camera is initialized but because start() is never called,
+ // the lock on Camera is never released(). This makes sure
+ // Camera's lock is released in this case.
+ releaseCamera();
+ }
+}
+
+void CameraSource::startCameraRecording() {
+ ALOGV("startCameraRecording");
+ // Reset the identity to the current thread because media server owns the
+ // camera and recording is started by the applications. The applications
+ // will connect to the camera in ICameraRecordingProxy::startRecording.
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ if (mCameraFlags & FLAGS_HOT_CAMERA) {
+ mCamera->unlock();
+ mCamera.clear();
+ CHECK_EQ((status_t)OK,
+ mCameraRecordingProxy->startRecording(new ProxyListener(this)));
+ } else {
+ mCamera->setListener(new CameraSourceListener(this));
+ mCamera->startRecording();
+ CHECK(mCamera->recordingEnabled());
+ }
+ IPCThreadState::self()->restoreCallingIdentity(token);
+}
+
+status_t CameraSource::start(MetaData *meta) {
+ ALOGV("start");
+ CHECK(!mStarted);
+ if (mInitCheck != OK) {
+ ALOGE("CameraSource is not initialized yet");
+ return mInitCheck;
+ }
+
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.stagefright.record-stats", value, NULL)
+ && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+ mCollectStats = true;
+ }
+
+ mStartTimeUs = 0;
+ int64_t startTimeUs;
+ if (meta && meta->findInt64(kKeyTime, &startTimeUs)) {
+ mStartTimeUs = startTimeUs;
+ }
+
+ startCameraRecording();
+
+ mStarted = true;
+ return OK;
+}
+
+void CameraSource::stopCameraRecording() {
+ ALOGV("stopCameraRecording");
+ if (mCameraFlags & FLAGS_HOT_CAMERA) {
+ mCameraRecordingProxy->stopRecording();
+ } else {
+ mCamera->setListener(NULL);
+ mCamera->stopRecording();
+ }
+}
+
+void CameraSource::releaseCamera() {
+ ALOGV("releaseCamera");
+ if (mCamera != 0) {
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ if ((mCameraFlags & FLAGS_HOT_CAMERA) == 0) {
+ ALOGV("Camera was cold when we started, stopping preview");
+ mCamera->stopPreview();
+ mCamera->disconnect();
+ }
+ mCamera->unlock();
+ mCamera.clear();
+ mCamera = 0;
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ }
+ if (mCameraRecordingProxy != 0) {
+ mCameraRecordingProxy->asBinder()->unlinkToDeath(mDeathNotifier);
+ mCameraRecordingProxy.clear();
+ }
+ mCameraFlags = 0;
+}
+
+status_t CameraSource::reset() {
+ ALOGD("reset: E");
+ Mutex::Autolock autoLock(mLock);
+ mStarted = false;
+ mFrameAvailableCondition.signal();
+
+ int64_t token;
+ bool isTokenValid = false;
+ if (mCamera != 0) {
+ token = IPCThreadState::self()->clearCallingIdentity();
+ isTokenValid = true;
+ }
+ releaseQueuedFrames();
+ while (!mFramesBeingEncoded.empty()) {
+ if (NO_ERROR !=
+ mFrameCompleteCondition.waitRelative(mLock,
+ mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
+ ALOGW("Timed out waiting for outstanding frames being encoded: %d",
+ mFramesBeingEncoded.size());
+ }
+ }
+ stopCameraRecording();
+ releaseCamera();
+ if (isTokenValid) {
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ }
+
+ if (mCollectStats) {
+ ALOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
+ mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
+ mLastFrameTimestampUs - mFirstFrameTimeUs);
+ }
+
+ if (mNumGlitches > 0) {
+ ALOGW("%d long delays between neighboring video frames", mNumGlitches);
+ }
+
+ CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
+ ALOGD("reset: X");
+ return OK;
+}
+
+void CameraSource::releaseRecordingFrame(const sp<IMemory>& frame) {
+ ALOGV("releaseRecordingFrame");
+ if (mCameraRecordingProxy != NULL) {
+ mCameraRecordingProxy->releaseRecordingFrame(frame);
+ } else if (mCamera != NULL) {
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ mCamera->releaseRecordingFrame(frame);
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ }
+}
+
+void CameraSource::releaseQueuedFrames() {
+ List<sp<IMemory> >::iterator it;
+ while (!mFramesReceived.empty()) {
+ it = mFramesReceived.begin();
+ releaseRecordingFrame(*it);
+ mFramesReceived.erase(it);
+ ++mNumFramesDropped;
+ }
+}
+
+sp<MetaData> CameraSource::getFormat() {
+ return mMeta;
+}
+
+void CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
+ releaseRecordingFrame(frame);
+}
+
+void CameraSource::signalBufferReturned(MediaBuffer *buffer) {
+ ALOGV("signalBufferReturned: %p", buffer->data());
+ Mutex::Autolock autoLock(mLock);
+ 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(!"signalBufferReturned: bogus buffer");
+}
+
+status_t CameraSource::read(
+ MediaBuffer **buffer, const ReadOptions *options) {
+ ALOGV("read");
+
+ *buffer = NULL;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ sp<IMemory> frame;
+ int64_t frameTime;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+ while (mStarted && mFramesReceived.empty()) {
+ if (NO_ERROR !=
+ mFrameAvailableCondition.waitRelative(mLock,
+ mTimeBetweenFrameCaptureUs * 1000LL + CAMERA_SOURCE_TIMEOUT_NS)) {
+ if (mCameraRecordingProxy != 0 &&
+ !mCameraRecordingProxy->asBinder()->isBinderAlive()) {
+ ALOGW("camera recording proxy is gone");
+ return ERROR_END_OF_STREAM;
+ }
+ ALOGW("Timed out waiting for incoming camera video frames: %lld us",
+ mLastFrameTimestampUs);
+ }
+ }
+ if (!mStarted) {
+ return OK;
+ }
+ frame = *mFramesReceived.begin();
+ mFramesReceived.erase(mFramesReceived.begin());
+
+ frameTime = *mFrameTimes.begin();
+ mFrameTimes.erase(mFrameTimes.begin());
+ 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;
+}
+
+void CameraSource::dataCallbackTimestamp(int64_t timestampUs,
+ int32_t msgType, const sp<IMemory> &data) {
+ ALOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
+ Mutex::Autolock autoLock(mLock);
+ if (!mStarted || (mNumFramesReceived == 0 && timestampUs < mStartTimeUs)) {
+ ALOGV("Drop frame at %lld/%lld us", timestampUs, mStartTimeUs);
+ releaseOneRecordingFrame(data);
+ return;
+ }
+
+ if (mNumFramesReceived > 0) {
+ CHECK(timestampUs > mLastFrameTimestampUs);
+ if (timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
+ ++mNumGlitches;
+ }
+ }
+
+ // May need to skip frame or modify timestamp. Currently implemented
+ // by the subclass CameraSourceTimeLapse.
+ if (skipCurrentFrame(timestampUs)) {
+ releaseOneRecordingFrame(data);
+ return;
+ }
+
+ 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;
+ }
+ }
+ ++mNumFramesReceived;
+
+ CHECK(data != NULL && data->size() > 0);
+ mFramesReceived.push_back(data);
+ int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
+ mFrameTimes.push_back(timeUs);
+ ALOGV("initial delay: %lld, current time stamp: %lld",
+ mStartTimeUs, timeUs);
+ mFrameAvailableCondition.signal();
+}
+
+bool CameraSource::isMetaDataStoredInVideoBuffers() const {
+ ALOGV("isMetaDataStoredInVideoBuffers");
+ return mIsMetaDataStoredInVideoBuffers;
+}
+
+CameraSource::ProxyListener::ProxyListener(const sp<CameraSource>& source) {
+ mSource = source;
+}
+
+void CameraSource::ProxyListener::dataCallbackTimestamp(
+ nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
+ mSource->dataCallbackTimestamp(timestamp / 1000, msgType, dataPtr);
+}
+
+void CameraSource::DeathNotifier::binderDied(const wp<IBinder>& who) {
+ ALOGI("Camera recording proxy died");
+}
+
+} // namespace android
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
new file mode 100644
index 0000000..26ce7ae
--- /dev/null
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -0,0 +1,296 @@
+/*
+ * 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 "CameraSourceTimeLapse"
+
+#include <binder/IPCThreadState.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/CameraSource.h>
+#include <media/stagefright/CameraSourceTimeLapse.h>
+#include <media/stagefright/MetaData.h>
+#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+// static
+CameraSourceTimeLapse *CameraSourceTimeLapse::CreateFromCamera(
+ const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
+ int32_t cameraId,
+ Size videoSize,
+ int32_t videoFrameRate,
+ const sp<Surface>& surface,
+ int64_t timeBetweenFrameCaptureUs) {
+
+ CameraSourceTimeLapse *source = new
+ CameraSourceTimeLapse(camera, proxy, cameraId,
+ videoSize, videoFrameRate, surface,
+ timeBetweenFrameCaptureUs);
+
+ if (source != NULL) {
+ if (source->initCheck() != OK) {
+ delete source;
+ return NULL;
+ }
+ }
+ return source;
+}
+
+CameraSourceTimeLapse::CameraSourceTimeLapse(
+ const sp<ICamera>& camera,
+ const sp<ICameraRecordingProxy>& proxy,
+ int32_t cameraId,
+ Size videoSize,
+ int32_t videoFrameRate,
+ const sp<Surface>& surface,
+ int64_t timeBetweenFrameCaptureUs)
+ : CameraSource(camera, proxy, cameraId, videoSize, videoFrameRate, surface, true),
+ mTimeBetweenTimeLapseVideoFramesUs(1E6/videoFrameRate),
+ mLastTimeLapseFrameRealTimestampUs(0),
+ mSkipCurrentFrame(false) {
+
+ mTimeBetweenFrameCaptureUs = timeBetweenFrameCaptureUs;
+ ALOGD("starting time lapse mode: %lld us",
+ mTimeBetweenFrameCaptureUs);
+
+ mVideoWidth = videoSize.width;
+ mVideoHeight = videoSize.height;
+
+ if (!trySettingVideoSize(videoSize.width, videoSize.height)) {
+ mInitCheck = NO_INIT;
+ }
+
+ // Initialize quick stop variables.
+ mQuickStop = false;
+ mForceRead = false;
+ mLastReadBufferCopy = NULL;
+ mStopWaitingForIdleCamera = false;
+}
+
+CameraSourceTimeLapse::~CameraSourceTimeLapse() {
+ if (mLastReadBufferCopy) {
+ mLastReadBufferCopy->release();
+ mLastReadBufferCopy = NULL;
+ }
+}
+
+void CameraSourceTimeLapse::startQuickReadReturns() {
+ ALOGV("startQuickReadReturns");
+ Mutex::Autolock autoLock(mQuickStopLock);
+
+ // Enable quick stop mode.
+ mQuickStop = true;
+
+ // Force dataCallbackTimestamp() coming from the video camera to
+ // not skip the next frame as we want read() to get a get a frame
+ // right away.
+ mForceRead = true;
+}
+
+bool CameraSourceTimeLapse::trySettingVideoSize(
+ int32_t width, int32_t height) {
+
+ ALOGV("trySettingVideoSize");
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ String8 s = mCamera->getParameters();
+
+ CameraParameters params(s);
+ Vector<Size> supportedSizes;
+ params.getSupportedVideoSizes(supportedSizes);
+ bool videoOutputSupported = false;
+ if (supportedSizes.size() == 0) {
+ params.getSupportedPreviewSizes(supportedSizes);
+ } else {
+ videoOutputSupported = true;
+ }
+
+ bool videoSizeSupported = false;
+ for (uint32_t i = 0; i < supportedSizes.size(); ++i) {
+ int32_t pictureWidth = supportedSizes[i].width;
+ int32_t pictureHeight = supportedSizes[i].height;
+
+ if ((pictureWidth == width) && (pictureHeight == height)) {
+ videoSizeSupported = true;
+ }
+ }
+
+ bool isSuccessful = false;
+ if (videoSizeSupported) {
+ ALOGV("Video size (%d, %d) is supported", width, height);
+ if (videoOutputSupported) {
+ params.setVideoSize(width, height);
+ } else {
+ params.setPreviewSize(width, height);
+ }
+ if (mCamera->setParameters(params.flatten()) == OK) {
+ isSuccessful = true;
+ } else {
+ ALOGE("Failed to set preview size to %dx%d", width, height);
+ isSuccessful = false;
+ }
+ }
+
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ return isSuccessful;
+}
+
+void CameraSourceTimeLapse::signalBufferReturned(MediaBuffer* buffer) {
+ ALOGV("signalBufferReturned");
+ Mutex::Autolock autoLock(mQuickStopLock);
+ if (mQuickStop && (buffer == mLastReadBufferCopy)) {
+ buffer->setObserver(NULL);
+ buffer->release();
+ } else {
+ return CameraSource::signalBufferReturned(buffer);
+ }
+}
+
+void createMediaBufferCopy(
+ const MediaBuffer& sourceBuffer,
+ int64_t frameTime,
+ MediaBuffer **newBuffer) {
+
+ ALOGV("createMediaBufferCopy");
+ size_t sourceSize = sourceBuffer.size();
+ void* sourcePointer = sourceBuffer.data();
+
+ (*newBuffer) = new MediaBuffer(sourceSize);
+ memcpy((*newBuffer)->data(), sourcePointer, sourceSize);
+
+ (*newBuffer)->meta_data()->setInt64(kKeyTime, frameTime);
+}
+
+void CameraSourceTimeLapse::fillLastReadBufferCopy(MediaBuffer& sourceBuffer) {
+ ALOGV("fillLastReadBufferCopy");
+ int64_t frameTime;
+ CHECK(sourceBuffer.meta_data()->findInt64(kKeyTime, &frameTime));
+ createMediaBufferCopy(sourceBuffer, frameTime, &mLastReadBufferCopy);
+ mLastReadBufferCopy->add_ref();
+ mLastReadBufferCopy->setObserver(this);
+}
+
+status_t CameraSourceTimeLapse::read(
+ MediaBuffer **buffer, const ReadOptions *options) {
+ ALOGV("read");
+ if (mLastReadBufferCopy == NULL) {
+ mLastReadStatus = CameraSource::read(buffer, options);
+
+ // mQuickStop may have turned to true while read was blocked.
+ // Make a copy of the buffer in that case.
+ Mutex::Autolock autoLock(mQuickStopLock);
+ if (mQuickStop && *buffer) {
+ fillLastReadBufferCopy(**buffer);
+ }
+ return mLastReadStatus;
+ } else {
+ (*buffer) = mLastReadBufferCopy;
+ (*buffer)->add_ref();
+ return mLastReadStatus;
+ }
+}
+
+sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(
+ const sp<IMemory> &source_data) {
+
+ ALOGV("createIMemoryCopy");
+ size_t source_size = source_data->size();
+ void* source_pointer = source_data->pointer();
+
+ sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(source_size);
+ sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, source_size);
+ memcpy(newMemory->pointer(), source_pointer, source_size);
+ return newMemory;
+}
+
+bool CameraSourceTimeLapse::skipCurrentFrame(int64_t timestampUs) {
+ ALOGV("skipCurrentFrame");
+ if (mSkipCurrentFrame) {
+ mSkipCurrentFrame = false;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) {
+ ALOGV("skipFrameAndModifyTimeStamp");
+ if (mLastTimeLapseFrameRealTimestampUs == 0) {
+ // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs
+ // to current time (timestampUs) and save frame data.
+ ALOGV("dataCallbackTimestamp timelapse: initial frame");
+
+ mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+ return false;
+ }
+
+ {
+ Mutex::Autolock autoLock(mQuickStopLock);
+
+ // mForceRead may be set to true by startQuickReadReturns(). In that
+ // case don't skip this frame.
+ if (mForceRead) {
+ ALOGV("dataCallbackTimestamp timelapse: forced read");
+ mForceRead = false;
+ *timestampUs =
+ mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
+
+ // Really make sure that this video recording frame will not be dropped.
+ if (*timestampUs < mStartTimeUs) {
+ ALOGI("set timestampUs to start time stamp %lld us", mStartTimeUs);
+ *timestampUs = mStartTimeUs;
+ }
+ return false;
+ }
+ }
+
+ // Workaround to bypass the first 2 input frames for skipping.
+ // The first 2 output frames from the encoder are: decoder specific info and
+ // the compressed video frame data for the first input video frame.
+ if (mNumFramesEncoded >= 1 && *timestampUs <
+ (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenFrameCaptureUs)) {
+ // Skip all frames from last encoded frame until
+ // sufficient time (mTimeBetweenFrameCaptureUs) has passed.
+ // Tell the camera to release its recording frame and return.
+ ALOGV("dataCallbackTimestamp timelapse: skipping intermediate frame");
+ return true;
+ } else {
+ // Desired frame has arrived after mTimeBetweenFrameCaptureUs time:
+ // - Reset mLastTimeLapseFrameRealTimestampUs to current time.
+ // - Artificially modify timestampUs to be one frame time (1/framerate) ahead
+ // of the last encoded frame's time stamp.
+ ALOGV("dataCallbackTimestamp timelapse: got timelapse frame");
+
+ mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+ *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
+ return false;
+ }
+ return false;
+}
+
+void CameraSourceTimeLapse::dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
+ const sp<IMemory> &data) {
+ ALOGV("dataCallbackTimestamp");
+ mSkipCurrentFrame = skipFrameAndModifyTimeStamp(&timestampUs);
+ CameraSource::dataCallbackTimestamp(timestampUs, msgType, data);
+}
+
+} // namespace android
diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp
new file mode 100644
index 0000000..524c3aa
--- /dev/null
+++ b/media/libstagefright/DRMExtractor.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.
+ */
+
+#include "include/DRMExtractor.h"
+#include "include/AMRExtractor.h"
+#include "include/MP3Extractor.h"
+#include "include/MPEG4Extractor.h"
+#include "include/WAVExtractor.h"
+#include "include/OggExtractor.h"
+
+#include <arpa/inet.h>
+#include <utils/String8.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/Utils.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaBuffer.h>
+
+#include <drm/drm_framework_common.h>
+#include <utils/Errors.h>
+
+
+namespace android {
+
+class DRMSource : public MediaSource {
+public:
+ DRMSource(const sp<MediaSource> &mediaSource,
+ const sp<DecryptHandle> &decryptHandle,
+ DrmManagerClient *managerClient,
+ int32_t trackId, DrmBuffer *ipmpBox);
+
+ 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);
+
+protected:
+ virtual ~DRMSource();
+
+private:
+ sp<MediaSource> mOriginalMediaSource;
+ sp<DecryptHandle> mDecryptHandle;
+ DrmManagerClient* mDrmManagerClient;
+ size_t mTrackId;
+ mutable Mutex mDRMLock;
+ size_t mNALLengthSize;
+ bool mWantsNALFragments;
+
+ DRMSource(const DRMSource &);
+ DRMSource &operator=(const DRMSource &);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+DRMSource::DRMSource(const sp<MediaSource> &mediaSource,
+ const sp<DecryptHandle> &decryptHandle,
+ DrmManagerClient *managerClient,
+ int32_t trackId, DrmBuffer *ipmpBox)
+ : mOriginalMediaSource(mediaSource),
+ mDecryptHandle(decryptHandle),
+ mDrmManagerClient(managerClient),
+ mTrackId(trackId),
+ mNALLengthSize(0),
+ mWantsNALFragments(false) {
+ CHECK(mDrmManagerClient);
+ mDrmManagerClient->initializeDecryptUnit(
+ mDecryptHandle, trackId, ipmpBox);
+
+ const char *mime;
+ bool success = getFormat()->findCString(kKeyMIMEType, &mime);
+ CHECK(success);
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ CHECK(getFormat()->findData(kKeyAVCC, &type, &data, &size));
+
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ CHECK(size >= 7);
+ CHECK_EQ(ptr[0], 1); // configurationVersion == 1
+
+ // The number of bytes used to encode the length of a NAL unit.
+ mNALLengthSize = 1 + (ptr[4] & 3);
+ }
+}
+
+DRMSource::~DRMSource() {
+ Mutex::Autolock autoLock(mDRMLock);
+ mDrmManagerClient->finalizeDecryptUnit(mDecryptHandle, mTrackId);
+}
+
+status_t DRMSource::start(MetaData *params) {
+ int32_t val;
+ if (params && params->findInt32(kKeyWantsNALFragments, &val)
+ && val != 0) {
+ mWantsNALFragments = true;
+ } else {
+ mWantsNALFragments = false;
+ }
+
+ return mOriginalMediaSource->start(params);
+}
+
+status_t DRMSource::stop() {
+ return mOriginalMediaSource->stop();
+}
+
+sp<MetaData> DRMSource::getFormat() {
+ return mOriginalMediaSource->getFormat();
+}
+
+status_t DRMSource::read(MediaBuffer **buffer, const ReadOptions *options) {
+ Mutex::Autolock autoLock(mDRMLock);
+ status_t err;
+ if ((err = mOriginalMediaSource->read(buffer, options)) != OK) {
+ return err;
+ }
+
+ size_t len = (*buffer)->range_length();
+
+ char *src = (char *)(*buffer)->data() + (*buffer)->range_offset();
+
+ DrmBuffer encryptedDrmBuffer(src, len);
+ DrmBuffer decryptedDrmBuffer;
+ decryptedDrmBuffer.length = len;
+ decryptedDrmBuffer.data = new char[len];
+ DrmBuffer *pDecryptedDrmBuffer = &decryptedDrmBuffer;
+
+ if ((err = mDrmManagerClient->decrypt(mDecryptHandle, mTrackId,
+ &encryptedDrmBuffer, &pDecryptedDrmBuffer)) != NO_ERROR) {
+
+ if (decryptedDrmBuffer.data) {
+ delete [] decryptedDrmBuffer.data;
+ decryptedDrmBuffer.data = NULL;
+ }
+
+ return err;
+ }
+ CHECK(pDecryptedDrmBuffer == &decryptedDrmBuffer);
+
+ const char *mime;
+ CHECK(getFormat()->findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) && !mWantsNALFragments) {
+ uint8_t *dstData = (uint8_t*)src;
+ size_t srcOffset = 0;
+ size_t dstOffset = 0;
+
+ len = decryptedDrmBuffer.length;
+ while (srcOffset < len) {
+ CHECK(srcOffset + mNALLengthSize <= len);
+ size_t nalLength = 0;
+ const uint8_t* data = (const uint8_t*)(&decryptedDrmBuffer.data[srcOffset]);
+
+ switch (mNALLengthSize) {
+ case 1:
+ nalLength = *data;
+ break;
+ case 2:
+ nalLength = U16_AT(data);
+ break;
+ case 3:
+ nalLength = ((size_t)data[0] << 16) | U16_AT(&data[1]);
+ break;
+ case 4:
+ nalLength = U32_AT(data);
+ break;
+ default:
+ CHECK(!"Should not be here.");
+ break;
+ }
+
+ srcOffset += mNALLengthSize;
+
+ if (srcOffset + nalLength > len) {
+ if (decryptedDrmBuffer.data) {
+ delete [] decryptedDrmBuffer.data;
+ decryptedDrmBuffer.data = NULL;
+ }
+
+ return ERROR_MALFORMED;
+ }
+
+ if (nalLength == 0) {
+ continue;
+ }
+
+ CHECK(dstOffset + 4 <= (*buffer)->size());
+
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 1;
+ memcpy(&dstData[dstOffset], &decryptedDrmBuffer.data[srcOffset], nalLength);
+ srcOffset += nalLength;
+ dstOffset += nalLength;
+ }
+
+ CHECK_EQ(srcOffset, len);
+ (*buffer)->set_range((*buffer)->range_offset(), dstOffset);
+
+ } else {
+ memcpy(src, decryptedDrmBuffer.data, decryptedDrmBuffer.length);
+ (*buffer)->set_range((*buffer)->range_offset(), decryptedDrmBuffer.length);
+ }
+
+ if (decryptedDrmBuffer.data) {
+ delete [] decryptedDrmBuffer.data;
+ decryptedDrmBuffer.data = NULL;
+ }
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+DRMExtractor::DRMExtractor(const sp<DataSource> &source, const char* mime)
+ : mDataSource(source),
+ mDecryptHandle(NULL),
+ mDrmManagerClient(NULL) {
+ mOriginalExtractor = MediaExtractor::Create(source, mime);
+ mOriginalExtractor->setDrmFlag(true);
+ mOriginalExtractor->getMetaData()->setInt32(kKeyIsDRM, 1);
+
+ source->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
+}
+
+DRMExtractor::~DRMExtractor() {
+}
+
+size_t DRMExtractor::countTracks() {
+ return mOriginalExtractor->countTracks();
+}
+
+sp<MediaSource> DRMExtractor::getTrack(size_t index) {
+ sp<MediaSource> originalMediaSource = mOriginalExtractor->getTrack(index);
+ originalMediaSource->getFormat()->setInt32(kKeyIsDRM, 1);
+
+ int32_t trackID;
+ CHECK(getTrackMetaData(index, 0)->findInt32(kKeyTrackID, &trackID));
+
+ DrmBuffer ipmpBox;
+ ipmpBox.data = mOriginalExtractor->getDrmTrackInfo(trackID, &(ipmpBox.length));
+ CHECK(ipmpBox.length > 0);
+
+ return new DRMSource(originalMediaSource, mDecryptHandle, mDrmManagerClient,
+ trackID, &ipmpBox);
+}
+
+sp<MetaData> DRMExtractor::getTrackMetaData(size_t index, uint32_t flags) {
+ return mOriginalExtractor->getTrackMetaData(index, flags);
+}
+
+sp<MetaData> DRMExtractor::getMetaData() {
+ return mOriginalExtractor->getMetaData();
+}
+
+bool SniffDRM(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
+ sp<DecryptHandle> decryptHandle = source->DrmInitialization();
+
+ if (decryptHandle != NULL) {
+ if (decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED) {
+ *mimeType = String8("drm+container_based+") + decryptHandle->mimeType;
+ *confidence = 10.0f;
+ } else if (decryptHandle->decryptApiType == DecryptApiType::ELEMENTARY_STREAM_BASED) {
+ *mimeType = String8("drm+es_based+") + decryptHandle->mimeType;
+ *confidence = 10.0f;
+ } else {
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+} //namespace android
+
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
new file mode 100644
index 0000000..d0a7880
--- /dev/null
+++ b/media/libstagefright/DataSource.cpp
@@ -0,0 +1,166 @@
+/*
+ * 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 "include/AMRExtractor.h"
+#include "include/AVIExtractor.h"
+
+#if CHROMIUM_AVAILABLE
+#include "include/DataUriSource.h"
+#endif
+
+#include "include/MP3Extractor.h"
+#include "include/MPEG4Extractor.h"
+#include "include/WAVExtractor.h"
+#include "include/OggExtractor.h"
+#include "include/MPEG2PSExtractor.h"
+#include "include/MPEG2TSExtractor.h"
+#include "include/NuCachedSource2.h"
+#include "include/HTTPBase.h"
+#include "include/DRMExtractor.h"
+#include "include/FLACExtractor.h"
+#include "include/AACExtractor.h"
+#include "include/WVMExtractor.h"
+
+#include "matroska/MatroskaExtractor.h"
+
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/String8.h>
+
+#include <cutils/properties.h>
+
+namespace android {
+
+bool DataSource::getUInt16(off64_t offset, uint16_t *x) {
+ *x = 0;
+
+ uint8_t byte[2];
+ if (readAt(offset, byte, 2) != 2) {
+ return false;
+ }
+
+ *x = (byte[0] << 8) | byte[1];
+
+ return true;
+}
+
+status_t DataSource::getSize(off64_t *size) {
+ *size = 0;
+
+ return ERROR_UNSUPPORTED;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+Mutex DataSource::gSnifferMutex;
+List<DataSource::SnifferFunc> DataSource::gSniffers;
+
+bool DataSource::sniff(
+ String8 *mimeType, float *confidence, sp<AMessage> *meta) {
+ *mimeType = "";
+ *confidence = 0.0f;
+ meta->clear();
+
+ Mutex::Autolock autoLock(gSnifferMutex);
+ for (List<SnifferFunc>::iterator it = gSniffers.begin();
+ it != gSniffers.end(); ++it) {
+ String8 newMimeType;
+ float newConfidence;
+ sp<AMessage> newMeta;
+ if ((*it)(this, &newMimeType, &newConfidence, &newMeta)) {
+ if (newConfidence > *confidence) {
+ *mimeType = newMimeType;
+ *confidence = newConfidence;
+ *meta = newMeta;
+ }
+ }
+ }
+
+ return *confidence > 0.0;
+}
+
+// static
+void DataSource::RegisterSniffer(SnifferFunc func) {
+ Mutex::Autolock autoLock(gSnifferMutex);
+
+ for (List<SnifferFunc>::iterator it = gSniffers.begin();
+ it != gSniffers.end(); ++it) {
+ if (*it == func) {
+ return;
+ }
+ }
+
+ gSniffers.push_back(func);
+}
+
+// static
+void DataSource::RegisterDefaultSniffers() {
+ RegisterSniffer(SniffMPEG4);
+ RegisterSniffer(SniffMatroska);
+ RegisterSniffer(SniffOgg);
+ RegisterSniffer(SniffWAV);
+ RegisterSniffer(SniffFLAC);
+ RegisterSniffer(SniffAMR);
+ RegisterSniffer(SniffMPEG2TS);
+ RegisterSniffer(SniffMP3);
+ RegisterSniffer(SniffAAC);
+ RegisterSniffer(SniffAVI);
+ RegisterSniffer(SniffMPEG2PS);
+ RegisterSniffer(SniffWVM);
+
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("drm.service.enabled", value, NULL)
+ && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+ RegisterSniffer(SniffDRM);
+ }
+}
+
+// static
+sp<DataSource> DataSource::CreateFromURI(
+ const char *uri, const KeyedVector<String8, String8> *headers) {
+ sp<DataSource> source;
+ if (!strncasecmp("file://", uri, 7)) {
+ source = new FileSource(uri + 7);
+ } else if (!strncasecmp("http://", uri, 7)
+ || !strncasecmp("https://", uri, 8)) {
+ sp<HTTPBase> httpSource = HTTPBase::Create();
+ if (httpSource->connect(uri, headers) != OK) {
+ return NULL;
+ }
+ source = new NuCachedSource2(httpSource);
+# if CHROMIUM_AVAILABLE
+ } else if (!strncasecmp("data:", uri, 5)) {
+ source = new DataUriSource(uri);
+#endif
+ } else {
+ // Assume it's a filename.
+ source = new FileSource(uri);
+ }
+
+ if (source == NULL || source->initCheck() != OK) {
+ return NULL;
+ }
+
+ return source;
+}
+
+String8 DataSource::getMIMEType() const {
+ return String8("application/octet-stream");
+}
+
+} // namespace android
diff --git a/media/libstagefright/ESDS.cpp b/media/libstagefright/ESDS.cpp
new file mode 100644
index 0000000..4a0c35c
--- /dev/null
+++ b/media/libstagefright/ESDS.cpp
@@ -0,0 +1,227 @@
+/*
+ * 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 "ESDS"
+#include <utils/Log.h>
+
+#include "include/ESDS.h"
+
+#include <string.h>
+
+namespace android {
+
+ESDS::ESDS(const void *data, size_t size)
+ : mData(new uint8_t[size]),
+ mSize(size),
+ mInitCheck(NO_INIT),
+ mDecoderSpecificOffset(0),
+ mDecoderSpecificLength(0),
+ mObjectTypeIndication(0) {
+ memcpy(mData, data, size);
+
+ mInitCheck = parse();
+}
+
+ESDS::~ESDS() {
+ delete[] mData;
+ mData = NULL;
+}
+
+status_t ESDS::InitCheck() const {
+ return mInitCheck;
+}
+
+status_t ESDS::getObjectTypeIndication(uint8_t *objectTypeIndication) const {
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ *objectTypeIndication = mObjectTypeIndication;
+
+ return OK;
+}
+
+status_t ESDS::getCodecSpecificInfo(const void **data, size_t *size) const {
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ *data = &mData[mDecoderSpecificOffset];
+ *size = mDecoderSpecificLength;
+
+ return OK;
+}
+
+status_t ESDS::skipDescriptorHeader(
+ size_t offset, size_t size,
+ uint8_t *tag, size_t *data_offset, size_t *data_size) const {
+ if (size == 0) {
+ return ERROR_MALFORMED;
+ }
+
+ *tag = mData[offset++];
+ --size;
+
+ *data_size = 0;
+ bool more;
+ do {
+ if (size == 0) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t x = mData[offset++];
+ --size;
+
+ *data_size = (*data_size << 7) | (x & 0x7f);
+ more = (x & 0x80) != 0;
+ }
+ while (more);
+
+ ALOGV("tag=0x%02x data_size=%d", *tag, *data_size);
+
+ if (*data_size > size) {
+ return ERROR_MALFORMED;
+ }
+
+ *data_offset = offset;
+
+ return OK;
+}
+
+status_t ESDS::parse() {
+ uint8_t tag;
+ size_t data_offset;
+ size_t data_size;
+ status_t err =
+ skipDescriptorHeader(0, mSize, &tag, &data_offset, &data_size);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (tag != kTag_ESDescriptor) {
+ return ERROR_MALFORMED;
+ }
+
+ return parseESDescriptor(data_offset, data_size);
+}
+
+status_t ESDS::parseESDescriptor(size_t offset, size_t size) {
+ if (size < 3) {
+ return ERROR_MALFORMED;
+ }
+
+ offset += 2; // skip ES_ID
+ size -= 2;
+
+ unsigned streamDependenceFlag = mData[offset] & 0x80;
+ unsigned URL_Flag = mData[offset] & 0x40;
+ unsigned OCRstreamFlag = mData[offset] & 0x20;
+
+ ++offset;
+ --size;
+
+ if (streamDependenceFlag) {
+ offset += 2;
+ size -= 2;
+ }
+
+ if (URL_Flag) {
+ if (offset >= size) {
+ return ERROR_MALFORMED;
+ }
+ unsigned URLlength = mData[offset];
+ offset += URLlength + 1;
+ size -= URLlength + 1;
+ }
+
+ if (OCRstreamFlag) {
+ offset += 2;
+ size -= 2;
+
+ if ((offset >= size || mData[offset] != kTag_DecoderConfigDescriptor)
+ && offset - 2 < size
+ && mData[offset - 2] == kTag_DecoderConfigDescriptor) {
+ // Content found "in the wild" had OCRstreamFlag set but was
+ // missing OCR_ES_Id, the decoder config descriptor immediately
+ // followed instead.
+ offset -= 2;
+ size += 2;
+
+ ALOGW("Found malformed 'esds' atom, ignoring missing OCR_ES_Id.");
+ }
+ }
+
+ if (offset >= size) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t tag;
+ size_t sub_offset, sub_size;
+ status_t err = skipDescriptorHeader(
+ offset, size, &tag, &sub_offset, &sub_size);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (tag != kTag_DecoderConfigDescriptor) {
+ return ERROR_MALFORMED;
+ }
+
+ err = parseDecoderConfigDescriptor(sub_offset, sub_size);
+
+ return err;
+}
+
+status_t ESDS::parseDecoderConfigDescriptor(size_t offset, size_t size) {
+ if (size < 13) {
+ return ERROR_MALFORMED;
+ }
+
+ mObjectTypeIndication = mData[offset];
+
+ offset += 13;
+ size -= 13;
+
+ if (size == 0) {
+ mDecoderSpecificOffset = 0;
+ mDecoderSpecificLength = 0;
+ return OK;
+ }
+
+ uint8_t tag;
+ size_t sub_offset, sub_size;
+ status_t err = skipDescriptorHeader(
+ offset, size, &tag, &sub_offset, &sub_size);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (tag != kTag_DecoderSpecificInfo) {
+ return ERROR_MALFORMED;
+ }
+
+ mDecoderSpecificOffset = sub_offset;
+ mDecoderSpecificLength = sub_size;
+
+ return OK;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/FLACExtractor.cpp b/media/libstagefright/FLACExtractor.cpp
new file mode 100644
index 0000000..668d7f7
--- /dev/null
+++ b/media/libstagefright/FLACExtractor.cpp
@@ -0,0 +1,813 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "FLACExtractor"
+#include <utils/Log.h>
+
+#include "include/FLACExtractor.h"
+// Vorbis comments
+#include "include/OggExtractor.h"
+// libFLAC parser
+#include "FLAC/stream_decoder.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaBuffer.h>
+
+namespace android {
+
+class FLACParser;
+
+class FLACSource : public MediaSource {
+
+public:
+ FLACSource(
+ const sp<DataSource> &dataSource,
+ const sp<MetaData> &trackMetadata);
+
+ virtual status_t start(MetaData *params);
+ virtual status_t stop();
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+protected:
+ virtual ~FLACSource();
+
+private:
+ sp<DataSource> mDataSource;
+ sp<MetaData> mTrackMetadata;
+ sp<FLACParser> mParser;
+ bool mInitCheck;
+ bool mStarted;
+
+ status_t init();
+
+ // no copy constructor or assignment
+ FLACSource(const FLACSource &);
+ FLACSource &operator=(const FLACSource &);
+
+};
+
+// FLACParser wraps a C libFLAC parser aka stream decoder
+
+class FLACParser : public RefBase {
+
+public:
+ FLACParser(
+ const sp<DataSource> &dataSource,
+ // If metadata pointers aren't provided, we don't fill them
+ const sp<MetaData> &fileMetadata = 0,
+ const sp<MetaData> &trackMetadata = 0);
+
+ status_t initCheck() const {
+ return mInitCheck;
+ }
+
+ // stream properties
+ unsigned getMaxBlockSize() const {
+ return mStreamInfo.max_blocksize;
+ }
+ unsigned getSampleRate() const {
+ return mStreamInfo.sample_rate;
+ }
+ unsigned getChannels() const {
+ return mStreamInfo.channels;
+ }
+ unsigned getBitsPerSample() const {
+ return mStreamInfo.bits_per_sample;
+ }
+ FLAC__uint64 getTotalSamples() const {
+ return mStreamInfo.total_samples;
+ }
+
+ // media buffers
+ void allocateBuffers();
+ void releaseBuffers();
+ MediaBuffer *readBuffer() {
+ return readBuffer(false, 0LL);
+ }
+ MediaBuffer *readBuffer(FLAC__uint64 sample) {
+ return readBuffer(true, sample);
+ }
+
+protected:
+ virtual ~FLACParser();
+
+private:
+ sp<DataSource> mDataSource;
+ sp<MetaData> mFileMetadata;
+ sp<MetaData> mTrackMetadata;
+ bool mInitCheck;
+
+ // media buffers
+ size_t mMaxBufferSize;
+ MediaBufferGroup *mGroup;
+ void (*mCopy)(short *dst, const int *const *src, unsigned nSamples);
+
+ // handle to underlying libFLAC parser
+ FLAC__StreamDecoder *mDecoder;
+
+ // current position within the data source
+ off64_t mCurrentPos;
+ bool mEOF;
+
+ // cached when the STREAMINFO metadata is parsed by libFLAC
+ FLAC__StreamMetadata_StreamInfo mStreamInfo;
+ bool mStreamInfoValid;
+
+ // cached when a decoded PCM block is "written" by libFLAC parser
+ bool mWriteRequested;
+ bool mWriteCompleted;
+ FLAC__FrameHeader mWriteHeader;
+ const FLAC__int32 * const *mWriteBuffer;
+
+ // most recent error reported by libFLAC parser
+ FLAC__StreamDecoderErrorStatus mErrorStatus;
+
+ status_t init();
+ MediaBuffer *readBuffer(bool doSeek, FLAC__uint64 sample);
+
+ // no copy constructor or assignment
+ FLACParser(const FLACParser &);
+ FLACParser &operator=(const FLACParser &);
+
+ // FLAC parser callbacks as C++ instance methods
+ FLAC__StreamDecoderReadStatus readCallback(
+ FLAC__byte buffer[], size_t *bytes);
+ FLAC__StreamDecoderSeekStatus seekCallback(
+ FLAC__uint64 absolute_byte_offset);
+ FLAC__StreamDecoderTellStatus tellCallback(
+ FLAC__uint64 *absolute_byte_offset);
+ FLAC__StreamDecoderLengthStatus lengthCallback(
+ FLAC__uint64 *stream_length);
+ FLAC__bool eofCallback();
+ FLAC__StreamDecoderWriteStatus writeCallback(
+ const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
+ void metadataCallback(const FLAC__StreamMetadata *metadata);
+ void errorCallback(FLAC__StreamDecoderErrorStatus status);
+
+ // FLAC parser callbacks as C-callable functions
+ static FLAC__StreamDecoderReadStatus read_callback(
+ const FLAC__StreamDecoder *decoder,
+ FLAC__byte buffer[], size_t *bytes,
+ void *client_data);
+ static FLAC__StreamDecoderSeekStatus seek_callback(
+ const FLAC__StreamDecoder *decoder,
+ FLAC__uint64 absolute_byte_offset,
+ void *client_data);
+ static FLAC__StreamDecoderTellStatus tell_callback(
+ const FLAC__StreamDecoder *decoder,
+ FLAC__uint64 *absolute_byte_offset,
+ void *client_data);
+ static FLAC__StreamDecoderLengthStatus length_callback(
+ const FLAC__StreamDecoder *decoder,
+ FLAC__uint64 *stream_length,
+ void *client_data);
+ static FLAC__bool eof_callback(
+ const FLAC__StreamDecoder *decoder,
+ void *client_data);
+ static FLAC__StreamDecoderWriteStatus write_callback(
+ const FLAC__StreamDecoder *decoder,
+ const FLAC__Frame *frame, const FLAC__int32 * const buffer[],
+ void *client_data);
+ static void metadata_callback(
+ const FLAC__StreamDecoder *decoder,
+ const FLAC__StreamMetadata *metadata,
+ void *client_data);
+ static void error_callback(
+ const FLAC__StreamDecoder *decoder,
+ FLAC__StreamDecoderErrorStatus status,
+ void *client_data);
+
+};
+
+// The FLAC parser calls our C++ static callbacks using C calling conventions,
+// inside FLAC__stream_decoder_process_until_end_of_metadata
+// and FLAC__stream_decoder_process_single.
+// We immediately then call our corresponding C++ instance methods
+// with the same parameter list, but discard redundant information.
+
+FLAC__StreamDecoderReadStatus FLACParser::read_callback(
+ const FLAC__StreamDecoder *decoder, FLAC__byte buffer[],
+ size_t *bytes, void *client_data)
+{
+ return ((FLACParser *) client_data)->readCallback(buffer, bytes);
+}
+
+FLAC__StreamDecoderSeekStatus FLACParser::seek_callback(
+ const FLAC__StreamDecoder *decoder,
+ FLAC__uint64 absolute_byte_offset, void *client_data)
+{
+ return ((FLACParser *) client_data)->seekCallback(absolute_byte_offset);
+}
+
+FLAC__StreamDecoderTellStatus FLACParser::tell_callback(
+ const FLAC__StreamDecoder *decoder,
+ FLAC__uint64 *absolute_byte_offset, void *client_data)
+{
+ return ((FLACParser *) client_data)->tellCallback(absolute_byte_offset);
+}
+
+FLAC__StreamDecoderLengthStatus FLACParser::length_callback(
+ const FLAC__StreamDecoder *decoder,
+ FLAC__uint64 *stream_length, void *client_data)
+{
+ return ((FLACParser *) client_data)->lengthCallback(stream_length);
+}
+
+FLAC__bool FLACParser::eof_callback(
+ const FLAC__StreamDecoder *decoder, void *client_data)
+{
+ return ((FLACParser *) client_data)->eofCallback();
+}
+
+FLAC__StreamDecoderWriteStatus FLACParser::write_callback(
+ const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame,
+ const FLAC__int32 * const buffer[], void *client_data)
+{
+ return ((FLACParser *) client_data)->writeCallback(frame, buffer);
+}
+
+void FLACParser::metadata_callback(
+ const FLAC__StreamDecoder *decoder,
+ const FLAC__StreamMetadata *metadata, void *client_data)
+{
+ ((FLACParser *) client_data)->metadataCallback(metadata);
+}
+
+void FLACParser::error_callback(
+ const FLAC__StreamDecoder *decoder,
+ FLAC__StreamDecoderErrorStatus status, void *client_data)
+{
+ ((FLACParser *) client_data)->errorCallback(status);
+}
+
+// These are the corresponding callbacks with C++ calling conventions
+
+FLAC__StreamDecoderReadStatus FLACParser::readCallback(
+ FLAC__byte buffer[], size_t *bytes)
+{
+ size_t requested = *bytes;
+ ssize_t actual = mDataSource->readAt(mCurrentPos, buffer, requested);
+ if (0 > actual) {
+ *bytes = 0;
+ return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
+ } else if (0 == actual) {
+ *bytes = 0;
+ mEOF = true;
+ return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+ } else {
+ assert(actual <= requested);
+ *bytes = actual;
+ mCurrentPos += actual;
+ return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+ }
+}
+
+FLAC__StreamDecoderSeekStatus FLACParser::seekCallback(
+ FLAC__uint64 absolute_byte_offset)
+{
+ mCurrentPos = absolute_byte_offset;
+ mEOF = false;
+ return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
+}
+
+FLAC__StreamDecoderTellStatus FLACParser::tellCallback(
+ FLAC__uint64 *absolute_byte_offset)
+{
+ *absolute_byte_offset = mCurrentPos;
+ return FLAC__STREAM_DECODER_TELL_STATUS_OK;
+}
+
+FLAC__StreamDecoderLengthStatus FLACParser::lengthCallback(
+ FLAC__uint64 *stream_length)
+{
+ off64_t size;
+ if (OK == mDataSource->getSize(&size)) {
+ *stream_length = size;
+ return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
+ } else {
+ return FLAC__STREAM_DECODER_LENGTH_STATUS_UNSUPPORTED;
+ }
+}
+
+FLAC__bool FLACParser::eofCallback()
+{
+ return mEOF;
+}
+
+FLAC__StreamDecoderWriteStatus FLACParser::writeCallback(
+ const FLAC__Frame *frame, const FLAC__int32 * const buffer[])
+{
+ if (mWriteRequested) {
+ mWriteRequested = false;
+ // FLAC parser doesn't free or realloc buffer until next frame or finish
+ mWriteHeader = frame->header;
+ mWriteBuffer = buffer;
+ mWriteCompleted = true;
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+ } else {
+ ALOGE("FLACParser::writeCallback unexpected");
+ return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+ }
+}
+
+void FLACParser::metadataCallback(const FLAC__StreamMetadata *metadata)
+{
+ switch (metadata->type) {
+ case FLAC__METADATA_TYPE_STREAMINFO:
+ if (!mStreamInfoValid) {
+ mStreamInfo = metadata->data.stream_info;
+ mStreamInfoValid = true;
+ } else {
+ ALOGE("FLACParser::metadataCallback unexpected STREAMINFO");
+ }
+ break;
+ case FLAC__METADATA_TYPE_VORBIS_COMMENT:
+ {
+ const FLAC__StreamMetadata_VorbisComment *vc;
+ vc = &metadata->data.vorbis_comment;
+ for (FLAC__uint32 i = 0; i < vc->num_comments; ++i) {
+ FLAC__StreamMetadata_VorbisComment_Entry *vce;
+ vce = &vc->comments[i];
+ if (mFileMetadata != 0) {
+ parseVorbisComment(mFileMetadata, (const char *) vce->entry,
+ vce->length);
+ }
+ }
+ }
+ break;
+ case FLAC__METADATA_TYPE_PICTURE:
+ if (mFileMetadata != 0) {
+ const FLAC__StreamMetadata_Picture *p = &metadata->data.picture;
+ mFileMetadata->setData(kKeyAlbumArt,
+ MetaData::TYPE_NONE, p->data, p->data_length);
+ mFileMetadata->setCString(kKeyAlbumArtMIME, p->mime_type);
+ }
+ break;
+ default:
+ ALOGW("FLACParser::metadataCallback unexpected type %u", metadata->type);
+ break;
+ }
+}
+
+void FLACParser::errorCallback(FLAC__StreamDecoderErrorStatus status)
+{
+ ALOGE("FLACParser::errorCallback status=%d", status);
+ mErrorStatus = status;
+}
+
+// Copy samples from FLAC native 32-bit non-interleaved to 16-bit interleaved.
+// These are candidates for optimization if needed.
+
+static void copyMono8(short *dst, const int *const *src, unsigned nSamples)
+{
+ for (unsigned i = 0; i < nSamples; ++i) {
+ *dst++ = src[0][i] << 8;
+ }
+}
+
+static void copyStereo8(short *dst, const int *const *src, unsigned nSamples)
+{
+ for (unsigned i = 0; i < nSamples; ++i) {
+ *dst++ = src[0][i] << 8;
+ *dst++ = src[1][i] << 8;
+ }
+}
+
+static void copyMono16(short *dst, const int *const *src, unsigned nSamples)
+{
+ for (unsigned i = 0; i < nSamples; ++i) {
+ *dst++ = src[0][i];
+ }
+}
+
+static void copyStereo16(short *dst, const int *const *src, unsigned nSamples)
+{
+ for (unsigned i = 0; i < nSamples; ++i) {
+ *dst++ = src[0][i];
+ *dst++ = src[1][i];
+ }
+}
+
+// 24-bit versions should do dithering or noise-shaping, here or in AudioFlinger
+
+static void copyMono24(short *dst, const int *const *src, unsigned nSamples)
+{
+ for (unsigned i = 0; i < nSamples; ++i) {
+ *dst++ = src[0][i] >> 8;
+ }
+}
+
+static void copyStereo24(short *dst, const int *const *src, unsigned nSamples)
+{
+ for (unsigned i = 0; i < nSamples; ++i) {
+ *dst++ = src[0][i] >> 8;
+ *dst++ = src[1][i] >> 8;
+ }
+}
+
+static void copyTrespass(short *dst, const int *const *src, unsigned nSamples)
+{
+ TRESPASS();
+}
+
+// FLACParser
+
+FLACParser::FLACParser(
+ const sp<DataSource> &dataSource,
+ const sp<MetaData> &fileMetadata,
+ const sp<MetaData> &trackMetadata)
+ : mDataSource(dataSource),
+ mFileMetadata(fileMetadata),
+ mTrackMetadata(trackMetadata),
+ mInitCheck(false),
+ mMaxBufferSize(0),
+ mGroup(NULL),
+ mCopy(copyTrespass),
+ mDecoder(NULL),
+ mCurrentPos(0LL),
+ mEOF(false),
+ mStreamInfoValid(false),
+ mWriteRequested(false),
+ mWriteCompleted(false),
+ mWriteBuffer(NULL),
+ mErrorStatus((FLAC__StreamDecoderErrorStatus) -1)
+{
+ ALOGV("FLACParser::FLACParser");
+ memset(&mStreamInfo, 0, sizeof(mStreamInfo));
+ memset(&mWriteHeader, 0, sizeof(mWriteHeader));
+ mInitCheck = init();
+}
+
+FLACParser::~FLACParser()
+{
+ ALOGV("FLACParser::~FLACParser");
+ if (mDecoder != NULL) {
+ FLAC__stream_decoder_delete(mDecoder);
+ mDecoder = NULL;
+ }
+}
+
+status_t FLACParser::init()
+{
+ // setup libFLAC parser
+ mDecoder = FLAC__stream_decoder_new();
+ if (mDecoder == NULL) {
+ // The new should succeed, since probably all it does is a malloc
+ // that always succeeds in Android. But to avoid dependence on the
+ // libFLAC internals, we check and log here.
+ ALOGE("new failed");
+ return NO_INIT;
+ }
+ FLAC__stream_decoder_set_md5_checking(mDecoder, false);
+ FLAC__stream_decoder_set_metadata_ignore_all(mDecoder);
+ FLAC__stream_decoder_set_metadata_respond(
+ mDecoder, FLAC__METADATA_TYPE_STREAMINFO);
+ FLAC__stream_decoder_set_metadata_respond(
+ mDecoder, FLAC__METADATA_TYPE_PICTURE);
+ FLAC__stream_decoder_set_metadata_respond(
+ mDecoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
+ FLAC__StreamDecoderInitStatus initStatus;
+ initStatus = FLAC__stream_decoder_init_stream(
+ mDecoder,
+ read_callback, seek_callback, tell_callback,
+ length_callback, eof_callback, write_callback,
+ metadata_callback, error_callback, (void *) this);
+ if (initStatus != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+ // A failure here probably indicates a programming error and so is
+ // unlikely to happen. But we check and log here similarly to above.
+ ALOGE("init_stream failed %d", initStatus);
+ return NO_INIT;
+ }
+ // parse all metadata
+ if (!FLAC__stream_decoder_process_until_end_of_metadata(mDecoder)) {
+ ALOGE("end_of_metadata failed");
+ return NO_INIT;
+ }
+ if (mStreamInfoValid) {
+ // check channel count
+ switch (getChannels()) {
+ case 1:
+ case 2:
+ break;
+ default:
+ ALOGE("unsupported channel count %u", getChannels());
+ return NO_INIT;
+ }
+ // check bit depth
+ switch (getBitsPerSample()) {
+ case 8:
+ case 16:
+ case 24:
+ break;
+ default:
+ ALOGE("unsupported bits per sample %u", getBitsPerSample());
+ return NO_INIT;
+ }
+ // check sample rate
+ switch (getSampleRate()) {
+ case 8000:
+ case 11025:
+ case 12000:
+ case 16000:
+ case 22050:
+ case 24000:
+ case 32000:
+ case 44100:
+ case 48000:
+ break;
+ default:
+ // 96000 would require a proper downsampler in AudioFlinger
+ ALOGE("unsupported sample rate %u", getSampleRate());
+ return NO_INIT;
+ }
+ // configure the appropriate copy function, defaulting to trespass
+ static const struct {
+ unsigned mChannels;
+ unsigned mBitsPerSample;
+ void (*mCopy)(short *dst, const int *const *src, unsigned nSamples);
+ } table[] = {
+ { 1, 8, copyMono8 },
+ { 2, 8, copyStereo8 },
+ { 1, 16, copyMono16 },
+ { 2, 16, copyStereo16 },
+ { 1, 24, copyMono24 },
+ { 2, 24, copyStereo24 },
+ };
+ for (unsigned i = 0; i < sizeof(table)/sizeof(table[0]); ++i) {
+ if (table[i].mChannels == getChannels() &&
+ table[i].mBitsPerSample == getBitsPerSample()) {
+ mCopy = table[i].mCopy;
+ break;
+ }
+ }
+ // populate track metadata
+ if (mTrackMetadata != 0) {
+ mTrackMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+ mTrackMetadata->setInt32(kKeyChannelCount, getChannels());
+ mTrackMetadata->setInt32(kKeySampleRate, getSampleRate());
+ // sample rate is non-zero, so division by zero not possible
+ mTrackMetadata->setInt64(kKeyDuration,
+ (getTotalSamples() * 1000000LL) / getSampleRate());
+ }
+ } else {
+ ALOGE("missing STREAMINFO");
+ return NO_INIT;
+ }
+ if (mFileMetadata != 0) {
+ mFileMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC);
+ }
+ return OK;
+}
+
+void FLACParser::allocateBuffers()
+{
+ CHECK(mGroup == NULL);
+ mGroup = new MediaBufferGroup;
+ mMaxBufferSize = getMaxBlockSize() * getChannels() * sizeof(short);
+ mGroup->add_buffer(new MediaBuffer(mMaxBufferSize));
+}
+
+void FLACParser::releaseBuffers()
+{
+ CHECK(mGroup != NULL);
+ delete mGroup;
+ mGroup = NULL;
+}
+
+MediaBuffer *FLACParser::readBuffer(bool doSeek, FLAC__uint64 sample)
+{
+ mWriteRequested = true;
+ mWriteCompleted = false;
+ if (doSeek) {
+ // We implement the seek callback, so this works without explicit flush
+ if (!FLAC__stream_decoder_seek_absolute(mDecoder, sample)) {
+ ALOGE("FLACParser::readBuffer seek to sample %llu failed", sample);
+ return NULL;
+ }
+ ALOGV("FLACParser::readBuffer seek to sample %llu succeeded", sample);
+ } else {
+ if (!FLAC__stream_decoder_process_single(mDecoder)) {
+ ALOGE("FLACParser::readBuffer process_single failed");
+ return NULL;
+ }
+ }
+ if (!mWriteCompleted) {
+ ALOGV("FLACParser::readBuffer write did not complete");
+ return NULL;
+ }
+ // verify that block header keeps the promises made by STREAMINFO
+ unsigned blocksize = mWriteHeader.blocksize;
+ if (blocksize == 0 || blocksize > getMaxBlockSize()) {
+ ALOGE("FLACParser::readBuffer write invalid blocksize %u", blocksize);
+ return NULL;
+ }
+ if (mWriteHeader.sample_rate != getSampleRate() ||
+ mWriteHeader.channels != getChannels() ||
+ mWriteHeader.bits_per_sample != getBitsPerSample()) {
+ ALOGE("FLACParser::readBuffer write changed parameters mid-stream");
+ }
+ // acquire a media buffer
+ CHECK(mGroup != NULL);
+ MediaBuffer *buffer;
+ status_t err = mGroup->acquire_buffer(&buffer);
+ if (err != OK) {
+ return NULL;
+ }
+ size_t bufferSize = blocksize * getChannels() * sizeof(short);
+ CHECK(bufferSize <= mMaxBufferSize);
+ short *data = (short *) buffer->data();
+ buffer->set_range(0, bufferSize);
+ // copy PCM from FLAC write buffer to our media buffer, with interleaving
+ (*mCopy)(data, mWriteBuffer, blocksize);
+ // fill in buffer metadata
+ CHECK(mWriteHeader.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
+ FLAC__uint64 sampleNumber = mWriteHeader.number.sample_number;
+ int64_t timeUs = (1000000LL * sampleNumber) / getSampleRate();
+ buffer->meta_data()->setInt64(kKeyTime, timeUs);
+ buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ return buffer;
+}
+
+// FLACsource
+
+FLACSource::FLACSource(
+ const sp<DataSource> &dataSource,
+ const sp<MetaData> &trackMetadata)
+ : mDataSource(dataSource),
+ mTrackMetadata(trackMetadata),
+ mParser(0),
+ mInitCheck(false),
+ mStarted(false)
+{
+ ALOGV("FLACSource::FLACSource");
+ mInitCheck = init();
+}
+
+FLACSource::~FLACSource()
+{
+ ALOGV("~FLACSource::FLACSource");
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t FLACSource::start(MetaData *params)
+{
+ ALOGV("FLACSource::start");
+
+ CHECK(!mStarted);
+ mParser->allocateBuffers();
+ mStarted = true;
+
+ return OK;
+}
+
+status_t FLACSource::stop()
+{
+ ALOGV("FLACSource::stop");
+
+ CHECK(mStarted);
+ mParser->releaseBuffers();
+ mStarted = false;
+
+ return OK;
+}
+
+sp<MetaData> FLACSource::getFormat()
+{
+ return mTrackMetadata;
+}
+
+status_t FLACSource::read(
+ MediaBuffer **outBuffer, const ReadOptions *options)
+{
+ MediaBuffer *buffer;
+ // process an optional seek request
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode mode;
+ if ((NULL != options) && options->getSeekTo(&seekTimeUs, &mode)) {
+ FLAC__uint64 sample;
+ if (seekTimeUs <= 0LL) {
+ sample = 0LL;
+ } else {
+ // sample and total samples are both zero-based, and seek to EOF ok
+ sample = (seekTimeUs * mParser->getSampleRate()) / 1000000LL;
+ if (sample >= mParser->getTotalSamples()) {
+ sample = mParser->getTotalSamples();
+ }
+ }
+ buffer = mParser->readBuffer(sample);
+ // otherwise read sequentially
+ } else {
+ buffer = mParser->readBuffer();
+ }
+ *outBuffer = buffer;
+ return buffer != NULL ? (status_t) OK : (status_t) ERROR_END_OF_STREAM;
+}
+
+status_t FLACSource::init()
+{
+ ALOGV("FLACSource::init");
+ // re-use the same track metadata passed into constructor from FLACExtractor
+ mParser = new FLACParser(mDataSource);
+ return mParser->initCheck();
+}
+
+// FLACExtractor
+
+FLACExtractor::FLACExtractor(
+ const sp<DataSource> &dataSource)
+ : mDataSource(dataSource),
+ mInitCheck(false)
+{
+ ALOGV("FLACExtractor::FLACExtractor");
+ mInitCheck = init();
+}
+
+FLACExtractor::~FLACExtractor()
+{
+ ALOGV("~FLACExtractor::FLACExtractor");
+}
+
+size_t FLACExtractor::countTracks()
+{
+ return mInitCheck == OK ? 1 : 0;
+}
+
+sp<MediaSource> FLACExtractor::getTrack(size_t index)
+{
+ if (mInitCheck != OK || index > 0) {
+ return NULL;
+ }
+ return new FLACSource(mDataSource, mTrackMetadata);
+}
+
+sp<MetaData> FLACExtractor::getTrackMetaData(
+ size_t index, uint32_t flags)
+{
+ if (mInitCheck != OK || index > 0) {
+ return NULL;
+ }
+ return mTrackMetadata;
+}
+
+status_t FLACExtractor::init()
+{
+ mFileMetadata = new MetaData;
+ mTrackMetadata = new MetaData;
+ // FLACParser will fill in the metadata for us
+ mParser = new FLACParser(mDataSource, mFileMetadata, mTrackMetadata);
+ return mParser->initCheck();
+}
+
+sp<MetaData> FLACExtractor::getMetaData()
+{
+ return mFileMetadata;
+}
+
+// Sniffer
+
+bool SniffFLAC(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *)
+{
+ // first 4 is the signature word
+ // second 4 is the sizeof STREAMINFO
+ // 042 is the mandatory STREAMINFO
+ // no need to read rest of the header, as a premature EOF will be caught later
+ uint8_t header[4+4];
+ if (source->readAt(0, header, sizeof(header)) != sizeof(header)
+ || memcmp("fLaC\0\0\0\042", header, 4+4))
+ {
+ return false;
+ }
+
+ *mimeType = MEDIA_MIMETYPE_AUDIO_FLAC;
+ *confidence = 0.5;
+
+ return true;
+}
+
+} // namespace android
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
new file mode 100644
index 0000000..73c8d03
--- /dev/null
+++ b/media/libstagefright/FileSource.cpp
@@ -0,0 +1,187 @@
+/*
+ * 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 <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/FileSource.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+namespace android {
+
+FileSource::FileSource(const char *filename)
+ : mFd(-1),
+ mOffset(0),
+ mLength(-1),
+ mDecryptHandle(NULL),
+ mDrmManagerClient(NULL),
+ mDrmBufOffset(0),
+ mDrmBufSize(0),
+ mDrmBuf(NULL){
+
+ mFd = open(filename, O_LARGEFILE | O_RDONLY);
+}
+
+FileSource::FileSource(int fd, int64_t offset, int64_t length)
+ : mFd(fd),
+ mOffset(offset),
+ mLength(length),
+ mDecryptHandle(NULL),
+ mDrmManagerClient(NULL),
+ mDrmBufOffset(0),
+ mDrmBufSize(0),
+ mDrmBuf(NULL){
+ CHECK(offset >= 0);
+ CHECK(length >= 0);
+}
+
+FileSource::~FileSource() {
+ if (mFd >= 0) {
+ close(mFd);
+ mFd = -1;
+ }
+
+ if (mDrmBuf != NULL) {
+ delete[] mDrmBuf;
+ mDrmBuf = NULL;
+ }
+
+ if (mDecryptHandle != NULL) {
+ // To release mDecryptHandle
+ CHECK(mDrmManagerClient);
+ mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+ mDecryptHandle = NULL;
+ }
+
+ if (mDrmManagerClient != NULL) {
+ delete mDrmManagerClient;
+ mDrmManagerClient = NULL;
+ }
+}
+
+status_t FileSource::initCheck() const {
+ return mFd >= 0 ? OK : NO_INIT;
+}
+
+ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) {
+ if (mFd < 0) {
+ return NO_INIT;
+ }
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (mLength >= 0) {
+ if (offset >= mLength) {
+ return 0; // read beyond EOF.
+ }
+ int64_t numAvailable = mLength - offset;
+ if ((int64_t)size > numAvailable) {
+ size = numAvailable;
+ }
+ }
+
+ if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED
+ == mDecryptHandle->decryptApiType) {
+ return readAtDRM(offset, data, size);
+ } else {
+ off64_t result = lseek64(mFd, offset + mOffset, SEEK_SET);
+ if (result == -1) {
+ ALOGE("seek to %lld failed", offset + mOffset);
+ return UNKNOWN_ERROR;
+ }
+
+ return ::read(mFd, data, size);
+ }
+}
+
+status_t FileSource::getSize(off64_t *size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mFd < 0) {
+ return NO_INIT;
+ }
+
+ if (mLength >= 0) {
+ *size = mLength;
+
+ return OK;
+ }
+
+ *size = lseek64(mFd, 0, SEEK_END);
+
+ return OK;
+}
+
+sp<DecryptHandle> FileSource::DrmInitialization(const char *mime) {
+ if (mDrmManagerClient == NULL) {
+ mDrmManagerClient = new DrmManagerClient();
+ }
+
+ if (mDrmManagerClient == NULL) {
+ return NULL;
+ }
+
+ if (mDecryptHandle == NULL) {
+ mDecryptHandle = mDrmManagerClient->openDecryptSession(
+ mFd, mOffset, mLength, mime);
+ }
+
+ if (mDecryptHandle == NULL) {
+ delete mDrmManagerClient;
+ mDrmManagerClient = NULL;
+ }
+
+ return mDecryptHandle;
+}
+
+void FileSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
+ handle = mDecryptHandle;
+
+ *client = mDrmManagerClient;
+}
+
+ssize_t FileSource::readAtDRM(off64_t offset, void *data, size_t size) {
+ size_t DRM_CACHE_SIZE = 1024;
+ if (mDrmBuf == NULL) {
+ mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
+ }
+
+ if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
+ && (offset + mOffset + size) <= (mDrmBufOffset + mDrmBufSize)) {
+ /* Use buffered data */
+ memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
+ return size;
+ } else if (size <= DRM_CACHE_SIZE) {
+ /* Buffer new data */
+ mDrmBufOffset = offset + mOffset;
+ mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf,
+ DRM_CACHE_SIZE, offset + mOffset);
+ if (mDrmBufSize > 0) {
+ int64_t dataRead = 0;
+ dataRead = size > mDrmBufSize ? mDrmBufSize : size;
+ memcpy(data, (void*)mDrmBuf, dataRead);
+ return dataRead;
+ } else {
+ return mDrmBufSize;
+ }
+ } else {
+ /* Too big chunk to cache. Call DRM directly */
+ return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
+ }
+}
+} // namespace android
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
new file mode 100644
index 0000000..d7eea3f
--- /dev/null
+++ b/media/libstagefright/HTTPBase.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "HTTPBase"
+#include <utils/Log.h>
+
+#include "include/HTTPBase.h"
+
+#if CHROMIUM_AVAILABLE
+#include "include/ChromiumHTTPDataSource.h"
+#endif
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+
+#include <cutils/properties.h>
+#include <cutils/qtaguid.h>
+
+namespace android {
+
+HTTPBase::HTTPBase()
+ : mNumBandwidthHistoryItems(0),
+ mTotalTransferTimeUs(0),
+ mTotalTransferBytes(0),
+ mPrevBandwidthMeasureTimeUs(0),
+ mPrevEstimatedBandWidthKbps(0),
+ mBandWidthCollectFreqMs(5000),
+ mUIDValid(false),
+ mUID(0) {
+}
+
+// static
+sp<HTTPBase> HTTPBase::Create(uint32_t flags) {
+#if CHROMIUM_AVAILABLE
+ return new ChromiumHTTPDataSource(flags);
+#endif
+ {
+ TRESPASS();
+
+ return NULL;
+ }
+}
+
+void HTTPBase::addBandwidthMeasurement(
+ size_t numBytes, int64_t delayUs) {
+ Mutex::Autolock autoLock(mLock);
+
+ BandwidthEntry entry;
+ entry.mDelayUs = delayUs;
+ entry.mNumBytes = numBytes;
+ mTotalTransferTimeUs += delayUs;
+ mTotalTransferBytes += numBytes;
+
+ mBandwidthHistory.push_back(entry);
+ if (++mNumBandwidthHistoryItems > 100) {
+ BandwidthEntry *entry = &*mBandwidthHistory.begin();
+ mTotalTransferTimeUs -= entry->mDelayUs;
+ mTotalTransferBytes -= entry->mNumBytes;
+ mBandwidthHistory.erase(mBandwidthHistory.begin());
+ --mNumBandwidthHistoryItems;
+
+ int64_t timeNowUs = ALooper::GetNowUs();
+ if (timeNowUs - mPrevBandwidthMeasureTimeUs >=
+ mBandWidthCollectFreqMs * 1000LL) {
+
+ if (mPrevBandwidthMeasureTimeUs != 0) {
+ mPrevEstimatedBandWidthKbps =
+ (mTotalTransferBytes * 8E3 / mTotalTransferTimeUs);
+ }
+ mPrevBandwidthMeasureTimeUs = timeNowUs;
+ }
+ }
+
+}
+
+bool HTTPBase::estimateBandwidth(int32_t *bandwidth_bps) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mNumBandwidthHistoryItems < 2) {
+ return false;
+ }
+
+ *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
+
+ return true;
+}
+
+status_t HTTPBase::getEstimatedBandwidthKbps(int32_t *kbps) {
+ Mutex::Autolock autoLock(mLock);
+ *kbps = mPrevEstimatedBandWidthKbps;
+ return OK;
+}
+
+status_t HTTPBase::setBandwidthStatCollectFreq(int32_t freqMs) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (freqMs < kMinBandwidthCollectFreqMs
+ || freqMs > kMaxBandwidthCollectFreqMs) {
+
+ ALOGE("frequency (%d ms) is out of range [1000, 60000]", freqMs);
+ return BAD_VALUE;
+ }
+
+ ALOGI("frequency set to %d ms", freqMs);
+ mBandWidthCollectFreqMs = freqMs;
+ return OK;
+}
+
+void HTTPBase::setUID(uid_t uid) {
+ mUIDValid = true;
+ mUID = uid;
+}
+
+bool HTTPBase::getUID(uid_t *uid) const {
+ if (!mUIDValid) {
+ return false;
+ }
+
+ *uid = mUID;
+
+ return true;
+}
+
+// static
+void HTTPBase::RegisterSocketUserTag(int sockfd, uid_t uid, uint32_t kTag) {
+ int res = qtaguid_tagSocket(sockfd, kTag, uid);
+ if (res != 0) {
+ ALOGE("Failed tagging socket %d for uid %d (My UID=%d)", sockfd, uid, geteuid());
+ }
+}
+
+// static
+void HTTPBase::UnRegisterSocketUserTag(int sockfd) {
+ int res = qtaguid_untagSocket(sockfd);
+ if (res != 0) {
+ ALOGE("Failed untagging socket %d (My UID=%d)", sockfd, geteuid());
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/JPEGSource.cpp b/media/libstagefright/JPEGSource.cpp
new file mode 100644
index 0000000..bafa4b2
--- /dev/null
+++ b/media/libstagefright/JPEGSource.cpp
@@ -0,0 +1,234 @@
+/*
+ * 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 "JPEGSource"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/JPEGSource.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+
+#define JPEG_SOF0 0xC0 /* nStart Of Frame N*/
+#define JPEG_SOF1 0xC1 /* N indicates which compression process*/
+#define JPEG_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use*/
+#define JPEG_SOF3 0xC3
+#define JPEG_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers*/
+#define JPEG_SOF6 0xC6
+#define JPEG_SOF7 0xC7
+#define JPEG_SOF9 0xC9
+#define JPEG_SOF10 0xCA
+#define JPEG_SOF11 0xCB
+#define JPEG_SOF13 0xCD
+#define JPEG_SOF14 0xCE
+#define JPEG_SOF15 0xCF
+#define JPEG_SOI 0xD8 /* nStart Of Image (beginning of datastream)*/
+#define JPEG_EOI 0xD9 /* End Of Image (end of datastream)*/
+#define JPEG_SOS 0xDA /* nStart Of Scan (begins compressed data)*/
+#define JPEG_JFIF 0xE0 /* Jfif marker*/
+#define JPEG_EXIF 0xE1 /* Exif marker*/
+#define JPEG_COM 0xFE /* COMment */
+#define JPEG_DQT 0xDB
+#define JPEG_DHT 0xC4
+#define JPEG_DRI 0xDD
+
+namespace android {
+
+JPEGSource::JPEGSource(const sp<DataSource> &source)
+ : mSource(source),
+ mGroup(NULL),
+ mStarted(false),
+ mSize(0),
+ mWidth(0),
+ mHeight(0),
+ mOffset(0) {
+ CHECK_EQ(parseJPEG(), (status_t)OK);
+ CHECK(mSource->getSize(&mSize) == OK);
+}
+
+JPEGSource::~JPEGSource() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t JPEGSource::start(MetaData *) {
+ if (mStarted) {
+ return UNKNOWN_ERROR;
+ }
+
+ mGroup = new MediaBufferGroup;
+ mGroup->add_buffer(new MediaBuffer(mSize));
+
+ mOffset = 0;
+
+ mStarted = true;
+
+ return OK;
+}
+
+status_t JPEGSource::stop() {
+ if (!mStarted) {
+ return UNKNOWN_ERROR;
+ }
+
+ delete mGroup;
+ mGroup = NULL;
+
+ mStarted = false;
+
+ return OK;
+}
+
+sp<MetaData> JPEGSource::getFormat() {
+ sp<MetaData> meta = new MetaData;
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_IMAGE_JPEG);
+ meta->setInt32(kKeyWidth, mWidth);
+ meta->setInt32(kKeyHeight, mHeight);
+ meta->setInt32(kKeyMaxInputSize, mSize);
+
+ return meta;
+}
+
+status_t JPEGSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode mode;
+ if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
+ return UNKNOWN_ERROR;
+ }
+
+ MediaBuffer *buffer;
+ mGroup->acquire_buffer(&buffer);
+
+ ssize_t n = mSource->readAt(mOffset, buffer->data(), mSize - mOffset);
+
+ if (n <= 0) {
+ buffer->release();
+ buffer = NULL;
+
+ return UNKNOWN_ERROR;
+ }
+
+ buffer->set_range(0, n);
+
+ mOffset += n;
+
+ *out = buffer;
+
+ return OK;
+}
+
+status_t JPEGSource::parseJPEG() {
+ mWidth = 0;
+ mHeight = 0;
+
+ off64_t i = 0;
+
+ uint16_t soi;
+ if (!mSource->getUInt16(i, &soi)) {
+ return ERROR_IO;
+ }
+
+ i += 2;
+
+ if (soi != 0xffd8) {
+ return UNKNOWN_ERROR;
+ }
+
+ for (;;) {
+ uint8_t marker;
+ if (mSource->readAt(i++, &marker, 1) != 1) {
+ return ERROR_IO;
+ }
+
+ CHECK_EQ(marker, 0xff);
+
+ if (mSource->readAt(i++, &marker, 1) != 1) {
+ return ERROR_IO;
+ }
+
+ CHECK(marker != 0xff);
+
+ uint16_t chunkSize;
+ if (!mSource->getUInt16(i, &chunkSize)) {
+ return ERROR_IO;
+ }
+
+ i += 2;
+
+ if (chunkSize < 2) {
+ return UNKNOWN_ERROR;
+ }
+
+ switch (marker) {
+ case JPEG_SOS:
+ {
+ return (mWidth > 0 && mHeight > 0) ? OK : UNKNOWN_ERROR;
+ }
+
+ case JPEG_EOI:
+ {
+ return UNKNOWN_ERROR;
+ }
+
+ case JPEG_SOF0:
+ case JPEG_SOF1:
+ case JPEG_SOF3:
+ case JPEG_SOF5:
+ case JPEG_SOF6:
+ case JPEG_SOF7:
+ case JPEG_SOF9:
+ case JPEG_SOF10:
+ case JPEG_SOF11:
+ case JPEG_SOF13:
+ case JPEG_SOF14:
+ case JPEG_SOF15:
+ {
+ uint16_t width, height;
+ if (!mSource->getUInt16(i + 1, &height)
+ || !mSource->getUInt16(i + 3, &width)) {
+ return ERROR_IO;
+ }
+
+ mWidth = width;
+ mHeight = height;
+
+ i += chunkSize - 2;
+ break;
+ }
+
+ default:
+ {
+ // Skip chunk
+
+ i += chunkSize - 2;
+
+ break;
+ }
+ }
+ }
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
new file mode 100644
index 0000000..6abaf23
--- /dev/null
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -0,0 +1,661 @@
+/*
+ * 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 "MP3Extractor"
+#include <utils/Log.h>
+
+#include "include/MP3Extractor.h"
+
+#include "include/avc_utils.h"
+#include "include/ID3.h"
+#include "include/VBRISeeker.h"
+#include "include/XINGSeeker.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// Everything must match except for
+// protection, bitrate, padding, private bits, mode, mode extension,
+// copyright bit, original bit and emphasis.
+// Yes ... there are things that must indeed match...
+static const uint32_t kMask = 0xfffe0c00;
+
+static bool Resync(
+ const sp<DataSource> &source, uint32_t match_header,
+ off64_t *inout_pos, off64_t *post_id3_pos, uint32_t *out_header) {
+ if (post_id3_pos != NULL) {
+ *post_id3_pos = 0;
+ }
+
+ if (*inout_pos == 0) {
+ // Skip an optional ID3 header if syncing at the very beginning
+ // of the datasource.
+
+ for (;;) {
+ uint8_t id3header[10];
+ if (source->readAt(*inout_pos, id3header, sizeof(id3header))
+ < (ssize_t)sizeof(id3header)) {
+ // If we can't even read these 10 bytes, we might as well bail
+ // out, even if there _were_ 10 bytes of valid mp3 audio data...
+ return false;
+ }
+
+ if (memcmp("ID3", id3header, 3)) {
+ break;
+ }
+
+ // Skip the ID3v2 header.
+
+ size_t len =
+ ((id3header[6] & 0x7f) << 21)
+ | ((id3header[7] & 0x7f) << 14)
+ | ((id3header[8] & 0x7f) << 7)
+ | (id3header[9] & 0x7f);
+
+ len += 10;
+
+ *inout_pos += len;
+
+ ALOGV("skipped ID3 tag, new starting offset is %lld (0x%016llx)",
+ *inout_pos, *inout_pos);
+ }
+
+ if (post_id3_pos != NULL) {
+ *post_id3_pos = *inout_pos;
+ }
+ }
+
+ off64_t pos = *inout_pos;
+ bool valid = false;
+
+ const size_t kMaxReadBytes = 1024;
+ const size_t kMaxBytesChecked = 128 * 1024;
+ uint8_t buf[kMaxReadBytes];
+ ssize_t bytesToRead = kMaxReadBytes;
+ ssize_t totalBytesRead = 0;
+ ssize_t remainingBytes = 0;
+ bool reachEOS = false;
+ uint8_t *tmp = buf;
+
+ do {
+ if (pos >= *inout_pos + kMaxBytesChecked) {
+ // Don't scan forever.
+ ALOGV("giving up at offset %lld", pos);
+ break;
+ }
+
+ if (remainingBytes < 4) {
+ if (reachEOS) {
+ break;
+ } else {
+ memcpy(buf, tmp, remainingBytes);
+ bytesToRead = kMaxReadBytes - remainingBytes;
+
+ /*
+ * The next read position should start from the end of
+ * the last buffer, and thus should include the remaining
+ * bytes in the buffer.
+ */
+ totalBytesRead = source->readAt(pos + remainingBytes,
+ buf + remainingBytes,
+ bytesToRead);
+ if (totalBytesRead <= 0) {
+ break;
+ }
+ reachEOS = (totalBytesRead != bytesToRead);
+ totalBytesRead += remainingBytes;
+ remainingBytes = totalBytesRead;
+ tmp = buf;
+ continue;
+ }
+ }
+
+ uint32_t header = U32_AT(tmp);
+
+ if (match_header != 0 && (header & kMask) != (match_header & kMask)) {
+ ++pos;
+ ++tmp;
+ --remainingBytes;
+ continue;
+ }
+
+ size_t frame_size;
+ int sample_rate, num_channels, bitrate;
+ if (!GetMPEGAudioFrameSize(
+ header, &frame_size,
+ &sample_rate, &num_channels, &bitrate)) {
+ ++pos;
+ ++tmp;
+ --remainingBytes;
+ continue;
+ }
+
+ ALOGV("found possible 1st frame at %lld (header = 0x%08x)", pos, header);
+
+ // We found what looks like a valid frame,
+ // now find its successors.
+
+ off64_t test_pos = pos + frame_size;
+
+ valid = true;
+ for (int j = 0; j < 3; ++j) {
+ uint8_t tmp[4];
+ if (source->readAt(test_pos, tmp, 4) < 4) {
+ valid = false;
+ break;
+ }
+
+ uint32_t test_header = U32_AT(tmp);
+
+ ALOGV("subsequent header is %08x", test_header);
+
+ if ((test_header & kMask) != (header & kMask)) {
+ valid = false;
+ break;
+ }
+
+ size_t test_frame_size;
+ if (!GetMPEGAudioFrameSize(
+ test_header, &test_frame_size)) {
+ valid = false;
+ break;
+ }
+
+ ALOGV("found subsequent frame #%d at %lld", j + 2, test_pos);
+
+ test_pos += test_frame_size;
+ }
+
+ if (valid) {
+ *inout_pos = pos;
+
+ if (out_header != NULL) {
+ *out_header = header;
+ }
+ } else {
+ ALOGV("no dice, no valid sequence of frames found.");
+ }
+
+ ++pos;
+ ++tmp;
+ --remainingBytes;
+ } while (!valid);
+
+ return valid;
+}
+
+class MP3Source : public MediaSource {
+public:
+ MP3Source(
+ const sp<MetaData> &meta, const sp<DataSource> &source,
+ off64_t first_frame_pos, uint32_t fixed_header,
+ const sp<MP3Seeker> &seeker);
+
+ 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);
+
+protected:
+ virtual ~MP3Source();
+
+private:
+ sp<MetaData> mMeta;
+ sp<DataSource> mDataSource;
+ off64_t mFirstFramePos;
+ uint32_t mFixedHeader;
+ off64_t mCurrentPos;
+ int64_t mCurrentTimeUs;
+ bool mStarted;
+ sp<MP3Seeker> mSeeker;
+ MediaBufferGroup *mGroup;
+
+ int64_t mBasisTimeUs;
+ int64_t mSamplesRead;
+
+ MP3Source(const MP3Source &);
+ MP3Source &operator=(const MP3Source &);
+};
+
+MP3Extractor::MP3Extractor(
+ const sp<DataSource> &source, const sp<AMessage> &meta)
+ : mInitCheck(NO_INIT),
+ mDataSource(source),
+ mFirstFramePos(-1),
+ mFixedHeader(0) {
+ off64_t pos = 0;
+ off64_t post_id3_pos;
+ uint32_t header;
+ bool success;
+
+ int64_t meta_offset;
+ uint32_t meta_header;
+ int64_t meta_post_id3_offset;
+ if (meta != NULL
+ && meta->findInt64("offset", &meta_offset)
+ && meta->findInt32("header", (int32_t *)&meta_header)
+ && meta->findInt64("post-id3-offset", &meta_post_id3_offset)) {
+ // The sniffer has already done all the hard work for us, simply
+ // accept its judgement.
+ pos = (off64_t)meta_offset;
+ header = meta_header;
+ post_id3_pos = (off64_t)meta_post_id3_offset;
+
+ success = true;
+ } else {
+ success = Resync(mDataSource, 0, &pos, &post_id3_pos, &header);
+ }
+
+ if (!success) {
+ // mInitCheck will remain NO_INIT
+ return;
+ }
+
+ mFirstFramePos = pos;
+ mFixedHeader = header;
+
+ size_t frame_size;
+ int sample_rate;
+ int num_channels;
+ int bitrate;
+ GetMPEGAudioFrameSize(
+ header, &frame_size, &sample_rate, &num_channels, &bitrate);
+
+ unsigned layer = 4 - ((header >> 17) & 3);
+
+ mMeta = new MetaData;
+
+ switch (layer) {
+ case 1:
+ mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I);
+ break;
+ case 2:
+ mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
+ break;
+ case 3:
+ mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+ break;
+ default:
+ TRESPASS();
+ }
+
+ mMeta->setInt32(kKeySampleRate, sample_rate);
+ mMeta->setInt32(kKeyBitRate, bitrate * 1000);
+ mMeta->setInt32(kKeyChannelCount, num_channels);
+
+ sp<XINGSeeker> seeker = XINGSeeker::CreateFromSource(mDataSource, mFirstFramePos);
+
+ if (seeker == NULL) {
+ mSeeker = VBRISeeker::CreateFromSource(mDataSource, post_id3_pos);
+ } else {
+ mSeeker = seeker;
+ int encd = seeker->getEncoderDelay();
+ int encp = seeker->getEncoderPadding();
+ if (encd != 0 || encp != 0) {
+ mMeta->setInt32(kKeyEncoderDelay, encd);
+ mMeta->setInt32(kKeyEncoderPadding, encp);
+ }
+ }
+
+ if (mSeeker != NULL) {
+ // While it is safe to send the XING/VBRI frame to the decoder, this will
+ // result in an extra 1152 samples being output. The real first frame to
+ // decode is after the XING/VBRI frame, so skip there.
+ mFirstFramePos += frame_size;
+ }
+
+ int64_t durationUs;
+
+ if (mSeeker == NULL || !mSeeker->getDuration(&durationUs)) {
+ off64_t fileSize;
+ if (mDataSource->getSize(&fileSize) == OK) {
+ durationUs = 8000LL * (fileSize - mFirstFramePos) / bitrate;
+ } else {
+ durationUs = -1;
+ }
+ }
+
+ if (durationUs >= 0) {
+ mMeta->setInt64(kKeyDuration, durationUs);
+ }
+
+ mInitCheck = OK;
+
+ // get iTunes-style gapless info if present
+ ID3 id3(mDataSource);
+ if (id3.isValid()) {
+ ID3::Iterator *com = new ID3::Iterator(id3, "COM");
+ if (com->done()) {
+ delete com;
+ com = new ID3::Iterator(id3, "COMM");
+ }
+ while(!com->done()) {
+ String8 commentdesc;
+ String8 commentvalue;
+ com->getString(&commentdesc, &commentvalue);
+ const char * desc = commentdesc.string();
+ const char * value = commentvalue.string();
+
+ // first 3 characters are the language, which we don't care about
+ if(strlen(desc) > 3 && strcmp(desc + 3, "iTunSMPB") == 0) {
+
+ int32_t delay, padding;
+ if (sscanf(value, " %*x %x %x %*x", &delay, &padding) == 2) {
+ mMeta->setInt32(kKeyEncoderDelay, delay);
+ mMeta->setInt32(kKeyEncoderPadding, padding);
+ }
+ break;
+ }
+ com->next();
+ }
+ delete com;
+ com = NULL;
+ }
+}
+
+size_t MP3Extractor::countTracks() {
+ return mInitCheck != OK ? 0 : 1;
+}
+
+sp<MediaSource> MP3Extractor::getTrack(size_t index) {
+ if (mInitCheck != OK || index != 0) {
+ return NULL;
+ }
+
+ return new MP3Source(
+ mMeta, mDataSource, mFirstFramePos, mFixedHeader,
+ mSeeker);
+}
+
+sp<MetaData> MP3Extractor::getTrackMetaData(size_t index, uint32_t flags) {
+ if (mInitCheck != OK || index != 0) {
+ return NULL;
+ }
+
+ return mMeta;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MP3Source::MP3Source(
+ const sp<MetaData> &meta, const sp<DataSource> &source,
+ off64_t first_frame_pos, uint32_t fixed_header,
+ const sp<MP3Seeker> &seeker)
+ : mMeta(meta),
+ mDataSource(source),
+ mFirstFramePos(first_frame_pos),
+ mFixedHeader(fixed_header),
+ mCurrentPos(0),
+ mCurrentTimeUs(0),
+ mStarted(false),
+ mSeeker(seeker),
+ mGroup(NULL),
+ mBasisTimeUs(0),
+ mSamplesRead(0) {
+}
+
+MP3Source::~MP3Source() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t MP3Source::start(MetaData *) {
+ CHECK(!mStarted);
+
+ mGroup = new MediaBufferGroup;
+
+ const size_t kMaxFrameSize = 32768;
+ mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
+
+ mCurrentPos = mFirstFramePos;
+ mCurrentTimeUs = 0;
+
+ mBasisTimeUs = mCurrentTimeUs;
+ mSamplesRead = 0;
+
+ mStarted = true;
+
+ return OK;
+}
+
+status_t MP3Source::stop() {
+ CHECK(mStarted);
+
+ delete mGroup;
+ mGroup = NULL;
+
+ mStarted = false;
+
+ return OK;
+}
+
+sp<MetaData> MP3Source::getFormat() {
+ return mMeta;
+}
+
+status_t MP3Source::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode mode;
+ bool seekCBR = false;
+
+ if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
+ int64_t actualSeekTimeUs = seekTimeUs;
+ if (mSeeker == NULL
+ || !mSeeker->getOffsetForTime(&actualSeekTimeUs, &mCurrentPos)) {
+ int32_t bitrate;
+ if (!mMeta->findInt32(kKeyBitRate, &bitrate)) {
+ // bitrate is in bits/sec.
+ ALOGI("no bitrate");
+
+ return ERROR_UNSUPPORTED;
+ }
+
+ mCurrentTimeUs = seekTimeUs;
+ mCurrentPos = mFirstFramePos + seekTimeUs * bitrate / 8000000;
+ seekCBR = true;
+ } else {
+ mCurrentTimeUs = actualSeekTimeUs;
+ }
+
+ mBasisTimeUs = mCurrentTimeUs;
+ mSamplesRead = 0;
+ }
+
+ MediaBuffer *buffer;
+ status_t err = mGroup->acquire_buffer(&buffer);
+ if (err != OK) {
+ return err;
+ }
+
+ size_t frame_size;
+ int bitrate;
+ int num_samples;
+ int sample_rate;
+ for (;;) {
+ ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4);
+ if (n < 4) {
+ buffer->release();
+ buffer = NULL;
+
+ return ERROR_END_OF_STREAM;
+ }
+
+ uint32_t header = U32_AT((const uint8_t *)buffer->data());
+
+ if ((header & kMask) == (mFixedHeader & kMask)
+ && GetMPEGAudioFrameSize(
+ header, &frame_size, &sample_rate, NULL,
+ &bitrate, &num_samples)) {
+
+ // re-calculate mCurrentTimeUs because we might have called Resync()
+ if (seekCBR) {
+ mCurrentTimeUs = (mCurrentPos - mFirstFramePos) * 8000 / bitrate;
+ mBasisTimeUs = mCurrentTimeUs;
+ }
+
+ break;
+ }
+
+ // Lost sync.
+ ALOGV("lost sync! header = 0x%08x, old header = 0x%08x\n", header, mFixedHeader);
+
+ off64_t pos = mCurrentPos;
+ if (!Resync(mDataSource, mFixedHeader, &pos, NULL, NULL)) {
+ ALOGE("Unable to resync. Signalling end of stream.");
+
+ buffer->release();
+ buffer = NULL;
+
+ return ERROR_END_OF_STREAM;
+ }
+
+ mCurrentPos = pos;
+
+ // Try again with the new position.
+ }
+
+ CHECK(frame_size <= buffer->size());
+
+ ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), frame_size);
+ if (n < (ssize_t)frame_size) {
+ buffer->release();
+ buffer = NULL;
+
+ return ERROR_END_OF_STREAM;
+ }
+
+ buffer->set_range(0, frame_size);
+
+ buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
+ buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+
+ mCurrentPos += frame_size;
+
+ mSamplesRead += num_samples;
+ mCurrentTimeUs = mBasisTimeUs + ((mSamplesRead * 1000000) / sample_rate);
+
+ *out = buffer;
+
+ return OK;
+}
+
+sp<MetaData> MP3Extractor::getMetaData() {
+ sp<MetaData> meta = new MetaData;
+
+ if (mInitCheck != OK) {
+ return meta;
+ }
+
+ meta->setCString(kKeyMIMEType, "audio/mpeg");
+
+ ID3 id3(mDataSource);
+
+ if (!id3.isValid()) {
+ return meta;
+ }
+
+ struct Map {
+ int key;
+ const char *tag1;
+ const char *tag2;
+ };
+ static const Map kMap[] = {
+ { kKeyAlbum, "TALB", "TAL" },
+ { kKeyArtist, "TPE1", "TP1" },
+ { kKeyAlbumArtist, "TPE2", "TP2" },
+ { kKeyComposer, "TCOM", "TCM" },
+ { kKeyGenre, "TCON", "TCO" },
+ { kKeyTitle, "TIT2", "TT2" },
+ { kKeyYear, "TYE", "TYER" },
+ { kKeyAuthor, "TXT", "TEXT" },
+ { kKeyCDTrackNumber, "TRK", "TRCK" },
+ { kKeyDiscNumber, "TPA", "TPOS" },
+ { kKeyCompilation, "TCP", "TCMP" },
+ };
+ static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
+
+ for (size_t i = 0; i < kNumMapEntries; ++i) {
+ ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
+ if (it->done()) {
+ delete it;
+ it = new ID3::Iterator(id3, kMap[i].tag2);
+ }
+
+ if (it->done()) {
+ delete it;
+ continue;
+ }
+
+ String8 s;
+ it->getString(&s);
+ delete it;
+
+ meta->setCString(kMap[i].key, s);
+ }
+
+ size_t dataSize;
+ String8 mime;
+ const void *data = id3.getAlbumArt(&dataSize, &mime);
+
+ if (data) {
+ meta->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
+ meta->setCString(kKeyAlbumArtMIME, mime.string());
+ }
+
+ return meta;
+}
+
+bool SniffMP3(
+ const sp<DataSource> &source, String8 *mimeType,
+ float *confidence, sp<AMessage> *meta) {
+ off64_t pos = 0;
+ off64_t post_id3_pos;
+ uint32_t header;
+ if (!Resync(source, 0, &pos, &post_id3_pos, &header)) {
+ return false;
+ }
+
+ *meta = new AMessage;
+ (*meta)->setInt64("offset", pos);
+ (*meta)->setInt32("header", header);
+ (*meta)->setInt64("post-id3-offset", post_id3_pos);
+
+ *mimeType = MEDIA_MIMETYPE_AUDIO_MPEG;
+ *confidence = 0.2f;
+
+ return true;
+}
+
+} // namespace android
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
new file mode 100644
index 0000000..f702376
--- /dev/null
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -0,0 +1,968 @@
+/*
+ * 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 "MPEG2TSWriter"
+#include <media/stagefright/foundation/ADebug.h>
+
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MPEG2TSWriter.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include "include/ESDS.h"
+
+namespace android {
+
+struct MPEG2TSWriter::SourceInfo : public AHandler {
+ SourceInfo(const sp<MediaSource> &source);
+
+ void start(const sp<AMessage> &notify);
+ void stop();
+
+ unsigned streamType() const;
+ unsigned incrementContinuityCounter();
+
+ void readMore();
+
+ enum {
+ kNotifyStartFailed,
+ kNotifyBuffer,
+ kNotifyReachedEOS,
+ };
+
+ sp<ABuffer> lastAccessUnit();
+ int64_t lastAccessUnitTimeUs();
+ void setLastAccessUnit(const sp<ABuffer> &accessUnit);
+
+ void setEOSReceived();
+ bool eosReceived() const;
+
+protected:
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+ virtual ~SourceInfo();
+
+private:
+ enum {
+ kWhatStart = 'strt',
+ kWhatRead = 'read',
+ };
+
+ sp<MediaSource> mSource;
+ sp<ALooper> mLooper;
+ sp<AMessage> mNotify;
+
+ sp<ABuffer> mAACCodecSpecificData;
+
+ sp<ABuffer> mAACBuffer;
+
+ sp<ABuffer> mLastAccessUnit;
+ bool mEOSReceived;
+
+ unsigned mStreamType;
+ unsigned mContinuityCounter;
+
+ void extractCodecSpecificData();
+
+ bool appendAACFrames(MediaBuffer *buffer);
+ bool flushAACFrames();
+
+ void postAVCFrame(MediaBuffer *buffer);
+
+ DISALLOW_EVIL_CONSTRUCTORS(SourceInfo);
+};
+
+MPEG2TSWriter::SourceInfo::SourceInfo(const sp<MediaSource> &source)
+ : mSource(source),
+ mLooper(new ALooper),
+ mEOSReceived(false),
+ mStreamType(0),
+ mContinuityCounter(0) {
+ mLooper->setName("MPEG2TSWriter source");
+
+ sp<MetaData> meta = mSource->getFormat();
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+ mStreamType = 0x0f;
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ mStreamType = 0x1b;
+ } else {
+ TRESPASS();
+ }
+}
+
+MPEG2TSWriter::SourceInfo::~SourceInfo() {
+}
+
+unsigned MPEG2TSWriter::SourceInfo::streamType() const {
+ return mStreamType;
+}
+
+unsigned MPEG2TSWriter::SourceInfo::incrementContinuityCounter() {
+ if (++mContinuityCounter == 16) {
+ mContinuityCounter = 0;
+ }
+
+ return mContinuityCounter;
+}
+
+void MPEG2TSWriter::SourceInfo::start(const sp<AMessage> &notify) {
+ mLooper->registerHandler(this);
+ mLooper->start();
+
+ mNotify = notify;
+
+ (new AMessage(kWhatStart, id()))->post();
+}
+
+void MPEG2TSWriter::SourceInfo::stop() {
+ mLooper->unregisterHandler(id());
+ mLooper->stop();
+
+ mSource->stop();
+}
+
+void MPEG2TSWriter::SourceInfo::extractCodecSpecificData() {
+ sp<MetaData> meta = mSource->getFormat();
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (!meta->findData(kKeyESDS, &type, &data, &size)) {
+ // Codec specific data better be in the first data buffer.
+ return;
+ }
+
+ ESDS esds((const char *)data, size);
+ CHECK_EQ(esds.InitCheck(), (status_t)OK);
+
+ const uint8_t *codec_specific_data;
+ size_t codec_specific_data_size;
+ esds.getCodecSpecificInfo(
+ (const void **)&codec_specific_data, &codec_specific_data_size);
+
+ CHECK_GE(codec_specific_data_size, 2u);
+
+ mAACCodecSpecificData = new ABuffer(codec_specific_data_size);
+
+ memcpy(mAACCodecSpecificData->data(), codec_specific_data,
+ codec_specific_data_size);
+
+ return;
+ }
+
+ if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ return;
+ }
+
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (!meta->findData(kKeyAVCC, &type, &data, &size)) {
+ // Codec specific data better be part of the data stream then.
+ return;
+ }
+
+ sp<ABuffer> out = new ABuffer(1024);
+ out->setRange(0, 0);
+
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ size_t numSeqParameterSets = ptr[5] & 31;
+
+ ptr += 6;
+ size -= 6;
+
+ for (size_t i = 0; i < numSeqParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ CHECK(size >= length);
+
+ CHECK_LE(out->size() + 4 + length, out->capacity());
+ memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4);
+ memcpy(out->data() + out->size() + 4, ptr, length);
+ out->setRange(0, out->size() + length + 4);
+
+ ptr += length;
+ size -= length;
+ }
+
+ CHECK(size >= 1);
+ size_t numPictureParameterSets = *ptr;
+ ++ptr;
+ --size;
+
+ for (size_t i = 0; i < numPictureParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ CHECK(size >= length);
+
+ CHECK_LE(out->size() + 4 + length, out->capacity());
+ memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4);
+ memcpy(out->data() + out->size() + 4, ptr, length);
+ out->setRange(0, out->size() + length + 4);
+
+ ptr += length;
+ size -= length;
+ }
+
+ out->meta()->setInt64("timeUs", 0ll);
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kNotifyBuffer);
+ notify->setBuffer("buffer", out);
+ notify->setInt32("oob", true);
+ notify->post();
+}
+
+void MPEG2TSWriter::SourceInfo::postAVCFrame(MediaBuffer *buffer) {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kNotifyBuffer);
+
+ sp<ABuffer> copy =
+ new ABuffer(buffer->range_length());
+ memcpy(copy->data(),
+ (const uint8_t *)buffer->data()
+ + buffer->range_offset(),
+ buffer->range_length());
+
+ int64_t timeUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ copy->meta()->setInt64("timeUs", timeUs);
+
+ int32_t isSync;
+ if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)
+ && isSync != 0) {
+ copy->meta()->setInt32("isSync", true);
+ }
+
+ notify->setBuffer("buffer", copy);
+ notify->post();
+}
+
+bool MPEG2TSWriter::SourceInfo::appendAACFrames(MediaBuffer *buffer) {
+ bool accessUnitPosted = false;
+
+ if (mAACBuffer != NULL
+ && mAACBuffer->size() + 7 + buffer->range_length()
+ > mAACBuffer->capacity()) {
+ accessUnitPosted = flushAACFrames();
+ }
+
+ if (mAACBuffer == NULL) {
+ size_t alloc = 4096;
+ if (buffer->range_length() + 7 > alloc) {
+ alloc = 7 + buffer->range_length();
+ }
+
+ mAACBuffer = new ABuffer(alloc);
+
+ int64_t timeUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+
+ mAACBuffer->meta()->setInt64("timeUs", timeUs);
+ mAACBuffer->meta()->setInt32("isSync", true);
+
+ mAACBuffer->setRange(0, 0);
+ }
+
+ const uint8_t *codec_specific_data = mAACCodecSpecificData->data();
+
+ unsigned profile = (codec_specific_data[0] >> 3) - 1;
+
+ unsigned sampling_freq_index =
+ ((codec_specific_data[0] & 7) << 1)
+ | (codec_specific_data[1] >> 7);
+
+ unsigned channel_configuration =
+ (codec_specific_data[1] >> 3) & 0x0f;
+
+ uint8_t *ptr = mAACBuffer->data() + mAACBuffer->size();
+
+ const uint32_t aac_frame_length = buffer->range_length() + 7;
+
+ *ptr++ = 0xff;
+ *ptr++ = 0xf1; // b11110001, ID=0, layer=0, protection_absent=1
+
+ *ptr++ =
+ profile << 6
+ | sampling_freq_index << 2
+ | ((channel_configuration >> 2) & 1); // private_bit=0
+
+ // original_copy=0, home=0, copyright_id_bit=0, copyright_id_start=0
+ *ptr++ =
+ (channel_configuration & 3) << 6
+ | aac_frame_length >> 11;
+ *ptr++ = (aac_frame_length >> 3) & 0xff;
+ *ptr++ = (aac_frame_length & 7) << 5;
+
+ // adts_buffer_fullness=0, number_of_raw_data_blocks_in_frame=0
+ *ptr++ = 0;
+
+ memcpy(ptr,
+ (const uint8_t *)buffer->data() + buffer->range_offset(),
+ buffer->range_length());
+
+ ptr += buffer->range_length();
+
+ mAACBuffer->setRange(0, ptr - mAACBuffer->data());
+
+ return accessUnitPosted;
+}
+
+bool MPEG2TSWriter::SourceInfo::flushAACFrames() {
+ if (mAACBuffer == NULL) {
+ return false;
+ }
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kNotifyBuffer);
+ notify->setBuffer("buffer", mAACBuffer);
+ notify->post();
+
+ mAACBuffer.clear();
+
+ return true;
+}
+
+void MPEG2TSWriter::SourceInfo::readMore() {
+ (new AMessage(kWhatRead, id()))->post();
+}
+
+void MPEG2TSWriter::SourceInfo::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatStart:
+ {
+ status_t err = mSource->start();
+ if (err != OK) {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kNotifyStartFailed);
+ notify->post();
+ break;
+ }
+
+ extractCodecSpecificData();
+
+ readMore();
+ break;
+ }
+
+ case kWhatRead:
+ {
+ MediaBuffer *buffer;
+ status_t err = mSource->read(&buffer);
+
+ if (err != OK && err != INFO_FORMAT_CHANGED) {
+ if (mStreamType == 0x0f) {
+ flushAACFrames();
+ }
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kNotifyReachedEOS);
+ notify->setInt32("status", err);
+ notify->post();
+ break;
+ }
+
+ if (err == OK) {
+ if (mStreamType == 0x0f && mAACCodecSpecificData == NULL) {
+ // The first buffer contains codec specific data.
+
+ CHECK_GE(buffer->range_length(), 2u);
+
+ mAACCodecSpecificData = new ABuffer(buffer->range_length());
+
+ memcpy(mAACCodecSpecificData->data(),
+ (const uint8_t *)buffer->data()
+ + buffer->range_offset(),
+ buffer->range_length());
+ } else if (buffer->range_length() > 0) {
+ if (mStreamType == 0x0f) {
+ if (!appendAACFrames(buffer)) {
+ msg->post();
+ }
+ } else {
+ postAVCFrame(buffer);
+ }
+ }
+
+ buffer->release();
+ buffer = NULL;
+ }
+
+ // Do not read more data until told to.
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+}
+
+sp<ABuffer> MPEG2TSWriter::SourceInfo::lastAccessUnit() {
+ return mLastAccessUnit;
+}
+
+void MPEG2TSWriter::SourceInfo::setLastAccessUnit(
+ const sp<ABuffer> &accessUnit) {
+ mLastAccessUnit = accessUnit;
+}
+
+int64_t MPEG2TSWriter::SourceInfo::lastAccessUnitTimeUs() {
+ if (mLastAccessUnit == NULL) {
+ return -1;
+ }
+
+ int64_t timeUs;
+ CHECK(mLastAccessUnit->meta()->findInt64("timeUs", &timeUs));
+
+ return timeUs;
+}
+
+void MPEG2TSWriter::SourceInfo::setEOSReceived() {
+ CHECK(!mEOSReceived);
+ mEOSReceived = true;
+}
+
+bool MPEG2TSWriter::SourceInfo::eosReceived() const {
+ return mEOSReceived;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MPEG2TSWriter::MPEG2TSWriter(int fd)
+ : mFile(fdopen(dup(fd), "wb")),
+ mWriteCookie(NULL),
+ mWriteFunc(NULL),
+ mStarted(false),
+ mNumSourcesDone(0),
+ mNumTSPacketsWritten(0),
+ mNumTSPacketsBeforeMeta(0) {
+ init();
+}
+
+MPEG2TSWriter::MPEG2TSWriter(const char *filename)
+ : mFile(fopen(filename, "wb")),
+ mWriteCookie(NULL),
+ mWriteFunc(NULL),
+ mStarted(false),
+ mNumSourcesDone(0),
+ mNumTSPacketsWritten(0),
+ mNumTSPacketsBeforeMeta(0) {
+ init();
+}
+
+MPEG2TSWriter::MPEG2TSWriter(
+ void *cookie,
+ ssize_t (*write)(void *cookie, const void *data, size_t size))
+ : mFile(NULL),
+ mWriteCookie(cookie),
+ mWriteFunc(write),
+ mStarted(false),
+ mNumSourcesDone(0),
+ mNumTSPacketsWritten(0),
+ mNumTSPacketsBeforeMeta(0) {
+ init();
+}
+
+void MPEG2TSWriter::init() {
+ CHECK(mFile != NULL || mWriteFunc != NULL);
+
+ mLooper = new ALooper;
+ mLooper->setName("MPEG2TSWriter");
+
+ mReflector = new AHandlerReflector<MPEG2TSWriter>(this);
+
+ mLooper->registerHandler(mReflector);
+ mLooper->start();
+}
+
+MPEG2TSWriter::~MPEG2TSWriter() {
+ if (mStarted) {
+ reset();
+ }
+
+ mLooper->unregisterHandler(mReflector->id());
+ mLooper->stop();
+
+ if (mFile != NULL) {
+ fclose(mFile);
+ mFile = NULL;
+ }
+}
+
+status_t MPEG2TSWriter::addSource(const sp<MediaSource> &source) {
+ CHECK(!mStarted);
+
+ sp<MetaData> meta = source->getFormat();
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
+ && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ sp<SourceInfo> info = new SourceInfo(source);
+
+ mSources.push(info);
+
+ return OK;
+}
+
+status_t MPEG2TSWriter::start(MetaData *param) {
+ CHECK(!mStarted);
+
+ mStarted = true;
+ mNumSourcesDone = 0;
+ mNumTSPacketsWritten = 0;
+ mNumTSPacketsBeforeMeta = 0;
+
+ for (size_t i = 0; i < mSources.size(); ++i) {
+ sp<AMessage> notify =
+ new AMessage(kWhatSourceNotify, mReflector->id());
+
+ notify->setInt32("source-index", i);
+
+ mSources.editItemAt(i)->start(notify);
+ }
+
+ return OK;
+}
+
+status_t MPEG2TSWriter::reset() {
+ CHECK(mStarted);
+
+ for (size_t i = 0; i < mSources.size(); ++i) {
+ mSources.editItemAt(i)->stop();
+ }
+ mStarted = false;
+
+ return OK;
+}
+
+status_t MPEG2TSWriter::pause() {
+ CHECK(mStarted);
+
+ return OK;
+}
+
+bool MPEG2TSWriter::reachedEOS() {
+ return !mStarted || (mNumSourcesDone == mSources.size() ? true : false);
+}
+
+status_t MPEG2TSWriter::dump(int fd, const Vector<String16> &args) {
+ return OK;
+}
+
+void MPEG2TSWriter::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatSourceNotify:
+ {
+ int32_t sourceIndex;
+ CHECK(msg->findInt32("source-index", &sourceIndex));
+
+ int32_t what;
+ CHECK(msg->findInt32("what", &what));
+
+ if (what == SourceInfo::kNotifyReachedEOS
+ || what == SourceInfo::kNotifyStartFailed) {
+ sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
+ source->setEOSReceived();
+
+ sp<ABuffer> buffer = source->lastAccessUnit();
+ source->setLastAccessUnit(NULL);
+
+ if (buffer != NULL) {
+ writeTS();
+ writeAccessUnit(sourceIndex, buffer);
+ }
+
+ ++mNumSourcesDone;
+ } else if (what == SourceInfo::kNotifyBuffer) {
+ sp<ABuffer> buffer;
+ CHECK(msg->findBuffer("buffer", &buffer));
+
+ int32_t oob;
+ if (msg->findInt32("oob", &oob) && oob) {
+ // This is codec specific data delivered out of band.
+ // It can be written out immediately.
+ writeTS();
+ writeAccessUnit(sourceIndex, buffer);
+ break;
+ }
+
+ // We don't just write out data as we receive it from
+ // the various sources. That would essentially write them
+ // out in random order (as the thread scheduler determines
+ // how the messages are dispatched).
+ // Instead we gather an access unit for all tracks and
+ // write out the one with the smallest timestamp, then
+ // request more data for the written out track.
+ // Rinse, repeat.
+ // If we don't have data on any track we don't write
+ // anything just yet.
+
+ sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
+
+ CHECK(source->lastAccessUnit() == NULL);
+ source->setLastAccessUnit(buffer);
+
+ ALOGV("lastAccessUnitTimeUs[%d] = %.2f secs",
+ sourceIndex, source->lastAccessUnitTimeUs() / 1E6);
+
+ int64_t minTimeUs = -1;
+ size_t minIndex = 0;
+
+ for (size_t i = 0; i < mSources.size(); ++i) {
+ const sp<SourceInfo> &source = mSources.editItemAt(i);
+
+ if (source->eosReceived()) {
+ continue;
+ }
+
+ int64_t timeUs = source->lastAccessUnitTimeUs();
+ if (timeUs < 0) {
+ minTimeUs = -1;
+ break;
+ } else if (minTimeUs < 0 || timeUs < minTimeUs) {
+ minTimeUs = timeUs;
+ minIndex = i;
+ }
+ }
+
+ if (minTimeUs < 0) {
+ ALOGV("not a all tracks have valid data.");
+ break;
+ }
+
+ ALOGV("writing access unit at time %.2f secs (index %d)",
+ minTimeUs / 1E6, minIndex);
+
+ source = mSources.editItemAt(minIndex);
+
+ buffer = source->lastAccessUnit();
+ source->setLastAccessUnit(NULL);
+
+ writeTS();
+ writeAccessUnit(minIndex, buffer);
+
+ source->readMore();
+ }
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+}
+
+void MPEG2TSWriter::writeProgramAssociationTable() {
+ // 0x47
+ // transport_error_indicator = b0
+ // payload_unit_start_indicator = b1
+ // transport_priority = b0
+ // PID = b0000000000000 (13 bits)
+ // transport_scrambling_control = b00
+ // adaptation_field_control = b01 (no adaptation field, payload only)
+ // continuity_counter = b????
+ // skip = 0x00
+ // --- payload follows
+ // table_id = 0x00
+ // section_syntax_indicator = b1
+ // must_be_zero = b0
+ // reserved = b11
+ // section_length = 0x00d
+ // transport_stream_id = 0x0000
+ // reserved = b11
+ // version_number = b00001
+ // current_next_indicator = b1
+ // section_number = 0x00
+ // last_section_number = 0x00
+ // one program follows:
+ // program_number = 0x0001
+ // reserved = b111
+ // program_map_PID = 0x01e0 (13 bits!)
+ // CRC = 0x????????
+
+ static const uint8_t kData[] = {
+ 0x47,
+ 0x40, 0x00, 0x10, 0x00, // b0100 0000 0000 0000 0001 ???? 0000 0000
+ 0x00, 0xb0, 0x0d, 0x00, // b0000 0000 1011 0000 0000 1101 0000 0000
+ 0x00, 0xc3, 0x00, 0x00, // b0000 0000 1100 0011 0000 0000 0000 0000
+ 0x00, 0x01, 0xe1, 0xe0, // b0000 0000 0000 0001 1110 0001 1110 0000
+ 0x00, 0x00, 0x00, 0x00 // b???? ???? ???? ???? ???? ???? ???? ????
+ };
+
+ sp<ABuffer> buffer = new ABuffer(188);
+ memset(buffer->data(), 0, buffer->size());
+ memcpy(buffer->data(), kData, sizeof(kData));
+
+ static const unsigned kContinuityCounter = 5;
+ buffer->data()[3] |= kContinuityCounter;
+
+ CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
+}
+
+void MPEG2TSWriter::writeProgramMap() {
+ // 0x47
+ // transport_error_indicator = b0
+ // payload_unit_start_indicator = b1
+ // transport_priority = b0
+ // PID = b0 0001 1110 0000 (13 bits) [0x1e0]
+ // transport_scrambling_control = b00
+ // adaptation_field_control = b01 (no adaptation field, payload only)
+ // continuity_counter = b????
+ // skip = 0x00
+ // -- payload follows
+ // table_id = 0x02
+ // section_syntax_indicator = b1
+ // must_be_zero = b0
+ // reserved = b11
+ // section_length = 0x???
+ // program_number = 0x0001
+ // reserved = b11
+ // version_number = b00001
+ // current_next_indicator = b1
+ // section_number = 0x00
+ // last_section_number = 0x00
+ // reserved = b111
+ // PCR_PID = b? ???? ???? ???? (13 bits)
+ // reserved = b1111
+ // program_info_length = 0x000
+ // one or more elementary stream descriptions follow:
+ // stream_type = 0x??
+ // reserved = b111
+ // elementary_PID = b? ???? ???? ???? (13 bits)
+ // reserved = b1111
+ // ES_info_length = 0x000
+ // CRC = 0x????????
+
+ static const uint8_t kData[] = {
+ 0x47,
+ 0x41, 0xe0, 0x10, 0x00, // b0100 0001 1110 0000 0001 ???? 0000 0000
+ 0x02, 0xb0, 0x00, 0x00, // b0000 0010 1011 ???? ???? ???? 0000 0000
+ 0x01, 0xc3, 0x00, 0x00, // b0000 0001 1100 0011 0000 0000 0000 0000
+ 0xe0, 0x00, 0xf0, 0x00 // b111? ???? ???? ???? 1111 0000 0000 0000
+ };
+
+ sp<ABuffer> buffer = new ABuffer(188);
+ memset(buffer->data(), 0, buffer->size());
+ memcpy(buffer->data(), kData, sizeof(kData));
+
+ static const unsigned kContinuityCounter = 5;
+ buffer->data()[3] |= kContinuityCounter;
+
+ size_t section_length = 5 * mSources.size() + 4 + 9;
+ buffer->data()[6] |= section_length >> 8;
+ buffer->data()[7] = section_length & 0xff;
+
+ static const unsigned kPCR_PID = 0x1e1;
+ buffer->data()[13] |= (kPCR_PID >> 8) & 0x1f;
+ buffer->data()[14] = kPCR_PID & 0xff;
+
+ uint8_t *ptr = &buffer->data()[sizeof(kData)];
+ for (size_t i = 0; i < mSources.size(); ++i) {
+ *ptr++ = mSources.editItemAt(i)->streamType();
+
+ const unsigned ES_PID = 0x1e0 + i + 1;
+ *ptr++ = 0xe0 | (ES_PID >> 8);
+ *ptr++ = ES_PID & 0xff;
+ *ptr++ = 0xf0;
+ *ptr++ = 0x00;
+ }
+
+ *ptr++ = 0x00;
+ *ptr++ = 0x00;
+ *ptr++ = 0x00;
+ *ptr++ = 0x00;
+
+ CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
+}
+
+void MPEG2TSWriter::writeAccessUnit(
+ int32_t sourceIndex, const sp<ABuffer> &accessUnit) {
+ // 0x47
+ // transport_error_indicator = b0
+ // payload_unit_start_indicator = b1
+ // transport_priority = b0
+ // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
+ // transport_scrambling_control = b00
+ // adaptation_field_control = b01 (no adaptation field, payload only)
+ // continuity_counter = b????
+ // -- payload follows
+ // packet_startcode_prefix = 0x000001
+ // stream_id = 0x?? (0xe0 for avc video, 0xc0 for aac audio)
+ // PES_packet_length = 0x????
+ // reserved = b10
+ // PES_scrambling_control = b00
+ // PES_priority = b0
+ // data_alignment_indicator = b1
+ // copyright = b0
+ // original_or_copy = b0
+ // PTS_DTS_flags = b10 (PTS only)
+ // ESCR_flag = b0
+ // ES_rate_flag = b0
+ // DSM_trick_mode_flag = b0
+ // additional_copy_info_flag = b0
+ // PES_CRC_flag = b0
+ // PES_extension_flag = b0
+ // PES_header_data_length = 0x05
+ // reserved = b0010 (PTS)
+ // PTS[32..30] = b???
+ // reserved = b1
+ // PTS[29..15] = b??? ???? ???? ???? (15 bits)
+ // reserved = b1
+ // PTS[14..0] = b??? ???? ???? ???? (15 bits)
+ // reserved = b1
+ // the first fragment of "buffer" follows
+
+ sp<ABuffer> buffer = new ABuffer(188);
+ memset(buffer->data(), 0, buffer->size());
+
+ const unsigned PID = 0x1e0 + sourceIndex + 1;
+
+ const unsigned continuity_counter =
+ mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
+
+ // XXX if there are multiple streams of a kind (more than 1 audio or
+ // more than 1 video) they need distinct stream_ids.
+ const unsigned stream_id =
+ mSources.editItemAt(sourceIndex)->streamType() == 0x0f ? 0xc0 : 0xe0;
+
+ int64_t timeUs;
+ CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
+
+ uint32_t PTS = (timeUs * 9ll) / 100ll;
+
+ size_t PES_packet_length = accessUnit->size() + 8;
+
+ if (PES_packet_length >= 65536) {
+ // This really should only happen for video.
+ CHECK_EQ(stream_id, 0xe0u);
+
+ // It's valid to set this to 0 for video according to the specs.
+ PES_packet_length = 0;
+ }
+
+ uint8_t *ptr = buffer->data();
+ *ptr++ = 0x47;
+ *ptr++ = 0x40 | (PID >> 8);
+ *ptr++ = PID & 0xff;
+ *ptr++ = 0x10 | continuity_counter;
+ *ptr++ = 0x00;
+ *ptr++ = 0x00;
+ *ptr++ = 0x01;
+ *ptr++ = stream_id;
+ *ptr++ = PES_packet_length >> 8;
+ *ptr++ = PES_packet_length & 0xff;
+ *ptr++ = 0x84;
+ *ptr++ = 0x80;
+ *ptr++ = 0x05;
+ *ptr++ = 0x20 | (((PTS >> 30) & 7) << 1) | 1;
+ *ptr++ = (PTS >> 22) & 0xff;
+ *ptr++ = (((PTS >> 15) & 0x7f) << 1) | 1;
+ *ptr++ = (PTS >> 7) & 0xff;
+ *ptr++ = ((PTS & 0x7f) << 1) | 1;
+
+ size_t sizeLeft = buffer->data() + buffer->size() - ptr;
+ size_t copy = accessUnit->size();
+ if (copy > sizeLeft) {
+ copy = sizeLeft;
+ }
+
+ memcpy(ptr, accessUnit->data(), copy);
+
+ CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
+
+ size_t offset = copy;
+ while (offset < accessUnit->size()) {
+ // for subsequent fragments of "buffer":
+ // 0x47
+ // transport_error_indicator = b0
+ // payload_unit_start_indicator = b0
+ // transport_priority = b0
+ // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
+ // transport_scrambling_control = b00
+ // adaptation_field_control = b01 (no adaptation field, payload only)
+ // continuity_counter = b????
+ // the fragment of "buffer" follows.
+
+ memset(buffer->data(), 0, buffer->size());
+
+ const unsigned continuity_counter =
+ mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
+
+ ptr = buffer->data();
+ *ptr++ = 0x47;
+ *ptr++ = 0x00 | (PID >> 8);
+ *ptr++ = PID & 0xff;
+ *ptr++ = 0x10 | continuity_counter;
+
+ size_t sizeLeft = buffer->data() + buffer->size() - ptr;
+ size_t copy = accessUnit->size() - offset;
+ if (copy > sizeLeft) {
+ copy = sizeLeft;
+ }
+
+ memcpy(ptr, accessUnit->data() + offset, copy);
+ CHECK_EQ(internalWrite(buffer->data(), buffer->size()),
+ buffer->size());
+
+ offset += copy;
+ }
+}
+
+void MPEG2TSWriter::writeTS() {
+ if (mNumTSPacketsWritten >= mNumTSPacketsBeforeMeta) {
+ writeProgramAssociationTable();
+ writeProgramMap();
+
+ mNumTSPacketsBeforeMeta = mNumTSPacketsWritten + 2500;
+ }
+}
+
+ssize_t MPEG2TSWriter::internalWrite(const void *data, size_t size) {
+ if (mFile != NULL) {
+ return fwrite(data, 1, size, mFile);
+ }
+
+ return (*mWriteFunc)(mWriteCookie, data, size);
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
new file mode 100644
index 0000000..9385b8a
--- /dev/null
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -0,0 +1,2477 @@
+/*
+ * 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 "MPEG4Extractor"
+#include <utils/Log.h>
+
+#include "include/MPEG4Extractor.h"
+#include "include/SampleTable.h"
+#include "include/ESDS.h"
+
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class MPEG4Source : public MediaSource {
+public:
+ // Caller retains ownership of both "dataSource" and "sampleTable".
+ MPEG4Source(const sp<MetaData> &format,
+ const sp<DataSource> &dataSource,
+ int32_t timeScale,
+ const sp<SampleTable> &sampleTable);
+
+ 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);
+
+protected:
+ virtual ~MPEG4Source();
+
+private:
+ Mutex mLock;
+
+ sp<MetaData> mFormat;
+ sp<DataSource> mDataSource;
+ int32_t mTimescale;
+ sp<SampleTable> mSampleTable;
+ uint32_t mCurrentSampleIndex;
+
+ bool mIsAVC;
+ size_t mNALLengthSize;
+
+ bool mStarted;
+
+ MediaBufferGroup *mGroup;
+
+ MediaBuffer *mBuffer;
+
+ bool mWantsNALFragments;
+
+ uint8_t *mSrcBuffer;
+
+ size_t parseNALSize(const uint8_t *data) const;
+
+ MPEG4Source(const MPEG4Source &);
+ MPEG4Source &operator=(const MPEG4Source &);
+};
+
+// This custom data source wraps an existing one and satisfies requests
+// falling entirely within a cached range from the cache while forwarding
+// all remaining requests to the wrapped datasource.
+// This is used to cache the full sampletable metadata for a single track,
+// possibly wrapping multiple times to cover all tracks, i.e.
+// Each MPEG4DataSource caches the sampletable metadata for a single track.
+
+struct MPEG4DataSource : public DataSource {
+ MPEG4DataSource(const sp<DataSource> &source);
+
+ virtual status_t initCheck() const;
+ virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+ virtual status_t getSize(off64_t *size);
+ virtual uint32_t flags();
+
+ status_t setCachedRange(off64_t offset, size_t size);
+
+protected:
+ virtual ~MPEG4DataSource();
+
+private:
+ Mutex mLock;
+
+ sp<DataSource> mSource;
+ off64_t mCachedOffset;
+ size_t mCachedSize;
+ uint8_t *mCache;
+
+ void clearCache();
+
+ MPEG4DataSource(const MPEG4DataSource &);
+ MPEG4DataSource &operator=(const MPEG4DataSource &);
+};
+
+MPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
+ : mSource(source),
+ mCachedOffset(0),
+ mCachedSize(0),
+ mCache(NULL) {
+}
+
+MPEG4DataSource::~MPEG4DataSource() {
+ clearCache();
+}
+
+void MPEG4DataSource::clearCache() {
+ if (mCache) {
+ free(mCache);
+ mCache = NULL;
+ }
+
+ mCachedOffset = 0;
+ mCachedSize = 0;
+}
+
+status_t MPEG4DataSource::initCheck() const {
+ return mSource->initCheck();
+}
+
+ssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (offset >= mCachedOffset
+ && offset + size <= mCachedOffset + mCachedSize) {
+ memcpy(data, &mCache[offset - mCachedOffset], size);
+ return size;
+ }
+
+ return mSource->readAt(offset, data, size);
+}
+
+status_t MPEG4DataSource::getSize(off64_t *size) {
+ return mSource->getSize(size);
+}
+
+uint32_t MPEG4DataSource::flags() {
+ return mSource->flags();
+}
+
+status_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ clearCache();
+
+ mCache = (uint8_t *)malloc(size);
+
+ if (mCache == NULL) {
+ return -ENOMEM;
+ }
+
+ mCachedOffset = offset;
+ mCachedSize = size;
+
+ ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
+
+ if (err < (ssize_t)size) {
+ clearCache();
+
+ return ERROR_IO;
+ }
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+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;
+ }
+}
+
+static const char *FourCC2MIME(uint32_t fourcc) {
+ switch (fourcc) {
+ case FOURCC('m', 'p', '4', 'a'):
+ return MEDIA_MIMETYPE_AUDIO_AAC;
+
+ case FOURCC('s', 'a', 'm', 'r'):
+ return MEDIA_MIMETYPE_AUDIO_AMR_NB;
+
+ case FOURCC('s', 'a', 'w', 'b'):
+ return MEDIA_MIMETYPE_AUDIO_AMR_WB;
+
+ case FOURCC('m', 'p', '4', 'v'):
+ return MEDIA_MIMETYPE_VIDEO_MPEG4;
+
+ case FOURCC('s', '2', '6', '3'):
+ case FOURCC('h', '2', '6', '3'):
+ case FOURCC('H', '2', '6', '3'):
+ return MEDIA_MIMETYPE_VIDEO_H263;
+
+ case FOURCC('a', 'v', 'c', '1'):
+ return MEDIA_MIMETYPE_VIDEO_AVC;
+
+ default:
+ CHECK(!"should not be here.");
+ return NULL;
+ }
+}
+
+MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
+ : mDataSource(source),
+ mInitCheck(NO_INIT),
+ mHasVideo(false),
+ mFirstTrack(NULL),
+ mLastTrack(NULL),
+ mFileMetaData(new MetaData),
+ mFirstSINF(NULL),
+ mIsDrm(false) {
+}
+
+MPEG4Extractor::~MPEG4Extractor() {
+ Track *track = mFirstTrack;
+ while (track) {
+ Track *next = track->next;
+
+ delete track;
+ track = next;
+ }
+ mFirstTrack = mLastTrack = NULL;
+
+ SINF *sinf = mFirstSINF;
+ while (sinf) {
+ SINF *next = sinf->next;
+ delete sinf->IPMPData;
+ delete sinf;
+ sinf = next;
+ }
+ mFirstSINF = NULL;
+}
+
+sp<MetaData> MPEG4Extractor::getMetaData() {
+ status_t err;
+ if ((err = readMetaData()) != OK) {
+ return new MetaData;
+ }
+
+ return mFileMetaData;
+}
+
+size_t MPEG4Extractor::countTracks() {
+ status_t err;
+ if ((err = readMetaData()) != OK) {
+ return 0;
+ }
+
+ size_t n = 0;
+ Track *track = mFirstTrack;
+ while (track) {
+ ++n;
+ track = track->next;
+ }
+
+ return n;
+}
+
+sp<MetaData> MPEG4Extractor::getTrackMetaData(
+ size_t index, uint32_t flags) {
+ status_t err;
+ if ((err = readMetaData()) != OK) {
+ return NULL;
+ }
+
+ Track *track = mFirstTrack;
+ while (index > 0) {
+ if (track == NULL) {
+ return NULL;
+ }
+
+ track = track->next;
+ --index;
+ }
+
+ if (track == NULL) {
+ return NULL;
+ }
+
+ if ((flags & kIncludeExtensiveMetaData)
+ && !track->includes_expensive_metadata) {
+ track->includes_expensive_metadata = true;
+
+ const char *mime;
+ CHECK(track->meta->findCString(kKeyMIMEType, &mime));
+ if (!strncasecmp("video/", mime, 6)) {
+ uint32_t sampleIndex;
+ uint32_t sampleTime;
+ if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
+ && track->sampleTable->getMetaDataForSample(
+ sampleIndex, NULL /* offset */, NULL /* size */,
+ &sampleTime) == OK) {
+ track->meta->setInt64(
+ kKeyThumbnailTime,
+ ((int64_t)sampleTime * 1000000) / track->timescale);
+ }
+ }
+ }
+
+ return track->meta;
+}
+
+status_t MPEG4Extractor::readMetaData() {
+ if (mInitCheck != NO_INIT) {
+ return mInitCheck;
+ }
+
+ off64_t offset = 0;
+ status_t err;
+ while ((err = parseChunk(&offset, 0)) == OK) {
+ }
+
+ if (mInitCheck == OK) {
+ if (mHasVideo) {
+ mFileMetaData->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
+ } else {
+ mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
+ }
+
+ mInitCheck = OK;
+ } else {
+ mInitCheck = err;
+ }
+
+ CHECK_NE(err, (status_t)NO_INIT);
+ return mInitCheck;
+}
+
+char* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
+ if (mFirstSINF == NULL) {
+ return NULL;
+ }
+
+ SINF *sinf = mFirstSINF;
+ while (sinf && (trackID != sinf->trackID)) {
+ sinf = sinf->next;
+ }
+
+ if (sinf == NULL) {
+ return NULL;
+ }
+
+ *len = sinf->len;
+ return sinf->IPMPData;
+}
+
+// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
+int32_t readSize(off64_t offset,
+ const sp<DataSource> DataSource, uint8_t *numOfBytes) {
+ uint32_t size = 0;
+ uint8_t data;
+ bool moreData = true;
+ *numOfBytes = 0;
+
+ while (moreData) {
+ if (DataSource->readAt(offset, &data, 1) < 1) {
+ return -1;
+ }
+ offset ++;
+ moreData = (data >= 128) ? true : false;
+ size = (size << 7) | (data & 0x7f); // Take last 7 bits
+ (*numOfBytes) ++;
+ }
+
+ return size;
+}
+
+status_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) {
+ uint8_t updateIdTag;
+ if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
+ return ERROR_IO;
+ }
+ data_offset ++;
+
+ if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t numOfBytes;
+ int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
+ if (size < 0) {
+ return ERROR_IO;
+ }
+ int32_t classSize = size;
+ data_offset += numOfBytes;
+
+ while(size >= 11 ) {
+ uint8_t descriptorTag;
+ if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
+ return ERROR_IO;
+ }
+ data_offset ++;
+
+ if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t buffer[8];
+ //ObjectDescriptorID and ObjectDescriptor url flag
+ if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
+ return ERROR_IO;
+ }
+ data_offset += 2;
+
+ if ((buffer[1] >> 5) & 0x0001) { //url flag is set
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
+ return ERROR_IO;
+ }
+ data_offset += 8;
+
+ if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
+ || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
+ return ERROR_MALFORMED;
+ }
+
+ SINF *sinf = new SINF;
+ sinf->trackID = U16_AT(&buffer[3]);
+ sinf->IPMPDescriptorID = buffer[7];
+ sinf->next = mFirstSINF;
+ mFirstSINF = sinf;
+
+ size -= (8 + 2 + 1);
+ }
+
+ if (size != 0) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
+ return ERROR_IO;
+ }
+ data_offset ++;
+
+ if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
+ return ERROR_MALFORMED;
+ }
+
+ size = readSize(data_offset, mDataSource, &numOfBytes);
+ if (size < 0) {
+ return ERROR_IO;
+ }
+ classSize = size;
+ data_offset += numOfBytes;
+
+ while (size > 0) {
+ uint8_t tag;
+ int32_t dataLen;
+ if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
+ return ERROR_IO;
+ }
+ data_offset ++;
+
+ if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
+ uint8_t id;
+ dataLen = readSize(data_offset, mDataSource, &numOfBytes);
+ if (dataLen < 0) {
+ return ERROR_IO;
+ } else if (dataLen < 4) {
+ return ERROR_MALFORMED;
+ }
+ data_offset += numOfBytes;
+
+ if (mDataSource->readAt(data_offset, &id, 1) < 1) {
+ return ERROR_IO;
+ }
+ data_offset ++;
+
+ SINF *sinf = mFirstSINF;
+ while (sinf && (sinf->IPMPDescriptorID != id)) {
+ sinf = sinf->next;
+ }
+ if (sinf == NULL) {
+ return ERROR_MALFORMED;
+ }
+ sinf->len = dataLen - 3;
+ sinf->IPMPData = new char[sinf->len];
+
+ if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) {
+ return ERROR_IO;
+ }
+ data_offset += sinf->len;
+
+ size -= (dataLen + numOfBytes + 1);
+ }
+ }
+
+ if (size != 0) {
+ return ERROR_MALFORMED;
+ }
+
+ return UNKNOWN_ERROR; // Return a dummy error.
+}
+
+static void MakeFourCCString(uint32_t x, char *s) {
+ s[0] = x >> 24;
+ s[1] = (x >> 16) & 0xff;
+ s[2] = (x >> 8) & 0xff;
+ s[3] = x & 0xff;
+ s[4] = '\0';
+}
+
+struct PathAdder {
+ PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
+ : mPath(path) {
+ mPath->push(chunkType);
+ }
+
+ ~PathAdder() {
+ mPath->pop();
+ }
+
+private:
+ Vector<uint32_t> *mPath;
+
+ PathAdder(const PathAdder &);
+ PathAdder &operator=(const PathAdder &);
+};
+
+static bool underMetaDataPath(const Vector<uint32_t> &path) {
+ return path.size() >= 5
+ && path[0] == FOURCC('m', 'o', 'o', 'v')
+ && path[1] == FOURCC('u', 'd', 't', 'a')
+ && path[2] == FOURCC('m', 'e', 't', 'a')
+ && path[3] == FOURCC('i', 'l', 's', 't');
+}
+
+// Given a time in seconds since Jan 1 1904, produce a human-readable string.
+static void convertTimeToDate(int64_t time_1904, String8 *s) {
+ time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
+
+ char tmp[32];
+ strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
+
+ s->setTo(tmp);
+}
+
+status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
+ ALOGV("entering parseChunk %lld/%d", *offset, depth);
+ uint32_t hdr[2];
+ if (mDataSource->readAt(*offset, hdr, 8) < 8) {
+ return ERROR_IO;
+ }
+ uint64_t chunk_size = ntohl(hdr[0]);
+ uint32_t chunk_type = ntohl(hdr[1]);
+ off64_t data_offset = *offset + 8;
+
+ if (chunk_size == 1) {
+ if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
+ return ERROR_IO;
+ }
+ 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];
+ MakeFourCCString(chunk_type, chunk);
+ ALOGV("chunk: %s @ %lld", chunk, *offset);
+
+#if 0
+ static const char kWhitespace[] = " ";
+ const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
+ printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
+
+ char buffer[256];
+ size_t n = chunk_size;
+ if (n > sizeof(buffer)) {
+ n = sizeof(buffer);
+ }
+ if (mDataSource->readAt(*offset, buffer, n)
+ < (ssize_t)n) {
+ return ERROR_IO;
+ }
+
+ hexdump(buffer, n);
+#endif
+
+ PathAdder autoAdder(&mPath, chunk_type);
+
+ off64_t chunk_data_size = *offset + chunk_size - data_offset;
+
+ if (chunk_type != FOURCC('c', 'p', 'r', 't')
+ && chunk_type != FOURCC('c', 'o', 'v', 'r')
+ && mPath.size() == 5 && underMetaDataPath(mPath)) {
+ off64_t stop_offset = *offset + chunk_size;
+ *offset = data_offset;
+ while (*offset < stop_offset) {
+ status_t err = parseChunk(offset, depth + 1);
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ if (*offset != stop_offset) {
+ return ERROR_MALFORMED;
+ }
+
+ return OK;
+ }
+
+ switch(chunk_type) {
+ case FOURCC('m', 'o', 'o', 'v'):
+ case FOURCC('t', 'r', 'a', 'k'):
+ case FOURCC('m', 'd', 'i', 'a'):
+ case FOURCC('m', 'i', 'n', 'f'):
+ case FOURCC('d', 'i', 'n', 'f'):
+ case FOURCC('s', 't', 'b', 'l'):
+ case FOURCC('m', 'v', 'e', 'x'):
+ case FOURCC('m', 'o', 'o', 'f'):
+ case FOURCC('t', 'r', 'a', 'f'):
+ case FOURCC('m', 'f', 'r', 'a'):
+ case FOURCC('u', 'd', 't', 'a'):
+ case FOURCC('i', 'l', 's', 't'):
+ {
+ if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
+ ALOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
+
+ if (mDataSource->flags()
+ & (DataSource::kWantsPrefetching
+ | DataSource::kIsCachingDataSource)) {
+ sp<MPEG4DataSource> cachedSource =
+ new MPEG4DataSource(mDataSource);
+
+ if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
+ mDataSource = cachedSource;
+ }
+ }
+
+ mLastTrack->sampleTable = new SampleTable(mDataSource);
+ }
+
+ bool isTrack = false;
+ if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
+ isTrack = true;
+
+ Track *track = new Track;
+ track->next = NULL;
+ if (mLastTrack) {
+ mLastTrack->next = track;
+ } else {
+ mFirstTrack = track;
+ }
+ mLastTrack = track;
+
+ track->meta = new MetaData;
+ track->includes_expensive_metadata = false;
+ track->skipTrack = false;
+ track->timescale = 0;
+ track->meta->setCString(kKeyMIMEType, "application/octet-stream");
+ }
+
+ off64_t stop_offset = *offset + chunk_size;
+ *offset = data_offset;
+ while (*offset < stop_offset) {
+ status_t err = parseChunk(offset, depth + 1);
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ if (*offset != stop_offset) {
+ return ERROR_MALFORMED;
+ }
+
+ if (isTrack) {
+ if (mLastTrack->skipTrack) {
+ Track *cur = mFirstTrack;
+
+ if (cur == mLastTrack) {
+ delete cur;
+ mFirstTrack = mLastTrack = NULL;
+ } else {
+ while (cur && cur->next != mLastTrack) {
+ cur = cur->next;
+ }
+ cur->next = NULL;
+ delete mLastTrack;
+ mLastTrack = cur;
+ }
+
+ return OK;
+ }
+
+ status_t err = verifyTrack(mLastTrack);
+
+ if (err != OK) {
+ return err;
+ }
+ } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
+ mInitCheck = OK;
+
+ if (!mIsDrm) {
+ return UNKNOWN_ERROR; // Return a dummy error.
+ } else {
+ return OK;
+ }
+ }
+ break;
+ }
+
+ case FOURCC('t', 'k', 'h', 'd'):
+ {
+ status_t err;
+ if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
+ return err;
+ }
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('m', 'd', 'h', 'd'):
+ {
+ if (chunk_data_size < 4) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t version;
+ if (mDataSource->readAt(
+ data_offset, &version, sizeof(version))
+ < (ssize_t)sizeof(version)) {
+ return ERROR_IO;
+ }
+
+ off64_t timescale_offset;
+
+ if (version == 1) {
+ timescale_offset = data_offset + 4 + 16;
+ } else if (version == 0) {
+ timescale_offset = data_offset + 4 + 8;
+ } else {
+ return ERROR_IO;
+ }
+
+ uint32_t timescale;
+ if (mDataSource->readAt(
+ timescale_offset, &timescale, sizeof(timescale))
+ < (ssize_t)sizeof(timescale)) {
+ return ERROR_IO;
+ }
+
+ mLastTrack->timescale = ntohl(timescale);
+
+ int64_t duration;
+ if (version == 1) {
+ if (mDataSource->readAt(
+ timescale_offset + 4, &duration, sizeof(duration))
+ < (ssize_t)sizeof(duration)) {
+ return ERROR_IO;
+ }
+ duration = ntoh64(duration);
+ } else {
+ int32_t duration32;
+ if (mDataSource->readAt(
+ timescale_offset + 4, &duration32, sizeof(duration32))
+ < (ssize_t)sizeof(duration32)) {
+ return ERROR_IO;
+ }
+ duration = ntohl(duration32);
+ }
+ mLastTrack->meta->setInt64(
+ kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
+
+ uint8_t lang[2];
+ off64_t lang_offset;
+ if (version == 1) {
+ lang_offset = timescale_offset + 4 + 8;
+ } else if (version == 0) {
+ lang_offset = timescale_offset + 4 + 4;
+ } else {
+ return ERROR_IO;
+ }
+
+ if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
+ < (ssize_t)sizeof(lang)) {
+ return ERROR_IO;
+ }
+
+ // To get the ISO-639-2/T three character language code
+ // 1 bit pad followed by 3 5-bits characters. Each character
+ // is packed as the difference between its ASCII value and 0x60.
+ char lang_code[4];
+ lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
+ lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
+ lang_code[2] = (lang[1] & 0x1f) + 0x60;
+ lang_code[3] = '\0';
+
+ mLastTrack->meta->setCString(
+ kKeyMediaLanguage, lang_code);
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('s', 't', 's', 'd'):
+ {
+ if (chunk_data_size < 8) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t buffer[8];
+ if (chunk_data_size < (off64_t)sizeof(buffer)) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(
+ data_offset, buffer, 8) < 8) {
+ return ERROR_IO;
+ }
+
+ if (U32_AT(buffer) != 0) {
+ // Should be version 0, flags 0.
+ return ERROR_MALFORMED;
+ }
+
+ uint32_t entry_count = U32_AT(&buffer[4]);
+
+ if (entry_count > 1) {
+ // For 3GPP timed text, there could be multiple tx3g boxes contain
+ // multiple text display formats. These formats will be used to
+ // display the timed text.
+ const char *mime;
+ CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
+ if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+ // For now we only support a single type of media per track.
+ mLastTrack->skipTrack = true;
+ *offset += chunk_size;
+ break;
+ }
+ }
+
+ off64_t stop_offset = *offset + chunk_size;
+ *offset = data_offset + 8;
+ for (uint32_t i = 0; i < entry_count; ++i) {
+ status_t err = parseChunk(offset, depth + 1);
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ if (*offset != stop_offset) {
+ return ERROR_MALFORMED;
+ }
+ break;
+ }
+
+ case FOURCC('m', 'p', '4', 'a'):
+ case FOURCC('s', 'a', 'm', 'r'):
+ case FOURCC('s', 'a', 'w', 'b'):
+ {
+ uint8_t buffer[8 + 20];
+ if (chunk_data_size < (ssize_t)sizeof(buffer)) {
+ // Basic AudioSampleEntry size.
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(
+ data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
+ return ERROR_IO;
+ }
+
+ uint16_t data_ref_index = U16_AT(&buffer[6]);
+ uint16_t num_channels = U16_AT(&buffer[16]);
+
+ uint16_t sample_size = U16_AT(&buffer[18]);
+ uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
+
+ if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
+ FourCC2MIME(chunk_type))) {
+ // AMR NB audio is always mono, 8kHz
+ num_channels = 1;
+ sample_rate = 8000;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
+ FourCC2MIME(chunk_type))) {
+ // AMR WB audio is always mono, 16kHz
+ num_channels = 1;
+ sample_rate = 16000;
+ }
+
+#if 0
+ printf("*** coding='%s' %d channels, size %d, rate %d\n",
+ chunk, num_channels, sample_size, sample_rate);
+#endif
+
+ mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
+ mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
+ mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
+
+ off64_t stop_offset = *offset + chunk_size;
+ *offset = data_offset + sizeof(buffer);
+ while (*offset < stop_offset) {
+ status_t err = parseChunk(offset, depth + 1);
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ if (*offset != stop_offset) {
+ return ERROR_MALFORMED;
+ }
+ break;
+ }
+
+ case FOURCC('m', 'p', '4', 'v'):
+ case FOURCC('s', '2', '6', '3'):
+ case FOURCC('H', '2', '6', '3'):
+ case FOURCC('h', '2', '6', '3'):
+ case FOURCC('a', 'v', 'c', '1'):
+ {
+ mHasVideo = true;
+
+ uint8_t buffer[78];
+ if (chunk_data_size < (ssize_t)sizeof(buffer)) {
+ // Basic VideoSampleEntry size.
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(
+ data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
+ return ERROR_IO;
+ }
+
+ uint16_t data_ref_index = U16_AT(&buffer[6]);
+ uint16_t width = U16_AT(&buffer[6 + 18]);
+ uint16_t height = U16_AT(&buffer[6 + 20]);
+
+ // The video sample is not stand-compliant if it has invalid dimension.
+ // Use some default width and height value, and
+ // let the decoder figure out the actual width and height (and thus
+ // be prepared for INFO_FOMRAT_CHANGED event).
+ if (width == 0) width = 352;
+ if (height == 0) height = 288;
+
+ // printf("*** coding='%s' width=%d height=%d\n",
+ // chunk, width, height);
+
+ mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
+ mLastTrack->meta->setInt32(kKeyWidth, width);
+ mLastTrack->meta->setInt32(kKeyHeight, height);
+
+ off64_t stop_offset = *offset + chunk_size;
+ *offset = data_offset + sizeof(buffer);
+ while (*offset < stop_offset) {
+ status_t err = parseChunk(offset, depth + 1);
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ if (*offset != stop_offset) {
+ return ERROR_MALFORMED;
+ }
+ break;
+ }
+
+ case FOURCC('s', 't', 'c', 'o'):
+ case FOURCC('c', 'o', '6', '4'):
+ {
+ status_t err =
+ mLastTrack->sampleTable->setChunkOffsetParams(
+ chunk_type, data_offset, chunk_data_size);
+
+ if (err != OK) {
+ return err;
+ }
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('s', 't', 's', 'c'):
+ {
+ status_t err =
+ mLastTrack->sampleTable->setSampleToChunkParams(
+ data_offset, chunk_data_size);
+
+ if (err != OK) {
+ return err;
+ }
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('s', 't', 's', 'z'):
+ case FOURCC('s', 't', 'z', '2'):
+ {
+ status_t err =
+ mLastTrack->sampleTable->setSampleSizeParams(
+ chunk_type, data_offset, chunk_data_size);
+
+ if (err != OK) {
+ return err;
+ }
+
+ size_t max_size;
+ err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
+
+ if (err != OK) {
+ return err;
+ }
+
+ // Assume that a given buffer only contains at most 10 fragments,
+ // each fragment originally prefixed with a 2 byte length will
+ // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
+ // and thus will grow by 2 bytes per fragment.
+ mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
+ *offset += chunk_size;
+
+ // Calculate average frame rate.
+ const char *mime;
+ CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
+ if (!strncasecmp("video/", mime, 6)) {
+ size_t nSamples = mLastTrack->sampleTable->countSamples();
+ int64_t durationUs;
+ if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
+ if (durationUs > 0) {
+ int32_t frameRate = (nSamples * 1000000LL +
+ (durationUs >> 1)) / durationUs;
+ mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
+ }
+ }
+ }
+
+ break;
+ }
+
+ case FOURCC('s', 't', 't', 's'):
+ {
+ status_t err =
+ mLastTrack->sampleTable->setTimeToSampleParams(
+ data_offset, chunk_data_size);
+
+ if (err != OK) {
+ return err;
+ }
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('c', 't', 't', 's'):
+ {
+ status_t err =
+ mLastTrack->sampleTable->setCompositionTimeToSampleParams(
+ data_offset, chunk_data_size);
+
+ if (err != OK) {
+ return err;
+ }
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('s', 't', 's', 's'):
+ {
+ status_t err =
+ mLastTrack->sampleTable->setSyncSampleParams(
+ data_offset, chunk_data_size);
+
+ if (err != OK) {
+ return err;
+ }
+
+ *offset += chunk_size;
+ break;
+ }
+
+ // @xyz
+ case FOURCC('\xA9', 'x', 'y', 'z'):
+ {
+ // Best case the total data length inside "@xyz" box
+ // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
+ // where "\x00\x04" is the text string length with value = 4,
+ // "\0x15\xc7" is the language code = en, and "0+0" is a
+ // location (string) value with longitude = 0 and latitude = 0.
+ if (chunk_data_size < 8) {
+ return ERROR_MALFORMED;
+ }
+
+ // Worst case the location string length would be 18,
+ // for instance +90.0000-180.0000, without the trailing "/" and
+ // the string length + language code.
+ char buffer[18];
+
+ // Substracting 5 from the data size is because the text string length +
+ // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
+ off64_t location_length = chunk_data_size - 5;
+ if (location_length >= (off64_t) sizeof(buffer)) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(
+ data_offset + 4, buffer, location_length) < location_length) {
+ return ERROR_IO;
+ }
+
+ buffer[location_length] = '\0';
+ mFileMetaData->setCString(kKeyLocation, buffer);
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('e', 's', 'd', 's'):
+ {
+ if (chunk_data_size < 4) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t buffer[256];
+ if (chunk_data_size > (off64_t)sizeof(buffer)) {
+ return ERROR_BUFFER_TOO_SMALL;
+ }
+
+ if (mDataSource->readAt(
+ data_offset, buffer, chunk_data_size) < chunk_data_size) {
+ return ERROR_IO;
+ }
+
+ if (U32_AT(buffer) != 0) {
+ // Should be version 0, flags 0.
+ return ERROR_MALFORMED;
+ }
+
+ mLastTrack->meta->setData(
+ kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
+
+ if (mPath.size() >= 2
+ && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
+ // Information from the ESDS must be relied on for proper
+ // setup of sample rate and channel count for MPEG4 Audio.
+ // The generic header appears to only contain generic
+ // information...
+
+ status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
+ &buffer[4], chunk_data_size - 4);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('a', 'v', 'c', 'C'):
+ {
+ char buffer[256];
+ if (chunk_data_size > (off64_t)sizeof(buffer)) {
+ return ERROR_BUFFER_TOO_SMALL;
+ }
+
+ if (mDataSource->readAt(
+ data_offset, buffer, chunk_data_size) < chunk_data_size) {
+ return ERROR_IO;
+ }
+
+ mLastTrack->meta->setData(
+ kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('d', '2', '6', '3'):
+ {
+ /*
+ * d263 contains a fixed 7 bytes part:
+ * vendor - 4 bytes
+ * version - 1 byte
+ * level - 1 byte
+ * profile - 1 byte
+ * optionally, "d263" box itself may contain a 16-byte
+ * bit rate box (bitr)
+ * average bit rate - 4 bytes
+ * max bit rate - 4 bytes
+ */
+ char buffer[23];
+ if (chunk_data_size != 7 &&
+ chunk_data_size != 23) {
+ ALOGE("Incorrect D263 box size %lld", chunk_data_size);
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(
+ data_offset, buffer, chunk_data_size) < chunk_data_size) {
+ return ERROR_IO;
+ }
+
+ mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('m', 'e', 't', 'a'):
+ {
+ uint8_t buffer[4];
+ if (chunk_data_size < (off64_t)sizeof(buffer)) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(
+ data_offset, buffer, 4) < 4) {
+ return ERROR_IO;
+ }
+
+ if (U32_AT(buffer) != 0) {
+ // Should be version 0, flags 0.
+
+ // If it's not, let's assume this is one of those
+ // apparently malformed chunks that don't have flags
+ // and completely different semantics than what's
+ // in the MPEG4 specs and skip it.
+ *offset += chunk_size;
+ return OK;
+ }
+
+ off64_t stop_offset = *offset + chunk_size;
+ *offset = data_offset + sizeof(buffer);
+ while (*offset < stop_offset) {
+ status_t err = parseChunk(offset, depth + 1);
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ if (*offset != stop_offset) {
+ return ERROR_MALFORMED;
+ }
+ break;
+ }
+
+ case FOURCC('m', 'e', 'a', 'n'):
+ case FOURCC('n', 'a', 'm', 'e'):
+ case FOURCC('d', 'a', 't', 'a'):
+ {
+ if (mPath.size() == 6 && underMetaDataPath(mPath)) {
+ status_t err = parseMetaData(data_offset, chunk_data_size);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('m', 'v', 'h', 'd'):
+ {
+ if (chunk_data_size < 12) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t header[12];
+ if (mDataSource->readAt(
+ data_offset, header, sizeof(header))
+ < (ssize_t)sizeof(header)) {
+ return ERROR_IO;
+ }
+
+ int64_t creationTime;
+ if (header[0] == 1) {
+ creationTime = U64_AT(&header[4]);
+ } else if (header[0] != 0) {
+ return ERROR_MALFORMED;
+ } else {
+ creationTime = U32_AT(&header[4]);
+ }
+
+ String8 s;
+ convertTimeToDate(creationTime, &s);
+
+ mFileMetaData->setCString(kKeyDate, s.string());
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('m', 'd', 'a', 't'):
+ {
+ if (!mIsDrm) {
+ *offset += chunk_size;
+ break;
+ }
+
+ if (chunk_size < 8) {
+ return ERROR_MALFORMED;
+ }
+
+ return parseDrmSINF(offset, data_offset);
+ }
+
+ case FOURCC('h', 'd', 'l', 'r'):
+ {
+ uint32_t buffer;
+ if (mDataSource->readAt(
+ data_offset + 8, &buffer, 4) < 4) {
+ return ERROR_IO;
+ }
+
+ uint32_t type = ntohl(buffer);
+ // For the 3GPP file format, the handler-type within the 'hdlr' box
+ // shall be 'text'. We also want to support 'sbtl' handler type
+ // for a practical reason as various MPEG4 containers use it.
+ if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
+ mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
+ }
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('t', 'x', '3', 'g'):
+ {
+ uint32_t type;
+ const void *data;
+ size_t size = 0;
+ if (!mLastTrack->meta->findData(
+ kKeyTextFormatData, &type, &data, &size)) {
+ size = 0;
+ }
+
+ uint8_t *buffer = new uint8_t[size + chunk_size];
+
+ if (size > 0) {
+ memcpy(buffer, data, size);
+ }
+
+ if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
+ < chunk_size) {
+ delete[] buffer;
+ buffer = NULL;
+
+ return ERROR_IO;
+ }
+
+ mLastTrack->meta->setData(
+ kKeyTextFormatData, 0, buffer, size + chunk_size);
+
+ delete[] buffer;
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('c', 'o', 'v', 'r'):
+ {
+ if (mFileMetaData != NULL) {
+ ALOGV("chunk_data_size = %lld and data_offset = %lld",
+ chunk_data_size, data_offset);
+ uint8_t *buffer = new uint8_t[chunk_data_size + 1];
+ if (mDataSource->readAt(
+ data_offset, buffer, chunk_data_size) != (ssize_t)chunk_data_size) {
+ delete[] buffer;
+ buffer = NULL;
+
+ return ERROR_IO;
+ }
+ const int kSkipBytesOfDataBox = 16;
+ mFileMetaData->setData(
+ kKeyAlbumArt, MetaData::TYPE_NONE,
+ buffer + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
+ }
+
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('-', '-', '-', '-'):
+ {
+ mLastCommentMean.clear();
+ mLastCommentName.clear();
+ mLastCommentData.clear();
+ *offset += chunk_size;
+ break;
+ }
+
+ default:
+ {
+ *offset += chunk_size;
+ break;
+ }
+ }
+
+ return OK;
+}
+
+status_t MPEG4Extractor::parseTrackHeader(
+ off64_t data_offset, off64_t data_size) {
+ if (data_size < 4) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t version;
+ if (mDataSource->readAt(data_offset, &version, 1) < 1) {
+ return ERROR_IO;
+ }
+
+ size_t dynSize = (version == 1) ? 36 : 24;
+
+ uint8_t buffer[36 + 60];
+
+ if (data_size != (off64_t)dynSize + 60) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(
+ data_offset, buffer, data_size) < (ssize_t)data_size) {
+ return ERROR_IO;
+ }
+
+ uint64_t ctime, mtime, duration;
+ int32_t id;
+
+ if (version == 1) {
+ ctime = U64_AT(&buffer[4]);
+ mtime = U64_AT(&buffer[12]);
+ id = U32_AT(&buffer[20]);
+ duration = U64_AT(&buffer[28]);
+ } else {
+ CHECK_EQ((unsigned)version, 0u);
+
+ ctime = U32_AT(&buffer[4]);
+ mtime = U32_AT(&buffer[8]);
+ id = U32_AT(&buffer[12]);
+ duration = U32_AT(&buffer[20]);
+ }
+
+ mLastTrack->meta->setInt32(kKeyTrackID, id);
+
+ size_t matrixOffset = dynSize + 16;
+ int32_t a00 = U32_AT(&buffer[matrixOffset]);
+ int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
+ int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
+ int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
+ int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
+ int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
+
+#if 0
+ ALOGI("x' = %.2f * x + %.2f * y + %.2f",
+ a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
+ ALOGI("y' = %.2f * x + %.2f * y + %.2f",
+ a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
+#endif
+
+ uint32_t rotationDegrees;
+
+ static const int32_t kFixedOne = 0x10000;
+ if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
+ // Identity, no rotation
+ rotationDegrees = 0;
+ } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
+ rotationDegrees = 90;
+ } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
+ rotationDegrees = 270;
+ } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
+ rotationDegrees = 180;
+ } else {
+ ALOGW("We only support 0,90,180,270 degree rotation matrices");
+ rotationDegrees = 0;
+ }
+
+ if (rotationDegrees != 0) {
+ mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
+ }
+
+ // Handle presentation display size, which could be different
+ // from the image size indicated by kKeyWidth and kKeyHeight.
+ uint32_t width = U32_AT(&buffer[dynSize + 52]);
+ uint32_t height = U32_AT(&buffer[dynSize + 56]);
+ mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
+ mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
+
+ return OK;
+}
+
+status_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) {
+ if (size < 4) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t *buffer = new uint8_t[size + 1];
+ if (mDataSource->readAt(
+ offset, buffer, size) != (ssize_t)size) {
+ delete[] buffer;
+ buffer = NULL;
+
+ return ERROR_IO;
+ }
+
+ uint32_t flags = U32_AT(buffer);
+
+ uint32_t metadataKey = 0;
+ char chunk[5];
+ MakeFourCCString(mPath[4], chunk);
+ ALOGV("meta: %s @ %lld", chunk, offset);
+ switch (mPath[4]) {
+ case FOURCC(0xa9, 'a', 'l', 'b'):
+ {
+ metadataKey = kKeyAlbum;
+ break;
+ }
+ case FOURCC(0xa9, 'A', 'R', 'T'):
+ {
+ metadataKey = kKeyArtist;
+ break;
+ }
+ case FOURCC('a', 'A', 'R', 'T'):
+ {
+ metadataKey = kKeyAlbumArtist;
+ break;
+ }
+ case FOURCC(0xa9, 'd', 'a', 'y'):
+ {
+ metadataKey = kKeyYear;
+ break;
+ }
+ case FOURCC(0xa9, 'n', 'a', 'm'):
+ {
+ metadataKey = kKeyTitle;
+ break;
+ }
+ case FOURCC(0xa9, 'w', 'r', 't'):
+ {
+ metadataKey = kKeyWriter;
+ break;
+ }
+ case FOURCC('c', 'o', 'v', 'r'):
+ {
+ metadataKey = kKeyAlbumArt;
+ break;
+ }
+ case FOURCC('g', 'n', 'r', 'e'):
+ {
+ metadataKey = kKeyGenre;
+ break;
+ }
+ case FOURCC(0xa9, 'g', 'e', 'n'):
+ {
+ metadataKey = kKeyGenre;
+ break;
+ }
+ case FOURCC('c', 'p', 'i', 'l'):
+ {
+ if (size == 9 && flags == 21) {
+ char tmp[16];
+ sprintf(tmp, "%d",
+ (int)buffer[size - 1]);
+
+ mFileMetaData->setCString(kKeyCompilation, tmp);
+ }
+ break;
+ }
+ case FOURCC('t', 'r', 'k', 'n'):
+ {
+ if (size == 16 && flags == 0) {
+ char tmp[16];
+ sprintf(tmp, "%d/%d",
+ (int)buffer[size - 5], (int)buffer[size - 3]);
+
+ mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
+ }
+ break;
+ }
+ case FOURCC('d', 'i', 's', 'k'):
+ {
+ if (size == 14 && flags == 0) {
+ char tmp[16];
+ sprintf(tmp, "%d/%d",
+ (int)buffer[size - 3], (int)buffer[size - 1]);
+
+ mFileMetaData->setCString(kKeyDiscNumber, tmp);
+ }
+ break;
+ }
+ case FOURCC('-', '-', '-', '-'):
+ {
+ buffer[size] = '\0';
+ switch (mPath[5]) {
+ case FOURCC('m', 'e', 'a', 'n'):
+ mLastCommentMean.setTo((const char *)buffer + 4);
+ break;
+ case FOURCC('n', 'a', 'm', 'e'):
+ mLastCommentName.setTo((const char *)buffer + 4);
+ break;
+ case FOURCC('d', 'a', 't', 'a'):
+ mLastCommentData.setTo((const char *)buffer + 8);
+ break;
+ }
+ if (mLastCommentMean == "com.apple.iTunes"
+ && mLastCommentName == "iTunSMPB"
+ && mLastCommentData.length() != 0) {
+ int32_t delay, padding;
+ if (sscanf(mLastCommentData,
+ " %*x %x %x %*x", &delay, &padding) == 2) {
+ mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
+ mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
+ }
+ mLastCommentMean.clear();
+ mLastCommentName.clear();
+ mLastCommentData.clear();
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (size >= 8 && metadataKey) {
+ if (metadataKey == kKeyAlbumArt) {
+ mFileMetaData->setData(
+ kKeyAlbumArt, MetaData::TYPE_NONE,
+ buffer + 8, size - 8);
+ } else if (metadataKey == kKeyGenre) {
+ if (flags == 0) {
+ // uint8_t genre code, iTunes genre codes are
+ // the standard id3 codes, except they start
+ // at 1 instead of 0 (e.g. Pop is 14, not 13)
+ // We use standard id3 numbering, so subtract 1.
+ int genrecode = (int)buffer[size - 1];
+ genrecode--;
+ if (genrecode < 0) {
+ genrecode = 255; // reserved for 'unknown genre'
+ }
+ char genre[10];
+ sprintf(genre, "%d", genrecode);
+
+ mFileMetaData->setCString(metadataKey, genre);
+ } else if (flags == 1) {
+ // custom genre string
+ buffer[size] = '\0';
+
+ mFileMetaData->setCString(
+ metadataKey, (const char *)buffer + 8);
+ }
+ } else {
+ buffer[size] = '\0';
+
+ mFileMetaData->setCString(
+ metadataKey, (const char *)buffer + 8);
+ }
+ }
+
+ delete[] buffer;
+ buffer = NULL;
+
+ return OK;
+}
+
+sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
+ status_t err;
+ if ((err = readMetaData()) != OK) {
+ return NULL;
+ }
+
+ Track *track = mFirstTrack;
+ while (index > 0) {
+ if (track == NULL) {
+ return NULL;
+ }
+
+ track = track->next;
+ --index;
+ }
+
+ if (track == NULL) {
+ return NULL;
+ }
+
+ return new MPEG4Source(
+ track->meta, mDataSource, track->timescale, track->sampleTable);
+}
+
+// static
+status_t MPEG4Extractor::verifyTrack(Track *track) {
+ const char *mime;
+ CHECK(track->meta->findCString(kKeyMIMEType, &mime));
+
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
+ || type != kTypeAVCC) {
+ return ERROR_MALFORMED;
+ }
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
+ || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+ if (!track->meta->findData(kKeyESDS, &type, &data, &size)
+ || type != kTypeESDS) {
+ return ERROR_MALFORMED;
+ }
+ }
+
+ if (!track->sampleTable->isValid()) {
+ // Make sure we have all the metadata we need.
+ return ERROR_MALFORMED;
+ }
+
+ return OK;
+}
+
+status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
+ const void *esds_data, size_t esds_size) {
+ ESDS esds(esds_data, esds_size);
+
+ uint8_t objectTypeIndication;
+ if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
+ return ERROR_MALFORMED;
+ }
+
+ if (objectTypeIndication == 0xe1) {
+ // This isn't MPEG4 audio at all, it's QCELP 14k...
+ mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
+ return OK;
+ }
+
+ if (objectTypeIndication == 0x6b) {
+ // The media subtype is MP3 audio
+ // Our software MP3 audio decoder may not be able to handle
+ // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
+ ALOGE("MP3 track in MP4/3GPP file is not supported");
+ return ERROR_UNSUPPORTED;
+ }
+
+ const uint8_t *csd;
+ size_t csd_size;
+ if (esds.getCodecSpecificInfo(
+ (const void **)&csd, &csd_size) != OK) {
+ return ERROR_MALFORMED;
+ }
+
+#if 0
+ printf("ESD of size %d\n", csd_size);
+ hexdump(csd, csd_size);
+#endif
+
+ if (csd_size == 0) {
+ // There's no further information, i.e. no codec specific data
+ // Let's assume that the information provided in the mpeg4 headers
+ // is accurate and hope for the best.
+
+ return OK;
+ }
+
+ if (csd_size < 2) {
+ return ERROR_MALFORMED;
+ }
+
+ uint32_t objectType = csd[0] >> 3;
+
+ if (objectType == 31) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
+ int32_t sampleRate = 0;
+ int32_t numChannels = 0;
+ if (freqIndex == 15) {
+ if (csd_size < 5) {
+ return ERROR_MALFORMED;
+ }
+
+ sampleRate = (csd[1] & 0x7f) << 17
+ | csd[2] << 9
+ | csd[3] << 1
+ | (csd[4] >> 7);
+
+ numChannels = (csd[4] >> 3) & 15;
+ } else {
+ static uint32_t kSamplingRate[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
+ 16000, 12000, 11025, 8000, 7350
+ };
+
+ if (freqIndex == 13 || freqIndex == 14) {
+ return ERROR_MALFORMED;
+ }
+
+ sampleRate = kSamplingRate[freqIndex];
+ numChannels = (csd[1] >> 3) & 15;
+ }
+
+ if (numChannels == 0) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ int32_t prevSampleRate;
+ CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
+
+ if (prevSampleRate != sampleRate) {
+ ALOGV("mpeg4 audio sample rate different from previous setting. "
+ "was: %d, now: %d", prevSampleRate, sampleRate);
+ }
+
+ mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
+
+ int32_t prevChannelCount;
+ CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
+
+ if (prevChannelCount != numChannels) {
+ ALOGV("mpeg4 audio channel count different from previous setting. "
+ "was: %d, now: %d", prevChannelCount, numChannels);
+ }
+
+ mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MPEG4Source::MPEG4Source(
+ const sp<MetaData> &format,
+ const sp<DataSource> &dataSource,
+ int32_t timeScale,
+ const sp<SampleTable> &sampleTable)
+ : mFormat(format),
+ mDataSource(dataSource),
+ mTimescale(timeScale),
+ mSampleTable(sampleTable),
+ mCurrentSampleIndex(0),
+ mIsAVC(false),
+ mNALLengthSize(0),
+ mStarted(false),
+ mGroup(NULL),
+ mBuffer(NULL),
+ mWantsNALFragments(false),
+ mSrcBuffer(NULL) {
+ const char *mime;
+ bool success = mFormat->findCString(kKeyMIMEType, &mime);
+ CHECK(success);
+
+ mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
+
+ if (mIsAVC) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ CHECK(format->findData(kKeyAVCC, &type, &data, &size));
+
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ CHECK(size >= 7);
+ CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
+
+ // The number of bytes used to encode the length of a NAL unit.
+ mNALLengthSize = 1 + (ptr[4] & 3);
+ }
+}
+
+MPEG4Source::~MPEG4Source() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t MPEG4Source::start(MetaData *params) {
+ Mutex::Autolock autoLock(mLock);
+
+ CHECK(!mStarted);
+
+ int32_t val;
+ if (params && params->findInt32(kKeyWantsNALFragments, &val)
+ && val != 0) {
+ mWantsNALFragments = true;
+ } else {
+ mWantsNALFragments = false;
+ }
+
+ mGroup = new MediaBufferGroup;
+
+ int32_t max_size;
+ CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
+
+ mGroup->add_buffer(new MediaBuffer(max_size));
+
+ mSrcBuffer = new uint8_t[max_size];
+
+ mStarted = true;
+
+ return OK;
+}
+
+status_t MPEG4Source::stop() {
+ Mutex::Autolock autoLock(mLock);
+
+ CHECK(mStarted);
+
+ if (mBuffer != NULL) {
+ mBuffer->release();
+ mBuffer = NULL;
+ }
+
+ delete[] mSrcBuffer;
+ mSrcBuffer = NULL;
+
+ delete mGroup;
+ mGroup = NULL;
+
+ mStarted = false;
+ mCurrentSampleIndex = 0;
+
+ return OK;
+}
+
+sp<MetaData> MPEG4Source::getFormat() {
+ Mutex::Autolock autoLock(mLock);
+
+ return mFormat;
+}
+
+size_t MPEG4Source::parseNALSize(const uint8_t *data) const {
+ switch (mNALLengthSize) {
+ case 1:
+ return *data;
+ case 2:
+ return U16_AT(data);
+ case 3:
+ return ((size_t)data[0] << 16) | U16_AT(&data[1]);
+ case 4:
+ return U32_AT(data);
+ }
+
+ // This cannot happen, mNALLengthSize springs to life by adding 1 to
+ // a 2-bit integer.
+ CHECK(!"Should not be here.");
+
+ return 0;
+}
+
+status_t MPEG4Source::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ Mutex::Autolock autoLock(mLock);
+
+ CHECK(mStarted);
+
+ *out = NULL;
+
+ int64_t targetSampleTimeUs = -1;
+
+ int64_t 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->findSampleAtTime(
+ seekTimeUs * mTimescale / 1000000,
+ &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);
+ }
+
+ uint32_t sampleTime;
+ if (err == OK) {
+ err = mSampleTable->getMetaDataForSample(
+ sampleIndex, NULL, NULL, &sampleTime);
+ }
+
+ if (err != OK) {
+ if (err == ERROR_OUT_OF_RANGE) {
+ // An attempt to seek past the end of the stream would
+ // normally cause this ERROR_OUT_OF_RANGE error. Propagating
+ // this all the way to the MediaPlayer would cause abnormal
+ // termination. Legacy behaviour appears to be to behave as if
+ // we had seeked to the end of stream, ending normally.
+ err = ERROR_END_OF_STREAM;
+ }
+ return err;
+ }
+
+ if (mode == ReadOptions::SEEK_CLOSEST) {
+ targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
+ }
+
+#if 0
+ uint32_t syncSampleTime;
+ CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
+ syncSampleIndex, NULL, NULL, &syncSampleTime));
+
+ ALOGI("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;
+ }
+
+ // fall through
+ }
+
+ off64_t offset;
+ size_t size;
+ uint32_t cts;
+ bool isSyncSample;
+ bool newBuffer = false;
+ if (mBuffer == NULL) {
+ newBuffer = true;
+
+ status_t err =
+ mSampleTable->getMetaDataForSample(
+ mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample);
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = mGroup->acquire_buffer(&mBuffer);
+
+ if (err != OK) {
+ CHECK(mBuffer == NULL);
+ return err;
+ }
+ }
+
+ if (!mIsAVC || mWantsNALFragments) {
+ if (newBuffer) {
+ ssize_t num_bytes_read =
+ mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
+
+ if (num_bytes_read < (ssize_t)size) {
+ mBuffer->release();
+ mBuffer = NULL;
+
+ return ERROR_IO;
+ }
+
+ CHECK(mBuffer != NULL);
+ mBuffer->set_range(0, size);
+ mBuffer->meta_data()->clear();
+ mBuffer->meta_data()->setInt64(
+ kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
+
+ if (targetSampleTimeUs >= 0) {
+ mBuffer->meta_data()->setInt64(
+ kKeyTargetTime, targetSampleTimeUs);
+ }
+
+ if (isSyncSample) {
+ mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ }
+
+ ++mCurrentSampleIndex;
+ }
+
+ if (!mIsAVC) {
+ *out = mBuffer;
+ mBuffer = NULL;
+
+ return OK;
+ }
+
+ // Each NAL unit is split up into its constituent fragments and
+ // each one of them returned in its own buffer.
+
+ CHECK(mBuffer->range_length() >= mNALLengthSize);
+
+ const uint8_t *src =
+ (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
+
+ size_t nal_size = parseNALSize(src);
+ if (mBuffer->range_length() < mNALLengthSize + nal_size) {
+ ALOGE("incomplete NAL unit.");
+
+ mBuffer->release();
+ mBuffer = NULL;
+
+ return ERROR_MALFORMED;
+ }
+
+ MediaBuffer *clone = mBuffer->clone();
+ CHECK(clone != NULL);
+ clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
+
+ CHECK(mBuffer != NULL);
+ mBuffer->set_range(
+ mBuffer->range_offset() + mNALLengthSize + nal_size,
+ mBuffer->range_length() - mNALLengthSize - nal_size);
+
+ if (mBuffer->range_length() == 0) {
+ mBuffer->release();
+ mBuffer = NULL;
+ }
+
+ *out = clone;
+
+ return OK;
+ } else {
+ // Whole NAL units are returned but each fragment is prefixed by
+ // the start code (0x00 00 00 01).
+ ssize_t num_bytes_read = 0;
+ int32_t drm = 0;
+ bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
+ if (usesDRM) {
+ num_bytes_read =
+ mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
+ } else {
+ num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
+ }
+
+ if (num_bytes_read < (ssize_t)size) {
+ mBuffer->release();
+ mBuffer = NULL;
+
+ return ERROR_IO;
+ }
+
+ if (usesDRM) {
+ CHECK(mBuffer != NULL);
+ mBuffer->set_range(0, size);
+
+ } else {
+ uint8_t *dstData = (uint8_t *)mBuffer->data();
+ size_t srcOffset = 0;
+ size_t dstOffset = 0;
+
+ while (srcOffset < size) {
+ bool isMalFormed = (srcOffset + mNALLengthSize > size);
+ size_t nalLength = 0;
+ if (!isMalFormed) {
+ nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
+ srcOffset += mNALLengthSize;
+ isMalFormed = srcOffset + nalLength > size;
+ }
+
+ if (isMalFormed) {
+ ALOGE("Video is malformed");
+ mBuffer->release();
+ mBuffer = NULL;
+ return ERROR_MALFORMED;
+ }
+
+ if (nalLength == 0) {
+ continue;
+ }
+
+ CHECK(dstOffset + 4 <= mBuffer->size());
+
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 1;
+ memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
+ srcOffset += nalLength;
+ dstOffset += nalLength;
+ }
+ CHECK_EQ(srcOffset, size);
+ CHECK(mBuffer != NULL);
+ mBuffer->set_range(0, dstOffset);
+ }
+
+ mBuffer->meta_data()->clear();
+ mBuffer->meta_data()->setInt64(
+ kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
+
+ if (targetSampleTimeUs >= 0) {
+ mBuffer->meta_data()->setInt64(
+ kKeyTargetTime, targetSampleTimeUs);
+ }
+
+ if (isSyncSample) {
+ mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ }
+
+ ++mCurrentSampleIndex;
+
+ *out = mBuffer;
+ mBuffer = NULL;
+
+ return OK;
+ }
+}
+
+MPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
+ const char *mimePrefix) {
+ for (Track *track = mFirstTrack; track != NULL; track = track->next) {
+ const char *mime;
+ if (track->meta != NULL
+ && track->meta->findCString(kKeyMIMEType, &mime)
+ && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
+ return track;
+ }
+ }
+
+ return NULL;
+}
+
+static bool LegacySniffMPEG4(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ uint8_t header[8];
+
+ ssize_t n = source->readAt(4, header, sizeof(header));
+ if (n < (ssize_t)sizeof(header)) {
+ return false;
+ }
+
+ if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
+ || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
+ || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
+ || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
+ || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
+ || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
+ *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
+ *confidence = 0.4;
+
+ return true;
+ }
+
+ 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'),
+
+ // Won't promise that the following file types can be played.
+ // Just give these file types a chance.
+ FOURCC('q', 't', ' ', ' '), // Apple's QuickTime
+ FOURCC('M', 'S', 'N', 'V'), // Sony's PSP
+
+ FOURCC('3', 'g', '2', 'a'), // 3GPP2
+ FOURCC('3', 'g', '2', 'b'),
+ };
+
+ 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.
+// Also try to identify where this file's metadata ends
+// (end of the 'moov' atom) and report it to the caller as part of
+// the metadata.
+static bool BetterSniffMPEG4(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *meta) {
+ // We scan up to 128 bytes to identify this file as an MP4.
+ static const off64_t kMaxScanOffset = 128ll;
+
+ off64_t offset = 0ll;
+ bool foundGoodFileType = false;
+ off64_t moovAtomEndOffset = -1ll;
+ bool done = false;
+
+ while (!done && offset < kMaxScanOffset) {
+ uint32_t hdr[2];
+ if (source->readAt(offset, hdr, 8) < 8) {
+ return false;
+ }
+
+ uint64_t chunkSize = ntohl(hdr[0]);
+ uint32_t chunkType = ntohl(hdr[1]);
+ off64_t chunkDataOffset = offset + 8;
+
+ if (chunkSize == 1) {
+ if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
+ return false;
+ }
+
+ chunkSize = ntoh64(chunkSize);
+ chunkDataOffset += 8;
+
+ if (chunkSize < 16) {
+ // The smallest valid chunk is 16 bytes long in this case.
+ return false;
+ }
+ } else if (chunkSize < 8) {
+ // The smallest valid chunk is 8 bytes long.
+ return false;
+ }
+
+ off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
+
+ switch (chunkType) {
+ case FOURCC('f', 't', 'y', 'p'):
+ {
+ if (chunkDataSize < 8) {
+ return false;
+ }
+
+ uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
+ for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
+ if (i == 1) {
+ // Skip this index, it refers to the minorVersion,
+ // not a brand.
+ continue;
+ }
+
+ uint32_t brand;
+ if (source->readAt(
+ chunkDataOffset + 4 * i, &brand, 4) < 4) {
+ return false;
+ }
+
+ brand = ntohl(brand);
+
+ if (isCompatibleBrand(brand)) {
+ foundGoodFileType = true;
+ break;
+ }
+ }
+
+ if (!foundGoodFileType) {
+ return false;
+ }
+
+ break;
+ }
+
+ case FOURCC('m', 'o', 'o', 'v'):
+ {
+ moovAtomEndOffset = offset + chunkSize;
+
+ done = true;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ offset += chunkSize;
+ }
+
+ if (!foundGoodFileType) {
+ return false;
+ }
+
+ *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
+ *confidence = 0.4f;
+
+ if (moovAtomEndOffset >= 0) {
+ *meta = new AMessage;
+ (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
+
+ ALOGV("found metadata size: %lld", moovAtomEndOffset);
+ }
+
+ return true;
+}
+
+bool SniffMPEG4(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *meta) {
+ if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
+ return true;
+ }
+
+ if (LegacySniffMPEG4(source, mimeType, confidence)) {
+ ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace android
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
new file mode 100755
index 0000000..7ebbe1d
--- /dev/null
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -0,0 +1,2862 @@
+/*
+ * 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 "MPEG4Writer"
+#include <utils/Log.h>
+
+#include <arpa/inet.h>
+
+#include <pthread.h>
+#include <sys/prctl.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MPEG4Writer.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MetaData.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 <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "include/ESDS.h"
+
+namespace android {
+
+static const int64_t kMax32BitFileSize = 0x007fffffffLL;
+static const uint8_t kNalUnitTypeSeqParamSet = 0x07;
+static const uint8_t kNalUnitTypePicParamSet = 0x08;
+static const int64_t kInitialDelayTimeUs = 700000LL;
+
+class MPEG4Writer::Track {
+public:
+ Track(MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId);
+
+ ~Track();
+
+ status_t start(MetaData *params);
+ status_t stop();
+ status_t pause();
+ bool reachedEOS();
+
+ int64_t getDurationUs() const;
+ int64_t getEstimatedTrackSizeBytes() const;
+ void writeTrackHeader(bool use32BitOffset = true);
+ void bufferChunk(int64_t timestampUs);
+ bool isAvc() const { return mIsAvc; }
+ bool isAudio() const { return mIsAudio; }
+ bool isMPEG4() const { return mIsMPEG4; }
+ void addChunkOffset(off64_t offset);
+ int32_t getTrackId() const { return mTrackId; }
+ status_t dump(int fd, const Vector<String16>& args) const;
+
+private:
+ enum {
+ kMaxCttsOffsetTimeUs = 1000000LL, // 1 second
+ };
+
+ MPEG4Writer *mOwner;
+ sp<MetaData> mMeta;
+ sp<MediaSource> mSource;
+ volatile bool mDone;
+ volatile bool mPaused;
+ volatile bool mResumed;
+ volatile bool mStarted;
+ bool mIsAvc;
+ bool mIsAudio;
+ bool mIsMPEG4;
+ int32_t mTrackId;
+ int64_t mTrackDurationUs;
+ int64_t mMaxChunkDurationUs;
+
+ bool mIsRealTimeRecording;
+ int64_t mMaxTimeStampUs;
+ int64_t mEstimatedTrackSizeBytes;
+ int64_t mMdatSizeBytes;
+ int32_t mTimeScale;
+
+ pthread_t mThread;
+
+ // 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;
+
+ size_t mNumStcoTableEntries;
+ List<off64_t> mChunkOffsets;
+
+ size_t mNumStscTableEntries;
+ 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<StscTableEntry> mStscTableEntries;
+
+ size_t mNumStssTableEntries;
+ List<int32_t> mStssTableEntries;
+
+ struct SttsTableEntry {
+
+ SttsTableEntry(uint32_t count, uint32_t duration)
+ : sampleCount(count), sampleDuration(duration) {}
+
+ uint32_t sampleCount;
+ uint32_t sampleDuration; // time scale based
+ };
+ size_t mNumSttsTableEntries;
+ List<SttsTableEntry> mSttsTableEntries;
+
+ struct CttsTableEntry {
+ CttsTableEntry(uint32_t count, int32_t timescaledDur)
+ : sampleCount(count), sampleDuration(timescaledDur) {}
+
+ uint32_t sampleCount;
+ uint32_t sampleDuration; // time scale based
+ };
+ size_t mNumCttsTableEntries;
+ List<CttsTableEntry> mCttsTableEntries;
+ int64_t mMinCttsOffsetTimeUs;
+ int64_t mMaxCttsOffsetTimeUs;
+
+ // Sequence parameter set or picture parameter set
+ struct AVCParamSet {
+ AVCParamSet(uint16_t length, const uint8_t *data)
+ : mLength(length), mData(data) {}
+
+ uint16_t mLength;
+ const uint8_t *mData;
+ };
+ List<AVCParamSet> mSeqParamSets;
+ List<AVCParamSet> mPicParamSets;
+ uint8_t mProfileIdc;
+ uint8_t mProfileCompatible;
+ uint8_t mLevelIdc;
+
+ void *mCodecSpecificData;
+ size_t mCodecSpecificDataSize;
+ bool mGotAllCodecSpecificData;
+ bool mTrackingProgressStatus;
+
+ bool mReachedEOS;
+ int64_t mStartTimestampUs;
+ int64_t mStartTimeRealUs;
+ int64_t mFirstSampleTimeRealUs;
+ int64_t mPreviousTrackTimeUs;
+ int64_t mTrackEveryTimeDurationUs;
+
+ // Update the audio track's drift information.
+ void updateDriftTime(const sp<MetaData>& meta);
+
+ int32_t getStartTimeOffsetScaledTime() const;
+
+ static void *ThreadWrapper(void *me);
+ status_t threadEntry();
+
+ const uint8_t *parseParamSet(
+ const uint8_t *data, size_t length, int type, size_t *paramSetLen);
+
+ status_t makeAVCCodecSpecificData(const uint8_t *data, size_t size);
+ status_t copyAVCCodecSpecificData(const uint8_t *data, size_t size);
+ status_t parseAVCCodecSpecificData(const uint8_t *data, size_t size);
+
+ // Track authoring progress status
+ void trackProgressStatus(int64_t timeUs, status_t err = OK);
+ void initTrackingProgressStatus(MetaData *params);
+
+ void getCodecSpecificDataFromInputFormatIfPossible();
+
+ // Determine the track time scale
+ // If it is an audio track, try to use the sampling rate as
+ // the time scale; however, if user chooses the overwrite
+ // value, the user-supplied time scale will be used.
+ void setTimeScale();
+
+ // Simple validation on the codec specific data
+ status_t checkCodecSpecificData() const;
+ int32_t mRotation;
+
+ void updateTrackSizeEstimate();
+ void addOneStscTableEntry(size_t chunkId, size_t sampleId);
+ void addOneStssTableEntry(size_t sampleId);
+
+ // Duration is time scale based
+ void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
+ void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
+
+ bool isTrackMalFormed() const;
+ void sendTrackSummary(bool hasMultipleTracks);
+
+ // Write the boxes
+ void writeStcoBox(bool use32BitOffset);
+ void writeStscBox();
+ void writeStszBox();
+ void writeStssBox();
+ void writeSttsBox();
+ void writeCttsBox();
+ void writeD263Box();
+ void writePaspBox();
+ void writeAvccBox();
+ void writeUrlBox();
+ void writeDrefBox();
+ void writeDinfBox();
+ void writeDamrBox();
+ void writeMdhdBox(time_t now);
+ void writeSmhdBox();
+ void writeVmhdBox();
+ void writeHdlrBox();
+ void writeTkhdBox(time_t now);
+ void writeMp4aEsdsBox();
+ void writeMp4vEsdsBox();
+ void writeAudioFourCCBox();
+ void writeVideoFourCCBox();
+ void writeStblBox(bool use32BitOffset);
+
+ Track(const Track &);
+ Track &operator=(const Track &);
+};
+
+MPEG4Writer::MPEG4Writer(const char *filename)
+ : mFd(-1),
+ mInitCheck(NO_INIT),
+ mUse4ByteNalLength(true),
+ mUse32BitOffset(true),
+ mIsFileSizeLimitExplicitlyRequested(false),
+ mPaused(false),
+ mStarted(false),
+ mWriterThreadStarted(false),
+ mOffset(0),
+ mMdatOffset(0),
+ mEstimatedMoovBoxSize(0),
+ mInterleaveDurationUs(1000000),
+ mLatitudex10000(0),
+ mLongitudex10000(0),
+ mAreGeoTagsAvailable(false),
+ mStartTimeOffsetMs(-1) {
+
+ mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR);
+ if (mFd >= 0) {
+ mInitCheck = OK;
+ }
+}
+
+MPEG4Writer::MPEG4Writer(int fd)
+ : mFd(dup(fd)),
+ mInitCheck(mFd < 0? NO_INIT: OK),
+ mUse4ByteNalLength(true),
+ mUse32BitOffset(true),
+ mIsFileSizeLimitExplicitlyRequested(false),
+ mPaused(false),
+ mStarted(false),
+ mWriterThreadStarted(false),
+ mOffset(0),
+ mMdatOffset(0),
+ mEstimatedMoovBoxSize(0),
+ mInterleaveDurationUs(1000000),
+ mLatitudex10000(0),
+ mLongitudex10000(0),
+ mAreGeoTagsAvailable(false),
+ mStartTimeOffsetMs(-1) {
+}
+
+MPEG4Writer::~MPEG4Writer() {
+ reset();
+
+ while (!mTracks.empty()) {
+ List<Track *>::iterator it = mTracks.begin();
+ delete *it;
+ (*it) = NULL;
+ mTracks.erase(it);
+ }
+ mTracks.clear();
+}
+
+status_t MPEG4Writer::dump(
+ int fd, const Vector<String16>& args) {
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ snprintf(buffer, SIZE, " MPEG4Writer %p\n", this);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " mStarted: %s\n", mStarted? "true": "false");
+ result.append(buffer);
+ ::write(fd, result.string(), result.size());
+ for (List<Track *>::iterator it = mTracks.begin();
+ it != mTracks.end(); ++it) {
+ (*it)->dump(fd, args);
+ }
+ return OK;
+}
+
+status_t MPEG4Writer::Track::dump(
+ int fd, const Vector<String16>& args) const {
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ snprintf(buffer, SIZE, " %s track\n", mIsAudio? "Audio": "Video");
+ result.append(buffer);
+ snprintf(buffer, SIZE, " reached EOS: %s\n",
+ mReachedEOS? "true": "false");
+ result.append(buffer);
+ ::write(fd, result.string(), result.size());
+ return OK;
+}
+
+status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
+ Mutex::Autolock l(mLock);
+ if (mStarted) {
+ ALOGE("Attempt to add source AFTER recording is started");
+ return UNKNOWN_ERROR;
+ }
+ Track *track = new Track(this, source, mTracks.size());
+ mTracks.push_back(track);
+
+ return OK;
+}
+
+status_t MPEG4Writer::startTracks(MetaData *params) {
+ for (List<Track *>::iterator it = mTracks.begin();
+ it != mTracks.end(); ++it) {
+ status_t err = (*it)->start(params);
+
+ if (err != OK) {
+ for (List<Track *>::iterator it2 = mTracks.begin();
+ it2 != it; ++it2) {
+ (*it2)->stop();
+ }
+
+ 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%.
+
+ // The default MIN_MOOV_BOX_SIZE is set to 0.6% x 1MB / 2,
+ // where 1MB is the common file size limit for MMS application.
+ // The default MAX _MOOV_BOX_SIZE value is based on about 3
+ // 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 = 3 * 1024; // 3 KB
+ static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
+ int64_t size = MIN_MOOV_BOX_SIZE;
+
+ // Max file size limit is set
+ if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
+ size = mMaxFileSizeLimitBytes * 6 / 1000;
+ }
+
+ // Max file duration limit is set
+ if (mMaxFileDurationLimitUs != 0) {
+ if (bitRate > 0) {
+ int64_t size2 =
+ ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
+ if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
+ // When both file size and duration limits are set,
+ // we use the smaller limit of the two.
+ if (size > size2) {
+ size = size2;
+ }
+ } else {
+ // Only max file duration limit is set
+ size = size2;
+ }
+ }
+ }
+
+ 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;
+ }
+
+ ALOGI("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 (mInitCheck != OK) {
+ return UNKNOWN_ERROR;
+ }
+
+ /*
+ * Check mMaxFileSizeLimitBytes at the beginning
+ * since mMaxFileSizeLimitBytes may be implicitly
+ * changed later for 32-bit file offset even if
+ * user does not ask to set it explicitly.
+ */
+ if (mMaxFileSizeLimitBytes != 0) {
+ mIsFileSizeLimitExplicitlyRequested = true;
+ }
+
+ int32_t use64BitOffset;
+ if (param &&
+ param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
+ use64BitOffset) {
+ mUse32BitOffset = false;
+ }
+
+ if (mUse32BitOffset) {
+ // Implicit 32 bit file size limit
+ if (mMaxFileSizeLimitBytes == 0) {
+ mMaxFileSizeLimitBytes = kMax32BitFileSize;
+ }
+
+ // If file size is set to be larger than the 32 bit file
+ // size limit, treat it as an error.
+ if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
+ ALOGW("32-bit file size limit (%lld bytes) too big. "
+ "It is changed to %lld bytes",
+ mMaxFileSizeLimitBytes, kMax32BitFileSize);
+ mMaxFileSizeLimitBytes = kMax32BitFileSize;
+ }
+ }
+
+ int32_t use2ByteNalLength;
+ if (param &&
+ param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
+ use2ByteNalLength) {
+ mUse4ByteNalLength = false;
+ }
+
+ mStartTimestampUs = -1;
+
+ if (mStarted) {
+ if (mPaused) {
+ mPaused = false;
+ return startTracks(param);
+ }
+ return OK;
+ }
+
+ if (!param ||
+ !param->findInt32(kKeyTimeScale, &mTimeScale)) {
+ mTimeScale = 1000;
+ }
+ CHECK_GT(mTimeScale, 0);
+ ALOGV("movie time scale: %d", mTimeScale);
+
+ mStreamableFile = true;
+ mWriteMoovBoxToMemory = false;
+ mMoovBoxBuffer = NULL;
+ mMoovBoxBufferOffset = 0;
+
+ writeFtypBox(param);
+
+ mFreeBoxOffset = mOffset;
+
+ if (mEstimatedMoovBoxSize == 0) {
+ int32_t bitRate = -1;
+ if (param) {
+ param->findInt32(kKeyBitRate, &bitRate);
+ }
+ mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
+ }
+ CHECK_GE(mEstimatedMoovBoxSize, 8);
+ lseek64(mFd, mFreeBoxOffset, SEEK_SET);
+ writeInt32(mEstimatedMoovBoxSize);
+ write("free", 4);
+
+ mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
+ mOffset = mMdatOffset;
+ lseek64(mFd, mMdatOffset, SEEK_SET);
+ if (mUse32BitOffset) {
+ write("????mdat", 8);
+ } else {
+ write("\x00\x00\x00\x01mdat????????", 16);
+ }
+
+ status_t err = startWriterThread();
+ if (err != OK) {
+ return err;
+ }
+
+ err = startTracks(param);
+ if (err != OK) {
+ return err;
+ }
+
+ mStarted = true;
+ return OK;
+}
+
+bool MPEG4Writer::use32BitFileOffset() const {
+ return mUse32BitOffset;
+}
+
+status_t MPEG4Writer::pause() {
+ if (mInitCheck != OK) {
+ return OK;
+ }
+ mPaused = true;
+ status_t err = OK;
+ for (List<Track *>::iterator it = mTracks.begin();
+ it != mTracks.end(); ++it) {
+ status_t status = (*it)->pause();
+ if (status != OK) {
+ err = status;
+ }
+ }
+ return err;
+}
+
+void MPEG4Writer::stopWriterThread() {
+ ALOGD("Stopping writer thread");
+ if (!mWriterThreadStarted) {
+ return;
+ }
+
+ {
+ Mutex::Autolock autolock(mLock);
+
+ mDone = true;
+ mChunkReadyCondition.signal();
+ }
+
+ void *dummy;
+ pthread_join(mThread, &dummy);
+ mWriterThreadStarted = false;
+ ALOGD("Writer thread stopped");
+}
+
+/*
+ * MP4 file standard defines a composition matrix:
+ * | a b u |
+ * | c d v |
+ * | x y w |
+ *
+ * the element in the matrix is stored in the following
+ * order: {a, b, u, c, d, v, x, y, w},
+ * where a, b, c, d, x, and y is in 16.16 format, while
+ * u, v and w is in 2.30 format.
+ */
+void MPEG4Writer::writeCompositionMatrix(int degrees) {
+ ALOGV("writeCompositionMatrix");
+ uint32_t a = 0x00010000;
+ uint32_t b = 0;
+ uint32_t c = 0;
+ uint32_t d = 0x00010000;
+ switch (degrees) {
+ case 0:
+ break;
+ case 90:
+ a = 0;
+ b = 0x00010000;
+ c = 0xFFFF0000;
+ d = 0;
+ break;
+ case 180:
+ a = 0xFFFF0000;
+ d = 0xFFFF0000;
+ break;
+ case 270:
+ a = 0;
+ b = 0xFFFF0000;
+ c = 0x00010000;
+ d = 0;
+ break;
+ default:
+ CHECK(!"Should never reach this unknown rotation");
+ break;
+ }
+
+ writeInt32(a); // a
+ writeInt32(b); // b
+ writeInt32(0); // u
+ writeInt32(c); // c
+ writeInt32(d); // d
+ writeInt32(0); // v
+ writeInt32(0); // x
+ writeInt32(0); // y
+ writeInt32(0x40000000); // w
+}
+
+void MPEG4Writer::release() {
+ close(mFd);
+ mFd = -1;
+ mInitCheck = NO_INIT;
+ mStarted = false;
+}
+
+status_t MPEG4Writer::reset() {
+ if (mInitCheck != OK) {
+ return OK;
+ } else {
+ if (!mWriterThreadStarted ||
+ !mStarted) {
+ if (mWriterThreadStarted) {
+ stopWriterThread();
+ }
+ release();
+ return OK;
+ }
+ }
+
+ status_t err = OK;
+ int64_t maxDurationUs = 0;
+ int64_t minDurationUs = 0x7fffffffffffffffLL;
+ for (List<Track *>::iterator it = mTracks.begin();
+ it != mTracks.end(); ++it) {
+ status_t status = (*it)->stop();
+ if (err == OK && status != OK) {
+ err = status;
+ }
+
+ int64_t durationUs = (*it)->getDurationUs();
+ if (durationUs > maxDurationUs) {
+ maxDurationUs = durationUs;
+ }
+ if (durationUs < minDurationUs) {
+ minDurationUs = durationUs;
+ }
+ }
+
+ if (mTracks.size() > 1) {
+ ALOGD("Duration from tracks range is [%lld, %lld] us",
+ minDurationUs, maxDurationUs);
+ }
+
+ stopWriterThread();
+
+ // Do not write out movie header on error.
+ if (err != OK) {
+ release();
+ return err;
+ }
+
+ // Fix up the size of the 'mdat' chunk.
+ if (mUse32BitOffset) {
+ lseek64(mFd, mMdatOffset, SEEK_SET);
+ int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
+ ::write(mFd, &size, 4);
+ } else {
+ lseek64(mFd, mMdatOffset + 8, SEEK_SET);
+ int64_t size = mOffset - mMdatOffset;
+ size = hton64(size);
+ ::write(mFd, &size, 8);
+ }
+ lseek64(mFd, mOffset, SEEK_SET);
+
+ const off64_t moovOffset = mOffset;
+ mWriteMoovBoxToMemory = true;
+ mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
+ mMoovBoxBufferOffset = 0;
+ CHECK(mMoovBoxBuffer != NULL);
+ writeMoovBox(maxDurationUs);
+
+ mWriteMoovBoxToMemory = false;
+ if (mStreamableFile) {
+ CHECK_LE(mMoovBoxBufferOffset + 8, mEstimatedMoovBoxSize);
+
+ // Moov box
+ lseek64(mFd, mFreeBoxOffset, SEEK_SET);
+ mOffset = mFreeBoxOffset;
+ write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
+
+ // Free box
+ lseek64(mFd, mOffset, SEEK_SET);
+ writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
+ write("free", 4);
+
+ // Free temp memory
+ free(mMoovBoxBuffer);
+ mMoovBoxBuffer = NULL;
+ mMoovBoxBufferOffset = 0;
+ } else {
+ ALOGI("The mp4 file will not be streamable.");
+ }
+
+ CHECK(mBoxes.empty());
+
+ release();
+ return err;
+}
+
+void MPEG4Writer::writeMvhdBox(int64_t durationUs) {
+ time_t now = time(NULL);
+ beginBox("mvhd");
+ writeInt32(0); // version=0, flags=0
+ writeInt32(now); // creation time
+ writeInt32(now); // modification time
+ writeInt32(mTimeScale); // mvhd timescale
+ int32_t duration = (durationUs * mTimeScale + 5E5) / 1E6;
+ writeInt32(duration);
+ writeInt32(0x10000); // rate: 1.0
+ writeInt16(0x100); // volume
+ writeInt16(0); // reserved
+ writeInt32(0); // reserved
+ writeInt32(0); // reserved
+ writeCompositionMatrix(0); // matrix
+ writeInt32(0); // predefined
+ writeInt32(0); // predefined
+ writeInt32(0); // predefined
+ writeInt32(0); // predefined
+ writeInt32(0); // predefined
+ writeInt32(0); // predefined
+ writeInt32(mTracks.size() + 1); // nextTrackID
+ endBox(); // mvhd
+}
+
+void MPEG4Writer::writeMoovBox(int64_t durationUs) {
+ beginBox("moov");
+ writeMvhdBox(durationUs);
+ if (mAreGeoTagsAvailable) {
+ writeUdtaBox();
+ }
+ int32_t id = 1;
+ for (List<Track *>::iterator it = mTracks.begin();
+ it != mTracks.end(); ++it, ++id) {
+ (*it)->writeTrackHeader(mUse32BitOffset);
+ }
+ endBox(); // moov
+}
+
+void MPEG4Writer::writeFtypBox(MetaData *param) {
+ 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();
+}
+
+static bool isTestModeEnabled() {
+#if (PROPERTY_VALUE_MAX < 5)
+#error "PROPERTY_VALUE_MAX must be at least 5"
+#endif
+
+ // Test mode is enabled only if rw.media.record.test system
+ // property is enabled.
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("rw.media.record.test", value, NULL) &&
+ (!strcasecmp(value, "true") || !strcasecmp(value, "1"))) {
+ return true;
+ }
+ return false;
+}
+
+void MPEG4Writer::sendSessionSummary() {
+ // Send session summary only if test mode is enabled
+ if (!isTestModeEnabled()) {
+ return;
+ }
+
+ for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
+ it != mChunkInfos.end(); ++it) {
+ int trackNum = it->mTrack->getTrackId() << 28;
+ notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS,
+ it->mMaxInterChunkDurUs);
+ }
+}
+
+status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
+ mInterleaveDurationUs = durationUs;
+ return OK;
+}
+
+void MPEG4Writer::lock() {
+ mLock.lock();
+}
+
+void MPEG4Writer::unlock() {
+ mLock.unlock();
+}
+
+off64_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
+ off64_t old_offset = mOffset;
+
+ ::write(mFd,
+ (const uint8_t *)buffer->data() + buffer->range_offset(),
+ buffer->range_length());
+
+ mOffset += buffer->range_length();
+
+ return old_offset;
+}
+
+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);
+ }
+}
+
+off64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
+ off64_t old_offset = mOffset;
+
+ size_t length = buffer->range_length();
+
+ if (mUse4ByteNalLength) {
+ uint8_t x = length >> 24;
+ ::write(mFd, &x, 1);
+ x = (length >> 16) & 0xff;
+ ::write(mFd, &x, 1);
+ x = (length >> 8) & 0xff;
+ ::write(mFd, &x, 1);
+ x = length & 0xff;
+ ::write(mFd, &x, 1);
+
+ ::write(mFd,
+ (const uint8_t *)buffer->data() + buffer->range_offset(),
+ length);
+
+ mOffset += length + 4;
+ } else {
+ CHECK_LT(length, 65536);
+
+ uint8_t x = length >> 8;
+ ::write(mFd, &x, 1);
+ x = length & 0xff;
+ ::write(mFd, &x, 1);
+ ::write(mFd, (const uint8_t *)buffer->data() + buffer->range_offset(), length);
+ mOffset += length + 2;
+ }
+
+ return old_offset;
+}
+
+size_t MPEG4Writer::write(
+ const void *ptr, size_t size, size_t nmemb) {
+
+ const size_t bytes = size * nmemb;
+ if (mWriteMoovBoxToMemory) {
+ // This happens only when we write the moov box at the end of
+ // recording, not for each output video/audio frame we receive.
+ off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
+ if (moovBoxSize > mEstimatedMoovBoxSize) {
+ for (List<off64_t>::iterator it = mBoxes.begin();
+ it != mBoxes.end(); ++it) {
+ (*it) += mOffset;
+ }
+ lseek64(mFd, mOffset, SEEK_SET);
+ ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
+ ::write(mFd, ptr, size * nmemb);
+ mOffset += (bytes + mMoovBoxBufferOffset);
+ free(mMoovBoxBuffer);
+ mMoovBoxBuffer = NULL;
+ mMoovBoxBufferOffset = 0;
+ mWriteMoovBoxToMemory = false;
+ mStreamableFile = false;
+ } else {
+ memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
+ mMoovBoxBufferOffset += bytes;
+ }
+ } else {
+ ::write(mFd, ptr, size * nmemb);
+ mOffset += bytes;
+ }
+ return bytes;
+}
+
+void MPEG4Writer::beginBox(const char *fourcc) {
+ CHECK_EQ(strlen(fourcc), 4);
+
+ mBoxes.push_back(mWriteMoovBoxToMemory?
+ mMoovBoxBufferOffset: mOffset);
+
+ writeInt32(0);
+ writeFourcc(fourcc);
+}
+
+void MPEG4Writer::endBox() {
+ CHECK(!mBoxes.empty());
+
+ off64_t offset = *--mBoxes.end();
+ mBoxes.erase(--mBoxes.end());
+
+ if (mWriteMoovBoxToMemory) {
+ int32_t x = htonl(mMoovBoxBufferOffset - offset);
+ memcpy(mMoovBoxBuffer + offset, &x, 4);
+ } else {
+ lseek64(mFd, offset, SEEK_SET);
+ writeInt32(mOffset - offset);
+ mOffset -= 4;
+ lseek64(mFd, mOffset, SEEK_SET);
+ }
+}
+
+void MPEG4Writer::writeInt8(int8_t x) {
+ write(&x, 1, 1);
+}
+
+void MPEG4Writer::writeInt16(int16_t x) {
+ x = htons(x);
+ write(&x, 1, 2);
+}
+
+void MPEG4Writer::writeInt32(int32_t x) {
+ x = htonl(x);
+ write(&x, 1, 4);
+}
+
+void MPEG4Writer::writeInt64(int64_t x) {
+ x = hton64(x);
+ write(&x, 1, 8);
+}
+
+void MPEG4Writer::writeCString(const char *s) {
+ size_t n = strlen(s);
+ write(s, 1, n + 1);
+}
+
+void MPEG4Writer::writeFourcc(const char *s) {
+ CHECK_EQ(strlen(s), 4);
+ write(s, 1, 4);
+}
+
+
+// Written in +/-DD.DDDD format
+void MPEG4Writer::writeLatitude(int degreex10000) {
+ bool isNegative = (degreex10000 < 0);
+ char sign = isNegative? '-': '+';
+
+ // Handle the whole part
+ char str[9];
+ int wholePart = degreex10000 / 10000;
+ if (wholePart == 0) {
+ snprintf(str, 5, "%c%.2d.", sign, wholePart);
+ } else {
+ snprintf(str, 5, "%+.2d.", wholePart);
+ }
+
+ // Handle the fractional part
+ int fractionalPart = degreex10000 - (wholePart * 10000);
+ if (fractionalPart < 0) {
+ fractionalPart = -fractionalPart;
+ }
+ snprintf(&str[4], 5, "%.4d", fractionalPart);
+
+ // Do not write the null terminator
+ write(str, 1, 8);
+}
+
+// Written in +/- DDD.DDDD format
+void MPEG4Writer::writeLongitude(int degreex10000) {
+ bool isNegative = (degreex10000 < 0);
+ char sign = isNegative? '-': '+';
+
+ // Handle the whole part
+ char str[10];
+ int wholePart = degreex10000 / 10000;
+ if (wholePart == 0) {
+ snprintf(str, 6, "%c%.3d.", sign, wholePart);
+ } else {
+ snprintf(str, 6, "%+.3d.", wholePart);
+ }
+
+ // Handle the fractional part
+ int fractionalPart = degreex10000 - (wholePart * 10000);
+ if (fractionalPart < 0) {
+ fractionalPart = -fractionalPart;
+ }
+ snprintf(&str[5], 5, "%.4d", fractionalPart);
+
+ // Do not write the null terminator
+ write(str, 1, 9);
+}
+
+/*
+ * Geodata is stored according to ISO-6709 standard.
+ * latitudex10000 is latitude in degrees times 10000, and
+ * longitudex10000 is longitude in degrees times 10000.
+ * The range for the latitude is in [-90, +90], and
+ * The range for the longitude is in [-180, +180]
+ */
+status_t MPEG4Writer::setGeoData(int latitudex10000, int longitudex10000) {
+ // Is latitude or longitude out of range?
+ if (latitudex10000 < -900000 || latitudex10000 > 900000 ||
+ longitudex10000 < -1800000 || longitudex10000 > 1800000) {
+ return BAD_VALUE;
+ }
+
+ mLatitudex10000 = latitudex10000;
+ mLongitudex10000 = longitudex10000;
+ mAreGeoTagsAvailable = true;
+ return OK;
+}
+
+void MPEG4Writer::write(const void *data, size_t size) {
+ write(data, 1, size);
+}
+
+bool MPEG4Writer::isFileStreamable() const {
+ return mStreamableFile;
+}
+
+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();
+ }
+
+ // Be conservative in the estimate: do not exceed 95% of
+ // the target file limit. For small target file size limit, though,
+ // this will not help.
+ return (nTotalBytesEstimate >= (95 * mMaxFileSizeLimitBytes) / 100);
+}
+
+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() {
+ bool allDone = true;
+ for (List<Track *>::iterator it = mTracks.begin();
+ it != mTracks.end(); ++it) {
+ if (!(*it)->reachedEOS()) {
+ allDone = false;
+ break;
+ }
+ }
+
+ return allDone;
+}
+
+void MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
+ ALOGI("setStartTimestampUs: %lld", timeUs);
+ CHECK_GE(timeUs, 0ll);
+ Mutex::Autolock autoLock(mLock);
+ if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
+ mStartTimestampUs = timeUs;
+ ALOGI("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(
+ MPEG4Writer *owner, const sp<MediaSource> &source, size_t trackId)
+ : mOwner(owner),
+ mMeta(source->getFormat()),
+ mSource(source),
+ mDone(false),
+ mPaused(false),
+ mResumed(false),
+ mStarted(false),
+ mTrackId(trackId),
+ mTrackDurationUs(0),
+ mEstimatedTrackSizeBytes(0),
+ mSamplesHaveSameSize(true),
+ mCodecSpecificData(NULL),
+ mCodecSpecificDataSize(0),
+ mGotAllCodecSpecificData(false),
+ mReachedEOS(false),
+ mRotation(0) {
+ getCodecSpecificDataFromInputFormatIfPossible();
+
+ const char *mime;
+ mMeta->findCString(kKeyMIMEType, &mime);
+ mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
+ mIsAudio = !strncasecmp(mime, "audio/", 6);
+ mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
+ !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
+
+ setTimeScale();
+}
+
+void MPEG4Writer::Track::updateTrackSizeEstimate() {
+
+ int64_t stcoBoxSizeBytes = mOwner->use32BitFileOffset()
+ ? mNumStcoTableEntries * 4
+ : mNumStcoTableEntries * 8;
+
+ int64_t stszBoxSizeBytes = mSamplesHaveSameSize? 4: (mNumSamples * 4);
+
+ mEstimatedTrackSizeBytes = mMdatSizeBytes; // media data size
+ if (!mOwner->isFileStreamable()) {
+ // Reserved free space is not large enough to hold
+ // all meta data and thus wasted.
+ mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 + // stsc box size
+ mNumStssTableEntries * 4 + // stss box size
+ mNumSttsTableEntries * 8 + // stts box size
+ mNumCttsTableEntries * 8 + // ctts box size
+ stcoBoxSizeBytes + // stco box size
+ stszBoxSizeBytes; // stsz box size
+ }
+}
+
+void MPEG4Writer::Track::addOneStscTableEntry(
+ size_t chunkId, size_t sampleId) {
+
+ StscTableEntry stscEntry(chunkId, sampleId, 1);
+ mStscTableEntries.push_back(stscEntry);
+ ++mNumStscTableEntries;
+}
+
+void MPEG4Writer::Track::addOneStssTableEntry(size_t sampleId) {
+ mStssTableEntries.push_back(sampleId);
+ ++mNumStssTableEntries;
+}
+
+void MPEG4Writer::Track::addOneSttsTableEntry(
+ size_t sampleCount, int32_t duration) {
+
+ if (duration == 0) {
+ ALOGW("0-duration samples found: %d", sampleCount);
+ }
+ SttsTableEntry sttsEntry(sampleCount, duration);
+ mSttsTableEntries.push_back(sttsEntry);
+ ++mNumSttsTableEntries;
+}
+
+void MPEG4Writer::Track::addOneCttsTableEntry(
+ size_t sampleCount, int32_t duration) {
+
+ if (mIsAudio) {
+ return;
+ }
+ CttsTableEntry cttsEntry(sampleCount, duration);
+ mCttsTableEntries.push_back(cttsEntry);
+ ++mNumCttsTableEntries;
+}
+
+void MPEG4Writer::Track::addChunkOffset(off64_t offset) {
+ ++mNumStcoTableEntries;
+ mChunkOffsets.push_back(offset);
+}
+
+void MPEG4Writer::Track::setTimeScale() {
+ ALOGV("setTimeScale");
+ // Default time scale
+ mTimeScale = 90000;
+
+ if (mIsAudio) {
+ // Use the sampling rate as the default time scale for audio track.
+ int32_t sampleRate;
+ bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
+ CHECK(success);
+ mTimeScale = sampleRate;
+ }
+
+ // If someone would like to overwrite the timescale, use user-supplied value.
+ int32_t timeScale;
+ if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
+ mTimeScale = timeScale;
+ }
+
+ CHECK_GT(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() {
+ stop();
+
+ if (mCodecSpecificData != NULL) {
+ free(mCodecSpecificData);
+ mCodecSpecificData = NULL;
+ }
+}
+
+void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
+ ALOGV("initTrackingProgressStatus");
+ mPreviousTrackTimeUs = -1;
+ mTrackingProgressStatus = false;
+ mTrackEveryTimeDurationUs = 0;
+ {
+ int64_t timeUs;
+ if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
+ ALOGV("Receive request to track progress status for every %lld us", timeUs);
+ mTrackEveryTimeDurationUs = timeUs;
+ mTrackingProgressStatus = true;
+ }
+ }
+}
+
+// static
+void *MPEG4Writer::ThreadWrapper(void *me) {
+ ALOGV("ThreadWrapper: %p", me);
+ MPEG4Writer *writer = static_cast<MPEG4Writer *>(me);
+ writer->threadFunc();
+ return NULL;
+}
+
+void MPEG4Writer::bufferChunk(const Chunk& chunk) {
+ ALOGV("bufferChunk: %p", chunk.mTrack);
+ Mutex::Autolock autolock(mLock);
+ CHECK_EQ(mDone, false);
+
+ for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
+ it != mChunkInfos.end(); ++it) {
+
+ if (chunk.mTrack == it->mTrack) { // Found owner
+ it->mChunks.push_back(chunk);
+ mChunkReadyCondition.signal();
+ return;
+ }
+ }
+
+ CHECK(!"Received a chunk for a unknown track");
+}
+
+void MPEG4Writer::writeChunkToFile(Chunk* chunk) {
+ ALOGV("writeChunkToFile: %lld from %s track",
+ chunk->mTimeStampUs, chunk->mTrack->isAudio()? "audio": "video");
+
+ int32_t isFirstSample = true;
+ while (!chunk->mSamples.empty()) {
+ List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
+
+ off64_t offset = chunk->mTrack->isAvc()
+ ? addLengthPrefixedSample_l(*it)
+ : addSample_l(*it);
+
+ if (isFirstSample) {
+ chunk->mTrack->addChunkOffset(offset);
+ isFirstSample = false;
+ }
+
+ (*it)->release();
+ (*it) = NULL;
+ chunk->mSamples.erase(it);
+ }
+ chunk->mSamples.clear();
+}
+
+void MPEG4Writer::writeAllChunks() {
+ ALOGV("writeAllChunks");
+ size_t outstandingChunks = 0;
+ Chunk chunk;
+ while (findChunkToWrite(&chunk)) {
+ writeChunkToFile(&chunk);
+ ++outstandingChunks;
+ }
+
+ sendSessionSummary();
+
+ mChunkInfos.clear();
+ ALOGD("%d chunks are written in the last batch", outstandingChunks);
+}
+
+bool MPEG4Writer::findChunkToWrite(Chunk *chunk) {
+ ALOGV("findChunkToWrite");
+
+ int64_t minTimestampUs = 0x7FFFFFFFFFFFFFFFLL;
+ Track *track = NULL;
+ for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
+ it != mChunkInfos.end(); ++it) {
+ if (!it->mChunks.empty()) {
+ List<Chunk>::iterator chunkIt = it->mChunks.begin();
+ if (chunkIt->mTimeStampUs < minTimestampUs) {
+ minTimestampUs = chunkIt->mTimeStampUs;
+ track = it->mTrack;
+ }
+ }
+ }
+
+ if (track == NULL) {
+ ALOGV("Nothing to be written after all");
+ return false;
+ }
+
+ if (mIsFirstChunk) {
+ mIsFirstChunk = false;
+ }
+
+ for (List<ChunkInfo>::iterator it = mChunkInfos.begin();
+ it != mChunkInfos.end(); ++it) {
+ if (it->mTrack == track) {
+ *chunk = *(it->mChunks.begin());
+ it->mChunks.erase(it->mChunks.begin());
+ CHECK_EQ(chunk->mTrack, track);
+
+ int64_t interChunkTimeUs =
+ chunk->mTimeStampUs - it->mPrevChunkTimestampUs;
+ if (interChunkTimeUs > it->mPrevChunkTimestampUs) {
+ it->mMaxInterChunkDurUs = interChunkTimeUs;
+ }
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void MPEG4Writer::threadFunc() {
+ ALOGV("threadFunc");
+
+ prctl(PR_SET_NAME, (unsigned long)"MPEG4Writer", 0, 0, 0);
+
+ Mutex::Autolock autoLock(mLock);
+ while (!mDone) {
+ Chunk chunk;
+ bool chunkFound = false;
+
+ while (!mDone && !(chunkFound = findChunkToWrite(&chunk))) {
+ mChunkReadyCondition.wait(mLock);
+ }
+
+ // Actual write without holding the lock in order to
+ // reduce the blocking time for media track threads.
+ if (chunkFound) {
+ mLock.unlock();
+ writeChunkToFile(&chunk);
+ mLock.lock();
+ }
+ }
+
+ writeAllChunks();
+}
+
+status_t MPEG4Writer::startWriterThread() {
+ ALOGV("startWriterThread");
+
+ mDone = false;
+ mIsFirstChunk = true;
+ mDriftTimeUs = 0;
+ for (List<Track *>::iterator it = mTracks.begin();
+ it != mTracks.end(); ++it) {
+ ChunkInfo info;
+ info.mTrack = *it;
+ info.mPrevChunkTimestampUs = 0;
+ info.mMaxInterChunkDurUs = 0;
+ mChunkInfos.push_back(info);
+ }
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ pthread_create(&mThread, &attr, ThreadWrapper, this);
+ pthread_attr_destroy(&attr);
+ mWriterThreadStarted = true;
+ return OK;
+}
+
+
+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;
+ }
+ mStartTimeRealUs = startTimeUs;
+
+ int32_t rotationDegrees;
+ if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
+ mRotation = rotationDegrees;
+ }
+
+ mIsRealTimeRecording = true;
+ {
+ int32_t isNotRealTime;
+ if (params && params->findInt32(kKeyNotRealTime, &isNotRealTime)) {
+ mIsRealTimeRecording = (isNotRealTime == 0);
+ }
+ }
+
+ initTrackingProgressStatus(params);
+
+ sp<MetaData> meta = new MetaData;
+ if (mIsRealTimeRecording && mOwner->numTracks() > 1) {
+ /*
+ * This extra delay of accepting incoming audio/video signals
+ * helps to align a/v start time at the beginning of a recording
+ * session, and it also helps eliminate the "recording" sound for
+ * camcorder applications.
+ *
+ * If client does not set the start time offset, we fall back to
+ * use the default initial delay value.
+ */
+ int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
+ if (startTimeOffsetUs < 0) { // Start time offset was not set
+ startTimeOffsetUs = kInitialDelayTimeUs;
+ }
+ startTimeUs += startTimeOffsetUs;
+ ALOGI("Start time offset: %lld us", startTimeOffsetUs);
+ }
+
+ meta->setInt64(kKeyTime, startTimeUs);
+
+ status_t err = mSource->start(meta.get());
+ if (err != OK) {
+ mDone = mReachedEOS = true;
+ return err;
+ }
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+ mDone = false;
+ mStarted = true;
+ mTrackDurationUs = 0;
+ mReachedEOS = false;
+ mEstimatedTrackSizeBytes = 0;
+ mNumStcoTableEntries = 0;
+ mNumStssTableEntries = 0;
+ mNumStscTableEntries = 0;
+ mNumSttsTableEntries = 0;
+ mNumCttsTableEntries = 0;
+ mMdatSizeBytes = 0;
+
+ mMaxChunkDurationUs = 0;
+
+ pthread_create(&mThread, &attr, ThreadWrapper, this);
+ pthread_attr_destroy(&attr);
+
+ return OK;
+}
+
+status_t MPEG4Writer::Track::pause() {
+ mPaused = true;
+ return OK;
+}
+
+status_t MPEG4Writer::Track::stop() {
+ ALOGD("Stopping %s track", mIsAudio? "Audio": "Video");
+ if (!mStarted) {
+ ALOGE("Stop() called but track is not started");
+ return ERROR_END_OF_STREAM;
+ }
+
+ if (mDone) {
+ return OK;
+ }
+ mDone = true;
+
+ void *dummy;
+ pthread_join(mThread, &dummy);
+
+ status_t err = (status_t) dummy;
+
+ ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video");
+ {
+ status_t status = mSource->stop();
+ if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
+ err = status;
+ }
+ }
+
+ ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
+ return err;
+}
+
+bool MPEG4Writer::Track::reachedEOS() {
+ return mReachedEOS;
+}
+
+// static
+void *MPEG4Writer::Track::ThreadWrapper(void *me) {
+ Track *track = static_cast<Track *>(me);
+
+ status_t err = track->threadEntry();
+ return (void *) err;
+}
+
+static void getNalUnitType(uint8_t byte, uint8_t* type) {
+ ALOGV("getNalUnitType: %d", byte);
+
+ // nal_unit_type: 5-bit unsigned integer
+ *type = (byte & 0x1F);
+}
+
+static const uint8_t *findNextStartCode(
+ const uint8_t *data, size_t length) {
+
+ ALOGV("findNextStartCode: %p %d", data, length);
+
+ size_t bytesLeft = length;
+ while (bytesLeft > 4 &&
+ memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
+ --bytesLeft;
+ }
+ if (bytesLeft <= 4) {
+ bytesLeft = 0; // Last parameter set
+ }
+ return &data[length - bytesLeft];
+}
+
+const uint8_t *MPEG4Writer::Track::parseParamSet(
+ const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
+
+ ALOGV("parseParamSet");
+ CHECK(type == kNalUnitTypeSeqParamSet ||
+ type == kNalUnitTypePicParamSet);
+
+ const uint8_t *nextStartCode = findNextStartCode(data, length);
+ *paramSetLen = nextStartCode - data;
+ if (*paramSetLen == 0) {
+ ALOGE("Param set is malformed, since its length is 0");
+ return NULL;
+ }
+
+ AVCParamSet paramSet(*paramSetLen, data);
+ if (type == kNalUnitTypeSeqParamSet) {
+ if (*paramSetLen < 4) {
+ ALOGE("Seq parameter set malformed");
+ return NULL;
+ }
+ if (mSeqParamSets.empty()) {
+ mProfileIdc = data[1];
+ mProfileCompatible = data[2];
+ mLevelIdc = data[3];
+ } else {
+ if (mProfileIdc != data[1] ||
+ mProfileCompatible != data[2] ||
+ mLevelIdc != data[3]) {
+ ALOGE("Inconsistent profile/level found in seq parameter sets");
+ return NULL;
+ }
+ }
+ mSeqParamSets.push_back(paramSet);
+ } else {
+ mPicParamSets.push_back(paramSet);
+ }
+ return nextStartCode;
+}
+
+status_t MPEG4Writer::Track::copyAVCCodecSpecificData(
+ const uint8_t *data, size_t size) {
+ ALOGV("copyAVCCodecSpecificData");
+
+ // 2 bytes for each of the parameter set length field
+ // plus the 7 bytes for the header
+ if (size < 4 + 7) {
+ ALOGE("Codec specific data length too short: %d", size);
+ return ERROR_MALFORMED;
+ }
+
+ mCodecSpecificDataSize = size;
+ mCodecSpecificData = malloc(size);
+ memcpy(mCodecSpecificData, data, size);
+ return OK;
+}
+
+status_t MPEG4Writer::Track::parseAVCCodecSpecificData(
+ const uint8_t *data, size_t size) {
+
+ ALOGV("parseAVCCodecSpecificData");
+ // Data starts with a start code.
+ // SPS and PPS are separated with start codes.
+ // Also, SPS must come before PPS
+ uint8_t type = kNalUnitTypeSeqParamSet;
+ bool gotSps = false;
+ bool gotPps = false;
+ const uint8_t *tmp = data;
+ const uint8_t *nextStartCode = data;
+ size_t bytesLeft = size;
+ size_t paramSetLen = 0;
+ mCodecSpecificDataSize = 0;
+ while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
+ getNalUnitType(*(tmp + 4), &type);
+ if (type == kNalUnitTypeSeqParamSet) {
+ if (gotPps) {
+ ALOGE("SPS must come before PPS");
+ return ERROR_MALFORMED;
+ }
+ if (!gotSps) {
+ gotSps = true;
+ }
+ nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
+ } else if (type == kNalUnitTypePicParamSet) {
+ if (!gotSps) {
+ ALOGE("SPS must come before PPS");
+ return ERROR_MALFORMED;
+ }
+ if (!gotPps) {
+ gotPps = true;
+ }
+ nextStartCode = parseParamSet(tmp + 4, bytesLeft - 4, type, &paramSetLen);
+ } else {
+ ALOGE("Only SPS and PPS Nal units are expected");
+ return ERROR_MALFORMED;
+ }
+
+ if (nextStartCode == NULL) {
+ return ERROR_MALFORMED;
+ }
+
+ // Move on to find the next parameter set
+ bytesLeft -= nextStartCode - tmp;
+ tmp = nextStartCode;
+ mCodecSpecificDataSize += (2 + paramSetLen);
+ }
+
+ {
+ // Check on the number of seq parameter sets
+ size_t nSeqParamSets = mSeqParamSets.size();
+ if (nSeqParamSets == 0) {
+ ALOGE("Cound not find sequence parameter set");
+ return ERROR_MALFORMED;
+ }
+
+ if (nSeqParamSets > 0x1F) {
+ ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
+ return ERROR_MALFORMED;
+ }
+ }
+
+ {
+ // Check on the number of pic parameter sets
+ size_t nPicParamSets = mPicParamSets.size();
+ if (nPicParamSets == 0) {
+ ALOGE("Cound not find picture parameter set");
+ return ERROR_MALFORMED;
+ }
+ if (nPicParamSets > 0xFF) {
+ ALOGE("Too many pic parameter sets (%d) found", nPicParamSets);
+ return ERROR_MALFORMED;
+ }
+ }
+// FIXME:
+// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above
+// and remove #if 0
+#if 0
+ {
+ // Check on the profiles
+ // These profiles requires additional parameter set extensions
+ if (mProfileIdc == 100 || mProfileIdc == 110 ||
+ mProfileIdc == 122 || mProfileIdc == 144) {
+ ALOGE("Sorry, no support for profile_idc: %d!", mProfileIdc);
+ return BAD_VALUE;
+ }
+ }
+#endif
+ return OK;
+}
+
+status_t MPEG4Writer::Track::makeAVCCodecSpecificData(
+ const uint8_t *data, size_t size) {
+
+ if (mCodecSpecificData != NULL) {
+ ALOGE("Already have codec specific data");
+ return ERROR_MALFORMED;
+ }
+
+ if (size < 4) {
+ ALOGE("Codec specific data length too short: %d", size);
+ return ERROR_MALFORMED;
+ }
+
+ // Data is in the form of AVCCodecSpecificData
+ if (memcmp("\x00\x00\x00\x01", data, 4)) {
+ return copyAVCCodecSpecificData(data, size);
+ }
+
+ if (parseAVCCodecSpecificData(data, size) != OK) {
+ return ERROR_MALFORMED;
+ }
+
+ // ISO 14496-15: AVC file format
+ mCodecSpecificDataSize += 7; // 7 more bytes in the header
+ mCodecSpecificData = malloc(mCodecSpecificDataSize);
+ uint8_t *header = (uint8_t *)mCodecSpecificData;
+ header[0] = 1; // version
+ header[1] = mProfileIdc; // profile indication
+ header[2] = mProfileCompatible; // profile compatibility
+ header[3] = mLevelIdc;
+
+ // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
+ if (mOwner->useNalLengthFour()) {
+ header[4] = 0xfc | 3; // length size == 4 bytes
+ } else {
+ header[4] = 0xfc | 1; // length size == 2 bytes
+ }
+
+ // 3-bit '111' followed by 5-bit numSequenceParameterSets
+ int nSequenceParamSets = mSeqParamSets.size();
+ header[5] = 0xe0 | nSequenceParamSets;
+ header += 6;
+ for (List<AVCParamSet>::iterator it = mSeqParamSets.begin();
+ it != mSeqParamSets.end(); ++it) {
+ // 16-bit sequence parameter set length
+ uint16_t seqParamSetLength = it->mLength;
+ header[0] = seqParamSetLength >> 8;
+ header[1] = seqParamSetLength & 0xff;
+
+ // SPS NAL unit (sequence parameter length bytes)
+ memcpy(&header[2], it->mData, seqParamSetLength);
+ header += (2 + seqParamSetLength);
+ }
+
+ // 8-bit nPictureParameterSets
+ int nPictureParamSets = mPicParamSets.size();
+ header[0] = nPictureParamSets;
+ header += 1;
+ for (List<AVCParamSet>::iterator it = mPicParamSets.begin();
+ it != mPicParamSets.end(); ++it) {
+ // 16-bit picture parameter set length
+ uint16_t picParamSetLength = it->mLength;
+ header[0] = picParamSetLength >> 8;
+ header[1] = picParamSetLength & 0xff;
+
+ // PPS Nal unit (picture parameter set length bytes)
+ memcpy(&header[2], it->mData, picParamSetLength);
+ header += (2 + picParamSetLength);
+ }
+
+ return OK;
+}
+
+/*
+ * Updates the drift time from the audio track so that
+ * the video track can get the updated drift time information
+ * from the file writer. The fluctuation of the drift time of the audio
+ * encoding path is smoothed out with a simple filter by giving a larger
+ * weight to more recently drift time. The filter coefficients, 0.5 and 0.5,
+ * are heuristically determined.
+ */
+void MPEG4Writer::Track::updateDriftTime(const sp<MetaData>& meta) {
+ int64_t driftTimeUs = 0;
+ if (meta->findInt64(kKeyDriftTime, &driftTimeUs)) {
+ int64_t prevDriftTimeUs = mOwner->getDriftTimeUs();
+ int64_t timeUs = (driftTimeUs + prevDriftTimeUs) >> 1;
+ mOwner->setDriftTimeUs(timeUs);
+ }
+}
+
+status_t MPEG4Writer::Track::threadEntry() {
+ int32_t count = 0;
+ const int64_t interleaveDurationUs = mOwner->interleaveDuration();
+ const bool hasMultipleTracks = (mOwner->numTracks() > 1);
+ int64_t chunkTimestampUs = 0;
+ int32_t nChunks = 0;
+ int32_t nZeroLengthFrames = 0;
+ int64_t lastTimestampUs = 0; // Previous sample time stamp
+ int64_t lastDurationUs = 0; // Between the previous two samples
+ int64_t currDurationTicks = 0; // Timescale based ticks
+ int64_t lastDurationTicks = 0; // Timescale based ticks
+ 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;
+ int64_t timestampUs = 0;
+ int64_t cttsOffsetTimeUs = 0;
+ int64_t currCttsOffsetTimeTicks = 0; // Timescale based ticks
+ int64_t lastCttsOffsetTimeTicks = -1; // Timescale based ticks
+ int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry
+
+ if (mIsAudio) {
+ prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
+ } else {
+ prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
+ }
+ androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
+
+ sp<MetaData> meta_data;
+
+ mNumSamples = 0;
+ status_t err = OK;
+ MediaBuffer *buffer;
+ 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;
+
+ int32_t isCodecConfig;
+ if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
+ && isCodecConfig) {
+ CHECK(!mGotAllCodecSpecificData);
+
+ if (mIsAvc) {
+ status_t err = makeAVCCodecSpecificData(
+ (const uint8_t *)buffer->data()
+ + buffer->range_offset(),
+ buffer->range_length());
+ CHECK_EQ((status_t)OK, err);
+ } else if (mIsMPEG4) {
+ 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;
+ }
+
+ // 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 (mIsAvc) StripStartcode(copy);
+
+ size_t sampleSize = copy->range_length();
+ if (mIsAvc) {
+ if (mOwner->useNalLengthFour()) {
+ sampleSize += 4;
+ } else {
+ sampleSize += 2;
+ }
+ }
+
+ // Max file size or duration handling
+ mMdatSizeBytes += sampleSize;
+ updateTrackSizeEstimate();
+
+ 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;
+ }
+
+
+ int32_t isSync = false;
+ meta_data->findInt32(kKeyIsSyncFrame, &isSync);
+ CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
+
+////////////////////////////////////////////////////////////////////////////////
+ if (mNumSamples == 0) {
+ mFirstSampleTimeRealUs = systemTime() / 1000;
+ mStartTimestampUs = timestampUs;
+ mOwner->setStartTimestampUs(mStartTimestampUs);
+ previousPausedDurationUs = mStartTimestampUs;
+ }
+
+ if (mResumed) {
+ int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
+ CHECK_GE(durExcludingEarlierPausesUs, 0ll);
+ int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
+ CHECK_GE(pausedDurationUs, lastDurationUs);
+ previousPausedDurationUs += pausedDurationUs - lastDurationUs;
+ mResumed = false;
+ }
+
+ timestampUs -= previousPausedDurationUs;
+ CHECK_GE(timestampUs, 0ll);
+ if (!mIsAudio) {
+ /*
+ * Composition time: timestampUs
+ * Decoding time: decodingTimeUs
+ * Composition time offset = composition time - decoding time
+ */
+ int64_t decodingTimeUs;
+ CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
+ decodingTimeUs -= previousPausedDurationUs;
+ cttsOffsetTimeUs =
+ timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
+ CHECK_GE(cttsOffsetTimeUs, 0ll);
+ timestampUs = decodingTimeUs;
+ ALOGV("decoding time: %lld and ctts offset time: %lld",
+ timestampUs, cttsOffsetTimeUs);
+
+ // Update ctts box table if necessary
+ currCttsOffsetTimeTicks =
+ (cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
+ CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL);
+ if (mNumSamples == 0) {
+ // Force the first ctts table entry to have one single entry
+ // so that we can do adjustment for the initial track start
+ // time offset easily in writeCttsBox().
+ lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
+ addOneCttsTableEntry(1, currCttsOffsetTimeTicks);
+ cttsSampleCount = 0; // No sample in ctts box is pending
+ } else {
+ if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
+ addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
+ lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
+ cttsSampleCount = 1; // One sample in ctts box is pending
+ } else {
+ ++cttsSampleCount;
+ }
+ }
+
+ // Update ctts time offset range
+ if (mNumSamples == 0) {
+ mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
+ mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
+ } else {
+ if (currCttsOffsetTimeTicks > mMaxCttsOffsetTimeUs) {
+ mMaxCttsOffsetTimeUs = currCttsOffsetTimeTicks;
+ } else if (currCttsOffsetTimeTicks < mMinCttsOffsetTimeUs) {
+ mMinCttsOffsetTimeUs = currCttsOffsetTimeTicks;
+ }
+ }
+
+ }
+
+ if (mIsRealTimeRecording) {
+ if (mIsAudio) {
+ updateDriftTime(meta_data);
+ }
+ }
+
+ CHECK_GE(timestampUs, 0ll);
+ ALOGV("%s media time stamp: %lld and previous paused duration %lld",
+ mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
+ if (timestampUs > mTrackDurationUs) {
+ mTrackDurationUs = timestampUs;
+ }
+
+ // We need to use the time scale based ticks, rather than the
+ // timestamp itself to determine whether we have to use a new
+ // stts entry, since we may have rounding errors.
+ // The calculation is intended to reduce the accumulated
+ // rounding errors.
+ currDurationTicks =
+ ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
+ (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
+ CHECK_GE(currDurationTicks, 0ll);
+
+ mSampleSizes.push_back(sampleSize);
+ ++mNumSamples;
+ if (mNumSamples > 2) {
+
+ // Force the first sample to have its own stts entry so that
+ // we can adjust its value later to maintain the A/V sync.
+ if (mNumSamples == 3 || currDurationTicks != lastDurationTicks) {
+ addOneSttsTableEntry(sampleCount, lastDurationTicks);
+ sampleCount = 1;
+ } else {
+ ++sampleCount;
+ }
+
+ }
+ if (mSamplesHaveSameSize) {
+ if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
+ mSamplesHaveSameSize = false;
+ }
+ previousSampleSize = sampleSize;
+ }
+ ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld",
+ mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs);
+ lastDurationUs = timestampUs - lastTimestampUs;
+ lastDurationTicks = currDurationTicks;
+ lastTimestampUs = timestampUs;
+
+ if (isSync != 0) {
+ addOneStssTableEntry(mNumSamples);
+ }
+
+ if (mTrackingProgressStatus) {
+ if (mPreviousTrackTimeUs <= 0) {
+ mPreviousTrackTimeUs = mStartTimestampUs;
+ }
+ trackProgressStatus(timestampUs);
+ }
+ if (!hasMultipleTracks) {
+ off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
+ : mOwner->addSample_l(copy);
+ if (mChunkOffsets.empty()) {
+ addChunkOffset(offset);
+ }
+ copy->release();
+ copy = NULL;
+ continue;
+ }
+
+ mChunkSamples.push_back(copy);
+ if (interleaveDurationUs == 0) {
+ addOneStscTableEntry(++nChunks, 1);
+ bufferChunk(timestampUs);
+ } else {
+ if (chunkTimestampUs == 0) {
+ chunkTimestampUs = timestampUs;
+ } else {
+ int64_t chunkDurationUs = timestampUs - chunkTimestampUs;
+ if (chunkDurationUs > interleaveDurationUs) {
+ if (chunkDurationUs > mMaxChunkDurationUs) {
+ mMaxChunkDurationUs = chunkDurationUs;
+ }
+ ++nChunks;
+ if (nChunks == 1 || // First chunk
+ (--(mStscTableEntries.end()))->samplesPerChunk !=
+ mChunkSamples.size()) {
+ addOneStscTableEntry(nChunks, mChunkSamples.size());
+ }
+ bufferChunk(timestampUs);
+ chunkTimestampUs = timestampUs;
+ }
+ }
+ }
+
+ }
+
+ if (isTrackMalFormed()) {
+ err = ERROR_MALFORMED;
+ }
+
+ mOwner->trackProgressStatus(mTrackId, -1, err);
+
+ // Last chunk
+ if (!hasMultipleTracks) {
+ addOneStscTableEntry(1, mNumSamples);
+ } else if (!mChunkSamples.empty()) {
+ addOneStscTableEntry(++nChunks, mChunkSamples.size());
+ bufferChunk(timestampUs);
+ }
+
+ // 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
+ lastDurationTicks = 0;
+ } else {
+ ++sampleCount; // Count for the last sample
+ }
+
+ if (mNumSamples <= 2) {
+ addOneSttsTableEntry(1, lastDurationTicks);
+ if (sampleCount - 1 > 0) {
+ addOneSttsTableEntry(sampleCount - 1, lastDurationTicks);
+ }
+ } else {
+ addOneSttsTableEntry(sampleCount, lastDurationTicks);
+ }
+
+ // The last ctts box may not have been written yet, and this
+ // is to make sure that we write out the last ctts box.
+ if (currCttsOffsetTimeTicks == lastCttsOffsetTimeTicks) {
+ if (cttsSampleCount > 0) {
+ addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
+ }
+ }
+
+ mTrackDurationUs += lastDurationUs;
+ mReachedEOS = true;
+
+ sendTrackSummary(hasMultipleTracks);
+
+ ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
+ count, nZeroLengthFrames, mNumSamples, mIsAudio? "audio": "video");
+ if (mIsAudio) {
+ ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs());
+ }
+
+ if (err == ERROR_END_OF_STREAM) {
+ return OK;
+ }
+ return err;
+}
+
+bool MPEG4Writer::Track::isTrackMalFormed() const {
+ if (mSampleSizes.empty()) { // no samples written
+ ALOGE("The number of recorded samples is 0");
+ return true;
+ }
+
+ if (!mIsAudio && mNumStssTableEntries == 0) { // no sync frames for video
+ ALOGE("There are no sync frames for video track");
+ return true;
+ }
+
+ if (OK != checkCodecSpecificData()) { // no codec specific data
+ return true;
+ }
+
+ return false;
+}
+
+void MPEG4Writer::Track::sendTrackSummary(bool hasMultipleTracks) {
+
+ // Send track summary only if test mode is enabled.
+ if (!isTestModeEnabled()) {
+ return;
+ }
+
+ int trackNum = (mTrackId << 28);
+
+ mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_TYPE,
+ mIsAudio? 0: 1);
+
+ mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_DURATION_MS,
+ mTrackDurationUs / 1000);
+
+ mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES,
+ mNumSamples);
+
+ {
+ // The system delay time excluding the requested initial delay that
+ // is used to eliminate the recording sound.
+ int64_t startTimeOffsetUs = mOwner->getStartTimeOffsetMs() * 1000LL;
+ if (startTimeOffsetUs < 0) { // Start time offset was not set
+ startTimeOffsetUs = kInitialDelayTimeUs;
+ }
+ int64_t initialDelayUs =
+ mFirstSampleTimeRealUs - mStartTimeRealUs - startTimeOffsetUs;
+
+ mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS,
+ (initialDelayUs) / 1000);
+ }
+
+ mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES,
+ mMdatSizeBytes / 1024);
+
+ if (hasMultipleTracks) {
+ mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS,
+ mMaxChunkDurationUs / 1000);
+
+ int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
+ if (mStartTimestampUs != moovStartTimeUs) {
+ int64_t startTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
+ mOwner->notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS,
+ startTimeOffsetUs / 1000);
+ }
+ }
+}
+
+void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
+ ALOGV("trackProgressStatus: %lld us", timeUs);
+ if (mTrackEveryTimeDurationUs > 0 &&
+ timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
+ ALOGV("Fire time tracking progress status at %lld us", timeUs);
+ mOwner->trackProgressStatus(mTrackId, timeUs - mPreviousTrackTimeUs, err);
+ mPreviousTrackTimeUs = timeUs;
+ }
+}
+
+void MPEG4Writer::trackProgressStatus(
+ size_t trackId, int64_t timeUs, status_t err) {
+ Mutex::Autolock lock(mLock);
+ int32_t trackNum = (trackId << 28);
+
+ // Error notification
+ // Do not consider ERROR_END_OF_STREAM an error
+ if (err != OK && err != ERROR_END_OF_STREAM) {
+ notify(MEDIA_RECORDER_TRACK_EVENT_ERROR,
+ trackNum | MEDIA_RECORDER_TRACK_ERROR_GENERAL,
+ err);
+ return;
+ }
+
+ if (timeUs == -1) {
+ // Send completion notification
+ notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS,
+ err);
+ } else {
+ // Send progress status
+ notify(MEDIA_RECORDER_TRACK_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME,
+ timeUs / 1000);
+ }
+}
+
+void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
+ ALOGV("setDriftTimeUs: %lld us", driftTimeUs);
+ Mutex::Autolock autolock(mLock);
+ mDriftTimeUs = driftTimeUs;
+}
+
+int64_t MPEG4Writer::getDriftTimeUs() {
+ ALOGV("getDriftTimeUs: %lld us", mDriftTimeUs);
+ Mutex::Autolock autolock(mLock);
+ return mDriftTimeUs;
+}
+
+bool MPEG4Writer::useNalLengthFour() {
+ return mUse4ByteNalLength;
+}
+
+void MPEG4Writer::Track::bufferChunk(int64_t timestampUs) {
+ ALOGV("bufferChunk");
+
+ Chunk chunk(this, timestampUs, mChunkSamples);
+ mOwner->bufferChunk(chunk);
+ mChunkSamples.clear();
+}
+
+int64_t MPEG4Writer::Track::getDurationUs() const {
+ return mTrackDurationUs;
+}
+
+int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
+ return mEstimatedTrackSizeBytes;
+}
+
+status_t MPEG4Writer::Track::checkCodecSpecificData() const {
+ const char *mime;
+ CHECK(mMeta->findCString(kKeyMIMEType, &mime));
+ if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
+ !strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
+ !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
+ if (!mCodecSpecificData ||
+ mCodecSpecificDataSize <= 0) {
+ ALOGE("Missing codec specific data");
+ return ERROR_MALFORMED;
+ }
+ } else {
+ if (mCodecSpecificData ||
+ mCodecSpecificDataSize > 0) {
+ ALOGE("Unexepected codec specific data found");
+ return ERROR_MALFORMED;
+ }
+ }
+ return OK;
+}
+
+void MPEG4Writer::Track::writeTrackHeader(bool use32BitOffset) {
+
+ ALOGV("%s track time scale: %d",
+ mIsAudio? "Audio": "Video", mTimeScale);
+
+ time_t now = time(NULL);
+ mOwner->beginBox("trak");
+ writeTkhdBox(now);
+ mOwner->beginBox("mdia");
+ writeMdhdBox(now);
+ writeHdlrBox();
+ mOwner->beginBox("minf");
+ if (mIsAudio) {
+ writeSmhdBox();
+ } else {
+ writeVmhdBox();
+ }
+ writeDinfBox();
+ writeStblBox(use32BitOffset);
+ mOwner->endBox(); // minf
+ mOwner->endBox(); // mdia
+ mOwner->endBox(); // trak
+}
+
+void MPEG4Writer::Track::writeStblBox(bool use32BitOffset) {
+ mOwner->beginBox("stbl");
+ mOwner->beginBox("stsd");
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt32(1); // entry count
+ if (mIsAudio) {
+ writeAudioFourCCBox();
+ } else {
+ writeVideoFourCCBox();
+ }
+ mOwner->endBox(); // stsd
+ writeSttsBox();
+ writeCttsBox();
+ if (!mIsAudio) {
+ writeStssBox();
+ }
+ writeStszBox();
+ writeStscBox();
+ writeStcoBox(use32BitOffset);
+ mOwner->endBox(); // stbl
+}
+
+void MPEG4Writer::Track::writeVideoFourCCBox() {
+ const char *mime;
+ bool success = mMeta->findCString(kKeyMIMEType, &mime);
+ CHECK(success);
+ if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
+ mOwner->beginBox("mp4v");
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
+ mOwner->beginBox("s263");
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
+ mOwner->beginBox("avc1");
+ } else {
+ ALOGE("Unknown mime type '%s'.", mime);
+ CHECK(!"should not be here, unknown mime type.");
+ }
+
+ mOwner->writeInt32(0); // reserved
+ mOwner->writeInt16(0); // reserved
+ mOwner->writeInt16(1); // data ref index
+ mOwner->writeInt16(0); // predefined
+ mOwner->writeInt16(0); // reserved
+ mOwner->writeInt32(0); // predefined
+ mOwner->writeInt32(0); // predefined
+ mOwner->writeInt32(0); // predefined
+
+ int32_t width, height;
+ success = mMeta->findInt32(kKeyWidth, &width);
+ success = success && mMeta->findInt32(kKeyHeight, &height);
+ CHECK(success);
+
+ mOwner->writeInt16(width);
+ mOwner->writeInt16(height);
+ mOwner->writeInt32(0x480000); // horiz resolution
+ mOwner->writeInt32(0x480000); // vert resolution
+ mOwner->writeInt32(0); // reserved
+ mOwner->writeInt16(1); // frame count
+ mOwner->write(" ", 32);
+ mOwner->writeInt16(0x18); // depth
+ mOwner->writeInt16(-1); // predefined
+
+ CHECK_LT(23 + mCodecSpecificDataSize, 128);
+
+ if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
+ writeMp4vEsdsBox();
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
+ writeD263Box();
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
+ writeAvccBox();
+ }
+
+ writePaspBox();
+ mOwner->endBox(); // mp4v, s263 or avc1
+}
+
+void MPEG4Writer::Track::writeAudioFourCCBox() {
+ const char *mime;
+ bool success = mMeta->findCString(kKeyMIMEType, &mime);
+ CHECK(success);
+ const char *fourcc = NULL;
+ if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
+ fourcc = "samr";
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
+ fourcc = "sawb";
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
+ fourcc = "mp4a";
+ } else {
+ ALOGE("Unknown mime type '%s'.", mime);
+ CHECK(!"should not be here, unknown mime type.");
+ }
+
+ mOwner->beginBox(fourcc); // audio format
+ mOwner->writeInt32(0); // reserved
+ mOwner->writeInt16(0); // reserved
+ mOwner->writeInt16(0x1); // data ref index
+ mOwner->writeInt32(0); // reserved
+ mOwner->writeInt32(0); // reserved
+ 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
+
+ int32_t samplerate;
+ success = mMeta->findInt32(kKeySampleRate, &samplerate);
+ CHECK(success);
+ mOwner->writeInt32(samplerate << 16);
+ if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
+ writeMp4aEsdsBox();
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
+ !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
+ writeDamrBox();
+ }
+ mOwner->endBox();
+}
+
+void MPEG4Writer::Track::writeMp4aEsdsBox() {
+ mOwner->beginBox("esds");
+ CHECK(mCodecSpecificData);
+ CHECK_GT(mCodecSpecificDataSize, 0);
+
+ // Make sure all sizes encode to a single byte.
+ CHECK_LT(mCodecSpecificDataSize + 23, 128);
+
+ 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
+}
+
+void MPEG4Writer::Track::writeMp4vEsdsBox() {
+ CHECK(mCodecSpecificData);
+ CHECK_GT(mCodecSpecificDataSize, 0);
+ 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(0x1f);
+
+ mOwner->writeInt8(0x04); // DecoderConfigDescrTag
+ mOwner->writeInt8(15 + mCodecSpecificDataSize);
+ mOwner->writeInt8(0x20); // objectTypeIndication ISO/IEC 14492-2
+ mOwner->writeInt8(0x11); // streamType VisualStream
+
+ static const uint8_t kData[] = {
+ 0x01, 0x77, 0x00,
+ 0x00, 0x03, 0xe8, 0x00,
+ 0x00, 0x03, 0xe8, 0x00
+ };
+ mOwner->write(kData, sizeof(kData));
+
+ 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
+}
+
+void MPEG4Writer::Track::writeTkhdBox(time_t now) {
+ mOwner->beginBox("tkhd");
+ // 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(mTrackId + 1); // track id starts with 1
+ mOwner->writeInt32(0); // reserved
+ int64_t trakDurationUs = getDurationUs();
+ int32_t mvhdTimeScale = mOwner->getTimeScale();
+ 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
+ mOwner->writeInt16(0); // alternate group
+ mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume
+ mOwner->writeInt16(0); // reserved
+
+ mOwner->writeCompositionMatrix(mRotation); // matrix
+
+ if (mIsAudio) {
+ mOwner->writeInt32(0);
+ mOwner->writeInt32(0);
+ } else {
+ int32_t width, height;
+ bool success = mMeta->findInt32(kKeyWidth, &width);
+ success = success && mMeta->findInt32(kKeyHeight, &height);
+ CHECK(success);
+
+ mOwner->writeInt32(width << 16); // 32-bit fixed-point value
+ mOwner->writeInt32(height << 16); // 32-bit fixed-point value
+ }
+ mOwner->endBox(); // tkhd
+}
+
+void MPEG4Writer::Track::writeVmhdBox() {
+ mOwner->beginBox("vmhd");
+ mOwner->writeInt32(0x01); // version=0, flags=1
+ mOwner->writeInt16(0); // graphics mode
+ mOwner->writeInt16(0); // opcolor
+ mOwner->writeInt16(0);
+ mOwner->writeInt16(0);
+ mOwner->endBox();
+}
+
+void MPEG4Writer::Track::writeSmhdBox() {
+ mOwner->beginBox("smhd");
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt16(0); // balance
+ mOwner->writeInt16(0); // reserved
+ mOwner->endBox();
+}
+
+void MPEG4Writer::Track::writeHdlrBox() {
+ mOwner->beginBox("hdlr");
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt32(0); // component type: should be mhlr
+ mOwner->writeFourcc(mIsAudio ? "soun" : "vide"); // component subtype
+ mOwner->writeInt32(0); // reserved
+ mOwner->writeInt32(0); // reserved
+ mOwner->writeInt32(0); // reserved
+ // Removing "r" for the name string just makes the string 4 byte aligned
+ mOwner->writeCString(mIsAudio ? "SoundHandle": "VideoHandle"); // name
+ mOwner->endBox();
+}
+
+void MPEG4Writer::Track::writeMdhdBox(time_t now) {
+ int64_t trakDurationUs = getDurationUs();
+ mOwner->beginBox("mdhd");
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt32(now); // creation time
+ mOwner->writeInt32(now); // modification time
+ 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();
+}
+
+void MPEG4Writer::Track::writeDamrBox() {
+ // 3gpp2 Spec AMRSampleEntry fields
+ mOwner->beginBox("damr");
+ mOwner->writeCString(" "); // vendor: 4 bytes
+ mOwner->writeInt8(0); // decoder version
+ mOwner->writeInt16(0x83FF); // mode set: all enabled
+ mOwner->writeInt8(0); // mode change period
+ mOwner->writeInt8(1); // frames per sample
+ mOwner->endBox();
+}
+
+void MPEG4Writer::Track::writeUrlBox() {
+ // 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
+}
+
+void MPEG4Writer::Track::writeDrefBox() {
+ mOwner->beginBox("dref");
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt32(1); // entry count (either url or urn)
+ writeUrlBox();
+ mOwner->endBox(); // dref
+}
+
+void MPEG4Writer::Track::writeDinfBox() {
+ mOwner->beginBox("dinf");
+ writeDrefBox();
+ mOwner->endBox(); // dinf
+}
+
+void MPEG4Writer::Track::writeAvccBox() {
+ CHECK(mCodecSpecificData);
+ CHECK_GE(mCodecSpecificDataSize, 5);
+
+ // Patch avcc's lengthSize field to match the number
+ // of bytes we use to indicate the size of a nal unit.
+ uint8_t *ptr = (uint8_t *)mCodecSpecificData;
+ ptr[4] = (ptr[4] & 0xfc) | (mOwner->useNalLengthFour() ? 3 : 1);
+ mOwner->beginBox("avcC");
+ mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
+ mOwner->endBox(); // avcC
+}
+
+void MPEG4Writer::Track::writeD263Box() {
+ mOwner->beginBox("d263");
+ mOwner->writeInt32(0); // vendor
+ mOwner->writeInt8(0); // decoder version
+ mOwner->writeInt8(10); // level: 10
+ mOwner->writeInt8(0); // profile: 0
+ mOwner->endBox(); // d263
+}
+
+// This is useful if the pixel is not square
+void MPEG4Writer::Track::writePaspBox() {
+ mOwner->beginBox("pasp");
+ mOwner->writeInt32(1 << 16); // hspacing
+ mOwner->writeInt32(1 << 16); // vspacing
+ mOwner->endBox(); // pasp
+}
+
+int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
+ int64_t trackStartTimeOffsetUs = 0;
+ int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
+ if (mStartTimestampUs != moovStartTimeUs) {
+ CHECK_GT(mStartTimestampUs, moovStartTimeUs);
+ trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
+ }
+ return (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL;
+}
+
+void MPEG4Writer::Track::writeSttsBox() {
+ mOwner->beginBox("stts");
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt32(mNumSttsTableEntries);
+
+ // Compensate for small start time difference from different media tracks
+ List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
+ CHECK(it != mSttsTableEntries.end() && it->sampleCount == 1);
+ mOwner->writeInt32(it->sampleCount);
+ mOwner->writeInt32(getStartTimeOffsetScaledTime() + it->sampleDuration);
+
+ int64_t totalCount = 1;
+ while (++it != mSttsTableEntries.end()) {
+ mOwner->writeInt32(it->sampleCount);
+ mOwner->writeInt32(it->sampleDuration);
+ totalCount += it->sampleCount;
+ }
+ CHECK_EQ(totalCount, mNumSamples);
+ mOwner->endBox(); // stts
+}
+
+void MPEG4Writer::Track::writeCttsBox() {
+ if (mIsAudio) { // ctts is not for audio
+ return;
+ }
+
+ // There is no B frame at all
+ if (mMinCttsOffsetTimeUs == mMaxCttsOffsetTimeUs) {
+ return;
+ }
+
+ // Do not write ctts box when there is no need to have it.
+ if ((mNumCttsTableEntries == 1 &&
+ mCttsTableEntries.begin()->sampleDuration == 0) ||
+ mNumCttsTableEntries == 0) {
+ return;
+ }
+
+ ALOGD("ctts box has %d entries with range [%lld, %lld]",
+ mNumCttsTableEntries, mMinCttsOffsetTimeUs, mMaxCttsOffsetTimeUs);
+
+ mOwner->beginBox("ctts");
+ // Version 1 allows to use negative offset time value, but
+ // we are sticking to version 0 for now.
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt32(mNumCttsTableEntries);
+
+ // Compensate for small start time difference from different media tracks
+ List<CttsTableEntry>::iterator it = mCttsTableEntries.begin();
+ CHECK(it != mCttsTableEntries.end() && it->sampleCount == 1);
+ mOwner->writeInt32(it->sampleCount);
+ mOwner->writeInt32(getStartTimeOffsetScaledTime() +
+ it->sampleDuration - mMinCttsOffsetTimeUs);
+
+ int64_t totalCount = 1;
+ while (++it != mCttsTableEntries.end()) {
+ mOwner->writeInt32(it->sampleCount);
+ mOwner->writeInt32(it->sampleDuration - mMinCttsOffsetTimeUs);
+ totalCount += it->sampleCount;
+ }
+ CHECK_EQ(totalCount, mNumSamples);
+ mOwner->endBox(); // ctts
+}
+
+void MPEG4Writer::Track::writeStssBox() {
+ mOwner->beginBox("stss");
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt32(mNumStssTableEntries); // number of sync frames
+ for (List<int32_t>::iterator it = mStssTableEntries.begin();
+ it != mStssTableEntries.end(); ++it) {
+ mOwner->writeInt32(*it);
+ }
+ mOwner->endBox(); // stss
+}
+
+void MPEG4Writer::Track::writeStszBox() {
+ mOwner->beginBox("stsz");
+ mOwner->writeInt32(0); // version=0, flags=0
+ 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
+}
+
+void MPEG4Writer::Track::writeStscBox() {
+ mOwner->beginBox("stsc");
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt32(mNumStscTableEntries);
+ 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
+}
+
+void MPEG4Writer::Track::writeStcoBox(bool use32BitOffset) {
+ mOwner->beginBox(use32BitOffset? "stco": "co64");
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt32(mNumStcoTableEntries);
+ for (List<off64_t>::iterator it = mChunkOffsets.begin();
+ it != mChunkOffsets.end(); ++it) {
+ if (use32BitOffset) {
+ mOwner->writeInt32(static_cast<int32_t>(*it));
+ } else {
+ mOwner->writeInt64((*it));
+ }
+ }
+ mOwner->endBox(); // stco or co64
+}
+
+void MPEG4Writer::writeUdtaBox() {
+ beginBox("udta");
+ writeGeoDataBox();
+ endBox();
+}
+
+/*
+ * Geodata is stored according to ISO-6709 standard.
+ */
+void MPEG4Writer::writeGeoDataBox() {
+ beginBox("\xA9xyz");
+ /*
+ * For historical reasons, any user data start
+ * with "\0xA9", must be followed by its assoicated
+ * language code.
+ * 0x0012: text string length
+ * 0x15c7: lang (locale) code: en
+ */
+ writeInt32(0x001215c7);
+ writeLatitude(mLatitudex10000);
+ writeLongitude(mLongitudex10000);
+ writeInt8(0x2F);
+ endBox();
+}
+
+} // namespace android
diff --git a/media/libstagefright/MediaBuffer.cpp b/media/libstagefright/MediaBuffer.cpp
new file mode 100644
index 0000000..11b80bf
--- /dev/null
+++ b/media/libstagefright/MediaBuffer.cpp
@@ -0,0 +1,203 @@
+/*
+ * 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 "MediaBuffer"
+#include <utils/Log.h>
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MetaData.h>
+
+#include <ui/GraphicBuffer.h>
+#include <sys/atomics.h>
+
+namespace android {
+
+MediaBuffer::MediaBuffer(void *data, size_t size)
+ : mObserver(NULL),
+ mNextBuffer(NULL),
+ mRefCount(0),
+ mData(data),
+ mSize(size),
+ mRangeOffset(0),
+ mRangeLength(size),
+ mOwnsData(false),
+ mMetaData(new MetaData),
+ mOriginal(NULL) {
+}
+
+MediaBuffer::MediaBuffer(size_t size)
+ : mObserver(NULL),
+ mNextBuffer(NULL),
+ mRefCount(0),
+ mData(malloc(size)),
+ mSize(size),
+ mRangeOffset(0),
+ mRangeLength(size),
+ mOwnsData(true),
+ mMetaData(new MetaData),
+ mOriginal(NULL) {
+}
+
+MediaBuffer::MediaBuffer(const sp<GraphicBuffer>& graphicBuffer)
+ : mObserver(NULL),
+ mNextBuffer(NULL),
+ mRefCount(0),
+ mData(NULL),
+ mSize(1),
+ mRangeOffset(0),
+ mRangeLength(mSize),
+ mGraphicBuffer(graphicBuffer),
+ mOwnsData(false),
+ mMetaData(new MetaData),
+ mOriginal(NULL) {
+}
+
+MediaBuffer::MediaBuffer(const sp<ABuffer> &buffer)
+ : mObserver(NULL),
+ mNextBuffer(NULL),
+ mRefCount(0),
+ mData(buffer->data()),
+ mSize(buffer->size()),
+ mRangeOffset(0),
+ mRangeLength(mSize),
+ mBuffer(buffer),
+ mOwnsData(false),
+ mMetaData(new MetaData),
+ mOriginal(NULL) {
+}
+
+void MediaBuffer::release() {
+ if (mObserver == NULL) {
+ CHECK_EQ(mRefCount, 0);
+ delete this;
+ return;
+ }
+
+ int prevCount = __atomic_dec(&mRefCount);
+ if (prevCount == 1) {
+ if (mObserver == NULL) {
+ delete this;
+ return;
+ }
+
+ mObserver->signalBufferReturned(this);
+ }
+ CHECK(prevCount > 0);
+}
+
+void MediaBuffer::claim() {
+ CHECK(mObserver != NULL);
+ CHECK_EQ(mRefCount, 1);
+
+ mRefCount = 0;
+}
+
+void MediaBuffer::add_ref() {
+ (void) __atomic_inc(&mRefCount);
+}
+
+void *MediaBuffer::data() const {
+ CHECK(mGraphicBuffer == NULL);
+ return mData;
+}
+
+size_t MediaBuffer::size() const {
+ CHECK(mGraphicBuffer == NULL);
+ return mSize;
+}
+
+size_t MediaBuffer::range_offset() const {
+ return mRangeOffset;
+}
+
+size_t MediaBuffer::range_length() const {
+ return mRangeLength;
+}
+
+void MediaBuffer::set_range(size_t offset, size_t length) {
+ if ((mGraphicBuffer == NULL) && (offset + length > mSize)) {
+ ALOGE("offset = %d, length = %d, mSize = %d", offset, length, mSize);
+ }
+ CHECK((mGraphicBuffer != NULL) || (offset + length <= mSize));
+
+ mRangeOffset = offset;
+ mRangeLength = length;
+}
+
+sp<GraphicBuffer> MediaBuffer::graphicBuffer() const {
+ return mGraphicBuffer;
+}
+
+sp<MetaData> MediaBuffer::meta_data() {
+ return mMetaData;
+}
+
+void MediaBuffer::reset() {
+ mMetaData->clear();
+ set_range(0, mSize);
+}
+
+MediaBuffer::~MediaBuffer() {
+ CHECK(mObserver == NULL);
+
+ if (mOwnsData && mData != NULL) {
+ free(mData);
+ mData = NULL;
+ }
+
+ if (mOriginal != NULL) {
+ mOriginal->release();
+ mOriginal = NULL;
+ }
+}
+
+void MediaBuffer::setObserver(MediaBufferObserver *observer) {
+ CHECK(observer == NULL || mObserver == NULL);
+ mObserver = observer;
+}
+
+void MediaBuffer::setNextBuffer(MediaBuffer *buffer) {
+ mNextBuffer = buffer;
+}
+
+MediaBuffer *MediaBuffer::nextBuffer() {
+ return mNextBuffer;
+}
+
+int MediaBuffer::refcount() const {
+ return mRefCount;
+}
+
+MediaBuffer *MediaBuffer::clone() {
+ CHECK(mGraphicBuffer == NULL);
+
+ MediaBuffer *buffer = new MediaBuffer(mData, mSize);
+ buffer->set_range(mRangeOffset, mRangeLength);
+ buffer->mMetaData = new MetaData(*mMetaData.get());
+
+ add_ref();
+ buffer->mOriginal = this;
+
+ return buffer;
+}
+
+} // namespace android
diff --git a/media/libstagefright/MediaBufferGroup.cpp b/media/libstagefright/MediaBufferGroup.cpp
new file mode 100644
index 0000000..80aae51
--- /dev/null
+++ b/media/libstagefright/MediaBufferGroup.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 "MediaBufferGroup"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+
+namespace android {
+
+MediaBufferGroup::MediaBufferGroup()
+ : mFirstBuffer(NULL),
+ mLastBuffer(NULL) {
+}
+
+MediaBufferGroup::~MediaBufferGroup() {
+ MediaBuffer *next;
+ for (MediaBuffer *buffer = mFirstBuffer; buffer != NULL;
+ buffer = next) {
+ next = buffer->nextBuffer();
+
+ CHECK_EQ(buffer->refcount(), 0);
+
+ buffer->setObserver(NULL);
+ buffer->release();
+ }
+}
+
+void MediaBufferGroup::add_buffer(MediaBuffer *buffer) {
+ Mutex::Autolock autoLock(mLock);
+
+ buffer->setObserver(this);
+
+ if (mLastBuffer) {
+ mLastBuffer->setNextBuffer(buffer);
+ } else {
+ mFirstBuffer = buffer;
+ }
+
+ mLastBuffer = buffer;
+}
+
+status_t MediaBufferGroup::acquire_buffer(MediaBuffer **out) {
+ Mutex::Autolock autoLock(mLock);
+
+ for (;;) {
+ for (MediaBuffer *buffer = mFirstBuffer;
+ buffer != NULL; buffer = buffer->nextBuffer()) {
+ if (buffer->refcount() == 0) {
+ buffer->add_ref();
+ buffer->reset();
+
+ *out = buffer;
+ goto exit;
+ }
+ }
+
+ // All buffers are in use. Block until one of them is returned to us.
+ mCondition.wait(mLock);
+ }
+
+exit:
+ return OK;
+}
+
+void MediaBufferGroup::signalBufferReturned(MediaBuffer *) {
+ Mutex::Autolock autoLock(mLock);
+ mCondition.signal();
+}
+
+} // namespace android
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
new file mode 100644
index 0000000..42b5c7e
--- /dev/null
+++ b/media/libstagefright/MediaCodec.cpp
@@ -0,0 +1,1325 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "MediaCodec"
+#include <utils/Log.h>
+
+#include <media/stagefright/MediaCodec.h>
+
+#include "include/SoftwareRenderer.h"
+
+#include <binder/IServiceManager.h>
+#include <gui/SurfaceTextureClient.h>
+#include <media/ICrypto.h>
+#include <media/IMediaPlayerService.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/ACodec.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/NativeWindowWrapper.h>
+
+namespace android {
+
+// static
+sp<MediaCodec> MediaCodec::CreateByType(
+ const sp<ALooper> &looper, const char *mime, bool encoder) {
+ sp<MediaCodec> codec = new MediaCodec(looper);
+ if (codec->init(mime, true /* nameIsType */, encoder) != OK) {
+ return NULL;
+ }
+
+ return codec;
+}
+
+// static
+sp<MediaCodec> MediaCodec::CreateByComponentName(
+ const sp<ALooper> &looper, const char *name) {
+ sp<MediaCodec> codec = new MediaCodec(looper);
+ if (codec->init(name, false /* nameIsType */, false /* encoder */) != OK) {
+ return NULL;
+ }
+
+ return codec;
+}
+
+MediaCodec::MediaCodec(const sp<ALooper> &looper)
+ : mState(UNINITIALIZED),
+ mLooper(looper),
+ mCodec(new ACodec),
+ mFlags(0),
+ mSoftRenderer(NULL),
+ mDequeueInputTimeoutGeneration(0),
+ mDequeueInputReplyID(0),
+ mDequeueOutputTimeoutGeneration(0),
+ mDequeueOutputReplyID(0) {
+}
+
+MediaCodec::~MediaCodec() {
+ CHECK_EQ(mState, UNINITIALIZED);
+}
+
+// static
+status_t MediaCodec::PostAndAwaitResponse(
+ const sp<AMessage> &msg, sp<AMessage> *response) {
+ status_t err = msg->postAndAwaitResponse(response);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (!(*response)->findInt32("err", &err)) {
+ err = OK;
+ }
+
+ return err;
+}
+
+status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) {
+ // Current video decoders do not return from OMX_FillThisBuffer
+ // quickly, violating the OpenMAX specs, until that is remedied
+ // we need to invest in an extra looper to free the main event
+ // queue.
+ bool needDedicatedLooper = false;
+ if (nameIsType && !strncasecmp(name, "video/", 6)) {
+ needDedicatedLooper = true;
+ } else if (!nameIsType && !strncmp(name, "OMX.TI.DUCATI1.VIDEO.", 21)) {
+ needDedicatedLooper = true;
+ }
+
+ if (needDedicatedLooper) {
+ if (mCodecLooper == NULL) {
+ mCodecLooper = new ALooper;
+ mCodecLooper->setName("CodecLooper");
+ mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
+ }
+
+ mCodecLooper->registerHandler(mCodec);
+ } else {
+ mLooper->registerHandler(mCodec);
+ }
+
+ mLooper->registerHandler(this);
+
+ mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id()));
+
+ sp<AMessage> msg = new AMessage(kWhatInit, id());
+ msg->setString("name", name);
+ msg->setInt32("nameIsType", nameIsType);
+
+ if (nameIsType) {
+ msg->setInt32("encoder", encoder);
+ }
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t MediaCodec::configure(
+ const sp<AMessage> &format,
+ const sp<SurfaceTextureClient> &nativeWindow,
+ uint32_t flags) {
+ sp<AMessage> msg = new AMessage(kWhatConfigure, id());
+
+ msg->setMessage("format", format);
+ msg->setInt32("flags", flags);
+
+ if (nativeWindow != NULL) {
+ if (!(mFlags & kFlagIsSoftwareCodec)) {
+ msg->setObject(
+ "native-window",
+ new NativeWindowWrapper(nativeWindow));
+ } else {
+ mNativeWindow = nativeWindow;
+ }
+ }
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t MediaCodec::start() {
+ sp<AMessage> msg = new AMessage(kWhatStart, id());
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t MediaCodec::stop() {
+ sp<AMessage> msg = new AMessage(kWhatStop, id());
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t MediaCodec::release() {
+ sp<AMessage> msg = new AMessage(kWhatRelease, id());
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t MediaCodec::queueInputBuffer(
+ size_t index,
+ size_t offset,
+ size_t size,
+ int64_t presentationTimeUs,
+ uint32_t flags) {
+ sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
+ msg->setSize("index", index);
+ msg->setSize("offset", offset);
+ msg->setSize("size", size);
+ msg->setInt64("timeUs", presentationTimeUs);
+ msg->setInt32("flags", flags);
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
+ sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id());
+ msg->setInt64("timeoutUs", timeoutUs);
+
+ sp<AMessage> response;
+ status_t err;
+ if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
+ return err;
+ }
+
+ CHECK(response->findSize("index", index));
+
+ return OK;
+}
+
+status_t MediaCodec::dequeueOutputBuffer(
+ size_t *index,
+ size_t *offset,
+ size_t *size,
+ int64_t *presentationTimeUs,
+ uint32_t *flags,
+ int64_t timeoutUs) {
+ sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id());
+ msg->setInt64("timeoutUs", timeoutUs);
+
+ sp<AMessage> response;
+ status_t err;
+ if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
+ return err;
+ }
+
+ CHECK(response->findSize("index", index));
+ CHECK(response->findSize("offset", offset));
+ CHECK(response->findSize("size", size));
+ CHECK(response->findInt64("timeUs", presentationTimeUs));
+ CHECK(response->findInt32("flags", (int32_t *)flags));
+
+ return OK;
+}
+
+status_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
+ sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
+ msg->setSize("index", index);
+ msg->setInt32("render", true);
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t MediaCodec::releaseOutputBuffer(size_t index) {
+ sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
+ msg->setSize("index", index);
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
+ sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id());
+
+ sp<AMessage> response;
+ status_t err;
+ if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
+ return err;
+ }
+
+ CHECK(response->findMessage("format", format));
+
+ return OK;
+}
+
+status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
+ sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
+ msg->setInt32("portIndex", kPortIndexInput);
+ msg->setPointer("buffers", buffers);
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
+ sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
+ msg->setInt32("portIndex", kPortIndexOutput);
+ msg->setPointer("buffers", buffers);
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+status_t MediaCodec::flush() {
+ sp<AMessage> msg = new AMessage(kWhatFlush, id());
+
+ sp<AMessage> response;
+ return PostAndAwaitResponse(msg, &response);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void MediaCodec::cancelPendingDequeueOperations() {
+ if (mFlags & kFlagDequeueInputPending) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+ response->postReply(mDequeueInputReplyID);
+
+ ++mDequeueInputTimeoutGeneration;
+ mDequeueInputReplyID = 0;
+ mFlags &= ~kFlagDequeueInputPending;
+ }
+
+ if (mFlags & kFlagDequeueOutputPending) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+ response->postReply(mDequeueOutputReplyID);
+
+ ++mDequeueOutputTimeoutGeneration;
+ mDequeueOutputReplyID = 0;
+ mFlags &= ~kFlagDequeueOutputPending;
+ }
+}
+
+bool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) {
+ if (mState != STARTED
+ || (mFlags & kFlagStickyError)
+ || (newRequest && (mFlags & kFlagDequeueInputPending))) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+
+ response->postReply(replyID);
+
+ return true;
+ }
+
+ ssize_t index = dequeuePortBuffer(kPortIndexInput);
+
+ if (index < 0) {
+ CHECK_EQ(index, -EAGAIN);
+ return false;
+ }
+
+ sp<AMessage> response = new AMessage;
+ response->setSize("index", index);
+ response->postReply(replyID);
+
+ return true;
+}
+
+bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) {
+ sp<AMessage> response = new AMessage;
+
+ if (mState != STARTED
+ || (mFlags & kFlagStickyError)
+ || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
+ response->setInt32("err", INVALID_OPERATION);
+ } else if (mFlags & kFlagOutputBuffersChanged) {
+ response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED);
+ mFlags &= ~kFlagOutputBuffersChanged;
+ } else if (mFlags & kFlagOutputFormatChanged) {
+ response->setInt32("err", INFO_FORMAT_CHANGED);
+ mFlags &= ~kFlagOutputFormatChanged;
+ } else {
+ ssize_t index = dequeuePortBuffer(kPortIndexOutput);
+
+ if (index < 0) {
+ CHECK_EQ(index, -EAGAIN);
+ return false;
+ }
+
+ const sp<ABuffer> &buffer =
+ mPortBuffers[kPortIndexOutput].itemAt(index).mData;
+
+ response->setSize("index", index);
+ response->setSize("offset", buffer->offset());
+ response->setSize("size", buffer->size());
+
+ int64_t timeUs;
+ CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
+
+ response->setInt64("timeUs", timeUs);
+
+ int32_t omxFlags;
+ CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
+
+ uint32_t flags = 0;
+ if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
+ flags |= BUFFER_FLAG_SYNCFRAME;
+ }
+ if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+ flags |= BUFFER_FLAG_CODECCONFIG;
+ }
+ if (omxFlags & OMX_BUFFERFLAG_EOS) {
+ flags |= BUFFER_FLAG_EOS;
+ }
+
+ response->setInt32("flags", flags);
+ }
+
+ response->postReply(replyID);
+
+ return true;
+}
+
+void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatCodecNotify:
+ {
+ int32_t what;
+ CHECK(msg->findInt32("what", &what));
+
+ switch (what) {
+ case ACodec::kWhatError:
+ {
+ int32_t omxError, internalError;
+ CHECK(msg->findInt32("omx-error", &omxError));
+ CHECK(msg->findInt32("err", &internalError));
+
+ ALOGE("Codec reported an error. "
+ "(omx error 0x%08x, internalError %d)",
+ omxError, internalError);
+
+ bool sendErrorReponse = true;
+
+ switch (mState) {
+ case INITIALIZING:
+ {
+ setState(UNINITIALIZED);
+ break;
+ }
+
+ case CONFIGURING:
+ {
+ setState(INITIALIZED);
+ break;
+ }
+
+ case STARTING:
+ {
+ setState(CONFIGURED);
+ break;
+ }
+
+ case STOPPING:
+ case RELEASING:
+ {
+ // Ignore the error, assuming we'll still get
+ // the shutdown complete notification.
+
+ sendErrorReponse = false;
+ break;
+ }
+
+ case FLUSHING:
+ {
+ setState(STARTED);
+ break;
+ }
+
+ case STARTED:
+ {
+ sendErrorReponse = false;
+
+ mFlags |= kFlagStickyError;
+
+ cancelPendingDequeueOperations();
+ break;
+ }
+
+ default:
+ {
+ sendErrorReponse = false;
+
+ mFlags |= kFlagStickyError;
+ break;
+ }
+ }
+
+ if (sendErrorReponse) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", UNKNOWN_ERROR);
+
+ response->postReply(mReplyID);
+ }
+ break;
+ }
+
+ case ACodec::kWhatComponentAllocated:
+ {
+ CHECK_EQ(mState, INITIALIZING);
+ setState(INITIALIZED);
+
+ AString componentName;
+ CHECK(msg->findString("componentName", &componentName));
+
+ if (componentName.startsWith("OMX.google.")) {
+ mFlags |= kFlagIsSoftwareCodec;
+ } else {
+ mFlags &= ~kFlagIsSoftwareCodec;
+ }
+
+ (new AMessage)->postReply(mReplyID);
+ break;
+ }
+
+ case ACodec::kWhatComponentConfigured:
+ {
+ CHECK_EQ(mState, CONFIGURING);
+ setState(CONFIGURED);
+
+ (new AMessage)->postReply(mReplyID);
+ break;
+ }
+
+ case ACodec::kWhatBuffersAllocated:
+ {
+ int32_t portIndex;
+ CHECK(msg->findInt32("portIndex", &portIndex));
+
+ ALOGV("%s buffers allocated",
+ portIndex == kPortIndexInput ? "input" : "output");
+
+ CHECK(portIndex == kPortIndexInput
+ || portIndex == kPortIndexOutput);
+
+ mPortBuffers[portIndex].clear();
+
+ Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
+ for (size_t i = 0;; ++i) {
+ AString name = StringPrintf("buffer-id_%d", i);
+
+ void *bufferID;
+ if (!msg->findPointer(name.c_str(), &bufferID)) {
+ break;
+ }
+
+ name = StringPrintf("data_%d", i);
+
+ BufferInfo info;
+ info.mBufferID = bufferID;
+ info.mOwnedByClient = false;
+ CHECK(msg->findBuffer(name.c_str(), &info.mData));
+
+ if (portIndex == kPortIndexInput
+ && (mFlags & kFlagIsSecure)) {
+ info.mEncryptedData =
+ new ABuffer(info.mData->capacity());
+ }
+
+ buffers->push_back(info);
+ }
+
+ if (portIndex == kPortIndexOutput) {
+ if (mState == STARTING) {
+ // We're always allocating output buffers after
+ // allocating input buffers, so this is a good
+ // indication that now all buffers are allocated.
+ setState(STARTED);
+ (new AMessage)->postReply(mReplyID);
+ } else {
+ mFlags |= kFlagOutputBuffersChanged;
+ }
+ }
+ break;
+ }
+
+ case ACodec::kWhatOutputFormatChanged:
+ {
+ ALOGV("codec output format changed");
+
+ if ((mFlags & kFlagIsSoftwareCodec)
+ && mNativeWindow != NULL) {
+ AString mime;
+ CHECK(msg->findString("mime", &mime));
+
+ if (!strncasecmp("video/", mime.c_str(), 6)) {
+ delete mSoftRenderer;
+ mSoftRenderer = NULL;
+
+ int32_t width, height;
+ CHECK(msg->findInt32("width", &width));
+ CHECK(msg->findInt32("height", &height));
+
+ int32_t colorFormat;
+ CHECK(msg->findInt32(
+ "color-format", &colorFormat));
+
+ sp<MetaData> meta = new MetaData;
+ meta->setInt32(kKeyWidth, width);
+ meta->setInt32(kKeyHeight, height);
+ meta->setInt32(kKeyColorFormat, colorFormat);
+
+ mSoftRenderer =
+ new SoftwareRenderer(mNativeWindow, meta);
+ }
+ }
+
+ mOutputFormat = msg;
+ mFlags |= kFlagOutputFormatChanged;
+ break;
+ }
+
+ case ACodec::kWhatFillThisBuffer:
+ {
+ /* size_t index = */updateBuffers(kPortIndexInput, msg);
+
+ if (mState == FLUSHING
+ || mState == STOPPING
+ || mState == RELEASING) {
+ returnBuffersToCodecOnPort(kPortIndexInput);
+ break;
+ }
+
+ if (mFlags & kFlagDequeueInputPending) {
+ CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
+
+ ++mDequeueInputTimeoutGeneration;
+ mFlags &= ~kFlagDequeueInputPending;
+ mDequeueInputReplyID = 0;
+ }
+ break;
+ }
+
+ case ACodec::kWhatDrainThisBuffer:
+ {
+ /* size_t index = */updateBuffers(kPortIndexOutput, msg);
+
+ if (mState == FLUSHING
+ || mState == STOPPING
+ || mState == RELEASING) {
+ returnBuffersToCodecOnPort(kPortIndexOutput);
+ break;
+ }
+
+ sp<ABuffer> buffer;
+ CHECK(msg->findBuffer("buffer", &buffer));
+
+ int32_t omxFlags;
+ CHECK(msg->findInt32("flags", &omxFlags));
+
+ buffer->meta()->setInt32("omxFlags", omxFlags);
+
+ if (mFlags & kFlagDequeueOutputPending) {
+ CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
+
+ ++mDequeueOutputTimeoutGeneration;
+ mFlags &= ~kFlagDequeueOutputPending;
+ mDequeueOutputReplyID = 0;
+ }
+ break;
+ }
+
+ case ACodec::kWhatEOS:
+ {
+ // We already notify the client of this by using the
+ // corresponding flag in "onOutputBufferReady".
+ break;
+ }
+
+ case ACodec::kWhatShutdownCompleted:
+ {
+ if (mState == STOPPING) {
+ setState(INITIALIZED);
+ } else {
+ CHECK_EQ(mState, RELEASING);
+ setState(UNINITIALIZED);
+ }
+
+ (new AMessage)->postReply(mReplyID);
+ break;
+ }
+
+ case ACodec::kWhatFlushCompleted:
+ {
+ CHECK_EQ(mState, FLUSHING);
+ setState(STARTED);
+
+ mCodec->signalResume();
+
+ (new AMessage)->postReply(mReplyID);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+ break;
+ }
+
+ case kWhatInit:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if (mState != UNINITIALIZED) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+
+ response->postReply(replyID);
+ break;
+ }
+
+ mReplyID = replyID;
+ setState(INITIALIZING);
+
+ AString name;
+ CHECK(msg->findString("name", &name));
+
+ int32_t nameIsType;
+ int32_t encoder = false;
+ CHECK(msg->findInt32("nameIsType", &nameIsType));
+ if (nameIsType) {
+ CHECK(msg->findInt32("encoder", &encoder));
+ }
+
+ sp<AMessage> format = new AMessage;
+
+ if (nameIsType) {
+ format->setString("mime", name.c_str());
+ format->setInt32("encoder", encoder);
+ } else {
+ format->setString("componentName", name.c_str());
+ }
+
+ mCodec->initiateAllocateComponent(format);
+ break;
+ }
+
+ case kWhatConfigure:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if (mState != INITIALIZED) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+
+ response->postReply(replyID);
+ break;
+ }
+
+ mReplyID = replyID;
+ setState(CONFIGURING);
+
+ sp<RefBase> obj;
+ if (!msg->findObject("native-window", &obj)) {
+ obj.clear();
+ }
+
+ sp<AMessage> format;
+ CHECK(msg->findMessage("format", &format));
+
+ if (obj != NULL) {
+ format->setObject("native-window", obj);
+ }
+
+ uint32_t flags;
+ CHECK(msg->findInt32("flags", (int32_t *)&flags));
+
+ if (flags & CONFIGURE_FLAG_ENCODE) {
+ format->setInt32("encoder", true);
+ }
+
+ if (flags & CONFIGURE_FLAG_SECURE) {
+ mFlags |= kFlagIsSecure;
+
+ sp<IServiceManager> sm = defaultServiceManager();
+
+ sp<IBinder> binder =
+ sm->getService(String16("media.player"));
+
+ sp<IMediaPlayerService> service =
+ interface_cast<IMediaPlayerService>(binder);
+
+ CHECK(service != NULL);
+
+ mCrypto = service->makeCrypto();
+
+ status_t err = mCrypto->initialize();
+
+ if (err == OK) {
+ sp<ABuffer> emm;
+ if (format->findBuffer("emm", &emm)) {
+ err = mCrypto->setEntitlementKey(
+ emm->data(), emm->size());
+ }
+ }
+
+ if (err == OK) {
+ sp<ABuffer> ecm;
+ if (format->findBuffer("ecm", &ecm)) {
+ CHECK_EQ(ecm->size(), 80u);
+
+ // bytes 16..47 of the original ecm stream data.
+ err = mCrypto->setEntitlementControlMessage(
+ ecm->data() + 16, 32);
+ }
+ }
+
+ if (err != OK) {
+ ALOGE("failed to instantiate crypto service.");
+
+ mCrypto.clear();
+
+ setState(INITIALIZED);
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", UNKNOWN_ERROR);
+
+ response->postReply(mReplyID);
+ break;
+ }
+ } else {
+ mFlags &= ~kFlagIsSecure;
+ }
+
+ mCodec->initiateConfigureComponent(format);
+ break;
+ }
+
+ case kWhatStart:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if (mState != CONFIGURED) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+
+ response->postReply(replyID);
+ break;
+ }
+
+ mReplyID = replyID;
+ setState(STARTING);
+
+ mCodec->initiateStart();
+ break;
+ }
+
+ case kWhatStop:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if (mState != INITIALIZED
+ && mState != CONFIGURED && mState != STARTED) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+
+ response->postReply(replyID);
+ break;
+ }
+
+ mReplyID = replyID;
+ setState(STOPPING);
+
+ mCodec->initiateShutdown(true /* keepComponentAllocated */);
+ returnBuffersToCodec();
+ break;
+ }
+
+ case kWhatRelease:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if (mState != INITIALIZED
+ && mState != CONFIGURED && mState != STARTED) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+
+ response->postReply(replyID);
+ break;
+ }
+
+ mReplyID = replyID;
+ setState(RELEASING);
+
+ mCodec->initiateShutdown();
+ returnBuffersToCodec();
+ break;
+ }
+
+ case kWhatDequeueInputBuffer:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if (handleDequeueInputBuffer(replyID, true /* new request */)) {
+ break;
+ }
+
+ int64_t timeoutUs;
+ CHECK(msg->findInt64("timeoutUs", &timeoutUs));
+
+ if (timeoutUs == 0ll) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", -EAGAIN);
+ response->postReply(replyID);
+ break;
+ }
+
+ mFlags |= kFlagDequeueInputPending;
+ mDequeueInputReplyID = replyID;
+
+ if (timeoutUs > 0ll) {
+ sp<AMessage> timeoutMsg =
+ new AMessage(kWhatDequeueInputTimedOut, id());
+ timeoutMsg->setInt32(
+ "generation", ++mDequeueInputTimeoutGeneration);
+ timeoutMsg->post(timeoutUs);
+ }
+ break;
+ }
+
+ case kWhatDequeueInputTimedOut:
+ {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+
+ if (generation != mDequeueInputTimeoutGeneration) {
+ // Obsolete
+ break;
+ }
+
+ CHECK(mFlags & kFlagDequeueInputPending);
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", -EAGAIN);
+ response->postReply(mDequeueInputReplyID);
+
+ mFlags &= ~kFlagDequeueInputPending;
+ mDequeueInputReplyID = 0;
+ break;
+ }
+
+ case kWhatQueueInputBuffer:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if (mState != STARTED || (mFlags & kFlagStickyError)) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+
+ response->postReply(replyID);
+ break;
+ }
+
+ status_t err = onQueueInputBuffer(msg);
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", err);
+ response->postReply(replyID);
+ break;
+ }
+
+ case kWhatDequeueOutputBuffer:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
+ break;
+ }
+
+ int64_t timeoutUs;
+ CHECK(msg->findInt64("timeoutUs", &timeoutUs));
+
+ if (timeoutUs == 0ll) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", -EAGAIN);
+ response->postReply(replyID);
+ break;
+ }
+
+ mFlags |= kFlagDequeueOutputPending;
+ mDequeueOutputReplyID = replyID;
+
+ if (timeoutUs > 0ll) {
+ sp<AMessage> timeoutMsg =
+ new AMessage(kWhatDequeueOutputTimedOut, id());
+ timeoutMsg->setInt32(
+ "generation", ++mDequeueOutputTimeoutGeneration);
+ timeoutMsg->post(timeoutUs);
+ }
+ break;
+ }
+
+ case kWhatDequeueOutputTimedOut:
+ {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+
+ if (generation != mDequeueOutputTimeoutGeneration) {
+ // Obsolete
+ break;
+ }
+
+ CHECK(mFlags & kFlagDequeueOutputPending);
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", -EAGAIN);
+ response->postReply(mDequeueOutputReplyID);
+
+ mFlags &= ~kFlagDequeueOutputPending;
+ mDequeueOutputReplyID = 0;
+ break;
+ }
+
+ case kWhatReleaseOutputBuffer:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if (mState != STARTED || (mFlags & kFlagStickyError)) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+
+ response->postReply(replyID);
+ break;
+ }
+
+ status_t err = onReleaseOutputBuffer(msg);
+
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", err);
+ response->postReply(replyID);
+ break;
+ }
+
+ case kWhatGetBuffers:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if (mState != STARTED || (mFlags & kFlagStickyError)) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+
+ response->postReply(replyID);
+ break;
+ }
+
+ int32_t portIndex;
+ CHECK(msg->findInt32("portIndex", &portIndex));
+
+ Vector<sp<ABuffer> > *dstBuffers;
+ CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
+
+ dstBuffers->clear();
+ const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
+
+ for (size_t i = 0; i < srcBuffers.size(); ++i) {
+ const BufferInfo &info = srcBuffers.itemAt(i);
+
+ dstBuffers->push_back(
+ (portIndex == kPortIndexInput
+ && (mFlags & kFlagIsSecure))
+ ? info.mEncryptedData : info.mData);
+ }
+
+ (new AMessage)->postReply(replyID);
+ break;
+ }
+
+ case kWhatFlush:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if (mState != STARTED || (mFlags & kFlagStickyError)) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+
+ response->postReply(replyID);
+ break;
+ }
+
+ mReplyID = replyID;
+ setState(FLUSHING);
+
+ mCodec->signalFlush();
+ returnBuffersToCodec();
+ break;
+ }
+
+ case kWhatGetOutputFormat:
+ {
+ uint32_t replyID;
+ CHECK(msg->senderAwaitsResponse(&replyID));
+
+ if ((mState != STARTED && mState != FLUSHING)
+ || (mFlags & kFlagStickyError)) {
+ sp<AMessage> response = new AMessage;
+ response->setInt32("err", INVALID_OPERATION);
+
+ response->postReply(replyID);
+ break;
+ }
+
+ sp<AMessage> response = new AMessage;
+ response->setMessage("format", mOutputFormat);
+ response->postReply(replyID);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+}
+
+void MediaCodec::setState(State newState) {
+ if (newState == INITIALIZED) {
+ delete mSoftRenderer;
+ mSoftRenderer = NULL;
+
+ if (mCrypto != NULL) {
+ mCrypto->terminate();
+ mCrypto.clear();
+ }
+
+ mNativeWindow.clear();
+
+ mOutputFormat.clear();
+ mFlags &= ~kFlagOutputFormatChanged;
+ mFlags &= ~kFlagOutputBuffersChanged;
+ mFlags &= ~kFlagStickyError;
+ }
+
+ mState = newState;
+
+ cancelPendingDequeueOperations();
+}
+
+void MediaCodec::returnBuffersToCodec() {
+ returnBuffersToCodecOnPort(kPortIndexInput);
+ returnBuffersToCodecOnPort(kPortIndexOutput);
+}
+
+void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
+ CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
+
+ Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
+
+ for (size_t i = 0; i < buffers->size(); ++i) {
+ BufferInfo *info = &buffers->editItemAt(i);
+
+ if (info->mNotify != NULL) {
+ sp<AMessage> msg = info->mNotify;
+ info->mNotify = NULL;
+ info->mOwnedByClient = false;
+
+ if (portIndex == kPortIndexInput) {
+ msg->setInt32("err", ERROR_END_OF_STREAM);
+ }
+ msg->post();
+ }
+ }
+
+ mAvailPortBuffers[portIndex].clear();
+}
+
+size_t MediaCodec::updateBuffers(
+ int32_t portIndex, const sp<AMessage> &msg) {
+ CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
+
+ void *bufferID;
+ CHECK(msg->findPointer("buffer-id", &bufferID));
+
+ Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
+
+ for (size_t i = 0; i < buffers->size(); ++i) {
+ BufferInfo *info = &buffers->editItemAt(i);
+
+ if (info->mBufferID == bufferID) {
+ CHECK(info->mNotify == NULL);
+ CHECK(msg->findMessage("reply", &info->mNotify));
+
+ mAvailPortBuffers[portIndex].push_back(i);
+
+ return i;
+ }
+ }
+
+ TRESPASS();
+
+ return 0;
+}
+
+status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
+ size_t index;
+ size_t offset;
+ size_t size;
+ int64_t timeUs;
+ uint32_t flags;
+ CHECK(msg->findSize("index", &index));
+ CHECK(msg->findSize("offset", &offset));
+ CHECK(msg->findSize("size", &size));
+ CHECK(msg->findInt64("timeUs", &timeUs));
+ CHECK(msg->findInt32("flags", (int32_t *)&flags));
+
+ if (index >= mPortBuffers[kPortIndexInput].size()) {
+ return -ERANGE;
+ }
+
+ BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
+
+ if (info->mNotify == NULL || !info->mOwnedByClient) {
+ return -EACCES;
+ }
+
+ if (offset + size > info->mData->capacity()) {
+ return -EINVAL;
+ }
+
+ sp<AMessage> reply = info->mNotify;
+ info->mNotify = NULL;
+ info->mOwnedByClient = false;
+
+ info->mData->setRange(offset, size);
+ info->mData->meta()->setInt64("timeUs", timeUs);
+
+ if (flags & BUFFER_FLAG_EOS) {
+ info->mData->meta()->setInt32("eos", true);
+ }
+
+ if (flags & BUFFER_FLAG_CODECCONFIG) {
+ info->mData->meta()->setInt32("csd", true);
+ }
+
+ if (mFlags & kFlagIsSecure) {
+ uint8_t iv[16];
+ memset(iv, 0, sizeof(iv));
+
+ ssize_t outLength;
+
+ if (mFlags & kFlagIsSoftwareCodec) {
+ outLength = mCrypto->decryptAudio(
+ (flags & BUFFER_FLAG_ENCRYPTED) ? iv : NULL,
+ (flags & BUFFER_FLAG_ENCRYPTED) ? sizeof(iv) : 0,
+ info->mEncryptedData->base() + offset,
+ size,
+ info->mData->base(),
+ info->mData->capacity());
+ } else {
+ outLength = mCrypto->decryptVideo(
+ (flags & BUFFER_FLAG_ENCRYPTED) ? iv : NULL,
+ (flags & BUFFER_FLAG_ENCRYPTED) ? sizeof(iv) : 0,
+ info->mEncryptedData->base() + offset,
+ size,
+ info->mData->base(),
+ 0 /* offset */);
+ }
+
+ if (outLength < 0) {
+ return outLength;
+ }
+
+ if ((size_t)outLength > info->mEncryptedData->capacity()) {
+ return -ERANGE;
+ }
+
+ info->mData->setRange(0, outLength);
+ } else if (flags & BUFFER_FLAG_ENCRYPTED) {
+ return -EINVAL;
+ }
+
+ reply->setBuffer("buffer", info->mData);
+ reply->post();
+
+ return OK;
+}
+
+status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
+ size_t index;
+ CHECK(msg->findSize("index", &index));
+
+ int32_t render;
+ if (!msg->findInt32("render", &render)) {
+ render = 0;
+ }
+
+ if (mState != STARTED) {
+ return -EINVAL;
+ }
+
+ if (index >= mPortBuffers[kPortIndexOutput].size()) {
+ return -ERANGE;
+ }
+
+ BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
+
+ if (info->mNotify == NULL || !info->mOwnedByClient) {
+ return -EACCES;
+ }
+
+ if (render) {
+ info->mNotify->setInt32("render", true);
+
+ if (mSoftRenderer != NULL) {
+ mSoftRenderer->render(
+ info->mData->data(), info->mData->size(), NULL);
+ }
+ }
+
+ info->mNotify->post();
+ info->mNotify = NULL;
+ info->mOwnedByClient = false;
+
+ return OK;
+}
+
+ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
+ CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
+
+ List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
+
+ if (availBuffers->empty()) {
+ return -EAGAIN;
+ }
+
+ size_t index = *availBuffers->begin();
+ availBuffers->erase(availBuffers->begin());
+
+ BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
+ CHECK(!info->mOwnedByClient);
+ info->mOwnedByClient = true;
+
+ return index;
+}
+
+} // namespace android
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
new file mode 100644
index 0000000..6b64e21
--- /dev/null
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -0,0 +1,475 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "MediaCodecList"
+#include <utils/Log.h>
+
+#include <media/stagefright/MediaCodecList.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/threads.h>
+
+#include <expat.h>
+
+namespace android {
+
+static Mutex sInitMutex;
+
+// static
+MediaCodecList *MediaCodecList::sCodecList;
+
+// static
+const MediaCodecList *MediaCodecList::getInstance() {
+ Mutex::Autolock autoLock(sInitMutex);
+
+ if (sCodecList == NULL) {
+ sCodecList = new MediaCodecList;
+ }
+
+ return sCodecList->initCheck() == OK ? sCodecList : NULL;
+}
+
+MediaCodecList::MediaCodecList()
+ : mInitCheck(NO_INIT) {
+ FILE *file = fopen("/etc/media_codecs.xml", "r");
+
+ if (file == NULL) {
+ ALOGW("unable to open media codecs configuration xml file.");
+ return;
+ }
+
+ parseXMLFile(file);
+
+ if (mInitCheck == OK) {
+ // These are currently still used by the video editing suite.
+
+ addMediaCodec(true /* encoder */, "AACEncoder", "audio/mp4a-latm");
+ addMediaCodec(true /* encoder */, "AVCEncoder", "video/avc");
+
+ addMediaCodec(true /* encoder */, "M4vH263Encoder");
+ addType("video/3gpp");
+ addType("video/mp4v-es");
+ }
+
+#if 0
+ for (size_t i = 0; i < mCodecInfos.size(); ++i) {
+ const CodecInfo &info = mCodecInfos.itemAt(i);
+
+ AString line = info.mName;
+ line.append(" supports ");
+ for (size_t j = 0; j < mTypes.size(); ++j) {
+ uint32_t value = mTypes.valueAt(j);
+
+ if (info.mTypes & (1ul << value)) {
+ line.append(mTypes.keyAt(j));
+ line.append(" ");
+ }
+ }
+
+ ALOGI("%s", line.c_str());
+ }
+#endif
+
+ fclose(file);
+ file = NULL;
+}
+
+MediaCodecList::~MediaCodecList() {
+}
+
+status_t MediaCodecList::initCheck() const {
+ return mInitCheck;
+}
+
+void MediaCodecList::parseXMLFile(FILE *file) {
+ mInitCheck = OK;
+ mCurrentSection = SECTION_TOPLEVEL;
+ mDepth = 0;
+
+ XML_Parser parser = ::XML_ParserCreate(NULL);
+ CHECK(parser != NULL);
+
+ ::XML_SetUserData(parser, this);
+ ::XML_SetElementHandler(
+ parser, StartElementHandlerWrapper, EndElementHandlerWrapper);
+
+ const int BUFF_SIZE = 512;
+ while (mInitCheck == OK) {
+ void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
+ if (buff == NULL) {
+ ALOGE("failed to in call to XML_GetBuffer()");
+ mInitCheck = UNKNOWN_ERROR;
+ break;
+ }
+
+ int bytes_read = ::fread(buff, 1, BUFF_SIZE, file);
+ if (bytes_read < 0) {
+ ALOGE("failed in call to read");
+ mInitCheck = ERROR_IO;
+ break;
+ }
+
+ if (::XML_ParseBuffer(parser, bytes_read, bytes_read == 0)
+ != XML_STATUS_OK) {
+ mInitCheck = ERROR_MALFORMED;
+ break;
+ }
+
+ if (bytes_read == 0) {
+ break;
+ }
+ }
+
+ ::XML_ParserFree(parser);
+
+ if (mInitCheck == OK) {
+ for (size_t i = mCodecInfos.size(); i-- > 0;) {
+ CodecInfo *info = &mCodecInfos.editItemAt(i);
+
+ if (info->mTypes == 0) {
+ // No types supported by this component???
+
+ ALOGW("Component %s does not support any type of media?",
+ info->mName.c_str());
+
+ mCodecInfos.removeAt(i);
+ }
+ }
+ }
+
+ if (mInitCheck != OK) {
+ mCodecInfos.clear();
+ mCodecQuirks.clear();
+ }
+}
+
+// static
+void MediaCodecList::StartElementHandlerWrapper(
+ void *me, const char *name, const char **attrs) {
+ static_cast<MediaCodecList *>(me)->startElementHandler(name, attrs);
+}
+
+// static
+void MediaCodecList::EndElementHandlerWrapper(void *me, const char *name) {
+ static_cast<MediaCodecList *>(me)->endElementHandler(name);
+}
+
+void MediaCodecList::startElementHandler(
+ const char *name, const char **attrs) {
+ if (mInitCheck != OK) {
+ return;
+ }
+
+ switch (mCurrentSection) {
+ case SECTION_TOPLEVEL:
+ {
+ if (!strcmp(name, "Decoders")) {
+ mCurrentSection = SECTION_DECODERS;
+ } else if (!strcmp(name, "Encoders")) {
+ mCurrentSection = SECTION_ENCODERS;
+ }
+ break;
+ }
+
+ case SECTION_DECODERS:
+ {
+ if (!strcmp(name, "MediaCodec")) {
+ mInitCheck =
+ addMediaCodecFromAttributes(false /* encoder */, attrs);
+
+ mCurrentSection = SECTION_DECODER;
+ }
+ break;
+ }
+
+ case SECTION_ENCODERS:
+ {
+ if (!strcmp(name, "MediaCodec")) {
+ mInitCheck =
+ addMediaCodecFromAttributes(true /* encoder */, attrs);
+
+ mCurrentSection = SECTION_ENCODER;
+ }
+ break;
+ }
+
+ case SECTION_DECODER:
+ case SECTION_ENCODER:
+ {
+ if (!strcmp(name, "Quirk")) {
+ mInitCheck = addQuirk(attrs);
+ } else if (!strcmp(name, "Type")) {
+ mInitCheck = addTypeFromAttributes(attrs);
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ ++mDepth;
+}
+
+void MediaCodecList::endElementHandler(const char *name) {
+ if (mInitCheck != OK) {
+ return;
+ }
+
+ switch (mCurrentSection) {
+ case SECTION_DECODERS:
+ {
+ if (!strcmp(name, "Decoders")) {
+ mCurrentSection = SECTION_TOPLEVEL;
+ }
+ break;
+ }
+
+ case SECTION_ENCODERS:
+ {
+ if (!strcmp(name, "Encoders")) {
+ mCurrentSection = SECTION_TOPLEVEL;
+ }
+ break;
+ }
+
+ case SECTION_DECODER:
+ {
+ if (!strcmp(name, "MediaCodec")) {
+ mCurrentSection = SECTION_DECODERS;
+ }
+ break;
+ }
+
+ case SECTION_ENCODER:
+ {
+ if (!strcmp(name, "MediaCodec")) {
+ mCurrentSection = SECTION_ENCODERS;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ --mDepth;
+}
+
+status_t MediaCodecList::addMediaCodecFromAttributes(
+ bool encoder, const char **attrs) {
+ const char *name = NULL;
+ const char *type = NULL;
+
+ size_t i = 0;
+ while (attrs[i] != NULL) {
+ if (!strcmp(attrs[i], "name")) {
+ if (attrs[i + 1] == NULL) {
+ return -EINVAL;
+ }
+ name = attrs[i + 1];
+ ++i;
+ } else if (!strcmp(attrs[i], "type")) {
+ if (attrs[i + 1] == NULL) {
+ return -EINVAL;
+ }
+ type = attrs[i + 1];
+ ++i;
+ } else {
+ return -EINVAL;
+ }
+
+ ++i;
+ }
+
+ if (name == NULL) {
+ return -EINVAL;
+ }
+
+ addMediaCodec(encoder, name, type);
+
+ return OK;
+}
+
+void MediaCodecList::addMediaCodec(
+ bool encoder, const char *name, const char *type) {
+ mCodecInfos.push();
+ CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
+ info->mName = name;
+ info->mIsEncoder = encoder;
+ info->mTypes = 0;
+ info->mQuirks = 0;
+
+ if (type != NULL) {
+ addType(type);
+ }
+}
+
+status_t MediaCodecList::addQuirk(const char **attrs) {
+ const char *name = NULL;
+
+ size_t i = 0;
+ while (attrs[i] != NULL) {
+ if (!strcmp(attrs[i], "name")) {
+ if (attrs[i + 1] == NULL) {
+ return -EINVAL;
+ }
+ name = attrs[i + 1];
+ ++i;
+ } else {
+ return -EINVAL;
+ }
+
+ ++i;
+ }
+
+ if (name == NULL) {
+ return -EINVAL;
+ }
+
+ uint32_t bit;
+ ssize_t index = mCodecQuirks.indexOfKey(name);
+ if (index < 0) {
+ bit = mCodecQuirks.size();
+
+ if (bit == 32) {
+ ALOGW("Too many distinct quirk names in configuration.");
+ return OK;
+ }
+
+ mCodecQuirks.add(name, bit);
+ } else {
+ bit = mCodecQuirks.valueAt(index);
+ }
+
+ CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
+ info->mQuirks |= 1ul << bit;
+
+ return OK;
+}
+
+status_t MediaCodecList::addTypeFromAttributes(const char **attrs) {
+ const char *name = NULL;
+
+ size_t i = 0;
+ while (attrs[i] != NULL) {
+ if (!strcmp(attrs[i], "name")) {
+ if (attrs[i + 1] == NULL) {
+ return -EINVAL;
+ }
+ name = attrs[i + 1];
+ ++i;
+ } else {
+ return -EINVAL;
+ }
+
+ ++i;
+ }
+
+ if (name == NULL) {
+ return -EINVAL;
+ }
+
+ addType(name);
+
+ return OK;
+}
+
+void MediaCodecList::addType(const char *name) {
+ uint32_t bit;
+ ssize_t index = mTypes.indexOfKey(name);
+ if (index < 0) {
+ bit = mTypes.size();
+
+ if (bit == 32) {
+ ALOGW("Too many distinct type names in configuration.");
+ return;
+ }
+
+ mTypes.add(name, bit);
+ } else {
+ bit = mTypes.valueAt(index);
+ }
+
+ CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1);
+ info->mTypes |= 1ul << bit;
+}
+
+ssize_t MediaCodecList::findCodecByType(
+ const char *type, bool encoder, size_t startIndex) const {
+ ssize_t typeIndex = mTypes.indexOfKey(type);
+
+ if (typeIndex < 0) {
+ return -ENOENT;
+ }
+
+ uint32_t typeMask = 1ul << mTypes.valueAt(typeIndex);
+
+ while (startIndex < mCodecInfos.size()) {
+ const CodecInfo &info = mCodecInfos.itemAt(startIndex);
+
+ if (info.mIsEncoder == encoder && (info.mTypes & typeMask)) {
+ return startIndex;
+ }
+
+ ++startIndex;
+ }
+
+ return -ENOENT;
+}
+
+ssize_t MediaCodecList::findCodecByName(const char *name) const {
+ for (size_t i = 0; i < mCodecInfos.size(); ++i) {
+ const CodecInfo &info = mCodecInfos.itemAt(i);
+
+ if (info.mName == name) {
+ return i;
+ }
+ }
+
+ return -ENOENT;
+}
+
+const char *MediaCodecList::getCodecName(size_t index) const {
+ if (index >= mCodecInfos.size()) {
+ return NULL;
+ }
+
+ const CodecInfo &info = mCodecInfos.itemAt(index);
+ return info.mName.c_str();
+}
+
+bool MediaCodecList::codecHasQuirk(
+ size_t index, const char *quirkName) const {
+ if (index >= mCodecInfos.size()) {
+ return NULL;
+ }
+
+ const CodecInfo &info = mCodecInfos.itemAt(index);
+
+ if (info.mQuirks != 0) {
+ ssize_t index = mCodecQuirks.indexOfKey(quirkName);
+ if (index >= 0 && info.mQuirks & (1ul << mCodecQuirks.valueAt(index))) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} // namespace android
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
new file mode 100644
index 0000000..2740d6b
--- /dev/null
+++ b/media/libstagefright/MediaDefs.cpp
@@ -0,0 +1,57 @@
+/*
+ * 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 <media/stagefright/MediaDefs.h>
+
+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";
+const char *MEDIA_MIMETYPE_VIDEO_MPEG2 = "video/mpeg2";
+const char *MEDIA_MIMETYPE_VIDEO_RAW = "video/raw";
+
+const char *MEDIA_MIMETYPE_AUDIO_AMR_NB = "audio/3gpp";
+const char *MEDIA_MIMETYPE_AUDIO_AMR_WB = "audio/amr-wb";
+const char *MEDIA_MIMETYPE_AUDIO_MPEG = "audio/mpeg";
+const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I = "audio/mpeg-L1";
+const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II = "audio/mpeg-L2";
+const char *MEDIA_MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
+const char *MEDIA_MIMETYPE_AUDIO_QCELP = "audio/qcelp";
+const char *MEDIA_MIMETYPE_AUDIO_VORBIS = "audio/vorbis";
+const char *MEDIA_MIMETYPE_AUDIO_G711_ALAW = "audio/g711-alaw";
+const char *MEDIA_MIMETYPE_AUDIO_G711_MLAW = "audio/g711-mlaw";
+const char *MEDIA_MIMETYPE_AUDIO_RAW = "audio/raw";
+const char *MEDIA_MIMETYPE_AUDIO_FLAC = "audio/flac";
+const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS = "audio/aac-adts";
+
+const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4";
+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";
+const char *MEDIA_MIMETYPE_CONTAINER_AVI = "video/avi";
+const char *MEDIA_MIMETYPE_CONTAINER_MPEG2PS = "video/mp2p";
+
+const char *MEDIA_MIMETYPE_CONTAINER_WVM = "video/wvm";
+
+const char *MEDIA_MIMETYPE_TEXT_3GPP = "text/3gpp-tt";
+const char *MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
+
+} // namespace android
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
new file mode 100644
index 0000000..2171492
--- /dev/null
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -0,0 +1,134 @@
+/*
+ * 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 "MediaExtractor"
+#include <utils/Log.h>
+
+#include "include/AMRExtractor.h"
+#include "include/AVIExtractor.h"
+#include "include/MP3Extractor.h"
+#include "include/MPEG4Extractor.h"
+#include "include/WAVExtractor.h"
+#include "include/OggExtractor.h"
+#include "include/MPEG2PSExtractor.h"
+#include "include/MPEG2TSExtractor.h"
+#include "include/DRMExtractor.h"
+#include "include/WVMExtractor.h"
+#include "include/FLACExtractor.h"
+#include "include/AACExtractor.h"
+
+#include "matroska/MatroskaExtractor.h"
+
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/String8.h>
+
+namespace android {
+
+sp<MetaData> MediaExtractor::getMetaData() {
+ return new MetaData;
+}
+
+uint32_t MediaExtractor::flags() const {
+ return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE | CAN_SEEK;
+}
+
+// static
+sp<MediaExtractor> MediaExtractor::Create(
+ const sp<DataSource> &source, const char *mime) {
+ sp<AMessage> meta;
+
+ String8 tmp;
+ if (mime == NULL) {
+ float confidence;
+ if (!source->sniff(&tmp, &confidence, &meta)) {
+ ALOGV("FAILED to autodetect media content.");
+
+ return NULL;
+ }
+
+ mime = tmp.string();
+ ALOGV("Autodetected media content as '%s' with confidence %.2f",
+ mime, confidence);
+ }
+
+ bool isDrm = false;
+ // DRM MIME type syntax is "drm+type+original" where
+ // type is "es_based" or "container_based" and
+ // original is the content's cleartext MIME type
+ if (!strncmp(mime, "drm+", 4)) {
+ const char *originalMime = strchr(mime+4, '+');
+ if (originalMime == NULL) {
+ // second + not found
+ return NULL;
+ }
+ ++originalMime;
+ if (!strncmp(mime, "drm+es_based+", 13)) {
+ // DRMExtractor sets container metadata kKeyIsDRM to 1
+ return new DRMExtractor(source, originalMime);
+ } else if (!strncmp(mime, "drm+container_based+", 20)) {
+ mime = originalMime;
+ isDrm = true;
+ } else {
+ return NULL;
+ }
+ }
+
+ MediaExtractor *ret = NULL;
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4)
+ || !strcasecmp(mime, "audio/mp4")) {
+ ret = new MPEG4Extractor(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
+ ret = new MP3Extractor(source, meta);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)
+ || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
+ ret = new AMRExtractor(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
+ ret = new FLACExtractor(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WAV)) {
+ ret = new WAVExtractor(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_OGG)) {
+ ret = new OggExtractor(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MATROSKA)) {
+ ret = new MatroskaExtractor(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
+ ret = new MPEG2TSExtractor(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_AVI)) {
+ ret = new AVIExtractor(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WVM)) {
+ ret = new WVMExtractor(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC_ADTS)) {
+ ret = new AACExtractor(source, meta);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2PS)) {
+ ret = new MPEG2PSExtractor(source);
+ }
+
+ if (ret != NULL) {
+ if (isDrm) {
+ ret->setDrmFlag(true);
+ } else {
+ ret->setDrmFlag(false);
+ }
+ }
+
+ return ret;
+}
+
+} // namespace android
diff --git a/media/libstagefright/MediaSource.cpp b/media/libstagefright/MediaSource.cpp
new file mode 100644
index 0000000..fd0e79c
--- /dev/null
+++ b/media/libstagefright/MediaSource.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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 <media/stagefright/MediaSource.h>
+
+namespace android {
+
+MediaSource::MediaSource() {}
+
+MediaSource::~MediaSource() {}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MediaSource::ReadOptions::ReadOptions() {
+ reset();
+}
+
+void MediaSource::ReadOptions::reset() {
+ mOptions = 0;
+ mSeekTimeUs = 0;
+ mLatenessUs = 0;
+}
+
+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, SeekMode *mode) const {
+ *time_us = mSeekTimeUs;
+ *mode = mSeekMode;
+ return (mOptions & kSeekTo_Option) != 0;
+}
+
+void MediaSource::ReadOptions::setLateBy(int64_t lateness_us) {
+ mLatenessUs = lateness_us;
+}
+
+int64_t MediaSource::ReadOptions::getLateBy() const {
+ return mLatenessUs;
+}
+
+} // namespace android
diff --git a/media/libstagefright/MetaData.cpp b/media/libstagefright/MetaData.cpp
new file mode 100644
index 0000000..755594a
--- /dev/null
+++ b/media/libstagefright/MetaData.cpp
@@ -0,0 +1,345 @@
+/*
+ * 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 "MetaData"
+#include <utils/Log.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+MetaData::MetaData() {
+}
+
+MetaData::MetaData(const MetaData &from)
+ : RefBase(),
+ mItems(from.mItems) {
+}
+
+MetaData::~MetaData() {
+ clear();
+}
+
+void MetaData::clear() {
+ mItems.clear();
+}
+
+bool MetaData::remove(uint32_t key) {
+ ssize_t i = mItems.indexOfKey(key);
+
+ if (i < 0) {
+ return false;
+ }
+
+ mItems.removeItemsAt(i);
+
+ return true;
+}
+
+bool MetaData::setCString(uint32_t key, const char *value) {
+ return setData(key, TYPE_C_STRING, value, strlen(value) + 1);
+}
+
+bool MetaData::setInt32(uint32_t key, int32_t value) {
+ return setData(key, TYPE_INT32, &value, sizeof(value));
+}
+
+bool MetaData::setInt64(uint32_t key, int64_t value) {
+ return setData(key, TYPE_INT64, &value, sizeof(value));
+}
+
+bool MetaData::setFloat(uint32_t key, float value) {
+ return setData(key, TYPE_FLOAT, &value, sizeof(value));
+}
+
+bool MetaData::setPointer(uint32_t key, void *value) {
+ return setData(key, TYPE_POINTER, &value, sizeof(value));
+}
+
+bool MetaData::setRect(
+ uint32_t key,
+ int32_t left, int32_t top,
+ int32_t right, int32_t bottom) {
+ Rect r;
+ r.mLeft = left;
+ r.mTop = top;
+ r.mRight = right;
+ r.mBottom = bottom;
+
+ return setData(key, TYPE_RECT, &r, sizeof(r));
+}
+
+bool MetaData::findCString(uint32_t key, const char **value) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_C_STRING) {
+ return false;
+ }
+
+ *value = (const char *)data;
+
+ return true;
+}
+
+bool MetaData::findInt32(uint32_t key, int32_t *value) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_INT32) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(*value));
+
+ *value = *(int32_t *)data;
+
+ return true;
+}
+
+bool MetaData::findInt64(uint32_t key, int64_t *value) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_INT64) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(*value));
+
+ *value = *(int64_t *)data;
+
+ return true;
+}
+
+bool MetaData::findFloat(uint32_t key, float *value) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_FLOAT) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(*value));
+
+ *value = *(float *)data;
+
+ return true;
+}
+
+bool MetaData::findPointer(uint32_t key, void **value) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_POINTER) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(*value));
+
+ *value = *(void **)data;
+
+ return true;
+}
+
+bool MetaData::findRect(
+ uint32_t key,
+ int32_t *left, int32_t *top,
+ int32_t *right, int32_t *bottom) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (!findData(key, &type, &data, &size) || type != TYPE_RECT) {
+ return false;
+ }
+
+ CHECK_EQ(size, sizeof(Rect));
+
+ const Rect *r = (const Rect *)data;
+ *left = r->mLeft;
+ *top = r->mTop;
+ *right = r->mRight;
+ *bottom = r->mBottom;
+
+ return true;
+}
+
+bool MetaData::setData(
+ uint32_t key, uint32_t type, const void *data, size_t size) {
+ bool overwrote_existing = true;
+
+ ssize_t i = mItems.indexOfKey(key);
+ if (i < 0) {
+ typed_data item;
+ i = mItems.add(key, item);
+
+ overwrote_existing = false;
+ }
+
+ typed_data &item = mItems.editValueAt(i);
+
+ item.setData(type, data, size);
+
+ return overwrote_existing;
+}
+
+bool MetaData::findData(uint32_t key, uint32_t *type,
+ const void **data, size_t *size) const {
+ ssize_t i = mItems.indexOfKey(key);
+
+ if (i < 0) {
+ return false;
+ }
+
+ const typed_data &item = mItems.valueAt(i);
+
+ item.getData(type, data, size);
+
+ return true;
+}
+
+MetaData::typed_data::typed_data()
+ : mType(0),
+ mSize(0) {
+}
+
+MetaData::typed_data::~typed_data() {
+ clear();
+}
+
+MetaData::typed_data::typed_data(const typed_data &from)
+ : mType(from.mType),
+ mSize(0) {
+ allocateStorage(from.mSize);
+ memcpy(storage(), from.storage(), mSize);
+}
+
+MetaData::typed_data &MetaData::typed_data::operator=(
+ const MetaData::typed_data &from) {
+ if (this != &from) {
+ clear();
+ mType = from.mType;
+ allocateStorage(from.mSize);
+ memcpy(storage(), from.storage(), mSize);
+ }
+
+ return *this;
+}
+
+void MetaData::typed_data::clear() {
+ freeStorage();
+
+ mType = 0;
+}
+
+void MetaData::typed_data::setData(
+ uint32_t type, const void *data, size_t size) {
+ clear();
+
+ mType = type;
+ allocateStorage(size);
+ memcpy(storage(), data, size);
+}
+
+void MetaData::typed_data::getData(
+ uint32_t *type, const void **data, size_t *size) const {
+ *type = mType;
+ *size = mSize;
+ *data = storage();
+}
+
+void MetaData::typed_data::allocateStorage(size_t size) {
+ mSize = size;
+
+ if (usesReservoir()) {
+ return;
+ }
+
+ u.ext_data = malloc(mSize);
+}
+
+void MetaData::typed_data::freeStorage() {
+ if (!usesReservoir()) {
+ if (u.ext_data) {
+ free(u.ext_data);
+ }
+ }
+
+ mSize = 0;
+}
+
+String8 MetaData::typed_data::asString() const {
+ String8 out;
+ const void *data = storage();
+ switch(mType) {
+ case TYPE_NONE:
+ out = String8::format("no type, size %d)", mSize);
+ break;
+ case TYPE_C_STRING:
+ out = String8::format("(char*) %s", (const char *)data);
+ break;
+ case TYPE_INT32:
+ out = String8::format("(int32_t) %d", *(int32_t *)data);
+ break;
+ case TYPE_INT64:
+ out = String8::format("(int64_t) %lld", *(int64_t *)data);
+ break;
+ case TYPE_FLOAT:
+ out = String8::format("(float) %f", *(float *)data);
+ break;
+ case TYPE_POINTER:
+ out = String8::format("(void*) %p", *(void **)data);
+ break;
+ case TYPE_RECT:
+ {
+ const Rect *r = (const Rect *)data;
+ out = String8::format("Rect(%d, %d, %d, %d)",
+ r->mLeft, r->mTop, r->mRight, r->mBottom);
+ break;
+ }
+
+ default:
+ out = String8::format("(unknown type %d, size %d)", mType, mSize);
+ break;
+ }
+ return out;
+}
+
+static void MakeFourCCString(uint32_t x, char *s) {
+ s[0] = x >> 24;
+ s[1] = (x >> 16) & 0xff;
+ s[2] = (x >> 8) & 0xff;
+ s[3] = x & 0xff;
+ s[4] = '\0';
+}
+
+void MetaData::dumpToLog() const {
+ for (int i = mItems.size(); --i >= 0;) {
+ int32_t key = mItems.keyAt(i);
+ char cc[5];
+ MakeFourCCString(key, cc);
+ const typed_data &item = mItems.valueAt(i);
+ ALOGI("%s: %s", cc, item.asString().string());
+ }
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
new file mode 100644
index 0000000..0957426
--- /dev/null
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -0,0 +1,703 @@
+/*
+ * 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 "NuCachedSource2"
+#include <utils/Log.h>
+
+#include "include/NuCachedSource2.h"
+#include "include/HTTPBase.h"
+
+#include <cutils/properties.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) {
+ ALOGV("copy from %d size %d", from, size);
+
+ if (size == 0) {
+ return;
+ }
+
+ 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,
+ const char *cacheConfig,
+ bool disconnectAtHighwatermark)
+ : mSource(source),
+ mReflector(new AHandlerReflector<NuCachedSource2>(this)),
+ mLooper(new ALooper),
+ mCache(new PageCache(kPageSize)),
+ mCacheOffset(0),
+ mFinalStatus(OK),
+ mLastAccessPos(0),
+ mFetching(true),
+ mLastFetchTimeUs(-1),
+ mNumRetriesLeft(kMaxNumRetries),
+ mHighwaterThresholdBytes(kDefaultHighWaterThreshold),
+ mLowwaterThresholdBytes(kDefaultLowWaterThreshold),
+ mKeepAliveIntervalUs(kDefaultKeepAliveIntervalUs),
+ mDisconnectAtHighwatermark(disconnectAtHighwatermark) {
+ // We are NOT going to support disconnect-at-highwatermark indefinitely
+ // and we are not guaranteeing support for client-specified cache
+ // parameters. Both of these are temporary measures to solve a specific
+ // problem that will be solved in a better way going forward.
+
+ updateCacheParamsFromSystemProperty();
+
+ if (cacheConfig != NULL) {
+ updateCacheParamsFromString(cacheConfig);
+ }
+
+ if (mDisconnectAtHighwatermark) {
+ // Makes no sense to disconnect and do keep-alives...
+ mKeepAliveIntervalUs = 0;
+ }
+
+ mLooper->setName("NuCachedSource2");
+ 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::getEstimatedBandwidthKbps(int32_t *kbps) {
+ if (mSource->flags() & kIsHTTPBasedSource) {
+ HTTPBase* source = static_cast<HTTPBase *>(mSource.get());
+ return source->getEstimatedBandwidthKbps(kbps);
+ }
+ return ERROR_UNSUPPORTED;
+}
+
+status_t NuCachedSource2::setCacheStatCollectFreq(int32_t freqMs) {
+ if (mSource->flags() & kIsHTTPBasedSource) {
+ HTTPBase *source = static_cast<HTTPBase *>(mSource.get());
+ return source->setBandwidthStatCollectFreq(freqMs);
+ }
+ return ERROR_UNSUPPORTED;
+}
+
+status_t NuCachedSource2::initCheck() const {
+ return mSource->initCheck();
+}
+
+status_t NuCachedSource2::getSize(off64_t *size) {
+ return mSource->getSize(size);
+}
+
+uint32_t NuCachedSource2::flags() {
+ // Remove HTTP related flags since NuCachedSource2 is not HTTP-based.
+ uint32_t flags = mSource->flags() & ~(kWantsPrefetching | kIsHTTPBasedSource);
+ return (flags | kIsCachingDataSource);
+}
+
+void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatFetchMore:
+ {
+ onFetch();
+ break;
+ }
+
+ case kWhatRead:
+ {
+ onRead(msg);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+}
+
+void NuCachedSource2::fetchInternal() {
+ ALOGV("fetchInternal");
+
+ bool reconnect = false;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+ CHECK(mFinalStatus == OK || mNumRetriesLeft > 0);
+
+ if (mFinalStatus != OK) {
+ --mNumRetriesLeft;
+
+ reconnect = true;
+ }
+ }
+
+ if (reconnect) {
+ status_t err =
+ mSource->reconnectAtOffset(mCacheOffset + mCache->totalSize());
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (err == ERROR_UNSUPPORTED) {
+ mNumRetriesLeft = 0;
+ return;
+ } else if (err != OK) {
+ ALOGI("The attempt to reconnect failed, %d retries remaining",
+ mNumRetriesLeft);
+
+ return;
+ }
+ }
+
+ PageCache::Page *page = mCache->acquirePage();
+
+ ssize_t n = mSource->readAt(
+ mCacheOffset + mCache->totalSize(), page->mData, kPageSize);
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (n < 0) {
+ ALOGE("source returned error %ld, %d retries left", n, mNumRetriesLeft);
+ mFinalStatus = n;
+ mCache->releasePage(page);
+ } else if (n == 0) {
+ ALOGI("ERROR_END_OF_STREAM");
+
+ mNumRetriesLeft = 0;
+ mFinalStatus = ERROR_END_OF_STREAM;
+
+ mCache->releasePage(page);
+ } else {
+ if (mFinalStatus != OK) {
+ ALOGI("retrying a previously failed read succeeded.");
+ }
+ mNumRetriesLeft = kMaxNumRetries;
+ mFinalStatus = OK;
+
+ page->mSize = n;
+ mCache->appendPage(page);
+ }
+}
+
+void NuCachedSource2::onFetch() {
+ ALOGV("onFetch");
+
+ if (mFinalStatus != OK && mNumRetriesLeft == 0) {
+ ALOGV("EOS reached, done prefetching for now");
+ mFetching = false;
+ }
+
+ bool keepAlive =
+ !mFetching
+ && mFinalStatus == OK
+ && mKeepAliveIntervalUs > 0
+ && ALooper::GetNowUs() >= mLastFetchTimeUs + mKeepAliveIntervalUs;
+
+ if (mFetching || keepAlive) {
+ if (keepAlive) {
+ ALOGI("Keep alive");
+ }
+
+ fetchInternal();
+
+ mLastFetchTimeUs = ALooper::GetNowUs();
+
+ if (mFetching && mCache->totalSize() >= mHighwaterThresholdBytes) {
+ ALOGI("Cache full, done prefetching for now");
+ mFetching = false;
+
+ if (mDisconnectAtHighwatermark
+ && (mSource->flags() & DataSource::kIsHTTPBasedSource)) {
+ ALOGV("Disconnecting at high watermark");
+ static_cast<HTTPBase *>(mSource.get())->disconnect();
+ mFinalStatus = -EAGAIN;
+ }
+ }
+ } else {
+ Mutex::Autolock autoLock(mLock);
+ restartPrefetcherIfNecessary_l();
+ }
+
+ int64_t delayUs;
+ if (mFetching) {
+ if (mFinalStatus != OK && mNumRetriesLeft > 0) {
+ // We failed this time and will try again in 3 seconds.
+ delayUs = 3000000ll;
+ } else {
+ delayUs = 0;
+ }
+ } else {
+ delayUs = 100000ll;
+ }
+
+ (new AMessage(kWhatFetchMore, mReflector->id()))->post(delayUs);
+}
+
+void NuCachedSource2::onRead(const sp<AMessage> &msg) {
+ ALOGV("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(
+ bool ignoreLowWaterThreshold, bool force) {
+ static const size_t kGrayArea = 1024 * 1024;
+
+ if (mFetching || (mFinalStatus != OK && mNumRetriesLeft == 0)) {
+ return;
+ }
+
+ if (!ignoreLowWaterThreshold && !force
+ && mCacheOffset + mCache->totalSize() - mLastAccessPos
+ >= mLowwaterThresholdBytes) {
+ return;
+ }
+
+ size_t maxBytes = mLastAccessPos - mCacheOffset;
+
+ if (!force) {
+ if (maxBytes < kGrayArea) {
+ return;
+ }
+
+ maxBytes -= kGrayArea;
+ }
+
+ size_t actualBytes = mCache->releaseFromStart(maxBytes);
+ mCacheOffset += actualBytes;
+
+ ALOGI("restarting prefetcher, totalSize = %d", mCache->totalSize());
+ mFetching = true;
+}
+
+ssize_t NuCachedSource2::readAt(off64_t offset, void *data, size_t size) {
+ Mutex::Autolock autoSerializer(mSerializer);
+
+ ALOGV("readAt offset %lld, size %d", offset, 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(status_t *finalStatus) {
+ Mutex::Autolock autoLock(mLock);
+ return approxDataRemaining_l(finalStatus);
+}
+
+size_t NuCachedSource2::approxDataRemaining_l(status_t *finalStatus) {
+ *finalStatus = mFinalStatus;
+
+ if (mFinalStatus != OK && mNumRetriesLeft > 0) {
+ // Pretend that everything is fine until we're out of retries.
+ *finalStatus = OK;
+ }
+
+ off64_t lastBytePosCached = mCacheOffset + mCache->totalSize();
+ if (mLastAccessPos < lastBytePosCached) {
+ return lastBytePosCached - mLastAccessPos;
+ }
+ return 0;
+}
+
+ssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) {
+ CHECK_LE(size, (size_t)mHighwaterThresholdBytes);
+
+ ALOGV("readInternal offset %lld size %d", offset, size);
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (!mFetching) {
+ mLastAccessPos = offset;
+ restartPrefetcherIfNecessary_l(
+ false, // ignoreLowWaterThreshold
+ true); // force
+ }
+
+ if (offset < mCacheOffset
+ || offset >= (off64_t)(mCacheOffset + mCache->totalSize())) {
+ static const off64_t kPadding = 256 * 1024;
+
+ // 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.
+ off64_t seekOffset = (offset > kPadding) ? offset - kPadding : 0;
+
+ seekInternal_l(seekOffset);
+ }
+
+ size_t delta = offset - mCacheOffset;
+
+ if (mFinalStatus != OK && mNumRetriesLeft == 0) {
+ if (delta >= mCache->totalSize()) {
+ return mFinalStatus;
+ }
+
+ size_t avail = mCache->totalSize() - delta;
+
+ if (avail > size) {
+ avail = size;
+ }
+
+ mCache->copy(delta, data, avail);
+
+ return avail;
+ }
+
+ if (offset + size <= mCacheOffset + mCache->totalSize()) {
+ mCache->copy(delta, data, size);
+
+ return size;
+ }
+
+ ALOGV("deferring read");
+
+ return -EAGAIN;
+}
+
+status_t NuCachedSource2::seekInternal_l(off64_t offset) {
+ mLastAccessPos = offset;
+
+ if (offset >= mCacheOffset
+ && offset <= (off64_t)(mCacheOffset + mCache->totalSize())) {
+ return OK;
+ }
+
+ ALOGI("new range: offset= %lld", offset);
+
+ mCacheOffset = offset;
+
+ size_t totalSize = mCache->totalSize();
+ CHECK_EQ(mCache->releaseFromStart(totalSize), totalSize);
+
+ mNumRetriesLeft = kMaxNumRetries;
+ mFetching = true;
+
+ return OK;
+}
+
+void NuCachedSource2::resumeFetchingIfNecessary() {
+ Mutex::Autolock autoLock(mLock);
+
+ restartPrefetcherIfNecessary_l(true /* ignore low water threshold */);
+}
+
+sp<DecryptHandle> NuCachedSource2::DrmInitialization(const char* mime) {
+ return mSource->DrmInitialization(mime);
+}
+
+void NuCachedSource2::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
+ mSource->getDrmInfo(handle, client);
+}
+
+String8 NuCachedSource2::getUri() {
+ return mSource->getUri();
+}
+
+String8 NuCachedSource2::getMIMEType() const {
+ return mSource->getMIMEType();
+}
+
+void NuCachedSource2::updateCacheParamsFromSystemProperty() {
+ char value[PROPERTY_VALUE_MAX];
+ if (!property_get("media.stagefright.cache-params", value, NULL)) {
+ return;
+ }
+
+ updateCacheParamsFromString(value);
+}
+
+void NuCachedSource2::updateCacheParamsFromString(const char *s) {
+ ssize_t lowwaterMarkKb, highwaterMarkKb;
+ int keepAliveSecs;
+
+ if (sscanf(s, "%ld/%ld/%d",
+ &lowwaterMarkKb, &highwaterMarkKb, &keepAliveSecs) != 3) {
+ ALOGE("Failed to parse cache parameters from '%s'.", s);
+ return;
+ }
+
+ if (lowwaterMarkKb >= 0) {
+ mLowwaterThresholdBytes = lowwaterMarkKb * 1024;
+ } else {
+ mLowwaterThresholdBytes = kDefaultLowWaterThreshold;
+ }
+
+ if (highwaterMarkKb >= 0) {
+ mHighwaterThresholdBytes = highwaterMarkKb * 1024;
+ } else {
+ mHighwaterThresholdBytes = kDefaultHighWaterThreshold;
+ }
+
+ if (mLowwaterThresholdBytes >= mHighwaterThresholdBytes) {
+ ALOGE("Illegal low/highwater marks specified, reverting to defaults.");
+
+ mLowwaterThresholdBytes = kDefaultLowWaterThreshold;
+ mHighwaterThresholdBytes = kDefaultHighWaterThreshold;
+ }
+
+ if (keepAliveSecs >= 0) {
+ mKeepAliveIntervalUs = keepAliveSecs * 1000000ll;
+ } else {
+ mKeepAliveIntervalUs = kDefaultKeepAliveIntervalUs;
+ }
+
+ ALOGV("lowwater = %d bytes, highwater = %d bytes, keepalive = %lld us",
+ mLowwaterThresholdBytes,
+ mHighwaterThresholdBytes,
+ mKeepAliveIntervalUs);
+}
+
+// static
+void NuCachedSource2::RemoveCacheSpecificHeaders(
+ KeyedVector<String8, String8> *headers,
+ String8 *cacheConfig,
+ bool *disconnectAtHighwatermark) {
+ *cacheConfig = String8();
+ *disconnectAtHighwatermark = false;
+
+ if (headers == NULL) {
+ return;
+ }
+
+ ssize_t index;
+ if ((index = headers->indexOfKey(String8("x-cache-config"))) >= 0) {
+ *cacheConfig = headers->valueAt(index);
+
+ headers->removeItemsAt(index);
+
+ ALOGV("Using special cache config '%s'", cacheConfig->string());
+ }
+
+ if ((index = headers->indexOfKey(
+ String8("x-disconnect-at-highwatermark"))) >= 0) {
+ *disconnectAtHighwatermark = true;
+ headers->removeItemsAt(index);
+
+ ALOGV("Client requested disconnection at highwater mark");
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
new file mode 100644
index 0000000..224ec33
--- /dev/null
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -0,0 +1,482 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "NuMediaExtractor"
+#include <utils/Log.h>
+
+#include <media/stagefright/NuMediaExtractor.h>
+
+#include "include/ESDS.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+NuMediaExtractor::NuMediaExtractor() {
+}
+
+NuMediaExtractor::~NuMediaExtractor() {
+ releaseTrackSamples();
+
+ for (size_t i = 0; i < mSelectedTracks.size(); ++i) {
+ TrackInfo *info = &mSelectedTracks.editItemAt(i);
+
+ CHECK_EQ((status_t)OK, info->mSource->stop());
+ }
+
+ mSelectedTracks.clear();
+}
+
+status_t NuMediaExtractor::setDataSource(const char *path) {
+ sp<DataSource> dataSource = DataSource::CreateFromURI(path);
+
+ if (dataSource == NULL) {
+ return -ENOENT;
+ }
+
+ mImpl = MediaExtractor::Create(dataSource);
+
+ if (mImpl == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ return OK;
+}
+
+size_t NuMediaExtractor::countTracks() const {
+ return mImpl == NULL ? 0 : mImpl->countTracks();
+}
+
+status_t NuMediaExtractor::getTrackFormat(
+ size_t index, sp<AMessage> *format) const {
+ *format = NULL;
+
+ if (mImpl == NULL) {
+ return -EINVAL;
+ }
+
+ if (index >= mImpl->countTracks()) {
+ return -ERANGE;
+ }
+
+ sp<MetaData> meta = mImpl->getTrackMetaData(index);
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ sp<AMessage> msg = new AMessage;
+ msg->setString("mime", mime);
+
+ if (!strncasecmp("video/", mime, 6)) {
+ int32_t width, height;
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+
+ msg->setInt32("width", width);
+ msg->setInt32("height", height);
+ } else {
+ CHECK(!strncasecmp("audio/", mime, 6));
+
+ int32_t numChannels, sampleRate;
+ CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
+ CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+
+ msg->setInt32("channel-count", numChannels);
+ msg->setInt32("sample-rate", sampleRate);
+
+ int32_t isADTS;
+ if (meta->findInt32(kKeyIsADTS, &isADTS)) {
+ msg->setInt32("is-adts", true);
+ }
+ }
+
+ int32_t maxInputSize;
+ if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
+ msg->setInt32("max-input-size", maxInputSize);
+ }
+
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (meta->findData(kKeyAVCC, &type, &data, &size)) {
+ // Parse the AVCDecoderConfigurationRecord
+
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ CHECK(size >= 7);
+ CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1
+ uint8_t profile = ptr[1];
+ uint8_t level = ptr[3];
+
+ // There is decodable content out there that fails the following
+ // assertion, let's be lenient for now...
+ // CHECK((ptr[4] >> 2) == 0x3f); // reserved
+
+ size_t lengthSize = 1 + (ptr[4] & 3);
+
+ // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
+ // violates it...
+ // CHECK((ptr[5] >> 5) == 7); // reserved
+
+ size_t numSeqParameterSets = ptr[5] & 31;
+
+ ptr += 6;
+ size -= 6;
+
+ sp<ABuffer> buffer = new ABuffer(1024);
+ buffer->setRange(0, 0);
+
+ for (size_t i = 0; i < numSeqParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ CHECK(size >= length);
+
+ memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
+ memcpy(buffer->data() + buffer->size() + 4, ptr, length);
+ buffer->setRange(0, buffer->size() + 4 + length);
+
+ ptr += length;
+ size -= length;
+ }
+
+ buffer->meta()->setInt32("csd", true);
+ buffer->meta()->setInt64("timeUs", 0);
+
+ msg->setBuffer("csd-0", buffer);
+
+ buffer = new ABuffer(1024);
+ buffer->setRange(0, 0);
+
+ CHECK(size >= 1);
+ size_t numPictureParameterSets = *ptr;
+ ++ptr;
+ --size;
+
+ for (size_t i = 0; i < numPictureParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ CHECK(size >= length);
+
+ memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
+ memcpy(buffer->data() + buffer->size() + 4, ptr, length);
+ buffer->setRange(0, buffer->size() + 4 + length);
+
+ ptr += length;
+ size -= length;
+ }
+
+ buffer->meta()->setInt32("csd", true);
+ buffer->meta()->setInt64("timeUs", 0);
+ msg->setBuffer("csd-1", buffer);
+ } else if (meta->findData(kKeyESDS, &type, &data, &size)) {
+ ESDS esds((const char *)data, size);
+ CHECK_EQ(esds.InitCheck(), (status_t)OK);
+
+ const void *codec_specific_data;
+ size_t codec_specific_data_size;
+ esds.getCodecSpecificInfo(
+ &codec_specific_data, &codec_specific_data_size);
+
+ sp<ABuffer> buffer = new ABuffer(codec_specific_data_size);
+
+ memcpy(buffer->data(), codec_specific_data,
+ codec_specific_data_size);
+
+ buffer->meta()->setInt32("csd", true);
+ buffer->meta()->setInt64("timeUs", 0);
+ msg->setBuffer("csd-0", buffer);
+ } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
+ sp<ABuffer> buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+
+ buffer->meta()->setInt32("csd", true);
+ buffer->meta()->setInt64("timeUs", 0);
+ msg->setBuffer("csd-0", buffer);
+
+ if (!meta->findData(kKeyVorbisBooks, &type, &data, &size)) {
+ return -EINVAL;
+ }
+
+ buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+
+ buffer->meta()->setInt32("csd", true);
+ buffer->meta()->setInt64("timeUs", 0);
+ msg->setBuffer("csd-1", buffer);
+ }
+
+ if (meta->findData(kKeyEMM, &type, &data, &size)) {
+ sp<ABuffer> emm = new ABuffer(size);
+ memcpy(emm->data(), data, size);
+
+ msg->setBuffer("emm", emm);
+ }
+
+ if (meta->findData(kKeyECM, &type, &data, &size)) {
+ sp<ABuffer> ecm = new ABuffer(size);
+ memcpy(ecm->data(), data, size);
+
+ msg->setBuffer("ecm", ecm);
+ }
+
+ *format = msg;
+
+ return OK;
+}
+
+status_t NuMediaExtractor::selectTrack(size_t index) {
+ if (mImpl == NULL) {
+ return -EINVAL;
+ }
+
+ if (index >= mImpl->countTracks()) {
+ return -ERANGE;
+ }
+
+ for (size_t i = 0; i < mSelectedTracks.size(); ++i) {
+ TrackInfo *info = &mSelectedTracks.editItemAt(i);
+
+ if (info->mTrackIndex == index) {
+ // This track has already been selected.
+ return OK;
+ }
+ }
+
+ sp<MediaSource> source = mImpl->getTrack(index);
+
+ CHECK_EQ((status_t)OK, source->start());
+
+ mSelectedTracks.push();
+ TrackInfo *info = &mSelectedTracks.editItemAt(mSelectedTracks.size() - 1);
+
+ info->mSource = source;
+ info->mTrackIndex = index;
+ info->mFinalResult = OK;
+ info->mSample = NULL;
+ info->mSampleTimeUs = -1ll;
+ info->mSampleFlags = 0;
+ info->mTrackFlags = 0;
+
+ const char *mime;
+ CHECK(source->getFormat()->findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
+ info->mTrackFlags |= kIsVorbis;
+ }
+
+ return OK;
+}
+
+void NuMediaExtractor::releaseTrackSamples() {
+ for (size_t i = 0; i < mSelectedTracks.size(); ++i) {
+ TrackInfo *info = &mSelectedTracks.editItemAt(i);
+
+ if (info->mSample != NULL) {
+ info->mSample->release();
+ info->mSample = NULL;
+
+ info->mSampleTimeUs = -1ll;
+ info->mSampleFlags = 0;
+ }
+ }
+}
+
+ssize_t NuMediaExtractor::fetchTrackSamples(int64_t seekTimeUs) {
+ TrackInfo *minInfo = NULL;
+ ssize_t minIndex = -1;
+
+ for (size_t i = 0; i < mSelectedTracks.size(); ++i) {
+ TrackInfo *info = &mSelectedTracks.editItemAt(i);
+
+ if (seekTimeUs >= 0ll) {
+ info->mFinalResult = OK;
+
+ if (info->mSample != NULL) {
+ info->mSample->release();
+ info->mSample = NULL;
+ info->mSampleTimeUs = -1ll;
+ info->mSampleFlags = 0;
+ }
+ } else if (info->mFinalResult != OK) {
+ continue;
+ }
+
+ if (info->mSample == NULL) {
+ MediaSource::ReadOptions options;
+ if (seekTimeUs >= 0ll) {
+ options.setSeekTo(seekTimeUs);
+ }
+ status_t err = info->mSource->read(&info->mSample, &options);
+
+ if (err != OK) {
+ CHECK(info->mSample == NULL);
+
+ info->mFinalResult = err;
+ info->mSampleTimeUs = -1ll;
+ info->mSampleFlags = 0;
+ continue;
+ } else {
+ CHECK(info->mSample != NULL);
+ CHECK(info->mSample->meta_data()->findInt64(
+ kKeyTime, &info->mSampleTimeUs));
+
+ info->mSampleFlags = 0;
+
+ int32_t val;
+ if (info->mSample->meta_data()->findInt32(
+ kKeyIsSyncFrame, &val) && val != 0) {
+ info->mSampleFlags |= SAMPLE_FLAG_SYNC;
+ }
+
+ if (info->mSample->meta_data()->findInt32(
+ kKeyScrambling, &val) && val != 0) {
+ info->mSampleFlags |= SAMPLE_FLAG_ENCRYPTED;
+ }
+ }
+ }
+
+ if (minInfo == NULL || info->mSampleTimeUs < minInfo->mSampleTimeUs) {
+ minInfo = info;
+ minIndex = i;
+ }
+ }
+
+ return minIndex;
+}
+
+status_t NuMediaExtractor::seekTo(int64_t timeUs) {
+ return fetchTrackSamples(timeUs);
+}
+
+status_t NuMediaExtractor::advance() {
+ ssize_t minIndex = fetchTrackSamples();
+
+ if (minIndex < 0) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ TrackInfo *info = &mSelectedTracks.editItemAt(minIndex);
+
+ info->mSample->release();
+ info->mSample = NULL;
+ info->mSampleTimeUs = -1ll;
+
+ return OK;
+}
+
+status_t NuMediaExtractor::readSampleData(const sp<ABuffer> &buffer) {
+ ssize_t minIndex = fetchTrackSamples();
+
+ if (minIndex < 0) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ TrackInfo *info = &mSelectedTracks.editItemAt(minIndex);
+
+ size_t sampleSize = info->mSample->range_length();
+
+ if (info->mTrackFlags & kIsVorbis) {
+ // Each sample's data is suffixed by the number of page samples
+ // or -1 if not available.
+ sampleSize += sizeof(int32_t);
+ }
+
+ if (buffer->capacity() < sampleSize) {
+ return -ENOMEM;
+ }
+
+ const uint8_t *src =
+ (const uint8_t *)info->mSample->data()
+ + info->mSample->range_offset();
+
+ memcpy((uint8_t *)buffer->data(), src, info->mSample->range_length());
+
+ if (info->mTrackFlags & kIsVorbis) {
+ int32_t numPageSamples;
+ if (!info->mSample->meta_data()->findInt32(
+ kKeyValidSamples, &numPageSamples)) {
+ numPageSamples = -1;
+ }
+
+ memcpy((uint8_t *)buffer->data() + info->mSample->range_length(),
+ &numPageSamples,
+ sizeof(numPageSamples));
+ }
+
+ buffer->setRange(0, sampleSize);
+
+ return OK;
+}
+
+status_t NuMediaExtractor::getSampleTrackIndex(size_t *trackIndex) {
+ ssize_t minIndex = fetchTrackSamples();
+
+ if (minIndex < 0) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ TrackInfo *info = &mSelectedTracks.editItemAt(minIndex);
+ *trackIndex = info->mTrackIndex;
+
+ return OK;
+}
+
+status_t NuMediaExtractor::getSampleTime(int64_t *sampleTimeUs) {
+ ssize_t minIndex = fetchTrackSamples();
+
+ if (minIndex < 0) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ TrackInfo *info = &mSelectedTracks.editItemAt(minIndex);
+ *sampleTimeUs = info->mSampleTimeUs;
+
+ return OK;
+}
+
+status_t NuMediaExtractor::getSampleFlags(uint32_t *sampleFlags) {
+ ssize_t minIndex = fetchTrackSamples();
+
+ if (minIndex < 0) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ TrackInfo *info = &mSelectedTracks.editItemAt(minIndex);
+ *sampleFlags = info->mSampleFlags;
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
new file mode 100644
index 0000000..7cdb793
--- /dev/null
+++ b/media/libstagefright/OMXClient.cpp
@@ -0,0 +1,344 @@
+/*
+ * 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 "OMXClient"
+#include <utils/Log.h>
+
+#include <binder/IServiceManager.h>
+#include <media/IMediaPlayerService.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/OMXClient.h>
+#include <utils/KeyedVector.h>
+
+#include "include/OMX.h"
+
+namespace android {
+
+struct MuxOMX : public IOMX {
+ MuxOMX(const sp<IOMX> &remoteOMX);
+ virtual ~MuxOMX();
+
+ virtual IBinder *onAsBinder() { return NULL; }
+
+ virtual bool livesLocally(node_id node, pid_t pid);
+
+ virtual status_t listNodes(List<ComponentInfo> *list);
+
+ virtual status_t allocateNode(
+ const char *name, const sp<IOMXObserver> &observer,
+ node_id *node);
+
+ virtual status_t freeNode(node_id node);
+
+ virtual status_t sendCommand(
+ node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param);
+
+ virtual status_t getParameter(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size);
+
+ virtual status_t setParameter(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size);
+
+ virtual status_t getConfig(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size);
+
+ virtual status_t setConfig(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size);
+
+ virtual status_t getState(
+ node_id node, OMX_STATETYPE* state);
+
+ virtual status_t storeMetaDataInBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable);
+
+ virtual status_t enableGraphicBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable);
+
+ virtual status_t getGraphicBufferUsage(
+ node_id node, OMX_U32 port_index, OMX_U32* usage);
+
+ virtual status_t useBuffer(
+ node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+ buffer_id *buffer);
+
+ virtual status_t useGraphicBuffer(
+ node_id node, OMX_U32 port_index,
+ const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer);
+
+ virtual status_t allocateBuffer(
+ node_id node, OMX_U32 port_index, size_t size,
+ buffer_id *buffer, void **buffer_data);
+
+ virtual status_t allocateBufferWithBackup(
+ node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+ buffer_id *buffer);
+
+ virtual status_t freeBuffer(
+ node_id node, OMX_U32 port_index, buffer_id buffer);
+
+ virtual status_t fillBuffer(node_id node, buffer_id buffer);
+
+ virtual status_t emptyBuffer(
+ node_id node,
+ buffer_id buffer,
+ OMX_U32 range_offset, OMX_U32 range_length,
+ OMX_U32 flags, OMX_TICKS timestamp);
+
+ virtual status_t getExtensionIndex(
+ node_id node,
+ const char *parameter_name,
+ OMX_INDEXTYPE *index);
+
+private:
+ mutable Mutex mLock;
+
+ sp<IOMX> mRemoteOMX;
+ sp<IOMX> mLocalOMX;
+
+ KeyedVector<node_id, bool> mIsLocalNode;
+
+ bool isLocalNode(node_id node) const;
+ bool isLocalNode_l(node_id node) const;
+ const sp<IOMX> &getOMX(node_id node) const;
+ const sp<IOMX> &getOMX_l(node_id node) const;
+
+ static bool IsSoftwareComponent(const char *name);
+
+ DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
+};
+
+MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
+ : mRemoteOMX(remoteOMX) {
+}
+
+MuxOMX::~MuxOMX() {
+}
+
+bool MuxOMX::isLocalNode(node_id node) const {
+ Mutex::Autolock autoLock(mLock);
+
+ return isLocalNode_l(node);
+}
+
+bool MuxOMX::isLocalNode_l(node_id node) const {
+ return mIsLocalNode.indexOfKey(node) >= 0;
+}
+
+// static
+bool MuxOMX::IsSoftwareComponent(const char *name) {
+ return !strncasecmp(name, "OMX.google.", 11);
+}
+
+const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
+ return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
+}
+
+const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
+ return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
+}
+
+bool MuxOMX::livesLocally(node_id node, pid_t pid) {
+ return getOMX(node)->livesLocally(node, pid);
+}
+
+status_t MuxOMX::listNodes(List<ComponentInfo> *list) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mLocalOMX == NULL) {
+ mLocalOMX = new OMX;
+ }
+
+ return mLocalOMX->listNodes(list);
+}
+
+status_t MuxOMX::allocateNode(
+ const char *name, const sp<IOMXObserver> &observer,
+ node_id *node) {
+ Mutex::Autolock autoLock(mLock);
+
+ sp<IOMX> omx;
+
+ if (IsSoftwareComponent(name)) {
+ if (mLocalOMX == NULL) {
+ mLocalOMX = new OMX;
+ }
+ omx = mLocalOMX;
+ } else {
+ omx = mRemoteOMX;
+ }
+
+ status_t err = omx->allocateNode(name, observer, node);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (omx == mLocalOMX) {
+ mIsLocalNode.add(*node, true);
+ }
+
+ return OK;
+}
+
+status_t MuxOMX::freeNode(node_id node) {
+ Mutex::Autolock autoLock(mLock);
+
+ status_t err = getOMX_l(node)->freeNode(node);
+
+ if (err != OK) {
+ return err;
+ }
+
+ mIsLocalNode.removeItem(node);
+
+ return OK;
+}
+
+status_t MuxOMX::sendCommand(
+ node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
+ return getOMX(node)->sendCommand(node, cmd, param);
+}
+
+status_t MuxOMX::getParameter(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size) {
+ return getOMX(node)->getParameter(node, index, params, size);
+}
+
+status_t MuxOMX::setParameter(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size) {
+ return getOMX(node)->setParameter(node, index, params, size);
+}
+
+status_t MuxOMX::getConfig(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size) {
+ return getOMX(node)->getConfig(node, index, params, size);
+}
+
+status_t MuxOMX::setConfig(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size) {
+ return getOMX(node)->setConfig(node, index, params, size);
+}
+
+status_t MuxOMX::getState(
+ node_id node, OMX_STATETYPE* state) {
+ return getOMX(node)->getState(node, state);
+}
+
+status_t MuxOMX::storeMetaDataInBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+ return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable);
+}
+
+status_t MuxOMX::enableGraphicBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+ return getOMX(node)->enableGraphicBuffers(node, port_index, enable);
+}
+
+status_t MuxOMX::getGraphicBufferUsage(
+ node_id node, OMX_U32 port_index, OMX_U32* usage) {
+ return getOMX(node)->getGraphicBufferUsage(node, port_index, usage);
+}
+
+status_t MuxOMX::useBuffer(
+ node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+ buffer_id *buffer) {
+ return getOMX(node)->useBuffer(node, port_index, params, buffer);
+}
+
+status_t MuxOMX::useGraphicBuffer(
+ node_id node, OMX_U32 port_index,
+ const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
+ return getOMX(node)->useGraphicBuffer(
+ node, port_index, graphicBuffer, buffer);
+}
+
+status_t MuxOMX::allocateBuffer(
+ node_id node, OMX_U32 port_index, size_t size,
+ buffer_id *buffer, void **buffer_data) {
+ return getOMX(node)->allocateBuffer(
+ node, port_index, size, buffer, buffer_data);
+}
+
+status_t MuxOMX::allocateBufferWithBackup(
+ node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+ buffer_id *buffer) {
+ return getOMX(node)->allocateBufferWithBackup(
+ node, port_index, params, buffer);
+}
+
+status_t MuxOMX::freeBuffer(
+ node_id node, OMX_U32 port_index, buffer_id buffer) {
+ return getOMX(node)->freeBuffer(node, port_index, buffer);
+}
+
+status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer) {
+ return getOMX(node)->fillBuffer(node, buffer);
+}
+
+status_t MuxOMX::emptyBuffer(
+ node_id node,
+ buffer_id buffer,
+ OMX_U32 range_offset, OMX_U32 range_length,
+ OMX_U32 flags, OMX_TICKS timestamp) {
+ return getOMX(node)->emptyBuffer(
+ node, buffer, range_offset, range_length, flags, timestamp);
+}
+
+status_t MuxOMX::getExtensionIndex(
+ node_id node,
+ const char *parameter_name,
+ OMX_INDEXTYPE *index) {
+ return getOMX(node)->getExtensionIndex(node, parameter_name, index);
+}
+
+OMXClient::OMXClient() {
+}
+
+status_t OMXClient::connect() {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.player"));
+ sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+
+ CHECK(service.get() != NULL);
+
+ mOMX = service->getOMX();
+ CHECK(mOMX.get() != NULL);
+
+ if (!mOMX->livesLocally(NULL /* node */, getpid())) {
+ ALOGI("Using client-side OMX mux.");
+ mOMX = new MuxOMX(mOMX);
+ }
+
+ return OK;
+}
+
+void OMXClient::disconnect() {
+ if (mOMX.get() != NULL) {
+ mOMX.clear();
+ mOMX = NULL;
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
new file mode 100755
index 0000000..9769f21
--- /dev/null
+++ b/media/libstagefright/OMXCodec.cpp
@@ -0,0 +1,4582 @@
+/*
+ * 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 "OMXCodec"
+#include <utils/Log.h>
+
+#include "include/AACEncoder.h"
+#include "include/AVCEncoder.h"
+#include "include/M4vH263Encoder.h"
+
+#include "include/ESDS.h"
+
+#include <binder/IServiceManager.h>
+#include <binder/MemoryDealer.h>
+#include <binder/ProcessState.h>
+#include <HardwareAPI.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/IMediaPlayerService.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/Utils.h>
+#include <media/stagefright/SkipCutBuffer.h>
+#include <utils/Vector.h>
+
+#include <OMX_Audio.h>
+#include <OMX_Component.h>
+
+#include "include/avc_utils.h"
+
+namespace android {
+
+// Treat time out as an error if we have not received any output
+// buffers after 3 seconds.
+const static int64_t kBufferFilledEventTimeOutNs = 3000000000LL;
+
+// OMX Spec defines less than 50 color formats. If the query for
+// color format is executed for more than kMaxColorFormatSupported,
+// the query will fail to avoid looping forever.
+// 1000 is more than enough for us to tell whether the omx
+// component in question is buggy or not.
+const static uint32_t kMaxColorFormatSupported = 1000;
+
+#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_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(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;
+}
+
+#undef FACTORY_CREATE_ENCODER
+#undef FACTORY_REF
+
+#define CODEC_LOGI(x, ...) ALOGI("[%s] "x, mComponentName, ##__VA_ARGS__)
+#define CODEC_LOGV(x, ...) ALOGV("[%s] "x, mComponentName, ##__VA_ARGS__)
+#define CODEC_LOGE(x, ...) ALOGE("[%s] "x, mComponentName, ##__VA_ARGS__)
+
+struct OMXCodecObserver : public BnOMXObserver {
+ OMXCodecObserver() {
+ }
+
+ void setCodec(const sp<OMXCodec> &target) {
+ mTarget = target;
+ }
+
+ // from IOMXObserver
+ virtual void onMessage(const omx_message &msg) {
+ sp<OMXCodec> codec = mTarget.promote();
+
+ if (codec.get() != NULL) {
+ Mutex::Autolock autoLock(codec->mLock);
+ codec->on_message(msg);
+ codec.clear();
+ }
+ }
+
+protected:
+ virtual ~OMXCodecObserver() {}
+
+private:
+ wp<OMXCodec> mTarget;
+
+ OMXCodecObserver(const OMXCodecObserver &);
+ OMXCodecObserver &operator=(const OMXCodecObserver &);
+};
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+static bool IsSoftwareCodec(const char *componentName) {
+ if (!strncmp("OMX.google.", componentName, 11)) {
+ return true;
+ }
+
+ if (!strncmp("OMX.", componentName, 4)) {
+ return false;
+ }
+
+ return true;
+}
+
+// A sort order in which OMX software codecs are first, followed
+// by other (non-OMX) software codecs, followed by everything else.
+static int CompareSoftwareCodecsFirst(
+ const String8 *elem1, const String8 *elem2) {
+ bool isOMX1 = !strncmp(elem1->string(), "OMX.", 4);
+ bool isOMX2 = !strncmp(elem2->string(), "OMX.", 4);
+
+ bool isSoftwareCodec1 = IsSoftwareCodec(elem1->string());
+ bool isSoftwareCodec2 = IsSoftwareCodec(elem2->string());
+
+ if (isSoftwareCodec1) {
+ if (!isSoftwareCodec2) { return -1; }
+
+ if (isOMX1) {
+ if (isOMX2) { return 0; }
+
+ return -1;
+ } else {
+ if (isOMX2) { return 0; }
+
+ return 1;
+ }
+
+ return -1;
+ }
+
+ if (isSoftwareCodec2) {
+ return 1;
+ }
+
+ return 0;
+}
+
+// static
+void OMXCodec::findMatchingCodecs(
+ const char *mime,
+ bool createEncoder, const char *matchComponentName,
+ uint32_t flags,
+ Vector<String8> *matchingCodecs,
+ Vector<uint32_t> *matchingCodecQuirks) {
+ matchingCodecs->clear();
+
+ if (matchingCodecQuirks) {
+ matchingCodecQuirks->clear();
+ }
+
+ const MediaCodecList *list = MediaCodecList::getInstance();
+ if (list == NULL) {
+ return;
+ }
+
+ size_t index = 0;
+ for (;;) {
+ ssize_t matchIndex =
+ list->findCodecByType(mime, createEncoder, index);
+
+ if (matchIndex < 0) {
+ break;
+ }
+
+ index = matchIndex + 1;
+
+ const char *componentName = list->getCodecName(matchIndex);
+
+ // If a specific codec is requested, skip the non-matching ones.
+ if (matchComponentName && strcmp(componentName, matchComponentName)) {
+ continue;
+ }
+
+ // When requesting software-only codecs, only push software codecs
+ // When requesting hardware-only codecs, only push hardware codecs
+ // When there is request neither for software-only nor for
+ // hardware-only codecs, push all codecs
+ if (((flags & kSoftwareCodecsOnly) && IsSoftwareCodec(componentName)) ||
+ ((flags & kHardwareCodecsOnly) && !IsSoftwareCodec(componentName)) ||
+ (!(flags & (kSoftwareCodecsOnly | kHardwareCodecsOnly)))) {
+
+ matchingCodecs->push(String8(componentName));
+
+ if (matchingCodecQuirks) {
+ matchingCodecQuirks->push(getComponentQuirks(list, matchIndex));
+ }
+ }
+ }
+
+ if (flags & kPreferSoftwareCodecs) {
+ matchingCodecs->sort(CompareSoftwareCodecsFirst);
+ }
+}
+
+// static
+uint32_t OMXCodec::getComponentQuirks(
+ const MediaCodecList *list, size_t index) {
+ uint32_t quirks = 0;
+ if (list->codecHasQuirk(
+ index, "requires-allocate-on-input-ports")) {
+ quirks |= kRequiresAllocateBufferOnInputPorts;
+ }
+ if (list->codecHasQuirk(
+ index, "requires-allocate-on-output-ports")) {
+ quirks |= kRequiresAllocateBufferOnOutputPorts;
+ }
+ if (list->codecHasQuirk(
+ index, "output-buffers-are-unreadable")) {
+ quirks |= kOutputBuffersAreUnreadable;
+ }
+
+ return quirks;
+}
+
+// static
+bool OMXCodec::findCodecQuirks(const char *componentName, uint32_t *quirks) {
+ const MediaCodecList *list = MediaCodecList::getInstance();
+
+ if (list == NULL) {
+ return false;
+ }
+
+ ssize_t index = list->findCodecByName(componentName);
+
+ if (index < 0) {
+ return false;
+ }
+
+ *quirks = getComponentQuirks(list, index);
+
+ return true;
+}
+
+// static
+sp<MediaSource> OMXCodec::Create(
+ const sp<IOMX> &omx,
+ const sp<MetaData> &meta, bool createEncoder,
+ const sp<MediaSource> &source,
+ const char *matchComponentName,
+ uint32_t flags,
+ const sp<ANativeWindow> &nativeWindow) {
+ int32_t requiresSecureBuffers;
+ if (source->getFormat()->findInt32(
+ kKeyRequiresSecureBuffers,
+ &requiresSecureBuffers)
+ && requiresSecureBuffers) {
+ flags |= kIgnoreCodecSpecificData;
+ flags |= kUseSecureInputBuffers;
+ }
+
+ const char *mime;
+ bool success = meta->findCString(kKeyMIMEType, &mime);
+ CHECK(success);
+
+ Vector<String8> matchingCodecs;
+ Vector<uint32_t> matchingCodecQuirks;
+ findMatchingCodecs(
+ mime, createEncoder, matchComponentName, flags,
+ &matchingCodecs, &matchingCodecQuirks);
+
+ if (matchingCodecs.isEmpty()) {
+ return NULL;
+ }
+
+ sp<OMXCodecObserver> observer = new OMXCodecObserver;
+ IOMX::node_id node = 0;
+
+ for (size_t i = 0; i < matchingCodecs.size(); ++i) {
+ const char *componentNameBase = matchingCodecs[i].string();
+ uint32_t quirks = matchingCodecQuirks[i];
+ const char *componentName = componentNameBase;
+
+ AString tmp;
+ if (flags & kUseSecureInputBuffers) {
+ tmp = componentNameBase;
+ tmp.append(".secure");
+
+ componentName = tmp.c_str();
+ }
+
+ if (createEncoder) {
+ sp<MediaSource> softwareCodec =
+ InstantiateSoftwareEncoder(componentName, source, meta);
+
+ if (softwareCodec != NULL) {
+ ALOGV("Successfully allocated software codec '%s'", componentName);
+
+ return softwareCodec;
+ }
+ }
+
+ ALOGV("Attempting to allocate OMX node '%s'", componentName);
+
+ if (!createEncoder
+ && (quirks & kOutputBuffersAreUnreadable)
+ && (flags & kClientNeedsFramebuffer)) {
+ if (strncmp(componentName, "OMX.SEC.", 8)) {
+ // For OMX.SEC.* decoders we can enable a special mode that
+ // gives the client access to the framebuffer contents.
+
+ ALOGW("Component '%s' does not give the client access to "
+ "the framebuffer contents. Skipping.",
+ componentName);
+
+ continue;
+ }
+ }
+
+ status_t err = omx->allocateNode(componentName, observer, &node);
+ if (err == OK) {
+ ALOGV("Successfully allocated OMX node '%s'", componentName);
+
+ sp<OMXCodec> codec = new OMXCodec(
+ omx, node, quirks, flags,
+ createEncoder, mime, componentName,
+ source, nativeWindow);
+
+ observer->setCodec(codec);
+
+ err = codec->configureCodec(meta);
+
+ if (err == OK) {
+ if (!strcmp("OMX.Nvidia.mpeg2v.decode", componentName)) {
+ codec->mFlags |= kOnlySubmitOneInputBufferAtOneTime;
+ }
+
+ return codec;
+ }
+
+ ALOGV("Failed to configure codec '%s'", componentName);
+ }
+ }
+
+ return NULL;
+}
+
+status_t OMXCodec::parseAVCCodecSpecificData(
+ const void *data, size_t size,
+ unsigned *profile, unsigned *level) {
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ // verify minimum size and configurationVersion == 1.
+ if (size < 7 || ptr[0] != 1) {
+ return ERROR_MALFORMED;
+ }
+
+ *profile = ptr[1];
+ *level = ptr[3];
+
+ // There is decodable content out there that fails the following
+ // assertion, let's be lenient for now...
+ // CHECK((ptr[4] >> 2) == 0x3f); // reserved
+
+ size_t lengthSize = 1 + (ptr[4] & 3);
+
+ // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
+ // violates it...
+ // CHECK((ptr[5] >> 5) == 7); // reserved
+
+ size_t numSeqParameterSets = ptr[5] & 31;
+
+ ptr += 6;
+ size -= 6;
+
+ for (size_t i = 0; i < numSeqParameterSets; ++i) {
+ if (size < 2) {
+ return ERROR_MALFORMED;
+ }
+
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ if (size < length) {
+ return ERROR_MALFORMED;
+ }
+
+ addCodecSpecificData(ptr, length);
+
+ ptr += length;
+ size -= length;
+ }
+
+ if (size < 1) {
+ return ERROR_MALFORMED;
+ }
+
+ size_t numPictureParameterSets = *ptr;
+ ++ptr;
+ --size;
+
+ for (size_t i = 0; i < numPictureParameterSets; ++i) {
+ if (size < 2) {
+ return ERROR_MALFORMED;
+ }
+
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ if (size < length) {
+ return ERROR_MALFORMED;
+ }
+
+ addCodecSpecificData(ptr, length);
+
+ ptr += length;
+ size -= length;
+ }
+
+ return OK;
+}
+
+status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
+ ALOGV("configureCodec protected=%d",
+ (mFlags & kEnableGrallocUsageProtected) ? 1 : 0);
+
+ if (!(mFlags & kIgnoreCodecSpecificData)) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (meta->findData(kKeyESDS, &type, &data, &size)) {
+ ESDS esds((const char *)data, size);
+ CHECK_EQ(esds.InitCheck(), (status_t)OK);
+
+ const void *codec_specific_data;
+ size_t codec_specific_data_size;
+ esds.getCodecSpecificInfo(
+ &codec_specific_data, &codec_specific_data_size);
+
+ addCodecSpecificData(
+ codec_specific_data, codec_specific_data_size);
+ } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
+ // Parse the AVCDecoderConfigurationRecord
+
+ unsigned profile, level;
+ status_t err;
+ if ((err = parseAVCCodecSpecificData(
+ data, size, &profile, &level)) != OK) {
+ ALOGE("Malformed AVC codec specific data.");
+ return err;
+ }
+
+ CODEC_LOGI(
+ "AVC profile = %u (%s), level = %u",
+ profile, AVCProfileToString(profile), level);
+ } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
+ addCodecSpecificData(data, size);
+
+ CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));
+ addCodecSpecificData(data, size);
+ }
+ }
+
+ int32_t bitRate = 0;
+ if (mIsEncoder) {
+ CHECK(meta->findInt32(kKeyBitRate, &bitRate));
+ }
+ if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mMIME)) {
+ setAMRFormat(false /* isWAMR */, bitRate);
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mMIME)) {
+ setAMRFormat(true /* isWAMR */, bitRate);
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mMIME)) {
+ int32_t numChannels, sampleRate;
+ CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
+ CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+
+ int32_t isADTS;
+ if (!meta->findInt32(kKeyIsADTS, &isADTS)) {
+ isADTS = false;
+ }
+
+ status_t err = setAACFormat(numChannels, sampleRate, bitRate, isADTS);
+ if (err != OK) {
+ CODEC_LOGE("setAACFormat() failed (err = %d)", err);
+ return err;
+ }
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_ALAW, mMIME)
+ || !strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_MLAW, mMIME)) {
+ // These are PCM-like formats with a fixed sample rate but
+ // a variable number of channels.
+
+ int32_t numChannels;
+ CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
+
+ setG711Format(numChannels);
+ }
+
+ if (!strncasecmp(mMIME, "video/", 6)) {
+
+ if (mIsEncoder) {
+ 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);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+ }
+
+ int32_t maxInputSize;
+ if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
+ setMinBufferSize(kPortIndexInput, (OMX_U32)maxInputSize);
+ }
+
+ initOutputFormat(meta);
+
+ if ((mFlags & kClientNeedsFramebuffer)
+ && !strncmp(mComponentName, "OMX.SEC.", 8)) {
+ OMX_INDEXTYPE index;
+
+ status_t err =
+ mOMX->getExtensionIndex(
+ mNode,
+ "OMX.SEC.index.ThumbnailMode",
+ &index);
+
+ if (err != OK) {
+ return err;
+ }
+
+ OMX_BOOL enable = OMX_TRUE;
+ err = mOMX->setConfig(mNode, index, &enable, sizeof(enable));
+
+ if (err != OK) {
+ CODEC_LOGE("setConfig('OMX.SEC.index.ThumbnailMode') "
+ "returned error 0x%08x", err);
+
+ return err;
+ }
+
+ mQuirks &= ~kOutputBuffersAreUnreadable;
+ }
+
+ if (mNativeWindow != NULL
+ && !mIsEncoder
+ && !strncasecmp(mMIME, "video/", 6)
+ && !strncmp(mComponentName, "OMX.", 4)) {
+ status_t err = initNativeWindow();
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = portIndex;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, (status_t)OK);
+
+ if ((portIndex == kPortIndexInput && (mQuirks & kInputBufferSizesAreBogus))
+ || (def.nBufferSize < size)) {
+ def.nBufferSize = size;
+ }
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, (status_t)OK);
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, (status_t)OK);
+
+ // Make sure the setting actually stuck.
+ if (portIndex == kPortIndexInput
+ && (mQuirks & kInputBufferSizesAreBogus)) {
+ CHECK_EQ(def.nBufferSize, size);
+ } else {
+ CHECK(def.nBufferSize >= size);
+ }
+}
+
+status_t OMXCodec::setVideoPortFormatType(
+ OMX_U32 portIndex,
+ OMX_VIDEO_CODINGTYPE compressionFormat,
+ OMX_COLOR_FORMATTYPE colorFormat) {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+ InitOMXParams(&format);
+ format.nPortIndex = portIndex;
+ format.nIndex = 0;
+ bool found = false;
+
+ OMX_U32 index = 0;
+ for (;;) {
+ format.nIndex = index;
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+
+ if (err != OK) {
+ return err;
+ }
+
+ // The following assertion is violated by TI's video decoder.
+ // CHECK_EQ(format.nIndex, index);
+
+#if 1
+ CODEC_LOGV("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d",
+ portIndex,
+ index, format.eCompressionFormat, format.eColorFormat);
+#endif
+
+ if (format.eCompressionFormat == compressionFormat
+ && format.eColorFormat == colorFormat) {
+ found = true;
+ break;
+ }
+
+ ++index;
+ if (index >= kMaxColorFormatSupported) {
+ CODEC_LOGE("color format %d or compression format %d is not supported",
+ colorFormat, compressionFormat);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ if (!found) {
+ return UNKNOWN_ERROR;
+ }
+
+ CODEC_LOGV("found a match.");
+ status_t err = mOMX->setParameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+
+ return err;
+}
+
+static size_t getFrameSize(
+ OMX_COLOR_FORMATTYPE colorFormat, int32_t width, int32_t height) {
+ switch (colorFormat) {
+ case OMX_COLOR_FormatYCbYCr:
+ case OMX_COLOR_FormatCbYCrY:
+ return width * height * 2;
+
+ case OMX_COLOR_FormatYUV420Planar:
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
+ /*
+ * FIXME: For the Opaque color format, the frame size does not
+ * need to be (w*h*3)/2. It just needs to
+ * be larger than certain minimum buffer size. However,
+ * currently, this opaque foramt has been tested only on
+ * YUV420 formats. If that is changed, then we need to revisit
+ * this part in the future
+ */
+ case OMX_COLOR_FormatAndroidOpaque:
+ return (width * height * 3) / 2;
+
+ default:
+ CHECK(!"Should not be here. Unsupported color format.");
+ break;
+ }
+}
+
+status_t OMXCodec::findTargetColorFormat(
+ const sp<MetaData>& meta, OMX_COLOR_FORMATTYPE *colorFormat) {
+ ALOGV("findTargetColorFormat");
+ CHECK(mIsEncoder);
+
+ *colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ int32_t targetColorFormat;
+ if (meta->findInt32(kKeyColorFormat, &targetColorFormat)) {
+ *colorFormat = (OMX_COLOR_FORMATTYPE) targetColorFormat;
+ }
+
+ // Check whether the target color format is supported.
+ return isColorFormatSupported(*colorFormat, kPortIndexInput);
+}
+
+status_t OMXCodec::isColorFormatSupported(
+ OMX_COLOR_FORMATTYPE colorFormat, int portIndex) {
+ ALOGV("isColorFormatSupported: %d", static_cast<int>(colorFormat));
+
+ // Enumerate all the color formats supported by
+ // the omx component to see whether the given
+ // color format is supported.
+ OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
+ InitOMXParams(&portFormat);
+ portFormat.nPortIndex = portIndex;
+ OMX_U32 index = 0;
+ portFormat.nIndex = index;
+ while (true) {
+ if (OMX_ErrorNone != mOMX->getParameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &portFormat, sizeof(portFormat))) {
+ break;
+ }
+ // Make sure that omx component does not overwrite
+ // the incremented index (bug 2897413).
+ CHECK_EQ(index, portFormat.nIndex);
+ if (portFormat.eColorFormat == colorFormat) {
+ CODEC_LOGV("Found supported color format: %d", portFormat.eColorFormat);
+ return OK; // colorFormat is supported!
+ }
+ ++index;
+ portFormat.nIndex = index;
+
+ if (index >= kMaxColorFormatSupported) {
+ CODEC_LOGE("More than %ld color formats are supported???", index);
+ break;
+ }
+ }
+
+ CODEC_LOGE("color format %d is not supported", colorFormat);
+ return UNKNOWN_ERROR;
+}
+
+void OMXCodec::setVideoInputFormat(
+ 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(kKeyFrameRate, &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)) {
+ compressionFormat = OMX_VIDEO_CodingAVC;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
+ compressionFormat = OMX_VIDEO_CodingMPEG4;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
+ compressionFormat = OMX_VIDEO_CodingH263;
+ } else {
+ ALOGE("Not a supported video mime type: %s", mime);
+ CHECK(!"Should not be here. Not a supported video mime type.");
+ }
+
+ OMX_COLOR_FORMATTYPE colorFormat;
+ CHECK_EQ((status_t)OK, findTargetColorFormat(meta, &colorFormat));
+
+ 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), (status_t)OK);
+
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexInput;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, (status_t)OK);
+
+ def.nBufferSize = getFrameSize(colorFormat,
+ stride > 0? stride: -stride, sliceHeight);
+
+ CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
+
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+ 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, (status_t)OK);
+
+ //////////////////////// Output port /////////////////////////
+ CHECK_EQ(setVideoPortFormatType(
+ kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused),
+ (status_t)OK);
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexOutput;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ CHECK_EQ(err, (status_t)OK);
+ CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
+
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+ 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;
+ if (mQuirks & kRequiresLargerEncoderOutputBuffer) {
+ // Increases the output buffer size
+ def.nBufferSize = ((def.nBufferSize * 3) >> 1);
+ }
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, (status_t)OK);
+
+ /////////////////// Codec-specific ////////////////////////
+ switch (compressionFormat) {
+ case OMX_VIDEO_CodingMPEG4:
+ {
+ CHECK_EQ(setupMPEG4EncoderParameters(meta), (status_t)OK);
+ break;
+ }
+
+ case OMX_VIDEO_CodingH263:
+ CHECK_EQ(setupH263EncoderParameters(meta), (status_t)OK);
+ break;
+
+ case OMX_VIDEO_CodingAVC:
+ {
+ CHECK_EQ(setupAVCEncoderParameters(meta), (status_t)OK);
+ break;
+ }
+
+ default:
+ CHECK(!"Support for this compressionFormat to be implemented.");
+ break;
+ }
+}
+
+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_IndexParamVideoErrorCorrection,
+ &errorCorrectionType, sizeof(errorCorrectionType));
+ if (err != OK) {
+ ALOGW("Error correction param query is not supported");
+ return OK; // Optional feature. Ignore this failure
+ }
+
+ errorCorrectionType.bEnableHEC = OMX_FALSE;
+ errorCorrectionType.bEnableResync = OMX_TRUE;
+ errorCorrectionType.nResynchMarkerSpacing = 256;
+ errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
+ errorCorrectionType.bEnableRVLC = OMX_FALSE;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamVideoErrorCorrection,
+ &errorCorrectionType, sizeof(errorCorrectionType));
+ if (err != OK) {
+ ALOGW("Error correction param configuration is not supported");
+ }
+
+ // Optional feature. Ignore the failure.
+ return OK;
+}
+
+status_t OMXCodec::setupBitRate(int32_t bitRate) {
+ OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
+ InitOMXParams(&bitrateType);
+ bitrateType.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoBitrate,
+ &bitrateType, sizeof(bitrateType));
+ CHECK_EQ(err, (status_t)OK);
+
+ bitrateType.eControlRate = OMX_Video_ControlRateVariable;
+ bitrateType.nTargetBitrate = bitRate;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamVideoBitrate,
+ &bitrateType, sizeof(bitrateType));
+ CHECK_EQ(err, (status_t)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);
+
+ // 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);
+
+ // 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) break;
+
+ 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) {
+ // We can further check whether the level is a valid
+ // value; but we will leave that to the omx encoder component
+ // via OMX_SetParameter call.
+ 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(kKeyFrameRate, &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, (status_t)OK);
+
+ 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 = h263type.eProfile;
+ defaultProfileLevel.mLevel = h263type.eLevel;
+ 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_IndexParamVideoH263, &h263type, sizeof(h263type));
+ CHECK_EQ(err, (status_t)OK);
+
+ CHECK_EQ(setupBitRate(bitRate), (status_t)OK);
+ CHECK_EQ(setupErrorCorrectionParameters(), (status_t)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(kKeyFrameRate, &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, (status_t)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 = mpeg4type.eProfile;
+ defaultProfileLevel.mLevel = mpeg4type.eLevel;
+ 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, (status_t)OK);
+
+ CHECK_EQ(setupBitRate(bitRate), (status_t)OK);
+ CHECK_EQ(setupErrorCorrectionParameters(), (status_t)OK);
+
+ return OK;
+}
+
+status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
+ int32_t iFramesInterval, frameRate, bitRate;
+ bool success = meta->findInt32(kKeyBitRate, &bitRate);
+ success = success && meta->findInt32(kKeyFrameRate, &frameRate);
+ success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
+ CHECK(success);
+
+ OMX_VIDEO_PARAM_AVCTYPE h264type;
+ InitOMXParams(&h264type);
+ h264type.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
+ CHECK_EQ(err, (status_t)OK);
+
+ h264type.nAllowedPictureTypes =
+ OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
+
+ // 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);
+
+ // FIXME:
+ // Remove the workaround after the work in done.
+ if (!strncmp(mComponentName, "OMX.TI.DUCATI1", 14)) {
+ h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
+ }
+
+ if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
+ h264type.nSliceHeaderSpacing = 0;
+ h264type.bUseHadamard = OMX_TRUE;
+ h264type.nRefFrames = 1;
+ h264type.nBFrames = 0;
+ h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+ if (h264type.nPFrames == 0) {
+ h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+ }
+ 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.bFrameMBsOnly = OMX_TRUE;
+ h264type.bMBAFF = OMX_FALSE;
+ h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
+
+ if (!strcasecmp("OMX.Nvidia.h264.encoder", mComponentName)) {
+ h264type.eLevel = OMX_VIDEO_AVCLevelMax;
+ }
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
+ CHECK_EQ(err, (status_t)OK);
+
+ CHECK_EQ(setupBitRate(bitRate), (status_t)OK);
+
+ return OK;
+}
+
+status_t OMXCodec::setVideoOutputFormat(
+ const char *mime, OMX_U32 width, OMX_U32 height) {
+ CODEC_LOGV("setVideoOutputFormat width=%ld, height=%ld", width, height);
+
+ OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
+ if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
+ compressionFormat = OMX_VIDEO_CodingAVC;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
+ compressionFormat = OMX_VIDEO_CodingMPEG4;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
+ compressionFormat = OMX_VIDEO_CodingH263;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_VPX, mime)) {
+ compressionFormat = OMX_VIDEO_CodingVPX;
+ } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG2, mime)) {
+ compressionFormat = OMX_VIDEO_CodingMPEG2;
+ } else {
+ ALOGE("Not a supported video mime type: %s", mime);
+ CHECK(!"Should not be here. Not a supported video mime type.");
+ }
+
+ status_t err = setVideoPortFormatType(
+ kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
+
+ if (err != OK) {
+ return err;
+ }
+
+#if 1
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+ InitOMXParams(&format);
+ format.nPortIndex = kPortIndexOutput;
+ format.nIndex = 0;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+ CHECK_EQ(err, (status_t)OK);
+ CHECK_EQ((int)format.eCompressionFormat, (int)OMX_VIDEO_CodingUnused);
+
+ CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
+ || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
+ || format.eColorFormat == OMX_COLOR_FormatCbYCrY
+ || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
+ || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+
+ if (err != OK) {
+ return err;
+ }
+ }
+#endif
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexInput;
+
+ OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ CHECK_EQ(err, (status_t)OK);
+
+#if 1
+ // XXX Need a (much) better heuristic to compute input buffer sizes.
+ const size_t X = 64 * 1024;
+ if (def.nBufferSize < X) {
+ def.nBufferSize = X;
+ }
+#endif
+
+ CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
+
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+
+ video_def->eCompressionFormat = compressionFormat;
+ video_def->eColorFormat = OMX_COLOR_FormatUnused;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexOutput;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, (status_t)OK);
+ CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
+
+#if 0
+ def.nBufferSize =
+ (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420
+#endif
+
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ return err;
+}
+
+OMXCodec::OMXCodec(
+ const sp<IOMX> &omx, IOMX::node_id node,
+ uint32_t quirks, uint32_t flags,
+ bool isEncoder,
+ const char *mime,
+ const char *componentName,
+ const sp<MediaSource> &source,
+ const sp<ANativeWindow> &nativeWindow)
+ : mOMX(omx),
+ mOMXLivesLocally(omx->livesLocally(node, getpid())),
+ mNode(node),
+ mQuirks(quirks),
+ mFlags(flags),
+ mIsEncoder(isEncoder),
+ mIsVideo(!strncasecmp("video/", mime, 6)),
+ mMIME(strdup(mime)),
+ mComponentName(strdup(componentName)),
+ mSource(source),
+ mCodecSpecificDataIndex(0),
+ mState(LOADED),
+ mInitialBufferSubmit(true),
+ mSignalledEOS(false),
+ mNoMoreOutputData(false),
+ mOutputPortSettingsHaveChanged(false),
+ mSeekTimeUs(-1),
+ mSeekMode(ReadOptions::SEEK_CLOSEST_SYNC),
+ mTargetTimeUs(-1),
+ mOutputPortSettingsChangedPending(false),
+ mSkipCutBuffer(NULL),
+ mLeftOverBuffer(NULL),
+ mPaused(false),
+ mNativeWindow(
+ (!strncmp(componentName, "OMX.google.", 11)
+ || !strcmp(componentName, "OMX.Nvidia.mpeg2v.decode"))
+ ? NULL : nativeWindow) {
+ mPortStatus[kPortIndexInput] = ENABLED;
+ mPortStatus[kPortIndexOutput] = ENABLED;
+
+ setComponentRole();
+}
+
+// static
+void OMXCodec::setComponentRole(
+ const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder,
+ const char *mime) {
+ struct MimeToRole {
+ const char *mime;
+ const char *decoderRole;
+ const char *encoderRole;
+ };
+
+ static const MimeToRole kMimeToRole[] = {
+ { MEDIA_MIMETYPE_AUDIO_MPEG,
+ "audio_decoder.mp3", "audio_encoder.mp3" },
+ { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I,
+ "audio_decoder.mp1", "audio_encoder.mp1" },
+ { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
+ "audio_decoder.mp2", "audio_encoder.mp2" },
+ { MEDIA_MIMETYPE_AUDIO_AMR_NB,
+ "audio_decoder.amrnb", "audio_encoder.amrnb" },
+ { MEDIA_MIMETYPE_AUDIO_AMR_WB,
+ "audio_decoder.amrwb", "audio_encoder.amrwb" },
+ { MEDIA_MIMETYPE_AUDIO_AAC,
+ "audio_decoder.aac", "audio_encoder.aac" },
+ { MEDIA_MIMETYPE_AUDIO_VORBIS,
+ "audio_decoder.vorbis", "audio_encoder.vorbis" },
+ { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
+ "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
+ { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
+ "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
+ { MEDIA_MIMETYPE_VIDEO_AVC,
+ "video_decoder.avc", "video_encoder.avc" },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4,
+ "video_decoder.mpeg4", "video_encoder.mpeg4" },
+ { MEDIA_MIMETYPE_VIDEO_H263,
+ "video_decoder.h263", "video_encoder.h263" },
+ { MEDIA_MIMETYPE_VIDEO_VPX,
+ "video_decoder.vpx", "video_encoder.vpx" },
+ };
+
+ static const size_t kNumMimeToRole =
+ sizeof(kMimeToRole) / sizeof(kMimeToRole[0]);
+
+ size_t i;
+ for (i = 0; i < kNumMimeToRole; ++i) {
+ if (!strcasecmp(mime, kMimeToRole[i].mime)) {
+ break;
+ }
+ }
+
+ if (i == kNumMimeToRole) {
+ return;
+ }
+
+ const char *role =
+ isEncoder ? kMimeToRole[i].encoderRole
+ : kMimeToRole[i].decoderRole;
+
+ if (role != NULL) {
+ OMX_PARAM_COMPONENTROLETYPE roleParams;
+ InitOMXParams(&roleParams);
+
+ strncpy((char *)roleParams.cRole,
+ role, OMX_MAX_STRINGNAME_SIZE - 1);
+
+ roleParams.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
+
+ status_t err = omx->setParameter(
+ node, OMX_IndexParamStandardComponentRole,
+ &roleParams, sizeof(roleParams));
+
+ if (err != OK) {
+ ALOGW("Failed to set standard component role '%s'.", role);
+ }
+ }
+}
+
+void OMXCodec::setComponentRole() {
+ setComponentRole(mOMX, mNode, mIsEncoder, mMIME);
+}
+
+OMXCodec::~OMXCodec() {
+ mSource.clear();
+
+ CHECK(mState == LOADED || mState == ERROR || mState == LOADED_TO_IDLE);
+
+ status_t err = mOMX->freeNode(mNode);
+ CHECK_EQ(err, (status_t)OK);
+
+ mNode = NULL;
+ setState(DEAD);
+
+ clearCodecSpecificData();
+
+ free(mComponentName);
+ mComponentName = NULL;
+
+ free(mMIME);
+ mMIME = NULL;
+
+ delete mSkipCutBuffer;
+ mSkipCutBuffer = NULL;
+}
+
+status_t OMXCodec::init() {
+ // mLock is held.
+
+ CHECK_EQ((int)mState, (int)LOADED);
+
+ status_t err;
+ if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
+ err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
+ CHECK_EQ(err, (status_t)OK);
+ setState(LOADED_TO_IDLE);
+ }
+
+ err = allocateBuffers();
+ if (err != (status_t)OK) {
+ return err;
+ }
+
+ if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
+ err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
+ CHECK_EQ(err, (status_t)OK);
+
+ setState(LOADED_TO_IDLE);
+ }
+
+ while (mState != EXECUTING && mState != ERROR) {
+ mAsyncCompletion.wait(mLock);
+ }
+
+ return mState == ERROR ? UNKNOWN_ERROR : OK;
+}
+
+// static
+bool OMXCodec::isIntermediateState(State state) {
+ return state == LOADED_TO_IDLE
+ || state == IDLE_TO_EXECUTING
+ || state == EXECUTING_TO_IDLE
+ || state == IDLE_TO_LOADED
+ || state == RECONFIGURING;
+}
+
+status_t OMXCodec::allocateBuffers() {
+ status_t err = allocateBuffersOnPort(kPortIndexInput);
+
+ if (err != OK) {
+ return err;
+ }
+
+ return allocateBuffersOnPort(kPortIndexOutput);
+}
+
+status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
+ if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
+ return allocateOutputBuffersFromNativeWindow();
+ }
+
+ if ((mFlags & kEnableGrallocUsageProtected) && portIndex == kPortIndexOutput) {
+ ALOGE("protected output buffers must be stent to an ANativeWindow");
+ return PERMISSION_DENIED;
+ }
+
+ status_t err = OK;
+ if ((mFlags & kStoreMetaDataInVideoBuffers)
+ && portIndex == kPortIndexInput) {
+ err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
+ if (err != OK) {
+ ALOGE("Storing meta data in video buffers is not supported");
+ return err;
+ }
+ }
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = portIndex;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ CODEC_LOGV("allocating %lu buffers of size %lu on %s port",
+ def.nBufferCountActual, def.nBufferSize,
+ portIndex == kPortIndexInput ? "input" : "output");
+
+ size_t totalSize = def.nBufferCountActual * def.nBufferSize;
+ mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
+
+ for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
+ sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
+ CHECK(mem.get() != NULL);
+
+ BufferInfo info;
+ info.mData = NULL;
+ info.mSize = def.nBufferSize;
+
+ IOMX::buffer_id buffer;
+ if (portIndex == kPortIndexInput
+ && ((mQuirks & kRequiresAllocateBufferOnInputPorts)
+ || (mFlags & kUseSecureInputBuffers))) {
+ if (mOMXLivesLocally) {
+ mem.clear();
+
+ err = mOMX->allocateBuffer(
+ mNode, portIndex, def.nBufferSize, &buffer,
+ &info.mData);
+ } else {
+ err = mOMX->allocateBufferWithBackup(
+ mNode, portIndex, mem, &buffer);
+ }
+ } else if (portIndex == kPortIndexOutput
+ && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
+ if (mOMXLivesLocally) {
+ mem.clear();
+
+ err = mOMX->allocateBuffer(
+ mNode, portIndex, def.nBufferSize, &buffer,
+ &info.mData);
+ } else {
+ err = mOMX->allocateBufferWithBackup(
+ mNode, portIndex, mem, &buffer);
+ }
+ } else {
+ err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
+ }
+
+ if (err != OK) {
+ ALOGE("allocate_buffer_with_backup failed");
+ return err;
+ }
+
+ if (mem != NULL) {
+ info.mData = mem->pointer();
+ }
+
+ info.mBuffer = buffer;
+ info.mStatus = OWNED_BY_US;
+ info.mMem = mem;
+ info.mMediaBuffer = NULL;
+
+ if (portIndex == kPortIndexOutput) {
+ if (!(mOMXLivesLocally
+ && (mQuirks & kRequiresAllocateBufferOnOutputPorts)
+ && (mQuirks & kDefersOutputBufferAllocation))) {
+ // If the node does not fill in the buffer ptr at this time,
+ // we will defer creating the MediaBuffer until receiving
+ // the first FILL_BUFFER_DONE notification instead.
+ info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
+ info.mMediaBuffer->setObserver(this);
+ }
+ }
+
+ mPortBuffers[portIndex].push(info);
+
+ CODEC_LOGV("allocated buffer %p on %s port", buffer,
+ portIndex == kPortIndexInput ? "input" : "output");
+ }
+
+ if (portIndex == kPortIndexOutput) {
+
+ sp<MetaData> meta = mSource->getFormat();
+ int32_t delay = 0;
+ if (!meta->findInt32(kKeyEncoderDelay, &delay)) {
+ delay = 0;
+ }
+ int32_t padding = 0;
+ if (!meta->findInt32(kKeyEncoderPadding, &padding)) {
+ padding = 0;
+ }
+ int32_t numchannels = 0;
+ if (delay + padding) {
+ if (meta->findInt32(kKeyChannelCount, &numchannels)) {
+ size_t frameSize = numchannels * sizeof(int16_t);
+ if (mSkipCutBuffer) {
+ size_t prevbuffersize = mSkipCutBuffer->size();
+ if (prevbuffersize != 0) {
+ ALOGW("Replacing SkipCutBuffer holding %d bytes", prevbuffersize);
+ }
+ delete mSkipCutBuffer;
+ }
+ mSkipCutBuffer = new SkipCutBuffer(delay * frameSize, padding * frameSize,
+ def.nBufferSize);
+ }
+ }
+ }
+
+ // dumpPortStatus(portIndex);
+
+ if (portIndex == kPortIndexInput && (mFlags & kUseSecureInputBuffers)) {
+ Vector<MediaBuffer *> buffers;
+ for (size_t i = 0; i < def.nBufferCountActual; ++i) {
+ const BufferInfo &info = mPortBuffers[kPortIndexInput].itemAt(i);
+
+ MediaBuffer *mbuf = new MediaBuffer(info.mData, info.mSize);
+ buffers.push(mbuf);
+ }
+
+ status_t err = mSource->setBuffers(buffers);
+
+ if (err != OK) {
+ for (size_t i = 0; i < def.nBufferCountActual; ++i) {
+ buffers.editItemAt(i)->release();
+ }
+ buffers.clear();
+
+ CODEC_LOGE(
+ "Codec requested to use secure input buffers but "
+ "upstream source didn't support that.");
+
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+status_t OMXCodec::applyRotation() {
+ sp<MetaData> meta = mSource->getFormat();
+
+ int32_t rotationDegrees;
+ if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
+ rotationDegrees = 0;
+ }
+
+ uint32_t transform;
+ switch (rotationDegrees) {
+ case 0: transform = 0; break;
+ case 90: transform = HAL_TRANSFORM_ROT_90; break;
+ case 180: transform = HAL_TRANSFORM_ROT_180; break;
+ case 270: transform = HAL_TRANSFORM_ROT_270; break;
+ default: transform = 0; break;
+ }
+
+ status_t err = OK;
+
+ if (transform) {
+ err = native_window_set_buffers_transform(
+ mNativeWindow.get(), transform);
+ }
+
+ return err;
+}
+
+status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
+ // Get the number of buffers needed.
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ if (err != OK) {
+ return err;
+ }
+
+ err = native_window_set_scaling_mode(mNativeWindow.get(),
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = native_window_set_buffers_geometry(
+ mNativeWindow.get(),
+ def.format.video.nFrameWidth,
+ def.format.video.nFrameHeight,
+ def.format.video.eColorFormat);
+
+ if (err != 0) {
+ ALOGE("native_window_set_buffers_geometry failed: %s (%d)",
+ strerror(-err), -err);
+ return err;
+ }
+
+ err = applyRotation();
+ if (err != OK) {
+ return err;
+ }
+
+ // Set up the native window.
+ OMX_U32 usage = 0;
+ err = mOMX->getGraphicBufferUsage(mNode, kPortIndexOutput, &usage);
+ if (err != 0) {
+ ALOGW("querying usage flags from OMX IL component failed: %d", err);
+ // XXX: Currently this error is logged, but not fatal.
+ usage = 0;
+ }
+ if (mFlags & kEnableGrallocUsageProtected) {
+ usage |= GRALLOC_USAGE_PROTECTED;
+ }
+
+ // Make sure to check whether either Stagefright or the video decoder
+ // requested protected buffers.
+ if (usage & GRALLOC_USAGE_PROTECTED) {
+ // Verify that the ANativeWindow sends images directly to
+ // SurfaceFlinger.
+ int queuesToNativeWindow = 0;
+ err = mNativeWindow->query(
+ mNativeWindow.get(), NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER,
+ &queuesToNativeWindow);
+ if (err != 0) {
+ ALOGE("error authenticating native window: %d", err);
+ return err;
+ }
+ if (queuesToNativeWindow != 1) {
+ ALOGE("native window could not be authenticated");
+ return PERMISSION_DENIED;
+ }
+ }
+
+ ALOGV("native_window_set_usage usage=0x%lx", usage);
+ err = native_window_set_usage(
+ mNativeWindow.get(), usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP);
+ if (err != 0) {
+ ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
+ return err;
+ }
+
+ int minUndequeuedBufs = 0;
+ err = mNativeWindow->query(mNativeWindow.get(),
+ NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
+ if (err != 0) {
+ ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d)",
+ strerror(-err), -err);
+ return err;
+ }
+
+ // XXX: Is this the right logic to use? It's not clear to me what the OMX
+ // buffer counts refer to - how do they account for the renderer holding on
+ // to buffers?
+ if (def.nBufferCountActual < def.nBufferCountMin + minUndequeuedBufs) {
+ OMX_U32 newBufferCount = def.nBufferCountMin + minUndequeuedBufs;
+ def.nBufferCountActual = newBufferCount;
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ if (err != OK) {
+ CODEC_LOGE("setting nBufferCountActual to %lu failed: %d",
+ newBufferCount, err);
+ return err;
+ }
+ }
+
+ err = native_window_set_buffer_count(
+ mNativeWindow.get(), def.nBufferCountActual);
+ if (err != 0) {
+ ALOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
+ -err);
+ return err;
+ }
+
+ CODEC_LOGV("allocating %lu buffers from a native window of size %lu on "
+ "output port", def.nBufferCountActual, def.nBufferSize);
+
+ // Dequeue buffers and send them to OMX
+ for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
+ ANativeWindowBuffer* buf;
+ err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
+ if (err != 0) {
+ ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
+ break;
+ }
+
+ sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
+ BufferInfo info;
+ info.mData = NULL;
+ info.mSize = def.nBufferSize;
+ info.mStatus = OWNED_BY_US;
+ info.mMem = NULL;
+ info.mMediaBuffer = new MediaBuffer(graphicBuffer);
+ info.mMediaBuffer->setObserver(this);
+ mPortBuffers[kPortIndexOutput].push(info);
+
+ IOMX::buffer_id bufferId;
+ err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
+ &bufferId);
+ if (err != 0) {
+ CODEC_LOGE("registering GraphicBuffer with OMX IL component "
+ "failed: %d", err);
+ break;
+ }
+
+ mPortBuffers[kPortIndexOutput].editItemAt(i).mBuffer = bufferId;
+
+ CODEC_LOGV("registered graphic buffer with ID %p (pointer = %p)",
+ bufferId, graphicBuffer.get());
+ }
+
+ OMX_U32 cancelStart;
+ OMX_U32 cancelEnd;
+ if (err != 0) {
+ // If an error occurred while dequeuing we need to cancel any buffers
+ // that were dequeued.
+ cancelStart = 0;
+ cancelEnd = mPortBuffers[kPortIndexOutput].size();
+ } else {
+ // Return the last two buffers to the native window.
+ cancelStart = def.nBufferCountActual - minUndequeuedBufs;
+ cancelEnd = def.nBufferCountActual;
+ }
+
+ for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
+ BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(i);
+ cancelBufferToNativeWindow(info);
+ }
+
+ return err;
+}
+
+status_t OMXCodec::cancelBufferToNativeWindow(BufferInfo *info) {
+ CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
+ CODEC_LOGV("Calling cancelBuffer on buffer %p", info->mBuffer);
+ int err = mNativeWindow->cancelBuffer(
+ mNativeWindow.get(), info->mMediaBuffer->graphicBuffer().get());
+ if (err != 0) {
+ CODEC_LOGE("cancelBuffer failed w/ error 0x%08x", err);
+
+ setState(ERROR);
+ return err;
+ }
+ info->mStatus = OWNED_BY_NATIVE_WINDOW;
+ return OK;
+}
+
+OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
+ // Dequeue the next buffer from the native window.
+ ANativeWindowBuffer* buf;
+ int err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
+ if (err != 0) {
+ CODEC_LOGE("dequeueBuffer failed w/ error 0x%08x", err);
+
+ setState(ERROR);
+ return 0;
+ }
+
+ // Determine which buffer we just dequeued.
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
+ BufferInfo *bufInfo = 0;
+ for (size_t i = 0; i < buffers->size(); i++) {
+ sp<GraphicBuffer> graphicBuffer = buffers->itemAt(i).
+ mMediaBuffer->graphicBuffer();
+ if (graphicBuffer->handle == buf->handle) {
+ bufInfo = &buffers->editItemAt(i);
+ break;
+ }
+ }
+
+ if (bufInfo == 0) {
+ CODEC_LOGE("dequeued unrecognized buffer: %p", buf);
+
+ setState(ERROR);
+ return 0;
+ }
+
+ // The native window no longer owns the buffer.
+ CHECK_EQ((int)bufInfo->mStatus, (int)OWNED_BY_NATIVE_WINDOW);
+ bufInfo->mStatus = OWNED_BY_US;
+
+ return bufInfo;
+}
+
+status_t OMXCodec::pushBlankBuffersToNativeWindow() {
+ status_t err = NO_ERROR;
+ ANativeWindowBuffer* anb = NULL;
+ int numBufs = 0;
+ int minUndequeuedBufs = 0;
+
+ // We need to reconnect to the ANativeWindow as a CPU client to ensure that
+ // no frames get dropped by SurfaceFlinger assuming that these are video
+ // frames.
+ err = native_window_api_disconnect(mNativeWindow.get(),
+ NATIVE_WINDOW_API_MEDIA);
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
+ strerror(-err), -err);
+ return err;
+ }
+
+ err = native_window_api_connect(mNativeWindow.get(),
+ NATIVE_WINDOW_API_CPU);
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
+ strerror(-err), -err);
+ return err;
+ }
+
+ err = native_window_set_scaling_mode(mNativeWindow.get(),
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
+ strerror(-err), -err);
+ goto error;
+ }
+
+ err = native_window_set_buffers_geometry(mNativeWindow.get(), 1, 1,
+ HAL_PIXEL_FORMAT_RGBX_8888);
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: set_buffers_geometry failed: %s (%d)",
+ strerror(-err), -err);
+ goto error;
+ }
+
+ err = native_window_set_usage(mNativeWindow.get(),
+ GRALLOC_USAGE_SW_WRITE_OFTEN);
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: set_usage failed: %s (%d)",
+ strerror(-err), -err);
+ goto error;
+ }
+
+ err = mNativeWindow->query(mNativeWindow.get(),
+ NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufs);
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
+ "failed: %s (%d)", strerror(-err), -err);
+ goto error;
+ }
+
+ numBufs = minUndequeuedBufs + 1;
+ err = native_window_set_buffer_count(mNativeWindow.get(), numBufs);
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)",
+ strerror(-err), -err);
+ goto error;
+ }
+
+ // We push numBufs + 1 buffers to ensure that we've drawn into the same
+ // buffer twice. This should guarantee that the buffer has been displayed
+ // on the screen and then been replaced, so an previous video frames are
+ // guaranteed NOT to be currently displayed.
+ for (int i = 0; i < numBufs + 1; i++) {
+ err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &anb);
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
+ strerror(-err), -err);
+ goto error;
+ }
+
+ sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ err = mNativeWindow->lockBuffer(mNativeWindow.get(),
+ buf->getNativeBuffer());
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: lockBuffer failed: %s (%d)",
+ strerror(-err), -err);
+ goto error;
+ }
+
+ // Fill the buffer with the a 1x1 checkerboard pattern ;)
+ uint32_t* img = NULL;
+ err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: lock failed: %s (%d)",
+ strerror(-err), -err);
+ goto error;
+ }
+
+ *img = 0;
+
+ err = buf->unlock();
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: unlock failed: %s (%d)",
+ strerror(-err), -err);
+ goto error;
+ }
+
+ err = mNativeWindow->queueBuffer(mNativeWindow.get(),
+ buf->getNativeBuffer());
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
+ strerror(-err), -err);
+ goto error;
+ }
+
+ anb = NULL;
+ }
+
+error:
+
+ if (err != NO_ERROR) {
+ // Clean up after an error.
+ if (anb != NULL) {
+ mNativeWindow->cancelBuffer(mNativeWindow.get(), anb);
+ }
+
+ native_window_api_disconnect(mNativeWindow.get(),
+ NATIVE_WINDOW_API_CPU);
+ native_window_api_connect(mNativeWindow.get(),
+ NATIVE_WINDOW_API_MEDIA);
+
+ return err;
+ } else {
+ // Clean up after success.
+ err = native_window_api_disconnect(mNativeWindow.get(),
+ NATIVE_WINDOW_API_CPU);
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
+ strerror(-err), -err);
+ return err;
+ }
+
+ err = native_window_api_connect(mNativeWindow.get(),
+ NATIVE_WINDOW_API_MEDIA);
+ if (err != NO_ERROR) {
+ ALOGE("error pushing blank frames: api_connect failed: %s (%d)",
+ strerror(-err), -err);
+ return err;
+ }
+
+ return NO_ERROR;
+ }
+}
+
+int64_t OMXCodec::getDecodingTimeUs() {
+ CHECK(mIsEncoder && mIsVideo);
+
+ if (mDecodingTimeList.empty()) {
+ CHECK(mSignalledEOS || mNoMoreOutputData);
+ // No corresponding input frame available.
+ // This could happen when EOS is reached.
+ return 0;
+ }
+
+ List<int64_t>::iterator it = mDecodingTimeList.begin();
+ int64_t timeUs = *it;
+ mDecodingTimeList.erase(it);
+ return timeUs;
+}
+
+void OMXCodec::on_message(const omx_message &msg) {
+ if (mState == ERROR) {
+ ALOGW("Dropping OMX message - we're in ERROR state.");
+ return;
+ }
+
+ switch (msg.type) {
+ case omx_message::EVENT:
+ {
+ onEvent(
+ msg.u.event_data.event, msg.u.event_data.data1,
+ msg.u.event_data.data2);
+
+ break;
+ }
+
+ case omx_message::EMPTY_BUFFER_DONE:
+ {
+ IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
+
+ CODEC_LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
+
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
+ size_t i = 0;
+ while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
+ ++i;
+ }
+
+ CHECK(i < buffers->size());
+ if ((*buffers)[i].mStatus != OWNED_BY_COMPONENT) {
+ ALOGW("We already own input buffer %p, yet received "
+ "an EMPTY_BUFFER_DONE.", buffer);
+ }
+
+ BufferInfo* info = &buffers->editItemAt(i);
+ info->mStatus = OWNED_BY_US;
+
+ // Buffer could not be released until empty buffer done is called.
+ if (info->mMediaBuffer != NULL) {
+ if (mIsEncoder &&
+ (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
+ // If zero-copy mode is enabled this will send the
+ // input buffer back to the upstream source.
+ restorePatchedDataPointer(info);
+ }
+
+ info->mMediaBuffer->release();
+ info->mMediaBuffer = NULL;
+ }
+
+ if (mPortStatus[kPortIndexInput] == DISABLING) {
+ CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
+
+ status_t err = freeBuffer(kPortIndexInput, i);
+ CHECK_EQ(err, (status_t)OK);
+ } else if (mState != ERROR
+ && mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
+ CHECK_EQ((int)mPortStatus[kPortIndexInput], (int)ENABLED);
+
+ if (mFlags & kUseSecureInputBuffers) {
+ drainAnyInputBuffer();
+ } else {
+ drainInputBuffer(&buffers->editItemAt(i));
+ }
+ }
+ break;
+ }
+
+ case omx_message::FILL_BUFFER_DONE:
+ {
+ IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
+ OMX_U32 flags = msg.u.extended_buffer_data.flags;
+
+ CODEC_LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx, timestamp: %lld us (%.2f secs))",
+ buffer,
+ msg.u.extended_buffer_data.range_length,
+ flags,
+ msg.u.extended_buffer_data.timestamp,
+ msg.u.extended_buffer_data.timestamp / 1E6);
+
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
+ size_t i = 0;
+ while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
+ ++i;
+ }
+
+ CHECK(i < buffers->size());
+ BufferInfo *info = &buffers->editItemAt(i);
+
+ if (info->mStatus != OWNED_BY_COMPONENT) {
+ ALOGW("We already own output buffer %p, yet received "
+ "a FILL_BUFFER_DONE.", buffer);
+ }
+
+ info->mStatus = OWNED_BY_US;
+
+ if (mPortStatus[kPortIndexOutput] == DISABLING) {
+ CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
+
+ status_t err = freeBuffer(kPortIndexOutput, i);
+ CHECK_EQ(err, (status_t)OK);
+
+#if 0
+ } else if (mPortStatus[kPortIndexOutput] == ENABLED
+ && (flags & OMX_BUFFERFLAG_EOS)) {
+ CODEC_LOGV("No more output data.");
+ mNoMoreOutputData = true;
+ mBufferFilled.signal();
+#endif
+ } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
+ CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)ENABLED);
+
+ if (info->mMediaBuffer == NULL) {
+ CHECK(mOMXLivesLocally);
+ CHECK(mQuirks & kRequiresAllocateBufferOnOutputPorts);
+ CHECK(mQuirks & kDefersOutputBufferAllocation);
+
+ // The qcom video decoders on Nexus don't actually allocate
+ // output buffer memory on a call to OMX_AllocateBuffer
+ // the "pBuffer" member of the OMX_BUFFERHEADERTYPE
+ // structure is only filled in later.
+
+ info->mMediaBuffer = new MediaBuffer(
+ msg.u.extended_buffer_data.data_ptr,
+ info->mSize);
+ info->mMediaBuffer->setObserver(this);
+ }
+
+ MediaBuffer *buffer = info->mMediaBuffer;
+ bool isGraphicBuffer = buffer->graphicBuffer() != NULL;
+
+ if (!isGraphicBuffer
+ && msg.u.extended_buffer_data.range_offset
+ + msg.u.extended_buffer_data.range_length
+ > buffer->size()) {
+ CODEC_LOGE(
+ "Codec lied about its buffer size requirements, "
+ "sending a buffer larger than the originally "
+ "advertised size in FILL_BUFFER_DONE!");
+ }
+ buffer->set_range(
+ msg.u.extended_buffer_data.range_offset,
+ msg.u.extended_buffer_data.range_length);
+
+ buffer->meta_data()->clear();
+
+ buffer->meta_data()->setInt64(
+ kKeyTime, msg.u.extended_buffer_data.timestamp);
+
+ if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
+ buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
+ }
+ bool isCodecSpecific = false;
+ if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_CODECCONFIG) {
+ buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
+ isCodecSpecific = true;
+ }
+
+ if (isGraphicBuffer || mQuirks & kOutputBuffersAreUnreadable) {
+ buffer->meta_data()->setInt32(kKeyIsUnreadable, true);
+ }
+
+ buffer->meta_data()->setPointer(
+ kKeyPlatformPrivate,
+ msg.u.extended_buffer_data.platform_private);
+
+ buffer->meta_data()->setPointer(
+ kKeyBufferID,
+ msg.u.extended_buffer_data.buffer);
+
+ if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_EOS) {
+ CODEC_LOGV("No more output data.");
+ mNoMoreOutputData = true;
+ }
+
+ if (mIsEncoder && mIsVideo) {
+ int64_t decodingTimeUs = isCodecSpecific? 0: getDecodingTimeUs();
+ buffer->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
+ }
+
+ 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();
+ if (mIsEncoder) {
+ sched_yield();
+ }
+ }
+
+ break;
+ }
+
+ default:
+ {
+ CHECK(!"should not be here.");
+ break;
+ }
+ }
+}
+
+// Has the format changed in any way that the client would have to be aware of?
+static bool formatHasNotablyChanged(
+ const sp<MetaData> &from, const sp<MetaData> &to) {
+ if (from.get() == NULL && to.get() == NULL) {
+ return false;
+ }
+
+ if ((from.get() == NULL && to.get() != NULL)
+ || (from.get() != NULL && to.get() == NULL)) {
+ return true;
+ }
+
+ const char *mime_from, *mime_to;
+ CHECK(from->findCString(kKeyMIMEType, &mime_from));
+ CHECK(to->findCString(kKeyMIMEType, &mime_to));
+
+ if (strcasecmp(mime_from, mime_to)) {
+ return true;
+ }
+
+ if (!strcasecmp(mime_from, MEDIA_MIMETYPE_VIDEO_RAW)) {
+ int32_t colorFormat_from, colorFormat_to;
+ CHECK(from->findInt32(kKeyColorFormat, &colorFormat_from));
+ CHECK(to->findInt32(kKeyColorFormat, &colorFormat_to));
+
+ if (colorFormat_from != colorFormat_to) {
+ return true;
+ }
+
+ int32_t width_from, width_to;
+ CHECK(from->findInt32(kKeyWidth, &width_from));
+ CHECK(to->findInt32(kKeyWidth, &width_to));
+
+ if (width_from != width_to) {
+ return true;
+ }
+
+ int32_t height_from, height_to;
+ CHECK(from->findInt32(kKeyHeight, &height_from));
+ CHECK(to->findInt32(kKeyHeight, &height_to));
+
+ if (height_from != height_to) {
+ return true;
+ }
+
+ int32_t left_from, top_from, right_from, bottom_from;
+ CHECK(from->findRect(
+ kKeyCropRect,
+ &left_from, &top_from, &right_from, &bottom_from));
+
+ int32_t left_to, top_to, right_to, bottom_to;
+ CHECK(to->findRect(
+ kKeyCropRect,
+ &left_to, &top_to, &right_to, &bottom_to));
+
+ if (left_to != left_from || top_to != top_from
+ || right_to != right_from || bottom_to != bottom_from) {
+ return true;
+ }
+ } else if (!strcasecmp(mime_from, MEDIA_MIMETYPE_AUDIO_RAW)) {
+ int32_t numChannels_from, numChannels_to;
+ CHECK(from->findInt32(kKeyChannelCount, &numChannels_from));
+ CHECK(to->findInt32(kKeyChannelCount, &numChannels_to));
+
+ if (numChannels_from != numChannels_to) {
+ return true;
+ }
+
+ int32_t sampleRate_from, sampleRate_to;
+ CHECK(from->findInt32(kKeySampleRate, &sampleRate_from));
+ CHECK(to->findInt32(kKeySampleRate, &sampleRate_to));
+
+ if (sampleRate_from != sampleRate_to) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+ switch (event) {
+ case OMX_EventCmdComplete:
+ {
+ onCmdComplete((OMX_COMMANDTYPE)data1, data2);
+ break;
+ }
+
+ case OMX_EventError:
+ {
+ CODEC_LOGE("ERROR(0x%08lx, %ld)", data1, data2);
+
+ setState(ERROR);
+ break;
+ }
+
+ case OMX_EventPortSettingsChanged:
+ {
+ CODEC_LOGV("OMX_EventPortSettingsChanged(port=%ld, data2=0x%08lx)",
+ data1, data2);
+
+ if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
+ // There is no need to check whether mFilledBuffers is empty or not
+ // when the OMX_EventPortSettingsChanged is not meant for reallocating
+ // the output buffers.
+ if (data1 == kPortIndexOutput) {
+ CHECK(mFilledBuffers.empty());
+ }
+ onPortSettingsChanged(data1);
+ } else if (data1 == kPortIndexOutput &&
+ (data2 == OMX_IndexConfigCommonOutputCrop ||
+ data2 == OMX_IndexConfigCommonScale)) {
+
+ sp<MetaData> oldOutputFormat = mOutputFormat;
+ initOutputFormat(mSource->getFormat());
+
+ if (data2 == OMX_IndexConfigCommonOutputCrop &&
+ formatHasNotablyChanged(oldOutputFormat, mOutputFormat)) {
+ mOutputPortSettingsHaveChanged = true;
+
+ } else if (data2 == OMX_IndexConfigCommonScale) {
+ OMX_CONFIG_SCALEFACTORTYPE scale;
+ InitOMXParams(&scale);
+ scale.nPortIndex = kPortIndexOutput;
+
+ // Change display dimension only when necessary.
+ if (OK == mOMX->getConfig(
+ mNode,
+ OMX_IndexConfigCommonScale,
+ &scale, sizeof(scale))) {
+ int32_t left, top, right, bottom;
+ CHECK(mOutputFormat->findRect(kKeyCropRect,
+ &left, &top,
+ &right, &bottom));
+
+ // The scale is in 16.16 format.
+ // scale 1.0 = 0x010000. When there is no
+ // need to change the display, skip it.
+ ALOGV("Get OMX_IndexConfigScale: 0x%lx/0x%lx",
+ scale.xWidth, scale.xHeight);
+
+ if (scale.xWidth != 0x010000) {
+ mOutputFormat->setInt32(kKeyDisplayWidth,
+ ((right - left + 1) * scale.xWidth) >> 16);
+ mOutputPortSettingsHaveChanged = true;
+ }
+
+ if (scale.xHeight != 0x010000) {
+ mOutputFormat->setInt32(kKeyDisplayHeight,
+ ((bottom - top + 1) * scale.xHeight) >> 16);
+ mOutputPortSettingsHaveChanged = true;
+ }
+ }
+ }
+ }
+ break;
+ }
+
+#if 0
+ case OMX_EventBufferFlag:
+ {
+ CODEC_LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
+
+ if (data1 == kPortIndexOutput) {
+ mNoMoreOutputData = true;
+ }
+ break;
+ }
+#endif
+
+ default:
+ {
+ CODEC_LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
+ break;
+ }
+ }
+}
+
+void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
+ switch (cmd) {
+ case OMX_CommandStateSet:
+ {
+ onStateChange((OMX_STATETYPE)data);
+ break;
+ }
+
+ case OMX_CommandPortDisable:
+ {
+ OMX_U32 portIndex = data;
+ CODEC_LOGV("PORT_DISABLED(%ld)", portIndex);
+
+ CHECK(mState == EXECUTING || mState == RECONFIGURING);
+ CHECK_EQ((int)mPortStatus[portIndex], (int)DISABLING);
+ CHECK_EQ(mPortBuffers[portIndex].size(), 0u);
+
+ mPortStatus[portIndex] = DISABLED;
+
+ if (mState == RECONFIGURING) {
+ CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
+
+ sp<MetaData> oldOutputFormat = mOutputFormat;
+ initOutputFormat(mSource->getFormat());
+
+ // Don't notify clients if the output port settings change
+ // wasn't of importance to them, i.e. it may be that just the
+ // number of buffers has changed and nothing else.
+ bool formatChanged = formatHasNotablyChanged(oldOutputFormat, mOutputFormat);
+ if (!mOutputPortSettingsHaveChanged) {
+ mOutputPortSettingsHaveChanged = formatChanged;
+ }
+
+ status_t err = enablePortAsync(portIndex);
+ if (err != OK) {
+ CODEC_LOGE("enablePortAsync(%ld) failed (err = %d)", portIndex, err);
+ setState(ERROR);
+ } else {
+ err = allocateBuffersOnPort(portIndex);
+ if (err != OK) {
+ CODEC_LOGE("allocateBuffersOnPort failed (err = %d)", err);
+ setState(ERROR);
+ }
+ }
+ }
+ break;
+ }
+
+ case OMX_CommandPortEnable:
+ {
+ OMX_U32 portIndex = data;
+ CODEC_LOGV("PORT_ENABLED(%ld)", portIndex);
+
+ CHECK(mState == EXECUTING || mState == RECONFIGURING);
+ CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLING);
+
+ mPortStatus[portIndex] = ENABLED;
+
+ if (mState == RECONFIGURING) {
+ CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
+
+ setState(EXECUTING);
+
+ fillOutputBuffers();
+ }
+ break;
+ }
+
+ case OMX_CommandFlush:
+ {
+ OMX_U32 portIndex = data;
+
+ CODEC_LOGV("FLUSH_DONE(%ld)", portIndex);
+
+ CHECK_EQ((int)mPortStatus[portIndex], (int)SHUTTING_DOWN);
+ mPortStatus[portIndex] = ENABLED;
+
+ CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
+ mPortBuffers[portIndex].size());
+
+ if (mSkipCutBuffer && mPortStatus[kPortIndexOutput] == ENABLED) {
+ mSkipCutBuffer->clear();
+ }
+
+ if (mState == RECONFIGURING) {
+ CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
+
+ disablePortAsync(portIndex);
+ } else if (mState == EXECUTING_TO_IDLE) {
+ if (mPortStatus[kPortIndexInput] == ENABLED
+ && mPortStatus[kPortIndexOutput] == ENABLED) {
+ CODEC_LOGV("Finished flushing both ports, now completing "
+ "transition from EXECUTING to IDLE.");
+
+ mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
+ mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
+
+ status_t err =
+ mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
+ CHECK_EQ(err, (status_t)OK);
+ }
+ } else {
+ // We're flushing both ports in preparation for seeking.
+
+ if (mPortStatus[kPortIndexInput] == ENABLED
+ && mPortStatus[kPortIndexOutput] == ENABLED) {
+ CODEC_LOGV("Finished flushing both ports, now continuing from"
+ " seek-time.");
+
+ // We implicitly resume pulling on our upstream source.
+ mPaused = false;
+
+ drainInputBuffers();
+ fillOutputBuffers();
+ }
+
+ if (mOutputPortSettingsChangedPending) {
+ CODEC_LOGV(
+ "Honoring deferred output port settings change.");
+
+ mOutputPortSettingsChangedPending = false;
+ onPortSettingsChanged(kPortIndexOutput);
+ }
+ }
+
+ break;
+ }
+
+ default:
+ {
+ CODEC_LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
+ break;
+ }
+ }
+}
+
+void OMXCodec::onStateChange(OMX_STATETYPE newState) {
+ CODEC_LOGV("onStateChange %d", newState);
+
+ switch (newState) {
+ case OMX_StateIdle:
+ {
+ CODEC_LOGV("Now Idle.");
+ if (mState == LOADED_TO_IDLE) {
+ status_t err = mOMX->sendCommand(
+ mNode, OMX_CommandStateSet, OMX_StateExecuting);
+
+ CHECK_EQ(err, (status_t)OK);
+
+ setState(IDLE_TO_EXECUTING);
+ } else {
+ CHECK_EQ((int)mState, (int)EXECUTING_TO_IDLE);
+
+ CHECK_EQ(
+ countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
+ mPortBuffers[kPortIndexInput].size());
+
+ CHECK_EQ(
+ countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
+ mPortBuffers[kPortIndexOutput].size());
+
+ status_t err = mOMX->sendCommand(
+ mNode, OMX_CommandStateSet, OMX_StateLoaded);
+
+ CHECK_EQ(err, (status_t)OK);
+
+ err = freeBuffersOnPort(kPortIndexInput);
+ CHECK_EQ(err, (status_t)OK);
+
+ err = freeBuffersOnPort(kPortIndexOutput);
+ CHECK_EQ(err, (status_t)OK);
+
+ mPortStatus[kPortIndexInput] = ENABLED;
+ mPortStatus[kPortIndexOutput] = ENABLED;
+
+ if ((mFlags & kEnableGrallocUsageProtected) &&
+ mNativeWindow != NULL) {
+ // We push enough 1x1 blank buffers to ensure that one of
+ // them has made it to the display. This allows the OMX
+ // component teardown to zero out any protected buffers
+ // without the risk of scanning out one of those buffers.
+ pushBlankBuffersToNativeWindow();
+ }
+
+ setState(IDLE_TO_LOADED);
+ }
+ break;
+ }
+
+ case OMX_StateExecuting:
+ {
+ CHECK_EQ((int)mState, (int)IDLE_TO_EXECUTING);
+
+ CODEC_LOGV("Now Executing.");
+
+ mOutputPortSettingsChangedPending = false;
+
+ setState(EXECUTING);
+
+ // Buffers will be submitted to the component in the first
+ // call to OMXCodec::read as mInitialBufferSubmit is true at
+ // this point. This ensures that this on_message call returns,
+ // releases the lock and ::init can notice the state change and
+ // itself return.
+ break;
+ }
+
+ case OMX_StateLoaded:
+ {
+ CHECK_EQ((int)mState, (int)IDLE_TO_LOADED);
+
+ CODEC_LOGV("Now Loaded.");
+
+ setState(LOADED);
+ break;
+ }
+
+ case OMX_StateInvalid:
+ {
+ setState(ERROR);
+ break;
+ }
+
+ default:
+ {
+ CHECK(!"should not be here.");
+ break;
+ }
+ }
+}
+
+// static
+size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
+ size_t n = 0;
+ for (size_t i = 0; i < buffers.size(); ++i) {
+ if (buffers[i].mStatus != OWNED_BY_COMPONENT) {
+ ++n;
+ }
+ }
+
+ return n;
+}
+
+status_t OMXCodec::freeBuffersOnPort(
+ OMX_U32 portIndex, bool onlyThoseWeOwn) {
+ Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
+
+ status_t stickyErr = OK;
+
+ for (size_t i = buffers->size(); i-- > 0;) {
+ BufferInfo *info = &buffers->editItemAt(i);
+
+ if (onlyThoseWeOwn && info->mStatus == OWNED_BY_COMPONENT) {
+ continue;
+ }
+
+ CHECK(info->mStatus == OWNED_BY_US
+ || info->mStatus == OWNED_BY_NATIVE_WINDOW);
+
+ CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
+
+ status_t err = freeBuffer(portIndex, i);
+
+ if (err != OK) {
+ stickyErr = err;
+ }
+
+ }
+
+ CHECK(onlyThoseWeOwn || buffers->isEmpty());
+
+ return stickyErr;
+}
+
+status_t OMXCodec::freeBuffer(OMX_U32 portIndex, size_t bufIndex) {
+ Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
+
+ BufferInfo *info = &buffers->editItemAt(bufIndex);
+
+ status_t err = mOMX->freeBuffer(mNode, portIndex, info->mBuffer);
+
+ if (err == OK && info->mMediaBuffer != NULL) {
+ CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
+ info->mMediaBuffer->setObserver(NULL);
+
+ // Make sure nobody but us owns this buffer at this point.
+ CHECK_EQ(info->mMediaBuffer->refcount(), 0);
+
+ // Cancel the buffer if it belongs to an ANativeWindow.
+ sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
+ if (info->mStatus == OWNED_BY_US && graphicBuffer != 0) {
+ err = cancelBufferToNativeWindow(info);
+ }
+
+ info->mMediaBuffer->release();
+ info->mMediaBuffer = NULL;
+ }
+
+ if (err == OK) {
+ buffers->removeAt(bufIndex);
+ }
+
+ return err;
+}
+
+void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
+ CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
+
+ CHECK_EQ((int)mState, (int)EXECUTING);
+ CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
+ CHECK(!mOutputPortSettingsChangedPending);
+
+ if (mPortStatus[kPortIndexOutput] != ENABLED) {
+ CODEC_LOGV("Deferring output port settings change.");
+ mOutputPortSettingsChangedPending = true;
+ return;
+ }
+
+ setState(RECONFIGURING);
+
+ if (mQuirks & kNeedsFlushBeforeDisable) {
+ if (!flushPortAsync(portIndex)) {
+ onCmdComplete(OMX_CommandFlush, portIndex);
+ }
+ } else {
+ disablePortAsync(portIndex);
+ }
+}
+
+bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
+ CHECK(mState == EXECUTING || mState == RECONFIGURING
+ || mState == EXECUTING_TO_IDLE);
+
+ CODEC_LOGV("flushPortAsync(%ld): we own %d out of %d buffers already.",
+ portIndex, countBuffersWeOwn(mPortBuffers[portIndex]),
+ mPortBuffers[portIndex].size());
+
+ CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLED);
+ mPortStatus[portIndex] = SHUTTING_DOWN;
+
+ if ((mQuirks & kRequiresFlushCompleteEmulation)
+ && countBuffersWeOwn(mPortBuffers[portIndex])
+ == mPortBuffers[portIndex].size()) {
+ // No flush is necessary and this component fails to send a
+ // flush-complete event in this case.
+
+ return false;
+ }
+
+ status_t err =
+ mOMX->sendCommand(mNode, OMX_CommandFlush, portIndex);
+ CHECK_EQ(err, (status_t)OK);
+
+ return true;
+}
+
+void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
+ CHECK(mState == EXECUTING || mState == RECONFIGURING);
+
+ CHECK_EQ((int)mPortStatus[portIndex], (int)ENABLED);
+ mPortStatus[portIndex] = DISABLING;
+
+ CODEC_LOGV("sending OMX_CommandPortDisable(%ld)", portIndex);
+ status_t err =
+ mOMX->sendCommand(mNode, OMX_CommandPortDisable, portIndex);
+ CHECK_EQ(err, (status_t)OK);
+
+ freeBuffersOnPort(portIndex, true);
+}
+
+status_t OMXCodec::enablePortAsync(OMX_U32 portIndex) {
+ CHECK(mState == EXECUTING || mState == RECONFIGURING);
+
+ CHECK_EQ((int)mPortStatus[portIndex], (int)DISABLED);
+ mPortStatus[portIndex] = ENABLING;
+
+ CODEC_LOGV("sending OMX_CommandPortEnable(%ld)", portIndex);
+ return mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
+}
+
+void OMXCodec::fillOutputBuffers() {
+ CHECK_EQ((int)mState, (int)EXECUTING);
+
+ // This is a workaround for some decoders not properly reporting
+ // end-of-output-stream. If we own all input buffers and also own
+ // all output buffers and we already signalled end-of-input-stream,
+ // the end-of-output-stream is implied.
+ if (mSignalledEOS
+ && countBuffersWeOwn(mPortBuffers[kPortIndexInput])
+ == mPortBuffers[kPortIndexInput].size()
+ && countBuffersWeOwn(mPortBuffers[kPortIndexOutput])
+ == mPortBuffers[kPortIndexOutput].size()) {
+ mNoMoreOutputData = true;
+ mBufferFilled.signal();
+
+ return;
+ }
+
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
+ for (size_t i = 0; i < buffers->size(); ++i) {
+ BufferInfo *info = &buffers->editItemAt(i);
+ if (info->mStatus == OWNED_BY_US) {
+ fillOutputBuffer(&buffers->editItemAt(i));
+ }
+ }
+}
+
+void OMXCodec::drainInputBuffers() {
+ CHECK(mState == EXECUTING || mState == RECONFIGURING);
+
+ if (mFlags & kUseSecureInputBuffers) {
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
+ for (size_t i = 0; i < buffers->size(); ++i) {
+ if (!drainAnyInputBuffer()
+ || (mFlags & kOnlySubmitOneInputBufferAtOneTime)) {
+ break;
+ }
+ }
+ } else {
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
+ for (size_t i = 0; i < buffers->size(); ++i) {
+ BufferInfo *info = &buffers->editItemAt(i);
+
+ if (info->mStatus != OWNED_BY_US) {
+ continue;
+ }
+
+ if (!drainInputBuffer(info)) {
+ break;
+ }
+
+ if (mFlags & kOnlySubmitOneInputBufferAtOneTime) {
+ break;
+ }
+ }
+ }
+}
+
+bool OMXCodec::drainAnyInputBuffer() {
+ return drainInputBuffer((BufferInfo *)NULL);
+}
+
+OMXCodec::BufferInfo *OMXCodec::findInputBufferByDataPointer(void *ptr) {
+ Vector<BufferInfo> *infos = &mPortBuffers[kPortIndexInput];
+ for (size_t i = 0; i < infos->size(); ++i) {
+ BufferInfo *info = &infos->editItemAt(i);
+
+ if (info->mData == ptr) {
+ CODEC_LOGV(
+ "input buffer data ptr = %p, buffer_id = %p",
+ ptr,
+ info->mBuffer);
+
+ return info;
+ }
+ }
+
+ TRESPASS();
+}
+
+OMXCodec::BufferInfo *OMXCodec::findEmptyInputBuffer() {
+ Vector<BufferInfo> *infos = &mPortBuffers[kPortIndexInput];
+ for (size_t i = 0; i < infos->size(); ++i) {
+ BufferInfo *info = &infos->editItemAt(i);
+
+ if (info->mStatus == OWNED_BY_US) {
+ return info;
+ }
+ }
+
+ TRESPASS();
+}
+
+bool OMXCodec::drainInputBuffer(BufferInfo *info) {
+ if (info != NULL) {
+ CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
+ }
+
+ if (mSignalledEOS) {
+ return false;
+ }
+
+ if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
+ CHECK(!(mFlags & kUseSecureInputBuffers));
+
+ const CodecSpecificData *specific =
+ mCodecSpecificData[mCodecSpecificDataIndex];
+
+ size_t size = specific->mSize;
+
+ if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mMIME)
+ && !(mQuirks & kWantsNALFragments)) {
+ static const uint8_t kNALStartCode[4] =
+ { 0x00, 0x00, 0x00, 0x01 };
+
+ CHECK(info->mSize >= specific->mSize + 4);
+
+ size += 4;
+
+ memcpy(info->mData, kNALStartCode, 4);
+ memcpy((uint8_t *)info->mData + 4,
+ specific->mData, specific->mSize);
+ } else {
+ CHECK(info->mSize >= specific->mSize);
+ memcpy(info->mData, specific->mData, specific->mSize);
+ }
+
+ mNoMoreOutputData = false;
+
+ CODEC_LOGV("calling emptyBuffer with codec specific data");
+
+ status_t err = mOMX->emptyBuffer(
+ mNode, info->mBuffer, 0, size,
+ OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
+ 0);
+ CHECK_EQ(err, (status_t)OK);
+
+ info->mStatus = OWNED_BY_COMPONENT;
+
+ ++mCodecSpecificDataIndex;
+ return true;
+ }
+
+ if (mPaused) {
+ return false;
+ }
+
+ status_t err;
+
+ bool signalEOS = false;
+ int64_t timestampUs = 0;
+
+ size_t offset = 0;
+ int32_t n = 0;
+
+
+ for (;;) {
+ MediaBuffer *srcBuffer;
+ if (mSeekTimeUs >= 0) {
+ if (mLeftOverBuffer) {
+ mLeftOverBuffer->release();
+ mLeftOverBuffer = NULL;
+ }
+
+ MediaSource::ReadOptions options;
+ 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) {
+ CODEC_LOGV("targetTimeUs = %lld us", targetTimeUs);
+ mTargetTimeUs = targetTimeUs;
+ } else {
+ mTargetTimeUs = -1;
+ }
+ }
+ } else if (mLeftOverBuffer) {
+ srcBuffer = mLeftOverBuffer;
+ mLeftOverBuffer = NULL;
+
+ err = OK;
+ } else {
+ err = mSource->read(&srcBuffer);
+ }
+
+ if (err != OK) {
+ signalEOS = true;
+ mFinalStatus = err;
+ mSignalledEOS = true;
+ mBufferFilled.signal();
+ break;
+ }
+
+ if (mFlags & kUseSecureInputBuffers) {
+ info = findInputBufferByDataPointer(srcBuffer->data());
+ CHECK(info != NULL);
+ }
+
+ size_t remainingBytes = info->mSize - offset;
+
+ if (srcBuffer->range_length() > remainingBytes) {
+ if (offset == 0) {
+ CODEC_LOGE(
+ "Codec's input buffers are too small to accomodate "
+ "buffer read from source (info->mSize = %d, srcLength = %d)",
+ info->mSize, srcBuffer->range_length());
+
+ srcBuffer->release();
+ srcBuffer = NULL;
+
+ setState(ERROR);
+ return false;
+ }
+
+ mLeftOverBuffer = srcBuffer;
+ break;
+ }
+
+ bool releaseBuffer = true;
+ if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
+ CHECK(mOMXLivesLocally && offset == 0);
+
+ OMX_BUFFERHEADERTYPE *header =
+ (OMX_BUFFERHEADERTYPE *)info->mBuffer;
+
+ CHECK(header->pBuffer == info->mData);
+
+ header->pBuffer =
+ (OMX_U8 *)srcBuffer->data() + srcBuffer->range_offset();
+
+ releaseBuffer = false;
+ info->mMediaBuffer = srcBuffer;
+ } else {
+ if (mFlags & kStoreMetaDataInVideoBuffers) {
+ releaseBuffer = false;
+ info->mMediaBuffer = srcBuffer;
+ }
+
+ if (mFlags & kUseSecureInputBuffers) {
+ // Data in "info" is already provided at this time.
+
+ releaseBuffer = false;
+
+ CHECK(info->mMediaBuffer == NULL);
+ info->mMediaBuffer = srcBuffer;
+ } else {
+ CHECK(srcBuffer->data() != NULL) ;
+ 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(lastBufferTimeUs >= 0);
+ if (mIsEncoder && mIsVideo) {
+ mDecodingTimeList.push_back(lastBufferTimeUs);
+ }
+
+ if (offset == 0) {
+ timestampUs = lastBufferTimeUs;
+ }
+
+ offset += srcBuffer->range_length();
+
+ if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_VORBIS, mMIME)) {
+ CHECK(!(mQuirks & kSupportsMultipleFramesPerInputBuffer));
+ CHECK_GE(info->mSize, offset + sizeof(int32_t));
+
+ int32_t numPageSamples;
+ if (!srcBuffer->meta_data()->findInt32(
+ kKeyValidSamples, &numPageSamples)) {
+ numPageSamples = -1;
+ }
+
+ memcpy((uint8_t *)info->mData + offset,
+ &numPageSamples,
+ sizeof(numPageSamples));
+
+ offset += sizeof(numPageSamples);
+ }
+
+ if (releaseBuffer) {
+ srcBuffer->release();
+ srcBuffer = NULL;
+ }
+
+ ++n;
+
+ if (!(mQuirks & kSupportsMultipleFramesPerInputBuffer)) {
+ break;
+ }
+
+ int64_t coalescedDurationUs = lastBufferTimeUs - timestampUs;
+
+ if (coalescedDurationUs > 250000ll) {
+ // Don't coalesce more than 250ms worth of encoded data at once.
+ break;
+ }
+ }
+
+ if (n > 1) {
+ ALOGV("coalesced %d frames into one input buffer", n);
+ }
+
+ OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
+
+ if (signalEOS) {
+ flags |= OMX_BUFFERFLAG_EOS;
+ } else {
+ mNoMoreOutputData = false;
+ }
+
+ CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d), "
+ "timestamp %lld us (%.2f secs)",
+ info->mBuffer, offset,
+ timestampUs, timestampUs / 1E6);
+
+ if (info == NULL) {
+ CHECK(mFlags & kUseSecureInputBuffers);
+ CHECK(signalEOS);
+
+ // This is fishy, there's still a MediaBuffer corresponding to this
+ // info available to the source at this point even though we're going
+ // to use it to signal EOS to the codec.
+ info = findEmptyInputBuffer();
+ }
+
+ err = mOMX->emptyBuffer(
+ mNode, info->mBuffer, 0, offset,
+ flags, timestampUs);
+
+ if (err != OK) {
+ setState(ERROR);
+ return false;
+ }
+
+ info->mStatus = OWNED_BY_COMPONENT;
+
+ return true;
+}
+
+void OMXCodec::fillOutputBuffer(BufferInfo *info) {
+ CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
+
+ if (mNoMoreOutputData) {
+ CODEC_LOGV("There is no more output data available, not "
+ "calling fillOutputBuffer");
+ return;
+ }
+
+ if (info->mMediaBuffer != NULL) {
+ sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
+ if (graphicBuffer != 0) {
+ // When using a native buffer we need to lock the buffer before
+ // giving it to OMX.
+ CODEC_LOGV("Calling lockBuffer on %p", info->mBuffer);
+ int err = mNativeWindow->lockBuffer(mNativeWindow.get(),
+ graphicBuffer.get());
+ if (err != 0) {
+ CODEC_LOGE("lockBuffer failed w/ error 0x%08x", err);
+
+ setState(ERROR);
+ return;
+ }
+ }
+ }
+
+ CODEC_LOGV("Calling fillBuffer on buffer %p", info->mBuffer);
+ status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
+
+ if (err != OK) {
+ CODEC_LOGE("fillBuffer failed w/ error 0x%08x", err);
+
+ setState(ERROR);
+ return;
+ }
+
+ info->mStatus = OWNED_BY_COMPONENT;
+}
+
+bool OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
+ for (size_t i = 0; i < buffers->size(); ++i) {
+ if ((*buffers)[i].mBuffer == buffer) {
+ return drainInputBuffer(&buffers->editItemAt(i));
+ }
+ }
+
+ CHECK(!"should not be here.");
+
+ return false;
+}
+
+void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
+ for (size_t i = 0; i < buffers->size(); ++i) {
+ if ((*buffers)[i].mBuffer == buffer) {
+ fillOutputBuffer(&buffers->editItemAt(i));
+ return;
+ }
+ }
+
+ CHECK(!"should not be here.");
+}
+
+void OMXCodec::setState(State newState) {
+ mState = newState;
+ mAsyncCompletion.signal();
+
+ // This may cause some spurious wakeups but is necessary to
+ // unblock the reader if we enter ERROR state.
+ mBufferFilled.signal();
+}
+
+status_t OMXCodec::waitForBufferFilled_l() {
+
+ if (mIsEncoder) {
+ // For timelapse video recording, the timelapse video recording may
+ // not send an input frame for a _long_ time. Do not use timeout
+ // for video encoding.
+ return mBufferFilled.wait(mLock);
+ }
+ status_t err = mBufferFilled.waitRelative(mLock, kBufferFilledEventTimeOutNs);
+ if (err != OK) {
+ CODEC_LOGE("Timed out waiting for output buffers: %d/%d",
+ countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
+ countBuffersWeOwn(mPortBuffers[kPortIndexOutput]));
+ }
+ return err;
+}
+
+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, (status_t)OK);
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+ CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
+ &def, sizeof(def)), (status_t)OK);
+
+ // pcm param
+ OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
+ InitOMXParams(&pcmParams);
+ pcmParams.nPortIndex = portIndex;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+
+ CHECK_EQ(err, (status_t)OK);
+
+ pcmParams.nChannels = numChannels;
+ pcmParams.eNumData = OMX_NumericalDataSigned;
+ pcmParams.bInterleaved = OMX_TRUE;
+ pcmParams.nBitPerSample = 16;
+ pcmParams.nSamplingRate = sampleRate;
+ pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
+
+ if (numChannels == 1) {
+ pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
+ } else {
+ CHECK_EQ(numChannels, 2);
+
+ pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+ pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+ }
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+
+ CHECK_EQ(err, (status_t)OK);
+}
+
+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;
+ InitOMXParams(&def);
+ def.nPortIndex = portIndex;
+
+ status_t err =
+ mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+
+ CHECK_EQ(err, (status_t)OK);
+
+ def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
+
+ def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitRate);
+ err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+ CHECK_EQ(err, (status_t)OK);
+
+ ////////////////////////
+
+ if (mIsEncoder) {
+ sp<MetaData> format = mSource->getFormat();
+ int32_t sampleRate;
+ int32_t numChannels;
+ CHECK(format->findInt32(kKeySampleRate, &sampleRate));
+ CHECK(format->findInt32(kKeyChannelCount, &numChannels));
+
+ setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+ }
+}
+
+status_t OMXCodec::setAACFormat(
+ int32_t numChannels, int32_t sampleRate, int32_t bitRate, bool isADTS) {
+ if (numChannels > 2) {
+ ALOGW("Number of channels: (%d) \n", numChannels);
+ }
+
+ if (mIsEncoder) {
+ if (isADTS) {
+ return -EINVAL;
+ }
+
+ //////////////// input port ////////////////////
+ setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+
+ //////////////// output port ////////////////////
+ // format
+ OMX_AUDIO_PARAM_PORTFORMATTYPE format;
+ InitOMXParams(&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)), (status_t)OK);
+ if (format.eEncoding == OMX_AUDIO_CodingAAC) {
+ break;
+ }
+ format.nIndex++;
+ }
+ CHECK_EQ((status_t)OK, err);
+ CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat,
+ &format, sizeof(format)), (status_t)OK);
+
+ // port definition
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexOutput;
+ CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition,
+ &def, sizeof(def)), (status_t)OK);
+ def.format.audio.bFlagErrorConcealment = OMX_TRUE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
+ CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
+ &def, sizeof(def)), (status_t)OK);
+
+ // profile
+ OMX_AUDIO_PARAM_AACPROFILETYPE profile;
+ InitOMXParams(&profile);
+ profile.nPortIndex = kPortIndexOutput;
+ CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac,
+ &profile, sizeof(profile)), (status_t)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;
+ err = mOMX->setParameter(mNode, OMX_IndexParamAudioAac,
+ &profile, sizeof(profile));
+
+ if (err != OK) {
+ CODEC_LOGE("setParameter('OMX_IndexParamAudioAac') failed "
+ "(err = %d)",
+ err);
+ return err;
+ }
+ } else {
+ OMX_AUDIO_PARAM_AACPROFILETYPE profile;
+ InitOMXParams(&profile);
+ profile.nPortIndex = kPortIndexInput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+ CHECK_EQ(err, (status_t)OK);
+
+ profile.nChannels = numChannels;
+ profile.nSampleRate = sampleRate;
+
+ profile.eAACStreamFormat =
+ isADTS
+ ? OMX_AUDIO_AACStreamFormatMP4ADTS
+ : OMX_AUDIO_AACStreamFormatMP4FF;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+
+ if (err != OK) {
+ CODEC_LOGE("setParameter('OMX_IndexParamAudioAac') failed "
+ "(err = %d)",
+ err);
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+void OMXCodec::setG711Format(int32_t numChannels) {
+ CHECK(!mIsEncoder);
+ setRawAudioFormat(kPortIndexInput, 8000, numChannels);
+}
+
+void OMXCodec::setImageOutputFormat(
+ OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
+ CODEC_LOGV("setImageOutputFormat(%ld, %ld)", width, height);
+
+#if 0
+ OMX_INDEXTYPE index;
+ status_t err = mOMX->get_extension_index(
+ mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
+ CHECK_EQ(err, (status_t)OK);
+
+ err = mOMX->set_config(mNode, index, &format, sizeof(format));
+ CHECK_EQ(err, (status_t)OK);
+#endif
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, (status_t)OK);
+
+ CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainImage);
+
+ OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
+
+ CHECK_EQ((int)imageDef->eCompressionFormat, (int)OMX_IMAGE_CodingUnused);
+ imageDef->eColorFormat = format;
+ imageDef->nFrameWidth = width;
+ imageDef->nFrameHeight = height;
+
+ switch (format) {
+ case OMX_COLOR_FormatYUV420PackedPlanar:
+ case OMX_COLOR_FormatYUV411Planar:
+ {
+ def.nBufferSize = (width * height * 3) / 2;
+ break;
+ }
+
+ case OMX_COLOR_FormatCbYCrY:
+ {
+ def.nBufferSize = width * height * 2;
+ break;
+ }
+
+ case OMX_COLOR_Format32bitARGB8888:
+ {
+ def.nBufferSize = width * height * 4;
+ break;
+ }
+
+ case OMX_COLOR_Format16bitARGB4444:
+ case OMX_COLOR_Format16bitARGB1555:
+ case OMX_COLOR_Format16bitRGB565:
+ case OMX_COLOR_Format16bitBGR565:
+ {
+ def.nBufferSize = width * height * 2;
+ break;
+ }
+
+ default:
+ CHECK(!"Should not be here. Unknown color format.");
+ break;
+ }
+
+ def.nBufferCountActual = def.nBufferCountMin;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, (status_t)OK);
+}
+
+void OMXCodec::setJPEGInputFormat(
+ OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexInput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, (status_t)OK);
+
+ CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainImage);
+ OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
+
+ CHECK_EQ((int)imageDef->eCompressionFormat, (int)OMX_IMAGE_CodingJPEG);
+ imageDef->nFrameWidth = width;
+ imageDef->nFrameHeight = height;
+
+ def.nBufferSize = compressedSize;
+ def.nBufferCountActual = def.nBufferCountMin;
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, (status_t)OK);
+}
+
+void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
+ CodecSpecificData *specific =
+ (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
+
+ specific->mSize = size;
+ memcpy(specific->mData, data, size);
+
+ mCodecSpecificData.push(specific);
+}
+
+void OMXCodec::clearCodecSpecificData() {
+ for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
+ free(mCodecSpecificData.editItemAt(i));
+ }
+ mCodecSpecificData.clear();
+ mCodecSpecificDataIndex = 0;
+}
+
+status_t OMXCodec::start(MetaData *meta) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mState != LOADED) {
+ return UNKNOWN_ERROR;
+ }
+
+ sp<MetaData> params = new 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) {
+ return err;
+ }
+
+ mCodecSpecificDataIndex = 0;
+ mInitialBufferSubmit = true;
+ mSignalledEOS = false;
+ mNoMoreOutputData = false;
+ mOutputPortSettingsHaveChanged = false;
+ mSeekTimeUs = -1;
+ mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
+ mTargetTimeUs = -1;
+ mFilledBuffers.clear();
+ mPaused = false;
+
+ return init();
+}
+
+status_t OMXCodec::stop() {
+ CODEC_LOGV("stop mState=%d", mState);
+
+ Mutex::Autolock autoLock(mLock);
+
+ while (isIntermediateState(mState)) {
+ mAsyncCompletion.wait(mLock);
+ }
+
+ bool isError = false;
+ switch (mState) {
+ case LOADED:
+ break;
+
+ case ERROR:
+ {
+ OMX_STATETYPE state = OMX_StateInvalid;
+ status_t err = mOMX->getState(mNode, &state);
+ CHECK_EQ(err, (status_t)OK);
+
+ if (state != OMX_StateExecuting) {
+ break;
+ }
+ // else fall through to the idling code
+ isError = true;
+ }
+
+ case EXECUTING:
+ {
+ setState(EXECUTING_TO_IDLE);
+
+ if (mQuirks & kRequiresFlushBeforeShutdown) {
+ CODEC_LOGV("This component requires a flush before transitioning "
+ "from EXECUTING to IDLE...");
+
+ bool emulateInputFlushCompletion =
+ !flushPortAsync(kPortIndexInput);
+
+ bool emulateOutputFlushCompletion =
+ !flushPortAsync(kPortIndexOutput);
+
+ if (emulateInputFlushCompletion) {
+ onCmdComplete(OMX_CommandFlush, kPortIndexInput);
+ }
+
+ if (emulateOutputFlushCompletion) {
+ onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
+ }
+ } else {
+ mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
+ mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
+
+ status_t err =
+ mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
+ CHECK_EQ(err, (status_t)OK);
+ }
+
+ while (mState != LOADED && mState != ERROR) {
+ mAsyncCompletion.wait(mLock);
+ }
+
+ if (isError) {
+ // We were in the ERROR state coming in, so restore that now
+ // that we've idled the OMX component.
+ setState(ERROR);
+ }
+
+ break;
+ }
+
+ default:
+ {
+ CHECK(!"should not be here.");
+ break;
+ }
+ }
+
+ if (mLeftOverBuffer) {
+ mLeftOverBuffer->release();
+ mLeftOverBuffer = NULL;
+ }
+
+ mSource->stop();
+
+ CODEC_LOGV("stopped in state %d", mState);
+
+ return OK;
+}
+
+sp<MetaData> OMXCodec::getFormat() {
+ Mutex::Autolock autoLock(mLock);
+
+ return mOutputFormat;
+}
+
+status_t OMXCodec::read(
+ MediaBuffer **buffer, const ReadOptions *options) {
+ status_t err = OK;
+ *buffer = NULL;
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (mState != EXECUTING && mState != RECONFIGURING) {
+ return UNKNOWN_ERROR;
+ }
+
+ bool seeking = false;
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode seekMode;
+ if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
+ seeking = true;
+ }
+
+ if (mInitialBufferSubmit) {
+ mInitialBufferSubmit = false;
+
+ 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();
+
+ if (mState == EXECUTING) {
+ // Otherwise mState == RECONFIGURING and this code will trigger
+ // after the output port is reenabled.
+ fillOutputBuffers();
+ }
+ }
+
+ if (seeking) {
+ while (mState == RECONFIGURING) {
+ if ((err = waitForBufferFilled_l()) != OK) {
+ return err;
+ }
+ }
+
+ if (mState != EXECUTING) {
+ return UNKNOWN_ERROR;
+ }
+
+ CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
+
+ mSignalledEOS = false;
+
+ CHECK(seekTimeUs >= 0);
+ mSeekTimeUs = seekTimeUs;
+ mSeekMode = seekMode;
+
+ mFilledBuffers.clear();
+
+ CHECK_EQ((int)mState, (int)EXECUTING);
+
+ bool emulateInputFlushCompletion = !flushPortAsync(kPortIndexInput);
+ bool emulateOutputFlushCompletion = !flushPortAsync(kPortIndexOutput);
+
+ if (emulateInputFlushCompletion) {
+ onCmdComplete(OMX_CommandFlush, kPortIndexInput);
+ }
+
+ if (emulateOutputFlushCompletion) {
+ onCmdComplete(OMX_CommandFlush, kPortIndexOutput);
+ }
+
+ while (mSeekTimeUs >= 0) {
+ if ((err = waitForBufferFilled_l()) != OK) {
+ return err;
+ }
+ }
+ }
+
+ while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
+ if ((err = waitForBufferFilled_l()) != OK) {
+ return err;
+ }
+ }
+
+ if (mState == ERROR) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (mFilledBuffers.empty()) {
+ return mSignalledEOS ? mFinalStatus : ERROR_END_OF_STREAM;
+ }
+
+ if (mOutputPortSettingsHaveChanged) {
+ mOutputPortSettingsHaveChanged = false;
+
+ return INFO_FORMAT_CHANGED;
+ }
+
+ size_t index = *mFilledBuffers.begin();
+ mFilledBuffers.erase(mFilledBuffers.begin());
+
+ BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
+ CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
+ info->mStatus = OWNED_BY_CLIENT;
+
+ info->mMediaBuffer->add_ref();
+ if (mSkipCutBuffer) {
+ mSkipCutBuffer->submit(info->mMediaBuffer);
+ }
+ *buffer = info->mMediaBuffer;
+
+ return OK;
+}
+
+void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
+ Mutex::Autolock autoLock(mLock);
+
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
+ for (size_t i = 0; i < buffers->size(); ++i) {
+ BufferInfo *info = &buffers->editItemAt(i);
+
+ if (info->mMediaBuffer == buffer) {
+ CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)ENABLED);
+ CHECK_EQ((int)info->mStatus, (int)OWNED_BY_CLIENT);
+
+ info->mStatus = OWNED_BY_US;
+
+ if (buffer->graphicBuffer() == 0) {
+ fillOutputBuffer(info);
+ } else {
+ sp<MetaData> metaData = info->mMediaBuffer->meta_data();
+ int32_t rendered = 0;
+ if (!metaData->findInt32(kKeyRendered, &rendered)) {
+ rendered = 0;
+ }
+ if (!rendered) {
+ status_t err = cancelBufferToNativeWindow(info);
+ if (err < 0) {
+ return;
+ }
+ }
+
+ info->mStatus = OWNED_BY_NATIVE_WINDOW;
+
+ // Dequeue the next buffer from the native window.
+ BufferInfo *nextBufInfo = dequeueBufferFromNativeWindow();
+ if (nextBufInfo == 0) {
+ return;
+ }
+
+ // Give the buffer to the OMX node to fill.
+ fillOutputBuffer(nextBufInfo);
+ }
+ return;
+ }
+ }
+
+ CHECK(!"should not be here.");
+}
+
+static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
+ static const char *kNames[] = {
+ "OMX_IMAGE_CodingUnused",
+ "OMX_IMAGE_CodingAutoDetect",
+ "OMX_IMAGE_CodingJPEG",
+ "OMX_IMAGE_CodingJPEG2K",
+ "OMX_IMAGE_CodingEXIF",
+ "OMX_IMAGE_CodingTIFF",
+ "OMX_IMAGE_CodingGIF",
+ "OMX_IMAGE_CodingPNG",
+ "OMX_IMAGE_CodingLZW",
+ "OMX_IMAGE_CodingBMP",
+ };
+
+ size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+ if (type < 0 || (size_t)type >= numNames) {
+ return "UNKNOWN";
+ } else {
+ return kNames[type];
+ }
+}
+
+static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
+ static const char *kNames[] = {
+ "OMX_COLOR_FormatUnused",
+ "OMX_COLOR_FormatMonochrome",
+ "OMX_COLOR_Format8bitRGB332",
+ "OMX_COLOR_Format12bitRGB444",
+ "OMX_COLOR_Format16bitARGB4444",
+ "OMX_COLOR_Format16bitARGB1555",
+ "OMX_COLOR_Format16bitRGB565",
+ "OMX_COLOR_Format16bitBGR565",
+ "OMX_COLOR_Format18bitRGB666",
+ "OMX_COLOR_Format18bitARGB1665",
+ "OMX_COLOR_Format19bitARGB1666",
+ "OMX_COLOR_Format24bitRGB888",
+ "OMX_COLOR_Format24bitBGR888",
+ "OMX_COLOR_Format24bitARGB1887",
+ "OMX_COLOR_Format25bitARGB1888",
+ "OMX_COLOR_Format32bitBGRA8888",
+ "OMX_COLOR_Format32bitARGB8888",
+ "OMX_COLOR_FormatYUV411Planar",
+ "OMX_COLOR_FormatYUV411PackedPlanar",
+ "OMX_COLOR_FormatYUV420Planar",
+ "OMX_COLOR_FormatYUV420PackedPlanar",
+ "OMX_COLOR_FormatYUV420SemiPlanar",
+ "OMX_COLOR_FormatYUV422Planar",
+ "OMX_COLOR_FormatYUV422PackedPlanar",
+ "OMX_COLOR_FormatYUV422SemiPlanar",
+ "OMX_COLOR_FormatYCbYCr",
+ "OMX_COLOR_FormatYCrYCb",
+ "OMX_COLOR_FormatCbYCrY",
+ "OMX_COLOR_FormatCrYCbY",
+ "OMX_COLOR_FormatYUV444Interleaved",
+ "OMX_COLOR_FormatRawBayer8bit",
+ "OMX_COLOR_FormatRawBayer10bit",
+ "OMX_COLOR_FormatRawBayer8bitcompressed",
+ "OMX_COLOR_FormatL2",
+ "OMX_COLOR_FormatL4",
+ "OMX_COLOR_FormatL8",
+ "OMX_COLOR_FormatL16",
+ "OMX_COLOR_FormatL24",
+ "OMX_COLOR_FormatL32",
+ "OMX_COLOR_FormatYUV420PackedSemiPlanar",
+ "OMX_COLOR_FormatYUV422PackedSemiPlanar",
+ "OMX_COLOR_Format18BitBGR666",
+ "OMX_COLOR_Format24BitARGB6666",
+ "OMX_COLOR_Format24BitABGR6666",
+ };
+
+ size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+ if (type == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
+ return "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar";
+ } else if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
+ return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
+ } else if (type < 0 || (size_t)type >= numNames) {
+ return "UNKNOWN";
+ } else {
+ return kNames[type];
+ }
+}
+
+static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
+ static const char *kNames[] = {
+ "OMX_VIDEO_CodingUnused",
+ "OMX_VIDEO_CodingAutoDetect",
+ "OMX_VIDEO_CodingMPEG2",
+ "OMX_VIDEO_CodingH263",
+ "OMX_VIDEO_CodingMPEG4",
+ "OMX_VIDEO_CodingWMV",
+ "OMX_VIDEO_CodingRV",
+ "OMX_VIDEO_CodingAVC",
+ "OMX_VIDEO_CodingMJPEG",
+ };
+
+ size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+ if (type < 0 || (size_t)type >= numNames) {
+ return "UNKNOWN";
+ } else {
+ return kNames[type];
+ }
+}
+
+static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
+ static const char *kNames[] = {
+ "OMX_AUDIO_CodingUnused",
+ "OMX_AUDIO_CodingAutoDetect",
+ "OMX_AUDIO_CodingPCM",
+ "OMX_AUDIO_CodingADPCM",
+ "OMX_AUDIO_CodingAMR",
+ "OMX_AUDIO_CodingGSMFR",
+ "OMX_AUDIO_CodingGSMEFR",
+ "OMX_AUDIO_CodingGSMHR",
+ "OMX_AUDIO_CodingPDCFR",
+ "OMX_AUDIO_CodingPDCEFR",
+ "OMX_AUDIO_CodingPDCHR",
+ "OMX_AUDIO_CodingTDMAFR",
+ "OMX_AUDIO_CodingTDMAEFR",
+ "OMX_AUDIO_CodingQCELP8",
+ "OMX_AUDIO_CodingQCELP13",
+ "OMX_AUDIO_CodingEVRC",
+ "OMX_AUDIO_CodingSMV",
+ "OMX_AUDIO_CodingG711",
+ "OMX_AUDIO_CodingG723",
+ "OMX_AUDIO_CodingG726",
+ "OMX_AUDIO_CodingG729",
+ "OMX_AUDIO_CodingAAC",
+ "OMX_AUDIO_CodingMP3",
+ "OMX_AUDIO_CodingSBC",
+ "OMX_AUDIO_CodingVORBIS",
+ "OMX_AUDIO_CodingWMA",
+ "OMX_AUDIO_CodingRA",
+ "OMX_AUDIO_CodingMIDI",
+ };
+
+ size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+ if (type < 0 || (size_t)type >= numNames) {
+ return "UNKNOWN";
+ } else {
+ return kNames[type];
+ }
+}
+
+static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
+ static const char *kNames[] = {
+ "OMX_AUDIO_PCMModeLinear",
+ "OMX_AUDIO_PCMModeALaw",
+ "OMX_AUDIO_PCMModeMULaw",
+ };
+
+ size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+ if (type < 0 || (size_t)type >= numNames) {
+ return "UNKNOWN";
+ } else {
+ return kNames[type];
+ }
+}
+
+static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) {
+ static const char *kNames[] = {
+ "OMX_AUDIO_AMRBandModeUnused",
+ "OMX_AUDIO_AMRBandModeNB0",
+ "OMX_AUDIO_AMRBandModeNB1",
+ "OMX_AUDIO_AMRBandModeNB2",
+ "OMX_AUDIO_AMRBandModeNB3",
+ "OMX_AUDIO_AMRBandModeNB4",
+ "OMX_AUDIO_AMRBandModeNB5",
+ "OMX_AUDIO_AMRBandModeNB6",
+ "OMX_AUDIO_AMRBandModeNB7",
+ "OMX_AUDIO_AMRBandModeWB0",
+ "OMX_AUDIO_AMRBandModeWB1",
+ "OMX_AUDIO_AMRBandModeWB2",
+ "OMX_AUDIO_AMRBandModeWB3",
+ "OMX_AUDIO_AMRBandModeWB4",
+ "OMX_AUDIO_AMRBandModeWB5",
+ "OMX_AUDIO_AMRBandModeWB6",
+ "OMX_AUDIO_AMRBandModeWB7",
+ "OMX_AUDIO_AMRBandModeWB8",
+ };
+
+ size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+ if (type < 0 || (size_t)type >= numNames) {
+ return "UNKNOWN";
+ } else {
+ return kNames[type];
+ }
+}
+
+static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) {
+ static const char *kNames[] = {
+ "OMX_AUDIO_AMRFrameFormatConformance",
+ "OMX_AUDIO_AMRFrameFormatIF1",
+ "OMX_AUDIO_AMRFrameFormatIF2",
+ "OMX_AUDIO_AMRFrameFormatFSF",
+ "OMX_AUDIO_AMRFrameFormatRTPPayload",
+ "OMX_AUDIO_AMRFrameFormatITU",
+ };
+
+ size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+ if (type < 0 || (size_t)type >= numNames) {
+ return "UNKNOWN";
+ } else {
+ return kNames[type];
+ }
+}
+
+void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = portIndex;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, (status_t)OK);
+
+ printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
+
+ CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
+ || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
+
+ printf(" nBufferCountActual = %ld\n", def.nBufferCountActual);
+ printf(" nBufferCountMin = %ld\n", def.nBufferCountMin);
+ printf(" nBufferSize = %ld\n", def.nBufferSize);
+
+ switch (def.eDomain) {
+ case OMX_PortDomainImage:
+ {
+ const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
+
+ printf("\n");
+ printf(" // Image\n");
+ printf(" nFrameWidth = %ld\n", imageDef->nFrameWidth);
+ printf(" nFrameHeight = %ld\n", imageDef->nFrameHeight);
+ printf(" nStride = %ld\n", imageDef->nStride);
+
+ printf(" eCompressionFormat = %s\n",
+ imageCompressionFormatString(imageDef->eCompressionFormat));
+
+ printf(" eColorFormat = %s\n",
+ colorFormatString(imageDef->eColorFormat));
+
+ break;
+ }
+
+ case OMX_PortDomainVideo:
+ {
+ OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
+
+ printf("\n");
+ printf(" // Video\n");
+ printf(" nFrameWidth = %ld\n", videoDef->nFrameWidth);
+ printf(" nFrameHeight = %ld\n", videoDef->nFrameHeight);
+ printf(" nStride = %ld\n", videoDef->nStride);
+
+ printf(" eCompressionFormat = %s\n",
+ videoCompressionFormatString(videoDef->eCompressionFormat));
+
+ printf(" eColorFormat = %s\n",
+ colorFormatString(videoDef->eColorFormat));
+
+ break;
+ }
+
+ case OMX_PortDomainAudio:
+ {
+ OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
+
+ printf("\n");
+ printf(" // Audio\n");
+ printf(" eEncoding = %s\n",
+ audioCodingTypeString(audioDef->eEncoding));
+
+ if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
+ OMX_AUDIO_PARAM_PCMMODETYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = portIndex;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
+ CHECK_EQ(err, (status_t)OK);
+
+ printf(" nSamplingRate = %ld\n", params.nSamplingRate);
+ printf(" nChannels = %ld\n", params.nChannels);
+ printf(" bInterleaved = %d\n", params.bInterleaved);
+ printf(" nBitPerSample = %ld\n", params.nBitPerSample);
+
+ printf(" eNumData = %s\n",
+ params.eNumData == OMX_NumericalDataSigned
+ ? "signed" : "unsigned");
+
+ printf(" ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
+ } else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) {
+ OMX_AUDIO_PARAM_AMRTYPE amr;
+ InitOMXParams(&amr);
+ amr.nPortIndex = portIndex;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
+ CHECK_EQ(err, (status_t)OK);
+
+ printf(" nChannels = %ld\n", amr.nChannels);
+ printf(" eAMRBandMode = %s\n",
+ amrBandModeString(amr.eAMRBandMode));
+ printf(" eAMRFrameFormat = %s\n",
+ amrFrameFormatString(amr.eAMRFrameFormat));
+ }
+
+ break;
+ }
+
+ default:
+ {
+ printf(" // Unknown\n");
+ break;
+ }
+ }
+
+ printf("}\n");
+}
+
+status_t OMXCodec::initNativeWindow() {
+ // Enable use of a GraphicBuffer as the output for this node. This must
+ // happen before getting the IndexParamPortDefinition parameter because it
+ // will affect the pixel format that the node reports.
+ status_t err = mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
+ if (err != 0) {
+ return err;
+ }
+
+ return OK;
+}
+
+void OMXCodec::initNativeWindowCrop() {
+ int32_t left, top, right, bottom;
+
+ CHECK(mOutputFormat->findRect(
+ kKeyCropRect,
+ &left, &top, &right, &bottom));
+
+ android_native_rect_t crop;
+ crop.left = left;
+ crop.top = top;
+ crop.right = right + 1;
+ crop.bottom = bottom + 1;
+
+ // We'll ignore any errors here, if the surface is
+ // already invalid, we'll know soon enough.
+ native_window_set_crop(mNativeWindow.get(), &crop);
+}
+
+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);
+ def.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, (status_t)OK);
+
+ switch (def.eDomain) {
+ case OMX_PortDomainImage:
+ {
+ OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
+ CHECK_EQ((int)imageDef->eCompressionFormat,
+ (int)OMX_IMAGE_CodingUnused);
+
+ mOutputFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+ mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
+ mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
+ mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
+ break;
+ }
+
+ case OMX_PortDomainAudio:
+ {
+ OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
+
+ if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
+ OMX_AUDIO_PARAM_PCMMODETYPE params;
+ InitOMXParams(&params);
+ params.nPortIndex = kPortIndexOutput;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
+ CHECK_EQ(err, (status_t)OK);
+
+ CHECK_EQ((int)params.eNumData, (int)OMX_NumericalDataSigned);
+ CHECK_EQ(params.nBitPerSample, 16u);
+ CHECK_EQ((int)params.ePCMMode, (int)OMX_AUDIO_PCMModeLinear);
+
+ int32_t numChannels, sampleRate;
+ inputFormat->findInt32(kKeyChannelCount, &numChannels);
+ inputFormat->findInt32(kKeySampleRate, &sampleRate);
+
+ if ((OMX_U32)numChannels != params.nChannels) {
+ ALOGV("Codec outputs a different number of channels than "
+ "the input stream contains (contains %d channels, "
+ "codec outputs %ld channels).",
+ numChannels, params.nChannels);
+ }
+
+ if (sampleRate != (int32_t)params.nSamplingRate) {
+ ALOGV("Codec outputs at different sampling rate than "
+ "what the input stream contains (contains data at "
+ "%d Hz, codec outputs %lu Hz)",
+ sampleRate, params.nSamplingRate);
+ }
+
+ mOutputFormat->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+
+ // Use the codec-advertised number of channels, as some
+ // codecs appear to output stereo even if the input data is
+ // mono. If we know the codec lies about this information,
+ // use the actual number of channels instead.
+ mOutputFormat->setInt32(
+ kKeyChannelCount,
+ (mQuirks & kDecoderLiesAboutNumberOfChannels)
+ ? numChannels : params.nChannels);
+
+ mOutputFormat->setInt32(kKeySampleRate, params.nSamplingRate);
+ } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
+ OMX_AUDIO_PARAM_AMRTYPE amr;
+ InitOMXParams(&amr);
+ amr.nPortIndex = kPortIndexOutput;
+
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioAmr, &amr, sizeof(amr));
+ CHECK_EQ(err, (status_t)OK);
+
+ CHECK_EQ(amr.nChannels, 1u);
+ mOutputFormat->setInt32(kKeyChannelCount, 1);
+
+ if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeNB0
+ && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeNB7) {
+ mOutputFormat->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
+ mOutputFormat->setInt32(kKeySampleRate, 8000);
+ } else if (amr.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0
+ && amr.eAMRBandMode <= OMX_AUDIO_AMRBandModeWB8) {
+ mOutputFormat->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
+ mOutputFormat->setInt32(kKeySampleRate, 16000);
+ } else {
+ CHECK(!"Unknown AMR band mode.");
+ }
+ } 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.");
+ }
+ break;
+ }
+
+ case OMX_PortDomainVideo:
+ {
+ OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
+
+ if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
+ mOutputFormat->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+ } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
+ mOutputFormat->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+ } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
+ mOutputFormat->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+ } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
+ mOutputFormat->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+ } else {
+ CHECK(!"Unknown compression format.");
+ }
+
+ mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
+ mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
+ mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
+
+ if (!mIsEncoder) {
+ OMX_CONFIG_RECTTYPE rect;
+ InitOMXParams(&rect);
+ rect.nPortIndex = kPortIndexOutput;
+ status_t err =
+ mOMX->getConfig(
+ mNode, OMX_IndexConfigCommonOutputCrop,
+ &rect, sizeof(rect));
+
+ CODEC_LOGI(
+ "video dimensions are %ld x %ld",
+ video_def->nFrameWidth, video_def->nFrameHeight);
+
+ if (err == OK) {
+ CHECK_GE(rect.nLeft, 0);
+ CHECK_GE(rect.nTop, 0);
+ CHECK_GE(rect.nWidth, 0u);
+ CHECK_GE(rect.nHeight, 0u);
+ CHECK_LE(rect.nLeft + rect.nWidth - 1, video_def->nFrameWidth);
+ CHECK_LE(rect.nTop + rect.nHeight - 1, video_def->nFrameHeight);
+
+ mOutputFormat->setRect(
+ kKeyCropRect,
+ rect.nLeft,
+ rect.nTop,
+ rect.nLeft + rect.nWidth - 1,
+ rect.nTop + rect.nHeight - 1);
+
+ CODEC_LOGI(
+ "Crop rect is %ld x %ld @ (%ld, %ld)",
+ rect.nWidth, rect.nHeight, rect.nLeft, rect.nTop);
+ } else {
+ mOutputFormat->setRect(
+ kKeyCropRect,
+ 0, 0,
+ video_def->nFrameWidth - 1,
+ video_def->nFrameHeight - 1);
+ }
+
+ if (mNativeWindow != NULL) {
+ initNativeWindowCrop();
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ CHECK(!"should not be here, neither audio nor video.");
+ break;
+ }
+ }
+
+ // If the input format contains rotation information, flag the output
+ // format accordingly.
+
+ int32_t rotationDegrees;
+ if (mSource->getFormat()->findInt32(kKeyRotation, &rotationDegrees)) {
+ mOutputFormat->setInt32(kKeyRotation, rotationDegrees);
+ }
+}
+
+status_t OMXCodec::pause() {
+ Mutex::Autolock autoLock(mLock);
+
+ mPaused = true;
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+status_t QueryCodecs(
+ const sp<IOMX> &omx,
+ const char *mime, bool queryDecoders, bool hwCodecOnly,
+ Vector<CodecCapabilities> *results) {
+ Vector<String8> matchingCodecs;
+ results->clear();
+
+ OMXCodec::findMatchingCodecs(mime,
+ !queryDecoders /*createEncoder*/,
+ NULL /*matchComponentName*/,
+ hwCodecOnly ? OMXCodec::kHardwareCodecsOnly : 0 /*flags*/,
+ &matchingCodecs);
+
+ for (size_t c = 0; c < matchingCodecs.size(); c++) {
+ const char *componentName = matchingCodecs.itemAt(c).string();
+
+ if (strncmp(componentName, "OMX.", 4)) {
+ // Not an OpenMax component but a software codec.
+
+ results->push();
+ CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
+ caps->mComponentName = componentName;
+ continue;
+ }
+
+ sp<OMXCodecObserver> observer = new OMXCodecObserver;
+ IOMX::node_id node;
+ status_t err = omx->allocateNode(componentName, observer, &node);
+
+ if (err != OK) {
+ continue;
+ }
+
+ OMXCodec::setComponentRole(omx, node, !queryDecoders, mime);
+
+ results->push();
+ CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
+ caps->mComponentName = componentName;
+
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ InitOMXParams(&param);
+
+ param.nPortIndex = queryDecoders ? 0 : 1;
+
+ for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
+ err = omx->getParameter(
+ node, OMX_IndexParamVideoProfileLevelQuerySupported,
+ &param, sizeof(param));
+
+ if (err != OK) {
+ break;
+ }
+
+ CodecProfileLevel profileLevel;
+ profileLevel.mProfile = param.eProfile;
+ profileLevel.mLevel = param.eLevel;
+
+ caps->mProfileLevels.push(profileLevel);
+ }
+
+ // Color format query
+ OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
+ InitOMXParams(&portFormat);
+ portFormat.nPortIndex = queryDecoders ? 1 : 0;
+ for (portFormat.nIndex = 0;; ++portFormat.nIndex) {
+ err = omx->getParameter(
+ node, OMX_IndexParamVideoPortFormat,
+ &portFormat, sizeof(portFormat));
+ if (err != OK) {
+ break;
+ }
+ caps->mColorFormats.push(portFormat.eColorFormat);
+ }
+
+ CHECK_EQ(omx->freeNode(node), (status_t)OK);
+ }
+
+ return OK;
+}
+
+status_t QueryCodecs(
+ const sp<IOMX> &omx,
+ const char *mimeType, bool queryDecoders,
+ Vector<CodecCapabilities> *results) {
+ return QueryCodecs(omx, mimeType, queryDecoders, false /*hwCodecOnly*/, results);
+}
+
+void OMXCodec::restorePatchedDataPointer(BufferInfo *info) {
+ CHECK(mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames));
+ CHECK(mOMXLivesLocally);
+
+ OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)info->mBuffer;
+ header->pBuffer = (OMX_U8 *)info->mData;
+}
+
+} // namespace android
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
new file mode 100644
index 0000000..5e79e78
--- /dev/null
+++ b/media/libstagefright/OggExtractor.cpp
@@ -0,0 +1,1027 @@
+/*
+ * 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 "OggExtractor"
+#include <utils/Log.h>
+
+#include "include/OggExtractor.h"
+
+#include <cutils/properties.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+#include <utils/String8.h>
+
+extern "C" {
+ #include <Tremolo/codec_internal.h>
+
+ int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
+ int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
+ int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
+}
+
+namespace android {
+
+struct OggSource : public MediaSource {
+ OggSource(const sp<OggExtractor> &extractor);
+
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+protected:
+ virtual ~OggSource();
+
+private:
+ sp<OggExtractor> mExtractor;
+ bool mStarted;
+
+ OggSource(const OggSource &);
+ OggSource &operator=(const OggSource &);
+};
+
+struct MyVorbisExtractor {
+ MyVorbisExtractor(const sp<DataSource> &source);
+ virtual ~MyVorbisExtractor();
+
+ sp<MetaData> getFormat() const;
+
+ // Returns an approximate bitrate in bits per second.
+ uint64_t approxBitrate();
+
+ status_t seekToTime(int64_t timeUs);
+ status_t seekToOffset(off64_t offset);
+ status_t readNextPacket(MediaBuffer **buffer);
+
+ status_t init();
+
+ sp<MetaData> getFileMetaData() { return mFileMeta; }
+
+private:
+ struct Page {
+ uint64_t mGranulePosition;
+ uint32_t mSerialNo;
+ uint32_t mPageNo;
+ uint8_t mFlags;
+ uint8_t mNumSegments;
+ uint8_t mLace[255];
+ };
+
+ struct TOCEntry {
+ off64_t mPageOffset;
+ int64_t mTimeUs;
+ };
+
+ sp<DataSource> mSource;
+ off64_t mOffset;
+ Page mCurrentPage;
+ uint64_t mPrevGranulePosition;
+ size_t mCurrentPageSize;
+ bool mFirstPacketInPage;
+ uint64_t mCurrentPageSamples;
+ size_t mNextLaceIndex;
+
+ off64_t mFirstDataOffset;
+
+ vorbis_info mVi;
+ vorbis_comment mVc;
+
+ sp<MetaData> mMeta;
+ sp<MetaData> mFileMeta;
+
+ Vector<TOCEntry> mTableOfContents;
+
+ ssize_t readPage(off64_t offset, Page *page);
+ status_t findNextPage(off64_t startOffset, off64_t *pageOffset);
+
+ status_t verifyHeader(
+ MediaBuffer *buffer, uint8_t type);
+
+ void parseFileMetaData();
+
+ status_t findPrevGranulePosition(off64_t pageOffset, uint64_t *granulePos);
+
+ void buildTableOfContents();
+
+ MyVorbisExtractor(const MyVorbisExtractor &);
+ MyVorbisExtractor &operator=(const MyVorbisExtractor &);
+};
+
+static void extractAlbumArt(
+ const sp<MetaData> &fileMeta, const void *data, size_t size);
+
+////////////////////////////////////////////////////////////////////////////////
+
+OggSource::OggSource(const sp<OggExtractor> &extractor)
+ : mExtractor(extractor),
+ mStarted(false) {
+}
+
+OggSource::~OggSource() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+sp<MetaData> OggSource::getFormat() {
+ return mExtractor->mImpl->getFormat();
+}
+
+status_t OggSource::start(MetaData *params) {
+ if (mStarted) {
+ return INVALID_OPERATION;
+ }
+
+ mStarted = true;
+
+ return OK;
+}
+
+status_t OggSource::stop() {
+ mStarted = false;
+
+ return OK;
+}
+
+status_t OggSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+ if (mExtractor->mImpl->seekToTime(seekTimeUs) != OK) {
+ return ERROR_END_OF_STREAM;
+ }
+ }
+
+ MediaBuffer *packet;
+ status_t err = mExtractor->mImpl->readNextPacket(&packet);
+
+ if (err != OK) {
+ return err;
+ }
+
+#if 0
+ int64_t timeUs;
+ if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) {
+ ALOGI("found time = %lld us", timeUs);
+ } else {
+ ALOGI("NO time");
+ }
+#endif
+
+ packet->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+
+ *out = packet;
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source)
+ : mSource(source),
+ mOffset(0),
+ mPrevGranulePosition(0),
+ mCurrentPageSize(0),
+ mFirstPacketInPage(true),
+ mCurrentPageSamples(0),
+ 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 {
+ return mMeta;
+}
+
+status_t MyVorbisExtractor::findNextPage(
+ off64_t startOffset, off64_t *pageOffset) {
+ *pageOffset = startOffset;
+
+ for (;;) {
+ char signature[4];
+ ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
+
+ if (n < 4) {
+ *pageOffset = 0;
+
+ return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
+ }
+
+ if (!memcmp(signature, "OggS", 4)) {
+ if (*pageOffset > startOffset) {
+ ALOGV("skipped %lld bytes of junk to reach next frame",
+ *pageOffset - startOffset);
+ }
+
+ return OK;
+ }
+
+ ++*pageOffset;
+ }
+}
+
+// Given the offset of the "current" page, find the page immediately preceding
+// it (if any) and return its granule position.
+// To do this we back up from the "current" page's offset until we find any
+// page preceding it and then scan forward to just before the current page.
+status_t MyVorbisExtractor::findPrevGranulePosition(
+ off64_t pageOffset, uint64_t *granulePos) {
+ *granulePos = 0;
+
+ off64_t prevPageOffset = 0;
+ off64_t prevGuess = pageOffset;
+ for (;;) {
+ if (prevGuess >= 5000) {
+ prevGuess -= 5000;
+ } else {
+ prevGuess = 0;
+ }
+
+ ALOGV("backing up %lld bytes", pageOffset - prevGuess);
+
+ status_t err = findNextPage(prevGuess, &prevPageOffset);
+ if (err != OK) {
+ return err;
+ }
+
+ if (prevPageOffset < pageOffset || prevGuess == 0) {
+ break;
+ }
+ }
+
+ if (prevPageOffset == pageOffset) {
+ // We did not find a page preceding this one.
+ return UNKNOWN_ERROR;
+ }
+
+ ALOGV("prevPageOffset at %lld, pageOffset at %lld",
+ prevPageOffset, pageOffset);
+
+ for (;;) {
+ Page prevPage;
+ ssize_t n = readPage(prevPageOffset, &prevPage);
+
+ if (n <= 0) {
+ return (status_t)n;
+ }
+
+ prevPageOffset += n;
+
+ if (prevPageOffset == pageOffset) {
+ *granulePos = prevPage.mGranulePosition;
+ return OK;
+ }
+ }
+}
+
+status_t MyVorbisExtractor::seekToTime(int64_t timeUs) {
+ if (mTableOfContents.isEmpty()) {
+ // Perform approximate seeking based on avg. bitrate.
+
+ off64_t pos = timeUs * approxBitrate() / 8000000ll;
+
+ ALOGV("seeking to offset %lld", pos);
+ return seekToOffset(pos);
+ }
+
+ size_t left = 0;
+ size_t right = mTableOfContents.size();
+ while (left < right) {
+ size_t center = left / 2 + right / 2 + (left & right & 1);
+
+ const TOCEntry &entry = mTableOfContents.itemAt(center);
+
+ if (timeUs < entry.mTimeUs) {
+ right = center;
+ } else if (timeUs > entry.mTimeUs) {
+ left = center + 1;
+ } else {
+ left = right = center;
+ break;
+ }
+ }
+
+ const TOCEntry &entry = mTableOfContents.itemAt(left);
+
+ ALOGV("seeking to entry %d / %d at offset %lld",
+ left, mTableOfContents.size(), entry.mPageOffset);
+
+ return seekToOffset(entry.mPageOffset);
+}
+
+status_t MyVorbisExtractor::seekToOffset(off64_t offset) {
+ if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) {
+ // Once we know where the actual audio data starts (past the headers)
+ // don't ever seek to anywhere before that.
+ offset = mFirstDataOffset;
+ }
+
+ off64_t pageOffset;
+ status_t err = findNextPage(offset, &pageOffset);
+
+ if (err != OK) {
+ return err;
+ }
+
+ // We found the page we wanted to seek to, but we'll also need
+ // the page preceding it to determine how many valid samples are on
+ // this page.
+ findPrevGranulePosition(pageOffset, &mPrevGranulePosition);
+
+ mOffset = pageOffset;
+
+ mCurrentPageSize = 0;
+ mFirstPacketInPage = true;
+ mCurrentPageSamples = 0;
+ mCurrentPage.mNumSegments = 0;
+ mNextLaceIndex = 0;
+
+ // XXX what if new page continues packet from last???
+
+ return OK;
+}
+
+ssize_t MyVorbisExtractor::readPage(off64_t offset, Page *page) {
+ uint8_t header[27];
+ ssize_t n;
+ if ((n = mSource->readAt(offset, header, sizeof(header)))
+ < (ssize_t)sizeof(header)) {
+ ALOGV("failed to read %d bytes at offset 0x%016llx, got %ld bytes",
+ sizeof(header), offset, n);
+
+ if (n < 0) {
+ return n;
+ } else if (n == 0) {
+ return ERROR_END_OF_STREAM;
+ } else {
+ return ERROR_IO;
+ }
+ }
+
+ if (memcmp(header, "OggS", 4)) {
+ return ERROR_MALFORMED;
+ }
+
+ if (header[4] != 0) {
+ // Wrong version.
+
+ return ERROR_UNSUPPORTED;
+ }
+
+ page->mFlags = header[5];
+
+ if (page->mFlags & ~7) {
+ // Only bits 0-2 are defined in version 0.
+ return ERROR_MALFORMED;
+ }
+
+ page->mGranulePosition = U64LE_AT(&header[6]);
+
+#if 0
+ printf("granulePosition = %llu (0x%llx)\n",
+ page->mGranulePosition, page->mGranulePosition);
+#endif
+
+ page->mSerialNo = U32LE_AT(&header[14]);
+ page->mPageNo = U32LE_AT(&header[18]);
+
+ page->mNumSegments = header[26];
+ if (mSource->readAt(
+ offset + sizeof(header), page->mLace, page->mNumSegments)
+ < (ssize_t)page->mNumSegments) {
+ return ERROR_IO;
+ }
+
+ size_t totalSize = 0;;
+ for (size_t i = 0; i < page->mNumSegments; ++i) {
+ totalSize += page->mLace[i];
+ }
+
+#if 0
+ String8 tmp;
+ for (size_t i = 0; i < page->mNumSegments; ++i) {
+ char x[32];
+ sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]);
+
+ tmp.append(x);
+ }
+
+ ALOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string());
+#endif
+
+ return sizeof(header) + page->mNumSegments + totalSize;
+}
+
+status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) {
+ *out = NULL;
+
+ MediaBuffer *buffer = NULL;
+ int64_t timeUs = -1;
+
+ for (;;) {
+ size_t i;
+ size_t packetSize = 0;
+ bool gotFullPacket = false;
+ for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) {
+ uint8_t lace = mCurrentPage.mLace[i];
+
+ packetSize += lace;
+
+ if (lace < 255) {
+ gotFullPacket = true;
+ ++i;
+ break;
+ }
+ }
+
+ if (mNextLaceIndex < mCurrentPage.mNumSegments) {
+ off64_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments;
+ for (size_t j = 0; j < mNextLaceIndex; ++j) {
+ dataOffset += mCurrentPage.mLace[j];
+ }
+
+ size_t fullSize = packetSize;
+ if (buffer != NULL) {
+ fullSize += buffer->range_length();
+ }
+ MediaBuffer *tmp = new MediaBuffer(fullSize);
+ if (buffer != NULL) {
+ memcpy(tmp->data(), buffer->data(), buffer->range_length());
+ tmp->set_range(0, buffer->range_length());
+ buffer->release();
+ } else {
+ // XXX Not only is this not technically the correct time for
+ // this packet, we also stamp every packet in this page
+ // with the same time. This needs fixing later.
+
+ if (mVi.rate) {
+ // Rate may not have been initialized yet if we're currently
+ // reading the configuration packets...
+ // Fortunately, the timestamp doesn't matter for those.
+ timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate;
+ }
+ tmp->set_range(0, 0);
+ }
+ buffer = tmp;
+
+ ssize_t n = mSource->readAt(
+ dataOffset,
+ (uint8_t *)buffer->data() + buffer->range_length(),
+ packetSize);
+
+ if (n < (ssize_t)packetSize) {
+ ALOGV("failed to read %d bytes at 0x%016llx, got %ld bytes",
+ packetSize, dataOffset, n);
+ return ERROR_IO;
+ }
+
+ buffer->set_range(0, fullSize);
+
+ mNextLaceIndex = i;
+
+ if (gotFullPacket) {
+ // We've just read the entire packet.
+
+ if (timeUs >= 0) {
+ buffer->meta_data()->setInt64(kKeyTime, timeUs);
+ }
+
+ if (mFirstPacketInPage) {
+ buffer->meta_data()->setInt32(
+ kKeyValidSamples, mCurrentPageSamples);
+ mFirstPacketInPage = false;
+ }
+
+ *out = buffer;
+
+ return OK;
+ }
+
+ // fall through, the buffer now contains the start of the packet.
+ }
+
+ CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments);
+
+ mOffset += mCurrentPageSize;
+ ssize_t n = readPage(mOffset, &mCurrentPage);
+
+ if (n <= 0) {
+ if (buffer) {
+ buffer->release();
+ buffer = NULL;
+ }
+
+ ALOGV("readPage returned %ld", n);
+
+ return n < 0 ? n : (status_t)ERROR_END_OF_STREAM;
+ }
+
+ mCurrentPageSamples =
+ mCurrentPage.mGranulePosition - mPrevGranulePosition;
+ mFirstPacketInPage = true;
+
+ mPrevGranulePosition = mCurrentPage.mGranulePosition;
+
+ mCurrentPageSize = n;
+ mNextLaceIndex = 0;
+
+ if (buffer != NULL) {
+ if ((mCurrentPage.mFlags & 1) == 0) {
+ // This page does not continue the packet, i.e. the packet
+ // is already complete.
+
+ if (timeUs >= 0) {
+ buffer->meta_data()->setInt64(kKeyTime, timeUs);
+ }
+
+ buffer->meta_data()->setInt32(
+ kKeyValidSamples, mCurrentPageSamples);
+ mFirstPacketInPage = false;
+
+ *out = buffer;
+
+ return OK;
+ }
+ }
+ }
+}
+
+status_t MyVorbisExtractor::init() {
+ mMeta = new MetaData;
+ mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
+
+ MediaBuffer *packet;
+ status_t err;
+ if ((err = readNextPacket(&packet)) != OK) {
+ return err;
+ }
+ ALOGV("read packet of size %d\n", packet->range_length());
+ err = verifyHeader(packet, 1);
+ packet->release();
+ packet = NULL;
+ if (err != OK) {
+ return err;
+ }
+
+ if ((err = readNextPacket(&packet)) != OK) {
+ return err;
+ }
+ ALOGV("read packet of size %d\n", packet->range_length());
+ err = verifyHeader(packet, 3);
+ packet->release();
+ packet = NULL;
+ if (err != OK) {
+ return err;
+ }
+
+ if ((err = readNextPacket(&packet)) != OK) {
+ return err;
+ }
+ ALOGV("read packet of size %d\n", packet->range_length());
+ err = verifyHeader(packet, 5);
+ packet->release();
+ packet = NULL;
+ if (err != OK) {
+ return err;
+ }
+
+ mFirstDataOffset = mOffset + mCurrentPageSize;
+
+ off64_t size;
+ uint64_t lastGranulePosition;
+ if (!(mSource->flags() & DataSource::kIsCachingDataSource)
+ && mSource->getSize(&size) == OK
+ && findPrevGranulePosition(size, &lastGranulePosition) == OK) {
+ // Let's assume it's cheap to seek to the end.
+ // The granule position of the final page in the stream will
+ // give us the exact duration of the content, something that
+ // we can only approximate using avg. bitrate if seeking to
+ // the end is too expensive or impossible (live streaming).
+
+ int64_t durationUs = lastGranulePosition * 1000000ll / mVi.rate;
+
+ mMeta->setInt64(kKeyDuration, durationUs);
+
+ buildTableOfContents();
+ }
+
+ return OK;
+}
+
+void MyVorbisExtractor::buildTableOfContents() {
+ off64_t offset = mFirstDataOffset;
+ Page page;
+ ssize_t pageSize;
+ while ((pageSize = readPage(offset, &page)) > 0) {
+ mTableOfContents.push();
+
+ TOCEntry &entry =
+ mTableOfContents.editItemAt(mTableOfContents.size() - 1);
+
+ entry.mPageOffset = offset;
+ entry.mTimeUs = page.mGranulePosition * 1000000ll / mVi.rate;
+
+ offset += (size_t)pageSize;
+ }
+
+ // Limit the maximum amount of RAM we spend on the table of contents,
+ // if necessary thin out the table evenly to trim it down to maximum
+ // size.
+
+ static const size_t kMaxTOCSize = 8192;
+ static const size_t kMaxNumTOCEntries = kMaxTOCSize / sizeof(TOCEntry);
+
+ size_t numerator = mTableOfContents.size();
+
+ if (numerator > kMaxNumTOCEntries) {
+ size_t denom = numerator - kMaxNumTOCEntries;
+
+ size_t accum = 0;
+ for (ssize_t i = mTableOfContents.size() - 1; i >= 0; --i) {
+ accum += denom;
+ if (accum >= numerator) {
+ mTableOfContents.removeAt(i);
+ accum -= numerator;
+ }
+ }
+ }
+}
+
+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();
+
+ if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) {
+ return ERROR_MALFORMED;
+ }
+
+ ogg_buffer buf;
+ buf.data = (uint8_t *)data;
+ buf.size = size;
+ buf.refcount = 1;
+ buf.ptr.owner = NULL;
+
+ ogg_reference ref;
+ ref.buffer = &buf;
+ ref.begin = 0;
+ ref.length = size;
+ ref.next = NULL;
+
+ oggpack_buffer bits;
+ oggpack_readinit(&bits, &ref);
+
+ CHECK_EQ(oggpack_read(&bits, 8), type);
+ for (size_t i = 0; i < 6; ++i) {
+ oggpack_read(&bits, 8); // skip 'vorbis'
+ }
+
+ switch (type) {
+ case 1:
+ {
+ CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits));
+
+ mMeta->setData(kKeyVorbisInfo, 0, data, size);
+ mMeta->setInt32(kKeySampleRate, mVi.rate);
+ mMeta->setInt32(kKeyChannelCount, mVi.channels);
+
+ ALOGV("lower-bitrate = %ld", mVi.bitrate_lower);
+ ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
+ ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
+ ALOGV("window-bitrate = %ld", mVi.bitrate_window);
+
+ off64_t size;
+ if (mSource->getSize(&size) == OK) {
+ uint64_t bps = approxBitrate();
+ if (bps != 0) {
+ mMeta->setInt64(kKeyDuration, size * 8000000ll / bps);
+ }
+ }
+ break;
+ }
+
+ case 3:
+ {
+ if (0 != _vorbis_unpack_comment(&mVc, &bits)) {
+ return ERROR_MALFORMED;
+ }
+
+ parseFileMetaData();
+ break;
+ }
+
+ case 5:
+ {
+ if (0 != _vorbis_unpack_books(&mVi, &bits)) {
+ return ERROR_MALFORMED;
+ }
+
+ mMeta->setData(kKeyVorbisBooks, 0, data, size);
+ break;
+ }
+ }
+
+ return OK;
+}
+
+uint64_t MyVorbisExtractor::approxBitrate() {
+ if (mVi.bitrate_nominal != 0) {
+ return mVi.bitrate_nominal;
+ }
+
+ return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
+}
+
+void MyVorbisExtractor::parseFileMetaData() {
+ mFileMeta = new MetaData;
+ mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
+
+ for (int i = 0; i < mVc.comments; ++i) {
+ const char *comment = mVc.user_comments[i];
+ size_t commentLength = mVc.comment_lengths[i];
+ parseVorbisComment(mFileMeta, comment, commentLength);
+ //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
+ }
+}
+
+void parseVorbisComment(
+ const sp<MetaData> &fileMeta, const char *comment, size_t commentLength)
+{
+ struct {
+ const char *const mTag;
+ uint32_t mKey;
+ } kMap[] = {
+ { "TITLE", kKeyTitle },
+ { "ARTIST", kKeyArtist },
+ { "ALBUMARTIST", kKeyAlbumArtist },
+ { "ALBUM ARTIST", kKeyAlbumArtist },
+ { "COMPILATION", kKeyCompilation },
+ { "ALBUM", kKeyAlbum },
+ { "COMPOSER", kKeyComposer },
+ { "GENRE", kKeyGenre },
+ { "AUTHOR", kKeyAuthor },
+ { "TRACKNUMBER", kKeyCDTrackNumber },
+ { "DISCNUMBER", kKeyDiscNumber },
+ { "DATE", kKeyDate },
+ { "LYRICIST", kKeyWriter },
+ { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
+ { "ANDROID_LOOP", kKeyAutoLoop },
+ };
+
+ 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(
+ fileMeta,
+ &comment[tagLen + 1],
+ commentLength - tagLen - 1);
+ } else if (kMap[j].mKey == kKeyAutoLoop) {
+ if (!strcasecmp(&comment[tagLen + 1], "true")) {
+ fileMeta->setInt32(kKeyAutoLoop, true);
+ }
+ } else {
+ fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
+ }
+ }
+ }
+
+}
+
+// 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;
+}
+
+static void extractAlbumArt(
+ const sp<MetaData> &fileMeta, const void *data, size_t size) {
+ ALOGV("extractAlbumArt from '%s'", (const char *)data);
+
+ size_t flacSize;
+ uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize);
+
+ if (flac == NULL) {
+ ALOGE("malformed base64 encoded data.");
+ return;
+ }
+
+ ALOGV("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';
+
+ ALOGV("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;
+ }
+
+ ALOGV("got image data, %d trailing bytes",
+ flacSize - 32 - typeLen - descLen - dataLen);
+
+ fileMeta->setData(
+ kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
+
+ fileMeta->setCString(kKeyAlbumArtMIME, type);
+
+exit:
+ free(flac);
+ flac = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+OggExtractor::OggExtractor(const sp<DataSource> &source)
+ : mDataSource(source),
+ mInitCheck(NO_INIT),
+ mImpl(NULL) {
+ mImpl = new MyVorbisExtractor(mDataSource);
+ mInitCheck = mImpl->seekToOffset(0);
+
+ if (mInitCheck == OK) {
+ mInitCheck = mImpl->init();
+ }
+}
+
+OggExtractor::~OggExtractor() {
+ delete mImpl;
+ mImpl = NULL;
+}
+
+size_t OggExtractor::countTracks() {
+ return mInitCheck != OK ? 0 : 1;
+}
+
+sp<MediaSource> OggExtractor::getTrack(size_t index) {
+ if (index >= 1) {
+ return NULL;
+ }
+
+ return new OggSource(this);
+}
+
+sp<MetaData> OggExtractor::getTrackMetaData(
+ size_t index, uint32_t flags) {
+ if (index >= 1) {
+ return NULL;
+ }
+
+ return mImpl->getFormat();
+}
+
+sp<MetaData> OggExtractor::getMetaData() {
+ return mImpl->getFileMetaData();
+}
+
+bool SniffOgg(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
+ char tmp[4];
+ if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
+ return false;
+ }
+
+ mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG);
+ *confidence = 0.2f;
+
+ return true;
+}
+
+} // namespace android
diff --git a/media/libstagefright/SampleIterator.cpp b/media/libstagefright/SampleIterator.cpp
new file mode 100644
index 0000000..eae721b
--- /dev/null
+++ b/media/libstagefright/SampleIterator.cpp
@@ -0,0 +1,316 @@
+/*
+ * 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 "SampleIterator"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "include/SampleIterator.h"
+
+#include <arpa/inet.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/Utils.h>
+
+#include "include/SampleTable.h"
+
+namespace android {
+
+SampleIterator::SampleIterator(SampleTable *table)
+ : mTable(table),
+ mInitialized(false),
+ mTimeToSampleIndex(0),
+ mTTSSampleIndex(0),
+ mTTSSampleTime(0),
+ mTTSCount(0),
+ mTTSDuration(0) {
+ reset();
+}
+
+void SampleIterator::reset() {
+ mSampleToChunkIndex = 0;
+ mFirstChunk = 0;
+ mFirstChunkSampleIndex = 0;
+ mStopChunk = 0;
+ mStopChunkSampleIndex = 0;
+ mSamplesPerChunk = 0;
+ mChunkDesc = 0;
+}
+
+status_t SampleIterator::seekTo(uint32_t sampleIndex) {
+ ALOGV("seekTo(%d)", sampleIndex);
+
+ if (sampleIndex >= mTable->mNumSampleSizes) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ if (mTable->mSampleToChunkOffset < 0
+ || mTable->mChunkOffsetOffset < 0
+ || mTable->mSampleSizeOffset < 0
+ || mTable->mTimeToSampleCount == 0) {
+
+ return ERROR_MALFORMED;
+ }
+
+ if (mInitialized && mCurrentSampleIndex == sampleIndex) {
+ return OK;
+ }
+
+ if (!mInitialized || sampleIndex < mFirstChunkSampleIndex) {
+ reset();
+ }
+
+ if (sampleIndex >= mStopChunkSampleIndex) {
+ status_t err;
+ if ((err = findChunkRange(sampleIndex)) != OK) {
+ ALOGE("findChunkRange failed");
+ return err;
+ }
+ }
+
+ CHECK(sampleIndex < mStopChunkSampleIndex);
+
+ uint32_t chunk =
+ (sampleIndex - mFirstChunkSampleIndex) / mSamplesPerChunk
+ + mFirstChunk;
+
+ if (!mInitialized || chunk != mCurrentChunkIndex) {
+ mCurrentChunkIndex = chunk;
+
+ status_t err;
+ if ((err = getChunkOffset(chunk, &mCurrentChunkOffset)) != OK) {
+ ALOGE("getChunkOffset return error");
+ return err;
+ }
+
+ mCurrentChunkSampleSizes.clear();
+
+ uint32_t firstChunkSampleIndex =
+ mFirstChunkSampleIndex
+ + mSamplesPerChunk * (mCurrentChunkIndex - mFirstChunk);
+
+ for (uint32_t i = 0; i < mSamplesPerChunk; ++i) {
+ size_t sampleSize;
+ if ((err = getSampleSizeDirect(
+ firstChunkSampleIndex + i, &sampleSize)) != OK) {
+ ALOGE("getSampleSizeDirect return error");
+ return err;
+ }
+
+ mCurrentChunkSampleSizes.push(sampleSize);
+ }
+ }
+
+ uint32_t chunkRelativeSampleIndex =
+ (sampleIndex - mFirstChunkSampleIndex) % mSamplesPerChunk;
+
+ mCurrentSampleOffset = mCurrentChunkOffset;
+ for (uint32_t i = 0; i < chunkRelativeSampleIndex; ++i) {
+ mCurrentSampleOffset += mCurrentChunkSampleSizes[i];
+ }
+
+ mCurrentSampleSize = mCurrentChunkSampleSizes[chunkRelativeSampleIndex];
+ if (sampleIndex < mTTSSampleIndex) {
+ mTimeToSampleIndex = 0;
+ mTTSSampleIndex = 0;
+ mTTSSampleTime = 0;
+ mTTSCount = 0;
+ mTTSDuration = 0;
+ }
+
+ status_t err;
+ if ((err = findSampleTime(sampleIndex, &mCurrentSampleTime)) != OK) {
+ ALOGE("findSampleTime return error");
+ return err;
+ }
+
+ mCurrentSampleIndex = sampleIndex;
+
+ mInitialized = true;
+
+ return OK;
+}
+
+status_t SampleIterator::findChunkRange(uint32_t sampleIndex) {
+ CHECK(sampleIndex >= mFirstChunkSampleIndex);
+
+ while (sampleIndex >= mStopChunkSampleIndex) {
+ if (mSampleToChunkIndex == mTable->mNumSampleToChunkOffsets) {
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ mFirstChunkSampleIndex = mStopChunkSampleIndex;
+
+ const SampleTable::SampleToChunkEntry *entry =
+ &mTable->mSampleToChunkEntries[mSampleToChunkIndex];
+
+ mFirstChunk = entry->startChunk;
+ mSamplesPerChunk = entry->samplesPerChunk;
+ mChunkDesc = entry->chunkDesc;
+
+ if (mSampleToChunkIndex + 1 < mTable->mNumSampleToChunkOffsets) {
+ mStopChunk = entry[1].startChunk;
+
+ mStopChunkSampleIndex =
+ mFirstChunkSampleIndex
+ + (mStopChunk - mFirstChunk) * mSamplesPerChunk;
+ } else {
+ mStopChunk = 0xffffffff;
+ mStopChunkSampleIndex = 0xffffffff;
+ }
+
+ ++mSampleToChunkIndex;
+ }
+
+ return OK;
+}
+
+status_t SampleIterator::getChunkOffset(uint32_t chunk, off64_t *offset) {
+ *offset = 0;
+
+ if (chunk >= mTable->mNumChunkOffsets) {
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ if (mTable->mChunkOffsetType == SampleTable::kChunkOffsetType32) {
+ uint32_t offset32;
+
+ if (mTable->mDataSource->readAt(
+ mTable->mChunkOffsetOffset + 8 + 4 * chunk,
+ &offset32,
+ sizeof(offset32)) < (ssize_t)sizeof(offset32)) {
+ return ERROR_IO;
+ }
+
+ *offset = ntohl(offset32);
+ } else {
+ CHECK_EQ(mTable->mChunkOffsetType, SampleTable::kChunkOffsetType64);
+
+ uint64_t offset64;
+ if (mTable->mDataSource->readAt(
+ mTable->mChunkOffsetOffset + 8 + 8 * chunk,
+ &offset64,
+ sizeof(offset64)) < (ssize_t)sizeof(offset64)) {
+ return ERROR_IO;
+ }
+
+ *offset = ntoh64(offset64);
+ }
+
+ return OK;
+}
+
+status_t SampleIterator::getSampleSizeDirect(
+ uint32_t sampleIndex, size_t *size) {
+ *size = 0;
+
+ if (sampleIndex >= mTable->mNumSampleSizes) {
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ if (mTable->mDefaultSampleSize > 0) {
+ *size = mTable->mDefaultSampleSize;
+ return OK;
+ }
+
+ switch (mTable->mSampleSizeFieldSize) {
+ case 32:
+ {
+ if (mTable->mDataSource->readAt(
+ mTable->mSampleSizeOffset + 12 + 4 * sampleIndex,
+ size, sizeof(*size)) < (ssize_t)sizeof(*size)) {
+ return ERROR_IO;
+ }
+
+ *size = ntohl(*size);
+ break;
+ }
+
+ case 16:
+ {
+ uint16_t x;
+ if (mTable->mDataSource->readAt(
+ mTable->mSampleSizeOffset + 12 + 2 * sampleIndex,
+ &x, sizeof(x)) < (ssize_t)sizeof(x)) {
+ return ERROR_IO;
+ }
+
+ *size = ntohs(x);
+ break;
+ }
+
+ case 8:
+ {
+ uint8_t x;
+ if (mTable->mDataSource->readAt(
+ mTable->mSampleSizeOffset + 12 + sampleIndex,
+ &x, sizeof(x)) < (ssize_t)sizeof(x)) {
+ return ERROR_IO;
+ }
+
+ *size = x;
+ break;
+ }
+
+ default:
+ {
+ CHECK_EQ(mTable->mSampleSizeFieldSize, 4);
+
+ uint8_t x;
+ if (mTable->mDataSource->readAt(
+ mTable->mSampleSizeOffset + 12 + sampleIndex / 2,
+ &x, sizeof(x)) < (ssize_t)sizeof(x)) {
+ return ERROR_IO;
+ }
+
+ *size = (sampleIndex & 1) ? x & 0x0f : x >> 4;
+ break;
+ }
+ }
+
+ return OK;
+}
+
+status_t SampleIterator::findSampleTime(
+ uint32_t sampleIndex, uint32_t *time) {
+ if (sampleIndex >= mTable->mNumSampleSizes) {
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ while (sampleIndex >= mTTSSampleIndex + mTTSCount) {
+ if (mTimeToSampleIndex == mTable->mTimeToSampleCount) {
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ mTTSSampleIndex += mTTSCount;
+ mTTSSampleTime += mTTSCount * mTTSDuration;
+
+ mTTSCount = mTable->mTimeToSample[2 * mTimeToSampleIndex];
+ mTTSDuration = mTable->mTimeToSample[2 * mTimeToSampleIndex + 1];
+
+ ++mTimeToSampleIndex;
+ }
+
+ *time = mTTSSampleTime + mTTSDuration * (sampleIndex - mTTSSampleIndex);
+
+ *time += mTable->getCompositionTimeOffset(sampleIndex);
+
+ return OK;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
new file mode 100644
index 0000000..d9858d7
--- /dev/null
+++ b/media/libstagefright/SampleTable.cpp
@@ -0,0 +1,831 @@
+/*
+ * 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 "SampleTable"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "include/SampleTable.h"
+#include "include/SampleIterator.h"
+
+#include <arpa/inet.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+// static
+const uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
+// static
+const uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
+// static
+const uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
+// static
+const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct SampleTable::CompositionDeltaLookup {
+ CompositionDeltaLookup();
+
+ void setEntries(
+ const uint32_t *deltaEntries, size_t numDeltaEntries);
+
+ uint32_t getCompositionTimeOffset(uint32_t sampleIndex);
+
+private:
+ Mutex mLock;
+
+ const uint32_t *mDeltaEntries;
+ size_t mNumDeltaEntries;
+
+ size_t mCurrentDeltaEntry;
+ size_t mCurrentEntrySampleIndex;
+
+ DISALLOW_EVIL_CONSTRUCTORS(CompositionDeltaLookup);
+};
+
+SampleTable::CompositionDeltaLookup::CompositionDeltaLookup()
+ : mDeltaEntries(NULL),
+ mNumDeltaEntries(0),
+ mCurrentDeltaEntry(0),
+ mCurrentEntrySampleIndex(0) {
+}
+
+void SampleTable::CompositionDeltaLookup::setEntries(
+ const uint32_t *deltaEntries, size_t numDeltaEntries) {
+ Mutex::Autolock autolock(mLock);
+
+ mDeltaEntries = deltaEntries;
+ mNumDeltaEntries = numDeltaEntries;
+ mCurrentDeltaEntry = 0;
+ mCurrentEntrySampleIndex = 0;
+}
+
+uint32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
+ uint32_t sampleIndex) {
+ Mutex::Autolock autolock(mLock);
+
+ if (mDeltaEntries == NULL) {
+ return 0;
+ }
+
+ if (sampleIndex < mCurrentEntrySampleIndex) {
+ mCurrentDeltaEntry = 0;
+ mCurrentEntrySampleIndex = 0;
+ }
+
+ while (mCurrentDeltaEntry < mNumDeltaEntries) {
+ uint32_t sampleCount = mDeltaEntries[2 * mCurrentDeltaEntry];
+ if (sampleIndex < mCurrentEntrySampleIndex + sampleCount) {
+ return mDeltaEntries[2 * mCurrentDeltaEntry + 1];
+ }
+
+ mCurrentEntrySampleIndex += sampleCount;
+ ++mCurrentDeltaEntry;
+ }
+
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SampleTable::SampleTable(const sp<DataSource> &source)
+ : mDataSource(source),
+ mChunkOffsetOffset(-1),
+ mChunkOffsetType(0),
+ mNumChunkOffsets(0),
+ mSampleToChunkOffset(-1),
+ mNumSampleToChunkOffsets(0),
+ mSampleSizeOffset(-1),
+ mSampleSizeFieldSize(0),
+ mDefaultSampleSize(0),
+ mNumSampleSizes(0),
+ mTimeToSampleCount(0),
+ mTimeToSample(NULL),
+ mSampleTimeEntries(NULL),
+ mCompositionTimeDeltaEntries(NULL),
+ mNumCompositionTimeDeltaEntries(0),
+ mCompositionDeltaLookup(new CompositionDeltaLookup),
+ mSyncSampleOffset(-1),
+ mNumSyncSamples(0),
+ mSyncSamples(NULL),
+ mLastSyncSampleIndex(0),
+ mSampleToChunkEntries(NULL) {
+ mSampleIterator = new SampleIterator(this);
+}
+
+SampleTable::~SampleTable() {
+ delete[] mSampleToChunkEntries;
+ mSampleToChunkEntries = NULL;
+
+ delete[] mSyncSamples;
+ mSyncSamples = NULL;
+
+ delete mCompositionDeltaLookup;
+ mCompositionDeltaLookup = NULL;
+
+ delete[] mCompositionTimeDeltaEntries;
+ mCompositionTimeDeltaEntries = NULL;
+
+ delete[] mSampleTimeEntries;
+ mSampleTimeEntries = NULL;
+
+ delete[] mTimeToSample;
+ mTimeToSample = NULL;
+
+ delete mSampleIterator;
+ mSampleIterator = NULL;
+}
+
+bool SampleTable::isValid() const {
+ return mChunkOffsetOffset >= 0
+ && mSampleToChunkOffset >= 0
+ && mSampleSizeOffset >= 0
+ && mTimeToSample != NULL;
+}
+
+status_t SampleTable::setChunkOffsetParams(
+ uint32_t type, off64_t data_offset, size_t data_size) {
+ if (mChunkOffsetOffset >= 0) {
+ return ERROR_MALFORMED;
+ }
+
+ CHECK(type == kChunkOffsetType32 || type == kChunkOffsetType64);
+
+ mChunkOffsetOffset = data_offset;
+ mChunkOffsetType = type;
+
+ if (data_size < 8) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t header[8];
+ if (mDataSource->readAt(
+ data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
+ return ERROR_IO;
+ }
+
+ if (U32_AT(header) != 0) {
+ // Expected version = 0, flags = 0.
+ return ERROR_MALFORMED;
+ }
+
+ mNumChunkOffsets = U32_AT(&header[4]);
+
+ if (mChunkOffsetType == kChunkOffsetType32) {
+ if (data_size < 8 + mNumChunkOffsets * 4) {
+ return ERROR_MALFORMED;
+ }
+ } else {
+ if (data_size < 8 + mNumChunkOffsets * 8) {
+ return ERROR_MALFORMED;
+ }
+ }
+
+ return OK;
+}
+
+status_t SampleTable::setSampleToChunkParams(
+ off64_t data_offset, size_t data_size) {
+ if (mSampleToChunkOffset >= 0) {
+ return ERROR_MALFORMED;
+ }
+
+ mSampleToChunkOffset = data_offset;
+
+ if (data_size < 8) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t header[8];
+ if (mDataSource->readAt(
+ data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
+ return ERROR_IO;
+ }
+
+ if (U32_AT(header) != 0) {
+ // Expected version = 0, flags = 0.
+ return ERROR_MALFORMED;
+ }
+
+ mNumSampleToChunkOffsets = U32_AT(&header[4]);
+
+ if (data_size < 8 + mNumSampleToChunkOffsets * 12) {
+ return ERROR_MALFORMED;
+ }
+
+ mSampleToChunkEntries =
+ new SampleToChunkEntry[mNumSampleToChunkOffsets];
+
+ for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
+ uint8_t buffer[12];
+ if (mDataSource->readAt(
+ mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer))
+ != (ssize_t)sizeof(buffer)) {
+ return ERROR_IO;
+ }
+
+ CHECK(U32_AT(buffer) >= 1); // chunk index is 1 based in the spec.
+
+ // We want the chunk index to be 0-based.
+ mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
+ mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]);
+ mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]);
+ }
+
+ return OK;
+}
+
+status_t SampleTable::setSampleSizeParams(
+ uint32_t type, off64_t data_offset, size_t data_size) {
+ if (mSampleSizeOffset >= 0) {
+ return ERROR_MALFORMED;
+ }
+
+ CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact);
+
+ mSampleSizeOffset = data_offset;
+
+ if (data_size < 12) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t header[12];
+ if (mDataSource->readAt(
+ data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
+ return ERROR_IO;
+ }
+
+ if (U32_AT(header) != 0) {
+ // Expected version = 0, flags = 0.
+ return ERROR_MALFORMED;
+ }
+
+ mDefaultSampleSize = U32_AT(&header[4]);
+ mNumSampleSizes = U32_AT(&header[8]);
+
+ if (type == kSampleSizeType32) {
+ mSampleSizeFieldSize = 32;
+
+ if (mDefaultSampleSize != 0) {
+ return OK;
+ }
+
+ if (data_size < 12 + mNumSampleSizes * 4) {
+ return ERROR_MALFORMED;
+ }
+ } else {
+ if ((mDefaultSampleSize & 0xffffff00) != 0) {
+ // The high 24 bits are reserved and must be 0.
+ return ERROR_MALFORMED;
+ }
+
+ mSampleSizeFieldSize = mDefaultSampleSize & 0xff;
+ mDefaultSampleSize = 0;
+
+ if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
+ && mSampleSizeFieldSize != 16) {
+ return ERROR_MALFORMED;
+ }
+
+ if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
+ return ERROR_MALFORMED;
+ }
+ }
+
+ return OK;
+}
+
+status_t SampleTable::setTimeToSampleParams(
+ off64_t data_offset, size_t data_size) {
+ if (mTimeToSample != NULL || data_size < 8) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t header[8];
+ if (mDataSource->readAt(
+ data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
+ return ERROR_IO;
+ }
+
+ if (U32_AT(header) != 0) {
+ // Expected version = 0, flags = 0.
+ return ERROR_MALFORMED;
+ }
+
+ mTimeToSampleCount = U32_AT(&header[4]);
+ mTimeToSample = new uint32_t[mTimeToSampleCount * 2];
+
+ size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
+ if (mDataSource->readAt(
+ data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
+ return ERROR_IO;
+ }
+
+ for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) {
+ mTimeToSample[i] = ntohl(mTimeToSample[i]);
+ }
+
+ return OK;
+}
+
+status_t SampleTable::setCompositionTimeToSampleParams(
+ off64_t data_offset, size_t data_size) {
+ ALOGI("There are reordered frames present.");
+
+ if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t header[8];
+ if (mDataSource->readAt(
+ data_offset, header, sizeof(header))
+ < (ssize_t)sizeof(header)) {
+ return ERROR_IO;
+ }
+
+ if (U32_AT(header) != 0) {
+ // Expected version = 0, flags = 0.
+ return ERROR_MALFORMED;
+ }
+
+ size_t numEntries = U32_AT(&header[4]);
+
+ if (data_size != (numEntries + 1) * 8) {
+ return ERROR_MALFORMED;
+ }
+
+ mNumCompositionTimeDeltaEntries = numEntries;
+ mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries];
+
+ if (mDataSource->readAt(
+ data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8)
+ < (ssize_t)numEntries * 8) {
+ delete[] mCompositionTimeDeltaEntries;
+ mCompositionTimeDeltaEntries = NULL;
+
+ return ERROR_IO;
+ }
+
+ for (size_t i = 0; i < 2 * numEntries; ++i) {
+ mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
+ }
+
+ mCompositionDeltaLookup->setEntries(
+ mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries);
+
+ return OK;
+}
+
+status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
+ if (mSyncSampleOffset >= 0 || data_size < 8) {
+ return ERROR_MALFORMED;
+ }
+
+ mSyncSampleOffset = data_offset;
+
+ uint8_t header[8];
+ if (mDataSource->readAt(
+ data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
+ return ERROR_IO;
+ }
+
+ if (U32_AT(header) != 0) {
+ // Expected version = 0, flags = 0.
+ return ERROR_MALFORMED;
+ }
+
+ mNumSyncSamples = U32_AT(&header[4]);
+
+ if (mNumSyncSamples < 2) {
+ ALOGV("Table of sync samples is empty or has only a single entry!");
+ }
+
+ mSyncSamples = new uint32_t[mNumSyncSamples];
+ size_t size = mNumSyncSamples * sizeof(uint32_t);
+ if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size)
+ != (ssize_t)size) {
+ return ERROR_IO;
+ }
+
+ for (size_t i = 0; i < mNumSyncSamples; ++i) {
+ mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
+ }
+
+ return OK;
+}
+
+uint32_t SampleTable::countChunkOffsets() const {
+ return mNumChunkOffsets;
+}
+
+uint32_t SampleTable::countSamples() const {
+ return mNumSampleSizes;
+}
+
+status_t SampleTable::getMaxSampleSize(size_t *max_size) {
+ Mutex::Autolock autoLock(mLock);
+
+ *max_size = 0;
+
+ for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
+ size_t sample_size;
+ status_t err = getSampleSize_l(i, &sample_size);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (sample_size > *max_size) {
+ *max_size = sample_size;
+ }
+ }
+
+ return OK;
+}
+
+uint32_t abs_difference(uint32_t time1, uint32_t time2) {
+ return time1 > time2 ? time1 - time2 : time2 - time1;
+}
+
+// static
+int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
+ const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
+ const SampleTimeEntry *b = (const SampleTimeEntry *)_b;
+
+ if (a->mCompositionTime < b->mCompositionTime) {
+ return -1;
+ } else if (a->mCompositionTime > b->mCompositionTime) {
+ return 1;
+ }
+
+ return 0;
+}
+
+void SampleTable::buildSampleEntriesTable() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mSampleTimeEntries != NULL) {
+ return;
+ }
+
+ mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes];
+
+ uint32_t sampleIndex = 0;
+ uint32_t sampleTime = 0;
+
+ for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
+ uint32_t n = mTimeToSample[2 * i];
+ uint32_t delta = mTimeToSample[2 * i + 1];
+
+ for (uint32_t j = 0; j < n; ++j) {
+ if (sampleIndex < mNumSampleSizes) {
+ // Technically this should always be the case if the file
+ // is well-formed, but you know... there's (gasp) malformed
+ // content out there.
+
+ mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
+
+ uint32_t compTimeDelta =
+ mCompositionDeltaLookup->getCompositionTimeOffset(
+ sampleIndex);
+
+ mSampleTimeEntries[sampleIndex].mCompositionTime =
+ sampleTime + compTimeDelta;
+ }
+
+ ++sampleIndex;
+ sampleTime += delta;
+ }
+ }
+
+ qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
+ CompareIncreasingTime);
+}
+
+status_t SampleTable::findSampleAtTime(
+ uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
+ buildSampleEntriesTable();
+
+ uint32_t left = 0;
+ uint32_t right = mNumSampleSizes;
+ while (left < right) {
+ uint32_t center = (left + right) / 2;
+ uint32_t centerTime = mSampleTimeEntries[center].mCompositionTime;
+
+ if (req_time < centerTime) {
+ right = center;
+ } else if (req_time > centerTime) {
+ left = center + 1;
+ } else {
+ left = center;
+ break;
+ }
+ }
+
+ if (left == mNumSampleSizes) {
+ if (flags == kFlagAfter) {
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ --left;
+ }
+
+ uint32_t closestIndex = left;
+
+ switch (flags) {
+ case kFlagBefore:
+ {
+ while (closestIndex > 0
+ && mSampleTimeEntries[closestIndex].mCompositionTime
+ > req_time) {
+ --closestIndex;
+ }
+ break;
+ }
+
+ case kFlagAfter:
+ {
+ while (closestIndex + 1 < mNumSampleSizes
+ && mSampleTimeEntries[closestIndex].mCompositionTime
+ < req_time) {
+ ++closestIndex;
+ }
+ break;
+ }
+
+ default:
+ {
+ CHECK(flags == kFlagClosest);
+
+ if (closestIndex > 0) {
+ // Check left neighbour and pick closest.
+ uint32_t absdiff1 =
+ abs_difference(
+ mSampleTimeEntries[closestIndex].mCompositionTime,
+ req_time);
+
+ uint32_t absdiff2 =
+ abs_difference(
+ mSampleTimeEntries[closestIndex - 1].mCompositionTime,
+ req_time);
+
+ if (absdiff1 > absdiff2) {
+ closestIndex = closestIndex - 1;
+ }
+ }
+
+ break;
+ }
+ }
+
+ *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
+
+ return OK;
+}
+
+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) {
+ // All samples are sync-samples.
+ *sample_index = start_sample_index;
+ return OK;
+ }
+
+ if (mNumSyncSamples == 0) {
+ *sample_index = 0;
+ return OK;
+ }
+
+ uint32_t left = 0;
+ uint32_t right = mNumSyncSamples;
+ while (left < right) {
+ uint32_t center = left + (right - left) / 2;
+ uint32_t x = mSyncSamples[center];
+
+ if (start_sample_index < x) {
+ right = center;
+ } else if (start_sample_index > x) {
+ left = center + 1;
+ } else {
+ left = center;
+ break;
+ }
+ }
+ if (left == mNumSyncSamples) {
+ if (flags == kFlagAfter) {
+ ALOGE("tried to find a sync frame after the last one: %d", left);
+ return ERROR_OUT_OF_RANGE;
+ }
+ left = left - 1;
+ }
+
+ // Now ssi[left] is the sync sample index just before (or at)
+ // start_sample_index.
+ // Also start_sample_index < ssi[left + 1], if left + 1 < mNumSyncSamples.
+
+ uint32_t x = mSyncSamples[left];
+
+ if (left + 1 < mNumSyncSamples) {
+ uint32_t y = mSyncSamples[left + 1];
+
+ // 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);
+
+ x = mSyncSamples[left - 1];
+
+ if (x > start_sample_index) {
+ // The table of sync sample indices was not sorted
+ // properly.
+ return ERROR_MALFORMED;
+ }
+ }
+ break;
+ }
+
+ case kFlagAfter:
+ {
+ if (x < start_sample_index) {
+ if (left + 1 >= mNumSyncSamples) {
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ x = mSyncSamples[left + 1];
+
+ if (x < start_sample_index) {
+ // The table of sync sample indices was not sorted
+ // properly.
+ return ERROR_MALFORMED;
+ }
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ *sample_index = x;
+
+ return OK;
+}
+
+status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mSyncSampleOffset < 0) {
+ // All samples are sync-samples.
+ *sample_index = 0;
+ return OK;
+ }
+
+ uint32_t bestSampleIndex = 0;
+ size_t maxSampleSize = 0;
+
+ static const size_t kMaxNumSyncSamplesToScan = 20;
+
+ // Consider the first kMaxNumSyncSamplesToScan sync samples and
+ // pick the one with the largest (compressed) size as the thumbnail.
+
+ size_t numSamplesToScan = mNumSyncSamples;
+ if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
+ numSamplesToScan = kMaxNumSyncSamplesToScan;
+ }
+
+ for (size_t i = 0; i < numSamplesToScan; ++i) {
+ uint32_t x = mSyncSamples[i];
+
+ // Now x is a sample index.
+ size_t sampleSize;
+ status_t err = getSampleSize_l(x, &sampleSize);
+ if (err != OK) {
+ return err;
+ }
+
+ if (i == 0 || sampleSize > maxSampleSize) {
+ bestSampleIndex = x;
+ maxSampleSize = sampleSize;
+ }
+ }
+
+ *sample_index = bestSampleIndex;
+
+ return OK;
+}
+
+status_t SampleTable::getSampleSize_l(
+ uint32_t sampleIndex, size_t *sampleSize) {
+ return mSampleIterator->getSampleSizeDirect(
+ sampleIndex, sampleSize);
+}
+
+status_t SampleTable::getMetaDataForSample(
+ uint32_t sampleIndex,
+ off64_t *offset,
+ size_t *size,
+ uint32_t *compositionTime,
+ bool *isSyncSample) {
+ Mutex::Autolock autoLock(mLock);
+
+ status_t err;
+ if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
+ return err;
+ }
+
+ if (offset) {
+ *offset = mSampleIterator->getSampleOffset();
+ }
+
+ if (size) {
+ *size = mSampleIterator->getSampleSize();
+ }
+
+ if (compositionTime) {
+ *compositionTime = mSampleIterator->getSampleTime();
+ }
+
+ if (isSyncSample) {
+ *isSyncSample = false;
+ if (mSyncSampleOffset < 0) {
+ // Every sample is a sync sample.
+ *isSyncSample = true;
+ } else {
+ size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
+ && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
+ ? mLastSyncSampleIndex : 0;
+
+ while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
+ ++i;
+ }
+
+ if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
+ *isSyncSample = true;
+ }
+
+ mLastSyncSampleIndex = i;
+ }
+ }
+
+ return OK;
+}
+
+uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
+ return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/SkipCutBuffer.cpp b/media/libstagefright/SkipCutBuffer.cpp
new file mode 100755
index 0000000..6d331b0
--- /dev/null
+++ b/media/libstagefright/SkipCutBuffer.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SkipCutBuffer"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/SkipCutBuffer.h>
+
+namespace android {
+
+SkipCutBuffer::SkipCutBuffer(int32_t skip, int32_t cut, int32_t output_size) {
+ mFrontPadding = skip;
+ mBackPadding = cut;
+ mWriteHead = 0;
+ mReadHead = 0;
+ mCapacity = cut + output_size;
+ mCutBuffer = new char[mCapacity];
+ ALOGV("skipcutbuffer %d %d %d", skip, cut, mCapacity);
+}
+
+SkipCutBuffer::~SkipCutBuffer() {
+ delete[] mCutBuffer;
+}
+
+void SkipCutBuffer::submit(MediaBuffer *buffer) {
+ int32_t offset = buffer->range_offset();
+ int32_t buflen = buffer->range_length();
+
+ // drop the initial data from the buffer if needed
+ if (mFrontPadding > 0) {
+ // still data left to drop
+ int32_t to_drop = (buflen < mFrontPadding) ? buflen : mFrontPadding;
+ offset += to_drop;
+ buflen -= to_drop;
+ buffer->set_range(offset, buflen);
+ mFrontPadding -= to_drop;
+ }
+
+
+ // append data to cutbuffer
+ char *src = ((char*) buffer->data()) + offset;
+ write(src, buflen);
+
+
+ // the mediabuffer is now empty. Fill it from cutbuffer, always leaving
+ // at least mBackPadding bytes in the cutbuffer
+ char *dst = (char*) buffer->data();
+ size_t copied = read(dst, buffer->size());
+ buffer->set_range(0, copied);
+}
+
+void SkipCutBuffer::clear() {
+ mWriteHead = mReadHead = 0;
+}
+
+void SkipCutBuffer::write(const char *src, size_t num) {
+ int32_t sizeused = (mWriteHead - mReadHead);
+ if (sizeused < 0) sizeused += mCapacity;
+
+ // everything must fit
+ CHECK_GE((mCapacity - size_t(sizeused)), num);
+
+ size_t copyfirst = (mCapacity - mWriteHead);
+ if (copyfirst > num) copyfirst = num;
+ if (copyfirst) {
+ memcpy(mCutBuffer + mWriteHead, src, copyfirst);
+ num -= copyfirst;
+ src += copyfirst;
+ mWriteHead += copyfirst;
+ CHECK_LE(mWriteHead, mCapacity);
+ if (mWriteHead == mCapacity) mWriteHead = 0;
+ if (num) {
+ memcpy(mCutBuffer, src, num);
+ mWriteHead += num;
+ }
+ }
+}
+
+size_t SkipCutBuffer::read(char *dst, size_t num) {
+ int32_t available = (mWriteHead - mReadHead);
+ if (available < 0) available += mCapacity;
+
+ available -= mBackPadding;
+ if (available <=0) {
+ return 0;
+ }
+ if (available < num) {
+ num = available;
+ }
+
+ size_t copyfirst = (mCapacity - mReadHead);
+ if (copyfirst > num) copyfirst = num;
+ if (copyfirst) {
+ memcpy(dst, mCutBuffer + mReadHead, copyfirst);
+ num -= copyfirst;
+ dst += copyfirst;
+ mReadHead += copyfirst;
+ CHECK_LE(mReadHead, mCapacity);
+ if (mReadHead == mCapacity) mReadHead = 0;
+ if (num) {
+ memcpy(dst, mCutBuffer, num);
+ mReadHead += num;
+ }
+ }
+ return available;
+}
+
+size_t SkipCutBuffer::size() {
+ int32_t available = (mWriteHead - mReadHead);
+ if (available < 0) available += mCapacity;
+ return available;
+}
+
+} // namespace android
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
new file mode 100644
index 0000000..bd7a226
--- /dev/null
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -0,0 +1,217 @@
+/*
+ * 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 "StagefrightMediaScanner"
+#include <utils/Log.h>
+
+#include <media/stagefright/StagefrightMediaScanner.h>
+
+#include <media/mediametadataretriever.h>
+#include <private/media/VideoFrame.h>
+
+// Sonivox includes
+#include <libsonivox/eas.h>
+
+namespace android {
+
+StagefrightMediaScanner::StagefrightMediaScanner() {}
+
+StagefrightMediaScanner::~StagefrightMediaScanner() {}
+
+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",
+ ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf",
+ ".avi", ".mpeg", ".mpg"
+ };
+ static const size_t kNumValidExtensions =
+ sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
+
+ for (size_t i = 0; i < kNumValidExtensions; ++i) {
+ if (!strcasecmp(extension, kValidExtensions[i])) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static MediaScanResult HandleMIDI(
+ const char *filename, MediaScannerClient *client) {
+ // get the library configuration and do sanity check
+ const S_EAS_LIB_CONFIG* pLibConfig = EAS_Config();
+ if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) {
+ ALOGE("EAS library/header mismatch\n");
+ return MEDIA_SCAN_RESULT_ERROR;
+ }
+ EAS_I32 temp;
+
+ // spin up a new EAS engine
+ EAS_DATA_HANDLE easData = NULL;
+ EAS_HANDLE easHandle = NULL;
+ EAS_RESULT result = EAS_Init(&easData);
+ if (result == EAS_SUCCESS) {
+ EAS_FILE file;
+ file.path = filename;
+ file.fd = 0;
+ file.offset = 0;
+ file.length = 0;
+ result = EAS_OpenFile(easData, &file, &easHandle);
+ }
+ if (result == EAS_SUCCESS) {
+ result = EAS_Prepare(easData, easHandle);
+ }
+ if (result == EAS_SUCCESS) {
+ result = EAS_ParseMetaData(easData, easHandle, &temp);
+ }
+ if (easHandle) {
+ EAS_CloseFile(easData, easHandle);
+ }
+ if (easData) {
+ EAS_Shutdown(easData);
+ }
+
+ if (result != EAS_SUCCESS) {
+ return MEDIA_SCAN_RESULT_SKIPPED;
+ }
+
+ char buffer[20];
+ sprintf(buffer, "%ld", temp);
+ status_t status = client->addStringTag("duration", buffer);
+ if (status != OK) {
+ return MEDIA_SCAN_RESULT_ERROR;
+ }
+ return MEDIA_SCAN_RESULT_OK;
+}
+
+MediaScanResult StagefrightMediaScanner::processFile(
+ const char *path, const char *mimeType,
+ MediaScannerClient &client) {
+ ALOGV("processFile '%s'.", path);
+
+ client.setLocale(locale());
+ client.beginFile();
+ MediaScanResult result = processFileInternal(path, mimeType, client);
+ client.endFile();
+ return result;
+}
+
+MediaScanResult StagefrightMediaScanner::processFileInternal(
+ const char *path, const char *mimeType,
+ MediaScannerClient &client) {
+ const char *extension = strrchr(path, '.');
+
+ if (!extension) {
+ return MEDIA_SCAN_RESULT_SKIPPED;
+ }
+
+ if (!FileHasAcceptableExtension(extension)) {
+ return MEDIA_SCAN_RESULT_SKIPPED;
+ }
+
+ if (!strcasecmp(extension, ".mid")
+ || !strcasecmp(extension, ".smf")
+ || !strcasecmp(extension, ".imy")
+ || !strcasecmp(extension, ".midi")
+ || !strcasecmp(extension, ".xmf")
+ || !strcasecmp(extension, ".rtttl")
+ || !strcasecmp(extension, ".rtx")
+ || !strcasecmp(extension, ".ota")
+ || !strcasecmp(extension, ".mxmf")) {
+ return HandleMIDI(path, &client);
+ }
+
+ sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);
+
+ status_t status = mRetriever->setDataSource(path);
+ if (status) {
+ return MEDIA_SCAN_RESULT_ERROR;
+ }
+
+ const char *value;
+ if ((value = mRetriever->extractMetadata(
+ METADATA_KEY_MIMETYPE)) != NULL) {
+ status = client.setMimeType(value);
+ if (status) {
+ return MEDIA_SCAN_RESULT_ERROR;
+ }
+ }
+
+ struct KeyMap {
+ const char *tag;
+ int key;
+ };
+ static const KeyMap kKeyMap[] = {
+ { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
+ { "discnumber", METADATA_KEY_DISC_NUMBER },
+ { "album", METADATA_KEY_ALBUM },
+ { "artist", METADATA_KEY_ARTIST },
+ { "albumartist", METADATA_KEY_ALBUMARTIST },
+ { "composer", METADATA_KEY_COMPOSER },
+ { "genre", METADATA_KEY_GENRE },
+ { "title", METADATA_KEY_TITLE },
+ { "year", METADATA_KEY_YEAR },
+ { "duration", METADATA_KEY_DURATION },
+ { "writer", METADATA_KEY_WRITER },
+ { "compilation", METADATA_KEY_COMPILATION },
+ { "isdrm", METADATA_KEY_IS_DRM },
+ };
+ static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
+
+ for (size_t i = 0; i < kNumEntries; ++i) {
+ const char *value;
+ if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
+ status = client.addStringTag(kKeyMap[i].tag, value);
+ if (status != OK) {
+ return MEDIA_SCAN_RESULT_ERROR;
+ }
+ }
+ }
+
+ return MEDIA_SCAN_RESULT_OK;
+}
+
+char *StagefrightMediaScanner::extractAlbumArt(int fd) {
+ ALOGV("extractAlbumArt %d", fd);
+
+ off64_t size = lseek64(fd, 0, SEEK_END);
+ if (size < 0) {
+ return NULL;
+ }
+ lseek64(fd, 0, SEEK_SET);
+
+ sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);
+ if (mRetriever->setDataSource(fd, 0, size) == OK) {
+ sp<IMemory> mem = mRetriever->extractAlbumArt();
+
+ if (mem != NULL) {
+ MediaAlbumArt *art = static_cast<MediaAlbumArt *>(mem->pointer());
+
+ char *data = (char *)malloc(art->mSize + 4);
+ *(int32_t *)data = art->mSize;
+ memcpy(&data[4], &art[1], art->mSize);
+
+ return data;
+ }
+ }
+
+ return NULL;
+}
+
+} // namespace android
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
new file mode 100644
index 0000000..35f9c1f
--- /dev/null
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -0,0 +1,553 @@
+/*
+ * 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 "StagefrightMetadataRetriever"
+#include <utils/Log.h>
+
+#include "include/StagefrightMetadataRetriever.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/ColorConverter.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/MediaDefs.h>
+
+namespace android {
+
+StagefrightMetadataRetriever::StagefrightMetadataRetriever()
+ : mParsedMetaData(false),
+ mAlbumArt(NULL) {
+ ALOGV("StagefrightMetadataRetriever()");
+
+ DataSource::RegisterDefaultSniffers();
+ CHECK_EQ(mClient.connect(), (status_t)OK);
+}
+
+StagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
+ ALOGV("~StagefrightMetadataRetriever()");
+
+ delete mAlbumArt;
+ mAlbumArt = NULL;
+
+ mClient.disconnect();
+}
+
+status_t StagefrightMetadataRetriever::setDataSource(
+ const char *uri, const KeyedVector<String8, String8> *headers) {
+ ALOGV("setDataSource(%s)", uri);
+
+ mParsedMetaData = false;
+ mMetaData.clear();
+ delete mAlbumArt;
+ mAlbumArt = NULL;
+
+ mSource = DataSource::CreateFromURI(uri, headers);
+
+ if (mSource == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ mExtractor = MediaExtractor::Create(mSource);
+
+ if (mExtractor == NULL) {
+ mSource.clear();
+
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+// Warning caller retains ownership of the filedescriptor! Dup it if necessary.
+status_t StagefrightMetadataRetriever::setDataSource(
+ int fd, int64_t offset, int64_t length) {
+ fd = dup(fd);
+
+ ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
+
+ mParsedMetaData = false;
+ mMetaData.clear();
+ delete mAlbumArt;
+ mAlbumArt = NULL;
+
+ mSource = new FileSource(fd, offset, length);
+
+ status_t err;
+ if ((err = mSource->initCheck()) != OK) {
+ mSource.clear();
+
+ return err;
+ }
+
+ mExtractor = MediaExtractor::Create(mSource);
+
+ if (mExtractor == NULL) {
+ mSource.clear();
+
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+static VideoFrame *extractVideoFrameWithCodecFlags(
+ OMXClient *client,
+ const sp<MetaData> &trackMeta,
+ const sp<MediaSource> &source,
+ uint32_t flags,
+ int64_t frameTimeUs,
+ int seekMode) {
+ sp<MediaSource> decoder =
+ OMXCodec::Create(
+ client->interface(), source->getFormat(), false, source,
+ NULL, flags | OMXCodec::kClientNeedsFramebuffer);
+
+ if (decoder.get() == NULL) {
+ ALOGV("unable to instantiate video decoder.");
+
+ return NULL;
+ }
+
+ status_t err = decoder->start();
+ if (err != OK) {
+ ALOGW("OMXCodec::start returned error %d (0x%08x)\n", err, err);
+ return NULL;
+ }
+
+ // Read one output buffer, ignore format change notifications
+ // and spurious empty buffers.
+
+ MediaSource::ReadOptions options;
+ if (seekMode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC ||
+ seekMode > MediaSource::ReadOptions::SEEK_CLOSEST) {
+
+ ALOGE("Unknown seek mode: %d", seekMode);
+ return NULL;
+ }
+
+ MediaSource::ReadOptions::SeekMode mode =
+ static_cast<MediaSource::ReadOptions::SeekMode>(seekMode);
+
+ int64_t thumbNailTime;
+ if (frameTimeUs < 0) {
+ if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)
+ || thumbNailTime < 0) {
+ thumbNailTime = 0;
+ }
+ options.setSeekTo(thumbNailTime, mode);
+ } else {
+ thumbNailTime = -1;
+ options.setSeekTo(frameTimeUs, mode);
+ }
+
+ MediaBuffer *buffer = NULL;
+ do {
+ if (buffer != NULL) {
+ buffer->release();
+ buffer = NULL;
+ }
+ err = decoder->read(&buffer, &options);
+ options.clearSeekTo();
+ } while (err == INFO_FORMAT_CHANGED
+ || (buffer != NULL && buffer->range_length() == 0));
+
+ if (err != OK) {
+ CHECK(buffer == NULL);
+
+ ALOGV("decoding frame failed.");
+ decoder->stop();
+
+ return NULL;
+ }
+
+ ALOGV("successfully decoded video frame.");
+
+ int32_t unreadable;
+ if (buffer->meta_data()->findInt32(kKeyIsUnreadable, &unreadable)
+ && unreadable != 0) {
+ ALOGV("video frame is unreadable, decoder does not give us access "
+ "to the video data.");
+
+ buffer->release();
+ buffer = NULL;
+
+ decoder->stop();
+
+ return NULL;
+ }
+
+ int64_t timeUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ if (thumbNailTime >= 0) {
+ if (timeUs != thumbNailTime) {
+ const char *mime;
+ CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
+
+ ALOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s",
+ thumbNailTime, timeUs, mime);
+ }
+ }
+
+ sp<MetaData> meta = decoder->getFormat();
+
+ int32_t width, height;
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+
+ int32_t crop_left, crop_top, crop_right, crop_bottom;
+ if (!meta->findRect(
+ kKeyCropRect,
+ &crop_left, &crop_top, &crop_right, &crop_bottom)) {
+ crop_left = crop_top = 0;
+ crop_right = width - 1;
+ crop_bottom = height - 1;
+ }
+
+ int32_t rotationAngle;
+ if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
+ rotationAngle = 0; // By default, no rotation
+ }
+
+ VideoFrame *frame = new VideoFrame;
+ frame->mWidth = crop_right - crop_left + 1;
+ frame->mHeight = crop_bottom - crop_top + 1;
+ frame->mDisplayWidth = frame->mWidth;
+ frame->mDisplayHeight = frame->mHeight;
+ frame->mSize = frame->mWidth * frame->mHeight * 2;
+ frame->mData = new uint8_t[frame->mSize];
+ frame->mRotationAngle = rotationAngle;
+
+ int32_t displayWidth, displayHeight;
+ if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
+ frame->mDisplayWidth = displayWidth;
+ }
+ if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
+ frame->mDisplayHeight = displayHeight;
+ }
+
+ int32_t srcFormat;
+ CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
+
+ ColorConverter converter(
+ (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
+ CHECK(converter.isValid());
+
+ err = converter.convert(
+ (const uint8_t *)buffer->data() + buffer->range_offset(),
+ width, height,
+ crop_left, crop_top, crop_right, crop_bottom,
+ frame->mData,
+ frame->mWidth,
+ frame->mHeight,
+ 0, 0, frame->mWidth - 1, frame->mHeight - 1);
+
+ buffer->release();
+ buffer = NULL;
+
+ decoder->stop();
+
+ if (err != OK) {
+ ALOGE("Colorconverter failed to convert frame.");
+
+ delete frame;
+ frame = NULL;
+ }
+
+ return frame;
+}
+
+VideoFrame *StagefrightMetadataRetriever::getFrameAtTime(
+ int64_t timeUs, int option) {
+
+ ALOGV("getFrameAtTime: %lld us option: %d", timeUs, option);
+
+ if (mExtractor.get() == NULL) {
+ ALOGV("no extractor.");
+ return NULL;
+ }
+
+ sp<MetaData> fileMeta = mExtractor->getMetaData();
+
+ if (fileMeta == NULL) {
+ ALOGV("extractor doesn't publish metadata, failed to initialize?");
+ return NULL;
+ }
+
+ int32_t drm = 0;
+ if (fileMeta->findInt32(kKeyIsDRM, &drm) && drm != 0) {
+ ALOGE("frame grab not allowed.");
+ return NULL;
+ }
+
+ size_t n = mExtractor->countTracks();
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ sp<MetaData> meta = mExtractor->getTrackMetaData(i);
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (!strncasecmp(mime, "video/", 6)) {
+ break;
+ }
+ }
+
+ if (i == n) {
+ ALOGV("no video track found.");
+ return NULL;
+ }
+
+ sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
+ i, MediaExtractor::kIncludeExtensiveMetaData);
+
+ sp<MediaSource> source = mExtractor->getTrack(i);
+
+ if (source.get() == NULL) {
+ ALOGV("unable to instantiate video track.");
+ return NULL;
+ }
+
+ const void *data;
+ uint32_t type;
+ size_t dataSize;
+ if (fileMeta->findData(kKeyAlbumArt, &type, &data, &dataSize)
+ && mAlbumArt == NULL) {
+ mAlbumArt = new MediaAlbumArt;
+ mAlbumArt->mSize = dataSize;
+ mAlbumArt->mData = new uint8_t[dataSize];
+ memcpy(mAlbumArt->mData, data, dataSize);
+ }
+
+ VideoFrame *frame =
+ extractVideoFrameWithCodecFlags(
+ &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs,
+ timeUs, option);
+
+ if (frame == NULL) {
+ ALOGV("Software decoder failed to extract thumbnail, "
+ "trying hardware decoder.");
+
+ frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0,
+ timeUs, option);
+ }
+
+ return frame;
+}
+
+MediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() {
+ ALOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO");
+
+ if (mExtractor == NULL) {
+ return NULL;
+ }
+
+ if (!mParsedMetaData) {
+ parseMetaData();
+
+ mParsedMetaData = true;
+ }
+
+ if (mAlbumArt) {
+ return new MediaAlbumArt(*mAlbumArt);
+ }
+
+ return NULL;
+}
+
+const char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
+ if (mExtractor == NULL) {
+ return NULL;
+ }
+
+ if (!mParsedMetaData) {
+ parseMetaData();
+
+ mParsedMetaData = true;
+ }
+
+ ssize_t index = mMetaData.indexOfKey(keyCode);
+
+ if (index < 0) {
+ return NULL;
+ }
+
+ return strdup(mMetaData.valueAt(index).string());
+}
+
+void StagefrightMetadataRetriever::parseMetaData() {
+ sp<MetaData> meta = mExtractor->getMetaData();
+
+ if (meta == NULL) {
+ ALOGV("extractor doesn't publish metadata, failed to initialize?");
+ return;
+ }
+
+ struct Map {
+ int from;
+ int to;
+ };
+ static const Map kMap[] = {
+ { kKeyMIMEType, METADATA_KEY_MIMETYPE },
+ { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER },
+ { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER },
+ { kKeyAlbum, METADATA_KEY_ALBUM },
+ { kKeyArtist, METADATA_KEY_ARTIST },
+ { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST },
+ { kKeyAuthor, METADATA_KEY_AUTHOR },
+ { kKeyComposer, METADATA_KEY_COMPOSER },
+ { kKeyDate, METADATA_KEY_DATE },
+ { kKeyGenre, METADATA_KEY_GENRE },
+ { kKeyTitle, METADATA_KEY_TITLE },
+ { kKeyYear, METADATA_KEY_YEAR },
+ { kKeyWriter, METADATA_KEY_WRITER },
+ { kKeyCompilation, METADATA_KEY_COMPILATION },
+ { kKeyLocation, METADATA_KEY_LOCATION },
+ };
+ static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
+
+ for (size_t i = 0; i < kNumMapEntries; ++i) {
+ const char *value;
+ if (meta->findCString(kMap[i].from, &value)) {
+ mMetaData.add(kMap[i].to, String8(value));
+ }
+ }
+
+ const void *data;
+ uint32_t type;
+ size_t dataSize;
+ if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize)
+ && mAlbumArt == NULL) {
+ mAlbumArt = new MediaAlbumArt;
+ mAlbumArt->mSize = dataSize;
+ mAlbumArt->mData = new uint8_t[dataSize];
+ memcpy(mAlbumArt->mData, data, dataSize);
+ }
+
+ size_t numTracks = mExtractor->countTracks();
+
+ char tmp[32];
+ sprintf(tmp, "%d", numTracks);
+
+ mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
+
+ bool hasAudio = false;
+ bool hasVideo = false;
+ int32_t videoWidth = -1;
+ int32_t videoHeight = -1;
+ int32_t audioBitrate = -1;
+
+ // The overall duration is the duration of the longest track.
+ int64_t maxDurationUs = 0;
+ String8 timedTextLang;
+ for (size_t i = 0; i < numTracks; ++i) {
+ sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
+
+ int64_t durationUs;
+ if (trackMeta->findInt64(kKeyDuration, &durationUs)) {
+ if (durationUs > maxDurationUs) {
+ maxDurationUs = durationUs;
+ }
+ }
+
+ const char *mime;
+ if (trackMeta->findCString(kKeyMIMEType, &mime)) {
+ if (!hasAudio && !strncasecmp("audio/", mime, 6)) {
+ hasAudio = true;
+
+ if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) {
+ audioBitrate = -1;
+ }
+ } else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
+ hasVideo = true;
+
+ CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth));
+ CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight));
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+ const char *lang;
+ trackMeta->findCString(kKeyMediaLanguage, &lang);
+ timedTextLang.append(String8(lang));
+ timedTextLang.append(String8(":"));
+ }
+ }
+ }
+
+ // To save the language codes for all timed text tracks
+ // If multiple text tracks present, the format will look
+ // like "eng:chi"
+ if (!timedTextLang.isEmpty()) {
+ mMetaData.add(METADATA_KEY_TIMED_TEXT_LANGUAGES, timedTextLang);
+ }
+
+ // 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 (hasAudio) {
+ mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes"));
+ }
+
+ if (hasVideo) {
+ mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes"));
+
+ sprintf(tmp, "%d", videoWidth);
+ mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp));
+
+ sprintf(tmp, "%d", videoHeight);
+ mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp));
+ }
+
+ if (numTracks == 1 && hasAudio && audioBitrate >= 0) {
+ sprintf(tmp, "%d", audioBitrate);
+ mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
+ } else {
+ off64_t sourceSize;
+ if (mSource->getSize(&sourceSize) == OK) {
+ int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs);
+
+ sprintf(tmp, "%lld", avgBitRate);
+ mMetaData.add(METADATA_KEY_BITRATE, 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"));
+ }
+ }
+ }
+
+ // To check whether the media file is drm-protected
+ if (mExtractor->getDrmFlag()) {
+ mMetaData.add(METADATA_KEY_IS_DRM, String8("1"));
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
new file mode 100644
index 0000000..7481e2e
--- /dev/null
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -0,0 +1,873 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SurfaceMediaSource"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/SurfaceMediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaDefs.h>
+#include <OMX_IVCommon.h>
+#include <MetadataBufferType.h>
+
+#include <ui/GraphicBuffer.h>
+#include <gui/ISurfaceComposer.h>
+#include <gui/IGraphicBufferAlloc.h>
+#include <OMX_Component.h>
+
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include <private/gui/ComposerService.h>
+
+namespace android {
+
+SurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) :
+ mDefaultWidth(bufW),
+ mDefaultHeight(bufH),
+ mPixelFormat(0),
+ mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
+ mClientBufferCount(0),
+ mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
+ mCurrentSlot(INVALID_BUFFER_SLOT),
+ mCurrentTimestamp(0),
+ mSynchronousMode(true),
+ mConnectedApi(NO_CONNECTED_API),
+ mFrameRate(30),
+ mStopped(false),
+ mNumFramesReceived(0),
+ mNumFramesEncoded(0),
+ mFirstFrameTimestamp(0) {
+ ALOGV("SurfaceMediaSource::SurfaceMediaSource");
+ sp<ISurfaceComposer> composer(ComposerService::getComposerService());
+ mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
+ if (mGraphicBufferAlloc == 0) {
+ ALOGE("createGraphicBufferAlloc() failed in SurfaceMediaSource()");
+ }
+}
+
+SurfaceMediaSource::~SurfaceMediaSource() {
+ ALOGV("SurfaceMediaSource::~SurfaceMediaSource");
+ if (!mStopped) {
+ reset();
+ }
+}
+
+size_t SurfaceMediaSource::getQueuedCount() const {
+ Mutex::Autolock lock(mMutex);
+ return mQueue.size();
+}
+
+status_t SurfaceMediaSource::setBufferCountServerLocked(int bufferCount) {
+ if (bufferCount > NUM_BUFFER_SLOTS)
+ return BAD_VALUE;
+
+ // special-case, nothing to do
+ if (bufferCount == mBufferCount)
+ return OK;
+
+ if (!mClientBufferCount &&
+ bufferCount >= mBufferCount) {
+ // easy, we just have more buffers
+ mBufferCount = bufferCount;
+ mServerBufferCount = bufferCount;
+ mDequeueCondition.signal();
+ } else {
+ // we're here because we're either
+ // - reducing the number of available buffers
+ // - or there is a client-buffer-count in effect
+
+ // less than 2 buffers is never allowed
+ if (bufferCount < 2)
+ return BAD_VALUE;
+
+ // when there is non client-buffer-count in effect, the client is not
+ // allowed to dequeue more than one buffer at a time,
+ // so the next time they dequeue a buffer, we know that they don't
+ // own one. the actual resizing will happen during the next
+ // dequeueBuffer.
+
+ mServerBufferCount = bufferCount;
+ }
+ return OK;
+}
+
+// Called from the consumer side
+status_t SurfaceMediaSource::setBufferCountServer(int bufferCount) {
+ Mutex::Autolock lock(mMutex);
+ return setBufferCountServerLocked(bufferCount);
+}
+
+status_t SurfaceMediaSource::setBufferCount(int bufferCount) {
+ ALOGV("SurfaceMediaSource::setBufferCount");
+ if (bufferCount > NUM_BUFFER_SLOTS) {
+ ALOGE("setBufferCount: bufferCount is larger than the number of buffer slots");
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mMutex);
+ // Error out if the user has dequeued buffers
+ for (int i = 0 ; i < mBufferCount ; i++) {
+ if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
+ ALOGE("setBufferCount: client owns some buffers");
+ return INVALID_OPERATION;
+ }
+ }
+
+ if (bufferCount == 0) {
+ const int minBufferSlots = mSynchronousMode ?
+ MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+ mClientBufferCount = 0;
+ bufferCount = (mServerBufferCount >= minBufferSlots) ?
+ mServerBufferCount : minBufferSlots;
+ return setBufferCountServerLocked(bufferCount);
+ }
+
+ // We don't allow the client to set a buffer-count less than
+ // MIN_ASYNC_BUFFER_SLOTS (3), there is no reason for it.
+ if (bufferCount < MIN_ASYNC_BUFFER_SLOTS) {
+ return BAD_VALUE;
+ }
+
+ // here we're guaranteed that the client doesn't have dequeued buffers
+ // and will release all of its buffer references.
+ mBufferCount = bufferCount;
+ mClientBufferCount = bufferCount;
+ mCurrentSlot = INVALID_BUFFER_SLOT;
+ mQueue.clear();
+ mDequeueCondition.signal();
+ freeAllBuffersLocked();
+ return OK;
+}
+
+status_t SurfaceMediaSource::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
+ ALOGV("SurfaceMediaSource::requestBuffer");
+ Mutex::Autolock lock(mMutex);
+ if (slot < 0 || mBufferCount <= slot) {
+ ALOGE("requestBuffer: slot index out of range [0, %d]: %d",
+ mBufferCount, slot);
+ return BAD_VALUE;
+ }
+ mSlots[slot].mRequestBufferCalled = true;
+ *buf = mSlots[slot].mGraphicBuffer;
+ return NO_ERROR;
+}
+
+status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
+ uint32_t format, uint32_t usage) {
+ ALOGV("dequeueBuffer");
+ Mutex::Autolock lock(mMutex);
+
+ // Check for the buffer size- the client should just use the
+ // default width and height, and not try to set those.
+ // This is needed since
+ // the getFormat() returns mDefaultWidth/ Height for the OMX. It is
+ // queried by OMX in the beginning and not every time a frame comes.
+ // Not sure if there is a way to update the
+ // frame size while recording. So as of now, the client side
+ // sets the default values via the constructor, and the encoder is
+ // setup to encode frames of that size
+ // The design might need to change in the future.
+ // TODO: Currently just uses mDefaultWidth/Height. In the future
+ // we might declare mHeight and mWidth and check against those here.
+ if ((w != 0) || (h != 0)) {
+ if ((w != mDefaultWidth) || (h != mDefaultHeight)) {
+ ALOGE("dequeuebuffer: invalid buffer size! Req: %dx%d, Found: %dx%d",
+ mDefaultWidth, mDefaultHeight, w, h);
+ return BAD_VALUE;
+ }
+ }
+
+ status_t returnFlags(OK);
+ int found, foundSync;
+ int dequeuedCount = 0;
+ bool tryAgain = true;
+ while (tryAgain) {
+ // We need to wait for the FIFO to drain if the number of buffer
+ // needs to change.
+ //
+ // The condition "number of buffer needs to change" is true if
+ // - the client doesn't care about how many buffers there are
+ // - AND the actual number of buffer is different from what was
+ // set in the last setBufferCountServer()
+ // - OR -
+ // setBufferCountServer() was set to a value incompatible with
+ // the synchronization mode (for instance because the sync mode
+ // changed since)
+ //
+ // As long as this condition is true AND the FIFO is not empty, we
+ // wait on mDequeueCondition.
+
+ int minBufferCountNeeded = mSynchronousMode ?
+ MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+
+ if (!mClientBufferCount &&
+ ((mServerBufferCount != mBufferCount) ||
+ (mServerBufferCount < minBufferCountNeeded))) {
+ // wait for the FIFO to drain
+ while (!mQueue.isEmpty()) {
+ ALOGV("Waiting for the FIFO to drain");
+ mDequeueCondition.wait(mMutex);
+ }
+ if (mStopped) {
+ return NO_INIT;
+ }
+ // need to check again since the mode could have changed
+ // while we were waiting
+ minBufferCountNeeded = mSynchronousMode ?
+ MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
+ }
+
+ if (!mClientBufferCount &&
+ ((mServerBufferCount != mBufferCount) ||
+ (mServerBufferCount < minBufferCountNeeded))) {
+ // here we're guaranteed that mQueue is empty
+ freeAllBuffersLocked();
+ mBufferCount = mServerBufferCount;
+ if (mBufferCount < minBufferCountNeeded)
+ mBufferCount = minBufferCountNeeded;
+ mCurrentSlot = INVALID_BUFFER_SLOT;
+ returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
+ }
+
+ // look for a free buffer to give to the client
+ found = INVALID_BUFFER_SLOT;
+ foundSync = INVALID_BUFFER_SLOT;
+ dequeuedCount = 0;
+ for (int i = 0; i < mBufferCount; i++) {
+ const int state = mSlots[i].mBufferState;
+ if (state == BufferSlot::DEQUEUED) {
+ dequeuedCount++;
+ continue; // won't be continuing if could
+ // dequeue a non 'FREE' current slot like
+ // that in SurfaceTexture
+ }
+ // In case of Encoding, we do not deque the mCurrentSlot buffer
+ // since we follow synchronous mode (unlike possibly in
+ // SurfaceTexture that could be using the asynch mode
+ // or has some mechanism in GL to be able to wait till the
+ // currentslot is done using the data)
+ // Here, we have to wait for the MPEG4Writer(or equiv)
+ // to tell us when it's done using the current buffer
+ if (state == BufferSlot::FREE) {
+ foundSync = i;
+ // Unlike that in SurfaceTexture,
+ // We don't need to worry if it is the
+ // currentslot or not as it is in state FREE
+ found = i;
+ break;
+ }
+ }
+
+ // clients are not allowed to dequeue more than one buffer
+ // if they didn't set a buffer count.
+ if (!mClientBufferCount && dequeuedCount) {
+ return -EINVAL;
+ }
+
+ // See whether a buffer has been queued since the last setBufferCount so
+ // we know whether to perform the MIN_UNDEQUEUED_BUFFERS check below.
+ bool bufferHasBeenQueued = mCurrentSlot != INVALID_BUFFER_SLOT;
+ if (bufferHasBeenQueued) {
+ // make sure the client is not trying to dequeue more buffers
+ // than allowed.
+ const int avail = mBufferCount - (dequeuedCount+1);
+ if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
+ ALOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)",
+ MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
+ dequeuedCount);
+ return -EBUSY;
+ }
+ }
+
+ // we're in synchronous mode and didn't find a buffer, we need to wait
+ // for for some buffers to be consumed
+ tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
+ if (tryAgain) {
+ ALOGV("Waiting..In synchronous mode and no buffer to dequeue");
+ mDequeueCondition.wait(mMutex);
+ }
+ if (mStopped) {
+ return NO_INIT;
+ }
+ }
+
+ if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
+ // foundSync guaranteed to be != INVALID_BUFFER_SLOT
+ found = foundSync;
+ }
+
+ if (found == INVALID_BUFFER_SLOT) {
+ return -EBUSY;
+ }
+
+ const int bufIndex = found;
+ *outBuf = found;
+
+ const bool useDefaultSize = !w && !h;
+ if (useDefaultSize) {
+ // use the default size
+ w = mDefaultWidth;
+ h = mDefaultHeight;
+ }
+
+ const bool updateFormat = (format != 0);
+ if (!updateFormat) {
+ // keep the current (or default) format
+ format = mPixelFormat;
+ }
+
+ // buffer is now in DEQUEUED (but can also be current at the same time,
+ // if we're in synchronous mode)
+ mSlots[bufIndex].mBufferState = BufferSlot::DEQUEUED;
+
+ const sp<GraphicBuffer>& buffer(mSlots[bufIndex].mGraphicBuffer);
+ if ((buffer == NULL) ||
+ (uint32_t(buffer->width) != w) ||
+ (uint32_t(buffer->height) != h) ||
+ (uint32_t(buffer->format) != format) ||
+ ((uint32_t(buffer->usage) & usage) != usage)) {
+ // XXX: This will be changed to USAGE_HW_VIDEO_ENCODER once driver
+ // issues with that flag get fixed.
+ usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+ status_t error;
+ sp<GraphicBuffer> graphicBuffer(
+ mGraphicBufferAlloc->createGraphicBuffer(
+ w, h, format, usage, &error));
+ if (graphicBuffer == 0) {
+ ALOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
+ return error;
+ }
+ if (updateFormat) {
+ mPixelFormat = format;
+ }
+ mSlots[bufIndex].mGraphicBuffer = graphicBuffer;
+ mSlots[bufIndex].mRequestBufferCalled = false;
+ returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
+ }
+ return returnFlags;
+}
+
+// TODO: clean this up
+status_t SurfaceMediaSource::setSynchronousMode(bool enabled) {
+ Mutex::Autolock lock(mMutex);
+ if (mStopped) {
+ ALOGE("setSynchronousMode: SurfaceMediaSource has been stopped!");
+ return NO_INIT;
+ }
+
+ if (!enabled) {
+ // Async mode is not allowed
+ ALOGE("SurfaceMediaSource can be used only synchronous mode!");
+ return INVALID_OPERATION;
+ }
+
+ if (mSynchronousMode != enabled) {
+ // - if we're going to asynchronous mode, the queue is guaranteed to be
+ // empty here
+ // - if the client set the number of buffers, we're guaranteed that
+ // we have at least 3 (because we don't allow less)
+ mSynchronousMode = enabled;
+ mDequeueCondition.signal();
+ }
+ return OK;
+}
+
+status_t SurfaceMediaSource::connect(int api,
+ uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
+ ALOGV("SurfaceMediaSource::connect");
+ Mutex::Autolock lock(mMutex);
+
+ if (mStopped) {
+ ALOGE("Connect: SurfaceMediaSource has been stopped!");
+ return NO_INIT;
+ }
+
+ status_t err = NO_ERROR;
+ switch (api) {
+ case NATIVE_WINDOW_API_EGL:
+ case NATIVE_WINDOW_API_CPU:
+ case NATIVE_WINDOW_API_MEDIA:
+ case NATIVE_WINDOW_API_CAMERA:
+ if (mConnectedApi != NO_CONNECTED_API) {
+ err = -EINVAL;
+ } else {
+ mConnectedApi = api;
+ *outWidth = mDefaultWidth;
+ *outHeight = mDefaultHeight;
+ *outTransform = 0;
+ }
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ return err;
+}
+
+// This is called by the client side when it is done
+// TODO: Currently, this also sets mStopped to true which
+// is needed for unblocking the encoder which might be
+// waiting to read more frames. So if on the client side,
+// the same thread supplies the frames and also calls stop
+// on the encoder, the client has to call disconnect before
+// it calls stop.
+// In the case of the camera,
+// that need not be required since the thread supplying the
+// frames is separate than the one calling stop.
+status_t SurfaceMediaSource::disconnect(int api) {
+ ALOGV("SurfaceMediaSource::disconnect");
+ Mutex::Autolock lock(mMutex);
+
+ if (mStopped) {
+ ALOGE("disconnect: SurfaceMediaSoource is already stopped!");
+ return NO_INIT;
+ }
+
+ status_t err = NO_ERROR;
+ switch (api) {
+ case NATIVE_WINDOW_API_EGL:
+ case NATIVE_WINDOW_API_CPU:
+ case NATIVE_WINDOW_API_MEDIA:
+ case NATIVE_WINDOW_API_CAMERA:
+ if (mConnectedApi == api) {
+ mConnectedApi = NO_CONNECTED_API;
+ mStopped = true;
+ mDequeueCondition.signal();
+ mFrameAvailableCondition.signal();
+ } else {
+ err = -EINVAL;
+ }
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ return err;
+}
+
+status_t SurfaceMediaSource::queueBuffer(int bufIndex, int64_t timestamp,
+ uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
+ ALOGV("queueBuffer");
+
+ Mutex::Autolock lock(mMutex);
+ *outWidth = mDefaultWidth;
+ *outHeight = mDefaultHeight;
+ *outTransform = 0;
+
+ if (bufIndex < 0 || bufIndex >= mBufferCount) {
+ ALOGE("queueBuffer: slot index out of range [0, %d]: %d",
+ mBufferCount, bufIndex);
+ return -EINVAL;
+ } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) {
+ ALOGE("queueBuffer: slot %d is not owned by the client (state=%d)",
+ bufIndex, mSlots[bufIndex].mBufferState);
+ return -EINVAL;
+ } else if (!mSlots[bufIndex].mRequestBufferCalled) {
+ ALOGE("queueBuffer: slot %d was enqueued without requesting a "
+ "buffer", bufIndex);
+ return -EINVAL;
+ }
+
+ if (mNumFramesReceived == 0) {
+ mFirstFrameTimestamp = timestamp;
+ // Initial delay
+ if (mStartTimeNs > 0) {
+ if (timestamp < mStartTimeNs) {
+ // This frame predates start of record, discard
+ mSlots[bufIndex].mBufferState = BufferSlot::FREE;
+ mDequeueCondition.signal();
+ return OK;
+ }
+ mStartTimeNs = timestamp - mStartTimeNs;
+ }
+ }
+ timestamp = mStartTimeNs + (timestamp - mFirstFrameTimestamp);
+
+ mNumFramesReceived++;
+ if (mSynchronousMode) {
+ // in synchronous mode we queue all buffers in a FIFO
+ mQueue.push_back(bufIndex);
+ ALOGV("Client queued buf# %d @slot: %d, Q size = %d, handle = %p, timestamp = %lld",
+ mNumFramesReceived, bufIndex, mQueue.size(),
+ mSlots[bufIndex].mGraphicBuffer->handle, timestamp);
+ } else {
+ // in asynchronous mode we only keep the most recent buffer
+ if (mQueue.empty()) {
+ mQueue.push_back(bufIndex);
+ } else {
+ Fifo::iterator front(mQueue.begin());
+ // buffer currently queued is freed
+ mSlots[*front].mBufferState = BufferSlot::FREE;
+ // and we record the new buffer index in the queued list
+ *front = bufIndex;
+ }
+ }
+
+ mSlots[bufIndex].mBufferState = BufferSlot::QUEUED;
+ mSlots[bufIndex].mTimestamp = timestamp;
+ // TODO: (Confirm) Don't want to signal dequeue here.
+ // May be just in asynchronous mode?
+ // mDequeueCondition.signal();
+
+ // Once the queuing is done, we need to let the listener
+ // and signal the buffer consumer (encoder) know that a
+ // buffer is available
+ onFrameReceivedLocked();
+
+
+ return OK;
+}
+
+
+// onFrameReceivedLocked informs the buffer consumers (StageFrightRecorder)
+// or listeners that a frame has been received
+// It is supposed to be called only from queuebuffer.
+// The buffer is NOT made available for dequeueing immediately. We need to
+// wait to hear from StageFrightRecorder to set the buffer FREE
+// Make sure this is called when the mutex is locked
+status_t SurfaceMediaSource::onFrameReceivedLocked() {
+ ALOGV("On Frame Received locked");
+ // Signal the encoder that a new frame has arrived
+ mFrameAvailableCondition.signal();
+
+ // call back the listener
+ // TODO: The listener may not be needed in SurfaceMediaSource at all.
+ // This can be made a SurfaceTexture specific thing
+ sp<FrameAvailableListener> listener;
+ if (mSynchronousMode || mQueue.empty()) {
+ listener = mFrameAvailableListener;
+ }
+
+ if (listener != 0) {
+ listener->onFrameAvailable();
+ }
+ return OK;
+}
+
+
+void SurfaceMediaSource::cancelBuffer(int bufIndex) {
+ ALOGV("SurfaceMediaSource::cancelBuffer");
+ Mutex::Autolock lock(mMutex);
+ if (bufIndex < 0 || bufIndex >= mBufferCount) {
+ ALOGE("cancelBuffer: slot index out of range [0, %d]: %d",
+ mBufferCount, bufIndex);
+ return;
+ } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) {
+ ALOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
+ bufIndex, mSlots[bufIndex].mBufferState);
+ return;
+ }
+ mSlots[bufIndex].mBufferState = BufferSlot::FREE;
+ mDequeueCondition.signal();
+}
+
+nsecs_t SurfaceMediaSource::getTimestamp() {
+ ALOGV("SurfaceMediaSource::getTimestamp");
+ Mutex::Autolock lock(mMutex);
+ return mCurrentTimestamp;
+}
+
+
+void SurfaceMediaSource::setFrameAvailableListener(
+ const sp<FrameAvailableListener>& listener) {
+ ALOGV("SurfaceMediaSource::setFrameAvailableListener");
+ Mutex::Autolock lock(mMutex);
+ mFrameAvailableListener = listener;
+}
+
+void SurfaceMediaSource::freeAllBuffersLocked() {
+ ALOGV("freeAllBuffersLocked");
+ for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+ mSlots[i].mGraphicBuffer = 0;
+ mSlots[i].mBufferState = BufferSlot::FREE;
+ }
+}
+
+sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const {
+ Mutex::Autolock lock(mMutex);
+ return mCurrentBuf;
+}
+
+int SurfaceMediaSource::query(int what, int* outValue)
+{
+ ALOGV("query");
+ Mutex::Autolock lock(mMutex);
+ int value;
+ switch (what) {
+ case NATIVE_WINDOW_WIDTH:
+ value = mDefaultWidth;
+ if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
+ value = mCurrentBuf->width;
+ break;
+ case NATIVE_WINDOW_HEIGHT:
+ value = mDefaultHeight;
+ if (!mDefaultWidth && !mDefaultHeight && mCurrentBuf != 0)
+ value = mCurrentBuf->height;
+ break;
+ case NATIVE_WINDOW_FORMAT:
+ value = mPixelFormat;
+ break;
+ case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
+ value = mSynchronousMode ?
+ (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
+ break;
+ default:
+ return BAD_VALUE;
+ }
+ outValue[0] = value;
+ return NO_ERROR;
+}
+
+void SurfaceMediaSource::dump(String8& result) const
+{
+ char buffer[1024];
+ dump(result, "", buffer, 1024);
+}
+
+void SurfaceMediaSource::dump(String8& result, const char* prefix,
+ char* buffer, size_t SIZE) const
+{
+ Mutex::Autolock _l(mMutex);
+ snprintf(buffer, SIZE,
+ "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
+ "mPixelFormat=%d, \n",
+ prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight,
+ mPixelFormat);
+ result.append(buffer);
+
+ String8 fifo;
+ int fifoSize = 0;
+ Fifo::const_iterator i(mQueue.begin());
+ while (i != mQueue.end()) {
+ snprintf(buffer, SIZE, "%02d ", *i++);
+ fifoSize++;
+ fifo.append(buffer);
+ }
+
+ result.append(buffer);
+
+ struct {
+ const char * operator()(int state) const {
+ switch (state) {
+ case BufferSlot::DEQUEUED: return "DEQUEUED";
+ case BufferSlot::QUEUED: return "QUEUED";
+ case BufferSlot::FREE: return "FREE";
+ default: return "Unknown";
+ }
+ }
+ } stateName;
+
+ for (int i = 0; i < mBufferCount; i++) {
+ const BufferSlot& slot(mSlots[i]);
+ snprintf(buffer, SIZE,
+ "%s%s[%02d] state=%-8s, "
+ "timestamp=%lld\n",
+ prefix, (i==mCurrentSlot)?">":" ", i, stateName(slot.mBufferState),
+ slot.mTimestamp
+ );
+ result.append(buffer);
+ }
+}
+
+status_t SurfaceMediaSource::setFrameRate(int32_t fps)
+{
+ Mutex::Autolock lock(mMutex);
+ const int MAX_FRAME_RATE = 60;
+ if (fps < 0 || fps > MAX_FRAME_RATE) {
+ return BAD_VALUE;
+ }
+ mFrameRate = fps;
+ return OK;
+}
+
+bool SurfaceMediaSource::isMetaDataStoredInVideoBuffers() const {
+ ALOGV("isMetaDataStoredInVideoBuffers");
+ return true;
+}
+
+int32_t SurfaceMediaSource::getFrameRate( ) const {
+ Mutex::Autolock lock(mMutex);
+ return mFrameRate;
+}
+
+status_t SurfaceMediaSource::start(MetaData *params)
+{
+ ALOGV("started!");
+
+ mStartTimeNs = 0;
+ int64_t startTimeUs;
+ if (params && params->findInt64(kKeyTime, &startTimeUs)) {
+ mStartTimeNs = startTimeUs * 1000;
+ }
+
+ return OK;
+}
+
+
+status_t SurfaceMediaSource::reset()
+{
+ ALOGV("Reset");
+
+ Mutex::Autolock lock(mMutex);
+ // TODO: Add waiting on mFrameCompletedCondition here?
+ mStopped = true;
+ mFrameAvailableCondition.signal();
+ mDequeueCondition.signal();
+ mQueue.clear();
+ freeAllBuffersLocked();
+
+ return OK;
+}
+
+sp<MetaData> SurfaceMediaSource::getFormat()
+{
+ ALOGV("getFormat");
+ Mutex::Autolock autoLock(mMutex);
+ sp<MetaData> meta = new MetaData;
+
+ meta->setInt32(kKeyWidth, mDefaultWidth);
+ meta->setInt32(kKeyHeight, mDefaultHeight);
+ // The encoder format is set as an opaque colorformat
+ // The encoder will later find out the actual colorformat
+ // from the GL Frames itself.
+ meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatAndroidOpaque);
+ meta->setInt32(kKeyStride, mDefaultWidth);
+ meta->setInt32(kKeySliceHeight, mDefaultHeight);
+ meta->setInt32(kKeyFrameRate, mFrameRate);
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+ return meta;
+}
+
+status_t SurfaceMediaSource::read( MediaBuffer **buffer,
+ const ReadOptions *options)
+{
+ Mutex::Autolock autoLock(mMutex) ;
+
+ ALOGV("Read. Size of queued buffer: %d", mQueue.size());
+ *buffer = NULL;
+
+ // If the recording has started and the queue is empty, then just
+ // wait here till the frames come in from the client side
+ while (!mStopped && mQueue.empty()) {
+ ALOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition");
+ mFrameAvailableCondition.wait(mMutex);
+ }
+
+ // If the loop was exited as a result of stopping the recording,
+ // it is OK
+ if (mStopped) {
+ ALOGV("Read: SurfaceMediaSource is stopped. Returning ERROR_END_OF_STREAM.");
+ return ERROR_END_OF_STREAM;
+ }
+
+ // Update the current buffer info
+ // TODO: mCurrentSlot can be made a bufferstate since there
+ // can be more than one "current" slots.
+ Fifo::iterator front(mQueue.begin());
+ mCurrentSlot = *front;
+ mQueue.erase(front);
+ mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer;
+ int64_t prevTimeStamp = mCurrentTimestamp;
+ mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp;
+
+ mNumFramesEncoded++;
+ // Pass the data to the MediaBuffer. Pass in only the metadata
+ passMetadataBufferLocked(buffer);
+
+ (*buffer)->setObserver(this);
+ (*buffer)->add_ref();
+ (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000);
+ ALOGV("Frames encoded = %d, timestamp = %lld, time diff = %lld",
+ mNumFramesEncoded, mCurrentTimestamp / 1000,
+ mCurrentTimestamp / 1000 - prevTimeStamp / 1000);
+
+ return OK;
+}
+
+// Pass the data to the MediaBuffer. Pass in only the metadata
+// The metadata passed consists of two parts:
+// 1. First, there is an integer indicating that it is a GRAlloc
+// source (kMetadataBufferTypeGrallocSource)
+// 2. This is followed by the buffer_handle_t that is a handle to the
+// GRalloc buffer. The encoder needs to interpret this GRalloc handle
+// and encode the frames.
+// --------------------------------------------------------------
+// | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
+// --------------------------------------------------------------
+// Note: Call only when you have the lock
+void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) {
+ ALOGV("passMetadataBuffer");
+ // MediaBuffer allocates and owns this data
+ MediaBuffer *tempBuffer =
+ new MediaBuffer(4 + sizeof(buffer_handle_t));
+ char *data = (char *)tempBuffer->data();
+ if (data == NULL) {
+ ALOGE("Cannot allocate memory for metadata buffer!");
+ return;
+ }
+ OMX_U32 type = kMetadataBufferTypeGrallocSource;
+ memcpy(data, &type, 4);
+ memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t));
+ *buffer = tempBuffer;
+
+ ALOGV("handle = %p, , offset = %d, length = %d",
+ mCurrentBuf->handle, (*buffer)->range_length(), (*buffer)->range_offset());
+}
+
+void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
+ ALOGV("signalBufferReturned");
+
+ bool foundBuffer = false;
+ Mutex::Autolock autoLock(mMutex);
+
+ if (mStopped) {
+ ALOGV("signalBufferReturned: mStopped = true! Nothing to do!");
+ return;
+ }
+
+ for (int id = 0; id < NUM_BUFFER_SLOTS; id++) {
+ if (mSlots[id].mGraphicBuffer == NULL) {
+ continue;
+ }
+ if (checkBufferMatchesSlot(id, buffer)) {
+ ALOGV("Slot %d returned, matches handle = %p", id,
+ mSlots[id].mGraphicBuffer->handle);
+ mSlots[id].mBufferState = BufferSlot::FREE;
+ buffer->setObserver(0);
+ buffer->release();
+ mDequeueCondition.signal();
+ mFrameCompleteCondition.signal();
+ foundBuffer = true;
+ break;
+ }
+ }
+
+ if (!foundBuffer) {
+ CHECK(!"signalBufferReturned: bogus buffer");
+ }
+}
+
+bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) {
+ ALOGV("Check if Buffer matches slot");
+ // need to convert to char* for pointer arithmetic and then
+ // copy the byte stream into our handle
+ buffer_handle_t bufferHandle ;
+ memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t));
+ return mSlots[slot].mGraphicBuffer->handle == bufferHandle;
+}
+
+} // end of namespace android
diff --git a/media/libstagefright/ThrottledSource.cpp b/media/libstagefright/ThrottledSource.cpp
new file mode 100644
index 0000000..b1fcafd
--- /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/foundation/ADebug.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(off64_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(off64_t *size) {
+ return mSource->getSize(size);
+}
+
+uint32_t ThrottledSource::flags() {
+ return mSource->flags();
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/TimeSource.cpp b/media/libstagefright/TimeSource.cpp
new file mode 100644
index 0000000..d987fbf
--- /dev/null
+++ b/media/libstagefright/TimeSource.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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 <stddef.h>
+#include <sys/time.h>
+
+#include <media/stagefright/TimeSource.h>
+
+namespace android {
+
+SystemTimeSource::SystemTimeSource()
+ : mStartTimeUs(GetSystemTimeUs()) {
+}
+
+int64_t SystemTimeSource::getRealTimeUs() {
+ return GetSystemTimeUs() - mStartTimeUs;
+}
+
+// static
+int64_t SystemTimeSource::GetSystemTimeUs() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp
new file mode 100644
index 0000000..9df15eb
--- /dev/null
+++ b/media/libstagefright/TimedEventQueue.cpp
@@ -0,0 +1,301 @@
+/*
+ * 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.
+ */
+
+#undef __STRICT_ANSI__
+#define __STDINT_LIMITS
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "TimedEventQueue"
+#include <utils/Log.h>
+#include <utils/threads.h>
+
+#include "include/TimedEventQueue.h"
+
+#include <sys/prctl.h>
+#include <sys/time.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+TimedEventQueue::TimedEventQueue()
+ : mNextEventID(1),
+ mRunning(false),
+ mStopped(false) {
+}
+
+TimedEventQueue::~TimedEventQueue() {
+ stop();
+}
+
+void TimedEventQueue::start() {
+ if (mRunning) {
+ return;
+ }
+
+ mStopped = false;
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+ pthread_create(&mThread, &attr, ThreadWrapper, this);
+
+ pthread_attr_destroy(&attr);
+
+ mRunning = true;
+}
+
+void TimedEventQueue::stop(bool flush) {
+ if (!mRunning) {
+ return;
+ }
+
+ if (flush) {
+ postEventToBack(new StopEvent);
+ } else {
+ postTimedEvent(new StopEvent, INT64_MIN);
+ }
+
+ void *dummy;
+ pthread_join(mThread, &dummy);
+
+ mQueue.clear();
+
+ mRunning = false;
+}
+
+TimedEventQueue::event_id TimedEventQueue::postEvent(const sp<Event> &event) {
+ // Reserve an earlier timeslot an INT64_MIN to be able to post
+ // the StopEvent to the absolute head of the queue.
+ return postTimedEvent(event, INT64_MIN + 1);
+}
+
+TimedEventQueue::event_id TimedEventQueue::postEventToBack(
+ const sp<Event> &event) {
+ return postTimedEvent(event, INT64_MAX);
+}
+
+TimedEventQueue::event_id TimedEventQueue::postEventWithDelay(
+ const sp<Event> &event, int64_t delay_us) {
+ CHECK(delay_us >= 0);
+ return postTimedEvent(event, getRealTimeUs() + delay_us);
+}
+
+TimedEventQueue::event_id TimedEventQueue::postTimedEvent(
+ const sp<Event> &event, int64_t realtime_us) {
+ Mutex::Autolock autoLock(mLock);
+
+ event->setEventID(mNextEventID++);
+
+ List<QueueItem>::iterator it = mQueue.begin();
+ while (it != mQueue.end() && realtime_us >= (*it).realtime_us) {
+ ++it;
+ }
+
+ QueueItem item;
+ item.event = event;
+ item.realtime_us = realtime_us;
+
+ if (it == mQueue.begin()) {
+ mQueueHeadChangedCondition.signal();
+ }
+
+ mQueue.insert(it, item);
+
+ mQueueNotEmptyCondition.signal();
+
+ return event->eventID();
+}
+
+static bool MatchesEventID(
+ void *cookie, const sp<TimedEventQueue::Event> &event) {
+ TimedEventQueue::event_id *id =
+ static_cast<TimedEventQueue::event_id *>(cookie);
+
+ if (event->eventID() != *id) {
+ return false;
+ }
+
+ *id = 0;
+
+ return true;
+}
+
+bool TimedEventQueue::cancelEvent(event_id id) {
+ if (id == 0) {
+ return false;
+ }
+
+ cancelEvents(&MatchesEventID, &id, true /* stopAfterFirstMatch */);
+
+ // if MatchesEventID found a match, it will have set id to 0
+ // (which is not a valid event_id).
+
+ return id == 0;
+}
+
+void TimedEventQueue::cancelEvents(
+ bool (*predicate)(void *cookie, const sp<Event> &event),
+ void *cookie,
+ bool stopAfterFirstMatch) {
+ Mutex::Autolock autoLock(mLock);
+
+ List<QueueItem>::iterator it = mQueue.begin();
+ while (it != mQueue.end()) {
+ if (!(*predicate)(cookie, (*it).event)) {
+ ++it;
+ continue;
+ }
+
+ if (it == mQueue.begin()) {
+ mQueueHeadChangedCondition.signal();
+ }
+
+ ALOGV("cancelling event %d", (*it).event->eventID());
+
+ (*it).event->setEventID(0);
+ it = mQueue.erase(it);
+
+ if (stopAfterFirstMatch) {
+ return;
+ }
+ }
+}
+
+// static
+int64_t TimedEventQueue::getRealTimeUs() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ return (int64_t)tv.tv_sec * 1000000ll + tv.tv_usec;
+}
+
+// static
+void *TimedEventQueue::ThreadWrapper(void *me) {
+
+ androidSetThreadPriority(0, ANDROID_PRIORITY_FOREGROUND);
+
+ static_cast<TimedEventQueue *>(me)->threadEntry();
+
+ return NULL;
+}
+
+void TimedEventQueue::threadEntry() {
+ prctl(PR_SET_NAME, (unsigned long)"TimedEventQueue", 0, 0, 0);
+
+ for (;;) {
+ int64_t now_us = 0;
+ sp<Event> event;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mStopped) {
+ break;
+ }
+
+ while (mQueue.empty()) {
+ mQueueNotEmptyCondition.wait(mLock);
+ }
+
+ event_id eventID = 0;
+ for (;;) {
+ if (mQueue.empty()) {
+ // The only event in the queue could have been cancelled
+ // while we were waiting for its scheduled time.
+ break;
+ }
+
+ List<QueueItem>::iterator it = mQueue.begin();
+ eventID = (*it).event->eventID();
+
+ now_us = getRealTimeUs();
+ int64_t when_us = (*it).realtime_us;
+
+ int64_t delay_us;
+ if (when_us < 0 || when_us == INT64_MAX) {
+ delay_us = 0;
+ } else {
+ delay_us = when_us - now_us;
+ }
+
+ if (delay_us <= 0) {
+ break;
+ }
+
+ static int64_t kMaxTimeoutUs = 10000000ll; // 10 secs
+ bool timeoutCapped = false;
+ if (delay_us > kMaxTimeoutUs) {
+ ALOGW("delay_us exceeds max timeout: %lld us", delay_us);
+
+ // We'll never block for more than 10 secs, instead
+ // we will split up the full timeout into chunks of
+ // 10 secs at a time. This will also avoid overflow
+ // when converting from us to ns.
+ delay_us = kMaxTimeoutUs;
+ timeoutCapped = true;
+ }
+
+ status_t err = mQueueHeadChangedCondition.waitRelative(
+ mLock, delay_us * 1000ll);
+
+ if (!timeoutCapped && err == -ETIMEDOUT) {
+ // We finally hit the time this event is supposed to
+ // trigger.
+ now_us = getRealTimeUs();
+ break;
+ }
+ }
+
+ // The event w/ this id may have been cancelled while we're
+ // waiting for its trigger-time, in that case
+ // removeEventFromQueue_l will return NULL.
+ // Otherwise, the QueueItem will be removed
+ // from the queue and the referenced event returned.
+ event = removeEventFromQueue_l(eventID);
+ }
+
+ if (event != NULL) {
+ // Fire event with the lock NOT held.
+ event->fire(this, now_us);
+ }
+ }
+}
+
+sp<TimedEventQueue::Event> TimedEventQueue::removeEventFromQueue_l(
+ event_id id) {
+ for (List<QueueItem>::iterator it = mQueue.begin();
+ it != mQueue.end(); ++it) {
+ if ((*it).event->eventID() == id) {
+ sp<Event> event = (*it).event;
+ event->setEventID(0);
+
+ mQueue.erase(it);
+
+ return event;
+ }
+ }
+
+ ALOGW("Event %d was not found in the queue, already cancelled?", id);
+
+ return NULL;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
new file mode 100644
index 0000000..c563ce6
--- /dev/null
+++ b/media/libstagefright/Utils.cpp
@@ -0,0 +1,57 @@
+/*
+ * 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 <arpa/inet.h>
+
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+uint16_t U16_AT(const uint8_t *ptr) {
+ return ptr[0] << 8 | ptr[1];
+}
+
+uint32_t U32_AT(const uint8_t *ptr) {
+ return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
+}
+
+uint64_t U64_AT(const uint8_t *ptr) {
+ return ((uint64_t)U32_AT(ptr)) << 32 | U32_AT(ptr + 4);
+}
+
+uint16_t U16LE_AT(const uint8_t *ptr) {
+ return ptr[0] | (ptr[1] << 8);
+}
+
+uint32_t U32LE_AT(const uint8_t *ptr) {
+ return ptr[3] << 24 | ptr[2] << 16 | ptr[1] << 8 | ptr[0];
+}
+
+uint64_t U64LE_AT(const uint8_t *ptr) {
+ return ((uint64_t)U32LE_AT(ptr + 4)) << 32 | U32LE_AT(ptr);
+}
+
+// XXX warning: these won't work on big-endian host.
+uint64_t ntoh64(uint64_t x) {
+ return ((uint64_t)ntohl(x & 0xffffffff) << 32) | ntohl(x >> 32);
+}
+
+uint64_t hton64(uint64_t x) {
+ return ((uint64_t)htonl(x & 0xffffffff) << 32) | htonl(x >> 32);
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/VBRISeeker.cpp b/media/libstagefright/VBRISeeker.cpp
new file mode 100644
index 0000000..bcba874
--- /dev/null
+++ b/media/libstagefright/VBRISeeker.cpp
@@ -0,0 +1,165 @@
+/*
+ * 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 "VBRISeeker"
+#include <utils/Log.h>
+
+#include "include/VBRISeeker.h"
+
+#include "include/avc_utils.h"
+#include "include/MP3Extractor.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+static uint32_t U24_AT(const uint8_t *ptr) {
+ return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
+}
+
+// static
+sp<VBRISeeker> VBRISeeker::CreateFromSource(
+ const sp<DataSource> &source, off64_t post_id3_pos) {
+ off64_t pos = post_id3_pos;
+
+ uint8_t header[4];
+ ssize_t n = source->readAt(pos, header, sizeof(header));
+ if (n < (ssize_t)sizeof(header)) {
+ return NULL;
+ }
+
+ uint32_t tmp = U32_AT(&header[0]);
+ size_t frameSize;
+ int sampleRate;
+ if (!GetMPEGAudioFrameSize(tmp, &frameSize, &sampleRate)) {
+ return NULL;
+ }
+
+ // VBRI header follows 32 bytes after the header _ends_.
+ pos += sizeof(header) + 32;
+
+ uint8_t vbriHeader[26];
+ n = source->readAt(pos, vbriHeader, sizeof(vbriHeader));
+ if (n < (ssize_t)sizeof(vbriHeader)) {
+ return NULL;
+ }
+
+ if (memcmp(vbriHeader, "VBRI", 4)) {
+ return NULL;
+ }
+
+ size_t numFrames = U32_AT(&vbriHeader[14]);
+
+ int64_t durationUs =
+ numFrames * 1000000ll * (sampleRate >= 32000 ? 1152 : 576) / sampleRate;
+
+ ALOGV("duration = %.2f secs", durationUs / 1E6);
+
+ size_t numEntries = U16_AT(&vbriHeader[18]);
+ size_t entrySize = U16_AT(&vbriHeader[22]);
+ size_t scale = U16_AT(&vbriHeader[20]);
+
+ ALOGV("%d entries, scale=%d, size_per_entry=%d",
+ numEntries,
+ scale,
+ entrySize);
+
+ size_t totalEntrySize = numEntries * entrySize;
+ uint8_t *buffer = new uint8_t[totalEntrySize];
+
+ n = source->readAt(pos + sizeof(vbriHeader), buffer, totalEntrySize);
+ if (n < (ssize_t)totalEntrySize) {
+ delete[] buffer;
+ buffer = NULL;
+
+ return NULL;
+ }
+
+ sp<VBRISeeker> seeker = new VBRISeeker;
+ seeker->mBasePos = post_id3_pos + frameSize;
+ seeker->mDurationUs = durationUs;
+
+ off64_t offset = post_id3_pos;
+ for (size_t i = 0; i < numEntries; ++i) {
+ uint32_t numBytes;
+ switch (entrySize) {
+ case 1: numBytes = buffer[i]; break;
+ case 2: numBytes = U16_AT(buffer + 2 * i); break;
+ case 3: numBytes = U24_AT(buffer + 3 * i); break;
+ default:
+ {
+ CHECK_EQ(entrySize, 4u);
+ numBytes = U32_AT(buffer + 4 * i); break;
+ }
+ }
+
+ numBytes *= scale;
+
+ seeker->mSegments.push(numBytes);
+
+ ALOGV("entry #%d: %d offset 0x%08lx", i, numBytes, offset);
+ offset += numBytes;
+ }
+
+ delete[] buffer;
+ buffer = NULL;
+
+ ALOGI("Found VBRI header.");
+
+ return seeker;
+}
+
+VBRISeeker::VBRISeeker()
+ : mDurationUs(-1) {
+}
+
+bool VBRISeeker::getDuration(int64_t *durationUs) {
+ if (mDurationUs < 0) {
+ return false;
+ }
+
+ *durationUs = mDurationUs;
+
+ return true;
+}
+
+bool VBRISeeker::getOffsetForTime(int64_t *timeUs, off64_t *pos) {
+ if (mDurationUs < 0) {
+ return false;
+ }
+
+ int64_t segmentDurationUs = mDurationUs / mSegments.size();
+
+ int64_t nowUs = 0;
+ *pos = mBasePos;
+ size_t segmentIndex = 0;
+ while (segmentIndex < mSegments.size() && nowUs < *timeUs) {
+ nowUs += segmentDurationUs;
+ *pos += mSegments.itemAt(segmentIndex++);
+ }
+
+ ALOGV("getOffsetForTime %lld us => 0x%08lx", *timeUs, *pos);
+
+ *timeUs = nowUs;
+
+ return true;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/VideoSourceDownSampler.cpp b/media/libstagefright/VideoSourceDownSampler.cpp
new file mode 100644
index 0000000..90a42c9
--- /dev/null
+++ b/media/libstagefright/VideoSourceDownSampler.cpp
@@ -0,0 +1,142 @@
+/*
+ * 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 "VideoSourceDownSampler"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/VideoSourceDownSampler.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/YUVImage.h>
+#include <media/stagefright/YUVCanvas.h>
+#include "OMX_Video.h"
+
+namespace android {
+
+VideoSourceDownSampler::VideoSourceDownSampler(const sp<MediaSource> &videoSource,
+ int32_t width, int32_t height) {
+ ALOGV("Construct VideoSourceDownSampler");
+ CHECK(width > 0);
+ CHECK(height > 0);
+
+ mRealVideoSource = videoSource;
+ mWidth = width;
+ mHeight = height;
+
+ mMeta = new MetaData(*(mRealVideoSource->getFormat()));
+ CHECK(mMeta->findInt32(kKeyWidth, &mRealSourceWidth));
+ CHECK(mMeta->findInt32(kKeyHeight, &mRealSourceHeight));
+
+ if ((mWidth != mRealSourceWidth) || (mHeight != mRealSourceHeight)) {
+ // Change meta data for width and height.
+ CHECK(mWidth <= mRealSourceWidth);
+ CHECK(mHeight <= mRealSourceHeight);
+
+ mNeedDownSampling = true;
+ computeDownSamplingParameters();
+ mMeta->setInt32(kKeyWidth, mWidth);
+ mMeta->setInt32(kKeyHeight, mHeight);
+ } else {
+ mNeedDownSampling = false;
+ }
+}
+
+VideoSourceDownSampler::~VideoSourceDownSampler() {
+}
+
+void VideoSourceDownSampler::computeDownSamplingParameters() {
+ mDownSampleSkipX = mRealSourceWidth / mWidth;
+ mDownSampleSkipY = mRealSourceHeight / mHeight;
+
+ mDownSampleOffsetX = mRealSourceWidth - mDownSampleSkipX * mWidth;
+ mDownSampleOffsetY = mRealSourceHeight - mDownSampleSkipY * mHeight;
+}
+
+void VideoSourceDownSampler::downSampleYUVImage(
+ const MediaBuffer &sourceBuffer, MediaBuffer **buffer) const {
+ // find the YUV format
+ int32_t srcFormat;
+ CHECK(mMeta->findInt32(kKeyColorFormat, &srcFormat));
+ YUVImage::YUVFormat yuvFormat;
+ if (srcFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
+ yuvFormat = YUVImage::YUV420SemiPlanar;
+ } else if (srcFormat == OMX_COLOR_FormatYUV420Planar) {
+ yuvFormat = YUVImage::YUV420Planar;
+ }
+
+ // allocate mediaBuffer for down sampled image and setup a canvas.
+ *buffer = new MediaBuffer(YUVImage::bufferSize(yuvFormat, mWidth, mHeight));
+ YUVImage yuvDownSampledImage(yuvFormat,
+ mWidth, mHeight,
+ (uint8_t *)(*buffer)->data());
+ YUVCanvas yuvCanvasDownSample(yuvDownSampledImage);
+
+ YUVImage yuvImageSource(yuvFormat,
+ mRealSourceWidth, mRealSourceHeight,
+ (uint8_t *)sourceBuffer.data());
+ yuvCanvasDownSample.downsample(mDownSampleOffsetX, mDownSampleOffsetY,
+ mDownSampleSkipX, mDownSampleSkipY,
+ yuvImageSource);
+}
+
+status_t VideoSourceDownSampler::start(MetaData *params) {
+ ALOGV("start");
+ return mRealVideoSource->start();
+}
+
+status_t VideoSourceDownSampler::stop() {
+ ALOGV("stop");
+ return mRealVideoSource->stop();
+}
+
+sp<MetaData> VideoSourceDownSampler::getFormat() {
+ ALOGV("getFormat");
+ return mMeta;
+}
+
+status_t VideoSourceDownSampler::read(
+ MediaBuffer **buffer, const ReadOptions *options) {
+ ALOGV("read");
+ MediaBuffer *realBuffer;
+ status_t err = mRealVideoSource->read(&realBuffer, options);
+
+ if (mNeedDownSampling) {
+ downSampleYUVImage(*realBuffer, buffer);
+
+ int64_t frameTime;
+ realBuffer->meta_data()->findInt64(kKeyTime, &frameTime);
+ (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
+
+ // We just want this buffer to be deleted when the encoder releases it.
+ // So don't add a reference to it and set the observer to NULL.
+ (*buffer)->setObserver(NULL);
+
+ // The original buffer is no longer required. Release it.
+ realBuffer->release();
+ } else {
+ *buffer = realBuffer;
+ }
+
+ return err;
+}
+
+status_t VideoSourceDownSampler::pause() {
+ ALOGV("pause");
+ return mRealVideoSource->pause();
+}
+
+} // namespace android
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
new file mode 100644
index 0000000..c35a77a
--- /dev/null
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -0,0 +1,506 @@
+/*
+ * 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 "WAVExtractor"
+#include <utils/Log.h>
+
+#include "include/WAVExtractor.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBufferGroup.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 <cutils/bitops.h>
+
+#define CHANNEL_MASK_USE_CHANNEL_ORDER 0
+
+namespace android {
+
+enum {
+ WAVE_FORMAT_PCM = 0x0001,
+ WAVE_FORMAT_ALAW = 0x0006,
+ WAVE_FORMAT_MULAW = 0x0007,
+ WAVE_FORMAT_EXTENSIBLE = 0xFFFE
+};
+
+static const char* WAVEEXT_SUBFORMAT = "\x00\x00\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71";
+
+
+static uint32_t U32_LE_AT(const uint8_t *ptr) {
+ return ptr[3] << 24 | ptr[2] << 16 | ptr[1] << 8 | ptr[0];
+}
+
+static uint16_t U16_LE_AT(const uint8_t *ptr) {
+ return ptr[1] << 8 | ptr[0];
+}
+
+struct WAVSource : public MediaSource {
+ WAVSource(
+ const sp<DataSource> &dataSource,
+ const sp<MetaData> &meta,
+ uint16_t waveFormat,
+ int32_t bitsPerSample,
+ off64_t offset, size_t size);
+
+ 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);
+
+protected:
+ virtual ~WAVSource();
+
+private:
+ static const size_t kMaxFrameSize;
+
+ sp<DataSource> mDataSource;
+ sp<MetaData> mMeta;
+ uint16_t mWaveFormat;
+ int32_t mSampleRate;
+ int32_t mNumChannels;
+ int32_t mBitsPerSample;
+ off64_t mOffset;
+ size_t mSize;
+ bool mStarted;
+ MediaBufferGroup *mGroup;
+ off64_t mCurrentPos;
+
+ WAVSource(const WAVSource &);
+ WAVSource &operator=(const WAVSource &);
+};
+
+WAVExtractor::WAVExtractor(const sp<DataSource> &source)
+ : mDataSource(source),
+ mValidFormat(false),
+ mChannelMask(CHANNEL_MASK_USE_CHANNEL_ORDER) {
+ mInitCheck = init();
+}
+
+WAVExtractor::~WAVExtractor() {
+}
+
+sp<MetaData> WAVExtractor::getMetaData() {
+ sp<MetaData> meta = new MetaData;
+
+ if (mInitCheck != OK) {
+ return meta;
+ }
+
+ meta->setCString(kKeyMIMEType, "audio/x-wav");
+
+ return meta;
+}
+
+size_t WAVExtractor::countTracks() {
+ return mInitCheck == OK ? 1 : 0;
+}
+
+sp<MediaSource> WAVExtractor::getTrack(size_t index) {
+ if (mInitCheck != OK || index > 0) {
+ return NULL;
+ }
+
+ return new WAVSource(
+ mDataSource, mTrackMeta,
+ mWaveFormat, mBitsPerSample, mDataOffset, mDataSize);
+}
+
+sp<MetaData> WAVExtractor::getTrackMetaData(
+ size_t index, uint32_t flags) {
+ if (mInitCheck != OK || index > 0) {
+ return NULL;
+ }
+
+ return mTrackMeta;
+}
+
+status_t WAVExtractor::init() {
+ uint8_t header[12];
+ if (mDataSource->readAt(
+ 0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
+ return NO_INIT;
+ }
+
+ if (memcmp(header, "RIFF", 4) || memcmp(&header[8], "WAVE", 4)) {
+ return NO_INIT;
+ }
+
+ size_t totalSize = U32_LE_AT(&header[4]);
+
+ off64_t offset = 12;
+ size_t remainingSize = totalSize;
+ while (remainingSize >= 8) {
+ uint8_t chunkHeader[8];
+ if (mDataSource->readAt(offset, chunkHeader, 8) < 8) {
+ return NO_INIT;
+ }
+
+ remainingSize -= 8;
+ offset += 8;
+
+ uint32_t chunkSize = U32_LE_AT(&chunkHeader[4]);
+
+ if (chunkSize > remainingSize) {
+ return NO_INIT;
+ }
+
+ if (!memcmp(chunkHeader, "fmt ", 4)) {
+ if (chunkSize < 16) {
+ return NO_INIT;
+ }
+
+ uint8_t formatSpec[40];
+ if (mDataSource->readAt(offset, formatSpec, 2) < 2) {
+ return NO_INIT;
+ }
+
+ mWaveFormat = U16_LE_AT(formatSpec);
+ if (mWaveFormat != WAVE_FORMAT_PCM
+ && mWaveFormat != WAVE_FORMAT_ALAW
+ && mWaveFormat != WAVE_FORMAT_MULAW
+ && mWaveFormat != WAVE_FORMAT_EXTENSIBLE) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ uint8_t fmtSize = 16;
+ if (mWaveFormat == WAVE_FORMAT_EXTENSIBLE) {
+ fmtSize = 40;
+ }
+ if (mDataSource->readAt(offset, formatSpec, fmtSize) < fmtSize) {
+ return NO_INIT;
+ }
+
+ mNumChannels = U16_LE_AT(&formatSpec[2]);
+ if (mWaveFormat != WAVE_FORMAT_EXTENSIBLE) {
+ if (mNumChannels != 1 && mNumChannels != 2) {
+ ALOGW("More than 2 channels (%d) in non-WAVE_EXT, unknown channel mask",
+ mNumChannels);
+ }
+ } else {
+ if (mNumChannels < 1 && mNumChannels > 8) {
+ return ERROR_UNSUPPORTED;
+ }
+ }
+
+ mSampleRate = U32_LE_AT(&formatSpec[4]);
+
+ if (mSampleRate == 0) {
+ return ERROR_MALFORMED;
+ }
+
+ mBitsPerSample = U16_LE_AT(&formatSpec[14]);
+
+ if (mWaveFormat == WAVE_FORMAT_PCM
+ || mWaveFormat == WAVE_FORMAT_EXTENSIBLE) {
+ if (mBitsPerSample != 8 && mBitsPerSample != 16
+ && mBitsPerSample != 24) {
+ return ERROR_UNSUPPORTED;
+ }
+ } else {
+ CHECK(mWaveFormat == WAVE_FORMAT_MULAW
+ || mWaveFormat == WAVE_FORMAT_ALAW);
+ if (mBitsPerSample != 8) {
+ return ERROR_UNSUPPORTED;
+ }
+ }
+
+ if (mWaveFormat == WAVE_FORMAT_EXTENSIBLE) {
+ uint16_t validBitsPerSample = U16_LE_AT(&formatSpec[18]);
+ if (validBitsPerSample != mBitsPerSample) {
+ ALOGE("validBits(%d) != bitsPerSample(%d) are not supported",
+ validBitsPerSample, mBitsPerSample);
+ return ERROR_UNSUPPORTED;
+ }
+
+ mChannelMask = U32_LE_AT(&formatSpec[20]);
+ ALOGV("numChannels=%d channelMask=0x%x", mNumChannels, mChannelMask);
+ if ((mChannelMask >> 18) != 0) {
+ ALOGE("invalid channel mask 0x%x", mChannelMask);
+ return ERROR_MALFORMED;
+ }
+
+ if ((mChannelMask != CHANNEL_MASK_USE_CHANNEL_ORDER)
+ && (popcount(mChannelMask) != mNumChannels)) {
+ ALOGE("invalid number of channels (%d) in channel mask (0x%x)",
+ popcount(mChannelMask), mChannelMask);
+ return ERROR_MALFORMED;
+ }
+
+ // In a WAVE_EXT header, the first two bytes of the GUID stored at byte 24 contain
+ // the sample format, using the same definitions as a regular WAV header
+ mWaveFormat = U16_LE_AT(&formatSpec[24]);
+ if (mWaveFormat != WAVE_FORMAT_PCM
+ && mWaveFormat != WAVE_FORMAT_ALAW
+ && mWaveFormat != WAVE_FORMAT_MULAW) {
+ return ERROR_UNSUPPORTED;
+ }
+ if (memcmp(&formatSpec[26], WAVEEXT_SUBFORMAT, 14)) {
+ ALOGE("unsupported GUID");
+ return ERROR_UNSUPPORTED;
+ }
+ }
+
+ mValidFormat = true;
+ } else if (!memcmp(chunkHeader, "data", 4)) {
+ if (mValidFormat) {
+ mDataOffset = offset;
+ mDataSize = chunkSize;
+
+ mTrackMeta = new MetaData;
+
+ switch (mWaveFormat) {
+ case WAVE_FORMAT_PCM:
+ mTrackMeta->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+ break;
+ case WAVE_FORMAT_ALAW:
+ mTrackMeta->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_ALAW);
+ break;
+ default:
+ CHECK_EQ(mWaveFormat, (uint16_t)WAVE_FORMAT_MULAW);
+ mTrackMeta->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_MLAW);
+ break;
+ }
+
+ mTrackMeta->setInt32(kKeyChannelCount, mNumChannels);
+ mTrackMeta->setInt32(kKeyChannelMask, mChannelMask);
+ mTrackMeta->setInt32(kKeySampleRate, mSampleRate);
+
+ size_t bytesPerSample = mBitsPerSample >> 3;
+
+ int64_t durationUs =
+ 1000000LL * (mDataSize / (mNumChannels * bytesPerSample))
+ / mSampleRate;
+
+ mTrackMeta->setInt64(kKeyDuration, durationUs);
+
+ return OK;
+ }
+ }
+
+ offset += chunkSize;
+ }
+
+ return NO_INIT;
+}
+
+const size_t WAVSource::kMaxFrameSize = 32768;
+
+WAVSource::WAVSource(
+ const sp<DataSource> &dataSource,
+ const sp<MetaData> &meta,
+ uint16_t waveFormat,
+ int32_t bitsPerSample,
+ off64_t offset, size_t size)
+ : mDataSource(dataSource),
+ mMeta(meta),
+ mWaveFormat(waveFormat),
+ mSampleRate(0),
+ mNumChannels(0),
+ mBitsPerSample(bitsPerSample),
+ mOffset(offset),
+ mSize(size),
+ mStarted(false),
+ mGroup(NULL) {
+ CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate));
+ CHECK(mMeta->findInt32(kKeyChannelCount, &mNumChannels));
+
+ mMeta->setInt32(kKeyMaxInputSize, kMaxFrameSize);
+}
+
+WAVSource::~WAVSource() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t WAVSource::start(MetaData *params) {
+ ALOGV("WAVSource::start");
+
+ CHECK(!mStarted);
+
+ mGroup = new MediaBufferGroup;
+ mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
+
+ if (mBitsPerSample == 8) {
+ // As a temporary buffer for 8->16 bit conversion.
+ mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
+ }
+
+ mCurrentPos = mOffset;
+
+ mStarted = true;
+
+ return OK;
+}
+
+status_t WAVSource::stop() {
+ ALOGV("WAVSource::stop");
+
+ CHECK(mStarted);
+
+ delete mGroup;
+ mGroup = NULL;
+
+ mStarted = false;
+
+ return OK;
+}
+
+sp<MetaData> WAVSource::getFormat() {
+ ALOGV("WAVSource::getFormat");
+
+ return mMeta;
+}
+
+status_t WAVSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode mode;
+ if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
+ int64_t pos = (seekTimeUs * mSampleRate) / 1000000 * mNumChannels * (mBitsPerSample >> 3);
+ if (pos > mSize) {
+ pos = mSize;
+ }
+ mCurrentPos = pos + mOffset;
+ }
+
+ MediaBuffer *buffer;
+ status_t err = mGroup->acquire_buffer(&buffer);
+ if (err != OK) {
+ return err;
+ }
+
+ size_t maxBytesToRead =
+ mBitsPerSample == 8 ? kMaxFrameSize / 2 : kMaxFrameSize;
+
+ size_t maxBytesAvailable =
+ (mCurrentPos - mOffset >= (off64_t)mSize)
+ ? 0 : mSize - (mCurrentPos - mOffset);
+
+ if (maxBytesToRead > maxBytesAvailable) {
+ maxBytesToRead = maxBytesAvailable;
+ }
+
+ ssize_t n = mDataSource->readAt(
+ mCurrentPos, buffer->data(),
+ maxBytesToRead);
+
+ if (n <= 0) {
+ buffer->release();
+ buffer = NULL;
+
+ return ERROR_END_OF_STREAM;
+ }
+
+ buffer->set_range(0, n);
+
+ if (mWaveFormat == WAVE_FORMAT_PCM) {
+ if (mBitsPerSample == 8) {
+ // Convert 8-bit unsigned samples to 16-bit signed.
+
+ MediaBuffer *tmp;
+ CHECK_EQ(mGroup->acquire_buffer(&tmp), (status_t)OK);
+
+ // The new buffer holds the sample number of samples, but each
+ // one is 2 bytes wide.
+ tmp->set_range(0, 2 * n);
+
+ int16_t *dst = (int16_t *)tmp->data();
+ const uint8_t *src = (const uint8_t *)buffer->data();
+ ssize_t numBytes = n;
+
+ while (numBytes-- > 0) {
+ *dst++ = ((int16_t)(*src) - 128) * 256;
+ ++src;
+ }
+
+ buffer->release();
+ buffer = tmp;
+ } else if (mBitsPerSample == 24) {
+ // Convert 24-bit signed samples to 16-bit signed.
+
+ const uint8_t *src =
+ (const uint8_t *)buffer->data() + buffer->range_offset();
+ int16_t *dst = (int16_t *)src;
+
+ size_t numSamples = buffer->range_length() / 3;
+ for (size_t i = 0; i < numSamples; ++i) {
+ int32_t x = (int32_t)(src[0] | src[1] << 8 | src[2] << 16);
+ x = (x << 8) >> 8; // sign extension
+
+ x = x >> 8;
+ *dst++ = (int16_t)x;
+ src += 3;
+ }
+
+ buffer->set_range(buffer->range_offset(), 2 * numSamples);
+ }
+ }
+
+ size_t bytesPerSample = mBitsPerSample >> 3;
+
+ buffer->meta_data()->setInt64(
+ kKeyTime,
+ 1000000LL * (mCurrentPos - mOffset)
+ / (mNumChannels * bytesPerSample) / mSampleRate);
+
+ buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ mCurrentPos += n;
+
+ *out = buffer;
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool SniffWAV(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
+ char header[12];
+ if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
+ return false;
+ }
+
+ if (memcmp(header, "RIFF", 4) || memcmp(&header[8], "WAVE", 4)) {
+ return false;
+ }
+
+ sp<MediaExtractor> extractor = new WAVExtractor(source);
+ if (extractor->countTracks() == 0) {
+ return false;
+ }
+
+ *mimeType = MEDIA_MIMETYPE_CONTAINER_WAV;
+ *confidence = 0.3f;
+
+ return true;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp
new file mode 100644
index 0000000..dac8106
--- /dev/null
+++ b/media/libstagefright/WVMExtractor.cpp
@@ -0,0 +1,161 @@
+/*
+ * 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 "WVMExtractor"
+#include <utils/Log.h>
+
+#include "include/WVMExtractor.h"
+
+#include <arpa/inet.h>
+#include <utils/String8.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/Utils.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <dlfcn.h>
+
+#include <utils/Errors.h>
+
+/* The extractor lifetime is short - just long enough to get
+ * the media sources constructed - so the shared lib needs to remain open
+ * beyond the lifetime of the extractor. So keep the handle as a global
+ * rather than a member of the extractor
+ */
+void *gVendorLibHandle = NULL;
+
+namespace android {
+
+static Mutex gWVMutex;
+
+WVMExtractor::WVMExtractor(const sp<DataSource> &source)
+ : mDataSource(source)
+{
+ Mutex::Autolock autoLock(gWVMutex);
+
+ if (!getVendorLibHandle()) {
+ return;
+ }
+
+ typedef WVMLoadableExtractor *(*GetInstanceFunc)(sp<DataSource>);
+ GetInstanceFunc getInstanceFunc =
+ (GetInstanceFunc) dlsym(gVendorLibHandle,
+ "_ZN7android11GetInstanceENS_2spINS_10DataSourceEEE");
+
+ if (getInstanceFunc) {
+ CHECK(source->DrmInitialization(MEDIA_MIMETYPE_CONTAINER_WVM) != NULL);
+ mImpl = (*getInstanceFunc)(source);
+ CHECK(mImpl != NULL);
+ setDrmFlag(true);
+ } else {
+ ALOGE("Failed to locate GetInstance in libwvm.so");
+ }
+}
+
+bool WVMExtractor::getVendorLibHandle()
+{
+ if (gVendorLibHandle == NULL) {
+ gVendorLibHandle = dlopen("libwvm.so", RTLD_NOW);
+ }
+
+ if (gVendorLibHandle == NULL) {
+ ALOGE("Failed to open libwvm.so");
+ }
+
+ return gVendorLibHandle != NULL;
+}
+
+WVMExtractor::~WVMExtractor() {
+}
+
+size_t WVMExtractor::countTracks() {
+ return (mImpl != NULL) ? mImpl->countTracks() : 0;
+}
+
+sp<MediaSource> WVMExtractor::getTrack(size_t index) {
+ if (mImpl == NULL) {
+ return NULL;
+ }
+ return mImpl->getTrack(index);
+}
+
+sp<MetaData> WVMExtractor::getTrackMetaData(size_t index, uint32_t flags) {
+ if (mImpl == NULL) {
+ return NULL;
+ }
+ return mImpl->getTrackMetaData(index, flags);
+}
+
+sp<MetaData> WVMExtractor::getMetaData() {
+ if (mImpl == NULL) {
+ return NULL;
+ }
+ return mImpl->getMetaData();
+}
+
+int64_t WVMExtractor::getCachedDurationUs(status_t *finalStatus) {
+ if (mImpl == NULL) {
+ return 0;
+ }
+
+ return mImpl->getCachedDurationUs(finalStatus);
+}
+
+void WVMExtractor::setAdaptiveStreamingMode(bool adaptive) {
+ if (mImpl != NULL) {
+ mImpl->setAdaptiveStreamingMode(adaptive);
+ }
+}
+
+void WVMExtractor::setUID(uid_t uid) {
+ if (mImpl != NULL) {
+ mImpl->setUID(uid);
+ }
+}
+
+bool SniffWVM(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
+
+ Mutex::Autolock autoLock(gWVMutex);
+
+ if (!WVMExtractor::getVendorLibHandle()) {
+ return false;
+ }
+
+ typedef WVMLoadableExtractor *(*SnifferFunc)(const sp<DataSource>&);
+ SnifferFunc snifferFunc =
+ (SnifferFunc) dlsym(gVendorLibHandle,
+ "_ZN7android15IsWidevineMediaERKNS_2spINS_10DataSourceEEE");
+
+ if (snifferFunc) {
+ if ((*snifferFunc)(source)) {
+ *mimeType = MEDIA_MIMETYPE_CONTAINER_WVM;
+ *confidence = 10.0f;
+ return true;
+ }
+ } else {
+ ALOGE("IsWidevineMedia not found in libwvm.so");
+ }
+
+ return false;
+}
+
+} //namespace android
+
diff --git a/media/libstagefright/XINGSeeker.cpp b/media/libstagefright/XINGSeeker.cpp
new file mode 100644
index 0000000..9c91134
--- /dev/null
+++ b/media/libstagefright/XINGSeeker.cpp
@@ -0,0 +1,196 @@
+/*
+ * 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 "XINGSEEKER"
+#include <utils/Log.h>
+
+#include "include/XINGSeeker.h"
+#include "include/avc_utils.h"
+
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+XINGSeeker::XINGSeeker()
+ : mDurationUs(-1),
+ mSizeBytes(0),
+ mEncoderDelay(0),
+ mEncoderPadding(0) {
+}
+
+bool XINGSeeker::getDuration(int64_t *durationUs) {
+ if (mDurationUs < 0) {
+ return false;
+ }
+
+ *durationUs = mDurationUs;
+
+ return true;
+}
+
+bool XINGSeeker::getOffsetForTime(int64_t *timeUs, off64_t *pos) {
+ if (mSizeBytes == 0 || !mTOCValid || mDurationUs < 0) {
+ return false;
+ }
+
+ float percent = (float)(*timeUs) * 100 / mDurationUs;
+ float fx;
+ if( percent <= 0.0f ) {
+ fx = 0.0f;
+ } else if( percent >= 100.0f ) {
+ fx = 256.0f;
+ } else {
+ int a = (int)percent;
+ float fa, fb;
+ if ( a == 0 ) {
+ fa = 0.0f;
+ } else {
+ fa = (float)mTOC[a-1];
+ }
+ if ( a < 99 ) {
+ fb = (float)mTOC[a];
+ } else {
+ fb = 256.0f;
+ }
+ fx = fa + (fb-fa)*(percent-a);
+ }
+
+ *pos = (int)((1.0f/256.0f)*fx*mSizeBytes) + mFirstFramePos;
+
+ return true;
+}
+
+// static
+sp<XINGSeeker> XINGSeeker::CreateFromSource(
+ const sp<DataSource> &source, off64_t first_frame_pos) {
+ sp<XINGSeeker> seeker = new XINGSeeker;
+
+ seeker->mFirstFramePos = first_frame_pos;
+
+ seeker->mSizeBytes = 0;
+ seeker->mTOCValid = false;
+ seeker->mDurationUs = 0;
+
+ uint8_t buffer[4];
+ int offset = first_frame_pos;
+ if (source->readAt(offset, &buffer, 4) < 4) { // get header
+ return NULL;
+ }
+ offset += 4;
+
+ int header = U32_AT(buffer);;
+ size_t xingframesize = 0;
+ int sampling_rate = 0;
+ int num_channels;
+ int samples_per_frame = 0;
+ if (!GetMPEGAudioFrameSize(header, &xingframesize, &sampling_rate, &num_channels,
+ NULL, &samples_per_frame)) {
+ return NULL;
+ }
+ seeker->mFirstFramePos += xingframesize;
+
+ uint8_t version = (buffer[1] >> 3) & 3;
+
+ // determine offset of XING header
+ if(version & 1) { // mpeg1
+ if (num_channels != 1) offset += 32;
+ else offset += 17;
+ } else { // mpeg 2 or 2.5
+ if (num_channels != 1) offset += 17;
+ else offset += 9;
+ }
+
+ int xingbase = offset;
+
+ if (source->readAt(offset, &buffer, 4) < 4) { // XING header ID
+ return NULL;
+ }
+ offset += 4;
+ // Check XING ID
+ if ((buffer[0] != 'X') || (buffer[1] != 'i')
+ || (buffer[2] != 'n') || (buffer[3] != 'g')) {
+ if ((buffer[0] != 'I') || (buffer[1] != 'n')
+ || (buffer[2] != 'f') || (buffer[3] != 'o')) {
+ return NULL;
+ }
+ }
+
+ if (source->readAt(offset, &buffer, 4) < 4) { // flags
+ return NULL;
+ }
+ offset += 4;
+ uint32_t flags = U32_AT(buffer);
+
+ if (flags & 0x0001) { // Frames field is present
+ if (source->readAt(offset, buffer, 4) < 4) {
+ return NULL;
+ }
+ int32_t frames = U32_AT(buffer);
+ seeker->mDurationUs = (int64_t)frames * samples_per_frame * 1000000LL / sampling_rate;
+ offset += 4;
+ }
+ if (flags & 0x0002) { // Bytes field is present
+ if (source->readAt(offset, buffer, 4) < 4) {
+ return NULL;
+ }
+ seeker->mSizeBytes = U32_AT(buffer);
+ offset += 4;
+ }
+ if (flags & 0x0004) { // TOC field is present
+ if (source->readAt(offset + 1, seeker->mTOC, 99) < 99) {
+ return NULL;
+ }
+ seeker->mTOCValid = true;
+ offset += 100;
+ }
+
+#if 0
+ if (flags & 0x0008) { // Quality indicator field is present
+ if (source->readAt(offset, buffer, 4) < 4) {
+ return NULL;
+ }
+ // do something with the quality indicator
+ offset += 4;
+ }
+
+ if (source->readAt(xingbase + 0xaf - 0x24, &buffer, 1) < 1) { // encoding flags
+ return false;
+ }
+
+ ALOGV("nogap preceding: %s, nogap continued in next: %s",
+ (buffer[0] & 0x80) ? "true" : "false",
+ (buffer[0] & 0x40) ? "true" : "false");
+#endif
+
+ if (source->readAt(xingbase + 0xb1 - 0x24, &buffer, 3) == 3) {
+ seeker->mEncoderDelay = (buffer[0] << 4) + (buffer[1] >> 4);
+ seeker->mEncoderPadding = ((buffer[1] & 0xf) << 8) + buffer[2];
+ }
+
+ return seeker;
+}
+
+int32_t XINGSeeker::getEncoderDelay() {
+ return mEncoderDelay;
+}
+
+int32_t XINGSeeker::getEncoderPadding() {
+ return mEncoderPadding;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
new file mode 100644
index 0000000..65c1848
--- /dev/null
+++ b/media/libstagefright/avc_utils.cpp
@@ -0,0 +1,633 @@
+/*
+ * 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 "avc_utils"
+#include <utils/Log.h>
+
+#include "include/avc_utils.h"
+
+#include <media/stagefright/foundation/ABitReader.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+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.
+void FindAVCDimensions(
+ 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
+
+ unsigned chroma_format_idc = 1; // 4:2:0 chroma format
+
+ if (profile_idc == 100 || profile_idc == 110
+ || profile_idc == 122 || profile_idc == 244
+ || profile_idc == 44 || profile_idc == 83 || profile_idc == 86) {
+ chroma_format_idc = parseUE(&br);
+ if (chroma_format_idc == 3) {
+ br.skipBits(1); // residual_colour_transform_flag
+ }
+ parseUE(&br); // bit_depth_luma_minus8
+ parseUE(&br); // bit_depth_chroma_minus8
+ br.skipBits(1); // qpprime_y_zero_transform_bypass_flag
+ CHECK_EQ(br.getBits(1), 0u); // seq_scaling_matrix_present_flag
+ }
+
+ 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) {
+ // offset_for_non_ref_pic, offset_for_top_to_bottom_field and
+ // offset_for_ref_frame are technically se(v), but since we are
+ // just skipping over them the midpoint does not matter.
+
+ 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);
+
+ if (!frame_mbs_only_flag) {
+ br.getBits(1); // mb_adaptive_frame_field_flag
+ }
+
+ br.getBits(1); // direct_8x8_inference_flag
+
+ if (br.getBits(1)) { // frame_cropping_flag
+ unsigned frame_crop_left_offset = parseUE(&br);
+ unsigned frame_crop_right_offset = parseUE(&br);
+ unsigned frame_crop_top_offset = parseUE(&br);
+ unsigned frame_crop_bottom_offset = parseUE(&br);
+
+ unsigned cropUnitX, cropUnitY;
+ if (chroma_format_idc == 0 /* monochrome */) {
+ cropUnitX = 1;
+ cropUnitY = 2 - frame_mbs_only_flag;
+ } else {
+ unsigned subWidthC = (chroma_format_idc == 3) ? 1 : 2;
+ unsigned subHeightC = (chroma_format_idc == 1) ? 2 : 1;
+
+ cropUnitX = subWidthC;
+ cropUnitY = subHeightC * (2 - frame_mbs_only_flag);
+ }
+
+ ALOGV("frame_crop = (%u, %u, %u, %u), cropUnitX = %u, cropUnitY = %u",
+ frame_crop_left_offset, frame_crop_right_offset,
+ frame_crop_top_offset, frame_crop_bottom_offset,
+ cropUnitX, cropUnitY);
+
+ *width -=
+ (frame_crop_left_offset + frame_crop_right_offset) * cropUnitX;
+ *height -=
+ (frame_crop_top_offset + frame_crop_bottom_offset) * cropUnitY;
+ }
+}
+
+status_t getNextNALUnit(
+ const uint8_t **_data, size_t *_size,
+ const uint8_t **nalStart, size_t *nalSize,
+ bool startCodeFollows) {
+ const uint8_t *data = *_data;
+ size_t size = *_size;
+
+ *nalStart = NULL;
+ *nalSize = 0;
+
+ if (size == 0) {
+ return -EAGAIN;
+ }
+
+ // Skip any number of leading 0x00.
+
+ size_t offset = 0;
+ while (offset < size && data[offset] == 0x00) {
+ ++offset;
+ }
+
+ if (offset == size) {
+ return -EAGAIN;
+ }
+
+ // A valid startcode consists of at least two 0x00 bytes followed by 0x01.
+
+ if (offset < 2 || data[offset] != 0x01) {
+ return ERROR_MALFORMED;
+ }
+
+ ++offset;
+
+ size_t startOffset = offset;
+
+ for (;;) {
+ while (offset < size && data[offset] != 0x01) {
+ ++offset;
+ }
+
+ if (offset == size) {
+ if (startCodeFollows) {
+ offset = size + 2;
+ break;
+ }
+
+ return -EAGAIN;
+ }
+
+ if (data[offset - 1] == 0x00 && data[offset - 2] == 0x00) {
+ break;
+ }
+
+ ++offset;
+ }
+
+ size_t endOffset = offset - 2;
+ while (endOffset > startOffset + 1 && data[endOffset - 1] == 0x00) {
+ --endOffset;
+ }
+
+ *nalStart = &data[startOffset];
+ *nalSize = endOffset - startOffset;
+
+ if (offset + 2 < size) {
+ *_data = &data[offset - 2];
+ *_size = size - offset + 2;
+ } else {
+ *_data = NULL;
+ *_size = 0;
+ }
+
+ return OK;
+}
+
+static sp<ABuffer> FindNAL(
+ const uint8_t *data, size_t size, unsigned nalType,
+ size_t *stopOffset) {
+ const uint8_t *nalStart;
+ size_t nalSize;
+ while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
+ if ((nalStart[0] & 0x1f) == nalType) {
+ sp<ABuffer> buffer = new ABuffer(nalSize);
+ memcpy(buffer->data(), nalStart, nalSize);
+ return buffer;
+ }
+ }
+
+ return NULL;
+}
+
+const char *AVCProfileToString(uint8_t profile) {
+ switch (profile) {
+ case kAVCProfileBaseline:
+ return "Baseline";
+ case kAVCProfileMain:
+ return "Main";
+ case kAVCProfileExtended:
+ return "Extended";
+ case kAVCProfileHigh:
+ return "High";
+ case kAVCProfileHigh10:
+ return "High 10";
+ case kAVCProfileHigh422:
+ return "High 422";
+ case kAVCProfileHigh444:
+ return "High 444";
+ case kAVCProfileCAVLC444Intra:
+ return "CAVLC 444 Intra";
+ default: return "Unknown";
+ }
+}
+
+sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) {
+ const uint8_t *data = accessUnit->data();
+ size_t size = accessUnit->size();
+
+ sp<ABuffer> seqParamSet = FindNAL(data, size, 7, NULL);
+ if (seqParamSet == NULL) {
+ return NULL;
+ }
+
+ int32_t width, height;
+ FindAVCDimensions(seqParamSet, &width, &height);
+
+ size_t stopOffset;
+ sp<ABuffer> picParamSet = FindNAL(data, size, 8, &stopOffset);
+ CHECK(picParamSet != NULL);
+
+ 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...
+
+ uint8_t profile = out[0];
+ uint8_t level = out[2];
+
+ 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());
+
+#if 0
+ ALOGI("AVC seq param set");
+ hexdump(seqParamSet->data(), seqParamSet->size());
+#endif
+
+ sp<MetaData> meta = new MetaData;
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+
+ meta->setData(kKeyAVCC, kTypeAVCC, csd->data(), csd->size());
+ meta->setInt32(kKeyWidth, width);
+ meta->setInt32(kKeyHeight, height);
+
+ ALOGI("found AVC codec config (%d x %d, %s-profile level %d.%d)",
+ width, height, AVCProfileToString(profile), level / 10, level % 10);
+
+ return meta;
+}
+
+bool IsIDR(const sp<ABuffer> &buffer) {
+ const uint8_t *data = buffer->data();
+ size_t size = buffer->size();
+
+ bool foundIDR = false;
+
+ const uint8_t *nalStart;
+ size_t nalSize;
+ while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
+ CHECK_GT(nalSize, 0u);
+
+ unsigned nalType = nalStart[0] & 0x1f;
+
+ if (nalType == 5) {
+ foundIDR = true;
+ break;
+ }
+ }
+
+ return foundIDR;
+}
+
+bool IsAVCReferenceFrame(const sp<ABuffer> &accessUnit) {
+ const uint8_t *data = accessUnit->data();
+ size_t size = accessUnit->size();
+
+ const uint8_t *nalStart;
+ size_t nalSize;
+ while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
+ CHECK_GT(nalSize, 0u);
+
+ unsigned nalType = nalStart[0] & 0x1f;
+
+ if (nalType == 5) {
+ return true;
+ } else if (nalType == 1) {
+ unsigned nal_ref_idc = (nalStart[0] >> 5) & 3;
+ return nal_ref_idc != 0;
+ }
+ }
+
+ return true;
+}
+
+sp<MetaData> MakeAACCodecSpecificData(
+ unsigned profile, unsigned sampling_freq_index,
+ unsigned channel_configuration) {
+ sp<MetaData> meta = new MetaData;
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+
+ CHECK_LE(sampling_freq_index, 11u);
+ static const int32_t kSamplingFreq[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
+ 16000, 12000, 11025, 8000
+ };
+ meta->setInt32(kKeySampleRate, kSamplingFreq[sampling_freq_index]);
+ meta->setInt32(kKeyChannelCount, 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);
+
+ meta->setData(kKeyESDS, 0, csd->data(), csd->size());
+
+ return meta;
+}
+
+bool ExtractDimensionsFromVOLHeader(
+ const uint8_t *data, size_t size, int32_t *width, int32_t *height) {
+ ABitReader br(&data[4], size - 4);
+ br.skipBits(1); // random_accessible_vol
+ unsigned video_object_type_indication = br.getBits(8);
+
+ CHECK_NE(video_object_type_indication,
+ 0x21u /* Fine Granularity Scalable */);
+
+ unsigned video_object_layer_verid;
+ unsigned video_object_layer_priority;
+ if (br.getBits(1)) {
+ video_object_layer_verid = br.getBits(4);
+ video_object_layer_priority = br.getBits(3);
+ }
+ unsigned aspect_ratio_info = br.getBits(4);
+ if (aspect_ratio_info == 0x0f /* extended PAR */) {
+ br.skipBits(8); // par_width
+ br.skipBits(8); // par_height
+ }
+ if (br.getBits(1)) { // vol_control_parameters
+ br.skipBits(2); // chroma_format
+ br.skipBits(1); // low_delay
+ if (br.getBits(1)) { // vbv_parameters
+ br.skipBits(15); // first_half_bit_rate
+ CHECK(br.getBits(1)); // marker_bit
+ br.skipBits(15); // latter_half_bit_rate
+ CHECK(br.getBits(1)); // marker_bit
+ br.skipBits(15); // first_half_vbv_buffer_size
+ CHECK(br.getBits(1)); // marker_bit
+ br.skipBits(3); // latter_half_vbv_buffer_size
+ br.skipBits(11); // first_half_vbv_occupancy
+ CHECK(br.getBits(1)); // marker_bit
+ br.skipBits(15); // latter_half_vbv_occupancy
+ CHECK(br.getBits(1)); // marker_bit
+ }
+ }
+ unsigned video_object_layer_shape = br.getBits(2);
+ CHECK_EQ(video_object_layer_shape, 0x00u /* rectangular */);
+
+ CHECK(br.getBits(1)); // marker_bit
+ unsigned vop_time_increment_resolution = br.getBits(16);
+ CHECK(br.getBits(1)); // marker_bit
+
+ if (br.getBits(1)) { // fixed_vop_rate
+ // range [0..vop_time_increment_resolution)
+
+ // vop_time_increment_resolution
+ // 2 => 0..1, 1 bit
+ // 3 => 0..2, 2 bits
+ // 4 => 0..3, 2 bits
+ // 5 => 0..4, 3 bits
+ // ...
+
+ CHECK_GT(vop_time_increment_resolution, 0u);
+ --vop_time_increment_resolution;
+
+ unsigned numBits = 0;
+ while (vop_time_increment_resolution > 0) {
+ ++numBits;
+ vop_time_increment_resolution >>= 1;
+ }
+
+ br.skipBits(numBits); // fixed_vop_time_increment
+ }
+
+ CHECK(br.getBits(1)); // marker_bit
+ unsigned video_object_layer_width = br.getBits(13);
+ CHECK(br.getBits(1)); // marker_bit
+ unsigned video_object_layer_height = br.getBits(13);
+ CHECK(br.getBits(1)); // marker_bit
+
+ unsigned interlaced = br.getBits(1);
+
+ *width = video_object_layer_width;
+ *height = video_object_layer_height;
+
+ return true;
+}
+
+bool GetMPEGAudioFrameSize(
+ uint32_t header, size_t *frame_size,
+ int *out_sampling_rate, int *out_channels,
+ int *out_bitrate, int *out_num_samples) {
+ *frame_size = 0;
+
+ if (out_sampling_rate) {
+ *out_sampling_rate = 0;
+ }
+
+ if (out_channels) {
+ *out_channels = 0;
+ }
+
+ if (out_bitrate) {
+ *out_bitrate = 0;
+ }
+
+ if (out_num_samples) {
+ *out_num_samples = 1152;
+ }
+
+ if ((header & 0xffe00000) != 0xffe00000) {
+ return false;
+ }
+
+ unsigned version = (header >> 19) & 3;
+
+ if (version == 0x01) {
+ return false;
+ }
+
+ unsigned layer = (header >> 17) & 3;
+
+ if (layer == 0x00) {
+ return false;
+ }
+
+ unsigned protection = (header >> 16) & 1;
+
+ unsigned bitrate_index = (header >> 12) & 0x0f;
+
+ if (bitrate_index == 0 || bitrate_index == 0x0f) {
+ // Disallow "free" bitrate.
+ return false;
+ }
+
+ unsigned sampling_rate_index = (header >> 10) & 3;
+
+ if (sampling_rate_index == 3) {
+ return false;
+ }
+
+ static const int kSamplingRateV1[] = { 44100, 48000, 32000 };
+ int sampling_rate = kSamplingRateV1[sampling_rate_index];
+ if (version == 2 /* V2 */) {
+ sampling_rate /= 2;
+ } else if (version == 0 /* V2.5 */) {
+ sampling_rate /= 4;
+ }
+
+ unsigned padding = (header >> 9) & 1;
+
+ if (layer == 3) {
+ // layer I
+
+ static const int kBitrateV1[] = {
+ 32, 64, 96, 128, 160, 192, 224, 256,
+ 288, 320, 352, 384, 416, 448
+ };
+
+ static const int kBitrateV2[] = {
+ 32, 48, 56, 64, 80, 96, 112, 128,
+ 144, 160, 176, 192, 224, 256
+ };
+
+ int bitrate =
+ (version == 3 /* V1 */)
+ ? kBitrateV1[bitrate_index - 1]
+ : kBitrateV2[bitrate_index - 1];
+
+ if (out_bitrate) {
+ *out_bitrate = bitrate;
+ }
+
+ *frame_size = (12000 * bitrate / sampling_rate + padding) * 4;
+
+ if (out_num_samples) {
+ *out_num_samples = 384;
+ }
+ } else {
+ // layer II or III
+
+ static const int kBitrateV1L2[] = {
+ 32, 48, 56, 64, 80, 96, 112, 128,
+ 160, 192, 224, 256, 320, 384
+ };
+
+ static const int kBitrateV1L3[] = {
+ 32, 40, 48, 56, 64, 80, 96, 112,
+ 128, 160, 192, 224, 256, 320
+ };
+
+ static const int kBitrateV2[] = {
+ 8, 16, 24, 32, 40, 48, 56, 64,
+ 80, 96, 112, 128, 144, 160
+ };
+
+ int bitrate;
+ if (version == 3 /* V1 */) {
+ bitrate = (layer == 2 /* L2 */)
+ ? kBitrateV1L2[bitrate_index - 1]
+ : kBitrateV1L3[bitrate_index - 1];
+
+ if (out_num_samples) {
+ *out_num_samples = 1152;
+ }
+ } else {
+ // V2 (or 2.5)
+
+ bitrate = kBitrateV2[bitrate_index - 1];
+ if (out_num_samples) {
+ *out_num_samples = 576;
+ }
+ }
+
+ if (out_bitrate) {
+ *out_bitrate = bitrate;
+ }
+
+ if (version == 3 /* V1 */) {
+ *frame_size = 144000 * bitrate / sampling_rate + padding;
+ } else {
+ // V2 or V2.5
+ *frame_size = 72000 * bitrate / sampling_rate + padding;
+ }
+ }
+
+ if (out_sampling_rate) {
+ *out_sampling_rate = sampling_rate;
+ }
+
+ if (out_channels) {
+ int channel_mode = (header >> 6) & 3;
+
+ *out_channels = (channel_mode == 3) ? 1 : 2;
+ }
+
+ return true;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/chromium_http/Android.mk b/media/libstagefright/chromium_http/Android.mk
new file mode 100644
index 0000000..d595686
--- /dev/null
+++ b/media/libstagefright/chromium_http/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+
+ifneq ($(TARGET_BUILD_PDK), true)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ DataUriSource.cpp \
+ ChromiumHTTPDataSource.cpp \
+ support.cpp
+
+LOCAL_C_INCLUDES:= \
+ frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax \
+ external/chromium \
+ external/chromium/android
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_SHARED_LIBRARIES += libstlport
+include external/stlport/libstlport.mk
+
+LOCAL_MODULE:= libstagefright_chromium_http
+
+include $(BUILD_STATIC_LIBRARY)
+endif
diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
new file mode 100644
index 0000000..76f7946
--- /dev/null
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ChromiumHTTPDataSource"
+#include <media/stagefright/foundation/ADebug.h>
+
+#include "include/ChromiumHTTPDataSource.h"
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MediaErrors.h>
+
+#include "support.h"
+
+#include <cutils/properties.h> // for property_get
+
+namespace android {
+
+ChromiumHTTPDataSource::ChromiumHTTPDataSource(uint32_t flags)
+ : mFlags(flags),
+ mState(DISCONNECTED),
+ mDelegate(new SfDelegate),
+ mCurrentOffset(0),
+ mIOResult(OK),
+ mContentSize(-1),
+ mDecryptHandle(NULL),
+ mDrmManagerClient(NULL) {
+ mDelegate->setOwner(this);
+}
+
+ChromiumHTTPDataSource::~ChromiumHTTPDataSource() {
+ disconnect();
+
+ delete mDelegate;
+ mDelegate = NULL;
+
+ clearDRMState_l();
+
+ if (mDrmManagerClient != NULL) {
+ delete mDrmManagerClient;
+ mDrmManagerClient = NULL;
+ }
+}
+
+status_t ChromiumHTTPDataSource::connect(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ Mutex::Autolock autoLock(mLock);
+
+ uid_t uid;
+ if (getUID(&uid)) {
+ mDelegate->setUID(uid);
+ }
+ LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG, "connect on behalf of uid %d", uid);
+
+ return connect_l(uri, headers, offset);
+}
+
+status_t ChromiumHTTPDataSource::connect_l(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ if (mState != DISCONNECTED) {
+ disconnect_l();
+ }
+
+ if (!(mFlags & kFlagIncognito)) {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "connect to %s @%lld", uri, offset);
+ } else {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG,
+ "connect to <URL suppressed> @%lld", offset);
+ }
+
+ mURI = uri;
+ mContentType = String8("application/octet-stream");
+
+ if (headers != NULL) {
+ mHeaders = *headers;
+ } else {
+ mHeaders.clear();
+ }
+
+ mState = CONNECTING;
+ mContentSize = -1;
+ mCurrentOffset = offset;
+
+ mDelegate->initiateConnection(mURI.c_str(), &mHeaders, offset);
+
+ while (mState == CONNECTING) {
+ mCondition.wait(mLock);
+ }
+
+ return mState == CONNECTED ? OK : mIOResult;
+}
+
+void ChromiumHTTPDataSource::onConnectionEstablished(
+ int64_t contentSize, const char *contentType) {
+ Mutex::Autolock autoLock(mLock);
+ mState = CONNECTED;
+ mContentSize = (contentSize < 0) ? -1 : contentSize + mCurrentOffset;
+ mContentType = String8(contentType);
+ mCondition.broadcast();
+}
+
+void ChromiumHTTPDataSource::onConnectionFailed(status_t err) {
+ Mutex::Autolock autoLock(mLock);
+ mState = DISCONNECTED;
+ mCondition.broadcast();
+
+ // mURI.clear();
+
+ mIOResult = err;
+}
+
+void ChromiumHTTPDataSource::disconnect() {
+ Mutex::Autolock autoLock(mLock);
+ disconnect_l();
+}
+
+void ChromiumHTTPDataSource::disconnect_l() {
+ if (mState == DISCONNECTED) {
+ return;
+ }
+
+ mState = DISCONNECTING;
+ mIOResult = -EINTR;
+
+ mDelegate->initiateDisconnect();
+
+ while (mState == DISCONNECTING) {
+ mCondition.wait(mLock);
+ }
+
+ CHECK_EQ((int)mState, (int)DISCONNECTED);
+}
+
+status_t ChromiumHTTPDataSource::initCheck() const {
+ Mutex::Autolock autoLock(mLock);
+
+ return mState == CONNECTED ? OK : NO_INIT;
+}
+
+ssize_t ChromiumHTTPDataSource::readAt(off64_t offset, void *data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mState != CONNECTED) {
+ return INVALID_OPERATION;
+ }
+
+#if 0
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.stagefright.disable-net", value, 0)
+ && (!strcasecmp(value, "true") || !strcmp(value, "1"))) {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Simulating that the network is down.");
+ disconnect_l();
+ return ERROR_IO;
+ }
+#endif
+
+ if (offset != mCurrentOffset) {
+ AString tmp = mURI;
+ KeyedVector<String8, String8> tmpHeaders = mHeaders;
+
+ disconnect_l();
+
+ status_t err = connect_l(tmp.c_str(), &tmpHeaders, offset);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ mState = READING;
+
+ int64_t startTimeUs = ALooper::GetNowUs();
+
+ mDelegate->initiateRead(data, size);
+
+ while (mState == READING) {
+ mCondition.wait(mLock);
+ }
+
+ if (mIOResult < OK) {
+ return mIOResult;
+ }
+
+ if (mState == CONNECTED) {
+ int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
+
+ // The read operation was successful, mIOResult contains
+ // the number of bytes read.
+ addBandwidthMeasurement(mIOResult, delayUs);
+
+ mCurrentOffset += mIOResult;
+ return mIOResult;
+ }
+
+ return ERROR_IO;
+}
+
+void ChromiumHTTPDataSource::onReadCompleted(ssize_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ mIOResult = size;
+
+ if (mState == READING) {
+ mState = CONNECTED;
+ mCondition.broadcast();
+ }
+}
+
+status_t ChromiumHTTPDataSource::getSize(off64_t *size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mContentSize < 0) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ *size = mContentSize;
+
+ return OK;
+}
+
+uint32_t ChromiumHTTPDataSource::flags() {
+ return kWantsPrefetching | kIsHTTPBasedSource;
+}
+
+// static
+void ChromiumHTTPDataSource::InitiateRead(
+ ChromiumHTTPDataSource *me, void *data, size_t size) {
+ me->initiateRead(data, size);
+}
+
+void ChromiumHTTPDataSource::initiateRead(void *data, size_t size) {
+ mDelegate->initiateRead(data, size);
+}
+
+void ChromiumHTTPDataSource::onDisconnectComplete() {
+ Mutex::Autolock autoLock(mLock);
+ CHECK_EQ((int)mState, (int)DISCONNECTING);
+
+ mState = DISCONNECTED;
+ // mURI.clear();
+
+ mCondition.broadcast();
+}
+
+sp<DecryptHandle> ChromiumHTTPDataSource::DrmInitialization(const char* mime) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mDrmManagerClient == NULL) {
+ mDrmManagerClient = new DrmManagerClient();
+ }
+
+ if (mDrmManagerClient == NULL) {
+ return NULL;
+ }
+
+ if (mDecryptHandle == NULL) {
+ /* Note if redirect occurs, mUri is the redirect uri instead of the
+ * original one
+ */
+ mDecryptHandle = mDrmManagerClient->openDecryptSession(
+ String8(mURI.c_str()), mime);
+ }
+
+ if (mDecryptHandle == NULL) {
+ delete mDrmManagerClient;
+ mDrmManagerClient = NULL;
+ }
+
+ return mDecryptHandle;
+}
+
+void ChromiumHTTPDataSource::getDrmInfo(
+ sp<DecryptHandle> &handle, DrmManagerClient **client) {
+ Mutex::Autolock autoLock(mLock);
+
+ handle = mDecryptHandle;
+ *client = mDrmManagerClient;
+}
+
+String8 ChromiumHTTPDataSource::getUri() {
+ Mutex::Autolock autoLock(mLock);
+
+ return String8(mURI.c_str());
+}
+
+String8 ChromiumHTTPDataSource::getMIMEType() const {
+ Mutex::Autolock autoLock(mLock);
+
+ return mContentType;
+}
+
+void ChromiumHTTPDataSource::clearDRMState_l() {
+ if (mDecryptHandle != NULL) {
+ // To release mDecryptHandle
+ CHECK(mDrmManagerClient);
+ mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+ mDecryptHandle = NULL;
+ }
+}
+
+status_t ChromiumHTTPDataSource::reconnectAtOffset(off64_t offset) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mURI.empty()) {
+ return INVALID_OPERATION;
+ }
+
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Reconnecting...");
+ status_t err = connect_l(mURI.c_str(), &mHeaders, offset);
+ if (err != OK) {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Reconnect failed w/ err 0x%08x", err);
+ }
+
+ return err;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/chromium_http/DataUriSource.cpp b/media/libstagefright/chromium_http/DataUriSource.cpp
new file mode 100644
index 0000000..ecf3fa1
--- /dev/null
+++ b/media/libstagefright/chromium_http/DataUriSource.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/DataUriSource.h>
+
+#include <net/base/data_url.h>
+#include <googleurl/src/gurl.h>
+
+
+namespace android {
+
+DataUriSource::DataUriSource(const char *uri) :
+ mDataUri(uri),
+ mInited(NO_INIT) {
+
+ // Copy1: const char *uri -> String8 mDataUri.
+ std::string mimeTypeStr, unusedCharsetStr, dataStr;
+ // Copy2: String8 mDataUri -> std::string
+ const bool ret = net::DataURL::Parse(
+ GURL(std::string(mDataUri.string())),
+ &mimeTypeStr, &unusedCharsetStr, &dataStr);
+ // Copy3: std::string dataStr -> AString mData
+ mData.setTo(dataStr.data(), dataStr.length());
+ mInited = ret ? OK : UNKNOWN_ERROR;
+
+ // The chromium data url implementation defaults to using "text/plain"
+ // if no mime type is specified. We prefer to leave this unspecified
+ // instead, since the mime type is sniffed in most cases.
+ if (mimeTypeStr != "text/plain") {
+ mMimeType = mimeTypeStr.c_str();
+ }
+}
+
+ssize_t DataUriSource::readAt(off64_t offset, void *out, size_t size) {
+ if (mInited != OK) {
+ return mInited;
+ }
+
+ const off64_t length = mData.size();
+ if (offset >= length) {
+ return UNKNOWN_ERROR;
+ }
+
+ const char *dataBuf = mData.c_str();
+ const size_t bytesToCopy =
+ offset + size >= length ? (length - offset) : size;
+
+ if (bytesToCopy > 0) {
+ memcpy(out, dataBuf + offset, bytesToCopy);
+ }
+
+ return bytesToCopy;
+}
+
+} // namespace android
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
new file mode 100644
index 0000000..f15014e
--- /dev/null
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -0,0 +1,531 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ChromiumHTTPDataSourceSupport"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/AString.h>
+
+#include "support.h"
+
+#include "android/net/android_network_library_impl.h"
+#include "base/logging.h"
+#include "base/threading/thread.h"
+#include "net/base/cert_verifier.h"
+#include "net/base/cookie_monster.h"
+#include "net/base/host_resolver.h"
+#include "net/base/ssl_config_service.h"
+#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_cache.h"
+#include "net/proxy/proxy_config_service_android.h"
+
+#include "include/ChromiumHTTPDataSource.h"
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <media/stagefright/MediaErrors.h>
+#include <string>
+
+namespace android {
+
+static Mutex gNetworkThreadLock;
+static base::Thread *gNetworkThread = NULL;
+static scoped_refptr<net::URLRequestContext> gReqContext;
+static scoped_ptr<net::NetworkChangeNotifier> gNetworkChangeNotifier;
+
+bool logMessageHandler(
+ int severity,
+ const char* file,
+ int line,
+ size_t message_start,
+ const std::string& str) {
+ int androidSeverity = ANDROID_LOG_VERBOSE;
+ switch(severity) {
+ case logging::LOG_FATAL:
+ androidSeverity = ANDROID_LOG_FATAL;
+ break;
+ case logging::LOG_ERROR_REPORT:
+ case logging::LOG_ERROR:
+ androidSeverity = ANDROID_LOG_ERROR;
+ break;
+ case logging::LOG_WARNING:
+ androidSeverity = ANDROID_LOG_WARN;
+ break;
+ default:
+ androidSeverity = ANDROID_LOG_VERBOSE;
+ break;
+ }
+ android_printLog(androidSeverity, "chromium-libstagefright",
+ "%s:%d: %s", file, line, str.c_str());
+ return false;
+}
+
+struct AutoPrioritySaver {
+ AutoPrioritySaver()
+ : mTID(androidGetTid()),
+ mPrevPriority(androidGetThreadPriority(mTID)) {
+ androidSetThreadPriority(mTID, ANDROID_PRIORITY_NORMAL);
+ }
+
+ ~AutoPrioritySaver() {
+ androidSetThreadPriority(mTID, mPrevPriority);
+ }
+
+private:
+ pid_t mTID;
+ int mPrevPriority;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AutoPrioritySaver);
+};
+
+static void InitializeNetworkThreadIfNecessary() {
+ Mutex::Autolock autoLock(gNetworkThreadLock);
+
+ if (gNetworkThread == NULL) {
+ // Make sure any threads spawned by the chromium framework are
+ // running at normal priority instead of inheriting this thread's.
+ AutoPrioritySaver saver;
+
+ gNetworkThread = new base::Thread("network");
+ base::Thread::Options options;
+ options.message_loop_type = MessageLoop::TYPE_IO;
+ CHECK(gNetworkThread->StartWithOptions(options));
+
+ gReqContext = new SfRequestContext;
+
+ gNetworkChangeNotifier.reset(net::NetworkChangeNotifier::Create());
+
+ net::AndroidNetworkLibrary::RegisterSharedInstance(
+ new SfNetworkLibrary);
+ logging::SetLogMessageHandler(logMessageHandler);
+ }
+}
+
+static void MY_LOGI(const char *s) {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "%s", s);
+}
+
+static void MY_LOGV(const char *s) {
+#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0
+ LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", s);
+#endif
+}
+
+SfNetLog::SfNetLog()
+ : mNextID(1) {
+}
+
+void SfNetLog::AddEntry(
+ EventType type,
+ const base::TimeTicks &time,
+ const Source &source,
+ EventPhase phase,
+ EventParameters *params) {
+#if 0
+ MY_LOGI(StringPrintf(
+ "AddEntry time=%s type=%s source=%s phase=%s\n",
+ TickCountToString(time).c_str(),
+ EventTypeToString(type),
+ SourceTypeToString(source.type),
+ EventPhaseToString(phase)).c_str());
+#endif
+}
+
+uint32 SfNetLog::NextID() {
+ return mNextID++;
+}
+
+net::NetLog::LogLevel SfNetLog::GetLogLevel() const {
+ return LOG_ALL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfRequestContext::SfRequestContext() {
+ AString ua;
+ ua.append("stagefright/1.2 (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");
+ ua.append(value);
+ ua.append(")");
+
+ mUserAgent = ua.c_str();
+
+ set_net_log(new SfNetLog());
+
+ set_host_resolver(
+ net::CreateSystemHostResolver(
+ net::HostResolver::kDefaultParallelism,
+ NULL /* resolver_proc */,
+ net_log()));
+
+ set_ssl_config_service(
+ net::SSLConfigService::CreateSystemSSLConfigService());
+
+ set_proxy_service(net::ProxyService::CreateWithoutProxyResolver(
+ new net::ProxyConfigServiceAndroid, net_log()));
+
+ set_http_transaction_factory(new net::HttpCache(
+ host_resolver(),
+ new net::CertVerifier(),
+ dnsrr_resolver(),
+ dns_cert_checker(),
+ proxy_service(),
+ ssl_config_service(),
+ net::HttpAuthHandlerFactory::CreateDefault(host_resolver()),
+ network_delegate(),
+ net_log(),
+ NULL)); // backend_factory
+
+ set_cookie_store(new net::CookieMonster(NULL, NULL));
+}
+
+const std::string &SfRequestContext::GetUserAgent(const GURL &url) const {
+ return mUserAgent;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfNetworkLibrary::SfNetworkLibrary() {}
+
+SfNetworkLibrary::VerifyResult SfNetworkLibrary::VerifyX509CertChain(
+ const std::vector<std::string>& cert_chain,
+ const std::string& hostname,
+ const std::string& auth_type) {
+ return VERIFY_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfDelegate::SfDelegate()
+ : mOwner(NULL),
+ mURLRequest(NULL),
+ mReadBuffer(new net::IOBufferWithSize(8192)),
+ mNumBytesRead(0),
+ mNumBytesTotal(0),
+ mDataDestination(NULL),
+ mAtEOS(false) {
+ InitializeNetworkThreadIfNecessary();
+}
+
+SfDelegate::~SfDelegate() {
+ CHECK(mURLRequest == NULL);
+}
+
+void SfDelegate::setOwner(ChromiumHTTPDataSource *owner) {
+ mOwner = owner;
+}
+
+void SfDelegate::setUID(uid_t uid) {
+ gReqContext->setUID(uid);
+}
+
+bool SfDelegate::getUID(uid_t *uid) const {
+ return gReqContext->getUID(uid);
+}
+
+void SfDelegate::OnReceivedRedirect(
+ net::URLRequest *request, const GURL &new_url, bool *defer_redirect) {
+ MY_LOGV("OnReceivedRedirect");
+}
+
+void SfDelegate::OnAuthRequired(
+ net::URLRequest *request, net::AuthChallengeInfo *auth_info) {
+ MY_LOGV("OnAuthRequired");
+
+ inherited::OnAuthRequired(request, auth_info);
+}
+
+void SfDelegate::OnCertificateRequested(
+ net::URLRequest *request, net::SSLCertRequestInfo *cert_request_info) {
+ MY_LOGV("OnCertificateRequested");
+
+ inherited::OnCertificateRequested(request, cert_request_info);
+}
+
+void SfDelegate::OnSSLCertificateError(
+ net::URLRequest *request, int cert_error, net::X509Certificate *cert) {
+ fprintf(stderr, "OnSSLCertificateError cert_error=%d\n", cert_error);
+
+ inherited::OnSSLCertificateError(request, cert_error, cert);
+}
+
+void SfDelegate::OnGetCookies(net::URLRequest *request, bool blocked_by_policy) {
+ MY_LOGV("OnGetCookies");
+}
+
+void SfDelegate::OnSetCookie(
+ net::URLRequest *request,
+ const std::string &cookie_line,
+ const net::CookieOptions &options,
+ bool blocked_by_policy) {
+ MY_LOGV("OnSetCookie");
+}
+
+void SfDelegate::OnResponseStarted(net::URLRequest *request) {
+ if (request->status().status() != net::URLRequestStatus::SUCCESS) {
+ MY_LOGI(StringPrintf(
+ "Request failed with status %d and os_error %d",
+ request->status().status(),
+ request->status().os_error()).c_str());
+
+ delete mURLRequest;
+ mURLRequest = NULL;
+
+ mOwner->onConnectionFailed(ERROR_IO);
+ return;
+ } else if (mRangeRequested && request->GetResponseCode() != 206) {
+ MY_LOGI(StringPrintf(
+ "We requested a content range, but server didn't "
+ "support that. (responded with %d)",
+ request->GetResponseCode()).c_str());
+
+ delete mURLRequest;
+ mURLRequest = NULL;
+
+ mOwner->onConnectionFailed(-EPIPE);
+ return;
+ } else if ((request->GetResponseCode() / 100) != 2) {
+ MY_LOGI(StringPrintf(
+ "Server responded with http status %d",
+ request->GetResponseCode()).c_str());
+
+ delete mURLRequest;
+ mURLRequest = NULL;
+
+ mOwner->onConnectionFailed(ERROR_IO);
+ return;
+ }
+
+ MY_LOGV("OnResponseStarted");
+
+ std::string headers;
+ request->GetAllResponseHeaders(&headers);
+
+ MY_LOGV(StringPrintf("response headers: %s", headers.c_str()).c_str());
+
+ std::string contentType;
+ request->GetResponseHeaderByName("Content-Type", &contentType);
+
+ mOwner->onConnectionEstablished(
+ request->GetExpectedContentSize(), contentType.c_str());
+}
+
+void SfDelegate::OnReadCompleted(net::URLRequest *request, int bytes_read) {
+ if (bytes_read == -1) {
+ MY_LOGI(StringPrintf(
+ "OnReadCompleted, read failed, status %d",
+ request->status().status()).c_str());
+
+ mOwner->onReadCompleted(ERROR_IO);
+ return;
+ }
+
+ MY_LOGV(StringPrintf("OnReadCompleted, read %d bytes", bytes_read).c_str());
+
+ if (bytes_read < 0) {
+ MY_LOGI(StringPrintf(
+ "Read failed w/ status %d\n",
+ request->status().status()).c_str());
+
+ mOwner->onReadCompleted(ERROR_IO);
+ return;
+ } else if (bytes_read == 0) {
+ mAtEOS = true;
+ mOwner->onReadCompleted(mNumBytesRead);
+ return;
+ }
+
+ CHECK_GT(bytes_read, 0);
+ CHECK_LE(mNumBytesRead + bytes_read, mNumBytesTotal);
+
+ memcpy((uint8_t *)mDataDestination + mNumBytesRead,
+ mReadBuffer->data(),
+ bytes_read);
+
+ mNumBytesRead += bytes_read;
+
+ readMore(request);
+}
+
+void SfDelegate::readMore(net::URLRequest *request) {
+ while (mNumBytesRead < mNumBytesTotal) {
+ size_t copy = mNumBytesTotal - mNumBytesRead;
+ if (copy > mReadBuffer->size()) {
+ copy = mReadBuffer->size();
+ }
+
+ int n;
+ if (request->Read(mReadBuffer, copy, &n)) {
+ MY_LOGV(StringPrintf("Read %d bytes directly.", n).c_str());
+
+ CHECK_LE((size_t)n, copy);
+
+ memcpy((uint8_t *)mDataDestination + mNumBytesRead,
+ mReadBuffer->data(),
+ n);
+
+ mNumBytesRead += n;
+
+ if (n == 0) {
+ mAtEOS = true;
+ break;
+ }
+ } else {
+ MY_LOGV("readMore pending read");
+
+ if (request->status().status() != net::URLRequestStatus::IO_PENDING) {
+ MY_LOGI(StringPrintf(
+ "Direct read failed w/ status %d\n",
+ request->status().status()).c_str());
+
+ mOwner->onReadCompleted(ERROR_IO);
+ return;
+ }
+
+ return;
+ }
+ }
+
+ mOwner->onReadCompleted(mNumBytesRead);
+}
+
+void SfDelegate::initiateConnection(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ GURL url(uri);
+
+ MessageLoop *loop = gNetworkThread->message_loop();
+ loop->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(
+ &SfDelegate::OnInitiateConnectionWrapper,
+ this,
+ url,
+ headers,
+ offset));
+
+}
+
+// static
+void SfDelegate::OnInitiateConnectionWrapper(
+ SfDelegate *me, GURL url,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ me->onInitiateConnection(url, headers, offset);
+}
+
+void SfDelegate::onInitiateConnection(
+ const GURL &url,
+ const KeyedVector<String8, String8> *extra,
+ off64_t offset) {
+ CHECK(mURLRequest == NULL);
+
+ mURLRequest = new net::URLRequest(url, this);
+ mAtEOS = false;
+
+ mRangeRequested = false;
+
+ if (offset != 0 || extra != NULL) {
+ net::HttpRequestHeaders headers =
+ mURLRequest->extra_request_headers();
+
+ if (offset != 0) {
+ headers.AddHeaderFromString(
+ StringPrintf("Range: bytes=%lld-", offset).c_str());
+
+ mRangeRequested = true;
+ }
+
+ if (extra != NULL) {
+ for (size_t i = 0; i < extra->size(); ++i) {
+ AString s;
+ s.append(extra->keyAt(i).string());
+ s.append(": ");
+ s.append(extra->valueAt(i).string());
+
+ headers.AddHeaderFromString(s.c_str());
+ }
+ }
+
+ mURLRequest->SetExtraRequestHeaders(headers);
+ }
+
+ mURLRequest->set_context(gReqContext);
+
+ mURLRequest->Start();
+}
+
+void SfDelegate::initiateDisconnect() {
+ MessageLoop *loop = gNetworkThread->message_loop();
+ loop->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(
+ &SfDelegate::OnInitiateDisconnectWrapper, this));
+}
+
+// static
+void SfDelegate::OnInitiateDisconnectWrapper(SfDelegate *me) {
+ me->onInitiateDisconnect();
+}
+
+void SfDelegate::onInitiateDisconnect() {
+ mURLRequest->Cancel();
+
+ delete mURLRequest;
+ mURLRequest = NULL;
+
+ mOwner->onDisconnectComplete();
+}
+
+void SfDelegate::initiateRead(void *data, size_t size) {
+ MessageLoop *loop = gNetworkThread->message_loop();
+ loop->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(
+ &SfDelegate::OnInitiateReadWrapper, this, data, size));
+}
+
+// static
+void SfDelegate::OnInitiateReadWrapper(
+ SfDelegate *me, void *data, size_t size) {
+ me->onInitiateRead(data, size);
+}
+
+void SfDelegate::onInitiateRead(void *data, size_t size) {
+ CHECK(mURLRequest != NULL);
+
+ mNumBytesRead = 0;
+ mNumBytesTotal = size;
+ mDataDestination = data;
+
+ if (mAtEOS) {
+ mOwner->onReadCompleted(0);
+ return;
+ }
+
+ readMore(mURLRequest);
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/chromium_http/support.h b/media/libstagefright/chromium_http/support.h
new file mode 100644
index 0000000..d2c5bc0
--- /dev/null
+++ b/media/libstagefright/chromium_http/support.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SUPPORT_H_
+
+#define SUPPORT_H_
+
+#include <assert.h>
+
+#include "net/base/net_log.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/base/android_network_library.h"
+#include "net/base/io_buffer.h"
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+namespace android {
+
+struct SfNetLog : public net::NetLog {
+ SfNetLog();
+
+ virtual void AddEntry(
+ EventType type,
+ const base::TimeTicks &time,
+ const Source &source,
+ EventPhase phase,
+ EventParameters *params);
+
+ virtual uint32 NextID();
+ virtual LogLevel GetLogLevel() const;
+
+private:
+ uint32 mNextID;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SfNetLog);
+};
+
+struct SfRequestContext : public net::URLRequestContext {
+ SfRequestContext();
+
+ virtual const std::string &GetUserAgent(const GURL &url) const;
+
+private:
+ std::string mUserAgent;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SfRequestContext);
+};
+
+// This is required for https support, we don't really verify certificates,
+// we accept anything...
+struct SfNetworkLibrary : public net::AndroidNetworkLibrary {
+ SfNetworkLibrary();
+
+ virtual VerifyResult VerifyX509CertChain(
+ const std::vector<std::string>& cert_chain,
+ const std::string& hostname,
+ const std::string& auth_type);
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(SfNetworkLibrary);
+};
+
+struct ChromiumHTTPDataSource;
+
+struct SfDelegate : public net::URLRequest::Delegate {
+ SfDelegate();
+ virtual ~SfDelegate();
+
+ void initiateConnection(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset);
+
+ void initiateDisconnect();
+ void initiateRead(void *data, size_t size);
+
+ void setOwner(ChromiumHTTPDataSource *mOwner);
+
+ // Gets the UID of the calling process
+ bool getUID(uid_t *uid) const;
+
+ void setUID(uid_t uid);
+
+ virtual void OnReceivedRedirect(
+ net::URLRequest *request, const GURL &new_url, bool *defer_redirect);
+
+ virtual void OnAuthRequired(
+ net::URLRequest *request, net::AuthChallengeInfo *auth_info);
+
+ virtual void OnCertificateRequested(
+ net::URLRequest *request, net::SSLCertRequestInfo *cert_request_info);
+
+ virtual void OnSSLCertificateError(
+ net::URLRequest *request, int cert_error, net::X509Certificate *cert);
+
+ virtual void OnGetCookies(net::URLRequest *request, bool blocked_by_policy);
+
+ virtual void OnSetCookie(
+ net::URLRequest *request,
+ const std::string &cookie_line,
+ const net::CookieOptions &options,
+ bool blocked_by_policy);
+
+ virtual void OnResponseStarted(net::URLRequest *request);
+
+ virtual void OnReadCompleted(net::URLRequest *request, int bytes_read);
+
+private:
+ typedef Delegate inherited;
+
+ ChromiumHTTPDataSource *mOwner;
+
+ net::URLRequest *mURLRequest;
+ scoped_refptr<net::IOBufferWithSize> mReadBuffer;
+
+ size_t mNumBytesRead;
+ size_t mNumBytesTotal;
+ void *mDataDestination;
+
+ bool mRangeRequested;
+ bool mAtEOS;
+
+ void readMore(net::URLRequest *request);
+
+ static void OnInitiateConnectionWrapper(
+ SfDelegate *me,
+ GURL url,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset);
+
+ static void OnInitiateDisconnectWrapper(SfDelegate *me);
+
+ static void OnInitiateReadWrapper(
+ SfDelegate *me, void *data, size_t size);
+
+ void onInitiateConnection(
+ const GURL &url,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset);
+
+ void onInitiateDisconnect();
+ void onInitiateRead(void *data, size_t size);
+
+ DISALLOW_EVIL_CONSTRUCTORS(SfDelegate);
+};
+
+} // namespace android
+
+#endif // SUPPORT_H_
diff --git a/media/libstagefright/codecs/Android.mk b/media/libstagefright/codecs/Android.mk
new file mode 100644
index 0000000..2e43120
--- /dev/null
+++ b/media/libstagefright/codecs/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/aacdec/Android.mk b/media/libstagefright/codecs/aacdec/Android.mk
new file mode 100644
index 0000000..fd6de79
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/Android.mk
@@ -0,0 +1,180 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ analysis_sub_band.cpp \
+ apply_ms_synt.cpp \
+ apply_tns.cpp \
+ buf_getbits.cpp \
+ byte_align.cpp \
+ calc_auto_corr.cpp \
+ calc_gsfb_table.cpp \
+ calc_sbr_anafilterbank.cpp \
+ calc_sbr_envelope.cpp \
+ calc_sbr_synfilterbank.cpp \
+ check_crc.cpp \
+ dct16.cpp \
+ dct64.cpp \
+ decode_huff_cw_binary.cpp \
+ decode_noise_floorlevels.cpp \
+ deinterleave.cpp \
+ digit_reversal_tables.cpp \
+ dst16.cpp \
+ dst32.cpp \
+ dst8.cpp \
+ esc_iquant_scaling.cpp \
+ extractframeinfo.cpp \
+ fft_rx4_long.cpp \
+ fft_rx4_short.cpp \
+ fft_rx4_tables_fxp.cpp \
+ find_adts_syncword.cpp \
+ fwd_long_complex_rot.cpp \
+ fwd_short_complex_rot.cpp \
+ gen_rand_vector.cpp \
+ get_adif_header.cpp \
+ get_adts_header.cpp \
+ get_audio_specific_config.cpp \
+ get_dse.cpp \
+ get_ele_list.cpp \
+ get_ga_specific_config.cpp \
+ get_ics_info.cpp \
+ get_prog_config.cpp \
+ get_pulse_data.cpp \
+ get_sbr_bitstream.cpp \
+ get_sbr_startfreq.cpp \
+ get_sbr_stopfreq.cpp \
+ get_tns.cpp \
+ getfill.cpp \
+ getgroup.cpp \
+ getics.cpp \
+ getmask.cpp \
+ hcbtables_binary.cpp \
+ huffcb.cpp \
+ huffdecode.cpp \
+ hufffac.cpp \
+ huffspec_fxp.cpp \
+ idct16.cpp \
+ idct32.cpp \
+ idct8.cpp \
+ imdct_fxp.cpp \
+ infoinit.cpp \
+ init_sbr_dec.cpp \
+ intensity_right.cpp \
+ inv_long_complex_rot.cpp \
+ inv_short_complex_rot.cpp \
+ iquant_table.cpp \
+ long_term_prediction.cpp \
+ long_term_synthesis.cpp \
+ lt_decode.cpp \
+ mdct_fxp.cpp \
+ mdct_tables_fxp.cpp \
+ mdst.cpp \
+ mix_radix_fft.cpp \
+ ms_synt.cpp \
+ pns_corr.cpp \
+ pns_intensity_right.cpp \
+ pns_left.cpp \
+ ps_all_pass_filter_coeff.cpp \
+ ps_all_pass_fract_delay_filter.cpp \
+ ps_allocate_decoder.cpp \
+ ps_applied.cpp \
+ ps_bstr_decoding.cpp \
+ ps_channel_filtering.cpp \
+ ps_decode_bs_utils.cpp \
+ ps_decorrelate.cpp \
+ ps_fft_rx8.cpp \
+ ps_hybrid_analysis.cpp \
+ ps_hybrid_filter_bank_allocation.cpp \
+ ps_hybrid_synthesis.cpp \
+ ps_init_stereo_mixing.cpp \
+ ps_pwr_transient_detection.cpp \
+ ps_read_data.cpp \
+ ps_stereo_processing.cpp \
+ pulse_nc.cpp \
+ pv_div.cpp \
+ pv_log2.cpp \
+ pv_normalize.cpp \
+ pv_pow2.cpp \
+ pv_sine.cpp \
+ pv_sqrt.cpp \
+ pvmp4audiodecoderconfig.cpp \
+ pvmp4audiodecoderframe.cpp \
+ pvmp4audiodecodergetmemrequirements.cpp \
+ pvmp4audiodecoderinitlibrary.cpp \
+ pvmp4audiodecoderresetbuffer.cpp \
+ q_normalize.cpp \
+ qmf_filterbank_coeff.cpp \
+ sbr_aliasing_reduction.cpp \
+ sbr_applied.cpp \
+ sbr_code_book_envlevel.cpp \
+ sbr_crc_check.cpp \
+ sbr_create_limiter_bands.cpp \
+ sbr_dec.cpp \
+ sbr_decode_envelope.cpp \
+ sbr_decode_huff_cw.cpp \
+ sbr_downsample_lo_res.cpp \
+ sbr_envelope_calc_tbl.cpp \
+ sbr_envelope_unmapping.cpp \
+ sbr_extract_extended_data.cpp \
+ sbr_find_start_andstop_band.cpp \
+ sbr_generate_high_freq.cpp \
+ sbr_get_additional_data.cpp \
+ sbr_get_cpe.cpp \
+ sbr_get_dir_control_data.cpp \
+ sbr_get_envelope.cpp \
+ sbr_get_header_data.cpp \
+ sbr_get_noise_floor_data.cpp \
+ sbr_get_sce.cpp \
+ sbr_inv_filt_levelemphasis.cpp \
+ sbr_open.cpp \
+ sbr_read_data.cpp \
+ sbr_requantize_envelope_data.cpp \
+ sbr_reset_dec.cpp \
+ sbr_update_freq_scale.cpp \
+ set_mc_info.cpp \
+ sfb.cpp \
+ shellsort.cpp \
+ synthesis_sub_band.cpp \
+ tns_ar_filter.cpp \
+ tns_decode_coef.cpp \
+ tns_inv_filter.cpp \
+ trans4m_freq_2_time_fxp.cpp \
+ trans4m_time_2_freq_fxp.cpp \
+ unpack_idx.cpp \
+ window_tables_fxp.cpp \
+ pvmp4setaudioconfig.cpp \
+
+LOCAL_CFLAGS := -DAAC_PLUS -DHQ_SBR -DPARAMETRICSTEREO -DOSCL_IMPORT_REF= -DOSCL_EXPORT_REF= -DOSCL_UNUSED_ARG=
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_MODULE := libstagefright_aacdec
+
+include $(BUILD_STATIC_LIBRARY)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ SoftAAC.cpp
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+ frameworks/native/include/media/openmax
+
+LOCAL_CFLAGS := -DOSCL_IMPORT_REF=
+
+LOCAL_STATIC_LIBRARIES := \
+ libstagefright_aacdec
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright_omx libstagefright_foundation libutils
+
+LOCAL_MODULE := libstagefright_soft_aacdec
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC.cpp b/media/libstagefright/codecs/aacdec/SoftAAC.cpp
new file mode 100644
index 0000000..90f96c6
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/SoftAAC.cpp
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SoftAAC"
+#include <utils/Log.h>
+
+#include "SoftAAC.h"
+
+#include "pvmp4audiodecoder_api.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/hexdump.h>
+
+namespace android {
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+SoftAAC::SoftAAC(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SimpleSoftOMXComponent(name, callbacks, appData, component),
+ mConfig(new tPVMP4AudioDecoderExternal),
+ mIsADTS(false),
+ mDecoderBuf(NULL),
+ mInputBufferCount(0),
+ mUpsamplingFactor(2),
+ mAnchorTimeUs(0),
+ mNumSamplesOutput(0),
+ mSignalledError(false),
+ mOutputPortSettingsChange(NONE) {
+ initPorts();
+ CHECK_EQ(initDecoder(), (status_t)OK);
+}
+
+SoftAAC::~SoftAAC() {
+ free(mDecoderBuf);
+ mDecoderBuf = NULL;
+
+ delete mConfig;
+ mConfig = NULL;
+}
+
+void SoftAAC::initPorts() {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+
+ def.nPortIndex = 0;
+ def.eDir = OMX_DirInput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 8192;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 1;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/aac");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
+
+ addPort(def);
+
+ def.nPortIndex = 1;
+ def.eDir = OMX_DirOutput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 8192;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 2;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ addPort(def);
+}
+
+status_t SoftAAC::initDecoder() {
+ memset(mConfig, 0, sizeof(tPVMP4AudioDecoderExternal));
+ mConfig->outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED;
+ mConfig->aacPlusEnabled = 1;
+
+ // The software decoder doesn't properly support mono output on
+ // AACplus files. Always output stereo.
+ mConfig->desiredChannels = 2;
+
+ UInt32 memRequirements = PVMP4AudioDecoderGetMemRequirements();
+ mDecoderBuf = malloc(memRequirements);
+
+ Int err = PVMP4AudioDecoderInitLibrary(mConfig, mDecoderBuf);
+ if (err != MP4AUDEC_SUCCESS) {
+ ALOGE("Failed to initialize MP4 audio decoder");
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+OMX_ERRORTYPE SoftAAC::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamAudioAac:
+ {
+ OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
+ (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
+
+ if (aacParams->nPortIndex != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ aacParams->nBitRate = 0;
+ aacParams->nAudioBandWidth = 0;
+ aacParams->nAACtools = 0;
+ aacParams->nAACERtools = 0;
+ aacParams->eAACProfile = OMX_AUDIO_AACObjectMain;
+
+ aacParams->eAACStreamFormat =
+ mIsADTS
+ ? OMX_AUDIO_AACStreamFormatMP4ADTS
+ : OMX_AUDIO_AACStreamFormatMP4FF;
+
+ aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
+
+ if (!isConfigured()) {
+ aacParams->nChannels = 1;
+ aacParams->nSampleRate = 44100;
+ aacParams->nFrameLength = 0;
+ } else {
+ aacParams->nChannels = mConfig->encodedChannels;
+ aacParams->nSampleRate = mConfig->samplingRate;
+ aacParams->nFrameLength = mConfig->frameLength;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPcm:
+ {
+ OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eEndian = OMX_EndianBig;
+ pcmParams->bInterleaved = OMX_TRUE;
+ pcmParams->nBitPerSample = 16;
+ pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
+ pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+ pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+
+ if (!isConfigured()) {
+ pcmParams->nChannels = 1;
+ pcmParams->nSamplingRate = 44100;
+ } else {
+ pcmParams->nChannels = mConfig->desiredChannels;
+ pcmParams->nSamplingRate = mConfig->samplingRate;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftAAC::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamStandardComponentRole:
+ {
+ const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+ (const OMX_PARAM_COMPONENTROLETYPE *)params;
+
+ if (strncmp((const char *)roleParams->cRole,
+ "audio_decoder.aac",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioAac:
+ {
+ const OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
+ (const OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
+
+ if (aacParams->nPortIndex != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (aacParams->eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4FF) {
+ mIsADTS = false;
+ } else if (aacParams->eAACStreamFormat
+ == OMX_AUDIO_AACStreamFormatMP4ADTS) {
+ mIsADTS = true;
+ } else {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPcm:
+ {
+ const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ }
+}
+
+bool SoftAAC::isConfigured() const {
+ return mInputBufferCount > 0;
+}
+
+void SoftAAC::onQueueFilled(OMX_U32 portIndex) {
+ if (mSignalledError || mOutputPortSettingsChange != NONE) {
+ return;
+ }
+
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+
+ if (portIndex == 0 && mInputBufferCount == 0) {
+ ++mInputBufferCount;
+
+ BufferInfo *info = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *header = info->mHeader;
+
+ mConfig->pInputBuffer = header->pBuffer + header->nOffset;
+ mConfig->inputBufferCurrentLength = header->nFilledLen;
+ mConfig->inputBufferMaxLength = 0;
+
+ Int err = PVMP4AudioDecoderConfig(mConfig, mDecoderBuf);
+ if (err != MP4AUDEC_SUCCESS) {
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, err, NULL);
+ return;
+ }
+
+ inQueue.erase(inQueue.begin());
+ info->mOwnedByUs = false;
+ notifyEmptyBufferDone(header);
+
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+ return;
+ }
+
+ while (!inQueue.empty() && !outQueue.empty()) {
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+
+ outHeader->nFilledLen = 0;
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+
+ outQueue.erase(outQueue.begin());
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+ return;
+ }
+
+ if (inHeader->nOffset == 0) {
+ mAnchorTimeUs = inHeader->nTimeStamp;
+ mNumSamplesOutput = 0;
+ }
+
+ if (mIsADTS) {
+ // skip 30 bits, aac_frame_length follows.
+ // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll?????
+
+ const uint8_t *adtsHeader = inHeader->pBuffer + inHeader->nOffset;
+
+ CHECK_GE(inHeader->nFilledLen, 7);
+
+ bool protectionAbsent = (adtsHeader[1] & 1);
+
+ unsigned aac_frame_length =
+ ((adtsHeader[3] & 3) << 11)
+ | (adtsHeader[4] << 3)
+ | (adtsHeader[5] >> 5);
+
+ CHECK_GE(inHeader->nFilledLen, aac_frame_length);
+
+ size_t headerSize = (protectionAbsent ? 7 : 9);
+
+ mConfig->pInputBuffer = (UChar *)adtsHeader + headerSize;
+ mConfig->inputBufferCurrentLength = aac_frame_length - headerSize;
+
+ inHeader->nOffset += headerSize;
+ inHeader->nFilledLen -= headerSize;
+ } else {
+ mConfig->pInputBuffer = inHeader->pBuffer + inHeader->nOffset;
+ mConfig->inputBufferCurrentLength = inHeader->nFilledLen;
+ }
+
+ mConfig->inputBufferMaxLength = 0;
+ mConfig->inputBufferUsedLength = 0;
+ mConfig->remainderBits = 0;
+
+ mConfig->pOutputBuffer =
+ reinterpret_cast<Int16 *>(outHeader->pBuffer + outHeader->nOffset);
+
+ mConfig->pOutputBuffer_plus = &mConfig->pOutputBuffer[2048];
+ mConfig->repositionFlag = false;
+
+ Int32 prevSamplingRate = mConfig->samplingRate;
+ Int decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf);
+
+ /*
+ * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
+ * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
+ * rate system and the sampling rate in the final output is actually
+ * doubled compared with the core AAC decoder sampling rate.
+ *
+ * Explicit signalling is done by explicitly defining SBR audio object
+ * type in the bitstream. Implicit signalling is done by embedding
+ * SBR content in AAC extension payload specific to SBR, and hence
+ * requires an AAC decoder to perform pre-checks on actual audio frames.
+ *
+ * Thus, we could not say for sure whether a stream is
+ * AAC+/eAAC+ until the first data frame is decoded.
+ */
+ if (decoderErr == MP4AUDEC_SUCCESS && mInputBufferCount <= 2) {
+ ALOGV("audio/extended audio object type: %d + %d",
+ mConfig->audioObjectType, mConfig->extendedAudioObjectType);
+ ALOGV("aac+ upsampling factor: %d desired channels: %d",
+ mConfig->aacPlusUpsamplingFactor, mConfig->desiredChannels);
+
+ if (mInputBufferCount == 1) {
+ mUpsamplingFactor = mConfig->aacPlusUpsamplingFactor;
+ // Check on the sampling rate to see whether it is changed.
+ if (mConfig->samplingRate != prevSamplingRate) {
+ ALOGW("Sample rate was %d Hz, but now is %d Hz",
+ prevSamplingRate, mConfig->samplingRate);
+
+ // We'll hold onto the input buffer and will decode
+ // it again once the output port has been reconfigured.
+
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+ return;
+ }
+ } else { // mInputBufferCount == 2
+ if (mConfig->extendedAudioObjectType == MP4AUDIO_AAC_LC ||
+ mConfig->extendedAudioObjectType == MP4AUDIO_LTP) {
+ if (mUpsamplingFactor == 2) {
+ // The stream turns out to be not aacPlus mode anyway
+ ALOGW("Disable AAC+/eAAC+ since extended audio object "
+ "type is %d",
+ mConfig->extendedAudioObjectType);
+ mConfig->aacPlusEnabled = 0;
+ }
+ } else {
+ if (mUpsamplingFactor == 1) {
+ // aacPlus mode does not buy us anything, but to cause
+ // 1. CPU load to increase, and
+ // 2. a half speed of decoding
+ ALOGW("Disable AAC+/eAAC+ since upsampling factor is 1");
+ mConfig->aacPlusEnabled = 0;
+ }
+ }
+ }
+ }
+
+ size_t numOutBytes =
+ mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels;
+
+ if (decoderErr == MP4AUDEC_SUCCESS) {
+ CHECK_LE(mConfig->inputBufferUsedLength, inHeader->nFilledLen);
+
+ inHeader->nFilledLen -= mConfig->inputBufferUsedLength;
+ inHeader->nOffset += mConfig->inputBufferUsedLength;
+ } else {
+ ALOGW("AAC decoder returned error %d, substituting silence",
+ decoderErr);
+
+ memset(outHeader->pBuffer + outHeader->nOffset, 0, numOutBytes);
+
+ // Discard input buffer.
+ inHeader->nFilledLen = 0;
+
+ // fall through
+ }
+
+ if (decoderErr == MP4AUDEC_SUCCESS || mNumSamplesOutput > 0) {
+ // We'll only output data if we successfully decoded it or
+ // we've previously decoded valid data, in the latter case
+ // (decode failed) we'll output a silent frame.
+
+ if (mUpsamplingFactor == 2) {
+ if (mConfig->desiredChannels == 1) {
+ memcpy(&mConfig->pOutputBuffer[1024],
+ &mConfig->pOutputBuffer[2048],
+ numOutBytes * 2);
+ }
+ numOutBytes *= 2;
+ }
+
+ outHeader->nFilledLen = numOutBytes;
+ outHeader->nFlags = 0;
+
+ outHeader->nTimeStamp =
+ mAnchorTimeUs
+ + (mNumSamplesOutput * 1000000ll) / mConfig->samplingRate;
+
+ mNumSamplesOutput += mConfig->frameLength * mUpsamplingFactor;
+
+ outInfo->mOwnedByUs = false;
+ outQueue.erase(outQueue.begin());
+ outInfo = NULL;
+ notifyFillBufferDone(outHeader);
+ outHeader = NULL;
+ }
+
+ if (inHeader->nFilledLen == 0) {
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+ }
+
+ if (decoderErr == MP4AUDEC_SUCCESS) {
+ ++mInputBufferCount;
+ }
+ }
+}
+
+void SoftAAC::onPortFlushCompleted(OMX_U32 portIndex) {
+ if (portIndex == 0) {
+ // Make sure that the next buffer output does not still
+ // depend on fragments from the last one decoded.
+ PVMP4AudioDecoderResetBuffer(mDecoderBuf);
+ }
+}
+
+void SoftAAC::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
+ if (portIndex != 1) {
+ return;
+ }
+
+ switch (mOutputPortSettingsChange) {
+ case NONE:
+ break;
+
+ case AWAITING_DISABLED:
+ {
+ CHECK(!enabled);
+ mOutputPortSettingsChange = AWAITING_ENABLED;
+ break;
+ }
+
+ default:
+ {
+ CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
+ CHECK(enabled);
+ mOutputPortSettingsChange = NONE;
+ break;
+ }
+ }
+}
+
+} // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+ const char *name, const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+ return new android::SoftAAC(name, callbacks, appData, component);
+}
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC.h b/media/libstagefright/codecs/aacdec/SoftAAC.h
new file mode 100644
index 0000000..da0b8ed
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/SoftAAC.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SOFT_AAC_H_
+
+#define SOFT_AAC_H_
+
+#include "SimpleSoftOMXComponent.h"
+
+struct tPVMP4AudioDecoderExternal;
+
+namespace android {
+
+struct SoftAAC : public SimpleSoftOMXComponent {
+ SoftAAC(const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ virtual ~SoftAAC();
+
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual void onQueueFilled(OMX_U32 portIndex);
+ virtual void onPortFlushCompleted(OMX_U32 portIndex);
+ virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled);
+
+private:
+ enum {
+ kNumBuffers = 4
+ };
+
+ tPVMP4AudioDecoderExternal *mConfig;
+ bool mIsADTS;
+ void *mDecoderBuf;
+
+ size_t mInputBufferCount;
+ size_t mUpsamplingFactor;
+ int64_t mAnchorTimeUs;
+ int64_t mNumSamplesOutput;
+
+ bool mSignalledError;
+
+ enum {
+ NONE,
+ AWAITING_DISABLED,
+ AWAITING_ENABLED
+ } mOutputPortSettingsChange;
+
+ void initPorts();
+ status_t initDecoder();
+ bool isConfigured() const;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftAAC);
+};
+
+} // namespace android
+
+#endif // SOFT_AAC_H_
diff --git a/media/libstagefright/codecs/aacdec/aac_mem_funcs.h b/media/libstagefright/codecs/aacdec/aac_mem_funcs.h
new file mode 100644
index 0000000..ce7cb12
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/aac_mem_funcs.h
@@ -0,0 +1,50 @@
+/* ------------------------------------------------------------------
+ * 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: aac_mem_funcs.h
+ Funtions:
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+
+#include <string.h>
+
+#ifndef AAC_MEM_FUNCS_H
+#define AAC_MEM_FUNCS_H
+
+#define pv_memset(to, c, n) memset(to, c, n)
+
+
+#define pv_memcpy(to, from, n) memcpy(to, from, n)
+#define pv_memmove(to, from, n) memmove(to, from, n)
+#define pv_memcmp(p, q, n) memcmp(p, q, n)
+
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/analysis_sub_band.cpp b/media/libstagefright/codecs/aacdec/analysis_sub_band.cpp
new file mode 100644
index 0000000..2786dcc
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/analysis_sub_band.cpp
@@ -0,0 +1,289 @@
+/* ------------------------------------------------------------------
+ * 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: analysis_sub_band.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 vec[], Input vector, 32-bit
+ const Int32 *cosTerms, Cosine Terms
+ Int maxbands number of bands used
+ Int32 *scratch_mem Scratch memory
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement root squared of a number
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "analysis_sub_band.h"
+#include "dst32.h"
+#include "idct32.h"
+#include "mdst.h"
+
+#include "aac_mem_funcs.h"
+#include "pv_audio_type_defs.h"
+#include "fxp_mul32.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+#ifdef HQ_SBR
+
+
+const Int32 exp_1_5_phi[32] =
+{
+
+ 0x7FEA04B6, 0x7F380E1C, 0x7DD6176E, 0x7BC6209F,
+ 0x790A29A4, 0x75A6326E, 0x719E3AF3, 0x6CF94326,
+ 0x67BD4AFB, 0x61F15269, 0x5B9D5964, 0x54CA5FE4,
+ 0x4D8165DE, 0x45CD6B4B, 0x3DB87023, 0x354E7460,
+ 0x2C9977FB, 0x23A77AEF, 0x1A837D3A, 0x113A7ED6,
+ 0x07D97FC2, 0xFE6E7FFE, 0xF5057F87, 0xEBAB7E60,
+ 0xE26D7C89, 0xD9587A06, 0xD07976D9, 0xC7DB7308,
+ 0xBF8C6E97, 0xB796698C, 0xB00563EF, 0xA8E25DC8,
+
+};
+
+#endif
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void analysis_sub_band_LC(Int32 vec[64],
+ Int32 cosine_total[],
+ Int32 maxBand,
+ Int32 scratch_mem[][64])
+{
+ Int32 i;
+ Int32 *cosine_term = &scratch_mem[0][0];
+ Int32 *sine_term = &scratch_mem[0][32];
+
+ Int32 *pt_cos_t;
+
+
+ Int32 *pt_vec = &vec[0];
+ Int32 *pt_vec_32 = &vec[32];
+
+ Int32 *pt_cos = cosine_term;
+ Int32 *pt_sin = sine_term;
+
+ for (i = 8; i != 0; i--)
+ {
+ Int32 tmp1 = *(pt_vec_32++);
+ Int32 tmp3 = *(pt_vec_32++);
+ Int32 tmp2 = *(pt_vec++);
+ Int32 tmp4 = *(pt_vec++);
+ *(pt_cos++) = (tmp1 - tmp2) >> 1;
+ *(pt_cos++) = (tmp3 - tmp4) >> 1;
+ *(pt_sin++) = (tmp1 + tmp2);
+ *(pt_sin++) = (tmp3 + tmp4);
+ tmp1 = *(pt_vec_32++);
+ tmp3 = *(pt_vec_32++);
+ tmp2 = *(pt_vec++);
+ tmp4 = *(pt_vec++);
+ *(pt_cos++) = (tmp1 - tmp2) >> 1;
+ *(pt_cos++) = (tmp3 - tmp4) >> 1;
+ *(pt_sin++) = (tmp1 + tmp2);
+ *(pt_sin++) = (tmp3 + tmp4);
+ }
+
+
+ idct_32(cosine_term, scratch_mem[1]);
+
+ dst_32(sine_term, scratch_mem[1]);
+
+ pt_cos = cosine_term;
+ pt_sin = sine_term;
+
+ pt_cos_t = cosine_total;
+
+ for (i = 0; i < maxBand; i += 4)
+ {
+ *(pt_cos_t++) = (*(pt_cos++) + *(pt_sin++));
+ *(pt_cos_t++) = (-*(pt_cos++) + *(pt_sin++));
+ *(pt_cos_t++) = (-*(pt_cos++) - *(pt_sin++));
+ *(pt_cos_t++) = (*(pt_cos++) - *(pt_sin++));
+ }
+
+ pt_cos_t = &cosine_total[maxBand];
+
+ for (i = (32 - maxBand); i != 0; i--)
+ {
+ *(pt_cos_t++) = 0;
+ }
+}
+
+
+#ifdef HQ_SBR
+
+
+void analysis_sub_band(Int32 vec[64],
+ Int32 cosine_total[],
+ Int32 sine_total[],
+ Int32 maxBand,
+ Int32 scratch_mem[][64])
+{
+ Int32 i;
+ Int32 *sine_term1 = &scratch_mem[0][0];
+ Int32 *sine_term2 = &scratch_mem[0][32];
+
+ Int32 temp1;
+ Int32 temp2;
+ Int32 temp3;
+ Int32 temp4;
+
+ const Int32 *pt_exp;
+ Int32 exp_1_5;
+
+ Int32 *pt_vec = &vec[0];
+ Int32 *pt_vec_32 = &vec[32];
+
+ Int32 *pt_cos1 = pt_vec;
+ Int32 *pt_sin1 = sine_term1;
+ Int32 *pt_cos2 = pt_vec_32;
+ Int32 *pt_sin2 = sine_term2;
+
+
+ pv_memcpy(sine_term1, vec, 64*sizeof(*vec));
+
+ mdst_32(sine_term1, scratch_mem[1]);
+ mdst_32(sine_term2, scratch_mem[1]);
+
+ mdct_32(&vec[ 0]);
+ mdct_32(&vec[32]);
+
+ pt_cos1 = &vec[ 0];
+ pt_cos2 = &vec[32];
+
+
+ pt_sin1 = sine_term1;
+ pt_sin2 = sine_term2;
+
+ pt_vec = cosine_total;
+ pt_vec_32 = sine_total;
+ pt_exp = exp_1_5_phi;
+
+ temp3 = (*(pt_cos1++) - *(pt_sin2++));
+ temp4 = (*(pt_sin1++) + *(pt_cos2++));
+
+ for (i = 0; i < maxBand; i += 2)
+ {
+
+ exp_1_5 = *(pt_exp++);
+ temp1 = cmplx_mul32_by_16(temp3, temp4, exp_1_5);
+ temp2 = cmplx_mul32_by_16(temp4, -temp3, exp_1_5);
+
+ *(pt_vec++) = shft_lft_1(temp1);
+ *(pt_vec_32++) = shft_lft_1(temp2);
+
+ temp3 = (*(pt_cos1++) + *(pt_sin2++));
+ temp4 = (*(pt_sin1++) - *(pt_cos2++));
+
+ exp_1_5 = *(pt_exp++);
+ temp1 = cmplx_mul32_by_16(temp3, temp4, exp_1_5);
+ temp2 = cmplx_mul32_by_16(temp4, -temp3, exp_1_5);
+
+ *(pt_vec++) = shft_lft_1(temp1);
+ *(pt_vec_32++) = shft_lft_1(temp2);
+
+ temp3 = (*(pt_cos1++) - *(pt_sin2++));
+ temp4 = (*(pt_sin1++) + *(pt_cos2++));
+ }
+
+
+ pt_cos1 = &cosine_total[maxBand]; /* in the chance that maxband is not even */
+ pt_sin1 = &sine_total[maxBand];
+
+ for (i = (32 - maxBand); i != 0; i--)
+ {
+ *(pt_cos1++) = 0;
+ *(pt_sin1++) = 0;
+ }
+
+}
+
+
+#endif
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/analysis_sub_band.h b/media/libstagefright/codecs/aacdec/analysis_sub_band.h
new file mode 100644
index 0000000..815456c
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/analysis_sub_band.h
@@ -0,0 +1,82 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./c/include/analysis_sub_band.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef ANALYSIS_SUB_BAND_H
+#define ANALYSIS_SUB_BAND_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ void analysis_sub_band_LC(Int32 vec[64],
+ Int32 cosine_total[],
+ Int32 maxBand,
+ Int32 scratch_mem[][64]);
+
+#ifdef HQ_SBR
+
+
+ void analysis_sub_band(Int32 vec[64],
+ Int32 cosine_total[],
+ Int32 sine_total[],
+ Int32 maxBand,
+ Int32 scratch_mem[][64]);
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ANALYSIS_SUB_BAND_H */
diff --git a/media/libstagefright/codecs/aacdec/apply_ms_synt.cpp b/media/libstagefright/codecs/aacdec/apply_ms_synt.cpp
new file mode 100644
index 0000000..ab36c6a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/apply_ms_synt.cpp
@@ -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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/apply_ms_synt.c
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated pseudocode to correct capitalized format for the IF
+ FOR and WHILE statements.
+
+ Description: Delete local variable start_indx, since it is never used.
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ pFrameInfo = Pointer to structure that holds information about each group.
+ (long block flag, number of windows, scalefactor bands
+ per group, etc.)
+ [const pFrameInfo * const]
+
+ group = Array that contains indexes of the
+ first window in the next group.
+ [const Int *, length 8]
+
+ mask_map = Array that denotes whether M/S stereo is turned on for
+ each grouped scalefactor band.
+ [const Int *, length MAX_SFB]
+
+ codebook_map = Array that denotes which Huffman codebook was used for
+ the encoding of each grouped scalefactor band.
+ [const Int *, length MAX_SFB]
+
+ coefLeft = Array containing the fixed-point spectral coefficients
+ for the left channel.
+ [Int32 *, length 1024]
+
+ coefRight = Array containing the fixed-point spectral coefficients
+ for the right channel.
+ [Int32 *, length 1024]
+
+ q_formatLeft = The Q-format for the left channel's fixed-point spectral
+ coefficients, on a per-scalefactor band, non-grouped basis.
+ [Int *, length MAX_SFB]
+
+ q_formatRight = The Q-format for the right channel's fixed-point spectral
+ coefficients, on a per-scalefactor band, non-grouped basis.
+ [Int *, length MAX_SFB]
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ coefLeft = Contains the new spectral information.
+
+ coefRight = Contains the new spectral information.
+
+ q_formatLeft = Q-format may be updated with changed to fixed-point
+ data in coefLeft.
+
+ q_formatRight = Q-format may be updated with changed to fixed-point
+ data in coefRight.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function steps through all of the tools that are applied on a
+ scalefactor band basis.
+
+ The use of M/S stereo is checked for. For M/S decoding to take
+ place, ms_mask_map must be TRUE for that particular SFB, AND the Huffman
+ codebook used must be < NOISE_HCB.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.6.7.1 M/S stereo
+ Subpart 4.6.2 ScaleFactors
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ pCoefRight = coefRight;
+ pCoefLeft = coefLeft;
+
+ window_start = 0;
+ tot_sfb = 0;
+
+ coef_per_win = pFrameInfo->coef_per_win[0];
+
+ sfb_per_win = pFrameInfo->sfb_per_win[0];
+
+ DO
+
+ pBand = pFrameInfo->win_sfb_top[window_start];
+
+ partition = *(pGroup);
+
+ pGroup = pGroup + 1;
+
+ band_start = 0;
+
+ wins_in_group = (partition - window_start);
+
+ FOR (sfb = sfb_per_win; sfb > 0; sfb--)
+
+ band_stop = *(pBand);
+
+ pBand = pBand + 1;
+
+ codebook = *(pCodebookMap);
+
+ pCodebookMap = pCodebookMap + 1;
+
+ mask_enabled = *(pMaskMap);
+
+ pMaskMap = pMaskMap + 1;
+
+ IF (codebook < NOISE_HCB)
+ THEN
+ IF (mask_enabled != FALSE)
+ THEN
+ band_length = band_stop - band_start;
+
+ CALL
+ ms_synt(
+ wins_in_group,
+ coef_per_win,
+ sfb_per_win,
+ band_length,
+ &(pCoefLeft[band_start]),
+ &(pCoefRight[band_start]),
+ &(q_formatLeft[tot_sfb]),
+ &(q_formatRight[tot_sfb]) );
+
+ MODIFYING
+ &(pCoefLeft[band_start]),
+ &(pCoefRight[band_start]),
+ &(q_formatLeft[tot_sfb]),
+ &(q_formatRight[tot_sfb])
+
+ RETURNING
+ None
+ ENDIF
+ ENDIF
+ band_start = band_stop;
+
+ tot_sfb = tot_sfb + 1;
+
+ ENDFOR
+
+ pCoefRight = pCoefRight + coef_per_win * wins_in_group;
+ pCoefLeft = pCoefLeft + coef_per_win * wins_in_group;
+
+ wins_in_group = wins_in_group - 1;
+
+ tot_sfb = tot_sfb + sfb_per_win * wins_in_group;
+
+ window_start = partition;
+
+ WHILE (partition < pFrameInfo->num_win);
+
+ return;
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "apply_ms_synt.h"
+#include "e_huffmanconst.h"
+#include "ms_synt.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void apply_ms_synt(
+ const FrameInfo * const pFrameInfo,
+ const Int group[],
+ const Bool mask_map[],
+ const Int codebook_map[],
+ Int32 coefLeft[],
+ Int32 coefRight[],
+ Int q_formatLeft[MAXBANDS],
+ Int q_formatRight[MAXBANDS])
+
+{
+
+ Int32 *pCoefRight;
+
+ Int32 *pCoefLeft;
+
+ Int tot_sfb;
+ Int sfb;
+
+ Int band_length;
+ Int band_start;
+ Int band_stop;
+ Int coef_per_win;
+
+ Int codebook;
+ Int partition;
+ Int window_start;
+
+ Int sfb_per_win;
+ Int wins_in_group;
+
+ const Int16 *pBand;
+ const Int *pCodebookMap = codebook_map;
+ const Int *pGroup = group;
+ const Bool *pMaskMap = mask_map;
+
+ Bool mask_enabled;
+
+ pCoefRight = coefRight;
+ pCoefLeft = coefLeft;
+
+ window_start = 0;
+ tot_sfb = 0;
+
+ /*
+ * Each window in the frame should have the same number of coef's,
+ * so coef_per_win is constant in all the loops
+ */
+ coef_per_win = pFrameInfo->coef_per_win[0];
+
+ /*
+ * Because the number of scalefactor bands per window should be
+ * constant for each frame, sfb_per_win can be determined outside
+ * of the loop.
+ *
+ * For 44.1 kHz sampling rate sfb_per_win = 14 for short windows
+ * sfb_per_win = 49 for long windows
+ */
+
+ sfb_per_win = pFrameInfo->sfb_per_win[0];
+
+ do
+ {
+ pBand = pFrameInfo->win_sfb_top[window_start];
+
+ /*
+ * Partition is equal to the first window in the next group
+ *
+ * { Group 0 }{ Group 1 }{ Group 2 }{Group 3}
+ * [win 0][win 1][win 2][win 3][win 4][win 5][win 6][win 7]
+ *
+ * pGroup[0] = 2
+ * pGroup[1] = 5
+ * pGroup[2] = 7
+ * pGroup[3] = 8
+ */
+
+ partition = *(pGroup++);
+
+ band_start = 0;
+
+ wins_in_group = (partition - window_start);
+
+ for (sfb = sfb_per_win; sfb > 0; sfb--)
+ {
+ /* band is offset table, band_stop is last coef in band */
+ band_stop = *(pBand++);
+
+ codebook = *(pCodebookMap++);
+
+ mask_enabled = *(pMaskMap++);
+
+ /*
+ * When a codebook < NOISE_HCB is found, apply M/S to that
+ * scalefactorband.
+ *
+ * Example... sfb[3] == NOISE_HCB
+ *
+ * [ Group 1 ]
+ * [win 0 ][win 1 ]
+ * [0][1][2][X][4][5][6][7][0][1][2][X][4][5][6][7]
+ *
+ * The for(sfb) steps through the sfb's 0-7 in win 0.
+ *
+ * Finding sfb[3]'s codebook == NOISE_HCB, the code
+ * steps through all the windows in the group (they share
+ * the same scalefactors) and replaces that sfb with noise.
+ */
+
+ if (codebook < NOISE_HCB)
+ {
+ if (mask_enabled != FALSE)
+ {
+ band_length = band_stop - band_start;
+
+ ms_synt(
+ wins_in_group,
+ coef_per_win,
+ sfb_per_win,
+ band_length,
+ &(pCoefLeft[band_start]),
+ &(pCoefRight[band_start]),
+ &(q_formatLeft[tot_sfb]),
+ &(q_formatRight[tot_sfb]));
+ }
+ }
+ band_start = band_stop;
+
+ tot_sfb++;
+
+ } /* for (sfb) */
+
+ /*
+ * Increment pCoefRight and pCoefLeft by
+ * coef_per_win * the number of windows
+ */
+
+ pCoefRight += coef_per_win * wins_in_group;
+ pCoefLeft += coef_per_win * wins_in_group--;
+
+ /*
+ * Increase tot_sfb by sfb_per_win times the number of windows minus 1.
+ * The minus 1 comes from the fact that tot_sfb is already pointing
+ * to the first sfb in the 2nd window of the group.
+ */
+ tot_sfb += sfb_per_win * wins_in_group;
+
+ window_start = partition;
+
+ }
+ while (partition < pFrameInfo->num_win);
+
+ /* pFrameInfo->num_win = 1 for long windows, 8 for short_windows */
+
+ return;
+
+} /* apply_ms_synt() */
+
+
diff --git a/media/libstagefright/codecs/aacdec/apply_ms_synt.h b/media/libstagefright/codecs/aacdec/apply_ms_synt.h
new file mode 100644
index 0000000..ed7fb7a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/apply_ms_synt.h
@@ -0,0 +1,94 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/apply_ms_synt.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes the function declaration for apply_ms_synt().
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef APPLY_MS_SYNT_H
+#define APPLY_MS_SYNT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_frameinfo.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void apply_ms_synt(
+ const FrameInfo * const pFrameInfo,
+ const Int group[],
+ const Bool mask_map[],
+ const Int codebook_map[],
+ Int32 coefLeft[],
+ Int32 coefRight[],
+ Int q_formatLeft[MAXBANDS],
+ Int q_formatRight[MAXBANDS]);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/apply_tns.cpp b/media/libstagefright/codecs/aacdec/apply_tns.cpp
new file mode 100644
index 0000000..96ecd27
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/apply_tns.cpp
@@ -0,0 +1,424 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: apply_tns.c
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ coef = Array of input coefficients.
+ [Int32 *, length 1024]
+
+ q_format = Array of q-formats, one per scalefactor band, for the
+ entire frame. In the case of tns_inv_filter, only the
+ first element is used, since the input to tns_inv_filter
+ is all of the same q-format.
+ [Int * const, length MAX_SFB]
+
+ pFrameInfo = Pointer to structure that holds information about each group.
+ (long block flag, number of windows, scalefactor bands
+ per group, etc.)
+ [const FrameInfo * const]
+
+ pTNS_frame_info = pointer to structure containing the details on each
+ TNS filter (order, filter coefficients,
+ coefficient res., etc.)
+ [TNS_frame_info * const]
+
+ inverse_flag = TRUE if inverse filter is to be applied.
+ FALSE if forward filter is to be applied.
+ [Bool]
+
+ scratch_Int_buffer = Pointer to scratch memory to store the
+ filter's state memory. Used by both
+ tns_inv_filter.
+ [Int *, length TNS_MAX_ORDER]
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ coef[] = TNS altered data.
+ q_format = q-formats in TNS scalefactor bands may be modified.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function applies either the TNS forward or TNS inverse filter, based
+ on inverse_flag being FALSE or TRUE, respectively.
+
+ For the TNS forward filter, the data fed into tns_ar_filter is normalized
+ all to the same q-format.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ The input, coef, should use all 32-bits, else the scaling by tns_ar_filter
+ may eliminate the data.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.6.8 (Temporal Noise Shaping)
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ NO PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_tns_frame_info.h"
+#include "s_tnsfilt.h"
+#include "s_frameinfo.h"
+#include "tns_inv_filter.h"
+#include "tns_ar_filter.h"
+#include "apply_tns.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void apply_tns(
+ Int32 coef[],
+ Int q_format[],
+ const FrameInfo * const pFrameInfo,
+ TNS_frame_info * const pTNS_frame_info,
+ const Bool inverse_flag,
+ Int32 scratch_Int_buffer[])
+{
+ Int num_tns_bands;
+ Int num_TNS_coef;
+
+ Int f;
+
+ Int tempInt;
+ Int tempInt2;
+
+ Int sfb_per_win;
+ Int sfbWidth;
+
+ Int coef_per_win;
+ Int min_q;
+ Int win;
+
+ Int32 *pCoef = coef;
+ Int32 *pTempCoef;
+
+ Int *pStartQformat = q_format;
+
+ Int *pQformat;
+ Int32 *pLpcCoef;
+
+ Int sfb_offset;
+
+ const Int16 *pWinSfbTop;
+
+ TNSfilt *pFilt;
+
+ coef_per_win = pFrameInfo->coef_per_win[0];
+ sfb_per_win = pFrameInfo->sfb_per_win[0];
+
+ win = 0;
+
+ pLpcCoef = pTNS_frame_info->lpc_coef;
+
+ pFilt = pTNS_frame_info->filt;
+
+ do
+ {
+ for (f = pTNS_frame_info->n_filt[win]; f > 0; f--)
+ {
+ /* Skip to the next filter if the order is 0 */
+ tempInt = pFilt->order;
+
+ if (tempInt > 0)
+ {
+ /*
+ * Do not call tns_ar_filter or tns_inv_filter
+ * if the difference
+ * between start_coef and stop_stop is <= 0.
+ *
+ */
+ num_TNS_coef = (pFilt->stop_coef - pFilt->start_coef);
+
+ if (num_TNS_coef > 0)
+ {
+ if (inverse_flag != FALSE)
+ {
+ tns_inv_filter(
+ &(pCoef[pFilt->start_coef]),
+ num_TNS_coef,
+ pFilt->direction,
+ pLpcCoef,
+ pFilt->q_lpc,
+ pFilt->order,
+ scratch_Int_buffer);
+ }
+ else
+ {
+ num_tns_bands = (pFilt->stop_band - pFilt->start_band);
+
+ /*
+ * pQformat is initialized only once.
+ *
+ * Here is how TNS is applied on scalefactor bands
+ *
+ * [0][1][2][3][4][5][6][7][8]
+ * | \
+ * start_band stop_band
+ *
+ * In this example, TNS would be applied to 8
+ * scalefactor bands, 0-7.
+ *
+ * pQformat is initially set to &(pStartQformat[8])
+ *
+ * 1st LOOP
+ * Entry: pQformat = &(pStartQformat[8])
+ *
+ * pQformat is pre-decremented 8 times in the
+ * search for min_q
+ *
+ * Exit: pQformat = &(pStartQformat[0])
+ *
+ * 2nd LOOP
+ * Entry: pQformat = &(pStartQformat[0])
+ *
+ * pQformat is post-incremented 8 times in the
+ * normalization of the data loop.
+ *
+ * Exit: pQformat = &(pStartQformat[8]
+ *
+ *
+ * shift_amt = tns_ar_filter(...)
+ *
+ * 3rd LOOP
+ * Entry: pQformat = &(pStartQformat[8])
+ *
+ * pQformat is pre-decremented 8 times in the
+ * adjustment of the q-format to min_q - shift_amt
+ *
+ * Exit: pQformat = &(pStartQformat[0])
+ *
+ */
+
+ pQformat =
+ &(pStartQformat[pFilt->stop_band]);
+
+ /*
+ * Scan the array of q-formats and find the minimum over
+ * the range where the filter is to be applied.
+ *
+ * At the end of this scan,
+ * pQformat = &(q-format[pFilt->start_band]);
+ *
+ */
+
+ min_q = INT16_MAX;
+
+ for (tempInt = num_tns_bands; tempInt > 0; tempInt--)
+ {
+ tempInt2 = *(--pQformat);
+
+ if (tempInt2 < min_q)
+ {
+ min_q = tempInt2;
+ }
+ } /* for(tempInt = num_bands; tempInt > 0; tempInt--)*/
+
+ /*
+ * Set up the pointers so we can index into coef[]
+ * on a scalefactor band basis.
+ */
+ tempInt = pFilt->start_band;
+
+ tempInt--;
+
+ /* Initialize sfb_offset and pWinSfbTop */
+ if (tempInt >= 0)
+ {
+ pWinSfbTop =
+ &(pFrameInfo->win_sfb_top[win][tempInt]);
+
+ sfb_offset = *(pWinSfbTop++);
+ }
+ else
+ {
+ pWinSfbTop = pFrameInfo->win_sfb_top[win];
+ sfb_offset = 0;
+ }
+
+ pTempCoef = pCoef + pFilt->start_coef;
+
+ /* Scale the data in the TNS bands to min_q q-format */
+ for (tempInt = num_tns_bands; tempInt > 0; tempInt--)
+ {
+ sfbWidth = *(pWinSfbTop++) - sfb_offset;
+
+ sfb_offset += sfbWidth;
+
+ tempInt2 = *(pQformat++) - min_q;
+
+ /*
+ * This should zero out the data in one scalefactor
+ * band if it is so much less than the neighboring
+ * scalefactor bands.
+ *
+ * The only way this "should" happen is if one
+ * scalefactor band contains zero data.
+ *
+ * Zero data can be of any q-format, but we always
+ * set it very high to avoid the zero-data band being
+ * picked as the one to normalize to in the scan for
+ * min_q.
+ *
+ */
+ if (tempInt2 > 31)
+ {
+ tempInt2 = 31;
+ }
+
+ for (sfbWidth >>= 2; sfbWidth > 0; sfbWidth--)
+ {
+ *(pTempCoef++) >>= tempInt2;
+ *(pTempCoef++) >>= tempInt2;
+ *(pTempCoef++) >>= tempInt2;
+ *(pTempCoef++) >>= tempInt2;
+ }
+
+ } /* for(tempInt = num_bands; tempInt > 0; tempInt--)*/
+
+ tempInt2 =
+ tns_ar_filter(
+ &(pCoef[pFilt->start_coef]),
+ num_TNS_coef,
+ pFilt->direction,
+ pLpcCoef,
+ pFilt->q_lpc,
+ pFilt->order);
+
+ /*
+ * Update the q-format for all the scalefactor bands
+ * taking into account the adjustment caused by
+ * tns_ar_filter
+ */
+
+ min_q -= tempInt2;
+
+ for (tempInt = num_tns_bands; tempInt > 0; tempInt--)
+ {
+ *(--pQformat) = min_q;
+ }
+
+ } /* if (inverse_flag != FALSE) */
+
+ } /* if (num_TNS_coef > 0) */
+
+ pLpcCoef += pFilt->order;
+
+ } /* if (tempInt > 0) */
+
+ pFilt++;
+
+ } /* for (f = pTNSinfo->n_filt; f > 0; f--) */
+
+ pCoef += coef_per_win;
+ pStartQformat += sfb_per_win;
+
+ win++;
+
+ }
+ while (win < pFrameInfo->num_win);
+
+ return;
+
+} /* apply_tns() */
diff --git a/media/libstagefright/codecs/aacdec/apply_tns.h b/media/libstagefright/codecs/aacdec/apply_tns.h
new file mode 100644
index 0000000..85fb851
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/apply_tns.h
@@ -0,0 +1,113 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/apply_tns.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated per review comments.
+
+ Description: Changed function prototype to mirror changes made in apply_tns.c
+
+ Description: The scratch memory was mistakenly declared here as type "Int32"
+ It should have been "Int"
+
+ Who: Date:
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file contains the function declaration for
+ apply_tns.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef APPLY_TNS_H
+#define APPLY_TNS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_tns_frame_info.h"
+#include "s_frameinfo.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void apply_tns(
+ Int32 coef[],
+ Int q_format[],
+ const FrameInfo * const pFrameInfo,
+ TNS_frame_info * const pTNS_frame_info,
+ const Bool inverse_flag,
+ Int32 scratch_Int_buffer[]);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/bit_reversal_swap.h b/media/libstagefright/codecs/aacdec/bit_reversal_swap.h
new file mode 100644
index 0000000..2669f87
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/bit_reversal_swap.h
@@ -0,0 +1,93 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+ Pathname: ./include/bit_reversal_swap.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed definitions from Int to Int32 for Data[]
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for function bit_reversal_swap()
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef BIT_REVERSAL_SWAP_H
+#define BIT_REVERSAL_SWAP_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+extern const Int Index_64_a[];
+extern const Int Index_64_b[];
+
+extern const Int Index_512_a[];
+extern const Int Index_512_b[];
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+void bit_reversal_swap(
+ Int32 Data[],
+ const Int *pIndex_a,
+ const Int *pIndex_b);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* BIT_REVERSAL_SWAP_H */
diff --git a/media/libstagefright/codecs/aacdec/buf_getbits.cpp b/media/libstagefright/codecs/aacdec/buf_getbits.cpp
new file mode 100644
index 0000000..34f4f60
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/buf_getbits.cpp
@@ -0,0 +1,167 @@
+/* ------------------------------------------------------------------
+ * 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: buf_getbits.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Arguments: hBitBuf Handle to Bitbuffer
+ n Number of bits to read
+
+ Return: bits
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Reads n bits from Bitbuffer
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#include "buf_getbits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+UInt32 buf_getbits(BIT_BUFFER * hBitBuf, Int32 n)
+{
+
+ /* read bits from MSB side */
+ if (hBitBuf->buffered_bits <= 16)
+ {
+ hBitBuf->buffer_word = (hBitBuf->buffer_word << 16) | (*(hBitBuf->char_ptr++) << 8);
+ hBitBuf->buffer_word |= *(hBitBuf->char_ptr++);
+ hBitBuf->buffered_bits += 16;
+ }
+
+ hBitBuf->buffered_bits -= n;
+ hBitBuf->nrBitsRead += n;
+
+ return ((hBitBuf->buffer_word >> hBitBuf->buffered_bits) & ((1 << n) - 1));
+
+}
+
+
+UInt32 buf_get_1bit(BIT_BUFFER * hBitBuf)
+{
+
+ /* read bits from MSB side */
+ if (hBitBuf->buffered_bits <= 16)
+ {
+ hBitBuf->buffer_word = (hBitBuf->buffer_word << 16) | (*(hBitBuf->char_ptr++) << 8);
+ hBitBuf->buffer_word |= *(hBitBuf->char_ptr++);
+ hBitBuf->buffered_bits += 16;
+ }
+
+ hBitBuf->buffered_bits--;
+ hBitBuf->nrBitsRead++;
+
+ return ((hBitBuf->buffer_word >> hBitBuf->buffered_bits) & 1);
+
+}
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/buf_getbits.h b/media/libstagefright/codecs/aacdec/buf_getbits.h
new file mode 100644
index 0000000..1b5d252
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/buf_getbits.h
@@ -0,0 +1,94 @@
+/* ------------------------------------------------------------------
+ * 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: buf_getbits.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef BUF_GETBITS_H
+#define BUF_GETBITS_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "s_bit_buffer.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ UInt32 buf_getbits(BIT_BUFFER * hBitBuf, Int32 n);
+
+ UInt32 buf_get_1bit(BIT_BUFFER * hBitBuf);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/buffer_normalization.h b/media/libstagefright/codecs/aacdec/buffer_normalization.h
new file mode 100644
index 0000000..031216a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/buffer_normalization.h
@@ -0,0 +1,93 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/buffer_normalization.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed definitions from Int to Int32 for IO_buffer[]
+
+ Description: Added copyrigth notice, added 'const' definitions to function
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for function buffer_normalization()
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef BUFFER_NORMALIZATION_H
+#define BUFFER_NORMALIZATION_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define ALL_ZEROS_BUFFER -100
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+void buffer_normalization(
+ Int q_format,
+ Int32 IO_buffer[],
+ const Int buffer_size,
+ Int * const pExp);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* BUFFER_NORMALIZATION_H */
diff --git a/media/libstagefright/codecs/aacdec/byte_align.cpp b/media/libstagefright/codecs/aacdec/byte_align.cpp
new file mode 100644
index 0000000..e75c79e
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/byte_align.cpp
@@ -0,0 +1,179 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pInputStream = pointer to a BITS structure that holds information
+ regarding the input stream.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ pInputStream->usedBits is rounded up to a number that represents the next
+ byte boundary.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Makes the input stream structure pointed to align to the next byte boundary.
+ If it is already at a byte boundary it is left alone.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function shall not use global or static variables.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void byte_align(
+ BITS *pInputStream)
+
+ MODIFYING(pInputStream->usedBits = pInputStream->usedBits +
+ (pInputStream->usedBits + 7) % 8)
+
+ RETURN(nothing)
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+
+ STACK USAGE:
+
+ where:
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES:
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+
+
+#include "pv_audio_type_defs.h"
+#include "s_bits.h"
+#include "ibstream.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*
+ * A negative number was used for this mask so that it works on both
+ * 16-bit or 32-bit machines. The mask must be cast to unsigned int to
+ * work with TI compiler, ver 1.80.
+ */
+#define BYTE_ALIGN_MASK ((UInt)(-8))
+
+#define BYTE_ALIGN_ROUNDUP 7
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void byte_align(
+ BITS *pInputStream)
+{
+ /*
+ * Round up to the next byte by adding 7 and masking off with
+ * FFF8 or FFFFFFF8. The masking operation is a faster way to
+ * perform modulo arithmetic if the number is a power of 2.
+ *
+ * This code is the same as
+ * pInputStream->usedBits += (pInputStream->usedBits + 7) % 8
+ */
+ pInputStream->usedBits += BYTE_ALIGN_ROUNDUP;
+ pInputStream->usedBits &= BYTE_ALIGN_MASK;
+
+ return;
+}
+
diff --git a/media/libstagefright/codecs/aacdec/calc_auto_corr.cpp b/media/libstagefright/codecs/aacdec/calc_auto_corr.cpp
new file mode 100644
index 0000000..ee32398
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/calc_auto_corr.cpp
@@ -0,0 +1,416 @@
+/* ------------------------------------------------------------------
+ * 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: calc_auto_corr.c
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#ifdef AAC_PLUS
+
+
+#include "calc_auto_corr.h"
+#include "aac_mem_funcs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#include "fxp_mul32.h"
+#include "pv_normalize.h"
+
+#define N 2
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+void calc_auto_corr_LC(struct ACORR_COEFS *ac,
+ Int32 realBuf[][32],
+ Int32 bd,
+ Int32 len)
+{
+ Int32 j;
+ Int32 temp1;
+ Int32 temp3;
+ Int32 temp5;
+
+ int64_t temp_r01r;
+ int64_t temp_r02r;
+ int64_t temp_r11r;
+ int64_t temp_r12r;
+ int64_t temp_r22r;
+ int64_t max = 0;
+
+
+ temp1 = (realBuf[ 0][bd]) >> N;
+ temp3 = (realBuf[-1][bd]) >> N;
+ temp5 = (realBuf[-2][bd]) >> N;
+
+
+ temp_r11r = fxp_mac64_Q31(0, temp3, temp3); /* [j-1]*[j-1] */
+ temp_r12r = fxp_mac64_Q31(0, temp3, temp5); /* [j-1]*[j-2] */
+ temp_r22r = fxp_mac64_Q31(0, temp5, temp5); /* [j-2]*[j-2] */
+
+ temp_r01r = 0;
+ temp_r02r = 0;
+
+ for (j = 1; j < len; j++)
+ {
+ temp_r01r = fxp_mac64_Q31(temp_r01r, temp1, temp3); /* [j ]*[j-1] */
+ temp_r02r = fxp_mac64_Q31(temp_r02r, temp1, temp5); /* [j ]*[j-2] */
+ temp_r11r = fxp_mac64_Q31(temp_r11r, temp1, temp1); /* [j-1]*[j-1] */
+
+ temp5 = temp3;
+ temp3 = temp1;
+ temp1 = (realBuf[j][bd]) >> N;
+ }
+
+
+ temp_r22r += temp_r11r;
+ temp_r12r += temp_r01r; /* [j-1]*[j-2] */
+
+ temp_r22r = fxp_mac64_Q31(temp_r22r, -temp3, temp3);
+
+ temp_r01r = fxp_mac64_Q31(temp_r01r, temp1, temp3);
+ temp_r02r = fxp_mac64_Q31(temp_r02r, temp1, temp5);
+
+ max |= temp_r01r ^(temp_r01r >> 63);
+ max |= temp_r02r ^(temp_r02r >> 63);
+ max |= temp_r11r;
+ max |= temp_r12r ^(temp_r12r >> 63);
+ max |= temp_r22r;
+
+ if (max)
+ {
+ temp1 = (UInt32)(max >> 32);
+ if (temp1)
+ {
+ temp3 = 33 - pv_normalize(temp1);
+ ac->r01r = (Int32)(temp_r01r >> temp3);
+ ac->r02r = (Int32)(temp_r02r >> temp3);
+ ac->r11r = (Int32)(temp_r11r >> temp3);
+ ac->r12r = (Int32)(temp_r12r >> temp3);
+ ac->r22r = (Int32)(temp_r22r >> temp3);
+
+ }
+ else
+ {
+ temp3 = pv_normalize(((UInt32)max) >> 1) - 2;
+
+ if (temp3 > 0)
+ {
+ ac->r01r = (Int32)(temp_r01r << temp3);
+ ac->r02r = (Int32)(temp_r02r << temp3);
+ ac->r11r = (Int32)(temp_r11r << temp3);
+ ac->r12r = (Int32)(temp_r12r << temp3);
+ ac->r22r = (Int32)(temp_r22r << temp3);
+ }
+ else
+ {
+ temp3 = -temp3;
+ ac->r01r = (Int32)(temp_r01r >> temp3);
+ ac->r02r = (Int32)(temp_r02r >> temp3);
+ ac->r11r = (Int32)(temp_r11r >> temp3);
+ ac->r12r = (Int32)(temp_r12r >> temp3);
+ ac->r22r = (Int32)(temp_r22r >> temp3);
+ }
+
+ }
+
+ /*
+ * ac->det = ac->r11r*ac->r22r - rel*(ac->r12r*ac->r12r);
+ */
+ /* 1/(1 + 1e-6) == 1 - 1e-6 */
+ /* 2^-20 == 1e-6 */
+ ac->det = fxp_mul32_Q30(ac->r12r, ac->r12r);
+
+ ac->det -= ac->det >> 20;
+
+ ac->det = fxp_mul32_Q30(ac->r11r, ac->r22r) - ac->det;
+ }
+ else
+ {
+ pv_memset((void *)ac, 0, sizeof(struct ACORR_COEFS));
+ }
+
+
+}
+
+
+#ifdef HQ_SBR
+
+
+void calc_auto_corr(struct ACORR_COEFS *ac,
+ Int32 realBuf[][32],
+ Int32 imagBuf[][32],
+ Int32 bd,
+ Int32 len)
+{
+
+
+ Int32 j;
+ Int32 temp1;
+ Int32 temp2;
+ Int32 temp3;
+ Int32 temp4;
+ Int32 temp5;
+ Int32 temp6;
+
+ int64_t accu1 = 0;
+ int64_t accu2 = 0;
+ int64_t accu3 = 0;
+ int64_t accu4 = 0;
+ int64_t accu5 = 0;
+
+
+ int64_t temp_r12r;
+ int64_t temp_r12i;
+ int64_t temp_r22r;
+ int64_t max = 0;
+
+
+ temp1 = realBuf[0 ][bd] >> N;
+ temp2 = imagBuf[0 ][bd] >> N;
+ temp3 = realBuf[0-1][bd] >> N;
+ temp4 = imagBuf[0-1][bd] >> N;
+ temp5 = realBuf[0-2][bd] >> N;
+ temp6 = imagBuf[0-2][bd] >> N;
+
+ temp_r22r = fxp_mac64_Q31(0, temp5, temp5);
+ temp_r22r = fxp_mac64_Q31(temp_r22r, temp6, temp6);
+ temp_r12r = fxp_mac64_Q31(0, temp3, temp5);
+ temp_r12r = fxp_mac64_Q31(temp_r12r, temp4, temp6);
+ temp_r12i = -fxp_mac64_Q31(0, temp3, temp6);
+ temp_r12i = fxp_mac64_Q31(temp_r12i, temp4, temp5);
+
+ for (j = 1; j < len; j++)
+ {
+ accu1 = fxp_mac64_Q31(accu1, temp3, temp3);
+ accu1 = fxp_mac64_Q31(accu1, temp4, temp4);
+ accu2 = fxp_mac64_Q31(accu2, temp1, temp3);
+ accu2 = fxp_mac64_Q31(accu2, temp2, temp4);
+ accu3 = fxp_mac64_Q31(accu3, temp2, temp3);
+ accu3 = fxp_mac64_Q31(accu3, -temp1, temp4);
+ accu4 = fxp_mac64_Q31(accu4, temp1, temp5);
+ accu4 = fxp_mac64_Q31(accu4, temp2, temp6);
+ accu5 = fxp_mac64_Q31(accu5, temp2, temp5);
+ accu5 = fxp_mac64_Q31(accu5, -temp1, temp6);
+
+ temp5 = temp3;
+ temp6 = temp4;
+ temp3 = temp1;
+ temp4 = temp2;
+ temp1 = realBuf[j][bd] >> N;
+ temp2 = imagBuf[j][bd] >> N;
+ }
+
+
+ temp_r22r += accu1;
+ temp_r12r += accu2;
+ temp_r12i += accu3;
+
+
+ accu1 = fxp_mac64_Q31(accu1, temp3, temp3);
+ accu1 = fxp_mac64_Q31(accu1, temp4, temp4);
+ accu2 = fxp_mac64_Q31(accu2, temp1, temp3);
+ accu2 = fxp_mac64_Q31(accu2, temp2, temp4);
+ accu3 = fxp_mac64_Q31(accu3, temp2, temp3);
+ accu3 = fxp_mac64_Q31(accu3, -temp1, temp4);
+ accu4 = fxp_mac64_Q31(accu4, temp1, temp5);
+ accu4 = fxp_mac64_Q31(accu4, temp2, temp6);
+ accu5 = fxp_mac64_Q31(accu5, temp2, temp5);
+ accu5 = fxp_mac64_Q31(accu5, -temp1, temp6);
+
+
+ max |= accu5 ^(accu5 >> 63);
+ max |= accu4 ^(accu4 >> 63);
+ max |= accu3 ^(accu3 >> 63);
+ max |= accu2 ^(accu2 >> 63);
+ max |= accu1;
+ max |= temp_r12r ^(temp_r12r >> 63);
+ max |= temp_r12i ^(temp_r12i >> 63);
+ max |= temp_r22r;
+
+ if (max)
+ {
+
+ temp1 = (UInt32)(max >> 32);
+ if (temp1)
+ {
+ temp1 = 34 - pv_normalize(temp1);
+ ac->r11r = (Int32)(accu1 >> temp1);
+ ac->r01r = (Int32)(accu2 >> temp1);
+ ac->r01i = (Int32)(accu3 >> temp1);
+ ac->r02r = (Int32)(accu4 >> temp1);
+ ac->r02i = (Int32)(accu5 >> temp1);
+ ac->r12r = (Int32)(temp_r12r >> temp1);
+ ac->r12i = (Int32)(temp_r12i >> temp1);
+ ac->r22r = (Int32)(temp_r22r >> temp1);
+ }
+ else
+ {
+ temp1 = pv_normalize(((UInt32)max) >> 1) - 3;
+
+ if (temp1 > 0)
+ {
+ ac->r11r = (Int32)(accu1 << temp1);
+ ac->r01r = (Int32)(accu2 << temp1);
+ ac->r01i = (Int32)(accu3 << temp1);
+ ac->r02r = (Int32)(accu4 << temp1);
+ ac->r02i = (Int32)(accu5 << temp1);
+ ac->r12r = (Int32)(temp_r12r << temp1);
+ ac->r12i = (Int32)(temp_r12i << temp1);
+ ac->r22r = (Int32)(temp_r22r << temp1);
+ }
+ else
+ {
+ temp1 = -temp1;
+ ac->r11r = (Int32)(accu1 >> temp1);
+ ac->r01r = (Int32)(accu2 >> temp1);
+ ac->r01i = (Int32)(accu3 >> temp1);
+ ac->r02r = (Int32)(accu4 >> temp1);
+ ac->r02i = (Int32)(accu5 >> temp1);
+ ac->r12r = (Int32)(temp_r12r >> temp1);
+ ac->r12i = (Int32)(temp_r12i >> temp1);
+ ac->r22r = (Int32)(temp_r22r >> temp1);
+ }
+
+ }
+
+ /*
+ * ac->det = ac->r11r*ac->r22r - rel*(ac->r12r*ac->r12r);
+ */
+ /* 1/(1 + 1e-6) == 1 - 1e-6 */
+ /* 2^-20 == 1e-6 */
+
+ ac->det = fxp_mul32_Q29(ac->r12i, ac->r12i);
+ ac->det = fxp_mac32_Q29(ac->r12r, ac->r12r, ac->det);
+
+ ac->det -= ac->det >> 20;
+
+ ac->det = -fxp_msu32_Q29(ac->r11r, ac->r22r, ac->det);
+
+ }
+ else
+ {
+ pv_memset((void *)ac, 0, sizeof(struct ACORR_COEFS));
+ }
+
+}
+
+#endif
+
+
+
+
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/calc_auto_corr.h b/media/libstagefright/codecs/aacdec/calc_auto_corr.h
new file mode 100644
index 0000000..0f0dae2
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/calc_auto_corr.h
@@ -0,0 +1,122 @@
+/* ------------------------------------------------------------------
+ * 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: calc_auto_corr.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+ ----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef CALC_AUTO_CORR_H
+#define CALC_AUTO_CORR_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+struct ACORR_COEFS
+{
+ Int32 r11r;
+ Int32 r01r;
+ Int32 r02r;
+ Int32 r12r;
+ Int32 r22r;
+#ifdef HQ_SBR
+ Int32 r01i;
+ Int32 r02i;
+ Int32 r12i;
+#endif
+ Int32 det;
+};
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void calc_auto_corr_LC(struct ACORR_COEFS *ac,
+ Int32 realBuf[][32],
+ Int32 bd,
+ Int32 len);
+
+
+#ifdef HQ_SBR
+
+ void calc_auto_corr(struct ACORR_COEFS *ac,
+ Int32 realBuf[][32],
+ Int32 imagBuf[][32],
+ Int32 bd,
+ Int32 len);
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/calc_gsfb_table.cpp b/media/libstagefright/codecs/aacdec/calc_gsfb_table.cpp
new file mode 100644
index 0000000..4047502
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/calc_gsfb_table.cpp
@@ -0,0 +1,267 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/calc_gsfb_table.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: (1) Modified to bring in-line with PV standards
+ (2) Removed if(pFrameInfo->islong), only short windows will
+ call this routine from getics.c
+
+ Description: Modified per review comments
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pFrameInfo = pointer to structure that holds information for current
+ frame. Data type FrameInfo
+
+ group[] = array that contains the grouping information of short
+ windows (stop index of windows in each group).
+ Data type Int
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ pFrameInfo -> frame_sfb_top contains the cumulative bandwidth of
+ scalefactor bands in each group
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function is only invoked when short windows are present. It calculates
+ the number of groups in one frame, and the scalefactor bandwidth of each
+ scalefactor band in each group.
+ All windows within one group share the same scalefactors and are interleaved
+ on a scalefactor band basis. Within each group, the actual length of one
+ scalefactor band equals to the number of windows times the number of
+ coefficients in a regular scalefactor band.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function shall replace the contents of pFrameInfo->frame_sfb_top
+ with the cumulative bandwidth of each scalefactor band in each group
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+ (2) ISO/IEC 14496-3: 1999(E)
+ Subpart 4 p54. 4.5.2.3.2 decoding process
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ offset = 0;
+ group_idx = 0;
+
+ DO
+ pFrameInfo->group_len[group_idx] = group[group_idx] - offset;
+ offset = group[group_idx];
+ group_idx++;
+
+ WHILE (offset < NUM_SHORT_WINDOWS);
+
+
+ pFrameInfo->num_groups = group_idx;
+
+ pFrameSfbTop = pFrameInfo->frame_sfb_top;
+ offset = 0;
+
+ FOR (group_idx = 0; group_idx < pFrameInfo->num_groups; group_idx++)
+
+ len = pFrameInfo->group_len[group_idx];
+
+ FOR (sfb = 0; sfb < pFrameInfo->sfb_per_win[group_idx]; sfb++)
+
+ offset += pFrameInfo->sfb_width_128[sfb] * len;
+ *pFrameSfbTop++ = offset;
+
+ ENDFOR
+
+ ENDFOR
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "huffman.h"
+#include "aac_mem_funcs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void calc_gsfb_table(
+ FrameInfo *pFrameInfo,
+ Int group[])
+{
+
+ Int group_idx;
+ Int offset;
+ Int *pFrameSfbTop;
+ Int *pSfbWidth128;
+ Int sfb;
+ Int nsfb;
+ Int len;
+ Int ngroups;
+
+ /* clear out the default values set by infoinit */
+ /* */
+ pv_memset(pFrameInfo->frame_sfb_top,
+ 0,
+ MAXBANDS*sizeof(pFrameInfo->frame_sfb_top[0]));
+ /* */
+ /* first calculate the group length*/
+ offset = 0;
+ ngroups = 0;
+ do
+ {
+ pFrameInfo->group_len[ngroups] = group[ngroups] - offset;
+ offset = group[ngroups];
+ ngroups++;
+
+ }
+ while (offset < NUM_SHORT_WINDOWS);
+
+
+ /* calculate the cumulative scalefactor bandwidth for one frame */
+ pFrameInfo->num_groups = ngroups;
+
+ pFrameSfbTop = pFrameInfo->frame_sfb_top;
+ offset = 0;
+
+
+ for (group_idx = 0; group_idx < ngroups; group_idx++)
+ {
+ len = pFrameInfo->group_len[ group_idx];
+ nsfb = pFrameInfo->sfb_per_win[group_idx];
+
+ pSfbWidth128 = pFrameInfo->sfb_width_128;
+
+ for (sfb = nsfb; sfb > 0; sfb--)
+ {
+ offset += *pSfbWidth128++ * len;
+ *pFrameSfbTop++ = offset;
+ }
+ }
+
+
+} /* calc_gsfb_table */
+
diff --git a/media/libstagefright/codecs/aacdec/calc_sbr_anafilterbank.cpp b/media/libstagefright/codecs/aacdec/calc_sbr_anafilterbank.cpp
new file mode 100644
index 0000000..5ec3f69
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/calc_sbr_anafilterbank.cpp
@@ -0,0 +1,360 @@
+/* ------------------------------------------------------------------
+ * 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: calc_sbr_anafilterbank.c
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "calc_sbr_anafilterbank.h"
+#include "qmf_filterbank_coeff.h"
+#include "analysis_sub_band.h"
+
+#include "aac_mem_funcs.h"
+#include "fxp_mul32.h"
+
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void calc_sbr_anafilterbank_LC(Int32 * Sr,
+ Int16 * X,
+ Int32 scratch_mem[][64],
+ Int32 maxBand)
+{
+
+ Int i;
+ Int32 *p_Y_1;
+ Int32 *p_Y_2;
+
+ Int16 * pt_X_1;
+ Int16 * pt_X_2;
+ Int32 realAccu1;
+ Int32 realAccu2;
+
+ Int32 tmp1;
+ Int32 tmp2;
+
+
+ const Int32 * pt_C;
+
+ p_Y_1 = scratch_mem[0];
+
+
+ p_Y_2 = p_Y_1 + 63;
+ pt_C = &sbrDecoderFilterbankCoefficients_an_filt_LC[0];
+
+ pt_X_1 = X;
+
+
+ realAccu1 = fxp_mul32_by_16(Qfmt27(-0.51075594183097F), pt_X_1[-192]);
+
+ realAccu1 = fxp_mac32_by_16(Qfmt27(-0.51075594183097F), -pt_X_1[-128], realAccu1);
+ realAccu1 = fxp_mac32_by_16(Qfmt27(-0.01876919066980F), pt_X_1[-256], realAccu1);
+ *(p_Y_1++) = fxp_mac32_by_16(Qfmt27(-0.01876919066980F), -pt_X_1[ -64], realAccu1);
+
+
+ /* create array Y */
+
+ pt_X_1 = &X[-1];
+ pt_X_2 = &X[-319];
+
+
+ for (i = 15; i != 0; i--)
+ {
+ tmp1 = *(pt_X_1--);
+ tmp2 = *(pt_X_2++);
+
+ realAccu1 = fxp_mul32_by_16(*(pt_C), tmp1);
+ realAccu2 = fxp_mul32_by_16(*(pt_C++), tmp2);
+ tmp1 = pt_X_1[ -63];
+ tmp2 = pt_X_2[ +63];
+ realAccu1 = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ realAccu2 = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+ tmp1 = pt_X_1[ -127];
+ tmp2 = pt_X_2[ +127];
+ realAccu1 = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ realAccu2 = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+ tmp1 = pt_X_1[ -191];
+ tmp2 = pt_X_2[ +191];
+ realAccu1 = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ realAccu2 = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+ tmp1 = pt_X_1[ -255];
+ tmp2 = pt_X_2[ +255];
+ *(p_Y_1++) = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ *(p_Y_2--) = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+
+ tmp1 = *(pt_X_1--);
+ tmp2 = *(pt_X_2++);
+ realAccu1 = fxp_mul32_by_16(*(pt_C), tmp1);
+ realAccu2 = fxp_mul32_by_16(*(pt_C++), tmp2);
+
+ tmp1 = pt_X_1[ -63];
+ tmp2 = pt_X_2[ +63];
+ realAccu1 = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ realAccu2 = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+ tmp1 = pt_X_1[ -127];
+ tmp2 = pt_X_2[ +127];
+ realAccu1 = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ realAccu2 = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+ tmp1 = pt_X_1[ -191];
+ tmp2 = pt_X_2[ +191];
+ realAccu1 = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ realAccu2 = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+ tmp1 = pt_X_1[ -255];
+ tmp2 = pt_X_2[ +255];
+ *(p_Y_1++) = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ *(p_Y_2--) = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+
+ }
+
+
+ tmp1 = *(pt_X_1--);
+ tmp2 = *(pt_X_2++);
+ realAccu1 = fxp_mul32_by_16(*(pt_C), tmp1);
+ realAccu2 = fxp_mul32_by_16(*(pt_C++), tmp2);
+
+ tmp1 = pt_X_1[ -63];
+ tmp2 = pt_X_2[ +63];
+ realAccu1 = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ realAccu2 = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+ tmp1 = pt_X_1[ -127];
+ tmp2 = pt_X_2[ +127];
+ realAccu1 = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ realAccu2 = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+ tmp1 = pt_X_1[ -191];
+ tmp2 = pt_X_2[ +191];
+ realAccu1 = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ realAccu2 = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+ tmp1 = pt_X_1[ -255];
+ tmp2 = pt_X_2[ +255];
+ *(p_Y_1++) = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ *(p_Y_2--) = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+
+
+ pt_X_1 = X;
+
+ realAccu2 = fxp_mul32_by_16(Qfmt27(0.00370548843500F), X[ -32]);
+
+ realAccu2 = fxp_mac32_by_16(Qfmt27(0.00370548843500F), pt_X_1[-288], realAccu2);
+ realAccu2 = fxp_mac32_by_16(Qfmt27(0.09949460091720F), pt_X_1[ -96], realAccu2);
+ realAccu2 = fxp_mac32_by_16(Qfmt27(0.09949460091720F), pt_X_1[-224], realAccu2);
+ *(p_Y_1++) = fxp_mac32_by_16(Qfmt27(1.20736865027288F), pt_X_1[-160], realAccu2);
+
+
+ analysis_sub_band_LC(scratch_mem[0],
+ Sr,
+ maxBand,
+ (Int32(*)[64])scratch_mem[1]);
+
+}
+
+
+
+#ifdef HQ_SBR
+
+void calc_sbr_anafilterbank(Int32 * Sr,
+ Int32 * Si,
+ Int16 * X,
+ Int32 scratch_mem[][64],
+ Int32 maxBand)
+{
+ Int i;
+ Int32 *p_Y_1;
+ Int32 *p_Y_2;
+
+
+
+
+ const Int32 * pt_C;
+ Int16 * pt_X_1;
+ Int16 * pt_X_2;
+ Int32 realAccu1;
+ Int32 realAccu2;
+
+ Int32 tmp1;
+ Int32 tmp2;
+
+
+ p_Y_1 = scratch_mem[0];
+
+
+ p_Y_2 = p_Y_1 + 63;
+ pt_C = &sbrDecoderFilterbankCoefficients_an_filt[0];
+
+ realAccu1 = fxp_mul32_by_16(Qfmt27(-0.36115899F), X[-192]);
+
+
+ realAccu1 = fxp_mac32_by_16(Qfmt27(-0.36115899F), -X[-128], realAccu1);
+ realAccu1 = fxp_mac32_by_16(Qfmt27(-0.013271822F), X[-256], realAccu1);
+ *(p_Y_1++) = fxp_mac32_by_16(Qfmt27(-0.013271822F), -X[ -64], realAccu1);
+
+ /* create array Y */
+
+ pt_X_1 = &X[-1];
+ pt_X_2 = &X[-319];
+
+
+ for (i = 31; i != 0; i--)
+ {
+ tmp1 = *(pt_X_1--);
+ tmp2 = *(pt_X_2++);
+ realAccu1 = fxp_mul32_by_16(*(pt_C), tmp1);
+ realAccu2 = fxp_mul32_by_16(*(pt_C++), tmp2);
+ tmp1 = pt_X_1[ -63];
+ tmp2 = pt_X_2[ 63];
+ realAccu1 = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ realAccu2 = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+ tmp1 = pt_X_1[ -127];
+ tmp2 = pt_X_2[ 127];
+ realAccu1 = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ realAccu2 = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+ tmp1 = pt_X_1[ -191];
+ tmp2 = pt_X_2[ 191];
+ realAccu1 = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ realAccu2 = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+ tmp1 = pt_X_1[ -255];
+ tmp2 = pt_X_2[ 255];
+ *(p_Y_1++) = fxp_mac32_by_16(*(pt_C), tmp1, realAccu1);
+ *(p_Y_2--) = fxp_mac32_by_16(*(pt_C++), tmp2, realAccu2);
+ }
+
+
+ realAccu2 = fxp_mul32_by_16(Qfmt27(0.002620176F), X[ -32]);
+ realAccu2 = fxp_mac32_by_16(Qfmt27(0.002620176F), X[-288], realAccu2);
+ realAccu2 = fxp_mac32_by_16(Qfmt27(0.070353307F), X[ -96], realAccu2);
+ realAccu2 = fxp_mac32_by_16(Qfmt27(0.070353307F), X[-224], realAccu2);
+
+
+ *(p_Y_1++) = fxp_mac32_by_16(Qfmt27(0.85373856F), (X[-160]), realAccu2);
+
+
+ analysis_sub_band(scratch_mem[0],
+ Sr,
+ Si,
+ maxBand,
+ (Int32(*)[64])scratch_mem[1]);
+
+}
+
+
+#endif
+
+
+
+#endif /* AAC_PLUS */
+
diff --git a/media/libstagefright/codecs/aacdec/calc_sbr_anafilterbank.h b/media/libstagefright/codecs/aacdec/calc_sbr_anafilterbank.h
new file mode 100644
index 0000000..c93848e
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/calc_sbr_anafilterbank.h
@@ -0,0 +1,113 @@
+/* ------------------------------------------------------------------
+ * 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: calc_sbr_anafilterbank.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef CALC_SBR_ANAFILTERBANK_H
+#define CALC_SBR_ANAFILTERBANK_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+#define ROUND_ANAFIL 0
+//#define ROUND_ANAFIL 0
+#define ROUND_ANAFIL_LC (0)
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ void calc_sbr_anafilterbank_LC(Int32 * Sr,
+ Int16 * X,
+ Int32 scratch_mem[][64],
+ Int32 maxBand);
+
+
+#ifdef HQ_SBR
+
+ void calc_sbr_anafilterbank(Int32 * Sr,
+ Int32 * Si,
+ Int16 * X,
+ Int32 scratch_mem[][64],
+ Int32 maxBand);
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* CALC_SBR_ANAFILTERBANK_H */
diff --git a/media/libstagefright/codecs/aacdec/calc_sbr_envelope.cpp b/media/libstagefright/codecs/aacdec/calc_sbr_envelope.cpp
new file mode 100644
index 0000000..4fb3535
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/calc_sbr_envelope.cpp
@@ -0,0 +1,2203 @@
+/* ------------------------------------------------------------------
+ * 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: calc_sbr_envelope.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "calc_sbr_envelope.h"
+#include "sbr_envelope_calc_tbl.h"
+#include "sbr_create_limiter_bands.h"
+#include "aac_mem_funcs.h"
+
+#include "fxp_mul32.h"
+#include "pv_normalize.h"
+
+#include "sbr_aliasing_reduction.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#include "pv_sqrt.h"
+
+#include "pv_div.h"
+#include "fxp_mul32.h"
+#include "pv_normalize.h"
+
+#define Q30fmt(x) (Int32)(x*((Int32)1<<30) + (x>=0?0.5F:-0.5F))
+#define Q28fmt(x) (Int32)(x*((Int32)1<<28) + (x>=0?0.5F:-0.5F))
+#define Q15fmt(x) (Int32)(x*((Int32)1<<15) + (x>=0?0.5F:-0.5F))
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void envelope_application_LC(Int32 *aBufR,
+ Int32 *nrg_gain_man,
+ Int32 *nrg_gain_exp,
+ Int32 *noise_level_man,
+ Int32 *noise_level_exp,
+ Int32 *nrg_tone_man,
+ Int32 *nrg_tone_exp,
+ Int32 band_nrg_tone_detector,
+ const Int32 *frame_info,
+ Int32 *harm_index,
+ Int32 *phase_index,
+ Int32 i,
+ Int32 lowSubband,
+ Int32 noSubbands,
+ Int32 noNoiseFlag);
+
+
+ void energy_estimation_LC(Int32 *aBufR,
+ Int32 *nrg_est_man,
+ Int32 *nrg_est_exp,
+ const Int32 *frame_info,
+ Int32 i,
+ Int32 k,
+ Int32 c,
+ Int32 ui2);
+
+#ifdef HQ_SBR
+
+
+ void envelope_application(Int32 *aBufR,
+ Int32 *aBufI,
+ Int32 *nrg_gain_man,
+ Int32 *nrg_gain_exp,
+ Int32 *noise_level_man,
+ Int32 *noise_level_exp,
+ Int32 *nrg_tone_man,
+ Int32 *nrg_tone_exp,
+ Int32 *fBuf_man[64],
+ Int32 *fBuf_exp[64],
+ Int32 *fBufN_man[64],
+ Int32 *fBufN_exp[64],
+ const Int32 *frame_info,
+ Int32 *harm_index,
+ Int32 *phase_index,
+ Int32 i,
+ Int32 lowSubband,
+ Int32 noSubbands,
+ Int32 noNoiseFlag,
+ Int32 band_nrg_tone_detector,
+ Int32 maxSmoothLength,
+ Int32 smooth_length);
+
+
+ void energy_estimation(Int32 *aBufR,
+ Int32 *aBufI,
+ Int32 *nrg_est_man,
+ Int32 *nrg_est_exp,
+ const Int32 *frame_info,
+ Int32 i,
+ Int32 k,
+ Int32 c,
+ Int32 ui2);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void calc_sbr_envelope(SBR_FRAME_DATA *frameData,
+ Int32 *aBufR,
+ Int32 *aBufI,
+ Int freqBandTable1[2][MAX_FREQ_COEFFS + 1],
+ const Int32 *nSfb,
+ Int32 freqBandTable2[MAX_NOISE_COEFFS + 1],
+ Int32 nNBands,
+ Int32 reset,
+ Int32 *degreeAlias,
+ Int32 *harm_index,
+ Int32 *phase_index,
+ Int32 hFp[64],
+ Int32 *sUp,
+ Int32 limSbc[][13],
+ Int32 *gateMode,
+#ifdef HQ_SBR
+ Int32 *fBuf_man[64],
+ Int32 *fBuf_exp[64],
+ Int32 *fBufN_man[64],
+ Int32 *fBufN_exp[64],
+#endif
+ Int32 scratch_mem[][64],
+ struct PATCH Patch,
+ Int32 sqrt_cache[][4],
+ Int32 LC_flag)
+{
+
+ Int32 c;
+ Int32 li;
+ Int32 ui;
+ Int32 i;
+ Int32 j;
+ Int32 k = 0;
+ Int32 l;
+ Int m = 0;
+ Int kk = 0;
+ Int o;
+ Int next = -1;
+ Int32 ui2;
+ Int flag;
+ Int noNoiseFlag;
+ Int *ptr;
+
+
+ UInt32 nrg = 0;
+ Int32 nrg_exp = 0;
+ struct intg_div quotient;
+ struct intg_sqrt root_sq;
+
+ Int32 aux1;
+
+ Int32 *nL_man = frameData->sbrNoiseFloorLevel_man;
+ Int32 *nL_exp = frameData->sbrNoiseFloorLevel_exp;
+
+ Int32 *sfb_nrg_man = frameData->iEnvelope_man;
+ Int32 *sfb_nrg_exp = frameData->iEnvelope_exp;
+
+ Int32 tmp_q1;
+ Int32 tmp_q2;
+
+ Int32 g_max_man;
+ Int32 g_max_exp;
+
+ Int32 p_ref_man;
+ Int32 p_ref_exp;
+
+ Int32 p_est_man;
+ Int32 p_est_exp;
+
+ Int32 p_adj_man;
+ Int32 p_adj_exp;
+ Int32 avg_gain;
+
+ Int32 boost_gain_q;
+
+ Int32 band_nrg_tone_detector;
+
+ Int32 *nrg_est_man = scratch_mem[0];
+ Int32 *nrg_est_exp = scratch_mem[1];
+ Int32 *nrg_ref_man = scratch_mem[2];
+ Int32 *nrg_ref_exp = scratch_mem[3];
+ Int32 *nrg_gain_man = scratch_mem[4];
+ Int32 *nrg_gain_exp = scratch_mem[5];
+ Int32 *noise_level_man = scratch_mem[6];
+ Int32 *noise_level_exp = scratch_mem[7];
+ Int32 *nrg_tone_man = scratch_mem[8];
+ Int32 *nrg_tone_exp = scratch_mem[9];
+ Int32 *hF = scratch_mem[10];
+
+
+
+ const Int32 *frame_info = frameData->frameInfo;
+ Int32 int_mode = frameData->sbr_header.interpolFreq;
+
+
+
+
+
+ Int32 dontUseTheseGainValues[64];
+
+#ifdef HQ_SBR
+
+ Int32 n;
+ Int32 smooth_length;
+ Int32 smoothingLength = frameData->sbr_header.smoothingLength;
+ Int32 maxSmoothLength = smoothLengths[0];
+
+#endif
+
+ Int32 limiterBand = frameData->sbr_header.limiterBands;
+ Int32 limiterGains = frameData->sbr_header.limiterGains;
+ Int32 *addHarmonics = frameData->addHarmonics;
+
+ Int32 lowSubband = freqBandTable1[LOW_RES][0];
+ Int32 noSubbands = freqBandTable1[LOW_RES][nSfb[LOW_RES]] - lowSubband;
+ Int32 nEnv = frame_info[0];
+ Int32 sEnv = frame_info[(nEnv + 1)<<1];
+
+ /* ensure that noSubbands in the range [0,64] */
+ noSubbands = (noSubbands >> 31) ^ noSubbands;
+ if (noSubbands > 64)
+ {
+ noSubbands = 64;
+ }
+
+ if (reset)
+ {
+ *sUp = 1;
+ *phase_index = 0;
+ sbr_create_limiter_bands(limSbc,
+ gateMode,
+ freqBandTable1[LOW_RES],
+ Patch,
+ nSfb[LOW_RES]);
+ }
+
+ /* Mapping. */
+ pv_memset((void*)hF, 0, (sizeof(*hF) << 6));
+
+ ptr = freqBandTable1[HI];
+ l = *(ptr++);
+
+ for (i = nSfb[HI]; i != 0; i--)
+ {
+ k = *(ptr++);
+ j = ((k + l) >> 1) - lowSubband;
+ l = k;
+ hF[j] = *(addHarmonics++);
+ }
+
+
+ /* Envelope adjustment. */
+
+ for (i = 0; i < nEnv; i++)
+ {
+
+ if (frame_info[1+i] == frame_info[(nEnv<<1)+4+kk])
+ {
+ kk++, next++;
+ }
+
+ noNoiseFlag = (i == sEnv || i == frameData->prevEnvIsShort) ? 1 : 0;
+
+#ifdef HQ_SBR
+ smooth_length = (noNoiseFlag ? 0 : smoothLengths[smoothingLength]);
+#endif
+
+
+ /* Estimate levels. */
+ c = 0;
+ o = 0;
+
+ band_nrg_tone_detector = 0;
+
+ Int kkkk = freqBandTable1[ frame_info[nEnv+2+i] ][0];
+
+ for (j = 0; j < nSfb[frame_info[nEnv+2+i]]; j++)
+ {
+ li = freqBandTable1[ frame_info[nEnv+2+i] ][j ];
+ ui = freqBandTable1[ frame_info[nEnv+2+i] ][j + 1];
+ flag = 0;
+
+ for (k = li; k < ui; k++)
+ { /* Calculate the average energy over the current envelope, */
+ ui2 = (frame_info[1+i] << 1);
+
+ if (LC_flag == ON)
+ {
+ energy_estimation_LC((Int32 *)aBufR,
+ nrg_est_man,
+ nrg_est_exp,
+ frame_info,
+ i,
+ k - kkkk,
+ c,
+ ui2);
+ }
+#ifdef HQ_SBR
+ else
+ {
+
+ energy_estimation((Int32 *)aBufR,
+ (Int32 *)aBufI,
+ nrg_est_man,
+ nrg_est_exp,
+ frame_info,
+ i,
+ k - kkkk,
+ c,
+ ui2);
+ }
+#endif
+
+ flag = (hF[c] && (i >= sEnv || hFp[c+lowSubband])) ? 1 : flag;
+ c++;
+ }
+
+
+ ui2 = freqBandTable2[o+1];
+
+ if (!int_mode)
+ { /* If no interpolation is used, */
+
+ tmp_q1 = -100;
+
+ for (k = c - (ui - li); k < c; k++)
+ {
+ if (tmp_q1 < nrg_est_exp[k])
+ {
+ tmp_q1 = nrg_est_exp[k];
+ }
+ }
+
+ nrg = 0;
+ for (k = c - (ui - li); k < c; k++)
+ { /* average the energy in all the QMF bands, */
+ nrg += nrg_est_man[k] >> (tmp_q1 - nrg_est_exp[k]); /* for the whole scalefactor band. */
+ }
+ nrg /= (ui - li);
+ nrg_exp = tmp_q1;
+
+ }
+
+ c -= (ui - li);
+
+ for (k = 0; k < ui - li; k++)
+ {
+ o = (k + li >= ui2) ? o + 1 : o;
+ ui2 = freqBandTable2[o+1];
+ /*
+ * If no interpolation is used, use the averaged energy from above,
+ * otherwise do nothing.
+ */
+
+
+ if (!int_mode)
+ {
+ nrg_est_man[c] = nrg;
+ nrg_est_exp[c] = nrg_exp;
+ }
+
+ if (LC_flag == ON)
+ {
+ nrg_est_exp[c] += 1;
+
+ if (flag)
+ {
+ dontUseTheseGainValues[k + li - lowSubband] = 1;
+ }
+ else
+ {
+ dontUseTheseGainValues[k + li - lowSubband] = 0;
+ }
+ }
+
+ nrg_ref_man[c] = sfb_nrg_man[m];
+ nrg_ref_exp[c] = sfb_nrg_exp[m];
+
+ /*
+ * compute nL/(1 + nL); where nL = nL_man*2^nL_exp
+ */
+ aux1 = next * nNBands + o;
+
+ tmp_q1 = nL_exp[aux1];
+
+ if (tmp_q1 >= 0)
+ {
+ pv_div(nL_man[aux1], nL_man[aux1] + (0x3FFFFFFF >> tmp_q1), &quotient);
+ }
+ else
+ {
+ tmp_q1 = nL_man[aux1] >> (-tmp_q1);
+ pv_div(tmp_q1, tmp_q1 + 0x3FFFFFFF, &quotient);
+ }
+
+ /*
+ * tmp_q1 = nL/(1 + nL)*nrg_ref[c];
+ */
+
+ tmp_q1 = fxp_mul32_Q30(quotient.quotient >> quotient.shift_factor, nrg_ref_man[c]);
+
+ if (flag)
+ {
+ /*
+ * Calculate levels and gain, dependent on whether a synthetic, a sine is present or not.
+ *
+ * nrg_gain[c]=(float)pv_sqrt( tmp/(nrg_est[c] + 1), sqrt_cache[1] );
+ */
+
+
+ pv_div(tmp_q1, nrg_est_man[c] + 1, &quotient);
+ /*
+ * nrg_est_man[c] is an integer number, while tmp_q1 and quotient.quotient
+ * are fractions in Q30
+ */
+
+ tmp_q2 = nrg_ref_exp[c] - nrg_est_exp[c] - quotient.shift_factor - 30;
+
+ pv_sqrt(quotient.quotient, tmp_q2, &root_sq, sqrt_cache[1]);
+ nrg_gain_man[c] = root_sq.root; /* in Q28 format */
+ nrg_gain_exp[c] = root_sq.shift_factor;
+
+
+ /*
+ * nrg_tone[c]=(float)( (hF[c] && (i >= sEnv || hFp[c+lowSubband])) ?
+ * pv_sqrt(nrg_ref[c]/(1+tmp_nL), sqrt_cache[2]) : 0);
+ */
+ if (hF[c] && (i >= sEnv || hFp[c+lowSubband]))
+ {
+ /*
+ * nrg_ref[c] and nL, as well as quotient.quotient
+ * are fractions in Q30
+ */
+
+ /* aux1 == next*nNBands + o */
+
+ tmp_q2 = nL_exp[aux1];
+ /*
+ * nrg_ref[c]/(1+tmp_nL)
+ */
+
+ if (tmp_q2 >= 0)
+ {
+ pv_div(nrg_ref_man[c], nL_man[aux1] + (0x3FFFFFFF >> tmp_q2), &quotient);
+ }
+ else
+ {
+ tmp_q2 = nL_man[aux1] >> (-tmp_q2);
+ pv_div(nrg_ref_man[c], tmp_q2 + 0x3FFFFFFF, &quotient);
+ tmp_q2 = 0; /* exponent has been applied to the sum ((man>>exp) + 1) */
+ }
+
+ tmp_q2 = nrg_ref_exp[c] - tmp_q2 - quotient.shift_factor;
+
+ pv_sqrt(quotient.quotient, tmp_q2, &root_sq, sqrt_cache[2]);
+ nrg_tone_man[c] = root_sq.root;
+ nrg_tone_exp[c] = root_sq.shift_factor;
+
+ }
+ else
+ {
+ nrg_tone_man[c] = 0;
+ nrg_tone_exp[c] = 0;
+ }
+
+ }
+ else
+ {
+ if (noNoiseFlag)
+ {
+ /*
+ * nrg_gain[c] = (float) pv_sqrt(nrg_ref[c] /(nrg_est[c] + 1), sqrt_cache[3]);
+ */
+
+ pv_div(nrg_ref_man[c], nrg_est_man[c] + 1, &quotient);
+
+ /*
+ * nrg_est_man[c] is an integer number, while nrg_ref_man[c] and
+ * quotient.quotient are fractions in Q30
+ */
+
+ tmp_q2 = nrg_ref_exp[c] - nrg_est_exp[c] - quotient.shift_factor - 30;
+
+ pv_sqrt(quotient.quotient, tmp_q2, &root_sq, sqrt_cache[3]);
+ nrg_gain_man[c] = root_sq.root;
+ nrg_gain_exp[c] = root_sq.shift_factor;
+
+ }
+ else
+ {
+ /*
+ * nrg_gain[c] = (float) pv_sqrt(nrg_ref[c]/((nrg_est[c] + 1)*(1+tmp_nL)), sqrt_cache[4]);
+ */
+ /* aux1 == next*nNBands + o */
+
+ tmp_q2 = nL_exp[aux1];
+ /*
+ * nrg_ref[c]/((nrg_est[c] + 1)*(1+tmp_nL))
+ */
+
+ if (nrg_est_man[c] == 0)
+ {
+ tmp_q2 = 0; /* avoid division by 0 in next if-else, this could be due to
+ rounding noise */
+ }
+
+
+ if (tmp_q2 >= 0)
+ {
+
+ tmp_q2 = fxp_mul32_Q30(nrg_est_man[c] + 1, nL_man[aux1] + (0x3FFFFFFF >> tmp_q2));
+ pv_div(nrg_ref_man[c], tmp_q2, &quotient);
+ /*
+ * nrg_est_man[c] is an integer number, while nrg_ref_man[c] and
+ * quotient.quotient are fractions in Q30
+ */
+ tmp_q2 = nrg_ref_exp[c] - quotient.shift_factor - 30 - nL_exp[aux1];
+ if (nrg_est_man[c])
+ {
+ tmp_q2 -= nrg_est_exp[c];
+ }
+
+ tmp_q2 = nrg_ref_exp[c] - nrg_est_exp[c] - quotient.shift_factor - 30 - nL_exp[aux1];
+ }
+ else
+ {
+ if (tmp_q2 > - 10)
+ {
+ tmp_q2 = nL_man[aux1] >> (-tmp_q2);
+
+ tmp_q2 = fxp_mul32_Q30(nrg_est_man[c] + 1, tmp_q2 + 0x3FFFFFFF);
+ }
+ else
+ {
+ tmp_q2 = nrg_est_man[c] + 1;
+ }
+
+
+ pv_div(nrg_ref_man[c], tmp_q2, &quotient);
+ /*
+ * nrg_est_man[c] is an integer number, while nrg_ref_man[c] and
+ * quotient.quotient are fractions in Q30
+ */
+
+ tmp_q2 = nrg_ref_exp[c] - quotient.shift_factor - 30;
+ if (nrg_est_man[c])
+ {
+ tmp_q2 -= nrg_est_exp[c];
+ }
+
+ }
+
+ pv_sqrt(quotient.quotient, tmp_q2, &root_sq, sqrt_cache[4]);
+ nrg_gain_man[c] = root_sq.root;
+ nrg_gain_exp[c] = root_sq.shift_factor;
+
+ }
+
+ nrg_tone_man[c] = 0;
+ nrg_tone_exp[c] = -100;
+
+ }
+
+ band_nrg_tone_detector |= nrg_tone_man[c]; /* detect any tone activity */
+
+ pv_sqrt(tmp_q1, nrg_ref_exp[c], &root_sq, sqrt_cache[5]);
+ noise_level_man[c] = root_sq.root;
+ noise_level_exp[c] = root_sq.shift_factor;
+
+ c++;
+
+ } /* ---- end-for-loop (k) ------ */
+ m++;
+
+ } /* -------- Estimate levels end-for-loop (j) ----- */
+
+
+
+ /*
+ * Limiter
+ */
+
+
+ for (c = 0; c < gateMode[limiterBand]; c++)
+ {
+
+ p_ref_man = 0;
+ p_est_man = 0;
+
+ /*
+ * get max exponent for the reference and estimated energy
+ */
+ p_ref_exp = -100;
+ p_est_exp = -100;
+
+ for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++)
+ {
+ if (p_ref_exp < nrg_ref_exp[k])
+ {
+ p_ref_exp = nrg_ref_exp[k]; /* max */
+ }
+ if (p_est_exp < nrg_est_exp[k])
+ {
+ p_est_exp = nrg_est_exp[k]; /* max */
+ }
+ }
+
+ k -= limSbc[limiterBand][c]; /* number of element used in the addition */
+
+ while (k != 0) /* bit guard protection depends on log2(k) */
+ {
+ k >>= 1;
+ p_ref_exp++; /* add extra bit-overflow-guard, nrg_ref_exp is in Q30 format */
+ }
+
+
+ for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++)
+ { /*Calculate the average gain for the current limiter band.*/
+ p_ref_man += (nrg_ref_man[k] >> (p_ref_exp - nrg_ref_exp[k]));
+ p_est_man += (nrg_est_man[k] >> (p_est_exp - nrg_est_exp[k]));
+
+ }
+
+ if (p_est_man)
+ {
+ /*
+ * "average gain" (not equal to average of nrg_gain)
+ */
+ pv_div(p_ref_man, p_est_man, &quotient);
+
+ tmp_q2 = p_ref_exp - 30 - p_est_exp - quotient.shift_factor;
+
+ /*
+ * avg_gain = sqrt(p_ref/p_est)
+ */
+ pv_sqrt(quotient.quotient, tmp_q2, &root_sq, sqrt_cache[6]);
+ avg_gain = root_sq.root;
+ g_max_exp = root_sq.shift_factor;
+
+ /*
+ * maximum gain allowed is calculated from table.
+ */
+
+ /*
+ * g_max = avg_gain * limGains[limiterGains];
+ */
+
+ g_max_man = fxp_mul32_Q30(avg_gain, limGains[limiterGains]); /* table is in Q30 */
+
+ if (limiterGains == 3)
+ {
+ g_max_exp = limGains[4];
+ }
+
+ tmp_q1 = g_max_exp >= 16 ? g_max_exp : 16;
+
+ tmp_q2 = g_max_man >> (tmp_q1 - g_max_exp);
+ tmp_q1 = Q28fmt(1.52587890625F) >> (tmp_q1 - 16);
+
+ if (tmp_q2 > tmp_q1)
+ {
+ /* upper limit, +100 dB */
+ g_max_man = Q28fmt(1.52587890625F);
+ g_max_exp = 16;
+ }
+ }
+ else
+ {
+ /* Qfmt(1.52587890625F) exp = 16 */
+ g_max_man = Q28fmt(1.52587890625F);
+ g_max_exp = 16;
+ }
+
+ /*
+ * Compute Adjusted power p_adj
+ */
+ for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++)
+ {
+
+ tmp_q1 = g_max_exp >= nrg_gain_exp[k] ? g_max_exp : nrg_gain_exp[k];
+
+ tmp_q2 = g_max_man >> (tmp_q1 - g_max_exp);
+ tmp_q1 = nrg_gain_man[k] >> (tmp_q1 - nrg_gain_exp[k]);
+ /*
+ * if(g_max <= nrg_gain[k])
+ */
+ if (tmp_q2 <= tmp_q1)
+ {
+ tmp_q1 = fxp_mul32_Q28(noise_level_man[k], g_max_man);
+ pv_div(tmp_q1, nrg_gain_man[k], &quotient);
+ noise_level_man[k] = quotient.quotient >> 2; /* in Q28 */
+ noise_level_exp[k] = noise_level_exp[k] + g_max_exp - quotient.shift_factor - nrg_gain_exp[k];
+
+ nrg_gain_man[k] = g_max_man; /* gains with noise supression */
+ nrg_gain_exp[k] = g_max_exp;
+ }
+ }
+
+ p_adj_exp = -100;
+
+ for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++)
+ {
+ tmp_q1 = nrg_est_exp[k] + (nrg_gain_exp[k] << 1) + 28; /* 28 to match shift down by mult32_Q28 */
+
+ if (p_adj_exp < tmp_q1)
+ {
+ p_adj_exp = tmp_q1;
+ }
+ if (nrg_tone_man[k])
+ {
+ tmp_q1 = (nrg_tone_exp[k] << 1);
+ if (p_adj_exp < tmp_q1)
+ {
+ p_adj_exp = tmp_q1;
+ }
+ }
+ else if (!noNoiseFlag)
+ {
+ tmp_q1 = (noise_level_exp[k] << 1);
+
+ if (p_adj_exp < tmp_q1)
+ {
+ p_adj_exp = tmp_q1;
+ }
+ }
+ }
+
+ p_adj_exp += 1; /* overflow bit-guard*/
+
+ p_adj_man = 0;
+
+ for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++)
+ {
+ /*
+ * p_adj += nrg_gain[k]*nrg_gain[k]*nrg_est[k];
+ */
+
+ if (p_adj_exp - (nrg_est_exp[k] + (nrg_gain_exp[k] << 1)) < 59)
+ {
+ tmp_q1 = fxp_mul32_Q28(nrg_gain_man[k], nrg_gain_man[k]);
+ tmp_q1 = fxp_mul32_Q28(tmp_q1, nrg_est_man[k]);
+ p_adj_man += (tmp_q1 >> (p_adj_exp - (nrg_est_exp[k] + (nrg_gain_exp[k] << 1) + 28)));
+ }
+
+ if (nrg_tone_man[k])
+ {
+ /*
+ * p_adj += nrg_tone[k]*nrg_tone[k];
+ */
+ if (p_adj_exp - (nrg_tone_exp[k] << 1) < 31)
+ {
+ tmp_q1 = fxp_mul32_Q28(nrg_tone_man[k], nrg_tone_man[k]);
+ p_adj_man += (tmp_q1 >> (p_adj_exp - (nrg_tone_exp[k] << 1)));
+ }
+ }
+ else if (!noNoiseFlag)
+ {
+ /*
+ * p_adj += noise_level[k]*noise_level[k];
+ */
+
+ if (p_adj_exp - (noise_level_exp[k] << 1) < 31)
+ {
+ tmp_q1 = fxp_mul32_Q28(noise_level_man[k], noise_level_man[k]);
+ p_adj_man += (tmp_q1 >> (p_adj_exp - (noise_level_exp[k] << 1)));
+ }
+
+ }
+ }
+
+
+ if (p_adj_man)
+ {
+ pv_div(p_ref_man, p_adj_man, &quotient);
+ tmp_q2 = p_ref_exp - p_adj_exp - 58 - quotient.shift_factor; /* 58 <> Q30 + Q28 */
+
+ pv_sqrt(quotient.quotient, tmp_q2, &root_sq, sqrt_cache[7]);
+
+ if (root_sq.shift_factor > -28)
+ {
+ boost_gain_q = root_sq.root << (root_sq.shift_factor + 28);
+ }
+ else
+ {
+ boost_gain_q = root_sq.root >> (-28 - root_sq.shift_factor);
+ }
+
+ tmp_q1 = root_sq.shift_factor >= -28 ? root_sq.shift_factor : -28;
+
+ tmp_q2 = root_sq.root >> (tmp_q1 - root_sq.shift_factor);
+ tmp_q1 = Q28fmt(1.584893192f) >> (tmp_q1 + 28);
+
+
+ if (tmp_q2 > tmp_q1)
+ {
+ boost_gain_q = Q28fmt(1.584893192f);
+ }
+ }
+ else
+ {
+ boost_gain_q = Q28fmt(1.584893192f);
+ }
+
+ if (band_nrg_tone_detector)
+ {
+ for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++)
+ {
+ nrg_gain_man[k] = fxp_mul32_Q28(nrg_gain_man[k], boost_gain_q);
+ noise_level_man[k] = fxp_mul32_Q28(noise_level_man[k], boost_gain_q);
+ nrg_tone_man[k] = fxp_mul32_Q28(nrg_tone_man[k], boost_gain_q);
+ }
+ }
+ else
+ {
+
+ for (k = limSbc[limiterBand][c]; k < limSbc[limiterBand][c + 1]; k++)
+ {
+ nrg_gain_man[k] = fxp_mul32_Q28(nrg_gain_man[k], boost_gain_q);
+ noise_level_man[k] = fxp_mul32_Q28(noise_level_man[k], boost_gain_q);
+ }
+
+
+ }
+
+ } /* Limiter End for loop (c) */
+
+
+ if (LC_flag == ON)
+ {
+
+ /*
+ * Aliasing correction
+ */
+
+ sbr_aliasing_reduction(degreeAlias,
+ nrg_gain_man,
+ nrg_gain_exp,
+ nrg_est_man,
+ nrg_est_exp,
+ dontUseTheseGainValues,
+ noSubbands,
+ lowSubband,
+ sqrt_cache,
+ scratch_mem[3]);
+
+ if (*sUp) /* Init only done once upon reset */
+ {
+ *sUp = 0;
+ }
+
+ envelope_application_LC((Int32 *)aBufR,
+ nrg_gain_man,
+ nrg_gain_exp,
+ noise_level_man,
+ noise_level_exp,
+ nrg_tone_man,
+ nrg_tone_exp,
+ band_nrg_tone_detector,
+ frame_info,
+ harm_index,
+ phase_index,
+ i,
+ lowSubband,
+ noSubbands,
+ noNoiseFlag);
+ }
+#ifdef HQ_SBR
+ else
+ {
+
+ if (*sUp) /* Init only done once upon reset */
+ {
+ for (n = 0; n < maxSmoothLength; n++)
+ {
+ pv_memcpy(fBuf_man[n], nrg_gain_man, noSubbands*sizeof(*fBuf_man[n]));
+ pv_memcpy(fBufN_man[n], noise_level_man, noSubbands*sizeof(*fBufN_man[n]));
+ pv_memcpy(fBuf_exp[n], nrg_gain_exp, noSubbands*sizeof(*fBuf_exp[n]));
+ pv_memcpy(fBufN_exp[n], noise_level_exp, noSubbands*sizeof(*fBufN_exp[n]));
+ }
+ *sUp = 0;
+ }
+
+
+ envelope_application((Int32 *)aBufR,
+ (Int32 *)aBufI,
+ nrg_gain_man,
+ nrg_gain_exp,
+ noise_level_man,
+ noise_level_exp,
+ nrg_tone_man,
+ nrg_tone_exp,
+ fBuf_man,
+ fBuf_exp,
+ fBufN_man,
+ fBufN_exp,
+ frame_info,
+ harm_index,
+ phase_index,
+ i,
+ lowSubband,
+ noSubbands,
+ noNoiseFlag,
+ band_nrg_tone_detector,
+ maxSmoothLength,
+ smooth_length);
+
+ }
+#endif
+
+ } /* ----- Envelope adjustment end for-loop (i) ---- */
+
+
+ pv_memcpy(&hFp[0] + lowSubband,
+ hF,
+ (64 - lowSubband)*sizeof(*hF));
+
+ if (sEnv == nEnv)
+ {
+ frameData->prevEnvIsShort = 0;
+ }
+ else
+ {
+ frameData->prevEnvIsShort = -1;
+ }
+
+
+}
+
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void envelope_application_LC(Int32 *aBufR,
+ Int32 *nrg_gain_man,
+ Int32 *nrg_gain_exp,
+ Int32 *noise_level_man,
+ Int32 *noise_level_exp,
+ Int32 *nrg_tone_man,
+ Int32 *nrg_tone_exp,
+ Int32 band_nrg_tone_detector,
+ const Int32 *frame_info,
+ Int32 *harm_index,
+ Int32 *phase_index,
+ Int32 i,
+ Int32 lowSubband,
+ Int32 noSubbands,
+ Int32 noNoiseFlag)
+{
+
+ Int32 *ptrReal;
+ Int32 sb_gain_man;
+ Int32 sb_noise_man;
+ Int32 sb_noise_exp;
+ Int32 l;
+ Int32 k;
+ Int32 tmp_q1;
+ Int32 tmp_q2;
+ Int32 tone_count;
+ Int16 tmp_16;
+ Int32 indexMinus1;
+ Int32 indexPlus1;
+
+
+ /*
+ * Application
+ */
+
+ if (band_nrg_tone_detector) /* Add tone energy only if energy is detected */
+ {
+
+ /*
+ * pre-calculate tone application
+ */
+ for (k = 0; k < noSubbands; k++)
+ {
+ tmp_q2 = (-nrg_tone_exp[k]);
+ tmp_q1 = nrg_tone_man[k];
+ tmp_q2 = tmp_q1 >> tmp_q2;
+ tmp_q1 = fxp_mul32_by_16(tmp_q2, Q15fmt(0.0163f));
+ nrg_tone_man[k] = tmp_q2;
+ nrg_tone_exp[k] = tmp_q1;
+ noise_level_exp[k] += 1;
+ nrg_gain_exp[k] += 28;
+ }
+
+ for (l = (frame_info[1+i] << 1); l < (frame_info[2+i] << 1); l++)
+ {
+ ptrReal = (aBufR + l * SBR_NUM_BANDS);
+
+ tone_count = 0;
+
+ indexPlus1 = (*harm_index + 1) & 3;
+
+ if (indexPlus1 & 1) /* if indexPlus1 is odd */
+ {
+ for (k = 0; k < noSubbands; k++)
+ {
+
+ sb_gain_man = nrg_gain_man[k];
+ tmp_q1 = *ptrReal;
+ tmp_q2 = nrg_gain_exp[k];
+ tmp_q1 = fxp_mul32_Q28(tmp_q1, sb_gain_man);
+
+ if (tmp_q2 < 0)
+ {
+ if (tmp_q2 > -32)
+ {
+ *ptrReal = tmp_q1 >> (-tmp_q2);
+ }
+ }
+ else
+ {
+ *ptrReal = tmp_q1 << tmp_q2;
+ }
+
+ *phase_index = (*phase_index + 1) & 511;
+
+ if (!nrg_tone_man[k] && !noNoiseFlag)
+
+ {
+ tmp_16 = rP_LCx[*phase_index];
+ sb_noise_man = noise_level_man[k];
+ sb_noise_exp = noise_level_exp[k];
+
+ tmp_q1 = fxp_mul32_by_16(sb_noise_man, tmp_16);
+
+ if (sb_noise_exp < 0)
+ {
+ if (sb_noise_exp > -32)
+ {
+ *ptrReal += tmp_q1 >> (-sb_noise_exp);
+ }
+ }
+ else
+ {
+ *ptrReal += tmp_q1 << sb_noise_exp;
+ }
+ }
+
+ tmp_q1 = nrg_tone_man[k];
+
+ if (*harm_index)
+ {
+ *ptrReal -= tmp_q1;
+ }
+ else
+ {
+ *ptrReal += tmp_q1;
+ }
+
+ if (tmp_q1)
+ {
+ tone_count++;
+ }
+
+ ptrReal++;
+
+ } /* for-loop (k) */
+
+ }
+ else /* if indexPlus1 is even */
+ {
+ indexMinus1 = (*harm_index - 1) & 3;
+
+ /* --- k = 0 ----- */
+
+ sb_gain_man = nrg_gain_man[0];
+ tmp_q1 = *ptrReal;
+ tmp_q2 = nrg_gain_exp[0];
+ tmp_q1 = fxp_mul32_Q28(tmp_q1, sb_gain_man);
+
+ if (tmp_q2 < 0)
+ {
+ if (tmp_q2 > -32)
+ {
+ *ptrReal = tmp_q1 >> (-tmp_q2);
+ }
+ }
+ else
+ {
+ *ptrReal = tmp_q1 << tmp_q2;
+ }
+
+ *phase_index = (*phase_index + 1) & 511;
+
+ tmp_q1 = nrg_tone_exp[0];
+ tmp_q2 = nrg_tone_exp[1];
+
+ if ((indexPlus1 != 0) ^((lowSubband & 1) != 0))
+ {
+ *(ptrReal - 1) -= tmp_q1;
+ *(ptrReal) += tmp_q2;
+ }
+ else
+ {
+ *(ptrReal - 1) += tmp_q1;
+ *(ptrReal) -= tmp_q2;
+ }
+
+ if (!nrg_tone_man[0] && !noNoiseFlag)
+ {
+ tmp_16 = rP_LCx[*phase_index];
+ sb_noise_man = noise_level_man[0];
+ sb_noise_exp = noise_level_exp[0];
+
+ tmp_q1 = fxp_mul32_by_16(sb_noise_man, tmp_16);
+
+ if (sb_noise_exp < 0)
+ {
+ if (sb_noise_exp > -32)
+ {
+ *ptrReal += tmp_q1 >> (-sb_noise_exp);
+ }
+ }
+ else
+ {
+ *ptrReal += tmp_q1 << sb_noise_exp;
+ }
+ }
+ else
+ {
+ tone_count++;
+ }
+
+ ptrReal++;
+
+ /* ---- */
+
+ for (k = 1; k < noSubbands - 1; k++)
+ {
+
+ sb_gain_man = nrg_gain_man[k];
+ tmp_q1 = *ptrReal;
+ tmp_q2 = nrg_gain_exp[k];
+ tmp_q1 = fxp_mul32_Q28(tmp_q1, sb_gain_man);
+
+ if (tmp_q2 < 0)
+ {
+ if (tmp_q2 > -32)
+ {
+ *ptrReal = tmp_q1 >> (-tmp_q2);
+ }
+ }
+ else
+ {
+ *ptrReal = tmp_q1 << tmp_q2;
+ }
+
+ *phase_index = (*phase_index + 1) & 511;
+
+
+ if (tone_count < 16)
+ {
+ tmp_q1 = nrg_tone_exp[k - 1];
+ tmp_q2 = nrg_tone_exp[k + 1];
+
+ tmp_q1 -= tmp_q2;
+
+
+ if ((indexPlus1 != 0) ^(((k + lowSubband) & 1) != 0))
+ {
+ *(ptrReal) -= tmp_q1;
+ }
+ else
+ {
+ *(ptrReal) += tmp_q1;
+ }
+ } /* if (tone_count < 16) */
+
+
+ if (!nrg_tone_man[k] && !noNoiseFlag)
+ {
+ tmp_16 = rP_LCx[*phase_index];
+ sb_noise_man = noise_level_man[k];
+ sb_noise_exp = noise_level_exp[k];
+
+ tmp_q1 = fxp_mul32_by_16(sb_noise_man, tmp_16);
+
+ if (sb_noise_exp < 0)
+ {
+ if (sb_noise_exp > -32)
+ {
+ *ptrReal += tmp_q1 >> (-sb_noise_exp);
+ }
+ }
+ else
+ {
+ *ptrReal += tmp_q1 << sb_noise_exp;
+ }
+ }
+ else
+ {
+ tone_count++;
+ }
+
+ ptrReal++;
+
+ } /* for-loop (k) */
+
+ sb_gain_man = nrg_gain_man[k];
+ tmp_q1 = *ptrReal;
+ tmp_q2 = nrg_gain_exp[k];
+ tmp_q1 = fxp_mul32_Q28(tmp_q1, sb_gain_man);
+
+ if (tmp_q2 < 0)
+ {
+ if (tmp_q2 > -31)
+ {
+ *ptrReal = tmp_q1 >> (-tmp_q2);
+ }
+ }
+ else
+ {
+ *ptrReal = tmp_q1 << tmp_q2;
+ }
+
+ *phase_index = (*phase_index + 1) & 511;
+
+
+ if ((tone_count < 16) && !(indexMinus1 &1))
+ {
+ tmp_q1 = nrg_tone_exp[k - 1];
+ tmp_q2 = nrg_tone_exp[k ];
+
+ if ((indexMinus1 != 0) ^(((k + lowSubband) & 1) != 0))
+ {
+ *(ptrReal) += tmp_q1;
+
+ if (k + lowSubband < 62)
+ {
+ *(ptrReal + 1) -= tmp_q2;
+ }
+ }
+ else
+ {
+ *(ptrReal) -= tmp_q1;
+
+ if (k + lowSubband < 62)
+ {
+ *(ptrReal + 1) += tmp_q2;
+ }
+ }
+ } /* if (tone_count < 16) */
+
+
+ if (!nrg_tone_man[k] && !noNoiseFlag)
+ {
+ tmp_16 = rP_LCx[*phase_index];
+ sb_noise_man = noise_level_man[k];
+ sb_noise_exp = noise_level_exp[k];
+
+ tmp_q1 = fxp_mul32_by_16(sb_noise_man, tmp_16);
+
+ if (sb_noise_exp < 0)
+ {
+ if (sb_noise_exp > -31)
+ {
+ *ptrReal += tmp_q1 >> (-sb_noise_exp);
+ }
+ }
+ else
+ {
+ *ptrReal += tmp_q1 << sb_noise_exp;
+ }
+ }
+
+ } /* if indexPlus1 is odd */
+
+ *harm_index = indexPlus1;
+
+
+ } /* for-loop (l) */
+
+ }
+ else /* if ( band_nrg_tone_detector) */
+ {
+
+ for (k = 0; k < noSubbands; k++)
+ {
+ tmp_q1 = noise_level_exp[k];
+ tmp_q2 = nrg_gain_exp[k];
+ noise_level_exp[k] = tmp_q1 + 1;
+ nrg_gain_exp[k] = tmp_q2 + 28;
+ }
+
+ for (l = (frame_info[1+i] << 1); l < (frame_info[2+i] << 1); l++)
+ {
+ ptrReal = (aBufR + l * SBR_NUM_BANDS);
+
+ for (k = 0; k < noSubbands; k++)
+ {
+
+ tmp_q1 = *ptrReal;
+ sb_gain_man = nrg_gain_man[k];
+
+ tmp_q2 = nrg_gain_exp[k];
+
+ tmp_q1 = fxp_mul32_Q28(tmp_q1, sb_gain_man);
+
+ if (tmp_q2 < 0)
+ {
+ if (tmp_q2 > -31)
+ {
+ *ptrReal = tmp_q1 >> (-tmp_q2);
+ }
+ }
+ else
+ {
+ *ptrReal = tmp_q1 << tmp_q2;
+ }
+
+ *phase_index = (*phase_index + 1) & 511;
+
+ if (! noNoiseFlag)
+ {
+ tmp_16 = rP_LCx[*phase_index];
+ sb_noise_man = noise_level_man[k];
+ sb_noise_exp = noise_level_exp[k];
+
+ tmp_q1 = fxp_mul32_by_16(sb_noise_man, tmp_16);
+
+ if (sb_noise_exp < 0)
+ {
+ if (sb_noise_exp > -31)
+ {
+ *ptrReal += tmp_q1 >> (-sb_noise_exp);
+ }
+ }
+ else
+ {
+ *ptrReal += tmp_q1 << sb_noise_exp;
+ }
+ }
+
+ ptrReal++;
+
+ } /* for-loop (k) */
+
+ *harm_index = (*harm_index + 1) & 3;
+
+
+ } /* for-loop (l) */
+
+ }
+
+}
+
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+#define Qfmt15(a) (Int32)(a*((Int32)1<<15) + (a>=0?0.5F:-0.5F))
+
+
+const Int16 pow2[39] = { 0, 0, 1, 0, 2,
+ 0, Qfmt15(2 / 6.0f), 0, 3, 0, Qfmt15(2 / 10.0f), 0, Qfmt15(2 / 12.0f), 0, Qfmt15(2 / 14.0f), 0, 4,
+ 0, Qfmt15(2 / 18.0f), 0, Qfmt15(2 / 20.0f), 0, Qfmt15(2 / 22.0f), 0, Qfmt15(2 / 24.0f),
+ 0, Qfmt15(2 / 26.0f), 0, Qfmt15(2 / 28.0f), 0, Qfmt15(2 / 30.0f), 0, 5, 0, Qfmt15(2 / 34.0f),
+ 0, Qfmt15(2 / 36.0f), 0, Qfmt15(2 / 38.0f)
+ };
+
+void energy_estimation_LC(Int32 *aBufR,
+ Int32 *nrg_est_man,
+ Int32 *nrg_est_exp,
+ const Int32 *frame_info,
+ Int32 i,
+ Int32 k,
+ Int32 c,
+ Int32 ui2)
+{
+
+
+ Int32 aux1;
+ Int32 aux2;
+ Int32 l;
+
+
+ int64_t nrg_h = 0;
+ Int32 tmp1;
+ UInt32 tmp2;
+
+ for (l = ui2; l < (frame_info[2+i] << 1); l++)
+ {
+
+ aux1 = aBufR[l++*SBR_NUM_BANDS + k ];
+ aux2 = aBufR[l *SBR_NUM_BANDS + k ];
+
+ nrg_h = fxp_mac64_Q31(nrg_h, aux1, aux1);
+ nrg_h = fxp_mac64_Q31(nrg_h, aux2, aux2);
+ }
+
+ /*
+ * Check for overflow and saturate if needed
+ */
+ if (nrg_h < 0)
+ {
+ nrg_h = 0x7fffffff;
+ }
+
+
+ if (nrg_h)
+ {
+ tmp2 = (UInt32)(nrg_h >> 32);
+ if (tmp2)
+ {
+ aux2 = pv_normalize(tmp2);
+ aux2 -= 1; /* ensure Q30 */
+ nrg_h = (nrg_h << aux2) >> 33;
+ tmp2 = (UInt32)(nrg_h);
+ nrg_est_exp[c] = 33 - aux2;
+ }
+ else
+ {
+ tmp2 = (UInt32)(nrg_h >> 2);
+ aux2 = pv_normalize(tmp2);
+ aux2 -= 1; /* ensure Q30 */
+
+ tmp2 = (tmp2 << aux2);
+ nrg_est_exp[c] = -aux2 + 2;
+ }
+
+ tmp1 = (l - ui2);
+
+ aux2 = pow2[tmp1];
+ if (tmp1 == (tmp1 & (-tmp1)))
+ {
+ nrg_est_man[c] = tmp2 >> aux2;
+ }
+ else
+ {
+ nrg_est_man[c] = fxp_mul32_by_16(tmp2, aux2);
+ }
+
+ }
+ else
+ {
+ nrg_est_man[c] = 0;
+ nrg_est_exp[c] = -100;
+ }
+
+
+
+
+
+}
+
+
+
+
+
+
+#if HQ_SBR
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void envelope_application(Int32 *aBufR,
+ Int32 *aBufI,
+ Int32 *nrg_gain_man,
+ Int32 *nrg_gain_exp,
+ Int32 *noise_level_man,
+ Int32 *noise_level_exp,
+ Int32 *nrg_tone_man,
+ Int32 *nrg_tone_exp,
+ Int32 *fBuf_man[64],
+ Int32 *fBuf_exp[64],
+ Int32 *fBufN_man[64],
+ Int32 *fBufN_exp[64],
+ const Int32 *frame_info,
+ Int32 *harm_index,
+ Int32 *phase_index,
+ Int32 i,
+ Int32 lowSubband,
+ Int32 noSubbands,
+ Int32 noNoiseFlag,
+ Int32 band_nrg_tone_detector,
+ Int32 maxSmoothLength,
+ Int32 smooth_length)
+{
+
+ Int32 *ptrReal;
+ Int32 *ptrImag;
+ Int32 sb_gain_man;
+ Int32 sb_gain_exp;
+ Int32 sb_noise_man;
+ Int32 sb_noise_exp;
+ Int32 l;
+ Int32 k;
+ Int32 n;
+ Int32 tmp_q1;
+ Int32 tmp_q2;
+ Int32 aux1;
+ Int32 aux2;
+ Int32 filter_history = 0;
+
+
+ if (band_nrg_tone_detector) /* Add tone energy only if energy is detected */
+ {
+
+ /*
+ * pre-calculate tone application
+ */
+
+ ptrReal = nrg_tone_exp;
+ ptrImag = nrg_tone_man;
+ tmp_q1 = - *(ptrReal++);
+ aux1 = *(ptrImag);
+ for (k = 0; k < noSubbands; k++)
+ {
+ *(ptrImag++) = aux1 >> tmp_q1;
+ tmp_q1 = - *(ptrReal++);
+ aux1 = *(ptrImag);
+ }
+
+ /*
+ * Application
+ */
+
+ for (l = (frame_info[1+i] << 1); l < (frame_info[2+i] << 1); l++)
+ {
+ ptrReal = (aBufR + l * SBR_NUM_BANDS);
+ ptrImag = (aBufI + l * SBR_NUM_BANDS);
+
+ if (filter_history <= maxSmoothLength) /* no more update is needed as buffer will have same info */
+ {
+ pv_memmove(fBuf_man[maxSmoothLength], nrg_gain_man, noSubbands*sizeof(*nrg_gain_man));
+ pv_memmove(fBuf_exp[maxSmoothLength], nrg_gain_exp, noSubbands*sizeof(*nrg_gain_exp));
+ pv_memmove(fBufN_man[maxSmoothLength], noise_level_man, noSubbands*sizeof(*noise_level_man));
+ pv_memmove(fBufN_exp[maxSmoothLength], noise_level_exp, noSubbands*sizeof(*noise_level_exp));
+ }
+
+ /*
+ * nrg_gain_max bounded to 1.584893192*1e5, which requires (32-bit) Q14 notation
+ */
+ for (k = 0; k < noSubbands; k++)
+ {
+ if (smooth_length == 0) /* no filter-smooth needed */
+ {
+ sb_gain_man = nrg_gain_man[k];
+ sb_gain_exp = nrg_gain_exp[k];
+
+ sb_noise_man = noise_level_man[k];
+ sb_noise_exp = noise_level_exp[k];
+
+ }
+ else
+ { /* else smooth_length == 4 and fir_4 filter is being used */
+
+ sb_gain_exp = fBuf_exp[maxSmoothLength][k];
+
+ sb_noise_exp = fBufN_exp[maxSmoothLength][k];
+
+ for (n = maxSmoothLength - smooth_length; n < maxSmoothLength; n++)
+ {
+ if (sb_gain_exp < fBuf_exp[n][k])
+ {
+ sb_gain_exp = fBuf_exp[n][k];
+ }
+
+ if (sb_noise_exp < fBufN_exp[n][k])
+ {
+ sb_noise_exp = fBufN_exp[n][k];
+ }
+ }
+
+ sb_gain_man = fxp_mul32_Q30(fBuf_man[maxSmoothLength][k], Q30fmt(0.33333333333333f));
+ sb_gain_man = sb_gain_man >> (sb_gain_exp - fBuf_exp[maxSmoothLength][k]);
+
+ sb_noise_man = fxp_mul32_Q30(fBufN_man[maxSmoothLength][k], Q30fmt(0.33333333333333f));
+ sb_noise_man = sb_noise_man >> (sb_noise_exp - fBufN_exp[maxSmoothLength][k]);
+
+ n = maxSmoothLength - smooth_length;
+
+ tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.03183050093751f));
+ sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.03183050093751f));
+ sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n++][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.11516383427084f));
+ sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.11516383427084f));
+ sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n++][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.21816949906249f));
+ sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.21816949906249f));
+ sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n++][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.30150283239582f));
+ sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.30150283239582f));
+ sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n][k]);
+
+ }
+
+
+
+ /*
+ * *ptrReal = *ptrReal * sb_gain ;
+ * *ptrImag = *ptrImag * sb_gain;
+ */
+ aux1 = *ptrReal;
+ aux2 = *ptrImag;
+ sb_gain_exp += 32;
+ aux1 = fxp_mul32_Q31(aux1, sb_gain_man);
+ aux2 = fxp_mul32_Q31(aux2, sb_gain_man);
+
+
+ if (sb_gain_exp < 0)
+ {
+ sb_gain_exp = -sb_gain_exp;
+ if (sb_gain_exp < 32)
+ {
+ *ptrReal = (aux1 >> sb_gain_exp);
+ *ptrImag = (aux2 >> sb_gain_exp);
+ }
+ }
+ else
+ {
+ *ptrReal = (aux1 << sb_gain_exp);
+ *ptrImag = (aux2 << sb_gain_exp);
+ }
+
+
+
+ /*
+ * if ( sb_noise != 0)
+ * {
+ * *ptrReal += sb_noise * rP[*phase_index][0];
+ * *ptrImag += sb_noise * rP[*phase_index][1];
+ * }
+ */
+ *phase_index = (*phase_index + 1) & 511;
+
+ if (nrg_tone_man[k] || noNoiseFlag)
+ {
+ sb_noise_man = 0;
+ sb_noise_exp = 0;
+ }
+ else
+ {
+
+ Int32 tmp = rPxx[*phase_index];
+ sb_noise_exp += 1;
+ tmp_q1 = fxp_mul32_by_16t(sb_noise_man, tmp);
+ tmp_q2 = fxp_mul32_by_16b(sb_noise_man, tmp);
+
+
+ if (sb_noise_exp < 0)
+ {
+ if (sb_noise_exp > -32)
+ {
+ *ptrReal += tmp_q1 >> (-sb_noise_exp);
+ *ptrImag += tmp_q2 >> (-sb_noise_exp);
+ }
+ }
+ else
+ {
+ *ptrReal += tmp_q1 << sb_noise_exp;
+ *ptrImag += tmp_q2 << sb_noise_exp;
+ }
+ }
+
+ /*
+ * tmp_q1 = nrg_tone[k]
+ */
+
+ tmp_q1 = nrg_tone_man[k];
+
+ if (*harm_index & 1)
+ {
+ if ((((k + lowSubband) & 1) != 0) ^(*harm_index != 1))
+ {
+ *ptrImag -= tmp_q1;
+ }
+ else
+ {
+ *ptrImag += tmp_q1;
+ }
+ }
+ else
+ {
+ *ptrReal += (*harm_index) ? -tmp_q1 : tmp_q1;
+ }
+
+ *ptrReal++ <<= 10;
+ *ptrImag++ <<= 10;
+
+
+ } /* for-loop (k) */
+
+
+ *harm_index = (*harm_index + 1) & 3;
+
+ /*
+ * Update smoothing filter history
+ */
+
+ if (filter_history++ < maxSmoothLength) /* no more update is needed as buffer will have same info */
+ {
+ /*
+ * mantissas
+ */
+
+ ptrReal = (Int32 *)fBuf_man[0];
+ ptrImag = (Int32 *)fBufN_man[0];
+
+ for (n = 0; n < maxSmoothLength; n++)
+ {
+ fBuf_man[n] = fBuf_man[n+1];
+ fBufN_man[n] = fBufN_man[n+1];
+ }
+
+ fBuf_man[maxSmoothLength] = ptrReal;
+ fBufN_man[maxSmoothLength] = ptrImag;
+
+ /*
+ * exponents
+ */
+ ptrReal = (Int32 *)fBuf_exp[0];
+ ptrImag = (Int32 *)fBufN_exp[0];
+
+ for (n = 0; n < maxSmoothLength; n++)
+ {
+ fBuf_exp[n] = fBuf_exp[n+1];
+ fBufN_exp[n] = fBufN_exp[n+1];
+ }
+
+ fBuf_exp[maxSmoothLength] = ptrReal;
+ fBufN_exp[maxSmoothLength] = ptrImag;
+ }
+
+ } /* for-loop (l) */
+
+
+ }
+ else /* ---- if ( band_nrg_tone_detector) ---- */
+ {
+
+ /*
+ * Application
+ */
+
+ for (l = (frame_info[1+i] << 1); l < (frame_info[2+i] << 1); l++)
+ {
+ ptrReal = (aBufR + l * SBR_NUM_BANDS);
+ ptrImag = (aBufI + l * SBR_NUM_BANDS);
+
+ if (filter_history <= maxSmoothLength) /* no more update is needed as buffer will have same info */
+ {
+ pv_memmove(fBuf_man[maxSmoothLength], nrg_gain_man, noSubbands*sizeof(*nrg_gain_man));
+ pv_memmove(fBuf_exp[maxSmoothLength], nrg_gain_exp, noSubbands*sizeof(*nrg_gain_exp));
+ pv_memmove(fBufN_man[maxSmoothLength], noise_level_man, noSubbands*sizeof(*noise_level_man));
+ pv_memmove(fBufN_exp[maxSmoothLength], noise_level_exp, noSubbands*sizeof(*noise_level_exp));
+ }
+
+ /*
+ * nrg_gain_max bounded to 1.584893192*1e5, which requires (32-bit) Q14 notation
+ */
+ for (k = 0; k < noSubbands; k++)
+ {
+ if (smooth_length == 0) /* no filter-smooth needed */
+ {
+ sb_gain_man = nrg_gain_man[k];
+ sb_gain_exp = nrg_gain_exp[k];
+
+ sb_noise_man = noise_level_man[k];
+ sb_noise_exp = noise_level_exp[k];
+
+ }
+ else
+ { /* else smooth_length == 4 and fir_4 filter is being used */
+
+ sb_gain_exp = fBuf_exp[maxSmoothLength][k];
+
+ sb_noise_exp = fBufN_exp[maxSmoothLength][k];
+
+ for (n = maxSmoothLength - smooth_length; n < maxSmoothLength; n++)
+ {
+ if (sb_gain_exp < fBuf_exp[n][k])
+ {
+ sb_gain_exp = fBuf_exp[n][k];
+ }
+
+ if (sb_noise_exp < fBufN_exp[n][k])
+ {
+ sb_noise_exp = fBufN_exp[n][k];
+ }
+ }
+
+ sb_gain_man = fxp_mul32_Q30(fBuf_man[maxSmoothLength][k], Q30fmt(0.33333333333333f));
+ sb_gain_man = sb_gain_man >> (sb_gain_exp - fBuf_exp[maxSmoothLength][k]);
+
+ sb_noise_man = fxp_mul32_Q30(fBufN_man[maxSmoothLength][k], Q30fmt(0.33333333333333f));
+ sb_noise_man = sb_noise_man >> (sb_noise_exp - fBufN_exp[maxSmoothLength][k]);
+
+ n = maxSmoothLength - smooth_length;
+
+ tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.03183050093751f));
+ sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.03183050093751f));
+ sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n++][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.11516383427084f));
+ sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.11516383427084f));
+ sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n++][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.21816949906249f));
+ sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.21816949906249f));
+ sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n++][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBuf_man[n][k], Q30fmt(0.30150283239582f));
+ sb_gain_man += tmp_q1 >> (sb_gain_exp - fBuf_exp[n][k]);
+
+ tmp_q1 = fxp_mul32_Q30(fBufN_man[n][k], Q30fmt(0.30150283239582f));
+ sb_noise_man += tmp_q1 >> (sb_noise_exp - fBufN_exp[n][k]);
+
+ }
+
+
+
+ /*
+ * *ptrReal = *ptrReal * sb_gain ;
+ * *ptrImag = *ptrImag * sb_gain;
+ */
+ aux1 = *ptrReal;
+ aux2 = *ptrImag;
+ sb_gain_exp += 32;
+ aux1 = fxp_mul32_Q31(aux1, sb_gain_man);
+ aux2 = fxp_mul32_Q31(aux2, sb_gain_man);
+
+
+
+ /*
+ * if ( sb_noise != 0)
+ * {
+ * *ptrReal += sb_noise * rP[*phase_index][0];
+ * *ptrImag += sb_noise * rP[*phase_index][1];
+ * }
+ */
+
+
+ if (sb_gain_exp < 0)
+ {
+ if (sb_gain_exp > -32)
+ {
+ if (sb_gain_exp > -10)
+ {
+ *ptrReal = aux1 << (10 + sb_gain_exp);
+ *ptrImag = aux2 << (10 + sb_gain_exp);
+ }
+ else
+ {
+ *ptrReal = aux1 >> (-sb_gain_exp - 10);
+ *ptrImag = aux2 >> (-sb_gain_exp - 10);
+ }
+ }
+ }
+ else
+ {
+ *ptrReal = aux1 << (sb_gain_exp + 10);
+ *ptrImag = aux2 << (sb_gain_exp + 10);
+ }
+
+
+
+
+ /*
+ * if ( sb_noise != 0)
+ * {
+ * *ptrReal += sb_noise * rP[*phase_index][0];
+ * *ptrImag += sb_noise * rP[*phase_index][1];
+ * }
+ */
+ *phase_index = (*phase_index + 1) & 511;
+
+ if (!noNoiseFlag)
+ {
+
+ Int32 tmp = rPxx[*phase_index];
+ sb_noise_exp += 1;
+ tmp_q1 = fxp_mul32_by_16t(sb_noise_man, tmp);
+ tmp_q2 = fxp_mul32_by_16b(sb_noise_man, tmp);
+
+ if (sb_noise_exp < 0)
+ {
+ if (sb_noise_exp > -32)
+ {
+ if (sb_noise_exp > -10)
+ {
+ *ptrReal += tmp_q1 << (10 + sb_noise_exp);
+ *ptrImag += tmp_q2 << (10 + sb_noise_exp);
+ }
+ else
+ {
+ *ptrReal += tmp_q1 >> (-sb_noise_exp - 10);
+ *ptrImag += tmp_q2 >> (-sb_noise_exp - 10);
+ }
+ }
+ }
+ else
+ {
+ *ptrReal += tmp_q1 << (sb_noise_exp + 10);
+ *ptrImag += tmp_q2 << (sb_noise_exp + 10);
+ }
+ }
+
+ ptrReal++;
+ ptrImag++;
+
+
+ } /* for-loop (k) */
+
+
+ *harm_index = (*harm_index + 1) & 3;
+
+ /*
+ * Update smoothing filter history
+ */
+
+ if (filter_history++ < maxSmoothLength) /* no more update is needed as buffer will have same info */
+ {
+ /*
+ * mantissas
+ */
+
+ ptrReal = (Int32 *)fBuf_man[0];
+ ptrImag = (Int32 *)fBufN_man[0];
+
+ for (n = 0; n < maxSmoothLength; n++)
+ {
+ fBuf_man[n] = fBuf_man[n+1];
+ fBufN_man[n] = fBufN_man[n+1];
+ }
+
+ fBuf_man[maxSmoothLength] = ptrReal;
+ fBufN_man[maxSmoothLength] = ptrImag;
+
+ /*
+ * exponents
+ */
+ ptrReal = (Int32 *)fBuf_exp[0];
+ ptrImag = (Int32 *)fBufN_exp[0];
+
+ for (n = 0; n < maxSmoothLength; n++)
+ {
+ fBuf_exp[n] = fBuf_exp[n+1];
+ fBufN_exp[n] = fBufN_exp[n+1];
+ }
+
+ fBuf_exp[maxSmoothLength] = ptrReal;
+ fBufN_exp[maxSmoothLength] = ptrImag;
+ }
+
+ } /* for-loop (l) */
+
+ } /* if ( band_nrg_tone_detector) */
+
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void energy_estimation(Int32 *aBufR,
+ Int32 *aBufI,
+ Int32 *nrg_est_man,
+ Int32 *nrg_est_exp,
+ const Int32 *frame_info,
+ Int32 i,
+ Int32 k,
+ Int32 c,
+ Int32 ui2)
+{
+
+ Int32 aux1;
+ Int32 aux2;
+ Int32 l;
+
+
+
+ int64_t nrg_h = 0;
+ Int32 tmp1;
+ Int32 tmp2;
+
+ aux1 = aBufR[ui2*SBR_NUM_BANDS + k];
+ aux2 = aBufI[ui2*SBR_NUM_BANDS + k];
+ for (l = ui2 + 1; l < (frame_info[2+i] << 1); l++)
+ {
+ nrg_h = fxp_mac64_Q31(nrg_h, aux1, aux1);
+ nrg_h = fxp_mac64_Q31(nrg_h, aux2, aux2);
+ aux1 = aBufR[l*SBR_NUM_BANDS + k];
+ aux2 = aBufI[l*SBR_NUM_BANDS + k];
+ }
+ nrg_h = fxp_mac64_Q31(nrg_h, aux1, aux1);
+ nrg_h = fxp_mac64_Q31(nrg_h, aux2, aux2);
+
+
+ /*
+ * Check for overflow and saturate if needed
+ */
+ if (nrg_h < 0)
+ {
+ nrg_h = 0x7fffffff;
+ }
+
+ if (nrg_h)
+ {
+
+ aux1 = (UInt32)(nrg_h >> 32);
+ if (aux1)
+ {
+ aux2 = pv_normalize(aux1);
+ if (aux2)
+ {
+ aux2 -= 1; /* ensure Q30 */
+ nrg_h = (nrg_h << aux2) >> 33;
+ tmp2 = (UInt32)(nrg_h);
+ nrg_est_exp[c] = 33 - aux2;
+ }
+ else
+ {
+ tmp2 = (UInt32)(aux1 >> 1);
+ nrg_est_exp[c] = 33 ;
+
+
+ }
+ }
+ else
+ {
+ aux1 = (UInt32)(nrg_h >> 1);
+ aux2 = pv_normalize(aux1);
+
+ tmp2 = (aux1 << aux2);
+ nrg_est_exp[c] = -aux2 + 1;
+
+
+ }
+
+
+
+ tmp1 = (l - ui2);
+ aux2 = pow2[tmp1];
+ if (tmp1 == (tmp1 & (-tmp1)))
+ {
+ nrg_est_man[c] = tmp2 >> aux2;
+ }
+ else
+ {
+ nrg_est_man[c] = fxp_mul32_by_16(tmp2, aux2);
+ }
+ }
+ else
+ {
+ nrg_est_man[c] = 0;
+ nrg_est_exp[c] = -100;
+ }
+
+
+}
+
+
+
+
+
+#endif
+
+
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/aacdec/calc_sbr_envelope.h b/media/libstagefright/codecs/aacdec/calc_sbr_envelope.h
new file mode 100644
index 0000000..2a6ae57
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/calc_sbr_envelope.h
@@ -0,0 +1,144 @@
+/* ------------------------------------------------------------------
+ * 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: calc_sbr_envelope.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+ $Id: ct_envcalc.h,v 1.3 2002/11/29 16:11:49 kaehleof Exp $
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef CALCULATE_SBR_ENVELOPE_H
+#define CALCULATE_SBR_ENVELOPE_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "s_sbr_frame_data.h"
+#include "sbr_generate_high_freq.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void calc_sbr_envelope(SBR_FRAME_DATA *frameData,
+ Int32 *aBufR,
+ Int32 *aBufI,
+ Int freqBandTable1[2][MAX_FREQ_COEFFS + 1],
+ const Int32 *nSfb,
+ Int32 freqBandTable2[MAX_NOISE_COEFFS + 1],
+ Int32 nNBands,
+ Int32 reset,
+ Int32 *degreeAlias,
+ Int32 *harm_index,
+ Int32 *phase_index,
+ Int32 hFp[64],
+ Int32 *sUp,
+ Int32 limSbc[][13],
+ Int32 *gateMode,
+#ifdef HQ_SBR
+ Int32 *fBuf_man[64],
+ Int32 *fBuf_exp[64],
+ Int32 *fBufN_man[64],
+ Int32 *fBufN_exp[64],
+#endif
+ Int32 scratch_mem[][64],
+ struct PATCH Patch,
+ Int32 sqrt_cache[][4],
+ Int32 LC_flag);
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* CALCULATE_SBR_ENVELOPE_H */
+
+
diff --git a/media/libstagefright/codecs/aacdec/calc_sbr_synfilterbank.cpp b/media/libstagefright/codecs/aacdec/calc_sbr_synfilterbank.cpp
new file mode 100644
index 0000000..e557aa1
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/calc_sbr_synfilterbank.cpp
@@ -0,0 +1,639 @@
+/* ------------------------------------------------------------------
+ * 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: calc_sbr_synfilterbank.c
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+#ifdef AAC_PLUS
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "calc_sbr_synfilterbank.h"
+#include "qmf_filterbank_coeff.h"
+#include "synthesis_sub_band.h"
+#include "fxp_mul32.h"
+#include "aac_mem_funcs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+#if defined (PV_ARM_V5)
+
+
+__inline Int16 sat(Int32 y)
+{
+ Int32 x;
+ __asm
+ {
+ qdadd y, y, y
+ mov y, y, asr #16
+ }
+
+ return((Int16)y);
+}
+
+#define saturate2( a, b, c, d) *c = sat( a); \
+ *d = sat( b); \
+ c += 2; \
+ d -= 2;
+
+
+#elif defined (PV_ARM_V4)
+
+
+__inline Int16 sat(Int32 y)
+{
+ Int32 x;
+ Int32 z = 31; /* rvct compiler problem */
+ __asm
+ {
+ sub y, y, y, asr 2
+ mov y, y, asr N
+ mov x, y, asr #15
+ teq x, y, asr z
+ eorne y, INT16_MAX, y, asr #31
+ }
+
+ return((Int16)y);
+}
+
+#define saturate2( a, b, c, d) *c = sat( a); \
+ *d = sat( b); \
+ c += 2; \
+ d -= 2;
+
+#elif defined(PV_ARM_GCC_V5)
+
+__inline Int16 sat(Int32 y)
+{
+ register Int32 x;
+ register Int32 ra = y;
+
+
+ asm volatile(
+ "qdadd %0, %1, %1\n\t"
+ "mov %0, %0, asr #16"
+ : "=&r*i"(x)
+ : "r"(ra));
+
+ return ((Int16)x);
+}
+
+
+#define saturate2( a, b, c, d) *c = sat( a); \
+ *d = sat( b); \
+ c += 2; \
+ d -= 2;
+
+
+#elif defined(PV_ARM_MSC_EVC_V5)
+
+#include "armintr.h"
+
+#define saturate2( a, b, c, d) *c = _DAddSatInt( a, a)>>16; \
+ *d = _DAddSatInt( b, b)>>16; \
+ c += 2; \
+ d -= 2;
+
+#else
+
+
+#define saturate2( a, b, c, d) a -= (a>>2); \
+ a = (a>>N); \
+ if((a>>15) != (a>>31)) \
+ { \
+ a = ((a >> 31) ^ INT16_MAX); \
+ } \
+ *c = (Int16)a; \
+ c += 2; \
+ b -= (b>>2); \
+ b = (b>>N); \
+ if((b>>15) != (b>>31)) \
+ { \
+ b = ((b >> 31) ^ INT16_MAX); \
+ } \
+ *d = (Int16)b; \
+ d -= 2;
+
+
+#endif
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void calc_sbr_synfilterbank_LC(Int32 * Sr,
+ Int16 * timeSig,
+ Int16 V[1280],
+ bool bDownSampleSBR)
+{
+ Int32 i;
+
+ Int32 realAccu1;
+ Int32 realAccu2;
+ const Int32 *pt_C2;
+
+ Int16 *pt_V1;
+ Int16 *pt_V2;
+
+
+ Int16 *pt_timeSig;
+
+ Int16 *pt_timeSig_2;
+ Int32 test1;
+ Int16 tmp1;
+ Int16 tmp2;
+
+ /* shift filterstates */
+
+ Int32 * pt_Sr = Sr;
+
+
+ if (bDownSampleSBR == false)
+ {
+
+ synthesis_sub_band_LC(pt_Sr, V);
+
+ /* content of V[] is at most 16 bits */
+
+ pt_timeSig = &timeSig[0];
+ pt_timeSig_2 = &timeSig[64];
+
+
+ tmp1 = V[ 704];
+ tmp2 = V[ 768];
+ realAccu1 = fxp_mac_16_by_16(tmp1, Qfmt(0.853738560F), ROUND_SYNFIL);
+ realAccu1 = fxp_mac_16_by_16(tmp2, Qfmt(-0.361158990F), realAccu1);
+ tmp1 = -V[ 512];
+ tmp2 = V[ 960];
+ realAccu1 = fxp_mac_16_by_16(tmp1, Qfmt(-0.361158990F), realAccu1);
+ realAccu1 = fxp_mac_16_by_16(tmp2, Qfmt(0.070353307F), realAccu1);
+ tmp1 = V[ 448];
+ tmp2 = V[1024];
+ realAccu1 = fxp_mac_16_by_16(tmp1, Qfmt(0.070353307F), realAccu1);
+ realAccu1 = fxp_mac_16_by_16(tmp2, Qfmt(-0.013271822F), realAccu1);
+ tmp1 = -V[ 256];
+ tmp2 = V[ 192];
+ realAccu1 = fxp_mac_16_by_16(tmp1, Qfmt(-0.013271822F), realAccu1);
+ realAccu1 = fxp_mac_16_by_16(tmp2, Qfmt(0.002620176F), realAccu1);
+ realAccu1 = fxp_mac_16_by_16(V[1216], Qfmt(0.002620176F), realAccu1);
+
+ tmp1 = V[ 32];
+ tmp2 = V[1248];
+ realAccu2 = fxp_mac_16_by_16(tmp1, Qfmt(-0.000665042F), ROUND_SYNFIL);
+ realAccu2 = fxp_mac_16_by_16(tmp2, Qfmt(-0.000665042F), realAccu2);
+ tmp1 = V[ 224];
+ tmp2 = V[1056];
+ realAccu2 = fxp_mac_16_by_16(tmp1, Qfmt(0.005271576F), realAccu2);
+ realAccu2 = fxp_mac_16_by_16(tmp2, Qfmt(0.005271576F), realAccu2);
+ tmp1 = V[ 992];
+ tmp2 = V[ 288];
+ realAccu2 = fxp_mac_16_by_16(tmp1, Qfmt(0.058591568F), realAccu2);
+ realAccu2 = fxp_mac_16_by_16(tmp2, Qfmt(0.058591568F), realAccu2);
+ tmp1 = V[ 480];
+ tmp2 = V[ 800];
+ realAccu2 = fxp_mac_16_by_16(tmp1, Qfmt(-0.058370533F), realAccu2);
+ realAccu2 = fxp_mac_16_by_16(tmp2, Qfmt(-0.058370533F), realAccu2);
+ tmp1 = V[ 736];
+ tmp2 = V[ 544];
+ realAccu2 = fxp_mac_16_by_16(tmp1, Qfmt(0.702238872F), realAccu2);
+ realAccu2 = fxp_mac_16_by_16(tmp2, Qfmt(0.702238872F), realAccu2);
+
+
+
+ saturate2(realAccu1, realAccu2, pt_timeSig, pt_timeSig_2);
+
+ pt_timeSig_2 = &timeSig[126];
+
+ pt_V1 = &V[1];
+ pt_V2 = &V[1279];
+
+ pt_C2 = &sbrDecoderFilterbankCoefficients[0];
+
+ for (i = 31; i != 0; i--)
+ {
+ test1 = *(pt_C2++);
+ tmp1 = *(pt_V1++);
+ tmp2 = *(pt_V2--);
+ realAccu1 = fxp_mac_16_by_16_bt(tmp1 , test1, ROUND_SYNFIL);
+ realAccu2 = fxp_mac_16_by_16_bt(tmp2 , test1, ROUND_SYNFIL);
+ tmp1 = pt_V1[ 191];
+ tmp2 = pt_V2[ -191];
+ realAccu1 = fxp_mac_16_by_16_bb(tmp1, test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bb(tmp2, test1, realAccu2);
+
+ test1 = *(pt_C2++);
+ tmp1 = pt_V1[ 255];
+ tmp2 = pt_V2[ -255];
+ realAccu1 = fxp_mac_16_by_16_bt(tmp1 , test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bt(tmp2 , test1, realAccu2);
+ tmp1 = pt_V1[ 447];
+ tmp2 = pt_V2[ -447];
+ realAccu1 = fxp_mac_16_by_16_bb(tmp1, test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bb(tmp2, test1, realAccu2);
+
+ test1 = *(pt_C2++);
+ tmp1 = pt_V1[ 511];
+ tmp2 = pt_V2[ -511];
+ realAccu1 = fxp_mac_16_by_16_bt(tmp1 , test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bt(tmp2 , test1, realAccu2);
+ tmp1 = pt_V1[ 703];
+ tmp2 = pt_V2[ -703];
+ realAccu1 = fxp_mac_16_by_16_bb(tmp1, test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bb(tmp2, test1, realAccu2);
+
+ test1 = *(pt_C2++);
+ tmp1 = pt_V1[ 767];
+ tmp2 = pt_V2[ -767];
+ realAccu1 = fxp_mac_16_by_16_bt(tmp1 , test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bt(tmp2 , test1, realAccu2);
+ tmp1 = pt_V1[ 959];
+ tmp2 = pt_V2[ -959];
+ realAccu1 = fxp_mac_16_by_16_bb(tmp1, test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bb(tmp2, test1, realAccu2);
+
+ test1 = *(pt_C2++);
+ tmp1 = pt_V1[ 1023];
+ tmp2 = pt_V2[ -1023];
+ realAccu1 = fxp_mac_16_by_16_bt(tmp1 , test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bt(tmp2 , test1, realAccu2);
+ tmp1 = pt_V1[ 1215];
+ tmp2 = pt_V2[ -1215];
+ realAccu1 = fxp_mac_16_by_16_bb(tmp1, test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bb(tmp2, test1, realAccu2);
+
+ saturate2(realAccu1, realAccu2, pt_timeSig, pt_timeSig_2);
+
+ }
+ }
+ else
+ {
+
+ synthesis_sub_band_LC_down_sampled(Sr, V);
+
+ /*
+ * window signal
+ * calculate output samples
+ */
+
+
+ pt_V1 = &V[0];
+ pt_V2 = &V[96];
+
+
+ Int32 * pt_out = Sr;
+
+ for (i = 0; i < 8; i++)
+ {
+ *(pt_out++) = 0;
+ *(pt_out++) = 0;
+ *(pt_out++) = 0;
+ *(pt_out++) = 0;
+ }
+
+ const Int32* pt_C1 = &sbrDecoderFilterbankCoefficients_down_smpl[0];
+ pt_C2 = &sbrDecoderFilterbankCoefficients_down_smpl[16];
+
+ for (int k = 0; k < 5; k++)
+ {
+ pt_out -= 32;
+ for (i = 0; i < 16; i++)
+ {
+ realAccu1 = fxp_mul_16_by_16bt(*(pt_V1++), *(pt_C1));
+ realAccu2 = fxp_mul_16_by_16bb(*(pt_V1++), *(pt_C1++));
+ realAccu1 = fxp_mac_16_by_16_bt(*(pt_V2++), *(pt_C2), realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bb(*(pt_V2++), *(pt_C2++), realAccu2);
+ *(pt_out++) += realAccu1 >> 5;
+ *(pt_out++) += realAccu2 >> 5;
+
+ }
+ pt_V1 += 96;
+ pt_V2 += 96;
+ pt_C1 += 16;
+ pt_C2 += 16;
+ }
+ pt_out -= 32;
+
+ for (i = 0; i < 32; i++)
+ {
+ timeSig[2*i] = (Int16)((*(pt_out++) + 512) >> 10);
+ }
+
+ }
+
+}
+
+
+
+#ifdef HQ_SBR
+
+void calc_sbr_synfilterbank(Int32 * Sr,
+ Int32 * Si,
+ Int16 * timeSig,
+ Int16 V[1280],
+ bool bDownSampleSBR)
+{
+ Int32 i;
+
+ const Int32 *pt_C2;
+
+ Int32 realAccu1;
+ Int32 realAccu2;
+
+ Int16 *pt_V1;
+ Int16 *pt_V2;
+
+ Int16 *pt_timeSig;
+
+ Int16 *pt_timeSig_2;
+ Int32 test1;
+ Int16 tmp1;
+ Int16 tmp2;
+
+
+ if (bDownSampleSBR == false)
+ {
+ synthesis_sub_band(Sr, Si, V);
+
+ /* content of V[] is at most 16 bits */
+ pt_timeSig = &timeSig[0];
+ pt_timeSig_2 = &timeSig[64];
+
+ tmp1 = V[ 704];
+ tmp2 = V[ 768];
+ realAccu1 = fxp_mac_16_by_16(tmp1, Qfmt(0.853738560F), ROUND_SYNFIL);
+ realAccu1 = fxp_mac_16_by_16(tmp2, Qfmt(-0.361158990F), realAccu1);
+ tmp1 = -V[ 512];
+ tmp2 = V[ 960];
+ realAccu1 = fxp_mac_16_by_16(tmp1, Qfmt(-0.361158990F), realAccu1);
+ realAccu1 = fxp_mac_16_by_16(tmp2, Qfmt(0.070353307F), realAccu1);
+ tmp1 = V[ 448];
+ tmp2 = V[1024];
+ realAccu1 = fxp_mac_16_by_16(tmp1, Qfmt(0.070353307F), realAccu1);
+ realAccu1 = fxp_mac_16_by_16(tmp2, Qfmt(-0.013271822F), realAccu1);
+ tmp1 = -V[ 256];
+ tmp2 = V[ 192];
+ realAccu1 = fxp_mac_16_by_16(tmp1, Qfmt(-0.013271822F), realAccu1);
+ realAccu1 = fxp_mac_16_by_16(tmp2, Qfmt(0.002620176F), realAccu1);
+ realAccu1 = fxp_mac_16_by_16(V[1216], Qfmt(0.002620176F), realAccu1);
+
+ tmp1 = V[ 32];
+ tmp2 = V[1248];
+ realAccu2 = fxp_mac_16_by_16(tmp1, Qfmt(-0.000665042F), ROUND_SYNFIL);
+ realAccu2 = fxp_mac_16_by_16(tmp2, Qfmt(-0.000665042F), realAccu2);
+ tmp1 = V[ 224];
+ tmp2 = V[1056];
+ realAccu2 = fxp_mac_16_by_16(tmp1, Qfmt(0.005271576F), realAccu2);
+ realAccu2 = fxp_mac_16_by_16(tmp2, Qfmt(0.005271576F), realAccu2);
+ tmp1 = V[ 992];
+ tmp2 = V[ 288];
+ realAccu2 = fxp_mac_16_by_16(tmp1, Qfmt(0.058591568F), realAccu2);
+ realAccu2 = fxp_mac_16_by_16(tmp2, Qfmt(0.058591568F), realAccu2);
+ tmp1 = V[ 480];
+ tmp2 = V[ 800];
+ realAccu2 = fxp_mac_16_by_16(tmp1, Qfmt(-0.058370533F), realAccu2);
+ realAccu2 = fxp_mac_16_by_16(tmp2, Qfmt(-0.058370533F), realAccu2);
+ tmp1 = V[ 736];
+ tmp2 = V[ 544];
+ realAccu2 = fxp_mac_16_by_16(tmp1, Qfmt(0.702238872F), realAccu2);
+ realAccu2 = fxp_mac_16_by_16(tmp2, Qfmt(0.702238872F), realAccu2);
+
+
+ saturate2(realAccu1, realAccu2, pt_timeSig, pt_timeSig_2);
+
+ pt_timeSig_2 = &timeSig[126];
+
+ pt_V1 = &V[1];
+ pt_V2 = &V[1279];
+
+ pt_C2 = &sbrDecoderFilterbankCoefficients[0];
+
+ for (i = 31; i != 0; i--)
+ {
+ test1 = *(pt_C2++);
+ tmp1 = *(pt_V1++);
+ tmp2 = *(pt_V2--);
+ realAccu1 = fxp_mac_16_by_16_bt(tmp1 , test1, ROUND_SYNFIL);
+ realAccu2 = fxp_mac_16_by_16_bt(tmp2 , test1, ROUND_SYNFIL);
+ tmp1 = pt_V1[ 191];
+ tmp2 = pt_V2[ -191];
+ realAccu1 = fxp_mac_16_by_16_bb(tmp1, test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bb(tmp2, test1, realAccu2);
+
+ test1 = *(pt_C2++);
+ tmp1 = pt_V1[ 255];
+ tmp2 = pt_V2[ -255];
+ realAccu1 = fxp_mac_16_by_16_bt(tmp1 , test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bt(tmp2 , test1, realAccu2);
+ tmp1 = pt_V1[ 447];
+ tmp2 = pt_V2[ -447];
+ realAccu1 = fxp_mac_16_by_16_bb(tmp1, test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bb(tmp2, test1, realAccu2);
+
+ test1 = *(pt_C2++);
+ tmp1 = pt_V1[ 511];
+ tmp2 = pt_V2[ -511];
+ realAccu1 = fxp_mac_16_by_16_bt(tmp1 , test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bt(tmp2 , test1, realAccu2);
+ tmp1 = pt_V1[ 703];
+ tmp2 = pt_V2[ -703];
+ realAccu1 = fxp_mac_16_by_16_bb(tmp1, test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bb(tmp2, test1, realAccu2);
+
+ test1 = *(pt_C2++);
+ tmp1 = pt_V1[ 767];
+ tmp2 = pt_V2[ -767];
+ realAccu1 = fxp_mac_16_by_16_bt(tmp1 , test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bt(tmp2 , test1, realAccu2);
+ tmp1 = pt_V1[ 959];
+ tmp2 = pt_V2[ -959];
+ realAccu1 = fxp_mac_16_by_16_bb(tmp1, test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bb(tmp2, test1, realAccu2);
+
+ test1 = *(pt_C2++);
+ tmp1 = pt_V1[ 1023];
+ tmp2 = pt_V2[ -1023];
+ realAccu1 = fxp_mac_16_by_16_bt(tmp1 , test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bt(tmp2 , test1, realAccu2);
+ tmp1 = pt_V1[ 1215];
+ tmp2 = pt_V2[ -1215];
+ realAccu1 = fxp_mac_16_by_16_bb(tmp1, test1, realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bb(tmp2, test1, realAccu2);
+
+ saturate2(realAccu1, realAccu2, pt_timeSig, pt_timeSig_2);
+ }
+
+ }
+ else
+ {
+
+ synthesis_sub_band_down_sampled(Sr, Si, V);
+
+
+ Int32 * pt_out = Sr;
+
+ for (i = 0; i < 8; i++)
+ {
+ *(pt_out++) = 0;
+ *(pt_out++) = 0;
+ *(pt_out++) = 0;
+ *(pt_out++) = 0;
+ }
+
+
+ /*
+ * window signal
+ * calculate output samples
+ */
+
+ pt_V1 = &V[0];
+ pt_V2 = &V[96];
+
+
+ const Int32* pt_C1 = &sbrDecoderFilterbankCoefficients_down_smpl[0];
+ pt_C2 = &sbrDecoderFilterbankCoefficients_down_smpl[16];
+
+ for (Int k = 0; k < 5; k++)
+ {
+ pt_out -= 32;
+ for (i = 0; i < 16; i++)
+ {
+ realAccu1 = fxp_mul_16_by_16bt(*(pt_V1++), *(pt_C1));
+ realAccu2 = fxp_mul_16_by_16bb(*(pt_V1++), *(pt_C1++));
+ realAccu1 = fxp_mac_16_by_16_bt(*(pt_V2++), *(pt_C2), realAccu1);
+ realAccu2 = fxp_mac_16_by_16_bb(*(pt_V2++), *(pt_C2++), realAccu2);
+ *(pt_out++) += realAccu1 >> 5;
+ *(pt_out++) += realAccu2 >> 5;
+ }
+ pt_V1 += 96;
+ pt_V2 += 96;
+ pt_C1 += 16;
+ pt_C2 += 16;
+ }
+ pt_out -= 32;
+
+ for (i = 0; i < 32; i++)
+ {
+ timeSig[2*i] = (Int16)((*(pt_out++) + 512) >> 10);
+ }
+
+ }
+}
+
+
+#endif /* --- HQ_SBR --- */
+
+
+#endif /* --- AAC_PLUS --- */
+
+
+
diff --git a/media/libstagefright/codecs/aacdec/calc_sbr_synfilterbank.h b/media/libstagefright/codecs/aacdec/calc_sbr_synfilterbank.h
new file mode 100644
index 0000000..28bd6de
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/calc_sbr_synfilterbank.h
@@ -0,0 +1,94 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef CALC_SBR_SYNFILTERBANK_H
+#define CALC_SBR_SYNFILTERBANK_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define N 14
+
+#define ROUND_SYNFIL (32768 + 4096)
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ void calc_sbr_synfilterbank_LC(Int32 * Sr,
+ Int16 * timeSig,
+ Int16 V[1280],
+ bool bDownSampleSBR);
+
+#ifdef HQ_SBR
+
+
+ void calc_sbr_synfilterbank(Int32 * Sr,
+ Int32 * Si,
+ Int16 * timeSig,
+ Int16 V[1280],
+ bool bDownSampleSBR);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/chans.h b/media/libstagefright/codecs/aacdec/chans.h
new file mode 100644
index 0000000..325b5cd
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/chans.h
@@ -0,0 +1,107 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: chans.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed file in the correct template format.
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef CHANS_H
+#define CHANS_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+ /* #define is required in order to use these args in #if () directive */
+#define ICChans 0
+#define DCChans 0
+#define XCChans 0
+#define CChans 0
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ enum
+ {
+ /*
+ * channels for 5.1 main profile configuration
+ * (modify for any desired decoder configuration)
+ */
+ FChans = 2, /* front channels: left, center, right */
+ FCenter = 0, /* 1 if decoder has front center channel */
+ SChans = 0, /* side channels: */
+ BChans = 0, /* back channels: left surround, right surround */
+ BCenter = 0, /* 1 if decoder has back center channel */
+ LChans = 0, /* LFE channels */
+ XChans = 0, /* scratch space for parsing unused channels */
+
+ Chans = FChans + SChans + BChans + LChans + XChans
+ };
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CHANS_H */
+
diff --git a/media/libstagefright/codecs/aacdec/check_crc.cpp b/media/libstagefright/codecs/aacdec/check_crc.cpp
new file mode 100644
index 0000000..17f3b87
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/check_crc.cpp
@@ -0,0 +1,144 @@
+/* ------------------------------------------------------------------
+ * 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: check_crc.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ INPUT
+
+
+ OUTPUT
+
+ errorCode, noError if successful
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "check_crc.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void check_crc(HANDLE_CRC hCrcBuf, UInt32 bValue, Int32 nBits)
+{
+ Int32 i;
+ UInt32 bMask = (1UL << (nBits - 1));
+
+ for (i = 0; i < nBits; i++, bMask >>= 1)
+ {
+ UInt16 flag = (UInt16)((hCrcBuf->crcState & hCrcBuf->crcMask) ? 1 : 0);
+ UInt16 flag1 = (UInt16)((bMask & bValue) ? 1 : 0);
+
+ flag ^= flag1;
+ hCrcBuf->crcState <<= 1;
+ if (flag)
+ hCrcBuf->crcState ^= hCrcBuf->crcPoly;
+ }
+
+}
+
diff --git a/media/libstagefright/codecs/aacdec/check_crc.h b/media/libstagefright/codecs/aacdec/check_crc.h
new file mode 100644
index 0000000..9293d47
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/check_crc.h
@@ -0,0 +1,124 @@
+/* ------------------------------------------------------------------
+ * 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: check_crc.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+ $Id: ct_envcalc.h,v 1.3 2002/11/29 16:11:49 kaehleof Exp $
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef CHECK_CRC_H
+#define CHECK_CRC_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_crc_buffer.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void check_crc(HANDLE_CRC hCrcBuf,
+ UInt32 bValue,
+ Int32 nBits);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/dct16.cpp b/media/libstagefright/codecs/aacdec/dct16.cpp
new file mode 100644
index 0000000..75bd4ba
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/dct16.cpp
@@ -0,0 +1,266 @@
+/* ------------------------------------------------------------------
+ * 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: dct16.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 x 32-bit integer input length 16
+
+ Int32 flag 1 forward dct16, 0 modified dct-16
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement dct of lenght 16
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#include "dct16.h"
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define Qfmt_31(a) (Int32)(a*0x7FFFFFFF + (a>=0?0.5F:-0.5F))
+
+#define Qfmt15(x) (Int16)(x*((Int32)1<<15) + (x>=0?0.5F:-0.5F))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void dct_16(Int32 vec[], Int flag)
+{
+ Int32 tmp0;
+ Int32 tmp1;
+ Int32 tmp2;
+ Int32 tmp3;
+ Int32 tmp4;
+ Int32 tmp5;
+ Int32 tmp6;
+ Int32 tmp7;
+ Int32 tmp_o0;
+ Int32 tmp_o1;
+ Int32 tmp_o2;
+ Int32 tmp_o3;
+ Int32 tmp_o4;
+ Int32 tmp_o5;
+ Int32 tmp_o6;
+ Int32 tmp_o7;
+ Int32 itmp_e0;
+ Int32 itmp_e1;
+ Int32 itmp_e2;
+
+ /* split input vector */
+
+
+ tmp_o0 = fxp_mul32_by_16((vec[ 0] - vec[15]), Qfmt15(0.50241928618816F));
+ tmp0 = vec[ 0] + vec[15];
+
+ tmp_o7 = fxp_mul32_Q31((vec[ 7] - vec[ 8]) << 3, Qfmt_31(0.63764357733614F));
+ tmp7 = vec[ 7] + vec[ 8];
+
+ itmp_e0 = (tmp0 + tmp7);
+ tmp7 = fxp_mul32_by_16((tmp0 - tmp7), Qfmt15(0.50979557910416F));
+
+ tmp_o1 = fxp_mul32_by_16((vec[ 1] - vec[14]), Qfmt15(0.52249861493969F));
+ tmp1 = vec[ 1] + vec[14];
+ tmp_o6 = fxp_mul32_by_16((vec[ 6] - vec[ 9]) << 1, Qfmt15(0.86122354911916F));
+ tmp6 = vec[ 6] + vec[ 9];
+
+ itmp_e1 = (tmp1 + tmp6);
+ tmp6 = fxp_mul32_by_16((tmp1 - tmp6), Qfmt15(0.60134488693505F));
+
+ tmp_o2 = fxp_mul32_by_16((vec[ 2] - vec[13]), Qfmt15(0.56694403481636F));
+ tmp2 = vec[ 2] + vec[13];
+ tmp_o5 = fxp_mul32_by_16((vec[ 5] - vec[10]) << 1, Qfmt15(0.53033884299517F));
+ tmp5 = vec[ 5] + vec[10];
+
+ itmp_e2 = (tmp2 + tmp5);
+ tmp5 = fxp_mul32_by_16((tmp2 - tmp5), Qfmt15(0.89997622313642F));
+
+ tmp_o3 = fxp_mul32_by_16((vec[ 3] - vec[12]), Qfmt15(0.64682178335999F));
+ tmp3 = vec[ 3] + vec[12];
+ tmp_o4 = fxp_mul32_by_16((vec[ 4] - vec[11]), Qfmt15(0.78815462345125F));
+ tmp4 = vec[ 4] + vec[11];
+
+ tmp1 = (tmp3 + tmp4);
+ tmp4 = fxp_mul32_Q31((tmp3 - tmp4) << 2, Qfmt_31(0.64072886193538F));
+
+ /* split even part of tmp_e */
+
+ tmp0 = (itmp_e0 + tmp1);
+ tmp1 = fxp_mul32_by_16((itmp_e0 - tmp1), Qfmt15(0.54119610014620F));
+
+
+ tmp3 = fxp_mul32_by_16((itmp_e1 - itmp_e2) << 1, Qfmt15(0.65328148243819F));
+ tmp2 = (itmp_e1 + itmp_e2);
+
+ vec[ 0] = (tmp0 + tmp2) >> 1;
+ vec[ 8] = fxp_mul32_by_16((tmp0 - tmp2), Qfmt15(0.70710678118655F));
+ vec[12] = fxp_mul32_by_16((tmp1 - tmp3) << 1, Qfmt15(0.70710678118655F));
+ vec[ 4] = tmp1 + tmp3;
+ vec[ 4] += vec[12];
+
+ /* split odd part of tmp_e */
+
+ tmp1 = fxp_mul32_by_16((tmp7 - tmp4) << 1, Qfmt15(0.54119610014620F));
+ tmp7 += tmp4;
+ tmp3 = fxp_mul32_Q31((tmp6 - tmp5) << 2, Qfmt_31(0.65328148243819F));
+
+ tmp6 += tmp5;
+
+ vec[10] = fxp_mul32_by_16((tmp7 - tmp6) << 1, Qfmt15(0.70710678118655F));
+ vec[ 2] = tmp7 + tmp6;
+ vec[14] = fxp_mul32_by_16((tmp1 - tmp3) << 1, Qfmt15(0.70710678118655F));
+
+ tmp1 += tmp3 + vec[14];
+ vec[ 2] += tmp1;
+ vec[ 6] = tmp1 + vec[10];
+
+ vec[10] += vec[14];
+
+
+ // dct8;
+
+ tmp7 = tmp_o0 + tmp_o7;
+ tmp_o7 = fxp_mul32_by_16((tmp_o0 - tmp_o7) << 1, Qfmt15(0.50979557910416F));
+
+ tmp6 = tmp_o1 + tmp_o6;
+ tmp_o1 = fxp_mul32_by_16((tmp_o1 - tmp_o6) << 1, Qfmt15(0.60134488693505F));
+
+ tmp5 = tmp_o2 + tmp_o5;
+ tmp_o5 = fxp_mul32_by_16((tmp_o2 - tmp_o5) << 1, Qfmt15(0.89997622313642F));
+
+ tmp4 = tmp_o3 + tmp_o4;
+
+ tmp_o3 = fxp_mul32_Q31((tmp_o3 - tmp_o4) << 3, Qfmt_31(0.6407288619354F));
+
+ if (!flag)
+ {
+ tmp7 = -tmp7;
+ tmp_o7 = -tmp_o7;
+ tmp6 = -tmp6;
+ tmp_o1 = -tmp_o1;
+ tmp5 = -tmp5;
+ tmp_o5 = -tmp_o5;
+ tmp4 = -tmp4;
+ tmp_o3 = -tmp_o3;
+ }
+
+ // even part
+
+ tmp1 = fxp_mul32_by_16((tmp7 - tmp4) << 1, Qfmt15(0.54119610014620F));
+ tmp0 = tmp7 + tmp4;
+ tmp3 = fxp_mul32_Q31((tmp6 - tmp5) << 2, Qfmt_31(0.65328148243819F));
+ tmp2 = tmp6 + tmp5;
+
+ vec[ 9] = fxp_mul32_Q31((tmp0 - tmp2) << 1, Qfmt_31(0.70710678118655F));
+ vec[ 1] = tmp0 + tmp2;
+ vec[13] = fxp_mul32_Q31((tmp1 - tmp3) << 1, Qfmt_31(0.70710678118655F));
+
+ vec[ 5] = tmp1 + tmp3 + vec[13];
+
+ // odd part
+
+ tmp0 = tmp_o7 + tmp_o3;
+ tmp1 = fxp_mul32_by_16((tmp_o7 - tmp_o3) << 1, Qfmt15(0.54119610014620F));
+ tmp2 = tmp_o1 + tmp_o5;
+ tmp3 = fxp_mul32_Q31((tmp_o1 - tmp_o5) << 2, Qfmt_31(0.65328148243819F));
+
+ vec[11] = fxp_mul32_Q31((tmp0 - tmp2) << 1, Qfmt_31(0.70710678118655F));
+ vec[ 3] = tmp0 + tmp2;
+ vec[15] = fxp_mul32_Q31((tmp1 - tmp3) << 1, Qfmt_31(0.70710678118655F));
+ vec[ 7] = tmp1 + tmp3 + vec[15];
+
+
+ vec[ 3] += vec[ 7];
+ vec[ 7] += vec[11];
+ vec[11] += vec[15];
+
+ vec[ 1] += vec[ 3];
+ vec[ 3] += vec[ 5];
+ vec[ 5] += vec[ 7];
+ vec[ 7] += vec[ 9];
+ vec[ 9] += vec[11];
+ vec[11] += vec[13];
+ vec[13] += vec[15];
+
+
+}
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/dct16.h b/media/libstagefright/codecs/aacdec/dct16.h
new file mode 100644
index 0000000..6f8fcb2
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/dct16.h
@@ -0,0 +1,68 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./c/include/dct16.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef DCT16_H
+#define DCT16_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ void dct_16(Int32 vec[], Int flag);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DCT16_H */
diff --git a/media/libstagefright/codecs/aacdec/dct64.cpp b/media/libstagefright/codecs/aacdec/dct64.cpp
new file mode 100644
index 0000000..a21a814
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/dct64.cpp
@@ -0,0 +1,569 @@
+/* ------------------------------------------------------------------
+ * 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: dct64.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 x 32-bit integer input length 64
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement dct of lenght 64
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "dct16.h"
+#include "dct64.h"
+
+#include "pv_audio_type_defs.h"
+#include "synthesis_sub_band.h"
+
+#include "fxp_mul32.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define Qfmt(a) (Int32)(a*((Int32)1<<26) + (a>=0?0.5F:-0.5F))
+#define Qfmt31(a) (Int32)(a*0x7FFFFFFF)
+
+const Int32 CosTable_48[48] =
+{
+ Qfmt31(0.50015063602065F) , Qfmt31(0.50135845244641F) ,
+ Qfmt31(0.50378872568104F) , Qfmt31(0.50747117207256F) ,
+ Qfmt31(0.51245147940822F) , Qfmt31(0.51879271310533F) ,
+ Qfmt31(0.52657731515427F) , Qfmt31(0.53590981690799F) ,
+ Qfmt31(0.54692043798551F) , Qfmt31(0.55976981294708F) ,
+ Qfmt31(0.57465518403266F) , Qfmt31(0.59181853585742F) ,
+ Qfmt31(0.61155734788251F) , Qfmt31(0.63423893668840F) ,
+ Qfmt31(0.66031980781371F) , Qfmt31(0.69037212820021F) ,
+ Qfmt31(0.72512052237720F) , Qfmt31(0.76549416497309F) ,
+ Qfmt31(0.81270209081449F) , Qfmt31(0.86834471522335F) ,
+ Qfmt(0.93458359703641F) , Qfmt(1.01440826499705F) ,
+ Qfmt(1.11207162057972F) , Qfmt(1.23383273797657F) ,
+ Qfmt(1.38929395863283F) , Qfmt(1.59397228338563F) ,
+ Qfmt(1.87467598000841F) , Qfmt(2.28205006800516F) ,
+ Qfmt(2.92462842815822F) , Qfmt(4.08461107812925F) ,
+ Qfmt(6.79675071167363F) , Qfmt(20.37387816723145F) , /* 32 */
+ Qfmt(0.50060299823520F) , Qfmt(0.50547095989754F) ,
+ Qfmt(0.51544730992262F) , Qfmt(0.53104259108978F) ,
+ Qfmt(0.55310389603444F) , Qfmt(0.58293496820613F) ,
+ Qfmt(0.62250412303566F) , Qfmt(0.67480834145501F) ,
+ Qfmt(0.74453627100230F) , Qfmt(0.83934964541553F) ,
+ Qfmt(0.97256823786196F) , Qfmt(1.16943993343288F) ,
+ Qfmt(1.48416461631417F) , Qfmt(2.05778100995341F) ,
+ Qfmt(3.40760841846872F) , Qfmt(10.19000812354803F)
+};
+
+
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; dct_64
+----------------------------------------------------------------------------*/
+
+void pv_split_LC(Int32 *vector,
+ Int32 *temp_o)
+{
+
+ Int32 i;
+ Int32 *pt_vector = &vector[0];
+ Int32 *pt_vector_N_1 = &vector[31];
+ const Int32 *pt_cosTerms = &CosTable_48[32];
+ Int32 *pt_temp_o = temp_o;
+ Int32 tmp1;
+ Int32 tmp2;
+ Int32 tmp3;
+
+
+ tmp1 = *(pt_vector);
+ tmp2 = *(pt_vector_N_1--);
+ for (i = 16; i != 0; i--)
+ {
+ tmp3 = *(pt_cosTerms++);
+ *(pt_vector++) = tmp1 + tmp2;
+ *(pt_temp_o++) = fxp_mul32_Q26((tmp1 - tmp2), tmp3);
+ tmp1 = *(pt_vector);
+ tmp2 = *(pt_vector_N_1--);
+ }
+
+}
+
+
+#ifdef HQ_SBR
+
+
+void dct_64(Int32 vec[], Int32 *scratch_mem)
+{
+ Int32 *temp_e1;
+ Int32 *temp_o1;
+
+ Int32 *pt_vec;
+
+ Int i;
+
+ Int32 aux1;
+ Int32 aux2;
+ Int32 aux3;
+ Int32 aux4;
+
+ const Int32 *cosTerms = &CosTable_48[31];
+
+ temp_o1 = &vec[32];
+ temp_e1 = temp_o1 - 1;
+
+
+ for (i = 6; i != 0; i--)
+ {
+ aux1 = *(temp_e1);
+ aux2 = *(temp_o1);
+ aux3 = *(cosTerms--);
+ *(temp_e1--) = aux1 + aux2;
+ *(temp_o1++) = fxp_mul32_Q26((aux1 - aux2), aux3);
+ aux1 = *(temp_e1);
+ aux2 = *(temp_o1);
+ aux3 = *(cosTerms--);
+ *(temp_e1--) = aux1 + aux2;
+ *(temp_o1++) = fxp_mul32_Q26((aux1 - aux2), aux3);
+ }
+
+
+ for (i = 10; i != 0; i--)
+ {
+ aux1 = *(temp_e1);
+ aux2 = *(temp_o1);
+ aux3 = *(cosTerms--);
+ *(temp_e1--) = aux1 + aux2;
+ *(temp_o1++) = fxp_mul32_Q31((aux1 - aux2), aux3) << 1;
+ aux1 = *(temp_e1);
+ aux2 = *(temp_o1);
+ aux3 = *(cosTerms--);
+ *(temp_e1--) = aux1 + aux2;
+ *(temp_o1++) = fxp_mul32_Q31((aux1 - aux2), aux3) << 1;
+ }
+
+
+ pv_split(&vec[16]);
+
+ dct_16(&vec[16], 0);
+ dct_16(vec, 1); // Even terms
+
+ pv_merge_in_place_N32(vec);
+
+ pv_split_z(&vec[32]);
+
+ dct_16(&vec[32], 1); // Even terms
+ dct_16(&vec[48], 0);
+
+ pv_merge_in_place_N32(&vec[32]);
+
+
+
+ aux1 = vec[32];
+ aux3 = vec[33];
+ aux4 = vec[ 1]; /* vec[ 1] */
+
+ /* -----------------------------------*/
+ aux1 = vec[32] + vec[33];
+ vec[ 0] += aux1;
+ vec[ 1] += aux1;
+
+ aux1 = vec[34];
+ aux2 = vec[ 2]; /* vec[ 2] */
+ aux3 += aux1;
+ vec[ 2] = aux4 + aux3;
+ aux4 = vec[ 3]; /* vec[ 3] */
+ vec[ 3] = aux2 + aux3;
+
+ aux3 = vec[35];
+
+ /* -----------------------------------*/
+ aux1 += aux3;
+ vec[32] = vec[ 4];
+ vec[33] = vec[ 5];
+ vec[ 4] = aux2 + aux1;
+ vec[ 5] = aux4 + aux1;
+
+ aux1 = vec[36];
+ aux2 = vec[32]; /* vec[ 4] */
+ aux3 += aux1;
+ vec[34] = vec[ 6];
+ vec[35] = vec[ 7];
+ vec[ 6] = aux4 + aux3;
+ vec[ 7] = aux2 + aux3;
+
+ aux3 = vec[37];
+ aux4 = vec[33]; /* vec[ 5] */
+
+ /* -----------------------------------*/
+ aux1 += aux3;
+ vec[32] = vec[ 8];
+ vec[33] = vec[ 9];
+ vec[ 8] = aux2 + aux1;
+ vec[ 9] = aux4 + aux1;
+
+ aux1 = vec[38];
+ aux2 = vec[34]; /* vec[ 6] */
+ aux3 += aux1;
+ vec[34] = vec[10];
+ vec[10] = aux4 + aux3;
+ aux4 = vec[35]; /* vec[ 7] */
+ vec[35] = vec[11];
+ vec[11] = aux2 + aux3;
+
+ aux3 = vec[39];
+
+ /* -----------------------------------*/
+ aux1 += aux3;
+ vec[36] = vec[12];
+ vec[37] = vec[13];
+ vec[12] = aux2 + aux1;
+ vec[13] = aux4 + aux1;
+
+ aux1 = vec[40];
+ aux2 = vec[32]; /* vec[ 8] */
+ aux3 += aux1;
+ vec[32] = vec[14];
+ vec[14] = aux4 + aux3;
+ aux4 = vec[33]; /* vec[ 9] */
+ vec[33] = vec[15];
+ vec[15] = aux2 + aux3;
+
+ aux3 = vec[41];
+
+ /* -----------------------------------*/
+ aux1 += aux3;
+ vec[38] = vec[16];
+ vec[39] = vec[17];
+ vec[16] = aux2 + aux1;
+ vec[17] = aux4 + aux1;
+
+ aux1 = vec[42];
+ aux2 = vec[34]; /* vec[10] */
+ aux3 += aux1;
+ vec[34] = vec[18];
+ vec[18] = aux4 + aux3;
+ aux4 = vec[35]; /* vec[11] */
+ vec[35] = vec[19];
+ vec[19] = aux2 + aux3;
+
+ aux3 = vec[43];
+
+ /* -----------------------------------*/
+ aux1 += aux3;
+ vec[40] = vec[20];
+ vec[41] = vec[21];
+ vec[20] = aux2 + aux1;
+ vec[21] = aux4 + aux1;
+
+ aux1 = vec[44];
+ aux2 = vec[36]; /* vec[12] */
+ aux3 += aux1;
+ vec[42] = vec[22];
+ vec[43] = vec[23];
+ vec[22] = aux4 + aux3;
+ vec[23] = aux2 + aux3;
+
+ aux3 = vec[45];
+ aux4 = vec[37]; /* vec[13] */
+
+ /* -----------------------------------*/
+
+
+ scratch_mem[0] = vec[24];
+ scratch_mem[1] = vec[25];
+ aux1 += aux3;
+ vec[24] = aux2 + aux1;
+ vec[25] = aux4 + aux1;
+
+ aux1 = vec[46];
+ aux2 = vec[32]; /* vec[14] */
+ scratch_mem[2] = vec[26];
+ scratch_mem[3] = vec[27];
+ aux3 += aux1;
+ vec[26] = aux4 + aux3;
+ vec[27] = aux2 + aux3;
+
+ aux3 = vec[47];
+ aux4 = vec[33]; /* vec[15] */
+
+ /* -----------------------------------*/
+ scratch_mem[4] = vec[28];
+ scratch_mem[5] = vec[29];
+ aux1 += aux3;
+ vec[28] = aux2 + aux1;
+ vec[29] = aux4 + aux1;
+
+ aux1 = vec[48];
+ aux2 = vec[38]; /* vec[16] */
+ scratch_mem[6] = vec[30];
+ scratch_mem[7] = vec[31];
+ aux3 += aux1;
+ vec[30] = aux4 + aux3;
+ vec[31] = aux2 + aux3;
+
+ aux3 = vec[49];
+ aux4 = vec[39]; /* vec[17] */
+
+ /* -----------------------------------*/
+ aux1 += aux3;
+ vec[32] = aux2 + aux1;
+ vec[33] = aux4 + aux1;
+
+ aux1 = vec[50];
+ aux2 = vec[34]; /* vec[18] */
+ aux3 += aux1;
+ vec[34] = aux4 + aux3;
+ aux4 = vec[35]; /* vec[19] */
+ vec[35] = aux2 + aux3;
+
+ aux3 = vec[51];
+
+
+ /* -----------------------------------*/
+ aux1 += aux3;
+ vec[36] = aux2 + aux1;
+ vec[37] = aux4 + aux1;
+
+ aux1 = vec[52];
+ aux2 = vec[40]; /* vec[20] */
+ aux3 += aux1;
+ vec[38] = aux4 + aux3;
+ vec[39] = aux2 + aux3;
+
+ aux3 = vec[53];
+ aux4 = vec[41]; /* vec[21] */
+
+ /* -----------------------------------*/
+ aux1 += aux3;
+ vec[40] = aux2 + aux1;
+ vec[41] = aux4 + aux1;
+
+ aux1 = vec[54];
+ aux2 = vec[42]; /* vec[22] */
+ aux3 += aux1;
+ vec[42] = aux4 + aux3;
+ aux4 = vec[43]; /* vec[23] */
+ vec[43] = aux2 + aux3;
+
+ aux3 = vec[55];
+
+ /* -----------------------------------*/
+
+ pt_vec = &vec[44];
+ temp_o1 = &vec[56];
+ temp_e1 = &scratch_mem[0];
+
+ for (i = 4; i != 0; i--)
+ {
+ aux1 += aux3;
+ *(pt_vec++) = aux2 + aux1;
+ *(pt_vec++) = aux4 + aux1;
+
+ aux1 = *(temp_o1++);
+ aux3 += aux1;
+ aux2 = *(temp_e1++);
+ *(pt_vec++) = aux4 + aux3;
+ *(pt_vec++) = aux2 + aux3;
+
+ aux3 = *(temp_o1++);
+ aux4 = *(temp_e1++);
+ }
+
+ aux1 += aux3;
+ vec[60] = aux2 + aux1;
+ vec[61] = aux4 + aux1;
+ vec[62] = aux4 + aux3;
+
+}
+
+
+#endif
+
+/*----------------------------------------------------------------------------
+; pv_split
+----------------------------------------------------------------------------*/
+
+
+void pv_split(Int32 *temp_o)
+{
+
+ Int32 i;
+ const Int32 *pt_cosTerms = &CosTable_48[47];
+ Int32 *pt_temp_o = temp_o;
+ Int32 *pt_temp_e = pt_temp_o - 1;
+ Int32 tmp1;
+ Int32 tmp2;
+ Int32 cosx;
+
+ for (i = 8; i != 0; i--)
+ {
+ tmp2 = *(pt_temp_o);
+ tmp1 = *(pt_temp_e);
+ cosx = *(pt_cosTerms--);
+ *(pt_temp_e--) = tmp1 + tmp2;
+ *(pt_temp_o++) = fxp_mul32_Q26((tmp1 - tmp2), cosx);
+ tmp1 = *(pt_temp_e);
+ tmp2 = *(pt_temp_o);
+ cosx = *(pt_cosTerms--);
+ *(pt_temp_e--) = tmp1 + tmp2;
+ *(pt_temp_o++) = fxp_mul32_Q26((tmp1 - tmp2), cosx);
+ }
+}
+
+
+
+void pv_split_z(Int32 *vector)
+{
+ Int32 i;
+ Int32 *pt_vector = &vector[31];
+ const Int32 *pt_cosTerms = &CosTable_48[32];
+ Int32 *pt_temp_e = vector;
+ Int32 tmp1;
+ Int32 tmp2;
+ Int32 cosx;
+
+ for (i = 8; i != 0; i--)
+ {
+ tmp1 = *(pt_vector);
+ tmp2 = *(pt_temp_e);
+ cosx = *(pt_cosTerms++);
+ *(pt_temp_e++) = tmp1 + tmp2;
+ *(pt_vector--) = fxp_mul32_Q26((tmp1 - tmp2), cosx);
+ tmp2 = *(pt_temp_e);
+ tmp1 = *(pt_vector);
+ cosx = *(pt_cosTerms++);
+ *(pt_temp_e++) = tmp1 + tmp2;
+ *(pt_vector--) = fxp_mul32_Q26((tmp1 - tmp2), cosx);
+ }
+}
+
+
+void pv_merge_in_place_N32(Int32 vec[])
+{
+
+ Int32 temp[4];
+
+ temp[0] = vec[14];
+ vec[14] = vec[ 7];
+ temp[1] = vec[12];
+ vec[12] = vec[ 6];
+ temp[2] = vec[10];
+ vec[10] = vec[ 5];
+ temp[3] = vec[ 8];
+ vec[ 8] = vec[ 4];
+ vec[ 6] = vec[ 3];
+ vec[ 4] = vec[ 2];
+ vec[ 2] = vec[ 1];
+
+ vec[ 1] = vec[16] + vec[17];
+ vec[16] = temp[3];
+ vec[ 3] = vec[18] + vec[17];
+ vec[ 5] = vec[19] + vec[18];
+ vec[18] = vec[9];
+ temp[3] = vec[11];
+
+ vec[ 7] = vec[20] + vec[19];
+ vec[ 9] = vec[21] + vec[20];
+ vec[20] = temp[2];
+ temp[2] = vec[13];
+ vec[11] = vec[22] + vec[21];
+ vec[13] = vec[23] + vec[22];
+ vec[22] = temp[3];
+ temp[3] = vec[15];
+ vec[15] = vec[24] + vec[23];
+ vec[17] = vec[25] + vec[24];
+ vec[19] = vec[26] + vec[25];
+ vec[21] = vec[27] + vec[26];
+ vec[23] = vec[28] + vec[27];
+ vec[25] = vec[29] + vec[28];
+ vec[27] = vec[30] + vec[29];
+ vec[29] = vec[30] + vec[31];
+ vec[24] = temp[1];
+ vec[26] = temp[2];
+ vec[28] = temp[0];
+ vec[30] = temp[3];
+}
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/dct64.h b/media/libstagefright/codecs/aacdec/dct64.h
new file mode 100644
index 0000000..3d5e82b
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/dct64.h
@@ -0,0 +1,81 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./c/include/dct64.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef DCT64_H
+#define DCT64_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+ extern const Int32 CosTable_48[48];
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ void pv_split_LC(Int32 *vector,
+ Int32 *temp_o);
+
+
+#ifdef HQ_SBR
+
+ void dct_64(Int32 vec[], Int32 *scratch_mem);
+
+#endif
+
+ void pv_split(Int32 *temp_o);
+
+ void pv_split_z(Int32 *vector);
+
+ void pv_merge_in_place_N32(Int32 vec[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DCT64_H */
diff --git a/media/libstagefright/codecs/aacdec/decode_huff_cw_binary.cpp b/media/libstagefright/codecs/aacdec/decode_huff_cw_binary.cpp
new file mode 100644
index 0000000..0d1561b
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/decode_huff_cw_binary.cpp
@@ -0,0 +1,708 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/decode_huff_cw_binary.c
+ Funtions:
+ decode_huff_cw_tab1
+ decode_huff_cw_tab2
+ decode_huff_cw_tab3
+ decode_huff_cw_tab4
+ decode_huff_cw_tab5
+ decode_huff_cw_tab6
+ decode_huff_cw_tab7
+ decode_huff_cw_tab8
+ decode_huff_cw_tab9
+ decode_huff_cw_tab10
+ decode_huff_cw_tab11
+ decode_huff_cw_scl
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated per review comments
+ (1) make cw sgined and change "if(cw&0x80000000)" to if(cw<0)
+ (2)
+
+ Description: Create specific functions for different huffman tables.
+
+
+ Description: Added ( Int16) castings to eliminate several compiler warnings
+
+
+ Description: Modified huffman tables to allocate int32 variables instead of
+ int16, which lead to data missaligned for some compiler.
+ Eliminated casting and unused variables
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ BITS *pInputStream = pointer to input bit stream
+
+ Local Stores/Buffers/Pointers Needed:
+
+
+ Global Stores/Buffers/Pointers Needed:
+
+
+ Outputs:
+ idx = bit field extracted from a leaf entry of packed Huffman Tables
+
+ Pointers and Buffers Modified:
+
+ Local Stores Modified:
+
+ Global Stores Modified:
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ These functions are used to decode huffman codewords from the input
+ bitstream using combined binary search and look-up table approach.
+
+ First the codewords are grouped and the input symbol is determined
+ which group it belongs. Then within that group, a look-up table is
+ used to determine which codeword the symbol is.
+ The table is created by ordering the codeword in the table according to their
+ normalized shifted binary value, i.e., all the codewords are left
+ shifted to meet the maximum codelength. Example, max codelength is
+ 10, the codeword with lenth 3 will left shift by 7.
+ The binary values of after the shift are sorted.
+ Then the sorted table is divided into several partition.
+ At the VLC decoding period, input is read in at max codelenght.
+ The partition is decided using if-else logic.
+ Inside each partition, a look-up table is used to map the input value
+ to a correct symbol. Table entries can appear to be repeated according
+ to the humming distance between adjacent codewords.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+ (2) Introduction to Algorithms,
+ Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest.
+ The MIT press, 1990
+
+ (3) "Selecting an Optimal Huffman Decoder for AAC",
+ Vladimir Z. Mesarovic, et al.
+ AES 111th Convention, September 21-24, 2001, New York, USA
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE:
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES:
+
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "huffman.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define MAX_CW_LEN (19)
+#define MASK_IDX (0x1FF)
+#define MASK_RIGHT (0xFE00)
+
+#define UPPER16 (16)
+#define MASK_LOW16 (0xFFFF)
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int decode_huff_cw_tab1(
+ BITS *pInputStream)
+{
+ Int32 tab;
+ Int32 cw;
+
+ cw = get17_n_lessbits(
+ 11,
+ pInputStream);
+ if ((cw >> 10) == 0)
+ {
+ pInputStream->usedBits -= (11 - 1);
+ return 40; /* idx is 40 */
+ }
+ else if ((cw >> 6) <= 23)
+ {
+ tab = (cw >> 6) - 16;
+ }
+ else if ((cw >> 4) <= 119)
+ {
+ tab = (cw >> 4) - 96 + 8;
+ }
+ else if ((cw >> 2) <= 503)
+ {
+ tab = (cw >> 2) - 480 + 32;
+ }
+ else
+ {
+ tab = cw - 2016 + 56;
+ }
+
+ tab = *(huff_tab1 + tab);
+
+ pInputStream->usedBits -= (11 - (tab & MASK_LOW16));
+ return ((Int)(tab >> UPPER16));
+}
+
+
+Int decode_huff_cw_tab2(
+ BITS *pInputStream)
+{
+ Int32 tab;
+ Int32 cw;
+
+ cw = get9_n_lessbits(
+ 9,
+ pInputStream);
+ if ((cw >> 6) == 0)
+ {
+ pInputStream->usedBits -= (9 - 3); /* used 3 bits */
+ return 40; /* idx is 40 */
+ }
+ else if ((cw >> 3) <= 49)
+ {
+ tab = (cw >> 3) - 8;
+ }
+ else if ((cw >> 2) <= 114)
+ {
+ tab = (cw >> 2) - 100 + 42;
+ }
+ else if ((cw >> 1) <= 248)
+ {
+ tab = (cw >> 1) - 230 + 57;
+ }
+ else
+ {
+ tab = cw - 498 + 76;
+ }
+
+ tab = *(huff_tab2 + tab);
+
+ pInputStream->usedBits -= (9 - (tab & MASK_LOW16));
+ return ((Int)(tab >> UPPER16));
+}
+
+
+Int decode_huff_cw_tab3(
+ BITS *pInputStream)
+{
+ Int32 tab;
+ Int32 cw;
+
+ cw = get17_n_lessbits(
+ 16,
+ pInputStream);
+ if ((cw >> 15) == 0)
+ {
+ pInputStream->usedBits -= (16 - 1); /* used 1 bits */
+ return 0; /* idx is 0 */
+ }
+ else if ((cw >> 10) <= 57)
+ {
+ tab = (cw >> 10) - 32;
+ }
+ else if ((cw >> 7) <= 500)
+ {
+ tab = (cw >> 7) - 464 + 26;
+ }
+ else if ((cw >> 6) <= 1016)
+ {
+ tab = (cw >> 6) - 1002 + 63;
+ }
+ else if ((cw >> 4) <= 4092)
+ {
+ tab = (cw >> 4) - 4068 + 78;
+ }
+ else
+ {
+ tab = cw - 65488 + 103;
+ }
+
+ tab = *(huff_tab3 + tab);
+
+ pInputStream->usedBits -= (16 - (tab & MASK_LOW16));
+ return ((Int)(tab >> UPPER16));
+}
+
+
+Int decode_huff_cw_tab4(
+ BITS *pInputStream)
+{
+ Int32 tab;
+ Int32 cw;
+
+ cw = get17_n_lessbits(
+ 12,
+ pInputStream);
+
+ if ((cw >> 7) <= 25)
+ {
+ tab = (cw >> 7);
+ }
+ else if ((cw >> 4) <= 246)
+ {
+ tab = (cw >> 4) - 208 + 26;
+ }
+ else if ((cw >> 2) <= 1017)
+ {
+ tab = (cw >> 2) - 988 + 65;
+ }
+ else
+ {
+ tab = cw - 4072 + 95;
+ }
+
+ tab = *(huff_tab4 + tab);
+
+ pInputStream->usedBits -= (12 - (tab & MASK_LOW16));
+ return ((Int)(tab >> UPPER16));
+}
+
+
+
+Int decode_huff_cw_tab5(
+ BITS *pInputStream)
+{
+ Int32 tab;
+ Int32 cw;
+
+ cw = get17_n_lessbits(
+ 13,
+ pInputStream);
+
+ if ((cw >> 12) == 0)
+ {
+ pInputStream->usedBits -= (13 - 1); /* used 1 bits */
+ return 40; /* idx is 40 */
+ }
+ else if ((cw >> 8) <= 27)
+ {
+ tab = (cw >> 8) - 16;
+ }
+ else if ((cw >> 5) <= 243)
+ {
+ tab = (cw >> 5) - 224 + 12;
+ }
+ else if ((cw >> 3) <= 1011)
+ {
+ tab = (cw >> 3) - 976 + 32;
+ }
+ else if ((cw >> 2) <= 2041)
+ {
+ tab = (cw >> 2) - 2024 + 68;
+ }
+ else
+ {
+ tab = cw - 8168 + 86;
+ }
+
+ tab = *(huff_tab5 + tab);
+
+ pInputStream->usedBits -= (13 - (tab & MASK_LOW16));
+ return ((Int)(tab >> UPPER16));
+}
+
+
+
+Int decode_huff_cw_tab6(
+ BITS *pInputStream)
+{
+ Int32 tab;
+ Int32 cw;
+
+ cw = get17_n_lessbits(
+ 11,
+ pInputStream);
+
+ if ((cw >> 7) <= 8)
+ {
+ tab = (cw >> 7);
+ }
+ else if ((cw >> 4) <= 116)
+ {
+ tab = (cw >> 4) - 72 + 9;
+ }
+ else if ((cw >> 2) <= 506)
+ {
+ tab = (cw >> 2) - 468 + 54;
+ }
+ else
+ {
+ tab = cw - 2028 + 93;
+ }
+
+ tab = *(huff_tab6 + tab);
+
+ pInputStream->usedBits -= (11 - (tab & MASK_LOW16));
+ return ((Int)(tab >> UPPER16));
+}
+
+
+
+Int decode_huff_cw_tab7(
+ BITS *pInputStream)
+{
+ Int32 tab;
+ Int32 cw;
+
+ cw = get17_n_lessbits(
+ 12,
+ pInputStream);
+
+ if ((cw >> 11) == 0)
+ {
+ pInputStream->usedBits -= (12 - 1); /* used 1 bits */
+ return 0; /* idx is 0 */
+ }
+ else if ((cw >> 6) <= 55)
+ {
+ tab = (cw >> 6) - 32;
+ }
+ else if ((cw >> 4) <= 243)
+ {
+ tab = (cw >> 4) - 224 + 24;
+ }
+ else if ((cw >> 2) <= 1018)
+ {
+ tab = (cw >> 2) - 976 + 44;
+ }
+ else
+ {
+ tab = cw - 4076 + 87;
+ }
+
+ tab = *(huff_tab7 + tab);
+
+ pInputStream->usedBits -= (12 - (tab & MASK_LOW16));
+ return ((Int)(tab >> UPPER16));
+}
+
+
+
+Int decode_huff_cw_tab8(
+ BITS *pInputStream)
+{
+ Int32 tab;
+ Int32 cw;
+
+ cw = get17_n_lessbits(
+ 10,
+ pInputStream);
+
+ if ((cw >> 5) <= 20)
+ {
+ tab = (cw >> 5);
+ }
+ else if ((cw >> 3) <= 117)
+ {
+ tab = (cw >> 3) - 84 + 21;
+ }
+ else if ((cw >> 2) <= 250)
+ {
+ tab = (cw >> 2) - 236 + 55;
+ }
+ else
+ {
+ tab = cw - 1004 + 70;
+ }
+
+ tab = *(huff_tab8 + tab);
+
+ pInputStream->usedBits -= (10 - (tab & MASK_LOW16));
+ return ((Int)(tab >> UPPER16));
+}
+
+
+Int decode_huff_cw_tab9(
+ BITS *pInputStream)
+{
+ Int32 tab;
+ Int32 cw;
+
+ cw = get17_n_lessbits(
+ 15,
+ pInputStream);
+
+ if ((cw >> 11) <= 12)
+ {
+ tab = (cw >> 11);
+ }
+ else if ((cw >> 8) <= 114)
+ {
+ tab = (cw >> 8) - 104 + 13;
+ }
+ else if ((cw >> 6) <= 486)
+ {
+ tab = (cw >> 6) - 460 + 24;
+ }
+ else if ((cw >> 5) <= 993)
+ {
+ tab = (cw >> 5) - 974 + 51;
+ }
+ else if ((cw >> 4) <= 2018)
+ {
+ tab = (cw >> 4) - 1988 + 71;
+ }
+ else if ((cw >> 3) <= 4075)
+ {
+ tab = (cw >> 3) - 4038 + 102;
+ }
+ else if ((cw >> 2) <= 8183)
+ {
+ tab = (cw >> 2) - 8152 + 140;
+ }
+ else
+ {
+ tab = cw - 32736 + 172;
+ }
+
+ tab = *(huff_tab9 + tab);
+
+ pInputStream->usedBits -= (15 - (tab & MASK_LOW16));
+ return ((Int)(tab >> UPPER16));
+}
+
+
+Int decode_huff_cw_tab10(
+ BITS *pInputStream)
+{
+ Int32 tab;
+ Int32 cw;
+
+ cw = get17_n_lessbits(
+ 12,
+ pInputStream);
+
+ if ((cw >> 6) <= 41)
+ {
+ tab = (cw >> 6);
+ }
+ else if ((cw >> 5) <= 100)
+ {
+ tab = (cw >> 5) - 84 + 42;
+ }
+ else if ((cw >> 4) <= 226)
+ {
+ tab = (cw >> 4) - 202 + 59;
+ }
+ else if ((cw >> 3) <= 484)
+ {
+ tab = (cw >> 3) - 454 + 84;
+ }
+ else if ((cw >> 2) <= 1010)
+ {
+ tab = (cw >> 2) - 970 + 115;
+ }
+ else if ((cw >> 1) <= 2043)
+ {
+ tab = (cw >> 1) - 2022 + 156;
+ }
+ else
+ {
+ tab = cw - 4088 + 178;
+ }
+
+ tab = *(huff_tab10 + tab);
+
+ pInputStream->usedBits -= (12 - (tab & MASK_LOW16));
+ return ((Int)(tab >> UPPER16));
+}
+
+
+Int decode_huff_cw_tab11(
+ BITS *pInputStream)
+{
+ Int32 tab;
+ Int32 cw;
+
+ cw = get17_n_lessbits(
+ 12,
+ pInputStream);
+
+ if ((cw >> 6) <= 26)
+ {
+ tab = (cw >> 6);
+ }
+ else if ((cw >> 5) <= 69)
+ {
+ tab = (cw >> 5) - 54 + 27;
+ }
+ else if ((cw >> 4) <= 198)
+ {
+ tab = (cw >> 4) - 140 + 43;
+ }
+ else if ((cw >> 3) <= 452)
+ {
+ tab = (cw >> 3) - 398 + 102;
+ }
+ else if ((cw >> 2) <= 1000)
+ {
+ tab = (cw >> 2) - 906 + 157;
+ }
+ else if ((cw >> 1) <= 2044)
+ {
+ tab = (cw >> 1) - 2002 + 252;
+ }
+ else
+ {
+ tab = cw - 4090 + 295;
+ }
+
+ tab = *(huff_tab11 + tab);
+
+ pInputStream->usedBits -= (12 - (tab & MASK_LOW16));
+ return ((Int)(tab >> UPPER16));
+}
+
+
+Int decode_huff_scl(
+ BITS *pInputStream)
+{
+ Int32 tab;
+ Int32 cw;
+
+ cw = getbits(
+ 19,
+ pInputStream);
+
+ if ((cw >> 18) == 0)
+ {
+ pInputStream->usedBits -= (19 - 1); /* used 1 bits */
+ return 60; /* idx is 60 */
+ }
+ else if ((cw >> 13) <= 59)
+ {
+ tab = (cw >> 13) - 32;
+ }
+ else if ((cw >> 10) <= 505)
+ {
+ tab = (cw >> 10) - 480 + 28;
+ }
+ else if ((cw >> 7) <= 4089)
+ {
+ tab = (cw >> 7) - 4048 + 54;
+ }
+ else if ((cw >> 5) <= 16377)
+ {
+ tab = (cw >> 5) - 16360 + 96;
+ }
+ else if ((cw >> 3) <= 65526)
+ {
+ tab = (cw >> 3) - 65512 + 114;
+ }
+ else if ((cw >> 1) <= 262120)
+ {
+ tab = (cw >> 1) - 262108 + 129;
+ }
+ else
+ {
+ tab = cw - 524242 + 142;
+ }
+
+ tab = *(huff_tab_scl + tab);
+
+ pInputStream->usedBits -= (19 - (tab & MASK_LOW16));
+ return ((Int)(tab >> UPPER16));
+}
+
diff --git a/media/libstagefright/codecs/aacdec/decode_noise_floorlevels.cpp b/media/libstagefright/codecs/aacdec/decode_noise_floorlevels.cpp
new file mode 100644
index 0000000..41cd187
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/decode_noise_floorlevels.cpp
@@ -0,0 +1,163 @@
+/* ------------------------------------------------------------------
+ * 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: decode_noise_floorlevels.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+#ifdef AAC_PLUS
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "decode_noise_floorlevels.h"
+#include "sbr_constants.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void decode_noise_floorlevels(SBR_FRAME_DATA * hFrameData)
+
+{
+ Int32 env;
+ Int32 i;
+
+ Int32 * frameInfo = hFrameData->frameInfo;
+ Int32 nNfb = hFrameData->nNfb;
+ Int32 * domain_vec = hFrameData->domain_vec2;
+
+ Int32 * sbrNoiseFloorLevel_man = hFrameData->sbrNoiseFloorLevel_man;
+ Int32 * prevNoiseLevel_man = hFrameData->prevNoiseLevel_man;
+
+ Int32 nEnv = frameInfo[(frameInfo[0] << 1) + 3];
+
+ for (env = 0; env < nEnv; env++)
+ {
+ if (domain_vec[env] == 0)
+ {
+ prevNoiseLevel_man[0] = *(sbrNoiseFloorLevel_man++);
+
+ for (i = 1; i < nNfb; i++)
+ {
+ *sbrNoiseFloorLevel_man += *(sbrNoiseFloorLevel_man - 1);
+ prevNoiseLevel_man[i] = *(sbrNoiseFloorLevel_man++);
+ }
+ }
+ else
+ {
+ for (i = 0; i < nNfb; i++)
+ {
+ *sbrNoiseFloorLevel_man += prevNoiseLevel_man[i];
+ prevNoiseLevel_man[i] = *(sbrNoiseFloorLevel_man++);
+ }
+ }
+
+ }
+}
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/decode_noise_floorlevels.h b/media/libstagefright/codecs/aacdec/decode_noise_floorlevels.h
new file mode 100644
index 0000000..a9c3551
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/decode_noise_floorlevels.h
@@ -0,0 +1,92 @@
+/* ------------------------------------------------------------------
+ * 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: decode_noise_floorlevels.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef DECODENOISEFLOORLEVELS_H
+#define DECODENOISEFLOORLEVELS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_sbr_frame_data.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void decode_noise_floorlevels(SBR_FRAME_DATA * hFrameData);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/deinterleave.cpp b/media/libstagefright/codecs/aacdec/deinterleave.cpp
new file mode 100644
index 0000000..5298b19
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/deinterleave.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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/deinterleave.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: (1) Modified with new template, rename variables
+ (2) Removed for-loop to calculate win_inc, win_inc = SN2 (128)
+ (3) Replaced for-loop with memcpy
+ (4) Converted Int16 -> Int
+
+ Description: Modified per review comments
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ interleaved = input array that contains interleaved coefficients
+ Data Type Int
+
+ deinterleaved = output array that will be updated with de-interleaved
+ coefficients of input array. Data Type Int
+
+ pFrameInfo = pointer to structure that holds information of current
+ frame. Data Type FrameInfo
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ deinterleaved contents updated with de-interleaved coefficients from
+ the input array: interleaved
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the deinterleaving across all short windows in
+ each group
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function should replace the contents of pDeinterleaved with the
+ de-interleaved 1024 coefficients of one frame
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+ (2) ISO/IEC 14496-3: 1999(E)
+ Subpart 4 p78 quant_to_spec
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ pInterleaved = interleaved;
+ pDeinterleaved = deinterleaved;
+
+ pSfbPerWin = pFrameInfo->sfb_per_win;
+ ngroups = pFrameInfo->num_groups;
+ pGroupLen = pFrameInfo->group_len;
+
+ pGroup = pDeinterleaved;
+
+ FOR (group = ngroups; group > 0; group--)
+
+ pSfbWidth = pFrameInfo->sfb_width_128;
+ sfb_inc = 0;
+ pStart = pInterleaved;
+
+ FOR (sfb = pSfbPerWin[ngroups-group]; sfb > 0; sfb--)
+
+ pWin = pGroup;
+
+ FOR (win = pGroupLen[ngroups-group]; win > 0; win--)
+
+ pDeinterleaved = pWin + sfb_inc;
+
+ pv_memcpy(
+ pDeinterleaved,
+ pInterleaved,
+ *pSfbWidth*sizeof(*pInterleaved));
+
+ pInterleaved += *pSfbWidth;
+
+ pWin += SN2;
+
+ ENDFOR (win)
+
+ sfb_inc += *pSfbWidth++;
+
+ ENDFOR (sfb)
+
+ pGroup += (pInterleaved - pStart);
+
+ ENDFOR (group)
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "huffman.h"
+#include "aac_mem_funcs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void deinterleave(
+ Int16 interleaved[],
+ Int16 deinterleaved[],
+ FrameInfo *pFrameInfo)
+{
+
+ Int group; /* group index */
+ Int sfb; /* scalefactor band index */
+ Int win; /* window index */
+ Int16 *pGroup;
+ Int16 *pWin;
+ Int16 *pStart;
+ Int16 *pInterleaved;
+ Int16 *pDeinterleaved;
+ Int sfb_inc;
+
+ Int ngroups;
+ Int *pGroupLen;
+ Int *pSfbPerWin;
+ Int *pSfbWidth;
+
+ pInterleaved = interleaved;
+ pDeinterleaved = deinterleaved;
+
+ pSfbPerWin = pFrameInfo->sfb_per_win;
+ ngroups = pFrameInfo->num_groups;
+ pGroupLen = pFrameInfo->group_len;
+
+ pGroup = pDeinterleaved;
+
+ for (group = ngroups; group > 0; group--)
+ {
+ pSfbWidth = pFrameInfo->sfb_width_128;
+ sfb_inc = 0;
+ pStart = pInterleaved;
+
+ /* Perform the deinterleaving across all windows in a group */
+
+ for (sfb = pSfbPerWin[ngroups-group]; sfb > 0; sfb--)
+ {
+ pWin = pGroup;
+
+ for (win = pGroupLen[ngroups-group]; win > 0; win--)
+ {
+ pDeinterleaved = pWin + sfb_inc;
+
+ pv_memcpy(
+ pDeinterleaved,
+ pInterleaved,
+ *pSfbWidth*sizeof(*pInterleaved));
+
+ pInterleaved += *pSfbWidth;
+
+ pWin += SN2;
+
+ } /* for (win) */
+
+ sfb_inc += *pSfbWidth++;
+
+ } /* for (sfb) */
+
+ pGroup += (pInterleaved - pStart);
+
+ } /* for (group) */
+
+} /* deinterleave */
diff --git a/media/libstagefright/codecs/aacdec/digit_reversal_tables.cpp b/media/libstagefright/codecs/aacdec/digit_reversal_tables.cpp
new file mode 100644
index 0000000..ffa980d
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/digit_reversal_tables.cpp
@@ -0,0 +1,279 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/digit_reversal_tables.c
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+ ------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Tables for digit reverse operation
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "digit_reversal_tables.h"
+#include "imdct_fxp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ Digit Reverse tables
+------------------------------------------------------------------------------
+*/
+
+const Int16 digit_reverse_64[ 64] =
+{
+ + 0, + 32, + 64, + 96,
+ + 8, + 40, + 72, + 104,
+ + 16, + 48, + 80, + 112,
+ + 24, + 56, + 88, + 120,
+ + 2, + 34, + 66, + 98,
+ + 10, + 42, + 74, + 106,
+ + 18, + 50, + 82, + 114,
+ + 26, + 58, + 90, + 122,
+ + 4, + 36, + 68, + 100,
+ + 12, + 44, + 76, + 108,
+ + 20, + 52, + 84, + 116,
+ + 28, + 60, + 92, + 124,
+ + 6, + 38, + 70, + 102,
+ + 14, + 46, + 78, + 110,
+ + 22, + 54, + 86, + 118,
+ + 30, + 62, + 94, + 126
+};
+
+
+const Int16 digit_reverse_256[ 256] =
+{
+ + 0, + 128, + 256, + 384,
+ + 32, + 160, + 288, + 416,
+ + 64, + 192, + 320, + 448,
+ + 96, + 224, + 352, + 480,
+ + 8, + 136, + 264, + 392,
+ + 40, + 168, + 296, + 424,
+ + 72, + 200, + 328, + 456,
+ + 104, + 232, + 360, + 488,
+ + 16, + 144, + 272, + 400,
+ + 48, + 176, + 304, + 432,
+ + 80, + 208, + 336, + 464,
+ + 112, + 240, + 368, + 496,
+ + 24, + 152, + 280, + 408,
+ + 56, + 184, + 312, + 440,
+ + 88, + 216, + 344, + 472,
+ + 120, + 248, + 376, + 504,
+ + 2, + 130, + 258, + 386,
+ + 34, + 162, + 290, + 418,
+ + 66, + 194, + 322, + 450,
+ + 98, + 226, + 354, + 482,
+ + 10, + 138, + 266, + 394,
+ + 42, + 170, + 298, + 426,
+ + 74, + 202, + 330, + 458,
+ + 106, + 234, + 362, + 490,
+ + 18, + 146, + 274, + 402,
+ + 50, + 178, + 306, + 434,
+ + 82, + 210, + 338, + 466,
+ + 114, + 242, + 370, + 498,
+ + 26, + 154, + 282, + 410,
+ + 58, + 186, + 314, + 442,
+ + 90, + 218, + 346, + 474,
+ + 122, + 250, + 378, + 506,
+ + 4, + 132, + 260, + 388,
+ + 36, + 164, + 292, + 420,
+ + 68, + 196, + 324, + 452,
+ + 100, + 228, + 356, + 484,
+ + 12, + 140, + 268, + 396,
+ + 44, + 172, + 300, + 428,
+ + 76, + 204, + 332, + 460,
+ + 108, + 236, + 364, + 492,
+ + 20, + 148, + 276, + 404,
+ + 52, + 180, + 308, + 436,
+ + 84, + 212, + 340, + 468,
+ + 116, + 244, + 372, + 500,
+ + 28, + 156, + 284, + 412,
+ + 60, + 188, + 316, + 444,
+ + 92, + 220, + 348, + 476,
+ + 124, + 252, + 380, + 508,
+ + 6, + 134, + 262, + 390,
+ + 38, + 166, + 294, + 422,
+ + 70, + 198, + 326, + 454,
+ + 102, + 230, + 358, + 486,
+ + 14, + 142, + 270, + 398,
+ + 46, + 174, + 302, + 430,
+ + 78, + 206, + 334, + 462,
+ + 110, + 238, + 366, + 494,
+ + 22, + 150, + 278, + 406,
+ + 54, + 182, + 310, + 438,
+ + 86, + 214, + 342, + 470,
+ + 118, + 246, + 374, + 502,
+ + 30, + 158, + 286, + 414,
+ + 62, + 190, + 318, + 446,
+ + 94, + 222, + 350, + 478,
+ + 126, + 254, + 382, + 510
+};
+
+
+
+
+const Int16 digit_reverse_swap_256[ 241] =
+{
+ + 2, + 128, + 4, + 256,
+ + 6, + 384, + 8, + 32,
+ + 10, + 160, + 12, + 288,
+ + 14, + 416, + 16, + 64,
+ + 18, + 192, + 20, + 320,
+ + 22, + 448, + 24, + 96,
+ + 26, + 224, + 28, + 352,
+ + 30, + 480, + 34, + 136,
+ + 36, + 264, + 38, + 392,
+ + 42, + 168, + 44, + 296,
+ + 46, + 424, + 48, + 72,
+ + 50, + 200, + 52, + 328,
+ + 54, + 456, + 56, + 104,
+ + 58, + 232, + 60, + 360,
+ + 62, + 488, + 66, + 144,
+ + 68, + 272, + 70, + 400,
+ + 74, + 176, + 76, + 304,
+ + 78, + 432, + 82, + 208,
+ + 84, + 336, + 86, + 464,
+ + 88, + 112, + 90, + 240,
+ + 92, + 368, + 94, + 496,
+ + 98, + 152, + 100, + 280,
+ + 102, + 408, + 106, + 184,
+ + 108, + 312, + 110, + 440,
+ + 114, + 216, + 116, + 344,
+ + 118, + 472, + 122, + 248,
+ + 124, + 376, + 126, + 504,
+ + 132, + 258, + 134, + 386,
+ + 138, + 162, + 140, + 290,
+ + 142, + 418, + 146, + 194,
+ + 148, + 322, + 150, + 450,
+ + 154, + 226, + 156, + 354,
+ + 158, + 482, + 164, + 266,
+ + 166, + 394, + 172, + 298,
+ + 174, + 426, + 178, + 202,
+ + 180, + 330, + 182, + 458,
+ + 186, + 234, + 188, + 362,
+ + 190, + 490, + 196, + 274,
+ + 198, + 402, + 204, + 306,
+ + 206, + 434, + 212, + 338,
+ + 214, + 466, + 218, + 242,
+ + 220, + 370, + 222, + 498,
+ + 228, + 282, + 230, + 410,
+ + 236, + 314, + 238, + 442,
+ + 244, + 346, + 246, + 474,
+ + 252, + 378, + 254, + 506,
+ + 262, + 388, + 268, + 292,
+ + 270, + 420, + 276, + 324,
+ + 278, + 452, + 284, + 356,
+ + 286, + 484, + 294, + 396,
+ + 302, + 428, + 308, + 332,
+ + 310, + 460, + 316, + 364,
+ + 318, + 492, + 326, + 404,
+ + 334, + 436, + 342, + 468,
+ + 348, + 372, + 350, + 500,
+ + 358, + 412, + 366, + 444,
+ + 374, + 476, + 382, + 508,
+ + 398, + 422, + 406, + 454,
+ + 414, + 486, + 438, + 462,
+ + 446, + 494, + 478, + 502
+};
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void digit_reversal_swapping(Int32 *y, Int32 *x);
+
+#ifdef __cplusplus
+}
+#endif
+
+void digit_reversal_swapping(Int32 *y, Int32 *x)
+{
+ Int16 i, j;
+ Int32 tmp[2];
+ const Int16 *pTable;
+
+ pTable = digit_reverse_swap_256;
+
+ for (Int k = 120; k != 0; k--)
+ {
+ i = *pTable++;
+ j = *pTable++;
+ tmp[0] = y[i];
+ tmp[1] = y[i+1];
+ y[i] = y[j];
+ y[i+1] = y[j+1];
+ y[j] = tmp[0];
+ y[j+1] = tmp[1];
+
+ tmp[0] = x[j];
+ tmp[1] = x[j+1];
+ x[j] = x[i];
+ x[j+1] = x[i+1];
+ x[i] = tmp[0];
+ x[i+1] = tmp[1];
+
+ }
+
+}
diff --git a/media/libstagefright/codecs/aacdec/digit_reversal_tables.h b/media/libstagefright/codecs/aacdec/digit_reversal_tables.h
new file mode 100644
index 0000000..7fdaaf7
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/digit_reversal_tables.h
@@ -0,0 +1,86 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/DIGIT_REVERSAL_TABLES.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for functions digit_reversal_tables
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef DIGIT_REVERSAL_TABLES_H
+#define DIGIT_REVERSAL_TABLES_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+extern const Int16 digit_reverse_64[];
+extern const Int16 digit_reverse_256[];
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* DIGIT_REVERSAL_TABLES_H */
diff --git a/media/libstagefright/codecs/aacdec/dst16.cpp b/media/libstagefright/codecs/aacdec/dst16.cpp
new file mode 100644
index 0000000..41c9259
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/dst16.cpp
@@ -0,0 +1,172 @@
+/* ------------------------------------------------------------------
+ * 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: dst16.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 x 32-bit integer input length 16
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement discrete sine transform of lenght 16
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#include "dst16.h"
+#include "dst8.h"
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+#define R_SHIFT 28
+#define Qfmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+const Int32 CosTable_8[8] =
+{
+ Qfmt(0.50241928618816F), Qfmt(0.52249861493969F),
+ Qfmt(0.56694403481636F), Qfmt(0.64682178335999F),
+ Qfmt(0.78815462345125F), Qfmt(1.06067768599035F),
+ Qfmt(1.72244709823833F), Qfmt(5.10114861868916F)
+};
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void dst_16(Int32 vec[], Int32 scratch_mem[]) /* scratch_mem size 8 */
+{
+ Int32 *temp_even = scratch_mem;
+
+ Int i;
+ const Int32 *pt_cos = &CosTable_8[7];
+ Int32 tmp0 = vec[15] >> 1;
+ Int32 tmp1, tmp2;
+ Int32 *pt_even = temp_even;
+ Int32 *pt_odd = vec;
+ Int32 *pt_vec = vec;
+ Int32 *pt_vecN_1;
+ Int32 tmp3;
+
+
+ *(pt_even++) = *(pt_vec++);
+ tmp1 = *(pt_vec++);
+ *(pt_odd++) = tmp1;
+
+ for (i = 3; i != 0; i--)
+ {
+ *(pt_even++) = *(pt_vec++);
+ tmp2 = *(pt_vec++);
+ *(pt_even++) = *(pt_vec++);
+ tmp3 = *(pt_vec++);
+ *(pt_odd++) = tmp2 + tmp1;
+ *(pt_odd++) = tmp3 + tmp2;
+ tmp1 = tmp3;
+
+ }
+
+ *(pt_even) = *(pt_vec++);
+ *(pt_odd++) = *(pt_vec) + tmp1;
+
+
+ dst_8(temp_even);
+ dst_8(vec);
+
+ pt_vec = &vec[7];
+
+ pt_even = &temp_even[7];
+ pt_vecN_1 = &vec[8];
+
+ tmp1 = *(pt_even--);
+
+ for (i = 4; i != 0; i--)
+ {
+ tmp3 = fxp_mul32_Q28((*(pt_vec) - tmp0), *(pt_cos--));
+ tmp2 = *(pt_even--);
+ *(pt_vec--) = tmp3 + tmp1;
+ *(pt_vecN_1++) = tmp3 - tmp1;
+ tmp3 = fxp_mul32_Q28((*(pt_vec) + tmp0), *(pt_cos--));
+ tmp1 = *(pt_even--);
+ *(pt_vecN_1++) = tmp3 - tmp2;
+ *(pt_vec--) = tmp3 + tmp2;
+ }
+
+}
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/dst16.h b/media/libstagefright/codecs/aacdec/dst16.h
new file mode 100644
index 0000000..bce73ba
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/dst16.h
@@ -0,0 +1,68 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./c/include/dst16.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef DST16_H
+#define DST16_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ void dst_16(Int32 vec[], Int32 scratch_mem[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DST16_H */
diff --git a/media/libstagefright/codecs/aacdec/dst32.cpp b/media/libstagefright/codecs/aacdec/dst32.cpp
new file mode 100644
index 0000000..5edecf1
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/dst32.cpp
@@ -0,0 +1,200 @@
+/* ------------------------------------------------------------------
+ * 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: dst32.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 x 32-bit integer input length 32
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement discrete sine transform of lenght 32
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "dst32.h"
+#include "dst16.h"
+
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+#define R_SHIFT1 29
+#define Qfmt29(x) (Int32)(x*((Int32)1<<R_SHIFT1) + (x>=0?0.5F:-0.5F))
+#define Qfmt31(a) (Int32)(a*0x7FFFFFFF + (a>=0?0.5F:-0.5F))
+
+const Int32 CosTable_16[14] =
+{
+ Qfmt31(0.50060299823520F), Qfmt31(0.50547095989754F),
+ Qfmt31(0.51544730992262F), Qfmt31(0.53104259108978F),
+ Qfmt31(0.55310389603444F), Qfmt31(0.58293496820613F),
+ Qfmt31(0.62250412303566F), Qfmt31(0.67480834145501F),
+ Qfmt31(0.74453627100230F), Qfmt31(0.83934964541553F),
+ Qfmt29(0.97256823786196F), Qfmt29(1.16943993343288F),
+ Qfmt29(1.48416461631417F), Qfmt29(2.05778100995341F)
+};
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void dst_32(Int32 vec[], Int32 scratch_mem[]) /* scratch_mem size 32 */
+{
+ Int32 *temp_even = scratch_mem;
+
+ Int32 i;
+ const Int32 *pt_cos = &CosTable_16[13];
+ Int32 tmp0 = vec[31] >> 1;
+ Int32 tmp1, tmp2;
+ Int32 *pt_even = temp_even;
+ Int32 *pt_odd = vec;
+ Int32 *pt_vec = vec;
+ Int32 *pt_vecN_1 = vec;
+ Int32 tmp3;
+
+
+ tmp1 = 0;
+
+ for (i = 5; i != 0; i--)
+ {
+ *(pt_even++) = *(pt_vec++);
+ tmp2 = *(pt_vec++);
+ *(pt_even++) = *(pt_vec++);
+ tmp3 = *(pt_vec++);
+ *(pt_even++) = *(pt_vec++);
+ *(pt_odd++) = tmp2 + tmp1;
+ *(pt_odd++) = tmp3 + tmp2;
+ tmp1 = *(pt_vec++);
+ *(pt_odd++) = tmp1 + tmp3;
+ }
+
+ *(pt_even) = *(pt_vec++);
+ *(pt_odd) = *(pt_vec) + tmp1;
+
+
+ dst_16(temp_even, &scratch_mem[16]);
+ dst_16(vec, &scratch_mem[24]);
+
+
+ pt_vecN_1 = &vec[16];
+
+ tmp1 = temp_even[15];
+
+ tmp3 = fxp_mul32_Q31((vec[15] - tmp0) << 3, Qfmt31(0.63687550772175F)) << 2;
+ tmp2 = temp_even[14];
+ *(pt_vecN_1++) = tmp3 - tmp1;
+ vec[15] = tmp3 + tmp1;
+ tmp1 = temp_even[13];
+ tmp3 = fxp_mul32_Q31((vec[14] + tmp0) << 3, Qfmt31(0.85190210461718F));
+ *(pt_vecN_1++) = tmp3 - tmp2;
+ vec[14] = tmp3 + tmp2;
+
+ pt_even = &temp_even[12];
+ pt_vec = &vec[13];
+
+ for (i = 2; i != 0; i--)
+ {
+ tmp3 = fxp_mul32_Q29((*(pt_vec) - tmp0), *(pt_cos--));
+ tmp2 = *(pt_even--);
+ *(pt_vec--) = tmp3 + tmp1;
+ *(pt_vecN_1++) = tmp3 - tmp1;
+ tmp3 = fxp_mul32_Q29((*(pt_vec) + tmp0), *(pt_cos--));
+ tmp1 = *(pt_even--);
+ *(pt_vec--) = tmp3 + tmp2;
+ *(pt_vecN_1++) = tmp3 - tmp2;
+ }
+
+ for (i = 5; i != 0; i--)
+ {
+ tmp3 = fxp_mul32_Q31((*(pt_vec) - tmp0) << 1, *(pt_cos--));
+ tmp2 = *(pt_even--);
+ *(pt_vec--) = tmp3 + tmp1;
+ *(pt_vecN_1++) = tmp3 - tmp1;
+ tmp3 = fxp_mul32_Q31((*(pt_vec) + tmp0) << 1, *(pt_cos--));
+ tmp1 = *(pt_even--);
+ *(pt_vec--) = tmp3 + tmp2;
+ *(pt_vecN_1++) = tmp3 - tmp2;
+ }
+
+
+}
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/dst32.h b/media/libstagefright/codecs/aacdec/dst32.h
new file mode 100644
index 0000000..c2bf1d2
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/dst32.h
@@ -0,0 +1,69 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./c/include/dst32.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef DST32_H
+#define DST32_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+ extern const Int32 CosTable_16[];
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ void dst_32(Int32 vec[], Int32 scratch_mem[]);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DST32_H */
diff --git a/media/libstagefright/codecs/aacdec/dst8.cpp b/media/libstagefright/codecs/aacdec/dst8.cpp
new file mode 100644
index 0000000..eaf8280
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/dst8.cpp
@@ -0,0 +1,179 @@
+/* ------------------------------------------------------------------
+ * 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: dst8.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 x 32-bit integer input length 8
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement discrete sine transform of lenght 8
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "dst8.h"
+
+#include "fxp_mul32.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define Qfmt15(x) (Int16)(x*((Int32)1<<15) + (x>=0?0.5F:-0.5F))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+#define R_SHIFT 29
+#define Qfmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+#define Qfmt31(x) (Int32)(x*0x7FFFFFFF + (x>=0?0.5F:-0.5F))
+
+
+void dst_8(Int32 vec[])
+{
+
+ Int32 temp1;
+ Int32 temp2;
+ Int32 temp3;
+ Int32 temp4;
+ Int32 temp5;
+ Int32 temp6;
+ Int32 temp7;
+ Int32 tmp_a;
+ Int32 tmp_aa;
+ Int32 tmp_b;
+ Int32 tmp_bb;
+ Int32 tmp_c;
+ Int32 tmp_cc;
+ Int32 tmp_d;
+ Int32 tmp_dd;
+
+ temp1 = fxp_mul32_by_16(vec[1], Qfmt15(0.50979557910416F)); /* (1/(2*cos( phi)));*/
+ temp2 = fxp_mul32_by_16(vec[2], Qfmt15(0.54119610014620F)); /* (1/(2*cos(2*phi)));*/
+ temp3 = fxp_mul32_by_16(vec[3], Qfmt15(0.60134488693505F)); /* (1/(2*cos(3*phi)));*/
+ temp5 = fxp_mul32_by_16(vec[5], Qfmt15(0.89997622313642F)); /* (1/(2*cos(5*phi)));*/
+ temp6 = fxp_mul32_by_16(vec[6] << 1, Qfmt15(0.65328148243819F)); /* (1/(2*cos(6*phi)));*/
+ temp7 = vec[7] + fxp_mul32_Q31(vec[7], Qfmt31(0.56291544774152F)); /* (1/(2*cos(7*phi)));*/
+
+ /* even */
+ tmp_a = fxp_mul32_Q31((temp2 + temp6) << 1, Qfmt31(0.70710678118655F));
+ tmp_b = (temp2 - temp6) + tmp_a;
+
+ temp4 = fxp_mul32_by_16(vec[4], Qfmt15(0.70710678118655F));
+ vec[0] = tmp_a + temp4;
+ vec[1] = tmp_b + temp4;
+ vec[2] = tmp_b - temp4;
+ vec[3] = tmp_a - temp4;
+
+
+ /* odd */
+
+ tmp_a = fxp_mul32_by_16((temp1 + temp7) << 1, Qfmt15(0.54119610014620F)); /* (1/(2*cos(2*phi))); */
+ tmp_aa = (temp1 - temp7);
+ tmp_bb = (temp5 - temp3);
+ temp5 = fxp_mul32_Q29((temp5 + temp3), Qfmt(1.30656296487638F)); /* (1/(2*cos(6*phi))); */
+
+
+ tmp_c = fxp_mul32_by_16((tmp_a + temp5) << 1, Qfmt15(0.70710678118655F));
+ tmp_cc = tmp_a - temp5;
+
+ tmp_d = fxp_mac32_by_16((tmp_aa - tmp_bb) << 1, Qfmt15(0.70710678118655F), tmp_c);
+ tmp_dd = (tmp_aa + tmp_bb);
+
+ tmp_dd += tmp_c;
+ tmp_a = tmp_d + tmp_cc;
+ vec[5] = tmp_a - vec[2];
+ vec[2] += tmp_a;
+
+ temp5 = tmp_dd + tmp_cc;
+
+ vec[4] = temp5 - vec[3];
+ vec[3] += temp5;
+ vec[7] = tmp_c - vec[0];
+ vec[0] += tmp_c;
+ vec[6] = tmp_d - vec[1];
+ vec[1] += tmp_d;
+
+}
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/dst8.h b/media/libstagefright/codecs/aacdec/dst8.h
new file mode 100644
index 0000000..2738e80
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/dst8.h
@@ -0,0 +1,68 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./c/include/dst8.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef DST8_H
+#define DST8_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ void dst_8(Int32 vec[]);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DST8_H */
diff --git a/media/libstagefright/codecs/aacdec/e_adif_const.h b/media/libstagefright/codecs/aacdec/e_adif_const.h
new file mode 100644
index 0000000..08b5415
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_adif_const.h
@@ -0,0 +1,97 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/e_ADIF_Const.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ enum for ADIF header related constants
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_ADIF_CONST_H
+#define E_ADIF_CONST_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ /*
+ * audio data interchange format header
+ */
+ LEN_ADIF_ID = (32 / 8),
+ LEN_COPYRT_PRES = 1,
+ LEN_COPYRT_ID = (72 / 8),
+ LEN_ORIG = 1,
+ LEN_HOME = 1,
+ LEN_BS_TYPE = 1,
+ LEN_BIT_RATE = 23,
+ LEN_NUM_PCE = 4,
+ LEN_ADIF_BF = 20
+
+} eADIF_Const;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/e_blockswitching.h b/media/libstagefright/codecs/aacdec/e_blockswitching.h
new file mode 100644
index 0000000..bf6ad15
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_blockswitching.h
@@ -0,0 +1,112 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/e_BlockSwitching.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ enum for BlockSwitching related constants
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_BLOCK_SWITCHING_H
+#define E_BLOCK_SWITCHING_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ /*
+ * block switching
+ */
+ LN = 2048,
+ SN = 256,
+ LN2 = LN / 2,
+ SN2 = SN / 2,
+ LN4 = LN / 4,
+ SN4 = SN / 4,
+ NSHORT = LN / SN,
+ MAX_SBK = NSHORT,
+ MAX_WIN = MAX_SBK,
+
+ ONLY_LONG_WINDOW = 0,
+ LONG_START_WINDOW,
+ EIGHT_SHORT_WINDOW,
+ LONG_STOP_WINDOW,
+ NUM_WIN_SEQ,
+
+ WLONG = ONLY_LONG_WINDOW,
+ WSTART,
+ WSHORT,
+ WSTOP,
+
+ MAXBANDS = 16 * NSHORT, /* max number of scale factor bands */
+ MAXFAC = 121, /* maximum scale factor */
+ MIDFAC = (MAXFAC - 1) / 2,
+ SF_OFFSET = 100 /* global gain must be positive */
+} eBlockSwitching;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/e_coupling_mode.h b/media/libstagefright/codecs/aacdec/e_coupling_mode.h
new file mode 100644
index 0000000..68244bb
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_coupling_mode.h
@@ -0,0 +1,88 @@
+/* ------------------------------------------------------------------
+ * 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: e_coupling_mode.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_COUPLING_MODE_H
+#define E_COUPLING_MODE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ COUPLING_OFF,
+ COUPLING_LEVEL,
+ COUPLING_BAL
+}
+COUPLING_MODE;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/e_elementid.h b/media/libstagefright/codecs/aacdec/e_elementid.h
new file mode 100644
index 0000000..5f84643
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_elementid.h
@@ -0,0 +1,99 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+ Pathname: ./include/e_BLOCKTYPE.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ enum for BlockType related constants
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_ELEMENTID_H
+#define E_ELEMENTID_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ /* sfb 40, coef 672, pred bw of 15.75 kHz at 48 kHz
+ * this is also the highest number of bins used
+ * by predictor for any sampling rate
+ */
+ MAX_PRED_SFB = 40, /* 48 kHz only, now obsolete */
+ MAX_PRED_BINS = 672,
+
+ ID_SCE = 0,
+ ID_CPE,
+ ID_CCE,
+ ID_LFE,
+ ID_DSE,
+ ID_PCE,
+ ID_FIL,
+ ID_END
+}
+ElementId;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/e_huffmanconst.h b/media/libstagefright/codecs/aacdec/e_huffmanconst.h
new file mode 100644
index 0000000..5d0e628
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_huffmanconst.h
@@ -0,0 +1,119 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/e_HuffmanConst.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ enum for Huffman related constants
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_HUFFMAN_CONST_H
+#define E_HUFFMAN_CONST_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ /*
+ * specify huffman tables as signed (1) or unsigned (0)
+ */
+ HUF1SGN = 1,
+ HUF2SGN = 1,
+ HUF3SGN = 0,
+ HUF4SGN = 0,
+ HUF5SGN = 1,
+ HUF6SGN = 1,
+ HUF7SGN = 0,
+ HUF8SGN = 0,
+ HUF9SGN = 0,
+ HUF10SGN = 0,
+ HUF11SGN = 0,
+
+ ZERO_HCB = 0,
+ BY4BOOKS = 4,
+ ESCBOOK = 11,
+ NSPECBOOKS = ESCBOOK + 1,
+ BOOKSCL = NSPECBOOKS,
+ NBOOKS = NSPECBOOKS + 1,
+ INTENSITY_HCB2 = 14,
+ INTENSITY_HCB = 15,
+ NOISE_HCB = 13,
+ NOISE_HCB2 = 113,
+
+ NOISE_PCM_BITS = 9,
+ NOISE_PCM_OFFSET = (1 << (NOISE_PCM_BITS - 1)),
+
+ NOISE_OFFSET = 90,
+
+ LONG_SECT_BITS = 5,
+ SHORT_SECT_BITS = 3
+} eHuffmanConst;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/e_infoinitconst.h b/media/libstagefright/codecs/aacdec/e_infoinitconst.h
new file mode 100644
index 0000000..788b5e9
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_infoinitconst.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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/e_infoinitConst.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ enum for Infoinit related constants
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_INFOINIT_CONST_H
+#define E_INFOINIT_CONST_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "chans.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ /* block switch windows for single channels or channel pairs */
+ Winds = Chans,
+
+ /* average channel block length, bytes */
+ Avjframe = 341,
+
+ TEXP = 128, /* size of exp cache table */
+ MAX_IQ_TBL = 128, /* size of inv quant table */
+ MAXFFT = LN4
+
+} infoinitConst;
+
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/e_invf_mode.h b/media/libstagefright/codecs/aacdec/e_invf_mode.h
new file mode 100644
index 0000000..57b3281
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_invf_mode.h
@@ -0,0 +1,91 @@
+/* ------------------------------------------------------------------
+ * 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: e_invf_mode.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_INVF_MODE_H
+#define E_INVF_MODE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ INVF_OFF,
+ INVF_LOW_LEVEL,
+ INVF_MID_LEVEL,
+ INVF_HIGH_LEVEL,
+
+ INVF_NO_OVERRIDE
+}
+INVF_MODE;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/e_maskstatus.h b/media/libstagefright/codecs/aacdec/e_maskstatus.h
new file mode 100644
index 0000000..010b6f8
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_maskstatus.h
@@ -0,0 +1,91 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/e_MaskStatus.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file gives the enum of mask_present value used in getmask.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_MASKSTATUS_H
+#define E_MASKSTATUS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+enum
+{
+ MASK_NOT_PRESENT,
+ MASK_FROM_BITSTREAM,
+ MASK_ALL_FRAME,
+ MASK_ERROR
+};
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/e_mp4ff_const.h b/media/libstagefright/codecs/aacdec/e_mp4ff_const.h
new file mode 100644
index 0000000..1006406
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_mp4ff_const.h
@@ -0,0 +1,105 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: e_MP4FF_const.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file enums the constants used by MP4FF header
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_MP4FF_CONST_H
+#define E_MP4FF_CONST_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ LEN_OBJ_TYPE = 5,
+ LEN_SAMP_RATE_IDX = 4,
+ LEN_SAMP_RATE = 24,
+ LEN_CHAN_CONFIG = 4,
+ LEN_SYNC_EXTENSION_TYPE = 11,
+ LEN_FRAME_LEN_FLAG = 1,
+ LEN_DEPEND_ON_CORE = 1,
+ LEN_CORE_DELAY = 14,
+ LEN_EXT_FLAG = 1,
+ LEN_EP_CONFIG = 2,
+ LEN_LAYER_NUM = 3,
+ LEN_SUB_FRAME = 5,
+ LEN_LAYER_LEN = 11,
+ LEN_SECT_RES_FLAG = 1,
+ LEN_SCF_RES_FLAG = 1,
+ LEN_SPEC_RES_FLAG = 1,
+ LEN_EXT_FLAG3 = 1
+} eMP4FF_const;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/e_progconfigconst.h b/media/libstagefright/codecs/aacdec/e_progconfigconst.h
new file mode 100644
index 0000000..b5fdc08
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_progconfigconst.h
@@ -0,0 +1,110 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: e_ProgConfigConst.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ enum for ProgConfig related constants
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_PROG_CONFIG_CONST_H
+#define E_PROG_CONFIG_CONST_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ /*
+ * Program Configuration
+ */
+ Main_Profile = 0,
+ LC_Profile = 1,
+
+ Fs_48 = 3,
+ Fs_44 = 4,
+ Fs_32 = 5,
+
+ LEN_PROFILE = 2,
+ LEN_SAMP_IDX = 4,
+ LEN_NUM_ELE = 4,
+ LEN_NUM_LFE = 2,
+ LEN_NUM_DAT = 3,
+ LEN_NUM_CCE = 4,
+ LEN_MIX_PRES = 1,
+ LEN_MMIX_IDX = 2,
+ LEN_PSUR_ENAB = 1,
+ LEN_ELE_IS_CPE = 1,
+ LEN_IND_SW_CCE = 1,
+ LEN_COMMENT_BYTES = 8
+
+} eProgConfigConst;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/e_rawbitstreamconst.h b/media/libstagefright/codecs/aacdec/e_rawbitstreamconst.h
new file mode 100644
index 0000000..a460d13
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_rawbitstreamconst.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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: e_RawBitstreamConst.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ enum for the Raw Bitstream related constants
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_RAW_BITSTREAM_CONST_H
+#define E_RAW_BITSTREAM_CONST_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ LEN_SE_ID = 3,
+ LEN_TAG = 4,
+ LEN_COM_WIN = 1,
+ LEN_ICS_RESERV = 1,
+ LEN_WIN_SEQ = 2,
+ LEN_WIN_SH = 1,
+ LEN_MAX_SFBL = 6,
+ LEN_MAX_SFBS = 4,
+ LEN_CB = 4,
+ LEN_SCL_PCM = 8,
+ LEN_PRED_PRES = 1,
+ LEN_PRED_RST = 1,
+ LEN_PRED_RSTGRP = 5,
+ LEN_PRED_ENAB = 1,
+ LEN_MASK_PRES = 2,
+ LEN_MASK = 1,
+ LEN_PULSE_PRES = 1,
+ LEN_TNS_PRES = 1,
+ LEN_GAIN_PRES = 1,
+
+ LEN_PULSE_NPULSE = 2,
+ LEN_PULSE_ST_SFB = 6,
+ LEN_PULSE_POFF = 5,
+ LEN_PULSE_PAMP = 4,
+ NUM_PULSE_LINES = 4,
+ PULSE_OFFSET_AMP = 4,
+
+ LEN_IND_CCE_FLG = 1,
+ LEN_NCC = 3,
+ LEN_IS_CPE = 1,
+ LEN_CC_LR = 1,
+ LEN_CC_DOM = 1,
+ LEN_CC_SGN = 1,
+ LEN_CCH_GES = 2,
+ LEN_CCH_CGP = 1,
+
+ LEN_D_ALIGN = 1,
+ LEN_D_CNT = 8,
+ LEN_D_ESC = 8,
+ LEN_F_CNT = 4,
+ LEN_F_ESC = 8,
+ LEN_BYTE = 8,
+ LEN_PAD_DATA = 8,
+
+ LEN_PC_COMM = 9
+
+} eRawBitstreamConst;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/e_sbr_element_id.h b/media/libstagefright/codecs/aacdec/e_sbr_element_id.h
new file mode 100644
index 0000000..1b021ff
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_sbr_element_id.h
@@ -0,0 +1,87 @@
+/* ------------------------------------------------------------------
+ * 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: e_sbr_element_id.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_SBR_ELEMENT_ID_H
+#define E_SBR_ELEMENT_ID_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ SBR_ID_SCE = 0,
+ SBR_ID_CPE
+}
+SBR_ELEMENT_ID;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/e_sbr_error.h b/media/libstagefright/codecs/aacdec/e_sbr_error.h
new file mode 100644
index 0000000..b6c8a90
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_sbr_error.h
@@ -0,0 +1,106 @@
+/* ------------------------------------------------------------------
+ * 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: e_sbr_error.h
+ Funtions:
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_SBR_ERROR_H
+#define E_SBR_ERROR_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define HANDLE_ERROR_INFO Int32
+#define noError 0
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+typedef enum
+{
+ SBRDEC_OK = 0,
+ SBRDEC_NOSYNCH,
+ SBRDEC_ILLEGAL_PROGRAM,
+ SBRDEC_ILLEGAL_TAG,
+ SBRDEC_ILLEGAL_CHN_CONFIG,
+ SBRDEC_ILLEGAL_SECTION,
+ SBRDEC_ILLEGAL_SCFACTORS,
+ SBRDEC_ILLEGAL_PULSE_DATA,
+ SBRDEC_MAIN_PROFILE_NOT_IMPLEMENTED,
+ SBRDEC_GC_NOT_IMPLEMENTED,
+ SBRDEC_ILLEGAL_PLUS_ELE_ID,
+ SBRDEC_CREATE_ERROR,
+ SBRDEC_NOT_INITIALIZED,
+ SBRDEC_TOO_MANY_SBR_ENVELOPES,
+ SBRDEC_INVALID_BITSTREAM
+}
+SBR_ERROR;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/e_sbr_header_status.h b/media/libstagefright/codecs/aacdec/e_sbr_header_status.h
new file mode 100644
index 0000000..5b2a43f
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_sbr_header_status.h
@@ -0,0 +1,88 @@
+/* ------------------------------------------------------------------
+ * 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: e_sbr_header_status.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_SBR_HEADER_STATUS_H
+#define E_SBR_HEADER_STATUS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ HEADER_OK,
+ HEADER_RESET,
+ HEADER_NOT_INITIALIZED
+}
+SBR_HEADER_STATUS;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/e_sbr_master_status.h b/media/libstagefright/codecs/aacdec/e_sbr_master_status.h
new file mode 100644
index 0000000..16e43a4
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_sbr_master_status.h
@@ -0,0 +1,87 @@
+/* ------------------------------------------------------------------
+ * 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: e_sbr_master_status.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_SBR_MASTER_STATUS_H
+#define E_SBR_MASTER_STATUS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ MASTER_OK,
+ MASTER_RESET
+}
+SBR_MASTER_STATUS;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/e_sbr_sync_state.h b/media/libstagefright/codecs/aacdec/e_sbr_sync_state.h
new file mode 100644
index 0000000..d9f8669
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_sbr_sync_state.h
@@ -0,0 +1,88 @@
+/* ------------------------------------------------------------------
+ * 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: e_sbr_sync_state.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_SBR_SYNC_STATE_H
+#define E_SBR_SYNC_STATE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ SBR_NOT_INITIALIZED,
+ UPSAMPLING,
+ SBR_ACTIVE
+}
+SBR_SYNC_STATE;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/e_sr_mode.h b/media/libstagefright/codecs/aacdec/e_sr_mode.h
new file mode 100644
index 0000000..eff00dd
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_sr_mode.h
@@ -0,0 +1,88 @@
+/* ------------------------------------------------------------------
+ * 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: e_sr_mode.h
+ Funtions:
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_SR_MODE_H
+#define E_SR_MODE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ SINGLE_RATE = 1,
+ UP_BY_2
+}
+SR_MODE;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/e_tmp4audioobjecttype.h b/media/libstagefright/codecs/aacdec/e_tmp4audioobjecttype.h
new file mode 100644
index 0000000..83cccce
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_tmp4audioobjecttype.h
@@ -0,0 +1,118 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/e_tMP4AudioObjectType.h
+
+ This file contains enumerated types for MP4 Audio Object Types, as defined
+ in ISO/IEC 14496-3, AMMENDMENT 1 Dated 2000-09-15
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_TMP4AUDIOOBJECTTYPE_H
+#define E_TMP4AUDIOOBJECTTYPE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ typedef enum eMP4AudioObjectType
+ {
+ MP4AUDIO_NULL = 0, /* */
+ MP4AUDIO_AAC_MAIN = 1, /* */
+ MP4AUDIO_AAC_LC = 2, /* LC = Low Complexity */
+ MP4AUDIO_AAC_SSR = 3, /* SSR = Scalable Sampling Rate */
+ MP4AUDIO_LTP = 4, /* LTP = Long Term Prediction */
+ MP4AUDIO_SBR = 5, /* SBR = Spectral Band Replication */
+ MP4AUDIO_AAC_SCALABLE = 6, /* scales both bitrate and sampling rate */
+ MP4AUDIO_TWINVQ = 7, /* low bit rate */
+ MP4AUDIO_CELP = 8,
+ MP4AUDIO_HVXC = 9,
+ /* 10 is reserved */
+ /* 11 is reserved */
+ MP4AUDIO_TTSI = 12,
+ /* 13-16 are synthesis and MIDI types */
+ MP4AUDIO_ER_AAC_LC = 17, /* */
+ /* 18 is reserved */
+ MP4AUDIO_ER_AAC_LTP = 19, /* */
+ MP4AUDIO_ER_AAC_SCALABLE = 20, /* */
+ MP4AUDIO_ER_TWINVQ = 21, /* */
+ MP4AUDIO_ER_BSAC = 22, /* */
+ MP4AUDIO_ER_AAC_LD = 23, /* */
+ MP4AUDIO_ER_CELP = 24, /* */
+ MP4AUDIO_ER_HVXC = 25, /* */
+ MP4AUDIO_ER_HILN = 26, /* */
+ MP4AUDIO_PARAMETRIC = 27, /* */
+ MP4AUDIO_PS = 29 /* Explicit Parametric Stereo */
+
+ } tMP4AudioObjectType;
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /* Should not be any function declarations in this file */
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* E_TMP4AUDIOOBJECTTYPE_H */
+
+
diff --git a/media/libstagefright/codecs/aacdec/e_tns_const.h b/media/libstagefright/codecs/aacdec/e_tns_const.h
new file mode 100644
index 0000000..157d471
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_tns_const.h
@@ -0,0 +1,91 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/e_TNS_Const.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ enum for TNS related constants
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_TNS_CONST_H
+#define E_TNS_CONST_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ TNS_MAX_BANDS = 49,
+ TNS_MAX_ORDER = 20,
+ TNS_MAX_WIN = 8,
+ TNS_MAX_FILT = 3,
+ Q_SPEC = 11,
+ Q_LPC = 19
+
+} eTNS_Const;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/e_window_sequence.h b/media/libstagefright/codecs/aacdec/e_window_sequence.h
new file mode 100644
index 0000000..c4b933e
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_window_sequence.h
@@ -0,0 +1,90 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/e_WINDOW_SEQUENCE.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ enum for Window Sequence related constants
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_WINDOW_SEQUENCE_H
+#define E_WINDOW_SEQUENCE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ ONLY_LONG_SEQUENCE,
+ LONG_START_SEQUENCE,
+ EIGHT_SHORT_SEQUENCE,
+ LONG_STOP_SEQUENCE,
+ NUM_WINDOW_SEQUENCE,
+ ENSURE_WINDOW_SEQUENCE_INT_SIZE = 0x7FFFFF
+}
+WINDOW_SEQUENCE;
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/e_window_shape.h b/media/libstagefright/codecs/aacdec/e_window_shape.h
new file mode 100644
index 0000000..3eca438
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/e_window_shape.h
@@ -0,0 +1,89 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: e_Window_shape.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ enum for Window Sequence related constants
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_WINDOW_SHAPE_H
+#define E_WINDOW_SHAPE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+ SINE_WINDOW = 0,
+ KAISER_BESSEL_WINDOW,
+ NUM_WINDOW_SHAPES,
+ ENSURE_WINDOW_SHAPE_INT_SIZE = 0x7FFFFF
+}
+WINDOW_SHAPE;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/esc_iquant_scaling.cpp b/media/libstagefright/codecs/aacdec/esc_iquant_scaling.cpp
new file mode 100644
index 0000000..778c88c
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/esc_iquant_scaling.cpp
@@ -0,0 +1,789 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/esc_iquant_scaling.c
+ Funtions: esc_iquant_scaling
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from esc_iquant_fxp.c code
+
+ Description: Eliminated unused variables to avoid warnings, changed header
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ quantSpec[] = array of quantized compressed spectral coefficients, of
+ data type Int and length sfbWidth.
+
+ sfbWidth = number of array elements in quantSpec and the output array
+ coef, data type Int.
+
+ coef[] = output array of uncompressed coefficients, stored in a
+ variable Q format, depending on the maximum value found
+ for the group, array of Int32, length sfbWdith to be
+ overwritten.
+
+ QFormat = the output Q format for the array coef[].
+
+
+ scale = scaling factor after separating power of 2 factor out from
+ 0.25*(sfb_scale - 100), i.e., 0.25*sfb_scale.
+
+ maxInput = maximum absolute value of quantSpec.
+
+ Local Stores/Buffers/Pointers Needed: None.
+
+ Global Stores/Buffers/Pointers Needed:
+ inverseQuantTable = lookup table of const integer values to the one third
+ power stored in Q27 format, in file iquant_table.c, const
+ array of UInt32, of size 1025.
+
+ Outputs: None
+
+ Pointers and Buffers Modified:
+ coef[] contents are overwritten with the uncompressed values from
+ quantSpec[]
+
+
+
+
+ Local Stores Modified: None.
+
+ Global Stores Modified: None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the inverse quantization of the spectral coeficients
+ read from huffman decoding. It takes each input array value to the four
+ thirds power, then scales it according to the scaling factor input argument
+ ,and stores the result in the output array in a variable Q format
+ depending upon the maximum input value found.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function shall not have static or global variables.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 13818-7:1997 Titled "Information technology - Generic coding
+ of moving pictures and associated audio information - Part 7: Advanced
+ Audio Coding (AAC)", Section 10.3, "Decoding process", page 43.
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ maxInput = 0;
+
+ FOR (i = sfbWidth - 1; i >= 0; i--)
+ x = quantSpec[i];
+
+ IF ( x >= 0)
+ absX = x;
+ ELSE
+ absX = -x;
+ ENDIF
+
+ coef[i] = absX;
+
+ IF (absX > maxInput)
+ maxInput = absX;
+ ENDIF
+ ENDFOR
+
+ IF (maxInput == 0)
+ *pQFormat = QTABLE;
+ ELSE
+ temp = inverseQuantTable[(maxInput >> ORDER) + 1];
+
+ temp += ((1 << (QTABLE))-1);
+
+ temp >>= (QTABLE-1);
+
+ temp *= maxInput;
+
+ binaryDigits = 0;
+ WHILE( temp != 0)
+ temp >>= 1;
+ binaryDigits++;
+ WEND
+
+ IF (binaryDigits < (SIGNED32BITS - QTABLE))
+ binaryDigits = SIGNED32BITS - QTABLE;
+ ENDIF
+
+ *pQFormat = SIGNED32BITS - binaryDigits;
+ shift = QTABLE - *pQFormat;
+
+ IF (maxInput < TABLESIZE)
+ FOR (i = sfbWidth - 1; i >= 0; i--)
+ x = quantSpec[i];
+
+ absX = coef[i];
+
+ tmp_coef = x * (inverseQuantTable[absX] >> shift);
+
+ b_low = (tmp_coef & 0xFFFF);
+ b_high = (tmp_coef >> 16);
+
+ mult_low = ( (UInt32) b_low * scale );
+ mult_high = ( (Int32) b_high * scale );
+
+ mult_low >>= 16;
+
+ coef[i] = (Int32) (mult_high + mult_low);
+
+ ENDFOR
+ ELSE
+ FOR (i = sfbWidth; i >= 0 ; i--)
+ x = quantSpec[i];
+ absX = coef[i];
+
+ IF (absX < TABLESIZE)
+ tmp_coef = x * (inverseQuantTable[absX] >> shift);
+ ELSE
+ index = absX >> ORDER;
+ w1 = inverseQuantTable[index];
+
+ approxOneThird = (w1 * FACTOR) >> shift;
+
+
+ x1 = index * SPACING;
+ w2 = inverseQuantTable[index+1];
+
+ deltaOneThird = (w2 - w1) * (absX - x1);
+
+ deltaOneThird >>= (shift + ORDER - 1);
+
+ tmp_coef = x * (approxOneThird + deltaOneThird);
+
+ ENDIF
+
+ b_low = (mult_high & 0xFFFF);
+ b_high = (mult_high >> 16);
+
+ mult_low = ( (UInt32) b_low * scale );
+ mult_high = ( (Int32) b_high * scale );
+
+ mult_low >>= 16;
+
+ coef[i] = (Int32) (mult_high + mult_low);
+
+ ENDFOR
+ ENDIF
+ ENDIF
+
+ RETURN
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "iquant_table.h"
+#include "esc_iquant_scaling.h"
+#include "aac_mem_funcs.h" /* For pv_memset */
+
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+/*
+ * Read further on what order is.
+ * Note: If ORDER is not a multiple of 3, FACTOR is not an integer.
+ * Note: Portions of this function assume ORDER is 3, and so does the table
+ * in iquant_table.c
+ */
+#define ORDER (3)
+/*
+ * For input values > TABLESIZE, multiply by FACTOR to get x ^ (1/3)
+ * FACTOR = 2 ^ (ORDER/3)
+ */
+#define FACTOR (2)
+
+/*
+ * This is one more than the range of expected inputs.
+ */
+#define INPUTRANGE (8192)
+
+/*
+ * SPACING is 2 ^ ORDER, and is the spacing between points when in the
+ * interpolation range.
+ */
+#define SPACING (1<<ORDER)
+
+/*
+ * The actual table size is one more than TABLESIZE, to allow for
+ * interpolation for numbers near 8191
+ */
+#define TABLESIZE (INPUTRANGE/SPACING)
+
+/*
+ * Format the table is stored in.
+ */
+#define QTABLE (27)
+
+/*
+ * Number of bits for data in a signed 32 bit integer.
+ */
+#define SIGNED32BITS (31)
+
+/*
+ * Round up value for intermediate values obtained from the table
+ */
+#define ROUND_UP (( ((UInt32) 1) << (QTABLE) )-1)
+
+#define MASK_LOW16 0xffff
+#define UPPER16 16
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*
+ * Processing in this function is performed in these steps:
+ *
+ * 1) Find the overall Q format for the entire group of inputs. This consists
+ * of:
+ * a) Finding the maximum input
+ * b) estimate the maximum output
+ * c) Using the table, get max ^ (4/3), taking into account the table is
+ * in q format.
+ * 2) For each array element, see if the value is directly inside the table.
+ * a) If yes, just multiply by table value by itself, then shift as
+ * appropriate.
+ * b) If no, get an approximation (described below) for x ^ (1/3) by linearly
+ * interpolating using lower values in the table, then multiply by a
+ * correction factor, then multiply by x (see below).
+ *
+ * It more accurate to interpolate x ^ (1/3) then x ^ (4/3), so that is stored
+ * in the lookup table. For values not in the table, interpolation is used:
+ *
+ * We want y = x ^ (4/3) = x * (x ^ (1/3))
+ *
+ * Let x = w * (2 ^ m) where m is a constant, = ORDER
+ *
+ * then x ^ (1/3) = w ^ (1/3) * (2 ^ (m/3))
+ *
+ * w is most likely not an integer, so an interpolation with floor(w) and
+ * ceil(w) can be performed to approximate w ^ (1/3) by getting values out of
+ * the table. Then to get x ^ (1/3), multiply by FACTOR. If m = 0, 3, 6,
+ * then FACTOR is a simple power of 2, so a shift can do the job.
+ *
+ * The actual code employs some more tricks to speed things up, and because
+ * the table is stored in Q format.
+ *
+ * Rather than saving the sign of each input, the unsigned value of
+ * abs(x) ^ (1/3) is multiplied by the signed input value.
+ */
+
+
+
+#if ( defined(_ARM) || defined(_ARM_V4))
+
+/*
+ * Absolute value for 16 bit-numbers
+ */
+__inline Int32 abs2(Int32 x)
+{
+ Int32 z;
+ /*
+ z = x - (x<0);
+ x = z ^ sign(z)
+ */
+ __asm
+ {
+ sub z, x, x, lsr #31
+ eor x, z, z, asr #31
+ }
+ return (x);
+}
+
+
+#define pv_abs(x) abs2(x)
+
+
+#elif (defined(PV_ARM_GCC_V5)||defined(PV_ARM_GCC_V4))
+
+/*
+ * Absolute value for 16 bit-numbers
+ */
+__inline Int32 abs2(Int32 x)
+{
+ register Int32 z;
+ register Int32 y;
+ register Int32 ra = x;
+ asm volatile(
+ "sub %0, %2, %2, lsr #31\n\t"
+ "eor %1, %0, %0, asr #31"
+ : "=&r*i"(z),
+ "=&r*i"(y)
+ : "r"(ra));
+
+ return (y);
+}
+
+#define pv_abs(x) abs2(x)
+
+
+#else
+
+#define pv_abs(x) ((x) > 0)? (x) : (-x)
+
+#endif
+
+
+
+
+
+void esc_iquant_scaling(
+ const Int16 quantSpec[],
+ Int32 coef[],
+ const Int sfbWidth,
+ Int const QFormat,
+ UInt16 scale,
+ Int maxInput)
+{
+ Int i;
+ Int x;
+ Int y;
+ Int index;
+ Int shift;
+ UInt absX;
+ UInt32 w1, w2;
+ UInt32 deltaOneThird;
+ UInt32 x1;
+ UInt32 approxOneThird;
+ Int32 mult_high;
+
+
+#if ( defined(_ARM) || defined(_ARM_V4))
+
+ {
+ Int32 *temp;
+ Int32 R12, R11, R10, R9;
+
+ deltaOneThird = sizeof(Int32) * sfbWidth;
+ temp = coef;
+
+ // from standard library call for __rt_memset
+ __asm
+ {
+ MOV R12, #0x0
+ MOV R11, #0x0
+ MOV R10, #0x0
+ MOV R9, #0x0
+ SUBS deltaOneThird, deltaOneThird, #0x20
+loop:
+ STMCSIA temp!, {R12, R11, R10, R9}
+ STMCSIA temp!, {R12, R11, R10, R9}
+ SUBCSS deltaOneThird, deltaOneThird, #0x20
+ BCS loop
+
+ MOVS deltaOneThird, deltaOneThird, LSL #28
+ STMCSIA temp!, {R12, R11, R10, R9}
+ STMMIIA temp!, {R12, R11}
+ }
+ }
+
+#else
+ pv_memset(coef, 0, sizeof(Int32) * sfbWidth);
+#endif
+
+ if (maxInput > 0)
+ {
+
+ shift = QTABLE - QFormat;
+
+ if (scale != 0)
+ {
+ if (maxInput < TABLESIZE)
+ {
+
+ for (i = sfbWidth - 1; i >= 0; i -= 4)
+ {
+ x = quantSpec[i];
+ y = quantSpec[i-1];
+ if (x)
+ {
+ absX = pv_abs(x);
+ mult_high = (x * (inverseQuantTable[absX] >> shift));
+ coef[i] = fxp_mul32_by_16(mult_high, scale) << 1;
+ }
+
+ if (y)
+ {
+ absX = pv_abs(y);
+ mult_high = y * (inverseQuantTable[absX] >> shift);
+ coef[i-1] = fxp_mul32_by_16(mult_high, scale) << 1;
+ }
+
+ x = quantSpec[i-2];
+ y = quantSpec[i-3];
+ if (x)
+ {
+ absX = pv_abs(x);
+ mult_high = x * (inverseQuantTable[absX] >> shift);
+ coef[i-2] = fxp_mul32_by_16(mult_high, scale) << 1;
+ }
+
+ if (y)
+ {
+ absX = pv_abs(y);
+ mult_high = y * (inverseQuantTable[absX] >> shift);
+ coef[i-3] = fxp_mul32_by_16(mult_high, scale) << 1;
+ }
+ } /* end for (i = sfbWidth - 1; i >= 0; i--) */
+
+ } /* end if (maxInput < TABLESIZE)*/
+
+ else /* maxInput >= TABLESIZE) */
+ {
+ for (i = sfbWidth - 1; i >= 0; i -= 4)
+ {
+ x = quantSpec[i];
+ if (x)
+ {
+ absX = pv_abs(x);
+ if (absX < TABLESIZE)
+ {
+ mult_high = x * (inverseQuantTable[absX] >> shift);
+ coef[i] = fxp_mul32_by_16(mult_high, scale) << 1;
+
+ }
+ else
+ {
+ index = absX >> ORDER;
+ w1 = inverseQuantTable[index];
+ w2 = inverseQuantTable[index+1];
+ approxOneThird = (w1 * FACTOR) >> shift;
+ x1 = index << ORDER;
+ deltaOneThird = (w2 - w1) * (absX - x1);
+ deltaOneThird >>= (shift + 2);
+ mult_high = x * (approxOneThird + deltaOneThird);
+ coef[i] = fxp_mul32_by_16(mult_high, scale) << 1;
+
+ }
+ } /* if(x) */
+
+
+ x = quantSpec[i-1];
+ if (x)
+ {
+ absX = pv_abs(x);
+ if (absX < TABLESIZE)
+ {
+ mult_high = (x * (inverseQuantTable[absX] >> shift));
+ coef[i-1] = fxp_mul32_by_16(mult_high, scale) << 1;
+
+ }
+ else
+ {
+ index = absX >> ORDER;
+ w1 = inverseQuantTable[index];
+ w2 = inverseQuantTable[index+1];
+ approxOneThird = (w1 * FACTOR) >> shift;
+ x1 = index << ORDER;
+ deltaOneThird = (w2 - w1) * (absX - x1);
+ deltaOneThird >>= (shift + 2);
+ mult_high = x * (approxOneThird + deltaOneThird);
+ coef[i-1] = fxp_mul32_by_16(mult_high, scale) << 1;
+ }
+ } /* if(x) */
+
+ x = quantSpec[i-2];
+ if (x)
+ {
+ absX = pv_abs(x);
+ if (absX < TABLESIZE)
+ {
+ mult_high = x * (inverseQuantTable[absX] >> shift);
+ coef[i-2] = fxp_mul32_by_16(mult_high, scale) << 1;
+ }
+ else
+ {
+ index = absX >> ORDER;
+ w1 = inverseQuantTable[index];
+ w2 = inverseQuantTable[index+1];
+ approxOneThird = (w1 * FACTOR) >> shift;
+ x1 = index << ORDER;
+ deltaOneThird = (w2 - w1) * (absX - x1);
+ deltaOneThird >>= (shift + 2);
+ mult_high = x * (approxOneThird + deltaOneThird);
+ coef[i-2] = fxp_mul32_by_16(mult_high, scale) << 1;
+ }
+ } /* if(x) */
+
+ x = quantSpec[i-3];
+ if (x)
+ {
+ absX = pv_abs(x);
+ if (absX < TABLESIZE)
+ {
+ mult_high = x * (inverseQuantTable[absX] >> shift);
+ coef[i-3] = fxp_mul32_by_16(mult_high, scale) << 1;
+
+ }
+ else
+ {
+ index = absX >> ORDER;
+ w1 = inverseQuantTable[index];
+ w2 = inverseQuantTable[index+1];
+ approxOneThird = (w1 * FACTOR) >> shift;
+ x1 = index << ORDER;
+ deltaOneThird = (w2 - w1) * (absX - x1);
+ deltaOneThird >>= (shift + 2);
+ mult_high = x * (approxOneThird + deltaOneThird);
+ coef[i-3] = fxp_mul32_by_16(mult_high, scale) << 1;
+
+ }
+ } /* if(x) */
+
+ } /* end for (i = sfbWidth - 1; i >= 0; i--) */
+ } /* end else for if (maxInput < TABLESIZE)*/
+ }
+ else /* scale == 0 */
+ {
+ if (maxInput < TABLESIZE)
+ {
+ for (i = sfbWidth - 1; i >= 0; i -= 4)
+ {
+ x = quantSpec[i];
+ y = quantSpec[i-1];
+ if (x)
+ {
+ absX = pv_abs(x);
+ mult_high = x * (inverseQuantTable[absX] >> shift);
+ coef[i] = mult_high >> 1;
+ }
+
+ if (y)
+ {
+ absX = pv_abs(y);
+ mult_high = y * (inverseQuantTable[absX] >> shift);
+ coef[i-1] = mult_high >> 1;
+ }
+
+ x = quantSpec[i-2];
+ y = quantSpec[i-3];
+ if (x)
+ {
+ absX = pv_abs(x);
+ mult_high = x * (inverseQuantTable[absX] >> shift);
+ coef[i-2] = mult_high >> 1;
+ }
+
+ if (y)
+ {
+ absX = pv_abs(y);
+ mult_high = y * (inverseQuantTable[absX] >> shift);
+ coef[i-3] = mult_high >> 1;
+ }
+ }
+
+ } /* end if (maxInput < TABLESIZE)*/
+
+ else /* maxInput >= TABLESIZE) */
+ {
+ for (i = sfbWidth - 1; i >= 0; i -= 4)
+ {
+ x = quantSpec[i];
+ if (x)
+ {
+ absX = pv_abs(x);
+ if (absX < TABLESIZE)
+ {
+ mult_high = x * (inverseQuantTable[absX] >> shift);
+ coef[i] = (mult_high >> 1);
+ } /* end if (absX < TABLESIZE) */
+ else
+ {
+ index = absX >> ORDER;
+ w1 = inverseQuantTable[index];
+ w2 = inverseQuantTable[index+1];
+ approxOneThird = (w1 * FACTOR) >> shift;
+ x1 = index << ORDER;
+ deltaOneThird = (w2 - w1) * (absX - x1);
+ deltaOneThird >>= (shift + 2);
+ mult_high = x * (approxOneThird + deltaOneThird);
+ coef[i] = (mult_high >> 1);
+ }
+ } /* if(x) */
+
+ x = quantSpec[i-1];
+ if (x)
+ {
+ absX = pv_abs(x);
+ if (absX < TABLESIZE)
+ {
+ mult_high = x * (inverseQuantTable[absX] >> shift);
+ coef[i-1] = (mult_high >> 1);
+ } /* end if (absX < TABLESIZE) */
+ else
+ {
+ index = absX >> ORDER;
+ w1 = inverseQuantTable[index];
+ w2 = inverseQuantTable[index+1];
+ approxOneThird = (w1 * FACTOR) >> shift;
+ x1 = index << ORDER;
+ deltaOneThird = (w2 - w1) * (absX - x1);
+ deltaOneThird >>= (shift + 2);
+ mult_high = x * (approxOneThird + deltaOneThird);
+ coef[i-1] = (mult_high >> 1);
+ }
+ } /* if(x) */
+
+ x = quantSpec[i-2];
+ if (x)
+ {
+ absX = pv_abs(x);
+ if (absX < TABLESIZE)
+ {
+ mult_high = x * (inverseQuantTable[absX] >> shift);
+ coef[i-2] = (mult_high >> 1);
+ } /* end if (absX < TABLESIZE) */
+ else
+ {
+ index = absX >> ORDER;
+ w1 = inverseQuantTable[index];
+ w2 = inverseQuantTable[index+1];
+ approxOneThird = (w1 * FACTOR) >> shift;
+ x1 = index << ORDER;
+ deltaOneThird = (w2 - w1) * (absX - x1);
+ deltaOneThird >>= (shift + 2);
+ mult_high = x * (approxOneThird + deltaOneThird);
+ coef[i-2] = (mult_high >> 1);
+ }
+ } /* if(x) */
+
+ x = quantSpec[i-3];
+ if (x)
+ {
+ absX = pv_abs(x);
+ if (absX < TABLESIZE)
+ {
+ mult_high = x * (inverseQuantTable[absX] >> shift);
+ coef[i-3] = (mult_high >> 1);
+ } /* end if (absX < TABLESIZE) */
+ else
+ {
+ index = absX >> ORDER;
+ w1 = inverseQuantTable[index];
+ w2 = inverseQuantTable[index+1];
+ approxOneThird = (w1 * FACTOR) >> shift;
+ x1 = index << ORDER;
+ deltaOneThird = (w2 - w1) * (absX - x1);
+ deltaOneThird >>= (shift + 2);
+ mult_high = x * (approxOneThird + deltaOneThird);
+ coef[i-3] = (mult_high >> 1);
+ }
+
+ } /* if(x) */
+
+ } /* end for (i = sfbWidth - 1; i >= 0; i--) */
+
+ } /* end else for if (maxInput < TABLESIZE)*/
+
+ } /* end else for if(scale!=0) */
+
+ } /* end else for if(maxInput == 0) */
+
+} /* end esc_iquant_fxp */
+
+
diff --git a/media/libstagefright/codecs/aacdec/esc_iquant_scaling.h b/media/libstagefright/codecs/aacdec/esc_iquant_scaling.h
new file mode 100644
index 0000000..a846b9f
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/esc_iquant_scaling.h
@@ -0,0 +1,102 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/esc_iquant_scaling.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for esc_iquant_scaling.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef ESC_IQUANT_SCALING_H
+#define ESC_IQUANT_SCALING_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ void esc_iquant_scaling(
+ const Int16 quantSpec[],
+ Int32 coef[],
+ const Int sfbWidth,
+ Int const pQFormat,
+ UInt16 scale,
+ Int maxInput);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* ESC_IQUANT_SCALING_H */
+
+
diff --git a/media/libstagefright/codecs/aacdec/extractframeinfo.cpp b/media/libstagefright/codecs/aacdec/extractframeinfo.cpp
new file mode 100644
index 0000000..571cc98
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/extractframeinfo.cpp
@@ -0,0 +1,487 @@
+/* ------------------------------------------------------------------
+ * 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: extractframeInfo.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Arguments: hBitBuf - bitbuffer handle
+ v_frame_info - pointer to memorylocation where the frame-info will
+ be stored.
+
+ Return: none.
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+Extracts a frame_info vector from control data read from the bitstream.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "extractframeinfo.h"
+#include "buf_getbits.h"
+#include "aac_mem_funcs.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+ * (int) ceil (log (bs_num_env + 1) / log (2))
+ * ceil(log([0:5]+1)/log(2))
+ */
+
+const Int32 bs_pointer_bits_tbl[MAX_ENVELOPES + 1] = { 0, 1, 2, 2, 3, 3};
+
+/*
+ * (int)((float)numTimeSlots/bs_num_env + 0.5f)
+ * floor(16./[0:5] + 0.5)
+ */
+
+const Int32 T_16_ov_bs_num_env_tbl[MAX_ENVELOPES + 1] = { 2147483647, 16, 8,
+ 5, 4, 3
+ };
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+SBR_ERROR extractFrameInfo(BIT_BUFFER * hBitBuf,
+ SBR_FRAME_DATA * h_frame_data)
+{
+
+ Int32 absBordLead = 0;
+ Int32 nRelLead = 0;
+ Int32 nRelTrail = 0;
+ Int32 bs_num_env = 0;
+ Int32 bs_num_rel = 0;
+ Int32 bs_var_bord = 0;
+ Int32 bs_var_bord_0 = 0;
+ Int32 bs_var_bord_1 = 0;
+ Int32 bs_pointer = 0;
+ Int32 bs_pointer_bits;
+ Int32 frameClass;
+ Int32 temp;
+ Int32 env;
+ Int32 k;
+ Int32 bs_num_rel_0 = 0;
+ Int32 bs_num_rel_1 = 0;
+ Int32 absBordTrail = 0;
+ Int32 middleBorder = 0;
+ Int32 bs_num_noise;
+ Int32 lA = 0;
+
+ Int32 tE[MAX_ENVELOPES + 1];
+ Int32 tQ[2 + 1];
+ Int32 f[MAX_ENVELOPES + 1];
+ Int32 bs_rel_bord[3];
+ Int32 bs_rel_bord_0[3];
+ Int32 bs_rel_bord_1[3];
+ Int32 relBordLead[3];
+ Int32 relBordTrail[3];
+
+
+ Int32 *v_frame_info = h_frame_data->frameInfo;
+
+ SBR_ERROR err = SBRDEC_OK;
+
+
+ /*
+ * First read from the bitstream.
+ */
+
+ /* Read frame class */
+ h_frame_data->frameClass = frameClass = buf_getbits(hBitBuf, SBR_CLA_BITS);
+
+
+ switch (frameClass)
+ {
+
+ case FIXFIX:
+ temp = buf_getbits(hBitBuf, SBR_ENV_BITS); /* 2 bits */
+
+ bs_num_env = 1 << temp;
+
+
+ f[0] = buf_getbits(hBitBuf, SBR_RES_BITS); /* 1 bit */
+
+ for (env = 1; env < bs_num_env; env++)
+ {
+ f[env] = f[0];
+ }
+
+ nRelLead = bs_num_env - 1;
+ absBordTrail = 16;
+
+
+ break;
+
+ case FIXVAR:
+ bs_var_bord = buf_getbits(hBitBuf, SBR_ABS_BITS); /* 2 bits */
+ bs_num_rel = buf_getbits(hBitBuf, SBR_NUM_BITS); /* 2 bits */
+ bs_num_env = bs_num_rel + 1;
+
+ for (k = 0; k < bs_num_env - 1; k++)
+ {
+ bs_rel_bord[k] = (buf_getbits(hBitBuf, SBR_REL_BITS) + 1) << 1;
+ }
+
+ bs_pointer_bits = bs_pointer_bits_tbl[bs_num_env];
+
+ bs_pointer = buf_getbits(hBitBuf, bs_pointer_bits);
+
+ for (env = 0; env < bs_num_env; env++)
+ { /* 1 bit */
+ f[bs_num_env - 1 - env] = buf_getbits(hBitBuf, SBR_RES_BITS);
+ }
+
+ absBordTrail = 16 + bs_var_bord;
+ nRelTrail = bs_num_rel;
+
+ break;
+
+ case VARFIX:
+ bs_var_bord = buf_getbits(hBitBuf, SBR_ABS_BITS); /* 2 bits */
+ bs_num_rel = buf_getbits(hBitBuf, SBR_NUM_BITS); /* 2 bits */
+ bs_num_env = bs_num_rel + 1;
+
+ for (k = 0; k < bs_num_env - 1; k++)
+ {
+ bs_rel_bord[k] = (buf_getbits(hBitBuf, SBR_REL_BITS) + 1) << 1;
+ }
+
+ bs_pointer_bits = bs_pointer_bits_tbl[bs_num_env];
+
+ bs_pointer = buf_getbits(hBitBuf, bs_pointer_bits);
+
+ for (env = 0; env < bs_num_env; env++)
+ { /* 1 bit */
+ f[env] = buf_getbits(hBitBuf, SBR_RES_BITS);
+ }
+
+ absBordTrail = 16;
+ absBordLead = bs_var_bord;
+ nRelLead = bs_num_rel;
+
+ break;
+
+ case VARVAR:
+ bs_var_bord_0 = buf_getbits(hBitBuf, SBR_ABS_BITS); /* 2 bits */
+ bs_var_bord_1 = buf_getbits(hBitBuf, SBR_ABS_BITS);
+ bs_num_rel_0 = buf_getbits(hBitBuf, SBR_NUM_BITS); /* 2 bits */
+ bs_num_rel_1 = buf_getbits(hBitBuf, SBR_NUM_BITS);
+
+ bs_num_env = bs_num_rel_0 + bs_num_rel_1 + 1;
+
+ for (k = 0; k < bs_num_rel_0; k++)
+ { /* 2 bits */
+ bs_rel_bord_0[k] = (buf_getbits(hBitBuf, SBR_REL_BITS) + 1) << 1;
+ }
+
+ for (k = 0; k < bs_num_rel_1; k++)
+ { /* 2 bits */
+ bs_rel_bord_1[k] = (buf_getbits(hBitBuf, SBR_REL_BITS) + 1) << 1;
+ }
+
+
+ bs_pointer_bits = bs_pointer_bits_tbl[bs_num_env];
+
+ bs_pointer = buf_getbits(hBitBuf, bs_pointer_bits);
+
+ for (env = 0; env < bs_num_env; env++)
+ { /* 1 bit */
+ f[env] = buf_getbits(hBitBuf, SBR_RES_BITS);
+ }
+
+ absBordLead = bs_var_bord_0;
+ absBordTrail = 16 + bs_var_bord_1;
+ nRelLead = bs_num_rel_0;
+ nRelTrail = bs_num_rel_1;
+
+ break;
+
+ };
+
+
+ /*
+ * Calculate the framing.
+ */
+
+
+ switch (frameClass)
+ {
+ case FIXFIX:
+ for (k = 0; k < nRelLead; k++)
+ {
+ relBordLead[k] = T_16_ov_bs_num_env_tbl[bs_num_env];
+ }
+ break;
+ case VARFIX:
+ for (k = 0; k < nRelLead; k++)
+ {
+ relBordLead[k] = bs_rel_bord[k];
+ }
+ break;
+ case VARVAR:
+ for (k = 0; k < nRelLead; k++)
+ {
+ relBordLead[k] = bs_rel_bord_0[k];
+ }
+ for (k = 0; k < nRelTrail; k++)
+ {
+ relBordTrail[k] = bs_rel_bord_1[k];
+ }
+ break;
+ case FIXVAR:
+ for (k = 0; k < nRelTrail; k++)
+ {
+ relBordTrail[k] = bs_rel_bord[k];
+ }
+ break;
+ }
+
+
+ tE[0] = absBordLead;
+ tE[bs_num_env] = absBordTrail;
+
+ for (env = 1; env <= nRelLead; env++)
+ {
+ tE[env] = absBordLead;
+ for (k = 0; k <= env - 1; k++)
+ {
+ tE[env] += relBordLead[k];
+ }
+ }
+
+ for (env = nRelLead + 1; env < bs_num_env; env++)
+ {
+ tE[env] = absBordTrail;
+ for (k = 0; k <= bs_num_env - env - 1; k++)
+ {
+ tE[env] -= relBordTrail[k];
+ }
+ }
+
+
+
+ switch (frameClass)
+ {
+ case FIXFIX:
+ middleBorder = bs_num_env >> 1;
+ break;
+ case VARFIX:
+ switch (bs_pointer)
+ {
+ case 0:
+ middleBorder = 1;
+ break;
+ case 1:
+ middleBorder = bs_num_env - 1;
+ break;
+ default:
+ middleBorder = bs_pointer - 1;
+ break;
+ };
+ break;
+ case FIXVAR:
+ case VARVAR:
+ switch (bs_pointer)
+ {
+ case 0:
+ case 1:
+ middleBorder = bs_num_env - 1;
+ break;
+ default:
+ middleBorder = bs_num_env + 1 - bs_pointer;
+ break;
+ };
+ break;
+ };
+
+
+ tQ[0] = tE[0];
+ if (bs_num_env > 1)
+ {
+ tQ[1] = tE[middleBorder];
+ tQ[2] = tE[bs_num_env];
+ bs_num_noise = 2;
+ }
+ else
+ {
+ tQ[1] = tE[bs_num_env];
+ bs_num_noise = 1;
+ }
+
+ /*
+ * Check consistency on freq bands
+ */
+
+ if ((tE[bs_num_env] < tE[0]) || (tE[0] < 0))
+ {
+ err = SBRDEC_INVALID_BITSTREAM;
+ }
+
+
+ switch (frameClass)
+ {
+ case FIXFIX:
+ lA = -1;
+ break;
+ case VARFIX:
+ switch (bs_pointer)
+ {
+ case 0:
+ case 1:
+ lA = -1;
+ break;
+ default:
+ lA = bs_pointer - 1;
+ break;
+ };
+ break;
+ case FIXVAR:
+ case VARVAR:
+ switch (bs_pointer)
+ {
+ case 0:
+ lA = - 1;
+ break;
+ default:
+ lA = bs_num_env + 1 - bs_pointer;
+ break;
+ };
+ break;
+ };
+
+ /*
+ * Build the frameInfo vector...
+ */
+
+ v_frame_info[0] = bs_num_env; /* Number of envelopes*/
+ pv_memcpy(v_frame_info + 1, tE, (bs_num_env + 1)*sizeof(Int32)); /* time borders*/
+ /* frequency resolution */
+ pv_memcpy(v_frame_info + 1 + bs_num_env + 1, f, bs_num_env*sizeof(Int32));
+
+ temp = (1 + bs_num_env) << 1;
+ v_frame_info[temp] = lA; /* transient envelope*/
+ v_frame_info[temp + 1] = bs_num_noise; /* Number of noise envelopes */
+ /* noise borders */
+ pv_memcpy(v_frame_info + temp + 2, tQ, (bs_num_noise + 1)*sizeof(Int32));
+
+
+ return (err);
+
+}
+
+
+
+
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/extractframeinfo.h b/media/libstagefright/codecs/aacdec/extractframeinfo.h
new file mode 100644
index 0000000..2fcfe37
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/extractframeinfo.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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Filename: extractFrameInfo.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef EXTRACTFRAMEINFO_H
+#define EXTRACTFRAMEINFO_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bit_buffer.h"
+#include "s_sbr_frame_data.h"
+#include "e_sbr_error.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef Int32 FRAME_INFO[LENGTH_FRAME_INFO];
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ SBR_ERROR extractFrameInfo(BIT_BUFFER * hBitBuf,
+ SBR_FRAME_DATA * h_frame_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/fft_rx4.h b/media/libstagefright/codecs/aacdec/fft_rx4.h
new file mode 100644
index 0000000..8e7acb3
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fft_rx4.h
@@ -0,0 +1,110 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/fft_rx4.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ (1) modified definition of w_64rx4 from Int to Int16
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for functions fft_rx4()
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef FFT_RX4_H
+#define FFT_RX4_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define FFT_RX4_LONG 256
+#define ONE_FOURTH_FFT_RX4_LONG ((FFT_RX4_LONG)>>2)
+#define FFT_RX4_SHORT 64
+#define ONE_FOURTH_FFT_RX4_SHORT ((FFT_RX4_SHORT)>>2)
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+extern const Int16 w_64rx4[];
+extern const Int32 W_64rx4[];
+extern const Int32 W_256rx4[];
+extern const Int32 w_512rx2[];
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void fft_rx4_long(
+ Int32 Data[],
+ Int32 *peak_value);
+
+ Int fft_rx4_short(
+ Int32 Data[],
+ Int32 *peak_value);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* FFT_RX4_H */
diff --git a/media/libstagefright/codecs/aacdec/fft_rx4_long.cpp b/media/libstagefright/codecs/aacdec/fft_rx4_long.cpp
new file mode 100644
index 0000000..c517e7e
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fft_rx4_long.cpp
@@ -0,0 +1,428 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/fft_rx4_long.c
+ Funtions: fft_rx4_long
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ (1) Eliminated search for max in the main loop.
+ (2) Reduced precision on w_256rx4 from Q15 to Q10
+
+ Description:
+ (1) Created function fft_rx4_long_no_max to overcome LTP problem.
+
+ Description:
+ (1) Modified shift so the accumulation growths faster than the
+ downshift, so now the input can be as high as 1.0 and saturation
+ will not occurre. The accumulation times the Q10 format will
+ never exceed 31 bits. This increases precision
+ (2) Eliminated unneeded data moves, used before for max search.
+ (3) Eliminated function fft_rx4_long_no_max.
+
+ Description:
+ (1) Added comment to explain max search elimination and
+ Q format during multiplications
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ Data = Input complex vector, arranged in the following order:
+ real, imag, real, imag...
+ This is a complex vector whose elements (real and Imag) are
+ Int32.
+ type Int32 *
+
+ peak_value = Input, peak value of the input vector
+ Output, peak value of the resulting vector
+ type Int32 *
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ calculation are done in-place and returned in Data
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Fast Fourier Transform, radix 4 with Decimation in Frequency and block
+ floating point arithmetic.
+ The radix-4 FFT simply divides the FFT into four smaller FFTs. Each of
+ the smaller FFTs is then further divided into smaller ones and so on.
+ It consists of log 4 N stages and each stage consists of N/4 dragonflies.
+
+ An FFT is nothing but a bundle of multiplications and summations which
+ may overflow during calculations.
+
+
+ This routine uses a scheme to test and scale the result output from
+ each FFT stage in order to fix the accumulation overflow.
+
+ The Input Data should be in Q13 format to get the highest precision.
+ At the end of each dragonfly calculation, a test for possible bit growth
+ is made, if bit growth is possible the Data is scale down back to Q13.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function should provide a fixed point FFT for an input array
+ of size 256.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] Advance Digital Signal Processing, J. Proakis, C. Rader, F. Ling,
+ C. Nikias, Macmillan Pub. Co.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+ MODIFY( x[] )
+ RETURN( exponent )
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+#include "fft_rx4.h"
+
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void fft_rx4_long(
+ Int32 Data[],
+ Int32 *peak_value)
+
+{
+ Int n1;
+ Int n2;
+ Int j;
+ Int k;
+ Int i;
+
+ Int32 t1;
+ Int32 t2;
+ Int32 r1;
+ Int32 r2;
+ Int32 r3;
+ Int32 r4;
+ Int32 s1;
+ Int32 s2;
+ Int32 s3;
+ Int32 *pData1;
+ Int32 *pData2;
+ Int32 *pData3;
+ Int32 *pData4;
+ Int32 temp1;
+ Int32 temp2;
+ Int32 temp3;
+ Int32 temp4;
+ Int32 max;
+
+ Int32 exp_jw1;
+ Int32 exp_jw2;
+ Int32 exp_jw3;
+
+
+
+ const Int32 *pw = W_256rx4;
+
+ n2 = FFT_RX4_LONG;
+
+ for (k = FFT_RX4_LONG; k > 4; k >>= 2)
+ {
+
+ n1 = n2;
+ n2 >>= 2;
+
+ for (i = 0; i < FFT_RX4_LONG; i += n1)
+ {
+ pData1 = &Data[ i<<1];
+ pData2 = pData1 + n1;
+
+ temp1 = *pData1;
+ temp2 = *pData2;
+
+ r1 = temp1 + temp2;
+ r2 = temp1 - temp2;
+
+ pData3 = pData1 + (n1 >> 1);
+ pData4 = pData3 + n1;
+ temp3 = *pData3++;
+ temp4 = *pData4++;
+
+ t1 = temp3 + temp4;
+
+ *(pData1++) = (r1 + t1);
+ t2 = temp3 - temp4;
+ *(pData2++) = (r1 - t1);
+
+ temp1 = *pData1;
+ temp2 = *pData2;
+
+ s1 = temp1 + temp2;
+ temp3 = *pData3;
+ s2 = temp1 - temp2;
+ temp4 = *pData4;
+ *pData3-- = (s2 - t2);
+ *pData4-- = (s2 + t2);
+
+ t1 = temp3 + temp4;
+
+ *pData1 = (s1 + t1);
+ *pData2 = (s1 - t1);
+
+ r1 = temp3 - temp4;
+
+ *pData4 = (r2 - r1);
+ *pData3 = (r2 + r1);
+
+ } /* i */
+
+
+
+ for (j = 1; j < n2; j++)
+ {
+
+ exp_jw1 = (*pw++);
+ exp_jw2 = (*pw++);
+ exp_jw3 = (*pw++);
+
+
+ for (i = j; i < FFT_RX4_LONG; i += n1)
+ {
+ pData1 = &Data[ i<<1];
+ pData2 = pData1 + n1;
+
+ temp1 = *pData1;
+ temp2 = *pData2++;
+
+ r1 = temp1 + temp2;
+ r2 = temp1 - temp2;
+
+ pData3 = pData1 + (n1 >> 1);
+ pData4 = pData3 + n1;
+ temp3 = *pData3++;
+ temp4 = *pData4++;
+
+ r3 = temp3 + temp4;
+ r4 = temp3 - temp4;
+
+ *(pData1++) = (r1 + r3);
+ r1 = (r1 - r3) << 1;
+
+ temp2 = *pData2;
+ temp1 = *pData1;
+
+ s1 = temp1 + temp2;
+ s2 = temp1 - temp2;
+ s3 = (s2 + r4) << 1;
+ s2 = (s2 - r4) << 1;
+
+ temp3 = *pData3;
+ temp4 = *pData4;
+
+ t1 = temp3 + temp4;
+ t2 = temp3 - temp4;
+
+ *pData1 = (s1 + t1);
+ s1 = (s1 - t1) << 1;
+
+ *pData2-- = cmplx_mul32_by_16(s1, -r1, exp_jw2);
+ r3 = (r2 - t2) << 1;
+ *pData2 = cmplx_mul32_by_16(r1, s1, exp_jw2);
+
+ r2 = (r2 + t2) << 1;
+
+ *pData3-- = cmplx_mul32_by_16(s2, -r2, exp_jw1);
+ *pData3 = cmplx_mul32_by_16(r2, s2, exp_jw1);
+
+ *pData4-- = cmplx_mul32_by_16(s3, -r3, exp_jw3);
+ *pData4 = cmplx_mul32_by_16(r3, s3, exp_jw3);
+
+ } /* i */
+
+ } /* j */
+
+ } /* k */
+
+
+ max = 0;
+
+ pData1 = Data - 7;
+
+
+ for (i = ONE_FOURTH_FFT_RX4_LONG; i != 0 ; i--)
+ {
+ pData1 += 7;
+ pData2 = pData1 + 4;
+
+
+ temp1 = *pData1;
+ temp2 = *pData2++;
+
+ r1 = temp1 + temp2;
+ r2 = temp1 - temp2;
+
+ pData3 = pData1 + 2;
+ pData4 = pData1 + 6;
+ temp1 = *pData3++;
+ temp2 = *pData4++;
+
+ t1 = temp1 + temp2;
+ t2 = temp1 - temp2;
+
+ temp1 = (r1 + t1);
+ r1 = (r1 - t1);
+ *(pData1++) = temp1;
+ max |= (temp1 >> 31) ^ temp1;
+
+
+
+ temp2 = *pData2;
+ temp1 = *pData1;
+
+ s1 = temp1 + temp2;
+ s2 = temp1 - temp2;
+
+
+ temp1 = *pData3;
+ temp2 = *pData4;
+
+ s3 = (s2 + t2);
+ s2 = (s2 - t2);
+
+ t1 = temp1 + temp2;
+ t2 = temp1 - temp2;
+
+ temp1 = (s1 + t1);
+ *pData1 = temp1;
+ temp2 = (s1 - t1);
+
+ max |= (temp1 >> 31) ^ temp1;
+ *pData2-- = temp2;
+ max |= (temp2 >> 31) ^ temp2;
+
+ *pData2 = r1;
+ max |= (r1 >> 31) ^ r1;
+ *pData3-- = s2;
+ max |= (s2 >> 31) ^ s2;
+ *pData4-- = s3;
+ max |= (s3 >> 31) ^ s3;
+
+ temp1 = (r2 - t2);
+ *pData4 = temp1;
+ temp2 = (r2 + t2);
+ *pData3 = temp2;
+ max |= (temp1 >> 31) ^ temp1;
+ max |= (temp2 >> 31) ^ temp2;
+
+ } /* i */
+
+ *peak_value = max;
+
+ return ;
+
+}
+
diff --git a/media/libstagefright/codecs/aacdec/fft_rx4_short.cpp b/media/libstagefright/codecs/aacdec/fft_rx4_short.cpp
new file mode 100644
index 0000000..4a8a0d6
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fft_rx4_short.cpp
@@ -0,0 +1,468 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/fft_rx4_short.c
+ Funtions: fft_rx4_short
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ (1) Eliminated search for max in the main loop.
+ (2) Simplified the function by eliminating different conditions
+ for exp.
+ (3) Reduced precision on w_64rx4 from Q15 to Q12, so now the
+ input can be as high as 1.0 and saturation will not occurre
+ because the accumulation times the new Q12 format will never
+ exceed 31 bits.
+
+ Description:
+ (1) Added comment to explain max search elimination and
+ Q format during multiplications
+ (2) Increased down shift from 1 to 2, to ensure that 32-bit
+ numbers will not overflow when 2 consecutive adds are done
+ This was found during code review.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ Data = Input complex vector, arranged in the following order:
+ real, imag, real, imag...
+ This is a complex vector whose elements (real and Imag) are
+ Int32.
+ type Int32 *
+
+ peak_value = Input, peak value of the input vector
+ Output, peak value of the resulting vector
+ type Int32 *
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ exponent returns a shift to compensate the scaling introduced by
+ overflow protection
+
+ Pointers and Buffers Modified:
+ calculation are done in-place and returned in Data
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Fast Fourier Transform, radix 4 with Decimation in Frequency and block
+ floating point arithmetic.
+ The radix-4 FFT simply divides the FFT into four smaller FFTs. Each of
+ the smaller FFTs is then further divided into smaller ones and so on.
+ It consists of log 4 N stages and each stage consists of N/4 dragonflies.
+
+ An FFT is nothing but a bundle of multiplications and summations which
+ may overflow during calculations.
+
+
+ This routine uses a scheme to test and scale the result output from
+ each FFT stage in order to fix the accumulation overflow.
+
+ The Input Data should be in Q13 format to get the highest precision.
+ At the end of each dragonfly calculation, a test for possible bit growth
+ is made, if bit growth is possible the Data is scale down back to Q13.
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function should provide a fixed point FFT for an input array
+ of size 64.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] Advance Digital Signal Processing, J. Proakis, C. Rader, F. Ling,
+ C. Nikias, Macmillan Pub. Co.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+ MODIFY( x[] )
+ RETURN( exponent )
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+#include "fft_rx4.h"
+#include "pv_normalize.h"
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int fft_rx4_short(
+ Int32 Data[],
+ Int32 *peak_value)
+
+{
+ Int n1;
+ Int n2;
+ Int n3;
+ Int j;
+ Int k;
+ Int i;
+ Int32 exp_jw1;
+ Int32 exp_jw2;
+ Int32 exp_jw3;
+
+
+ Int32 t1;
+ Int32 t2;
+ Int32 r1;
+ Int32 r2;
+ Int32 r3;
+ Int32 s1;
+ Int32 s2;
+ Int32 s3;
+
+ Int32 *pData1;
+ Int32 *pData2;
+ Int32 *pData3;
+ Int32 *pData4;
+ const Int32 *pw;
+ Int32 temp1;
+ Int32 temp2;
+ Int32 temp3;
+ Int32 temp4;
+ Int32 max;
+ Int exp;
+ Int exponent = 0;
+ Int shift;
+
+
+ max = *peak_value;
+ exp = 0;
+
+ if (max > 0x008000)
+ {
+ exp = 8 - pv_normalize(max); /* use 24 bits */
+
+ exponent = exp; /* keeps track of # of shifts */
+
+ }
+
+ n2 = FFT_RX4_SHORT;
+
+ pw = W_64rx4;
+
+
+ /* shift down to avoid possible overflow in first pass of the loop */
+ shift = 2;
+
+ for (k = FFT_RX4_SHORT; k > 4; k >>= 2)
+ {
+
+ n1 = n2;
+ n2 >>= 2;
+ n3 = n1 >> 1;
+
+ exp -= 2;
+
+ for (i = 0; i < FFT_RX4_SHORT; i += n1)
+ {
+ pData1 = &Data[ i<<1];
+ pData3 = pData1 + n3;
+ pData2 = pData1 + n1;
+ pData4 = pData3 + n1;
+
+ temp1 = *(pData1);
+ temp2 = *(pData2);
+ temp1 >>= shift;
+ temp2 >>= shift;
+
+ r1 = temp1 + temp2;
+ r2 = temp1 - temp2;
+
+ temp3 = *(pData3++);
+ temp4 = *(pData4++);
+ temp3 >>= shift;
+ temp4 >>= shift;
+
+ t1 = temp3 + temp4;
+ t2 = temp3 - temp4;
+
+ *(pData1++) = (r1 + t1) >> exp;
+ *(pData2++) = (r1 - t1) >> exp;
+
+ temp1 = *pData1;
+ temp2 = *pData2;
+ temp1 >>= shift;
+ temp2 >>= shift;
+
+ s1 = temp1 + temp2;
+ s2 = temp1 - temp2;
+
+ temp3 = *pData3;
+ temp4 = *pData4;
+ temp3 >>= shift;
+ temp4 >>= shift;
+
+ t1 = temp3 + temp4;
+ r1 = temp3 - temp4;
+
+ *pData1 = (s1 + t1) >> exp;
+ *pData2 = (s1 - t1) >> exp;
+
+ *pData4-- = (s2 + t2) >> exp;
+ *pData4 = (r2 - r1) >> exp;
+
+ *pData3-- = (s2 - t2) >> exp;
+ *pData3 = (r2 + r1) >> exp;
+
+
+ } /* i */
+
+ for (j = 1; j < n2; j++)
+ {
+ exp_jw1 = *pw++;
+ exp_jw2 = *pw++;
+ exp_jw3 = *pw++;
+
+
+ for (i = j; i < FFT_RX4_SHORT; i += n1)
+ {
+ pData1 = &Data[ i<<1];
+ pData3 = pData1 + n3;
+ pData2 = pData1 + n1;
+ pData4 = pData3 + n1;
+
+ temp1 = *(pData1);
+ temp2 = *(pData2++);
+ temp1 >>= shift;
+ temp2 >>= shift;
+
+ r1 = temp1 + temp2;
+ r2 = temp1 - temp2;
+ temp3 = *(pData3++);
+ temp4 = *(pData4++);
+ temp3 >>= shift;
+ temp4 >>= shift;
+
+ t1 = temp3 + temp4;
+ t2 = temp3 - temp4;
+
+ *(pData1++) = (r1 + t1) >> exp;
+ r1 = (r1 - t1) >> exp;
+
+ temp1 = *pData1;
+ temp2 = *pData2;
+ temp1 >>= shift;
+ temp2 >>= shift;
+
+ s1 = temp1 + temp2;
+ s2 = temp1 - temp2;
+
+ s3 = (s2 + t2) >> exp;
+ s2 = (s2 - t2) >> exp;
+
+ temp3 = *pData3;
+ temp4 = *pData4 ;
+ temp3 >>= shift;
+ temp4 >>= shift;
+
+ t1 = temp3 + temp4;
+ t2 = temp3 - temp4;
+
+ *pData1 = (s1 + t1) >> exp;
+ s1 = (s1 - t1) >> exp;
+
+
+ *pData2-- = cmplx_mul32_by_16(s1, -r1, exp_jw2) << 1;
+ *pData2 = cmplx_mul32_by_16(r1, s1, exp_jw2) << 1;
+
+ r3 = ((r2 - t2) >> exp);
+ r2 = ((r2 + t2) >> exp);
+
+ *pData3-- = cmplx_mul32_by_16(s2, -r2, exp_jw1) << 1;
+ *pData3 = cmplx_mul32_by_16(r2, s2, exp_jw1) << 1;
+
+ *pData4-- = cmplx_mul32_by_16(s3, -r3, exp_jw3) << 1;
+ *pData4 = cmplx_mul32_by_16(r3, s3, exp_jw3) << 1;
+
+ } /* i */
+
+ } /* j */
+
+ /*
+ * this will reset exp and shift to zero for the second pass of the
+ * loop
+ */
+ exp = 2;
+ shift = 0;
+
+ } /* k */
+
+
+ max = 0;
+
+ pData1 = Data - 7;
+
+ for (i = ONE_FOURTH_FFT_RX4_SHORT; i != 0 ; i--)
+ {
+ pData1 += 7;
+
+ pData3 = pData1 + 2;
+ pData2 = pData1 + 4;
+ pData4 = pData1 + 6;
+
+ temp1 = *pData1;
+ temp2 = *pData2++;
+
+ r1 = temp1 + temp2;
+ r2 = temp1 - temp2;
+
+ temp1 = *pData3++;
+ temp2 = *pData4++;
+
+ t1 = temp1 + temp2;
+ t2 = temp1 - temp2;
+
+ temp1 = (r1 + t1);
+ r1 = (r1 - t1);
+ *(pData1++) = temp1;
+ max |= (temp1 >> 31) ^ temp1;
+
+
+
+ temp1 = *pData1;
+ temp2 = *pData2;
+
+ s1 = temp1 + temp2;
+ s2 = temp1 - temp2;
+
+ s3 = (s2 + t2);
+ s2 = (s2 - t2);
+
+ temp1 = *pData3;
+ temp2 = *pData4;
+
+ t1 = temp1 + temp2;
+ t2 = temp1 - temp2;
+
+ temp1 = (s1 + t1);
+ temp2 = (s1 - t1);
+ *pData1 = temp1;
+ *pData2-- = temp2;
+ max |= (temp1 >> 31) ^ temp1;
+ max |= (temp2 >> 31) ^ temp2;
+
+ *pData2 = r1;
+ *pData3-- = s2;
+ *pData4-- = s3;
+ max |= (r1 >> 31) ^ r1;
+ max |= (s2 >> 31) ^ s2;
+ max |= (s3 >> 31) ^ s3;
+
+ temp1 = (r2 - t2);
+ temp2 = (r2 + t2);
+ *pData4 = temp1;
+ *pData3 = temp2;
+ max |= (temp1 >> 31) ^ temp1;
+ max |= (temp2 >> 31) ^ temp2;
+
+ } /* i */
+
+ *peak_value = max;
+
+
+ return (exponent);
+
+}
diff --git a/media/libstagefright/codecs/aacdec/fft_rx4_tables_fxp.cpp b/media/libstagefright/codecs/aacdec/fft_rx4_tables_fxp.cpp
new file mode 100644
index 0000000..2476b87
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fft_rx4_tables_fxp.cpp
@@ -0,0 +1,269 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/fft_rx4_tables_fxp.c
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Reduce the accuracy of w_256rx4 and w_512rx2 to Q10 format.
+ Try to to pack sin and cos into one 32-bit number to reduce the
+ memory access, but doesn't help in speed, so commented out for now.
+
+ Description:
+ (1) Reduced precision of w_64rx4 from Q15 to Q12.
+ (2) Increased precision of w_512rx2 from Q10 to Q13, Both changes
+ increase overall decoder precision
+
+ Description:
+ (1) per code review comment, added description for table generation
+ (2) modified definition of w_64rx4 from Int to Int16
+
+
+ Who: Date:
+ Description:
+
+ ----------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Table generation
+
+ n = 256 or 64;
+ M = precision; 2^10, 2^12, 2^13
+
+ for j=1; j<log4(n); j *= 4
+
+ for i=0; i<n/4; i +=j
+
+ phi_1 = 2*pi*i/n;
+ phi_2 = 4*pi*i/n;
+ phi_3 = 6*pi*i/n;
+ M*[cos(phi_1) sin(phi_1) cos(phi_2) sin(phi_2) cos(phi_3) sin(phi_4)];
+
+ end
+
+ end
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "fft_rx4.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ Forward FFT radix-4 tables
+------------------------------------------------------------------------------
+*/
+
+
+const Int32 W_64rx4[60] = /* 2 Q15 */
+{
+
+ 0x7F610C8C, 0x7D8918F9, 0x7A7C2528,
+ 0x7D8918F9, 0x764130FB, 0x6A6D471C,
+ 0x7A7C2528, 0x6A6D471C, 0x513362F1,
+ 0x764130FB, 0x5A825A82, 0x30FB7641,
+ 0x70E23C56, 0x471C6A6D, 0x0C8C7F61,
+ 0x6A6D471C, 0x30FB7641, 0xE7057D89,
+ 0x62F15133, 0x18F97D89, 0xC3A870E2,
+ 0x5A825A82, 0x00007FFF, 0xA57C5A82,
+ 0x513362F1, 0xE7057D89, 0x8F1C3C56,
+ 0x471C6A6D, 0xCF037641, 0x827518F9,
+ 0x3C5670E2, 0xB8E26A6D, 0x809DF372,
+ 0x30FB7641, 0xA57C5A82, 0x89BDCF03,
+ 0x25287A7C, 0x9591471C, 0x9D0DAECB,
+ 0x18F97D89, 0x89BD30FB, 0xB8E29591,
+ 0x0C8C7F61, 0x827518F9, 0xDAD68582,
+ 0x764130FB, 0x5A825A82, 0x30FB7641,
+ 0x5A825A82, 0x00007FFF, 0xA57C5A82,
+ 0x30FB7641, 0xA57C5A82, 0x89BDCF03,
+};
+
+
+
+const Int32 W_256rx4[495] = /* 2 Q15 */
+{
+
+ 0x7FF50324, 0x7FD80648, 0x7FA6096A,
+ 0x7FD80648, 0x7F610C8C, 0x7E9C12C8,
+ 0x7FA6096A, 0x7E9C12C8, 0x7CE31C0B,
+ 0x7F610C8C, 0x7D8918F9, 0x7A7C2528,
+ 0x7F090FAB, 0x7C291F1A, 0x776B2E11,
+ 0x7E9C12C8, 0x7A7C2528, 0x73B536BA,
+ 0x7E1D15E2, 0x78842B1F, 0x6F5E3F17,
+ 0x7D8918F9, 0x764130FB, 0x6A6D471C,
+ 0x7CE31C0B, 0x73B536BA, 0x64E84EBF,
+ 0x7C291F1A, 0x70E23C56, 0x5ED755F5,
+ 0x7B5C2223, 0x6DC941CE, 0x58425CB3,
+ 0x7A7C2528, 0x6A6D471C, 0x513362F1,
+ 0x79892826, 0x66CF4C3F, 0x49B468A6,
+ 0x78842B1F, 0x62F15133, 0x41CE6DC9,
+ 0x776B2E11, 0x5ED755F5, 0x398C7254,
+ 0x764130FB, 0x5A825A82, 0x30FB7641,
+ 0x750433DF, 0x55F55ED7, 0x28267989,
+ 0x73B536BA, 0x513362F1, 0x1F1A7C29,
+ 0x7254398C, 0x4C3F66CF, 0x15E27E1D,
+ 0x70E23C56, 0x471C6A6D, 0x0C8C7F61,
+ 0x6F5E3F17, 0x41CE6DC9, 0x03247FF5,
+ 0x6DC941CE, 0x3C5670E2, 0xF9B67FD8,
+ 0x6C23447A, 0x36BA73B5, 0xF0537F09,
+ 0x6A6D471C, 0x30FB7641, 0xE7057D89,
+ 0x68A649B4, 0x2B1F7884, 0xDDDB7B5C,
+ 0x66CF4C3F, 0x25287A7C, 0xD4DF7884,
+ 0x64E84EBF, 0x1F1A7C29, 0xCC1F7504,
+ 0x62F15133, 0x18F97D89, 0xC3A870E2,
+ 0x60EB539B, 0x12C87E9C, 0xBB846C23,
+ 0x5ED755F5, 0x0C8C7F61, 0xB3BF66CF,
+ 0x5CB35842, 0x06487FD8, 0xAC6360EB,
+ 0x5A825A82, 0x00007FFF, 0xA57C5A82,
+ 0x58425CB3, 0xF9B67FD8, 0x9F13539B,
+ 0x55F55ED7, 0xF3727F61, 0x992F4C3F,
+ 0x539B60EB, 0xED367E9C, 0x93DB447A,
+ 0x513362F1, 0xE7057D89, 0x8F1C3C56,
+ 0x4EBF64E8, 0xE0E47C29, 0x8AFA33DF,
+ 0x4C3F66CF, 0xDAD67A7C, 0x877A2B1F,
+ 0x49B468A6, 0xD4DF7884, 0x84A22223,
+ 0x471C6A6D, 0xCF037641, 0x827518F9,
+ 0x447A6C23, 0xC94473B5, 0x80F50FAB,
+ 0x41CE6DC9, 0xC3A870E2, 0x80260648,
+ 0x3F176F5E, 0xBE306DC9, 0x8009FCDA,
+ 0x3C5670E2, 0xB8E26A6D, 0x809DF372,
+ 0x398C7254, 0xB3BF66CF, 0x81E1EA1C,
+ 0x36BA73B5, 0xAECB62F1, 0x83D5E0E4,
+ 0x33DF7504, 0xAA095ED7, 0x8675D7D8,
+ 0x30FB7641, 0xA57C5A82, 0x89BDCF03,
+ 0x2E11776B, 0xA12755F5, 0x8DAAC672,
+ 0x2B1F7884, 0x9D0D5133, 0x9235BE30,
+ 0x28267989, 0x992F4C3F, 0x9758B64A,
+ 0x25287A7C, 0x9591471C, 0x9D0DAECB,
+ 0x22237B5C, 0x923541CE, 0xA34BA7BC,
+ 0x1F1A7C29, 0x8F1C3C56, 0xAA09A127,
+ 0x1C0B7CE3, 0x8C4936BA, 0xB13F9B16,
+ 0x18F97D89, 0x89BD30FB, 0xB8E29591,
+ 0x15E27E1D, 0x877A2B1F, 0xC0E790A0,
+ 0x12C87E9C, 0x85822528, 0xC9448C49,
+ 0x0FAB7F09, 0x83D51F1A, 0xD1ED8893,
+ 0x0C8C7F61, 0x827518F9, 0xDAD68582,
+ 0x096A7FA6, 0x816212C8, 0xE3F3831B,
+ 0x06487FD8, 0x809D0C8C, 0xED368162,
+ 0x03247FF5, 0x80260648, 0xF6948058,
+ 0x7F610C8C, 0x7D8918F9, 0x7A7C2528,
+ 0x7D8918F9, 0x764130FB, 0x6A6D471C,
+ 0x7A7C2528, 0x6A6D471C, 0x513362F1,
+ 0x764130FB, 0x5A825A82, 0x30FB7641,
+ 0x70E23C56, 0x471C6A6D, 0x0C8C7F61,
+ 0x6A6D471C, 0x30FB7641, 0xE7057D89,
+ 0x62F15133, 0x18F97D89, 0xC3A870E2,
+ 0x5A825A82, 0x00007FFF, 0xA57C5A82,
+ 0x513362F1, 0xE7057D89, 0x8F1C3C56,
+ 0x471C6A6D, 0xCF037641, 0x827518F9,
+ 0x3C5670E2, 0xB8E26A6D, 0x809DF372,
+ 0x30FB7641, 0xA57C5A82, 0x89BDCF03,
+ 0x25287A7C, 0x9591471C, 0x9D0DAECB,
+ 0x18F97D89, 0x89BD30FB, 0xB8E29591,
+ 0x0C8C7F61, 0x827518F9, 0xDAD68582,
+ 0x764130FB, 0x5A825A82, 0x30FB7641,
+ 0x5A825A82, 0x00007FFF, 0xA57C5A82,
+ 0x30FB7641, 0xA57C5A82, 0x89BDCF03
+};
+
+
+
+/*
+------------------------------------------------------------------------------
+ Forward FFT radix-2 table
+------------------------------------------------------------------------------
+*/
+
+
+const Int32 w_512rx2[127] =
+{
+ /* Q15 */
+ 0x7FFE0192, 0x7FF60324, 0x7FEA04B6,
+ 0x7FD90648, 0x7FC207D9, 0x7FA7096B, 0x7F870AFB,
+ 0x7F620C8C, 0x7F380E1C, 0x7F0A0FAB, 0x7ED6113A,
+ 0x7E9D12C8, 0x7E601455, 0x7E1E15E2, 0x7DD6176E,
+ 0x7D8A18F9, 0x7D3A1A83, 0x7CE41C0C, 0x7C891D93,
+ 0x7C2A1F1A, 0x7BC6209F, 0x7B5D2224, 0x7AEF23A7,
+ 0x7A7D2528, 0x7A0626A8, 0x798A2827, 0x790A29A4,
+ 0x78852B1F, 0x77FB2C99, 0x776C2E11, 0x76D92F87,
+ 0x764230FC, 0x75A6326E, 0x750533DF, 0x7460354E,
+ 0x73B636BA, 0x73083825, 0x7255398D, 0x719E3AF3,
+ 0x70E33C57, 0x70233DB8, 0x6F5F3F17, 0x6E974074,
+ 0x6DCA41CE, 0x6CF94326, 0x6C24447B, 0x6B4B45CD,
+ 0x6A6E471D, 0x698C486A, 0x68A749B4, 0x67BD4AFB,
+ 0x66D04C40, 0x65DE4D81, 0x64E94EC0, 0x63EF4FFB,
+ 0x62F25134, 0x61F15269, 0x60EC539B, 0x5FE454CA,
+ 0x5ED755F6, 0x5DC8571E, 0x5CB45843, 0x5B9D5964,
+ 0x5A825A82, 0x59645B9D, 0x58435CB4, 0x571E5DC8,
+ 0x55F65ED7, 0x54CA5FE4, 0x539B60EC, 0x526961F1,
+ 0x513462F2, 0x4FFB63EF, 0x4EC064E9, 0x4D8165DE,
+ 0x4C4066D0, 0x4AFB67BD, 0x49B468A7, 0x486A698C,
+ 0x471D6A6E, 0x45CD6B4B, 0x447B6C24, 0x43266CF9,
+ 0x41CE6DCA, 0x40746E97, 0x3F176F5F, 0x3DB87023,
+ 0x3C5770E3, 0x3AF3719E, 0x398D7255, 0x38257308,
+ 0x36BA73B6, 0x354E7460, 0x33DF7505, 0x326E75A6,
+ 0x30FC7642, 0x2F8776D9, 0x2E11776C, 0x2C9977FB,
+ 0x2B1F7885, 0x29A4790A, 0x2827798A, 0x26A87A06,
+ 0x25287A7D, 0x23A77AEF, 0x22247B5D, 0x209F7BC6,
+ 0x1F1A7C2A, 0x1D937C89, 0x1C0C7CE4, 0x1A837D3A,
+ 0x18F97D8A, 0x176E7DD6, 0x15E27E1E, 0x14557E60,
+ 0x12C87E9D, 0x113A7ED6, 0x0FAB7F0A, 0x0E1C7F38,
+ 0x0C8C7F62, 0x0AFB7F87, 0x096B7FA7, 0x07D97FC2,
+ 0x06487FD9, 0x04B67FEA, 0x03247FF6, 0x01927FFE
+};
+
diff --git a/media/libstagefright/codecs/aacdec/find_adts_syncword.cpp b/media/libstagefright/codecs/aacdec/find_adts_syncword.cpp
new file mode 100644
index 0000000..535f177
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/find_adts_syncword.cpp
@@ -0,0 +1,305 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/find_adts_syncword.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Fixed error in logic that determines whether there are enough
+ bits available to conduct a search for the syncword. The plus sign in
+ the following condition should be a minus.
+
+ if (pInputStream->usedBits <
+ (pInputStream->availableBits + syncword_length)
+
+ The length of the syncword should subtract from the number of available
+ bits, not add.
+
+ Description: Fixed condition when the end of file was found, unsigned
+ comparison produced a undesired search. Fixed by casting comparison
+ if ((Int)pInputStream->usedBits <
+ ((Int)pInputStream->availableBits - syncword_length) )
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pSyncword = Pointer to variable containing the syncword that the
+ function should be scanning for in the buffer. [ UInt32 * ]
+
+ pInputStream = Pointer to a BITS structure, used by the function getbits
+ to retrieve data from the bitstream. [ BITS * ]
+
+ syncword_length = The length of the syncword. [ Int ]
+
+ syncword_mask = A mask to be applied to the bitstream before comparison
+ with the value pointed to by pSyncword. [ UInt32 ]
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This module scans the bitstream for a syncword of any length between 1 and 32.
+ If certain bits in the syncword are to be ignored, that bit position should
+ be set to 0 in both parameters *(pSyncword) and syncword_mask. This allows
+ for a syncword to be constructed out of non-contiguous bits.
+
+ Upon finding the syncword's position in the bitstream, a value denoting the
+ syncword's degree of deviance from being byte-aligned (byte_align_offset)
+ is set in the structure pointed to by pInputStream.
+ This is a value between 0 and 7.
+
+ If no syncword is found, the function returns status == ERROR.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ "Don't care" bits must be set to '0' in both *(pSyncword) and syncword_mask.
+
+ This function should not be called if there are less than
+ (8 + syncword_length) bits in the buffer.
+
+------------------------------------------------------------------------------
+ REFERENCES
+ (1) ISO/IEC 13818-7:1997(E)
+ Part 7
+ Subpart 6.2 (Audio_Data_Transport_Stream frame, ADTS)
+
+ (2) ISO/IEC 11172-3:1993(E)
+ Part 3
+ Subpart 2.4.3 The audio decoding process
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ IF (pInputStream->usedBits <
+ (pInputStream->availableBits + syncword_length) )
+
+ max_search_length = (pInputStream->availableBits - pInputStream->usedBits);
+
+ max_search_length = max_search_length - syncword_length;
+
+ search_length = 0;
+
+ adts_header =
+ CALL getbits(syncword_length, pInputStream);
+ MODIFYING pInputStream->usedBits
+ RETURNING bits from bitstream of length (syncword_length)
+
+ test_for_syncword = adts_header AND syncword_mask;
+ test_for_syncword = test_for_syncword XOR syncword;
+
+ WHILE ( (test_for_syncword != 0) && (search_length > 0) )
+
+ search_length = search_length - 1;
+
+ adts_header = adts_header << 1;
+ adts_header = adts_header OR ...
+
+ CALL getbits(syncword_length, pInputStream);
+ MODIFYING pInputStream->usedBits
+ RETURNING 1 bit from the bitstream
+
+ test_for_syncword = adts_header AND syncword_mask;
+ test_for_syncword = test_for_syncword XOR syncword;
+
+ ENDWHILE
+
+ IF (search_length == 0)
+ status = ERROR;
+ ENDIF
+
+ *(pSyncword) = adts_header;
+
+ pInputStream->byteAlignOffset =
+ (pInputStream->usedBits - syncwordlength) AND 0x7;
+
+ ELSE
+ status = ERROR;
+ ENDIF
+
+ return (status);
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bits.h"
+#include "ibstream.h"
+#include "find_adts_syncword.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define FIND_ADTS_ERROR -1
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Int find_adts_syncword(
+ UInt32 *pSyncword,
+ BITS *pInputStream,
+ Int syncword_length,
+ UInt32 syncword_mask)
+{
+
+ Int status = SUCCESS;
+ UInt search_length;
+ UInt32 adts_header = 0;
+ UInt32 test_for_syncword;
+ UInt32 syncword = *(pSyncword);
+
+ /*
+ * Determine the maximum number of bits available to this function for
+ * the syncword search.
+ */
+ if ((Int)pInputStream->usedBits <
+ ((Int)pInputStream->availableBits - syncword_length))
+ {
+ search_length = (pInputStream->availableBits - pInputStream->usedBits);
+
+ search_length -= syncword_length;
+
+ adts_header = getbits(syncword_length, pInputStream);
+
+ /*
+ * Mask the result in adts_header with the syncword_mask, so only the
+ * bits relevant to syncword detection are compared to *(pSyncword).
+ */
+ test_for_syncword = adts_header & syncword_mask;
+ test_for_syncword ^= syncword;
+
+ /*
+ * Scan bit-by-bit through the bitstream, until the function either
+ * runs out of bits, or finds the syncword.
+ */
+
+ while ((test_for_syncword != 0) && (search_length > 0))
+ {
+ search_length--;
+
+ adts_header <<= 1;
+ adts_header |= getbits(1, pInputStream);
+
+ test_for_syncword = adts_header & syncword_mask;
+ test_for_syncword ^= syncword;
+ }
+
+ if (search_length == 0)
+ {
+ status = FIND_ADTS_ERROR;
+ }
+
+ /*
+ * Return the syncword's position in the bitstream. Correct placement
+ * of the syncword will result in byte_align_offset == 0.
+ * If the syncword is found not to be byte-aligned, then return
+ * the degree of disalignment, so further decoding can
+ * be shifted as necessary.
+ *
+ */
+ pInputStream->byteAlignOffset =
+ (pInputStream->usedBits - syncword_length) & 0x7;
+
+ } /* END if (pInputStream->usedBits < ...) */
+
+ else
+ {
+ status = FIND_ADTS_ERROR;
+ }
+
+ *(pSyncword) = adts_header;
+
+ return (status);
+
+} /* find_adts_syncword() */
diff --git a/media/libstagefright/codecs/aacdec/find_adts_syncword.h b/media/libstagefright/codecs/aacdec/find_adts_syncword.h
new file mode 100644
index 0000000..d147bc5
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/find_adts_syncword.h
@@ -0,0 +1,87 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/find_adts_syncword.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This function includes the function declaration for find_adts_syncword()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef FIND_ADTS_SYNCWORD_H
+#define FIND_ADTS_SYNCWORD_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "s_bits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+Int find_adts_syncword(
+ UInt32 *pSyncword,
+ BITS *pInputStream,
+ Int syncword_length,
+ UInt32 syncword_mask);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/fwd_long_complex_rot.cpp b/media/libstagefright/codecs/aacdec/fwd_long_complex_rot.cpp
new file mode 100644
index 0000000..b85c7df
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fwd_long_complex_rot.cpp
@@ -0,0 +1,284 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/fwd_long_complex_rot.c
+ Funtions: fwd_long_complex_rot
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Date: 10/18/2002
+ Description:
+ (1) Change the input arguments, no shifts information from
+ long_fft_rx4 is passed, only a single max is passed.
+ (2) Eliminate search for max, a fixed shift has replaced the
+ search for max with minimal loss of precision.
+ (3) Eliminated unused variables
+
+ Date: 10/28/2002
+ Description:
+ (1) Added comments per code review
+ (2) Eliminated hardly used condition on if-else (exp==0)
+
+ Description:
+
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ Data_in = Input vector (sized for long windows
+ TWICE_FWD_LONG_CX_ROT_LENGTH), with time domain samples
+ type Int32 *
+
+ Data_out = Output vector with a post-rotation by exp(-j(2pi/N)(k+1/8)),
+ (sized for long windows TWICE_FWD_LONG_CX_ROT_LENGTH)
+ type Int32 *
+
+ max = Input, carries the maximum value of the input vector
+ "Data_in"
+ type Int32
+
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ exp = shift factor to reflect signal scaling
+
+ Pointers and Buffers Modified:
+ Results are return in "Data_out"
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ fwd_long_complex_rot() performs the pre complex rotation for the MDCT
+ for the case of long windows. It also performs digit reverse ordering of
+ the first and second halves of the input vector "Data_in", as well as
+ reordering of the two half vectors (following radix-2 decomposition)
+ Word normalization is also done to ensure 16 by 16 bit multiplications.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ fwd_long_complex_rot() should execute a pre-rotation by
+ exp(-j(2pi/N)(k+1/8)), digit reverse ordering and normalization
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "fwd_long_complex_rot.h"
+#include "digit_reversal_tables.h"
+#include "imdct_fxp.h"
+#include "pv_normalize.h"
+
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+Int fwd_long_complex_rot(
+ Int32 *Data_in,
+ Int32 *Data_out,
+ Int32 max)
+{
+ Int i;
+ const Int32 *p_rotate;
+ Int32 temp_re;
+ Int32 temp_im;
+ Int32 *pData_in_ref1;
+ Int32 *pData_in_ref2;
+ Int32 exp_jw;
+ Int32 temp_re_32;
+ Int32 temp_im_32;
+
+ Int32 *pData_out_1;
+ Int32 *pData_out_2;
+ Int32 *pData_out_3;
+ Int32 *pData_out_4;
+
+ Int32 *pData_in_1;
+ Int32 *pData_in_2;
+
+ Int exp;
+
+ p_rotate = exp_rotation_N_2048;
+
+ pData_in_ref1 = Data_in;
+ pData_in_ref2 = &Data_in[TWICE_FWD_LONG_CX_ROT_LENGTH];
+
+ pData_out_1 = Data_out;
+ pData_out_2 = &Data_out[LONG_WINDOW_LENGTH_m_1];
+ pData_out_3 = &Data_out[LONG_WINDOW_LENGTH];
+ pData_out_4 = &Data_out[TWICE_LONG_WINDOW_LENGTH_m_1];
+
+ /*
+ * Data_out
+ * >>>> <<<<
+ * pData_out_3 pData_out_4
+ * | | | | |
+ * pData_out_1 pData_out_2
+ * >>>> <<<<
+ */
+
+
+ exp = 16 - pv_normalize(max);
+
+ if (exp < 0)
+ {
+ exp = 0;
+ }
+
+ /*
+ * Apply A/2^(diff) + B
+ */
+
+
+ pData_in_1 = pData_in_ref1;
+ pData_in_2 = pData_in_ref2;
+
+ for (i = FWD_LONG_CX_ROT_LENGTH; i != 0; i--)
+ {
+
+ /*
+ * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
+ */
+
+ exp_jw = *p_rotate++;
+
+ /*
+ * Use auxiliary variables to avoid double accesses to memory.
+ * Data in is scaled to use only lower 16 bits.
+ */
+
+ temp_re = *(pData_in_1++) >> exp;
+ temp_im = *(pData_in_1++) >> exp;
+
+ /*
+ * Pre-rotation
+ */
+
+ temp_re_32 = (cmplx_mul32_by_16(temp_re, temp_im, exp_jw));
+ temp_im_32 = (cmplx_mul32_by_16(temp_im, -temp_re, exp_jw));
+
+ *(pData_out_1++) = - temp_re_32;
+ *(pData_out_2--) = temp_im_32;
+ *(pData_out_3++) = - temp_im_32;
+ *(pData_out_4--) = temp_re_32;
+
+ /*
+ * Pointer increment to jump over imag (1 & 4) or real parts
+ * (2 & 3)
+ */
+ pData_out_1++;
+ pData_out_2--;
+ pData_out_3++;
+ pData_out_4--;
+
+ /*
+ * Repeat procedure for odd index at the output
+ */
+
+ exp_jw = *p_rotate++;
+
+ temp_re = *(pData_in_2++) >> exp;
+ temp_im = *(pData_in_2++) >> exp;
+
+ temp_re_32 = (cmplx_mul32_by_16(temp_re, temp_im, exp_jw));
+ temp_im_32 = (cmplx_mul32_by_16(temp_im, -temp_re, exp_jw));
+
+ *(pData_out_1++) = - temp_re_32;
+ *(pData_out_2--) = temp_im_32;
+ *(pData_out_3++) = - temp_im_32;
+ *(pData_out_4--) = temp_re_32;
+
+ pData_out_1++;
+ pData_out_2--;
+ pData_out_3++;
+ pData_out_4--;
+
+ }
+
+ return (exp + 1);
+}
diff --git a/media/libstagefright/codecs/aacdec/fwd_long_complex_rot.h b/media/libstagefright/codecs/aacdec/fwd_long_complex_rot.h
new file mode 100644
index 0000000..5978906
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fwd_long_complex_rot.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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/fwd_long_complex_rot.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for functions fwd_long_complex_rot
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef FWD_LONG_COMPLEX_ROT_H
+#define FWD_LONG_COMPLEX_ROT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define FWD_LONG_CX_ROT_LENGTH 256
+#define TWICE_FWD_LONG_CX_ROT_LENGTH (FWD_LONG_CX_ROT_LENGTH<<1)
+#define LONG_WINDOW_LENGTH 1024
+#define LONG_WINDOW_LENGTH_m_1 (LONG_WINDOW_LENGTH - 1)
+#define TWICE_LONG_WINDOW_LENGTH_m_1 ((LONG_WINDOW_LENGTH<<1) - 1)
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+
+Int fwd_long_complex_rot(
+ Int32 *Data_in,
+ Int32 *Data_out,
+ Int32 max);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* FWD_LONG_COMPLEX_ROT_H */
diff --git a/media/libstagefright/codecs/aacdec/fwd_short_complex_rot.cpp b/media/libstagefright/codecs/aacdec/fwd_short_complex_rot.cpp
new file mode 100644
index 0000000..964f766
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fwd_short_complex_rot.cpp
@@ -0,0 +1,261 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+ Pathname: ./src/fwd_short_complex_rot.c
+ Funtions: fwd_short_complex_rot
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Date: 10/18/2002
+ Description:
+ (1) Change the input argument, only a single max is passed.
+ (2) Eliminate search for max, a fixed shift has replaced the
+ search for max with minimal loss of precision.
+ (3) Eliminated unused variables
+
+ Date: 10/28/2002
+ Description:
+ (1) Added comments per code review
+ (2) Eliminated hardly used condition on if-else (exp==0)
+
+ Description:
+
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ Data_in = Input vector (sized for short windows
+ 2*FWD_SHORT_CX_ROT_LENGTH elements), with freq. domain samples
+ type Int32 *
+
+ Data_out = Output vector with a post-rotation by exp(-j(2pi/N)(k+1/8)),
+ (sized for short windows 2*FWD_SHORT_CX_ROT_LENGTH)
+ type Int32 *
+
+ max = Input, carries the maximum value of the input vector
+ "Data_in"
+ type Int32
+
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ exp = shift factor to reflect signal scaling
+
+ Pointers and Buffers Modified:
+ Results are return in "Data_out"
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ fwd_short_complex_rot() performs the complex rotation for the MDCT
+ for the case of short windows. It performs digit reverse ordering as well
+ word normalization to ensure 16 by 16 bit multiplications.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ fwd_short_complex_rot() should execute a pre-rotation by
+ exp(-j(2pi/N)(k+1/8)), digit reverse ordering and word normalization
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "fwd_short_complex_rot.h"
+#include "digit_reversal_tables.h"
+#include "imdct_fxp.h"
+#include "pv_normalize.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+Int fwd_short_complex_rot(
+ Int32 *Data_in,
+ Int32 *Data_out,
+ Int32 max)
+
+{
+ Int i;
+ Int16 I;
+ const Int16 *pTable;
+ const Int32 *p_rotate;
+
+ Int32 *pData_in_1;
+ Int exp;
+ Int32 temp_re;
+ Int32 temp_im;
+
+ Int32 cos_n;
+ Int32 sin_n;
+ Int32 temp_re_32;
+ Int32 temp_im_32;
+
+ Int32 *pData_in_ref;
+
+ Int32 *pData_out_1;
+ Int32 *pData_out_2;
+ Int32 *pData_out_3;
+ Int32 *pData_out_4;
+
+ pTable = digit_reverse_64;
+ p_rotate = exp_rotation_N_256;
+
+ pData_in_ref = Data_in;
+
+ exp = 16 - pv_normalize(max);
+
+ if (exp < 0)
+ {
+ exp = 0;
+ }
+
+ pData_out_1 = Data_out;
+ pData_out_2 = &Data_out[TWICE_FWD_SHORT_CX_ROT_LENGTH_m_1];
+ pData_out_3 = &Data_out[TWICE_FWD_SHORT_CX_ROT_LENGTH];
+ pData_out_4 = &Data_out[FOUR_FWD_SHORT_CX_ROT_LENGTH_m_1];
+
+ /*
+ * Data_out
+ * >>>> <<<<
+ * pData_out_3 pData_out_4
+ * | | | | |
+ * pData_out_1 pData_out_2
+ * >>>> <<<<
+ */
+
+
+ for (i = FWD_SHORT_CX_ROT_LENGTH; i != 0; i--)
+ {
+ /*
+ * Perform digit reversal by accessing index I from table
+ */
+
+ I = *pTable++;
+ pData_in_1 = pData_in_ref + I;
+
+ /*
+ * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
+ */
+
+ sin_n = *p_rotate++;
+ cos_n = sin_n >> 16;
+ sin_n = sin_n & 0xFFFF;
+
+ /*
+ * Use auxiliary variables to avoid double accesses to memory.
+ * Data in is scaled to use only lower 16 bits.
+ */
+
+ temp_re = *(pData_in_1++) >> exp;
+ temp_im = *(pData_in_1) >> exp;
+
+ /*
+ * Pre-rotation
+ */
+
+ temp_re_32 = (temp_re * cos_n + temp_im * sin_n) >> 16;
+ temp_im_32 = (temp_im * cos_n - temp_re * sin_n) >> 16;
+
+ *(pData_out_1++) = - temp_re_32;
+ *(pData_out_2--) = temp_im_32;
+ *(pData_out_3++) = - temp_im_32;
+ *(pData_out_4--) = temp_re_32;
+
+ /*
+ * Pointer increment to jump over imag (1 & 4) or real parts
+ * (2 & 3)
+ */
+
+ pData_out_1++;
+ pData_out_2--;
+ pData_out_3++;
+ pData_out_4--;
+
+ } /* for(i) */
+
+ return (exp);
+}
diff --git a/media/libstagefright/codecs/aacdec/fwd_short_complex_rot.h b/media/libstagefright/codecs/aacdec/fwd_short_complex_rot.h
new file mode 100644
index 0000000..3d1e1f1
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fwd_short_complex_rot.h
@@ -0,0 +1,92 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: .fwd_short_complex_rot.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for functions fwd_short_complex_rot
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef FWD_SHORT_COMPLEX_ROT_H
+#define FWD_SHORT_COMPLEX_ROT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define FWD_SHORT_CX_ROT_LENGTH 64
+#define TWICE_FWD_SHORT_CX_ROT_LENGTH (FWD_SHORT_CX_ROT_LENGTH<<1)
+#define TWICE_FWD_SHORT_CX_ROT_LENGTH_m_1 ((FWD_SHORT_CX_ROT_LENGTH<<1) - 1)
+#define FOUR_FWD_SHORT_CX_ROT_LENGTH_m_1 ((FWD_SHORT_CX_ROT_LENGTH<<2) - 1)
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+Int fwd_short_complex_rot(
+ Int32 *Data_in,
+ Int32 *Data_out,
+ Int32 max);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* FWD_SHORT_COMPLEX_ROT_H */
diff --git a/media/libstagefright/codecs/aacdec/fxp_mul32.h b/media/libstagefright/codecs/aacdec/fxp_mul32.h
new file mode 100644
index 0000000..230cef5
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fxp_mul32.h
@@ -0,0 +1,72 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./c/include/fxp_mul32.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef FXP_MUL32
+#define FXP_MUL32
+
+#if defined(PV_ARM_V5)
+
+#include "fxp_mul32_arm_v5.h"
+
+#elif defined(PV_ARM_V4)
+
+#include "fxp_mul32_arm_v4.h"
+
+#elif defined(PV_ARM_MSC_EVC_V4)
+
+#include "fxp_mul32_c_msc_evc.h"
+
+#elif defined(PV_ARM_MSC_EVC_V5)
+
+#include "fxp_mul32_c_msc_evc_armv5.h"
+
+#elif defined(PV_ARM_GCC_V5)
+
+#include "fxp_mul32_arm_gcc.h"
+
+#elif defined(PV_ARM_GCC_V4)
+
+#include "fxp_mul32_arm_v4_gcc.h"
+
+#else
+
+#ifndef C_EQUIVALENT
+#define C_EQUIVALENT
+#endif
+
+#include "fxp_mul32_c_equivalent.h"
+
+#endif
+
+
+#endif /* FXP_MUL32 */
+
diff --git a/media/libstagefright/codecs/aacdec/fxp_mul32_arm_gcc.h b/media/libstagefright/codecs/aacdec/fxp_mul32_arm_gcc.h
new file mode 100644
index 0000000..dc58976
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fxp_mul32_arm_gcc.h
@@ -0,0 +1,547 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./c/include/fxp_mul32_arm_gcc.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef FXP_MUL32_ARM_GCC
+#define FXP_MUL32_ARM_GCC
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#include "pv_audio_type_defs.h"
+
+
+#if (defined (PV_ARM_GCC_V4) || defined(PV_ARM_GCC_V5)) /* ARM GNU COMPILER */
+
+
+
+#define preload_cache( a)
+
+
+ static inline Int32 shft_lft_1(Int32 y)
+ {
+ register Int32 x;
+ register Int32 ra = y;
+
+
+ asm volatile(
+ "qadd %0, %1, %1\n\t"
+ : "=&r*i"(x)
+ : "r"(ra));
+
+ return (x);
+ }
+
+ static inline Int32 fxp_mul_16_by_16bb(Int32 L_var1, const Int32 L_var2)
+ {
+
+ register Int32 tmp;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+
+ asm volatile(
+ "smulbb %0, %1, %2"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb));
+
+ return (tmp);
+ }
+
+
+#define fxp_mul_16_by_16(a, b) fxp_mul_16_by_16bb( a, b)
+
+
+ static inline Int32 fxp_mul_16_by_16tb(Int32 L_var1, const Int32 L_var2)
+{
+
+ register Int32 tmp;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+
+ asm volatile(
+ "smultb %0, %1, %2"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb));
+
+ return (tmp);
+ }
+
+ static inline Int32 fxp_mul_16_by_16bt(Int32 L_var1, const Int32 L_var2)
+{
+
+ register Int32 tmp;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+
+ asm volatile(
+ "smulbt %0, %1, %2"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb));
+
+ return (tmp);
+ }
+
+ static inline Int32 fxp_mul_16_by_16tt(Int32 L_var1, const Int32 L_var2)
+{
+
+ register Int32 tmp;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+
+ asm volatile(
+ "smultt %0, %1, %2"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb));
+
+ return (tmp);
+ }
+
+ static inline Int32 fxp_mac_16_by_16(const Int32 L_var1, const Int32 L_var2, Int32 L_add)
+{
+ register Int32 tmp;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile(
+ "smlabb %0, %1, %2, %3"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (tmp);
+ }
+
+
+
+ static inline Int32 fxp_mac_16_by_16_bb(const Int32 L_var1, const Int32 L_var2, Int32 L_add)
+{
+ register Int32 tmp;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile(
+ "smlabb %0, %1, %2, %3"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (tmp);
+ }
+
+
+ static inline Int32 fxp_mac_16_by_16_bt(const Int32 L_var1, const Int32 L_var2, Int32 L_add)
+{
+ register Int32 tmp;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile(
+ "smlabt %0, %1, %2, %3"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (tmp);
+ }
+
+
+
+ static inline Int32 cmplx_mul32_by_16(Int32 x, const Int32 y, Int32 exp_jw)
+{
+ register Int32 cx_sum;
+ register Int32 rx = (Int32)x;
+ register Int32 ry = (Int32)y;
+ register Int32 rexp = (Int32)exp_jw;
+ asm volatile(
+ "smulwt %0, %1, %3\n\t"
+ "smlawb %0, %2, %3, %0"
+ : "=&r*i"(cx_sum)
+ : "r"(rx),
+ "r"(ry),
+ "r"(rexp));
+
+ return (cx_sum);
+ }
+
+
+ static inline Int32 fxp_mul32_by_16(Int32 L_var1, const Int32 L_var2)
+{
+
+ register Int32 tmp;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+
+ asm volatile(
+ "smulwb %0, %1, %2"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb));
+
+ return (tmp);
+ }
+
+#define fxp_mul32_by_16b( a, b) fxp_mul32_by_16( a, b)
+
+
+ static inline Int32 fxp_mul32_by_16t(Int32 L_var1, const Int32 L_var2)
+{
+
+ register Int32 tmp;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+
+ asm volatile(
+ "smulwt %0, %1, %2"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb));
+
+ return (tmp);
+ }
+
+
+
+ static inline Int32 fxp_mac32_by_16(const Int32 L_var1, const Int32 L_var2, Int32 L_add)
+{
+
+ register Int32 tmp;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile(
+ "smlawb %0, %1, %2, %3"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (tmp);
+ }
+
+
+ __inline int64 fxp_mac64_Q31(int64 sum, const Int32 L_var1, const Int32 L_var2)
+{
+ sum += (int64)L_var1 * L_var2;
+ return (sum);
+ }
+
+
+
+
+ static inline Int32 fxp_mac32_Q30(const Int32 a, const Int32 b, Int32 L_add)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "add %4, %4, %0, asl #2\n\t"
+ "add %0, %4, %1, lsr #30"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_mac32_Q31(Int32 L_add, const Int32 a, const Int32 b)
+{
+
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "add %0, %0, %4"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (result64_hi);
+ }
+
+
+
+ static inline Int32 fxp_msu32_Q31(Int32 L_sub, const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ register Int32 rc = (Int32)L_sub;
+
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "sub %0, %4, %0"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_mul32_Q31(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile(
+ "smull %1, %0, %2, %3"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_mul32_Q30(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #2\n\t"
+ "orr %0, %0, %1, lsr #30"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+ return (result64_hi);
+ }
+
+
+
+ static inline Int32 fxp_mac32_Q29(const Int32 a, const Int32 b, Int32 L_add)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "add %4, %4, %0, lsl #3\n\t"
+ "add %0, %4, %1, lsr #29"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_msu32_Q29(const Int32 a, const Int32 b, Int32 L_sub)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ register Int32 rc = (Int32)L_sub;
+
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "sub %4, %4, %0, lsl #3\n\t"
+ "sub %0, %4, %1, lsr #29"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (result64_hi);
+ }
+
+ static inline Int32 fxp_mul32_Q29(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #3\n\t"
+ "orr %0, %0, %1, lsr #29"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+ return (result64_hi);
+ }
+
+
+
+ static inline Int32 fxp_mul32_Q28(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #4\n\t"
+ "orr %0, %0, %1, lsr #28"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+ return (result64_hi);
+ }
+
+ static inline Int32 fxp_mul32_Q27(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #5\n\t"
+ "orr %0, %0, %1, lsr #27"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_mul32_Q26(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #6\n\t"
+ "orr %0, %0, %1, lsr #26"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_mul32_Q20(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #12\n\t"
+ "orr %0, %0, %1, lsr #20"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_mul32_Q15(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #17\n\t"
+ "orr %0, %0, %1, lsr #15"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+
+
+ static inline Int32 fxp_mul32_Q14(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #18\n\t"
+ "orr %0, %0, %1, lsr #14"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FXP_MUL32 */
+
diff --git a/media/libstagefright/codecs/aacdec/fxp_mul32_arm_v4.h b/media/libstagefright/codecs/aacdec/fxp_mul32_arm_v4.h
new file mode 100644
index 0000000..6869c54
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fxp_mul32_arm_v4.h
@@ -0,0 +1,429 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: fxp_mul32_c_equivalent.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef FXP_MUL32_ARM_V4
+#define FXP_MUL32_ARM_V4
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#include "pv_audio_type_defs.h"
+
+
+#if defined(PV_ARM_V4)
+
+#define preload_cache( a)
+
+
+ __inline Int32 shft_lft_1(Int32 L_var1)
+ {
+ Int32 x;
+ Int32 z = 1; /* rvct compiler problem */
+ __asm
+ {
+ mov x, L_var1, asl 1
+ teq L_var1, x, asr z
+ eorne x, INT32_MAX, L_var1, asr #31
+ }
+
+ return(x);
+ }
+
+
+ __inline Int32 fxp_mul_16_by_16bb(Int32 L_var1, Int32 L_var2)
+ {
+ __asm
+ {
+
+ mov L_var2, L_var2, asl #16
+ mov L_var2, L_var2, asr #16
+ mov L_var1, L_var1, asl #16
+ mov L_var1, L_var1, asr #16
+
+
+ mul L_var1, L_var2, L_var1
+ }
+
+ return L_var1;
+
+ }
+
+
+#define fxp_mul_16_by_16(a, b) fxp_mul_16_by_16bb( a, b)
+
+
+ __inline Int32 fxp_mul_16_by_16tb(Int32 L_var1, Int32 L_var2)
+ {
+ __asm
+ {
+ mov L_var2, L_var2, asl #16
+ mov L_var2, L_var2, asr #16
+ mov L_var1, L_var1, asr #16
+
+ mul L_var1, L_var2, L_var1
+ }
+ return L_var1;
+ }
+
+ __inline Int32 fxp_mul_16_by_16bt(Int32 L_var1, Int32 L_var2)
+ {
+ __asm
+ {
+ mov L_var2, L_var2, asr #16
+ mov L_var1, L_var1, asl #16
+ mov L_var1, L_var1, asr #16
+
+ mul L_var1, L_var2, L_var1
+ }
+
+ return L_var1;
+
+ }
+
+
+ __inline Int32 fxp_mul_16_by_16tt(Int32 L_var1, Int32 L_var2)
+ {
+ __asm
+ {
+ mov L_var2, L_var2, asr #16
+ mov L_var1, L_var1, asr #16
+
+ mul L_var1, L_var2, L_var1
+ }
+
+ return L_var1;
+
+ }
+
+ __inline Int32 fxp_mac_16_by_16(const Int32 L_var1, const Int32 L_var2, Int32 L_add)
+ {
+ __asm
+ {
+ mla L_add, L_var1, L_var2, L_add
+ }
+ return (L_add);
+ }
+
+
+ __inline Int32 fxp_mac_16_by_16_bb(const Int32 L_var1, Int32 L_var2, Int32 L_add)
+ {
+ __asm
+ {
+ mov L_var2, L_var2, asl #16
+ mov L_var2, L_var2, asr #16
+ mla L_add, L_var1, L_var2, L_add
+ }
+ return L_add;
+ }
+
+ __inline Int32 fxp_mac_16_by_16_bt(Int16 L_var1, Int32 L_var2, Int32 L_add)
+ {
+ __asm
+ {
+ mov L_var2, L_var2, asr #16
+ mla L_add, L_var1, L_var2, L_add
+ }
+ return L_add;
+ }
+
+
+ __inline Int32 cmplx_mul32_by_16(Int32 x, const Int32 y, Int32 exp_jw)
+ {
+
+ Int32 result64_hi;
+ Int32 rTmp0;
+ Int32 iTmp0;
+ __asm
+ {
+ mov rTmp0, exp_jw, asr #16
+ mov rTmp0, rTmp0, asl #16
+ mov iTmp0, exp_jw, asl #16
+ smull rTmp0, result64_hi, x, rTmp0
+ smlal iTmp0, result64_hi, y, iTmp0
+ }
+
+ return (result64_hi);
+ }
+
+
+ __inline Int32 fxp_mul32_by_16(Int32 L_var1, Int32 L_var2)
+ {
+ Int32 result64_hi;
+ __asm
+ {
+ mov L_var2, L_var2, asl #16
+ smull L_var1, result64_hi, L_var2, L_var1
+ }
+ return (result64_hi);
+ }
+
+
+
+#define fxp_mul32_by_16b( a, b) fxp_mul32_by_16( a, b)
+
+
+
+ __inline Int32 fxp_mul32_by_16t(Int32 L_var1, Int32 L_var2)
+ {
+
+ Int32 result64_hi;
+ __asm
+ {
+ mov L_var2, L_var2, asr #16
+ mov L_var2, L_var2, asl #16
+ smull L_var1, result64_hi, L_var2, L_var1
+ }
+ return (result64_hi);
+
+ }
+
+ __inline Int32 fxp_mac32_by_16(Int32 L_var1, Int32 L_var2, Int32 L_add)
+ {
+
+ __asm
+ {
+ mov L_var2, L_var2, asl #16
+ smlal L_var1, L_add, L_var2, L_var1
+ }
+
+ return (L_add);
+ }
+
+
+ __inline int64 fxp_mac64_Q31(int64 sum, const Int32 L_var1, const Int32 L_var2)
+ {
+ uint32 b = (UInt32)(sum);
+ int32 c = Int32(sum >> 32);
+ __asm
+ {
+ smlal b, c, L_var1, L_var2
+ }
+ return (((int64(c)) << 32) | b);
+ }
+
+
+ __inline Int32 fxp_mul32_Q31(Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ __asm
+ {
+ smull L_var1, result64_hi, L_var2, L_var1
+ }
+ return (result64_hi);
+ }
+
+
+ __inline Int32 fxp_mac32_Q31(Int32 L_add, Int32 L_var1, const Int32 L_var2)
+ {
+ __asm
+ {
+ smlal L_var1, L_add, L_var2, L_var1
+ }
+ return L_add;
+ }
+
+ __inline Int32 fxp_msu32_Q31(Int32 L_sub, Int32 L_var1, const Int32 L_var2)
+ {
+ __asm
+ {
+ rsb L_var1, L_var1, #0
+ smlal L_var1, L_sub, L_var2, L_var1
+ }
+ return L_sub;
+ }
+
+
+ __inline Int32 fxp_mul32_Q30(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #2
+ orr result64_hi, result64_hi, result64_lo, lsr #30
+ }
+ return (result64_hi);
+ }
+
+
+ __inline Int32 fxp_mac32_Q30(const Int32 L_var1, const Int32 L_var2, Int32 L_add)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ add L_add, L_add, result64_hi, asl #2
+ add L_add, L_add, result64_lo, lsr #30
+ }
+ return (L_add);
+ }
+
+
+ __inline Int32 fxp_mul32_Q29(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #3
+ orr result64_hi, result64_hi, result64_lo, lsr #29
+ }
+ return (result64_hi);
+ }
+
+ __inline Int32 fxp_mac32_Q29(const Int32 L_var1, const Int32 L_var2, Int32 L_add)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ add L_add, L_add, result64_hi, asl #3
+ add L_add, L_add, result64_lo, lsr #29
+ }
+ return (L_add);
+ }
+
+ __inline Int32 fxp_msu32_Q29(const Int32 L_var1, const Int32 L_var2, Int32 L_sub)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ sub L_sub, L_sub, result64_hi, asl #3
+ sub L_sub, L_sub, result64_lo, lsr #29
+ }
+ return (L_sub);
+ }
+
+ __inline Int32 fxp_mul32_Q28(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #4
+ orr result64_hi, result64_hi, result64_lo, lsr #28
+ }
+ return (result64_hi);
+ }
+
+ __inline Int32 fxp_mul32_Q27(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #5
+ orr result64_hi, result64_hi, result64_lo, lsr #27
+ }
+ return (result64_hi);
+ }
+
+ __inline Int32 fxp_mul32_Q26(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #6
+ orr result64_hi, result64_hi, result64_lo, lsr #26
+ }
+ return (result64_hi);
+ }
+
+ __inline Int32 fxp_mul32_Q20(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #12
+ orr result64_hi, result64_hi, result64_lo, lsr #20
+ }
+ return (result64_hi);
+ }
+
+ __inline Int32 fxp_mul32_Q15(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #17
+ orr result64_hi, result64_hi, result64_lo, lsr #15
+ }
+ return (result64_hi);
+ }
+
+
+
+
+ __inline Int32 fxp_mul32_Q14(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #18
+ orr result64_hi, result64_hi, result64_lo, lsr #14
+ }
+ return (result64_hi);
+ }
+
+
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FXP_MUL32 */
+
diff --git a/media/libstagefright/codecs/aacdec/fxp_mul32_arm_v4_gcc.h b/media/libstagefright/codecs/aacdec/fxp_mul32_arm_v4_gcc.h
new file mode 100755
index 0000000..f4ab2f7
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fxp_mul32_arm_v4_gcc.h
@@ -0,0 +1,630 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: fxp_mul32_arm_v4_gcc.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+
+
+#ifndef FXP_MUL32_V4_ARM_GCC
+#define FXP_MUL32_V4_ARM_GCC
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#include "pv_audio_type_defs.h"
+
+
+#if defined (_ARM_V4_GCC) /* ARM_V4 GNU COMPILER */
+
+
+#define preload_cache( a)
+
+
+ static inline Int32 shft_lft_1(Int32 L_var1)
+ {
+ Int32 x;
+ register Int32 ra = L_var1;
+ Int32 z = INT32_MAX;
+
+ asm volatile(
+ "mov %0, %1, asl #1\n\t"
+ "teq %1, %0, asr #1\n\t"
+ "eorne %0, %2, %1, asr #31"
+ : "=&r*i"(x)
+ : "r"(ra),
+ "r"(z));
+
+ return(x);
+ }
+
+ static inline Int32 fxp_mul_16_by_16bb(Int32 L_var1, Int32 L_var2)
+{
+
+ Int32 tmp1;
+ Int32 tmp2;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+
+ asm volatile(
+ "mov %0, %3, asl #16\n\t"
+ "mov %0, %0, asr #16\n\t"
+ "mov %1, %2, asl #16\n\t"
+ "mov %1, %1, asr #16\n\t"
+ "mul %0, %1, %0"
+ : "=&r*i"(tmp1),
+ "=&r*i"(tmp2)
+ : "r"(ra),
+ "r"(rb));
+
+ return (tmp1);
+
+ }
+
+#define fxp_mul_16_by_16(a, b) fxp_mul_16_by_16bb( a, b)
+
+
+ static inline Int32 fxp_mul_16_by_16tb(Int32 L_var1, Int32 L_var2)
+{
+
+ Int32 tmp1;
+ Int32 tmp2;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+
+ asm volatile(
+ "mov %0, %3, asl #16\n\t"
+ "mov %0, %0, asr #16\n\t"
+ "mov %1, %2, asr #16\n\t"
+ "mul %0, %1, %0"
+ : "=&r*i"(tmp1),
+ "=&r*i"(tmp2)
+ : "r"(ra),
+ "r"(rb));
+
+ return (tmp1);
+
+ }
+
+
+ static inline Int32 fxp_mul_16_by_16bt(Int32 L_var1, Int32 L_var2)
+{
+
+ Int32 tmp1;
+ Int32 tmp2;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+
+ asm volatile(
+ "mov %0, %3, asr #16\n\t"
+ "mov %1, %2, asl #16\n\t"
+ "mov %1, %1, asr #16\n\t"
+ "mul %0, %1, %0"
+ : "=&r*i"(tmp1),
+ "=&r*i"(tmp2)
+ : "r"(ra),
+ "r"(rb));
+
+ return (tmp1);
+
+ }
+
+
+ static inline Int32 fxp_mul_16_by_16tt(Int32 L_var1, Int32 L_var2)
+{
+
+ Int32 tmp1;
+ Int32 tmp2;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+
+ asm volatile(
+ "mov %0, %3, asr #16\n\t"
+ "mov %1, %2, asr #16\n\t"
+ "mul %0, %1, %0"
+ : "=&r*i"(tmp1),
+ "=&r*i"(tmp2)
+ : "r"(ra),
+ "r"(rb));
+
+ return (tmp1);
+
+ }
+
+
+
+ static inline Int32 fxp_mac_16_by_16(Int16 L_var1, Int16 L_var2, Int32 L_add)
+{
+
+ Int32 tmp;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile(
+ "mla %0, %1, %2, %3"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (tmp);
+ }
+
+
+
+ static inline Int32 fxp_mac_16_by_16_bb(Int16 L_var1, Int32 L_var2, Int32 L_add)
+{
+
+ Int32 tmp1;
+ Int32 tmp2;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile(
+ "mov %0, %3, asl #16\n\t"
+ "mov %0, %0, asr #16\n\t"
+ "mla %1, %0, %2, %4"
+ : "=&r*i"(tmp1),
+ "=&r*i"(tmp2)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (tmp2);
+ }
+
+
+
+ static inline Int32 fxp_mac_16_by_16_bt(Int16 L_var1, Int32 L_var2, Int32 L_add)
+{
+
+ Int32 tmp1;
+ Int32 tmp2;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile(
+ "mov %0, %3, asr #16\n\t"
+ "mla %1, %0, %2, %4"
+ : "=&r*i"(tmp1),
+ "=&r*i"(tmp2)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (tmp2);
+
+ }
+
+
+
+ static inline Int32 cmplx_mul32_by_16(Int32 x, Int32 y, Int32 exp_jw)
+{
+
+ Int32 rTmp0;
+ Int32 iTmp0;
+ Int32 result64_hi;
+ register Int32 ra = (Int32)x;
+ register Int32 rb = (Int32)y;
+ register Int32 rc = (Int32)exp_jw;
+
+
+
+ asm volatile(
+ "mov %0, %5, asr #16\n\t"
+ "mov %1, %5, asl #16\n\t"
+ "mov %0, %0, asl #16\n\t"
+ : "=&r*i"(rTmp0),
+ "=&r*i"(iTmp0),
+ "=&r*i"(result64_hi)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+
+ asm volatile(
+ "smull %0, %2, %3, %0\n\t"
+ "smlal %1, %2, %4, %1"
+ : "=&r*i"(rTmp0),
+ "=&r*i"(iTmp0),
+ "=&r*i"(result64_hi)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (result64_hi);
+
+
+ }
+
+
+ static inline Int32 fxp_mul32_by_16(Int32 L_var1, Int32 L_var2)
+{
+
+ Int32 rTmp0;
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+
+ asm volatile(
+ "mov %0, %4, asl #16\n\t"
+ "smull %2, %1, %0, %3"
+ : "=&r*i"(rTmp0),
+ "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+
+#define fxp_mul32_by_16b( a, b) fxp_mul32_by_16( a, b)
+
+
+
+ static inline Int32 fxp_mul32_by_16t(Int32 L_var1, Int32 L_var2)
+{
+
+ Int32 rTmp0;
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+
+ asm volatile(
+ "mov %0, %4, asr #16\n\t"
+ "mov %0, %0, asl #16\n\t"
+ "smull %2, %1, %0, %3"
+ : "=&r*i"(rTmp0),
+ "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+
+
+ static inline Int32 fxp_mac32_by_16(Int32 L_var1, Int32 L_var2, Int32 L_add)
+{
+
+ Int32 rTmp0;
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)L_var1;
+ register Int32 rb = (Int32)L_var2;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile(
+ "mov %0, %4, asl #16\n\t"
+ "mov %1, %5\n\t"
+ "smlal %2, %1, %0, %3"
+ : "=&r*i"(rTmp0),
+ "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (result64_hi);
+ }
+
+
+ static inline int64 fxp_mac64_Q31(int64 sum, const Int32 L_var1, const Int32 L_var2)
+{
+ sum += (int64)L_var1 * L_var2;
+ return (sum);
+ }
+
+
+ static inline Int32 fxp_mac32_Q30(const Int32 a, const Int32 b, Int32 L_add)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "add %4, %4, %0, asl #2\n\t"
+ "add %0, %4, %1, lsr #30"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_mac32_Q31(Int32 L_add, const Int32 a, const Int32 b)
+{
+
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "add %0, %0, %4"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (result64_hi);
+ }
+
+
+
+ static inline Int32 fxp_msu32_Q31(Int32 L_sub, const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ register Int32 rc = (Int32)L_sub;
+
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "sub %0, %4, %0"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_mul32_Q31(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile(
+ "smull %1, %0, %2, %3"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_mul32_Q30(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #2\n\t"
+ "orr %0, %0, %1, lsr #30"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+ return (result64_hi);
+ }
+
+
+
+ static inline Int32 fxp_mac32_Q29(const Int32 a, const Int32 b, Int32 L_add)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ register Int32 rc = (Int32)L_add;
+
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "add %4, %4, %0, lsl #3\n\t"
+ "add %0, %4, %1, lsr #29"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_msu32_Q29(const Int32 a, const Int32 b, Int32 L_sub)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ register Int32 rc = (Int32)L_sub;
+
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "sub %4, %4, %0, lsl #3\n\t"
+ "sub %0, %4, %1, lsr #29"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (result64_hi);
+ }
+
+ static inline Int32 fxp_mul32_Q29(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #3\n\t"
+ "orr %0, %0, %1, lsr #29"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+ return (result64_hi);
+ }
+
+
+
+ static inline Int32 fxp_mul32_Q28(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #4\n\t"
+ "orr %0, %0, %1, lsr #28"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+ return (result64_hi);
+ }
+
+ static inline Int32 fxp_mul32_Q27(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #5\n\t"
+ "orr %0, %0, %1, lsr #27"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_mul32_Q26(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #6\n\t"
+ "orr %0, %0, %1, lsr #26"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_mul32_Q20(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #12\n\t"
+ "orr %0, %0, %1, lsr #20"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+
+ static inline Int32 fxp_mul32_Q15(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #17\n\t"
+ "orr %0, %0, %1, lsr #15"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+
+
+ static inline Int32 fxp_mul32_Q14(const Int32 a, const Int32 b)
+{
+ Int32 result64_hi;
+ Int32 result64_lo;
+ register Int32 ra = (Int32)a;
+ register Int32 rb = (Int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %0, %0, lsl #18\n\t"
+ "orr %0, %0, %1, lsr #14"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FXP_MUL32_V4_ARM_GCC */
+
+
+
diff --git a/media/libstagefright/codecs/aacdec/fxp_mul32_arm_v5.h b/media/libstagefright/codecs/aacdec/fxp_mul32_arm_v5.h
new file mode 100644
index 0000000..8ab108f
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fxp_mul32_arm_v5.h
@@ -0,0 +1,450 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./c/include/fxp_mul32_arm_v5.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef FXP_MUL32_ARM_V5
+#define FXP_MUL32_ARM_V5
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "pv_audio_type_defs.h"
+
+
+#if defined(PV_ARM_V5)
+
+//#undef EXTENDED_ASM
+#define EXTENDED_ASM
+#define _ARM_V5_
+
+
+ __inline Int32 shft_lft_1(Int32 L_var1)
+ {
+ __asm
+ {
+ qadd L_var1, L_var1, L_var1
+ }
+
+ return L_var1;
+ }
+
+
+ __inline Int32 fxp_mul_16_by_16(Int32 L_var1, Int32 L_var2)
+ {
+ __asm
+ {
+ smulbb L_var1, L_var1, L_var2
+ }
+ return L_var1;
+ }
+
+
+ __inline Int32 fxp_mul_16_by_16bb(Int32 L_var1, Int32 L_var2)
+ {
+ __asm
+ {
+ smulbb L_var1, L_var1, L_var2
+ }
+ return L_var1;
+ }
+
+
+ __inline Int32 fxp_mul_16_by_16tb(Int32 L_var1, Int32 L_var2)
+ {
+ __asm
+ {
+ smultb L_var1, L_var1, L_var2
+ }
+ return L_var1;
+ }
+
+ __inline Int32 fxp_mul_16_by_16tt(Int32 L_var1, Int32 L_var2)
+ {
+ __asm
+ {
+ smultt L_var1, L_var1, L_var2
+ }
+ return L_var1;
+ }
+
+ __inline Int32 fxp_mul_16_by_16bt(Int32 L_var1, Int32 L_var2)
+ {
+ __asm
+ {
+ smulbt L_var1, L_var1, L_var2
+ }
+ return L_var1;
+ }
+
+
+
+ __inline Int32 fxp_mac_16_by_16(const Int32 L_var1, const Int32 L_var2, Int32 L_add)
+ {
+ __asm
+ {
+ smlabb L_add, L_var1, L_var2, L_add
+ }
+ return (L_add);
+ }
+
+ __inline Int32 fxp_mac_16_by_16_bb(const Int32 L_var1, Int32 L_var2, Int32 L_add)
+ {
+ __asm
+ {
+ smlabb L_add, L_var1, L_var2, L_add
+ }
+ return L_add;
+ }
+
+ __inline Int32 fxp_mac_16_by_16_bt(const Int32 L_var1, Int32 L_var2, Int32 L_add)
+ {
+ __asm
+ {
+ smlabt L_add, L_var1, L_var2, L_add
+ }
+ return L_add;
+ }
+
+
+ __inline Int32 fxp_mac_16_by_16_tb(const Int32 L_var1, Int32 L_var2, Int32 L_add)
+ {
+ __asm
+ {
+ smlatb L_add, L_var1, L_var2, L_add
+ }
+ return L_add;
+ }
+
+ __inline Int32 fxp_mac_16_by_16_tt(const Int32 L_var1, Int32 L_var2, Int32 L_add)
+ {
+ __asm
+ {
+ smlatt L_add, L_var1, L_var2, L_add
+ }
+ return L_add;
+ }
+
+ __inline Int32 fxp_mac32_by_16(Int32 L_var1, const Int32 L_var2, Int32 L_add)
+ {
+ __asm
+ {
+ smlawb L_add, L_var1, L_var2, L_add
+ }
+ return (L_add);
+ }
+
+
+ __inline int64 fxp_mac64_Q31(int64 sum, const Int32 L_var1, const Int32 L_var2)
+ {
+ uint32 b = (UInt32)(sum);
+ int32 c = Int32(sum >> 32);
+ __asm
+ {
+ smlal b, c, L_var1, L_var2
+ }
+ return (((int64(c)) << 32) | b);
+ }
+
+
+ __inline Int32 fxp_mac32_Q31(Int32 L_add, Int32 L_var1, const Int32 L_var2)
+ {
+ __asm
+ {
+ smlal L_var1, L_add, L_var2, L_var1
+ }
+ return L_add;
+ }
+
+ __inline Int32 fxp_msu32_Q31(Int32 L_sub, Int32 L_var1, const Int32 L_var2)
+ {
+ __asm
+ {
+ rsb L_var1, L_var1, #0
+ smlal L_var1, L_sub, L_var2, L_var1
+ }
+ return L_sub;
+ }
+
+ __inline Int32 fxp_mul32_Q31(Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ __asm
+ {
+ smull L_var1, result64_hi, L_var2, L_var1
+ }
+ return (result64_hi);
+ }
+
+ __inline Int32 fxp_mul32_Q30(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #2
+#ifdef EXTENDED_ASM
+ mov result64_lo, result64_lo, lsr #30
+ orr result64_hi, result64_lo, result64_hi
+#else
+ orr result64_hi, result64_hi, result64_lo, lsr #30
+#endif
+ }
+ return (result64_hi);
+ }
+
+
+ __inline Int32 fxp_mac32_Q30(const Int32 L_var1, const Int32 L_var2, Int32 L_add)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ add L_add, L_add, result64_hi, asl #2
+ add L_add, L_add, result64_lo, lsr #30
+ }
+ return (L_add);
+ }
+
+
+ __inline Int32 fxp_mul32_Q29(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #3
+#ifdef EXTENDED_ASM
+ mov result64_lo, result64_lo, lsr #29
+ orr result64_hi, result64_lo, result64_hi
+#else
+ orr result64_hi, result64_hi, result64_lo, lsr #29
+#endif
+ }
+ return (result64_hi);
+ }
+
+
+
+ __inline Int32 fxp_mac32_Q29(const Int32 L_var1, const Int32 L_var2, Int32 L_add)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ add L_add, L_add, result64_hi, asl #3
+ add L_add, L_add, result64_lo, lsr #29
+ }
+ return (L_add);
+ }
+
+
+ __inline Int32 fxp_msu32_Q29(const Int32 L_var1, const Int32 L_var2, Int32 L_sub)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ sub L_sub, L_sub, result64_hi, asl #3
+ sub L_sub, L_sub, result64_lo, lsr #29
+ }
+ return (L_sub);
+ }
+
+
+ __inline Int32 fxp_mul32_Q28(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #4
+#ifdef EXTENDED_ASM
+ mov result64_lo, result64_lo, lsr #28
+ orr result64_hi, result64_lo, result64_hi
+#else
+ orr result64_hi, result64_hi, result64_lo, lsr #28
+#endif
+
+ }
+ return (result64_hi);
+ }
+
+ __inline Int32 fxp_mul32_Q27(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #5
+#ifdef EXTENDED_ASM
+ mov result64_lo, result64_lo, lsr #27
+ orr result64_hi, result64_lo, result64_hi
+#else
+ orr result64_hi, result64_hi, result64_lo, lsr #27
+#endif
+ }
+ return (result64_hi);
+ }
+
+ __inline Int32 fxp_mul32_Q26(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #6
+#ifdef EXTENDED_ASM
+ mov result64_lo, result64_lo, lsr #26
+ orr result64_hi, result64_lo, result64_hi
+#else
+ orr result64_hi, result64_hi, result64_lo, lsr #26
+#endif
+
+ }
+ return (result64_hi);
+ }
+
+ __inline Int32 fxp_mul32_Q20(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #12
+#ifdef EXTENDED_ASM
+ mov result64_lo, result64_lo, lsr #20
+ orr result64_hi, result64_lo, result64_hi
+#else
+ orr result64_hi, result64_hi, result64_lo, lsr #20
+#endif
+ }
+ return (result64_hi);
+ }
+
+ __inline Int32 fxp_mul32_by_16(Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ __asm
+ {
+ smulwb result64_hi, L_var1, L_var2
+ }
+ return (result64_hi);
+ }
+
+#define fxp_mul32_by_16b( a, b) fxp_mul32_by_16(a, b)
+
+ __inline Int32 fxp_mul32_by_16t(Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ __asm
+ {
+ smulwt result64_hi, L_var1, L_var2
+ }
+ return (result64_hi);
+ }
+
+ __inline Int32 fxp_mul32_Q15(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #17
+#ifdef EXTENDED_ASM
+ mov result64_lo, result64_lo, lsr #15
+ orr result64_hi, result64_lo, result64_hi
+#else
+ orr result64_hi, result64_hi, result64_lo, lsr #15
+#endif
+ }
+ return (result64_hi);
+ }
+
+
+ __inline Int32 cmplx_mul32_by_16(Int32 L_var1, const Int32 L_var2, const Int32 cmplx)
+ {
+ Int32 result64_hi;
+
+ __asm
+ {
+ smulwt result64_hi, L_var1, cmplx
+ smlawb result64_hi, L_var2, cmplx, result64_hi
+ }
+ return (result64_hi);
+
+ }
+
+ __inline Int32 fxp_mul32_Q14(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_hi, result64_hi, asl #18
+#ifdef EXTENDED_ASM
+ mov result64_lo, result64_lo, lsr #14
+ orr result64_hi, result64_lo, result64_hi
+#else
+ orr result64_hi, result64_hi, result64_lo, lsr #14
+#endif
+ }
+ return (result64_hi);
+ }
+
+
+#define preload_cache( a)
+
+
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FXP_MUL32 */
+
diff --git a/media/libstagefright/codecs/aacdec/fxp_mul32_c_equivalent.h b/media/libstagefright/codecs/aacdec/fxp_mul32_c_equivalent.h
new file mode 100644
index 0000000..5bcbe53
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fxp_mul32_c_equivalent.h
@@ -0,0 +1,285 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./c/include/fxp_mul32_c_equivalent.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef FXP_MUL32_C_EQUIVALENT
+#define FXP_MUL32_C_EQUIVALENT
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#include "pv_audio_type_defs.h"
+
+
+#if defined(C_EQUIVALENT)
+
+#define preload_cache( a)
+
+ __inline Int32 shft_lft_1(Int32 L_var1)
+ {
+ if (((L_var1 << 1) >> 1) == L_var1)
+ L_var1 <<= 1;
+ else
+ L_var1 = ((L_var1 >> 31) ^ INT32_MAX);
+
+ return (L_var1);
+
+ }
+
+
+ __inline Int32 fxp_mul_16_by_16bb(Int32 L_var1, Int32 L_var2)
+ {
+ L_var2 = (L_var2 << 16) >> 16;
+ L_var1 = (L_var1 << 16) >> 16;
+
+ L_var1 *= L_var2;
+
+ return L_var1;
+
+ }
+
+
+#define fxp_mul_16_by_16(a, b) fxp_mul_16_by_16bb( a, b)
+
+
+ __inline Int32 fxp_mul_16_by_16tb(Int32 L_var1, Int32 L_var2)
+ {
+ L_var2 = (L_var2 << 16) >> 16;
+ L_var1 = L_var1 >> 16;
+
+ L_var1 *= L_var2;
+
+ return L_var1;
+
+ }
+
+
+ __inline Int32 fxp_mul_16_by_16bt(Int32 L_var1, Int32 L_var2)
+ {
+ L_var2 = L_var2 >> 16;
+ L_var1 = (L_var1 << 16) >> 16;
+
+ L_var1 *= L_var2;
+
+ return L_var1;
+
+ }
+
+
+ __inline Int32 fxp_mul_16_by_16tt(Int32 L_var1, Int32 L_var2)
+ {
+ L_var2 = L_var2 >> 16;
+ L_var1 = L_var1 >> 16;
+
+ L_var1 *= L_var2;
+
+ return L_var1;
+
+ }
+
+ __inline Int32 fxp_mac_16_by_16(Int16 L_var1, Int16 L_var2, Int32 L_add)
+ {
+
+ L_add += L_var1 * L_var2;
+
+ return L_add;
+
+ }
+
+
+
+
+
+ __inline Int32 fxp_mac_16_by_16_bb(Int16 L_var1, Int32 L_var2, Int32 L_add)
+ {
+ L_var2 = (L_var2 << 16) >> 16;
+
+ L_add += L_var1 * L_var2;
+
+ return L_add;
+
+ }
+
+
+ __inline Int32 fxp_mac_16_by_16_bt(Int16 L_var1, Int32 L_var2, Int32 L_add)
+ {
+ L_var2 = L_var2 >> 16;
+
+ L_add += L_var1 * L_var2;
+
+ return L_add;
+
+ }
+
+
+
+
+
+ __inline Int32 cmplx_mul32_by_16(Int32 x, const Int32 y, Int32 exp_jw)
+ {
+ Int32 rTmp0 = (Int16)(exp_jw >> 16);
+ Int32 iTmp0 = exp_jw;
+ Int32 z;
+
+ z = (Int32)(((int64_t)x * (rTmp0 << 16)) >> 32);
+ z += (Int32)(((int64_t)y * (iTmp0 << 16)) >> 32);
+
+ return (z);
+ }
+
+
+ __inline Int32 fxp_mul32_by_16(Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 z;
+
+ z = (Int32)(((int64_t) L_var1 * (L_var2 << 16)) >> 32);
+ return(z);
+ }
+
+
+#define fxp_mul32_by_16b( a, b) fxp_mul32_by_16( a, b)
+
+
+ __inline Int32 fxp_mul32_by_16t(Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 rTmp0 = (Int16)(L_var2 >> 16);
+ Int32 z;
+
+ z = (Int32)(((int64_t) L_var1 * (rTmp0 << 16)) >> 32);
+
+ return(z);
+ }
+
+
+ __inline Int32 fxp_mac32_by_16(const Int32 L_var1, const Int32 L_var2, Int32 L_add)
+ {
+ Int32 rTmp0 = L_var2 << 16;
+
+ L_add += (Int32)(((int64_t) L_var1 * rTmp0) >> 32);
+
+ return(L_add);
+ }
+
+ __inline int64_t fxp_mac64_Q31(int64_t sum, const Int32 L_var1, const Int32 L_var2)
+ {
+ sum += (int64_t)L_var1 * L_var2;
+ return (sum);
+ }
+
+ __inline Int32 fxp_mul32_Q31(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64_t)(a) * b) >> 32);
+ }
+
+ __inline Int32 fxp_mac32_Q31(Int32 L_add, const Int32 a, const Int32 b)
+ {
+ return (L_add + (Int32)(((int64_t)(a) * b) >> 32));
+ }
+
+ __inline Int32 fxp_msu32_Q31(Int32 L_sub, const Int32 a, const Int32 b)
+ {
+ return (L_sub - (Int32)(((int64_t)(a) * b) >> 32));
+ }
+
+
+ __inline Int32 fxp_mul32_Q30(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64_t)(a) * b) >> 30);
+ }
+
+ __inline Int32 fxp_mac32_Q30(const Int32 a, const Int32 b, Int32 L_add)
+ {
+ return (L_add + (Int32)(((int64_t)(a) * b) >> 30));
+ }
+
+
+ __inline Int32 fxp_mul32_Q29(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64_t)(a) * b) >> 29);
+ }
+
+ __inline Int32 fxp_mac32_Q29(const Int32 a, const Int32 b, Int32 L_add)
+ {
+ return (L_add + (Int32)(((int64_t)(a) * b) >> 29));
+ }
+
+ __inline Int32 fxp_msu32_Q29(const Int32 a, const Int32 b, Int32 L_sub)
+ {
+ return (L_sub - (Int32)(((int64_t)(a) * b) >> 29));
+ }
+
+
+ __inline Int32 fxp_mul32_Q28(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64_t)(a) * b) >> 28);
+ }
+
+ __inline Int32 fxp_mul32_Q27(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64_t)(a) * b) >> 27);
+ }
+
+ __inline Int32 fxp_mul32_Q26(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64_t)(a) * b) >> 26);
+ }
+
+ __inline Int32 fxp_mul32_Q20(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64_t)(a) * b) >> 20);
+ }
+
+ __inline Int32 fxp_mul32_Q15(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64_t)(a) * b) >> 15);
+ }
+
+ __inline Int32 fxp_mul32_Q14(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64_t)(a) * b) >> 14);
+ }
+
+
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FXP_MUL32 */
+
diff --git a/media/libstagefright/codecs/aacdec/fxp_mul32_c_msc_evc.h b/media/libstagefright/codecs/aacdec/fxp_mul32_c_msc_evc.h
new file mode 100644
index 0000000..64397cf
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fxp_mul32_c_msc_evc.h
@@ -0,0 +1,254 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: fxp_mul32_msc_evc.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+
+#ifndef FXP_MUL32_MSC_EVC
+#define FXP_MUL32_MSC_EVC
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#include "pv_audio_type_defs.h"
+
+#if defined(PV_ARM_MSC_EVC_V4)
+
+#include "cmnintrin.h"
+
+#define preload_cache( a)
+
+ __inline Int32 shft_lft_1(Int32 L_var1)
+ {
+ if (((L_var1 << 1) >> 1) == L_var1)
+ L_var1 <<= 1;
+ else
+ L_var1 = ((L_var1 >> 31) ^ INT32_MAX);
+
+ return L_var1;
+
+ }
+
+ __inline Int32 fxp_mul_16_by_16bb(Int32 L_var1, Int32 L_var2)
+ {
+ L_var2 = (L_var2 << 16) >> 16;
+ L_var1 = (L_var1 << 16) >> 16;
+
+ return (L_var1*L_var2);
+
+ }
+
+#define fxp_mul_16_by_16(a, b) fxp_mul_16_by_16bb( a, b)
+
+ __inline Int32 fxp_mul_16_by_16tb(Int32 L_var1, Int32 L_var2)
+ {
+ L_var2 = (L_var2 << 16) >> 16;
+ L_var1 = L_var1 >> 16;
+
+ return (L_var1*L_var2);
+
+ }
+
+
+ __inline Int32 fxp_mul_16_by_16bt(Int32 L_var1, Int32 L_var2)
+ {
+ L_var2 = L_var2 >> 16;
+ L_var1 = (L_var1 << 16) >> 16;
+
+ return (L_var1*L_var2);
+
+ }
+
+
+ __inline Int32 fxp_mul_16_by_16tt(Int32 L_var1, Int32 L_var2)
+ {
+ L_var2 = L_var2 >> 16;
+ L_var1 = L_var1 >> 16;
+
+ return (L_var1*L_var2);
+
+ }
+
+ __inline Int32 fxp_mac_16_by_16(Int16 L_var1, Int16 L_var2, Int32 L_add)
+ {
+ return (L_add + (L_var1*L_var2));
+ }
+
+
+
+ __inline Int32 fxp_mac_16_by_16_bb(Int16 L_var1, Int32 L_var2, Int32 L_add)
+ {
+ L_var2 = (L_var2 << 16) >> 16;
+
+ return (L_add + (L_var1*L_var2));
+
+ }
+
+
+ __inline Int32 fxp_mac_16_by_16_bt(Int16 L_var1, Int32 L_var2, Int32 L_add)
+ {
+ L_var2 = L_var2 >> 16;
+
+ return (L_add + (L_var1*L_var2));
+
+ }
+
+
+ __inline Int32 cmplx_mul32_by_16(Int32 x, const Int32 y, Int32 exp_jw)
+ {
+ Int32 rTmp0 = (exp_jw >> 16) << 16;
+ Int32 iTmp0 = exp_jw << 16;
+ Int32 z;
+
+
+ z = _MulHigh(rTmp0, x);
+ z += _MulHigh(iTmp0, y);
+
+ return (z);
+ }
+
+
+ __inline Int32 fxp_mul32_by_16(Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 rTmp0 = L_var2 << 16;
+
+ return(_MulHigh(rTmp0, L_var1));
+ }
+
+#define fxp_mul32_by_16b( a, b) fxp_mul32_by_16( a, b)
+
+
+ __inline Int32 fxp_mul32_by_16t(Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 rTmp0 = (Int16)(L_var2 >> 16);
+
+ return(_MulHigh((rTmp0 << 16), L_var1));
+ }
+
+
+ __inline Int32 fxp_mac32_by_16(const Int32 L_var1, const Int32 L_var2, Int32 L_add)
+ {
+
+ Int32 rTmp0 = (L_var2 << 16);
+
+ return(L_add + _MulHigh(rTmp0, L_var1));
+ }
+
+ __inline int64 fxp_mac64_Q31(int64 sum, const Int32 L_var1, const Int32 L_var2)
+ {
+ sum += (int64)L_var1 * L_var2;
+ return (sum);
+ }
+
+#define fxp_mul32_Q31( a, b) _MulHigh( b, a)
+
+ __inline Int32 fxp_mac32_Q31(Int32 L_add, const Int32 a, const Int32 b)
+ {
+ return (L_add + _MulHigh(b, a));
+ }
+
+ __inline Int32 fxp_msu32_Q31(Int32 L_sub, const Int32 a, const Int32 b)
+ {
+ return (L_sub - _MulHigh(b, a));
+ }
+
+
+ __inline Int32 fxp_mul32_Q30(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 30);
+ }
+
+ __inline Int32 fxp_mac32_Q30(const Int32 a, const Int32 b, Int32 L_add)
+ {
+ return (L_add + (Int32)(((int64)(a) * b) >> 30));
+ }
+
+
+ __inline Int32 fxp_mul32_Q29(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 29);
+ }
+
+ __inline Int32 fxp_mac32_Q29(const Int32 a, const Int32 b, Int32 L_add)
+ {
+ return (L_add + (Int32)(((int64)(a) * b) >> 29));
+ }
+
+ __inline Int32 fxp_msu32_Q29(const Int32 a, const Int32 b, Int32 L_sub)
+ {
+ return (L_sub - (Int32)(((int64)(a) * b) >> 29));
+ }
+
+
+ __inline Int32 fxp_mul32_Q28(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 28);
+ }
+
+ __inline Int32 fxp_mul32_Q27(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 27);
+ }
+
+ __inline Int32 fxp_mul32_Q26(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 26);
+ }
+
+ __inline Int32 fxp_mul32_Q20(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 20);
+ }
+
+ __inline Int32 fxp_mul32_Q15(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 15);
+ }
+
+ __inline Int32 fxp_mul32_Q14(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 14);
+ }
+
+
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FXP_MUL32 */
diff --git a/media/libstagefright/codecs/aacdec/fxp_mul32_c_msc_evc_armv5.h b/media/libstagefright/codecs/aacdec/fxp_mul32_c_msc_evc_armv5.h
new file mode 100644
index 0000000..04cbf49
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fxp_mul32_c_msc_evc_armv5.h
@@ -0,0 +1,178 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: .fxp_mul32_msc_evc_armv5.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef FXP_MUL32_MSC_EVC_ARMV5
+#define FXP_MUL32_MSC_EVC_ARMV5
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#include "pv_audio_type_defs.h"
+
+#if defined(PV_ARM_MSC_EVC_V5)
+
+#include "armintr.h"
+#include "cmnintrin.h"
+
+#define preload_cache( a)
+
+#define shft_lft_1( L_var1) _AddSatInt( L_var1, L_var1)
+
+#define fxp_mul_16_by_16bb( L_var1, L_var2) _SmulLo_SW_SL( L_var1, L_var2)
+
+#define fxp_mul_16_by_16(a, b) fxp_mul_16_by_16bb( a, b)
+
+#define fxp_mul_16_by_16tb( L_var1, L_var2) _SmulHiLo_SW_SL( L_var1, L_var2)
+
+#define fxp_mul_16_by_16bt( L_var1, L_var2) _SmulLoHi_SW_SL( L_var1, L_var2)
+
+#define fxp_mul_16_by_16tt( L_var1, L_var2) _SmulHi_SW_SL( L_var1, L_var2)
+
+#define fxp_mac_16_by_16( L_var1, L_var2, L_add) _SmulAddLo_SW_SL( L_add, L_var1, L_var2)
+
+#define fxp_mac_16_by_16_bb(a, b, c) fxp_mac_16_by_16( a, b, c)
+
+#define fxp_mac_16_by_16_bt( L_var1, L_var2, L_add) _SmulAddLoHi_SW_SL( L_add, L_var1, L_var2)
+
+
+ __inline Int32 cmplx_mul32_by_16(Int32 L_var1, const Int32 L_var2, const Int32 cmplx)
+ {
+ Int32 result64_hi;
+
+ result64_hi = _SmulWHi_SW_SL(L_var1, cmplx);
+ result64_hi = _SmulAddWLo_SW_SL(result64_hi, L_var2, cmplx);
+
+ return (result64_hi);
+ }
+
+#define fxp_mul32_by_16( L_var1, L_var2) _SmulWLo_SW_SL( L_var1, L_var2)
+
+#define fxp_mul32_by_16b( a, b) fxp_mul32_by_16( a, b)
+
+#define fxp_mul32_by_16t( L_var1, L_var2) _SmulWHi_SW_SL( L_var1, L_var2)
+
+#define fxp_mac32_by_16( L_var1, L_var2, L_add) _SmulAddWLo_SW_SL( L_add, L_var1, L_var2)
+
+
+ __inline int64 fxp_mac64_Q31(int64 sum, const Int32 L_var1, const Int32 L_var2)
+ {
+ sum += (int64)L_var1 * L_var2;
+ return (sum);
+ }
+
+#define fxp_mul32_Q31( a, b) _MulHigh( b, a)
+
+
+ __inline Int32 fxp_mac32_Q31(Int32 L_add, const Int32 a, const Int32 b)
+ {
+ return (L_add + _MulHigh(b, a));
+ }
+
+
+ __inline Int32 fxp_msu32_Q31(Int32 L_sub, const Int32 a, const Int32 b)
+ {
+ return (L_sub - _MulHigh(b, a));
+ }
+
+
+ __inline Int32 fxp_mul32_Q30(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 30);
+ }
+
+ __inline Int32 fxp_mac32_Q30(const Int32 a, const Int32 b, Int32 L_add)
+ {
+ return (L_add + (Int32)(((int64)(a) * b) >> 30));
+ }
+
+
+ __inline Int32 fxp_mul32_Q29(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 29);
+ }
+
+ __inline Int32 fxp_mac32_Q29(const Int32 a, const Int32 b, Int32 L_add)
+ {
+ return (L_add + (Int32)(((int64)(a) * b) >> 29));
+ }
+
+ __inline Int32 fxp_msu32_Q29(const Int32 a, const Int32 b, Int32 L_sub)
+ {
+ return (L_sub - (Int32)(((int64)(a) * b) >> 29));
+ }
+
+
+ __inline Int32 fxp_mul32_Q28(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 28);
+ }
+
+ __inline Int32 fxp_mul32_Q27(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 27);
+ }
+
+ __inline Int32 fxp_mul32_Q26(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 26);
+ }
+
+ __inline Int32 fxp_mul32_Q20(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 20);
+ }
+
+ __inline Int32 fxp_mul32_Q15(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 15);
+ }
+
+ __inline Int32 fxp_mul32_Q14(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 14);
+ }
+
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FXP_MUL32 */
+
diff --git a/media/libstagefright/codecs/aacdec/fxp_mul32_pentium.h b/media/libstagefright/codecs/aacdec/fxp_mul32_pentium.h
new file mode 100644
index 0000000..72862e7
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/fxp_mul32_pentium.h
@@ -0,0 +1,55 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: .fxp_mul32_pentium.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef FXP_MUL32_PENTIUM
+#define FXP_MUL32_PENTIUM
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#include "pv_audio_type_defs.h"
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FXP_MUL32 */
+
diff --git a/media/libstagefright/codecs/aacdec/gen_rand_vector.cpp b/media/libstagefright/codecs/aacdec/gen_rand_vector.cpp
new file mode 100644
index 0000000..08ccc4a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/gen_rand_vector.cpp
@@ -0,0 +1,512 @@
+/* ------------------------------------------------------------------
+ * 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
+
+ Description: Modified from original shareware code
+
+ Description: Modified to remove instances of pow() and sqrt(), and
+ optimized for inclusion in fixed-point version of decoder.
+
+ Description: Modified to include comments/optimizations from code review.
+ Also, declared appropriate variables as type "const"
+
+ Description: Adopted strategy of "one q-format per sfb" strategy, which
+ eliminated the array q-format from this function. The q-format the
+ random vector is stored in is now returned from the function.
+
+ Description: Completely redesigned the routine to allow a simplified
+ calculation of the adjusted noise, by eliminating the dependency
+ on the band_length. Added polynomial approximation for the
+ function 1/sqrt(power). Updated comments and pseudo-code
+
+ Description: Modified function description, pseudocode, etc.
+
+ Description:
+ Modified casting to ensure proper operations for different platforms
+
+ Description:
+ Eliminiated access to memory for noise seed. Now a local variable is
+ used. Also unrolled loops to speed up code.
+
+ Description:
+ Modified pointer decrement to a pointer increment, to ensure proper
+ compiler behavior
+
+ Description:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs: random_array[] = Array for storage of the power-scaled
+ random values of length "band_length"
+ Int32
+
+ band_length = Length of random_array[]
+ const Int
+
+ pSeed = seed for random number generator
+ Int32*
+
+ power_scale = scale factor for this particular band
+ const Int
+
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs: Function returns the q-format the random vector is stored in.
+
+ Pointers and Buffers Modified:
+ random_array[] = filled with random numbers scaled
+ to the correct power as defined by the input value power_scale.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function generates a vector of uniformly distributed random numbers for
+ the PNS block. The random numbers are each scaled by a scale_factor,
+ defined in Ref(2) as
+
+ 2^(scale_factor/4)
+ ------------------
+ sqrt(N*MEAN_NRG)
+
+ where N == band_length, and MEAN_NRG is defined as...
+
+ N-1
+ ___
+ 1 \
+ --- > x(i)^2
+ N /__
+ i=0
+
+ And x is the unscaled vector from the random number generator.
+
+ This function takes advantage of the fact that the portion of the
+ scale_factor that is divisible by 4 can be simply accounted for by varying
+ the q-format.
+
+ The scaling of the random numbers is thus broken into the
+ equivalent equation below.
+
+ 2^(scale_factor%4) 2^(floor(scale_factor/4))
+ ------------------ *
+ sqrt(N*MEAN_NRG)
+
+
+ 2^(scale_factor%4) is stored in a simple 4-element table.
+ 2^(floor(scale_factor/4) is accounted for by adjusting the q-format.
+ sqrt(N*MEAN_NRG) is calculated and implemented via a polynomial approximation.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function shall produce uniformly distributed random 32-bit integers,
+ with signed random values of average energy equal to the results of the ISO
+ code's multiplying factor discussed in the FUNCTION DESCRIPTION section.
+
+ Please see Ref (2) for a detailed description of the requirements.
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) Numerical Recipes in C Second Edition
+ William H. Press Saul A. Teukolsky
+ William T. Vetterling Brian P. Flannery
+ Page 284
+
+ (2) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.6.12 (Perceptual Noise Substitution)
+
+ (3) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ power_adj = scale_mod_4[power_scale & 3];
+
+ power = 0;
+
+ FOR (k=band_length; k > 0; k--)
+
+ *(pSeed) = *(pSeed) * 1664525L;
+ *(pSeed) = *(pSeed) + 1013904223L;
+
+ temp = (Int)(*(pSeed) >> 16);
+
+ power = power + ((temp*temp) >> 6);
+
+ *(pArray) = (Int32)temp;
+
+ pArray = pArray + 1;
+
+ ENDFOR
+
+ k = 0;
+ q_adjust = 30;
+
+ IF (power)
+ THEN
+
+ WHILE ( power > 32767)
+
+ power = power >> 1;
+ k = k + 1;
+
+ ENDWHILE
+
+ k = k - 13;
+
+ IF (k < 0)
+ THEN
+ k = -k;
+ IF ( k & 1 )
+ THEN
+ power_adj = (power_adj*SQRT_OF_2)>>14;
+ ENDIF
+ q_adjust = q_adjust - ( k >> 1);
+
+ ELSE IF (k > 0)
+ THEN
+ IF ( k & 1 )
+ THEN
+ power_adj = (power_adj*INV_SQRT_OF_2)>>14;
+ ENDIF
+ q_adjust = q_adjust + ( k >> 1);
+ ENDIF
+
+ pInvSqrtCoeff = inv_sqrt_coeff;
+
+ inv_sqrt_power = (*(pInvSqrtCoeff)* power) >>15;
+
+ pInvSqrtCoeff = pInvSqrtCoeff + 1;
+
+ inv_sqrt_power = inv_sqrt_power + *(pInvSqrtCoeff);
+
+ pInvSqrtCoeff = pInvSqrtCoeff + 1;
+
+ FOR ( k=INV_SQRT_POLY_ORDER - 1; k>0; k--)
+
+ inv_sqrt_power = ( inv_sqrt_power * power)>>15;
+
+ inv_sqrt_power = inv_sqrt_power + *(pInvSqrtCoeff);
+
+ pInvSqrtCoeff = pInvSqrtCoeff + 1;
+
+ ENDFOR
+
+ inv_sqrt_power = (inv_sqrt_power*power_adj)>>13;
+
+ FOR (k=band_length; k > 0; k--)
+
+ pArray = pArray - 1;
+
+ *(pArray) = *(pArray)*inv_sqrt_power;
+
+ ENDFOR
+
+ ENDIF
+
+ q_adjust = q_adjust - (power_scale >> 2);
+
+ return q_adjust;
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "gen_rand_vector.h"
+#include "window_block_fxp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define SQRT_OF_2 23170 /* sqrt(2) in Q14 */
+#define INV_SQRT_OF_2 11585 /* 1/sqrt(2) in Q14 */
+#define INV_SQRT_POLY_ORDER 4
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+
+/*
+ * 2^([0:3]/4) = 1.0000 1.1892 1.4142 1.6818
+ */
+const UInt scale_mod_4[4] = { 16384, 19484, 23170, 27554};
+
+/*
+ * polynomial approx. in Q12 (type Int)
+ */
+
+const Int inv_sqrt_coeff[INV_SQRT_POLY_ORDER+1] =
+ { 4680, -17935, 27697, -22326, 11980};
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int gen_rand_vector(
+ Int32 random_array[],
+ const Int band_length,
+ Int32* pSeed,
+ const Int power_scale)
+{
+
+ Int k;
+ UInt power_adj;
+ Int q_adjust = 30;
+
+ Int32 temp;
+ Int32 seed;
+ Int32 power;
+
+ Int32* pArray = &random_array[0];
+
+ Int32 inv_sqrt_power;
+ const Int *pInvSqrtCoeff;
+
+ /*
+ * The out of the random number generator is scaled is such a way
+ * that is independent of the band length.
+ * The output is computed as:
+ *
+ * x(i)
+ * output = ------------------ * 2^(power_scale%4) 2^(floor(power_scale/4))
+ * bl
+ * sqrt( SUM x(i)^2 )
+ * 0
+ *
+ * bl == band length
+ */
+
+
+ /*
+ * get 2^(power_scale%4)
+ */
+
+
+ power = 0;
+
+ seed = *pSeed;
+
+ /*
+ * band_length is always an even number (check tables in pg.66 IS0 14496-3)
+ */
+ if (band_length < 0 || band_length > LONG_WINDOW)
+ {
+ return q_adjust; /* avoid any processing on error condition */
+ }
+
+ for (k = (band_length >> 1); k != 0; k--)
+ {
+ /*------------------------------------------------
+ Numerical Recipes in C
+ Page 284
+ ------------------------------------------------*/
+ seed *= 1664525L;
+ seed += 1013904223L;
+
+ temp = seed >> 16;
+
+ seed *= 1664525L;
+ seed += 1013904223L;
+
+ /* shift by 6 make room for band length accumulation */
+ power += ((temp * temp) >> 6);
+ *pArray++ = temp;
+
+ temp = seed >> 16;
+ power += ((temp * temp) >> 6);
+ *pArray++ = temp;
+
+ } /* END for (k=half_band_length; k > 0; k--) */
+
+
+ *pSeed = seed;
+
+ /*
+ * If the distribution is uniform, the power is expected to use between
+ * 28 and 27 bits, by shifting down by 13 bits the power will be a
+ * Q15 number.
+ * For different band lengths, the power uses between 20 and 29 bits
+ */
+
+
+ k = 0;
+
+ if (power)
+ {
+ /*
+ * approximation requires power between 0.5 < power < 1 in Q15.
+ */
+
+ while (power > 32767)
+ {
+ power >>= 1;
+ k++;
+ }
+
+ /*
+ * expected power bit usage == 27 bits
+ */
+
+ k -= 13;
+
+ power_adj = scale_mod_4[power_scale & 3];
+
+ if (k < 0)
+ {
+ k = -k;
+ if (k & 1)
+ { /* multiply by sqrt(2) */
+ power_adj = (UInt)(((UInt32) power_adj * SQRT_OF_2) >> 14);
+ }
+ q_adjust -= (k >> 1); /* adjust Q instead of shifting up */
+ }
+ else if (k > 0)
+ {
+ if (k & 1)
+ { /* multiply by 1/sqrt(2) */
+ power_adj = (UInt)(((UInt32) power_adj * INV_SQRT_OF_2) >> 14);
+ }
+ q_adjust += (k >> 1); /* adjust Q instead of shifting down */
+ }
+
+ /*
+ * Compute 1/sqrt(power), where 0.5 < power < 1.0 is approximated
+ * using a polynomial order INV_SQRT_POLY_ORDER
+ */
+
+ pInvSqrtCoeff = inv_sqrt_coeff;
+
+ inv_sqrt_power = (*(pInvSqrtCoeff++) * power) >> 15;
+ inv_sqrt_power += *(pInvSqrtCoeff++);
+ inv_sqrt_power = (inv_sqrt_power * power) >> 15;
+ inv_sqrt_power += *(pInvSqrtCoeff++);
+ inv_sqrt_power = (inv_sqrt_power * power) >> 15;
+ inv_sqrt_power += *(pInvSqrtCoeff++);
+ inv_sqrt_power = (inv_sqrt_power * power) >> 15;
+ inv_sqrt_power += *(pInvSqrtCoeff);
+
+ inv_sqrt_power = (inv_sqrt_power * power_adj) >> 13;
+
+ pArray = &random_array[0];
+
+ for (k = (band_length >> 1); k != 0; k--)
+ {
+ temp = *(pArray) * inv_sqrt_power;
+ *(pArray++) = temp;
+ temp = *(pArray) * inv_sqrt_power;
+ *(pArray++) = temp;
+ } /* END for (k=half_band_length; k > 0; k--) */
+
+ } /* if(power) */
+
+ /*
+ * Adjust Q with the value corresponding to 2^(floor(power_scale/4))
+ */
+
+ q_adjust -= (power_scale >> 2);
+
+ return (q_adjust);
+
+} /* gen_rand_vector */
diff --git a/media/libstagefright/codecs/aacdec/gen_rand_vector.h b/media/libstagefright/codecs/aacdec/gen_rand_vector.h
new file mode 100644
index 0000000..17b5490
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/gen_rand_vector.h
@@ -0,0 +1,87 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: gen_rand_vector.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added include of pv_audio_type_defs.h
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file contains the function declaration for gen_rand_vector.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef gen_rand_vector_H
+#define gen_rand_vector_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+Int gen_rand_vector(
+ Int32 random_array[],
+ const Int band_length,
+ Int32 *pSeed,
+ const Int power_scale);
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/get_adif_header.cpp b/media/libstagefright/codecs/aacdec/get_adif_header.cpp
new file mode 100644
index 0000000..8a1e74b
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_adif_header.cpp
@@ -0,0 +1,443 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_adif_header.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: Change to PV template, remove default config parameter,
+ move some functionality into get_prog_config().
+
+ Description: Update per code review
+ 1) Add parameter pScratchPCE
+ 2) Change way ADIF_ID is read in.
+ 3) Fix comments
+ 4) ADD a test for status != SUCCESS in loop.
+
+ Description: The ADIF_Header has now been delegated to the "scratch memory"
+ union. This change inside s_tDec_Int_File.h had to be reflected here also.
+
+ Description: Updated the SW template to include the full pathname to the
+ source file and a slightly modified copyright header.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pVars = pointer to the structure that contains the current state
+ of this instance of the library, of data type pointer to
+ tDec_Int_File
+
+ pScratchPCE = pointer to a ProgConfig structure used as scratch in the
+ the function get_prog_config. of data type pointer to
+ ProgConfig
+
+ Local Stores/Buffers/Pointers Needed: None
+
+ Global Stores/Buffers/Pointers Needed: None
+
+ Outputs:
+ The function returns 0 if no error occurred, non-zero otherwise.
+
+ Pointers and Buffers Modified:
+ pVars->adif_header contents are updated with the some of the ADIF header
+ contents
+ pVars->tempProgConfig contents are overwritten with last PCE found,
+ which is most likely the first one found.
+ pVars->prog_config contents are updated with the first PCE found.
+ pVars->inputStream contents are modify in such a way that the
+ stream is moved further along in the buffer.
+ pVars->SFBWidth128 contents may be updated.
+ pVars->winSeqInfo contents may be updated.
+ pScratchPCE contents may be updated.
+
+ Local Stores Modified: None
+
+ Global Stores Modified: None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function reads in the ADIF Header found at the front of ADIF streams.
+ If the header is not found an error is returned. An ADIF header can contain
+ from zero to sixteen program configuration elements (PCE). This function, and
+ the rest of the library, saves and uses the first PCE found.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ Function shall not use static or global variables.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 13818-7:1997 Titled "Information technology - Generic coding
+ of moving pictures and associated audio information - Part 7: Advanced
+ Audio Coding (AAC)", Table 6.21 - Syntax of program_config_element(),
+ page 16, and section 8.5 "Program Config Element (PCE)", page 30.
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ CALL getbits(
+ neededBits = 2 * LEN_BYTE,
+ pInputStream = pInputStream)
+ MODIFYING( pInputStream )
+ RETURNING( theIDFromFile )
+
+ CALL getbits(
+ neededBits = 2 * LEN_BYTE,
+ pInputStream = pInputStream)
+ MODIFYING( pInputStream )
+ RETURNING( temp )
+
+ theIDFromFile = (theIDFromFile << (2*LEN_BYTE)) | temp;
+
+ IF (theIDFromFile != ADIF_ID)
+ THEN
+
+ pInputStream->usedBits -= (4 * LEN_BYTE);
+
+ status = -1;
+ ELSE
+ CALL getbits(
+ neededBits = LEN_COPYRT_PRES,
+ pInputStream = pInputStream)
+ MODIFYING( pInputStream )
+ RETURNING( temp )
+
+ IF (temp != FALSE) THEN
+ FOR (i = LEN_COPYRT_ID; i > 0; i--)
+ CALL getbits(
+ neededBits = LEN_BYTE,
+ pInputStream = pInputStream)
+ MODIFYING( pInputStream )
+
+ END FOR
+ END IF
+
+ CALL getbits(
+ neededBits = LEN_ORIG + LEN_HOME,
+ pInputStream = pInputStream)
+ MODIFYING( pInputStream )
+
+ CALL getbits(
+ neededBits = LEN_BS_TYPE,
+ pInputStream = pInputStream)
+ MODIFYING( pInputStream )
+ RETURNING( bitStreamType )
+
+ CALL getbits(
+ neededBits = LEN_BIT_RATE,
+ pInputStream = pInputStream)
+ MODIFYING( pInputStream )
+ RETURNING( pHeader->bitrate )
+
+ CALL getbits(
+ neededBits = LEN_NUM_PCE,
+ pInputStream = pInputStream)
+ MODIFYING( pInputStream )
+ RETURNING( numConfigElementsMinus1 )
+
+ FOR ( i = numConfigElementsMinus1;
+ (i >= 0) && (status == SUCCESS);
+ i--)
+
+ IF (bitStreamType == CONSTANT_RATE_BITSTREAM) THEN
+ CALL getbits(
+ neededBits = LEN_ADIF_BF,
+ pInputStream = pInputStream)
+ MODIFYING( pInputStream )
+ END IF
+
+ CALL get_prog_config(
+ pVars = pVars)
+ MODIFYING( pVars->prog_config )
+ RETURNING( status )
+
+ END FOR
+ END IF
+
+ RETURN (status)
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_adif_const.h"
+
+#include "s_progconfig.h"
+#include "s_adif_header.h"
+#include "s_bits.h"
+#include "s_mc_info.h"
+#include "s_frameinfo.h"
+#include "s_tdec_int_file.h"
+
+#include "get_prog_config.h"
+#include "ibstream.h"
+
+#include "get_adif_header.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*
+ * This constant is simply the characters 'A' 'D' 'I' 'F' compressed into
+ * a UInt32. Any possible endian problems that exist must be solved by
+ * the function that fills the buffer and getbits(), or this constant and
+ * the rest of the bit stream will not work.
+ */
+#define ADIF_ID (0x41444946)
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+Int get_adif_header(
+ tDec_Int_File *pVars,
+ ProgConfig *pScratchPCE)
+{
+ Int i;
+ UInt32 temp;
+ Int numConfigElementsMinus1;
+ Int bitStreamType;
+ UInt32 theIDFromFile;
+
+ BITS *pInputStream = &pVars->inputStream;
+ ADIF_Header *pHeader = &pVars->scratch.adif_header;
+ Int status = SUCCESS;
+
+ /*
+ * The ADIF_ID field is 32 bits long, one more than what getbits() can
+ * do, so read the field in two parts. There is no point in saving the
+ * string - it either matches or it does not. If it matches, it must
+ * have been 'ADIF'
+ */
+
+ theIDFromFile = get17_n_lessbits((2 * LEN_BYTE), pInputStream);
+
+ temp = get17_n_lessbits((2 * LEN_BYTE), pInputStream);
+
+ theIDFromFile = (theIDFromFile << (2 * LEN_BYTE)) | temp;
+
+
+ if (theIDFromFile != ADIF_ID)
+ {
+ /*
+ * Rewind the bit stream pointer so a search for ADTS header
+ * can start at the beginning.
+ */
+
+ pInputStream->usedBits -= (4 * LEN_BYTE);
+
+ /*
+ * The constant in the next line needs to be updated when
+ * error handling method is determined.
+ */
+ status = -1;
+ }
+ else
+ {
+ /*
+ * To save space, the unused fields are read in, but not saved.
+ */
+
+ /* copyright string */
+ temp =
+ get1bits(/* LEN_COPYRT_PRES,*/
+ pInputStream);
+
+ if (temp != FALSE)
+ {
+ /*
+ * Read in and ignore the copyright string. If restoring
+ * watch out for count down loop.
+ */
+
+ for (i = LEN_COPYRT_ID; i > 0; i--)
+ {
+ get9_n_lessbits(LEN_BYTE,
+ pInputStream);
+ } /* end for */
+
+ /*
+ * Make sure to terminate the string with '\0' if restoring
+ * the the copyright string.
+ */
+
+ } /* end if */
+
+ /* Combine the original/copy and fields into one call */
+ get9_n_lessbits(
+ LEN_ORIG + LEN_HOME,
+ pInputStream);
+
+ bitStreamType =
+ get1bits(/* LEN_BS_TYPE,*/
+ pInputStream);
+
+ pHeader->bitrate =
+ getbits(
+ LEN_BIT_RATE,
+ pInputStream);
+
+ /*
+ * Read in all the Program Configuration Elements.
+ * For this library, only one of the up to 16 possible PCE's will be
+ * saved. Since each PCE must be read, a temporary PCE structure is
+ * used, and if that PCE is the one to use, it is copied into the
+ * single PCE. This is done inside of get_prog_config()
+ */
+
+ numConfigElementsMinus1 = get9_n_lessbits(LEN_NUM_PCE,
+ pInputStream);
+
+ for (i = numConfigElementsMinus1;
+ (i >= 0) && (status == SUCCESS);
+ i--)
+ {
+ /*
+ * For ADIF contant bit rate streams, the _encoder_ buffer
+ * fullness is transmitted. This version of an AAC decoder has
+ * no use for this variable; yet it must be read in to move
+ * the bitstream pointers.
+ */
+
+ if (bitStreamType == CONSTANT_RATE_BITSTREAM)
+ {
+ getbits(
+ LEN_ADIF_BF,
+ pInputStream);
+ } /* end if */
+
+ pVars->adif_test = 1;
+ /* Get one program configuration element */
+ status =
+ get_prog_config(
+ pVars,
+ pScratchPCE);
+
+#ifdef AAC_PLUS
+
+ /*
+ * For implicit signalling, no hint that sbr or ps is used, so we need to
+ * check the sampling frequency of the aac content, if lesser or equal to
+ * 24 KHz, by defualt upsample, otherwise, do nothing
+ */
+ if ((pVars->prog_config.sampling_rate_idx >= 6) && (pVars->aacPlusEnabled == true) &&
+ pVars->mc_info.audioObjectType == MP4AUDIO_AAC_LC)
+ {
+ pVars->mc_info.upsamplingFactor = 2;
+ pVars->prog_config.sampling_rate_idx -= 3;
+ pVars->mc_info.sbrPresentFlag = 1;
+ pVars->sbrDecoderData.SbrChannel[0].syncState = UPSAMPLING;
+ pVars->sbrDecoderData.SbrChannel[1].syncState = UPSAMPLING;
+ }
+#endif
+
+
+
+ } /* end for */
+
+
+ } /* end 'else' of --> if (theIDFromFile != ADIF_ID) */
+
+ return status;
+
+} /* end get_adif_header */
diff --git a/media/libstagefright/codecs/aacdec/get_adif_header.h b/media/libstagefright/codecs/aacdec/get_adif_header.h
new file mode 100644
index 0000000..8bc3411
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_adif_header.h
@@ -0,0 +1,95 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_adif_header.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Add parameter to get_adif_header() function.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for get_adif_header.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_ADIF_HEADER_H
+#define GET_ADIF_HEADER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_tdec_int_file.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define CONSTANT_RATE_BITSTREAM (0)
+#define VARIABLE_RATE_BITSTREAM (1)
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+Int get_adif_header(
+ tDec_Int_File *pVars,
+ ProgConfig *pScratchPCE);
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/get_adts_header.cpp b/media/libstagefright/codecs/aacdec/get_adts_header.cpp
new file mode 100644
index 0000000..3ac2756
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_adts_header.cpp
@@ -0,0 +1,672 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_adts_header.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Remove default_config variable
+
+ Description: change enter_mc_info to set_mc_info
+
+ Description: (1) add error checking for channel_config > 2
+ (2) eliminated call to check_mc_info
+ (3) use (profile + 1) when calling set_mc_info
+ (4) use winmap when calling set_mc_info
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pVars = Pointer to structure that holds file-scope variables.
+ [ tDec_Int_File * ]
+
+ pSyncword = Pointer to variable that holds the 28-bit fixed
+ header upon the exit of this function. [ UInt32 * ]
+
+ pInvoke = Pointer to variable that keeps track of how many
+ "short" (14 bit) headers have been successfully
+ parsed from the bitstream. [ Int * ]
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ Status = SUCCESS or ERROR CODE
+
+ Pointers and Buffers Modified:
+ pVars->prog_config Updated with program information data as read from
+ the ADTS header.
+
+ pSyncword Value pointed to is updated with the contents of
+ the 28-bit fixed header.
+
+ pInvoke Value pointed to is updated to reflect the number
+ of successful "short" (14 bit) headers that have
+ been successfully parsed from the bitstream.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Acronym Definitions
+ ADTS Audio Data Transport Stream
+ CRC Cyclic Redundancy Code
+
+ This function calls find_adts_syncword to find the next ADTS header. Until
+ three consistent headers have been read, the syncword used for detection
+ consists of the 12-bit syncword and the 2-bit Layer. After three consistent
+ headers are read, the entire fixed header is used for a robust 28-bit
+ syncword.
+
+ Configuration information is then extracted from the bitstream.
+
+ The bitstream information is packed as follows.
+ Comments about the correct interpretation of these bits are contained within
+ the code.
+
+ CRC_absent sampling_rate_idx
+ \ / \
+ \ / \
+ \ Profile / \ UNUSED
+ \ / \ / \ /
+|00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|
+ \ _______________ / | \ / \ /
+ \-------|0xFFF syncword |-------/ | Layer == '00' for AAC \ /
+ \-------------/ | \ /
+ | \/
+ ID == '1' for MPEG-2 AAC channel_config
+ copyright_id_bit == '0' for MPEG-4 AAC
+ /
+ home /
+ / /
+|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|
+ | \ \ _____________ /
+ | \ \--------|frame length |---------/
+ orig_copy \ \-----------/
+ \ ______________________________
+ copyright_id_start | TOTAL HEADER LENGTH: 56 bits|
+ |-----------------------------|
+|43|44|45|46|47|48|49|50|51|52|53|54|55| | FIXED HEADER BITS 00-27 |
+ \ _______________ / | | | VARIABLE HEADER BITS 28-55 |
+ \-----|buffer_fullness|----/ \ / |_____________________________|
+ \-------------/ |
+ headerless_frames
+
+ In addition to the bits displayed above, if the value CRC_absent is '0' an
+ additional 16 bits corresponding to a CRC word are read from the bitstream,
+ following the header.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ After the ADTS syncword is detected, this function shall parse the
+ information residing behind the syncword in the bitstream.
+------------------------------------------------------------------------------
+ REFERENCES
+ (1) ISO/IEC 13818-7:1997(E)
+ Part 7
+ Subpart 6.2 (Audio_Data_Transport_Stream frame, ADTS)
+
+ (2) ISO/IEC 11172-3:1993(E)
+ Part 3
+ Subpart 2.4.3 The audio decoding process
+
+ (3) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those UIntending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ IF (*(pInvoke) > 3)
+
+ CALL find_adts_syncword(
+ pSyncword,
+ &(pVars->inputStream),
+ LENGTH_FIXED_HEADER,
+ MASK_28BITS);
+ RETURNING status
+ ELSE
+
+ *(pSyncword) = SYNCWORD_15BITS;
+
+ CALL find_adts_syncword(
+ pSyncword,
+ &(pVars->inputStream),
+ LENGTH_SYNCWORD,
+ ID_BIT_FILTER);
+
+ MODIFYING *(pSyncword) = 28-bit fixed header (long syncword)
+ RETURNING status
+
+ CALL getbits(
+ (LENGTH_FIXED_HEADER - LENGTH_SYNCWORD),
+ &(pVars->inputStream));
+
+ MODIFYING pVars->inputStream
+ RETURNING adts_header = remaining bits in the fixed header
+
+ *(pSyncword) <<= 13;
+ *(pSyncword) = *(pSyncword) OR adts_header;
+
+ pVars->prog_config.CRC_absent = ((UInt)(adts_header >> 12)) AND 0x0001;
+
+ lower_16 = (UInt)adts_header;
+
+ pVars->prog_config.profile = (lower_16 >> 10) AND 0x3;
+
+ pVars->prog_config.sampling_rate_idx = (lower_16 >> 6) AND 0xF;
+
+ channel_configuration = (lower_16 >> 2) AND 0x7;
+
+ channel_configuration = channel_configuration - 1;
+ pVars->prog_config.front.ele_is_cpe[0] = channel_configuration;
+
+ pVars->prog_config.front.num_ele = 1;
+
+ pVars->prog_config.front.ele_tag[0] = 0;
+
+ pVars->prog_config.mono_mix.present = 0;
+ pVars->prog_config.stereo_mix.present = 0;
+ pVars->prog_config.matrix_mix.present = 0;
+
+ CALL set_mc_info(
+ &(pVars->mc_info),
+ &(pVars->savedMCInfo),
+ &(pVars->prog_config),
+ pVars->pWinSeqInfo,
+ pVars->SFBWidth128);
+ MODIFYING pVars->mc_info = multi-channel configuration information
+ RETURNING status = SUCCESS/FAILURE
+
+ IF ( (*pInvoke) != 0)
+ CALL check_mc_info(
+ &(pVars->mc_info),
+ &(pVars->savedMCInfo),
+ FALSE);
+ RETURNING status = SUCCESS/FAILURE
+ ELSE
+ CALL check_mc_info(
+ &(pVars->mc_info),
+ &(pVars->savedMCInfo),
+ TRUE);
+ MODIFYING pVars->savedMCInfo = pVars->mc_info
+ RETURNING status = SUCCESS/FAILURE
+ ENDIF
+
+ IF (status == SUCCESS)
+ (*pInvoke) = (*pInvoke) + 1;
+ ELSE
+ (*pInvoke) = 0;
+ ENDIF
+
+ ENDIF
+
+ CALL getbits(
+ LENGTH_VARIABLE_HEADER,
+ &(pVars->inputStream));
+ RETURNING adts_header = 28-bits (the contents of the variable header.)
+
+ pVars->prog_config.frame_length = ((UInt)(adts_header >> 13)) AND 0x1FFF;
+
+ lower_16 = (UInt)adts_header;
+
+ pVars->prog_config.buffer_fullness = (lower_16 >> 2) AND 0x7FF;
+
+ pVars->prog_config.headerless_frames = (lower_16 AND 0x0003);
+
+ IF (pVars->prog_config.CRC_absent == 0)
+
+ CALL getbits(
+ LENGTH_CRC,
+ &(pVars->inputStream) );
+ RETURNING pVars->prog_config.CRC_check = 16-bit CRC
+
+ ENDIF
+
+ pVars->default_config = 0;
+
+ IF (byte_align_offset > 7)
+ status = 1;
+ ENDIF
+
+ return (status);
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bits.h"
+#include "s_tdec_int_file.h"
+#include "ibstream.h"
+#include "set_mc_info.h"
+#include "find_adts_syncword.h"
+#include "get_adts_header.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define LENGTH_VARIABLE_HEADER 28
+#define LENGTH_FIXED_HEADER 28
+#define LENGTH_SYNCWORD 15
+#define LENGTH_CRC 16
+
+#define ID_BIT_FILTER 0x7FFB
+#define SYNCWORD_15BITS 0x7FF8
+#define MASK_28BITS 0x0FFFFFFFL
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Int get_adts_header(
+ tDec_Int_File *pVars,
+ UInt32 *pSyncword,
+ Int *pInvoke,
+ Int CorrectlyReadFramesCount)
+{
+ UInt32 adts_header;
+ UInt lower_16;
+ Int status = SUCCESS;
+ UInt channel_configuration;
+
+ /*
+ * Search for the LONG ADTS syncword (comprised of the entire fixed header)
+ * if the number of CorrectlyReadFrames is > CorrectlyReadFramesCount
+ *
+ * Otherwise, search for just the short syncword.
+ */
+ if (*(pInvoke) > CorrectlyReadFramesCount)
+ {
+ /*
+ * Find the long ADTS syncword
+ * (comprised of the entire ADTS fixed header)
+ */
+
+ status = find_adts_syncword(pSyncword,
+ &(pVars->inputStream),
+ LENGTH_FIXED_HEADER,
+ MASK_28BITS);
+ }
+ else
+ {
+
+ *(pSyncword) = SYNCWORD_15BITS;
+
+ status = find_adts_syncword(pSyncword,
+ &(pVars->inputStream),
+ LENGTH_SYNCWORD,
+ ID_BIT_FILTER);
+
+ /*
+ * Extract the data from the header following the syncword
+ */
+ adts_header = getbits((LENGTH_FIXED_HEADER - LENGTH_SYNCWORD),
+ &(pVars->inputStream));
+
+ *(pSyncword) <<= (LENGTH_FIXED_HEADER - LENGTH_SYNCWORD);
+ *(pSyncword) |= adts_header;
+
+ /* Denotes whether a CRC check should be performed */
+ pVars->prog_config.CRC_absent = ((UInt)(adts_header >> 12)) & 0x0001;
+
+ /*
+ * All the unread bits in adts_header reside in the lower
+ * 16-bits at this point. Perform a typecast for faster
+ * execution on 16-bit processors.
+ */
+ lower_16 = (UInt)adts_header;
+
+ /*
+ * Profile consists of 2 bits, which indicate
+ * the profile used.
+ *
+ * '00' AAC_MAIN profile
+ * '01' AAC_LC (Low Complexity) profile
+ * '10' AAC_SSR (Scaleable Sampling Rate) profile
+ * '11' AAC_LTP (Long Term Prediction) profile
+ */
+ pVars->prog_config.profile = (lower_16 >> 10) & 0x3;
+
+ if (pVars->prog_config.profile == MP4AUDIO_AAC_SSR)
+ {
+ status = 1; /* Not supported */
+ }
+
+ /*
+ * Sampling_rate_idx consists of 4 bits
+ * see Ref #1 for their interpretation.
+ */
+ pVars->prog_config.sampling_rate_idx = (lower_16 >> 6) & 0xF;
+
+ /*
+ * private_bit is a bit for private use. ISO/IEC will not make
+ * use of this bit in the future.
+ *
+ * We currently make no use of it, but parsing the information
+ * from the bitstream could be easily implemented with the
+ * following instruction...
+ *
+ * private_bit = (lower_16 & 0x0400) >> 10;
+ */
+
+ /*
+ * These 3 bits indicate the channel configuration used.
+ *
+ * If '0' then the channel configuration is unspecified here,
+ * and must be given by a program configuration element in
+ * the raw data block.
+ *
+ * If '1' then the channel configuration is MONO.
+ * If '2' then the channel configuration is STEREO
+ *
+ * 3-7 represent channel configurations which this library
+ * will not support in the forseeable future.
+ */
+ channel_configuration = (lower_16 >> 2) & 0x7;
+ /* do not support more than 2 channels */
+ if (channel_configuration > 2)
+ {
+ status = 1;
+ }
+
+ /*
+ * The following 2 bits encode copyright information.
+ * original_copy is '0' if there is no copyright in the bitstream.
+ * '1' if the bitstream is copyright protected.
+ *
+ * home is '0' for a copy, '1' for an original.
+ *
+ * PacketVideo currently does nothing with this information,
+ * however, parsing the data from the bitstream could be easily
+ * implemented with the following instructions...
+ *
+ * original_copy = (lower_16 >> 1) & 0x1;
+ *
+ * home = (lower_16 & 0x1);
+ *
+ */
+
+ /* Set up based on information extracted from the ADTS FIXED header */
+
+ /* This equals 1 for STEREO, 0 for MONO */
+ if (channel_configuration)
+ {
+ channel_configuration--;
+ }
+ pVars->prog_config.front.ele_is_cpe[0] = channel_configuration;
+
+ /* This value is constant for both MONO and STEREO */
+ pVars->prog_config.front.num_ele = 1;
+
+ /* ADTS does not specify this tag value - do we even use it? */
+ pVars->prog_config.front.ele_tag[0] = 0;
+
+ /* Disable all mix related variables */
+ pVars->prog_config.mono_mix.present = 0;
+ pVars->prog_config.stereo_mix.present = 0;
+ pVars->prog_config.matrix_mix.present = 0;
+
+ /* enter configuration into MC_Info structure */
+ if (status == SUCCESS)
+ {
+ /* profile + 1 == audioObjectType */
+ status =
+ set_mc_info(
+ &(pVars->mc_info),
+ (tMP4AudioObjectType)(pVars->prog_config.profile + 1),
+ pVars->prog_config.sampling_rate_idx,
+ pVars->prog_config.front.ele_tag[0],
+ pVars->prog_config.front.ele_is_cpe[0],
+ pVars->winmap, /* changed from pVars->pWinSeqInfo, */
+ pVars->SFBWidth128);
+
+ } /* if (status == SUCCESS) */
+
+
+#ifdef AAC_PLUS
+
+ /*
+ * For implicit signalling, no hint that sbr or ps is used, so we need to
+ * check the sampling frequency of the aac content, if lesser or equal to
+ * 24 KHz, by defualt upsample, otherwise, do nothing
+ */
+ if ((pVars->prog_config.sampling_rate_idx >= 6) && (pVars->aacPlusEnabled == TRUE))
+ {
+ pVars->mc_info.upsamplingFactor = 2;
+ pVars->prog_config.sampling_rate_idx -= 3;
+ pVars->mc_info.sbrPresentFlag = 1;
+ pVars->sbrDecoderData.SbrChannel[0].syncState = SBR_ACTIVE;
+ pVars->sbrDecoderData.SbrChannel[1].syncState = SBR_ACTIVE;
+ }
+#endif
+
+
+ /*
+ * The tag and is_cpe will be checked in huffdecode,
+ * remove this check routine.
+ */
+ /*if (status == SUCCESS)
+ *{
+ * if ( (*pInvoke) != 0)
+ * {
+ * status =
+ * check_mc_info(
+ * &(pVars->mc_info),
+ * &(pVars->savedMCInfo),
+ * FALSE);
+ * }
+ * else
+ * {
+ * status =
+ * check_mc_info(
+ * &(pVars->mc_info),
+ * &(pVars->savedMCInfo),
+ * TRUE);
+ * }
+ *
+ *}*/ /* if (status == SUCCESS) */
+
+ /*
+ * This keeps track of how many headers have been read in the file.
+ * After the three successful headers with the same configuration
+ * are read in, the entire ADTS fixed header is used as the syncword
+ * for a more robust 28-bit long syncword
+ */
+
+ if (status == SUCCESS)
+ {
+ (*pInvoke)++;
+ }
+ else
+ {
+ (*pInvoke) = 0;
+ }
+
+ } /* END if (*(pInvoke) > 3) */
+
+ /* Grab the bits in the ADTS variable header */
+ adts_header = getbits(
+ LENGTH_VARIABLE_HEADER,
+ &(pVars->inputStream));
+ /*
+ * copyright_identification bit is a single bit of the 72-bit
+ * copyright_id field. This consists of a 8-bit copyright identifier
+ * and a 64-bit copyright_number. 72 headers must be decoded
+ * to reconstruct the entire copyright_id field.
+ *
+ * copyright_identification_start is a single bit flagging
+ * the beginning bit of the copyright_id field. '1' for start of
+ * copyright_id, '0' otherwise.
+ *
+ *
+ * PacketVideo currently does nothing with this information,
+ * however, parsing the data from the bitstream could be easily
+ * implemented with the following instructions...
+ *
+ * copyright_id_bit = ((UInt)(adts_header >> 27)) & 0x1;
+ *
+ * copyright_id_start = ((UInt)(adts_header >> 26)) & 0x1;
+ */
+
+ /*
+ * frame_length is a 13-bit field which indicates the length,
+ * in bytes, of the frame including error_check and headers.
+ * This information can theoretically be used to help verify syncwords.
+ */
+ pVars->prog_config.frame_length = ((UInt)(adts_header >> 13)) & 0x1FFF;
+
+ /*
+ * All the unread bits in adts_header reside in the lower
+ * 16-bits at this point. Perform a typecast for faster
+ * execution on 16-bit processors.
+ */
+ lower_16 = (UInt)adts_header;
+
+ /*
+ * Indicates the number of 32-bit words remaining in the
+ * encoder buffer after the encoding of the first raw
+ * data block. This value is 0x7ff for variable bit
+ * rate encoders, since buffer fullness does not apply
+ * to Variable Bit Rate (VBR) encoders.
+ */
+ pVars->prog_config.buffer_fullness = (lower_16 >> 2) & 0x7FF;
+
+ /*
+ * headerless_frames indicates the number of
+ * frames with no headers to be processed before the reading
+ * in of the next header.
+ *
+ * In ADTS, up to 4 "no header frames" can exist between
+ * syncwords.
+ *
+ * EXAMPLES:
+ *
+ * Legend: (Sync words denoted by X, frames
+ * deonted by FRAME_#)
+ *
+ * Example(1): The ADTS sequence below packs 5
+ * frames per header.
+ * Here, headerless_frames would always be read in as "4"
+ *
+ * |X||FRAME_0||FRAME_1||FRAME_2||FRAME_3||FRAME_4||X||FRAME_0|
+ *
+ * Example(2): The ADTS sequence below packs 1 frame per header.
+ * Here, headerless_frames would always be read in as "0"
+ *
+ * |X||FRAME_0||X||FRAME_1||X||FRAME_2|
+ *
+ */
+ pVars->prog_config.headerless_frames = (lower_16 & 0x0003);
+
+ if (pVars->prog_config.CRC_absent == 0)
+ {
+ pVars->prog_config.CRC_check = (UInt)getbits(
+ LENGTH_CRC,
+ &(pVars->inputStream));
+ }
+
+ /* pVars->current_program = 0; */ /* shall be set after PCE is read */
+
+ return (status);
+
+} /* END get_adts_header */
diff --git a/media/libstagefright/codecs/aacdec/get_adts_header.h b/media/libstagefright/codecs/aacdec/get_adts_header.h
new file mode 100644
index 0000000..13afa05
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_adts_header.h
@@ -0,0 +1,90 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/get_adts_header.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file has the function declaration for get_adts_header().
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_ADTS_HEADER_H
+#define GET_ADTS_HEADER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_tdec_int_file.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+Int get_adts_header(
+ tDec_Int_File *pVars,
+ UInt32 *pSyncword,
+ Int *pInvoke,
+ Int CorrectlyReadFramesCount);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/get_audio_specific_config.cpp b/media/libstagefright/codecs/aacdec/get_audio_specific_config.cpp
new file mode 100644
index 0000000..092f397
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_audio_specific_config.cpp
@@ -0,0 +1,691 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/get_audio_specific_config.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified per review comments
+
+ Description: Modified per second review comments
+ (1) change audioObjectType to Int
+ (2) do not set pVars->prog_config.profile
+ (3) clean up status flag, default to SUCCESS
+ (4) fix multiple lines comments
+
+ Description: Change getbits.h to ibstream.h
+
+ Description: Modified per review comments
+ (1) updated revision history
+ (2) declare audioObjectType as enum type
+
+ Description: Replace some instances of getbits to get9_n_lessbits
+ when the number of bits read is 9 or less.
+
+ Description: Added support for backward and non-backward (explicit)
+ mode for Parametric Stereo (PS) used in enhanced AAC+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pVars = pointer to the structure that holds all information for
+ this instance of the library. pVars->prog_config is directly
+ used, and pVars->mc_info, pVars->prog_config,
+ pVars->pWinSeqInfo, pVars->SFBWidth128 are needed indirectly
+ for calling set_mc_info. Data type pointer to tDec_Int_File
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ status = 0 if successfully decoded AudioSpecificConfig
+ 1 if un-supported config is used for this release
+
+ Pointers and Buffers Modified:
+ pVars->prog_config contents are updated with the information read in.
+ pVars->mc_info contents are updated with channel information.
+ pVars->pWinSeqInfo contents are updated with window information.
+ pVars->SFBWidth128 contents are updated with scale factor band width data.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function reads the bitstream for the structure "AudioSpecificConfig",
+ and sets the decoder configuration that is needed by the decoder to be able
+ to decode the media properly.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function shall not use global variables
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3: 1999(E)
+ Part 3
+ Subpart 1 p18 1.6 Interface to MPEG-4 Systems
+ Subpart 4 p13 4.4.1 GA Specific Configuration
+ Amendment p10 6.2.1 AudioSpecificInfo
+ Amendment p78 8.2 Decoder configuration (GASpecificConfig)
+
+ (2) AAC DecoderSpecificInfo Information
+ PacketVideo descriptions - San Diego
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ status = SUCCESS;
+
+ pInputStream = &(pVars->inputStream);
+
+ temp = CALL getbits(
+ neededBits = LEN_OBJ_TYPE + LEN_SAMP_RATE_IDX,
+ pInputStream = pInputStream)
+ MODIFYING (pInputStream)
+ RETURNING (temp)
+
+ audioObjectType = (temp & 0x1f0) >> 4;
+
+ pVars->prog_config.profile = audioObjectType;
+
+ pVars->prog_config.sampling_rate_idx = temp & 0xf;
+
+ IF (pVars->prog_config.sampling_rate_idx == 0xf)
+ THEN
+ sampling_rate = CALL getbits(
+ neededBits = LEN_SAMP_RATE,
+ pInputStream = pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (sampling_rate)
+ ENDIF
+
+ channel_config = CALL getbits(
+ neededBits = LEN_CHAN_CONFIG,
+ pInputStream = pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (channel_config)
+
+ IF (channel_config > 2)
+ THEN
+ status = 1;
+ ENDIF
+
+ IF (((audioObjectType == MP4AUDIO_AAC_MAIN) OR
+ (audioObjectType == MP4AUDIO_AAC_LC) OR
+ (audioObjectType == MP4AUDIO_AAC_SSR) OR
+ (audioObjectType == MP4AUDIO_LTP) OR
+ (audioObjectType == MP4AUDIO_AAC_SCALABLE) OR
+ (audioObjectType == MP4AUDIO_TWINVQ)) AND (status == -1))
+ THEN
+ status = CALL get_GA_specific_config(
+ pVars = pVars,
+ channel_config = channel_config,
+ audioObjectType = audioObjectType,
+ pInputStream = pInputStream);
+ MODIFYING (pVars->mc_info,channel_config,pInputStream)
+ RETURNING (status)
+
+ ENDIF
+
+ IF (audioObjectType == MP4AUDIO_CELP)
+ THEN
+ status = 1;
+ ENDIF
+
+ IF (audioObjectType == MP4AUDIO_HVXC)
+ THEN
+ status = 1;
+ ENDIF
+
+ IF (audioObjectType == MP4AUDIO_TTSI)
+ THEN
+ status = 1;
+ ENDIF
+
+ IF ((audioObjectType == 13) OR (audioObjectType == 14) OR
+ (audioObjectType == 15) OR (audioObjectType == 16))
+ THEN
+ status = 1;
+ ENDIF
+
+ IF (((audioObjectType == MP4AUDIO_ER_AAC_LC) OR
+ (audioObjectType == MP4AUDIO_ER_AAC_LTP) OR
+ (audioObjectType == MP4AUDIO_ER_AAC_SCALABLE) OR
+ (audioObjectType == MP4AUDIO_ER_TWINVQ) OR
+ (audioObjectType == MP4AUDIO_ER_BSAC) OR
+ (audioObjectType == MP4AUDIO_ER_AAC_LD)) AND (status == -1))
+ THEN
+ status = 1;
+ ENDIF
+
+ IF (audioObjectType == MP4AUDIO_ER_CELP)
+ THEN
+ status = 1;
+ ENDIF
+
+ IF (audioObjectType == MP4AUDIO_ER_HVXC)
+ THEN
+ status = 1;
+ ENDIF
+
+ IF ((audioObjectType == MP4AUDIO_ER_HILN) OR
+ (audioObjectType == MP4AUDIO_PARAMETRIC))
+ THEN
+ status = 1;
+ ENDIF
+
+ IF ((audioObjectType == MP4AUDIO_ER_AAC_LC) OR
+ (audioObjectType == MP4AUDIO_ER_AAC_LTP) OR
+ (audioObjectType == MP4AUDIO_ER_AAC_SCALABLE) OR
+ (audioObjectType == MP4AUDIO_ER_TWINVQ) OR
+ (audioObjectType == MP4AUDIO_ER_BSAC) OR
+ (audioObjectType == MP4AUDIO_ER_AAC_LD) OR
+ (audioObjectType == MP4AUDIO_ER_CELP) OR
+ (audioObjectType == MP4AUDIO_ER_HVXC) OR
+ (audioObjectType == MP4AUDIO_ER_HILN) OR
+ (audioObjectType == MP4AUDIO_PARAMETRIC))
+ THEN
+ epConfig = CALL getbits(
+ neededBits = LEN_EP_CONFIG,
+ pInputStream = pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (epConfig)
+
+ IF (epConfig == 2)
+ THEN
+ status = 1;
+ ENDIF
+
+ ENDIF
+
+ RETURN status;
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_mp4ff_const.h"
+#include "e_tmp4audioobjecttype.h"
+#include "get_audio_specific_config.h"
+#include "get_ga_specific_config.h"
+#include "ibstream.h"
+#include "sfb.h" /* Where samp_rate_info[] is declared */
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Int get_audio_specific_config(tDec_Int_File * const pVars)
+{
+
+ UInt temp;
+ tMP4AudioObjectType audioObjectType;
+ //UInt32 sampling_rate;
+ UInt channel_config;
+ UInt syncExtensionType;
+ UInt extensionAudioObjectType = 0;
+ UInt extensionSamplingFrequencyIndex = 0;
+ BITS *pInputStream;
+ Int status;
+
+ status = SUCCESS;
+
+ pInputStream = &(pVars->inputStream);
+
+ pVars->mc_info.upsamplingFactor = 1; /* default to regular AAC */
+
+ temp = get9_n_lessbits(LEN_OBJ_TYPE + LEN_SAMP_RATE_IDX,
+ pInputStream);
+
+ /*
+ * The following code can directly set the values of elements in
+ * MC_Info, rather than first setting the values in pVars->prog_config
+ * and then copy these values to MC_Info by calling set_mc_info.
+ * In order to keep consistent with get_prog_config (ADIF) and
+ * get_adts_header (ADTS), the code here is still copying
+ * the info, and set the pVars->current_program = 0
+ */
+
+ /* AudioObjectType */
+ audioObjectType = (tMP4AudioObjectType)((temp & 0x1f0) >> 4);
+
+ pVars->mc_info.ExtendedAudioObjectType = audioObjectType; /* default */
+ /* saving an audioObjectType into a profile field */
+ /* pVars->prog_config.profile = audioObjectType; */
+
+ /* sampling rate index */
+ pVars->prog_config.sampling_rate_idx = temp & 0xf;
+
+ if (pVars->prog_config.sampling_rate_idx > 0xb)
+ {
+ /*
+ * Only support 12 sampling frequencies from array samp_rate_info ( see sfb.cpp)
+ * 7350 Hz (index 0xc) is not supported, the other indexes are reserved or escape
+ */
+ if (pVars->prog_config.sampling_rate_idx == 0xf) /* escape sequence */
+ {
+ /*
+ * sampling rate not listed in Table 1.6.2,
+ * this release does not support this
+ */
+ /*sampling_rate = getbits( LEN_SAMP_RATE,
+ pInputStream);*/
+ getbits(LEN_SAMP_RATE, pInputStream); /* future use */
+ }
+
+ status = 1;
+ }
+
+ channel_config = get9_n_lessbits(LEN_CHAN_CONFIG,
+ pInputStream);
+
+ if ((channel_config > 2) && (!pVars->aacConfigUtilityEnabled))
+ {
+ /*
+ * AAC lib does not support more than two channels
+ * signal error when in decoder mode
+ * do not test when in utility mode
+ */
+ status = 1;
+
+ }
+
+ if (audioObjectType == MP4AUDIO_SBR || audioObjectType == MP4AUDIO_PS)
+ {
+ /* to disable explicit backward compatiblity check */
+ pVars->mc_info.ExtendedAudioObjectType = MP4AUDIO_SBR;
+ pVars->mc_info.sbrPresentFlag = 1;
+
+ if (audioObjectType == MP4AUDIO_PS)
+ {
+ pVars->mc_info.psPresentFlag = 1;
+ pVars->mc_info.ExtendedAudioObjectType = MP4AUDIO_PS;
+ }
+
+ extensionSamplingFrequencyIndex = /* extensionSamplingFrequencyIndex */
+ get9_n_lessbits(LEN_SAMP_RATE_IDX,
+ pInputStream);
+ if (extensionSamplingFrequencyIndex == 0x0f)
+ {
+ /*
+ * sampling rate not listed in Table 1.6.2,
+ * this release does not support this
+ */
+ /*sampling_rate = getbits( LEN_SAMP_RATE,
+ pInputStream);*/
+ getbits(LEN_SAMP_RATE, pInputStream);
+ }
+
+ audioObjectType = (tMP4AudioObjectType) get9_n_lessbits(LEN_OBJ_TYPE ,
+ pInputStream);
+ }
+
+
+ if ((/*(audioObjectType == MP4AUDIO_AAC_MAIN) ||*/
+ (audioObjectType == MP4AUDIO_AAC_LC) ||
+ /*(audioObjectType == MP4AUDIO_AAC_SSR) ||*/
+ (audioObjectType == MP4AUDIO_LTP) /*||*/
+ /*(audioObjectType == MP4AUDIO_AAC_SCALABLE) ||*/
+ /*(audioObjectType == MP4AUDIO_TWINVQ)*/) && (status == SUCCESS))
+ {
+ status = get_GA_specific_config(pVars,
+ pInputStream,
+ channel_config,
+ audioObjectType);
+
+ /*
+ * verify that Program config returned a supported audio object type
+ */
+
+ if ((pVars->mc_info.audioObjectType != MP4AUDIO_AAC_LC) &&
+ (pVars->mc_info.audioObjectType != MP4AUDIO_LTP))
+ {
+ return 1; /* status != SUCCESS invalid aot */
+ }
+ }
+ else
+ {
+ return 1; /* status != SUCCESS invalid aot or invalid parameter */
+ }
+
+ /*
+ * SBR tool explicit signaling ( backward compatible )
+ */
+ if (extensionAudioObjectType != MP4AUDIO_SBR)
+ {
+ syncExtensionType = (UInt)get17_n_lessbits(LEN_SYNC_EXTENSION_TYPE,
+ pInputStream);
+
+ if (syncExtensionType == 0x2b7)
+ {
+ extensionAudioObjectType = get9_n_lessbits( /* extensionAudioObjectType */
+ LEN_OBJ_TYPE,
+ pInputStream);
+
+ if (extensionAudioObjectType == MP4AUDIO_SBR)
+ {
+ pVars->mc_info.sbrPresentFlag = get1bits(pInputStream); /* sbrPresentFlag */
+ if (pVars->mc_info.sbrPresentFlag == 1)
+ {
+ extensionSamplingFrequencyIndex =
+ get9_n_lessbits( /* extensionSamplingFrequencyIndex */
+ LEN_SAMP_RATE_IDX,
+ pInputStream);
+ if (pVars->aacPlusEnabled == true)
+ {
+#ifdef AAC_PLUS
+ pVars->mc_info.upsamplingFactor = (samp_rate_info[extensionSamplingFrequencyIndex].samp_rate >> 1) ==
+ samp_rate_info[pVars->prog_config.sampling_rate_idx].samp_rate ? 2 : 1;
+
+ if ((Int)extensionSamplingFrequencyIndex == pVars->prog_config.sampling_rate_idx)
+ {
+ /*
+ * Disable SBR decoding for any sbr-downsampled file whose SF is >= 24 KHz
+ */
+ if (pVars->prog_config.sampling_rate_idx < 6)
+ {
+ pVars->aacPlusEnabled = false;
+ }
+
+ pVars->mc_info.bDownSampledSbr = true;
+ }
+ pVars->prog_config.sampling_rate_idx = extensionSamplingFrequencyIndex;
+
+#endif
+ }
+
+ if (extensionSamplingFrequencyIndex == 0x0f)
+ {
+ /*
+ * sampling rate not listed in Table 1.6.2,
+ * this release does not support this
+ */
+ /*sampling_rate = getbits( LEN_SAMP_RATE,
+ pInputStream);*/
+ getbits(LEN_SAMP_RATE, pInputStream);
+ }
+ /* syncExtensionType */
+ syncExtensionType = (UInt)get17_n_lessbits(LEN_SYNC_EXTENSION_TYPE,
+ pInputStream);
+ if (syncExtensionType == 0x548)
+ {
+ pVars->mc_info.psPresentFlag = get1bits(pInputStream); /* psPresentFlag */
+ if (pVars->mc_info.psPresentFlag)
+ {
+ extensionAudioObjectType = MP4AUDIO_PS;
+ }
+ }
+ else
+ {
+ /*
+ * Rewind bitstream pointer so that the syncExtensionType reading has no
+ * effect when decoding raw bitstream
+ */
+ pVars->inputStream.usedBits -= LEN_SYNC_EXTENSION_TYPE;
+ }
+
+ pVars->mc_info.ExtendedAudioObjectType = (eMP4AudioObjectType)extensionAudioObjectType;
+ }
+ }
+ }
+ else if (!status)
+ {
+ /*
+ * Rewind bitstream pointer so that the syncExtensionType reading has no
+ * effect when decoding raw bitstream
+ */
+ pVars->inputStream.usedBits -= LEN_SYNC_EXTENSION_TYPE;
+
+#ifdef AAC_PLUS
+
+ /*
+ * For implicit signalling, no hint that sbr or ps is used, so we need to
+ * check the sampling frequency of the aac content, if lesser or equal to
+ * 24 KHz, by defualt upsample, otherwise, do nothing
+ */
+ if ((pVars->prog_config.sampling_rate_idx >= 6) && (pVars->aacPlusEnabled == true) &&
+ audioObjectType == MP4AUDIO_AAC_LC)
+ {
+ pVars->mc_info.upsamplingFactor = 2;
+ pVars->prog_config.sampling_rate_idx -= 3;
+ pVars->mc_info.sbrPresentFlag = 1;
+ pVars->sbrDecoderData.SbrChannel[0].syncState = SBR_NOT_INITIALIZED;
+ pVars->sbrDecoderData.SbrChannel[1].syncState = SBR_NOT_INITIALIZED;
+
+ }
+#endif
+
+ }
+ }
+ else /* MP4AUDIO_SBR was detected */
+ {
+ /*
+ * Set the real output frequency use by the SBR tool, define tentative upsample ratio
+ */
+ if (pVars->aacPlusEnabled == true)
+ {
+#ifdef AAC_PLUS
+ pVars->mc_info.upsamplingFactor = (samp_rate_info[extensionSamplingFrequencyIndex].samp_rate >> 1) ==
+ samp_rate_info[pVars->prog_config.sampling_rate_idx].samp_rate ? 2 : 1;
+
+ if ((Int)extensionSamplingFrequencyIndex == pVars->prog_config.sampling_rate_idx)
+ {
+ /*
+ * Disable SBR decoding for any sbr-downsampled file whose SF is >= 24 KHz
+ */
+ if (pVars->prog_config.sampling_rate_idx < 6)
+ {
+ pVars->aacPlusEnabled = false;
+ }
+ pVars->mc_info.bDownSampledSbr = true;
+ }
+ pVars->prog_config.sampling_rate_idx = extensionSamplingFrequencyIndex;
+
+
+
+#endif
+
+
+
+
+ }
+
+ } /* if ( extensionAudioObjectType != MP4AUDIO_SBR ) */
+
+ /*
+ * The following object types are not supported in this release,
+ * however, keep these interfaces for future implementation
+ */
+
+ /*
+ *if (audioObjectType == MP4AUDIO_CELP)
+ *{
+ * status = 1;
+ *}
+ */
+
+ /*
+ *if (audioObjectType == MP4AUDIO_HVXC)
+ *{
+ * status = 1;
+ *}
+ */
+
+ /*
+ *if (audioObjectType == MP4AUDIO_TTSI)
+ *{
+ * status = 1;
+ *}
+ */
+
+ /*
+ *if ((audioObjectType == 13) || (audioObjectType == 14) ||
+ * (audioObjectType == 15) || (audioObjectType == 16))
+ *{
+ * status = 1;
+ *}
+ */
+
+ /* The following objects are Amendment 1 objects */
+ /*
+ *if (((audioObjectType == MP4AUDIO_ER_AAC_LC) ||
+ * (audioObjectType == MP4AUDIO_ER_AAC_LTP) ||
+ * (audioObjectType == MP4AUDIO_ER_AAC_SCALABLE) ||
+ * (audioObjectType == MP4AUDIO_ER_TWINVQ) ||
+ * (audioObjectType == MP4AUDIO_ER_BSAC) ||
+ * (audioObjectType == MP4AUDIO_ER_AAC_LD)) && (status == -1))
+ *{
+ */
+ /*
+ * should call get_GA_specific_config
+ * for this release, do not support Error Resilience
+ * temporary solution is set status flag and exit decoding
+ */
+ /* status = 1;
+ *}
+ */
+
+ /*
+ *if (audioObjectType == MP4AUDIO_ER_CELP)
+ * {
+ * status = 1;
+ *}
+ */
+
+ /*
+ *if (audioObjectType == MP4AUDIO_ER_HVXC)
+ *{
+ * status = 1;
+ *}
+ */
+
+ /*
+ *if ((audioObjectType == MP4AUDIO_ER_HILN) ||
+ * (audioObjectType == MP4AUDIO_PARAMETRIC))
+ *{
+ * status = 1;
+ *}
+ */
+
+ /*
+ *if ((audioObjectType == MP4AUDIO_ER_AAC_LC) ||
+ * (audioObjectType == MP4AUDIO_ER_AAC_LTP) ||
+ * (audioObjectType == MP4AUDIO_ER_AAC_SCALABLE) ||
+ * (audioObjectType == MP4AUDIO_ER_TWINVQ) ||
+ * (audioObjectType == MP4AUDIO_ER_BSAC) ||
+ * (audioObjectType == MP4AUDIO_ER_AAC_LD) ||
+ * (audioObjectType == MP4AUDIO_ER_CELP) ||
+ * (audioObjectType == MP4AUDIO_ER_HVXC) ||
+ * (audioObjectType == MP4AUDIO_ER_HILN) ||
+ * (audioObjectType == MP4AUDIO_PARAMETRIC))
+ *{
+ */
+ /* error protection config */
+ /*
+ * epConfig =
+ * getbits(
+ * LEN_EP_CONFIG,
+ * pInputStream);
+ *
+ * if (epConfig == 2)
+ * {
+ */
+ /* should call ErrorProtectionSpecificConfig() */
+ /*
+ * status = 1;
+ * }
+ *
+ *}
+ */
+
+ return status;
+
+}
diff --git a/media/libstagefright/codecs/aacdec/get_audio_specific_config.h b/media/libstagefright/codecs/aacdec/get_audio_specific_config.h
new file mode 100644
index 0000000..b7cfcf5
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_audio_specific_config.h
@@ -0,0 +1,86 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/get_audio_specific_config.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes function declaration for get_audio_specific_config
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_AUDIO_SPECIFIC_CONFIG_H
+#define GET_AUDIO_SPECIFIC_CONFIG_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_tdec_int_file.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+Int get_audio_specific_config(
+ tDec_Int_File * const pVars
+);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/get_dse.cpp b/media/libstagefright/codecs/aacdec/get_dse.cpp
new file mode 100644
index 0000000..d64087f
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_dse.cpp
@@ -0,0 +1,215 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pInputStream = pointer to a BITS structure that holds information
+ regarding the input stream.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ pInputStream->usedBits is rounded up to a number that represents the next
+ byte boundary.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Adquire Data Stream element (DSE) from raw bitstream
+ At this time this function just drops the information.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function shall not use global or static variables.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void byte_align(
+ BITS *pInputStream)
+
+ MODIFYING(pInputStream->usedBits = pInputStream->usedBits +
+ (pInputStream->usedBits + 7) % 8)
+
+ RETURN(nothing)
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+
+ STACK USAGE:
+
+ where:
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES:
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+#include "get_dse.h"
+#include "ibstream.h"
+#include "getbits.h"
+#include "s_bits.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void get_dse(
+ Char *DataStreamBytes,
+ BITS *pInputStream)
+{
+ Int i;
+ Int data_byte_align_flag;
+ UInt count;
+ Int esc_count;
+ Char *pDataStreamBytes;
+
+ pDataStreamBytes = DataStreamBytes;
+
+ /*
+ * Get element instance tag ( 4 bits)
+ * ( max of 16 per raw data block)
+ */
+ get9_n_lessbits(LEN_TAG, pInputStream);
+
+ /*
+ * get data_byte_align_flag ( 1 bit0 to see if byte alignment is
+ * performed within the DSE
+ */
+ data_byte_align_flag = get1bits(pInputStream);
+
+ /*
+ * get count ( 8 bits)
+ */
+ count = get9_n_lessbits(LEN_D_CNT, pInputStream);
+
+ /*
+ * if count == 255, its value it is incremented by a
+ * second 8 bit value, esc_count. This final value represents
+ * the number of bytes in the DSE
+ */
+ if (count == (1 << LEN_D_CNT) - 1)
+ {
+ esc_count = (Int)get9_n_lessbits(LEN_D_ESC, pInputStream); /* 8 bits */
+ count += esc_count;
+ }
+
+ /*
+ * Align if flag is set
+ */
+ if (data_byte_align_flag)
+ {
+ byte_align(pInputStream);
+ }
+
+ for (i = count; i != 0; i--)
+ {
+ *(pDataStreamBytes++) = (Char) get9_n_lessbits(
+ LEN_BYTE,
+ pInputStream);
+ }
+
+ return;
+
+} /* end get_dse */
+
diff --git a/media/libstagefright/codecs/aacdec/get_dse.h b/media/libstagefright/codecs/aacdec/get_dse.h
new file mode 100644
index 0000000..3563f71
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_dse.h
@@ -0,0 +1,87 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_dse.h
+ Funtions:
+ get_dse
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_DSE_H
+#define GET_DSE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_elelist.h"
+#include "s_bits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void get_dse(
+ Char *DataStreamBytes,
+ BITS *pInputStream);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/get_ele_list.cpp b/media/libstagefright/codecs/aacdec/get_ele_list.cpp
new file mode 100644
index 0000000..0534c13
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_ele_list.cpp
@@ -0,0 +1,243 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_ele_list.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: Change to PacketVideo standard, rename variables.
+
+ Description: Add own header file, make pInputStream second param for speed.
+
+ Description: Changes per code review:
+ 1) Include header file
+ 2) Convert to count down
+ 3) Add return (not in review)
+
+ Description:
+ (1) Updated copyright header
+ (2) Replaced include of "interface.h" with "e_ProgConfig.h"
+
+ Description: Replace some instances of getbits to get9_n_lessbits
+ when the number of bits read is 9 or less and get1bits
+ when only 1 bit is read.
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pElementList = pointer to an EleList structure - only the field num_ele
+ needs to be set. Data type pointer to EleList.
+
+ pInputStream = pointer to a BITS structure, used by the function getbits
+ to provide data. Data type pointer to BITS
+
+ enableCPE = boolean value indicating the area to be read contains
+ a channel pair element field. Data type Bool
+
+
+ Local Stores/Buffers/Pointers Needed: None
+
+ Global Stores/Buffers/Pointers Needed: None
+
+ Outputs: None
+
+ Pointers and Buffers Modified:
+ pElementList contents are updated with information pertaining to channel
+ configuration.
+
+ pInputBuffer contents are updated to the next location to be read from
+ the input stream.
+
+ Local Stores Modified: None
+
+ Global Stores Modified: None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function is called several times by get_prog_config() to read in part of
+ the program configuration data related to channel setup.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function shall not have static or global variables.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 13818-7:1997 Titled "Information technology - Generic coding
+ of moving pictures and associated audio information - Part 7: Advanced
+ Audio Coding (AAC)", Table 6.21 - Syntax of program_config_element(),
+ page 16, and section 8.5 "Program Config Element (PCE)", page 30.
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ elementCount = pElementList->num_ele;
+
+ FOR (index = 0; index < elementCount; index++)
+ IF (enableCPE != FALSE) THEN
+ pElementList->ele_is_cpe[index] =
+ getbits(LEN_ELE_IS_CPE, pInputStream);
+ ELSE
+ pElementList->ele_is_cpe[index] = 0;
+ END IF
+
+ pElementList->ele_tag[index] = getbits(LEN_TAG, pInputStream);
+
+ END FOR
+
+ RETURNS nothing
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_elelist.h"
+#include "s_bits.h"
+#include "e_progconfigconst.h"
+#include "ibstream.h"
+#include "get_ele_list.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void get_ele_list(
+ EleList *pElementList,
+ BITS *pInputStream,
+ const Bool enableCPE)
+{
+ Int index;
+ Int *pEleIsCPE;
+ Int *pEleTag;
+
+ pEleIsCPE = &pElementList->ele_is_cpe[0];
+ pEleTag = &pElementList->ele_tag[0];
+
+ for (index = pElementList->num_ele; index > 0; index--)
+ {
+ if (enableCPE != FALSE)
+ {
+ *pEleIsCPE++ = get1bits(/*LEN_ELE_IS_CPE, */pInputStream);
+ }
+ else
+ {
+ *pEleIsCPE++ = FALSE;
+ }
+
+ *pEleTag++ = get9_n_lessbits(LEN_TAG, pInputStream);
+
+ } /* end for (index) */
+
+ return;
+
+} /* end get_ele_list */
+
diff --git a/media/libstagefright/codecs/aacdec/get_ele_list.h b/media/libstagefright/codecs/aacdec/get_ele_list.h
new file mode 100644
index 0000000..82f140b
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_ele_list.h
@@ -0,0 +1,90 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/get_ele_list.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for get_ele_list.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_ELE_LIST_H
+#define GET_ELE_LIST_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_elelist.h"
+#include "s_bits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+void get_ele_list(
+ EleList *pElementList,
+ BITS *pInputStream,
+ const Bool enableCPE);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/get_ga_specific_config.cpp b/media/libstagefright/codecs/aacdec/get_ga_specific_config.cpp
new file mode 100644
index 0000000..65c00ea
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_ga_specific_config.cpp
@@ -0,0 +1,473 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_GA_specific_config.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified per review comments
+
+ Description: Change getbits.h to ibstream.h
+
+ Description: (1) use enum type for audioObjectType (2) update revision history
+
+ Description: Updated the SW template to include the full pathname to the
+ source file and a slightly modified copyright header.
+
+ Description: Updated to use scratch memory for the temporary prog config.
+
+ Description: Replace some instances of getbits to get1bits
+ when only 1 bit is read.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pVars = pointer to the structure that holds all information for
+ this instance of the library. pVars->prog_config
+ pVars->mc_info, pVars->pWinSeqInfo, pVars->SFBWidth128
+ are needed for calling set_mc_info.
+ Data type pointer to tDec_Int_File
+
+ channel_config = variable that indicates the channel configuration
+ information, in this decoder library, only values
+ 0, 1, and 2 are allowed.
+ Data type UInt
+
+ audioObjectType = variable that indicates the Audio Object Type.
+ Data type UInt.
+
+ pInputStream = pointer to a BITS structure that holds information
+ regarding the input stream.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ status = 0 if success
+ 1 otherwise
+
+ Pointers and Buffers Modified:
+ pVars->mc_info contents are updated with channel information.
+ if infoinit is called within set_mc_info, then
+ pVars->pWinSeqInfo contents are updated with window information.
+ pVars->SFBWidth128 contents are updated with scale factor band width data.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function takes the sampling_rate_idx, channel_config, and
+ audioObjectType from AudioSpecificConfig() and set the decoder configuration
+ necessary for the decoder to decode properly.
+ It also reads the bitstream for frame length, scalable bitstream information
+ and extension information to General Audio defined in MPEG-4 phase 1
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function shall not use global variables
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3: 1999(E)
+ Part 3
+ Subpart 1 p18 1.6 Interface to MPEG-4 Systems
+ Subpart 4 p13 4.4.1 GA Specific Configuration
+ Amendment p10 6.2.1 AudioSpecificInfo
+ Amendment p78 8.2 Decoder configuration (GASpecificConfig)
+
+ (2) AAC DecoderSpecificInfo Information
+ PacketVideo descriptions - San Diego
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ frameLenFlag = CALL getbits(
+ neededBits = LEN_FRAME_LEN_FLAG,
+ pInputStream = pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (frameLenFlag)
+
+ dependsOnCoreCoder = CALL getbits(
+ neededBits = LEN_DEPEND_ON_CORE,
+ pInputStream = pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (dependsOnCoreCoder)
+
+ IF (dependsOnCoreCoder != FALSE)
+ THEN
+ coreCoderDelay = CALL getbits(
+ neededBits = LEN_CORE_DELAY,
+ pInputStream = pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (coreCoderDelay)
+ ENDIF
+
+ extFlag = CALL getbits(
+ neededBits = LEN_EXT_FLAG,
+ pInputStream = pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (extFlag)
+
+ IF (channel_config == 0)
+ THEN
+ status = CALL get_prog_config(
+ pVars = pVars,
+ pScratchPCE = &pVars->scratch_prog_config);
+ MODIFYING (pVars, pScratchPCE)
+ RETURNING (status)
+
+ ELSE
+ channel_config--;
+ pVars->prog_config.front.ele_is_cpe[0] = channel_config;
+ pVars->prog_config.front.ele_tag[0] = 0;
+
+ status = CALL set_mc_info(
+ pMC_Info = &(pVars->mc_info),
+ audioObjectType = audioObjectType,
+ sampling_rate_idx = pVars->prog_config.sampling_rate_idx,
+ tag = pVars->prog_config.front.ele_tag[0],
+ is_cpe = pVars->prog_config.front.ele_is_cpe[0],
+ pWinSeqInfo = pVars->pWinSeqInfo,
+ sfbwidth128 = pVars->SFBWidth128);
+ MODIFYING (pMC_Info, pWinSeqInfo, sfbwidth128)
+ RETURNING (SUCCESS)
+ ENDIF
+
+ IF ((audioObjectType == MP4AUDIO_AAC_SCALABLE) OR
+ (audioObjectType == MP4AUDIO_ER_AAC_SCALABLE))
+ THEN
+ layer_num = CALL getbits(
+ neededBits = LEN_LAYER_NUM,
+ pInputStream = pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (layer_num)
+
+ status = 1;
+ ENDIF
+
+ IF (extFlag != FALSE)
+ THEN
+ IF (audioObjectType == MP4AUDIO_ER_BSAC)
+ THEN
+ numOfSubFrame = CALL getbits(
+ neededBits = LEN_SUB_FRAME,
+ pInputStream = pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (numOfSubFrame)
+
+ layer_len = CALL getbits(
+ neededBits = LEN_LAYER_LEN,
+ pInputStream = pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (layer_len)
+
+ ENDIF
+
+ IF (((audioObjectType > 16) AND (audioObjectType < 22)) OR
+ (audioObjectType == 23))
+ THEN
+ aacSectionDataResilienceFlag =
+ CALL getbits(
+ neededBits = LEN_SECT_RES_FLAG,
+ pInputStream = pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (aacSectionDataResilienceFlag)
+
+ aacScalefactorDataResilienceFlag =
+ CALL getbits(
+ neededBits = LEN_SFB_RES_FLAG,
+ pInputStream = pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (aacScalefactorDataResilienceFlag)
+
+ aacSpectralDataResilienceFlag =
+ CALL getbits(
+ neededBits = LEN_SPEC_RES_FLAG,
+ pInputStream = pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (aacSpectralDataResilienceFlag)
+ ENDIF
+
+ status = 1;
+
+ ENDIF
+
+ RETURN status;
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_mp4ff_const.h"
+#include "e_tmp4audioobjecttype.h"
+#include "s_tdec_int_file.h"
+#include "get_ga_specific_config.h"
+#include "set_mc_info.h"
+#include "get_prog_config.h"
+#include "ibstream.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Int get_GA_specific_config(
+ tDec_Int_File * const pVars,
+ BITS *pInputStream,
+ UInt channel_config,
+ const tMP4AudioObjectType audioObjectType
+)
+{
+
+ Int status = SUCCESS;
+ UInt dependsOnCoreCoder;
+ /* Int coreCoderDelay; */
+ UInt extFlag;
+
+ /* These variables are left for future implementation */
+ /* UInt layer_num; */
+ /* UInt numOfSubFrame; */
+ /* UInt layer_len; */
+ /* UInt aacSectionDataResilienceFlag; */
+ /* UInt aacScalefactorDataResilienceFlag; */
+ /* UInt aacSpectralDataResilienceFlag; */
+ Int extFlag3;
+
+ /*
+ * frame length flag == 0, 1024 samples/frame
+ * frame length flag == 1, 960 samples/frame
+ */
+ get1bits(/* LEN_FRAME_LEN_FLAG,*/
+ pInputStream);
+
+ /*
+ * dependsOnCoreCoder == 1, core coder has different sampling rate
+ * in a scalable bitstream
+ */
+ dependsOnCoreCoder =
+ get1bits(/* LEN_DEPEND_ON_CORE,*/
+ pInputStream);
+
+ if (dependsOnCoreCoder != FALSE)
+ {
+ /*coreCoderDelay =
+ * getbits(
+ * LEN_CORE_DELAY,
+ * pInputStream);
+ */
+
+ status = 1; /* do not support scalable coding in this release */
+ }
+
+ /*
+ * extension flag indicates if Amendment 1 objects are used or not
+ * extension flag == 0 objects = 1, 2, 3, 4, 6, 7
+ * extension flag == 1 objects = 17, 19, 20, 21, 22, 23
+ */
+ extFlag = get1bits(pInputStream); /* LEN_EXT_FLAG,*/
+
+
+ /* Force checks for implicit channel configuration */
+ pVars->mc_info.implicit_channeling = 1;
+
+ if (status == SUCCESS)
+ {
+
+ if (channel_config == 0)
+ {
+ status = get_prog_config(pVars,
+ &pVars->scratch.scratch_prog_config);
+
+ if (status != SUCCESS)
+ {
+ pVars->prog_config.front.ele_is_cpe[0] = 0; /* default to mono */
+ pVars->mc_info.nch = 1;
+ pVars->prog_config.front.ele_tag[0] = 0;
+
+ status = SUCCESS;
+ }
+ }
+ else
+ {
+ /*
+ * dummy tag = 0 and
+ * set up decoding configurations
+ */
+ channel_config--;
+ pVars->prog_config.front.ele_is_cpe[0] = channel_config;
+ pVars->prog_config.front.ele_tag[0] = 0;
+
+ status =
+ set_mc_info(
+ &(pVars->mc_info),
+ audioObjectType, /* previously profile */
+ pVars->prog_config.sampling_rate_idx,
+ pVars->prog_config.front.ele_tag[0],
+ pVars->prog_config.front.ele_is_cpe[0],
+ pVars->winmap, /*pVars->pWinSeqInfo,*/
+ pVars->SFBWidth128);
+
+ } /* if (channel_config) */
+
+ } /* if(status) */
+
+ /*
+ * This layer_num is not found in ISO/IEC specs,
+ * but it is defined in San Diego spec for scalable bitstream
+ */
+ if ((audioObjectType == MP4AUDIO_AAC_SCALABLE) ||
+ (audioObjectType == MP4AUDIO_ER_AAC_SCALABLE))
+ {
+ /*layer_num =
+ * getbits(
+ * LEN_LAYER_NUM,
+ * pInputStream);
+ */
+
+ status = 1; /* for this release only */
+ }
+
+ if (extFlag)
+ {
+ /*
+ * currently do not implement these functionalities
+ * defined in Amendment 1
+ * keep it here for future release
+ */
+ if (audioObjectType == MP4AUDIO_ER_BSAC)
+ {
+ status = 1; /* NOT SUPPORTED */
+ /*
+ numOfSubFrame = getbits( LEN_SUB_FRAME, pInputStream);
+
+ layer_len = getbits( LEN_LAYER_LEN, pInputStream);
+ */
+ }
+
+ /*
+ * The following code is equivalent to
+ * if ((audioObjectType == 17) || (audioObjectType == 18) ||
+ * (audioObjectType == 19) || (audioObjectType == 20) ||
+ * (audioObjectType == 21) || (audioObjectType == 23))
+ */
+
+ if (((audioObjectType > 16) && (audioObjectType < 22)) ||
+ (audioObjectType == 23))
+ {
+ status = 1; /* NOT SUPPORTED */
+ /*
+ aacSectionDataResilienceFlag = getbits( LEN_SECT_RES_FLAG,
+ pInputStream);
+
+ aacScalefactorDataResilienceFlag = getbits( LEN_SCF_RES_FLAG,
+ pInputStream);
+
+ aacSpectralDataResilienceFlag = getbits( LEN_SPEC_RES_FLAG,
+ pInputStream);
+ */
+ }
+ /*
+ * this flag is tbd in version 3 of ISO/IEC spec
+ * if the encoder generates this bit, then it has to be read
+ * current adif2mp4ff does not write this bit. If this bit is to
+ * be read, it can be done by the following code:
+ */
+
+ extFlag3 = get1bits(pInputStream); /* LEN_EXT_FLAG3 */
+
+ if (extFlag3)
+ {
+ status = 1; /* NOT SUPPORTED */
+ }
+
+ }
+
+ return status;
+}
diff --git a/media/libstagefright/codecs/aacdec/get_ga_specific_config.h b/media/libstagefright/codecs/aacdec/get_ga_specific_config.h
new file mode 100644
index 0000000..7c77da5
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_ga_specific_config.h
@@ -0,0 +1,94 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_GA_specific_config.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: (1) use enum type for audioObjectType
+ (2) update revision history
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes the function declaration for get_GA_specific_config.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_GA_SPECIFIC_CONFIG_H
+#define GET_GA_SPECIFIC_CONFIG_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_tdec_int_file.h"
+#include "s_bits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+Int get_GA_specific_config(
+ tDec_Int_File * const pVars,
+ BITS *pInputStream,
+ UInt channel_config,
+ const tMP4AudioObjectType audioObjectType
+);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/get_ics_info.cpp b/media/libstagefright/codecs/aacdec/get_ics_info.cpp
new file mode 100644
index 0000000..17204cc
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_ics_info.cpp
@@ -0,0 +1,608 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/get_ics_info.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: Clean up code.
+
+ Description: Fix comments before review, remove lpflag[]
+
+ Description: Update per review comments, and match ISO/IEC 14496-3
+
+ Description: Update per peer review comments.
+
+ Description: Remove "rollback" of used bits, since lt_decode is to change.
+
+ Description: Replace some instances of getbits to get9_n_lessbits
+ when the number of bits read is 9 or less and get1bits
+ when only 1 bit is read.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ audioObjectType = MP4 Audio Object Type for the current song. Only if
+ this is set to LTP (MP4AUDIO_LTP) will long term
+ prediction bits be retrieved. Data type
+ tMP4AudioObjectType, which is an enumeration, which in
+ turn is an Int.
+
+ pInputStream = pointer to a BITS structure, used by the function getbits
+ to provide data. This is the second parameter to this
+ function to match its position in getbits().
+ Data type pointer to BITS structure
+
+ common_window = field read in huffdecode, which tells whether information
+ is shared between the left and right channel. Long term
+ prediction (LTP) data is NOT shared even if its a common
+ window, so this flag is needed to see if another set of
+ LTP possibly needs to be read. If this flag is false,
+ pSecondLTPStatus is not touched, it could be NULL if
+ need be. Data type Bool, which is Int.
+
+ pWindowSequence = pointer to where the the window type of the current
+ frame and channel should be placed, of data type
+ WINDOW_SEQUENCE, which is Int. It can take on one
+ of four values: ONLY_LONG_SEQUENCE, LONG_START_SEQUENCE,
+ EIGHT_SHORT_SEQUENCE, LONG_STOP_SEQUENCE,
+
+ pWindowShape = pointer to where the window shape for the current frame
+ and channel should be placed, of data type WINDOW_SHAPE,
+ which is Int. It can take on the one of these two values:
+ SINE_WINDOW, KAISER_BESSEL_WINDOW. It is used in the
+ "filterbank" section of decoding.
+
+ group = array that holds the index of the first window in each
+ group. Data type array of Int, eight elements.
+
+ p_max_sfb = pointer to where the maximum number of scale factor bands
+ for the current frame and channel will be placed. Data
+ type of pointer to Int.
+
+ p_winmap = array of pointers to all of the possible four window
+ configurations. This parameter did not need to be pointers,
+ and could be changed in the future. Data type array of pointers
+ to FrameInfo structures, length 4.
+
+ pFirstLTPStatus = pointer to a structure where the first LTP
+ information will be stored. It would be confusing and wrong
+ to call this left LTP status since if common_window = FALSE,
+ this function will be called twice - once for the left, once
+ for the right. It could be done, but extra conditional code
+ would need to be done.
+ Data type pointer to LT_PRED_STATUS structure.
+
+ pSecondLTPStatus = pointer to where the right channel of LTP
+ information will be stored only if common_window is non-zero.
+ Data type pointer to LT_PRED_STATUS structure.
+
+ Local Stores/Buffers/Pointers Needed: None.
+
+ Global Stores/Buffers/Pointers Needed: None.
+
+ Outputs:
+ status = 0 implies no error occurred, non-zero otherwise.
+
+ Pointers and Buffers Modified:
+ pInputStream contents are modified in such a way that the number of bits
+ read increases.
+ pWindowSequence contents are updated with the current window for this
+ frame and channel
+ group[] contents will be modified to grouping information. See getgroup
+ source code for a better description of what this is.
+ p_max_sfb contents will be updated with the maximum scale factor bands
+ for this frame and channel.
+ pFirstLTPStatus contents may be updated if the stream has long term
+ prediction information.
+ pSecondLTPStatus contents may be updated if common_window != 0 and LTP data
+ is present.
+
+
+ Local Stores Modified: None
+
+ Global Stores Modified: None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function retrieves the individual channel stream (ICS) information
+ from the bitstream. The information read for the current
+ frame and channel is:
+ - window sequence
+ - window shape for use in the filter bank
+ - number of scale factor bands
+ - long term predication (LTP) information
+ - grouping information
+
+ This function does NOT support MPEG2 style AAC Frequency Domain Predictor,
+ not to be confused with LTP (Long Term Prediction). If such data is found
+ to be on the file an error is generated.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function is not to use static or global data.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E) Titled "Information technology - Coding
+ of audio-visual objects Part 3: Audio Subpart 4:"
+ Table 4.4.6 - Syntax of ics_info(), page 16.
+
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ status = 0;
+ first_ltp_data_present = FALSE;
+ second_ltp_data_present = FALSE;
+
+
+ CALL getbits(
+ neededBits = LEN_ICS_RESERV + LEN_WIN_SEQ + LEN_WIN_SH,
+ pInputStream = pInputStream)
+ MODIFYING( pInputStream )
+ RETURNING( temp = returnValue )
+
+ windowSequence = (temp >> LEN_WIN_SH) & ((0x1<<LEN_WIN_SEQ)-1);
+
+ *pWindowShape = (temp) & ((0x1<<LEN_WIN_SH)-1);
+
+ IF (windowSequence == EIGHT_SHORT_SEQUENCE)
+ THEN
+ CALL getbits(
+ neededBits = LEN_MAX_SFBS,
+ pInputStream = pInputStream)
+ MODIFYING(pInputStream)
+ RETURNING(local_max_sfb = returnValue)
+
+ CALL getgroup(
+ group = group,
+ pInputStream = pInputStream)
+ MODIFYING(group)
+ MODIFYING(pInputStream)
+ RETURNING(nothing)
+
+
+ ELSE
+
+ group[0] = 1;
+
+ CALL getbits(
+ neededBits = LEN_MAX_SFBL + LEN_PREDICTOR_DATA_PRESENT,
+ pInputStream = pInputStream)
+ MODIFYING(pInputStream)
+ RETURNING(temp = returnValue)
+
+ predictor_data_present =
+ (Bool) getbits(
+ LEN_BOOLEAN,
+ pInputStream);
+
+ local_max_sfb = (Int)(temp >> LEN_PREDICTOR_DATA_PRESENT);
+
+ predictor_data_present =
+ (Bool) (temp & ((0x1 << LEN_PREDICTOR_DATA_PRESENT)-1));
+
+ IF (local_max_sfb > allowed_max_sfb)
+ THEN
+ status = 1
+ ELSEIF (audioObjectType == MP4AUDIO_LTP)
+ THEN
+ IF (predictor_data_present != FALSE)
+ THEN
+ CALL getbits(
+ neededBits = LEN_LTP_DATA_PRESENT,
+ pInputStream = pInputStream)
+ MODIFYING(pInputStream)
+ RETURNING(first_ltp_data_present = returnValue)
+
+ IF (ltp_data_present != FALSE)
+ THEN
+
+ CALL lt_decode(
+ win_type = windowSequence,
+ pInputStream = pInputStream,
+ max_sfb = local_max_sfb,
+ pLt_pred = pFirstLTPStatus)
+ MODIFYING(pInputStream)
+ MODIFYING(pFirstLTPStatus)
+ RETURNING(nothing)
+
+ ENDIF
+
+ IF (common_window != FALSE)
+ THEN
+ CALL getbits(
+ neededBits = LEN_LTP_DATA_PRESENT,
+ pInputStream = pInputStream)
+ MODIFYING(pInputStream)
+ RETURNING(second_ltp_data_present = returnValue)
+
+ IF (second_ltp_data_present != FALSE)
+ THEN
+
+ CALL lt_decode(
+ win_type = windowSequence,
+ pInputStream = pInputStream,
+ max_sfb = local_max_sfb,
+ pLt_pred = pSecondLTPStatus)
+ MODIFYING(pInputStream)
+ MODIFYING(pSecondLTPStatus)
+ RETURNING(nothing)
+ ENDIF
+ ENDIF
+ ENDIF
+ ELSE
+ IF (predictor_data_present != FALSE)
+ THEN
+ status = 1
+ ENDIF
+ END IF
+ ENDIF
+
+ pFirstLTPStatus->ltp_data_present = first_ltp_data_present;
+
+ IF (common_window != FALSE)
+ THEN
+ pSecondLTPStatus->ltp_data_present = second_ltp_data_present;
+ ENDIF
+
+ pFrameInfo = p_winmap[*p_wnd];
+ IF (local_max_sfb > pFrameInfo->sfb_per_frame)
+ THEN
+ status = 1;
+ ENDIF
+
+ *(p_max_sfb) = local_max_sfb;
+
+ MODIFY(*(pWindowSequence))
+ MODIFY(*(pWinShape))
+ MODIFY(*(p_max_sfb))
+ MODIFY(group[])
+ MODIFY(*pInputStream)
+ MODIFY(*pFirstLTPStatus)
+ MODIFY(*pSecondLTPStatus)
+ RETURN (status);
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+#include "e_rawbitstreamconst.h"
+#include "e_tmp4audioobjecttype.h"
+
+#include "s_bits.h"
+#include "s_frameinfo.h"
+#include "s_lt_pred_status.h"
+
+#include "ibstream.h"
+#include "lt_decode.h"
+#include "ltp_common_internal.h" /* For LEN_LTP_DATA_PRESENT constant */
+
+#include "get_ics_info.h"
+#include "huffman.h" /* For the declaration of getgroup */
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define LEN_PREDICTOR_DATA_PRESENT (1)
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int get_ics_info(
+ const tMP4AudioObjectType audioObjectType,
+ BITS *pInputStream,
+ const Bool common_window,
+ WINDOW_SEQUENCE *pWindowSequence,
+ WINDOW_SHAPE *pWindowShape,
+ Int group[],
+ Int *p_max_sfb,
+ FrameInfo *p_winmap[],
+ LT_PRED_STATUS *pFirstLTPStatus,
+ LT_PRED_STATUS *pSecondLTPStatus)
+{
+ WINDOW_SEQUENCE windowSequence;
+ UInt temp;
+ Bool predictor_data_present;
+ UInt local_max_sfb;
+ UInt allowed_max_sfb;
+ Int status = SUCCESS;
+ Bool first_ltp_data_present = FALSE;
+ Bool second_ltp_data_present = FALSE;
+
+ /*
+ * The following three calls to getbits have been replaced with one
+ * call for speed:
+ *
+ * getbits(LEN_ICS_RESERV, pInputStream);
+ * windowSequence = getbits(LEN_WIN_SEQ, pInputStream);
+ * *pWindowShape = getbits(LEN_WIN_SH, pInputStream);
+ *
+ */
+
+ temp =
+ get9_n_lessbits(
+ LEN_ICS_RESERV + LEN_WIN_SEQ + LEN_WIN_SH,
+ pInputStream);
+
+
+ windowSequence = (WINDOW_SEQUENCE)((temp >> LEN_WIN_SH) & ((0x1 << LEN_WIN_SEQ) - 1));
+
+ *pWindowShape = (WINDOW_SHAPE)((temp) & ((0x1 << LEN_WIN_SH) - 1));
+
+ /*
+ * This pointer should not be NULL as long as the initialization code
+ * has been run, so the test for NULL has been removed.
+ */
+ allowed_max_sfb = p_winmap[windowSequence]->sfb_per_win[0];
+
+ if (windowSequence == EIGHT_SHORT_SEQUENCE)
+ {
+ local_max_sfb = get9_n_lessbits(LEN_MAX_SFBS,
+ pInputStream);
+
+ getgroup(
+ group,
+ pInputStream);
+
+ if (local_max_sfb > allowed_max_sfb)
+ {
+ status = 1; /* ERROR CODE - needs to be updated */
+ }
+
+ } /* end of TRUE of if (windowSequence == EIGHT_SHORT_SEQUENCE) */
+ else
+ {
+ /* There is only one group for long windows. */
+ group[0] = 1;
+
+ /*
+ * The window is long, get the maximum scale factor bands,
+ * and get long term prediction info.
+ *
+ * Reference [1] states that the audioObjectType is first tested,
+ * then the predictor_data_present is read on either branch of the
+ * if (audioObjectType == MP4AUDIO_LTP). Instead, this code combines
+ * the two calls on both branches into one before the
+ * if, and then in turn combines with another call to getbits, all
+ * in the name of speed.
+ *
+ * This would be the individual calls, without checking the number
+ * of scale factor bands:
+ *
+ * local_max_sfb =
+ * (Int) getbits(
+ * LEN_MAX_SFBL,
+ * pInputStream);
+ *
+ * if (audioObjectType == MP4AUDIO_LTP)
+ * {
+ * predictor_data_present =
+ * (Bool) getbits(
+ * LEN_PREDICTOR_DATA_PRESENT,
+ * pInputStream);
+ *
+ * ..... (read LTP data)
+ *
+ * }
+ * else
+ * {
+ *
+ * predictor_data_present =
+ * (Bool) getbits(
+ * LEN_PREDICTOR_DATA_PRESENT,
+ * pInputStream);
+ *
+ * ..... (its an error for this library)
+ * }
+ */
+ temp =
+ get9_n_lessbits(
+ LEN_MAX_SFBL + LEN_PREDICTOR_DATA_PRESENT,
+ pInputStream);
+
+ local_max_sfb = (Int)(temp >> LEN_PREDICTOR_DATA_PRESENT);
+
+ predictor_data_present =
+ (Bool)(temp & ((0x1 << LEN_PREDICTOR_DATA_PRESENT) - 1));
+
+ if (local_max_sfb > allowed_max_sfb)
+ {
+ status = 1; /* ERROR CODE - needs to be updated */
+ }
+ else if (audioObjectType == MP4AUDIO_LTP)
+ {
+ /*
+ * Note that the predictor data bit has already been
+ * read.
+ */
+
+ /*
+ * If the object type is LTP, the predictor data is
+ * LTP. If the object type is not LTP, the predictor data
+ * is so called "frequency predictor data", which is not
+ * supported by this implementation. Refer to (1)
+ */
+ if (predictor_data_present != FALSE)
+ {
+ first_ltp_data_present =
+ (Bool) get1bits(/* LEN_LTP_DATA_PRESENT,*/
+ pInputStream);
+
+ if (first_ltp_data_present != FALSE)
+ {
+ lt_decode(
+ windowSequence,
+ pInputStream,
+ local_max_sfb,
+ pFirstLTPStatus);
+ }
+ if (common_window != FALSE)
+ {
+ second_ltp_data_present =
+ (Bool) get1bits(/* LEN_LTP_DATA_PRESENT,*/
+ pInputStream);
+
+ if (second_ltp_data_present != FALSE)
+ {
+ lt_decode(
+ windowSequence,
+ pInputStream,
+ local_max_sfb,
+ pSecondLTPStatus);
+ }
+ } /* if (common_window != FALSE) */
+
+ } /* if (predictor_data_present != FALSE) */
+
+ } /* else if (audioObjectType == MP4AUDIO_LTP) */
+ else
+ {
+ /*
+ * Note that the predictor data bit has already been
+ * read.
+ */
+
+ /*
+ * The object type is not LTP. If there is data, its
+ * frequency predictor data, not supported by this
+ * implementation.
+ */
+ if (predictor_data_present != FALSE)
+ {
+ status = 1; /* ERROR CODE UPDATE LATER */
+ } /* if (predictor_data_present != FALSE) */
+
+ } /* end of "else" clause of if (audioObjectType == MP4AUDIO_LTP) */
+
+ } /* if (windowSequence == EIGHT_SHORT_SEQUENCE) [FALSE branch] */
+
+
+ /*
+ * Save all local copies.
+ */
+ pFirstLTPStatus->ltp_data_present = first_ltp_data_present;
+ if (common_window != FALSE)
+ {
+ pSecondLTPStatus->ltp_data_present = second_ltp_data_present;
+ }
+
+ *p_max_sfb = local_max_sfb;
+
+ *pWindowSequence = windowSequence;
+
+ return (status);
+
+} /* get_ics_info */
+
diff --git a/media/libstagefright/codecs/aacdec/get_ics_info.h b/media/libstagefright/codecs/aacdec/get_ics_info.h
new file mode 100644
index 0000000..b94ef8e
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_ics_info.h
@@ -0,0 +1,111 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/get_ics_info.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Contains the declaration for the function get_ics_info()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_ICS_INFO_H
+#define GET_ICS_INFO_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_tmp4audioobjecttype.h"
+#include "s_bits.h"
+#include "e_window_sequence.h"
+#include "e_window_shape.h"
+#include "s_frameinfo.h"
+#include "s_lt_pred_status.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Int get_ics_info(
+ const tMP4AudioObjectType audioObjectType,
+ BITS *pInputStream,
+ const Bool common_window,
+ WINDOW_SEQUENCE *p_wnd,
+ WINDOW_SHAPE *pWindowShape,
+ Int group[],
+ Int *p_max_sfb,
+ FrameInfo *p_winmap[],
+ LT_PRED_STATUS *pFirstLTPStatus,
+ LT_PRED_STATUS *pSecondLTPStatus);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* GET_ICS_INFO_H */
+
+
diff --git a/media/libstagefright/codecs/aacdec/get_prog_config.cpp b/media/libstagefright/codecs/aacdec/get_prog_config.cpp
new file mode 100644
index 0000000..6bddd57
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_prog_config.cpp
@@ -0,0 +1,739 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_prog_config.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: Move functionality from get_adif_header for when to change
+ the current program configuration, add a temporary config
+ to read into, clean up code, change function prototype.
+
+ Description: Clean up
+
+ Description: Update per review comments
+
+ Description: Fix double 'could'
+
+ Description: change enter_mc_info to set_mc_info
+
+ Description: update comments
+
+ Description: Replace some instances of getbits to get9_n_lessbits
+ when the number of bits read is 9 or less and get1bits
+ when only 1 bit is read.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pVars = pointer to the structure that holds all information for
+ this instance of the library. pVars->prog_config is directly
+ used, and pVars->mc_info, pVars->prog_config, pVars->winmap,
+ pVars->SFBWidth128 are needed indirectly for calling
+ set_mc_info. Data type pointer to tDec_Int_File structure.
+
+ pScratchPCE = pointer to a temporary ProgConfig structure to be used
+ to read in the program configuration element.
+
+ Local Stores/Buffers/Pointers Needed: None
+
+ Global Stores/Buffers/Pointers Needed: None
+
+ Outputs:
+ status = zero if no error was found, non-zero otherwise.
+
+ Pointers and Buffers Modified:
+ pVars->prog_config contents are updated with the PCE read in.
+ pVars->mc_info contents are updated with channel information.
+ pVars->winmap contents are updated with window information.
+ pVars->SFBWidth128 contents are updated with scale factor band width data.
+
+ Local Stores Modified: None
+
+ Global Stores Modified: None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function reads from the input stream to memory for a temporary
+ program configuration element (PCE). If the PCE read is the first
+ encountered it is saved. Or, if the tag of the PCE read matches the tag of
+ the first PCE encounted, it is saved as well. This is a mechanism for
+ changing the sampling rate.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function shall not use static or global variables.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 13818-7:1997 Titled "Information technology - Generic coding
+ of moving pictures and associated audio information - Part 7: Advanced
+ Audio Coding (AAC)", Table 6.21 - Syntax of program_config_element(),
+ page 16, and section 8.5 "Program Config Element (PCE)", page 30.
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ status = SUCCESS;
+ pInputStream = &(pVars->inputStream);
+
+
+ CALL getbits(
+ neededBits = LEN_TAG,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( tag = returnValue )
+
+ CALL getbits(
+ neededBits = LEN_PROFILE,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( pScratchPCE->profile = returnValue )
+
+ CALL getbits(
+ neededBits = LEN_PROFILE,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( pScratchPCE->sampling_rate_idx = returnValue )
+
+ CALL getbits(
+ neededBits = LEN_NUM_ELE,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( temp = returnValue )
+
+ pScratchPCE->front.num_ele = temp;
+
+ CALL getbits(
+ neededBits = LEN_NUM_ELE,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( temp = returnValue )
+
+ pScratchPCE->side.num_ele = temp;
+
+ CALL getbits(
+ neededBits = LEN_NUM_ELE,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( temp = returnValue )
+
+ pScratchPCE->back.num_ele = temp;
+
+ CALL getbits(
+ neededBits = LEN_NUM_LFE,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( temp = returnValue )
+
+ pScratchPCE->lfe.num_ele = temp;
+
+ CALL getbits(
+ neededBits = LEN_NUM_DAT,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( temp = returnValue )
+
+ pScratchPCE->data.num_ele = temp;
+
+ CALL getbits(
+ neededBits = LEN_NUM_CCE,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( temp = returnValue )
+
+ pScratchPCE->coupling.num_ele = temp;
+
+ CALL getbits(
+ neededBits = LEN_MIX_PRES,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( flag = returnValue )
+
+ pScratchPCE->mono_mix.present = flag;
+
+ IF (flag != FALSE)
+ THEN
+ CALL getbits(
+ neededBits = LEN_TAG,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( temp = returnValue )
+
+ pScratchPCE->mono_mix.ele_tag = temp;
+
+ ENDIF
+
+ CALL getbits(
+ neededBits = LEN_MIX_PRES,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( flag = returnValue )
+
+ pScratchPCE->stereo_mix.present = flag;
+
+ IF (flag != FALSE)
+ THEN
+
+ CALL getbits(
+ neededBits = LEN_TAG,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( temp = returnValue )
+
+ pScratchPCE->stereo_mix.ele_tag = temp;
+
+ ENDIF
+
+ CALL getbits(
+ neededBits = LEN_MIX_PRES,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( flag = returnValue )
+
+ flag =
+ getbits(
+ LEN_MIX_PRES,
+ pInputStream);
+
+ pScratchPCE->matrix_mix.present = flag;
+
+ IF (flag != FALSE)
+ THEN
+ CALL getbits(
+ neededBits = LEN_MMIX_IDX,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( temp = returnValue )
+
+ pScratchPCE->matrix_mix.ele_tag = temp;
+
+ CALL getbits(
+ neededBits = LEN_PSUR_ENAB,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( temp = returnValue )
+
+ pScratchPCE->matrix_mix.pseudo_enab = temp;
+
+ ENDIF
+
+
+ CALL get_ele_list(
+ pElementList = &pScratchPCE->front,
+ pInputStream = pInputStream,
+ enableCPE = TRUE )
+ MODIFYING( pInputStream )
+ MODIFYING( pScratchPCE->front )
+ RETURNING( nothing )
+
+ CALL get_ele_list(
+ pElementList = &pScratchPCE->side,
+ pInputStream = pInputStream,
+ enableCPE = TRUE )
+ MODIFYING( pInputStream )
+ MODIFYING( pScratchPCE->side )
+ RETURNING( nothing )
+
+ CALL get_ele_list(
+ pElementList = &pScratchPCE->back,
+ pInputStream = pInputStream,
+ enableCPE = TRUE )
+ MODIFYING( pInputStream )
+ MODIFYING( pScratchPCE->back )
+ RETURNING( nothing )
+
+ CALL get_ele_list(
+ pElementList = &pScratchPCE->lfe,
+ pInputStream = pInputStream,
+ enableCPE = FALSE )
+ MODIFYING( pInputStream )
+ MODIFYING( pScratchPCE->lfe )
+ RETURNING( nothing )
+
+ CALL get_ele_list(
+ pElementList = &pScratchPCE->data,
+ pInputStream = pInputStream,
+ enableCPE = FALSE )
+ MODIFYING( pInputStream )
+ MODIFYING( pScratchPCE->data )
+ RETURNING( nothing )
+
+ CALL get_ele_list(
+ pElementList = &pScratchPCE->coupling,
+ pInputStream = pInputStream,
+ enableCPE = TRUE )
+ MODIFYING( pInputStream )
+ MODIFYING( pScratchPCE->coupling )
+ RETURNING( nothing )
+
+
+ CALL byte_align(
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( nothing )
+
+ CALL getbits(
+ neededBits = LEN_COMMENT_BYTES,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( numChars = returnValue )
+
+ FOR (i = numChars; i > 0; i--)
+
+ CALL getbits(
+ neededBits = LEN_COMMENT_BYTES,
+ pInputStream = pInputStream )
+ MODIFYING( pInputStream )
+ RETURNING( nothing )
+
+ ENDFOR
+
+ IF (pVars->current_program < 0)
+ THEN
+ pVars->current_program = tag;
+ ENDIF
+
+
+ IF (tag == pVars->current_program)
+ THEN
+
+ CALL pv_memcpy(
+ to = &pVars->prog_config,
+ from = pScratchPCE,
+ n = sizeof(ProgConfig))
+ MODIFYING( pVars->prog_config )
+ RETURNING( nothing )
+
+ CALL set_mc_info(
+ pMC_Info = &pVars->mc_info,
+ objectType = pVars->prog_config.profile + 1,
+ samplin_rate_idx = pVars->prog_config.sampling_rate_idx,
+ tag = pVars->prog_config.front.ele_tag[0],
+ is_cpe = pVars->prog_config.front.ele_is_cpe[0],
+ pWinSeqInfo = pVars->winmap,
+ pSfbwidth128 = pVars->SFBWidth128)
+ MODIFYING( pVars->mc_info )
+ MODIFYING( pVars->winmap )
+ MODIFYING( pVars->SFBWidth128 )
+ RETURN( status = return_value )
+
+ ENDIF
+
+ MODIFY( pVars->mc_info )
+ MODIFY( pVars->winmap )
+ MODIFY( pVars->SFBWidth128 )
+ RETURN (status)
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bits.h"
+#include "s_elelist.h"
+#include "s_tdec_int_file.h"
+#include "s_tdec_int_chan.h"
+#include "e_progconfigconst.h"
+#include "ibstream.h"
+#include "get_ele_list.h"
+#include "aac_mem_funcs.h"
+#include "set_mc_info.h"
+#include "get_prog_config.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+Int get_prog_config(
+ tDec_Int_File *pVars,
+ ProgConfig *pScratchPCE)
+{
+ Int i;
+ UInt tag;
+ Int numChars;
+ UInt temp;
+ Bool flag;
+ Int status = SUCCESS;
+ BITS *pInputStream = &(pVars->inputStream);
+
+
+ /*
+ * The tag is used at the very end to see if this PCE is
+ * the one to be used. Otherwise it does not need to be saved for the
+ * the simple configurations to be used in this version of an AAC
+ * decoder.
+ *
+ * All of the bits of this PCE must be read even if this PCE will not
+ * be used. They are read into a temporary PCE, then later it is decided
+ * whether to keep this PCE.
+ *
+ * To allow quick removal of the fields from the ProgConfig structure
+ * that will probably not be used at a later date,
+ * while still advancing the bitstream pointer,the return value of
+ * getbits is saved into a temporary variable, then transfered to
+ * the structure item.
+ */
+ tag =
+ get9_n_lessbits(
+ LEN_TAG,
+ pInputStream);
+
+ pScratchPCE->profile =
+ get9_n_lessbits(
+ LEN_PROFILE,
+ pInputStream);
+
+ pScratchPCE->sampling_rate_idx =
+ get9_n_lessbits(
+ LEN_SAMP_IDX,
+ pInputStream);
+
+ if (!pVars->adif_test && pScratchPCE->sampling_rate_idx != pVars->prog_config.sampling_rate_idx)
+ {
+ /* rewind the pointer as implicit channel configuration maybe the case */
+ pInputStream->usedBits -= (LEN_TAG + LEN_PROFILE + LEN_SAMP_IDX);
+
+ return (1); /* mismatch cannot happen */
+ }
+
+
+ /*
+ * Retrieve the number of element lists for each of
+ * front, side, back, lfe, data, and coupling.
+ *
+ * For two-channel stereo or mono, only the data in the front needs
+ * to be saved. However, ALL fields need to be skipped over in some
+ * fashion. Also, the number of elements needs to be temporarily saved
+ * to call get_ele_list(). If that function was changed to pass in
+ * the number of points to be read, the memory set aside inside the
+ * ProgConfig structure could be removed.
+ */
+
+ /*
+ * The next six function calls could be combined into one, then use
+ * shifts and masks to retrieve the individual fields.
+ */
+ temp =
+ get9_n_lessbits(
+ LEN_NUM_ELE,
+ pInputStream);
+
+ pScratchPCE->front.num_ele = temp;
+
+ /* Needed only to read in the element list. */
+ temp =
+ get9_n_lessbits(
+ LEN_NUM_ELE,
+ pInputStream);
+
+ pScratchPCE->side.num_ele = temp;
+
+ /* Needed only to read in the element list. */
+ temp =
+ get9_n_lessbits(
+ LEN_NUM_ELE,
+ pInputStream);
+
+ pScratchPCE->back.num_ele = temp;
+
+ /* Needed only to read in the element list. */
+ temp =
+ get9_n_lessbits(
+ LEN_NUM_LFE,
+ pInputStream);
+
+ pScratchPCE->lfe.num_ele = temp;
+
+ /* Needed only to read in the element list. */
+ temp =
+ get9_n_lessbits(
+ LEN_NUM_DAT,
+ pInputStream);
+ pScratchPCE->data.num_ele = temp;
+
+ /* Needed only to read in the element list. */
+ temp =
+ get9_n_lessbits(
+ LEN_NUM_CCE,
+ pInputStream);
+
+ pScratchPCE->coupling.num_ele = temp;
+
+ /*
+ * Read in mix down data.
+ *
+ * Whether these fields can be removed and have proper operation
+ * will be determined at a later date.
+ */
+
+ /* Read presence of mono_mix */
+ flag =
+ get1bits(/* LEN_MIX_PRES,*/
+ pInputStream);
+
+ pScratchPCE->mono_mix.present = flag;
+
+ if (flag != FALSE)
+ {
+ temp =
+ get9_n_lessbits(
+ LEN_TAG,
+ pInputStream);
+
+ pScratchPCE->mono_mix.ele_tag = temp;
+
+ } /* end if (flag != FALSE) */
+
+ /* Read presence of stereo mix */
+ flag =
+ get1bits(/* LEN_MIX_PRES,*/
+ pInputStream);
+
+ pScratchPCE->stereo_mix.present = flag;
+
+ if (flag != FALSE)
+ {
+ temp =
+ get9_n_lessbits(
+ LEN_TAG,
+ pInputStream);
+
+ pScratchPCE->stereo_mix.ele_tag = temp;
+
+ } /* end if (flag != FALSE) */
+
+ /* Read presence of matrix mix */
+ flag =
+ get1bits(/* LEN_MIX_PRES,*/
+ pInputStream);
+
+ pScratchPCE->matrix_mix.present = flag;
+
+ if (flag != FALSE)
+ {
+ temp =
+ get9_n_lessbits(
+ LEN_MMIX_IDX,
+ pInputStream);
+
+ pScratchPCE->matrix_mix.ele_tag = temp;
+
+ temp =
+ get1bits(/* LEN_PSUR_ENAB,*/
+ pInputStream);
+
+ pScratchPCE->matrix_mix.pseudo_enab = temp;
+
+ } /* end if (flag != FALSE) */
+
+ /*
+ * Get each of the element lists. Only the front information will be
+ * used for the PV decoder, but the usedBits field of pInputStream must
+ * be advanced appropriately.
+ *
+ * This could be optimized by advancing the bit stream for the
+ * elements that do not need to be read.
+ */
+ get_ele_list(
+ &pScratchPCE->front,
+ pInputStream,
+ TRUE);
+
+ get_ele_list(
+ &pScratchPCE->side,
+ pInputStream,
+ TRUE);
+
+ get_ele_list(
+ &pScratchPCE->back,
+ pInputStream,
+ TRUE);
+
+ get_ele_list(
+ &pScratchPCE->lfe,
+ pInputStream,
+ FALSE);
+
+ get_ele_list(
+ &pScratchPCE->data,
+ pInputStream,
+ FALSE);
+
+ get_ele_list(
+ &pScratchPCE->coupling,
+ pInputStream,
+ TRUE);
+
+ /*
+ * The standard requests a byte alignment before reading in the
+ * comment. This can be done because LEN_COMMENT_BYTES == 8.
+ */
+ byte_align(pInputStream);
+
+ numChars =
+ get9_n_lessbits(
+ LEN_COMMENT_BYTES, pInputStream);
+
+ /*
+ * Ignore the comment - it requires 65 bytes to store (or worse on DSP).
+ * If this field is restored, make sure to append a trailing '\0'
+ */
+ for (i = numChars; i > 0; i--)
+ {
+ pScratchPCE->comments[i] = (Char) get9_n_lessbits(LEN_BYTE,
+ pInputStream);
+
+ } /* end for */
+
+ if (pVars->current_program < 0)
+ {
+ /*
+ * If this is the first PCE, it becomes the current, regardless of
+ * its tag number.
+ */
+ pVars->current_program = tag;
+
+ } /* end if (pVars->current_program < 0) */
+
+
+ if (tag == (UInt)pVars->current_program)
+ {
+ /*
+ * This branch is reached under two conditions:
+ * 1) This is the first PCE found, it was selected in the above if
+ * block. In all encoders found thus far, the tag value has been
+ * zero.
+ * 2) A PCE has been sent by the encoder with a tag that matches the
+ * the first one sent. It will then be re-read. No encoder found
+ * thus far re-sends a PCE, when looking at ADIF files.
+ *
+ * Regardless, the temporary PCE will now be copied into the
+ * the one official program configuration.
+ */
+ pv_memcpy(
+ &pVars->prog_config,
+ pScratchPCE,
+ sizeof(ProgConfig));
+
+ /* enter configuration into MC_Info structure */
+ status =
+ set_mc_info(
+ &pVars->mc_info,
+ (tMP4AudioObjectType)(pVars->prog_config.profile + 1),
+ pVars->prog_config.sampling_rate_idx,
+ pVars->prog_config.front.ele_tag[0],
+ pVars->prog_config.front.ele_is_cpe[0],
+ pVars->winmap,
+ pVars->SFBWidth128);
+
+ } /* end if (tag == pVars->current_program) */
+
+ return (status);
+}
+
diff --git a/media/libstagefright/codecs/aacdec/get_prog_config.h b/media/libstagefright/codecs/aacdec/get_prog_config.h
new file mode 100644
index 0000000..646ba46
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_prog_config.h
@@ -0,0 +1,89 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_prog_config.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for get_prog_config.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_PROG_CONFIG_H
+#define GET_PROG_CONFIG_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_progconfig.h"
+#include "s_tdec_int_file.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+Int get_prog_config(
+ tDec_Int_File *pVars,
+ ProgConfig *pTempPCE);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/get_pulse_data.cpp b/media/libstagefright/codecs/aacdec/get_pulse_data.cpp
new file mode 100644
index 0000000..f9c24f4
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_pulse_data.cpp
@@ -0,0 +1,286 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_pulse_data.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: Put into PV format
+
+ Description: 1) Change loop to use pointers.
+ 2) Rename to from get_nec_nc to get_pulse_data
+
+ Description: Changes per code review
+ 1) Fix pathname
+ 2) Read in two fields to save call to getbits
+ 3) Change how pPulseInfo->number_pulse is stored.
+
+ Description: Placed typecast to Int in places where UInt->Int
+
+ Description: Replace some instances of getbits to get9_n_lessbits
+ when the number of bits read is 9.
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pInputStream = pointer to a BITS structure, used by the function getbits
+ to provide data. Data type pointer to BITS structure
+
+ pPulseInfo = pointer to pulse data structure to be filled with data
+ concerning pulses in the frequency domain.
+ Data type pointer to PulseInfo
+
+ Local Stores/Buffers/Pointers Needed: None
+
+ Global Stores/Buffers/Pointers Needed: None
+
+ Outputs:
+ status = return value, zero signifies success, non-zero otherwise.
+ Presently this function only returns a success, error
+ checking may be added later.
+ Data type Int.
+
+ Pointers and Buffers Modified:
+
+ pPulseInfo contents are updated with pulse information. Specifically,
+ pPulseInfo->number_pulse with the number of pulses found, and
+ pPulseInfo->pulse_start_sfb is set to the first scale factor band.
+ Then pPulseInfo->pulse_offset and pPulseInfo->pulse_amp are filled
+ with data. For these array, only the number of pulses defined will be
+ set, those values beyond the number of pulses will retain their previous
+ value and should not be read from.
+ Note: The value in pPulseInfo->number_pulse is different by a value of
+ one from the original ISO code.
+
+ pInputBuffer contents are updated to the next location to be read from
+ the input stream.
+
+ Local Stores Modified: None
+
+ Global Stores Modified: None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function fills in the pulse data structure with information to be used
+ later for restoring pulses in the spectrum.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function shall not use global or static variables.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 13818-7:1997 Titled "Information technology - Generic coding
+ of moving pictures and associated audio information - Part 7: Advanced
+ Audio Coding (AAC)", Table 6.17 - Syntax of pulse_data(),
+ page 15, and section 9.3 "Decoding process", starting on page 41.
+
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ status = SUCCESS;
+
+ CALL getbits(neededBits = LEN_PULSE_NPULSE + LEN_PULSE_ST_SFB,
+ pInputStream = pInputStream)
+ MODIFYING(*pInputStream)
+ RETURNING(temp)
+
+ pPulseInfo->number_pulse = 1 + (temp >> LEN_PULSE_ST_SFB);
+ pPulseInfo->pulse_start_sfb = temp & ((1 << LEN_PULSE_ST_SFB) - 1);
+
+ pPulseOffset = &pPulseInfo->pulse_offset[0];
+ pPulseAmp = &pPulseInfo->pulse_amp[0];
+
+ FOR (i = PulseInfo->number_pulse; i > 0; i--)
+ CALL getbits(neededBits = LEN_PULSE_POFF + LEN_PULSE_PAMP,
+ pInputStream = pInputStream)
+ MODIFYING(*pInputStream)
+ RETURNING(temp)
+
+ *pPulseOffset++ = temp >> LEN_PULSE_PAMP;
+ *pPulseAmp++ = temp & ((1 << LEN_PULSE_PAMP) - 1);
+ END FOR
+
+ MODIFYING (*pInputStream)
+ MODIFYING (*pPulseInfo)
+
+ RETURN status
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+#include "ibstream.h"
+#include "s_pulseinfo.h"
+#include "s_bits.h"
+#include "e_rawbitstreamconst.h"
+#include "get_pulse_data.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Int get_pulse_data(
+ PulseInfo *pPulseInfo,
+ BITS *pInputStream)
+{
+ Int i;
+ Int *pPulseOffset;
+ Int *pPulseAmp;
+ Int status = SUCCESS;
+ UInt temp;
+
+ /*
+ * Read in both field fields at once to save cycles. These are the
+ * original lines of code:
+ * pPulseInfo->number_pulse = getbits(LEN_PULSE_NPULSE, pInputStream);
+ * pPulseInfo->pulse_start_sfb = getbits(LEN_PULSE_ST_SFB, pInputStream);
+ */
+
+ temp =
+ get9_n_lessbits(
+ LEN_PULSE_NPULSE + LEN_PULSE_ST_SFB,
+ pInputStream);
+
+ pPulseInfo->number_pulse = (Int)(1 + (temp >> LEN_PULSE_ST_SFB));
+ pPulseInfo->pulse_start_sfb = (Int)(temp & ((1 << LEN_PULSE_ST_SFB) - 1));
+
+ pPulseOffset = &pPulseInfo->pulse_offset[0];
+ pPulseAmp = &pPulseInfo->pulse_amp[0];
+
+ /*
+ * This loop needs to count one more than the number read in from
+ * the bitstream - look at reference [1].
+ */
+
+ for (i = pPulseInfo->number_pulse; i > 0; i--)
+ {
+ /*
+ * Read in both fields. Original lines:
+ * *pPulseOffset++ = getbits(LEN_PULSE_POFF, pInputStream);
+ * *pPulseAmp++ = getbits(LEN_PULSE_PAMP, pInputStream);
+ */
+
+ temp =
+ get9_n_lessbits(
+ LEN_PULSE_POFF + LEN_PULSE_PAMP,
+ pInputStream);
+
+ *pPulseOffset++ = (Int)(temp >> LEN_PULSE_PAMP);
+
+ *pPulseAmp++ = (Int)(temp & ((1 << LEN_PULSE_PAMP) - 1));
+ }
+
+ return (status);
+}
+
diff --git a/media/libstagefright/codecs/aacdec/get_pulse_data.h b/media/libstagefright/codecs/aacdec/get_pulse_data.h
new file mode 100644
index 0000000..267f534
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_pulse_data.h
@@ -0,0 +1,100 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_pulse_data.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Change structure name.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for get_pulse_data.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_PULSE_DATA_H
+#define GET_PULSE_DATA_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_pulseinfo.h"
+#include "s_bits.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Int get_pulse_data(
+ PulseInfo *pPulseInfo,
+ BITS *pInputStream);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* GET_PULSE_DATA_H */
+
diff --git a/media/libstagefright/codecs/aacdec/get_sbr_bitstream.cpp b/media/libstagefright/codecs/aacdec/get_sbr_bitstream.cpp
new file mode 100644
index 0000000..b6ec365
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_sbr_bitstream.cpp
@@ -0,0 +1,183 @@
+/* ------------------------------------------------------------------
+ * 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: get_sbr_bitstream.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ INPUT
+
+ SBRDECODER self,
+ SBRBITSTREAM * stream,
+ float *timeData,
+ int numChannels
+
+ OUTPUT
+
+ errorCode, noError if successful
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ sbr decoder processing, set up SBR decoder phase 2 in case of
+ different cotrol data
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#ifdef AAC_PLUS
+
+#include "get_sbr_bitstream.h"
+#include "pv_audio_type_defs.h"
+#include "sbr_crc_check.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void get_sbr_bitstream(SBRBITSTREAM *sbrBitStream, BITS *pInputStream)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+
+ Int32 count;
+ Int32 esc_count;
+ Int32 Extention_Type;
+ Int32 i;
+
+ count = get9_n_lessbits(LEN_F_CNT, pInputStream);
+ if (count == 15)
+ {
+ esc_count = get9_n_lessbits(LEN_F_ESC, pInputStream);
+ count = esc_count + 14;
+ }
+
+
+
+ Extention_Type = get9_n_lessbits(LEN_F_CNT, pInputStream);
+
+
+ if (((Extention_Type == SBR_EXTENSION) || (Extention_Type == SBR_EXTENSION_CRC))
+ && (count < MAXSBRBYTES) && (count) && (sbrBitStream->NrElements < MAXNRELEMENTS))
+ {
+
+ sbrBitStream->sbrElement[sbrBitStream->NrElements].ExtensionType = Extention_Type;
+ sbrBitStream->sbrElement[sbrBitStream->NrElements].Payload = count;
+ sbrBitStream->sbrElement[sbrBitStream->NrElements].Data[0] = (UChar) get9_n_lessbits(LEN_F_CNT, pInputStream);
+ for (i = 1 ; i < count ; i++)
+ {
+ sbrBitStream->sbrElement[sbrBitStream->NrElements].Data[i] = (UChar) get9_n_lessbits(8, pInputStream);
+ }
+
+ sbrBitStream->NrElements += 1;
+
+ }
+ else
+ {
+ pInputStream->usedBits += (count - 1) * LEN_BYTE;
+ pInputStream->usedBits += 4; /* compenste for LEN_F_CNT (=4) bits read for Extention_Type */
+
+ }
+}
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/get_sbr_bitstream.h b/media/libstagefright/codecs/aacdec/get_sbr_bitstream.h
new file mode 100644
index 0000000..8094b1a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_sbr_bitstream.h
@@ -0,0 +1,126 @@
+/* ------------------------------------------------------------------
+ * 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: get_sbr_bitstream.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+ $Id: ct_envcalc.h,v 1.3 2002/11/29 16:11:49 kaehleof Exp $
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_SBR_BITSTREAM_H
+#define GET_SBR_BITSTREAM_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "s_bits.h"
+#include "ibstream.h"
+#include "e_rawbitstreamconst.h"
+#include "s_sbrbitstream.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void get_sbr_bitstream(SBRBITSTREAM *sbrBitStream,
+ BITS *pInputStream);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/get_sbr_startfreq.cpp b/media/libstagefright/codecs/aacdec/get_sbr_startfreq.cpp
new file mode 100644
index 0000000..38ddc0b
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_sbr_startfreq.cpp
@@ -0,0 +1,183 @@
+/* ------------------------------------------------------------------
+ * 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: get_sbr_startfreq.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "get_sbr_startfreq.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const Int v_offset[7][16] =
+{
+ { -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7},
+ { -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13},
+ { -5, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16},
+ { -6, -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16},
+ { -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20},
+ { -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24},
+ { 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24, 28, 33}
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int get_sbr_startfreq(const Int32 fs,
+ const Int32 start_freq)
+{
+ Int k0_min = 0;
+ Int32 index;
+
+
+ switch (fs)
+ {
+ case 16000:
+ index = 0;
+ k0_min = 24;
+ break;
+ case 22050:
+ index = 1;
+ k0_min = 17;
+ break;
+ case 24000:
+ index = 2;
+ k0_min = 16;
+ break;
+ case 32000:
+ index = 3;
+ k0_min = 16;
+ break;
+ case 44100:
+ index = 4;
+ k0_min = 12;
+ break;
+ case 48000:
+ index = 4;
+ k0_min = 11;
+ break;
+ case 64000:
+ index = 4;
+ k0_min = 10;
+ break;
+ case 88200:
+ case 96000:
+ index = 5;
+ k0_min = 7;
+ break;
+
+ default:
+ index = 6;
+ }
+ return (k0_min + v_offset[index][start_freq]);
+
+}
+
+
+
diff --git a/media/libstagefright/codecs/aacdec/get_sbr_startfreq.h b/media/libstagefright/codecs/aacdec/get_sbr_startfreq.h
new file mode 100644
index 0000000..10fa160
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_sbr_startfreq.h
@@ -0,0 +1,85 @@
+/* ------------------------------------------------------------------
+ * 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: get_sbr_startfreq.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_SBR_STARTFREQ_H
+#define GET_SBR_STARTFREQ_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+Int get_sbr_startfreq(const Int32 fs,
+ const Int32 start_freq);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/get_sbr_stopfreq.cpp b/media/libstagefright/codecs/aacdec/get_sbr_stopfreq.cpp
new file mode 100644
index 0000000..e32c61d
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_sbr_stopfreq.cpp
@@ -0,0 +1,190 @@
+/* ------------------------------------------------------------------
+ * 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: get_sbr_stopfreq.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ if(fs < 32000)
+ {
+ k1_min = (Int) ( ( (float) (6000 * 2 * 64) / fs ) + 0.5 );
+ }
+ else
+ {
+ if (fs < 64000)
+ {
+ k1_min = (Int) ( ( (float) (8000 * 2 * 64) / fs ) + 0.5 );
+ }
+ else
+ {
+ k1_min = (Int) ( ((float) (10000 * 2 * 64) / fs ) + 0.5);
+ }
+ }
+
+ return((Int)( k1_min * pow( 64.0 / k1_min,(stop_freq)/13.0) + 0.5));
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#include "get_sbr_stopfreq.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+const UChar sbr_stopfreq_tbl[6][13] =
+{
+
+ { 21, 23, 25, 27, 29, 32, 35, 38, 41, 45, 49, 54, 59}, /* 48000 */
+ { 23, 25, 27, 29, 31, 34, 37, 40, 43, 47, 51, 55, 59}, /* 44100 */
+ { 32, 34, 36, 38, 40, 42, 44, 46, 49, 52, 55, 58, 61}, /* 32000 and 24000 */
+ { 35, 36, 38, 40, 42, 44, 46, 48, 50, 52, 55, 58, 61}, /* 22050 */
+ { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 62} /* 16000 */
+
+};
+
+Int get_sbr_stopfreq(const Int32 fs,
+ const Int32 stop_freq)
+{
+
+ Int i;
+
+ switch (fs)
+ {
+ case 48000:
+ i = 0;
+ break;
+
+ case 32000:
+ case 24000:
+ i = 2;
+ break;
+
+ case 22050:
+ i = 3;
+ break;
+
+ case 16000:
+ i = 4;
+ break;
+
+ case 44100:
+ default:
+ i = 1;
+ break;
+ }
+
+ return((Int)sbr_stopfreq_tbl[i][stop_freq]);
+
+}
+
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/get_sbr_stopfreq.h b/media/libstagefright/codecs/aacdec/get_sbr_stopfreq.h
new file mode 100644
index 0000000..341a3d4
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_sbr_stopfreq.h
@@ -0,0 +1,85 @@
+/* ------------------------------------------------------------------
+ * 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: get_sbr_stopfreq.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+ ----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_SBR_STOPFREQ_H
+#define GET_SBR_STOPFREQ_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+Int get_sbr_stopfreq(const Int32 fs,
+ const Int32 stop_freq);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/get_sign_bits.h b/media/libstagefright/codecs/aacdec/get_sign_bits.h
new file mode 100644
index 0000000..445d2f2
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_sign_bits.h
@@ -0,0 +1,99 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_sign_bits.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Update comments for the structure
+
+ Description: Change include file. Above description probably from another
+ header file.
+
+ Description: Fix pathname above
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for the function get_sign_bits()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_SIGN_BITS_H
+#define GET_SIGN_BITS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "ibstream.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void get_sign_bits(
+ Int q[],
+ BITS *pInputStream,
+ const Int q_len
+);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* GET_SIGN_BITS_H */
+
+
diff --git a/media/libstagefright/codecs/aacdec/get_tns.cpp b/media/libstagefright/codecs/aacdec/get_tns.cpp
new file mode 100644
index 0000000..e0b021b
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_tns.cpp
@@ -0,0 +1,573 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_tns.c
+
+ Date: 10/25/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: Brought code in-line with PV standards. Some minor
+ optimizations (count-down for loops, etc.) were made.
+
+ Description: Made cosmetic changes as suggested during review. Also,
+ changed calculation of s_mask and n_mask from table-based to being
+ calculated based on res_index. Also, the flag coef_res was changed
+ from having a range of [3,4] to having a range of [0,1], which corresponds
+ exactly with the true value that is passed via the bitstream.
+
+ Description: Modified to use more efficient TNS memory structure.
+
+ Description: Updated to reflect more efficient usage of memory by the TNS
+ filters.
+
+ Description: Updated the SW template to include the full pathname to the
+ source file and a slightly modified copyright header.
+
+ Description: Moved pInputStream to be the 2nd parameter, for a slight
+ optimization on some platforms.
+
+ Description: Moved pSfbTop outside of the loops, since its value does
+ not change.
+
+ Description: Replace some instances of getbits to get1bits
+ when only 1 bit is read.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ FrameInfo *pFrameInfo
+ Pointer to structure that holds information about each block.
+ (long block flag,
+ number of subblocks,
+ scalefactor bands per subblock, etc.)
+
+ BITS *pInputStream
+ Pointer to a BITS structure that is
+ passed on to function getbits to pull information from the bitstream.
+
+ TNS_Frame_info *pTnsFrameInfo
+ Pointer to filter data structure - to be populated by this function.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ TNS_frame_info *pTnsFrameInfo
+
+ pTnsFrameInfo->n_filt = Number of tns filters to be applied to the data.
+
+ pTnsFrameInfo->filt[]->order = The order of each individual TNS filter.
+
+ pTnsFrameInfo->filt[]->coef_res = The resolution of the filter coefficients
+
+ pTnsFrameInfo->filt[]->start_band = start of spectral band
+
+ pTnsFrameInfo->filt[]->stop_band = end of spectral band
+
+ pTnsFrameInfo->filt[]->coef[] = Each filter's coefficients are filled with
+ data read from the input bitstream.
+
+ pTnsFrameInfo->filt[]->direction = A flag is set for each TNS filter.
+
+ If the direction flag (on the bitstream) = 0, then the filter
+ is applied to the block of spectral data in normal (upward) fashion.
+
+ If the direction flag (on the bitstream) = 1, then the filter
+ is applied in a reverse (downward) fashion.
+ (Starting with the last element in the block of data.)
+
+ The value stored in filt[]->direction maps the values [0,1] to [1,-1] for
+ a more intuitive storage of this flag's meaning.
+
+ Local Stores Modified:
+
+ Global Stores Modified:
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function reads the TNS filter information from the bitstream, and stores
+ the filter order, LPC coefficients, and the number of TNS filters to
+ be applied in the structure TNS_frame_info.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This code should match the ISO code in functionality, with the exception
+ that coef_res has range of [0,1] (PV code) instead of [3,4] (ISO code)
+
+ coef_res is only used by tns_decode_coef.
+
+------------------------------------------------------------------------------
+ REFERENCES
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.6.8 (Temporal Noise Shaping)
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "get_tns.h"
+#include "s_mc_info.h"
+#include "s_frameinfo.h"
+#include "s_tnsfilt.h"
+#include "s_tns_frame_info.h"
+#include "s_bits.h"
+#include "ibstream.h"
+#include "e_window_sequence.h"
+#include "e_progconfigconst.h"
+
+#include "tns_decode_coef.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#define SCALE_FACTOR_BAND_OFFSET(x) ( ((x) > 0) ? pSFB_top[(x)-1] : 0 )
+#define MINIMUM(x,y) ( ((x) < (y)) ? (x) : (y) )
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+/*
+ * The entries in the ensuing tables provide the maximum permissable
+ * number of scalefactor bands for each TNS filter. This value is effected
+ * by the sampling rate, and window type.
+ */
+
+const Int tns_max_bands_tbl_long_wndw[(1<<LEN_SAMP_IDX)] =
+ {31, /* 96000 Hz */
+ 31, /* 88200 Hz */
+ 34, /* 64000 Hz */
+ 40, /* 48000 Hz */
+ 42, /* 44100 Hz */
+ 51, /* 32000 Hz */
+ 46, /* 24000 Hz */
+ 46, /* 22050 Hz */
+ 42, /* 16000 Hz */
+ 42, /* 12000 Hz */
+ 42, /* 11025 Hz */
+ 39, /* 8000 Hz */
+ 0,
+ 0,
+ 0,
+ 0
+ };
+
+const Int tns_max_bands_tbl_short_wndw[(1<<LEN_SAMP_IDX)] =
+ {9, /* 96000 Hz */
+ 9, /* 88200 Hz */
+ 10, /* 64000 Hz */
+ 14, /* 48000 Hz */
+ 14, /* 44100 Hz */
+ 14, /* 32000 Hz */
+ 14, /* 24000 Hz */
+ 14, /* 22050 Hz */
+ 14, /* 16000 Hz */
+ 14, /* 12000 Hz */
+ 14, /* 11025 Hz */
+ 14, /* 8000 Hz */
+ 0,
+ 0,
+ 0,
+ 0
+ };
+
+/*
+ * For completeness, here are the table entries for object types that make
+ * use of PQF filter bank. We do not currently support this; these are
+ * given here only to ease future implementation.
+ *
+ * const Int tns_max_bands_tbl_long_wndw_PQF[(1<<LEN_SAMP_IDX)] =
+ * {28, ; 96000
+ * 28, ; 88200
+ * 27, ; 64000
+ * 26, ; 48000
+ * 26, ; 44100
+ * 26, ; 32000
+ * 29, ; 24000
+ * 29, ; 22050
+ * 23, ; 16000
+ * 23, ; 12000
+ * 23, ; 11025
+ * 19, ; 8000
+ * 0,
+ * 0,
+ * 0,
+ * 0};
+ *
+ * const Int tns_max_bands_tbl_short_wndw_PQF[(1<<LEN_SAMP_IDX)] =
+ * {7, ; 96000
+ * 7, ; 88200
+ * 7, ; 64000
+ * 6, ; 48000
+ * 6, ; 44100
+ * 6, ; 32000
+ * 7, ; 24000
+ * 7, ; 22050
+ * 8, ; 16000
+ * 8, ; 12000
+ * 8, ; 11025
+ * 7, ; 8000
+ * 0,
+ * 0,
+ * 0,
+ * 0};
+ */
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void get_tns(
+ const Int max_bands,
+ BITS * const pInputStream,
+ const WINDOW_SEQUENCE wnd_seq,
+ const FrameInfo * const pFrameInfo,
+ const MC_Info * const pMC_Info,
+ TNS_frame_info * const pTnsFrameInfo,
+ Int32 scratchTnsDecCoefMem[])
+{
+
+ const Int16 * const pSFB_top = pFrameInfo->win_sfb_top[0];
+
+ Int f;
+ Int t;
+ Int win;
+ UInt tempInt;
+
+ Int num_filt_bits;
+ Int num_order_bits;
+ Int num_start_band_bits;
+
+ Int top;
+ Int res;
+ Int res_index;
+ Int compress;
+
+ Int sfb_per_win;
+
+ Int32 *pLpcCoef;
+ Int32 *pStartLpcCoef;
+ Int s_mask;
+ Int n_mask;
+
+ Int tns_bands;
+ UInt max_order;
+ Int coef_res;
+
+
+ TNSfilt *pFilt;
+
+ if (wnd_seq != EIGHT_SHORT_SEQUENCE)
+ {
+ num_filt_bits = 2;
+ num_order_bits = 5;
+ num_start_band_bits = 6;
+
+ tns_bands = tns_max_bands_tbl_long_wndw[pMC_Info->sampling_rate_idx];
+
+ /*
+ * Definition from 14496-3:1999 doc. Our first encoder follows this rule,
+ * later encoders don't
+ */
+
+ if (pMC_Info->sampling_rate_idx > 4) /* if (sampling_rate <= 32000 */
+ {
+ max_order = 20;
+ }
+ else
+ {
+ max_order = 12;
+ }
+ }
+ else
+ {
+ num_filt_bits = 1;
+ num_order_bits = 3;
+ num_start_band_bits = 4;
+
+ tns_bands = tns_max_bands_tbl_short_wndw[pMC_Info->sampling_rate_idx];
+
+ max_order = 7;
+ }
+
+ /*
+ * After this branch, tns_bands will be equal to the minimum of
+ * the passed in variable, nbands, and the result from the
+ * tns_max_bands_tbl
+ */
+
+ if (max_bands < tns_bands)
+ {
+ tns_bands = max_bands;
+ }
+
+ sfb_per_win = pFrameInfo->sfb_per_win[0];
+
+ win = 0;
+
+ pLpcCoef = pTnsFrameInfo->lpc_coef;
+
+ pFilt = pTnsFrameInfo->filt;
+
+ do
+ {
+ tempInt = get9_n_lessbits(num_filt_bits,
+ pInputStream);
+
+ pTnsFrameInfo->n_filt[win] = tempInt;
+
+ if (tempInt != 0)
+ {
+ /*
+ * coef_res = [0, 1]
+ * Switch between a resolution of 3 and 4 bits respectively
+ *
+ * if coef_res = 0, the coefficients have a range of
+ *
+ * -4 -3 -2 -1 0 1 2 3
+ *
+ * if coef_res = 1, the coefficients have a range of
+ *
+ * -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7
+ *
+ * The arrays in ./src/tns_tab.c are completely based on
+ * the value of coef_res.
+ */
+ res = get1bits(
+ pInputStream);
+
+ /* res is post-incremented for correct calculation of res_index */
+ coef_res = res++;
+
+ top = sfb_per_win;
+
+ for (f = pTnsFrameInfo->n_filt[win]; f > 0; f--)
+ {
+ tempInt = MINIMUM(top, tns_bands);
+
+ pFilt->stop_coef = SCALE_FACTOR_BAND_OFFSET(tempInt);
+
+ pFilt->stop_band = tempInt;
+
+ top -= get9_n_lessbits(num_start_band_bits,
+ pInputStream);
+
+ tempInt = MINIMUM(top, tns_bands);
+
+ pFilt->start_coef = SCALE_FACTOR_BAND_OFFSET(tempInt);
+
+ pFilt->start_band = tempInt;
+
+ tempInt = get9_n_lessbits(num_order_bits,
+ pInputStream);
+
+ pFilt->order = tempInt;
+
+ if (tempInt != 0)
+ {
+ if (tempInt > max_order)
+ {
+ pFilt->order = max_order;
+ }
+
+ /*
+ * This maps the bitstream's [0,1] to
+ * pFilt->direction = [1,-1]
+ */
+
+ tempInt = get1bits(pInputStream);
+
+ pFilt->direction = (-(Int)tempInt) | 0x1;
+
+ /*
+ * compress = [0,1]
+ * If compress is true, the MSB has
+ * been omitted from transmission (Ref. 1)
+ *
+ * For coef_res = 0, this limits the range of
+ * transmitted coefficients to...
+ *
+ * -2 -1 0 1
+ *
+ * For coef_res = 1, the coefficients have
+ * a range of...
+ *
+ * -4 -3 -2 -1 0 1 2 3
+ */
+ compress = get1bits(pInputStream);
+
+ /*
+ * res has a range of [1,2]
+ * compress has a range of [0,1]
+ * So (res - compress) has range [0,2];
+ */
+ res_index = res - compress;
+
+ s_mask = 2 << res_index;
+
+ /*
+ * If res_index = 0, grab 2 bits of data
+ * If res_index = 1, grab 3 bits of data
+ * If res_index = 2, grab 4 bits of data
+ */
+ res_index += 2;
+
+ pStartLpcCoef = pLpcCoef;
+
+ for (t = pFilt->order; t > 0; t--)
+ {
+ /*
+ * These are the encoded coefficients, which will
+ * later be decoded into LPC coefficients by
+ * the function tns_decode_coef()
+ */
+ tempInt = get9_n_lessbits(res_index,
+ pInputStream);
+
+ n_mask = -((Int)tempInt & s_mask);
+
+ /*
+ * n_mask is used to sign_extend the
+ * value, if it is negative.
+ *
+ */
+ *(pLpcCoef++) = tempInt | n_mask;
+ }
+
+ /* Decode the TNS coefficients */
+
+ tempInt = pFilt->stop_coef - pFilt->start_coef;
+
+ if (tempInt > 0)
+ {
+ pFilt->q_lpc =
+ tns_decode_coef(
+ pFilt->order,
+ coef_res,
+ pStartLpcCoef,
+ scratchTnsDecCoefMem);
+ }
+
+ } /* if (pTnsFilt->order != 0) */
+
+ pFilt++;
+
+ } /* END for (f=pTnsInfo->n_filt; f>0; f--, pTnsFilt++) */
+
+ } /* if (pTnsInfo->n_filt != 0) */
+
+ win++;
+
+ }
+ while (win < pFrameInfo->num_win);
+
+ return;
+
+} /* get_tns */
diff --git a/media/libstagefright/codecs/aacdec/get_tns.h b/media/libstagefright/codecs/aacdec/get_tns.h
new file mode 100644
index 0000000..731484f
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/get_tns.h
@@ -0,0 +1,124 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: get_tns.h
+
+ Author:
+ Date: 03/08/2001
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ (1) Modified to include the lines...
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ (2) Updated the copyright header.
+
+ Description: Modified to include updated function declaration, which reflects
+ the combination of the get_tns and tns_setup_filter routines. Also, moved
+ pInputStream to be the 2nd parameter, for a slight optimization.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes the function definition for get_tns.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GET_TNS_H
+#define GET_TNS_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_frameinfo.h"
+#include "s_mc_info.h"
+#include "s_tns_frame_info.h"
+#include "s_bits.h"
+#include "e_window_sequence.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void get_tns(
+ const Int max_bands,
+ BITS * const pInputStream,
+ const WINDOW_SEQUENCE wnd_seq,
+ const FrameInfo * const pFrameInfo,
+ const MC_Info * const pMC_Info,
+ TNS_frame_info * const pTnsFrameInfo,
+ Int32 scratchTnsDecCoefMem[]);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GET_TNS_H */
+
+
diff --git a/media/libstagefright/codecs/aacdec/getbits.h b/media/libstagefright/codecs/aacdec/getbits.h
new file mode 100644
index 0000000..e854be5
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/getbits.h
@@ -0,0 +1,346 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: getbits.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Update comments for the structure
+
+ Description: Move structur to another file
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for the function getbits().
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GETBITS_H
+#define GETBITS_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "ibstream.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+#define INBUF_ARRAY_INDEX_SHIFT (3)
+#define INBUF_BIT_WIDTH (1<<(INBUF_ARRAY_INDEX_SHIFT))
+#define INBUF_BIT_MODULO_MASK ((INBUF_BIT_WIDTH)-1)
+
+#define MAX_GETBITS (25)
+
+#define CHECK_INPUT_BUFFER_LIMITS 1
+
+ __inline UInt32 getbits(
+ const UInt neededBits,
+ BITS *pInputStream)
+ {
+ UInt32 returnValue = 0;
+ UInt offset;
+ UInt bitIndex;
+ UChar *pElem; /* Needs to be same type as pInput->pBuffer */
+
+ offset = (pInputStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
+
+ pElem = pInputStream->pBuffer + offset;
+
+#if CHECK_INPUT_BUFFER_LIMITS
+
+ offset = pInputStream->inputBufferCurrentLength - offset;
+ /* check if access to input buffer does not go beyond boundaries */
+ if (offset > 3)
+ {
+ returnValue = (((UInt32) * (pElem)) << 24) |
+ (((UInt32) * (pElem + 1)) << 16) |
+ (((UInt32) * (pElem + 2)) << 8) |
+ ((UInt32) * (pElem + 3));
+ }
+ else /* then access only available bytes */
+ {
+ /* Access to the bitstream beyond frame boundaries are not allowed,
+ * Here, only what was available before the end of the frame will
+ * be processed. Non-accessible bytes will be filled in with zeros.
+ * Zero values guarantees that the data structures are filled in with values
+ * that eventually will signal an error (like invalid parameters) or that allow
+ * completion of the parsing routine.
+ * Overrun is detected on file pvmp4audiodecodeframe.cpp.
+ */
+ switch (offset)
+ {
+ case 3:
+ returnValue = (((UInt32) * (pElem + 2)) << 8);
+ case 2:
+ returnValue |= (((UInt32) * (pElem + 1)) << 16);
+ case 1:
+ returnValue |= (((UInt32) * (pElem)) << 24);
+ default:
+ break;
+ }
+ }
+
+
+#else
+
+ returnValue = (((UInt32) * (pElem)) << 24) |
+ (((UInt32) * (pElem + 1)) << 16) |
+ (((UInt32) * (pElem + 2)) << 8) |
+ ((UInt32) * (pElem + 3));
+#endif
+
+ /* Remove extra high bits by shifting up */
+ bitIndex = (UInt)((pInputStream->usedBits) & INBUF_BIT_MODULO_MASK);
+
+ /* This line is faster way to mask off the high bits. */
+ returnValue = returnValue << (bitIndex);
+
+ /* Move the field down. */
+ returnValue = returnValue >> (32 - neededBits);
+
+ pInputStream->usedBits += neededBits;
+
+ return (returnValue);
+
+ }
+
+
+
+ __inline UInt get1bits(
+ BITS *pInputStream)
+ {
+ UInt returnValue;
+ UInt offset;
+ UInt bitIndex;
+ UChar *pElem; /* Needs to be same type as pInput->pBuffer */
+
+ offset = (pInputStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
+
+ pElem = pInputStream->pBuffer + offset;
+
+#if CHECK_INPUT_BUFFER_LIMITS
+ returnValue = (offset < pInputStream->inputBufferCurrentLength) ? ((UInt) * (pElem)) : 0;
+#else
+ returnValue = ((UInt32) * (pElem));
+#endif
+
+
+ /* Remove extra high bits by shifting up */
+ bitIndex = (UInt)((pInputStream->usedBits++) & INBUF_BIT_MODULO_MASK);
+
+ /* This line is faster way to mask off the high bits. */
+ returnValue = 0xFF & (returnValue << (bitIndex));
+
+ /* Move the field down. */
+
+ return ((UInt)(returnValue >> 7));
+
+ }
+
+
+
+ __inline UInt get9_n_lessbits(
+ const UInt neededBits,
+ BITS *pInputStream)
+
+ {
+ UInt returnValue;
+ UInt offset;
+ UInt bitIndex;
+ UChar *pElem; /* Needs to be same type as pInput->pBuffer */
+
+ offset = (pInputStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
+
+ pElem = pInputStream->pBuffer + offset;
+
+#if CHECK_INPUT_BUFFER_LIMITS
+
+
+ offset = pInputStream->inputBufferCurrentLength - offset;
+ /* check if access to input buffer does not go beyond boundaries */
+ if (offset > 1)
+ {
+ returnValue = (((UInt32) * (pElem)) << 8) |
+ ((UInt32) * (pElem + 1));
+ }
+ else /* then access only available bytes */
+ {
+ /* Access to the bitstream beyond frame boundaries are not allowed,
+ * Here, only what was available before the end of the frame will
+ * be processed. Non-accessible bytes will be filled in with zeros.
+ * Zero values guarantees that the data structures are filled in with values
+ * that eventually will signal an error (like invalid parameters) or that allow
+ * completion of the parsing routine.
+ * Overrun is detected on file pvmp4audiodecodeframe.cpp
+ */
+ switch (offset)
+ {
+ case 1:
+ returnValue = (((UInt32) * (pElem)) << 8);
+ break;
+ default:
+ returnValue = 0;
+ break;
+ }
+ }
+
+
+#else
+ returnValue = (((UInt32) * (pElem)) << 8) |
+ ((UInt32) * (pElem + 1)) ;
+#endif
+
+ /* Remove extra high bits by shifting up */
+ bitIndex = (UInt)((pInputStream->usedBits) & INBUF_BIT_MODULO_MASK);
+
+ pInputStream->usedBits += neededBits;
+
+ /* This line is faster way to mask off the high bits. */
+ returnValue = 0xFFFF & (returnValue << (bitIndex));
+
+ /* Move the field down. */
+
+ return (UInt)(returnValue >> (16 - neededBits));
+
+ }
+
+ __inline UInt32 get17_n_lessbits(
+ const UInt neededBits,
+ BITS *pInputStream)
+ {
+ UInt32 returnValue;
+ UInt offset;
+ UInt bitIndex;
+ UChar *pElem; /* Needs to be same type as pInput->pBuffer */
+
+ offset = (pInputStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
+
+ pElem = pInputStream->pBuffer + offset;
+
+#if CHECK_INPUT_BUFFER_LIMITS
+
+ offset = pInputStream->inputBufferCurrentLength - offset;
+ /* check if access to input buffer does not go beyond boundaries */
+
+ if (offset > 2)
+ {
+ returnValue = (((UInt32) * (pElem)) << 16) |
+ (((UInt32) * (pElem + 1)) << 8) |
+ ((UInt32) * (pElem + 2));
+ }
+ else /* then access only available bytes */
+ {
+ /* Access to the bitstream beyond frame boundaries are not allowed,
+ * Here, only what was available before the end of the frame will
+ * be processed. Non-accessible bytes will be filled in with zeros.
+ * Zero values guarantees that the data structures are filled in with values
+ * that eventually will signal an error (like invalid parameters) or that allow
+ * completion of the parsing routine.
+ * Overrun is detected on file pvmp4audiodecodeframe.cpp
+ */
+ returnValue = 0;
+ switch (offset)
+ {
+ case 2:
+ returnValue = (((UInt32) * (pElem + 1)) << 8);
+ case 1:
+ returnValue |= (((UInt32) * (pElem)) << 16);
+ default:
+ break;
+ }
+ }
+
+#else
+
+ returnValue = (((UInt32) * (pElem)) << 16) |
+ (((UInt32) * (pElem + 1)) << 8) |
+ ((UInt32) * (pElem + 2));
+#endif
+
+ /* Remove extra high bits by shifting up */
+ bitIndex = (UInt)((pInputStream->usedBits) & INBUF_BIT_MODULO_MASK);
+
+ /* This line is faster way to mask off the high bits. */
+ returnValue = 0xFFFFFF & (returnValue << (bitIndex));
+
+ /* Move the field down. */
+ returnValue = returnValue >> (24 - neededBits);
+
+ pInputStream->usedBits += neededBits;
+
+ return (returnValue);
+
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* GETBITS_H*/
+
+
diff --git a/media/libstagefright/codecs/aacdec/getfill.cpp b/media/libstagefright/codecs/aacdec/getfill.cpp
new file mode 100644
index 0000000..3c4fc4c
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/getfill.cpp
@@ -0,0 +1,247 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: getfill.c
+ Funtions: getfill
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: 1. Used template to re-organize function and filled out
+ Input/Output and Function definition section.
+ 2. Optimized code.
+
+ Description: Made the following changes based on review comments.
+ 1. Exchanging MODIFYING and RETURNING on line 87, 88.
+ 2. Added MPEG reference.
+ 3. Changed "fill" to "pass over", "bitstreams are" to
+ "bitstream is" in FUNCTION DESCRIPTION section.
+ 4. Fixed tabs.
+
+ Description: Replace some instances of getbits to get9_n_lessbits
+ when the number of bits read is 9 or less.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pInputStream = pointer to structure BITS containing input stream
+ information.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ pInputStream->usedBits is updated to the newly calculated value.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function passes over fill bits in the raw data block to adjust the
+ instantaneous bit rate when the bitstream is to be transmitted over a
+ constant rate channel.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+ (2) ISO/IEC 14496-3: 1999(E)
+ Subpart 4 p15 (Table 4.4.11)
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ CALL getbits(
+ LEN_F_CNT,
+ pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (cnt)
+
+ IF ( cnt == (1<<LEN_F_CNT)-1 )
+
+ CALL getbits(
+ LEN_F_ESC,
+ pInputStream);
+ MODIFYING (pInputStream)
+ RETURNING (esc_cnt)
+
+ cnt += esc_cnt - 1;
+
+ ENDIF
+
+ pInputStream->usedBits += cnt * LEN_BYTE;
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bits.h"
+#include "ibstream.h"
+#include "e_rawbitstreamconst.h"
+#include "getfill.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void getfill(BITS *pInputStream)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ Int cnt;
+ Int esc_cnt;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ cnt = get9_n_lessbits(
+ LEN_F_CNT,
+ pInputStream);
+
+ if (cnt == (1 << LEN_F_CNT) - 1) /* if (cnt == 15) */
+ {
+ esc_cnt = get9_n_lessbits(
+ LEN_F_ESC,
+ pInputStream);
+
+ cnt += esc_cnt - 1;
+ }
+
+ /*
+ * The following codes are replaced by directly updating usedBits
+ * in BITS structure. This will save one call for getbits().
+ *
+ * for (i=0; i<cnt; i++)
+ * { getbits(LEN_BYTE, pInputStream); }
+ */
+
+ pInputStream->usedBits += cnt * LEN_BYTE;
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+
+} /* getfill */
+
diff --git a/media/libstagefright/codecs/aacdec/getfill.h b/media/libstagefright/codecs/aacdec/getfill.h
new file mode 100644
index 0000000..3ba976a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/getfill.h
@@ -0,0 +1,88 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: getfill.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed "definition" to "declaration" on line 28 per
+ review comments.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains prototype declaration for getfill function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef GETFILL_H
+#define GETFILL_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "s_bits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+void getfill(BITS *pInputStream);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/getgroup.cpp b/media/libstagefright/codecs/aacdec/getgroup.cpp
new file mode 100644
index 0000000..0f909cd
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/getgroup.cpp
@@ -0,0 +1,255 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: getgroup.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: (1) Modified to bring code in-line with PV standards
+ (2) Eliminated if(first_short) statement, move for-loop
+ inside if statement
+ (3) Modified UChar -> Int on data types of group
+
+ Description: Replace some instances of getbits to get9_n_lessbits
+ when the number of bits read is 9 or less.
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pInputStream = pointer to structure that holds input bitstream
+ information. Type BITS
+
+ group[] = array that holds the index of the first window in each
+ group. Type Int
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ group contains the index of first windows in each group
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function reads the window grouping information associated with an
+ Individual Channel Stream (ICS). If the window sequence is
+ EIGHT_SHORT_SEQUENCE, scalefactor grouping information is transmitted. If a
+ set of short windows form a group then they share scalefactors, intensity
+ positions and PNS information. The first short window is always a new group
+ so no grouping bit is transmitted. Subsequent short windows are in the same
+ group if the associated grouping bit is 1. A new group is started if the
+ associated grouping bit is 0.
+ The pointer pGroup points to an array that stores the first window index
+ of next group. For example, if the window grouping is:
+
+ window index: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+ grouping : |<- 0 ->| 1 |<- 2 ->|<- 3 ->|
+
+ Then:
+
+ group[] : | 2 | 3 | 6 | 8 |
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function should replace the contents of the array pointed to by pGroup
+ with the first window indexes of groups starting from the second group.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+ (2) ISO/IEC 14496-3: 1999(E)
+ Subpart 4
+ p16 (Table 4.4.6)
+ p55 (Recovering ics_info)
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ IF (pFrameInfo->coef_per_win[0] > SN2)
+
+ *pGroup++ = 1;
+ *pGroup = 1;
+
+ ELSE
+
+ FOR (win = 1; win < pFrameInfo->num_win; win++)
+
+ IF (getbits(1,pInputStream) == 0)
+
+ *pGroup++ = win;
+
+ ENDIF
+
+ ENDFOR (win)
+
+ *pGroup = win;
+
+ ENDIF(pFrameInfo)
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "huffman.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define SEVEN 7
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void getgroup(
+ Int group[],
+ BITS *pInputStream)
+{
+ Int win;
+ Int *pGroup;
+ UInt mask;
+ UInt groupBits;
+
+ pGroup = group;
+
+ mask = 0x40;
+
+ /* only short-window sequences are grouped!
+ * first short window is always a new group,
+ * start reading bitstream from the second
+ * window, a new group is indicated by an
+ * "0" bit in the input stream
+ */
+ groupBits =
+ get9_n_lessbits(
+ SEVEN,
+ pInputStream);
+
+ for (win = 1; win < NUM_SHORT_WINDOWS; win++)
+ {
+ if ((groupBits & mask) == 0)
+ {
+ *pGroup++ = win;
+
+ } /* if (groupBits) */
+
+ mask >>= 1;
+
+ } /* for (win) */
+
+ *pGroup = win;
+
+} /* getgroup */
diff --git a/media/libstagefright/codecs/aacdec/getics.cpp b/media/libstagefright/codecs/aacdec/getics.cpp
new file mode 100644
index 0000000..8d76744
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/getics.cpp
@@ -0,0 +1,674 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: getics.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables
+
+ Description: Remove pass-in parameter global_gain, define it on stack.
+
+ Description: (1) Modified to bring in-line with PV standards
+ (2) Modified pass in parameters
+ (3) Removed multiple returns, removed some if branch
+ (4) Replace for loop with pv_memset
+
+ Description: Remove prstflag, fix copyright.
+
+ Description: Fix pseudo-code
+
+ Description: Remove lpflag from get_ics_info
+
+ Description: (1) Removed widx, therefore, pChVarsWin is eliminated from
+ pass in parameter
+
+ Description: merged the above changes from Michael and Wen
+
+ Description: Removed initialization of "pTnsFrameInfo->num_subblocks" since
+ this element was removed from that structure, as a part of
+ rearchitecting the TNS routines to use memory more efficiently.
+
+ Description:
+ (1) Added #include of "e_HuffmanConst.h"
+ Previously, this function was relying on another include file
+ to include "e_HuffmanConst.h"
+
+ (2) Updated the copyright header.
+
+ (3) Added #include of <stdlib.h> for NULL macro definition.
+
+ Description:
+ (1) Removed the first parameter to getics.c This extra
+ FrameInfo was not needed, the contents of winmap can be used.
+ (2) Removed the memcpy of the data from winmap to the temporary
+ FrameInfo.
+
+ Description: Replace some instances of getbits to get1bits
+ when only 1 bit is read.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pInputStream = pointer to structure that holds input stream,
+ Type BITS
+
+ common_window = flag that indicates whether left and right channel
+ share the same window sequence & shape, Type Int
+
+ pVars = pointer to structure that holds decoder information
+ Type tDec_Int_File
+
+ pChVarsCh = pointer to structure that holds channel related
+ decoding information, Type tDec_Int_Chan
+
+ group[] = pointer to array that contains window grouping
+ information of current frame, Type UChar
+
+ pMax_sfb = pointer to variable that stores maximum active
+ scalefactor bands of current frame, Type UChar
+
+ pCodebookMap = pointer to array that holds the indexes of all
+ Huffman codebooks used for current frame, ordered
+ from section 0 to last section. Type UChar
+
+ pTnsFrameInfo = pointer to structure that holds TNS information.
+ Type TNS_frame_info
+
+ pWinMap = array of pointers which points to structures that
+ hold information of long and short window sequences
+ Type FrameInfo
+
+ pPulseInfo = pointer to structure that holds pulse data decoding
+ information, Type Nec_info
+
+ sect[] = array of structures that hold section codebook and
+ section length in current frame, Type SectInfo
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ status = 0 if success
+ 1 otherwise
+
+ Pointers and Buffers Modified:
+ pCodebookMap contents are replaced by the indexes of all the huffman
+ codebooks used for current frame
+
+ pWinMap For short windows, the contents of frame_sfb_top are
+ modified by calc_gsfb_table, with the top coefficient
+ index of each scalefactor band.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function decodes individual channel stream by calling other Huffman
+ decoding functions.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function replaces the contents of pCodebookMap with the decoded
+ codebook indexes. By calling hufffac, it decodes scale factor data. Call
+ huffspec_fxp to decode spectral coefficients of current frame.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+ (2) ISO/IEC 14496-3: 1999(E)
+ Subpart 4 p24 (Table 4.4.24)
+ p54 (4.5.2.3.2)
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ pGroup = group;
+
+ global_gain = CALL getbits(
+ neededBits = LEN_SCL_PCM,
+ pInputStream = pInputStream)
+ MODIFYING(pInputStream)
+ ReTURNING(global_gain)
+
+ IF (common_window == FALSE)
+ THEN
+ status = CALL get_ics_info(
+ pVars->mc_info.audioObjectType,
+ pInputStream,
+ common_window,
+ &pChVars->wnd,
+ &pChVars->wnd_shape_this_bk,
+ group,
+ pMax_sfb,
+ pWinMap,
+ &pChVars->lt_status,
+ NULL)
+ MODIFYING(pInputStream,pChVars,group,max_sfb,lt_status)
+ RETURNING(status)
+ ENDIF
+
+ memcpy(pFrameInfo, pWinMap[pChVars->wnd], sizeof(FrameInfo))
+
+ IF (*pMax_sfb > 0)
+ THEN
+
+ i = 0;
+ totSfb = 0;
+
+ DO
+
+ totSfb++;
+
+ WHILE( *pGroup++ < pFrameInfo->num_win);
+
+ totSfb *= pFrameInfo->sfb_per_win[0];
+
+ nsect = CALL huffcb(
+ sect,
+ pInputStream,
+ pFrameInfo->sectbits,
+ totSfb,
+ pFrameInfo->sfb_per_win[0],
+ *pMax_sfb)
+ MODIFYING(sect,pInputStream,sectbits)
+ RETURNING(nsect)
+
+ IF (nsect == 0)
+ THEN
+ status = 1
+
+ ENDIF
+
+ sectStart = 0;
+ FOR (i = 0; i < nsect; i++)
+
+ cb = sect[i].sect_cb;
+ sectWidth = sect[i].sect_end - sectStart;
+ sectStart += sectWidth;
+
+ WHILE (sectWidth > 0)
+
+ *pCodebookMap++ = cb
+ sectWidth--
+ ENDWHILE
+
+ ENDFOR (i)
+
+ ELSE
+
+ memset(pCodebookMap,ZERO_HCB,MAXBANDS*sizeof(*pCodebookMap));
+
+ ENDIF (*pMax_sfb)
+
+ IF (pFrameInfo->islong == FALSE)
+ THEN
+ CALL calc_gsfb_table(
+ pFramInfo = pFrameInfo,
+ group[] = group)
+ MODIFYING(pFrameInfo->frame_sfb_top)
+ RETURNING(void)
+ ENDIF
+
+ IF (status == SUCCESS)
+ THEN
+ status = CALL hufffac(
+ pFrameInfo,
+ pInputStream,
+ group,
+ nsect,
+ sect,
+ global_gain,
+ pChVars->factors,
+ pVars->huffBookUsed)
+ MODIFYING(pInputStream,factors)
+ RETURNING(status)
+
+ ENDIF (status)
+
+ IF (status == SUCCESS)
+ THEN
+ present = CALL getbits(
+ neededBits = LEN_PULSE_PRES,
+ pInputStream = pInputStream)
+ MODIFYING(pInputStream)
+ RETURNING(present)
+
+ pPulseInfo->pulse_data_present = present;
+
+ IF (present != FALSE)
+ THEN
+ IF (pFrameInfo->islong == 1)
+ THEN
+ CALL get_pulse_data(
+ pPulseInfo = pPulseInfo,
+ pInputStream = pInputStream)
+ MODIFYING(pInputStream,pPulseInfo)
+ RETURNING(void)
+
+ ELSE
+
+ status = 1;
+
+ ENDIF (pFrameInfo)
+ ENDIF (present)
+
+ ENDIF (status)
+
+ IF (status == SUCCESS)
+ THEN
+ present = CALL getbits(
+ neededBits = LEN_TNS_PRES,
+ pInputStream = pInputStream)
+ MODIFYING(pInputStream)
+ RETURNING(present)
+
+ pTnsFrameInfo->tns_data_present = present;
+
+ IF (present != FALSE)
+ THEN
+ CALL get_tns(
+ pFrameInfo = pFrameInfo,
+ pTnsFrameInfo = pTnsFrameInfo,
+ pInputStream = pInputStream)
+ MODIFYING(pInputStream, pTnsFrameInfo)
+ RETURNING(void)
+ ELSE
+
+ FOR (i = pTnsFrameInfo->n_subblocks - 1; i >= 0 ; i--)
+
+ pTnsFrameInfo->info[i].n_filt = 0;
+ ENDFOR
+
+ ENDIF(present)
+
+ ENDIF (status)
+
+ IF (status == SUCCESS)
+ THEN
+ present = CALL getbits(
+ neededBits = LEN_GAIN_PRES,
+ pInputStream = pInputStream)
+ MODIFYING(pInputStream)
+ RETURNING(present)
+
+ IF (present != FALSE)
+ THEN
+ status = 1;
+ ENDIF
+ ENDIF (status)
+
+ IF (status == SUCCESS)
+ THEN
+ status = CALL huffspec_fxp(
+ pFrameInfo,
+ pInputStream,
+ nsect,
+ sect,
+ pChVars->factors,
+ pChVars->fxpCoef,
+ pVars->quantSpec,
+ pVars->tmp_spec,
+ pWinMap[ONLY_LONG_WINDOW],
+ pPulseInfo,
+ pChVars->qFormat)
+ MODIFYING(pInputStream,fxpCoef,quantSpec,tmp_spec,qFormat)
+ RETURNING(status)
+ ENDIF
+
+ RETURN status
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_huffmanconst.h"
+#include "huffman.h"
+#include "aac_mem_funcs.h"
+#include "get_tns.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Int getics(
+ BITS *pInputStream,
+ Int common_window,
+ tDec_Int_File *pVars,
+ tDec_Int_Chan *pChVars,
+ Int group[],
+ Int *pMax_sfb,
+ Int *pCodebookMap,
+ TNS_frame_info *pTnsFrameInfo,
+ FrameInfo **pWinMap,
+ PulseInfo *pPulseInfo,
+ SectInfo sect[])
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ Int status = SUCCESS;
+
+ Int nsect = 0;
+ Int i;
+ Int cb;
+ Int sectWidth;
+ Int sectStart;
+ Int totSfb;
+ Int *pGroup;
+
+ FrameInfo *pFrameInfo;
+
+ Int global_gain; /* originally passed in from huffdecode */
+ Bool present;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ pGroup = group;
+
+ /* read global gain from Input bitstream */
+ global_gain =
+ get9_n_lessbits(
+ LEN_SCL_PCM,
+ pInputStream);
+
+ if (common_window == FALSE)
+ {
+ status = get_ics_info(
+ pVars->mc_info.audioObjectType,
+ pInputStream,
+ common_window,
+ &pChVars->wnd,
+ &pChVars->wnd_shape_this_bk,
+ group,
+ pMax_sfb,
+ pWinMap,
+ &pChVars->pShareWfxpCoef->lt_status,
+ NULL);
+ }
+
+ pFrameInfo = pWinMap[pChVars->wnd];
+
+ /* First, calculate total number of scalefactor bands
+ * for this grouping. Then, decode section data
+ */
+ if (*pMax_sfb > 0)
+ {
+
+ /* calculate total number of sfb */
+ i = 0;
+ totSfb = 0;
+
+ do
+ {
+ totSfb++;
+
+ }
+ while (*pGroup++ < pFrameInfo->num_win);
+
+ totSfb *= pFrameInfo->sfb_per_win[0];
+
+ /* decode section data */
+ nsect =
+ huffcb(
+ sect,
+ pInputStream,
+ pFrameInfo->sectbits,
+ totSfb,
+ pFrameInfo->sfb_per_win[0],
+ *pMax_sfb);
+
+ if (nsect == 0)
+ {
+ status = 1; /* decode section data error */
+
+ }/* if (nsect) */
+
+ /* generate "linear" description from section info
+ * stored as codebook for each scalefactor band and group
+ * when nsect == 0, for-loop does not execute
+ */
+ sectStart = 0;
+ for (i = 0; i < nsect; i++)
+ {
+ cb = sect[i].sect_cb;
+ sectWidth = sect[i].sect_end - sectStart;
+ sectStart += sectWidth;
+
+ while (sectWidth > 0)
+ {
+ *pCodebookMap++ = cb; /* cannot use memset for Int */
+ sectWidth--;
+ }
+
+ } /* for (i) */
+
+ }
+ else
+ {
+ /* set all sections with ZERO_HCB */
+ pv_memset(
+ pCodebookMap,
+ ZERO_HCB,
+ MAXBANDS*sizeof(*pCodebookMap));
+ /*
+ for (i=MAXBANDS; i>0; i--)
+ {
+ *(pCodebookMap++) = ZERO_HCB;
+ }
+ */
+
+ } /* if (*pMax_sfb) */
+
+ /* calculate band offsets
+ * (because of grouping and interleaving this cannot be
+ * a constant: store it in pFrameInfo->frame_sfb_top)
+ */
+ if (pFrameInfo->islong == FALSE)
+ {
+ calc_gsfb_table(
+ pFrameInfo,
+ group);
+ }
+
+ /* decode scale factor data */
+ if (status == SUCCESS)
+ {
+ status =
+ hufffac(
+ pFrameInfo,
+ pInputStream,
+ group,
+ nsect,
+ sect,
+ global_gain,
+ pChVars->pShareWfxpCoef->factors,
+ pVars->scratch.huffbook_used);
+
+ } /* if (status) */
+
+ /* noiseless coding */
+ if (status == SUCCESS)
+ {
+ present =
+ get1bits(pInputStream);
+
+ pPulseInfo->pulse_data_present = present;
+
+ if (present != FALSE)
+ {
+ if (pFrameInfo->islong == 1)
+ {
+ status = get_pulse_data(
+ pPulseInfo,
+ pInputStream);
+ }
+ else
+ {
+ /* CommonExit(1,"Pulse data not allowed for short blocks"); */
+ status = 1;
+
+ } /* if (pFrameInfo) */
+ } /* if (present) */
+
+ } /* if (status) */
+
+
+ /* decode tns data */
+ if (status == SUCCESS)
+ {
+ present =
+ get1bits(pInputStream);
+
+ pTnsFrameInfo->tns_data_present = present;
+
+ if (present != FALSE)
+ {
+ get_tns(
+ pChVars->pShareWfxpCoef->max_sfb,
+ pInputStream,
+ pChVars->wnd,
+ pFrameInfo,
+ &pVars->mc_info,
+ pTnsFrameInfo,
+ pVars->scratch.tns_decode_coef);
+ }
+ else
+ {
+ for (i = pFrameInfo->num_win - 1; i >= 0 ; i--)
+ {
+ pTnsFrameInfo->n_filt[i] = 0;
+ }
+
+ } /* if(present) */
+
+ } /* if (status) */
+
+ /* gain control */
+ if (status == SUCCESS)
+ {
+ present =
+ get1bits(pInputStream);
+
+ if (present != FALSE)
+ {
+ /* CommonExit(1, "Gain control not implemented"); */
+ status = 1;
+ }
+ } /* if (status) */
+
+ if (status == SUCCESS)
+ {
+ status =
+ huffspec_fxp(
+ pFrameInfo,
+ pInputStream,
+ nsect,
+ sect,
+ pChVars->pShareWfxpCoef->factors,
+ pChVars->fxpCoef,
+ pVars->share.a.quantSpec,
+ pVars->scratch.tmp_spec,
+ pWinMap[ONLY_LONG_WINDOW],
+ pPulseInfo,
+ pChVars->pShareWfxpCoef->qFormat);
+ }
+
+ /*----------------------------------------------------------------------------
+ ; Return status
+ ----------------------------------------------------------------------------*/
+
+ return status;
+
+} /* getics */
diff --git a/media/libstagefright/codecs/aacdec/getmask.cpp b/media/libstagefright/codecs/aacdec/getmask.cpp
new file mode 100644
index 0000000..2fd34f1
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/getmask.cpp
@@ -0,0 +1,384 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: getmask.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+ Replaced for-loop style memory initialization with memset()
+
+ Description: (1) Modified to bring code in-line with PV standard
+ (2) Removed multiple returns, Replaced multiple 'if's with
+ switch
+
+ Description: (1) Modified per review comments
+ (2) increment pointer pMask after memset
+
+ Description: Make the maximum number of bits requested from getbits
+ become a constant.
+
+ Description: Typecast 1 to UInt32 for bitmask to avoid masking on a 16-bit
+ platform
+
+ Description: Replace some instances of getbits to get9_n_lessbits
+ when the number of bits read is 9 or less.
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pFrameInfo = pointer to structure that holds information for current
+ frame, Type FrameInfo
+
+ pInputStream= pointer to structure that holds input stream information
+ Type BITS
+
+ pGroup = pointer to array that holds the stop window index for
+ each group in current frame, Type Int
+
+ max_sfb = number of active sfbs for each window, Type Int
+
+ mask[] = array that holds the MS_mask information
+ Type Int
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ mask_present = 0 (no Mid/Side mixed)
+ 2 (Mid/Side mixed present for entire frame)
+ 1 (Mid/Side mixed information read from bitstream)
+ -1 (invalid mask_present read from bitstream)
+
+ Pointers and Buffers Modified:
+ pMask contents replaced by MS information of each scalefactor band
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function reads the Mid/Side(MS) mask information from the input
+ bitstream. If the mask_present field is equal to 2, the mask bits is set to
+ 1 for the entire frame. If mask_present has a value of 0, the function
+ returns 0, If mask_present is set to 1, the Mid/Side(MS) information is
+ read from the input stream. When mask_present is 3, an error code (-1) is
+ generated.
+ The Mid/Side(MS) information is later used for mixing the left and right
+ channel sounds. Each scalefactor band has its own MS information.
+
+ (ISO comments: read a synthesis mask, read a synthesis mask uses
+ EXTENDED_MS_MASK and grouped mask )
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function shall replace the contents of pMask with the MS information
+ of each scalefactor band
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+ (2) ISO/IEC 14496-3: 1999(E)
+ Subpart 4
+ p15 (Table 4.4.5 getmask)
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ CALL getbits(LEN_MASK_PRES, pInputStream)
+ MODIFYING (pInputStream)
+ RETURNING (mask present information)
+ mask_present = mask present information
+
+ SWITCH (mask_present)
+
+ CASE (0):
+ BREAK;
+
+ CASE (2):
+ nwin = pFrameInfo->num_win;
+ FOR(win = 0; win < nwin; win = *(pGroup++))
+
+ FOR(sfb = pFrameInfo->sfb_per_win[win]; sfb > 0; sfb--)
+ *(pMask++) = 1;
+ ENDFOR
+
+ ENDFOR
+
+ BREAK;
+
+ CASE(1):
+
+ nwin = pFrameInfo->num_win;
+
+ nToDo = max_sfb;
+
+ WHILE (nToDo > 0)
+ nCall = nToDo;
+
+ IF (nCall > MAX_GETBITS)
+ THEN
+ nCall = MAX_GETBITS;
+ ENDIF
+
+ tempMask =
+ getbits(
+ nCall,
+ pInputStream);
+
+ bitmask = 1 << (nCall - 1);
+ FOR (sfb = nCall; sfb > 0; sfb--)
+ *(pMask++) = (tempMask & bitmask) >> (sfb - 1);
+ bitmask >>= 1;
+ ENDFOR
+
+ nToDo -= nCall;
+ END WHILE
+
+ pv_memset(
+ pMask,
+ 0,
+ (pFrameInfo->sfb_per_win[win]-max_sfb)*sizeof(*pMask));
+
+ ENDFOR (win)
+
+ BREAK
+
+ DEFAULT:
+ mask_present = -1
+
+ ENDSWITCH
+
+ RETURN mask_present
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "huffman.h"
+#include "aac_mem_funcs.h"
+#include "e_maskstatus.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Int getmask(
+ FrameInfo *pFrameInfo,
+ BITS *pInputStream,
+ Int group[],
+ Int max_sfb,
+ Int mask[])
+{
+
+ Int win; /* window index */
+ Int sfb;
+ Int mask_present;
+ Int *pMask;
+ Int *pGroup;
+ Int nwin;
+ Int nCall;
+ Int nToDo;
+ UInt32 tempMask;
+ UInt32 bitmask;
+
+ pMask = mask;
+ pGroup = group;
+
+ mask_present =
+ get9_n_lessbits(
+ LEN_MASK_PRES,
+ pInputStream);
+
+ switch (mask_present)
+ {
+ case(MASK_NOT_PRESENT):
+ /* special EXTENDED_MS_MASK cases */
+ /* no ms at all */
+ break;
+
+ case(MASK_ALL_FRAME):
+ /* MS for whole spectrum on, mask bits set to 1 */
+ nwin = pFrameInfo->num_win;
+ for (win = 0; win < nwin; win = *(pGroup++))
+ {
+ for (sfb = pFrameInfo->sfb_per_win[win]; sfb > 0; sfb--)
+ {
+ *(pMask++) = 1; /* cannot use memset for Int type */
+ }
+
+ }
+
+ break;
+
+ case(MASK_FROM_BITSTREAM):
+ /* MS_mask_present==1, get mask information*/
+ nwin = pFrameInfo->num_win;
+ for (win = 0; win < nwin; win = *(pGroup++))
+ {
+ /*
+ * the following code is equivalent to
+ *
+ * for(sfb = max_sfb; sfb > 0; sfb--)
+ * {
+ * *(pMask++) =
+ * getbits(
+ * LEN_MASK,
+ * pInputStream);
+ * }
+ *
+ * in order to save the calls to getbits, the above
+ * for-loop is broken into two parts
+ */
+
+ nToDo = max_sfb;
+
+ while (nToDo > 0)
+ {
+ nCall = nToDo;
+
+ if (nCall > MAX_GETBITS)
+ {
+ nCall = MAX_GETBITS;
+ }
+
+ tempMask =
+ getbits(
+ nCall,
+ pInputStream);
+
+ bitmask = (UInt32) 1 << (nCall - 1);
+ for (sfb = nCall; sfb > 0; sfb--)
+ {
+ *(pMask++) = (Int)((tempMask & bitmask) >> (sfb - 1));
+ bitmask >>= 1;
+ }
+
+ nToDo -= nCall;
+ }
+
+ /*
+ * set remaining sfbs to zero
+ * re-use nCall to save one variable on stack
+ */
+
+ nCall = pFrameInfo->sfb_per_win[win] - max_sfb;
+
+
+ if (nCall >= 0)
+ {
+ pv_memset(pMask,
+ 0,
+ nCall*sizeof(*pMask));
+
+ pMask += nCall;
+ }
+ else
+ {
+ mask_present = MASK_ERROR;
+ break;
+ }
+
+
+ } /* for (win) */
+
+ break;
+
+ default:
+ /* error */
+ break;
+
+ } /* switch (mask_present) */
+
+ return mask_present;
+
+} /* getmask */
diff --git a/media/libstagefright/codecs/aacdec/hcbtables.h b/media/libstagefright/codecs/aacdec/hcbtables.h
new file mode 100644
index 0000000..a35fed0
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/hcbtables.h
@@ -0,0 +1,118 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: hcbtables.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: (1) Add declaration of binary tree tables
+ (2) #if optimized Linear Search Huffman decoding
+
+ Description: Modified per review comments
+ (1) delete #if optimized Linear Search Huffman decoding
+ (2) modified copyright header
+
+ Description: (1) Add declaration different huffman tables
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Declare the structure array for Huffman Codebooks information.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef _HCBTABLES_H
+#define _HCBTABLES_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "s_hcb.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /* ISO: Hcb book[NSPECBOOKS + 2]; */
+
+ extern const Hcb hcbbook_binary[13];
+ extern const Int32 huff_tab1[88];
+ extern const Int32 huff_tab2[90];
+ extern const Int32 huff_tab3[151];
+ extern const Int32 huff_tab4[119];
+ extern const Int32 huff_tab5[110];
+ extern const Int32 huff_tab6[113];
+ extern const Int32 huff_tab7[107];
+ extern const Int32 huff_tab8[90];
+ extern const Int32 huff_tab9[204];
+ extern const Int32 huff_tab10[186];
+ extern const Int32 huff_tab11[301];
+ extern const UInt32 huff_tab_scl[188];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/hcbtables_binary.cpp b/media/libstagefright/codecs/aacdec/hcbtables_binary.cpp
new file mode 100644
index 0000000..d097af1
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/hcbtables_binary.cpp
@@ -0,0 +1,1938 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: hcbtables.c
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modifiy per review comments
+ (1) delete the following comments:
+ The LAV field has been deleted, since it is never used.
+
+ Description: Remove old structure of huffman table and add new table structure.
+
+ Description: Modified structure to avoid assigning addresses to constant
+ tables. This solve linking problem when using the
+ /ropi option (Read-only position independent) for some
+ compilers
+ - Eliminated references to contant vector addresses in
+ hcbbook_binary
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs: None
+
+ Local Stores/Buffers/Pointers Needed: None
+
+ Global Stores/Buffers/Pointers Needed: None
+
+ Outputs: None
+
+ Pointers and Buffers Modified: None
+
+ Local Stores Modified: None
+
+ Global Stores Modified: None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This file defines the 12 packed Huffman Tables and a structure that reference
+ to these tables.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ISO/IEC 14496-3: 1999(E)
+ Subpart 4 p78 (Table 4.6.1 and Table 4.6.2)
+ p77 (pseudo code)
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+#include "s_hcb.h"
+#include "hcbtables.h"
+
+/* This file store packed Huffman tables for binary tree search */
+
+/*
+ * all tables are packed in the following way:
+ * right pointer (7 bits) idx (9 bits)
+ */
+
+
+const Hcb hcbbook_binary[13] =
+{
+
+ { 0, -1, -1, -1, -1 }, /* ZERO_HCB */
+ { 1, 4, 3, 1, 1 }, /* codebook 1 */
+ { 2, 4, 3, 1, 1 }, /* codebook 2 */
+ { 3, 4, 3, 0, 0 }, /* codebook 3 */
+ { 4, 4, 3, 0, 0 }, /* codebook 4 */
+ { 5, 2, 9, 4, 1 },
+ { 6, 2, 9, 4, 1 },
+ { 7, 2, 8, 0, 0 },
+ { 8, 2, 8, 0, 0 },
+ { 9, 2, 13, 0, 0 },
+ {10, 2, 13, 0, 0 },
+ {11, 2, 17, 0, 0 }, /* codebook 11 ESC book */
+ {12, -1, -1, -1, -1 } /* scalefactor codebook */
+
+
+};
+
+
+/* New look-up table for huffman decoding
+ Created by ordering the codeword in the table according to their
+ normalized shifted binary value, i.e., all the codewords are left
+ shifted to meet the maximum codelength. Example, max codelength is
+ 10, the codeword with lenth 3 will left shift by 7.
+ The binary values of after the shift are sorted.
+ Then the sorted table is divided into several partition.
+ At the VLC decoding period, input is read in at max codelenght.
+ The partition is decided using if-else logic.
+ Inside each partition, a look-up table is used to map the input value
+ to a correct symbol. Table entries can appear to be repeated according
+ to the humming distance between adjacent codewords.
+*/
+
+const Int32 huff_tab1[88] =
+{
+ 0x430005,
+ 0xd0005,
+ 0x270005,
+ 0x310005,
+ 0x290005,
+ 0x250005,
+ 0x2b0005,
+ 0x1f0005,
+ 0x3a0007,
+ 0x160007,
+ 0x260007,
+ 0x2e0007,
+ 0x220007,
+ 0x2a0007,
+ 0x4c0007,
+ 0x240007,
+ 0x40007,
+ 0x1c0007,
+ 0x400007,
+ 0x300007,
+ 0x100007,
+ 0x2c0007,
+ 0x460007,
+ 0x200007,
+ 0x340007,
+ 0x320007,
+ 0xa0007,
+ 0x440007,
+ 0xc0007,
+ 0x420007,
+ 0xe0007,
+ 0x1e0007,
+ 0x490009,
+ 0x130009,
+ 0x3d0009,
+ 0x330009,
+ 0x2f0009,
+ 0x230009,
+ 0x210009,
+ 0x370009,
+ 0x410009,
+ 0x2d0009,
+ 0x190009,
+ 0xf0009,
+ 0x70009,
+ 0x1d0009,
+ 0x3b0009,
+ 0x390009,
+ 0x150009,
+ 0x10009,
+ 0x1b0009,
+ 0x350009,
+ 0x450009,
+ 0x4d0009,
+ 0x170009,
+ 0x4f0009,
+ 0x5000a,
+ 0x5000a,
+ 0x9000a,
+ 0x9000a,
+ 0x4b000a,
+ 0x4b000a,
+ 0x3f000a,
+ 0x3f000a,
+ 0xb000a,
+ 0xb000a,
+ 0x3000a,
+ 0x3000a,
+ 0x11000a,
+ 0x11000a,
+ 0x47000a,
+ 0x47000a,
+ 0x3c000b,
+ 0x14000b,
+ 0x18000b,
+ 0x38000b,
+ 0x50000b,
+ 0x8000b,
+ 0x48000b,
+ 0x6000b,
+ 0xb,
+ 0x4a000b,
+ 0x3e000b,
+ 0x1a000b,
+ 0x12000b,
+ 0x2000b,
+ 0x36000b,
+ 0x4e000b
+};
+
+const Int32 huff_tab2[90] =
+{
+ 0x430004,
+ 0x430004,
+ 0x430004,
+ 0x430004,
+ 0xd0005,
+ 0xd0005,
+ 0x290005,
+ 0x290005,
+ 0x250005,
+ 0x250005,
+ 0x270005,
+ 0x270005,
+ 0x1f0005,
+ 0x1f0005,
+ 0x2b0005,
+ 0x2b0005,
+ 0x310005,
+ 0x310005,
+ 0x220006,
+ 0x160006,
+ 0x2e0006,
+ 0x2a0006,
+ 0x300006,
+ 0x260006,
+ 0xc0006,
+ 0x3a0006,
+ 0x400006,
+ 0x40006,
+ 0x240006,
+ 0x460006,
+ 0x440006,
+ 0x200006,
+ 0x100006,
+ 0x320006,
+ 0x1c0006,
+ 0xe0006,
+ 0x1e0006,
+ 0xa0006,
+ 0x4c0006,
+ 0x340006,
+ 0x2c0006,
+ 0x420006,
+ 0x2f0007,
+ 0x410007,
+ 0x130007,
+ 0x210007,
+ 0x3d0007,
+ 0x4b0007,
+ 0x470007,
+ 0x190007,
+ 0x1d0007,
+ 0x4f0007,
+ 0xf0007,
+ 0x10007,
+ 0xb0007,
+ 0x370007,
+ 0x490007,
+ 0x3b0008,
+ 0x150008,
+ 0x70008,
+ 0x110008,
+ 0x50008,
+ 0x30008,
+ 0x1b0008,
+ 0x450008,
+ 0x3f0008,
+ 0x2d0008,
+ 0x350008,
+ 0x170008,
+ 0x90008,
+ 0x330008,
+ 0x390008,
+ 0x230008,
+ 0x4d0008,
+ 0x3c0008,
+ 0x140008,
+ 0x380009,
+ 0x9,
+ 0x180009,
+ 0x1a0009,
+ 0x500009,
+ 0x60009,
+ 0x3e0009,
+ 0x120009,
+ 0x80009,
+ 0x480009,
+ 0x360009,
+ 0x20009,
+ 0x4a0009,
+ 0x4e0009
+};
+
+const Int32 huff_tab3[151] =
+{
+ 0x1b0004,
+ 0x1b0004,
+ 0x1b0004,
+ 0x1b0004,
+ 0x10004,
+ 0x10004,
+ 0x10004,
+ 0x10004,
+ 0x90004,
+ 0x90004,
+ 0x90004,
+ 0x90004,
+ 0x30004,
+ 0x30004,
+ 0x30004,
+ 0x30004,
+ 0x240005,
+ 0x240005,
+ 0x40005,
+ 0x40005,
+ 0xc0006,
+ 0xa0006,
+ 0x1e0006,
+ 0xd0006,
+ 0x1c0006,
+ 0x270006,
+ 0x280007,
+ 0x280007,
+ 0x280007,
+ 0x280007,
+ 0x1f0007,
+ 0x1f0007,
+ 0x1f0007,
+ 0x1f0007,
+ 0x250007,
+ 0x250007,
+ 0x250007,
+ 0x250007,
+ 0x360008,
+ 0x360008,
+ 0x20008,
+ 0x20008,
+ 0x50008,
+ 0x50008,
+ 0x3f0008,
+ 0x3f0008,
+ 0x300008,
+ 0x300008,
+ 0x70009,
+ 0x100009,
+ 0x2d0009,
+ 0xe0009,
+ 0x420009,
+ 0x60009,
+ 0x150009,
+ 0xf0009,
+ 0x120009,
+ 0xb0009,
+ 0x390009,
+ 0x310009,
+ 0x160009,
+ 0x2a0009,
+ 0x2b0009,
+ 0x2e000a,
+ 0x21000a,
+ 0x22000a,
+ 0x13000a,
+ 0x43000a,
+ 0x29000a,
+ 0x40000a,
+ 0x20000a,
+ 0x8000a,
+ 0x11000a,
+ 0x4b000a,
+ 0x33000a,
+ 0x1d000a,
+ 0x37000a,
+ 0x19000a,
+ 0x48000b,
+ 0x48000b,
+ 0x34000b,
+ 0x34000b,
+ 0x26000b,
+ 0x26000b,
+ 0x3a000b,
+ 0x3a000b,
+ 0x2c000b,
+ 0x2c000b,
+ 0x4c000b,
+ 0x4c000b,
+ 0x18000b,
+ 0x18000b,
+ 0x17000b,
+ 0x17000b,
+ 0x23000c,
+ 0x49000c,
+ 0x45000c,
+ 0x4e000c,
+ 0x1a000c,
+ 0x4f000c,
+ 0x46000c,
+ 0x32000c,
+ 0x35000c,
+ 0x14000d,
+ 0x14000d,
+ 0x14000d,
+ 0x14000d,
+ 0x14000d,
+ 0x14000d,
+ 0x14000d,
+ 0x14000d,
+ 0x3c000d,
+ 0x3c000d,
+ 0x3c000d,
+ 0x3c000d,
+ 0x3c000d,
+ 0x3c000d,
+ 0x3c000d,
+ 0x3c000d,
+ 0x2f000d,
+ 0x2f000d,
+ 0x2f000d,
+ 0x2f000d,
+ 0x2f000d,
+ 0x2f000d,
+ 0x2f000d,
+ 0x2f000d,
+ 0x3d000e,
+ 0x3d000e,
+ 0x3d000e,
+ 0x3d000e,
+ 0x44000e,
+ 0x44000e,
+ 0x44000e,
+ 0x44000e,
+ 0x41000e,
+ 0x41000e,
+ 0x41000e,
+ 0x41000e,
+ 0x50000f,
+ 0x50000f,
+ 0x4d000f,
+ 0x4d000f,
+ 0x47000f,
+ 0x47000f,
+ 0x3b000f,
+ 0x3b000f,
+ 0x38000f,
+ 0x38000f,
+ 0x4a0010,
+ 0x3e0010
+};
+
+const Int32 huff_tab4[119] =
+{
+ 0x280004,
+ 0x280004,
+ 0xd0004,
+ 0xd0004,
+ 0x250004,
+ 0x250004,
+ 0x270004,
+ 0x270004,
+ 0x1f0004,
+ 0x1f0004,
+ 0x1b0004,
+ 0x1b0004,
+ 0x240004,
+ 0x240004,
+ 0x4,
+ 0x4,
+ 0x40004,
+ 0x40004,
+ 0x1e0004,
+ 0x1e0004,
+ 0x1c0005,
+ 0xc0005,
+ 0x10005,
+ 0xa0005,
+ 0x30005,
+ 0x90005,
+ 0x430007,
+ 0x430007,
+ 0x2b0007,
+ 0x2b0007,
+ 0x310007,
+ 0x310007,
+ 0x290007,
+ 0x290007,
+ 0x420007,
+ 0x420007,
+ 0x400007,
+ 0x400007,
+ 0x300007,
+ 0x300007,
+ 0x3a0007,
+ 0x3a0007,
+ 0x100007,
+ 0x100007,
+ 0xe0008,
+ 0x2a0008,
+ 0x160008,
+ 0x200008,
+ 0x2e0008,
+ 0x260008,
+ 0x220008,
+ 0x3f0008,
+ 0x390008,
+ 0x2d0008,
+ 0x370008,
+ 0xb0008,
+ 0x150008,
+ 0x50008,
+ 0xf0008,
+ 0x130008,
+ 0x1d0008,
+ 0x70008,
+ 0x210008,
+ 0x360008,
+ 0x20008,
+ 0x120009,
+ 0x120009,
+ 0x60009,
+ 0x60009,
+ 0x340009,
+ 0x340009,
+ 0x4c0009,
+ 0x4c0009,
+ 0x460009,
+ 0x460009,
+ 0x2c0009,
+ 0x2c0009,
+ 0x320009,
+ 0x320009,
+ 0x440009,
+ 0x440009,
+ 0x33000a,
+ 0x4b000a,
+ 0x45000a,
+ 0x19000a,
+ 0x11000a,
+ 0x49000a,
+ 0x17000a,
+ 0x3d000a,
+ 0x23000a,
+ 0x4f000a,
+ 0x2f000a,
+ 0x3b000a,
+ 0x41000a,
+ 0x35000a,
+ 0x47000b,
+ 0x47000b,
+ 0x4d000b,
+ 0x4d000b,
+ 0x18000b,
+ 0x18000b,
+ 0x48000b,
+ 0x48000b,
+ 0x8000b,
+ 0x8000b,
+ 0x3c000b,
+ 0x3c000b,
+ 0x14000b,
+ 0x14000b,
+ 0x38000b,
+ 0x38000b,
+ 0x50000b,
+ 0x50000b,
+ 0x1a000b,
+ 0x1a000b,
+ 0x4e000b,
+ 0x4e000b,
+ 0x4a000c,
+ 0x3e000c
+};
+
+const Int32 huff_tab5[110] =
+{
+ 0x1f0004,
+ 0x1f0004,
+ 0x310004,
+ 0x310004,
+ 0x290004,
+ 0x290004,
+ 0x270004,
+ 0x270004,
+ 0x300005,
+ 0x200005,
+ 0x1e0005,
+ 0x320005,
+ 0x160007,
+ 0x160007,
+ 0x2a0007,
+ 0x2a0007,
+ 0x3a0007,
+ 0x3a0007,
+ 0x260007,
+ 0x260007,
+ 0x150008,
+ 0x3b0008,
+ 0x1d0008,
+ 0x330008,
+ 0x170008,
+ 0x390008,
+ 0x210008,
+ 0x2f0008,
+ 0xd0008,
+ 0x430008,
+ 0x250008,
+ 0x2b0008,
+ 0xc0009,
+ 0xc0009,
+ 0x340009,
+ 0x340009,
+ 0x440009,
+ 0x440009,
+ 0x1c0009,
+ 0x1c0009,
+ 0xe0009,
+ 0xe0009,
+ 0x420009,
+ 0x420009,
+ 0x2e0009,
+ 0x2e0009,
+ 0x220009,
+ 0x220009,
+ 0x180009,
+ 0x180009,
+ 0x3c0009,
+ 0x3c0009,
+ 0x140009,
+ 0x140009,
+ 0x380009,
+ 0x380009,
+ 0xb000a,
+ 0x41000a,
+ 0x19000a,
+ 0x37000a,
+ 0x45000a,
+ 0x3d000a,
+ 0xf000a,
+ 0x13000a,
+ 0x24000a,
+ 0x4000a,
+ 0x4d000a,
+ 0x4c000a,
+ 0x3000b,
+ 0x2c000b,
+ 0x4b000b,
+ 0x1b000b,
+ 0x35000b,
+ 0x23000b,
+ 0x5000b,
+ 0x2d000b,
+ 0x40000b,
+ 0xa000b,
+ 0x10000b,
+ 0x1a000b,
+ 0x2000b,
+ 0x4e000b,
+ 0x36000b,
+ 0x3e000b,
+ 0x46000b,
+ 0x6000b,
+ 0x12000c,
+ 0x12000c,
+ 0x4a000c,
+ 0x4a000c,
+ 0x3f000c,
+ 0x3f000c,
+ 0x1000c,
+ 0x1000c,
+ 0x7000c,
+ 0x7000c,
+ 0x47000c,
+ 0x47000c,
+ 0x11000c,
+ 0x11000c,
+ 0x4f000c,
+ 0x4f000c,
+ 0x49000c,
+ 0x49000c,
+ 0x9000c,
+ 0x9000c,
+ 0x48000d,
+ 0x8000d,
+ 0x50000d,
+ 0xd
+};
+const Int32 huff_tab6[113] =
+{
+ 0x280004,
+ 0x310004,
+ 0x270004,
+ 0x290004,
+ 0x1f0004,
+ 0x320004,
+ 0x200004,
+ 0x300004,
+ 0x1e0004,
+ 0x390006,
+ 0x390006,
+ 0x3b0006,
+ 0x3b0006,
+ 0x170006,
+ 0x170006,
+ 0x150006,
+ 0x150006,
+ 0x160006,
+ 0x160006,
+ 0x210006,
+ 0x210006,
+ 0x3a0006,
+ 0x3a0006,
+ 0x2f0006,
+ 0x2f0006,
+ 0x330006,
+ 0x330006,
+ 0x260006,
+ 0x260006,
+ 0x1d0006,
+ 0x1d0006,
+ 0x2a0006,
+ 0x2a0006,
+ 0x380006,
+ 0x380006,
+ 0x180006,
+ 0x180006,
+ 0x140006,
+ 0x140006,
+ 0x3c0006,
+ 0x3c0006,
+ 0xe0007,
+ 0x440007,
+ 0x420007,
+ 0x220007,
+ 0xc0007,
+ 0x340007,
+ 0x2e0007,
+ 0x1c0007,
+ 0x430007,
+ 0xd0007,
+ 0x250007,
+ 0x2b0007,
+ 0x450007,
+ 0xb0008,
+ 0xb0008,
+ 0x190008,
+ 0x190008,
+ 0x3d0008,
+ 0x3d0008,
+ 0x410008,
+ 0x410008,
+ 0x370008,
+ 0x370008,
+ 0x130008,
+ 0x130008,
+ 0xf0008,
+ 0xf0008,
+ 0x460008,
+ 0x460008,
+ 0x400009,
+ 0xa0009,
+ 0x100009,
+ 0x2d0009,
+ 0x1b0009,
+ 0x4d0009,
+ 0x50009,
+ 0x30009,
+ 0x350009,
+ 0x4b0009,
+ 0x230009,
+ 0x240009,
+ 0x60009,
+ 0x20009,
+ 0x3e0009,
+ 0x120009,
+ 0x40009,
+ 0x4e0009,
+ 0x4a0009,
+ 0x1a0009,
+ 0x4c0009,
+ 0x360009,
+ 0x2c0009,
+ 0x9000a,
+ 0x9000a,
+ 0x11000a,
+ 0x11000a,
+ 0x3f000a,
+ 0x3f000a,
+ 0x49000a,
+ 0x49000a,
+ 0x47000a,
+ 0x47000a,
+ 0x4f000a,
+ 0x4f000a,
+ 0x7000a,
+ 0x7000a,
+ 0x1000a,
+ 0x1000a,
+ 0x50000b,
+ 0x8000b,
+ 0xb,
+ 0x48000b
+};
+
+const Int32 huff_tab7[107] =
+{
+ 0x80003,
+ 0x80003,
+ 0x80003,
+ 0x80003,
+ 0x80003,
+ 0x80003,
+ 0x80003,
+ 0x80003,
+ 0x10003,
+ 0x10003,
+ 0x10003,
+ 0x10003,
+ 0x10003,
+ 0x10003,
+ 0x10003,
+ 0x10003,
+ 0x90004,
+ 0x90004,
+ 0x90004,
+ 0x90004,
+ 0x110006,
+ 0xa0006,
+ 0x100006,
+ 0x20006,
+ 0x190007,
+ 0x190007,
+ 0xb0007,
+ 0xb0007,
+ 0x120007,
+ 0x120007,
+ 0x180007,
+ 0x180007,
+ 0x30007,
+ 0x30007,
+ 0x130008,
+ 0x1a0008,
+ 0xc0008,
+ 0x210008,
+ 0xd0008,
+ 0x290008,
+ 0x1b0008,
+ 0x140008,
+ 0x40008,
+ 0x200008,
+ 0x220009,
+ 0x220009,
+ 0x150009,
+ 0x150009,
+ 0x2a0009,
+ 0x2a0009,
+ 0x50009,
+ 0x50009,
+ 0x310009,
+ 0x310009,
+ 0x280009,
+ 0x280009,
+ 0xe0009,
+ 0xe0009,
+ 0x230009,
+ 0x230009,
+ 0x1d0009,
+ 0x1d0009,
+ 0x1c0009,
+ 0x1c0009,
+ 0x2b0009,
+ 0x2b0009,
+ 0x160009,
+ 0x160009,
+ 0x320009,
+ 0x320009,
+ 0xf0009,
+ 0xf0009,
+ 0x1e000a,
+ 0x6000a,
+ 0x30000a,
+ 0x24000a,
+ 0x39000a,
+ 0x25000a,
+ 0x3a000a,
+ 0x2c000a,
+ 0x33000a,
+ 0x17000a,
+ 0x3b000a,
+ 0x34000a,
+ 0x2d000a,
+ 0x26000a,
+ 0x1f000a,
+ 0x38000b,
+ 0x38000b,
+ 0x7000b,
+ 0x7000b,
+ 0x35000b,
+ 0x35000b,
+ 0x2e000b,
+ 0x2e000b,
+ 0x3c000b,
+ 0x3c000b,
+ 0x27000b,
+ 0x27000b,
+ 0x2f000b,
+ 0x2f000b,
+ 0x3d000b,
+ 0x3d000b,
+ 0x3e000c,
+ 0x36000c,
+ 0x37000c,
+ 0x3f000c
+};
+const Int32 huff_tab8[90] =
+{
+ 0x90003,
+ 0x90003,
+ 0x90003,
+ 0x90003,
+ 0x110004,
+ 0x110004,
+ 0x80004,
+ 0x80004,
+ 0xa0004,
+ 0xa0004,
+ 0x10004,
+ 0x10004,
+ 0x120004,
+ 0x120004,
+ 0x5,
+ 0x100005,
+ 0x20005,
+ 0x190005,
+ 0xb0005,
+ 0x1a0005,
+ 0x130005,
+ 0x1b0006,
+ 0x1b0006,
+ 0x210006,
+ 0x210006,
+ 0xc0006,
+ 0xc0006,
+ 0x220006,
+ 0x220006,
+ 0x140006,
+ 0x140006,
+ 0x180006,
+ 0x180006,
+ 0x30006,
+ 0x30006,
+ 0x230006,
+ 0x230006,
+ 0x1c0006,
+ 0x1c0006,
+ 0x2a0006,
+ 0x2a0006,
+ 0x290007,
+ 0x150007,
+ 0xd0007,
+ 0x2b0007,
+ 0x1d0007,
+ 0x240007,
+ 0x2c0007,
+ 0x40007,
+ 0x250007,
+ 0x200007,
+ 0x160007,
+ 0x320007,
+ 0x310007,
+ 0xe0007,
+ 0x1e0008,
+ 0x330008,
+ 0x2d0008,
+ 0x280008,
+ 0x340008,
+ 0x50008,
+ 0x260008,
+ 0x390008,
+ 0x3a0008,
+ 0x170008,
+ 0x350008,
+ 0x3b0008,
+ 0xf0008,
+ 0x2e0008,
+ 0x1f0008,
+ 0x360009,
+ 0x360009,
+ 0x3c0009,
+ 0x3c0009,
+ 0x300009,
+ 0x300009,
+ 0x270009,
+ 0x270009,
+ 0x60009,
+ 0x60009,
+ 0x3d0009,
+ 0x3d0009,
+ 0x3e0009,
+ 0x3e0009,
+ 0x370009,
+ 0x370009,
+ 0x2f000a,
+ 0x38000a,
+ 0x7000a,
+ 0x3f000a
+};
+const Int32 huff_tab9[204] =
+{
+ 0x1,
+ 0x1,
+ 0x1,
+ 0x1,
+ 0x1,
+ 0x1,
+ 0x1,
+ 0x1,
+ 0xd0003,
+ 0xd0003,
+ 0x10003,
+ 0x10003,
+ 0xe0004,
+ 0x1b0006,
+ 0x1b0006,
+ 0xf0006,
+ 0xf0006,
+ 0x1a0006,
+ 0x1a0006,
+ 0x20006,
+ 0x20006,
+ 0x280007,
+ 0x1c0007,
+ 0x100007,
+ 0x270008,
+ 0x270008,
+ 0x30008,
+ 0x30008,
+ 0x1d0008,
+ 0x1d0008,
+ 0x290008,
+ 0x290008,
+ 0x110008,
+ 0x110008,
+ 0x350008,
+ 0x350008,
+ 0x1e0008,
+ 0x1e0008,
+ 0x120008,
+ 0x120008,
+ 0x360009,
+ 0x2a0009,
+ 0x40009,
+ 0x340009,
+ 0x420009,
+ 0x1f0009,
+ 0x130009,
+ 0x2b0009,
+ 0x430009,
+ 0x4f0009,
+ 0x370009,
+ 0x5000a,
+ 0x20000a,
+ 0x41000a,
+ 0x14000a,
+ 0x2c000a,
+ 0x15000a,
+ 0x69000a,
+ 0x38000a,
+ 0x44000a,
+ 0x50000a,
+ 0x5c000a,
+ 0x6000a,
+ 0x6a000a,
+ 0x22000a,
+ 0x2d000a,
+ 0x21000a,
+ 0x39000a,
+ 0x76000a,
+ 0x16000a,
+ 0x5d000a,
+ 0x4e000b,
+ 0x45000b,
+ 0x51000b,
+ 0x6b000b,
+ 0x7000b,
+ 0x77000b,
+ 0x2f000b,
+ 0x3a000b,
+ 0x2e000b,
+ 0x8000b,
+ 0x83000b,
+ 0x52000b,
+ 0x23000b,
+ 0x46000b,
+ 0x68000b,
+ 0x5b000b,
+ 0x5e000b,
+ 0x84000b,
+ 0x78000b,
+ 0x6c000b,
+ 0x17000b,
+ 0x5f000b,
+ 0x53000b,
+ 0x47000b,
+ 0x3c000b,
+ 0x3b000b,
+ 0x30000b,
+ 0x90000b,
+ 0x49000b,
+ 0x75000b,
+ 0x6d000b,
+ 0x85000c,
+ 0x24000c,
+ 0x9000c,
+ 0x91000c,
+ 0x79000c,
+ 0x54000c,
+ 0x9d000c,
+ 0x3d000c,
+ 0x6e000c,
+ 0x18000c,
+ 0x7a000c,
+ 0x86000c,
+ 0x48000c,
+ 0x60000c,
+ 0x25000c,
+ 0x19000c,
+ 0x9e000c,
+ 0x92000c,
+ 0x31000c,
+ 0x4a000c,
+ 0x55000c,
+ 0x6f000c,
+ 0x93000c,
+ 0xa000c,
+ 0x61000c,
+ 0x9f000c,
+ 0x82000c,
+ 0x87000c,
+ 0x3e000c,
+ 0x56000c,
+ 0x26000c,
+ 0x7b000c,
+ 0x7c000c,
+ 0x3f000c,
+ 0x8f000c,
+ 0x57000c,
+ 0x32000c,
+ 0x4b000c,
+ 0x70000d,
+ 0x63000d,
+ 0xa1000d,
+ 0x33000d,
+ 0x94000d,
+ 0x62000d,
+ 0xa0000d,
+ 0x95000d,
+ 0x88000d,
+ 0x40000d,
+ 0x64000d,
+ 0x4c000d,
+ 0xb000d,
+ 0xa2000d,
+ 0x58000d,
+ 0x9c000d,
+ 0x89000d,
+ 0x4d000d,
+ 0x65000d,
+ 0x7d000d,
+ 0xc000d,
+ 0x96000d,
+ 0x71000d,
+ 0x7e000d,
+ 0x8a000d,
+ 0x66000d,
+ 0xa3000d,
+ 0x59000d,
+ 0x73000d,
+ 0x97000d,
+ 0x67000d,
+ 0x5a000d,
+ 0x72000e,
+ 0x72000e,
+ 0x8b000e,
+ 0x8b000e,
+ 0x74000e,
+ 0x74000e,
+ 0x7f000e,
+ 0x7f000e,
+ 0x80000e,
+ 0x80000e,
+ 0x81000e,
+ 0x81000e,
+ 0x8d000e,
+ 0x8d000e,
+ 0xa5000e,
+ 0xa5000e,
+ 0x8c000e,
+ 0x8c000e,
+ 0x98000e,
+ 0x98000e,
+ 0xa4000e,
+ 0xa4000e,
+ 0x99000e,
+ 0x99000e,
+ 0xa6000e,
+ 0xa6000e,
+ 0xa7000e,
+ 0xa7000e,
+ 0x8e000f,
+ 0x9a000f,
+ 0x9b000f,
+ 0xa8000f
+};
+const Int32 huff_tab10[186] =
+{
+ 0xe0004,
+ 0xe0004,
+ 0xe0004,
+ 0xe0004,
+ 0xf0004,
+ 0xf0004,
+ 0xf0004,
+ 0xf0004,
+ 0x1b0004,
+ 0x1b0004,
+ 0x1b0004,
+ 0x1b0004,
+ 0x1c0005,
+ 0x1c0005,
+ 0xd0005,
+ 0xd0005,
+ 0x10005,
+ 0x10005,
+ 0x100005,
+ 0x100005,
+ 0x290005,
+ 0x290005,
+ 0x280005,
+ 0x280005,
+ 0x1d0005,
+ 0x1d0005,
+ 0x2a0005,
+ 0x2a0005,
+ 0x1a0006,
+ 0x20006,
+ 0x1e0006,
+ 0x360006,
+ 0x110006,
+ 0x350006,
+ 0x6,
+ 0x370006,
+ 0x2b0006,
+ 0x270006,
+ 0x30006,
+ 0x380006,
+ 0x1f0006,
+ 0x430006,
+ 0x120007,
+ 0x420007,
+ 0x440007,
+ 0x2c0007,
+ 0x450007,
+ 0x390007,
+ 0x500007,
+ 0x200007,
+ 0x510007,
+ 0x340007,
+ 0x4f0007,
+ 0x40007,
+ 0x130007,
+ 0x2d0007,
+ 0x460007,
+ 0x520007,
+ 0x3a0007,
+ 0x530008,
+ 0x5d0008,
+ 0x2e0008,
+ 0x210008,
+ 0x470008,
+ 0x6a0008,
+ 0x5e0008,
+ 0x410008,
+ 0x5c0008,
+ 0x50008,
+ 0x690008,
+ 0x140008,
+ 0x6b0008,
+ 0x5f0008,
+ 0x3b0008,
+ 0x220008,
+ 0x540008,
+ 0x600008,
+ 0x150008,
+ 0x2f0008,
+ 0x6c0008,
+ 0x3c0008,
+ 0x480008,
+ 0x6d0008,
+ 0x490008,
+ 0x610009,
+ 0x550009,
+ 0x770009,
+ 0x4e0009,
+ 0x560009,
+ 0x780009,
+ 0x300009,
+ 0x760009,
+ 0x230009,
+ 0x60009,
+ 0x6e0009,
+ 0x790009,
+ 0x3d0009,
+ 0x840009,
+ 0x160009,
+ 0x620009,
+ 0x6f0009,
+ 0x7a0009,
+ 0x630009,
+ 0x850009,
+ 0x4a0009,
+ 0x860009,
+ 0x240009,
+ 0x830009,
+ 0x310009,
+ 0x7b0009,
+ 0x570009,
+ 0x680009,
+ 0x3e0009,
+ 0x5b0009,
+ 0x910009,
+ 0x64000a,
+ 0x92000a,
+ 0x88000a,
+ 0x17000a,
+ 0x90000a,
+ 0x7c000a,
+ 0x7000a,
+ 0x70000a,
+ 0x87000a,
+ 0x32000a,
+ 0x4b000a,
+ 0x71000a,
+ 0x94000a,
+ 0x8000a,
+ 0x93000a,
+ 0x25000a,
+ 0x65000a,
+ 0x58000a,
+ 0x89000a,
+ 0x3f000a,
+ 0x18000a,
+ 0x9e000a,
+ 0x7d000a,
+ 0x9f000a,
+ 0x95000a,
+ 0x4c000a,
+ 0xa0000a,
+ 0x96000a,
+ 0xa1000a,
+ 0x33000a,
+ 0x59000a,
+ 0x75000a,
+ 0x8a000a,
+ 0x82000a,
+ 0x9d000a,
+ 0x9000a,
+ 0x40000a,
+ 0x7e000a,
+ 0xa2000a,
+ 0x26000a,
+ 0x72000a,
+ 0x7f000b,
+ 0x19000b,
+ 0x97000b,
+ 0xa3000b,
+ 0x66000b,
+ 0x4d000b,
+ 0x5a000b,
+ 0x8b000b,
+ 0x73000b,
+ 0xa4000b,
+ 0xa000b,
+ 0x67000b,
+ 0x8f000b,
+ 0x8c000b,
+ 0x98000b,
+ 0x99000b,
+ 0xb000b,
+ 0x9a000b,
+ 0x80000b,
+ 0x8d000b,
+ 0x9c000b,
+ 0x74000b,
+ 0xa5000c,
+ 0x8e000c,
+ 0x81000c,
+ 0x9b000c,
+ 0xa7000c,
+ 0xc000c,
+ 0xa6000c,
+ 0xa8000c
+};
+const Int32 huff_tab11[301] =
+{
+ 0x4,
+ 0x4,
+ 0x4,
+ 0x4,
+ 0x120004,
+ 0x120004,
+ 0x120004,
+ 0x120004,
+ 0x1200005,
+ 0x1200005,
+ 0x110005,
+ 0x110005,
+ 0x10005,
+ 0x10005,
+ 0x230005,
+ 0x230005,
+ 0x130005,
+ 0x130005,
+ 0x240005,
+ 0x240005,
+ 0x140006,
+ 0x340006,
+ 0x350006,
+ 0x220006,
+ 0x250006,
+ 0x20006,
+ 0x360006,
+ 0x450007,
+ 0x150007,
+ 0x460007,
+ 0x260007,
+ 0x470007,
+ 0x370007,
+ 0x330007,
+ 0x30007,
+ 0x560007,
+ 0x570007,
+ 0x270007,
+ 0x480007,
+ 0x160007,
+ 0x580007,
+ 0x380007,
+ 0x590007,
+ 0x490008,
+ 0x680008,
+ 0x280008,
+ 0x670008,
+ 0x690008,
+ 0x390008,
+ 0x170008,
+ 0x540008,
+ 0x430008,
+ 0x1150008,
+ 0x1130008,
+ 0x1140008,
+ 0x6a0008,
+ 0x1160008,
+ 0x440008,
+ 0x4a0008,
+ 0x40008,
+ 0x320008,
+ 0x5a0008,
+ 0x650008,
+ 0x1170008,
+ 0x1120008,
+ 0x1180008,
+ 0x290008,
+ 0x790008,
+ 0x3a0008,
+ 0x6b0008,
+ 0x5b0008,
+ 0x760008,
+ 0x11a0008,
+ 0x7a0008,
+ 0x780008,
+ 0x1190008,
+ 0x870008,
+ 0x210008,
+ 0x180008,
+ 0x4b0008,
+ 0x11b0008,
+ 0x7b0008,
+ 0x11c0008,
+ 0x980008,
+ 0x1110008,
+ 0x6c0008,
+ 0xa90008,
+ 0x2a0008,
+ 0x5c0008,
+ 0xba0008,
+ 0x11d0008,
+ 0x8b0008,
+ 0x8a0008,
+ 0x3b0008,
+ 0x550008,
+ 0x11e0008,
+ 0xcb0008,
+ 0x7c0008,
+ 0x4c0008,
+ 0x6d0008,
+ 0x7d0008,
+ 0x50008,
+ 0x8c0009,
+ 0x11f0009,
+ 0xdc0009,
+ 0x190009,
+ 0x890009,
+ 0xfe0009,
+ 0x5d0009,
+ 0xed0009,
+ 0x3c0009,
+ 0x8d0009,
+ 0x7e0009,
+ 0x2b0009,
+ 0x8e0009,
+ 0x9b0009,
+ 0x9c0009,
+ 0x10f0009,
+ 0x4d0009,
+ 0x6e0009,
+ 0x660009,
+ 0x9d0009,
+ 0x5e0009,
+ 0x8f0009,
+ 0x7f0009,
+ 0x1a0009,
+ 0xad0009,
+ 0x60009,
+ 0xac0009,
+ 0x9a0009,
+ 0x9e0009,
+ 0x4e0009,
+ 0x2c0009,
+ 0x9f0009,
+ 0x3d0009,
+ 0x6f0009,
+ 0xae0009,
+ 0x900009,
+ 0xaf0009,
+ 0xa00009,
+ 0xbe0009,
+ 0x1b0009,
+ 0x770009,
+ 0xb00009,
+ 0x800009,
+ 0x3e0009,
+ 0x5f0009,
+ 0xab0009,
+ 0x4f0009,
+ 0xbd0009,
+ 0xdf0009,
+ 0x700009,
+ 0xe00009,
+ 0x2d0009,
+ 0x1100009,
+ 0x600009,
+ 0xc00009,
+ 0xbf000a,
+ 0xa1000a,
+ 0x81000a,
+ 0x91000a,
+ 0x10000a,
+ 0x51000a,
+ 0x7000a,
+ 0x40000a,
+ 0xc1000a,
+ 0xde000a,
+ 0xe1000a,
+ 0xcf000a,
+ 0x2f000a,
+ 0xe2000a,
+ 0x92000a,
+ 0x71000a,
+ 0xb2000a,
+ 0xb1000a,
+ 0xf0000a,
+ 0xd0000a,
+ 0x1c000a,
+ 0x50000a,
+ 0xbc000a,
+ 0x3f000a,
+ 0x1e000a,
+ 0xce000a,
+ 0x82000a,
+ 0x41000a,
+ 0x61000a,
+ 0x62000a,
+ 0xf2000a,
+ 0x52000a,
+ 0xc2000a,
+ 0xf1000a,
+ 0xd1000a,
+ 0xe3000a,
+ 0xd2000a,
+ 0x88000a,
+ 0xc3000a,
+ 0x2e000a,
+ 0xa2000a,
+ 0xf3000a,
+ 0x73000a,
+ 0xb4000a,
+ 0x101000a,
+ 0x93000a,
+ 0xa3000a,
+ 0xf4000a,
+ 0xb3000a,
+ 0x63000a,
+ 0xc4000a,
+ 0xef000a,
+ 0x30000a,
+ 0x72000a,
+ 0x1d000a,
+ 0xe5000a,
+ 0x8000a,
+ 0xe4000a,
+ 0x83000a,
+ 0xd3000a,
+ 0x84000a,
+ 0x102000a,
+ 0xcd000a,
+ 0x74000a,
+ 0x31000a,
+ 0x104000a,
+ 0x103000a,
+ 0x1f000a,
+ 0xa4000a,
+ 0x53000a,
+ 0xf5000a,
+ 0x95000a,
+ 0xe6000a,
+ 0x94000a,
+ 0x64000a,
+ 0x42000a,
+ 0xb5000a,
+ 0xc5000a,
+ 0xd4000a,
+ 0x105000a,
+ 0x106000a,
+ 0x96000a,
+ 0x100000a,
+ 0x85000a,
+ 0x99000a,
+ 0x9000a,
+ 0xa6000a,
+ 0xa5000a,
+ 0xd5000a,
+ 0xf6000a,
+ 0xb7000a,
+ 0xf7000a,
+ 0xd6000a,
+ 0x75000a,
+ 0x86000a,
+ 0xa7000b,
+ 0x107000b,
+ 0xc6000b,
+ 0xc9000b,
+ 0x20000b,
+ 0xb6000b,
+ 0xb8000b,
+ 0xe8000b,
+ 0xe7000b,
+ 0xc8000b,
+ 0xc7000b,
+ 0x97000b,
+ 0xf9000b,
+ 0xe9000b,
+ 0xd9000b,
+ 0x108000b,
+ 0xf8000b,
+ 0xaa000b,
+ 0xd7000b,
+ 0xa8000b,
+ 0xa000b,
+ 0xd8000b,
+ 0xbb000b,
+ 0xda000b,
+ 0xb9000b,
+ 0xea000b,
+ 0xd000b,
+ 0xfa000b,
+ 0x109000b,
+ 0x10a000b,
+ 0xca000b,
+ 0xfb000b,
+ 0xdd000b,
+ 0xb000b,
+ 0xeb000b,
+ 0x10b000b,
+ 0x10c000b,
+ 0xdb000b,
+ 0xee000b,
+ 0xfc000b,
+ 0xec000b,
+ 0xcc000b,
+ 0xfd000b,
+ 0xe000c,
+ 0xc000c,
+ 0x10d000c,
+ 0xff000c,
+ 0xf000c,
+ 0x10e000c
+};
+
+const UInt32 huff_tab_scl[188] =
+{
+ 0x3b0003,
+ 0x3b0003,
+ 0x3b0003,
+ 0x3b0003,
+ 0x3b0003,
+ 0x3b0003,
+ 0x3b0003,
+ 0x3b0003,
+ 0x3d0004,
+ 0x3d0004,
+ 0x3d0004,
+ 0x3d0004,
+ 0x3a0004,
+ 0x3a0004,
+ 0x3a0004,
+ 0x3a0004,
+ 0x3e0004,
+ 0x3e0004,
+ 0x3e0004,
+ 0x3e0004,
+ 0x390005,
+ 0x390005,
+ 0x3f0005,
+ 0x3f0005,
+ 0x380006,
+ 0x400006,
+ 0x370006,
+ 0x410006,
+ 0x420007,
+ 0x420007,
+ 0x420007,
+ 0x420007,
+ 0x360007,
+ 0x360007,
+ 0x360007,
+ 0x360007,
+ 0x430007,
+ 0x430007,
+ 0x430007,
+ 0x430007,
+ 0x350008,
+ 0x350008,
+ 0x440008,
+ 0x440008,
+ 0x340008,
+ 0x340008,
+ 0x450008,
+ 0x450008,
+ 0x330008,
+ 0x330008,
+ 0x460009,
+ 0x320009,
+ 0x310009,
+ 0x470009,
+ 0x48000a,
+ 0x48000a,
+ 0x48000a,
+ 0x48000a,
+ 0x30000a,
+ 0x30000a,
+ 0x30000a,
+ 0x30000a,
+ 0x49000a,
+ 0x49000a,
+ 0x49000a,
+ 0x49000a,
+ 0x2f000a,
+ 0x2f000a,
+ 0x2f000a,
+ 0x2f000a,
+ 0x4a000a,
+ 0x4a000a,
+ 0x4a000a,
+ 0x4a000a,
+ 0x2e000a,
+ 0x2e000a,
+ 0x2e000a,
+ 0x2e000a,
+ 0x4c000b,
+ 0x4c000b,
+ 0x4b000b,
+ 0x4b000b,
+ 0x4d000b,
+ 0x4d000b,
+ 0x4e000b,
+ 0x4e000b,
+ 0x2d000b,
+ 0x2d000b,
+ 0x2b000b,
+ 0x2b000b,
+ 0x2c000c,
+ 0x4f000c,
+ 0x2a000c,
+ 0x29000c,
+ 0x50000c,
+ 0x28000c,
+ 0x51000d,
+ 0x51000d,
+ 0x27000d,
+ 0x27000d,
+ 0x52000d,
+ 0x52000d,
+ 0x26000d,
+ 0x26000d,
+ 0x53000d,
+ 0x53000d,
+ 0x25000e,
+ 0x23000e,
+ 0x55000e,
+ 0x21000e,
+ 0x24000e,
+ 0x22000e,
+ 0x54000e,
+ 0x20000e,
+ 0x57000f,
+ 0x57000f,
+ 0x59000f,
+ 0x59000f,
+ 0x1e000f,
+ 0x1e000f,
+ 0x1f000f,
+ 0x1f000f,
+ 0x560010,
+ 0x1d0010,
+ 0x1a0010,
+ 0x1b0010,
+ 0x1c0010,
+ 0x180010,
+ 0x580010,
+ 0x190011,
+ 0x190011,
+ 0x160011,
+ 0x160011,
+ 0x170011,
+ 0x170011,
+ 0x5a0012,
+ 0x150012,
+ 0x130012,
+ 0x30012,
+ 0x10012,
+ 0x20012,
+ 0x12,
+ 0x620013,
+ 0x630013,
+ 0x640013,
+ 0x650013,
+ 0x660013,
+ 0x750013,
+ 0x610013,
+ 0x5b0013,
+ 0x5c0013,
+ 0x5d0013,
+ 0x5e0013,
+ 0x5f0013,
+ 0x600013,
+ 0x680013,
+ 0x6f0013,
+ 0x700013,
+ 0x710013,
+ 0x720013,
+ 0x730013,
+ 0x740013,
+ 0x6e0013,
+ 0x690013,
+ 0x6a0013,
+ 0x6b0013,
+ 0x6c0013,
+ 0x6d0013,
+ 0x760013,
+ 0x60013,
+ 0x80013,
+ 0x90013,
+ 0xa0013,
+ 0x50013,
+ 0x670013,
+ 0x780013,
+ 0x770013,
+ 0x40013,
+ 0x70013,
+ 0xf0013,
+ 0x100013,
+ 0x120013,
+ 0x140013,
+ 0x110013,
+ 0xb0013,
+ 0xc0013,
+ 0xe0013,
+ 0xd0013
+};
diff --git a/media/libstagefright/codecs/aacdec/huffcb.cpp b/media/libstagefright/codecs/aacdec/huffcb.cpp
new file mode 100644
index 0000000..30f38fa
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/huffcb.cpp
@@ -0,0 +1,381 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/huffcb.c
+ Funtions:
+ huffcb
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: Change variable names for clarity,
+ change variables 'base', 'sect_len_inc', and 'esc_val' to
+ UChar type.
+
+ Description: Add "if ((pSect[-1] % sfb_per_win) > max_sfb)" statement to
+ detect the error condition.
+ add more white space.
+
+ Description: eliminated "pSect[-1]%sfb_per_win" operation
+
+ Description: eliminated "pSect[-1]%sfb_per_win" operation
+
+ Description: (1) Pass in SectInfo pSect
+ (2) put BITS *pInputStream as second parameter
+
+ Description: Fix a failure for thrid party AAC encoding.
+ The problem came when the total and the
+ maximun number of active scale factor bands do not coincide.
+ This is a rare situation but produces a problem when decoding
+ encoders that tolerate this.
+
+ Description: Replace some instances of getbits to get9_n_lessbits
+ when the number of bits read is 9 or less and get1bits
+ when only 1 bit is read.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ UChar *pSect = pointer to array that contains the interleaved
+ information of huffman codebook index and section
+ length. Array contains:
+ [codebook index]
+ [section boundary]
+ [codebook index]
+ [section boundary]
+ ...
+
+ Int sectbits = array that defines the number of bits
+ used for expressing the escape value of
+ section length
+
+ Int tot_sfb = total number of sfb in one Frame
+
+ Int sfb_per_win = number of sfb in each sub-block (window)
+
+ UChar max_sfb = 1 + number of active sfbs - see reference (2) p56
+
+ BITS *pInputStream = pointer to input stream
+
+
+ Local Stores/Buffers/Pointers Needed:
+
+ UChar base = number of sfb in already detected sections
+
+ UChar sect_len_inc = section length increment in number of sfbs'
+
+ UChar esc_val = escape value for section length
+
+ Int bits = number of bits needed for expressing section length
+
+
+ Global Stores/Buffers/Pointers Needed:
+
+
+ Outputs:
+
+ num_sect = total number of sections in one frame
+
+
+ Pointers and Buffers Modified:
+
+ UChar *pSect = pointer to array where huffman codebook index and
+ section length are stored
+
+ Local Stores Modified:
+
+ Global Stores Modified:
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Background knowledge: 1024(960) coef's are separated into several sections,
+ each section is encoded with one single Huffman codebook, and each section
+ has a length of multiples of sfb.
+
+ max_sfb <= sfb_per_win <= tot_sfb
+ tot_sfb = total number of scalefactor bands in one frame (1024 coefs)
+
+ This function reads the codebook index and section boundaries (expressed
+ in number of sfb) from the input bitstream, store these information in
+ *pSect, and return the number of sections been detected. Returns 0 if there
+ is an error.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function should fill the array *pSect with section Huffman codebook
+ indexes and section boundaries
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+ (2) ISO/IEC 14496-3 1999(E)
+ Subpart 4 p55 (Recovering section_data())
+ p24-25 (Syntax of section_data())
+
+ (3) M. Bosi, K. Brandenburg, etc., "ISO/IEC MPEG-2 Advanced Audio Coding,"
+ J. Audio Eng. Soc., Vol.45, No.10, 1997 October
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ bits_needed_for_ESC = sectbits[0];
+ ESC_value = (1<<bits_needed_for_ESC) - 1;
+ num_of_section = 0;
+
+
+ FOR (base = 0; base<total_sfb AND num_of_section<total_sfb)
+ {
+ *pSect++ = getbits(LEN_CB, pInputStream); (read huffman_codebook_num)
+ sect_length_incr = getbits(bits_needed_for_ESC, pInputStream);
+
+ WHILE (sect_length_incr == ESC_value AND base < total_sfb)
+ {
+ base += ESC_value;
+ sect_length_incr = getbits(bits_needed_for_ESC, ebits);
+ }
+ ENDWHILE
+
+ base += sect_length_incr;
+ *pSect++ = base;
+ num_of_section++;
+
+ IF (num_of_sfb_for_this_group==max_sfb)
+ {
+ *pSect++ = 0; (use huffman codebook 0)
+ base += sfb_per_win - max_sfb;
+ *pSect++ = base;
+ num_of_section++;
+ }
+ ENDIF
+
+ IF (num_of_sfb_for_this_group > max_sfb)
+ break;
+ ENDIF
+
+ }
+ ENDFOR
+
+ IF (base != total_sfb OR num_of_section>total_sfb)
+ return 0;
+ ENDIF
+
+ return num_sect;
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "huffman.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Int huffcb(
+ SectInfo *pSect,
+ BITS *pInputStream,
+ Int sectbits[],
+ Int tot_sfb,
+ Int sfb_per_win,
+ Int max_sfb)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+
+ Int base; /* section boundary */
+ Int sect_len_incr;
+ Int esc_val; /* ESC of section length = 31(long), =7 (short) */
+ Int bits; /* # of bits used to express esc_val */
+ Int num_sect;
+ Int active_sfb;
+ Int group_base;
+
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ bits = sectbits[0]; /* 3 for SHORT_WIN, 5 for LONG_WIN */
+ esc_val = (1 << bits) - 1; /* ESC_value for section length */
+ num_sect = 0;
+ base = 0;
+ group_base = 0;
+
+ /* read until the end of one frame */
+ while ((base < tot_sfb) && (num_sect < tot_sfb))
+ {
+
+ pSect->sect_cb = get9_n_lessbits(
+ LEN_CB,
+ pInputStream); /* section codebook */
+
+ sect_len_incr = get9_n_lessbits(
+ bits,
+ pInputStream); /* length_incr */
+
+
+ /* read until non-ESC value, see p55 reference 2 */
+ while ((sect_len_incr == esc_val) && (base < tot_sfb))
+ {
+ base += esc_val;
+
+ sect_len_incr = get9_n_lessbits(
+ bits,
+ pInputStream);
+ }
+
+ base += sect_len_incr;
+ pSect->sect_end = base; /* total # of sfb until current section */
+ pSect++;
+ num_sect++;
+
+ /* active_sfb = base % sfb_per_win; */
+ active_sfb = base - group_base;
+
+ /*
+ * insert a zero section for regions above max_sfb for each group
+ * Make sure that active_sfb is also lesser than tot_sfb
+ */
+
+ if ((active_sfb == max_sfb) && (active_sfb < tot_sfb))
+ {
+ base += (sfb_per_win - max_sfb);
+ pSect->sect_cb = 0; /* huffman codebook 0 */
+ pSect->sect_end = base;
+ num_sect++;
+ pSect++;
+ group_base = base;
+ }
+ else if (active_sfb > max_sfb)
+ {
+ /* within each group, the sections must delineate the sfb
+ * from zero to max_sfb so that the 1st section within each
+ * group starts at sfb0 and the last section ends at max_sfb
+ * see p55 reference 2
+ */
+ break;
+ }
+
+ } /* while (base=0) */
+
+
+ if (base != tot_sfb || num_sect > tot_sfb)
+ {
+ num_sect = 0; /* error */
+ }
+
+ return num_sect;
+
+} /* huffcb */
+
+
diff --git a/media/libstagefright/codecs/aacdec/huffdecode.cpp b/media/libstagefright/codecs/aacdec/huffdecode.cpp
new file mode 100644
index 0000000..890a6fb
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/huffdecode.cpp
@@ -0,0 +1,528 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: huffdecode.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: Change variable types.
+
+ Description: (1) Modified to bring in-line with PV standards.
+ (2) Eliminated global_gain on stack,
+ getics() has to define this parameter on its stack.
+ (3) Eliminated multiple returns
+ (4) Altered return logic of getics()
+ (5) Convert Real coef -> Int32 coef
+ (6) Move BITS *pInputStream to 2nd parameter of huffdecode.c
+ and getics.c
+ (7) Pass pFrameInfo per channel, because two channels can have
+ different windows
+
+ Description: (1) Eliminated function call to chn_config
+ (2) Eliminate widx calculation
+ (3) copy channel info from left to right when common_window
+ is enabled
+ (4) add error checking of getmask return value
+
+ Description: Change default_position to current_program
+
+ Description: Remove prstflag
+
+ Description: Modify call to get_ics_info
+
+ Description: Modified so getmask is NOT called if the status returned
+ from get_ics_info indicates an error.
+
+ Description:
+ (1) Added include of "e_ElementId.h"
+ Previously, this function was relying on another include file
+ to include e_ElementId.h
+
+ (2) Updated the copyright header.
+
+ Description: Modified to include usage of the new "shared memory" structures
+ defined in s_tDec_Int_File.h and s_tDec_Int_Chan.h
+
+ Description:
+ (1) Updated to reflect the fact that the temporary FrameInfo used by getics.c
+ was moved into the region of memory shared with fxpCoef.
+
+ Description:
+ (1) Removed first parameter to getics. The temporary FrameInfo was
+ unnecessary.
+
+ Description: Replace some instances of getbits to get9_n_lessbits
+ when the number of bits read is 9 or less and get1bits
+ when only 1 bit is read.
+
+ Description: Relaxed tag verification. Some encoder do not match the tag
+ to the channel ID (as the standard request to differentiate
+ different channel), in our wireless work, with only mono
+ or stereo channel, this become restrictive to some encoders
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ id_syn_ele = identification flag for channel syntactic element, Int
+
+ pInputStream= pointer to input bitstream, BITS.
+
+ pVars = pointer to structure that holds information for decoding,
+ tDec_Int_File
+
+ pChVars[] = pointer to structure that holds channel information,
+ tDec_Int_Chan
+
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ status = 0 if success
+ non-zero otherwise
+
+ Pointers and Buffers Modified:
+ pChVars->sect contents updated by newly decoded section information
+ of current frame
+
+ pChVars->factors contents updated by newly decoded scalefactors
+
+ pChVars->ch_coef contents updated by newly decoded spectral coefficients
+
+ PChVars->tns contents updated by newly decoded TNS information
+
+ pVars->hasmask contents updated by newly decoded Mid/Side mask
+ information
+
+ pVars->pulseInfo contents updated by newly decoded pulse data information
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function offers a framework for decoding the data of the next 1024
+ samples. It maps the channel configuration according to the id_syn_ele flag,
+ configures the channel information, and calls getics to do huffman decoding
+ The function returns 1 if there was an error
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function should set up the channel configuration for huffman decoding
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+ (2) ISO/IEC 14496-3: 1999(E)
+ Subpart 4 p15 (single_channel_element, channel_pair_element)
+ p15 (Table 4.4.5 getmask)
+ p16 (Table 4.4.6 get_ics_info)
+ p24 (Table 4.4.24 getics)
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ tag = CALL getbits(LEN_TAG,pInputStream)
+ MODIFYING(pInputStream)
+ RETURNING(tag)
+
+ common_window = 0;
+
+ IF (id_syn_ele == ID_CPE)
+ THEN
+ common_window = CALL getbits(LEN_COM_WIN,pInputStream);
+ MODIFYING(pInputStream)
+ RETURNING(common_window)
+ ENDIF
+
+ pMcInfo = &pVars->mc_info;
+
+ IF ( (pMcInfo->ch_info[0].cpe != id_syn_ele) OR
+ (pMcInfo->ch_info[0].tag != tag) )
+ THEN
+ status = 1;
+ ENDIF
+
+
+ IF (status == SUCCESS)
+ THEN
+ IF (id_syn_ele == ID_SCE)
+ THEN
+
+ leftCh = 0;
+ RIGHT = 0;
+ pChVars[leftCh]->hasmask = 0;
+ ELSEIF (id_syn_ele == ID_CPE)
+
+ leftCh = 0;
+ rightCh = 1;
+
+ IF (common_window != FALSE)
+ THEN
+
+ CALL get_ics_info(
+ audioObjectType = pVars->mc_info.audioObjectType,
+ pInputStream = pInputStream,
+ common_window = common_window,
+ pWindowSequence = &pChVars[leftCh]->wnd,
+ &pChVars[leftCh]->wnd_shape_this_bk,
+ pChVars[leftCh]->group,
+ &pChVars[leftCh]->max_sfb,
+ pVars->winmap,
+ &pChVars[leftCh]->lt_status,
+ &pChVars[rightCh]->lt_status);
+ MODIFYING(pInputStream, wnd, wnd_shape_this_bk,group,
+ max_sfb, lt_status)
+ RETURNING(status)
+
+ IF (status == SUCCESS)
+ THEN
+
+ pChVars[rightCh]->wnd = pChVars[leftCh]->wnd;
+ pChVars[rightCh]->wnd_shape_this_bk =
+ pChVars[leftCh]->wnd_shape_this_bk;
+ pChVars[rightCh]->max_sfb = pChVars[leftCh]->max_sfb;
+ pv_memcpy(
+ pChVars[rightCh]->group,
+ pChVars[leftCh]->group,
+ NSHORT*sizeof(pChVars[leftCh]->group[0]));
+
+ hasmask = CALL getmask(
+ pVars->winmap[pChVars[leftCh]->wnd],
+ pInputStream,
+ pChVars[leftCh]->group,
+ pChVars[leftCh]->max_sfb,
+ pChVars[leftCh]->mask);
+ MODIFYING(pInputStream, mask)
+ RETURNING(hasmask)
+
+ IF (hasmask == MASK_ERROR)
+ THEN
+ status = 1;
+ ENDIF
+ pChVars[leftCh]->hasmask = hasmask;
+ pChVars[rightCh]->hasmask = hasmask;
+
+ ENDIF
+
+ ELSE
+
+ pChVars[leftCh]->hasmask = 0;
+ pChVars[rightCh]->hasmask = 0;
+ ENDIF(common_window)
+
+ ENDIF(id_syn_ele)
+
+ ENDIF (status)
+
+ ch = leftCh;
+
+ WHILE((ch <= rightCh) AND (status == SUCCESS))
+
+ status = CALL getics(
+ pInputStream,
+ common_window,
+ pVars,
+ pChVars[ch],
+ pChVars[ch]->group,
+ &pChVars[ch]->max_sfb,
+ pChVars[ch]->cb_map,
+ &pChVars[ch]->tns,
+ pVars->winmap,
+ &pVars->pulseInfo,
+ pChVars[ch]->sect);
+ MODIFYING(pInputStream,pVarsp,ChVars[ch],group,
+ max_sfb,tns,pulseInfo,sect)
+ RETURNING(status)
+
+ ch++;
+
+ ENDWHILE
+
+ RETURN status;
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "aac_mem_funcs.h"
+#include "huffman.h"
+#include "e_maskstatus.h"
+#include "e_elementid.h"
+#include "get_ics_info.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define LEFT (0)
+#define RIGHT (1)
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Int huffdecode(
+ Int id_syn_ele,
+ BITS *pInputStream,
+ tDec_Int_File *pVars,
+ tDec_Int_Chan *pChVars[])
+
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ Int ch;
+ Int common_window;
+ Int hasmask;
+ Int status = SUCCESS;
+ Int num_channels = 0;
+ MC_Info *pMcInfo;
+
+ per_chan_share_w_fxpCoef *pChLeftShare; /* Helper pointer */
+ per_chan_share_w_fxpCoef *pChRightShare; /* Helper pointer */
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ get9_n_lessbits(
+ LEN_TAG,
+ pInputStream);
+
+ /* suppose an un-supported id_syn_ele will never be passed */
+
+ common_window = 0;
+
+ if (id_syn_ele == ID_CPE)
+ {
+ common_window =
+ get1bits(pInputStream);
+ }
+
+ pMcInfo = &pVars->mc_info;
+
+ /*
+ * check if provided info (num of channels) on audio config,
+ * matches read bitstream data, if not, allow update only once.
+ * In almost all cases it should match.
+ */
+ if ((pMcInfo->ch_info[0].cpe != id_syn_ele))
+ {
+ if (pVars->mc_info.implicit_channeling) /* check done only once */
+ {
+ pMcInfo->ch_info[0].cpe = id_syn_ele & 1; /* collect info from bitstream
+ * implicit_channeling flag is locked
+ * after 1st frame, to avoid toggling
+ * parameter in the middle of the clip
+ */
+ pMcInfo->nch = (id_syn_ele & 1) + 1; /* update number of channels */
+ }
+ else
+ {
+ status = 1; /* ERROR break if syntax error persist */
+ }
+ }
+
+ if (status == SUCCESS)
+ {
+ if (id_syn_ele == ID_SCE)
+ {
+
+ num_channels = 1;
+ pVars->hasmask = 0;
+ }
+ else if (id_syn_ele == ID_CPE)
+ {
+ pChLeftShare = pChVars[LEFT]->pShareWfxpCoef;
+ pChRightShare = pChVars[RIGHT]->pShareWfxpCoef;
+ num_channels = 2;
+
+ if (common_window != FALSE)
+ {
+
+ status = get_ics_info(
+ (tMP4AudioObjectType) pVars->mc_info.audioObjectType,
+ pInputStream,
+ (Bool)common_window,
+ (WINDOW_SEQUENCE *) & pChVars[LEFT]->wnd,
+ (WINDOW_SHAPE *) & pChVars[LEFT]->wnd_shape_this_bk,
+ pChLeftShare->group,
+ (Int *) & pChLeftShare->max_sfb,
+ pVars->winmap,
+ (LT_PRED_STATUS *) & pChLeftShare->lt_status,
+ (LT_PRED_STATUS *) & pChRightShare->lt_status);
+
+ if (status == SUCCESS)
+ {
+ /* copy left channel info to right channel */
+ pChVars[RIGHT]->wnd = pChVars[LEFT]->wnd;
+ pChVars[RIGHT]->wnd_shape_this_bk =
+ pChVars[LEFT]->wnd_shape_this_bk;
+ pChRightShare->max_sfb = pChLeftShare->max_sfb;
+ pv_memcpy(
+ pChRightShare->group,
+ pChLeftShare->group,
+ NSHORT*sizeof(pChLeftShare->group[0]));
+
+ hasmask = getmask(
+ pVars->winmap[pChVars[LEFT]->wnd],
+ pInputStream,
+ pChLeftShare->group,
+ pChLeftShare->max_sfb,
+ pVars->mask);
+
+ if (hasmask == MASK_ERROR)
+ {
+ status = 1; /* ERROR code */
+ }
+ pVars->hasmask = hasmask;
+
+ } /* if (status == 0) */
+ }
+ else
+ {
+ pVars->hasmask = 0;
+ } /* if (common_window) */
+
+ } /* if (id_syn_ele) */
+
+ } /* if (status) */
+
+ ch = 0;
+ while ((ch < num_channels) && (status == SUCCESS))
+ {
+ pChLeftShare = pChVars[ch]->pShareWfxpCoef;
+
+ status = getics(
+ pInputStream,
+ common_window,
+ pVars,
+ pChVars[ch],
+ pChLeftShare->group,
+ &pChLeftShare->max_sfb,
+ pChLeftShare->cb_map,
+ &pChLeftShare->tns,
+ pVars->winmap,
+ &pVars->share.a.pulseInfo,
+ pVars->share.a.sect);
+
+ ch++;
+
+ } /* while (ch) */
+
+ /*----------------------------------------------------------------------------
+ ; Return status
+ ----------------------------------------------------------------------------*/
+
+ return status;
+
+} /* huffdecode */
+
diff --git a/media/libstagefright/codecs/aacdec/hufffac.cpp b/media/libstagefright/codecs/aacdec/hufffac.cpp
new file mode 100644
index 0000000..e5a9c59
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/hufffac.cpp
@@ -0,0 +1,550 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/hufffac.c
+ Funtions:
+ hufffac
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: (1) Modified with new templates,
+ (2) Modified variable names for clarity
+ (3) adjusted variables of "for loop"
+ (4) eliminated multiple returns, use return valid
+
+ Description: (1) Change return logic: 0 if success, 1 if error
+ (2) Define SectInfo structure to store section codebook index
+ and section boundary
+ (3) Substitute "switch" with "if- else if"
+ (4) move BITS *pInputStream to second pass-in parameter
+ (5) pass in huffBookUsed[] to save stack size
+
+ Description: (1) Remove pass in parameter Hcb pBook
+
+ Description: Use binary tree search in decode_huff_cw_binary
+
+ Description: Use decode_huff_scl function.
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ *pFrameInfo = pointer to structure that holds information
+ of each Frame. type FrameInfo
+
+ *pInputStream = pointer to input bitstream. type BITS
+
+ *pGroup = pointer to array that contains the index of the first
+ window in each group, type UChar
+
+ nsect = number of sections to be decoded. type Int
+
+ *pSect = pointer to structure array that contains the huffman
+ codebook index and section boundary for each section,
+ type SectInfo
+
+ global_gain = initial value for "DPCM encoded" scalefactors and noise
+ energy, type Int
+
+ *pFactors = pointer to array that stores the decoded scalefactors,
+ intensity position or noise energy, type Int
+
+ huffBookUsed = array that will hold the huffman codebook index for
+ each sfb, type Int
+
+ *pBook = pointer to structure that contains the huffman codebook
+ information, such as dimension, Largest Absolute Value
+ (LAV) of each huffman codebook, etc. type Hcb
+
+
+ Local Stores/Buffers/Pointers Needed: None
+
+ Global Stores/Buffers/Pointers Needed: None
+
+ Outputs:
+ 0 if success
+ 1 if error
+
+ Pointers and Buffers Modified:
+
+ Int *pFactors contains the newly decoded scalefactors and/or
+ intensity position and/or noise energy level
+
+ Local Stores Modified:
+
+ Global Stores Modified:
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function first reads the Huffman codebook index of all sections within
+ one Frame. Then, depending on the huffman codebook index of each section,
+ the function decodes the scalefactors, and/or intensity positions
+ (INTENSITY_HCB, INTENSITY_HCB2), and/or noise energy (NOISE_HCB)
+ for every scalefactor band in each section.
+ The function returns 0 upon successful decoding, returns 1 if error.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function should replace the content of the array pFactors with the
+ decoded scalefactors and/or intensity positions and/or noise energy
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+ (2) ISO/IEC 14496-3: 1999(E)
+ Subpart 4 p72-73 (scalefactors)
+ p76 (decoding)
+ p78 (Table 4.6.1, Table 4.6.2)
+ p93-94 (INTENSITY_HCB)
+ p123 (NOISE_HCB)
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ status = SUCCESS;
+
+ CALL pv_memset(pHuffBookUsed, ZERO_HCB, MAXBANDS*sizeof(*pHuffBookUsed));
+
+ CALL pv_memset(pFactors, ZERO_HCB, MAXBANDS*sizeof(*pFactors));
+
+ sect_start = 0;
+
+ FOR(sect_idx = nsect; sect_idx > 0; sect_idx--)
+ {
+ sect_cb = pSect->sect_cb;
+ sect_end = pSect->sect_end;
+ pSect++;
+
+ CALL pv_memset(
+ &pHuffBookUsed[sect_start],
+ sect_cb,
+ (sect_end - sect_start));
+
+ }
+ ENDFOR
+
+ fac = global_gain;
+ is_pos = 0;
+ noise_nrg = global_gain - NOISE_OFFSET;
+
+ pTable = pBook[BOOKSCL].pTable;
+ group_win = 0;
+ group_end = 0;
+
+ WHILE((group_end < pFrameInfo->num_win)&&(status == SUCCESS))
+ {
+ nsfb_win = pFrameInfo->sfb_per_win[group_end];
+ group_end = *pGroup++;
+
+ FOR(sfb = 0; sfb < nsfb_win; sfb++)
+ {
+ IF ((pHuffBookUsed[sfb] > 0)&&(pHuffBookUsed[sfb] < BOOKSCL))
+ {
+ cw_index = CALL decode_huff_cw_binary(pTable, pInputStream);
+
+ fac += cw_index - MIDFAC;
+
+ IF((fac >= 2*TEXP) || (fac < 0))
+ {
+ status = 1;
+ }
+ ELSE
+ {
+ pFactors[sfb] = fac;
+ }
+ ENDIF (fac)
+
+ }
+ ELSE IF (pHuffBookUsed[sfb] == ZERO_HCB)
+ {
+ do nothing;
+ }
+
+ ELSE IF ((pHuffBookUsed[sfb] == INTENSITY_HCB)||
+ (pHuffBookUsed[sfb] == INTENSITY_HCB2))
+ {
+ cw_index = CALL decode_huff_cw_binary(pTable, pInputStream);
+
+ is_pos += cw_index - MIDFAC;
+ pFactors[sfb] = is_pos;
+ }
+
+ ELSE IF (pHuffBookUsed[sfb] == NOISE_HCB)
+ {
+ IF (noise_pcm_flag == TRUE)
+ {
+ noise_pcm_flag = FALSE;
+ dpcm_noise_nrg = CALL getbits(
+ NOISE_PCM_BITS,
+ pInputStream);
+
+ dpcm_noise_nrg -= NOISE_PCM_OFFSET;
+ }
+ ELSE
+ {
+ dpcm_noise_nrg = CALL decode_huff_cw_binary(
+ pTable,
+ pInputStream);
+
+ dpcm_noise_nrg -= MIDFAC;
+ }
+ ENDIF (noise_pcm_flag)
+
+ noise_nrg += dpcm_noise_nrg;
+ pFactors[sfb] = noise_nrg;
+ }
+
+ ELSE IF (pHuffBookUsed[sfb] == BOOKSCL)
+ {
+ status = 1;
+ }
+ ENDIF (pHuffBookUsed[sfb])
+
+ }
+ ENDFOR (sfb)
+
+ IF (pFrameInfo->islong == FALSE)
+ {
+
+ FOR(group_win++; group_win < group_end; group_win++)
+ {
+ FOR (sfb=0; sfb < nsfb_win; sfb++)
+ {
+ pFactors[sfb + nsfb_win] = pFactors[sfb];
+ }
+ ENDFOR
+
+ pFactors += nsfb_win;
+ }
+ ENDFOR
+
+ }
+ ENDIF (pFrameInfo)
+
+ pHuffBookUsed += nsfb_win;
+ pFactors += nsfb_win;
+
+ }
+ ENDWHILE (group_end)
+
+ return status;
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "aac_mem_funcs.h" /* pv_memset */
+#include "s_frameinfo.h"
+#include "s_bits.h"
+#include "s_sectinfo.h"
+#include "s_huffman.h"
+#include "ibstream.h"
+
+#include "hcbtables.h"
+#include "e_huffmanconst.h"
+#include "e_infoinitconst.h"
+#include "huffman.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Int hufffac(
+ FrameInfo *pFrameInfo,
+ BITS *pInputStream,
+ Int *pGroup, /* may be changed to Int */
+ Int nsect,
+ SectInfo *pSect, /* may be changed to Int */
+ Int global_gain,
+ Int *pFactors,
+ Int huffBookUsed[])
+{
+ Int sect_idx;
+ Int group_end; /* index of 1st window in next group */
+ Int group_win; /* window index within group */
+ Int cw_index; /* huff codeword index */
+ Int nsfb_win; /* # of scfbands per window */
+ Int sfb; /* scalefactor band index */
+ Int sect_cb; /* huff codebook # for each section */
+ Int fac; /* decoded scf */
+ Int is_pos; /* intensity stereo position */
+ Int noise_pcm_flag = TRUE; /* first PNS sfb */
+ Int dpcm_noise_nrg; /* dpcm noise energy */
+ Int noise_nrg; /* noise energy */
+ Int status = SUCCESS; /* status of decoding */
+ Int *pHuffBookUsed = &huffBookUsed[0];
+
+
+ pv_memset(pFactors,
+ ZERO_HCB,
+ MAXBANDS*sizeof(*pFactors));
+
+
+ if (nsect)
+ {
+ /* read section length and codebook */
+
+ if (nsect == 1) /* long window */
+ {
+ sect_cb = pSect->sect_cb; /* codebook for this section */
+
+ /* all sfbs in one section share the same codebook */
+
+ for (sfb = pSect->sect_end >> 2; sfb != 0; sfb--)
+ {
+ *(pHuffBookUsed++) = sect_cb;
+ *(pHuffBookUsed++) = sect_cb;
+ *(pHuffBookUsed++) = sect_cb;
+ *(pHuffBookUsed++) = sect_cb;
+ }
+ for (sfb = pSect->sect_end & 3; sfb != 0; sfb--)
+ {
+ *(pHuffBookUsed++) = sect_cb;
+ }
+
+ }
+ else /* short */
+ {
+ Int sect_start = 0; /* start index of sfb for each section */
+ for (sect_idx = nsect; sect_idx > 0; sect_idx--)
+ {
+ sect_cb = pSect->sect_cb; /* codebook for this section */
+
+ /* all sfbs in one section share the same codebook */
+ for (sfb = sect_start; sfb < pSect->sect_end; sfb++)
+ {
+ pHuffBookUsed[sfb] = sect_cb;
+ }
+
+ pSect++;
+ sect_start = sfb;
+
+ } /* for (sect_idx) */
+ }
+ }
+ else
+ {
+ /* clear array for the case of max_sfb == 0 */
+ pv_memset(pHuffBookUsed,
+ ZERO_HCB,
+ MAXBANDS*sizeof(*pHuffBookUsed));
+ }
+
+ pHuffBookUsed = &huffBookUsed[0];
+
+ /* scale factors and noise energy are dpcm relative to global gain
+ * intensity positions are dpcm relative to zero
+ */
+ fac = global_gain;
+ is_pos = 0;
+ noise_nrg = global_gain - NOISE_OFFSET;
+
+ /* get scale factors,
+ * use reserved Table entry = 12, see reference (2) p78 Table 4.6.2
+ */
+ group_win = 0;
+ group_end = 0;
+
+
+ /* group by group decoding scalefactors and/or noise energy
+ * and/or intensity position
+ */
+ while ((group_end < pFrameInfo->num_win) && (status == SUCCESS))
+ {
+ nsfb_win = pFrameInfo->sfb_per_win[group_end];
+ group_end = *pGroup++; /* index of 1st window in next group */
+
+ /* decode scf in first window of each group */
+
+ for (sfb = 0; sfb < nsfb_win; sfb++)
+ {
+
+ switch (pHuffBookUsed[sfb])
+ {
+ case ZERO_HCB:
+ break;
+ case INTENSITY_HCB:
+ case INTENSITY_HCB2:
+ /* intensity books */
+ /* decode intensity position */
+ cw_index = decode_huff_scl(pInputStream);
+
+ is_pos += cw_index - MIDFAC;
+ pFactors[sfb] = is_pos;
+ break;
+ case NOISE_HCB:
+ /* noise books */
+ /* decode noise energy */
+ if (noise_pcm_flag == TRUE)
+ {
+ noise_pcm_flag = FALSE;
+ dpcm_noise_nrg = get9_n_lessbits(NOISE_PCM_BITS,
+ pInputStream);
+
+ dpcm_noise_nrg -= NOISE_PCM_OFFSET;
+ }
+ else
+ {
+ dpcm_noise_nrg = decode_huff_scl(pInputStream);
+
+ dpcm_noise_nrg -= MIDFAC;
+ } /* if (noise_pcm_flag) */
+
+ noise_nrg += dpcm_noise_nrg;
+ pFactors[sfb] = noise_nrg;
+ break;
+ case BOOKSCL:
+ status = 1; /* invalid books */
+ sfb = nsfb_win; /* force out */
+ break;
+ default:
+ /* spectral books */
+ /* decode scale factors */
+ cw_index = decode_huff_scl(pInputStream);
+
+ fac += cw_index - MIDFAC; /* 1.5 dB */
+ if ((fac >= 2*TEXP) || (fac < 0))
+ {
+ status = 1; /* error, MUST 0<=scf<256, Ref. p73 */
+ }
+ else
+ {
+ pFactors[sfb] = fac; /* store scf */
+ } /* if (fac) */
+ }
+
+ } /* for (sfb=0), first window decode ends */
+
+ /* expand scf to other windows in the same group */
+ if (pFrameInfo->islong == FALSE)
+ {
+
+ for (group_win++; group_win < group_end; group_win++)
+ {
+ for (sfb = 0; sfb < nsfb_win; sfb++)
+ {
+ pFactors[sfb + nsfb_win] = pFactors[sfb];
+ }
+ pFactors += nsfb_win;
+ }
+
+ } /* if (pFrameInfo->islong), one group decode ends */
+
+
+ /* points to next group */
+ pHuffBookUsed += nsfb_win;
+ pFactors += nsfb_win;
+
+ } /* while (group_end), all groups decode end */
+
+ return status;
+
+} /* hufffac */
+
diff --git a/media/libstagefright/codecs/aacdec/huffman.h b/media/libstagefright/codecs/aacdec/huffman.h
new file mode 100644
index 0000000..030ae23
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/huffman.h
@@ -0,0 +1,241 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: .huffman.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Put declaration of getfill in this file.
+
+ Description: Remove prstflag from get_ics_info declaration.
+
+ Description: Trivial change of the data type of one of the parameters to
+ get_ics_info.
+
+ Description: Change where get_ics_info is declared.
+
+ Description: Clean up comments
+
+ Description: (1) Add declaration of binary tree search function for Huffman
+ decoding
+ (2) #if the traditional and optimized linear seach methods.
+
+ Description: Modified per review comments
+ (1) delete #if traditional and optimized linear seach methods
+
+ Description: Merged Ken's change on getics: delete pFrameInfo from argument
+ list
+
+ Description: Added function definition for table specific huffman decoding
+ functions.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ include function prototype definitions for Huffman decoding module
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef HUFFMAN_H
+#define HUFFMAN_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_frameinfo.h"
+#include "s_sectinfo.h"
+#include "s_pulseinfo.h"
+#include "s_tdec_int_file.h"
+#include "s_tdec_int_chan.h"
+#include "ibstream.h"
+
+#include "s_hcb.h"
+#include "hcbtables.h"
+
+#include "get_pulse_data.h"
+#include "get_ics_info.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define DIMENSION_4 4
+#define DIMENSION_2 2
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Int decode_huff_cw_tab1(
+ BITS *pInputStream);
+
+ Int decode_huff_cw_tab2(
+ BITS *pInputStream);
+
+ Int decode_huff_cw_tab3(
+ BITS *pInputStream);
+
+ Int decode_huff_cw_tab4(
+ BITS *pInputStream);
+
+ Int decode_huff_cw_tab5(
+ BITS *pInputStream);
+
+ Int decode_huff_cw_tab6(
+ BITS *pInputStream);
+
+ Int decode_huff_cw_tab7(
+ BITS *pInputStream);
+
+ Int decode_huff_cw_tab8(
+ BITS *pInputStream);
+
+ Int decode_huff_cw_tab9(
+ BITS *pInputStream);
+
+ Int decode_huff_cw_tab10(
+ BITS *pInputStream);
+
+ Int decode_huff_cw_tab11(
+ BITS *pInputStream);
+
+ Int decode_huff_scl(
+ BITS *pInputStream);
+
+ Int infoinit(
+ const Int sampling_rate_idx,
+ FrameInfo **ppWin_seq_info,
+ Int *pSfbwidth128);
+
+ Int huffcb(
+ SectInfo *pSect,
+ BITS *pInputStream,
+ Int *pSectbits,
+ Int tot_sfb,
+ Int sfb_per_sbk,
+ Int max_sfb);
+
+ Int hufffac(
+ FrameInfo *pFrameInfo,
+ BITS *pInputStream,
+ Int *pGroup,
+ Int nsect,
+ SectInfo *pSect,
+ Int global_gain,
+ Int *pFactors,
+ Int huffBookUsed[]);
+
+ Int huffspec_fxp(
+ FrameInfo *pFrameInfo,
+ BITS *pInputStream,
+ Int nsect,
+ SectInfo *pSectInfo,
+ Int factors[],
+ Int32 coef[],
+ Int16 quantSpec[],
+ Int16 tmp_spec[],
+ const FrameInfo *pLongFrameInfo,
+ PulseInfo *pPulseInfo,
+ Int qFormat[]);
+
+ Int huffdecode(
+ Int id_syn_ele,
+ BITS *pInputStream,
+ tDec_Int_File *pVars,
+ tDec_Int_Chan *pChVars[]);
+
+ void deinterleave(
+ Int16 interleaved[],
+ Int16 deinterleaved[],
+ FrameInfo *pFrameInfo);
+
+ Int getics(
+
+ BITS *pInputStream,
+ Int common_window,
+ tDec_Int_File *pVars,
+ tDec_Int_Chan *pChVars,
+ Int group[],
+ Int *pMax_sfb,
+ Int *pCodebookMap,
+ TNS_frame_info *pTnsInfo,
+ FrameInfo **pWinMap,
+ PulseInfo *pPulseInfo,
+ SectInfo sect[]);
+
+ void calc_gsfb_table(
+ FrameInfo *pFrameInfo,
+ Int group[]);
+
+ Int getmask(
+ FrameInfo *pFrameInfo,
+ BITS *pInputStream,
+ Int *pGroup,
+ Int max_sfb,
+ Int *pMask);
+
+ void getgroup(
+ Int group[],
+ BITS *pInputStream);
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/huffspec_fxp.cpp b/media/libstagefright/codecs/aacdec/huffspec_fxp.cpp
new file mode 100644
index 0000000..b18c12d
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/huffspec_fxp.cpp
@@ -0,0 +1,671 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: huffspec_fxp.c
+ Funtions:
+ huffspec_fxp
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: (1) Modified to keep in-line with PV standards
+ (2) Eliminated "continue" in if(sect_cb==ZERO_HCB||...)
+
+ Description: (1) Use SectInfo *pSect
+ (2) Convert 'Real' to 'Int32', float -> fixed-point
+ (3) move BITS *pInputStream to second parameter
+ (4) pass in quantSpec and tmp_spec, scratch shared with hufffac
+ (5) pass in FrameInfo *pLongFrameInfo, eliminate only_long_info
+
+ Description: (1) Eliminate parameter Hcb *book, because of eliminating
+ function 'hufftab.c', Hcb hcbbook defined as a
+ const structure in 'hcbtables.h'.
+ (2) Replace three nested 'for' loops with a for-while loop in
+ the rescaling part.
+ (3) Change esc_iquant-> esc_iquant_fxp, call esc_iquant_fxp()
+ by sfb
+
+ Description: Cleaned up include files.
+
+ Description: Correct definition of stack variable "scale".
+ It was defined as Int, but it receives an UInt value,
+ this present a problem when Int is 16 bits and
+ the sign bit is not interpreted correctly. This does not
+ shows for 32-bit implementations. This problem manifest itself
+ as a flipping sign on some spectral coefficients (the ones
+ multiplied by 0x8000).
+
+ Description: Typecast b_low and b_high to 32-bits before multiplication, this
+ assures propoer compilation on a 16-bit platform (TI-C55x)
+
+ Description: Modified to speed up decode_huff_cw
+
+ Description: pass codebook index to decode_huff_cw, delete pointer to Huffman
+ structure
+
+ Description: keep memset to quantSpec, remove memset to temp_spec
+
+ Description: Modified per review comments
+
+ Description: Use Binary tree search in decode_huff_cw_binary
+
+ Description: Modified per review comments
+ (1) delete unused codes
+
+ Description: (1) Change the interface to decode huffman codeword.
+ (2) Move the scaling inside the inverse quantization.
+ (3) Change scaling factor accuracy to 10 bits.
+
+ Description:
+ (1) delete unused variable max_fac
+
+ Description: Addresses of huffman tables are now found by means of a
+ switch statement, this solve linking problem when using the
+ /ropi option (Read-only position independent) for some
+ compilers
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pFrameInfo = ptr to structure that holds Information of current Frame,
+ type FrameInfo
+
+ pInputStream = ptr to structure of bitstream, type BITS
+
+ nsect = number of sections in current Frame, at fs = 44.1 kHz,
+ range [0, 49] long block, [0,112] short blocks. type Int
+
+ pSect = ptr to structure that holds section codebook and boundary
+ type SectInfo
+
+ factors[] = array that contains scalefactors for each sfb, type Int16
+
+ coef[] = array that holds inverse quantized coefs, Int32 QFormat.
+
+ quantSpec[] = array that holds quantized spectral coefs, type Int
+
+ tmp_spec[] = temporary buffer to hold the de-interleaved coefs.
+
+ pLongFrameInfo = ptr to structure that holds long frame info
+
+ Local Stores/Buffers/Pointers Needed:
+ exptable = array contains the Q15 format data for 2^0, 2^0.25, 2^0.5,
+ and 2^0.75, type const Int.
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+
+ return 0 if decoding properly.
+
+ Pointers and Buffers Modified:
+
+ pInputStream read codeword index and/or sign bits and/or ESC value
+
+ coef contains the newly inverse quantized 1024 spec coefs,
+ type Int32 Q-format from esc_iquant()
+
+ quantSpec contains decoded quantized 1024 spec coefs, type Int
+
+ tmp_spec contains the de-interleaved version of quantSpec
+
+ qFormat contains Q-Format for each scalefactor band
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function first reads the section info (codebook and boundary), then
+ decode the spectral coefficients if a spectral codebook is used.
+ If necessary, get the sign bits, ESC value or the NEC_pulse data. In case of
+ short window sequences, the decoded data is de-interleaved before
+ multiplied by scalefactors.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function should set the content of the array 'coef' with the inverse
+ quantized and rescaled value of spectral coefficients.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+ (2) ISO/IEC 14496-3: 1999(E)
+ Subpart (4) p56 (spectral_data() parsing and decoding)
+ p26 (Syntax of spectral_data())
+ p74-78 (decoding: unpack_idx, get_sign_bits,
+ getescape, pulse_nc, deinterleave)
+ p72 (inverse quantization: esc_iquant)
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "aac_mem_funcs.h"
+#include "esc_iquant_scaling.h"
+#include "huffman.h"
+#include "unpack_idx.h"
+#include "pulse_nc.h"
+#include "iquant_table.h"
+#include "e_huffmanconst.h"
+
+
+#include "pv_normalize.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define ORDER (3)
+
+/*
+ * Format the table is stored in.
+ */
+#define QTABLE (27)
+
+/*
+ * Number of bits for data in a signed 32 bit integer.
+ */
+#define SIGNED32BITS (31)
+
+/*
+ * Round up value for intermediate values obtained from the table
+ */
+#define ROUND_UP (( ((UInt32) 1) << (QTABLE) )-1)
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const UInt16 exptable[4] =
+{
+ 0, /* (2^0.00)<<15 (Q10), use zero to signal no scaling required! */
+ 19485, /* (2^0.25)<<15 */
+ 23171, /* (2^0.50)<<15 */
+ 27555 /* (2^0.75)<<15 */
+
+};
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int huffspec_fxp(
+ FrameInfo *pFrameInfo,
+ BITS *pInputStream,
+ Int nsect,
+ SectInfo *pSectInfo,
+ Int factors[],
+ Int32 coef[],
+ Int16 quantSpec[],
+ Int16 tmp_spec[],
+ const FrameInfo *pLongFrameInfo,
+ PulseInfo *pPulseInfo,
+ Int qFormat[])
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ const Hcb *pHcb;
+ Int i;
+ Int sfb;
+ Int idx_count;
+ Int sect_cb; /* section codebook */
+ Int dim;
+ Int idx;
+ Int stop_idx; /* index of 1st coef in next sfb */
+ Int sect_start; /* start index of sfb in one section*/
+ Int sect_end; /* index of 1st sfb in next section */
+ Int *pSfbStart;
+ Int *pSfb;
+ Int16 *pQuantSpec; /* probably could be short */
+ Int max = 0;
+ /* rescaling parameters */
+ Int nsfb;
+ Int tot_sfb;
+ Int fac;
+
+ Int32 *pCoef; /* ptr to coef[], inverse quantized coefs */
+ UInt16 scale;
+
+ Int power_scale_div_4;
+ Int sfbWidth;
+
+ void (*pUnpack_idx)(
+ Int16 quant_spec[],
+ Int codeword_indx,
+ const Hcb *pHuffCodebook,
+ BITS *pInputStream,
+ Int *max);
+
+ Int(*pDec_huff_tab)(BITS *) = NULL;
+
+ UInt32 temp;
+ Int binaryDigits, QFormat;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ sect_start = 0;
+ stop_idx = 0;
+
+ /* pSfb: ptr to array that holds stop index of each sfb */
+ pSfbStart = pFrameInfo->frame_sfb_top;
+
+ if (pSfbStart == NULL)
+ {
+ return (-1); /* error condition */
+ }
+
+ pSfb = pSfbStart;
+
+ /* decoding spectral values section by section */
+ for (i = nsect; i > 0; i--)
+ {
+ /* read the codebook and section length */
+ sect_cb = pSectInfo->sect_cb; /* codebook */
+ if ((sect_cb > 15) || (sect_cb < 0))
+ {
+ return (-1); /* error condition */
+ }
+ sect_end = pSectInfo->sect_end; /* # of sfbs */
+
+ if (sect_end < 0)
+ {
+ return (-1); /* error condition */
+ }
+
+ pSectInfo++;
+
+ /* sect_cb sect_cb - 1
+ * ZERO_HCB 1111b
+ * 1 0000b
+ * 2 0001b
+ * 3 0010b
+ * 4 0011b
+ * 5 0100b
+ * 6 0101b
+ * 7 0110b
+ * 8 0111b
+ * 9 1000b
+ * 10 1001b
+ * 11 1010b
+ * 12 1011b
+ * NOISE_HCB 1100b
+ * INTENSITY_HCB2 1101b
+ * INTENSITY_HCB 1110b
+ * if ( ((sect_cb - 1) & 0xC) == 0xC ) is identical to
+ * if !((sect_cb == ZERO_HCB) || (sect_cb == NOISE_HCB) ||
+ * (sec_cb == INTENSITY_HCB) || (sect_cb==INTENSITY_HCB2) )
+ * use this compare scheme to speed up the execution
+ */
+
+ if (((sect_cb - 1) & 0xC) != 0xC)
+ {
+ /* decode spec in one section */
+ if (sect_cb > BY4BOOKS)
+ {
+ dim = DIMENSION_2; /* set codebook dimension */
+ }
+ else
+ {
+ dim = DIMENSION_4;
+ }
+
+ pHcb = &hcbbook_binary[sect_cb];
+
+ if (sect_cb == ESCBOOK)
+ {
+ pUnpack_idx = &unpack_idx_esc;
+ }
+ else if (pHcb->signed_cb == FALSE)
+ {
+ pUnpack_idx = &unpack_idx_sgn;
+ }
+ else
+ {
+ pUnpack_idx = &unpack_idx;
+ }
+
+
+ switch (sect_cb)
+ {
+ case 1:
+ pDec_huff_tab = decode_huff_cw_tab1;
+ break;
+ case 2:
+ pDec_huff_tab = decode_huff_cw_tab2;
+ break;
+ case 3:
+ pDec_huff_tab = decode_huff_cw_tab3;
+ break;
+ case 4:
+ pDec_huff_tab = decode_huff_cw_tab4;
+ break;
+ case 5:
+ pDec_huff_tab = decode_huff_cw_tab5;
+ break;
+ case 6:
+ pDec_huff_tab = decode_huff_cw_tab6;
+ break;
+ case 7:
+ pDec_huff_tab = decode_huff_cw_tab7;
+ break;
+ case 8:
+ pDec_huff_tab = decode_huff_cw_tab8;
+ break;
+ case 9:
+ pDec_huff_tab = decode_huff_cw_tab9;
+ break;
+ case 10:
+ pDec_huff_tab = decode_huff_cw_tab10;
+ break;
+ case 11:
+ pDec_huff_tab = decode_huff_cw_tab11;
+ break;
+ default:
+ return (-1); /* error condition */
+ }
+
+ /* move ptr to first sfb of current section */
+ pQuantSpec = quantSpec + stop_idx;
+
+ /* step through all sfbs in current section */
+ for (sfb = sect_start; sfb < sect_end; sfb++)
+ {
+ idx_count = *pSfb - stop_idx;
+ stop_idx = *pSfb++;
+
+ /* decode all coefs for one sfb */
+ while ((idx_count > 0) && (idx_count < 1024))
+ {
+
+ idx = (*pDec_huff_tab)(pInputStream);
+
+ (*pUnpack_idx)(pQuantSpec,
+ idx,
+ pHcb,
+ pInputStream,
+ &max); /* unpack idx -> coefs */
+
+ pQuantSpec += dim;
+ idx_count -= dim;
+
+ } /* while(idx_count) */
+
+ } /* for (sfb=sect_start) */
+ }
+ else
+ {
+
+ /* current section uses ZERO_HCB, NOISE_HCB, etc */
+
+ /* move sfb pointer to the start sfb of next section */
+ pSfb = pSfbStart + sect_end;
+ /* number of coefs in current section */
+ idx_count = *(pSfb - 1) - stop_idx;
+
+ if ((idx_count > 1024) || (idx_count < 0))
+ {
+ return (-1); /* error condition */
+ }
+
+ /*
+ * This memset is necessary in terms of (1) net savings in total
+ * MIPS and (2) accurate Q-Formats for fft_rx2
+ * In case a scalefactor band uses ZERO_HCB, all coefficients of
+ * that sfb should be zeros. Without this call to memset, the
+ * coefficients for a ZERO_HCB sfb are the "leftovers" of the
+ * previous frame, which may not have all zero values. This leads
+ * to a drastical increase in the cycles consumed by esc_iquant_fxp
+ * and fft_rx2, which is the most "expensive" function of the
+ * library.
+ * This memset also guarantees the Q_Format for sfbs with all zero
+ * coefficients will be set properly.
+ * Profiling data on ARM and TMS320C55x proves that there is a net
+ * gain in total MIPS if a memset is called here.
+ */
+ pv_memset(&quantSpec[stop_idx],
+ 0,
+ idx_count * sizeof(quantSpec[0]));
+
+ /*
+ * This memset is called because pQuantSpec points to tmp_spec
+ * after deinterleaving
+ */
+
+ pv_memset(&tmp_spec[stop_idx],
+ 0,
+ idx_count * sizeof(tmp_spec[0]));
+
+
+ /* stop_idx is the index of the 1st coef of next section */
+ stop_idx = *(pSfb - 1);
+
+ }/* if (sect_cb) */
+
+ sect_start = sect_end;
+
+ } /* for (i=nsect) */
+
+ /* noisless coding reconstruction */
+ if (pFrameInfo->islong != FALSE)
+ {
+ if (pPulseInfo->pulse_data_present == 1)
+ {
+ pulse_nc(quantSpec,
+ pPulseInfo,
+ pLongFrameInfo,
+ &max); /* add pulse data */
+ }
+
+ pQuantSpec = quantSpec;
+
+ }
+ else
+ {
+ deinterleave(quantSpec,
+ tmp_spec,
+ pFrameInfo);
+
+ pQuantSpec = tmp_spec;
+ }
+
+
+ /* inverse quantization, Q_format: Int32 */
+ /* rescaling */
+
+ /* what we can do here is assuming that we already know maxInput for each band, we have to go
+ though each one of them for re-quant and scaling, and pick the right qFormat to apply to
+ all spectral coeffs.*/
+
+ if ((max < 0) || (max > 8192)) /* (8192>>ORDER) == 1024 is the inverseQuantTable size */
+ {
+ return (-1); /* error condition */
+ }
+ else
+ {
+ /* Get (max/SPACING) ^ (1/3), in Q Format */
+ temp = inverseQuantTable[(max >> ORDER) + 1];
+ }
+
+
+ /* Round up before shifting down to Q0 */
+ temp += ROUND_UP;
+
+ /* shift down to Q0 and multiply by 2 (FACTOR) in one step */
+ temp >>= (QTABLE - 1);
+
+ /* Now get max ^ (4/3) in Q0 */
+ temp *= max;
+
+
+ binaryDigits = 31 - pv_normalize(temp);
+
+
+ /* Prevent negative shifts caused by low maximums. */
+ if (binaryDigits < (SIGNED32BITS - QTABLE))
+ {
+ binaryDigits = SIGNED32BITS - QTABLE;
+ }
+
+ QFormat = SIGNED32BITS - binaryDigits;
+
+ /********************/
+ tot_sfb = 0;
+ nsfb = pFrameInfo->sfb_per_win[0];
+ pCoef = coef;
+
+ for (i = pFrameInfo->num_win; i > 0; i--)
+ {
+ stop_idx = 0;
+
+ for (sfb = 0; sfb < nsfb; sfb++)
+ {
+ sfbWidth = pFrameInfo->win_sfb_top[0][sfb] - stop_idx;
+
+ if ((sfbWidth < 0) || (sfbWidth > 1024))
+ {
+ return (-1); /* error condition */
+ }
+
+ stop_idx += sfbWidth;
+
+ fac = factors[tot_sfb] - SF_OFFSET;
+ scale = exptable[fac & 0x3];
+
+ power_scale_div_4 = fac >> 2;
+
+ power_scale_div_4++;
+
+ qFormat[tot_sfb] = QFormat;
+
+ esc_iquant_scaling(pQuantSpec,
+ pCoef,
+ sfbWidth,
+ QFormat,
+ scale,
+ max);
+
+ pQuantSpec += sfbWidth;
+ qFormat[tot_sfb] -= power_scale_div_4;
+ pCoef += sfbWidth;
+
+ tot_sfb++;
+
+ } /* for (sfb) */
+ } /* for (i) */
+
+
+ /*----------------------------------------------------------------------------
+ ; Return status
+ ----------------------------------------------------------------------------*/
+ return SUCCESS;
+
+} /* huffspec_fxp */
diff --git a/media/libstagefright/codecs/aacdec/ibstream.h b/media/libstagefright/codecs/aacdec/ibstream.h
new file mode 100644
index 0000000..8b644dc
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ibstream.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ibstream.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Change names of constants.
+
+ Description: Change the buffer from UInt to UInt32
+
+ Description: Remove declaration of getbits and include header file
+
+ Description: Change input buffer to UChar
+ Add constant
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Contains defines, structures, and function definitions for the
+ input bit stream used in the AAC Decoder.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef IBSTREAM_H
+#define IBSTREAM_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bits.h"
+#include "getbits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+#define INBUF_ARRAY_INDEX_SHIFT (3)
+#define INBUF_BIT_WIDTH (1<<(INBUF_ARRAY_INDEX_SHIFT))
+#define INBUF_BIT_MODULO_MASK ((INBUF_BIT_WIDTH)-1)
+
+#define MAX_GETBITS (25)
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void byte_align(
+ BITS *pInputStream);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* IBSTREAM_H */
+
+
diff --git a/media/libstagefright/codecs/aacdec/idct16.cpp b/media/libstagefright/codecs/aacdec/idct16.cpp
new file mode 100644
index 0000000..324fe9e
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/idct16.cpp
@@ -0,0 +1,204 @@
+/* ------------------------------------------------------------------
+ * 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: idct16.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 x 32-bit integer input length 16
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement inverse discrete cosine transform of lenght 16
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "idct16.h"
+#include "idct8.h"
+
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+#define R_SHIFT 28
+#define Qfmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+#define Qfmt31(x) (Int32)(x*(0x7FFFFFFF) + (x>=0?0.5F:-0.5F))
+
+const Int32 CosTable_8i[8] =
+{
+ Qfmt31(0.50241928618816F), Qfmt31(0.52249861493969F),
+ Qfmt31(0.56694403481636F), Qfmt31(0.64682178335999F),
+ Qfmt(0.78815462345125F), Qfmt(1.06067768599035F),
+ Qfmt(1.72244709823833F), Qfmt(5.10114861868916F)
+};
+
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void idct_16(Int32 vec[], Int32 scratch_mem[]) /* scratch_mem size 8 */
+{
+ Int32 *temp_even = scratch_mem;
+
+ Int32 i;
+ const Int32 *pt_cos = CosTable_8i;
+ Int32 tmp1, tmp2;
+ Int32 *pt_even = temp_even;
+ Int32 *pt_odd = vec;
+ Int32 *pt_vec = vec;
+
+ Int32 tmp3;
+ Int32 *pt_vecN_1;
+
+
+ *(pt_even++) = *(pt_vec++);
+ tmp1 = *(pt_vec++);
+ *(pt_odd++) = tmp1;
+
+ for (i = 2; i != 0; i--)
+ {
+ *(pt_even++) = *(pt_vec++);
+ tmp2 = *(pt_vec++);
+ *(pt_even++) = *(pt_vec++);
+ tmp3 = *(pt_vec++);
+ *(pt_odd++) = tmp2 + tmp1;
+ *(pt_odd++) = tmp3 + tmp2;
+ tmp1 = tmp3;
+ }
+
+ *(pt_even++) = *(pt_vec++);
+ tmp2 = *(pt_vec++);
+ *(pt_even++) = *(pt_vec++);
+ tmp3 = *(pt_vec++);
+ *(pt_odd++) = tmp2 + tmp1;
+ *(pt_odd++) = tmp3 + tmp2;
+
+
+ *(pt_even) = *(pt_vec++);
+ *(pt_odd++) = *(pt_vec) + tmp3;
+
+
+ idct_8(temp_even);
+ idct_8(vec);
+
+
+ pt_cos = &CosTable_8i[7];
+
+ pt_vec = &vec[7];
+
+ pt_even = &temp_even[7];
+ pt_vecN_1 = &vec[8];
+
+ tmp1 = *(pt_even--);
+
+ for (i = 2; i != 0; i--)
+ {
+ tmp3 = fxp_mul32_Q28(*(pt_vec), *(pt_cos--));
+ tmp2 = *(pt_even--);
+ *(pt_vecN_1++) = tmp1 - tmp3;
+ *(pt_vec--) = tmp1 + tmp3;
+ tmp3 = fxp_mul32_Q28(*(pt_vec), *(pt_cos--));
+ tmp1 = *(pt_even--);
+ *(pt_vecN_1++) = tmp2 - tmp3;
+ *(pt_vec--) = tmp2 + tmp3;
+ }
+
+ tmp3 = fxp_mul32_Q31(*(pt_vec), *(pt_cos--)) << 1;
+ tmp2 = *(pt_even--);
+ *(pt_vecN_1++) = tmp1 - tmp3;
+ *(pt_vec--) = tmp1 + tmp3;
+ tmp3 = fxp_mul32_Q31(*(pt_vec), *(pt_cos--)) << 1;
+ tmp1 = *(pt_even--);
+ *(pt_vecN_1++) = tmp2 - tmp3;
+ *(pt_vec--) = tmp2 + tmp3;
+ tmp3 = fxp_mul32_Q31(*(pt_vec), *(pt_cos--)) << 1;
+ tmp2 = *(pt_even--);
+ *(pt_vecN_1++) = tmp1 - tmp3;
+ *(pt_vec--) = tmp1 + tmp3;
+ tmp3 = fxp_mul32_Q31(*(pt_vec), *(pt_cos)) << 1;
+ *(pt_vecN_1) = tmp2 - tmp3;
+ *(pt_vec) = tmp2 + tmp3;
+
+}
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/idct16.h b/media/libstagefright/codecs/aacdec/idct16.h
new file mode 100644
index 0000000..afade07
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/idct16.h
@@ -0,0 +1,69 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: idct16.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef IDCT16_H
+#define IDCT16_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ void idct_16(Int32 vec[], Int32 scratch_mem[]);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDCT16_H */
diff --git a/media/libstagefright/codecs/aacdec/idct32.cpp b/media/libstagefright/codecs/aacdec/idct32.cpp
new file mode 100644
index 0000000..ac9773b
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/idct32.cpp
@@ -0,0 +1,196 @@
+/* ------------------------------------------------------------------
+ * 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: idct32.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 x 32-bit integer input length 32
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement inverse discrete cosine transform of lenght 32
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#include "idct32.h"
+#include "dst32.h"
+#include "idct16.h"
+
+#include "fxp_mul32.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+
+#define R_SHIFT1 29
+#define Qfmt1(x) (Int32)(x*((Int32)1<<R_SHIFT1) + (x>=0?0.5F:-0.5F))
+
+#define Qfmt3(a) (Int32)(a*0x7FFFFFFF + (a>=0?0.5F:-0.5F))
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void idct_32(Int32 vec[], Int32 scratch_mem[]) /* scratch_mem size 32 */
+{
+ Int32 *temp_even = scratch_mem;
+
+ Int32 i;
+ const Int32 *pt_cos = CosTable_16;
+ Int32 tmp1, tmp2;
+ Int32 *pt_even = temp_even;
+ Int32 *pt_odd = vec;
+ Int32 *pt_vec = vec;
+ Int32 *pt_vecN_1;
+ Int32 tmp3;
+
+
+ *(pt_even++) = *(pt_vec++);
+ tmp1 = *(pt_vec++);
+ tmp2 = 0;
+
+ for (i = 7; i != 0; i--)
+ {
+ *(pt_odd++) = tmp2 + tmp1;
+ *(pt_even++) = *(pt_vec++);
+ tmp2 = *(pt_vec++);
+ *(pt_even++) = *(pt_vec++);
+ *(pt_odd++) = tmp2 + tmp1;
+ tmp1 = *(pt_vec++);
+ }
+
+ *(pt_odd++) = tmp2 + tmp1;
+ *(pt_even++) = *(pt_vec++);
+ tmp2 = *(pt_vec++);
+ *(pt_odd++) = tmp2 + tmp1;
+
+
+ idct_16(temp_even, &scratch_mem[16]);
+ idct_16(vec, &scratch_mem[24]);
+
+
+ pt_cos = &CosTable_16[13];
+
+ pt_vec = &vec[15];
+
+ pt_even = &temp_even[15];
+ pt_vecN_1 = &vec[16];
+
+ tmp1 = *(pt_even--);
+
+
+ tmp3 = fxp_mul32_Q31(*(pt_vec) << 3, Qfmt3(0.63687550772175F)) << 2;
+ tmp2 = *(pt_even--);
+ *(pt_vecN_1++) = tmp1 - tmp3;
+ *(pt_vec--) = tmp1 + tmp3;
+ tmp3 = fxp_mul32_Q31(*(pt_vec) << 3, Qfmt3(0.85190210461718F));
+
+ tmp1 = *(pt_even--);
+ *(pt_vecN_1++) = tmp2 - tmp3;
+ *(pt_vec--) = tmp2 + tmp3;
+
+ for (i = 2; i != 0; i--)
+ {
+ tmp3 = fxp_mul32_Q29(*(pt_vec), *(pt_cos--));
+ tmp2 = *(pt_even--);
+ *(pt_vecN_1++) = tmp1 - tmp3;
+ *(pt_vec--) = tmp1 + tmp3;
+ tmp3 = fxp_mul32_Q29(*(pt_vec), *(pt_cos--));
+ tmp1 = *(pt_even--);
+ *(pt_vecN_1++) = tmp2 - tmp3;
+ *(pt_vec--) = tmp2 + tmp3;
+ }
+
+ for (i = 5; i != 0; i--)
+ {
+ tmp3 = fxp_mul32_Q31(*(pt_vec) << 1, *(pt_cos--));
+ tmp2 = *(pt_even--);
+ *(pt_vecN_1++) = tmp1 - tmp3;
+ *(pt_vec--) = tmp1 + tmp3;
+ tmp3 = fxp_mul32_Q31(*(pt_vec) << 1, *(pt_cos--));
+ tmp1 = *(pt_even--);
+ *(pt_vecN_1++) = tmp2 - tmp3;
+ *(pt_vec--) = tmp2 + tmp3;
+ }
+}
+
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/idct32.h b/media/libstagefright/codecs/aacdec/idct32.h
new file mode 100644
index 0000000..12c685a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/idct32.h
@@ -0,0 +1,69 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: idct32.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef IDCT32_H
+#define IDCT32_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ void idct_32(Int32 vec[], Int32 scratch_mem[]);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDCT32_H */
diff --git a/media/libstagefright/codecs/aacdec/idct8.cpp b/media/libstagefright/codecs/aacdec/idct8.cpp
new file mode 100644
index 0000000..8f040ce
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/idct8.cpp
@@ -0,0 +1,168 @@
+/* ------------------------------------------------------------------
+ * 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: idct8.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 x 32-bit integer input length 8
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement inverse discrete cosine transform of lenght 8
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+#ifdef AAC_PLUS
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "idct8.h"
+
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+#define R_SHIFT 29
+#define Qfmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+#define Qfmt15(x) (Int16)(x*((Int32)1<<15) + (x>=0?0.5F:-0.5F))
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void idct_8(Int32 vec[])
+{
+
+ Int32 tmp0;
+ Int32 tmp1;
+ Int32 tmp2;
+ Int32 tmp3;
+ Int32 tmp4;
+ Int32 tmp5;
+ Int32 tmp6;
+ Int32 tmp7;
+ Int32 tmp8;
+
+
+ tmp5 = fxp_mul32_by_16(vec[4] << 1, Qfmt15(0.70710678118655F));
+
+ tmp1 = vec[0] + tmp5;
+ tmp5 = vec[0] - tmp5;
+
+ tmp3 = fxp_mul32_by_16(vec[2] << 1, Qfmt15(0.54119610014620F)); /* (1/(2*cos(2*phi)));*/
+ tmp7 = fxp_mul32_Q29(vec[6], Qfmt(1.30656296487638F)); /* (1/(2*cos(6*phi)));*/
+
+ tmp0 = fxp_mul32_by_16((tmp3 - tmp7) << 1, Qfmt15(0.70710678118655F)); /* (1/(2*cos(2*phi))); */
+ tmp7 = (tmp3 + tmp7) + tmp0;
+
+ vec[0] = tmp1 + tmp7;
+ tmp2 = fxp_mul32_by_16(vec[1] << 1, Qfmt15(0.50979557910416F)); /* (1/(2*cos( phi)));*/
+ vec[1] = tmp5 + tmp0;
+ vec[2] = tmp5 - tmp0;
+ tmp4 = fxp_mul32_by_16(vec[3] << 1, Qfmt15(0.60134488693505F)); /* (1/(2*cos(3*phi)));*/
+ vec[3] = tmp1 - tmp7;
+
+ tmp6 = fxp_mul32_by_16(vec[5] << 1, Qfmt15(0.89997622313642F)); /* (1/(2*cos(5*phi)));*/
+ tmp8 = fxp_mul32_Q29(vec[7], Qfmt(2.56291544774151F)); /* (1/(2*cos(7*phi)));*/
+
+ tmp7 = tmp2 + tmp8;
+ tmp5 = fxp_mul32_by_16((tmp2 - tmp8) << 1, Qfmt15(0.54119610014620F));
+ tmp8 = tmp4 + tmp6;
+ tmp6 = fxp_mul32_Q29((tmp4 - tmp6), Qfmt(1.30656296487638F));
+
+ tmp0 = tmp7 + tmp8;
+ tmp2 = fxp_mul32_by_16((tmp7 - tmp8) << 1, Qfmt15(0.70710678118655F));
+
+ tmp3 = fxp_mul32_by_16((tmp5 - tmp6) << 1, Qfmt15(0.70710678118655F));
+ tmp1 = (tmp5 + tmp6) + tmp3;
+
+ tmp5 = tmp0 + tmp1;
+ tmp6 = tmp1 + tmp2;
+ tmp7 = tmp2 + tmp3;
+
+ vec[7] = vec[0] - tmp5;
+ vec[0] += tmp5;
+ vec[6] = vec[1] - tmp6;
+ vec[1] += tmp6;
+ vec[5] = vec[2] - tmp7;
+ vec[2] += tmp7;
+ vec[4] = vec[3] - tmp3;
+ vec[3] += tmp3;
+
+}
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/idct8.h b/media/libstagefright/codecs/aacdec/idct8.h
new file mode 100644
index 0000000..ad7eaae
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/idct8.h
@@ -0,0 +1,69 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: idct8.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef IDCT8_H
+#define IDCT8_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ void idct_8(Int32 vec[]);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDCT8_H */
diff --git a/media/libstagefright/codecs/aacdec/imdct_fxp.cpp b/media/libstagefright/codecs/aacdec/imdct_fxp.cpp
new file mode 100644
index 0000000..ad67f20
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/imdct_fxp.cpp
@@ -0,0 +1,476 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: imdct_fxp.c
+ Funtions: imdct_fxp
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ data_quant = Input vector, with quantized spectral lines:
+ type Int32
+
+ freq_2_time_buffer = Scratch memory used for in-place FFT calculation,
+ min size required 1024,
+ type Int32
+
+ n = Length of input vector "data_quant". Currently 256 or 2048
+ type const Int
+
+ Q_format = Q_format of the input vector "data_quant"
+ type Int
+
+ max = Maximum value inside input vector "data_quant"
+ type Int32
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ shift = shift factor to reflect scaling introduced by IFFT and imdct_fxp,
+
+ Pointers and Buffers Modified:
+ Results are return in "Data_Int_precision"
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ The IMDCT is a linear orthogonal lapped transform, based on the idea of
+ time domain aliasing cancellation (TDAC).
+ IMDCT is critically sampled, which means that though it is 50% overlapped,
+ a sequence data after IMDCT has the same number of coefficients as samples
+ before the transform (after overlap-and-add). This means, that a single
+ block of IMDCT data does not correspond to the original block on which the
+ IMDCT was performed. When subsequent blocks of inverse transformed data
+ are added (still using 50% overlap), the errors introduced by the
+ transform cancels out.Thanks to the overlapping feature, the IMDCT is very
+ useful for quantization. It effectively removes the otherwise easily
+ detectable blocking artifact between transform blocks.
+
+ N = twice the length of input vector X
+ y = vector of length N, will hold fixed point IDCT
+ p = 0:1:N-1
+
+ 2 N/2-1
+ y(p) = --- SUM X(m)*cos(pi/(2*N)*(2*p+1+N/2)*(2*m+1))
+ N m=0
+
+ The window that completes the TDAC is applied before calling this function.
+ The IMDCT can be calculated using an IFFT, for this, the IMDCT need be
+ rewritten as an odd-time odd-frequency discrete Fourier transform. Thus,
+ the IMDCT can be calculated using only one n/4 point FFT and some pre and
+ post-rotation of the sample points.
+
+
+ where X(k) is the input with N frequency lines
+
+ X(k) ----------------------------
+ |
+ |
+ Pre-rotation by exp(j(2pi/N)(k+1/8))
+ |
+ |
+ N/4- point IFFT
+ |
+ |
+ Post-rotation by exp(j(2pi/N)(n+1/8))
+ |
+ |
+ ------------- x(n) In the time domain
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function should provide a fixed point IMDCT with an average
+ quantization error less than 1 % (variance and mean).
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] Analysis/Synthesis Filter Bank design based on time domain
+ aliasing cancellation
+ Jhon Princen, et. al.
+ IEEE Transactions on ASSP, vol ASSP-34, No. 5 October 1986
+ Pg 1153 - 1161
+
+ [2] Regular FFT-related transform kernels for DCT/DST based
+ polyphase filterbanks
+ Rolf Gluth
+ Proc. ICASSP 1991, pg. 2205 - 2208
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Cx, Cy are complex number
+
+
+ exp = log2(n)-1
+
+ FOR ( k=0; k< n/2; k +=2)
+
+ Cx = - data_quant[k] + j data_quant[n/2-1 - k]
+
+ freq_2_time_buffer = Cx * exp(j(2pi/n)(k+1/8))
+
+ ENDFOR
+
+ CALL IFFT( freq_2_time_buffer, n/4)
+
+ MODIFYING( freq_2_time_buffer )
+
+ RETURNING( shift )
+
+ FOR ( k=0; k< n/4; k +=2)
+
+ Cx = freq_2_time_buffer[ k] + j freq_2_time_buffer[ k+1]
+
+ Cy = Cx * exp(j(2pi/n)(k+1/8))
+
+ data_quant[3n/4-1 - k ] = Real(Cy)
+ data_quant[ n/4-1 - k ] = - Imag(Cy)
+ data_quant[3n/4 + k ] = Real(Cy)
+ data_quant[ n/4 + k ] = Imag(Cy)
+
+ ENDFOR
+
+ FOR ( k=n/4; k< n/2; k +=2)
+
+ Cx = freq_2_time_buffer[ k] + j freq_2_time_buffer[ k+1]
+
+ Cy = Cx * exp(j(2pi/n)(k+1/8))
+
+ data_quant[3n/4-1 - k ] = Real(Cy)
+ data_quant[ n/4 + k ] = - Real(Cy)
+ data_quant[5n/4 - k ] = Imag(Cy)
+ data_quant[ n/4 + k ] = Imag(Cy)
+
+ ENDFOR
+
+ MODIFIED data_quant[]
+
+ RETURN (exp - shift)
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+#include "imdct_fxp.h"
+
+
+#include "mix_radix_fft.h"
+#include "digit_reversal_tables.h"
+#include "fft_rx4.h"
+#include "inv_short_complex_rot.h"
+#include "inv_long_complex_rot.h"
+#include "pv_normalize.h"
+#include "fxp_mul32.h"
+#include "aac_mem_funcs.h"
+
+#include "window_block_fxp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define ERROR_IN_FRAME_SIZE 10
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+Int imdct_fxp(Int32 data_quant[],
+ Int32 freq_2_time_buffer[],
+ const Int n,
+ Int Q_format,
+ Int32 max)
+{
+
+ Int32 exp_jw;
+ Int shift = 0;
+
+ const Int32 *p_rotate;
+ const Int32 *p_rotate_2;
+
+ Int32 *p_data_1;
+ Int32 *p_data_2;
+
+ Int32 temp_re32;
+ Int32 temp_im32;
+
+ Int shift1 = 0;
+ Int32 temp1;
+ Int32 temp2;
+
+ Int k;
+ Int n_2 = n >> 1;
+ Int n_4 = n >> 2;
+
+
+
+ if (max != 0)
+ {
+
+ switch (n)
+ {
+ case SHORT_WINDOW_TYPE:
+ p_rotate = exp_rotation_N_256;
+ shift = 21; /* log2(n)-1 + 14 acomodates 2/N factor */
+ break;
+
+ case LONG_WINDOW_TYPE:
+ p_rotate = exp_rotation_N_2048;
+ shift = 24; /* log2(n)-1 +14 acomodates 2/N factor */
+ break;
+
+ default:
+ /*
+ * There is no defined behavior for a non supported frame
+ * size. By returning a fixed scaling factor, the input will
+ * scaled down and the will be heard as a low level noise
+ */
+ return(ERROR_IN_FRAME_SIZE);
+
+ }
+
+ /*
+ * p_data_1 p_data_2
+ * | |
+ * RIRIRIRIRIRIRIRIRIRIRIRIRIRIRI....RIRIRIRIRIRI
+ * | |
+ *
+ */
+
+ p_data_1 = data_quant; /* uses first half of buffer */
+ p_data_2 = &data_quant[n_2 - 1]; /* uses second half of buffer */
+
+ p_rotate_2 = &p_rotate[n_4-1];
+
+ shift1 = pv_normalize(max) - 1; /* -1 to leave room for addition */
+ Q_format -= (16 - shift1);
+ max = 0;
+
+
+ if (shift1 >= 0)
+ {
+ temp_re32 = *(p_data_1++) << shift1;
+ temp_im32 = *(p_data_2--) << shift1;
+
+ for (k = n_4 >> 1; k != 0; k--)
+ {
+ /*
+ * Real and Imag parts have been swaped to use FFT as IFFT
+ */
+ /*
+ * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
+ */
+ exp_jw = *p_rotate++;
+
+ temp1 = cmplx_mul32_by_16(temp_im32, -temp_re32, exp_jw);
+ temp2 = -cmplx_mul32_by_16(temp_re32, temp_im32, exp_jw);
+
+ temp_im32 = *(p_data_1--) << shift1;
+ temp_re32 = *(p_data_2--) << shift1;
+ *(p_data_1++) = temp1;
+ *(p_data_1++) = temp2;
+ max |= (temp1 >> 31) ^ temp1;
+ max |= (temp2 >> 31) ^ temp2;
+
+
+ /*
+ * Real and Imag parts have been swaped to use FFT as IFFT
+ */
+
+ /*
+ * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
+ */
+
+ exp_jw = *p_rotate_2--;
+
+ temp1 = cmplx_mul32_by_16(temp_im32, -temp_re32, exp_jw);
+ temp2 = -cmplx_mul32_by_16(temp_re32, temp_im32, exp_jw);
+
+
+ temp_re32 = *(p_data_1++) << shift1;
+ temp_im32 = *(p_data_2--) << shift1;
+
+ *(p_data_2 + 2) = temp1;
+ *(p_data_2 + 3) = temp2;
+ max |= (temp1 >> 31) ^ temp1;
+ max |= (temp2 >> 31) ^ temp2;
+
+ }
+ }
+ else
+ {
+ temp_re32 = *(p_data_1++) >> 1;
+ temp_im32 = *(p_data_2--) >> 1;
+
+ for (k = n_4 >> 1; k != 0; k--)
+ {
+ /*
+ * Real and Imag parts have been swaped to use FFT as IFFT
+ */
+ /*
+ * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
+ */
+ exp_jw = *p_rotate++;
+
+ temp1 = cmplx_mul32_by_16(temp_im32, -temp_re32, exp_jw);
+ temp2 = -cmplx_mul32_by_16(temp_re32, temp_im32, exp_jw);
+
+ temp_im32 = *(p_data_1--) >> 1;
+ temp_re32 = *(p_data_2--) >> 1;
+ *(p_data_1++) = temp1;
+ *(p_data_1++) = temp2;
+
+ max |= (temp1 >> 31) ^ temp1;
+ max |= (temp2 >> 31) ^ temp2;
+
+
+ /*
+ * Real and Imag parts have been swaped to use FFT as IFFT
+ */
+
+ /*
+ * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
+ */
+ exp_jw = *p_rotate_2--;
+
+ temp1 = cmplx_mul32_by_16(temp_im32, -temp_re32, exp_jw);
+ temp2 = -cmplx_mul32_by_16(temp_re32, temp_im32, exp_jw);
+
+ temp_re32 = *(p_data_1++) >> 1;
+ temp_im32 = *(p_data_2--) >> 1;
+
+ *(p_data_2 + 3) = temp2;
+ *(p_data_2 + 2) = temp1;
+
+ max |= (temp1 >> 31) ^ temp1;
+ max |= (temp2 >> 31) ^ temp2;
+
+ }
+ }
+
+
+ if (n != SHORT_WINDOW_TYPE)
+ {
+
+ shift -= mix_radix_fft(data_quant,
+ &max);
+
+ shift -= inv_long_complex_rot(data_quant,
+ max);
+
+ }
+ else /* n_4 is 64 */
+ {
+
+ shift -= fft_rx4_short(data_quant, &max);
+
+
+ shift -= inv_short_complex_rot(data_quant,
+ freq_2_time_buffer,
+ max);
+
+ pv_memcpy(data_quant,
+ freq_2_time_buffer,
+ SHORT_WINDOW*sizeof(*data_quant));
+ }
+
+ }
+ else
+ {
+ Q_format = ALL_ZEROS_BUFFER;
+ }
+
+ return(shift + Q_format);
+
+} /* imdct_fxp */
diff --git a/media/libstagefright/codecs/aacdec/imdct_fxp.h b/media/libstagefright/codecs/aacdec/imdct_fxp.h
new file mode 100644
index 0000000..5837750
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/imdct_fxp.h
@@ -0,0 +1,122 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: imdct_fxp.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: This extern had the incorrect length of the arrays. The true
+ lengths are 128 and 1024, not 64 and 512.
+
+ Description: Modified interface so a vector with extended precision is
+ returned, this is a 32 bit vector whose MSB 16 bits will be
+ extracted later. Added copyright notice.
+
+ Description: Modified function interface to accomodate the normalization
+ that now is done in this function.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for function imdct_fxp()
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef IMDCT_FXP_H
+#define IMDCT_FXP_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+#define LONG_WINDOW_TYPE 2048
+#define SHORT_WINDOW_TYPE 256
+
+#define ALL_ZEROS_BUFFER 31
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ extern const Int32 exp_rotation_N_256[64];
+ extern const Int32 exp_rotation_N_2048[512];
+ /*
+ extern const Int exp_rotation_N_256[128];
+ extern const Int exp_rotation_N_2048[1024];
+ */
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Int imdct_fxp(
+ Int32 data_quant[],
+ Int32 freq_2_time_buffer[],
+ const Int n,
+ Int Q_format,
+ Int32 max
+ );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* IMDCT_FXP_H */
diff --git a/media/libstagefright/codecs/aacdec/infoinit.cpp b/media/libstagefright/codecs/aacdec/infoinit.cpp
new file mode 100644
index 0000000..7bdcdcd
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/infoinit.cpp
@@ -0,0 +1,355 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: infoinit.c
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: Pass eight_short_info and the array 'sfbwidth128'.
+ Change function arguments' names for clarity
+
+ Description: move sfb definitions to "sfb.h", and "sfb.c", eliminated
+ the function "huffbookinit.c"
+
+ Description: Remove initialization of the never used array,
+ pFrameInfo->group_offs
+
+ Description:
+ (1) Changed "stdinc.h" to <stdlib.h> - this avoids linking in the math
+ library and stdio.h. (All for just defining the NULL pointer macro)
+
+ (2) Updated copyright header.
+
+ Description: Updated the SW template to include the full pathname to the
+ source file and a slightly modified copyright header.
+
+ Description: Addresses of constant vectors are now found by means of a
+ switch statement, this solve linking problem when using the
+ /ropi option (Read-only position independent) for some
+ compilers
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pSi = pointer to sampling rate info
+ ppWin_seq_info = pointer array to window sequence Info struct
+ pSfbwidth128 = pointer to sfb bandwidth array of short window
+
+ Local Stores/Buffers/Pointers Needed:
+
+ Global Stores/Buffers/Pointers Needed:
+
+ Outputs:
+
+ Pointers and Buffers Modified:
+
+ ppWin_seq_info[ONLY_LONG_WINDOW]{all structure members} = setup values
+ ppWin_seq_info[EIGHT_SHORT_WINDOW]{all structure members} = setup values
+
+ Local Stores Modified:
+
+ Global Stores Modified:
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function sets the values of 'Info' structure for blocks containing long
+ and short window sequences, the following structures are being set:
+
+ win_seq_info[ONLY_LONG_WINDOW], win_seq_info[EIGHT_SHORT_WINDOW],
+ only_long_info and eight_short_info
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+ (2) ISO/IEC 14496-3: 1999(E)
+ Subpart 4 p66 (sfb tables)
+ p111 (4.6.10)
+ p200 (Annex 4.B.5)
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ pFrameInfo = pointer to only_long_info;
+ win_seq_info[ONLY_LONG_WINDOW] = pFrameInfo;
+ pFrameInfo{all structure members} = setup values;
+
+
+ pFrameInfo = pointer to eight_short_info;
+ win_seq_info[EIGHT_SHORT_WINDOW] = pFrameInfo;
+ pFrameInfo{all structure.members} = setup values;
+
+
+ FOR (window_seq = 0; window_seq < NUM_WIN_SEQ; win_seq++)
+
+ win_seq_info[window_seq].members = setup values;
+
+ ENDFOR
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE:
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES:
+
+------------------------------------------------------------------------------
+*/
+
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_sr_info.h"
+#include "s_frameinfo.h"
+#include "e_blockswitching.h"
+#include "e_huffmanconst.h"
+#include "sfb.h"
+#include "huffman.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int infoinit(
+ const Int samp_rate_idx,
+ FrameInfo **ppWin_seq_info,
+ Int *pSfbwidth128)
+
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+
+ Int i;
+ Int sfb_idx, sfb_sbk;
+ Int bins_sbk;
+ Int win_seq;
+ Int start_idx, end_idx;
+ Int nsfb_short;
+ Int16 *sfbands;
+ FrameInfo *pFrameInfo;
+
+ const SR_Info *pSi = &(samp_rate_info[samp_rate_idx]);
+
+ const Int16 * pt_SFbands1024 = NULL;
+ const Int16 * pt_SFbands128 = NULL;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ switch (pSi->samp_rate)
+ {
+ case 96000:
+ case 88200:
+ pt_SFbands1024 = sfb_96_1024;
+ pt_SFbands128 = sfb_64_128; /* equal to table sfb_96_128, (eliminated) */
+ break;
+ case 64000:
+ pt_SFbands1024 = sfb_64_1024;
+ pt_SFbands128 = sfb_64_128;
+ break;
+ case 48000:
+ case 44100:
+ pt_SFbands1024 = sfb_48_1024;
+ pt_SFbands128 = sfb_48_128;
+ break;
+ case 32000:
+ pt_SFbands1024 = sfb_32_1024;
+ pt_SFbands128 = sfb_48_128;
+ break;
+ case 24000:
+ case 22050:
+ pt_SFbands1024 = sfb_24_1024;
+ pt_SFbands128 = sfb_24_128;
+ break;
+ case 16000:
+ case 12000:
+ case 11025:
+ pt_SFbands1024 = sfb_16_1024;
+ pt_SFbands128 = sfb_16_128;
+ break;
+ case 8000:
+ pt_SFbands1024 = sfb_8_1024;
+ pt_SFbands128 = sfb_8_128;
+ break;
+ default:
+ // sampling rate not supported
+ return -1;
+ }
+
+ /* long block info */
+
+ pFrameInfo = ppWin_seq_info[ONLY_LONG_WINDOW];
+ pFrameInfo->islong = 1;
+ pFrameInfo->num_win = 1;
+ pFrameInfo->coef_per_frame = LN2; /* = 1024 */
+
+ pFrameInfo->sfb_per_win[0] = pSi->nsfb1024;
+ pFrameInfo->sectbits[0] = LONG_SECT_BITS;
+ pFrameInfo->win_sfb_top[0] = (Int16 *)pt_SFbands1024;
+
+ pFrameInfo->sfb_width_128 = NULL; /* no short block sfb */
+ pFrameInfo->num_groups = 1; /* long block, one group */
+ pFrameInfo->group_len[0] = 1; /* only one window */
+
+ /* short block info */
+ pFrameInfo = ppWin_seq_info[EIGHT_SHORT_WINDOW];
+ pFrameInfo->islong = 0;
+ pFrameInfo->num_win = NSHORT;
+ pFrameInfo->coef_per_frame = LN2;
+
+ for (i = 0; i < pFrameInfo->num_win; i++)
+ {
+ pFrameInfo->sfb_per_win[i] = pSi->nsfb128;
+ pFrameInfo->sectbits[i] = SHORT_SECT_BITS;
+ pFrameInfo->win_sfb_top[i] = (Int16 *)pt_SFbands128;
+ }
+
+ /* construct sfb width table */
+ pFrameInfo->sfb_width_128 = pSfbwidth128;
+ for (i = 0, start_idx = 0, nsfb_short = pSi->nsfb128; i < nsfb_short; i++)
+ {
+ end_idx = pt_SFbands128[i];
+ pSfbwidth128[i] = end_idx - start_idx;
+ start_idx = end_idx;
+ }
+
+
+ /* common to long and short */
+ for (win_seq = 0; win_seq < NUM_WIN_SEQ; win_seq++)
+ {
+
+ if (ppWin_seq_info[win_seq] != NULL)
+ {
+ pFrameInfo = ppWin_seq_info[win_seq];
+ pFrameInfo->sfb_per_frame = 0;
+ sfb_sbk = 0;
+ bins_sbk = 0;
+
+ for (i = 0; i < pFrameInfo->num_win; i++)
+ {
+
+ /* compute coef_per_win */
+ pFrameInfo->coef_per_win[i] =
+ pFrameInfo->coef_per_frame / pFrameInfo->num_win;
+
+ /* compute sfb_per_frame */
+ pFrameInfo->sfb_per_frame += pFrameInfo->sfb_per_win[i];
+
+ /* construct default (non-interleaved) bk_sfb_top[] */
+ sfbands = pFrameInfo->win_sfb_top[i];
+ for (sfb_idx = 0; sfb_idx < pFrameInfo->sfb_per_win[i];
+ sfb_idx++)
+ {
+ pFrameInfo->frame_sfb_top[sfb_idx+sfb_sbk] =
+ sfbands[sfb_idx] + bins_sbk;
+ }
+
+ bins_sbk += pFrameInfo->coef_per_win[i];
+ sfb_sbk += pFrameInfo->sfb_per_win[i];
+ } /* for i = sbk ends */
+ }
+
+ } /* for win_seq ends */
+
+ return SUCCESS;
+
+} /* infoinit */
diff --git a/media/libstagefright/codecs/aacdec/init_sbr_dec.cpp b/media/libstagefright/codecs/aacdec/init_sbr_dec.cpp
new file mode 100644
index 0000000..fc47dd3
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/init_sbr_dec.cpp
@@ -0,0 +1,192 @@
+/* ------------------------------------------------------------------
+ * 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: init_sbr_dec.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ initializes sbr decoder structure
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "init_sbr_dec.h"
+#include "aac_mem_funcs.h"
+#include "extractframeinfo.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int32 init_sbr_dec(Int32 codecSampleRate,
+ Int upsampleFac,
+ SBR_DEC *sbrDec,
+ SBR_FRAME_DATA *hFrameData)
+{
+ Int32 outFrameSize;
+ Int32 coreCodecFrameSize = 1024;
+#ifdef HQ_SBR
+ Int32 i;
+#endif
+
+
+ sbrDec->sbStopCodec = upsampleFac << 5;
+ sbrDec->prevLowSubband = upsampleFac << 5;
+
+
+ /* set sbr sampling frequency */
+ sbrDec->outSampleRate = 2 * codecSampleRate;
+ outFrameSize = upsampleFac * coreCodecFrameSize;
+
+ hFrameData->nSfb[LO] = 0; /* number of scale factor bands for high resp.low frequency resolution */
+ hFrameData->nSfb[HI] = 0;
+ hFrameData->offset = 0;
+
+ hFrameData->nNfb = hFrameData->sbr_header.noNoiseBands;
+ hFrameData->prevEnvIsShort = -1;
+
+ /* Initializes pointers */
+#ifdef HQ_SBR
+ for (i = 0; i < 5; i++)
+ {
+ hFrameData->fBuf_man[i] = hFrameData->fBuffer_man[i];
+ hFrameData->fBufN_man[i] = hFrameData->fBufferN_man[i];
+ hFrameData->fBuf_exp[i] = hFrameData->fBuffer_exp[i];
+ hFrameData->fBufN_exp[i] = hFrameData->fBufferN_exp[i];
+ }
+#endif
+
+
+ pv_memset((void *)hFrameData->sbr_invf_mode_prev,
+ 0,
+ MAX_NUM_NOISE_VALUES*sizeof(INVF_MODE));
+
+ /* Direct assignments */
+
+ sbrDec->noCols = 32;
+
+ sbrDec->bufWriteOffs = 6 + 2;
+ sbrDec->bufReadOffs = 2;
+ sbrDec->qmfBufLen = sbrDec->noCols + sbrDec->bufWriteOffs;
+
+ sbrDec->lowBandAddSamples = 288;
+
+ sbrDec->startIndexCodecQmf = 0;
+
+ sbrDec->lowSubband = 32;
+
+
+ return outFrameSize;
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/init_sbr_dec.h b/media/libstagefright/codecs/aacdec/init_sbr_dec.h
new file mode 100644
index 0000000..844fa0e
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/init_sbr_dec.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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: init_sbr_dec.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+ $Id: ct_envcalc.h,v 1.3 2002/11/29 16:11:49 kaehleof Exp $
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef INIT_SBR_DEC_H
+#define INIT_SBR_DEC_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "sbr_dec.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+Int32 init_sbr_dec(Int32 codecSampleRate,
+ Int upsampleFac,
+ SBR_DEC *sbrDec,
+ SBR_FRAME_DATA *hFrameData);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/intensity_right.cpp b/media/libstagefright/codecs/aacdec/intensity_right.cpp
new file mode 100644
index 0000000..106298a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/intensity_right.cpp
@@ -0,0 +1,457 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: intensity_right.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified per review comments.
+
+ Description: Noticed that the code could be more efficient by
+ using some other method for storing the sign. The code was changed to
+ use a signed Int to store the table, and an adjustment of the q-format to
+ reflect the difference between the data being shifted by 16 and the table
+ being stored in q-15 format.
+
+ Description: Updated pseudocode
+
+ Description: When the multiplication of two 16-bits variables is stored in
+ an 32-bits variable, the result should be typecasted explicitly
+ to Int32 before it is stored.
+ *(pCoefRight++) = (Int32) tempInt2 * multiplier;
+
+ Description:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ scalefactor = Multiplier used to scale the data extracted from the left
+ channel for use on the right.
+ [const Int]
+
+ coef_per_win = Number of coefficients per window.
+ (128 for short, 1024 for long)
+ [const Int]
+
+ sfb_per_win = Number of scalefactor bands per window. This should be
+ a number divisible by four.
+ [const Int]
+
+ wins_in_group = The number of windows in the group being decoded.
+ This number falls within the range 1-8.
+ [const Int]
+
+ band_length = The length of the scalefactor band being decoded.
+ This value is divisible by 4.
+ [const Int]
+
+ codebook = Value that denotes which Huffman codebook was used for
+ the encoding of this grouped scalefactor band.
+ [const Int]
+
+ ms_used = Flag that denotes whether M/S is active for this band.
+ [const Bool]
+
+ q_formatLeft = The Q-format for the left channel's fixed-point spectral
+ coefficients, on a per-scalefactor band, non-grouped basis.
+ [const Int *, length MAXBANDS]
+
+ q_formatRight = The Q-format for the right channel's fixed-point spectral
+ coefficients, on a per-scalefactor band, non-grouped basis.
+ [Int *, length MAXBANDS]
+
+ coefLeft = Array containing the fixed-point spectral coefficients
+ for the left channel.
+ [const Int32 *, length 1024]
+
+ coefRight = Array containing the fixed-point spectral coefficients
+ for the right channel.
+ [Int32 *, length 1024]
+
+ Local Stores/Buffers/Pointers Needed:
+ intensity_factor = Table which stores the values of
+ 0.5^(0), 0.5^(1/4), 0.5^(2/4) and 0.5^(3/4)
+ [UInt, length 4]
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ coefRight[] Contains the new spectral information
+
+ q_formatRight[] Q-format may be updated with changed fixed-point
+ data in coefRight.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function applies Intensity Stereo, generating data on the right channel
+ that is derived from data on the Left. A scalefactor is applied using the
+ following formula...
+
+ RightCh = LeftCh*0.5^(scalefactor/4)
+
+ This function works for one scalefactor band, which may belong to a group.
+ (i.e. the same scalefactor band repeated across multiple windows belonging
+ to one group.)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ codebook must be either INTENSITY_HCB or INTENSITY_HCB2 when this function
+ is called.
+
+ ms_used must be 1 when TRUE, 0 when FALSE.
+
+ wins_in_group falls within the range [1-8]
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.6.7.2.3 Decoding Process (Intensity Stereo)
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+ multiplier = codebook AND 0x1;
+
+ multiplier = multiplier XOR ms_used;
+
+ multiplier = multiplier << 1;
+
+ multiplier = multiplier - 1;
+
+ multiplier = multiplier * intensity_factor[scalefactor & 0x3];
+
+ scf_div_4 = (scalefactor >> 2);
+
+ nextWinPtrUpdate = (coef_per_win - band_length);
+
+ FOR (win_indx = wins_in_group; win_indx > 0; win_indx--)
+
+ *(pQformatRight) = scf_div_4 + *(pQformatLeft) - 1;
+
+ FOR (tempInt = band_length; tempInt > 0; tempInt--)
+ tempInt2 = (Int)(*(pCoefLeft) >> 16);
+
+ *(pCoefRight) = tempInt2 * multiplier;
+
+ pCoefRight = pCoefRight + 1;
+ pCoefLeft = pCoefLeft + 1;
+
+ ENDFOR
+
+ pCoefRight = pCoefRight + nextWinPtrUpdate;
+ pCoefLeft = pCoefLeft + nextWinPtrUpdate;
+
+ pQformatRight = pQformatRight + sfb_per_win;
+ pQformatLeft = pQformatLeft + sfb_per_win;
+ ENDFOR
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "intensity_right.h"
+#include "e_huffmanconst.h"
+
+#include "fxp_mul32.h"
+#include "aac_mem_funcs.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const Int16 intensity_factor[4] =
+{
+ 32767, /* (0.5^0.00)*2^15 - 1 (minus 1 for storage as type Int) */
+ 27554, /* (0.5^0.25)*2^15 */
+ 23170, /* (0.5^0.50)*2^15 */
+ 19484
+}; /* (0.5^0.75)*2^15 */
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void intensity_right(
+ const Int scalefactor,
+ const Int coef_per_win,
+ const Int sfb_per_win,
+ const Int wins_in_group,
+ const Int band_length,
+ const Int codebook,
+ const Bool ms_used,
+ const Int q_formatLeft[],
+ Int q_formatRight[],
+ const Int32 coefLeft[],
+ Int32 coefRight[])
+
+{
+ const Int32 *pCoefLeft = coefLeft;
+ Int32 *pCoefRight = coefRight;
+
+ const Int *pQformatLeft = q_formatLeft;
+ Int *pQformatRight = q_formatRight;
+
+ Int multiplier;
+ Int scf_div_4;
+ Int nextWinPtrUpdate;
+
+ /*
+ * The sign of the intensity multiplier obeys the following table...
+ *
+ * codebook | ms_used | multiplier
+ * --------------------------------------
+ * INTENSITY_HCB | TRUE | -1
+ * INTENSITY_HCB | FALSE | +1
+ * INTENSITY_HCB2 | TRUE | +1
+ * INTENSITY_HCB2 | FALSE | -1
+ *
+ * In binary, the above table is represented as...
+ *
+ * codebook | ms_used | multiplier
+ * --------------------------------------
+ * 1111b | 1 | -1
+ * 1111b | 0 | +1
+ * 1110b | 1 | +1
+ * 1110b | 0 | -1
+ *
+ */
+
+ /*
+ * Deriving the correct value for "multiplier" is illustrated
+ * below for all 4 possible combinations of codebook and ms_used
+ */
+
+ /*
+ * 1111b AND 0x1 = 1b
+ * 1111b AND 0x1 = 1b
+ * 1110b AND 0x1 = 0b
+ * 1110b AND 0x1 = 0b
+ */
+ multiplier = (codebook & 0x1);
+
+ /*
+ * 1b XOR 1 = 0b
+ * 1b XOR 0 = 1b
+ * 0b XOR 1 = 1b
+ * 0b XOR 0 = 0b
+ */
+ multiplier ^= ms_used;
+
+ /*
+ * 0b << 1 = 0
+ * 1b << 1 = 2
+ * 1b << 1 = 2
+ * 0b << 1 = 0
+ */
+ multiplier <<= 1;
+
+ /*
+ * 0 - 1 = -1
+ * 2 - 1 = +1
+ * 2 - 1 = +1
+ * 0 - 1 = -1
+ */
+ multiplier--;
+
+ multiplier *= intensity_factor[scalefactor & 0x3];
+
+ scf_div_4 = (scalefactor >> 2);
+
+ /*
+ * Step through all the windows in this group, replacing this
+ * band in each window's spectrum with
+ * left-channel correlated data
+ */
+
+ nextWinPtrUpdate = (coef_per_win - band_length);
+
+ for (Int win_indx = wins_in_group; win_indx > 0; win_indx--)
+ {
+
+ /*
+ * Calculate q_formatRight
+ *
+ * q_formatLeft must be included, since the values
+ * on the right-channel are derived from the values
+ * on the left-channel.
+ *
+ * scalefactor/4 is included, since the intensity
+ * formula is RightCh = LeftCh*0.5^(scalefactor/4)
+ *
+ * powers of 0.5 increase the q_format by 1.
+ * (Another way to multiply something by 0.5^(x)
+ * is to increase its q-format by x.)
+ *
+ * Finally the q-format must be decreased by 1.
+ * The reason for this is because the table is stored
+ * in q-15 format, but we are shifting by 16 to do
+ * a 16 x 16 multiply.
+ */
+
+ *(pQformatRight) = scf_div_4 + *(pQformatLeft);
+
+ /*
+ * reconstruct right intensity values
+ *
+ * to make things faster, this for loop
+ * can be partially unrolled, since band_length is a multiple
+ * of four.
+ */
+
+
+ if (multiplier == 32767)
+ {
+ Int32 tempInt2 = *(pCoefLeft++);
+ Int32 tempInt22 = *(pCoefLeft++);
+
+ for (Int tempInt = band_length >> 1; tempInt > 0; tempInt--)
+ {
+ *(pCoefRight++) = tempInt2;
+ *(pCoefRight++) = tempInt22;
+ tempInt2 = *(pCoefLeft++);
+ tempInt22 = *(pCoefLeft++);
+ }
+
+ }
+ else
+ {
+
+ Int32 tempInt2 = *(pCoefLeft++);
+ Int32 tempInt22 = *(pCoefLeft++);
+ for (Int tempInt = band_length >> 1; tempInt > 0; tempInt--)
+ {
+ *(pCoefRight++) = fxp_mul32_by_16(tempInt2, multiplier) << 1;
+ *(pCoefRight++) = fxp_mul32_by_16(tempInt22, multiplier) << 1;
+ tempInt2 = *(pCoefLeft++);
+ tempInt22 = *(pCoefLeft++);
+ }
+ }
+
+ /*
+ * Set pCoefRight and pCoefLeft to the beginning of
+ * this sfb in the next window in the group.
+ */
+
+ pCoefRight += nextWinPtrUpdate;
+ pCoefLeft += (nextWinPtrUpdate - 2);
+
+ /*
+ * Update pQformatRight and pQformatLeft to this sfb in
+ * in the next window in the group.
+ */
+
+ pQformatRight += sfb_per_win;
+ pQformatLeft += sfb_per_win;
+
+ } /* for (win_indx) */
+
+
+} /* void intensity_right */
diff --git a/media/libstagefright/codecs/aacdec/intensity_right.h b/media/libstagefright/codecs/aacdec/intensity_right.h
new file mode 100644
index 0000000..823da07
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/intensity_right.h
@@ -0,0 +1,97 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: intensity_right.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Change ms_used from Int to Bool
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Contains the function definitions for intensity_right
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef INTENSITY_RIGHT_H
+#define INTENSITY_RIGHT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void intensity_right(
+ const Int scalefactor,
+ const Int coef_per_win,
+ const Int sfb_per_win,
+ const Int wins_in_group,
+ const Int band_length,
+ const Int codebook,
+ const Bool ms_used,
+ const Int q_formatLeft[],
+ Int q_formatRight[],
+ const Int32 coefLeft[],
+ Int32 coefRight[]);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/inv_long_complex_rot.cpp b/media/libstagefright/codecs/aacdec/inv_long_complex_rot.cpp
new file mode 100644
index 0000000..84a7ec8
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/inv_long_complex_rot.cpp
@@ -0,0 +1,408 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: .inv_long_complex_rot.c
+ Funtions: inv_long_complex_rot
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Change the input argument, no shifts information from long fft_rx4
+ , do not have to check for shifts.
+
+ Date: 10/18/2002
+ Description:
+ (1) Change the input argument, only a single max is passed.
+ (2) Eliminate search for max, a fixed shift has replaced the
+ search for max with minimal loss of precision.
+ (3) Eliminated unused variables
+
+ Date: 10/28/2002
+ Description:
+ (1) Added comments per code review
+
+ Description:
+
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ Data_in = Input vector (sized for long windows
+ TWICE_INV_LONG_CX_ROT_LENGTH), with time domain samples
+ type Int32 *
+
+ Data_out = Output vector with a post-rotation by exp(j(2pi/N)(k+1/8)),
+ (sized for long windows TWICE_INV_LONG_CX_ROT_LENGTH)
+ type Int32 *
+
+ max = Input, carries the maximum value of the input vector
+ "Data_in"
+ type Int32
+
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ exp = shift factor to reflect signal scaling
+
+ Pointers and Buffers Modified:
+ Results are return in "Data_out"
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ inv_long_complex_rot() performs the complex rotation for the inverse MDCT
+ for the case of long windows. It also performs digit reverse ordering of
+ the first and second halves of the input vector "Data_in", as well as
+ reordering of the two half vectors (following radix-2 decomposition)
+ Word normalization is also done to ensure 16 by 16 bit multiplications.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ inv_long_complex_rot() should execute a post-rotation by
+ exp(-j(2pi/N)(k+1/8)), digit reverse ordering and word normalization
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "digit_reversal_tables.h"
+#include "inv_long_complex_rot.h"
+#include "imdct_fxp.h"
+#include "inv_long_complex_rot.h"
+#include "pv_normalize.h"
+
+#include "fxp_mul32.h"
+#include "aac_mem_funcs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+
+Int inv_long_complex_rot(
+ Int32 *Data,
+ Int32 max)
+{
+ Int i;
+ Int16 I;
+ const Int32 *p_rotate;
+ Int32 temp_re;
+ Int32 temp_im;
+
+ Int32 exp_jw;
+ Int32 *pData_in_1;
+ Int32 *pData_in_2;
+ Int exp;
+ Int32 *pData_in_ref1;
+ Int32 *pData_in_ref2;
+
+
+ Int16 temp_re_0;
+ Int16 temp_im_0;
+ Int16 temp_re_1;
+ Int16 temp_im_1;
+ Int16 *p_Data_Int_precision;
+ Int n = 2048;
+ Int n_2 = n >> 1;
+ Int n_4 = n >> 2;
+ Int n_3_4 = n_2 + n_4;
+
+ Int16 *px_1;
+ Int16 *px_2;
+ Int16 *px_3;
+ Int16 *px_4;
+
+ Int16 J;
+ const Int32 *p_rotate2;
+
+
+
+
+ p_rotate = &exp_rotation_N_2048[255];
+ p_rotate2 = &exp_rotation_N_2048[256];
+
+ pData_in_ref1 = Data;
+ pData_in_ref2 = &Data[TWICE_INV_LONG_CX_ROT_LENGTH];
+
+
+ /*
+ * Apply A/2^(diff) + B
+ */
+
+ p_Data_Int_precision = (Int16 *)Data;
+
+ exp = 16 - pv_normalize(max);
+
+
+ /*
+ * px2--> <--px1 px4--> <--px3
+ *
+ * | | |
+ * |+++++++++++++|+++++++++++++|+++++++++++++|+++++++++++++|
+ * | | | |
+ * n/4 n/2 3n/4
+ */
+
+ I = 255;
+ J = 256;
+
+ pData_in_1 = pData_in_ref2 + I;
+
+ px_1 = (Int16 *)pData_in_1;
+ px_1++;
+
+ pData_in_2 = pData_in_ref2 + J;
+
+ px_4 = (Int16 *)pData_in_2;
+
+
+
+ exp -= 1;
+
+
+ for (i = INV_LONG_CX_ROT_LENGTH >> 1; i != 0; i--)
+ {
+
+ pData_in_2 = pData_in_ref1 + J;
+
+ temp_im = *(pData_in_2++);
+ temp_re = *(pData_in_2);
+
+
+ /*
+ * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
+ */
+ exp_jw = *p_rotate2++;
+
+ /*
+ * Post-rotation
+ */
+
+
+
+ temp_re_0 = (Int16)(cmplx_mul32_by_16(temp_re, -temp_im, exp_jw) >> exp);
+ temp_im_0 = (Int16)(cmplx_mul32_by_16(temp_im, temp_re, exp_jw) >> exp);
+
+
+ pData_in_1 = pData_in_ref2 + I;
+
+ /*
+ * Use auxiliary variables to avoid double accesses to memory.
+ * Data in is scaled to use only lower 16 bits.
+ */
+
+ temp_re = *(pData_in_1--);
+ temp_im = *(pData_in_1);
+
+ /*
+ * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
+ */
+ exp_jw = *p_rotate--;
+
+
+ /*
+ * Post-rotation
+ */
+
+ temp_re_1 = (Int16)(cmplx_mul32_by_16(temp_re, -temp_im, exp_jw) >> exp);
+ temp_im_1 = (Int16)(cmplx_mul32_by_16(temp_im, temp_re, exp_jw) >> exp);
+
+
+ /*
+ * Repeat procedure for odd index at the output
+ */
+
+ pData_in_2 = pData_in_ref2 + J;
+ J += 2;
+
+ temp_im = *(pData_in_2++);
+ temp_re = *(pData_in_2);
+
+
+ *(px_1--) = temp_re_0;
+ *(px_1--) = temp_im_1;
+ *(px_4++) = temp_im_0;
+ *(px_4++) = temp_re_1;
+
+
+ exp_jw = *p_rotate2++;
+
+
+ *(px_1--) = (Int16)(cmplx_mul32_by_16(temp_re, -temp_im, exp_jw) >> exp);
+ *(px_4++) = (Int16)(cmplx_mul32_by_16(temp_im, temp_re, exp_jw) >> exp);
+
+
+
+ /*
+ * Repeat procedure for odd index at the output
+ */
+
+ pData_in_1 = pData_in_ref1 + I;
+ I -= 2;
+
+ temp_re = *(pData_in_1--);
+ temp_im = *(pData_in_1);
+
+
+ exp_jw = *p_rotate--;
+
+
+ *(px_4++) = (Int16)(cmplx_mul32_by_16(temp_re, -temp_im, exp_jw) >> exp);
+ *(px_1--) = (Int16)(cmplx_mul32_by_16(temp_im, temp_re, exp_jw) >> exp);
+
+ }
+
+ /*
+ * <--px1 px4-->
+ *
+ * | | |
+ * |-------------|-------------|/////////////|\\\\\\\\\\\\\|
+ * | | | |
+ * n/4 n/2 3n/4
+ */
+
+
+ px_1 = p_Data_Int_precision + n_2 - 1;
+ px_2 = p_Data_Int_precision;
+
+ px_4 = p_Data_Int_precision + n_3_4 - 1;
+
+ for (i = 0; i<INV_LONG_CX_ROT_LENGTH >> 1; i++)
+ {
+
+ Int16 temp_re_0 = *(px_4--);
+ Int16 temp_im_1 = *(px_4--);
+ Int16 temp_re_2 = *(px_4--);
+ Int16 temp_im_3 = *(px_4--);
+ *(px_1--) = temp_re_0;
+ *(px_1--) = temp_im_1;
+ *(px_1--) = temp_re_2;
+ *(px_1--) = temp_im_3;
+
+ *(px_2++) = (-temp_re_0);
+ *(px_2++) = (-temp_im_1);
+ *(px_2++) = (-temp_re_2);
+ *(px_2++) = (-temp_im_3);
+
+ }
+
+
+ px_4 = p_Data_Int_precision + n_2;
+
+
+ pv_memcpy(px_4, pData_in_ref2 + 256, TWICE_INV_LONG_CX_ROT_LENGTH*sizeof(*px_4));
+
+
+
+ /*
+ * px2--> <--px1 px4--> <--px3
+ *
+ * | | |
+ * |+++++++++++++|+++++++++++++|+++++++++++++|+++++++++++++|
+ * | | | |
+ * n/4 n/2 3n/4
+ */
+ px_3 = p_Data_Int_precision + n - 1;
+
+
+ for (i = 0; i<INV_LONG_CX_ROT_LENGTH >> 1; i++)
+ {
+
+ Int16 temp_im_0 = *(px_4++);
+ Int16 temp_re_1 = *(px_4++);
+ Int16 temp_im_2 = *(px_4++);
+ Int16 temp_re_3 = *(px_4++);
+ *(px_3--) = temp_im_0;
+ *(px_3--) = temp_re_1;
+ *(px_3--) = temp_im_2;
+ *(px_3--) = temp_re_3;
+
+ }
+
+
+ return (exp + 1);
+}
+
diff --git a/media/libstagefright/codecs/aacdec/inv_long_complex_rot.h b/media/libstagefright/codecs/aacdec/inv_long_complex_rot.h
new file mode 100644
index 0000000..8b95867
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/inv_long_complex_rot.h
@@ -0,0 +1,99 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: inv_long_complex_rot.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for function inv_long_complex_rot()
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef INV_LONG_COMPLEX_ROT_H
+#define INV_LONG_COMPLEX_ROT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define INV_LONG_CX_ROT_LENGTH 256
+#define TWICE_INV_LONG_CX_ROT_LENGTH (INV_LONG_CX_ROT_LENGTH<<1)
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ Int inv_long_complex_rot(
+ Int32 *Data,
+ Int32 max);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* INV_LONG_COMPLEX_ROT_H */
diff --git a/media/libstagefright/codecs/aacdec/inv_short_complex_rot.cpp b/media/libstagefright/codecs/aacdec/inv_short_complex_rot.cpp
new file mode 100644
index 0000000..5b4f1c5
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/inv_short_complex_rot.cpp
@@ -0,0 +1,305 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: inv_short_complex_rot.c
+ Funtions: inv_short_complex_rot
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Date: 10/18/2002
+ Description:
+ (1) Change the input argument, only a single max is passed.
+ (2) Eliminate search for max, a fixed shift has replaced the
+ search for max with minimal loss of precision.
+ (3) Eliminated unused variables
+
+ Date: 10/28/2002
+ Description:
+ (1) Added comments per code review
+ (2) Eliminated hardly used condition on if-else (exp==0)
+
+ Description:
+
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ Data_in = Input vector (sized for short windows
+ 2*INV_SHORT_CX_ROT_LENGTH elements), with time domain samples
+ type Int32 *
+
+ Data_out = Output vector with a post-rotation by exp(j(2pi/N)(k+1/8)),
+ (sized for short windows 2*INV_SHORT_CX_ROT_LENGTH)
+ type Int32 *
+
+ max = Input, carries the maximum value of the input vector
+ "Data_in"
+ type Int32
+
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ exp = shift factor to reflect signal scaling
+
+ Pointers and Buffers Modified:
+ Results are return in "Data_out"
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ inv_short_complex_rot() performs the complex rotation for the inverse MDCT
+ for the case of short windows. It performs digit reverse ordering as well
+ word normalization to ensure 16 by 16 bit multiplications.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ inv_short_complex_rot() should execute a post-rotation by
+ exp( j(2pi/N)(k+1/8)), digit reverse ordering and word normalization
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "digit_reversal_tables.h"
+#include "imdct_fxp.h"
+#include "inv_short_complex_rot.h"
+#include "pv_normalize.h"
+#include "fxp_mul32.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+Int inv_short_complex_rot(
+ Int32 *Data_in,
+ Int32 *Data_out,
+ Int32 max)
+
+{
+ Int i;
+ Int16 I;
+ const Int16 *pTable;
+ const Int32 *p_rotate;
+
+ Int32 *pData_in_1;
+ Int exp;
+ Int32 temp_re;
+ Int32 temp_im;
+
+ Int32 exp_jw;
+ Int16 *pData_re;
+ Int16 *pData_im;
+ Int32 *pData_in_ref;
+
+ Int16 temp_re_0;
+ Int16 temp_im_0;
+ Int16 temp_re_1;
+ Int16 temp_im_1;
+ Int16 *p_data_1;
+ Int16 *p_data_2;
+ Int16 *p_Data_Int_precision;
+ Int16 *p_Data_Int_precision_1;
+ Int16 *p_Data_Int_precision_2;
+
+ Int n = 256;
+ Int n_2 = n >> 1;
+ Int n_4 = n >> 2;
+ Int n_8 = n >> 3;
+ Int n_3_4 = n_2 + n_4;
+
+
+ p_data_1 = (Int16 *)Data_out;
+ p_data_1 += n;
+ pData_re = p_data_1;
+ pData_im = p_data_1 + n_4;
+
+
+ p_rotate = exp_rotation_N_256;
+ pTable = digit_reverse_64;
+
+ pData_in_ref = Data_in;
+
+ exp = 16 - pv_normalize(max);
+
+
+ if (exp < 0)
+ {
+ exp = 0;
+ }
+
+ exp -= 1;
+
+ for (i = INV_SHORT_CX_ROT_LENGTH; i != 0; i--)
+ {
+
+ /*
+ * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
+ */
+
+ /*
+ * Perform digit reversal by accessing index I from table
+ */
+
+ I = *pTable++;
+ pData_in_1 = pData_in_ref + I;
+ /*
+ * Use auxiliary variables to avoid double accesses to memory.
+ * Data in is scaled to use only lower 16 bits.
+ */
+
+ temp_im = *(pData_in_1++);
+ temp_re = *(pData_in_1);
+
+ exp_jw = *p_rotate++;
+
+ /*
+ * Post-rotation
+ */
+
+ *(pData_re++) = (Int16)(cmplx_mul32_by_16(temp_re, -temp_im, exp_jw) >> exp);
+ *(pData_im++) = (Int16)(cmplx_mul32_by_16(temp_im, temp_re, exp_jw) >> exp);
+ }
+
+
+ p_data_2 = pData_im - 1;
+
+
+ p_Data_Int_precision = (Int16 *)Data_out;
+ p_Data_Int_precision_1 = p_Data_Int_precision + n_3_4 - 1;
+ p_Data_Int_precision_2 = p_Data_Int_precision + n_3_4;
+
+ for (i = n_8 >> 1; i != 0; i--)
+ {
+ temp_re_0 = (*(p_data_1++));
+ temp_re_1 = (*(p_data_1++));
+ temp_im_0 = (*(p_data_2--));
+ temp_im_1 = (*(p_data_2--));
+
+ *(p_Data_Int_precision_1--) = temp_re_0;
+ *(p_Data_Int_precision_1--) = temp_im_0;
+ *(p_Data_Int_precision_1--) = temp_re_1;
+ *(p_Data_Int_precision_1--) = temp_im_1;
+
+ *(p_Data_Int_precision_2++) = temp_re_0;
+ *(p_Data_Int_precision_2++) = temp_im_0;
+ *(p_Data_Int_precision_2++) = temp_re_1;
+ *(p_Data_Int_precision_2++) = temp_im_1;
+
+ }
+
+
+ /*
+ * loop is split to avoid conditional testing inside loop
+ */
+
+ p_Data_Int_precision_2 = p_Data_Int_precision;
+
+ for (i = n_8 >> 1; i != 0; i--)
+ {
+
+ temp_re_0 = (*(p_data_1++));
+ temp_re_1 = (*(p_data_1++));
+ temp_im_0 = (*(p_data_2--));
+ temp_im_1 = (*(p_data_2--));
+
+ *(p_Data_Int_precision_1--) = temp_re_0;
+ *(p_Data_Int_precision_1--) = temp_im_0;
+ *(p_Data_Int_precision_1--) = temp_re_1;
+ *(p_Data_Int_precision_1--) = temp_im_1;
+
+ *(p_Data_Int_precision_2++) = (Int16)(-temp_re_0);
+ *(p_Data_Int_precision_2++) = (Int16)(-temp_im_0);
+ *(p_Data_Int_precision_2++) = (Int16)(-temp_re_1);
+ *(p_Data_Int_precision_2++) = (Int16)(-temp_im_1);
+
+ }
+
+ return (exp + 1);
+}
diff --git a/media/libstagefright/codecs/aacdec/inv_short_complex_rot.h b/media/libstagefright/codecs/aacdec/inv_short_complex_rot.h
new file mode 100644
index 0000000..97ed730
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/inv_short_complex_rot.h
@@ -0,0 +1,88 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: inv_short_complex_rot.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for functions inv_short_complex_rot()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef INV_SHORT_COMPLEX_ROT_H
+#define INV_SHORT_COMPLEX_ROT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define INV_SHORT_CX_ROT_LENGTH 64
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+Int inv_short_complex_rot(
+ Int32 *Data_in,
+ Int32 *Data_out,
+ Int32 max);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* INV_SHORT_COMPLEX_ROT_H */
diff --git a/media/libstagefright/codecs/aacdec/iquant_table.cpp b/media/libstagefright/codecs/aacdec/iquant_table.cpp
new file mode 100644
index 0000000..aee47d6
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/iquant_table.cpp
@@ -0,0 +1,1131 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: iquant_table.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ None, just contains tables.
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Holds a table used for esc_iquant, containing the values of x^1/3 in
+ Q format.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 13818-7:1997 Titled "Information technology - Generic coding
+ of moving pictures and associated audio information - Part 7: Advanced
+ Audio Coding (AAC)", Section 10.3, "Decoding process", page 43.
+
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+ None.
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ None.
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "iquant_table.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+ This table contains the value of x ^ (1/3) where x is in the range of
+ [0..1024], in Q27 format.
+ Note that the length of the table is 1025, and not 1024 - this is because
+ the function esc_iquant may need to do an interpolation for numbers near
+ 8191, which in that case it needs to get 8192 ^(1/3).
+ */
+const UInt32 inverseQuantTable[] =
+{
+ 0x00000000, /* 0 */
+ 0x08000000, /* 1 */
+ 0x0a14517d, /* 2 */
+ 0x0b89ba25, /* 3 */
+ 0x0cb2ff53, /* 4 */
+ 0x0dae07de, /* 5 */
+ 0x0e897685, /* 6 */
+ 0x0f4daedd, /* 7 */
+ 0x10000000, /* 8 */
+ 0x10a402fd, /* 9 */
+ 0x113c4841, /* 10 */
+ 0x11cab613, /* 11 */
+ 0x1250bfe2, /* 12 */
+ 0x12cf8890, /* 13 */
+ 0x1347f8ab, /* 14 */
+ 0x13bacd65, /* 15 */
+ 0x1428a2fa, /* 16 */
+ 0x1491fc15, /* 17 */
+ 0x14f74744, /* 18 */
+ 0x1558e2f7, /* 19 */
+ 0x15b72095, /* 20 */
+ 0x161246d7, /* 21 */
+ 0x166a9399, /* 22 */
+ 0x16c03d55, /* 23 */
+ 0x17137449, /* 24 */
+ 0x17646369, /* 25 */
+ 0x17b33124, /* 26 */
+ 0x18000000, /* 27 */
+ 0x184aef29, /* 28 */
+ 0x18941ad8, /* 29 */
+ 0x18db9cb7, /* 30 */
+ 0x19218c2e, /* 31 */
+ 0x1965fea5, /* 32 */
+ 0x19a907c2, /* 33 */
+ 0x19eab998, /* 34 */
+ 0x1a2b24d0, /* 35 */
+ 0x1a6a58d5, /* 36 */
+ 0x1aa863ee, /* 37 */
+ 0x1ae5535d, /* 38 */
+ 0x1b213377, /* 39 */
+ 0x1b5c0fbd, /* 40 */
+ 0x1b95f2ec, /* 41 */
+ 0x1bcee70f, /* 42 */
+ 0x1c06f590, /* 43 */
+ 0x1c3e2745, /* 44 */
+ 0x1c74847a, /* 45 */
+ 0x1caa1501, /* 46 */
+ 0x1cdee035, /* 47 */
+ 0x1d12ed0b, /* 48 */
+ 0x1d464212, /* 49 */
+ 0x1d78e582, /* 50 */
+ 0x1daadd3a, /* 51 */
+ 0x1ddc2ecf, /* 52 */
+ 0x1e0cdf8c, /* 53 */
+ 0x1e3cf476, /* 54 */
+ 0x1e6c7257, /* 55 */
+ 0x1e9b5dba, /* 56 */
+ 0x1ec9baf6, /* 57 */
+ 0x1ef78e2c, /* 58 */
+ 0x1f24db4e, /* 59 */
+ 0x1f51a620, /* 60 */
+ 0x1f7df23c, /* 61 */
+ 0x1fa9c314, /* 62 */
+ 0x1fd51bf2, /* 63 */
+ 0x20000000, /* 64 */
+ 0x202a7244, /* 65 */
+ 0x205475a6, /* 66 */
+ 0x207e0cee, /* 67 */
+ 0x20a73aca, /* 68 */
+ 0x20d001cc, /* 69 */
+ 0x20f8646d, /* 70 */
+ 0x2120650e, /* 71 */
+ 0x214805fa, /* 72 */
+ 0x216f4963, /* 73 */
+ 0x2196316c, /* 74 */
+ 0x21bcc020, /* 75 */
+ 0x21e2f77a, /* 76 */
+ 0x2208d961, /* 77 */
+ 0x222e67ad, /* 78 */
+ 0x2253a425, /* 79 */
+ 0x22789082, /* 80 */
+ 0x229d2e6e, /* 81 */
+ 0x22c17f82, /* 82 */
+ 0x22e5854f, /* 83 */
+ 0x23094155, /* 84 */
+ 0x232cb509, /* 85 */
+ 0x234fe1d5, /* 86 */
+ 0x2372c918, /* 87 */
+ 0x23956c26, /* 88 */
+ 0x23b7cc47, /* 89 */
+ 0x23d9eabb, /* 90 */
+ 0x23fbc8b9, /* 91 */
+ 0x241d676e, /* 92 */
+ 0x243ec7ff, /* 93 */
+ 0x245feb86, /* 94 */
+ 0x2480d319, /* 95 */
+ 0x24a17fc3, /* 96 */
+ 0x24c1f28b, /* 97 */
+ 0x24e22c6c, /* 98 */
+ 0x25022e5f, /* 99 */
+ 0x2521f954, /* 100 */
+ 0x25418e33, /* 101 */
+ 0x2560ede2, /* 102 */
+ 0x2580193e, /* 103 */
+ 0x259f111f, /* 104 */
+ 0x25bdd657, /* 105 */
+ 0x25dc69b4, /* 106 */
+ 0x25facbfe, /* 107 */
+ 0x2618fdf8, /* 108 */
+ 0x26370060, /* 109 */
+ 0x2654d3ef, /* 110 */
+ 0x2672795c, /* 111 */
+ 0x268ff156, /* 112 */
+ 0x26ad3c8a, /* 113 */
+ 0x26ca5ba2, /* 114 */
+ 0x26e74f41, /* 115 */
+ 0x27041808, /* 116 */
+ 0x2720b695, /* 117 */
+ 0x273d2b81, /* 118 */
+ 0x27597762, /* 119 */
+ 0x27759acb, /* 120 */
+ 0x2791964b, /* 121 */
+ 0x27ad6a6f, /* 122 */
+ 0x27c917c0, /* 123 */
+ 0x27e49ec5, /* 124 */
+ 0x28000000, /* 125 */
+ 0x281b3bf3, /* 126 */
+ 0x2836531b, /* 127 */
+ 0x285145f3, /* 128 */
+ 0x286c14f5, /* 129 */
+ 0x2886c096, /* 130 */
+ 0x28a1494b, /* 131 */
+ 0x28bbaf85, /* 132 */
+ 0x28d5f3b3, /* 133 */
+ 0x28f01641, /* 134 */
+ 0x290a179b, /* 135 */
+ 0x2923f82a, /* 136 */
+ 0x293db854, /* 137 */
+ 0x2957587e, /* 138 */
+ 0x2970d90a, /* 139 */
+ 0x298a3a59, /* 140 */
+ 0x29a37cca, /* 141 */
+ 0x29bca0bb, /* 142 */
+ 0x29d5a687, /* 143 */
+ 0x29ee8e87, /* 144 */
+ 0x2a075914, /* 145 */
+ 0x2a200684, /* 146 */
+ 0x2a38972c, /* 147 */
+ 0x2a510b5f, /* 148 */
+ 0x2a696370, /* 149 */
+ 0x2a819fae, /* 150 */
+ 0x2a99c069, /* 151 */
+ 0x2ab1c5ed, /* 152 */
+ 0x2ac9b088, /* 153 */
+ 0x2ae18085, /* 154 */
+ 0x2af9362c, /* 155 */
+ 0x2b10d1c6, /* 156 */
+ 0x2b28539b, /* 157 */
+ 0x2b3fbbef, /* 158 */
+ 0x2b570b09, /* 159 */
+ 0x2b6e412b, /* 160 */
+ 0x2b855e97, /* 161 */
+ 0x2b9c6390, /* 162 */
+ 0x2bb35056, /* 163 */
+ 0x2bca2527, /* 164 */
+ 0x2be0e242, /* 165 */
+ 0x2bf787e4, /* 166 */
+ 0x2c0e1649, /* 167 */
+ 0x2c248dad, /* 168 */
+ 0x2c3aee4a, /* 169 */
+ 0x2c513859, /* 170 */
+ 0x2c676c13, /* 171 */
+ 0x2c7d89af, /* 172 */
+ 0x2c939164, /* 173 */
+ 0x2ca98368, /* 174 */
+ 0x2cbf5ff1, /* 175 */
+ 0x2cd52731, /* 176 */
+ 0x2cead95e, /* 177 */
+ 0x2d0076a9, /* 178 */
+ 0x2d15ff45, /* 179 */
+ 0x2d2b7363, /* 180 */
+ 0x2d40d332, /* 181 */
+ 0x2d561ee4, /* 182 */
+ 0x2d6b56a7, /* 183 */
+ 0x2d807aaa, /* 184 */
+ 0x2d958b19, /* 185 */
+ 0x2daa8823, /* 186 */
+ 0x2dbf71f4, /* 187 */
+ 0x2dd448b7, /* 188 */
+ 0x2de90c98, /* 189 */
+ 0x2dfdbdc0, /* 190 */
+ 0x2e125c5c, /* 191 */
+ 0x2e26e892, /* 192 */
+ 0x2e3b628d, /* 193 */
+ 0x2e4fca75, /* 194 */
+ 0x2e642070, /* 195 */
+ 0x2e7864a8, /* 196 */
+ 0x2e8c9741, /* 197 */
+ 0x2ea0b862, /* 198 */
+ 0x2eb4c831, /* 199 */
+ 0x2ec8c6d3, /* 200 */
+ 0x2edcb46c, /* 201 */
+ 0x2ef09121, /* 202 */
+ 0x2f045d14, /* 203 */
+ 0x2f18186a, /* 204 */
+ 0x2f2bc345, /* 205 */
+ 0x2f3f5dc7, /* 206 */
+ 0x2f52e812, /* 207 */
+ 0x2f666247, /* 208 */
+ 0x2f79cc88, /* 209 */
+ 0x2f8d26f4, /* 210 */
+ 0x2fa071ac, /* 211 */
+ 0x2fb3acd0, /* 212 */
+ 0x2fc6d87f, /* 213 */
+ 0x2fd9f4d7, /* 214 */
+ 0x2fed01f8, /* 215 */
+ 0x30000000, /* 216 */
+ 0x3012ef0c, /* 217 */
+ 0x3025cf39, /* 218 */
+ 0x3038a0a6, /* 219 */
+ 0x304b636d, /* 220 */
+ 0x305e17ad, /* 221 */
+ 0x3070bd81, /* 222 */
+ 0x30835504, /* 223 */
+ 0x3095de51, /* 224 */
+ 0x30a85985, /* 225 */
+ 0x30bac6b9, /* 226 */
+ 0x30cd2609, /* 227 */
+ 0x30df778d, /* 228 */
+ 0x30f1bb60, /* 229 */
+ 0x3103f19c, /* 230 */
+ 0x31161a59, /* 231 */
+ 0x312835b0, /* 232 */
+ 0x313a43ba, /* 233 */
+ 0x314c4490, /* 234 */
+ 0x315e3849, /* 235 */
+ 0x31701efd, /* 236 */
+ 0x3181f8c4, /* 237 */
+ 0x3193c5b4, /* 238 */
+ 0x31a585e6, /* 239 */
+ 0x31b7396f, /* 240 */
+ 0x31c8e066, /* 241 */
+ 0x31da7ae1, /* 242 */
+ 0x31ec08f6, /* 243 */
+ 0x31fd8abc, /* 244 */
+ 0x320f0047, /* 245 */
+ 0x322069ac, /* 246 */
+ 0x3231c702, /* 247 */
+ 0x3243185c, /* 248 */
+ 0x32545dcf, /* 249 */
+ 0x32659770, /* 250 */
+ 0x3276c552, /* 251 */
+ 0x3287e78a, /* 252 */
+ 0x3298fe2c, /* 253 */
+ 0x32aa094a, /* 254 */
+ 0x32bb08f9, /* 255 */
+ 0x32cbfd4a, /* 256 */
+ 0x32dce652, /* 257 */
+ 0x32edc423, /* 258 */
+ 0x32fe96d0, /* 259 */
+ 0x330f5e6a, /* 260 */
+ 0x33201b04, /* 261 */
+ 0x3330ccb0, /* 262 */
+ 0x33417380, /* 263 */
+ 0x33520f85, /* 264 */
+ 0x3362a0d0, /* 265 */
+ 0x33732774, /* 266 */
+ 0x3383a380, /* 267 */
+ 0x33941506, /* 268 */
+ 0x33a47c17, /* 269 */
+ 0x33b4d8c4, /* 270 */
+ 0x33c52b1b, /* 271 */
+ 0x33d5732f, /* 272 */
+ 0x33e5b10f, /* 273 */
+ 0x33f5e4ca, /* 274 */
+ 0x34060e71, /* 275 */
+ 0x34162e14, /* 276 */
+ 0x342643c1, /* 277 */
+ 0x34364f88, /* 278 */
+ 0x34465178, /* 279 */
+ 0x345649a1, /* 280 */
+ 0x34663810, /* 281 */
+ 0x34761cd6, /* 282 */
+ 0x3485f800, /* 283 */
+ 0x3495c99d, /* 284 */
+ 0x34a591bb, /* 285 */
+ 0x34b55069, /* 286 */
+ 0x34c505b4, /* 287 */
+ 0x34d4b1ab, /* 288 */
+ 0x34e4545b, /* 289 */
+ 0x34f3edd2, /* 290 */
+ 0x35037e1d, /* 291 */
+ 0x3513054b, /* 292 */
+ 0x35228367, /* 293 */
+ 0x3531f881, /* 294 */
+ 0x354164a3, /* 295 */
+ 0x3550c7dc, /* 296 */
+ 0x35602239, /* 297 */
+ 0x356f73c5, /* 298 */
+ 0x357ebc8e, /* 299 */
+ 0x358dfca0, /* 300 */
+ 0x359d3408, /* 301 */
+ 0x35ac62d1, /* 302 */
+ 0x35bb8908, /* 303 */
+ 0x35caa6b9, /* 304 */
+ 0x35d9bbf0, /* 305 */
+ 0x35e8c8b9, /* 306 */
+ 0x35f7cd20, /* 307 */
+ 0x3606c92f, /* 308 */
+ 0x3615bcf3, /* 309 */
+ 0x3624a878, /* 310 */
+ 0x36338bc8, /* 311 */
+ 0x364266ee, /* 312 */
+ 0x365139f6, /* 313 */
+ 0x366004ec, /* 314 */
+ 0x366ec7d9, /* 315 */
+ 0x367d82c9, /* 316 */
+ 0x368c35c6, /* 317 */
+ 0x369ae0dc, /* 318 */
+ 0x36a98414, /* 319 */
+ 0x36b81f7a, /* 320 */
+ 0x36c6b317, /* 321 */
+ 0x36d53ef7, /* 322 */
+ 0x36e3c323, /* 323 */
+ 0x36f23fa5, /* 324 */
+ 0x3700b488, /* 325 */
+ 0x370f21d5, /* 326 */
+ 0x371d8797, /* 327 */
+ 0x372be5d7, /* 328 */
+ 0x373a3ca0, /* 329 */
+ 0x37488bf9, /* 330 */
+ 0x3756d3ef, /* 331 */
+ 0x37651489, /* 332 */
+ 0x37734dd1, /* 333 */
+ 0x37817fd1, /* 334 */
+ 0x378faa92, /* 335 */
+ 0x379dce1d, /* 336 */
+ 0x37abea7c, /* 337 */
+ 0x37b9ffb7, /* 338 */
+ 0x37c80dd7, /* 339 */
+ 0x37d614e6, /* 340 */
+ 0x37e414ec, /* 341 */
+ 0x37f20df1, /* 342 */
+ 0x38000000, /* 343 */
+ 0x380deb20, /* 344 */
+ 0x381bcf5a, /* 345 */
+ 0x3829acb6, /* 346 */
+ 0x3837833d, /* 347 */
+ 0x384552f8, /* 348 */
+ 0x38531bee, /* 349 */
+ 0x3860de28, /* 350 */
+ 0x386e99af, /* 351 */
+ 0x387c4e89, /* 352 */
+ 0x3889fcc0, /* 353 */
+ 0x3897a45b, /* 354 */
+ 0x38a54563, /* 355 */
+ 0x38b2dfdf, /* 356 */
+ 0x38c073d7, /* 357 */
+ 0x38ce0152, /* 358 */
+ 0x38db885a, /* 359 */
+ 0x38e908f4, /* 360 */
+ 0x38f68329, /* 361 */
+ 0x3903f701, /* 362 */
+ 0x39116483, /* 363 */
+ 0x391ecbb6, /* 364 */
+ 0x392c2ca1, /* 365 */
+ 0x3939874d, /* 366 */
+ 0x3946dbc0, /* 367 */
+ 0x39542a01, /* 368 */
+ 0x39617218, /* 369 */
+ 0x396eb40c, /* 370 */
+ 0x397befe4, /* 371 */
+ 0x398925a7, /* 372 */
+ 0x3996555c, /* 373 */
+ 0x39a37f09, /* 374 */
+ 0x39b0a2b7, /* 375 */
+ 0x39bdc06a, /* 376 */
+ 0x39cad82b, /* 377 */
+ 0x39d7ea01, /* 378 */
+ 0x39e4f5f0, /* 379 */
+ 0x39f1fc01, /* 380 */
+ 0x39fefc3a, /* 381 */
+ 0x3a0bf6a2, /* 382 */
+ 0x3a18eb3e, /* 383 */
+ 0x3a25da16, /* 384 */
+ 0x3a32c32f, /* 385 */
+ 0x3a3fa691, /* 386 */
+ 0x3a4c8441, /* 387 */
+ 0x3a595c46, /* 388 */
+ 0x3a662ea6, /* 389 */
+ 0x3a72fb67, /* 390 */
+ 0x3a7fc28f, /* 391 */
+ 0x3a8c8425, /* 392 */
+ 0x3a99402e, /* 393 */
+ 0x3aa5f6b1, /* 394 */
+ 0x3ab2a7b3, /* 395 */
+ 0x3abf533a, /* 396 */
+ 0x3acbf94d, /* 397 */
+ 0x3ad899f1, /* 398 */
+ 0x3ae5352c, /* 399 */
+ 0x3af1cb03, /* 400 */
+ 0x3afe5b7d, /* 401 */
+ 0x3b0ae6a0, /* 402 */
+ 0x3b176c70, /* 403 */
+ 0x3b23ecf3, /* 404 */
+ 0x3b306830, /* 405 */
+ 0x3b3cde2c, /* 406 */
+ 0x3b494eeb, /* 407 */
+ 0x3b55ba74, /* 408 */
+ 0x3b6220cc, /* 409 */
+ 0x3b6e81f9, /* 410 */
+ 0x3b7ade00, /* 411 */
+ 0x3b8734e5, /* 412 */
+ 0x3b9386b0, /* 413 */
+ 0x3b9fd364, /* 414 */
+ 0x3bac1b07, /* 415 */
+ 0x3bb85d9e, /* 416 */
+ 0x3bc49b2f, /* 417 */
+ 0x3bd0d3be, /* 418 */
+ 0x3bdd0751, /* 419 */
+ 0x3be935ed, /* 420 */
+ 0x3bf55f97, /* 421 */
+ 0x3c018453, /* 422 */
+ 0x3c0da427, /* 423 */
+ 0x3c19bf17, /* 424 */
+ 0x3c25d52a, /* 425 */
+ 0x3c31e662, /* 426 */
+ 0x3c3df2c6, /* 427 */
+ 0x3c49fa5b, /* 428 */
+ 0x3c55fd24, /* 429 */
+ 0x3c61fb27, /* 430 */
+ 0x3c6df468, /* 431 */
+ 0x3c79e8ed, /* 432 */
+ 0x3c85d8b9, /* 433 */
+ 0x3c91c3d2, /* 434 */
+ 0x3c9daa3c, /* 435 */
+ 0x3ca98bfc, /* 436 */
+ 0x3cb56915, /* 437 */
+ 0x3cc1418e, /* 438 */
+ 0x3ccd156a, /* 439 */
+ 0x3cd8e4ae, /* 440 */
+ 0x3ce4af5e, /* 441 */
+ 0x3cf0757f, /* 442 */
+ 0x3cfc3714, /* 443 */
+ 0x3d07f423, /* 444 */
+ 0x3d13acb0, /* 445 */
+ 0x3d1f60bf, /* 446 */
+ 0x3d2b1055, /* 447 */
+ 0x3d36bb75, /* 448 */
+ 0x3d426224, /* 449 */
+ 0x3d4e0466, /* 450 */
+ 0x3d59a23f, /* 451 */
+ 0x3d653bb4, /* 452 */
+ 0x3d70d0c8, /* 453 */
+ 0x3d7c6180, /* 454 */
+ 0x3d87ede0, /* 455 */
+ 0x3d9375ec, /* 456 */
+ 0x3d9ef9a8, /* 457 */
+ 0x3daa7918, /* 458 */
+ 0x3db5f43f, /* 459 */
+ 0x3dc16b23, /* 460 */
+ 0x3dccddc7, /* 461 */
+ 0x3dd84c2e, /* 462 */
+ 0x3de3b65d, /* 463 */
+ 0x3def1c58, /* 464 */
+ 0x3dfa7e22, /* 465 */
+ 0x3e05dbc0, /* 466 */
+ 0x3e113535, /* 467 */
+ 0x3e1c8a85, /* 468 */
+ 0x3e27dbb3, /* 469 */
+ 0x3e3328c4, /* 470 */
+ 0x3e3e71bb, /* 471 */
+ 0x3e49b69c, /* 472 */
+ 0x3e54f76b, /* 473 */
+ 0x3e60342b, /* 474 */
+ 0x3e6b6ce0, /* 475 */
+ 0x3e76a18d, /* 476 */
+ 0x3e81d237, /* 477 */
+ 0x3e8cfee0, /* 478 */
+ 0x3e98278d, /* 479 */
+ 0x3ea34c40, /* 480 */
+ 0x3eae6cfe, /* 481 */
+ 0x3eb989ca, /* 482 */
+ 0x3ec4a2a8, /* 483 */
+ 0x3ecfb79a, /* 484 */
+ 0x3edac8a5, /* 485 */
+ 0x3ee5d5cb, /* 486 */
+ 0x3ef0df10, /* 487 */
+ 0x3efbe478, /* 488 */
+ 0x3f06e606, /* 489 */
+ 0x3f11e3be, /* 490 */
+ 0x3f1cdda2, /* 491 */
+ 0x3f27d3b6, /* 492 */
+ 0x3f32c5fd, /* 493 */
+ 0x3f3db47b, /* 494 */
+ 0x3f489f32, /* 495 */
+ 0x3f538627, /* 496 */
+ 0x3f5e695c, /* 497 */
+ 0x3f6948d5, /* 498 */
+ 0x3f742494, /* 499 */
+ 0x3f7efc9d, /* 500 */
+ 0x3f89d0f3, /* 501 */
+ 0x3f94a19a, /* 502 */
+ 0x3f9f6e94, /* 503 */
+ 0x3faa37e4, /* 504 */
+ 0x3fb4fd8e, /* 505 */
+ 0x3fbfbf94, /* 506 */
+ 0x3fca7dfb, /* 507 */
+ 0x3fd538c4, /* 508 */
+ 0x3fdfeff3, /* 509 */
+ 0x3feaa38a, /* 510 */
+ 0x3ff5538e, /* 511 */
+ 0x40000000, /* 512 */
+ 0x400aa8e4, /* 513 */
+ 0x40154e3d, /* 514 */
+ 0x401ff00d, /* 515 */
+ 0x402a8e58, /* 516 */
+ 0x40352921, /* 517 */
+ 0x403fc06a, /* 518 */
+ 0x404a5436, /* 519 */
+ 0x4054e488, /* 520 */
+ 0x405f7164, /* 521 */
+ 0x4069facb, /* 522 */
+ 0x407480c1, /* 523 */
+ 0x407f0348, /* 524 */
+ 0x40898264, /* 525 */
+ 0x4093fe16, /* 526 */
+ 0x409e7663, /* 527 */
+ 0x40a8eb4c, /* 528 */
+ 0x40b35cd4, /* 529 */
+ 0x40bdcafe, /* 530 */
+ 0x40c835cd, /* 531 */
+ 0x40d29d43, /* 532 */
+ 0x40dd0164, /* 533 */
+ 0x40e76231, /* 534 */
+ 0x40f1bfae, /* 535 */
+ 0x40fc19dc, /* 536 */
+ 0x410670c0, /* 537 */
+ 0x4110c45a, /* 538 */
+ 0x411b14af, /* 539 */
+ 0x412561c0, /* 540 */
+ 0x412fab90, /* 541 */
+ 0x4139f222, /* 542 */
+ 0x41443578, /* 543 */
+ 0x414e7595, /* 544 */
+ 0x4158b27a, /* 545 */
+ 0x4162ec2c, /* 546 */
+ 0x416d22ac, /* 547 */
+ 0x417755fd, /* 548 */
+ 0x41818621, /* 549 */
+ 0x418bb31a, /* 550 */
+ 0x4195dcec, /* 551 */
+ 0x41a00399, /* 552 */
+ 0x41aa2722, /* 553 */
+ 0x41b4478b, /* 554 */
+ 0x41be64d6, /* 555 */
+ 0x41c87f05, /* 556 */
+ 0x41d2961a, /* 557 */
+ 0x41dcaa19, /* 558 */
+ 0x41e6bb03, /* 559 */
+ 0x41f0c8db, /* 560 */
+ 0x41fad3a3, /* 561 */
+ 0x4204db5d, /* 562 */
+ 0x420ee00c, /* 563 */
+ 0x4218e1b1, /* 564 */
+ 0x4222e051, /* 565 */
+ 0x422cdbeb, /* 566 */
+ 0x4236d484, /* 567 */
+ 0x4240ca1d, /* 568 */
+ 0x424abcb8, /* 569 */
+ 0x4254ac58, /* 570 */
+ 0x425e98fe, /* 571 */
+ 0x426882ae, /* 572 */
+ 0x42726969, /* 573 */
+ 0x427c4d31, /* 574 */
+ 0x42862e09, /* 575 */
+ 0x42900bf3, /* 576 */
+ 0x4299e6f1, /* 577 */
+ 0x42a3bf05, /* 578 */
+ 0x42ad9432, /* 579 */
+ 0x42b76678, /* 580 */
+ 0x42c135dc, /* 581 */
+ 0x42cb025e, /* 582 */
+ 0x42d4cc01, /* 583 */
+ 0x42de92c7, /* 584 */
+ 0x42e856b2, /* 585 */
+ 0x42f217c4, /* 586 */
+ 0x42fbd5ff, /* 587 */
+ 0x43059166, /* 588 */
+ 0x430f49f9, /* 589 */
+ 0x4318ffbc, /* 590 */
+ 0x4322b2b1, /* 591 */
+ 0x432c62d8, /* 592 */
+ 0x43361036, /* 593 */
+ 0x433fbaca, /* 594 */
+ 0x43496298, /* 595 */
+ 0x435307a2, /* 596 */
+ 0x435ca9e8, /* 597 */
+ 0x4366496e, /* 598 */
+ 0x436fe636, /* 599 */
+ 0x43798041, /* 600 */
+ 0x43831790, /* 601 */
+ 0x438cac28, /* 602 */
+ 0x43963e08, /* 603 */
+ 0x439fcd33, /* 604 */
+ 0x43a959ab, /* 605 */
+ 0x43b2e372, /* 606 */
+ 0x43bc6a89, /* 607 */
+ 0x43c5eef3, /* 608 */
+ 0x43cf70b2, /* 609 */
+ 0x43d8efc7, /* 610 */
+ 0x43e26c34, /* 611 */
+ 0x43ebe5fb, /* 612 */
+ 0x43f55d1e, /* 613 */
+ 0x43fed19f, /* 614 */
+ 0x44084380, /* 615 */
+ 0x4411b2c1, /* 616 */
+ 0x441b1f66, /* 617 */
+ 0x44248970, /* 618 */
+ 0x442df0e1, /* 619 */
+ 0x443755bb, /* 620 */
+ 0x4440b7fe, /* 621 */
+ 0x444a17ae, /* 622 */
+ 0x445374cc, /* 623 */
+ 0x445ccf5a, /* 624 */
+ 0x44662758, /* 625 */
+ 0x446f7ccb, /* 626 */
+ 0x4478cfb2, /* 627 */
+ 0x4482200f, /* 628 */
+ 0x448b6de5, /* 629 */
+ 0x4494b935, /* 630 */
+ 0x449e0201, /* 631 */
+ 0x44a7484b, /* 632 */
+ 0x44b08c13, /* 633 */
+ 0x44b9cd5d, /* 634 */
+ 0x44c30c29, /* 635 */
+ 0x44cc4879, /* 636 */
+ 0x44d5824f, /* 637 */
+ 0x44deb9ac, /* 638 */
+ 0x44e7ee93, /* 639 */
+ 0x44f12105, /* 640 */
+ 0x44fa5103, /* 641 */
+ 0x45037e8f, /* 642 */
+ 0x450ca9ab, /* 643 */
+ 0x4515d258, /* 644 */
+ 0x451ef899, /* 645 */
+ 0x45281c6e, /* 646 */
+ 0x45313dd8, /* 647 */
+ 0x453a5cdb, /* 648 */
+ 0x45437977, /* 649 */
+ 0x454c93ae, /* 650 */
+ 0x4555ab82, /* 651 */
+ 0x455ec0f3, /* 652 */
+ 0x4567d404, /* 653 */
+ 0x4570e4b7, /* 654 */
+ 0x4579f30c, /* 655 */
+ 0x4582ff05, /* 656 */
+ 0x458c08a4, /* 657 */
+ 0x45950fea, /* 658 */
+ 0x459e14d9, /* 659 */
+ 0x45a71773, /* 660 */
+ 0x45b017b8, /* 661 */
+ 0x45b915aa, /* 662 */
+ 0x45c2114c, /* 663 */
+ 0x45cb0a9e, /* 664 */
+ 0x45d401a1, /* 665 */
+ 0x45dcf658, /* 666 */
+ 0x45e5e8c4, /* 667 */
+ 0x45eed8e6, /* 668 */
+ 0x45f7c6c0, /* 669 */
+ 0x4600b253, /* 670 */
+ 0x46099ba0, /* 671 */
+ 0x461282a9, /* 672 */
+ 0x461b6770, /* 673 */
+ 0x462449f6, /* 674 */
+ 0x462d2a3c, /* 675 */
+ 0x46360844, /* 676 */
+ 0x463ee40f, /* 677 */
+ 0x4647bd9f, /* 678 */
+ 0x465094f5, /* 679 */
+ 0x46596a12, /* 680 */
+ 0x46623cf8, /* 681 */
+ 0x466b0da8, /* 682 */
+ 0x4673dc24, /* 683 */
+ 0x467ca86c, /* 684 */
+ 0x46857283, /* 685 */
+ 0x468e3a69, /* 686 */
+ 0x46970021, /* 687 */
+ 0x469fc3ab, /* 688 */
+ 0x46a88509, /* 689 */
+ 0x46b1443b, /* 690 */
+ 0x46ba0144, /* 691 */
+ 0x46c2bc25, /* 692 */
+ 0x46cb74df, /* 693 */
+ 0x46d42b74, /* 694 */
+ 0x46dcdfe4, /* 695 */
+ 0x46e59231, /* 696 */
+ 0x46ee425c, /* 697 */
+ 0x46f6f068, /* 698 */
+ 0x46ff9c54, /* 699 */
+ 0x47084622, /* 700 */
+ 0x4710edd4, /* 701 */
+ 0x4719936b, /* 702 */
+ 0x472236e7, /* 703 */
+ 0x472ad84b, /* 704 */
+ 0x47337798, /* 705 */
+ 0x473c14cf, /* 706 */
+ 0x4744aff1, /* 707 */
+ 0x474d48ff, /* 708 */
+ 0x4755dffb, /* 709 */
+ 0x475e74e6, /* 710 */
+ 0x476707c1, /* 711 */
+ 0x476f988e, /* 712 */
+ 0x4778274d, /* 713 */
+ 0x4780b400, /* 714 */
+ 0x47893ea8, /* 715 */
+ 0x4791c746, /* 716 */
+ 0x479a4ddc, /* 717 */
+ 0x47a2d26b, /* 718 */
+ 0x47ab54f3, /* 719 */
+ 0x47b3d577, /* 720 */
+ 0x47bc53f7, /* 721 */
+ 0x47c4d074, /* 722 */
+ 0x47cd4af0, /* 723 */
+ 0x47d5c36c, /* 724 */
+ 0x47de39e9, /* 725 */
+ 0x47e6ae69, /* 726 */
+ 0x47ef20ec, /* 727 */
+ 0x47f79173, /* 728 */
+ 0x48000000, /* 729 */
+ 0x48086c94, /* 730 */
+ 0x4810d730, /* 731 */
+ 0x48193fd5, /* 732 */
+ 0x4821a685, /* 733 */
+ 0x482a0b40, /* 734 */
+ 0x48326e07, /* 735 */
+ 0x483acedd, /* 736 */
+ 0x48432dc1, /* 737 */
+ 0x484b8ab5, /* 738 */
+ 0x4853e5bb, /* 739 */
+ 0x485c3ed2, /* 740 */
+ 0x486495fd, /* 741 */
+ 0x486ceb3c, /* 742 */
+ 0x48753e91, /* 743 */
+ 0x487d8ffd, /* 744 */
+ 0x4885df80, /* 745 */
+ 0x488e2d1d, /* 746 */
+ 0x489678d3, /* 747 */
+ 0x489ec2a4, /* 748 */
+ 0x48a70a91, /* 749 */
+ 0x48af509b, /* 750 */
+ 0x48b794c4, /* 751 */
+ 0x48bfd70c, /* 752 */
+ 0x48c81774, /* 753 */
+ 0x48d055fe, /* 754 */
+ 0x48d892aa, /* 755 */
+ 0x48e0cd7a, /* 756 */
+ 0x48e9066e, /* 757 */
+ 0x48f13d88, /* 758 */
+ 0x48f972c9, /* 759 */
+ 0x4901a632, /* 760 */
+ 0x4909d7c3, /* 761 */
+ 0x4912077e, /* 762 */
+ 0x491a3564, /* 763 */
+ 0x49226175, /* 764 */
+ 0x492a8bb4, /* 765 */
+ 0x4932b420, /* 766 */
+ 0x493adabc, /* 767 */
+ 0x4942ff87, /* 768 */
+ 0x494b2283, /* 769 */
+ 0x495343b1, /* 770 */
+ 0x495b6312, /* 771 */
+ 0x496380a7, /* 772 */
+ 0x496b9c71, /* 773 */
+ 0x4973b670, /* 774 */
+ 0x497bcea7, /* 775 */
+ 0x4983e515, /* 776 */
+ 0x498bf9bc, /* 777 */
+ 0x49940c9e, /* 778 */
+ 0x499c1db9, /* 779 */
+ 0x49a42d11, /* 780 */
+ 0x49ac3aa5, /* 781 */
+ 0x49b44677, /* 782 */
+ 0x49bc5088, /* 783 */
+ 0x49c458d8, /* 784 */
+ 0x49cc5f69, /* 785 */
+ 0x49d4643c, /* 786 */
+ 0x49dc6750, /* 787 */
+ 0x49e468a9, /* 788 */
+ 0x49ec6845, /* 789 */
+ 0x49f46627, /* 790 */
+ 0x49fc624f, /* 791 */
+ 0x4a045cbe, /* 792 */
+ 0x4a0c5575, /* 793 */
+ 0x4a144c76, /* 794 */
+ 0x4a1c41c0, /* 795 */
+ 0x4a243555, /* 796 */
+ 0x4a2c2735, /* 797 */
+ 0x4a341763, /* 798 */
+ 0x4a3c05de, /* 799 */
+ 0x4a43f2a7, /* 800 */
+ 0x4a4bddc0, /* 801 */
+ 0x4a53c729, /* 802 */
+ 0x4a5baee3, /* 803 */
+ 0x4a6394ef, /* 804 */
+ 0x4a6b794f, /* 805 */
+ 0x4a735c02, /* 806 */
+ 0x4a7b3d09, /* 807 */
+ 0x4a831c67, /* 808 */
+ 0x4a8afa1b, /* 809 */
+ 0x4a92d626, /* 810 */
+ 0x4a9ab089, /* 811 */
+ 0x4aa28946, /* 812 */
+ 0x4aaa605d, /* 813 */
+ 0x4ab235ce, /* 814 */
+ 0x4aba099b, /* 815 */
+ 0x4ac1dbc5, /* 816 */
+ 0x4ac9ac4c, /* 817 */
+ 0x4ad17b31, /* 818 */
+ 0x4ad94876, /* 819 */
+ 0x4ae1141a, /* 820 */
+ 0x4ae8de1f, /* 821 */
+ 0x4af0a686, /* 822 */
+ 0x4af86d50, /* 823 */
+ 0x4b00327d, /* 824 */
+ 0x4b07f60d, /* 825 */
+ 0x4b0fb803, /* 826 */
+ 0x4b17785f, /* 827 */
+ 0x4b1f3722, /* 828 */
+ 0x4b26f44b, /* 829 */
+ 0x4b2eafde, /* 830 */
+ 0x4b3669d9, /* 831 */
+ 0x4b3e223e, /* 832 */
+ 0x4b45d90e, /* 833 */
+ 0x4b4d8e4a, /* 834 */
+ 0x4b5541f2, /* 835 */
+ 0x4b5cf407, /* 836 */
+ 0x4b64a48a, /* 837 */
+ 0x4b6c537c, /* 838 */
+ 0x4b7400dd, /* 839 */
+ 0x4b7bacaf, /* 840 */
+ 0x4b8356f2, /* 841 */
+ 0x4b8affa7, /* 842 */
+ 0x4b92a6ce, /* 843 */
+ 0x4b9a4c69, /* 844 */
+ 0x4ba1f079, /* 845 */
+ 0x4ba992fd, /* 846 */
+ 0x4bb133f8, /* 847 */
+ 0x4bb8d369, /* 848 */
+ 0x4bc07151, /* 849 */
+ 0x4bc80db2, /* 850 */
+ 0x4bcfa88c, /* 851 */
+ 0x4bd741df, /* 852 */
+ 0x4bded9ad, /* 853 */
+ 0x4be66ff6, /* 854 */
+ 0x4bee04bb, /* 855 */
+ 0x4bf597fc, /* 856 */
+ 0x4bfd29bc, /* 857 */
+ 0x4c04b9f9, /* 858 */
+ 0x4c0c48b6, /* 859 */
+ 0x4c13d5f2, /* 860 */
+ 0x4c1b61af, /* 861 */
+ 0x4c22ebed, /* 862 */
+ 0x4c2a74ad, /* 863 */
+ 0x4c31fbf0, /* 864 */
+ 0x4c3981b6, /* 865 */
+ 0x4c410600, /* 866 */
+ 0x4c4888d0, /* 867 */
+ 0x4c500a25, /* 868 */
+ 0x4c578a00, /* 869 */
+ 0x4c5f0862, /* 870 */
+ 0x4c66854c, /* 871 */
+ 0x4c6e00bf, /* 872 */
+ 0x4c757abb, /* 873 */
+ 0x4c7cf341, /* 874 */
+ 0x4c846a52, /* 875 */
+ 0x4c8bdfee, /* 876 */
+ 0x4c935416, /* 877 */
+ 0x4c9ac6cb, /* 878 */
+ 0x4ca2380e, /* 879 */
+ 0x4ca9a7de, /* 880 */
+ 0x4cb1163e, /* 881 */
+ 0x4cb8832d, /* 882 */
+ 0x4cbfeead, /* 883 */
+ 0x4cc758bd, /* 884 */
+ 0x4ccec15f, /* 885 */
+ 0x4cd62894, /* 886 */
+ 0x4cdd8e5c, /* 887 */
+ 0x4ce4f2b7, /* 888 */
+ 0x4cec55a7, /* 889 */
+ 0x4cf3b72c, /* 890 */
+ 0x4cfb1747, /* 891 */
+ 0x4d0275f8, /* 892 */
+ 0x4d09d340, /* 893 */
+ 0x4d112f21, /* 894 */
+ 0x4d188999, /* 895 */
+ 0x4d1fe2ab, /* 896 */
+ 0x4d273a57, /* 897 */
+ 0x4d2e909d, /* 898 */
+ 0x4d35e57f, /* 899 */
+ 0x4d3d38fc, /* 900 */
+ 0x4d448b16, /* 901 */
+ 0x4d4bdbcd, /* 902 */
+ 0x4d532b21, /* 903 */
+ 0x4d5a7914, /* 904 */
+ 0x4d61c5a7, /* 905 */
+ 0x4d6910d9, /* 906 */
+ 0x4d705aab, /* 907 */
+ 0x4d77a31e, /* 908 */
+ 0x4d7eea34, /* 909 */
+ 0x4d862feb, /* 910 */
+ 0x4d8d7445, /* 911 */
+ 0x4d94b743, /* 912 */
+ 0x4d9bf8e6, /* 913 */
+ 0x4da3392d, /* 914 */
+ 0x4daa7819, /* 915 */
+ 0x4db1b5ac, /* 916 */
+ 0x4db8f1e6, /* 917 */
+ 0x4dc02cc7, /* 918 */
+ 0x4dc76650, /* 919 */
+ 0x4dce9e81, /* 920 */
+ 0x4dd5d55c, /* 921 */
+ 0x4ddd0ae1, /* 922 */
+ 0x4de43f10, /* 923 */
+ 0x4deb71eb, /* 924 */
+ 0x4df2a371, /* 925 */
+ 0x4df9d3a3, /* 926 */
+ 0x4e010283, /* 927 */
+ 0x4e083010, /* 928 */
+ 0x4e0f5c4b, /* 929 */
+ 0x4e168735, /* 930 */
+ 0x4e1db0cf, /* 931 */
+ 0x4e24d918, /* 932 */
+ 0x4e2c0012, /* 933 */
+ 0x4e3325bd, /* 934 */
+ 0x4e3a4a1a, /* 935 */
+ 0x4e416d2a, /* 936 */
+ 0x4e488eec, /* 937 */
+ 0x4e4faf62, /* 938 */
+ 0x4e56ce8c, /* 939 */
+ 0x4e5dec6b, /* 940 */
+ 0x4e6508ff, /* 941 */
+ 0x4e6c2449, /* 942 */
+ 0x4e733e4a, /* 943 */
+ 0x4e7a5702, /* 944 */
+ 0x4e816e71, /* 945 */
+ 0x4e888498, /* 946 */
+ 0x4e8f9979, /* 947 */
+ 0x4e96ad13, /* 948 */
+ 0x4e9dbf67, /* 949 */
+ 0x4ea4d075, /* 950 */
+ 0x4eabe03e, /* 951 */
+ 0x4eb2eec4, /* 952 */
+ 0x4eb9fc05, /* 953 */
+ 0x4ec10803, /* 954 */
+ 0x4ec812bf, /* 955 */
+ 0x4ecf1c39, /* 956 */
+ 0x4ed62471, /* 957 */
+ 0x4edd2b68, /* 958 */
+ 0x4ee4311f, /* 959 */
+ 0x4eeb3596, /* 960 */
+ 0x4ef238cd, /* 961 */
+ 0x4ef93ac6, /* 962 */
+ 0x4f003b81, /* 963 */
+ 0x4f073afe, /* 964 */
+ 0x4f0e393f, /* 965 */
+ 0x4f153642, /* 966 */
+ 0x4f1c320a, /* 967 */
+ 0x4f232c96, /* 968 */
+ 0x4f2a25e8, /* 969 */
+ 0x4f311dff, /* 970 */
+ 0x4f3814dc, /* 971 */
+ 0x4f3f0a80, /* 972 */
+ 0x4f45feeb, /* 973 */
+ 0x4f4cf21f, /* 974 */
+ 0x4f53e41a, /* 975 */
+ 0x4f5ad4de, /* 976 */
+ 0x4f61c46c, /* 977 */
+ 0x4f68b2c4, /* 978 */
+ 0x4f6f9fe6, /* 979 */
+ 0x4f768bd3, /* 980 */
+ 0x4f7d768c, /* 981 */
+ 0x4f846011, /* 982 */
+ 0x4f8b4862, /* 983 */
+ 0x4f922f81, /* 984 */
+ 0x4f99156d, /* 985 */
+ 0x4f9ffa27, /* 986 */
+ 0x4fa6ddb0, /* 987 */
+ 0x4fadc008, /* 988 */
+ 0x4fb4a12f, /* 989 */
+ 0x4fbb8127, /* 990 */
+ 0x4fc25ff0, /* 991 */
+ 0x4fc93d8a, /* 992 */
+ 0x4fd019f5, /* 993 */
+ 0x4fd6f533, /* 994 */
+ 0x4fddcf43, /* 995 */
+ 0x4fe4a827, /* 996 */
+ 0x4feb7fde, /* 997 */
+ 0x4ff2566a, /* 998 */
+ 0x4ff92bca, /* 999 */
+ 0x50000000, /* 1000 */
+ 0x5006d30b, /* 1001 */
+ 0x500da4ed, /* 1002 */
+ 0x501475a5, /* 1003 */
+ 0x501b4535, /* 1004 */
+ 0x5022139c, /* 1005 */
+ 0x5028e0dc, /* 1006 */
+ 0x502facf4, /* 1007 */
+ 0x503677e5, /* 1008 */
+ 0x503d41b0, /* 1009 */
+ 0x50440a55, /* 1010 */
+ 0x504ad1d5, /* 1011 */
+ 0x50519830, /* 1012 */
+ 0x50585d67, /* 1013 */
+ 0x505f217a, /* 1014 */
+ 0x5065e469, /* 1015 */
+ 0x506ca635, /* 1016 */
+ 0x507366df, /* 1017 */
+ 0x507a2667, /* 1018 */
+ 0x5080e4cd, /* 1019 */
+ 0x5087a212, /* 1020 */
+ 0x508e5e37, /* 1021 */
+ 0x5095193c, /* 1022 */
+ 0x509bd320, /* 1023 */
+ 0x50a28be6, /* 1024 */
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/aacdec/iquant_table.h b/media/libstagefright/codecs/aacdec/iquant_table.h
new file mode 100644
index 0000000..dadc3d0
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/iquant_table.h
@@ -0,0 +1,85 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: iquant_table.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for iquant_table.c, which contains a table used with
+ esc_iquant.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef IQUANT_TABLE_H
+#define IQUANT_TABLE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+extern const UInt32 inverseQuantTable[];
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/long_term_prediction.cpp b/media/libstagefright/codecs/aacdec/long_term_prediction.cpp
new file mode 100644
index 0000000..69e4c46
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/long_term_prediction.cpp
@@ -0,0 +1,648 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: long_term_prediction.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Made changes based on comments and experiment results.
+
+ Description: Passed in buffer sizes based on review comments and prototype
+ agreements.
+
+ Description: 1. Passed in "weight_index" instead of "weight".
+ 2. Added weight table.
+
+ Description: 1. Removed some passed in buffer size variables since they are
+ not used for long window.
+ 2. Modified comments format.
+
+ Description:
+ Modified casting to ensure proper operations for different platforms
+
+ Description:
+ Implemented circular buffer techniques, which save 4096 memmoves per
+ frame.
+
+ Description:
+ Implemented some optimizations found during the code review of this
+ module. The optimizations related to the rules on the range of
+ ltp_buffer_index and num_samples, which allows for a simpler
+ code construct to be used in the processing of the predicted samples.
+
+ Description:
+ Add max calculation on the filter implementation, this to eliminate
+ function buffer_adaptation() on the time to frequency transformation.
+ Function interface changed. It now return the amount of shifting needed
+ to garb only the top 16 MSB.
+
+ Description:
+ Replace clearing memory with for-loop with pvmemset function
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ win_seq = type of window sequence (WINDOW_SEQUENCE).
+
+ weight_index = index (Int) of LTP coefficient table for all windows in
+ current frame.
+
+ delay = buffer (Int) containing delays for each window.
+
+ buffer = history buffer (Int16) containing the reconstructed time domain
+ signals of previous frames.
+
+ buffer_offset = value (Int) that indicates the location of the first
+ element in the LTP circular buffer. (Either 0 or 1024)
+
+ time_quant = filterbank buffer (Int32) This buffer is used by the
+ filterbank, but it's first 1024 elements are equivalent
+ to the last 1024 elements in the conventionally
+ implemented LTP buffer. Using this buffer directly avoids
+ costly duplication of memory.
+
+ predicted_samples = buffer (Int32) with length of 2048 to hold
+ predicted time domain signals.
+
+ buffer_index = index into buffer where the first sample of data from
+ the frame (t-2) (two frames ago) resides. (Int)
+
+ frame_length = length of one frame, type of Int.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ Amount of shifting needed to grab the top 16 MSB from teh predicted buffer
+
+ Pointers and Buffers Modified:
+ predicted_samples contents are the newly calculated predicted time
+ domain signals
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Long term prediction (LTP) is used to reduce the redundancy of a signal
+ between successive coding frames. This function performs prediction by
+ applying 1-tap IIR filtering to calculate the predicted time domain
+ signals of current frame from previous reconstructed frames stored in
+ time domain history buffer.
+
+ The equation used for IIR filter is as following.
+
+ y(n) = weight * x(n - delay)
+
+ where y(n) ----- predicted time domain signals
+ x(n) ----- reconstructed time domain signals
+ weight ----- LTP coefficient
+ delay ----- optimal delay from 0 to 2047
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3: Audio
+ Subpart 4.6.6 Long Term Prediction (LTP)
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by Nokia in the course
+ of development of the MPEG-2 AAC/MPEG-4 Audio standard ISO/IEC13818-7,
+ 14496-1, 2 and 3. This software module is an implementation of a part
+ of one or more MPEG-2 AAC/MPEG-4 Audio tools as specified by the MPEG-2
+ aac/MPEG-4 Audio standard. ISO/IEC gives users of the MPEG-2aac/MPEG-4
+ Audio standards free license to this software module or modifications
+ thereof for use in hardware or software products claiming conformance
+ to the MPEG-2 aac/MPEG-4 Audio standards. Those intending to use this
+ software module in hardware or software products are advised that this
+ use may infringe existing patents. The original developer of this
+ software module, 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-2
+ aac/MPEG-4 Audio conforming products. The original developer retains
+ full right to use the code for the developer's own purpose, assign or
+ donate the code to a third party and to inhibit third party from using
+ the code for non MPEG-2 aac/MPEG-4 Audio conforming products. This
+ copyright notice must be included in all copies or derivative works.
+ Copyright (c)1997.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ pPredicted_samples = &predicted_samples[0];
+
+ weight = codebook[weight_index];
+
+ IF (win_seq != EIGHT_SHORT_SEQUENCE)
+ THEN
+
+ block_length = frame_length << 1;
+
+ lag = delay[0];
+
+ j = block_length - lag;
+
+ IF (lag < frame_length)
+ THEN
+
+ num_samples = frame_length + lag;
+
+ ELSE
+
+ num_samples = block_length;
+
+ ENDIF
+
+ pBuffer = &buffer[j];
+
+ FOR (i = num_samples; i>0; i--)
+
+ *pPredicted_samples = weight * (*pBuffer);
+ pPredicted_samples = pPredicted_samples + 1;
+ pBuffer = pBuffer + 1;
+
+ ENDFOR
+
+ FOR (i = block_length - num_samples; i>0; i--)
+
+ *pPredicted_samples = 0;
+ pPredicted_samples = pPredicted_samples + 1;
+
+ ENDFOR
+
+ ELSE
+
+ FOR (wnd = 0; wnd < short_window_num; wnd++)
+
+ IF (win_prediction_used[wnd] != FALSE)
+ THEN
+
+ delay[wnd] = delay[0] + ltp_short_lag[wnd];
+
+ lag = delay[wnd];
+
+ j = wnd*short_block_length - lag;
+
+ IF (lag < short_frame_length)
+ THEN
+
+ num_samples = short_frame_length + lag;
+
+ ELSE
+
+ num_samples = short_block_length;
+
+ ENDIF
+
+ pBuffer = &buffer[j];
+
+ FOR (i = num_samples; i>0; i--)
+
+ *pPredicted_samples = weight * (*pBuffer);
+ pPredicted_samples = pPredicted_samples + 1;
+ pBuffer = pBuffer + 1;
+
+ ENDFOR
+
+ FOR (i = short_block_length - num_samples; i>0; i--)
+
+ *pPredicted_samples = 0;
+ pPredicted_samples = pPredicted_samples + 1;
+
+ ENDFOR
+
+ ELSE
+
+ CALL pv_memset(
+ pPredicted_samples,
+ 0,
+ sizeof(*pPredicted_samples)*short_block_length);
+ MODIFYING (predicted_samples[]);
+
+ pPredicted_samples = pPredicted_samples + short_block_length;
+
+ ENDIF [ IF (win_prediction_used[wnd] != FALSE) ]
+
+ ENDFOR [ FOR (wnd=0; wnd<short_window_num; wnd++) ]
+
+ ENDIF [ IF (win_seq != EIGHT_SHORT_SEQUENCE) ]
+
+ RETURN
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_window_sequence.h"
+#include "ltp_common_internal.h"
+#include "long_term_prediction.h"
+#include "aac_mem_funcs.h"
+#include "pv_normalize.h"
+#include "window_block_fxp.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+/* Purpose: Codebook for LTP weight coefficients. Stored in Q15 format */
+const UInt codebook[CODESIZE] =
+{
+ 18705, /* 0 */
+ 22827, /* 1 */
+ 26641, /* 2 */
+ 29862, /* 3 */
+ 32273, /* 4 */
+ 34993, /* 5 */
+ 39145, /* 6 */
+ 44877 /* 7 */
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Int long_term_prediction(
+ WINDOW_SEQUENCE win_seq,
+ const Int weight_index,
+ const Int delay[],
+ const Int16 buffer[],
+ const Int buffer_offset,
+ const Int32 time_quant[],
+ Int32 predicted_samples[], /* Q15 */
+ const Int frame_length)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ /*
+ * Window index
+ *
+ * Int wnd;
+ *
+ * will be enabled when short window information is available.
+ */
+
+ /* Pointer to time domain history buffer */
+
+ const Int16 *pBuffer;
+
+ const Int32 *pTimeQuant = time_quant;
+
+ /* Pointer to array containing predicted samples */
+ Int32 *pPredicted_samples;
+
+ Int32 test;
+ Int32 datum;
+
+ /* IIR coefficient with Q15 format */
+ UInt weight;
+
+ /* Length of one block (two frames) */
+ Int block_length;
+
+ Int shift;
+ Int k;
+ Int ltp_buffer_index;
+ Int jump_point;
+ Int lag;
+ Int num_samples;
+
+ Int32 max = 0;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* Initialize pointers */
+ pPredicted_samples = &predicted_samples[0];
+
+ weight = codebook[weight_index];
+
+ /****************************************/
+ /* LTP decoding process for long window */
+ /****************************************/
+
+ if (win_seq != EIGHT_SHORT_SEQUENCE)
+ {
+ /****************************************************/
+ /* Prediction based on previous time domain signals */
+ /****************************************************/
+ block_length = frame_length << 1;
+
+ /* Calculate time lag for 1-tap IIR filter */
+ lag = delay[0];
+
+ ltp_buffer_index = block_length - lag;
+
+ /* Calculate number of samples used in IIR filter */
+ if (lag < frame_length)
+ {
+ num_samples = frame_length + lag;
+ }
+ else
+ {
+ num_samples = block_length;
+ }
+
+
+ /*
+ * Calculate the predicted time domain signals from the
+ * reconstructed time domain signals of previous frames.
+ */
+
+ /* The data is stored in TWO buffers, either as...
+ *
+ * [ t == 0 ]
+ *
+ * [ t == -1 ][ t == -2 ]
+ *
+ * OR...
+ * [ t == 0 ]
+ *
+ * [ t == -2 ][ t == -1 ]
+ *
+ *
+ *
+ * In the first case, all of the buffers are non-contiguous,
+ * and each must be handled separately. Code for this first case
+ * will function correctly for both cases.
+ *
+ * In the second case, the buffers storing t == -2, and t == -1
+ * data are contiguous, and an optimization could take advantage
+ * of this, at the cost of an increase in code size for this function.
+ */
+
+ /* Decrement block_length by num_samples. This is important
+ * for the loop at the end of the "ACCESS DATA IN THE LTP BUFFERS"
+ * section that sets all remaining samples in the block to zero.
+ */
+
+ block_length -= num_samples;
+
+
+
+
+
+
+ /*
+ ************************************ ACCESS DATA IN THE LTP BUFFERS
+ */
+
+ /*
+ * This section of the code handles the t == -2
+ * buffer, which corresponds to 0 <= ltp_buffer_index < 1024
+ *
+ * BUFFER t == -2
+ *
+ * [0][][][][][][][][][][][...][][][][][][][][][][][][1023]
+ *
+ */
+
+ jump_point = (frame_length - ltp_buffer_index);
+
+ if (jump_point > 0)
+ {
+ pBuffer = &(buffer[ltp_buffer_index + buffer_offset]);
+
+ for (k = jump_point; k > 0; k--)
+ {
+ /* Q15 = Q15 * Q0 */
+ test = (Int32) weight * (*(pBuffer++));
+ *(pPredicted_samples++) = test;
+ max |= (test >> 31) ^ test;
+ }
+
+ num_samples -= jump_point;
+
+ ltp_buffer_index += jump_point;
+ }
+
+ /*
+ * This section of the code handles the t == -1
+ * buffer, which corresponds to 1024 <= ltp_buffer_index < 2048
+ *
+ * BUFFER t == -1
+ *
+ * [1024][][][][][][][][][][][...][][][][][][][][][][][][2047]
+ *
+ */
+
+ jump_point = 2 * frame_length - ltp_buffer_index;
+
+ pBuffer = &(buffer[ltp_buffer_index - buffer_offset]);
+
+ if (num_samples < jump_point)
+ {
+ jump_point = num_samples;
+ }
+
+ for (k = jump_point; k > 0; k--)
+ {
+ /* Q15 = Q15 * Q0 */
+ test = (Int32) weight * (*(pBuffer++));
+ *(pPredicted_samples++) = test;
+ max |= (test >> 31) ^ test;
+ }
+
+ num_samples -= jump_point;
+
+ ltp_buffer_index += jump_point;
+
+ /*
+ * This section of the code handles the t == 0
+ * buffer, which corresponds to 2048 <= ltp_buffer_index < 3072
+ *
+ * BUFFER t == 0
+ *
+ * [2048][][][][][][][][][][][...][][][][][][][][][][][][3071]
+ *
+ */
+ for (k = num_samples; k > 0; k--)
+ {
+
+ datum = *(pTimeQuant++) >> SCALING;
+
+ /*
+ * Limit the values in the 32-bit filterbank's buffer to
+ * 16-bit resolution.
+ *
+ * Value's greater than 32767 or less than -32768 are saturated
+ * to 32767 and -32768, respectively.
+ */
+
+ test = (Int32)datum * weight;
+ *(pPredicted_samples++) = test;
+ max |= (test >> 31) ^ test;
+
+ }
+
+ /* Set any remaining samples in the block to 0. */
+
+ pv_memset(
+ pPredicted_samples,
+ 0,
+ block_length*sizeof(*pPredicted_samples));
+
+ } /* if (win_seq != EIGHT_SHORT_SEQUENCE) */
+
+
+ /*****************************************/
+ /* LTP decoding process for short window */
+ /*****************************************/
+
+ /*
+ * For short window LTP, since there is no "ltp_short_lag"
+ * information being passed, the following code for short
+ * window LTP will be applied in the future when those
+ * information are available.
+ */
+
+ /*
+ *----------------------------------------------------------------------------
+ * else
+ * {
+ * for (wnd = 0; wnd < short_window_num; wnd++)
+ * {
+ * if (win_prediction_used[wnd] != FALSE)
+ * {
+ * delay[wnd] = delay[0] + ltp_short_lag[wnd];
+ *
+ * lag = delay[wnd];
+ *
+ * j = wnd*short_block_length - lag;
+ *
+ * if (lag < short_frame_length)
+ * {
+ * num_samples = short_frame_length + lag;
+ * }
+ * else
+ * {
+ * num_samples = short_block_length;
+ * }
+ *
+ * pBuffer = &buffer[j];
+ *
+ * for(i = num_samples; i>0; i--)
+ * {
+ * *(pPredicted_samples++) = weight * (*(pBuffer++));
+ * }
+ *
+ * for(i = short_block_length - num_samples; i>0; i--)
+ * {
+ * *(pPredicted_samples++) = 0;
+ * }
+ * }
+ * else
+ * {
+ * pv_memset(
+ * pPredicted_samples,
+ * 0,
+ * sizeof(*pPredicted_samples)*short_block_length);
+ *
+ * pPredicted_samples += short_block_length;
+ * }
+ * }
+ * }
+ *----------------------------------------------------------------------------
+ */
+
+ shift = 16 - pv_normalize(max);
+
+ if (shift < 0)
+ {
+ shift = 0;
+ }
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return (shift);
+} /* long_term_prediction */
+
+
+
+
diff --git a/media/libstagefright/codecs/aacdec/long_term_prediction.h b/media/libstagefright/codecs/aacdec/long_term_prediction.h
new file mode 100644
index 0000000..014934b
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/long_term_prediction.h
@@ -0,0 +1,122 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: long_term_prediction.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified prototype with array size passed in per review
+ comments.
+
+ Description: Changed prototype with "weight_index" instead of "weight".
+
+ Description: Removed some passed in buffer size variables since they are
+ not being used for long window.
+
+ Description: Temporarily define LTP_Q_FORMAT for current release.
+ Need to change function prototype and pass out Q_format
+ information later.
+
+ Description: Updated function prototype to reflect the usage of a
+ circular buffer by LTP.
+
+ Description: Updated function interface with new return type
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes function prototype declaration for long_term_prediction().
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef LONG_TERM_PREDICTION_H
+#define LONG_TERM_PREDICTION_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_window_sequence.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define LTP_Q_FORMAT (15)
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ Int long_term_prediction(
+ WINDOW_SEQUENCE win_seq,
+ const Int weight_index,
+ const Int delay[],
+ const Int16 buffer[],
+ const Int buffer_offset,
+ const Int32 time_quant[],
+ Int32 predicted_samples[], /* Q15 */
+ const Int frame_length);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/long_term_synthesis.cpp b/media/libstagefright/codecs/aacdec/long_term_synthesis.cpp
new file mode 100644
index 0000000..c361db1
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/long_term_synthesis.cpp
@@ -0,0 +1,1158 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: long_term_synthesis.c
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Made the following changes based on the review comments.
+ 1. Separated "shift_factor>=0" on line 395 to "shift_factor>0"
+ and "shift_factor=0" two cases.
+ 2. Added comments on line 393 to explain why factor 2 is being
+ used to calculate shift_factor.
+ 3. Added comments for short window implementation.
+ 4. Changed "*(pPredicted_spectral++) = *pPredicted_spectral>>2"
+ to "*(pPredicted++)>>=2" although they are the same.
+ 5. Changed pseudo code "X+=Y" to "X=X+Y".
+ 6. Fixed ending comment of "for" loop.
+ 7. Passed in the size of the array and deleted some of the
+ include files.
+
+ Description: Unroll the loops.
+
+ Description: Changed index "wnd" in previous line 584 with "wnd_offset"
+ and made other correspondent changes to the code.
+
+
+ Description: Based on Ken's suggestion, modified the function with the
+ passing-in Q format as scalefactor band basis in order to
+ simplify TNS block functions.
+
+ Description: Optimization.
+
+ Description: Made changes based on review comments.
+ 1. Changed misspellings.
+ 2. Changed win_sfb_top[] from two dimensional array to one
+ dimensional array and correspondently changed the code.
+ 3. Changed function prototype to remove some redundant
+ informations.
+ 4. Fixed the adjusting Q format part code.
+ 5. Fixed lines 825, 826 with correct updating pointers.
+
+ Description: Due to TNS and LTP Q format issue, added code to adjust
+ predicted_spectral() to maximum resolution before perform
+ long term synthesis.
+
+ Description: Modified based on review comments.
+
+ Description: Changed "max" data type from UInt to UInt32.
+
+ Description: Changed so that nothing is done for the case of "all zero"
+ data coming from the output of Trans4m_time_2_freq. Also, included more
+ efficient calculation of the abs(x). And, I updated the pseudocode.
+
+ Description: Use an auxiliary variable temp, to avoid using the same
+ pointer and a post-increment pointer in the same line. This may not
+ work with all compilers.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ win_seq = type of window sequence (WINDOW_SEQUENCE).
+ sfb_per_win = number of scalefactor bands for each window, 1024 for
+ long window, 128 for short window, type of Int.
+ win_sfb_top = buffer (Int16) containing the top coefficient per
+ scalefactor band for each window.
+ win_prediction_used = buffer (Int) containing the prediction flag
+ information for short windows. Each item in the
+ buffer toggles prediction on(1)/off(0) for each
+ window separately.
+ sfb_prediction_used = buffer (Int) containing the prediction flag
+ information for scalefactor band(sfb). Each item
+ toggle prediction on(1)/off(0) on each scalefactor
+ band of every window.
+ current_frame = channel buffer (Int32) containing the dequantized
+ spectral coefficients or errors of current frame.
+ q_format = buffer (Int) containing Q format for each scalefactor band of
+ input current_frame.
+ predicted_spectral = buffer (Int32) containing predicted spectral
+ components of current frame.
+ pred_q_format = Q format (Int) for predicted spectral components of
+ current frame.
+ coef_per_win = number of coefficients per window for short windows.
+ type of Int.
+ short_window_num = number of short windows, type of Int.
+ reconstruct_sfb_num = number of scalefactor bands used for reconstruction
+ for short windows, type of Int.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ current_frame contents are the dequantized spectrum with a prediction
+ vector added when prediction is turned on.
+
+ q_format contents are updated with the new Q format (Int) for each
+ scalefactor band of output current_frame buffer.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs long term synthesis using transmitted spectral
+ coeffients or errors and predicted spectral components.
+
+ Long term synthesis is part of long term prediction (LTP) which is used to
+ reduce the redundancy of a signal between successive coding frames. The
+ functionality of long term synthesis is to reconstruct the frequency domain
+ spectral by adding the predicted spectral components and the transmitted
+ spectral error when prediction is turned on.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3: Audio
+ Subpart 4.6.6 Long Term Prediction (LTP)
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by Nokia in the course
+ of development of the MPEG-2 AAC/MPEG-4 Audio standard ISO/IEC13818-7,
+ 14496-1, 2 and 3. This software module is an implementation of a part
+ of one or more MPEG-2 AAC/MPEG-4 Audio tools as specified by the MPEG-2
+ aac/MPEG-4 Audio standard. ISO/IEC gives users of the MPEG-2aac/MPEG-4
+ Audio standards free license to this software module or modifications
+ thereof for use in hardware or software products claiming conformance
+ to the MPEG-2 aac/MPEG-4 Audio standards. Those intending to use this
+ software module in hardware or software products are advised that this
+ use may infringe existing patents. The original developer of this
+ software module, 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-2
+ aac/MPEG-4 Audio conforming products. The original developer retains
+ full right to use the code for the developer's own purpose, assign or
+ donate the code to a third party and to inhibit third party from using
+ the code for non MPEG-2 aac/MPEG-4 Audio conforming products. This
+ copyright notice must be included in all copies or derivative works.
+ Copyright (c)1997.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ pPredicted_spectral = &predicted_spectral[0];
+ pPredicted_spectral_start = pPredicted_spectral;
+ pSfb_prediction_used = &sfb_prediction_used[0];
+
+ IF (win_seq != EIGHT_SHORT_SEQUENCE)
+ THEN
+
+ sfb_offset = 0;
+
+ pWinSfbTop = &pWin_sfb_top[0];
+
+ pQ_format = &q_format[0];
+
+ FOR (i = sfb_per_frame; i>0; i--)
+
+ IF (*(pSfb_prediction_used++) != FALSE)
+ THEN
+
+ pPredicted_offset = pPredicted_spectral_start +
+ sfb_offset;
+ pCurrent_frame = &current_frame[sfb_offset];
+
+ quarter_sfb_width = (*pWinSfbTop - sfb_offset) >> 2;
+
+ max = 0;
+
+ pPredicted_spectral = pPredicted_offset;
+
+ FOR (j = (*pWinSfbTop - sfb_offset); j>0 ; j--)
+
+ tmpInt32 = *(pPredicted_spectral++);
+
+ IF (tmpInt32 < 0)
+ THEN
+
+ tmpInt32 = -tmpInt32;
+
+ ENDIF
+
+ max |= tmpInt32;
+
+ ENDFOR
+
+ tmpInt = 0;
+
+ IF (max != 0)
+ THEN
+
+ WHILE (max < 0x40000000L)
+
+ max <<= 1;
+ tmpInt++;
+
+ ENDWHILE
+
+ pPredicted_spectral = pPredicted_offset;
+
+ FOR (j = quarter_sfb_width; j>0 ; j--)
+
+ *(pPredicted_spectral++) <<= tmpInt;
+ *(pPredicted_spectral++) <<= tmpInt;
+ *(pPredicted_spectral++) <<= tmpInt;
+ *(pPredicted_spectral++) <<= tmpInt;
+
+ ENDFOR
+
+ adjusted_pred_q = pred_q_format + tmpInt;
+
+ pPredicted_spectral = pPredicted_offset;
+
+ shift_factor = *(pQ_format) - adjusted_pred_q;
+
+ IF ((shift_factor >= 0) && (shift_factor < 31))
+ THEN
+
+ shift_factor = shift_factor + 1;
+
+ FOR (j = quarter_sfb_width; j>0 ; j--)
+
+ *(pCurrent_frame++) =
+ (*pCurrent_frame>>shift_factor)
+ + (*(pPredicted_spectral++)>>1);
+ *(pCurrent_frame++) =
+ (*pCurrent_frame>>shift_factor)
+ + (*(pPredicted_spectral++)>>1);
+ *(pCurrent_frame++) =
+ (*pCurrent_frame>>shift_factor)
+ + (*(pPredicted_spectral++)>>1);
+ *(pCurrent_frame++) =
+ (*pCurrent_frame>>shift_factor)
+ + (*(pPredicted_spectral++)>>1);
+
+ ENDFOR
+
+ *(pQ_format) = adjusted_pred_q - 1;
+
+ ELSEIF (shift_factor >= 31)
+ THEN
+
+ FOR (j = quarter_sfb_width; j>0 ; j--)
+
+ *(pCurrent_frame++) = *(pPredicted_spectral++);
+ *(pCurrent_frame++) = *(pPredicted_spectral++);
+ *(pCurrent_frame++) = *(pPredicted_spectral++);
+ *(pCurrent_frame++) = *(pPredicted_spectral++);
+
+ ENDFOR
+
+ *(pQ_format) = adjusted_pred_q;
+
+ ELSEIF ((shift_factor < 0) && (shift_factor > -31))
+ THEN
+
+ shift_factor = 1 - shift_factor;
+
+ FOR (j = quarter_sfb_width; j>0 ; j--)
+
+ *(pCurrent_frame++) = (*pCurrent_frame>>1) +
+ (*(pPredicted_spectral++)>>shift_factor);
+ *(pCurrent_frame++) = (*pCurrent_frame>>1) +
+ (*(pPredicted_spectral++)>>shift_factor);
+ *(pCurrent_frame++) = (*pCurrent_frame>>1) +
+ (*(pPredicted_spectral++)>>shift_factor);
+ *(pCurrent_frame++) = (*pCurrent_frame>>1) +
+ (*(pPredicted_spectral++)>>shift_factor);
+
+ ENDFOR
+
+ *(pQ_format) = *(pQ_format) - 1;
+
+ ENDIF
+
+ ENDIF
+
+ ENDIF [ IF (*(pSfb_prediction_used++) != FALSE) ]
+
+ sfb_offset = *pWinSfbTop;
+ pWinSfbTop = pWinSfbTop + 1;
+ pQ_format = pQ_format + 1;
+
+ ENDFOR [ FOR (i = sfb_per_frame; i>0; i--) ]
+
+ ELSE
+
+ pCurrent_frame_start = &current_frame[0];
+
+ pQ_format_start = &q_format[0];
+
+ num_sfb = sfb_per_win[0];
+
+ FOR (wnd=0; wnd<short_window_num; wnd++)
+
+ pWinSfbTop = &pWin_sfb_top[0];
+
+ pQ_format = pQ_format_start;
+
+ IF (win_prediction_used[wnd] != FALSE)
+ THEN
+
+ sfb_offset = 0;
+
+ FOR (i = reconstruct_sfb_num; i > 0; i--)
+
+ pPredicted_offset = pPredicted_spectral_start +
+ sfb_offset;
+ pCurrent_frame = pCurrent_frame_start + sfb_offset;
+
+ quarter_sfb_width = (*pWinSfbTop - sfb_offset) >> 2;
+
+ max = 0;
+
+ pPredicted_spectral = pPredicted_offset;
+
+ FOR (j = (*pWinSfbTop - sfb_offset); j>0 ; j--)
+
+ tmpInt32 = *(pPredicted_spectral++);
+
+ IF (tmpInt32 < 0)
+ THEN
+
+ tmpInt32 = -tmpInt32;
+
+ ENDIF
+
+ max |= tmpInt32;
+
+ ENDFOR
+
+ tmpInt = 0;
+
+ IF (max != 0)
+ THEN
+
+ WHILE (max < 0x40000000L)
+
+ max <<= 1;
+ tmpInt++;
+
+ ENDWHILE
+
+
+ pPredicted_spectral = pPredicted_offset;
+
+ FOR (j = quarter_sfb_width; j>0 ; j--)
+
+ *(pPredicted_spectral++) <<= tmpInt;
+ *(pPredicted_spectral++) <<= tmpInt;
+ *(pPredicted_spectral++) <<= tmpInt;
+ *(pPredicted_spectral++) <<= tmpInt;
+
+ ENDFOR
+
+ adjusted_pred_q = pred_q_format + tmpInt;
+
+ pPredicted_spectral = pPredicted_offset;
+
+ shift_factor = *(pQ_format) - adjusted_pred_q;
+
+ IF ((shift_factor >= 0) && (shift_factor < 31))
+ THEN
+
+ shift_factor = shift_factor + 1;
+
+ FOR (j = quarter_sfb_width; j>0 ; j--)
+
+ *(pCurrent_frame++) =
+ (*pCurrent_frame>>shift_factor) +
+ (*(pPredicted_spectral++)>>1);
+ *(pCurrent_frame++) =
+ (*pCurrent_frame>>shift_factor) +
+ (*(pPredicted_spectral++)>>1);
+ *(pCurrent_frame++) =
+ (*pCurrent_frame>>shift_factor) +
+ (*(pPredicted_spectral++)>>1);
+ *(pCurrent_frame++) =
+ (*pCurrent_frame>>shift_factor) +
+ (*(pPredicted_spectral++)>>1);
+
+ ENDFOR
+
+ *(pQ_format) = adjusted_pred_q - 1;
+
+ ELSEIF (shift_factor >= 31)
+ THEN
+
+ FOR (j = quarter_sfb_width; j>0 ; j--)
+
+ *(pCurrent_frame++) = *(pPredicted_spectral++);
+ *(pCurrent_frame++) = *(pPredicted_spectral++);
+ *(pCurrent_frame++) = *(pPredicted_spectral++);
+ *(pCurrent_frame++) = *(pPredicted_spectral++);
+
+ ENDFOR
+
+ *(pQ_format) = adjusted_pred_q;
+
+ ELSEIF ((shift_factor < 0) && (shift_factor > -31))
+ THEN
+
+ shift_factor = 1 - shift_factor;
+
+ FOR (j = quarter_sfb_width; j>0 ; j--)
+
+ *(pCurrent_frame++) = (*pCurrent_frame>>1) +
+ (*(pPredicted_spectral++)>>shift_factor);
+ *(pCurrent_frame++) = (*pCurrent_frame>>1) +
+ (*(pPredicted_spectral++)>>shift_factor);
+ *(pCurrent_frame++) = (*pCurrent_frame>>1) +
+ (*(pPredicted_spectral++)>>shift_factor);
+ *(pCurrent_frame++) = (*pCurrent_frame>>1) +
+ (*(pPredicted_spectral++)>>shift_factor);
+
+ ENDFOR
+
+ *(pQ_format) = *(pQ_format) - 1;
+
+ ENDIF
+
+ ENDIF
+
+ sfb_offset = *pWinSfbTop;
+ pWinSfbTop = pWinSfbTop + 1;
+ pQ_format = pQ_format + 1;
+
+ ENDFOR [ FOR (i = reconstruct_sfb_num; i > 0; i--) ]
+
+ ENDIF [ IF (win_prediction_used[wnd] != FALSE) ]
+
+ pPredicted_spectral_start = pPredicted_spectral_start + num_sfb;
+ pCurrent_frame_start = pCurrent_frame_start + num_sfb;
+ wnd_offset = wnd_offset + num_sfb;
+ pQ_format_start = pQ_format_start + num_sfb;
+
+ ENDFOR [ FOR (wnd=0; wnd<short_window_num; wnd++) ]
+
+ ENDIF [ IF (win_seq != EIGHT_SHORT_SEQUENCE) ]
+
+ RETURN
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_window_sequence.h"
+#include "long_term_synthesis.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void long_term_synthesis(
+ WINDOW_SEQUENCE win_seq,
+ Int sfb_per_win,
+ Int16 win_sfb_top[],
+ Int win_prediction_used[],
+ Int sfb_prediction_used[],
+ Int32 current_frame[],
+ Int q_format[], /* for each sfb */
+ Int32 predicted_spectral[],
+ Int pred_q_format, /* for predicted_spectral[] */
+ Int coef_per_win,
+ Int short_window_num,
+ Int reconstruct_sfb_num)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ /* Scalefactor band offset */
+ Int sfb_offset;
+
+ /* Window index */
+ Int wnd;
+
+ /* Pointer to array containing predicted samples */
+ Int32 *pPredicted_spectral;
+
+ /* Pointer to the beginning of array containing predicted samples */
+ Int32 *pPredicted_spectral_start;
+
+ Int32 *pPredicted_offset;
+
+ /* Pointer to array containing current spectral components for a channel*/
+ Int32 *pCurrent_frame;
+
+ /* Another pointer to array containing current spectral components */
+ Int32 *pCurrent_frame_start;
+
+ /* Pointer to prediction flag for each scalefactor band */
+ Int *pSfb_prediction_used;
+
+ /* Pointer to top coef per scalefactor band */
+ Int16 *pWinSfbTop;
+
+ /* Pointer to q_format array */
+ Int *pQ_format;
+ Int *pQ_format_start;
+ Int32 temp;
+
+ Int i;
+ Int j;
+
+ Int quarter_sfb_width;
+ Int num_sfb;
+ Int shift_factor;
+
+ UInt32 max;
+ Int32 tmpInt32;
+
+ Int tmpInt;
+ Int adjusted_pred_q;
+ Int pred_shift;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* Initialize pointers */
+ pPredicted_spectral = &predicted_spectral[0];
+ pPredicted_spectral_start = pPredicted_spectral;
+
+ /*
+ * NOTE:
+ * sfb_prediction_used[] start from 0 or 1 depending on nok_lt_decode.c;
+ * currently we agree to make it start from 0;
+ */
+ pSfb_prediction_used = &sfb_prediction_used[0];
+
+ /*********************************/
+ /* LTP synthesis for long window */
+ /*********************************/
+ if (win_seq != EIGHT_SHORT_SEQUENCE)
+ {
+
+ /*******************************************************/
+ /* Reconstruction of current frequency domain spectrum */
+ /*******************************************************/
+
+ /* Initialize scalefactor band offset */
+ sfb_offset = 0;
+
+ /*
+ * Reconstruction is processed on scalefactor band basis.
+ * 1. When prediction is turned on, all the predicted spectral
+ * components will be used for reconstruction.
+ * 2. When prediction is turned off, reconstruction is not
+ * needed. Spectral components of current frame will directly
+ * come from the transmitted data.
+ */
+ pWinSfbTop = &win_sfb_top[0];
+
+ pQ_format = &q_format[0];
+
+ for (i = sfb_per_win; i > 0; i--)
+ {
+ /* Check prediction flag for each scalefactor band. */
+ if (*(pSfb_prediction_used++) != FALSE)
+ {
+ /*
+ * Prediction is on. Do reconstruction routine.
+ * Reconstruct spectral component of current
+ * frame by adding the predicted spectral
+ * components and the quantized prediction
+ * errors that reconstructed from transmitted
+ * data when prediction is turned on.
+ */
+
+ /* Set pointers to the offset of scalefactor bands */
+ pPredicted_offset = pPredicted_spectral_start +
+ sfb_offset;
+ pCurrent_frame = &current_frame[sfb_offset];
+
+ /*
+ * (*pWinSfbTop - sfb_offset) is number of coefficients
+ * of the scalefactor band.
+ * ">>2" is used to set up for later unrolling the loop.
+ */
+ quarter_sfb_width = (*pWinSfbTop - sfb_offset) >> 2;
+
+ /*
+ * Adjust pred_q_format and predicted_spectral() to
+ * maximum resolution.
+ */
+ max = 0;
+
+ pPredicted_spectral = pPredicted_offset;
+
+ /* Find the maximum absolute value */
+ for (j = (*pWinSfbTop - sfb_offset); j > 0 ; j--)
+ {
+ tmpInt32 = *(pPredicted_spectral++);
+
+ /*
+ * Note: overflow is protected here even though
+ * tmpInt32 = 0x80000000 is very rare case.
+ *
+ * if (tmpInt32 == LONG_MIN)
+ * {
+ * tmpInt32 = LONG_MAX;
+ * }
+ * if (tmpInt32 < 0)
+ * {
+ * tmpInt32 = -tmpInt32;
+ * }
+ */
+
+ max |= tmpInt32 ^(tmpInt32 >> 31);
+ }
+
+ /*
+ * IF the LTP data is all zeros
+ * (max == 0) - do nothing for this sfb.
+ */
+
+ if (max != 0)
+ {
+ /* Find the number of bits to reach the max resolution */
+ tmpInt = 0;
+
+ while (max < 0x40000000L)
+ {
+ max <<= 1;
+ tmpInt++;
+ }
+
+ /*
+ * The following codes are combinded into shift factor
+ * adjusting and reconstruction section.
+ *
+ * pPredicted_spectral = pPredicted_offset;
+ * for(j = quarter_sfb_width; j>0 ; j--)
+ * {
+ * *(pPredicted_spectral++) <<= tmpInt;
+ * *(pPredicted_spectral++) <<= tmpInt;
+ * *(pPredicted_spectral++) <<= tmpInt;
+ * *(pPredicted_spectral++) <<= tmpInt;
+ * }
+ *
+ */
+
+ /* Adjust Q format for predicted_spectral() */
+ adjusted_pred_q = pred_q_format + tmpInt;
+
+ /*
+ * Adjust Q format to prevent overflow that may occur during
+ * frequency domain reconstruction.
+ *
+ */
+ pPredicted_spectral = pPredicted_offset;
+
+ shift_factor = *(pQ_format) - adjusted_pred_q;
+
+ if ((shift_factor >= 0) && (shift_factor < 31))
+ {
+ shift_factor = shift_factor + 1;
+ pred_shift = tmpInt - 1;
+
+ if (pred_shift >= 0)
+ {
+ for (j = quarter_sfb_width; j > 0 ; j--)
+ {
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) << pred_shift);
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) << pred_shift);
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) << pred_shift);
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) << pred_shift);
+ }
+ }
+ else
+ {
+ for (j = quarter_sfb_width; j > 0 ; j--)
+ {
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) >> 1);
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) >> 1);
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) >> 1);
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) >> 1);
+ }
+ }
+
+ /* Updated new Q format for current scalefactor band */
+ *(pQ_format) = adjusted_pred_q - 1;
+ }
+ else if (shift_factor >= 31)
+ {
+ for (j = quarter_sfb_width; j > 0 ; j--)
+ {
+ *(pCurrent_frame++) =
+ *(pPredicted_spectral++) << tmpInt;
+ *(pCurrent_frame++) =
+ *(pPredicted_spectral++) << tmpInt;
+ *(pCurrent_frame++) =
+ *(pPredicted_spectral++) << tmpInt;
+ *(pCurrent_frame++) =
+ *(pPredicted_spectral++) << tmpInt;
+ }
+
+ /* Updated new Q format for current scalefactor band */
+ *(pQ_format) = adjusted_pred_q ;
+ }
+ else if ((shift_factor < 0) && (shift_factor > -31))
+ {
+ shift_factor = 1 - shift_factor;
+ pred_shift = tmpInt - shift_factor;
+
+ if (pred_shift >= 0)
+ {
+ for (j = quarter_sfb_width; j > 0 ; j--)
+ {
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) << pred_shift);
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) << pred_shift);
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) << pred_shift);
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) << pred_shift);
+ }
+ }
+ else
+ {
+ pred_shift = -pred_shift;
+
+ for (j = quarter_sfb_width; j > 0 ; j--)
+ {
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) >> pred_shift);
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) >> pred_shift);
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) >> pred_shift);
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) >> pred_shift);
+ }
+ }
+
+ /*
+ * Updated new Q format for current scalefactor band
+ *
+ * This is NOT a pointer decrement
+ */
+ (*pQ_format)--;
+ }
+
+ } /* if (max != 0) */
+
+ /*
+ * For case (shift_factor <= -31), *pCurrent_frame and
+ * *pQ_format do not need to be updated.
+ */
+
+ } /* if (*(pSfb_prediction_used++) != FALSE) */
+
+ /* Updated to next scalefactor band. */
+ sfb_offset = *(pWinSfbTop++);
+
+ /* Updated pointer to next scalefactor band's Q-format */
+ pQ_format++;
+
+ } /* for (i = sfb_per_frame; i>0; i--) */
+
+ } /* if (win_seq!=EIGHT_SHORT_SEQUENCE) */
+
+ /**********************************/
+ /* LTP synthesis for short window */
+ /**********************************/
+ else
+ {
+ /******************************************************/
+ /*Reconstruction of current frequency domain spectrum */
+ /******************************************************/
+ pCurrent_frame_start = &current_frame[0];
+
+ pQ_format_start = &q_format[0];
+
+ num_sfb = sfb_per_win;
+
+ /* Reconstruction is processed on window basis */
+ for (wnd = 0; wnd < short_window_num; wnd++)
+ {
+ pWinSfbTop = &win_sfb_top[0];
+
+ pQ_format = pQ_format_start;
+
+ /* Check if prediction flag is on for each window */
+ if (win_prediction_used[wnd] != FALSE)
+ {
+ /* Initialize scalefactor band offset */
+ sfb_offset = 0;
+
+ /*
+ * Reconstruction is processed on scalefactor band basis.
+ * 1. When prediction is turned on, all the predicted
+ * spectral components will be used for reconstruction.
+ * 2. When prediction is turned off, reconstruction is
+ * not needed. Spectral components of current frame
+ * will directly come from the transmitted data.
+ */
+
+ /*
+ * According to ISO/IEC 14496-3 pg.91
+ * Only the spectral components in first eight scalefactor
+ * bands are added to the quantized prediction error.
+ */
+ for (i = reconstruct_sfb_num; i > 0; i--)
+ {
+ /* Set pointer to the offset of scalefactor bands */
+ pPredicted_offset = pPredicted_spectral_start +
+ sfb_offset;
+ pCurrent_frame = pCurrent_frame_start + sfb_offset;
+
+ /*
+ * Prediction is on. Do reconstruction routine.
+ * Reconstruct spectral component of
+ * current frame by adding the predicted
+ * spectral components and the quantized
+ * prediction errors that reconstructed
+ * from transmitted data when prediction
+ * is turned on.
+ */
+
+ /*
+ * (*pWinSfbTop - sfb_offset) is number of coefficients
+ * of the scalefactor band.
+ * ">>2" is used to set up for later unrolling the loop.
+ */
+ quarter_sfb_width = (*pWinSfbTop - sfb_offset) >> 2;
+
+ /*
+ * Adjust pred_q_format and predicted_spectral() to
+ * maximum resolution.
+ */
+ max = 0;
+ pPredicted_spectral = pPredicted_offset;
+
+ /* Find the maximum absolute value */
+ for (j = (*pWinSfbTop - sfb_offset); j > 0 ; j--)
+ {
+ tmpInt32 = *(pPredicted_spectral++);
+
+
+ /*
+ * Note: overflow is protected here even though
+ * tmpInt32 = 0x80000000 is very rare case.
+ *
+ * if (tmpInt32 == LONG_MIN)
+ * {
+ * tmpInt32 = LONG_MAX;
+ * }
+ * if (tmpInt32 < 0)
+ * {
+ * tmpInt32 = -tmpInt32;
+ * }
+ */
+
+ max |= tmpInt32 ^(tmpInt32 >> 31);
+ }
+
+ if (max != 0)
+ {
+ /* Find the number of bits to reach
+ * the max resolution
+ */
+ tmpInt = 0;
+
+ while (max < 0x40000000L)
+ {
+ max <<= 1;
+ tmpInt++;
+ }
+ /*
+ * The following codes are combined into shift factor
+ * adjusting and reconstruction section.
+ *
+ * pPredicted_spectral = pPredicted_offset;
+ * for(j = quarter_sfb_width; j>0 ; j--)
+ * {
+ * *(pPredicted_spectral++) <<= tmpInt;
+ * *(pPredicted_spectral++) <<= tmpInt;
+ * *(pPredicted_spectral++) <<= tmpInt;
+ * *(pPredicted_spectral++) <<= tmpInt;
+ * }
+ *
+ */
+
+ /* Adjust Q format for predicted_spectral() */
+ adjusted_pred_q = pred_q_format + tmpInt;
+
+ /*
+ * Adjust Q format to prevent overflow that may occur
+ * during frequency domain reconstruction.
+ */
+ pPredicted_spectral = pPredicted_offset;
+
+ shift_factor = *(pQ_format) - adjusted_pred_q;
+
+ if ((shift_factor >= 0) && (shift_factor < 31))
+ {
+ shift_factor = shift_factor + 1;
+
+ pred_shift = tmpInt - 1;
+
+ if (pred_shift >= 0)
+ {
+ for (j = quarter_sfb_width; j > 0 ; j--)
+ {
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) << pred_shift);
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) << pred_shift);
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) << pred_shift);
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) << pred_shift);
+
+ }
+ }
+ else
+ {
+ for (j = quarter_sfb_width; j > 0 ; j--)
+ {
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) >> 1);
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) >> 1);
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) >> 1);
+ temp = *pCurrent_frame >> shift_factor;
+ *(pCurrent_frame++) = temp
+ + (*(pPredicted_spectral++) >> 1);
+ }
+ }
+
+ /* Updated new Q format for current scalefactor band*/
+ *(pQ_format) = adjusted_pred_q - 1;
+ }
+ else if (shift_factor >= 31)
+ {
+ for (j = quarter_sfb_width; j > 0 ; j--)
+ {
+ *(pCurrent_frame++) =
+ *(pPredicted_spectral++) << tmpInt;
+ *(pCurrent_frame++) =
+ *(pPredicted_spectral++) << tmpInt;
+ *(pCurrent_frame++) =
+ *(pPredicted_spectral++) << tmpInt;
+ *(pCurrent_frame++) =
+ *(pPredicted_spectral++) << tmpInt;
+ }
+
+ /* Updated new Q format for current scalefactor band*/
+ *(pQ_format) = adjusted_pred_q;
+ }
+ else if ((shift_factor < 0) && (shift_factor > -31))
+ {
+ shift_factor = 1 - shift_factor;
+
+ pred_shift = tmpInt - shift_factor;
+
+ if (pred_shift >= 0)
+ {
+ for (j = quarter_sfb_width; j > 0 ; j--)
+ {
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) << pred_shift);
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) << pred_shift);
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) << pred_shift);
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) << pred_shift);
+
+ }
+ }
+ else
+ {
+ pred_shift = -pred_shift;
+
+ for (j = quarter_sfb_width; j > 0 ; j--)
+ {
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) >> pred_shift);
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) >> pred_shift);
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) >> pred_shift);
+ temp = *pCurrent_frame >> 1;
+ *(pCurrent_frame++) = temp +
+ (*(pPredicted_spectral++) >> pred_shift);
+ }
+ }
+
+ /* Updated new Q format for current scalefactor band*/
+ *(pQ_format) = *(pQ_format) - 1;
+ }
+
+ /*
+ * For case (shift_factor <= -31), *pCurrent_frame and
+ * *pQ_format do not need to be updated.
+ */
+
+ } /* if (max != 0) */
+
+ /* Updated to next scalefactor band. */
+ sfb_offset = *(pWinSfbTop++);
+
+ /* Updated pointer to next scalefactor band's Q-format */
+ pQ_format++;
+
+ } /* for (i = reconstruct_sfb_num; i > 0; i--) */
+
+ } /* if (win_prediction_used[wnd] != FALSE) */
+
+ /* Updated to next window */
+ pPredicted_spectral_start += coef_per_win;
+ pCurrent_frame_start += coef_per_win;
+ pQ_format_start += num_sfb;
+
+ } /* for (wnd=0; wnd<short_window_num; wnd++) */
+
+ } /* else */
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+} /* long_term_synthesis */
+
+
diff --git a/media/libstagefright/codecs/aacdec/long_term_synthesis.h b/media/libstagefright/codecs/aacdec/long_term_synthesis.h
new file mode 100644
index 0000000..1195709
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/long_term_synthesis.h
@@ -0,0 +1,105 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: long_term_synthesis.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: 1. Changed protoype with array size passed in per review
+ comments.
+ 2. Moved #define NUM_RECONSTRUCTED_SFB to ltp_common_internal.h
+
+ Description: Modified prototype based on review comments for new version
+ long_term_synthesis.c.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes function prototype declaration for long_term_synthesis().
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef LONG_TERM_SYNTHESIS_H
+#define LONG_TERM_SYNTHESIS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_window_sequence.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+void long_term_synthesis(
+ WINDOW_SEQUENCE win_seq,
+ Int sfb_per_win,
+ Int16 win_sfb_top[],
+ Int win_prediction_used[],
+ Int sfb_prediction_used[],
+ Int32 current_frame[],
+ Int q_format[],
+ Int32 predicted_spectral[],
+ Int pred_q_format,
+ Int coef_per_win,
+ Int short_window_num,
+ Int reconstruct_sfb_num);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/lt_decode.cpp b/media/libstagefright/codecs/aacdec/lt_decode.cpp
new file mode 100644
index 0000000..e5f5f91
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/lt_decode.cpp
@@ -0,0 +1,507 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: lt_decode.c
+
+
+------------------------------------------------------------------------------
+
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: First round of optimizations.
+
+ Description: pInputStream is now the 2nd parameter to this function.
+
+ Description: Changed to work with MT's new get_ics_info.c function, which
+ only calls lt_decode if LTP is enabled. This removes one grab from the
+ bitstream and one "if" from this code. Also, changed setting of weight.
+ Now, rather than setting the actual weight, I only set the index into
+ a table in this function.
+
+ Description: Replace some instances of getbits to get9_n_lessbits
+ when the number of bits read is 9 or less and get1bits
+ when only 1 bit is read.
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ win_type Type of window (SHORT or LONG)
+ [WINDOW_TYPE]
+
+ max_sfb Maximum number of active scalefactor bands
+ [Int]
+
+ pLt_pred Pointer to structure containing information for
+ long-term prediction.
+ [LT_PRED_STATUS *]
+
+ pInputStream Pointer to structure containing bitstream
+ information.
+ [BITS *]
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ pLt_pred->weight_index - updated with index into weight table for LTP.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function decodes the bitstream elements for long term prediction
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by Nokia
+ in the course of development of the MPEG-2 AAC/MPEG-4 Audio standard
+ ISO/IEC13818-7, 14496-1, 2 and 3. This software module is an implementation
+ of a part of one or more MPEG-2 AAC/MPEG-4 Audio tools as specified by the
+ MPEG-2 aac/MPEG-4 Audio standard. ISO/IEC gives users of the
+ MPEG-2aac/MPEG-4 Audio standards free license to this software module or
+ modifications thereof for use in hardware or software products claiming
+ conformance to the MPEG-2 aac/MPEG-4 Audio standards. Those intending to
+ use this software module in hardware or software products are advised that
+ this use may infringe existing patents. The original developer of this
+ software module, 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-2 aac/MPEG-4
+ Audio conforming products. The original developer retains full right to use
+ the code for the developer's own purpose, assign or donate the code to a
+ third party and to inhibit third party from using the code for non
+ MPEG-2 aac/MPEG-4 Audio conforming products. This copyright notice
+ must be included in all copies or derivative works."
+ Copyright (c)1997.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ pDelay[0] = (Int) getbits(
+ LEN_LTP_LAG,
+ pInputStream);
+
+ temp_reg = (Int) getbits(
+ LEN_LTP_COEF,
+ pInputStream);
+
+ pLt_pred->weight = codebook[temp_reg];
+
+ last_band = max_sfb;
+
+ IF (win_type != EIGHT_SHORT_SEQUENCE)
+
+ IF (last_band > MAX_LT_PRED_LONG_SFB)
+
+ last_band = MAX_LT_PRED_LONG_SFB;
+
+ ENDIF
+
+ FOR (m = last_band; m > 0; m--)
+
+ *(pSfbPredictionUsed++) = (Int) getbits(
+ LEN_LTP_LONG_USED,
+ pInputStream);
+ ENDFOR
+
+ FOR (m = (max_sfb - last_band); m > 0; m--)
+
+ *(pSfbPredictionUsed++) = 0;
+
+ ENDFOR
+
+ ELSE
+
+ IF (last_band > MAX_LT_PRED_SHORT_SFB)
+
+ last_band = MAX_LT_PRED_SHORT_SFB;
+
+ ENDIF
+
+ prev_subblock = pDelay[0];
+
+ pWinPredictionUsed++;
+
+ pTempPtr = &pSfbPredictionUsed[0];
+
+ FOR (m = NUM_SHORT_WINDOWS; m > 0;)
+
+ m--;
+ temp_reg = (Int) getbits(
+ LEN_LTP_SHORT_USED,
+ pInputStream);
+
+ *(pWinPredictionUsed++) = temp_reg;
+
+ IF (temp_reg != FALSE)
+ {
+ *(pDelay++) = prev_subblock;
+
+ FOR (k = last_band; k > 0; k--)
+ {
+ *(pTempPtr++) = 1;
+ }
+ break;
+ ELSE
+ {
+ pDelay++;
+ pTempPtr += last_band;
+ }
+
+ ENDFOR (m = NUM_SHORT_WINDOWS; m > 0;)
+
+ prev_subblock += LTP_LAG_OFFSET;
+
+ FOR (; m > 0; m--)
+
+ temp_reg = (Int) getbits (
+ LEN_LTP_SHORT_USED,
+ pInputStream);
+
+ *(pWinPredictionUsed++) = temp_reg;
+
+ IF (temp_reg != FALSE)
+
+ temp_reg = (Int) getbits(
+ LEN_LTP_SHORT_LAG_PRESENT,
+ pInputStream);
+ IF (temp_reg != 0)
+
+ temp_reg = (Int) getbits(
+ LEN_LTP_SHORT_LAG,
+ pInputStream);
+
+ *(pDelay++) = prev_subblock - temp_reg;
+
+ ELSE
+
+ *(pDelay++) = prev_subblock - LTP_LAG_OFFSET;
+
+ ENDIF
+
+ FOR (k = last_band; k > 0; k--)
+ *(pTempPtr++) = 1;
+ ENDFOR
+
+ ELSE
+
+ pDelay++;
+ pTempPtr += last_band;
+
+ ENDIF
+
+ ENDFOR (; m > 0; m--)
+
+ ENDIF (win_type != EIGHT_SHORT_SEQUENCE)
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "lt_decode.h"
+#include "ltp_common_internal.h"
+#include "window_block_fxp.h"
+#include "e_window_sequence.h"
+#include "s_lt_pred_status.h"
+#include "s_bits.h"
+#include "ibstream.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void lt_decode(
+ const WINDOW_SEQUENCE win_type,
+ BITS *pInputStream,
+ const Int max_sfb,
+ LT_PRED_STATUS *pLt_pred)
+{
+ Int wnd_num;
+ Int k;
+ Int last_band;
+ Int prev_subblock;
+ Int prev_subblock_nonzero;
+ Int temp_reg;
+
+ Bool *pWinPredictionUsed = pLt_pred->win_prediction_used;
+ Bool *pSfbPredictionUsed = pLt_pred->sfb_prediction_used;
+ Int *pTempPtr;
+ Int *pDelay = pLt_pred->delay;
+
+ pDelay[0] = (Int) get17_n_lessbits(
+ LEN_LTP_LAG, /* 11 bits */
+ pInputStream);
+
+ pLt_pred->weight_index = (Int) get9_n_lessbits(
+ LEN_LTP_COEF, /* 3 bits */
+ pInputStream);
+
+ last_band = max_sfb;
+
+ if (win_type != EIGHT_SHORT_SEQUENCE)
+ {
+
+ /* last_band = min(MAX_LT_PRED_LONG_SFB, max_sfb) MAX_SCFAC_BANDS */
+ if (last_band > MAX_LT_PRED_LONG_SFB)
+ {
+ last_band = MAX_LT_PRED_LONG_SFB;
+ }
+
+ for (k = last_band; k > 0; k--)
+ {
+ *(pSfbPredictionUsed++) = (Int) get1bits(pInputStream);
+ }
+
+ /*
+ * This is not a call to memset, because
+ * (max_sfb - last_band) should typically be a small value.
+ */
+ for (k = (max_sfb - last_band); k > 0; k--)
+ {
+ *(pSfbPredictionUsed++) = FALSE;
+ }
+ }
+ else /* (win_type == EIGHT_SHORT_SEQUENCE) */
+ {
+ /* last_band = min(MAX_LT_PRED_SHORT_SFB, max_sfb) */
+
+ if (last_band > MAX_LT_PRED_SHORT_SFB)
+ {
+ last_band = MAX_LT_PRED_SHORT_SFB;
+ }
+
+ /*
+ * The following two coding constructs are equivalent...
+ *
+ * first_time == 1
+ * for (wnd_num=NUM_SHORT_WINDOWS; wnd_num > 0; wnd_num--)
+ * {
+ * if (condition)
+ * {
+ * if (first_time == 1)
+ * {
+ * CODE SECTION A
+ * first_time = 0;
+ * }
+ * else
+ * {
+ * CODE SECTION B
+ * }
+ * }
+ * }
+ *
+ * -----------------------------------EQUIVALENT TO------------
+ *
+ * wnd_num=NUM_SHORT_WINDOWS;
+ *
+ * do
+ * {
+ * wnd_num--;
+ * if (condition)
+ * {
+ * CODE SECTION A
+ * break;
+ * }
+ * } while( wnd_num > 0)
+ *
+ * while (wnd_num > 0)
+ * {
+ * if (condition)
+ * {
+ * CODE SECTION B
+ * }
+ * wnd_num--;
+ * }
+ *
+ */
+
+ prev_subblock = pDelay[0];
+
+ pTempPtr = &pSfbPredictionUsed[0];
+
+ wnd_num = NUM_SHORT_WINDOWS;
+
+ prev_subblock_nonzero = prev_subblock;
+ prev_subblock += LTP_LAG_OFFSET;
+
+ do
+ {
+ /*
+ * Place decrement of wnd_num here, to insure
+ * that the decrement occurs before the
+ * break out of the do-while loop.
+ */
+ wnd_num--;
+
+ temp_reg = (Int) get1bits(pInputStream);
+
+ *(pWinPredictionUsed++) = temp_reg;
+
+ if (temp_reg != FALSE)
+ {
+ *(pDelay++) = prev_subblock_nonzero;
+
+ for (k = last_band; k > 0; k--)
+ {
+ *(pTempPtr++) = TRUE;
+ }
+ for (k = (max_sfb - last_band); k > 0; k--)
+ {
+ *(pTempPtr++) = FALSE;
+ }
+ break;
+
+ } /* if(pWinPredictionUsed) */
+ else
+ {
+ pDelay++;
+ pTempPtr += max_sfb;
+ }
+
+ }
+ while (wnd_num > 0);
+
+ /*
+ * This while loop picks up where the previous one left off.
+ * Notice that the code functions differently inside the loop
+ */
+
+ while (wnd_num > 0)
+ {
+ temp_reg = (Int) get1bits(pInputStream);
+
+ *(pWinPredictionUsed++) = temp_reg;
+
+ if (temp_reg != FALSE)
+ {
+ temp_reg = (Int) get1bits(pInputStream);
+ if (temp_reg != 0)
+ {
+ temp_reg = (Int) get9_n_lessbits(
+ LEN_LTP_SHORT_LAG,
+ pInputStream);
+
+ *(pDelay++) = prev_subblock - temp_reg;
+ }
+ else
+ {
+ *(pDelay++) = prev_subblock_nonzero;
+ }
+ for (k = last_band; k > 0; k--)
+ {
+ *(pTempPtr++) = TRUE;
+ }
+ for (k = (max_sfb - last_band); k > 0; k--)
+ {
+ *(pTempPtr++) = FALSE;
+ }
+
+ } /* if (temp_reg) */
+ else
+ {
+ pDelay++;
+ pTempPtr += max_sfb;
+ }
+
+ wnd_num--;
+
+ } /* while(wnd_num) */
+
+ } /* else (win_type == EIGHT_SHORT_SEQUENCE) */
+
+} /* lt_decode */
diff --git a/media/libstagefright/codecs/aacdec/lt_decode.h b/media/libstagefright/codecs/aacdec/lt_decode.h
new file mode 100644
index 0000000..c655270
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/lt_decode.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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: lt_decode.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changing to move pInputStream to 2nd parameter.
+
+ Description: Replaced "e_WINDOW_TYPE.h" with "e_WINDOW_SEQUENCE.h"
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file contains the global function declaration for lt_decode
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef LT_DECODE_H
+#define LT_DECODE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_window_sequence.h"
+#include "s_lt_pred_status.h"
+#include "s_bits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+void lt_decode(
+ const WINDOW_SEQUENCE win_type,
+ BITS *pInputStream,
+ const Int max_sfb,
+ LT_PRED_STATUS *pLt_pred);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/lt_prediction.h b/media/libstagefright/codecs/aacdec/lt_prediction.h
new file mode 100644
index 0000000..e52a1e8
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/lt_prediction.h
@@ -0,0 +1,69 @@
+/* ------------------------------------------------------------------
+ * 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
+Nokia in the course of development of the MPEG-2 AAC/MPEG-4
+Audio standard ISO/IEC13818-7, 14496-1, 2 and 3.
+This software module is an implementation of a part
+of one or more MPEG-2 AAC/MPEG-4 Audio tools as specified by the
+MPEG-2 aac/MPEG-4 Audio standard. ISO/IEC gives users of the
+MPEG-2aac/MPEG-4 Audio standards free license to this software module
+or modifications thereof for use in hardware or software products
+claiming conformance to the MPEG-2 aac/MPEG-4 Audio standards. Those
+intending to use this software module in hardware or software products
+are advised that this use may infringe existing patents. The original
+developer of this software module, 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-2 aac/MPEG-4
+Audio conforming products. The original developer retains full right to
+use the code for the developer's own purpose, assign or donate the code to a
+third party and to inhibit third party from using the code for non
+MPEG-2 aac/MPEG-4 Audio conforming products. This copyright notice
+must be included in all copies or derivative works.
+Copyright (c)1997.
+
+***************************************************************************/
+
+#ifndef _LT_PREDICTION_H
+#define _LT_PREDICTION_H
+
+#include "block.h"
+#include "ltp_common.h"
+#include "ibstream.h"
+#include "lt_decode.h"
+#include "s_frameinfo.h"
+#include "window_block.h"
+
+void init_lt_pred(LT_PRED_STATUS * lt_status);
+
+void lt_predict(
+ Int object,
+ FrameInfo *pFrameInfo,
+ WINDOW_SEQUENCE win_seq,
+ Wnd_Shape *pWin_shape,
+ LT_PRED_STATUS *pLt_status,
+ Real *pPredicted_samples,
+ Real *pOverlap_buffer,
+ Real *pCurrent_frame_copy,
+ Real current_frame[]);
+
+short double_to_int(double sig_in);
+
+#endif /* not defined _LT_PREDICTION_H */
diff --git a/media/libstagefright/codecs/aacdec/ltp_common_internal.h b/media/libstagefright/codecs/aacdec/ltp_common_internal.h
new file mode 100644
index 0000000..d76ac75
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ltp_common_internal.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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
+
+Mikko Suonio (Nokia)
+
+in the course of development of the MPEG-2 NBC/MPEG-4 Audio standard
+ISO/IEC 13818-7, 14496-1,2 and 3. This software module is an
+implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools
+as specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC gives
+users of the MPEG-2 NBC/MPEG-4 Audio standards free license to this
+software module or modifications thereof for use in hardware or
+software products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audio
+standards. Those intending to use this software module in hardware or
+software products are advised that this 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-2
+NBC/MPEG-4 Audio conforming products. The original developer retains
+full right to use the code for his/her own purpose, assign or donate
+the code to a third party and to inhibit third party from using the
+code for non MPEG-2 NBC/MPEG-4 Audio conforming products. This
+copyright notice must be included in all copies or derivative works.
+
+Copyright (c) 1997.
+
+***************************************************************************/
+
+#ifndef _LTP_COMMON_INTERNAL_H
+#define _LTP_COMMON_INTERNAL_H
+
+
+/*
+ Purpose: Number of LTP coefficients. */
+#define LPC 1
+
+/*
+ Purpose: Maximum LTP lag. */
+#define DELAY 2048
+
+/*
+ Purpose: Length of the bitstream element ltp_data_present. */
+#define LEN_LTP_DATA_PRESENT 1
+
+/*
+ Purpose: Length of the bitstream element ltp_lag. */
+#define LEN_LTP_LAG 11
+
+/*
+ Purpose: Length of the bitstream element ltp_coef. */
+#define LEN_LTP_COEF 3
+
+/*
+ Purpose: Length of the bitstream element ltp_short_used. */
+#define LEN_LTP_SHORT_USED 1
+
+/*
+ Purpose: Length of the bitstream element ltp_short_lag_present. */
+#define LEN_LTP_SHORT_LAG_PRESENT 1
+
+/*
+ Purpose: Length of the bitstream element ltp_short_lag. */
+#define LEN_LTP_SHORT_LAG 5
+
+/*
+ Purpose: Offset of the lags written in the bitstream. */
+#define LTP_LAG_OFFSET 16
+
+/*
+ Purpose: Length of the bitstream element ltp_long_used. */
+#define LEN_LTP_LONG_USED 1
+
+/*
+ Purpose: Upper limit for the number of scalefactor bands
+ which can use lt prediction with long windows.
+ Explanation: Bands 0..MAX_LT_PRED_SFB-1 can use lt prediction. */
+#define MAX_LT_PRED_LONG_SFB 40
+
+/*
+ Purpose: Upper limit for the number of scalefactor bands
+ which can use lt prediction with short windows.
+ Explanation: Bands 0..MAX_LT_PRED_SFB-1 can use lt prediction. */
+#define MAX_LT_PRED_SHORT_SFB 13
+
+/*
+ Purpose: Buffer offset to maintain block alignment.
+ Explanation: This is only used for a short window sequence. */
+#define SHORT_SQ_OFFSET (BLOCK_LEN_LONG-(BLOCK_LEN_SHORT*4+BLOCK_LEN_SHORT/2))
+
+/*
+ Purpose: Number of codes for LTP weight. */
+#define CODESIZE 8
+
+/* number of scalefactor bands used for reconstruction for short windows */
+#define NUM_RECONSTRUCTED_SFB (8)
+
+#endif /* _LTP_COMMON_INTERNAL_H */
diff --git a/media/libstagefright/codecs/aacdec/mdct_fxp.cpp b/media/libstagefright/codecs/aacdec/mdct_fxp.cpp
new file mode 100644
index 0000000..df371e8
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/mdct_fxp.cpp
@@ -0,0 +1,450 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: mdct_fxp.c
+ Funtions: fft_rx2
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ data_quant = Input vector, with quantized Q15 spectral lines:
+ type Int32
+
+ Q_FFTarray = Scratch memory used for in-place IFFT calculation,
+ min size required 1024, type Int32
+
+ n = Length of input vector "data_quant". Currently 256 or 2048.
+ type const Int
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ shift = shift factor to reflect scaling introduced by FFT and mdct_fxp,
+
+ Pointers and Buffers Modified:
+ calculation are done in-place and returned in "data_quant"
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ The MDCT is a linear orthogonal lapped transform, based on the idea of
+ time domain aliasing cancellation (TDAC).
+ MDCT is critically sampled, which means that though it is 50% overlapped,
+ a sequence data after MDCT has the same number of coefficients as samples
+ before the transform (after overlap-and-add). This means, that a single
+ block of MDCT data does not correspond to the original block on which the
+ MDCT was performed. When subsequent blocks of data are added (still using
+ 50% overlap), the errors introduced by the transform cancels out.
+ Thanks to the overlapping feature, the MDCT is very useful for
+ quantization. It effectively removes the otherwise easily detectable
+ blocking artifact between transform blocks.
+ N = length of input vector X
+ X = vector of length N/2, will hold fixed point DCT
+ k = 0:1:N-1
+
+ N-1
+ X(m) = 2 SUM x(k)*cos(pi/(2*N)*(2*k+1+N/2)*(2*m+1))
+ k=0
+
+
+ The window that completes the TDAC is applied before calling this function.
+ The MDCT can be calculated using an FFT, for this, the MDCT needs to be
+ rewritten as an odd-time odd-frequency discrete Fourier transform. Thus,
+ the MDCT can be calculated using only one n/4 point FFT and some pre and
+ post-rotation of the sample points.
+
+ Computation of the MDCT implies computing
+
+ x = ( y - y ) + j( y + y )
+ n 2n N/2-1-2n N-1-2n N/2+2n
+
+ using the Fast discrete cosine transform as described in [2]
+
+ where x(n) is an input with N points
+
+ x(n) ----------------------------
+ |
+ |
+ Pre-rotation by exp(j(2pi/N)(n+1/8))
+ |
+ |
+ N/4- point FFT
+ |
+ |
+ Post-rotation by exp(j(2pi/N)(k+1/8))
+ |
+ |
+ ------------- DCT
+
+ By considering the N/2 overlap, a relation between successive input blocks
+ is found:
+
+ x (2n) = x (N/2 + 2n)
+ m+1 m
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function should provide a fixed point MDCT with an average
+ quantization error less than 1 %.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] Analysis/Synthesis Filter Bank design based on time domain
+ aliasing cancellation
+ Jhon Princen, et. al.
+ IEEE Transactions on ASSP, vol ASSP-34, No. 5 October 1986
+ Pg 1153 - 1161
+
+ [2] Regular FFT-related transform kernels for DCT/DST based
+ polyphase filterbanks
+ Rolf Gluth
+ Proc. ICASSP 1991, pg. 2205 - 2208
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Cx, Cy are complex number
+
+
+ exp = log2(n)-1
+
+ FOR ( k=0; k< n/4; k +=2)
+
+ Cx = (data_quant[3n/4 + k] + data_quant[3n/4 - 1 - k]) +
+ j (data_quant[ n/4 + k] - data_quant[ n/4 - 1 - k])
+
+ Q_FFTarray = Cx * exp(-j(2pi/n)(k+1/8))
+
+ ENDFOR
+
+ FOR ( k=n/4; k< n/2; k +=2)
+
+ Cx = (data_quant[3n/4 - 1 - k] + data_quant[ - n/4 + k]) +
+ j (data_quant[5n/4 - 1 - k] - data_quant[ n/4 + k])
+
+ Q_FFTarray = Cx * exp(-j(2pi/n)(k+1/8))
+
+ ENDFOR
+
+ CALL FFT( Q_FFTarray, n/4)
+
+ MODIFYING( Q_FFTarray )
+
+ RETURNING( shift )
+
+ FOR ( k=0; k< n/2; k +=2)
+
+ Cx = Q_FFTarray[ k] + j Q_FFTarray[ k+1]
+
+ Cy = 2 * Cx * exp(-j(2pi/n)(k+1/8))
+
+ data_quant[ k ] = - Real(Cy)
+ data_quant[ n/2 - 1 - k ] = Imag(Cy)
+ data_quant[ n/2 + k ] = - Imag(Cy)
+ data_quant[ n - k ] = Real(Cy)
+
+ ENDFOR
+
+ MODIFIED data_quant[]
+
+ RETURN (-shift-1)
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+#include "mdct_fxp.h"
+#include "fft_rx4.h"
+#include "mix_radix_fft.h"
+#include "fwd_long_complex_rot.h"
+#include "fwd_short_complex_rot.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define ERROR_IN_FRAME_SIZE 10
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+Int mdct_fxp(
+ Int32 data_quant[],
+ Int32 Q_FFTarray[],
+ Int n)
+{
+
+ Int32 temp_re;
+ Int32 temp_im;
+
+ Int32 temp_re_32;
+ Int32 temp_im_32;
+
+ Int16 cos_n;
+ Int16 sin_n;
+ Int32 exp_jw;
+ Int shift;
+
+
+ const Int32 *p_rotate;
+
+
+ Int32 *p_data_1;
+ Int32 *p_data_2;
+ Int32 *p_data_3;
+ Int32 *p_data_4;
+
+ Int32 *p_Q_FFTarray;
+
+ Int32 max1;
+
+ Int k;
+ Int n_2 = n >> 1;
+ Int n_4 = n >> 2;
+ Int n_8 = n >> 3;
+ Int n_3_4 = 3 * n_4;
+
+ switch (n)
+ {
+ case SHORT_WINDOW_TYPE:
+ p_rotate = (Int32 *)exp_rotation_N_256;
+ break;
+
+ case LONG_WINDOW_TYPE:
+ p_rotate = (Int32 *)exp_rotation_N_2048;
+ break;
+
+ default:
+ /*
+ * There is no defined behavior for a non supported frame
+ * size. By returning a fixed scaling factor, the input will
+ * scaled down and this will be heard as a low level noise
+ */
+ return(ERROR_IN_FRAME_SIZE);
+
+ }
+
+ /*--- Reordering and Pre-rotation by exp(-j(2pi/N)(r+1/8)) */
+ p_data_1 = &data_quant[n_3_4];
+ p_data_2 = &data_quant[n_3_4 - 1];
+ p_data_3 = &data_quant[n_4];
+ p_data_4 = &data_quant[n_4 - 1];
+
+ p_Q_FFTarray = Q_FFTarray;
+
+ max1 = 0;
+
+ for (k = n_8; k > 0; k--)
+ {
+ /*
+ * scale down to ensure numbers are Q15
+ * temp_re and temp_im are 32-bit but
+ * only the lower 16 bits are used
+ */
+
+ temp_re = (*(p_data_1++) + *(p_data_2--)) >> 1;
+ temp_im = (*(p_data_3++) - *(p_data_4--)) >> 1;
+
+
+ /*
+ * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
+ */
+
+ exp_jw = *p_rotate++;
+
+ cos_n = (Int16)(exp_jw >> 16);
+ sin_n = (Int16)(exp_jw & 0xFFFF);
+
+ temp_re_32 = temp_re * cos_n + temp_im * sin_n;
+ temp_im_32 = temp_im * cos_n - temp_re * sin_n;
+ *(p_Q_FFTarray++) = temp_re_32;
+ *(p_Q_FFTarray++) = temp_im_32;
+ max1 |= (temp_re_32 >> 31) ^ temp_re_32;
+ max1 |= (temp_im_32 >> 31) ^ temp_im_32;
+
+
+ p_data_1++;
+ p_data_2--;
+ p_data_4--;
+ p_data_3++;
+ }
+
+
+ p_data_1 = &data_quant[n - 1];
+ p_data_2 = &data_quant[n_2 - 1];
+ p_data_3 = &data_quant[n_2];
+ p_data_4 = data_quant;
+
+ for (k = n_8; k > 0; k--)
+ {
+ /*
+ * scale down to ensure numbers are Q15
+ */
+ temp_re = (*(p_data_2--) - *(p_data_4++)) >> 1;
+ temp_im = (*(p_data_1--) + *(p_data_3++)) >> 1;
+
+ p_data_2--;
+ p_data_1--;
+ p_data_4++;
+ p_data_3++;
+
+ /*
+ * cos_n + j*sin_n == exp(j(2pi/N)(k+1/8))
+ */
+
+ exp_jw = *p_rotate++;
+
+ cos_n = (Int16)(exp_jw >> 16);
+ sin_n = (Int16)(exp_jw & 0xFFFF);
+
+ temp_re_32 = temp_re * cos_n + temp_im * sin_n;
+ temp_im_32 = temp_im * cos_n - temp_re * sin_n;
+
+ *(p_Q_FFTarray++) = temp_re_32;
+ *(p_Q_FFTarray++) = temp_im_32;
+ max1 |= (temp_re_32 >> 31) ^ temp_re_32;
+ max1 |= (temp_im_32 >> 31) ^ temp_im_32;
+
+
+ } /* for(k) */
+
+
+
+ p_Q_FFTarray = Q_FFTarray;
+
+ if (max1)
+ {
+
+ if (n != SHORT_WINDOW_TYPE)
+ {
+
+ shift = mix_radix_fft(
+ Q_FFTarray,
+ &max1);
+
+ shift += fwd_long_complex_rot(
+ Q_FFTarray,
+ data_quant,
+ max1);
+
+ }
+ else /* n_4 is 64 */
+ {
+
+ shift = fft_rx4_short(
+ Q_FFTarray,
+ &max1);
+
+ shift += fwd_short_complex_rot(
+ Q_FFTarray,
+ data_quant,
+ max1);
+ }
+
+ }
+ else
+ {
+ shift = -31;
+ }
+
+ /*
+ * returns shift introduced by FFT and mdct_fxp, 12 accounts for
+ * regular downshift (14) and MDCT scale factor (-2)
+ * number are returned as 16 bits
+ */
+ return (12 - shift);
+
+} /* mdct_fxp */
+
diff --git a/media/libstagefright/codecs/aacdec/mdct_fxp.h b/media/libstagefright/codecs/aacdec/mdct_fxp.h
new file mode 100644
index 0000000..b8d5a80
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/mdct_fxp.h
@@ -0,0 +1,107 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: mdct_fxp.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: This extern had the incorrect length of the arrays. The true
+ lengths are 128 and 1024, not 64 and 512.
+
+ Description: Modified interface so a vector with extended precision is
+ returned. Added copyright notice.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for function mdct_fxp()
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef MDCT_FXP_H
+#define MDCT_FXP_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define LONG_WINDOW_TYPE 2048
+#define SHORT_WINDOW_TYPE 256
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ extern const Int exp_rotation_N_256[128];
+ extern const Int exp_rotation_N_2048[1024];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Int mdct_fxp(
+ Int32 data_quant[],
+ Int32 Q_FFTarray[],
+ Int n);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* MDCT_FXP_H */
diff --git a/media/libstagefright/codecs/aacdec/mdct_tables_fxp.cpp b/media/libstagefright/codecs/aacdec/mdct_tables_fxp.cpp
new file mode 100644
index 0000000..709cbf2
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/mdct_tables_fxp.cpp
@@ -0,0 +1,253 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: mdct_tables_fxp.c
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created from fft_rx2.c
+
+ Description: Modified to include forward and inverse tables
+
+ Who: Date:
+ Description:
+
+ ------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ MDCT rotation tables fixpoint tables
+
+ For a table with N complex points:
+
+ cos_n + j*sin_n == exp(j(2pi/N)(n+1/8))
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL FUNCTION REFERENCES
+ ; Declare functions defined elsewhere and referenced in this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+
+
+
+ extern const Int32 exp_rotation_N_256[64] =
+ {
+
+ 0x5A820047, 0x5A7A0280, 0x5A6304B8, 0x5A3E06EF,
+ 0x5A0C0926, 0x59CB0B5B, 0x597D0D8E, 0x59210FBF,
+ 0x58B711EE, 0x5840141A, 0x57BB1643, 0x57281868,
+ 0x56881A8A, 0x55DB1CA8, 0x55201EC1, 0x545820D5,
+ 0x538322E5, 0x52A224EF, 0x51B326F3, 0x50B828F1,
+ 0x4FB12AE9, 0x4E9D2CDA, 0x4D7D2EC5, 0x4C5230A8,
+ 0x4B1A3284, 0x49D73458, 0x48883624, 0x472F37E7,
+ 0x45CA39A2, 0x445A3B54, 0x42E03CFD, 0x415C3E9C,
+ 0x3FCE4032, 0x3E3541BE, 0x3C944340, 0x3AE844B7,
+ 0x39344624, 0x37774786, 0x35B148DD, 0x33E44A29,
+ 0x320E4B69, 0x30304C9E, 0x2E4B4DC6, 0x2C5F4EE3,
+ 0x2A6C4FF4, 0x287250F8, 0x267251F0, 0x246D52DB,
+ 0x226153BA, 0x2051548B, 0x1E3B5550, 0x1C215607,
+ 0x1A0256B1, 0x17DF574E, 0x15B957DD, 0x138F585F,
+ 0x116358D3, 0x0F335939, 0x0D015992, 0x0ACE59DD,
+ 0x08985A1A, 0x06625A49, 0x042A5A6A, 0x01F25A7D
+ };
+
+
+
+
+
+
+ extern const Int32 exp_rotation_N_2048[512] =
+ {
+
+ 0x5A820009, 0x5A820050, 0x5A820097, 0x5A8100DE,
+ 0x5A810125, 0x5A80016C, 0x5A7E01B3, 0x5A7D01FA,
+ 0x5A7B0242, 0x5A790289, 0x5A7702D0, 0x5A750317,
+ 0x5A72035E, 0x5A7003A5, 0x5A6D03EC, 0x5A6A0433,
+ 0x5A66047A, 0x5A6304C1, 0x5A5F0508, 0x5A5B054F,
+ 0x5A560596, 0x5A5205DD, 0x5A4D0624, 0x5A48066A,
+ 0x5A4306B1, 0x5A3E06F8, 0x5A38073F, 0x5A320786,
+ 0x5A2C07CD, 0x5A260814, 0x5A20085A, 0x5A1908A1,
+ 0x5A1208E8, 0x5A0B092F, 0x5A040975, 0x59FC09BC,
+ 0x59F40A03, 0x59EC0A49, 0x59E40A90, 0x59DC0AD7,
+ 0x59D30B1D, 0x59CA0B64, 0x59C10BAA, 0x59B80BF1,
+ 0x59AE0C37, 0x59A50C7E, 0x599B0CC4, 0x59910D0A,
+ 0x59860D51, 0x597C0D97, 0x59710DDD, 0x59660E23,
+ 0x595B0E6A, 0x594F0EB0, 0x59440EF6, 0x59380F3C,
+ 0x592C0F82, 0x59200FC8, 0x5913100E, 0x59061054,
+ 0x58F9109A, 0x58EC10E0, 0x58DF1126, 0x58D1116B,
+ 0x58C411B1, 0x58B611F7, 0x58A7123C, 0x58991282,
+ 0x588A12C8, 0x587B130D, 0x586C1353, 0x585D1398,
+ 0x584E13DD, 0x583E1423, 0x582E1468, 0x581E14AD,
+ 0x580D14F2, 0x57FD1538, 0x57EC157D, 0x57DB15C2,
+ 0x57CA1607, 0x57B9164C, 0x57A71690, 0x579516D5,
+ 0x5783171A, 0x5771175F, 0x575E17A3, 0x574C17E8,
+ 0x5739182C, 0x57261871, 0x571218B5, 0x56FF18FA,
+ 0x56EB193E, 0x56D71982, 0x56C319C6, 0x56AF1A0A,
+ 0x569A1A4F, 0x56851A93, 0x56701AD6, 0x565B1B1A,
+ 0x56461B5E, 0x56301BA2, 0x561A1BE5, 0x56041C29,
+ 0x55EE1C6D, 0x55D81CB0, 0x55C11CF3, 0x55AA1D37,
+ 0x55931D7A, 0x557C1DBD, 0x55651E00, 0x554D1E43,
+ 0x55351E86, 0x551D1EC9, 0x55051F0C, 0x54EC1F4F,
+ 0x54D31F91, 0x54BB1FD4, 0x54A12016, 0x54882059,
+ 0x546F209B, 0x545520DE, 0x543B2120, 0x54212162,
+ 0x540721A4, 0x53EC21E6, 0x53D12228, 0x53B62269,
+ 0x539B22AB, 0x538022ED, 0x5364232E, 0x53492370,
+ 0x532D23B1, 0x531123F2, 0x52F42434, 0x52D82475,
+ 0x52BB24B6, 0x529E24F7, 0x52812538, 0x52642578,
+ 0x524625B9, 0x522825FA, 0x520B263A, 0x51EC267A,
+ 0x51CE26BB, 0x51B026FB, 0x5191273B, 0x5172277B,
+ 0x515327BB, 0x513427FB, 0x5114283A, 0x50F4287A,
+ 0x50D428BA, 0x50B428F9, 0x50942938, 0x50742978,
+ 0x505329B7, 0x503229F6, 0x50112A35, 0x4FF02A74,
+ 0x4FCE2AB2, 0x4FAD2AF1, 0x4F8B2B2F, 0x4F692B6E,
+ 0x4F472BAC, 0x4F242BEA, 0x4F022C29, 0x4EDF2C67,
+ 0x4EBC2CA4, 0x4E992CE2, 0x4E752D20, 0x4E522D5D,
+ 0x4E2E2D9B, 0x4E0A2DD8, 0x4DE62E15, 0x4DC22E53,
+ 0x4D9D2E90, 0x4D792ECD, 0x4D542F09, 0x4D2F2F46,
+ 0x4D0A2F83, 0x4CE42FBF, 0x4CBF2FFB, 0x4C993038,
+ 0x4C733074, 0x4C4D30B0, 0x4C2630EC, 0x4C003127,
+ 0x4BD93163, 0x4BB2319E, 0x4B8B31DA, 0x4B643215,
+ 0x4B3D3250, 0x4B15328B, 0x4AED32C6, 0x4AC53301,
+ 0x4A9D333C, 0x4A753376, 0x4A4C33B1, 0x4A2433EB,
+ 0x49FB3425, 0x49D2345F, 0x49A83499, 0x497F34D3,
+ 0x4955350C, 0x492C3546, 0x4902357F, 0x48D835B9,
+ 0x48AD35F2, 0x4883362B, 0x48583664, 0x482E369C,
+ 0x480336D5, 0x47D7370E, 0x47AC3746, 0x4781377E,
+ 0x475537B6, 0x472937EE, 0x46FD3826, 0x46D1385E,
+ 0x46A43895, 0x467838CD, 0x464B3904, 0x461E393B,
+ 0x45F13972, 0x45C439A9, 0x459739E0, 0x45693A16,
+ 0x453C3A4D, 0x450E3A83, 0x44E03AB9, 0x44B13AEF,
+ 0x44833B25, 0x44553B5B, 0x44263B90, 0x43F73BC6,
+ 0x43C83BFB, 0x43993C30, 0x43693C65, 0x433A3C9A,
+ 0x430A3CCF, 0x42DA3D04, 0x42AA3D38, 0x427A3D6C,
+ 0x424A3DA0, 0x42193DD4, 0x41E93E08, 0x41B83E3C,
+ 0x41873E6F, 0x41563EA3, 0x41253ED6, 0x40F33F09,
+ 0x40C23F3C, 0x40903F6F, 0x405E3FA1, 0x402C3FD4,
+ 0x3FFA4006, 0x3FC74038, 0x3F95406A, 0x3F62409C,
+ 0x3F2F40CE, 0x3EFC4100, 0x3EC94131, 0x3E964162,
+ 0x3E634193, 0x3E2F41C4, 0x3DFB41F5, 0x3DC74226,
+ 0x3D934256, 0x3D5F4286, 0x3D2B42B6, 0x3CF642E6,
+ 0x3CC24316, 0x3C8D4346, 0x3C584375, 0x3C2343A5,
+ 0x3BEE43D4, 0x3BB84403, 0x3B834432, 0x3B4D4460,
+ 0x3B18448F, 0x3AE244BD, 0x3AAC44EB, 0x3A754519,
+ 0x3A3F4547, 0x3A094575, 0x39D245A2, 0x399B45CF,
+ 0x396445FD, 0x392D462A, 0x38F64656, 0x38BF4683,
+ 0x388746B0, 0x385046DC, 0x38184708, 0x37E04734,
+ 0x37A84760, 0x3770478B, 0x373847B7, 0x36FF47E2,
+ 0x36C7480D, 0x368E4838, 0x36554863, 0x361D488E,
+ 0x35E348B8, 0x35AA48E2, 0x3571490C, 0x35384936,
+ 0x34FE4960, 0x34C44989, 0x348B49B3, 0x345149DC,
+ 0x34164A05, 0x33DC4A2E, 0x33A24A56, 0x33684A7F,
+ 0x332D4AA7, 0x32F24ACF, 0x32B74AF7, 0x327C4B1F,
+ 0x32414B46, 0x32064B6E, 0x31CB4B95, 0x31904BBC,
+ 0x31544BE3, 0x31184C0A, 0x30DD4C30, 0x30A14C56,
+ 0x30654C7C, 0x30294CA2, 0x2FEC4CC8, 0x2FB04CEE,
+ 0x2F734D13, 0x2F374D38, 0x2EFA4D5D, 0x2EBD4D82,
+ 0x2E804DA7, 0x2E434DCB, 0x2E064DEF, 0x2DC94E13,
+ 0x2D8C4E37, 0x2D4E4E5B, 0x2D104E7E, 0x2CD34EA2,
+ 0x2C954EC5, 0x2C574EE8, 0x2C194F0A, 0x2BDB4F2D,
+ 0x2B9D4F4F, 0x2B5E4F71, 0x2B204F93, 0x2AE14FB5,
+ 0x2AA34FD7, 0x2A644FF8, 0x2A255019, 0x29E6503A,
+ 0x29A7505B, 0x2968507C, 0x2929509C, 0x28E950BC,
+ 0x28AA50DC, 0x286A50FC, 0x282B511C, 0x27EB513B,
+ 0x27AB515B, 0x276B517A, 0x272B5199, 0x26EB51B7,
+ 0x26AB51D6, 0x266A51F4, 0x262A5212, 0x25E95230,
+ 0x25A9524E, 0x2568526B, 0x25275288, 0x24E652A5,
+ 0x24A652C2, 0x246452DF, 0x242352FB, 0x23E25318,
+ 0x23A15334, 0x235F5350, 0x231E536B, 0x22DC5387,
+ 0x229B53A2, 0x225953BD, 0x221753D8, 0x21D553F3,
+ 0x2193540D, 0x21515427, 0x210F5442, 0x20CD545B,
+ 0x208B5475, 0x2048548F, 0x200654A8, 0x1FC354C1,
+ 0x1F8154DA, 0x1F3E54F2, 0x1EFB550B, 0x1EB85523,
+ 0x1E76553B, 0x1E335553, 0x1DF0556A, 0x1DAC5582,
+ 0x1D695599, 0x1D2655B0, 0x1CE355C7, 0x1C9F55DD,
+ 0x1C5C55F4, 0x1C18560A, 0x1BD55620, 0x1B915636,
+ 0x1B4D564B, 0x1B095661, 0x1AC55676, 0x1A82568B,
+ 0x1A3E569F, 0x19F956B4, 0x19B556C8, 0x197156DC,
+ 0x192D56F0, 0x18E95704, 0x18A45717, 0x1860572A,
+ 0x181B573E, 0x17D75750, 0x17925763, 0x174D5775,
+ 0x17095788, 0x16C4579A, 0x167F57AB, 0x163A57BD,
+ 0x15F557CE, 0x15B057DF, 0x156B57F0, 0x15265801,
+ 0x14E15812, 0x149C5822, 0x14575832, 0x14115842,
+ 0x13CC5851, 0x13875861, 0x13415870, 0x12FC587F,
+ 0x12B6588E, 0x1271589D, 0x122B58AB, 0x11E558B9,
+ 0x11A058C7, 0x115A58D5, 0x111458E2, 0x10CE58F0,
+ 0x108858FD, 0x1042590A, 0x0FFD5916, 0x0FB75923,
+ 0x0F71592F, 0x0F2A593B, 0x0EE45947, 0x0E9E5952,
+ 0x0E58595E, 0x0E125969, 0x0DCC5974, 0x0D85597E,
+ 0x0D3F5989, 0x0CF95993, 0x0CB2599D, 0x0C6C59A7,
+ 0x0C2559B1, 0x0BDF59BA, 0x0B9959C4, 0x0B5259CD,
+ 0x0B0B59D5, 0x0AC559DE, 0x0A7E59E6, 0x0A3859EE,
+ 0x09F159F6, 0x09AA59FE, 0x09645A05, 0x091D5A0D,
+ 0x08D65A14, 0x08905A1B, 0x08495A21, 0x08025A28,
+ 0x07BB5A2E, 0x07745A34, 0x072D5A3A, 0x06E75A3F,
+ 0x06A05A44, 0x06595A49, 0x06125A4E, 0x05CB5A53,
+ 0x05845A57, 0x053D5A5C, 0x04F65A60, 0x04AF5A63,
+ 0x04685A67, 0x04215A6A, 0x03DA5A6D, 0x03935A70,
+ 0x034C5A73, 0x03055A76, 0x02BE5A78, 0x02775A7A,
+ 0x02305A7C, 0x01E95A7D, 0x01A25A7F, 0x015B5A80,
+ 0x01135A81, 0x00CC5A82, 0x00855A82, 0x003E5A82
+ };
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/media/libstagefright/codecs/aacdec/mdst.cpp b/media/libstagefright/codecs/aacdec/mdst.cpp
new file mode 100644
index 0000000..19f82e3
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/mdst.cpp
@@ -0,0 +1,294 @@
+/* ------------------------------------------------------------------
+ * 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: mdst.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 x 32-bit integer input length 64
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ mdst
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#include "pv_audio_type_defs.h"
+#include "synthesis_sub_band.h"
+#include "dct16.h"
+#include "dct64.h"
+#include "mdst.h"
+
+#ifdef HQ_SBR
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#include "fxp_mul32.h"
+#include "dst32.h"
+
+
+#define Qfmt1(a) (Int32)(a*0x7FFFFFFF + (a>=0?0.5F:-0.5F))
+#define Qfmt(a) (Int32)(a*((Int32)1<<27) + (a>=0?0.5F:-0.5F))
+
+const Int32 CosTable_32[32] =
+{
+ Qfmt1(0.50015063602065F), Qfmt1(0.50135845244641F),
+ Qfmt1(0.50378872568104F), Qfmt1(0.50747117207256F),
+ Qfmt1(0.51245147940822F), Qfmt1(0.51879271310533F),
+ Qfmt1(0.52657731515427F), Qfmt1(0.53590981690799F),
+ Qfmt1(0.54692043798551F), Qfmt1(0.55976981294708F),
+ Qfmt1(0.57465518403266F), Qfmt1(0.59181853585742F),
+ Qfmt1(0.61155734788251F), Qfmt1(0.63423893668840F),
+ Qfmt1(0.66031980781371F), Qfmt1(0.69037212820021F),
+ Qfmt1(0.72512052237720F), Qfmt1(0.76549416497309F),
+ Qfmt1(0.81270209081449F), Qfmt1(0.86834471522335F),
+ Qfmt(0.93458359703641F), Qfmt(1.01440826499705F),
+ Qfmt(1.11207162057972F), Qfmt(1.23383273797657F),
+ Qfmt(1.38929395863283F), Qfmt(1.59397228338563F),
+ Qfmt(1.87467598000841F), Qfmt(2.28205006800516F),
+ Qfmt(2.92462842815822F), Qfmt(4.08461107812925F),
+ Qfmt(6.79675071167363F), Qfmt(10.18693908361573F)
+};
+
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; mdst_32
+----------------------------------------------------------------------------*/
+
+void mdst_32(Int32 vec[], Int32 scratch_mem[])
+{
+
+ Int i;
+ const Int32 *pt_cos = CosTable_32;
+ Int32 *pt_vec = vec;
+ Int32 tmp1;
+ Int32 tmp2;
+
+
+
+ Int32 tmp3;
+
+ tmp3 = *(pt_vec++);
+ tmp2 = *(pt_vec);
+
+ for (i = 5; i != 0; i--)
+ {
+ *(pt_vec++) += tmp3;
+ tmp1 = *(pt_vec);
+ *(pt_vec++) += tmp2;
+ tmp3 = *(pt_vec);
+ *(pt_vec++) += tmp1;
+ tmp2 = *(pt_vec);
+ *(pt_vec++) += tmp3;
+ tmp1 = *(pt_vec);
+ *(pt_vec++) += tmp2;
+ tmp3 = *(pt_vec);
+ *(pt_vec++) += tmp1;
+ tmp2 = *(pt_vec);
+ }
+
+ *(pt_vec) += tmp3;
+
+ dst_32(vec, scratch_mem);
+
+ pt_vec = vec;
+
+ for (i = 5; i != 0; i--)
+ {
+ *(pt_vec) = fxp_mul32_Q31((*(pt_vec) << 1) + tmp2, *(pt_cos++));
+ pt_vec++;
+ *(pt_vec) = fxp_mul32_Q31((*(pt_vec) << 1) - tmp2, *(pt_cos++));
+ pt_vec++;
+ *(pt_vec) = fxp_mul32_Q31((*(pt_vec) << 1) + tmp2, *(pt_cos++));
+ pt_vec++;
+ *(pt_vec) = fxp_mul32_Q31((*(pt_vec) << 1) - tmp2, *(pt_cos++));
+ pt_vec++;
+ }
+
+ tmp2 >>= 1;
+ for (i = 3; i != 0; i--)
+ {
+ *(pt_vec) = fxp_mul32_Q27((*(pt_vec) + tmp2), *(pt_cos++));
+ pt_vec++;
+ *(pt_vec) = fxp_mul32_Q27((*(pt_vec) - tmp2), *(pt_cos++));
+ pt_vec++;
+ *(pt_vec) = fxp_mul32_Q27((*(pt_vec) + tmp2), *(pt_cos++));
+ pt_vec++;
+ *(pt_vec) = fxp_mul32_Q27((*(pt_vec) - tmp2), *(pt_cos++));
+ pt_vec++;
+ }
+
+ *(pt_vec - 1) <<= 1;
+
+}
+
+
+
+/*----------------------------------------------------------------------------
+; mdct_32
+----------------------------------------------------------------------------*/
+
+void mdct_32(Int32 vec[])
+{
+ Int i;
+ Int32 *pt_vec = vec;
+ Int32 tmp1, tmp2;
+
+
+ const Int32 *pt_CosTable = CosTable_32;
+
+
+ for (i = 5; i != 0; i--)
+ {
+ *(pt_vec) = fxp_mul32_Q31(*(pt_vec) << 1, *(pt_CosTable++));
+ pt_vec++;
+ *(pt_vec) = fxp_mul32_Q31(*(pt_vec) << 1, *(pt_CosTable++));
+ pt_vec++;
+ *(pt_vec) = fxp_mul32_Q31(*(pt_vec) << 1, *(pt_CosTable++));
+ pt_vec++;
+ *(pt_vec) = fxp_mul32_Q31(*(pt_vec) << 1, *(pt_CosTable++));
+ pt_vec++;
+ }
+ for (i = 3; i != 0; i--)
+ {
+ *(pt_vec) = fxp_mul32_Q27(*(pt_vec), *(pt_CosTable++));
+ pt_vec++;
+ *(pt_vec) = fxp_mul32_Q27(*(pt_vec), *(pt_CosTable++));
+ pt_vec++;
+ *(pt_vec) = fxp_mul32_Q27(*(pt_vec), *(pt_CosTable++));
+ pt_vec++;
+ *(pt_vec) = fxp_mul32_Q27(*(pt_vec), *(pt_CosTable++));
+ pt_vec++;
+ }
+ *(pt_vec - 1) <<= 1;
+
+
+ dct_32(vec);
+
+
+ pt_vec = &vec[31];
+
+ tmp1 = *(pt_vec--);
+
+ for (i = 5; i != 0; i--)
+ {
+ tmp2 = *(pt_vec);
+ *(pt_vec--) += tmp1;
+ tmp1 = *(pt_vec);
+ *(pt_vec--) += tmp2;
+ tmp2 = *(pt_vec);
+ *(pt_vec--) += tmp1;
+ tmp1 = *(pt_vec);
+ *(pt_vec--) += tmp2;
+ tmp2 = *(pt_vec);
+ *(pt_vec--) += tmp1;
+ tmp1 = *(pt_vec);
+ *(pt_vec--) += tmp2;
+ }
+
+ *(pt_vec) += tmp1;
+
+}
+
+#endif /* HQ_SBR */
+
+
+/*----------------------------------------------------------------------------
+; dct_32
+----------------------------------------------------------------------------*/
+
+
+void dct_32(Int32 vec[])
+{
+
+ pv_split(&vec[16]);
+
+ dct_16(&vec[16], 0);
+ dct_16(vec, 1); // Even terms
+
+ pv_merge_in_place_N32(vec);
+}
+
+#endif /* AAC_PLUS */
+
+
diff --git a/media/libstagefright/codecs/aacdec/mdst.h b/media/libstagefright/codecs/aacdec/mdst.h
new file mode 100644
index 0000000..5b3e1c9
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/mdst.h
@@ -0,0 +1,73 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: mdst.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef MDST_H
+#define MDST_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ void mdst_32(Int32 vec[], Int32 scratch_mem[]);
+
+ void dct_32(Int32 vec[]);
+
+ void mdct_32(Int32 vec[]);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MDST_H */
diff --git a/media/libstagefright/codecs/aacdec/mix_radix_fft.cpp b/media/libstagefright/codecs/aacdec/mix_radix_fft.cpp
new file mode 100644
index 0000000..6081c46
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/mix_radix_fft.cpp
@@ -0,0 +1,319 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: mix_radix_fft.c
+ Funtions: mix_radix_fft
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Eliminated pointer dependency ( pData_1) on Buffer address.
+ Modified for-loop to countdown loops.
+
+ Description: No shift information going in/out from fft_rx4_long.
+
+ Description:
+ (1) Increased precision on the radix 2 fft coeff. (from Q10 to Q12)
+ (2) Increased precision on the input (from 0.5 to 1.0).
+ (3) Eliminated hardly used condition (exp = 0).
+ (4) Change interface to fft_rx4_long, so now the same function is
+ used for forward and inverse calculations.
+
+ Description: per code review comments, eliminated unnecessary headers
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ Data = Input vector, with quantized spectral with a pre-rotation
+ by exp(j(2pi/N)(k+1/8))
+ type Int32 *
+
+ peak_value = Input, carries the maximum value in input vector "Data"
+ Output, maximum value computed in the first FFT, used
+ to set precision on next stages
+ type Int32 *
+
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ exponent = shift factor to reflect signal scaling
+
+ Pointers and Buffers Modified:
+ Results are return in "Data"
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ mix_radix_fft() mixes radix-2 and radix-4 FFT. This is needed to be able
+ to use power of 4 length when the input length sequence is a power of 2.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ mix_radix_fft() should support only the FFT for the long window case of
+ the inverse modified cosine transform (IMDCT)
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+ MODIFY( x[] )
+ RETURN( exponent )
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "fft_rx4.h"
+#include "mix_radix_fft.h"
+#include "pv_normalize.h"
+
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void digit_reversal_swapping(Int32 *y, Int32 *x);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int mix_radix_fft(
+ Int32 *Data,
+ Int32 *peak_value
+)
+
+{
+
+ const Int32 *p_w;
+ Int32 *pData_1;
+ Int32 *pData_2;
+
+ Int32 *pData_3;
+ Int32 *pData_4;
+
+ Int32 exp_jw;
+ Int32 max1;
+ Int32 max2;
+ Int32 temp1;
+ Int32 temp2;
+ Int32 temp3;
+ Int32 temp4;
+ Int32 diff1;
+ Int32 diff2;
+ Int i;
+ Int exp;
+
+ max1 = *peak_value;
+ p_w = w_512rx2;
+
+ pData_1 = Data;
+ pData_3 = Data + HALF_FFT_RX4_LENGTH_FOR_LONG;
+
+
+ /*
+ * normalization to 0.9999 (0x7FFF) guarantees proper operation
+ */
+
+ exp = 8 - pv_normalize(max1); /* use 24 bits for mix radix fft */
+
+ if (exp < 4)
+ {
+ exp = 4;
+ }
+
+
+ temp1 = (*pData_3);
+ pData_4 = pData_3 + FFT_RX4_LENGTH_FOR_LONG;
+ temp2 = (*pData_4++);
+
+
+
+ diff1 = (temp1 - temp2) >> exp;
+ *pData_3++ = (temp1 + temp2) >> exp;
+
+ temp3 = (*pData_3);
+ temp4 = (*pData_4);
+
+ *pData_4-- = -diff1;
+ *pData_3++ = (temp3 + temp4) >> exp;
+ *pData_4 = (temp3 - temp4) >> exp;
+
+ temp1 = (*pData_1);
+ pData_2 = pData_1 + FFT_RX4_LENGTH_FOR_LONG;
+ temp2 = (*pData_2++);
+ temp4 = (*pData_2);
+
+ *pData_1++ = (temp1 + temp2) >> exp;
+
+ temp3 = (*pData_1);
+ diff1 = (temp1 - temp2) >> exp ;
+
+ *pData_1++ = (temp3 + temp4) >> exp;
+ *pData_2-- = (temp3 - temp4) >> exp;
+ *pData_2 = diff1;
+
+ temp1 = (*pData_3);
+ pData_4 = pData_3 + FFT_RX4_LENGTH_FOR_LONG;
+ temp2 = (*pData_4++);
+
+
+ for (i = ONE_FOURTH_FFT_RX4_LENGTH_FOR_LONG - 1; i != 0; i--)
+ {
+ /*
+ * radix 2 Butterfly
+ */
+
+ diff1 = (temp1 - temp2) >> (exp - 4);
+ *pData_3++ = (temp1 + temp2) >> exp;
+
+ temp3 = (*pData_3);
+ temp4 = (*pData_4);
+
+ exp_jw = *p_w++;
+
+
+ diff2 = (temp3 - temp4) >> (exp - 4);
+ *pData_3++ = (temp3 + temp4) >> exp;
+
+ *pData_4-- = -cmplx_mul32_by_16(diff1, diff2, exp_jw) >> 3;
+ *pData_4 = cmplx_mul32_by_16(diff2, -diff1, exp_jw) >> 3;
+
+
+ temp1 = (*pData_1);
+ pData_2 = pData_1 + FFT_RX4_LENGTH_FOR_LONG;
+ temp2 = (*pData_2++);
+ temp4 = (*pData_2);
+
+ *pData_1++ = (temp1 + temp2) >> exp;
+
+ temp3 = (*pData_1);
+ diff1 = (temp1 - temp2) >> (exp - 4);
+
+ diff2 = (temp3 - temp4) >> (exp - 4);
+ *pData_1++ = (temp3 + temp4) >> exp;
+
+ *pData_2-- = cmplx_mul32_by_16(diff2, -diff1, exp_jw) >> 3;
+ *pData_2 = cmplx_mul32_by_16(diff1, diff2, exp_jw) >> 3;
+
+ temp1 = (*pData_3);
+ pData_4 = pData_3 + FFT_RX4_LENGTH_FOR_LONG;
+ temp2 = (*pData_4++);
+
+ }/* for i */
+
+
+ fft_rx4_long(
+ Data,
+ &max1);
+
+
+ fft_rx4_long(
+ &Data[FFT_RX4_LENGTH_FOR_LONG],
+ &max2);
+
+ digit_reversal_swapping(Data, &Data[FFT_RX4_LENGTH_FOR_LONG]);
+
+ *peak_value = max1 | max2;
+
+ return(exp);
+}
+
diff --git a/media/libstagefright/codecs/aacdec/mix_radix_fft.h b/media/libstagefright/codecs/aacdec/mix_radix_fft.h
new file mode 100644
index 0000000..563c280
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/mix_radix_fft.h
@@ -0,0 +1,98 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: mix_radix_fft.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for functions mix_radix_fft
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef MIX_RADIX_FFT_H
+#define MIX_RADIX_FFT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define FFT_RX4_LENGTH_FOR_LONG 512
+#define HALF_FFT_RX4_LENGTH_FOR_LONG (FFT_RX4_LENGTH_FOR_LONG>>1)
+#define ONE_FOURTH_FFT_RX4_LENGTH_FOR_LONG (FFT_RX4_LENGTH_FOR_LONG>>2)
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ Int mix_radix_fft(
+ Int32 *Data,
+ Int32 *peak_value);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* MIX_RADIX_FFT_H */
diff --git a/media/libstagefright/codecs/aacdec/ms_map_mask.h b/media/libstagefright/codecs/aacdec/ms_map_mask.h
new file mode 100644
index 0000000..fbbec78
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ms_map_mask.h
@@ -0,0 +1,87 @@
+/* ------------------------------------------------------------------
+ * 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:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ [Describe the contents of the include file.]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef MS_MAP_MASK_H
+#define MS_MAP_MASK_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+void MS_map_mask(
+ FrameInfo *info,
+ Int *group,
+ Int *mask,
+ Int *cb_map);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/ms_synt.cpp b/media/libstagefright/codecs/aacdec/ms_synt.cpp
new file mode 100644
index 0000000..1f25516
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ms_synt.cpp
@@ -0,0 +1,403 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ms_synt.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Cleaned up a bit, not finished.
+
+ Description:
+ Copied in code from pns_intensity_right.c, which has the same structure as
+ this file. Also, merged in code from ms_map_mask.c
+
+ Description:
+ (1) Various optimizations (eliminated extra variables by making use of a
+ single temporary register throughout the code, etc.)
+ (2) Wrote pseudocode, pasted in correct function template, etc.
+
+ Description: Unrolled loops to get speed up code
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ wins_in_group = Number of windows in the current group.
+ [const Int]
+
+ coef_per_win = Number of coefficients per window.
+ [const Int]
+
+ num_bands = Number of scalefactor bands.
+ [const Int]
+
+ band_length = Number of coefficients per scalefactor band.
+ [const Int]
+
+ pFirst_Window_CoefsL = Array containing the spectral coefficients for
+ the left channel.
+ [Int32 *, length LN]
+ pFirst_Window_CoefsR = Array containing the spectral coefficients for
+ the right channel.
+ [Int32 *, length LN]
+ q_formatLeft = Array containing the q-format used to encode each
+ scalefactor band's data on the left channel.
+ [Int *, length MAXBANDS]
+ q_formatRight = Array containing the q-format used to encode each
+ scalefactor band's data on the right channel.
+ [Int *, length MAXBANDS]
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ pFirst_Window_CoefsL The coefficients in the group will be modified per the
+ formula for M/S stereo on each scalefactor band where
+ M/S stereo is active.
+
+ pFirst_Window_CoefsR The coefficients in the group will be modified per the
+ formula for M/S stereo on each scalefactor band where
+ M/S stereo is active.
+
+ q_formatLeft The q_format may be modified on scalefactor bands
+ where M/S stereo is active.
+
+ q_formatRight The q_format may be modified on scalefactor bands
+ where M/S stereo is active.
+
+ Local Stores Modified:
+
+ Global Stores Modified:
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This module applies the formula for M/S coding to one grouped scalefactor
+ band. The ISO code has a similar function which applies M/S coding to an
+ entire frame.
+
+ It is the calling function's responsibility to check the map_mask array, which
+ is filled by the function getmask. If a scalefactor band is identified as
+ using M/S stereo, the coefficients in that array are calculated using
+ the following formula...
+
+ TempLeft = LeftCoefficient;
+
+ LeftCoefficient = LeftCoefficient + RightCoefficient;
+ RightCoefficient = TempLeft - RightCoefficient;
+
+ This function should be inlined if the compiler supports C99 inlining,
+ as this short function is only called by sfb_tools_ms().
+ Therefore, inlining will not increase the code size.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.6.7.1 M/S stereo
+ Subpart 4.6.2 ScaleFactors
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ start_indx = 0;
+
+ pCoefR = coefLeft;
+ pCoefL = coefRight;
+
+ FOR (win_indx = wins_in_group; win_indx > 0; win_indx--)
+
+
+ tempInt = q_formatLeft[start_indx] - q_formatRight[start_indx];
+
+ IF (tempInt > 0)
+ THEN
+
+ shift_left_chan = 1 + tempInt;
+ shift_right_chan = 1;
+
+ q_formatLeft[start_indx] = (q_formatRight[start_indx] - 1);
+ q_formatRight[start_indx] = (q_formatRight[start_indx] - 1);
+
+ ELSE
+ shift_left_chan = 1;
+ shift_right_chan = 1 - tempInt;
+
+ q_formatRight[start_indx] = (q_formatLeft[start_indx] - 1);
+ q_formatLeft[start_indx] = (q_formatLeft[start_indx] - 1);
+
+ ENDIF
+
+ FOR (tempInt = band_length; tempInt > 0; tempInt--)
+
+ temp_left = *(pCoefL) >> shift_left_chan;
+ temp_right = *(pCoefR) >> shift_right_chan;
+
+ *(pCoefL++) = temp_left + temp_right;
+ *(pCoefR++) = temp_left - temp_right;
+
+ ENDFOR
+
+ tempInt = (coef_per_win - band_length);
+
+ pCoefR = pCoefR + tempInt;
+ pCoefL = pCoefL + tempInt;
+
+ start_indx = start_indx + num_bands;
+
+ ENDFOR
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "ms_synt.h"
+#include "fxp_mul32.h"
+#include "aac_mem_funcs.h"
+#include "window_block_fxp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void ms_synt(
+ const Int wins_in_group,
+ const Int coef_per_win,
+ const Int num_bands,
+ const Int band_length,
+ Int32 coefLeft[],
+ Int32 coefRight[],
+ Int q_formatLeft[],
+ Int q_formatRight[])
+{
+
+ Int32 *pCoefL = coefLeft;
+ Int32 *pCoefR = coefRight;
+ Int start_indx = 0;
+
+
+ if (band_length < 0 || band_length > LONG_WINDOW)
+ {
+ return; /* avoid any processing on error condition */
+ }
+
+
+ Int nextWinPtrUpdate = (coef_per_win - band_length);
+
+ for (Int win_indx = wins_in_group; win_indx > 0; win_indx--)
+ {
+
+ if (q_formatRight[start_indx] < 31)
+ {
+ Int tempInt = q_formatLeft[start_indx] - q_formatRight[start_indx];
+
+ /* Normalize the left and right channel to the same q-format */
+ if (tempInt > 0)
+ {
+ /*
+ * shift_left_chan and shift_right_chan each have an offset
+ * of 1. Even if the left and right channel share the same
+ * q-format, we must shift each by 1 to guard against
+ * overflow.
+ */
+ Int shift_left_chan = 1 + tempInt;
+
+ /*
+ * Following code line is equivalent to...
+ * q_formatLeft = q_formatRight - 1;
+ * q_formatRight = q_formatRight - 1;
+ */
+ q_formatLeft[start_indx] = --(q_formatRight[start_indx]);
+
+
+ /*
+ * band_length is always an even number (check tables in pg.66 IS0 14496-3)
+ */
+
+ Int32 temp_left = *(pCoefL) >> shift_left_chan;
+ Int32 temp_right = *(pCoefR) >> 1;
+
+
+
+ for (Int i = band_length; i != 0; i--)
+ {
+ *(pCoefL++) = temp_left + temp_right;
+ *(pCoefR++) = temp_left - temp_right;
+ temp_left = *(pCoefL) >> shift_left_chan;
+ temp_right = *(pCoefR) >> 1;
+
+ }
+
+ }
+ else
+ {
+ /*
+ * shift_left_chan and shift_right_chan each have an offset
+ * of 1. Even if the left and right channel share the same
+ * q-format, we must shift each by 1 to guard against
+ * overflow.
+ */
+ Int shift_right_chan = 1 - tempInt;
+
+ /*
+ * Following code line is equivalent to...
+ * q_formatRight = q_formatLeft - 1;
+ * q_formatLeft = q_formatLeft - 1;
+ */
+ q_formatRight[start_indx] = --(q_formatLeft[start_indx]);
+
+ /*
+ * band_length is always an even number (check tables in pg.66 IS0 14496-3)
+ */
+
+ Int32 temp_left = *(pCoefL) >> 1;
+ Int32 temp_right = *(pCoefR) >> shift_right_chan;
+
+ for (Int i = band_length; i != 0; i--)
+ {
+ *(pCoefL++) = temp_left + temp_right;
+ *(pCoefR++) = temp_left - temp_right;
+
+ temp_left = *(pCoefL) >> 1;
+ temp_right = *(pCoefR) >> shift_right_chan;
+
+ }
+ }
+
+ }
+ else
+ {
+ /*
+ * Nothing on right channel, just copy left into right
+ */
+ q_formatRight[start_indx] = (q_formatLeft[start_indx]);
+
+ pv_memcpy(pCoefR, pCoefL, band_length*sizeof(*pCoefR));
+ pCoefR += band_length;
+ pCoefL += band_length;
+ }
+
+ /*
+ * Increment the window pointers so they point
+ * to the next window in the group
+ */
+ pCoefL += nextWinPtrUpdate;
+ pCoefR += nextWinPtrUpdate;
+
+ start_indx += num_bands;
+
+ } /* for (win_indx) */
+
+ return;
+
+} /* MS_synt */
diff --git a/media/libstagefright/codecs/aacdec/ms_synt.h b/media/libstagefright/codecs/aacdec/ms_synt.h
new file mode 100644
index 0000000..a00e6e2
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ms_synt.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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ms_synt.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated to reflect new functionality of ms_synt() routine.
+ (ms_synt now only decodes one grouped scalefactor band at a time.)
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes the function declaration for ms_synt().
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef MS_SYNT_H
+#define MS_SYNT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void ms_synt(
+ const Int wins_in_group,
+ const Int coef_per_win,
+ const Int num_bands,
+ const Int band_length,
+ Int32 spectralCoefLeft[],
+ Int32 spectralCoefRight[],
+ Int q_formatLeft[],
+ Int q_formatRight[]);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/pns_corr.cpp b/media/libstagefright/codecs/aacdec/pns_corr.cpp
new file mode 100644
index 0000000..4cfe720
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pns_corr.cpp
@@ -0,0 +1,342 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pns_corr.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Made changes per review comments, the most major of which
+ being the change of the scaling into a 16 x 16 multiply.
+
+ Description: When the multiplication of two 16-bits variables is stored in
+ an 32-bits variable, the result should be typecasted explicitly
+ to Int32 before it is stored.
+ *(pCoefRight++) = (Int32) tempInt2 * multiplier;
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ scale = Multiplier used to scale the noise extracted from the left
+ channel for use on the right.
+ [const Int]
+
+ coef_per_win = Number of coefficients per window.
+ (128 for short, 1024 for long)
+ [const Int]
+
+ sfb_per_win = Number of scalefactors per window.
+ [const Int]
+
+ wins_in_group = The number of windows in the group being decoded.
+ [const Int]
+
+ band_length = The length of the scalefactor band being decoded.
+ [const Int]
+
+ sfb_prediction_used = Flag that denotes the activation of long term
+ prediction on a per-scalefactor band,
+ non-grouped basis.
+ [const Int *, length MAX_SFB]
+
+ q_formatLeft = The Q-format for the left channel's fixed-point spectral
+ coefficients, on a per-scalefactor band, non-grouped basis.
+ [const Int]
+
+ q_formatRight = The Q-format for the right channel's fixed-point spectral
+ coefficients, on a per-scalefactor band, non-grouped basis.
+ [Int *, length MAX_SFB]
+
+ coefLeft = Array containing the fixed-point spectral coefficients
+ for the left channel.
+ [const Int32 *, length 1024]
+
+ coefRight = Array containing the fixed-point spectral coefficients
+ for the right channel.
+ [Int32 *, length 1024]
+
+ Local Stores/Buffers/Pointers Needed:
+
+ Global Stores/Buffers/Pointers Needed:
+
+ Outputs:
+
+ Pointers and Buffers Modified:
+ pcoefRight Contains the new spectral information
+
+ q_formatRight Q-format may be updated with changed to fixed-point
+ data in coefRight.
+
+ sfb_prediction_used LTP may be disabled by presence of PNS tool on the
+ same scalefactor band.
+
+ Local Stores Modified:
+
+ Global Stores Modified:
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function derives noise from the left channel. The PNS tool is assumed
+ to have been used on the same scalefactor band on the left channel. The
+ noise on the left/right channels are not necessarily of the same amplitude,
+ and therefore have separate scalefactors. The noise is thus scaled by the
+ difference between the two transmitted scalefactors. This scaling is done
+ in fixed-point using a constant 4-element table.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.6.7.1 M/S stereo
+ Subpart 4.6.12.3 Decoding Process (PNS)
+ Subpart 4.6.2 ScaleFactors
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ q_format = q_formatLeft - (scale >> 2);
+ q_format = q_format - 1;
+ q_formatRight = q_format;
+
+ multiplier = hcb2_scale_mod_4[scale & 0x3];
+
+ pCoefLeft = coefLeft;
+ pCoefRight = coefRight;
+
+ start_indx = 0;
+
+ FOR (win_indx = wins_in_group; win_indx > 0; win_indx--)
+
+ q_formatRight[start_indx] = q_format;
+
+ sfb_prediction_used[start_indx] = FALSE;
+
+ start_indx = start_indx + sfb_per_win;
+
+ FOR (tempInt = band_length; tempInt > 0; tempInt--)
+
+ *(pCoefRight) = (*(pCoefLeft) >> 9) * multiplier;
+ pCoefRight = pCoefRight + 1;
+ pCoefLeft = pCoefLeft + 1;
+
+ ENDFOR
+
+ tempInt = (coef_per_win - band_length);
+ pCoefRight = pCoefRight + tempInt;
+ pCoefLeft = pCoefLeft + tempInt;
+
+ ENDFOR
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "pns_corr.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+const UInt hcb2_scale_mod_4[4] =
+{
+ 32768, /* (2.0^0.00)*2^15 */
+ 38968, /* (2.0^0.25)*2^15 */
+ 46341, /* (2.0^0.50)*2^15 */
+ 55109
+}; /* (2.0^0.75)*2^15 */
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pns_corr(
+ const Int scale,
+ const Int coef_per_win,
+ const Int sfb_per_win,
+ const Int wins_in_group,
+ const Int band_length,
+ const Int q_formatLeft,
+ Int q_formatRight[],
+ const Int32 coefLeft[],
+ Int32 coefRight[])
+{
+ Int tempInt;
+ Int nextWinPtrUpdate;
+
+ Int q_format;
+
+ Int start_indx;
+ Int win_indx;
+
+ const Int32 *pCoefLeft;
+ Int32 *pCoefRight;
+
+ UInt multiplier;
+
+ /*
+ * Generate noise correlated with the noise on the left channel
+ *
+ */
+
+ /*
+ * scale is interpreted as 2^(scale/4)
+ * Therefore, we can adjust the q-format by floor(scale/4)
+ * and save some complexity in the multiplier.
+ */
+ q_format = q_formatLeft - (scale >> 2);
+
+ /*
+ * Reduce the q-format by 1 to guard against overflow.
+ * This must be done because the hcb2_scale_mod_4 table
+ * must be stored in a common q-format, and we must shift
+ * by 16 to get *pCoefLeft into a 16-bit value, but we
+ * cannot store 2^0*2^16 and 2^0.75*2^16 in a table.
+ */
+ q_format--;
+
+ multiplier = hcb2_scale_mod_4[scale & 0x3];
+
+ pCoefLeft = coefLeft;
+ pCoefRight = coefRight;
+
+ nextWinPtrUpdate = (coef_per_win - band_length);
+
+ /*
+ * Step through all the windows in this group, replacing this
+ * band in each window's spectrum with correlated random noise
+ */
+
+ start_indx = 0;
+
+ for (win_indx = wins_in_group; win_indx > 0; win_indx--)
+ {
+ /*
+ * Set the q-format for all scalefactor bands in the group.
+ * Normally, we could not assume that grouped scalefactors
+ * share the same q-format.
+ * However, here we can make this assumption. The reason
+ * being -- if this function is called, it is assumed
+ * PNS was used on the left channel. When PNS is used,
+ * all scalefactors in a group share the same q-format.
+ *
+ */
+ q_formatRight[start_indx] = q_format;
+
+ start_indx += sfb_per_win;
+
+ /* reconstruct right noise values */
+ for (tempInt = band_length; tempInt > 0; tempInt--)
+ {
+ *(pCoefRight++) = (Int32)(*(pCoefLeft++) >> 16) * multiplier;
+ }
+
+ pCoefRight += nextWinPtrUpdate;
+ pCoefLeft += nextWinPtrUpdate;
+
+ } /* for (win_indx) */
+
+ return;
+
+} /* void pns_corr */
diff --git a/media/libstagefright/codecs/aacdec/pns_corr.h b/media/libstagefright/codecs/aacdec/pns_corr.h
new file mode 100644
index 0000000..c892a8c
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pns_corr.h
@@ -0,0 +1,95 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pns_corr.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Made changes per review comments.
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Contains the function declaration for pns_corr.c
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PNS_CORR_H
+#define PNS_CORR_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void pns_corr(
+ const Int scale,
+ const Int coef_per_win,
+ const Int sfb_per_win,
+ const Int wins_in_group,
+ const Int band_length,
+ const Int q_formatLeft,
+ Int q_formatRight[],
+ const Int32 coefLeft[],
+ Int32 coefRight[]);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/pns_intensity_right.cpp b/media/libstagefright/codecs/aacdec/pns_intensity_right.cpp
new file mode 100644
index 0000000..f2d50c1
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pns_intensity_right.cpp
@@ -0,0 +1,653 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pns_intensity_right.c
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ hasmask = mask status for the frame. Enumerated.
+
+ pFrameInfo = Pointer to structure that holds information about each group.
+ (long block flag, number of windows, scalefactor bands
+ per group, etc.)
+ [const pFrameInfo * const]
+
+ group = Array that contains indexes of the
+ first window in the next group.
+ [const Int *, length num_win]
+
+ mask_map = Array that denotes whether M/S stereo is turned on for
+ each grouped scalefactor band.
+ [const Int *, length MAX_SFB]
+
+ codebook_map = Array that denotes which Huffman codebook was used for
+ the encoding of each grouped scalefactor band.
+ [const Int *, length MAX_SFB]
+
+ factorsL = Array of grouped scalefactors for left chan.
+ [const Int *, length MAX_SFB]
+
+ factorsR = Array of scalefactors for right chan.
+ [const Int *, length MAX_SFB]
+
+ sfb_prediction_used = Flag that denotes the activation of long term prediction
+ on a per-scalefactor band, non-grouped basis.
+ [const Int *, length MAX_SFB]
+
+ ltp_data_present = Flag that indicates whether LTP is enbaled for this frame.
+ [const Bool]
+
+ coefLeft = Array containing the fixed-point spectral coefficients
+ for the left channel.
+ [Int32 *, length 1024]
+
+ coefRight = Array containing the fixed-point spectral coefficients
+ for the right channel.
+ [Int32 *, length 1024]
+
+ q_formatLeft = The Q-format for the left channel's fixed-point spectral
+ coefficients, on a per-scalefactor band, non-grouped basis.
+ [Int *, length MAX_SFB]
+
+ q_formatRight = The Q-format for the right channel's fixed-point spectral
+ coefficients, on a per-scalefactor band, non-grouped basis.
+ [Int *, length MAX_SFB]
+
+ pCurrentSeed = Pointer to the current seed for the random number
+ generator in the function gen_rand_vector().
+ [Int32 * const]
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ coefLeft = Contains the new spectral information.
+
+ coefRight = Contains the new spectral information.
+
+ q_formatLeft = Q-format may be updated with changed to fixed-point
+ data in coefLeft.
+
+ q_formatRight = Q-format may be updated with changed to fixed-point
+ data in coefRight.
+
+ pCurrentSeed = Value pointed to by pCurrentSeed updated by calls
+ to gen_rand_vector().
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function steps through all of the scalefactor bands, looking for
+ either PNS or IS to be enabled on the right channel.
+
+ If the codebook used is >= NOISE_HCB, the code then checks for the use
+ of Huffman codebooks NOISE_HCB, INTENSITY_HCB, or INTENSITY_HCB2.
+
+ When a SFB utilizing the codebook NOISE_HCB is detected, a check is made to
+ see if M/S has also been enabled for that SFB.
+
+ If M/S is not enabled, the band's spectral information is filled with
+ scaled random data. The scaled random data is generated by the function
+ gen_rand_vector. This is done across all windows in the group.
+
+ If M/S is enabled, the band's spectral information is derived from the data
+ residing in the same band on the left channel. The information on the right
+ channel has independent scaling, so this is a bit more involved than a
+ direct copy of the information on the left channel. This is done by calling
+ the inline function pns_corr().
+
+ When a SFB utilizing an intensity codebook is detected, the band's spectral
+ information is generated from the information on the left channel.
+ This is done across all windows in the group. M/S being enabled has the
+ effect of reversing the sign of the data on the right channel. This code
+ resides in the inline function intensity_right().
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.6.7.1 M/S stereo
+ Subpart 4.6.7.2.3 Decoding Process (Intensity Stereo)
+ Subpart 4.6.12.3 Decoding Process (PNS)
+ Subpart 4.6.2 ScaleFactors
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+ pCoefRight = coefRight;
+ pCoefLeft = coefLeft;
+
+ window_start = 0;
+ tot_sfb = 0;
+ start_indx = 0;
+
+ coef_per_win = pFrameInfo->coef_per_win[0];
+
+ sfb_per_win = pFrameInfo->sfb_per_win[0];
+
+ DO
+ pBand = pFrameInfo->win_sfb_top[window_start];
+
+ partition = *pGroup;
+ pGroup = pGroup + 1;
+
+ band_start = 0;
+
+ wins_in_group = (partition - window_start);
+
+ FOR (sfb = sfb_per_win; sfb > 0; sfb--)
+
+ band_stop = *(pBand);
+ pBand = pBand + 1;
+
+ codebook = *(pCodebookMap);
+ pCodebookMap = pCodebookMap + 1;
+
+ mask_enabled = *(pMaskMap);
+ pMaskMap = pMaskMap + 1;
+
+ band_length = band_stop - band_start;
+
+ IF (codebook == NOISE_HCB)
+
+ sfb_prediction_used[tot_sfb] &= ltp_data_present;
+
+ IF (sfb_prediction_used[tot_sfb] == FALSE)
+
+ mask_enabled = mask_enabled AND hasmask;
+
+ IF (mask_enabled == FALSE)
+
+ pWindow_CoefR = &(pCoefRight[band_start]);
+
+ start_indx = tot_sfb;
+
+ FOR (win_indx = wins_in_group;
+ win_indx > 0;
+ win_indx--)
+
+ CALL
+ q_formatRight[start_indx] =
+ gen_rand_vector(
+ pWindow_CoefR,
+ band_length,
+ pCurrentSeed,
+ *(pFactorsRight));
+ MODIFYING
+ pCoefRight[band_start]
+ RETURNING
+ q_formatRight[start_indx]
+
+ pWindow_CoefR += coef_per_win;
+
+ start_indx = start_indx + sfb_per_win;
+
+ ENDFOR
+
+ ELSE
+ CALL
+ pns_corr(
+ (*(pFactorsRight) -
+ *(pFactorsLeft) ),
+ coef_per_win,
+ sfb_per_win,
+ wins_in_group,
+ band_length,
+ q_formatLeft[tot_sfb],
+ &(q_formatRight[tot_sfb]),
+ &(pCoefLeft[band_start]),
+ &(pCoefRight[band_start]));
+
+ MODIFYING
+ pCoefRightt[band_start]
+ q_formatRight[tot_sfb]
+ RETURNING
+ NONE
+ ENDIF
+
+ ENDIF
+
+ ELSE IF (codebook >= INTENSITY_HCB2)
+
+ mask_enabled = mask_enabled AND hasmask;
+
+ CALL
+ intensity_right(
+ *(pFactorsRight),
+ coef_per_win,
+ sfb_per_win,
+ wins_in_group,
+ band_length,
+ codebook,
+ mask_enabled,
+ &(q_formatLeft[tot_sfb]),
+ &(q_formatRight[tot_sfb]),
+ &(pCoefLeft[band_start]),
+ &(pCoefRight[band_start]));
+
+ MODIFYING
+ pCoefRightt[band_start]
+ q_formatRight[tot_sfb]
+ RETURNING
+ NONE
+
+ ENDIF
+
+ band_start = band_stop;
+
+ tot_sfb = tot_sfb + 1;
+
+ ENDFOR
+
+ coef_per_win = coef_per_win * (wins_in_group);
+
+ wins_in_group = wins_in_group - 1;
+
+ tot_sfb = tot_sfb + sfb_per_win * wins_in_group;
+ pFactorsRight = pFactorsRight + sfb_per_win * wins_in_group;
+ pFactorsLeft = pFactorsLeft + sfb_per_win * wins_in_group;
+
+ pCoefRight = pCoefRight + coef_per_win;
+ pCoefLeft = pCoefLeft + coef_per_win;
+
+ window_start = partition;
+
+ WHILE (partition < pFrameInfo->num_win);
+
+ return;
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "pns_intensity_right.h"
+#include "e_huffmanconst.h"
+#include "gen_rand_vector.h"
+#include "intensity_right.h"
+#include "pns_corr.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pns_intensity_right(
+ const Int hasmask,
+ const FrameInfo * const pFrameInfo,
+ const Int group[],
+ const Bool mask_map[],
+ const Int codebook_map[],
+ const Int factorsL[],
+ const Int factorsR[],
+ Int sfb_prediction_used[],
+ const Bool ltp_data_present,
+ Int32 coefLeft[],
+ Int32 coefRight[],
+ Int q_formatLeft[MAXBANDS],
+ Int q_formatRight[MAXBANDS],
+ Int32 * const pCurrentSeed)
+{
+
+ Int32 *pCoefRight;
+ Int32 *pWindow_CoefR;
+
+ Int32 *pCoefLeft;
+
+ Int tot_sfb;
+ Int start_indx;
+ Int sfb;
+
+ Int band_length;
+ Int band_start;
+ Int band_stop;
+ Int coef_per_win;
+
+ Int codebook;
+ Int partition;
+ Int window_start;
+
+ Int sfb_per_win;
+ Int wins_in_group;
+ Int win_indx;
+
+ const Int16 *pBand;
+ const Int *pFactorsLeft = factorsL;
+ const Int *pFactorsRight = factorsR;
+ const Int *pCodebookMap = codebook_map;
+ const Int *pGroup = group;
+ const Bool *pMaskMap = mask_map;
+
+ Bool mask_enabled;
+
+ pCoefRight = coefRight;
+ pCoefLeft = coefLeft;
+
+ window_start = 0;
+ tot_sfb = 0;
+ start_indx = 0;
+
+ /*
+ * Each window in the frame should have the same number of coef's,
+ * so coef_per_win is constant in all the loops
+ */
+ coef_per_win = pFrameInfo->coef_per_win[0];
+
+ /*
+ * Because the number of scalefactor bands per window should be
+ * constant for each frame, sfb_per_win can be determined outside
+ * of the loop.
+ *
+ * For 44.1 kHz sampling rate sfb_per_win = 14 for short windows
+ * sfb_per_win = 49 for long windows
+ */
+
+ sfb_per_win = pFrameInfo->sfb_per_win[0];
+
+ do
+ {
+ pBand = pFrameInfo->win_sfb_top[window_start];
+
+ /*----------------------------------------------------------
+ Partition is equal to the first window in the next group
+
+ { Group 0 }{ Group 1 }{ Group 2 }{Group 3}
+ [win 0][win 1][win 2][win 3][win 4][win 5][win 6][win 7]
+
+ pGroup[0] = 2
+ pGroup[1] = 5
+ pGroup[2] = 7
+ pGroup[3] = 8
+ -----------------------------------------------------------*/
+ partition = *(pGroup++);
+
+ band_start = 0;
+
+ wins_in_group = (partition - window_start);
+
+ for (sfb = sfb_per_win; sfb > 0; sfb--)
+ {
+ /* band is offset table, band_stop is last coef in band */
+ band_stop = *(pBand++);
+
+ codebook = *(pCodebookMap++);
+
+ mask_enabled = *(pMaskMap++);
+
+ /*
+ * When a tool utilizing sfb is found, apply the correct tool
+ * to that sfb in each window in the group
+ *
+ * Example... sfb[3] == NOISE_HCB
+ *
+ * [ Group 1 ]
+ * [win 0 ][win 1 ]
+ * [0][1][2][X][4][5][6][7][0][1][2][X][4][5][6][7]
+ *
+ * The for(sfb) steps through the sfb's 0-7 in win 0.
+ *
+ * Finding sfb[3]'s codebook == NOISE_HCB, the code
+ * steps through all the windows in the group (they share
+ * the same scalefactors) and replaces that sfb with noise.
+ */
+
+ /*
+ * Experimental results suggest that ms_synt is the most
+ * commonly used tool, so check for it first.
+ *
+ */
+
+ band_length = band_stop - band_start;
+
+ if (codebook == NOISE_HCB)
+ {
+ sfb_prediction_used[tot_sfb] &= ltp_data_present;
+
+ if (sfb_prediction_used[tot_sfb] == FALSE)
+ {
+ /*
+ * The branch and the logical AND interact in the
+ * following manner...
+ *
+ * mask_enabled == 0 hasmask == X -- gen_rand_vector
+ * mask_enabled == 1 hasmask == 1 -- pns_corr
+ * mask_enabled == 0 hasmask == 1 -- gen_rand_vector
+ * mask_enabled == 1 hasmask == 2 -- gen_rand_vector
+ * mask_enabled == 0 hasmask == 2 -- gen_rand_vector
+ */
+
+ mask_enabled &= hasmask;
+
+ if (mask_enabled == FALSE)
+ {
+ pWindow_CoefR = &(pCoefRight[band_start]);
+
+ /*
+ * Step through all the windows in this group,
+ * replacing this band in each window's
+ * spectrum with random noise
+ */
+ start_indx = tot_sfb;
+
+ for (win_indx = wins_in_group;
+ win_indx > 0;
+ win_indx--)
+ {
+
+ /* generate random noise */
+ q_formatRight[start_indx] =
+ gen_rand_vector(
+ pWindow_CoefR,
+ band_length,
+ pCurrentSeed,
+ *(pFactorsRight));
+
+ pWindow_CoefR += coef_per_win;
+
+ start_indx += sfb_per_win;
+ }
+
+ }
+ else
+ {
+ pns_corr(
+ (*(pFactorsRight) -
+ *(pFactorsLeft)),
+ coef_per_win,
+ sfb_per_win,
+ wins_in_group,
+ band_length,
+ q_formatLeft[tot_sfb],
+ &(q_formatRight[tot_sfb]),
+ &(pCoefLeft[band_start]),
+ &(pCoefRight[band_start]));
+
+ } /* if (mask_map == FALSE) */
+
+ } /* if (sfb_prediction_used[tot_sfb] == FALSE) */
+
+ } /* if (codebook == 0) */
+ else if (codebook >= INTENSITY_HCB2)
+ {
+ /*
+ * The logical AND flags the inversion of intensity
+ * in the following manner.
+ *
+ * mask_enabled == X hasmask == 0 -- DO NOT INVERT
+ * mask_enabled == 0 hasmask == X -- DO NOT INVERT
+ * mask_enabled == 1 hasmask == 1 -- DO INVERT
+ * mask_enabled == 0 hasmask == 1 -- DO NOT INVERT
+ * mask_enabled == 1 hasmask == 2 -- DO NOT INVERT
+ * mask_enabled == 0 hasmask == 2 -- DO NOT INVERT
+ */
+
+ mask_enabled &= hasmask;
+
+ intensity_right(
+ *(pFactorsRight),
+ coef_per_win,
+ sfb_per_win,
+ wins_in_group,
+ band_length,
+ codebook,
+ mask_enabled,
+ &(q_formatLeft[tot_sfb]),
+ &(q_formatRight[tot_sfb]),
+ &(pCoefLeft[band_start]),
+ &(pCoefRight[band_start]));
+
+ } /* END else codebook must be INTENSITY_HCB or ... */
+
+ band_start = band_stop;
+
+ tot_sfb++;
+
+ pFactorsLeft++;
+ pFactorsRight++;
+
+ } /* for (sfb) */
+
+ /*
+ * Increment pCoefRight and pCoefLeft by
+ * coef_per_win * the number of windows
+ */
+
+ pCoefRight += coef_per_win * wins_in_group;
+ pCoefLeft += coef_per_win * wins_in_group--;
+
+ /*
+ * Increase tot_sfb by sfb_per_win times the number of windows minus 1.
+ * The minus 1 comes from the fact that tot_sfb is already pointing
+ * to the first sfb in the 2nd window of the group.
+ */
+ tot_sfb += sfb_per_win * wins_in_group;
+
+ pFactorsRight += sfb_per_win * wins_in_group;
+ pFactorsLeft += sfb_per_win * wins_in_group;
+
+ window_start = partition;
+
+ }
+ while (partition < pFrameInfo->num_win);
+
+ /* pFrameInfo->num_win = 1 for long windows, 8 for short_windows */
+
+ return;
+
+} /* pns_intensity_right() */
+
+
diff --git a/media/libstagefright/codecs/aacdec/pns_intensity_right.h b/media/libstagefright/codecs/aacdec/pns_intensity_right.h
new file mode 100644
index 0000000..7b6f79f
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pns_intensity_right.h
@@ -0,0 +1,106 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pns_intensity_right.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Add hasmask parameter
+
+ Description: Changed name to from right_ch_sfb_tools_ms to intensity_right
+ to more correct reflect the purpose of the function.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file contains the function declaration for
+ pns_intensity_right.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PNS_INTENSITY_RIGHT_H
+#define PNS_INTENSITY_RIGHT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_frameinfo.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+void pns_intensity_right(
+ const Int hasmask,
+ const FrameInfo * const pFrameInfo,
+ const Int group[],
+ const Bool mask_map[],
+ const Int codebook_map[],
+ const Int factorsL[],
+ const Int factorsR[],
+ Int sfb_prediction_used[],
+ const Bool ltp_data_present,
+ Int32 spectralCoefLeft[],
+ Int32 spectralCoefRight[],
+ Int q_formatLeft[MAXBANDS],
+ Int q_formatRight[MAXBANDS],
+ Int32 * const pCurrentSeed);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/pns_left.cpp b/media/libstagefright/codecs/aacdec/pns_left.cpp
new file mode 100644
index 0000000..2446de2
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pns_left.cpp
@@ -0,0 +1,431 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+ Pathname: pns_left.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Brought code in-line with PV standards.
+ Merged PNS and Intensity blocks into one function.
+ Modified routine to interface with a fixed-point implementation.
+ Modified variable names for clarity.
+ Improved for-loop structure that was previously checking
+ the codebook used in each scale factor band multiple times.
+
+ Description: Added some comments for clarity.
+
+ Description: Changed strategy for q-format. Q-format for SFBs should not
+ be grouped.
+
+ Description: Function had to be modified to obey new interpretation of the
+ sfb_prediction_used flag. LTP takes precedence, and PNS should not be
+ executed when a collision occurs between these two tools.
+
+ Description:
+ (1) Added flag "ltp_data_present"
+ (2) Where feasible, I updated the code to resemble right_ch_sfb_tools_ms.c
+ Just for conformance, readability.
+
+ Description: Added include file - "e_huffmanconst.h"
+
+ Description: The same "Factors" pointer indexing problem that existed in
+ right_ch_sfb_tools_ms also existed here in pns_left.c
+
+ Description: Modified how groups and windows are handled, as the multigroup
+ case was not correct
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ const FrameInfo *pFrameInfo = Pointer to structure that holds
+ information about each group.
+ (long block flag,
+ number of windows,
+ scalefactor bands per group, etc.)
+
+ const Int group[] = Array that contains indexes of the
+ the first window in the next group.
+
+ const Int codebook_map[] = Array that denotes which Huffman
+ codebook was used for the encoding
+ of each scalefactor band.
+
+ const Int factors[] = Array of scalefactors
+
+ Int sfb_prediction_used[] = Flag that denotes the activation
+ of long term prediction on a sfb
+ basis.
+
+ Bool ltp_data_present = Flag that denotes whether LTP
+ is active for the entire frame. If
+ this flag is FALSE,
+ sfb_prediction_used is garbage.
+
+ Int32 spectral_coef[] = Array of pointers pointing to the
+ spectral coef's for the LEFT channel.
+
+ Int q_format[] = Q-format for the information
+ pointed to by spectral_coef.
+ Indexed by scalefactor band.
+
+ Int32 *pCurrentSeed = Pointer to the current seed for the
+ random number generator.
+ (gen_rand_vector)
+
+ Local Stores/Buffers/Pointers Needed:
+
+ Global Stores/Buffers/Pointers Needed:
+
+ Outputs:
+
+ Pointers and Buffers Modified:
+ Int32 spectral_coef[] = Contains the new spectral information
+
+ Local Stores Modified:
+
+ Global Stores Modified:
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ The function steps through each scalefactor band in the group, and
+ checks for the use of Huffman codebook NOISE_HCB.
+
+ When a SFB utilizing NOISE_HCB is detected, the band in every window in the
+ group has its spectral information filled with scaled random data.
+
+ The scaled random data is generated by the function gen_rand_vector.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This module shall replace bands that were encoded with the Huffman codebook
+ NOISE_HCB with random noise as returned from gen_rand_vector(). The result
+ shall be perceptually indistinguishable from the result obtained by the
+ ISO decoder.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.5.5 Figures
+ Subpart 4.6.2 ScaleFactors
+ Subpart 4.6.12 Perceptual Noise Substituion (PNS)
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ pFirst_Window_Coefs = spectral_coef;
+
+ window_start = 0;
+
+ tot_sfb = 0;
+
+ DO
+
+ num_bands = pFrameInfo->sfb_per_win[window_start];
+ pBand = pFrameInfo->win_sfb_top[window_start];
+
+ partition = *(pGroup);
+ pGroup = pGroup + 1;
+
+ band_start = 0;
+
+ coef_per_win = pFrameInfo->coef_per_win[window_start];
+
+ wins_in_group = (partition - window_start);
+
+ FOR (sfb = num_bands; sfb > 0; sfb--)
+
+ band_stop = *pBand;
+ pBand = pBand + 1;
+
+ IF (*(pCodebookMap++) == NOISE_HCB )
+
+ tempInt = sfb_prediction_used[tot_sfb] AND ltp_data_present;
+
+ IF (tempInt == FALSE)
+
+ pWindow_Coef = pFirst_Window_Coefs + band_start;
+
+ band_length = (band_stop - band_start);
+
+ start_indx = tot_sfb;
+
+ tempInt = *(pFactors);
+
+ FOR (win_indx = wins_in_group; win_indx > 0; win_indx--)
+
+ CALL gen_rand_vector( pWindow_CoefR,
+ band_length,
+ pCurrentSeed,
+ tempInt);
+
+ MODIFYING pWindow_CoefR = scaled random noise
+ pCurrentSeed = current state of the random
+ noise generator.
+
+ RETURNING q_format[start_indx] = q-format for this sfb.
+
+ pWindow_Coef = pWindow_Coef + coef_per_win;
+
+ start_indx = start_indx +
+ pFrameInfo->sfb_per_win[win_indx];
+
+ ENDFOR
+
+ ENDIF
+
+ ENDIF
+
+ band_start = band_stop;
+
+ tot_sfb = tot_sfb + 1;
+
+ pFactors = pFactors + 1;
+
+ ENDFOR
+
+ coef_per_win = coef_per_win * wins_in_group;
+ wins_in_group = wins_in_group - 1;
+
+ tot_sfb = tot_sfb + num_bands * wins_in_group;
+ pFactors = pFactors + num_bands * wins_in_group;
+
+ pFirst_Window_Coefs = pFirst_Window_Coefs + coef_per_win;
+
+ window_start = partition;
+
+ WHILE (partition < pFrameInfo->num_win);
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "pns_left.h"
+#include "e_huffmanconst.h"
+#include "gen_rand_vector.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pns_left(
+ const FrameInfo *pFrameInfo,
+ const Int group[],
+ const Int codebook_map[],
+ const Int factors[],
+ const Int sfb_prediction_used[],
+ const Bool ltp_data_present,
+ Int32 spectral_coef[],
+ Int q_format[],
+ Int32 *pCurrentSeed)
+{
+
+ Int tot_sfb;
+ Int start_indx;
+
+ Int sfb;
+ Int band_stop;
+
+ const Int16 *pBand;
+
+ const Int *pCodebookMap = &(codebook_map[0]);
+ const Int *pGroup = &(group[0]);
+ const Int *pFactors = &(factors[0]);
+
+ Int tempInt;
+ Int32 *pWindow_Coef;
+
+
+ Int32 *spec;
+
+ Int partition;
+ Int win_indx;
+
+ tot_sfb = 0;
+
+ spec = spectral_coef;
+
+ /* PNS goes by group */
+ win_indx = 0;
+ partition = 0;
+ do
+ {
+ Int num_bands = pFrameInfo->sfb_per_win[partition];
+ pBand = pFrameInfo->win_sfb_top[partition];
+
+ /*----------------------------------------------------------
+ Partition is equal to the first window in the next group
+
+ { Group 0 }{ Group 1 }{ Group 2 }{Group 3}
+ [win 0][win 1][win 2][win 3][win 4][win 5][win 6][win 7]
+
+ pGroup[0] = 2
+ pGroup[1] = 5
+ pGroup[2] = 7
+ pGroup[3] = 8
+ -----------------------------------------------------------*/
+
+ partition = *pGroup++; /* partition = index of last sbk in group */
+
+ do
+ {
+ Int band_start = 0;
+ for (sfb = 0; sfb < num_bands; sfb++)
+ {
+ band_stop = pBand[sfb]; /* band is offset table, band_stop is last coef in band */
+
+ Int band_length = band_stop - band_start;
+ if (pCodebookMap[sfb] == NOISE_HCB)
+ {
+
+ tempInt = sfb_prediction_used[tot_sfb] & ltp_data_present;
+
+ if (tempInt == FALSE)
+ {
+ /* generate random noise */
+ pWindow_Coef = spec + band_start;
+
+ tempInt = pFactors[sfb];
+
+ start_indx = tot_sfb++;
+
+ /* reconstruct noise substituted values */
+ /* generate random noise */
+
+ q_format[start_indx] = gen_rand_vector(pWindow_Coef,
+ band_length,
+ pCurrentSeed,
+ tempInt);
+
+ } /* if (sfb_prediction_used[tot_sfb] == FALSE) */
+
+ } /* if (*(pCodebookMap++) == NOISE_HCB) */
+ else
+ {
+ tot_sfb ++; /* update absolute sfb counter */
+ }
+
+ band_start = band_stop;
+
+ } /* for (sfb) */
+
+ spec += pFrameInfo->coef_per_win[win_indx++];
+ pFactors += num_bands;
+
+ }
+ while (win_indx < partition);
+
+ pCodebookMap += pFrameInfo->sfb_per_win[win_indx-1];
+
+ }
+ while (partition < pFrameInfo->num_win);
+
+
+ return;
+
+} /* pns */
diff --git a/media/libstagefright/codecs/aacdec/pns_left.h b/media/libstagefright/codecs/aacdec/pns_left.h
new file mode 100644
index 0000000..c44b13c
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pns_left.h
@@ -0,0 +1,113 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pns_left.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Removed #defines of LEFT and RIGHT, and the extra include
+ file "e_huffmanconst.h"
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Contains the function definition for pns_left.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PNS_LEFT_H
+#define PNS_LEFT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_frameinfo.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void pns_left(
+ const FrameInfo *pFrameInfo,
+ const Int group[],
+ const Int codebook_map[],
+ const Int factors[],
+ const Int sfb_prediction_used[],
+ const Bool ltp_data_present,
+ Int32 spectral_coef[],
+ Int q_format[],
+ Int32 *pCurrentSeed);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/aacdec/ps_all_pass_filter_coeff.cpp b/media/libstagefright/codecs/aacdec/ps_all_pass_filter_coeff.cpp
new file mode 100644
index 0000000..48432f8
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_all_pass_filter_coeff.cpp
@@ -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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Filename: ps_all_pass_filter_coeff.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Decorrelation is achieved by means of all-pass filtering
+
+
+ _______ ________
+ | | _______ | |
+ ->|Hybrid | LF ---- | |->| Hybrid |-->
+ | Anal. | | | | | Synth | QMF -> L
+ ------- o----------------------->| | -------- Synth
+QMF | s_k(n) |Stereo |-------------->
+Anal. -------------------------->| |
+ _______ | | | | ________
+ | | HF --o | ----------- |Process| | |
+ ->| Delay | | ->| |-------->| |->| Hybrid |-->
+ ------- | |decorrelate| d_k(n) | | | Synth | QMF -> R
+ ---->| |-------->| | -------- Synth
+ ----------- |_______|-------------->
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+
+#include "pv_audio_type_defs.h"
+#include "s_ps_dec.h"
+#include "ps_all_pass_filter_coeff.h"
+#include "ps_all_pass_fract_delay_filter.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+const Int16 aRevLinkDecaySerCoeff[NO_ALLPASS_CHANNELS][NO_SERIAL_ALLPASS_LINKS] =
+{
+
+
+ { Qfmt15(0.74915491616071f), Qfmt15(0.64942584030892f), Qfmt15(0.56297290849050f) },
+ { Qfmt15(0.71658296328416f), Qfmt15(0.62118993420853f), Qfmt15(0.53849582551265f) },
+ { Qfmt15(0.68401101040761f), Qfmt15(0.59295402810815f), Qfmt15(0.51401874253480f) },
+ { Qfmt15(0.65143905753106f), Qfmt15(0.56471812200776f), Qfmt15(0.97908331911390f) }, /* 3 */
+ { Qfmt15(0.61886710465450f), Qfmt15(0.53648221590737f), Qfmt15(0.93012915315822f) },
+ { Qfmt15(0.58629515177795f), Qfmt15(0.50824630980698f), Qfmt15(0.88117498720252f) },
+ { Qfmt15(0.55372319890140f), Qfmt15(0.48001040370660f), Qfmt15(0.83222082124682f) },
+ { Qfmt15(0.52115124602484f), Qfmt15(0.45177449760621f), Qfmt15(0.78326665529112f) },
+ { Qfmt15(0.48857929314829f), Qfmt15(0.42353859150582f), Qfmt15(0.73431248933542f) },
+ { Qfmt15(0.45600734027174f), Qfmt15(0.39530268540543f), Qfmt15(0.68535832337974f) },
+ { Qfmt15(0.42343538739519f), Qfmt15(0.36706677930504f), Qfmt15(0.63640415742404f) },
+ { Qfmt15(0.39086343451863f), Qfmt15(0.33883087320466f), Qfmt15(0.58744999146834f) },
+ { Qfmt15(0.35829148164208f), Qfmt15(0.31059496710427f), Qfmt15(0.53849582551265f) },
+ { Qfmt15(0.32571952876553f), Qfmt15(0.28235906100388f), Qfmt15(0.48954165955695f) },
+ { Qfmt15(0.29314757588898f), Qfmt15(0.25412315490349f), Qfmt15(0.44058749360126f) },
+ { Qfmt15(0.26057562301242f), Qfmt15(0.22588724880310f), Qfmt15(0.39163332764556f) },
+ { Qfmt15(0.22800367013587f), Qfmt15(0.19765134270272f), Qfmt15(0.34267916168986f) },
+ { Qfmt15(0.19543171725932f), Qfmt15(0.16941543660233f), Qfmt15(0.29372499573418f) },
+ { Qfmt15(0.16285976438276f), Qfmt15(0.14117953050194f), Qfmt15(0.24477082977848f) },
+ { Qfmt15(0.13028781150621f), Qfmt15(0.11294362440155f), Qfmt15(0.19581666382278f) },
+ { Qfmt15(0.09771585862966f), Qfmt15(0.08470771830116f), Qfmt15(0.14686249786708f) },
+ { Qfmt15(0.06514390575311f), Qfmt15(0.05647181220078f), Qfmt15(0.09790833191140f) },
+ { Qfmt15(0.03257195287655f), Qfmt15(0.02823590610039f), Qfmt15(0.04895416595570f) }
+
+};
+
+
+
+
+
+const Char groupBorders[NO_IID_GROUPS + 1] =
+{
+ 4, 5, 0, 1, 2, 3, 7, 6, 8, 9, 3, 4,
+ 5, 6, 7, 8, 9, 11, 14, 18, 23, 35, 64
+};
+
+const Char bins2groupMap[NO_IID_GROUPS] =
+{
+ 1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
+};
+
+
+
+
+/*
+ * q_phi = 0.39
+ *
+ * cos(pi*([3:22]+0.5)*q_phi)
+ */
+
+
+/*
+ * sin(-pi*([3:22]+0.5)*q_phi)
+ */
+
+
+const Int32 aFractDelayPhaseFactor[NO_QMF_ALLPASS_CHANNELS] =
+{
+ 0xCB5474A9, 0x5BEC5914, 0x72F3C7B0, 0xF1F480C6, 0x8389E21E,
+ 0xB9BA6AFC, 0x4CDB665C, 0x7A57DA5D, 0x06088024, 0x89BECF04,
+ 0xA9DB5EAC, 0x3BE5711F, 0x7EB9EDF7, 0x19F582A9, 0x92DDBD1F,
+ 0x9C1B5008, 0x29767919, 0x7FFC0203, 0x2D3F8843, 0x9EABACDF
+};
+
+/*
+ * q(m) = { 0.43, 0.75, 0.347 }
+ *
+ * cos(pi*([3:22]+0.5)*q(m)) cos(pi*([3:22]+0.5)'*q)
+ *
+ * sin(-pi*([3:22]+0.5)*q(m))
+ *
+ */
+
+
+const Int32 aaFractDelayPhaseFactorSerQmf[NO_QMF_ALLPASS_CHANNELS][3] =
+{
+ { 0x02037FFC, 0xCF0489BE, 0x9BFB4FE0 },
+ { 0x7D5719F5, 0xCF047642, 0x18947D9E },
+ { 0x34AD8B57, 0x7642CF04, 0x7ABF244A },
+ { 0x99A4B325, 0x89BECF04, 0x58EFA3F1 },
+ { 0x9EAB5321, 0x30FC7642, 0xD77E8694 },
+ { 0x3BE5711F, 0x30FC89BE, 0x819CEBC7 },
+ { 0x7B77DE39, 0x89BE30FC, 0xB3A166B8 },
+ { 0xF9F88024, 0x764230FC, 0x37C57336 },
+ { 0x81E8E9FE, 0xCF0489BE, 0x7FF103D2 },
+ { 0xCF047642, 0xCF047642, 0x3E8B9052 },
+ { 0x68B9499A, 0x7642CF04, 0xB9E594E8 },
+ { 0x5EACA9DB, 0x89BECF04, 0x80A00CA5 },
+ { 0xC09590D1, 0x30FC7642, 0xD05276CA },
+ { 0x85A925A3, 0x30FC89BE, 0x53486134 },
+ { 0x0A0B7F9B, 0x89BE30FC, 0x7CB2E319 },
+ { 0x7EB91209, 0x764230FC, 0x20078412 },
+ { 0x2D3F8843, 0xCF0489BE, 0xA0ECAA4D },
+ { 0x9504B9BA, 0xCF047642, 0x880D2CAE },
+ { 0xA4145914, 0x7642CF04, 0xF0287F04 },
+ { 0x42E16D23, 0x89BECF04, 0x694C48C7 }
+};
+
+/*
+ * Fractional delay vector
+ *
+ * phi_fract(k) = exp(-j*pi*q_phi*f_center(k)) 0<= k <= SUBQMF_GROUPS
+ *
+ * q_phi = 0.39
+ * f_center(k) frequency vector
+ *
+ *
+ * f_center(k) = {0.5/4, 1.5/4, 2.5/4, 3.5/4,
+ * -1.5/4, -0.5/4,
+ * 3.5/2, 2.5/2, 4.5/2, 5.5/2};
+ */
+
+
+
+const Int32 aFractDelayPhaseFactorSubQmf[SUBQMF_GROUPS] =
+{
+ 0x7E80EC79, 0x72BAC73D, 0x5C45A749, 0x3D398F97, 0x72BA38C3,
+ 0x7E801387, 0xBA919478, 0x05068019, 0x895DCFF2, 0x834E1CE7,
+};
+
+
+
+
+
+/*
+ * Fractional delay length matrix
+ *
+ * Q_fract(k,m) = exp(-j*pi*q(m)*f_center(k))
+ *
+ * q(m) = { 0.43, 0.75, 0.347 }
+ * f_center(k) frequency vector
+ *
+ *
+ * f_center(k) = { 0.5/4, 1.5/4, 2.5/4, 3.5/4,
+ * -1.5/4, -0.5/4,
+ * 3.5/2, 2.5/2, 4.5/2, 5.5/2};
+ */
+
+const Int32 aaFractDelayPhaseFactorSerSubQmf[SUBQMF_GROUPS][3] =
+{
+
+ { 0x7E2EEA7D, 0x7A7DDAD8, 0x7ED0EE9D },
+ { 0x6FEDC1E5, 0x51349D0E, 0x7574CD1E },
+ { 0x5506A052, 0x0C8C809E, 0x636CAF62 },
+ { 0x3085898D, 0xC3A98F1D, 0x4A0D9799 },
+ { 0x6FED3E1B, 0x513462F2, 0x757432E2 },
+ { 0x7E2E1583, 0x7A7D2528, 0x7ED01163 },
+ { 0xA4C8A634, 0xB8E36A6E, 0xD5AF8732 },
+ { 0xF0F580E3, 0x8276E707, 0x1A7382C3 },
+ { 0x80ABF2F4, 0x471D6A6E, 0x9D2FAEA4 },
+ { 0x9478456F, 0x7D8AE707, 0x8152EDAB }
+};
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_all_pass_filter_coeff.h b/media/libstagefright/codecs/aacdec/ps_all_pass_filter_coeff.h
new file mode 100644
index 0000000..0358acb
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_all_pass_filter_coeff.h
@@ -0,0 +1,105 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_all_pass_filter_coeff.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for all pass filter coefficients
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_ALL_PASS_FILTER_COEFF_H
+#define PS_ALL_PASS_FILTER_COEFF_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_ps_dec.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+extern const Char groupBorders[NO_IID_GROUPS + 1];
+extern const Int16 aRevLinkDecaySerCoeff[NO_ALLPASS_CHANNELS][NO_SERIAL_ALLPASS_LINKS];
+extern const Int32 aRevLinkDelaySer[];
+extern const Int16 aFractDelayPhaseFactorReQmf[NO_QMF_ALLPASS_CHANNELS];
+extern const Int16 aFractDelayPhaseFactorImQmf[NO_QMF_ALLPASS_CHANNELS];
+/* the old center frequencies (found in "else") were too small (factor 1/2) */
+extern const Int16 aFractDelayPhaseFactorReSubQmf[SUBQMF_GROUPS];
+extern const Int16 aFractDelayPhaseFactorImSubQmf[SUBQMF_GROUPS];
+extern const Int32 aFractDelayPhaseFactorSubQmf[SUBQMF_GROUPS];
+extern const Int32 aFractDelayPhaseFactor[NO_QMF_ALLPASS_CHANNELS];
+extern const Int32 aaFractDelayPhaseFactorSerQmf[NO_QMF_ALLPASS_CHANNELS][3];
+extern const Int32 aaFractDelayPhaseFactorSerSubQmf[SUBQMF_GROUPS][3];
+extern const Char bins2groupMap[NO_IID_GROUPS];
+extern const Int32 aaFractDelayPhaseFactorSerReQmf[NO_QMF_ALLPASS_CHANNELS][3];
+extern const Int32 aaFractDelayPhaseFactorSerImQmf[NO_QMF_ALLPASS_CHANNELS][3];
+extern const Int32 aaFractDelayPhaseFactorSerReSubQmf[SUBQMF_GROUPS][3];
+extern const Int32 aaFractDelayPhaseFactorSerImSubQmf[SUBQMF_GROUPS][3];
+
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_ALL_PASS_FILTER_COEFF_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_all_pass_fract_delay_filter.cpp b/media/libstagefright/codecs/aacdec/ps_all_pass_fract_delay_filter.cpp
new file mode 100644
index 0000000..81761a6
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_all_pass_fract_delay_filter.cpp
@@ -0,0 +1,391 @@
+/* ------------------------------------------------------------------
+ * 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: ps_all_pass_fract_delay_filter.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Decorrelation
+ Decorrelation is achieved by means of all-pass filtering and delaying
+ Sub-band samples s_k(n) are converted into de-correlated sub-bands samples
+ d_k(n). k index for frequency, n time index
+
+
+ _______ ________
+ | | _______ | |
+ ->|Hybrid | LF ---- | |->| Hybrid |-->
+ | Anal. | | | | | Synth | QMF -> L
+ ------- o----------------------->| | -------- Synth
+QMF | s_k(n) |Stereo |-------------->
+Anal. -------------------------->| |
+ _______ | | | | ________
+ | | HF --o | ----------- |Process| | |
+ ->| Delay | | ->| |-------->| |->| Hybrid |-->
+ ------- | |decorrelate| d_k(n) | | | Synth | QMF -> R
+ ---->| |-------->| | -------- Synth
+ ----------- |_______|-------------->
+
+
+ Delay is introduced to compensate QMF bands not passed through Hybrid
+ Analysis
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+
+#include "pv_audio_type_defs.h"
+#include "ps_decorrelate.h"
+#include "aac_mem_funcs.h"
+#include "ps_all_pass_filter_coeff.h"
+#include "ps_pwr_transient_detection.h"
+#include "ps_all_pass_fract_delay_filter.h"
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*
+ * For lower subbands
+ * Apply all-pass filtering
+ *
+ */
+
+
+void ps_all_pass_fract_delay_filter_type_I(UInt32 *delayBufIndex,
+ Int32 sb_delay,
+ const Int32 *ppFractDelayPhaseFactorSer,
+ Int32 ***pppRealDelayRBufferSer,
+ Int32 ***pppImagDelayRBufferSer,
+ Int32 *rIn,
+ Int32 *iIn)
+{
+
+ Int32 cmplx;
+ Int16 rTmp0;
+ Int32 rTmp;
+ Int32 iTmp;
+ Int32 *pt_rTmp;
+ Int32 *pt_iTmp;
+
+
+
+ /*
+ * All pass filters
+ * 2
+ * ___ Q_fract(k,m)*z^(-d(m)) - a(m)*g_decay_slope(k)
+ * z^(-2)*phi_fract(k)* | | ------------------------------------------------
+ * m=0 1 - a(m)*g_decay_slope(k)*Q_fract(k,m)*z^(-d(m))
+ *
+ *
+ * Fractional delay matrix:
+ *
+ * Q_fract(k,m) = exp(-j*pi*q(m)*f_center(k)) 0<= k <= SUBQMF_GROUPS
+ *
+ * Vectors: a(m), q(m), d(m) are constants
+ *
+ * m m 0 1 2
+ * -------------------------------
+ * delay length d(m) == 3 4 5 (Fs > 32 KHz)
+ * fractional delay length q(m) == 0.43 0.75 0.347
+ * filter coefficient a(m) == 0.65144 0.56472 0.48954
+ *
+ * g_decay_slope(k) is given
+ */
+
+
+ Int32 tmp_r;
+ Int32 tmp_i;
+
+ pt_rTmp = &pppRealDelayRBufferSer[0][*(delayBufIndex)][sb_delay];
+ pt_iTmp = &pppImagDelayRBufferSer[0][*(delayBufIndex++)][sb_delay];
+
+ cmplx = *(ppFractDelayPhaseFactorSer++); /* Q_fract(k,m) */
+ tmp_r = *pt_rTmp << 1;
+ tmp_i = *pt_iTmp << 1;
+
+ rTmp = cmplx_mul32_by_16(tmp_r, -tmp_i, cmplx);
+ rTmp0 = Qfmt15(0.65143905753106f);
+ iTmp = cmplx_mul32_by_16(tmp_i, tmp_r, cmplx);
+
+
+ iTmp = fxp_mac32_by_16(-*iIn << 1, rTmp0, iTmp); /* Q_fract(k,m)*y(n-1) - a(m)*g_decay_slope(k)*x(n) */
+ *pt_iTmp = fxp_mac32_by_16(iTmp << 1, rTmp0, *iIn); /* y(n) = x(n) + a(m)*g_decay_slope(k)*( Q_fract(k,m)*y(n-1) - a(m)*g_decay_slope(k)*x(n)) */
+ *iIn = iTmp;
+
+ rTmp = fxp_mac32_by_16(-*rIn << 1, rTmp0, rTmp);
+ *pt_rTmp = fxp_mac32_by_16(rTmp << 1, rTmp0, *rIn);
+
+ *rIn = rTmp;
+
+ pt_rTmp = &pppRealDelayRBufferSer[1][*(delayBufIndex)][sb_delay];
+ pt_iTmp = &pppImagDelayRBufferSer[1][*(delayBufIndex++)][sb_delay];
+
+
+
+ cmplx = *(ppFractDelayPhaseFactorSer++); /* Q_fract(k,m) */
+ tmp_r = *pt_rTmp << 1;
+ tmp_i = *pt_iTmp << 1;
+
+ rTmp = cmplx_mul32_by_16(tmp_r, -tmp_i, cmplx);
+ rTmp0 = Qfmt15(0.56471812200776f);
+ iTmp = cmplx_mul32_by_16(tmp_i, tmp_r, cmplx);
+
+
+ iTmp = fxp_mac32_by_16(-*iIn << 1, rTmp0, iTmp); /* Q_fract(k,m)*y(n-1) - a(m)*g_decay_slope(k)*x(n) */
+ *pt_iTmp = fxp_mac32_by_16(iTmp << 1, rTmp0, *iIn); /* y(n) = x(n) + a(m)*g_decay_slope(k)*( Q_fract(k,m)*y(n-1) - a(m)*g_decay_slope(k)*x(n)) */
+ *iIn = iTmp;
+
+ rTmp = fxp_mac32_by_16(-*rIn << 1, rTmp0, rTmp);
+ *pt_rTmp = fxp_mac32_by_16(rTmp << 1, rTmp0, *rIn);
+ *rIn = rTmp;
+
+ pt_rTmp = &pppRealDelayRBufferSer[2][*(delayBufIndex)][sb_delay];
+ pt_iTmp = &pppImagDelayRBufferSer[2][*(delayBufIndex)][sb_delay];
+
+
+ cmplx = *(ppFractDelayPhaseFactorSer); /* Q_fract(k,m) */
+ tmp_r = *pt_rTmp << 1;
+ tmp_i = *pt_iTmp << 1;
+
+ rTmp = cmplx_mul32_by_16(tmp_r, -tmp_i, cmplx);
+ rTmp0 = Qfmt15(0.97908331911390f);
+ iTmp = cmplx_mul32_by_16(tmp_i, tmp_r, cmplx);
+
+
+ iTmp = fxp_mac32_by_16(-*iIn, rTmp0, iTmp); /* Q_fract(k,m)*y(n-1) - a(m)*g_decay_slope(k)*x(n) */
+ *pt_iTmp = fxp_mac32_by_16(iTmp, rTmp0, *iIn); /* y(n) = x(n) + a(m)*g_decay_slope(k)*( Q_fract(k,m)*y(n-1) - a(m)*g_decay_slope(k)*x(n)) */
+ *iIn = iTmp << 2;
+
+ rTmp = fxp_mac32_by_16(-*rIn, rTmp0, rTmp);
+ *pt_rTmp = fxp_mac32_by_16(rTmp, rTmp0, *rIn);
+ *rIn = rTmp << 2;
+}
+
+
+void ps_all_pass_fract_delay_filter_type_II(UInt32 *delayBufIndex,
+ Int32 sb_delay,
+ const Int32 *ppFractDelayPhaseFactorSer,
+ Int32 ***pppRealDelayRBufferSer,
+ Int32 ***pppImagDelayRBufferSer,
+ Int32 *rIn,
+ Int32 *iIn,
+ Int32 decayScaleFactor)
+{
+
+ Int32 cmplx;
+ Int16 rTmp0;
+ Int32 rTmp;
+ Int32 iTmp;
+ Int32 *pt_rTmp;
+ Int32 *pt_iTmp;
+ const Int16 *pt_delay;
+
+
+
+ /*
+ * All pass filters
+ * 2
+ * ___ Q_fract(k,m)*z^(-d(m)) - a(m)*g_decay_slope(k)
+ * z^(-2)*phi_fract(k)* | | ------------------------------------------------
+ * m=0 1 - a(m)*g_decay_slope(k)*Q_fract(k,m)*z^(-d(m))
+ *
+ *
+ * Fractional delay matrix:
+ *
+ * Q_fract(k,m) = exp(-j*pi*q(m)*f_center(k)) 0<= k <= SUBQMF_GROUPS
+ *
+ * Vectors: a(m), q(m), d(m) are constants
+ *
+ * m m 0 1 2
+ * -------------------------------
+ * delay length d(m) == 3 4 5 (Fs > 32 KHz)
+ * fractional delay length q(m) == 0.43 0.75 0.347
+ * filter coefficient a(m) == 0.65144 0.56472 0.48954
+ *
+ * g_decay_slope(k) is given
+ */
+
+
+ Int32 tmp_r;
+ Int32 tmp_i;
+
+ pt_rTmp = &pppRealDelayRBufferSer[0][*(delayBufIndex)][sb_delay];
+ pt_iTmp = &pppImagDelayRBufferSer[0][*(delayBufIndex++)][sb_delay];
+
+ cmplx = *(ppFractDelayPhaseFactorSer++); /* Q_fract(k,m) */
+ pt_delay = aRevLinkDecaySerCoeff[decayScaleFactor];
+ tmp_r = *pt_rTmp << 1;
+ tmp_i = *pt_iTmp << 1;
+
+ rTmp = cmplx_mul32_by_16(tmp_r, -tmp_i, cmplx);
+ rTmp0 = *(pt_delay++);
+ iTmp = cmplx_mul32_by_16(tmp_i, tmp_r, cmplx);
+
+
+ iTmp = fxp_mac32_by_16(-*iIn << 1, rTmp0, iTmp); /* Q_fract(k,m)*y(n-1) - a(m)*g_decay_slope(k)*x(n) */
+ *pt_iTmp = fxp_mac32_by_16(iTmp << 1, rTmp0, *iIn); /* y(n) = x(n) + a(m)*g_decay_slope(k)*( Q_fract(k,m)*y(n-1) - a(m)*g_decay_slope(k)*x(n)) */
+ *iIn = iTmp;
+
+ rTmp = fxp_mac32_by_16(-*rIn << 1, rTmp0, rTmp);
+ *pt_rTmp = fxp_mac32_by_16(rTmp << 1, rTmp0, *rIn);
+ *rIn = rTmp;
+
+ pt_rTmp = &pppRealDelayRBufferSer[1][*(delayBufIndex)][sb_delay];
+ pt_iTmp = &pppImagDelayRBufferSer[1][*(delayBufIndex++)][sb_delay];
+
+
+ cmplx = *(ppFractDelayPhaseFactorSer++); /* Q_fract(k,m) */
+ tmp_r = *pt_rTmp << 1;
+ tmp_i = *pt_iTmp << 1;
+
+ rTmp = cmplx_mul32_by_16(tmp_r, -tmp_i, cmplx);
+ rTmp0 = *(pt_delay++);
+ iTmp = cmplx_mul32_by_16(tmp_i, tmp_r, cmplx);
+ iTmp = fxp_mac32_by_16(-*iIn << 1, rTmp0, iTmp); /* Q_fract(k,m)*y(n-1) - a(m)*g_decay_slope(k)*x(n) */
+ *pt_iTmp = fxp_mac32_by_16(iTmp << 1, rTmp0, *iIn); /* y(n) = x(n) + a(m)*g_decay_slope(k)*( Q_fract(k,m)*y(n-1) - a(m)*g_decay_slope(k)*x(n)) */
+ *iIn = iTmp;
+
+ rTmp = fxp_mac32_by_16(-*rIn << 1, rTmp0, rTmp);
+ *pt_rTmp = fxp_mac32_by_16(rTmp << 1, rTmp0, *rIn);
+ *rIn = rTmp;
+
+ pt_rTmp = &pppRealDelayRBufferSer[2][*(delayBufIndex)][sb_delay];
+ pt_iTmp = &pppImagDelayRBufferSer[2][*(delayBufIndex)][sb_delay];
+
+
+ cmplx = *(ppFractDelayPhaseFactorSer); /* Q_fract(k,m) */
+ tmp_r = *pt_rTmp << 1;
+ tmp_i = *pt_iTmp << 1;
+
+ rTmp = cmplx_mul32_by_16(tmp_r, -tmp_i, cmplx);
+ rTmp0 = *(pt_delay);
+ iTmp = cmplx_mul32_by_16(tmp_i, tmp_r, cmplx);
+
+
+ iTmp = fxp_mac32_by_16(-*iIn, rTmp0, iTmp); /* Q_fract(k,m)*y(n-1) - a(m)*g_decay_slope(k)*x(n) */
+ *pt_iTmp = fxp_mac32_by_16(iTmp, rTmp0, *iIn); /* y(n) = x(n) + a(m)*g_decay_slope(k)*( Q_fract(k,m)*y(n-1) - a(m)*g_decay_slope(k)*x(n)) */
+ *iIn = iTmp << 2;
+
+ rTmp = fxp_mac32_by_16(-*rIn, rTmp0, rTmp);
+ *pt_rTmp = fxp_mac32_by_16(rTmp, rTmp0, *rIn);
+ *rIn = rTmp << 2;
+
+}
+
+
+
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_all_pass_fract_delay_filter.h b/media/libstagefright/codecs/aacdec/ps_all_pass_fract_delay_filter.h
new file mode 100644
index 0000000..b4e9876
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_all_pass_fract_delay_filter.h
@@ -0,0 +1,117 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_all_pass_fract_delay_filter.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for function ps_all_pass_fract_delay_filter()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_ALL_PASS_FRACT_DELAY_FILTER_H
+#define PS_ALL_PASS_FRACT_DELAY_FILTER_H
+
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define R_SHIFT 29
+#define Q29_fmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+#define Qfmt15(x) (Int16)(x*((Int32)1<<15) + (x>=0?0.5F:-0.5F))
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ void ps_all_pass_fract_delay_filter_type_I(UInt32 *delayBufIndex,
+ Int32 sb_delay,
+ const Int32 *ppFractDelayPhaseFactorSer,
+ Int32 ***pppRealDelayRBufferSer,
+ Int32 ***pppImagDelayRBufferSer,
+ Int32 *rIn,
+ Int32 *iIn);
+
+
+ void ps_all_pass_fract_delay_filter_type_II(UInt32 *delayBufIndex,
+ Int32 sb_delay,
+ const Int32 *ppFractDelayPhaseFactorSer,
+ Int32 ***pppRealDelayRBufferSer,
+ Int32 ***pppImagDelayRBufferSer,
+ Int32 *rIn,
+ Int32 *iIn,
+ Int32 decayScaleFactor);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_ALL_PASS_FRACT_DELAY_FILTER_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_allocate_decoder.cpp b/media/libstagefright/codecs/aacdec/ps_allocate_decoder.cpp
new file mode 100644
index 0000000..ab15651
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_allocate_decoder.cpp
@@ -0,0 +1,341 @@
+/* ------------------------------------------------------------------
+ * 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: ps_allocate_decoder.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Reuses AAC+ HQ right channel, which is not used when PS is enabled
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef HQ_SBR
+
+#ifdef PARAMETRICSTEREO
+
+#include "s_sbr_channel.h"
+#include "aac_mem_funcs.h"
+#include "ps_hybrid_filter_bank_allocation.h"
+#include "s_ps_dec.h"
+#include "ps_all_pass_filter_coeff.h"
+#include "ps_allocate_decoder.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define R_SHIFT 30
+#define Q30_fmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const Int32 aRevLinkDelaySer[] = {3, 4, 5};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int32 ps_allocate_decoder(SBRDECODER_DATA *self,
+ UInt32 noSubSamples)
+{
+ Int32 i, j;
+ Int32 status;
+
+ Int32 *ptr1;
+ Int32 *ptr2;
+ Int32 *ptr3;
+ Int32 *ptr4;
+ Int32 *ptr5;
+ Int32 *ptr6;
+ Int32 *ptr7;
+
+ const Int32 pHybridResolution[] = { HYBRID_8_CPLX,
+ HYBRID_2_REAL,
+ HYBRID_2_REAL
+ };
+
+ STRUCT_PS_DEC *h_ps_dec = self->hParametricStereoDec;
+
+ /* initialisation */
+ h_ps_dec->noSubSamples = noSubSamples;
+
+ h_ps_dec->invNoSubSamples = Q30_fmt(1.0f) / noSubSamples;
+
+ /*
+ * Reuse AAC+ HQ right channel, which is not used when PS is enabled
+ */
+ ptr1 = (Int32 *)(self->SbrChannel[1].frameData.codecQmfBufferReal[0]); /* reuse un-used right channel QMF_FILTER Synthesis buffer */
+
+ ptr2 = (&ptr1[658]); /* reuse un-used right channel QMF_FILTER Synthesis buffer */
+ /* 1162 - 658 = 504
+ * = NO_QMF_ALLPASS_CHANNELS*2 (Re&Im)*( 3 + 4 + 5) + ( 3 + 4 + 5)*2 (Re&Im)
+ */
+
+ ptr3 = (&ptr1[1162]); /* reuse un-used right channel QMF_FILTER Synthesis buffer */
+ /* 1426 - 1162 = 264
+ * = SUBQMF_GROUPS*2 (Re&Im)*( 3 + 4 + 5) + ( 3 + 4 + 5)*2 (Re&Im)
+ */
+
+ ptr4 = (&ptr1[1426]); /* high freq generation buffers */
+
+ ptr5 = (&ptr1[1490]); /* high freq generation buffers */
+
+ ptr6 = (&ptr1[1618]); /* high freq generation buffers */
+
+ ptr7 = (&ptr1[1810]); /* high freq generation buffers */
+
+ /* whole allocation requires 1871 words, sbrQmfBufferImag has 1920 words */
+
+
+ h_ps_dec->aPeakDecayFast = ptr1;
+ ptr1 += NO_BINS;
+
+ h_ps_dec->aPrevNrg = ptr1;
+ ptr1 += NO_BINS;
+
+ h_ps_dec->aPrevPeakDiff = ptr1;
+ ptr1 += NO_BINS;
+
+
+
+ status = ps_hybrid_filter_bank_allocation(&h_ps_dec->hHybrid,
+ NO_QMF_CHANNELS_IN_HYBRID,
+ pHybridResolution,
+ &ptr1);
+ h_ps_dec->mHybridRealLeft = ptr1;
+ ptr1 += SUBQMF_GROUPS;
+
+ h_ps_dec->mHybridImagLeft = ptr1;
+ ptr1 += SUBQMF_GROUPS;
+
+ h_ps_dec->mHybridRealRight = ptr1;
+ ptr1 += SUBQMF_GROUPS;
+
+ h_ps_dec->mHybridImagRight = ptr1;
+ ptr1 += SUBQMF_GROUPS;
+
+
+ h_ps_dec->delayBufIndex = 0;
+
+
+
+ for (i = 0 ; i < NO_DELAY_CHANNELS ; i++) /* 41 */
+ {
+ if (i < SHORT_DELAY_START) /* 12 */
+ {
+ h_ps_dec->aNoSampleDelay[i] = LONG_DELAY;
+ }
+ else
+ {
+ h_ps_dec->aNoSampleDelay[i] = SHORT_DELAY;
+ }
+ }
+
+
+ h_ps_dec->aaRealDelayBufferQmf = (Int32 **)ptr6;
+ ptr6 += NO_QMF_ICC_CHANNELS * sizeof(Int32 *) / sizeof(Int32);
+
+ h_ps_dec->aaImagDelayBufferQmf = (Int32 **)ptr7;
+ ptr7 += NO_QMF_ICC_CHANNELS * sizeof(Int32 *) / sizeof(Int32);
+
+ h_ps_dec->aaRealDelayBufferSubQmf = (Int32 **)ptr1;
+ ptr1 += SUBQMF_GROUPS * sizeof(Int32 *) / sizeof(Int32);
+
+ h_ps_dec->aaImagDelayBufferSubQmf = (Int32 **)ptr1;
+ ptr1 += SUBQMF_GROUPS * sizeof(Int32 *) / sizeof(Int32);
+
+ for (i = 0; i < NO_QMF_ICC_CHANNELS; i++) /* 61 */
+ {
+ int delay;
+
+ if (i < NO_QMF_ALLPASS_CHANNELS) /* 20 */
+ {
+ delay = 2;
+ h_ps_dec->aaRealDelayBufferQmf[i] = (Int32 *)ptr4;
+ ptr4 += delay;
+
+ h_ps_dec->aaImagDelayBufferQmf[i] = (Int32 *)ptr5;
+ ptr5 += delay;
+ }
+ else
+ {
+
+ if (i >= (NO_QMF_ALLPASS_CHANNELS + SHORT_DELAY_START))
+ {
+ delay = SHORT_DELAY;
+ }
+ else
+ {
+ delay = LONG_DELAY;
+ }
+
+ h_ps_dec->aaRealDelayBufferQmf[i] = (Int32 *)ptr1;
+ ptr1 += delay;
+
+ h_ps_dec->aaImagDelayBufferQmf[i] = (Int32 *)ptr1;
+ ptr1 += delay;
+ }
+ }
+
+ for (i = 0; i < SUBQMF_GROUPS; i++)
+ {
+ h_ps_dec->aaRealDelayBufferSubQmf[i] = (Int32 *)ptr1;
+ ptr1 += DELAY_ALLPASS;
+
+ h_ps_dec->aaImagDelayBufferSubQmf[i] = (Int32 *)ptr1;
+ ptr1 += DELAY_ALLPASS;
+
+ }
+
+ for (i = 0 ; i < NO_SERIAL_ALLPASS_LINKS ; i++) /* NO_SERIAL_ALLPASS_LINKS == 3 */
+ {
+
+ h_ps_dec->aDelayRBufIndexSer[i] = 0;
+
+ h_ps_dec->aaaRealDelayRBufferSerQmf[i] = (Int32 **)ptr2;
+ ptr2 += aRevLinkDelaySer[i];
+
+ h_ps_dec->aaaImagDelayRBufferSerQmf[i] = (Int32 **)ptr2;
+ ptr2 += aRevLinkDelaySer[i];
+
+ h_ps_dec->aaaRealDelayRBufferSerSubQmf[i] = (Int32 **)ptr3;
+ ptr3 += aRevLinkDelaySer[i];
+
+ h_ps_dec->aaaImagDelayRBufferSerSubQmf[i] = (Int32 **)ptr3;
+ ptr3 += aRevLinkDelaySer[i];
+
+ for (j = 0; j < aRevLinkDelaySer[i]; j++)
+ {
+ h_ps_dec->aaaRealDelayRBufferSerQmf[i][j] = ptr2;
+ ptr2 += NO_QMF_ALLPASS_CHANNELS; /* NO_QMF_ALLPASS_CHANNELS == 20 */
+
+ h_ps_dec->aaaImagDelayRBufferSerQmf[i][j] = ptr2;
+ ptr2 += NO_QMF_ALLPASS_CHANNELS;
+
+ h_ps_dec->aaaRealDelayRBufferSerSubQmf[i][j] = ptr3;
+ ptr3 += SUBQMF_GROUPS;
+
+ h_ps_dec->aaaImagDelayRBufferSerSubQmf[i][j] = ptr3;
+ ptr3 += SUBQMF_GROUPS;
+
+ }
+ }
+
+
+ for (i = 0; i < NO_IID_GROUPS; i++) /* NO_IID_GROUPS == 22 */
+ {
+ h_ps_dec->h11Prev[i] = Q30_fmt(1.0f);
+ h_ps_dec->h12Prev[i] = Q30_fmt(1.0f);
+ }
+
+
+
+ return status;
+} /*END CreatePsDec*/
+#endif
+
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_allocate_decoder.h b/media/libstagefright/codecs/aacdec/ps_allocate_decoder.h
new file mode 100644
index 0000000..d5f152f
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_allocate_decoder.h
@@ -0,0 +1,94 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_allocate_decoder.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for function ps_allocate_decoder()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_ALLOCATE_DECODER_H
+#define PS_ALLOCATE_DECODER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ Int32 ps_allocate_decoder(SBRDECODER_DATA *self,
+ UInt32 noSubSamples);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_ALLOCATE_DECODER_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_applied.cpp b/media/libstagefright/codecs/aacdec/ps_applied.cpp
new file mode 100644
index 0000000..77fd8a7
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_applied.cpp
@@ -0,0 +1,216 @@
+/* ------------------------------------------------------------------
+ * 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: ps_applied.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Applies Parametric Stereo Tool to a QMF-analized mono signal
+ providing a stereo image as output
+
+
+ _______ ________
+ | | _______ | |
+ ->|Hybrid | LF ---- | |->| Hybrid |-->
+ | Anal. | | | | | Synth | QMF -> L
+ ------- o----------------------->| | -------- Synth
+QMF | s_k(n) |Stereo |-------------->
+Anal. -------------------------->| |
+ _______ | | | | ________
+ | | HF --o | ----------- |Process| | |
+ ->| Delay | | ->| |-------->| |->| Hybrid |-->
+ ------- | |decorrelate| d_k(n) | | | Synth | QMF -> R
+ ---->| |-------->| | -------- Synth
+ ----------- |_______|-------------->
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+#include "aac_mem_funcs.h"
+#include "ps_stereo_processing.h"
+#include "ps_decorrelate.h"
+#include "ps_hybrid_synthesis.h"
+#include "ps_hybrid_analysis.h"
+#include "ps_applied.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void ps_applied(STRUCT_PS_DEC *h_ps_dec,
+ Int32 rIntBufferLeft[][64],
+ Int32 iIntBufferLeft[][64],
+ Int32 *rIntBufferRight,
+ Int32 *iIntBufferRight,
+ Int32 scratch_mem[],
+ Int32 band)
+
+{
+
+ /*
+ * Get higher frequency resolution in the lower QMF subbands
+ * creating sub-subbands
+ */
+ ps_hybrid_analysis(rIntBufferLeft,
+ iIntBufferLeft,
+ h_ps_dec->mHybridRealLeft,
+ h_ps_dec->mHybridImagLeft,
+ h_ps_dec->hHybrid,
+ scratch_mem,
+ band);
+
+ /*
+ * By means of delaying and all-pass filtering, sub-subbands of
+ * left ch. are decorrelate to creates right ch. sub-subbands
+ */
+
+ ps_decorrelate(h_ps_dec,
+ *rIntBufferLeft,
+ *iIntBufferLeft,
+ rIntBufferRight,
+ iIntBufferRight,
+ scratch_mem);
+
+ /*
+ * sub-subbands of left and right ch. are processed according to
+ * stereo clues.
+ */
+
+ ps_stereo_processing(h_ps_dec,
+ *rIntBufferLeft,
+ *iIntBufferLeft,
+ rIntBufferRight,
+ iIntBufferRight);
+
+ /*
+ * Reconstruct stereo signals
+ */
+
+ ps_hybrid_synthesis((const Int32*)h_ps_dec->mHybridRealLeft,
+ (const Int32*)h_ps_dec->mHybridImagLeft,
+ *rIntBufferLeft,
+ *iIntBufferLeft,
+ h_ps_dec->hHybrid);
+
+ ps_hybrid_synthesis((const Int32*)h_ps_dec->mHybridRealRight,
+ (const Int32*)h_ps_dec->mHybridImagRight,
+ rIntBufferRight,
+ iIntBufferRight,
+ h_ps_dec->hHybrid);
+
+}/* END ps_applied */
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_applied.h b/media/libstagefright/codecs/aacdec/ps_applied.h
new file mode 100644
index 0000000..231d9c3
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_applied.h
@@ -0,0 +1,101 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_applied.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for functions ps_applied()
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_APPLIED_H
+#define PS_APPLIED_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_ps_dec.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void ps_applied(STRUCT_PS_DEC *h_ps_dec,
+ Int32 rIntBufferLeft[][64],
+ Int32 iIntBufferLeft[][64],
+ Int32 *rIntBufferRight,
+ Int32 *iIntBufferRight,
+ Int32 scratch_mem[],
+ Int32 band);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_APPLIED_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_bstr_decoding.cpp b/media/libstagefright/codecs/aacdec/ps_bstr_decoding.cpp
new file mode 100644
index 0000000..c7ed60b
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_bstr_decoding.cpp
@@ -0,0 +1,304 @@
+/* ------------------------------------------------------------------
+ * 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: ps_bstr_decoding.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Decodes parametric stereo
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+
+#include "pv_audio_type_defs.h"
+#include "aac_mem_funcs.h"
+#include "ps_bstr_decoding.h"
+#include "ps_decode_bs_utils.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+const Int32 aNoIidBins[3] = {NO_LOW_RES_IID_BINS, NO_IID_BINS, NO_HI_RES_BINS};
+const Int32 aNoIccBins[3] = {NO_LOW_RES_ICC_BINS, NO_ICC_BINS, NO_HI_RES_BINS};
+const Int32 aFixNoEnvDecode[4] = {0, 1, 2, 4};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void ps_bstr_decoding(STRUCT_PS_DEC *ps_dec)
+{
+ UInt32 env;
+ Int32 noIidSteps;
+
+ if (!ps_dec->bPsDataAvail)
+ {
+ ps_dec->noEnv = 0;
+ }
+
+ noIidSteps = ps_dec->bFineIidQ ? NO_IID_STEPS_FINE : NO_IID_STEPS;
+
+ for (env = 0; env < ps_dec->noEnv; env++)
+ {
+ Int32 *aPrevIidIndex;
+ Int32 *aPrevIccIndex;
+ if (env == 0)
+ {
+ aPrevIidIndex = ps_dec->aIidPrevFrameIndex;
+ aPrevIccIndex = ps_dec->aIccPrevFrameIndex;
+ }
+ else
+ {
+ aPrevIidIndex = ps_dec->aaIidIndex[env-1];
+ aPrevIccIndex = ps_dec->aaIccIndex[env-1];
+ }
+
+ /*
+ * Differential Decoding of IID parameters over time/frequency
+ */
+ differential_Decoding(ps_dec->bEnableIid,
+ ps_dec->aaIidIndex[env],
+ aPrevIidIndex,
+ ps_dec->abIidDtFlag[env],
+ aNoIidBins[ps_dec->freqResIid],
+ (ps_dec->freqResIid) ? 1 : 2,
+ -noIidSteps,
+ noIidSteps);
+
+ /*
+ * Differential Decoding of ICC parameters over time/frequency
+ */
+ differential_Decoding(ps_dec->bEnableIcc,
+ ps_dec->aaIccIndex[env],
+ aPrevIccIndex,
+ ps_dec->abIccDtFlag[env],
+ aNoIccBins[ps_dec->freqResIcc],
+ (ps_dec->freqResIcc) ? 1 : 2,
+ 0,
+ NO_ICC_STEPS - 1);
+
+
+ } /* for (env=0; env<ps_dec->noEnv; env++) */
+
+ if (ps_dec->noEnv == 0)
+ {
+ ps_dec->noEnv = 1;
+
+ if (ps_dec->bEnableIid)
+ { /* NO_HI_RES_BINS == 34 */
+ pv_memmove(ps_dec->aaIidIndex[ps_dec->noEnv-1],
+ ps_dec->aIidPrevFrameIndex,
+ NO_HI_RES_BINS*sizeof(*ps_dec->aIidPrevFrameIndex));
+
+ }
+ else
+ {
+ pv_memset((void *)ps_dec->aaIidIndex[ps_dec->noEnv-1],
+ 0,
+ NO_HI_RES_BINS*sizeof(**ps_dec->aaIidIndex));
+ }
+ if (ps_dec->bEnableIcc)
+ {
+ pv_memmove(ps_dec->aaIccIndex[ps_dec->noEnv-1],
+ ps_dec->aIccPrevFrameIndex,
+ NO_HI_RES_BINS*sizeof(*ps_dec->aIccPrevFrameIndex));
+ }
+ else
+ {
+ pv_memset((void *)ps_dec->aaIccIndex[ps_dec->noEnv-1],
+ 0,
+ NO_HI_RES_BINS*sizeof(**ps_dec->aaIccIndex));
+ }
+ }
+
+ pv_memmove(ps_dec->aIidPrevFrameIndex,
+ ps_dec->aaIidIndex[ps_dec->noEnv-1],
+ NO_HI_RES_BINS*sizeof(*ps_dec->aIidPrevFrameIndex));
+
+ pv_memmove(ps_dec->aIccPrevFrameIndex,
+ ps_dec->aaIccIndex[ps_dec->noEnv-1],
+ NO_HI_RES_BINS*sizeof(*ps_dec->aIccPrevFrameIndex));
+
+ ps_dec->bPsDataAvail = 0;
+
+ if (ps_dec->bFrameClass == 0)
+ {
+ Int32 shift;
+
+ shift = ps_dec->noEnv >> 1;
+
+ ps_dec->aEnvStartStop[0] = 0;
+
+ for (env = 1; env < ps_dec->noEnv; env++)
+ {
+ ps_dec->aEnvStartStop[env] =
+ (env * ps_dec->noSubSamples) >> shift;
+ }
+
+ ps_dec->aEnvStartStop[ps_dec->noEnv] = ps_dec->noSubSamples;
+ }
+ else
+ { /* if (ps_dec->bFrameClass != 0) */
+ ps_dec->aEnvStartStop[0] = 0;
+
+ if (ps_dec->aEnvStartStop[ps_dec->noEnv] < ps_dec->noSubSamples)
+ {
+ ps_dec->noEnv++;
+ ps_dec->aEnvStartStop[ps_dec->noEnv] = ps_dec->noSubSamples;
+
+ pv_memmove(ps_dec->aaIidIndex[ps_dec->noEnv],
+ ps_dec->aaIidIndex[ps_dec->noEnv-1],
+ NO_HI_RES_BINS*sizeof(**ps_dec->aaIidIndex));
+
+ pv_memmove(ps_dec->aaIccIndex[ps_dec->noEnv],
+ ps_dec->aaIccIndex[ps_dec->noEnv-1],
+ NO_HI_RES_BINS*sizeof(**ps_dec->aaIccIndex));
+ }
+
+ for (env = 1; env < ps_dec->noEnv; env++)
+ {
+ UInt32 thr;
+ thr = ps_dec->noSubSamples - ps_dec->noEnv + env;
+
+ if (ps_dec->aEnvStartStop[env] > thr)
+ {
+ ps_dec->aEnvStartStop[env] = thr;
+ }
+ else
+ {
+ thr = ps_dec->aEnvStartStop[env-1] + 1;
+
+ if (ps_dec->aEnvStartStop[env] < thr)
+ {
+ ps_dec->aEnvStartStop[env] = thr;
+ }
+ }
+ }
+ } /* if (ps_dec->bFrameClass == 0) ... else */
+
+ for (env = 0; env < ps_dec->noEnv; env++)
+ {
+ if (ps_dec->freqResIid == 2)
+ {
+ map34IndexTo20(ps_dec->aaIidIndex[env]);
+ }
+ if (ps_dec->freqResIcc == 2)
+ {
+ map34IndexTo20(ps_dec->aaIccIndex[env]);
+ }
+ }
+
+
+}
+
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_bstr_decoding.h b/media/libstagefright/codecs/aacdec/ps_bstr_decoding.h
new file mode 100644
index 0000000..5212bf8
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_bstr_decoding.h
@@ -0,0 +1,98 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_bstr_decoding.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for functions ps_bstr_decoding()
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_BSTR_DECODING_H
+#define PS_BSTR_DECODING_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_ps_dec.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+extern const Int32 aNoIidBins[3];
+extern const Int32 aNoIccBins[3];
+
+extern const Int32 aFixNoEnvDecode[4];
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void ps_bstr_decoding(STRUCT_PS_DEC *h_ps_dec);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_BSTR_DECODING_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_channel_filtering.cpp b/media/libstagefright/codecs/aacdec/ps_channel_filtering.cpp
new file mode 100644
index 0000000..03a53df
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_channel_filtering.cpp
@@ -0,0 +1,281 @@
+/* ------------------------------------------------------------------
+ * 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: ps_hybrid_analysis.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Does Hybrid analysis
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+
+#include "s_hybrid.h"
+#include "aac_mem_funcs.h"
+#include "ps_fft_rx8.h"
+#include "ps_channel_filtering.h"
+#include "pv_audio_type_defs.h"
+#include "fxp_mul32.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define R_SHIFT 29
+#define Q29_fmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+#define Qfmt31(a) (Int32)(-a*((Int32)1<<31) + (a>=0?0.5F:-0.5F))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void two_ch_filtering(const Int32 *pQmf_r,
+ const Int32 *pQmf_i,
+ Int32 *mHybrid_r,
+ Int32 *mHybrid_i)
+{
+
+ Int32 cum0;
+ Int32 cum1;
+ Int32 cum2;
+ Int32 tmp1;
+ Int32 tmp2;
+
+ tmp1 = pQmf_r[ 1] + pQmf_r[11];
+ tmp2 = pQmf_i[ 1] + pQmf_i[11];
+ cum1 = fxp_mul32_Q31(Qfmt31(0.03798975052098f), tmp1);
+ cum2 = fxp_mul32_Q31(Qfmt31(0.03798975052098f), tmp2);
+ tmp1 = pQmf_r[ 3] + pQmf_r[ 9];
+ tmp2 = pQmf_i[ 3] + pQmf_i[ 9];
+ cum1 = fxp_msu32_Q31(cum1, Qfmt31(0.14586278335076f), tmp1);
+ cum2 = fxp_msu32_Q31(cum2, Qfmt31(0.14586278335076f), tmp2);
+ tmp1 = pQmf_r[ 5] + pQmf_r[ 7];
+ tmp2 = pQmf_i[ 5] + pQmf_i[ 7];
+ cum1 = fxp_mac32_Q31(cum1, Qfmt31(0.61193261090336f), tmp1);
+ cum2 = fxp_mac32_Q31(cum2, Qfmt31(0.61193261090336f), tmp2);
+
+ cum0 = pQmf_r[HYBRID_FILTER_DELAY] >> 1; /* HYBRID_FILTER_DELAY == 6 */
+
+ mHybrid_r[0] = (cum0 + cum1);
+ mHybrid_r[1] = (cum0 - cum1);
+
+ cum0 = pQmf_i[HYBRID_FILTER_DELAY] >> 1; /* HYBRID_FILTER_DELAY == 6 */
+
+ mHybrid_i[0] = (cum0 + cum2);
+ mHybrid_i[1] = (cum0 - cum2);
+
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void eight_ch_filtering(const Int32 *pQmfReal,
+ const Int32 *pQmfImag,
+ Int32 *mHybridReal,
+ Int32 *mHybridImag,
+ Int32 scratch_mem[])
+
+{
+
+ Int32 real;
+ Int32 imag;
+ Int32 tmp1;
+ Int32 tmp2;
+
+ real = fxp_mul32_Q29(Q29_fmt(-0.06989827306334f), pQmfReal[ 4]);
+
+ real = fxp_mac32_Q31(real, Qfmt31(0.01055120626280f), pQmfReal[12]);
+ imag = fxp_mul32_Q29(Q29_fmt(-0.06989827306334f), pQmfImag[ 4]);
+
+ imag = fxp_mac32_Q31(imag, Qfmt31(0.01055120626280f), pQmfImag[12]);
+
+ mHybridReal[2] = (imag - real);
+ mHybridImag[2] = -(imag + real);
+
+ real = fxp_mul32_Q29(Q29_fmt(-0.07266113929591f), pQmfReal[ 3]);
+
+ real = fxp_mac32_Q31(real, Qfmt31(0.04540841899650f), pQmfReal[11]);
+ imag = fxp_mul32_Q29(Q29_fmt(-0.07266113929591f), pQmfImag[ 3]);
+
+ imag = fxp_mac32_Q31(imag, Qfmt31(0.04540841899650f), pQmfImag[11]);
+
+ tmp1 = fxp_mul32_Q29(Q29_fmt(-0.38268343236509f), real);
+ mHybridReal[3] = fxp_mac32_Q29(Q29_fmt(0.92387953251129f), imag, tmp1);
+ tmp2 = fxp_mul32_Q29(Q29_fmt(-0.92387953251129f), real);
+ mHybridImag[3] = fxp_mac32_Q29(Q29_fmt(-0.38268343236509f), imag, tmp2);
+
+
+ mHybridImag[4] = fxp_mul32_Q31(Qfmt31(0.09093731860946f), (pQmfReal[ 2] - pQmfReal[10]));
+ mHybridReal[4] = fxp_mul32_Q31(Qfmt31(0.09093731860946f), (pQmfImag[10] - pQmfImag[ 2]));
+
+
+ real = fxp_mul32_Q29(Q29_fmt(-0.02270420949825f), pQmfReal[ 1]);
+
+ real = fxp_mac32_Q31(real, Qfmt31(0.14532227859182f), pQmfReal[ 9]);
+ imag = fxp_mul32_Q29(Q29_fmt(-0.02270420949825f), pQmfImag[ 1]);
+
+ imag = fxp_mac32_Q31(imag, Qfmt31(0.14532227859182f), pQmfImag[ 9]);
+
+ tmp1 = fxp_mul32_Q29(Q29_fmt(0.92387953251129f), imag);
+
+ mHybridReal[5] = fxp_mac32_Q31(tmp1, Qfmt31(0.76536686473018f), real);
+ tmp2 = fxp_mul32_Q29(Q29_fmt(-0.92387953251129f), real);
+
+ mHybridImag[5] = fxp_mac32_Q31(tmp2, Qfmt31(0.76536686473018f), imag);
+
+ real = fxp_mul32_Q29(Q29_fmt(-0.00527560313140f), pQmfReal[ 0]);
+
+ real = fxp_mac32_Q31(real, Qfmt31(0.13979654612668f), pQmfReal[ 8]);
+ imag = fxp_mul32_Q29(Q29_fmt(-0.00527560313140f), pQmfImag[ 0]);
+
+ imag = fxp_mac32_Q31(imag, Qfmt31(0.13979654612668f), pQmfImag[ 8]);
+
+ mHybridReal[6] = (imag + real);
+ mHybridImag[6] = (imag - real);
+
+
+ tmp1 = fxp_mul32_Q31(Qfmt31(0.21791935610828f), pQmfReal[ 7]);
+ mHybridReal[7] = fxp_mac32_Q31(tmp1, Qfmt31(0.09026515280366f), pQmfImag[ 7]);
+
+ tmp2 = fxp_mul32_Q29(Q29_fmt(-0.04513257640183f), pQmfReal[ 7]);
+
+ mHybridImag[7] = fxp_mac32_Q31(tmp2, Qfmt31(0.21791935610828f), pQmfImag[ 7]);
+
+ mHybridReal[0] = pQmfReal[HYBRID_FILTER_DELAY] >> 3;
+ mHybridImag[0] = pQmfImag[HYBRID_FILTER_DELAY] >> 3;
+
+ tmp1 = fxp_mul32_Q29(Q29_fmt(-0.04513257640183f), pQmfImag[ 5]);
+
+ mHybridReal[1] = fxp_mac32_Q31(tmp1, Qfmt31(0.21791935610828f), pQmfReal[ 5]);
+
+
+ tmp2 = fxp_mul32_Q31(Qfmt31(0.21791935610828f), pQmfImag[ 5]);
+ mHybridImag[1] = fxp_mac32_Q31(tmp2, Qfmt31(0.09026515280366f), pQmfReal[ 5]);
+
+ /*
+ * 8*ifft
+ */
+
+ ps_fft_rx8(mHybridReal, mHybridImag, scratch_mem);
+
+}
+
+
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_channel_filtering.h b/media/libstagefright/codecs/aacdec/ps_channel_filtering.h
new file mode 100644
index 0000000..19cda79
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_channel_filtering.h
@@ -0,0 +1,104 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_channel_filtering.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for functions two_ch_filtering()
+ and eight_ch_filtering()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_CHANNEL_FILTERING_H
+#define PS_CHANNEL_FILTERING_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void two_ch_filtering(const Int32 *pQmf_r,
+ const Int32 *pQmf_i,
+ Int32 *mHybrid_r,
+ Int32 *mHybrid_i);
+
+
+ void eight_ch_filtering(const Int32 *pQmfReal,
+ const Int32 *pQmfImag,
+ Int32 *mHybridReal,
+ Int32 *mHybridImag,
+ Int32 scratch_mem[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_CHANNEL_FILTERING_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_constants.h b/media/libstagefright/codecs/aacdec/ps_constants.h
new file mode 100644
index 0000000..d5b2ad4
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_constants.h
@@ -0,0 +1,89 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+*******************************************************************************/
+/*
+*/
+#ifndef PS_CONSTANTS_H
+#define PS_CONSTANTS_H
+
+
+#define NO_SUB_QMF_CHANNELS 12
+#define NO_QMF_CHANNELS_IN_HYBRID 3
+#define NO_QMF_CHANNELS 64
+#define NO_ALLPASS_CHANNELS 23
+#define NO_DELAY_CHANNELS (NO_QMF_CHANNELS-NO_ALLPASS_CHANNELS)
+#define DELAY_ALLPASS 2
+#define SHORT_DELAY_START 12
+#define SHORT_DELAY 1
+#define LONG_DELAY 14
+#define NO_QMF_ALLPASS_CHANNELS (NO_ALLPASS_CHANNELS-NO_QMF_CHANNELS_IN_HYBRID)
+#define NO_QMF_ICC_CHANNELS (NO_QMF_ALLPASS_CHANNELS+NO_DELAY_CHANNELS)
+#define HYBRIDGROUPS 8
+#define DECAY_CUTOFF 3
+#define NO_SERIAL_ALLPASS_LINKS 3
+#define MAX_NO_PS_ENV 5
+#define NEGATE_IPD_MASK ( 0x00001000 )
+#define NO_BINS ( 20 )
+#define NO_HI_RES_BINS ( 34 )
+#define NO_LOW_RES_BINS ( NO_IID_BINS / 2 )
+#define NO_IID_BINS ( NO_BINS )
+#define NO_ICC_BINS ( NO_BINS )
+#define NO_LOW_RES_IID_BINS ( NO_LOW_RES_BINS )
+#define NO_LOW_RES_ICC_BINS ( NO_LOW_RES_BINS )
+#define SUBQMF_GROUPS ( 10 )
+#define QMF_GROUPS ( 12 )
+#define NO_IID_GROUPS ( SUBQMF_GROUPS + QMF_GROUPS )
+#define NO_IID_STEPS ( 7 )
+#define NO_IID_STEPS_FINE ( 15 )
+#define NO_ICC_STEPS ( 8 )
+#define NO_IID_LEVELS ( 2 * NO_IID_STEPS + 1 )
+#define NO_IID_LEVELS_FINE ( 2 * NO_IID_STEPS_FINE + 1 )
+#define NO_ICC_LEVELS ( NO_ICC_STEPS )
+
+
+
+#endif /* PS_CONSTANTS_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_decode_bs_utils.cpp b/media/libstagefright/codecs/aacdec/ps_decode_bs_utils.cpp
new file mode 100644
index 0000000..241da34
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_decode_bs_utils.cpp
@@ -0,0 +1,274 @@
+/* ------------------------------------------------------------------
+ * 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: ps_decode_bs_utils.c
+
+ Functions:
+ GetNrBitsAvailable
+ differential_Decoding
+ map34IndexTo20
+ limitMinMax
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Decode bitstream parametric stereo's utilities
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+
+#include "aac_mem_funcs.h"
+#include "s_ps_dec.h"
+#include "ps_decode_bs_utils.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int32 GetNrBitsAvailable(HANDLE_BIT_BUFFER hBitBuf)
+{
+
+ return (hBitBuf->bufferLen - hBitBuf->nrBitsRead);
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+;
+; Differential Decoding of parameters over time/frequency
+----------------------------------------------------------------------------*/
+
+void differential_Decoding(Int32 enable,
+ Int32 *aIndex,
+ Int32 *aPrevFrameIndex,
+ Int32 DtDf,
+ Int32 nrElements,
+ Int32 stride,
+ Int32 minIdx,
+ Int32 maxIdx)
+{
+ Int32 i;
+ Int32 *ptr_aIndex;
+
+ if (enable == 1)
+ {
+ ptr_aIndex = aIndex;
+
+ if (DtDf == 0)
+ {
+ *(ptr_aIndex) = limitMinMax(*ptr_aIndex, minIdx, maxIdx);
+ ptr_aIndex++;
+
+ for (i = 1; i < nrElements; i++)
+ {
+ *(ptr_aIndex) = limitMinMax(aIndex[i-1] + *ptr_aIndex, minIdx, maxIdx);
+ ptr_aIndex++;
+ }
+ }
+ else
+ {
+ if (stride == 1)
+ {
+ for (i = 0; i < nrElements; i++)
+ {
+ *(ptr_aIndex) = limitMinMax(aPrevFrameIndex[i] + *ptr_aIndex, minIdx, maxIdx);
+ ptr_aIndex++;
+ }
+ }
+ else
+ {
+ for (i = 0; i < nrElements; i++)
+ {
+ *(ptr_aIndex) = limitMinMax(aPrevFrameIndex[(i<<1)] + *ptr_aIndex, minIdx, maxIdx);
+ ptr_aIndex++;
+ }
+ }
+ }
+ }
+ else
+ {
+ pv_memset((void *)aIndex, 0, nrElements*sizeof(*aIndex));
+ }
+ if (stride == 2)
+ {
+ for (i = (nrElements << 1) - 1; i > 0; i--)
+ {
+ aIndex[i] = aIndex[(i>>1)];
+ }
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+ map34IndexTo20
+----------------------------------------------------------------------------*/
+
+void map34IndexTo20(Int32 *aIndex)
+{
+
+ aIndex[ 0] = ((aIndex[0] << 1) + aIndex[1]) / 3;
+ aIndex[ 1] = (aIndex[1] + (aIndex[2] << 1)) / 3;
+ aIndex[ 2] = ((aIndex[3] << 1) + aIndex[4]) / 3;
+ aIndex[ 3] = (aIndex[4] + (aIndex[5] << 1)) / 3;
+ aIndex[ 4] = (aIndex[ 6] + aIndex[7]) >> 1;
+ aIndex[ 5] = (aIndex[ 8] + aIndex[9]) >> 1;
+ aIndex[ 6] = aIndex[10];
+ aIndex[ 7] = aIndex[11];
+ aIndex[ 8] = (aIndex[12] + aIndex[13]) >> 1;
+ aIndex[ 9] = (aIndex[14] + aIndex[15]) >> 1;
+ aIndex[10] = aIndex[16];
+ aIndex[11] = aIndex[17];
+ aIndex[12] = aIndex[18];
+ aIndex[13] = aIndex[19];
+ aIndex[14] = (aIndex[20] + aIndex[21]) >> 1;
+ aIndex[15] = (aIndex[22] + aIndex[23]) >> 1;
+ aIndex[16] = (aIndex[24] + aIndex[25]) >> 1;
+ aIndex[17] = (aIndex[26] + aIndex[27]) >> 1;
+ aIndex[18] = (aIndex[28] + aIndex[29] + aIndex[30] + aIndex[31]) >> 2;
+ aIndex[19] = (aIndex[32] + aIndex[33]) >> 1;
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+ limitMinMax
+----------------------------------------------------------------------------*/
+
+
+Int32 limitMinMax(Int32 i,
+ Int32 min,
+ Int32 max)
+{
+ if (i < max)
+ {
+ if (i > min)
+ {
+ return i;
+ }
+ else
+ {
+ return min;
+ }
+ }
+ else
+ {
+ return max;
+ }
+}
+
+
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_decode_bs_utils.h b/media/libstagefright/codecs/aacdec/ps_decode_bs_utils.h
new file mode 100644
index 0000000..a672d94
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_decode_bs_utils.h
@@ -0,0 +1,112 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_decode_bs_utils.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for functions differential_Decoding(), limitMinMax(),
+ GetNrBitsAvailable(), map34IndexTo20()
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_DECODE_BS_UTILS_H
+#define PS_DECODE_BS_UTILS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_ps_dec.h"
+#include "s_bit_buffer.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void differential_Decoding(Int32 enable,
+ Int32 *aIndex,
+ Int32 *aPrevFrameIndex,
+ Int32 DtDf,
+ Int32 nrElements,
+ Int32 stride,
+ Int32 minIdx,
+ Int32 maxIdx);
+
+ Int32 limitMinMax(Int32 i,
+ Int32 min,
+ Int32 max);
+
+ Int32 GetNrBitsAvailable(HANDLE_BIT_BUFFER hBitBuf);
+
+ void map34IndexTo20(Int32 *aIndex);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_DECODE_BS_UTILS_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_decorrelate.cpp b/media/libstagefright/codecs/aacdec/ps_decorrelate.cpp
new file mode 100644
index 0000000..6776d6e
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_decorrelate.cpp
@@ -0,0 +1,499 @@
+/* ------------------------------------------------------------------
+ * 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: ps_decorrelate.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Decorrelation
+ Decorrelation is achieved by means of all-pass filtering and delaying
+ Sub-band samples s_k(n) are converted into de-correlated sub-bands samples
+ d_k(n). k index for frequency, n time index
+
+
+ _______ ________
+ | | _______ | |
+ ->|Hybrid | LF ---- | |->| Hybrid |-->
+ | Anal. | | | | | Synth | QMF -> L
+ ------- o----------------------->| | -------- Synth
+QMF | s_k(n) |Stereo |-------------->
+Anal. -------------------------->| |
+ _______ | | | | ________
+ | | HF --o | ----------- |Process| | |
+ ->| Delay | | ->| |-------->| |->| Hybrid |-->
+ ------- | |decorrelate| d_k(n) | | | Synth | QMF -> R
+ ---->| |-------->| | -------- Synth
+ ----------- |_______|-------------->
+
+
+ Delay is introduced to compensate QMF bands not passed through Hybrid
+ Analysis
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+#include "pv_audio_type_defs.h"
+#include "ps_decorrelate.h"
+#include "aac_mem_funcs.h"
+#include "ps_all_pass_filter_coeff.h"
+#include "ps_pwr_transient_detection.h"
+#include "ps_all_pass_fract_delay_filter.h"
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+#ifndef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void ps_decorrelate(STRUCT_PS_DEC *h_ps_dec,
+ Int32 *rIntBufferLeft,
+ Int32 *iIntBufferLeft,
+ Int32 *rIntBufferRight,
+ Int32 *iIntBufferRight,
+ Int32 scratch_mem[])
+{
+ Int32 sb;
+ Int32 maxsb;
+ Int32 gr;
+ Int32 sb_delay;
+ Int32 bin;
+
+
+
+
+ Int32 *aLeftReal;
+ Int32 *aLeftImag;
+ Int32 *aRightReal;
+ Int32 *aRightImag;
+
+ Int32 *aTransRatio = scratch_mem; /* use NO_BINS == 20 */
+
+
+ Int32 ***pppRealDelayRBufferSer;
+ Int32 ***pppImagDelayRBufferSer;
+
+ Int32 **ppRealDelayBuffer;
+ Int32 **ppImagDelayBuffer;
+
+ const Int32(*ppFractDelayPhaseFactorSer)[3];
+ /*
+ * Power transient estimation and detection
+ */
+
+
+ ps_pwr_transient_detection(h_ps_dec,
+ rIntBufferLeft,
+ iIntBufferLeft,
+ aTransRatio);
+
+
+ aLeftReal = h_ps_dec->mHybridRealLeft;
+ aLeftImag = h_ps_dec->mHybridImagLeft;
+ aRightReal = h_ps_dec->mHybridRealRight;
+ aRightImag = h_ps_dec->mHybridImagRight;
+
+ pppRealDelayRBufferSer = h_ps_dec->aaaRealDelayRBufferSerSubQmf;
+ pppImagDelayRBufferSer = h_ps_dec->aaaImagDelayRBufferSerSubQmf;
+
+ ppRealDelayBuffer = h_ps_dec->aaRealDelayBufferSubQmf;
+ ppImagDelayBuffer = h_ps_dec->aaImagDelayBufferSubQmf;
+
+
+
+ ppFractDelayPhaseFactorSer = aaFractDelayPhaseFactorSerSubQmf;
+
+
+ /*
+ * NO_IID_GROUPS (SUBQMF_GROUPS (12) + QMF_GROUPS (10)) == 22
+ */
+
+ for (gr = 0; gr < SUBQMF_GROUPS; gr++) /* 0 to 9 */
+ {
+ Int32 rIn;
+ Int32 iIn;
+ Int32 *pt_rTmp;
+ Int32 *pt_iTmp;
+ Int32 rTmp;
+ Int32 cmplx;
+ Int32 tmp1, tmp2;
+
+ /* sb = subQMF/QMF subband */
+
+ sb = groupBorders[gr];
+
+ /*
+ * For lower subbands
+ * Apply all-pass filtering
+ *
+ */
+ pt_rTmp = &ppRealDelayBuffer[sb][h_ps_dec->delayBufIndex];
+ pt_iTmp = &ppImagDelayBuffer[sb][h_ps_dec->delayBufIndex];
+
+ tmp1 = aLeftReal[sb];
+ tmp2 = aLeftImag[sb];
+ rIn = *pt_rTmp >> 1;
+ iIn = *pt_iTmp >> 1;
+
+
+ *pt_rTmp = tmp1;
+ *pt_iTmp = tmp2;
+
+ /*
+ * Fractional delay vector
+ *
+ * phi_fract(k) = exp(-j*pi*q_phi*f_center(k)) 0<= k <= SUBQMF_GROUPS
+ *
+ * q_phi = 0.39
+ * f_center(k) frequency vector
+ */
+
+ cmplx = aFractDelayPhaseFactorSubQmf[sb];
+
+ aRightReal[sb] = cmplx_mul32_by_16(rIn, -iIn, cmplx);
+ aRightImag[sb] = cmplx_mul32_by_16(iIn, rIn, cmplx);
+
+ ps_all_pass_fract_delay_filter_type_I(h_ps_dec->aDelayRBufIndexSer,
+ sb,
+ ppFractDelayPhaseFactorSer[sb],
+ pppRealDelayRBufferSer,
+ pppImagDelayRBufferSer,
+ &aRightReal[sb],
+ &aRightImag[sb]);
+
+ bin = bins2groupMap[gr];
+ rTmp = aTransRatio[bin];
+
+ if (rTmp != 0x7FFFFFFF)
+ {
+ aRightReal[sb] = fxp_mul32_Q31(rTmp, aRightReal[sb]) << 1;
+ aRightImag[sb] = fxp_mul32_Q31(rTmp, aRightImag[sb]) << 1;
+ }
+
+
+ } /* gr */
+
+ aLeftReal = rIntBufferLeft;
+ aLeftImag = iIntBufferLeft;
+ aRightReal = rIntBufferRight;
+ aRightImag = iIntBufferRight;
+
+ pppRealDelayRBufferSer = h_ps_dec->aaaRealDelayRBufferSerQmf;
+ pppImagDelayRBufferSer = h_ps_dec->aaaImagDelayRBufferSerQmf;
+
+ ppRealDelayBuffer = h_ps_dec->aaRealDelayBufferQmf;
+ ppImagDelayBuffer = h_ps_dec->aaImagDelayBufferQmf;
+
+
+
+ ppFractDelayPhaseFactorSer = aaFractDelayPhaseFactorSerQmf;
+
+
+ for (gr = SUBQMF_GROUPS; gr < NO_BINS; gr++) /* 10 to 20 */
+ {
+
+ maxsb = min(h_ps_dec->usb, groupBorders[gr+1]);
+
+ /* sb = subQMF/QMF subband */
+
+ for (sb = groupBorders[gr]; sb < maxsb; sb++)
+ {
+
+ Int32 rIn, iIn;
+ Int32 *pt_rTmp, *pt_iTmp;
+ Int32 cmplx;
+ Int32 tmp1, tmp2;
+ Int32 rTmp;
+
+
+ sb_delay = sb - NO_QMF_CHANNELS_IN_HYBRID; /* NO_QMF_CHANNELS_IN_HYBRID == 3 */
+
+ /*
+ * For lower subbands
+ * Apply all-pass filtering
+ *
+ */
+ pt_rTmp = &ppRealDelayBuffer[sb_delay][h_ps_dec->delayBufIndex];
+ pt_iTmp = &ppImagDelayBuffer[sb_delay][h_ps_dec->delayBufIndex];
+
+ rIn = *pt_rTmp >> 1;
+ iIn = *pt_iTmp >> 1;
+
+ tmp1 = aLeftReal[sb];
+ tmp2 = aLeftImag[sb];
+ *pt_rTmp = tmp1;
+ *pt_iTmp = tmp2;
+
+ /*
+ * Fractional delay vector
+ *
+ * phi_fract(k) = exp(-j*pi*q_phi*f_center(k)) 0<= k <= SUBQMF_GROUPS
+ *
+ * q_phi = 0.39
+ * f_center(k) frequency vector
+ */
+
+ cmplx = aFractDelayPhaseFactor[sb_delay];
+ aRightReal[sb] = cmplx_mul32_by_16(rIn, -iIn, cmplx);
+ aRightImag[sb] = cmplx_mul32_by_16(iIn, rIn, cmplx);
+
+ ps_all_pass_fract_delay_filter_type_II(h_ps_dec->aDelayRBufIndexSer,
+ sb_delay,
+ ppFractDelayPhaseFactorSer[sb_delay],
+ pppRealDelayRBufferSer,
+ pppImagDelayRBufferSer,
+ &aRightReal[sb],
+ &aRightImag[sb],
+ sb);
+
+ rTmp = aTransRatio[gr-2];
+ if (rTmp != 0x7FFFFFFF)
+ {
+ aRightReal[sb] = fxp_mul32_Q31(rTmp, aRightReal[sb]) << 1;
+ aRightImag[sb] = fxp_mul32_Q31(rTmp, aRightImag[sb]) << 1;
+ }
+
+
+ } /* sb */
+
+ }
+
+
+ maxsb = min(h_ps_dec->usb, 35); /* 35 == groupBorders[NO_BINS + 1] */
+
+ /* sb = subQMF/QMF subband */
+ {
+ Int32 factor = aTransRatio[NO_BINS-2];
+
+ for (sb = 23; sb < maxsb; sb++) /* 23 == groupBorders[NO_BINS] */
+ {
+
+ Int32 tmp, tmp2;
+ Int32 *pt_rTmp, *pt_iTmp;
+
+ sb_delay = sb - NO_QMF_CHANNELS_IN_HYBRID; /* == 3 */
+
+ /*
+ * For the Upper Bands apply delay only
+ * -D(k)
+ * Apply Delay H_k(z) = z , D(k) == 1 or 14
+ *
+ */
+ Int32 k = sb - NO_ALLPASS_CHANNELS; /* == 23 */
+
+
+ pt_rTmp = &ppRealDelayBuffer[sb_delay][h_ps_dec->aDelayBufIndex[ k]];
+ pt_iTmp = &ppImagDelayBuffer[sb_delay][h_ps_dec->aDelayBufIndex[ k]];
+
+ if (++h_ps_dec->aDelayBufIndex[ k] >= LONG_DELAY) /* == 14 */
+ {
+ h_ps_dec->aDelayBufIndex[ k] = 0;
+ }
+
+
+ tmp = *pt_rTmp;
+ tmp2 = *pt_iTmp;
+
+ if (aTransRatio[NO_BINS-2] < 0x7FFFFFFF)
+ {
+ aRightReal[sb] = fxp_mul32_Q31(factor, tmp) << 1;
+ aRightImag[sb] = fxp_mul32_Q31(factor, tmp2) << 1;
+ }
+ else
+ {
+ aRightReal[sb] = tmp;
+ aRightImag[sb] = tmp2;
+ }
+
+
+ tmp = aLeftReal[sb];
+ tmp2 = aLeftImag[sb];
+ *pt_rTmp = tmp;
+ *pt_iTmp = tmp2;
+
+
+ } /* sb */
+ }
+
+
+ maxsb = min(h_ps_dec->usb, 64); /* 64 == groupBorders[NO_BINS+2] */
+
+ /* sb = subQMF/QMF subband */
+
+ {
+
+ for (sb = 35; sb < maxsb; sb++) /* 35 == groupBorders[NO_BINS+1] */
+ {
+
+ Int32 *pt_rTmp, *pt_iTmp;
+
+ sb_delay = sb - NO_QMF_CHANNELS_IN_HYBRID; /* == 3 */
+
+ /*
+ * For the Upper Bands apply delay only
+ * -D(k)
+ * Apply Delay H_k(z) = z , D(k) == 1 or 14
+ *
+ */
+
+ pt_rTmp = &ppRealDelayBuffer[sb_delay][0];
+ pt_iTmp = &ppImagDelayBuffer[sb_delay][0];
+
+ aRightReal[sb] = *pt_rTmp;
+ aRightImag[sb] = *pt_iTmp;
+
+
+ if (aTransRatio[NO_BINS-1] < 0x7FFFFFFF)
+ {
+ aRightReal[sb] = fxp_mul32_Q31(aTransRatio[NO_BINS-1], aRightReal[sb]) << 1;
+ aRightImag[sb] = fxp_mul32_Q31(aTransRatio[NO_BINS-1], aRightImag[sb]) << 1;
+ }
+
+ *pt_rTmp = aLeftReal[sb];
+ *pt_iTmp = aLeftImag[sb];
+
+
+ } /* sb */
+ }
+
+
+ if (++h_ps_dec->delayBufIndex >= DELAY_ALLPASS)
+ {
+ h_ps_dec->delayBufIndex = 0;
+ }
+
+ if (++h_ps_dec->aDelayRBufIndexSer[0] >= 3)
+ {
+ h_ps_dec->aDelayRBufIndexSer[0] = 0;
+ }
+ if (++h_ps_dec->aDelayRBufIndexSer[1] >= 4)
+ {
+ h_ps_dec->aDelayRBufIndexSer[1] = 0;
+ }
+ if (++h_ps_dec->aDelayRBufIndexSer[2] >= 5)
+ {
+ h_ps_dec->aDelayRBufIndexSer[2] = 0;
+ }
+
+
+} /* END deCorrelate */
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_decorrelate.h b/media/libstagefright/codecs/aacdec/ps_decorrelate.h
new file mode 100644
index 0000000..c2a025a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_decorrelate.h
@@ -0,0 +1,99 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_decorrelate.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for function ps_decorrelate()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_DECORRELATE_H
+#define PS_DECORRELATE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_ps_dec.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void ps_decorrelate(STRUCT_PS_DEC *h_ps_dec,
+ Int32 *rIntBufferLeft,
+ Int32 *iIntBufferLeft,
+ Int32 *rIntBufferRight,
+ Int32 *iIntBufferRight,
+ Int32 scratch_mem[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_DECORRELATE_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_fft_rx8.cpp b/media/libstagefright/codecs/aacdec/ps_fft_rx8.cpp
new file mode 100644
index 0000000..7669be3
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_fft_rx8.cpp
@@ -0,0 +1,318 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: fft_rx8.c
+ Funtions: ps_fft_rx8
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ Real Vector of Real components size 8
+
+ Imag Vector of Imag components size 8
+ type Int32
+
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ scratch_mem size 32
+
+ Outputs:
+ In-place calculation of a 8-point FFT (radix-8)
+
+ Pointers and Buffers Modified:
+ calculation are done in-place and returned in Data
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ 8-point DFT, radix 8 with Decimation in Frequency
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function should provide a fixed point FFT for any input array
+ of size power of 8.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] Advance Digital Signal Processing, J. Proakis, C. Rader, F. Ling,
+ C. Nikias, Macmillan Pub. Co.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+ MODIFY( x[] )
+ RETURN( exponent )
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#ifdef PARAMETRICSTEREO
+
+
+#include "pv_audio_type_defs.h"
+#include "ps_fft_rx8.h"
+
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define R_SHIFT 29
+#define Q29_fmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void ps_fft_rx8(Int32 Re[], Int32 Im[], Int32 scratch_mem[])
+
+/* scratch_mem size 32 */
+{
+
+ Int i;
+ Int32 *Q = &scratch_mem[0];
+ Int32 *Z = &scratch_mem[16];
+ Int32 temp1;
+ Int32 temp2;
+ Int32 temp3;
+ Int32 temp4;
+ Int32 aux_r[2];
+ Int32 aux_i[2];
+ Int32 *pt_r1 = &Re[0];
+ Int32 *pt_r2 = &Re[4];
+ Int32 *pt_i1 = &Im[0];
+ Int32 *pt_i2 = &Im[4];
+
+ Int32 *pt_Q = Q;
+ Int32 *pt_Z = Z;
+
+
+ temp1 = *(pt_r1++); /* Real */
+ temp2 = *(pt_r2++); /* Real */
+ temp3 = *(pt_i1++); /* Imag */
+ temp4 = *(pt_i2++); /* Imag */
+ /*
+ * Vector Q stores data as Real, Imag, Real, Imag,....
+ */
+
+ *(pt_Q++) = temp1 + temp2; /* Q(0) = v(0) + v(4) */
+ *(pt_Q++) = temp3 + temp4;
+ *(pt_Q++) = temp1 - temp2; /* Q(1) = v(0) - v(4) */
+ *(pt_Q++) = temp3 - temp4;
+
+ temp1 = *(pt_r1++);
+ temp2 = *(pt_r2++);
+ temp3 = *(pt_i1++);
+ temp4 = *(pt_i2++);
+
+ *(pt_Q++) = temp1 + temp2; /* Q(2) = v(1) + v(5) */
+ *(pt_Q++) = temp3 + temp4;
+ aux_r[0] = temp1 - temp2; /* aux[0] = v(1) - v(5) */
+ aux_i[0] = temp3 - temp4;
+
+ temp1 = *(pt_r1++);
+ temp2 = *(pt_r2++);
+ temp3 = *(pt_i1++);
+ temp4 = *(pt_i2++);
+
+ *(pt_Q++) = temp1 + temp2; /* Q(3) = v(2) + v(6) */
+ *(pt_Q++) = temp3 + temp4;
+ *(pt_Q++) = temp4 - temp3; /* Q(4) = (v(2) - v(6))*j */
+ *(pt_Q++) = temp1 - temp2;
+
+ temp1 = *(pt_r1++);
+ temp2 = *(pt_r2++);
+ temp3 = *(pt_i1++);
+ temp4 = *(pt_i2++);
+
+
+ *(pt_Q++) = temp1 + temp2; /* Q(5) = v(3) + v(7) */
+ *(pt_Q++) = temp3 + temp4;
+ aux_r[1] = temp1 - temp2; /* aux[1] = v(3) - v(7) */
+ aux_i[1] = temp3 - temp4;
+ /* Q(6) = (aux[0] - aux[1])/sqrt(2); */
+ *(pt_Q++) = fxp_mul32_Q29((aux_r[0] - aux_r[1]), Q29_fmt(0.70710678118655f));
+ *(pt_Q++) = fxp_mul32_Q29((aux_i[0] - aux_i[1]), Q29_fmt(0.70710678118655f));
+
+ /* Q(7) = (aux[0] + aux[1])*j/sqrt(2); */
+ *(pt_Q++) = fxp_mul32_Q29((aux_i[0] + aux_i[1]), Q29_fmt(-0.70710678118655f));
+ *(pt_Q) = fxp_mul32_Q29((aux_r[0] + aux_r[1]), Q29_fmt(0.70710678118655f));
+
+ pt_r1 = &Q[0]; /* reset pointer */
+ pt_r2 = &Q[6]; /* reset pointer */
+
+ temp1 = *(pt_r1++);
+ temp2 = *(pt_r2++);
+ temp3 = *(pt_r1++);
+ temp4 = *(pt_r2++);
+
+ /*
+ * Vector Z stores data as Real, Imag, Real, Imag,....
+ */
+
+ *(pt_Z++) = temp1 + temp2; /* Q(0) + Q(3) */
+ *(pt_Z++) = temp3 + temp4;
+ aux_r[0] = temp1 - temp2;
+ aux_i[0] = temp3 - temp4;
+
+ temp1 = *(pt_r1++);
+ temp2 = *(pt_r2++);
+ temp3 = *(pt_r1++);
+ temp4 = *(pt_r2++);
+
+ *(pt_Z++) = temp1 + temp2; /* Q(1) + Q(4) */
+ *(pt_Z++) = temp3 + temp4;
+ *(pt_Z++) = aux_r[0]; /* Q(0) - Q(3) */
+ *(pt_Z++) = aux_i[0];
+ *(pt_Z++) = temp1 - temp2; /* Q(1) - Q(4) */
+ *(pt_Z++) = temp3 - temp4;
+
+ temp1 = *(pt_r1++);
+ temp2 = *(pt_r2++);
+ temp3 = *(pt_r1);
+ temp4 = *(pt_r2++);
+
+ *(pt_Z++) = temp1 + temp2; /* Q(2) + Q(5) */
+ *(pt_Z++) = temp3 + temp4;
+ aux_r[0] = temp1 - temp2;
+ aux_i[0] = temp3 - temp4;
+
+ temp1 = *(pt_r2++);
+ temp3 = *(pt_r2++);
+ temp2 = *(pt_r2++);
+ temp4 = *(pt_r2);
+
+ *(pt_Z++) = temp1 + temp2; /* Q(6) + Q(7) */
+ *(pt_Z++) = temp3 + temp4;
+
+ *(pt_Z++) = -aux_i[0]; /* (Q(2) - Q(5))*j */
+ *(pt_Z++) = aux_r[0];
+
+ *(pt_Z++) = temp2 - temp1; /* -Q(6) + Q(7) */
+ *(pt_Z) = temp4 - temp3;
+
+ pt_Z = &Z[0]; /* reset pointer */
+ pt_Q = &Z[8]; /* reset pointer */
+
+ pt_r1 = &Re[0];
+ pt_r2 = &Re[4];
+ pt_i1 = &Im[0];
+ pt_i2 = &Im[4];
+
+
+ for (i = 4; i != 0; i--)
+ {
+ temp1 = *(pt_Z++);
+ temp2 = *(pt_Q++);
+ temp3 = *(pt_Z++);
+ temp4 = *(pt_Q++);
+
+ *(pt_r1++) = temp1 + temp2; /* Z(n) + Z(n+4) */
+ *(pt_i1++) = temp3 + temp4;
+ *(pt_r2++) = temp1 - temp2; /* Z(n) - Z(n+4) */
+ *(pt_i2++) = temp3 - temp4;
+ }
+
+}
+
+#endif /* PARAMETRICSTEREO */
+
+
+#endif /* AAC_PLUS */
diff --git a/media/libstagefright/codecs/aacdec/ps_fft_rx8.h b/media/libstagefright/codecs/aacdec/ps_fft_rx8.h
new file mode 100644
index 0000000..6c3482e
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_fft_rx8.h
@@ -0,0 +1,94 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_fft_rx8.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for functions ps_fft_rx8()
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_FFT_RX8_H
+#define PS_FFT_RX8_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void ps_fft_rx8(Int32 Re[], Int32 Im[], Int32 scratch_mem[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_FFT_RX4_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_hybrid_analysis.cpp b/media/libstagefright/codecs/aacdec/ps_hybrid_analysis.cpp
new file mode 100644
index 0000000..933b07e
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_hybrid_analysis.cpp
@@ -0,0 +1,285 @@
+/* ------------------------------------------------------------------
+ * 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: ps_hybrid_analysis.c
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Does Hybrid analysis:
+
+ Get higher frequency resolution in the lower QMF subbands
+ creating sub-subbands. This is done by low frequency filtering.
+ Lower QMF subbands are further split in order to obtain a higher
+ frequency resolution, enabling a proper stereo analysis and synthesis
+ for the lower frequencies.
+ Two hybrid are defined. Both filters have length 13 and a delay of 6.
+ In this implementation, the symmetry of the filters helps to simplify
+ the design.
+
+
+ Increase Freq. Resolution
+ _______ ________
+ | | _______ | |
+ ->|Hybrid | LF ---- | |->| Hybrid |-->
+ | Anal. | | | | | Synth | QMF -> L
+ ------- o----------------------->| | -------- Synth
+QMF | s_k(n) |Stereo |-------------->
+Anal. -------------------------->| |
+ _______ | | | | ________
+ | | HF --o | ----------- |Process| | |
+ ->| Delay | | ->| |-------->| |->| Hybrid |-->
+ ------- | |decorrelate| d_k(n) | | | Synth | QMF -> R
+ ---->| |-------->| | -------- Synth
+ ----------- |_______|-------------->
+
+
+
+ subband k QMF channel
+ 0 ................. 0 -----------
+ 1 ................. 0
+ 2 ................. 0
+ 3 ................. 0
+ 4 ................. 0
+ 5 ................. 0 Sub-QMF ( Increase Freq. Resolution)
+ 6 ................. 1
+ 7 ................. 1
+ 8 ................. 2
+ 9 ................. 2
+ 10 ................. 3 -----------
+ 11 ................. 4
+ 12 ................. 5
+ 13 ................. 6
+ 14 ................. 7
+ 15 ................. 8 QMF
+ 16-17 ................. 9-10
+ 18-20 ................. 11-13
+ 21-24 ................. 14-17
+ 25-29 ................. 18-22
+ 30-41 ................. 23-34
+ 42-70 ................. 35-63 -----------
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+
+#include "s_hybrid.h"
+#include "aac_mem_funcs.h"
+#include "ps_channel_filtering.h"
+#include "ps_hybrid_analysis.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void ps_hybrid_analysis(const Int32 mQmfReal[][64],
+ const Int32 mQmfImag[][64],
+ Int32 *mHybridReal,
+ Int32 *mHybridImag,
+ HYBRID *pHybrid,
+ Int32 scratch_mem[],
+ Int32 i)
+
+{
+
+ Int32 band;
+ HYBRID_RES hybridRes;
+ Int32 chOffset = 0;
+
+ Int32 *ptr_mHybrid_Re;
+ Int32 *ptr_mHybrid_Im;
+
+ Int32 *pt_mQmfBufferReal;
+ Int32 *pt_mQmfBufferImag;
+
+ pt_mQmfBufferReal = &scratch_mem[32 + i];
+
+ for (band = 0; band < pHybrid->nQmfBands; band++)
+ {
+ pt_mQmfBufferImag = pt_mQmfBufferReal + 44;
+
+
+ pt_mQmfBufferReal[HYBRID_FILTER_LENGTH_m_1] = mQmfReal[HYBRID_FILTER_DELAY][band];
+ pt_mQmfBufferImag[HYBRID_FILTER_LENGTH_m_1] = mQmfImag[HYBRID_FILTER_DELAY][band];
+
+
+ ptr_mHybrid_Re = &mHybridReal[ chOffset];
+ ptr_mHybrid_Im = &mHybridImag[ chOffset];
+
+ hybridRes = (HYBRID_RES)pHybrid->pResolution[band];
+ switch (hybridRes)
+ {
+ /*
+ * For QMF band = 1 and 2
+ */
+
+ case HYBRID_2_REAL:
+
+ two_ch_filtering(pt_mQmfBufferReal,
+ pt_mQmfBufferImag,
+ ptr_mHybrid_Re,
+ ptr_mHybrid_Im);
+ chOffset += 2;
+
+ break;
+
+ /*
+ * For QMF band = 0
+ */
+
+ case HYBRID_8_CPLX:
+
+ eight_ch_filtering(pt_mQmfBufferReal,
+ pt_mQmfBufferImag,
+ pHybrid->mTempReal,
+ pHybrid->mTempImag,
+ scratch_mem);
+
+ pv_memmove(ptr_mHybrid_Re, pHybrid->mTempReal, 4*sizeof(*pHybrid->mTempReal));
+
+ ptr_mHybrid_Re += 2;
+
+ *(ptr_mHybrid_Re++) += pHybrid->mTempReal[5];
+ *(ptr_mHybrid_Re++) += pHybrid->mTempReal[4];
+ *(ptr_mHybrid_Re++) = pHybrid->mTempReal[6];
+ *(ptr_mHybrid_Re) = pHybrid->mTempReal[7];
+
+ pv_memmove(ptr_mHybrid_Im, pHybrid->mTempImag, 4*sizeof(*pHybrid->mTempImag));
+ ptr_mHybrid_Im += 2;
+
+ *(ptr_mHybrid_Im++) += pHybrid->mTempImag[5];
+ *(ptr_mHybrid_Im++) += pHybrid->mTempImag[4];
+ *(ptr_mHybrid_Im++) = pHybrid->mTempImag[6];
+ *(ptr_mHybrid_Im) = pHybrid->mTempImag[7];
+
+ chOffset += 6;
+
+ break;
+
+ default:
+ ;
+ }
+
+ pt_mQmfBufferReal = pt_mQmfBufferImag + 44;
+
+ }
+
+
+}
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_hybrid_analysis.h b/media/libstagefright/codecs/aacdec/ps_hybrid_analysis.h
new file mode 100644
index 0000000..0140a1f
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_hybrid_analysis.h
@@ -0,0 +1,98 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_hybrid_analysis.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for function ps_hybrid_analysis()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_HYBRID_ANALYSIS_H
+#define PS_HYBRID_ANALYSIS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_hybrid.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void ps_hybrid_analysis(const Int32 mQmfReal[][64],
+ const Int32 mQmfImag[][64],
+ Int32 *mHybridReal,
+ Int32 *mHybridImag,
+ HYBRID *pHybrid,
+ Int32 scratch_mem[],
+ Int32 band);
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_HYBRID_ANALYSIS_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_hybrid_filter_bank_allocation.cpp b/media/libstagefright/codecs/aacdec/ps_hybrid_filter_bank_allocation.cpp
new file mode 100644
index 0000000..4ff2385
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_hybrid_filter_bank_allocation.cpp
@@ -0,0 +1,213 @@
+/* ------------------------------------------------------------------
+ * 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: ps_hybrid_filter_bank_allocation.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Does Hybrid filter bank memory allocation
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+#include "aac_mem_funcs.h"
+#include "ps_hybrid_filter_bank_allocation.h"
+#include "ps_all_pass_filter_coeff.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int32 ps_hybrid_filter_bank_allocation(HYBRID **phHybrid,
+ Int32 noBands,
+ const Int32 *pResolution,
+ Int32 **pPtr)
+{
+ Int32 i;
+ Int32 tmp;
+ Int32 maxNoChannels = 0;
+ HYBRID *hs;
+ Int32 *ptr = *pPtr;
+
+
+ *phHybrid = (HYBRID *)NULL;
+
+ hs = (HYBRID *)ptr;
+
+ ptr += sizeof(HYBRID) / sizeof(*ptr);
+
+ hs->pResolution = (Int32*)ptr;
+
+ ptr += noBands * sizeof(Int32) / sizeof(*ptr);
+
+ for (i = 0; i < noBands; i++)
+ {
+
+ hs->pResolution[i] = pResolution[i];
+
+ if (pResolution[i] != HYBRID_8_CPLX &&
+ pResolution[i] != HYBRID_2_REAL &&
+ pResolution[i] != HYBRID_4_CPLX)
+ {
+ return 1;
+ }
+
+ if (pResolution[i] > maxNoChannels)
+ {
+ maxNoChannels = pResolution[i];
+ }
+ }
+
+ hs->nQmfBands = noBands;
+ hs->qmfBufferMove = HYBRID_FILTER_LENGTH - 1;
+
+ hs->mQmfBufferReal = (Int32 **)ptr;
+ ptr += noBands * sizeof(ptr) / sizeof(*ptr);
+
+ hs->mQmfBufferImag = (Int32 **)ptr;
+ ptr += noBands * sizeof(ptr) / sizeof(*ptr);
+
+ tmp = hs->qmfBufferMove; /* HYBRID_FILTER_LENGTH == 13 */
+
+ for (i = 0; i < noBands; i++)
+ {
+ hs->mQmfBufferReal[i] = ptr;
+ ptr += tmp;
+
+ hs->mQmfBufferImag[i] = ptr;
+ ptr += tmp;
+
+ }
+
+ hs->mTempReal = ptr;
+ ptr += maxNoChannels;
+
+
+ hs->mTempImag = ptr;
+ ptr += maxNoChannels;
+
+
+ *phHybrid = hs;
+ *pPtr = ptr;
+
+ return 0;
+}
+
+
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_hybrid_filter_bank_allocation.h b/media/libstagefright/codecs/aacdec/ps_hybrid_filter_bank_allocation.h
new file mode 100644
index 0000000..fbc0d80
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_hybrid_filter_bank_allocation.h
@@ -0,0 +1,97 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_hybrid_filter_bank_allocation.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for ps_hybrid_filter_bank_allocation
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_HYBRID_FILTER_BANK_ALLOCATION_H
+#define PS_HYBRID_FILTER_BANK_ALLOCATION_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_hybrid.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ Int32 ps_hybrid_filter_bank_allocation(HYBRID **phHybrid,
+ Int32 noBands,
+ const Int32 *pResolution,
+ Int32 **pPtr);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_HYBRID_FILTER_BANK_ALLOCATION_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_hybrid_synthesis.cpp b/media/libstagefright/codecs/aacdec/ps_hybrid_synthesis.cpp
new file mode 100644
index 0000000..4fbd016
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_hybrid_synthesis.cpp
@@ -0,0 +1,192 @@
+/* ------------------------------------------------------------------
+ * 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: ps_hybrid_synthesis.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Hybrid synthesis
+
+ _______ ________
+ | | _______ | |
+ ->|Hybrid | LF ---- | |->| Hybrid |-->
+ | Anal. | | | | | Synth | QMF -> L
+ ------- o----------------------->| | -------- Synth
+QMF | s_k(n) |Stereo |-------------->
+Anal. -------------------------->| |
+ _______ | | | | ________
+ | | HF --o | ----------- |Process| | |
+ ->| Delay | | ->| |-------->| |->| Hybrid |-->
+ ------- | |decorrelate| d_k(n) | | | Synth | QMF -> R
+ ---->| |-------->| | -------- Synth
+ ----------- |_______|-------------->
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+
+#include "s_hybrid.h"
+#include "ps_hybrid_synthesis.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#ifndef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void ps_hybrid_synthesis(const Int32 *mHybridReal,
+ const Int32 *mHybridImag,
+ Int32 *mQmfReal,
+ Int32 *mQmfImag,
+ HYBRID *hHybrid)
+{
+ Int32 k;
+ Int32 band;
+ HYBRID_RES hybridRes;
+
+ Int32 real;
+ Int32 imag;
+ Int32 *ptr_mQmfReal = mQmfReal;
+ Int32 *ptr_mQmfImag = mQmfImag;
+ const Int32 *ptr_mHybrid_Re = mHybridReal;
+ const Int32 *ptr_mHybrid_Im = mHybridImag;
+
+ for (band = 0; band < hHybrid->nQmfBands; band++)
+ {
+ hybridRes = (HYBRID_RES)(min(hHybrid->pResolution[band], 6) - 2);
+
+ real = *(ptr_mHybrid_Re++);
+ real += *(ptr_mHybrid_Re++);
+ imag = *(ptr_mHybrid_Im++);
+ imag += *(ptr_mHybrid_Im++);
+
+ for (k = (hybridRes >> 1); k != 0; k--) /* hybridRes = { 2,4,6 } */
+ {
+ real += *(ptr_mHybrid_Re++);
+ real += *(ptr_mHybrid_Re++);
+ imag += *(ptr_mHybrid_Im++);
+ imag += *(ptr_mHybrid_Im++);
+ }
+
+ *(ptr_mQmfReal++) = real;
+ *(ptr_mQmfImag++) = imag;
+ }
+}
+
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_hybrid_synthesis.h b/media/libstagefright/codecs/aacdec/ps_hybrid_synthesis.h
new file mode 100644
index 0000000..d7242dd
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_hybrid_synthesis.h
@@ -0,0 +1,97 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_hybrid_synthesis.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for function ps_hybrid_synthesis()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_HYBRID_SYNTHESIS_H
+#define PS_HYBRID_SYNTHESIS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_hybrid.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void ps_hybrid_synthesis(const Int32 *mHybridReal,
+ const Int32 *mHybridImag,
+ Int32 *mQmfReal,
+ Int32 *mQmfImag,
+ HYBRID *hHybrid);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_HYBRID_SYNTHESIS_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_init_stereo_mixing.cpp b/media/libstagefright/codecs/aacdec/ps_init_stereo_mixing.cpp
new file mode 100644
index 0000000..7027b5c
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_init_stereo_mixing.cpp
@@ -0,0 +1,496 @@
+/* ------------------------------------------------------------------
+ * 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: ps_init_stereo_mixing.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ initialize mixing procedure type Ra, type Rb is not supported
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+
+#include "pv_audio_type_defs.h"
+#include "fxp_mul32.h"
+
+#include "aac_mem_funcs.h"
+#include "pv_sine.h"
+#include "s_ps_dec.h"
+#include "ps_all_pass_filter_coeff.h"
+#include "ps_init_stereo_mixing.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+;
+; c(b) = 10^(iid(b)/20)
+;
+; Intensity differences
+;
+; sqrt(2)
+; c_1(b) = ----------------
+; sqrt( 1 + c^2(b))
+;
+; sqrt(2)*c(b)
+; c_2(b) = ----------------
+; sqrt( 1 + c^2(b))
+;
+*/
+
+
+
+#define R_SHIFT 30
+#define Q30_fmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+const Int32 scaleFactors[NO_IID_LEVELS] =
+{
+ Q30_fmt(1.411983f), Q30_fmt(1.403138f), Q30_fmt(1.386877f),
+ Q30_fmt(1.348400f), Q30_fmt(1.291249f), Q30_fmt(1.196037f),
+ Q30_fmt(1.107372f), Q30_fmt(1.000000f), Q30_fmt(0.879617f),
+ Q30_fmt(0.754649f), Q30_fmt(0.576780f), Q30_fmt(0.426401f),
+ Q30_fmt(0.276718f), Q30_fmt(0.176645f), Q30_fmt(0.079402f)
+};
+
+const Int32 scaleFactorsFine[NO_IID_LEVELS_FINE] =
+{
+ Q30_fmt(1.414207f), Q30_fmt(1.414191f), Q30_fmt(1.414143f),
+ Q30_fmt(1.413990f), Q30_fmt(1.413507f), Q30_fmt(1.411983f),
+ Q30_fmt(1.409773f), Q30_fmt(1.405395f), Q30_fmt(1.396780f),
+ Q30_fmt(1.380053f), Q30_fmt(1.348400f), Q30_fmt(1.313920f),
+ Q30_fmt(1.264310f), Q30_fmt(1.196037f), Q30_fmt(1.107372f),
+ Q30_fmt(1.000000f), Q30_fmt(0.879617f), Q30_fmt(0.754649f),
+ Q30_fmt(0.633656f), Q30_fmt(0.523081f), Q30_fmt(0.426401f),
+ Q30_fmt(0.308955f), Q30_fmt(0.221375f), Q30_fmt(0.157688f),
+ Q30_fmt(0.111982f), Q30_fmt(0.079402f), Q30_fmt(0.044699f),
+ Q30_fmt(0.025145f), Q30_fmt(0.014141f), Q30_fmt(0.007953f),
+ Q30_fmt(0.004472f)
+};
+
+
+/*
+ * alphas ranged between 0 and pi/2
+ * alpha(b) = (1/2)*arccos( gamma(b))
+ *
+ * b 0 1 2 3 4 5 6 7
+ * gamma 1 0.937 0.84118 0.60092 0.36764 0 -0.589 -1
+ *
+ */
+
+
+
+const Int32 scaled_alphas[NO_ICC_LEVELS] =
+{
+ Q30_fmt(0.00000000000000f), Q30_fmt(0.12616764875355f),
+ Q30_fmt(0.20199707286122f), Q30_fmt(0.32744135137762f),
+ Q30_fmt(0.42225800677370f), Q30_fmt(0.55536025173035f),
+ Q30_fmt(0.77803595530059f), Q30_fmt(1.11072050346071f)
+};
+
+const Int32 cos_alphas[NO_ICC_LEVELS] =
+{
+ Q30_fmt(1.00000000000000f), Q30_fmt(0.98412391153249f),
+ Q30_fmt(0.95947390717984f), Q30_fmt(0.89468446298319f),
+ Q30_fmt(0.82693418207478f), Q30_fmt(0.70710689672598f),
+ Q30_fmt(0.45332071670080f), Q30_fmt(0.00000032679490f)
+};
+
+const Int32 sin_alphas[NO_ICC_LEVELS] =
+{
+ Q30_fmt(0.00000000000000f), Q30_fmt(0.17748275057029f),
+ Q30_fmt(0.28179748302823f), Q30_fmt(0.44669868110000f),
+ Q30_fmt(0.56229872711603f), Q30_fmt(0.70710666564709f),
+ Q30_fmt(0.89134747871404f), Q30_fmt(1.00000000000000f)
+};
+
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int32 ps_init_stereo_mixing(STRUCT_PS_DEC *pms,
+ Int32 env,
+ Int32 usb)
+{
+ Int32 group;
+ Int32 bin;
+ Int32 noIidSteps;
+ Int32 tmp;
+
+ Int32 invEnvLength;
+ const Int32 *pScaleFactors;
+ Int32 scaleR;
+ Int32 scaleL;
+ Int32 cos_alpha;
+ Int32 sin_alpha;
+ Int32 beta;
+ Int32 cos_beta;
+ Int32 sin_beta;
+ Int32 temp1;
+ Int32 temp2;
+ Int32 *ptr_tmp;
+ Int32 h11;
+ Int32 h12;
+ Int32 h21;
+ Int32 h22;
+
+ if (pms->bFineIidQ)
+ {
+ noIidSteps = NO_IID_STEPS_FINE; /* NO_IID_STEPS_FINE == 15 */
+ pScaleFactors = scaleFactorsFine;
+ }
+ else
+ {
+ noIidSteps = NO_IID_STEPS; /* NO_IID_STEPS == 7 */
+ pScaleFactors = scaleFactors;
+ }
+
+ if (env == 0)
+ {
+ pms->lastUsb = pms->usb;
+ pms->usb = usb;
+ if (usb != pms->lastUsb && pms->lastUsb != 0)
+ {
+ return(-1);
+
+ }
+ }
+
+ invEnvLength = pms->aEnvStartStop[env + 1] - pms->aEnvStartStop[env];
+
+ if (invEnvLength == (Int32) pms->noSubSamples)
+ {
+ invEnvLength = pms->invNoSubSamples;
+ }
+ else
+ {
+ invEnvLength = Q30_fmt(1.0f) / invEnvLength;
+ }
+
+ if (invEnvLength == 32) /* more likely value */
+ {
+ for (group = 0; group < NO_IID_GROUPS; group++) /* == 22 */
+ {
+ bin = bins2groupMap[group];
+
+ /*
+ * c(b) = 10^(iid(b)/20)
+ */
+
+ tmp = pms->aaIidIndex[env][bin];
+
+ /*
+ * Intensity differences
+ *
+ * sqrt(2)
+ * c_1(b) = ----------------
+ * sqrt( 1 + c^2(b))
+ *
+ */
+ scaleR = pScaleFactors[noIidSteps + tmp];
+
+ /*
+ * sqrt(2)*c(b)
+ * c_2(b) = ----------------
+ * sqrt( 1 + c^2(b))
+ *
+ */
+
+ scaleL = pScaleFactors[noIidSteps - tmp];
+
+
+ /*
+ * alpha(b) = (1/2)*arccos( gamma(b))
+ */
+ tmp = pms->aaIccIndex[env][bin];
+
+ cos_alpha = cos_alphas[ tmp];
+ sin_alpha = sin_alphas[ tmp];
+
+ /*
+ * beta(b) = alpha(b)/sqrt(2)*( c_1(b) - c_2(b))
+ */
+
+ beta = fxp_mul32_Q30(scaled_alphas[ tmp], (scaleR - scaleL));
+
+ cos_beta = pv_cosine(beta);
+ sin_beta = pv_sine(beta);
+
+ temp1 = fxp_mul32_Q30(cos_beta, cos_alpha);
+ temp2 = fxp_mul32_Q30(sin_beta, sin_alpha);
+
+
+ /*
+ * h11(b) = cos( alpha(b) + beta(b))* c_2(b)
+ * h12(b) = cos( beta(b) - alpha(b))* c_1(b)
+ */
+
+ h11 = fxp_mul32_Q30(scaleL, (temp1 - temp2));
+ h12 = fxp_mul32_Q30(scaleR, (temp1 + temp2));
+
+ temp1 = fxp_mul32_Q30(sin_beta, cos_alpha);
+ temp2 = fxp_mul32_Q30(cos_beta, sin_alpha);
+
+ /*
+ * h21(b) = sin( alpha(b) + beta(b))* c_2(b)
+ * h22(b) = sin( beta(b) - alpha(b))* c_1(b)
+ */
+
+ h21 = fxp_mul32_Q30(scaleL, (temp1 + temp2));
+ h22 = fxp_mul32_Q30(scaleR, (temp1 - temp2));
+
+
+ /*
+ * Linear interpolation
+ *
+ * Hij(k, n_e+1) - Hij(k, n_e)
+ * Hij(k,n) = Hij(k, n_e) + (n - n_e)*---------------------------
+ * n_e+1 - n_e
+ */
+
+ ptr_tmp = &pms->h11Prev[group];
+ pms->H11[group] = *ptr_tmp;
+ pms->deltaH11[group] = (h11 - *ptr_tmp) >> 5;
+ *ptr_tmp = h11;
+
+ ptr_tmp = &pms->h12Prev[group];
+ pms->H12[group] = *ptr_tmp;
+ pms->deltaH12[group] = (h12 - *ptr_tmp) >> 5;
+ *ptr_tmp = h12;
+
+ ptr_tmp = &pms->h21Prev[group];
+ pms->H21[group] = *ptr_tmp;
+ pms->deltaH21[group] = (h21 - *ptr_tmp) >> 5;
+ *ptr_tmp = h21;
+
+ ptr_tmp = &pms->h22Prev[group];
+ pms->H22[group] = *ptr_tmp;
+ pms->deltaH22[group] = (h22 - *ptr_tmp) >> 5;
+ *ptr_tmp = h22;
+
+
+ } /* groups loop */
+ }
+ else
+ {
+
+ for (group = 0; group < NO_IID_GROUPS; group++) /* == 22 */
+ {
+ bin = bins2groupMap[group];
+
+ /*
+ * c(b) = 10^(iid(b)/20)
+ */
+
+ tmp = pms->aaIidIndex[env][bin];
+
+ /*
+ * Intensity differences
+ *
+ * sqrt(2)
+ * c_1(b) = ----------------
+ * sqrt( 1 + c^2(b))
+ *
+ */
+ scaleR = pScaleFactors[noIidSteps + tmp];
+
+ /*
+ * sqrt(2)*c(b)
+ * c_2(b) = ----------------
+ * sqrt( 1 + c^2(b))
+ *
+ */
+
+ scaleL = pScaleFactors[noIidSteps - tmp];
+
+
+ /*
+ * alpha(b) = (1/2)*arccos( gamma(b))
+ */
+ tmp = pms->aaIccIndex[env][bin];
+
+ cos_alpha = cos_alphas[ tmp];
+ sin_alpha = sin_alphas[ tmp];
+
+ /*
+ * beta(b) = alpha(b)/sqrt(2)*( c_1(b) - c_2(b))
+ */
+
+ beta = fxp_mul32_Q30(scaled_alphas[ tmp], (scaleR - scaleL));
+
+ cos_beta = pv_cosine(beta);
+ sin_beta = pv_sine(beta);
+
+ temp1 = fxp_mul32_Q30(cos_beta, cos_alpha);
+ temp2 = fxp_mul32_Q30(sin_beta, sin_alpha);
+
+
+ /*
+ * h11(b) = cos( alpha(b) + beta(b))* c_2(b)
+ * h12(b) = cos( beta(b) - alpha(b))* c_1(b)
+ */
+
+ h11 = fxp_mul32_Q30(scaleL, (temp1 - temp2));
+ h12 = fxp_mul32_Q30(scaleR, (temp1 + temp2));
+
+ temp1 = fxp_mul32_Q30(sin_beta, cos_alpha);
+ temp2 = fxp_mul32_Q30(cos_beta, sin_alpha);
+
+ /*
+ * h21(b) = sin( alpha(b) + beta(b))* c_2(b)
+ * h22(b) = sin( beta(b) - alpha(b))* c_1(b)
+ */
+
+ h21 = fxp_mul32_Q30(scaleL, (temp1 + temp2));
+ h22 = fxp_mul32_Q30(scaleR, (temp1 - temp2));
+
+
+ /*
+ * Linear interpolation
+ *
+ * Hij(k, n_e+1) - Hij(k, n_e)
+ * Hij(k,n) = Hij(k, n_e) + (n - n_e)*---------------------------
+ * n_e+1 - n_e
+ */
+
+ ptr_tmp = &pms->h11Prev[group];
+ pms->deltaH11[group] = fxp_mul32_Q30((h11 - *ptr_tmp), invEnvLength);
+ pms->H11[group] = *ptr_tmp;
+ *ptr_tmp = h11;
+
+ ptr_tmp = &pms->h12Prev[group];
+ pms->deltaH12[group] = fxp_mul32_Q30((h12 - *ptr_tmp), invEnvLength);
+ pms->H12[group] = *ptr_tmp;
+ *ptr_tmp = h12;
+
+ ptr_tmp = &pms->h21Prev[group];
+ pms->deltaH21[group] = fxp_mul32_Q30((h21 - *ptr_tmp), invEnvLength);
+ pms->H21[group] = *ptr_tmp;
+ *ptr_tmp = h21;
+
+ ptr_tmp = &pms->h22Prev[group];
+ pms->deltaH22[group] = fxp_mul32_Q30((h22 - *ptr_tmp), invEnvLength);
+ pms->H22[group] = *ptr_tmp;
+ *ptr_tmp = h22;
+
+
+ } /* groups loop */
+ }
+
+
+ return (0);
+
+} /* END ps_init_stereo_mixing */
+
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_init_stereo_mixing.h b/media/libstagefright/codecs/aacdec/ps_init_stereo_mixing.h
new file mode 100644
index 0000000..6c30781
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_init_stereo_mixing.h
@@ -0,0 +1,97 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_init_stereo_mixing.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for functions ps_init_stereo_mixing()
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_INIT_STEREO_MIXING_H
+#define PS_INIT_STEREO_MIXING_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_ps_dec.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ Int32 ps_init_stereo_mixing(STRUCT_PS_DEC *pms,
+ Int32 env,
+ Int32 usb);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_INIT_STEREO_MIXING_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_pwr_transient_detection.cpp b/media/libstagefright/codecs/aacdec/ps_pwr_transient_detection.cpp
new file mode 100644
index 0000000..a0e8c38
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_pwr_transient_detection.cpp
@@ -0,0 +1,340 @@
+/* ------------------------------------------------------------------
+ * 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: ps_pwr_transient_detection.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Decorrelation
+ Decorrelation is achieved by means of all-pass filtering and delaying
+ Sub-band samples s_k(n) are converted into de-correlated sub-bands samples
+ d_k(n). k index for frequency, n time index
+
+
+ _______ ________
+ | | _______ | |
+ ->|Hybrid | LF ---- | |->| Hybrid |-->
+ | Anal. | | | | | Synth | QMF -> L
+ ------- o----------------------->| | -------- Synth
+QMF | s_k(n) |Stereo |-------------->
+Anal. -------------------------->| |
+ _______ | | | | ________
+ | | HF --o | ----------- |Process| | |
+ ->| Delay | | ->| |-------->| |->| Hybrid |-->
+ ------- | |decorrelate| d_k(n) | | | Synth | QMF -> R
+ ---->| |-------->| | -------- Synth
+ ----------- |_______|-------------->
+
+
+ To handle transients and other fast time-envelopes, the output of the all
+ pass filters has to be attenuated at those signals.
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+
+#include "pv_audio_type_defs.h"
+#include "s_ps_dec.h"
+#include "aac_mem_funcs.h"
+#include "ps_all_pass_filter_coeff.h"
+#include "ps_pwr_transient_detection.h"
+
+#include "fxp_mul32.h"
+#include "pv_div.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+#ifndef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define R_SHIFT 29
+#define Q29_fmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+#define Qfmt31(a) (Int32)(-a*((Int32)1<<31) - 1 + (a>=0?0.5F:-0.5F))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void ps_pwr_transient_detection(STRUCT_PS_DEC *h_ps_dec,
+ Int32 *rIntBufferLeft,
+ Int32 *iIntBufferLeft,
+ Int32 aTransRatio[])
+{
+
+ Int32 sb;
+ Int32 maxsb;
+ Int32 gr;
+ Int32 bin;
+
+
+
+ Int32 *aLeftReal;
+ Int32 *aLeftImag;
+ Int32 temp_r;
+ Int32 temp_i;
+ Int32 accu;
+ Int32 *aPower = aTransRatio;
+ Quotient result;
+
+ Int32 nrg;
+ Int32 *ptr_aPrevNrg;
+ Int32 peakDiff;
+ Int32 *ptr_PrevPeakDiff;
+
+
+ aLeftReal = rIntBufferLeft;
+ aLeftImag = iIntBufferLeft;
+
+ /*
+ * Input Power Matrix
+ * 2
+ * Power(i,n) = SUM | s_k(n)|
+ * i
+ */
+
+ for (gr = SUBQMF_GROUPS; gr < NO_IID_GROUPS; gr++) /* 10 to 22 */
+ {
+ maxsb = min(h_ps_dec->usb, groupBorders[ gr+1]);
+
+ accu = 0;
+
+ for (sb = groupBorders[gr]; sb < maxsb; sb++)
+ {
+
+ temp_r = aLeftReal[sb];
+ temp_i = aLeftImag[sb];
+ accu = fxp_mac32_Q31(accu, temp_r, temp_r);
+ accu = fxp_mac32_Q31(accu, temp_i, temp_i);
+
+ } /* sb */
+ aPower[gr - 2] = accu >> 1;
+ } /* gr */
+
+ aLeftReal = h_ps_dec->mHybridRealLeft;
+ aLeftImag = h_ps_dec->mHybridImagLeft;
+
+
+ temp_r = aLeftReal[0];
+ temp_i = aLeftImag[0];
+ accu = fxp_mul32_Q31(temp_r, temp_r);
+ accu = fxp_mac32_Q31(accu, temp_i, temp_i);
+ temp_r = aLeftReal[5];
+ temp_i = aLeftImag[5];
+ accu = fxp_mac32_Q31(accu, temp_r, temp_r);
+ aPower[0] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1;
+
+ temp_r = aLeftReal[1];
+ temp_i = aLeftImag[1];
+ accu = fxp_mul32_Q31(temp_r, temp_r);
+ accu = fxp_mac32_Q31(accu, temp_i, temp_i);
+ temp_r = aLeftReal[4];
+ temp_i = aLeftImag[4];
+ accu = fxp_mac32_Q31(accu, temp_r, temp_r);
+ aPower[1] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1;
+
+ temp_r = aLeftReal[2];
+ temp_i = aLeftImag[2];
+ accu = fxp_mul32_Q31(temp_r, temp_r);
+ aPower[2] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1;
+
+ temp_r = aLeftReal[3];
+ temp_i = aLeftImag[3];
+ accu = fxp_mul32_Q31(temp_r, temp_r);
+ aPower[3] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1;
+
+
+
+ temp_r = aLeftReal[6];
+ temp_i = aLeftImag[6];
+ accu = fxp_mul32_Q31(temp_r, temp_r);
+ aPower[5] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1;
+
+ temp_r = aLeftReal[7];
+ temp_i = aLeftImag[7];
+ accu = fxp_mul32_Q31(temp_r, temp_r);
+ aPower[4] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1;
+
+ temp_r = aLeftReal[8];
+ temp_i = aLeftImag[8];
+ accu = fxp_mul32_Q31(temp_r, temp_r);
+ aPower[6] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1;
+
+ temp_r = aLeftReal[9];
+ temp_i = aLeftImag[9];
+ accu = fxp_mul32_Q31(temp_r, temp_r);
+ aPower[7] = fxp_mac32_Q31(accu, temp_i, temp_i) >> 1;
+
+
+ /*
+ * Power transient detection
+ */
+
+ ptr_aPrevNrg = h_ps_dec->aPrevNrg;
+
+ ptr_PrevPeakDiff = h_ps_dec->aPrevPeakDiff;
+
+ for (bin = 0; bin < NO_BINS; bin++) /* NO_BINS = 20 */
+ {
+
+ peakDiff = *ptr_PrevPeakDiff;
+
+
+ /* PEAK_DECAY_FACTOR 0.765928338364649f @ 48 KHz for Fs > 32 Khz */
+ accu = h_ps_dec->aPeakDecayFast[bin];
+ peakDiff -= peakDiff >> 2;
+
+ accu = fxp_mul32_Q31(accu, Qfmt31(0.765928338364649f)) << 1;
+
+ if (accu < *aPower)
+ {
+ accu = *aPower;
+ }
+ else
+ {
+ peakDiff += ((accu - *aPower) >> 2);
+ }
+
+ h_ps_dec->aPeakDecayFast[bin] = accu;
+
+ *(ptr_PrevPeakDiff++) = peakDiff;
+
+ nrg = *ptr_aPrevNrg + ((*aPower - *ptr_aPrevNrg) >> 2);
+
+ *(ptr_aPrevNrg++) = nrg;
+
+ peakDiff += peakDiff >> 1; /* transient impact factor == 1.5 */
+
+ if (peakDiff <= nrg)
+ {
+ *(aPower++) = 0x7FFFFFFF; /* in Q31 */
+ }
+ else
+ {
+ pv_div(nrg, peakDiff, &result);
+ *(aPower++) = (result.quotient >> (result.shift_factor)) << 1; /* in Q31 */
+ }
+
+ } /* bin */
+
+}
+
+
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/ps_pwr_transient_detection.h b/media/libstagefright/codecs/aacdec/ps_pwr_transient_detection.h
new file mode 100644
index 0000000..80a73a8
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_pwr_transient_detection.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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_pwr_transient_detection.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for function ps_pwr_transient_detection()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_PWR_TRANSIENT_DETECTION_H
+#define PS_PWR_TRANSIENT_DETECTION_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_ps_dec.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void ps_pwr_transient_detection(STRUCT_PS_DEC *h_ps_dec,
+ Int32 *rIntBufferLeft,
+ Int32 *iIntBufferLeft,
+ Int32 aTransRatio[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_PWR_TRANSIENT_DETECTION_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_read_data.cpp b/media/libstagefright/codecs/aacdec/ps_read_data.cpp
new file mode 100644
index 0000000..c49eb3d
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_read_data.cpp
@@ -0,0 +1,388 @@
+/* ------------------------------------------------------------------
+ * 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: ps_read_data.c
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Decodes parametric stereo
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+
+#include "pv_audio_type_defs.h"
+#include "buf_getbits.h"
+#include "s_bit_buffer.h"
+#include "s_huffman.h"
+#include "aac_mem_funcs.h"
+#include "s_ps_dec.h"
+#include "sbr_decode_huff_cw.h"
+#include "ps_decode_bs_utils.h"
+#include "ps_bstr_decoding.h"
+#include "ps_read_data.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/* IID & ICC Huffman codebooks */
+const Char aBookPsIidTimeDecode[28][2] =
+{
+ { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 },
+ { -62, 5 }, { -67, 6 }, { -61, 7 }, { -68, 8 },
+ { -60, 9 }, { -69, 10 }, { -59, 11 }, { -70, 12 },
+ { -58, 13 }, { -57, 14 }, { -71, 15 }, { 16, 17 },
+ { -56, -72 }, { 18, 21 }, { 19, 20 }, { -55, -78 },
+ { -77, -76 }, { 22, 25 }, { 23, 24 }, { -75, -74 },
+ { -73, -54 }, { 26, 27 }, { -53, -52 }, { -51, -50 }
+};
+
+const Char aBookPsIidFreqDecode[28][2] =
+{
+ { -64, 1 }, { 2, 3 }, { -63, -65 }, { 4, 5 },
+ { -62, -66 }, { 6, 7 }, { -61, -67 }, { 8, 9 },
+ { -68, -60 }, { -59, 10 }, { -69, 11 }, { -58, 12 },
+ { -70, 13 }, { -71, 14 }, { -57, 15 }, { 16, 17 },
+ { -56, -72 }, { 18, 19 }, { -55, -54 }, { 20, 21 },
+ { -73, -53 }, { 22, 24 }, { -74, 23 }, { -75, -78 },
+ { 25, 26 }, { -77, -76 }, { -52, 27 }, { -51, -50 }
+};
+
+const Char aBookPsIccTimeDecode[14][2] =
+{
+ { -64, 1 }, { -63, 2 }, { -65, 3 }, { -62, 4 },
+ { -66, 5 }, { -61, 6 }, { -67, 7 }, { -60, 8 },
+ { -68, 9 }, { -59, 10 }, { -69, 11 }, { -58, 12 },
+ { -70, 13 }, { -71, -57 }
+};
+
+const Char aBookPsIccFreqDecode[14][2] =
+{
+ { -64, 1 }, { -63, 2 }, { -65, 3 }, { -62, 4 },
+ { -66, 5 }, { -61, 6 }, { -67, 7 }, { -60, 8 },
+ { -59, 9 }, { -68, 10 }, { -58, 11 }, { -69, 12 },
+ { -57, 13 }, { -70, -71 }
+};
+
+const Char aBookPsIidFineTimeDecode[60][2] =
+{
+ { 1, -64 }, { -63, 2 }, { 3, -65 }, { 4, 59 },
+ { 5, 7 }, { 6, -67 }, { -68, -60 }, { -61, 8 },
+ { 9, 11 }, { -59, 10 }, { -70, -58 }, { 12, 41 },
+ { 13, 20 }, { 14, -71 }, { -55, 15 }, { -53, 16 },
+ { 17, -77 }, { 18, 19 }, { -85, -84 }, { -46, -45 },
+ { -57, 21 }, { 22, 40 }, { 23, 29 }, { -51, 24 },
+ { 25, 26 }, { -83, -82 }, { 27, 28 }, { -90, -38 },
+ { -92, -91 }, { 30, 37 }, { 31, 34 }, { 32, 33 },
+ { -35, -34 }, { -37, -36 }, { 35, 36 }, { -94, -93 },
+ { -89, -39 }, { 38, -79 }, { 39, -81 }, { -88, -40 },
+ { -74, -54 }, { 42, -69 }, { 43, 44 }, { -72, -56 },
+ { 45, 52 }, { 46, 50 }, { 47, -76 }, { -49, 48 },
+ { -47, 49 }, { -87, -41 }, { -52, 51 }, { -78, -50 },
+ { 53, -73 }, { 54, -75 }, { 55, 57 }, { 56, -80 },
+ { -86, -42 }, { -48, 58 }, { -44, -43 }, { -66, -62 }
+};
+
+const Char aBookPsIidFineFreqDecode[60][2] =
+{
+ { 1, -64 }, { 2, 4 }, { 3, -65 }, { -66, -62 },
+ { -63, 5 }, { 6, 7 }, { -67, -61 }, { 8, 9 },
+ { -68, -60 }, { 10, 11 }, { -69, -59 }, { 12, 13 },
+ { -70, -58 }, { 14, 18 }, { -57, 15 }, { 16, -72 },
+ { -54, 17 }, { -75, -53 }, { 19, 37 }, { -56, 20 },
+ { 21, -73 }, { 22, 29 }, { 23, -76 }, { 24, -78 },
+ { 25, 28 }, { 26, 27 }, { -85, -43 }, { -83, -45 },
+ { -81, -47 }, { -52, 30 }, { -50, 31 }, { 32, -79 },
+ { 33, 34 }, { -82, -46 }, { 35, 36 }, { -90, -89 },
+ { -92, -91 }, { 38, -71 }, { -55, 39 }, { 40, -74 },
+ { 41, 50 }, { 42, -77 }, { -49, 43 }, { 44, 47 },
+ { 45, 46 }, { -86, -42 }, { -88, -87 }, { 48, 49 },
+ { -39, -38 }, { -41, -40 }, { -51, 51 }, { 52, 59 },
+ { 53, 56 }, { 54, 55 }, { -35, -34 }, { -37, -36 },
+ { 57, 58 }, { -94, -93 }, { -84, -44 }, { -80, -48 }
+};
+
+
+
+
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int32 ps_read_data(STRUCT_PS_DEC *ps_dec,
+ BIT_BUFFER * hBitBuf,
+ Int32 nBitsLeft)
+
+{
+ Int gr;
+ UInt32 env;
+ UInt32 dtFlag;
+ Int32 startbits;
+ SbrHuffman CurrentTable;
+
+ if (!ps_dec)
+ {
+ return 0;
+ }
+
+ startbits = GetNrBitsAvailable(hBitBuf);
+
+ if (buf_get_1bit(hBitBuf)) /* Enable Header */
+ {
+ ps_dec->bEnableIid = buf_get_1bit(hBitBuf);
+
+ if (ps_dec->bEnableIid)
+ {
+ ps_dec->freqResIid = buf_getbits(hBitBuf, 3);
+
+ if (ps_dec->freqResIid > 2)
+ {
+ ps_dec->bFineIidQ = 1;
+ ps_dec->freqResIid -= 3;
+ }
+ else
+ {
+ ps_dec->bFineIidQ = 0;
+ }
+ }
+
+ ps_dec->bEnableIcc = buf_get_1bit(hBitBuf);
+ if (ps_dec->bEnableIcc)
+ {
+ ps_dec->freqResIcc = buf_getbits(hBitBuf, 3);
+
+ if (ps_dec->freqResIcc > 2)
+ {
+ ps_dec->freqResIcc -= 3;
+ }
+ }
+ ps_dec->bEnableExt = buf_get_1bit(hBitBuf);
+ }
+
+ ps_dec->bFrameClass = buf_get_1bit(hBitBuf);
+ if (ps_dec->bFrameClass == 0)
+ {
+ ps_dec->noEnv = aFixNoEnvDecode[ buf_getbits(hBitBuf, 2)];
+ }
+ else
+ {
+ ps_dec->noEnv = 1 + buf_getbits(hBitBuf, 2);
+ for (env = 1; env < ps_dec->noEnv + 1; env++)
+ {
+ ps_dec->aEnvStartStop[env] = (buf_getbits(hBitBuf, 5)) + 1;
+ }
+ }
+
+ if ((ps_dec->freqResIid > 2) || (ps_dec->freqResIcc > 2))
+ {
+
+ ps_dec->bPsDataAvail = 0;
+
+ nBitsLeft -= startbits - GetNrBitsAvailable(hBitBuf);
+ while (nBitsLeft)
+ {
+ int i = nBitsLeft;
+ if (i > 8)
+ {
+ i = 8;
+ }
+ buf_getbits(hBitBuf, i);
+ nBitsLeft -= i;
+ }
+ return (startbits - GetNrBitsAvailable(hBitBuf));
+ }
+
+ if (ps_dec->bEnableIid)
+ {
+ for (env = 0; env < ps_dec->noEnv; env++)
+ {
+ dtFlag = buf_get_1bit(hBitBuf);
+
+ if (!dtFlag)
+ {
+ if (ps_dec->bFineIidQ)
+ {
+ CurrentTable = aBookPsIidFineFreqDecode;
+ }
+ else
+ {
+ CurrentTable = aBookPsIidFreqDecode;
+ }
+ }
+ else
+ {
+ if (ps_dec->bFineIidQ)
+ {
+ CurrentTable = aBookPsIidFineTimeDecode;
+ }
+ else
+ {
+ CurrentTable = aBookPsIidTimeDecode;
+ }
+ }
+
+ for (gr = 0; gr < aNoIidBins[ps_dec->freqResIid]; gr++)
+ {
+ ps_dec->aaIidIndex[env][gr] = sbr_decode_huff_cw(CurrentTable, hBitBuf);
+ }
+
+ ps_dec->abIidDtFlag[env] = dtFlag;
+ }
+ }
+
+ if (ps_dec->bEnableIcc)
+ {
+ for (env = 0; env < ps_dec->noEnv; env++)
+ {
+ dtFlag = buf_get_1bit(hBitBuf);
+ if (!dtFlag)
+ {
+ CurrentTable = aBookPsIccFreqDecode;
+ }
+ else
+ {
+ CurrentTable = aBookPsIccTimeDecode;
+ }
+ for (gr = 0; gr < aNoIccBins[ps_dec->freqResIcc]; gr++)
+ {
+ ps_dec->aaIccIndex[env][gr] = sbr_decode_huff_cw(CurrentTable, hBitBuf);
+ }
+
+ ps_dec->abIccDtFlag[env] = dtFlag;
+ }
+ }
+
+ if (ps_dec->bEnableExt)
+ {
+
+ int cnt;
+
+ cnt = (int)buf_getbits(hBitBuf, 4);
+
+ if (cnt == 15)
+ {
+ cnt += (int)buf_getbits(hBitBuf, 8);
+ }
+
+ hBitBuf->nrBitsRead += (cnt << 3);
+ }
+
+ ps_dec->bPsDataAvail = 1;
+
+ return (startbits - GetNrBitsAvailable(hBitBuf));
+}
+
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_read_data.h b/media/libstagefright/codecs/aacdec/ps_read_data.h
new file mode 100644
index 0000000..e2fec53
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_read_data.h
@@ -0,0 +1,100 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_read_data.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for functions ps_read_data()
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_READ_DATA_H
+#define PS_READ_DATA_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_ps_dec.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+#define EXTENSION_ID_PS_CODING 2
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ Int32 ps_read_data(STRUCT_PS_DEC *ps_dec,
+ BIT_BUFFER * hBitBuf,
+ Int32 nBitsLeft);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_READ_DATA_H */
diff --git a/media/libstagefright/codecs/aacdec/ps_stereo_processing.cpp b/media/libstagefright/codecs/aacdec/ps_stereo_processing.cpp
new file mode 100644
index 0000000..813b55d
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_stereo_processing.cpp
@@ -0,0 +1,372 @@
+/* ------------------------------------------------------------------
+ * 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: ps_stereo_processing.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Stereo Process or reconstruction
+
+ l_k(n) = H11(k,n)*s_k(n) + H21(k,n)*d_k(n)
+
+ r_k(n) = H12(k,n)*s_k(n) + H22(k,n)*d_k(n)
+
+ _______ ________
+ | | _______ | |
+ ->|Hybrid | LF ---- | |->| Hybrid |-->
+ | Anal. | | | | | Synth | QMF -> L
+ ------- o----------------------->| | -------- Synth
+QMF | s_k(n) |Stereo |-------------->
+Anal. -------------------------->| |
+ _______ | | | | ________
+ | | HF --o | ----------- |Process| | |
+ ->| Delay | | ->| |-------->| |->| Hybrid |-->
+ ------- | |decorrelate| d_k(n) | | | Synth | QMF -> R
+ ---->| |-------->| | -------- Synth
+ ----------- |_______|-------------->
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+#include "pv_audio_type_defs.h"
+#include "ps_stereo_processing.h"
+#include "fxp_mul32.h"
+#include "ps_all_pass_filter_coeff.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+#ifndef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void ps_stereo_processing(STRUCT_PS_DEC *pms,
+ Int32 *qmfLeftReal,
+ Int32 *qmfLeftImag,
+ Int32 *qmfRightReal,
+ Int32 *qmfRightImag)
+{
+ Int32 group;
+ Int32 subband;
+ Int32 maxSubband;
+ Int32 usb;
+ Char index;
+
+
+ Int32 *hybrLeftReal;
+ Int32 *hybrLeftImag;
+ Int32 *hybrRightReal;
+ Int32 *hybrRightImag;
+ Int32 *ptr_hybrLeftReal;
+ Int32 *ptr_hybrLeftImag;
+ Int32 *ptr_hybrRightReal;
+ Int32 *ptr_hybrRightImag;
+
+
+ Int16 h11;
+ Int16 h12;
+ Int16 h21;
+ Int16 h22;
+
+ Int32 temp1;
+ Int32 temp2;
+ Int32 temp3;
+
+ usb = pms->usb;
+
+ /*
+ * Complete Linear interpolation
+ */
+
+ hybrLeftReal = pms->mHybridRealLeft;
+ hybrLeftImag = pms->mHybridImagLeft;
+ hybrRightReal = pms->mHybridRealRight;
+ hybrRightImag = pms->mHybridImagRight;
+
+ for (group = 0; group < SUBQMF_GROUPS; group++) /* SUBQMF_GROUPS == 10 */
+ {
+
+ temp1 = pms->deltaH11[group];
+ temp2 = pms->deltaH12[group];
+
+ pms->H11[group] += temp1;
+ h11 = (Int16)(pms->H11[group] >> 16);
+ pms->H12[group] += temp2;
+ h12 = (Int16)(pms->H12[group] >> 16);
+
+ temp1 = pms->deltaH21[group];
+ temp2 = pms->deltaH22[group];
+
+ pms->H21[group] += temp1;
+ h21 = (Int16)(pms->H21[group] >> 16);
+ pms->H22[group] += temp2;
+ h22 = (Int16)(pms->H22[group] >> 16);
+
+ index = groupBorders[group];
+
+ /*
+ * Reconstruction of Stereo sub-band signal
+ *
+ * l_k(n) = H11(k,n)*s_k(n) + H21(k,n)*d_k(n)
+ *
+ * r_k(n) = H12(k,n)*s_k(n) + H22(k,n)*d_k(n)
+ */
+ ptr_hybrLeftReal = &hybrLeftReal[ index];
+ ptr_hybrRightReal = &hybrRightReal[ index];
+
+ temp1 = *(ptr_hybrLeftReal) << 1;
+ temp2 = *(ptr_hybrRightReal) << 1;
+
+ temp3 = fxp_mul32_by_16(temp1, h11);
+ *(ptr_hybrLeftReal) = fxp_mac32_by_16(temp2, h21, temp3) << 1;
+
+ temp3 = fxp_mul32_by_16(temp1, h12);
+ *(ptr_hybrRightReal) = fxp_mac32_by_16(temp2, h22, temp3) << 1;
+
+
+ ptr_hybrLeftImag = &hybrLeftImag[ index];
+ ptr_hybrRightImag = &hybrRightImag[ index];
+
+ temp1 = *(ptr_hybrLeftImag) << 1;
+ temp2 = *(ptr_hybrRightImag) << 1;
+
+ temp3 = fxp_mul32_by_16(temp1, h11);
+ *(ptr_hybrLeftImag) = fxp_mac32_by_16(temp2, h21, temp3) << 1;
+
+ temp3 = fxp_mul32_by_16(temp1, h12);
+ *(ptr_hybrRightImag) = fxp_mac32_by_16(temp2, h22, temp3) << 1;
+
+
+ } /* groups loop */
+
+ temp1 = pms->deltaH11[SUBQMF_GROUPS];
+ temp2 = pms->deltaH12[SUBQMF_GROUPS];
+
+ pms->H11[SUBQMF_GROUPS] += temp1;
+ h11 = (Int16)(pms->H11[SUBQMF_GROUPS] >> 16);
+ pms->H12[SUBQMF_GROUPS] += temp2;
+ h12 = (Int16)(pms->H12[SUBQMF_GROUPS] >> 16);
+
+ temp1 = pms->deltaH21[SUBQMF_GROUPS];
+ temp2 = pms->deltaH22[SUBQMF_GROUPS];
+
+ pms->H21[SUBQMF_GROUPS] += temp1;
+ h21 = (Int16)(pms->H21[SUBQMF_GROUPS] >> 16);
+ pms->H22[SUBQMF_GROUPS] += temp2;
+ h22 = (Int16)(pms->H22[SUBQMF_GROUPS] >> 16);
+
+
+ ptr_hybrLeftReal = &qmfLeftReal[ 3];
+ ptr_hybrRightReal = &qmfRightReal[ 3];
+
+ /*
+ * Reconstruction of Stereo sub-band signal
+ *
+ * l_k(n) = H11(k,n)*s_k(n) + H21(k,n)*d_k(n)
+ *
+ * r_k(n) = H12(k,n)*s_k(n) + H22(k,n)*d_k(n)
+ */
+ temp1 = *(ptr_hybrLeftReal) << 1;
+ temp2 = *(ptr_hybrRightReal) << 1;
+
+
+ temp3 = fxp_mul32_by_16(temp1, h11);
+ *(ptr_hybrLeftReal) = fxp_mac32_by_16(temp2, h21, temp3) << 1;
+
+ temp3 = fxp_mul32_by_16(temp1, h12);
+ *(ptr_hybrRightReal) = fxp_mac32_by_16(temp2, h22, temp3) << 1;
+
+ ptr_hybrLeftImag = &qmfLeftImag[ 3];
+ ptr_hybrRightImag = &qmfRightImag[ 3];
+
+
+ temp1 = *(ptr_hybrLeftImag) << 1;
+ temp2 = *(ptr_hybrRightImag) << 1;
+
+ temp3 = fxp_mul32_by_16(temp1, h11);
+ *(ptr_hybrLeftImag) = fxp_mac32_by_16(temp2, h21, temp3) << 1;
+
+ temp3 = fxp_mul32_by_16(temp1, h12);
+ *(ptr_hybrRightImag) = fxp_mac32_by_16(temp2, h22, temp3) << 1;
+
+
+ for (group = SUBQMF_GROUPS + 1; group < NO_IID_GROUPS; group++) /* 11 to NO_IID_GROUPS == 22 */
+ {
+ temp1 = pms->deltaH11[group];
+ temp2 = pms->deltaH12[group];
+
+ pms->H11[group] += temp1;
+ h11 = (Int16)(pms->H11[group] >> 16);
+ pms->H12[group] += temp2;
+ h12 = (Int16)(pms->H12[group] >> 16);
+
+ temp1 = pms->deltaH21[group];
+ temp2 = pms->deltaH22[group];
+
+ pms->H21[group] += temp1;
+ h21 = (Int16)(pms->H21[group] >> 16);
+ pms->H22[group] += temp2;
+ h22 = (Int16)(pms->H22[group] >> 16);
+
+ index = groupBorders[group];
+ maxSubband = groupBorders[group + 1];
+ maxSubband = min(usb, maxSubband);
+
+ /*
+ * Reconstruction of Stereo sub-band signal
+ *
+ * l_k(n) = H11(k,n)*s_k(n) + H21(k,n)*d_k(n)
+ *
+ * r_k(n) = H12(k,n)*s_k(n) + H22(k,n)*d_k(n)
+ */
+
+ ptr_hybrLeftReal = &qmfLeftReal[ index];
+ ptr_hybrRightReal = &qmfRightReal[ index];
+
+ for (subband = index; subband < maxSubband; subband++)
+ {
+ temp1 = *(ptr_hybrLeftReal) << 1;
+ temp2 = *(ptr_hybrRightReal) << 1;
+ temp3 = fxp_mul32_by_16(temp1, h11);
+ *(ptr_hybrLeftReal++) = fxp_mac32_by_16(temp2, h21, temp3) << 1;
+
+ temp3 = fxp_mul32_by_16(temp1, h12);
+ *(ptr_hybrRightReal++) = fxp_mac32_by_16(temp2, h22, temp3) << 1;
+ }
+
+ ptr_hybrLeftImag = &qmfLeftImag[ index];
+ ptr_hybrRightImag = &qmfRightImag[ index];
+
+ for (subband = index; subband < maxSubband; subband++)
+ {
+ temp1 = *(ptr_hybrLeftImag) << 1;
+ temp2 = *(ptr_hybrRightImag) << 1;
+ temp3 = fxp_mul32_by_16(temp1, h11);
+ *(ptr_hybrLeftImag++) = fxp_mac32_by_16(temp2, h21, temp3) << 1;
+
+ temp3 = fxp_mul32_by_16(temp1, h12);
+ *(ptr_hybrRightImag++) = fxp_mac32_by_16(temp2, h22, temp3) << 1;
+
+ } /* subband loop */
+
+ } /* groups loop */
+
+} /* END ps_stereo_processing */
+
+
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/ps_stereo_processing.h b/media/libstagefright/codecs/aacdec/ps_stereo_processing.h
new file mode 100644
index 0000000..58b025a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/ps_stereo_processing.h
@@ -0,0 +1,98 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ps_stereo_processing.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for function ps_stereo_processing()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PS_STEREO_PROCESSING_H
+#define PS_STEREO_PROCESSING_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_ps_dec.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void ps_stereo_processing(STRUCT_PS_DEC *pms,
+ Int32 *qmfLeftReal,
+ Int32 *qmfLeftImag,
+ Int32 *qmfRightReal,
+ Int32 *qmfRightImag);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* PS_STEREO_PROCESSING_H */
diff --git a/media/libstagefright/codecs/aacdec/pulse_nc.cpp b/media/libstagefright/codecs/aacdec/pulse_nc.cpp
new file mode 100644
index 0000000..87b264d
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pulse_nc.cpp
@@ -0,0 +1,298 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pulse_nc.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Modified to pass variables by reference to eliminate use
+ of global variables.
+
+ Description: Modified to bring code in-line with PV standards.
+
+ Description: Pass in max as input argument.
+
+ Description: Went back to the if-statement to check for max.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ coef[] = Array of quantized spectral coefficents.
+ (Int [])
+
+ pPulseInfo = Pointer to structure which contains noiseless
+ encoding info, includes information about the pulse data,
+ pulse amplitude, etc.
+ (const PulseInfo *)
+
+ pLongFrameInfo = Pointer to structure that holds information about
+ each group. (long block flag, number of windows,
+ scalefactor bands per group, etc.)
+
+ Variable is named (pLongFrameInfo) because this function
+ is only used for LONG windows.
+ (FrameInfo *)
+ max = Pointer to the maximum value of coef[]
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ coef[] = coefficient contents are modified by the encoded pulse
+
+ Local Stores Modified:
+
+ Global Stores Modified:
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function adds pulses to defined ranges of coefficients in the window,
+ for the case of LONG windows. The pulses are unsigned, so
+ negative coefficients subtract the pulse, and positive coefficients add it.
+ (The ampltiude of the coefficient is always increased by the pulse)
+
+ A maximum of 4 coefficients may be modified by a pulse, and these
+ coefficients must all occur in the same scalefactor band.
+
+ The number of pulse-encoded coefficients to be processed by this function
+ is communicated to this function via pPulseInfo->number_pulse
+
+ This value is equal to the actual number of pulses - 1.
+ (e.g if pPulseInfo->number_pulse == 0, one pulse is assumed)
+ This function must not be called if no pulse encoded data exists.
+ The function assumes that at least one pulse exists.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This module shall correctly add transmitted pulse(s) to the correct
+ coefficients in a LONG window.
+
+------------------------------------------------------------------------------
+ REFERENCES
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.6.3.3 Decoding Process
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ index = pLongFrameInfo->win_sfb_top[0][pPulseInfo->pulse_start_sfb];
+
+ pPulseOffset = &(pPulseInfo->pulse_offset[0]);
+
+ pPulseAmp = &(pPulseInfo->pulse_amp[0]);
+
+ pCoef = &(Coef[index]);
+
+ FOR (index = pPulseInfo->number_pulse; index >= 0; index--)
+
+ pCoef = pCoef + *(pPulseOffset);
+ pPulseOffset = pPulseOffset + 1;
+
+ IF (*pCoef > 0)
+ *(pCoef) = *(pCoef) + *(pPulseAmp);
+ pPulseAmp = pPulseAmp + 1;
+ ELSE
+ *(pCoef) = *(pCoef) - *(pPulseAmp);
+ pPulseAmp = pPulseAmp + 1;
+ ENDIF
+
+ ENDFOR
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_frameinfo.h"
+#include "s_pulseinfo.h"
+#include "pulse_nc.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pulse_nc(
+ Int16 coef[],
+ const PulseInfo *pPulseInfo,
+ const FrameInfo *pLongFrameInfo,
+ Int *max)
+{
+ Int index;
+
+ Int16 *pCoef;
+ Int temp;
+
+ const Int *pPulseOffset;
+ const Int *pPulseAmp;
+
+ /*--- Find the scalefactor band where pulse-encoded data starts ---*/
+
+ if (pPulseInfo->pulse_start_sfb > 0)
+ {
+ index = pLongFrameInfo->win_sfb_top[0][pPulseInfo->pulse_start_sfb - 1];
+ }
+ else
+ {
+ index = 0;
+ }
+
+ /*-------------------------------------------------------------------------
+ Each pulse index is stored as an offset from the previous pulse
+
+ Example - here we have a sfb that is 20 coefficients in length:
+
+ [0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19]
+ [ ][ ][ ][ ][ ][P][P][ ][ ][ ][ ][ ][ ][ ][ ][ P][ ][ ][ ][ P]
+
+ The array pointed to by pPulseOffset == [5][1][9][4]
+
+ pPulseAmp is of the same length as pPulseOffset, and contains
+ an individual pulse amplitude for each coefficient.
+ --------------------------------------------------------------------------*/
+
+ pCoef = &(coef[index]);
+
+ pPulseOffset = &(pPulseInfo->pulse_offset[0]);
+
+ pPulseAmp = &(pPulseInfo->pulse_amp[0]);
+
+ for (index = pPulseInfo->number_pulse; index > 0; index--)
+ {
+ pCoef += *pPulseOffset++;
+
+ temp = *pCoef;
+
+ if (temp > 0)
+ {
+ temp += *(pPulseAmp++);
+ *pCoef = (Int16)temp;
+ if (temp > *max)
+ {
+ *max = temp;
+ }
+ }
+ else
+ {
+ temp -= *(pPulseAmp++);
+ *pCoef = (Int16)temp;
+ if (-temp > *max)
+ {
+ *max = -temp;
+ }
+ }
+
+ } /* for() */
+
+ return;
+
+} /* pulse_nc */
diff --git a/media/libstagefright/codecs/aacdec/pulse_nc.h b/media/libstagefright/codecs/aacdec/pulse_nc.h
new file mode 100644
index 0000000..8181dd0
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pulse_nc.h
@@ -0,0 +1,104 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pulse_nc.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Pass in max as input argument.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file contains the global function declaration for pulse_nc
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PULSE_NC_H
+#define PULSE_NC_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_frameinfo.h"
+#include "s_pulseinfo.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void pulse_nc(
+ Int16 coef[],
+ const PulseInfo *pPulseInfo,
+ const FrameInfo *pLongFrameInfo,
+ Int *max);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/pv_audio_type_defs.h b/media/libstagefright/codecs/aacdec/pv_audio_type_defs.h
new file mode 100644
index 0000000..dee66bc
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pv_audio_type_defs.h
@@ -0,0 +1,183 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ Pathname: ./c/include/pv_audio_type_defs.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Removed errant semicolons from #define statements
+
+ Description:
+ 1. Modified ifndef STD_TYPE_DEFS_H with
+ #ifndef PV_AUDIO_TYPE_DEFS_H to avoid double definition
+ if file was already included
+ 2. Merged cai if-def structures and C++ definition
+ 3. Updated copyright notice
+
+ Description: Added dependency on OSCL libraries
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file was derived from a number of standards bodies. The type
+ definitions below were created from some of the best practices observed
+ in the standards bodies.
+
+ This file is dependent on limits.h for defining the bit widths. In an
+ ANSI C environment limits.h is expected to always be present and contain
+ the following definitions:
+
+ SCHAR_MIN
+ SCHAR_MAX
+ UCHAR_MAX
+
+ INT_MAX
+ INT_MIN
+ UINT_MAX
+
+ SHRT_MIN
+ SHRT_MAX
+ USHRT_MAX
+
+ LONG_MIN
+ LONG_MAX
+ ULONG_MAX
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PV_AUDIO_TYPE_DEFS_H
+#define PV_AUDIO_TYPE_DEFS_H
+
+#include <stdint.h>
+
+typedef int8_t Char;
+
+typedef uint8_t UChar;
+
+
+
+/*----------------------------------------------------------------------------
+; Define generic signed and unsigned int
+----------------------------------------------------------------------------*/
+#ifndef Int
+typedef signed int Int;
+#endif
+
+#ifndef UInt
+typedef unsigned int UInt;
+#endif
+
+
+/*----------------------------------------------------------------------------
+; Define 16 bit signed and unsigned words
+----------------------------------------------------------------------------*/
+
+
+#ifndef Int16
+typedef int16_t Int16;
+#endif
+
+#ifndef INT16_MIN
+#define INT16_MIN (-32768)
+#endif
+
+#ifndef INT16_MAX
+#define INT16_MAX 32767
+#endif
+
+#ifndef UInt16
+typedef uint16_t UInt16;
+
+#endif
+
+
+/*----------------------------------------------------------------------------
+; Define 32 bit signed and unsigned words
+----------------------------------------------------------------------------*/
+
+
+#ifndef Int32
+typedef int32_t Int32;
+#endif
+
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647 - 1)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX 2147483647
+#endif
+
+#ifndef UInt32
+typedef uint32_t UInt32;
+#endif
+
+#ifndef UINT32_MIN
+#define UINT32_MIN 0
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX 0xffffffff
+#endif
+
+
+/*----------------------------------------------------------------------------
+; Define 64 bit signed and unsigned words
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Define boolean type
+----------------------------------------------------------------------------*/
+#ifndef Bool
+typedef Int Bool;
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef OFF
+#define OFF 0
+#endif
+#ifndef ON
+#define ON 1
+#endif
+
+#ifndef NO
+#define NO 0
+#endif
+#ifndef YES
+#define YES 1
+#endif
+
+#ifndef SUCCESS
+#define SUCCESS 0
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+#endif /* PV_AUDIO_TYPE_DEFS_H */
diff --git a/media/libstagefright/codecs/aacdec/pv_div.cpp b/media/libstagefright/codecs/aacdec/pv_div.cpp
new file mode 100644
index 0000000..86d2487
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pv_div.cpp
@@ -0,0 +1,188 @@
+/* ------------------------------------------------------------------
+ * 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: pv_div.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 x 32-bit integer numerator
+ Int32 y 32-bit integer denominator
+ Quotient *result structure that hold result and shift factor
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement division of two Int32 numbers, provides back quotient and a
+ shift factor
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#ifdef AAC_PLUS
+
+
+#include "pv_audio_type_defs.h"
+#include "fxp_mul32.h"
+#include "pv_div.h"
+#include "pv_normalize.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void pv_div(Int32 x, Int32 y, Quotient *result)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ Int32 quotient;
+ Int32 i;
+ Int32 j;
+ Int32 y_ov_y_hi;
+ Int32 flag = 0; /* carries negative sign, if any */
+
+
+ result->shift_factor = 0; /* default */
+
+ if (y == 0)
+ {
+ x = 0; /* this will return 0 for any div/0 */
+ }
+ /*
+ * make sure x and y are both positive
+ */
+
+ if (y < 0)
+ {
+ y = -y;
+ flag ^= 1;
+ }
+
+
+ if (x < 0)
+ {
+ x = -x;
+ flag ^= 1;
+ }
+
+ if (x != 0)
+ {
+ /*----------------------------------------------------------------------------
+ ; Scale the input to get maximum precision for x
+ ----------------------------------------------------------------------------*/
+
+ i = pv_normalize(x);
+
+ x <<= i;
+
+
+ /*----------------------------------------------------------------------------
+ ; Scale the input to get maximum precision for y
+ ----------------------------------------------------------------------------*/
+
+ j = pv_normalize(y);
+
+ y <<= j;
+
+ result->shift_factor = i - j;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /*---------------------------------------------------------------
+ ; take the inverse of the 16 MSB of y
+ ---------------------------------------------------------------*/
+
+ quotient = (0x40000000 / (y >> 15));
+
+ y_ov_y_hi = fxp_mul32_Q15(y, quotient); /* y*(1/y_hi) */
+
+ y_ov_y_hi = 0x7FFFFFFF - y_ov_y_hi; /* 2 - y*(1/y_hi) */
+ y_ov_y_hi = fxp_mul32_Q14(quotient, y_ov_y_hi);
+ i = fxp_mul32_Q31(y_ov_y_hi, x) << 1;
+
+ result->quotient = flag ? -i : i;
+ }
+ else
+ {
+ result->quotient = 0;
+ }
+
+
+
+}
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/pv_div.h b/media/libstagefright/codecs/aacdec/pv_div.h
new file mode 100644
index 0000000..2dfa8a0
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pv_div.h
@@ -0,0 +1,74 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pv_div.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PV_DIV_H
+#define PV_DIV_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ struct intg_div
+ {
+ Int32 quotient;
+ Int32 shift_factor;
+ };
+ typedef struct intg_div Quotient;
+
+
+ void pv_div(Int32 x, Int32 y, Quotient *quotient);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PV_DIV_H */
diff --git a/media/libstagefright/codecs/aacdec/pv_log2.cpp b/media/libstagefright/codecs/aacdec/pv_log2.cpp
new file mode 100644
index 0000000..69cbe91
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pv_log2.cpp
@@ -0,0 +1,168 @@
+/* ------------------------------------------------------------------
+ * 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: pv_log2.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 x 32-bit integer input
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement the logarithm base 2 of a number
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "pv_log2.h"
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+#define R_SHIFT 20
+#define Q_fmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+const Int32 log_table[9] =
+{
+ Q_fmt(-0.00879832091331F), Q_fmt(0.12022974263833F),
+ Q_fmt(-0.72883958314294F), Q_fmt(2.57909824242332F),
+ Q_fmt(-5.90041216630330F), Q_fmt(9.15023342527264F),
+ Q_fmt(-9.90616619500413F), Q_fmt(8.11228968755409F),
+ Q_fmt(-3.41763474309898F)
+};
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+Int32 pv_log2(Int32 z)
+{
+ const Int32 *pt_table = log_table;
+ Int32 y;
+ Int32 i;
+
+ Int32 int_log2 = 0;
+
+ if (z > Q_fmt(2.0f))
+ {
+ while (z > Q_fmt(2.0f))
+ {
+ z >>= 1;
+ int_log2++;
+ }
+ }
+ else if (z < Q_fmt(1.0f))
+ {
+ {
+ while (z < Q_fmt(1.0f))
+ {
+ z <<= 1;
+ int_log2--;
+ }
+ }
+ }
+
+ /*
+ * at this point, input limited to 1<x<2
+ */
+
+ if (z != Q_fmt(1.0f))
+ {
+ y = fxp_mul32_Q20(*(pt_table++), z);
+
+ for (i = 7; i != 0; i--)
+ {
+ y += *(pt_table++);
+ y = fxp_mul32_Q20(y, z);
+ }
+
+ y += *(pt_table++);
+ }
+ else
+ {
+ y = 0;
+ }
+
+
+ return (y + (int_log2 << 20)); /* Q20 */
+}
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/pv_log2.h b/media/libstagefright/codecs/aacdec/pv_log2.h
new file mode 100644
index 0000000..4834e82
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pv_log2.h
@@ -0,0 +1,69 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pv_log2.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PV_LOG2_H
+#define PV_LOG2_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ Int32 pv_log2(Int32 z);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PV_LOG2_H */
diff --git a/media/libstagefright/codecs/aacdec/pv_normalize.cpp b/media/libstagefright/codecs/aacdec/pv_normalize.cpp
new file mode 100644
index 0000000..365b5ad
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pv_normalize.cpp
@@ -0,0 +1,167 @@
+/* ------------------------------------------------------------------
+ * 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: pv_normalize.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+ Int32 x 32-bit integer non-zero input
+Returns
+ Int32 i number of leading zeros on x
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Returns number of leading zeros on the non-zero input
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+#include "pv_normalize.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+#if defined(_ARM)
+#elif (defined(PV_ARM_GCC_V5)||defined(PV_ARM_GCC_V4))
+/* function is inlined in header file */
+
+
+#else
+
+Int pv_normalize(Int32 x)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ Int i;
+
+
+ if (x > 0x0FFFFFFF)
+ {
+ i = 0; /* most likely case */
+ }
+ else if (x > 0x00FFFFFF)
+ {
+ i = 3; /* second most likely case */
+ }
+ else if (x > 0x0000FFFF)
+ {
+ i = x > 0x000FFFFF ? 7 : 11;
+ }
+ else
+ {
+ if (x > 0x000000FF)
+ {
+ i = x > 0x00000FFF ? 15 : 19;
+ }
+ else
+ {
+ i = x > 0x0000000F ? 23 : 27;
+ }
+ }
+
+
+ x <<= i;
+
+ switch (x & 0x78000000)
+ {
+ case 0x08000000:
+ i += 3;
+ break;
+
+ case 0x18000000:
+ case 0x10000000:
+ i += 2;
+ break;
+ case 0x28000000:
+ case 0x20000000:
+ case 0x38000000:
+ case 0x30000000:
+ i++;
+
+ default:
+ ;
+ }
+
+ return i;
+
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/pv_normalize.h b/media/libstagefright/codecs/aacdec/pv_normalize.h
new file mode 100644
index 0000000..dce080e
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pv_normalize.h
@@ -0,0 +1,105 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pv_normalize.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PV_NORMALIZE_H
+#define PV_NORMALIZE_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES AND SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+#if defined(_ARM)
+
+__inline Int pv_normalize(Int32 x)
+{
+ Int32 y;
+ __asm
+ {
+ clz y, x;
+ sub y, y, #1
+ }
+ return (y);
+}
+
+
+#elif (defined(PV_ARM_GCC_V5)||defined(PV_ARM_GCC_V4))
+
+__inline Int pv_normalize(Int32 x)
+{
+ register Int32 y;
+ register Int32 ra = x;
+
+
+ asm volatile(
+ "clz %0, %1\n\t"
+ "sub %0, %0, #1"
+ : "=&r*i"(y)
+ : "r"(ra));
+ return (y);
+
+}
+
+#else
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ Int pv_normalize(Int32 x);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+#endif /* PV_NORMALIZE_H */
diff --git a/media/libstagefright/codecs/aacdec/pv_pow2.cpp b/media/libstagefright/codecs/aacdec/pv_pow2.cpp
new file mode 100644
index 0000000..8dfca23
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pv_pow2.cpp
@@ -0,0 +1,170 @@
+/* ------------------------------------------------------------------
+ * 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: pv_pow2.c
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+ Int32 x 32-bit integer input Q27
+
+Output
+ Int32 32-bit integer in Q25
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement the power base 2 for positive numbers lesser than 5.999999
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+#ifdef AAC_PLUS
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_pow2.h"
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#define POW_2_TABLE_LENGTH 6
+#define POW_2_TABLE_LENGTH_m_2 (POW_2_TABLE_LENGTH - 2)
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+#define R_SHIFT 29
+#define Q_fmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+#define Q27fmt(x) (Int32)(x*((Int32)1<<27) + (x>=0?0.5F:-0.5F))
+
+const Int32 pow2_table[6] =
+{
+ Q_fmt(0.00224510927441F), Q_fmt(0.00777943379416F),
+ Q_fmt(0.05737929218747F), Q_fmt(0.23918017179889F),
+ Q_fmt(0.69345251849351F), Q_fmt(0.99996347120248F)
+};
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+/*
+ * z in Q27 format
+ */
+
+Int32 pv_pow2(Int32 z)
+{
+ const Int32 *pt_table = pow2_table;
+ Int32 multiplier = 0;
+ Int32 shift_factor;
+ Int32 i;
+ Int32 v_q;
+ Int32 y;
+
+
+ if (z > Q27fmt(1.0f))
+ {
+ v_q = z - (z & 0xF8000000);
+ shift_factor = z >> 27;
+ }
+ else
+ {
+ v_q = z;
+ shift_factor = 0;
+ }
+
+ if (v_q < Q27fmt(0.5f))
+ {
+ v_q += Q27fmt(0.5f);
+ multiplier = Q_fmt(0.70710678118655F);
+ }
+
+ v_q = v_q << 2;
+
+ y = fxp_mul32_Q29(*(pt_table++), v_q);
+
+ for (i = POW_2_TABLE_LENGTH_m_2; i != 0; i--)
+ {
+ y += *(pt_table++);
+ y = fxp_mul32_Q29(y, v_q);
+ }
+ y += *(pt_table++);
+
+ if (multiplier)
+ {
+ y = fxp_mul32_Q29(y, multiplier);
+ }
+
+ /*
+ * returns number on Q25
+ */
+ return (y >> (4 - shift_factor));
+
+}
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/pv_pow2.h b/media/libstagefright/codecs/aacdec/pv_pow2.h
new file mode 100644
index 0000000..04bfe93
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pv_pow2.h
@@ -0,0 +1,68 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pv_pow2.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PV_POW2_H
+#define PV_POW2_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ Int32 pv_pow2(Int32 z);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PV_POW2_H */
diff --git a/media/libstagefright/codecs/aacdec/pv_sine.cpp b/media/libstagefright/codecs/aacdec/pv_sine.cpp
new file mode 100644
index 0000000..54319b1
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pv_sine.cpp
@@ -0,0 +1,182 @@
+/* ------------------------------------------------------------------
+ * 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: pv_sine.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 x 32-bit integer angle (in Q30) between 0 and pi/2
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Find the sine of a number between 0 and pi/2
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+#ifdef PARAMETRICSTEREO
+
+#include "pv_audio_type_defs.h"
+#include "fxp_mul32.h"
+#include "pv_sine.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+#define R_SHIFT 30
+
+#define Q_fmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+const Int32 sin_table[9] =
+{
+ Q_fmt(0.00001724684028), Q_fmt(-0.00024606242846),
+ Q_fmt(0.00007297328923), Q_fmt(0.00826706596417),
+ Q_fmt(0.00003585160465), Q_fmt(-0.16667772526248),
+ Q_fmt(0.00000174197440), Q_fmt(0.99999989138797),
+ Q_fmt(0.00000000110513)
+};
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+Int32 pv_sine(Int32 z)
+{
+ Int32 sine;
+ Int32 i;
+ const Int32 *pt_table = sin_table;
+ Int32 sign = 0;
+
+ if (z < 0)
+ {
+ z = -z;
+ sign = 1;
+ }
+
+ if (z > Q_fmt(0.0015))
+ {
+ sine = fxp_mul32_Q30(*(pt_table++), z);
+
+ for (i = 7; i != 0; i--)
+ {
+ sine += *(pt_table++);
+ sine = fxp_mul32_Q30(sine, z);
+ }
+
+ }
+ else
+ {
+ sine = z; /* better approximation in this range */
+ }
+
+ if (sign)
+ {
+ sine = -sine;
+ }
+
+ return sine;
+}
+
+
+
+Int32 pv_cosine(Int32 z)
+{
+ Int32 cosine;
+
+ if (z < 0)
+ {
+ z = -z; /* sign does not play a role in cosine */
+ }
+
+ if (z > Q_fmt(0.0015))
+ {
+ z = Q_fmt(1.57079632679490) - z; /* pi/2 - z */
+
+ cosine = pv_sine(z);
+ }
+ else
+ { /* better approximation in this range */
+ cosine = Q_fmt(0.99999999906868) - (fxp_mul32_Q30(z, z) >> 1);
+ }
+
+ return cosine;
+}
+
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/pv_sine.h b/media/libstagefright/codecs/aacdec/pv_sine.h
new file mode 100644
index 0000000..145013a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pv_sine.h
@@ -0,0 +1,68 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pv_sine.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PV_SINE_H
+#define PV_SINE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ Int32 pv_sine(Int32 x);
+ Int32 pv_cosine(Int32 x);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PV_SINE_H */
diff --git a/media/libstagefright/codecs/aacdec/pv_sqrt.cpp b/media/libstagefright/codecs/aacdec/pv_sqrt.cpp
new file mode 100644
index 0000000..065fa38
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pv_sqrt.cpp
@@ -0,0 +1,218 @@
+/* ------------------------------------------------------------------
+ * 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: pv_sqrt.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 x 32-bit integer
+
+ Int32 y 32-bit integer
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement root squared of a number
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "pv_audio_type_defs.h"
+
+#include "fxp_mul32.h"
+#include "pv_sqrt.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#define R_SHIFT 28
+#define Q_fmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+
+const Int32 sqrt_table[9] =
+{
+ Q_fmt(-0.13829740941110F), Q_fmt(0.95383399963991F),
+ Q_fmt(-2.92784603873353F), Q_fmt(5.27429191920042F),
+ Q_fmt(-6.20272445821478F), Q_fmt(5.04717433019620F),
+ Q_fmt(-3.03362807640415F), Q_fmt(1.86178814410910F),
+ Q_fmt(0.16540758699193F)
+};
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void pv_sqrt(Int32 man, Int32 exp, Root_sq *result, Int32 *sqrt_cache)
+{
+
+ Int32 y;
+ Int32 xx;
+ Int32 nn;
+ Int32 i;
+ const Int32 *pt_table = sqrt_table;
+
+
+ if (sqrt_cache[0] == man && sqrt_cache[1] == exp)
+ {
+ result->root = sqrt_cache[2];
+ result->shift_factor = (Int16)sqrt_cache[3];
+ }
+ else
+ {
+
+ sqrt_cache[0] = man;
+ sqrt_cache[1] = exp;
+
+
+ if (man > 0)
+ {
+ xx = man;
+ if (man >= Q_fmt(1.0f))
+ {
+ nn = exp + 1;
+ while ((xx >>= 1) > Q_fmt(1.0f))
+ {
+ nn++;
+ }
+ }
+ else if (man < Q_fmt(0.5f))
+ {
+ nn = exp - 1;
+ while ((xx <<= 1) < Q_fmt(0.5f))
+ {
+ nn--;
+ }
+ }
+ else
+ {
+ nn = exp;
+ }
+
+
+ y = fxp_mul32_Q28(*(pt_table++), xx);
+
+ for (i = 3; i != 0; i--)
+ {
+ y += *(pt_table++);
+ y = fxp_mul32_Q28(y, xx);
+ y += *(pt_table++);
+ y = fxp_mul32_Q28(y, xx);
+ }
+ y += *(pt_table++);
+ y = fxp_mul32_Q28(y, xx) + *(pt_table++);
+
+ if (nn >= 0)
+ {
+ if (nn&1)
+ {
+ y = fxp_mul32_Q29(y, Q_fmt(1.41421356237310F));
+ result->shift_factor = (nn >> 1) - 28;
+ }
+ else
+ {
+ result->shift_factor = (nn >> 1) - 29;
+ }
+ }
+ else
+ {
+ if (nn&1)
+ {
+ y = fxp_mul32_Q28(y, Q_fmt(0.70710678118655F));
+ }
+
+ result->shift_factor = -((-nn) >> 1) - 29;
+ }
+
+ result->root = y;
+
+ }
+ else
+ {
+ result->root = 0;
+ result->shift_factor = 0;
+ }
+
+ }
+
+ sqrt_cache[2] = result->root;
+ sqrt_cache[3] = result->shift_factor;
+
+}
+
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/pv_sqrt.h b/media/libstagefright/codecs/aacdec/pv_sqrt.h
new file mode 100644
index 0000000..45d6f52
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pv_sqrt.h
@@ -0,0 +1,74 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pv_sqrt.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PV_SQRT_H
+#define PV_SQRT_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ struct intg_sqrt
+ {
+ Int32 root;
+ Int32 shift_factor;
+ };
+ typedef struct intg_sqrt Root_sq;
+
+ void pv_sqrt(Int32 man, Int32 exp, Root_sq *result, Int32 *sqrt_cache);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PV_SQRT_H */
diff --git a/media/libstagefright/codecs/aacdec/pvmp4audiodecoder_api.h b/media/libstagefright/codecs/aacdec/pvmp4audiodecoder_api.h
new file mode 100644
index 0000000..7806f88
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pvmp4audiodecoder_api.h
@@ -0,0 +1,376 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Name: PVMP4AudioDecoder_API.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Change buffer type to UChar
+
+ Description: Update comments
+
+ Description: Updated a comment that MT did not get around to
+ before the end of his contract.
+
+ Description: add a new API to decode audioSpecificConfig separately, the same
+ change has been made on 32-bits version (element \main\2)
+
+ Description: add a new API to reset history buffer, the same change has been
+ made on a 32-bits version(element \nd.e0352.wjin\1)
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Main header file for the Packet Video MP4/AAC audio decoder library. The
+ constants, structures, and functions defined within this file, along with
+ a basic data types header file, is all that is needed to use and communicate
+ with the library. The internal data structures within the library are
+ purposely hidden.
+
+ ---* Need description of the input buffering. *-------
+
+ ---* Need an example of calling the library here *----
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (Normally header files do not have a reference section)
+
+ ISO/EIC 14496-3:(1999) Document titled
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP4AUDIODECODER_API_H
+#define PVMP4AUDIODECODER_API_H
+
+#include "pv_audio_type_defs.h" /* Basic data types used within the lib */
+
+#include "e_tmp4audioobjecttype.h"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*
+ * This constant is the guaranteed-to-work buffer size, specified in bytes,
+ * for the input buffer for 2 audio channels to decode one frame of data,
+ * as specified by the MPEG-2 or MPEG-4 standard.
+ * The standard, and this constant, do not take into account that lower
+ * bitrates will use less data per frame. Note that the number of bits
+ * used per frame is variable, and only that the average value will be the
+ * bit rate specified during encoding. The standard does not specify
+ * over how many frames the average must be maintained.
+ *
+ * The constant value is 6144 * 2 channels / 8 bits per byte
+ */
+
+
+#define PVMP4AUDIODECODER_INBUFSIZE 1536
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ /*
+ * This enumeration is used for the structure element outputFormat. It
+ * specifies how the output data is to be formatted. Presently only 16-bit
+ * PCM data is supported, and this enum informs how the single output
+ * buffer should be for two-channel stereo data.
+ * Grouped format stores all the left channel values, then right:
+ * "LLLL...LLRRRR...RR"
+ * Interleave format store left, then right audio samples:
+ * "LRLRLRLR...."
+ */
+ typedef enum ePVMP4AudioDecoderOutputFormat
+ {
+ OUTPUTFORMAT_16PCM_GROUPED = 0,
+ OUTPUTFORMAT_16PCM_INTERLEAVED = 1
+
+ } tPVMP4AudioDecoderOutputFormat;
+
+ /*
+ * This enumeration holds the possible return values for the main decoder
+ * function, PVMP4AudioDecodeFrame. The plan was to easily distinguish
+ * whether an error was recoverable (streaming mode) or not. Presently no
+ * errors are recoverable, which is a result of not supporting ADTS in
+ * this release.
+ */
+ typedef enum ePVMP4AudioDecoderErrorCode
+ {
+ MP4AUDEC_SUCCESS = 0,
+ MP4AUDEC_INVALID_FRAME = 10,
+ MP4AUDEC_INCOMPLETE_FRAME = 20,
+ MP4AUDEC_LOST_FRAME_SYNC = 30 /* Cannot happen since no ADTS */
+ } tPVMP4AudioDecoderErrorCode;
+
+
+ /*
+ * This enumeration holds the possible return values for stream type
+ * being decoded
+ */
+ typedef enum
+ {
+ AAC = 0,
+ AACPLUS,
+ ENH_AACPLUS
+ } STREAMTYPE;
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ /*
+ * This structure is used to communicate information in to and out of the
+ * AAC decoder.
+ */
+
+ typedef struct
+#ifdef __cplusplus
+ tPVMP4AudioDecoderExternal // To allow forward declaration of this struct in C++
+#endif
+ {
+ /*
+ * INPUT:
+ * Pointer to the input buffer that contains the encoded bistream data.
+ * The data is filled in such that the first bit transmitted is
+ * the most-significant bit (MSB) of the first array element.
+ * The buffer is accessed in a linear fashion for speed, and the number of
+ * bytes consumed varies frame to frame.
+ * The calling environment can change what is pointed to between calls to
+ * the decode function, library, as long as the inputBufferCurrentLength,
+ * and inputBufferUsedLength are updated too. Also, any remaining bits in
+ * the old buffer must be put at the beginning of the new buffer.
+ */
+ UChar *pInputBuffer;
+
+ /*
+ * INPUT:
+ * Number of valid bytes in the input buffer, set by the calling
+ * function. After decoding the bitstream the library checks to
+ * see if it when past this value; it would be to prohibitive to
+ * check after every read operation. This value is not modified by
+ * the AAC library.
+ */
+ Int inputBufferCurrentLength;
+
+ /*
+ * INPUT:
+ * The actual size of the buffer.
+ * This variable is not used by the library, but is used by the
+ * console test application. This parameter could be deleted
+ * if this value was passed into these function. The helper functions are
+ * not part of the library and are not used by the Common Audio Decoder
+ * Interface.
+ */
+ Int inputBufferMaxLength;
+
+ /*
+ * INPUT:
+ * Enumerated value the output is to be interleaved left-right-left-right.
+ * For further information look at the comments for the enumeration.
+ */
+ tPVMP4AudioDecoderOutputFormat outputFormat;
+
+ /*
+ * INPUT: (but what is pointed to is an output)
+ * Pointer to the output buffer to hold the 16-bit PCM audio samples.
+ * If the output is stereo, both left and right channels will be stored
+ * in this one buffer. Presently it must be of length of 2048 points.
+ * The format of the buffer is set by the parameter outputFormat.
+ */
+ Int16 *pOutputBuffer;
+
+ /*
+ * INPUT: (but what is pointed to is an output)
+ * Pointer to the output buffer to hold the 16-bit PCM AAC-plus audio samples.
+ * If the output is stereo, both left and right channels will be stored
+ * in this one buffer. Presently it must be of length of 2048 points.
+ * The format of the buffer is set by the parameter outputFormat.
+ */
+ Int16 *pOutputBuffer_plus; /* Used in AAC+ and enhanced AAC+ */
+
+ /*
+ * INPUT:
+ * AAC Plus Upsampling Factor. Normally set to 2 when Spectrum Band
+ * Replication (SBR) is used
+ */
+ Int32 aacPlusUpsamplingFactor; /* Used in AAC+ and enhanced AAC+ */
+
+ /*
+ * INPUT:
+ * AAC Plus enabler. Deafaults to be ON, unless run time conditions
+ * require the SBR and PS tools disabled
+ */
+ bool aacPlusEnabled;
+ /*
+ * INPUT:
+ * (Currently not being used inside the AAC library.)
+ * This flag is set to TRUE when the playback position has been changed,
+ * for example, rewind or fast forward. This informs the AAC library to
+ * take an appropriate action, which has yet to be determined.
+ */
+ Bool repositionFlag;
+
+ /*
+ * INPUT:
+ * Number of requested output audio channels. This relieves the calling
+ * environment from having to perform stereo-to-mono or mono-to-stereo
+ * conversions.
+ */
+ Int desiredChannels;
+
+ /*
+ * INPUT/OUTPUT:
+ * Number of elements used by the library, initially set to zero by
+ * the function PVMP4AudioDecoderInitLibrary, and modified by each
+ * call to PVMP4AudioDecodeFrame.
+ */
+ Int inputBufferUsedLength;
+
+ /*
+ * INPUT/OUTPUT:
+ * Number of bits left over in the next buffer element,
+ * This value will always be zero, unless support for ADTS is added.
+ */
+ Int32 remainderBits;
+
+ /*
+ * OUTPUT:
+ * The sampling rate decoded from the bitstream, in units of
+ * samples/second. For this release of the library this value does
+ * not change from frame to frame, but future versions will.
+ */
+ Int32 samplingRate;
+
+ /*
+ * OUTPUT:
+ * This value is the bitrate in units of bits/second. IT
+ * is calculated using the number of bits consumed for the current frame,
+ * and then multiplying by the sampling_rate, divided by points in a frame.
+ * This value can changes frame to frame.
+ */
+ Int32 bitRate;
+
+ /*
+ * OUTPUT:
+ * The number of channels decoded from the bitstream. The output data
+ * will have be the amount specified in the variable desiredChannels,
+ * this output is informative only, and can be ignored.
+ */
+ Int encodedChannels;
+
+ /*
+ * OUTPUT:
+ * This value is the number of output PCM samples per channel.
+ * It is presently hard-coded to 1024, but may change in the future.
+ * It will not change frame to frame, and would take on
+ * one of these four values: 1024, 960, 512, or 480. If an error occurs
+ * do not rely on this value.
+ */
+ Int frameLength;
+
+ /*
+ * This value is audio object type as defined in struct tMP4AudioObjectType
+ * in file e_tMP4AudioObjectType.h
+ */
+ Int audioObjectType;
+
+ /*
+ * This value is extended audio object type as defined in struct tMP4AudioObjectType
+ * in file e_tMP4AudioObjectType.h. It carries the output Audio Object Type
+ */
+ Int extendedAudioObjectType;
+
+
+ } tPVMP4AudioDecoderExternal;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ OSCL_IMPORT_REF UInt32 PVMP4AudioDecoderGetMemRequirements(void);
+
+ OSCL_IMPORT_REF Int PVMP4AudioDecoderInitLibrary(
+ tPVMP4AudioDecoderExternal *pExt,
+ void *pMem);
+
+ OSCL_IMPORT_REF Int PVMP4AudioDecodeFrame(
+ tPVMP4AudioDecoderExternal *pExt,
+ void *pMem);
+
+ OSCL_IMPORT_REF Int PVMP4AudioDecoderConfig(
+ tPVMP4AudioDecoderExternal *pExt,
+ void *pMem);
+
+ OSCL_IMPORT_REF void PVMP4AudioDecoderResetBuffer(
+ void *pMem);
+
+ OSCL_IMPORT_REF void PVMP4AudioDecoderDisableAacPlus(
+ tPVMP4AudioDecoderExternal *pExt,
+ void *pMem);
+
+ Int PVMP4SetAudioConfig(
+ tPVMP4AudioDecoderExternal *pExt,
+ void *pMem,
+ Int upsamplingFactor,
+ Int samp_rate,
+ int num_ch,
+ tMP4AudioObjectType audioObjectType);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* PVMP4AUDIODECODER_API_H */
+
+
diff --git a/media/libstagefright/codecs/aacdec/pvmp4audiodecoderconfig.cpp b/media/libstagefright/codecs/aacdec/pvmp4audiodecoderconfig.cpp
new file mode 100644
index 0000000..9208fa8
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pvmp4audiodecoderconfig.cpp
@@ -0,0 +1,285 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: PVMP4AudioDecoderConfig
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: (1) Modified to decode AudioSpecificConfig for any frame number
+ pVars->bno
+ (2) Update the input and output descriptions
+
+ Description: Eliminated search for ADIF header
+
+ Description: Added support for AAC+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pExt = pointer to the external interface structure. See the file
+ PVMP4AudioDecoder_API.h for a description of each field.
+ Data type of pointer to a tPVMP4AudioDecoderExternal
+ structure.
+
+ pExt->pInputBuffer: pointer to input buffer containing input
+ bitstream
+
+ pExt->inputBufferCurrentLength: number of bytes in the input buffer
+
+ pExt->inputBufferUsedLength: number of bytes already consumed in
+ input buffer
+
+ pExt->remainderBits: number of bits consumed in addition to
+ pExt->inputBufferUsedLength
+
+ pMem = void pointer to hide the internal implementation of the library
+ It is cast back to a tDec_Int_File structure. This structure
+ contains information that needs to persist between calls to
+ this function, or is too big to be placed on the stack, even
+ though the data is only needed during execution of this function
+ Data type void pointer, internally pointer to a tDec_Int_File
+ structure.
+
+ Local Stores/Buffers/Pointers Needed: None
+ (The memory set aside in pMem performs this task)
+
+ Global Stores/Buffers/Pointers Needed: None
+
+ Outputs:
+ status = 0 if no error occurred
+ MP4AUDEC_NONRECOVERABLE if a non-recoverable error occurred
+ MP4AUDEC_RECOVERABLE if a recoverable error occurred.
+ Presently a recoverable error does not exist, but this
+ was a requirement.
+
+
+ Pointers and Buffers Modified:
+ pMem contents are modified.
+ pExt: (more detail in the file PVMP4AudioDecoder_API.h)
+ inputBufferUsedLength - number of array elements used up by the stream.
+ remainderBits - remaining bits in the next UInt32 buffer
+ samplingRate - sampling rate in samples per sec
+ encodedChannels - channels found on the file (informative)
+ frameLength - length of the frame
+
+ Local Stores Modified: None.
+
+ Global Stores Modified: None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ PacketVideo Document # CCC-AUD-AAC-ERS-0003
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3: 1999(E)
+ subclause 1.6
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_tdec_int_file.h"
+#include "ibstream.h" /* where #define INBUF_ARRAY_INDEX_SHIFT */
+#include "sfb.h" /* Where samp_rate_info[] is declared */
+
+#include "get_audio_specific_config.h"
+#include "pvmp4audiodecoder_api.h" /* Where this function is declared */
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+OSCL_EXPORT_REF Int PVMP4AudioDecoderConfig(
+ tPVMP4AudioDecoderExternal *pExt,
+ void *pMem)
+{
+
+ UInt initialUsedBits; /* Unsigned for C55x */
+ tDec_Int_File *pVars; /* Helper pointer */
+
+ Int status = MP4AUDEC_INCOMPLETE_FRAME;
+
+ /*
+ * Initialize "helper" pointers to existing memory.
+ */
+ pVars = (tDec_Int_File *)pMem;
+ /*
+ * Translate input buffer variables.
+ */
+ pVars->inputStream.pBuffer = pExt->pInputBuffer;
+
+ pVars->inputStream.inputBufferCurrentLength =
+ (UInt)pExt->inputBufferCurrentLength;
+
+ pVars->inputStream.availableBits =
+ (UInt)(pExt->inputBufferCurrentLength << INBUF_ARRAY_INDEX_SHIFT);
+
+ initialUsedBits =
+ (UInt)((pExt->inputBufferUsedLength << INBUF_ARRAY_INDEX_SHIFT) +
+ pExt->remainderBits);
+
+ pVars->inputStream.usedBits = initialUsedBits;
+
+ if (initialUsedBits <= pVars->inputStream.availableBits)
+ {
+
+ /*
+ * Buffer is not overrun, then
+ * decode the AudioSpecificConfig() structure
+ */
+
+ pVars->aacConfigUtilityEnabled = false; /* set aac dec mode */
+
+ status = get_audio_specific_config(pVars);
+
+ }
+
+ byte_align(&pVars->inputStream);
+
+
+ if (status == SUCCESS)
+ {
+
+ pVars->bno++;
+
+ /*
+ * A possible improvement would be to set these values only
+ * when they change.
+ */
+ pExt->samplingRate =
+ samp_rate_info[pVars->prog_config.sampling_rate_idx].samp_rate;
+
+ /*
+ * we default to 2 channel, even for mono files, (where channels have same content)
+ * this is done to ensure support for enhanced aac+ with implicit signalling
+ */
+ pExt->aacPlusEnabled = pVars->aacPlusEnabled;
+
+// pExt->encodedChannels = pVars->mc_info.nch;
+
+ pExt->encodedChannels = 2;
+
+ pExt->frameLength = pVars->frameLength;
+#ifdef AAC_PLUS
+ pExt->aacPlusUpsamplingFactor = pVars->mc_info.upsamplingFactor;
+#endif
+
+ }
+ else
+ {
+ /*
+ * Default to nonrecoverable error status unless there is a Buffer overrun
+ */
+ status = MP4AUDEC_INVALID_FRAME;
+
+ if (pVars->inputStream.usedBits > pVars->inputStream.availableBits)
+ {
+ /* all bits were used but were not enough to complete parsing */
+ pVars->inputStream.usedBits = pVars->inputStream.availableBits;
+
+ status = MP4AUDEC_INCOMPLETE_FRAME; /* audio config too small */
+ }
+
+ }
+
+ /*
+ * Translate from units of bits back into units of words.
+ */
+
+ pExt->inputBufferUsedLength =
+ pVars->inputStream.usedBits >> INBUF_ARRAY_INDEX_SHIFT;
+
+ pExt->remainderBits = pVars->inputStream.usedBits & INBUF_BIT_MODULO_MASK;
+
+ pVars->status = status;
+
+ return (status);
+
+} /* PVMP4AudioDecoderDecodeFrame */
+
diff --git a/media/libstagefright/codecs/aacdec/pvmp4audiodecoderframe.cpp b/media/libstagefright/codecs/aacdec/pvmp4audiodecoderframe.cpp
new file mode 100644
index 0000000..7a279dc
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pvmp4audiodecoderframe.cpp
@@ -0,0 +1,1458 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pvmp4audiodecodeframe
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Pulled in loop structure from console.c, so that this function
+ now decodes all frames in the file.
+
+ Original program used several global variables. These have been
+ eliminated, except for situations in which the global variables
+ could be converted into const types. Otherwise, they are passed
+ by reference through the functions.
+
+ Description: Begin mods for file I/O removal
+
+ Description: Merged trans4m_freq_2_time, trans4m_time_2_freq, etc.
+
+ Description: Removing commented out sections of code. This includes the
+ removal of unneeded functions init_lt_pred, reset_mc_info,
+
+ Description: Copied from aac_decode_frame.c and renamed file,
+ Made many changes.
+
+ Description: Prepare for code review
+
+ Description: Update per review comments:
+ 1) Add comment about leaveGetLoop
+ 2) Remove inverseTNSCoef array
+ 3) fix wnd_shape_this_bk to wnd_shape_prev_bk in F to T
+ 4) Clean up comments
+ 5) Change call to long_term_synthesis
+
+ Description: Remove division for calculation of bitrate.
+
+ Description: Remove update of LTP buffers if not LTP audio object type.
+
+ Description: Add hasmask to call to right_ch_sfb_tools_ms
+
+ Description:
+ Modified to call ltp related routines on the left channel
+ before intensity is called on the right channel. The previous version
+ was causing a problem when IS was used on the right channel and LTP
+ on the left channel for the same scalefactor band.
+
+ This fix required creating a new function, apply_ms_synt, deleting another
+ function (right_ch_sfb_tools_noms.c), and modifying the calling order of
+ the other functions.
+
+ Description: Made changes per review comments.
+
+ Description: Changed name of right_ch_sfb_tools_ms to pns_intensity_right
+
+ Description: Added cast, since pVars->inputStream.usedBits is UInt, and
+ pExt->remainderBits is Int.
+
+ pExt->remainderBits =
+ (Int)(pVars->inputStream.usedBits & INBUF_BIT_MODULO_MASK);
+
+ Description: Modified to pass a pointer to scratch memory into
+ tns_setup_filter.c
+
+ Description: Removed include of "s_TNSInfo.h"
+
+ Description: Removed call to "tns_setup_filter" which has been eliminated
+ by merging its functionality into "get_tns"
+
+ Description: Passing in a pointer to a q-format array, rather than
+ the address of a single q-format, for the inverse filter case for
+ apply_tns.
+
+ Description:
+ (1) Added #include of "e_ElementId.h"
+ Previously, this function was relying on another include file
+ to include "e_ElementId.h"
+
+ (2) Updated the copyright header.
+
+ Description:
+ Per review comments, declared two temporary variables
+
+ pChLeftShare = pChVars[LEFT]->pShareWfxpCoef;
+ pChRightShare = pChVars[RIGHT]->pShareWfxpCoef;
+
+ Description:
+ long_term_synthesis should have been invoked with max_sfb
+ as the 2nd parameter, rather than pFrameInfo->sfb_per_win[0].
+
+ Old
+ long_term_synthesis(
+ pChVars[ch]->wnd,
+ pFrameInfo->sfb_per_win[0] ...
+
+ Correction
+ long_term_synthesis(
+ pChVars[ch]->wnd,
+ pChVars[ch]->pShareWfxpCoef->max_sfb ...
+
+ This problem caused long_term_synthesis to read memory which
+ was not initialized in get_ics_info.c
+
+ Description:
+ (1) Utilize scratch memory for the scratch Prog_Config.
+
+ Description: (1) Modified to decode ID_END syntactic element after header
+
+ Description:
+ (1) Reconfigured LTP buffer as a circular buffer. This saves
+ 2048 Int16->Int16 copies per frame.
+
+ Description: Updated so ltp buffers are not used as a wasteful
+ intermediate buffer for LC streams. Data is transferred directly
+ from the filterbank to the output stream.
+
+ Description: Decode ADIF header if frame count is zero.
+ The AudioSpecificConfig is decoded by a separate API.
+
+ Description: Added comments explaining how the ltp_buffer_state
+ variable is updated.
+
+
+ Description: Modified code to take advantage of new trans4m_freq_2_time_fxp,
+ which writes the output directly into a 16-bit output buffer. This
+ improvement allows faster operation by reducing the amount of memory
+ transfers. Speed can be further improved on most platforms via use of a
+ DMA transfer in the function write_output.c
+
+ Description: perChan[] is an array of structures in tDec_Int_File. Made
+ corresponding changes.
+
+ Description: Included changes in interface for q_normalize() and
+ trans4m_freq_2_time_fxp.
+
+ Description: Included changes in interface for long_term_prediction.
+
+ Description: Added support for DSE (Data Streaming Channel). Added
+ function get_dse() and included file get_dse.h
+
+ Description: Added support for the ill-case when a raw data block contains
+ only a terminator <ID_END>. This is illegal but is added
+ for convinience
+
+ Description: Added support for empty audio frames, such the one containing
+ only DSE or FILL elements. A trap was added to stop processing
+ when no audio information was sent.
+
+ Description: Added support for adts format files. Added saturation to
+ floating point version of aac+ decoding
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pExt = pointer to the external interface structure. See the file
+ PVMP4AudioDecoder_API.h for a description of each field.
+ Data type of pointer to a tPVMP4AudioDecoderExternal
+ structure.
+
+ pMem = void pointer to hide the internal implementation of the library
+ It is cast back to a tDec_Int_File structure. This structure
+ contains information that needs to persist between calls to
+ this function, or is too big to be placed on the stack, even
+ though the data is only needed during execution of this function
+ Data type void pointer, internally pointer to a tDec_Int_File
+ structure.
+
+ Local Stores/Buffers/Pointers Needed: None
+ (The memory set aside in pMem performs this task)
+
+ Global Stores/Buffers/Pointers Needed: None
+
+ Outputs:
+ status = 0 if no error occurred
+ MP4AUDEC_NONRECOVERABLE if a non-recoverable error occurred
+ MP4AUDEC_RECOVERABLE if a recoverable error occurred.
+ Presently a recoverable error does not exist, but this
+ was a requirement.
+
+
+ Pointers and Buffers Modified:
+ pMem contents are modified.
+ pExt: (more detail in the file PVMP4AudioDecoder_API.h)
+ inputBufferUsedLength - number of array elements used up by the stream.
+ remainderBits - remaining bits in the next UInt32 buffer
+ samplingRate - sampling rate in samples per sec
+ bitRate - bit rate in bits per second, varies frame to frame.
+ encodedChannels - channels found on the file (informative)
+ frameLength - length of the frame
+
+ Local Stores Modified: None.
+
+ Global Stores Modified: None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Decodes one frame of an MPEG-2/MPEG-4 encoded audio bitstream.
+
+ This function calls the various components of the decoder in the proper order.
+
+
+ Left Channel Right Channel
+ | |
+ | |
+ | |
+ \|/ \|/
+ #1 ____________________ #2 ____________________
+ | | | |
+ | Huffman Decoding | | Huffman Decoding |
+ |__________________| |__________________|
+ | |
+ | |
+ | |
+ \|/ |
+ #3 ____________________ |
+ | | |
+ | PNS LEFT | |
+ |__________________| |
+ | |
+ | |
+ | |
+ \|/ \|/
+ #4 ______________________________________________________________________
+ | |
+ | Apply MS_Synt |
+ |____________________________________________________________________|
+ | |
+ | |
+ \|/ |
+ #5 ____________________ |
+ | | W
+ | LTP | A
+ |__________________| I
+ | T
+ | |
+ | F
+ \|/ O
+ #6 ____________________ R
+ | | |
+ | Time -> Freq | L
+ |__________________| E
+ | F
+ | T
+ | |
+ \|/ C
+ #7 ____________________ H
+ | | A
+ | TNS Inverse | N
+ |__________________| N
+ | E
+ | L
+ | |
+ \|/ |
+ #8 ____________________ |
+ | | |
+ | Long Term Synth | |
+ |__________________| |
+ | |
+ | \|/
+ | #9 ____________________
+ | | |
+ |--DATA ON LEFT CHANNEL MAY BE USED----->| PNS/Intensity Rt |
+ | |__________________|
+ | |
+ | |
+ | \|/
+ | #10 ____________________
+ W | |
+ A | LTP |
+ I |__________________|
+ T |
+ | |
+ F |
+ O \|/
+ R #11 ____________________
+ | | |
+ R | Time -> Freq |
+ I |__________________|
+ G |
+ H |
+ T |
+ | \|/
+ C #12 ____________________
+ H | |
+ A | TNS Inverse |
+ N |__________________|
+ N |
+ E |
+ L |
+ | \|/
+ | #13 ____________________
+ | | |
+ | | Long Term Synth |
+ | |__________________|
+ | |
+ | |
+ | |
+ \|/ \|/
+#14 ____________________ #18 ____________________
+ | | | |
+ | TNS | | TNS |
+ |__________________| |__________________|
+ | |
+ | |
+ | |
+ \|/ \|/
+#15 ____________________ #19 ____________________
+ | | | |
+ | qFormatNorm | | qFormatNorm |
+ |__________________| |__________________|
+ | |
+ | |
+ | |
+ \|/ \|/
+#16 ____________________ #20 ____________________
+ | | | |
+ | Freq / Time | | Freq / Time |
+ |__________________| |__________________|
+ | |
+ | |
+ | |
+ \|/ \|/
+#17 ____________________ #21 ____________________
+ | | | |
+ | Limit Buffer | | Limit Buffer |
+ |__________________| |__________________|
+ | |
+ | |
+ | |
+ \|/ \|/
+#22 ______________________________________________________________________
+ | |
+ | Write Output |
+ |____________________________________________________________________|
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ PacketVideo Document # CCC-AUD-AAC-ERS-0003
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+#include "s_tdec_int_chan.h"
+#include "s_tdec_int_file.h"
+#include "aac_mem_funcs.h"
+#include "sfb.h" /* Where samp_rate_info[] is declared */
+#include "e_tmp4audioobjecttype.h"
+#include "e_elementid.h"
+
+
+#include "get_adif_header.h"
+#include "get_adts_header.h"
+#include "get_audio_specific_config.h"
+#include "ibstream.h" /* where getbits is declared */
+
+#include "huffman.h" /* where huffdecode is declared */
+#include "get_prog_config.h"
+#include "getfill.h"
+#include "pns_left.h"
+
+#include "apply_ms_synt.h"
+#include "pns_intensity_right.h"
+#include "q_normalize.h"
+#include "long_term_prediction.h"
+#include "long_term_synthesis.h"
+#include "ltp_common_internal.h"
+#include "apply_tns.h"
+
+#include "window_block_fxp.h"
+
+#include "write_output.h"
+
+#include "pvmp4audiodecoder_api.h" /* Where this function is declared */
+#include "get_dse.h"
+
+#include "sbr_applied.h"
+#include "sbr_open.h"
+#include "get_sbr_bitstream.h"
+#include "e_sbr_element_id.h"
+
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define LEFT (0)
+#define RIGHT (1)
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+void InitSbrSynFilterbank(bool bDownSampleSBR);
+
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+OSCL_EXPORT_REF Int PVMP4AudioDecodeFrame(
+ tPVMP4AudioDecoderExternal *pExt,
+ void *pMem)
+{
+ Int frameLength; /* Helper variable */
+ Int ch;
+ Int id_syn_ele;
+ UInt initialUsedBits; /* Unsigned for C55x */
+ Int qFormatNorm;
+ Int qPredictedSamples;
+ Bool leaveGetLoop;
+ MC_Info *pMC_Info; /* Helper pointer */
+ FrameInfo *pFrameInfo; /* Helper pointer */
+ tDec_Int_File *pVars; /* Helper pointer */
+ tDec_Int_Chan *pChVars[Chans]; /* Helper pointer */
+
+ per_chan_share_w_fxpCoef *pChLeftShare; /* Helper pointer */
+ per_chan_share_w_fxpCoef *pChRightShare; /* Helper pointer */
+
+ Int status = MP4AUDEC_SUCCESS;
+
+
+ Bool empty_frame;
+
+#ifdef AAC_PLUS
+
+ SBRDECODER_DATA *sbrDecoderData;
+ SBR_DEC *sbrDec;
+ SBRBITSTREAM *sbrBitStream;
+
+#endif
+ /*
+ * Initialize "helper" pointers to existing memory.
+ */
+ pVars = (tDec_Int_File *)pMem;
+
+ pMC_Info = &pVars->mc_info;
+
+ pChVars[LEFT] = &pVars->perChan[LEFT];
+ pChVars[RIGHT] = &pVars->perChan[RIGHT];
+
+ pChLeftShare = pChVars[LEFT]->pShareWfxpCoef;
+ pChRightShare = pChVars[RIGHT]->pShareWfxpCoef;
+
+
+#ifdef AAC_PLUS
+
+ sbrDecoderData = (SBRDECODER_DATA *) & pVars->sbrDecoderData;
+ sbrDec = (SBR_DEC *) & pVars->sbrDec;
+ sbrBitStream = (SBRBITSTREAM *) & pVars->sbrBitStr;
+
+#ifdef PARAMETRICSTEREO
+ sbrDecoderData->hParametricStereoDec = (HANDLE_PS_DEC) & pVars->sbrDecoderData.ParametricStereoDec;
+#endif
+
+#endif
+ /*
+ * Translate input buffer variables.
+ */
+ pVars->inputStream.pBuffer = pExt->pInputBuffer;
+
+ pVars->inputStream.inputBufferCurrentLength = (UInt)pExt->inputBufferCurrentLength;
+
+ pVars->inputStream.availableBits =
+ (UInt)(pExt->inputBufferCurrentLength << INBUF_ARRAY_INDEX_SHIFT);
+
+ initialUsedBits =
+ (UInt)((pExt->inputBufferUsedLength << INBUF_ARRAY_INDEX_SHIFT) +
+ pExt->remainderBits);
+
+ pVars->inputStream.usedBits = initialUsedBits;
+
+ if (initialUsedBits > pVars->inputStream.availableBits)
+ {
+ status = MP4AUDEC_INVALID_FRAME;
+ }
+ else if (pVars->bno == 0)
+ {
+ /*
+ * Attempt to read in ADIF format first because it is easily identified.
+ * If its not an ADIF bitstream, get_adif_header rewinds the "pointer"
+ * (actually usedBits).
+ */
+ status =
+ get_adif_header(
+ pVars,
+ &(pVars->scratch.scratch_prog_config));
+
+ byte_align(&pVars->inputStream);
+
+ if (status == SUCCESS)
+ {
+ pVars->prog_config.file_is_adts = FALSE;
+ }
+ else /* we've tried simple audio config, adif, then it should be adts */
+ {
+ pVars->prog_config.file_is_adts = TRUE;
+ }
+ }
+ else if ((pVars->bno == 1) && (pVars->prog_config.file_is_adts == FALSE))
+ {
+
+ /*
+ * There might be an ID_END element following immediately after the
+ * AudioSpecificConfig header. This syntactic element should be read
+ * and byte_aligned before proceeds to decode "real" AAC raw data.
+ */
+ id_syn_ele = (Int)getbits(LEN_SE_ID, &pVars->inputStream) ;
+
+ if (id_syn_ele == ID_END)
+ {
+
+ byte_align(&pVars->inputStream);
+
+ pExt->inputBufferUsedLength =
+ pVars->inputStream.usedBits >> INBUF_ARRAY_INDEX_SHIFT;
+
+ pExt->remainderBits = pVars->inputStream.usedBits & INBUF_BIT_MODULO_MASK;
+
+ pVars->bno++;
+
+ return(status);
+ }
+ else
+ {
+ /*
+ * Rewind bitstream pointer so that the syntactic element can be
+ * read when decoding raw bitstream
+ */
+ pVars->inputStream.usedBits -= LEN_SE_ID;
+ }
+
+ }
+
+ if (pVars->prog_config.file_is_adts == TRUE)
+ {
+ /*
+ * If file is adts format, let the decoder handle only on data raw
+ * block at the time, once the last (or only) data block has been
+ * processed, then synch on the next header
+ */
+ if (pVars->prog_config.headerless_frames)
+ {
+ pVars->prog_config.headerless_frames--; /* raw data block counter */
+ }
+ else
+ {
+ status = get_adts_header(pVars,
+ &(pVars->syncword),
+ &(pVars->invoke),
+ 3); /* CorrectlyReadFramesCount */
+
+ if (status != SUCCESS)
+ {
+ status = MP4AUDEC_LOST_FRAME_SYNC; /* we lost track of header */
+ }
+ }
+ }
+ else
+ {
+ byte_align(&pVars->inputStream);
+ }
+
+#ifdef AAC_PLUS
+ sbrBitStream->NrElements = 0;
+ sbrBitStream->NrElementsCore = 0;
+
+#endif
+
+ /*
+ * The variable leaveGetLoop is used to signal that the following
+ * loop can be left, which retrieves audio syntatic elements until
+ * an ID_END is found, or an error occurs.
+ */
+ leaveGetLoop = FALSE;
+ empty_frame = TRUE;
+
+ while ((leaveGetLoop == FALSE) && (status == SUCCESS))
+ {
+ /* get audio syntactic element */
+ id_syn_ele = (Int)get9_n_lessbits(LEN_SE_ID, &pVars->inputStream);
+
+ /*
+ * As fractional frames are a possible input, check that parsing does not
+ * go beyond the available bits before parsing the syntax.
+ */
+ if (pVars->inputStream.usedBits > pVars->inputStream.availableBits)
+ {
+ status = MP4AUDEC_INCOMPLETE_FRAME; /* possible EOF or fractional frame */
+ id_syn_ele = ID_END; /* quit while-loop */
+ }
+
+ switch (id_syn_ele)
+ {
+ case ID_END: /* terminator field */
+ leaveGetLoop = TRUE;
+ break;
+
+ case ID_SCE: /* single channel */
+ case ID_CPE: /* channel pair */
+ empty_frame = FALSE;
+ status =
+ huffdecode(
+ id_syn_ele,
+ &(pVars->inputStream),
+ pVars,
+ pChVars);
+
+#ifdef AAC_PLUS
+ if (id_syn_ele == ID_SCE)
+ {
+ sbrBitStream->sbrElement[sbrBitStream->NrElements].ElementID = SBR_ID_SCE;
+ }
+ else if (id_syn_ele == ID_CPE)
+ {
+ sbrBitStream->sbrElement[sbrBitStream->NrElements].ElementID = SBR_ID_CPE;
+ }
+ sbrBitStream->NrElementsCore++;
+
+
+#endif
+
+ break;
+
+ case ID_PCE: /* program config element */
+ /*
+ * PCE are not accepted in the middle of a
+ * raw_data_block. If found, a possible error may happen
+ * If a PCE is encountered during the first 2 frames,
+ * it will be read and accepted
+ * if its tag matches the first, with no error checking
+ * (inside of get_prog_config)
+ */
+
+ if (pVars->bno <= 1)
+ {
+ status = get_prog_config(pVars,
+ &(pVars->scratch.scratch_prog_config));
+ }
+ else
+ {
+ status = MP4AUDEC_INVALID_FRAME;
+ }
+ break;
+
+ case ID_FIL: /* fill element */
+#ifdef AAC_PLUS
+ get_sbr_bitstream(sbrBitStream, &pVars->inputStream);
+
+#else
+ getfill(&pVars->inputStream);
+#endif
+
+ break;
+
+ case ID_DSE: /* Data Streaming element */
+ get_dse(pVars->share.data_stream_bytes,
+ &pVars->inputStream);
+ break;
+
+ default: /* Unsupported element, including ID_LFE */
+ status = -1; /* ERROR CODE needs to be updated */
+ break;
+
+ } /* end switch() */
+
+ } /* end while() */
+
+ byte_align(&pVars->inputStream);
+
+ /*
+ * After parsing the first frame ( bno=0 (adif), bno=1 (raw))
+ * verify if implicit signalling is forcing to upsample AAC with
+ * no AAC+/eAAC+ content. If so, disable upsampling
+ */
+
+#ifdef AAC_PLUS
+ if (pVars->bno <= 1)
+ {
+ if ((pVars->mc_info.ExtendedAudioObjectType == MP4AUDIO_AAC_LC) &&
+ (!sbrBitStream->NrElements))
+ {
+ PVMP4AudioDecoderDisableAacPlus(pExt, pMem);
+ }
+ }
+#endif
+
+ /*
+ * There might be an empty raw data block with only a
+ * ID_END element or non audio ID_DSE, ID_FIL
+ * This is an "illegal" condition but this trap
+ * avoids any further processing
+ */
+
+ if (empty_frame == TRUE)
+ {
+ pExt->inputBufferUsedLength =
+ pVars->inputStream.usedBits >> INBUF_ARRAY_INDEX_SHIFT;
+
+ pExt->remainderBits = pVars->inputStream.usedBits & INBUF_BIT_MODULO_MASK;
+
+ pVars->bno++;
+
+ return(status);
+
+ }
+
+#ifdef AAC_PLUS
+
+ if (sbrBitStream->NrElements)
+ {
+ /* for every core SCE or CPE there must be an SBR element, otherwise sths. wrong */
+ if (sbrBitStream->NrElements != sbrBitStream->NrElementsCore)
+ {
+ status = MP4AUDEC_INVALID_FRAME;
+ }
+
+ if (pExt->aacPlusEnabled == false)
+ {
+ sbrBitStream->NrElements = 0; /* disable aac processing */
+ }
+ }
+ else
+ {
+ /*
+ * This is AAC, but if aac+/eaac+ was declared in the stream, and there is not sbr content
+ * something is wrong
+ */
+ if (pMC_Info->sbrPresentFlag || pMC_Info->psPresentFlag)
+ {
+ status = MP4AUDEC_INVALID_FRAME;
+ }
+ }
+#endif
+
+
+
+
+ /*
+ * Signal processing section.
+ */
+ frameLength = pVars->frameLength;
+
+ if (status == SUCCESS)
+ {
+ /*
+ * PNS and INTENSITY STEREO and MS
+ */
+
+ pFrameInfo = pVars->winmap[pChVars[LEFT]->wnd];
+
+ pns_left(
+ pFrameInfo,
+ pChLeftShare->group,
+ pChLeftShare->cb_map,
+ pChLeftShare->factors,
+ pChLeftShare->lt_status.sfb_prediction_used,
+ pChLeftShare->lt_status.ltp_data_present,
+ pChVars[LEFT]->fxpCoef,
+ pChLeftShare->qFormat,
+ &(pVars->pns_cur_noise_state));
+
+ /*
+ * apply_ms_synt can only be ran for common windows.
+ * (where both the left and right channel share the
+ * same grouping, window length, etc.
+ *
+ * pVars->hasmask will be > 0 only if
+ * common windows are enabled for this frame.
+ */
+
+ if (pVars->hasmask > 0)
+ {
+ apply_ms_synt(
+ pFrameInfo,
+ pChLeftShare->group,
+ pVars->mask,
+ pChLeftShare->cb_map,
+ pChVars[LEFT]->fxpCoef,
+ pChVars[RIGHT]->fxpCoef,
+ pChLeftShare->qFormat,
+ pChRightShare->qFormat);
+ }
+
+ for (ch = 0; (ch < pMC_Info->nch); ch++)
+ {
+ pFrameInfo = pVars->winmap[pChVars[ch]->wnd];
+
+ /*
+ * Note: This MP4 library assumes that if there are two channels,
+ * then the second channel is right AND it was a coupled channel,
+ * therefore there is no need to check the "is_cpe" flag.
+ */
+
+ if (ch > 0)
+ {
+ pns_intensity_right(
+ pVars->hasmask,
+ pFrameInfo,
+ pChRightShare->group,
+ pVars->mask,
+ pChRightShare->cb_map,
+ pChLeftShare->factors,
+ pChRightShare->factors,
+ pChRightShare->lt_status.sfb_prediction_used,
+ pChRightShare->lt_status.ltp_data_present,
+ pChVars[LEFT]->fxpCoef,
+ pChVars[RIGHT]->fxpCoef,
+ pChLeftShare->qFormat,
+ pChRightShare->qFormat,
+ &(pVars->pns_cur_noise_state));
+ }
+
+ if (pChVars[ch]->pShareWfxpCoef->lt_status.ltp_data_present != FALSE)
+ {
+ /*
+ * LTP - Long Term Prediction
+ */
+
+ qPredictedSamples = long_term_prediction(
+ pChVars[ch]->wnd,
+ pChVars[ch]->pShareWfxpCoef->lt_status.
+ weight_index,
+ pChVars[ch]->pShareWfxpCoef->lt_status.
+ delay,
+ pChVars[ch]->ltp_buffer,
+ pVars->ltp_buffer_state,
+ pChVars[ch]->time_quant,
+ pVars->share.predictedSamples, /* Scratch */
+ frameLength);
+
+ trans4m_time_2_freq_fxp(
+ pVars->share.predictedSamples,
+ pChVars[ch]->wnd,
+ pChVars[ch]->wnd_shape_prev_bk,
+ pChVars[ch]->wnd_shape_this_bk,
+ &qPredictedSamples,
+ pVars->scratch.fft); /* scratch memory for FFT */
+
+
+ /*
+ * To solve a potential problem where a pointer tied to
+ * the qFormat was being incremented, a pointer to
+ * pChVars[ch]->qFormat is passed in here rather than
+ * the address of qPredictedSamples.
+ *
+ * Neither values are actually needed in the case of
+ * inverse filtering, but the pointer was being
+ * passed (and incremented) regardless.
+ *
+ * So, the solution is to pass a space of memory
+ * that a pointer can happily point to.
+ */
+
+ /* This is the inverse filter */
+ apply_tns(
+ pVars->share.predictedSamples, /* scratch re-used for each ch */
+ pChVars[ch]->pShareWfxpCoef->qFormat, /* Not used by the inv_filter */
+ pFrameInfo,
+ &(pChVars[ch]->pShareWfxpCoef->tns),
+ TRUE, /* TRUE is FIR */
+ pVars->scratch.tns_inv_filter);
+
+ /*
+ * For the next function long_term_synthesis,
+ * the third param win_sfb_top[], and
+ * the tenth param coef_per_win,
+ * are used differently that in the rest of the project. This
+ * is because originally the ISO code was going to have
+ * these parameters change as the "short window" changed.
+ * These are all now the same value for each of the eight
+ * windows. This is why there is a [0] at the
+ * end of each of theses parameters.
+ * Note in particular that win_sfb_top was originally an
+ * array of pointers to arrays, but inside long_term_synthesis
+ * it is now a simple array.
+ * When the rest of the project functions are changed, the
+ * structure FrameInfo changes, and the [0]'s are removed,
+ * this comment could go away.
+ */
+ long_term_synthesis(
+ pChVars[ch]->wnd,
+ pChVars[ch]->pShareWfxpCoef->max_sfb,
+ pFrameInfo->win_sfb_top[0], /* Look above */
+ pChVars[ch]->pShareWfxpCoef->lt_status.win_prediction_used,
+ pChVars[ch]->pShareWfxpCoef->lt_status.sfb_prediction_used,
+ pChVars[ch]->fxpCoef, /* input and output */
+ pChVars[ch]->pShareWfxpCoef->qFormat, /* input and output */
+ pVars->share.predictedSamples,
+ qPredictedSamples, /* q format for previous aray */
+ pFrameInfo->coef_per_win[0], /* Look above */
+ NUM_SHORT_WINDOWS,
+ NUM_RECONSTRUCTED_SFB);
+
+ } /* end if (pChVars[ch]->lt_status.ltp_data_present != FALSE) */
+
+ } /* for(ch) */
+
+ for (ch = 0; (ch < pMC_Info->nch); ch++)
+ {
+
+ pFrameInfo = pVars->winmap[pChVars[ch]->wnd];
+
+ /*
+ * TNS - Temporal Noise Shaping
+ */
+
+ /* This is the forward filter
+ *
+ * A special note: Scratch memory is not used by
+ * the forward filter, but is passed in to maintain
+ * common interface for inverse and forward filter
+ */
+ apply_tns(
+ pChVars[ch]->fxpCoef,
+ pChVars[ch]->pShareWfxpCoef->qFormat,
+ pFrameInfo,
+ &(pChVars[ch]->pShareWfxpCoef->tns),
+ FALSE, /* FALSE is IIR */
+ pVars->scratch.tns_inv_filter);
+
+ /*
+ * Normalize the q format across all scale factor bands
+ * to one value.
+ */
+ qFormatNorm =
+ q_normalize(
+ pChVars[ch]->pShareWfxpCoef->qFormat,
+ pFrameInfo,
+ pChVars[ch]->abs_max_per_window,
+ pChVars[ch]->fxpCoef);
+
+ /*
+ * filterbank - converts frequency coeficients to time domain.
+ */
+
+#ifdef AAC_PLUS
+ if (sbrBitStream->NrElements == 0 && pMC_Info->upsamplingFactor == 1)
+ {
+ trans4m_freq_2_time_fxp_2(
+ pChVars[ch]->fxpCoef,
+ pChVars[ch]->time_quant,
+ pChVars[ch]->wnd, /* window sequence */
+ pChVars[ch]->wnd_shape_prev_bk,
+ pChVars[ch]->wnd_shape_this_bk,
+ qFormatNorm,
+ pChVars[ch]->abs_max_per_window,
+ pVars->scratch.fft,
+ &pExt->pOutputBuffer[ch]);
+ /*
+ * Update LTP buffers if needed
+ */
+
+ if (pVars->mc_info.audioObjectType == MP4AUDIO_LTP)
+ {
+ Int16 * pt = &pExt->pOutputBuffer[ch];
+ Int16 * ptr = &(pChVars[ch]->ltp_buffer[pVars->ltp_buffer_state]);
+ Int16 x, y;
+ for (Int32 i = HALF_LONG_WINDOW; i != 0; i--)
+ {
+ x = *pt;
+ pt += 2;
+ y = *pt;
+ pt += 2;
+ *(ptr++) = x;
+ *(ptr++) = y;
+ }
+ }
+ }
+ else
+ {
+ trans4m_freq_2_time_fxp_1(
+ pChVars[ch]->fxpCoef,
+ pChVars[ch]->time_quant,
+ &(pChVars[ch]->ltp_buffer[pVars->ltp_buffer_state + 288]),
+ pChVars[ch]->wnd, /* window sequence */
+ pChVars[ch]->wnd_shape_prev_bk,
+ pChVars[ch]->wnd_shape_this_bk,
+ qFormatNorm,
+ pChVars[ch]->abs_max_per_window,
+ pVars->scratch.fft);
+
+ }
+#else
+
+ trans4m_freq_2_time_fxp_2(
+ pChVars[ch]->fxpCoef,
+ pChVars[ch]->time_quant,
+ pChVars[ch]->wnd, /* window sequence */
+ pChVars[ch]->wnd_shape_prev_bk,
+ pChVars[ch]->wnd_shape_this_bk,
+ qFormatNorm,
+ pChVars[ch]->abs_max_per_window,
+ pVars->scratch.fft,
+ &pExt->pOutputBuffer[ch]);
+ /*
+ * Update LTP buffers only if needed
+ */
+
+ if (pVars->mc_info.audioObjectType == MP4AUDIO_LTP)
+ {
+ Int16 * pt = &pExt->pOutputBuffer[ch];
+ Int16 * ptr = &(pChVars[ch]->ltp_buffer[pVars->ltp_buffer_state]);
+ Int16 x, y;
+ for (Int32 i = HALF_LONG_WINDOW; i != 0; i--)
+ {
+ x = *pt;
+ pt += 2;
+ y = *pt;
+ pt += 2;
+ *(ptr++) = x;
+ *(ptr++) = y;
+ }
+
+ }
+
+
+#endif
+
+
+ /* Update the window shape */
+ pChVars[ch]->wnd_shape_prev_bk = pChVars[ch]->wnd_shape_this_bk;
+
+ } /* end for() */
+
+
+ /*
+ * Copy to the final output buffer, taking into account the desired
+ * channels from the calling environment, the actual channels, and
+ * whether the data should be interleaved or not.
+ *
+ * If the stream had only one channel, write_output will not use
+ * the right channel data.
+ *
+ */
+
+
+ /* CONSIDER USE OF DMA OPTIMIZATIONS WITHIN THE write_output FUNCTION.
+ *
+ * It is presumed that the ltp_buffer will reside in internal (fast)
+ * memory, while the pExt->pOutputBuffer will reside in external
+ * (slow) memory.
+ *
+ */
+
+
+#ifdef AAC_PLUS
+
+ if (sbrBitStream->NrElements || pMC_Info->upsamplingFactor == 2)
+ {
+
+ if (pVars->bno <= 1) /* allows console to operate with ADIF and audio config */
+ {
+ if (sbrDec->outSampleRate == 0) /* do it only once (disregarding of signaling type) */
+ {
+ sbr_open(samp_rate_info[pVars->mc_info.sampling_rate_idx].samp_rate,
+ sbrDec,
+ sbrDecoderData,
+ pVars->mc_info.bDownSampledSbr);
+ }
+
+ }
+ pMC_Info->upsamplingFactor =
+ sbrDecoderData->SbrChannel[0].frameData.sbr_header.sampleRateMode;
+
+
+ /* reuse right aac spectrum channel */
+ {
+ Int16 *pt_left = &(pChVars[LEFT ]->ltp_buffer[pVars->ltp_buffer_state]);
+ Int16 *pt_right = &(pChVars[RIGHT]->ltp_buffer[pVars->ltp_buffer_state]);
+
+ if (sbr_applied(sbrDecoderData,
+ sbrBitStream,
+ pt_left,
+ pt_right,
+ pExt->pOutputBuffer,
+ sbrDec,
+ pVars,
+ pMC_Info->nch) != SBRDEC_OK)
+ {
+ status = MP4AUDEC_INVALID_FRAME;
+ }
+ }
+
+
+ } /* if( pExt->aacPlusEnabled == FALSE) */
+#endif
+
+ /*
+ * Copied mono data in both channels or just leave it as mono,
+ * according with desiredChannels (default is 2)
+ */
+
+ if (pExt->desiredChannels == 2)
+ {
+
+#if defined(AAC_PLUS)
+#if defined(PARAMETRICSTEREO)&&defined(HQ_SBR)
+ if (pMC_Info->nch != 2 && pMC_Info->psPresentFlag != 1)
+#else
+ if (pMC_Info->nch != 2)
+#endif
+#else
+ if (pMC_Info->nch != 2)
+#endif
+ {
+ /* mono */
+
+
+ Int16 * pt = &pExt->pOutputBuffer[0];
+ Int16 * pt2 = &pExt->pOutputBuffer[1];
+ Int i;
+ if (pMC_Info->upsamplingFactor == 2)
+ {
+ for (i = 0; i < 1024; i++)
+ {
+ *pt2 = *pt;
+ pt += 2;
+ pt2 += 2;
+ }
+ pt = &pExt->pOutputBuffer_plus[0];
+ pt2 = &pExt->pOutputBuffer_plus[1];
+
+ for (i = 0; i < 1024; i++)
+ {
+ *pt2 = *pt;
+ pt += 2;
+ pt2 += 2;
+ }
+ }
+ else
+ {
+ for (i = 0; i < 1024; i++)
+ {
+ *pt2 = *pt;
+ pt += 2;
+ pt2 += 2;
+ }
+ }
+
+ }
+
+#if defined(AAC_PLUS)
+#if defined(PARAMETRICSTEREO)&&defined(HQ_SBR)
+
+ else if (pMC_Info->psPresentFlag == 1)
+ {
+ Int32 frameSize = 0;
+ if (pExt->aacPlusEnabled == false)
+ {
+ /*
+ * Decoding eaac+ when only aac is enabled, copy L into R
+ */
+ frameSize = 1024;
+ }
+ else if (sbrDecoderData->SbrChannel[0].syncState != SBR_ACTIVE)
+ {
+ /*
+ * Decoding eaac+ when no PS data was found, copy upsampled L into R
+ */
+ frameSize = 2048;
+ }
+
+ Int16 * pt = &pExt->pOutputBuffer[0];
+ Int16 * pt2 = &pExt->pOutputBuffer[1];
+ Int i;
+ for (i = 0; i < frameSize; i++)
+ {
+ *pt2 = *pt;
+ pt += 2;
+ pt2 += 2;
+ }
+ }
+#endif
+#endif
+
+ }
+ else
+ {
+
+#if defined(AAC_PLUS)
+#if defined(PARAMETRICSTEREO)&&defined(HQ_SBR)
+ if (pMC_Info->nch != 2 && pMC_Info->psPresentFlag != 1)
+#else
+ if (pMC_Info->nch != 2)
+#endif
+#else
+ if (pMC_Info->nch != 2)
+#endif
+ {
+ /* mono */
+ Int16 * pt = &pExt->pOutputBuffer[0];
+ Int16 * pt2 = &pExt->pOutputBuffer[0];
+ Int i;
+
+ if (pMC_Info->upsamplingFactor == 2)
+ {
+ for (i = 0; i < 1024; i++)
+ {
+ *pt2++ = *pt;
+ pt += 2;
+ }
+
+ pt = &pExt->pOutputBuffer_plus[0];
+ pt2 = &pExt->pOutputBuffer_plus[0];
+
+ for (i = 0; i < 1024; i++)
+ {
+ *pt2++ = *pt;
+ pt += 2;
+ }
+ }
+ else
+ {
+ for (i = 0; i < 1024; i++)
+ {
+ *pt2++ = *pt;
+ pt += 2;
+ }
+ }
+
+ }
+
+ }
+
+
+
+
+ /* pVars->ltp_buffer_state cycles between 0 and 1024. The value
+ * indicates the location of the data corresponding to t == -2.
+ *
+ * | t == -2 | t == -1 | pVars->ltp_buffer_state == 0
+ *
+ * | t == -1 | t == -2 | pVars->ltp_buffer_state == 1024
+ *
+ */
+
+#ifdef AAC_PLUS
+ if (sbrBitStream->NrElements == 0 && pMC_Info->upsamplingFactor == 1)
+ {
+ pVars->ltp_buffer_state ^= frameLength;
+ }
+ else
+ {
+ pVars->ltp_buffer_state ^= (frameLength + 288);
+ }
+#else
+ pVars->ltp_buffer_state ^= frameLength;
+#endif
+
+
+ if (pVars->bno <= 1)
+ {
+ /*
+ * to set these values only during the second call
+ * when they change.
+ */
+ pExt->samplingRate =
+ samp_rate_info[pVars->mc_info.sampling_rate_idx].samp_rate;
+
+ pVars->mc_info.implicit_channeling = 0; /* disable flag, as this is allowed
+ * only the first time
+ */
+
+
+#ifdef AAC_PLUS
+
+ if (pMC_Info->upsamplingFactor == 2)
+ {
+ pExt->samplingRate *= pMC_Info->upsamplingFactor;
+ pExt->aacPlusUpsamplingFactor = pMC_Info->upsamplingFactor;
+ }
+
+#endif
+
+ pExt->extendedAudioObjectType = pMC_Info->ExtendedAudioObjectType;
+ pExt->audioObjectType = pMC_Info->audioObjectType;
+
+ pExt->encodedChannels = pMC_Info->nch;
+ pExt->frameLength = pVars->frameLength;
+ }
+
+ pVars->bno++;
+
+
+ /*
+ * Using unit analysis, the bitrate is a function of the sampling rate, bits,
+ * points in a frame
+ *
+ * bits samples frame
+ * ---- = --------- * bits * -------
+ * sec sec sample
+ *
+ * To save a divide, a shift is used. Presently only the value of
+ * 1024 is used by this library, so make it the most accurate for that
+ * value. This may need to be updated later.
+ */
+
+ pExt->bitRate = (pExt->samplingRate *
+ (pVars->inputStream.usedBits - initialUsedBits)) >> 10; /* LONG_WINDOW 1024 */
+
+ pExt->bitRate >>= (pMC_Info->upsamplingFactor - 1);
+
+
+ } /* end if (status == SUCCESS) */
+
+
+ if (status != MP4AUDEC_SUCCESS)
+ {
+ /*
+ * A non-SUCCESS decoding could be due to an error on the bitstream or
+ * an incomplete frame. As access to the bitstream beyond frame boundaries
+ * are not allowed, in those cases the bitstream reading routine return a 0
+ * Zero values guarantees that the data structures are filled in with values
+ * that eventually will signal an error (like invalid parameters) or that allow
+ * completion of the parsing routine. Either way, the partial frame condition
+ * is verified at this time.
+ */
+ if (pVars->prog_config.file_is_adts == TRUE)
+ {
+ status = MP4AUDEC_LOST_FRAME_SYNC;
+ pVars->prog_config.headerless_frames = 0; /* synchronization forced */
+ }
+ else
+ {
+ /*
+ * Check if the decoding error was due to buffer overrun, if it was,
+ * update status
+ */
+ if (pVars->inputStream.usedBits > pVars->inputStream.availableBits)
+ {
+ /* all bits were used but were not enough to complete decoding */
+ pVars->inputStream.usedBits = pVars->inputStream.availableBits;
+
+ status = MP4AUDEC_INCOMPLETE_FRAME; /* possible EOF or fractional frame */
+ }
+ }
+ }
+
+ /*
+ * Translate from units of bits back into units of words.
+ */
+
+ pExt->inputBufferUsedLength =
+ pVars->inputStream.usedBits >> INBUF_ARRAY_INDEX_SHIFT;
+
+ pExt->remainderBits = (Int)(pVars->inputStream.usedBits & INBUF_BIT_MODULO_MASK);
+
+
+
+ return (status);
+
+} /* PVMP4AudioDecoderDecodeFrame */
+
diff --git a/media/libstagefright/codecs/aacdec/pvmp4audiodecodergetmemrequirements.cpp b/media/libstagefright/codecs/aacdec/pvmp4audiodecodergetmemrequirements.cpp
new file mode 100644
index 0000000..7cdecd0
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pvmp4audiodecodergetmemrequirements.cpp
@@ -0,0 +1,157 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: PVMP4AudioDecoderGetMemRequirements.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Copied from aac_decode_frame
+
+ Description: Cleaned up.
+
+ Description: (1) use UInt32 to replace size_t type
+ (2) memory of tDec_Int_File is splitted into 3 pieces,
+ sizeof(tDec_Int_File) is only part of the total memory
+ required. The additional memory required to decode per
+ channel information is allocated by a DPI call outside this
+ API
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs: None
+
+ Local Stores/Buffers/Pointers Needed: None
+
+ Global Stores/Buffers/Pointers Needed: None
+
+ Outputs:
+ size = amount of memory needed to be allocated by the calling
+ environment.
+
+ Pointers and Buffers Modified: None
+
+ Local Stores Modified: None
+
+ Global Stores Modified: None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function returns the amount of internal memory needed by the library.
+ Presently this is a constant value, but could later be more sophisticated
+ by taking into account mono or stereo, and whether LTP is to be used.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ size = sizeof(tDec_Int_File);
+
+ RETURN (size)
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+#include "s_tdec_int_file.h"
+#include "pvmp4audiodecoder_api.h" /* Where this function is declared */
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+OSCL_EXPORT_REF UInt32 PVMP4AudioDecoderGetMemRequirements(void)
+{
+ UInt32 size;
+
+ size = (UInt32) sizeof(tDec_Int_File);
+
+ return (size);
+
+} /* PVMP4AudioDecoderGetMemRequirements() */
+
diff --git a/media/libstagefright/codecs/aacdec/pvmp4audiodecoderinitlibrary.cpp b/media/libstagefright/codecs/aacdec/pvmp4audiodecoderinitlibrary.cpp
new file mode 100644
index 0000000..146ba0f
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pvmp4audiodecoderinitlibrary.cpp
@@ -0,0 +1,418 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: PVMP4AudioDecoderInitLibrary.c
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Copied from aac_decode_frame
+
+ Description: Clean up.
+
+ Description: Update per review comments
+
+ Description: Add frame_length, fix mistake in pseudo-code.
+ Change frame_length to frameLength, to matcht the API,
+ look more professional, etc.
+
+ Description:
+ (1) Added #include of "e_ProgConfigConst.h"
+ Previously, this function was relying on another include file
+ to include "e_ProgConfigConst.h"
+
+ (2) Updated the copyright header.
+
+ Description:
+ (1) Modified to initialize pointers for shared memory techniques.
+
+ Description: Since memory will be allocated continuously, it is initialized
+ in one spot
+
+ Description: Added field aacPlusUpsamplingFactor (default == 1) to have a
+ common interface for all AAC variations
+
+ Description: Added PVMP4AudioDecoderDisableAacPlus to disable sbr decoding
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pExt = pointer to the external application-program interface (API)
+ structure that a client program uses to communicate information
+ with this library. Among the items in this structure is a pointer
+ to the input and output buffers, data for handling the input buffer
+ and output information. Look in PVMP4AudioDecoder_API.h for all the
+ fields to this structure. Data type pointer to a
+ tPVMP4AudioDecoderExternal structure.
+
+ pMem = pointer to allocated memory, of the size returned by the function
+ PVMP4AudioDecoderGetMemRequirements. This is a void pointer for
+ two reasons:
+ 1) So the external program does not need all of the header files
+ for all of the fields in the structure tDec_Int_File
+ 2) To hide data and the implementation of the program. Even knowing
+ how data is stored can help in reverse engineering software.
+
+ Local Stores/Buffers/Pointers Needed: None
+
+ Global Stores/Buffers/Pointers Needed: None
+
+ Outputs:
+ status = 0 (SUCCESS). Presently there is no error checking in this
+ function.
+
+ Pointers and Buffers Modified: None
+
+ Local Stores Modified: None
+
+ Global Stores Modified: None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Initializes the internal memory for the MP4 Audio Decoder library.
+ Also sets relevant values for the external interface structure, clears
+ the bit rate, channel count, sampling rate, and number of used buffer
+ elements.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ pVars = pMem;
+
+ CALL pv_memset(
+ to = pVars,
+ c = 0,
+ n = sizeof(tDec_Int_File))
+ MODIFYING(*pVars = 0)
+ RETURNING(nothing)
+
+ pVars->current_program = -1
+ pVars->mc_info.sampling_rate_idx = Fs_44
+ pVars->frameLength = LONG_WINDOW
+
+
+ pVars->winmap[ONLY_LONG_SEQUENCE] = &pVars->longFrameInfo;
+ pVars->winmap[LONG_START_SEQUENCE] = &pVars->longFrameInfo;
+ pVars->winmap[EIGHT_SHORT_SEQUENCE] = &pVars->shortFrameInfo;
+ pVars->winmap[LONG_STOP_SEQUENCE] = &pVars->longFrameInfo;
+
+ CALL infoinit(
+ samp_rate_indx = pVars->mc_info.sampling_rate_idx,
+ ppWin_seq_info = pVars->winmap,
+ pSfbwidth128 = pVars->SFBWidth128)
+ MODIFYING(ppWinSeq_info)
+ MODIFYING(pSfbwidth128)
+ RETURNING(nothing)
+
+ pExt->bitRate = 0;
+ pExt->encodedChannels = 0;
+ pExt->samplingRate = 0;
+ pExt->inputBufferUsedLength = 0;
+
+ MODIFY(pExt)
+ MODIFY(pMem)
+ RETURN(SUCCESS)
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+#include "s_tdec_int_file.h"
+#include "e_progconfigconst.h"
+
+#include "huffman.h" /* For the definition of infoinit */
+#include "aac_mem_funcs.h" /* For pv_memset */
+#include "pvmp4audiodecoder_api.h" /* Where this function is declared */
+#include "s_tdec_int_chan.h"
+#include "sfb.h" /* samp_rate_info[] is declared here */
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+OSCL_EXPORT_REF Int PVMP4AudioDecoderInitLibrary(
+ tPVMP4AudioDecoderExternal *pExt,
+ void *pMem)
+{
+ tDec_Int_File *pVars;
+
+ pVars = (tDec_Int_File *)pMem;
+
+ /*
+ * Initialize all memory. The pointers to channel memory will be
+ * set to zero also.
+ */
+ pv_memset(
+ pVars,
+ 0,
+ sizeof(tDec_Int_File));
+
+ /*
+ * Pick default values for the library.
+ */
+ pVars->perChan[0].fxpCoef = pVars->fxpCoef[0];
+ pVars->perChan[1].fxpCoef = pVars->fxpCoef[1];
+
+ /* Here, the "shared memory" pointer is set to point
+ * at the 1024th element of fxpCoef, because those spaces
+ * in memory are not used until the filterbank is called.
+ *
+ * Therefore, any variables that are only used before
+ * the filterbank can occupy this same space in memory.
+ */
+
+ pVars->perChan[0].pShareWfxpCoef = (per_chan_share_w_fxpCoef *)
+ & (pVars->perChan[0].fxpCoef[1024]);
+
+ pVars->perChan[1].pShareWfxpCoef = (per_chan_share_w_fxpCoef *)
+ & (pVars->perChan[1].fxpCoef[1024]);
+
+ /*
+ * This next line informs the function get_prog_config that no
+ * configuration has been found thus far, so it is a default
+ * configuration.
+ */
+
+ pVars->current_program = -1;
+ pVars->mc_info.sampling_rate_idx = Fs_44; /* Fs_44 = 4, 44.1kHz */
+
+ /*
+ * In the future, the frame length will change with MP4 file format.
+ * Presently this variable is used to simply the unit test for
+ * the function PVMP4AudioDecodeFrame() .. otherwise the test would
+ * have to pass around 1024 length arrays.
+ */
+ pVars->frameLength = LONG_WINDOW; /* 1024*/
+
+ /*
+ * The window types ONLY_LONG_SEQUENCE, LONG_START_SEQUENCE, and
+ * LONG_STOP_SEQUENCE share the same information. The only difference
+ * between the windows is accounted for in the "filterbank", in
+ * the function trans4m_freq_2_time_fxp()
+ */
+
+ pVars->winmap[ONLY_LONG_SEQUENCE] /* 0 */ = &pVars->longFrameInfo;
+ pVars->winmap[LONG_START_SEQUENCE] /* 1 */ = &pVars->longFrameInfo;
+ pVars->winmap[EIGHT_SHORT_SEQUENCE] /* 2 */ = &pVars->shortFrameInfo;
+ pVars->winmap[LONG_STOP_SEQUENCE] /* 3 */ = &pVars->longFrameInfo;
+
+ infoinit(
+ pVars->mc_info.sampling_rate_idx,
+ (FrameInfo **)pVars->winmap,
+ pVars->SFBWidth128);
+
+
+ /*
+ * Clear out external output values. These values are set later at the end
+ * of PVMP4AudioDecodeFrames()
+ */
+ pExt->bitRate = 0;
+ pExt->encodedChannels = 0;
+ pExt->samplingRate = 0;
+ pExt->aacPlusUpsamplingFactor = 1; /* Default for regular AAC */
+ pVars->aacPlusEnabled = pExt->aacPlusEnabled;
+
+
+#if defined(AAC_PLUS)
+ pVars->sbrDecoderData.setStreamType = 1; /* Enable Lock for AAC stream type setting */
+#endif
+
+ /*
+ * Initialize input buffer variable.
+ */
+
+ pExt->inputBufferUsedLength = 0;
+
+ return (MP4AUDEC_SUCCESS);
+
+} /* PVMP4AudioDecoderInitLibrary */
+
+
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pExt = pointer to the external application-program interface (API)
+ structure that a client program uses to communicate information
+ with this library. Among the items in this structure is a pointer
+ to the input and output buffers, data for handling the input buffer
+ and output information. Look in PVMP4AudioDecoder_API.h for all the
+ fields to this structure. Data type pointer to a
+ tPVMP4AudioDecoderExternal structure.
+
+ pMem = pointer to allocated memory, of the size returned by the function
+ PVMP4AudioDecoderGetMemRequirements. This is a void pointer for
+ two reasons:
+ 1) So the external program does not need all of the header files
+ for all of the fields in the structure tDec_Int_File
+ 2) To hide data and the implementation of the program. Even knowing
+ how data is stored can help in reverse engineering software.
+
+ Local Stores/Buffers/Pointers Needed: None
+
+ Global Stores/Buffers/Pointers Needed: None
+
+ Outputs:
+ status = 0 (SUCCESS). Presently there is no error checking in this
+ function.
+
+ Pointers and Buffers Modified: None
+
+ Local Stores Modified: None
+
+ Global Stores Modified: None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Disable SBR decoding functionality and set parameters accordingly
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+OSCL_EXPORT_REF void PVMP4AudioDecoderDisableAacPlus(
+ tPVMP4AudioDecoderExternal *pExt,
+ void *pMem)
+{
+ tDec_Int_File *pVars;
+
+ pVars = (tDec_Int_File *)pMem;
+
+ if ((pVars->aacPlusEnabled == true) && (pExt->aacPlusEnabled == true))
+ {
+ // disable only when makes sense
+ pVars->aacPlusEnabled = false;
+ pExt->aacPlusEnabled = false;
+
+#if defined(AAC_PLUS)
+ pVars->mc_info.upsamplingFactor = 1;
+ pVars->mc_info.psPresentFlag = 0;
+ pVars->mc_info.sbrPresentFlag = 0;
+ pVars->prog_config.sampling_rate_idx += 3;
+ pVars->sbrDecoderData.SbrChannel[0].syncState = SBR_NOT_INITIALIZED;
+ pVars->sbrDecoderData.SbrChannel[1].syncState = SBR_NOT_INITIALIZED;
+
+
+ pExt->samplingRate = samp_rate_info[pVars->prog_config.sampling_rate_idx].samp_rate;
+ pExt->aacPlusUpsamplingFactor = 1;
+#endif
+ }
+} /* PVMP4AudioDecoderDisableAacPlus */
+
+
+
diff --git a/media/libstagefright/codecs/aacdec/pvmp4audiodecoderresetbuffer.cpp b/media/libstagefright/codecs/aacdec/pvmp4audiodecoderresetbuffer.cpp
new file mode 100644
index 0000000..c10423b
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pvmp4audiodecoderresetbuffer.cpp
@@ -0,0 +1,354 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: PVMP4AudioDecoderResetBuffer.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: (1) add more comments (2) set pVars->bno = 1
+
+ Description: perChan[] is an array of structures in tDec_Int_File. Made
+ corresponding changes.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ pMem = void pointer to hide the internal implementation of the library
+ It is cast back to a tDec_Int_File structure. This structure
+ contains information that needs to persist between calls to
+ PVMP4AudioDecodeFrame
+ Data type void pointer, internally pointer to a tDec_Int_File
+ structure.
+
+ Local Stores/Buffers/Pointers Needed: None
+ (The memory set aside in pMem performs this task)
+
+ Global Stores/Buffers/Pointers Needed: None
+
+ Outputs: None
+
+ Pointers and Buffers Modified:
+ pMem contents are modified.
+ pMem->perChan[0].time_quant[0-1023]: contents are set to zero
+ pMem->perChan[1].time_quant[0-1023]: contents are set to zero
+ pMem->bno = 1
+
+ Local Stores Modified: None.
+
+ Global Stores Modified: None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function is called when the same audio clip will be played again from
+ the begining. This situation happens when the "stop" button is pressed or
+ the "loop-mode" is selected on PVPlayer. Since it is the same audio clip to
+ be played again, the decoder does not need to reset the audioSpecificInfo.
+ However, the overlap-and-add buffer of the filterbank output needs to be
+ cleared, so that the decoder can re-start properly from the begining of
+ the audio. The frame number counter, pVars->bno, is set to 1 because the
+ audioSpecificInfo is decoded on pVars->bno==0
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ PacketVideo Document # CCC-AUD-AAC-ERS-0003
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3: 1999(E)
+ subclause 1.6
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_tdec_int_file.h"
+#include "pvmp4audiodecoder_api.h" /* Where this function is declared */
+#include "aac_mem_funcs.h"
+
+#ifdef AAC_PLUS
+#include "s_sbr_frame_data.h"
+#endif
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define LEFT (0)
+#define RIGHT (1)
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+OSCL_EXPORT_REF void PVMP4AudioDecoderResetBuffer(void *pMem)
+{
+
+ tDec_Int_File *pVars; /* Helper pointer */
+
+#ifdef AAC_PLUS
+ SBR_FRAME_DATA * hFrameData_1;
+ SBR_FRAME_DATA * hFrameData_2;
+#ifdef HQ_SBR
+#ifdef PARAMETRICSTEREO
+ SBRDECODER_DATA *sbrDecoderData;
+#endif
+#endif
+
+#endif
+ /*
+ * Initialize "helper" pointers to existing memory.
+ */
+ pVars = (tDec_Int_File *)pMem;
+
+ /*
+ * Clear the overlap-and-add buffer of filterbank output. The audio
+ * clip will be played again from the beginning.
+ */
+ pv_memset(pVars->perChan[LEFT].time_quant,
+ 0,
+ LONG_WINDOW*sizeof(pVars->perChan[LEFT].time_quant[0]));
+
+ pv_memset(pVars->perChan[RIGHT].time_quant,
+ 0,
+ LONG_WINDOW*sizeof(pVars->perChan[RIGHT].time_quant[0]));
+
+
+#ifdef AAC_PLUS
+
+ if (!pVars->sbrDecoderData.setStreamType) /* reset only when stream type is defined */
+ {
+ if (pVars->aacPlusEnabled == true) /* clear buffer only if they were used */
+ {
+
+ hFrameData_1 = (SBR_FRAME_DATA *) & pVars->sbrDecoderData.SbrChannel[LEFT].frameData;
+ hFrameData_2 = (SBR_FRAME_DATA *) & pVars->sbrDecoderData.SbrChannel[RIGHT].frameData;
+#ifdef HQ_SBR
+#ifdef PARAMETRICSTEREO
+ sbrDecoderData = (SBRDECODER_DATA *) & pVars->sbrDecoderData;
+ sbrDecoderData->hParametricStereoDec = (HANDLE_PS_DEC) & pVars->sbrDecoderData.ParametricStereoDec;
+#endif
+#endif
+
+
+ pv_memset(&pVars->perChan[LEFT].ltp_buffer[0],
+ 0,
+ 288*sizeof(pVars->perChan[LEFT].ltp_buffer[0]));
+ pv_memset(&pVars->perChan[LEFT].ltp_buffer[1024 + 288],
+ 0,
+ 288*sizeof(pVars->perChan[LEFT].ltp_buffer[0]));
+ pv_memset(hFrameData_1->V,
+ 0,
+ 1152*sizeof(hFrameData_1->V[0]));
+ pv_memset(hFrameData_1->prevNoiseLevel_man,
+ 0,
+ MAX_NUM_NOISE_VALUES*sizeof(hFrameData_1->prevNoiseLevel_man[0]));
+
+
+ pv_memset(&pVars->perChan[RIGHT].ltp_buffer[0],
+ 0,
+ 288*sizeof(pVars->perChan[RIGHT].ltp_buffer[0]));
+ pv_memset(&pVars->perChan[RIGHT].ltp_buffer[1024 + 288],
+ 0,
+ 288*sizeof(pVars->perChan[RIGHT].ltp_buffer[0]));
+ pv_memset(hFrameData_2->V,
+ 0,
+ 1152*sizeof(hFrameData_2->V[0]));
+
+ pv_memset(hFrameData_2->prevNoiseLevel_man,
+ 0,
+ MAX_NUM_NOISE_VALUES*sizeof(hFrameData_2->prevNoiseLevel_man[0]));
+
+
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ pv_memset((void *)&hFrameData_1->codecQmfBufferReal[i],
+ 0,
+ sizeof(**hFrameData_1->codecQmfBufferReal) << 5);
+ }
+
+
+ /* ---- */
+ pv_memset((void *)hFrameData_1->BwVectorOld,
+ 0,
+ sizeof(*hFrameData_1->BwVectorOld)*MAX_NUM_PATCHES);
+
+#ifdef HQ_SBR
+
+ for (i = 0; i < 5; i++)
+ {
+ pv_memset((void *)&hFrameData_1->fBuffer_man[i],
+ 0,
+ sizeof(**hFrameData_1->fBuffer_man)*64);
+ pv_memset((void *)&hFrameData_1->fBufferN_man[i],
+ 0,
+ sizeof(**hFrameData_1->fBufferN_man)*64);
+ }
+#endif
+
+
+ /* ---- */
+
+
+
+ pv_memset((void *)hFrameData_1->HistsbrQmfBufferReal,
+ 0,
+ sizeof(*hFrameData_1->HistsbrQmfBufferReal)*6*SBR_NUM_BANDS);
+
+#ifdef HQ_SBR
+ pv_memset((void *)hFrameData_1->HistsbrQmfBufferImag,
+ 0,
+ sizeof(*hFrameData_1->HistsbrQmfBufferImag)*6*SBR_NUM_BANDS);
+#endif
+
+ if (pVars->sbrDec.LC_aacP_DecoderFlag == 1) /* clear buffer only for LC decoding */
+ {
+
+ for (i = 0; i < 8; i++)
+ {
+ pv_memset((void *)&hFrameData_2->codecQmfBufferReal[i],
+ 0,
+ sizeof(**hFrameData_1->codecQmfBufferReal) << 5);
+ }
+
+ pv_memset((void *)hFrameData_2->HistsbrQmfBufferReal,
+ 0,
+ sizeof(*hFrameData_2->HistsbrQmfBufferReal)*6*SBR_NUM_BANDS);
+
+
+ pv_memset((void *)hFrameData_2->BwVectorOld,
+ 0,
+ sizeof(*hFrameData_2->BwVectorOld)*MAX_NUM_PATCHES);
+
+#ifdef HQ_SBR
+
+ for (i = 0; i < 5; i++)
+ {
+ pv_memset((void *)&hFrameData_2->fBuffer_man[i],
+ 0,
+ sizeof(**hFrameData_2->fBuffer_man)*64);
+ pv_memset((void *)&hFrameData_2->fBufferN_man[i],
+ 0,
+ sizeof(**hFrameData_2->fBufferN_man)*64);
+ }
+#endif
+
+ }
+
+#ifdef HQ_SBR
+#ifdef PARAMETRICSTEREO
+ else if (pVars->mc_info.psPresentFlag == 1)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ pv_memset(sbrDecoderData->hParametricStereoDec->hHybrid->mQmfBufferReal[i],
+ 0,
+ HYBRID_FILTER_LENGTH_m_1*sizeof(*sbrDecoderData->hParametricStereoDec->hHybrid->mQmfBufferReal));
+ pv_memset(sbrDecoderData->hParametricStereoDec->hHybrid->mQmfBufferImag[i],
+ 0,
+ HYBRID_FILTER_LENGTH_m_1*sizeof(*sbrDecoderData->hParametricStereoDec->hHybrid->mQmfBufferImag));
+ }
+ }
+#endif
+#endif
+
+ /*
+ * default to UPSAMPLING, as if the file is SBR_ACTIVE, this will be fine and will be
+ * fixed onced the new sbr header is found
+ * SBR headers contain SBT freq. range as well as control signals that do not require
+ * frequent changes.
+ * For streaming, the SBR header is sent twice per second. Also, an SBR header can be
+ * inserted at any time, if a change of parameters is needed.
+ */
+
+ pVars->sbrDecoderData.SbrChannel[LEFT].syncState = UPSAMPLING;
+ pVars->sbrDecoderData.SbrChannel[RIGHT].syncState = UPSAMPLING;
+
+ }
+ }
+#endif /* #ifdef AAC_PLUS */
+
+ /* reset frame count to 1 */
+ pVars->bno = 1;
+
+ return ;
+
+} /* PVMP4AudioDecoderDecodeFrame */
+
diff --git a/media/libstagefright/codecs/aacdec/pvmp4setaudioconfig.cpp b/media/libstagefright/codecs/aacdec/pvmp4setaudioconfig.cpp
new file mode 100644
index 0000000..d183d84
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/pvmp4setaudioconfig.cpp
@@ -0,0 +1,368 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: pvmp4setaudioconfigg
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pExt = pointer to the external interface structure. See the file
+ PVMP4AudioDecoder_API.h for a description of each field.
+ Data type of pointer to a tPVMP4AudioDecoderExternal
+ structure.
+
+ pExt->pInputBuffer: pointer to input buffer containing input
+ bitstream
+
+ pExt->inputBufferCurrentLength: number of bytes in the input buffer
+
+ pExt->inputBufferUsedLength: number of bytes already consumed in
+ input buffer
+
+ pExt->remainderBits: number of bits consumed in addition to
+ pExt->inputBufferUsedLength
+
+ pMem = void pointer to hide the internal implementation of the library
+ It is cast back to a tDec_Int_File structure. This structure
+ contains information that needs to persist between calls to
+ this function, or is too big to be placed on the stack, even
+ though the data is only needed during execution of this function
+ Data type void pointer, internally pointer to a tDec_Int_File
+ structure.
+
+ Local Stores/Buffers/Pointers Needed: None
+ (The memory set aside in pMem performs this task)
+
+ Global Stores/Buffers/Pointers Needed: None
+
+ Outputs:
+ status = 0 if no error occurred
+ MP4AUDEC_NONRECOVERABLE if a non-recoverable error occurred
+ MP4AUDEC_RECOVERABLE if a recoverable error occurred.
+ Presently a recoverable error does not exist, but this
+ was a requirement.
+
+
+ Pointers and Buffers Modified:
+ pMem contents are modified.
+ pExt: (more detail in the file PVMP4AudioDecoder_API.h)
+ inputBufferUsedLength - number of array elements used up by the stream.
+ remainderBits - remaining bits in the next UInt32 buffer
+ samplingRate - sampling rate in samples per sec
+ encodedChannels - channels found on the file (informative)
+ frameLength - length of the frame
+
+ Local Stores Modified: None.
+
+ Global Stores Modified: None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ PacketVideo Document # CCC-AUD-AAC-ERS-0003
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+#include "s_tdec_int_file.h"
+#include "ibstream.h" /* where #define INBUF_ARRAY_INDEX_SHIFT */
+#include "sfb.h" /* Where samp_rate_info[] is declared */
+
+#include "get_audio_specific_config.h"
+#include "pvmp4audiodecoder_api.h" /* Where this function is declared */
+#include "set_mc_info.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int PVMP4SetAudioConfig(
+ tPVMP4AudioDecoderExternal *pExt,
+ void *pMem,
+ Int upsamplingFactor,
+ Int samp_rate,
+ Int num_ch,
+ tMP4AudioObjectType audioObjectType)
+
+{
+
+ tDec_Int_File *pVars; /* Helper pointer */
+
+ Int status = MP4AUDEC_INCOMPLETE_FRAME;
+
+ /*
+ * Initialize "helper" pointers to existing memory.
+ */
+ pVars = (tDec_Int_File *)pMem;
+ /*
+ * Translate input buffer variables.
+ */
+ pVars->inputStream.pBuffer = pExt->pInputBuffer;
+
+ pVars->inputStream.availableBits = 0;
+
+ pVars->inputStream.usedBits = 0;
+
+
+
+ /*
+ * get sampling rate index
+ */
+
+ switch (samp_rate)
+ {
+ case 96000:
+ pVars->prog_config.sampling_rate_idx = 0;
+ break;
+ case 88200:
+ pVars->prog_config.sampling_rate_idx = 1;
+ break;
+ case 64000:
+ pVars->prog_config.sampling_rate_idx = 2;
+ break;
+ case 48000:
+ pVars->prog_config.sampling_rate_idx = 3;
+ break;
+ case 44100:
+ pVars->prog_config.sampling_rate_idx = 4;
+ break;
+ case 32000:
+ pVars->prog_config.sampling_rate_idx = 5;
+ break;
+ case 24000:
+ pVars->prog_config.sampling_rate_idx = 6;
+ break;
+ case 22050:
+ pVars->prog_config.sampling_rate_idx = 7;
+ break;
+ case 16000:
+ pVars->prog_config.sampling_rate_idx = 8;
+ break;
+ case 12000:
+ pVars->prog_config.sampling_rate_idx = 9;
+ break;
+ case 11025:
+ pVars->prog_config.sampling_rate_idx = 10;
+ break;
+ case 8000:
+ pVars->prog_config.sampling_rate_idx = 11;
+ break;
+ case 7350:
+ pVars->prog_config.sampling_rate_idx = 12;
+ break;
+ default:
+ status = -1;
+
+ break;
+ }
+
+ pVars->mc_info.sbrPresentFlag = 0;
+ pVars->mc_info.psPresentFlag = 0;
+#ifdef AAC_PLUS
+ pVars->mc_info.bDownSampledSbr = 0;
+#endif
+ pVars->mc_info.implicit_channeling = 0;
+ pVars->mc_info.nch = num_ch;
+ pVars->mc_info.upsamplingFactor = upsamplingFactor;
+
+
+ /*
+ * Set number of channels
+ */
+
+ if (num_ch == 2)
+ {
+ pVars->prog_config.front.ele_is_cpe[0] = 1;
+ }
+ else if (num_ch == 1)
+ {
+ pVars->prog_config.front.ele_is_cpe[0] = 0;
+ }
+ else
+ {
+ status = -1; /* do not support more than two channels */
+ pVars->status = status;
+ return (status);
+ }
+
+
+ /*
+ * Set AAC bitstream
+ */
+
+ if ((audioObjectType == MP4AUDIO_AAC_LC) ||
+ (audioObjectType == MP4AUDIO_LTP))
+ {
+ pVars->aacPlusEnabled = false;
+
+ status = set_mc_info(&(pVars->mc_info),
+ audioObjectType, /* previously profile */
+ pVars->prog_config.sampling_rate_idx,
+ pVars->prog_config.front.ele_tag[0],
+ pVars->prog_config.front.ele_is_cpe[0],
+ pVars->winmap, /*pVars->pWinSeqInfo,*/
+ pVars->SFBWidth128);
+ }
+ else if ((audioObjectType == MP4AUDIO_SBR) ||
+ (audioObjectType == MP4AUDIO_PS))
+ {
+ pVars->aacPlusEnabled = true;
+
+
+ status = set_mc_info(&(pVars->mc_info),
+ MP4AUDIO_AAC_LC,
+ pVars->prog_config.sampling_rate_idx,
+ pVars->prog_config.front.ele_tag[0],
+ pVars->prog_config.front.ele_is_cpe[0],
+ pVars->winmap, /*pVars->pWinSeqInfo,*/
+ pVars->SFBWidth128);
+
+ pVars->mc_info.sbrPresentFlag = 1;
+ if (audioObjectType == MP4AUDIO_PS)
+ {
+ pVars->mc_info.psPresentFlag = 1;
+ }
+
+ if (upsamplingFactor == 1)
+ {
+#ifdef AAC_PLUS
+ pVars->mc_info.bDownSampledSbr = 1;
+#endif
+
+ /*
+ * Disable SBR decoding for any sbr-downsampled file whose SF is >= 24 KHz
+ */
+ if (pVars->prog_config.sampling_rate_idx < 6)
+ {
+ pVars->aacPlusEnabled = false;
+ }
+ }
+
+ }
+ else
+ {
+ status = -1;
+ }
+
+
+ /*
+ * Translate from units of bits back into units of words.
+ */
+ pExt->inputBufferUsedLength = 0;
+
+ pExt->remainderBits = 0;
+
+ pVars->bno++;
+
+ pExt->samplingRate = samp_rate * upsamplingFactor;
+
+ pExt->aacPlusEnabled = pVars->aacPlusEnabled;
+
+ /*
+ * we default to 2 channel, even for mono files, (where channels have same content)
+ * this is done to ensure support for enhanced aac+ with implicit signalling
+ */
+
+ pExt->encodedChannels = 2;
+
+ pExt->frameLength = 1024;
+#ifdef AAC_PLUS
+ pExt->aacPlusUpsamplingFactor = upsamplingFactor;
+#endif
+
+ pVars->status = status;
+
+ return (status);
+
+} /* PVMP4AudioDecoderDecodeFrame */
diff --git a/media/libstagefright/codecs/aacdec/q_normalize.cpp b/media/libstagefright/codecs/aacdec/q_normalize.cpp
new file mode 100644
index 0000000..5266966
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/q_normalize.cpp
@@ -0,0 +1,388 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: q_normalize.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ (1) Modify to include search over the scalefactor bands to insure
+ that the data is using all 31 data-bits.
+
+ Description:
+ (1) Modify to remove search over the scalefactor bands to insure
+ that the data is using all 31 data-bits.
+ (Pushed out into separate function)
+ (2) Change variable "k" to more descriptive "shift_amt"
+ (3) Update pseudocode to reflect removed code.
+ (4) Add PV Copyright notice.
+
+ Description:
+ (1) Modified to protect q-normalize from shifting by amounts >= 32.
+
+ Description:
+ (1) Delete local variable idx_count.
+
+ Description:
+ (1) Included search for max in each frame, modified interface.
+
+ Description:
+ (1) unrolled loop based on the fact that the size of each scale band
+ is always an even number.
+
+ Description:Check shift, if zero, do not shift.
+
+ Description: Eliminated warning: non use variable "i" and memset function
+ definition
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ qFormat[] = Array of qFormats, one per scalefactor band. [ Int ]
+
+ pFrameInfo = Pointer to structure that holds information about each group.
+ (long block flag, number of windows, scalefactor bands, etc.)
+ [const FrameInfo]
+
+ coef[] = Array of the spectral coefficients for one channel. [ Int32 ]
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ min_q = The common q-format for the entire frame. [Int]
+
+ Pointers and Buffers Modified:
+ coef[] = Array of spectral data, now normalized to one q-format.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This module first scans every scalefactor band for the frame, insuring that
+ at least one element in that scalefactor band is using all available bits.
+ If not, the elements in the scalefactor band are shifted up to use all 31
+ data bits. The q-format is adjusted accordingly.
+
+ This module then scans the q-formats for each scalefactor band.
+ Upon finding the minimum q-format in the frame, the coefficients in each
+ scalefactor band are normalized to the minimum q-format.
+ The minimum q-format is then returned to the calling function, which is now
+ the q-format for the entire frame.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ nwin = pFrameInfo->num_win;
+
+ pQformat = &(qFormat[0]);
+ pSfbPerWin = &(pFrameInfo->sfb_per_win[0]);
+ pCoef = &(coef[0]);
+
+ FOR (win = nwin; win > 0; win--)
+
+ nsfb = *(pSfbPerWin++);
+
+ FOR (sfb = nsfb; sfb > 0; sfb--)
+
+ IF ( *(pQformat) < min_q)
+ min_q = *(pQformat);
+ ENDIF
+
+ pQformat++;
+
+ ENDFOR
+
+ ENDFOR
+
+ pQformat = &(qFormat[0]);
+ pSfbPerWin = &(pFrameInfo->sfb_per_win[0]);
+ pCoef = &(coef[0]);
+
+ FOR (win = 0; win < nwin; win++)
+
+ stop_idx = 0;
+
+ nsfb = *(pSfbPerWin++);
+
+ pWinSfbTop = &(pFrameInfo->win_sfb_top[win][0]);
+
+ FOR (sfb = nsfb; sfb > 0; sfb--)
+
+ sfbWidth = *(pWinSfbTop++) - stop_idx;
+
+ stop_idx += sfbWidth;
+
+ k = *(pQformat++) - min_q;
+
+ IF (k < 32)
+ THEN
+ FOR (; sfbWidth > 0; sfbWidth--)
+ *(pCoef++) >>= k;
+ ENDFOR
+ ELSE
+ FOR (; sfbWidth > 0; sfbWidth--)
+ *(pCoef++) = 0;
+ ENDFOR
+ ENDIF
+
+ ENDFOR
+
+ ENDFOR
+
+ return min_q;
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_frameinfo.h"
+#include "q_normalize.h"
+#include "aac_mem_funcs.h" /* For pv_memset */
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Int q_normalize(
+ Int qFormat[],
+ const FrameInfo *pFrameInfo,
+ Int32 abs_max_per_window[],
+ Int32 coef[])
+{
+ Int sfb;
+ Int nsfb;
+ Int win;
+ Int nwin;
+ Int sfbWidth;
+
+ Int shift_amt;
+
+ /* Initialize min_q to a very large value */
+ Int min_q = 1000;
+
+ Int stop_idx = 0;
+
+ const Int *pSfbPerWin;
+ const Int16 *pWinSfbTop;
+
+ Int *pQformat;
+ Int32 *pCoef;
+
+ nwin = pFrameInfo->num_win;
+
+ /* Find the minimum q format */
+ pQformat = &(qFormat[0]);
+ pSfbPerWin = &(pFrameInfo->sfb_per_win[0]);
+
+ for (win = nwin; win != 0; win--)
+ {
+
+ nsfb = *(pSfbPerWin++);
+
+ if (nsfb < 0 || nsfb > MAXBANDS)
+ {
+ break; /* avoid any processing on error condition */
+ }
+
+ for (sfb = nsfb; sfb != 0; sfb--)
+ {
+ Int qformat = *(pQformat++);
+ if (qformat < min_q)
+ {
+ min_q = qformat;
+ }
+ }
+
+ } /* for(win) */
+
+ /* Normalize the coefs in each scalefactor band to one q-format */
+ pQformat = &(qFormat[0]);
+ pSfbPerWin = &(pFrameInfo->sfb_per_win[0]);
+ pCoef = &(coef[0]);
+
+ for (win = 0; win < nwin; win++)
+ {
+
+ Int32 max = 0;
+ stop_idx = 0;
+
+ nsfb = *(pSfbPerWin++);
+
+ if (nsfb < 0 || nsfb > MAXBANDS)
+ {
+ break; /* avoid any processing on error condition */
+ }
+
+ pWinSfbTop = &(pFrameInfo->win_sfb_top[win][0]);
+
+ for (sfb = nsfb; sfb != 0; sfb--)
+ {
+ Int tmp1, tmp2;
+ tmp1 = *(pWinSfbTop++);
+ tmp2 = *(pQformat++);
+ sfbWidth = tmp1 - stop_idx;
+
+ if (sfbWidth < 2)
+ {
+ break; /* will lead to error condition */
+ }
+
+ stop_idx += sfbWidth;
+
+ shift_amt = tmp2 - min_q;
+
+ if (shift_amt == 0)
+ {
+ Int32 tmp1, tmp2;
+ tmp1 = *(pCoef++);
+ tmp2 = *(pCoef++);
+ /*
+ * sfbWidth is always an even number
+ * (check tables in pg.66 IS0 14496-3)
+ */
+ for (Int i = (sfbWidth >> 1) - 1; i != 0; i--)
+ {
+ max |= (tmp1 >> 31) ^ tmp1;
+ max |= (tmp2 >> 31) ^ tmp2;
+ tmp1 = *(pCoef++);
+ tmp2 = *(pCoef++);
+ }
+ max |= (tmp1 >> 31) ^ tmp1;
+ max |= (tmp2 >> 31) ^ tmp2;
+
+ }
+ else
+ {
+ if (shift_amt < 31)
+ {
+ Int32 tmp1, tmp2;
+ tmp1 = *(pCoef++) >> shift_amt;
+ tmp2 = *(pCoef--) >> shift_amt;
+ /*
+ * sfbWidth is always an even number
+ * (check tables in pg.66 IS0 14496-3)
+ */
+ for (Int i = (sfbWidth >> 1) - 1; i != 0; i--)
+ {
+ *(pCoef++) = tmp1;
+ *(pCoef++) = tmp2;
+
+ max |= (tmp1 >> 31) ^ tmp1;
+ max |= (tmp2 >> 31) ^ tmp2;
+ tmp1 = *(pCoef++) >> shift_amt;
+ tmp2 = *(pCoef--) >> shift_amt;
+
+ }
+ *(pCoef++) = tmp1;
+ *(pCoef++) = tmp2;
+ max |= (tmp1 >> 31) ^ tmp1;
+ max |= (tmp2 >> 31) ^ tmp2;
+
+ }
+ else
+ {
+ pv_memset(pCoef, 0, sizeof(Int32)*sfbWidth);
+ pCoef += sfbWidth;
+ }
+ }
+
+ abs_max_per_window[win] = max;
+
+ }
+
+ } /* for (win) */
+
+ return min_q;
+
+} /* normalize() */
diff --git a/media/libstagefright/codecs/aacdec/q_normalize.h b/media/libstagefright/codecs/aacdec/q_normalize.h
new file mode 100644
index 0000000..63a9d53
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/q_normalize.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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: q_normalize.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ (1) Added PV Copyright notice.
+ (2) Removed embedded TABS
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes the function definition for q_normalize.h
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef Q_NORMALIZE_H
+#define Q_NORMALIZE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_frameinfo.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ Int q_normalize(
+ Int qFormat[],
+ const FrameInfo *pFrameInfo,
+ Int32 abs_max_per_window[],
+ Int32 coef[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/qmf_filterbank_coeff.cpp b/media/libstagefright/codecs/aacdec/qmf_filterbank_coeff.cpp
new file mode 100644
index 0000000..1164129
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/qmf_filterbank_coeff.cpp
@@ -0,0 +1,319 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: qmf_filterbank_coeff.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ Local Stores/Buffers/Pointers Needed:
+
+ Global Stores/Buffers/Pointers Needed:
+
+ Outputs:
+
+ Pointers and Buffers Modified:
+
+
+ Local Stores Modified:
+
+ Global Stores Modified:
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function defines the scalefactor bands for all sampling rates
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "qmf_filterbank_coeff.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+
+const Int32 sbrDecoderFilterbankCoefficients[155] =
+{
+ /* 10/9*table */
+
+ 0xFFEA0066, 0x020C09CF, 0x34F67965, 0xCE380A2F, 0xFE43005A,
+ 0xFFEA006C, 0x02360998, 0x36907954, 0xCFCD0A57, 0xFE690054,
+ 0xFFEC0072, 0x0262095B, 0x382B7937, 0xD1600A7A, 0xFE8E004F,
+ 0xFFED0078, 0x028E0919, 0x39C6790F, 0xD2F00A98, 0xFEB20049,
+ 0xFFED007E, 0x02BB08D0, 0x3B6378DB, 0xD47D0AB1, 0xFED50043,
+ 0xFFEC0084, 0x02E90882, 0x3D00789B, 0xD6080AC6, 0xFEF6003E,
+ 0xFFEB0089, 0x0318082F, 0x3E9D7851, 0xD78F0AD6, 0xFF160039,
+ 0xFFEB008F, 0x034807D5, 0x403A77FB, 0xD9130AE2, 0xFF350033,
+ 0xFFEA0095, 0x03790775, 0x41D7779A, 0xDA930AEA, 0xFF53002E,
+ 0xFFE9009A, 0x03AB070E, 0x4373772D, 0xDC100AED, 0xFF6F0029,
+ 0xFFE800A0, 0x03DE06A2, 0x450D76B6, 0xDD890AED, 0xFF8A0024,
+ 0xFFE800A5, 0x0412062F, 0x46A77633, 0xDEFD0AE9, 0xFFA40020,
+ 0xFFE700AA, 0x044705B6, 0x483F75A6, 0xE06D0AE2, 0xFFBD001C,
+ 0xFFE600AF, 0x047B0537, 0x49D5750E, 0xE1D90AD7, 0xFFD40017,
+ 0xFFE500B3, 0x04B104B0, 0x4B69746B, 0xE3400AC8, 0xFFEB0013,
+ 0xFFE400B8, 0x04E70423, 0x4CFA73BE, 0xE4A20AB7, 0x0002000F,
+ 0xFFE400BC, 0x051E0390, 0x4E897306, 0xE5FF0AA2, 0x0016000B,
+ 0xFFE300BF, 0x055502F6, 0x50157244, 0xE7560A8A, 0x00280008,
+ 0xFFE300C3, 0x058D0254, 0x519D7178, 0xE8A80A6F, 0x003A0004,
+ 0xFFE300C6, 0x05C401AD, 0x532270A2, 0xE9F50A53, 0x004A0001,
+ 0xFFE200C8, 0x05FC00FE, 0x54A36FC3, 0xEB3C0A33, 0x005AFFFC,
+ 0xFFE200CA, 0x06340048, 0x56206EDA, 0xEC7D0A11, 0x0068FFF9,
+ 0xFFE200CC, 0x066CFF8A, 0x57986DE8, 0xEDB809EC, 0x0075FFF7,
+ 0xFFE200CD, 0x06A4FEC6, 0x590C6CEC, 0xEEED09C6, 0x0081FFF4,
+ 0xFFE200CE, 0x06DCFDFC, 0x5A7B6BE7, 0xF01C099E, 0x008DFFF2,
+ 0xFFE200CE, 0x0713FD2B, 0x5BE56ADA, 0xF1450973, 0x0097FFF0,
+ 0xFFE300CD, 0x074BFC52, 0x5D4869C4, 0xF2680947, 0x00A0FFEE,
+ 0xFFE300CC, 0x0781FB73, 0x5EA668A6, 0xF384091A, 0x00A8FFEC,
+ 0xFFE400CA, 0x07B7FA8D, 0x5FFF6780, 0xF49908EB, 0x00B0FFEA,
+ 0xFFE400C8, 0x07EDF9A0, 0x61506652, 0xF5A808BA, 0x00B6FFE9,
+ 0xFFE500C5, 0x0822F8AC, 0x629B651C, 0xF6B00888, 0x00BCFFE7
+};
+
+
+const Int32 sbrDecoderFilterbankCoefficients_down_smpl[160] =
+{
+ 0x0000FFEE, 0xFFF0FFEF, 0xFFEEFFED, 0xFFEBFFEA,
+ 0xFFE9FFE8, 0xFFE7FFE6, 0xFFE6FFE7, 0xFFE7FFE8,
+ 0xFFEAFFED, 0xFFEFFFF3, 0xFFF7FFFB, 0x00000007,
+ 0x000D0014, 0x001C0025, 0x002E0037, 0x0041004B,
+ 0x00560061, 0x006B0076, 0x0080008A, 0x0094009D,
+ 0x00A500AC, 0x00B200B6, 0x00B800B9, 0x00B700B3,
+ 0x00AD00A3, 0x00970087, 0x0074005D, 0x00420024,
+ 0x0001FFDA, 0xFFAFFF7F, 0xFF4BFF12, 0xFED5FE93,
+ 0x01B301FD, 0x024C029E, 0x02F4034D, 0x03A90408,
+ 0x046904CC, 0x05300595, 0x05FA065E, 0x06C10722,
+ 0x078007DA, 0x08300881, 0x08CB090F, 0x094A097C,
+ 0x09A409C1, 0x09D209D5, 0x09CB09B2, 0x0988094D,
+ 0x090108A2, 0x082F07A8, 0x070C0659, 0x059104B1,
+ 0x03B902AA, 0x01810041, 0xFEE7FD74, 0xFBE9FA45,
+ 0xF887F6B2, 0xF4C4F2BF, 0xF0A4EE72, 0xEC2AE9CF,
+ 0xE760E4DE, 0xE24CDFA9, 0xDCF9DA3B, 0xD772D4A0,
+ 0x2E3A311B, 0x33FF36E7, 0x39CE3CB4, 0x3F964273,
+ 0x45484813, 0x4AD24D84, 0x502552B4, 0x55305795,
+ 0x59E35C17, 0x5E2F602B, 0x620863C4, 0x655F66D7,
+ 0x682B6959, 0x6A626B43, 0x6BFC6C8C, 0x6CF46D32,
+ 0x6D476D32, 0x6CF46C8C, 0x6BFC6B43, 0x6A626959,
+ 0x682B66D7, 0x655F63C4, 0x6208602B, 0x5E2F5C17,
+ 0x59E35795, 0x553052B4, 0x50254D84, 0x4AD24813,
+ 0x45484273, 0x3F963CB4, 0x39CE36E7, 0x33FF311B,
+ 0xD1C6D4A0, 0xD772DA3B, 0xDCF9DFA9, 0xE24CE4DE,
+ 0xE760E9CF, 0xEC2AEE72, 0xF0A4F2BF, 0xF4C4F6B2,
+ 0xF887FA45, 0xFBE9FD74, 0xFEE70041, 0x018102AA,
+ 0x03B904B1, 0x05910659, 0x070C07A8, 0x082F08A2,
+ 0x0901094D, 0x098809B2, 0x09CB09D5, 0x09D209C1,
+ 0x09A4097C, 0x094A090F, 0x08CB0881, 0x083007DA,
+ 0x07800722, 0x06C1065E, 0x05FA0595, 0x053004CC,
+ 0x04690408, 0x03A9034D, 0x02F4029E, 0x024C01FD,
+ 0xFE4DFE93, 0xFED5FF12, 0xFF4BFF7F, 0xFFAFFFDA,
+ 0x00010024, 0x0042005D, 0x00740087, 0x009700A3,
+ 0x00AD00B3, 0x00B700B9, 0x00B800B6, 0x00B200AC,
+ 0x00A5009D, 0x0094008A, 0x00800076, 0x006B0061,
+ 0x0056004B, 0x00410037, 0x002E0025, 0x001C0014,
+ 0x000D0007, 0x0000FFFB, 0xFFF7FFF3, 0xFFEFFFED,
+ 0xFFEAFFE8, 0xFFE7FFE7, 0xFFE6FFE6, 0xFFE7FFE8,
+ 0xFFE9FFEA, 0xFFEBFFED, 0xFFEEFFEF, 0xFFF0FFEE
+};
+
+const Int32 sbrDecoderFilterbankCoefficients_an_filt_LC[155] =
+{
+
+ Qfmt27(-0.00079446133872F), Qfmt27(0.02197766364781F), Qfmt27(0.54254182141522F), Qfmt27(-0.47923775873194F),
+ Qfmt27(-0.01574239605130F), Qfmt27(-0.00068946163857F), Qfmt27(0.02537571195384F), Qfmt27(0.57449847577240F),
+ Qfmt27(-0.44806230039026F), Qfmt27(-0.01291535202742F), Qfmt27(-0.00071286404460F), Qfmt27(0.02892516313544F),
+ Qfmt27(0.60657315615086F), Qfmt27(-0.41729436041451F), Qfmt27(-0.01026942774868F), Qfmt27(-0.00077308974337F),
+ Qfmt27(0.03262310249845F), Qfmt27(0.63865835544980F), Qfmt27(-0.38701849746199F), Qfmt27(-0.00782586328859F),
+ Qfmt27(-0.00083027488297F), Qfmt27(0.03646915244785F), Qfmt27(0.67068416485018F), Qfmt27(-0.35729827194706F),
+ Qfmt27(-0.00557215982767F), Qfmt27(-0.00089272089703F), Qfmt27(0.04045671426315F), Qfmt27(0.70254003810627F),
+ Qfmt27(-0.32819525024294F), Qfmt27(-0.00351102841332F), Qfmt27(-0.00095851011196F), Qfmt27(0.04455021764484F),
+ Qfmt27(0.73415149000395F), Qfmt27(-0.29977591877185F), Qfmt27(-0.00163598204794F), Qfmt27(-0.00101225729839F),
+ Qfmt27(0.04873676213679F), Qfmt27(0.76545064960593F), Qfmt27(-0.27208998714049F), Qfmt27(0.00003903936539F),
+ Qfmt27(-0.00105230782648F), Qfmt27(0.05300654158217F), Qfmt27(0.79631383686511F), Qfmt27(-0.24519750285673F),
+ Qfmt27(0.00154182229475F), Qfmt27(-0.00108630976316F), Qfmt27(0.05732502937107F), Qfmt27(0.82666485395476F),
+ Qfmt27(-0.21914753347432F), Qfmt27(0.00286720203220F), Qfmt27(-0.00110794157381F), Qfmt27(0.06167350555855F),
+ Qfmt27(0.85641712130638F), Qfmt27(-0.19396671004887F), Qfmt27(0.00402297937976F), Qfmt27(-0.00110360418081F),
+ Qfmt27(0.06602157445253F), Qfmt27(0.88547343436495F), Qfmt27(-0.16971665552213F), Qfmt27(0.00500649278750F),
+ Qfmt27(-0.00109714405326F), Qfmt27(0.07034096875232F), Qfmt27(0.91376152398903F), Qfmt27(-0.14641770628514F),
+ Qfmt27(0.00583386287581F), Qfmt27(-0.00106490281247F), Qfmt27(0.07461825625751F), Qfmt27(0.94117890777861F),
+ Qfmt27(-0.12410396326951F), Qfmt27(0.00651097277313F), Qfmt27(-0.00102041023958F), Qfmt27(0.07879625324269F),
+ Qfmt27(0.96765488212662F), Qfmt27(-0.10280530739363F), Qfmt27(0.00704839655425F), Qfmt27(-0.00094051141595F),
+ Qfmt27(0.08286099010631F), Qfmt27(0.99311573680798F), Qfmt27(-0.08254839941155F), Qfmt27(0.00745513427428F),
+ Qfmt27(-0.00084090835475F), Qfmt27(0.08675566213219F), Qfmt27(1.01745066253324F), Qfmt27(-0.06332944781672F),
+ Qfmt27(0.00774335382672F), Qfmt27(-0.00072769348801F), Qfmt27(0.09046949018457F), Qfmt27(1.04060828658052F),
+ Qfmt27(-0.04518854556363F), Qfmt27(0.00790787636150F), Qfmt27(-0.00057913742435F), Qfmt27(0.09395575430420F),
+ Qfmt27(1.06251808919053F), Qfmt27(-0.02811939233087F), Qfmt27(0.00797463714114F), Qfmt27(-0.00040969484059F),
+ Qfmt27(0.09716267023308F), Qfmt27(1.08310018709600F), Qfmt27(-0.01212147193047F), Qfmt27(0.00795079915733F),
+ Qfmt27(-0.00020454902123F), Qfmt27(0.10007381188066F), Qfmt27(1.10227871198194F), Qfmt27(0.00279527795884F),
+ Qfmt27(0.00784545014643F), Qfmt27(0.00001908481202F), Qfmt27(0.10262701466139F), Qfmt27(1.12001978353403F),
+ Qfmt27(0.01663452156443F), Qfmt27(0.00766458213130F), Qfmt27(0.00028892665922F), Qfmt27(0.10479373974558F),
+ Qfmt27(1.13624787143434F), Qfmt27(0.02941522773279F), Qfmt27(0.00741912981120F), Qfmt27(0.00056943874774F),
+ Qfmt27(0.10650970405576F), Qfmt27(1.15091404672203F), Qfmt27(0.04112872592057F), Qfmt27(0.00712664923329F),
+ Qfmt27(0.00088238158168F), Qfmt27(0.10776200996423F), Qfmt27(1.16395714324633F), Qfmt27(0.05181934748033F),
+ Qfmt27(0.00677868764313F), Qfmt27(0.00121741725989F), Qfmt27(0.10848340171661F), Qfmt27(1.17535833075364F),
+ Qfmt27(0.06148559051724F), Qfmt27(0.00639363830229F), Qfmt27(0.00159101288509F), Qfmt27(0.10864412991640F),
+ Qfmt27(1.18507099110810F), Qfmt27(0.07014197759039F), Qfmt27(0.00597707038378F), Qfmt27(0.00196610899088F),
+ Qfmt27(0.10819451041273F), Qfmt27(1.19306425909871F), Qfmt27(0.07784680399703F), Qfmt27(0.00554476792518F),
+ Qfmt27(0.00238550675072F), Qfmt27(0.10709920766553F), Qfmt27(1.19929775892826F), Qfmt27(0.08459352758522F),
+ Qfmt27(0.00509233837916F), Qfmt27(0.00280596092809F), Qfmt27(0.10531144797543F), Qfmt27(1.20377455661175F),
+ Qfmt27(0.09043115226911F), Qfmt27(0.00463008004888F), Qfmt27(0.00325513071185F), Qfmt27(0.10278145526768F),
+ Qfmt27(1.20646855283790F), Qfmt27(0.09539224314440F), Qfmt27(0.00416760958657F)
+};
+
+
+
+#ifdef HQ_SBR
+
+
+const Int32 sbrDecoderFilterbankCoefficients_an_filt[155] =
+{
+ Qfmt27(-0.000561769F), Qfmt27(+ 0.015540555F), Qfmt27(+ 0.383635001F), Qfmt27(-0.338872269F), Qfmt27(-0.011131555F),
+ Qfmt27(-0.000487523F), Qfmt27(+ 0.017943338F), Qfmt27(+ 0.406231768F), Qfmt27(-0.316827891F), Qfmt27(-0.009132533F),
+ Qfmt27(-0.000504071F), Qfmt27(+ 0.020453179F), Qfmt27(+ 0.428911992F), Qfmt27(-0.295071672F), Qfmt27(-0.007261582F),
+ Qfmt27(-0.000546657F), Qfmt27(+ 0.023068017F), Qfmt27(+ 0.451599654F), Qfmt27(-0.273663404F), Qfmt27(-0.005533721F),
+ Qfmt27(-0.000587093F), Qfmt27(+ 0.025787585F), Qfmt27(+ 0.474245321F), Qfmt27(-0.252648031F), Qfmt27(-0.003940112F),
+ Qfmt27(-0.000631249F), Qfmt27(+ 0.028607217F), Qfmt27(+ 0.496770825F), Qfmt27(-0.232069087F), Qfmt27(-0.002482672F),
+ Qfmt27(-0.000677769F), Qfmt27(+ 0.031501761F), Qfmt27(+ 0.519123497F), Qfmt27(-0.211973585F), Qfmt27(-0.001156814F),
+ Qfmt27(-0.000715774F), Qfmt27(+ 0.034462095F), Qfmt27(+ 0.541255345F), Qfmt27(-0.192396675F), Qfmt27(+ 0.000027605F),
+ Qfmt27(-0.000744094F), Qfmt27(+ 0.037481285F), Qfmt27(+ 0.563078914F), Qfmt27(-0.173380817F), Qfmt27(+ 0.001090233F),
+ Qfmt27(-0.000768137F), Qfmt27(+ 0.040534917F), Qfmt27(+ 0.584540324F), Qfmt27(-0.154960707F), Qfmt27(+ 0.002027418F),
+ Qfmt27(-0.000783433F), Qfmt27(+ 0.043609754F), Qfmt27(+ 0.605578354F), Qfmt27(-0.137155176F), Qfmt27(+ 0.002844676F),
+ Qfmt27(-0.000780366F), Qfmt27(+ 0.046684303F), Qfmt27(+ 0.626124270F), Qfmt27(-0.120007798F), Qfmt27(+ 0.003540125F),
+ Qfmt27(-0.000775798F), Qfmt27(+ 0.049738576F), Qfmt27(+ 0.646126970F), Qfmt27(-0.103532953F), Qfmt27(+ 0.004125164F),
+ Qfmt27(-0.000753000F), Qfmt27(+ 0.052763075F), Qfmt27(+ 0.665513988F), Qfmt27(-0.087754754F), Qfmt27(+ 0.004603953F),
+ Qfmt27(-0.000721539F), Qfmt27(+ 0.055717365F), Qfmt27(+ 0.684235329F), Qfmt27(-0.072694330F), Qfmt27(+ 0.004983969F),
+ Qfmt27(-0.000665042F), Qfmt27(+ 0.058591568F), Qfmt27(+ 0.702238872F), Qfmt27(-0.058370533F), Qfmt27(+ 0.005271576F),
+ Qfmt27(-0.000594612F), Qfmt27(+ 0.061345517F), Qfmt27(+ 0.719446263F), Qfmt27(-0.044780682F), Qfmt27(+ 0.005475378F),
+ Qfmt27(-0.000514557F), Qfmt27(+ 0.063971590F), Qfmt27(+ 0.735821176F), Qfmt27(-0.031953127F), Qfmt27(+ 0.005591713F),
+ Qfmt27(-0.000409512F), Qfmt27(+ 0.066436751F), Qfmt27(+ 0.751313746F), Qfmt27(-0.019883413F), Qfmt27(+ 0.005638920F),
+ Qfmt27(-0.000289698F), Qfmt27(+ 0.068704383F), Qfmt27(+ 0.765867487F), Qfmt27(-0.008571175F), Qfmt27(+ 0.005622064F),
+ Qfmt27(-0.000144638F), Qfmt27(+ 0.070762871F), Qfmt27(+ 0.779428752F), Qfmt27(+ 0.001976560F), Qfmt27(+ 0.005547571F),
+ Qfmt27(+ 0.000013495F), Qfmt27(+ 0.072568258F), Qfmt27(+ 0.791973584F), Qfmt27(+ 0.011762383F), Qfmt27(+ 0.005419678F),
+ Qfmt27(+ 0.000204302F), Qfmt27(+ 0.074100364F), Qfmt27(+ 0.803448575F), Qfmt27(+ 0.020799707F), Qfmt27(+ 0.005246117F),
+ Qfmt27(+ 0.000402654F), Qfmt27(+ 0.075313734F), Qfmt27(+ 0.813819127F), Qfmt27(+ 0.029082401F), Qfmt27(+ 0.005039302F),
+ Qfmt27(+ 0.000623938F), Qfmt27(+ 0.076199248F), Qfmt27(+ 0.823041989F), Qfmt27(+ 0.036641812F), Qfmt27(+ 0.004793256F),
+ Qfmt27(+ 0.000860844F), Qfmt27(+ 0.076709349F), Qfmt27(+ 0.831103846F), Qfmt27(+ 0.043476878F), Qfmt27(+ 0.004520985F),
+ Qfmt27(+ 0.001125016F), Qfmt27(+ 0.076823001F), Qfmt27(+ 0.837971734F), Qfmt27(+ 0.049597868F), Qfmt27(+ 0.004226427F),
+ Qfmt27(+ 0.001390249F), Qfmt27(+ 0.076505072F), Qfmt27(+ 0.843623828F), Qfmt27(+ 0.055046003F), Qfmt27(+ 0.003920743F),
+ Qfmt27(+ 0.001686808F), Qfmt27(+ 0.075730576F), Qfmt27(+ 0.848031578F), Qfmt27(+ 0.059816657F), Qfmt27(+ 0.003600827F),
+ Qfmt27(+ 0.001984114F), Qfmt27(+ 0.074466439F), Qfmt27(+ 0.851197152F), Qfmt27(+ 0.063944481F), Qfmt27(+ 0.003273961F),
+ Qfmt27(+ 0.002301725F), Qfmt27(+ 0.072677464F), Qfmt27(+ 0.853102095F), Qfmt27(+ 0.067452502F), Qfmt27(+ 0.002946945F)
+};
+
+
+
+#endif /* HQ_SBR */
+
+
+#endif /* AAC_PLUS */
diff --git a/media/libstagefright/codecs/aacdec/qmf_filterbank_coeff.h b/media/libstagefright/codecs/aacdec/qmf_filterbank_coeff.h
new file mode 100644
index 0000000..c8968cb
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/qmf_filterbank_coeff.h
@@ -0,0 +1,99 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: qmf_filterbank_coeff.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ this file declares the scalefactor bands for all sampling rates
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef QMF_FILTERBANK_COEFF_H
+#define QMF_FILTERBANK_COEFF_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+#define Qfmt(x) (Int16)(x*(((Int32)1<<15)*1.11111111111111111F) + (x>=0?0.5F:-0.5F))
+
+
+#define Qfmt30(x) (Int32)(x*((Int32)1<<30) + (x>=0?0.5F:-0.5F))
+#define Qfmt27(x) (Int32)(x*(((Int32)1<<27)) + (x>=0?0.5F:-0.5F))
+
+extern const Int32 sbrDecoderFilterbankCoefficients[155];
+
+
+extern const Int32 sbrDecoderFilterbankCoefficients_down_smpl[160];
+extern const Int32 sbrDecoderFilterbankCoefficients_an_filt_LC[155];
+
+#ifdef HQ_SBR
+extern const Int32 sbrDecoderFilterbankCoefficients_an_filt[155];
+#endif
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/s_adif_header.h b/media/libstagefright/codecs/aacdec/s_adif_header.h
new file mode 100644
index 0000000..7fd49d3
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_adif_header.h
@@ -0,0 +1,98 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_ADIF_Header.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, ADIF_Header
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_ADIF_HEADER_H
+#define S_ADIF_HEADER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_adif_const.h"
+#include "e_rawbitstreamconst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+typedef struct
+{
+ Char adif_id[LEN_ADIF_ID+1];
+ Int copy_id_present;
+ Char copy_id[LEN_COPYRT_ID+1];
+ Int original_copy;
+ Int home;
+ Int bitstream_type;
+ Int32 bitrate;
+ Int num_pce;
+ Int prog_tags[(1<<LEN_TAG)];
+} ADIF_Header;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/s_bit_buffer.h b/media/libstagefright/codecs/aacdec/s_bit_buffer.h
new file mode 100644
index 0000000..9f0dbda
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_bit_buffer.h
@@ -0,0 +1,93 @@
+/* ------------------------------------------------------------------
+ * 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: s_bit_buffer.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_BIT_BUFFER_H
+#define S_BIT_BUFFER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ UChar *char_ptr;
+ UInt32 buffered_bits;
+ UInt32 buffer_word;
+ UInt32 nrBitsRead;
+ UInt32 bufferLen;
+}
+BIT_BUFFER;
+
+typedef BIT_BUFFER *HANDLE_BIT_BUFFER;
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/s_bits.h b/media/libstagefright/codecs/aacdec/s_bits.h
new file mode 100644
index 0000000..cae69ad
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_bits.h
@@ -0,0 +1,112 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_BITS.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Remove unused field.
+
+ Description: Change buffer type from UInt to UInt32, makes API much easier
+ to understand and describe, and getbits is faster on TI C55X
+ if the buffer is 32 bits instead of 16.
+
+ Description: Change buffer type from UInt32 to UChar.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, BITS
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_BITS_H
+#define S_BITS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+/*
+ * Name: BITS
+ * Description: Holds information for processing the input data buffer
+ * as a "stream". The data is in packed format.
+ * Fields:
+ * pBuffer - pointer to the beginning of the buffer. If the data type of
+ * this changes, make sure to update the constants in ibstream.h
+ * usedBits - number of bits read thus far from the buffer. Bit 0 is
+ * the LSB of pBuffer[0].
+ * availableBits - number of bits available in the buffer.
+ * byteAlignOffset - used with ADTS in case sync word is not aligned
+ on a boundary.
+ */
+typedef struct
+{
+ UChar *pBuffer;
+ UInt usedBits; /* Keep this unsigned so can go to 65536 */
+ UInt availableBits; /* Ditto */
+ UInt inputBufferCurrentLength; /* Ditto */
+ Int byteAlignOffset; /* Used in ADTS. See find_adts_syncword() */
+} BITS;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/s_ch_info.h b/media/libstagefright/codecs/aacdec/s_ch_info.h
new file mode 100644
index 0000000..9fd259c
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_ch_info.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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_Ch_Info.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, Ch_Info
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_CH_INFO_H
+#define S_CH_INFO_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+typedef struct
+{
+// Int present; /* channel present */
+ Int tag; /* element tag */
+ Int cpe; /* 0 if single channel, 1 if channel pair */
+// Int common_window; /* 1 if common window for cpe */
+// Int ch_is_left; /* 1 if left channel of cpe */
+// Int paired_ch; /* index of paired channel in cpe */
+// Int widx; /* window element index for this channel */
+ Int is_present; /* intensity stereo is used */
+ Int ncch; /* number of coupling channels for this ch */
+ /* #if (CChans > 0) */
+ /* int cch[CChans];*/ /* coupling channel idx */
+ /* int cc_dom[CChans];*/ /* coupling channel domain */
+ /* int cc_ind[CChans];*/ /* independently switched coupling channel flag */
+ /* #endif */
+ Char *fext; /* filename extension */
+
+} Ch_Info;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/s_crc_buffer.h b/media/libstagefright/codecs/aacdec/s_crc_buffer.h
new file mode 100644
index 0000000..69250e7
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_crc_buffer.h
@@ -0,0 +1,90 @@
+/* ------------------------------------------------------------------
+ * 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: s_crc_buffer.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_CRC_BUFFER_H
+#define S_CRC_BUFFER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ unsigned short crcState;
+ unsigned short crcMask;
+ unsigned short crcPoly;
+}
+CRC_BUFFER;
+
+typedef CRC_BUFFER *HANDLE_CRC;
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/s_elelist.h b/media/libstagefright/codecs/aacdec/s_elelist.h
new file mode 100644
index 0000000..40b2f13
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_elelist.h
@@ -0,0 +1,90 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_EleList.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, EleList
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_ELELIST_H
+#define S_ELELIST_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_rawbitstreamconst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+typedef struct
+{
+ Int num_ele;
+ Int ele_is_cpe[(1<<LEN_TAG)];
+ Int ele_tag[(1<<LEN_TAG)];
+} EleList;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/s_frameinfo.h b/media/libstagefright/codecs/aacdec/s_frameinfo.h
new file mode 100644
index 0000000..871ae83
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_frameinfo.h
@@ -0,0 +1,127 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_frameinfo.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed name of bk_sfb_top to frame_sfb_top.
+ Included "interface.h" for defintion of MAX_WIN. This
+ will hopefully be simplified when interface.h is broken up into smaller
+ include files.
+
+ Description: Eliminated the never used array, group_offs[8]
+
+ Description:
+ (1) Modified to include the lines...
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ (2) Updated the copyright header.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, FrameInfo
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_FRAMEINFO_H
+#define S_FRAMEINFO_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_blockswitching.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Int islong; /* true if long block */
+ Int num_win; /* sub-blocks (SB) per block */
+ Int coef_per_frame; /* coef's per block */
+ Int sfb_per_frame; /* sfb per block */
+ Int coef_per_win[MAX_WIN]; /* coef's per SB */
+ Int sfb_per_win[MAX_WIN]; /* sfb per SB */
+ Int sectbits[MAX_WIN];
+ Int16 *win_sfb_top[MAX_WIN]; /* top coef per sfb per SB */
+ Int *sfb_width_128; /* sfb width for short blocks */
+
+ Int frame_sfb_top[MAXBANDS]; /* Only used in calc_gsfb_table() -
+ it is simply a cum version of
+ the above information */
+ Int num_groups;
+ Int group_len[8];
+
+ } FrameInfo;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* S_FRAMEINFO_H */
diff --git a/media/libstagefright/codecs/aacdec/s_hcb.h b/media/libstagefright/codecs/aacdec/s_hcb.h
new file mode 100644
index 0000000..6a64c27
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_hcb.h
@@ -0,0 +1,123 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_Hcb.h
+
+ Date: 05/07/2001
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ (1) Modified to include the lines...
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ (2) Updated the copyright header.
+
+ Description:
+ (1) LAV removed from structure definition, since it was never used.
+
+ Description: Huffman tables are stored as UInt16
+
+ Description: Modified the declaration of the structure so no pointers are
+ used in the structure.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ define the structure Hcb to store Huffman codebook information,
+ this structure was originally defined in all.h
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_HCB_H
+#define S_HCB_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_huffman.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Int n;
+ Int dim;
+ Int mod;
+ Int off;
+ Int signed_cb;
+ } Hcb;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* S_HCB_H */
+
diff --git a/media/libstagefright/codecs/aacdec/s_huffman.h b/media/libstagefright/codecs/aacdec/s_huffman.h
new file mode 100644
index 0000000..2db3dd9
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_huffman.h
@@ -0,0 +1,91 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_Huffman.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed "ulong" to "UInt32"
+
+ Description: add helper structure to speed up decode_huff_cw
+
+ Description: Remove the structure definition of Huffman
+
+ Description: Added definition for SBR Huffman, used for AAC plus
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, Huffman
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_HUFFMAN_H
+#define S_HUFFMAN_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+typedef const Char(*SbrHuffman)[2];
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/s_hybrid.h b/media/libstagefright/codecs/aacdec/s_hybrid.h
new file mode 100644
index 0000000..3880d30
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_hybrid.h
@@ -0,0 +1,100 @@
+/* ------------------------------------------------------------------
+ * 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: s_hybrid.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_HYBRID_H
+#define S_HYBRID_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "ps_constants.h"
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define HYBRID_FILTER_LENGTH 13
+#define HYBRID_FILTER_LENGTH_m_1 12
+#define HYBRID_FILTER_DELAY 6
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef enum
+{
+
+ HYBRID_2_REAL = 2,
+ HYBRID_4_CPLX = 4,
+ HYBRID_8_CPLX = 8
+
+} HYBRID_RES;
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ Int32 nQmfBands;
+ Int32 *pResolution;
+ Int32 qmfBufferMove;
+
+ Int32 **mQmfBufferReal;
+ Int32 **mQmfBufferImag;
+ Int32 *mTempReal;
+ Int32 *mTempImag;
+
+
+} HYBRID;
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+#endif /* S_HYBRID_H */
diff --git a/media/libstagefright/codecs/aacdec/s_lt_pred_status.h b/media/libstagefright/codecs/aacdec/s_lt_pred_status.h
new file mode 100644
index 0000000..4b5b56e
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_lt_pred_status.h
@@ -0,0 +1,174 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: LT_PRED_STATUS.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ (1) Merged in #defines from ltp_common.h, thereby eliminating that file.
+
+ Description:
+ (1) Modified to include the lines...
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ (2) Updated the copyright header.
+
+ Description: Moved large ltp_buffer up to s_tDec_Int_Chan.h, since this
+ move allowed for other elements in this structure to be shared with
+ the fxpCoef array.
+
+ Description: Decreased size of LTP buffers from 4096 to 3072. The upper 1024
+ elements in the LTP buffers were never touched in the code. This saves
+ 4 kilobytes in memory.
+
+ Description: Decreased size of LTP buffers again from 3072 to 2048. This
+ time, I realized that 1024 elements were duplicated in the 32-bit array
+ pVars->pChVars[]->time_quant. Rather than copy this data EVERY frame
+ from a 32-bit to a 16-bit LTP buffer, the data is accessed only
+ when it is needed. This saves both MIPS and memory.
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ define LT_PRED_STATUS structure for pulse data decoding.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_LT_PRED_STATUS_H
+#define S_LT_PRED_STATUS_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_blockswitching.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+ /*
+ Macro: MAX_SHORT_WINDOWS
+ Purpose: Number of short windows in one long window.
+ Explanation: - */
+#ifndef MAX_SHORT_WINDOWS
+#define MAX_SHORT_WINDOWS NSHORT
+#endif
+
+ /*
+ Macro: MAX_SCFAC_BANDS
+ Purpose: Maximum number of scalefactor bands in one frame.
+ Explanation: - */
+#ifndef MAX_SCFAC_BANDS
+#define MAX_SCFAC_BANDS MAXBANDS
+#endif
+
+ /*
+ Macro: BLOCK_LEN_LONG
+ Purpose: Length of one long window
+ Explanation: - */
+#ifndef BLOCK_LEN_LONG
+#define BLOCK_LEN_LONG LN2
+#endif
+
+
+ /*
+ Macro: LTP_MAX_BLOCK_LEN_LONG
+ Purpose: Informs the routine of the maximum block size used.
+ Explanation: This is needed since the TwinVQ long window
+ is different from the AAC long window. */
+#define LTP_MAX_BLOCK_LEN_LONG BLOCK_LEN_LONG //(2 * BLOCK_LEN_LONG)
+
+ /*
+ Macro: LT_BLEN
+ Purpose: Length of the history buffer.
+ Explanation: Has to hold 2 long windows of time domain data. */
+#ifndef LT_BLEN
+#define LT_BLEN (2 * LTP_MAX_BLOCK_LEN_LONG)
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ /*
+ Type: LT_PRED_STATUS
+ Purpose: Type of the struct holding the LTP encoding parameters.
+ Explanation: - */
+ typedef struct
+ {
+ Int weight_index;
+ Int win_prediction_used[MAX_SHORT_WINDOWS];
+ Int sfb_prediction_used[MAX_SCFAC_BANDS];
+ Bool ltp_data_present;
+
+ Int delay[MAX_SHORT_WINDOWS];
+ }
+ LT_PRED_STATUS;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* S_LT_PRED_STATUS_H */
+
+
diff --git a/media/libstagefright/codecs/aacdec/s_mc_info.h b/media/libstagefright/codecs/aacdec/s_mc_info.h
new file mode 100644
index 0000000..9006119
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_mc_info.h
@@ -0,0 +1,116 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_MC_Info.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: (1) use enum type for audioObjectType (2) update revision history
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, MC_Info
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_MC_INFO_H
+#define S_MC_INFO_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_rawbitstreamconst.h"
+#include "s_ch_info.h"
+#include "chans.h"
+#include "e_tmp4audioobjecttype.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+typedef struct
+{
+ Int nch; /* total number of audio channels */
+ Int nfsce; /* number of front SCE's pror to first front CPE */
+ Int nfch; /* number of front channels */
+ Int nsch; /* number of side channels */
+ Int nbch; /* number of back channels */
+ Int nlch; /* number of lfe channels */
+ Int ncch; /* number of valid coupling channels */
+ tMP4AudioObjectType audioObjectType; /* Should eventually be called object */
+ Int sampling_rate_idx;
+
+ Int implicit_channeling;
+ Int upsamplingFactor;
+#ifdef AAC_PLUS
+ bool bDownSampledSbr;
+ Int HE_AAC_level;
+#endif
+ /* All AAC content should be aware of these flag */
+ /* AAC+ content Flag */
+ Int sbrPresentFlag;
+ /* Enhanced AAC+ content Flag */
+ Int psPresentFlag;
+ tMP4AudioObjectType ExtendedAudioObjectType; /* Should eventually be called object */
+
+ Ch_Info ch_info[Chans];
+} MC_Info;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/s_mixdown.h b/media/libstagefright/codecs/aacdec/s_mixdown.h
new file mode 100644
index 0000000..7f456d5
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_mixdown.h
@@ -0,0 +1,88 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_MIXdown.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, MIXdown
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_MIXDOWN_H
+#define S_MIXDOWN_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ Int present;
+ Int ele_tag;
+ Int pseudo_enab;
+} MIXdown;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/s_patch.h b/media/libstagefright/codecs/aacdec/s_patch.h
new file mode 100644
index 0000000..554fc2d
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_patch.h
@@ -0,0 +1,121 @@
+/* ------------------------------------------------------------------
+ * 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: s_patch.h
+ Funtions:
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+ $Id: ct_envcalc.h,v 1.3 2002/11/29 16:11:49 kaehleof Exp $
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_PATCH_H
+#define S_PATCH_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define MAX_NUM_PATCHES 6
+
+#define SBR_NUM_COLUMNS 38
+#define SBR_NUM_BANDS 48
+#define SBR_NUM_BANDS_OVR_4 (SBR_NUM_BANDS>>2)
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+struct PATCH
+{
+ Int32 noOfPatches;
+ Int32 targetStartBand[MAX_NUM_PATCHES];
+};
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/s_progconfig.h b/media/libstagefright/codecs/aacdec/s_progconfig.h
new file mode 100644
index 0000000..e58e5fc
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_progconfig.h
@@ -0,0 +1,108 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_ProgConfig.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, ProgConfig
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_PROGCONFIG_H
+#define S_PROGCONFIG_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_mixdown.h"
+#include "s_elelist.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ Int profile;
+ Int sampling_rate_idx;
+ EleList front;
+ EleList side;
+ EleList back;
+ EleList lfe;
+ EleList data;
+ EleList coupling;
+ MIXdown mono_mix;
+ MIXdown stereo_mix;
+ MIXdown matrix_mix;
+
+ Char comments[(1<<LEN_PC_COMM)+1]; /* TO BE DELETED */
+
+ Int32 buffer_fullness; /* put this transport level info here */
+ Bool file_is_adts; /* For ADTS use only */
+ Int32 headerless_frames; /* For ADTS use only */
+ Int32 frame_length; /* For use by ADTS only */
+ Int32 CRC_absent; /* For use by ADTS only */
+ UInt32 CRC_check; /* For use by ADTS only */
+
+} ProgConfig;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/s_ps_dec.h b/media/libstagefright/codecs/aacdec/s_ps_dec.h
new file mode 100644
index 0000000..8b4391c
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_ps_dec.h
@@ -0,0 +1,154 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2003.
+
+*******************************************************************************/
+
+#ifndef S_PS_DEC_H
+#define S_PS_DEC_H
+
+
+#include "s_hybrid.h"
+#include "s_patch.h"
+
+/****************************************************************
+ Type definitions
+ ****************************************************************/
+struct PS_DEC
+{
+
+ Int psDetected;
+ Int32 *R_ch_qmf_filter_history;
+ Int32 invNoSubSamples;
+
+ Int32 bForceMono;
+ UInt32 noSubSamples;
+ Int32 usb;
+ Int32 lastUsb;
+
+ Int32 bPsDataAvail;
+
+ UInt32 bEnableIid;
+ UInt32 bEnableIcc;
+
+ UInt32 bEnableExt;
+ Int32 bFineIidQ;
+
+ Int32 aIidPrevFrameIndex[NO_HI_RES_BINS];
+ Int32 aIccPrevFrameIndex[NO_HI_RES_BINS];
+
+ UInt32 freqResIid;
+ UInt32 freqResIcc;
+
+ UInt32 bFrameClass;
+ UInt32 noEnv;
+ UInt32 aEnvStartStop[MAX_NO_PS_ENV+1];
+
+ UInt32 abIidDtFlag[MAX_NO_PS_ENV];
+ UInt32 abIccDtFlag[MAX_NO_PS_ENV];
+
+ Int32 delayBufIndex;
+
+ UInt32 aDelayRBufIndexSer[NO_SERIAL_ALLPASS_LINKS];
+
+ Int32 **aaaRealDelayRBufferSerQmf[NO_SERIAL_ALLPASS_LINKS];
+ Int32 **aaaImagDelayRBufferSerQmf[NO_SERIAL_ALLPASS_LINKS];
+
+ Int32 **aaaRealDelayRBufferSerSubQmf[NO_SERIAL_ALLPASS_LINKS];
+ Int32 **aaaImagDelayRBufferSerSubQmf[NO_SERIAL_ALLPASS_LINKS];
+
+ Int32 **aaRealDelayBufferQmf;
+ Int32 **aaImagDelayBufferQmf;
+ Int32 **aaRealDelayBufferSubQmf;
+ Int32 **aaImagDelayBufferSubQmf;
+
+ Int32 *aPeakDecayFast;
+ Int32 *aPrevNrg;
+ Int32 *aPrevPeakDiff;
+
+ Int32 *mHybridRealLeft;
+ Int32 *mHybridImagLeft;
+ Int32 *mHybridRealRight;
+ Int32 *mHybridImagRight;
+
+
+ HYBRID *hHybrid;
+
+
+
+ Int32 h11Prev[NO_IID_GROUPS];
+ Int32 h12Prev[NO_IID_GROUPS];
+ Int32 h21Prev[NO_IID_GROUPS];
+ Int32 h22Prev[NO_IID_GROUPS];
+
+ Int32 H11[NO_IID_GROUPS];
+ Int32 H12[NO_IID_GROUPS];
+ Int32 H21[NO_IID_GROUPS];
+ Int32 H22[NO_IID_GROUPS];
+
+ Int32 deltaH11[NO_IID_GROUPS];
+ Int32 deltaH12[NO_IID_GROUPS];
+ Int32 deltaH21[NO_IID_GROUPS];
+ Int32 deltaH22[NO_IID_GROUPS];
+
+ Int32(*qmfBufferReal)[64];
+ Int32(*qmfBufferImag)[64];
+
+ Int32 aDelayBufIndex[NO_DELAY_CHANNELS];
+ Int32 aNoSampleDelay[NO_DELAY_CHANNELS]; /////
+ Int32 aaIidIndex[MAX_NO_PS_ENV+1][NO_HI_RES_BINS];
+ Int32 aaIccIndex[MAX_NO_PS_ENV+1][NO_HI_RES_BINS];
+
+};
+
+typedef struct PS_DEC STRUCT_PS_DEC;
+typedef struct PS_DEC * HANDLE_PS_DEC;
+
+
+
+#endif /* E_PS_DEC_H */
+
diff --git a/media/libstagefright/codecs/aacdec/s_pulseinfo.h b/media/libstagefright/codecs/aacdec/s_pulseinfo.h
new file mode 100644
index 0000000..a7ced04
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_pulseinfo.h
@@ -0,0 +1,97 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_PulseInfo.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Comment out unused field.
+
+ Description: Fix ARM warnings, update copyright.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ define PulseInfo structure for pulse data decoding.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_PULSEINFO_H
+#define S_PULSEINFO_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_rawbitstreamconst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ Int pulse_data_present;
+ Int number_pulse;
+ Int pulse_start_sfb;
+ Int pulse_offset[NUM_PULSE_LINES];
+ Int pulse_amp[NUM_PULSE_LINES];
+} PulseInfo;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/s_sbr_channel.h b/media/libstagefright/codecs/aacdec/s_sbr_channel.h
new file mode 100644
index 0000000..99e28dd
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_sbr_channel.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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: s_sbr_channel.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_SBR_CHANNEL_H
+#define S_SBR_CHANNEL_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "s_sbr_frame_data.h"
+#include "e_sbr_sync_state.h"
+
+#ifdef PARAMETRICSTEREO
+#include "s_ps_dec.h"
+
+#endif
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define MAXNRELEMENTS 1
+#define MAXNRSBRCHANNELS (MAXNRELEMENTS*2)
+
+#ifdef PARAMETRICSTEREO
+#define MAXNRQMFCHANNELS MAXNRSBRCHANNELS
+#else
+#define MAXNRQMFCHANNELS MAXNRSBRCHANNELS
+#endif
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ Int32 outFrameSize;
+ SBR_SYNC_STATE syncState;
+ SBR_FRAME_DATA frameData;
+
+} SBR_CHANNEL;
+
+typedef struct
+{
+ SBR_CHANNEL SbrChannel[MAXNRSBRCHANNELS];
+ Int32 setStreamType;
+#ifdef PARAMETRICSTEREO
+ HANDLE_PS_DEC hParametricStereoDec;
+ STRUCT_PS_DEC ParametricStereoDec;
+#endif
+
+} SBRDECODER_DATA;
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/s_sbr_dec.h b/media/libstagefright/codecs/aacdec/s_sbr_dec.h
new file mode 100644
index 0000000..810479c
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_sbr_dec.h
@@ -0,0 +1,145 @@
+/* ------------------------------------------------------------------
+ * 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: s_sbr_dec.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+ $Id: ct_envcalc.h,v 1.3 2002/11/29 16:11:49 kaehleof Exp $
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_SBR_DEC_H
+#define S_SBR_DEC_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "s_sbr_frame_data.h"
+#include "pv_audio_type_defs.h"
+#include "s_patch.h"
+#include "e_blockswitching.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ Int32 outSampleRate;
+ Int32 LC_aacP_DecoderFlag; /* Low Complexity decoder flag */
+
+ Int32 startIndexCodecQmf;
+ Int32 lowBandAddSamples;
+ Int32 noCols;
+ Int32 qmfBufLen;
+ Int32 bufWriteOffs;
+ Int32 bufReadOffs;
+
+ Int32 sbStopCodec;
+ Int lowSubband;
+ Int prevLowSubband;
+ Int32 highSubband;
+ Int32 noSubbands;
+
+ Int FreqBandTable[2][MAX_FREQ_COEFFS + 1];
+ Int32 FreqBandTableNoise[MAX_NOISE_COEFFS + 1];
+ Int32 V_k_master[MAX_FREQ_COEFFS + 1]; /* Master BandTable which freqBandTable is derived from*/
+ Int32 NSfb[2];
+ Int32 NoNoiseBands; /* Number of noisebands */
+ Int32 Num_Master; /* Number of bands in V_k_master*/
+
+ struct PATCH Patch; /* Used by sbr_generate_high_freq */
+ /* Used by calc_sbr_envelope */
+ Int32 gateMode[4];
+ Int32 limSbc[4][12 + 1]; /* Limiting bands */
+
+ Int32 sqrt_cache[8][4]; /* cache memory for repeated sqrt() calculations */
+
+} SBR_DEC;
+
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/s_sbr_element_stream.h b/media/libstagefright/codecs/aacdec/s_sbr_element_stream.h
new file mode 100644
index 0000000..e9b6780
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_sbr_element_stream.h
@@ -0,0 +1,92 @@
+/* ------------------------------------------------------------------
+ * 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: s_sbr_element_stream.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_SBR_ELEMENT_STREAM_H
+#define S_SBR_ELEMENT_STREAM_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+#define MAXSBRBYTES 1024
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+typedef struct
+{
+ Int32 ElementID;
+ Int32 ExtensionType;
+ Int32 Payload;
+ UChar Data[MAXSBRBYTES];
+}
+SBR_ELEMENT_STREAM;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/s_sbr_frame_data.h b/media/libstagefright/codecs/aacdec/s_sbr_frame_data.h
new file mode 100644
index 0000000..89d1bb1
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_sbr_frame_data.h
@@ -0,0 +1,181 @@
+/* ------------------------------------------------------------------
+ * 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: s_sbr_frame_data.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_SBR_FRAME_DATA_H
+#define S_SBR_FRAME_DATA_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_sbr_header_data.h"
+#include "e_invf_mode.h"
+#include "e_coupling_mode.h"
+#include "sbr_constants.h"
+#include "s_patch.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ Int32 nScaleFactors; /* total number of scalefactors in frame */
+ Int32 nNoiseFactors;
+ Int32 crcCheckSum;
+ Int32 frameClass;
+ Int32 frameInfo[LENGTH_FRAME_INFO];
+ Int32 nSfb[2];
+ Int32 nNfb;
+ Int32 offset;
+ Int32 ampRes;
+ Int32 nNoiseFloorEnvelopes;
+ Int32 p;
+ Int32 prevEnvIsShort;
+
+ Int32 reset_flag;
+
+
+ SBR_HEADER_DATA sbr_header;
+
+
+ /* dynamic control signals */
+ Int32 domain_vec1[MAX_ENVELOPES];
+ Int32 domain_vec2[MAX_ENVELOPES];
+
+
+ INVF_MODE sbr_invf_mode[MAX_NUM_NOISE_VALUES];
+ INVF_MODE sbr_invf_mode_prev[MAX_NUM_NOISE_VALUES];
+
+ COUPLING_MODE coupling; /* 3 possibilities: off, level, pan */
+
+
+ Int32 addHarmonics[MAX_NUM_ENVELOPE_VALUES];
+
+ /* Used by calc_sbr_envelope */
+ Int32 hFp[64];
+ Int32 harm_index;
+ Int32 phase_index;
+ Int32 sUp;
+
+ /*
+ * envelope data
+ */
+
+ Int32 iEnvelope_man[MAX_NUM_ENVELOPE_VALUES]; /* mantissa */
+ Int32 iEnvelope_exp[MAX_NUM_ENVELOPE_VALUES]; /* exponent */
+ Int32 sfb_nrg_prev_man[MAX_FREQ_COEFFS]; /* mantissa */
+
+
+ /*
+ * noise data
+ */
+
+ Int32 sbrNoiseFloorLevel_man[MAX_NUM_NOISE_VALUES]; /* mantissa */
+ Int32 sbrNoiseFloorLevel_exp[MAX_NUM_NOISE_VALUES]; /* exponent */
+ Int32 prevNoiseLevel_man[MAX_NUM_NOISE_VALUES]; /* mantissa */
+
+ Int32 BwVector[MAX_NUM_PATCHES];
+ Int32 BwVectorOld[MAX_NUM_PATCHES];
+ /* Both implement a pseudo circular buffer */
+
+ /*
+ * 40 == Biggest of autoCorrLength(38) + sbrDec->bufReadOffs (2) and
+ * sbrDec->noCols (32) + sbrDec->bufWriteOffs (6)
+ */
+ Int32 codecQmfBufferReal[40][32];
+ Int32 *sbrQmfBufferReal;
+ Int32 HistsbrQmfBufferReal[6*SBR_NUM_BANDS];
+#ifdef HQ_SBR
+ Int32 codecQmfBufferImag[40][32];
+ Int32 *sbrQmfBufferImag;
+ Int32 HistsbrQmfBufferImag[6*SBR_NUM_BANDS];
+#endif
+ Int16 V[1152]; /* Used by calc_sbr_synfilterbank as freq. history buffer */
+
+
+ Int32 degreeAlias[64];
+
+
+#ifdef HQ_SBR
+
+ Int32 fBuffer_man[5][64]; /* smoothing history buffers */
+ Int32 fBufferN_man[5][64];
+ Int32 fBuffer_exp[5][64]; /* smoothing history buffers */
+ Int32 fBufferN_exp[5][64];
+
+ Int32 *fBuf_man[64]; /* pointer to smoothing history buffers */
+ Int32 *fBuf_exp[64]; /* pointer to smoothing history buffers */
+ Int32 *fBufN_man[64];
+ Int32 *fBufN_exp[64];
+
+
+#endif
+
+}
+SBR_FRAME_DATA;
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/s_sbr_header_data.h b/media/libstagefright/codecs/aacdec/s_sbr_header_data.h
new file mode 100644
index 0000000..7d7d746
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_sbr_header_data.h
@@ -0,0 +1,112 @@
+/* ------------------------------------------------------------------
+ * 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: s_sbr_header_data.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_SBR_HEADER_DATA_H
+#define S_SBR_HEADER_DATA_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_sbr_header_status.h"
+#include "e_sbr_master_status.h"
+#include "e_sr_mode.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ SBR_HEADER_STATUS status; /* the current status of the header */
+ SBR_MASTER_STATUS masterStatus;/* status of v_k_master freq table */
+
+ /* Changes in these variables indicates an error */
+ Int32 crcEnable;
+ SR_MODE sampleRateMode;
+ Int32 ampResolution;
+
+ /* Changes in these variables causes a reset of the decoder */
+ Int32 startFreq;
+ Int32 stopFreq;
+ Int32 xover_band;
+ Int32 freqScale;
+ Int32 alterScale;
+ Int32 noise_bands; /* noise bands per octave, read from bitstream */
+
+ /* Helper variable*/
+ Int32 noNoiseBands; /* actual number of noise bands to read from the bitstream */
+
+ Int32 limiterBands;
+ Int32 limiterGains;
+ Int32 interpolFreq;
+ Int32 smoothingLength;
+}
+SBR_HEADER_DATA;
+
+typedef SBR_HEADER_DATA *HANDLE_SBR_HEADER_DATA;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/s_sbrbitstream.h b/media/libstagefright/codecs/aacdec/s_sbrbitstream.h
new file mode 100644
index 0000000..609463a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_sbrbitstream.h
@@ -0,0 +1,91 @@
+/* ------------------------------------------------------------------
+ * 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: s_sbrbitstream.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_SBRBITSTREAM_H
+#define S_SBRBITSTREAM_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "s_sbr_element_stream.h"
+#include "s_sbr_channel.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+typedef struct
+{
+ Int32 NrElements;
+ Int32 NrElementsCore;
+ SBR_ELEMENT_STREAM sbrElement[MAXNRELEMENTS];
+}
+SBRBITSTREAM;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/s_sectinfo.h b/media/libstagefright/codecs/aacdec/s_sectinfo.h
new file mode 100644
index 0000000..83dcc31
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_sectinfo.h
@@ -0,0 +1,91 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/s_SectInfo.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ defines a structre that holds the Huffman codebook index and section
+ boundary information for each Frame.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_SECTINFO_H
+#define S_SECTINFO_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ Int sect_cb;
+ Int sect_end;
+} SectInfo;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/s_sr_info.h b/media/libstagefright/codecs/aacdec/s_sr_info.h
new file mode 100644
index 0000000..9b71003
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_sr_info.h
@@ -0,0 +1,91 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_SR_info.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified the declaration of the structure so no pointers are
+ used in the structure.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, SR_Info
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_SR_INFO_H
+#define S_SR_INFO_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ Int32 samp_rate;
+ Int nsfb1024;
+ Int nsfb128;
+} SR_Info;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/s_tdec_int_chan.h b/media/libstagefright/codecs/aacdec/s_tdec_int_chan.h
new file mode 100644
index 0000000..f7a3602
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_tdec_int_chan.h
@@ -0,0 +1,183 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_tDec_Int_Chan.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Change data types of win
+
+ Description: Remove wnd_shape structure.
+
+ Description: Remove dependency on window_block.h, Fix header too.
+
+ Description:
+ Modified to utilize memory in the last 1024 elements in fxpCoef.
+
+ Description:
+ (1) Modified to include the lines...
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ (2) Updated the copyright header.
+
+ Description:
+ (1) Move temporary FrameInfo structure into the shared region with fxpCoef.
+ (2) Add more comments detailing the size of the shared structure.
+
+ Description:
+ (1) Changed time_quant from 2048 Int32 buffer to 1024 Int32 buffer.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, tDec_Int_Chan
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_TDEC_INT_CHAN_H
+#define S_TDEC_INT_CHAN_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_rawbitstreamconst.h"
+#include "s_tns_frame_info.h"
+#include "s_wnd_shape.h"
+#include "s_lt_pred_status.h"
+#include "s_sectinfo.h"
+#include "s_frameinfo.h"
+#include "e_window_shape.h"
+#include "e_window_sequence.h"
+#include "window_block_fxp.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /* This structure was created with the specific goal in mind of sharing memory
+ * with the last 1024 data elements in fxpCoef.
+ *
+ * The size of this structure must NOT exceed 4 kilobytes
+ * Also, the size of the fxpCoef array cannot be less than 8 kilobytes
+ *
+ * The fxpCoef array is declared as an Int32, so its size should not vary
+ * from platform to platform.
+ *
+ * The shared structure is 3,640 bytes (3.55 KB), on a 32-bit platform,
+ * which represents the worst case.
+ */
+ typedef struct
+ {
+ TNS_frame_info tns;
+
+ FrameInfo frameInfo;
+
+ Int factors[MAXBANDS];
+ Int cb_map[MAXBANDS];
+ Int group[NSHORT];
+ Int qFormat[MAXBANDS];
+
+ Int max_sfb;
+ LT_PRED_STATUS lt_status;
+
+ } per_chan_share_w_fxpCoef;
+
+ /*
+ * This structure contains one per channel.
+ */
+ typedef struct
+ {
+#ifdef AAC_PLUS
+ Int16 ltp_buffer[LT_BLEN + 2*288]; /* LT_BLEN = 2048 + 2*288 */
+#else
+ Int16 ltp_buffer[LT_BLEN]; /* LT_BLEN = 2048 */
+#endif
+
+
+ Int32 time_quant[LONG_WINDOW]; /* 1024 holds overlap&add */
+
+ Int32 *fxpCoef; /* Spectrum coeff.*/
+
+ per_chan_share_w_fxpCoef * pShareWfxpCoef;
+
+ Int32 abs_max_per_window[NUM_SHORT_WINDOWS];
+
+ WINDOW_SEQUENCE wnd;
+
+
+ WINDOW_SHAPE wnd_shape_prev_bk;
+ WINDOW_SHAPE wnd_shape_this_bk;
+
+ } tDec_Int_Chan;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* S_TDEC_INT_CHAN_H */
+
diff --git a/media/libstagefright/codecs/aacdec/s_tdec_int_file.h b/media/libstagefright/codecs/aacdec/s_tdec_int_file.h
new file mode 100644
index 0000000..d0ffb0b
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_tdec_int_file.h
@@ -0,0 +1,277 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_tDec_Int_File.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Remove unneeded structure elements, clean up.
+
+ Description: Remove block.h, not needed, chains in other not needed files.
+
+ Description: Added declaration of scratch memory, scratchTnsDecCoefMem,
+ which will be utilized by tns_decode_coef().
+
+ Description:
+ (1) Modified to include the lines...
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ (2) Updated the copyright header.
+
+ Description: Per review comments...
+ (1) Removed declaration of unused variable, savedMCInfo
+ (2) Commented out ADTS related variables.
+ (3) Slight re-wording of comment for clarity.
+
+ Description:
+ (1) Moved scratch_prog_config into the scratch union.
+
+ Description:
+ (1) Added ltp state variable.
+
+ Description: Make tDec_Int_perChan an array of structures.
+ In the user applications, the malloc command will allocate a
+ continuous chunk of memory.
+
+ Description:
+ (1) Added the array data_stream_bytes[] to structure tDec_Int_File.
+ This to support Data Streaming Elements (DSE).
+ (2) Updated the copyright header.
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, tDec_Int_Chan
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_TDEC_INT_FILE_H
+#define S_TDEC_INT_FILE_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_progconfig.h"
+#include "s_frameinfo.h"
+#include "s_mc_info.h"
+#include "s_adif_header.h"
+#include "s_tdec_int_chan.h"
+#include "s_pulseinfo.h"
+#include "s_bits.h"
+#include "s_hcb.h"
+#include "e_infoinitconst.h"
+
+#include "s_sbr_channel.h"
+#include "s_sbr_dec.h"
+#include "s_sbrbitstream.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+
+
+
+ /*
+ * Note: most of the names of the variables put into this structure were kept
+ * the same because the name is also used in called functions.
+ *
+ * bno - block number
+ *
+ */
+ typedef struct
+ {
+ UInt32 bno;
+ Int status; /* save the status */
+
+ bool aacPlusEnabled;
+ bool aacConfigUtilityEnabled;
+
+ Int current_program;
+ Int frameLength;
+ Int adif_test;
+
+ BITS inputStream;
+
+ ProgConfig prog_config;
+
+ Int SFBWidth128[(1<<LEN_MAX_SFBS)];
+
+ /*
+ * One of the two arrays should be deleted in the final version.
+ */
+ FrameInfo longFrameInfo;
+ FrameInfo shortFrameInfo;
+ FrameInfo *winmap[NUM_WIN_SEQ];
+
+ /*
+ * Pns variables.
+ */
+ Int32 pns_cur_noise_state;
+
+ /*
+ *
+ */
+ MC_Info mc_info;
+
+ Int ltp_buffer_state;
+
+ /*
+ * For eaac+, a scratch matrix is created with the rigth element ( perChan[1] is not used)
+ * and the fxpCoef matrix. These 2 matrices are [2][38][64] == 4864 Int32
+ * 2349 coming from the perChan[1] plus 4096 coming from fxpCoef
+ */
+ tDec_Int_Chan perChan[Chans];
+
+ Int32 fxpCoef[2][LN]; /* LN = 2048 */
+
+
+
+#ifdef AAC_PLUS
+
+ SBRDECODER_DATA sbrDecoderData;/* allocates 2 SBR_CHANNEL, each has a SBR_FRAME_DATA */
+ SBR_DEC sbrDec;
+ SBRBITSTREAM sbrBitStr;
+
+#endif
+
+
+ /*
+ * If ADTS support is needed, the following variables will
+ * be required.
+ */
+ UInt32 syncword;
+ Int invoke;
+
+ Int mask[MAXBANDS];
+ Int hasmask;
+
+
+ /* SBR usage
+ * These two unions are used for the SBR tool and used
+ * as a single 2560 int32 continuous memory for circular
+ * buffering the synthesis QMF's bank history
+ */
+
+ /* This union specifies memory for arrays which are used
+ * by only one function. This is the simplest type of scratch
+ * memory to implement, since there are no worries about
+ * function interaction.
+ */
+ union scratch_memory
+ {
+ Int32 fft[LONG_WINDOW]; /* 1024, as needed by the FFT */
+ Int32 tns_inv_filter[TNS_MAX_ORDER];
+ Int32 tns_decode_coef[2*TNS_MAX_ORDER];
+ Int huffbook_used[248];
+ Int16 tmp_spec[LN2]; /* Used in conjunction with quant_spec */
+
+ ADIF_Header adif_header;
+
+ ProgConfig scratch_prog_config;
+
+
+ Int32 scratch_mem[16][64];
+ } scratch;
+
+ /* This union tries to take advantage of the fact that
+ * some variables are only used before LTP, and
+ * the long array, predictedSamples, is only used after LTP.
+ */
+
+ /*
+ * also used by the circular buffer scheme on aac+ (needs 4096 + 1152)
+ * from scratch_mem[2] + 5248 (uses most of shared_memory).
+ * For eaac+, shared memory is used by sbrQmfBufferReal which needs
+ * 1824 bytes
+ */
+ union shared_memory
+ {
+ Int32 predictedSamples[LONG_BLOCK1]; /* 2048 Int32 */
+
+ Char data_stream_bytes[(1<<LEN_D_CNT)+1];
+
+ struct
+ {
+ Int16 quantSpec[LN2];
+ SectInfo sect[MAXBANDS + 1];
+ PulseInfo pulseInfo;
+ } a;
+
+ } share;
+
+
+ } tDec_Int_File;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* S_TDEC_INT_FILE_H */
diff --git a/media/libstagefright/codecs/aacdec/s_tns_frame_info.h b/media/libstagefright/codecs/aacdec/s_tns_frame_info.h
new file mode 100644
index 0000000..61af0ac
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_tns_frame_info.h
@@ -0,0 +1,147 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_TNS_frame_info.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified to eliminate triple-nested structure, which wasted
+ 2 KB of memory.
+
+ Description:
+ (1) Modified to include the lines...
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ (2) Updated the copyright header.
+
+ Description:
+ (1) Changed hard coded size of arrays from "8" to "TNS_MAX_WIN"
+ (2) Moved elements from s_TNSinfo.h up to the level of TNS_frame_info
+ (3) Added Bool "tns_data_present" for future use.
+ (4) Moved lpc_coef up from s_TNSfilt.h (allowed for use of smaller array.)
+
+ Description:
+ (1) Removed the array "coef_res", which is now a local variable on the
+ stack inside get_tns.c
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, s_TNS_frame_info
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_TNS_FRAME_INFO_H
+#define S_TNS_FRAME_INFO_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_tns_const.h"
+#include "s_tnsfilt.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Bool tns_data_present;
+
+ /* Information about the number of filters for each window. */
+ Int n_filt[TNS_MAX_WIN];
+
+ /*
+ * Filter Information
+ *
+ * For short windows, there is a maximum of
+ * 1 filter per window (8 total)
+ *
+ * For long windows, there is a maximum of 3 filters
+ *
+ */
+ TNSfilt filt[TNS_MAX_WIN];
+
+ /*
+ * For short windows, there is a maximum of 8 filters,
+ * each of order 7 (requring 56 Ints)
+ *
+ * For long windows, there is a maximum of 3 filters,
+ * each of order 20 (requiring 60 Ints)
+ *
+ * So, 3*TNS_MAX_ORDER declares an array of sufficient
+ * size (60) for both cases.
+ */
+ Int32 lpc_coef[3*TNS_MAX_ORDER];
+
+ } TNS_frame_info;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* S_TNS_FRAME_INFO_H */
diff --git a/media/libstagefright/codecs/aacdec/s_tnsfilt.h b/media/libstagefright/codecs/aacdec/s_tnsfilt.h
new file mode 100644
index 0000000..c1d78af
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_tnsfilt.h
@@ -0,0 +1,132 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_TNSfilt.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added lpc, start, & size, so the data from
+ tns_inv_subblock can be shared with tns_decode_subblock.
+
+ Description: Removed lpc to save 2KB of memory (on 32-bit machines.)
+ This change requires tns_decode_coef.c to perform calculations in place.
+
+ Description: Removed start & size. start_band and stop_band can simply
+ take on a new meaning after this function. (coef index, rather than
+ scalefactor band index.)
+
+ Description: Had to add "start_coef" and "stop_coef" in order to preserve
+ values "start_band" and "stop_band." This required a change to
+ tns_setup_filter.c also.
+
+ Description: Had to add element "q_lpc" to store the q-format of the lpc
+ coefficients passed via "coef."
+
+ Description: Moved lpc_coef array up to the s_TNS_frame_info.h structure.
+
+ Description:
+ (1) Modified to include the lines...
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ (2) Updated the copyright header.
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, s_TNSfilt
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_TNSFILT_H
+#define S_TNSFILT_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_tns_const.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ typedef struct
+ {
+ Int start_band;
+ Int stop_band;
+ Int start_coef;
+ Int stop_coef;
+ UInt order;
+ Int direction;
+ Int q_lpc;
+
+ } TNSfilt;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* S_TNSFILT_H */
diff --git a/media/libstagefright/codecs/aacdec/s_wnd_shape.h b/media/libstagefright/codecs/aacdec/s_wnd_shape.h
new file mode 100644
index 0000000..c8a05c8
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/s_wnd_shape.h
@@ -0,0 +1,89 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: s_Wnd_Shape.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Change data type to Int
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, Wnd_Shape
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_WND_SHAPE_H
+#define S_WND_SHAPE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ Int this_bk;
+ Int prev_bk;
+} Wnd_Shape;
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/sbr_aliasing_reduction.cpp b/media/libstagefright/codecs/aacdec/sbr_aliasing_reduction.cpp
new file mode 100644
index 0000000..efbab7d
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_aliasing_reduction.cpp
@@ -0,0 +1,366 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_aliasing_reduction.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+
+#include "sbr_aliasing_reduction.h"
+#include "pv_sqrt.h"
+
+#include "aac_mem_funcs.h"
+
+#include "pv_div.h"
+#include "fxp_mul32.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define Q30fmt(x) (Int32)(x*((Int32)1<<30) + (x>=0?0.5F:-0.5F))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+#include "pv_normalize.h"
+#include "sbr_constants.h"
+
+/*******************************************************************************
+ Functionname: sbr_aliasing_reduction
+ *******************************************************************************
+ Description:
+ Arguments:
+
+ Return: none
+*******************************************************************************/
+void sbr_aliasing_reduction(Int32 *degreeAlias,
+ Int32 * nrg_gain_man,
+ Int32 * nrg_gain_exp,
+ Int32 * nrg_est_man,
+ Int32 * nrg_est_exp,
+ Int32 * dontUseTheseGainValues,
+ Int32 noSubbands,
+ Int32 lowSubband,
+ Int32 sqrt_cache[][4],
+ Int32 * groupVector)
+{
+
+ Int32 temp1;
+ Int32 est_total;
+ Int32 ref_total_man;
+ Int32 ref_total_exp;
+ Int32 tmp_q1;
+ Int32 tmp_q2;
+ Int32 tmp_q3;
+ Int32 tmp_q4;
+ Int32 bst_man;
+ Int32 bst_exp;
+ struct intg_div quotient;
+ struct intg_sqrt root_sq;
+ Int32 group;
+ Int32 grouping = 0;
+ Int32 index = 0;
+ Int32 noGroups;
+ Int32 k;
+
+
+ /* Calculate grouping*/
+ for (k = 0; k < noSubbands - 1; k++)
+ {
+ if (degreeAlias[k + lowSubband + 1] && dontUseTheseGainValues[k] == 0)
+ {
+ if (grouping == 0)
+ {
+ groupVector[index] = k + lowSubband;
+ grouping = 1;
+ index++;
+ }
+ }
+ else
+ {
+ if (grouping)
+ {
+ groupVector[index] = k + lowSubband;
+
+ if (! dontUseTheseGainValues[k])
+ {
+ (groupVector[index])++;
+ }
+ grouping = 0;
+ index++;
+ }
+ }
+ }
+
+ if (grouping)
+ {
+ groupVector[index] = noSubbands + lowSubband;
+ index++;
+ }
+ noGroups = (index >> 1);
+
+
+
+ /*Calculate new gain*/
+ for (group = 0; group < noGroups; group ++)
+ {
+
+ int startGroup = groupVector[(group<<1)] - lowSubband;
+ int stopGroup = groupVector[(group<<1)+1] - lowSubband;
+
+
+ est_total = 0;
+ ref_total_man = 0;
+
+ tmp_q1 = -100;
+ tmp_q2 = -100;
+
+ for (k = startGroup; k < stopGroup; k++)
+ {
+ if (tmp_q1 < nrg_est_exp[k])
+ {
+ tmp_q1 = nrg_est_exp[k]; /* max */
+ }
+ if (tmp_q2 < (nrg_est_exp[k] + (nrg_gain_exp[k] << 1)))
+ {
+ tmp_q2 = (nrg_est_exp[k] + (nrg_gain_exp[k] << 1)); /* max */
+ }
+ }
+
+
+ k -= startGroup; /* number of element used in the addition */
+ /* adjust Q format */
+ tmp_q2 += 59 - pv_normalize(k);
+
+ for (k = startGroup; k < stopGroup; k++)
+ {
+ /*
+ * est_total += nrg_est[k]
+ * ref_total += nrg_est[k]*nrg_gain[k]*nrg_gain[k
+ */
+ est_total += nrg_est_man[k] >> (tmp_q1 - nrg_est_exp[k]);
+
+ if (tmp_q2 - (nrg_est_exp[k] + (nrg_gain_exp[k] << 1)) < 60)
+ {
+ nrg_gain_man[k] = fxp_mul32_Q28(nrg_gain_man[k], nrg_gain_man[k]);
+ nrg_gain_exp[k] = (nrg_gain_exp[k] << 1) + 28;
+ tmp_q3 = fxp_mul32_Q28(nrg_gain_man[k], nrg_est_man[k]);
+ ref_total_man += tmp_q3 >> (tmp_q2 - (nrg_est_exp[k] + nrg_gain_exp[k]));
+ }
+ }
+
+ ref_total_exp = tmp_q2 + 28;
+
+ pv_div(ref_total_man, est_total, &quotient);
+
+ tmp_q2 += - tmp_q1 - quotient.shift_factor - 2;
+
+
+
+ for (k = startGroup; k < stopGroup; k++)
+ {
+ Int32 alpha;
+ temp1 = k + lowSubband;
+ if (k < noSubbands - 1)
+ {
+ alpha = degreeAlias[temp1 + 1] > degreeAlias[temp1 ] ?
+ degreeAlias[temp1 + 1] : degreeAlias[temp1 ];
+ }
+ else
+ {
+ alpha = degreeAlias[temp1];
+ }
+
+ /*
+ * nrg_gain[k] = alpha*newGain + (1.0f-alpha)*nrg_gain[k]*nrg_gain[k];
+ */
+
+ tmp_q1 = tmp_q2 > nrg_gain_exp[k] ? tmp_q2 : nrg_gain_exp[k];
+ tmp_q1++;
+
+ tmp_q3 = fxp_mul32_Q30(alpha, quotient.quotient);
+ tmp_q4 = fxp_mul32_Q30(Q30fmt(1.0f) - alpha, nrg_gain_man[k]);
+
+ nrg_gain_man[k] = (tmp_q3 >> (tmp_q1 - tmp_q2)) +
+ (tmp_q4 >> (tmp_q1 - nrg_gain_exp[k]));
+
+ nrg_gain_exp[k] = tmp_q1;
+ }
+
+
+ bst_exp = -100;
+
+ for (k = startGroup; k < stopGroup; k++)
+ {
+ if (bst_exp < nrg_gain_exp[k] + nrg_est_exp[k])
+ {
+ bst_exp = nrg_gain_exp[k] + nrg_est_exp[k]; /* max */
+ }
+ }
+
+ k -= startGroup; /* number of element used in the addition */
+
+ while (k != 0) /* bit guard protection depends on log2(k) */
+ {
+ k >>= 1;
+ bst_exp++; /* add extra bit-overflow-guard */
+ }
+
+ bst_man = 0;
+
+ for (k = startGroup; k < stopGroup; k++)
+ {
+ tmp_q2 = fxp_mul32_Q28(nrg_gain_man[k], nrg_est_man[k]);
+ bst_man += tmp_q2 >> (bst_exp - nrg_gain_exp[k] - nrg_est_exp[k]);
+ }
+
+ bst_exp += 28; /* compensate for shift down */
+
+ if (bst_man)
+ {
+ /*
+ * bst = ref_total / bst
+ */
+
+ pv_div(ref_total_man, bst_man, &quotient);
+ bst_exp = ref_total_exp - bst_exp - quotient.shift_factor - 30;
+ bst_man = quotient.quotient; /* Q30 */
+
+ for (k = startGroup; k < stopGroup; k++)
+ {
+ tmp_q1 = fxp_mul32_Q30(bst_man, nrg_gain_man[k]);
+ pv_sqrt(tmp_q1, (bst_exp + nrg_gain_exp[k] + 60), &root_sq, sqrt_cache[0]);
+ nrg_gain_man[k] = root_sq.root;
+ nrg_gain_exp[k] = root_sq.shift_factor;
+ }
+ }
+ else
+ {
+ pv_memset((void *)&nrg_gain_man[startGroup],
+ 0,
+ (stopGroup - startGroup)*sizeof(nrg_gain_man[0]));
+
+ pv_memset((void *)&nrg_gain_exp[startGroup],
+ 0,
+ (stopGroup - startGroup)*sizeof(nrg_gain_exp[0]));
+
+ }
+
+ }
+}
+
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_aliasing_reduction.h b/media/libstagefright/codecs/aacdec/sbr_aliasing_reduction.h
new file mode 100644
index 0000000..2ce99ec
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_aliasing_reduction.h
@@ -0,0 +1,92 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_aliasing_reduction.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_ALIASING_REDUCTION_H
+#define SBR_ALIASING_REDUCTION_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void sbr_aliasing_reduction(Int32 *degreeAlias,
+ Int32 * nrg_gain_man,
+ Int32 * nrg_gain_exp,
+ Int32 * nrg_est_man,
+ Int32 * nrg_est_exp,
+ Int32 * dontUseTheseGainValues,
+ Int32 noSubbands,
+ Int32 lowSubband,
+ Int32 sqrt_cache[][4],
+ Int32 * groupVector);
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_applied.cpp b/media/libstagefright/codecs/aacdec/sbr_applied.cpp
new file mode 100644
index 0000000..c8b81b2
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_applied.cpp
@@ -0,0 +1,435 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_applied.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ INPUT
+
+ SBRDECODER self,
+ SBRBITSTREAM * stream,
+ float *timeData,
+ int numChannels
+
+ OUTPUT
+
+ errorCode, noError if successful
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ sbr decoder processing, set up SBR decoder phase 2 in case of
+ different cotrol data
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#ifdef AAC_PLUS
+
+
+#include "sbr_applied.h"
+#include "sbr_read_data.h"
+
+#include "sbr_decode_envelope.h"
+#include "decode_noise_floorlevels.h"
+#include "sbr_requantize_envelope_data.h"
+#include "sbr_envelope_unmapping.h"
+#include "sbr_dec.h"
+#include "e_sbr_element_id.h"
+#include "aac_mem_funcs.h"
+
+#ifdef PARAMETRICSTEREO
+#include "ps_bstr_decoding.h"
+#include "ps_allocate_decoder.h"
+
+#endif
+
+#include "init_sbr_dec.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define LEFT (0)
+#define RIGHT (1)
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+SBR_ERROR sbr_applied(SBRDECODER_DATA * self,
+ SBRBITSTREAM * stream,
+ Int16 *ch_left,
+ Int16 *ch_right,
+ Int16 *timeData,
+ SBR_DEC *sbrDec,
+ tDec_Int_File *pVars,
+ Int32 numChannels)
+{
+ SBR_ERROR err = SBRDEC_OK ;
+
+ Int32 eleChannels = 0;
+
+ SBR_CHANNEL *SbrChannel = self->SbrChannel;
+
+ /* Get SBR or PS Data only when available */
+ if (stream->NrElements)
+ {
+ /* read frame data from bitstream */
+
+ err = sbr_read_data(self,
+ sbrDec,
+ stream);
+
+ if (err != SBRDEC_OK)
+ {
+ /*
+ * This error condition disables any further SBR processing
+ */
+ self->SbrChannel[LEFT].syncState = UPSAMPLING;
+ if (eleChannels == 2)
+ {
+ self->SbrChannel[RIGHT].syncState = UPSAMPLING;
+ }
+ }
+
+ /*
+ * Setting bistream and decoding type is only done once,
+ */
+ if (SbrChannel[LEFT].syncState == SBR_ACTIVE && self->setStreamType)
+ {
+ self->setStreamType = 0; /* Disable Lock for AAC stream type setting */
+
+#ifdef HQ_SBR
+#ifdef PARAMETRICSTEREO
+
+ Int sbrEnablePS = self->hParametricStereoDec->psDetected;
+
+ pVars->mc_info.psPresentFlag = sbrEnablePS;
+
+ if (sbrEnablePS) /* Initialize PS arrays */
+ {
+ pVars->mc_info.ExtendedAudioObjectType = MP4AUDIO_PS;
+ ps_allocate_decoder(self, 32);
+
+ /* Disable LC (or Enable HQ) if PS is detected */
+ sbrDec->LC_aacP_DecoderFlag = OFF;
+ }
+ else
+ {
+ /*
+ * Do not downgrade stream type from eaac+, if it has been explicitly declared
+ */
+ if (pVars->mc_info.ExtendedAudioObjectType != MP4AUDIO_PS)
+ {
+ pVars->mc_info.ExtendedAudioObjectType = MP4AUDIO_SBR;
+
+ if (pVars->mc_info.nch > 1)
+ {
+ sbrDec->LC_aacP_DecoderFlag = ON; /* Enable LC for stereo */
+ }
+ else
+ {
+ sbrDec->LC_aacP_DecoderFlag = OFF; /* Disable LC, Enable HQ for mono */
+ }
+ }
+ else
+ {
+ sbrEnablePS = 1; /* Force this condition as it was explicititly declared */
+ pVars->mc_info.psPresentFlag = sbrEnablePS;
+
+ }
+ }
+#else
+
+ pVars->mc_info.ExtendedAudioObjectType = MP4AUDIO_SBR;
+
+ if (pVars->mc_info.nch > 1)
+ {
+ sbrDec->LC_aacP_DecoderFlag = ON; /* Enable LC for stereo */
+ }
+ else
+ {
+ sbrDec->LC_aacP_DecoderFlag = OFF; /* Disable LC, Enable HQ for mono */
+ }
+#endif
+
+#else
+ pVars->mc_info.ExtendedAudioObjectType = MP4AUDIO_SBR;
+
+ sbrDec->LC_aacP_DecoderFlag = ON; /* Enable LC for all sbr decoding */
+
+#endif
+
+ } /* (SbrChannel[LEFT].syncState == SBR_ACTIVE && lock) */
+ else
+ {
+ /*
+ * Default setting for upsampler
+ */
+ if (pVars->mc_info.ExtendedAudioObjectType == MP4AUDIO_AAC_LC)
+ {
+ /*
+ * Change only in implicit signalling, otherwise keep original declaration
+ */
+ pVars->mc_info.ExtendedAudioObjectType = MP4AUDIO_SBR;
+ }
+
+#ifdef HQ_SBR
+ if (pVars->mc_info.nch > 1)
+ {
+ sbrDec->LC_aacP_DecoderFlag = ON; /* Enable LC for stereo */
+ }
+ else
+ {
+ sbrDec->LC_aacP_DecoderFlag = OFF; /* Disable LC, Enable HQ for mono */
+ }
+#else
+ sbrDec->LC_aacP_DecoderFlag = ON; /* Enable LC for all sbr decoding */
+
+#endif
+ /* mask error and let upsampler run */
+ err = SBRDEC_OK;
+
+ }
+
+ /* decoding */
+ eleChannels = (stream->sbrElement [LEFT].ElementID == SBR_ID_CPE) ? 2 : 1;
+
+ if (SbrChannel[LEFT].syncState == SBR_ACTIVE)
+ {
+
+ sbr_decode_envelope(&(SbrChannel[LEFT].frameData));
+
+ decode_noise_floorlevels(&(SbrChannel[LEFT].frameData));
+
+ if (! SbrChannel[LEFT].frameData.coupling)
+ {
+ sbr_requantize_envelope_data(&(SbrChannel[LEFT].frameData));
+ }
+
+ if (eleChannels == 2)
+ {
+
+ sbr_decode_envelope(&(SbrChannel[RIGHT].frameData));
+
+ decode_noise_floorlevels(&(SbrChannel[RIGHT].frameData));
+
+ if (SbrChannel[RIGHT].frameData.coupling)
+ {
+ sbr_envelope_unmapping(&(SbrChannel[ LEFT].frameData),
+ &(SbrChannel[RIGHT].frameData));
+ }
+ else
+ {
+ sbr_requantize_envelope_data(&(SbrChannel[RIGHT].frameData));
+ }
+ }
+ }
+ else /* enable upsampling until valid SBR is obtained */
+ {
+ /*
+ * Incomplete sbr frame, or disabled SBR section
+ * Set the decoder to act as a regular upsampler
+ */
+
+ init_sbr_dec((sbrDec->outSampleRate >> 1),
+ pVars->mc_info.upsamplingFactor,
+ sbrDec,
+ &(self->SbrChannel[LEFT].frameData));
+
+ if ((eleChannels == 2) && (SbrChannel[RIGHT].syncState != SBR_ACTIVE))
+ {
+ init_sbr_dec((sbrDec->outSampleRate >> 1),
+ pVars->mc_info.upsamplingFactor,
+ sbrDec,
+ &(self->SbrChannel[RIGHT].frameData));
+
+ }
+
+ }
+
+ }
+
+
+#ifdef HQ_SBR
+#ifdef PARAMETRICSTEREO
+ if (pVars->mc_info.ExtendedAudioObjectType == MP4AUDIO_PS)
+ {
+ ps_bstr_decoding(self->hParametricStereoDec);
+ /* allocate pointer for rigth channel qmf filter history */
+ Int16 *tempInt16Ptr = (Int16 *)SbrChannel[RIGHT].frameData.V;
+ self->hParametricStereoDec->R_ch_qmf_filter_history = (Int32 *)tempInt16Ptr;
+
+
+ /*
+ * 1824 (48*38) Int32 needed by each matrix sbrQmfBufferReal, sbrQmfBufferImag
+ * pVars->share.predictedSamples has 2048 available
+ * pVars->fxpCoef[1] has 2048 available
+ */
+ SbrChannel[LEFT].frameData.sbrQmfBufferReal = pVars->share.predictedSamples;
+ SbrChannel[LEFT].frameData.sbrQmfBufferImag = &pVars->fxpCoef[0][920];
+
+ sbr_dec(ch_left,
+ timeData,
+ &(SbrChannel[LEFT].frameData),
+ (SbrChannel[LEFT].syncState == SBR_ACTIVE),
+ sbrDec,
+ &timeData[RIGHT],
+ self->hParametricStereoDec,
+ pVars);
+ }
+ else
+ {
+#endif
+#endif
+
+ SbrChannel[LEFT].frameData.sbrQmfBufferReal = pVars->fxpCoef[LEFT];
+#ifdef HQ_SBR
+ SbrChannel[LEFT].frameData.sbrQmfBufferImag = pVars->fxpCoef[RIGHT];
+#endif
+
+ sbr_dec(ch_left,
+ timeData,
+ &(SbrChannel[LEFT].frameData),
+ (SbrChannel[LEFT].syncState == SBR_ACTIVE),
+ sbrDec,
+#ifdef HQ_SBR
+#ifdef PARAMETRICSTEREO
+ NULL,
+ NULL,
+#endif
+#endif
+ pVars);
+
+ if (numChannels == 2)
+ {
+ SbrChannel[RIGHT].frameData.sbrQmfBufferReal = pVars->fxpCoef[LEFT];
+#ifdef HQ_SBR
+ SbrChannel[RIGHT].frameData.sbrQmfBufferImag = pVars->fxpCoef[RIGHT];
+#endif
+
+ sbr_dec(ch_right,
+ &timeData[RIGHT],
+ &(SbrChannel[RIGHT].frameData),
+ (SbrChannel[RIGHT].syncState == SBR_ACTIVE),
+ sbrDec,
+#ifdef HQ_SBR
+#ifdef PARAMETRICSTEREO
+ NULL,
+ NULL,
+#endif
+#endif
+ pVars);
+
+ }
+
+
+#ifdef HQ_SBR
+#ifdef PARAMETRICSTEREO
+ }
+#endif
+#endif
+
+ return err;
+}
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_applied.h b/media/libstagefright/codecs/aacdec/sbr_applied.h
new file mode 100644
index 0000000..6878537
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_applied.h
@@ -0,0 +1,136 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_applied.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+ $Id: ct_envcalc.h,v 1.3 2002/11/29 16:11:49 kaehleof Exp $
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_APPLIED_H
+#define SBR_APPLIED_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "e_sbr_error.h"
+#include "s_sbr_channel.h"
+#include "s_sbrbitstream.h"
+#include "sbr_dec.h"
+#include "pv_audio_type_defs.h"
+#include "s_tdec_int_file.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define MAX_FRAME_SIZE 1024
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ SBR_ERROR sbr_applied(SBRDECODER_DATA * self,
+ SBRBITSTREAM * stream,
+ Int16 *ch_left,
+ Int16 *ch_right,
+ Int16 *timeData,
+ SBR_DEC *sbrDec,
+ tDec_Int_File *pVars,
+ Int32 numChannels);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_code_book_envlevel.cpp b/media/libstagefright/codecs/aacdec/sbr_code_book_envlevel.cpp
new file mode 100644
index 0000000..9db3221
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_code_book_envlevel.cpp
@@ -0,0 +1,403 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_code_book_envlevel.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "pv_audio_type_defs.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL FUNCTION REFERENCES
+ ; Declare functions defined elsewhere and referenced in this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ /*******************************************************************************/
+ /* table : envelope level, 1.5 dB */
+ /* theor range : [-58,58], CODE_BOOK_SCF_LAV = 58 */
+ /* implem range: [-60,60], CODE_BOOK_SCF_LAV10 = 60 */
+ /* raw stats : envelopeLevel_00 (yes, wrong suffix in name) KK 01-03-09 */
+ /*******************************************************************************/
+
+ /* direction: time
+ raw table: HuffCode3C2FIX.m/envelopeLevel_00T_cF.mat/m_hALC_cF
+ built by : FH 01-07-05 */
+
+ extern const Char bookSbrEnvLevel10T[120][2] =
+ {
+ { 1, 2 }, { -64, -65 }, { 3, 4 }, { -63, -66 },
+ { 5, 6 }, { -62, -67 }, { 7, 8 }, { -61, -68 },
+ { 9, 10 }, { -60, -69 }, { 11, 12 }, { -59, -70 },
+ { 13, 14 }, { -58, -71 }, { 15, 16 }, { -57, -72 },
+ { 17, 18 }, { -73, -56 }, { 19, 21 }, { -74, 20 },
+ { -55, -75 }, { 22, 26 }, { 23, 24 }, { -54, -76 },
+ { -77, 25 }, { -53, -78 }, { 27, 34 }, { 28, 29 },
+ { -52, -79 }, { 30, 31 }, { -80, -51 }, { 32, 33 },
+ { -83, -82 }, { -81, -50 }, { 35, 57 }, { 36, 40 },
+ { 37, 38 }, { -88, -84 }, { -48, 39 }, { -90, -85 },
+ { 41, 46 }, { 42, 43 }, { -49, -87 }, { 44, 45 },
+ { -89, -86 }, { -124, -123 }, { 47, 50 }, { 48, 49 },
+ { -122, -121 }, { -120, -119 }, { 51, 54 }, { 52, 53 },
+ { -118, -117 }, { -116, -115 }, { 55, 56 }, { -114, -113 },
+ { -112, -111 }, { 58, 89 }, { 59, 74 }, { 60, 67 },
+ { 61, 64 }, { 62, 63 }, { -110, -109 }, { -108, -107 },
+ { 65, 66 }, { -106, -105 }, { -104, -103 }, { 68, 71 },
+ { 69, 70 }, { -102, -101 }, { -100, -99 }, { 72, 73 },
+ { -98, -97 }, { -96, -95 }, { 75, 82 }, { 76, 79 },
+ { 77, 78 }, { -94, -93 }, { -92, -91 }, { 80, 81 },
+ { -47, -46 }, { -45, -44 }, { 83, 86 }, { 84, 85 },
+ { -43, -42 }, { -41, -40 }, { 87, 88 }, { -39, -38 },
+ { -37, -36 }, { 90, 105 }, { 91, 98 }, { 92, 95 },
+ { 93, 94 }, { -35, -34 }, { -33, -32 }, { 96, 97 },
+ { -31, -30 }, { -29, -28 }, { 99, 102 }, { 100, 101 },
+ { -27, -26 }, { -25, -24 }, { 103, 104 }, { -23, -22 },
+ { -21, -20 }, { 106, 113 }, { 107, 110 }, { 108, 109 },
+ { -19, -18 }, { -17, -16 }, { 111, 112 }, { -15, -14 },
+ { -13, -12 }, { 114, 117 }, { 115, 116 }, { -11, -10 },
+ { -9, -8 }, { 118, 119 }, { -7, -6 }, { -5, -4 }
+ };
+
+ /* direction: freq
+ raw table: HuffCode3C2FIX.m/envelopeLevel_00F_cF.mat/m_hALC_cF
+ built by : FH 01-07-05 */
+
+ extern const Char bookSbrEnvLevel10F[120][2] =
+ {
+ { 1, 2 }, { -64, -65 }, { 3, 4 }, { -63, -66 },
+ { 5, 6 }, { -67, -62 }, { 7, 8 }, { -68, -61 },
+ { 9, 10 }, { -69, -60 }, { 11, 13 }, { -70, 12 },
+ { -59, -71 }, { 14, 16 }, { -58, 15 }, { -72, -57 },
+ { 17, 19 }, { -73, 18 }, { -56, -74 }, { 20, 23 },
+ { 21, 22 }, { -55, -75 }, { -54, -53 }, { 24, 27 },
+ { 25, 26 }, { -76, -52 }, { -77, -51 }, { 28, 31 },
+ { 29, 30 }, { -50, -78 }, { -79, -49 }, { 32, 36 },
+ { 33, 34 }, { -48, -47 }, { -80, 35 }, { -81, -82 },
+ { 37, 47 }, { 38, 41 }, { 39, 40 }, { -83, -46 },
+ { -45, -84 }, { 42, 44 }, { -85, 43 }, { -44, -43 },
+ { 45, 46 }, { -88, -87 }, { -86, -90 }, { 48, 66 },
+ { 49, 56 }, { 50, 53 }, { 51, 52 }, { -92, -42 },
+ { -41, -39 }, { 54, 55 }, { -105, -89 }, { -38, -37 },
+ { 57, 60 }, { 58, 59 }, { -94, -91 }, { -40, -36 },
+ { 61, 63 }, { -20, 62 }, { -115, -110 }, { 64, 65 },
+ { -108, -107 }, { -101, -97 }, { 67, 89 }, { 68, 75 },
+ { 69, 72 }, { 70, 71 }, { -95, -93 }, { -34, -27 },
+ { 73, 74 }, { -22, -17 }, { -16, -124 }, { 76, 82 },
+ { 77, 79 }, { -123, 78 }, { -122, -121 }, { 80, 81 },
+ { -120, -119 }, { -118, -117 }, { 83, 86 }, { 84, 85 },
+ { -116, -114 }, { -113, -112 }, { 87, 88 }, { -111, -109 },
+ { -106, -104 }, { 90, 105 }, { 91, 98 }, { 92, 95 },
+ { 93, 94 }, { -103, -102 }, { -100, -99 }, { 96, 97 },
+ { -98, -96 }, { -35, -33 }, { 99, 102 }, { 100, 101 },
+ { -32, -31 }, { -30, -29 }, { 103, 104 }, { -28, -26 },
+ { -25, -24 }, { 106, 113 }, { 107, 110 }, { 108, 109 },
+ { -23, -21 }, { -19, -18 }, { 111, 112 }, { -15, -14 },
+ { -13, -12 }, { 114, 117 }, { 115, 116 }, { -11, -10 },
+ { -9, -8 }, { 118, 119 }, { -7, -6 }, { -5, -4 }
+ };
+
+ /*******************************************************************************/
+ /* table : envelope balance, 1.5 dB */
+ /* theor range : [-48,48], CODE_BOOK_SCF_LAV = 48 */
+ /* implem range: same but mapped to [-24,24], CODE_BOOK_SCF_LAV_BALANCE10 = 24 */
+ /* raw stats : envelopePan_00 (yes, wrong suffix in name) KK 01-03-09 */
+ /*******************************************************************************/
+
+ /* direction: time
+ raw table: HuffCode3C.m/envelopePan_00T.mat/v_hALB
+ built by : FH 01-05-15 */
+
+ extern const Char bookSbrEnvBalance10T[48][2] =
+ {
+ { -64, 1 }, { -63, 2 }, { -65, 3 }, { -62, 4 },
+ { -66, 5 }, { -61, 6 }, { -67, 7 }, { -60, 8 },
+ { -68, 9 }, { 10, 11 }, { -69, -59 }, { 12, 13 },
+ { -70, -58 }, { 14, 28 }, { 15, 21 }, { 16, 18 },
+ { -57, 17 }, { -71, -56 }, { 19, 20 }, { -88, -87 },
+ { -86, -85 }, { 22, 25 }, { 23, 24 }, { -84, -83 },
+ { -82, -81 }, { 26, 27 }, { -80, -79 }, { -78, -77 },
+ { 29, 36 }, { 30, 33 }, { 31, 32 }, { -76, -75 },
+ { -74, -73 }, { 34, 35 }, { -72, -55 }, { -54, -53 },
+ { 37, 41 }, { 38, 39 }, { -52, -51 }, { -50, 40 },
+ { -49, -48 }, { 42, 45 }, { 43, 44 }, { -47, -46 },
+ { -45, -44 }, { 46, 47 }, { -43, -42 }, { -41, -40 }
+ };
+
+ /* direction: freq
+ raw table: HuffCode3C.m/envelopePan_00T.mat/v_hALB
+ built by : FH 01-05-15 */
+
+ extern const Char bookSbrEnvBalance10F[48][2] =
+ {
+ { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 },
+ { -62, 5 }, { -61, 6 }, { -67, 7 }, { -68, 8 },
+ { -60, 9 }, { 10, 11 }, { -69, -59 }, { -70, 12 },
+ { -58, 13 }, { 14, 17 }, { -71, 15 }, { -57, 16 },
+ { -56, -73 }, { 18, 32 }, { 19, 25 }, { 20, 22 },
+ { -72, 21 }, { -88, -87 }, { 23, 24 }, { -86, -85 },
+ { -84, -83 }, { 26, 29 }, { 27, 28 }, { -82, -81 },
+ { -80, -79 }, { 30, 31 }, { -78, -77 }, { -76, -75 },
+ { 33, 40 }, { 34, 37 }, { 35, 36 }, { -74, -55 },
+ { -54, -53 }, { 38, 39 }, { -52, -51 }, { -50, -49 },
+ { 41, 44 }, { 42, 43 }, { -48, -47 }, { -46, -45 },
+ { 45, 46 }, { -44, -43 }, { -42, 47 }, { -41, -40 }
+ };
+
+ /*******************************************************************************/
+ /* table : envelope level, 3.0 dB */
+ /* theor range : [-29,29], CODE_BOOK_SCF_LAV = 29 */
+ /* implem range: [-31,31], CODE_BOOK_SCF_LAV11 = 31 */
+ /* raw stats : envelopeLevel_11 KK 00-02-03 */
+ /*******************************************************************************/
+
+ /* direction: time
+ raw table: HuffCode2.m
+ built by : FH 00-02-04 */
+
+ extern const Char bookSbrEnvLevel11T[62][2] =
+ {
+ { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 },
+ { -62, 5 }, { -67, 6 }, { -61, 7 }, { -68, 8 },
+ { -60, 9 }, { 10, 11 }, { -69, -59 }, { 12, 14 },
+ { -70, 13 }, { -71, -58 }, { 15, 18 }, { 16, 17 },
+ { -72, -57 }, { -73, -74 }, { 19, 22 }, { -56, 20 },
+ { -55, 21 }, { -54, -77 }, { 23, 31 }, { 24, 25 },
+ { -75, -76 }, { 26, 27 }, { -78, -53 }, { 28, 29 },
+ { -52, -95 }, { -94, 30 }, { -93, -92 }, { 32, 47 },
+ { 33, 40 }, { 34, 37 }, { 35, 36 }, { -91, -90 },
+ { -89, -88 }, { 38, 39 }, { -87, -86 }, { -85, -84 },
+ { 41, 44 }, { 42, 43 }, { -83, -82 }, { -81, -80 },
+ { 45, 46 }, { -79, -51 }, { -50, -49 }, { 48, 55 },
+ { 49, 52 }, { 50, 51 }, { -48, -47 }, { -46, -45 },
+ { 53, 54 }, { -44, -43 }, { -42, -41 }, { 56, 59 },
+ { 57, 58 }, { -40, -39 }, { -38, -37 }, { 60, 61 },
+ { -36, -35 }, { -34, -33 }
+ };
+
+ /* direction: freq
+ raw table: HuffCode2.m
+ built by : FH 00-02-04 */
+
+ extern const Char bookSbrEnvLevel11F[62][2] =
+ {
+ { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 },
+ { -62, 5 }, { -67, 6 }, { 7, 8 }, { -61, -68 },
+ { 9, 10 }, { -60, -69 }, { 11, 12 }, { -59, -70 },
+ { 13, 14 }, { -58, -71 }, { 15, 16 }, { -57, -72 },
+ { 17, 19 }, { -56, 18 }, { -55, -73 }, { 20, 24 },
+ { 21, 22 }, { -74, -54 }, { -53, 23 }, { -75, -76 },
+ { 25, 30 }, { 26, 27 }, { -52, -51 }, { 28, 29 },
+ { -77, -79 }, { -50, -49 }, { 31, 39 }, { 32, 35 },
+ { 33, 34 }, { -78, -46 }, { -82, -88 }, { 36, 37 },
+ { -83, -48 }, { -47, 38 }, { -86, -85 }, { 40, 47 },
+ { 41, 44 }, { 42, 43 }, { -80, -44 }, { -43, -42 },
+ { 45, 46 }, { -39, -87 }, { -84, -40 }, { 48, 55 },
+ { 49, 52 }, { 50, 51 }, { -95, -94 }, { -93, -92 },
+ { 53, 54 }, { -91, -90 }, { -89, -81 }, { 56, 59 },
+ { 57, 58 }, { -45, -41 }, { -38, -37 }, { 60, 61 },
+ { -36, -35 }, { -34, -33 }
+ };
+
+ /*******************************************************************************/
+ /* table : envelope balance, 3.0 dB */
+ /* theor range : [-24,24], CODE_BOOK_SCF_LAV = 24 */
+ /* implem range: same but mapped to [-12,12], CODE_BOOK_SCF_LAV_BALANCE11 = 12 */
+ /* raw stats : envelopeBalance_11 KK 00-02-03 */
+ /*******************************************************************************/
+
+ /* direction: time
+ raw table: HuffCode3C.m/envelopeBalance_11T.mat/v_hALB
+ built by : FH 01-05-15 */
+
+ extern const Char bookSbrEnvBalance11T[24][2] =
+ {
+ { -64, 1 }, { -63, 2 }, { -65, 3 }, { -66, 4 },
+ { -62, 5 }, { -61, 6 }, { -67, 7 }, { -68, 8 },
+ { -60, 9 }, { 10, 16 }, { 11, 13 }, { -69, 12 },
+ { -76, -75 }, { 14, 15 }, { -74, -73 }, { -72, -71 },
+ { 17, 20 }, { 18, 19 }, { -70, -59 }, { -58, -57 },
+ { 21, 22 }, { -56, -55 }, { -54, 23 }, { -53, -52 }
+ };
+
+ /* direction: time (?)
+ raw table: HuffCode3C.m/envelopeBalance_11T.mat/v_hALB
+ built by : FH 01-05-15 */
+
+ extern const Char bookSbrEnvBalance11F[24][2] =
+ {
+ { -64, 1 }, { -65, 2 }, { -63, 3 }, { -66, 4 },
+ { -62, 5 }, { -61, 6 }, { -67, 7 }, { -68, 8 },
+ { -60, 9 }, { 10, 13 }, { -69, 11 }, { -59, 12 },
+ { -58, -76 }, { 14, 17 }, { 15, 16 }, { -75, -74 },
+ { -73, -72 }, { 18, 21 }, { 19, 20 }, { -71, -70 },
+ { -57, -56 }, { 22, 23 }, { -55, -54 }, { -53, -52 }
+ };
+
+ /*******************************************************************************/
+ /* table : noise level, 3.0 dB */
+ /* theor range : [-29,29], CODE_BOOK_SCF_LAV = 29 */
+ /* implem range: [-31,31], CODE_BOOK_SCF_LAV11 = 31 */
+ /* raw stats : noiseLevel_11 KK 00-02-03 */
+ /*******************************************************************************/
+
+ /* direction: time
+ raw table: HuffCode2.m
+ built by : FH 00-02-04 */
+
+ extern const Char bookSbrNoiseLevel11T[62][2] =
+ {
+ { -64, 1 }, { -63, 2 }, { -65, 3 }, { -66, 4 },
+ { -62, 5 }, { -67, 6 }, { 7, 8 }, { -61, -68 },
+ { 9, 30 }, { 10, 15 }, { -60, 11 }, { -69, 12 },
+ { 13, 14 }, { -59, -53 }, { -95, -94 }, { 16, 23 },
+ { 17, 20 }, { 18, 19 }, { -93, -92 }, { -91, -90 },
+ { 21, 22 }, { -89, -88 }, { -87, -86 }, { 24, 27 },
+ { 25, 26 }, { -85, -84 }, { -83, -82 }, { 28, 29 },
+ { -81, -80 }, { -79, -78 }, { 31, 46 }, { 32, 39 },
+ { 33, 36 }, { 34, 35 }, { -77, -76 }, { -75, -74 },
+ { 37, 38 }, { -73, -72 }, { -71, -70 }, { 40, 43 },
+ { 41, 42 }, { -58, -57 }, { -56, -55 }, { 44, 45 },
+ { -54, -52 }, { -51, -50 }, { 47, 54 }, { 48, 51 },
+ { 49, 50 }, { -49, -48 }, { -47, -46 }, { 52, 53 },
+ { -45, -44 }, { -43, -42 }, { 55, 58 }, { 56, 57 },
+ { -41, -40 }, { -39, -38 }, { 59, 60 }, { -37, -36 },
+ { -35, 61 }, { -34, -33 }
+ };
+
+ /*******************************************************************************/
+ /* table : noise balance, 3.0 dB */
+ /* theor range : [-24,24], CODE_BOOK_SCF_LAV = 24 */
+ /* implem range: same but mapped to [-12,12], CODE_BOOK_SCF_LAV_BALANCE11 = 12 */
+ /* raw stats : noiseBalance_11 KK 00-02-03 */
+ /*******************************************************************************/
+
+ /* direction: time
+ raw table: HuffCode3C.m/noiseBalance_11.mat/v_hALB
+ built by : FH 01-05-15 */
+
+ extern const Char bookSbrNoiseBalance11T[24][2] =
+ {
+ { -64, 1 }, { -65, 2 }, { -63, 3 }, { 4, 9 },
+ { -66, 5 }, { -62, 6 }, { 7, 8 }, { -76, -75 },
+ { -74, -73 }, { 10, 17 }, { 11, 14 }, { 12, 13 },
+ { -72, -71 }, { -70, -69 }, { 15, 16 }, { -68, -67 },
+ { -61, -60 }, { 18, 21 }, { 19, 20 }, { -59, -58 },
+ { -57, -56 }, { 22, 23 }, { -55, -54 }, { -53, -52 }
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_code_book_envlevel.h b/media/libstagefright/codecs/aacdec/sbr_code_book_envlevel.h
new file mode 100644
index 0000000..3df0531
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_code_book_envlevel.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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: sbr_code_book_envlevel.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ this file declares the scalefactor bands for all sampling rates
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_CODE_BOOK_ENVLEVEL_H
+#define SBR_CODE_BOOK_ENVLEVEL_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Char bookSbrEnvLevel10T[120][2];
+ extern const Char bookSbrEnvLevel10F[120][2];
+ extern const Char bookSbrEnvBalance10T[48][2];
+ extern const Char bookSbrEnvBalance10F[48][2];
+ extern const Char bookSbrEnvLevel11T[62][2];
+ extern const Char bookSbrEnvLevel11F[62][2];
+ extern const Char bookSbrEnvBalance11T[24][2];
+ extern const Char bookSbrEnvBalance11F[24][2];
+ extern const Char bookSbrNoiseLevel11T[62][2];
+ extern const Char bookSbrNoiseBalance11T[24][2];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_constants.h b/media/libstagefright/codecs/aacdec/sbr_constants.h
new file mode 100644
index 0000000..d54a699
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_constants.h
@@ -0,0 +1,210 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_constants.h
+ Funtions:
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_CONSTANTS_H
+#define SBR_CONSTANTS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+
+#define SBR_AMP_RES_1_5 0
+#define SBR_AMP_RES_3_0 1
+
+#define MAX_NOISE_ENVELOPES 2
+#define MAX_NOISE_COEFFS 5
+#define MAX_NUM_NOISE_VALUES (MAX_NOISE_ENVELOPES * MAX_NOISE_COEFFS)
+
+#define MAX_ENVELOPES 5
+#define MAX_FREQ_COEFFS 58
+#define MAX_NUM_ENVELOPE_VALUES (MAX_ENVELOPES * MAX_FREQ_COEFFS)
+
+#define MAX_NUM_CHANNELS 2
+#define NOISE_FLOOR_OFFSET 6
+#define NOISE_FLOOR_OFFSET_PLUS_1 7
+
+#define LOW_RES 0
+#define HIGH_RES 1
+
+#define LO 0
+#define HI 1
+
+#define TIME 1
+#define FREQ 0
+
+#define LENGTH_FRAME_INFO 35
+
+#define SI_SBR_CRC_BITS 10
+
+#define SBR_FREQ_SCALE_DEFAULT 2
+#define SBR_ALTER_SCALE_DEFAULT 1
+#define SBR_NOISE_BANDS_DEFAULT 2
+
+#define SBR_LIMITER_BANDS_DEFAULT 2
+#define SBR_LIMITER_GAINS_DEFAULT 2
+#define SBR_INTERPOL_FREQ_DEFAULT 1
+#define SBR_SMOOTHING_LENGTH_DEFAULT 1
+
+/* header */
+#define SI_SBR_AMP_RES_BITS 1
+#define SI_SBR_START_FREQ_BITS 4
+#define SI_SBR_STOP_FREQ_BITS 4
+#define SI_SBR_XOVER_BAND_BITS 3
+#define SI_SBR_RESERVED_BITS_HDR 2
+#define SI_SBR_DATA_EXTRA_BITS 1
+#define SI_SBR_HEADER_EXTRA_1_BITS 1
+#define SI_SBR_HEADER_EXTRA_2_BITS 1
+
+#define SI_SBR_FREQ_SCALE_BITS 2
+#define SI_SBR_ALTER_SCALE_BITS 1
+#define SI_SBR_NOISE_BANDS_BITS 2
+
+#define SI_SBR_LIMITER_BANDS_BITS 2
+#define SI_SBR_LIMITER_GAINS_BITS 2
+#define SI_SBR_INTERPOL_FREQ_BITS 1
+#define SI_SBR_SMOOTHING_LENGTH_BITS 1
+
+
+/* data */
+#define SI_SBR_RESERVED_PRESENT 1
+#define SI_SBR_RESERVED_BITS_DATA 4
+
+#define SI_SBR_COUPLING_BITS 1
+
+#define SI_SBR_INVF_MODE_BITS 2
+
+#define SI_SBR_EXTENDED_DATA_BITS 1
+#define SI_SBR_EXTENSION_SIZE_BITS 4
+#define SI_SBR_EXTENSION_ESC_COUNT_BITS 8
+#define SI_SBR_EXTENSION_ID_BITS 2
+
+#define SI_SBR_NOISE_MODE_BITS 1
+#define SI_SBR_DOMAIN_BITS 1
+
+#define SI_SBR_START_ENV_BITS_AMP_RES_3_0 6
+#define SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_3_0 5
+#define SI_SBR_START_NOISE_BITS_AMP_RES_3_0 5
+#define SI_SBR_START_NOISE_BITS_BALANCE_AMP_RES_3_0 5
+
+#define SI_SBR_START_ENV_BITS_AMP_RES_1_5 7
+#define SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_1_5 6
+
+
+#define SBR_CLA_BITS 2
+#define SBR_ABS_BITS 2
+#define SBR_RES_BITS 1
+#define SBR_REL_BITS 2
+#define SBR_ENV_BITS 2
+#define SBR_NUM_BITS 2
+
+
+#define FIXFIX 0
+#define FIXVAR 1
+#define VARFIX 2
+#define VARVAR 3
+
+
+#define LEN_EX_TYPE (4)
+#define LEN_NIBBLE (4)
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_crc_check.cpp b/media/libstagefright/codecs/aacdec/sbr_crc_check.cpp
new file mode 100644
index 0000000..3bb4398
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_crc_check.cpp
@@ -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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Filename: sbr_crc_check.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_crc_check.h"
+#include "s_crc_buffer.h"
+#include "buf_getbits.h"
+#include "sbr_constants.h"
+#include "check_crc.h"
+
+
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+const unsigned short MAXCRCSTEP = 16;
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int32 sbr_crc_check(BIT_BUFFER * hBitBuf, UInt32 NrBits)
+{
+ Int32 crcResult = 1;
+ BIT_BUFFER BitBufferCRC;
+ UInt32 NrCrcBits;
+
+ UInt32 crcCheckSum;
+
+ Int32 i;
+ CRC_BUFFER CrcBuf;
+ UInt32 bValue;
+ Int32 CrcStep;
+ Int32 CrcNrBitsRest;
+
+ crcCheckSum = buf_getbits(hBitBuf, SI_SBR_CRC_BITS);
+
+
+ /*
+ * Copy Bit buffer State
+ */
+
+ BitBufferCRC.char_ptr = hBitBuf->char_ptr;
+ BitBufferCRC.buffer_word = hBitBuf->buffer_word;
+ BitBufferCRC.buffered_bits = hBitBuf->buffered_bits;
+ BitBufferCRC.nrBitsRead = hBitBuf->nrBitsRead;
+ BitBufferCRC.bufferLen = hBitBuf->bufferLen;
+
+
+ NrCrcBits = min(NrBits, BitBufferCRC.bufferLen - BitBufferCRC.nrBitsRead);
+
+
+ CrcStep = NrCrcBits / MAXCRCSTEP;
+ CrcNrBitsRest = (NrCrcBits - CrcStep * MAXCRCSTEP);
+
+ CrcBuf.crcState = CRCSTART;
+ CrcBuf.crcMask = CRCMASK;
+ CrcBuf.crcPoly = CRCPOLY;
+
+ for (i = 0; i < CrcStep; i++)
+ {
+ bValue = buf_getbits(&BitBufferCRC, MAXCRCSTEP);
+ check_crc(&CrcBuf, bValue, MAXCRCSTEP);
+ }
+
+ bValue = buf_getbits(&BitBufferCRC, CrcNrBitsRest);
+ check_crc(&CrcBuf, bValue, CrcNrBitsRest);
+
+ if ((UInt32)(CrcBuf.crcState & CRCRANGE) != crcCheckSum)
+ {
+ crcResult = 0;
+ }
+
+ return (crcResult);
+}
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_crc_check.h b/media/libstagefright/codecs/aacdec/sbr_crc_check.h
new file mode 100644
index 0000000..9e6b1be
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_crc_check.h
@@ -0,0 +1,98 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_crc_check.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_CRC_CHECK_H
+#define SBR_CRC_CHECK_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bit_buffer.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define CRCPOLY 0x0233
+#define CRCMASK 0x0200
+#define CRCSTART 0x0000
+#define CRCRANGE 0x03FF
+
+#define SBR_EXTENSION 13 /* 1101 */
+#define SBR_EXTENSION_CRC 14 /* 1110 */
+
+
+
+#ifndef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+Int32 sbr_crc_check(BIT_BUFFER * hBitBuf,
+ UInt32 NrBits);
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_create_limiter_bands.cpp b/media/libstagefright/codecs/aacdec/sbr_create_limiter_bands.cpp
new file mode 100644
index 0000000..9472ffc
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_create_limiter_bands.cpp
@@ -0,0 +1,253 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_create_limiter_bands.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_create_limiter_bands.h"
+#include "shellsort.h"
+#include "s_patch.h"
+#include "pv_log2.h"
+
+#include "fxp_mul32.h"
+
+#define R_SHIFT 29
+#define Q_fmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void sbr_create_limiter_bands(Int32 limSbc[][13],
+ Int32 *gateMode,
+ Int *freqTable,
+ struct PATCH Patch,
+ const Int32 noBands)
+{
+ Int32 i;
+ Int32 j;
+ Int32 k;
+ Int isPatchBorder[2];
+ Int32 patchBorders[MAX_NUM_PATCHES + 1];
+ Int32 workLimiterBandTable[32 + MAX_NUM_PATCHES + 1];
+
+ Int32 nOctaves;
+ const Int32 limiterBandsPerOctave[4] =
+ {Q_fmt(0.0F), Q_fmt(1.2F),
+ Q_fmt(2.0F), Q_fmt(3.0F)
+ };
+
+ Int32 tmp_q1;
+
+ Int32 noPatches = Patch.noOfPatches;
+ Int32 lowSubband = freqTable[0];
+ Int32 highSubband = freqTable[noBands];
+
+
+ for (i = 0; i < noPatches; i++)
+ {
+ patchBorders[i] = Patch.targetStartBand[i] - lowSubband;
+ }
+ patchBorders[i] = highSubband - lowSubband;
+
+ /* First band: 1 limiter band. */
+ limSbc[0][0] = freqTable[0] - lowSubband;
+ limSbc[0][1] = freqTable[noBands] - lowSubband;
+ gateMode[0] = 1;
+
+ /* Next three bands: 1.2, 2, 3 limiter bands/octave plus bandborders at patchborders. */
+ for (i = 1; i < 4; i++)
+ {
+
+ for (k = 0; k <= noBands; k++)
+ {
+ workLimiterBandTable[k] = freqTable[k] - lowSubband;
+ }
+
+ for (k = 1; k < noPatches; k++)
+ {
+ workLimiterBandTable[noBands+k] = patchBorders[k];
+ }
+
+ gateMode[i] = noBands + noPatches - 1;
+ shellsort(workLimiterBandTable, gateMode[i] + 1);
+
+ for (j = 1; j <= gateMode[i]; j++)
+ {
+ tmp_q1 = ((workLimiterBandTable[j] + lowSubband) << 20) / (workLimiterBandTable[j-1] + lowSubband);
+
+ nOctaves = pv_log2(tmp_q1);
+
+ tmp_q1 = fxp_mul32_Q20(nOctaves, limiterBandsPerOctave[i]);
+ if (tmp_q1 < Q_fmt(0.49))
+ {
+ if (workLimiterBandTable[j] == workLimiterBandTable[j-1])
+ {
+ workLimiterBandTable[j] = highSubband;
+ shellsort(workLimiterBandTable, gateMode[i] + 1);
+ gateMode[i]--;
+ j--;
+ continue;
+ }
+
+ isPatchBorder[0] = isPatchBorder[1] = 0;
+
+ for (k = 0; k <= noPatches; k++)
+ {
+ if (workLimiterBandTable[j-1] == patchBorders[k])
+ {
+ isPatchBorder[0] = 1;
+ break;
+ }
+ }
+
+ for (k = 0; k <= noPatches; k++)
+ {
+ if (workLimiterBandTable[j] == patchBorders[k])
+ {
+ isPatchBorder[1] = 1;
+ break;
+ }
+ }
+
+ if (!isPatchBorder[1])
+ {
+ workLimiterBandTable[j] = highSubband;
+ shellsort(workLimiterBandTable, gateMode[i] + 1);
+ gateMode[i]--;
+ j--;
+ }
+ else if (!isPatchBorder[0])
+ {
+ workLimiterBandTable[j-1] = highSubband;
+ shellsort(workLimiterBandTable, gateMode[i] + 1);
+ gateMode[i]--;
+ j--;
+ }
+ }
+ }
+ for (k = 0; k <= gateMode[i]; k++)
+ {
+ limSbc[i][k] = workLimiterBandTable[k];
+ }
+ }
+}
+
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_create_limiter_bands.h b/media/libstagefright/codecs/aacdec/sbr_create_limiter_bands.h
new file mode 100644
index 0000000..7a53944
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_create_limiter_bands.h
@@ -0,0 +1,95 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_create_limiter_bands.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_CREATE_LIMITER_BANDS_H
+#define SBR_CREATE_LIMITER_BANDS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "sbr_generate_high_freq.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void sbr_create_limiter_bands(Int32 limSbc[4][12 + 1],
+ Int32 gateMode[4],
+ Int *freqTable,
+ struct PATCH Patch,
+ const Int32 noBands);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_dec.cpp b/media/libstagefright/codecs/aacdec/sbr_dec.cpp
new file mode 100644
index 0000000..8519b17
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_dec.cpp
@@ -0,0 +1,960 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2010 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: sbr_dec.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ sbr decoder core function
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#ifdef AAC_PLUS
+
+
+#include "s_sbr_frame_data.h"
+#include "calc_sbr_synfilterbank.h"
+#include "calc_sbr_anafilterbank.h"
+#include "calc_sbr_envelope.h"
+#include "sbr_generate_high_freq.h"
+#include "sbr_dec.h"
+#include "decode_noise_floorlevels.h"
+#include "aac_mem_funcs.h"
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+#ifdef PARAMETRICSTEREO
+
+#include "ps_applied.h"
+#include "ps_init_stereo_mixing.h"
+
+#endif
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void sbr_dec(Int16 *inPcmData,
+ Int16 *ftimeOutPtr,
+ SBR_FRAME_DATA * hFrameData,
+ int32_t applyProcessing,
+ SBR_DEC *sbrDec,
+#ifdef HQ_SBR
+#ifdef PARAMETRICSTEREO
+ Int16 * ftimeOutPtrPS,
+ HANDLE_PS_DEC hParametricStereoDec,
+#endif
+#endif
+ tDec_Int_File *pVars)
+{
+ int32_t i;
+ int32_t j;
+ int32_t m;
+
+ int32_t *frameInfo = hFrameData->frameInfo;
+ Int num_qmf_bands;
+
+#ifdef HQ_SBR
+#ifdef PARAMETRICSTEREO
+
+ int32_t env;
+
+ int32_t *qmf_PS_generated_Real;
+ int32_t *qmf_PS_generated_Imag;
+
+ int32_t *Sr_x;
+ int32_t *Si_x;
+
+
+#endif
+#endif
+
+ int32_t(*scratch_mem)[64];
+ Int16 *circular_buffer_s;
+
+ int32_t k;
+ int32_t *Sr;
+ int32_t *Si;
+ int32_t *ptr_tmp1;
+ int32_t *ptr_tmp2;
+ scratch_mem = pVars->scratch.scratch_mem;
+
+
+ if (applyProcessing)
+ {
+ num_qmf_bands = sbrDec->lowSubband;
+ }
+ else
+ {
+ num_qmf_bands = 32; /* becomes a resampler by 2 */
+ }
+
+ /* -------------------------------------------------- */
+ /*
+ * Re-Load Buffers
+ */
+ pv_memmove(&hFrameData->sbrQmfBufferReal[0],
+ &hFrameData->HistsbrQmfBufferReal[0],
+ 6*SBR_NUM_BANDS*sizeof(*hFrameData->sbrQmfBufferReal));
+#ifdef HQ_SBR
+
+
+ if (sbrDec->LC_aacP_DecoderFlag == OFF)
+ {
+ pv_memmove(&hFrameData->sbrQmfBufferImag[0],
+ &hFrameData->HistsbrQmfBufferImag[0],
+ 6*SBR_NUM_BANDS*sizeof(*hFrameData->sbrQmfBufferImag));
+ }
+#endif
+ /* -------------------------------------------------- */
+
+
+ /*
+ * low band codec signal subband filtering
+ */
+
+ for (i = 0; i < 32; i++)
+ {
+
+ if (sbrDec->LC_aacP_DecoderFlag == ON)
+ {
+
+ calc_sbr_anafilterbank_LC(hFrameData->codecQmfBufferReal[sbrDec->bufWriteOffs + i],
+ &inPcmData[319] + (i << 5),
+ scratch_mem,
+ num_qmf_bands);
+
+ }
+#ifdef HQ_SBR
+ else
+ {
+
+ calc_sbr_anafilterbank(hFrameData->codecQmfBufferReal[sbrDec->bufWriteOffs + i],
+ hFrameData->codecQmfBufferImag[sbrDec->bufWriteOffs + i],
+ &inPcmData[319] + (i << 5),
+ scratch_mem,
+ num_qmf_bands);
+ }
+#endif
+
+ }
+
+ if (pVars->ltp_buffer_state)
+ {
+ pv_memcpy(&inPcmData[-1024-288], &inPcmData[1024], 288*sizeof(*inPcmData));
+ }
+ else
+ {
+ pv_memcpy(&inPcmData[1024 + 288], &inPcmData[1024], 288*sizeof(*inPcmData));
+ }
+
+
+ if (applyProcessing)
+ {
+
+ /*
+ * Inverse filtering of lowband + HF generation
+ */
+
+ if (sbrDec->LC_aacP_DecoderFlag == ON)
+ {
+
+ sbr_generate_high_freq((int32_t(*)[32])(hFrameData->codecQmfBufferReal + sbrDec->bufReadOffs),
+ NULL,
+ (int32_t *)(hFrameData->sbrQmfBufferReal),
+ NULL,
+ hFrameData->sbr_invf_mode,
+ hFrameData->sbr_invf_mode_prev,
+ &(sbrDec->FreqBandTableNoise[1]),
+ sbrDec->NoNoiseBands,
+ sbrDec->lowSubband,
+ sbrDec->V_k_master,
+ sbrDec->Num_Master,
+ sbrDec->outSampleRate,
+ frameInfo,
+ hFrameData->degreeAlias,
+ scratch_mem,
+ hFrameData->BwVector,/* */
+ hFrameData->BwVectorOld,
+ &(sbrDec->Patch),
+ sbrDec->LC_aacP_DecoderFlag,
+ &(sbrDec->highSubband));
+
+
+ /*
+ * Adjust envelope of current frame.
+ */
+
+ calc_sbr_envelope(hFrameData,
+ (int32_t *)(hFrameData->sbrQmfBufferReal),
+ NULL,
+ sbrDec->FreqBandTable,
+ sbrDec->NSfb,
+ sbrDec->FreqBandTableNoise,
+ sbrDec->NoNoiseBands,
+ hFrameData->reset_flag,
+ hFrameData->degreeAlias,
+ &(hFrameData->harm_index),
+ &(hFrameData->phase_index),
+ hFrameData->hFp,
+ &(hFrameData->sUp),
+ sbrDec->limSbc,
+ sbrDec->gateMode,
+#ifdef HQ_SBR
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+#endif
+ scratch_mem,
+ sbrDec->Patch,
+ sbrDec->sqrt_cache,
+ sbrDec->LC_aacP_DecoderFlag);
+ }
+#ifdef HQ_SBR
+ else
+ {
+
+ sbr_generate_high_freq((int32_t(*)[32])(hFrameData->codecQmfBufferReal + sbrDec->bufReadOffs),
+ (int32_t(*)[32])(hFrameData->codecQmfBufferImag + sbrDec->bufReadOffs),
+ (int32_t *)(hFrameData->sbrQmfBufferReal),
+ (int32_t *)(hFrameData->sbrQmfBufferImag),
+ hFrameData->sbr_invf_mode,
+ hFrameData->sbr_invf_mode_prev,
+ &(sbrDec->FreqBandTableNoise[1]),
+ sbrDec->NoNoiseBands,
+ sbrDec->lowSubband,
+ sbrDec->V_k_master,
+ sbrDec->Num_Master,
+ sbrDec->outSampleRate,
+ frameInfo,
+ NULL,
+ scratch_mem,
+ hFrameData->BwVector,
+ hFrameData->BwVectorOld,
+ &(sbrDec->Patch),
+ sbrDec->LC_aacP_DecoderFlag,
+ &(sbrDec->highSubband));
+
+ /*
+ * Adjust envelope of current frame.
+ */
+
+ calc_sbr_envelope(hFrameData,
+ (int32_t *)(hFrameData->sbrQmfBufferReal),
+ (int32_t *)(hFrameData->sbrQmfBufferImag),
+ sbrDec->FreqBandTable,
+ sbrDec->NSfb,
+ sbrDec->FreqBandTableNoise,
+ sbrDec->NoNoiseBands,
+ hFrameData->reset_flag,
+ NULL,
+ &(hFrameData->harm_index),
+ &(hFrameData->phase_index),
+ hFrameData->hFp,
+ &(hFrameData->sUp),
+ sbrDec->limSbc,
+ sbrDec->gateMode,
+ hFrameData->fBuf_man,
+ hFrameData->fBuf_exp,
+ hFrameData->fBufN_man,
+ hFrameData->fBufN_exp,
+ scratch_mem,
+ sbrDec->Patch,
+ sbrDec->sqrt_cache,
+ sbrDec->LC_aacP_DecoderFlag);
+
+ }
+#endif
+
+
+ }
+ else /* else for applyProcessing */
+ {
+ /* no sbr, set high band buffers to zero */
+
+ for (i = 0; i < SBR_NUM_COLUMNS; i++)
+ {
+ pv_memset((void *)&hFrameData->sbrQmfBufferReal[i*SBR_NUM_BANDS],
+ 0,
+ SBR_NUM_BANDS*sizeof(*hFrameData->sbrQmfBufferReal));
+
+#ifdef HQ_SBR
+ pv_memset((void *)&hFrameData->sbrQmfBufferImag[i*SBR_NUM_BANDS],
+ 0,
+ SBR_NUM_BANDS*sizeof(*hFrameData->sbrQmfBufferImag));
+
+#endif
+ }
+
+ }
+
+
+ /*
+ * Synthesis subband filtering.
+ */
+
+#ifdef HQ_SBR
+
+#ifdef PARAMETRICSTEREO
+
+
+ /*
+ * psPresentFlag set implies hParametricStereoDec !=NULL, second condition is
+ * is just here to prevent CodeSonar warnings.
+ */
+ if ((pVars->mc_info.psPresentFlag) && (applyProcessing) &&
+ (hParametricStereoDec != NULL))
+ {
+
+ /*
+ * qmfBufferReal uses the rigth aac channel ( perChan[1] is not used)
+ * followed by the buffer fxpCoef[2][2048] which makes a total of
+ * 2349 + 2048*2 = 6445
+ * These 2 matrices (qmfBufferReal & qmfBufferImag) are
+ * [2][38][64] == 4864 int32_t
+ */
+
+
+ tDec_Int_Chan *tmpx = &pVars->perChan[1];
+ /*
+ * dereferencing type-punned pointer avoid
+ * breaking strict-aliasing rules
+ */
+ int32_t *tmp = (int32_t *)tmpx;
+ hParametricStereoDec->qmfBufferReal = (int32_t(*)[64]) tmp;
+
+ tmp = (int32_t *) & hParametricStereoDec->qmfBufferReal[38][0];
+ hParametricStereoDec->qmfBufferImag = (int32_t(*)[64]) tmp;
+
+ for (i = 0; i < 32; i++)
+ {
+ Int xoverBand;
+
+ if (i < ((hFrameData->frameInfo[1]) << 1))
+ {
+ xoverBand = sbrDec->prevLowSubband;
+ }
+ else
+ {
+ xoverBand = sbrDec->lowSubband;
+ }
+
+ if (xoverBand > sbrDec->highSubband)
+ {
+ /*
+ * error condition, default to upsampling mode
+ * and make sure that the number of bands for xover does
+ * not exceed the number of high freq bands.
+ */
+ xoverBand = (sbrDec->highSubband > 32)? 32: sbrDec->highSubband;
+ }
+
+ m = sbrDec->bufReadOffs + i; /* 2 + i */
+
+ Sr_x = hParametricStereoDec->qmfBufferReal[i];
+ Si_x = hParametricStereoDec->qmfBufferImag[i];
+
+
+
+ for (int32_t j = 0; j < xoverBand; j++)
+ {
+ Sr_x[j] = shft_lft_1(hFrameData->codecQmfBufferReal[m][j]);
+ Si_x[j] = shft_lft_1(hFrameData->codecQmfBufferImag[m][j]);
+ }
+
+
+
+
+ pv_memcpy(&Sr_x[xoverBand],
+ &hFrameData->sbrQmfBufferReal[i*SBR_NUM_BANDS],
+ (sbrDec->highSubband - xoverBand)*sizeof(*Sr_x));
+
+ pv_memcpy(&Si_x[xoverBand],
+ &hFrameData->sbrQmfBufferImag[i*SBR_NUM_BANDS],
+ (sbrDec->highSubband - xoverBand)*sizeof(*Si_x));
+
+ pv_memset((void *)&Sr_x[sbrDec->highSubband],
+ 0,
+ (64 - sbrDec->highSubband)*sizeof(*Sr_x));
+
+ pv_memset((void *)&Si_x[sbrDec->highSubband],
+ 0,
+ (64 - sbrDec->highSubband)*sizeof(*Si_x));
+
+
+ }
+
+ for (i = 32; i < 32 + 6; i++)
+ {
+ m = sbrDec->bufReadOffs + i; /* 2 + i */
+
+ for (int32_t j = 0; j < 5; j++)
+ {
+ hParametricStereoDec->qmfBufferReal[i][j] = shft_lft_1(hFrameData->codecQmfBufferReal[m][j]);
+ hParametricStereoDec->qmfBufferImag[i][j] = shft_lft_1(hFrameData->codecQmfBufferImag[m][j]);
+ }
+
+ }
+
+
+ /*
+ * Update Buffers
+ */
+ for (i = 0; i < sbrDec->bufWriteOffs; i++) /* sbrDec->bufWriteOffs set to 8 and unchanged */
+ {
+ j = sbrDec->noCols + i; /* sbrDec->noCols set to 32 and unchanged */
+
+ pv_memmove(hFrameData->codecQmfBufferReal[i], /* to */
+ hFrameData->codecQmfBufferReal[j], /* from */
+ sizeof(*hFrameData->codecQmfBufferReal[i]) << 5);
+
+ pv_memmove(hFrameData->codecQmfBufferImag[i],
+ hFrameData->codecQmfBufferImag[j],
+ sizeof(*hFrameData->codecQmfBufferImag[i]) << 5);
+ }
+
+
+ pv_memmove(&hFrameData->HistsbrQmfBufferReal[0],
+ &hFrameData->sbrQmfBufferReal[32*SBR_NUM_BANDS],
+ 6*SBR_NUM_BANDS*sizeof(*hFrameData->sbrQmfBufferReal));
+
+ pv_memmove(&hFrameData->HistsbrQmfBufferImag[0],
+ &hFrameData->sbrQmfBufferImag[32*SBR_NUM_BANDS],
+ 6*SBR_NUM_BANDS*sizeof(*hFrameData->sbrQmfBufferImag));
+
+
+ /*
+ * Needs whole QMF matrix formed before applying
+ * Parametric stereo processing.
+ */
+
+ qmf_PS_generated_Real = scratch_mem[0];
+ qmf_PS_generated_Imag = scratch_mem[1];
+ env = 0;
+
+ /*
+ * Set circular buffer for Left channel
+ */
+
+ circular_buffer_s = (Int16 *)scratch_mem[7];
+
+
+ if (pVars->mc_info.bDownSampledSbr)
+ {
+ pv_memmove(&circular_buffer_s[2048],
+ hFrameData->V,
+ 640*sizeof(*circular_buffer_s));
+ }
+ else
+ {
+ pv_memmove(&circular_buffer_s[4096],
+ hFrameData->V,
+ 1152*sizeof(*circular_buffer_s));
+
+ }
+
+
+ /*
+ * Set Circular buffer for PS hybrid analysis
+ */
+
+ int32_t *pt_temp = &scratch_mem[2][32];
+
+ for (i = 0, j = 0; i < 3; i++)
+ {
+
+ pv_memmove(&pt_temp[ j],
+ hParametricStereoDec->hHybrid->mQmfBufferReal[i],
+ HYBRID_FILTER_LENGTH_m_1*sizeof(*hParametricStereoDec->hHybrid->mQmfBufferReal));
+ pv_memmove(&pt_temp[ j + 44],
+ hParametricStereoDec->hHybrid->mQmfBufferImag[i],
+ HYBRID_FILTER_LENGTH_m_1*sizeof(*hParametricStereoDec->hHybrid->mQmfBufferImag));
+ j += 88;
+ }
+
+
+ pv_memset((void *)&qmf_PS_generated_Real[hParametricStereoDec->usb],
+ 0,
+ (64 - hParametricStereoDec->usb)*sizeof(*qmf_PS_generated_Real));
+
+ pv_memset((void *)&qmf_PS_generated_Imag[hParametricStereoDec->usb],
+ 0,
+ (64 - hParametricStereoDec->usb)*sizeof(*qmf_PS_generated_Imag));
+
+
+ for (i = 0; i < 32; i++)
+ {
+ if (i == (Int)hParametricStereoDec-> aEnvStartStop[env])
+ {
+ ps_init_stereo_mixing(hParametricStereoDec, env, sbrDec->highSubband);
+ env++;
+ }
+
+
+ ps_applied(hParametricStereoDec,
+ &hParametricStereoDec->qmfBufferReal[i],
+ &hParametricStereoDec->qmfBufferImag[i],
+ qmf_PS_generated_Real,
+ qmf_PS_generated_Imag,
+ scratch_mem[2],
+ i);
+
+ /* Create time samples for regular mono channel */
+
+ if (pVars->mc_info.bDownSampledSbr)
+ {
+ calc_sbr_synfilterbank(hParametricStereoDec->qmfBufferReal[i], /* realSamples */
+ hParametricStereoDec->qmfBufferImag[i], /* imagSamples */
+ ftimeOutPtr + (i << 6),
+ &circular_buffer_s[1984 - (i<<6)],
+ pVars->mc_info.bDownSampledSbr);
+ }
+ else
+ {
+ calc_sbr_synfilterbank(hParametricStereoDec->qmfBufferReal[i], /* realSamples */
+ hParametricStereoDec->qmfBufferImag[i], /* imagSamples */
+ ftimeOutPtr + (i << 7),
+ &circular_buffer_s[3968 - (i<<7)],
+ pVars->mc_info.bDownSampledSbr);
+
+ }
+
+ pv_memmove(hParametricStereoDec->qmfBufferReal[i], qmf_PS_generated_Real, 64*sizeof(*qmf_PS_generated_Real));
+ pv_memmove(hParametricStereoDec->qmfBufferImag[i], qmf_PS_generated_Imag, 64*sizeof(*qmf_PS_generated_Real));
+
+ }
+
+
+ /*
+ * Save Circular buffer history used on PS hybrid analysis
+ */
+
+
+ pt_temp = &scratch_mem[2][64];
+
+ for (i = 0, j = 0; i < 3; i++)
+ {
+ pv_memmove(hParametricStereoDec->hHybrid->mQmfBufferReal[i],
+ &pt_temp[ j],
+ HYBRID_FILTER_LENGTH_m_1*sizeof(*hParametricStereoDec->hHybrid->mQmfBufferReal));
+
+ pv_memmove(hParametricStereoDec->hHybrid->mQmfBufferImag[i],
+ &pt_temp[ j + 44],
+ HYBRID_FILTER_LENGTH_m_1*sizeof(*hParametricStereoDec->hHybrid->mQmfBufferImag));
+
+ j += 88;
+ }
+
+
+ pv_memmove(hFrameData->V, &circular_buffer_s[0], 1152*sizeof(*circular_buffer_s));
+
+ /*
+ * Set circular buffer for Right channel
+ */
+
+ circular_buffer_s = (Int16 *)scratch_mem[5];
+
+ if (pVars->mc_info.bDownSampledSbr)
+ {
+ pv_memmove(&circular_buffer_s[2048],
+ (int32_t *)hParametricStereoDec->R_ch_qmf_filter_history,
+ 640*sizeof(*circular_buffer_s));
+ }
+ else
+ {
+ pv_memmove(&circular_buffer_s[4096],
+ (int32_t *)hParametricStereoDec->R_ch_qmf_filter_history,
+ 1152*sizeof(*circular_buffer_s));
+
+ }
+
+
+ for (i = 0; i < 32; i++)
+ {
+ if (pVars->mc_info.bDownSampledSbr)
+ {
+
+ calc_sbr_synfilterbank(hParametricStereoDec->qmfBufferReal[i], /* realSamples */
+ hParametricStereoDec->qmfBufferImag[i], /* imagSamples */
+ ftimeOutPtrPS + (i << 6),
+ &circular_buffer_s[1984 - (i<<6)],
+ pVars->mc_info.bDownSampledSbr);
+ }
+ else
+ {
+ calc_sbr_synfilterbank(hParametricStereoDec->qmfBufferReal[i], /* realSamples */
+ hParametricStereoDec->qmfBufferImag[i], /* imagSamples */
+ ftimeOutPtrPS + (i << 7),
+ &circular_buffer_s[3968 - (i<<7)],
+ pVars->mc_info.bDownSampledSbr);
+ }
+
+ }
+
+ if (pVars->mc_info.bDownSampledSbr)
+ {
+ pv_memmove((int32_t *)hParametricStereoDec->R_ch_qmf_filter_history, &circular_buffer_s[0], 640*sizeof(*circular_buffer_s));
+ }
+ else
+ {
+ pv_memmove((int32_t *)hParametricStereoDec->R_ch_qmf_filter_history, &circular_buffer_s[0], 1152*sizeof(*circular_buffer_s));
+ }
+
+
+
+
+
+ }
+ else /* else -- sbrEnablePS */
+ {
+
+#endif /* PARAMETRICSTEREO */
+#endif /* HQ_SBR */
+
+ /*
+ * Use shared aac memory as continuous buffer
+ */
+
+
+ Sr = scratch_mem[0];
+ Si = scratch_mem[1];
+
+ circular_buffer_s = (Int16*)scratch_mem[2];
+
+ if (pVars->mc_info.bDownSampledSbr)
+ {
+
+ pv_memmove(&circular_buffer_s[2048],
+ hFrameData->V,
+ 640*sizeof(*circular_buffer_s));
+ }
+ else
+ {
+ pv_memmove(&circular_buffer_s[4096],
+ hFrameData->V,
+ 1152*sizeof(*circular_buffer_s));
+ }
+
+ for (i = 0; i < 32; i++)
+ {
+ Int xoverBand;
+
+ if (applyProcessing)
+ {
+ if (i < ((hFrameData->frameInfo[1]) << 1))
+ {
+ xoverBand = sbrDec->prevLowSubband;
+
+ }
+ else
+ {
+ xoverBand = sbrDec->lowSubband;
+ }
+
+ if (xoverBand > sbrDec->highSubband)
+ {
+ /*
+ * error condition, default to upsampling mode
+ * and make sure that the number of bands for xover does
+ * not exceed the number of high freq bands.
+ */
+ xoverBand = (sbrDec->highSubband > 32)? 32: sbrDec->highSubband;
+ }
+ }
+ else
+ {
+ xoverBand = 32;
+ sbrDec->highSubband = 32;
+ }
+
+
+ m = sbrDec->bufReadOffs + i; /* sbrDec->bufReadOffs == 2 */
+
+
+ ptr_tmp1 = (hFrameData->codecQmfBufferReal[m]);
+ ptr_tmp2 = Sr;
+
+ if (sbrDec->LC_aacP_DecoderFlag == ON)
+ {
+
+ for (k = (xoverBand >> 1); k != 0; k--)
+ {
+ *(ptr_tmp2++) = (*(ptr_tmp1++)) >> 9;
+ *(ptr_tmp2++) = (*(ptr_tmp1++)) >> 9;
+ }
+ if (xoverBand & 1)
+ {
+ *(ptr_tmp2++) = (*(ptr_tmp1)) >> 9;
+ }
+
+ ptr_tmp1 = &hFrameData->sbrQmfBufferReal[i*SBR_NUM_BANDS];
+
+
+ for (k = xoverBand; k < sbrDec->highSubband; k++)
+ {
+ *(ptr_tmp2++) = (*(ptr_tmp1++)) << 1;
+ }
+
+ pv_memset((void *)ptr_tmp2,
+ 0,
+ (64 - sbrDec->highSubband)*sizeof(*ptr_tmp2));
+
+
+ if (pVars->mc_info.bDownSampledSbr)
+ {
+ calc_sbr_synfilterbank_LC(Sr, /* realSamples */
+ ftimeOutPtr + (i << 6),
+ &circular_buffer_s[1984 - (i<<6)],
+ pVars->mc_info.bDownSampledSbr);
+ }
+ else
+ {
+ calc_sbr_synfilterbank_LC(Sr, /* realSamples */
+ ftimeOutPtr + (i << 7),
+ &circular_buffer_s[3968 - (i<<7)],
+ pVars->mc_info.bDownSampledSbr);
+ }
+ }
+#ifdef HQ_SBR
+ else
+ {
+
+ for (k = xoverBand; k != 0; k--)
+ {
+ *(ptr_tmp2++) = shft_lft_1(*(ptr_tmp1++));
+ }
+
+ ptr_tmp1 = &hFrameData->sbrQmfBufferReal[i*SBR_NUM_BANDS];
+ ptr_tmp2 = &Sr[xoverBand];
+
+
+ for (k = xoverBand; k < sbrDec->highSubband; k++)
+ {
+ *(ptr_tmp2++) = (*(ptr_tmp1++));
+ }
+
+ pv_memset((void *)ptr_tmp2,
+ 0,
+ (64 - sbrDec->highSubband)*sizeof(*ptr_tmp2));
+
+
+ ptr_tmp1 = (hFrameData->codecQmfBufferImag[m]);
+ ptr_tmp2 = Si;
+
+ for (k = (xoverBand >> 1); k != 0; k--)
+ {
+ *(ptr_tmp2++) = shft_lft_1(*(ptr_tmp1++));
+ *(ptr_tmp2++) = shft_lft_1(*(ptr_tmp1++));
+ }
+ if (xoverBand & 1)
+ {
+ *(ptr_tmp2) = shft_lft_1(*(ptr_tmp1));
+ }
+
+ ptr_tmp1 = &hFrameData->sbrQmfBufferImag[i*SBR_NUM_BANDS];
+ ptr_tmp2 = &Si[xoverBand];
+
+ for (k = xoverBand; k < sbrDec->highSubband; k++)
+ {
+ *(ptr_tmp2++) = (*(ptr_tmp1++));
+ }
+
+ pv_memset((void *)ptr_tmp2,
+ 0,
+ (64 - sbrDec->highSubband)*sizeof(*ptr_tmp2));
+
+
+ if (pVars->mc_info.bDownSampledSbr)
+ {
+ calc_sbr_synfilterbank(Sr, /* realSamples */
+ Si, /* imagSamples */
+ ftimeOutPtr + (i << 6),
+ &circular_buffer_s[1984 - (i<<6)],
+ pVars->mc_info.bDownSampledSbr);
+ }
+ else
+ {
+ calc_sbr_synfilterbank(Sr, /* realSamples */
+ Si, /* imagSamples */
+ ftimeOutPtr + (i << 7),
+ &circular_buffer_s[3968 - (i<<7)],
+ pVars->mc_info.bDownSampledSbr);
+ }
+ }
+#endif
+
+ }
+
+ if (pVars->mc_info.bDownSampledSbr)
+ {
+ pv_memmove(hFrameData->V, &circular_buffer_s[0], 640*sizeof(*circular_buffer_s));
+ }
+ else
+ {
+ pv_memmove(hFrameData->V, &circular_buffer_s[0], 1152*sizeof(*circular_buffer_s));
+ }
+
+
+
+
+ /*
+ * Update Buffers
+ */
+ for (i = 0; i < sbrDec->bufWriteOffs; i++) /* sbrDec->bufWriteOffs set to 8 and unchanged */
+ {
+ j = sbrDec->noCols + i; /* sbrDec->noCols set to 32 and unchanged */
+
+ pv_memmove(hFrameData->codecQmfBufferReal[i], /* to */
+ hFrameData->codecQmfBufferReal[j], /* from */
+ sizeof(*hFrameData->codecQmfBufferReal[i]) << 5);
+ }
+
+
+ pv_memmove(&hFrameData->HistsbrQmfBufferReal[0],
+ &hFrameData->sbrQmfBufferReal[32*SBR_NUM_BANDS],
+ 6*SBR_NUM_BANDS*sizeof(*hFrameData->sbrQmfBufferReal));
+
+#ifdef HQ_SBR
+ if (sbrDec->LC_aacP_DecoderFlag == OFF)
+ {
+ for (i = 0; i < sbrDec->bufWriteOffs; i++) /* sbrDec->bufWriteOffs set to 6 and unchanged */
+ {
+ j = sbrDec->noCols + i; /* sbrDec->noCols set to 32 and unchanged */
+
+
+ pv_memmove(hFrameData->codecQmfBufferImag[i],
+ hFrameData->codecQmfBufferImag[j],
+ sizeof(*hFrameData->codecQmfBufferImag[i]) << 5);
+
+ }
+
+ pv_memmove(&hFrameData->HistsbrQmfBufferImag[0],
+ &hFrameData->sbrQmfBufferImag[32*SBR_NUM_BANDS],
+ 6*SBR_NUM_BANDS*sizeof(*hFrameData->sbrQmfBufferImag));
+ }
+#endif
+
+
+#ifdef HQ_SBR
+#ifdef PARAMETRICSTEREO
+ }
+#endif
+#endif
+
+
+ hFrameData->reset_flag = 0;
+ if (applyProcessing)
+ {
+ sbrDec->prevLowSubband = sbrDec->lowSubband;
+ }
+
+}
+
+
+#endif /* AAC_PLUS */
diff --git a/media/libstagefright/codecs/aacdec/sbr_dec.h b/media/libstagefright/codecs/aacdec/sbr_dec.h
new file mode 100644
index 0000000..ba7c1f3
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_dec.h
@@ -0,0 +1,144 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_dec.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+ $Id: ct_envcalc.h,v 1.3 2002/11/29 16:11:49 kaehleof Exp $
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_DEC_H
+#define SBR_DEC_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "s_sbr_frame_data.h"
+#include "pv_audio_type_defs.h"
+#include "s_patch.h"
+#include "e_blockswitching.h"
+#include "s_sbr_dec.h"
+#include "s_tdec_int_file.h"
+#ifdef PARAMETRICSTEREO
+#include "s_ps_dec.h"
+#endif
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+
+ void sbr_dec(Int16 *inPcmData,
+ Int16 *ftimeOutPtr,
+ SBR_FRAME_DATA * hFrameData,
+ Int32 applyProcessing,
+ SBR_DEC *sbrDec,
+#ifdef HQ_SBR
+#ifdef PARAMETRICSTEREO
+ Int16 * ftimeOutPtrPS,
+ HANDLE_PS_DEC hParametricStereoDec,
+#endif
+#endif
+ tDec_Int_File *pVars);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_decode_envelope.cpp b/media/libstagefright/codecs/aacdec/sbr_decode_envelope.cpp
new file mode 100644
index 0000000..771bb32
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_decode_envelope.cpp
@@ -0,0 +1,286 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_decode_envelope.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_decode_envelope.h"
+#include "sbr_constants.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+void mapLowResEnergyVal(
+ Int32 currVal,
+ Int32 *prevData,
+ Int32 offset,
+ Int32 index,
+ Int32 res);
+
+Int32 indexLow2High(Int32 offset,
+ Int32 index,
+ Int32 res);
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void sbr_decode_envelope(SBR_FRAME_DATA * hFrameData)
+
+{
+ Int32 i;
+ Int32 no_of_bands;
+ Int32 band;
+ Int32 freqRes;
+ Int32 *iEnvelope = hFrameData->iEnvelope_man;
+ Int32 *sfb_nrg_prev = hFrameData->sfb_nrg_prev_man;
+
+ Int32 offset = hFrameData->offset;
+ Int32 *nSfb = hFrameData->nSfb;
+ Int32 *domain_vec = hFrameData->domain_vec1;
+ Int32 *frameInfo = hFrameData->frameInfo;
+
+
+
+ for (i = 0; i < frameInfo[0]; i++)
+ {
+ freqRes = frameInfo[frameInfo[0] + i + 2];
+ no_of_bands = nSfb[freqRes];
+
+ if (domain_vec[i] == 0)
+ {
+ mapLowResEnergyVal(*iEnvelope,
+ sfb_nrg_prev,
+ offset,
+ 0,
+ freqRes);
+ iEnvelope++;
+
+ for (band = 1; band < no_of_bands; band++)
+ {
+ *iEnvelope += *(iEnvelope - 1);
+
+ mapLowResEnergyVal(*iEnvelope,
+ sfb_nrg_prev,
+ offset,
+ band,
+ freqRes);
+ iEnvelope++;
+ }
+ }
+ else
+ {
+ for (band = 0; band < no_of_bands; band++)
+ {
+ *iEnvelope += sfb_nrg_prev[ indexLow2High(offset, band, freqRes)];
+
+ mapLowResEnergyVal(*iEnvelope,
+ sfb_nrg_prev,
+ offset,
+ band,
+ freqRes);
+ iEnvelope++;
+ }
+ }
+ }
+}
+
+
+
+void mapLowResEnergyVal(
+ Int32 currVal,
+ Int32 *prevData,
+ Int32 offset,
+ Int32 index,
+ Int32 res)
+{
+ Int32 tmp;
+
+ if (res == LO)
+ {
+ if (offset >= 0)
+ {
+ if (index < offset)
+ {
+ prevData[index] = currVal;
+ }
+ else
+ {
+ tmp = (index << 1) - offset;
+ prevData[tmp ] = currVal;
+ prevData[tmp +1 ] = currVal;
+ }
+ }
+ else
+ {
+ offset = -offset;
+ if (index < offset)
+ {
+ tmp = (index << 1) + index;
+ prevData[tmp ] = currVal;
+ prevData[tmp + 1] = currVal;
+ prevData[tmp + 2] = currVal;
+ }
+ else
+ {
+ tmp = (index << 1) + offset;
+ prevData[tmp ] = currVal;
+ prevData[tmp + 1] = currVal;
+ }
+ }
+ }
+ else
+ {
+ prevData[index] = currVal;
+ }
+}
+
+
+Int32 indexLow2High(Int32 offset,
+ Int32 index,
+ Int32 res)
+{
+ if (res == LO)
+ {
+ if (offset >= 0)
+ {
+ if (index < offset)
+ {
+ return(index);
+ }
+ else
+ {
+ return((index << 1) - offset);
+ }
+ }
+ else
+ {
+ offset = -offset;
+ if (index < offset)
+ {
+ return((index << 1) + index);
+ }
+ else
+ {
+ return((index << 1) + offset);
+ }
+ }
+ }
+ else
+ {
+ return(index);
+ }
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_decode_envelope.h b/media/libstagefright/codecs/aacdec/sbr_decode_envelope.h
new file mode 100644
index 0000000..19c04a9
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_decode_envelope.h
@@ -0,0 +1,94 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_decode_envelope.h
+ Funtions:
+ decodeEnvelope
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_DECODE_ENVELOPE_H
+#define SBR_DECODE_ENVELOPE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_sbr_frame_data.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void sbr_decode_envelope(SBR_FRAME_DATA * hFrameData);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_decode_huff_cw.cpp b/media/libstagefright/codecs/aacdec/sbr_decode_huff_cw.cpp
new file mode 100644
index 0000000..290fd18
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_decode_huff_cw.cpp
@@ -0,0 +1,149 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_decode_huff_cw.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ SbrHuffman h, pointer to huffman codebook table
+ BIT_BUFFER * hBitBuf pointer to Bitbuffer
+
+ return decoded value
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Decodes one huffman code word
+
+ Reads bits from the bitstream until a valid codeword is found.
+ The table entries are interpreted either as index to the next entry
+ or - if negative - as the codeword.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_decode_huff_cw.h"
+#include "buf_getbits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int32 sbr_decode_huff_cw(SbrHuffman h,
+ BIT_BUFFER * hBitBuf)
+{
+ Int32 bits;
+ Char index = 0;
+
+ while (index >= 0)
+ {
+ bits = buf_get_1bit(hBitBuf);
+ index = h[index][bits];
+ }
+
+ return((Int32)index + 64); /* Add offset */
+}
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/sbr_decode_huff_cw.h b/media/libstagefright/codecs/aacdec/sbr_decode_huff_cw.h
new file mode 100644
index 0000000..bfbdb67
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_decode_huff_cw.h
@@ -0,0 +1,93 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_decode_huff_cw.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_DECODE_HUFF_CW_H
+#define SBR_DECODE_HUFF_CW_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bit_buffer.h"
+#include "s_huffman.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ Int32 sbr_decode_huff_cw(SbrHuffman h,
+ BIT_BUFFER * hBitBuf);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_downsample_lo_res.cpp b/media/libstagefright/codecs/aacdec/sbr_downsample_lo_res.cpp
new file mode 100644
index 0000000..c2b007a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_downsample_lo_res.cpp
@@ -0,0 +1,162 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_downsample_lo_res.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_downsample_lo_res.h"
+#include "sbr_constants.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void sbr_downsample_lo_res(Int32 v_result[],
+ Int32 num_result,
+ Int freqBandTableRef[],
+ Int32 num_Ref)
+{
+ Int32 step;
+ Int32 i, j;
+ Int32 org_length;
+ Int32 result_length;
+ Int32 v_index[MAX_FREQ_COEFFS/2];
+
+ /* init */
+ org_length = num_Ref;
+ result_length = num_result;
+
+ v_index[0] = 0; /* Always use left border */
+ i = 0;
+ while (org_length > 0) /* Create downsample vector */
+ {
+ i++;
+ step = org_length / result_length; /* floor; */
+ org_length = org_length - step;
+ result_length--;
+ v_index[i] = v_index[i-1] + step;
+ }
+
+ for (j = 0; j <= i; j++) /* Use downsample vector to index LoResolution vector. */
+ {
+ v_result[j] = freqBandTableRef[ v_index[j]];
+ }
+
+} /* End downSampleLoRes */
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_downsample_lo_res.h b/media/libstagefright/codecs/aacdec/sbr_downsample_lo_res.h
new file mode 100644
index 0000000..2f49aea
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_downsample_lo_res.h
@@ -0,0 +1,97 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_downsample_lo_res.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+ ----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_DOWNSAMPLE_LO_RES_H
+#define SBR_DOWNSAMPLE_LO_RES_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void sbr_downsample_lo_res(Int32 v_result[],
+ Int32 num_result,
+ Int freqBandTableRef[],
+ Int32 num_Ref);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_envelope_calc_tbl.cpp b/media/libstagefright/codecs/aacdec/sbr_envelope_calc_tbl.cpp
new file mode 100644
index 0000000..2ed76dd
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_envelope_calc_tbl.cpp
@@ -0,0 +1,424 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_envelope_calc_tbl.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_envelope_calc_tbl.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+#define Q30_fmt(x) (Int32)(x*((Int32)1<<30) + (x>=0?0.5F:-0.5F))
+#define Qfmt15(x) (Int16)(x*((Int32)1<<15) + (x>=0?0.5F:-0.5F))
+
+
+const Int32 limGains[5] = { Q30_fmt(0.70795f), Q30_fmt(1.0f),
+ Q30_fmt(1.41254f), Q30_fmt(1.16415321826935f), 33
+ };
+
+const Int32 smoothLengths[2] = { 4, 0 };
+
+const Int16 rP_LCx[512] =
+{
+ Qfmt15(-0.99948153278296f), Qfmt15(0.97113454393991f), Qfmt15(0.14130051758487f), Qfmt15(-0.47005496701697f),
+ Qfmt15(0.80705063769351f), Qfmt15(-0.38981478896926f), Qfmt15(-0.01053049862020f), Qfmt15(-0.91266367957293f),
+ Qfmt15(0.54840422910309f), Qfmt15(0.40009252867955f), Qfmt15(-0.99867974711855f), Qfmt15(-0.95531076805040f),
+ Qfmt15(-0.45725933317144f), Qfmt15(-0.72929675029275f), Qfmt15(0.75622801399036f), Qfmt15(0.07069442601050f),
+ Qfmt15(0.74496252926055f), Qfmt15(-0.96440182703856f), Qfmt15(0.30424629369539f), Qfmt15(0.66565033746925f),
+ Qfmt15(0.91697008020594f), Qfmt15(-0.70774918760427f), Qfmt15(-0.70051415345560f), Qfmt15(-0.99496513054797f),
+ Qfmt15(0.98164490790123f), Qfmt15(-0.54671580548181f), Qfmt15(-0.01689629065389f), Qfmt15(-0.86110349531986f),
+ Qfmt15(-0.98892980586032f), Qfmt15(0.51756627678691f), Qfmt15(-0.99635026409640f), Qfmt15(-0.99969370862163f),
+ Qfmt15(0.55266258627194f), Qfmt15(0.34581177741673f), Qfmt15(0.62664209577999f), Qfmt15(-0.77149701404973f),
+ Qfmt15(-0.91592244254432f), Qfmt15(-0.76285492357887f), Qfmt15(0.79788337195331f), Qfmt15(0.54473080610200f),
+ Qfmt15(-0.85639281671058f), Qfmt15(-0.92882402971423f), Qfmt15(-0.11708371046774f), Qfmt15(0.21356749817493f),
+ Qfmt15(-0.76191692573909f), Qfmt15(0.98111043100884f), Qfmt15(-0.85913269895572f), Qfmt15(-0.93307242253692f),
+ Qfmt15(0.30485754879632f), Qfmt15(0.85289650925190f), Qfmt15(0.91328082618125f), Qfmt15(-0.05890199924154f),
+ Qfmt15(0.28398686150148f), Qfmt15(0.95258164539612f), Qfmt15(-0.78566324168507f), Qfmt15(-0.95789495447877f),
+ Qfmt15(0.82411158711197f), Qfmt15(-0.65185446735885f), Qfmt15(-0.93643603134666f), Qfmt15(0.91427159529618f),
+ Qfmt15(-0.70395684036886f), Qfmt15(0.00563771969365f), Qfmt15(0.89065051931895f), Qfmt15(-0.68683707712762f),
+ Qfmt15(0.72165342518718f), Qfmt15(-0.62928247730667f), Qfmt15(0.29938434065514f), Qfmt15(-0.91781958879280f),
+ Qfmt15(0.99298717043688f), Qfmt15(0.82368298622748f), Qfmt15(-0.98512833386833f), Qfmt15(-0.95915368242257f),
+ Qfmt15(-0.21411126572790f), Qfmt15(-0.68821476106884f), Qfmt15(0.91851997982317f), Qfmt15(-0.96062769559127f),
+ Qfmt15(0.51646184922287f), Qfmt15(0.61130721139669f), Qfmt15(0.47336129371299f), Qfmt15(0.90998308703519f),
+ Qfmt15(0.44844799194357f), Qfmt15(0.66614891079092f), Qfmt15(0.74922239129237f), Qfmt15(-0.99571588506485f),
+ Qfmt15(0.97401082477563f), Qfmt15(0.72683747733879f), Qfmt15(0.95432193457128f), Qfmt15(-0.72962208425191f),
+ Qfmt15(-0.85359479233537f), Qfmt15(-0.81412430338535f), Qfmt15(-0.87930772356786f), Qfmt15(-0.71573331064977f),
+ Qfmt15(0.83524300028228f), Qfmt15(-0.48086065601423f), Qfmt15(0.97139128574778f), Qfmt15(0.51992825347895f),
+ Qfmt15(-0.00848591195325f), Qfmt15(-0.70294374303036f), Qfmt15(-0.95894428168140f), Qfmt15(0.97079252950321f),
+ Qfmt15(-0.92404293670797f), Qfmt15(-0.69506469500450f), Qfmt15(0.26559203620024f), Qfmt15(0.28038443336943f),
+ Qfmt15(-0.74138124825523f), Qfmt15(-0.01752795995444f), Qfmt15(-0.55126773094930f), Qfmt15(0.97960898850996f),
+ Qfmt15(-0.99196309146936f), Qfmt15(-0.67684928085260f), Qfmt15(0.09140039465500f), Qfmt15(-0.71658965751996f),
+ Qfmt15(0.81014640078925f), Qfmt15(0.40616991671205f), Qfmt15(-0.67680188682972f), Qfmt15(0.86849774348749f),
+ Qfmt15(-0.99500381284851f), Qfmt15(0.84329189340667f), Qfmt15(-0.09215968531446f), Qfmt15(0.99956173327206f),
+ Qfmt15(-0.79732779473535f), Qfmt15(0.96349973642406f), Qfmt15(-0.79942778496547f), Qfmt15(-0.11566039853896f),
+ Qfmt15(-0.39922954514662f), Qfmt15(0.99089197565987f), Qfmt15(0.28631285179909f), Qfmt15(-0.83302725605608f),
+ Qfmt15(0.95404443402072f), Qfmt15(-0.06449863579434f), Qfmt15(-0.99575054486311f), Qfmt15(-0.65501142790847f),
+ Qfmt15(-0.81254441908887f), Qfmt15(-0.99646369485481f), Qfmt15(0.00287840603348f), Qfmt15(0.70176989408455f),
+ Qfmt15(0.96361882270190f), Qfmt15(-0.68883758192426f), Qfmt15(-0.34875585502238f), Qfmt15(0.91980081243087f),
+ Qfmt15(-0.99009048343881f), Qfmt15(0.68865791458395f), Qfmt15(-0.99484402129368f), Qfmt15(0.94214511408023f),
+ Qfmt15(-0.67414626793544f), Qfmt15(-0.47339353684664f), Qfmt15(0.14323651387360f), Qfmt15(-0.29268293575672f),
+ Qfmt15(0.43793861458754f), Qfmt15(-0.36345126374441f), Qfmt15(-0.08750604656825f), Qfmt15(-0.96495267812511f),
+ Qfmt15(0.55526940659947f), Qfmt15(0.73538215752630f), Qfmt15(-0.30889773919437f), Qfmt15(0.03574995626194f),
+ Qfmt15(0.98720684660488f), Qfmt15(-0.81689296271203f), Qfmt15(0.67866860118215f), Qfmt15(-0.15808569732583f),
+ Qfmt15(0.80723395114371f), Qfmt15(0.47788757329038f), Qfmt15(0.96367554763201f), Qfmt15(-0.99143875716818f),
+ Qfmt15(0.83081876925833f), Qfmt15(-0.58753191905341f), Qfmt15(0.95538108220960f), Qfmt15(-0.96490920476211f),
+ Qfmt15(-0.97327101028521f), Qfmt15(0.91400366022124f), Qfmt15(-0.99925837363824f), Qfmt15(-0.86875903507313f),
+ Qfmt15(-0.26240034795124f), Qfmt15(-0.24664412953388f), Qfmt15(0.02416275806869f), Qfmt15(0.82068619590515f),
+ Qfmt15(0.88547373760759f), Qfmt15(-0.18173078152226f), Qfmt15(0.09355476558534f), Qfmt15(-0.54668414224090f),
+ Qfmt15(0.37050990604091f), Qfmt15(-0.70373594262891f), Qfmt15(-0.34600785879594f), Qfmt15(-0.68774481731008f),
+ Qfmt15(-0.26843291251234f), Qfmt15(0.49072334613242f), Qfmt15(0.38975993093975f), Qfmt15(-0.97757125224150f),
+ Qfmt15(-0.17325552859616f), Qfmt15(0.99948035025744f), Qfmt15(-0.64946246527458f), Qfmt15(-0.12016920576437f),
+ Qfmt15(-0.58947456517751f), Qfmt15(-0.41815140454465f), Qfmt15(0.99885650204884f), Qfmt15(-0.56649614128386f),
+ Qfmt15(0.94138021032330f), Qfmt15(-0.75725076534641f), Qfmt15(0.20541973692630f), Qfmt15(0.99980371023351f),
+ Qfmt15(0.29078277605775f), Qfmt15(-0.62858772103030f), Qfmt15(0.43440904467688f), Qfmt15(-0.98298583762390f),
+ Qfmt15(0.19513029146934f), Qfmt15(-0.95476662400101f), Qfmt15(0.93379635304810f), Qfmt15(-0.85235410573336f),
+ Qfmt15(-0.86425093011245f), Qfmt15(0.38879779059045f), Qfmt15(0.92045124735495f), Qfmt15(0.89162532251878f),
+ Qfmt15(-0.36834336949252f), Qfmt15(0.93891760988045f), Qfmt15(0.99267657565094f), Qfmt15(-0.94063471614176f),
+ Qfmt15(0.99740224117019f), Qfmt15(-0.35899413170555f), Qfmt15(0.05237237274947f), Qfmt15(0.36703583957424f),
+ Qfmt15(0.91653180367913f), Qfmt15(0.69000803499316f), Qfmt15(-0.38658751133527f), Qfmt15(-0.29250814029851f),
+ Qfmt15(-0.60182204677608f), Qfmt15(-0.97418588163217f), Qfmt15(0.88461574003963f), Qfmt15(0.05198933055162f),
+ Qfmt15(-0.53499621979720f), Qfmt15(-0.49429560226497f), Qfmt15(-0.98935142339139f), Qfmt15(-0.98081380091130f),
+ Qfmt15(-0.27338148835532f), Qfmt15(0.06310802338302f), Qfmt15(-0.20461677199539f), Qfmt15(0.66223843141647f),
+ Qfmt15(-0.84764345483665f), Qfmt15(-0.89039863483811f), Qfmt15(0.95903308477986f), Qfmt15(0.73504123909879f),
+ Qfmt15(-0.31744434966056f), Qfmt15(-0.34110827591623f), Qfmt15(0.47803883714199f), Qfmt15(0.98299195879514f),
+ Qfmt15(-0.30963073129751f), Qfmt15(0.99992588229018f), Qfmt15(-0.93149731080767f), Qfmt15(0.99923472302773f),
+ Qfmt15(-0.26024169633417f), Qfmt15(-0.35712514743563f), Qfmt15(-0.99899084509530f), Qfmt15(0.86557171579452f),
+ Qfmt15(0.33408042438752f), Qfmt15(0.99010736374716f), Qfmt15(-0.66694269691195f), Qfmt15(0.64016792079480f),
+ Qfmt15(0.99570534804836f), Qfmt15(-0.63431466947340f), Qfmt15(-0.07706847005931f), Qfmt15(0.98590090577724f),
+ Qfmt15(0.80099335254678f), Qfmt15(0.78368131392666f), Qfmt15(0.08707806671691f), Qfmt15(-0.86811883080712f),
+ Qfmt15(-0.39466529740375f), Qfmt15(0.97875325649683f), Qfmt15(-0.95038560288864f), Qfmt15(0.17005239424212f),
+ Qfmt15(-0.76910792026848f), Qfmt15(0.99743281016846f), Qfmt15(0.95437383549973f), Qfmt15(0.99578905365569f),
+ Qfmt15(0.28058259829990f), Qfmt15(0.85256524470573f), Qfmt15(-0.50608540105128f), Qfmt15(-0.97210735183243f),
+ Qfmt15(0.95424048234441f), Qfmt15(-0.96926570524023f), Qfmt15(0.30872163214726f), Qfmt15(-0.24523839572639f),
+ Qfmt15(-0.33813265086024f), Qfmt15(-0.05826828420146f), Qfmt15(-0.22898461455054f), Qfmt15(-0.18509915019881f),
+ Qfmt15(-0.10488238045009f), Qfmt15(-0.71886586182037f), Qfmt15(0.99793873738654f), Qfmt15(0.57563307626120f),
+ Qfmt15(0.28909646383717f), Qfmt15(0.42188998312520f), Qfmt15(0.93335049681047f), Qfmt15(-0.97087374418267f),
+ Qfmt15(0.36722871286923f), Qfmt15(-0.81093025665696f), Qfmt15(-0.26240603062237f), Qfmt15(0.83996497984604f),
+ Qfmt15(-0.99909615720225f), Qfmt15(0.74649464155061f), Qfmt15(-0.74774595569805f), Qfmt15(0.95781667469567f),
+ Qfmt15(0.95472308713099f), Qfmt15(0.48708332746299f), Qfmt15(0.46332038247497f), Qfmt15(-0.76497004940162f),
+ Qfmt15(0.57397389364339f), Qfmt15(0.75374316974495f), Qfmt15(-0.59174397685714f), Qfmt15(0.75087906691890f),
+ Qfmt15(-0.98607857336230f), Qfmt15(-0.40761056640505f), Qfmt15(0.66929266740477f), Qfmt15(-0.97463695257310f),
+ Qfmt15(0.90145509409859f), Qfmt15(-0.87259289048043f), Qfmt15(-0.91529461447692f), Qfmt15(-0.03305738840705f),
+ Qfmt15(0.07223051368337f), Qfmt15(0.99498012188353f), Qfmt15(-0.74904939500519f), Qfmt15(0.04585228574211f),
+ Qfmt15(-0.89054954257993f), Qfmt15(-0.83782144651251f), Qfmt15(0.33454804933804f), Qfmt15(-0.99707579362824f),
+ Qfmt15(-0.22827527843994f), Qfmt15(0.67248046289143f), Qfmt15(-0.05146538187944f), Qfmt15(0.99947295749905f),
+ Qfmt15(0.66951124390363f), Qfmt15(-0.99602956559179f), Qfmt15(0.82104905483590f), Qfmt15(0.99186510988782f),
+ Qfmt15(-0.65284592392918f), Qfmt15(0.93885443798188f), Qfmt15(0.96735248738388f), Qfmt15(-0.22225968841114f),
+ Qfmt15(-0.44132783753414f), Qfmt15(-0.85694974219574f), Qfmt15(0.91783042091762f), Qfmt15(0.72556974415690f),
+ Qfmt15(-0.99711581834508f), Qfmt15(0.77638976371966f), Qfmt15(0.07717324253925f), Qfmt15(-0.56049829194163f),
+ Qfmt15(0.98398893639988f), Qfmt15(0.47546946844938f), Qfmt15(0.65675089314631f), Qfmt15(0.03273375457980f),
+ Qfmt15(-0.38684144784738f), Qfmt15(-0.97346267944545f), Qfmt15(-0.53282156061942f), Qfmt15(0.99817310731176f),
+ Qfmt15(-0.50254500772635f), Qfmt15(0.01995873238855f), Qfmt15(0.99930381973804f), Qfmt15(0.82907767600783f),
+ Qfmt15(-0.58660709669728f), Qfmt15(-0.17573736667267f), Qfmt15(0.83434292401346f), Qfmt15(0.05946491307025f),
+ Qfmt15(0.81505484574602f), Qfmt15(-0.44976380954860f), Qfmt15(-0.89746474625671f), Qfmt15(0.39677256130792f),
+ Qfmt15(-0.07588948563079f), Qfmt15(0.76343198951445f), Qfmt15(-0.74490104699626f), Qfmt15(0.64880119792759f),
+ Qfmt15(0.62319537462542f), Qfmt15(0.42215817594807f), Qfmt15(0.02704554141885f), Qfmt15(0.80001773566818f),
+ Qfmt15(-0.79351832348816f), Qfmt15(0.63872359151636f), Qfmt15(0.52890520960295f), Qfmt15(0.74238552914587f),
+ Qfmt15(0.99096131449250f), Qfmt15(-0.80412329643109f), Qfmt15(-0.64612616129736f), Qfmt15(0.11657770663191f),
+ Qfmt15(-0.95053182488101f), Qfmt15(-0.62228872928622f), Qfmt15(0.03004475787316f), Qfmt15(-0.97987214341034f),
+ Qfmt15(-0.99986980746200f), Qfmt15(0.89110648599879f), Qfmt15(0.10407960510582f), Qfmt15(0.95964737821728f),
+ Qfmt15(0.50843233159162f), Qfmt15(0.17006334670615f), Qfmt15(0.25872675063360f), Qfmt15(-0.01115998681937f),
+ Qfmt15(-0.79598702973261f), Qfmt15(-0.99264708948101f), Qfmt15(-0.99829663752818f), Qfmt15(-0.70801016548184f),
+ Qfmt15(-0.70467057786826f), Qfmt15(0.99846021905254f), Qfmt15(-0.63364968534650f), Qfmt15(-0.16258217500792f),
+ Qfmt15(-0.43645594360633f), Qfmt15(-0.99848471702976f), Qfmt15(-0.16796458968998f), Qfmt15(-0.87979225745213f),
+ Qfmt15(0.44183099021786f), Qfmt15(0.93310180125532f), Qfmt15(-0.93941931782002f), Qfmt15(-0.88590003188677f),
+ Qfmt15(0.99971463703691f), Qfmt15(-0.75376385639978f), Qfmt15(0.93887685615875f), Qfmt15(0.85126435782309f),
+ Qfmt15(0.39701421446381f), Qfmt15(-0.37024464187437f), Qfmt15(-0.36024828242896f), Qfmt15(-0.93388812549209f),
+ Qfmt15(-0.65298804552119f), Qfmt15(0.11960319006843f), Qfmt15(0.94292565553160f), Qfmt15(0.75081145286948f),
+ Qfmt15(0.56721979748394f), Qfmt15(0.46857766746029f), Qfmt15(0.97312313923635f), Qfmt15(-0.38299976567017f),
+ Qfmt15(0.41025800019463f), Qfmt15(0.09638062008048f), Qfmt15(-0.85283249275397f), Qfmt15(0.88866808958124f),
+ Qfmt15(-0.48202429536989f), Qfmt15(0.27572582416567f), Qfmt15(-0.65889129659168f), Qfmt15(0.98838086953732f),
+ Qfmt15(-0.20651349620689f), Qfmt15(-0.62126416356920f), Qfmt15(0.20320105410437f), Qfmt15(-0.97790548600584f),
+ Qfmt15(0.11112534735126f), Qfmt15(-0.41368337314182f), Qfmt15(0.24133038992960f), Qfmt15(-0.66393410674885f),
+ Qfmt15(-0.53697829178752f), Qfmt15(-0.97224737889348f), Qfmt15(0.87392477144549f), Qfmt15(0.19050361015753f),
+ Qfmt15(-0.46353441212724f), Qfmt15(-0.07064096339021f), Qfmt15(-0.92444085484466f), Qfmt15(-0.83822593578728f),
+ Qfmt15(0.75214681811150f), Qfmt15(-0.42102998829339f), Qfmt15(-0.72094786237696f), Qfmt15(0.78843311019251f),
+ Qfmt15(0.97394027897442f), Qfmt15(0.99206463477946f), Qfmt15(0.76789609461795f), Qfmt15(-0.82002421836409f),
+ Qfmt15(0.81924990025724f), Qfmt15(-0.26719850873357f), Qfmt15(-0.43311260380975f), Qfmt15(0.99194979673836f),
+ Qfmt15(-0.80692001248487f), Qfmt15(0.43080003649976f), Qfmt15(0.67709491937357f), Qfmt15(0.56151770568316f),
+ Qfmt15(0.10831862810749f), Qfmt15(0.91229417540436f), Qfmt15(-0.48972893932274f), Qfmt15(-0.89033658689697f),
+ Qfmt15(0.65269447475094f), Qfmt15(0.67439478141121f), Qfmt15(-0.47770832416973f), Qfmt15(-0.99715979260878f),
+ Qfmt15(-0.90889593602546f), Qfmt15(-0.06618622548177f), Qfmt15(0.99430266919728f), Qfmt15(0.97686402381843f),
+ Qfmt15(0.94813650221268f), Qfmt15(-0.95434497492853f), Qfmt15(-0.49104783137150f), Qfmt15(0.99881175120751f),
+ Qfmt15(0.50449166760303f), Qfmt15(0.47162891065108f), Qfmt15(-0.62081581361840f), Qfmt15(-0.43867015250812f),
+ Qfmt15(0.98630563232075f), Qfmt15(-0.61510362277374f), Qfmt15(-0.03841517601843f), Qfmt15(-0.30102157304644f),
+ Qfmt15(0.41881284182683f), Qfmt15(-0.86135454941237f), Qfmt15(0.67226861393788f), Qfmt15(-0.70737398842068f),
+ Qfmt15(0.94044946687963f), Qfmt15(-0.82386352534327f), Qfmt15(-0.32070666698656f), Qfmt15(0.57593163224487f),
+ Qfmt15(-0.36326018419965f), Qfmt15(0.99979044674350f), Qfmt15(-0.92366023326932f), Qfmt15(-0.44607178518598f),
+ Qfmt15(0.44226800932956f), Qfmt15(0.03671907158312f), Qfmt15(0.52175424682195f), Qfmt15(-0.94701139690956f),
+ Qfmt15(-0.98759606946049f), Qfmt15(0.87434794743625f), Qfmt15(-0.93412041758744f), Qfmt15(0.96063943315511f),
+ Qfmt15(0.97534253457837f), Qfmt15(0.99642466504163f), Qfmt15(-0.94705089665984f), Qfmt15(0.91599807087376f)
+};
+
+
+#ifdef HQ_SBR
+
+
+const Int32 fir_table[5][5] =
+{
+ { Q30_fmt(1.0f)},
+ { Q30_fmt(0.33333333333333f), Q30_fmt(0.66666666666666f)},
+ { Q30_fmt(0.12500000000000f), Q30_fmt(0.37500000000000f),
+ Q30_fmt(0.50000000000000f)},
+ { Q30_fmt(0.05857864376269f), Q30_fmt(0.20000000000000f),
+ Q30_fmt(0.34142135623731f), Q30_fmt(0.40000000000000f)},
+ { Q30_fmt(0.03183050093751f), Q30_fmt(0.11516383427084f),
+ Q30_fmt(0.21816949906249f), Q30_fmt(0.30150283239582f),
+ Q30_fmt(0.33333333333333f)}
+};
+
+
+
+const Int32 rPxx[512] =
+{
+
+ 0x8010B3DB, 0x7C4DA98F, 0x12168648, 0xC3D4D033,
+ 0x674D25F5, 0xCE1972A6, 0xFEA5AA4A, 0x8B2DF13E,
+ 0x46326048, 0x3336815E, 0x802A8F2B, 0x85B7745C,
+ 0xC577B766, 0xA2A5828C, 0x60CB1AD1, 0x090C9BD7,
+ 0x5F5A8B4D, 0x848D86BB, 0x26F1C0B7, 0x553352C1,
+ 0x755E166B, 0xA5674343, 0xA654C5F5, 0x80A48CB4,
+ 0x7DA69CD8, 0xBA04FCB4, 0xFDD4005E, 0x91C63676,
+ 0x816A8F82, 0x423F55AA, 0x8077B59E, 0x80097DE9,
+ 0x46BD4C18, 0x2C437971, 0x5035A0C2, 0x9D3ED49F,
+ 0x8AC204B8, 0x9E5A8B0A, 0x662088B9, 0x45B9F0BC,
+ 0x9261364F, 0x891B23AD, 0xF1028040, 0x1B568BE1,
+ 0x9E787FB3, 0x7D94854D, 0x92077A94, 0x88903F45,
+ 0x2705A5B4, 0x6D2B3BDC, 0x74E58034, 0xF8745A8C,
+ 0x24592C54, 0x79EDB9BB, 0x9B6E9F44, 0x8563E5DA,
+ 0x697C7BB7, 0xAC8F8E6A, 0x88227FD5, 0x7506822F,
+ 0xA5E34B42, 0x00B94F10, 0x72004390, 0xA814676E,
+ 0x5C5EA758, 0xAF721171, 0x2652C50C, 0x8A84A142,
+ 0x7F19343E, 0x696EA13B, 0x81E68008, 0x853980F9,
+ 0xE4968869, 0xA7E7DD92, 0x75910BFA, 0x85092E35,
+ 0x421BA4A3, 0x4E3F3C18, 0x3C97DD02, 0x74797BCB,
+ 0x39667EFD, 0x55447BA2, 0x5FE68CF3, 0x808B4390,
+ 0x7CABEA6B, 0x5D08C27A, 0x7A265820, 0xA29A9DF0,
+ 0x92BC7195, 0x97CA8338, 0x8F725FAD, 0xA46281D3,
+ 0x6AE86B23, 0xC2728178, 0x7C566684, 0x428C66B7,
+ 0xFEE89DDB, 0xA60546DC, 0x8540C89D, 0x7C420BF0,
+ 0x89B86D72, 0xA7077E3F, 0x21FF5DD7, 0x23E3129C,
+ 0xA1197F1D, 0xFDC0963F, 0xB96F8168, 0x7D6387A6,
+ 0x810655C8, 0xA95C102B, 0x0BB3E5B4, 0xA44682D4,
+ 0x67B244C3, 0x33FDDE1D, 0xA95D78F5, 0x6F2AE887,
+ 0x80A3FC9F, 0x6BF00D52, 0xF4325902, 0x7FF1F02C,
+ 0x99F08AC5, 0x7B537BB2, 0x99AB5255, 0xF1302497,
+ 0xCCE4787B, 0x7ED58A28, 0x24A68B79, 0x955EA9D0,
+ 0x7A1D3EED, 0xF7BD0429, 0x808A3642, 0xAC2769A8,
+ 0x97FDBDE9, 0x80736C25, 0x005E52E7, 0x59D3E5D0,
+ 0x7B57341A, 0xA7D374E9, 0xD35A5B7B, 0x75BB5520,
+ 0x81446DE8, 0x5825473E, 0x80A8E653, 0x78978062,
+ 0xA9B43F6B, 0xC366920A, 0x1255877D, 0xDA88075F,
+ 0x380E9AFF, 0xD1795309, 0xF4CB7D09, 0x847BBAED,
+ 0x471364FA, 0x5E207B74, 0xD87498BF, 0x0493836B,
+ 0x7E5C3DF6, 0x976F8BBC, 0x56DE680A, 0xEBC26D28,
+ 0x6753E05B, 0x3D2BC4B0, 0x7B593143, 0x8118E010,
+ 0x6A5786AD, 0xB4CA01A7, 0x7A49927C, 0x847DAE0C,
+ 0x836B0FD8, 0x74FD4A34, 0x80175AFC, 0x90CBE605,
+ 0xDE68A89E, 0xE06C8FD0, 0x031822CE, 0x690B9315,
+ 0x71568D43, 0xE8BBDE85, 0x0BFA4633, 0xBA057ADA,
+ 0x2F6CB34F, 0xA5EB74C5, 0xD3B480B6, 0xA7F7D94A,
+ 0xDDA26A63, 0x3ED0C5EF, 0x31E37A42, 0x82DE06CB,
+ 0xE9D18940, 0x7FEE4A9A, 0xACDD57DD, 0xF09CB6D9,
+ 0xB48BD364, 0xCA7814D5, 0x7FDA0E41, 0xB77C8C2A,
+ 0x787E2D29, 0x9F1144AC, 0x1A4B871E, 0x7FF96630,
+ 0x25382D4D, 0xAF89319E, 0x379A81DB, 0x822D1AE8,
+ 0x18FA875E, 0x85C97DE7, 0x7786A544, 0x92E5F550,
+ 0x915FC560, 0x31C47C82, 0x75D0B014, 0x72204656,
+ 0xD0D87B76, 0x782E8CD6, 0x7F0FFB2F, 0x879834E7,
+ 0x7FAAEA73, 0xD20BC44E, 0x06B4DF2C, 0x2EFBCE84,
+ 0x7550D8D7, 0x5851746A, 0xCE837F5C, 0xDA8D2FEE,
+ 0xB2F66F13, 0x834D7B7A, 0x713A499C, 0x06A81B39,
+ 0xBB847C77, 0xC0B97DAC, 0x815CCC7A, 0x8274A2BD,
+ 0xDD007FEF, 0x0814BA2F, 0xE5CDEDCE, 0x54C45CD5,
+ 0x937F0309, 0x8E0671BF, 0x7AC1623B, 0x5E15FB32,
+ 0xD75CD0D9, 0xD4553378, 0x3D30CD88, 0x7DD2028C,
+ 0xD85CE8DB, 0x7FFDDE5A, 0x88C48228, 0x7FE6996A,
+ 0xDEAF9EB7, 0xD24818B4, 0x80205F8B, 0x6ECA4728,
+ 0x2AC36E51, 0x7EBB05E4, 0xAAA08AB1, 0x51F01408,
+ 0x7F723AAE, 0xAECD1AFB, 0xF6218D55, 0x7E3170F2,
+ 0x6686D0D3, 0x644F3A3F, 0x0B256799, 0x90E0325D,
+ 0xCD7AAA7B, 0x7D47A33C, 0x865972A3, 0x15C445FE,
+ 0x9D8D84D3, 0x7FAB36A7, 0x7A287C29, 0x7F75BABD,
+ 0x23EA92BC, 0x6D20AD59, 0xBF37ABB6, 0x8391E26E,
+ 0x7A2480F8, 0x83EE5E6E, 0x27843523, 0xE09A50E7,
+ 0xD4B6CE82, 0xF889F71C, 0xE2AF7C3A, 0xE84D3CE2,
+ 0xF2918FA6, 0xA3FB63E0, 0x7FBB7340, 0x49AE8B79,
+ 0x25017B45, 0x36003DA1, 0x7777C844, 0x83B96EE4,
+ 0x2F015392, 0x98320B3C, 0xDE68893F, 0x6B834779,
+ 0x801D8516, 0x5F8C0F8C, 0xA049DD90, 0x7A999AD0,
+ 0x7A33F500, 0x3E587FFF, 0x3B4E0E09, 0x9E147230,
+ 0x49772D2B, 0x607A7BC7, 0xB4408D8F, 0x601CDA17,
+ 0x81C7200B, 0xCBD28CBD, 0x55AB7E3E, 0x833EFFC0,
+ 0x73627FB7, 0x904E7F04, 0x8AD7EBE6, 0xFBC3D05F,
+ 0x093F8E53, 0x7F5B7C47, 0xA01E7FFA, 0x05DE7FC2,
+ 0x8E01D74D, 0x94C17CF9, 0x2AD2919F, 0x805F7757,
+ 0xE2C61829, 0x5613FB53, 0xF9688978, 0x7FEE77D6,
+ 0x55B27E98, 0x8081C6D6, 0x69177F69, 0x7EF45C30,
+ 0xAC6E42CC, 0x782BA021, 0x7BD17457, 0xE38B491E,
+ 0xC781895B, 0x924E71B8, 0x757BC4A8, 0x5CDF8020,
+ 0x805E4A82, 0x636078BA, 0x09E14B0E, 0xB84069A0,
+ 0x7DF23284, 0x3CDC57D2, 0x54101777, 0x0431A015,
+ 0xCE7A41B6, 0x8365846A, 0xBBCB8AF9, 0x7FC34E40,
+ 0xBFAB8E4B, 0x028E6D15, 0x7FE8790F, 0x6A1EF7E6,
+ 0xB4E97BF4, 0xE980C257, 0x6ACBEF53, 0x079C1A41,
+ 0x685386CC, 0xC66D3458, 0x8D1F7FCD, 0x32C9A02E,
+ 0xF6475ED7, 0x61B7356F, 0xA0A6793F, 0x530B34E9,
+ 0x4FC488D4, 0x3609F61F, 0x0376F90F, 0x6666752C,
+ 0x9A6DD1A5, 0x51C10A67, 0x43B34CDC, 0x5F0605C0,
+ 0x7ED7E718, 0x99118EB3, 0xAD4A5C69, 0x0EEC94E8,
+ 0x865483EA, 0xB05769F0, 0x03D88055, 0x82932EC1,
+ 0x8003D1E3, 0x720F82B1, 0x0D526304, 0x7AD5D2A3,
+ 0x41147B04, 0x15C49D9F, 0x211E7FDC, 0xFE907E12,
+ 0x9A1C7C55, 0x80F08095, 0x80370267, 0xA55F2B1C,
+ 0xA5CC7763, 0x7FCD81A1, 0xAEE3EAE8, 0xEB2F8532,
+ 0xC82186A5, 0x80317B31, 0xEA7E814B, 0x8F62A430,
+ 0x388D883A, 0x776F801B, 0x87C0B7CA, 0x8E9A3CF5,
+ 0x7FF6949E, 0x9F83010B, 0x782CF18C, 0x6CF54301,
+ 0x32D168AD, 0xD09A908B, 0xD1E22C5C, 0x887593DE,
+ 0xAC6AE864, 0x0F4F7FDE, 0x78B16A72, 0x601AD283,
+ 0x489AE12D, 0x3BFAD96A, 0x7C8E8093, 0xCEF87E19,
+ 0x348302B6, 0x0C5605A6, 0x92D57516, 0x71BF8056,
+ 0xC24C8416, 0x234B4B0D, 0xABA84B4F, 0x7E827FFD,
+ 0xE58F45E1, 0xB079B355, 0x1A0290CA, 0x82D37B40,
+ 0x0E391B80, 0xCB0B241E, 0x1EE441A8, 0xAB03F56F,
+ 0xBB438301, 0x838C1C43, 0x6FDCEF9D, 0x1862020D,
+ 0xC4A98614, 0xF6F38710, 0x89ABF29B, 0x94B4FDD3,
+ 0x6046800E, 0xCA1A7FA4, 0xA3B7D32F, 0x64EB43A6,
+ 0x7CA9DDD3, 0x7EFBB705, 0x624A9E0D, 0x9708A1E0,
+ 0x68DC7F9C, 0xDDCB5832, 0xC88E6D35, 0x7EF77599,
+ 0x98B6D63B, 0x3724E3F0, 0x56AA85C9, 0x47DFA582,
+ 0x0DDDF4F3, 0x74C5AB88, 0xC14F480C, 0x8E08A446,
+ 0x538B545F, 0x56529770, 0xC2D9EA81, 0x805C883B,
+ 0x8BA84F67, 0xF785E183, 0x7F441814, 0x7D09DB4D,
+ 0x795C8330, 0x85D79A19, 0xC1242A1B, 0x7FD871E9,
+ 0x409391EC, 0x3C5EE815, 0xB0885FFF, 0xC7D87FFE,
+ 0x7E3EBB6A, 0xB1438D6B, 0xFB13A68A, 0xD976F62D,
+ 0x359B02CD, 0x91BE7EA6, 0x560CEEB8, 0xA5739E04,
+ 0x78600B8E, 0x968A0B6C, 0xD6F1402E, 0x49B88152,
+ 0xD17F0986, 0x7FF8EDE8, 0x89C48295, 0xC6E6BA93,
+ 0x389C5B4C, 0x04B3516A, 0x42C892B0, 0x86C7FDA8,
+ 0x81956954, 0x6FEA726E, 0x886E34F5, 0x7AF57730,
+ 0x7CD76E45, 0x7F8A59D7, 0x86C6DA22, 0x753F825E
+};
+
+
+#endif
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_envelope_calc_tbl.h b/media/libstagefright/codecs/aacdec/sbr_envelope_calc_tbl.h
new file mode 100644
index 0000000..60e806d
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_envelope_calc_tbl.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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Filename: sbr_envelope_calc_tbl.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_ENVELOPE_CALC_TBL_H
+#define SBR_ENVELOPE_CALC_TBL_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+extern const Int32 limGains[5];
+
+extern const Int32 smoothLengths[2];
+
+extern const Int16 rP_LCx[512];
+
+#ifdef HQ_SBR
+
+
+extern const Int32 fir_table[5][5];
+
+extern const Int32 rPxx[512];
+
+#endif
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_envelope_unmapping.cpp b/media/libstagefright/codecs/aacdec/sbr_envelope_unmapping.cpp
new file mode 100644
index 0000000..7fce46b
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_envelope_unmapping.cpp
@@ -0,0 +1,427 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_envelope_unmapping.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_envelope_unmapping.h"
+#include "sbr_constants.h"
+
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+#define R_SHIFT 30
+#define Qfmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+/*
+ * 1./(1+2.^-[0:10])
+ */
+const Int32 one_over_one_plus_two_to_n[11] =
+{
+ Qfmt(0.50000000000000F), Qfmt(0.66666666666667F), Qfmt(0.80000000000000F),
+ Qfmt(0.88888888888889F), Qfmt(0.94117647058824F), Qfmt(0.96969696969697F),
+ Qfmt(0.98461538461538F), Qfmt(0.99224806201550F), Qfmt(0.99610894941634F),
+ Qfmt(0.99805068226121F), Qfmt(0.99902439024390F)
+};
+
+/*
+ * 1./(1+2.^[0.5:-1:-10.5])
+ */
+const Int32 one_over_one_plus_sq_2_by_two_to_n[12] =
+{
+ Qfmt(0.41421356237310F), Qfmt(0.58578643762690F), Qfmt(0.73879612503626F),
+ Qfmt(0.84977889517767F), Qfmt(0.91878969685839F), Qfmt(0.95767628767521F),
+ Qfmt(0.97838063800882F), Qfmt(0.98907219289563F), Qfmt(0.99450607818892F),
+ Qfmt(0.99724547251514F), Qfmt(0.99862083678608F), Qfmt(0.99930994254211F)
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void sbr_envelope_unmapping(SBR_FRAME_DATA * hFrameData1,
+ SBR_FRAME_DATA * hFrameData2)
+
+{
+ Int32 i;
+ Int32 tempLeft;
+ Int32 tempRight;
+
+ Int32 tmp;
+ Int32 *iEnvelopeLeft_man = hFrameData1->iEnvelope_man;
+ Int32 *iEnvelopeLeft_exp = hFrameData1->iEnvelope_exp;
+ Int32 *noiseFloorLeft_man = hFrameData1->sbrNoiseFloorLevel_man;
+ Int32 *noiseFloorLeft_exp = hFrameData1->sbrNoiseFloorLevel_exp;
+
+ Int32 *iEnvelopeRight_man = hFrameData2->iEnvelope_man;
+ Int32 *iEnvelopeRight_exp = hFrameData2->iEnvelope_exp;
+ Int32 *noiseFloorRight_man = hFrameData2->sbrNoiseFloorLevel_man;
+ Int32 *noiseFloorRight_exp = hFrameData2->sbrNoiseFloorLevel_exp;
+
+
+ if (hFrameData2->ampRes)
+ {
+ for (i = 0; i < hFrameData1->nScaleFactors; i++)
+ {
+ tempRight = iEnvelopeRight_man[i];
+ tempLeft = iEnvelopeLeft_man[i];
+ /* iEnvelope[i] always positive 6 bits max */
+
+ iEnvelopeLeft_exp[i] = tempLeft + 7;
+
+ iEnvelopeRight_exp[i] = tempRight - 12;
+ iEnvelopeRight_man[i] = Qfmt(1.000F);
+
+ /*
+ * iEnvelopeRight[i] = tempLeft / (1 + tempRight);
+ * iEnvelopeLeft[i] = tempRight * iEnvelopeRight[i];
+ *
+ *
+ * iEnvelopeRight[i] = k*2^n/(1+2^m) = k*2^(n-m)/(1 + 2^-m);
+ * where k = 1 or sqrt(2)
+ */
+ if (iEnvelopeRight_exp[i] >= 0)
+ {
+ if (iEnvelopeRight_exp[i] < 11)
+ {
+ iEnvelopeRight_man[i] = one_over_one_plus_two_to_n[ iEnvelopeRight_exp[i]];
+ }
+ else /* 1/(1+2^-m) == 1 - 2^-m ; for m >= 10 */
+ {
+ iEnvelopeRight_man[i] -= (Qfmt(1.000F) >> iEnvelopeRight_exp[i]);
+ }
+ iEnvelopeRight_exp[i] = iEnvelopeLeft_exp[i] - iEnvelopeRight_exp[i];
+ }
+ else
+ {
+ if (iEnvelopeRight_exp[i] > -11)
+ {
+ iEnvelopeRight_man[i] -= one_over_one_plus_two_to_n[ -iEnvelopeRight_exp[i]];
+ iEnvelopeRight_exp[i] = iEnvelopeLeft_exp[i] - iEnvelopeRight_exp[i];
+
+ }
+ else /* 1/(1+2^m) == 2^-m ; for m >= 10 */
+ {
+ iEnvelopeRight_exp[i] = iEnvelopeLeft_exp[i];
+ iEnvelopeLeft_exp[i] = 0;
+ }
+ }
+
+ iEnvelopeLeft_man[i] = iEnvelopeRight_man[i];
+ }
+ }
+ else
+ {
+ for (i = 0; i < hFrameData1->nScaleFactors; i++)
+ {
+ /* iEnvelope[i] always positive 7 bits max */
+ tempRight = iEnvelopeRight_man[i];
+ tempLeft = iEnvelopeLeft_man[i];
+
+ iEnvelopeLeft_exp[i] = (tempLeft >> 1) + 7;
+ if (tempLeft & 0x1) /* odd */
+ {
+ iEnvelopeLeft_man[i] = Qfmt(1.41421356237310F);
+ }
+ else
+ {
+ iEnvelopeLeft_man[i] = Qfmt(1.000F);
+ }
+
+ iEnvelopeRight_exp[i] = (tempRight >> 1) - 12;
+ if (tempRight & 0x1) /* odd */
+ {
+ if (iEnvelopeRight_exp[i] > 0)
+ {
+ iEnvelopeRight_man[i] = Qfmt(1.41421356237310F);
+ }
+ else
+ {
+ iEnvelopeRight_man[i] = Qfmt(0.7071067811865F);
+ }
+ }
+ else
+ {
+ iEnvelopeRight_man[i] = Qfmt(1.000F);
+ }
+
+ if (iEnvelopeRight_man[i] == Qfmt(1.000F))
+ {
+
+ /*
+ * iEnvelopeRight[i] = tempLeft / (1 + tempRight);
+ * iEnvelopeLeft[i] = tempRight * iEnvelopeRight[i];
+ *
+ *
+ * iEnvelopeRight[i] = k*2^n/(1+2^m) = k*2^(n-m)/(1 + 2^-m);
+ * where k = 1 or sqrt(2)
+ */
+ if (iEnvelopeRight_exp[i] >= 0)
+ {
+ if (iEnvelopeRight_exp[i] < 11)
+ {
+ iEnvelopeRight_man[i] = one_over_one_plus_two_to_n[ iEnvelopeRight_exp[i]];
+ }
+ else /* 1/(1+2^-m) == 1 - 2^-m ; for m >= 10 */
+ {
+ iEnvelopeRight_man[i] -= (Qfmt(1.000F) >> iEnvelopeRight_exp[i]);
+ }
+ iEnvelopeRight_exp[i] = iEnvelopeLeft_exp[i] - iEnvelopeRight_exp[i];
+
+ }
+ else
+ {
+ if (iEnvelopeRight_exp[i] > -11)
+ {
+ iEnvelopeRight_man[i] -= one_over_one_plus_two_to_n[ -iEnvelopeRight_exp[i]];
+ iEnvelopeRight_exp[i] = iEnvelopeLeft_exp[i] - iEnvelopeRight_exp[i];
+ }
+ else /* 1/(1+2^m) == 2^-m ; for m >= 10 */
+ {
+ iEnvelopeRight_exp[i] = iEnvelopeLeft_exp[i];
+ iEnvelopeLeft_exp[i] = 0;
+ }
+ }
+
+ /*
+ * apply "k" factor 1 or sqrt(2)
+ *
+ * (2^m)*2*k*2^n/(1+2^m) = k*2^(n+1)/(1 + 2^-m);
+ *
+ */
+ if (iEnvelopeLeft_man[i] != Qfmt(1.000F))
+ {
+ iEnvelopeRight_man[i] = fxp_mul32_Q30(iEnvelopeLeft_man[i], iEnvelopeRight_man[i]);
+ }
+
+ iEnvelopeLeft_man[i] = iEnvelopeRight_man[i];
+
+ }
+ else
+ {
+
+ /*
+ * iEnvelopeRight[i] = tempLeft / (1 + tempRight);
+ * iEnvelopeLeft[i] = tempRight * iEnvelopeRight[i];
+ *
+ *
+ * iEnvelopeRight[i] = k*2^n/(1+q2^m) = k*2^(n-m)/(1 + q2^-m);
+ * where k = 1 or sqrt(2)
+ * and q = sqrt(2)
+ */
+ if (iEnvelopeRight_exp[i] >= 0)
+ {
+ if (iEnvelopeRight_exp[i] < 12)
+ {
+ iEnvelopeRight_man[i] = one_over_one_plus_sq_2_by_two_to_n[ iEnvelopeRight_exp[i]];
+ }
+ else /* 1/(1+2^-m) == 1 - 2^-m ; for m >= 11 */
+ {
+ iEnvelopeRight_man[i] = Qfmt(1.000F) - (Qfmt(1.000F) >> iEnvelopeRight_exp[i]);
+ }
+ }
+ else
+ {
+ if (iEnvelopeRight_exp[i] > -12)
+ {
+ iEnvelopeRight_man[i] = Qfmt(1.000F) - one_over_one_plus_sq_2_by_two_to_n[ -iEnvelopeRight_exp[i]];
+ }
+ else /* 1/(1+2^m) == 2^-m ; for m >= 11 */
+ {
+ iEnvelopeRight_man[i] = Qfmt(1.000F);
+ iEnvelopeRight_exp[i] = 0;
+ }
+ }
+
+ iEnvelopeRight_exp[i] = iEnvelopeLeft_exp[i] - iEnvelopeRight_exp[i];
+
+ /*
+ * apply "k" factor 1 or sqrt(2)
+ *
+ * Right == k*2^(n-m)/(1 + q2^-m)
+ * Left == (q2^m)*k*2^n/(1 + q2^m) = qk*2^n/(1 + q2^-m);
+ */
+ if (iEnvelopeLeft_man[i] != Qfmt(1.000F))
+ {
+ /*
+ * k/(1 + q2^-m);
+ */
+ tmp = iEnvelopeRight_man[i];
+ iEnvelopeRight_man[i] = fxp_mul32_Q30(iEnvelopeLeft_man[i], iEnvelopeRight_man[i]);
+ iEnvelopeLeft_man[i] = tmp;
+ iEnvelopeLeft_exp[i] += 1; /* extra one due to sqrt(2)^2 */
+ }
+ else
+ {
+ iEnvelopeLeft_man[i] = fxp_mul32_Q30(iEnvelopeRight_man[i], Qfmt(1.41421356237310F));
+ }
+
+ } /* end of if (iEnvelopeRight_man[i] == Qfmt( 1.000F) ) */
+ } /* end of for loop */
+ } /* end if (hFrameData2->ampRes) */
+
+
+ for (i = 0; i < hFrameData1->nNoiseFactors; i++)
+ {
+
+ noiseFloorLeft_exp[i] = NOISE_FLOOR_OFFSET_PLUS_1 - noiseFloorLeft_man[i];
+ noiseFloorRight_exp[i] = noiseFloorRight_man[i] - SBR_ENERGY_PAN_OFFSET_INT;
+
+
+ /*
+ * noiseFloorRight[i] = tempLeft / (1.0f + tempRight);
+ * noiseFloorLeft[i] = tempRight*noiseFloorRight[i];
+ *
+ *
+ * noiseFloorRight[i] = 2^n/(1+2^m) = 2^(n-m)/(1 + 2^-m);
+ */
+ if (noiseFloorRight_exp[i] >= 0)
+ {
+ if (noiseFloorRight_exp[i] < 11)
+ {
+ noiseFloorRight_man[i] = one_over_one_plus_two_to_n[ noiseFloorRight_exp[i]];
+ }
+ else /* 1/(1+2^-m) == 1 - 2^-m ; for m >= 10 */
+ {
+ noiseFloorRight_man[i] = Qfmt(1.000F) - (Qfmt(1.000F) >> noiseFloorRight_exp[i]);
+ }
+ }
+ else
+ {
+ if (noiseFloorRight_exp[i] > -11)
+ {
+ noiseFloorRight_man[i] = Qfmt(1.000F) - one_over_one_plus_two_to_n[ -noiseFloorRight_exp[i]];
+ }
+ else /* 1/(1+2^m) == 2^-m ; for m >= 10 */
+ {
+ noiseFloorRight_man[i] = Qfmt(1.000F);
+ noiseFloorRight_exp[i] = 0;
+ }
+ }
+
+ noiseFloorRight_exp[i] = noiseFloorLeft_exp[i] - noiseFloorRight_exp[i];
+
+ /*
+ * (2^m)*2^n/(1+2^m) = 2^n/(1 + 2^-m);
+ */
+
+ noiseFloorLeft_man[i] = noiseFloorRight_man[i];
+ noiseFloorLeft_exp[i] = noiseFloorLeft_exp[i];
+
+ }
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_envelope_unmapping.h b/media/libstagefright/codecs/aacdec/sbr_envelope_unmapping.h
new file mode 100644
index 0000000..b949830
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_envelope_unmapping.h
@@ -0,0 +1,89 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_envelope_unmapping.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_ENVELOPE_UNMAPPING_H
+#define SBR_ENVELOPE_UNMAPPING_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_sbr_frame_data.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+#define UNMAPPING_SCALE_INT (-18) /* factor's 2-exponent */
+#define SBR_ENERGY_PAN_OFFSET_INT 12
+
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void sbr_envelope_unmapping(SBR_FRAME_DATA * hFrameData1,
+ SBR_FRAME_DATA * hFrameData2);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_extract_extended_data.cpp b/media/libstagefright/codecs/aacdec/sbr_extract_extended_data.cpp
new file mode 100644
index 0000000..92b22f7
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_extract_extended_data.cpp
@@ -0,0 +1,223 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_extract_extended_data.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ SBR_FRAME_DATA *hFrameData, Destination for extracted data of left channel
+ SBR_FRAME_DATA *hFrameDataRight Destination for extracted data of right channel
+ BIT_BUFFER hBitBuf pointer to bit buffer
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Reads extension data from the bitstream
+
+ The bitstream format allows up to 4 kinds of extended data element.
+ Extended data may contain several elements, each identified by a 2-bit-ID.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_extract_extended_data.h"
+#include "buf_getbits.h"
+
+#ifdef PARAMETRICSTEREO
+#include "ps_read_data.h"
+#endif
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void sbr_extract_extended_data(BIT_BUFFER * hBitBuf
+#ifdef PARAMETRICSTEREO /* Parametric Stereo Decoder */
+ , HANDLE_PS_DEC hParametricStereoDec
+#endif
+ )
+{
+ Int32 extended_data;
+ Int32 i;
+ Int32 nBitsLeft;
+ Int32 extension_id;
+
+ extended_data = buf_get_1bit(hBitBuf); /* SI_SBR_EXTENDED_DATA_BITS */
+
+ if (extended_data)
+ {
+ Int32 cnt;
+
+ cnt = buf_getbits(hBitBuf, SI_SBR_EXTENSION_SIZE_BITS);
+ if (cnt == (1 << SI_SBR_EXTENSION_SIZE_BITS) - 1)
+ {
+ cnt += buf_getbits(hBitBuf, SI_SBR_EXTENSION_ESC_COUNT_BITS);
+ }
+
+ nBitsLeft = (cnt << 3);
+ while (nBitsLeft > 7)
+ {
+ extension_id = buf_getbits(hBitBuf, SI_SBR_EXTENSION_ID_BITS);
+ nBitsLeft -= SI_SBR_EXTENSION_ID_BITS;
+
+ switch (extension_id)
+ {
+#ifdef HQ_SBR
+#ifdef PARAMETRICSTEREO
+
+ /*
+ * Parametric Coding supports the Transient, Sinusoidal, Noise, and
+ * Parametric Stereo tools (MPEG4).
+ * 3GPP use aac+ hq along with ps for enhanced aac+
+ * The PS tool uses complex-value QMF data, therefore can not be used
+ * with low power version of aac+
+ */
+ case EXTENSION_ID_PS_CODING:
+
+ if (hParametricStereoDec != NULL)
+ {
+ if (!hParametricStereoDec->psDetected)
+ {
+ /* parametric stereo detected */
+ hParametricStereoDec->psDetected = 1;
+ }
+
+ nBitsLeft -= ps_read_data(hParametricStereoDec,
+ hBitBuf,
+ nBitsLeft);
+
+ }
+
+ break;
+#endif
+#endif
+ case 0:
+
+ default:
+ /* An unknown extension id causes the remaining extension data
+ * to be skipped
+ */
+ cnt = nBitsLeft >> 3; /* number of remaining bytes */
+
+ for (i = 0; i < cnt; i++)
+ {
+ buf_getbits(hBitBuf, 8);
+ }
+
+ nBitsLeft -= (cnt << 3);
+ }
+ }
+ /* read fill bits for byte alignment */
+ buf_getbits(hBitBuf, nBitsLeft);
+ }
+}
+
+
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_extract_extended_data.h b/media/libstagefright/codecs/aacdec/sbr_extract_extended_data.h
new file mode 100644
index 0000000..bbca3b9
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_extract_extended_data.h
@@ -0,0 +1,93 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_extract_extended_data.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_EXTRACT_EXTENDED_DATA_H
+#define SBR_EXTRACT_EXTENDED_DATA_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bit_buffer.h"
+#include "s_sbr_frame_data.h"
+
+#ifdef PARAMETRICSTEREO
+#include "s_ps_dec.h"
+#endif
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void sbr_extract_extended_data(BIT_BUFFER * hBitBuf
+#ifdef PARAMETRICSTEREO /* Parametric Stereo Decoder */
+ , HANDLE_PS_DEC hParametricStereoDec
+#endif
+ );
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_find_start_andstop_band.cpp b/media/libstagefright/codecs/aacdec/sbr_find_start_andstop_band.cpp
new file mode 100644
index 0000000..fc3d38f
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_find_start_andstop_band.cpp
@@ -0,0 +1,198 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_find_start_andstop_band.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_find_start_andstop_band.h"
+#include "get_sbr_startfreq.h"
+#include "get_sbr_stopfreq.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+SBR_ERROR sbr_find_start_andstop_band(const Int32 samplingFreq,
+ const Int32 startFreq,
+ const Int32 stopFreq,
+ Int *lsbM,
+ Int *usb)
+{
+ /* Update startFreq struct */
+ *lsbM = get_sbr_startfreq(samplingFreq, startFreq);
+
+ if (*lsbM == 0)
+ {
+ return(SBRDEC_ILLEGAL_SCFACTORS);
+ }
+
+ /*Update stopFreq struct */
+ if (stopFreq < 13)
+ {
+ *usb = get_sbr_stopfreq(samplingFreq, stopFreq);
+ }
+ else if (stopFreq == 13)
+ {
+ *usb = 64;
+ }
+ else if (stopFreq == 14)
+ {
+ *usb = (*lsbM) << 1;
+ }
+ else
+ {
+ *usb = 3 * *lsbM;
+ }
+
+ /* limit to Nyqvist */
+ if (*usb > 64)
+ {
+ *usb = 64;
+ }
+
+ /* test for invalid lsb, usb combinations */
+ if ((*usb - *lsbM) > 48)
+ {
+ /*
+ * invalid SBR bitstream ?
+ */
+ return(SBRDEC_INVALID_BITSTREAM);
+ }
+
+ if ((samplingFreq == 44100) && ((*usb - *lsbM) > 35))
+ {
+ /*
+ * invalid SBR bitstream ?
+ */
+ return(SBRDEC_INVALID_BITSTREAM);
+ }
+
+ if ((samplingFreq >= 48000) && ((*usb - *lsbM) > 32))
+ {
+ /*
+ * invalid SBR bitstream ?
+ */
+ return(SBRDEC_INVALID_BITSTREAM);
+ }
+
+ return(SBRDEC_OK);
+
+}
+
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_find_start_andstop_band.h b/media/libstagefright/codecs/aacdec/sbr_find_start_andstop_band.h
new file mode 100644
index 0000000..88283c6
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_find_start_andstop_band.h
@@ -0,0 +1,89 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_find_start_andstop_band.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+ ----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_FIND_START_ANDSTOP_BAND_H
+#define SBR_FIND_START_ANDSTOP_BAND_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_sbr_error.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+SBR_ERROR sbr_find_start_andstop_band(const Int32 samplingFreq,
+ const Int32 startFreq,
+ const Int32 stopFreq,
+ Int *lsbM,
+ Int *usb);
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_generate_high_freq.cpp b/media/libstagefright/codecs/aacdec/sbr_generate_high_freq.cpp
new file mode 100644
index 0000000..2126e47
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_generate_high_freq.cpp
@@ -0,0 +1,1040 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_generate_high_freq.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ HF generator with built-in QMF bank inverse filtering function
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#ifdef AAC_PLUS
+
+
+
+#include "sbr_generate_high_freq.h"
+#include "calc_auto_corr.h"
+#include "sbr_inv_filt_levelemphasis.h"
+#include "pv_div.h"
+#include "fxp_mul32.h"
+#include "aac_mem_funcs.h"
+#include "sbr_constants.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void high_freq_coeff_LC(Int32 sourceBufferReal[][32],
+ Int32 *alphar[2],
+ Int32 *degreeAlias,
+ Int32 *v_k_master,
+ Int32 *scratch_mem);
+
+
+ void high_freq_generation_LC(Int32 sourceBufferReal[][32],
+ Int32 *targetBufferReal,
+ Int32 *alphar[2],
+ Int32 *degreeAlias,
+ Int32 *invFiltBandTable,
+ Int32 targetStopBand,
+ Int32 patchDistance,
+ Int32 numBandsInPatch,
+ Int32 startSample,
+ Int32 slopeLength,
+ Int32 stopSample,
+ Int32 *BwVector,
+ Int32 sbrStartFreqOffset);
+
+
+#ifdef HQ_SBR
+
+ void high_freq_coeff(Int32 sourceBufferReal[][32],
+ Int32 sourceBufferImag[][32],
+ Int32 *alphar[2],
+ Int32 *alphai[2],
+ Int32 *v_k_master);
+
+ void high_freq_generation(Int32 sourceBufferReal[][32],
+ Int32 sourceBufferImag[][32],
+ Int32 *targetBufferReal,
+ Int32 *targetBufferImag,
+ Int32 *alphar[2],
+ Int32 *alphai[2],
+ Int32 *invFiltBandTable,
+ Int32 targetStopBand,
+ Int32 patchDistance,
+ Int32 numBandsInPatch,
+ Int32 startSample,
+ Int32 slopeLength,
+ Int32 stopSample,
+ Int32 *BwVector,
+ Int32 sbrStartFreqOffset);
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void sbr_generate_high_freq(Int32 sourceBufferReal[][32],
+ Int32 sourceBufferImag[][32],
+ Int32 *targetBufferReal,
+ Int32 *targetBufferImag,
+ INVF_MODE *invFiltMode,
+ INVF_MODE *prevInvFiltMode,
+ Int32 *invFiltBandTable,
+ Int32 noInvFiltBands,
+ Int32 highBandStartSb,
+ Int32 *v_k_master,
+ Int32 numMaster,
+ Int32 fs,
+ Int32 *frameInfo,
+ Int32 *degreeAlias,
+ Int32 scratch_mem[][64],
+ Int32 BwVector[MAX_NUM_PATCHES],
+ Int32 BwVectorOld[MAX_NUM_PATCHES],
+ struct PATCH *Patch,
+ Int32 LC_flag,
+ Int32 *highBandStopSb)
+{
+ Int32 i;
+ Int32 patch;
+ Int32 startSample;
+ Int32 stopSample;
+ Int32 goalSb;
+ Int32 targetStopBand;
+ Int32 sourceStartBand;
+ Int32 patchDistance;
+ Int32 numBandsInPatch;
+ Int32 sbrStartFreqOffset;
+
+ Int32 *alphar[2];
+ Int32 *alphai[2];
+
+ Int32 lsb = v_k_master[0]; /* Lowest subband related to the synthesis filterbank */
+ Int32 usb = v_k_master[numMaster]; /* Stop subband related to the synthesis filterbank */
+ Int32 xoverOffset = highBandStartSb - v_k_master[0]; /* Calculate distance in subbands between k0 and kx */
+
+
+
+ Int slopeLength = 0;
+
+ Int32 firstSlotOffs = frameInfo[1];
+ Int32 lastSlotOffs = frameInfo[frameInfo[0] + 1] - 16;
+
+
+ alphar[0] = scratch_mem[0];
+ alphar[1] = scratch_mem[1];
+ alphai[0] = scratch_mem[2];
+ alphai[1] = scratch_mem[3];
+
+
+ startSample = (firstSlotOffs << 1);
+ stopSample = (lastSlotOffs << 1) + 32;
+
+
+ sbr_inv_filt_levelemphasis(invFiltMode,
+ prevInvFiltMode,
+ noInvFiltBands,
+ BwVector,
+ BwVectorOld);
+
+
+ if (LC_flag == ON)
+ {
+ /* Set subbands to zero */
+
+ pv_memset((void *)&targetBufferReal[startSample*SBR_NUM_BANDS],
+ 0,
+ (stopSample - startSample)*SBR_NUM_BANDS*sizeof(targetBufferReal[0]));
+
+ high_freq_coeff_LC(sourceBufferReal,
+ alphar,
+ degreeAlias,
+ v_k_master,
+ scratch_mem[4]);
+ }
+#ifdef HQ_SBR
+ else
+ {
+ /* Set subbands to zero */
+
+ pv_memset((void *)&targetBufferReal[startSample*SBR_NUM_BANDS],
+ 0,
+ (stopSample - startSample)*SBR_NUM_BANDS*sizeof(targetBufferReal[0]));
+ pv_memset((void *)&targetBufferImag[startSample*SBR_NUM_BANDS],
+ 0,
+ (stopSample - startSample)*SBR_NUM_BANDS*sizeof(targetBufferImag[0]));
+
+ high_freq_coeff(sourceBufferReal,
+ sourceBufferImag,
+ alphar,
+ alphai,
+ v_k_master);
+
+ }
+#endif /* #ifdef HQ_SBR */
+
+
+
+
+ /*
+ * Initialize the patching parameter
+ */
+ switch (fs)
+
+ {
+ /*
+ * goalSb = (int)( 2.048e6f / fs + 0.5f );
+ */
+ case 48000:
+ goalSb = 43; /* 16 kHz band */
+ break;
+ case 32000:
+ goalSb = 64; /* 16 kHz band */
+ break;
+ case 24000:
+ goalSb = 85; /* 16 kHz band */
+ break;
+ case 22050:
+ goalSb = 93; /* 16 kHz band */
+ break;
+ case 16000:
+ goalSb = 128; /* 16 kHz band */
+ break;
+ case 44100:
+ default:
+ goalSb = 46; /* 16 kHz band */
+ break;
+ }
+
+ i = 0;
+
+ if (goalSb > v_k_master[0])
+ {
+ if (goalSb < v_k_master[numMaster])
+ {
+ while (v_k_master[i] < goalSb)
+ {
+ i++;
+ }
+ }
+ else
+ {
+ i = numMaster;
+ }
+ }
+
+ goalSb = v_k_master[i];
+
+ /* First patch */
+ sourceStartBand = xoverOffset + 1;
+ targetStopBand = lsb + xoverOffset;
+
+ /* even (odd) numbered channel must be patched to even (odd) numbered channel */
+ patch = 0;
+
+
+ sbrStartFreqOffset = targetStopBand;
+
+ while (targetStopBand < usb)
+ {
+ Patch->targetStartBand[patch] = targetStopBand;
+
+ numBandsInPatch = goalSb - targetStopBand; /* get the desired range of the patch */
+
+ if (numBandsInPatch >= lsb - sourceStartBand)
+ {
+ /* desired number bands are not available -> patch whole source range */
+ patchDistance = targetStopBand - sourceStartBand; /* get the targetOffset */
+ patchDistance = patchDistance & ~1; /* rounding off odd numbers and make all even */
+ numBandsInPatch = lsb - (targetStopBand - patchDistance);
+
+ if (targetStopBand + numBandsInPatch > v_k_master[0])
+ {
+ i = numMaster;
+ if (targetStopBand + numBandsInPatch < v_k_master[numMaster])
+ {
+ while (v_k_master[i] > targetStopBand + numBandsInPatch)
+ {
+ i--;
+ }
+ }
+ }
+ else
+ {
+ i = 0;
+ }
+ numBandsInPatch = v_k_master[i] - targetStopBand;
+ }
+
+ /* desired number bands are available -> get the minimal even patching distance */
+ patchDistance = numBandsInPatch + targetStopBand - lsb; /* get minimal distance */
+ patchDistance = (patchDistance + 1) & ~1; /* rounding up odd numbers and make all even */
+
+ /* All patches but first */
+ sourceStartBand = 1;
+
+ /* Check if we are close to goalSb */
+ if (goalSb - (targetStopBand + numBandsInPatch) < 3)
+ { /* MPEG doc */
+ goalSb = usb;
+ }
+
+
+ if ((numBandsInPatch < 3) && (patch > 0))
+ {
+ if (LC_flag == ON)
+ {
+
+ pv_memset((void *) &degreeAlias[targetStopBand], 0, numBandsInPatch*sizeof(*degreeAlias));
+ }
+ break;
+ }
+
+ if (numBandsInPatch <= 0)
+ {
+ continue;
+ }
+
+
+ /*
+ * High Frequency generation
+ */
+
+ if (LC_flag == ON)
+ {
+
+ high_freq_generation_LC(sourceBufferReal,
+ (Int32 *)targetBufferReal,
+ alphar,
+ degreeAlias,
+ invFiltBandTable,
+ targetStopBand,
+ patchDistance,
+ numBandsInPatch,
+ startSample,
+ slopeLength,
+ stopSample,
+ BwVector,
+ sbrStartFreqOffset);
+
+ }
+#ifdef HQ_SBR
+ else
+ {
+
+ high_freq_generation(sourceBufferReal,
+ sourceBufferImag,
+ (Int32 *)targetBufferReal,
+ (Int32 *)targetBufferImag,
+ alphar,
+ alphai,
+ invFiltBandTable,
+ targetStopBand,
+ patchDistance,
+ numBandsInPatch,
+ startSample,
+ slopeLength,
+ stopSample,
+ BwVector,
+ sbrStartFreqOffset);
+
+ }
+#endif
+
+ targetStopBand += numBandsInPatch;
+
+ patch++;
+
+ } /* targetStopBand */
+
+ Patch->noOfPatches = patch;
+
+ pv_memmove(BwVectorOld, BwVector, noInvFiltBands*sizeof(BwVector[0]));
+
+ *highBandStopSb = goalSb;
+
+
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void high_freq_coeff_LC(Int32 sourceBufferReal[][32],
+ Int32 *alphar[2],
+ Int32 *degreeAlias,
+ Int32 *v_k_master,
+ Int32 *scratch_mem)
+{
+
+ Int32 fac;
+ Int32 *k1;
+ struct ACORR_COEFS ac;
+ struct intg_div quotient;
+
+ Int32 temp1;
+ Int32 temp2;
+ Int32 temp3;
+ Int32 autoCorrLength;
+ Int32 loBand;
+
+ k1 = scratch_mem;
+
+
+ autoCorrLength = 38;
+
+ for (loBand = 1; loBand < v_k_master[0]; loBand++)
+ {
+
+ calc_auto_corr_LC(&ac,
+ sourceBufferReal,
+ loBand,
+ autoCorrLength);
+
+ if (ac.r11r && ac.det)
+ {
+
+ pv_div(ac.r01r, ac.r11r, &quotient);
+
+ fac = -(quotient.quotient >> 2); /* Q28 */
+
+ if (quotient.shift_factor > 0)
+ {
+ fac >>= quotient.shift_factor; /* Q28 */
+ }
+ else if (quotient.shift_factor < 0)
+ {
+ if (quotient.shift_factor > -4) /* |fac| < 8 */
+ {
+ fac <<= (-quotient.shift_factor); /* Q28 */
+ }
+ else
+ {
+ fac = 0x80000000; /* overshoot possible fac = -8 */
+ }
+ }
+
+ /*
+ * prevent for overflow of reflection coefficients
+ */
+ if (quotient.shift_factor > 0)
+ {
+ k1[loBand] = - quotient.quotient >> quotient.shift_factor;
+ }
+ else if (quotient.shift_factor == 0)
+ {
+ if (quotient.quotient >= 0x40000000)
+ {
+ k1[loBand] = (Int32)0xC0000000; /* -1.0 in Q30 */
+ }
+ else if (quotient.quotient <= (Int32)0xC0000000)
+ {
+ k1[loBand] = 0x40000000; /* 1.0 in Q30 */
+ }
+ else
+ {
+ k1[loBand] = -quotient.quotient;
+ }
+ }
+ else
+ {
+ if (quotient.quotient > 0)
+ {
+ k1[loBand] = (Int32)0xC0000000; /* -1.0 in Q30 */
+ }
+ else
+ {
+ k1[loBand] = 0x40000000; /* 1.0 in Q30 */
+ }
+ }
+ /*
+ * alphar[1][loBand] = ( ac.r01r * ac.r12r - ac.r02r * ac.r11r ) / ac.det;
+ */
+
+ temp1 = -fxp_mul32_Q30(ac.r02r, ac.r11r);
+ temp1 = fxp_mac32_Q30(ac.r01r, ac.r12r, temp1);
+
+ temp2 = ac.det;
+ temp3 = temp1 > 0 ? temp1 : -temp1;
+ temp2 = temp2 > 0 ? temp2 : -temp2;
+
+ /* prevent for shootovers */
+ if ((temp3 >> 2) >= temp2 || fac == (Int32)0x80000000)
+ {
+ alphar[0][loBand] = 0;
+ alphar[1][loBand] = 0;
+ }
+ else
+ {
+ pv_div(temp1, ac.det, &quotient);
+ /*
+ * alphar[1][loBand] is lesser than 4.0
+ */
+ alphar[1][loBand] = quotient.quotient;
+ quotient.shift_factor += 2; /* Q28 */
+
+ if (quotient.shift_factor > 0)
+ {
+ alphar[1][loBand] >>= quotient.shift_factor; /* Q28 */
+ }
+ else if (quotient.shift_factor < 0) /* at this point can only be -1 */
+ {
+ alphar[1][loBand] <<= (-quotient.shift_factor); /* Q28 */
+ }
+
+ /*
+ * alphar[0][loBand] = - ( ac.r01r + alphar[1][loBand] * ac.r12r ) / ac.r11r;
+ */
+
+ pv_div(ac.r12r, ac.r11r, &quotient);
+
+ temp3 = (quotient.quotient >> 2); /* Q28 */
+
+ if (quotient.shift_factor > 0)
+ {
+ temp3 >>= quotient.shift_factor; /* Q28 */
+ }
+ else if (quotient.shift_factor < 0)
+ {
+ temp3 <<= (-quotient.shift_factor); /* Q28 */
+ }
+
+ alphar[0][loBand] = fac - fxp_mul32_Q28(alphar[1][loBand], temp3) ; /* Q28 */
+
+ if ((alphar[0][loBand] >= 0x40000000) || (alphar[0][loBand] <= (Int32)0xC0000000))
+ {
+ alphar[0][loBand] = 0;
+ alphar[1][loBand] = 0;
+ }
+
+ }
+
+ }
+ else
+ {
+ alphar[0][loBand] = 0;
+ alphar[1][loBand] = 0;
+
+ k1[loBand] = 0;
+ }
+
+ }
+
+ k1[0] = 0;
+ degreeAlias[1] = 0;
+ for (loBand = 2; loBand < v_k_master[0]; loBand++)
+ {
+ degreeAlias[loBand] = 0;
+ if ((!(loBand & 1)) && (k1[loBand] < 0))
+ {
+ if (k1[loBand-1] < 0)
+ { // 2-CH Aliasing Detection
+ degreeAlias[loBand] = 0x40000000;
+ if (k1[loBand-2] > 0)
+ { // 3-CH Aliasing Detection
+ degreeAlias[loBand-1] = 0x40000000 - fxp_mul32_Q30(k1[loBand-1], k1[loBand-1]);
+
+ }
+ }
+ else if (k1[loBand-2] > 0)
+ { // 3-CH Aliasing Detection
+ degreeAlias[loBand] = 0x40000000 - fxp_mul32_Q30(k1[loBand-1], k1[loBand-1]);
+ }
+ }
+ if ((loBand & 1) && (k1[loBand] > 0))
+ {
+ if (k1[loBand-1] > 0)
+ { // 2-CH Aliasing Detection
+ degreeAlias[loBand] = 0x40000000;
+ if (k1[loBand-2] < 0)
+ { // 3-CH Aliasing Detection
+ degreeAlias[loBand-1] = 0x40000000 - fxp_mul32_Q30(k1[loBand-1], k1[loBand-1]);
+ }
+ }
+ else if (k1[loBand-2] < 0)
+ { // 3-CH Aliasing Detection
+ degreeAlias[loBand] = 0x40000000 - fxp_mul32_Q30(k1[loBand-1], k1[loBand-1]);
+ }
+ }
+ }
+
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void high_freq_generation_LC(Int32 sourceBufferReal[][32],
+ Int32 *targetBufferReal,
+ Int32 *alphar[2],
+ Int32 *degreeAlias,
+ Int32 *invFiltBandTable,
+ Int32 targetStopBand,
+ Int32 patchDistance,
+ Int32 numBandsInPatch,
+ Int32 startSample,
+ Int32 slopeLength,
+ Int32 stopSample,
+ Int32 *BwVector,
+ Int32 sbrStartFreqOffset)
+{
+
+ Int32 temp1;
+ Int32 temp2;
+ Int32 temp3;
+
+
+ Int32 a0r;
+ Int32 a1r;
+ Int32 i;
+ Int32 bw;
+ Int32 hiBand;
+ Int32 bwIndex;
+ Int32 loBand;
+ Int32 j;
+
+ bwIndex = 0;
+
+ for (hiBand = targetStopBand; hiBand < targetStopBand + numBandsInPatch; hiBand++)
+ {
+ loBand = hiBand - patchDistance;
+
+ if (hiBand != targetStopBand)
+ {
+ degreeAlias[hiBand] = degreeAlias[loBand];
+ }
+ else
+ {
+ degreeAlias[hiBand] = 0;
+ }
+
+ while (hiBand >= invFiltBandTable[bwIndex])
+ {
+ bwIndex++;
+ }
+
+ bw = BwVector[bwIndex];
+
+ /*
+ * Inverse Filtering
+ */
+
+
+ j = hiBand - sbrStartFreqOffset;
+
+ if (bw > 0 && (alphar[0][loBand] | alphar[1][loBand]))
+ {
+ /* Apply current bandwidth expansion factor */
+ a0r = fxp_mul32_Q29(bw, alphar[0][loBand]);
+
+ bw = fxp_mul32_Q31(bw, bw) << 2;
+
+ a1r = fxp_mul32_Q28(bw, alphar[1][loBand]);
+
+ i = startSample + slopeLength;
+
+ temp1 = sourceBufferReal[i ][loBand];
+ temp2 = sourceBufferReal[i - 1][loBand];
+ temp3 = sourceBufferReal[i - 2][loBand];
+
+ for (; i < stopSample + slopeLength - 1; i++)
+ {
+
+
+ targetBufferReal[i*SBR_NUM_BANDS + j] = temp1 + fxp_mul32_Q28(a0r, temp2) +
+ fxp_mul32_Q28(a1r, temp3);
+
+
+ temp3 = temp2;
+ temp2 = temp1;
+ temp1 = sourceBufferReal[i + 1][loBand];
+ }
+ targetBufferReal[i*SBR_NUM_BANDS + j] = temp1 + fxp_mul32_Q28(a0r, temp2) +
+ fxp_mul32_Q28(a1r, temp3);
+
+ }
+ else
+ {
+
+ for (i = startSample + slopeLength; i < stopSample + slopeLength; i++)
+ {
+ targetBufferReal[i*SBR_NUM_BANDS + j] = sourceBufferReal[i][loBand];
+ }
+ }
+
+
+ } /* hiBand */
+
+}
+
+
+#ifdef HQ_SBR
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void high_freq_coeff(Int32 sourceBufferReal[][32],
+ Int32 sourceBufferImag[][32],
+ Int32 *alphar[2],
+ Int32 *alphai[2],
+ Int32 *v_k_master)
+{
+
+ Int32 overflow_flag;
+
+ Int32 temp1r;
+ Int32 temp1i;
+ Int32 temp0r;
+ Int32 temp0i;
+ Int32 loBand;
+
+ struct ACORR_COEFS ac;
+ struct intg_div quotient;
+
+ Int32 autoCorrLength;
+
+ autoCorrLength = 38;
+
+ for (loBand = 1; loBand < v_k_master[0]; loBand++)
+ {
+
+ calc_auto_corr(&ac,
+ sourceBufferReal,
+ sourceBufferImag,
+ loBand,
+ autoCorrLength);
+
+
+ overflow_flag = 0;
+
+ if (ac.det < 1)
+ {
+ /* --- */
+ temp1r = 0;
+ temp1i = 0;
+ alphar[1][loBand] = 0;
+ alphai[1][loBand] = 0;
+
+ }
+ else
+ {
+
+ temp1r = fxp_mul32_Q29(ac.r01r, ac.r12r);
+ temp1r = fxp_msu32_Q29(ac.r01i, ac.r12i, temp1r);
+ temp1r = fxp_msu32_Q29(ac.r02r, ac.r11r, temp1r);
+
+ temp1i = fxp_mul32_Q29(ac.r01r, ac.r12i);
+ temp1i = fxp_msu32_Q29(ac.r02i, ac.r11r, temp1i);
+ temp1i = fxp_mac32_Q29(ac.r01i, ac.r12r, temp1i);
+
+ pv_div(temp1r, ac.det, &quotient);
+ overflow_flag = (quotient.shift_factor < -2) ? 1 : 0;
+ temp1r = quotient.quotient >> (2 + quotient.shift_factor); /* Q28 */
+ pv_div(temp1i, ac.det, &quotient);
+ overflow_flag = (quotient.shift_factor < -2) ? 1 : 0;
+ temp1i = quotient.quotient >> (2 + quotient.shift_factor); /* Q28 */
+
+ alphar[1][loBand] = temp1r;
+ alphai[1][loBand] = temp1i;
+
+ }
+
+ if (ac.r11r == 0)
+ {
+ temp0r = 0;
+ temp0i = 0;
+ alphar[0][loBand] = 0;
+ alphai[0][loBand] = 0;
+
+ }
+ else
+ {
+ temp0r = - (ac.r01r + fxp_mul32_Q28(temp1r, ac.r12r) + fxp_mul32_Q28(temp1i, ac.r12i));
+ temp0i = - (ac.r01i + fxp_mul32_Q28(temp1i, ac.r12r) - fxp_mul32_Q28(temp1r, ac.r12i));
+
+ pv_div(temp0r, ac.r11r, &quotient);
+ overflow_flag = (quotient.shift_factor < -2) ? 1 : 0;
+ temp0r = quotient.quotient >> (2 + quotient.shift_factor); /* Q28 */
+ pv_div(temp0i, ac.r11r, &quotient);
+ overflow_flag = (quotient.shift_factor < -2) ? 1 : 0;
+ temp0i = quotient.quotient >> (2 + quotient.shift_factor); /* Q28 */
+
+ alphar[0][loBand] = temp0r;
+ alphai[0][loBand] = temp0i;
+
+ }
+
+ /* prevent for shootovers */
+
+ if (fxp_mul32_Q28((temp0r >> 2), (temp0r >> 2)) + fxp_mul32_Q28((temp0i >> 2), (temp0i >> 2)) >= 0x10000000 ||
+ fxp_mul32_Q28((temp1r >> 2), (temp1r >> 2)) + fxp_mul32_Q28((temp1i >> 2), (temp1i >> 2)) >= 0x10000000 ||
+ overflow_flag) /* 0x10000000 == 1 in Q28 */
+
+ {
+ alphar[0][loBand] = 0;
+ alphar[1][loBand] = 0;
+ alphai[0][loBand] = 0;
+ alphai[1][loBand] = 0;
+
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+void high_freq_generation(Int32 sourceBufferReal[][32],
+ Int32 sourceBufferImag[][32],
+ Int32 *targetBufferReal,
+ Int32 *targetBufferImag,
+ Int32 *alphar[2],
+ Int32 *alphai[2],
+ Int32 *invFiltBandTable,
+ Int32 targetStopBand,
+ Int32 patchDistance,
+ Int32 numBandsInPatch,
+ Int32 startSample,
+ Int32 slopeLength,
+ Int32 stopSample,
+ Int32 *BwVector,
+ Int32 sbrStartFreqOffset)
+{
+ Int32 temp1_r;
+ Int32 temp2_r;
+ Int32 temp3_r;
+ Int32 temp1_i;
+ Int32 temp2_i;
+ Int32 temp3_i;
+
+
+ Int32 a0i;
+ Int32 a1i;
+ Int32 a0r;
+ Int32 a1r;
+ Int32 i;
+ Int32 bw;
+ Int32 hiBand;
+ Int32 bwIndex;
+ Int32 loBand;
+ Int32 j;
+
+
+
+ int64_t tmp;
+
+ bwIndex = 0;
+
+ for (hiBand = targetStopBand; hiBand < targetStopBand + numBandsInPatch; hiBand++)
+ {
+
+ loBand = hiBand - patchDistance;
+
+ while (hiBand >= invFiltBandTable[bwIndex])
+ {
+ bwIndex++;
+ }
+
+ bw = BwVector[bwIndex];
+
+ /*
+ * Inverse Filtering
+ */
+
+
+ j = hiBand - sbrStartFreqOffset;
+
+ if (bw >= 0 && (alphar[0][loBand] | alphar[1][loBand] |
+ alphai[0][loBand] | alphai[1][loBand]))
+ {
+ /* Apply current bandwidth expansion factor */
+ a0r = fxp_mul32_Q29(bw, alphar[0][loBand]);
+ a0i = fxp_mul32_Q29(bw, alphai[0][loBand]);
+
+
+ bw = fxp_mul32_Q30(bw, bw);
+
+
+ a1r = fxp_mul32_Q28(bw, alphar[1][loBand]);
+ a1i = fxp_mul32_Q28(bw, alphai[1][loBand]);
+
+
+ i = startSample + slopeLength;
+ j += i * SBR_NUM_BANDS;
+
+ temp1_r = sourceBufferReal[i ][loBand];
+ temp2_r = sourceBufferReal[i - 1][loBand];
+ temp3_r = sourceBufferReal[i - 2][loBand];
+
+ temp1_i = sourceBufferImag[i ][loBand];
+ temp2_i = sourceBufferImag[i - 1][loBand];
+ temp3_i = sourceBufferImag[i - 2][loBand];
+
+ while (i < stopSample + slopeLength)
+ {
+ tmp = fxp_mac64_Q31(((int64_t)temp1_r << 28), a0r, temp2_r);
+ tmp = fxp_mac64_Q31(tmp, -a0i, temp2_i);
+ tmp = fxp_mac64_Q31(tmp, a1r, temp3_r);
+ targetBufferReal[j] = (Int32)(fxp_mac64_Q31(tmp, -a1i, temp3_i) >> 28);
+
+ tmp = fxp_mac64_Q31(((int64_t)temp1_i << 28), a0i, temp2_r);
+ tmp = fxp_mac64_Q31(tmp, a0r, temp2_i);
+ tmp = fxp_mac64_Q31(tmp, a1i, temp3_r);
+ targetBufferImag[j] = (Int32)(fxp_mac64_Q31(tmp, a1r, temp3_i) >> 28);
+
+ i++;
+ j += SBR_NUM_BANDS;
+
+ temp3_r = temp2_r;
+ temp2_r = temp1_r;
+ temp1_r = sourceBufferReal[i ][loBand];
+
+ temp3_i = temp2_i;
+ temp2_i = temp1_i;
+ temp1_i = sourceBufferImag[i ][loBand];
+
+ }
+
+ }
+
+
+
+ else
+ {
+ i = startSample + slopeLength;
+ j += i * SBR_NUM_BANDS;
+
+ for (; i < stopSample + slopeLength; i++)
+ {
+ targetBufferReal[j] = sourceBufferReal[i][loBand];
+ targetBufferImag[j] = sourceBufferImag[i][loBand];
+ j += SBR_NUM_BANDS;
+ }
+ }
+ }
+}
+
+#endif
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/sbr_generate_high_freq.h b/media/libstagefright/codecs/aacdec/sbr_generate_high_freq.h
new file mode 100644
index 0000000..0e9c928
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_generate_high_freq.h
@@ -0,0 +1,144 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_generate_high_freq.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+ $Id: ct_envcalc.h,v 1.3 2002/11/29 16:11:49 kaehleof Exp $
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_GENERATE_HIGH_FREQ_H
+#define SBR_GENERATE_HIGH_FREQ_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "e_invf_mode.h"
+#include "s_patch.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+
+
+ void sbr_generate_high_freq(
+ Int32 sourceBufferReal[][32],
+ Int32 sourceBufferImag[][32],
+ Int32 *targetBufferReal,
+ Int32 *targetBufferImag,
+ INVF_MODE *invFiltMode,
+ INVF_MODE *prevInvFiltMode,
+ Int32 *invFiltBandTable,
+ Int32 noInvFiltBands,
+ Int32 highBandStartSb,
+ Int32 *v_k_master,
+ Int32 numMaster,
+ Int32 fs,
+ Int32 *frameInfo,
+ Int32 *degreeAlias,
+ Int32 scratch_mem[][64],
+ Int32 BwVector[MAX_NUM_PATCHES],
+ Int32 BwVectorOld[MAX_NUM_PATCHES],
+ struct PATCH * Patch,
+ Int32 LC_flag,
+ Int32 *highBandStopSb);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_additional_data.cpp b/media/libstagefright/codecs/aacdec/sbr_get_additional_data.cpp
new file mode 100644
index 0000000..60072dd
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_additional_data.cpp
@@ -0,0 +1,145 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_additional_data.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_get_additional_data.h"
+#include "buf_getbits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void sbr_get_additional_data(SBR_FRAME_DATA * hFrameData,
+ BIT_BUFFER * hBitBuf)
+{
+ Int32 i;
+
+ Int32 flag = buf_getbits(hBitBuf, 1);
+
+ if (flag)
+ {
+ for (i = 0; i < hFrameData->nSfb[HI]; i++)
+ {
+ hFrameData->addHarmonics[i] = buf_getbits(hBitBuf, 1);
+ }
+ }
+}
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_additional_data.h b/media/libstagefright/codecs/aacdec/sbr_get_additional_data.h
new file mode 100644
index 0000000..51285c5
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_additional_data.h
@@ -0,0 +1,87 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_additional_data.h
+ Funtions:
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_GET_ADDITIONAL_DATA_H
+#define SBR_GET_ADDITIONAL_DATA_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bit_buffer.h"
+#include "s_sbr_header_data.h"
+#include "s_sbr_frame_data.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void sbr_get_additional_data(SBR_FRAME_DATA * hFrameData,
+ BIT_BUFFER * hBitBuf);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_cpe.cpp b/media/libstagefright/codecs/aacdec/sbr_get_cpe.cpp
new file mode 100644
index 0000000..657d032
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_cpe.cpp
@@ -0,0 +1,266 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_cpe.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Arguments: hFrameDataLeft - handle to struct SBR_FRAME_DATA for first channel
+ hFrameDataRight - handle to struct SBR_FRAME_DATA for first channel
+ hBitBuf - handle to struct BIT_BUF
+
+ Return: SbrFrameOK
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_get_cpe.h"
+#include "buf_getbits.h"
+#include "extractframeinfo.h"
+#include "sbr_get_dir_control_data.h"
+#include "sbr_get_envelope.h"
+#include "sbr_get_noise_floor_data.h"
+#include "sbr_get_additional_data.h"
+#include "sbr_extract_extended_data.h"
+#include "aac_mem_funcs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+SBR_ERROR sbr_get_cpe(SBR_FRAME_DATA * hFrameDataLeft,
+ SBR_FRAME_DATA * hFrameDataRight,
+ BIT_BUFFER * hBitBuf)
+{
+ Int32 i;
+ Int32 bits;
+ SBR_ERROR err = SBRDEC_OK;
+
+ /* reserved bits */
+ bits = buf_getbits(hBitBuf, SI_SBR_RESERVED_PRESENT);
+
+ if (bits)
+ {
+ buf_getbits(hBitBuf, SI_SBR_RESERVED_BITS_DATA);
+ buf_getbits(hBitBuf, SI_SBR_RESERVED_BITS_DATA);
+ }
+
+ /* Read coupling flag */
+ bits = buf_getbits(hBitBuf, SI_SBR_COUPLING_BITS);
+
+ if (bits)
+ {
+ hFrameDataLeft->coupling = COUPLING_LEVEL;
+ hFrameDataRight->coupling = COUPLING_BAL;
+ }
+ else
+ {
+ hFrameDataLeft->coupling = COUPLING_OFF;
+ hFrameDataRight->coupling = COUPLING_OFF;
+ }
+
+
+ err = extractFrameInfo(hBitBuf, hFrameDataLeft);
+
+ if (err != SBRDEC_OK)
+ {
+ return err;
+ }
+
+ if (hFrameDataLeft->coupling)
+ {
+
+ pv_memcpy(hFrameDataRight->frameInfo,
+ hFrameDataLeft->frameInfo,
+ LENGTH_FRAME_INFO * sizeof(Int32));
+
+ hFrameDataRight->nNoiseFloorEnvelopes = hFrameDataLeft->nNoiseFloorEnvelopes;
+ hFrameDataRight->frameClass = hFrameDataLeft->frameClass;
+
+
+ sbr_get_dir_control_data(hFrameDataLeft, hBitBuf);
+ sbr_get_dir_control_data(hFrameDataRight, hBitBuf);
+
+ for (i = 0; i < hFrameDataLeft->nNfb; i++)
+ {
+ hFrameDataLeft->sbr_invf_mode_prev[i] = hFrameDataLeft->sbr_invf_mode[i];
+ hFrameDataRight->sbr_invf_mode_prev[i] = hFrameDataRight->sbr_invf_mode[i];
+
+ hFrameDataLeft->sbr_invf_mode[i] = (INVF_MODE) buf_getbits(hBitBuf, SI_SBR_INVF_MODE_BITS);
+ hFrameDataRight->sbr_invf_mode[i] = hFrameDataLeft->sbr_invf_mode[i];
+ }
+
+ sbr_get_envelope(hFrameDataLeft, hBitBuf);
+ sbr_get_noise_floor_data(hFrameDataLeft, hBitBuf);
+ sbr_get_envelope(hFrameDataRight, hBitBuf);
+
+ }
+ else
+ {
+ err = extractFrameInfo(hBitBuf, hFrameDataRight);
+
+ if (err != SBRDEC_OK)
+ {
+ return err;
+ }
+
+
+ sbr_get_dir_control_data(hFrameDataLeft, hBitBuf);
+ sbr_get_dir_control_data(hFrameDataRight, hBitBuf);
+
+ for (i = 0; i < hFrameDataLeft->nNfb; i++)
+ {
+ hFrameDataLeft->sbr_invf_mode_prev[i] = hFrameDataLeft->sbr_invf_mode[i];
+ hFrameDataLeft->sbr_invf_mode[i] =
+ (INVF_MODE) buf_getbits(hBitBuf, SI_SBR_INVF_MODE_BITS);
+ }
+
+ for (i = 0; i < hFrameDataRight->nNfb; i++)
+ {
+ hFrameDataRight->sbr_invf_mode_prev[i] = hFrameDataRight->sbr_invf_mode[i];
+
+ hFrameDataRight->sbr_invf_mode[i] =
+ (INVF_MODE) buf_getbits(hBitBuf, SI_SBR_INVF_MODE_BITS);
+ }
+ sbr_get_envelope(hFrameDataLeft, hBitBuf);
+ sbr_get_envelope(hFrameDataRight, hBitBuf);
+
+ sbr_get_noise_floor_data(hFrameDataLeft, hBitBuf);
+
+ }
+
+ sbr_get_noise_floor_data(hFrameDataRight, hBitBuf);
+
+ pv_memset((void *)hFrameDataLeft->addHarmonics,
+ 0,
+ hFrameDataLeft->nSfb[HI]*sizeof(Int32));
+
+ pv_memset((void *)hFrameDataRight->addHarmonics,
+ 0,
+ hFrameDataRight->nSfb[HI]*sizeof(Int32));
+
+ sbr_get_additional_data(hFrameDataLeft, hBitBuf);
+ sbr_get_additional_data(hFrameDataRight, hBitBuf);
+
+ sbr_extract_extended_data(hBitBuf
+#ifdef PARAMETRICSTEREO
+ , NULL
+#endif
+ );
+
+ return SBRDEC_OK;
+
+}
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_cpe.h b/media/libstagefright/codecs/aacdec/sbr_get_cpe.h
new file mode 100644
index 0000000..b6f99f8
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_cpe.h
@@ -0,0 +1,88 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_cpe.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_GET_CPE_H
+#define SBR_GET_CPE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bit_buffer.h"
+#include "s_sbr_frame_data.h"
+#include "e_sbr_error.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+SBR_ERROR sbr_get_cpe(SBR_FRAME_DATA * hFrameDataLeft,
+ SBR_FRAME_DATA * hFrameDataRight,
+ BIT_BUFFER * hBitBuf);
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_dir_control_data.cpp b/media/libstagefright/codecs/aacdec/sbr_get_dir_control_data.cpp
new file mode 100644
index 0000000..3d7ad8c
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_dir_control_data.cpp
@@ -0,0 +1,153 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_dir_control_data.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Arguments: h_frame_data - handle to struct SBR_FRAME_DATA
+ hBitBuf - handle to struct BIT_BUF
+
+ Return: void
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Reads direction control data from bitstream
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_get_dir_control_data.h"
+#include "buf_getbits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void sbr_get_dir_control_data(SBR_FRAME_DATA * h_frame_data,
+ BIT_BUFFER * hBitBuf)
+{
+ Int32 i;
+
+ h_frame_data->nNoiseFloorEnvelopes = h_frame_data->frameInfo[0] > 1 ? 2 : 1;
+
+
+ for (i = 0; i < h_frame_data->frameInfo[0]; i++)
+ {
+ h_frame_data->domain_vec1[i] = buf_getbits(hBitBuf, SI_SBR_DOMAIN_BITS);
+ }
+
+ for (i = 0; i < h_frame_data->nNoiseFloorEnvelopes; i++)
+ {
+ h_frame_data->domain_vec2[i] = buf_getbits(hBitBuf, SI_SBR_DOMAIN_BITS);
+ }
+}
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_dir_control_data.h b/media/libstagefright/codecs/aacdec/sbr_get_dir_control_data.h
new file mode 100644
index 0000000..3b587dc
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_dir_control_data.h
@@ -0,0 +1,87 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_dir_control_data.h
+ Funtions:
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_GET_DIR_CONTROL_DATA_H
+#define SBR_GET_DIR_CONTROL_DATA_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bit_buffer.h"
+#include "s_sbr_frame_data.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void sbr_get_dir_control_data(SBR_FRAME_DATA * h_frame_data,
+ BIT_BUFFER * hBitBuf);
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_envelope.cpp b/media/libstagefright/codecs/aacdec/sbr_get_envelope.cpp
new file mode 100644
index 0000000..e92abb1
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_envelope.cpp
@@ -0,0 +1,265 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_envelope.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Arguments: h_frame_data - handle to struct SBR_FRAME_DATA
+ hBitBuf - handle to struct BIT_BUF
+ channel - channel number
+
+ Return: void
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Reads envelope data from bitstream
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_get_envelope.h"
+#include "s_huffman.h"
+#include "e_coupling_mode.h"
+#include "sbr_code_book_envlevel.h"
+#include "buf_getbits.h"
+#include "sbr_decode_huff_cw.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void sbr_get_envelope(SBR_FRAME_DATA * h_frame_data,
+ BIT_BUFFER * hBitBuf)
+{
+ Int32 i;
+ Int32 j;
+ Int32 tmp;
+ Int32 no_band[MAX_ENVELOPES];
+ Int32 delta = 0;
+ Int32 offset = 0;
+ Int32 ampRes;
+ Int32 envDataTableCompFactor;
+ Int32 start_bits;
+ Int32 start_bits_balance;
+ SbrHuffman hcb_t;
+ SbrHuffman hcb_f;
+ COUPLING_MODE coupling = h_frame_data->coupling;
+
+ h_frame_data->nScaleFactors = 0;
+
+ if ((h_frame_data->frameClass == FIXFIX) &&
+ (h_frame_data->frameInfo[0] == 1))
+ {
+ h_frame_data->ampRes = SBR_AMP_RES_1_5;
+ }
+ else
+ {
+ h_frame_data->ampRes = h_frame_data->sbr_header.ampResolution;
+ }
+
+ ampRes = h_frame_data->ampRes;
+
+ /*
+ * Set number of bits for first value depending on amplitude resolution
+ */
+ if (ampRes == SBR_AMP_RES_3_0)
+ {
+ start_bits = SI_SBR_START_ENV_BITS_AMP_RES_3_0;
+ start_bits_balance = SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_3_0;
+ }
+ else
+ {
+ start_bits = SI_SBR_START_ENV_BITS_AMP_RES_1_5;
+ start_bits_balance = SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_1_5;
+ }
+
+ /*
+ * Calculate number of values for each envelope and alltogether
+ */
+ for (i = 0; i < h_frame_data->frameInfo[0]; i++)
+ {
+ no_band[i] =
+ h_frame_data->nSfb[h_frame_data->frameInfo[h_frame_data->frameInfo[0] + 2 + i]];
+ h_frame_data->nScaleFactors += no_band[i];
+ }
+
+
+ /*
+ * Select huffman codebook depending on coupling mode and amplitude resolution
+ */
+ if (coupling == COUPLING_BAL)
+ {
+ envDataTableCompFactor = 1;
+ if (ampRes == SBR_AMP_RES_1_5)
+ {
+ hcb_t = bookSbrEnvBalance10T;
+ hcb_f = bookSbrEnvBalance10F;
+ }
+ else
+ {
+ hcb_t = bookSbrEnvBalance11T;
+ hcb_f = bookSbrEnvBalance11F;
+ }
+ }
+ else
+ {
+ envDataTableCompFactor = 0;
+ if (ampRes == SBR_AMP_RES_1_5)
+ {
+ hcb_t = bookSbrEnvLevel10T;
+ hcb_f = bookSbrEnvLevel10F;
+ }
+ else
+ {
+ hcb_t = bookSbrEnvLevel11T;
+ hcb_f = bookSbrEnvLevel11F;
+ }
+ }
+
+ /*
+ * Now read raw envelope data
+ */
+ for (j = 0; j < h_frame_data->frameInfo[0]; j++)
+ {
+ if (h_frame_data->domain_vec1[j] == FREQ)
+ {
+ if (coupling == COUPLING_BAL)
+ {
+ tmp = buf_getbits(hBitBuf, start_bits_balance);
+ h_frame_data->iEnvelope_man[offset] = tmp << envDataTableCompFactor;
+ }
+ else
+ {
+ tmp = buf_getbits(hBitBuf, start_bits);
+ h_frame_data->iEnvelope_man[offset] = tmp;
+ }
+ }
+
+ for (i = (1 - h_frame_data->domain_vec1[j]); i < no_band[j]; i++)
+ {
+
+ if (h_frame_data->domain_vec1[j] == FREQ)
+ {
+ delta = sbr_decode_huff_cw(hcb_f, hBitBuf);
+ }
+ else
+ {
+ delta = sbr_decode_huff_cw(hcb_t, hBitBuf);
+ }
+
+ h_frame_data->iEnvelope_man[offset + i] = delta << envDataTableCompFactor;
+ }
+ offset += no_band[j];
+ }
+
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_envelope.h b/media/libstagefright/codecs/aacdec/sbr_get_envelope.h
new file mode 100644
index 0000000..b7a266a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_envelope.h
@@ -0,0 +1,93 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_envelope.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_GET_ENVELOPE_H
+#define SBR_GET_ENVELOPE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bit_buffer.h"
+#include "s_sbr_frame_data.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void sbr_get_envelope(SBR_FRAME_DATA * h_frame_data,
+ BIT_BUFFER * hBitBuf);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_header_data.cpp b/media/libstagefright/codecs/aacdec/sbr_get_header_data.cpp
new file mode 100644
index 0000000..42789ae
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_header_data.cpp
@@ -0,0 +1,221 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_header_data.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Arguments: h_sbr_header - handle to struct SBR_HEADER_DATA
+ hBitBuf - handle to struct BIT_BUFFER
+ id_sbr - SBR_ELEMENT_ID
+
+ Return: error status - 0 if ok
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Reads header data from bitstream
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_get_header_data.h"
+#include "sbr_constants.h"
+#include "buf_getbits.h"
+#include "aac_mem_funcs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+SBR_HEADER_STATUS sbr_get_header_data(SBR_HEADER_DATA * h_sbr_header,
+ BIT_BUFFER * hBitBuf,
+ SBR_SYNC_STATE syncState)
+{
+ SBR_HEADER_DATA lastHeader;
+ Int32 headerExtra1, headerExtra2;
+
+
+ /* Copy header to temporary header */
+ if (syncState == SBR_ACTIVE)
+ {
+ pv_memcpy(&lastHeader, h_sbr_header, sizeof(SBR_HEADER_DATA));
+ }
+ else
+ {
+ pv_memset((void *)&lastHeader, 0, sizeof(SBR_HEADER_DATA));
+ }
+
+
+ /* Read new header from bitstream */
+ h_sbr_header->ampResolution = buf_getbits(hBitBuf, SI_SBR_AMP_RES_BITS);
+ h_sbr_header->startFreq = buf_getbits(hBitBuf, SI_SBR_START_FREQ_BITS);
+ h_sbr_header->stopFreq = buf_getbits(hBitBuf, SI_SBR_STOP_FREQ_BITS);
+ h_sbr_header->xover_band = buf_getbits(hBitBuf, SI_SBR_XOVER_BAND_BITS);
+
+ buf_getbits(hBitBuf, SI_SBR_RESERVED_BITS_HDR);
+
+ headerExtra1 = buf_getbits(hBitBuf, SI_SBR_HEADER_EXTRA_1_BITS);
+ headerExtra2 = buf_getbits(hBitBuf, SI_SBR_HEADER_EXTRA_2_BITS);
+
+ /* handle extra header information */
+ if (headerExtra1)
+ {
+ h_sbr_header->freqScale = buf_getbits(hBitBuf, SI_SBR_FREQ_SCALE_BITS);
+ h_sbr_header->alterScale = buf_getbits(hBitBuf, SI_SBR_ALTER_SCALE_BITS);
+ h_sbr_header->noise_bands = buf_getbits(hBitBuf, SI_SBR_NOISE_BANDS_BITS);
+ }
+ else
+ { /* Set default values.*/
+ h_sbr_header->freqScale = SBR_FREQ_SCALE_DEFAULT;
+ h_sbr_header->alterScale = SBR_ALTER_SCALE_DEFAULT;
+ h_sbr_header->noise_bands = SBR_NOISE_BANDS_DEFAULT;
+ }
+
+
+ if (headerExtra2)
+ {
+ h_sbr_header->limiterBands = buf_getbits(hBitBuf, SI_SBR_LIMITER_BANDS_BITS);
+ h_sbr_header->limiterGains = buf_getbits(hBitBuf, SI_SBR_LIMITER_GAINS_BITS);
+ h_sbr_header->interpolFreq = buf_getbits(hBitBuf, SI_SBR_INTERPOL_FREQ_BITS);
+ h_sbr_header->smoothingLength = buf_getbits(hBitBuf, SI_SBR_SMOOTHING_LENGTH_BITS);
+ }
+ else
+ { /* Set default values.*/
+ h_sbr_header->limiterBands = SBR_LIMITER_BANDS_DEFAULT;
+ h_sbr_header->limiterGains = SBR_LIMITER_GAINS_DEFAULT;
+ h_sbr_header->interpolFreq = SBR_INTERPOL_FREQ_DEFAULT;
+ h_sbr_header->smoothingLength = SBR_SMOOTHING_LENGTH_DEFAULT;
+ }
+
+ if (syncState == SBR_ACTIVE)
+ {
+ h_sbr_header->status = HEADER_OK;
+
+ /* look for new settings */
+ if (lastHeader.startFreq != h_sbr_header->startFreq ||
+ lastHeader.stopFreq != h_sbr_header->stopFreq ||
+ lastHeader.xover_band != h_sbr_header->xover_band ||
+ lastHeader.freqScale != h_sbr_header->freqScale ||
+ lastHeader.alterScale != h_sbr_header->alterScale ||
+ lastHeader.noise_bands != h_sbr_header->noise_bands)
+ {
+ h_sbr_header->status = HEADER_RESET;
+ }
+ }
+ else
+ {
+ h_sbr_header->status = HEADER_RESET;
+ }
+
+ return h_sbr_header->status;
+}
+
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_header_data.h b/media/libstagefright/codecs/aacdec/sbr_get_header_data.h
new file mode 100644
index 0000000..7bfb272
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_header_data.h
@@ -0,0 +1,89 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_header_data.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_GET_HEADER_DATA_H
+#define SBR_GET_HEADER_DATA_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bit_buffer.h"
+#include "s_sbr_header_data.h"
+#include "e_sbr_element_id.h"
+#include "e_sbr_sync_state.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+SBR_HEADER_STATUS sbr_get_header_data(SBR_HEADER_DATA *h_sbr_header,
+ BIT_BUFFER * hBitBuf,
+ SBR_SYNC_STATE syncState);
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_noise_floor_data.cpp b/media/libstagefright/codecs/aacdec/sbr_get_noise_floor_data.cpp
new file mode 100644
index 0000000..8d86158
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_noise_floor_data.cpp
@@ -0,0 +1,218 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_noise_floor_data.c
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Arguments: h_frame_data - handle to struct SBR_FRAME_DATA
+ hBitBuf - handle to struct BIT_BUF
+
+ Return: void
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Reads noise-floor-level data from bitstream
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_get_noise_floor_data.h"
+#include "e_coupling_mode.h"
+#include "buf_getbits.h"
+#include "sbr_code_book_envlevel.h"
+#include "s_huffman.h"
+#include "sbr_decode_huff_cw.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void sbr_get_noise_floor_data(SBR_FRAME_DATA * h_frame_data,
+ BIT_BUFFER * hBitBuf)
+{
+ Int32 i;
+ Int32 j;
+ Int32 k;
+ Int32 tmp;
+ Int32 delta;
+ Int32 noNoiseBands = h_frame_data->nNfb;
+ Int32 envDataTableCompFactor;
+
+ COUPLING_MODE coupling = h_frame_data->coupling;
+
+ SbrHuffman hcb_noiseF;
+ SbrHuffman hcb_noise;
+
+
+ if (coupling == COUPLING_BAL)
+ {
+ hcb_noise = bookSbrNoiseBalance11T;
+ hcb_noiseF = bookSbrEnvBalance11F; /* "bookSbrNoiseBalance11F" */
+ envDataTableCompFactor = 1;
+ }
+ else
+ {
+ hcb_noise = bookSbrNoiseLevel11T;
+ hcb_noiseF = bookSbrEnvLevel11F; /* "bookSbrNoiseLevel11F" */
+ envDataTableCompFactor = 0;
+ }
+
+ /*
+ * Calculate number of values alltogether
+ */
+ h_frame_data->nNoiseFactors = h_frame_data->frameInfo[((h_frame_data->frameInfo[0]) << 1) + 3] * noNoiseBands;
+
+
+ for (i = 0; i < h_frame_data->nNoiseFloorEnvelopes; i++)
+ {
+ k = i * noNoiseBands;
+ if (h_frame_data->domain_vec2[i] == FREQ)
+ {
+ if (coupling == COUPLING_BAL)
+ {
+ tmp = buf_getbits(hBitBuf, SI_SBR_START_NOISE_BITS_BALANCE_AMP_RES_3_0) << 1; /* max. 62 */
+ h_frame_data->sbrNoiseFloorLevel_man[k] = tmp;
+ h_frame_data->sbrNoiseFloorLevel_exp[k] = 0;
+ }
+ else
+ {
+ tmp = buf_getbits(hBitBuf, SI_SBR_START_NOISE_BITS_AMP_RES_3_0); /* max. 31 */
+ h_frame_data->sbrNoiseFloorLevel_man[k] = tmp;
+ h_frame_data->sbrNoiseFloorLevel_exp[k] = 0;
+ }
+
+ for (j = 1; j < noNoiseBands; j++)
+ {
+ delta = sbr_decode_huff_cw(hcb_noiseF, hBitBuf); /*
+ * -31 < delta < 31
+ * -24 < delta < 24 COUPLING_BAL (incl. <<1)
+ */
+ h_frame_data->sbrNoiseFloorLevel_man[k+j] = delta << envDataTableCompFactor;
+ h_frame_data->sbrNoiseFloorLevel_exp[k+j] = 0;
+ }
+ }
+ else
+ {
+ for (j = 0; j < noNoiseBands; j++)
+ {
+ delta = sbr_decode_huff_cw(hcb_noise, hBitBuf); /*
+ * -31 < delta < 31
+ * -24 < delta < 24 COUPLING_BAL (incl. <<1)
+ */
+ h_frame_data->sbrNoiseFloorLevel_man[k+j] = delta << envDataTableCompFactor;
+ h_frame_data->sbrNoiseFloorLevel_exp[k+j] = 0;
+ }
+ }
+ }
+}
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_noise_floor_data.h b/media/libstagefright/codecs/aacdec/sbr_get_noise_floor_data.h
new file mode 100644
index 0000000..e61abda
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_noise_floor_data.h
@@ -0,0 +1,94 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_noise_floor_data.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_GET_NOISE_FLOOR_DATA_H
+#define SBR_GET_NOISE_FLOOR_DATA_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bit_buffer.h"
+#include "s_sbr_frame_data.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void sbr_get_noise_floor_data(SBR_FRAME_DATA * h_frame_data,
+ BIT_BUFFER * hBitBuf);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_sce.cpp b/media/libstagefright/codecs/aacdec/sbr_get_sce.cpp
new file mode 100644
index 0000000..ba514f4
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_sce.cpp
@@ -0,0 +1,202 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_sce.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Arguments: hFrameData - handle to struct SBR_FRAME_DATA
+ hBitBuf - handle to struct BIT_BUF
+
+ Return: SbrFrameOK
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+
+#include "sbr_get_sce.h"
+#include "sbr_get_additional_data.h"
+#include "sbr_extract_extended_data.h"
+#include "buf_getbits.h"
+#include "sbr_get_envelope.h"
+#include "sbr_get_noise_floor_data.h"
+#include "extractframeinfo.h"
+#include "sbr_get_dir_control_data.h"
+#include "e_invf_mode.h"
+#include "aac_mem_funcs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+SBR_ERROR sbr_get_sce(SBR_FRAME_DATA * hFrameData,
+ BIT_BUFFER * hBitBuf
+#ifdef PARAMETRICSTEREO
+ , HANDLE_PS_DEC hParametricStereoDec
+#endif
+ )
+{
+ Int32 i;
+ Int32 bits;
+ SBR_ERROR err = SBRDEC_OK;
+
+ /* reserved bits */
+ bits = buf_getbits(hBitBuf, SI_SBR_RESERVED_PRESENT);
+
+ if (bits)
+ {
+ buf_getbits(hBitBuf, SI_SBR_RESERVED_BITS_DATA);
+ }
+
+ /* side info */
+ err = extractFrameInfo(hBitBuf, hFrameData);
+
+ if (err != SBRDEC_OK)
+ {
+ return err;
+ }
+
+
+ sbr_get_dir_control_data(hFrameData, hBitBuf);
+
+ for (i = 0; i < hFrameData->nNfb; i++)
+ {
+ hFrameData->sbr_invf_mode_prev[i] = hFrameData->sbr_invf_mode[i];
+ hFrameData->sbr_invf_mode[i] =
+ (INVF_MODE) buf_getbits(hBitBuf, SI_SBR_INVF_MODE_BITS);
+ }
+
+
+ /* raw data */
+ sbr_get_envelope(hFrameData, hBitBuf);
+
+ sbr_get_noise_floor_data(hFrameData, hBitBuf);
+
+ pv_memset((void *)hFrameData->addHarmonics,
+ 0,
+ hFrameData->nSfb[HI]*sizeof(Int32));
+
+ sbr_get_additional_data(hFrameData, hBitBuf);
+
+ sbr_extract_extended_data(hBitBuf
+#ifdef PARAMETRICSTEREO
+ , hParametricStereoDec
+#endif
+ );
+
+ hFrameData->coupling = COUPLING_OFF;
+
+ return SBRDEC_OK;
+
+}
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/sbr_get_sce.h b/media/libstagefright/codecs/aacdec/sbr_get_sce.h
new file mode 100644
index 0000000..36adb04
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_get_sce.h
@@ -0,0 +1,102 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_get_sce.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_GET_SCE_H
+#define SBR_GET_SCE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_bit_buffer.h"
+#include "s_sbr_frame_data.h"
+#include "e_sbr_error.h"
+
+#ifdef PARAMETRICSTEREO
+#include "s_ps_dec.h"
+#endif
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ SBR_ERROR sbr_get_sce(SBR_FRAME_DATA * hFrameData,
+ BIT_BUFFER * hBitBuf
+#ifdef PARAMETRICSTEREO
+ , HANDLE_PS_DEC hParametricStereoDec
+#endif
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_inv_filt_levelemphasis.cpp b/media/libstagefright/codecs/aacdec/sbr_inv_filt_levelemphasis.cpp
new file mode 100644
index 0000000..833ace3
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_inv_filt_levelemphasis.cpp
@@ -0,0 +1,214 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_inv_filt_levelemphasis.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_inv_filt_levelemphasis.h"
+#include "sbr_generate_high_freq.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+#include "pv_audio_type_defs.h"
+#include "fxp_mul32.h"
+
+#define R_SHIFT 29
+#define Qfmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+
+const Int32 InvFiltFactors[5] = {Qfmt(0.00f), /* OFF_LEVEL */
+ Qfmt(0.60f), /* TRANSITION_LEVEL */
+ Qfmt(0.75f), /* LOW_LEVEL */
+ Qfmt(0.90f), /* MID_LEVEL */
+ Qfmt(0.98f)
+ }; /* HIGH_LEVEL */
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void sbr_inv_filt_levelemphasis(INVF_MODE *invFiltMode,
+ INVF_MODE *prevInvFiltMode,
+ Int32 nNfb,
+ Int32 BwVector[MAX_NUM_PATCHES],
+ Int32 BwVectorOld[MAX_NUM_PATCHES])
+{
+ Int32 i;
+ Int32 j;
+ Int32 tmp;
+
+ for (i = 0; i < nNfb; i++)
+ {
+ switch (invFiltMode[i])
+ {
+ case INVF_LOW_LEVEL:
+ if (prevInvFiltMode[i] == INVF_OFF)
+ {
+ j = 1;
+ }
+ else
+ {
+ j = 2;
+ }
+ break;
+
+ case INVF_MID_LEVEL:
+ j = 3;
+ break;
+
+ case INVF_HIGH_LEVEL:
+ j = 4;
+ break;
+
+ default:
+ if (prevInvFiltMode[i] == INVF_LOW_LEVEL)
+ {
+ j = 1;
+ }
+ else
+ {
+ j = 0;
+ }
+ }
+
+ tmp = InvFiltFactors[j];
+
+ if (tmp < BwVectorOld[i])
+ {
+ tmp = ((tmp << 1) + tmp + BwVectorOld[i]) >> 2;
+ }
+ else
+ {
+ tmp = fxp_mul32_Q29(Qfmt(0.90625f), tmp);
+ tmp = fxp_mac32_Q29(Qfmt(0.09375f), BwVectorOld[i], tmp);
+ }
+
+ if (tmp < Qfmt(0.015625F))
+ {
+ tmp = 0;
+ }
+
+ if (tmp >= Qfmt(0.99609375f))
+ {
+ tmp = Qfmt(0.99609375f);
+ }
+
+ BwVector[i] = tmp;
+ }
+}
+
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_inv_filt_levelemphasis.h b/media/libstagefright/codecs/aacdec/sbr_inv_filt_levelemphasis.h
new file mode 100644
index 0000000..586214c
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_inv_filt_levelemphasis.h
@@ -0,0 +1,91 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_inv_filt_levelemphasis.h
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+ ----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_INV_FILT_LEVELEMPHASIS_H
+#define SBR_INV_FILT_LEVELEMPHASIS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_invf_mode.h"
+#include "sbr_generate_high_freq.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+void sbr_inv_filt_levelemphasis(INVF_MODE *invFiltMode,
+ INVF_MODE *prevInvFiltMode,
+ Int32 nNfb,
+ Int32 BwVector[MAX_NUM_PATCHES],
+ Int32 BwVectorOld[MAX_NUM_PATCHES]);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_open.cpp b/media/libstagefright/codecs/aacdec/sbr_open.cpp
new file mode 100644
index 0000000..868819a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_open.cpp
@@ -0,0 +1,195 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_open.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_open.h"
+#include "s_sbr_header_data.h"
+#include "init_sbr_dec.h"
+#include "e_sbr_error.h"
+#include "aac_mem_funcs.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const SBR_HEADER_DATA defaultHeader =
+{
+ HEADER_NOT_INITIALIZED, /* status */
+ MASTER_RESET, /* masterStatus */
+ 0, /* crcEnable */
+ UP_BY_2, /* sampleRateMode */
+ SBR_AMP_RES_3_0, /* ampResolution */
+ 5, /* startFreq */
+ 0, /* stopFreq */
+ 0, /* xover_band */
+ SBR_FREQ_SCALE_DEFAULT, /* freqScale */
+ SBR_ALTER_SCALE_DEFAULT, /* alterScale */
+ SBR_NOISE_BANDS_DEFAULT, /* noise_bands */
+ 0, /* noNoiseBands */
+ SBR_LIMITER_BANDS_DEFAULT,
+ SBR_LIMITER_GAINS_DEFAULT,
+ SBR_INTERPOL_FREQ_DEFAULT,
+ SBR_SMOOTHING_LENGTH_DEFAULT
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void sbr_open(Int32 sampleRate,
+ SBR_DEC *sbrDec,
+ SBRDECODER_DATA * self,
+ bool bDownSampledSbr)
+
+{
+ Int16 i ;
+
+ SBR_CHANNEL *SbrChannel;
+
+
+ SbrChannel = self->SbrChannel;
+
+ for (i = 0; i < MAX_NUM_CHANNELS; i++)
+ {
+ pv_memset((void *)&(SbrChannel[i]),
+ 0,
+ sizeof(SBR_CHANNEL));
+
+ /* init a default header such that we can at least do upsampling later */
+
+ pv_memcpy(&(SbrChannel[i].frameData.sbr_header),
+ &defaultHeader,
+ sizeof(SBR_HEADER_DATA));
+
+ /* should be handled by sample rate mode bit */
+ if (sampleRate > 24000 || bDownSampledSbr)
+ {
+ SbrChannel[i].frameData.sbr_header.sampleRateMode = SINGLE_RATE;
+ }
+
+
+ SbrChannel[i].outFrameSize =
+ init_sbr_dec(sampleRate,
+ self->SbrChannel[0].frameData.sbr_header.sampleRateMode,
+ sbrDec,
+ &(SbrChannel[i].frameData));
+
+ SbrChannel[i].syncState = UPSAMPLING;
+
+ SbrChannel[i].frameData.sUp = 1; /* reset mode */
+ }
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_open.h b/media/libstagefright/codecs/aacdec/sbr_open.h
new file mode 100644
index 0000000..8d17ffa
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_open.h
@@ -0,0 +1,116 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_open.h
+ Funtions:
+ get_dse
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+ $Id: ct_envcalc.h,v 1.3 2002/11/29 16:11:49 kaehleof Exp $
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_OPEN_H
+#define SBR_OPEN_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "s_sbr_channel.h"
+#include "sbr_dec.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+void sbr_open(Int32 sampleRate,
+ SBR_DEC *sbrDec,
+ SBRDECODER_DATA * self,
+ bool bDownSampledSbr);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_read_data.cpp b/media/libstagefright/codecs/aacdec/sbr_read_data.cpp
new file mode 100644
index 0000000..2220fce
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_read_data.cpp
@@ -0,0 +1,324 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_read_data.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ INPUT
+
+ SBRDECODER self,
+ SBRBITSTREAM * stream,
+ float *timeData,
+ int numChannels
+
+ OUTPUT
+
+ errorCode, noError if successful
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ sbr decoder processing, set up SBR decoder phase 2 in case of
+ different cotrol data
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_read_data.h"
+#include "s_bit_buffer.h"
+#include "buf_getbits.h"
+#include "sbr_get_sce.h"
+#include "sbr_get_cpe.h"
+#include "sbr_reset_dec.h"
+#include "sbr_get_header_data.h"
+#include "sbr_crc_check.h"
+#include "aac_mem_funcs.h"
+
+
+#include "init_sbr_dec.h" /* !!! */
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+SBR_ERROR sbr_read_data(SBRDECODER_DATA * self,
+ SBR_DEC * sbrDec,
+ SBRBITSTREAM *stream)
+{
+ SBR_ERROR sbr_err = SBRDEC_OK;
+ int32_t SbrFrameOK = 1;
+ int32_t sbrCRCAlwaysOn = 0;
+
+ UInt32 bs_header_flag = 0;
+
+ SBR_HEADER_STATUS headerStatus = HEADER_OK;
+
+ SBR_CHANNEL *SbrChannel = self->SbrChannel;
+
+ int32_t zeropadding_bits;
+
+ BIT_BUFFER bitBuf ;
+
+ /*
+ * evaluate Bitstream
+ */
+
+ bitBuf.buffer_word = 0;
+ bitBuf.buffered_bits = 0;
+ bitBuf.nrBitsRead = 0;
+
+ bitBuf.char_ptr = stream->sbrElement[0].Data;
+ bitBuf.bufferLen = (stream->sbrElement[0].Payload) << 3;
+
+
+ /*
+ * we have to skip a nibble because the first element of Data only
+ * contains a nibble of data !
+ */
+ buf_getbits(&bitBuf, LEN_NIBBLE);
+
+ if ((stream->sbrElement[0].ExtensionType == SBR_EXTENSION_CRC) ||
+ sbrCRCAlwaysOn)
+ {
+ int32_t CRCLen = ((stream->sbrElement[0].Payload - 1) << 3) + 4 - SI_SBR_CRC_BITS;
+ SbrFrameOK = sbr_crc_check(&bitBuf, CRCLen);
+ }
+
+
+ if (SbrFrameOK)
+ {
+ /*
+ * The sbr data seems ok, if the header flag is set we read the header
+ * and check if vital parameters have changed since the previous frame.
+ * If the syncState equals UPSAMPLING, the SBR Tool has not been
+ * initialised by SBR header data, and can only do upsampling
+ */
+
+ bs_header_flag = buf_getbits(&bitBuf, 1); /* read Header flag */
+
+ if (bs_header_flag)
+ {
+ /*
+ * If syncState == SBR_ACTIVE, it means that we've had a SBR header
+ * before, and we will compare with the previous header to see if a
+ * reset is required. If the syncState equals UPSAMPLING this means
+ * that the SBR-Tool so far is only initialised to do upsampling
+ * and hence we need to do a reset, and initialise the system
+ * according to the present header.
+ */
+
+ headerStatus = sbr_get_header_data(&(SbrChannel[0].frameData.sbr_header),
+ &bitBuf,
+ SbrChannel[0].syncState);
+ } /* if (bs_header_flag) */
+
+
+ switch (stream->sbrElement[0].ElementID)
+ {
+ case SBR_ID_SCE :
+
+ /* change of control data, reset decoder */
+ if (headerStatus == HEADER_RESET)
+ {
+ sbr_err = sbr_reset_dec(&(SbrChannel[0].frameData),
+ sbrDec,
+ self->SbrChannel[0].frameData.sbr_header.sampleRateMode);
+
+ if (sbr_err != SBRDEC_OK)
+ {
+ break;
+ }
+ /*
+ * At this point we have a header and the system has been reset,
+ * hence syncState from now on will be SBR_ACTIVE.
+ */
+ SbrChannel[0].syncState = SBR_ACTIVE;
+ }
+
+ if ((SbrChannel[0].syncState == SBR_ACTIVE))
+ {
+ sbr_err = sbr_get_sce(&(SbrChannel[0].frameData),
+ &bitBuf
+#ifdef PARAMETRICSTEREO
+ , self->hParametricStereoDec
+#endif
+ );
+
+ if (sbr_err != SBRDEC_OK)
+ {
+ break;
+ }
+ }
+
+ break;
+
+ case SBR_ID_CPE :
+
+ if (bs_header_flag)
+ {
+ pv_memcpy(&(SbrChannel[1].frameData.sbr_header),
+ &(SbrChannel[0].frameData.sbr_header),
+ sizeof(SBR_HEADER_DATA));
+ }
+
+ /* change of control data, reset decoder */
+ if (headerStatus == HEADER_RESET)
+ {
+ for (int32_t lr = 0 ; lr < 2 ; lr++)
+ {
+ sbr_err = sbr_reset_dec(&(SbrChannel[lr].frameData),
+ sbrDec,
+ self->SbrChannel[0].frameData.sbr_header.sampleRateMode);
+
+ if (sbr_err != SBRDEC_OK)
+ {
+ break;
+ }
+
+ SbrChannel[lr].syncState = SBR_ACTIVE;
+ }
+ }
+
+ if (SbrChannel[0].syncState == SBR_ACTIVE)
+ {
+ sbr_err = sbr_get_cpe(&(SbrChannel[0].frameData),
+ &(SbrChannel[1].frameData),
+ &bitBuf);
+
+ if (sbr_err != SBRDEC_OK)
+ {
+ break;
+ }
+
+ }
+ break;
+
+ default:
+ sbr_err = SBRDEC_ILLEGAL_PLUS_ELE_ID;
+ break;
+ }
+
+ } /* if (SbrFrameOK) */
+
+ /*
+ * Check that the bits read did not go beyond SBR frame boundaries
+ */
+
+ zeropadding_bits = (8 - (bitBuf.nrBitsRead & 0x7)) & 0x7;
+
+ if ((bitBuf.nrBitsRead + zeropadding_bits) > bitBuf.bufferLen)
+ {
+ sbr_err = SBRDEC_INVALID_BITSTREAM;
+ }
+
+ return sbr_err;
+}
+
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_read_data.h b/media/libstagefright/codecs/aacdec/sbr_read_data.h
new file mode 100644
index 0000000..74cf5b9
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_read_data.h
@@ -0,0 +1,127 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_read_data.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+ $Id: ct_envcalc.h,v 1.3 2002/11/29 16:11:49 kaehleof Exp $
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_READ_DATA
+#define SBR_READ_DATA
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "e_sbr_error.h"
+#include "s_sbr_channel.h"
+#include "s_sbrbitstream.h"
+#include "sbr_dec.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ SBR_ERROR sbr_read_data(SBRDECODER_DATA * self,
+ SBR_DEC * sbrDec,
+ SBRBITSTREAM *stream);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_requantize_envelope_data.cpp b/media/libstagefright/codecs/aacdec/sbr_requantize_envelope_data.cpp
new file mode 100644
index 0000000..487496f
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_requantize_envelope_data.cpp
@@ -0,0 +1,183 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_requantize_envelope_data.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_constants.h"
+#include "sbr_requantize_envelope_data.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define R_SHIFT 30
+#define Qfmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void sbr_requantize_envelope_data(SBR_FRAME_DATA * hFrameData)
+
+{
+ Int32 i;
+
+
+ Int32 nScaleFactors = hFrameData->nScaleFactors;
+ Int32 nNoiseFactors = hFrameData->nNoiseFactors;
+ Int32 ampRes = hFrameData->ampRes;
+ Int32 *iEnvelope_man = hFrameData->iEnvelope_man;
+ Int32 *iEnvelope_exp = hFrameData->iEnvelope_exp;
+ Int32 *sbrNoiseFloorLevel_man = hFrameData->sbrNoiseFloorLevel_man;
+ Int32 *sbrNoiseFloorLevel_exp = hFrameData->sbrNoiseFloorLevel_exp;
+
+ /*
+ * ampRes could be 0 (resolution step = 1.5 dB) or
+ * 1 (resolution step = 3 dB)
+ */
+ if (ampRes)
+ {
+ /* iEnvelope[i] always positive 6 bits max */
+ for (i = 0; i < nScaleFactors; i++)
+ {
+
+ iEnvelope_exp[i] = iEnvelope_man[i] + 6;
+ iEnvelope_man[i] = Qfmt(1.000F);
+ }
+ }
+ else
+ {
+ /* iEnvelope[i] always positive 7 bits max */
+ for (i = 0; i < nScaleFactors; i++)
+ {
+ iEnvelope_exp[i] = (iEnvelope_man[i] >> 1) + 6;
+ if (iEnvelope_man[i] & 0x1) /* odd */
+ {
+ iEnvelope_man[i] = Qfmt(1.41421356237310F);
+ }
+ else
+ {
+ iEnvelope_man[i] = Qfmt(1.000F);
+ }
+ }
+
+ }
+ for (i = 0; i < nNoiseFactors; i++)
+ {
+ /* sbrNoiseFloorLevel[i] varies from -31 to 31 if no coupling is used */
+
+ sbrNoiseFloorLevel_exp[i] = NOISE_FLOOR_OFFSET - sbrNoiseFloorLevel_man[i];
+ sbrNoiseFloorLevel_man[i] = 0x40000000;
+ }
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_requantize_envelope_data.h b/media/libstagefright/codecs/aacdec/sbr_requantize_envelope_data.h
new file mode 100644
index 0000000..2113586
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_requantize_envelope_data.h
@@ -0,0 +1,83 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_requantize_envelope_data.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_REQUANTIZE_ENVELOPE_DATA_H
+#define SBR_REQUANTIZE_ENVELOPE_DATA_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_sbr_frame_data.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void sbr_requantize_envelope_data(SBR_FRAME_DATA * hFrameData);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_reset_dec.cpp b/media/libstagefright/codecs/aacdec/sbr_reset_dec.cpp
new file mode 100644
index 0000000..810a34a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_reset_dec.cpp
@@ -0,0 +1,269 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_reset_dec.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ resets sbr decoder structure
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#ifdef AAC_PLUS
+
+#include "sbr_dec.h"
+
+#include "pv_log2.h"
+#include "fxp_mul32.h"
+
+
+#include "sbr_reset_dec.h"
+#include "sbr_find_start_andstop_band.h"
+#include "sbr_update_freq_scale.h"
+#include "sbr_downsample_lo_res.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+SBR_ERROR sbr_reset_dec(SBR_FRAME_DATA * hFrameData,
+ SBR_DEC * sbrDec,
+ Int32 upsampleFac)
+{
+
+ SBR_ERROR err = SBRDEC_OK;
+ Int lsbM;
+ Int lsb;
+ Int usb;
+ Int32 i;
+ Int32 tmp_q1;
+
+ SBR_HEADER_DATA *headerData = &(hFrameData->sbr_header);
+ Int32 samplingFreq = sbrDec->outSampleRate;
+
+ hFrameData->reset_flag = 1;
+
+ /*Calculate master frequency function */
+ err = sbr_find_start_andstop_band(samplingFreq,
+ headerData->startFreq,
+ headerData->stopFreq,
+ &lsbM,
+ &usb);
+
+ if (err != SBRDEC_OK)
+ {
+ return err;
+ }
+
+ /* Calculate new v_k_master if needed */
+ if (headerData->masterStatus == MASTER_RESET)
+ {
+ sbr_update_freq_scale(sbrDec->V_k_master,
+ &(sbrDec->Num_Master),
+ lsbM,
+ usb,
+ headerData->freqScale,
+ headerData->alterScale,
+ 0);
+
+ }
+
+ /*Derive Hiresolution from master frequency function*/
+
+ sbrDec->NSfb[HI] = sbrDec->Num_Master - headerData->xover_band;
+
+ for (i = headerData->xover_band; i <= sbrDec->Num_Master; i++)
+ {
+ sbrDec->FreqBandTable[HI][i-headerData->xover_band] = (Int)sbrDec->V_k_master[i];
+ }
+
+
+ if ((sbrDec->NSfb[HI] & 0x01) == 0) /* if even number of hires bands */
+ {
+
+ sbrDec->NSfb[LO] = sbrDec->NSfb[HI] >> 1;
+ /* Use every second lo-res=hi-res[0,2,4...] */
+ for (i = 0; i <= sbrDec->NSfb[LO]; i++)
+ {
+ sbrDec->FreqBandTable[LO][i] = sbrDec->FreqBandTable[HI][(i<<1)];
+ }
+ }
+ else
+ { /* odd number of hi-res which means xover is odd */
+
+ sbrDec->NSfb[LO] = (sbrDec->NSfb[HI] + 1) >> 1;
+ /* Use lo-res=hi-res[0,1,3,5 ...] */
+ sbrDec->FreqBandTable[LO][0] = sbrDec->FreqBandTable[HI][0];
+ for (i = 1; i <= sbrDec->NSfb[LO]; i++)
+ {
+ sbrDec->FreqBandTable[LO][i] = sbrDec->FreqBandTable[HI][(i<<1)-1];
+ }
+
+ }
+
+ lsb = sbrDec->FreqBandTable[LOW_RES][0];
+ usb = sbrDec->FreqBandTable[LOW_RES][sbrDec->NSfb[LOW_RES]];
+
+ sbrDec->lowSubband = lsb;
+ sbrDec->highSubband = usb;
+ sbrDec->noSubbands = usb - lsb;
+
+ if ((lsb > 32) || (sbrDec->noSubbands <= 0))
+ {
+ return SBRDEC_ILLEGAL_SCFACTORS; /* invalid bands */
+ }
+
+ /* Calculate number of noise bands */
+ if (headerData->noise_bands == 0)
+ {
+ sbrDec->NoNoiseBands = 1;
+ }
+ else /* Calculate number of noise bands 1,2 or 3 bands/octave */
+ {
+
+ if (! lsb)
+ {
+ return SBRDEC_ILLEGAL_SCFACTORS; /* avoid div by 0 */
+ }
+
+ tmp_q1 = pv_log2((usb << 20) / lsb);
+
+ tmp_q1 = fxp_mul32_Q15(headerData->noise_bands, tmp_q1);
+
+ sbrDec->NoNoiseBands = (tmp_q1 + 16) >> 5;
+
+ if (sbrDec->NoNoiseBands == 0)
+ {
+ sbrDec->NoNoiseBands = 1;
+ }
+ }
+
+ headerData->noNoiseBands = sbrDec->NoNoiseBands;
+
+ /* Get noise bands */
+ sbr_downsample_lo_res(sbrDec->FreqBandTableNoise,
+ sbrDec->NoNoiseBands,
+ sbrDec->FreqBandTable[LO],
+ sbrDec->NSfb[LO]);
+
+ sbrDec->sbStopCodec = sbrDec->lowSubband;
+
+ if (sbrDec->sbStopCodec > (upsampleFac << 5))
+ {
+ sbrDec->sbStopCodec = (upsampleFac << 5);
+ }
+
+ hFrameData->nSfb[LO] = sbrDec->NSfb[LO];
+ hFrameData->nSfb[HI] = sbrDec->NSfb[HI];
+ hFrameData->nNfb = hFrameData->sbr_header.noNoiseBands;
+ hFrameData->offset = ((hFrameData->nSfb[LO]) << 1) - hFrameData->nSfb[HI];
+
+ return (SBRDEC_OK);
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_reset_dec.h b/media/libstagefright/codecs/aacdec/sbr_reset_dec.h
new file mode 100644
index 0000000..0ff94a5
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_reset_dec.h
@@ -0,0 +1,118 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_reset_dec.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+ $Id: ct_envcalc.h,v 1.3 2002/11/29 16:11:49 kaehleof Exp $
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_RESET_DEC_H
+#define SBR_RESET_DEC_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "s_sbr_frame_data.h"
+#include "sbr_dec.h"
+#include "e_sbr_error.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+SBR_ERROR sbr_reset_dec(SBR_FRAME_DATA * hFrameData,
+ SBR_DEC * sbrDec,
+ Int32 upsampleFac);
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sbr_update_freq_scale.cpp b/media/libstagefright/codecs/aacdec/sbr_update_freq_scale.cpp
new file mode 100644
index 0000000..18bd5d9
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_update_freq_scale.cpp
@@ -0,0 +1,364 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_update_freq_scale.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+SC 29 Software Copyright Licencing Disclaimer:
+
+This software module was originally developed by
+ Coding Technologies
+
+and edited by
+ -
+
+in the course of development of the ISO/IEC 13818-7 and ISO/IEC 14496-3
+standards for reference purposes and its performance may not have been
+optimized. This software module is an implementation of one or more tools as
+specified by the ISO/IEC 13818-7 and ISO/IEC 14496-3 standards.
+ISO/IEC gives users free license to this software module or modifications
+thereof for use in products claiming conformance to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International
+Standards. ISO/IEC gives users the same free license to this software module or
+modifications thereof for research purposes and further ISO/IEC standardisation.
+Those intending to use this software module in products are advised that its
+use may infringe existing patents. ISO/IEC have no liability for use of this
+software module or modifications thereof. Copyright is not released for
+products that do not conform to audiovisual and image-coding related ITU
+Recommendations and/or ISO/IEC International Standards.
+The original developer retains full right to modify and use the code for its
+own purpose, assign or donate the code to a third party and to inhibit third
+parties from using the code for products that do not conform to audiovisual and
+image-coding related ITU Recommendations and/or ISO/IEC International Standards.
+This copyright notice must be included in all copies or derivative works.
+Copyright (c) ISO/IEC 2002.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "sbr_update_freq_scale.h"
+#include "shellsort.h"
+
+#include "pv_pow2.h"
+#include "pv_log2.h"
+
+#include "fxp_mul32.h"
+#define R_SHIFT 30
+#define Q_fmt(x) (Int32)(x*((Int32)1<<R_SHIFT) + (x>=0?0.5F:-0.5F))
+#define Q28fmt(x) (Int32)(x*((Int32)1<<28) + (x>=0?0.5F:-0.5F))
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+void sbr_update_freq_scale(Int32 * v_k_master,
+ Int32 *h_num_bands,
+ const Int32 lsbM,
+ const Int32 usb,
+ const Int32 freqScale,
+ const Int32 alterScale,
+ const Int32 channelOffset)
+{
+ Int32 i;
+ Int32 numBands = 0;
+ Int32 numBands2;
+ Int32 tmp_q1;
+
+ if (freqScale > 0) /*Bark mode*/
+ {
+ Int32 reg;
+ Int32 regions;
+ Int32 b_p_o;
+ Int32 k[3];
+ Int32 d[MAX_SECOND_REGION];
+ Int32 d2[MAX_SECOND_REGION];
+ Int32 w[2] = {Q_fmt(1.0F), Q_fmt(1.0F)};
+
+
+ k[0] = lsbM;
+ k[1] = usb;
+ k[2] = usb;
+
+ b_p_o = (freqScale == 1) ? 12 : 8;
+ b_p_o = (freqScale == 2) ? 10 : b_p_o;
+
+ w[1] = (alterScale == 0) ? Q_fmt(0.5f) : Q_fmt(0.384615384615386f);
+
+ if (usb > fxp_mul32_Q28(lsbM, Q28fmt(2.2449)))
+ {
+ regions = 2;
+ k[1] = (lsbM << 1);
+ }
+ else
+ {
+ regions = 1;
+ }
+
+ *h_num_bands = 0;
+ for (reg = 0; reg < regions; reg++)
+ {
+ if (reg == 0)
+ {
+
+ tmp_q1 = pv_log2((k[1] << 20) / k[0]);
+
+ tmp_q1 = fxp_mul32_Q15(tmp_q1, b_p_o);
+ tmp_q1 = (tmp_q1 + 32) >> 6;
+
+ numBands = tmp_q1 << 1;
+
+
+ CalcBands(d, k[0], k[1], numBands); /* CalcBands => d */
+ shellsort(d, numBands); /* SortBands sort d */
+ cumSum(k[0] - channelOffset,
+ d,
+ numBands,
+ (v_k_master + *h_num_bands)); /* cumsum */
+
+ *h_num_bands += numBands; /* Output nr of bands */
+ }
+ else
+ {
+ tmp_q1 = pv_log2((k[reg + 1] << 20) / k[reg]);
+
+ tmp_q1 = fxp_mul32_Q30(tmp_q1, w[reg]);
+ tmp_q1 = fxp_mul32_Q15(tmp_q1, b_p_o);
+ tmp_q1 = (tmp_q1 + 16) >> 5;
+
+ numBands2 = tmp_q1 << 1;
+
+ CalcBands(d2, k[reg], k[reg+1], numBands2); /* CalcBands => d */
+ shellsort(d2, numBands2); /* SortBands sort d */
+ if (d[numBands-1] > d2[0])
+ {
+
+ Int32 change = d[numBands-1] - d2[0];
+ /* Limit the change so that the last band cannot get narrower than the first one */
+ if (change > (d2[numBands2-1] - d2[0]) >> 1)
+ {
+ change = (d2[numBands2-1] - d2[0]) >> 1;
+ }
+
+ d2[0] += change;
+ d2[numBands2-1] -= change;
+ shellsort(d2, numBands2);
+
+ }
+ cumSum(k[reg] - channelOffset,
+ d2,
+ numBands2,
+ v_k_master + *h_num_bands); /* cumsum */
+
+ *h_num_bands += numBands2; /* Output nr of bands */
+ }
+ }
+ }
+ else
+ { /* Linear mode */
+ Int32 k2_achived;
+ Int32 k2_diff;
+ Int32 diff_tot[MAX_OCTAVE + MAX_SECOND_REGION];
+ Int32 dk;
+ Int32 incr = 0;
+
+
+ if (alterScale)
+ {
+ numBands = (usb - lsbM) >> 1;
+ dk = 1;
+ k2_achived = lsbM + numBands;
+ }
+ else
+ {
+ numBands = usb - lsbM;
+ if (numBands & 0x1) /* equivalent rounding */
+ {
+ numBands--;
+ }
+ dk = 2;
+ k2_achived = lsbM + (numBands << 1);
+ }
+
+ k2_diff = usb - k2_achived;
+
+ for (i = 0; i < numBands; i++)
+ {
+ diff_tot[i] = dk;
+ }
+
+ if (k2_diff < 0) /* If linear scale wasn't achived */
+ {
+ incr = 1; /* and we got too large SBR area */
+ i = 0;
+ }
+
+ if (k2_diff > 0) /* If linear scale wasn't achived */
+ {
+ incr = -1; /* and we got too small SBR area */
+ i = numBands - 1;
+ }
+
+ /* Adjust diff vector to get spec. SBR range */
+ while (k2_diff != 0)
+ {
+ diff_tot[i] -= incr;
+ i += incr;
+ k2_diff += incr;
+ }
+
+ cumSum(lsbM,
+ diff_tot,
+ numBands,
+ v_k_master); /* cumsum */
+
+ *h_num_bands = numBands; /* Output nr of bands */
+ }
+}
+
+
+void CalcBands(Int32 * diff,
+ Int32 start,
+ Int32 stop,
+ Int32 num_bands)
+{
+ Int32 i;
+ Int32 previous;
+ Int32 current;
+ Int32 tmp_q1;
+
+
+ previous = start;
+
+ for (i = 1; i <= num_bands; i++)
+ {
+ /* float temp=(start * pow( (float)stop/start, (float)i/num_bands)); */
+
+ tmp_q1 = pv_log2((stop << 20) / start);
+
+ tmp_q1 = fxp_mul32_Q20(tmp_q1, (i << 27) / num_bands);
+ tmp_q1 = pv_pow2(tmp_q1);
+
+ tmp_q1 = fxp_mul32_Q20(tmp_q1, start);
+
+ current = (tmp_q1 + 16) >> 5;
+
+ diff[i-1] = current - previous;
+ previous = current;
+ }
+
+} /* End CalcBands */
+
+
+void cumSum(Int32 start_value,
+ Int32 * diff,
+ Int32 length,
+ Int32 * start_adress)
+{
+ Int32 i;
+ Int32 *pt_start_adress = start_adress;
+ Int32 *pt_start_adress_1 = start_adress;
+ Int32 *pt_diff = diff;
+
+ if (length > 0) /* avoid possible error on loop */
+ {
+ *(pt_start_adress_1++) = start_value;
+
+ for (i = (length >> 1); i != 0; i--)
+ {
+ *(pt_start_adress_1++) = *(pt_start_adress++) + *(pt_diff++);
+ *(pt_start_adress_1++) = *(pt_start_adress++) + *(pt_diff++);
+ }
+
+ if (length&1)
+ {
+ *(pt_start_adress_1) = *(pt_start_adress) + *(pt_diff);
+ }
+ }
+
+} /* End cumSum */
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacdec/sbr_update_freq_scale.h b/media/libstagefright/codecs/aacdec/sbr_update_freq_scale.h
new file mode 100644
index 0000000..4acf3aa
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sbr_update_freq_scale.h
@@ -0,0 +1,104 @@
+/* ------------------------------------------------------------------
+ * 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: sbr_update_freq_scale.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+ ----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SBR_UPDATE_FREQ_SCALE_H
+#define SBR_UPDATE_FREQ_SCALE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define MAX_OCTAVE 29
+#define MAX_SECOND_REGION 50
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void sbr_update_freq_scale(Int32 * v_k_master,
+ Int32 *h_num_bands,
+ const Int32 lsbM,
+ const Int32 usb,
+ const Int32 freqScale,
+ const Int32 alterScale,
+ const Int32 channelOffset);
+
+
+void CalcBands(Int32 * diff,
+ Int32 start,
+ Int32 stop,
+ Int32 num_bands);
+
+void cumSum(Int32 start_value,
+ Int32 * diff,
+ Int32 length,
+ Int32 * start_adress);
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/set_mc_info.cpp b/media/libstagefright/codecs/aacdec/set_mc_info.cpp
new file mode 100644
index 0000000..5a11941
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/set_mc_info.cpp
@@ -0,0 +1,309 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/set_mc_info.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified per review comments
+
+ Description: Change audioObjectType from Int to enum types
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pMC_Info = pointer to structure MC_Info that holds information of
+ multiple channels' configurations
+ Data type pointer to MC_Info
+
+ objectType = variable that holds the Audio Object Type of current
+ file/bitstream.
+ Data type Int
+
+ sampling_rate_idx = variable that indicates the sampling rate of the
+ source file being encoded
+ Data Type Int
+
+ tag = variable that stores the element instance tag of the
+ first (front) channel element.
+ Data type Int
+
+ is_cpe = variable that indicates if a Channel Pair Element (CPE)
+ or a Single Channel Element (SCE) is used.
+ Data type Int (maybe Boolean)
+
+ pWinSeqInfo = array of pointers that points to structures holding
+ frame information of long and short window sequences.
+ Data type FrameInfo
+
+ pSfbwidth128 = array that will store the scalefactor bandwidth of
+ short window sequence frame.
+ Data type Int array
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ return SUCCESS
+
+ Pointers and Buffers Modified:
+ pMC_Info->nch contains the number of channels depending
+ upon if CPE or SCE is used
+ pMC_Info->objectType contents updated with the decoded Audio
+ Object Type
+
+ pMC_Info->ch_info.tag contents updated with the value of decoded
+ channel element tag
+
+ PMC_Info->ch_info.cpe contents updated depending upon if CPE or
+ SCE is used
+
+ pWinSeqInfo contents updated by calling infoinit if
+ sampling_rate_idx is different from
+ previous value
+
+ pSfbWidth128 contents updated by calling infoinit if
+ sampling_rate_idx is different from
+ previous value
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function initializes the channel configuration information. The
+ structure MC_Info stores the number of channels, channel element tag.
+ If sampling rate index is different from the previous value,
+ The frame information will be updated by calling infoinit.c
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function shall update the relevant information on channel configs
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+ (2) ISO/IEC 14496-3: 1999(E)
+ Subpart 1 p20 Table 1.6.3
+ Subpart 4 p30 5.1.2.1
+ Subpart 4 p31 4.5.2.1.1
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ pMC_Info->nch = 0;
+
+ pMC_Info->profile = objectType;
+
+ IF (pMC_Info->sampling_rate_idx != sampling_rate_idx)
+ THEN
+ pMC_Info->sampling_rate_idx = sampling_rate_idx;
+
+ CALL infoinit(
+ samp_rate_idx = sampling_rate_idx
+ ppWin_seq_info= pWinSeqInfo
+ pSfbwidth128 = pSfbwidth128)
+ MODIFYING(pWinSeqInfo, pSfbwidth128)
+ RETURNING(None)
+ ENDIF
+
+ pCh_Info = &pMC_Info->ch_info[0];
+ pCh_Info->tag = tag;
+
+ IF (is_cpe == FALSE)
+ THEN
+ pCh_Info->cpe = FALSE;
+
+ pMC_Info->nch = 1;
+
+ ELSE
+ pCh_Info->cpe = TRUE;
+ pCh_Info = &pMC_Info->ch_info[1];
+ pCh_Info->tag = tag;
+ pCh_Info->cpe = TRUE;
+
+ pMC_Info->nch = 2;
+
+ ENDIF
+
+ RETURN(SUCCESS)
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "set_mc_info.h"
+#include "huffman.h"
+#include "s_ch_info.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Int set_mc_info(
+ MC_Info *pMC_Info,
+ const tMP4AudioObjectType audioObjectType, /* used to be profile */
+ const Int sampling_rate_idx,
+ const Int tag, /* always pass-in last element's value */
+ const Int is_cpe,
+ FrameInfo *pWinSeqInfo[],
+ Int sfbwidth128[]
+)
+{
+ Ch_Info *pCh_Info; /*optional task: eliminate this structure */
+
+ /*
+ * audioObjectType and sampling rate
+ * re-configure if new sampling rate
+ *
+ */
+ pMC_Info->audioObjectType = audioObjectType;
+
+ if (pMC_Info->sampling_rate_idx != sampling_rate_idx)
+ {
+ pMC_Info->sampling_rate_idx = sampling_rate_idx;
+
+ Int status;
+ status = infoinit(sampling_rate_idx,
+ pWinSeqInfo,
+ sfbwidth128);
+ if (SUCCESS != status)
+ {
+ return 1;
+ }
+ }
+
+ /*
+ * first setup values for mono config, Single Channel Element (SCE)
+ * then if stereo, go inside if(is_cpe != FALSE) branch to setup
+ * values for stereo.
+ * set the channel counts
+ * save tag for left channel
+ */
+ pMC_Info->nch = 1 + is_cpe;
+
+ pCh_Info = &pMC_Info->ch_info[0];
+ pCh_Info->tag = tag;
+ pCh_Info->cpe = is_cpe;
+
+ /* This if branch maybe deleted in the future */
+ if (is_cpe != FALSE)
+ {
+ /* Channel Pair Element (CPE) */
+ /* right channel*/
+ pCh_Info = &pMC_Info->ch_info[1];
+ pCh_Info->cpe = TRUE;
+
+ }
+
+ return(SUCCESS); /* possible future error checkings */
+}
diff --git a/media/libstagefright/codecs/aacdec/set_mc_info.h b/media/libstagefright/codecs/aacdec/set_mc_info.h
new file mode 100644
index 0000000..8043b3b
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/set_mc_info.h
@@ -0,0 +1,98 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/set_mc_info.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: (1) use enum type for audioObjectType (2) update revision history
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes function declaration for set_mc_info.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SET_MC_INFO_H
+#define SET_MC_INFO_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_mc_info.h"
+#include "s_frameinfo.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+Int set_mc_info(
+ MC_Info *pMC_Info,
+ const tMP4AudioObjectType objectType, /* used to be profile */
+ const Int sampling_rate_idx,
+ const Int tag, /* always pass-in last element's value */
+ const Int is_cpe,
+ FrameInfo *pWinSeqInfo[],
+ Int pSfbwidth128[]
+);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/sfb.cpp b/media/libstagefright/codecs/aacdec/sfb.cpp
new file mode 100644
index 0000000..f2d3a3e
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sfb.cpp
@@ -0,0 +1,275 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/sfb.c
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: created to define the scalefactor bands for all sampling rates
+
+ Description: Change short to Int16
+
+ Description: Modified structure to avoid assigning addresses to constant
+ tables. This solve linking problem when using the
+ /ropi option (Read-only position independent) for some
+ compilers
+ - Eliminated redundant vector sfb_96_128.
+ - Eliminated references to contant vector addresses in
+ samp_rate_info
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ Local Stores/Buffers/Pointers Needed:
+
+ Global Stores/Buffers/Pointers Needed:
+
+ Outputs:
+
+ Pointers and Buffers Modified:
+
+
+ Local Stores Modified:
+
+ Global Stores Modified:
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function defines the scalefactor bands for all sampling rates
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3: 1999(E)
+ Subpart 4 p66 (sfb tables)
+ p111 (4.6.10)
+ p200 (Annex 4.B.5)
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "sfb.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const Int16 sfb_96_1024[] =
+{
+ 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
+}; /* 41 scfbands */
+
+const Int16 sfb_64_1024[] =
+{
+ 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
+}; /* 41 scfbands 47 */
+
+const Int16 sfb_64_128[] =
+{
+ 4, 8, 12, 16, 20, 24, 32,
+ 40, 48, 64, 92, 128
+}; /* 12 scfbands */
+
+
+const Int16 sfb_48_1024[] =
+{
+ 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
+};
+/* 49 scfbands*/
+
+const Int16 sfb_48_128[] =
+{
+ 4, 8, 12, 16, 20, 28, 36,
+ 44, 56, 68, 80, 96, 112, 128
+}; /* 14 scfbands */
+
+const Int16 sfb_32_1024[] =
+{
+ 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
+}; /* 51 scfbands */
+
+const Int16 sfb_24_1024[] =
+{
+ 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
+}; /* 47 scfbands */
+
+const Int16 sfb_24_128[] =
+{
+ 4, 8, 12, 16, 20, 24, 28,
+ 36, 44, 52, 64, 76, 92, 108,
+ 128
+}; /* 15 scfbands */
+
+const Int16 sfb_16_1024[] =
+{
+ 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
+}; /* 43 scfbands */
+
+const Int16 sfb_16_128[] =
+{
+ 4, 8, 12, 16, 20, 24, 28,
+ 32, 40, 48, 60, 72, 88, 108,
+ 128
+}; /* 15 scfbands */
+
+const Int16 sfb_8_1024[] =
+{
+ 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
+}; /* 40 scfbands */
+
+const Int16 sfb_8_128[] =
+{
+ 4, 8, 12, 16, 20, 24, 28,
+ 36, 44, 52, 60, 72, 88, 108,
+ 128
+}; /* 15 scfbands */
+
+const SR_Info samp_rate_info[12] =
+{
+ /* sampling_frequency, #long sfb, #short sfb */
+ /* samp_rate, nsfb1024, nsfb128 */
+ {96000, 41, 12}, /* 96000 */
+ {88200, 41, 12}, /* 88200 */
+ {64000, 47, 12}, /* 64000 */
+ {48000, 49, 14}, /* 48000 */
+ {44100, 49, 14}, /* 44100 */
+ {32000, 51, 14}, /* 32000 */
+ {24000, 47, 15}, /* 24000 */
+ {22050, 47, 15}, /* 22050 */
+ {16000, 43, 15}, /* 16000 */
+ {12000, 43, 15}, /* 12000 */
+ {11025, 43, 15}, /* 11025 */
+ { 8000, 40, 15}, /* 8000 */
+};
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
diff --git a/media/libstagefright/codecs/aacdec/sfb.h b/media/libstagefright/codecs/aacdec/sfb.h
new file mode 100644
index 0000000..0cc1707
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/sfb.h
@@ -0,0 +1,117 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: sfb.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: created to declare scalefactor bands for all sampling rates
+
+ Description: Change short to Int16
+
+ Description: Eliminated declaration of sfb_96_128 array, values are equal
+ to array sfb_64_128
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ this file declares the scalefactor bands for all sampling rates
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SFB_H
+#define SFB_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_sr_info.h"
+#include "e_progconfigconst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+extern const Int16 sfb_96_1024[]; /* 41 scfbands */
+
+extern const Int16 sfb_64_1024[]; /* 41 scfbands 47 */
+
+extern const Int16 sfb_64_128[]; /* 12 scfbands */
+
+
+extern const Int16 sfb_48_1024[]; /* 49 scfbands */
+
+extern const Int16 sfb_48_128[]; /* 14 scfbands */
+
+extern const Int16 sfb_32_1024[]; /* 51 scfbands */
+
+extern const Int16 sfb_24_1024[]; /* 47 scfbands */
+
+extern const Int16 sfb_24_128[]; /* 15 scfbands */
+
+extern const Int16 sfb_16_1024[]; /* 43 scfbands */
+
+extern const Int16 sfb_16_128[]; /* 15 scfbands */
+
+extern const Int16 sfb_8_1024[]; /* 40 scfbands */
+
+extern const Int16 sfb_8_128[]; /* 15 scfbands */
+
+extern const SR_Info samp_rate_info[12];
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/shellsort.cpp b/media/libstagefright/codecs/aacdec/shellsort.cpp
new file mode 100644
index 0000000..5feb803
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/shellsort.cpp
@@ -0,0 +1,138 @@
+/* ------------------------------------------------------------------
+ * 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: shellsort.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Sorting routine
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "shellsort.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void shellsort(Int32 in[], Int32 n)
+{
+
+ Int32 i;
+ Int32 j;
+ Int32 v;
+ Int32 inc = 1;
+
+ do
+ {
+ inc = 3 * inc + 1;
+ }
+ while (inc <= n);
+
+ do
+ {
+ inc = inc / 3;
+ for (i = inc + 1; i <= n; i++)
+ {
+ v = in[i-1];
+ j = i;
+ while (in[j-inc-1] > v)
+ {
+ in[j-1] = in[j-inc-1];
+ j -= inc;
+ if (j <= inc)
+ {
+ break;
+ }
+ }
+ in[j-1] = v;
+ }
+ }
+ while (inc > 1);
+
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacdec/shellsort.h b/media/libstagefright/codecs/aacdec/shellsort.h
new file mode 100644
index 0000000..a4658e3
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/shellsort.h
@@ -0,0 +1,84 @@
+/* ------------------------------------------------------------------
+ * 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: shellsort.h
+ Funtions:
+ get_dse
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+------------------------------------------------------------------------------
+
+
+ ----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SHELLSORT_H
+#define SHELLSORT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+void shellsort(Int32 in[], Int32 n);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/stereo_2_mono.h b/media/libstagefright/codecs/aacdec/stereo_2_mono.h
new file mode 100644
index 0000000..3e27c70
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/stereo_2_mono.h
@@ -0,0 +1,97 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: stereo_2_mono.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for the declaration of the function stereo_2_mono()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef STEREO_2_MONO_H
+#define STEREO_2_MONO_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void stereo_2_mono(
+ const Int16 sourceLeft[],
+ const Int16 sourceRight[],
+ Int16 outputBuffer[],
+ const Int sourcePointsPerChannel);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STEREO_2_MONO_H */
+
diff --git a/media/libstagefright/codecs/aacdec/synthesis_sub_band.cpp b/media/libstagefright/codecs/aacdec/synthesis_sub_band.cpp
new file mode 100644
index 0000000..c1418e3
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/synthesis_sub_band.cpp
@@ -0,0 +1,483 @@
+/* ------------------------------------------------------------------
+ * 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: synthesis_sub_band.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date: MM/DD/YYYY
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Int32 vec[], Input vector, 32-bit
+ const Int32 *cosTerms, Cosine Terms
+ Int32 *scratch_mem Scratch memory
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Implement root squared of a number
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+#include "pv_audio_type_defs.h"
+#include "fxp_mul32.h"
+#include "dct64.h"
+#include "synthesis_sub_band.h"
+#include "mdst.h"
+#include "dct16.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define Qfmt_30(x) (Int32)(x*((Int32)(1<<30)) + (x>=0?0.5F:-0.5F))
+#define Qfmt_25(x) (Int32)(x*((Int32)(1<<25))*(1.5625F) + (x>=0?0.5F:-0.5F))
+
+#define SCALE_DOWN_LP Qfmt_30(0.075000F) /* 3/40 */
+#define SCALE_DOWN_HQ Qfmt_30(0.009375F*0.64F) /* 3/40 * 1/8 */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+const Int32 CosTable_64[64] =
+{
+ Qfmt_25(0.50003765191555F), Qfmt_25(40.74468810335183F), Qfmt_25(0.50033903744282F), Qfmt_25(13.58429025728446F),
+ Qfmt_25(0.50094271763809F), Qfmt_25(8.15384860246681F), Qfmt_25(0.50185051748424F), Qfmt_25(5.82768837784465F),
+ Qfmt_25(0.50306519130137F), Qfmt_25(4.53629093696936F), Qfmt_25(0.50459044322165F), Qfmt_25(3.71524273832697F),
+ Qfmt_25(0.50643095492855F), Qfmt_25(3.14746219178191F), Qfmt_25(0.50859242104981F), Qfmt_25(2.73164502877394F),
+ Qfmt_25(0.51108159270668F), Qfmt_25(2.41416000025008F), Qfmt_25(0.51390632984754F), Qfmt_25(2.16395781875198F),
+ Qfmt_25(0.51707566313349F), Qfmt_25(1.96181784857117F), Qfmt_25(0.52059986630189F), Qfmt_25(1.79520521907789F),
+ Qfmt_25(0.52449054011472F), Qfmt_25(1.65559652426412F), Qfmt_25(0.52876070920749F), Qfmt_25(1.53699410085250F),
+ Qfmt_25(0.53342493339713F), Qfmt_25(1.43505508844143F), Qfmt_25(0.53849943529198F), Qfmt_25(1.34655762820629F),
+ Qfmt_25(0.54400224638178F), Qfmt_25(1.26906117169912F), Qfmt_25(0.54995337418324F), Qfmt_25(1.20068325572942F),
+ Qfmt_25(0.55637499348989F), Qfmt_25(1.13994867510150F), Qfmt_25(0.56329166534170F), Qfmt_25(1.08568506425801F),
+ Qfmt_25(0.57073058801215F), Qfmt_25(1.03694904091039F), Qfmt_25(0.57872188513482F), Qfmt_25(0.99297296126755F),
+ Qfmt_25(0.58729893709379F), Qfmt_25(0.95312587439212F), Qfmt_25(0.59649876302446F), Qfmt_25(0.91688444618465F),
+ Qfmt_25(0.60636246227215F), Qfmt_25(0.88381100455962F), Qfmt_25(0.61693572600507F), Qfmt_25(0.85353675100661F),
+ Qfmt_25(0.62826943197077F), Qfmt_25(0.82574877386279F), Qfmt_25(0.64042033824166F), Qfmt_25(0.80017989562169F),
+ Qfmt_25(0.65345189537513F), Qfmt_25(0.77660065823396F), Qfmt_25(0.66743520092634F), Qfmt_25(0.75481293911653F),
+ Qfmt_25(0.68245012597642F), Qfmt_25(0.73464482364786F), Qfmt_25(0.69858665064723F), Qfmt_25(0.71594645497057F),
+};
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+void synthesis_sub_band_LC(Int32 Sr[], Int16 data[])
+{
+
+ Int32 *temp_o1 = (Int32 *) & data[0];
+
+ Int i;
+ Int32 *pt_temp_e;
+ Int32 *pt_temp_o = temp_o1;
+ Int32 *pt_temp_x = &Sr[63];
+ Int32 temp1;
+ Int32 temp2;
+ Int32 temp3;
+ Int32 temp11;
+
+ Int16 *pt_data_1;
+ Int16 *pt_data_2;
+
+ Int32 *pt_Sr_1 = Sr;
+ Int16 tmp1;
+ Int16 tmp2;
+ Int16 tmp11;
+ Int16 tmp22;
+ const Int32 *pt_cosTerms = CosTable_48;
+
+
+ temp2 = *(pt_temp_x--);
+ for (i = 20; i != 0; i--)
+ {
+ temp1 = *(pt_Sr_1);
+ temp3 = *(pt_cosTerms++);
+ *(pt_Sr_1++) = temp1 + temp2;
+ *(pt_temp_o++) = fxp_mul32_Q31((temp1 - temp2), temp3) << 1;
+ temp2 = *(pt_temp_x--);
+ }
+
+ for (i = 12; i != 0; i--)
+ {
+ temp1 = *(pt_Sr_1);
+ temp3 = *(pt_cosTerms++);
+ *(pt_Sr_1++) = temp1 + temp2;
+ *(pt_temp_o++) = fxp_mul32_Q26((temp1 - temp2), temp3);
+ temp2 = *(pt_temp_x--);
+ }
+
+
+ pv_split_LC(temp_o1, &Sr[32]);
+
+ dct_16(temp_o1, 1); // Even terms
+ dct_16(&Sr[32], 1); // Odd terms
+
+ /* merge */
+
+
+ pt_Sr_1 = &temp_o1[31];
+ pt_temp_e = &temp_o1[15];
+ pt_temp_o = &Sr[47];
+
+ temp1 = *(pt_temp_o--);
+ *(pt_Sr_1--) = temp1;
+ for (i = 5; i != 0; i--)
+ {
+ temp2 = *(pt_temp_o--);
+ *(pt_Sr_1--) = *(pt_temp_e--);
+ *(pt_Sr_1--) = temp1 + temp2;
+ temp3 = *(pt_temp_o--);
+ *(pt_Sr_1--) = *(pt_temp_e--);
+ *(pt_Sr_1--) = temp2 + temp3;
+ temp1 = *(pt_temp_o--);
+ *(pt_Sr_1--) = *(pt_temp_e--);
+ *(pt_Sr_1--) = temp1 + temp3;
+ }
+
+
+ pv_split_LC(Sr, &Sr[32]);
+
+ dct_16(Sr, 1); // Even terms
+ dct_16(&Sr[32], 1); // Odd terms
+
+
+ pt_temp_x = &temp_o1[31];
+ pt_temp_e = &Sr[15];
+ pt_temp_o = &Sr[47];
+
+ pt_data_1 = &data[95];
+
+ temp2 = *(pt_temp_x--);
+ temp11 = *(pt_temp_x--);
+ temp1 = *(pt_temp_o--);
+
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31(temp2, SCALE_DOWN_LP);
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31(temp1, SCALE_DOWN_LP);
+
+ for (i = 5; i != 0; i--)
+ {
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31((temp11 + temp2), SCALE_DOWN_LP);
+ temp3 = *(pt_temp_x--);
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31(*(pt_temp_e--), SCALE_DOWN_LP);
+ temp2 = *(pt_temp_o--);
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31((temp11 + temp3), SCALE_DOWN_LP);
+ temp11 = *(pt_temp_x--);
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31((temp1 + temp2), SCALE_DOWN_LP);
+
+
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31((temp11 + temp3), SCALE_DOWN_LP);
+ temp1 = *(pt_temp_x--);
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31(*(pt_temp_e--), SCALE_DOWN_LP);
+ temp3 = *(pt_temp_o--);
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31((temp11 + temp1), SCALE_DOWN_LP);
+ temp11 = *(pt_temp_x--);
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31((temp2 + temp3), SCALE_DOWN_LP);
+
+
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31((temp11 + temp1), SCALE_DOWN_LP);
+ temp2 = *(pt_temp_x--);
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31(*(pt_temp_e--), SCALE_DOWN_LP);
+ temp1 = *(pt_temp_o--);
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31((temp11 + temp2), SCALE_DOWN_LP);
+ temp11 = *(pt_temp_x--);
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31((temp1 + temp3), SCALE_DOWN_LP);
+ }
+
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31((temp11 + temp2), SCALE_DOWN_LP);
+ *(pt_data_1--) = (Int16) fxp_mul32_Q31(*(pt_temp_e), SCALE_DOWN_LP);
+
+ /* ---- merge ends---- */
+
+
+ pt_data_1 = &data[95];
+ pt_data_2 = &data[96];
+
+ *(pt_data_2++) = 0;
+ tmp1 = *(pt_data_1--);
+ tmp2 = *(pt_data_1--);
+ tmp11 = *(pt_data_1--);
+ tmp22 = *(pt_data_1--);
+
+ for (i = 7; i != 0; i--)
+ {
+ *(pt_data_2++) = (-tmp1);
+ *(pt_data_2++) = (-tmp2);
+ *(pt_data_2++) = (-tmp11);
+ *(pt_data_2++) = (-tmp22);
+ tmp1 = *(pt_data_1--);
+ tmp2 = *(pt_data_1--);
+ tmp11 = *(pt_data_1--);
+ tmp22 = *(pt_data_1--);
+ }
+
+
+ *(pt_data_2++) = (-tmp1);
+ *(pt_data_2++) = (-tmp2);
+ *(pt_data_2++) = (-tmp11);
+
+ pt_data_2 = &data[0];
+
+ *(pt_data_2++) = tmp22;
+ tmp1 = *(pt_data_1--);
+ tmp2 = *(pt_data_1--);
+ tmp11 = *(pt_data_1--);
+ tmp22 = *(pt_data_1--);
+
+ for (i = 7; i != 0; i--)
+ {
+ *(pt_data_2++) = tmp1;
+ *(pt_data_2++) = tmp2;
+ *(pt_data_2++) = tmp11;
+ *(pt_data_2++) = tmp22;
+ tmp1 = *(pt_data_1--);
+ tmp2 = *(pt_data_1--);
+ tmp11 = *(pt_data_1--);
+ tmp22 = *(pt_data_1--);
+ }
+
+ *(pt_data_2++) = tmp1;
+ *(pt_data_2++) = tmp2;
+ *(pt_data_2++) = tmp11;
+ *(pt_data_2) = tmp22;
+
+}
+
+
+void synthesis_sub_band_LC_down_sampled(Int32 Sr[], Int16 data[])
+{
+
+ Int i ;
+ Int16 *pt_data_1;
+
+ pt_data_1 = &data[0];
+
+ dct_32(Sr);
+
+ for (i = 0; i < 16; i++)
+ {
+ pt_data_1[ i] = (Int16)(Sr[16-i] >> 5);
+ pt_data_1[16+i] = (Int16)(Sr[i] >> 5);
+ pt_data_1[32+i] = (Int16)(Sr[16+i] >> 5);
+ }
+ for (i = 0; i < 15; i++)
+ {
+ pt_data_1[49+i] = (Int16)(-Sr[31-i] >> 5);
+ }
+ pt_data_1[48] = 0;
+}
+
+
+#ifdef HQ_SBR
+
+void synthesis_sub_band(Int32 Sr[], Int32 Si[], Int16 data[])
+{
+
+
+ Int32 i ;
+ Int16 *pt_data_1;
+ Int16 *pt_data_2;
+ Int32 *pt_Sr_1;
+ Int32 *pt_Sr_2;
+ Int32 *pt_Si_1;
+ Int32 *pt_Si_2;
+
+ Int32 tmp1;
+ Int32 tmp2;
+ Int32 tmp3;
+ Int32 tmp4;
+
+ Int32 cosx;
+ const Int32 *pt_CosTable = CosTable_64;
+
+
+ pt_Sr_1 = &Sr[0];
+ pt_Sr_2 = &Sr[63];
+
+ pt_Si_1 = &Si[0];
+ pt_Si_2 = &Si[63];
+
+
+ tmp3 = *pt_Sr_1;
+
+ for (i = 32; i != 0; i--)
+ {
+ tmp4 = *pt_Si_2;
+ cosx = *(pt_CosTable++);
+ *(pt_Sr_1++) = fxp_mul32_Q31(tmp3, cosx);
+ tmp3 = *pt_Si_1;
+ *(pt_Si_1++) = fxp_mul32_Q31(tmp4, cosx);
+ tmp4 = *pt_Sr_2;
+ cosx = *(pt_CosTable++);
+ *(pt_Si_2--) = fxp_mul32_Q31(tmp3, cosx);
+ *(pt_Sr_2--) = fxp_mul32_Q31(tmp4, cosx);
+ tmp3 = *pt_Sr_1;
+ }
+
+
+ dct_64(Sr, (Int32 *)data);
+ dct_64(Si, (Int32 *)data);
+
+
+ pt_data_1 = &data[0];
+ pt_data_2 = &data[127];
+
+ pt_Sr_1 = &Sr[0];
+ pt_Si_1 = &Si[0];
+
+ tmp1 = *(pt_Sr_1++);
+ tmp3 = *(pt_Sr_1++);
+ tmp2 = *(pt_Si_1++);
+ tmp4 = *(pt_Si_1++);
+
+ for (i = 32; i != 0; i--)
+ {
+ *(pt_data_1++) = (Int16) fxp_mul32_Q31((tmp2 - tmp1), SCALE_DOWN_HQ);
+ *(pt_data_1++) = (Int16) fxp_mul32_Q31(-(tmp3 + tmp4), SCALE_DOWN_HQ);
+ *(pt_data_2--) = (Int16) fxp_mul32_Q31((tmp1 + tmp2), SCALE_DOWN_HQ);
+ *(pt_data_2--) = (Int16) fxp_mul32_Q31((tmp3 - tmp4), SCALE_DOWN_HQ);
+
+ tmp1 = *(pt_Sr_1++);
+ tmp3 = *(pt_Sr_1++);
+ tmp2 = *(pt_Si_1++);
+ tmp4 = *(pt_Si_1++);
+ }
+
+}
+
+
+const Int32 exp_m0_25_phi[32] =
+{
+
+ 0x7FFEFE6E, 0x7FEAFB4A, 0x7FC2F827, 0x7F87F505,
+ 0x7F38F1E4, 0x7ED6EEC6, 0x7E60EBAB, 0x7DD6E892,
+ 0x7D3AE57D, 0x7C89E26D, 0x7BC6DF61, 0x7AEFDC59,
+ 0x7A06D958, 0x790AD65C, 0x77FBD367, 0x76D9D079,
+ 0x75A6CD92, 0x7460CAB2, 0x7308C7DB, 0x719EC50D,
+ 0x7023C248, 0x6E97BF8C, 0x6CF9BCDA, 0x6B4BBA33,
+ 0x698CB796, 0x67BDB505, 0x65DEB27F, 0x63EFB005,
+ 0x61F1AD97, 0x5FE4AB36, 0x5DC8A8E2, 0x5B9DA69C
+};
+
+void synthesis_sub_band_down_sampled(Int32 Sr[], Int32 Si[], Int16 data[])
+{
+
+ Int16 k;
+ Int16 *pt_data_1;
+ Int32 exp_m0_25;
+ const Int32 *pt_exp = exp_m0_25_phi;
+
+ Int32 *XX = Sr;
+ Int32 *YY = (Int32 *)data;
+ Int32 tmp1;
+ Int32 tmp2;
+
+ for (k = 0; k < 32; k++)
+ {
+ exp_m0_25 = *(pt_exp++);
+ tmp1 = Sr[k];
+ tmp2 = Si[k];
+ XX[k] = cmplx_mul32_by_16(-tmp1, tmp2, exp_m0_25);
+ YY[31-k] = cmplx_mul32_by_16(tmp2, tmp1, exp_m0_25);
+ }
+
+ mdct_32(XX);
+ mdct_32(YY);
+
+ for (k = 0; k < 32; k++)
+ {
+ Si[k] = YY[k];
+ }
+
+ pt_data_1 = data;
+
+ for (k = 0; k < 16; k++)
+ {
+ *(pt_data_1++) = (Int16)((XX[2*k ] + Si[2*k ]) >> 14);
+ *(pt_data_1++) = (Int16)((XX[2*k+1] - Si[2*k+1]) >> 14);
+ }
+
+ for (k = 15; k > -1; k--)
+ {
+ *(pt_data_1++) = (Int16)(-(XX[2*k+1] + Si[2*k+1]) >> 14);
+ *(pt_data_1++) = (Int16)(-(XX[2*k ] - Si[2*k ]) >> 14);
+ }
+
+}
+
+
+#endif /* HQ_SBR */
+
+#endif /* AAC_PLUS */
+
+
diff --git a/media/libstagefright/codecs/aacdec/synthesis_sub_band.h b/media/libstagefright/codecs/aacdec/synthesis_sub_band.h
new file mode 100644
index 0000000..042c488
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/synthesis_sub_band.h
@@ -0,0 +1,78 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: synthesis_sub_band.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef SYNTHESIS_SUB_BAND_H
+#define SYNTHESIS_SUB_BAND_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ void synthesis_sub_band_LC(Int32 Sr[], Int16 data[]);
+ void synthesis_sub_band_LC_down_sampled(Int32 Sr[], Int16 data[]);
+
+
+#ifdef HQ_SBR
+
+ void synthesis_sub_band(Int32 Sr[], Int32 Si[], Int16 data[]);
+ void synthesis_sub_band_down_sampled(Int32 Sr[], Int32 Si[], Int16 data[]);
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SYNTHESIS_SUB_BAND_H */
+
diff --git a/media/libstagefright/codecs/aacdec/tns_ar_filter.cpp b/media/libstagefright/codecs/aacdec/tns_ar_filter.cpp
new file mode 100644
index 0000000..db31a63
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/tns_ar_filter.cpp
@@ -0,0 +1,474 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: tns_ar_filter.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Implemented 24-bit fixed point version
+ Optimized C code
+
+ Description:
+ - Added OVERFLOW_SHIFT_DOWN to avoid overflow.
+ - Increased precision by using the Q format of the LPC coefficient.
+ - Modified interface to add LPC Q format and scratch memory
+ for the state variables.
+ - Added pv_memset to clear state filter
+ - Updated format for comments (to PV standard)
+ - Updated copyright notice
+
+ Description:
+ - Changed multiplication scheme to increase precision. This
+ works better than older version.
+
+ Description:
+ - Include log2(order) as a scaling down parameter.
+
+ Description:
+ Modified to reflect code review comments
+ - misspelled words, extra comments and explicit requirements
+
+ Description:
+ deleted comment about fix Q format (L 107)
+
+ Description: Implemented a more efficient version, which eliminated the use
+ of "scratch memory" via introducing a pointer that references the actual
+ output.
+
+ Description: Removed the parameter "scratch_Int32_buffer" as this space
+ in memory is no longer needed by this function.
+
+ Description: Removed references to "scratch_Int32_buffer" in the Inputs
+ section.
+
+ Description:
+ Modified casting to ensure proper operations for different platforms
+
+ Description:
+ Per code review comment:
+ Eliminated casting to UInt and Int in b_low and b_high, they are
+ redundant and may add unncessary extra cycles in some platforms
+
+ Description: Updated the SW template to include the full pathname to the
+ source file and a slightly modified copyright header.
+
+ Description: Changed the order of the unsigned * signed multiply so the
+ casting to Int32 is performed on the unsigned operand.
+
+ Description:
+ Modified 32 by 16 bit multiplications to avoid unnecessary moves to
+ registers. Also split the code (based on flag direction) to simplify
+ pointer's updates
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ spec = spectral input to be shaped by the filter.
+ Fixed point format
+ Int32[]
+ length = spec_length
+
+ spec_length = length of spec array.
+ const Int
+
+ direction = direction for application of tns filter.
+ +1 filters spectrum from low to high frequencies
+ (first input to filter is spec[0])
+ -1 filters spectrum from high to low frequencies
+ (first input to filter is spec[spec_length-1])
+ const Int
+
+ lpc = array of lpc coefficients, minus lpc[0] which is assumed to be "1"
+ Fixed point format
+ const Int[]
+ length = TNS_MAX_ORDER
+
+ Q_lpc = Q format for the lpc coeffcients (for max. precision, it assumes
+ that all 16 bits are used)
+ const Int
+
+ order = order of the TNS filter (Range of 1 - TNS_MAX_ORDER)
+ Int
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ spec = contains spectral data after application of TNS filter
+ Int32 array
+ length = spec_length
+
+
+ Local Stores Modified:
+
+ Global Stores Modified:
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ A block of spectral data (Int32 spec[]) of length (const Int spec_length)
+ is processed by a simple all-pole filter defined by
+ LPC coefficients passed via (const Int lpc[])
+
+ TNS filter equation
+ y(n) = x(n) - lpc(2)*y(n-1) - ... - lpc(order+1)*y(n-order)
+
+ The filter calculation is performed in place, i.e. the output is passed
+ back to the calling function via (Int32 spec[])
+
+ The filter's order is defined by the variable (const Int order)
+ The direction of the filter's application is defined by (const Int inc)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function should match the functionality of the ISO code.
+ The implementation does support filter orders bigger or equal to 1.
+ The size of the spectral coeffcients has to be bigger or equal than 1.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.6.8 (Temporal Noise Shaping)
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+ FOR (i=0; i<order; i++)
+ state[i] = 0;
+ ENDFOR
+
+ IF (inc == -1)
+ THEN
+ spec = spec + spec_length - 1;
+ ENDIF
+
+ FOR (i=0; i<spec_length; i++)
+
+ y = *spec;
+
+ FOR (j=0; j<order; j++)
+
+ y -= lpc[j] * state[j];
+
+ ENDFOR
+
+ FOR (j=order-1; j>0; j--)
+
+ state[j] = state[j-1];
+
+ ENDFOR
+
+ state[0] = y;
+
+ *spec = y;
+
+ spec = spec + inc;
+
+ ENDFOR
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+
+ When the code is written for a specific target processor
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_tns_const.h"
+#include "tns_ar_filter.h"
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define MASK_LOW16 0xFFFF
+#define UPPER16 16
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Int tns_ar_filter(
+ Int32 spec[],
+ const Int spec_length,
+ const Int direction,
+ const Int32 lpc[],
+ const Int Q_lpc,
+ const Int order)
+{
+
+ Int i;
+ Int j;
+
+ /*
+ * Multiplication related variables
+ */
+
+ Int32 temp;
+
+ /*
+ * Filter related variables
+ */
+ Int32 y0;
+
+ /*
+ * Circular buffer to hold the filter's state
+ * (y[n-1],y[n-2],y[n-3],etc.)
+ *
+ * p_state and p_lpc should take advantage
+ * of any special circular buffer instructions
+ * if this code is hand-optimized in assembly.
+ */
+
+ Int32 *p_state = NULL;
+
+ const Int32 *p_lpc;
+
+
+ Int shift_up;
+ Int shift_down_amount;
+
+ /*
+ * Pointer to the I/O memory space
+ */
+ Int32 *p_spec = spec;
+
+
+ i = 0;
+ j = order;
+
+ /*
+ * get the power of 2 that is bigger than the order
+ * i is the bit counter and j is modified until exceed
+ * the power of 2 corresponding to TNS_MAX_ORDER
+ */
+
+ while (j < 0x010)
+ {
+ j <<= 1;
+ i++;
+ }
+
+ /*
+ * 5 is the number of bits needed to represent 0x010
+ * TNS_MAX_ORDER = 20, power of 2 that include 20 is 5
+ */
+ shift_down_amount = 4 - i;
+
+ shift_up = UPPER16 - Q_lpc;
+
+ /*
+ * shift_down_amount == power of 2 that is bigger than the order - 1
+ */
+
+ shift_down_amount += shift_up;
+
+ if (direction == -1)
+ {
+ p_spec += spec_length - 1;
+
+ for (i = order; i != 0; i--)
+ {
+
+ y0 = *p_spec >> shift_down_amount;
+
+ p_lpc = lpc;
+
+ /* 32 by 32 bit multiplication */
+ for (j = order; j > i; j--)
+ {
+ temp = *p_state++;
+ y0 -= fxp_mul32_Q31(temp, *(p_lpc++)) << shift_up;
+ }
+
+ /*
+ * Record the output in-place
+ */
+ p_state = p_spec;
+ *(p_spec--) = y0;
+
+ }
+
+ if (spec_length > order)
+ {
+ for (i = (spec_length - order); i != 0; i--)
+ {
+ y0 = *p_spec >> shift_down_amount;
+
+ p_lpc = &(lpc[0]);
+
+ /* 32 by 32 bit multiplication */
+ for (j = order; j != 0; j--)
+ {
+ temp = *p_state++;
+ y0 -= fxp_mul32_Q31(temp, *(p_lpc++)) << shift_up;
+ }
+
+ /*
+ * Record the output in-place
+ */
+ p_state = p_spec;
+ *(p_spec--) = y0;
+
+ } /* END for (i = (spec_length - order); i>0; i--) */
+ }
+
+ }
+ else
+ {
+ for (i = order; i != 0; i--)
+ {
+
+ p_lpc = lpc;
+
+ y0 = 0;
+
+ /* 32 by 32 bit multiplication */
+ for (j = order; j > i; j--)
+ {
+ y0 -= fxp_mul32_Q31(*p_state--, *(p_lpc++));
+ }
+
+ p_state = p_spec;
+ /*
+ * Record the output in-place
+ */
+ *(p_spec) = (*p_spec >> shift_down_amount) + (y0 << shift_up);
+ p_spec++;
+ }
+
+ if (spec_length > order)
+ {
+ for (i = (spec_length - order); i != 0; i--)
+ {
+ p_lpc = lpc;
+
+ y0 = 0;
+
+ /* 32 by 32 bit multiplication */
+ for (j = order; j != 0; j--)
+ {
+ y0 -= fxp_mul32_Q31(*p_state--, *(p_lpc++));
+ }
+
+ p_state = p_spec;
+ /*
+ * Record the output in-place
+ */
+ *(p_spec) = (*p_spec >> shift_down_amount) + (y0 << shift_up);
+ p_spec++;
+
+ } /* END for (i = (spec_length - order); i>0; i--) */
+ }
+ }
+
+ return(shift_down_amount);
+
+
+} /* tns_ar_filter */
diff --git a/media/libstagefright/codecs/aacdec/tns_ar_filter.h b/media/libstagefright/codecs/aacdec/tns_ar_filter.h
new file mode 100644
index 0000000..2538b4d
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/tns_ar_filter.h
@@ -0,0 +1,104 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: tns_ar_filter.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Per request of JT, the lpc coefficients q-format will now
+ be transmitted to the function.
+
+ Description: Removed the parameter "scratch_Int32_buffer" as this space
+ in memory is no longer needed by this function.
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This function includes the function declaration for tns_ar_filter()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef TNS_AR_FILTER_H
+#define TNS_AR_FILTER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "e_tns_const.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ Int tns_ar_filter(
+ Int32 spec[],
+ const Int spec_length,
+ const Int inc,
+ const Int32 lpc[],
+ const Int lpc_qformat,
+ const Int order);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/aacdec/tns_decode_coef.cpp b/media/libstagefright/codecs/aacdec/tns_decode_coef.cpp
new file mode 100644
index 0000000..366cce5
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/tns_decode_coef.cpp
@@ -0,0 +1,500 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: tns_decode_coef.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Implemented in 16-bit Fixed Point
+
+ Description: Implemented in 24-bit Fixed Point
+
+ Description: Modified to return the calculated LPC coefficients "in place"
+ This saves memory, cycles, etc. because it saves a large temporary
+ array being declared on the stack in another function (tns_setup_filter)
+
+ Description: Modified to return the q-format of the lpc coefficients.
+
+ Description: Modified for more reliable overflow protection. tns_decode_coef
+ no longer relies on "reasonable" outputs. This code should handle all
+ possible inputs.
+
+ Description: Modified per review comments.
+
+ Description: Added check condition to avoid numbers with a Q bigger than
+ 15 from being passed, otherwise in a 16-bit number the sign is lost.
+
+ Description: Modified to utilize scratch memory techniques, thereby
+ eliminating two arrays of size TNS_MAX_ORDER, which were previously declared
+ on the stack.
+
+ Description: Updated the SW template to include the full pathname to the
+ source file and a slightly modified copyright header.
+
+ Description:
+ (1) Changed the order of the unsigned * signed multiply so the
+ casting to Int32 is performed on the unsigned operand.
+
+ (2) Removed some unnecessary casting.
+ (3) Fixed a problem where a 16-bit value was casted to 32-bits AFTER
+ a shift. It should have been cast to 32-bits BEFORE the shifting.
+
+
+ Description: modified precision of coefficients
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ The inputs and their range are defined in ISO/IEC 14496-3:1999(E)
+ Part 3 MPEG-4 Audio
+ Subpart 4
+
+ Inputs: order = RANGE = 1-20
+ const Int
+
+ coef_res = RANGE = 0-1
+ const Int
+
+ lpc_coef = RANGE = -8 to 7 if coef_res = 1 compression OFF
+ -4 to 3 if coef_res = 1 compression ON
+ -4 to 3 if coef_res = 0 compression OFF
+ -2 to 1 if coef_res = 0 compression ON
+
+ [Int *, length TNS_MAX_ORDER]
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ q_lpc = q_format for the calculated LPC coefs.
+ Int
+
+ Pointers and Buffers Modified:
+ lpc_coef = used to return the calculated LPC coefs in-place.
+ Int *
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+This function calculates the LPC coefs from the encoded coefs...
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+This function should match the functionality of the ISO source code within
+a reasonable tolerance for fixed point errors.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.6.8 (Temporal Noise Shaping)
+ (2) Markel & Gray Page 95
+ As referenced in the ISO source code
+
+ (3) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+ PSEUDOCODE: (ISO Reference Code)
+
+ int i, m;
+ Real iqfac, iqfac_m;
+ Real lpc_fp[TNS_MAX_ORDER+1];
+ Real sin_result_fp[TNS_MAX_ORDER+1], b[TNS_MAX_ORDER+1];
+
+ Inverse quantization
+ iqfac = (Real)(((1 << (coef_res-1)) - 0.5) / (PI/2.0));
+ iqfac_m = (Real)(((1 << (coef_res-1)) + 0.5) / (PI/2.0));
+
+ for (i=0; i<order; i++)
+ {
+ sin_result[i+1] =
+ (Real)sin( coef[i] / ((coef[i] >= 0) ? iqfac : iqfac_m) );
+ }
+
+ lpc[0] = 1;
+ for (m=1; m<=order; m++)
+ {
+
+ b[0] = lpc[0];
+ for (i=1; i<m; i++)
+ {
+ b[i] = sin_result[m] * lpc[m-i];
+ b[i] += lpc[i];
+ }
+
+ b[m] = sin_result[m];
+
+
+ for (i=0; i<=m; i++)
+ {
+ lpc[i] = b[i];
+ }
+
+ }
+
+ return;
+
+}
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_tns_const.h"
+#include "tns_decode_coef.h"
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define MASK_LOW16 0xffff
+#define UPPER16 16
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+/*
+ * Derivation of tns_tables and q_tns_tables
+ *
+ * As defined in the ISO source code
+ * (with the modification that our coef_res has a range[0,1]
+ * The ISO code has a range of [3,4])
+ *
+ * pi / 2 pi / 2
+ * iqfac = -------------------- iqfac_m = --------------------
+ * (coef_res + 2) - 1/ (coef_res + 2) + 1/
+ * 2 /2 2 /2
+ *
+ *
+ * ... Move 1/2 into denominator
+ *
+ * pi pi
+ * iqfac = -------------------- iqfac_m = --------------------
+ * (coef_res + 3) (coef_res + 3)
+ * 2 - 1 2 + 1
+ *
+ *
+ * if a coef is negative, it is multiplied by iqfac_m
+ * if positive, " " " iqfac
+ *
+ * The range of coefs is limited to -4:3 if coef_res = 0
+ * -8:7 if coef_res = 1
+ *
+ *
+ *
+ */
+
+
+const Int32 tns_table[2][16] =
+{
+ {
+ -2114858546, -1859775393, -1380375881, -734482665,
+ 0, 931758235, 1678970324, 2093641749
+ },
+ {
+ -2138322861, -2065504841, -1922348530, -1713728946,
+ -1446750378, -1130504462, -775760571, -394599085,
+ 0, 446486956, 873460290, 1262259218,
+ 1595891361, 1859775393, 2042378317, 2135719508
+ }
+};
+
+
+const Int neg_offset[2] = {4, 8};
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ FUNCTION NAME: tns_decode_coef
+ Decoder transmitted coefficients for one TNS filter
+----------------------------------------------------------------------------*/
+
+Int tns_decode_coef(
+ const Int order,
+ const Int coef_res,
+ Int32 lpc_coef[TNS_MAX_ORDER],
+ Int32 scratchTnsDecCoefMem[2*TNS_MAX_ORDER])
+{
+
+ /* Simple loop counters */
+ Int i;
+ Int m;
+
+ /* Arrays for calculation of the LPC */
+ Int32 *pB = &(scratchTnsDecCoefMem[TNS_MAX_ORDER]);
+
+ Int32 *pA = scratchTnsDecCoefMem;
+
+ Int32 *temp_ptr = NULL;
+
+ /* Pointer for reading/storing the lpc_coef in place */
+ Int32 *pLPC;
+ Int q_lpc = Q_LPC;
+
+ /* TNS table related variables */
+ const Int32 *pTnsTable;
+ Int coef_offset;
+ Int32 table_index;
+ Int shift_amount;
+ Int32 sin_result;
+
+ Int32 tempInt32;
+
+ Int32 max;
+ Int32 mask;
+
+ Int32 mult_high;
+
+ /* Conversion to LPC coefficients Ref. (2) */
+ coef_offset = neg_offset[coef_res];
+ pTnsTable = tns_table[coef_res];
+
+ m = 0;
+ pLPC = lpc_coef;
+
+
+ /*
+ * Conversion to LPC coefficients
+ */
+
+ do
+ {
+ table_index = coef_offset + *(pLPC++);
+
+ /* Equiv. to sin_result = tns_table[coef_res][table_index]; */
+ sin_result = *(pTnsTable + table_index);
+
+ /* sin_result has a range of -0.999 to +0.999 in Q-31 */
+
+ /*
+ * It is important that this for loop is not entered on the first
+ * iteration of the do-while( m < order ) loop.
+ */
+ for (i = m; i > 0; i--)
+ {
+
+ /*
+ * temp_ptr used to optimize index into pA
+ * mult = (Int32)( pA[m-i] * sin_result);
+ */
+
+ mult_high = fxp_mul32_Q31(*(temp_ptr--), sin_result);
+
+ /*
+ * pB[i] = pA[i] + sin_result * pA[m-i]
+ *
+ * (mult_high <<1) eliminates extra sign bit
+ */
+
+ *(pB++) = *(pA++) + (mult_high << 1);
+
+ } /* END for (i=m; i > 0; i--) */
+
+
+ /* Shift to place pB[m] in q_lpc format */
+
+ *pB = sin_result >> 12;
+
+ /*
+ * Swapping the pointers here has the same effect
+ * as specifically copying the data from b to a
+ */
+
+ temp_ptr = pA;
+ pA = pB;
+ pB = temp_ptr;
+
+ /*
+ * At this point, pA = pA[m]
+ * and pB = pB[m]
+ */
+ temp_ptr = pA;
+
+ tempInt32 = *(pA);
+
+ mask = tempInt32 >> 31;
+ tempInt32 ^= mask;
+
+ max = tempInt32;
+
+ /*
+ * It is important that this for loop is not entered on the first
+ * iteration of the do-while( m < order ) loop.
+ */
+ for (i = m; i > 0; i--)
+ {
+ tempInt32 = *(--pA);
+
+ mask = tempInt32 >> 31;
+ tempInt32 ^= mask;
+
+ max |= tempInt32;
+ }
+
+ pB -= m;
+
+ /*
+ * Here, pA = &(pA[0])
+ * and pB = &(pB[0])
+ */
+
+ if (max >= 0x40000000L)
+ {
+ max >>= 1;
+
+ for (i = m; i > 0; i--)
+ {
+ *(pA++) >>= 1;
+ *(pB++) >>= 1;
+ }
+
+ /* Shift the most recent entry down also */
+ *(pA) >>= 1;
+
+ q_lpc--;
+
+ pA -= m;
+ pB -= m;
+ }
+
+ m++;
+
+ }
+ while (m < order);
+
+
+ /*
+ * The following code compacts
+ * 32-bit LPC coefficients into 16-bit numbers,
+ * shifting by the minimum amount necessary.
+ */
+
+ shift_amount = 0;
+
+ while (max > 32767)
+ {
+ max >>= 1;
+ shift_amount++;
+ }
+
+ /*
+ * This while loop is for protective purposes only.
+ * I have not found data that causes it to be entered.
+ *
+ */
+ if (max != 0)
+ {
+ while (max < 16384)
+ {
+ max <<= 1;
+ shift_amount--;
+ }
+ }
+
+
+ pLPC = lpc_coef;
+
+ if (shift_amount >= 0)
+ {
+
+ for (m = order; m > 0; m--)
+ {
+ *(pLPC++) = *(pA++) << (16 - shift_amount);
+ }
+ }
+
+
+ q_lpc -= shift_amount;
+
+ /*
+ * make sure that the numbers have some meaning, q_lpc can not be
+ * bigger than 15 (15 bits + sign)
+ */
+
+ if (q_lpc > 15)
+ {
+ shift_amount = q_lpc - 15;
+ pLPC = lpc_coef;
+
+ for (m = order; m > 0; m--)
+ {
+ *(pLPC++) >>= shift_amount;
+ }
+
+ q_lpc -= shift_amount;
+ }
+
+ return (q_lpc);
+
+} /* tns_decode_coef */
diff --git a/media/libstagefright/codecs/aacdec/tns_decode_coef.h b/media/libstagefright/codecs/aacdec/tns_decode_coef.h
new file mode 100644
index 0000000..a6bac6c
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/tns_decode_coef.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: tns_decode_coef.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified to return the LPC coefficients in-place, so the
+ interface to tns_decode_coef is changed.
+
+ Description: Modified to return the q-format of the LPC coefficients.
+
+ Description: Modified so that only the function is declared here. extern
+ references to constant tables removed. Also, new copyright header included.
+
+ Description: Modified to include extra parameter, so tns_decode_coef can use
+ scratch memory techniques.
+
+ Description:
+ (1) Modified to include the lines...
+
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+ (2) Updated the copyright header.
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This function includes the function declaration for tns_decode_coef()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef TNS_DECODE_COEF_H
+#define TNS_DECODE_COEF_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Int tns_decode_coef(
+ const Int order,
+ const Int coef_res,
+ Int32 lpc_coef[],
+ Int32 scratchTnsDecCoefMem[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TNS_DECODE_COEF */
diff --git a/media/libstagefright/codecs/aacdec/tns_inv_filter.cpp b/media/libstagefright/codecs/aacdec/tns_inv_filter.cpp
new file mode 100644
index 0000000..631f887
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/tns_inv_filter.cpp
@@ -0,0 +1,421 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: tns_inv_filter.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changes made per review comments.
+
+ Description: As requested by JT, the q-format for the LPC coefficients is
+ now passed via the parameter lpc_qformat.
+
+ Description: For speed, the calculation of the shift amount was pulled
+ outside of the loop.
+
+ Description:
+ Modified casting to ensure proper operations for different platforms
+
+ Description:
+ Simplified MAC operations for filter by eliminating extra variables
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ coef = spectral input to be shaped by the filter.
+ Fixed point format
+ [Int32[], length = num_coef]
+
+ num_coef = length of spec array.
+ [const Int]
+
+ direction = direction for application of tns filter.
+ +1 applies forward filter
+ (first input to filter is coef[0])
+ -1 applies reversed filter
+ (first input to filter is coef[num_coef-1])
+ [const Int]
+
+ lpc = array of lpc coefficients.
+ Fixed point format Q-11
+ [const Int[], length = TNS_MAX_ORDER]
+
+ lpc_qformat = The q-format of the lpc coefficients.
+ [const Int]
+
+ order = order of the TNS filter (Range of 1 : TNS_MAX_ORDER)
+ [const Int]
+
+ scratch_memory = scratch_memory needed for filter operation
+ [Int[], length = TNS_MAX_ORDER]
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ coef = contains spectral data after application of TNS filter
+ q-format is not modified.
+ Int32 array
+ length = num_coef
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ A block of spectral data (Int32 coef[]) of length (const Int num_coef)
+ is processed by a simple all-zero filter defined by
+ LPC coefficients passed via (const Int lpc[])
+
+ TNS filter equation
+ y(n) = x(n) + lpc(2)*x(n-1) + ... + lpc(order+1)*x(n-order)
+
+ The filter calculation is performed in place, i.e. the output is passed
+ back to the calling function via (Int32 coef[])
+
+ In order to avoid overflow, the filter input (Int32 coef[]) must utilize
+ only the lower 16-bits. The upper 16-bits must be available.
+
+ The filter's order is defined by the variable (const Int order)
+
+ The direction of the filter's application is defined by
+ (const Int direction)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ [Int32 coef] must store no more than 16 bits of data.
+
+ This is required to utilize methods that do not change the q-format of
+ the input data [Int32 coef], and to make use of a fast
+ 16 x 16 bit multiply.
+
+ This function should not be called for order <= 0.
+
+ This function must not be called with lpc_qformat < 5
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.6.6.4.1 (LTP with TNS)
+ Subpart 4.6.8 (Temporal Noise Shaping)
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ IF (direction == -1)
+ THEN
+ pCoef = pCoef + (num_coef - 1);
+ END IF
+
+ FOR (i = order; i > 0; i--)
+
+ *(pFilterInput) = 0;
+ pFilterInput = pFilterInput + 1;
+
+ END FOR
+
+ wrap_point = 0;
+
+ shift_amt = (lpc_qformat - 5);
+
+ FOR (i = num_coef; i > 0; i--)
+
+ pLPC = lpc;
+
+ mult = 0;
+
+ FOR (j = wrap_point; j>0; j--)
+
+ tempInt32 = (Int32)(*(pLPC) * *(pFilterInput));
+ tempInt32 = tempInt32 >> 5;
+
+ mult = mult + tempInt32;
+
+ pFilterInput = pFilterInput + 1;
+ pLPC = pLPC + 1;
+
+ ENDFOR
+
+ pFilterInput = scratch_memory;
+
+ FOR (j = (order - wrap_point); j>0; j--)
+
+ tempInt32 = (Int32)(*(pLPC) * *(pFilterInput));
+ tempInt32 = tempInt32 >> 5;
+
+ mult = mult + tempInt32;
+
+ pFilterInput = pFilterInput + 1;
+ pLPC = pLPC + 1;
+
+ ENDFOR
+
+ pFilterInput = pFilterInput - 1;
+ *(pFilterInput) = (Int)(*pCoef);
+
+ mult = mult >> shift_amt;
+
+ *(pCoef) = *(pCoef) + mult;
+
+ pCoef = pCoef + direction;
+
+ wrap_point = wrap_point + 1;
+
+ IF (wrap_point == order)
+ THEN
+ wrap_point = 0;
+ END IF
+
+ END FOR
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+
+ When the code is written for a specific target processor
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "tns_inv_filter.h"
+#include "fxp_mul32.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void tns_inv_filter(
+ Int32 coef[],
+ const Int num_coef,
+ const Int direction,
+ const Int32 lpc[],
+ const Int lpc_qformat,
+ const Int order,
+ Int32 scratch_memory[])
+{
+
+ Int i;
+ Int j;
+ Int shift_amt;
+ Int wrap_point;
+
+ Int32 mult;
+
+ /*
+ * Circular buffer to hold the filter's input
+ *
+ * (x[n-1],x[n-2],x[n-3],etc.)
+ *
+ * This scratch space is necessary, because
+ * the filter's output is returned in-place.
+ *
+ * pFilterInput and pLPC should take advantage
+ * of any special circular buffer instructions
+ * if this code is hand-optimized in assembly.
+ *
+ */
+ Int32 *pFilterInput = scratch_memory;
+
+ const Int32 *pLPC;
+
+ /*
+ * Pointer to the I/O memory space
+ */
+ Int32 *pCoef = coef;
+
+ if (direction == -1)
+ {
+ pCoef += (num_coef - 1);
+ }
+
+ /* Make sure the scratch memory is "clean" */
+ for (i = order; i != 0; i--)
+ {
+ *(pFilterInput++) = 0;
+ }
+
+ wrap_point = 0;
+
+ shift_amt = (lpc_qformat - 5);
+
+ for (i = num_coef; i > 0; i--)
+ {
+ /*
+ * Copy spectral input into special
+ * filter input buffer.
+ */
+ pLPC = lpc;
+
+ mult = 0;
+
+ /*
+ * wrap_point = 0 when this code is
+ * entered for the first iteration of
+ * for(i=num_coef; i>0; i--)
+ *
+ * So, this first for-loop will be
+ * skipped when i == num_coef.
+ */
+
+ for (j = wrap_point; j > 0; j--)
+ {
+ mult += fxp_mul32_Q31(*(pLPC++), *(pFilterInput++)) >> 5;
+
+ } /* for (j = wrap_point; j>0; j--) */
+
+ /*
+ * pFilterInput has reached &scratch_memory[order-1]
+ * Reset pointer to beginning of filter's state memory
+ */
+ pFilterInput = scratch_memory;
+
+ for (j = (order - wrap_point); j > 0; j--)
+ {
+ mult += fxp_mul32_Q31(*(pLPC++), *(pFilterInput++)) >> 5;
+
+ } /* for (j = wrap_point; j>0; j--) */
+
+
+ /*
+ * Fill the filter's state buffer
+ * avoid obvious casting
+ */
+ *(--pFilterInput) = (*pCoef);
+
+
+ /* Scale the data down so the output q-format is not adjusted.
+ *
+ * Here is an equation, which shows how the spectral coefficients
+ * and lpc coefficients are multiplied and the spectral
+ * coefficient's q-format does not change.
+ *
+ * Q-(coef) * Q-(lpc_qformat) >> 5 = Q-(coef + lpc_q_format - 5)
+ *
+ * Q-(coef + lpc_q_format - 5) >> (lpc_qformat - 5) = Q-(coef)
+ */
+
+ /* Store output in place */
+ *(pCoef) += (mult >> shift_amt);
+
+ /* Adjust pointers and placeholders */
+ pCoef += direction;
+
+ wrap_point++;
+
+ if (wrap_point == order)
+ {
+ wrap_point = 0;
+ }
+
+ } /* for (i = num_coef; i > 0; i--) */
+
+} /* tns_inv_filter */
diff --git a/media/libstagefright/codecs/aacdec/tns_inv_filter.h b/media/libstagefright/codecs/aacdec/tns_inv_filter.h
new file mode 100644
index 0000000..1b57fc1
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/tns_inv_filter.h
@@ -0,0 +1,99 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: tns_inv_filter.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Per request of JT, the lpc coefficients q-format will now
+ be transmitted to the function.
+
+ Description: The scratch memory was mistakenly declared here as type "Int32"
+ It should have been "Int"
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file contains the function declaration for
+ tns_inv_filter.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef TNS_INV_FILTER_H
+#define TNS_INV_FILTER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+void tns_inv_filter(
+ Int32 coef[],
+ const Int num_coef,
+ const Int inc,
+ const Int32 lpc[],
+ const Int lpc_qformat,
+ const Int order,
+ Int32 scratch_memory[]);
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/trans4m_freq_2_time_fxp.cpp b/media/libstagefright/codecs/aacdec/trans4m_freq_2_time_fxp.cpp
new file mode 100644
index 0000000..6ccc023
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/trans4m_freq_2_time_fxp.cpp
@@ -0,0 +1,2604 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: trans4m_freq_2_time_fxp.c
+ Function: trans4m_freq_2_time_fxp
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ changed to decrement loop
+ change wnd_shape from structure to passing parameters
+ modified window tables from UInt to UInt16 to assure proper operation
+ without dubious typecast
+ changed logic to hit most common states first.
+ modified Time_data from Int to Int32 to hold
+ possible overflow before saturation process.
+
+ Description:
+ Increase processing on some loop by using more pointers
+ changed interface to avoid passing a pointer for wnd_shape_prev_bk, this
+ element is not change in this function because of this function use
+ in the LTP module
+
+ Description:
+ Added rounding to multiplication
+
+ Description:
+ Update input description and eliminate unneeded comments
+
+ Description:
+ LONG_START_WINDOW was using SHORT_WINDOW instead of
+ HALF_SHORT_WINDOW, causing a for loop to exceed its count
+
+ Description:
+ Modified structure of code so exp is not tested before it
+ is initialized. Also, new structure avoids double-testing
+ of exp_freq = ALL_ZEROS_BUFFER.
+
+ Description:
+ The result of a shift is undefined if the right operand is greater than
+ or equal to the number of bits in the left expression's type
+ To avoid undefined shift by 32, a check of the shift has been
+ added, so the function proceeds only when the exponent is less
+ than 32. By design the shift up is related to the global gain,
+ and controlled by the encoder, so saturation is not allowed.
+ In both short and long window, processing is skip if an all zero
+ input buffer or excessive down shift is detected.
+
+ Description:
+ Changes according to code review comments. Also, modified if-else
+ structure so the imdct_fxp is not called with an all zero input buffer
+
+ Description:
+ Replaced function buffer_normalization by buffer_adaptation, to ease
+ use of 16 bits. Function buffer_normalization becomes obsolete.
+
+ Description:
+ Modified call to imdct_fxp to reflect extended precision use. Added
+ routine buffer_adaptation to extract 16 MSB and keep highest.
+ precision. Modify casting to ensure proper operations for different
+ platforms
+
+ Description:
+ Eliminate double access to memory by loading data directly to the
+ time array. Also reduced cycle count and added precision by combining
+ downshifting in only one operation. Added adaptive rounding factor.
+ Change exponent threshold when operations are waived. It is use to be 32
+ but by combining downshifting, this new threshold is now 16. This may
+ avoid unneeded calculations for extremely small numbers.
+
+ Description:
+ Per review comments:
+ - Added comments to clarify buffer_adaptation function
+ - Deleted reference to include file "buffer_normalization.h"
+ - Modified IF-ELSE so long_windows case is considered first
+ - Eliminated extra IF when computing the rounding, so when exp ==0
+ less cycles are used shifting than in an extra if-else
+ - Corrected negative shift when computing rounding factor
+ - Added condition when exp > 16 (for long windows)
+
+ Description:
+ Modified IF-ELSE structure so now ALL_ZEROS_BUFFER condition is share
+ with exp > 16 condition. This avoid code duplication for both cases.
+
+ Description:
+ - Modified function interface to add output_buffer
+ - Eliminated the 32 bit version of the current output, calculations
+ are placed directly in output_buffer. In this way the buffer
+ Time_data needs only to be 1024 Int32, instead of 2048 (per channel).
+ Also, added the limit macro inside the function (this reduces access
+ to memory).
+ - Updated Pseudo - Code
+
+ Description:
+ Per review comments:
+ Corrected line sizes and mispelling, added comments and swap
+ order or switch statement for ONLY_LONG_SEQUENCE.
+
+ Description:
+ Eliminated adaptive rounding due to potential saturation.
+
+ Description:
+ Eliminated use of buffer adaptation by shifting this functionality inside
+ the imdct_fxp() routine. Also modified the call to imdct_fxp to accomodate
+ new function interface.
+ Modified macro limit() to save cycles when testing the most common case:
+ no saturation.
+
+ Description:
+ Changed new function interface for imdct_fxp().
+
+ Description:
+ Replaced for-loop with memset and memcopy.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ Frequency_data = vector with spectral information, size 2048
+ type Int32
+
+ Time_data = buffer with data from previous Frequency to Time
+ conversion, used for overlap and add, size 1024
+ type Int32
+
+ Output_buffer = place holder for current output, size 1024
+ type Int16
+
+ wnd_seq = window sequence
+ type WINDOW_SEQUENCE
+
+ wnd_shape_prev_bk = previous window shape type
+ type Int
+
+ wnd_shape_this_bk = current window shape type
+ type Int
+
+ Q_format = Q format for the input frequency data
+ type Int
+
+ freq_2_time_buffer[] = scratch memory for computing FFT
+ type Int32
+
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ Output_buffer
+ Time_data
+ Frequency_data
+ pWnd_shape_prev_bk
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+The time/frequency representation of the signal is mapped onto the time
+domain by feeding it into the filterbank module. This module consists of
+an inverse modified discrete cosine transform (IMDCT), and a window and an
+overlap-add function. In order to adapt the time/frequency resolution of the
+filterbank to the characteristics of the input signal, a block switching tool
+is also adopted. N represents the window length, where N is a function of the
+window_sequence. For each channel, the N/2 time-frequency values are
+transformed into the N time domain values via the IMDCT. After applying the
+window function, for each channel, the first half of the sequence is added to
+the second half of the previous block windowed sequence to reconstruct the
+output samples for each channel outi,n.
+
+The adaptation of the time-frequency resolution of the filterbank to the
+characteristics of the input signal is done by shifting between transforms
+whose input lengths are either 2048 or 256 samples. By enabling the block
+switching tool, the following transitions are meaningful:
+
+from ONLY_LONG_SEQUENCE to { LONG_START_SEQUENCE
+ ONLY_LONG_SEQUENCE
+
+from LONG_START_SEQUENCE to { LONG_STOP_SEQUENCE
+ EIGHT_SHORT_SEQUENCE
+
+from LONG_STOP_SEQUENCE to { LONG_START_SEQUENCE
+ ONLY_LONG_SEQUENCE
+
+from EIGHT_SHORT_SEQUENCE to { LONG_STOP_SEQUENCE
+ EIGHT_SHORT_SEQUENCE
+
+Window shape decisions are made by the encoder on a frame-by-frame-basis.
+The window selected is applicable to the second half of the window function
+only, since the first half is constrained to use the appropriate window
+shape from the preceding frame.
+The 2048 time-domain values x'(i)(n), (i window, n sample) to be windowed are
+the last 1024 values of the previous window_sequence concatenated with 1024
+values of the current block. The formula below shows this fact:
+
+ | x(i-1)(n+1024) for 0 < n < 1024
+ x'(i)(n) {
+ | x(i)(n) for 1024 < n < 2048
+
+
+Buffer Time_data data from previous Frequency to Time conversion, used
+for overlap and add
+
+Once the window shape is selected, the window_shape syntax element is
+initialized. Together with the chosen window_sequence all information needed
+for windowing exist.
+With the window halves described below all window_sequences can be assembled.
+For window_shape == 1, the window coefficients are given by the Kaiser -
+Bessel derived (KBD) window.
+Otherwise, for window_shape == 0, a sine window is employed.
+
+The window length N can be 2048 or 256 for the KBD and the sine window.
+All four window_sequences explained below have a total length of 2048
+samples.
+For all kinds of window_sequences the window_shape of the left half of
+the first transform window is determined by the window shape of the previous
+block.
+
+In the case of EIGHT_SHORT_SEQUENCE the processing is done in-place and
+in descendent order to avoid using extra memory.
+The ordering is as follows:
+
+ Pn: Previous data for window n
+ Cn: Current data for window n
+
+
+ 128 freq.
+ samples
+ FREQ ++++++
+IN ===========================
+ \
+ \
+ -> 256 time
+ samples
+
+ P8 C8
+ 8 #######++++++
+ P7 C7
+ 7 #######++++++
+ : :
+ : :
+ P2 C2
+ 2 #######++++++
+ P1 C1
+ 1 #######++++++
+ TIME
+OUT ==============================================================
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This module shall implement a scheme to switch between window types
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO 14496-3:1999, pag 111
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+ IF ( wnd_seq == EIGHT_SHORT_SEQUENCE)
+ THEN
+
+ FOR ( i=0; i<LONG_WINDOW; i++)
+ Time_data[LONG_WINDOW + i] = 0;
+ ENDFOR
+
+ FOR ( wnd=NUM_SHORT_WINDOWS-1; wnd>=0; wnd--)
+
+ pFreqInfo = &Frequency_data[ wnd*SHORT_WINDOW];
+
+ CALL IMDCT( pFreqInfo, SHORT_BLOCK1);
+ MODIFYING(pFreqInfo)
+
+
+ IF (wnd == 0)
+ THEN
+ pShort_Window_1 = &Short_Window[wnd_shape_prev_bk][0];
+ ELSE
+ pShort_Window_1 = &Short_Window[wnd_shape_this_bk][0];
+ ENDIF
+
+ pShort_Window_2 =
+ &Short_Window[wnd_shape->this_bk][SHORT_WINDOW_m_1];
+
+ FOR( i=0, j=SHORT_WINDOW; i<SHORT_WINDOW; i++, j--)
+ pFreqInfo[ i] *= pShort_Window_1[i];
+ pFreqInfo[SHORT_WINDOW+i] *= pShort_Window_2[j];
+ ENDFOR
+
+
+ FOR( i=0; i<SHORT_BLOCK1; i++)
+ Time_data[W_L_STOP_1 + SHORT_WINDOW*wnd + i] += pFreqInfo[i];
+ ENDFOR
+
+ ENDFOR
+
+ FOR ( i=0; i<LONG_WINDOW; i++)
+ temp = Time_data[i];
+ Output_buffer[i] = Time_data[i];
+ Time_data[i] = temp;
+ ENDFOR
+ ELSE
+
+ CALL IMDCT( Frequency_data, LONG_BLOCK1)
+ MODIFYING(Frequency_data)
+
+ SWITCH ( wnd_seq)
+
+ CASE ( ONLY_LONG_SEQUENCE)
+
+ pLong_Window_1 = &Long_Window[wnd_shape_prev_bk][0];
+ pLong_Window_2 =
+ &Long_Window[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+ FOR (i=0; i<LONG_WINDOW; i++)
+ Frequency_data[ i] *= *pLong_Window_1++;
+ Frequency_data[LONG_WINDOW+i] *= *pLong_Window_2--;
+ ENDFOR
+
+ BREAK
+
+ CASE ( LONG_START_SEQUENCE)
+
+ pLong_Window_1 = &Long_Window[wnd_shape_prev_bk][0];
+
+ FOR ( i=0; i<LONG_WINDOW; i++)
+ Frequency_data[ i] *= *pLong_Window_1++;
+ ENDFOR
+
+ pShort_Window_1 =
+ &Short_Window[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+ FOR ( i=0; i<SHORT_WINDOW; i++)
+ Frequency_data[W_L_START_1 + i] *= *pShort_Window_1--;
+ ENDFOR
+
+ FOR ( i=W_L_START_2; i<LONG_BLOCK1; i++)
+ Frequency_data[W_L_START_2 + i] = 0;
+ ENDFOR
+
+ BREAK
+
+
+ CASE ( LONG_STOP_SEQUENCE )
+
+ FOR ( i=0; i<W_L_STOP_1; i++)
+ Frequency_data[ i] = 0;
+ ENDFOR
+
+ pShort_Window_1 = &Short_Window[wnd_shape_prev_bk][0];
+
+ FOR ( i=0; i<SHORT_WINDOW; i++)
+ Frequency_data[W_L_STOP_1+ i] *= *pShort_Window_1++;
+ ENDFOR
+
+ pLong_Window_1 =
+ &Long_Window[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+ FOR ( i=0; i<LONG_WINDOW; i++)
+ Frequency_data[LONG_WINDOW + i] *= *pLong_Window_1--;
+ ENDFOR
+
+ BREAK
+
+ }
+
+
+ FOR ( i=0; i<LONG_WINDOW; i++)
+ Output_buffer[i] = Frequency_data[i] + Time_data[i];
+ Time_data[i] = Frequency_data[LONG_WINDOW+i];
+ ENDFOR
+
+ }
+
+ ENDIF
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+#include "aac_mem_funcs.h"
+#include "window_block_fxp.h"
+#include "imdct_fxp.h"
+
+#include "fxp_mul32.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; limit(x) saturates any number that exceeds a 16-bit representation into a
+; 16 bit number.
+----------------------------------------------------------------------------*/
+
+#define ROUNDING_SCALED (ROUNDING<<(16 - SCALING))
+
+
+#if defined(PV_ARM_V5)
+
+
+__inline Int16 sat(Int32 y)
+{
+ Int32 x;
+ Int32 z;
+ __asm
+ {
+ mov x, ROUNDING_SCALED
+ mov y, y, lsl #(15-SCALING)
+ qdadd z, x, y
+ mov y, z, lsr #16
+ }
+ return((Int16)y);
+}
+
+#define limiter( y, x) y = sat(x);
+
+
+
+#elif defined(PV_ARM_GCC_V5)
+
+
+__inline Int16 sat(Int32 y)
+{
+ register Int32 x;
+ register Int32 ra = (Int32)y;
+ register Int32 z = ROUNDING_SCALED;
+
+
+ asm volatile(
+ "mov %0, %1, lsl #5\n\t" // (15-SCALING) assembler does not take symbols
+ "qdadd %0, %2, %0\n\t"
+ "mov %0, %0, lsr #16"
+ : "=&r*i"(x)
+ : "r"(ra),
+ "r"(z));
+
+ return ((Int16)x);
+}
+
+#define limiter( y, x) y = sat(x);
+
+
+#elif defined(PV_ARM_MSC_EVC_V5)
+
+
+#define limiter( y, x) z = x<< (15-SCALING); \
+ y = _DAddSatInt( ROUNDING_SCALED, z)>>16;
+
+
+#else
+
+#define limiter( y, x) z = ((x + ROUNDING )>>SCALING); \
+ if ((z>>15) != (z>>31)) \
+ { \
+ z = (z >> 31) ^ INT16_MAX; \
+ } \
+ y = (Int16)(z);
+
+#endif
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+#ifdef AAC_PLUS
+
+
+void trans4m_freq_2_time_fxp_1(
+ Int32 Frequency_data[],
+ Int32 Time_data[],
+ Int16 Output_buffer[],
+ WINDOW_SEQUENCE wnd_seq,
+ Int wnd_shape_prev_bk,
+ Int wnd_shape_this_bk,
+ Int Q_format,
+ Int32 abs_max_per_window[],
+ Int32 freq_2_time_buffer[])
+
+{
+ Int exp;
+ Int shift;
+
+ Int i;
+ Int wnd;
+#if !(defined( PV_ARM_GCC_V5)||(PV_ARM_V5))
+ Int32 z;
+#endif
+
+ Int16 *pFreqInfo;
+ Int32 temp;
+ Int32 test;
+
+ Int16 *pFreq_2_Time_data_1;
+ Int16 *pFreq_2_Time_data_2;
+
+ const Int16 *pLong_Window_1;
+ const Int16 *pLong_Window_2;
+ const Int16 *pShort_Window_1;
+ const Int16 *pShort_Window_2;
+
+ Int32 *pOverlap_and_Add_Buffer_1;
+ Int32 *pOverlap_and_Add_Buffer_2;
+
+ Int16 *pOutput_buffer;
+ Int16 *pOutput_buffer_2;
+
+ const Int16 * Long_Window_fxp[NUM_WINDOW_SHAPES];
+ const Int16 * Short_Window_fxp[NUM_WINDOW_SHAPES];
+
+ Long_Window_fxp[0] = Long_Window_sine_fxp;
+ Long_Window_fxp[1] = Long_Window_KBD_fxp;
+ Short_Window_fxp[0] = Short_Window_sine_fxp;
+ Short_Window_fxp[1] = Short_Window_KBD_fxp;
+
+
+ if (wnd_seq != EIGHT_SHORT_SEQUENCE)
+ {
+
+ pFreqInfo = (Int16 *)Frequency_data;
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ LONG_BLOCK1,
+ Q_format,
+ abs_max_per_window[0]);
+
+
+
+ /*
+ * The C Programming Language, Second Edition, Kernighan & Ritchie,
+ * page 206.
+ * "The result [of a shift] is undefined if the right operand is
+ * negative, or greater than or equal to the number of bits in the
+ * left expression's type"
+ * => avoid shift by 32 or 16
+ */
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = pFreqInfo;
+
+ switch (wnd_seq)
+ {
+
+ case ONLY_LONG_SEQUENCE:
+ default:
+
+ pOutput_buffer = Output_buffer;
+
+ pOverlap_and_Add_Buffer_1 = Time_data;
+
+ {
+ const Int16 *pLong_Window_2 = &Long_Window_fxp[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+ Int32 * pFreq2T = (Int32 *)pFreqInfo;
+ Int32 * win = (Int32 *) & Long_Window_fxp[wnd_shape_prev_bk][0];
+ Int shift = exp + 15 - SCALING;
+
+
+ Int32 * pFreq2T_2 = &pFreq2T[HALF_LONG_WINDOW];
+
+
+ for (i = HALF_LONG_WINDOW; i != 0; i--)
+ {
+ Int16 win1, win2;
+ Int32 temp2, test2;
+
+ Int32 winx;
+
+ temp2 = *(pFreq2T++);
+ winx = *(win++);
+
+ test = *(pOverlap_and_Add_Buffer_1++);
+ test2 = *(pOverlap_and_Add_Buffer_1--);
+ temp = fxp_mul_16_by_16bb(temp2, winx) >> shift;
+ temp2 = fxp_mul_16_by_16tt(temp2, winx) >> shift;
+ limiter(*(pOutput_buffer++), (temp + test));
+ limiter(*(pOutput_buffer++), (temp2 + test2));
+
+ temp2 = *(pFreq2T_2++);
+
+ win1 = *(pLong_Window_2--);
+ win2 = *(pLong_Window_2--);
+ temp = fxp_mul_16_by_16bb(temp2, win1) >> shift;
+ test2 = fxp_mul_16_by_16tb(temp2, win2) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp;
+ *(pOverlap_and_Add_Buffer_1++) = test2;
+
+ }
+ }
+
+ break;
+
+ case LONG_START_SEQUENCE:
+
+
+ pFreq_2_Time_data_2 =
+ &pFreq_2_Time_data_1[ HALF_LONG_WINDOW];
+
+ pLong_Window_1 = &Long_Window_fxp[wnd_shape_prev_bk][0];
+ pLong_Window_2 = &pLong_Window_1[ HALF_LONG_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[0];
+ pOverlap_and_Add_Buffer_2 = &Time_data[HALF_LONG_WINDOW];
+
+ pOutput_buffer = Output_buffer;
+ pOutput_buffer_2 = pOutput_buffer + HALF_LONG_WINDOW;
+
+
+ shift = exp + 15 - SCALING;
+
+ for (i = HALF_LONG_WINDOW; i != 0; i--)
+ {
+
+ Int16 win1, win2;
+ Int16 dat1, dat2;
+ Int32 test1, test2;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pLong_Window_1++);
+ test1 = *(pOverlap_and_Add_Buffer_1++);
+
+ dat2 = *(pFreq_2_Time_data_2++);
+ win2 = *(pLong_Window_2++);
+ test2 = *(pOverlap_and_Add_Buffer_2++);
+
+ limiter(*(pOutput_buffer++), (test1 + (fxp_mul_16_by_16(dat1, win1) >> shift)));
+
+ limiter(*(pOutput_buffer_2++), (test2 + (fxp_mul_16_by_16(dat2, win2) >> shift)));
+
+ }
+
+ /*
+ * data unchanged from LONG_WINDOW to W_L_START_1
+ * only scaled accordingly
+ */
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[0];
+ pFreq_2_Time_data_1 = &pFreqInfo[LONG_WINDOW];
+
+ exp -= SCALING;
+
+ if (exp >= 0)
+ {
+
+ for (i = (W_L_START_1 - LONG_WINDOW) >> 1; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++) >> exp;
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++) >> exp;
+
+ }
+
+ }
+ else if (exp < 0)
+ {
+
+ Int shift = -exp;
+ for (i = (W_L_START_1 - LONG_WINDOW) >> 1; i != 0 ; i--)
+ {
+ Int32 temp2 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp2;
+ temp2 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp2;
+ }
+
+ }
+ else
+ {
+
+ for (i = (W_L_START_1 - LONG_WINDOW) >> 1; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++);
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++);
+
+ }
+
+ }
+
+
+ pFreq_2_Time_data_1 = &pFreqInfo[W_L_START_1];
+ pFreq_2_Time_data_2 =
+ &pFreq_2_Time_data_1[HALF_SHORT_WINDOW];
+
+ pShort_Window_1 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+ pShort_Window_2 = pShort_Window_1 - HALF_SHORT_WINDOW;
+
+ pOverlap_and_Add_Buffer_2 = pOverlap_and_Add_Buffer_1 +
+ HALF_SHORT_WINDOW;
+
+
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ Int16 win1, win2;
+ Int16 dat1, dat2;
+ Int32 temp2;
+ dat1 = (*pFreq_2_Time_data_1++);
+ dat2 = (*pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_1--);
+ win2 = *(pShort_Window_2--);
+
+ temp = fxp_mul_16_by_16(dat1, win1) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp;
+
+ temp2 = fxp_mul_16_by_16(dat2, win2) >> shift;
+ *(pOverlap_and_Add_Buffer_2++) = temp2;
+
+
+ }
+
+
+ pOverlap_and_Add_Buffer_1 += HALF_SHORT_WINDOW;
+
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ (LONG_BLOCK1 - W_L_START_2)
+ *sizeof(*pOverlap_and_Add_Buffer_1));
+
+
+ break;
+
+
+ case LONG_STOP_SEQUENCE:
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[ W_L_STOP_2];
+
+ pOutput_buffer = &Output_buffer[W_L_STOP_2];
+
+ pFreq_2_Time_data_1 = &pFreqInfo[W_L_STOP_2];
+
+ exp -= SCALING; /* !!!! */
+
+ if (exp > 0)
+ {
+ Int16 tmp1 = (*(pFreq_2_Time_data_1++) >> exp);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ for (i = (LONG_WINDOW - W_L_STOP_2); i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), (temp + tmp1));
+
+ tmp1 = *(pFreq_2_Time_data_1++) >> exp;
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ }
+ }
+ else if (exp < 0)
+ {
+ shift = -exp;
+ Int32 temp1 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ for (i = (LONG_WINDOW - W_L_STOP_2); i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), (temp + temp1));
+
+ temp1 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ }
+ }
+ else
+ {
+ Int16 tmp1 = *(pFreq_2_Time_data_1++);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ for (i = (LONG_WINDOW - W_L_STOP_2); i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), (temp + tmp1));
+
+ tmp1 = *(pFreq_2_Time_data_1++);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ }
+ }
+
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_prev_bk][0];
+ pShort_Window_2 = &pShort_Window_1[HALF_SHORT_WINDOW];
+
+ pFreq_2_Time_data_1 = &pFreqInfo[W_L_STOP_1];
+ pFreq_2_Time_data_2 =
+ &pFreq_2_Time_data_1[HALF_SHORT_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[ W_L_STOP_1];
+ pOverlap_and_Add_Buffer_2 = pOverlap_and_Add_Buffer_1
+ + HALF_SHORT_WINDOW;
+
+ pOutput_buffer = &Output_buffer[W_L_STOP_1];
+ pOutput_buffer_2 = pOutput_buffer + HALF_SHORT_WINDOW;
+
+ exp += SCALING; /* +8 back to what it was */
+
+ shift = exp + 15 - SCALING;
+
+
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ Int16 win1;
+ Int16 dat1;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ test = fxp_mul_16_by_16(dat1, win1);
+
+ limiter(*(pOutput_buffer++), (temp + (test >> shift)));
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2++);
+ temp = *(pOverlap_and_Add_Buffer_2++);
+ test = fxp_mul_16_by_16(dat1, win1);
+ limiter(*(pOutput_buffer_2++), (temp + (test >> shift)));
+
+ }
+
+
+ pFreq_2_Time_data_2 = &pFreqInfo[LONG_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = Time_data;
+
+ pOutput_buffer = Output_buffer;
+
+ pLong_Window_2 =
+ &Long_Window_fxp[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+
+ /*
+ * Copy previous time in current buffer, also copy overlap
+ * and add buffer
+ */
+
+ for (i = W_L_STOP_1; i != 0; i--)
+ {
+ Int16 win1;
+ Int16 dat1;
+
+ win1 = *(pLong_Window_2--);
+ dat1 = *pFreq_2_Time_data_2++;
+
+ limiter(*(pOutput_buffer++), *(pOverlap_and_Add_Buffer_1));
+
+
+ temp = fxp_mul_16_by_16(dat1, win1) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp ;
+
+ }
+
+ for (i = (LONG_WINDOW - W_L_STOP_1); i != 0; i--)
+ {
+ temp = fxp_mul_16_by_16(*pFreq_2_Time_data_2++, *(pLong_Window_2--)) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp ;
+ }
+
+
+ break;
+
+
+
+ } /* switch (wnd_seq) */
+
+ } /* if (exp < 16) */
+
+ else
+ {
+ /* all zeros buffer or excessive down shift */
+
+ /* Overlap and add, setup buffer for next iteration */
+ pOverlap_and_Add_Buffer_1 = &Time_data[0];
+
+ pOutput_buffer = Output_buffer;
+
+ temp = (*pOverlap_and_Add_Buffer_1++);
+
+ for (i = LONG_WINDOW; i != 0; i--)
+ {
+
+ limiter(*(pOutput_buffer++), temp);
+
+ temp = (*pOverlap_and_Add_Buffer_1++);
+
+ }
+
+ pv_memset(Time_data, 0, LONG_WINDOW*sizeof(Time_data[0]));
+
+
+ }
+
+ }
+ else
+ {
+
+ Int32 *pScrath_mem;
+ Int32 *pScrath_mem_entry;
+ Int32 *pFrequency_data = Frequency_data;
+
+ Int32 * pOverlap_and_Add_Buffer_1;
+ Int32 * pOverlap_and_Add_Buffer_2;
+ Int32 * pOverlap_and_Add_Buffer_1x;
+ Int32 * pOverlap_and_Add_Buffer_2x;
+
+ /*
+ * Frequency_data is 2*LONG_WINDOW length but only
+ * the first LONG_WINDOW elements are filled in,
+ * then the second part can be used as scratch mem,
+ * then grab data from one window at a time in
+ * reverse order.
+ * The upper LONG_WINDOW Int32 are used to hold the
+ * computed overlap and add, used in the next call to
+ * this function, and also as sctrach memory
+ */
+
+ /*
+ * Frequency_data usage for the case EIGHT_SHORT_SEQUENCE
+
+ |<----- Input Freq. data ----->|< Overlap & Add ->| Unused |-Scratch-|
+ | | Store for next | | memory |
+ | | call | | |
+ | | | | |
+ |//////////////////////////////|\\\\\\\\\\\\\\\\\\|--------|+++++++++|
+ | | | | |
+ 0 LONG_WINDOW LONG_WINDOW | 2*LONG_WINDOW
+ + | |
+ W_L_STOP_2 | |
+ |<-- -->|
+ SHORT_WINDOW +
+ HALF_SHORT_WINDOW
+ *
+ */
+
+ pOverlap_and_Add_Buffer_1 = &pFrequency_data[
+ LONG_WINDOW + 3*SHORT_WINDOW + HALF_SHORT_WINDOW];
+
+ /*
+ * Initialize to zero, only the firt short window used in overlap
+ * and add
+ */
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ SHORT_WINDOW*sizeof(*pOverlap_and_Add_Buffer_1));
+
+ /*
+ * Showt windows are evaluated in decresing order. Windows from 7
+ * to 0 are break down in four cases: window numbers 7 to 5, 4, 3,
+ * and 2 to 0.
+ * The data from short windows 3 and 4 is situated at the boundary
+ * between the 'overlap and add' buffer and the output buffer.
+ */
+ for (wnd = NUM_SHORT_WINDOWS - 1; wnd >= NUM_SHORT_WINDOWS / 2 + 1; wnd--)
+ {
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ pOverlap_and_Add_Buffer_1 =
+ &pFrequency_data[ W_L_STOP_1 + SHORT_WINDOW*wnd];
+
+
+ pOverlap_and_Add_Buffer_2 =
+ pOverlap_and_Add_Buffer_1 + SHORT_WINDOW;
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+ if (exp < 16)
+ {
+
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+
+ /*
+ * Each of the eight short blocks is windowed separately.
+ * Window shape decisions are made on a frame-by-frame
+ * basis.
+ */
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+
+
+
+ /*
+ * For short windows from 7 to 5
+ * | =========================
+ * | | 5 6 7
+ * _--_ _--_ _--_ _--_ | _-|-_ _--_ _--_ _--_
+ * / \/ \/ \/ \|/ | \/ \/ \/ \
+ * / /\ /\ /\ /|\ | /\ /\ /\ \
+ * / / \ / \ / \ / | \ | / \ / \ / \ \
+ * / / \/ \/ \/ | \|/ \/ \ \ \
+ * --------------------------------|---[///////////////////////]--------
+ *
+ */
+
+
+ shift = exp + 15 - SCALING;
+
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ Int16 win1, win2;
+ Int16 dat1, dat2;
+
+ dat2 = *(pFreq_2_Time_data_2++);
+ win2 = *(pShort_Window_2--);
+ temp = *pOverlap_and_Add_Buffer_2;
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+
+ *(pOverlap_and_Add_Buffer_2++) = temp + (fxp_mul_16_by_16(dat2, win2) >> shift);
+
+ *(pOverlap_and_Add_Buffer_1++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ SHORT_WINDOW*sizeof(*pOverlap_and_Add_Buffer_1));
+ }
+
+
+ }/* for ( wnd=NUM_SHORT_WINDOWS-1; wnd>=NUM_SHORT_WINDOWS/2; wnd--) */
+
+
+ wnd = NUM_SHORT_WINDOWS / 2;
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+ /*
+ * scratch memory is allocated in an unused part of memory
+ */
+
+
+ pScrath_mem = &pFrequency_data[ 2*LONG_WINDOW - HALF_SHORT_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = &pFrequency_data[ LONG_WINDOW];
+
+ pOverlap_and_Add_Buffer_2 = pOverlap_and_Add_Buffer_1
+ + HALF_SHORT_WINDOW;
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+
+ /*
+ * For short window 4
+ * ====|===========
+ * | 4
+ * | | | |
+ * _--_ _--_ _--_ _-|-_ | _-|-_ _-|-_ _--_ _--_
+ * / \/ \/ \/ | \|/ | \/ | \/ \/ \
+ * / /\ /\ /\ | /|\ | /\ | /\ /\ \
+ * / / \ / \ / \ | / | \ | / \ | / \ / \ \
+ * / / \/ \/ \|/ | \|/ \|/ \/ \ \
+ * ------------------------------[\\\|\\\|//////]-------------------
+ * | | A | B | C |
+ * |
+ * W_L_STOP_1
+ */
+
+ shift = exp + 15 - SCALING;
+ {
+ Int16 win1;
+ Int16 dat1;
+ /* -------- segment A ---------------*/
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ *(pScrath_mem++) = fxp_mul_16_by_16(dat1, win1) >> (shift);
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ }
+
+ /* -------- segment B ---------------*/
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_1++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ }
+
+ /* -------- segment C ---------------*/
+ temp = *pOverlap_and_Add_Buffer_2;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_2++) = temp + (fxp_mul_16_by_16(dat1, win1) >> shift);
+
+ temp = *pOverlap_and_Add_Buffer_2;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+ }
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+ pv_memset(
+ pScrath_mem,
+ 0,
+ HALF_SHORT_WINDOW*sizeof(*pScrath_mem));
+
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ HALF_SHORT_WINDOW*sizeof(*pOverlap_and_Add_Buffer_1));
+ }
+
+
+ wnd = NUM_SHORT_WINDOWS / 2 - 1;
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+ pScrath_mem_entry =
+ &pFrequency_data[2*LONG_WINDOW - HALF_SHORT_WINDOW - SHORT_WINDOW];
+ pScrath_mem = pScrath_mem_entry;
+
+ pOverlap_and_Add_Buffer_1 = &pFrequency_data[ LONG_WINDOW];
+
+ /* point to end of buffer less HALF_SHORT_WINDOW */
+
+ pOutput_buffer_2 = &Output_buffer[LONG_WINDOW - HALF_SHORT_WINDOW];
+ pOutput_buffer = pOutput_buffer_2;
+
+ pOverlap_and_Add_Buffer_1x = &Time_data[W_L_STOP_1 + SHORT_WINDOW*(wnd+1)]; /* !!!! */
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+
+ /*
+ * For short window 3
+ * ===========|====
+ * 3 |
+ * | | | |
+ * _--_ _--_ _-|-_ _-|-_ | _-|-_ _--_ _--_ _--_
+ * / \/ \/ | \/ | \|/ | \/ \/ \/ \
+ * / /\ /\ | /\ | /|\ | /\ /\ /\ \
+ * / / \ / \ | / \ | / | \ | / \ / \ / \ \
+ * / / \/ \|/ \|/ | \|/ \/ \ \ \
+ * -----|------------------[\\\\\\|///|///]--------------------------
+ * | | A | B | C |
+ *
+ * W_L_STOP_1
+ */
+
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+ shift = exp + 15 - SCALING;
+
+
+ Int16 win1;
+ Int16 dat1;
+ /* -------- segment A ---------------*/
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ *(pScrath_mem++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ }
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+
+ /* -------- segment B ---------------*/
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ test = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ temp = *(pScrath_mem++) + test;
+
+
+ test = *(pOverlap_and_Add_Buffer_1x++); /* !!!! */
+
+ limiter(*(pOutput_buffer++), (temp + test));
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+
+ }
+
+ /* -------- segment C ---------------*/
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ temp = fxp_mul_16_by_16(dat1, win1) >> (shift);
+
+ *(pOverlap_and_Add_Buffer_1++) += temp;
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+
+ pv_memset(
+ pScrath_mem,
+ 0,
+ SHORT_WINDOW*sizeof(*pScrath_mem));
+
+ pScrath_mem += SHORT_WINDOW;
+
+ temp = *(pScrath_mem++);
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), temp);
+ temp = *(pScrath_mem++);
+
+
+ }
+ }
+
+
+ for (wnd = NUM_SHORT_WINDOWS / 2 - 2; wnd >= 0; wnd--)
+ {
+
+
+ pOutput_buffer_2 -= SHORT_WINDOW;
+ pOutput_buffer = pOutput_buffer_2;
+
+ /*
+ * The same memory is used as scratch in every iteration
+ */
+ pScrath_mem = pScrath_mem_entry;
+
+ pOverlap_and_Add_Buffer_2x =
+ &Time_data[W_L_STOP_1 + SHORT_WINDOW*(wnd+1)];
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+
+ /*
+ * Each of the eight short blocks is windowed separately.
+ * Window shape decisions are made on a frame-by-frame
+ * basis.
+ */
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ if (wnd == 0)
+ {
+ pShort_Window_1 =
+ &Short_Window_fxp[wnd_shape_prev_bk][0];
+ }
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+
+ /*
+ * For short windows from 2 to 0
+ *
+ * =========================
+ * |
+ * 0 1 2 | |
+ * _--_ _--_ _--_ _-|-_ | _--_ _--_ _--_ _--_
+ * / \/ \/ \/ | \|/ \/ \/ \/ \
+ * / /\ /\ /\ | /|\ /\ /\ /\ \
+ * / / \ / \ / \ | / | \ / \ / \ / \ \
+ * / / \/ \/ \|/ | \/ \/ \ \ \
+ * ----[\\\\\\\\\\\\\\\\\\\\\\\\]---|-----------------------------
+ * |
+ *
+ * W_L_STOP_1
+ */
+
+ shift = exp + 15 - SCALING;
+
+ Int16 dat1 = *(pFreq_2_Time_data_2++);
+ Int16 win1 = *(pShort_Window_2--);
+
+ temp = *(pScrath_mem);
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ test = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ temp += test;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+
+ limiter(*(pOutput_buffer++), (temp + *(pOverlap_and_Add_Buffer_2x++)));
+
+
+ *(pScrath_mem++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+ temp = *(pScrath_mem);
+
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+ test = *(pScrath_mem);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), (temp + test));
+
+ *(pScrath_mem++) = 0;
+ test = *(pScrath_mem);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ }
+ }
+
+ } /* for ( wnd=NUM_SHORT_WINDOWS/2-1; wnd>=0; wnd--) */
+
+ pOverlap_and_Add_Buffer_2x = &Time_data[W_L_STOP_1];
+
+ pScrath_mem = pScrath_mem_entry;
+
+ pOutput_buffer_2 -= SHORT_WINDOW;
+ pOutput_buffer = pOutput_buffer_2;
+
+ test = *(pScrath_mem++);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), (temp + test));
+
+ test = *(pScrath_mem++);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ }
+
+ pOverlap_and_Add_Buffer_1x = Time_data;
+
+ pOutput_buffer = Output_buffer;
+
+
+ temp = *(pOverlap_and_Add_Buffer_1x++);
+
+ for (i = W_L_STOP_1; i != 0; i--)
+ {
+ limiter(*(pOutput_buffer++), temp);
+
+ temp = *(pOverlap_and_Add_Buffer_1x++);
+ }
+
+ pOverlap_and_Add_Buffer_1x = &Time_data[0];
+
+ pOverlap_and_Add_Buffer_2 = &pFrequency_data[LONG_WINDOW];
+
+ /*
+ * update overlap and add buffer,
+ * so is ready for next iteration
+ */
+
+ for (int i = 0; i < W_L_STOP_2; i++)
+ {
+ temp = *(pOverlap_and_Add_Buffer_2++);
+ *(pOverlap_and_Add_Buffer_1x++) = temp;
+ }
+
+ pv_memset(
+ pOverlap_and_Add_Buffer_1x,
+ 0,
+ W_L_STOP_1*sizeof(*pOverlap_and_Add_Buffer_1x));
+
+ } /* if ( wnd_seq != EIGHT_SHORT_SEQUENCE) */
+
+}
+
+#endif
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+void trans4m_freq_2_time_fxp_2(
+ Int32 Frequency_data[],
+ Int32 Time_data[],
+ WINDOW_SEQUENCE wnd_seq,
+ Int wnd_shape_prev_bk,
+ Int wnd_shape_this_bk,
+ Int Q_format,
+ Int32 abs_max_per_window[],
+ Int32 freq_2_time_buffer[],
+ Int16 *Interleaved_output)
+
+{
+
+ Int exp;
+ Int shift;
+
+ Int i;
+ Int wnd;
+#if !(defined( PV_ARM_GCC_V5)||(PV_ARM_V5))
+ Int32 z;
+#endif
+ Int16 *pFreqInfo;
+ Int32 temp;
+ Int32 test;
+
+ Int16 *pFreq_2_Time_data_1;
+ Int16 *pFreq_2_Time_data_2;
+
+ const Int16 *pLong_Window_1;
+ const Int16 *pLong_Window_2;
+ const Int16 *pShort_Window_1;
+ const Int16 *pShort_Window_2;
+
+ Int32 *pOverlap_and_Add_Buffer_1;
+ Int32 *pOverlap_and_Add_Buffer_2;
+
+ Int16 *pInterleaved_output;
+ Int16 *pInterleaved_output_2;
+
+
+ const Int16 * Long_Window_fxp[NUM_WINDOW_SHAPES];
+ const Int16 * Short_Window_fxp[NUM_WINDOW_SHAPES];
+
+ Long_Window_fxp[0] = Long_Window_sine_fxp;
+ Long_Window_fxp[1] = Long_Window_KBD_fxp;
+ Short_Window_fxp[0] = Short_Window_sine_fxp;
+ Short_Window_fxp[1] = Short_Window_KBD_fxp;
+
+ if (wnd_seq != EIGHT_SHORT_SEQUENCE)
+ {
+
+ pFreqInfo = (Int16 *)Frequency_data;
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ LONG_BLOCK1,
+ Q_format,
+ abs_max_per_window[0]);
+
+
+ /*
+ * The C Programming Language, Second Edition, Kernighan & Ritchie,
+ * page 206.
+ * "The result [of a shift] is undefined if the right operand is
+ * negative, or greater than or equal to the number of bits in the
+ * left expression's type"
+ * => avoid shift by 32 or 16
+ */
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = pFreqInfo;
+
+
+ switch (wnd_seq)
+ {
+
+ case ONLY_LONG_SEQUENCE:
+ default:
+
+ {
+ pOverlap_and_Add_Buffer_1 = Time_data;
+
+ pInterleaved_output = Interleaved_output;
+
+ {
+
+ const Int16 *pLong_Window_2 = &Long_Window_fxp[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+ Int32 * pFreq2T = (Int32 *)pFreqInfo;
+ Int32 * pFreq2T_2 = &pFreq2T[HALF_LONG_WINDOW];
+ Int32 * win = (Int32 *) & Long_Window_fxp[wnd_shape_prev_bk][0];
+
+ Int shift = exp + 15 - SCALING;
+
+ for (i = HALF_LONG_WINDOW; i != 0; i--)
+ {
+ Int16 win1, win2;
+ Int32 temp2, test2;
+
+ Int32 winx;
+
+ temp2 = *(pFreq2T++);
+ winx = *(win++);
+
+ test = *(pOverlap_and_Add_Buffer_1++);
+ test2 = *(pOverlap_and_Add_Buffer_1--);
+ temp = fxp_mul_16_by_16bb(temp2, winx) >> shift;
+ temp2 = fxp_mul_16_by_16tt(temp2, winx) >> shift;
+
+ limiter(*(pInterleaved_output), (temp + test));
+
+ limiter(*(pInterleaved_output + 2), (temp2 + test2));
+ pInterleaved_output += 4;
+
+ temp2 = *(pFreq2T_2++);
+
+ win1 = *(pLong_Window_2--);
+ win2 = *(pLong_Window_2--);
+ temp = fxp_mul_16_by_16bb(temp2, win1) >> shift;
+ test2 = fxp_mul_16_by_16tb(temp2, win2) >> shift;
+
+ *(pOverlap_and_Add_Buffer_1++) = temp;
+ *(pOverlap_and_Add_Buffer_1++) = test2;
+ }
+
+ }
+
+ }
+
+ break;
+
+ case LONG_START_SEQUENCE:
+
+ pFreq_2_Time_data_2 =
+ &pFreq_2_Time_data_1[ HALF_LONG_WINDOW];
+
+ pLong_Window_1 = &Long_Window_fxp[wnd_shape_prev_bk][0];
+ pLong_Window_2 = &pLong_Window_1[ HALF_LONG_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[0];
+ pOverlap_and_Add_Buffer_2 = &Time_data[HALF_LONG_WINDOW];
+
+
+ pInterleaved_output = Interleaved_output;
+ pInterleaved_output_2 = pInterleaved_output + (2 * HALF_LONG_WINDOW);
+
+
+ /*
+ * process first LONG_WINDOW elements
+ */
+
+ shift = exp + 15 - SCALING;
+
+ for (i = HALF_LONG_WINDOW; i != 0; i--)
+ {
+ Int16 win1, win2;
+ Int16 dat1, dat2;
+ Int32 test1, test2;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pLong_Window_1++);
+ test1 = *(pOverlap_and_Add_Buffer_1++);
+
+ dat2 = *(pFreq_2_Time_data_2++);
+ win2 = *(pLong_Window_2++);
+ test2 = *(pOverlap_and_Add_Buffer_2++);
+
+ limiter(*(pInterleaved_output), (test1 + (fxp_mul_16_by_16(dat1, win1) >> shift)));
+
+ pInterleaved_output += 2;
+
+ limiter(*(pInterleaved_output_2), (test2 + (fxp_mul_16_by_16(dat2, win2) >> shift)));
+
+ pInterleaved_output_2 += 2;
+ }
+
+
+ /*
+ * data unchanged from LONG_WINDOW to W_L_START_1
+ * only scaled accordingly
+ */
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[0];
+ pFreq_2_Time_data_1 = &pFreqInfo[LONG_WINDOW];
+
+ exp -= SCALING;
+
+ if (exp >= 0)
+ {
+
+ for (i = (W_L_START_1 - LONG_WINDOW) >> 1; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++) >> exp;
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++) >> exp;
+
+ }
+
+ }
+ else if (exp < 0)
+ {
+
+ Int shift = -exp;
+ for (i = (W_L_START_1 - LONG_WINDOW) >> 1; i != 0 ; i--)
+ {
+ Int32 temp2 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp2;
+ temp2 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp2;
+ }
+
+ }
+ else
+ {
+
+ for (i = (W_L_START_1 - LONG_WINDOW) >> 1; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++);
+ *(pOverlap_and_Add_Buffer_1++) =
+ *(pFreq_2_Time_data_1++);
+
+ }
+
+ }
+
+
+ pFreq_2_Time_data_1 = &pFreqInfo[W_L_START_1];
+ pFreq_2_Time_data_2 =
+ &pFreq_2_Time_data_1[HALF_SHORT_WINDOW];
+
+ pShort_Window_1 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+ pShort_Window_2 = pShort_Window_1 - HALF_SHORT_WINDOW;
+
+ pOverlap_and_Add_Buffer_2 = pOverlap_and_Add_Buffer_1 +
+ HALF_SHORT_WINDOW;
+
+ {
+ Int16 win1, win2;
+ Int16 dat1, dat2;
+ Int32 temp2;
+
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+
+ dat1 = (*pFreq_2_Time_data_1++);
+ dat2 = (*pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_1--);
+ win2 = *(pShort_Window_2--);
+
+ temp = fxp_mul_16_by_16(dat1, win1) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp;
+
+ temp2 = fxp_mul_16_by_16(dat2, win2) >> shift;
+ *(pOverlap_and_Add_Buffer_2++) = temp2;
+
+ }
+ }
+
+ pOverlap_and_Add_Buffer_1 += HALF_SHORT_WINDOW;
+
+
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ (LONG_BLOCK1 - W_L_START_2)
+ *sizeof(*pOverlap_and_Add_Buffer_1));
+
+
+ break;
+
+
+ case LONG_STOP_SEQUENCE:
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[ W_L_STOP_2];
+
+ pInterleaved_output = &Interleaved_output[2*W_L_STOP_2];
+
+ pFreq_2_Time_data_1 = &pFreqInfo[W_L_STOP_2];
+
+ exp -= SCALING;
+
+
+ if (exp > 0)
+ {
+ Int16 tmp1 = (*(pFreq_2_Time_data_1++) >> exp);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ for (i = (LONG_WINDOW - W_L_STOP_2); i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), (temp + tmp1));
+
+ pInterleaved_output += 2;
+ tmp1 = *(pFreq_2_Time_data_1++) >> exp;
+ temp = *(pOverlap_and_Add_Buffer_1++);
+ }
+ }
+ else if (exp < 0)
+ {
+ shift = -exp;
+
+ Int32 temp1 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ for (i = (LONG_WINDOW - W_L_STOP_2); i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), (temp + temp1));
+
+ pInterleaved_output += 2;
+ temp1 = ((Int32) * (pFreq_2_Time_data_1++)) << shift;
+ temp = *(pOverlap_and_Add_Buffer_1++);
+ }
+ }
+ else
+ {
+ Int16 tmp1 = *(pFreq_2_Time_data_1++);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+ for (i = (LONG_WINDOW - W_L_STOP_2); i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), (temp + tmp1));
+
+ pInterleaved_output += 2;
+ tmp1 = *(pFreq_2_Time_data_1++);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+ }
+ }
+
+
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_prev_bk][0];
+ pShort_Window_2 = &pShort_Window_1[HALF_SHORT_WINDOW];
+
+ pFreq_2_Time_data_1 = &pFreqInfo[W_L_STOP_1];
+ pFreq_2_Time_data_2 =
+ &pFreq_2_Time_data_1[HALF_SHORT_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = &Time_data[ W_L_STOP_1];
+ pOverlap_and_Add_Buffer_2 = pOverlap_and_Add_Buffer_1
+ + HALF_SHORT_WINDOW;
+
+
+ pInterleaved_output = &Interleaved_output[2*W_L_STOP_1];
+ pInterleaved_output_2 = pInterleaved_output + (2 * HALF_SHORT_WINDOW);
+
+ exp += SCALING; /* +8 back to what it was */
+ shift = exp + 15 - SCALING;
+
+
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+
+ Int16 win1;
+ Int16 dat1;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ temp = *(pOverlap_and_Add_Buffer_1++);
+
+ test = fxp_mul_16_by_16(dat1, win1);
+
+ limiter(*(pInterleaved_output), (temp + (test >> shift)));
+
+ pInterleaved_output += 2;
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2++);
+ temp = *(pOverlap_and_Add_Buffer_2++);
+ test = fxp_mul_16_by_16(dat1, win1);
+
+ limiter(*(pInterleaved_output_2), (temp + (test >> shift)));
+
+ pInterleaved_output_2 += 2;
+
+ }
+
+
+
+ pFreq_2_Time_data_2 = &pFreqInfo[LONG_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = Time_data;
+
+
+ pInterleaved_output = Interleaved_output;
+
+ pLong_Window_2 =
+ &Long_Window_fxp[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+
+ /*
+ * Copy previous time in current buffer, also copy overlap
+ * and add buffer
+ */
+
+ for (i = W_L_STOP_1; i != 0; i--)
+ {
+
+ Int16 win1;
+ Int16 dat1;
+
+ win1 = *(pLong_Window_2--);
+ dat1 = *pFreq_2_Time_data_2++;
+
+ limiter(*(pInterleaved_output), *(pOverlap_and_Add_Buffer_1));
+
+ pInterleaved_output += 2;
+
+ temp = fxp_mul_16_by_16(dat1, win1) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp ;
+
+ }
+
+ for (i = (LONG_WINDOW - W_L_STOP_1); i != 0; i--)
+ {
+
+ temp = fxp_mul_16_by_16(*pFreq_2_Time_data_2++, *(pLong_Window_2--)) >> shift;
+ *(pOverlap_and_Add_Buffer_1++) = temp ;
+
+ }
+
+ break;
+
+
+
+ } /* switch (wnd_seq) */
+
+ } /* if (exp < 16) */
+
+ else
+ {
+ /* all zeros buffer or excessive down shift */
+
+ /* Overlap and add, setup buffer for next iteration */
+ pOverlap_and_Add_Buffer_1 = &Time_data[0];
+
+ pInterleaved_output = Interleaved_output;
+
+
+ temp = (*pOverlap_and_Add_Buffer_1++);
+ for (i = LONG_WINDOW; i != 0; i--)
+ {
+
+ limiter(*(pInterleaved_output), temp);
+
+ pInterleaved_output += 2;
+ temp = (*pOverlap_and_Add_Buffer_1++);
+ }
+ pv_memset(Time_data, 0, LONG_WINDOW*sizeof(Time_data[0]));
+ }
+
+ }
+ else
+ {
+
+ Int32 *pScrath_mem;
+ Int32 *pScrath_mem_entry;
+ Int32 *pFrequency_data = Frequency_data;
+
+ Int32 * pOverlap_and_Add_Buffer_1;
+ Int32 * pOverlap_and_Add_Buffer_2;
+ Int32 * pOverlap_and_Add_Buffer_1x;
+ Int32 * pOverlap_and_Add_Buffer_2x;
+
+
+ /*
+ * Frequency_data is 2*LONG_WINDOW length but only
+ * the first LONG_WINDOW elements are filled in,
+ * then the second part can be used as scratch mem,
+ * then grab data from one window at a time in
+ * reverse order.
+ * The upper LONG_WINDOW Int32 are used to hold the
+ * computed overlap and add, used in the next call to
+ * this function, and also as sctrach memory
+ */
+
+ /*
+ * Frequency_data usage for the case EIGHT_SHORT_SEQUENCE
+
+ |<----- Input Freq. data ----->|< Overlap & Add ->| Unused |-Scratch-|
+ | | Store for next | | memory |
+ | | call | | |
+ | | | | |
+ |//////////////////////////////|\\\\\\\\\\\\\\\\\\|--------|+++++++++|
+ | | | | |
+ 0 LONG_WINDOW LONG_WINDOW | 2*LONG_WINDOW
+ + | |
+ W_L_STOP_2 | |
+ |<-- -->|
+ SHORT_WINDOW +
+ HALF_SHORT_WINDOW
+ *
+ */
+
+ pOverlap_and_Add_Buffer_1 = &pFrequency_data[
+ LONG_WINDOW + 3*SHORT_WINDOW + HALF_SHORT_WINDOW];
+
+ /*
+ * Initialize to zero, only the firt short window used in overlap
+ * and add
+ */
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ SHORT_WINDOW*sizeof(*pOverlap_and_Add_Buffer_1));
+
+ /*
+ * Showt windows are evaluated in decresing order. Windows from 7
+ * to 0 are break down in four cases: window numbers 7 to 5, 4, 3,
+ * and 2 to 0.
+ * The data from short windows 3 and 4 is situated at the boundary
+ * between the 'overlap and add' buffer and the output buffer.
+ */
+ for (wnd = NUM_SHORT_WINDOWS - 1; wnd >= NUM_SHORT_WINDOWS / 2 + 1; wnd--)
+ {
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /* W_L_STOP_1 == (LONG_WINDOW - SHORT_WINDOW)>>1 */
+ pOverlap_and_Add_Buffer_1 =
+ &pFrequency_data[ W_L_STOP_1 + SHORT_WINDOW*wnd];
+
+
+ pOverlap_and_Add_Buffer_2 =
+ pOverlap_and_Add_Buffer_1 + SHORT_WINDOW;
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+ if (exp < 16)
+ {
+
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+
+ /*
+ * Each of the eight short blocks is windowed separately.
+ * Window shape decisions are made on a frame-by-frame
+ * basis.
+ */
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+
+
+
+ /*
+ * For short windows from 7 to 5
+ * | =========================
+ * | | 5 6 7
+ * _--_ _--_ _--_ _--_ | _-|-_ _--_ _--_ _--_
+ * / \/ \/ \/ \|/ | \/ \/ \/ \
+ * / /\ /\ /\ /|\ | /\ /\ /\ \
+ * / / \ / \ / \ / | \ | / \ / \ / \ \
+ * / / \/ \/ \/ | \|/ \/ \ \ \
+ * --------------------------------|---[///////////////////////]--------
+ *
+ */
+
+
+ shift = exp + 15 - SCALING;
+
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ Int16 win1, win2;
+ Int16 dat1, dat2;
+
+ dat2 = *(pFreq_2_Time_data_2++);
+ win2 = *(pShort_Window_2--);
+ temp = *pOverlap_and_Add_Buffer_2;
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+
+ *(pOverlap_and_Add_Buffer_2++) = temp + (fxp_mul_16_by_16(dat2, win2) >> shift);
+
+ *(pOverlap_and_Add_Buffer_1++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ SHORT_WINDOW*sizeof(*pOverlap_and_Add_Buffer_1));
+ }
+
+
+ }/* for ( wnd=NUM_SHORT_WINDOWS-1; wnd>=NUM_SHORT_WINDOWS/2; wnd--) */
+
+
+ wnd = NUM_SHORT_WINDOWS / 2;
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+ /*
+ * scratch memory is allocated in an unused part of memory
+ */
+
+
+ pScrath_mem = &pFrequency_data[ 2*LONG_WINDOW - HALF_SHORT_WINDOW];
+
+ pOverlap_and_Add_Buffer_1 = &pFrequency_data[ LONG_WINDOW];
+
+ pOverlap_and_Add_Buffer_2 = pOverlap_and_Add_Buffer_1
+ + HALF_SHORT_WINDOW;
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+
+ /*
+ * For short window 4
+ * ====|===========
+ * | 4
+ * | | | |
+ * _--_ _--_ _--_ _-|-_ | _-|-_ _-|-_ _--_ _--_
+ * / \/ \/ \/ | \|/ | \/ | \/ \/ \
+ * / /\ /\ /\ | /|\ | /\ | /\ /\ \
+ * / / \ / \ / \ | / | \ | / \ | / \ / \ \
+ * / / \/ \/ \|/ | \|/ \|/ \/ \ \
+ * ------------------------------[\\\|\\\|//////]-------------------
+ * | | A | B | C |
+ * |
+ * W_L_STOP_1
+ */
+
+ shift = exp + 15 - SCALING;
+ {
+ Int16 win1;
+ Int16 dat1;
+ /* -------- segment A ---------------*/
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ *(pScrath_mem++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ }
+
+ /* -------- segment B ---------------*/
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_1++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ }
+
+ /* -------- segment C ---------------*/
+ temp = *pOverlap_and_Add_Buffer_2;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ *(pOverlap_and_Add_Buffer_2++) = temp + (fxp_mul_16_by_16(dat1, win1) >> shift);
+
+ temp = *pOverlap_and_Add_Buffer_2;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+ }
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+ pv_memset(
+ pScrath_mem,
+ 0,
+ HALF_SHORT_WINDOW*sizeof(*pScrath_mem));
+
+ pv_memset(
+ pOverlap_and_Add_Buffer_1,
+ 0,
+ HALF_SHORT_WINDOW*sizeof(*pOverlap_and_Add_Buffer_1));
+ }
+
+
+ wnd = NUM_SHORT_WINDOWS / 2 - 1;
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+ pScrath_mem_entry =
+ &pFrequency_data[2*LONG_WINDOW - HALF_SHORT_WINDOW - SHORT_WINDOW];
+
+
+ pScrath_mem = pScrath_mem_entry;
+
+ pOverlap_and_Add_Buffer_1 = &pFrequency_data[ LONG_WINDOW];
+
+ /* point to end of buffer less HALF_SHORT_WINDOW */
+
+ pInterleaved_output_2 = &Interleaved_output[2*(LONG_WINDOW - HALF_SHORT_WINDOW)];
+ pInterleaved_output = pInterleaved_output_2;
+
+ pOverlap_and_Add_Buffer_1x = &Time_data[W_L_STOP_1 + SHORT_WINDOW*(wnd+1)];
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+
+ /*
+ * For short window 3
+ * ===========|====
+ * 3 |
+ * | | | |
+ * _--_ _--_ _-|-_ _-|-_ | _-|-_ _--_ _--_ _--_
+ * / \/ \/ | \/ | \|/ | \/ \/ \/ \
+ * / /\ /\ | /\ | /|\ | /\ /\ /\ \
+ * / / \ / \ | / \ | / | \ | / \ / \ / \ \
+ * / / \/ \|/ \|/ | \|/ \/ \ \ \
+ * -----|------------------[\\\\\\|///|///]--------------------------
+ * | | A | B | C |
+ *
+ * W_L_STOP_1
+ */
+
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+ shift = exp + 15 - SCALING;
+
+ Int16 win1;
+ Int16 dat1;
+ /* -------- segment A ---------------*/
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ *(pScrath_mem++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+ }
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+
+
+ /* -------- segment B ---------------*/
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ test = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ temp = *(pScrath_mem++) + test;
+
+ test = *(pOverlap_and_Add_Buffer_1x++);
+ limiter(*(pInterleaved_output), (temp + test));
+
+
+ pInterleaved_output += 2;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+
+ }
+
+ /* -------- segment C ---------------*/
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+
+ temp = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ *(pOverlap_and_Add_Buffer_1++) += temp;
+
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+ }
+
+
+ } /* if (exp < 16) */
+ else
+ {
+
+ pv_memset(
+ pScrath_mem,
+ 0,
+ SHORT_WINDOW*sizeof(*pScrath_mem));
+
+ pScrath_mem += SHORT_WINDOW;
+
+ temp = *(pScrath_mem++);
+ for (i = HALF_SHORT_WINDOW; i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), (temp));
+
+ pInterleaved_output += 2;
+ temp = *(pScrath_mem++);
+
+ }
+ }
+
+
+ for (wnd = NUM_SHORT_WINDOWS / 2 - 2; wnd >= 0; wnd--)
+ {
+
+
+ pInterleaved_output_2 -= (SHORT_WINDOW * 2);
+ pInterleaved_output = pInterleaved_output_2;
+
+ /*
+ * The same memory is used as scratch in every iteration
+ */
+ pScrath_mem = pScrath_mem_entry;
+
+ pOverlap_and_Add_Buffer_2x =
+ &Time_data[W_L_STOP_1 + SHORT_WINDOW*(wnd+1)];
+
+ pFreqInfo = (Int16 *) & pFrequency_data[ wnd*SHORT_WINDOW];
+
+
+
+ exp = imdct_fxp(
+ (Int32 *)pFreqInfo,
+ freq_2_time_buffer,
+ SHORT_BLOCK1,
+ Q_format,
+ abs_max_per_window[wnd]);
+
+ /*
+ * If all element are zero or if the exponent is bigger than
+ * 16 ( it becomes an undefined shift) -> skip
+ */
+
+ if (exp < 16)
+ {
+
+ pFreq_2_Time_data_1 = &pFreqInfo[0];
+ pFreq_2_Time_data_2 = &pFreqInfo[SHORT_WINDOW];
+
+
+ /*
+ * Each of the eight short blocks is windowed separately.
+ * Window shape decisions are made on a frame-by-frame
+ * basis.
+ */
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+
+ if (wnd == 0)
+ {
+ pShort_Window_1 =
+ &Short_Window_fxp[wnd_shape_prev_bk][0];
+ }
+
+ pShort_Window_2 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+
+ /*
+ * For short windows from 2 to 0
+ *
+ * =========================
+ * |
+ * 0 1 2 | |
+ * _--_ _--_ _--_ _-|-_ | _--_ _--_ _--_ _--_
+ * / \/ \/ \/ | \|/ \/ \/ \/ \
+ * / /\ /\ /\ | /|\ /\ /\ /\ \
+ * / / \ / \ / \ | / | \ / \ / \ / \ \
+ * / / \/ \/ \|/ | \/ \/ \ \ \
+ * ----[\\\\\\\\\\\\\\\\\\\\\\\\]---|-----------------------------
+ * |
+ *
+ * W_L_STOP_1
+ */
+
+ shift = exp + 15 - SCALING;
+
+ Int16 dat1 = *(pFreq_2_Time_data_2++);
+ Int16 win1 = *(pShort_Window_2--);
+
+ temp = *(pScrath_mem);
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ test = fxp_mul_16_by_16(dat1, win1) >> shift;
+
+ temp += test;
+ dat1 = *(pFreq_2_Time_data_1++);
+ win1 = *(pShort_Window_1++);
+
+ limiter(*(pInterleaved_output), (temp + *(pOverlap_and_Add_Buffer_2x++)));
+
+ pInterleaved_output += 2;
+
+ *(pScrath_mem++) = fxp_mul_16_by_16(dat1, win1) >> shift;
+ dat1 = *(pFreq_2_Time_data_2++);
+ win1 = *(pShort_Window_2--);
+ temp = *(pScrath_mem);
+
+ }
+
+ } /* if (exp < 16) */
+ else
+ {
+ test = *(pScrath_mem);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), (temp + test));
+
+ pInterleaved_output += 2;
+
+ *(pScrath_mem++) = 0;
+ test = *(pScrath_mem);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+ }
+ }
+
+ } /* for ( wnd=NUM_SHORT_WINDOWS/2-1; wnd>=0; wnd--) */
+
+ pOverlap_and_Add_Buffer_2x = &Time_data[W_L_STOP_1];
+
+ pScrath_mem = pScrath_mem_entry;
+
+ pInterleaved_output_2 -= (SHORT_WINDOW * 2);
+ pInterleaved_output = pInterleaved_output_2;
+
+ test = *(pScrath_mem++);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ for (i = SHORT_WINDOW; i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), (temp + test));
+
+ pInterleaved_output += 2;
+ test = *(pScrath_mem++);
+ temp = *(pOverlap_and_Add_Buffer_2x++);
+
+ }
+
+ pOverlap_and_Add_Buffer_1x = Time_data;
+
+ pInterleaved_output = Interleaved_output;
+
+
+ temp = *(pOverlap_and_Add_Buffer_1x++);
+ for (i = W_L_STOP_1; i != 0; i--)
+ {
+ limiter(*(pInterleaved_output), temp);
+
+ pInterleaved_output += 2;
+ temp = *(pOverlap_and_Add_Buffer_1x++);
+
+ }
+
+ pOverlap_and_Add_Buffer_1x = &Time_data[0];
+
+ pOverlap_and_Add_Buffer_2 = &pFrequency_data[LONG_WINDOW];
+
+ /*
+ * update overlap and add buffer,
+ * so is ready for next iteration
+ */
+
+ for (int i = 0; i < W_L_STOP_2; i++)
+ {
+ temp = *(pOverlap_and_Add_Buffer_2++);
+ *(pOverlap_and_Add_Buffer_1x++) = temp;
+ }
+
+ pv_memset(
+ pOverlap_and_Add_Buffer_1x,
+ 0,
+ W_L_STOP_1*sizeof(*pOverlap_and_Add_Buffer_1x));
+
+ } /* if ( wnd_seq != EIGHT_SHORT_SEQUENCE) */
+
+
+
+
+} /* trans4m_freq_2_time_fxp */
+
+
+
+
diff --git a/media/libstagefright/codecs/aacdec/trans4m_time_2_freq_fxp.cpp b/media/libstagefright/codecs/aacdec/trans4m_time_2_freq_fxp.cpp
new file mode 100644
index 0000000..b1b44f0
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/trans4m_time_2_freq_fxp.cpp
@@ -0,0 +1,663 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: trans4m_time_2_freq_fxp.c
+ Function: trans4m_time_2_freq_fxp
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ Modified normalization, so it now happen per window basis, eliminated
+ shifts left or rigth to accomodate TNS inverse filtering. The output
+ is 32 bits but only the lowest 16 are being used.
+ Modified fuction interface
+
+ Description: Modified variable names with leading "p" for pointers
+
+ Description:
+ Modified call to mdct_fxp to reflect extended precision use. Added routine
+ buffer_adaptation to extract 16 MSB and keep highest precision.
+ Modify casting to ensure proper operations for different platforms
+
+ Description:
+ Added comments according to code review
+
+ Description:
+ Removed include file "buffer_normalization.h"
+
+ Description:
+ Eliminated buffer_adaptation() and embedded its functionality in other
+ functions. Commented out the short window section given that this is
+ not supported by the standards
+
+ Description:
+ Added shift down operation for case when the window was equal to one.
+ This was not needed previuosly because buffer_adaptation() was doing
+ it.
+
+ Description: Created local version of vectors Long_Window_fxp and
+ Short_Window_fxp. This solve linking problem when using the
+ /ropi option (Read-only position independent) for some
+ compilers.
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ Time2Freq_data = buffer with data in the time domain, it holds 2048
+ points of input time data
+ Output holds frequency (first 1024 points )
+ type Int32
+
+ wnd_seq = window sequence
+ type WINDOW_SEQUENCE
+
+ wnd_shape_prev_bk = previous window shape type
+ type Int
+
+ wnd_shape_this_bk = current window shape type
+ type Int
+
+ pQ_format = Holds the Q format of the data in, and data out
+ type Int *
+
+ mem_4_in_place_FFT[] = scratch memory for computing FFT, 1024 point
+ type Int32
+
+
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ Frequency information (1024 pts.) is returned in Time2Freq_data
+ pQ_format content spectral coefficients Q format
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+The time/frequency representation of the signal is mapped onto the frequency
+domain by feeding it into the filterbank module. This module consists of
+a modified discrete cosine transform (MDCT), (windowing and DCT).
+In order to adapt the time/frequency resolution of the filterbank to the
+ characteristics of the input signal, a block switching tool is also
+adopted. N represents the window length, where N is a function of the
+window_sequence. For each channel, the N time values are transformed into the
+N/2 frequency domain values via the MDCT.
+
+The adaptation of the time-frequency resolution of the filterbank to the
+characteristics of the input signal is done by shifting between transforms
+whose input lengths are either 2048 or 256 samples. By enabling the block
+switching tool, the following transitions are meaningful:
+
+from ONLY_LONG_SEQUENCE to { LONG_START_SEQUENCE
+ ONLY_LONG_SEQUENCE
+
+from LONG_START_SEQUENCE to { LONG_STOP_SEQUENCE
+ EIGHT_SHORT_SEQUENCE
+
+from LONG_STOP_SEQUENCE to { LONG_START_SEQUENCE
+ ONLY_LONG_SEQUENCE
+
+from EIGHT_SHORT_SEQUENCE to { LONG_STOP_SEQUENCE
+ EIGHT_SHORT_SEQUENCE
+
+Window shape decisions are made by the encoder on a frame-by-frame-basis.
+The window selected is applicable to the second half of the window function
+only, since the first half is constrained to use the appropriate window
+shape from the preceding frame.
+The 2048 time-domain values x'(i)(n), (i window, n sample) to be windowed are
+the last 1024 values of the previous window_sequence concatenated with 1024
+values of the current block. The formula below shows this fact:
+
+ | x(i-1)(n+1024) for 0 < n < 1024
+ x'(i)(n) {
+ | x(i)(n) for 1024 < n < 2048
+
+
+
+Once the window shape is selected, the window_shape syntax element is
+initialized. Together with the chosen window_sequence all information needed
+for windowing exist.
+With the window halves described below all window_sequences can be assembled.
+For window_shape == 1, the window coefficients are given by the Kaiser -
+Bessel derived (KBD) window.
+Otherwise, for window_shape == 0, a sine window is employed.
+
+The window length N can be 2048 or 256 for the KBD and the sine window.
+All four window_sequences explained below have a total length of 2048
+samples.
+For all kinds of window_sequences the window_shape of the left half of
+the first transform window is determined by the window shape of the previous
+block.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This module shall implement a scheme to switch between window types and
+ in turn perform time to frequency transformations
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO 14496-3:1999, pag 111
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ IF ( wnd_seq == EIGHT_SHORT_SEQUENCE)
+ THEN
+
+
+ FOR ( wnd=0; wnd<NUM_SHORT_WINDOWS; wnd++)
+
+ time_info = &Time2Freq_data[ W_L_STOP_1 + wnd*SHORT_WINDOW]
+
+ FOR( i=0; i<SHORT_BLOCK1; i++)
+ aux_temp[i] = time_info[i]
+ ENDFOR
+
+
+ IF (wnd == 0)
+ THEN
+ pShort_Window_1 = &Short_Window[wnd_shape_prev_bk][0]
+ ELSE
+ pShort_Window_1 = &Short_Window[wnd_shape_this_bk][0]
+ ENDIF
+
+
+ pShort_Window_2 =
+ &Short_Window[wnd_shape->this_bk][SHORT_WINDOW_m_1]
+
+ FOR( i=0, j=SHORT_WINDOW; i<SHORT_WINDOW; i++, j--)
+ aux_temp[ i] *= pShort_Window_1[i]
+ aux_temp[SHORT_WINDOW+i] *= pShort_Window_2[j]
+ ENDFOR
+
+
+ CALL MDCT( aux_temp, SHORT_BLOCK1)
+ MODIFYING( aux_temp)
+
+ FOR( i=0; i<SHORT_WINDOW; i++)
+ Time2Freq_data[wnd*SHORT_WINDOW + i] = aux_temp[i];
+ ENDFOR
+
+ ENDFOR
+
+ ELSE
+
+ SWITCH ( wnd_seq)
+
+ CASE ( ONLY_LONG_SEQUENCE)
+
+ pLong_Window_1 = &Long_Window[wnd_shape_prev_bk][0]
+ pLong_Window_2 =
+ &Long_Window[wnd_shape_this_bk][LONG_WINDOW_m_1]
+
+ FOR (i=0; i<LONG_WINDOW; i++)
+ Time2Freq_data[ i] *= *pLong_Window_1++
+ Time2Freq_data[LONG_WINDOW+i] *= *pLong_Window_2--
+ ENDFOR
+
+ BREAK
+
+
+ CASE ( LONG_START_SEQUENCE)
+
+ pLong_Window_1 = &Long_Window[wnd_shape_prev_bk][0];
+
+ FOR ( i=0; i<LONG_WINDOW; i++)
+ Time2Freq_data[ i] *= *pLong_Window_1++;
+ ENDFOR
+
+
+ pShort_Window_1 =
+ &Short_Window[wnd_shape->this_bk][SHORT_WINDOW_m_1];
+
+ FOR ( i=0; i<SHORT_WINDOW; i++)
+ Time2Freq_data[W_L_START_1 + i] *= *pShort_Window_1--;
+ ENDFOR
+
+
+ FOR ( i=W_L_START_2; i<LONG_BLOCK1; i++)
+ Time2Freq_data[W_L_START_2 + i] = 0;
+ ENDFOR
+
+ BREAK
+
+
+ CASE ( LONG_STOP_SEQUENCE )
+
+ FOR ( i=0; i<W_L_STOP_1; i++)
+ Time2Freq_data[ i] = 0;
+ ENDFOR
+
+
+ pShort_Window_1 = &Short_Window[wnd_shape->prev_bk][0];
+
+ FOR ( i=0; i<SHORT_WINDOW; i++)
+ Time2Freq_data[W_L_STOP_1+ i] *= *pShort_Window_1++;
+ ENDFOR
+
+
+ pLong_Window_1 =
+ &Long_Window[wnd_shape->this_bk][LONG_WINDOW_m_1];
+
+ FOR ( i=0; i<LONG_WINDOW; i++)
+ Time2Freq_data[LONG_WINDOW + i] *= *pLong_Window_1--;
+ ENDFOR
+
+ BREAK
+
+
+ }
+
+ MDCT( Time2Freq_data, LONG_BLOCK1);
+ MODIFYING( Time2Freq_data)
+
+ ENDIF
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_audio_type_defs.h"
+#include "aac_mem_funcs.h"
+#include "window_block_fxp.h"
+#include "mdct_fxp.h"
+#include "long_term_prediction.h"
+#include "fxp_mul32.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void trans4m_time_2_freq_fxp(
+ Int32 Time2Freq_data[], /* time data size 2048 */
+ WINDOW_SEQUENCE wnd_seq, /* window sequence */
+ Int wnd_shape_prev_bk, /* window shape, current and previous */
+ Int wnd_shape_this_bk,
+ Int *pQ_format,
+ Int32 mem_4_in_place_FFT[]) /* scratch memory for computing FFT */
+{
+
+ Int i;
+
+ Int32 *pAux_temp_1;
+ Int32 *pAux_temp_2;
+ Int32 *pAux_temp;
+// Int32 temp;
+ const Int16 *pLong_Window_1;
+ const Int16 *pLong_Window_2;
+ const Int16 *pShort_Window_1;
+ const Int16 *pShort_Window_2;
+ Int shift = *pQ_format - 1;
+
+ const Int16 * Long_Window_fxp[NUM_WINDOW_SHAPES];
+ const Int16 * Short_Window_fxp[NUM_WINDOW_SHAPES];
+
+ Long_Window_fxp[0] = Long_Window_sine_fxp;
+ Long_Window_fxp[1] = Long_Window_KBD_fxp;
+ Short_Window_fxp[0] = Short_Window_sine_fxp;
+ Short_Window_fxp[1] = Short_Window_KBD_fxp;
+
+ if (wnd_seq != EIGHT_SHORT_SEQUENCE)
+ {
+
+ pAux_temp = Time2Freq_data;
+
+ *pQ_format = LTP_Q_FORMAT - *pQ_format;
+
+ pAux_temp_1 = pAux_temp;
+
+ switch (wnd_seq)
+ {
+
+ case LONG_START_SEQUENCE:
+
+ pAux_temp_2 = &pAux_temp_1[HALF_LONG_WINDOW];
+
+ pLong_Window_1 = &Long_Window_fxp[wnd_shape_prev_bk][0];
+ pLong_Window_2 = &pLong_Window_1[ HALF_LONG_WINDOW];
+
+
+
+
+ for (i = HALF_LONG_WINDOW; i > 0; i--)
+ {
+
+ *pAux_temp_1 = fxp_mul32_by_16((*pAux_temp_1), *pLong_Window_1++) >> shift;
+ pAux_temp_1++;
+ *pAux_temp_2 = fxp_mul32_by_16((*pAux_temp_2), *pLong_Window_2++) >> shift;
+ pAux_temp_2++;
+
+ }
+
+
+ /* data unchanged from LONG_WINDOW to W_L_START_1 */
+ pAux_temp_1 = &pAux_temp[LONG_WINDOW];
+ if (shift)
+ {
+ for (i = (W_L_START_1 - LONG_WINDOW) >> 1; i != 0; i--)
+ {
+ *(pAux_temp_1++) >>= shift;
+ *(pAux_temp_1++) >>= shift;
+ }
+ }
+
+
+ pAux_temp_1 = &pAux_temp[W_L_START_1];
+ pAux_temp_2 = &pAux_temp_1[HALF_SHORT_WINDOW];
+
+ pShort_Window_1 =
+ &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+
+ pShort_Window_2 = pShort_Window_1 - HALF_SHORT_WINDOW;
+
+ for (i = HALF_SHORT_WINDOW; i > 0; i--)
+ {
+
+ *pAux_temp_1 = fxp_mul32_by_16((*pAux_temp_1), *pShort_Window_1--) >> shift;
+ pAux_temp_1++;
+ *pAux_temp_2 = fxp_mul32_by_16((*pAux_temp_2), *pShort_Window_2--) >> shift;
+ pAux_temp_2++;
+
+ }
+
+ pAux_temp_1 = &pAux_temp[W_L_START_2];
+
+ pv_memset(
+ pAux_temp_1,
+ 0,
+ (LONG_BLOCK1 - W_L_START_2)*sizeof(*pAux_temp_1));
+
+ break;
+
+
+ case LONG_STOP_SEQUENCE:
+
+ pv_memset(
+ pAux_temp_1,
+ 0,
+ (W_L_STOP_1)*sizeof(*pAux_temp_1));
+
+ pShort_Window_1 = &Short_Window_fxp[wnd_shape_prev_bk][0];
+ pShort_Window_2 = &pShort_Window_1[HALF_SHORT_WINDOW];
+
+ pAux_temp_1 = &pAux_temp_1[W_L_STOP_1];
+ pAux_temp_2 = pAux_temp_1 + HALF_SHORT_WINDOW;
+
+ for (i = HALF_SHORT_WINDOW; i > 0; i--)
+ {
+
+ *pAux_temp_1 = fxp_mul32_by_16((*pAux_temp_1), *pShort_Window_1++) >> shift;
+ pAux_temp_1++;
+ *pAux_temp_2 = fxp_mul32_by_16((*pAux_temp_2), *pShort_Window_2++) >> shift;
+ pAux_temp_2++;
+
+
+ }
+
+ /* data unchanged from W_L_STOP_2 to LONG_WINDOW */
+ pAux_temp_1 = &pAux_temp[W_L_STOP_2];
+
+ if (shift)
+ {
+ for (i = ((LONG_WINDOW - W_L_STOP_2) >> 1); i != 0; i--)
+ {
+ *(pAux_temp_1++) >>= shift;
+ *(pAux_temp_1++) >>= shift;
+ }
+ }
+
+
+
+ pAux_temp_1 = &pAux_temp[LONG_WINDOW];
+ pAux_temp_2 = pAux_temp_1 + HALF_LONG_WINDOW;
+
+ pLong_Window_1 =
+ &Long_Window_fxp[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+
+ pLong_Window_2 = &pLong_Window_1[-HALF_LONG_WINDOW];
+
+ for (i = HALF_LONG_WINDOW; i > 0; i--)
+ {
+ *pAux_temp_1 = fxp_mul32_by_16((*pAux_temp_1), *pLong_Window_1--) >> shift;
+ pAux_temp_1++;
+ *pAux_temp_2 = fxp_mul32_by_16((*pAux_temp_2), *pLong_Window_2--) >> shift;
+ pAux_temp_2++;
+
+ }
+
+ break;
+
+ case ONLY_LONG_SEQUENCE:
+ default:
+
+ pAux_temp_2 = &pAux_temp[LONG_WINDOW];
+
+ pLong_Window_1 = &Long_Window_fxp[wnd_shape_prev_bk][0];
+
+
+ pLong_Window_2 =
+ &Long_Window_fxp[wnd_shape_this_bk][LONG_WINDOW_m_1];
+
+
+ for (i = LONG_WINDOW; i > 0; i--)
+ {
+
+ *pAux_temp_1 = fxp_mul32_by_16((*pAux_temp_1), *pLong_Window_1++) >> shift;
+ pAux_temp_1++;
+ *pAux_temp_2 = fxp_mul32_by_16((*pAux_temp_2), *pLong_Window_2--) >> shift;
+ pAux_temp_2++;
+ }
+
+ break;
+
+ } /* end switch ( wnd_seq) */
+
+
+
+ *pQ_format += mdct_fxp(
+ pAux_temp,
+ mem_4_in_place_FFT,
+ LONG_BLOCK1);
+
+
+ } /* end if( wnd_seq != EIGHT_SHORT_SEQUENCE) */
+
+
+
+ /*****************************************/
+ /* decoding process for short window */
+ /*****************************************/
+
+ /*
+ * For short window the following code will be applied
+ * in the future when short window is supported in the
+ * standards
+ */
+ /*-------------------------------------------------------------------------
+
+ * pAux_temp = &mem_4_in_place_FFT[(2*SHORT_BLOCK1)];
+ *
+ * for ( wnd=0; wnd<NUM_SHORT_WINDOWS; wnd++)
+ * {
+ *
+ * pShort_Window_1 = &Short_Window_fxp[wnd_shape_this_bk][0];
+ *
+ * if (wnd == 0)
+ * {
+ * pShort_Window_1 = &Short_Window_fxp[wnd_shape_prev_bk][0];
+ * }
+ *
+ * pShort_Window_2 =
+ * &Short_Window_fxp[wnd_shape_this_bk][SHORT_WINDOW_m_1];
+ *
+ * pAux_temp_1 = pAux_temp;
+ * pAux_temp_2 = pAux_temp_1 + SHORT_WINDOW;
+ *
+ * Q_aux = 0;
+ *
+ * buffer_adaptation (
+ * &Q_aux,
+ * &Time2Freq_data[ W_L_STOP_1 + wnd*SHORT_WINDOW],
+ * (void *) pAux_temp,
+ * SHORT_BLOCK1,
+ * USING_INT,
+ * 16);
+ *
+ *
+ * for ( i=SHORT_WINDOW; i>0; i--)
+ * {
+ * temp = (*pAux_temp_1) * *pShort_Window_1++;
+ * *pAux_temp_1++ = (temp + 0x08000L) >> 16;
+ *
+ * temp = (*pAux_temp_2) * *pShort_Window_2--;
+ * *pAux_temp_2++ = (temp + 0x08000L) >> 16;
+ *
+ * }
+ *
+ *
+ * exp = mdct_fxp(
+ * pAux_temp,
+ * mem_4_in_place_FFT,
+ * SHORT_BLOCK1);
+ *
+ *
+ * exp += Q_aux;
+ *
+ * pAux_temp_1 = pAux_temp;
+ * pAux_temp_2 = pAux_temp_1 + HALF_SHORT_WINDOW;
+ * pTime_data_1 = &Time2Freq_data[wnd*SHORT_WINDOW];
+ * pTime_data_2 = pTime_data_1 + HALF_SHORT_WINDOW;
+ *
+ *
+ * if (exp > 0)
+ * {
+ * for ( i=HALF_SHORT_WINDOW; i>0; i--)
+ * {
+ * *pTime_data_1++ = (*pAux_temp_1++>>exp);
+ * *pTime_data_2++ = (*pAux_temp_2++>>exp);
+ * }
+ * }
+ * else if (exp < 0)
+ * {
+ * exp = -exp;
+ * for ( i=HALF_SHORT_WINDOW; i>0; i--)
+ * {
+ * *pTime_data_1++ = (*pAux_temp_1++<<exp);
+ * *pTime_data_2++ = (*pAux_temp_2++<<exp);
+ * }
+ * }
+ * else
+ * {
+ * for ( i=HALF_SHORT_WINDOW; i>0; i--)
+ * {
+ * *pTime_data_1++ = (*pAux_temp_1++);
+ * *pTime_data_2++ = (*pAux_temp_2++);
+ * }
+ * }
+ *
+ * }
+ *
+ * }
+ *
+ *--------------------------------------------------------------------------*/
+
+} /* trans4m_time_2_freq_fxp */
diff --git a/media/libstagefright/codecs/aacdec/unpack_idx.cpp b/media/libstagefright/codecs/aacdec/unpack_idx.cpp
new file mode 100644
index 0000000..9180994
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/unpack_idx.cpp
@@ -0,0 +1,660 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./src/unpack_idx.c
+ Function: unpack_idx
+ unpack_idx_sgn
+ unpack_idx_esc
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified from original shareware code
+
+ Description: Eliminated 3 divisions and 1 multiplication through a table
+ look-up method for calculating 1/mod and constant allocation of 1/mod^3
+ and 1/mod^2.
+ Eliminated 3 additions through simple optimizations in the code.
+ Changed if/else statement to a switch/case utilizing fall-through.
+
+ Description: Made changes per review comments. Main improvements were
+ in change of switch/case to if statement, and use of temporary variable
+ to hold value of *pQuantSpec.
+
+ Description: (1) Typecast codeword_indx to Int32 before multiplication, this
+ assures the shift operation happens on a 32-bit product on
+ TI-C55x processor.
+ (2) define temp_spec as Int32 to avoid overflow
+
+ Description: Modified per review comments
+ (1) remove the two typecastings of codeword_indx when
+ pHuffCodebook->dim == DIMENSION_4
+ (2) temp_spec is Int because the result never exceeds 16 bits
+
+ Description: Break up and combine unpack index with sign bit reading and for
+ special escape code. Parent function must know which one of the
+ 3 functions should be called.
+
+ Description: Put back if-statement to get the max.
+
+ Description: When searching for the max, there was some instances where the
+ max was compared against a negative number, so the max was never
+ updated (defaulted to 0), leading to block processing in other
+ magnitude sensitive stages.
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ Int quant_spec[] = Array for storage of the quantized
+ spectral coefficients. Length is either 2 or 4.
+ See Ref #1, Page 76 for a complete description.
+
+ Int codeword_indx = The index into the Huffman table.
+ Range is [1-288]
+
+ const Hcb *pHuffCodebook = Pointer to HuffmanCodebook information.
+
+ BITS *pInputStream = Pointer to the bitstream buffer.
+ Int *max = Pointer to maximum coefficient value.
+
+ Local Stores/Buffers/Pointers Needed:
+ const UInt div_mod[18] = An array with the values for 1/mod
+ stored in Q-formats 13.
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ Int quant_spec[] = Output (the quantized and signed spectral coefficients)
+ returned via this pointer.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function decodes quantized spectral coefficients and decode their signs
+ from the input bitstream. Quantized spectral coefficients are transmitted as
+ four-tuples or 2-tuples, and this information is conveyed to the function via
+ the variable HuffCodebook->dim.
+
+ See Reference #1 for a complete description
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This function shall correctly calculate pQuantSpec[], given the inputs
+
+ codeword_indx = {1-288};
+ HuffCodebook->off = {0, 1, 4};
+ HuffCodebook->mod = {3, 8, 9, 13, 17};
+
+ mod = LAV + 1 if unsigned codebook
+ mod = 2*LAV + 1 if signed codebook
+
+ Range of values for LAV is {2,7,12,16} if unsigned
+ {1,4} if signed
+
+ Additionally,
+ LAV <= 2 if dim == 4
+
+ This restricts mod == 3 if dim == 4
+ and mod == {3, 8, 9, 13, 17} if dim == 2
+
+ This function will NOT function correctly if fed values that do not
+ meet the requirements as stated above.
+
+ This limitation on the range of values was determined by analysis
+ of Reference #1 (see below.)
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 14496-3:1999(E)
+ Part 3
+ Subpart 4.6.3.3 Decoding Process
+ Subpart 4.6.4 Tables
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ IF (pHuffCodebook->dim == 4)
+ *(pQuantSpec) = codeword_indx/(3^3);
+ codeword_indx = codeword_indx - *(pQuantSpec)*(3^3);
+ *(pQuantSpec) = *(pQuantSpec) - off;
+
+ pQuantSpec = pQuantSpec + 1;
+
+ *(pQuantSpec) = codeword_indx/(3^2);
+ codeword_indx = codeword_indx - *(pQuantSpec)*(3^2);
+ *(pQuantSpec) = *(pQuantSpec) - off;
+
+ pQuantSpec = pQuantSpec + 1;
+ ENDIF
+
+ *(pQuantSpec) = codeword_indx/mod;
+ codeword_indx = codeword_indx - (*pQuantSpec)*mod;
+ *(pQuantSpec) = *(pQuantSpec) - off;
+
+ pQuantSpec = pQuantSpec + 1;
+
+ *(pQuantSpec) = codeword_indx - off;
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_hcb.h"
+#include "ibstream.h"
+#include "unpack_idx.h"
+
+#include "fxp_mul32.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define DIV_3_CUBED 19 /* 19 = 1/27 in Q-9 format */
+#define THREE_CUBED 27 /* 27 = 3^3 */
+
+#define DIV_3_SQUARED 57 /* 57 = 1/9 in Q-9 format */
+#define THREE_SQUARED 9 /* 9 = 3^2 */
+
+#define Q_FORMAT_MOD 13 /* Q-format for 1/mod table */
+#define Q_FORMAT_MOD2 9 /* Q-format for DIV_3_SQUARED */
+#define Q_FORMAT_MOD3 9 /* Q-format for DIV_3_CUBED */
+
+#define LOWER_5_BITS_MASK 0x1F
+
+
+#if ( defined(PV_ARM_V5) || defined(PV_ARM_V4))
+
+__inline Int32 abs1(Int32 x)
+{
+ Int32 z;
+ /*
+ z = x - (x<0);
+ x = z ^ sign(z)
+ */
+ __asm
+ {
+ sub z, x, x, lsr #31
+ eor x, z, z, asr #31
+ }
+ return (x);
+}
+
+#define pv_abs(x) abs1(x)
+
+
+#else
+
+#define pv_abs(x) ((x) > 0)? (x) : (-x)
+
+#endif
+
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------
+ Possible values for mod = {3,8,9,13,17}
+
+ There exists "empty" spaces in the table. These can potentially
+ be utilized by other const tables, if available memory becomes an issue.
+---------------------------------------------------------------------------*/
+
+const Int div_mod[18] = /* mod index Q-format */
+{
+ /* ----------------------- */
+ 0xCC, /* | | 0 | */
+ 0xCC, /* | | 1 | */
+ 0xCC, /* | | 2 | */
+ 2731, /* | 3 | 3 | 13 */
+ 0xCC, /* | | 4 | */
+ 0xCC, /* | | 5 | */
+ 0xCC, /* | | 6 | */
+ 0xCC, /* | | 7 | */
+ 1025, /* | 8 | 8 | 13 */
+ 911, /* | 9 | 9 | 13 */
+ 0xCC, /* | | 10 | */
+ 0xCC, /* | | 11 | */
+ 0xCC, /* | | 12 | */
+ 631, /* | 13 | 13 | 13 */
+ 0xCC, /* | | 14 | */
+ 0xCC, /* | | 15 | */
+ 0xCC, /* | | 16 | */
+ 482, /* | 17 | 17 | 13 */
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void unpack_idx(
+ Int16 quant_spec[],
+ Int codeword_indx,
+ const Hcb *pHuffCodebook,
+ BITS *pInputStream,
+ Int *max)
+{
+ Int16 *pQuantSpec = &quant_spec[0];
+ Int temp_spec;
+
+ const Int mod = pHuffCodebook->mod;
+ const Int off = pHuffCodebook->off;
+
+ OSCL_UNUSED_ARG(pInputStream);
+
+
+ if (pHuffCodebook->dim == DIMENSION_4)
+ {
+ /* Calculate pQuantSpec[0] */
+
+ temp_spec = (codeword_indx * DIV_3_CUBED) >> Q_FORMAT_MOD3;
+
+ codeword_indx -= temp_spec * THREE_CUBED;
+
+ temp_spec -= off;
+ *pQuantSpec++ = (Int16)temp_spec;
+
+ temp_spec = pv_abs(temp_spec);
+
+ if (temp_spec > *max)
+ {
+ *max = temp_spec;
+ }
+
+ /* Calculate pQuantSpec[1] */
+ temp_spec = (codeword_indx * DIV_3_SQUARED) >> Q_FORMAT_MOD2;
+
+ codeword_indx -= temp_spec * THREE_SQUARED;
+
+ temp_spec -= off;
+ *pQuantSpec++ = (Int16)temp_spec;
+
+ temp_spec = pv_abs(temp_spec);
+
+ if (temp_spec > *max)
+ {
+ *max = temp_spec;
+ }
+ }
+
+ /*
+ * Calculate pQuantSpec[2] if dim == 4
+ * Calculate pQuantSpec[0] if dim == 2
+ */
+
+ temp_spec = ((Int32) codeword_indx * div_mod[mod]) >> Q_FORMAT_MOD;
+
+ codeword_indx -= temp_spec * mod;
+
+ temp_spec -= off;
+ *pQuantSpec++ = (Int16)temp_spec;
+
+ temp_spec = pv_abs(temp_spec);
+
+
+ if (temp_spec > *max)
+ {
+ *max = temp_spec;
+ }
+
+ /*
+ * Calculate pQuantSpec[3] if dim == 4
+ * Calculate pQuantSpec[1] if dim == 2
+ */
+ codeword_indx -= off;
+ *pQuantSpec = (Int16)codeword_indx ;
+
+
+ codeword_indx = pv_abs(codeword_indx);
+
+ if (codeword_indx > *max)
+ {
+ *max = codeword_indx;
+ }
+
+
+ return ;
+} /* unpack_idx */
+
+
+void unpack_idx_sgn(
+ Int16 quant_spec[],
+ Int codeword_indx,
+ const Hcb *pHuffCodebook,
+ BITS *pInputStream,
+ Int *max)
+{
+ Int16 *pQuantSpec = &quant_spec[0];
+ Int temp_spec;
+ Int sgn;
+
+ const Int mod = pHuffCodebook->mod;
+ const Int off = pHuffCodebook->off;
+
+
+
+ if (pHuffCodebook->dim == DIMENSION_4)
+ {
+ /* Calculate pQuantSpec[0] */
+ preload_cache((Int32 *)pQuantSpec);
+ temp_spec = (codeword_indx * DIV_3_CUBED) >> Q_FORMAT_MOD3;
+
+ codeword_indx -= temp_spec * THREE_CUBED;
+
+ temp_spec -= off;
+ if (temp_spec)
+ {
+ sgn = get1bits(pInputStream);
+
+
+ *pQuantSpec++ = (Int16)((sgn) ? -temp_spec : temp_spec);
+
+ temp_spec = pv_abs(temp_spec);
+
+ if (temp_spec > *max)
+ {
+ *max = temp_spec;
+ }
+
+ }
+ else
+ {
+ *pQuantSpec++ = 0;
+ }
+
+ /* Calculate pQuantSpec[1] */
+ temp_spec = (codeword_indx * DIV_3_SQUARED) >> Q_FORMAT_MOD2;
+
+ codeword_indx -= temp_spec * THREE_SQUARED;
+
+ temp_spec -= off;
+ if (temp_spec)
+ {
+
+ sgn = get1bits(pInputStream);
+
+ *pQuantSpec++ = (Int16)((sgn) ? -temp_spec : temp_spec);
+
+ temp_spec = pv_abs(temp_spec);
+
+ if (temp_spec > *max)
+ {
+ *max = temp_spec;
+ }
+ }
+ else
+ {
+ *pQuantSpec++ = 0;
+ }
+ }
+
+ /*
+ * Calculate pQuantSpec[2] if dim == 4
+ * Calculate pQuantSpec[0] if dim == 2
+ */
+
+ temp_spec = ((Int32) codeword_indx * div_mod[mod]) >> Q_FORMAT_MOD;
+
+ codeword_indx -= temp_spec * mod;
+
+ temp_spec -= off;
+ if (temp_spec)
+ {
+
+ sgn = get1bits(pInputStream);
+
+ *pQuantSpec++ = (Int16)((sgn) ? -temp_spec : temp_spec);
+
+ temp_spec = pv_abs(temp_spec);
+
+ if (temp_spec > *max)
+ {
+ *max = temp_spec;
+ }
+ }
+ else
+ {
+ *pQuantSpec++ = 0;
+ }
+
+ /*
+ * Calculate pQuantSpec[3] if dim == 4
+ * Calculate pQuantSpec[1] if dim == 2
+ */
+ codeword_indx -= off;
+ if (codeword_indx)
+ {
+
+ sgn = get1bits(pInputStream);
+
+ *pQuantSpec = (Int16)((sgn) ? -codeword_indx : codeword_indx);
+
+ codeword_indx = pv_abs(codeword_indx);
+
+ if (codeword_indx > *max)
+ {
+ *max = codeword_indx;
+ }
+ }
+ else
+ {
+ *pQuantSpec = 0;
+ }
+
+ return ;
+} /* unpack_idx_sgn */
+
+
+void unpack_idx_esc(
+ Int16 quant_spec[],
+ Int codeword_indx,
+ const Hcb *pHuffCodebook,
+ BITS *pInputStream,
+ Int *max)
+{
+ Int temp_spec;
+ Int sgn1 = 0, sgn2 = 0;
+ Int N;
+ Int32 esc_seq;
+
+ const Int mod = pHuffCodebook->mod;
+ const Int off = pHuffCodebook->off;
+
+
+ temp_spec = ((Int32) codeword_indx * div_mod[mod]) >> Q_FORMAT_MOD;
+
+ codeword_indx -= temp_spec * mod;
+
+ temp_spec -= off;
+ if (temp_spec)
+ {
+ sgn1 = get1bits(pInputStream);
+ }
+
+ codeword_indx -= off;
+ if (codeword_indx)
+ {
+ sgn2 = get1bits(pInputStream);
+ }
+
+
+ if ((temp_spec & LOWER_5_BITS_MASK) == 16)
+ {
+ N = 3;
+ do
+ {
+ N++;
+
+ esc_seq = get1bits(pInputStream);
+
+ }
+ while (esc_seq != 0);
+
+ esc_seq = getbits(N, pInputStream);
+
+ esc_seq += (1 << N);
+
+
+ temp_spec = (Int)((temp_spec * esc_seq) >> 4);
+
+ }
+
+
+ if (sgn1)
+ {
+ quant_spec[0] = (Int16)(-temp_spec);
+ }
+ else
+ {
+ quant_spec[0] = (Int16)temp_spec;
+ }
+
+ temp_spec = pv_abs(temp_spec);
+
+ if (temp_spec > *max)
+ {
+ *max = temp_spec;
+ }
+
+ if ((codeword_indx & LOWER_5_BITS_MASK) == 16)
+ {
+ N = 3;
+ do
+ {
+ N++;
+
+ esc_seq = get1bits(pInputStream);
+
+ }
+ while (esc_seq != 0);
+
+ esc_seq = getbits(N, pInputStream);
+
+ esc_seq += (1 << N);
+
+ codeword_indx = (Int)((codeword_indx * esc_seq) >> 4);
+ }
+
+
+
+
+ if (sgn2)
+ {
+ quant_spec[1] = (Int16)(-codeword_indx);
+ }
+ else
+ {
+ quant_spec[1] = (Int16)codeword_indx;
+ }
+
+
+ codeword_indx = pv_abs(codeword_indx);
+
+ if (codeword_indx > *max)
+ {
+ *max = codeword_indx;
+ }
+
+
+ return ;
+} /* unpack_idx_esc */
diff --git a/media/libstagefright/codecs/aacdec/unpack_idx.h b/media/libstagefright/codecs/aacdec/unpack_idx.h
new file mode 100644
index 0000000..a308c4a
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/unpack_idx.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: ./include/unpack_idx.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This header file includes the function definition for unpack_idx()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef UNPACK_IDX_H
+#define UNPACK_IDX_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "s_hcb.h"
+#include "s_bits.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define DIMENSION_4 4
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ void unpack_idx(
+ Int16 QuantSpec[],
+ Int codeword_indx,
+ const Hcb *pHuffCodebook,
+ BITS *pInputStream,
+ Int *max);
+ void unpack_idx_sgn(
+ Int16 quant_spec[],
+ Int codeword_indx,
+ const Hcb *pHuffCodebook,
+ BITS *pInputStream,
+ Int *max);
+ void unpack_idx_esc(
+ Int16 quant_spec[],
+ Int codeword_indx,
+ const Hcb *pHuffCodebook,
+ BITS *pInputStream,
+ Int *max);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/aacdec/window_block_fxp.h b/media/libstagefright/codecs/aacdec/window_block_fxp.h
new file mode 100644
index 0000000..f936199
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/window_block_fxp.h
@@ -0,0 +1,231 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: window_block_fxp.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ modified function definition: Time_data from Int to Int32
+ change wnd_shape from structure to passing parameters
+ delete definition of wnd_shape1, not needed.
+
+ Description: Modified based on unit test comments
+
+ Description: Change copyright, add () around constants.
+
+ Description:
+ changed Long_Window_fxp and Short _Window_fxp tables definition, from
+ "const UInt16 *" to "const UInt16 * const" to avoid global variable
+ definition.
+
+ Description: Updated function trans4m_freq_2_time_fxp definition
+
+ Description: Modified function interface to add output_buffer
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for window and block switch
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (1) ISO/IEC 13818-7 Part 7: Advanced Audo Coding (AAC)
+
+
+ (2) MPEG-2 NBC Audio Decoder
+ "This software module was originally developed by AT&T, Dolby
+ Laboratories, Fraunhofer Gesellschaft IIS in the course of development
+ of the MPEG-2 NBC/MPEG-4 Audio standard ISO/IEC 13818-7, 14496-1,2 and
+ 3. This software module is an implementation of a part of one or more
+ MPEG-2 NBC/MPEG-4 Audio tools as specified by the MPEG-2 NBC/MPEG-4
+ Audio standard. ISO/IEC gives users of the MPEG-2 NBC/MPEG-4 Audio
+ standards free license to this software module or modifications thereof
+ for use in hardware or software products claiming conformance to the
+ MPEG-2 NBC/MPEG-4 Audio standards. Those intending to use this software
+ module in hardware or software products are advised that this 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-2 NBC/MPEG-4 Audio conforming products.The original
+ developer retains full right to use the code for his/her own purpose,
+ assign or donate the code to a third party and to inhibit third party
+ from using the code for non MPEG-2 NBC/MPEG-4 Audio conforming products.
+ This copyright notice must be included in all copies or derivative
+ works."
+ Copyright(c)1996.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef WINDOW_BLOCK_FXP_H
+#define WINDOW_BLOCK_FXP_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "e_window_shape.h"
+#include "e_window_sequence.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define LONG_WINDOW (1024)
+#define SHORT_WINDOW (128)
+
+#define HALF_LONG_WINDOW (LONG_WINDOW>>1)
+#define HALF_SHORT_WINDOW (SHORT_WINDOW>>1)
+
+#define NUM_SHORT_WINDOWS (8)
+#define LONG_WINDOW_m_1 (LONG_WINDOW-1)
+#define SHORT_WINDOW_m_1 (SHORT_WINDOW-1)
+
+ /*
+ * Limits for window sequences, they are used to build
+ * each long window, they are defined in the standards
+ */
+#define W_L_START_1 ((3*LONG_WINDOW - SHORT_WINDOW)>>1)
+#define W_L_START_2 ((3*LONG_WINDOW + SHORT_WINDOW)>>1)
+#define W_L_STOP_1 ((LONG_WINDOW - SHORT_WINDOW)>>1)
+#define W_L_STOP_2 ((LONG_WINDOW + SHORT_WINDOW)>>1)
+
+
+#define LONG_BLOCK1 (2*LONG_WINDOW)
+#define SHORT_BLOCK1 (2*SHORT_WINDOW)
+
+
+#define SCALING 10
+#define ROUNDING (1<<(SCALING-1))
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Int16 Short_Window_KBD_fxp[ SHORT_WINDOW];
+ extern const Int16 Long_Window_KBD_fxp[ LONG_WINDOW];
+ extern const Int16 Short_Window_sine_fxp[ SHORT_WINDOW];
+ extern const Int16 Long_Window_sine_fxp[ LONG_WINDOW];
+
+ extern const Int16 * const Long_Window_fxp[];
+ extern const Int16 * const Short_Window_fxp[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void trans4m_freq_2_time_fxp(
+ Int32 Frequency_data[],
+ Int32 Time_data[],
+#ifdef AAC_PLUS
+ Int32 Output_buffer[],
+#else
+ Int16 Output_buffer[],
+#endif
+ WINDOW_SEQUENCE wnd_seq,
+ Int wnd_shape_prev_bk,
+ Int wnd_shape_this_bk,
+ Int Q_format,
+ Int32 abs_max_per_window[],
+ Int32 freq_2_time_buffer[] ,
+ Int16 *Interleave_output
+ );
+
+
+
+ void trans4m_freq_2_time_fxp_1(
+ Int32 Frequency_data[],
+ Int32 Time_data[],
+ Int16 Output_buffer[],
+ WINDOW_SEQUENCE wnd_seq,
+ Int wnd_shape_prev_bk,
+ Int wnd_shape_this_bk,
+ Int Q_format,
+ Int32 abs_max_per_window[],
+ Int32 freq_2_time_buffer[]
+ );
+
+
+ void trans4m_freq_2_time_fxp_2(
+ Int32 Frequency_data[],
+ Int32 Time_data[],
+ WINDOW_SEQUENCE wnd_seq,
+ Int wnd_shape_prev_bk,
+ Int wnd_shape_this_bk,
+ Int Q_format,
+ Int32 abs_max_per_window[],
+ Int32 freq_2_time_buffer[] ,
+ Int16 *Interleave_output
+ );
+
+ void trans4m_time_2_freq_fxp(
+ Int32 Time2Freq_data[],
+ WINDOW_SEQUENCE wnd_seq,
+ Int wnd_shape_prev_bk,
+ Int wnd_shape_this_bk,
+ Int *pQ_format,
+ Int32 mem_4_in_place_FFT[]);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WINDOW_BLOCK_FXP_H */
+
diff --git a/media/libstagefright/codecs/aacdec/window_tables_fxp.cpp b/media/libstagefright/codecs/aacdec/window_tables_fxp.cpp
new file mode 100644
index 0000000..aa04225
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/window_tables_fxp.cpp
@@ -0,0 +1,730 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: window_tables_fxp.c
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ changed table content definition from UInt to UInt16.
+
+ Description:
+ changed Long_Window_fxp and Short _Window_fxp tables definition, from
+ "const UInt16 *" to "const UInt16 * const" to avoid global variable
+ definition.
+
+ Description:
+ Improved rounding on table elements.
+
+ Description: Eliminated structure to avoid assigning addresses to constant
+ tables. This solve linking problem when using the
+ /ropi option (Read-only position independent) for some
+ compilers
+ - Eliminated Long_Window_fxp and Short_Window_fxp as global
+ contants vectors
+
+ Who: Date:
+ Description:
+
+ ------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Window tables
+
+ For a sine table with N points:
+
+ w_left = sin(pi/N (n + 1/2)) for 0 =< n < N/2
+
+ w_rigth = sin(pi/N (n + 1/2)) for N/2 =< n < N
+
+
+ For Kaiser-Bessel derived (KBD)
+
+ n N/2
+ w_left = sqrt(( SUM W(p,a) )/( SUM W(p,a) ) for 0 =< n < N/2
+ p=0 p=0
+
+
+ N-n-1 N/2
+ w_rigth = sqrt(( SUM W(p,a) )/( SUM W(p,a) ) for N/2 =< n < N
+ p=0 p=0
+
+
+ W(p,a) see ISO 14496-3, pag 113
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ This module shall implement the fix point verwion of the windowing tables
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO 14496-3, pag 113
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_audio_type_defs.h"
+#include "window_block_fxp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+const Int16 Long_Window_sine_fxp[LONG_WINDOW] =
+{
+
+
+ 0x0019, 0x004B, 0x007E, 0x00B0,
+ 0x00E2, 0x0114, 0x0147, 0x0179,
+ 0x01AB, 0x01DD, 0x0210, 0x0242,
+ 0x0274, 0x02A7, 0x02D9, 0x030B,
+ 0x033D, 0x0370, 0x03A2, 0x03D4,
+ 0x0406, 0x0438, 0x046B, 0x049D,
+ 0x04CF, 0x0501, 0x0534, 0x0566,
+ 0x0598, 0x05CA, 0x05FC, 0x062F,
+ 0x0661, 0x0693, 0x06C5, 0x06F7,
+ 0x072A, 0x075C, 0x078E, 0x07C0,
+ 0x07F2, 0x0825, 0x0857, 0x0889,
+ 0x08BB, 0x08ED, 0x091F, 0x0951,
+ 0x0984, 0x09B6, 0x09E8, 0x0A1A,
+ 0x0A4C, 0x0A7E, 0x0AB0, 0x0AE2,
+ 0x0B14, 0x0B46, 0x0B78, 0x0BAB,
+ 0x0BDD, 0x0C0F, 0x0C41, 0x0C73,
+ 0x0CA5, 0x0CD7, 0x0D09, 0x0D3B,
+ 0x0D6D, 0x0D9F, 0x0DD1, 0x0E03,
+ 0x0E35, 0x0E67, 0x0E99, 0x0ECA,
+ 0x0EFC, 0x0F2E, 0x0F60, 0x0F92,
+ 0x0FC4, 0x0FF6, 0x1028, 0x105A,
+ 0x108B, 0x10BD, 0x10EF, 0x1121,
+ 0x1153, 0x1185, 0x11B6, 0x11E8,
+ 0x121A, 0x124C, 0x127D, 0x12AF,
+ 0x12E1, 0x1312, 0x1344, 0x1376,
+ 0x13A8, 0x13D9, 0x140B, 0x143C,
+ 0x146E, 0x14A0, 0x14D1, 0x1503,
+ 0x1534, 0x1566, 0x1598, 0x15C9,
+ 0x15FB, 0x162C, 0x165E, 0x168F,
+ 0x16C1, 0x16F2, 0x1724, 0x1755,
+ 0x1786, 0x17B8, 0x17E9, 0x181B,
+ 0x184C, 0x187D, 0x18AF, 0x18E0,
+ 0x1911, 0x1942, 0x1974, 0x19A5,
+ 0x19D6, 0x1A07, 0x1A39, 0x1A6A,
+ 0x1A9B, 0x1ACC, 0x1AFD, 0x1B2E,
+ 0x1B60, 0x1B91, 0x1BC2, 0x1BF3,
+ 0x1C24, 0x1C55, 0x1C86, 0x1CB7,
+ 0x1CE8, 0x1D19, 0x1D4A, 0x1D7B,
+ 0x1DAC, 0x1DDC, 0x1E0D, 0x1E3E,
+ 0x1E6F, 0x1EA0, 0x1ED1, 0x1F01,
+ 0x1F32, 0x1F63, 0x1F94, 0x1FC4,
+ 0x1FF5, 0x2026, 0x2056, 0x2087,
+ 0x20B7, 0x20E8, 0x2119, 0x2149,
+ 0x217A, 0x21AA, 0x21DB, 0x220B,
+ 0x223C, 0x226C, 0x229C, 0x22CD,
+ 0x22FD, 0x232E, 0x235E, 0x238E,
+ 0x23BE, 0x23EF, 0x241F, 0x244F,
+ 0x247F, 0x24AF, 0x24E0, 0x2510,
+ 0x2540, 0x2570, 0x25A0, 0x25D0,
+ 0x2600, 0x2630, 0x2660, 0x2690,
+ 0x26C0, 0x26F0, 0x2720, 0x274F,
+ 0x277F, 0x27AF, 0x27DF, 0x280F,
+ 0x283E, 0x286E, 0x289E, 0x28CD,
+ 0x28FD, 0x292D, 0x295C, 0x298C,
+ 0x29BB, 0x29EB, 0x2A1A, 0x2A4A,
+ 0x2A79, 0x2AA8, 0x2AD8, 0x2B07,
+ 0x2B37, 0x2B66, 0x2B95, 0x2BC4,
+ 0x2BF4, 0x2C23, 0x2C52, 0x2C81,
+ 0x2CB0, 0x2CDF, 0x2D0E, 0x2D3D,
+ 0x2D6C, 0x2D9B, 0x2DCA, 0x2DF9,
+ 0x2E28, 0x2E57, 0x2E86, 0x2EB5,
+ 0x2EE3, 0x2F12, 0x2F41, 0x2F70,
+ 0x2F9E, 0x2FCD, 0x2FFC, 0x302A,
+ 0x3059, 0x3087, 0x30B6, 0x30E4,
+ 0x3113, 0x3141, 0x316F, 0x319E,
+ 0x31CC, 0x31FA, 0x3229, 0x3257,
+ 0x3285, 0x32B3, 0x32E1, 0x330F,
+ 0x333E, 0x336C, 0x339A, 0x33C8,
+ 0x33F6, 0x3423, 0x3451, 0x347F,
+ 0x34AD, 0x34DB, 0x3509, 0x3536,
+ 0x3564, 0x3592, 0x35BF, 0x35ED,
+ 0x361A, 0x3648, 0x3676, 0x36A3,
+ 0x36D0, 0x36FE, 0x372B, 0x3759,
+ 0x3786, 0x37B3, 0x37E0, 0x380E,
+ 0x383B, 0x3868, 0x3895, 0x38C2,
+ 0x38EF, 0x391C, 0x3949, 0x3976,
+ 0x39A3, 0x39D0, 0x39FD, 0x3A29,
+ 0x3A56, 0x3A83, 0x3AB0, 0x3ADC,
+ 0x3B09, 0x3B35, 0x3B62, 0x3B8E,
+ 0x3BBB, 0x3BE7, 0x3C14, 0x3C40,
+ 0x3C6C, 0x3C99, 0x3CC5, 0x3CF1,
+ 0x3D1D, 0x3D4A, 0x3D76, 0x3DA2,
+ 0x3DCE, 0x3DFA, 0x3E26, 0x3E52,
+ 0x3E7D, 0x3EA9, 0x3ED5, 0x3F01,
+ 0x3F2D, 0x3F58, 0x3F84, 0x3FB0,
+ 0x3FDB, 0x4007, 0x4032, 0x405E,
+ 0x4089, 0x40B5, 0x40E0, 0x410B,
+ 0x4136, 0x4162, 0x418D, 0x41B8,
+ 0x41E3, 0x420E, 0x4239, 0x4264,
+ 0x428F, 0x42BA, 0x42E5, 0x4310,
+ 0x433B, 0x4365, 0x4390, 0x43BB,
+ 0x43E5, 0x4410, 0x443B, 0x4465,
+ 0x448F, 0x44BA, 0x44E4, 0x450F,
+ 0x4539, 0x4563, 0x458D, 0x45B8,
+ 0x45E2, 0x460C, 0x4636, 0x4660,
+ 0x468A, 0x46B4, 0x46DE, 0x4707,
+ 0x4731, 0x475B, 0x4785, 0x47AE,
+ 0x47D8, 0x4802, 0x482B, 0x4855,
+ 0x487E, 0x48A7, 0x48D1, 0x48FA,
+ 0x4923, 0x494D, 0x4976, 0x499F,
+ 0x49C8, 0x49F1, 0x4A1A, 0x4A43,
+ 0x4A6C, 0x4A95, 0x4ABE, 0x4AE6,
+ 0x4B0F, 0x4B38, 0x4B61, 0x4B89,
+ 0x4BB2, 0x4BDA, 0x4C03, 0x4C2B,
+ 0x4C53, 0x4C7C, 0x4CA4, 0x4CCC,
+ 0x4CF4, 0x4D1D, 0x4D45, 0x4D6D,
+ 0x4D95, 0x4DBD, 0x4DE5, 0x4E0D,
+ 0x4E34, 0x4E5C, 0x4E84, 0x4EAB,
+ 0x4ED3, 0x4EFB, 0x4F22, 0x4F4A,
+ 0x4F71, 0x4F99, 0x4FC0, 0x4FE7,
+ 0x500E, 0x5036, 0x505D, 0x5084,
+ 0x50AB, 0x50D2, 0x50F9, 0x5120,
+ 0x5147, 0x516D, 0x5194, 0x51BB,
+ 0x51E2, 0x5208, 0x522F, 0x5255,
+ 0x527C, 0x52A2, 0x52C8, 0x52EF,
+ 0x5315, 0x533B, 0x5361, 0x5387,
+ 0x53AE, 0x53D4, 0x53FA, 0x541F,
+ 0x5445, 0x546B, 0x5491, 0x54B7,
+ 0x54DC, 0x5502, 0x5527, 0x554D,
+ 0x5572, 0x5598, 0x55BD, 0x55E2,
+ 0x5608, 0x562D, 0x5652, 0x5677,
+ 0x569C, 0x56C1, 0x56E6, 0x570B,
+ 0x5730, 0x5754, 0x5779, 0x579E,
+ 0x57C2, 0x57E7, 0x580C, 0x5830,
+ 0x5854, 0x5879, 0x589D, 0x58C1,
+ 0x58E5, 0x590A, 0x592E, 0x5952,
+ 0x5976, 0x599A, 0x59BD, 0x59E1,
+ 0x5A05, 0x5A29, 0x5A4C, 0x5A70,
+ 0x5A94, 0x5AB7, 0x5ADA, 0x5AFE,
+ 0x5B21, 0x5B44, 0x5B68, 0x5B8B,
+ 0x5BAE, 0x5BD1, 0x5BF4, 0x5C17,
+ 0x5C3A, 0x5C5D, 0x5C7F, 0x5CA2,
+ 0x5CC5, 0x5CE7, 0x5D0A, 0x5D2C,
+ 0x5D4F, 0x5D71, 0x5D94, 0x5DB6,
+ 0x5DD8, 0x5DFA, 0x5E1C, 0x5E3E,
+ 0x5E60, 0x5E82, 0x5EA4, 0x5EC6,
+ 0x5EE8, 0x5F09, 0x5F2B, 0x5F4D,
+ 0x5F6E, 0x5F90, 0x5FB1, 0x5FD2,
+ 0x5FF4, 0x6015, 0x6036, 0x6057,
+ 0x6078, 0x6099, 0x60BA, 0x60DB,
+ 0x60FC, 0x611D, 0x613D, 0x615E,
+ 0x617F, 0x619F, 0x61C0, 0x61E0,
+ 0x6200, 0x6221, 0x6241, 0x6261,
+ 0x6281, 0x62A1, 0x62C1, 0x62E1,
+ 0x6301, 0x6321, 0x6341, 0x6360,
+ 0x6380, 0x63A0, 0x63BF, 0x63DF,
+ 0x63FE, 0x641D, 0x643D, 0x645C,
+ 0x647B, 0x649A, 0x64B9, 0x64D8,
+ 0x64F7, 0x6516, 0x6535, 0x6554,
+ 0x6572, 0x6591, 0x65AF, 0x65CE,
+ 0x65EC, 0x660B, 0x6629, 0x6647,
+ 0x6666, 0x6684, 0x66A2, 0x66C0,
+ 0x66DE, 0x66FC, 0x6719, 0x6737,
+ 0x6755, 0x6772, 0x6790, 0x67AE,
+ 0x67CB, 0x67E8, 0x6806, 0x6823,
+ 0x6840, 0x685D, 0x687A, 0x6897,
+ 0x68B4, 0x68D1, 0x68EE, 0x690B,
+ 0x6927, 0x6944, 0x6961, 0x697D,
+ 0x699A, 0x69B6, 0x69D2, 0x69EE,
+ 0x6A0B, 0x6A27, 0x6A43, 0x6A5F,
+ 0x6A7B, 0x6A97, 0x6AB2, 0x6ACE,
+ 0x6AEA, 0x6B05, 0x6B21, 0x6B3C,
+ 0x6B58, 0x6B73, 0x6B8E, 0x6BAA,
+ 0x6BC5, 0x6BE0, 0x6BFB, 0x6C16,
+ 0x6C31, 0x6C4C, 0x6C66, 0x6C81,
+ 0x6C9C, 0x6CB6, 0x6CD1, 0x6CEB,
+ 0x6D06, 0x6D20, 0x6D3A, 0x6D54,
+ 0x6D6E, 0x6D88, 0x6DA2, 0x6DBC,
+ 0x6DD6, 0x6DF0, 0x6E0A, 0x6E23,
+ 0x6E3D, 0x6E56, 0x6E70, 0x6E89,
+ 0x6EA2, 0x6EBC, 0x6ED5, 0x6EEE,
+ 0x6F07, 0x6F20, 0x6F39, 0x6F52,
+ 0x6F6B, 0x6F83, 0x6F9C, 0x6FB4,
+ 0x6FCD, 0x6FE5, 0x6FFE, 0x7016,
+ 0x702E, 0x7046, 0x705F, 0x7077,
+ 0x708F, 0x70A6, 0x70BE, 0x70D6,
+ 0x70EE, 0x7105, 0x711D, 0x7134,
+ 0x714C, 0x7163, 0x717A, 0x7192,
+ 0x71A9, 0x71C0, 0x71D7, 0x71EE,
+ 0x7205, 0x721C, 0x7232, 0x7249,
+ 0x7260, 0x7276, 0x728D, 0x72A3,
+ 0x72B9, 0x72D0, 0x72E6, 0x72FC,
+ 0x7312, 0x7328, 0x733E, 0x7354,
+ 0x7369, 0x737F, 0x7395, 0x73AA,
+ 0x73C0, 0x73D5, 0x73EB, 0x7400,
+ 0x7415, 0x742A, 0x743F, 0x7454,
+ 0x7469, 0x747E, 0x7493, 0x74A8,
+ 0x74BC, 0x74D1, 0x74E5, 0x74FA,
+ 0x750E, 0x7522, 0x7537, 0x754B,
+ 0x755F, 0x7573, 0x7587, 0x759B,
+ 0x75AE, 0x75C2, 0x75D6, 0x75E9,
+ 0x75FD, 0x7610, 0x7624, 0x7637,
+ 0x764A, 0x765E, 0x7671, 0x7684,
+ 0x7697, 0x76A9, 0x76BC, 0x76CF,
+ 0x76E2, 0x76F4, 0x7707, 0x7719,
+ 0x772C, 0x773E, 0x7750, 0x7762,
+ 0x7774, 0x7786, 0x7798, 0x77AA,
+ 0x77BC, 0x77CE, 0x77DF, 0x77F1,
+ 0x7803, 0x7814, 0x7825, 0x7837,
+ 0x7848, 0x7859, 0x786A, 0x787B,
+ 0x788C, 0x789D, 0x78AE, 0x78BE,
+ 0x78CF, 0x78E0, 0x78F0, 0x7901,
+ 0x7911, 0x7921, 0x7931, 0x7941,
+ 0x7952, 0x7962, 0x7971, 0x7981,
+ 0x7991, 0x79A1, 0x79B0, 0x79C0,
+ 0x79CF, 0x79DF, 0x79EE, 0x79FD,
+ 0x7A0D, 0x7A1C, 0x7A2B, 0x7A3A,
+ 0x7A49, 0x7A57, 0x7A66, 0x7A75,
+ 0x7A83, 0x7A92, 0x7AA0, 0x7AAF,
+ 0x7ABD, 0x7ACB, 0x7AD9, 0x7AE7,
+ 0x7AF5, 0x7B03, 0x7B11, 0x7B1F,
+ 0x7B2D, 0x7B3A, 0x7B48, 0x7B55,
+ 0x7B63, 0x7B70, 0x7B7D, 0x7B8B,
+ 0x7B98, 0x7BA5, 0x7BB2, 0x7BBF,
+ 0x7BCB, 0x7BD8, 0x7BE5, 0x7BF1,
+ 0x7BFE, 0x7C0A, 0x7C17, 0x7C23,
+ 0x7C2F, 0x7C3B, 0x7C47, 0x7C53,
+ 0x7C5F, 0x7C6B, 0x7C77, 0x7C83,
+ 0x7C8E, 0x7C9A, 0x7CA5, 0x7CB1,
+ 0x7CBC, 0x7CC7, 0x7CD2, 0x7CDD,
+ 0x7CE8, 0x7CF3, 0x7CFE, 0x7D09,
+ 0x7D14, 0x7D1E, 0x7D29, 0x7D33,
+ 0x7D3E, 0x7D48, 0x7D52, 0x7D5C,
+ 0x7D67, 0x7D71, 0x7D7B, 0x7D84,
+ 0x7D8E, 0x7D98, 0x7DA2, 0x7DAB,
+ 0x7DB5, 0x7DBE, 0x7DC8, 0x7DD1,
+ 0x7DDA, 0x7DE3, 0x7DEC, 0x7DF5,
+ 0x7DFE, 0x7E07, 0x7E10, 0x7E18,
+ 0x7E21, 0x7E29, 0x7E32, 0x7E3A,
+ 0x7E42, 0x7E4B, 0x7E53, 0x7E5B,
+ 0x7E63, 0x7E6B, 0x7E73, 0x7E7A,
+ 0x7E82, 0x7E8A, 0x7E91, 0x7E99,
+ 0x7EA0, 0x7EA7, 0x7EAF, 0x7EB6,
+ 0x7EBD, 0x7EC4, 0x7ECB, 0x7ED2,
+ 0x7ED8, 0x7EDF, 0x7EE6, 0x7EEC,
+ 0x7EF3, 0x7EF9, 0x7EFF, 0x7F05,
+ 0x7F0C, 0x7F12, 0x7F18, 0x7F1E,
+ 0x7F23, 0x7F29, 0x7F2F, 0x7F35,
+ 0x7F3A, 0x7F40, 0x7F45, 0x7F4A,
+ 0x7F50, 0x7F55, 0x7F5A, 0x7F5F,
+ 0x7F64, 0x7F69, 0x7F6D, 0x7F72,
+ 0x7F77, 0x7F7B, 0x7F80, 0x7F84,
+ 0x7F88, 0x7F8D, 0x7F91, 0x7F95,
+ 0x7F99, 0x7F9D, 0x7FA1, 0x7FA4,
+ 0x7FA8, 0x7FAC, 0x7FAF, 0x7FB3,
+ 0x7FB6, 0x7FB9, 0x7FBD, 0x7FC0,
+ 0x7FC3, 0x7FC6, 0x7FC9, 0x7FCC,
+ 0x7FCE, 0x7FD1, 0x7FD4, 0x7FD6,
+ 0x7FD9, 0x7FDB, 0x7FDD, 0x7FE0,
+ 0x7FE2, 0x7FE4, 0x7FE6, 0x7FE8,
+ 0x7FEA, 0x7FEB, 0x7FED, 0x7FEF,
+ 0x7FF0, 0x7FF2, 0x7FF3, 0x7FF5,
+ 0x7FF6, 0x7FF7, 0x7FF8, 0x7FF9,
+ 0x7FFA, 0x7FFB, 0x7FFC, 0x7FFC,
+ 0x7FFD, 0x7FFD, 0x7FFE, 0x7FFE,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF
+
+};
+
+
+const Int16 Short_Window_sine_fxp[SHORT_WINDOW] =
+{
+
+ 0x00C9, 0x025B, 0x03ED, 0x057F,
+ 0x0711, 0x08A2, 0x0A33, 0x0BC4,
+ 0x0D54, 0x0EE3, 0x1072, 0x1201,
+ 0x138F, 0x151C, 0x16A8, 0x1833,
+ 0x19BE, 0x1B47, 0x1CCF, 0x1E57,
+ 0x1FDD, 0x2161, 0x22E5, 0x2467,
+ 0x25E8, 0x2767, 0x28E5, 0x2A61,
+ 0x2BDC, 0x2D55, 0x2ECC, 0x3041,
+ 0x31B5, 0x3326, 0x3496, 0x3604,
+ 0x376F, 0x38D9, 0x3A40, 0x3BA5,
+ 0x3D07, 0x3E68, 0x3FC5, 0x4121,
+ 0x427A, 0x43D0, 0x4524, 0x4675,
+ 0x47C3, 0x490F, 0x4A58, 0x4B9D,
+ 0x4CE0, 0x4E20, 0x4F5D, 0x5097,
+ 0x51CE, 0x5302, 0x5432, 0x5560,
+ 0x568A, 0x57B0, 0x58D3, 0x59F3,
+ 0x5B0F, 0x5C28, 0x5D3E, 0x5E4F,
+ 0x5F5D, 0x6068, 0x616E, 0x6271,
+ 0x6370, 0x646C, 0x6563, 0x6656,
+ 0x6746, 0x6832, 0x6919, 0x69FD,
+ 0x6ADC, 0x6BB7, 0x6C8E, 0x6D61,
+ 0x6E30, 0x6EFB, 0x6FC1, 0x7083,
+ 0x7140, 0x71F9, 0x72AE, 0x735E,
+ 0x740A, 0x74B2, 0x7555, 0x75F3,
+ 0x768D, 0x7722, 0x77B3, 0x783F,
+ 0x78C7, 0x794A, 0x79C8, 0x7A41,
+ 0x7AB6, 0x7B26, 0x7B91, 0x7BF8,
+ 0x7C59, 0x7CB6, 0x7D0E, 0x7D62,
+ 0x7DB0, 0x7DFA, 0x7E3E, 0x7E7E,
+ 0x7EB9, 0x7EEF, 0x7F21, 0x7F4D,
+ 0x7F74, 0x7F97, 0x7FB4, 0x7FCD,
+ 0x7FE1, 0x7FF0, 0x7FF9, 0x7FFE
+};
+
+
+
+const Int16 Long_Window_KBD_fxp[LONG_WINDOW] =
+{
+
+ 0x000A, 0x000E, 0x0012, 0x0015,
+ 0x0019, 0x001C, 0x0020, 0x0023,
+ 0x0026, 0x002A, 0x002D, 0x0030,
+ 0x0034, 0x0038, 0x003B, 0x003F,
+ 0x0043, 0x0047, 0x004B, 0x004F,
+ 0x0053, 0x0057, 0x005B, 0x0060,
+ 0x0064, 0x0069, 0x006D, 0x0072,
+ 0x0077, 0x007C, 0x0081, 0x0086,
+ 0x008B, 0x0091, 0x0096, 0x009C,
+ 0x00A1, 0x00A7, 0x00AD, 0x00B3,
+ 0x00B9, 0x00BF, 0x00C6, 0x00CC,
+ 0x00D3, 0x00DA, 0x00E0, 0x00E7,
+ 0x00EE, 0x00F5, 0x00FD, 0x0104,
+ 0x010C, 0x0113, 0x011B, 0x0123,
+ 0x012B, 0x0133, 0x013C, 0x0144,
+ 0x014D, 0x0156, 0x015F, 0x0168,
+ 0x0171, 0x017A, 0x0183, 0x018D,
+ 0x0197, 0x01A1, 0x01AB, 0x01B5,
+ 0x01BF, 0x01CA, 0x01D4, 0x01DF,
+ 0x01EA, 0x01F5, 0x0200, 0x020C,
+ 0x0217, 0x0223, 0x022F, 0x023B,
+ 0x0247, 0x0253, 0x0260, 0x026D,
+ 0x027A, 0x0287, 0x0294, 0x02A1,
+ 0x02AF, 0x02BC, 0x02CA, 0x02D8,
+ 0x02E7, 0x02F5, 0x0304, 0x0312,
+ 0x0321, 0x0331, 0x0340, 0x034F,
+ 0x035F, 0x036F, 0x037F, 0x038F,
+ 0x03A0, 0x03B0, 0x03C1, 0x03D2,
+ 0x03E3, 0x03F5, 0x0406, 0x0418,
+ 0x042A, 0x043C, 0x044F, 0x0461,
+ 0x0474, 0x0487, 0x049A, 0x04AE,
+ 0x04C1, 0x04D5, 0x04E9, 0x04FD,
+ 0x0512, 0x0526, 0x053B, 0x0550,
+ 0x0566, 0x057B, 0x0591, 0x05A7,
+ 0x05BD, 0x05D3, 0x05EA, 0x0601,
+ 0x0618, 0x062F, 0x0646, 0x065E,
+ 0x0676, 0x068E, 0x06A6, 0x06BF,
+ 0x06D8, 0x06F1, 0x070A, 0x0723,
+ 0x073D, 0x0757, 0x0771, 0x078C,
+ 0x07A6, 0x07C1, 0x07DC, 0x07F7,
+ 0x0813, 0x082F, 0x084B, 0x0867,
+ 0x0884, 0x08A0, 0x08BD, 0x08DA,
+ 0x08F8, 0x0916, 0x0933, 0x0952,
+ 0x0970, 0x098F, 0x09AE, 0x09CD,
+ 0x09EC, 0x0A0C, 0x0A2C, 0x0A4C,
+ 0x0A6C, 0x0A8D, 0x0AAD, 0x0ACF,
+ 0x0AF0, 0x0B11, 0x0B33, 0x0B55,
+ 0x0B78, 0x0B9A, 0x0BBD, 0x0BE0,
+ 0x0C03, 0x0C27, 0x0C4B, 0x0C6F,
+ 0x0C93, 0x0CB8, 0x0CDD, 0x0D02,
+ 0x0D27, 0x0D4D, 0x0D73, 0x0D99,
+ 0x0DBF, 0x0DE6, 0x0E0C, 0x0E33,
+ 0x0E5B, 0x0E82, 0x0EAA, 0x0ED2,
+ 0x0EFB, 0x0F23, 0x0F4C, 0x0F75,
+ 0x0F9F, 0x0FC8, 0x0FF2, 0x101C,
+ 0x1047, 0x1071, 0x109C, 0x10C7,
+ 0x10F3, 0x111E, 0x114A, 0x1176,
+ 0x11A3, 0x11D0, 0x11FC, 0x122A,
+ 0x1257, 0x1285, 0x12B3, 0x12E1,
+ 0x130F, 0x133E, 0x136D, 0x139C,
+ 0x13CB, 0x13FB, 0x142B, 0x145B,
+ 0x148B, 0x14BC, 0x14ED, 0x151E,
+ 0x1550, 0x1581, 0x15B3, 0x15E5,
+ 0x1618, 0x164A, 0x167D, 0x16B0,
+ 0x16E3, 0x1717, 0x174B, 0x177F,
+ 0x17B3, 0x17E8, 0x181D, 0x1852,
+ 0x1887, 0x18BC, 0x18F2, 0x1928,
+ 0x195E, 0x1995, 0x19CB, 0x1A02,
+ 0x1A39, 0x1A71, 0x1AA8, 0x1AE0,
+ 0x1B18, 0x1B50, 0x1B89, 0x1BC1,
+ 0x1BFA, 0x1C34, 0x1C6D, 0x1CA7,
+ 0x1CE0, 0x1D1A, 0x1D55, 0x1D8F,
+ 0x1DCA, 0x1E05, 0x1E40, 0x1E7B,
+ 0x1EB7, 0x1EF2, 0x1F2E, 0x1F6B,
+ 0x1FA7, 0x1FE4, 0x2020, 0x205D,
+ 0x209B, 0x20D8, 0x2116, 0x2153,
+ 0x2191, 0x21D0, 0x220E, 0x224D,
+ 0x228B, 0x22CA, 0x2309, 0x2349,
+ 0x2388, 0x23C8, 0x2408, 0x2448,
+ 0x2488, 0x24C9, 0x2509, 0x254A,
+ 0x258B, 0x25CC, 0x260E, 0x264F,
+ 0x2691, 0x26D3, 0x2715, 0x2757,
+ 0x2799, 0x27DC, 0x281F, 0x2861,
+ 0x28A4, 0x28E8, 0x292B, 0x296E,
+ 0x29B2, 0x29F6, 0x2A3A, 0x2A7E,
+ 0x2AC2, 0x2B06, 0x2B4B, 0x2B8F,
+ 0x2BD4, 0x2C19, 0x2C5E, 0x2CA3,
+ 0x2CE9, 0x2D2E, 0x2D74, 0x2DB9,
+ 0x2DFF, 0x2E45, 0x2E8B, 0x2ED1,
+ 0x2F18, 0x2F5E, 0x2FA5, 0x2FEB,
+ 0x3032, 0x3079, 0x30C0, 0x3107,
+ 0x314E, 0x3195, 0x31DD, 0x3224,
+ 0x326C, 0x32B4, 0x32FB, 0x3343,
+ 0x338B, 0x33D3, 0x341B, 0x3463,
+ 0x34AC, 0x34F4, 0x353D, 0x3585,
+ 0x35CE, 0x3616, 0x365F, 0x36A8,
+ 0x36F1, 0x373A, 0x3783, 0x37CC,
+ 0x3815, 0x385E, 0x38A7, 0x38F0,
+ 0x393A, 0x3983, 0x39CC, 0x3A16,
+ 0x3A5F, 0x3AA9, 0x3AF2, 0x3B3C,
+ 0x3B86, 0x3BCF, 0x3C19, 0x3C63,
+ 0x3CAC, 0x3CF6, 0x3D40, 0x3D8A,
+ 0x3DD3, 0x3E1D, 0x3E67, 0x3EB1,
+ 0x3EFB, 0x3F45, 0x3F8E, 0x3FD8,
+ 0x4022, 0x406C, 0x40B6, 0x4100,
+ 0x414A, 0x4193, 0x41DD, 0x4227,
+ 0x4271, 0x42BB, 0x4304, 0x434E,
+ 0x4398, 0x43E1, 0x442B, 0x4475,
+ 0x44BE, 0x4508, 0x4551, 0x459B,
+ 0x45E4, 0x462E, 0x4677, 0x46C0,
+ 0x4709, 0x4753, 0x479C, 0x47E5,
+ 0x482E, 0x4877, 0x48C0, 0x4909,
+ 0x4951, 0x499A, 0x49E3, 0x4A2B,
+ 0x4A74, 0x4ABC, 0x4B04, 0x4B4D,
+ 0x4B95, 0x4BDD, 0x4C25, 0x4C6D,
+ 0x4CB5, 0x4CFC, 0x4D44, 0x4D8C,
+ 0x4DD3, 0x4E1A, 0x4E62, 0x4EA9,
+ 0x4EF0, 0x4F37, 0x4F7E, 0x4FC4,
+ 0x500B, 0x5051, 0x5098, 0x50DE,
+ 0x5124, 0x516A, 0x51B0, 0x51F6,
+ 0x523B, 0x5281, 0x52C6, 0x530B,
+ 0x5351, 0x5396, 0x53DA, 0x541F,
+ 0x5464, 0x54A8, 0x54EC, 0x5530,
+ 0x5574, 0x55B8, 0x55FC, 0x563F,
+ 0x5683, 0x56C6, 0x5709, 0x574C,
+ 0x578F, 0x57D1, 0x5814, 0x5856,
+ 0x5898, 0x58DA, 0x591B, 0x595D,
+ 0x599E, 0x59E0, 0x5A21, 0x5A61,
+ 0x5AA2, 0x5AE3, 0x5B23, 0x5B63,
+ 0x5BA3, 0x5BE3, 0x5C22, 0x5C62,
+ 0x5CA1, 0x5CE0, 0x5D1F, 0x5D5D,
+ 0x5D9C, 0x5DDA, 0x5E18, 0x5E56,
+ 0x5E93, 0x5ED1, 0x5F0E, 0x5F4B,
+ 0x5F87, 0x5FC4, 0x6000, 0x603D,
+ 0x6079, 0x60B4, 0x60F0, 0x612B,
+ 0x6166, 0x61A1, 0x61DC, 0x6216,
+ 0x6250, 0x628A, 0x62C4, 0x62FE,
+ 0x6337, 0x6370, 0x63A9, 0x63E2,
+ 0x641A, 0x6452, 0x648A, 0x64C2,
+ 0x64F9, 0x6531, 0x6568, 0x659E,
+ 0x65D5, 0x660B, 0x6641, 0x6677,
+ 0x66AD, 0x66E2, 0x6717, 0x674C,
+ 0x6781, 0x67B5, 0x67E9, 0x681D,
+ 0x6851, 0x6885, 0x68B8, 0x68EB,
+ 0x691D, 0x6950, 0x6982, 0x69B4,
+ 0x69E6, 0x6A17, 0x6A48, 0x6A79,
+ 0x6AAA, 0x6ADB, 0x6B0B, 0x6B3B,
+ 0x6B6A, 0x6B9A, 0x6BC9, 0x6BF8,
+ 0x6C27, 0x6C55, 0x6C83, 0x6CB1,
+ 0x6CDF, 0x6D0D, 0x6D3A, 0x6D67,
+ 0x6D93, 0x6DC0, 0x6DEC, 0x6E18,
+ 0x6E44, 0x6E6F, 0x6E9A, 0x6EC5,
+ 0x6EF0, 0x6F1A, 0x6F44, 0x6F6E,
+ 0x6F98, 0x6FC1, 0x6FEA, 0x7013,
+ 0x703C, 0x7064, 0x708C, 0x70B4,
+ 0x70DB, 0x7103, 0x712A, 0x7151,
+ 0x7177, 0x719D, 0x71C3, 0x71E9,
+ 0x720F, 0x7234, 0x7259, 0x727E,
+ 0x72A2, 0x72C7, 0x72EB, 0x730E,
+ 0x7332, 0x7355, 0x7378, 0x739B,
+ 0x73BD, 0x73E0, 0x7402, 0x7424,
+ 0x7445, 0x7466, 0x7487, 0x74A8,
+ 0x74C9, 0x74E9, 0x7509, 0x7529,
+ 0x7548, 0x7568, 0x7587, 0x75A5,
+ 0x75C4, 0x75E2, 0x7601, 0x761E,
+ 0x763C, 0x7659, 0x7676, 0x7693,
+ 0x76B0, 0x76CC, 0x76E9, 0x7705,
+ 0x7720, 0x773C, 0x7757, 0x7772,
+ 0x778D, 0x77A8, 0x77C2, 0x77DC,
+ 0x77F6, 0x780F, 0x7829, 0x7842,
+ 0x785B, 0x7874, 0x788C, 0x78A5,
+ 0x78BD, 0x78D5, 0x78EC, 0x7904,
+ 0x791B, 0x7932, 0x7949, 0x795F,
+ 0x7976, 0x798C, 0x79A2, 0x79B7,
+ 0x79CD, 0x79E2, 0x79F7, 0x7A0C,
+ 0x7A21, 0x7A35, 0x7A4A, 0x7A5E,
+ 0x7A72, 0x7A85, 0x7A99, 0x7AAC,
+ 0x7ABF, 0x7AD2, 0x7AE5, 0x7AF7,
+ 0x7B09, 0x7B1B, 0x7B2D, 0x7B3F,
+ 0x7B51, 0x7B62, 0x7B73, 0x7B84,
+ 0x7B95, 0x7BA5, 0x7BB6, 0x7BC6,
+ 0x7BD6, 0x7BE6, 0x7BF6, 0x7C05,
+ 0x7C15, 0x7C24, 0x7C33, 0x7C42,
+ 0x7C50, 0x7C5F, 0x7C6D, 0x7C7B,
+ 0x7C89, 0x7C97, 0x7CA5, 0x7CB2,
+ 0x7CC0, 0x7CCD, 0x7CDA, 0x7CE7,
+ 0x7CF3, 0x7D00, 0x7D0C, 0x7D18,
+ 0x7D25, 0x7D31, 0x7D3C, 0x7D48,
+ 0x7D53, 0x7D5F, 0x7D6A, 0x7D75,
+ 0x7D80, 0x7D8B, 0x7D95, 0x7DA0,
+ 0x7DAA, 0x7DB4, 0x7DBE, 0x7DC8,
+ 0x7DD2, 0x7DDC, 0x7DE5, 0x7DEF,
+ 0x7DF8, 0x7E01, 0x7E0A, 0x7E13,
+ 0x7E1C, 0x7E25, 0x7E2D, 0x7E36,
+ 0x7E3E, 0x7E46, 0x7E4E, 0x7E56,
+ 0x7E5E, 0x7E66, 0x7E6D, 0x7E75,
+ 0x7E7C, 0x7E83, 0x7E8B, 0x7E92,
+ 0x7E99, 0x7EA0, 0x7EA6, 0x7EAD,
+ 0x7EB3, 0x7EBA, 0x7EC0, 0x7EC6,
+ 0x7ECD, 0x7ED3, 0x7ED9, 0x7EDE,
+ 0x7EE4, 0x7EEA, 0x7EF0, 0x7EF5,
+ 0x7EFA, 0x7F00, 0x7F05, 0x7F0A,
+ 0x7F0F, 0x7F14, 0x7F19, 0x7F1E,
+ 0x7F23, 0x7F27, 0x7F2C, 0x7F30,
+ 0x7F35, 0x7F39, 0x7F3D, 0x7F41,
+ 0x7F46, 0x7F4A, 0x7F4E, 0x7F52,
+ 0x7F55, 0x7F59, 0x7F5D, 0x7F60,
+ 0x7F64, 0x7F68, 0x7F6B, 0x7F6E,
+ 0x7F72, 0x7F75, 0x7F78, 0x7F7B,
+ 0x7F7E, 0x7F81, 0x7F84, 0x7F87,
+ 0x7F8A, 0x7F8D, 0x7F90, 0x7F92,
+ 0x7F95, 0x7F97, 0x7F9A, 0x7F9C,
+ 0x7F9F, 0x7FA1, 0x7FA4, 0x7FA6,
+ 0x7FA8, 0x7FAA, 0x7FAC, 0x7FAE,
+ 0x7FB1, 0x7FB3, 0x7FB5, 0x7FB6,
+ 0x7FB8, 0x7FBA, 0x7FBC, 0x7FBE,
+ 0x7FBF, 0x7FC1, 0x7FC3, 0x7FC4,
+ 0x7FC6, 0x7FC8, 0x7FC9, 0x7FCB,
+ 0x7FCC, 0x7FCD, 0x7FCF, 0x7FD0,
+ 0x7FD1, 0x7FD3, 0x7FD4, 0x7FD5,
+ 0x7FD6, 0x7FD8, 0x7FD9, 0x7FDA,
+ 0x7FDB, 0x7FDC, 0x7FDD, 0x7FDE,
+ 0x7FDF, 0x7FE0, 0x7FE1, 0x7FE2,
+ 0x7FE3, 0x7FE4, 0x7FE4, 0x7FE5,
+ 0x7FE6, 0x7FE7, 0x7FE8, 0x7FE8,
+ 0x7FE9, 0x7FEA, 0x7FEA, 0x7FEB,
+ 0x7FEC, 0x7FEC, 0x7FED, 0x7FEE,
+ 0x7FEE, 0x7FEF, 0x7FEF, 0x7FF0,
+ 0x7FF0, 0x7FF1, 0x7FF1, 0x7FF2,
+ 0x7FF2, 0x7FF3, 0x7FF3, 0x7FF4,
+ 0x7FF4, 0x7FF4, 0x7FF5, 0x7FF5,
+ 0x7FF6, 0x7FF6, 0x7FF6, 0x7FF7,
+ 0x7FF7, 0x7FF7, 0x7FF8, 0x7FF8,
+ 0x7FF8, 0x7FF8, 0x7FF9, 0x7FF9,
+ 0x7FF9, 0x7FF9, 0x7FFA, 0x7FFA,
+ 0x7FFA, 0x7FFA, 0x7FFA, 0x7FFB,
+ 0x7FFB, 0x7FFB, 0x7FFB, 0x7FFB,
+ 0x7FFC, 0x7FFC, 0x7FFC, 0x7FFC,
+ 0x7FFC, 0x7FFC, 0x7FFC, 0x7FFC,
+ 0x7FFD, 0x7FFD, 0x7FFD, 0x7FFD,
+ 0x7FFD, 0x7FFD, 0x7FFD, 0x7FFD,
+ 0x7FFD, 0x7FFD, 0x7FFE, 0x7FFE,
+ 0x7FFE, 0x7FFE, 0x7FFE, 0x7FFE,
+ 0x7FFE, 0x7FFE, 0x7FFE, 0x7FFE,
+ 0x7FFE, 0x7FFE, 0x7FFE, 0x7FFE,
+ 0x7FFE, 0x7FFE, 0x7FFE, 0x7FFE,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF
+
+};
+
+
+
+
+const Int16 Short_Window_KBD_fxp[SHORT_WINDOW] =
+{
+
+ 0x0001, 0x0004, 0x0008, 0x000D,
+ 0x0014, 0x001D, 0x0029, 0x0039,
+ 0x004C, 0x0063, 0x0080, 0x00A2,
+ 0x00CB, 0x00FB, 0x0133, 0x0174,
+ 0x01BE, 0x0214, 0x0275, 0x02E3,
+ 0x035E, 0x03E8, 0x0481, 0x052B,
+ 0x05E7, 0x06B4, 0x0795, 0x088A,
+ 0x0993, 0x0AB2, 0x0BE7, 0x0D32,
+ 0x0E94, 0x100E, 0x119F, 0x1347,
+ 0x1507, 0x16DE, 0x18CC, 0x1AD0,
+ 0x1CEB, 0x1F1A, 0x215F, 0x23B6,
+ 0x2620, 0x289C, 0x2B27, 0x2DC0,
+ 0x3066, 0x3317, 0x35D2, 0x3894,
+ 0x3B5C, 0x3E28, 0x40F6, 0x43C4,
+ 0x468F, 0x4956, 0x4C18, 0x4ED1,
+ 0x5181, 0x5425, 0x56BC, 0x5944,
+ 0x5BBB, 0x5E21, 0x6073, 0x62B1,
+ 0x64DA, 0x66EC, 0x68E7, 0x6ACB,
+ 0x6C96, 0x6E49, 0x6FE4, 0x7166,
+ 0x72D0, 0x7421, 0x755B, 0x767E,
+ 0x778A, 0x7881, 0x7962, 0x7A30,
+ 0x7AEA, 0x7B92, 0x7C29, 0x7CB0,
+ 0x7D28, 0x7D92, 0x7DF0, 0x7E42,
+ 0x7E89, 0x7EC7, 0x7EFC, 0x7F2A,
+ 0x7F50, 0x7F71, 0x7F8C, 0x7FA3,
+ 0x7FB6, 0x7FC5, 0x7FD2, 0x7FDC,
+ 0x7FE4, 0x7FEB, 0x7FF0, 0x7FF4,
+ 0x7FF7, 0x7FF9, 0x7FFB, 0x7FFC,
+ 0x7FFD, 0x7FFE, 0x7FFE, 0x7FFE,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF
+};
+
diff --git a/media/libstagefright/codecs/aacdec/write_output.h b/media/libstagefright/codecs/aacdec/write_output.h
new file mode 100644
index 0000000..0085a63
--- /dev/null
+++ b/media/libstagefright/codecs/aacdec/write_output.h
@@ -0,0 +1,138 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Pathname: write_output.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Change function prototype.
+
+ Description: Remove CR/LF from unknown editor
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Header file for the declaration of the function write_output()
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef WRITE_OUTPUT_H
+#define WRITE_OUTPUT_H
+
+#include "pv_audio_type_defs.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; INCLUDES
+ ----------------------------------------------------------------------------*/
+#include "pvmp4audiodecoder_api.h"
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+#ifndef AAC_PLUS
+
+ Int write_output(
+ const Int16 sourceLeft[],
+ const Int16 sourceRight[],
+ Int16 outputBuffer[],
+ const Int sourcePointsPerChannel,
+ const Int sourceChannels,
+ const Int requestedChannels,
+ const tPVMP4AudioDecoderOutputFormat outputFormat);
+
+#else
+
+ Int write_output(
+ const Int16 sourceLeft[],
+ const Int16 sourceRight[],
+ Int16 outputBuffer[],
+ const Int sourcePointsPerChannel,
+ const Int sourceChannels,
+ const Int requestedChannels,
+#ifdef PARAMETRICSTEREO
+ Int32 sbrEnablePS,
+#endif
+ const tPVMP4AudioDecoderOutputFormat outputFormat);
+
+#ifdef AAC_32_BIT_INTERFACE
+
+ Int write_output_1(
+ const Int32 sourceLeft[],
+ const Int32 sourceRight[],
+ Int16 outputBuffer[],
+ const Int sourcePointsPerChannel,
+ const Int sourceChannels,
+ const Int requestedChannels,
+ const tPVMP4AudioDecoderOutputFormat outputFormat);
+#endif
+
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WRITE_OUTPUT_H */
+
+
diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
new file mode 100644
index 0000000..8b5007e
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
@@ -0,0 +1,334 @@
+/*
+ * 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/foundation/ADebug.h>
+#include <media/stagefright/MediaBufferGroup.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),
+ mInputFrame(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(mChannels <= 2 && mChannels >= 1);
+ CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate));
+
+ mApiHandle = new VO_AUDIO_CODECAPI;
+ CHECK(mApiHandle);
+
+ if (VO_ERR_NONE != voGetAACEncAPI(mApiHandle)) {
+ ALOGE("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)) {
+ ALOGE("Failed to init AAC encoder");
+ return UNKNOWN_ERROR;
+ }
+ if (OK != setAudioSpecificConfigData()) {
+ ALOGE("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; // We add adts header in the file writer if needed.
+ if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AAC_ENCPARAM, &params)) {
+ ALOGE("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;
+ }
+ }
+
+ ALOGE("Sampling rate %d bps is not supported", sampleRate);
+ return UNKNOWN_ERROR;
+}
+
+status_t AACEncoder::setAudioSpecificConfigData() {
+ ALOGV("setAudioSpecificConfigData: %d hz, %d bps, and %d channels",
+ mSampleRate, mBitRate, mChannels);
+
+ int32_t index = 0;
+ CHECK_EQ((status_t)OK, getSampleRateTableIndex(mSampleRate, index));
+ if (mChannels > 2 || mChannels <= 0) {
+ ALOGE("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) {
+ ALOGW("Call start() when encoder already started");
+ return OK;
+ }
+
+ mBufferGroup = new MediaBufferGroup;
+ mBufferGroup->add_buffer(new MediaBuffer(2048));
+
+ CHECK_EQ((status_t)OK, initCheck());
+
+ mNumInputSamples = 0;
+ mAnchorTimeUs = 0;
+ mFrameCount = 0;
+
+ mInputFrame = new int16_t[mChannels * kNumSamplesPerFrame];
+ CHECK(mInputFrame != NULL);
+
+ status_t err = mSource->start(params);
+ if (err != OK) {
+ ALOGE("AudioSource is not available");
+ return err;
+ }
+
+ mStarted = true;
+
+ return OK;
+}
+
+status_t AACEncoder::stop() {
+ if (mInputBuffer) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ }
+
+ delete mBufferGroup;
+ mBufferGroup = NULL;
+
+ if (mInputFrame) {
+ delete[] mInputFrame;
+ mInputFrame = NULL;
+ }
+
+ if (!mStarted) {
+ ALOGW("Call stop() when encoder has not started");
+ return ERROR_END_OF_STREAM;
+ }
+
+ mSource->stop();
+ if (mEncoderHandle) {
+ CHECK_EQ((VO_U32)VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
+ mEncoderHandle = NULL;
+ }
+ delete mApiHandle;
+ mApiHandle = NULL;
+
+ delete mMemOperator;
+ mMemOperator = 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), (status_t)OK);
+ uint8_t *outPtr = (uint8_t *)buffer->data();
+ bool readFromSource = false;
+ int64_t wallClockTimeUs = -1;
+
+ 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);
+ }
+
+ const int32_t nSamples = mChannels * kNumSamplesPerFrame;
+ while (mNumInputSamples < nSamples) {
+ 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) * (nSamples - mNumInputSamples));
+ mNumInputSamples = 0;
+ break;
+ }
+
+ size_t align = mInputBuffer->range_length() % sizeof(int16_t);
+ CHECK_EQ(align, (size_t)0);
+
+ int64_t timeUs;
+ if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) {
+ wallClockTimeUs = timeUs;
+ }
+ if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) {
+ mAnchorTimeUs = timeUs;
+ }
+ readFromSource = true;
+ } else {
+ readFromSource = false;
+ }
+ size_t copy = (nSamples - 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 >= nSamples) {
+ mNumInputSamples %= nSamples;
+ break;
+ }
+ }
+
+ VO_CODECBUFFER inputData;
+ memset(&inputData, 0, sizeof(inputData));
+ inputData.Buffer = (unsigned char*) mInputFrame;
+ inputData.Length = nSamples * 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;
+ size_t nOutputBytes = 0;
+ do {
+ outputData.Buffer = outPtr;
+ outputData.Length = buffer->size() - nOutputBytes;
+ ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
+ if (ret == VO_ERR_NONE) {
+ outPtr += outputData.Length;
+ nOutputBytes += outputData.Length;
+ }
+ } while (ret != VO_ERR_INPUT_BUFFER_SMALL);
+ buffer->set_range(0, nOutputBytes);
+
+ int64_t mediaTimeUs =
+ ((mFrameCount - 1) * 1000000LL * kNumSamplesPerFrame) / mSampleRate;
+
+ buffer->meta_data()->setInt64(kKeyTime, mAnchorTimeUs + mediaTimeUs);
+ if (readFromSource && wallClockTimeUs != -1) {
+ buffer->meta_data()->setInt64(kKeyDriftTime, mediaTimeUs - wallClockTimeUs);
+ }
+ ++mFrameCount;
+
+ *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..b47cb1e
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/Android.mk
@@ -0,0 +1,113 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include frameworks/base/media/libstagefright/codecs/common/Config.mk
+
+
+
+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 -DARMV6_INASM
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7
+endif
+
+include $(BUILD_STATIC_LIBRARY)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ SoftAACEncoder.cpp
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+ frameworks/base/media/libstagefright/codecs/common/include \
+ frameworks/native/include/media/openmax
+
+LOCAL_CFLAGS := -DOSCL_IMPORT_REF=
+
+LOCAL_STATIC_LIBRARIES := \
+ libstagefright_aacenc
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright_omx libstagefright_foundation libutils \
+ libstagefright_enc_common
+
+LOCAL_MODULE := libstagefright_soft_aacenc
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_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..2f31de4
--- /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("libstagefright.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..ba3f4d2
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/SampleCode/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ AAC_E_SAMPLES.c \
+ ../../common/cmnMemory.c
+
+LOCAL_CFLAGS += $(VO_CFLAGS)
+
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_MODULE := AACEncTest
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright \
+ libdl
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/ \
+ $(LOCAL_PATH)/../../common \
+ $(LOCAL_PATH)/../../common/include \
+
+include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder.cpp
new file mode 100644
index 0000000..c6724c2
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder.cpp
@@ -0,0 +1,560 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SoftAACEncoder"
+#include <utils/Log.h>
+
+#include "SoftAACEncoder.h"
+
+#include "voAAC.h"
+#include "cmnMemory.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/hexdump.h>
+
+namespace android {
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+SoftAACEncoder::SoftAACEncoder(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SimpleSoftOMXComponent(name, callbacks, appData, component),
+ mEncoderHandle(NULL),
+ mApiHandle(NULL),
+ mMemOperator(NULL),
+ mNumChannels(1),
+ mSampleRate(44100),
+ mBitRate(0),
+ mSentCodecSpecificData(false),
+ mInputSize(0),
+ mInputFrame(NULL),
+ mInputTimeUs(-1ll),
+ mSawInputEOS(false),
+ mSignalledError(false) {
+ initPorts();
+ CHECK_EQ(initEncoder(), (status_t)OK);
+
+ setAudioParams();
+}
+
+SoftAACEncoder::~SoftAACEncoder() {
+ delete[] mInputFrame;
+ mInputFrame = NULL;
+
+ if (mEncoderHandle) {
+ CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
+ mEncoderHandle = NULL;
+ }
+
+ delete mApiHandle;
+ mApiHandle = NULL;
+
+ delete mMemOperator;
+ mMemOperator = NULL;
+}
+
+void SoftAACEncoder::initPorts() {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+
+ def.nPortIndex = 0;
+ def.eDir = OMX_DirInput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 2;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 1;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ addPort(def);
+
+ def.nPortIndex = 1;
+ def.eDir = OMX_DirOutput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 8192;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 2;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/aac");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
+
+ addPort(def);
+}
+
+status_t SoftAACEncoder::initEncoder() {
+ mApiHandle = new VO_AUDIO_CODECAPI;
+
+ if (VO_ERR_NONE != voGetAACEncAPI(mApiHandle)) {
+ ALOGE("Failed to get api handle");
+ return UNKNOWN_ERROR;
+ }
+
+ mMemOperator = new VO_MEM_OPERATOR;
+ 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)) {
+ ALOGE("Failed to init AAC encoder");
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+OMX_ERRORTYPE SoftAACEncoder::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamAudioPortFormat:
+ {
+ OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+ (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+ if (formatParams->nPortIndex > 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (formatParams->nIndex > 0) {
+ return OMX_ErrorNoMore;
+ }
+
+ formatParams->eEncoding =
+ (formatParams->nPortIndex == 0)
+ ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAAC;
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioAac:
+ {
+ OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
+ (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
+
+ if (aacParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ aacParams->nBitRate = mBitRate;
+ aacParams->nAudioBandWidth = 0;
+ aacParams->nAACtools = 0;
+ aacParams->nAACERtools = 0;
+ aacParams->eAACProfile = OMX_AUDIO_AACObjectMain;
+ aacParams->eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
+ aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
+
+ aacParams->nChannels = mNumChannels;
+ aacParams->nSampleRate = mSampleRate;
+ aacParams->nFrameLength = 0;
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPcm:
+ {
+ OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eEndian = OMX_EndianBig;
+ pcmParams->bInterleaved = OMX_TRUE;
+ pcmParams->nBitPerSample = 16;
+ pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
+ pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+ pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+
+ pcmParams->nChannels = mNumChannels;
+ pcmParams->nSamplingRate = mSampleRate;
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftAACEncoder::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamStandardComponentRole:
+ {
+ const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+ (const OMX_PARAM_COMPONENTROLETYPE *)params;
+
+ if (strncmp((const char *)roleParams->cRole,
+ "audio_encoder.aac",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPortFormat:
+ {
+ const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+ (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+ if (formatParams->nPortIndex > 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (formatParams->nIndex > 0) {
+ return OMX_ErrorNoMore;
+ }
+
+ if ((formatParams->nPortIndex == 0
+ && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
+ || (formatParams->nPortIndex == 1
+ && formatParams->eEncoding != OMX_AUDIO_CodingAAC)) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioAac:
+ {
+ OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
+ (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
+
+ if (aacParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ mBitRate = aacParams->nBitRate;
+ mNumChannels = aacParams->nChannels;
+ mSampleRate = aacParams->nSampleRate;
+
+ if (setAudioParams() != OK) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPcm:
+ {
+ OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ mNumChannels = pcmParams->nChannels;
+ mSampleRate = pcmParams->nSamplingRate;
+
+ if (setAudioParams() != OK) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+
+ default:
+ return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ }
+}
+
+status_t SoftAACEncoder::setAudioParams() {
+ // We call this whenever sample rate, number of channels or bitrate change
+ // in reponse to setParameter calls.
+
+ ALOGV("setAudioParams: %lu Hz, %lu channels, %lu bps",
+ mSampleRate, mNumChannels, mBitRate);
+
+ status_t err = setAudioSpecificConfigData();
+
+ if (err != OK) {
+ return err;
+ }
+
+ AACENC_PARAM params;
+ memset(&params, 0, sizeof(params));
+ params.sampleRate = mSampleRate;
+ params.bitRate = mBitRate;
+ params.nChannels = mNumChannels;
+ params.adtsUsed = 0; // We add adts header in the file writer if needed.
+ if (VO_ERR_NONE != mApiHandle->SetParam(
+ mEncoderHandle, VO_PID_AAC_ENCPARAM, &params)) {
+ ALOGE("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;
+ }
+ }
+
+ return UNKNOWN_ERROR;
+}
+
+status_t SoftAACEncoder::setAudioSpecificConfigData() {
+ // The AAC encoder's audio specific config really only encodes
+ // number of channels and the sample rate (mapped to an index into
+ // a fixed sample rate table).
+
+ int32_t index;
+ status_t err = getSampleRateTableIndex(mSampleRate, index);
+ if (err != OK) {
+ ALOGE("Unsupported sample rate (%lu Hz)", mSampleRate);
+ return err;
+ }
+
+ if (mNumChannels > 2 || mNumChannels <= 0) {
+ ALOGE("Unsupported number of channels(%lu)", mNumChannels);
+ return UNKNOWN_ERROR;
+ }
+
+ // OMX_AUDIO_AACObjectLC
+ mAudioSpecificConfigData[0] = ((0x02 << 3) | (index >> 1));
+ mAudioSpecificConfigData[1] = ((index & 0x01) << 7) | (mNumChannels << 3);
+
+ return OK;
+}
+
+void SoftAACEncoder::onQueueFilled(OMX_U32 portIndex) {
+ if (mSignalledError) {
+ return;
+ }
+
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+
+ if (!mSentCodecSpecificData) {
+ // The very first thing we want to output is the codec specific
+ // data. It does not require any input data but we will need an
+ // output buffer to store it in.
+
+ if (outQueue.empty()) {
+ return;
+ }
+
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+ outHeader->nFilledLen = sizeof(mAudioSpecificConfigData);
+ outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
+
+ uint8_t *out = outHeader->pBuffer + outHeader->nOffset;
+ memcpy(out, mAudioSpecificConfigData, sizeof(mAudioSpecificConfigData));
+
+#if 0
+ ALOGI("sending codec specific data.");
+ hexdump(out, sizeof(mAudioSpecificConfigData));
+#endif
+
+ outQueue.erase(outQueue.begin());
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+
+ mSentCodecSpecificData = true;
+ }
+
+ size_t numBytesPerInputFrame =
+ mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);
+
+ for (;;) {
+ // We do the following until we run out of buffers.
+
+ while (mInputSize < numBytesPerInputFrame) {
+ // As long as there's still input data to be read we
+ // will drain "kNumSamplesPerFrame * mNumChannels" samples
+ // into the "mInputFrame" buffer and then encode those
+ // as a unit into an output buffer.
+
+ if (mSawInputEOS || inQueue.empty()) {
+ return;
+ }
+
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+
+ const void *inData = inHeader->pBuffer + inHeader->nOffset;
+
+ size_t copy = numBytesPerInputFrame - mInputSize;
+ if (copy > inHeader->nFilledLen) {
+ copy = inHeader->nFilledLen;
+ }
+
+ if (mInputFrame == NULL) {
+ mInputFrame = new int16_t[kNumSamplesPerFrame * mNumChannels];
+ }
+
+ if (mInputSize == 0) {
+ mInputTimeUs = inHeader->nTimeStamp;
+ }
+
+ memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
+ mInputSize += copy;
+
+ inHeader->nOffset += copy;
+ inHeader->nFilledLen -= copy;
+
+ // "Time" on the input buffer has in effect advanced by the
+ // number of audio frames we just advanced nOffset by.
+ inHeader->nTimeStamp +=
+ (copy * 1000000ll / mSampleRate)
+ / (mNumChannels * sizeof(int16_t));
+
+ if (inHeader->nFilledLen == 0) {
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ ALOGV("saw input EOS");
+ mSawInputEOS = true;
+
+ // Pad any remaining data with zeroes.
+ memset((uint8_t *)mInputFrame + mInputSize,
+ 0,
+ numBytesPerInputFrame - mInputSize);
+
+ mInputSize = numBytesPerInputFrame;
+ }
+
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+
+ inData = NULL;
+ inHeader = NULL;
+ inInfo = NULL;
+ }
+ }
+
+ // At this point we have all the input data necessary to encode
+ // a single frame, all we need is an output buffer to store the result
+ // in.
+
+ if (outQueue.empty()) {
+ return;
+ }
+
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+
+ VO_CODECBUFFER inputData;
+ memset(&inputData, 0, sizeof(inputData));
+ inputData.Buffer = (unsigned char *)mInputFrame;
+ inputData.Length = numBytesPerInputFrame;
+ 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));
+
+ uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset;
+ size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
+
+ VO_U32 ret = VO_ERR_NONE;
+ size_t nOutputBytes = 0;
+ do {
+ outputData.Buffer = outPtr;
+ outputData.Length = outAvailable - nOutputBytes;
+ ret = mApiHandle->GetOutputData(
+ mEncoderHandle, &outputData, &outputInfo);
+ if (ret == VO_ERR_NONE) {
+ outPtr += outputData.Length;
+ nOutputBytes += outputData.Length;
+ }
+ } while (ret != VO_ERR_INPUT_BUFFER_SMALL);
+
+ outHeader->nFilledLen = nOutputBytes;
+
+ outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
+
+ if (mSawInputEOS) {
+ // We also tag this output buffer with EOS if it corresponds
+ // to the final input buffer.
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+ }
+
+ outHeader->nTimeStamp = mInputTimeUs;
+
+#if 0
+ ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
+ nOutputBytes, mInputTimeUs, outHeader->nFlags);
+
+ hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
+#endif
+
+ outQueue.erase(outQueue.begin());
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+
+ outHeader = NULL;
+ outInfo = NULL;
+
+ mInputSize = 0;
+ }
+}
+
+} // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+ const char *name, const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+ return new android::SoftAACEncoder(name, callbacks, appData, component);
+}
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder.h b/media/libstagefright/codecs/aacenc/SoftAACEncoder.h
new file mode 100644
index 0000000..d148eb7
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SOFT_AAC_ENCODER_H_
+
+#define SOFT_AAC_ENCODER_H_
+
+#include "SimpleSoftOMXComponent.h"
+
+struct VO_AUDIO_CODECAPI;
+struct VO_MEM_OPERATOR;
+
+namespace android {
+
+struct SoftAACEncoder : public SimpleSoftOMXComponent {
+ SoftAACEncoder(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ virtual ~SoftAACEncoder();
+
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual void onQueueFilled(OMX_U32 portIndex);
+
+private:
+ enum {
+ kNumBuffers = 4,
+ kNumSamplesPerFrame = 1024,
+ };
+
+ void *mEncoderHandle;
+ VO_AUDIO_CODECAPI *mApiHandle;
+ VO_MEM_OPERATOR *mMemOperator;
+
+ OMX_U32 mNumChannels;
+ OMX_U32 mSampleRate;
+ OMX_U32 mBitRate;
+
+ bool mSentCodecSpecificData;
+ size_t mInputSize;
+ int16_t *mInputFrame;
+ int64_t mInputTimeUs;
+
+ bool mSawInputEOS;
+
+ uint8_t mAudioSpecificConfigData[2];
+
+ bool mSignalledError;
+
+ void initPorts();
+ status_t initEncoder();
+
+ status_t setAudioSpecificConfigData();
+ status_t setAudioParams();
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftAACEncoder);
+};
+
+} // namespace android
+
+#endif // SOFT_AAC_ENCODER_H_
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..5cd7e5f
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/basic_op.h
@@ -0,0 +1,1171 @@
+/*
+ ** 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)
+{
+ return L_var1 >> var2;
+}
+
+__inline Word32 ASM_L_shl(Word32 L_var1, Word16 var2)
+{
+ Word32 result;
+ asm (
+ "MOV %[result], %[L_var1], ASL %[var2] \n"
+ "TEQ %[L_var1], %[result], ASR %[var2]\n"
+ "EORNE %[result], %[mask], %[L_var1], ASR #31\n"
+ :[result]"=&r"(result)
+ :[L_var1]"r"(L_var1), [var2]"r"(var2), [mask]"r"(0x7fffffff)
+ );
+ return result;
+}
+
+__inline Word32 ASM_shr(Word32 L_var1, Word16 var2)
+{
+ Word32 result;
+ asm (
+ "CMP %[var2], #15\n"
+ "MOVLT %[result], %[L_var1], ASR %[var2]\n"
+ "MOVGE %[result], %[L_var1], ASR #15\n"
+ :[result]"=r"(result)
+ :[L_var1]"r"(L_var1), [var2]"r"(var2)
+ );
+ return result;
+}
+
+__inline Word32 ASM_shl(Word32 L_var1, Word16 var2)
+{
+#if ARMV6_SAT
+ Word32 result;
+ asm (
+ "CMP %[var2], #16\n"
+ "MOVLT %[result], %[L_var1], ASL %[var2]\n"
+ "MOVGE %[result], %[L_var1], ASL #16\n"
+ "SSAT %[result], #16, %[result]\n"
+ :[result]"=r"(result)
+ :[L_var1]"r"(L_var1), [var2]"r"(var2)
+ );
+ return result;
+#else
+ Word32 result;
+ Word32 tmp;
+ asm (
+ "CMP %[var2], #16\n"
+ "MOVLT %[result], %[L_var1], ASL %[var2]\n"
+ "MOVGE %[result], %[L_var1], ASL #16\n"
+ "MOV %[tmp], %[result], ASR #15\n"
+ "TEQ %[tmp], %[result], ASR #31 \n"
+ "EORNE %[result], %[mask], %[result],ASR #31"
+ :[result]"=&r"(result), [tmp]"=&r"(tmp)
+ :[L_var1]"r"(L_var1), [var2]"r"(var2), [mask]"r"(0x7fff)
+ );
+ return result;
+#endif
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | definitions for inline basic arithmetic operators |
+ |___________________________________________________________________________|
+*/
+#if (SATRUATE_IS_INLINE)
+__inline Word16 saturate(Word32 L_var1)
+{
+#if ARMV6_SAT
+ Word16 result;
+ asm (
+ "SSAT %[result], #16, %[L_var1]"
+ : [result]"=r"(result)
+ : [L_var1]"r"(L_var1)
+ );
+ return result;
+#elif ARMV5TE_SAT
+ Word16 result;
+ Word32 tmp;
+ asm volatile (
+ "MOV %[tmp], %[L_var1],ASR#15\n"
+ "TEQ %[tmp], %[L_var1],ASR#31\n"
+ "EORNE %[result], %[mask],%[L_var1],ASR#31\n"
+ "MOVEQ %[result], %[L_var1]\n"
+ :[result]"=&r"(result), [tmp]"=&r"(tmp)
+ :[L_var1]"r"(L_var1), [mask]"r"(0x7fff)
+ );
+
+ 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 (
+ "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 (
+ "SMULBB %[result], %[var1], %[var2] \n"
+ "QDSUB %[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 (
+ "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;
+ Word32 tmp;
+ asm (
+ "ADD %[result], %[var1], %[var2] \n"
+ "MOV %[tmp], %[result], ASR #15 \n"
+ "TEQ %[tmp], %[result], ASR #31 \n"
+ "EORNE %[result], %[mask], %[result], ASR #31"
+ :[result]"=&r"(result), [tmp]"=&r"(tmp)
+ :[var1]"r"(var1), [var2]"r"(var2), [mask]"r"(0x7fff)
+ );
+ 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;
+ Word32 tmp;
+ asm (
+ "SUB %[result], %[var1], %[var2] \n"
+ "MOV %[tmp], %[var1], ASR #15 \n"
+ "TEQ %[tmp], %[var1], ASR #31 \n"
+ "EORNE %[result], %[mask], %[result], ASR #31 \n"
+ :[result]"=&r"(result), [tmp]"=&r"(tmp)
+ :[var1]"r"(var1), [var2]"r"(var2), [mask]"r"(0x7fff)
+ );
+ 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 && ARMV6_SAT
+ Word32 result;
+ asm (
+ "SMULBB %[result], %[var1], %[var2] \n"
+ "SSAT %[result], #16, %[result], ASR #15 \n"
+ :[result]"=r"(result)
+ :[var1]"r"(var1), [var2]"r"(var2)
+ );
+ return result;
+#elif ARMV5TE_MULT
+ Word32 result, tmp;
+ asm (
+ "SMULBB %[tmp], %[var1], %[var2] \n"
+ "MOV %[result], %[tmp], ASR #15\n"
+ "MOV %[tmp], %[result], ASR #15\n"
+ "TEQ %[tmp], %[result], ASR #31\n"
+ "EORNE %[result], %[mask], %[result], ASR #31 \n"
+ :[result]"=&r"(result), [tmp]"=&r"(tmp)
+ :[var1]"r"(var1), [var2]"r"(var2), [mask]"r"(0x7fff)
+ );
+ 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;
+ Word32 tmp;
+ asm (
+ "RSBS %[tmp], %[var1], #0 \n"
+ "CLZLT %[result], %[var1]\n"
+ "CLZGT %[result], %[tmp]\n"
+ "SUBNE %[result], %[result], #17\n"
+ "MOVEQ %[result], #0\n"
+ "CMP %[var1], #-1\n"
+ "MOVEQ %[result], #15\n"
+ :[result]"=&r"(result), [tmp]"=&r"(tmp)
+ :[var1]"r"(var1)
+ );
+ 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 (
+ "QADD %[result], %[L_var1], %[bias]\n"
+ "MOV %[result], %[result], ASR #16 \n"
+ :[result]"=r"(result)
+ :[L_var1]"r"(L_var1), [bias]"r"(0x8000)
+ );
+ 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 (
+ "SMULBB %[result], %[var1], %[var2]\n"
+ "QDADD %[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_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 (
+ "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..d43bbd9
--- /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..982f4fd
--- /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);
+}
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..6e5844f
--- /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..b1f8225
--- /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..6059237
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/typedefs.h
@@ -0,0 +1,184 @@
+/*
+ ** 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
+
+#define __inline static __inline
+
+#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 int Word32;
+typedef unsigned int UWord32;
+
+
+
+#ifndef _MSC_VER
+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
+#if ARMV6_INASM
+ #undef ARMV5TE_ADD
+ #define ARMV5TE_ADD 0
+ #undef ARMV5TE_SUB
+ #define ARMV5TE_SUB 0
+ #define ARMV6_SAT 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/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..8e206b7
--- /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..bb75b6d
--- /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 */
+ VO_U32 *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..0f4bb5e
--- /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..30132d8
--- /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..65453c0
--- /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..266a219
--- /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..7c79f07
--- /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,
+ UWord32 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..6a58aeb
--- /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..a4d3e8f
--- /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..c361feb
--- /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..b0b4c26
--- /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
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..d3a8a67
--- /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..4c1b2cb
--- /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..a42e6a9
--- /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..116d5a8
--- /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..30bbf45
--- /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..3c03dea
--- /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..e719ba7
--- /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..f6981fa
--- /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 */
+ const 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 */
+ const 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..19fb9b2
--- /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..3ea6a84
--- /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..2ccac60
--- /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..109922d
--- /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..8f83973
--- /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..1cafef6
--- /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..997eba5
--- /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
diff --git a/media/libstagefright/codecs/aacenc/inc/spreading.h b/media/libstagefright/codecs/aacenc/inc/spreading.h
new file mode 100644
index 0000000..0c96fc7
--- /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..9cddc1d
--- /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..40cfaee
--- /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..02df24d
--- /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..0aa33c3
--- /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..311cef5
--- /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
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..127322d
--- /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,
+};
diff --git a/media/libstagefright/codecs/aacenc/src/aacenc.c b/media/libstagefright/codecs/aacenc/src/aacenc.c
new file mode 100644
index 0000000..ad2f29a
--- /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;
+}
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..cecbc8f
--- /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) */
+ VO_U32 *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..07b33b7
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/adj_thr.c
@@ -0,0 +1,1225 @@
+/*
+ ** 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"
+#include <string.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) && (redThrExp >= *psfbNActiveLines)) {
+
+ *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 && (normFactor* (*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;
+ memset(&peData, 0, sizeof(peData));
+
+ 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..e705197
--- /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..b30e8cb
--- /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..da21d5f
--- /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
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..4ca4f31
--- /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
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..b59b967
--- /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
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..4789f6d
--- /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..7f6b881
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/PrePostMDCT_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: PrePostMDCT_v7.s
+@
+@ Content: premdct and postmdct function armv7 assemble
+@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+ .section .text
+ .global PreMDCT
+ .fnstart
+
+PreMDCT:
+ stmdb sp!, {r4 - r11, lr}
+ .save {r4 - r11, lr}
+ fstmfdd sp!, {d8 - d15}
+ .vsave {d8 - d15}
+
+ 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:
+ fldmfdd sp!, {d8 - d15}
+ ldmia sp!, {r4 - r11, pc}
+ @ENDP @ |PreMDCT|
+ .fnend
+
+ .section .text
+ .global PostMDCT
+ .fnstart
+
+PostMDCT:
+ stmdb sp!, {r4 - r11, lr}
+ .save {r4 - r11, lr}
+ fstmfdd sp!, {d8 - d15}
+ .vsave {d8 - d15}
+
+ 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:
+ fldmfdd sp!, {d8 - d15}
+ ldmia sp!, {r4 - r11, pc}
+
+ @ENDP @ |PostMDCT|
+ .fnend
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..03fa6a9
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/R4R8First_v7.s
@@ -0,0 +1,157 @@
+@/*
+@ ** 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
+ .fnstart
+
+Radix8First:
+ stmdb sp!, {r4 - r11, lr}
+ .save {r4 - r11, lr}
+ fstmfdd sp!, {d8 - d15}
+ .vsave {d8 - d15}
+
+ 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:
+ fldmfdd sp!, {d8 - d15}
+ ldmia sp!, {r4 - r11, pc}
+SQRT1_2:
+ .word 0x2d413ccd
+
+ @ENDP @ |Radix8First|
+ .fnend
+
+ .section .text
+ .global Radix4First
+ .fnstart
+
+Radix4First:
+ stmdb sp!, {r4 - r11, lr}
+ .save {r4 - r11, lr}
+ fstmfdd sp!, {d8 - d15}
+ .vsave {d8 - d15}
+
+ 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:
+ fldmfdd sp!, {d8 - d15}
+ ldmia sp!, {r4 - r11, pc}
+
+ @ENDP @ |Radix4First|
+ .fnend
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..431bc30
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/Radix4FFT_v7.s
@@ -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: Radix4FFT_v7.s
+@
+@ Content: Radix4FFT armv7 assemble
+@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+ .section .text
+ .global Radix4FFT
+ .fnstart
+
+Radix4FFT:
+ stmdb sp!, {r4 - r11, lr}
+ .save {r4 - r11, lr}
+ fstmfdd sp!, {d8 - d15}
+ .vsave {d8 - d15}
+
+ 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:
+ fldmfdd sp!, {d8 - d15}
+ ldmia sp!, {r4 - r11, pc}
+
+ @ENDP @ |Radix4FFT|
+ .fnend
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..e4034b8
--- /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
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..9fe511c
--- /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;
+ UWord16 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..0ce93d3
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/bitbuffer.c
@@ -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: 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,
+ UWord32 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 &= ~(0xffffffff << noBitsToWrite); // Mask out everything except the lowest noBitsToWrite bits
+ 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..fcc12dd
--- /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..47fd15e
--- /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..f6552ed
--- /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..7769188
--- /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;
+ const 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..7861e1c
--- /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..d0ad433
--- /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;
+ const Word32 *pSumMS = sfbEnergySumMS.sfbShort;
+ const 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..480dc28
--- /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..bb266dc
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/memalign.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: mem_align.c
+
+ Content: Memory alloc alignments functions
+
+*******************************************************************************/
+
+
+#include "memalign.h"
+#ifdef _MSC_VER
+#include <stddef.h>
+#else
+#include <stdint.h>
+#endif
+
+/*****************************************************************************
+*
+* 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 *) ((intptr_t) (tmp + alignment - 1) &
+ (~((intptr_t) (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..2e34f14
--- /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..1406e11
--- /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..dd40f9b
--- /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,
+ const 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,
+ const 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..4e9218c
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/psy_main.c
@@ -0,0 +1,811 @@
+/*
+ ** 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;
+ const Word32 *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..48ff300
--- /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..0d0f550
--- /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;
+ const 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;
+ const 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..bc320ec
--- /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)
+{
+ Word16 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..aaf2fff
--- /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..c2bd8bd
--- /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..455a864
--- /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..a02336f
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/transform.c
@@ -0,0 +1,678 @@
+/*
+ ** 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);
+ }
+}
+#else
+void Radix4First(int *buf, int num);
+void Radix8First(int *buf, int num);
+void Radix4FFT(int *buf, int num, int bgn, int *twidTab);
+void PreMDCT(int *buf0, int num, const int *csptr);
+void PostMDCT(int *buf0, int num, const int *csptr);
+#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/Android.mk b/media/libstagefright/codecs/amrnb/Android.mk
new file mode 100644
index 0000000..2e43120
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/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/amrnb/common/Android.mk b/media/libstagefright/codecs/amrnb/common/Android.mk
new file mode 100644
index 0000000..30ce29c
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/Android.mk
@@ -0,0 +1,74 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ src/add.cpp \
+ src/az_lsp.cpp \
+ src/bitno_tab.cpp \
+ src/bitreorder_tab.cpp \
+ src/bits2prm.cpp \
+ src/bytesused.cpp \
+ src/c2_9pf_tab.cpp \
+ src/copy.cpp \
+ src/div_32.cpp \
+ src/div_s.cpp \
+ src/extract_h.cpp \
+ src/extract_l.cpp \
+ src/gains_tbl.cpp \
+ src/gc_pred.cpp \
+ src/gmed_n.cpp \
+ src/grid_tbl.cpp \
+ src/gray_tbl.cpp \
+ src/int_lpc.cpp \
+ src/inv_sqrt.cpp \
+ src/inv_sqrt_tbl.cpp \
+ src/l_abs.cpp \
+ src/l_deposit_h.cpp \
+ src/l_deposit_l.cpp \
+ src/l_shr_r.cpp \
+ src/log2.cpp \
+ src/log2_norm.cpp \
+ src/log2_tbl.cpp \
+ src/lsfwt.cpp \
+ src/lsp.cpp \
+ src/lsp_az.cpp \
+ src/lsp_lsf.cpp \
+ src/lsp_lsf_tbl.cpp \
+ src/lsp_tab.cpp \
+ src/mult_r.cpp \
+ src/norm_l.cpp \
+ src/norm_s.cpp \
+ src/overflow_tbl.cpp \
+ src/ph_disp_tab.cpp \
+ src/pow2.cpp \
+ src/pow2_tbl.cpp \
+ src/pred_lt.cpp \
+ src/q_plsf.cpp \
+ src/q_plsf_3.cpp \
+ src/q_plsf_3_tbl.cpp \
+ src/q_plsf_5.cpp \
+ src/q_plsf_5_tbl.cpp \
+ src/qua_gain_tbl.cpp \
+ src/reorder.cpp \
+ src/residu.cpp \
+ src/round.cpp \
+ src/set_zero.cpp \
+ src/shr.cpp \
+ src/shr_r.cpp \
+ src/sqrt_l.cpp \
+ src/sqrt_l_tbl.cpp \
+ src/sub.cpp \
+ src/syn_filt.cpp \
+ src/vad1.cpp \
+ src/weight_a.cpp \
+ src/window_tab.cpp
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/include
+
+LOCAL_CFLAGS := \
+ -DOSCL_UNUSED_ARG= -DOSCL_IMPORT_REF= -DOSCL_EXPORT_REF=
+
+LOCAL_MODULE := libstagefright_amrnb_common
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/amrnb/common/include/abs_s.h b/media/libstagefright/codecs/amrnb/common/include/abs_s.h
new file mode 100644
index 0000000..e92eaf4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/abs_s.h
@@ -0,0 +1,113 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/include/abs_s.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for abs_s function.
+
+ Description: Updated template to make it build for Symbian.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the abs_s function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef ABS_S_H
+#define ABS_S_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 abs_s(Word16 var1);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ABS_S_H */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/add.h b/media/libstagefright/codecs/amrnb/common/include/add.h
new file mode 100644
index 0000000..43daeca
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/add.h
@@ -0,0 +1,116 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/add.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description: Created separate header file for add function.
+
+ Description: Changed function prototype; pointer to overflow flag is passed
+ in as a parameter.
+
+ Description: Updated copyright section.
+ Changed "overflow" to "pOverflow" in the function prototype.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the add function.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef ADD_H
+#define ADD_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 add(Word16 var1, Word16 var2, Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ADD_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/az_lsp.h b/media/libstagefright/codecs/amrnb/common/include/az_lsp.h
new file mode 100644
index 0000000..7c24ca9
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/az_lsp.h
@@ -0,0 +1,120 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/az_lsp.h.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description: Changed function prototype; pointer to overflow flag is passed
+ in as a parameter. Added extern declaration for grid_tbl[],
+ defined in grid_tbl.c
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the function Az_lsp()
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef AZ_LSP_H
+#define AZ_LSP_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define grid_points 60
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 grid[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void Az_lsp(
+ Word16 a[], /* (i) : predictor coefficients (MP1) */
+ Word16 lsp[], /* (o) : line spectral pairs (M) */
+ Word16 old_lsp[], /* (i) : old lsp[] (in case not found 10 roots) (M) */
+ Flag *pOverflow /* (i/o): overflow flag */
+ );
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AZ_LSP_H */
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/basic_op.h b/media/libstagefright/codecs/amrnb/common/include/basic_op.h
new file mode 100644
index 0000000..f6c80e2
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/basic_op.h
@@ -0,0 +1,448 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./include/basic_op.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Revised basic_op.h since the basicop2.c functions were split
+ up into separate source and header files. This function was
+ retained because there are legacy GSM AMR C functions that still
+ include this file. This file now includes the various basicop2
+ functions' header files instead of defining the function
+ prototypes.
+
+ Description: Including header files with platform specific inline assembly
+ instructions.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes all the basicop2.c functions' header files.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef BASIC_OP_H
+#define BASIC_OP_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+#if defined(PV_ARM_V5)
+#include "basic_op_arm_v5.h"
+
+#elif defined(PV_ARM_GCC_V5)
+#include "basic_op_arm_gcc_v5.h"
+
+#else
+#include "basic_op_c_equivalent.h"
+
+#endif
+
+
+
+#include "add.h"
+#include "div_s.h"
+#include "div_32.h"
+#include "extract_h.h"
+#include "extract_l.h"
+#include "l_deposit_h.h"
+#include "l_deposit_l.h"
+#include "l_shr_r.h"
+#include "mult_r.h"
+#include "norm_l.h"
+#include "norm_s.h"
+#include "round.h"
+#include "shr_r.h"
+#include "sub.h"
+#include "shr.h"
+#include "l_abs.h"
+#include "l_negate.h"
+#include "l_extract.h"
+#include "l_abs.h"
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: mac_32
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var3 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+ L_var1_hi = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ L_var1_lo = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+ L_var2_hi = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ L_var2_lo = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit mac operation resulted in overflow
+
+ Returns:
+ L_var3 = 32-bit result of L_var3 + (L_var1 * L_var2)(Word32)
+
+ */
+ static inline Word32 Mac_32(Word32 L_var3,
+ Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 L_var2_hi,
+ Word16 L_var2_lo,
+ Flag *pOverflow)
+ {
+ Word16 product;
+
+ L_var3 = L_mac(L_var3, L_var1_hi, L_var2_hi, pOverflow);
+
+ product = mult(L_var1_hi, L_var2_lo, pOverflow);
+ L_var3 = L_mac(L_var3, product, 1, pOverflow);
+
+ product = mult(L_var1_lo, L_var2_hi, pOverflow);
+ L_var3 = L_mac(L_var3, product, 1, pOverflow);
+
+ return (L_var3);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: mac_32_16
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var3 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+ L_var1_hi = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ L_var1_lo = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+ var2= 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit mac operation resulted in overflow
+
+ Returns:
+ L_var3 = 32-bit result of L_var3 + (L_var1 * var2)(Word32)
+ */
+
+ static inline Word32 Mac_32_16(Word32 L_var3,
+ Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 var2,
+ Flag *pOverflow)
+ {
+ Word16 product;
+
+ L_var3 = L_mac(L_var3, L_var1_hi, var2, pOverflow);
+
+ product = mult(L_var1_lo, var2, pOverflow);
+ L_var3 = L_mac(L_var3, product, 1, pOverflow);
+
+ return (L_var3);
+ }
+
+
+ /*----------------------------------------------------------------------------
+ Function Name : negate
+
+ Negate var1 with saturation, saturate in the case where input is -32768:
+ negate(var1) = sub(0,var1).
+
+ Inputs :
+ var1
+ 16 bit short signed integer (Word16) whose value falls in the
+ range : 0x8000 <= var1 <= 0x7fff.
+
+ Outputs :
+ none
+
+ Return Value :
+ 16 bit short signed integer (Word16) whose value falls in the
+ range : 0x8000 <= var_out <= 0x7fff.
+ ----------------------------------------------------------------------------*/
+
+ static inline Word16 negate(Word16 var1)
+ {
+ return (((var1 == MIN_16) ? MAX_16 : -var1));
+ }
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : shl
+
+ 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.
+
+ Inputs :
+ var1
+ 16 bit short signed integer (Word16) whose value falls in the
+ range : 0x8000 <= var1 <= 0x7fff.
+
+ var2
+ 16 bit short signed integer (Word16) whose value falls in the
+ range : 0x8000 <= var1 <= 0x7fff.
+
+ pOverflow : pointer to overflow (Flag)
+
+ Return Value :
+ var_out
+ 16 bit short signed integer (Word16) whose value falls in the
+ range : 0x8000 <= var_out <= 0x7fff.
+ ----------------------------------------------------------------------------*/
+
+ static inline Word16 shl(Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ Word16 var_out = 0;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ if (var2 < 0)
+ {
+ var2 = -var2;
+ if (var2 < 15)
+ {
+ var_out = var1 >> var2;
+ }
+
+ }
+ else
+ {
+ var_out = var1 << var2;
+ if (var_out >> var2 != var1)
+ {
+ var_out = (var1 >> 15) ^ MAX_16;
+ }
+ }
+ return (var_out);
+ }
+
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : L_shl
+
+ 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.
+
+ Inputs :
+ L_var1 32 bit long signed integer (Word32) whose value falls in the
+ range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ var2
+ 16 bit short signed integer (Word16) whose value falls in the
+ range : 8000 <= var2 <= 7fff.
+
+ pOverflow : pointer to overflow (Flag)
+
+ Return Value :
+ 32 bit long signed integer (Word32) whose value falls in the
+ range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+
+ ----------------------------------------------------------------------------*/
+
+ static inline Word32 L_shl(Word32 L_var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 L_var_out = 0;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ if (var2 > 0)
+ {
+ L_var_out = L_var1 << var2;
+ if (L_var_out >> var2 != L_var1)
+ {
+ L_var_out = (L_var1 >> 31) ^ MAX_32;
+ }
+ }
+ else
+ {
+ var2 = -var2;
+ if (var2 < 31)
+ {
+ L_var_out = L_var1 >> var2;
+ }
+
+ }
+
+ return (L_var_out);
+ }
+
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : L_shr
+
+ 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.
+
+ Inputs :
+ L_var1 32 bit long signed integer (Word32) whose value falls in the
+ range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ var2
+ 16 bit short signed integer (Word16) whose value falls in the
+ range : 8000 <= var2 <= 7fff.
+
+ pOverflow : pointer to overflow (Flag)
+
+ Return Value :
+ 32 bit long signed integer (Word32) whose value falls in the
+ range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+
+ ----------------------------------------------------------------------------*/
+
+ static inline Word32 L_shr(Word32 L_var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 L_var_out = 0;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ if (var2 > 0)
+ {
+ if (var2 < 31)
+ {
+ L_var_out = L_var1 >> var2;
+ }
+ }
+ else
+ {
+ var2 = -var2;
+
+ L_var_out = L_var1 << (var2) ;
+ if ((L_var_out >> (var2)) != L_var1)
+ {
+ L_var_out = (L_var1 >> 31) ^ MAX_32;
+ }
+
+ }
+
+ return (L_var_out);
+ }
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : abs_s
+
+ Absolute value of var1; abs_s(-32768) = 32767.
+
+ Inputs :
+ var1
+ 16 bit short signed integer (Word16) whose value falls in the
+ range : 0x8000 <= var1 <= 0x7fff.
+
+ pOverflow : pointer to overflow (Flag)
+
+ Outputs :
+ none
+
+ Return Value :
+ 16 bit short signed integer (Word16) whose value falls in the
+ range : 0x0000 <= var_out <= 0x7fff.
+
+ ----------------------------------------------------------------------------*/
+
+ static inline Word16 abs_s(Word16 var1)
+ {
+
+ Word16 y = var1 - (var1 < 0);
+ y = y ^(y >> 15);
+ return (y);
+
+ }
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* BASIC_OP_H */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h b/media/libstagefright/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h
new file mode 100644
index 0000000..48f0bcb
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h
@@ -0,0 +1,543 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./include/basic_op_arm_gcc_v5.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes all the GCC-ARM V5 basicop.c functions.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef BASIC_OP_ARM_GCC_V5_H
+#define BASIC_OP_ARM_GCC_V5_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_add
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ L_var2 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit add operation resulted in overflow
+
+ Returns:
+ L_sum = 32-bit sum of L_var1 and L_var2 (Word32)
+ */
+
+ __inline Word32 L_add(register Word32 L_var1, register Word32 L_var2, Flag *pOverflow)
+ {
+ register Word32 ra = L_var1;
+ register Word32 rb = L_var2;
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("qadd %0, %1, %2"
+ : "=r"(result)
+ : "r"(ra), "r"(rb)
+ );
+ return (result);
+
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_sub
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ L_var2 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit add operation resulted in overflow
+
+ Returns:
+ L_diff = 32-bit difference of L_var1 and L_var2 (Word32)
+ */
+ __inline Word32 L_sub(Word32 L_var1, Word32 L_var2, Flag *pOverflow)
+{
+ register Word32 ra = L_var1;
+ register Word32 rb = L_var2;
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("qsub %0, %1, %2"
+ : "=r"(result)
+ : "r"(ra), "r"(rb)
+ );
+
+ return (result);
+ }
+
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_mac
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit add operation resulted in overflow
+
+ Returns:
+ result = 32-bit result of L_var3 + (var1 * var2)(Word32)
+ */
+ static inline Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
+{
+ register Word32 ra = L_var3;
+ register Word32 rb = var1;
+ register Word32 rc = var2;
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(result)
+ : "r"(rb), "r"(rc)
+ );
+
+ asm volatile("qdadd %0, %1, %2"
+ : "=r"(rc)
+ : "r"(ra), "r"(result)
+ );
+
+ return (rc);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_mult
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ L_var2 = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit add operation resulted in overflow
+
+ Returns:
+ L_product = 32-bit product of L_var1 and L_var2 (Word32)
+ */
+
+ __inline Word32 L_mult(Word16 var1, Word16 var2, Flag *pOverflow)
+{
+ register Word32 ra = var1;
+ register Word32 rb = var2;
+ Word32 result;
+ Word32 product;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(product)
+ : "r"(ra), "r"(rb)
+ );
+
+ asm volatile("qadd %0, %1, %2"
+ : "=r"(result)
+ : "r"(product), "r"(product)
+ );
+
+ return(result);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_msu
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit operation resulted in overflow
+
+ Returns:
+ result = 32-bit result of L_var3 - (var1 * var2)
+ */
+ __inline Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
+{
+ register Word32 ra = L_var3;
+ register Word32 rb = var1;
+ register Word32 rc = var2;
+ Word32 product;
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(product)
+ : "r"(rb), "r"(rc)
+ );
+
+ asm volatile("qdsub %0, %1, %2"
+ : "=r"(result)
+ : "r"(ra), "r"(product)
+ );
+
+ return (result);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: Mpy_32
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1_hi = most significant word of first input (Word16).
+ L_var1_lo = least significant word of first input (Word16).
+ L_var2_hi = most significant word of second input (Word16).
+ L_var2_lo = least significant word of second input (Word16).
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit multiply operation resulted in overflow
+
+ Returns:
+ L_product = 32-bit product of L_var1 and L_var2 (Word32)
+ */
+ static inline Word32 Mpy_32(Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 L_var2_hi,
+ Word16 L_var2_lo,
+ Flag *pOverflow)
+{
+ register Word32 product32;
+ register Word32 L_sum;
+ register Word32 L_product, result;
+ register Word32 ra = L_var1_hi;
+ register Word32 rb = L_var1_lo;
+ register Word32 rc = L_var2_hi;
+ register Word32 rd = L_var2_lo;
+
+
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(L_product)
+ : "r"(ra), "r"(rc)
+ );
+ asm volatile("mov %0, #0"
+ : "=r"(result)
+ );
+
+ asm volatile("qdadd %0, %1, %2"
+ : "=r"(L_sum)
+ : "r"(result), "r"(L_product)
+ );
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(product32)
+ : "r"(ra), "r"(rd)
+ );
+
+ asm volatile("mov %0, %1, ASR #15"
+ : "=r"(ra)
+ : "r"(product32)
+ );
+ asm volatile("qdadd %0, %1, %2"
+ : "=r"(L_product)
+ : "r"(L_sum), "r"(ra)
+ );
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(product32)
+ : "r"(rb), "r"(rc)
+ );
+
+ asm volatile("mov %0, %1, ASR #15"
+ : "=r"(rb)
+ : "r"(product32)
+ );
+
+ asm volatile("qdadd %0, %1, %2"
+ : "=r"(L_sum)
+ : "r"(L_product), "r"(rb)
+ );
+
+ return (L_sum);
+ }
+
+
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: Mpy_32_16
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1_hi = most significant 16 bits of 32-bit input (Word16).
+ L_var1_lo = least significant 16 bits of 32-bit input (Word16).
+ var2 = 16-bit signed integer (Word16).
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit product operation resulted in overflow
+
+ Returns:
+ product = 32-bit product of the 32-bit L_var1 and 16-bit var1 (Word32)
+ */
+ static inline Word32 Mpy_32_16(Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 var2,
+ Flag *pOverflow)
+{
+
+ register Word32 ra = L_var1_hi;
+ register Word32 rb = L_var1_lo;
+ register Word32 rc = var2;
+ Word32 result, L_product;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(L_product)
+ : "r"(ra), "r"(rc)
+ );
+ asm volatile("mov %0, #0"
+ : "=r"(result)
+ );
+
+ asm volatile("qdadd %0, %1, %2"
+ : "=r"(L_product)
+ : "r"(result), "r"(L_product)
+ );
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(result)
+ : "r"(rb), "r"(rc)
+ );
+
+ asm volatile("mov %0, %1, ASR #15"
+ : "=r"(ra)
+ : "r"(result)
+ );
+ asm volatile("qdadd %0, %1, %2"
+ : "=r"(result)
+ : "r"(L_product), "r"(ra)
+ );
+
+ return (result);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: mult
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the add operation resulted in overflow
+
+ Returns:
+ product = 16-bit limited product of var1 and var2 (Word16)
+ */
+ __inline Word16 mult(Word16 var1, Word16 var2, Flag *pOverflow)
+{
+ register Word32 ra = var1;
+ register Word32 rb = var2;
+ Word32 product;
+ Word32 temp;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile(
+ "smulbb %0, %1, %2"
+ : "=r"(temp)
+ : "r"(ra), "r"(rb)
+ );
+ asm volatile(
+ "qadd %0, %1, %2\n\t"
+ "mov %0, %0, asr #16"
+ : "=&r*i"(product)
+ : "r"(temp), "r"(temp)
+ );
+
+ return ((Word16) product);
+ }
+
+ __inline Word32 amrnb_fxp_mac_16_by_16bb(Word32 L_var1, Word32 L_var2, Word32 L_var3)
+{
+ register Word32 ra = L_var1;
+ register Word32 rb = L_var2;
+ register Word32 rc = L_var3;
+ Word32 result;
+
+ asm volatile("smlabb %0, %1, %2, %3"
+ : "=r"(result)
+ : "r"(ra), "r"(rb), "r"(rc)
+ );
+ return (result);
+ }
+
+ __inline Word32 amrnb_fxp_msu_16_by_16bb(Word32 L_var1, Word32 L_var2, Word32 L_var3)
+{
+ register Word32 ra = L_var1;
+ register Word32 rb = L_var2;
+ register Word32 rc = L_var3;
+ Word32 result;
+
+ asm volatile("rsb %0, %1, #0"
+ : "=r"(ra)
+ : "r"(ra)
+ );
+
+ asm volatile("smlabb %0, %1, %2, %3"
+ : "=r"(result)
+ : "r"(ra), "r"(rb), "r"(rc)
+ );
+ return (result);
+ }
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BASIC_OP_ARM_GCC_V5_H */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/basic_op_arm_v5.h b/media/libstagefright/codecs/amrnb/common/include/basic_op_arm_v5.h
new file mode 100644
index 0000000..c939356
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/basic_op_arm_v5.h
@@ -0,0 +1,440 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./include/basic_op_arm_v5.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes all the ARM-V5 based basicop.c functions.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef BASIC_OP_ARM_V5_H
+#define BASIC_OP_ARM_V5_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_add
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ L_var2 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit add operation resulted in overflow
+
+ Returns:
+ L_sum = 32-bit sum of L_var1 and L_var2 (Word32)
+ */
+
+ __inline Word32 L_add(register Word32 L_var1, register Word32 L_var2, Flag *pOverflow)
+ {
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+ __asm
+ {
+ QADD result, L_var1, L_var2
+ }
+ return(result);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_sub
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ L_var2 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit add operation resulted in overflow
+
+ Returns:
+ L_diff = 32-bit difference of L_var1 and L_var2 (Word32)
+ */
+ __inline Word32 L_sub(Word32 L_var1, Word32 L_var2, Flag *pOverflow)
+ {
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ __asm
+ {
+ QSUB result, L_var1, L_var2
+ }
+
+ return(result);
+
+ }
+
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_mac
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit add operation resulted in overflow
+
+ Returns:
+ result = 32-bit result of L_var3 + (var1 * var2)(Word32)
+ */
+ __inline Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 result;
+ Word32 L_sum;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ __asm {SMULBB result, var1, var2}
+ __asm {QDADD L_sum, L_var3, result}
+ return (L_sum);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_mult
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ L_var2 = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit add operation resulted in overflow
+
+ Returns:
+ L_product = 32-bit product of L_var1 and L_var2 (Word32)
+ */
+ __inline Word32 L_mult(Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 result;
+ Word32 product;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ __asm
+ {
+ SMULBB product, var1, var2
+ QADD result, product, product
+ }
+
+ return (result);
+ }
+
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_msu
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit operation resulted in overflow
+
+ Returns:
+ result = 32-bit result of L_var3 - (var1 * var2)
+ */
+ __inline Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 product;
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ __asm
+ {
+ SMULBB product, var1, var2
+ QDSUB result, L_var3, product
+ }
+
+ return (result);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: Mpy_32
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1_hi = most significant word of first input (Word16).
+ L_var1_lo = least significant word of first input (Word16).
+ L_var2_hi = most significant word of second input (Word16).
+ L_var2_lo = least significant word of second input (Word16).
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit multiply operation resulted in overflow
+
+ Returns:
+ L_product = 32-bit product of L_var1 and L_var2 (Word32)
+ */
+ __inline Word32 Mpy_32(Word16 L_var1_hi, Word16 L_var1_lo, Word16 L_var2_hi,
+ Word16 L_var2_lo, Flag *pOverflow)
+
+ {
+
+ Word32 L_product;
+ Word32 L_sum;
+ Word32 product32;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ __asm
+ {
+ SMULBB L_product, L_var1_hi, L_var2_hi
+ QDADD L_product, 0, L_product
+ SMULBB product32, L_var1_hi, L_var2_lo
+ }
+ product32 >>= 15;
+ __asm
+ {
+ QDADD L_sum, L_product, product32
+ }
+ L_product = L_sum;
+ __asm
+ {
+ SMULBB product32, L_var1_lo, L_var2_hi
+ }
+ product32 >>= 15;
+ __asm
+ {
+ QDADD L_sum, L_product, product32
+ }
+ return (L_sum);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: Mpy_32_16
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1_hi = most significant 16 bits of 32-bit input (Word16).
+ L_var1_lo = least significant 16 bits of 32-bit input (Word16).
+ var2 = 16-bit signed integer (Word16).
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit product operation resulted in overflow
+
+ Returns:
+ product = 32-bit product of the 32-bit L_var1 and 16-bit var1 (Word32)
+ */
+ __inline Word32 Mpy_32_16(Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 var2,
+ Flag *pOverflow)
+ {
+
+ Word32 L_product;
+ Word32 L_sum;
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ __asm {SMULBB L_product, L_var1_hi, var2}
+ __asm {QDADD L_product, 0, L_product}
+ __asm {SMULBB result, L_var1_lo, var2}
+ result >>= 15;
+ __asm {QDADD L_sum, L_product, result}
+ return (L_sum);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: mult
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the add operation resulted in overflow
+
+ Returns:
+ product = 16-bit limited product of var1 and var2 (Word16)
+ */
+ __inline Word16 mult(Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 product;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ __asm
+ {
+ SMULBB product, var1, var2
+ MOV product, product, ASR #15
+ CMP product, 0x7FFF
+ MOVGE product, 0x7FFF
+ }
+
+ return ((Word16) product);
+ }
+
+ __inline Word32 amrnb_fxp_mac_16_by_16bb(Word32 L_var1, Word32 L_var2, Word32 L_var3)
+ {
+ Word32 result;
+ __asm
+ {
+ smlabb result, L_var1, L_var2, L_var3
+ }
+ return result;
+ }
+
+ __inline Word32 amrnb_fxp_msu_16_by_16bb(Word32 L_var1, Word32 L_var2, Word32 L_var3)
+ {
+ Word32 result;
+ __asm
+ {
+ rsb L_var1, L_var1, #0
+ smlabb result, L_var1, L_var2, L_var3
+ }
+ return result;
+ }
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BASIC_OP_ARM_V5_H */
diff --git a/media/libstagefright/codecs/amrnb/common/include/basic_op_c_equivalent.h b/media/libstagefright/codecs/amrnb/common/include/basic_op_c_equivalent.h
new file mode 100644
index 0000000..35638e3
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/basic_op_c_equivalent.h
@@ -0,0 +1,505 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./include/basic_op_c_equivalent.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes all the C-Equivalent basicop.c functions.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef BASIC_OP_C_EQUIVALENT_H
+#define BASIC_OP_C_EQUIVALENT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_add
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ L_var2 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit add operation resulted in overflow
+
+ Returns:
+ L_sum = 32-bit sum of L_var1 and L_var2 (Word32)
+ */
+ static inline Word32 L_add(register Word32 L_var1, register Word32 L_var2, Flag *pOverflow)
+ {
+ Word32 L_sum;
+
+ L_sum = L_var1 + L_var2;
+
+ if ((L_var1 ^ L_var2) >= 0)
+ {
+ if ((L_sum ^ L_var1) < 0)
+ {
+ L_sum = (L_var1 < 0) ? MIN_32 : MAX_32;
+ *pOverflow = 1;
+ }
+ }
+
+ return (L_sum);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_sub
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ L_var2 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit add operation resulted in overflow
+
+ Returns:
+ L_diff = 32-bit difference of L_var1 and L_var2 (Word32)
+ */
+ static inline Word32 L_sub(register Word32 L_var1, register Word32 L_var2,
+ register Flag *pOverflow)
+ {
+ Word32 L_diff;
+
+ L_diff = L_var1 - L_var2;
+
+ if ((L_var1 ^ L_var2) < 0)
+ {
+ if ((L_diff ^ L_var1) & MIN_32)
+ {
+ L_diff = (L_var1 < 0L) ? MIN_32 : MAX_32;
+ *pOverflow = 1;
+ }
+ }
+
+ return (L_diff);
+ }
+
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_mac
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit add operation resulted in overflow
+
+ Returns:
+ result = 32-bit result of L_var3 + (var1 * var2)(Word32)
+ */
+ __inline Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 result;
+ Word32 L_sum;
+ result = (Word32) var1 * var2;
+ if (result != (Word32) 0x40000000L)
+ {
+ L_sum = (result << 1) + L_var3;
+
+ /* Check if L_sum and L_var_3 share the same sign */
+ if ((L_var3 ^ result) > 0)
+ {
+ if ((L_sum ^ L_var3) < 0)
+ {
+ L_sum = (L_var3 < 0) ? MIN_32 : MAX_32;
+ *pOverflow = 1;
+ }
+ }
+ }
+ else
+ {
+ *pOverflow = 1;
+ L_sum = MAX_32;
+ }
+ return (L_sum);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_mult
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ L_var2 = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit add operation resulted in overflow
+
+ Returns:
+ L_product = 32-bit product of L_var1 and L_var2 (Word32)
+ */
+ static inline Word32 L_mult(Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ register Word32 L_product;
+
+ L_product = (Word32) var1 * var2;
+
+ if (L_product != (Word32) 0x40000000L)
+ {
+ L_product <<= 1; /* Multiply by 2 */
+ }
+ else
+ {
+ *pOverflow = 1;
+ L_product = MAX_32;
+ }
+
+ return (L_product);
+ }
+
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: L_msu
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit operation resulted in overflow
+
+ Returns:
+ result = 32-bit result of L_var3 - (var1 * var2)
+ */
+
+ static inline Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 result;
+
+ result = L_mult(var1, var2, pOverflow);
+ result = L_sub(L_var3, result, pOverflow);
+
+ return (result);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: Mpy_32
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1_hi = most significant word of first input (Word16).
+ L_var1_lo = least significant word of first input (Word16).
+ L_var2_hi = most significant word of second input (Word16).
+ L_var2_lo = least significant word of second input (Word16).
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit multiply operation resulted in overflow
+
+ Returns:
+ L_product = 32-bit product of L_var1 and L_var2 (Word32)
+ */
+ __inline Word32 Mpy_32(Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 L_var2_hi,
+ Word16 L_var2_lo,
+ Flag *pOverflow)
+ {
+ Word32 L_product;
+ Word32 L_sum;
+ Word32 product32;
+
+ OSCL_UNUSED_ARG(pOverflow);
+ L_product = (Word32) L_var1_hi * L_var2_hi;
+
+ if (L_product != (Word32) 0x40000000L)
+ {
+ L_product <<= 1;
+ }
+ else
+ {
+ L_product = MAX_32;
+ }
+
+ /* result = mult (L_var1_hi, L_var2_lo, pOverflow); */
+ product32 = ((Word32) L_var1_hi * L_var2_lo) >> 15;
+
+ /* L_product = L_mac (L_product, result, 1, pOverflow); */
+ L_sum = L_product + (product32 << 1);
+
+ if ((L_product ^ product32) > 0)
+ {
+ if ((L_sum ^ L_product) < 0)
+ {
+ L_sum = (L_product < 0) ? MIN_32 : MAX_32;
+ }
+ }
+
+ L_product = L_sum;
+
+ /* result = mult (L_var1_lo, L_var2_hi, pOverflow); */
+ product32 = ((Word32) L_var1_lo * L_var2_hi) >> 15;
+
+ /* L_product = L_mac (L_product, result, 1, pOverflow); */
+ L_sum = L_product + (product32 << 1);
+
+ if ((L_product ^ product32) > 0)
+ {
+ if ((L_sum ^ L_product) < 0)
+ {
+ L_sum = (L_product < 0) ? MIN_32 : MAX_32;
+ }
+ }
+ return (L_sum);
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: Mpy_32_16
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1_hi = most significant 16 bits of 32-bit input (Word16).
+ L_var1_lo = least significant 16 bits of 32-bit input (Word16).
+ var2 = 16-bit signed integer (Word16).
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit product operation resulted in overflow
+
+ Returns:
+ product = 32-bit product of the 32-bit L_var1 and 16-bit var1 (Word32)
+ */
+
+ __inline Word32 Mpy_32_16(Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 var2,
+ Flag *pOverflow)
+ {
+
+ Word32 L_product;
+ Word32 L_sum;
+ Word32 result;
+ L_product = (Word32) L_var1_hi * var2;
+
+ if (L_product != (Word32) 0x40000000L)
+ {
+ L_product <<= 1;
+ }
+ else
+ {
+ *pOverflow = 1;
+ L_product = MAX_32;
+ }
+
+ result = ((Word32)L_var1_lo * var2) >> 15;
+
+ L_sum = L_product + (result << 1);
+
+ if ((L_product ^ result) > 0)
+ {
+ if ((L_sum ^ L_product) < 0)
+ {
+ L_sum = (L_product < 0) ? MIN_32 : MAX_32;
+ *pOverflow = 1;
+ }
+ }
+ return (L_sum);
+
+ }
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: mult
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the add operation resulted in overflow
+
+ Returns:
+ product = 16-bit limited product of var1 and var2 (Word16)
+ */
+ static inline Word16 mult(Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ register Word32 product;
+
+ product = ((Word32) var1 * var2) >> 15;
+
+ /* Saturate result (if necessary). */
+ /* var1 * var2 >0x00007fff is the only case */
+ /* that saturation occurs. */
+
+ if (product > 0x00007fffL)
+ {
+ *pOverflow = 1;
+ product = (Word32) MAX_16;
+ }
+
+
+ /* Return the product as a 16 bit value by type casting Word32 to Word16 */
+
+ return ((Word16) product);
+ }
+
+
+ static inline Word32 amrnb_fxp_mac_16_by_16bb(Word32 L_var1, Word32 L_var2, Word32 L_var3)
+ {
+ Word32 result;
+
+ result = L_var3 + L_var1 * L_var2;
+
+ return result;
+ }
+
+ static inline Word32 amrnb_fxp_msu_16_by_16bb(Word32 L_var1, Word32 L_var2, Word32 L_var3)
+ {
+ Word32 result;
+
+ result = L_var3 - L_var1 * L_var2;
+
+ return result;
+ }
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BASIC_OP_C_EQUIVALENT_H */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/basicop_malloc.h b/media/libstagefright/codecs/amrnb/common/include/basicop_malloc.h
new file mode 100644
index 0000000..363d148
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/basicop_malloc.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/include/basicop_malloc.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains constant definitions and external references to the stores
+ used by any arithmetic function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef BASICOP_MALLOC_H
+#define BASICOP_MALLOC_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define MAX_32 (Word32)0x7fffffffL
+#define MIN_32 (Word32)0x80000000L
+
+#define MAX_16 (Word16)0x7fff
+#define MIN_16 (Word16)0x8000
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern Flag Overflow;
+ extern Flag Carry;
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/bitno_tab.h b/media/libstagefright/codecs/amrnb/common/include/bitno_tab.h
new file mode 100644
index 0000000..a170750
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/bitno_tab.h
@@ -0,0 +1,146 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: .audio/gsm-amr/c/include/bitno_tab.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Define "const Word16 *bitno[N_MODES]" as "const Word16 *const
+ bitno[N_MODES]"
+
+ Description: Added #ifdef __cplusplus after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file declares a tables in bitno_tab.c.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef BITNO_TAB_H
+#define BITNO_TAB_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define BIT_0 0
+#define BIT_1 1
+
+#define PRMNO_MR475 17
+#define PRMNO_MR515 19
+#define PRMNO_MR59 19
+#define PRMNO_MR67 19
+#define PRMNO_MR74 19
+#define PRMNO_MR795 23
+#define PRMNO_MR102 39
+#define PRMNO_MR122 57
+#define PRMNO_MRDTX 5
+
+ /* number of parameters to first subframe */
+#define PRMNOFSF_MR475 7
+#define PRMNOFSF_MR515 7
+#define PRMNOFSF_MR59 7
+#define PRMNOFSF_MR67 7
+#define PRMNOFSF_MR74 7
+#define PRMNOFSF_MR795 8
+#define PRMNOFSF_MR102 12
+#define PRMNOFSF_MR122 18
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 prmno[];
+ extern const Word16 prmnofsf[];
+ extern const Word16 bitno_MR475[];
+ extern const Word16 bitno_MR515[];
+ extern const Word16 bitno_MR59[];
+ extern const Word16 bitno_MR67[];
+ extern const Word16 bitno_MR74[];
+ extern const Word16 bitno_MR95[];
+ extern const Word16 bitno_MR102[];
+ extern const Word16 bitno_MR122[];
+ extern const Word16 bitno_MRDTX[];
+ extern const Word16 *const bitno[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/bitreorder_tab.h b/media/libstagefright/codecs/amrnb/common/include/bitreorder_tab.h
new file mode 100644
index 0000000..bfcb4cf
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/bitreorder_tab.h
@@ -0,0 +1,125 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: .audio/gsm-amr/c/include/bitreorder.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Define "const Word16 *reorderBits[NUM_MODES-1]" as
+ "const Word16 *const reorderBits[NUM_MODES-1]".
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Added #ifdef __cplusplus after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file declares a tables in bitreorder.c.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef BITREORDER_H
+#define BITREORDER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 numOfBits[];
+ extern const Word16 reorderBits_MR475[];
+ extern const Word16 reorderBits_MR515[];
+ extern const Word16 reorderBits_MR59[];
+ extern const Word16 reorderBits_MR67[];
+ extern const Word16 reorderBits_MR74[];
+ extern const Word16 reorderBits_MR795[];
+ extern const Word16 reorderBits_MR102[];
+ extern const Word16 reorderBits_MR122[];
+
+ extern const Word16 *const reorderBits[];
+ extern const Word16 numCompressedBytes[];
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/bits2prm.h b/media/libstagefright/codecs/amrnb/common/include/bits2prm.h
new file mode 100644
index 0000000..6a11bb4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/bits2prm.h
@@ -0,0 +1,91 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+*****************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+*****************************************************************************
+*
+* File : bits2prm.h
+* Purpose : Retrieves the vector of encoder parameters from
+* : the received serial bits in a frame.
+*
+*****************************************************************************
+*/
+#ifndef bits2prm_h
+#define bits2prm_h "$Id $"
+
+/*
+*****************************************************************************
+* INCLUDE FILES
+*****************************************************************************
+*/
+#include "typedef.h"
+#include "mode.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ *****************************************************************************
+ * DEFINITION OF DATA TYPES
+ *****************************************************************************
+ */
+
+ /*
+ *****************************************************************************
+ * DECLARATION OF PROTOTYPES
+ *****************************************************************************
+ */
+ /*
+ **************************************************************************
+ *
+ * Function : Bits2prm
+ * Purpose : Retrieves the vector of encoder parameters from
+ * the received serial bits in a frame.
+ * Returns : void
+ *
+ **************************************************************************
+ */
+ OSCL_IMPORT_REF void Bits2prm(
+ enum Mode mode,
+ Word16 bits[], /* input : serial bits, (244 + bfi) */
+ Word16 prm[] /* output: analysis parameters, (57+1 parameters) */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/bytesused.h b/media/libstagefright/codecs/amrnb/common/include/bytesused.h
new file mode 100644
index 0000000..934efbe
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/bytesused.h
@@ -0,0 +1,109 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: .audio/gsm-amr/c/include/BytesUsed.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file declares a table BytesUsed.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef BYTESUSED_H
+#define BYTESUSED_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const short BytesUsed[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/cnst.h b/media/libstagefright/codecs/amrnb/common/include/cnst.h
new file mode 100644
index 0000000..b648eb7
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/cnst.h
@@ -0,0 +1,129 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ INCLUDE DESCRIPTION
+
+ This file contains the Speech code (encoder, decoder, and postfilter)
+ constant parameters.
+
+ NOTE: This file must be synchronized with /gsm-amr/asm/include/cnst.inc file.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef _CNST_H_
+#define _CNST_H_
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define L_TOTAL 320 /* Total size of speech buffer. */
+#define L_WINDOW 240 /* Window size in LP analysis */
+#define L_FRAME 160 /* Frame size */
+#define L_FRAME_BY2 80 /* Frame size divided by 2 */
+#define L_SUBFR 40 /* Subframe size */
+#define L_CODE 40 /* codevector length */
+#define NB_TRACK 5 /* number of tracks */
+#define STEP 5 /* codebook step size */
+#define NB_TRACK_MR102 4 /* number of tracks mode mr102 */
+#define STEP_MR102 4 /* codebook step size mode mr102 */
+#define M 10 /* Order of LP filter */
+#define MP1 (M+1) /* Order of LP filter + 1 */
+#define LSF_GAP 205 /* Minimum distance between LSF after quan- */
+ /* tization; 50 Hz = 205 */
+#define LSP_PRED_FAC_MR122 21299 /* MR122 LSP prediction factor (0.65 Q15) */
+#define AZ_SIZE (4*M+4) /* Size of array of LP filters in 4 subfr.s */
+#define PIT_MIN_MR122 18 /* Minimum pitch lag (MR122 mode) */
+#define PIT_MIN 20 /* Minimum pitch lag (all other modes) */
+#define PIT_MAX 143 /* Maximum pitch lag */
+#define L_INTERPOL (10+1) /* Length of filter for interpolation */
+#define L_INTER_SRCH 4 /* Length of filter for CL LTP search */
+ /* interpolation */
+
+#define MU 26214 /* Factor for tilt compensation filter 0.8 */
+#define AGC_FAC 29491 /* Factor for automatic gain control 0.9 */
+
+#define L_NEXT 40 /* Overhead in LP analysis */
+#define SHARPMAX 13017 /* Maximum value of pitch sharpening */
+#define SHARPMIN 0 /* Minimum value of pitch sharpening */
+
+
+#define MAX_PRM_SIZE 57 /* max. num. of params */
+#define MAX_SERIAL_SIZE 244 /* max. num. of serial bits */
+
+#define GP_CLIP 15565 /* Pitch gain clipping = 0.95 */
+#define N_FRAME 7 /* old pitch gains in average calculation */
+
+#define EHF_MASK 0x0008 /* encoder homing frame pattern */
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CNST_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/cnst_vad.h b/media/libstagefright/codecs/amrnb/common/include/cnst_vad.h
new file mode 100644
index 0000000..6877a1b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/cnst_vad.h
@@ -0,0 +1,133 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+**-------------------------------------------------------------------------**
+** **
+** GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001 **
+** R99 Version 3.2.0 **
+** REL-4 Version 4.0.0 **
+** **
+**-------------------------------------------------------------------------**
+********************************************************************************
+*
+* File : cnst_vad.h
+* Purpose : Constants and definitions for VAD
+*
+********************************************************************************
+*/
+#ifndef cnst_vad_h
+#define cnst_vad_h "$Id $"
+
+#define FRAME_LEN 160 /* Length (samples) of the input frame */
+#define COMPLEN 9 /* Number of sub-bands used by VAD */
+#define INV_COMPLEN 3641 /* 1.0/COMPLEN*2^15 */
+#define LOOKAHEAD 40 /* length of the lookahead used by speech coder */
+
+#define UNITY 512 /* Scaling used with SNR calculation */
+#define UNIRSHFT 6 /* = log2(MAX_16/UNITY) */
+
+#define TONE_THR (Word16)(0.65*MAX_16) /* Threshold for tone detection */
+
+/* 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 VAD_THR_HIGH 1260 /* Highest threshold */
+#define VAD_THR_LOW 720 /* Lowest threshold */
+#define VAD_P1 0 /* Noise level for highest threshold */
+#define VAD_P2 6300 /* Noise level for lowest threshold */
+#define VAD_SLOPE (Word16)(MAX_16*(float)(VAD_THR_LOW-VAD_THR_HIGH)/(float)(VAD_P2-VAD_P1))
+
+/* Parameters for background spectrum recovery function */
+#define STAT_COUNT 20 /* threshold of stationary detection counter */
+#define STAT_COUNT_BY_2 10 /* threshold of stationary detection counter */
+#define CAD_MIN_STAT_COUNT 5 /* 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 16000 /* maximum */
+#define NOISE_INIT 150 /* initial */
+
+/* Constants for VAD hangover addition */
+#define HANG_NOISE_THR 100
+#define BURST_LEN_HIGH_NOISE 4
+#define HANG_LEN_HIGH_NOISE 7
+#define BURST_LEN_LOW_NOISE 5
+#define HANG_LEN_LOW_NOISE 4
+
+/* Thresholds for signal power */
+#define VAD_POW_LOW (Word32)15000 /* If input power is lower, */
+/* VAD is set to 0 */
+#define POW_PITCH_THR (Word32)343040 /* If input power is lower, pitch */
+/* detection is ignored */
+
+#define POW_COMPLEX_THR (Word32)15000 /* If input power is lower, complex */
+/* flags value for previous frame is un-set */
+
+
+/* Constants for the filter bank */
+#define LEVEL_SHIFT 0 /* scaling */
+#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 */
+
+/* Constants for pitch detection */
+#define LTHRESH 4
+#define NTHRESH 4
+
+/* Constants for complex signal VAD */
+#define CVAD_THRESH_ADAPT_HIGH (Word16)(0.6 * MAX_16) /* threshold for adapt stopping high */
+#define CVAD_THRESH_ADAPT_LOW (Word16)(0.5 * MAX_16) /* threshold for adapt stopping low */
+#define CVAD_THRESH_IN_NOISE (Word16)(0.65 * MAX_16) /* threshold going into speech on */
+/* a short term basis */
+
+#define CVAD_THRESH_HANG (Word16)(0.70 * MAX_16) /* threshold */
+#define CVAD_HANG_LIMIT (Word16)(100) /* 2 second estimation time */
+#define CVAD_HANG_LENGTH (Word16)(250) /* 5 second hangover */
+
+#define CVAD_LOWPOW_RESET (Word16) (0.40 * MAX_16) /* init in low power segment */
+#define CVAD_MIN_CORR (Word16) (0.40 * MAX_16) /* lowest adaptation value */
+
+#define CVAD_BURST 20 /* speech burst length for speech reset */
+#define CVAD_ADAPT_SLOW (Word16)(( 1.0 - 0.98) * MAX_16) /* threshold for slow adaption */
+#define CVAD_ADAPT_FAST (Word16)((1.0 - 0.92) * MAX_16) /* threshold for fast adaption */
+#define CVAD_ADAPT_REALLY_FAST (Word16)((1.0 - 0.80) * MAX_16) /* threshold for really fast */
+/* adaption */
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/copy.h b/media/libstagefright/codecs/amrnb/common/include/copy.h
new file mode 100644
index 0000000..b539ebb
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/copy.h
@@ -0,0 +1,88 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+* File : copy.h
+* Purpose : Copy vector x[] to y[]
+*
+********************************************************************************
+*/
+#ifndef copy_h
+#define copy_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ ********************************************************************************
+ * DEFINITION OF DATA TYPES
+ ********************************************************************************
+ */
+
+ /*
+ ********************************************************************************
+ * DECLARATION OF PROTOTYPES
+ ********************************************************************************
+ */
+
+ /*
+ **************************************************************************
+ *
+ * Function : Copy
+ * Purpose : Copy vector x[] to y[], vector length L
+ * Returns : void
+ *
+ **************************************************************************
+ */
+ void Copy(
+ const Word16 x[], /* i : input vector (L) */
+ Word16 y[], /* o : output vector (L) */
+ Word16 L /* i : vector length */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/d_gain_c.h b/media/libstagefright/codecs/amrnb/common/include/d_gain_c.h
new file mode 100644
index 0000000..70868f4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/d_gain_c.h
@@ -0,0 +1,125 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/include/d_gain_c.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : d_gain_c.h
+ Purpose : Decode the fixed codebook gain using the received index.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _D_GAIN_C_H_
+#define _D_GAIN_C_H_
+#define d_gain_c_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "gc_pred.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ /*
+ * Function : d_gain_code
+ * Purpose : Decode the fixed codebook gain using the received index.
+ * Description : The received index gives the gain correction factor
+ * gamma. The quantized gain is given by g_q = g0 * gamma
+ * where g0 is the predicted gain. To find g0, 4th order
+ * MA prediction is applied to the mean-removed innovation
+ * energy in dB.
+ * Returns : void
+ */
+ void d_gain_code(
+ gc_predState *pred_state, /* i/o : MA predictor state */
+ enum Mode mode, /* i : AMR mode */
+ Word16 index, /* i : received quantization index */
+ Word16 code[], /* i : innovation codevector */
+ Word16 *gain_code, /* o : decoded innovation gain */
+ Flag *pOverflow
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _D_GAIN_C_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/d_gain_p.h b/media/libstagefright/codecs/amrnb/common/include/d_gain_p.h
new file mode 100644
index 0000000..fec072b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/d_gain_p.h
@@ -0,0 +1,80 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : d_gain_p.h
+* Purpose : Decodes the pitch gain using the received index.
+*
+********************************************************************************
+*/
+#ifndef d_gain_p_h
+#define d_gain_p_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+#include "mode.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ **************************************************************************
+ *
+ * Function : d_gain_pitch
+ * Purpose : Decodes the pitch gain using the received index.
+ * Description : In case of no frame erasure, the gain is obtained
+ * from the quantization table at the given index;
+ * otherwise, a downscaled past gain is used.
+ * Returns : Quantized pitch gain
+ *
+ **************************************************************************
+ */
+ Word16 d_gain_pitch( /* return value: gain (Q14) */
+ enum Mode mode, /* i : AMR mode */
+ Word16 index /* i : index of quantization */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/d_plsf.h b/media/libstagefright/codecs/amrnb/common/include/d_plsf.h
new file mode 100644
index 0000000..0e5ca9a
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/d_plsf.h
@@ -0,0 +1,199 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/d_plsf.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the d_plsf_3.c and d_plsf_5.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef d_plsf_h
+#define d_plsf_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+#include "mode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 past_r_q[M]; /* Past quantized prediction error, Q15 */
+ Word16 past_lsf_q[M]; /* Past dequantized lsfs, Q15 */
+ } D_plsfState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*
+ **************************************************************************
+ *
+ * Function : D_plsf_reset
+ * Purpose : Resets state memory
+ * Returns : 0 on success
+ *
+ **************************************************************************
+ */
+ Word16 D_plsf_reset(D_plsfState *st);
+
+ /*
+ **************************************************************************
+ *
+ * Function : D_plsf_exit
+ * Purpose : The memory used for state memory is freed
+ * Description : Stores NULL in *st
+ * Returns : void
+ *
+ **************************************************************************
+ */
+ void D_plsf_exit(D_plsfState **st);
+
+ /*
+ **************************************************************************
+ *
+ * Function : D_plsf_5
+ * Purpose : Decodes the 2 sets of LSP parameters in a frame
+ * using the received quantization indices.
+ * Description : The two sets of LSFs are quantized using split by
+ * 5 matrix quantization (split-MQ) with 1st order MA
+ * prediction.
+ * See "q_plsf_5.c" for more details about the
+ * quantization procedure
+ * Returns : 0
+ *
+ **************************************************************************
+ */
+ void D_plsf_5(
+ D_plsfState *st, /* i/o: State variables */
+ Word16 bfi, /* i : bad frame indicator (set to 1 if a bad
+ frame is received) */
+ Word16 *indice, /* i : quantization indices of 5 submatrices, Q0 */
+ Word16 *lsp1_q, /* o : quantized 1st LSP vector (M) Q15 */
+ Word16 *lsp2_q, /* o : quantized 2nd LSP vector (M) Q15 */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ /*************************************************************************
+ *
+ * FUNCTION: D_plsf_3()
+ *
+ * PURPOSE: Decodes the LSP parameters using the received quantization
+ * indices.1st order MA prediction and split by 3 matrix
+ * quantization (split-MQ)
+ *
+ *************************************************************************/
+
+ void D_plsf_3(
+ D_plsfState *st, /* i/o: State struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 bfi, /* i : bad frame indicator (set to 1 if a */
+ /* bad frame is received) */
+ Word16 * indice, /* i : quantization indices of 3 submatrices, Q0 */
+ Word16 * lsp1_q, /* o : quantized 1st LSP vector, Q15 */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ /*************************************************************************
+ *
+ * FUNCTION: Init_D_plsf_3()
+ *
+ * PURPOSE: Set the past_r_q[M] vector to one of the eight
+ * past_rq_init vectors.
+ *
+ *************************************************************************/
+ void Init_D_plsf_3(D_plsfState *st, /* i/o: State struct */
+ Word16 index /* i : past_rq_init[] index [0, 7] */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _Q_PLSF_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/div_32.h b/media/libstagefright/codecs/amrnb/common/include/div_32.h
new file mode 100644
index 0000000..28b726b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/div_32.h
@@ -0,0 +1,116 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/div_32.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the Div_32 function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef DIV_32_H
+#define DIV_32_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word32 Div_32(Word32 L_num,
+ Word16 L_denom_hi,
+ Word16 L_denom_lo,
+ Flag *pOverflow) ;
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DIV_32_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/div_s.h b/media/libstagefright/codecs/amrnb/common/include/div_s.h
new file mode 100644
index 0000000..e8421db
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/div_s.h
@@ -0,0 +1,114 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/include/div_s.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for div_s function.
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the div_s function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef DIV_S_H
+#define DIV_S_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 div_s(Word16 var1, Word16 var2);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/dtx_common_def.h b/media/libstagefright/codecs/amrnb/common/include/dtx_common_def.h
new file mode 100644
index 0000000..c29b9e1
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/dtx_common_def.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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Filename: /audio/gsm_amr/c/include/dtx_common_def.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : dtx_common_def.h
+ Purpose : DTX definitions common to encoder and decoder
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef DTX_COMMON_DEF_H
+#define DTX_COMMON_DEF_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define DTX_MAX_EMPTY_THRESH 50
+#define DTX_HIST_SIZE 8
+#define DTX_ELAPSED_FRAMES_THRESH (24 + 7 -1)
+#define DTX_HANG_CONST 7 /* yields eight frames of SP HANGOVER */
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DTX_COMMON_DEF_H */
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/extract_h.h b/media/libstagefright/codecs/amrnb/common/include/extract_h.h
new file mode 100644
index 0000000..34a623f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/extract_h.h
@@ -0,0 +1,114 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/include/extract_h.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for extract_h function.
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the extract_h function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef EXTRACT_H_H
+#define EXTRACT_H_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 extract_h(Word32 L_var1);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/extract_l.h b/media/libstagefright/codecs/amrnb/common/include/extract_l.h
new file mode 100644
index 0000000..ed7460d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/extract_l.h
@@ -0,0 +1,114 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/include/extract_l.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for extract_l function.
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the extract_l function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef EXTRACT_L_H
+#define EXTRACT_L_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 extract_l(Word32 L_var1);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/frame.h b/media/libstagefright/codecs/amrnb/common/include/frame.h
new file mode 100644
index 0000000..1d0c6c1
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/frame.h
@@ -0,0 +1,114 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+*****************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+*****************************************************************************
+*
+* File : frame.h
+* Purpose : Declaration of received and transmitted frame types
+*
+*****************************************************************************
+*/
+#ifndef frame_h
+#define frame_h "$Id $"
+
+/*
+*****************************************************************************
+* INCLUDE FILES
+*****************************************************************************
+*/
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ *****************************************************************************
+ * DEFINITION OF DATA TYPES
+ *****************************************************************************
+ * Note: The order of the TX and RX_Type identifiers has been chosen in
+ * the way below to be compatible to an earlier version of the
+ * AMR-NB C reference program.
+ *****************************************************************************
+ */
+
+ enum RXFrameType { RX_SPEECH_GOOD = 0,
+ RX_SPEECH_DEGRADED,
+ RX_ONSET,
+ RX_SPEECH_BAD,
+ RX_SID_FIRST,
+ RX_SID_UPDATE,
+ RX_SID_BAD,
+ RX_NO_DATA,
+ RX_N_FRAMETYPES /* number of frame types */
+ };
+
+ enum TXFrameType { TX_SPEECH_GOOD = 0,
+ TX_SID_FIRST,
+ TX_SID_UPDATE,
+ TX_NO_DATA,
+ TX_SPEECH_DEGRADED,
+ TX_SPEECH_BAD,
+ TX_SID_BAD,
+ TX_ONSET,
+ TX_N_FRAMETYPES /* number of frame types */
+ };
+
+
+ /* Channel decoded frame type */
+ enum CHDECFrameType { CHDEC_SID_FIRST = 0,
+ CHDEC_SID_FIRST_INCOMPLETE,
+ CHDEC_SID_UPDATE_INCOMPLETE,
+ CHDEC_SID_UPDATE,
+ CHDEC_SPEECH,
+ CHDEC_SPEECH_ONSET,
+ CHDEC_ESCAPE_MARKER,
+ CHDEC_ESCAPE_DATA,
+ CHDEC_NO_DATA
+ };
+
+ /* Channel decoded frame quality */
+ enum CHDECFrameQuality { CHDEC_GOOD = 0,
+ CHDEC_PROBABLY_DEGRADED,
+ CHDEC_PROBABLY_BAD,
+ CHDEC_BAD
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/frame_type_3gpp.h b/media/libstagefright/codecs/amrnb/common/include/frame_type_3gpp.h
new file mode 100644
index 0000000..3ebd929
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/frame_type_3gpp.h
@@ -0,0 +1,123 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./audio/gsm-amr/c/include/frame_type_3gpp.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated to new PV C header template.
+
+ Description: Added #ifdef __cplusplus after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains the definition of the 3GPP frame types.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef FRAME_TYPE_3GPP_H
+#define FRAME_TYPE_3GPP_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ enum Frame_Type_3GPP
+ {
+ AMR_475 = 0, /* 4.75 kbps */
+ AMR_515, /* 5.15 kbps */
+ AMR_59, /* 5.9 kbps */
+ AMR_67, /* 6.7 kbps */
+ AMR_74, /* 7.4 kbps */
+ AMR_795, /* 7.95 kbps */
+ AMR_102, /* 10.2 kbps */
+ AMR_122, /* 12.2 kbps */
+ AMR_SID, /* GSM AMR DTX */
+ GSM_EFR_SID, /* GSM EFR DTX */
+ TDMA_EFR_SID, /* TDMA EFR DTX */
+ PDC_EFR_SID, /* PDC EFR DTX */
+ FOR_FUTURE_USE1, /* Unused 1 */
+ FOR_FUTURE_USE2, /* Unused 2 */
+ FOR_FUTURE_USE3, /* Unused 3 */
+ AMR_NO_DATA /* No data */
+ };
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _FRAME_TYPE_3GPP_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/gc_pred.h b/media/libstagefright/codecs/amrnb/common/include/gc_pred.h
new file mode 100644
index 0000000..b82603c
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/gc_pred.h
@@ -0,0 +1,176 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/include/gc_pred.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : gc_pred.h
+ Purpose : codebook gain MA prediction
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _GC_PRED_H_
+#define _GC_PRED_H_
+#define gc_pred_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 past_qua_en[4]; /* normal MA predictor memory, Q10 */
+ /* (contains 20*log10(qua_err)) */
+ Word16 past_qua_en_MR122[4]; /* MA predictor memory for MR122 mode, Q10 */
+ /* (contains log2(qua_err)) */
+ } gc_predState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ Word16 gc_pred_reset(gc_predState *st);
+ /* reset of codebook gain MA predictor state (i.e. set state memory to zero)
+ returns 0 on success
+ */
+ void gc_pred_exit(gc_predState **st);
+ /* de-initialize codebook gain MA predictor state (i.e. free state struct)
+ stores NULL in *st
+ */
+
+ void
+ gc_pred_copy(
+ gc_predState *st_src, /* i : State struct */
+ gc_predState *st_dest /* o : State struct */
+ );
+
+ /*
+ * FUNCTION: gc_pred()
+ * PURPOSE: MA prediction of the innovation energy
+ * (in dB/(20*log10(2))) with mean removed).
+ */
+ void gc_pred(
+ gc_predState *st, /* i/o: State struct */
+ enum Mode mode, /* i : AMR mode */
+ Word16 *code, /* i : innovative codebook vector (L_SUBFR) */
+ /* MR122: Q12, other modes: Q13 */
+ Word16 *exp_gcode0, /* o : exponent of predicted gain factor, Q0 */
+ Word16 *frac_gcode0,/* o : fraction of predicted gain factor Q15 */
+ Word16 *exp_en, /* o : exponent of innovation energy, Q0 */
+ /* (only calculated for MR795) */
+ Word16 *frac_en, /* o : fraction of innovation energy, Q15 */
+ /* (only calculated for MR795) */
+ Flag *pOverflow
+ );
+
+ /*
+ * FUNCTION: gc_pred_update()
+ * PURPOSE: update MA predictor with last quantized energy
+ */
+ void gc_pred_update(
+ gc_predState *st, /* i/o: State struct */
+ Word16 qua_ener_MR122, /* i : quantized energy for update, Q10 */
+ /* (log2(qua_err)) */
+ Word16 qua_ener /* i : quantized energy for update, Q10 */
+ /* (20*log10(qua_err)) */
+ );
+
+ /*
+ * FUNCTION: gc_pred_average_limited()
+ * PURPOSE: get average of MA predictor state values (with a lower limit)
+ * [used in error concealment]
+ */
+ void gc_pred_average_limited(
+ gc_predState *st, /* i: State struct */
+ Word16 *ener_avg_MR122, /* o: averaged quantized energy, Q10 */
+ /* (log2(qua_err)) */
+ Word16 *ener_avg, /* o: averaged quantized energy, Q10 */
+ /* (20*log10(qua_err)) */
+ Flag *pOverflow
+ );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GC_PRED_H_ */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/gmed_n.h b/media/libstagefright/codecs/amrnb/common/include/gmed_n.h
new file mode 100644
index 0000000..1c4ede2
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/gmed_n.h
@@ -0,0 +1,80 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : gmed_n.h
+* Purpose : calculates N-point median.
+*
+********************************************************************************
+*/
+#ifndef gmed_n_h
+#define gmed_n_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ ********************************************************************************
+ * DEFINITION OF DATA TYPES
+ ********************************************************************************
+ */
+
+ /*
+ ********************************************************************************
+ * DECLARATION OF PROTOTYPES
+ ********************************************************************************
+ */
+ Word16 gmed_n( /* o : index of the median value (0...N-1) */
+ Word16 ind[], /* i : Past gain values */
+ Word16 n /* i : The number of gains; this routine */
+ /* is only valid for a odd number of gains */
+ );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/gsm_amr_typedefs.h b/media/libstagefright/codecs/amrnb/common/include/gsm_amr_typedefs.h
new file mode 100644
index 0000000..4abcbbd
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/gsm_amr_typedefs.h
@@ -0,0 +1,133 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: codecs/audio/gsm_amr/gsm_two_way/c/include/gsm_amr_typedefs.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description: Removed unused defintions and corrected ifdef, that depended on
+ incorrect typedef
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains the definition of the amr codec types.
+
+------------------------------------------------------------------------------
+*/
+#ifndef GSM_AMR_TYPEDEFS_H
+#define GSM_AMR_TYPEDEFS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include <stdint.h>
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+typedef int8_t Word8;
+typedef uint8_t UWord8;
+
+
+/*----------------------------------------------------------------------------
+; Define 16 bit signed and unsigned words
+----------------------------------------------------------------------------*/
+
+typedef int16_t Word16;
+typedef uint16_t UWord16;
+
+/*----------------------------------------------------------------------------
+; Define 32 bit signed and unsigned words
+----------------------------------------------------------------------------*/
+
+typedef int32_t Word32;
+typedef uint32_t UWord32;
+
+
+/*----------------------------------------------------------------------------
+; Define boolean type
+----------------------------------------------------------------------------*/
+typedef int Bool;
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef OFF
+#define OFF 0
+#endif
+
+#ifndef ON
+#define ON 1
+#endif
+
+#ifndef NO
+#define NO 0
+#endif
+
+#ifndef YES
+#define YES 1
+#endif
+
+#ifndef SUCCESS
+#define SUCCESS 0
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+typedef int32_t Flag;
+
+#endif /* GSM_AMR_TYPEDEFS_H */
diff --git a/media/libstagefright/codecs/amrnb/common/include/int_lpc.h b/media/libstagefright/codecs/amrnb/common/include/int_lpc.h
new file mode 100644
index 0000000..e95e6ca
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/int_lpc.h
@@ -0,0 +1,212 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/lsp_avg.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the lsp_avg.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef int_lpc_h
+#define int_lpc_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*
+ **************************************************************************
+ *
+ * Function : Int_lpc_1and3
+ * Purpose : Interpolates the LSPs and converts to LPC parameters
+ * to get a different LP filter in each subframe.
+ * Description : The 20 ms speech frame is divided into 4 subframes.
+ * The LSPs are quantized and transmitted at the 2nd and
+ * 4th subframes (twice per frame) and interpolated at the
+ * 1st and 3rd subframe.
+ *
+ * |------|------|------|------|
+ * sf1 sf2 sf3 sf4
+ * F0 Fm F1
+ *
+ * sf1: 1/2 Fm + 1/2 F0 sf3: 1/2 F1 + 1/2 Fm
+ * sf2: Fm sf4: F1
+ * Returns : void
+ *
+ **************************************************************************
+ */
+ void Int_lpc_1and3(
+ Word16 lsp_old[], /* i : LSP vector at the 4th subfr. of past frame (M) */
+ Word16 lsp_mid[], /* i : LSP vector at the 2nd subfr. of
+ present frame (M) */
+ Word16 lsp_new[], /* i : LSP vector at the 4th subfr. of
+ present frame (M) */
+ Word16 Az[], /* o : interpolated LP parameters in all subfr.
+ (AZ_SIZE) */
+ Flag *pOverflow
+ );
+
+ /*
+ **************************************************************************
+ *
+ * Function : Int_lpc_1and3_2
+ * Purpose : Interpolation of the LPC parameters. Same as the Int_lpc
+ * function but we do not recompute Az() for subframe 2 and
+ * 4 because it is already available.
+ * Returns : void
+ *
+ **************************************************************************
+ */
+ void Int_lpc_1and3_2(
+ Word16 lsp_old[], /* i : LSP vector at the 4th subfr. of past frame (M) */
+ Word16 lsp_mid[], /* i : LSP vector at the 2nd subframe of
+ present frame (M) */
+ Word16 lsp_new[], /* i : LSP vector at the 4th subframe of
+ present frame (M) */
+ Word16 Az[], /* o :interpolated LP parameters
+ in subframes 1 and 3 (AZ_SIZE) */
+ Flag *pOverflow
+ );
+
+ /*
+ **************************************************************************
+ *
+ * Function : Int_lpc_1to3
+ * Purpose : Interpolates the LSPs and converts to LPC parameters
+ * to get a different LP filter in each subframe.
+ * Description : The 20 ms speech frame is divided into 4 subframes.
+ * The LSPs are quantized and transmitted at the 4th
+ * subframes (once per frame) and interpolated at the
+ * 1st, 2nd and 3rd subframe.
+ *
+ * |------|------|------|------|
+ * sf1 sf2 sf3 sf4
+ * F0 F1
+ *
+ * sf1: 3/4 F0 + 1/4 F1 sf3: 1/4 F0 + 3/4 F1
+ * sf2: 1/2 F0 + 1/2 F1 sf4: F1
+ * Returns : void
+ *
+ **************************************************************************
+ */
+ void Int_lpc_1to3(
+ Word16 lsp_old[], /* i : LSP vector at the 4th SF of past frame (M) */
+ Word16 lsp_new[], /* i : LSP vector at the 4th SF of present frame (M) */
+ Word16 Az[], /* o : interpolated LP parameters in all SFs (AZ_SIZE) */
+ Flag *pOverflow
+ );
+
+ /*
+ **************************************************************************
+ *
+ * Function : Int_lpc_1to3_2
+ * Purpose : Interpolation of the LPC parameters. Same as the Int_lpc
+ * function but we do not recompute Az() for subframe 4
+ * because it is already available.
+ * Returns : void
+ *
+ **************************************************************************
+ */
+ void Int_lpc_1to3_2(
+ Word16 lsp_old[], /* i : LSP vector at the 4th SF of past frame (M) */
+ Word16 lsp_new[], /* i : LSP vector at the 4th SF present frame (M) */
+ Word16 Az[], /* o :interpolated LP parameters in SFs 1, 2, 3
+ (AZ_SIZE) */
+ Flag *pOverflow
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _INT_LPC_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/int_lsf.h b/media/libstagefright/codecs/amrnb/common/include/int_lsf.h
new file mode 100644
index 0000000..4e02ae6
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/int_lsf.h
@@ -0,0 +1,113 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/int_lsf.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the int_lsf function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef int_lsf_h
+#define int_lsf_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void Int_lsf(
+ Word16 lsf_old[], /* i : LSF vector at the 4th SF of past frame */
+ Word16 lsf_new[], /* i : LSF vector at the 4th SF of present frame */
+ Word16 i_subfr, /* i : Current sf (equal to 0,40,80 or 120) */
+ Word16 lsf_out[], /* o : interpolated LSF parameters for current sf */
+ Flag *pOverflow /* o : flag set if overflow occurs */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _INT_LSF_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/inv_sqrt.h b/media/libstagefright/codecs/amrnb/common/include/inv_sqrt.h
new file mode 100644
index 0000000..91ab3e4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/inv_sqrt.h
@@ -0,0 +1,118 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/inv_sqrt.h
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Added an extern declaration for inv_sqrt_tbl[], now defined in
+ the file inv_sqrt_tbl.c
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the inv_sqrt() function.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef INV_SQRT_H
+#define INV_SQRT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 inv_sqrt_tbl[];
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word32 Inv_sqrt( /* (o) : output value */
+ Word32 L_x, /* (i) : input value */
+ Flag *pOverflow /* (i) : pointer to overflow flag */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _INV_SQRT_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_abs.h b/media/libstagefright/codecs/amrnb/common/include/l_abs.h
new file mode 100644
index 0000000..db57b82
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_abs.h
@@ -0,0 +1,111 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/include/l_abs.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for L_abs function.
+
+ Description: Moved _cplusplus #ifdef after Include section..
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_abs function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_ABS_H
+#define L_ABS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word32 L_abs(Word32 L_var1);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_add.h b/media/libstagefright/codecs/amrnb/common/include/l_add.h
new file mode 100644
index 0000000..136b914
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_add.h
@@ -0,0 +1,171 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/l_add.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for L_add function.
+
+ Description: Changed function prototype declaration. A pointer to the overflow
+ flag is being passed in as a parameter instead of using global
+ data.
+
+ Description: Updated template. Changed paramter name from overflow to
+ pOverflow
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description: Providing support for ARM and Linux-ARM assembly instructions.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_add function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_ADD_H
+#define L_ADD_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
+
+ __inline Word32 L_add(register Word32 L_var1, register Word32 L_var2, Flag *pOverflow)
+ {
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+ __asm
+ {
+ QADD result, L_var1, L_var2
+ }
+ return(result);
+ }
+
+#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
+
+ __inline Word32 L_add(register Word32 L_var1, register Word32 L_var2, Flag *pOverflow)
+ {
+ register Word32 ra = L_var1;
+ register Word32 rb = L_var2;
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("qadd %0, %1, %2"
+ : "=r"(result)
+ : "r"(ra), "r"(rb)
+ );
+ return (result);
+
+ }
+
+#else /* C EQUIVALENT */
+
+
+ static inline Word32 L_add(register Word32 L_var1, register Word32 L_var2, Flag *pOverflow)
+ {
+ Word32 L_sum;
+
+ L_sum = L_var1 + L_var2;
+
+ if ((L_var1 ^ L_var2) >= 0)
+ {
+ if ((L_sum ^ L_var1) < 0)
+ {
+ L_sum = (L_var1 < 0) ? MIN_32 : MAX_32;
+ *pOverflow = 1;
+ }
+ }
+
+ return (L_sum);
+ }
+
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _L_ADD_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_add_c.h b/media/libstagefright/codecs/amrnb/common/include/l_add_c.h
new file mode 100644
index 0000000..3585a3c
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_add_c.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/l_add_c.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for L_add_c function.
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag and carry flag is passed into the
+ function. Updated template.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_add_c function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_ADD_C_H
+#define L_ADD_C_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word32 L_add_c(Word32 L_var1, Word32 L_var2, Flag *pOverflow, Flag *pCarry);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _L_ADD_C_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_comp.h b/media/libstagefright/codecs/amrnb/common/include/l_comp.h
new file mode 100644
index 0000000..02a4bb7
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_comp.h
@@ -0,0 +1,114 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/include/l_comp.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Passing in pOverflow for EPOC changes.
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_comp function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_COMP_H
+#define L_COMP_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word32 L_Comp(Word16 hi, Word16 lo, Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_deposit_h.h b/media/libstagefright/codecs/amrnb/common/include/l_deposit_h.h
new file mode 100644
index 0000000..e58bc5f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_deposit_h.h
@@ -0,0 +1,114 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/include/l_deposit_h.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for L_deposit_h function.
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_deposit_h function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_DEPOSIT_H_H
+#define L_DEPOSIT_H_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word32 L_deposit_h(Word16 var1);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_deposit_l.h b/media/libstagefright/codecs/amrnb/common/include/l_deposit_l.h
new file mode 100644
index 0000000..09fabfd
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_deposit_l.h
@@ -0,0 +1,114 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/include/l_deposit_l.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for L_deposit_l function.
+
+ Description: Updated template to make it build for Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_deposit_l function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_DEPOSIT_L_H
+#define L_DEPOSIT_L_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word32 L_deposit_l(Word16 var1);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_extract.h b/media/libstagefright/codecs/amrnb/common/include/l_extract.h
new file mode 100644
index 0000000..fdbe351
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_extract.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/l_extract.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_extract function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_EXTRACT_H
+#define L_EXTRACT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void L_Extract(Word32 L_var,
+ Word16 *pL_var_hi,
+ Word16 *pL_var_lo,
+ Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _L_EXTRACT_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_mac.h b/media/libstagefright/codecs/amrnb/common/include/l_mac.h
new file mode 100644
index 0000000..b4af3aa
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_mac.h
@@ -0,0 +1,183 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Filename: /audio/gsm_amr/c/include/l_mac.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for L_mac function.
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description: 1. Updated the function to include ARM and Linux-ARM assembly
+ instructions.
+ 2. Added OSCL_UNUSED_ARG(pOverflow) to remove compiler warnings.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_mac function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_MAC_H
+#define L_MAC_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
+
+ __inline Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 result;
+ Word32 L_sum;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ __asm {SMULBB result, var1, var2}
+ __asm {QDADD L_sum, L_var3, result}
+ return (L_sum);
+ }
+
+#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
+
+ static inline Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ register Word32 ra = L_var3;
+ register Word32 rb = var1;
+ register Word32 rc = var2;
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(result)
+ : "r"(rb), "r"(rc)
+ );
+
+ asm volatile("qdadd %0, %1, %2"
+ : "=r"(rc)
+ : "r"(ra), "r"(result)
+ );
+
+ return (rc);
+ }
+
+#else /* C_EQUIVALENT */
+
+ __inline Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 result;
+ Word32 L_sum;
+ result = (Word32) var1 * var2;
+ if (result != (Word32) 0x40000000L)
+ {
+ L_sum = (result << 1) + L_var3;
+
+ /* Check if L_sum and L_var_3 share the same sign */
+ if ((L_var3 ^ result) > 0)
+ {
+ if ((L_sum ^ L_var3) < 0)
+ {
+ L_sum = (L_var3 < 0) ? MIN_32 : MAX_32;
+ *pOverflow = 1;
+ }
+ }
+ }
+ else
+ {
+ *pOverflow = 1;
+ L_sum = MAX_32;
+ }
+ return (L_sum);
+ }
+
+#endif
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _L_MAC_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_msu.h b/media/libstagefright/codecs/amrnb/common/include/l_msu.h
new file mode 100644
index 0000000..3bafb00
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_msu.h
@@ -0,0 +1,171 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Filename: /audio/gsm_amr/c/include/l_msu.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for L_msu function.
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description: Providing support for ARM and Linux-ARM assembly instructions.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_msu function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_MSU_H
+#define L_MSU_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+#include "l_mult.h"
+#include "l_sub.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
+
+ __inline Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 product;
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ __asm
+ {
+ SMULBB product, var1, var2
+ QDSUB result, L_var3, product
+ }
+
+ return (result);
+ }
+
+#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
+
+ __inline Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ register Word32 ra = L_var3;
+ register Word32 rb = var1;
+ register Word32 rc = var2;
+ Word32 product;
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(product)
+ : "r"(rb), "r"(rc)
+ );
+
+ asm volatile("qdsub %0, %1, %2"
+ : "=r"(result)
+ : "r"(ra), "r"(product)
+ );
+
+ return (result);
+ }
+
+#else /* C EQUIVALENT */
+
+ static inline Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 result;
+
+ result = L_mult(var1, var2, pOverflow);
+ result = L_sub(L_var3, result, pOverflow);
+
+ return (result);
+ }
+
+#endif
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _L_MSU_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_mult.h b/media/libstagefright/codecs/amrnb/common/include/l_mult.h
new file mode 100644
index 0000000..061df60
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_mult.h
@@ -0,0 +1,178 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/l_mult.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for L_mult function.
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description: Providing support for ARM and Linux-ARM assembly instructions.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_mult function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_MULT_H
+#define L_MULT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
+
+ __inline Word32 L_mult(Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 result;
+ Word32 product;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ __asm
+ {
+ SMULBB product, var1, var2
+ QADD result, product, product
+ }
+
+ return (result);
+ }
+
+#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
+
+ __inline Word32 L_mult(Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ register Word32 ra = var1;
+ register Word32 rb = var2;
+ Word32 result;
+ Word32 product;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(product)
+ : "r"(ra), "r"(rb)
+ );
+
+ asm volatile("qadd %0, %1, %2"
+ : "=r"(result)
+ : "r"(product), "r"(product)
+ );
+
+ return(result);
+ }
+
+#else /* C EQUIVALENT */
+
+ static inline Word32 L_mult(Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ register Word32 L_product;
+
+ L_product = (Word32) var1 * var2;
+
+ if (L_product != (Word32) 0x40000000L)
+ {
+ L_product <<= 1; /* Multiply by 2 */
+ }
+ else
+ {
+ *pOverflow = 1;
+ L_product = MAX_32;
+ }
+
+ return (L_product);
+ }
+#endif
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _L_MULT_H */
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_negate.h b/media/libstagefright/codecs/amrnb/common/include/l_negate.h
new file mode 100644
index 0000000..11e14a8
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_negate.h
@@ -0,0 +1,114 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/include/l_negate.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for L_negate function.
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_negate function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_NEGATE_H
+#define L_NEGATE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word32 L_negate(Word32 L_var1);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_shl.h b/media/libstagefright/codecs/amrnb/common/include/l_shl.h
new file mode 100644
index 0000000..7b9fdb1
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_shl.h
@@ -0,0 +1,116 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/l_shl.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for L_shl function.
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_shl function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_SHL_H
+#define L_SHL_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word32 L_shl(Word32 L_var1, Word16 var2, Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _L_SHL_H_ */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_shr.h b/media/libstagefright/codecs/amrnb/common/include/l_shr.h
new file mode 100644
index 0000000..ef22073
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_shr.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Filename: /audio/gsm_amr/c/include/l_shr.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for L_shr function.
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_shr function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_SHR_H
+#define L_SHR_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word32 L_shr(Word32 L_var1, Word16 var2, Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _L_SHR_H_ */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_shr_r.h b/media/libstagefright/codecs/amrnb/common/include/l_shr_r.h
new file mode 100644
index 0000000..1a1661f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_shr_r.h
@@ -0,0 +1,114 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/l_shr_r.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for L_shr_r function.
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_shr_r function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_SHR_R_H
+#define L_SHR_R_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word32 L_shr_r(Word32 L_var1, Word16 var2, Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _L_SHR_R_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/l_sub.h b/media/libstagefright/codecs/amrnb/common/include/l_sub.h
new file mode 100644
index 0000000..97d7538
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/l_sub.h
@@ -0,0 +1,173 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/l_sub.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for L_sub function.
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description: Providing support for ARM and Linux-ARM assembly instructions.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the L_sub function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef L_SUB_H
+#define L_SUB_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
+
+ __inline Word32 L_sub(Word32 L_var1, Word32 L_var2, Flag *pOverflow)
+ {
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ __asm
+ {
+ QSUB result, L_var1, L_var2
+ }
+
+ return(result);
+
+ }
+
+#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
+
+ __inline Word32 L_sub(Word32 L_var1, Word32 L_var2, Flag *pOverflow)
+ {
+ register Word32 ra = L_var1;
+ register Word32 rb = L_var2;
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("qsub %0, %1, %2"
+ : "=r"(result)
+ : "r"(ra), "r"(rb)
+ );
+
+ return (result);
+ }
+
+#else /* C EQUIVALENT */
+
+ static inline Word32 L_sub(register Word32 L_var1, register Word32 L_var2,
+ register Flag *pOverflow)
+ {
+ Word32 L_diff;
+
+ L_diff = L_var1 - L_var2;
+
+ if ((L_var1 ^ L_var2) < 0)
+ {
+ if ((L_diff ^ L_var1) & MIN_32)
+ {
+ L_diff = (L_var1 < 0L) ? MIN_32 : MAX_32;
+ *pOverflow = 1;
+ }
+ }
+
+ return (L_diff);
+ }
+
+#endif
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _L_SUB_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/log2.h b/media/libstagefright/codecs/amrnb/common/include/log2.h
new file mode 100644
index 0000000..e589b2f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/log2.h
@@ -0,0 +1,120 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/log2.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template. Deleted function
+ prototype for Log2_norm and put it in its own header file.
+ Added log2_norm.h in Include section for legacy files.
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Moved _cplusplus #ifdef after Include section..
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains the function prototype definition for Log2 function.
+
+------------------------------------------------------------------------------
+*/
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef LOG2_H
+#define LOG2_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+#include "log2_norm.h" /* Used by legacy files */
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void Log2(
+ Word32 L_x, /* (i) : input value */
+ Word16 *pExponent, /* (o) : Integer part of Log2. (range: 0<=val<=30)*/
+ Word16 *pFraction, /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+ Flag *pOverflow /* (i/o) : overflow flag */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LOG2_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/log2_norm.h b/media/libstagefright/codecs/amrnb/common/include/log2_norm.h
new file mode 100644
index 0000000..46b4e4d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/log2_norm.h
@@ -0,0 +1,119 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/log2_norm.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for Log2_norm function.
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template. Added extern declaration for log2_tbl[]
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains the prototype declaration for Log2_norm function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef LOG2_NORM_H
+#define LOG2_NORM_H
+
+#define log2_h "$Id $" /* Used by legacy code */
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 log2_tbl[];
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ 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) */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LOG2_NORM_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/lsfwt.h b/media/libstagefright/codecs/amrnb/common/include/lsfwt.h
new file mode 100644
index 0000000..d9a1f80
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/lsfwt.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/lsfwt.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the lsfwt.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef lsfwt_h
+#define lsfwt_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void Lsf_wt(
+ Word16 *lsf, /* input : LSF vector */
+ Word16 *wf, /* output: square of weighting factors */
+ Flag * pOverflow); /* o : Flag set when overflow occurs */
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LSF_WT_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/lsp.h b/media/libstagefright/codecs/amrnb/common/include/lsp.h
new file mode 100644
index 0000000..26a4b34
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/lsp.h
@@ -0,0 +1,186 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/lsp.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the lsp.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef lsp_h
+#define lsp_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "q_plsf.h"
+#include "mode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+
+ /* Past LSPs */
+ Word16 lsp_old[M];
+ Word16 lsp_old_q[M];
+
+ /* Quantization state */
+ Q_plsfState *qSt;
+
+ } lspState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ /*
+ **************************************************************************
+ *
+ * Function : lsp_init
+ * Purpose : Allocates memory and initializes state variables
+ * Description : Stores pointer to filter status struct in *st. This
+ * pointer has to be passed to lsp in each call.
+ * Returns : 0 on success
+ *
+ **************************************************************************
+ */
+ Word16 lsp_init(lspState **st);
+
+ /*
+ **************************************************************************
+ *
+ * Function : lsp_reset
+ * Purpose : Resets state memory
+ * Returns : 0 on success
+ *
+ **************************************************************************
+ */
+ Word16 lsp_reset(lspState *st);
+
+ /*
+ **************************************************************************
+ *
+ * Function : lsp_exit
+ * Purpose : The memory used for state memory is freed
+ * Description : Stores NULL in *st
+ *
+ **************************************************************************
+ */
+ void lsp_exit(lspState **st);
+
+ /*
+ **************************************************************************
+ *
+ * Function : lsp
+ * Purpose : Conversion from LP coefficients to LSPs.
+ * Quantization of LSPs.
+ * Description : Generates 2 sets of LSPs from 2 sets of
+ * LP coefficients for mode 12.2. For the other
+ * modes 1 set of LSPs is generated from 1 set of
+ * LP coefficients. These LSPs are quantized with
+ * Matrix/Vector quantization (depending on the mode)
+ * and interpolated for the subframes not yet having
+ * their own LSPs.
+ *
+ **************************************************************************
+ */
+ void lsp(lspState *st, /* i/o : State struct */
+ enum Mode req_mode, /* i : requested coder mode */
+ enum Mode used_mode,/* i : used coder mode */
+ Word16 az[], /* i/o : interpolated LP parameters Q12 */
+ Word16 azQ[], /* o : quantization interpol. LP parameters Q12*/
+ Word16 lsp_new[], /* o : new lsp vector */
+ Word16 **anap, /* o : analysis parameters */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LSP_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/lsp_az.h b/media/libstagefright/codecs/amrnb/common/include/lsp_az.h
new file mode 100644
index 0000000..ae81507
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/lsp_az.h
@@ -0,0 +1,111 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/lsp_az.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the lsp_az function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef LSP_AZ_H
+#define LSP_AZ_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void Lsp_Az(
+ Word16 lsp[], /* (i) : line spectral frequencies */
+ Word16 a[], /* (o) : predictor coefficients (order = 10) */
+ Flag *pOverflow /* (o) : overflow flag */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LSP_AZ_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/lsp_lsf.h b/media/libstagefright/codecs/amrnb/common/include/lsp_lsf.h
new file mode 100644
index 0000000..186b4d3
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/lsp_lsf.h
@@ -0,0 +1,121 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Filename: /audio/gsm_amr/c/include/lsp_lsf.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the lsp_lsf.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef lsp_lsf_h
+#define lsp_lsf_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void Lsf_lsp(
+ Word16 lsf[], /* (i) : lsf[m] normalized (range: 0.0<=val<=0.5) */
+ Word16 lsp[], /* (o) : lsp[m] (range: -1<=val<1) */
+ Word16 m, /* (i) : LPC order */
+ Flag *pOverflow /* (o) : Flag set when overflow occurs */
+ );
+ void Lsp_lsf(
+ Word16 lsp[], /* (i) : lsp[m] (range: -1<=val<1) */
+ Word16 lsf[], /* (o) : lsf[m] normalized (range: 0.0<=val<=0.5) */
+ Word16 m, /* (i) : LPC order */
+ Flag *pOverflow /* (o) : Flag set when overflow occurs */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LSP_LSF_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/lsp_tab.h b/media/libstagefright/codecs/amrnb/common/include/lsp_tab.h
new file mode 100644
index 0000000..01b3317
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/lsp_tab.h
@@ -0,0 +1,111 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: .audio/gsm-amr/c/include/lsp_tab.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file declares a table lsp_init_data.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef LSP_TAB_H
+#define LSP_TAB_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 lsp_init_data[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/mac_32.h b/media/libstagefright/codecs/amrnb/common/include/mac_32.h
new file mode 100644
index 0000000..9e9ebe1
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/mac_32.h
@@ -0,0 +1,150 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/mac_32.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description: Inlined the functions from mac_32.cpp. A performance improvement
+ change.
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the Mac_32 and Mac_32_16 functions
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef MAC_32_H
+#define MAC_32_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ static inline Word32 Mac_32(Word32 L_var3,
+ Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 L_var2_hi,
+ Word16 L_var2_lo,
+ Flag *pOverflow)
+ {
+ Word16 product;
+
+ L_var3 = L_mac(L_var3, L_var1_hi, L_var2_hi, pOverflow);
+
+ product = mult(L_var1_hi, L_var2_lo, pOverflow);
+ L_var3 = L_mac(L_var3, product, 1, pOverflow);
+
+ product = mult(L_var1_lo, L_var2_hi, pOverflow);
+ L_var3 = L_mac(L_var3, product, 1, pOverflow);
+
+ return (L_var3);
+ }
+
+ static inline Word32 Mac_32_16(Word32 L_var3,
+ Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 var2,
+ Flag *pOverflow)
+ {
+ Word16 product;
+
+ L_var3 = L_mac(L_var3, L_var1_hi, var2, pOverflow);
+
+ product = mult(L_var1_lo, var2, pOverflow);
+ L_var3 = L_mac(L_var3, product, 1, pOverflow);
+
+ return (L_var3);
+ }
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MAC_32_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/mode.h b/media/libstagefright/codecs/amrnb/common/include/mode.h
new file mode 100644
index 0000000..75f86cb
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/mode.h
@@ -0,0 +1,82 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : mode.h
+* Purpose : Declaration of mode type
+*
+********************************************************************************
+*/
+#ifndef mode_h
+#define mode_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ ********************************************************************************
+ * DEFINITION OF DATA TYPES
+ ********************************************************************************
+ */
+ enum Mode { MR475 = 0,
+ MR515,
+ MR59,
+ MR67,
+ MR74,
+ MR795,
+ MR102,
+ MR122,
+
+ MRDTX,
+
+ N_MODES /* number of (SPC) modes */
+
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/mpy_32.h b/media/libstagefright/codecs/amrnb/common/include/mpy_32.h
new file mode 100644
index 0000000..03f36b2
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/mpy_32.h
@@ -0,0 +1,272 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/mpy_32.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description: Updated the function to include ARM and Linux-ARM assembly
+ instructions.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the Mpy_32 function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef MPY_32_H
+#define MPY_32_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
+
+ __inline Word32 Mpy_32(Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 L_var2_hi,
+ Word16 L_var2_lo,
+ Flag *pOverflow)
+
+ {
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ Word32 L_product;
+ Word32 L_sum;
+ Word32 product32;
+
+ OSCL_UNUSED_ARG(pOverflow);
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* L_product = L_mult (L_var1_hi, L_var2_hi, pOverflow);*/
+
+ __asm {SMULBB L_product, L_var1_hi, L_var2_hi}
+ __asm {QDADD L_product, 0, L_product}
+ __asm {SMULBB product32, L_var1_hi, L_var2_lo}
+ product32 >>= 15;
+ __asm {QDADD L_sum, L_product, product32}
+ L_product = L_sum;
+ __asm {SMULBB product32, L_var1_lo, L_var2_hi}
+ product32 >>= 15;
+ __asm {QDADD L_sum, L_product, product32}
+ return (L_sum);
+ }
+
+#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
+
+ static inline Word32 Mpy_32(Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 L_var2_hi,
+ Word16 L_var2_lo,
+ Flag *pOverflow)
+ {
+ register Word32 product32;
+ register Word32 L_sum;
+ register Word32 L_product, result;
+ register Word32 ra = L_var1_hi;
+ register Word32 rb = L_var1_lo;
+ register Word32 rc = L_var2_hi;
+ register Word32 rd = L_var2_lo;
+
+
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(L_product)
+ : "r"(ra), "r"(rc)
+ );
+ asm volatile("mov %0, #0"
+ : "=r"(result)
+ );
+
+ asm volatile("qdadd %0, %1, %2"
+ : "=r"(L_sum)
+ : "r"(result), "r"(L_product)
+ );
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(product32)
+ : "r"(ra), "r"(rd)
+ );
+
+ asm volatile("mov %0, %1, ASR #15"
+ : "=r"(ra)
+ : "r"(product32)
+ );
+ asm volatile("qdadd %0, %1, %2"
+ : "=r"(L_product)
+ : "r"(L_sum), "r"(ra)
+ );
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(product32)
+ : "r"(rb), "r"(rc)
+ );
+
+ asm volatile("mov %0, %1, ASR #15"
+ : "=r"(rb)
+ : "r"(product32)
+ );
+
+ asm volatile("qdadd %0, %1, %2"
+ : "=r"(L_sum)
+ : "r"(L_product), "r"(rb)
+ );
+
+ return (L_sum);
+ }
+
+#else /* C_EQUIVALENT */
+
+ __inline Word32 Mpy_32(Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 L_var2_hi,
+ Word16 L_var2_lo,
+ Flag *pOverflow)
+ {
+ Word32 L_product;
+ Word32 L_sum;
+ Word32 product32;
+
+ OSCL_UNUSED_ARG(pOverflow);
+ L_product = (Word32) L_var1_hi * L_var2_hi;
+
+ if (L_product != (Word32) 0x40000000L)
+ {
+ L_product <<= 1;
+ }
+ else
+ {
+ L_product = MAX_32;
+ }
+
+ /* result = mult (L_var1_hi, L_var2_lo, pOverflow); */
+ product32 = ((Word32) L_var1_hi * L_var2_lo) >> 15;
+
+ /* L_product = L_mac (L_product, result, 1, pOverflow); */
+ L_sum = L_product + (product32 << 1);
+
+ if ((L_product ^ product32) > 0)
+ {
+ if ((L_sum ^ L_product) < 0)
+ {
+ L_sum = (L_product < 0) ? MIN_32 : MAX_32;
+ }
+ }
+
+ L_product = L_sum;
+
+ /* result = mult (L_var1_lo, L_var2_hi, pOverflow); */
+ product32 = ((Word32) L_var1_lo * L_var2_hi) >> 15;
+
+ /* L_product = L_mac (L_product, result, 1, pOverflow); */
+ L_sum = L_product + (product32 << 1);
+
+ if ((L_product ^ product32) > 0)
+ {
+ if ((L_sum ^ L_product) < 0)
+ {
+ L_sum = (L_product < 0) ? MIN_32 : MAX_32;
+ }
+ }
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return (L_sum);
+ }
+
+#endif
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MPY_32_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/mpy_32_16.h b/media/libstagefright/codecs/amrnb/common/include/mpy_32_16.h
new file mode 100644
index 0000000..7eaa741
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/mpy_32_16.h
@@ -0,0 +1,206 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/mpy_32_16.h
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the Mpy_32_16 function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef MPY_32_16_H
+#define MPY_32_16_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
+
+ __inline Word32 Mpy_32_16(Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 var2,
+ Flag *pOverflow)
+ {
+
+ Word32 L_product;
+ Word32 L_sum;
+ Word32 result;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ __asm {SMULBB L_product, L_var1_hi, var2}
+ __asm {QDADD L_product, 0, L_product}
+ __asm {SMULBB result, L_var1_lo, var2}
+ result >>= 15;
+ __asm {QDADD L_sum, L_product, result}
+ return (L_sum);
+ }
+
+#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
+
+ static inline Word32 Mpy_32_16(Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 var2,
+ Flag *pOverflow)
+ {
+
+ register Word32 ra = L_var1_hi;
+ register Word32 rb = L_var1_lo;
+ register Word32 rc = var2;
+ Word32 result, L_product;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(L_product)
+ : "r"(ra), "r"(rc)
+ );
+ asm volatile("mov %0, #0"
+ : "=r"(result)
+ );
+
+ asm volatile("qdadd %0, %1, %2"
+ : "=r"(L_product)
+ : "r"(result), "r"(L_product)
+ );
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(result)
+ : "r"(rb), "r"(rc)
+ );
+
+ asm volatile("mov %0, %1, ASR #15"
+ : "=r"(ra)
+ : "r"(result)
+ );
+ asm volatile("qdadd %0, %1, %2"
+ : "=r"(result)
+ : "r"(L_product), "r"(ra)
+ );
+
+ return (result);
+ }
+
+#else /* C_EQUIVALENT */
+ __inline Word32 Mpy_32_16(Word16 L_var1_hi,
+ Word16 L_var1_lo,
+ Word16 var2,
+ Flag *pOverflow)
+ {
+
+ Word32 L_product;
+ Word32 L_sum;
+ Word32 result;
+ L_product = (Word32) L_var1_hi * var2;
+
+ if (L_product != (Word32) 0x40000000L)
+ {
+ L_product <<= 1;
+ }
+ else
+ {
+ *pOverflow = 1;
+ L_product = MAX_32;
+ }
+
+ result = ((Word32)L_var1_lo * var2) >> 15;
+
+ L_sum = L_product + (result << 1);
+
+ if ((L_product ^ result) > 0)
+ {
+ if ((L_sum ^ L_product) < 0)
+ {
+ L_sum = (L_product < 0) ? MIN_32 : MAX_32;
+ *pOverflow = 1;
+ }
+ }
+ return (L_sum);
+
+ }
+
+#endif
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MPY_32_16_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/mult.h b/media/libstagefright/codecs/amrnb/common/include/mult.h
new file mode 100644
index 0000000..6927eba
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/mult.h
@@ -0,0 +1,190 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/mult.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for mult function.
+
+ Description: Changed prototype of the mult() function. Instead of using global
+ a pointer to overflow flag is now passed into the function.
+
+ Description: Updated copyright information.
+ Updated variable name from "overflow" to "pOverflow" to match
+ with original function declaration.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description: Providing support for ARM and Linux-ARM assembly instructions.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the mult function.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef MULT_H
+#define MULT_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+#if defined(PV_ARM_V5)
+
+ __inline Word16 mult(Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ Word32 product;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ __asm
+ {
+ SMULBB product, var1, var2
+ MOV product, product, ASR #15
+ CMP product, 0x7FFF
+ MOVGE product, 0x7FFF
+ }
+
+ return ((Word16) product);
+ }
+
+#elif defined(PV_ARM_GCC_V5)
+
+ __inline Word16 mult(Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ register Word32 ra = var1;
+ register Word32 rb = var2;
+ Word32 product;
+ Word32 temp = 0x7FFF;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=r"(product)
+ : "r"(ra), "r"(rb)
+ );
+ asm volatile("mov %0, %1, ASR #15"
+ : "=r"(product)
+ : "r"(product)
+ );
+ asm volatile("cmp %0, %1"
+ : "=r"(product)
+ : "r"(temp)
+ );
+ asm volatile("movge %0, %1"
+ : "=r"(product)
+ : "r"(temp)
+ );
+
+ return ((Word16) product);
+ }
+
+#else /* C EQUIVALENT */
+
+ static inline Word16 mult(Word16 var1, Word16 var2, Flag *pOverflow)
+ {
+ register Word32 product;
+
+ product = ((Word32) var1 * var2) >> 15;
+
+ /* Saturate result (if necessary). */
+ /* var1 * var2 >0x00007fff is the only case */
+ /* that saturation occurs. */
+
+ if (product > 0x00007fffL)
+ {
+ *pOverflow = 1;
+ product = (Word32) MAX_16;
+ }
+
+
+ /* Return the product as a 16 bit value by type casting Word32 to Word16 */
+
+ return ((Word16) product);
+ }
+
+#endif
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MULT_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/mult_r.h b/media/libstagefright/codecs/amrnb/common/include/mult_r.h
new file mode 100644
index 0000000..d7a1857
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/mult_r.h
@@ -0,0 +1,121 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/mult_r.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for mult_r function.
+
+ Description: Changed prototype of the mult() function. Instead of using global
+ data, a pointer to overflow flag is now passed into the function.
+
+ Description: Made the following based on P2/P3 review
+ 1) Changed the parameter name from "overflow" to "pOverflow"
+ in the function prototype declaration.
+ 2) Updated template
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the mult_r function.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef MULT_R__H
+#define MULT_R__H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 mult_r(Word16 var1, Word16 var2, Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _MULT_R_H_ */
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/n_proc.h b/media/libstagefright/codecs/amrnb/common/include/n_proc.h
new file mode 100644
index 0000000..e5738c1
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/n_proc.h
@@ -0,0 +1,31 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/* $Id $ */
+
+void proc_head(char *mes);
diff --git a/media/libstagefright/codecs/amrnb/common/include/negate.h b/media/libstagefright/codecs/amrnb/common/include/negate.h
new file mode 100644
index 0000000..f67569e
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/negate.h
@@ -0,0 +1,113 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./gsm-amr/c/include/negate.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for negate function.
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the negate function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef NEGATE_H
+#define NEGATE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 negate(register Word16 var1);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/norm_l.h b/media/libstagefright/codecs/amrnb/common/include/norm_l.h
new file mode 100644
index 0000000..533b105
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/norm_l.h
@@ -0,0 +1,153 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./gsm-amr/c/include/norm_l.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for norm_l function.
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description: Support for ARM and Linux-ARM assembly.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the norm_l function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef NORM_L_H
+#define NORM_L_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+#if !( defined(PV_ARM_V5) || defined(PV_ARM_GCC_V5) )
+
+ /* C EQUIVALENT */
+ Word16 norm_l(Word32 L_var1);
+
+#elif defined(PV_ARM_V5)
+
+ __inline Word16 norm_l(Word32 L_var1)
+ {
+ register Word32 var_out = 0;
+
+ __asm
+ {
+ CMP L_var1, #0
+ EORNE L_var1, L_var1, L_var1, LSL #1
+ CLZNE var_out, L_var1
+ }
+
+ return ((Word16)var_out);
+ }
+
+#elif defined(PV_ARM_GCC_V5)
+
+ static inline Word16 norm_l(Word32 L_var1)
+ {
+ register Word32 var_out = 0;
+ register Word32 ra = L_var1;
+ if (L_var1)
+ {
+ ra ^= (ra << 1);
+ asm volatile(
+ "clz %0, %1"
+ : "=r"(var_out)
+ : "r"(ra)
+ );
+ }
+ return (var_out);
+ }
+
+#endif
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/norm_s.h b/media/libstagefright/codecs/amrnb/common/include/norm_s.h
new file mode 100644
index 0000000..2e37a9f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/norm_s.h
@@ -0,0 +1,153 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./gsm-amr/c/include/norm_s.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for norm_s function.
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the norm_s function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef NORM_S_H
+#define NORM_S_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+#if !( defined(PV_ARM_V5) || defined(PV_ARM_GCC_V5) )
+
+ /* C EQUIVALENT */
+
+ Word16 norm_s(Word16 var1);
+
+#elif defined(PV_ARM_V5)
+
+ __inline Word16 norm_s(Word16 var)
+ {
+ register Word32 var_out = 0;
+ Word32 var1 = var << 16;
+
+ __asm
+ {
+ CMP var1, #0
+ EORNE var1, var1, var1, LSL #1
+ CLZNE var_out, var1
+ }
+
+ return ((Word16)var_out);
+ }
+
+#elif defined(PV_ARM_GCC_V5)
+
+ static inline Word16 norm_s(Word16 var1)
+ {
+ register Word32 var_out = 0;
+ register Word32 ra = var1 << 16;
+ if (ra)
+ {
+ ra ^= (ra << 1);
+ asm volatile(
+ "clz %0, %1"
+ : "=r"(var_out)
+ : "r"(ra)
+ );
+ }
+ return (var_out);
+ }
+
+#endif
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/oper_32b.h b/media/libstagefright/codecs/amrnb/common/include/oper_32b.h
new file mode 100644
index 0000000..ec3fcfb
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/oper_32b.h
@@ -0,0 +1,102 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/include/oper_32b.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Deleted inclusion of files that were not part of the original
+ oper_32b.h file.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file includes all the oper_32b.c functions' header files.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef OPER_32B_H
+#define OPER_32B_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+#include "div_32.h"
+#include "l_comp.h"
+#include "l_extract.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/p_ol_wgh.h b/media/libstagefright/codecs/amrnb/common/include/p_ol_wgh.h
new file mode 100644
index 0000000..6c277da
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/p_ol_wgh.h
@@ -0,0 +1,144 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/include/p_ol_wgh.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : p_ol_wgh.h
+ Purpose : Compute the open loop pitch lag with weighting.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef P_OL_WGH_H
+#define P_OL_WGH_H "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "vad.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+ extern const Word16 corrweight[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ /* state variable */
+
+ typedef struct
+ {
+ Word16 old_T0_med;
+ Word16 ada_w;
+ Word16 wght_flg;
+ } pitchOLWghtState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ Word16 p_ol_wgh_init(pitchOLWghtState **st);
+ /* initialize one instance of the pre processing state.
+ Stores pointer to filter status struct in *st. This pointer has to
+ be passed to p_ol_wgh in each call.
+ returns 0 on success
+ */
+
+ Word16 p_ol_wgh_reset(pitchOLWghtState *st);
+ /* reset of pre processing state (i.e. set state memory to zero)
+ returns 0 on success
+ */
+
+ void p_ol_wgh_exit(pitchOLWghtState **st);
+ /* de-initialize pre processing state (i.e. free status struct)
+ stores NULL in *st
+ */
+
+ Word16 Pitch_ol_wgh( /* o : open loop pitch lag */
+ pitchOLWghtState *st, /* i/o : State struct */
+ vadState *vadSt, /* i/o : VAD state struct */
+ Word16 signal[], /* i : signal used to compute the open loop pitch */
+ /* signal[-pit_max] to signal[-1] should be known */
+ Word16 pit_min, /* i : minimum pitch lag */
+ Word16 pit_max, /* i : maximum pitch lag */
+ Word16 L_frame, /* i : length of frame to compute pitch */
+ Word16 old_lags[], /* i : history with old stored Cl lags */
+ Word16 ol_gain_flg[], /* i : OL gain flag */
+ Word16 idx, /* i : index */
+ Flag dtx, /* i : dtx flag; use dtx=1, do not use dtx=0 */
+ Flag *pOverflow /* o : overflow flag */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _P_OL_WGH_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/pow2.h b/media/libstagefright/codecs/amrnb/common/include/pow2.h
new file mode 100644
index 0000000..9b944eb
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/pow2.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/log2_norm.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template. Added extern declaration for pow2_tbl[]
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains the prototype declaration for Pow2() function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef POW2_H
+#define POW2_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 pow2_tbl[];
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ Word32 Pow2( /* (o) : result (range: 0<=val<=0x7fffffff) */
+ Word16 exponent, /* (i) : Integer part. (range: 0<=val<=30) */
+ Word16 fraction, /* (i) : Fractional part. (range: 0.0<=val<1.0) */
+ Flag *pOverflow /* (i/o) : overflow flag */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _POW2_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/pred_lt.h b/media/libstagefright/codecs/amrnb/common/include/pred_lt.h
new file mode 100644
index 0000000..a2bfed2
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/pred_lt.h
@@ -0,0 +1,113 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Filename: /audio/gsm_amr/c/include/pred_lt.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the pred_lt function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef pred_lt_h
+#define pred_lt_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void Pred_lt_3or6(
+ 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 flag3, /* input : if set, upsampling rate = 3 (6 otherwise) */
+ Flag *pOverflow /* output: if set, overflow occurred in this function */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PRED_LT_H */
diff --git a/media/libstagefright/codecs/amrnb/common/include/pvgsmamr.h b/media/libstagefright/codecs/amrnb/common/include/pvgsmamr.h
new file mode 100644
index 0000000..b697524
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/pvgsmamr.h
@@ -0,0 +1,63 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+#ifndef __PVGSMAMR_H
+#define __PVGSMAMR_H
+
+
+// includes
+#include <e32std.h>
+#include <e32base.h>
+
+#include "sp_dec.h"
+#include "pvglobals.h"
+
+
+// PVGsmDecoder AO
+class CPVGsmDecoder : public CBase
+{
+ public:
+ IMPORT_C static CPVGsmDecoder* NewL(void);
+ IMPORT_C ~CPVGsmDecoder();
+ IMPORT_C TInt StartL(void);
+
+ // only port the API's used in PVPlayer 2.0
+ IMPORT_C TInt DecodeFrame(enum Mode mode, unsigned char* compressedBlock, unsigned char* audioBuffer);
+ IMPORT_C TInt InitDecoder(void);
+ IMPORT_C void ExitDecoder(void);
+
+ private:
+ CPVGsmDecoder();
+ void ConstructL(void);
+
+ Speech_Decode_FrameState* decState;
+ enum RXFrameType rx_type;
+ struct globalDataStruct *gds;
+};
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/q_plsf.h b/media/libstagefright/codecs/amrnb/common/include/q_plsf.h
new file mode 100644
index 0000000..431272a
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/q_plsf.h
@@ -0,0 +1,169 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/q_plsf.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the q_plsf_3.c and q_plsf_5.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef q_plsf_h
+#define q_plsf_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+#include "mode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define MR795_1_SIZE 512
+#define PAST_RQ_INIT_SIZE 8
+
+#define DICO1_SIZE 256
+#define DICO2_SIZE 512
+#define DICO3_SIZE 512
+
+#define DICO1_5_SIZE 128
+#define DICO2_5_SIZE 256
+#define DICO3_5_SIZE 256
+#define DICO4_5_SIZE 256
+#define DICO5_5_SIZE 64
+
+#define MR515_3_SIZE 128
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 past_rq[M]; /* Past quantized prediction error, Q15 */
+
+ } Q_plsfState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ Word16 Q_plsf_init(Q_plsfState **st);
+ /* initialize one instance of the state.
+ Stores pointer to filter status struct in *st. This pointer has to
+ be passed to Q_plsf_5 / Q_plsf_3 in each call.
+ returns 0 on success
+ */
+
+ Word16 Q_plsf_reset(Q_plsfState *st);
+ /* reset of state (i.e. set state memory to zero)
+ returns 0 on success
+ */
+
+ void Q_plsf_exit(Q_plsfState **st);
+ /* de-initialize state (i.e. free status struct)
+ stores NULL in *st
+ */
+
+ void Q_plsf_3(
+ Q_plsfState *st, /* i/o: state struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 *lsp1, /* i : 1st LSP vector Q15 */
+ Word16 *lsp1_q, /* o : quantized 1st LSP vector Q15 */
+ Word16 *indice, /* o : quantization indices of 3 vectors Q0 */
+ Word16 *pred_init_i,/* o : init index for MA prediction in DTX mode */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ void Q_plsf_5(
+ Q_plsfState *st,
+ Word16 *lsp1, /* i : 1st LSP vector, Q15 */
+ Word16 *lsp2, /* i : 2nd LSP vector, Q15 */
+ Word16 *lsp1_q, /* o : quantized 1st LSP vector, Q15 */
+ Word16 *lsp2_q, /* o : quantized 2nd LSP vector, Q15 */
+ Word16 *indice, /* o : quantization indices of 5 matrices, Q0 */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+ );
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _Q_PLSF_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/q_plsf_3_tbl.h b/media/libstagefright/codecs/amrnb/common/include/q_plsf_3_tbl.h
new file mode 100644
index 0000000..2e43d10
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/q_plsf_3_tbl.h
@@ -0,0 +1,136 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/q_plsf_3_tbl.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created this file from the reference, q_plsf_3_tbl.tab
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+#define MR795_1_SIZE 512
+#define PAST_RQ_INIT_SIZE 8
+
+#define DICO1_SIZE 256
+#define DICO2_SIZE 512
+#define DICO3_SIZE 512
+
+#define MR515_3_SIZE 128
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /* Codebooks of LSF prediction residual */
+ extern const Word16 mean_lsf_3[];
+
+ extern const Word16 pred_fac_3[];
+
+ extern const Word16 dico1_lsf_3[];
+ extern const Word16 dico2_lsf_3[];
+ extern const Word16 dico3_lsf_3[];
+
+ extern const Word16 mr515_3_lsf[];
+ extern const Word16 mr795_1_lsf[];
+
+ extern const Word16 past_rq_init[];
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/q_plsf_5_tbl.h b/media/libstagefright/codecs/amrnb/common/include/q_plsf_5_tbl.h
new file mode 100644
index 0000000..245b5f4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/q_plsf_5_tbl.h
@@ -0,0 +1,110 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: .audio/gsm-amr/c/include/q_plsf_5_tbl.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file declares tables defined in q_plsf_5_tbl.c.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef Q_PLSF_5_TBL_H
+#define Q_PLSF_5_TBL_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 mean_lsf_5[];
+ extern const Word16 dico1_lsf_5[];
+ extern const Word16 dico2_lsf_5[];
+ extern const Word16 dico3_lsf_5[];
+ extern const Word16 dico4_lsf_5[];
+ extern const Word16 dico5_lsf_5[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/qgain475_tab.h b/media/libstagefright/codecs/amrnb/common/include/qgain475_tab.h
new file mode 100644
index 0000000..6c0d766
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/qgain475_tab.h
@@ -0,0 +1,107 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: .audio/gsm-amr/c/include/qgain475_tab.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file declares tables defined in qgain475_tab.c.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef QGAIN475_TAB_H
+#define QGAIN475_TAB_H
+
+#define MR475_VQ_SIZE 256
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 table_gain_MR475[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/qua_gain.h b/media/libstagefright/codecs/amrnb/common/include/qua_gain.h
new file mode 100644
index 0000000..65b35ee
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/qua_gain.h
@@ -0,0 +1,135 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/qua_gain.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the file, qua_gain.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef qua_gain_h
+#define qua_gain_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "gc_pred.h"
+#include "mode.h"
+
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define VQ_SIZE_HIGHRATES 128
+#define VQ_SIZE_LOWRATES 64
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ Word16
+ Qua_gain( /* o : index of quantization. */
+ enum Mode mode, /* i : AMR mode */
+ Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
+ Word16 frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
+ Word16 frac_coeff[], /* i : energy coeff. (5), fraction part, Q15 */
+ Word16 exp_coeff[], /* i : energy coeff. (5), exponent part, Q0 */
+ /* (frac_coeff and exp_coeff computed in */
+ /* calc_filt_energies()) */
+ Word16 gp_limit, /* i : pitch gain limit */
+ Word16 *gain_pit, /* o : Pitch gain, Q14 */
+ Word16 *gain_cod, /* o : Code gain, Q1 */
+ Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */
+ /* (for MR122 MA predictor update) */
+ Word16 *qua_ener, /* o : quantized energy error, Q10 */
+ /* (for other MA predictor update) */
+ Flag *pOverflow /* o : overflow indicator */
+ );
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* qua_gain_h */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/qua_gain_tbl.h b/media/libstagefright/codecs/amrnb/common/include/qua_gain_tbl.h
new file mode 100644
index 0000000..a7691e7
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/qua_gain_tbl.h
@@ -0,0 +1,108 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: .audio/gsm-amr/c/include/qua_gain_tbl.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file declares tables defined in qua_gain_tbl.c.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef QUA_GAIN_TBL_H
+#define QUA_GAIN_TBL_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 table_gain_highrates[];
+ extern const Word16 table_gain_lowrates[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/reorder.h b/media/libstagefright/codecs/amrnb/common/include/reorder.h
new file mode 100644
index 0000000..620cd0b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/reorder.h
@@ -0,0 +1,109 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Filename: /audio/gsm_amr/c/include/reorder.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the Reorder_lsf() function.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef REORDER_H
+#define REORDER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void Reorder_lsf(
+ Word16 *lsf, /* (i/o) : vector of LSFs (range: 0<=val<=0.5) */
+ Word16 min_dist, /* (i) : minimum required distance */
+ Word16 n, /* (i) : LPC order */
+ Flag *pOverflow /* (i/o) : overflow Flag */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _REORDER_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/residu.h b/media/libstagefright/codecs/amrnb/common/include/residu.h
new file mode 100644
index 0000000..f4d0041
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/residu.h
@@ -0,0 +1,83 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : residu.h
+* Purpose : Computes the LP residual.
+* Description : The LP residual is computed by filtering the input
+* : speech through the LP inverse filter A(z).
+*
+*
+********************************************************************************
+*/
+#ifndef residu_h
+#define residu_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ ********************************************************************************
+ * DEFINITION OF DATA TYPES
+ ********************************************************************************
+ */
+
+ /*
+ ********************************************************************************
+ * DECLARATION OF PROTOTYPES
+ ********************************************************************************
+ */
+ void Residu(
+ Word16 a[], /* (i) : prediction coefficients */
+ Word16 x[], /* (i) : speech signal */
+ Word16 y[], /* (o) : residual signal */
+ Word16 lg /* (i) : size of filtering */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/reverse_bits.h b/media/libstagefright/codecs/amrnb/common/include/reverse_bits.h
new file mode 100644
index 0000000..fcc8df6
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/reverse_bits.h
@@ -0,0 +1,114 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: .audio/gsm-amr/c/include/reverse_bits.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Adding #include "mode.h" so that it compiles and works for the
+ ARM tools.
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the reverse_bits function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef REVERSE_BITS_H
+#define REVERSE_BITS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void reverse_bits(enum Mode mode, unsigned char *pCompressedBlock);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/round.h b/media/libstagefright/codecs/amrnb/common/include/round.h
new file mode 100644
index 0000000..3129e27
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/round.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Filename: /audio/gsm_amr/c/include/round.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for round function.
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the pv_round function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef ROUND_H
+#define ROUND_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 pv_round(Word32 L_var1, Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ROUND_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/set_zero.h b/media/libstagefright/codecs/amrnb/common/include/set_zero.h
new file mode 100644
index 0000000..debd223
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/set_zero.h
@@ -0,0 +1,79 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : set_zero.h
+* Description : Set vector x[] to zero
+*
+*
+********************************************************************************
+*/
+#ifndef set_zero_h
+#define set_zero_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ ********************************************************************************
+ * DEFINITION OF DATA TYPES
+ ********************************************************************************
+ */
+
+ /*
+ ********************************************************************************
+ * DECLARATION OF PROTOTYPES
+ ********************************************************************************
+ */
+ void Set_zero(
+ Word16 x[], /* (o) : vector to clear */
+ Word16 L /* (i) : length of vector */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/shl.h b/media/libstagefright/codecs/amrnb/common/include/shl.h
new file mode 100644
index 0000000..84ca8d9
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/shl.h
@@ -0,0 +1,118 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/shl.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for shl function.
+
+ Description: Changed prototype of the mult() function. Instead of using global
+ a pointer to overflow flag is now passed into the function.
+
+ Description: Updated template. Changed the parameter name from "overflow" to
+ "pOverflow" in the function prototype declaration
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the shl function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SHL_H
+#define SHL_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 shl(Word16 var1, Word16 var2, Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SHL_H_ */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/shr.h b/media/libstagefright/codecs/amrnb/common/include/shr.h
new file mode 100644
index 0000000..e961c04
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/shr.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/shr.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for shr function.
+
+ Description: Changed the function prototype declaration.
+ Updated template.
+
+ Description: Updated template. Changed the parameter name from "overflow" to
+ "pOverflow" in the function prototype declaration
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the shr function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SHR_H
+#define SHR_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 shr(Word16 var1, Word16 var2, Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SHR_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/shr_r.h b/media/libstagefright/codecs/amrnb/common/include/shr_r.h
new file mode 100644
index 0000000..c4f9e2c
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/shr_r.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./gsm-amr/c/include/shr_r.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for shr_r function.
+
+ Description: Passing in pOverflow.
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #define after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the shr_r function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SHR_R_H
+#define SHR_R_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 shr_r(Word16 var1, Word16 var2, Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/sqrt_l.h b/media/libstagefright/codecs/amrnb/common/include/sqrt_l.h
new file mode 100644
index 0000000..a6a2ee5
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/sqrt_l.h
@@ -0,0 +1,118 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/sqrt_l.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description: Updated function prototype declaration to reflect new interface.
+ A pointer to overflow flag is passed into the function. Updated
+ template.
+
+ Description: Added extern declaration for sqrt_l_tbl[]
+
+ Description: Moved _cplusplus #ifdef before function prototype.
+
+ Who: Date:
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the sqrt_l() function.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef SQRT_L_H
+#define SQRT_L_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 sqrt_l_tbl[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ Word32 sqrt_l_exp( /* o : output value, Q31 */
+ Word32 L_x, /* i : input value, Q31 */
+ Word16 *pExp, /* o : right shift to be applied to result, Q1 */
+ Flag *pOverflow /* i : pointer to overflow flag */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SQRT_L__H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/sub.h b/media/libstagefright/codecs/amrnb/common/include/sub.h
new file mode 100644
index 0000000..18dc456
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/sub.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/sub.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for sub function.
+
+ Description: Changed function prototype declaration.
+
+ Description: Updated copyright information.
+ Updated variable name from "overflow" to "pOverflow" to match
+ with original function declaration.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the sub function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef SUB_H
+#define SUB_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 sub(Word16 var1, Word16 var2, Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SUB_H_ */
diff --git a/media/libstagefright/codecs/amrnb/common/include/syn_filt.h b/media/libstagefright/codecs/amrnb/common/include/syn_filt.h
new file mode 100644
index 0000000..7fff112
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/syn_filt.h
@@ -0,0 +1,83 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : syn_filt.h
+* Purpose : Perform synthesis filtering through 1/A(z).
+*
+*
+********************************************************************************
+*/
+#ifndef syn_filt_h
+#define syn_filt_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ ********************************************************************************
+ * DEFINITION OF DATA TYPES
+ ********************************************************************************
+ */
+
+ /*
+ ********************************************************************************
+ * DECLARATION OF PROTOTYPES
+ ********************************************************************************
+ */
+ void Syn_filt(
+ Word16 a[], /* (i) : a[m+1] prediction coefficients (m=10) */
+ 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. */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/typedef.h b/media/libstagefright/codecs/amrnb/common/include/typedef.h
new file mode 100644
index 0000000..ee4d732
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/typedef.h
@@ -0,0 +1,73 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : typedef.c
+* Purpose : Basic types.
+*
+********************************************************************************
+*/
+#ifndef typedef_h
+#define typedef_h "$Id $"
+
+#undef ORIGINAL_TYPEDEF_H /* CHANGE THIS TO #define to get the */
+/* "original" ETSI version of typedef.h */
+/* CHANGE TO #undef for PV version */
+
+#ifdef ORIGINAL_TYPEDEF_H
+/*
+ * this is the original code from the ETSI file typedef.h
+ */
+
+#if defined(__unix__) || defined(__unix)
+typedef signed char Word8;
+typedef short Word16;
+typedef int Word32;
+typedef int Flag;
+
+#else
+#error No System recognized
+#endif
+#else /* not original typedef.h */
+
+/*
+ * use (improved) type definition file typdefs.h
+ */
+#include "gsm_amr_typedefs.h"
+
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/vad.h b/media/libstagefright/codecs/amrnb/common/include/vad.h
new file mode 100644
index 0000000..b9ee89f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/vad.h
@@ -0,0 +1,76 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+**-------------------------------------------------------------------------**
+** **
+** GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001 **
+** R99 Version 3.2.0 **
+** REL-4 Version 4.0.0 **
+** **
+**-------------------------------------------------------------------------**
+********************************************************************************
+*
+* File : vad.h
+* Purpose : Voice Activity Detection (VAD) for AMR
+*
+********************************************************************************
+*/
+#ifndef vad_h
+#define vad_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+
+#include "vad1.h" /* for VAD option 1 */
+#include "vad2.h" /* for VAD option 2 */
+
+/*
+********************************************************************************
+* LOCAL VARIABLES AND TABLES
+********************************************************************************
+*/
+
+/*
+********************************************************************************
+* DEFINITION OF DATA TYPES
+********************************************************************************
+*/
+
+#ifndef VAD2
+#define vadState vadState1
+#else
+#define vadState vadState2
+#endif
+
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/vad1.h b/media/libstagefright/codecs/amrnb/common/include/vad1.h
new file mode 100644
index 0000000..c144ea0
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/vad1.h
@@ -0,0 +1,197 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/include/vad_1.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions, prototype and structure
+ definitions needed by vad_1.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef vad_1_h
+#define vad_1_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst_vad.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ /* state variable */
+ 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[3][2]; /* memory for the filter bank */
+ Word16 a_data3[5]; /* 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 three variables (vadreg, pitch and tone)
+ 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 pitch; /* flags for pitch detection */
+ Word16 tone; /* flags for tone detection */
+ Word16 complex_high; /* flags for complex detection */
+ Word16 complex_low; /* flags for complex detection */
+
+ Word16 oldlag_count, oldlag; /* variables for pitch detection */
+
+ Word16 complex_hang_count; /* complex hangover counter, used by VAD */
+ Word16 complex_hang_timer; /* hangover initiator, used by CAD */
+
+ Word16 best_corr_hp; /* FIP filtered value Q15 */
+
+ Word16 speech_vad_decision; /* final decision */
+ Word16 complex_warning; /* complex background warning */
+
+ Word16 sp_burst_count; /* counts length of a speech burst incl */
+ Word16 corr_hp_fast; /* filtered value */
+ } vadState1;
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 vad1_init(vadState1 **st);
+ /* initialize one instance of the pre processing state.
+ Stores pointer to filter status struct in *st. This pointer has to
+ be passed to vad in each call.
+ returns 0 on success
+ */
+
+ Word16 vad1_reset(vadState1 *st);
+ /* reset of pre processing state (i.e. set state memory to zero)
+ returns 0 on success
+ */
+
+ void vad1_exit(vadState1 **st);
+ /* de-initialize pre processing state (i.e. free status struct)
+ stores NULL in *st
+ */
+
+ void vad_complex_detection_update(vadState1 *st, /* i/o : State struct */
+ Word16 best_corr_hp /* i : best Corr Q15 */
+ );
+
+ void vad_tone_detection(vadState1 *st, /* i/o : State struct */
+ Word32 t0, /* i : autocorrelation maxima */
+ Word32 t1, /* i : energy */
+ Flag *pOverflow
+ );
+
+ void vad_tone_detection_update(
+ vadState1 *st, /* i/o : State struct */
+ Word16 one_lag_per_frame, /* i : 1 if one open-loop lag is
+ calculated per each frame,
+ otherwise 0 */
+ Flag *pOverflow
+ );
+
+ void vad_pitch_detection(vadState1 *st, /* i/o : State struct */
+ Word16 lags[], /* i : speech encoder open loop lags */
+ Flag *pOverflow
+ );
+
+ Word16 vad1(vadState1 *st, /* i/o : State struct */
+ Word16 in_buf[], /* i : samples of the input frame
+ inbuf[159] is the very last sample,
+ incl lookahead */
+ Flag *pOverflow
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VAD1_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/vad2.h b/media/libstagefright/codecs/amrnb/common/include/vad2.h
new file mode 100644
index 0000000..3197b3a
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/vad2.h
@@ -0,0 +1,203 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Filename: /audio/gsm_amr/c/include/vad2.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Added pOverflow to the r_fft function prototype.
+
+ Description: Added pOverflow to the LTP_flag_update prototype.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions, prototype and structure
+ definitions needed by vad_2.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef vad_2_h
+#define vad_2_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+#define YES 1
+#define NO 0
+#define ON 1
+#define OFF 0
+#define TRUE 1
+#define FALSE 0
+
+#define FRM_LEN 80
+#define DELAY 24
+#define FFT_LEN 128
+
+#define NUM_CHAN 16
+#define LO_CHAN 0
+#define HI_CHAN 15
+
+#define UPDATE_THLD 35
+#define HYSTER_CNT_THLD 6
+#define UPDATE_CNT_THLD 50
+
+#define SHIFT_STATE_0 0 /* channel energy scaled as 22,9 */
+#define SHIFT_STATE_1 1 /* channel energy scaled as 27,4 */
+
+#define NOISE_FLOOR_CHAN_0 512 /* 1.0 scaled as 22,9 */
+#define MIN_CHAN_ENRG_0 32 /* 0.0625 scaled as 22,9 */
+#define MIN_NOISE_ENRG_0 32 /* 0.0625 scaled as 22,9 */
+#define INE_NOISE_0 8192 /* 16.0 scaled as 22,9 */
+#define FRACTIONAL_BITS_0 9 /* used as input to fn10Log10() */
+
+#define NOISE_FLOOR_CHAN_1 16 /* 1.0 scaled as 27,4 */
+#define MIN_CHAN_ENRG_1 1 /* 0.0625 scaled as 27,4 */
+#define MIN_NOISE_ENRG_1 1 /* 0.0625 scaled as 27,4 */
+#define INE_NOISE_1 256 /* 16.0 scaled as 27,4 */
+#define FRACTIONAL_BITS_1 4 /* used as input to fn10Log10() */
+
+#define STATE_1_TO_0_SHIFT_R (FRACTIONAL_BITS_1-FRACTIONAL_BITS_0) /* state correction factor */
+#define STATE_0_TO_1_SHIFT_R (FRACTIONAL_BITS_0-FRACTIONAL_BITS_1) /* state correction factor */
+
+#define HIGH_ALPHA 29491 /* 0.9 scaled as 0,15 */
+#define LOW_ALPHA 22938 /* 0.7 scaled as 0,15 */
+#define ALPHA_RANGE (HIGH_ALPHA - LOW_ALPHA)
+#define DEV_THLD 7168 /* 28.0 scaled as 7,8 */
+
+#define PRE_EMP_FAC (-26214) /* -0.8 scaled as 0,15 */
+
+#define CEE_SM_FAC 18022 /* 0.55 scaled as 0,15 */
+#define ONE_MINUS_CEE_SM_FAC 14746 /* 0.45 scaled as 0,15 */
+
+#define CNE_SM_FAC 3277 /* 0.1 scaled as 0,15 */
+#define ONE_MINUS_CNE_SM_FAC 29491 /* 0.9 scaled as 0,15 */
+
+#define FFT_HEADROOM 2
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ typedef struct
+ {
+ Word16 pre_emp_mem;
+ Word16 update_cnt;
+ Word16 hyster_cnt;
+ Word16 last_update_cnt;
+ Word16 ch_enrg_long_db[NUM_CHAN]; /* scaled as 7,8 */
+
+ Word32 Lframe_cnt;
+ Word32 Lch_enrg[NUM_CHAN]; /* scaled as 22,9 or 27,4 */
+ Word32 Lch_noise[NUM_CHAN]; /* scaled as 22,9 */
+
+ Word16 last_normb_shift; /* last block norm shift count */
+
+ Word16 tsnr; /* total signal-to-noise ratio in dB (scaled as 7,8) */
+ Word16 hangover;
+ Word16 burstcount;
+ Word16 fupdate_flag; /* forced update flag from previous frame */
+ Word16 negSNRvar; /* Negative SNR variance (scaled as 7,8) */
+ Word16 negSNRbias; /* sensitivity bias from negative SNR variance (scaled as 15,0) */
+
+ Word16 shift_state; /* use 22,9 or 27,4 scaling for ch_enrg[] */
+
+ Word32 L_R0;
+ Word32 L_Rmax;
+ Flag LTP_flag; /* Use to indicate the the LTP gain is > LTP_THRESH */
+
+ } vadState2;
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 vad2(Word16 *farray_ptr, vadState2 *st, Flag *pOverflow);
+ Word16 vad2_init(vadState2 **st);
+ Word16 vad2_reset(vadState2 *st);
+ void vad2_exit(vadState2 **state);
+
+ void r_fft(Word16 *farray_ptr, Flag *pOverflow);
+
+ void LTP_flag_update(vadState2 *st, Word16 mode, Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VAD2_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/weight_a.h b/media/libstagefright/codecs/amrnb/common/include/weight_a.h
new file mode 100644
index 0000000..0358c85
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/weight_a.h
@@ -0,0 +1,81 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : weight_a.h
+* Purpose : Spectral expansion of LP coefficients. (order==10)
+* Description : a_exp[i] = a[i] * fac[i-1] ,i=1,10
+*
+*
+********************************************************************************
+*/
+#ifndef weight_a_h
+#define weight_a_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ ********************************************************************************
+ * DEFINITION OF DATA TYPES
+ ********************************************************************************
+ */
+
+ /*
+ ********************************************************************************
+ * DECLARATION OF PROTOTYPES
+ ********************************************************************************
+ */
+ void Weight_Ai(
+ Word16 a[], /* (i) : a[m+1] LPC coefficients (m=10) */
+ const Word16 fac[],/* (i) : Spectral expansion factors. */
+ Word16 a_exp[] /* (o) : Spectral expanded LPC coefficients */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/include/window_tab.h b/media/libstagefright/codecs/amrnb/common/include/window_tab.h
new file mode 100644
index 0000000..42233af
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/window_tab.h
@@ -0,0 +1,109 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: .audio/gsm-amr/c/include/window_tab.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file declares a tables in window_tab.c used in lpc.c.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef WINDOW_TAB_H
+#define WINDOW_TAB_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 window_200_40[];
+ extern const Word16 window_160_80[];
+ extern const Word16 window_232_8[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/include/wmf_to_ets.h b/media/libstagefright/codecs/amrnb/common/include/wmf_to_ets.h
new file mode 100644
index 0000000..8bcccc8
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/include/wmf_to_ets.h
@@ -0,0 +1,119 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./audio/gsm-amr/include/src/wmf_to_ets.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed mode to frame_type_3gpp
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the wmf_to_ets function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef WMF_TO_ETS_H
+#define WMF_TO_ETS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "frame_type_3gpp.h"
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void wmf_to_ets(enum Frame_Type_3GPP frame_type_3gpp,
+ UWord8 *wmf_input_ptr,
+ Word16 *ets_output_ptr);
+
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/pvgsmamrdecoderinterface.h b/media/libstagefright/codecs/amrnb/common/pvgsmamrdecoderinterface.h
new file mode 100644
index 0000000..ccbed44
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/pvgsmamrdecoderinterface.h
@@ -0,0 +1,183 @@
+/* ------------------------------------------------------------------
+ * 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: pvgsmamrdecoderinterface.h //
+// //
+//////////////////////////////////////////////////////////////////////////////////
+
+#ifndef _PVGSMAMR_DECODER_INTERFACE_H
+#define _PVGSMAMR_DECODER_INTERFACE_H
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+typedef enum
+{
+ /*
+ * One word (2-byte) to indicate type of frame type.
+ * One word (2-byte) to indicate frame type.
+ * One word (2-byte) to indicate mode.
+ * N words (2-byte) containing N bits (bit 0 = 0xff81, bit 1 = 0x007f).
+ */
+ ETS = 0, /* Both AMR-Narrowband and AMR-Wideband */
+
+ /*
+ * One word (2-byte) for sync word (good frames: 0x6b21, bad frames: 0x6b20)
+ * One word (2-byte) for frame length N.
+ * N words (2-byte) containing N bits (bit 0 = 0x007f, bit 1 = 0x0081).
+ */
+ ITU, /* AMR-Wideband */
+
+ /*
+ * AMR-WB MIME/storage format, see RFC 3267 (sections 5.1 and 5.3) for details
+ */
+ MIME_IETF,
+
+ WMF, /* AMR-Narrowband */
+
+ IF2 /* AMR-Narrowband */
+
+} bitstream_format;
+
+
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+typedef struct
+{
+ int16_t prev_ft;
+ int16_t prev_mode;
+} RX_State;
+
+
+typedef struct tPVAmrDecoderExternal
+{
+ /*
+ * INPUT:
+ * Pointer to the input buffer that contains the encoded bistream data.
+ * The data is filled in such that the first bit transmitted is
+ * the most-significant bit (MSB) of the first array element.
+ * The buffer is accessed in a linear fashion for speed, and the number of
+ * bytes consumed varies frame to frame. This is use for mime/ietf data
+ */
+ uint8_t *pInputBuffer;
+
+ /*
+ * INPUT:
+ * Pointer to the input buffer that contains the encoded stream data.
+ * The data is filled such that the first bit transmitted is
+ * in the first int16_t element.
+ * The buffer is accessed in a linear fashion for speed, and the number of
+ * bytes consumed varies frame to frame.
+ */
+ int16_t *pInputSampleBuffer;
+
+ /*
+ * INPUT: (but what is pointed to is an output)
+ * Pointer to the output buffer to hold the 16-bit PCM audio samples.
+ */
+ int16_t *pOutputBuffer;
+
+ /*
+ * INPUT:
+ * Number of requested output audio channels. This relieves the calling
+ * environment from having to perform stereo-to-mono or mono-to-stereo
+ * conversions.
+ */
+ int32_t desiredChannels;
+
+ /*
+ * INPUT:
+ * Format type of the encoded bitstream.
+ */
+ bitstream_format input_format;
+
+ /*
+ * OUTPUT:
+ * The sampling rate decoded from the bitstream, in units of
+ * samples/second. For this release of the library this value does
+ * not change from frame to frame, but future versions will.
+ */
+ int32_t samplingRate;
+
+ /*
+ * OUTPUT:
+ * This value is the bitrate in units of bits/second. IT
+ * is calculated using the number of bits consumed for the current frame,
+ * and then multiplying by the sampling_rate, divided by points in a frame.
+ * This value can changes frame to frame.
+ */
+ int32_t bitRate;
+
+ /*
+ * OUTPUT:
+ * The number of channels decoded from the bitstream. The output data
+ * will have be the amount specified in the variable desiredChannels,
+ * this output is informative only, and can be ignored.
+ */
+ int32_t encodedChannels;
+
+ /*
+ * OUTPUT:
+ * This value is the number of output PCM samples per channel.
+ * It is 320.
+ */
+ int16_t frameLength;
+
+ /*
+ * OUTPUT:
+ * This value is the quality indicator. 1 (good) 0 (bad)
+ */
+ uint8_t quality;
+
+
+ /*
+ * OUTPUT:
+ * GSM AMR NB and WB mode (i.e. bit-rate )
+ */
+ int16_t mode;
+ int16_t mode_old;
+
+ /*
+ * OUTPUT:
+ * GSM AMR NB and WB frame type ( speech_good, speech_bad, sid, etc.)
+ */
+ int16_t frame_type;
+
+ int16_t reset_flag;
+ int16_t reset_flag_old;
+
+ /*
+ * OUTPUT:
+ * Decoder status
+ */
+ int32_t status;
+
+ /*
+ * OUTPUT:
+ * Rx status state
+ */
+ RX_State rx_state;
+
+} tPVAmrDecoderExternal;
+
+#endif
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/add.cpp b/media/libstagefright/codecs/amrnb/common/src/add.cpp
new file mode 100644
index 0000000..d488ca5
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/add.cpp
@@ -0,0 +1,203 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/add.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for add function. Sync'ed up with the
+ current template and fixed tabs.
+
+ Description: Changed all occurrences of L_sum with sum.
+
+ Description: Changed function protype to pass in pointer to Overflow flag
+ as a parameter.
+
+ Description: Removed code that updates MOPS counter
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Summation function with overflow control
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: add
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the add operation resulted in overflow
+
+ Returns:
+ sum = 16-bit limited sum of var1 and var2 (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function 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.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] add.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Word16 add (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 sum;
+
+ sum = (Word32) var1 + var2;
+
+* The reference ETSI code uses a global flag for Overflow inside the function
+* saturate(). In the actual implementation a pointer to Overflow flag is passed in
+* as a parameter to the function
+
+ var_out = saturate (sum);
+#if (WMOPS)
+ multiCounter[currCounter].add++;
+#endif
+ return (var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word16 add(Word16 var1, Word16 var2, Flag *pOverflow)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ Word32 sum;
+ sum = (Word32) var1 + var2;
+
+ /* Saturate result (if necessary). */
+ /* Replaced function call with in-line code */
+ /* to conserve MIPS, i.e., var_out = saturate (sum) */
+
+ if (sum > 0X00007fffL)
+ {
+ *pOverflow = 1;
+ sum = MAX_16;
+ }
+ else if (sum < (Word32) 0xffff8000L)
+ {
+ *pOverflow = 1;
+ sum = MIN_16;
+ }
+
+ /* Return the sum as a 16 bit value by type casting Word32 to Word16 */
+
+ return ((Word16) sum);
+}
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp b/media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp
new file mode 100644
index 0000000..4135f30
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/az_lsp.cpp
@@ -0,0 +1,740 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./audio/gsm-amr/c/src/az_lsp.c
+ Funtions: Chebps
+ Chebps_Wrapper
+ Az_lsp
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Finished first pass of optimization.
+
+ Description: Made changes based on review comments.
+
+ Description: Made input to Chebps_Wrapper consistent with that of Chebps.
+
+ Description: Replaced current Pseudo-code with the UMTS code version 3.2.0.
+ Updated coding template.
+
+ Description: Replaced basic_op.h and oper_32b.h with the header files of the
+ math functions used by the file.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Used "-" operator instead of calling sub function in the
+ az_lsp() code.
+ 2. Copied detailed function description of az_lsp from the
+ header file.
+ 3. Modified local variable definition to one per line.
+ 4. Used NC in the definition of f1 and f2 arrays.
+ 5. Added curly brackets in the IF statement.
+
+ Description: Changed function interface to pass in a pointer to overflow
+ flag into the function instead of using a global flag. Removed
+ inclusion of unneeded header files.
+
+ Description: For Chebps() and Az_lsp()
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated math operations that unnecessary checked for
+ saturation.
+ 4. Eliminated not needed variables
+ 5. Eliminated if-else checks for saturation
+ 6. Deleted unused function cheps_wraper
+
+ Description: Added casting to eliminate warnings
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ These modules compute the LSPs from the LP coefficients.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "az_lsp.h"
+#include "cnst.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define NC M/2 /* M = LPC order, NC = M/2 */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Chebps
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ x = input value (Word16)
+ f = polynomial (Word16)
+ n = polynomial order (Word16)
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the operations in the function resulted in saturation.
+
+ Returns:
+ cheb = Chebyshev polynomial for the input value x.(Word16)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This module evaluates the Chebyshev polynomial series.
+ - The polynomial order is n = m/2 = 5
+ - The polynomial F(z) (F1(z) or F2(z)) is given by
+ F(w) = 2 exp(-j5w) C(x)
+ where
+ C(x) = T_n(x) + f(1)T_n-1(x) + ... +f(n-1)T_1(x) + f(n)/2
+ and T_m(x) = cos(mw) is the mth order Chebyshev
+ polynomial ( x=cos(w) )
+ - C(x) for the input x is returned.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ az_lsp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+static Word16 Chebps (Word16 x,
+ Word16 f[], // (n)
+ Word16 n)
+{
+ Word16 i, cheb;
+ Word16 b0_h, b0_l, b1_h, b1_l, b2_h, b2_l;
+ Word32 t0;
+
+// The reference ETSI code uses a global flag for Overflow. However, in the
+// actual implementation a pointer to Overflow flag is passed in as a
+// parameter to the function. This pointer is passed into all the basic math
+// functions invoked
+
+ b2_h = 256; // b2 = 1.0
+ b2_l = 0;
+
+ t0 = L_mult (x, 512); // 2*x
+ t0 = L_mac (t0, f[1], 8192); // + f[1]
+ L_Extract (t0, &b1_h, &b1_l); // b1 = 2*x + f[1]
+
+ for (i = 2; i < n; i++)
+ {
+ t0 = Mpy_32_16 (b1_h, b1_l, x); // t0 = 2.0*x*b1
+ t0 = L_shl (t0, 1);
+ t0 = L_mac (t0, b2_h, (Word16) 0x8000); // t0 = 2.0*x*b1 - b2
+ t0 = L_msu (t0, b2_l, 1);
+ t0 = L_mac (t0, f[i], 8192); // t0 = 2.0*x*b1 - b2 + f[i]
+
+ L_Extract (t0, &b0_h, &b0_l); // b0 = 2.0*x*b1 - b2 + f[i]
+
+ b2_l = b1_l; // b2 = b1;
+ b2_h = b1_h;
+ b1_l = b0_l; // b1 = b0;
+ b1_h = b0_h;
+ }
+
+ t0 = Mpy_32_16 (b1_h, b1_l, x); // t0 = x*b1;
+ t0 = L_mac (t0, b2_h, (Word16) 0x8000); // t0 = x*b1 - b2
+ t0 = L_msu (t0, b2_l, 1);
+ t0 = L_mac (t0, f[i], 4096); // t0 = x*b1 - b2 + f[i]/2
+
+ t0 = L_shl (t0, 6);
+
+ cheb = extract_h (t0);
+
+ return (cheb);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static Word16 Chebps(Word16 x,
+ Word16 f[], /* (n) */
+ Word16 n,
+ Flag *pOverflow)
+{
+ Word16 i;
+ Word16 cheb;
+ Word16 b1_h;
+ Word16 b1_l;
+ Word32 t0;
+ Word32 L_temp;
+ Word16 *p_f = &f[1];
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ /* L_temp = 1.0 */
+
+ L_temp = 0x01000000L;
+
+ t0 = ((Word32) x << 10) + ((Word32) * (p_f++) << 14);
+
+ /* b1 = t0 = 2*x + f[1] */
+
+ b1_h = (Word16)(t0 >> 16);
+ b1_l = (Word16)((t0 >> 1) - (b1_h << 15));
+
+
+ for (i = 2; i < n; i++)
+ {
+ /* t0 = 2.0*x*b1 */
+ t0 = ((Word32) b1_h * x);
+ t0 += ((Word32) b1_l * x) >> 15;
+ t0 <<= 2;
+
+ /* t0 = 2.0*x*b1 - b2 */
+ t0 -= L_temp;
+
+ /* t0 = 2.0*x*b1 - b2 + f[i] */
+ t0 += (Word32) * (p_f++) << 14;
+
+ L_temp = ((Word32) b1_h << 16) + ((Word32) b1_l << 1);
+
+ /* b0 = 2.0*x*b1 - b2 + f[i]*/
+ b1_h = (Word16)(t0 >> 16);
+ b1_l = (Word16)((t0 >> 1) - (b1_h << 15));
+
+ }
+
+ /* t0 = x*b1; */
+ t0 = ((Word32) b1_h * x);
+ t0 += ((Word32) b1_l * x) >> 15;
+ t0 <<= 1;
+
+
+ /* t0 = x*b1 - b2 */
+ t0 -= L_temp;
+
+ /* t0 = x*b1 - b2 + f[i]/2 */
+ t0 += (Word32) * (p_f) << 13;
+
+
+ if ((UWord32)(t0 - 0xfe000000L) < (UWord32)0x03ffffffL)
+ {
+ cheb = (Word16)(t0 >> 10);
+ }
+ else
+ {
+ if (t0 > (Word32) 0x01ffffffL)
+ {
+ cheb = MAX_16;
+
+ }
+ else
+ {
+ cheb = MIN_16;
+ }
+ }
+
+ return (cheb);
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Az_lsp
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS FOR Az_lsp
+
+ Inputs:
+ a = predictor coefficients (Word16)
+ lsp = line spectral pairs (Word16)
+ old_lsp = old line spectral pairs (Word16)
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the operations in the function resulted in saturation.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes the LSPs from the LP coefficients.
+
+ The sum and difference filters are computed and divided by 1+z^{-1} and
+ 1-z^{-1}, respectively.
+
+ f1[i] = a[i] + a[11-i] - f1[i-1] ; i=1,...,5
+ f2[i] = a[i] - a[11-i] + f2[i-1] ; i=1,...,5
+
+ The roots of F1(z) and F2(z) are found using Chebyshev polynomial evaluation.
+ The polynomials are evaluated at 60 points regularly spaced in the
+ frequency domain. The sign change interval is subdivided 4 times to better
+ track the root. The LSPs are found in the cosine domain [1,-1].
+
+ If less than 10 roots are found, the LSPs from the past frame are used.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ az_lsp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Az_lsp (
+ Word16 a[], // (i) : predictor coefficients (MP1)
+ Word16 lsp[], // (o) : line spectral pairs (M)
+ Word16 old_lsp[] // (i) : old lsp[] (in case not found 10 roots) (M)
+)
+{
+ Word16 i, j, nf, ip;
+ Word16 xlow, ylow, xhigh, yhigh, xmid, ymid, xint;
+ Word16 x, y, sign, exp;
+ Word16 *coef;
+ Word16 f1[M / 2 + 1], f2[M / 2 + 1];
+ Word32 t0;
+
+ *-------------------------------------------------------------*
+ * find the sum and diff. pol. F1(z) and F2(z) *
+ * F1(z) <--- F1(z)/(1+z**-1) & F2(z) <--- F2(z)/(1-z**-1) *
+ * *
+ * f1[0] = 1.0; *
+ * f2[0] = 1.0; *
+ * *
+ * for (i = 0; i< NC; i++) *
+ * { *
+ * f1[i+1] = a[i+1] + a[M-i] - f1[i] ; *
+ * f2[i+1] = a[i+1] - a[M-i] + f2[i] ; *
+ * } *
+ *-------------------------------------------------------------*
+
+ f1[0] = 1024; // f1[0] = 1.0
+ f2[0] = 1024; // f2[0] = 1.0
+
+// The reference ETSI code uses a global flag for Overflow. However, in the
+// actual implementation a pointer to Overflow flag is passed in as a
+// parameter to the function. This pointer is passed into all the basic math
+// functions invoked
+
+ for (i = 0; i < NC; i++)
+ {
+ t0 = L_mult (a[i + 1], 8192); // x = (a[i+1] + a[M-i]) >> 2
+ t0 = L_mac (t0, a[M - i], 8192);
+ x = extract_h (t0);
+ // f1[i+1] = a[i+1] + a[M-i] - f1[i]
+ f1[i + 1] = sub (x, f1[i]);
+
+ t0 = L_mult (a[i + 1], 8192); // x = (a[i+1] - a[M-i]) >> 2
+ t0 = L_msu (t0, a[M - i], 8192);
+ x = extract_h (t0);
+ // f2[i+1] = a[i+1] - a[M-i] + f2[i]
+ f2[i + 1] = add (x, f2[i]);
+ }
+
+ *-------------------------------------------------------------*
+ * find the LSPs using the Chebychev pol. evaluation *
+ *-------------------------------------------------------------*
+
+ nf = 0; // number of found frequencies
+ ip = 0; // indicator for f1 or f2
+
+ coef = f1;
+
+ xlow = grid[0];
+ ylow = Chebps (xlow, coef, NC);
+
+ j = 0;
+ // while ( (nf < M) && (j < grid_points) )
+ while ((sub (nf, M) < 0) && (sub (j, grid_points) < 0))
+ {
+ j++;
+ xhigh = xlow;
+ yhigh = ylow;
+ xlow = grid[j];
+ ylow = Chebps (xlow, coef, NC);
+
+ if (L_mult (ylow, yhigh) <= (Word32) 0L)
+ {
+
+ // divide 4 times the interval
+
+ for (i = 0; i < 4; i++)
+ {
+ // xmid = (xlow + xhigh)/2
+ xmid = add (shr (xlow, 1), shr (xhigh, 1));
+ ymid = Chebps (xmid, coef, NC);
+
+ if (L_mult (ylow, ymid) <= (Word32) 0L)
+ {
+ yhigh = ymid;
+ xhigh = xmid;
+ }
+ else
+ {
+ ylow = ymid;
+ xlow = xmid;
+ }
+ }
+
+ *-------------------------------------------------------------*
+ * Linear interpolation *
+ * xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow); *
+ *-------------------------------------------------------------*
+
+ x = sub (xhigh, xlow);
+ y = sub (yhigh, ylow);
+
+ if (y == 0)
+ {
+ xint = xlow;
+ }
+ else
+ {
+ sign = y;
+ y = abs_s (y);
+ exp = norm_s (y);
+ y = shl (y, exp);
+ y = div_s ((Word16) 16383, y);
+ t0 = L_mult (x, y);
+ t0 = L_shr (t0, sub (20, exp));
+ y = extract_l (t0); // y= (xhigh-xlow)/(yhigh-ylow)
+
+ if (sign < 0)
+ y = negate (y);
+
+ t0 = L_mult (ylow, y);
+ t0 = L_shr (t0, 11);
+ xint = sub (xlow, extract_l (t0)); // xint = xlow - ylow*y
+ }
+
+ lsp[nf] = xint;
+ xlow = xint;
+ nf++;
+
+ if (ip == 0)
+ {
+ ip = 1;
+ coef = f2;
+ }
+ else
+ {
+ ip = 0;
+ coef = f1;
+ }
+ ylow = Chebps (xlow, coef, NC);
+
+ }
+ }
+
+ // Check if M roots found
+
+ if (sub (nf, M) < 0)
+ {
+ for (i = 0; i < M; i++)
+ {
+ lsp[i] = old_lsp[i];
+ }
+
+ }
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Az_lsp(
+ Word16 a[], /* (i) : predictor coefficients (MP1) */
+ Word16 lsp[], /* (o) : line spectral pairs (M) */
+ Word16 old_lsp[], /* (i) : old lsp[] (in case not found 10 roots) (M) */
+ Flag *pOverflow /* (i/o): overflow flag */
+)
+{
+ register Word16 i;
+ register Word16 j;
+ register Word16 nf;
+ register Word16 ip;
+ Word16 xlow;
+ Word16 ylow;
+ Word16 xhigh;
+ Word16 yhigh;
+ Word16 xmid;
+ Word16 ymid;
+ Word16 xint;
+ Word16 x;
+ Word16 y;
+ Word16 sign;
+ Word16 exp;
+ Word16 *coef;
+ Word16 f1[NC + 1];
+ Word16 f2[NC + 1];
+ Word32 L_temp1;
+ Word32 L_temp2;
+ Word16 *p_f1 = f1;
+ Word16 *p_f2 = f2;
+
+ /*-------------------------------------------------------------*
+ * find the sum and diff. pol. F1(z) and F2(z) *
+ * F1(z) <--- F1(z)/(1+z**-1) & F2(z) <--- F2(z)/(1-z**-1) *
+ * *
+ * f1[0] = 1.0; *
+ * f2[0] = 1.0; *
+ * *
+ * for (i = 0; i< NC; i++) *
+ * { *
+ * f1[i+1] = a[i+1] + a[M-i] - f1[i] ; *
+ * f2[i+1] = a[i+1] - a[M-i] + f2[i] ; *
+ * } *
+ *-------------------------------------------------------------*/
+
+ *p_f1 = 1024; /* f1[0] = 1.0 */
+ *p_f2 = 1024; /* f2[0] = 1.0 */
+
+ for (i = 0; i < NC; i++)
+ {
+ L_temp1 = (Word32) * (a + i + 1);
+ L_temp2 = (Word32) * (a + M - i);
+ /* x = (a[i+1] + a[M-i]) >> 2 */
+ x = (Word16)((L_temp1 + L_temp2) >> 2);
+ /* y = (a[i+1] - a[M-i]) >> 2 */
+ y = (Word16)((L_temp1 - L_temp2) >> 2);
+ /* f1[i+1] = a[i+1] + a[M-i] - f1[i] */
+ x -= *(p_f1++);
+ *(p_f1) = x;
+ /* f2[i+1] = a[i+1] - a[M-i] + f2[i] */
+ y += *(p_f2++);
+ *(p_f2) = y;
+ }
+
+ /*-------------------------------------------------------------*
+ * find the LSPs using the Chebychev pol. evaluation *
+ *-------------------------------------------------------------*/
+
+ nf = 0; /* number of found frequencies */
+ ip = 0; /* indicator for f1 or f2 */
+
+ coef = f1;
+
+ xlow = *(grid);
+ ylow = Chebps(xlow, coef, NC, pOverflow);
+
+ j = 0;
+
+ while ((nf < M) && (j < grid_points))
+ {
+ j++;
+ xhigh = xlow;
+ yhigh = ylow;
+ xlow = *(grid + j);
+ ylow = Chebps(xlow, coef, NC, pOverflow);
+
+ if (((Word32)ylow*yhigh) <= 0)
+ {
+ /* divide 4 times the interval */
+ for (i = 4; i != 0; i--)
+ {
+ /* xmid = (xlow + xhigh)/2 */
+ x = xlow >> 1;
+ y = xhigh >> 1;
+ xmid = x + y;
+
+ ymid = Chebps(xmid, coef, NC, pOverflow);
+
+ if (((Word32)ylow*ymid) <= 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 <<= exp;
+ y = div_s((Word16) 16383, y);
+
+ y = ((Word32)x * y) >> (19 - exp);
+
+ if (sign < 0)
+ {
+ y = -y;
+ }
+
+ /* xint = xlow - ylow*y */
+ xint = xlow - (((Word32) ylow * y) >> 10);
+ }
+
+ *(lsp + nf) = xint;
+ xlow = xint;
+ nf++;
+
+ if (ip == 0)
+ {
+ ip = 1;
+ coef = f2;
+ }
+ else
+ {
+ ip = 0;
+ coef = f1;
+ }
+
+ ylow = Chebps(xlow, coef, NC, pOverflow);
+
+ }
+ }
+
+ /* Check if M roots found */
+
+ if (nf < M)
+ {
+ for (i = NC; i != 0 ; i--)
+ {
+ *lsp++ = *old_lsp++;
+ *lsp++ = *old_lsp++;
+ }
+ }
+
+}
+
+Word16 Chebps_Wrapper(Word16 x,
+ Word16 f[], /* (n) */
+ Word16 n,
+ Flag *pOverflow)
+{
+ return Chebps(x, f, n, pOverflow);
+}
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/bitno_tab.cpp b/media/libstagefright/codecs/amrnb/common/src/bitno_tab.cpp
new file mode 100644
index 0000000..4ee04a5
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/bitno_tab.cpp
@@ -0,0 +1,309 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: .audio/gsm-amr/c/src/bitno_tab.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Define "const Word16 *bitno[N_MODES]" as "const Word16 *const
+ bitno[N_MODES]"
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ File : bitno.tab
+ Purpose : Tables for bit2prm and prm2bit
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h" /* parameter sizes: MAX_PRM_SIZE */
+#include "mode.h" /* N_MODES */
+#include "bitno_tab.h"
+
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+ /* number of parameters per modes (values must be <= MAX_PRM_SIZE!) */
+ const Word16 prmno[N_MODES] =
+ {
+ PRMNO_MR475,
+ PRMNO_MR515,
+ PRMNO_MR59,
+ PRMNO_MR67,
+ PRMNO_MR74,
+ PRMNO_MR795,
+ PRMNO_MR102,
+ PRMNO_MR122,
+ PRMNO_MRDTX
+ };
+
+ /* number of parameters to first subframe per modes */
+ const Word16 prmnofsf[N_MODES - 1] =
+ {
+ PRMNOFSF_MR475,
+ PRMNOFSF_MR515,
+ PRMNOFSF_MR59,
+ PRMNOFSF_MR67,
+ PRMNOFSF_MR74,
+ PRMNOFSF_MR795,
+ PRMNOFSF_MR102,
+ PRMNOFSF_MR122
+ };
+
+ /* parameter sizes (# of bits), one table per mode */
+ const Word16 bitno_MR475[PRMNO_MR475] =
+ {
+ 8, 8, 7, /* LSP VQ */
+ 8, 7, 2, 8, /* first subframe */
+ 4, 7, 2, /* second subframe */
+ 4, 7, 2, 8, /* third subframe */
+ 4, 7, 2, /* fourth subframe */
+ };
+
+ const Word16 bitno_MR515[PRMNO_MR515] =
+ {
+ 8, 8, 7, /* LSP VQ */
+ 8, 7, 2, 6, /* first subframe */
+ 4, 7, 2, 6, /* second subframe */
+ 4, 7, 2, 6, /* third subframe */
+ 4, 7, 2, 6, /* fourth subframe */
+ };
+
+ const Word16 bitno_MR59[PRMNO_MR59] =
+ {
+ 8, 9, 9, /* LSP VQ */
+ 8, 9, 2, 6, /* first subframe */
+ 4, 9, 2, 6, /* second subframe */
+ 8, 9, 2, 6, /* third subframe */
+ 4, 9, 2, 6, /* fourth subframe */
+ };
+
+ const Word16 bitno_MR67[PRMNO_MR67] =
+ {
+ 8, 9, 9, /* LSP VQ */
+ 8, 11, 3, 7, /* first subframe */
+ 4, 11, 3, 7, /* second subframe */
+ 8, 11, 3, 7, /* third subframe */
+ 4, 11, 3, 7, /* fourth subframe */
+ };
+
+ const Word16 bitno_MR74[PRMNO_MR74] =
+ {
+ 8, 9, 9, /* LSP VQ */
+ 8, 13, 4, 7, /* first subframe */
+ 5, 13, 4, 7, /* second subframe */
+ 8, 13, 4, 7, /* third subframe */
+ 5, 13, 4, 7, /* fourth subframe */
+ };
+
+ const Word16 bitno_MR795[PRMNO_MR795] =
+ {
+ 9, 9, 9, /* LSP VQ */
+ 8, 13, 4, 4, 5, /* first subframe */
+ 6, 13, 4, 4, 5, /* second subframe */
+ 8, 13, 4, 4, 5, /* third subframe */
+ 6, 13, 4, 4, 5, /* fourth subframe */
+ };
+
+ const Word16 bitno_MR102[PRMNO_MR102] =
+ {
+ 8, 9, 9, /* LSP VQ */
+ 8, 1, 1, 1, 1, 10, 10, 7, 7, /* first subframe */
+ 5, 1, 1, 1, 1, 10, 10, 7, 7, /* second subframe */
+ 8, 1, 1, 1, 1, 10, 10, 7, 7, /* third subframe */
+ 5, 1, 1, 1, 1, 10, 10, 7, 7, /* fourth subframe */
+ };
+
+ const Word16 bitno_MR122[PRMNO_MR122] =
+ {
+ 7, 8, 9, 8, 6, /* LSP VQ */
+ 9, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5, /* first subframe */
+ 6, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5, /* second subframe */
+ 9, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5, /* third subframe */
+ 6, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 5 /* fourth subframe */
+ };
+
+ const Word16 bitno_MRDTX[PRMNO_MRDTX] =
+ {
+ 3,
+ 8, 9, 9,
+ 6
+ };
+
+ /* overall table with all parameter sizes for all modes */
+ const Word16 * const bitno[N_MODES] =
+ {
+ bitno_MR475,
+ bitno_MR515,
+ bitno_MR59,
+ bitno_MR67,
+ bitno_MR74,
+ bitno_MR795,
+ bitno_MR102,
+ bitno_MR122,
+ bitno_MRDTX
+ };
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL FUNCTION REFERENCES
+ ; Declare functions defined elsewhere and referenced in this module
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; Define all local variables
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Function body here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Return nothing or data or data pointer
+----------------------------------------------------------------------------*/
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/bitreorder_tab.cpp b/media/libstagefright/codecs/amrnb/common/src/bitreorder_tab.cpp
new file mode 100644
index 0000000..e284bbc
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/bitreorder_tab.cpp
@@ -0,0 +1,422 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: .audio/gsm-amr/c/src/bitreorder.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed file name to bitreorder_tab.c and .h. Also, updated the
+ module description.
+
+ Description: Define "const Word16 *reorderBits[NUM_MODES-1]" as
+ "const Word16 *const reorderBits[NUM_MODES-1]".
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition. Removed corresponding header file from Include
+ section.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function contains tables needed to reformat the encoded speech bits
+ into IF2, WMF, and ETS.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ AMR Speech Codec Frame Structure,
+ 3GPP TS 26.101 version 4.1.0 Release 4, June 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "bitreorder_tab.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+#define NUM_MODES 16
+#define NUMBIT_MR475 95
+#define NUMBIT_MR515 103
+#define NUMBIT_MR59 118
+#define NUMBIT_MR67 134
+#define NUMBIT_MR74 148
+#define NUMBIT_MR795 159
+#define NUMBIT_MR102 204
+#define NUMBIT_MR122 244
+#define NUMBIT_AMR_SID 39
+#define NUMBIT_GSMEFR_SID 43
+#define NUMBIT_TDMAEFR_SID 38
+#define NUMBIT_PDCEFR_SID 37
+#define NUMBIT_UNUSED1 0
+#define NUMBIT_UNUSED2 0
+#define NUMBIT_UNUSED3 0
+#define NUMBIT_NO_DATA 0
+
+#define MAX_NUM_BITS 244
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+ /* number of parameters per modes (values must be <= MAX_PRM_SIZE!) */
+ const Word16 numOfBits[NUM_MODES] =
+ {
+ NUMBIT_MR475,
+ NUMBIT_MR515,
+ NUMBIT_MR59,
+ NUMBIT_MR67,
+ NUMBIT_MR74,
+ NUMBIT_MR795,
+ NUMBIT_MR102,
+ NUMBIT_MR122,
+ NUMBIT_AMR_SID,
+ NUMBIT_GSMEFR_SID,
+ NUMBIT_TDMAEFR_SID,
+ NUMBIT_PDCEFR_SID,
+ NUMBIT_UNUSED1,
+ NUMBIT_UNUSED2,
+ NUMBIT_UNUSED3,
+ NUMBIT_NO_DATA
+ };
+
+ const Word16 reorderBits_MR475[NUMBIT_MR475] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 23, 24, 25, 26,
+ 27, 28, 48, 49, 61, 62, 82, 83, 47, 46,
+ 45, 44, 81, 80, 79, 78, 17, 18, 20, 22,
+ 77, 76, 75, 74, 29, 30, 43, 42, 41, 40,
+ 38, 39, 16, 19, 21, 50, 51, 59, 60, 63,
+ 64, 72, 73, 84, 85, 93, 94, 32, 33, 35,
+ 36, 53, 54, 56, 57, 66, 67, 69, 70, 87,
+ 88, 90, 91, 34, 55, 68, 89, 37, 58, 71,
+ 92, 31, 52, 65, 86
+ };
+
+ const Word16 reorderBits_MR515[NUMBIT_MR515] =
+ {
+ 7, 6, 5, 4, 3, 2, 1, 0, 15, 14,
+ 13, 12, 11, 10, 9, 8, 23, 24, 25, 26,
+ 27, 46, 65, 84, 45, 44, 43, 64, 63, 62,
+ 83, 82, 81, 102, 101, 100, 42, 61, 80, 99,
+ 28, 47, 66, 85, 18, 41, 60, 79, 98, 29,
+ 48, 67, 17, 20, 22, 40, 59, 78, 97, 21,
+ 30, 49, 68, 86, 19, 16, 87, 39, 38, 58,
+ 57, 77, 35, 54, 73, 92, 76, 96, 95, 36,
+ 55, 74, 93, 32, 51, 33, 52, 70, 71, 89,
+ 90, 31, 50, 69, 88, 37, 56, 75, 94, 34,
+ 53, 72, 91
+ };
+
+ const Word16 reorderBits_MR59[NUMBIT_MR59] =
+ {
+ 0, 1, 4, 5, 3, 6, 7, 2, 13, 15,
+ 8, 9, 11, 12, 14, 10, 16, 28, 74, 29,
+ 75, 27, 73, 26, 72, 30, 76, 51, 97, 50,
+ 71, 96, 117, 31, 77, 52, 98, 49, 70, 95,
+ 116, 53, 99, 32, 78, 33, 79, 48, 69, 94,
+ 115, 47, 68, 93, 114, 46, 67, 92, 113, 19,
+ 21, 23, 22, 18, 17, 20, 24, 111, 43, 89,
+ 110, 64, 65, 44, 90, 25, 45, 66, 91, 112,
+ 54, 100, 40, 61, 86, 107, 39, 60, 85, 106,
+ 36, 57, 82, 103, 35, 56, 81, 102, 34, 55,
+ 80, 101, 42, 63, 88, 109, 41, 62, 87, 108,
+ 38, 59, 84, 105, 37, 58, 83, 104
+ };
+
+ const Word16 reorderBits_MR67[NUMBIT_MR67] =
+ {
+ 0, 1, 4, 3, 5, 6, 13, 7, 2, 8,
+ 9, 11, 15, 12, 14, 10, 28, 82, 29, 83,
+ 27, 81, 26, 80, 30, 84, 16, 55, 109, 56,
+ 110, 31, 85, 57, 111, 48, 73, 102, 127, 32,
+ 86, 51, 76, 105, 130, 52, 77, 106, 131, 58,
+ 112, 33, 87, 19, 23, 53, 78, 107, 132, 21,
+ 22, 18, 17, 20, 24, 25, 50, 75, 104, 129,
+ 47, 72, 101, 126, 54, 79, 108, 133, 46, 71,
+ 100, 125, 128, 103, 74, 49, 45, 70, 99, 124,
+ 42, 67, 96, 121, 39, 64, 93, 118, 38, 63,
+ 92, 117, 35, 60, 89, 114, 34, 59, 88, 113,
+ 44, 69, 98, 123, 43, 68, 97, 122, 41, 66,
+ 95, 120, 40, 65, 94, 119, 37, 62, 91, 116,
+ 36, 61, 90, 115
+ };
+
+ const Word16 reorderBits_MR74[NUMBIT_MR74] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 26, 87, 27,
+ 88, 28, 89, 29, 90, 30, 91, 51, 80, 112,
+ 141, 52, 81, 113, 142, 54, 83, 115, 144, 55,
+ 84, 116, 145, 58, 119, 59, 120, 21, 22, 23,
+ 17, 18, 19, 31, 60, 92, 121, 56, 85, 117,
+ 146, 20, 24, 25, 50, 79, 111, 140, 57, 86,
+ 118, 147, 49, 78, 110, 139, 48, 77, 53, 82,
+ 114, 143, 109, 138, 47, 76, 108, 137, 32, 33,
+ 61, 62, 93, 94, 122, 123, 41, 42, 43, 44,
+ 45, 46, 70, 71, 72, 73, 74, 75, 102, 103,
+ 104, 105, 106, 107, 131, 132, 133, 134, 135, 136,
+ 34, 63, 95, 124, 35, 64, 96, 125, 36, 65,
+ 97, 126, 37, 66, 98, 127, 38, 67, 99, 128,
+ 39, 68, 100, 129, 40, 69, 101, 130
+ };
+
+ const Word16 reorderBits_MR795[NUMBIT_MR795] =
+ {
+ 8, 7, 6, 5, 4, 3, 2, 14, 16, 9,
+ 10, 12, 13, 15, 11, 17, 20, 22, 24, 23,
+ 19, 18, 21, 56, 88, 122, 154, 57, 89, 123,
+ 155, 58, 90, 124, 156, 52, 84, 118, 150, 53,
+ 85, 119, 151, 27, 93, 28, 94, 29, 95, 30,
+ 96, 31, 97, 61, 127, 62, 128, 63, 129, 59,
+ 91, 125, 157, 32, 98, 64, 130, 1, 0, 25,
+ 26, 33, 99, 34, 100, 65, 131, 66, 132, 54,
+ 86, 120, 152, 60, 92, 126, 158, 55, 87, 121,
+ 153, 117, 116, 115, 46, 78, 112, 144, 43, 75,
+ 109, 141, 40, 72, 106, 138, 36, 68, 102, 134,
+ 114, 149, 148, 147, 146, 83, 82, 81, 80, 51,
+ 50, 49, 48, 47, 45, 44, 42, 39, 35, 79,
+ 77, 76, 74, 71, 67, 113, 111, 110, 108, 105,
+ 101, 145, 143, 142, 140, 137, 133, 41, 73, 107,
+ 139, 37, 69, 103, 135, 38, 70, 104, 136
+ };
+
+ const Word16 reorderBits_MR102[NUMBIT_MR102] =
+ {
+ 7, 6, 5, 4, 3, 2, 1, 0, 16, 15,
+ 14, 13, 12, 11, 10, 9, 8, 26, 27, 28,
+ 29, 30, 31, 115, 116, 117, 118, 119, 120, 72,
+ 73, 161, 162, 65, 68, 69, 108, 111, 112, 154,
+ 157, 158, 197, 200, 201, 32, 33, 121, 122, 74,
+ 75, 163, 164, 66, 109, 155, 198, 19, 23, 21,
+ 22, 18, 17, 20, 24, 25, 37, 36, 35, 34,
+ 80, 79, 78, 77, 126, 125, 124, 123, 169, 168,
+ 167, 166, 70, 67, 71, 113, 110, 114, 159, 156,
+ 160, 202, 199, 203, 76, 165, 81, 82, 92, 91,
+ 93, 83, 95, 85, 84, 94, 101, 102, 96, 104,
+ 86, 103, 87, 97, 127, 128, 138, 137, 139, 129,
+ 141, 131, 130, 140, 147, 148, 142, 150, 132, 149,
+ 133, 143, 170, 171, 181, 180, 182, 172, 184, 174,
+ 173, 183, 190, 191, 185, 193, 175, 192, 176, 186,
+ 38, 39, 49, 48, 50, 40, 52, 42, 41, 51,
+ 58, 59, 53, 61, 43, 60, 44, 54, 194, 179,
+ 189, 196, 177, 195, 178, 187, 188, 151, 136, 146,
+ 153, 134, 152, 135, 144, 145, 105, 90, 100, 107,
+ 88, 106, 89, 98, 99, 62, 47, 57, 64, 45,
+ 63, 46, 55, 56
+ };
+
+ const Word16 reorderBits_MR122[NUMBIT_MR122] =
+ {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 23, 15, 16, 17, 18,
+ 19, 20, 21, 22, 24, 25, 26, 27, 28, 38,
+ 141, 39, 142, 40, 143, 41, 144, 42, 145, 43,
+ 146, 44, 147, 45, 148, 46, 149, 47, 97, 150,
+ 200, 48, 98, 151, 201, 49, 99, 152, 202, 86,
+ 136, 189, 239, 87, 137, 190, 240, 88, 138, 191,
+ 241, 91, 194, 92, 195, 93, 196, 94, 197, 95,
+ 198, 29, 30, 31, 32, 33, 34, 35, 50, 100,
+ 153, 203, 89, 139, 192, 242, 51, 101, 154, 204,
+ 55, 105, 158, 208, 90, 140, 193, 243, 59, 109,
+ 162, 212, 63, 113, 166, 216, 67, 117, 170, 220,
+ 36, 37, 54, 53, 52, 58, 57, 56, 62, 61,
+ 60, 66, 65, 64, 70, 69, 68, 104, 103, 102,
+ 108, 107, 106, 112, 111, 110, 116, 115, 114, 120,
+ 119, 118, 157, 156, 155, 161, 160, 159, 165, 164,
+ 163, 169, 168, 167, 173, 172, 171, 207, 206, 205,
+ 211, 210, 209, 215, 214, 213, 219, 218, 217, 223,
+ 222, 221, 73, 72, 71, 76, 75, 74, 79, 78,
+ 77, 82, 81, 80, 85, 84, 83, 123, 122, 121,
+ 126, 125, 124, 129, 128, 127, 132, 131, 130, 135,
+ 134, 133, 176, 175, 174, 179, 178, 177, 182, 181,
+ 180, 185, 184, 183, 188, 187, 186, 226, 225, 224,
+ 229, 228, 227, 232, 231, 230, 235, 234, 233, 238,
+ 237, 236, 96, 199
+ };
+
+ /* overall table with all parameter sizes for all modes */
+ const Word16 * const reorderBits[NUM_MODES-1] =
+ {
+ reorderBits_MR475,
+ reorderBits_MR515,
+ reorderBits_MR59,
+ reorderBits_MR67,
+ reorderBits_MR74,
+ reorderBits_MR795,
+ reorderBits_MR102,
+ reorderBits_MR122
+ };
+
+ /* Number of Frames (16-bit segments sent for each mode */
+ const Word16 numCompressedBytes[16] =
+ {
+ 13, /*4.75*/
+ 14, /*5.15*/
+ 16, /*5.90*/
+ 18, /*6.70*/
+ 19, /*7.40*/
+ 21, /*7.95*/
+ 26, /*10.2*/
+ 31, /*12.2*/
+ 6, /*GsmAmr comfort noise*/
+ 6, /*Gsm-Efr comfort noise*/
+ 6, /*IS-641 comfort noise*/
+ 6, /*Pdc-Efr comfort noise*/
+ 0, /*future use*/
+ 0, /*future use*/
+ 0, /*future use*/
+ 1 /*No transmission*/
+ };
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL FUNCTION REFERENCES
+ ; Declare functions defined elsewhere and referenced in this module
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; Define all local variables
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Function body here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Return nothing or data or data pointer
+----------------------------------------------------------------------------*/
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/bits2prm.cpp b/media/libstagefright/codecs/amrnb/common/src/bits2prm.cpp
new file mode 100644
index 0000000..1d6f7b1
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/bits2prm.cpp
@@ -0,0 +1,292 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/bits2prm.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Fixed a typo in the include section. Optimized some lines of
+ code as per review comments.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "bits2prm.h"
+#include "typedef.h"
+#include "mode.h"
+#include "bitno_tab.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Bin2int
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ no_of_bits = number of bits associated with value
+ bitstream = pointer to buffer where bits are read
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function : Bin2int
+ Purpose : Read "no_of_bits" bits from the array bitstream[]
+ and convert to integer.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ bits2prm.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+static Word16 Bin2int ( // Reconstructed parameter
+ Word16 no_of_bits, // input : number of bits associated with value
+ Word16 *bitstream // output: address where bits are written
+)
+{
+ Word16 value, i, bit;
+
+ value = 0;
+ for (i = 0; i < no_of_bits; i++)
+ {
+ value = shl (value, 1);
+ bit = *bitstream++;
+ if (sub (bit, BIT_1) == 0)
+ value = add (value, 1);
+ }
+ return (value);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+static Word16 Bin2int( /* Reconstructed parameter */
+ Word16 no_of_bits, /* input : number of bits associated with value */
+ Word16 *bitstream /* input: address where bits are read from */
+)
+{
+ Word16 value;
+ Word16 i;
+ Word16 single_bit;
+
+ value = 0;
+ for (i = 0; i < no_of_bits; i++)
+ {
+ value <<= 1;
+ single_bit = *(bitstream++);
+ value |= single_bit;
+ }
+ return (value);
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: bits2prm
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ mode = AMR mode of type enum Mode
+ bits[] = pointer to serial bits of type Word16
+ prm[] = pointer to analysis parameters of type Word16
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function : Bits2prm
+ Purpose : Retrieves the vector of encoder parameters from
+ the received serial bits in a frame.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ bits2prm.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Bits2prm (
+ enum Mode mode, // i : AMR mode
+ Word16 bits[], // i : serial bits (size <= MAX_SERIAL_SIZE)
+ Word16 prm[] // o : analysis parameters (size <= MAX_PRM_SIZE)
+)
+{
+ Word16 i;
+
+ for (i = 0; i < prmno[mode]; i++)
+ {
+ prm[i] = Bin2int (bitno[mode][i], bits);
+ bits += bitno[mode][i];
+ add(0,0); // account for above pointer update
+ }
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+OSCL_EXPORT_REF void Bits2prm(
+ enum Mode mode, /* i : AMR mode */
+ Word16 bits[], /* i : serial bits (size <= MAX_SERIAL_SIZE) */
+ Word16 prm[] /* o : analysis parameters (size <= MAX_PRM_SIZE) */
+)
+{
+ Word16 i;
+
+ for (i = 0; i < prmno[mode]; i++)
+ {
+ prm[i] = Bin2int(bitno[mode][i], bits);
+ bits += bitno[mode][i];
+ }
+
+ return;
+}
+
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/bytesused.cpp b/media/libstagefright/codecs/amrnb/common/src/bytesused.cpp
new file mode 100644
index 0000000..b61bac4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/bytesused.cpp
@@ -0,0 +1,208 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./audio/gsm-amr/c/src/BytesUsed.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Corrected entries for all SID frames and updated function
+ description. Updated copyright year.
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition. Removed corresponding header file from Include
+ section.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function creates a table called BytesUsed that holds the value that
+ describes the number of bytes required to hold one frame worth of data in
+ the WMF (non-IF2) frame format. Each table entry is the sum of the frame
+ type byte and the number of bytes used up by the core speech data for each
+ 3GPP frame type.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] "AMR Speech Codec Frame Structure", 3GPP TS 26.101 version 4.1.0
+ Release 4, June 2001, page 13.
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+ const short BytesUsed[16] =
+ {
+ 13, /* 4.75 */
+ 14, /* 5.15 */
+ 16, /* 5.90 */
+ 18, /* 6.70 */
+ 20, /* 7.40 */
+ 21, /* 7.95 */
+ 27, /* 10.2 */
+ 32, /* 12.2 */
+ 6, /* GsmAmr comfort noise */
+ 7, /* Gsm-Efr comfort noise */
+ 6, /* IS-641 comfort noise */
+ 6, /* Pdc-Efr comfort noise */
+ 0, /* future use */
+ 0, /* future use */
+ 0, /* future use */
+ 1 /* No transmission */
+ };
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL FUNCTION REFERENCES
+ ; Declare functions defined elsewhere and referenced in this module
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; Define all local variables
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Function body here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Return nothing or data or data pointer
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/c2_9pf_tab.cpp b/media/libstagefright/codecs/amrnb/common/src/c2_9pf_tab.cpp
new file mode 100644
index 0000000..20de9d6
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/c2_9pf_tab.cpp
@@ -0,0 +1,166 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/c2_9pf_tab.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ (1) Corrected the module description
+ (2) Corrected the filename in the template.
+ (3) Removed embedded tabs.
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the declaration for startPos[] used by the functions
+ c2_9pf.c and d2_9pf.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+ extern const Word16 startPos[];
+ const Word16 startPos[2*4*2] = {0, 2, 0, 3,
+ 0, 2, 0, 3,
+ 1, 3, 2, 4,
+ 1, 4, 1, 4
+ };
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c2_9pf.c UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
diff --git a/media/libstagefright/codecs/amrnb/common/src/copy.cpp b/media/libstagefright/codecs/amrnb/common/src/copy.cpp
new file mode 100644
index 0000000..75890b2
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/copy.cpp
@@ -0,0 +1,87 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+* File : copy.h
+*
+********************************************************************************
+*/
+
+/*
+********************************************************************************
+* MODULE INCLUDE FILE AND VERSION ID
+********************************************************************************
+*/
+#include "copy.h"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include <string.h>
+
+#include "typedef.h"
+#include "basic_op.h"
+
+/*
+********************************************************************************
+* PUBLIC PROGRAM CODE
+********************************************************************************
+*/
+/*************************************************************************
+ *
+ * FUNCTION: Copy
+ *
+ * PURPOSE: Copy vector x[] to y[]
+ *
+ *
+ *************************************************************************/
+/*
+**************************************************************************
+*
+* Function : Copy
+* Purpose : Copy vector x[] to y[]
+*
+**************************************************************************
+*/
+void Copy(
+ const Word16 x[], /* i : input vector (L) */
+ Word16 y[], /* o : output vector (L) */
+ Word16 L /* i : vector length */
+)
+{
+ memmove(y, x, L*sizeof(*x));
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/div_32.cpp b/media/libstagefright/codecs/amrnb/common/src/div_32.cpp
new file mode 100644
index 0000000..143e37c
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/div_32.cpp
@@ -0,0 +1,209 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/div_32.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template. Changed function interface to pass in a
+ pointer to overflow flag into the function instead of using a
+ global flag. Removed inclusion of unwanted header files. Changed
+ the name of input and output variables for clarity.
+
+ Description:
+ 1. Eliminated unused include files.
+ 2. Replaced l_extract functionality, code size and speed
+ do not justify calling this function
+ 3. Eliminated sub() function call, replace by (-), this knowing
+ that the result will not saturate.
+
+ Description: Added casting to eliminate warnings
+
+ Who: Date:
+ Description:
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: div_32
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_num = 32 bit signed integer (Word32) whose value falls in the
+ range : 0x0000 0000 < L_num < L_denom
+ L_denom_hi = 16 bit positive normalized integer whose value falls in
+ the range : 0x4000 < hi < 0x7fff
+ L_denom_lo = 16 bit positive integer whose value falls in the range :
+ 0 < lo < 0x7fff
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit divide operation resulted in overflow
+
+ Returns:
+ result = 32-bit quotient of of the division of two 32 bit integers
+ L_num / L_denom (Word32)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function is a fractional integer division of two 32 bit numbers, the
+ numerator L_num and the denominator L_denom. The denominator is formed by
+ combining denom_hi and denom_lo. Note that denom_hi is a normalized numbers.
+ The numerator and denominator must be positive and the numerator must be
+ less than the denominator.
+
+ The division is done as follows:
+ 1. Find 1/L_denom by first approximating: approx = 1 / denom_hi.
+ 2. 1/L_denom = approx * (2.0 - L_denom * approx ).
+ 3. result = L_num * (1/L_denom).
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] div_32() function in oper_32b.c, UMTS GSM AMR speech codec, R99 -
+ Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word32 Div_32(Word32 L_num,
+ Word16 L_denom_hi,
+ Word16 L_denom_lo,
+ Flag *pOverflow)
+{
+
+ Word16 approx;
+ Word16 hi;
+ Word16 lo;
+ Word16 n_hi;
+ Word16 n_lo;
+ Word32 result;
+
+ /* First approximation: 1 / L_denom = 1/L_denom_hi */
+
+ approx = div_s((Word16) 0x3fff, L_denom_hi);
+
+ /* 1/L_denom = approx * (2.0 - L_denom * approx) */
+
+ result = Mpy_32_16(L_denom_hi, L_denom_lo, approx, pOverflow);
+ /* result is > 0 , and less than 1.0 */
+ result = 0x7fffffffL - result;
+
+ hi = (Word16)(result >> 16);
+ lo = (result >> 1) - (hi << 15);
+
+ result = Mpy_32_16(hi, lo, approx, pOverflow);
+
+ /* L_num * (1/L_denom) */
+
+ hi = (Word16)(result >> 16);
+ lo = (result >> 1) - (hi << 15);
+
+ n_hi = (Word16)(L_num >> 16);
+ n_lo = (L_num >> 1) - (n_hi << 15);
+
+ result = Mpy_32(n_hi, n_lo, hi, lo, pOverflow);
+ result = L_shl(result, 2, pOverflow);
+
+ return (result);
+}
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/div_s.cpp b/media/libstagefright/codecs/amrnb/common/src/div_s.cpp
new file mode 100644
index 0000000..f3bed7e
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/div_s.cpp
@@ -0,0 +1,277 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./gsm-amr/c/src/div_s.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the div_s function. Sync'ed up
+ with the current template and fixed tabs.
+
+ Description: Making changes based on review meeting.
+
+ Description: Made changes based on P3 review meeting.
+
+ Description: Changing abort() to exit(0).
+
+ Description: Made the following changes
+ 1. Unrolled the division loop to make three comparison per
+ pass, using only five iterations of the loop and saving
+ shifts cycles
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ var1 = 16 bit signed integer (Word16) whose value falls in
+ the range : 0x0000 <= var1 <= 0x7fff.
+ var2 = 16 bit signed integer (Word16) whose value falls in
+ the range : 0x0000 <= var1 <= 0x7fff.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ var_out = quotient of var1 divided by var2 (Word16)
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function 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.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] basicop2.c, ETS Version 2.0.0, February 8, 1999
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 div_s (Word16 var1, Word16 var2)
+{
+ Word16 var_out = 0;
+ Word16 iteration;
+ Word32 L_num;
+ Word32 L_denom;
+ Word16 abort_flag = 0;
+
+ if ((var1 > var2) || (var1 < 0))
+ {
+ printf ("Division Error var1=%d var2=%d\n", var1, var2);
+ abort_flag = 1;
+ exit(0);
+ }
+ if ((var1 != 0) && (abort_flag == 0))
+ {
+ if (var1 == var2)
+ {
+ var_out = MAX_16;
+ }
+ else
+ {
+ L_num = (Word32) var1;
+ L_denom = (Word32) var2;
+
+ for (iteration = 15; iteration > 0; iteration--)
+ {
+ var_out <<= 1;
+ L_num <<= 1;
+
+ if (L_num >= L_denom)
+ {
+ L_num -= L_denom;
+ var_out += 1;
+ }
+ }
+ }
+ }
+
+#if (WMOPS)
+ multiCounter[currCounter].div_s++;
+#endif
+ return (var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word16 div_s(register Word16 var1, register Word16 var2)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ Word16 var_out = 0;
+ register Word16 iteration;
+ Word32 L_num;
+ Word32 L_denom;
+ Word32 L_denom_by_2;
+ Word32 L_denom_by_4;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ if ((var1 > var2) || (var1 < 0))
+ {
+ return 0; // used to exit(0);
+ }
+ if (var1)
+ {
+ if (var1 != var2)
+ {
+
+ L_num = (Word32) var1;
+ L_denom = (Word32) var2;
+ L_denom_by_2 = (L_denom << 1);
+ L_denom_by_4 = (L_denom << 2);
+ for (iteration = 5; iteration > 0; iteration--)
+ {
+ var_out <<= 3;
+ L_num <<= 3;
+
+ if (L_num >= L_denom_by_4)
+ {
+ L_num -= L_denom_by_4;
+ var_out |= 4;
+ }
+
+ if (L_num >= L_denom_by_2)
+ {
+ L_num -= L_denom_by_2;
+ var_out |= 2;
+ }
+
+ if (L_num >= (L_denom))
+ {
+ L_num -= (L_denom);
+ var_out |= 1;
+ }
+
+ }
+ }
+ else
+ {
+ var_out = MAX_16;
+ }
+ }
+
+#if (WMOPS)
+ multiCounter[currCounter].div_s++;
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return (var_out);
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/extract_h.cpp b/media/libstagefright/codecs/amrnb/common/src/extract_h.cpp
new file mode 100644
index 0000000..e538f9f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/extract_h.cpp
@@ -0,0 +1,177 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/src/extract_h.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the extract_h function. Sync'ed up
+ with the current template and fixed tabs.
+
+ Description: Removed conditional code that updates WMOPS counter
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 32 bit long signed integer (Word32 ) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ L_var1 = Most significant word of input (Word16)
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function returns the 16 MSB of the input, L_var1.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] basicop2.c, ETS Version 2.0.0, February 8, 1999
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 extract_h (Word32 L_var1)
+{
+ Word16 var_out;
+
+ var_out = (Word16) (L_var1 >> 16);
+#if (WMOPS)
+ multiCounter[currCounter].extract_h++;
+#endif
+ return (var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word16 extract_h(Word32 L_var1)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return ((Word16)(L_var1 >> 16));
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/extract_l.cpp b/media/libstagefright/codecs/amrnb/common/src/extract_l.cpp
new file mode 100644
index 0000000..dbb9a6e
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/extract_l.cpp
@@ -0,0 +1,176 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./gsm-amr/c/src/extract_l.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the extract_l function. Sync'ed up
+ with the current template and fixed tabs.
+
+ Description: Removed conditional code that updates WMOPS counter
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 32 bit long signed integer (Word32 ) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ L_var1 = Most significant word of input (Word16)
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function returns the 16 LSB of the input, L_var1.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] basicop2.c, ETS Version 2.0.0, February 8, 1999
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 extract_l (Word32 L_var1)
+{
+ Word16 var_out;
+
+ var_out = (Word16) L_var1;
+#if (WMOPS)
+ multiCounter[currCounter].extract_l++;
+#endif
+ return (var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word16 extract_l(Word32 L_var1)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return ((Word16) L_var1);
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/gains_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/gains_tbl.cpp
new file mode 100644
index 0000000..a7cd6fb
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/gains_tbl.cpp
@@ -0,0 +1,219 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/gains_tbl.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created this file from the reference, gains.tab
+
+ Description: Added include of "typedef.h" to includes section.
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+#define NB_QUA_PITCH 16
+#define NB_QUA_CODE 32
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+
+
+ extern const Word16 qua_gain_pitch[];
+ const Word16 qua_gain_pitch[NB_QUA_PITCH] =
+ {
+ 0, 3277, 6556, 8192, 9830, 11469, 12288, 13107,
+ 13926, 14746, 15565, 16384, 17203, 18022, 18842, 19661
+ };
+
+
+ extern const Word16 qua_gain_code[];
+ const Word16 qua_gain_code[(NB_QUA_CODE+1)*3] =
+ {
+ /* gain factor (g_fac) and quantized energy error (qua_ener_MR122, qua_ener)
+ * are stored:
+ *
+ * qua_ener_MR122 = log2(g_fac) (not the rounded floating point value, but
+ * the value the original EFR algorithm
+ * calculates from g_fac [using Log2])
+ * qua_ener = 20*log10(g_fac); (rounded floating point value)
+ *
+ *
+ * g_fac (Q11), qua_ener_MR122 (Q10), qua_ener (Q10)
+ */
+ 159, -3776, -22731,
+ 206, -3394, -20428,
+ 268, -3005, -18088,
+ 349, -2615, -15739,
+ 419, -2345, -14113,
+ 482, -2138, -12867,
+ 554, -1932, -11629,
+ 637, -1726, -10387,
+ 733, -1518, -9139,
+ 842, -1314, -7906,
+ 969, -1106, -6656,
+ 1114, -900, -5416,
+ 1281, -694, -4173,
+ 1473, -487, -2931,
+ 1694, -281, -1688,
+ 1948, -75, -445,
+ 2241, 133, 801,
+ 2577, 339, 2044,
+ 2963, 545, 3285,
+ 3408, 752, 4530,
+ 3919, 958, 5772,
+ 4507, 1165, 7016,
+ 5183, 1371, 8259,
+ 5960, 1577, 9501,
+ 6855, 1784, 10745,
+ 7883, 1991, 11988,
+ 9065, 2197, 13231,
+ 10425, 2404, 14474,
+ 12510, 2673, 16096,
+ 16263, 3060, 18429,
+ 21142, 3448, 20763,
+ 27485, 3836, 23097,
+ 27485, 3836, 23097
+ };
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] gains.tab, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/gc_pred.cpp b/media/libstagefright/codecs/amrnb/common/src/gc_pred.cpp
new file mode 100644
index 0000000..3650f3c
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/gc_pred.cpp
@@ -0,0 +1,1046 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./audio/gsm-amr/c/src/gc_pred.c
+ Functions:
+ gc_pred_reset
+ gc_pred
+ gc_pred_update
+ gc_pred_average_limited
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the functions that perform codebook gain MA prediction.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "gc_pred.h"
+#include "basicop_malloc.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "log2.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define NPRED 4 /* number of prediction taps */
+
+/* average innovation energy. */
+/* MEAN_ENER = 36.0/constant, constant = 20*Log10(2) */
+#define MEAN_ENER_MR122 783741L /* 36/(20*log10(2)) (Q17) */
+
+/* minimum quantized energy: -14 dB */
+#define MIN_ENERGY -14336 /* 14 Q10 */
+#define MIN_ENERGY_MR122 -2381 /* 14 / (20*log10(2)) Q10 */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/* MA prediction coefficients (Q13) */
+static const Word16 pred[NPRED] = {5571, 4751, 2785, 1556};
+
+/* MA prediction coefficients (Q6) */
+static const Word16 pred_MR122[NPRED] = {44, 37, 22, 12};
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: gc_pred_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a structure of type gc_predState
+
+ Outputs:
+ past_qua_en field in the structure pointed to by state is initialized
+ to MIN_ENERGY
+ past_qua_en_MR122 field in the structure pointed to by state is
+ initialized to MIN_ENERGY_MR122
+
+ Returns:
+ return_value = 0, if reset was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function initializes the state memory used by gc_pred to zero.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ gc_pred.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int gc_pred_reset (gc_predState *state)
+{
+ Word16 i;
+
+ if (state == (gc_predState *) NULL){
+ fprintf(stderr, "gc_pred_reset: invalid parameter\n");
+ return -1;
+ }
+
+ for(i = 0; i < NPRED; i++)
+ {
+ state->past_qua_en[i] = MIN_ENERGY;
+ state->past_qua_en_MR122[i] = MIN_ENERGY_MR122;
+ }
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 gc_pred_reset(gc_predState *state)
+{
+ Word16 i;
+
+ if (state == (gc_predState *) NULL)
+ {
+ /* fprintf(stderr, "gc_pred_reset: invalid parameter\n"); */
+ return -1;
+ }
+
+ for (i = 0; i < NPRED; i++)
+ {
+ state->past_qua_en[i] = MIN_ENERGY;
+ state->past_qua_en_MR122[i] = MIN_ENERGY_MR122;
+ }
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: gc_pred
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type gc_predState
+ mode = AMR mode (enum Mode)
+ code = pointer to the innovative codebook vector; Q12 in MR122 mode,
+ otherwise, Q13 (Word16)
+ exp_gcode0 = pointer to the exponent part of predicted gain factor
+ (Q0) (Word16)
+ frac_gcode0 = pointer to the fractional part of predicted gain factor
+ (Q15) (Word16)
+ exp_en = pointer to the exponent part of the innovation energy; this
+ is calculated for MR795 mode, Q0 (Word16)
+ frac_en = pointer to the fractional part of the innovation energy;
+ this is calculated for MR795 mode, Q15 (Word16)
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ store pointed to by exp_gcode0 contains the exponent part of the
+ recently calculated predicted gain factor
+ store pointed to by frac_gcode0 contains the fractional part of the
+ recently calculated predicted gain factor
+ store pointed to by exp_en contains the exponent part of the
+ recently calculated innovation energy
+ store pointed to by frac_en contains the fractional part of the
+ recently calculated innovation energy
+ pOverflow = 1 if the math functions called by gc_pred
+ results in overflow else zero.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ pred = table of MA prediction coefficients (Q13) (Word16)
+ pred_MR122 = table of MA prediction coefficients (Q6) (Word16)
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the MA prediction of the innovation energy (in
+ dB/(20*log10(2))), with the mean removed.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ gc_pred.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+The original etsi reference code uses a global flag Overflow. However, in the
+actual implementation a pointer to a the overflow flag is passed in.
+
+void
+gc_pred(
+ gc_predState *st, // i/o: State struct
+ enum Mode mode, // i : AMR mode
+ Word16 *code, // i : innovative codebook vector (L_SUBFR)
+ // MR122: Q12, other modes: Q13
+ Word16 *exp_gcode0, // o : exponent of predicted gain factor, Q0
+ Word16 *frac_gcode0,// o : fraction of predicted gain factor Q15
+ Word16 *exp_en, // o : exponent of innovation energy, Q0
+ // (only calculated for MR795)
+ Word16 *frac_en // o : fraction of innovation energy, Q15
+ // (only calculated for MR795)
+)
+{
+ Word16 i;
+ Word32 ener_code;
+ Word16 exp, frac;
+
+ *-------------------------------------------------------------------*
+ * energy of code: *
+ * ~~~~~~~~~~~~~~~ *
+ * ener_code = sum(code[i]^2) *
+ *-------------------------------------------------------------------*
+ ener_code = L_mac((Word32) 0, code[0], code[0]);
+ // MR122: Q12*Q12 -> Q25
+ // others: Q13*Q13 -> Q27
+ for (i = 1; i < L_SUBFR; i++)
+ ener_code = L_mac(ener_code, code[i], code[i]);
+
+ if (sub (mode, MR122) == 0)
+ {
+ Word32 ener;
+
+ // ener_code = ener_code / lcode; lcode = 40; 1/40 = 26214 Q20
+ ener_code = L_mult (pv_round (ener_code), 26214); // Q9 * Q20 -> Q30
+
+ *-------------------------------------------------------------------*
+ * energy of code: *
+ * ~~~~~~~~~~~~~~~ *
+ * ener_code(Q17) = 10 * Log10(energy) / constant *
+ * = 1/2 * Log2(energy) *
+ * constant = 20*Log10(2) *
+ *-------------------------------------------------------------------*
+ // ener_code = 1/2 * Log2(ener_code); Note: Log2=log2+30
+ Log2(ener_code, &exp, &frac);
+ ener_code = L_Comp (sub (exp, 30), frac); // Q16 for log()
+ // ->Q17 for 1/2 log()
+
+ *-------------------------------------------------------------------*
+ * predicted energy: *
+ * ~~~~~~~~~~~~~~~~~ *
+ * ener(Q24) = (Emean + sum{pred[i]*past_en[i]})/constant *
+ * = MEAN_ENER + sum(pred[i]*past_qua_en[i]) *
+ * constant = 20*Log10(2) *
+ *-------------------------------------------------------------------*
+
+ ener = MEAN_ENER_MR122; // Q24 (Q17)
+ for (i = 0; i < NPRED; i++)
+ {
+ ener = L_mac (ener, st->past_qua_en_MR122[i], pred_MR122[i]);
+ // Q10 * Q13 -> Q24
+ // Q10 * Q6 -> Q17
+ }
+
+ *-------------------------------------------------------------------*
+ * predicted codebook gain *
+ * ~~~~~~~~~~~~~~~~~~~~~~~ *
+ * gc0 = Pow10( (ener*constant - ener_code*constant) / 20 ) *
+ * = Pow2(ener-ener_code) *
+ * = Pow2(int(d)+frac(d)) *
+ * *
+ * (store exp and frac for pow2()) *
+ *-------------------------------------------------------------------*
+
+ ener = L_shr (L_sub (ener, ener_code), 1); // Q16
+ L_Extract(ener, exp_gcode0, frac_gcode0);
+ }
+ else // all modes except 12.2
+ {
+ Word32 L_tmp;
+ Word16 exp_code, gcode0;
+
+ *-----------------------------------------------------------------*
+ * Compute: means_ener - 10log10(ener_code/ L_sufr) *
+ *-----------------------------------------------------------------*
+
+ exp_code = norm_l (ener_code);
+ ener_code = L_shl (ener_code, exp_code);
+
+ // Log2 = log2 + 27
+ Log2_norm (ener_code, exp_code, &exp, &frac);
+
+ // fact = 10/log2(10) = 3.01 = 24660 Q13
+ L_tmp = Mpy_32_16(exp, frac, -24660); // Q0.Q15 * Q13 -> Q14
+
+ * L_tmp = means_ener - 10log10(ener_code/L_SUBFR)
+ * = means_ener - 10log10(ener_code) + 10log10(L_SUBFR)
+ * = K - fact * Log2(ener_code)
+ * = K - fact * log2(ener_code) - fact*27
+ *
+ * ==> K = means_ener + fact*27 + 10log10(L_SUBFR)
+ *
+ * means_ener = 33 = 540672 Q14 (MR475, MR515, MR59)
+ * means_ener = 28.75 = 471040 Q14 (MR67)
+ * means_ener = 30 = 491520 Q14 (MR74)
+ * means_ener = 36 = 589824 Q14 (MR795)
+ * means_ener = 33 = 540672 Q14 (MR102)
+ * 10log10(L_SUBFR) = 16.02 = 262481.51 Q14
+ * fact * 27 = 1331640 Q14
+ * -----------------------------------------
+ * (MR475, MR515, MR59) K = 2134793.51 Q14 ~= 16678 * 64 * 2
+ * (MR67) K = 2065161.51 Q14 ~= 32268 * 32 * 2
+ * (MR74) K = 2085641.51 Q14 ~= 32588 * 32 * 2
+ * (MR795) K = 2183945.51 Q14 ~= 17062 * 64 * 2
+ * (MR102) K = 2134793.51 Q14 ~= 16678 * 64 * 2
+
+
+ if (sub (mode, MR102) == 0)
+ {
+ // mean = 33 dB
+ L_tmp = L_mac(L_tmp, 16678, 64); // Q14
+ }
+ else if (sub (mode, MR795) == 0)
+ {
+ // ener_code = <xn xn> * 2^27*2^exp_code
+ // frac_en = ener_code / 2^16
+ // = <xn xn> * 2^11*2^exp_code
+ // <xn xn> = <xn xn>*2^11*2^exp * 2^exp_en
+ // := frac_en * 2^exp_en
+
+ // ==> exp_en = -11-exp_code;
+
+ *frac_en = extract_h (ener_code);
+ *exp_en = sub (-11, exp_code);
+
+ // mean = 36 dB
+ L_tmp = L_mac(L_tmp, 17062, 64); // Q14
+ }
+ else if (sub (mode, MR74) == 0)
+ {
+ // mean = 30 dB
+ L_tmp = L_mac(L_tmp, 32588, 32); // Q14
+ }
+ else if (sub (mode, MR67) == 0)
+ {
+ // mean = 28.75 dB
+ L_tmp = L_mac(L_tmp, 32268, 32); // Q14
+ }
+ else // MR59, MR515, MR475
+ {
+ // mean = 33 dB
+ L_tmp = L_mac(L_tmp, 16678, 64); // Q14
+ }
+
+ *-----------------------------------------------------------------*
+ * Compute gcode0. *
+ * = Sum(i=0,3) pred[i]*past_qua_en[i] - ener_code + mean_ener *
+ *-----------------------------------------------------------------*
+
+ L_tmp = L_shl(L_tmp, 10); // Q24
+ for (i = 0; i < 4; i++)
+ L_tmp = L_mac(L_tmp, pred[i], st->past_qua_en[i]);
+ // Q13 * Q10 -> Q24
+
+ gcode0 = extract_h(L_tmp); // Q8
+
+ *-----------------------------------------------------------------*
+ * gcode0 = pow(10.0, gcode0/20) *
+ * = pow(2, 3.3219*gcode0/20) *
+ * = pow(2, 0.166*gcode0) *
+ *-----------------------------------------------------------------*
+
+ // 5439 Q15 = 0.165985
+ // (correct: 1/(20*log10(2)) 0.166096 = 5443 Q15)
+ if (sub (mode, MR74) == 0) // For IS641 bitexactness
+ L_tmp = L_mult(gcode0, 5439); // Q8 * Q15 -> Q24
+ else
+ L_tmp = L_mult(gcode0, 5443); // Q8 * Q15 -> Q24
+
+ L_tmp = L_shr(L_tmp, 8); // -> Q16
+ L_Extract(L_tmp, exp_gcode0, frac_gcode0); // -> Q0.Q15
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void gc_pred(
+ gc_predState *st, /* i/o: State struct */
+ enum Mode mode, /* i : AMR mode */
+ Word16 *code, /* i : innovative codebook vector (L_SUBFR) */
+ /* MR122: Q12, other modes: Q13 */
+ Word16 *exp_gcode0, /* o : exponent of predicted gain factor, Q0 */
+ Word16 *frac_gcode0,/* o : fraction of predicted gain factor Q15 */
+ Word16 *exp_en, /* o : exponent of innovation energy, Q0 */
+ /* (only calculated for MR795) */
+ Word16 *frac_en, /* o : fraction of innovation energy, Q15 */
+ /* (only calculated for MR795) */
+ Flag *pOverflow
+)
+{
+ register Word16 i;
+ register Word32 L_temp1, L_temp2;
+ register Word32 L_tmp;
+ Word32 ener_code;
+ Word32 ener;
+ Word16 exp, frac;
+ Word16 exp_code, gcode0;
+ Word16 tmp;
+ Word16 *p_code = &code[0];
+
+ /*-------------------------------------------------------------------*
+ * energy of code: *
+ * ~~~~~~~~~~~~~~~ *
+ * ener_code = sum(code[i]^2) *
+ *-------------------------------------------------------------------*/
+ ener_code = 0;
+
+ /* MR122: Q12*Q12 -> Q25 */
+ /* others: Q13*Q13 -> Q27 */
+
+ for (i = L_SUBFR >> 2; i != 0; i--)
+ {
+ tmp = *(p_code++);
+ ener_code += ((Word32) tmp * tmp) >> 3;
+ tmp = *(p_code++);
+ ener_code += ((Word32) tmp * tmp) >> 3;
+ tmp = *(p_code++);
+ ener_code += ((Word32) tmp * tmp) >> 3;
+ tmp = *(p_code++);
+ ener_code += ((Word32) tmp * tmp) >> 3;
+ }
+
+ ener_code <<= 4;
+
+ if (ener_code < 0) /* Check for saturation */
+ {
+ ener_code = MAX_32;
+ }
+
+ if (mode == MR122)
+ {
+ /* ener_code = ener_code / lcode; lcode = 40; 1/40 = 26214 Q20 */
+ /* Q9 * Q20 -> Q30 */
+
+ ener_code = ((Word32)(pv_round(ener_code, pOverflow) * 26214)) << 1;
+
+ /*-------------------------------------------------------------*
+ * energy of code: *
+ * ~~~~~~~~~~~~~~~ *
+ * ener_code(Q17) = 10 * Log10(energy) / constant *
+ * = 1/2 * Log2(energy) *
+ * constant = 20*Log10(2) *
+ *-------------------------------------------------------------*/
+ /* ener_code = 1/2 * Log2(ener_code); Note: Log2=log2+30 */
+ Log2(ener_code, &exp, &frac, pOverflow);
+
+ /* Q16 for log() */
+ /* ->Q17 for 1/2 log()*/
+
+ L_temp1 = (Word32)(exp - 30) << 16;
+ ener_code = L_temp1 + ((Word32)frac << 1);
+
+ /*-------------------------------------------------------------*
+ * predicted energy: *
+ * ~~~~~~~~~~~~~~~~~ *
+ * ener(Q24) = (Emean + sum{pred[i]*past_en[i]})/constant *
+ * = MEAN_ENER + sum(pred[i]*past_qua_en[i]) *
+ * constant = 20*Log10(2) *
+ *-------------------------------------------------------------*/
+
+ ener = MEAN_ENER_MR122; /* Q24 (Q17) */
+ for (i = 0; i < NPRED; i++)
+ {
+ L_temp1 = (((Word32) st->past_qua_en_MR122[i]) *
+ pred_MR122[i]) << 1;
+ ener = L_add(ener, L_temp1, pOverflow);
+
+ /* Q10 * Q13 -> Q24 */
+ /* Q10 * Q6 -> Q17 */
+ }
+
+ /*---------------------------------------------------------------*
+ * predicted codebook gain *
+ * ~~~~~~~~~~~~~~~~~~~~~~~ *
+ * gc0 = Pow10( (ener*constant - ener_code*constant) / 20 ) *
+ * = Pow2(ener-ener_code) *
+ * = Pow2(int(d)+frac(d)) *
+ * *
+ * (store exp and frac for pow2()) *
+ *---------------------------------------------------------------*/
+ /* Q16 */
+
+ L_temp1 = L_sub(ener, ener_code, pOverflow);
+
+
+ *exp_gcode0 = (Word16)(L_temp1 >> 17);
+
+ L_temp2 = (Word32) * exp_gcode0 << 15;
+ L_temp1 >>= 2;
+
+ *frac_gcode0 = (Word16)(L_temp1 - L_temp2);
+
+ }
+ else /* all modes except 12.2 */
+ {
+ /*-----------------------------------------------------------------*
+ * Compute: means_ener - 10log10(ener_code/ L_sufr) *
+ *-----------------------------------------------------------------*/
+
+ exp_code = norm_l(ener_code);
+ ener_code = L_shl(ener_code, exp_code, pOverflow);
+
+ /* Log2 = log2 + 27 */
+ Log2_norm(ener_code, exp_code, &exp, &frac);
+
+ /* fact = 10/log2(10) = 3.01 = 24660 Q13 */
+ /* Q0.Q15 * Q13 -> Q14 */
+
+ L_temp2 = (((Word32) exp) * -24660) << 1;
+ L_tmp = (((Word32) frac) * -24660) >> 15;
+
+ /* Sign-extend resulting product */
+ if (L_tmp & (Word32) 0x00010000L)
+ {
+ L_tmp = L_tmp | (Word32) 0xffff0000L;
+ }
+
+ L_tmp = L_tmp << 1;
+ L_tmp = L_add(L_tmp, L_temp2, pOverflow);
+
+
+ /* L_tmp = means_ener - 10log10(ener_code/L_SUBFR)
+ * = means_ener - 10log10(ener_code) + 10log10(L_SUBFR)
+ * = K - fact * Log2(ener_code)
+ * = K - fact * log2(ener_code) - fact*27
+ *
+ * ==> K = means_ener + fact*27 + 10log10(L_SUBFR)
+ *
+ * means_ener = 33 = 540672 Q14 (MR475, MR515, MR59)
+ * means_ener = 28.75 = 471040 Q14 (MR67)
+ * means_ener = 30 = 491520 Q14 (MR74)
+ * means_ener = 36 = 589824 Q14 (MR795)
+ * means_ener = 33 = 540672 Q14 (MR102)
+ * 10log10(L_SUBFR) = 16.02 = 262481.51 Q14
+ * fact * 27 = 1331640 Q14
+ * -----------------------------------------
+ * (MR475, MR515, MR59) K = 2134793.51 Q14 ~= 16678 * 64 * 2
+ * (MR67) K = 2065161.51 Q14 ~= 32268 * 32 * 2
+ * (MR74) K = 2085641.51 Q14 ~= 32588 * 32 * 2
+ * (MR795) K = 2183945.51 Q14 ~= 17062 * 64 * 2
+ * (MR102) K = 2134793.51 Q14 ~= 16678 * 64 * 2
+ */
+
+ if (mode == MR102)
+ {
+ /* mean = 33 dB */
+ L_temp2 = (Word32) 16678 << 7;
+ L_tmp = L_add(L_tmp, L_temp2, pOverflow); /* Q14 */
+ }
+ else if (mode == MR795)
+ {
+ /* ener_code = <xn xn> * 2^27*2^exp_code
+ frac_en = ener_code / 2^16
+ = <xn xn> * 2^11*2^exp_code
+ <xn xn> = <xn xn>*2^11*2^exp * 2^exp_en
+ : = frac_en * 2^exp_en
+ ==> exp_en = -11-exp_code; */
+ *frac_en = (Word16)(ener_code >> 16);
+ *exp_en = sub(-11, exp_code, pOverflow);
+
+ /* mean = 36 dB */
+ L_temp2 = (Word32) 17062 << 7;
+ L_tmp = L_add(L_tmp, L_temp2, pOverflow); /* Q14 */
+ }
+ else if (mode == MR74)
+ {
+ /* mean = 30 dB */
+ L_temp2 = (Word32) 32588 << 6;
+ L_tmp = L_add(L_tmp, L_temp2, pOverflow); /* Q14 */
+ }
+ else if (mode == MR67)
+ {
+ /* mean = 28.75 dB */
+ L_temp2 = (Word32) 32268 << 6;
+ L_tmp = L_add(L_tmp, L_temp2, pOverflow); /* Q14 */
+ }
+ else /* MR59, MR515, MR475 */
+ {
+ /* mean = 33 dB */
+ L_temp2 = (Word32) 16678 << 7;
+ L_tmp = L_add(L_tmp, L_temp2, pOverflow); /* Q14 */
+ }
+
+ /*-------------------------------------------------------------*
+ * Compute gcode0. *
+ * = Sum(i=0,3) pred[i]*past_qua_en[i] - ener_code + mean_ener *
+ *--------------------------------------------------------------*/
+ /* Q24 */
+ if (L_tmp > (Word32) 0X001fffffL)
+ {
+ *pOverflow = 1;
+ L_tmp = MAX_32;
+ }
+ else if (L_tmp < (Word32) 0xffe00000L)
+ {
+ *pOverflow = 1;
+ L_tmp = MIN_32;
+ }
+ else
+ {
+ L_tmp = L_tmp << 10;
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ L_temp2 = ((((Word32) pred[i]) * st->past_qua_en[i]) << 1);
+ L_tmp = L_add(L_tmp, L_temp2, pOverflow); /* Q13 * Q10 -> Q24 */
+ }
+
+ gcode0 = (Word16)(L_tmp >> 16); /* Q8 */
+
+ /*-----------------------------------------------------------*
+ * gcode0 = pow(10.0, gcode0/20) *
+ * = pow(2, 3.3219*gcode0/20) *
+ * = pow(2, 0.166*gcode0) *
+ *-----------------------------------------------------------*/
+
+ /* 5439 Q15 = 0.165985 */
+ /* (correct: 1/(20*log10(2)) 0.166096 = 5443 Q15) */
+
+ if (mode == MR74) /* For IS641 bitexactness */
+ {
+ L_tmp = (((Word32) gcode0) * 5439) << 1; /* Q8 * Q15 -> Q24 */
+ }
+ else
+ {
+ L_tmp = (((Word32) gcode0) * 5443) << 1; /* Q8 * Q15 -> Q24 */
+ }
+
+ if (L_tmp < 0)
+ {
+ L_tmp = ~((~L_tmp) >> 8);
+ }
+ else
+ {
+ L_tmp = L_tmp >> 8; /* -> Q16 */
+ }
+
+ *exp_gcode0 = (Word16)(L_tmp >> 16);
+ if (L_tmp < 0)
+ {
+ L_temp1 = ~((~L_tmp) >> 1);
+ }
+ else
+ {
+ L_temp1 = L_tmp >> 1;
+ }
+ L_temp2 = (Word32) * exp_gcode0 << 15;
+ *frac_gcode0 = (Word16)(L_sub(L_temp1, L_temp2, pOverflow));
+ /* -> Q0.Q15 */
+ }
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: gc_pred_update
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type gc_predState
+ qua_ener_MR122 = quantized energy for update (Q10); calculated as
+ (log2(qua_err)) (Word16)
+ qua_ener = quantized energy for update (Q10); calculated as
+ (20*log10(qua_err)) (Word16)
+
+ Outputs:
+ structure pointed to by st contains the calculated quantized energy
+ for update
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function updates the MA predictor with the last quantized energy.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ gc_pred.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void gc_pred_update(
+ gc_predState *st, // i/o: State struct
+ Word16 qua_ener_MR122, // i : quantized energy for update, Q10
+ // (log2(qua_err))
+ Word16 qua_ener // i : quantized energy for update, Q10
+ // (20*log10(qua_err))
+)
+{
+ Word16 i;
+
+ for (i = 3; i > 0; i--)
+ {
+ st->past_qua_en[i] = st->past_qua_en[i - 1];
+ st->past_qua_en_MR122[i] = st->past_qua_en_MR122[i - 1];
+ }
+
+ st->past_qua_en_MR122[0] = qua_ener_MR122; // log2 (qua_err), Q10
+
+ st->past_qua_en[0] = qua_ener; // 20*log10(qua_err), Q10
+
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void gc_pred_update(
+ gc_predState *st, /* i/o: State struct */
+ Word16 qua_ener_MR122, /* i : quantized energy for update, Q10 */
+ /* (log2(qua_err)) */
+ Word16 qua_ener /* i : quantized energy for update, Q10 */
+ /* (20*log10(qua_err)) */
+)
+{
+ st->past_qua_en[3] = st->past_qua_en[2];
+ st->past_qua_en_MR122[3] = st->past_qua_en_MR122[2];
+
+ st->past_qua_en[2] = st->past_qua_en[1];
+ st->past_qua_en_MR122[2] = st->past_qua_en_MR122[1];
+
+ st->past_qua_en[1] = st->past_qua_en[0];
+ st->past_qua_en_MR122[1] = st->past_qua_en_MR122[0];
+
+ st->past_qua_en_MR122[0] = qua_ener_MR122; /* log2 (qua_err), Q10 */
+
+ st->past_qua_en[0] = qua_ener; /* 20*log10(qua_err), Q10 */
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: gc_pred_average_limited
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type gc_predState
+ ener_avg_MR122 = pointer to the averaged quantized energy (Q10);
+ calculated as (log2(qua_err)) (Word16)
+ ener_avg = pointer to the averaged quantized energy (Q10); calculated
+ as (20*log10(qua_err)) (Word16)
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ store pointed to by ener_avg_MR122 contains the new averaged quantized
+ energy
+ store pointed to by ener_avg contains the new averaged quantized
+ energy
+ pOverflow = 1 if the math functions called by gc_pred_average_limited
+ results in overflow else zero.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function calculates the average of MA predictor state values (with a
+ lower limit) used in error concealment.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ gc_pred.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+The original etsi reference code uses a global flag Overflow. However, in the
+actual implementation a pointer to a the overflow flag is passed in.
+
+void gc_pred_average_limited(
+ gc_predState *st, // i: State struct
+ Word16 *ener_avg_MR122, // o: everaged quantized energy, Q10
+ // (log2(qua_err))
+ Word16 *ener_avg // o: averaged quantized energy, Q10
+ // (20*log10(qua_err))
+)
+{
+ Word16 av_pred_en;
+ Word16 i;
+
+ // do average in MR122 mode (log2() domain)
+ av_pred_en = 0;
+ for (i = 0; i < NPRED; i++)
+ {
+ av_pred_en = add (av_pred_en, st->past_qua_en_MR122[i]);
+ }
+
+ // av_pred_en = 0.25*av_pred_en
+ av_pred_en = mult (av_pred_en, 8192);
+
+ // if (av_pred_en < -14/(20Log10(2))) av_pred_en = ..
+
+ if (sub (av_pred_en, MIN_ENERGY_MR122) < 0)
+ {
+ av_pred_en = MIN_ENERGY_MR122;
+ }
+ *ener_avg_MR122 = av_pred_en;
+
+ // do average for other modes (20*log10() domain)
+ av_pred_en = 0;
+ for (i = 0; i < NPRED; i++)
+ {
+ av_pred_en = add (av_pred_en, st->past_qua_en[i]);
+ }
+
+ // av_pred_en = 0.25*av_pred_en
+ av_pred_en = mult (av_pred_en, 8192);
+
+ // if (av_pred_en < -14) av_pred_en = ..
+
+ if (sub (av_pred_en, MIN_ENERGY) < 0)
+ {
+ av_pred_en = MIN_ENERGY;
+ }
+ *ener_avg = av_pred_en;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void gc_pred_average_limited(
+ gc_predState *st, /* i: State struct */
+ Word16 *ener_avg_MR122, /* o: everaged quantized energy, Q10 */
+ /* (log2(qua_err)) */
+ Word16 *ener_avg, /* o: averaged quantized energy, Q10 */
+ /* (20*log10(qua_err)) */
+ Flag *pOverflow
+)
+{
+ Word16 av_pred_en;
+ register Word16 i;
+
+ /* do average in MR122 mode (log2() domain) */
+ av_pred_en = 0;
+ for (i = 0; i < NPRED; i++)
+ {
+ av_pred_en =
+ add(av_pred_en, st->past_qua_en_MR122[i], pOverflow);
+ }
+
+ /* av_pred_en = 0.25*av_pred_en (with sign-extension)*/
+ if (av_pred_en < 0)
+ {
+ av_pred_en = (av_pred_en >> 2) | 0xc000;
+ }
+ else
+ {
+ av_pred_en >>= 2;
+ }
+
+ /* if (av_pred_en < -14/(20Log10(2))) av_pred_en = .. */
+ if (av_pred_en < MIN_ENERGY_MR122)
+ {
+ av_pred_en = MIN_ENERGY_MR122;
+ }
+ *ener_avg_MR122 = av_pred_en;
+
+ /* do average for other modes (20*log10() domain) */
+ av_pred_en = 0;
+ for (i = 0; i < NPRED; i++)
+ {
+ av_pred_en = add(av_pred_en, st->past_qua_en[i], pOverflow);
+ }
+
+ /* av_pred_en = 0.25*av_pred_en (with sign-extension)*/
+ if (av_pred_en < 0)
+ {
+ av_pred_en = (av_pred_en >> 2) | 0xc000;
+ }
+ else
+ {
+ av_pred_en >>= 2;
+ }
+
+ /* if (av_pred_en < -14) av_pred_en = .. */
+ if (av_pred_en < MIN_ENERGY)
+ {
+ av_pred_en = MIN_ENERGY;
+ }
+ *ener_avg = av_pred_en;
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/gmed_n.cpp b/media/libstagefright/codecs/amrnb/common/src/gmed_n.cpp
new file mode 100644
index 0000000..be76241
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/gmed_n.cpp
@@ -0,0 +1,218 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./audio/gsm-amr/c/src/gmed_n.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Put file into template and first pass at optimization.
+
+ Description: Made changes based on comments from the review meeting. Used
+ pointers instead of index addressing in the arrays.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unncessary include files.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "gmed_n.h"
+#include "typedef.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define NMAX 9 /* largest N used in median calculation */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: gmed_n
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ ind = input values (Word16)
+ n = number of inputs to find the median (Word16)
+
+ Returns:
+ median value.
+
+ Outputs:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function calculates N-point median of a data set. This routine is only
+ valid for a odd number of gains (n <= NMAX).
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ gmed_n.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 gmed_n ( // o : The median value (0...N-1)
+ Word16 ind[], // i : Past gain values
+ Word16 n // i : The number of gains; this routine
+ // is only valid for a odd number of gains
+ // (n <= NMAX)
+)
+{
+ Word16 i, j, ix = 0;
+ Word16 max;
+ Word16 medianIndex;
+ Word16 tmp[NMAX];
+ Word16 tmp2[NMAX];
+
+ for (i = 0; i < n; i++)
+ {
+ tmp2[i] = ind[i];
+ }
+
+ for (i = 0; i < n; i++)
+ {
+ max = -32767;
+ for (j = 0; j < n; j++)
+ {
+ if (sub (tmp2[j], max) >= 0)
+ {
+ max = tmp2[j];
+ ix = j;
+ }
+ }
+ tmp2[ix] = -32768;
+ tmp[i] = ix;
+ }
+
+ medianIndex=tmp[ shr(n,1) ]; // account for complex addressing
+ return (ind[medianIndex]);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 gmed_n( /* o : the median value */
+ Word16 ind[], /* i : input values */
+ Word16 n /* i : number of inputs */
+)
+{
+ register Word16 i, j, ix = 0;
+ register Word16 max;
+ register Word16 medianIndex;
+ Word16 tmp[NMAX];
+ Word16 tmp2[NMAX];
+
+ for (i = 0; i < n; i++)
+ {
+ *(tmp2 + i) = *(ind + i);
+ }
+
+ for (i = 0; i < n; i++)
+ {
+ max = -32767;
+ for (j = 0; j < n; j++)
+ {
+ if (*(tmp2 + j) >= max)
+ {
+ max = *(tmp2 + j);
+ ix = j;
+ }
+ }
+ *(tmp2 + ix) = -32768;
+ *(tmp + i) = ix;
+ }
+
+ medianIndex = *(tmp + (n >> 1)); /* account for complex addressing */
+
+ return (*(ind + medianIndex));
+}
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/gray_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/gray_tbl.cpp
new file mode 100644
index 0000000..c4b2dbc
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/gray_tbl.cpp
@@ -0,0 +1,162 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/gray_tbl.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the declaration for the gray encoding and decoding tables,
+ gray_tbl[] and dgray_tbl[] used by the c1035pf and d1035pf module
+ respectively.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+
+ extern const Word16 gray[];
+ extern const Word16 dgray[];
+ const Word16 gray[8] = {0, 1, 3, 2, 6, 4, 5, 7};
+ const Word16 dgray[8] = {0, 1, 3, 2, 5, 6, 4, 7};
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] gray.tab, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/grid_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/grid_tbl.cpp
new file mode 100644
index 0000000..48566cc
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/grid_tbl.cpp
@@ -0,0 +1,181 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/grid_tbl.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the declaration for grid_tbl[] used by the az_lsp()
+ function.
+
+ // Table for az_lsp()
+ //
+ // 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));
+ //
+ //
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "az_lsp.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+#define grid_points 60
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+ const Word16 grid[grid_points + 1] =
+ {
+ 32760, 32723, 32588, 32364, 32051, 31651,
+ 31164, 30591, 29935, 29196, 28377, 27481,
+ 26509, 25465, 24351, 23170, 21926, 20621,
+ 19260, 17846, 16384, 14876, 13327, 11743,
+ 10125, 8480, 6812, 5126, 3425, 1714,
+ 0, -1714, -3425, -5126, -6812, -8480,
+ -10125, -11743, -13327, -14876, -16384, -17846,
+ -19260, -20621, -21926, -23170, -24351, -25465,
+ -26509, -27481, -28377, -29196, -29935, -30591,
+ -31164, -31651, -32051, -32364, -32588, -32723,
+ -32760
+ };
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] grid.tab, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/int_lpc.cpp b/media/libstagefright/codecs/amrnb/common/src/int_lpc.cpp
new file mode 100644
index 0000000..806474d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/int_lpc.cpp
@@ -0,0 +1,633 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./audio/gsm-amr/c/src/int_lpc.c
+ Functions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+ Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description: Per review comments, replaced includes of "basic_op.h"
+ and "count.h" with "shr.h", "sub.h", and "add.h"
+
+ Description: For Int_lpc_1and3() and Int_lpc_1and3_2()
+ 1. Replaced array addressing by pointers
+ 2. Eliminated math operations that unnecessary checked for
+ saturation
+ 3. Unrolled loops to speed up processing
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "int_lpc.h"
+#include "typedef.h"
+#include "cnst.h"
+#include "lsp_az.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Int_lpc_1and3
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsp_old -- array of type Word16 -- LSP vector at the
+ 4th subfr. of past frame (M)
+ lsp_mid -- array of type Word16 -- LSP vector at the 2nd subfr. of
+ present frame (M)
+ lsp_new -- array of type Word16 -- LSP vector at the 4th subfr. of
+ present frame (M)
+
+ Outputs:
+ Az -- array of type Word16 -- interpolated LP parameters in all subfr.
+ (AZ_SIZE)
+ pOverflow -- pointer to type Flag -- Overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Interpolates the LSPs and converts to LPC parameters
+ to get a different LP filter in each subframe.
+ Description : The 20 ms speech frame is divided into 4 subframes.
+ The LSPs are quantized and transmitted at the 2nd and
+ 4th subframes (twice per frame) and interpolated at the
+ 1st and 3rd subframe.
+
+ |------|------|------|------|
+ sf1 sf2 sf3 sf4
+ F0 Fm F1
+
+ sf1: 1/2 Fm + 1/2 F0 sf3: 1/2 F1 + 1/2 Fm
+ sf2: Fm sf4: F1
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ int_lpc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Int_lpc_1and3(
+ Word16 lsp_old[], /* i : LSP vector at the 4th subfr. of past frame (M) */
+ Word16 lsp_mid[], /* i : LSP vector at the 2nd subfr. of
+ present frame (M) */
+ Word16 lsp_new[], /* i : LSP vector at the 4th subfr. of
+ present frame (M) */
+ Word16 Az[], /* o : interpolated LP parameters in all subfr.
+ (AZ_SIZE) */
+ Flag *pOverflow
+)
+{
+ Word16 i;
+ Word16 lsp[M];
+ Word16 *p_lsp_old = &lsp_old[0];
+ Word16 *p_lsp_mid = &lsp_mid[0];
+ Word16 *p_lsp_new = &lsp_new[0];
+ Word16 *p_lsp = &lsp[0];
+
+ /* lsp[i] = lsp_mid[i] * 0.5 + lsp_old[i] * 0.5 */
+
+ for (i = M >> 1; i != 0; i--)
+ {
+ *(p_lsp++) = (*(p_lsp_old++) >> 1) + (*(p_lsp_mid++) >> 1);
+ *(p_lsp++) = (*(p_lsp_old++) >> 1) + (*(p_lsp_mid++) >> 1);
+ }
+
+ Lsp_Az(
+ lsp,
+ Az,
+ pOverflow); /* Subframe 1 */
+
+ Az += MP1;
+
+ Lsp_Az(
+ lsp_mid,
+ Az,
+ pOverflow); /* Subframe 2 */
+
+ Az += MP1;
+
+ p_lsp_mid = &lsp_mid[0];
+ p_lsp = &lsp[0];
+
+ for (i = M >> 1; i != 0; i--)
+ {
+ *(p_lsp++) = (*(p_lsp_mid++) >> 1) + (*(p_lsp_new++) >> 1);
+ *(p_lsp++) = (*(p_lsp_mid++) >> 1) + (*(p_lsp_new++) >> 1);
+ }
+
+ Lsp_Az(
+ lsp,
+ Az,
+ pOverflow); /* Subframe 3 */
+
+ Az += MP1;
+
+ Lsp_Az(
+ lsp_new,
+ Az,
+ pOverflow); /* Subframe 4 */
+
+ return;
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Int_lpc_1and3_2
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsp_old -- array of type Word16 -- LSP vector at the
+ 4th subfr. of past frame (M)
+ lsp_mid -- array of type Word16 -- LSP vector at the 2nd subfr. of
+ present frame (M)
+ lsp_new -- array of type Word16 -- LSP vector at the 4th subfr. of
+ present frame (M)
+
+ Outputs:
+ Az -- array of type Word16 -- interpolated LP parameters in.
+ subfr 1 and 2.
+ pOverflow -- pointer to type Flag -- Overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Interpolation of the LPC parameters. Same as the Int_lpc
+ function but we do not recompute Az() for subframe 2 and
+ 4 because it is already available.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ int_lpc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Int_lpc_1and3_2(
+ Word16 lsp_old[], /* i : LSP vector at the 4th subfr. of past frame (M) */
+ Word16 lsp_mid[], /* i : LSP vector at the 2nd subframe of
+ present frame (M) */
+ Word16 lsp_new[], /* i : LSP vector at the 4th subframe of
+ present frame (M) */
+ Word16 Az[], /* o :interpolated LP parameters
+ in subframes 1 and 3 (AZ_SIZE) */
+ Flag *pOverflow
+)
+{
+ Word16 i;
+ Word16 lsp[M];
+ Word16 *p_lsp_old = &lsp_old[0];
+ Word16 *p_lsp_mid = &lsp_mid[0];
+ Word16 *p_lsp_new = &lsp_new[0];
+ Word16 *p_lsp = &lsp[0];
+
+ /* lsp[i] = lsp_mid[i] * 0.5 + lsp_old[i] * 0.5 */
+
+ for (i = M >> 1; i != 0; i--)
+ {
+ *(p_lsp++) = (*(p_lsp_old++) >> 1) + (*(p_lsp_mid++) >> 1);
+ *(p_lsp++) = (*(p_lsp_old++) >> 1) + (*(p_lsp_mid++) >> 1);
+ }
+ Lsp_Az(lsp, Az, pOverflow); /* Subframe 1 */
+ Az += MP1 * 2;
+
+ p_lsp_mid = &lsp_mid[0];
+ p_lsp = &lsp[0];
+
+ for (i = M >> 1; i != 0; i--)
+ {
+ *(p_lsp++) = (*(p_lsp_mid++) >> 1) + (*(p_lsp_new++) >> 1);
+ *(p_lsp++) = (*(p_lsp_mid++) >> 1) + (*(p_lsp_new++) >> 1);
+ }
+
+ Lsp_Az(lsp, Az, pOverflow); /* Subframe 3 */
+
+ return;
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: lsp
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsp_old -- array of type Word16 -- LSP vector at the
+ 4th subfr. of past frame (M)
+ lsp_new -- array of type Word16 -- LSP vector at the 4th subfr. of
+ present frame (M)
+
+ Outputs:
+ Az -- array of type Word16 -- interpolated LP parameters in.
+ all subframes.
+ pOverflow -- pointer to type Flag -- Overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Interpolates the LSPs and convert to LP parameters to get
+ a different LP filter in each subframe.
+
+ DESCRIPTION:
+ The 20 ms speech frame is divided into 4 subframes.
+ The LSPs are quantized and transmitted at the 4th subframe
+ (once per frame) and interpolated at the 1st, 2nd and 3rd subframe.
+
+ |------|------|------|------|
+ sf1 sf2 sf3 sf4
+ F0 F1
+
+ sf1: 3/4 F0 + 1/4 F1 sf3: 1/4 F0 + 3/4 F1
+ sf2: 1/2 F0 + 1/2 F1 sf4: F1
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ int_lpc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Int_lpc_1to3(
+ Word16 lsp_old[], /* input : LSP vector at the 4th SF of past frame */
+ Word16 lsp_new[], /* input : LSP vector at the 4th SF of present frame */
+ Word16 Az[], /* output: interpolated LP parameters in all SFs */
+ Flag *pOverflow
+)
+{
+ Word16 i;
+ Word16 temp;
+ Word16 temp2;
+
+ Word16 lsp[M];
+
+ for (i = 0; i < M; i++)
+ {
+ temp = shr(lsp_old[i], 2, pOverflow);
+ temp = sub(lsp_old[i], temp, pOverflow);
+ temp2 = shr(lsp_new[i], 2, pOverflow);
+
+ lsp[i] = add(temp2, temp, pOverflow);
+ }
+
+ Lsp_Az(
+ lsp,
+ Az,
+ pOverflow); /* Subframe 1 */
+
+ Az += MP1;
+
+
+ for (i = 0; i < M; i++)
+ {
+ temp = shr(lsp_new[i], 1, pOverflow);
+ temp2 = shr(lsp_old[i], 1, pOverflow);
+ lsp[i] = add(temp, temp2, pOverflow);
+ }
+
+ Lsp_Az(
+ lsp,
+ Az,
+ pOverflow); /* Subframe 2 */
+
+ Az += MP1;
+
+ for (i = 0; i < M; i++)
+ {
+ temp = shr(lsp_new[i], 2, pOverflow);
+ temp = sub(lsp_new[i], temp, pOverflow);
+ temp2 = shr(lsp_old[i], 2, pOverflow);
+
+ lsp[i] = add(temp2, temp, pOverflow);
+ }
+
+ Lsp_Az(
+ lsp,
+ Az,
+ pOverflow); /* Subframe 3 */
+
+ Az += MP1;
+
+ Lsp_Az(
+ lsp_new,
+ Az,
+ pOverflow); /* Subframe 4 */
+
+ return;
+}
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Int_lpc_1to3_2
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsp_old -- array of type Word16 -- LSP vector at the
+ 4th subfr. of past frame (M)
+ lsp_new -- array of type Word16 -- LSP vector at the 4th subfr. of
+ present frame (M)
+
+ Outputs:
+ Az -- array of type Word16 -- interpolated LP parameters in.
+ subfr 1, 2, and 3.
+ pOverflow -- pointer to type Flag -- Overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Interpolation of the LPC parameters.
+ Same as the previous function but we do not recompute Az() for
+ subframe 4 because it is already available.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ int_lpc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Int_lpc_1to3_2(
+ Word16 lsp_old[], /* input : LSP vector at the 4th SF of past frame */
+ Word16 lsp_new[], /* input : LSP vector at the 4th SF of present frame */
+ Word16 Az[], /* output: interpolated LP parameters in SFs 1,2,3 */
+ Flag *pOverflow
+)
+{
+ Word16 i;
+ Word16 temp;
+ Word16 temp2;
+ Word16 lsp[M];
+
+ for (i = 0; i < M; i++)
+ {
+ temp = shr(lsp_old[i], 2, pOverflow);
+
+ temp = sub(lsp_old[i], temp, pOverflow);
+
+ temp2 = shr(lsp_new[i], 2, pOverflow);
+
+ lsp[i] = add(temp2, temp, pOverflow);
+ }
+
+ Lsp_Az(
+ lsp,
+ Az,
+ pOverflow); /* Subframe 1 */
+
+ Az += MP1;
+
+ for (i = 0; i < M; i++)
+ {
+ temp = shr(lsp_new[i], 1, pOverflow);
+ temp2 = shr(lsp_old[i], 1, pOverflow);
+
+ lsp[i] = add(temp2, temp, pOverflow);
+ }
+
+ Lsp_Az(
+ lsp,
+ Az,
+ pOverflow); /* Subframe 2 */
+
+ Az += MP1;
+
+ for (i = 0; i < M; i++)
+ {
+ temp = shr(lsp_new[i], 2, pOverflow);
+ temp = sub(lsp_new[i], temp, pOverflow);
+ temp2 = shr(lsp_old[i], 2, pOverflow);
+
+ lsp[i] = add(temp, temp2, pOverflow);
+ }
+
+ Lsp_Az(
+ lsp,
+ Az,
+ pOverflow); /* Subframe 3 */
+
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/inv_sqrt.cpp b/media/libstagefright/codecs/amrnb/common/src/inv_sqrt.cpp
new file mode 100644
index 0000000..83f4d0c
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/inv_sqrt.cpp
@@ -0,0 +1,270 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./audio/gsm-amr/c/src/inv_sqrt.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Put file into template.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Replaced basic_op.h with the header files of the math functions
+ used in the file.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Defined one local variable per line.
+ 2. Used "&=", ">>=", and "+=" in the code.
+
+ Description: Updated template. Changed function interface to pass in a
+ pointer to overflow flag into the function instead of using a
+ global flag.
+
+ Description: Removed inclusion of inv_sqrt.tab file. Changed array name
+ from "table" to "inv_sqrt_tbl"
+
+ Description: Removed math operations that were not needed as functions,
+ this because the numbers themselves will not saturate the
+ operators, so there is not need to check for saturation.
+
+ Description: Updated copyrigth year, according to code review comments.
+
+ Description: Replaced "int" and/or "char" with defined types.
+ Added proper casting (Word32) to some left shifting operations
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "inv_sqrt.h"
+#include "typedef.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Inv_sqrt
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_x = input value (Word32)
+ pOverflow = pointer to overflow flag
+
+ Outputs:
+ pOverflow -> if the Inv_sqrt operation resulted in an overflow.
+
+ Returns:
+ L_y = inverse squareroot of L_x (Word32)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes 1/sqrt(L_x), where L_x is positive.
+ If L_x is negative or zero, the result is 1 (3fff ffff).
+
+ The function 1/sqrt(L_x) is approximated by a table and linear
+ interpolation. The inverse square root is computed using the
+ following steps:
+ 1- Normalization of L_x.
+ 2- If (30-exponent) is even then shift right once.
+ 3- exponent = (30-exponent)/2 +1
+ 4- i = bit25-b31 of L_x; 16<=i<=63 because of normalization.
+ 5- a = bit10-b24
+ 6- i -=16
+ 7- L_y = table[i]<<16 - (table[i] - table[i+1]) * a * 2
+ 8- L_y >>= exponent
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ inv_sqrt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word32 Inv_sqrt ( // (o) : output value
+ Word32 L_x // (i) : input value
+)
+{
+ Word16 exp, i, a, tmp;
+ Word32 L_y;
+
+* The reference ETSI code uses a global Overflow flag. In the actual
+* implementation a pointer to the overflow flag is passed into the function.
+* This pointer is in turn passed into the basic math functions such as add(),
+* L_shl(), L_shr(), sub() called by this module.
+
+ if (L_x <= (Word32) 0)
+ return ((Word32) 0x3fffffffL);
+
+ exp = norm_l (L_x);
+ L_x = L_shl (L_x, exp); // L_x is normalize
+
+ exp = sub (30, exp);
+
+ if ((exp & 1) == 0) // If exponent even -> shift right
+ {
+ L_x = L_shr (L_x, 1);
+ }
+ exp = shr (exp, 1);
+ exp = add (exp, 1);
+
+ L_x = L_shr (L_x, 9);
+ i = extract_h (L_x); // Extract b25-b31
+ L_x = L_shr (L_x, 1);
+ a = extract_l (L_x); // Extract b10-b24
+ a = a & (Word16) 0x7fff;
+
+ i = sub (i, 16);
+
+ L_y = L_deposit_h (table[i]); // table[i] << 16
+ tmp = sub (table[i], table[i + 1]); // table[i] - table[i+1])
+ L_y = L_msu (L_y, tmp, a); // L_y -= tmp*a*2
+
+ L_y = L_shr (L_y, exp); // denormalization
+
+ return (L_y);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word32 Inv_sqrt( /* (o) : output value */
+ Word32 L_x, /* (i) : input value */
+ Flag * pOverflow /* (i) : pointer to overflow flag */
+)
+{
+ Word16 exp;
+ Word16 i;
+ Word16 a;
+ Word16 tmp;
+ Word32 L_y;
+ OSCL_UNUSED_ARG(pOverflow);
+
+ if (L_x <= (Word32) 0)
+ {
+ return ((Word32) 0x3fffffffL);
+ }
+
+ exp = norm_l(L_x);
+ L_x <<= exp; /* L_x is normalize */
+
+ exp = 30 - exp;
+
+ if ((exp & 1) == 0) /* If exponent even -> shift right */
+ {
+ L_x >>= 1;
+ }
+ exp >>= 1;
+ exp += 1;
+
+ L_x >>= 9;
+ i = (Word16)(L_x >> 16); /* Extract b25-b31 */
+ a = (Word16)(L_x >> 1); /* Extract b10-b24 */
+ a &= (Word16) 0x7fff;
+
+ i -= 16;
+
+ L_y = (Word32)inv_sqrt_tbl[i] << 16; /* inv_sqrt_tbl[i] << 16 */
+
+ /* inv_sqrt_tbl[i] - inv_sqrt_tbl[i+1]) */
+ tmp = inv_sqrt_tbl[i] - inv_sqrt_tbl[i + 1];
+ /* always a positive number less than 200 */
+
+ L_y -= ((Word32)tmp * a) << 1; /* L_y -= tmp*a*2 */
+ /* always a positive minus a small negative number */
+
+ L_y >>= exp; /* denormalization, exp always 0< exp < 31 */
+
+ return (L_y);
+}
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/inv_sqrt_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/inv_sqrt_tbl.cpp
new file mode 100644
index 0000000..13c3b24
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/inv_sqrt_tbl.cpp
@@ -0,0 +1,168 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/inv_sqrt_tbl.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed table name to inv_sqrt_tbl
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the declaration for table[] used by the inv_sqrt function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "inv_sqrt.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+ const Word16 inv_sqrt_tbl[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
+ };
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] inv_sqrt.tab file, UMTS GSM AMR speech codec, R99 - Version 3.2.0,
+ March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/l_abs.cpp b/media/libstagefright/codecs/amrnb/common/src/l_abs.cpp
new file mode 100644
index 0000000..fd1c90d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/l_abs.cpp
@@ -0,0 +1,193 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./gsm-amr/c/src/l_abs.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the L_abs function. Sync'ed up
+ with the current template and fixed tabs.
+
+ Description: Removed conditional code that updates WMOPS counter
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 32 bit long signed integer (Word32 ) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ L_var1 = absolute value of input (Word32)
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function calculates the absolute value of L_var1; saturate in case
+ where the input is -214783648.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] basicop2.c, ETS Version 2.0.0, February 8, 1999
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+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;
+ }
+ }
+
+#if (WMOPS)
+ multiCounter[currCounter].L_abs++;
+#endif
+ return (L_var_out);
+}
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word32 L_abs(register Word32 L_var1)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ Word32 y = L_var1 - (L_var1 < 0);
+ y = y ^(y >> 31);
+ return (y);
+
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/l_deposit_h.cpp b/media/libstagefright/codecs/amrnb/common/src/l_deposit_h.cpp
new file mode 100644
index 0000000..e705ed1
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/l_deposit_h.cpp
@@ -0,0 +1,177 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./gsm-amr/c/src/l_deposit_h.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the L_deposit_h function. Sync'ed up
+ with the current template and fixed tabs.
+
+ Description: Removed conditional code that updates WMOPS counter
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ var1 = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ var1 = deposit of var1 into MSWord of 32 bit value (Word32)
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function deposits the 16 bit var1 into the 16 MS bits of the 32 bit
+ output. The 16 LS bits of the output are zeroed.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] basicop2.c, ETS Version 2.0.0, February 8, 1999
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word32 L_deposit_h (Word16 var1)
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1 << 16;
+#if (WMOPS)
+ multiCounter[currCounter].L_deposit_h++;
+#endif
+ return (L_var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word32 L_deposit_h(Word16 var1)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return ((Word32) var1 << 16);
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/l_deposit_l.cpp b/media/libstagefright/codecs/amrnb/common/src/l_deposit_l.cpp
new file mode 100644
index 0000000..5064fdb
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/l_deposit_l.cpp
@@ -0,0 +1,177 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./gsm-amr/c/src/l_deposit_l.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the L_deposit_l function. Sync'ed up
+ with the current template and fixed tabs.
+
+ Description: Removed conditional code that updates WMOPS counter
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ var1 = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ var1 = deposit of var1 into LSWord of 32 bit value (Word32)
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function deposits the 16 bit var1 into the 16 LS bits of the 32 bit
+ output. The 16 MS bits of the output are sign extended.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] basicop2.c, ETS Version 2.0.0, February 8, 1999
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word32 L_deposit_l (Word16 var1)
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1;
+#if (WMOPS)
+ multiCounter[currCounter].L_deposit_l++;
+#endif
+ return (L_var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word32 L_deposit_l(Word16 var1)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return ((Word32) var1);
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/l_shr_r.cpp b/media/libstagefright/codecs/amrnb/common/src/l_shr_r.cpp
new file mode 100644
index 0000000..f609a73
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/l_shr_r.cpp
@@ -0,0 +1,214 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Filename: /audio/gsm_amr/c/src/l_shr_r.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the L_shr_r function. Sync'ed up
+ with the current template and fixed tabs.
+
+ Description: Updated template. Changed function interface to pass in a
+ pointer to overflow flag into the function instead of using a
+ global flag. Removed code that updates MOPS counter. Changed
+ function return value name from "L_var_out" to "result".
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: L_shr_r
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 32 bit long signed integer (Word32 ) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+ var2 = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit shift operation resulted in overflow
+
+ Returns:
+ result = Shifted result w/ rounding (Word32)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function arithmetically shifts the 32 bit input L_var1 right var2
+ positions with rounding. If var2 is negative, the function
+ arithmetically shifts L_var1 left by -var2 and zero fills the -var2 LSB of
+ the result. The result is saturated in case of underflows or overflows, i.e.,
+
+ - 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).
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] L_shr_r() function in basic_op2.c, UMTS GSM AMR speech codec, R99 -
+ Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word32 L_shr_r (Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+* The reference ETSI code uses a global flag for Overflow. In the actual
+* implementation a pointer to Overflow flag is passed in as a parameter to the
+* function L_shr()
+
+ if (var2 > 31)
+ {
+ L_var_out = 0;
+ }
+ else
+ {
+ L_var_out = L_shr (L_var1, var2);
+#if (WMOPS)
+ multiCounter[currCounter].L_shr--;
+#endif
+ if (var2 > 0)
+ {
+ if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)
+ {
+ L_var_out++;
+ }
+ }
+ }
+#if (WMOPS)
+ multiCounter[currCounter].L_shr_r++;
+#endif
+ return (L_var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word32 L_shr_r(register Word32 L_var1, register Word16 var2, Flag *pOverflow)
+{
+ Word32 result;
+
+ if (var2 > 31)
+ {
+ result = 0;
+ }
+ else
+ {
+ result = L_shr(L_var1, var2, pOverflow);
+
+ if (var2 > 0)
+ {
+ if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)
+ {
+ result++;
+ }
+ }
+ }
+ return (result);
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/log2.cpp b/media/libstagefright/codecs/amrnb/common/src/log2.cpp
new file mode 100644
index 0000000..0ada423
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/log2.cpp
@@ -0,0 +1,179 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Filename: /audio/gsm_amr/c/src/log2.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template. Moved Log2_norm
+ function to its own file.
+
+ Description: Changed l_shl.c to l_shl.h in Include section.
+
+ Description: Updated template. Changed function interface to pass in a
+ pointer to overflow flag into the function instead of using a
+ global flag. Changed input pointer names for clarity.
+
+ Description:
+ 1. Eliminated l_shl function knowing that after normalization
+ the left shift factor will not saturate.
+ 2. Eliminated unused include files typedef.h and l_shl.h.
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "log2.h"
+#include "basic_op.h"
+#include "log2_norm.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: log2()
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_x = input value of type Word32
+ pExponent = pointer to the integer part of Log2 of type Word16 whose
+ valid range is: 0 <= value <= 30
+ pFraction = pointer to the fractional part of Log2 of type Word16
+ whose valid range is: 0 <= value < 1
+ pOverflow = pointer to overflow flag
+
+
+ Outputs:
+ pExponent -> integer part of the newly calculated Log2
+ pFraction -> fractional part of the newly calculated Log2
+ pOverflow -> 1 if the log2() operation resulted in saturation
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes logarithm (base2) of the input L_x, where L_x is
+ positive. If L_x is negative or zero, the result is 0.
+
+ This function first normalizes the input L_x and calls the function Log2_norm
+ to calculate the logarithm.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] log2.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void Log2(
+ Word32 L_x, /* (i) : input value */
+ Word16 *pExponent, /* (o) : Integer part of Log2. (range: 0<=val<=30)*/
+ Word16 *pFraction, /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+ Flag *pOverflow /* (i/o) : overflow flag */
+)
+{
+ Word16 exp;
+ Word32 result;
+ OSCL_UNUSED_ARG(pOverflow);
+
+ exp = norm_l(L_x);
+ result = L_x << exp;
+ Log2_norm(result, exp, pExponent, pFraction);
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/log2_norm.cpp b/media/libstagefright/codecs/amrnb/common/src/log2_norm.cpp
new file mode 100644
index 0000000..feda874
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/log2_norm.cpp
@@ -0,0 +1,238 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./audio/gsm-amr/c/src/log2_norm.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for Log2_norm function.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include file.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Modified code to improve performance.
+ 2. Fixed typecasting issue with TI C compiler.
+ 3. Added more comments to the code.
+
+ Description: Removed unnecessary line of code (line 208).
+
+ Description: Removed inclusion of "log2.tab"
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "log2_norm.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Log2_norm
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_x = normalized input value of type Word32
+ exp = number of shifts required to normalize L_x; it is of type Word16
+ exponent = pointer to the integer part of Log2 (of type Word16)
+ whose valid range is: 0 <= value <= 30
+ fraction = pointer to the fractional part of Log2 (of type Word16)
+ whose valid range is: 0 <= value < 1
+
+ Outputs:
+ exponent points to the newly calculated integer part of Log2
+ fraction points to the newly calculated fractional part of Log2
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ table = Log2 table of constants of type Word16
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ The function Log2(L_x) calculates the logarithm of the normalized input
+ buffer L_x. The logarithm 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 = i - 32
+ 5. fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ log2.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+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 = sub (30, exp);
+
+ L_x = L_shr (L_x, 9);
+ i = extract_h (L_x); // Extract b25-b31
+ L_x = L_shr (L_x, 1);
+ a = extract_l (L_x); // Extract b10-b24 of fraction
+ a = a & (Word16) 0x7fff;
+
+ i = sub (i, 32);
+
+ L_y = L_deposit_h (table[i]); // table[i] << 16
+ tmp = sub (table[i], table[i + 1]); // table[i] - table[i+1]
+ L_y = L_msu (L_y, tmp, a); // L_y -= tmp*a*2
+
+ *fraction = extract_h (L_y);
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+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;
+ }
+ else
+ {
+ /* Calculate exponent portion of Log2 */
+ *exponent = 30 - exp;
+
+ /* At this point, L_x > 0 */
+ /* Shift L_x to the right by 10 to extract bits 10-31, */
+ /* which is needed to calculate fractional part of Log2 */
+ L_x >>= 10;
+ i = (Word16)(L_x >> 15); /* Extract b25-b31 */
+ a = L_x & 0x7fff; /* Extract b10-b24 of fraction */
+
+ /* Calculate table index -> subtract by 32 is done for */
+ /* proper table indexing, since 32<=i<=63 (due to normalization) */
+ i -= 32;
+
+ /* Fraction part of Log2 is approximated by using table[] */
+ /* and linear interpolation, i.e., */
+ /* fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2 */
+ L_y = (Word32) log2_tbl[i] << 16; /* table[i] << 16 */
+ tmp = log2_tbl[i] - log2_tbl[i + 1]; /* table[i] - table[i+1] */
+ L_y -= (((Word32) tmp) * a) << 1; /* L_y -= tmp*a*2 */
+
+ *fraction = (Word16)(L_y >> 16);
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/log2_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/log2_tbl.cpp
new file mode 100644
index 0000000..9b9b099
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/log2_tbl.cpp
@@ -0,0 +1,165 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/log2_tbl.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the declaration for log2_tbl[] used by the log2() and
+ log2_norm() function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "log2_norm.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+
+ const Word16 log2_tbl[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
+ };
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] log2.tab, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsfwt.cpp b/media/libstagefright/codecs/amrnb/common/src/lsfwt.cpp
new file mode 100644
index 0000000..6b511f7
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/lsfwt.cpp
@@ -0,0 +1,242 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./audio/gsm-amr/c/src/lsfwt.c
+ Functions: Lsf_wt
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated to accept new parameter, Flag *pOverflow. Placed
+ file in the proper PV Software template.
+
+ Description:
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated math operations that unnecessary checked for
+ saturation, by evaluating the operands
+ 4. Unrolled loops to speed up processing, use decrement loops
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Who: Date:
+ Description:
+
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsf -- Pointer to Word16 -- LSF vector
+
+ Outputs:
+ wf -- Pointer to Word16 -- square of weighting factors
+ pOverflow -- Pointer to type Flag -- Flag set when overflow occurs
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+Compute LSF weighting factors
+
+ d[i] = lsf[i+1] - lsf[i-1]
+
+ The weighting factors are approximated by two line segment
+
+ First segment passes by the following 2 points:
+
+ d[i] = 0Hz wf[i] = 3.347
+ d[i] = 450Hz wf[i] = 1.8
+
+ Second segment passes by the following 2 points:
+
+ d[i] = 450Hz wf[i] = 1.8
+ d[i] = 1500Hz wf[i] = 1.0
+
+ if( d[i] < 450Hz )
+ wf[i] = 3.347 - ( (3.347-1.8) / (450-0)) * d[i]
+ else
+ wf[i] = 1.8 - ( (1.8-1.0) / (1500-450)) * (d[i] - 450)
+
+
+ if( d[i] < 1843)
+ wf[i] = 3427 - (28160*d[i])>>15
+ else
+ wf[i] = 1843 - (6242*(d[i]-1843))>>15
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lsfwt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "lsfwt.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void Lsf_wt(
+ Word16 *lsf, /* input : LSF vector */
+ Word16 *wf, /* output: square of weighting factors */
+ Flag *pOverflow
+)
+{
+ Word16 temp;
+ Word16 wgt_fct;
+ Word16 i;
+ Word16 *p_wf = wf;
+ Word16 *p_lsf = &lsf[0];
+ Word16 *p_lsf_2 = &lsf[1];
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ /* wf[0] = lsf[1] - 0 */
+ *(p_wf++) = *(p_lsf_2++);
+
+ for (i = 4; i != 0 ; i--)
+ {
+ *(p_wf++) = *(p_lsf_2++) - *(p_lsf++);
+ *(p_wf++) = *(p_lsf_2++) - *(p_lsf++);
+ }
+ /*
+ * wf[9] = 4000 - lsf[8]
+ */
+ *(p_wf) = 16384 - *(p_lsf);
+
+ p_wf = wf;
+
+ for (i = 10; i != 0; i--)
+ {
+ /*
+ * (wf[i] - 450);
+ * 1843 == 450 Hz (Q15 considering 7FFF = 8000 Hz)
+ */
+ wgt_fct = *p_wf;
+ temp = wgt_fct - 1843;
+
+ if (temp > 0)
+ {
+ temp = (Word16)(((Word32)temp * 6242) >> 15);
+ wgt_fct = 1843 - temp;
+ }
+ else
+ {
+ temp = (Word16)(((Word32)wgt_fct * 28160) >> 15);
+ wgt_fct = 3427 - temp;
+ }
+
+ *(p_wf++) = wgt_fct << 3;
+
+ } /* for (i = 10; i != 0; i--) */
+
+ return;
+
+} /* Lsf_wt() */
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp.cpp b/media/libstagefright/codecs/amrnb/common/src/lsp.cpp
new file mode 100644
index 0000000..0e3f772
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/lsp.cpp
@@ -0,0 +1,530 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./audio/gsm-amr/c/src/lsp.c
+ Functions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+ Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description: Per review comments, added pOverflow flag to a few forgotten
+ functions. Removed unnecessary include files.
+
+ Description: For lsp_reset() and lsp()
+ 1. Replaced copy() with more efficient memcpy().
+ 2. Eliminated unused include file copy.h.
+
+ Description: For lsp_reset()
+ 1. Modified memcpy() operands order.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+#include <string.h>
+
+#include "lsp.h"
+#include "typedef.h"
+#include "q_plsf.h"
+#include "az_lsp.h"
+#include "int_lpc.h"
+#include "lsp_tab.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: lsp_init (lspState **st)
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = Pointer to type lspState
+
+ Outputs:
+ st = Pointer to type lspState -- values are initialized.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ lsp_init_data = Word16 array.
+
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Initializes lsp state data.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lsp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 lsp_init(lspState **st)
+{
+ lspState* s;
+
+ if (st == (lspState **) NULL)
+ {
+ /* fprintf(stderr, "lsp_init: invalid parameter\n"); */
+ return -1;
+ }
+
+ *st = NULL;
+
+ /* allocate memory */
+ if ((s = (lspState *) malloc(sizeof(lspState))) == NULL)
+ {
+ /* fprintf(stderr, "lsp_init: can not malloc state structure\n"); */
+ return -1;
+ }
+
+ /* Initialize quantization state */
+ if (0 != Q_plsf_init(&s->qSt))
+ {
+ return -1;
+ }
+
+ if (0 != lsp_reset(s))
+ {
+ return -1;
+ }
+
+ *st = s;
+
+ return 0;
+}
+
+
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: lsp_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = Pointer to type lspState
+
+ Outputs:
+ st = Pointer to type lspState -- values are reset.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ resets lsp_state data
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lsp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 lsp_reset(lspState *st)
+{
+
+ if (st == (lspState *) NULL)
+ {
+ /* fprintf(stderr, "lsp_reset: invalid parameter\n"); */
+ return -1;
+ }
+
+ /* Init lsp_old[] */
+ memcpy(st->lsp_old, lsp_init_data, M*sizeof(Word16));
+
+ /* Initialize lsp_old_q[] */
+ memcpy(st->lsp_old_q, st->lsp_old, M*sizeof(Word16));
+
+ /* Reset quantization state */
+ Q_plsf_reset(st->qSt);
+
+ return 0;
+}
+
+
+
+
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: lsp_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = Pointer to type lspState
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Frees memory used by lspState.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lsp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void lsp_exit(lspState **st)
+{
+ if (st == NULL || *st == NULL)
+ return;
+
+ /* Deallocate members */
+ Q_plsf_exit(&(*st)->qSt);
+
+ /* deallocate memory */
+ free(*st);
+ *st = NULL;
+
+ return;
+}
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: lsp
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+
+ Inputs:
+ st = Pointer to type lspState -- State struct
+ req_mode = enum Mode -- requested coder mode
+ used_mode = enum Mode -- used coder mode
+ az = array of type Word16 -- interpolated LP parameters Q12
+
+ Outputs:
+ azQ = array of type Word16 -- quantization interpol. LP parameters Q12
+ lsp_new = array of type Word16 -- new lsp vector
+ anap = Double pointer of type Word16 -- analysis parameters
+ pOverflow = Pointer to type Flag -- Flag set when overflow occurs
+ st = Pointer to type lspState -- State struct
+ az = array of type Word16 -- interpolated LP parameters Q12
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lsp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void lsp(lspState *st, /* i/o : State struct */
+ enum Mode req_mode, /* i : requested coder mode */
+ enum Mode used_mode,/* i : used coder mode */
+ Word16 az[], /* i/o : interpolated LP parameters Q12 */
+ Word16 azQ[], /* o : quantization interpol. LP parameters Q12*/
+ Word16 lsp_new[], /* o : new lsp vector */
+ Word16 **anap, /* o : analysis parameters */
+ Flag *pOverflow) /* o : Flag set when overflow occurs */
+
+{
+ Word16 lsp_new_q[M]; /* LSPs at 4th subframe */
+ Word16 lsp_mid[M], lsp_mid_q[M]; /* LSPs at 2nd subframe */
+
+ Word16 pred_init_i; /* init index for MA prediction in DTX mode */
+
+ if (req_mode == MR122)
+ {
+ Az_lsp(&az[MP1], lsp_mid, st->lsp_old, pOverflow);
+ Az_lsp(&az[MP1 * 3], lsp_new, lsp_mid, pOverflow);
+
+ /*--------------------------------------------------------------------*
+ * Find interpolated LPC parameters in all subframes (both quantized *
+ * and unquantized). *
+ * The interpolated parameters are in array A_t[] of size (M+1)*4 *
+ * and the quantized interpolated parameters are in array Aq_t[] *
+ *--------------------------------------------------------------------*/
+ Int_lpc_1and3_2(st->lsp_old, lsp_mid, lsp_new, az, pOverflow);
+
+ if (used_mode != MRDTX)
+ {
+ /* LSP quantization (lsp_mid[] and lsp_new[] jointly quantized) */
+ Q_plsf_5(
+ st->qSt,
+ lsp_mid,
+ lsp_new,
+ lsp_mid_q,
+ lsp_new_q,
+ *anap,
+ pOverflow);
+
+ Int_lpc_1and3(st->lsp_old_q, lsp_mid_q, lsp_new_q, azQ, pOverflow);
+
+ /* Advance analysis parameters pointer */
+ (*anap) += 5;
+ }
+ }
+ else
+ {
+ Az_lsp(&az[MP1 * 3], lsp_new, st->lsp_old, pOverflow); /* From A(z) to lsp */
+
+ /*--------------------------------------------------------------------*
+ * Find interpolated LPC parameters in all subframes (both quantized *
+ * and unquantized). *
+ * The interpolated parameters are in array A_t[] of size (M+1)*4 *
+ * and the quantized interpolated parameters are in array Aq_t[] *
+ *--------------------------------------------------------------------*/
+
+ Int_lpc_1to3_2(st->lsp_old, lsp_new, az, pOverflow);
+
+ if (used_mode != MRDTX)
+ {
+ /* LSP quantization */
+ Q_plsf_3(
+ st->qSt,
+ req_mode,
+ lsp_new,
+ lsp_new_q,
+ *anap,
+ &pred_init_i,
+ pOverflow);
+
+ Int_lpc_1to3(
+ st->lsp_old_q,
+ lsp_new_q,
+ azQ,
+ pOverflow);
+
+ /* Advance analysis parameters pointer */
+ (*anap) += 3;
+ }
+ }
+
+ /* update the LSPs for the next frame */
+ memcpy(st->lsp_old, lsp_new, M*sizeof(Word16));
+
+ if (used_mode != MRDTX)
+ {
+ memcpy(st->lsp_old_q, lsp_new_q, M*sizeof(Word16));
+ }
+}
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp_az.cpp b/media/libstagefright/codecs/amrnb/common/src/lsp_az.cpp
new file mode 100644
index 0000000..6b7b471
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/lsp_az.cpp
@@ -0,0 +1,555 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./audio/gsm-amr/c/src/lsp_az.c
+ Funtions: Get_lsp_pol
+ Lsp_Az
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template. First attempt at
+ optimizing C code.
+
+ Description: Deleted all Local stores needed/modified. Optimized Lsp_Az
+ function by getting rid of call to L_shr_r function.
+
+ Description: Updated file per comments gathered from Phase 2/3 review.
+
+ Description: Added setting of Overflow flag in the inlined code.
+
+ Description: 1. Optimized Lsp_Az function code.
+ 2. Changed Input/Output definitions by adding Word type.
+
+ Description: Made changes based on review meeting.
+ 1. Removed pseudocode.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Replaced basic_op.h and oper_32b.h with the header files of the
+ math functions used in the file.
+
+ Description: Modified to pass overflow flag through to L_add and L_sub. The
+ flag is passed back to the calling function by pointer reference.
+
+ Description: Removed the id line since it was removed in the header file by
+ Ken.
+
+ Description: Added the write-only variable, pOverflow, to the inputs section.
+
+ Description: For lsp_az() and Get_lsp_pol()
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated math operations that unnecessary checked for
+ saturation, in some cases this by shifting before adding and
+ in other cases by evaluating the operands
+ 4. Unrolled loops to speed up processing
+ 5. Replaced mpy_32_16 by multpilcations in place
+ 6. Eliminated if-else statements for sign extension when
+ right-shifting
+
+ Description: Added casting to eliminate warnings, and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with defined types.
+ Added proper casting (Word32) to some left shifting operations
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains functions that convert line spectral pairs (LSP) to
+ linear predictive (LP) coefficients (filter order = 10). The functions
+ included in this file include Get_lsp_pol, which finds the coefficients of
+ F1(z) and F2(z), and Lsp_Az, which converts LSP to LPC by multiplying
+ F1(z) by 1+z^(-1) and F2(z) by 1-z^(-1), then calculating A(z) = (F1(z) +
+ F2(z))/2.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "lsp_az.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Get_lsp_pol
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsp = pointer to the buffer containing the line spectral pairs (LSP)
+ of type Word16
+ f = pointer to the polynomial of type Word32 to be generated
+
+ pOverflow = pointer set in case where one of the operations overflows.
+ [data type Pointer to Flag]
+
+ Outputs:
+ buffer pointed to by f contains the polynomial generated
+
+ pOverflow = pointer set in case where one of the operations overflows.
+ [data type Pointer to Flag]
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function finds the polynomial F1(z) or F2(z) from the LSPs. If the LSP
+ vector is passed at address 0, F1(z) is computed and if it is passed at
+ address 1, F2(z) is computed.
+
+ This is performed by expanding the product polynomials:
+
+ F1(z) = product ( 1 - 2 lsp[i] z^-1 + z^-2 )
+ i=0,2,4,6,8
+ F2(z) = product ( 1 - 2 lsp[i] z^-1 + z^-2 )
+ i=1,3,5,7,9
+
+ where lsp[] is the LSP vector in the cosine domain.
+
+ The expansion is performed using the following recursion:
+
+ f[0] = 1
+ b = -2.0 * lsp[0]
+ f[1] = b
+ for i=2 to 5 do
+ b = -2.0 * lsp[2*i-2];
+ for j=i-1 down to 2 do
+ f[j] = f[j] + b*f[j-1] + f[j-2];
+ f[1] = f[1] + b;
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lsp_az.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+static void Get_lsp_pol (Word16 *lsp, Word32 *f)
+{
+ Word16 i, j, hi, lo;
+ Word32 t0;
+
+ // f[0] = 1.0;
+ *f = L_mult (4096, 2048);
+ f++;
+ *f = L_msu ((Word32) 0, *lsp, 512); // f[1] = -2.0 * lsp[0];
+ f++;
+ lsp += 2; // Advance lsp pointer
+
+ for (i = 2; i <= 5; i++)
+ {
+ *f = f[-2];
+
+ for (j = 1; j < i; j++, f--)
+ {
+ L_Extract (f[-1], &hi, &lo);
+ t0 = Mpy_32_16 (hi, lo, *lsp); // t0 = f[-1] * lsp
+ t0 = L_shl (t0, 1);
+ *f = L_add (*f, f[-2]); // *f += f[-2]
+ *f = L_sub (*f, t0); // *f -= t0
+ }
+ *f = L_msu (*f, *lsp, 512); // *f -= lsp<<9
+ f += i; // Advance f pointer
+ lsp += 2; // Advance lsp pointer
+ }
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void Get_lsp_pol(
+ Word16 *lsp,
+ Word32 *f,
+ Flag *pOverflow)
+{
+ register Word16 i;
+ register Word16 j;
+
+ Word16 hi;
+ Word16 lo;
+ Word32 t0;
+ OSCL_UNUSED_ARG(pOverflow);
+
+ /* f[0] = 1.0; */
+ *f++ = (Word32) 0x01000000;
+ *f++ = (Word32) - *(lsp++) << 10; /* f[1] = -2.0 * lsp[0]; */
+ lsp++; /* Advance lsp pointer */
+
+ for (i = 2; i <= 5; i++)
+ {
+ *f = *(f - 2);
+
+ for (j = 1; j < i; j++)
+ {
+ hi = (Word16)(*(f - 1) >> 16);
+
+ lo = (Word16)((*(f - 1) >> 1) - ((Word32) hi << 15));
+
+ t0 = ((Word32)hi * *lsp);
+ t0 += ((Word32)lo * *lsp) >> 15;
+
+ *(f) += *(f - 2); /* *f += f[-2] */
+ *(f--) -= t0 << 2; /* *f -= t0 */
+
+ }
+
+ *f -= (Word32)(*lsp++) << 10;
+
+ f += i;
+ lsp++;
+ }
+
+ return;
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Get_lsp_pol_wrapper
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsp = pointer to the buffer containing the line spectral pairs (LSP)
+ of type Word16
+ f = pointer to the polynomial of type Word32 to be generated
+
+ pOverflow = pointer set in case where one of the operations overflows.
+ [data type Pointer to Flag]
+
+ Outputs:
+ buffer pointed to by f contains the polynomial generated
+
+ pOverflow = pointer set in case where one of the operations overflows.
+ [data type Pointer to Flag]
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function provides external access to the static function Get_lsp_pol.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ CALL Get_lsp_pol(lsp = lsp_ptr
+ f = f_ptr )
+ MODIFYING(nothing)
+ RETURNING(nothing)
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Get_lsp_pol_wrapper(
+ Word16 *lsp,
+ Word32 *f,
+ Flag *pOverflow)
+{
+ /*----------------------------------------------------------------------------
+ CALL Get_lsp_pol(lsp = lsp_ptr
+ f = f_ptr )
+ ----------------------------------------------------------------------------*/
+ Get_lsp_pol(lsp, f, pOverflow);
+
+ /*----------------------------------------------------------------------------
+ MODIFYING(nothing)
+ RETURNING(nothing)
+ ----------------------------------------------------------------------------*/
+ return;
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Lsp_Az
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsp = pointer to the buffer containing the line spectral pairs (LSP)
+ of type Word16
+
+ a = pointer to the buffer containing Linear Predictive (LP)
+ coefficients of type Word16 to be generated
+
+ pOverflow = pointer set in case where one of the operations overflows.
+ [data type Pointer to Flag]
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ pOverflow = pointer set in case where one of the operations overflows.
+ [data type Pointer to Flag]
+
+ Pointers and Buffers Modified:
+ a buffer contains the generated Linear Predictive (LP) coefficients
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function converts from the line spectral pairs (LSP) to LP coefficients
+ for a 10th order filter.
+
+ This is done by:
+ (1) Find the coefficients of F1(z) and F2(z) (see Get_lsp_pol)
+ (2) Multiply F1(z) by 1+z^{-1} and F2(z) by 1-z^{-1}
+ (3) A(z) = ( F1(z) + F2(z) ) / 2
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lsp_az.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Lsp_Az (
+ Word16 lsp[], // (i) : line spectral frequencies
+ Word16 a[] // (o) : predictor coefficients (order = 10)
+)
+{
+ Word16 i, j;
+ Word32 f1[6], f2[6];
+ Word32 t0;
+
+ Get_lsp_pol (&lsp[0], f1);
+ Get_lsp_pol (&lsp[1], f2);
+
+ for (i = 5; i > 0; i--)
+ {
+ f1[i] = L_add (f1[i], f1[i - 1]); // f1[i] += f1[i-1];
+ f2[i] = L_sub (f2[i], f2[i - 1]); // f2[i] -= f2[i-1];
+ }
+
+ a[0] = 4096;
+ for (i = 1, j = 10; i <= 5; i++, j--)
+ {
+ t0 = L_add (f1[i], f2[i]); // f1[i] + f2[i]
+ a[i] = extract_l (L_shr_r (t0, 13));
+ t0 = L_sub (f1[i], f2[i]); // f1[i] - f2[i]
+ a[j] = extract_l (L_shr_r (t0, 13));
+ }
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Lsp_Az(
+ Word16 lsp[], /* (i) : line spectral frequencies */
+ Word16 a[], /* (o) : predictor coefficients (order = 10) */
+ Flag *pOverflow /* (o) : overflow flag */
+)
+{
+ register Word16 i;
+ register Word16 j;
+
+ Word32 f1[6];
+ Word32 f2[6];
+ Word32 t0;
+ Word32 t1;
+ Word16 *p_a = &a[0];
+ Word32 *p_f1;
+ Word32 *p_f2;
+
+ Get_lsp_pol(&lsp[0], f1, pOverflow);
+
+ Get_lsp_pol(&lsp[1], f2, pOverflow);
+
+ p_f1 = &f1[5];
+ p_f2 = &f2[5];
+
+ for (i = 5; i > 0; i--)
+ {
+ *(p_f1--) += f1[i-1];
+ *(p_f2--) -= f2[i-1];
+ }
+
+ *(p_a++) = 4096;
+ p_f1 = &f1[1];
+ p_f2 = &f2[1];
+
+ for (i = 1, j = 10; i <= 5; i++, j--)
+ {
+ t0 = *(p_f1) + *(p_f2); /* f1[i] + f2[i] */
+ t1 = *(p_f1++) - *(p_f2++); /* f1[i] - f2[i] */
+
+ t0 = t0 + ((Word32) 1 << 12);
+ t1 = t1 + ((Word32) 1 << 12);
+
+ *(p_a++) = (Word16)(t0 >> 13);
+ a[j] = (Word16)(t1 >> 13);
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp_lsf.cpp b/media/libstagefright/codecs/amrnb/common/src/lsp_lsf.cpp
new file mode 100644
index 0000000..39d6eda
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/lsp_lsf.cpp
@@ -0,0 +1,384 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./audio/gsm-amr/c/src/lsp_lsf.c
+ Functions: Lsp_lsf
+ Lsf_lsp
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+
+ Description: Deleted variables listed in the Local Stores Needed/Modified
+ section.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template and removed unnecessary include files.
+
+ Description: Replaced basic_op.h with the header file of the math functions
+ used in the file.
+
+ Description: Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description: Placed table declarations in a .c file, rather than an included
+ .tab. The tables are now referenced via an extern in this file.
+
+ Description: For Lsp_lsf()
+ 1. Eliminated unused include file typedef.h.
+ 2. Replaced array addressing by pointers
+
+ Description: Replaced "int" and/or "char" with defined types.
+ Added proper casting (Word32) to some left shifting operations
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the functions that convert line spectral pairs (LSP) to
+ line spectral frequencies (LSF) and vice-versa.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "lsp_lsf.h"
+#include "basicop_malloc.h"
+#include "basic_op.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ extern const Word16 table[];
+ extern const Word16 slope[];
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Lsf_lsp
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsf = buffer containing normalized line spectral frequencies; valid
+ range is between 0 and 0.5 (Word16)
+ lsp = buffer containing line spectral pairs; valid range is between
+ -1 and 1 (Word16)
+ m = LPC order (Word16)
+
+ Outputs:
+ lsp contains the newly calculated line spectral pairs
+
+ Returns:
+ None
+
+ Global Variables Used:
+ table = cosine table
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the LSF to LSP transformation using the equation:
+
+ lsf[i] = arccos(lsp[i])/(2*pi)
+
+ The transformation from lsp[i] to lsf[i] is approximated by a look-up table
+ and interpolation.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lsp_lsf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Lsf_lsp (
+ Word16 lsf[], // (i) : lsf[m] normalized (range: 0.0<=val<=0.5)
+ Word16 lsp[], // (o) : lsp[m] (range: -1<=val<1)
+ Word16 m // (i) : LPC order
+)
+{
+ Word16 i, ind, offset;
+ Word32 L_tmp;
+
+ for (i = 0; i < m; i++)
+ {
+ ind = shr (lsf[i], 8); // ind = b8-b15 of lsf[i]
+ offset = lsf[i] & 0x00ff; // offset = b0-b7 of lsf[i]
+
+ // lsp[i] = table[ind]+ ((table[ind+1]-table[ind])*offset) / 256
+
+ L_tmp = L_mult (sub (table[ind + 1], table[ind]), offset);
+ lsp[i] = add (table[ind], extract_l (L_shr (L_tmp, 9)));
+
+ }
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Lsf_lsp(
+ Word16 lsf[], /* (i) : lsf[m] normalized (range: 0.0<=val<=0.5) */
+ Word16 lsp[], /* (o) : lsp[m] (range: -1<=val<1) */
+ Word16 m, /* (i) : LPC order */
+ Flag *pOverflow /* (o) : Flag set when overflow occurs */
+)
+{
+ Word16 i, ind, offset;
+ Word32 L_tmp;
+
+ for (i = 0; i < m; i++)
+ {
+ ind = lsf[i] >> 8; /* ind = b8-b15 of lsf[i] */
+ offset = lsf[i] & 0x00ff; /* offset = b0-b7 of lsf[i] */
+
+ /* lsp[i] = table[ind]+ ((table[ind+1]-table[ind])*offset) / 256 */
+
+ L_tmp = ((Word32)(table[ind + 1] - table[ind]) * offset) >> 8;
+ lsp[i] = add(table[ind], (Word16) L_tmp, pOverflow);
+
+ }
+
+ return;
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Lsp_lsf
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsp = buffer containing line spectral pairs; valid range is between
+ -1 and 1 (Word16)
+ lsf = buffer containing normalized line spectral frequencies; valid
+ range is between 0 and 0.5 (Word16)
+ m = LPC order (Word16)
+
+ Outputs:
+ lsf contains the newly calculated normalized line spectral frequencies
+
+ Returns:
+ None
+
+ Global Variables Used:
+ table = cosine table
+ slope = table to used to calculate inverse cosine
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the LSP to LSF transformation using the equation:
+
+ lsp[i] = cos(2*pi*lsf[i])
+
+ The transformation from lsf[i] to lsp[i] is approximated by a look-up table
+ and interpolation.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lsp_lsf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Lsp_lsf (
+ Word16 lsp[], // (i) : lsp[m] (range: -1<=val<1)
+ Word16 lsf[], // (o) : lsf[m] normalized (range: 0.0<=val<=0.5)
+ Word16 m // (i) : LPC order
+)
+{
+ Word16 i, ind;
+ Word32 L_tmp;
+
+ ind = 63; // begin at end of table -1
+
+ for (i = m - 1; i >= 0; i--)
+ {
+ // find value in table that is just greater than lsp[i]
+
+ while (sub (table[ind], lsp[i]) < 0)
+ {
+ ind--;
+
+ }
+
+ // acos(lsp[i])= ind*256 + ( ( lsp[i]-table[ind] ) *
+ slope[ind] )/4096
+
+ L_tmp = L_mult (sub (lsp[i], table[ind]), slope[ind]);
+ //(lsp[i]-table[ind])*slope[ind])>>12
+ lsf[i] = pv_round (L_shl (L_tmp, 3));
+ lsf[i] = add (lsf[i], shl (ind, 8));
+ }
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Lsp_lsf(
+ Word16 lsp[], /* (i) : lsp[m] (range: -1<=val<1) */
+ Word16 lsf[], /* (o) : lsf[m] normalized (range: 0.0<=val<=0.5) */
+ Word16 m, /* (i) : LPC order */
+ Flag *pOverflow /* (o) : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word16 ind;
+ Word16 temp;
+ Word32 L_tmp;
+ Word16 *p_lsp = &lsp[m-1];
+ Word16 *p_lsf = &lsf[m-1];
+ OSCL_UNUSED_ARG(pOverflow);
+
+ ind = 63; /* begin at end of table -1 */
+
+ for (i = m - 1; i >= 0; i--)
+ {
+ /* find value in table that is just greater than lsp[i] */
+ temp = *(p_lsp--);
+ while (table[ind] < temp)
+ {
+ ind--;
+ }
+
+ /* acos(lsp[i])= ind*256 + ( ( lsp[i]-table[ind] ) *
+ slope[ind] )/4096 */
+
+ L_tmp = (Word32)(temp - table[ind]) * slope[ind];
+
+ /*(lsp[i]-table[ind])*slope[ind])>>12*/
+ L_tmp = (L_tmp + 0x00000800) >> 12;
+
+ *(p_lsf--) = (Word16)(L_tmp) + (ind << 8);
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp_lsf_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/lsp_lsf_tbl.cpp
new file mode 100644
index 0000000..ddeeba4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/lsp_lsf_tbl.cpp
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Filename: /audio/gsm_amr/c/src/lsp_lsf_tbl.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created this file from the reference, lsp_lsf.tab
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+
+ extern const Word16 table[];
+ const Word16 table[65] =
+ {
+ 32767, 32729, 32610, 32413, 32138, 31786, 31357, 30853,
+ 30274, 29622, 28899, 28106, 27246, 26320, 25330, 24279,
+ 23170, 22006, 20788, 19520, 18205, 16846, 15447, 14010,
+ 12540, 11039, 9512, 7962, 6393, 4808, 3212, 1608,
+ 0, -1608, -3212, -4808, -6393, -7962, -9512, -11039,
+ -12540, -14010, -15447, -16846, -18205, -19520, -20788, -22006,
+ -23170, -24279, -25330, -26320, -27246, -28106, -28899, -29622,
+ -30274, -30853, -31357, -31786, -32138, -32413, -32610, -32729,
+ (Word16) 0x8000
+ };
+
+ /* 0x8000 = -32768 (used to silence the compiler) */
+
+ /* slope used to compute y = acos(x) */
+
+ extern const Word16 slope[];
+ const Word16 slope[64] =
+ {
+ -26887, -8812, -5323, -3813, -2979, -2444, -2081, -1811,
+ -1608, -1450, -1322, -1219, -1132, -1059, -998, -946,
+ -901, -861, -827, -797, -772, -750, -730, -713,
+ -699, -687, -677, -668, -662, -657, -654, -652,
+ -652, -654, -657, -662, -668, -677, -687, -699,
+ -713, -730, -750, -772, -797, -827, -861, -901,
+ -946, -998, -1059, -1132, -1219, -1322, -1450, -1608,
+ -1811, -2081, -2444, -2979, -3813, -5323, -8812, -26887
+ };
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/lsp_tab.cpp b/media/libstagefright/codecs/amrnb/common/src/lsp_tab.cpp
new file mode 100644
index 0000000..0a32dd7
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/lsp_tab.cpp
@@ -0,0 +1,188 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: .audio/gsm-amr/c/src/lsp_tab.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition. Removed corresponding header file from Include
+ section.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ File : lsp.tab
+ Purpose : Table for lsp init
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+#include "lsp_tab.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+ const Word16 lsp_init_data[M] = {30000, 26000, 21000, 15000, 8000,
+ 0, -8000, -15000, -21000, -26000
+ };
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL FUNCTION REFERENCES
+ ; Declare functions defined elsewhere and referenced in this module
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; Define all local variables
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Function body here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Return nothing or data or data pointer
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/mult_r.cpp b/media/libstagefright/codecs/amrnb/common/src/mult_r.cpp
new file mode 100644
index 0000000..0777e68
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/mult_r.cpp
@@ -0,0 +1,218 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/mult_r.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the mult_r function. Sync'ed up
+ with the current template and fixed tabs.
+
+ Description: Passing in a pointer to the overflow flag instead of using
+ a global flag.
+
+ Description: Made the following changes based on P2/P3 review:
+ 1) Simplified test to determine if sign extension is necessary
+ 2) Changed the name of pointer "overflow" to "Poverflow"
+ 3) Removed code that updates MOPS counter
+ 4) Updated template and reference section
+
+ Who: Date:
+ Description:
+
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Multiplication function with rounding and overflow control
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: mult_r
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the add operation resulted in overflow
+
+ Returns:
+ L_product_arr = 16-bit limited product of var1 and var2 (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the multiplication of var1 by var2 with rounding, and
+ gives a 16 bit result which is scaled, i.e.:
+ mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and |
+ mult_r(-32768,-32768) = 32767
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] mult_r() function in basicop2.c, UMTS GSM AMR speech codec, R99 -
+ Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 mult_r (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_product_arr;
+
+ L_product_arr = (Word32) var1 *(Word32) var2;
+ L_product_arr += (Word32) 0x00004000L;
+ L_product_arr &= (Word32) 0xffff8000L;
+ L_product_arr >>= 15;
+
+ if (L_product_arr & (Word32) 0x00010000L)
+ {
+ L_product_arr |= (Word32) 0xffff0000L;
+ }
+* The reference ETSI code uses a global flag for Overflow inside the function
+* saturate(). In the actual implementation a pointer to Overflow flag is passed in
+* as a parameter to the function
+
+ var_out = saturate (L_product_arr);
+
+#if (WMOPS)
+ multiCounter[currCounter].mult_r++;
+#endif
+
+ return (var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Word16 mult_r(Word16 var1, Word16 var2, Flag *pOverflow)
+{
+
+ register Word32 L_product_arr;
+
+ L_product_arr = ((Word32) var1) * var2; /* product */
+ L_product_arr += (Word32) 0x00004000L; /* round */
+ L_product_arr >>= 15; /* shift */
+
+ /* sign extend when necessary */
+ L_product_arr |= (Word32) - (L_product_arr & (Word32) 0x00010000L);
+
+ /* Saturate result (if necessary). */
+ /* Replaced function call with in-line code to conserve MIPS, */
+ /* i.e., var_out = saturate (L_product_arr) */
+
+ if (L_product_arr > 0X00007fffL)
+ {
+ *pOverflow = 1;
+ L_product_arr = MAX_16;
+ }
+ else if (L_product_arr < (Word32) 0xffff8000L)
+ {
+ *pOverflow = 1;
+ L_product_arr = MIN_16;
+ }
+
+ return ((Word16) L_product_arr);
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/negate.cpp b/media/libstagefright/codecs/amrnb/common/src/negate.cpp
new file mode 100644
index 0000000..be58d2b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/negate.cpp
@@ -0,0 +1,179 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/src/negate.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the negate function. Sync'ed up with
+ the current template and fixed tabs.
+
+ Description: Removed conditional code that updates WMOPS counter
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ var1 = 16 bit short signed integer (Word16) whose value falls in
+ the range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ var1 = negated value of input (Word16)
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function negates var1 with saturation; saturate in the case where input
+ is -32768: negate(var1) = sub(0,var1).
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] basicop2.c, ETS Version 2.0.0, February 8, 1999
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 negate (Word16 var1)
+{
+ Word16 var_out;
+
+ var_out = (var1 == MIN_16) ? MAX_16 : -var1;
+#if (WMOPS)
+ multiCounter[currCounter].negate++;
+#endif
+ return (var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "negate.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word16 negate(register Word16 var1)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ var1 = (var1 == MIN_16) ? MAX_16 : -var1;
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return (var1);
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/norm_l.cpp b/media/libstagefright/codecs/amrnb/common/src/norm_l.cpp
new file mode 100644
index 0000000..132fed6
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/norm_l.cpp
@@ -0,0 +1,247 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./gsm-amr/c/src/norm_l.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the norm_l function. Sync'ed up
+ with the current template and fixed tabs.
+
+ Description: Updated module description to be the same as the equivalent
+ assembly file (norm_l.asm).
+
+ Description: Removed conditional code that updates WMOPS counter
+
+ Description: Made the following changes
+ 1. Unrolled the search loop to make four comparison per
+ pass, using only four iterations of the loop and saving
+ shifts cycles
+ 2. Updated header and copyright year
+
+ Description: 1. Support for ARM and Linux-ARM assembly instructions.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= var1 <= 0x7fff ffff.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ var_out = number of left shifts need to normalize input (Word16)
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function produces the number of left shifts needed to normalize the 32
+ bit variable L_var1 for positive values on the interval with minimum of
+ 0x40000000 and maximum of 0x7fffffff, and for negative values on the interval
+ with minimum of 0x80000000 and maximum of 0xc0000000. Note that when L_var1
+ is equal to zero, the output var_out is set to zero.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] basicop2.c, ETS Version 2.0.0, February 8, 1999
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+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;
+ }
+ }
+ }
+
+#if (WMOPS)
+ multiCounter[currCounter].norm_l++;
+#endif
+ return (var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+#if !( defined(PV_ARM_V5) || defined(PV_ARM_GCC_V5) )
+Word16 norm_l(register Word32 L_var1)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ register Word16 var_out = 0;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ if (L_var1)
+ {
+
+ Word32 y = L_var1 - (L_var1 < 0);
+ L_var1 = y ^(y >> 31);
+
+
+ while (!(0x40000000L & L_var1))
+ {
+ var_out++;
+ if ((0x20000000L & L_var1))
+ {
+ break;
+ }
+ var_out++;
+ if ((0x10000000L & L_var1))
+ {
+ break;
+ }
+ var_out++;
+ if ((0x08000000L & L_var1))
+ {
+ break;
+ }
+ var_out++;
+ L_var1 <<= 4;
+ }
+ }
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+
+
+ return (var_out);
+}
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/src/norm_s.cpp b/media/libstagefright/codecs/amrnb/common/src/norm_s.cpp
new file mode 100644
index 0000000..8cdcdb8
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/norm_s.cpp
@@ -0,0 +1,242 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/src/norm_s.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the norm_s function. Sync'ed up
+ with the current template and fixed tabs.
+
+ Description: Updated input/output definition and module description to
+ be the same as the equivalent assembly file (norm_s.asm).
+
+ Description: Updated definition of var1 to be the same as that in the
+ assembly file (norm_s.asm).
+
+ Description: Removed conditional code that updates WMOPS counter
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ var1 = 16 bit signed integer of type Word16, whose value falls
+ in the range: 0x8000 <= var1 <= 0x7fff
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ var_out = number of left shifts need to normalize var1 (Word16)
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function produces the number of left shifts needed to normalize the 16
+ bit variable var1 for positive values on the interval with minimum of 0x4000
+ and maximum of 0x7fff, and for negative values on the interval with minimum
+ of 0x8000 and maximum of 0xc000. Note that when var1 is zero, the resulting
+ output var_out is set to zero.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] basicop2.c, ETS Version 2.0.0, February 8, 1999
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 norm_s (Word16 var1)
+{
+ Word16 var_out;
+
+ if (var1 == 0)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if (var1 == (Word16) 0xffff)
+ {
+ var_out = 15;
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var1 = ~var1;
+ }
+ for (var_out = 0; var1 < 0x4000; var_out++)
+ {
+ var1 <<= 1;
+ }
+ }
+ }
+
+#if (WMOPS)
+ multiCounter[currCounter].norm_s++;
+#endif
+ return (var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+#if !( defined(PV_ARM_V5) || defined(PV_ARM_GCC_V5) )
+
+Word16 norm_s(register Word16 var1)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+
+ register Word16 var_out = 0;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ if (var1)
+ {
+ Word16 y = var1 - (var1 < 0);
+ var1 = y ^(y >> 15);
+
+ while (!(0x4000 & var1))
+ {
+ var_out++;
+ if ((0x2000 & var1))
+ {
+ break;
+ }
+ var_out++;
+ if ((0x1000 & var1))
+ {
+ break;
+ }
+ var_out++;
+ if ((0x0800 & var1))
+ {
+ break;
+ }
+ var_out++;
+ var1 <<= 4;
+ }
+ }
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return (var_out);
+}
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/common/src/overflow_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/overflow_tbl.cpp
new file mode 100644
index 0000000..c4a016d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/overflow_tbl.cpp
@@ -0,0 +1,174 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/overflow_tbl.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the declaration for overflow_tbl[] used by the l_shl()
+ and l_shr() functions.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+ const Word32 overflow_tbl [32] = {0x7fffffffL, 0x3fffffffL,
+ 0x1fffffffL, 0x0fffffffL,
+ 0x07ffffffL, 0x03ffffffL,
+ 0x01ffffffL, 0x00ffffffL,
+ 0x007fffffL, 0x003fffffL,
+ 0x001fffffL, 0x000fffffL,
+ 0x0007ffffL, 0x0003ffffL,
+ 0x0001ffffL, 0x0000ffffL,
+ 0x00007fffL, 0x00003fffL,
+ 0x00001fffL, 0x00000fffL,
+ 0x000007ffL, 0x000003ffL,
+ 0x000001ffL, 0x000000ffL,
+ 0x0000007fL, 0x0000003fL,
+ 0x0000001fL, 0x0000000fL,
+ 0x00000007L, 0x00000003L,
+ 0x00000001L, 0x00000000L
+ };
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] l_shl() function in basic_op2.c, UMTS GSM AMR speech codec, R99 -
+ Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/ph_disp_tab.cpp b/media/libstagefright/codecs/amrnb/common/src/ph_disp_tab.cpp
new file mode 100644
index 0000000..d568b78
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/ph_disp_tab.cpp
@@ -0,0 +1,192 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/ph_disp_tab.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the table of impulse responses of the phase dispersion
+ filters. All impulse responses are in Q15
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+ extern const Word16 ph_imp_low_MR795[];
+ const Word16 ph_imp_low_MR795[40] =
+ {
+ 26777, 801, 2505, -683, -1382, 582, 604, -1274, 3511, -5894,
+ 4534, -499, -1940, 3011, -5058, 5614, -1990, -1061, -1459, 4442,
+ -700, -5335, 4609, 452, -589, -3352, 2953, 1267, -1212, -2590,
+ 1731, 3670, -4475, -975, 4391, -2537, 949, -1363, -979, 5734
+ };
+ extern const Word16 ph_imp_mid_MR795[];
+ const Word16 ph_imp_mid_MR795[40] =
+ {
+ 30274, 3831, -4036, 2972, -1048, -1002, 2477, -3043, 2815, -2231,
+ 1753, -1611, 1714, -1775, 1543, -1008, 429, -169, 472, -1264,
+ 2176, -2706, 2523, -1621, 344, 826, -1529, 1724, -1657, 1701,
+ -2063, 2644, -3060, 2897, -1978, 557, 780, -1369, 842, 655
+ };
+
+ extern const Word16 ph_imp_low[];
+ const Word16 ph_imp_low[40] =
+ {
+ 14690, 11518, 1268, -2761, -5671, 7514, -35, -2807, -3040, 4823,
+ 2952, -8424, 3785, 1455, 2179, -8637, 8051, -2103, -1454, 777,
+ 1108, -2385, 2254, -363, -674, -2103, 6046, -5681, 1072, 3123,
+ -5058, 5312, -2329, -3728, 6924, -3889, 675, -1775, 29, 10145
+ };
+ extern const Word16 ph_imp_mid[];
+ const Word16 ph_imp_mid[40] =
+ {
+ 30274, 3831, -4036, 2972, -1048, -1002, 2477, -3043, 2815, -2231,
+ 1753, -1611, 1714, -1775, 1543, -1008, 429, -169, 472, -1264,
+ 2176, -2706, 2523, -1621, 344, 826, -1529, 1724, -1657, 1701,
+ -2063, 2644, -3060, 2897, -1978, 557, 780, -1369, 842, 655
+ };
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ph_disp.tab, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/pow2.cpp b/media/libstagefright/codecs/amrnb/common/src/pow2.cpp
new file mode 100644
index 0000000..a8686f8
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/pow2.cpp
@@ -0,0 +1,202 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/pow2.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template. Changed function interface to pass in a
+ pointer to overflow flag into the function instead of using a
+ global flag. Removed inclusion of "pow2.tab"
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pow2.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Pow2
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ exponent = Integer part whose valid range is: 0 <= value <= 30 (Word16)
+ fraction = Fractional part whose valid range is 0 <= value < 1
+
+ pOverflow = pointer to overflow flag
+
+ Outputs:
+ L_x = Result of the Pow2() computation (Word32)
+ pOverflow -> 1 if the Pow2() function results in saturation
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes L_x = pow(2.0, exponent.fraction)
+
+ 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-exponent) (with rounding)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pow2.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word32 Pow2 ( // (o) : result (range: 0<=val<=0x7fffffff)
+ Word16 exponent, // (i) : Integer part. (range: 0<=val<=30)
+ Word16 fraction // (i) : Fractional part. (range: 0.0<=val<1.0)
+)
+{
+ Word16 exp, i, a, tmp;
+ Word32 L_x;
+
+ L_x = L_mult (fraction, 32); // L_x = fraction<<6
+ i = extract_h (L_x); // Extract b10-b16 of fraction
+ L_x = L_shr (L_x, 1);
+ a = extract_l (L_x); // Extract b0-b9 of fraction
+ a = a & (Word16) 0x7fff;
+
+ L_x = L_deposit_h (table[i]); // table[i] << 16
+ tmp = sub (table[i], table[i + 1]); // table[i] - table[i+1]
+ L_x = L_msu (L_x, tmp, a); // L_x -= tmp*a*2
+
+ exp = sub (30, exponent);
+ L_x = L_shr_r (L_x, exp);
+
+ return (L_x);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Word32 Pow2( /* (o) : result (range: 0<=val<=0x7fffffff) */
+ Word16 exponent, /* (i) : Integer part. (range: 0<=val<=30) */
+ Word16 fraction, /* (i) : Fractional part. (range: 0.0<=val<1.0) */
+ Flag *pOverflow
+)
+{
+ Word16 exp, i, a, tmp;
+ Word32 L_x;
+
+ L_x = L_mult(fraction, 32, pOverflow); /* L_x = fraction<<6 */
+
+ /* Extract b0-b16 of fraction */
+
+ i = ((Word16)(L_x >> 16)) & 31; /* ensure index i is bounded */
+ a = (Word16)((L_x >> 1) & 0x7fff);
+
+ L_x = L_deposit_h(pow2_tbl[i]); /* pow2_tbl[i] << 16 */
+
+ /* pow2_tbl[i] - pow2_tbl[i+1] */
+ tmp = sub(pow2_tbl[i], pow2_tbl[i + 1], pOverflow);
+ L_x = L_msu(L_x, tmp, a, pOverflow); /* L_x -= tmp*a*2 */
+
+ exp = sub(30, exponent, pOverflow);
+ L_x = L_shr_r(L_x, exp, pOverflow);
+
+ return (L_x);
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/pow2_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/pow2_tbl.cpp
new file mode 100644
index 0000000..902ea0f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/pow2_tbl.cpp
@@ -0,0 +1,164 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/pow2_tbl.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the declaration for log2_tbl[] used by the Pow2() function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "pow2.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+
+ const Word16 pow2_tbl[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
+ };
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] pow2.tab, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/pred_lt.cpp b/media/libstagefright/codecs/amrnb/common/src/pred_lt.cpp
new file mode 100644
index 0000000..9163623
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/pred_lt.cpp
@@ -0,0 +1,349 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./audio/gsm-amr/c/src/pred_lt.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template. First attempt at
+ optimizing C code.
+
+ Description: Deleted variables listed in the Local Stores Needed/Modified
+ sections.
+
+ Description: Updated file per comments from Phase 2/3 review.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Fixed typecasting issue with TI C compiler. Updated copyright
+ year.
+
+ Description:
+ (1) Removed instance of static in the const table "inter_6"
+ (2) Changed Overflow from a global to a parameter passed via a pointer.
+ (3) Made numerous small changes to bring code more in line with PV standards.
+
+ Description: For pred_ltp()
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated math operations that unnecessary checked for
+ saturation
+ 4. Unrolled loops to speed up processing, use decrement loops,
+ loaded into memory filter coefficient in linear order for
+ faster execution in main loop.
+ 5. Eliminated call to round by proper initialization
+
+ Description: Replaced "int" and/or "char" with defined types.
+ Added proper casting (Word32) to some left shifting operations
+
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pred_lt.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define UP_SAMP_MAX 6
+#define L_INTER10 (L_INTERPOL-1)
+#define FIR_SIZE (UP_SAMP_MAX*L_INTER10+1)
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/* 1/6 resolution interpolation filter (-3 dB at 3600 Hz) */
+/* Note: the 1/3 resolution filter is simply a subsampled
+ * version of the 1/6 resolution filter, i.e. it uses
+ * every second coefficient:
+ *
+ * inter_3l[k] = inter_6[2*k], 0 <= k <= 3*L_INTER10
+ */
+
+const Word16 inter_6_pred_lt[FIR_SIZE] =
+{
+ 29443,
+ 28346, 25207, 20449, 14701, 8693, 3143,
+ -1352, -4402, -5865, -5850, -4673, -2783,
+ -672, 1211, 2536, 3130, 2991, 2259,
+ 1170, 0, -1001, -1652, -1868, -1666,
+ -1147, -464, 218, 756, 1060, 1099,
+ 904, 550, 135, -245, -514, -634,
+ -602, -451, -231, 0, 191, 308,
+ 340, 296, 198, 78, -36, -120,
+ -163, -165, -132, -79, -19, 34,
+ 73, 91, 89, 70, 38, 0
+};
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Pred_lt_3or6
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ exc = buffer containing the excitation (Word16)
+ T0 = integer pitch lag (Word16)
+ frac = fraction of lag (Word16)
+ L_subfr = number of samples per subframe (Word16)
+ flag3 = flag to indicate the upsampling rate; if set, upsampling
+ rate is 3, otherwise, upsampling rate is 6 (Word16)
+
+ pOverflow = pointer to overflow (Flag)
+
+ Returns:
+ None
+
+ Outputs:
+ exc buffer contains the newly formed adaptive codebook excitation
+ pOverflow -> 1 if the add operation resulted in overflow
+
+ Global Variables Used:
+ inter_6_pred_lt = (1/6) resolution interpolation filter table (Word16)
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes the result of long term prediction with fractional
+ interpolation of resolution 1/3 or 1/6. (Interpolated past excitation).
+
+ The past excitation signal at the given delay is interpolated at
+ the given fraction to build the adaptive codebook excitation.
+ On return exc[0..L_subfr-1] contains the interpolated signal
+ (adaptive codebook excitation).
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pred_lt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Pred_lt_3or6 (
+ 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 flag3 // input : if set, upsampling rate = 3 (6 otherwise)
+)
+{
+ Word16 i, j, k;
+ Word16 *pX0, *pX1, *pX2;
+ const Word16 *pC1, *pC2;
+ Word32 s;
+
+ pX0 = &exc[-T0];
+
+ frac = negate (frac);
+ if (flag3 != 0)
+ {
+ frac = shl (frac, 1); // inter_3l[k] = inter_6[2*k] -> k' = 2*k
+ }
+
+ if (frac < 0)
+ {
+ frac = add (frac, UP_SAMP_MAX);
+ pX0--;
+ }
+
+ for (j = 0; j < L_subfr; j++)
+ {
+ pX1 = pX0++;
+ pX2 = pX0;
+ pC1 = &inter_6[frac];
+ pC2 = &inter_6[sub (UP_SAMP_MAX, frac)];
+
+ s = 0;
+ for (i = 0, k = 0; i < L_INTER10; i++, k += UP_SAMP_MAX)
+ {
+ s = L_mac (s, pX1[-i], pC1[k]);
+ s = L_mac (s, pX2[i], pC2[k]);
+ }
+
+ exc[j] = pv_round (s);
+ }
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Pred_lt_3or6(
+ 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 flag3, /* input : if set, upsampling rate = 3 (6 otherwise) */
+ Flag *pOverflow /* output: if set, overflow occurred in this function */
+)
+{
+ register Word16 i;
+ register Word16 j;
+ register Word16 k;
+
+ Word16 *pX0;
+ Word16 *pX2;
+ Word16 *pX3;
+ Word16 *p_exc;
+ Word16 *pC1;
+ const Word16 *pC1_ref;
+ const Word16 *pC2_ref;
+
+ Word16 Coeff_1[(L_INTER10<<1)];
+
+ Word32 s1;
+ Word32 s2;
+ OSCL_UNUSED_ARG(pOverflow);
+
+ pX0 = &(exc[-T0]);
+
+ /* frac goes between -3 and 3 */
+
+ frac = -frac;
+
+ if (flag3 != 0)
+ {
+ frac <<= 1; /* inter_3l[k] = inter_6[2*k] -> k' = 2*k */
+ }
+
+ if (frac < 0)
+ {
+ frac += UP_SAMP_MAX;
+ pX0--;
+ }
+
+ pC1_ref = &inter_6_pred_lt[frac];
+ pC2_ref = &inter_6_pred_lt[UP_SAMP_MAX-frac];
+
+
+ pC1 = Coeff_1;
+
+ k = 0;
+
+ for (i = L_INTER10 >> 1; i > 0; i--)
+ {
+ *(pC1++) = pC1_ref[k];
+ *(pC1++) = pC2_ref[k];
+ k += UP_SAMP_MAX;
+ *(pC1++) = pC1_ref[k];
+ *(pC1++) = pC2_ref[k];
+ k += UP_SAMP_MAX;
+
+ }
+
+ p_exc = exc;
+
+ for (j = (L_subfr >> 1); j != 0 ; j--)
+ {
+ pX0++;
+ pX2 = pX0;
+ pX3 = pX0++;
+
+ pC1 = Coeff_1;
+
+ s1 = 0x00004000L;
+ s2 = 0x00004000L;
+
+ for (i = L_INTER10 >> 1; i > 0; i--)
+ {
+ s2 += ((Word32) * (pX3--)) * *(pC1);
+ s1 += ((Word32) * (pX3)) * *(pC1++);
+ s1 += ((Word32) * (pX2++)) * *(pC1);
+ s2 += ((Word32) * (pX2)) * *(pC1++);
+ s2 += ((Word32) * (pX3--)) * *(pC1);
+ s1 += ((Word32) * (pX3)) * *(pC1++);
+ s1 += ((Word32) * (pX2++)) * *(pC1);
+ s2 += ((Word32) * (pX2)) * *(pC1++);
+
+ } /* for (i = L_INTER10>>1; i > 0; i--) */
+
+ *(p_exc++) = (Word16)(s1 >> 15);
+ *(p_exc++) = (Word16)(s2 >> 15);
+
+ } /* for (j = (L_subfr>>1); j != 0 ; j--) */
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/q_plsf.cpp b/media/libstagefright/codecs/amrnb/common/src/q_plsf.cpp
new file mode 100644
index 0000000..5d96baa
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/q_plsf.cpp
@@ -0,0 +1,144 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : q_plsf.c
+* Purpose : common part (init, exit, reset) of LSF quantization
+* module (rest in q_plsf_3.c and q_plsf_5.c)
+*
+********************************************************************************
+*/
+
+/*
+********************************************************************************
+* MODULE INCLUDE FILE AND VERSION ID
+********************************************************************************
+*/
+
+#include <stdlib.h>
+
+#include "q_plsf.h"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+#include "basic_op.h"
+
+
+/*
+********************************************************************************
+* PUBLIC PROGRAM CODE
+********************************************************************************
+*/
+
+/*
+**************************************************************************
+*
+* Function : Q_plsf_init
+* Purpose : Allocates memory and initializes state variables
+*
+**************************************************************************
+*/
+Word16 Q_plsf_init(Q_plsfState **state)
+{
+ Q_plsfState* s;
+
+ if (state == (Q_plsfState **) NULL)
+ {
+ /* fprintf(stderr, "Q_plsf_init: invalid parameter\n"); */
+ return -1;
+ }
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (Q_plsfState *) malloc(sizeof(Q_plsfState))) == NULL)
+ {
+ /* fprintf(stderr, "Q_plsf_init: can not malloc state structure\n"); */
+ return -1;
+ }
+
+ Q_plsf_reset(s);
+ *state = s;
+
+ return 0;
+}
+
+/*
+**************************************************************************
+*
+* Function : Q_plsf_reset
+* Purpose : Resets state memory
+*
+**************************************************************************
+*/
+Word16 Q_plsf_reset(Q_plsfState *state)
+{
+ Word16 i;
+
+ if (state == (Q_plsfState *) NULL)
+ {
+ /* fprintf(stderr, "Q_plsf_reset: invalid parameter\n"); */
+ return -1;
+ }
+
+ for (i = 0; i < M; i++)
+ state->past_rq[i] = 0;
+
+ return 0;
+}
+
+/*
+**************************************************************************
+*
+* Function : Q_plsf_exit
+* Purpose : The memory used for state memory is freed
+*
+**************************************************************************
+*/
+void Q_plsf_exit(Q_plsfState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ /* deallocate memory */
+ free(*state);
+ *state = NULL;
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/q_plsf_3.cpp b/media/libstagefright/codecs/amrnb/common/src/q_plsf_3.cpp
new file mode 100644
index 0000000..2b30bf4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/q_plsf_3.cpp
@@ -0,0 +1,1226 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./audio/gsm-amr/c/src/q_plsf_3.c
+ Funtions: Vq_subvec4
+ Test_Vq_subvec4
+ Vq_subvec3
+ Test_Vq_subvec3
+ Q_plsf_3
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template. First attempt at
+ optimizing C code.
+
+ Description: Updated modules per Phase 2/3 review comments. Updated
+ Vq_subvec3 pseudo-code to reflect the new restructured code.
+
+ Description: Added setting of Overflow flag in inlined code.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Replaced basic_op.h with the header file of the math functions
+ used in the file.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Fixed typecasting issue with TI C compiler.
+ 2. Optimized IF stament in Vq_subvec3() function.
+ 3. Updated copyright year.
+
+ Description: Removed redundancy in the Vq_subvec4 function.
+
+ Description: Updated to accept new parameter, Flag *pOverflow.
+
+ Description: Per review comments, added pOverflow flag description
+ to the input/outputs section.
+
+ Description: Corrected missed Overflow global variables -- changed to
+ proper pOverflow.
+
+ Description: Optimized all functions to further reduce clock cycle usage.
+ Updated copyright year.
+
+ Description: Added left shift by 1 in line 1050 of Q_plsf_3().
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the functions that perform the quantization of LSF
+ parameters with first order MA prediction and split by 3 vector
+ quantization (split-VQ).
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include <string.h>
+
+#include "q_plsf.h"
+#include "typedef.h"
+#include "lsp_lsf.h"
+#include "reorder.h"
+#include "lsfwt.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+#define PAST_RQ_INIT_SIZE 8
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ /* Codebooks of LSF prediction residual */
+ extern const Word16 mean_lsf_3[];
+
+ extern const Word16 pred_fac_3[];
+
+ extern const Word16 dico1_lsf_3[];
+ extern const Word16 dico2_lsf_3[];
+ extern const Word16 dico3_lsf_3[];
+
+ extern const Word16 mr515_3_lsf[];
+ extern const Word16 mr795_1_lsf[];
+
+ extern const Word16 past_rq_init[];
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Vq_subvec4
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsf_r1 = pointer to the first LSF residual vector (Q15) (Word16)
+ dico = pointer to the quantization codebook (Q15) (const Word16)
+ wf1 = pointer to the first LSF weighting factor (Q13) (Word16)
+ dico_size = size of quantization codebook (Q0) (Word16)
+
+ Outputs:
+ buffer pointed to by lsf_r1 contains the selected vector
+ pOverflow -- pointer to Flag -- Flag set when overflow occurs
+
+ Returns:
+ index = quantization index (Q0) (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the quantization of a 4-dimensional subvector.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ q_plsf_3.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+static Word16
+Vq_subvec4( // o: quantization index, Q0
+ Word16 * lsf_r1, // i: 1st LSF residual vector, Q15
+ Word16 * dico, // i: quantization codebook, Q15
+ Word16 * wf1, // i: 1st LSF weighting factors, Q13
+ Word16 dico_size) // i: size of quantization codebook, Q0
+{
+ Word16 i, index = 0;
+ Word16 *p_dico, temp;
+ Word32 dist_min, dist;
+
+ dist_min = MAX_32;
+ p_dico = dico;
+
+ for (i = 0; i < dico_size; i++)
+ {
+ temp = sub (lsf_r1[0], *p_dico++);
+ temp = mult (wf1[0], temp);
+ dist = L_mult (temp, temp);
+
+ temp = sub (lsf_r1[1], *p_dico++);
+ temp = mult (wf1[1], temp);
+ dist = L_mac (dist, temp, temp);
+
+ temp = sub (lsf_r1[2], *p_dico++);
+ temp = mult (wf1[2], temp);
+ dist = L_mac (dist, temp, temp);
+
+ temp = sub (lsf_r1[3], *p_dico++);
+ temp = mult (wf1[3], temp);
+ dist = L_mac (dist, temp, temp);
+
+
+ if (L_sub (dist, dist_min) < (Word32) 0)
+ {
+ dist_min = dist;
+ index = i;
+ }
+ }
+
+ // Reading the selected vector
+
+ p_dico = &dico[shl (index, 2)];
+ lsf_r1[0] = *p_dico++;
+ lsf_r1[1] = *p_dico++;
+ lsf_r1[2] = *p_dico++;
+ lsf_r1[3] = *p_dico;
+
+ return index;
+
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static Word16 Vq_subvec4( /* o: quantization index, Q0 */
+ Word16 * lsf_r1, /* i: 1st LSF residual vector, Q15 */
+ const Word16 * dico, /* i: quantization codebook, Q15 */
+ Word16 * wf1, /* i: 1st LSF weighting factors, Q13 */
+ Word16 dico_size, /* i: size of quantization codebook, Q0 */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ register Word16 i;
+ Word16 temp;
+ const Word16 *p_dico;
+ Word16 index = 0;
+ Word32 dist_min;
+ Word32 dist;
+
+ Word16 lsf_r1_0;
+ Word16 lsf_r1_1;
+ Word16 lsf_r1_2;
+ Word16 lsf_r1_3;
+
+ Word16 wf1_0;
+ Word16 wf1_1;
+ Word16 wf1_2;
+ Word16 wf1_3;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ dist_min = MAX_32;
+ p_dico = dico;
+
+ lsf_r1_0 = lsf_r1[0];
+ lsf_r1_1 = lsf_r1[1];
+ lsf_r1_2 = lsf_r1[2];
+ lsf_r1_3 = lsf_r1[3];
+
+ wf1_0 = wf1[0];
+ wf1_1 = wf1[1];
+ wf1_2 = wf1[2];
+ wf1_3 = wf1[3];
+
+ for (i = 0; i < dico_size; i++)
+ {
+ temp = lsf_r1_0 - (*p_dico++);
+ temp = (Word16)((((Word32) wf1_0) * temp) >> 15);
+ dist = ((Word32) temp) * temp;
+
+ temp = lsf_r1_1 - (*p_dico++);
+ temp = (Word16)((((Word32) wf1_1) * temp) >> 15);
+ dist += ((Word32) temp) * temp;
+
+ temp = lsf_r1_2 - (*p_dico++);
+ temp = (Word16)((((Word32) wf1_2) * temp) >> 15);
+ dist += ((Word32) temp) * temp;
+
+ temp = lsf_r1_3 - (*p_dico++);
+ temp = (Word16)((((Word32) wf1_3) * temp) >> 15);
+ dist += ((Word32) temp) * temp;
+
+ if (dist < dist_min)
+ {
+ dist_min = dist;
+ index = i;
+ }
+ }
+
+ /* Reading the selected vector */
+
+ p_dico = dico + (index << 2);
+ *lsf_r1++ = *p_dico++;
+ *lsf_r1++ = *p_dico++;
+ *lsf_r1++ = *p_dico++;
+ *lsf_r1 = *p_dico;
+
+ return(index);
+
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Test_Vq_subvec4
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsf_r1 = pointer to the first LSF residual vector (Q15) (Word16)
+ dico = pointer to the quantization codebook (Q15) (const Word16)
+ wf1 = pointer to the first LSF weighting factor (Q13) (Word16)
+ dico_size = size of quantization codebook (Q0) (Word16)
+
+ Outputs:
+ buffer pointed to by lsf_r1 contains the selected vector
+ pOverflow -- pointer to Flag -- Flag set when overflow occurs
+
+ Returns:
+ index = quantization index (Q0) (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function calls the static function Vq_subvec4. It is used for testing
+ purposes only
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+ CALL Vq_subvec4(lsf_r1 = lsf_r1
+ dico = dico
+ wf1 = wf1
+ dico_size = dico_size)
+ MODIFYING(nothing)
+ RETURNING(index = tst_index4)
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Test_Vq_subvec4(
+ Word16 * lsf_r1,
+ const Word16 * dico,
+ Word16 * wf1,
+ Word16 dico_size,
+ Flag *pOverflow)
+{
+ Word16 tst_index4 = 0;
+
+ /*------------------------------------------------------------------------
+ CALL Vq_subvec4(lsf_r1 = lsf_r1
+ dico = dico
+ wf1 = wf1
+ dico_size = dico_size)
+ MODIFYING(nothing)
+ RETURNING(index = index)
+ ------------------------------------------------------------------------*/
+ tst_index4 =
+ Vq_subvec4(
+ lsf_r1,
+ dico,
+ wf1,
+ dico_size,
+ pOverflow);
+
+ return(tst_index4);
+
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Vq_subvec3
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsf_r1 = pointer to the first LSF residual vector (Q15) (Word16)
+ dico = pointer to the quantization codebook (Q15) (const Word16)
+ wf1 = pointer to the first LSF weighting factor (Q13) (Word16)
+ dico_size = size of quantization codebook (Q0) (Word16)
+ use_half = flag to indicate use of every second entry in the
+ codebook (Flag)
+
+ Outputs:
+ buffer pointed to by lsf_r1 contains the selected vector
+ pOverflow -- pointer to Flag -- Flag set when overflow occurs
+
+ Returns:
+ index = quantization index (Q0) (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the quantization of a 3 dimensional subvector.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ q_plsf_3.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+static Word16
+Vq_subvec3( // o: quantization index, Q0
+ Word16 * lsf_r1, // i: 1st LSF residual vector, Q15
+ Word16 * dico, // i: quantization codebook, Q15
+ Word16 * wf1, // i: 1st LSF weighting factors, Q13
+ Word16 dico_size, // i: size of quantization codebook, Q0
+ Flag use_half) // i: use every second entry in codebook
+{
+ Word16 i, index = 0;
+ Word16 *p_dico, temp;
+ Word32 dist_min, dist;
+
+ dist_min = MAX_32;
+ p_dico = dico;
+
+ if (use_half == 0) {
+ for (i = 0; i < dico_size; i++)
+ {
+ temp = sub(lsf_r1[0], *p_dico++);
+ temp = mult(wf1[0], temp);
+ dist = L_mult(temp, temp);
+
+ temp = sub(lsf_r1[1], *p_dico++);
+ temp = mult(wf1[1], temp);
+ dist = L_mac(dist, temp, temp);
+
+ temp = sub(lsf_r1[2], *p_dico++);
+ temp = mult(wf1[2], temp);
+ dist = L_mac(dist, temp, temp);
+
+ if (L_sub(dist, dist_min) < (Word32) 0) {
+ dist_min = dist;
+ index = i;
+ }
+ }
+ p_dico = &dico[add(index, add(index, index))];
+ }
+ else
+ {
+ for (i = 0; i < dico_size; i++)
+ {
+ temp = sub(lsf_r1[0], *p_dico++);
+ temp = mult(wf1[0], temp);
+ dist = L_mult(temp, temp);
+
+ temp = sub(lsf_r1[1], *p_dico++);
+ temp = mult(wf1[1], temp);
+ dist = L_mac(dist, temp, temp);
+
+ temp = sub(lsf_r1[2], *p_dico++);
+ temp = mult(wf1[2], temp);
+ dist = L_mac(dist, temp, temp);
+
+ if (L_sub(dist, dist_min) < (Word32) 0)
+ {
+ dist_min = dist;
+ index = i;
+ }
+ p_dico = p_dico + 3; add(0,0);
+ }
+ p_dico = &dico[shl(add(index, add(index, index)),1)];
+ }
+
+
+ // Reading the selected vector
+ lsf_r1[0] = *p_dico++;
+ lsf_r1[1] = *p_dico++;
+ lsf_r1[2] = *p_dico++;
+
+ return index;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static Word16 Vq_subvec3( /* o: quantization index, Q0 */
+ Word16 * lsf_r1, /* i: 1st LSF residual vector, Q15 */
+ const Word16 * dico, /* i: quantization codebook, Q15 */
+ Word16 * wf1, /* i: 1st LSF weighting factors, Q13 */
+ Word16 dico_size, /* i: size of quantization codebook, Q0 */
+ Flag use_half, /* i: use every second entry in codebook */
+ Flag *pOverflow) /* o : Flag set when overflow occurs */
+{
+ register Word16 i;
+ Word16 temp;
+
+ const Word16 *p_dico;
+
+ Word16 p_dico_index = 0;
+ Word16 index = 0;
+
+ Word32 dist_min;
+ Word32 dist;
+
+ Word16 lsf_r1_0;
+ Word16 lsf_r1_1;
+ Word16 lsf_r1_2;
+
+ Word16 wf1_0;
+ Word16 wf1_1;
+ Word16 wf1_2;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ dist_min = MAX_32;
+ p_dico = dico;
+
+ lsf_r1_0 = lsf_r1[0];
+ lsf_r1_1 = lsf_r1[1];
+ lsf_r1_2 = lsf_r1[2];
+
+ wf1_0 = wf1[0];
+ wf1_1 = wf1[1];
+ wf1_2 = wf1[2];
+
+ if (use_half != 0)
+ {
+ p_dico_index = 3;
+ }
+
+ for (i = 0; i < dico_size; i++)
+ {
+ temp = lsf_r1_0 - (*p_dico++);
+ temp = (Word16)((((Word32) wf1_0) * temp) >> 15);
+ dist = ((Word32) temp) * temp;
+
+ temp = lsf_r1_1 - (*p_dico++);
+ temp = (Word16)((((Word32) wf1_1) * temp) >> 15);
+ dist += ((Word32) temp) * temp;
+
+ temp = lsf_r1_2 - (*p_dico++);
+ temp = (Word16)((((Word32) wf1_2) * temp) >> 15);
+ dist += ((Word32) temp) * temp;
+
+ if (dist < dist_min)
+ {
+ dist_min = dist;
+ index = i;
+ }
+
+ p_dico = p_dico + p_dico_index;
+ }
+
+ p_dico = dico + (3 * index);
+
+ if (use_half != 0)
+ {
+ p_dico += (3 * index);
+ }
+
+ /* Reading the selected vector */
+ *lsf_r1++ = *p_dico++;
+ *lsf_r1++ = *p_dico++;
+ *lsf_r1 = *p_dico;
+
+ return(index);
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Test_Vq_subvec3
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsf_r1 = pointer to the first LSF residual vector (Q15) (Word16)
+ dico = pointer to the quantization codebook (Q15) (const Word16)
+ wf1 = pointer to the first LSF weighting factor (Q13) (Word16)
+ dico_size = size of quantization codebook (Q0) (Word16)
+ use_half = flag to indicate use of every second entry in the
+ codebook (Flag)
+
+ Outputs:
+ buffer pointed to by lsf_r1 contains the selected vector
+ pOverflow -- pointer to Flag -- Flag set when overflow occurs
+
+ Returns:
+ index = quantization index (Q0) (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function calls the static function Vq_subvec3. It is used for testing
+ purposes only
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ CALL Vq_subvec3(lsf_r1 = lsf_r1
+ dico = dico
+ wf1 = wf1
+ dico_size = dico_size
+ use_half = use_half)
+ MODIFYING(nothing)
+ RETURNING(index = tst_index3)
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Test_Vq_subvec3(
+ Word16 * lsf_r1,
+ const Word16 * dico,
+ Word16 * wf1,
+ Word16 dico_size,
+ Flag use_half,
+ Flag *pOverflow)
+{
+ Word16 tst_index3 = 0;
+
+ /*------------------------------------------------------------------------
+ CALL Vq_subvec3(lsf_r1 = lsf_r1
+ dico = dico
+ wf1 = wf1
+ dico_size = dico_size
+ use_half = use_half)
+ MODIFYING(nothing)
+ RETURNING(index = index)
+ ------------------------------------------------------------------------*/
+ tst_index3 =
+ Vq_subvec3(
+ lsf_r1,
+ dico,
+ wf1,
+ dico_size,
+ use_half,
+ pOverflow);
+
+ return(tst_index3);
+
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Q_plsf_3
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to structures of type Q_plsfState (Q_plsfState)
+ mode = coder mode (enum)
+ lsp1 = pointer to the first LSP vector (Word16)
+ lsp1_q = pointer to the quantized first LSP vector (Word16)
+ indice = pointer to the quantization indices of 3 vectors (Word16)
+ pred_init_i = pointer to the index of the initial value for
+ MA prediction in DTX mode (Word16)
+
+ Outputs:
+ lsp1_q points to a vector containing the new quantized LSPs
+ indice points to the new quantization indices of 3 vectors
+ pred_init_i points to the new initial index for MA prediction
+ in DTX mode
+ past_rq field of structure pointed to by st contains the current
+ quantized LSF parameters
+ pOverflow -- pointer to Flag -- Flag set when overflow occurs
+
+ Returns:
+ None
+
+ Global Variables Used:
+ pred_fac = table containing prediction factors (const Word16)
+ dico1_lsf = quantization table for split_MQ of 2 sets of LSFs
+ in a 20 ms frame (const Word16)
+ dico2_lsf = quantization table for split_MQ of 2 sets of LSFs
+ in a 20 ms frame (const Word16)
+ dico3_lsf = quantization table for split_MQ of 2 sets of LSFs
+ in a 20 ms frame (const Word16)
+ mr515_3_lsf = third codebook for MR475 and MR515 modes (const Word16)
+ mr795_1_lsf = first codebook for MR795 mode (const Word16)
+ mean_lsf = table of mean LSFs (const Word16)
+ past_rq_init = initalization table for MA predictor in DTX mode
+ (const Word16)
+
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs quantization of LSF parameters with 1st order MA
+ prediction and split by 3 vector quantization (split-VQ)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ q_plsf_3.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Q_plsf_3(
+ Q_plsfState *st, // i/o: state struct
+ enum Mode mode, // i : coder mode
+ Word16 *lsp1, // i : 1st LSP vector Q15
+ Word16 *lsp1_q, // o : quantized 1st LSP vector Q15
+ Word16 *indice, // o : quantization indices of 3 vectors Q0
+ Word16 *pred_init_i // o : init index for MA prediction in DTX mode
+)
+{
+ Word16 i, j;
+ Word16 lsf1[M], wf1[M], lsf_p[M], lsf_r1[M];
+ Word16 lsf1_q[M];
+
+ Word32 L_pred_init_err;
+ Word32 L_min_pred_init_err;
+ Word16 temp_r1[M];
+ Word16 temp_p[M];
+
+ // convert LSFs to normalize frequency domain 0..16384
+
+ Lsp_lsf(lsp1, lsf1, M);
+
+ // compute LSF weighting factors (Q13)
+
+ Lsf_wt(lsf1, wf1);
+
+ // Compute predicted LSF and prediction error
+ if (test(), sub(mode, MRDTX) != 0)
+ {
+ for (i = 0; i < M; i++)
+ {
+ lsf_p[i] = add(mean_lsf[i],
+ mult(st->past_rq[i],
+ pred_fac[i]));
+ lsf_r1[i] = sub(lsf1[i], lsf_p[i]);
+ }
+ }
+ else
+ {
+ // DTX mode, search the init vector that yields
+ // lowest prediction resuidual energy
+ *pred_init_i = 0;
+ L_min_pred_init_err = 0x7fffffff; // 2^31 - 1
+ for (j = 0; j < PAST_RQ_INIT_SIZE; j++)
+ {
+ L_pred_init_err = 0;
+ for (i = 0; i < M; i++)
+ {
+ temp_p[i] = add(mean_lsf[i], past_rq_init[j*M+i]);
+ temp_r1[i] = sub(lsf1[i],temp_p[i]);
+ L_pred_init_err = L_mac(L_pred_init_err, temp_r1[i], temp_r1[i]);
+ } // next i
+
+
+ if (L_sub(L_pred_init_err, L_min_pred_init_err) < (Word32) 0)
+ {
+ L_min_pred_init_err = L_pred_init_err;
+ Copy(temp_r1, lsf_r1, M);
+ Copy(temp_p, lsf_p, M);
+ // Set zerom
+ Copy(&past_rq_init[j*M], st->past_rq, M);
+ *pred_init_i = j;
+ } // endif
+ } // next j
+ } // endif MRDTX
+
+ //---- Split-VQ of prediction error ----
+ if (sub (mode, MR475) == 0 || sub (mode, MR515) == 0)
+ { // MR475, MR515
+
+
+ indice[0] = Vq_subvec3(&lsf_r1[0], dico1_lsf, &wf1[0], DICO1_SIZE, 0);
+
+ indice[1] = Vq_subvec3(&lsf_r1[3], dico2_lsf, &wf1[3], DICO2_SIZE/2, 1);
+
+ indice[2] = Vq_subvec4(&lsf_r1[6], mr515_3_lsf, &wf1[6], MR515_3_SIZE);
+
+ }
+ else if (sub (mode, MR795) == 0)
+ { // MR795
+
+
+ indice[0] = Vq_subvec3(&lsf_r1[0], mr795_1_lsf, &wf1[0], MR795_1_SIZE, 0);
+
+ indice[1] = Vq_subvec3(&lsf_r1[3], dico2_lsf, &wf1[3], DICO2_SIZE, 0);
+
+ indice[2] = Vq_subvec4(&lsf_r1[6], dico3_lsf, &wf1[6], DICO3_SIZE);
+
+ }
+ else
+ { // MR59, MR67, MR74, MR102 , MRDTX
+
+
+ indice[0] = Vq_subvec3(&lsf_r1[0], dico1_lsf, &wf1[0], DICO1_SIZE, 0);
+
+ indice[1] = Vq_subvec3(&lsf_r1[3], dico2_lsf, &wf1[3], DICO2_SIZE, 0);
+
+ indice[2] = Vq_subvec4(&lsf_r1[6], dico3_lsf, &wf1[6], DICO3_SIZE);
+
+ }
+
+
+ // Compute quantized LSFs and update the past quantized residual
+
+ for (i = 0; i < M; i++)
+ {
+ lsf1_q[i] = add(lsf_r1[i], lsf_p[i]);
+ st->past_rq[i] = lsf_r1[i];
+ }
+
+ // verification that LSFs has mimimum distance of LSF_GAP Hz
+
+ Reorder_lsf(lsf1_q, LSF_GAP, M);
+
+ // convert LSFs to the cosine domain
+
+ Lsf_lsp(lsf1_q, lsp1_q, M);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Q_plsf_3(
+ Q_plsfState *st, /* i/o: state struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 *lsp1, /* i : 1st LSP vector Q15 */
+ Word16 *lsp1_q, /* o : quantized 1st LSP vector Q15 */
+ Word16 *indice, /* o : quantization indices of 3 vectors Q0 */
+ Word16 *pred_init_i,/* o : init index for MA prediction in DTX mode */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ register Word16 i, j;
+ Word16 lsf1[M];
+ Word16 wf1[M];
+ Word16 lsf_p[M];
+ Word16 lsf_r1[M];
+ Word16 lsf1_q[M];
+
+ Word32 L_pred_init_err;
+ Word32 L_min_pred_init_err;
+ Word32 L_temp;
+ Word16 temp_r1[M];
+ Word16 temp_p[M];
+ Word16 temp;
+
+ /* convert LSFs to normalize frequency domain 0..16384 */
+
+ Lsp_lsf(
+ lsp1,
+ lsf1,
+ M,
+ pOverflow);
+
+ /* compute LSF weighting factors (Q13) */
+
+ Lsf_wt(
+ lsf1,
+ wf1,
+ pOverflow);
+
+ /* Compute predicted LSF and prediction error */
+ if (mode != MRDTX)
+ {
+ for (i = 0; i < M; i++)
+ {
+ temp = (Word16)((((Word32) st->past_rq[i]) *
+ (*(pred_fac_3 + i))) >> 15);
+
+ *(lsf_p + i) = *(mean_lsf_3 + i) + temp;
+
+ *(lsf_r1 + i) = *(lsf1 + i) - *(lsf_p + i);
+ }
+ }
+ else
+ {
+ /* DTX mode, search the init vector that yields */
+ /* lowest prediction resuidual energy */
+ *pred_init_i = 0;
+ L_min_pred_init_err = 0x7fffffff; /* 2^31 - 1 */
+
+ for (j = 0; j < PAST_RQ_INIT_SIZE; j++)
+ {
+ L_pred_init_err = 0;
+ for (i = 0; i < M; i++)
+ {
+ *(temp_p + i) = *(mean_lsf_3 + i) + *(past_rq_init + j * M + i);
+
+ *(temp_r1 + i) = *(lsf1 + i) - *(temp_p + i);
+
+ L_temp = ((Word32) * (temp_r1 + i)) * *(temp_r1 + i);
+
+ L_pred_init_err = L_pred_init_err + (L_temp << 1);
+
+ } /* next i */
+
+
+ if (L_pred_init_err < L_min_pred_init_err)
+ {
+ L_min_pred_init_err = L_pred_init_err;
+
+ memcpy(
+ lsf_r1,
+ temp_r1,
+ M*sizeof(Word16));
+
+ memcpy(
+ lsf_p,
+ temp_p,
+ M*sizeof(Word16));
+
+ /* Set zerom */
+ memcpy(
+ st->past_rq,
+ &past_rq_init[j*M],
+ M*sizeof(Word16));
+
+ *pred_init_i = j;
+
+ } /* endif */
+ } /* next j */
+ } /* endif MRDTX */
+
+ /*---- Split-VQ of prediction error ----*/
+ if ((mode == MR475) || (mode == MR515))
+ { /* MR475, MR515 */
+
+ *indice =
+ Vq_subvec3(
+ lsf_r1,
+ dico1_lsf_3,
+ wf1,
+ DICO1_SIZE,
+ 0,
+ pOverflow);
+
+ *(indice + 1) =
+ Vq_subvec3(
+ lsf_r1 + 3,
+ dico2_lsf_3,
+ wf1 + 3,
+ DICO2_SIZE / 2,
+ 1,
+ pOverflow);
+
+ *(indice + 2) =
+ Vq_subvec4(
+ lsf_r1 + 6,
+ mr515_3_lsf,
+ wf1 + 6,
+ MR515_3_SIZE,
+ pOverflow);
+
+ }
+ else if (mode == MR795)
+ { /* MR795 */
+
+ *indice =
+ Vq_subvec3(
+ lsf_r1,
+ mr795_1_lsf,
+ wf1,
+ MR795_1_SIZE,
+ 0,
+ pOverflow);
+
+ *(indice + 1) =
+ Vq_subvec3(
+ lsf_r1 + 3,
+ dico2_lsf_3,
+ wf1 + 3,
+ DICO2_SIZE,
+ 0,
+ pOverflow);
+
+ *(indice + 2) =
+ Vq_subvec4(
+ lsf_r1 + 6,
+ dico3_lsf_3,
+ wf1 + 6,
+ DICO3_SIZE,
+ pOverflow);
+
+ }
+ else
+ { /* MR59, MR67, MR74, MR102 , MRDTX */
+
+ *indice =
+ Vq_subvec3(
+ lsf_r1,
+ dico1_lsf_3,
+ wf1,
+ DICO1_SIZE,
+ 0,
+ pOverflow);
+
+ *(indice + 1) =
+ Vq_subvec3(
+ lsf_r1 + 3,
+ dico2_lsf_3,
+ wf1 + 3,
+ DICO2_SIZE,
+ 0,
+ pOverflow);
+
+ *(indice + 2) =
+ Vq_subvec4(
+ lsf_r1 + 6,
+ dico3_lsf_3,
+ wf1 + 6,
+ DICO3_SIZE,
+ pOverflow);
+
+ }
+
+
+ /* Compute quantized LSFs and update the past quantized residual */
+
+ for (i = 0; i < M; i++)
+ {
+ *(lsf1_q + i) = *(lsf_r1 + i) + *(lsf_p + i);
+ st->past_rq[i] = *(lsf_r1 + i);
+ }
+
+ /* verification that LSFs has mimimum distance of LSF_GAP Hz */
+
+ Reorder_lsf(
+ lsf1_q,
+ LSF_GAP,
+ M,
+ pOverflow);
+
+ /* convert LSFs to the cosine domain */
+
+ Lsf_lsp(
+ lsf1_q,
+ lsp1_q,
+ M,
+ pOverflow);
+
+ return;
+
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/q_plsf_3_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/q_plsf_3_tbl.cpp
new file mode 100644
index 0000000..56c13e7
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/q_plsf_3_tbl.cpp
@@ -0,0 +1,2096 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/q_plsf_3_tbl.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created this file from the reference, q_plsf_3_tbl.tab
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "q_plsf_3_tbl.h"
+
+/*--------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : q_plsf_3.tab
+* Purpose : Table for routine LSF VQ.
+* $Id $
+*
+********************************************************************************
+*/
+
+
+/* initalization table for MA predictor in dtx mode */
+const Word16 past_rq_init[80] =
+{
+ -258, -318, -439, -634, -656, -773, -711, -502, -268, -193,
+ -2, 125, 122, -39, -9, 105, 129, 283, 372, 575,
+ -277, -324, -197, -487, -445, -362, -292, -27, 177, 543,
+ 342, 517, 516, 130, 27, -104, -120, -140, -74, -56,
+ -564, -943, -1520, -965, -814, -526, -322, -2, 159, 657,
+ -312, -284, -386, -597, -493, -526, -418, -229, 105, 449,
+ -557, -870, -1075, -919, -950, -752, -709, -316, 62, 486,
+ -314, -191, -203, -330, -160, -103, -51, 131, 338, 515
+};
+
+
+const Word16 mean_lsf_3[10] =
+{
+ 1546,
+ 2272,
+ 3778,
+ 5488,
+ 6972,
+ 8382,
+ 10047,
+ 11229,
+ 12766,
+ 13714
+};
+
+
+const Word16 pred_fac_3[10] =
+{
+ 9556,
+ 10769,
+ 12571,
+ 13292,
+ 14381,
+ 11651,
+ 10588,
+ 9767,
+ 8593,
+ 6484
+};
+
+
+
+/* first codebook from IS641 */
+
+const Word16 dico1_lsf_3[DICO1_SIZE*3] =
+{
+ 6, 82, -131,
+ 154, -56, -735,
+ 183, -65, -265,
+ 9, -210, -361,
+ 113, 718, 1817,
+ 1010, 1214, 1573,
+ 857, 1333, 2276,
+ 827, 1568, 1933,
+ 717, 1989, 2206,
+ 838, 1172, 1823,
+ 721, 1000, 2154,
+ 286, 476, 1509,
+ -247, -531, 230,
+ 147, -82, 569,
+ 26, -177, -944,
+ -27, -273, 692,
+ -164, -264, -183,
+ 224, 790, 1039,
+ 899, 946, 601,
+ 485, 771, 1150,
+ 524, 677, 903,
+ -140, 375, 778,
+ 410, 676, 429,
+ 301, 530, 1009,
+ 719, 646, 38,
+ 226, 367, 40,
+ 145, -45, -505,
+ 290, 121, -121,
+ 302, 127, 166,
+ -124, -383, -956,
+ -358, -455, -977,
+ 715, 878, 894,
+ 978, 923, 211,
+ 477, 272, 64,
+ 188, -78, 17,
+ -143, -65, 38,
+ 643, 586, 621,
+ -134, -426, -651,
+ 347, 545, 2820,
+ 1188, 2726, 2442,
+ 142, -80, 1735,
+ 283, 130, 461,
+ -262, -399, -1145,
+ -411, 155, 430,
+ 329, 375, 779,
+ 53, -226, -139,
+ -129, -236, 1682,
+ 285, 744, 1327,
+ 738, 697, 1664,
+ 312, 409, 266,
+ 325, 720, 135,
+ 1, 221, 453,
+ 8, 203, 145,
+ 299, 640, 760,
+ 29, 468, 638,
+ 103, 429, 379,
+ 420, 954, 932,
+ 1326, 1210, 1258,
+ 704, 1012, 1152,
+ -166, -444, -266,
+ -316, -130, -376,
+ 191, 1151, 1904,
+ -240, -543, -1260,
+ -112, 268, 1207,
+ 70, 1062, 1583,
+ 278, 1360, 1574,
+ -258, -272, -768,
+ 19, 563, 2240,
+ -3, -265, 135,
+ -295, -591, -388,
+ 140, 354, -206,
+ -260, -504, -795,
+ -433, -718, -1319,
+ 109, 331, 962,
+ -429, -87, 652,
+ -296, 426, 1019,
+ -239, 775, 851,
+ 489, 1334, 1073,
+ -334, -332, 25,
+ 543, 1206, 1807,
+ 326, 61, 727,
+ 578, 849, 1405,
+ -208, -277, 329,
+ -152, 64, 669,
+ -434, -678, -727,
+ -454, -71, 251,
+ 605, 480, 254,
+ -482, 11, 996,
+ -289, 395, 486,
+ 722, 1049, 1440,
+ -30, -316, -786,
+ -106, -115, -619,
+ 861, 1474, 1412,
+ 1055, 1366, 1184,
+ 812, 1237, 925,
+ 42, -251, -576,
+ 342, 141, -454,
+ -168, -80, 1359,
+ -342, -656, -1763,
+ 100, 821, 725,
+ 990, 747, 800,
+ 332, 440, 568,
+ 663, 379, 852,
+ 112, 165, -369,
+ 597, 910, 282,
+ -8, 834, 1281,
+ -352, 572, 695,
+ 462, 2246, 1806,
+ 345, 190, 1374,
+ 416, 915, 2166,
+ 168, -82, 280,
+ -516, -446, 840,
+ 47, 533, 44,
+ -362, -711, -1143,
+ 22, 193, 1472,
+ -85, 233, 1813,
+ -62, 579, 1504,
+ 550, 944, 1749,
+ 723, 650, 1148,
+ 972, 884, 1395,
+ -425, 643, 0,
+ 1000, 952, 1098,
+ 249, 1446, 672,
+ -334, -87, 2172,
+ -554, 1882, 2672,
+ 140, 1826, 1853,
+ 920, 1749, 2590,
+ 1076, 1933, 2038,
+ -137, -443, -1555,
+ 1269, 1174, 468,
+ -493, -122, 1521,
+ -451, 1033, 1214,
+ 482, 1695, 1118,
+ 815, 649, 384,
+ -446, -692, 107,
+ -319, -605, -118,
+ -207, -505, 525,
+ -468, -12, 2736,
+ 75, 1934, 1305,
+ 880, 2358, 2267,
+ 1285, 1575, 2004,
+ -48, -304, -1186,
+ -435, -461, -251,
+ -366, -404, -547,
+ -289, -605, -597,
+ -538, -810, -165,
+ -120, 3, 356,
+ 639, 1241, 1502,
+ 96, 177, 750,
+ -435, -585, -1174,
+ -356, 109, -79,
+ -485, 288, 2005,
+ 9, 1116, 731,
+ 880, 2134, 946,
+ -265, 1585, 1065,
+ 1157, 1210, 843,
+ -498, -668, 431,
+ 374, 321, -229,
+ 1440, 2101, 1381,
+ 449, 461, 1155,
+ -105, 39, -384,
+ -263, 367, 182,
+ -371, -660, 773,
+ -188, 1151, 971,
+ 1333, 1632, 1435,
+ 774, 1267, 1221,
+ -482, -832, -1489,
+ -237, -210, 860,
+ 890, 1615, 1064,
+ 472, 1062, 1192,
+ 185, 1077, 989,
+ -568, -992, -1704,
+ -449, -902, -2043,
+ -142, -377, -458,
+ -210, -554, -1029,
+ -11, 1133, 2265,
+ -329, -675, -893,
+ -250, 657, 1187,
+ 519, 1510, 1779,
+ 520, 539, 1403,
+ 527, 1421, 1302,
+ -563, -871, -1248,
+ -147, -463, 879,
+ -76, 2334, 2840,
+ 563, 2573, 2385,
+ 632, 1926, 2920,
+ 719, 2023, 1840,
+ -545, -723, 1108,
+ 129, -125, 884,
+ 1417, 1632, 925,
+ -94, 1566, 1751,
+ -341, 1533, 1551,
+ 591, 395, -274,
+ -76, 981, 2831,
+ 153, 2985, 1844,
+ 1032, 2565, 2749,
+ 1508, 2832, 1879,
+ 791, 1199, 538,
+ -190, -453, 1489,
+ -278, -548, 1158,
+ -245, 1941, 2044,
+ 1024, 1560, 1650,
+ 512, 253, 466,
+ -62, -323, 1151,
+ -473, -376, 507,
+ -433, 1380, 2162,
+ 899, 1943, 1445,
+ 134, 704, 440,
+ 460, 525, -28,
+ -450, 279, 1338,
+ 0, 971, 252,
+ -445, -627, -991,
+ -348, -602, -1424,
+ 398, 712, 1656,
+ -107, 314, -178,
+ 93, 2226, 2238,
+ 518, 849, 656,
+ -462, -711, -447,
+ 174, -34, 1191,
+ -119, 42, 1005,
+ -372, 274, 758,
+ 1036, 2352, 1838,
+ 675, 1724, 1498,
+ 430, 1286, 2133,
+ -129, -439, 0,
+ -373, 800, 2144,
+ 6, 1587, 2478,
+ 478, 596, 2128,
+ -428, -736, 1505,
+ 385, 178, 980,
+ 139, 449, 1225,
+ -526, -842, -982,
+ 145, 1554, 1242,
+ 623, 1448, 656,
+ 349, 1016, 1482,
+ 31, -280, 415,
+ -316, 724, 1641,
+ 360, 1058, 556,
+ -436, -358, 1201,
+ -355, 1123, 1939,
+ 401, 1584, 2248,
+ -527, -1012, 355,
+ 233, 238, 2233,
+ -550, -897, -639,
+ -365, -501, 1957,
+ 389, 1860, 1621,
+ 162, 1132, 1264,
+ -237, 1174, 1390,
+ -640, -411, 116,
+ -228, 1694, 2298,
+ 1639, 2186, 2267,
+ 562, 1273, 2658,
+ 323, 338, 1774,
+ 578, 1107, 852,
+ 22, 594, 934,
+ -143, 718, 446
+};
+
+
+/* second codebook from IS641 */
+
+const Word16 dico2_lsf_3[DICO2_SIZE*3] =
+{
+ 50, 71, -9,
+ -338, -698, -1407,
+ 102, -138, -820,
+ -310, -469, -1147,
+ 414, 67, -267,
+ 1060, 814, 1441,
+ 1548, 1360, 1272,
+ 1754, 1895, 1661,
+ 2019, 2133, 1820,
+ 1808, 2318, 1845,
+ 644, -93, 454,
+ 858, 329, -136,
+ 489, -258, -128,
+ -198, -745, -41,
+ -52, -265, -985,
+ 346, 137, 479,
+ -1741, -748, -684,
+ -1163, -1725, -367,
+ -895, -1145, -784,
+ -488, -946, -968,
+ -85, -390, -725,
+ 215, -340, -171,
+ 1020, 916, 1969,
+ 564, 179, 746,
+ 662, 977, 1734,
+ 887, 622, 914,
+ 939, 856, 1165,
+ 309, 688, 803,
+ 917, 161, 570,
+ 118, -20, -283,
+ -816, -42, 204,
+ -1228, -325, -462,
+ -963, -202, -143,
+ -988, -484, -361,
+ -702, -978, -477,
+ -302, -790, -1188,
+ -100, -786, -1088,
+ -1054, -947, -1684,
+ -202, -843, -782,
+ -1039, -1378, -901,
+ -624, -110, -85,
+ 356, 213, -10,
+ -493, 364, 774,
+ 425, 822, 479,
+ -83, 557, 520,
+ -992, -1560, -572,
+ -603, -741, -26,
+ -502, -638, -903,
+ 209, 306, 147,
+ -316, -593, -596,
+ -85, -211, -225,
+ -918, -529, 117,
+ 233, -439, -738,
+ 1101, 751, 633,
+ 1457, 1716, 1511,
+ 1765, 1457, 910,
+ 1122, 1156, 849,
+ 1354, 868, 470,
+ -871, -1150, -1796,
+ -871, -861, -992,
+ -118, 155, 212,
+ -1051, -849, -606,
+ -1117, -1849, -2750,
+ -1019, -1427, -1869,
+ 370, -184, -414,
+ 959, 493, 104,
+ 958, 1039, 543,
+ 154, 653, 201,
+ 1249, 507, 150,
+ 663, 503, 230,
+ 623, 777, 675,
+ 659, 88, -110,
+ 843, 244, 224,
+ 382, 541, 302,
+ 724, 433, 666,
+ 1166, 734, 341,
+ -138, 20, -397,
+ -1183, -424, -46,
+ -321, -352, -124,
+ 1333, 1021, 1080,
+ 262, 366, 723,
+ 922, 283, -551,
+ 31, -636, -611,
+ -689, -697, -415,
+ -952, -779, -201,
+ -1329, -598, -359,
+ -953, -1285, 166,
+ 493, 305, 221,
+ 846, 703, 610,
+ 840, 936, 774,
+ -723, -1324, -1261,
+ -357, -1025, -1388,
+ -1096, -1376, -365,
+ -1416, -1881, -608,
+ -1798, -1727, -674,
+ -545, -1173, -703,
+ 678, 786, 148,
+ -123, 696, 1288,
+ 644, 350, -10,
+ 414, 614, 15,
+ 137, 344, -211,
+ -814, -1512, -819,
+ -391, -930, -588,
+ 47, -591, -898,
+ -909, -1097, -163,
+ -1272, -1167, -157,
+ -1464, -1525, -389,
+ -1274, -1188, -624,
+ 671, 213, 454,
+ 124, -274, -525,
+ -729, -496, -152,
+ -1344, 122, 135,
+ -2905, -589, -394,
+ -1728, 441, -50,
+ 1476, 904, 787,
+ 316, 236, -440,
+ -347, 217, 413,
+ -911, -917, 121,
+ -455, -932, 202,
+ -92, -465, -375,
+ 488, 390, 474,
+ 876, 729, 316,
+ -1815, -1312, -669,
+ 87, 962, 432,
+ 563, -249, -1058,
+ 250, 285, 1105,
+ 1141, 427, 696,
+ -1038, -1664, -1582,
+ -948, 346, 160,
+ -309, -272, -858,
+ 670, 624, 1250,
+ -944, -408, -666,
+ -606, -320, -384,
+ -492, 230, 65,
+ 334, -50, -16,
+ -16, -690, -1397,
+ 1791, 1716, 1399,
+ 2478, 2063, 1404,
+ 1245, 1471, 1426,
+ -382, -1037, -2,
+ 173, -398, 1145,
+ 1491, 2024, 1801,
+ 772, 1274, 1506,
+ 1429, 1735, 2001,
+ 1079, 1218, 1273,
+ -1154, -1851, -1329,
+ -808, -1133, -1096,
+ -451, -1033, -1722,
+ 65, 578, -84,
+ -1476, -2434, -1778,
+ -765, -1366, -494,
+ -218, -594, -931,
+ 337, -236, 562,
+ 2357, 2662, 1938,
+ 1489, 1276, 874,
+ 189, 358, 374,
+ -1519, -2281, -2346,
+ -967, -1271, -2095,
+ -628, -1188, -1542,
+ 1661, 1043, 546,
+ 565, 1061, 732,
+ -64, -836, -434,
+ -436, -96, 203,
+ 1078, 1216, 1636,
+ 907, 1534, 986,
+ 326, 965, 845,
+ 142, -84, 197,
+ 470, 2379, 1570,
+ 1133, 470, 1214,
+ 395, 1376, 1200,
+ 1125, 1042, 348,
+ -543, -1234, -376,
+ -215, -181, 481,
+ -1947, -1621, -210,
+ -750, -1185, 390,
+ 29, -399, 27,
+ 820, 1236, 755,
+ 695, 979, 409,
+ -174, 1197, 1035,
+ 912, 1356, 1846,
+ -992, -1437, 484,
+ -1485, -1700, 208,
+ -412, 1204, 1432,
+ -271, 896, 1144,
+ -416, 1777, 1434,
+ -1696, -2644, -204,
+ -1789, -1551, 1033,
+ -1656, -1559, 1303,
+ -1253, -1589, 1081,
+ -669, -1095, -66,
+ -682, 320, -345,
+ 659, 305, 1069,
+ -1292, -804, -19,
+ -1635, -1291, 29,
+ -1683, -497, 71,
+ -287, -7, -100,
+ -494, -962, -237,
+ 852, 1881, 1740,
+ -1217, -1387, 227,
+ -660, 302, 373,
+ 96, 1087, 1257,
+ -1074, -1669, 160,
+ 485, 2076, 1798,
+ -934, -220, 552,
+ -596, -612, 237,
+ 336, 1720, 879,
+ 643, 629, 434,
+ 1267, 522, 1633,
+ 15, 244, -441,
+ 1475, 717, 184,
+ 1819, 1590, 1709,
+ 988, 261, 937,
+ 2093, 2345, 1520,
+ 2139, 1858, 1606,
+ -577, -579, -1203,
+ -956, 135, -488,
+ -464, 51, -338,
+ -629, -348, -723,
+ 1146, 2073, 1442,
+ 2192, 1466, 911,
+ -1444, -1572, -2278,
+ 1400, 710, 1297,
+ 1335, 633, 928,
+ 1434, 2194, 2594,
+ 2422, 2204, 1881,
+ 982, 2242, 1854,
+ 380, 792, 1145,
+ -63, -539, 414,
+ -252, -964, -314,
+ -1261, -683, -780,
+ -831, -526, -1005,
+ -1666, -1135, -424,
+ -1611, -452, -299,
+ 1268, 1048, 642,
+ 1147, 853, 856,
+ -675, -336, 139,
+ 2268, 1343, 1418,
+ 29, 768, 797,
+ -1224, 423, 564,
+ -1318, -1082, 245,
+ -1302, -812, 573,
+ -1298, -1617, 646,
+ -968, 834, 723,
+ 993, 1652, 2027,
+ -191, -817, 432,
+ 662, 60, 198,
+ 626, 997, 1330,
+ 1648, 1963, 1289,
+ -1597, -93, -45,
+ -1088, 37, -84,
+ 1653, 2607, 2337,
+ 1065, 2040, 2377,
+ 1139, 2326, 2118,
+ 859, 357, 1510,
+ 664, 1227, 1099,
+ 479, 1360, 912,
+ 1897, 1754, 2019,
+ 1168, 1909, 1784,
+ 399, 34, 256,
+ -593, -304, -1053,
+ 547, 1694, 1407,
+ 647, -99, -341,
+ 1492, 1647, 1190,
+ 38, -644, -212,
+ 395, 846, 222,
+ -704, -765, -716,
+ -724, -1964, -2804,
+ -150, 291, -82,
+ 1233, 1459, 1007,
+ -140, -155, 153,
+ 439, 297, 1568,
+ -1529, -410, -636,
+ 1536, 455, -237,
+ -1328, -139, -260,
+ 531, 554, 868,
+ 269, 1264, 606,
+ -233, 883, 463,
+ 742, 600, -120,
+ -73, 421, 212,
+ -439, -58, 804,
+ -1286, -1241, 728,
+ 294, -490, 50,
+ -591, -905, -1254,
+ 42, -687, 147,
+ -25, 273, 596,
+ -311, 1213, 601,
+ -754, 849, 584,
+ 429, 607, 587,
+ -602, -166, 461,
+ -796, -823, 777,
+ 1380, 910, 1755,
+ 119, 1417, 972,
+ -219, -880, -1596,
+ -1049, -1010, 438,
+ -713, -1379, 78,
+ 0, -447, -1179,
+ -1136, -1319, -1573,
+ 2248, 1767, 1309,
+ 946, 1583, 1432,
+ 1150, 482, 436,
+ -469, -1108, 618,
+ -447, -966, 1088,
+ -1252, -1515, -114,
+ -1104, -2008, -579,
+ 210, 613, 497,
+ -1975, -1437, 642,
+ -1269, -856, 1011,
+ -1646, -1185, 1063,
+ -1555, -672, 1204,
+ -1692, -1114, 623,
+ -979, -1326, -1277,
+ 539, -147, 894,
+ -1354, -897, -434,
+ 888, 475, 428,
+ 153, -384, 338,
+ -1492, -511, 359,
+ -974, -1115, -470,
+ 105, -550, 677,
+ -937, -1145, 877,
+ 380, -260, 210,
+ 1685, 924, 1256,
+ 1775, 1190, 1095,
+ 1419, 631, 533,
+ 627, 299, -347,
+ -411, -534, 647,
+ -650, 29, -595,
+ -378, -1367, 1563,
+ 1402, 1121, 1465,
+ 1089, 1410, 648,
+ -2096, -1090, -6,
+ 311, -194, -869,
+ -639, -831, 416,
+ -1162, -1224, 1349,
+ -1247, -941, 1813,
+ -2193, -1987, 453,
+ -619, -1367, -956,
+ -1606, -1972, -1507,
+ -1175, -1057, -1104,
+ -377, 601, 201,
+ 1876, 825, 374,
+ -430, -1323, 29,
+ -1397, -1249, -1331,
+ -1007, -1504, 960,
+ -1401, -2009, 197,
+ -1379, -1949, -236,
+ -1077, 123, 422,
+ 615, 1269, 546,
+ -306, 1526, 904,
+ 1194, 1788, 1177,
+ -626, -884, -1526,
+ 199, 766, 1504,
+ -1065, 862, 197,
+ -1034, -1773, -887,
+ -800, 145, 599,
+ -1134, -519, 626,
+ -1205, -1926, 500,
+ -910, -1041, -1395,
+ -1476, -1567, -969,
+ -523, 842, 34,
+ 1794, 646, 862,
+ -1207, -1888, -1002,
+ -78, -9, -672,
+ 1044, 759, 80,
+ -600, 1139, 1019,
+ 57, 2000, 1422,
+ -833, 1414, 1121,
+ -1202, 1630, 1260,
+ -461, 1420, 1244,
+ 1537, 975, 253,
+ -283, 324, -359,
+ 599, -195, 106,
+ 588, 62, -587,
+ -757, 645, 205,
+ 51, 1201, 758,
+ -1209, 673, -390,
+ -624, 1581, 941,
+ -151, 1023, 735,
+ 2820, 1301, 690,
+ -302, 524, -99,
+ -900, -1588, -1189,
+ 1084, 251, 238,
+ 2014, 1792, 1010,
+ 1245, 1633, 1741,
+ -1227, -1540, -1208,
+ -621, 456, -109,
+ 40, -65, 788,
+ -805, -699, -1350,
+ -583, 904, 832,
+ -801, 532, 594,
+ 1972, 1408, 1351,
+ -1177, -1880, -2114,
+ -773, 568, 948,
+ -1015, 1079, 1260,
+ -1111, 482, -130,
+ 1778, 1044, 780,
+ -1491, 245, 912,
+ -316, -1141, -917,
+ -536, -1442, -2346,
+ -785, -1546, -1988,
+ -2003, 257, 909,
+ -1849, -633, -1209,
+ -1538, -1918, -1054,
+ 1606, 2239, 1576,
+ -567, -1500, -1544,
+ -1279, 195, 1369,
+ -817, 293, 1219,
+ -525, 630, 1197,
+ -1698, -2425, -1840,
+ -303, 731, 747,
+ -1169, -251, 269,
+ -950, -75, 1684,
+ -1182, -453, 1005,
+ -1599, 585, 378,
+ -2075, -571, -427,
+ -529, -1159, -1171,
+ -283, -205, -564,
+ -796, 1246, 717,
+ 2277, 927, 539,
+ -454, 559, 440,
+ -717, 1460, 1615,
+ -1030, 1052, 1610,
+ -1169, -138, 847,
+ 226, 39, -612,
+ -1251, -106, -729,
+ -651, 968, 1302,
+ -714, -636, 1727,
+ 353, 1069, 410,
+ -798, -156, 1099,
+ -574, 918, 446,
+ -1310, 1012, 466,
+ 1408, 1591, 765,
+ 1429, 1380, 1757,
+ 1949, 1956, 2378,
+ 1578, 2047, 2148,
+ 916, 98, -7,
+ 1893, 1418, 2141,
+ 348, 1405, 1579,
+ 152, 1134, 1801,
+ -267, 154, 1395,
+ -1166, 469, 1054,
+ -1142, -405, -1073,
+ -1341, -2264, -1581,
+ -364, 869, 1706,
+ -1162, 549, 1550,
+ -1225, -1932, -1666,
+ -1485, -1977, -2055,
+ -1727, -906, -98,
+ -1897, 233, 1492,
+ 892, 108, -331,
+ -1728, -1170, -1700,
+ -1060, 1980, 1790,
+ -1070, -1741, -1909,
+ -11, 1539, 1317,
+ -1600, 94, 497,
+ 421, 443, -197,
+ -1578, -349, -994,
+ -599, -539, 1140,
+ -965, -1419, -129,
+ -1341, 175, -447,
+ -375, 1311, 2055,
+ -371, -650, -307,
+ -1073, 605, 365,
+ -2057, -113, 430,
+ 652, 914, 967,
+ -1012, -1586, -2323,
+ 1505, 1248, 559,
+ 262, -486, -401,
+ -1727, 1342, 1546,
+ 50, 56, 432,
+ -330, 119, -604,
+ -1517, -1080, -810,
+ 946, 1127, 1055,
+ -1400, -1703, -1712,
+ -1270, -704, -1317,
+ 807, 1821, 1143,
+ 2760, 1606, 2171,
+ 1120, 409, -150,
+ -147, 404, 959,
+ 2439, 1911, 2189,
+ -906, -141, -866,
+ -904, -142, -458,
+ -557, -708, -1679,
+ -830, -1431, -1583,
+ -1842, -1346, -1086,
+ -1604, -272, 915,
+ -1196, 772, 1056,
+ -638, -1234, -1897,
+ -500, -81, -822,
+ -1289, -1613, -735,
+ -117, 785, 168,
+ -1090, 1133, 922,
+ -1096, -746, 1384,
+ 287, -547, -1063,
+ -1376, -2201, -1204,
+ -2176, -1570, -1757,
+ -1511, -2241, -771,
+ -1737, 1099, 830,
+ -1588, 724, 1243,
+ -1542, 693, 805,
+ -1690, -240, 1665,
+ -1700, -4, -668,
+ 2149, 816, 1042,
+ -818, -1841, 22,
+ -764, -507, 449,
+ -1151, -617, 289,
+ -843, -1596, -240,
+ 498, -234, -657,
+ -752, 480, 1678,
+ -319, -481, 193,
+ -811, 171, -119,
+ -2128, -202, -848,
+ 1717, 1140, 1700
+};
+
+
+/* third codebook from IS641 */
+
+const Word16 dico3_lsf_3[DICO3_SIZE*4] =
+{
+ 67, -17, 66, -12,
+ -1690, -581, -104, -272,
+ -1076, -1186, -1845, -376,
+ -1140, -926, -420, -58,
+ -259, -656, -1134, -553,
+ 1788, 1227, 455, 129,
+ 462, 441, -240, -528,
+ 840, 514, 130, -75,
+ 1114, 623, 153, 216,
+ 1068, 564, -6, -276,
+ 1119, 727, 190, -68,
+ 704, 306, 119, -264,
+ 329, 61, -100, 156,
+ 364, 123, 183, -208,
+ -171, -123, 220, -65,
+ -306, -62, 402, 17,
+ -660, -938, -266, 0,
+ 385, 235, 276, 285,
+ 320, 268, -336, -200,
+ -724, 17, -84, 381,
+ -544, 429, 494, 519,
+ -117, 288, 304, 329,
+ 643, 157, 701, 508,
+ 1200, 625, 796, 608,
+ 998, 421, 492, 632,
+ 1204, 780, 446, 132,
+ 1257, 844, 547, 449,
+ 829, 658, 541, 470,
+ 1132, 1258, 918, 639,
+ 547, 51, 423, 279,
+ 9, 392, 83, 94,
+ 542, 543, 229, -147,
+ -198, 129, 194, -185,
+ -863, -1321, -302, 30,
+ -597, -629, -19, 114,
+ -900, -1081, 466, 353,
+ -1483, -1573, 15, -143,
+ -1708, -2059, -751, 196,
+ -1876, -2067, -642, -258,
+ -2335, -1470, -450, -564,
+ -584, -186, -872, -414,
+ -1805, -988, -1125, -1310,
+ -726, -1129, 28, 169,
+ -1039, -864, -718, -246,
+ 484, 36, -233, -49,
+ 265, 67, 289, 467,
+ 178, 543, 810, 540,
+ 84, 282, 672, 703,
+ -975, -777, 129, 287,
+ -938, -227, 955, 595,
+ -1617, -289, 836, 649,
+ -1847, -215, 1106, 718,
+ -2034, -1085, 650, 440,
+ -2101, -529, 907, 575,
+ -2011, -336, 670, 204,
+ -2389, -692, 360, 137,
+ -2156, -2204, -9, 280,
+ -266, 119, 39, 193,
+ 78, -59, -120, 226,
+ -975, -858, -781, -1095,
+ -619, -413, -451, -842,
+ -1216, -1321, -813, -883,
+ -1376, -1615, -394, -428,
+ -737, -1113, -549, -790,
+ -880, -975, -967, -642,
+ -985, -886, -1273, -1361,
+ -473, -804, -1401, -1407,
+ 160, -265, -919, -275,
+ -248, -250, -718, -380,
+ 97, -103, -375, -229,
+ -415, -193, -135, -555,
+ 628, 361, 119, 216,
+ 579, 364, 391, 209,
+ 634, 522, -154, -148,
+ 526, 389, 170, 33,
+ 105, 267, 64, 380,
+ -1503, -1000, -30, -369,
+ -1070, 58, 647, 223,
+ -1520, -291, 621, 307,
+ -1531, 156, 762, 404,
+ -2029, 141, 734, 499,
+ -1849, -650, 306, 512,
+ -187, -104, -59, 438,
+ 134, -230, 156, -186,
+ -61, -260, -16, 10,
+ -569, -3, -421, -297,
+ -1725, -521, -346, 178,
+ -1362, -59, -44, 157,
+ -2146, -461, -470, -349,
+ -2170, -1, -369, -121,
+ -1579, -373, -900, -1015,
+ -1117, -591, -613, -784,
+ -561, 122, -75, -449,
+ -4, -171, -123, -372,
+ 192, 168, -76, -132,
+ 252, -107, 340, 210,
+ 392, 509, 272, 181,
+ -109, 145, 218, 119,
+ -416, -263, 485, 265,
+ -181, -8, -286, 226,
+ -244, -218, 69, -290,
+ -158, 191, -1, -64,
+ -592, -90, 213, -96,
+ 255, 435, 178, -80,
+ -369, -18, -33, -80,
+ -42, 415, 140, -222,
+ 1143, 651, 649, 329,
+ 767, 556, 249, 235,
+ 948, 413, 442, 279,
+ 141, 339, 356, 557,
+ -470, -170, 99, 237,
+ -569, -800, 352, 565,
+ 282, 473, 470, 332,
+ -199, -690, -1284, -917,
+ -193, -426, -800, -1122,
+ -26, -371, -490, -193,
+ 637, 595, 519, 330,
+ 408, -115, 79, 12,
+ 477, 87, -103, -376,
+ -666, -347, -277, -291,
+ -510, -481, 169, 297,
+ -829, -738, -205, -171,
+ -320, -540, 328, 283,
+ -859, -958, 442, -2,
+ 556, 686, 130, 56,
+ 1383, 1012, 755, 427,
+ 612, 741, 628, 553,
+ -339, -796, 134, 277,
+ -633, -1085, -2, -246,
+ -880, -1035, -1607, -1064,
+ -994, -474, -1138, -488,
+ -414, -795, 73, -206,
+ -8, -139, 439, 204,
+ -176, -578, 23, 131,
+ -269, -757, -191, 245,
+ -109, -338, 112, 316,
+ 120, -406, -118, 611,
+ -180, -186, -645, 115,
+ -173, 34, -518, -489,
+ -151, 61, -583, -844,
+ 220, -138, -681, -1020,
+ 391, -17, -598, -321,
+ 157, -295, 129, 155,
+ -926, -875, -987, 285,
+ 241, -83, -125, -125,
+ 620, 597, 432, 92,
+ 393, 78, 409, 61,
+ -393, -739, -413, -748,
+ 83, 54, 361, 27,
+ -1084, 130, -337, -694,
+ -1565, 297, 318, -19,
+ -1873, 36, 51, -317,
+ -2323, -246, 231, -84,
+ -2306, -783, 40, -179,
+ -2233, -930, -474, -462,
+ -754, -86, -288, -626,
+ -2411, -455, -63, 171,
+ -1099, -1094, -26, -143,
+ -1193, -455, -406, -381,
+ -605, -210, -96, -51,
+ -580, -476, -276, -15,
+ -1195, -634, -1203, -881,
+ -378, -221, -669, -952,
+ 594, 178, -403, -676,
+ 763, 327, 601, 290,
+ 172, 300, 203, 157,
+ -56, -336, 356, 24,
+ -228, -296, -259, -29,
+ -186, 263, 416, 14,
+ -353, 373, -12, -216,
+ 257, 96, 174, 57,
+ -1526, -616, -954, -499,
+ -497, -152, -333, 125,
+ 105, 200, 179, -97,
+ -331, -224, 765, 697,
+ 760, 256, 301, 59,
+ 455, -85, 204, 288,
+ -514, 240, 251, -109,
+ 256, 417, -34, -413,
+ 101, 430, 384, 156,
+ -31, -10, 206, 426,
+ 589, 145, 143, 71,
+ 808, 906, 333, 349,
+ 986, 938, 589, 331,
+ 1300, 824, 187, 509,
+ 1062, 653, 379, 466,
+ 1462, 937, 401, 274,
+ 787, 861, 265, 2,
+ 609, 553, 28, 305,
+ 926, 340, 106, 386,
+ 241, -267, -147, 225,
+ -178, -534, 347, 502,
+ -643, -381, 397, 30,
+ -651, -733, -435, 398,
+ -407, -726, -484, -248,
+ -789, -914, -438, -476,
+ -498, -390, 75, -295,
+ -964, -590, -606, 150,
+ -121, -49, -155, -78,
+ 935, 550, 389, 38,
+ -321, 127, 424, 315,
+ -285, -113, 283, 259,
+ 658, 203, 322, 486,
+ 903, 505, 748, 417,
+ 611, 423, 555, 512,
+ 239, -83, -578, -19,
+ -339, -731, 349, 13,
+ -934, -1399, -114, -360,
+ 107, 692, 182, 90,
+ -1243, -1538, -1551, -725,
+ -568, -903, -1363, -525,
+ -517, -853, -861, -1004,
+ -168, -690, -835, 63,
+ -137, -556, -547, 144,
+ -286, -817, 485, 319,
+ -147, -408, 526, 246,
+ -347, -434, 297, -28,
+ -290, -471, -1110, -1285,
+ -460, -359, -988, -794,
+ 1347, 1299, 690, 523,
+ 1216, 1068, 1094, 757,
+ 825, 1140, 752, 494,
+ 1252, 1365, 1195, 898,
+ 521, 1053, 532, 432,
+ -334, -216, -313, -263,
+ -160, 52, -472, -155,
+ 127, 136, -380, 44,
+ 851, 410, -162, -489,
+ 123, -255, -796, -667,
+ 1090, 917, 789, 493,
+ 1397, 1197, 558, 202,
+ -51, -118, -342, -701,
+ 83, 108, -42, -441,
+ 61, 95, 287, 256,
+ -27, 89, 524, 531,
+ 351, 227, 592, 545,
+ 697, 155, -164, 307,
+ 638, 274, -489, -50,
+ 754, 240, -166, -124,
+ -116, -579, -1212, -63,
+ 190, -295, -1040, -1296,
+ 147, -376, -177, -113,
+ 841, 1241, 1051, 668,
+ 2, 293, 551, 304,
+ -1096, -953, -248, 376,
+ -750, -965, 87, 516,
+ -275, -516, 689, 391,
+ -379, -643, 876, 594,
+ -390, -1013, -645, 573,
+ -107, -568, -689, -826,
+ -1025, -27, -328, -203,
+ 861, 749, 548, 233,
+ -1660, -1043, 451, 108,
+ -660, -620, 430, 236,
+ 21, -396, -1158, -631,
+ 1372, 1298, 967, 577,
+ 1125, 1125, 589, 454,
+ -323, -865, -467, 153,
+ -468, -699, -804, -509,
+ -392, -718, -204, -35,
+ -603, -1093, -567, -162,
+ -505, -1004, -102, 350,
+ 219, 224, 423, 252,
+ 395, 591, 608, 363,
+ -746, -96, 373, 172,
+ 171, 295, 714, 339,
+ 233, 77, 107, 277,
+ 157, 153, -499, -356,
+ 1547, 1073, 576, 494,
+ -292, -339, -504, -592,
+ -903, -72, -619, -481,
+ -1594, -1117, -567, -254,
+ -793, -507, -564, -291,
+ -492, -532, 502, 560,
+ -382, 427, 600, 230,
+ -227, 477, 251, 75,
+ 285, 842, 813, 476,
+ -1310, -1333, 186, 377,
+ -587, -917, 643, 381,
+ -1186, -553, 411, 82,
+ -1127, -820, -174, -540,
+ -604, 119, 543, 205,
+ -380, 657, 909, 567,
+ 112, -298, -374, 114,
+ -857, -251, 56, 159,
+ 401, 345, -34, -140,
+ -111, -607, 41, 614,
+ 355, -114, -77, 474,
+ 578, 56, 1450, 924,
+ 1098, 1420, 741, 400,
+ 246, 22, 588, 313,
+ -121, 327, 831, 472,
+ -1138, -608, 856, 552,
+ -1241, -1072, 638, 600,
+ -358, 254, -333, -303,
+ -646, 739, 358, 74,
+ 1226, 1671, 1221, 849,
+ 2241, 1624, 983, 636,
+ 1841, 1477, 749, 384,
+ 350, 263, 87, 128,
+ -1902, -941, -144, -64,
+ -1734, -255, 288, -31,
+ -2644, -1238, 366, 235,
+ -1643, -1092, -1344, -304,
+ -541, -1075, -1116, 123,
+ -1178, -252, -816, -180,
+ -1016, 533, 565, 233,
+ -487, -430, -188, 334,
+ 867, 1236, 534, 171,
+ -1590, -1607, 635, 630,
+ -2196, 310, 924, 412,
+ -2358, -328, 956, 529,
+ -2639, -377, 630, 278,
+ -2602, 317, 799, 299,
+ -2406, 133, 340, 31,
+ -2156, -1468, 131, 125,
+ -1184, -490, -139, 46,
+ -744, 447, 891, 564,
+ 67, -451, 646, 604,
+ -553, -429, -876, 396,
+ 162, -66, 1305, 915,
+ 479, 579, 1088, 794,
+ 450, 278, 566, 324,
+ -1057, -154, 148, -177,
+ -2545, 168, 1070, 592,
+ -2351, -42, 819, 345,
+ -2344, -707, 721, 250,
+ -2175, -1497, -309, 122,
+ -78, -73, 120, 173,
+ -4, 262, -263, -261,
+ -431, -64, -405, -732,
+ -2609, 116, -83, -193,
+ -1525, -944, -477, -725,
+ -508, 307, 170, 172,
+ 832, 417, 832, 686,
+ -225, 177, 894, 818,
+ -482, -389, 1279, 1039,
+ -383, 201, -350, 40,
+ 730, 635, 226, 526,
+ 503, 462, 338, 398,
+ 535, 714, 40, -282,
+ 1482, 1471, 1085, 731,
+ 1561, 1072, 909, 693,
+ 1419, 1282, 889, 879,
+ 1153, 728, 1186, 840,
+ -226, 1130, 949, 689,
+ -494, -986, -1556, -128,
+ -568, -721, -713, -26,
+ 317, 524, 70, 135,
+ -405, -865, -1766, -652,
+ -174, -801, 885, 773,
+ -153, -91, 1099, 751,
+ -506, -1149, 853, 646,
+ 241, 782, 519, 539,
+ 1853, 1700, 1101, 684,
+ -1249, -1486, -464, 188,
+ -893, -1409, -1312, -341,
+ -135, 438, -175, 18,
+ 1111, 976, 319, 208,
+ -1430, -1768, 83, 458,
+ -530, -1000, 307, 129,
+ -840, -15, -29, -356,
+ -911, -924, -1147, -242,
+ -119, -528, 127, -133,
+ -761, -765, 190, -83,
+ -315, 895, 522, 231,
+ -222, 102, -63, -428,
+ 316, 699, 379, 70,
+ 25, 716, 314, -108,
+ 507, 874, 566, 238,
+ 108, 941, 519, 195,
+ 425, -60, -427, 257,
+ 139, -103, -630, 446,
+ 334, 370, 412, 48,
+ -172, -690, -283, 557,
+ 187, -286, 158, 483,
+ 140, 270, -344, -631,
+ 924, 579, -116, 132,
+ 142, 466, -68, -64,
+ 230, -145, -302, -542,
+ -803, -912, 1018, 737,
+ -773, 1015, 630, 297,
+ -2596, 95, 445, 336,
+ -2122, 491, 510, 191,
+ -1253, 161, -2, -324,
+ -1450, -633, -712, -105,
+ -842, -254, -411, 100,
+ -640, -290, 1010, 763,
+ -650, 313, 1169, 730,
+ 140, 505, 1030, 766,
+ 772, 287, 1067, 823,
+ 495, 749, 305, 323,
+ -164, 462, 78, 399,
+ -342, -874, 69, 597,
+ -16, 620, 621, 337,
+ -138, -444, -265, 218,
+ 84, -450, 953, 666,
+ -222, -803, 541, 604,
+ -921, -1376, 244, 116,
+ -841, -723, 630, 588,
+ 140, 663, 294, 368,
+ 935, 1046, 881, 759,
+ 1746, 1464, 916, 628,
+ 436, 963, 281, 1,
+ -119, 74, 542, 213,
+ 1, -567, 301, 241,
+ 260, 435, 222, 396,
+ 936, 957, 1108, 703,
+ 510, 506, 808, 478,
+ 601, 694, 960, 620,
+ 972, 741, 980, 600,
+ 834, 717, 767, 684,
+ 643, 972, 935, 638,
+ 501, 661, 720, 851,
+ -105, -632, -303, -117,
+ -429, 130, 789, 442,
+ -522, -188, 704, 373,
+ -759, 42, 814, 523,
+ -531, -1137, 373, 578,
+ -682, -1203, -455, 285,
+ -1163, -1577, -1098, 44,
+ 81, -82, 712, 363,
+ 477, 246, 954, 622,
+ 1604, 1622, 1277, 891,
+ 1409, 859, 924, 892,
+ 774, 1041, 947, 1142,
+ 40, -546, -75, 288,
+ -616, -106, -697, -26,
+ -169, -160, -891, -739,
+ -279, -384, -1029, -350,
+ 1781, 1308, 1046, 816,
+ 1580, 1533, 1472, 1178,
+ 1505, 1076, 1216, 899,
+ 890, 904, 564, 654,
+ 920, 692, 1021, 856,
+ -493, 132, 177, 505,
+ 71, 195, -28, 97,
+ 456, 351, -164, 88,
+ 439, 278, -40, 350,
+ 1395, 949, 234, -95,
+ -805, -472, 38, -163,
+ 367, -98, 489, 523,
+ 1025, 1178, 1212, 906,
+ 319, 1314, 814, 461,
+ -123, -543, -804, 447,
+ -748, -324, -897, -1127,
+ -737, -501, -789, -713,
+ 715, 777, 1239, 922,
+ 1949, 1939, 1368, 865,
+ 730, 880, 758, 388,
+ -871, 454, 17, -251,
+ -381, -810, -1583, 239,
+ -521, -966, -792, 259,
+ -890, -1358, -770, -73,
+ 166, 349, -212, 323,
+ -840, -301, 473, 435,
+ -679, -464, 728, 351,
+ -156, -199, 667, 432,
+ 29, -252, 415, 480,
+ -731, -379, 145, 559,
+ -528, -631, -1158, -159,
+ 445, 273, 123, 639,
+ 373, -126, 800, 568,
+ 84, -162, 720, 712,
+ -830, -536, -185, 222,
+ 408, 452, 501, 771,
+ -897, -1355, -67, 442,
+ -792, -1406, 566, 602,
+ 167, -326, 509, 330,
+ -95, -626, -730, -344,
+ 1668, 1217, 779, 455,
+ 1316, 828, 584, 719,
+ 404, -31, 1013, 789,
+ 89, 107, 891, 549,
+ 871, 1581, 917, 671,
+ 866, 1479, 1289, 854,
+ 391, 1068, 1122, 812,
+ 78, -562, 345, 563,
+ 429, -103, 417, 787,
+ -122, -437, 411, 788,
+ -913, -417, 602, 754,
+ -226, -16, 151, 760,
+ -700, 118, -104, -14,
+ -1128, 48, 284, 393,
+ -390, -419, -639, -116,
+ -910, 306, 316, -13,
+ 1207, 984, 821, 669,
+ -1195, -693, 140, -213,
+ -884, -416, -199, -558,
+ -616, 245, -404, -664,
+ 262, 56, -617, -724,
+ -85, -491, -320, -656,
+ -570, -831, -129, -528,
+ -1506, -63, -367, -385,
+ -358, -321, 4, 51,
+ -366, -214, 319, 511,
+ 146, 671, -17, -291,
+ -110, 464, -139, -496,
+ -202, 220, -312, -631,
+ -660, -73, -655, -820,
+ -662, -653, -1288, -857,
+ -430, -953, -959, -264,
+ -49, -468, -72, -381,
+ -350, -563, -193, -407,
+ 55, -408, -803, 11,
+ -309, 649, 188, -198,
+ -512, 461, -79, -458,
+ -1318, -263, -134, -523,
+ -1657, -435, -495, -765,
+ 57, -347, -414, 434,
+ -1141, -242, -664, -857,
+ 34, -68, -707, -338
+};
+
+
+
+/* third codebook for MR475, MR515 */
+
+const Word16 mr515_3_lsf[MR515_3_SIZE*4] =
+{
+ 419, 163, -30, -262,
+ -455, -789, -1430, -721,
+ 1006, 664, 269, 25,
+ 619, 260, 183, 96,
+ -968, -1358, -388, 135,
+ -693, 835, 456, 154,
+ 1105, 703, 569, 363,
+ 1625, 1326, 985, 748,
+ -220, 219, 76, -208,
+ -1455, -1662, 49, 149,
+ -964, -172, -752, -336,
+ 625, 209, -250, -66,
+ -1017, -838, -2, 317,
+ -2168, -1485, -138, 123,
+ -1876, -2099, -521, 85,
+ -967, -366, -695, -881,
+ -921, -1011, -763, -949,
+ -124, -256, -352, -660,
+ 178, 463, 354, 304,
+ -1744, -591, -282, 79,
+ -2249, 175, 867, 499,
+ -138, -180, -181, -21,
+ -2291, -1241, -460, -520,
+ -771, 451, -10, -308,
+ 271, -65, 4, 214,
+ -279, -435, -43, -348,
+ -670, 35, -65, -211,
+ 806, 535, 85, 297,
+ 57, 239, 722, 493,
+ 225, 661, 840, 547,
+ -540, -376, 14, 349,
+ 469, 721, 331, 162,
+ -544, -752, -62, -10,
+ 398, -88, 724, 701,
+ -19, -533, -94, 601,
+ 136, -71, -681, -747,
+ -166, -344, 261, -50,
+ 161, -52, 485, 337,
+ -1675, 50, 190, -93,
+ -2282, -231, -194, -82,
+ -95, -595, -154, 128,
+ 894, 501, 588, 457,
+ -345, 206, 122, 110,
+ -631, -227, -569, 3,
+ 408, 239, 397, 226,
+ -197, -2, 128, 491,
+ 1281, 904, 292, 215,
+ 538, 306, 259, 509,
+ -677, -1047, 13, 321,
+ -679, -588, -358, -212,
+ -558, 243, 646, 479,
+ 486, 342, 634, 532,
+ 107, 802, 331, 136,
+ -112, -398, -1031, -286,
+ -326, -705, 288, 272,
+ 1299, 1144, 1178, 860,
+ -423, 121, -385, -148,
+ -295, -302, -834, -819,
+ 16, -24, -201, -476,
+ 555, 91, -245, 294,
+ -38, -379, -962, -1221,
+ -1191, -1518, -273, -395,
+ -390, -1013, -645, 573,
+ -1843, -1030, 505, 468,
+ 744, 947, 609, 493,
+ -689, -1172, -628, -135,
+ -1026, 195, 411, 196,
+ 1582, 1147, 575, 337,
+ -1239, -777, -648, -142,
+ 595, 825, 967, 735,
+ -1206, -970, -81, -342,
+ -745, 13, -72, 375,
+ 454, 19, 1407, 921,
+ -1647, -172, 861, 562,
+ 928, 1537, 1063, 740,
+ -2472, -952, 264, 82,
+ -502, -965, -1334, 123,
+ 867, 1236, 534, 171,
+ -2320, -460, 780, 363,
+ -1190, -617, 252, -61,
+ -174, 34, 1011, 788,
+ -2333, 247, 423, 153,
+ -16, -355, 262, 449,
+ -1576, -1073, -544, -371,
+ -615, -305, 1051, 805,
+ 687, 528, 6, -182,
+ 935, 875, 1002, 809,
+ 199, 257, 126, 76,
+ -584, -1138, 599, 556,
+ -1105, -1391, -1591, -519,
+ -977, -1325, 108, 347,
+ -722, -975, 365, 101,
+ -145, 681, 249, -153,
+ 0, -334, -570, 159,
+ 412, 285, -336, -617,
+ -953, -966, 887, 689,
+ -1251, 84, -185, -398,
+ -592, 433, 1044, 653,
+ 85, 329, -40, 361,
+ -433, -705, 466, 574,
+ -154, 654, 592, 290,
+ -167, 72, 349, 175,
+ 674, 297, 977, 720,
+ 1235, 1204, 757, 488,
+ -400, -269, 538, 372,
+ -1350, -1387, -1194, -91,
+ 1262, 876, 775, 700,
+ -599, -38, -430, -722,
+ 1976, 1630, 991, 608,
+ 111, 276, -226, -96,
+ -947, -388, -11, -7,
+ -303, -531, -839, 338,
+ 1734, 1710, 1405, 1013,
+ -516, -855, -645, 210,
+ -688, -416, 513, 230,
+ -822, -637, -1146, -320,
+ -952, -658, -694, 183,
+ -114, -623, 818, 674,
+ -191, -204, 731, 635,
+ 51, 1221, 883, 576,
+ -954, -431, 826, 598,
+ -342, -755, -900, -407,
+ -1126, -354, -206, -512,
+ -547, -810, -357, -620,
+ 66, 515, -73, -410,
+ -872, -945, -1444, -1227,
+ 191, -17, -544, -231,
+ -1540, -544, -901, -886
+};
+
+/* first codebook for MR795 */
+
+const Word16 mr795_1_lsf[MR795_1_SIZE*3] =
+{
+ -890, -1550, -2541,
+ -819, -970, 175,
+ -826, -1234, -762,
+ -599, -22, 634,
+ -811, -987, -902,
+ -323, 203, 26,
+ -383, -235, -781,
+ -399, 1262, 906,
+ -932, -1399, -1380,
+ -624, 93, 87,
+ -414, -539, -691,
+ 37, 633, 510,
+ -387, -476, -1330,
+ 399, 66, 263,
+ -407, -49, -335,
+ -417, 1041, 1865,
+ -779, -1089, -1440,
+ -746, -858, 832,
+ -581, -759, -371,
+ -673, -506, 2088,
+ -560, -634, -1179,
+ 271, 241, 14,
+ -438, -244, -397,
+ 463, 1202, 1047,
+ -606, -797, -1438,
+ -51, -323, 481,
+ -224, -584, -527,
+ 494, 881, 682,
+ -433, -306, -1002,
+ 554, 659, 222,
+ 171, -160, -353,
+ 681, 1798, 1565,
+ -852, -1181, -1695,
+ -336, -666, 114,
+ -581, -756, -744,
+ -195, 375, 497,
+ -465, -804, -1098,
+ 154, 282, -131,
+ -50, -191, -719,
+ 323, 732, 1542,
+ -722, -819, -1404,
+ 105, -250, 185,
+ -178, -502, -742,
+ 321, 510, 1111,
+ -323, -567, -966,
+ 127, 484, 338,
+ -160, 52, -338,
+ 732, 1367, 1554,
+ -626, -802, -1696,
+ -286, -586, 676,
+ -695, -343, -370,
+ -490, 295, 1893,
+ -630, -574, -1014,
+ -80, 645, -69,
+ -6, -318, -364,
+ 782, 1450, 1038,
+ -313, -733, -1395,
+ 120, 60, 477,
+ -264, -585, -123,
+ 711, 1245, 633,
+ -91, -355, -1016,
+ 771, 758, 261,
+ 253, 81, -474,
+ 930, 2215, 1720,
+ -808, -1099, -1925,
+ -560, -782, 169,
+ -804, -1074, -188,
+ -626, -55, 1405,
+ -694, -716, -1194,
+ -660, 354, 329,
+ -514, -55, -543,
+ 366, 1033, 1182,
+ -658, -959, -1357,
+ -55, -184, 93,
+ -605, -286, -662,
+ 404, 449, 827,
+ -286, -350, -1263,
+ 628, 306, 227,
+ -16, 147, -623,
+ 186, 923, 2146,
+ -674, -890, -1606,
+ -443, -228, 339,
+ -369, -790, -409,
+ 231, 86, 1469,
+ -448, -581, -1061,
+ 594, 450, -177,
+ -124, -170, -447,
+ 671, 1159, 1404,
+ -476, -667, -1511,
+ -77, -138, 716,
+ -177, -372, -381,
+ 451, 934, 915,
+ -250, -432, -822,
+ 272, 828, 446,
+ 26, 19, -31,
+ 698, 1692, 2168,
+ -646, -977, -1924,
+ -179, -473, 268,
+ -379, -745, -691,
+ 11, 127, 1033,
+ -488, -917, -825,
+ 61, 323, 135,
+ 147, -145, -686,
+ 685, 786, 1682,
+ -506, -848, -1297,
+ 35, 90, 222,
+ -23, -346, -670,
+ 455, 591, 1287,
+ -203, -593, -1086,
+ 652, 352, 437,
+ 39, 63, -457,
+ 841, 1265, 2105,
+ -520, -882, -1584,
+ -328, -711, 1421,
+ -596, -342, -70,
+ 209, 173, 1928,
+ -423, -598, -921,
+ 421, 605, -38,
+ -2, -245, -127,
+ 896, 1969, 1135,
+ -379, -518, -1579,
+ 173, 118, 753,
+ -55, -381, -52,
+ 985, 1021, 753,
+ -2, -291, -891,
+ 753, 992, 423,
+ 264, 131, -196,
+ 895, 2274, 2543,
+ -635, -1088, -2499,
+ -529, -982, 526,
+ -764, -830, -548,
+ -436, 316, 599,
+ -675, -940, -746,
+ -57, 236, -11,
+ -201, -81, -798,
+ 16, 845, 1558,
+ -737, -985, -1212,
+ -468, 17, 290,
+ -279, -584, -700,
+ 183, 822, 705,
+ -265, -492, -1187,
+ 421, 152, 468,
+ -390, 166, -268,
+ 39, 1550, 1868,
+ -635, -966, -1571,
+ -453, -492, 910,
+ -284, -1027, -75,
+ -181, -133, 1852,
+ -445, -624, -1174,
+ 420, 367, -49,
+ -389, -212, -169,
+ 707, 1073, 1208,
+ -539, -710, -1449,
+ 83, -163, 484,
+ -236, -543, -355,
+ 338, 1175, 814,
+ -246, -309, -958,
+ 606, 760, 60,
+ 166, -8, -163,
+ -306, 1849, 2563,
+ -747, -1025, -1783,
+ -419, -446, 209,
+ -718, -566, -534,
+ -506, 693, 857,
+ -463, -697, -1082,
+ 325, 431, -206,
+ -15, -8, -763,
+ 545, 919, 1518,
+ -611, -783, -1313,
+ 256, -55, 208,
+ -165, -348, -662,
+ 321, 680, 930,
+ -326, -429, -951,
+ 484, 446, 570,
+ -197, 72, -73,
+ 909, 1455, 1741,
+ -563, -737, -1974,
+ -124, -416, 718,
+ -478, -404, -314,
+ -16, 446, 1636,
+ -551, -537, -750,
+ -58, 638, 214,
+ 55, -185, -271,
+ 1148, 1301, 1212,
+ -483, -671, -1264,
+ 117, 285, 543,
+ -204, -391, -111,
+ 513, 1538, 854,
+ -114, -190, -978,
+ 877, 595, 464,
+ 260, 260, -311,
+ 748, 2283, 2216,
+ -517, -945, -2171,
+ -326, -708, 378,
+ -812, -691, -232,
+ -560, 687, 1409,
+ -732, -690, -836,
+ -359, 645, 386,
+ -265, 62, -678,
+ 145, 1644, 1208,
+ -555, -988, -1233,
+ -78, 14, 114,
+ -327, -358, -489,
+ 392, 677, 697,
+ -201, -236, -1140,
+ 693, 449, 178,
+ -243, 256, -433,
+ 611, 1385, 2456,
+ -612, -901, -1464,
+ -307, -17, 499,
+ -315, -667, -254,
+ 256, 428, 1463,
+ -486, -422, -1056,
+ 655, 370, 18,
+ -102, -185, -276,
+ 755, 1578, 1335,
+ -488, -603, -1418,
+ 182, -93, 870,
+ -73, -458, -348,
+ 835, 862, 957,
+ -282, -333, -746,
+ 547, 839, 428,
+ 273, -89, 13,
+ 940, 1708, 2576,
+ -418, -1084, -1758,
+ -44, -358, 259,
+ -497, -643, -560,
+ 99, 557, 961,
+ -421, -766, -917,
+ 295, 326, 184,
+ 175, 15, -626,
+ 532, 878, 1981,
+ -443, -768, -1275,
+ 221, 156, 268,
+ 39, -363, -505,
+ 695, 772, 1140,
+ -162, -459, -912,
+ 709, 444, 658,
+ 25, 303, -312,
+ 1268, 1410, 1715,
+ -297, -766, -1836,
+ -263, -108, 1070,
+ -406, -13, -129,
+ 57, 438, 2734,
+ -374, -487, -835,
+ 304, 696, 164,
+ 104, -235, 5,
+ 1611, 1900, 1399,
+ -229, -582, -1325,
+ 405, 192, 817,
+ -87, -438, 111,
+ 1028, 1199, 993,
+ 68, -175, -934,
+ 1033, 1117, 451,
+ 478, 200, -248,
+ 2127, 2696, 2042,
+ -835, -1323, -2131,
+ -799, -692, 466,
+ -812, -1032, -469,
+ -622, 288, 920,
+ -701, -841, -1070,
+ -411, 512, 8,
+ -390, -91, -744,
+ -30, 1043, 1161,
+ -822, -1148, -1156,
+ -294, -46, 110,
+ -411, -374, -678,
+ 214, 531, 668,
+ -406, -420, -1194,
+ 487, 232, 303,
+ -318, 91, -472,
+ 123, 1232, 2445,
+ -722, -952, -1495,
+ -738, -675, 1332,
+ -543, -606, -211,
+ -95, -98, 1508,
+ -549, -514, -1193,
+ 473, 211, 73,
+ -288, -112, -389,
+ 537, 1332, 1258,
+ -567, -755, -1545,
+ 71, -283, 632,
+ -170, -481, -493,
+ 681, 1002, 817,
+ -356, -331, -877,
+ 419, 706, 346,
+ 241, -34, -326,
+ 377, 1950, 1883,
+ -727, -1075, -1625,
+ -233, -543, 116,
+ -524, -806, -585,
+ -73, 478, 729,
+ -288, -925, -1143,
+ 173, 447, -52,
+ 68, -229, -606,
+ 449, 529, 1797,
+ -591, -875, -1363,
+ 183, -144, 324,
+ -103, -452, -666,
+ 623, 488, 1176,
+ -238, -511, -1004,
+ 326, 552, 458,
+ 136, 108, -319,
+ 626, 1343, 1883,
+ -490, -646, -1730,
+ -186, -449, 984,
+ -738, -76, -170,
+ -550, 755, 2560,
+ -496, -510, -947,
+ 210, 694, -52,
+ 84, -322, -199,
+ 1090, 1625, 1224,
+ -376, -603, -1396,
+ 343, 74, 632,
+ -175, -502, -32,
+ 972, 1332, 734,
+ 52, -295, -1113,
+ 1065, 918, 160,
+ 393, 107, -397,
+ 1214, 2649, 1741,
+ -632, -1201, -1891,
+ -719, -277, 353,
+ -651, -880, -122,
+ -211, 209, 1338,
+ -562, -714, -1059,
+ -208, 388, 159,
+ -320, -61, -551,
+ 293, 1092, 1443,
+ -648, -865, -1253,
+ -49, -143, 305,
+ -401, -227, -585,
+ 561, 532, 927,
+ -117, -443, -1188,
+ 507, 436, 292,
+ -79, 233, -458,
+ 671, 1025, 2396,
+ -633, -842, -1525,
+ -308, -286, 640,
+ -373, -621, -407,
+ 418, 253, 1305,
+ -315, -581, -1137,
+ 572, 685, -281,
+ 61, -68, -371,
+ 991, 1101, 1498,
+ -493, -683, -1362,
+ -47, 164, 704,
+ -256, -314, -268,
+ 631, 949, 1052,
+ -118, -348, -833,
+ 68, 1180, 568,
+ 152, 117, 34,
+ 1113, 1902, 2239,
+ -601, -959, -1706,
+ -143, -489, 480,
+ -332, -655, -574,
+ 54, 353, 1192,
+ -462, -652, -796,
+ 150, 549, 112,
+ 195, -111, -515,
+ 679, 1108, 1647,
+ -558, -749, -1217,
+ -9, 272, 341,
+ -53, -265, -535,
+ 489, 843, 1298,
+ -120, -482, -1032,
+ 632, 543, 408,
+ 179, 306, -526,
+ 1124, 1464, 2244,
+ -417, -786, -1562,
+ -224, -384, 1364,
+ -377, -459, -25,
+ 385, 489, 2174,
+ -332, -651, -829,
+ 544, 553, 61,
+ 22, -113, -89,
+ 1128, 1725, 1524,
+ -216, -373, -1653,
+ 161, 316, 908,
+ -165, -222, -67,
+ 1362, 1175, 789,
+ 73, -252, -767,
+ 738, 932, 616,
+ 362, 246, -126,
+ 787, 2654, 3027,
+ -691, -1106, -2190,
+ -565, -588, 524,
+ -590, -979, -490,
+ -263, 397, 982,
+ -577, -837, -945,
+ -22, 435, -49,
+ -190, -118, -629,
+ -88, 1240, 1513,
+ -636, -1051, -1019,
+ -291, 189, 259,
+ -257, -470, -629,
+ 145, 945, 894,
+ -326, -364, -1094,
+ 543, 260, 630,
+ -202, 189, -209,
+ 357, 1379, 2091,
+ -569, -1075, -1449,
+ -714, -239, 919,
+ -420, -705, -84,
+ -109, -114, 2407,
+ -413, -529, -1177,
+ 482, 368, 131,
+ -186, -72, -131,
+ 861, 1255, 1220,
+ -611, -658, -1341,
+ 227, -121, 631,
+ -176, -489, -218,
+ 745, 1175, 957,
+ -321, -148, -936,
+ 671, 966, 216,
+ 340, -3, -143,
+ 469, 1848, 2437,
+ -729, -961, -1683,
+ -213, -254, 321,
+ -511, -438, -521,
+ -126, 725, 903,
+ -340, -685, -1032,
+ 316, 480, 20,
+ 23, -89, -551,
+ 353, 1051, 1789,
+ -544, -757, -1364,
+ 298, -25, 436,
+ -100, -392, -519,
+ 467, 754, 1078,
+ -210, -398, -1078,
+ 620, 658, 630,
+ 33, 147, -178,
+ 921, 1687, 1921,
+ -325, -528, -1978,
+ 2, -285, 910,
+ -371, -490, -230,
+ 0, 597, 2010,
+ -496, -395, -834,
+ 37, 945, 245,
+ 181, -160, -144,
+ 1481, 1373, 1357,
+ -355, -601, -1270,
+ 298, 322, 672,
+ -193, -336, 77,
+ 1089, 1533, 922,
+ 177, -39, -1125,
+ 996, 781, 536,
+ 456, 366, -432,
+ 1415, 2440, 2279,
+ -466, -758, -2325,
+ -303, -509, 387,
+ -727, -557, 66,
+ -145, 643, 1248,
+ -544, -676, -916,
+ -225, 862, 588,
+ -152, 40, -533,
+ 423, 1423, 1558,
+ -572, -843, -1145,
+ -128, 85, 461,
+ -238, -257, -584,
+ 605, 748, 861,
+ 24, -202, -1409,
+ 797, 487, 303,
+ -181, 364, -182,
+ 616, 1378, 2942,
+ -494, -852, -1441,
+ -292, 61, 812,
+ -84, -723, -182,
+ 555, 532, 1506,
+ -365, -493, -1057,
+ 822, 588, 11,
+ -14, -18, -230,
+ 1001, 1401, 1451,
+ -474, -569, -1292,
+ 302, 62, 1062,
+ -70, -376, -222,
+ 982, 974, 1149,
+ -196, -234, -795,
+ 479, 1098, 499,
+ 362, 58, 70,
+ 1147, 2069, 2857,
+ -487, -878, -1824,
+ 73, -288, 348,
+ -358, -500, -508,
+ 199, 721, 1242,
+ -78, -697, -795,
+ 361, 536, 196,
+ 374, 110, -735,
+ 847, 1051, 1896,
+ -366, -713, -1182,
+ 315, 320, 429,
+ 72, -215, -450,
+ 759, 886, 1363,
+ -30, -428, -834,
+ 861, 627, 796,
+ 118, 468, -279,
+ 1355, 1883, 1893,
+ -188, -642, -1612,
+ 63, -175, 1198,
+ -418, -211, 51,
+ 414, 587, 2601,
+ -234, -557, -858,
+ 424, 889, 222,
+ 136, -101, 83,
+ 1413, 2278, 1383,
+ -84, -445, -1389,
+ 414, 313, 1045,
+ 29, -343, 65,
+ 1552, 1647, 980,
+ 183, -91, -829,
+ 1273, 1413, 360,
+ 553, 272, -107,
+ 1587, 3149, 2603
+};
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/q_plsf_5.cpp b/media/libstagefright/codecs/amrnb/common/src/q_plsf_5.cpp
new file mode 100644
index 0000000..2f9e40e
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/q_plsf_5.cpp
@@ -0,0 +1,691 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./audio/gsm-amr/c/src/q_plsf_5.c
+ Funtions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed code in the PV standard template format.
+ Updated to accept new parameter, Flag *pOverflow.
+
+ Description:
+ Eliminated unused include files.
+ For Vq_subvec()
+ 1. Eliminated math operations that unnecessary checked for
+ saturation (number are bounded to 2^12)
+ 2. Eliminated access to (slow) memory by using axiliar variables
+ 3. Because this routine is looking for the minimum distance,
+ introduced 3 check conditions inside the loop, so when the
+ partial distance is bigger than the minimun distance, the
+ loop is not completed and process continue with next iteration
+ For Vq_subvec_s()
+ 1. Eliminated math operations that unnecessary checked for
+ saturation (number are bounded to 2^12)
+ 2. Combined increasing and decreasing loops to avoid double
+ accesses to the same table element
+ 3. Eliminated access to (slow) memory by using axiliar variables
+ 4. Because this routine is looking for the minimum distance,
+ introduced 2 check conditions inside the loop, so when the
+ partial distance is bigger than the minimun distance, the
+ loop is not completed and process continue with next iteration
+ For Q_plsf_5()
+ 1. Eliminated math operations that unnecessary checked for
+ saturation (number are bounded to 2^12)
+ 2. Replaced array addressing by pointers
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "q_plsf.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "lsp_lsf.h"
+#include "reorder.h"
+#include "lsfwt.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ /* Codebooks of LSF prediction residual */
+ extern const Word16 mean_lsf_5[];
+
+ extern const Word16 dico1_lsf_5[];
+ extern const Word16 dico2_lsf_5[];
+ extern const Word16 dico3_lsf_5[];
+ extern const Word16 dico4_lsf_5[];
+ extern const Word16 dico5_lsf_5[];
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Vq_subvec
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsf_r1 -- array of type Word16 -- 1st LSF residual vector, Q15
+ lsf_r2 -- array of type Word16 -- 2nd LSF residual vector, Q15
+ dico -- pointer to const Word16 -- quantization codebook, Q15
+ wf1 -- array of type Word16 -- 1st LSF weighting factors, Q13
+ wf2 -- array of type Word16 -- 2nd LSF weighting factors, Q13
+ dico_size -- Word16 -- size of quantization codebook, Q0
+ Outputs:
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ Word16 -- quantization index, Q0
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the quantization of a 4-dimensional subvector.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ q_plsf_5.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+/* Quantization of a 4 dimensional subvector */
+
+static Word16 Vq_subvec( /* o : quantization index, Q0 */
+ Word16 *lsf_r1, /* i : 1st LSF residual vector, Q15 */
+ Word16 *lsf_r2, /* i : 2nd LSF residual vector, Q15 */
+ const Word16 *dico, /* i : quantization codebook, Q15 */
+ Word16 *wf1, /* i : 1st LSF weighting factors Q13 */
+ Word16 *wf2, /* i : 2nd LSF weighting factors Q13 */
+ Word16 dico_size, /* i : size of quantization codebook, Q0 */
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ Word16 index = 0; /* initialization only needed to keep gcc silent */
+ Word16 i;
+ Word16 temp;
+ const Word16 *p_dico;
+ Word32 dist_min;
+ Word32 dist;
+ Word16 wf1_0;
+ Word16 wf1_1;
+ Word16 wf2_0;
+ Word16 wf2_1;
+ Word32 aux1;
+ Word32 aux2;
+ Word32 aux3;
+ Word32 aux4;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ dist_min = MAX_32;
+ p_dico = dico;
+
+ wf1_0 = wf1[0];
+ wf1_1 = wf1[1];
+ wf2_0 = wf2[0];
+ wf2_1 = wf2[1];
+
+ aux1 = ((Word32) lsf_r1[0] * wf1_0);
+ aux2 = ((Word32) lsf_r1[1] * wf1_1);
+ aux3 = ((Word32) lsf_r2[0] * wf2_0);
+ aux4 = ((Word32) lsf_r2[1] * wf2_1);
+
+ for (i = 0; i < dico_size; i++)
+ {
+ temp = (aux1 - ((Word32)wf1_0 * *(p_dico++))) >> 15;
+ dist = ((Word32)temp * temp);
+
+ if (dist >= dist_min)
+ {
+ p_dico += 3;
+ continue;
+ }
+
+ temp = (aux2 - ((Word32)wf1_1 * *(p_dico++))) >> 15;
+ dist += ((Word32)temp * temp);
+
+ if (dist >= dist_min)
+ {
+ p_dico += 2;
+ continue;
+ }
+
+ temp = (aux3 - ((Word32)wf2_0 * *(p_dico++))) >> 15;
+ dist += ((Word32)temp * temp);
+
+ if (dist >= dist_min)
+ {
+ p_dico += 1;
+ continue;
+ }
+
+ temp = (aux4 - ((Word32)wf2_1 * *(p_dico++))) >> 15;
+ dist += ((Word32)temp * temp);
+
+
+ if (dist < dist_min)
+ {
+ dist_min = dist;
+ index = i;
+ }
+ }
+
+
+
+ /* Reading the selected vector */
+
+ p_dico = &dico[ index<<2];
+ lsf_r1[0] = *p_dico++;
+ lsf_r1[1] = *p_dico++;
+ lsf_r2[0] = *p_dico++;
+ lsf_r2[1] = *p_dico;
+
+ return index;
+
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Vq_subvec_s
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsf_r1 -- array of type Word16 -- 1st LSF residual vector, Q15
+ lsf_r2 -- array of type Word16 -- 2nd LSF residual vector, Q15
+ dico -- pointer to const Word16 -- quantization codebook, Q15
+ wf1 -- array of type Word16 -- 1st LSF weighting factors, Q13
+ wf2 -- array of type Word16 -- 2nd LSF weighting factors, Q13
+ dico_size -- Word16 -- size of quantization codebook, Q0
+
+ Outputs:
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ Word16 -- quantization index, Q0
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the quantization of a 4-dimensional subvector.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ q_plsf_5.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+
+/* Quantization of a 4 dimensional subvector with a signed codebook */
+
+static Word16 Vq_subvec_s( /* o : quantization index Q0 */
+ Word16 *lsf_r1, /* i : 1st LSF residual vector Q15 */
+ Word16 *lsf_r2, /* i : and LSF residual vector Q15 */
+ const Word16 *dico, /* i : quantization codebook Q15 */
+ Word16 *wf1, /* i : 1st LSF weighting factors Q13 */
+ Word16 *wf2, /* i : 2nd LSF weighting factors Q13 */
+ Word16 dico_size, /* i : size of quantization codebook Q0 */
+ Flag *pOverflow) /* o : overflow indicator */
+{
+ Word16 index = 0; /* initialization only needed to keep gcc silent */
+ Word16 sign = 0; /* initialization only needed to keep gcc silent */
+ Word16 i;
+ Word16 temp;
+ Word16 temp1;
+ Word16 temp2;
+ const Word16 *p_dico;
+ Word32 dist_min;
+ Word32 dist1;
+ Word32 dist2;
+
+ Word16 lsf_r1_0;
+ Word16 lsf_r1_1;
+ Word16 lsf_r2_0;
+ Word16 lsf_r2_1;
+
+ Word16 wf1_0;
+ Word16 wf1_1;
+ Word16 wf2_0;
+ Word16 wf2_1;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ dist_min = MAX_32;
+ p_dico = dico;
+
+
+ lsf_r1_0 = lsf_r1[0];
+ lsf_r1_1 = lsf_r1[1];
+ lsf_r2_0 = lsf_r2[0];
+ lsf_r2_1 = lsf_r2[1];
+
+ wf1_0 = wf1[0];
+ wf1_1 = wf1[1];
+ wf2_0 = wf2[0];
+ wf2_1 = wf2[1];
+
+ for (i = 0; i < dico_size; i++)
+ {
+ /* test positive */
+ temp = *p_dico++;
+ temp1 = lsf_r1_0 - temp;
+ temp2 = lsf_r1_0 + temp;
+ temp1 = ((Word32)wf1_0 * temp1) >> 15;
+ temp2 = ((Word32)wf1_0 * temp2) >> 15;
+ dist1 = ((Word32)temp1 * temp1);
+ dist2 = ((Word32)temp2 * temp2);
+
+ temp = *p_dico++;
+ temp1 = lsf_r1_1 - temp;
+ temp2 = lsf_r1_1 + temp;
+ temp1 = ((Word32)wf1_1 * temp1) >> 15;
+ temp2 = ((Word32)wf1_1 * temp2) >> 15;
+ dist1 += ((Word32)temp1 * temp1);
+ dist2 += ((Word32)temp2 * temp2);
+
+ if ((dist1 >= dist_min) && (dist2 >= dist_min))
+ {
+ p_dico += 2;
+ continue;
+ }
+
+ temp = *p_dico++;
+ temp1 = lsf_r2_0 - temp;
+ temp2 = lsf_r2_0 + temp;
+ temp1 = ((Word32)wf2_0 * temp1) >> 15;
+ temp2 = ((Word32)wf2_0 * temp2) >> 15;
+ dist1 += ((Word32)temp1 * temp1);
+ dist2 += ((Word32)temp2 * temp2);
+
+ temp = *p_dico++;
+ temp1 = lsf_r2_1 - temp;
+ temp2 = lsf_r2_1 + temp;
+ temp1 = ((Word32)wf2_1 * temp1) >> 15;
+ temp2 = ((Word32)wf2_1 * temp2) >> 15;
+ dist1 += ((Word32)temp1 * temp1);
+ dist2 += ((Word32)temp2 * temp2);
+
+ if (dist1 < dist_min)
+ {
+ dist_min = dist1;
+ index = i;
+ sign = 0;
+ }
+
+ /* test negative */
+
+ if (dist2 < dist_min)
+ {
+ dist_min = dist2;
+ index = i;
+ sign = 1;
+ }
+ }
+
+ /* Reading the selected vector */
+
+ p_dico = &dico[index<<2];
+ index <<= 1;
+ if (sign)
+ {
+ lsf_r1[0] = - (*p_dico++);
+ lsf_r1[1] = - (*p_dico++);
+ lsf_r2[0] = - (*p_dico++);
+ lsf_r2[1] = - (*p_dico);
+ index += 1;
+ }
+ else
+ {
+ lsf_r1[0] = *p_dico++;
+ lsf_r1[1] = *p_dico++;
+ lsf_r2[0] = *p_dico++;
+ lsf_r2[1] = *p_dico;
+ }
+
+ return index;
+
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Q_plsf_5
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+ Inputs:
+ st -- pointer to Q_plsfState -- state information
+ lsp1 -- array of type Word16 -- 1st LSP vector, Q15
+ lsp2 -- array of type Word16 -- 2nd LSP vector, Q15
+
+ Outputs:
+ lps1_q -- array of type Word16 -- quantized 1st LSP vector, Q15
+ lps2_q -- array of type Word16 -- quantized 2nd LSP vector, Q15
+ indices -- array of type Word16 -- quantization indices of 5 matrics, Q0
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ mean_lsf_5[];
+
+ dico1_lsf_5[];
+ dico2_lsf_5[];
+ dico3_lsf_5[];
+ dico4_lsf_5[];
+ dico5_lsf_5[];
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Quantization of 2 sets of LSF parameters using 1st order MA
+ prediction and split by 5 matrix quantization (split-MQ)
+
+ DESCRIPTION:
+
+ p[i] = pred_factor*past_rq[i]; i=0,...,m-1
+ r1[i]= lsf1[i] - p[i]; i=0,...,m-1
+ r2[i]= lsf2[i] - p[i]; i=0,...,m-1
+ where:
+ lsf1[i] 1st mean-removed LSF vector.
+ lsf2[i] 2nd mean-removed LSF vector.
+ r1[i] 1st residual prediction vector.
+ r2[i] 2nd residual prediction vector.
+ past_r2q[i] Past quantized residual (2nd vector).
+
+ The residual vectors r1[i] and r2[i] are jointly quantized using
+ split-MQ with 5 codebooks. Each 4th dimension submatrix contains 2
+ elements from each residual vector. The 5 submatrices are as follows:
+ {r1[0], r1[1], r2[0], r2[1]}; {r1[2], r1[3], r2[2], r2[3]};
+ {r1[4], r1[5], r2[4], r2[5]}; {r1[6], r1[7], r2[6], r2[7]};
+ {r1[8], r1[9], r2[8], r2[9]}
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ q_plsf_5.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Q_plsf_5(
+ Q_plsfState *st,
+ Word16 *lsp1, /* i : 1st LSP vector, Q15 */
+ Word16 *lsp2, /* i : 2nd LSP vector, Q15 */
+ Word16 *lsp1_q, /* o : quantized 1st LSP vector, Q15 */
+ Word16 *lsp2_q, /* o : quantized 2nd LSP vector, Q15 */
+ Word16 *indice, /* o : quantization indices of 5 matrices, Q0 */
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ Word16 i;
+ Word16 lsf1[M];
+ Word16 lsf2[M];
+ Word16 wf1[M];
+ Word16 wf2[M];
+ Word16 lsf_p[M];
+ Word16 lsf_r1[M];
+ Word16 lsf_r2[M];
+ Word16 lsf1_q[M];
+ Word16 lsf2_q[M];
+
+ Word16 *p_lsf_p;
+ Word16 *p_lsf1;
+ Word16 *p_lsf2;
+ Word16 *p_lsf_r1;
+ Word16 *p_lsf_r2;
+
+ /* convert LSFs to normalize frequency domain 0..16384 */
+
+ Lsp_lsf(lsp1, lsf1, M, pOverflow);
+ Lsp_lsf(lsp2, lsf2, M, pOverflow);
+
+ /* Compute LSF weighting factors (Q13) */
+
+ Lsf_wt(lsf1, wf1, pOverflow);
+ Lsf_wt(lsf2, wf2, pOverflow);
+
+ /* Compute predicted LSF and prediction error */
+
+ p_lsf_p = &lsf_p[0];
+ p_lsf1 = &lsf1[0];
+ p_lsf2 = &lsf2[0];
+ p_lsf_r1 = &lsf_r1[0];
+ p_lsf_r2 = &lsf_r2[0];
+
+ for (i = 0; i < M; i++)
+ {
+ *(p_lsf_p) = mean_lsf_5[i] +
+ (((Word32)st->past_rq[i] * LSP_PRED_FAC_MR122) >> 15);
+
+ *(p_lsf_r1++) = *(p_lsf1++) - *(p_lsf_p);
+ *(p_lsf_r2++) = *(p_lsf2++) - *(p_lsf_p++);
+ }
+
+ /*---- Split-MQ of prediction error ----*/
+
+ indice[0] = Vq_subvec(&lsf_r1[0], &lsf_r2[0], dico1_lsf_5,
+ &wf1[0], &wf2[0], DICO1_5_SIZE, pOverflow);
+
+ indice[1] = Vq_subvec(&lsf_r1[2], &lsf_r2[2], dico2_lsf_5,
+ &wf1[2], &wf2[2], DICO2_5_SIZE, pOverflow);
+
+ indice[2] = Vq_subvec_s(&lsf_r1[4], &lsf_r2[4], dico3_lsf_5,
+ &wf1[4], &wf2[4], DICO3_5_SIZE, pOverflow);
+
+ indice[3] = Vq_subvec(&lsf_r1[6], &lsf_r2[6], dico4_lsf_5,
+ &wf1[6], &wf2[6], DICO4_5_SIZE, pOverflow);
+
+ indice[4] = Vq_subvec(&lsf_r1[8], &lsf_r2[8], dico5_lsf_5,
+ &wf1[8], &wf2[8], DICO5_5_SIZE, pOverflow);
+
+ /* Compute quantized LSFs and update the past quantized residual */
+
+ p_lsf_r1 = &lsf_r1[0];
+ p_lsf_r2 = &lsf_r2[0];
+ p_lsf_p = &lsf_p[0];
+ p_lsf1 = &lsf1_q[0];
+ p_lsf2 = &lsf2_q[0];
+
+
+ for (i = 0; i < M; i++)
+ {
+ *(p_lsf1++) = *(p_lsf_r1++) + *(p_lsf_p);
+ *(p_lsf2++) = *(p_lsf_r2) + *(p_lsf_p++);
+ st->past_rq[i] = *(p_lsf_r2++);
+ }
+
+ /* verification that LSFs has minimum distance of LSF_GAP */
+
+ Reorder_lsf(lsf1_q, LSF_GAP, M, pOverflow);
+ Reorder_lsf(lsf2_q, LSF_GAP, M, pOverflow);
+
+ /* convert LSFs to the cosine domain */
+
+ Lsf_lsp(lsf1_q, lsp1_q, M, pOverflow);
+ Lsf_lsp(lsf2_q, lsp2_q, M, pOverflow);
+}
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/q_plsf_5_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/q_plsf_5_tbl.cpp
new file mode 100644
index 0000000..caa81cb
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/q_plsf_5_tbl.cpp
@@ -0,0 +1,1164 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/q_plsf_5_tbl.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created this file from the reference, q_plsf_5_tbl.tab
+
+ Description: Changed #defines of DICO_SIZE to DICO_5_SIZE, to avoid name
+ conflicts.
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "q_plsf_5_tbl.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+#define NB_QUA_PITCH 16
+#define NB_QUA_CODE 32
+
+
+#define DICO1_5_SIZE 128
+#define DICO2_5_SIZE 256
+#define DICO3_5_SIZE 256
+#define DICO4_5_SIZE 256
+#define DICO5_5_SIZE 64
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+ /* LSF means ->normalize frequency domain */
+
+ const Word16 mean_lsf_5[10] =
+ {
+ 1384,
+ 2077,
+ 3420,
+ 5108,
+ 6742,
+ 8122,
+ 9863,
+ 11092,
+ 12714,
+ 13701
+ };
+
+ const Word16 dico1_lsf_5[DICO1_5_SIZE * 4] =
+ {
+ -451, -1065, -529, -1305,
+ -450, -756, -497, -863,
+ -384, -619, -413, -669,
+ -317, -538, -331, -556,
+ -414, -508, -424, -378,
+ -274, -324, -434, -614,
+ -226, -500, -232, -514,
+ -263, -377, -298, -410,
+ -151, -710, -174, -818,
+ -149, -412, -156, -429,
+ -288, -462, -186, -203,
+ -170, -302, -191, -321,
+ -131, -147, -297, -395,
+ -228, -214, -245, -192,
+ -67, -316, -71, -327,
+ -104, -205, -94, -183,
+ -143, -38, -193, -95,
+ 16, -76, -124, -248,
+ 23, -237, 24, -244,
+ 18, -136, 44, -111,
+ -33, -24, -25, 0,
+ 149, 19, 23, -143,
+ 158, -169, 174, -181,
+ 133, -55, 165, -26,
+ 111, 84, 98, 75,
+ 87, 183, -115, -11,
+ -8, 130, 11, 170,
+ 254, 77, 205, 17,
+ 183, 112, 262, 194,
+ 202, 287, 95, 189,
+ -42, -105, 234, 179,
+ 39, 186, 163, 345,
+ 332, 199, 299, 161,
+ -54, 285, -78, 281,
+ -133, 141, -182, 111,
+ 249, 341, 271, 364,
+ 93, 403, 75, 391,
+ 92, 510, -138, 220,
+ -185, -29, -34, 361,
+ -115, 320, 3, 554,
+ 99, 286, 218, 591,
+ -245, 406, -268, 453,
+ 0, 580, 25, 606,
+ 275, 532, 148, 450,
+ -73, 739, -285, 518,
+ -288, 94, -203, 674,
+ -140, -74, 205, 714,
+ -114, 299, 176, 923,
+ 182, 557, 240, 705,
+ -16, 513, 485, 593,
+ 293, 384, 451, 617,
+ -38, 50, 563, 529,
+ 303, 209, 459, 363,
+ 433, 452, 450, 454,
+ 367, 606, 477, 741,
+ 432, 353, 368, 267,
+ 361, 716, 273, 583,
+ 453, 166, 510, 172,
+ 201, 629, 274, 191,
+ 568, 639, 302, 298,
+ 634, 387, 643, 350,
+ 587, 560, 612, 565,
+ 600, 788, 487, 672,
+ 512, 1015, 321, 333,
+ 357, 854, -125, 413,
+ 474, 712, 17, -151,
+ 564, 285, 270, -241,
+ 971, 889, 489, 220,
+ 510, 896, 549, 924,
+ 327, 825, 290, 911,
+ 540, 1108, 158, 805,
+ 199, 957, 511, 730,
+ 100, 874, 13, 791,
+ 435, 632, 676, 972,
+ 249, 900, 467, 1218,
+ 781, 1074, 585, 785,
+ -23, 669, 267, 1043,
+ 619, 1084, 615, 1145,
+ 622, 905, 916, 1049,
+ 80, 331, 584, 1075,
+ 89, 639, 988, 961,
+ 770, 720, 798, 699,
+ 492, 447, 899, 627,
+ 271, 1188, 725, 1333,
+ 87, 603, 832, 1603,
+ 616, 1127, 890, 1505,
+ 1000, 1156, 866, 1009,
+ 995, 827, 1149, 858,
+ 817, 1450, 773, 1320,
+ 500, 1389, 312, 1153,
+ -20, 1084, 64, 1283,
+ 2, 1172, 399, 1869,
+ 514, 1706, 502, 1636,
+ 886, 1522, 416, 600,
+ 1131, 1350, 1275, 1390,
+ 889, 1795, 914, 1766,
+ 227, 1183, 1250, 1826,
+ 505, 1854, 919, 2353,
+ -199, 431, 152, 1735,
+ -213, -28, 392, 1334,
+ -153, -52, 978, 1151,
+ -323, -400, 813, 1703,
+ -136, 84, 1449, 2015,
+ -331, -143, -137, 1192,
+ -256, 534, -157, 1031,
+ -307, -439, 542, 731,
+ -329, -420, -97, 616,
+ -362, -168, -322, 366,
+ -247, -110, -211, 89,
+ -196, -309, 20, 59,
+ -364, -463, -286, 89,
+ -336, 175, -432, 141,
+ -379, -190, -434, -196,
+ -79, 150, -278, -227,
+ -280, 166, -555, -422,
+ -155, 541, -366, 54,
+ -29, -83, -301, -774,
+ 186, 628, -397, -264,
+ 242, 293, -197, -585,
+ 124, 410, 53, -133,
+ 10, 340, -570, -1065,
+ 65, -446, 68, -493,
+ 383, 937, -357, -711,
+ -359, -250, -677, -1068,
+ 292, -26, 363, 6,
+ 607, 1313, -127, -10,
+ 1513, 1886, 713, 972,
+ 1469, 2181, 1443, 2016
+ };
+
+ const Word16 dico2_lsf_5[DICO2_5_SIZE * 4] =
+ {
+ -1631, -1600, -1796, -2290,
+ -1027, -1770, -1100, -2025,
+ -1277, -1388, -1367, -1534,
+ -947, -1461, -972, -1524,
+ -999, -1222, -1020, -1172,
+ -815, -987, -992, -1371,
+ -1216, -1006, -1289, -1094,
+ -744, -1268, -755, -1293,
+ -862, -923, -905, -984,
+ -678, -1051, -685, -1050,
+ -1087, -985, -1062, -679,
+ -989, -641, -1127, -976,
+ -762, -654, -890, -806,
+ -833, -1091, -706, -629,
+ -621, -806, -640, -812,
+ -775, -634, -779, -543,
+ -996, -565, -1075, -580,
+ -546, -611, -572, -619,
+ -760, -290, -879, -526,
+ -823, -462, -795, -253,
+ -553, -415, -589, -439,
+ -533, -340, -692, -935,
+ -505, -772, -702, -1131,
+ -263, -306, -971, -483,
+ -445, -74, -555, -548,
+ -614, -129, -693, -234,
+ -396, -246, -475, -250,
+ -265, -404, -376, -514,
+ -417, -510, -300, -313,
+ -334, -664, -463, -814,
+ -386, -704, -337, -615,
+ -234, -201, -233, -239,
+ -167, -567, -203, -619,
+ -147, -415, -115, -352,
+ -166, -750, -171, -761,
+ -270, -879, -264, -903,
+ -367, -744, 43, -475,
+ 14, -653, 43, -670,
+ 11, -448, -59, -521,
+ -126, -119, -155, -613,
+ -42, -863, -27, -931,
+ 136, -483, 183, -468,
+ 55, -298, 55, -304,
+ 313, -609, 313, -720,
+ 322, -167, 100, -541,
+ -3, -119, -111, -187,
+ 233, -236, 260, -234,
+ 26, -165, 134, -45,
+ -40, -549, 360, -203,
+ 378, -388, 450, -383,
+ 275, 20, 182, -103,
+ 246, -111, 431, 37,
+ 462, -146, 487, -157,
+ -284, -59, 503, -184,
+ 24, 53, -3, 54,
+ 122, 259, 333, 66,
+ 484, 104, 436, 68,
+ 195, 116, 190, 206,
+ 269, -9, 482, 352,
+ 382, 285, 399, 277,
+ 452, 256, 69, 186,
+ 13, 297, -13, 259,
+ -95, 30, 56, 394,
+ 196, 425, 205, 456,
+ 281, 577, 15, 191,
+ 375, 290, 407, 576,
+ -56, 227, 544, 405,
+ 0, 549, -92, 528,
+ -229, 351, -245, 338,
+ -362, 435, 167, 527,
+ -75, 302, 91, 824,
+ 129, 599, 496, 679,
+ 186, 749, 153, 737,
+ -281, 600, -348, 615,
+ -236, 769, 41, 881,
+ 38, 890, -220, 841,
+ -357, 883, -393, 903,
+ -634, 474, -444, 850,
+ -175, 678, -493, 242,
+ -519, 785, -714, 582,
+ -541, 366, -543, 434,
+ -597, 500, -765, 222,
+ -702, 917, -743, 962,
+ -869, 501, -899, 548,
+ -379, 200, -435, 157,
+ -819, 214, -861, 157,
+ -614, 40, -632, 94,
+ -883, -54, -741, 516,
+ -501, 298, -614, -171,
+ -870, -161, -865, -23,
+ -818, 93, -1015, -267,
+ -662, -359, -549, 2,
+ -442, -121, -377, 0,
+ -227, 33, -414, -126,
+ -129, 212, -934, 34,
+ -1082, -282, -1119, -268,
+ -710, -825, -420, -191,
+ -1076, -928, -917, -93,
+ -628, -358, 97, 7,
+ -206, -393, -101, 24,
+ -203, 38, -168, 83,
+ -599, -423, -279, 426,
+ -700, 118, -75, 206,
+ -981, -673, -680, 417,
+ -367, 37, -279, 474,
+ -129, -318, 319, 296,
+ -626, -39, 343, 602,
+ -696, -39, -303, 940,
+ 104, 233, -380, 137,
+ -36, 269, -75, -214,
+ 120, 43, -529, -477,
+ 459, 164, -202, -229,
+ -49, -167, 609, 792,
+ 98, -220, 915, 148,
+ 293, 283, 869, 91,
+ 575, 394, 326, -78,
+ 717, 67, 365, -323,
+ 616, -36, 731, 27,
+ 619, 238, 632, 273,
+ 448, 99, 801, 476,
+ 869, 273, 685, 64,
+ 789, 72, 1021, 217,
+ 793, 459, 734, 360,
+ 646, 480, 360, 322,
+ 429, 464, 638, 430,
+ 756, 363, 1000, 404,
+ 683, 528, 602, 615,
+ 655, 413, 946, 687,
+ 937, 602, 904, 604,
+ 555, 737, 786, 662,
+ 467, 654, 362, 589,
+ 929, 710, 498, 478,
+ 415, 420, 693, 883,
+ 813, 683, 781, 925,
+ 913, 939, 726, 732,
+ 491, 853, 531, 948,
+ 734, 963, 315, 808,
+ 761, 755, 1144, 760,
+ 655, 1076, 826, 1057,
+ 1091, 838, 1003, 808,
+ 1047, 1133, 659, 1101,
+ 992, 1050, 1074, 1075,
+ 971, 694, 1226, 1054,
+ 571, 841, 884, 1404,
+ 1379, 1096, 1080, 861,
+ 1231, 735, 1284, 760,
+ 1272, 991, 1367, 1053,
+ 1257, 700, 1050, 534,
+ 988, 453, 1264, 599,
+ 1140, 679, 1621, 815,
+ 1384, 521, 1317, 393,
+ 1564, 805, 1448, 686,
+ 1068, 648, 875, 307,
+ 1083, 361, 1047, 317,
+ 1417, 964, 675, 571,
+ 1152, 79, 1114, -47,
+ 1530, 311, 1721, 314,
+ 1166, 689, 514, -94,
+ 349, 282, 1412, 328,
+ 1025, 487, -65, 57,
+ 805, 970, 36, 62,
+ 769, -263, 791, -346,
+ 637, 699, -137, 620,
+ 534, 541, -735, 194,
+ 711, 300, -268, -863,
+ 926, 769, -708, -428,
+ 506, 174, -892, -630,
+ 435, 547, -1435, -258,
+ 621, 471, -1018, -1368,
+ -393, 521, -920, -686,
+ -25, 20, -982, -1156,
+ 340, 9, -1558, -1135,
+ -352, 48, -1579, -402,
+ -887, 6, -1156, -888,
+ -548, -352, -1643, -1168,
+ -159, 610, -2024, -963,
+ -225, 193, -1656, -1960,
+ -245, -493, -964, -1680,
+ -936, -635, -1299, -1744,
+ -1388, -604, -1540, -835,
+ -1397, -135, -1588, -290,
+ -1670, -712, -2011, -1632,
+ -1663, -27, -2258, -811,
+ -1157, 184, -1265, 189,
+ -1367, 586, -2011, 201,
+ -790, 712, -1210, 3,
+ -1033, 808, -1251, 830,
+ -111, 635, -1636, 447,
+ -463, -949, -445, -928,
+ -504, -1162, -501, -1211,
+ 144, -351, -372, -1052,
+ -283, -1059, -279, -1123,
+ -575, -1438, -587, -1614,
+ -935, -984, 229, 690,
+ -921, -719, -403, 1362,
+ -685, -465, 874, 397,
+ -509, -46, 317, 1334,
+ -485, 456, 813, 439,
+ -411, 339, 898, 1067,
+ -425, 46, 1441, 497,
+ -909, -800, 1465, 1046,
+ -254, -321, 1430, 1165,
+ 68, 350, 1034, 666,
+ 370, 11, 1311, 790,
+ 143, 232, 1041, 1562,
+ -114, 663, 1616, 1078,
+ 454, 579, 1275, 1040,
+ -76, 909, 752, 1067,
+ 153, 512, 348, 1214,
+ 614, 385, 1843, 808,
+ 269, 1034, 203, 1086,
+ 652, 1017, 1783, 1130,
+ 429, 1327, 387, 1384,
+ -49, 1183, -72, 1215,
+ -416, 1001, 544, 1749,
+ -352, 1223, -502, 1199,
+ -589, 569, -227, 1630,
+ -142, 1578, -230, 1715,
+ -714, 1288, -838, 1398,
+ 1131, 1357, -208, 1232,
+ 437, 965, -929, 818,
+ 811, 1410, 859, 1507,
+ 164, 1212, 1387, 1793,
+ 484, 1874, 456, 2063,
+ 996, 1170, 1326, 1402,
+ 1316, 1360, 1135, 1262,
+ 1234, 1618, 1361, 1768,
+ 1421, 1227, 1584, 1347,
+ 854, 672, 1685, 1566,
+ 1139, 1270, 2016, 1825,
+ 1773, 1581, 1532, 1460,
+ 1487, 946, 1659, 1021,
+ 1744, 1212, 1392, 977,
+ 1772, 1161, 1826, 1164,
+ 1718, 1429, 1973, 1591,
+ 1185, 864, 2132, 1061,
+ 1799, 814, 1838, 757,
+ 2104, 1315, 2054, 1258,
+ 2113, 915, 2331, 930,
+ 1467, 1147, 2590, 1439,
+ 2245, 1744, 2090, 1620,
+ 2358, 1454, 2666, 1506,
+ 1876, 1837, 2070, 1975,
+ 1739, 1577, 682, 1289,
+ 1584, 2045, 1454, 2098,
+ 2498, 2004, 2711, 2066,
+ 726, 1588, 2756, 2336,
+ 228, 847, 2456, 1659,
+ 36, 301, 1942, 1957,
+ -446, -96, 2154, 1396,
+ 1533, 1101, 14, 608,
+ -923, -732, 1383, 1982,
+ 1345, 952, -680, 321,
+ 1281, 1268, -1594, 365,
+ 941, 946, -1737, -822,
+ 2374, 2787, 1821, 2788
+ };
+
+ const Word16 dico3_lsf_5[DICO3_5_SIZE * 4] =
+ {
+ -1812, -2275, -1879, -2537,
+ -1640, -1848, -1695, -2004,
+ -1220, -1912, -1221, -2106,
+ -1559, -1588, -1573, -1556,
+ -1195, -1615, -1224, -1727,
+ -1359, -1151, -1616, -1948,
+ -1274, -1391, -1305, -1403,
+ -1607, -1179, -1676, -1311,
+ -1443, -1478, -1367, -898,
+ -1256, -1059, -1331, -1134,
+ -982, -1133, -1149, -1504,
+ -1080, -1308, -1020, -1183,
+ -980, -1486, -967, -1495,
+ -988, -922, -1047, -1077,
+ -838, -1179, -858, -1222,
+ -1131, -1041, -1064, -767,
+ -872, -1157, -701, -880,
+ -706, -906, -774, -1016,
+ -578, -1080, -801, -1478,
+ -591, -1111, -592, -1146,
+ -713, -1388, -640, -1376,
+ -597, -1059, -416, -903,
+ -686, -832, -661, -708,
+ -444, -868, -490, -921,
+ -374, -776, -619, -1170,
+ -585, -549, -769, -795,
+ -435, -659, -530, -741,
+ -498, -837, -357, -597,
+ -279, -871, -243, -887,
+ -282, -665, -280, -667,
+ -165, -560, -394, -903,
+ -362, -410, -448, -583,
+ -409, -574, -313, -357,
+ -637, -548, -570, -436,
+ -896, -504, -382, -757,
+ -58, -481, -165, -618,
+ -191, -374, -234, -382,
+ -222, -683, -25, -480,
+ -418, -359, -730, -353,
+ -324, -157, -432, -322,
+ -394, -303, -284, -104,
+ -601, -289, -556, -196,
+ -588, -150, -659, -608,
+ -473, -24, -68, -448,
+ -474, -8, -506, -45,
+ -748, -184, -844, -252,
+ -901, -91, -584, -97,
+ -652, 138, -764, -131,
+ -678, -12, -670, 165,
+ -259, -3, -840, -107,
+ -909, 37, -992, 44,
+ -854, -415, -839, 13,
+ -1001, -271, -1026, -309,
+ -798, -478, -832, -488,
+ -943, 168, -1112, -387,
+ -1185, -101, -1183, -40,
+ -941, -316, -1030, -770,
+ -1044, -625, -1081, -538,
+ -1224, -299, -1312, -436,
+ -1197, -663, -1167, -161,
+ -1216, -690, -1237, -831,
+ -1432, -720, -1403, -493,
+ -898, -740, -922, -801,
+ -1102, -402, -1579, -964,
+ -1061, -638, -1269, -1438,
+ -1499, -934, -1502, -895,
+ -1598, -564, -1723, -717,
+ -606, -597, -1166, -1085,
+ -1369, -468, -1946, -1493,
+ -1838, -953, -1932, -931,
+ -1499, -188, -1635, -421,
+ -1457, -338, -1448, -22,
+ -1942, -422, -2006, -249,
+ -496, -114, -1910, -755,
+ -1289, 174, -1451, -109,
+ -482, -257, -1221, -508,
+ -1617, 151, -1694, 208,
+ -654, 107, -1651, 29,
+ -1141, 279, -1215, 306,
+ -1228, -506, -730, -175,
+ -1236, -101, -969, 551,
+ -870, 278, -823, 315,
+ -563, 376, -1051, 228,
+ -507, 280, -599, 281,
+ -758, 253, -305, 379,
+ -755, -134, -611, 660,
+ -824, 536, -817, 646,
+ -413, 49, -341, 177,
+ -453, 526, -482, 589,
+ -71, 339, -657, 264,
+ -244, 295, -237, 315,
+ -387, 569, -506, -9,
+ -377, 14, -160, 661,
+ -216, 40, -308, -46,
+ 95, 214, -242, 167,
+ -86, 192, -56, 27,
+ -76, 31, 36, 309,
+ -106, -182, -113, 74,
+ -441, -22, 23, 139,
+ 81, -11, 44, 15,
+ -87, -137, -118, -207,
+ -158, -58, 272, -92,
+ -156, -441, 8, -136,
+ 128, -221, 101, -218,
+ 40, -197, -76, -456,
+ 9, -445, 33, -423,
+ 226, 60, 73, -222,
+ 156, -399, 280, -318,
+ 245, -341, 166, -499,
+ 339, -190, 327, -219,
+ 325, -137, -89, -596,
+ 100, -627, 144, -677,
+ 487, 28, 252, -391,
+ 214, -41, 282, -28,
+ 99, -286, 331, 49,
+ 459, -388, 565, -369,
+ 436, 28, 336, -9,
+ 397, -167, 618, 34,
+ 596, -17, 561, -140,
+ 299, 79, 522, 125,
+ 203, 2, 244, 288,
+ 255, 211, 175, 82,
+ 596, 187, 517, 108,
+ 381, 255, 365, 297,
+ 497, 352, 327, -82,
+ 25, 210, 371, 245,
+ 261, 3, 545, 449,
+ 140, 294, 44, 295,
+ 212, 347, 244, 494,
+ 331, 528, 201, 307,
+ 349, 411, 613, 284,
+ 614, 413, 464, 322,
+ 624, 397, 97, 200,
+ -160, 384, 149, 362,
+ 495, 525, 269, 585,
+ 33, 491, -121, 433,
+ 427, 611, 498, 516,
+ 171, 443, 497, 666,
+ 440, 275, 566, 575,
+ 146, 639, 155, 670,
+ -33, 173, 212, 696,
+ -166, 601, -191, 695,
+ -489, 503, 175, 742,
+ 214, 476, 372, 1083,
+ 578, 530, 586, 777,
+ 425, 874, 315, 841,
+ 374, 848, -165, 565,
+ 35, 991, -39, 1062,
+ 329, 712, 786, 840,
+ 645, 795, 661, 676,
+ 571, 918, 632, 1079,
+ 673, 817, 318, 388,
+ 874, 1012, 564, 848,
+ 880, 620, 557, 479,
+ 671, 453, 692, 468,
+ 840, 642, 844, 645,
+ 506, 428, 897, 567,
+ 837, 387, 962, 499,
+ 691, 561, 939, 926,
+ 783, 296, 790, 268,
+ 1028, 530, 874, 329,
+ 548, 143, 675, 291,
+ 503, 66, 1041, 359,
+ 786, 97, 805, 33,
+ 837, 470, 511, 49,
+ 1092, 327, 1174, 323,
+ 3, 242, 872, 474,
+ 689, 429, 1329, 678,
+ 1042, 620, 1109, 664,
+ 321, 193, 889, 950,
+ 1153, 874, 893, 635,
+ 877, 862, 948, 913,
+ 1293, 665, 1320, 639,
+ 997, 793, 1402, 1030,
+ 1176, 1012, 1110, 959,
+ 1410, 925, 1403, 915,
+ 543, 862, 1116, 1222,
+ 835, 1190, 835, 1190,
+ 959, 1148, 1147, 1376,
+ 1300, 1193, 1415, 1231,
+ 1335, 1341, 746, 1092,
+ 1711, 1283, 1389, 1073,
+ 1334, 1566, 1153, 1475,
+ 1645, 1137, 1825, 1220,
+ 1056, 1382, 1521, 1730,
+ 1632, 1545, 1620, 1542,
+ 855, 1596, 865, 1667,
+ 693, 885, 1716, 1519,
+ 1167, 1296, 2209, 1760,
+ 1952, 1493, 2020, 1482,
+ 1534, 1866, 1694, 2008,
+ 1566, 748, 1761, 825,
+ 294, 1392, 1084, 2058,
+ 621, 1315, 365, 1287,
+ 198, 1028, 488, 1408,
+ 249, 403, 1014, 1561,
+ 324, 363, 1645, 1044,
+ 193, 367, 2034, 1859,
+ -251, 579, 750, 994,
+ -243, 30, 1325, 879,
+ -28, -169, 624, 917,
+ -453, 159, 186, 1370,
+ -614, 6, 537, 392,
+ -94, -291, 781, 229,
+ -128, -298, 245, 491,
+ -701, -648, 972, 789,
+ -501, -640, 178, 255,
+ -365, -390, -255, 317,
+ -958, -294, -191, 228,
+ -775, -447, 157, -237,
+ -657, -720, -407, 92,
+ -117, -611, 334, -230,
+ -679, -1084, -144, -317,
+ -901, -861, -738, -360,
+ -85, -727, -90, -787,
+ 100, -22, -391, -263,
+ -56, -73, -337, -754,
+ 5, -189, -706, -624,
+ 89, -344, -135, -1113,
+ -353, -237, -684, -1135,
+ -275, -1102, -269, -1203,
+ 152, 145, -722, -1232,
+ 49, 80, -1248, -776,
+ -248, 391, -732, -547,
+ 469, 218, -255, -864,
+ 69, 366, -166, -485,
+ -688, 191, -1212, -1196,
+ -170, -169, -1308, -1631,
+ 321, 470, -1419, -1243,
+ -64, 272, -1361, -248,
+ 492, 565, -721, -609,
+ 195, 485, -573, -133,
+ 427, 202, -171, -118,
+ 199, 575, 2, -31,
+ 694, 755, -1366, -39,
+ 552, 557, -489, 271,
+ 680, 537, 13, -453,
+ 855, 954, -133, -52,
+ -81, 738, -1169, 637,
+ 1055, 1059, -95, 676,
+ 1259, 1081, 489, 305,
+ -449, 954, -534, 996,
+ -969, 866, -1058, 1059,
+ -1294, 618, -1416, 617,
+ -458, 1366, -159, 1821,
+ -774, -528, -14, 1110,
+ -1202, -901, -772, 433,
+ -1256, -1255, -1011, -302,
+ -602, -585, -759, -1618,
+ -760, -1549, -840, -1921,
+ -816, -539, -1769, -2235,
+ -227, -36, -2034, -1831,
+ -2107, -1126, -2471, -1816,
+ -1470, 252, -2701, -415,
+ -571, -467, 1509, 1554,
+ 2180, 1975, 2326, 2020
+ };
+
+ const Word16 dico4_lsf_5[DICO4_5_SIZE * 4] =
+ {
+ -1857, -1681, -1857, -1755,
+ -2056, -1150, -2134, -1654,
+ -1619, -1099, -1704, -1131,
+ -1345, -1608, -1359, -1638,
+ -1338, -1293, -1325, -1265,
+ -1664, -1649, -1487, -851,
+ -1346, -1832, -1413, -2188,
+ -1282, -681, -1785, -1649,
+ -966, -1082, -1183, -1676,
+ -1054, -1073, -1142, -1158,
+ -1207, -744, -1274, -997,
+ -934, -1383, -927, -1416,
+ -1010, -1305, -783, -955,
+ -1049, -900, -993, -817,
+ -737, -823, -972, -1189,
+ -738, -1094, -738, -1154,
+ -784, -801, -810, -786,
+ -892, -520, -1000, -818,
+ -644, -965, -577, -882,
+ -541, -694, -671, -917,
+ -595, -642, -646, -615,
+ -956, -621, -925, -515,
+ -727, -483, -815, -485,
+ -840, -578, -440, -713,
+ -578, -325, -657, -670,
+ -386, -570, -441, -666,
+ -514, -787, -392, -529,
+ -522, -453, -487, -423,
+ -616, -585, -617, -157,
+ -662, -268, -680, -348,
+ -322, -323, -632, -444,
+ -304, -430, -332, -458,
+ -277, -468, -659, -793,
+ -319, -636, -227, -554,
+ -373, -347, -334, -210,
+ -456, -192, -530, -242,
+ -216, -198, -366, -370,
+ -338, -161, -409, -748,
+ -107, -380, -294, -643,
+ -223, -665, -234, -741,
+ -141, -496, -130, -510,
+ -139, -327, -172, -305,
+ -306, -580, -164, -263,
+ -262, -172, -67, -402,
+ 31, -366, -10, -436,
+ -86, -527, 71, -377,
+ -22, -609, -12, -678,
+ -67, -319, 63, -191,
+ 35, -181, -39, -242,
+ 126, -167, -140, -544,
+ 155, -297, 174, -297,
+ 38, -8, 117, -380,
+ 197, -452, 240, -522,
+ 223, -103, 110, -187,
+ 87, -155, 169, -47,
+ 157, 26, -83, -100,
+ 128, 80, 209, -62,
+ 6, 7, 22, 5,
+ 318, -20, 248, -45,
+ -200, -63, 156, -69,
+ 250, -183, 369, -126,
+ -113, -76, -142, -122,
+ -64, -254, -31, 35,
+ -177, -71, -7, 171,
+ 93, 27, 108, 212,
+ -330, -209, -123, -70,
+ -279, 95, -96, 20,
+ -188, -61, -314, 87,
+ -300, -78, -354, -134,
+ 11, 122, -140, 122,
+ -275, 152, -293, 140,
+ -82, 138, -321, -111,
+ -480, -156, -359, 76,
+ -254, -40, -635, -96,
+ -522, 79, -507, 8,
+ -268, 303, -539, 68,
+ -446, 61, -522, 306,
+ 111, 189, -435, 122,
+ -379, 166, -571, -398,
+ -632, -74, -747, -95,
+ -455, 194, -952, 83,
+ -798, 192, -755, 192,
+ -781, -162, -619, 234,
+ -663, -297, -488, -109,
+ -964, -132, -838, -68,
+ -843, 58, -1112, -86,
+ -805, -299, -944, -253,
+ -778, -50, -965, -549,
+ -352, -98, -992, -343,
+ -1117, -315, -1117, -307,
+ -1155, -374, -637, -230,
+ -1166, -43, -1299, -100,
+ -925, -393, -1274, -600,
+ -689, -130, -1479, -312,
+ -1321, -254, -1464, -442,
+ -1292, -613, -1261, -503,
+ -1501, -368, -1322, 26,
+ -1432, -66, -1743, -161,
+ -1644, -467, -1760, -548,
+ -1393, -568, -1556, -871,
+ -1495, -1034, -1387, -571,
+ -1917, -528, -1783, -123,
+ -1897, -231, -2054, -323,
+ -2052, -906, -1976, -567,
+ -1917, -620, -2047, -989,
+ -1077, -370, -2031, -704,
+ -2355, -749, -2740, -1089,
+ -1909, 159, -2012, 248,
+ -626, -123, -2339, -962,
+ -669, -408, -1379, -1174,
+ -452, -364, -1044, -735,
+ -132, 183, -1620, -752,
+ -547, -307, -777, -1261,
+ -98, 41, -880, -1091,
+ -257, 97, -1602, -1833,
+ 31, -26, -644, -561,
+ -180, -546, -385, -1095,
+ -410, -802, -414, -827,
+ -457, -970, -490, -1109,
+ -215, -916, -144, -937,
+ -493, -1269, -517, -1507,
+ 181, 101, -332, -889,
+ -836, -937, -559, -429,
+ -629, -547, -183, -337,
+ -545, -82, -250, -286,
+ 5, -132, -348, -252,
+ -293, -472, -158, 100,
+ -29, 197, -236, -424,
+ -861, -213, -140, -7,
+ -427, -443, 187, -97,
+ -684, -736, -293, 258,
+ -368, -152, -150, 392,
+ -609, 175, -142, 299,
+ -138, 152, -119, 329,
+ -486, -52, 293, 198,
+ -183, 117, 175, 331,
+ -58, -274, 231, 300,
+ -288, 330, -305, 372,
+ -111, 409, -9, 423,
+ 83, 256, 67, 367,
+ -19, 248, 91, 113,
+ -35, 406, -191, 154,
+ 238, 296, 5, 197,
+ 141, 221, 313, 198,
+ 211, 421, 244, 334,
+ 88, 426, -243, 454,
+ 202, 552, -5, 403,
+ 291, 185, 219, 301,
+ 251, 138, 128, 69,
+ 197, 288, -140, -61,
+ 188, 361, 197, 598,
+ 442, 273, 290, 143,
+ 472, 482, 157, 370,
+ 415, 321, 372, 385,
+ 402, 552, 155, 24,
+ 550, 263, -11, 21,
+ 360, 227, 147, -254,
+ 424, 97, 366, -13,
+ 375, 141, 449, 232,
+ 396, 507, 474, 272,
+ 701, 324, 362, -47,
+ 587, 148, 543, 69,
+ 400, -51, 561, 59,
+ 220, -10, 352, 147,
+ 206, 211, 653, 185,
+ 563, 297, 565, 284,
+ 594, 121, 766, 192,
+ 398, 118, 642, 434,
+ 233, 264, 481, 467,
+ 129, -165, 699, 239,
+ 90, 26, 342, 474,
+ -55, 27, 388, 94,
+ -172, 0, 725, 379,
+ -60, 337, 370, 465,
+ 95, 319, 806, 595,
+ 78, 260, 497, 851,
+ 210, 560, 458, 574,
+ -464, 202, 497, 625,
+ -202, 152, 48, 712,
+ -20, 566, 100, 715,
+ 455, 468, 411, 605,
+ 319, 646, 195, 615,
+ 401, 538, 680, 739,
+ 201, 667, 434, 954,
+ 454, 425, 646, 491,
+ 606, 681, 416, 508,
+ 497, 822, 426, 815,
+ 660, 647, 628, 716,
+ 697, 466, 618, 457,
+ 685, 460, 365, 309,
+ 721, 567, 836, 601,
+ 609, 300, 825, 459,
+ 943, 687, 681, 533,
+ 915, 598, 591, 243,
+ 876, 451, 874, 420,
+ 786, 317, 732, 220,
+ 922, 317, 1108, 367,
+ 531, 466, 1028, 649,
+ 1053, 615, 1034, 553,
+ 829, 602, 1021, 799,
+ 927, 803, 878, 763,
+ 799, 496, 1373, 773,
+ 585, 770, 803, 930,
+ 1099, 793, 1222, 862,
+ 1209, 895, 1025, 727,
+ 772, 845, 1172, 1115,
+ 867, 1021, 830, 1013,
+ 841, 910, 506, 703,
+ 1239, 1077, 620, 819,
+ 1196, 1083, 1155, 1081,
+ 1142, 907, 1547, 1121,
+ 1309, 648, 1343, 612,
+ 1484, 988, 1479, 937,
+ 985, 1328, 955, 1341,
+ 429, 910, 841, 1338,
+ 564, 1179, 412, 1156,
+ 1427, 1320, 1434, 1330,
+ 640, 760, 1726, 1410,
+ 190, 555, 1073, 1005,
+ 426, 257, 839, 980,
+ 235, 231, 1520, 1167,
+ 109, 293, 1014, 1569,
+ 305, 142, 1148, 539,
+ -291, -108, 1213, 972,
+ 22, -216, 667, 828,
+ -482, 438, 453, 1431,
+ -581, -422, 789, 387,
+ -358, -454, 174, 780,
+ -36, -372, 390, -134,
+ -629, 160, -306, 751,
+ -1258, -331, 177, 522,
+ -248, 574, -251, 639,
+ -531, 407, -596, 394,
+ -419, 789, -617, 801,
+ -986, 399, -857, 727,
+ -7, 518, -703, 310,
+ -1143, -24, -1002, 287,
+ -960, 363, -1299, 312,
+ -1534, 245, -1557, 305,
+ 28, 153, -859, -175,
+ -33, 332, -1398, -154,
+ 212, 410, -593, -197,
+ -1092, -704, -904, -65,
+ 282, 367, -918, -686,
+ 345, 93, -258, -357,
+ 696, 644, -693, -28,
+ 448, 493, -273, 193,
+ 527, 546, -243, -513,
+ 384, -136, 273, -353,
+ 512, -142, 537, -198,
+ 941, 750, 83, 248,
+ 578, 861, -56, 592,
+ 842, 44, 892, 24,
+ 33, 890, -16, 982,
+ 831, 1398, 1535, 1898,
+ 1716, 1376, 1948, 1465
+ };
+
+ const Word16 dico5_lsf_5[DICO5_5_SIZE * 4] =
+ {
+ -1002, -929, -1096, -1203,
+ -641, -931, -604, -961,
+ -779, -673, -835, -788,
+ -416, -664, -458, -766,
+ -652, -521, -662, -495,
+ -1023, -509, -1023, -428,
+ -444, -552, -368, -449,
+ -479, -211, -1054, -903,
+ -316, -249, -569, -591,
+ -569, -275, -541, -191,
+ -716, -188, -842, -264,
+ -333, -248, -318, -228,
+ -275, 1, -567, -228,
+ -115, -221, -238, -374,
+ -197, -507, -222, -579,
+ -258, -432, -61, -244,
+ -345, 2, -338, 39,
+ -215, -169, -58, 0,
+ -56, -6, -203, -131,
+ 1, -186, -5, -211,
+ 6, -380, 11, -418,
+ -116, 131, -134, 113,
+ 89, -4, 71, -2,
+ -19, -192, 262, 24,
+ 189, 151, -133, -109,
+ 186, -153, 166, -219,
+ 37, 139, 193, 171,
+ 337, 124, 158, -61,
+ 141, 226, -13, 190,
+ 231, 34, 354, 109,
+ 316, 201, 244, 164,
+ 330, -85, 390, -84,
+ 254, 327, 257, 335,
+ 491, 147, 476, 105,
+ 54, 77, 437, 370,
+ 421, 314, 449, 342,
+ 329, 126, 673, 292,
+ 571, 388, 243, 193,
+ 653, 320, 621, 280,
+ 194, 380, 517, 581,
+ 45, 323, 111, 422,
+ 489, 395, 734, 534,
+ 622, 546, 486, 502,
+ 318, 572, 189, 550,
+ 385, 422, -157, 153,
+ -125, 382, -197, 386,
+ -263, 334, 228, 697,
+ -188, 1, 51, 297,
+ -507, 213, -376, 397,
+ -24, 255, -547, 89,
+ -502, -94, 387, 179,
+ -620, 68, -684, 112,
+ -642, -350, -260, 172,
+ -438, -324, 264, 648,
+ -964, -4, -1121, 7,
+ -134, 134, -1133, -306,
+ 143, 96, -420, -497,
+ -1221, -350, -1527, -685,
+ -161, 72, 873, 691,
+ 732, 283, 921, 353,
+ 334, 475, 1095, 821,
+ 864, 524, 843, 497,
+ 714, 711, 788, 750,
+ 1076, 714, 1204, 753
+ };
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] q_plsf_5.tab, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/qua_gain_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/qua_gain_tbl.cpp
new file mode 100644
index 0000000..2d913b8
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/qua_gain_tbl.cpp
@@ -0,0 +1,391 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/qua_gain_tbl.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created this file from the reference, qua_gain.tab
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "qua_gain.h"
+#include "qua_gain_tbl.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+
+ /* The tables contains the following data:
+ *
+ * g_pitch (Q14),
+ * g_fac (Q12), (g_code = g_code0*g_fac),
+ * qua_ener_MR122 (Q10), (log2(g_fac))
+ * qua_ener (Q10) (20*log10(g_fac))
+ *
+ * The log2() and log10() values are calculated on the fixed point value
+ * (g_fac Q12) and not on the original floating point value of g_fac
+ * to make the quantizer/MA predictdor use corresponding values.
+ */
+
+ /* table used in 'high' rates: MR67 MR74 */
+
+ const Word16 table_gain_highrates[VQ_SIZE_HIGHRATES*4] =
+ {
+
+ /*
+ * Note: column 4 (qua_ener) contains the original values from IS641
+ * to ensure bit-exactness; however, they are not exactly the
+ * rounded value of (20*log10(g_fac))
+ *
+ */
+
+ /*g_pit, g_fac, qua_ener_MR122, qua_ener */
+ 577, 662, -2692, -16214,
+ 806, 1836, -1185, -7135,
+ 3109, 1052, -2008, -12086,
+ 4181, 1387, -1600, -9629,
+ 2373, 1425, -1560, -9394,
+ 3248, 1985, -1070, -6442,
+ 1827, 2320, -840, -5056,
+ 941, 3314, -313, -1885,
+ 2351, 2977, -471, -2838,
+ 3616, 2420, -777, -4681,
+ 3451, 3096, -414, -2490,
+ 2955, 4301, 72, 434,
+ 1848, 4500, 139, 836,
+ 3884, 5416, 413, 2484,
+ 1187, 7210, 835, 5030,
+ 3083, 9000, 1163, 7002,
+ 7384, 883, -2267, -13647,
+ 5962, 1506, -1478, -8900,
+ 5155, 2134, -963, -5800,
+ 7944, 2009, -1052, -6335,
+ 6507, 2250, -885, -5327,
+ 7670, 2752, -588, -3537,
+ 5952, 3016, -452, -2724,
+ 4898, 3764, -125, -751,
+ 6989, 3588, -196, -1177,
+ 8174, 3978, -43, -260,
+ 6064, 4404, 107, 645,
+ 7709, 5087, 320, 1928,
+ 5523, 6021, 569, 3426,
+ 7769, 7126, 818, 4926,
+ 6060, 7938, 977, 5885,
+ 5594, 11487, 1523, 9172,
+ 10581, 1356, -1633, -9831,
+ 9049, 1597, -1391, -8380,
+ 9794, 2035, -1033, -6220,
+ 8946, 2415, -780, -4700,
+ 10296, 2584, -681, -4099,
+ 9407, 2734, -597, -3595,
+ 8700, 3218, -356, -2144,
+ 9757, 3395, -277, -1669,
+ 10177, 3892, -75, -454,
+ 9170, 4528, 148, 891,
+ 10152, 5004, 296, 1781,
+ 9114, 5735, 497, 2993,
+ 10500, 6266, 628, 3782,
+ 10110, 7631, 919, 5534,
+ 8844, 8727, 1117, 6728,
+ 8956, 12496, 1648, 9921,
+ 12924, 976, -2119, -12753,
+ 11435, 1755, -1252, -7539,
+ 12138, 2328, -835, -5024,
+ 11388, 2368, -810, -4872,
+ 10700, 3064, -429, -2580,
+ 12332, 2861, -530, -3192,
+ 11722, 3327, -307, -1848,
+ 11270, 3700, -150, -904,
+ 10861, 4413, 110, 663,
+ 12082, 4533, 150, 902,
+ 11283, 5205, 354, 2132,
+ 11960, 6305, 637, 3837,
+ 11167, 7534, 900, 5420,
+ 12128, 8329, 1049, 6312,
+ 10969, 10777, 1429, 8604,
+ 10300, 17376, 2135, 12853,
+ 13899, 1681, -1316, -7921,
+ 12580, 2045, -1026, -6179,
+ 13265, 2439, -766, -4610,
+ 14033, 2989, -465, -2802,
+ 13452, 3098, -413, -2482,
+ 12396, 3658, -167, -1006,
+ 13510, 3780, -119, -713,
+ 12880, 4272, 62, 374,
+ 13533, 4861, 253, 1523,
+ 12667, 5457, 424, 2552,
+ 13854, 6106, 590, 3551,
+ 13031, 6483, 678, 4084,
+ 13557, 7721, 937, 5639,
+ 12957, 9311, 1213, 7304,
+ 13714, 11551, 1532, 9221,
+ 12591, 15206, 1938, 11667,
+ 15113, 1540, -1445, -8700,
+ 15072, 2333, -832, -5007,
+ 14527, 2511, -723, -4352,
+ 14692, 3199, -365, -2197,
+ 15382, 3560, -207, -1247,
+ 14133, 3960, -50, -300,
+ 15102, 4236, 50, 298,
+ 14332, 4824, 242, 1454,
+ 14846, 5451, 422, 2542,
+ 15306, 6083, 584, 3518,
+ 14329, 6888, 768, 4623,
+ 15060, 7689, 930, 5602,
+ 14406, 9426, 1231, 7413,
+ 15387, 9741, 1280, 7706,
+ 14824, 14271, 1844, 11102,
+ 13600, 24939, 2669, 16067,
+ 16396, 1969, -1082, -6517,
+ 16817, 2832, -545, -3283,
+ 15713, 2843, -539, -3248,
+ 16104, 3336, -303, -1825,
+ 16384, 3963, -49, -294,
+ 16940, 4579, 165, 992,
+ 15711, 4599, 171, 1030,
+ 16222, 5448, 421, 2537,
+ 16832, 6382, 655, 3945,
+ 15745, 7141, 821, 4944,
+ 16326, 7469, 888, 5343,
+ 16611, 8624, 1100, 6622,
+ 17028, 10418, 1379, 8303,
+ 15905, 11817, 1565, 9423,
+ 16878, 14690, 1887, 11360,
+ 16515, 20870, 2406, 14483,
+ 18142, 2083, -999, -6013,
+ 19401, 3178, -375, -2257,
+ 17508, 3426, -264, -1589,
+ 20054, 4027, -25, -151,
+ 18069, 4249, 54, 326,
+ 18952, 5066, 314, 1890,
+ 17711, 5402, 409, 2461,
+ 19835, 6192, 610, 3676,
+ 17950, 7014, 795, 4784,
+ 21318, 7877, 966, 5816,
+ 17910, 9289, 1210, 7283,
+ 19144, 9290, 1210, 7284,
+ 20517, 11381, 1510, 9089,
+ 18075, 14485, 1866, 11234,
+ 19999, 17882, 2177, 13108,
+ 18842, 32764, 3072, 18494
+ };
+
+
+ /* table used in 'low' rates: MR475, MR515, MR59 */
+
+ const Word16 table_gain_lowrates[VQ_SIZE_LOWRATES*4] =
+ {
+ /*g_pit, g_fac, qua_ener_MR122, qua_ener */
+ 10813, 28753, 2879, 17333,
+ 20480, 2785, -570, -3431,
+ 18841, 6594, 703, 4235,
+ 6225, 7413, 876, 5276,
+ 17203, 10444, 1383, 8325,
+ 21626, 1269, -1731, -10422,
+ 21135, 4423, 113, 683,
+ 11304, 1556, -1430, -8609,
+ 19005, 12820, 1686, 10148,
+ 17367, 2498, -731, -4398,
+ 17858, 4833, 244, 1472,
+ 9994, 2498, -731, -4398,
+ 17530, 7864, 964, 5802,
+ 14254, 1884, -1147, -6907,
+ 15892, 3153, -387, -2327,
+ 6717, 1802, -1213, -7303,
+ 18186, 20193, 2357, 14189,
+ 18022, 3031, -445, -2678,
+ 16711, 5857, 528, 3181,
+ 8847, 4014, -30, -180,
+ 15892, 8970, 1158, 6972,
+ 18022, 1392, -1594, -9599,
+ 16711, 4096, 0, 0,
+ 8192, 655, -2708, -16305,
+ 15237, 13926, 1808, 10884,
+ 14254, 3112, -406, -2444,
+ 14090, 4669, 193, 1165,
+ 5406, 2703, -614, -3697,
+ 13434, 6553, 694, 4180,
+ 12451, 901, -2237, -13468,
+ 12451, 2662, -637, -3833,
+ 3768, 655, -2708, -16305,
+ 14745, 23511, 2582, 15543,
+ 19169, 2457, -755, -4546,
+ 20152, 5079, 318, 1913,
+ 6881, 4096, 0, 0,
+ 20480, 8560, 1089, 6556,
+ 19660, 737, -2534, -15255,
+ 19005, 4259, 58, 347,
+ 7864, 2088, -995, -5993,
+ 11468, 12288, 1623, 9771,
+ 15892, 1474, -1510, -9090,
+ 15728, 4628, 180, 1086,
+ 9175, 1433, -1552, -9341,
+ 16056, 7004, 793, 4772,
+ 14827, 737, -2534, -15255,
+ 15073, 2252, -884, -5321,
+ 5079, 1228, -1780, -10714,
+ 13271, 17326, 2131, 12827,
+ 16547, 2334, -831, -5002,
+ 15073, 5816, 518, 3118,
+ 3932, 3686, -156, -938,
+ 14254, 8601, 1096, 6598,
+ 16875, 778, -2454, -14774,
+ 15073, 3809, -107, -646,
+ 6062, 614, -2804, -16879,
+ 9338, 9256, 1204, 7251,
+ 13271, 1761, -1247, -7508,
+ 13271, 3522, -223, -1343,
+ 2457, 1966, -1084, -6529,
+ 11468, 5529, 443, 2668,
+ 10485, 737, -2534, -15255,
+ 11632, 3194, -367, -2212,
+ 1474, 778, -2454, -14774
+ };
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] qua_gain.tab, UMTS GSM AMR speech codec,
+ R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/reorder.cpp b/media/libstagefright/codecs/amrnb/common/src/reorder.cpp
new file mode 100644
index 0000000..b1e4711
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/reorder.cpp
@@ -0,0 +1,199 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Filename: /audio/gsm_amr/c/src/reorder.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ 1. Eliminated unused include file add.h.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated math operations that unnecessary checked for
+ saturation
+ 4. Replaced loop counter with decrement loops
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "reorder.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Reorder_lsf
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsf = vector of LSFs (range: 0<=val<=0.5)(Word16)
+ min_dist = minimum required distance (Word16)
+ n = LPC order (Word16)
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the add operation called by Reorder_lsf() results in
+ overflow
+ lsf -> reordered vector of LSFs (Word16)
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function makes sure that the LSFs are properly ordered keeps a certain
+ minimum distance between adjacent LSFs.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] reorder.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Reorder_lsf (
+ Word16 *lsf, // (i/o) : vector of LSFs (range: 0<=val<=0.5)
+ Word16 min_dist, // (i) : minimum required distance
+ Word16 n // (i) : LPC order
+)
+{
+ Word16 i;
+ Word16 lsf_min;
+
+// The reference ETSI code uses a global flag for Overflow. In the actual
+// implementation a pointer to Overflow flag is passed into the function
+// for use by the math functions add() and sub()
+
+ lsf_min = min_dist;
+ for (i = 0; i < n; i++)
+ {
+ if (sub (lsf[i], lsf_min) < 0)
+ {
+ lsf[i] = lsf_min;
+ }
+ lsf_min = add (lsf[i], min_dist);
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void Reorder_lsf(
+ Word16 *lsf, /* (i/o) : vector of LSFs (range: 0<=val<=0.5) */
+ Word16 min_dist, /* (i) : minimum required distance */
+ Word16 n, /* (i) : LPC order */
+ Flag *pOverflow /* (i/o) : Overflow flag */
+)
+{
+ Word16 i;
+ Word16 lsf_min;
+ Word16 *p_lsf = &lsf[0];
+ OSCL_UNUSED_ARG(pOverflow);
+
+ lsf_min = min_dist;
+ for (i = 0; i < n; i++)
+ {
+ if (*(p_lsf) < lsf_min)
+ {
+ *(p_lsf++) = lsf_min;
+ lsf_min += min_dist;
+ }
+ else
+ {
+ lsf_min = *(p_lsf++) + min_dist;
+ }
+ }
+}
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/residu.cpp b/media/libstagefright/codecs/amrnb/common/src/residu.cpp
new file mode 100644
index 0000000..b25d3be
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/residu.cpp
@@ -0,0 +1,255 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./audio/gsm-amr/c/src/residu.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template. First attempt at
+ optimizing code.
+
+ Description: Deleted stores listed in the Local Stores Needed/Modified
+ section.
+
+ Description: Updated file per comments gathered from Phase 2/3 review.
+
+ Description: Updating to reflect variable name changes made in residu.asm
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Modified FOR loops to count down.
+ 2. Fixed typecasting issue with TI C compiler.
+
+ Description: Made the following changes
+ 1. Unrolled the convolutional loop.
+ 2. Performed 4 convolution per pass to avoid recalling the same
+ filter coefficient as many times.
+ 2. Eliminated math operations that check for saturation.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "residu.h"
+#include "typedef.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Residu
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ coef_ptr = pointer to buffer containing the prediction coefficients
+ input_ptr = pointer to buffer containing the speech signal
+ input_len = filter order
+ residual_ptr = pointer to buffer of residual signal
+
+ Outputs:
+ residual_ptr buffer contains the newly calculated the residual signal
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes the LP residual by filtering the input speech through
+ the LP inverse filter A(z).
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ residu.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Note: Input argument names were changed to be more descriptive. Shown below
+ are the original names. Shown below are the name changes:
+ a[] <--> coef_ptr[]
+ x[] <--> input_ptr[]
+ y[] <--> residual_ptr[]
+ lg <--> input_len
+
+
+void Residu (
+ Word16 a[], // (i) : prediction coefficients
+ Word16 x[], // (i) : speech signal
+ Word16 y[], // (o) : residual signal
+ Word16 lg // (i) : size of filtering
+)
+{
+ Word16 i, j;
+ Word32 s;
+
+ for (i = 0; i < lg; i++)
+ {
+ s = L_mult (x[i], a[0]);
+ for (j = 1; j <= M; j++)
+ {
+ s = L_mac (s, a[j], x[i - j]);
+ }
+ s = L_shl (s, 3);
+ y[i] = pv_round (s);
+ }
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Residu(
+ Word16 coef_ptr[], /* (i) : prediction coefficients*/
+ Word16 input_ptr[], /* (i) : speech signal */
+ Word16 residual_ptr[], /* (o) : residual signal */
+ Word16 input_len /* (i) : size of filtering */
+)
+{
+
+
+ register Word16 i, j;
+ Word32 s1;
+ Word32 s2;
+ Word32 s3;
+ Word32 s4;
+ Word16 *p_input1;
+ Word16 *p_input2;
+ Word16 *p_input3;
+ Word16 *p_input4;
+ Word16 *p_coef;
+ Word16 *p_residual_ptr = &residual_ptr[input_len-1];
+ Word16 *p_input_ptr = &input_ptr[input_len-1-M];
+
+ for (i = input_len >> 2; i != 0; i--)
+ {
+ s1 = 0x0000800L;
+ s2 = 0x0000800L;
+ s3 = 0x0000800L;
+ s4 = 0x0000800L;
+ p_coef = &coef_ptr[M];
+ p_input1 = p_input_ptr--;
+ p_input2 = p_input_ptr--;
+ p_input3 = p_input_ptr--;
+ p_input4 = p_input_ptr--;
+
+ for (j = M >> 1; j != 0; j--)
+ {
+ s1 += ((Word32) * (p_coef) * *(p_input1++));
+ s2 += ((Word32) * (p_coef) * *(p_input2++));
+ s3 += ((Word32) * (p_coef) * *(p_input3++));
+ s4 += ((Word32) * (p_coef--) * *(p_input4++));
+ s1 += ((Word32) * (p_coef) * *(p_input1++));
+ s2 += ((Word32) * (p_coef) * *(p_input2++));
+ s3 += ((Word32) * (p_coef) * *(p_input3++));
+ s4 += ((Word32) * (p_coef--) * *(p_input4++));
+ }
+
+ s1 += (((Word32) * (p_coef)) * *(p_input1));
+ s2 += (((Word32) * (p_coef)) * *(p_input2));
+ s3 += (((Word32) * (p_coef)) * *(p_input3));
+ s4 += (((Word32) * (p_coef)) * *(p_input4));
+
+ *(p_residual_ptr--) = (Word16)(s1 >> 12);
+ *(p_residual_ptr--) = (Word16)(s2 >> 12);
+ *(p_residual_ptr--) = (Word16)(s3 >> 12);
+ *(p_residual_ptr--) = (Word16)(s4 >> 12);
+
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/round.cpp b/media/libstagefright/codecs/amrnb/common/src/round.cpp
new file mode 100644
index 0000000..71d1702
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/round.cpp
@@ -0,0 +1,195 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/round.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the round function. Sync'ed up
+ with the current template and fixed tabs.
+
+ Description: Made changes based on review meeting:
+ 1. Removed long in Inputs Definitions.
+ 2. Changed L_var1 to var_out and description in
+ Output Definitions.
+
+ Description: Added a parameter to the function interface, pOverflow which is
+ a pointer to the overflow flag. This flag is required by the
+ L_add() function invoked by round().
+ Removed code that updates the MOPS counter.
+ Created a new return variable result.
+
+ Description: Removed embedded tabs. Included comment in the Pseudo code
+ Section about using pointer to overflow flag in the actual
+ implementation instead of using a global flag.
+
+ Description: Changed function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Rounding function with saturation.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: pv_round
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 32 bit signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ None
+
+ Returns:
+ result = MS 16 bits of rounded input L_var1.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function rounds 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:
+ pv_round(L_var1) = extract_h(L_add(L_var1,32768))
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] round() function in basic_op2.c, UMTS GSM AMR speech codec, R99 -
+ Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 pv_round (Word32 L_var1)
+{
+ Word16 var_out;
+ Word32 L_rounded;
+
+* The reference ETSI code uses a global flag for Overflow in the L_add() function.
+* In the actual implementation a pointer to Overflow flag is passed in as a
+* parameter to the function.
+
+ L_rounded = L_add (L_var1, (Word32) 0x00008000L);
+#if (WMOPS)
+ multiCounter[currCounter].L_add--;
+#endif
+ var_out = extract_h (L_rounded);
+#if (WMOPS)
+ multiCounter[currCounter].extract_h--;
+ multiCounter[currCounter].round++;
+#endif
+ return (var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word16 pv_round(register Word32 L_var1, Flag *pOverflow)
+{
+ Word16 result;
+
+ L_var1 = L_add(L_var1, (Word32) 0x00008000L, pOverflow);
+ result = (Word16)(L_var1 >> 16);
+
+ return (result);
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/set_zero.cpp b/media/libstagefright/codecs/amrnb/common/src/set_zero.cpp
new file mode 100644
index 0000000..be23b25
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/set_zero.cpp
@@ -0,0 +1,74 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : set_zero.h
+*
+********************************************************************************
+*/
+/*
+********************************************************************************
+* MODULE INCLUDE FILE AND VERSION ID
+********************************************************************************
+*/
+#include "set_zero.h"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+#include "basic_op.h"
+
+/*
+********************************************************************************
+* PUBLIC PROGRAM CODE
+********************************************************************************
+*/
+void Set_zero(
+ Word16 x[], /* (o) : vector to clear */
+ Word16 L /* (i) : length of vector */
+)
+{
+ Word16 i;
+
+ for (i = 0; i < L; i++)
+ {
+ x[i] = 0;
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/shr.cpp b/media/libstagefright/codecs/amrnb/common/src/shr.cpp
new file mode 100644
index 0000000..775dc69
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/shr.cpp
@@ -0,0 +1,258 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/shr.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the shr function. Sync'ed up with
+ the current template and fixed tabs.
+
+ Description: 1. Modified code by seperating var2=0 condition.
+ 2. Changed Input range definitions.
+
+ Description: Made changes based on review meeting.
+ 1. Changed Overflow definition.
+ 2. Removed pseudo-code.
+ 3. Deleted (var2>15&&var1!=0) condition.
+ 4. Moved var2>0 condition in front of var2<0 condition.
+
+ Description: Changed the function prototype to pass in a pointer to the
+ overflow flag instead of using global data.
+
+ Description: Made changes per formal review. Updated template.
+ Removed code that updates MOPS counter.
+ Changed parameter name from "overflow" and "pOverflow".
+ Optimized code by eliminating unnecessary typecasting.
+ Filled in the PSEUDO CODE section
+
+ Description: Further optimized typecasting for overflow case
+
+ Who: Date:
+ Description:
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+ Shift right function with overflow control
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: shr
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the shift operation resulted in overflow
+
+ Returns:
+ product = Shifted result limited to 16 bits (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function arithmetically shifts 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.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+ None
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] shr() function in basic_op2.c, UMTS GSM AMR speech codec, R99 -
+ Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 shr_std (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ if (var2 < 0)
+ {
+ if (var2 < -16)
+ var2 = -16;
+ var_out = shl_std (var1, -var2);
+#if (WMOPS)
+ mult_stdiCounter[currCounter].shl_std--;
+#endif
+ }
+ else
+ {
+ if (var2 >= 15)
+ {
+ var_out = (var1 < 0) ? -1 : 0;
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var_out = ~((~var1) >> var2);
+ }
+ else
+ {
+ var_out = var1 >> var2;
+ }
+ }
+ }
+
+#if (WMOPS)
+ mult_stdiCounter[currCounter].shr_std++;
+#endif
+ return (var_out);
+}
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word16 shr(register Word16 var1, register Word16 var2, Flag *pOverflow)
+{
+ register Word16 result;
+ register Word32 temp_res;
+
+ if (var2 != 0)
+ {
+ if (var2 > 0)
+ {
+ if (var2 >= 15)
+ {
+ result = ((var1 < 0) ? -1 : 0);
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ result = (~((~var1) >> var2));
+ }
+ else
+ {
+ result = (var1 >> var2);
+ }
+ }
+ }
+ else
+ {
+ if (var2 < -16)
+ {
+ var2 = -16;
+ }
+
+ var2 = -var2; /* Shift right negative is equivalent */
+ /* to shifting left positive. */
+
+ temp_res = ((Word32) var1) << var2;
+ result = (Word16)(temp_res);
+
+ if (temp_res != (Word32) result)
+ {
+ *pOverflow = 1;
+ result = ((var1 > 0) ? MAX_16 : MIN_16);
+ }
+ }
+
+ }
+ else
+ {
+ result = var1;
+ }
+
+ return (result);
+}
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/shr_r.cpp b/media/libstagefright/codecs/amrnb/common/src/shr_r.cpp
new file mode 100644
index 0000000..6656f93
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/shr_r.cpp
@@ -0,0 +1,226 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./gsm-amr/c/src/shr_r.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the shr_r function. Sync'ed up
+ with the current template and fixed tabs.
+
+ Description: Passing around pOverflow as per EPOC changes.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ var_out = shifted input w/ rounding (Word16)
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function arithmetically shifts the 16 bit input var1 right var2 positions
+ with rounding. If var2 is negative, arithmetically shift var1 left by
+ -var2 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).
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] basicop2.c, ETS Version 2.0.0, February 8, 1999
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 shr_r (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ if (var2 > 15)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ var_out = shr (var1, var2);
+#if (WMOPS)
+ multiCounter[currCounter].shr--;
+#endif
+
+ if (var2 > 0)
+ {
+ if ((var1 & ((Word16) 1 << (var2 - 1))) != 0)
+ {
+ var_out++;
+ }
+ }
+ }
+#if (WMOPS)
+ multiCounter[currCounter].shr_r++;
+#endif
+ return (var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word16 shr_r(register Word16 var1, register Word16 var2, Flag *pOverflow)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ Word16 var_out;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ if (var2 > 15)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ var_out = shr(var1, var2, pOverflow);
+ if (var2 > 0)
+ {
+ if ((var1 & ((Word16) 1 << (var2 - 1))) != 0)
+ {
+ var_out++;
+ }
+ }
+ }
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return (var_out);
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/sqrt_l.cpp b/media/libstagefright/codecs/amrnb/common/src/sqrt_l.cpp
new file mode 100644
index 0000000..8f74aa6
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/sqrt_l.cpp
@@ -0,0 +1,266 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./audio/gsm-amr/c/src/sqrt_l.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description: Updated template. Changed function interface to pass in a
+ pointer to overflow flag into the function instead of using a
+ global flag. Changed name of an input pointer from "exp" to "pExp"
+ for clarity. Removed inclusion of unwanted header files.
+
+ Description: Removed inclusion of sqrt_l.tab file. Changed the array name
+ "table" to "sqrt_l_tbl". Fixed typos.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "sqrt_l.h"
+#include "typedef.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: sqrt_l_exp
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_x = input value (Word32)
+ pExp = pointer to right shift to be applied to result
+ pOverflow = pointer to overflow flag
+
+ Outputs:
+ pOverflow -> if the Inv_sqrt operation resulted in an overflow.
+
+ Returns:
+ L_y = squareroot of L_x (Word32)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes sqrt(L_x), where L_x is positive.
+ If L_var is negative or zero, the result is 0
+
+ The function sqrt(L_x) is approximated by a table and linear
+ interpolation. The square root is computed using the
+ following steps:
+ 1- Normalization of L_x.
+ 2- If exponent is even then shift right once.
+ 3- exponent = exponent/2
+ 4- i = bit25-b31 of L_x; 16<=i<=63 because of normalization.
+ 5- a = bit10-b24
+ 6- i -=16
+ 7- L_y = table[i]<<16 - (table[i] - table[i+1]) * a * 2
+ 8- return L_y and exponent so caller can do denormalization
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sqrt_l.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word32 sqrt_l_exp ( // o : output value
+ Word32 L_x, // i : input value
+ Word16 *exp // o : right shift to be applied to result
+)
+{
+
+// y = sqrt(x)
+// x = f * 2^-e, 0.5 <= f < 1 (normalization)
+// y = sqrt(f) * 2^(-e/2)
+//
+// a) e = 2k --> y = sqrt(f) * 2^-k (k = e div 2,
+// 0.707 <= sqrt(f) < 1)
+// b) e = 2k+1 --> y = sqrt(f/2) * 2^-k (k = e div 2,
+ 0.5 <= sqrt(f/2) < 0.707)
+
+
+ Word16 e, i, a, tmp;
+ Word32 L_y;
+
+ if (L_x <= (Word32) 0)
+ {
+ *exp = 0;
+ return (Word32) 0;
+ }
+
+* The reference ETSI code uses a global Overflow flag. In the actual
+* implementation a pointer to the overflow flag is passed into the function.
+* This pointer is in turn passed into the basic math functions such as add(),
+* L_shl(), L_shr(), sub() called by this module.
+
+ e = norm_l (L_x) & 0xFFFE; // get next lower EVEN norm. exp
+ L_x = L_shl (L_x, e); // L_x is normalized to [0.25..1)
+ *exp = e; // return 2*exponent (or Q1)
+
+ L_x = L_shr (L_x, 9);
+ i = extract_h (L_x); // Extract b25-b31, 16 <= i <= 63
+ because of normalization
+ L_x = L_shr (L_x, 1);
+ a = extract_l (L_x); // Extract b10-b24
+ a = a & (Word16) 0x7fff;
+
+ i = sub (i, 16); // 0 <= i <= 47
+
+ L_y = L_deposit_h (table[i]); // table[i] << 16
+ tmp = sub (table[i], table[i + 1]); // table[i] - table[i+1])
+ L_y = L_msu (L_y, tmp, a); // L_y -= tmp*a*2
+
+ return (L_y);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word32 sqrt_l_exp( /* o : output value, Q31 */
+ Word32 L_x, /* i : input value, Q31 */
+ Word16 *pExp, /* o : right shift to be applied to result, Q1 */
+ Flag *pOverflow /* i : pointer to overflow flag */
+)
+
+{
+ Word16 e;
+ Word16 i;
+ Word16 a;
+ Word16 tmp;
+ Word32 L_y;
+
+ /*
+ y = sqrt(x)
+ x = f * 2^-e, 0.5 <= f < 1 (normalization)
+ y = sqrt(f) * 2^(-e/2)
+ a) e = 2k --> y = sqrt(f) * 2^-k (k = e div 2,
+ 0.707 <= sqrt(f) < 1)
+ b) e = 2k+1 --> y = sqrt(f/2) * 2^-k (k = e div 2,
+ 0.5 <= sqrt(f/2) < 0.707)
+ */
+
+ if (L_x <= (Word32) 0)
+ {
+ *pExp = 0;
+ return (Word32) 0;
+ }
+
+ e = norm_l(L_x) & 0xFFFE; /* get next lower EVEN norm. exp */
+ L_x = L_shl(L_x, e, pOverflow); /* L_x is normalized to [0.25..1) */
+ *pExp = e; /* return 2*exponent (or Q1) */
+
+ L_x >>= 10;
+ i = (Word16)(L_x >> 15) & 63; /* Extract b25-b31, 16<= i <=63 */
+ /* because of normalization */
+
+ a = (Word16)(L_x); /* Extract b10-b24 */
+ a &= (Word16) 0x7fff;
+
+ if (i > 15)
+ {
+ i -= 16; /* 0 <= i <= 47 */
+ }
+
+ L_y = L_deposit_h(sqrt_l_tbl[i]); /* sqrt_l_tbl[i] << 16 */
+
+ /* sqrt_l_tbl[i] - sqrt_l_tbl[i+1]) */
+ tmp = sub(sqrt_l_tbl[i], sqrt_l_tbl[i + 1], pOverflow);
+
+ L_y = L_msu(L_y, tmp, a, pOverflow); /* L_y -= tmp*a*2 */
+
+ /* L_y = L_shr (L_y, *exp); */ /* denormalization done by caller */
+
+ return (L_y);
+}
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/sqrt_l_tbl.cpp b/media/libstagefright/codecs/amrnb/common/src/sqrt_l_tbl.cpp
new file mode 100644
index 0000000..5a84b63
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/sqrt_l_tbl.cpp
@@ -0,0 +1,171 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/sqrt_l_tbl.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed the table name to sqrt_l_tbl.
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the declaration for sqrt_l_table[] used by the sqrt_l_exp
+ function.
+
+ sqrt_l_tbl[i] = sqrt((i+16)*2^-6) * 2^15, i.e. sqrt(x) scaled Q15
+
+ ------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "sqrt_l.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+ const Word16 sqrt_l_tbl[50] =
+ {
+ 16384, 16888, 17378, 17854, 18318, 18770, 19212, 19644, 20066, 20480,
+ 20886, 21283, 21674, 22058, 22435, 22806, 23170, 23530, 23884, 24232,
+ 24576, 24915, 25249, 25580, 25905, 26227, 26545, 26859, 27170, 27477,
+ 27780, 28081, 28378, 28672, 28963, 29251, 29537, 29819, 30099, 30377,
+ 30652, 30924, 31194, 31462, 31727, 31991, 32252, 32511, 32767, 32767
+ };
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] inv_sqrt.tab file, UMTS GSM AMR speech codec, R99 - Version 3.2.0,
+ March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/sub.cpp b/media/libstagefright/codecs/amrnb/common/src/sub.cpp
new file mode 100644
index 0000000..d936128
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/sub.cpp
@@ -0,0 +1,218 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: /audio/gsm_amr/c/src/sub.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate file for the sub function. Sync'ed up with the
+ current template and fixed tabs.
+
+ Description: Changed all occurrences of L_diff to diff, deleted "short" in
+ the definition of var1 and var2, and fixed the range values.
+
+ Description: Changed function prototype passing in a pointer to overflow flag
+ instead of using global data.
+
+ Description: Changes made per formal review comments.
+ 1. Changed the parameter name fron "overflow" to "pOverflow"
+ 2. Updated template
+ 3. Updated reference section
+
+ Description: Removed conditional code that updates WMOPS counter
+
+ Description:
+ 1. Modified if-else structure to save cycles by processing
+ the most common case faster.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Subtraction function with overflow control
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: sub
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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 <= var2 <= 0x0000 7fff.
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the subtract operation resulted in overflow
+
+ Returns:
+ diff = 16-bit limited difference between var1 and var2 (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the subtraction (var1-var2) with overflow control and
+ saturation; the 16 bit result is set at +32767 when overflow occurs or at
+ -32768 when underflow occurs.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] sub() function in basicop2.c, UMTS GSM AMR speech codec, R99 -
+ Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+
+ PSEUDO-CODE
+
+ Word16 sub (Word16 var1, Word16 var2)
+ {
+ Word16 var_out;
+ Word32 diff;
+
+ diff = (Word32) var1 - var2;
+
+* The reference ETSI code uses a global flag for Overflow inside the function
+* saturate(). In the actual implementation a pointer to Overflow flag is passed
+* in as a parameter to the function
+
+ var_out = saturate (diff);
+
+ #if (WMOPS)
+ multiCounter[currCounter].sub++;
+ #endif
+
+ return (var_out);
+ }
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Word16 sub(Word16 var1, Word16 var2, Flag *pOverflow)
+{
+
+ Word32 diff;
+
+ diff = (Word32) var1 - var2;
+
+ /* Saturate result (if necessary). */
+ /* Replaced function call with in-line code */
+ /* to conserve MIPS, i.e., var_out = saturate (diff) */
+
+
+ if ((UWord32)(diff - 0xFFFF8000L) > 0x000FFFF)
+ {
+ if (diff > (Word32) 0x0007FFFL)
+ {
+ diff = MAX_16;
+ }
+ else
+ {
+ diff = MIN_16;
+ }
+
+ *pOverflow = 1;
+ }
+
+
+ return ((Word16) diff);
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/syn_filt.cpp b/media/libstagefright/codecs/amrnb/common/src/syn_filt.cpp
new file mode 100644
index 0000000..bcdc696
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/syn_filt.cpp
@@ -0,0 +1,399 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./audio/gsm-amr/c/src/syn_filt.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Making changes based on comments from the review meeting.
+
+ Description: Added typedef to Input/Output Definition section.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template.
+
+ Description: Fixed typecasting issue with the TI C compiler.
+
+ Description: Modified FOR loops to count down.
+
+ Description: Modified FOR loop to count up again so that the correct values
+ are stored in the tmp buffer. Updated copyright year.
+
+ Description:
+ - Modified for loop and introduced pointers to avoid adding
+ offsets
+ - Eliminated check for saturation given that the max values of input
+ data and coefficients will not saturate the multiply and
+ accumulation
+ - eliminated memcpy to update history buffer in every pass. This is
+ done now just updating the pointers.
+
+ Description:
+ 1. Eliminated unused include files.
+ 2. Unrolled loops to process twice as many samples as before,
+ this saves on memory accesses to the vector coeff. a[] and
+ elements in the history buffer of this recursive filter
+
+ Description:
+ 1. Added overflow check inside both loops. (this is needed just
+ to satisfy bit exactness on the decoder, a faster
+ implementation will add an extra shift, do the same,
+ but will not be bit exact, and it may have better audio
+ quality because will avoid clipping)
+ 2. Added include file for constant definitions
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Using fxp_arithmetic.h that includes inline assembly functions
+ for ARM and linux-arm.
+
+ Description: Replacing fxp_arithmetic.h with basic_op.h.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include <string.h>
+
+#include "syn_filt.h"
+#include "cnst.h"
+#include "basic_op.h"
+
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Syn_filt
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ a = buffer containing the prediction coefficients (Word16) max 2^12
+ x = input signal buffer (Word16) max 2^15
+ y = output signal buffer (Word16)
+ lg = size of filtering (Word16)
+ mem = memory buffer associated with this filtering (Word16)
+ update = flag to indicate memory update; 0=no update, 1=update memory
+ (Word16)
+
+ Outputs:
+ mem buffer is changed to be the last M data points of the output signal
+ if update was set to 1
+ y buffer contains the newly calculated filter output
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Perform synthesis filtering through 1/A(z)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ syn_filt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Syn_filt (
+ Word16 a[], // (i) : a[M+1] prediction coefficients (M=10)
+ 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.
+)
+{
+ Word16 i, j;
+ Word32 s;
+ Word16 tmp[80]; // This is usually done by memory allocation (lg+M)
+ Word16 *yy;
+
+ // Copy mem[] to yy[]
+
+ yy = tmp;
+
+ for (i = 0; i < M; i++)
+ {
+ *yy++ = mem[i];
+ }
+
+ // Do the filtering.
+
+ for (i = 0; i < lg; i++)
+ {
+ s = L_mult (x[i], a[0]);
+ for (j = 1; j <= M; j++)
+ {
+ s = L_msu (s, a[j], yy[-j]);
+ }
+ s = L_shl (s, 3);
+ *yy++ = pv_round (s);
+ }
+
+ for (i = 0; i < lg; i++)
+ {
+ y[i] = tmp[i + M];
+ }
+
+ // Update of memory if update==1
+
+ if (update != 0)
+ {
+ for (i = 0; i < M; i++)
+ {
+ mem[i] = y[lg - M + i];
+ }
+ }
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Syn_filt(
+ Word16 a[], /* (i) : a[M+1] prediction coefficients (M=10) */
+ Word16 x[], /* (i) : input signal */
+ Word16 y[], /* (o) : output signal */
+ Word16 lg, /* (i) : size of filtering (40) */
+ Word16 mem[], /* (i/o) : memory associated with this filtering. */
+ Word16 update /* (i) : 0=no update, 1=update of memory. */
+)
+{
+ Word16 i, j;
+ Word32 s1;
+ Word32 s2;
+ Word16 tmp[2*M]; /* This is usually done by memory allocation (lg+M) */
+ Word16 *yy;
+
+ Word16 *p_a;
+ Word16 *p_yy1;
+ Word16 *p_y;
+ Word16 *p_x;
+ Word16 temp;
+ /* Copy mem[] to yy[] */
+
+ yy = tmp;
+
+ memcpy(yy, mem, M*sizeof(Word16));
+
+ yy = yy + M;
+
+ /* Do the filtering. */
+
+ p_y = y;
+ p_x = x;
+ p_yy1 = &yy[-1];
+
+ for (i = M >> 1; i != 0; i--)
+ {
+ p_a = a;
+
+ s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L);
+ s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L);
+ s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
+
+ for (j = (M >> 1) - 2; j != 0; j--)
+ {
+ s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
+ s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
+ s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
+ s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
+ s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
+ s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
+ }
+
+ /* check for overflow on s1 */
+ if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL)
+ {
+ temp = (Word16)(s1 >> 12);
+ }
+ else if (s1 > 0x07ffffffL)
+ {
+ temp = MAX_16;
+ }
+ else
+ {
+ temp = MIN_16;
+ }
+
+ s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2);
+
+ *(yy++) = temp;
+ *(p_y++) = temp;
+
+ p_yy1 = yy;
+
+ /* check for overflow on s2 */
+ if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL)
+ {
+ temp = (Word16)(s2 >> 12);
+ }
+ else if (s2 > 0x07ffffffL)
+ {
+ temp = MAX_16;
+ }
+ else
+ {
+ temp = MIN_16;
+ }
+
+ *(yy++) = temp;
+ *(p_y++) = temp;
+ }
+
+ p_yy1 = &y[M-1];
+
+ for (i = (lg - M) >> 1; i != 0; i--)
+ {
+ p_a = a;
+
+ s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a), 0x00000800L);
+ s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_a++), 0x00000800L);
+ s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
+
+ for (j = (M >> 1) - 2; j != 0; j--)
+ {
+ s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
+ s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
+ s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
+ s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
+ s2 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a), (Word32) * (p_yy1--), s2);
+ s1 = amrnb_fxp_msu_16_by_16bb((Word32) * (p_a++), (Word32) * (p_yy1), s1);
+ }
+
+ if ((UWord32)(s1 - 0xf8000000L) < 0x0fffffffL)
+ {
+ temp = (Word16)(s1 >> 12);
+ }
+ else if (s1 > 0x07ffffffL)
+ {
+ temp = MAX_16;
+ }
+ else
+ {
+ temp = MIN_16;
+ }
+
+ s2 = amrnb_fxp_msu_16_by_16bb((Word32)a[1], (Word32)temp, s2);
+
+ *(p_y++) = temp;
+ p_yy1 = p_y;
+
+ if ((UWord32)(s2 - 0xf8000000L) < 0x0fffffffL)
+ {
+ *(p_y++) = (Word16)(s2 >> 12);
+ }
+ else if (s2 > 0x07ffffffL)
+ {
+ *(p_y++) = MAX_16;
+ }
+ else
+ {
+ *(p_y++) = MIN_16;
+ }
+ }
+
+ /* Update of memory if update==1 */
+ if (update != 0)
+ {
+ memcpy(mem, &y[lg-M], M*sizeof(Word16));
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/common/src/vad1.cpp b/media/libstagefright/codecs/amrnb/common/src/vad1.cpp
new file mode 100644
index 0000000..a6e1131
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/vad1.cpp
@@ -0,0 +1,2330 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: ./audio/gsm-amr/c/src/vad1.c
+ Functions:
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+ Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description: Made changes per review comments
+ (1) Removed include of "count.h"
+ (2) Replaced "basic_op.h" with individual include files
+ (3) Removed some unnecessary instances of sub().
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "vad.h"
+#include "typedef.h"
+#include "shr.h"
+#include "basic_op.h"
+#include "cnst_vad.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: first_filter_stage
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ data -- array of type Word16 -- filter memory
+ in -- array of type Word16 -- input signal
+
+ Outputs:
+ data -- array of type Word16 -- filter memory
+ out -- array of type Word16 -- output values, every other
+ output is low-pass part and
+ other is high-pass part every
+
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Scale input down by one bit. Calculate 5th order
+ half-band lowpass/highpass filter pair with
+ decimation.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void first_filter_stage(
+ Word16 in[], /* i : input signal */
+ Word16 out[], /* o : output values, every other */
+ /* output is low-pass part and */
+ /* other is high-pass part every */
+ Word16 data[], /* i/o : filter memory */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 temp0;
+ Word16 temp1;
+ Word16 temp2;
+ Word16 temp3;
+ Word16 i;
+ Word16 data0;
+ Word16 data1;
+
+ data0 = data[0];
+ data1 = data[1];
+
+ for (i = 0; i < FRAME_LEN / 4; i++)
+ {
+ temp0 = mult(COEFF5_1, data0, pOverflow);
+ temp1 = shr(in[4*i+0], 2, pOverflow);
+ temp0 = sub(temp1, temp0, pOverflow);
+
+ temp1 = mult(COEFF5_1, temp0, pOverflow);
+ temp1 = add(data0, temp1, pOverflow);
+
+ temp3 = mult(COEFF5_2, data1, pOverflow);
+ temp2 = shr(in[4*i+1], 2, pOverflow);
+
+ temp3 = sub(temp2, temp3, pOverflow);
+
+ temp2 = mult(COEFF5_2, temp3, pOverflow);
+ temp2 = add(data1, temp2, pOverflow);
+
+ out[4*i+0] = add(temp1, temp2, pOverflow);
+ out[4*i+1] = sub(temp1, temp2, pOverflow);
+
+ temp1 = mult(COEFF5_1, temp0, pOverflow);
+ temp2 = shr(in[4*i+2], 2, pOverflow);
+ data0 = sub(temp2, temp1, pOverflow);
+
+ temp1 = mult(COEFF5_1, data0, pOverflow);
+ temp1 = add(temp0, temp1, pOverflow);
+
+ data1 = mult(COEFF5_2, temp3, pOverflow);
+ temp2 = shr(in[4*i+3], 2, pOverflow);
+ data1 = sub(temp2, data1, pOverflow);
+
+ temp2 = mult(COEFF5_2, data1, pOverflow);
+ temp2 = add(temp3, temp2, pOverflow);
+
+ out[4*i+2] = add(temp1, temp2, pOverflow);
+ out[4*i+3] = sub(temp1, temp2, pOverflow);
+ }
+
+ data[0] = data0;
+ data[1] = data1;
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: filter5
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ in0 -- array of type Word16 -- input values; output low-pass part
+ in1 -- array of type Word16 -- input values; output high-pass part
+ data -- array of type Word16 -- updated filter memory
+
+ Outputs:
+ in0 -- array of type Word16 -- input values; output low-pass part
+ in1 -- array of type Word16 -- input values; output high-pass part
+ data -- array of type Word16 -- updated filter memory
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Fifth-order half-band lowpass/highpass filter pair with
+ decimation.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+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 : updated filter memory */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+ )
+{
+ Word16 temp0;
+ Word16 temp1;
+ Word16 temp2;
+
+ temp0 = mult(COEFF5_1, data[0], pOverflow);
+ temp0 = sub(*in0, temp0, pOverflow);
+
+ temp1 = mult(COEFF5_1, temp0, pOverflow);
+ temp1 = add(data[0], temp1, pOverflow);
+ data[0] = temp0;
+
+ temp0 = mult(COEFF5_2, data[1], pOverflow);
+ temp0 = sub(*in1, temp0, pOverflow);
+
+ temp2 = mult(COEFF5_2, temp0, pOverflow);
+ temp2 = add(data[1], temp2, pOverflow);
+
+ data[1] = temp0;
+
+ temp0 = add(temp1, temp2, pOverflow);
+ *in0 = shr(temp0, 1, pOverflow);
+
+ temp0 = sub(temp1, temp2, pOverflow);
+ *in1 = shr(temp0, 1, pOverflow);
+}
+
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: filter3
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+ Inputs:
+ in0 -- array of type Word16 -- input values; output low-pass part
+ in1 -- array of type Word16 -- input values; output high-pass part
+ data -- array of type Word16 -- updated filter memory
+
+ Outputs:
+ in0 -- array of type Word16 -- input values; output low-pass part
+ in1 -- array of type Word16 -- input values; output high-pass part
+ data -- array of type Word16 -- updated filter memory
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Third-order half-band lowpass/highpass filter pair with
+ decimation.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+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 : updated filter memory */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 temp1;
+ Word16 temp2;
+
+ temp1 = mult(COEFF3, *data, pOverflow);
+ temp1 = sub(*in1, temp1, pOverflow);
+
+ temp2 = mult(COEFF3, temp1, pOverflow);
+ temp2 = add(*data, temp2, pOverflow);
+
+ *data = temp1;
+
+ temp1 = sub(*in0, temp2, pOverflow);
+
+ *in1 = shr(temp1, 1, pOverflow);
+
+ temp1 = add(*in0, temp2, pOverflow);
+
+ *in0 = shr(temp1, 1, pOverflow);
+}
+
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: level_calculation
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ data -- array of type Word16 -- signal buffer
+ sub_level -- pointer to type Word16 -- level calculated at the end of
+ the previous frame
+
+ count1 -- Word16 -- number of samples to be counted
+ count2 -- Word16 -- number of samples to be counted
+ ind_m -- Word16 -- step size for the index of the data buffer
+ ind_a -- Word16 -- starting index of the data buffer
+ scale -- Word16 -- scaling for the level calculation
+
+ Outputs:
+ sub_level -- pointer to tyep Word16 -- level of signal calculated from the
+ last (count2 - count1) samples.
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ signal level
+
+ Global Variables Used:
+
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Calculate signal level in a sub-band. Level is calculated
+ by summing absolute values of the input data.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static Word16 level_calculation(
+ Word16 data[], /* i : signal buffer */
+ Word16 *sub_level, /* i : level calculate 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 */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word32 l_temp1;
+ Word32 l_temp2;
+ Word16 level;
+ Word16 i;
+
+ l_temp1 = 0L;
+
+ for (i = count1; i < count2; i++)
+ {
+ l_temp1 = L_mac(l_temp1, 1, abs_s(data[ind_m*i+ind_a]), pOverflow);
+ }
+
+ l_temp2 = L_add(l_temp1, L_shl(*sub_level, sub(16, scale, pOverflow), pOverflow), pOverflow);
+ *sub_level = extract_h(L_shl(l_temp1, scale, pOverflow));
+
+ for (i = 0; i < count1; i++)
+ {
+ l_temp2 = L_mac(l_temp2, 1, abs_s(data[ind_m*i+ind_a]), pOverflow);
+ }
+ level = extract_h(L_shl(l_temp2, scale, pOverflow));
+
+ return level;
+}
+
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: filter_bank
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- pointer to type vadState1 -- State struct
+ in -- array of type Word16 -- input frame
+
+ Outputs:
+ level -- array of type Word16 -- signal levels at each band
+ st -- pointer to type vadState1 -- State struct
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Divides input signal into 9-bands and calculas level of
+ the signal in each band
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void filter_bank(
+ vadState1 *st, /* i/o : State struct */
+ Word16 in[], /* i : input frame */
+ Word16 level[], /* 0 : signal levels at each band */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word16 tmp_buf[FRAME_LEN];
+
+ /* calculate the filter bank */
+
+ first_filter_stage(in, tmp_buf, st->a_data5[0], pOverflow);
+
+ for (i = 0; i < FRAME_LEN / 4; i++)
+ {
+ filter5(&tmp_buf[4*i], &tmp_buf[4*i+2], st->a_data5[1], pOverflow);
+ filter5(&tmp_buf[4*i+1], &tmp_buf[4*i+3], st->a_data5[2], pOverflow);
+ }
+ for (i = 0; i < FRAME_LEN / 8; i++)
+ {
+ filter3(&tmp_buf[8*i+0], &tmp_buf[8*i+4], &st->a_data3[0], pOverflow);
+ filter3(&tmp_buf[8*i+2], &tmp_buf[8*i+6], &st->a_data3[1], pOverflow);
+ filter3(&tmp_buf[8*i+3], &tmp_buf[8*i+7], &st->a_data3[4], pOverflow);
+ }
+
+ for (i = 0; i < FRAME_LEN / 16; i++)
+ {
+ filter3(&tmp_buf[16*i+0], &tmp_buf[16*i+8], &st->a_data3[2], pOverflow);
+ filter3(&tmp_buf[16*i+4], &tmp_buf[16*i+12], &st->a_data3[3], pOverflow);
+ }
+
+ /* calculate levels in each frequency band */
+
+ /* 3000 - 4000 Hz*/
+ level[8] = level_calculation(tmp_buf, &st->sub_level[8], FRAME_LEN / 4 - 8,
+ FRAME_LEN / 4, 4, 1, 15, pOverflow);
+ /* 2500 - 3000 Hz*/
+ level[7] = level_calculation(tmp_buf, &st->sub_level[7], FRAME_LEN / 8 - 4,
+ FRAME_LEN / 8, 8, 7, 16, pOverflow);
+ /* 2000 - 2500 Hz*/
+ level[6] = level_calculation(tmp_buf, &st->sub_level[6], FRAME_LEN / 8 - 4,
+ FRAME_LEN / 8, 8, 3, 16, pOverflow);
+ /* 1500 - 2000 Hz*/
+ level[5] = level_calculation(tmp_buf, &st->sub_level[5], FRAME_LEN / 8 - 4,
+ FRAME_LEN / 8, 8, 2, 16, pOverflow);
+ /* 1000 - 1500 Hz*/
+ level[4] = level_calculation(tmp_buf, &st->sub_level[4], FRAME_LEN / 8 - 4,
+ FRAME_LEN / 8, 8, 6, 16, pOverflow);
+ /* 750 - 1000 Hz*/
+ level[3] = level_calculation(tmp_buf, &st->sub_level[3], FRAME_LEN / 16 - 2,
+ FRAME_LEN / 16, 16, 4, 16, pOverflow);
+ /* 500 - 750 Hz*/
+ level[2] = level_calculation(tmp_buf, &st->sub_level[2], FRAME_LEN / 16 - 2,
+ FRAME_LEN / 16, 16, 12, 16, pOverflow);
+ /* 250 - 500 Hz*/
+ level[1] = level_calculation(tmp_buf, &st->sub_level[1], FRAME_LEN / 16 - 2,
+ FRAME_LEN / 16, 16, 8, 16, pOverflow);
+ /* 0 - 250 Hz*/
+ level[0] = level_calculation(tmp_buf, &st->sub_level[0], FRAME_LEN / 16 - 2,
+ FRAME_LEN / 16, 16, 0, 16, pOverflow);
+}
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: update_cntrl
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- pointer to type vadState1 -- State struct
+ level -- array of type Word16 -- sub-band levels of the input frame
+
+ Outputs:
+ st -- pointer to type vadState1 -- State struct
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Control update of the background noise estimate.
+ Inputs : pitch: flags for pitch detection
+ stat_count: stationary counter
+ tone: flags indicating presence of a tone
+ complex: flags for complex detection
+ vadreg: intermediate VAD flags
+ Output : stat_count: stationary counter
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void update_cntrl(
+ vadState1 *st, /* i/o : State struct */
+ Word16 level[], /* i : sub-band levels of the input frame */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word16 temp;
+ Word16 stat_rat;
+ Word16 exp;
+ Word16 num;
+ Word16 denom;
+ Word16 alpha;
+
+ /* handle highband complex signal input separately */
+ /* if ther has been highband correlation for some time */
+ /* make sure that the VAD update speed is low for a while */
+ if (st->complex_warning != 0)
+ {
+ if (st->stat_count < CAD_MIN_STAT_COUNT)
+ {
+ st->stat_count = CAD_MIN_STAT_COUNT;
+ }
+ }
+ /* NB stat_count is allowed to be decreased by one below again */
+ /* deadlock in speech is not possible unless the signal is very */
+ /* complex and need a high rate */
+
+ /* if fullband pitch or tone have been detected for a while, initialize stat_count */
+ if (((Word16)(st->pitch & 0x6000) == 0x6000) ||
+ ((Word16)(st->tone & 0x7c00) == 0x7c00))
+ {
+ 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 = shl(denom, exp, pOverflow);
+
+ /* stat_rat = num/denom * 64 */
+ temp = shr(num, 1, pOverflow);
+ temp = div_s(temp, denom);
+
+ stat_rat = add(stat_rat, shr(temp, sub(8, exp, pOverflow), pOverflow), pOverflow);
+ }
+
+ /* 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 = sub(st->stat_count, 1, pOverflow);
+ }
+ }
+ }
+ }
+ }
+
+ /* 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++)
+ {
+ temp = sub(level[i], st->ave_level[i], pOverflow);
+ temp = mult_r(alpha, temp, pOverflow);
+
+ st->ave_level[i] =
+ add(
+ st->ave_level[i],
+ temp,
+ pOverflow);
+ }
+}
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: hangover_addition
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ noise_level -- Word16 -- average level of the noise estimates
+ low_power -- Word16 -- flag power of the input frame
+
+ Outputs:
+ st -- pointer to type vadState1 -- State struct
+ pOverflow -- pointer to type Flag -- overflow indicato
+
+ Returns:
+ VAD_flag indicating final VAD decision (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function : hangover_addition
+ Purpose : Add hangover for complex signal or after speech bursts
+ Inputs : burst_count: counter for the length of speech bursts
+ hang_count: hangover counter
+ vadreg: intermediate VAD decision
+ Outputs : burst_count: counter for the length of speech bursts
+ hang_count: hangover counter
+ Return value : VAD_flag indicating final VAD decision
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static Word16 hangover_addition(
+ vadState1 *st, /* i/o : State struct */
+ Word16 noise_level, /* i : average level of the noise */
+ /* estimates */
+ Word16 low_power, /* i : flag power of the input frame */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 hang_len;
+ Word16 burst_len;
+
+ /*
+ Calculate burst_len and hang_len
+ burst_len: number of consecutive intermediate vad flags with "1"-decision
+ required for hangover addition
+ hang_len: length of the hangover
+ */
+
+ if (noise_level > HANG_NOISE_THR)
+ {
+ burst_len = BURST_LEN_HIGH_NOISE;
+ hang_len = HANG_LEN_HIGH_NOISE;
+ }
+ else
+ {
+ burst_len = BURST_LEN_LOW_NOISE;
+ hang_len = HANG_LEN_LOW_NOISE;
+ }
+
+ /* if the input power (pow_sum) is lower than a threshold, clear
+ counters and set VAD_flag to "0" "fast exit" */
+ if (low_power != 0)
+ {
+ st->burst_count = 0;
+ st->hang_count = 0;
+ st->complex_hang_count = 0;
+ st->complex_hang_timer = 0;
+ return 0;
+ }
+
+ if (st->complex_hang_timer > CVAD_HANG_LIMIT)
+ {
+ if (st->complex_hang_count < CVAD_HANG_LENGTH)
+ {
+ st->complex_hang_count = CVAD_HANG_LENGTH;
+ }
+ }
+
+ /* long time very complex signal override VAD output function */
+ if (st->complex_hang_count != 0)
+ {
+ st->burst_count = BURST_LEN_HIGH_NOISE;
+ st->complex_hang_count = sub(st->complex_hang_count, 1, pOverflow);
+ return 1;
+ }
+ else
+ {
+ /* let hp_corr work in from a noise_period indicated by the VAD */
+ if (((st->vadreg & 0x3ff0) == 0) &&
+ (st->corr_hp_fast > CVAD_THRESH_IN_NOISE))
+ {
+ return 1;
+ }
+ }
+
+ /* update the counters (hang_count, burst_count) */
+ if ((st->vadreg & 0x4000) != 0)
+ {
+ st->burst_count = add(st->burst_count, 1, pOverflow);
+
+ 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 = sub(st->hang_count, 1, pOverflow);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: noise_estimate_update
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- pointer to type vadState1 -- State struct
+ level -- array of type Word16 -- sub-band levels of the input frame
+
+ Outputs:
+ st -- pointer to type vadState1 -- State struct
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Update of background noise estimate
+ Inputs : bckr_est: background noise estimate
+ pitch: flags for pitch detection
+ stat_count: stationary counter
+ Outputs : bckr_est: background noise estimate
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void noise_estimate_update(
+ vadState1 *st, /* i/o : State struct */
+ Word16 level[], /* i : sub-band levels of the input frame */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word16 alpha_up;
+ Word16 alpha_down;
+ Word16 bckr_add;
+
+ /* Control update of bckr_est[] */
+ update_cntrl(st, level, pOverflow);
+
+ /* Choose update speed */
+ bckr_add = 2;
+
+ if (((0x7800 & st->vadreg) == 0) &&
+ ((st->pitch & 0x7800) == 0)
+ && (st->complex_hang_count == 0))
+ {
+ alpha_up = ALPHA_UP1;
+ alpha_down = ALPHA_DOWN1;
+ }
+ else
+ {
+ if ((st->stat_count == 0)
+ && (st->complex_hang_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 = sub(st->old_level[i], st->bckr_est[i], pOverflow);
+
+ if (temp < 0)
+ { /* update downwards*/
+ temp = mult_r(alpha_down, temp, pOverflow);
+ temp = add(st->bckr_est[i], temp, pOverflow);
+
+ st->bckr_est[i] = add(-2, temp, pOverflow);
+
+ /* 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 */
+ temp = mult_r(alpha_up, temp, pOverflow);
+ temp = add(st->bckr_est[i], temp, pOverflow);
+ st->bckr_est[i] = add(bckr_add, temp, pOverflow);
+
+ /* 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 NAME: complex_estimate_adapt
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- pointer to type vadState1 -- State struct
+ low_power -- Word16 -- very low level flag of the input frame
+
+ Outputs:
+ st -- pointer to type vadState1 -- State struct
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function : complex_estimate_adapt
+ Purpose : Update/adapt of complex signal estimate
+ Inputs : low_power: low signal power flag
+ Outputs : st->corr_hp_fast: long term complex signal estimate
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void complex_estimate_adapt(
+ vadState1 *st, /* i/o : VAD state struct */
+ Word16 low_power, /* i : very low level flag of the input frame */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 alpha; /* Q15 */
+ Word32 L_tmp; /* Q31 */
+
+
+ /* adapt speed on own state */
+ if (st->best_corr_hp < st->corr_hp_fast) /* decrease */
+ {
+ if (st->corr_hp_fast < CVAD_THRESH_ADAPT_HIGH)
+ { /* low state */
+ alpha = CVAD_ADAPT_FAST;
+ }
+ else
+ { /* high state */
+ alpha = CVAD_ADAPT_REALLY_FAST;
+ }
+ }
+ else /* increase */
+ {
+ if (st->corr_hp_fast < CVAD_THRESH_ADAPT_HIGH)
+ {
+ alpha = CVAD_ADAPT_FAST;
+ }
+ else
+ {
+ alpha = CVAD_ADAPT_SLOW;
+ }
+ }
+
+ L_tmp = L_deposit_h(st->corr_hp_fast);
+ L_tmp = L_msu(L_tmp, alpha, st->corr_hp_fast, pOverflow);
+ L_tmp = L_mac(L_tmp, alpha, st->best_corr_hp, pOverflow);
+ st->corr_hp_fast = pv_round(L_tmp, pOverflow); /* Q15 */
+
+ if (st->corr_hp_fast < CVAD_MIN_CORR)
+ {
+ st->corr_hp_fast = CVAD_MIN_CORR;
+ }
+
+ if (low_power != 0)
+ {
+ st->corr_hp_fast = CVAD_MIN_CORR;
+ }
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: complex_vad
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- pointer to type vadState1 -- State struct
+ low_power -- Word16 -- flag power of the input frame
+
+ Outputs:
+ st -- pointer to type vadState1 -- State struct
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+
+ Returns:
+ the complex background decision
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : complex background decision
+ Return value : the complex background decision
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static Word16 complex_vad(
+ vadState1 *st, /* i/o : VAD state struct */
+ Word16 low_power, /* i : flag power of the input frame */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ st->complex_high = shr(st->complex_high, 1, pOverflow);
+ st->complex_low = shr(st->complex_low, 1, pOverflow);
+
+ if (low_power == 0)
+ {
+ if (st->corr_hp_fast > CVAD_THRESH_ADAPT_HIGH)
+ {
+ st->complex_high |= 0x4000;
+ }
+
+ if (st->corr_hp_fast > CVAD_THRESH_ADAPT_LOW)
+ {
+ st->complex_low |= 0x4000;
+ }
+ }
+
+ if (st->corr_hp_fast > CVAD_THRESH_HANG)
+ {
+ st->complex_hang_timer = add(st->complex_hang_timer, 1, pOverflow);
+ }
+ else
+ {
+ st->complex_hang_timer = 0;
+ }
+
+ return ((Word16)(st->complex_high & 0x7f80) == 0x7f80 ||
+ (Word16)(st->complex_low & 0x7fff) == 0x7fff);
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: vad_decision
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- pointer to type vadState1 -- State struct
+ level -- array of type Word16 -- sub-band levels of the input frame
+ pow_sum -- Word32 -- power of the input frame
+
+ Outputs:
+ st -- pointer to type vadState1 -- State struct
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ VAD_flag (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Calculates VAD_flag
+ Inputs : bckr_est: background noise estimate
+ vadreg: intermediate VAD flags
+ Outputs : noise_level: average level of the noise estimates
+ vadreg: intermediate VAD flags
+ Return value : VAD_flag
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static Word16 vad_decision(
+ vadState1 *st, /* i/o : State struct */
+ Word16 level[COMPLEN], /* i : sub-band levels of the input frame */
+ Word32 pow_sum, /* i : power of the input frame */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word16 snr_sum;
+ Word32 L_temp;
+ Word16 vad_thr;
+ Word16 temp;
+ Word16 noise_level;
+ Word16 low_power_flag;
+ Word16 temp1;
+
+ /*
+ Calculate squared sum of the input levels (level)
+ divided by the background noise components (bckr_est).
+ */
+ L_temp = 0;
+
+ for (i = 0; i < COMPLEN; i++)
+ {
+ Word16 exp;
+
+ exp = norm_s(st->bckr_est[i]);
+ temp = shl(st->bckr_est[i], exp, pOverflow);
+ temp = div_s(shr(level[i], 1, pOverflow), temp);
+ temp = shl(temp, sub(exp, UNIRSHFT - 1, pOverflow), pOverflow);
+ L_temp = L_mac(L_temp, temp, temp, pOverflow);
+ }
+
+ snr_sum = extract_h(L_shl(L_temp, 6, pOverflow));
+ snr_sum = mult(snr_sum, INV_COMPLEN, pOverflow);
+
+ /* Calculate average level of estimated background noise */
+ L_temp = 0;
+ for (i = 0; i < COMPLEN; i++)
+ {
+ L_temp = L_add(L_temp, st->bckr_est[i], pOverflow);
+ }
+
+ noise_level = extract_h(L_shl(L_temp, 13, pOverflow));
+
+ /* Calculate VAD threshold */
+ temp1 = sub(noise_level, VAD_P1, pOverflow);
+ temp1 = mult(VAD_SLOPE, temp1, pOverflow);
+ vad_thr = add(temp1, VAD_THR_HIGH, pOverflow);
+
+ if (vad_thr < VAD_THR_LOW)
+ {
+ vad_thr = VAD_THR_LOW;
+ }
+
+ /* Shift VAD decision register */
+ st->vadreg = shr(st->vadreg, 1, pOverflow);
+
+ /* Make intermediate VAD decision */
+ if (snr_sum > vad_thr)
+ {
+ st->vadreg |= 0x4000;
+ }
+ /* primary vad decsion made */
+
+ /* check if the input power (pow_sum) is lower than a threshold" */
+ if (L_sub(pow_sum, VAD_POW_LOW, pOverflow) < 0)
+ {
+ low_power_flag = 1;
+ }
+ else
+ {
+ low_power_flag = 0;
+ }
+
+ /* update complex signal estimate st->corr_hp_fast and hangover reset timer using */
+ /* low_power_flag and corr_hp_fast and various adaptation speeds */
+ complex_estimate_adapt(st, low_power_flag, pOverflow);
+
+ /* check multiple thresholds of the st->corr_hp_fast value */
+ st->complex_warning = complex_vad(st, low_power_flag, pOverflow);
+
+ /* Update speech subband vad background noise estimates */
+ noise_estimate_update(st, level, pOverflow);
+
+ /* Add speech and complex hangover and return speech VAD_flag */
+ /* long term complex hangover may be added */
+ st->speech_vad_decision = hangover_addition(st, noise_level, low_power_flag, pOverflow);
+
+ return (st->speech_vad_decision);
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: vad1_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state -- double pointer to type vadState1 -- pointer to memory to
+ be initialized.
+
+ Outputs:
+ state -- points to initalized area in memory.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Allocates state memory and initializes state memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 vad1_init(vadState1 **state)
+{
+ vadState1* s;
+
+ if (state == (vadState1 **) NULL)
+ {
+ return -1;
+ }
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (vadState1 *) malloc(sizeof(vadState1))) == NULL)
+ {
+ return -1;
+ }
+
+ vad1_reset(s);
+
+ *state = s;
+
+ return 0;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: vad1_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state -- pointer to type vadState1 -- State struct
+
+ Outputs:
+ state -- pointer to type vadState1 -- State struct
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose: Resets state memory to zero
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 vad1_reset(vadState1 *state)
+{
+ Word16 i;
+ Word16 j;
+
+ if (state == (vadState1 *) NULL)
+ {
+ return -1;
+ }
+
+ /* Initialize pitch detection variables */
+ state->oldlag_count = 0;
+ state->oldlag = 0;
+ state->pitch = 0;
+ state->tone = 0;
+
+ state->complex_high = 0;
+ state->complex_low = 0;
+ state->complex_hang_timer = 0;
+
+ state->vadreg = 0;
+
+ state->stat_count = 0;
+ state->burst_count = 0;
+ state->hang_count = 0;
+ state->complex_hang_count = 0;
+
+ /* initialize memory used by the filter bank */
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ state->a_data5[i][j] = 0;
+ }
+ }
+
+ for (i = 0; i < 5; 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->best_corr_hp = CVAD_LOWPOW_RESET;
+
+ state->speech_vad_decision = 0;
+ state->complex_warning = 0;
+ state->sp_burst_count = 0;
+
+ state->corr_hp_fast = CVAD_LOWPOW_RESET;
+
+ return 0;
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: vad1_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state -- pointer to type vadState1 -- State struct
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ The memory used for state memory is freed
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void vad1_exit(vadState1 **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ /* deallocate memory */
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: vad_complex_detection_update
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ best_corr_hp -- Word16 -- best Corr
+ state -- pointer to type vadState1 -- State struct
+
+ Outputs:
+ state -- pointer to type vadState1 -- State struct
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : update vad->bestCorr_hp complex signal feature state
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void vad_complex_detection_update(
+ vadState1 *st, /* i/o : State struct */
+ Word16 best_corr_hp) /* i : best Corr */
+{
+ st->best_corr_hp = best_corr_hp;
+}
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: vad_tone_detection
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- pointer to type vadState1 -- State struct
+ t0 -- Word32 -- autocorrelation maxima
+ t1 -- Word32 -- energy
+
+ Outputs:
+ st -- pointer to type vadState1 -- State struct
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Set tone flag if pitch gain is high. This is used to detect
+ signaling tones and other signals with high pitch gain.
+ Inputs : tone: flags indicating presence of a tone
+ Outputs : tone: flags indicating presence of a tone
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void vad_tone_detection(
+ vadState1 *st, /* i/o : State struct */
+ Word32 t0, /* i : autocorrelation maxima */
+ Word32 t1, /* i : energy */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 temp;
+ /*
+ if (t0 > TONE_THR * t1)
+ set tone flag
+ */
+ temp = pv_round(t1, pOverflow);
+
+ if ((temp > 0) && (L_msu(t0, temp, TONE_THR, pOverflow) > 0))
+ {
+ st->tone |= 0x4000;
+ }
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: vad_tone_detection_update
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ one_lag_per_frame -- Word16 -- 1 if one open-loop lag is calculated per
+ each frame, otherwise 0
+ st -- pointer to type vadState1 -- State struct
+
+ Outputs:
+ st -- pointer to type vadState1 -- State struct
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Update the tone flag register. Tone flags are shifted right
+ by one bit. This function should be called from the speech
+ encoder before call to Vad_tone_detection() function.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void vad_tone_detection_update(
+ vadState1 *st, /* i/o : State struct */
+ Word16 one_lag_per_frame, /* i : 1 if one open-loop lag */
+ /* is calculated per each */
+ /* frame, otherwise 0 */
+ Flag *pOverflow /* o : Flags overflow */
+)
+{
+ /* Shift tone flags right by one bit */
+ st->tone = shr(st->tone, 1, pOverflow);
+
+ /* If open-loop lag is calculated only once in each frame, do extra update
+ and assume that the other tone flag of the frame is one. */
+ if (one_lag_per_frame != 0)
+ {
+ st->tone = shr(st->tone, 1, pOverflow);
+ st->tone |= 0x2000;
+ }
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: vad_pitch_detection
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ T_op -- array of type Word16 -- speech encoder open loop lags
+ st -- pointer to type vadState1 -- State struct
+
+ Outputs:
+ st -- pointer to type vadState1 -- State struct
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Test whether signal contains pitch or other periodic
+ component.
+ Return value : Boolean voiced / unvoiced decision in state variable
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void vad_pitch_detection(
+ vadState1 *st, /* i/o : State struct */
+ Word16 T_op[], /* i : speech encoder open loop lags */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 lagcount;
+ Word16 i;
+ Word16 temp;
+
+ lagcount = 0;
+
+ for (i = 0; i < 2; i++)
+ {
+ temp = sub(st->oldlag, T_op[i], pOverflow);
+ temp = abs_s(temp);
+
+ if (temp < LTHRESH)
+ {
+ lagcount = add(lagcount, 1, pOverflow);
+ }
+
+ /* Save the current LTP lag */
+ st->oldlag = T_op[i];
+ }
+
+ /* Make pitch decision.
+ Save flag of the pitch detection to the variable pitch.
+ */
+ st->pitch = shr(st->pitch, 1, pOverflow);
+
+ temp =
+ add(
+ st->oldlag_count,
+ lagcount,
+ pOverflow);
+
+ if (temp >= NTHRESH)
+ {
+ st->pitch |= 0x4000;
+ }
+
+ /* Update oldlagcount */
+ st->oldlag_count = lagcount;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: vad1
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- pointer to type vadState1 -- State struct
+ in_buf -- array of type Word16 -- samples of the input frame
+
+ Outputs:
+ st -- pointer to type vadState1 -- State struct
+ pOverflow -- pointer to type Flag -- overflow indicator
+
+ Returns:
+ VAD Decision, 1 = speech, 0 = noise
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Main program for Voice Activity Detection (VAD) for AMR
+ Return value : VAD Decision, 1 = speech, 0 = noise
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ vad1.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 vad1(
+ vadState1 *st, /* i/o : State struct */
+ Word16 in_buf[], /* i : samples of the input frame */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 level[COMPLEN];
+ Word32 pow_sum;
+ Word16 i;
+
+ /* Calculate power of the input frame. */
+ pow_sum = 0L;
+
+ for (i = 0; i < FRAME_LEN; i++)
+ {
+ pow_sum = L_mac(pow_sum, in_buf[i-LOOKAHEAD], in_buf[i-LOOKAHEAD], pOverflow);
+ }
+
+ /*
+ If input power is very low, clear pitch flag of the current frame
+ */
+ if (L_sub(pow_sum, POW_PITCH_THR, pOverflow) < 0)
+ {
+ st->pitch = st->pitch & 0x3fff;
+ }
+
+ /*
+ If input power is very low, clear complex flag of the "current" frame
+ */
+ if (L_sub(pow_sum, POW_COMPLEX_THR, pOverflow) < 0)
+ {
+ st->complex_low = st->complex_low & 0x3fff;
+ }
+
+ /*
+ Run the filter bank which calculates signal levels at each band
+ */
+ filter_bank(st, in_buf, level, pOverflow);
+
+ return (vad_decision(st, level, pow_sum, pOverflow));
+}
+
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/weight_a.cpp b/media/libstagefright/codecs/amrnb/common/src/weight_a.cpp
new file mode 100644
index 0000000..2e2efc4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/weight_a.cpp
@@ -0,0 +1,196 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Pathname: ./audio/gsm-amr/c/src/weight_a.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Put file into template and first pass at optimization.
+
+ Description: Made changes based on comments from the review meeting. Used
+ pointers instead of index addressing in the arrays.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Fixed typecasting issue with TI C compiler.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Modified FOR loop to count down.
+ 2. Used address pre-increment instead of address offsets.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "weight_a.h"
+#include "typedef.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Weight_Ai
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ a = LPC coefficients (Word16)
+ fac = Spectral expansion factors (Word16)
+ a_exp = Spectral expanded LPC coefficients (Word16)
+
+ Outputs:
+ a_exp points to the updated spectral expanded LPC coefficients
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function calculates the spectral expansion for the LP coefficients of
+ order M.
+ a_exp[i] = a[i] * fac[i-1] ; i=1..M
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ weight_a.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Weight_Ai (
+ Word16 a[], // (i) : a[M+1] LPC coefficients (M=10)
+ const Word16 fac[], // (i) : Spectral expansion factors.
+ Word16 a_exp[] // (o) : Spectral expanded LPC coefficients
+)
+{
+ Word16 i;
+ a_exp[0] = a[0];
+
+ for (i = 1; i <= M; i++)
+ {
+ a_exp[i] = pv_round (L_mult (a[i], fac[i - 1]));
+ }
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Weight_Ai(
+ Word16 a[], /* (i) : a[M+1] LPC coefficients (M=10) */
+ const Word16 fac[], /* (i) : Spectral expansion factors. */
+ Word16 a_exp[] /* (o) : Spectral expanded LPC coefficients */
+)
+{
+ register Word16 i;
+
+ *(a_exp) = *(a);
+
+ for (i = M; i >= 1; i--)
+ {
+ a_exp += 1;
+ a += 1;
+ fac += 1;
+ *(a_exp) = (Word16)((((Word32) * (a)) * *(fac - 1)
+ + 0x00004000L) >> 15);
+ }
+
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrnb/common/src/window_tab.cpp b/media/libstagefright/codecs/amrnb/common/src/window_tab.cpp
new file mode 100644
index 0000000..d8fc8cc
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/common/src/window_tab.cpp
@@ -0,0 +1,281 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Pathname: .audio/gsm-amr/c/src/window_tab.c
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed tables from static const to just const.
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ File : window.tab
+ Purpose : Hamming_cos window for LPC analysis.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+#include "window_tab.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+ /*************************************************************************
+ *
+ * Hamming_cos windows for LPC analysis.
+ *
+ *************************************************************************/
+
+ /* window for non-EFR modesm; uses 40 samples lookahead */
+
+ const Word16 window_200_40[L_WINDOW] =
+ {
+ 2621, 2623, 2629, 2638, 2651, 2668, 2689, 2713, 2741, 2772,
+ 2808, 2847, 2890, 2936, 2986, 3040, 3097, 3158, 3223, 3291,
+ 3363, 3438, 3517, 3599, 3685, 3774, 3867, 3963, 4063, 4166,
+ 4272, 4382, 4495, 4611, 4731, 4853, 4979, 5108, 5240, 5376,
+ 5514, 5655, 5800, 5947, 6097, 6250, 6406, 6565, 6726, 6890,
+ 7057, 7227, 7399, 7573, 7750, 7930, 8112, 8296, 8483, 8672,
+ 8863, 9057, 9252, 9450, 9650, 9852, 10055, 10261, 10468, 10677,
+ 10888, 11101, 11315, 11531, 11748, 11967, 12187, 12409, 12632, 12856,
+ 13082, 13308, 13536, 13764, 13994, 14225, 14456, 14688, 14921, 15155,
+ 15389, 15624, 15859, 16095, 16331, 16568, 16805, 17042, 17279, 17516,
+ 17754, 17991, 18228, 18465, 18702, 18939, 19175, 19411, 19647, 19882,
+ 20117, 20350, 20584, 20816, 21048, 21279, 21509, 21738, 21967, 22194,
+ 22420, 22644, 22868, 23090, 23311, 23531, 23749, 23965, 24181, 24394,
+ 24606, 24816, 25024, 25231, 25435, 25638, 25839, 26037, 26234, 26428,
+ 26621, 26811, 26999, 27184, 27368, 27548, 27727, 27903, 28076, 28247,
+ 28415, 28581, 28743, 28903, 29061, 29215, 29367, 29515, 29661, 29804,
+ 29944, 30081, 30214, 30345, 30472, 30597, 30718, 30836, 30950, 31062,
+ 31170, 31274, 31376, 31474, 31568, 31659, 31747, 31831, 31911, 31988,
+ 32062, 32132, 32198, 32261, 32320, 32376, 32428, 32476, 32521, 32561,
+ 32599, 32632, 32662, 32688, 32711, 32729, 32744, 32755, 32763, 32767,
+ 32767, 32741, 32665, 32537, 32359, 32129, 31850, 31521, 31143, 30716,
+ 30242, 29720, 29151, 28538, 27879, 27177, 26433, 25647, 24821, 23957,
+ 23055, 22117, 21145, 20139, 19102, 18036, 16941, 15820, 14674, 13505,
+ 12315, 11106, 9879, 8637, 7381, 6114, 4838, 3554, 2264, 971
+ };
+
+
+ /* window for EFR, first two subframes, no lookahead */
+
+ const Word16 window_160_80[L_WINDOW] =
+ {
+ 2621, 2624, 2633, 2648, 2668, 2695, 2727, 2765, 2809, 2859,
+ 2915, 2976, 3043, 3116, 3194, 3279, 3368, 3464, 3565, 3671,
+ 3783, 3900, 4023, 4151, 4285, 4423, 4567, 4716, 4870, 5029,
+ 5193, 5362, 5535, 5714, 5897, 6084, 6277, 6473, 6674, 6880,
+ 7089, 7303, 7521, 7742, 7968, 8197, 8430, 8667, 8907, 9151,
+ 9398, 9648, 9902, 10158, 10417, 10680, 10945, 11212, 11482, 11755,
+ 12030, 12307, 12586, 12867, 13150, 13435, 13722, 14010, 14299, 14590,
+ 14882, 15175, 15469, 15764, 16060, 16356, 16653, 16950, 17248, 17546,
+ 17844, 18141, 18439, 18736, 19033, 19330, 19625, 19920, 20214, 20507,
+ 20799, 21090, 21380, 21668, 21954, 22239, 22522, 22803, 23083, 23360,
+ 23635, 23907, 24177, 24445, 24710, 24972, 25231, 25488, 25741, 25991,
+ 26238, 26482, 26722, 26959, 27192, 27422, 27647, 27869, 28087, 28300,
+ 28510, 28715, 28916, 29113, 29305, 29493, 29676, 29854, 30028, 30197,
+ 30361, 30519, 30673, 30822, 30966, 31105, 31238, 31366, 31489, 31606,
+ 31718, 31825, 31926, 32021, 32111, 32195, 32273, 32346, 32413, 32475,
+ 32530, 32580, 32624, 32662, 32695, 32721, 32742, 32756, 32765, 32767,
+ 32767, 32756, 32720, 32661, 32578, 32471, 32341, 32188, 32012, 31813,
+ 31592, 31349, 31084, 30798, 30492, 30165, 29818, 29453, 29068, 28666,
+ 28247, 27810, 27358, 26891, 26408, 25913, 25404, 24883, 24350, 23807,
+ 23255, 22693, 22124, 21548, 20965, 20378, 19786, 19191, 18593, 17994,
+ 17395, 16796, 16199, 15604, 15012, 14424, 13842, 13265, 12696, 12135,
+ 11582, 11039, 10507, 9986, 9477, 8981, 8499, 8031, 7579, 7143,
+ 6723, 6321, 5937, 5571, 5225, 4898, 4591, 4305, 4041, 3798,
+ 3577, 3378, 3202, 3048, 2918, 2812, 2729, 2669, 2633, 2621
+ };
+
+ /* window for EFR, last two subframes, no lookahead */
+
+ const Word16 window_232_8[L_WINDOW] =
+ {
+ 2621, 2623, 2627, 2634, 2644, 2656, 2671, 2689, 2710, 2734,
+ 2760, 2789, 2821, 2855, 2893, 2933, 2975, 3021, 3069, 3120,
+ 3173, 3229, 3288, 3350, 3414, 3481, 3550, 3622, 3697, 3774,
+ 3853, 3936, 4021, 4108, 4198, 4290, 4385, 4482, 4582, 4684,
+ 4788, 4895, 5004, 5116, 5230, 5346, 5464, 5585, 5708, 5833,
+ 5960, 6090, 6221, 6355, 6491, 6629, 6769, 6910, 7054, 7200,
+ 7348, 7498, 7649, 7803, 7958, 8115, 8274, 8434, 8597, 8761,
+ 8926, 9093, 9262, 9432, 9604, 9778, 9952, 10129, 10306, 10485,
+ 10665, 10847, 11030, 11214, 11399, 11586, 11773, 11962, 12152, 12342,
+ 12534, 12727, 12920, 13115, 13310, 13506, 13703, 13901, 14099, 14298,
+ 14497, 14698, 14898, 15100, 15301, 15504, 15706, 15909, 16112, 16316,
+ 16520, 16724, 16928, 17132, 17337, 17541, 17746, 17950, 18155, 18359,
+ 18564, 18768, 18972, 19175, 19379, 19582, 19785, 19987, 20189, 20390,
+ 20591, 20792, 20992, 21191, 21390, 21588, 21785, 21981, 22177, 22372,
+ 22566, 22759, 22951, 23143, 23333, 23522, 23710, 23897, 24083, 24268,
+ 24451, 24633, 24814, 24994, 25172, 25349, 25525, 25699, 25871, 26042,
+ 26212, 26380, 26546, 26711, 26874, 27035, 27195, 27353, 27509, 27664,
+ 27816, 27967, 28115, 28262, 28407, 28550, 28691, 28830, 28967, 29102,
+ 29234, 29365, 29493, 29619, 29743, 29865, 29985, 30102, 30217, 30330,
+ 30440, 30548, 30654, 30757, 30858, 30956, 31052, 31146, 31237, 31326,
+ 31412, 31495, 31576, 31655, 31730, 31804, 31874, 31942, 32008, 32071,
+ 32131, 32188, 32243, 32295, 32345, 32392, 32436, 32477, 32516, 32552,
+ 32585, 32615, 32643, 32668, 32690, 32709, 32726, 32740, 32751, 32759,
+ 32765, 32767, 32767, 32097, 30112, 26895, 22576, 17333, 11380, 4962
+ };
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL FUNCTION REFERENCES
+ ; Declare functions defined elsewhere and referenced in this module
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; Define all local variables
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Function body here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Return nothing or data or data pointer
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk
new file mode 100644
index 0000000..b81306d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/Android.mk
@@ -0,0 +1,83 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ src/a_refl.cpp \
+ src/agc.cpp \
+ src/amrdecode.cpp \
+ src/b_cn_cod.cpp \
+ src/bgnscd.cpp \
+ src/c_g_aver.cpp \
+ src/d1035pf.cpp \
+ src/d2_11pf.cpp \
+ src/d2_9pf.cpp \
+ src/d3_14pf.cpp \
+ src/d4_17pf.cpp \
+ src/d8_31pf.cpp \
+ src/d_gain_c.cpp \
+ src/d_gain_p.cpp \
+ src/d_plsf.cpp \
+ src/d_plsf_3.cpp \
+ src/d_plsf_5.cpp \
+ src/dec_amr.cpp \
+ src/dec_gain.cpp \
+ src/dec_input_format_tab.cpp \
+ src/dec_lag3.cpp \
+ src/dec_lag6.cpp \
+ src/dtx_dec.cpp \
+ src/ec_gains.cpp \
+ src/ex_ctrl.cpp \
+ src/if2_to_ets.cpp \
+ src/int_lsf.cpp \
+ src/lsp_avg.cpp \
+ src/ph_disp.cpp \
+ src/post_pro.cpp \
+ src/preemph.cpp \
+ src/pstfilt.cpp \
+ src/qgain475_tab.cpp \
+ src/sp_dec.cpp \
+ src/wmf_to_ets.cpp
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/include \
+ $(LOCAL_PATH)/../common/include \
+ $(LOCAL_PATH)/../common
+
+LOCAL_CFLAGS := \
+ -DOSCL_UNUSED_ARG= -DOSCL_IMPORT_REF=
+
+LOCAL_MODULE := libstagefright_amrnbdec
+
+include $(BUILD_STATIC_LIBRARY)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ SoftAMR.cpp
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+ frameworks/base/media/libstagefright/codecs/amrwb/src \
+ frameworks/native/include/media/openmax \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/include \
+ $(LOCAL_PATH)/../common/include \
+ $(LOCAL_PATH)/../common
+
+LOCAL_CFLAGS := -DOSCL_IMPORT_REF=
+
+LOCAL_STATIC_LIBRARIES := \
+ libstagefright_amrnbdec libstagefright_amrwbdec
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright_omx libstagefright_foundation libutils \
+ libstagefright_amrnb_common
+
+LOCAL_MODULE := libstagefright_soft_amrdec
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
new file mode 100644
index 0000000..796caa4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SoftAMR"
+#include <utils/Log.h>
+
+#include "SoftAMR.h"
+
+#include "gsmamr_dec.h"
+#include "pvamrwbdecoder.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+SoftAMR::SoftAMR(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SimpleSoftOMXComponent(name, callbacks, appData, component),
+ mMode(MODE_NARROW),
+ mState(NULL),
+ mDecoderBuf(NULL),
+ mDecoderCookie(NULL),
+ mInputBufferCount(0),
+ mAnchorTimeUs(0),
+ mNumSamplesOutput(0),
+ mSignalledError(false),
+ mOutputPortSettingsChange(NONE) {
+ if (!strcmp(name, "OMX.google.amrwb.decoder")) {
+ mMode = MODE_WIDE;
+ } else {
+ CHECK(!strcmp(name, "OMX.google.amrnb.decoder"));
+ }
+
+ initPorts();
+ CHECK_EQ(initDecoder(), (status_t)OK);
+}
+
+SoftAMR::~SoftAMR() {
+ if (mMode == MODE_NARROW) {
+ GSMDecodeFrameExit(&mState);
+ mState = NULL;
+ } else {
+ free(mDecoderBuf);
+ mDecoderBuf = NULL;
+
+ mState = NULL;
+ mDecoderCookie = NULL;
+ }
+}
+
+void SoftAMR::initPorts() {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+
+ def.nPortIndex = 0;
+ def.eDir = OMX_DirInput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 8192;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 1;
+
+ def.format.audio.cMIMEType =
+ mMode == MODE_NARROW
+ ? const_cast<char *>("audio/amr")
+ : const_cast<char *>("audio/amrwb");
+
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingAMR;
+
+ addPort(def);
+
+ def.nPortIndex = 1;
+ def.eDir = OMX_DirOutput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+
+ def.nBufferSize =
+ (mMode == MODE_NARROW ? kNumSamplesPerFrameNB : kNumSamplesPerFrameWB)
+ * sizeof(int16_t);
+
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 2;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ addPort(def);
+}
+
+status_t SoftAMR::initDecoder() {
+ if (mMode == MODE_NARROW) {
+ Word16 err = GSMInitDecode(&mState, (Word8 *)"AMRNBDecoder");
+
+ if (err != 0) {
+ return UNKNOWN_ERROR;
+ }
+ } else {
+ int32_t memReq = pvDecoder_AmrWbMemRequirements();
+ mDecoderBuf = malloc(memReq);
+
+ pvDecoder_AmrWb_Init(&mState, mDecoderBuf, &mDecoderCookie);
+ }
+
+ return OK;
+}
+
+OMX_ERRORTYPE SoftAMR::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamAudioAmr:
+ {
+ OMX_AUDIO_PARAM_AMRTYPE *amrParams =
+ (OMX_AUDIO_PARAM_AMRTYPE *)params;
+
+ if (amrParams->nPortIndex != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ amrParams->nChannels = 1;
+ amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
+ amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatConformance;
+
+ if (!isConfigured()) {
+ amrParams->nBitRate = 0;
+ amrParams->eAMRBandMode = OMX_AUDIO_AMRBandModeUnused;
+ } else {
+ amrParams->nBitRate = 0;
+ amrParams->eAMRBandMode =
+ mMode == MODE_NARROW
+ ? OMX_AUDIO_AMRBandModeNB0 : OMX_AUDIO_AMRBandModeWB0;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPcm:
+ {
+ OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ pcmParams->nChannels = 1;
+ pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eEndian = OMX_EndianBig;
+ pcmParams->bInterleaved = OMX_TRUE;
+ pcmParams->nBitPerSample = 16;
+
+ pcmParams->nSamplingRate =
+ (mMode == MODE_NARROW) ? kSampleRateNB : kSampleRateWB;
+
+ pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
+ pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+ pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftAMR::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamStandardComponentRole:
+ {
+ const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+ (const OMX_PARAM_COMPONENTROLETYPE *)params;
+
+ if (mMode == MODE_NARROW) {
+ if (strncmp((const char *)roleParams->cRole,
+ "audio_decoder.amrnb",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+ } else {
+ if (strncmp((const char *)roleParams->cRole,
+ "audio_decoder.amrwb",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioAmr:
+ {
+ const OMX_AUDIO_PARAM_AMRTYPE *aacParams =
+ (const OMX_AUDIO_PARAM_AMRTYPE *)params;
+
+ if (aacParams->nPortIndex != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPcm:
+ {
+ const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ }
+}
+
+bool SoftAMR::isConfigured() const {
+ return mInputBufferCount > 0;
+}
+
+static size_t getFrameSize(unsigned FT) {
+ static const size_t kFrameSizeWB[9] = {
+ 132, 177, 253, 285, 317, 365, 397, 461, 477
+ };
+
+ size_t frameSize = kFrameSizeWB[FT];
+
+ // Round up bits to bytes and add 1 for the header byte.
+ frameSize = (frameSize + 7) / 8 + 1;
+
+ return frameSize;
+}
+
+void SoftAMR::onQueueFilled(OMX_U32 portIndex) {
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+
+ if (mSignalledError || mOutputPortSettingsChange != NONE) {
+ return;
+ }
+
+ while (!inQueue.empty() && !outQueue.empty()) {
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+
+ outHeader->nFilledLen = 0;
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+
+ outQueue.erase(outQueue.begin());
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+ return;
+ }
+
+ if (inHeader->nOffset == 0) {
+ mAnchorTimeUs = inHeader->nTimeStamp;
+ mNumSamplesOutput = 0;
+ }
+
+ const uint8_t *inputPtr = inHeader->pBuffer + inHeader->nOffset;
+ int32_t numBytesRead;
+
+ if (mMode == MODE_NARROW) {
+ numBytesRead =
+ AMRDecode(mState,
+ (Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f),
+ (UWord8 *)&inputPtr[1],
+ reinterpret_cast<int16_t *>(outHeader->pBuffer),
+ MIME_IETF);
+
+ if (numBytesRead == -1) {
+ ALOGE("PV AMR decoder AMRDecode() call failed");
+
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+
+ return;
+ }
+
+ ++numBytesRead; // Include the frame type header byte.
+
+ if (static_cast<size_t>(numBytesRead) > inHeader->nFilledLen) {
+ // This is bad, should never have happened, but did. Abort now.
+
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+
+ return;
+ }
+ } else {
+ int16 mode = ((inputPtr[0] >> 3) & 0x0f);
+ size_t frameSize = getFrameSize(mode);
+ CHECK_GE(inHeader->nFilledLen, frameSize);
+
+ int16 frameType;
+ RX_State_wb rx_state;
+ mime_unsorting(
+ const_cast<uint8_t *>(&inputPtr[1]),
+ mInputSampleBuffer,
+ &frameType, &mode, 1, &rx_state);
+
+ int16_t *outPtr = (int16_t *)outHeader->pBuffer;
+
+ int16_t numSamplesOutput;
+ pvDecoder_AmrWb(
+ mode, mInputSampleBuffer,
+ outPtr,
+ &numSamplesOutput,
+ mDecoderBuf, frameType, mDecoderCookie);
+
+ CHECK_EQ((int)numSamplesOutput, (int)kNumSamplesPerFrameWB);
+
+ for (int i = 0; i < kNumSamplesPerFrameWB; ++i) {
+ /* Delete the 2 LSBs (14-bit output) */
+ outPtr[i] &= 0xfffC;
+ }
+
+ numBytesRead = frameSize;
+ }
+
+ inHeader->nOffset += numBytesRead;
+ inHeader->nFilledLen -= numBytesRead;
+
+ outHeader->nFlags = 0;
+ outHeader->nOffset = 0;
+
+ if (mMode == MODE_NARROW) {
+ outHeader->nFilledLen = kNumSamplesPerFrameNB * sizeof(int16_t);
+
+ outHeader->nTimeStamp =
+ mAnchorTimeUs
+ + (mNumSamplesOutput * 1000000ll) / kSampleRateNB;
+
+ mNumSamplesOutput += kNumSamplesPerFrameNB;
+ } else {
+ outHeader->nFilledLen = kNumSamplesPerFrameWB * sizeof(int16_t);
+
+ outHeader->nTimeStamp =
+ mAnchorTimeUs
+ + (mNumSamplesOutput * 1000000ll) / kSampleRateWB;
+
+ mNumSamplesOutput += kNumSamplesPerFrameWB;
+ }
+
+ if (inHeader->nFilledLen == 0) {
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+ }
+
+ outInfo->mOwnedByUs = false;
+ outQueue.erase(outQueue.begin());
+ outInfo = NULL;
+ notifyFillBufferDone(outHeader);
+ outHeader = NULL;
+
+ ++mInputBufferCount;
+ }
+}
+
+void SoftAMR::onPortFlushCompleted(OMX_U32 portIndex) {
+}
+
+void SoftAMR::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
+ if (portIndex != 1) {
+ return;
+ }
+
+ switch (mOutputPortSettingsChange) {
+ case NONE:
+ break;
+
+ case AWAITING_DISABLED:
+ {
+ CHECK(!enabled);
+ mOutputPortSettingsChange = AWAITING_ENABLED;
+ break;
+ }
+
+ default:
+ {
+ CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
+ CHECK(enabled);
+ mOutputPortSettingsChange = NONE;
+ break;
+ }
+ }
+}
+
+} // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+ const char *name, const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+ return new android::SoftAMR(name, callbacks, appData, component);
+}
+
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.h b/media/libstagefright/codecs/amrnb/dec/SoftAMR.h
new file mode 100644
index 0000000..9a596e5
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SOFT_AMR_H_
+
+#define SOFT_AMR_H_
+
+#include "SimpleSoftOMXComponent.h"
+
+namespace android {
+
+struct SoftAMR : public SimpleSoftOMXComponent {
+ SoftAMR(const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ virtual ~SoftAMR();
+
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual void onQueueFilled(OMX_U32 portIndex);
+ virtual void onPortFlushCompleted(OMX_U32 portIndex);
+ virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled);
+
+private:
+ enum {
+ kNumBuffers = 4,
+ kSampleRateNB = 8000,
+ kSampleRateWB = 16000,
+ kNumSamplesPerFrameNB = 160,
+ kNumSamplesPerFrameWB = 320,
+ };
+
+ enum {
+ MODE_NARROW,
+ MODE_WIDE
+
+ } mMode;
+
+ void *mState;
+ void *mDecoderBuf;
+ int16_t *mDecoderCookie;
+
+ size_t mInputBufferCount;
+ int64_t mAnchorTimeUs;
+ int64_t mNumSamplesOutput;
+
+ bool mSignalledError;
+
+ enum {
+ NONE,
+ AWAITING_DISABLED,
+ AWAITING_ENABLED
+ } mOutputPortSettingsChange;
+
+ int16_t mInputSampleBuffer[477];
+
+ void initPorts();
+ status_t initDecoder();
+ bool isConfigured() const;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftAMR);
+};
+
+} // namespace android
+
+#endif // SOFT_AMR_H_
+
diff --git a/media/libstagefright/codecs/amrnb/dec/include/pvamrnbdecoder_api.h b/media/libstagefright/codecs/amrnb/dec/include/pvamrnbdecoder_api.h
new file mode 100644
index 0000000..7b94320
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/include/pvamrnbdecoder_api.h
@@ -0,0 +1,122 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ Name: pvamrnbdecoder_api.h
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Main header file for the Packet Video AMR Narrow Band decoder library. The
+ constants, structures, and functions defined within this file, along with
+ a basic data types header file, is all that is needed to use and communicate
+ with the library. The internal data structures within the library are
+ purposely hidden.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef _PVAMRNBDECODER_API_H
+#define _PVAMRNBDECODER_API_H
+
+#include "pvgsmamrdecoderinterface.h"
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define MAX_NUM_FRAMES_PER_PACKET 20 /* Max number of frames per packet */
+
+#define MAX_NUM_PACKED_INPUT_BYTES 32 /* Max number of packed input bytes */
+
+#define L_FRAME 160
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* PVMP4AUDIODECODER_API_H */
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp b/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
new file mode 100644
index 0000000..fb7cff3
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
@@ -0,0 +1,313 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm-amr/c/src/a_refl.c
+ Functions: a_refl
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Removing unneeded include files and the goto statement.
+
+
+ Description: Changed function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Using inline functions from basic_op.h .
+ Removing unneeded include files.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "a_refl.h"
+#include "typedef.h"
+#include "cnst.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS [optional]
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES [optional]
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: AMREncode
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ a[] = pointer to directform coefficients of type Word16
+ refl[] = pointer to reflection coefficients of type Word16
+
+ Outputs:
+ pOverflow = 1 if overflow exists in the math operations else zero.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ File : a_refl.c
+ Purpose : Convert from direct form coefficients to
+ reflection coefficients
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] a_refl.c , 3GPP TS 26.101 version 4.1.0 Release 4, June 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+void A_Refl(
+ Word16 a[], // i : Directform coefficients
+ Word16 refl[] // o : Reflection coefficients
+)
+{
+ // local variables
+ Word16 i,j;
+ Word16 aState[M];
+ Word16 bState[M];
+ Word16 normShift;
+ Word16 normProd;
+ Word32 L_acc;
+ Word16 scale;
+ Word32 L_temp;
+ Word16 temp;
+ Word16 mult;
+
+ // initialize states
+ for (i = 0; i < M; i++)
+ {
+ aState[i] = a[i];
+ }
+
+ // backward Levinson recursion
+ for (i = M-1; i >= 0; i--)
+ {
+ if (sub(abs_s(aState[i]), 4096) >= 0)
+ {
+ goto ExitRefl;
+ }
+
+ refl[i] = shl(aState[i], 3);
+
+ L_temp = L_mult(refl[i], refl[i]);
+ L_acc = L_sub(MAX_32, L_temp);
+
+ normShift = norm_l(L_acc);
+ scale = sub(15, normShift);
+
+ L_acc = L_shl(L_acc, normShift);
+ normProd = pv_round(L_acc);
+
+ mult = div_s(16384, normProd);
+
+ for (j = 0; j < i; j++)
+ {
+ L_acc = L_deposit_h(aState[j]);
+ L_acc = L_msu(L_acc, refl[i], aState[i-j-1]);
+
+ temp = pv_round(L_acc);
+ L_temp = L_mult(mult, temp);
+ L_temp = L_shr_r(L_temp, scale);
+
+ if (L_sub(L_abs(L_temp), 32767) > 0)
+ {
+ goto ExitRefl;
+ }
+
+ bState[j] = extract_l(L_temp);
+ }
+
+ for (j = 0; j < i; j++)
+ {
+ aState[j] = bState[j];
+ }
+ }
+ return;
+
+ExitRefl:
+ for (i = 0; i < M; i++)
+ {
+ refl[i] = 0;
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void A_Refl(
+ Word16 a[], /* i : Directform coefficients */
+ Word16 refl[], /* o : Reflection coefficients */
+ Flag *pOverflow
+)
+{
+ /* local variables */
+ Word16 i;
+ Word16 j;
+ Word16 aState[M];
+ Word16 bState[M];
+ Word16 normShift;
+ Word16 normProd;
+ Word32 L_acc;
+ Word16 scale;
+ Word32 L_temp;
+ Word16 temp;
+ Word16 mult;
+
+ /* initialize states */
+ for (i = 0; i < M; i++)
+ {
+ aState[i] = a[i];
+ }
+
+ /* backward Levinson recursion */
+ for (i = M - 1; i >= 0; i--)
+ {
+ if (abs_s(aState[i]) >= 4096)
+ {
+ for (i = 0; i < M; i++)
+ {
+ refl[i] = 0;
+ }
+ break;
+ }
+
+ refl[i] = shl(aState[i], 3, pOverflow);
+
+ L_temp = L_mult(refl[i], refl[i], pOverflow);
+ L_acc = L_sub(MAX_32, L_temp, pOverflow);
+
+ normShift = norm_l(L_acc);
+ scale = sub(15, normShift, pOverflow);
+
+ L_acc = L_shl(L_acc, normShift, pOverflow);
+ normProd = pv_round(L_acc, pOverflow);
+
+ mult = div_s(16384, normProd);
+
+ for (j = 0; j < i; j++)
+ {
+ L_acc = L_deposit_h(aState[j]);
+ L_acc = L_msu(L_acc, refl[i], aState[i-j-1], pOverflow);
+
+ temp = pv_round(L_acc, pOverflow);
+ L_temp = L_mult(mult, temp, pOverflow);
+ L_temp = L_shr_r(L_temp, scale, pOverflow);
+
+ if (L_abs(L_temp) > 32767)
+ {
+ for (i = 0; i < M; i++)
+ {
+ refl[i] = 0;
+ }
+ break;
+ }
+
+ bState[j] = extract_l(L_temp);
+ }
+
+ for (j = 0; j < i; j++)
+ {
+ aState[j] = bState[j];
+ }
+ }
+ return;
+}
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/a_refl.h b/media/libstagefright/codecs/amrnb/dec/src/a_refl.h
new file mode 100644
index 0000000..4028e1e
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/a_refl.h
@@ -0,0 +1,124 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/a_refl.h
+
+ Date: 08/11/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : a_refl.h
+ Purpose : Convert from direct form coefficients to
+ reflection coefficients
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef A_REFL_H
+#define A_REFL_H
+#define a_refl_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ /*
+ * FUNCTION: A_Refl()
+ * PURPOSE: Convert from direct form coefficients to reflection coefficients
+ * DESCRIPTION:
+ * Directform coeffs in Q12 are converted to
+ * reflection coefficients Q15
+ */
+ void A_Refl(
+ Word16 a[], /* i : Directform coefficients */
+ Word16 refl[], /* o : Reflection coefficients */
+ Flag *pOverflow
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _A_REFL_H_ */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/agc.cpp b/media/libstagefright/codecs/amrnb/dec/src/agc.cpp
new file mode 100644
index 0000000..4c66d54
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/agc.cpp
@@ -0,0 +1,1066 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/agc.c
+ Funtions: energy_old
+ energy_new
+ agc_init
+ agc_reset
+ agc_exit
+ agc
+ agc2
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This set of modules scale the excitation level and output of the speech
+ signals.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "agc.h"
+#include "cnst.h"
+#include "inv_sqrt.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: energy_old
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ in = input signal (Word16)
+ l_trm = input signal length (Word16)
+ pOverflow = address of overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the energy computation saturates
+
+ Returns:
+ s = return energy of signal (Word32)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Returns the energy of the signal.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+static Word32 energy_old( // o : return energy of signal
+ Word16 in[], // i : input signal (length l_trm)
+ Word16 l_trm // i : signal length
+)
+{
+ Word32 s;
+ Word16 i, temp;
+
+ temp = shr (in[0], 2);
+ s = L_mult (temp, temp);
+
+ for (i = 1; i < l_trm; i++)
+ {
+ temp = shr (in[i], 2);
+ s = L_mac (s, temp, temp);
+ }
+
+ return s;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static Word32 energy_old( /* o : return energy of signal */
+ Word16 in[], /* i : input signal (length l_trm) */
+ Word16 l_trm, /* i : signal length */
+ Flag *pOverflow /* overflow: flag to indicate overflow */
+)
+
+{
+ Word32 s = 0;
+ Word16 i;
+ Word16 temp;
+
+ for (i = 0; i < l_trm; i++)
+ {
+ temp = in[i] >> 2;
+ s = L_mac(s, temp, temp, pOverflow);
+ }
+
+ return(s);
+}
+
+/*----------------------------------------------------------------------------*/
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: energy_old__Wrapper
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ in = input signal (Word16)
+ l_trm = input signal length (Word16)
+ pOverflow = address of overflow (Flag)
+ Outputs:
+ pOverflow -> 1 if the energy computation saturates
+
+ Returns:
+ s = return energy of signal (Word32)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function provides external access to the static function energy_old.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ CALL energy_old ( in = in
+ l_trm = l_trm
+ pOverflow = pOverflow )
+ MODIFYING(nothing)
+ RETURNING(energy_old_value = s)
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word32 energy_old_Wrapper(Word16 in[], Word16 l_trm, Flag *pOverflow)
+{
+ Word32 energy_old_value;
+
+ /*----------------------------------------------------------------------------
+ CALL energy_old ( in = in
+ l_trm = l_trm
+ pOverflow = pOverflow )
+
+ MODIFYING(nothing)
+ RETURNING(energy_old_value = s)
+ ----------------------------------------------------------------------------*/
+ energy_old_value = energy_old(in, l_trm, pOverflow);
+ return(energy_old_value);
+}
+/*--------------------------------------------------------------------------*/
+
+/*
+-----------------------------------------------------------------------------
+ FUNCTION NAME: energy_new
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ in = input signal
+ l_trm = input signal length
+ pOverflow = address of overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the energy computation saturates
+
+ Returns:
+ s = return energy of signal
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Returns the energy of the signal.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+static Word32 energy_new( // o : return energy of signal
+ Word16 in[], // i : input signal (length l_trm)
+ Word16 l_trm ) // i : signal length
+
+{
+ Word32 s;
+ Word16 i;
+ Flag ov_save;
+
+ ov_save = Overflow; //save overflow flag in case energy_old
+ // must be called
+ s = L_mult(in[0], in[0]);
+ for (i = 1; i < l_trm; i++)
+ {
+ s = L_mac(s, in[i], in[i]);
+ }
+
+ // check for overflow
+ if (L_sub (s, MAX_32) == 0L)
+ {
+ Overflow = ov_save; // restore overflow flag
+ s = energy_old (in, l_trm); // function result
+ }
+ else
+ {
+ s = L_shr(s, 4);
+ }
+
+ return(s);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static Word32 energy_new( /* o : return energy of signal */
+ Word16 in[], /* i : input signal (length l_trm) */
+ Word16 l_trm, /* i : signal length */
+ Flag *pOverflow /* i : overflow flag */
+)
+
+{
+ Word32 s = 0;
+ Word16 i;
+ Flag ov_save;
+
+ ov_save = *(pOverflow); /* save overflow flag in case energy_old */
+ /* must be called */
+
+
+ for (i = 0; i < l_trm; i++)
+ {
+ s = L_mac(s, in[i], in[i], pOverflow);
+ }
+
+ /* check for overflow */
+ if (s != MAX_32)
+ {
+ /* s is a sum of squares, so it won't be negative */
+ s = s >> 4;
+ }
+ else
+ {
+ *(pOverflow) = ov_save; /* restore overflow flag */
+ s = energy_old(in, l_trm, pOverflow); /* function result */
+ }
+
+ return (s);
+}
+
+/*--------------------------------------------------------------------------*/
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: energy_new__Wrapper
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ in = input signal (Word16)
+ l_trm = input signal length (Word16)
+ overflow = address of overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the energy computation saturates
+
+ Returns:
+ s = return energy of signal (Word32)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function provides external access to the static function energy_new.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ CALL energy_new ( in = in
+ l_trm = l_trm
+ pOverflow = pOverflow )
+
+ MODIFYING(nothing)
+
+ RETURNING(energy_new_value = s)
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word32 energy_new_Wrapper(Word16 in[], Word16 l_trm, Flag *pOverflow)
+{
+ Word32 energy_new_value;
+
+ /*----------------------------------------------------------------------------
+ CALL energy_new ( in = in
+ l_trm = l_trm
+ pOverflow = pOverflow )
+
+ MODIFYING(nothing)
+ RETURNING(energy_new_value = s)
+
+ ----------------------------------------------------------------------------*/
+ energy_new_value = energy_new(in, l_trm, pOverflow);
+
+ return(energy_new_value);
+
+}
+
+/*--------------------------------------------------------------------------*/
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: agc_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a structure of type agcState
+
+ Outputs:
+ Structure pointed to by state is initialized to zeros
+
+ Returns:
+ Returns 0 if memory was successfully initialized,
+ otherwise returns -1.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Reset of agc (i.e. set state memory to 1.0).
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int agc_reset (agcState *state)
+{
+ if (state == (agcState *) NULL)
+ {
+ fprintf(stderr, "agc_reset: invalid parameter\n");
+ return -1;
+ }
+
+ state->past_gain = 4096; // initial value of past_gain = 1.0
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 agc_reset(agcState *state)
+{
+ if (state == (agcState *) NULL)
+ {
+ /* fprintf(stderr, "agc_reset: invalid parameter\n"); */
+ return(-1);
+ }
+
+ state->past_gain = 4096; /* initial value of past_gain = 1.0 */
+
+ return(0);
+}
+
+/*--------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: agc
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to agc state
+ sig_in = pointer to a buffer containing the postfilter input signal
+ sig_out = pointer to a buffer containing the postfilter output signal
+ agc_fac = AGC factor
+ l_trm = subframe size
+ pOverflow = pointer to the overflow flag
+
+ Outputs:
+ st->past_gain = gain
+ buffer pointed to by sig_out contains the new postfilter output signal
+ pOverflow -> 1 if the agc computation saturates
+
+ Returns:
+ return = 0
+
+ Global Variables Used:
+ none.
+
+ Local Variables Needed:
+ none.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Scales the postfilter output on a subframe basis using:
+
+ sig_out[n] = sig_out[n] * gain[n]
+ gain[n] = agc_fac * gain[n-1] + (1 - agc_fac) g_in/g_out
+
+ where: gain[n] = gain at the nth sample given by
+ g_in/g_out = square root of the ratio of energy at
+ the input and output of the postfilter.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int agc (
+ agcState *st, // i/o : agc state
+ Word16 *sig_in, // i : postfilter input signal (l_trm)
+ Word16 *sig_out, // i/o : postfilter output signal (l_trm)
+ Word16 agc_fac, // i : AGC factor
+ Word16 l_trm // i : subframe size
+)
+{
+ Word16 i, exp;
+ Word16 gain_in, gain_out, g0, gain;
+ Word32 s;
+
+ // calculate gain_out with exponent
+ s = energy_new(sig_out, l_trm); // function result
+
+ if (s == 0)
+ {
+ st->past_gain = 0;
+ return 0;
+ }
+ exp = sub (norm_l (s), 1);
+ gain_out = pv_round (L_shl (s, exp));
+
+ // calculate gain_in with exponent
+ s = energy_new(sig_in, l_trm); // function result
+
+ if (s == 0)
+ {
+ g0 = 0;
+ }
+ else
+ {
+ i = norm_l (s);
+ gain_in = pv_round (L_shl (s, i));
+ exp = sub (exp, i);
+
+ *---------------------------------------------------*
+ * g0 = (1-agc_fac) * sqrt(gain_in/gain_out); *
+ *---------------------------------------------------*
+
+ s = L_deposit_l (div_s (gain_out, gain_in));
+ s = L_shl (s, 7); // s = gain_out / gain_in
+ s = L_shr (s, exp); // add exponent
+
+ s = Inv_sqrt (s); // function result
+ i = pv_round (L_shl (s, 9));
+
+ // g0 = i * (1-agc_fac)
+ g0 = mult (i, sub (32767, agc_fac));
+ }
+
+ // compute gain[n] = agc_fac * gain[n-1]
+ + (1-agc_fac) * sqrt(gain_in/gain_out)
+ // sig_out[n] = gain[n] * sig_out[n]
+
+ gain = st->past_gain;
+
+ for (i = 0; i < l_trm; i++)
+ {
+ gain = mult (gain, agc_fac);
+ gain = add (gain, g0);
+ sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], gain), 3));
+ }
+
+ st->past_gain = gain;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void agc(
+ agcState *st, /* i/o : agc state */
+ Word16 *sig_in, /* i : postfilter input signal (l_trm) */
+ Word16 *sig_out, /* i/o : postfilter output signal (l_trm) */
+ Word16 agc_fac, /* i : AGC factor */
+ Word16 l_trm, /* i : subframe size */
+ Flag *pOverflow /* i : overflow Flag */
+
+)
+
+{
+ Word16 i;
+ Word16 exp;
+ Word16 gain_in;
+ Word16 gain_out;
+ Word16 g0;
+ Word16 gain;
+ Word32 s;
+ Word32 L_temp;
+ Word16 temp;
+
+ Word16 *p_sig_out;
+
+ /* calculate gain_out with exponent */
+ s = energy_new(sig_out, l_trm, pOverflow); /* function result */
+
+ if (s == 0)
+ {
+ st->past_gain = 0;
+ return;
+ }
+ exp = norm_l(s) - 1;
+
+ L_temp = L_shl(s, exp, pOverflow);
+ gain_out = pv_round(L_temp, pOverflow);
+
+ /* calculate gain_in with exponent */
+ s = energy_new(sig_in, l_trm, pOverflow); /* function result */
+
+ if (s == 0)
+ {
+ g0 = 0;
+ }
+ else
+ {
+ i = norm_l(s);
+
+ /* L_temp = L_shl(s, i, pOverflow); */
+ L_temp = s << i;
+
+ gain_in = pv_round(L_temp, pOverflow);
+
+ exp -= i;
+
+ /*---------------------------------------------------*
+ * g0 = (1-agc_fac) * sqrt(gain_in/gain_out); *
+ *---------------------------------------------------*/
+
+ /* s = gain_out / gain_in */
+ temp = div_s(gain_out, gain_in);
+
+ /* s = L_deposit_l (temp); */
+ s = (Word32) temp;
+ s = s << 7;
+ s = L_shr(s, exp, pOverflow); /* add exponent */
+
+ s = Inv_sqrt(s, pOverflow); /* function result */
+ L_temp = s << 9;
+
+ i = (Word16)((L_temp + (Word32) 0x00008000L) >> 16);
+
+ /* g0 = i * (1-agc_fac) */
+ temp = 32767 - agc_fac;
+
+ g0 = (Word16)(((Word32) i * temp) >> 15);
+
+ }
+
+ /* compute gain[n] = agc_fac * gain[n-1]
+ + (1-agc_fac) * sqrt(gain_in/gain_out) */
+ /* sig_out[n] = gain[n] * sig_out[n] */
+
+ gain = st->past_gain;
+ p_sig_out = sig_out;
+
+ for (i = 0; i < l_trm; i++)
+ {
+ /* gain = mult (gain, agc_fac, pOverflow); */
+ gain = (Word16)(((Word32) gain * agc_fac) >> 15);
+
+ /* gain = add (gain, g0, pOverflow); */
+ gain += g0;
+
+ /* L_temp = L_mult (sig_out[i], gain, pOverflow); */
+ L_temp = ((Word32)(*(p_sig_out)) * gain) << 1;
+
+ *(p_sig_out++) = (Word16)(L_temp >> 13);
+ }
+
+ st->past_gain = gain;
+
+ return;
+}
+
+/*--------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: agc2
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ sig_in = pointer to a buffer containing the postfilter input signal
+ sig_out = pointer to a buffer containing the postfilter output signal
+ l_trm = subframe size
+ pOverflow = pointer to overflow flag
+
+ Outputs:
+ sig_out points to a buffer containing the new scaled output signal.
+ pOverflow -> 1 if the agc computation saturates
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Scales the excitation on a subframe basis.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void agc2 (
+ Word16 *sig_in, // i : postfilter input signal
+ Word16 *sig_out, // i/o : postfilter output signal
+ Word16 l_trm // i : subframe size
+)
+{
+ Word16 i, exp;
+ Word16 gain_in, gain_out, g0;
+ Word32 s;
+
+ // calculate gain_out with exponent
+ s = energy_new(sig_out, l_trm); // function result
+
+ if (s == 0)
+ {
+ return;
+ }
+ exp = sub (norm_l (s), 1);
+ gain_out = pv_round (L_shl (s, exp));
+
+ // calculate gain_in with exponent
+ s = energy_new(sig_in, l_trm); // function result
+
+ if (s == 0)
+ {
+ g0 = 0;
+ }
+ else
+ {
+ i = norm_l (s);
+ gain_in = pv_round (L_shl (s, i));
+ exp = sub (exp, i);
+
+ *---------------------------------------------------*
+ * g0 = sqrt(gain_in/gain_out); *
+ *---------------------------------------------------*
+
+ s = L_deposit_l (div_s (gain_out, gain_in));
+ s = L_shl (s, 7); // s = gain_out / gain_in
+ s = L_shr (s, exp); // add exponent
+
+ s = Inv_sqrt (s); // function result
+ g0 = pv_round (L_shl (s, 9));
+ }
+
+ // sig_out(n) = gain(n) sig_out(n)
+
+ for (i = 0; i < l_trm; i++)
+ {
+ sig_out[i] = extract_h (L_shl (L_mult (sig_out[i], g0), 3));
+ }
+
+ return;
+}
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void agc2(
+ Word16 *sig_in, /* i : postfilter input signal */
+ Word16 *sig_out, /* i/o : postfilter output signal */
+ Word16 l_trm, /* i : subframe size */
+ Flag *pOverflow /* i : overflow flag */
+)
+
+{
+ Word16 i;
+ Word16 exp;
+ Word16 gain_in;
+ Word16 gain_out;
+ Word16 g0;
+ Word32 s;
+ Word32 L_temp;
+ Word16 temp;
+
+ /* calculate gain_out with exponent */
+ s = energy_new(sig_out, l_trm, pOverflow); /* function result */
+
+ if (s == 0)
+ {
+ return;
+ }
+ exp = norm_l(s) - 1;
+ L_temp = L_shl(s, exp, pOverflow);
+ gain_out = pv_round(L_temp, pOverflow);
+
+ /* calculate gain_in with exponent */
+ s = energy_new(sig_in, l_trm, pOverflow); /* function result */
+
+ if (s == 0)
+ {
+ g0 = 0;
+ }
+ else
+ {
+ i = norm_l(s);
+ L_temp = L_shl(s, i, pOverflow);
+ gain_in = pv_round(L_temp, pOverflow);
+ exp -= i;
+
+ /*---------------------------------------------------*
+ * g0 = sqrt(gain_in/gain_out); *
+ *---------------------------------------------------*/
+
+ /* s = gain_out / gain_in */
+ temp = div_s(gain_out, gain_in);
+
+ /* s = L_deposit_l (temp); */
+ s = (Word32)temp;
+
+ if (s > (Word32) 0x00FFFFFFL)
+ {
+ s = MAX_32;
+ }
+ else if (s < (Word32) 0xFF000000L)
+ {
+ s = MIN_32;
+ }
+ else
+ {
+ s = s << 7;
+ }
+ s = L_shr(s, exp, pOverflow); /* add exponent */
+
+ s = Inv_sqrt(s, pOverflow); /* function result */
+
+ if (s > (Word32) 0x003FFFFFL)
+ {
+ L_temp = MAX_32;
+ }
+ else if (s < (Word32) 0xFFC00000L)
+ {
+ L_temp = MIN_32;
+ }
+ else
+ {
+ L_temp = s << 9;
+ }
+ g0 = pv_round(L_temp, pOverflow);
+ }
+
+ /* sig_out(n) = gain(n) sig_out(n) */
+
+ for (i = l_trm - 1; i >= 0; i--)
+ {
+ L_temp = L_mult(sig_out[i], g0, pOverflow);
+ if (L_temp > (Word32) 0x0FFFFFFFL)
+ {
+ sig_out[i] = MAX_16;
+ }
+ else if (L_temp < (Word32) 0xF0000000L)
+ {
+ sig_out[i] = MIN_16;
+ }
+ else
+ {
+ sig_out[i] = (Word16)(L_temp >> 13);
+ }
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/agc.h b/media/libstagefright/codecs/amrnb/dec/src/agc.h
new file mode 100644
index 0000000..b6e3249
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/agc.h
@@ -0,0 +1,163 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/agc.h
+
+ Date: 12/07/2001
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Removed unneeded sections of the standard template.
+ Updated function prototype for agc() and agc2() to match new
+ interface
+
+ Description: Changed paramter name from "overflow" to "pOverflow" for
+ functions agc() and agc2()
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : agc.h
+ Purpose : Scales the postfilter output on a subframe basis
+ : by automatic control of the subframe gain.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _AGC_H_
+#define _AGC_H_
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 past_gain;
+ } agcState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ /*----------------------------------------------------------------------------
+ ;
+ ; Function : agc_reset
+ ; Purpose : Reset of agc (i.e. set state memory to 1.0)
+ ; Returns : 0 on success
+ ;
+ ----------------------------------------------------------------------------*/
+ Word16 agc_reset(agcState *st);
+
+
+ /*----------------------------------------------------------------------------
+ ;
+ ; Function : agc
+ ; Purpose : Scales the postfilter output on a subframe basis
+ ; Description : sig_out[n] = sig_out[n] * gain[n];
+ ; where gain[n] is the gain at the nth sample given by
+ ; gain[n] = agc_fac * gain[n-1] + (1 - agc_fac) g_in/g_out
+ ; g_in/g_out is the square root of the ratio of energy at
+ ; the input and output of the postfilter.
+ ;
+ ----------------------------------------------------------------------------*/
+ void agc(
+ agcState *st, /* i/o : agc state */
+ Word16 *sig_in, /* i : postfilter input signal, (l_trm) */
+ Word16 *sig_out, /* i/o : postfilter output signal, (l_trm) */
+ Word16 agc_fac, /* i : AGC factor */
+ Word16 l_trm, /* i : subframe size */
+ Flag *pOverflow /* i : overflow flag */
+ );
+
+ /*----------------------------------------------------------------------------
+ ;
+ ; Function: agc2
+ ; Purpose: Scales the excitation on a subframe basis
+ ;
+ ----------------------------------------------------------------------------*/
+ void agc2(
+ Word16 *sig_in, /* i : postfilter input signal */
+ Word16 *sig_out, /* i/o : postfilter output signal */
+ Word16 l_trm, /* i : subframe size */
+ Flag *pOverflow /* i : overflow flag */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AGC_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/amrdecode.cpp b/media/libstagefright/codecs/amrnb/dec/src/amrdecode.cpp
new file mode 100644
index 0000000..873d7af
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/amrdecode.cpp
@@ -0,0 +1,544 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+ Pathname: ./audio/gsm-amr/c/src/amrdecode.c
+
+ Date: 05/23/2001
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: AMRDecode now doesn't call getbits() or put_header_in().
+ It also now obtains a new bit_offset value from a constant
+ rather than from the returned value of getbits().
+
+ Description: AMRDecode now returns byte_offset rather than bit_offset,
+ so the program can access the next frame that is byte
+ aligned rather than packed without padding.
+
+ Description: The structure types Speech_Decode_FrameState are now
+ passed into amrdecode( ) using void pointers, so that
+ higher level functions don't need to know anything about
+ this structure type.
+
+ Description: Changed input argument list. Added code to handle incoming DTX
+ frames, and added call to wmf_to_ets function prior to calling
+ GSMFrameDecode.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Changed all references to bit_offset to byte_offset.
+
+ Description: Added input_type to the function interface and modified code
+ to check type of conversion that needs to be made.
+
+ Description: Modified pseudo-code to include IF2 and ETS input formats.
+ Removed byte_offset from input list. Renamed speech_bits
+ to speech_bits_ptr.
+
+ Description: Added dec_input_format_tab.h in Include section. Modified
+ pseudo-code to use correct table names. Renamed input_type to
+ input_format and speech_bits to speech_bits_ptr.
+
+ Description: Removed *prev_mode_ptr in the input argument list.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Removed dec_input_format_tab.h from Include section.
+ 2. Changed type definition of raw_pcm_buffer in the I/O
+ definition section.
+
+ Description: Renamed WmfBytesPerFrame to WmfDecBytesPerFrame, and
+ If2BytesPerFrame to If2DecBytesPerFrame.
+
+ Description: Modified code so that the ETS testvectors could be fed directly
+ to this function.
+
+ Description: Changed '&' to '&&' in the setting of rx_type and mode for
+ AMR_SID < frame_type < NO_DATA case.
+
+ Description: Added code comments and made some code optimizations per Phase
+ 2/3 review comments.
+
+ Description: Added conditional compile around the call to GSMFrameDecode to
+ allow amrdecode.c to be used in the ETS reference console.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "amrdecode.h"
+#include "cnst.h"
+#include "typedef.h"
+#include "frame.h"
+#include "sp_dec.h"
+#include "wmf_to_ets.h"
+#include "if2_to_ets.h"
+#include "frame_type_3gpp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: AMRDecode
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state_data = pointer to a structure (type void)
+
+ frame_type = 3GPP frame type (enum Frame_Type_3GPP)
+
+ speech_bits_ptr = pointer to the beginning of the raw encoded speech bits
+ for the current frame to be decoded (unsigned char)
+
+ raw_pcm_buffer = pointer to the output pcm outputs array (Word16)
+
+ input_format = input format used; valid values are AMR_WMF, AMR_IF2,
+ and AMR_ETS (Word16)
+
+ Outputs:
+ raw_pcm_buffer contains the newly decoded linear PCM speech samples
+ state_data->prev_mode contains the new mode
+
+ Returns:
+ byte_offset = address offset of the next frame to be processed or
+ error condition flag (-1) (int)
+
+ Global Variables Used:
+ WmfDecBytesPerFrame = table containing the number of core AMR data bytes
+ used by each codec mode for WMF input format (const
+ int)
+
+ If2DecBytesPerFrame = table containing the number of core AMR data bytes
+ used by each codec mode for IF2 input format (const
+ int)
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function is the top level entry function to the GSM AMR Decoder library.
+
+ First, it checks the input format type (input_format) to determine the type
+ of de-formattting that needs to be done. If input_format is AMR_WMF, the input
+ data is in WMF (aka, non-IF2) format and the function wmf_to_ets will be
+ called to convert to the ETS format (1 bit/word, where 1 word = 16 bits),
+ and byte_offset will be updated according to the contents of WmfDecBytesPerFrame
+ table.
+
+ If input_format is AMR_IF2, the input data is in IF2 format [1] and the
+ function if2_to_ets will be called to convert to the ETS format, and
+ byte_offset will be updated according to the contents of If2DecBytesPerFrame
+ table.
+
+ The codec mode and receive frame type is initialized based on the incoming
+ frame_type.
+
+ If input_format is AMR_ETS, the input data is in the ETS format. The receive
+ frame type is set to the value in the first location of the buffer pointed to
+ by speech_bits_ptr. Then, the encoded speech parameters in the buffer pointed
+ to by speech_bits is copied to dec_ets_input_bfr and the type will be changed
+ from unsigned char to Word16. Lastly, if the receive frame type is not
+ RX_NO_DATA, the mode is obtained from the buffer pointed to by
+ speech_bits_ptr, offset by MAX_SERIAL_SIZE+1, otherwise, the mode is set to
+ the previous mode (found the in state_data->prev_mode).
+
+ If input_format is an unsupported format, byte_offset will be set to -1, to
+ indicate an error condition has occurred, and the function will exit.
+
+ If there are no errors, GSMFrameDecode is called to decode a 20 ms frame. It
+ puts the decoded linear PCM samples in the buffer pointed to by
+ raw_pcm_buffer. Then, the prev_mode field of the structure pointed to by
+ state_data is updated to the current mode.
+
+ This function returns the new byte_offset value to indicate the address
+ offset of the next speech frame to be decoded.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] "AMR Speech Codec Frame Structure", 3GPP TS 26.101 version 4.1.0
+ Release 4, June 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Note: AMRSID_RXTYPE_BIT_OFFSET = 35
+ AMRSID_RXMODE_BIT_OFFSET = 36
+ NUM_AMRSID_RXMODE_BITS = 3
+
+
+ // Set up Decoder state structure pointer
+ Speech_Decode_FrameState *decoder_state
+ = (Speech_Decode_FrameState *) state_data
+
+ // Determine type of de-formatting
+
+ // Decode WMF or IF2 frames
+ IF ((input_format == AMR_RX_WMF) | (input_format == AMR_RX_IF2))
+ THEN
+ IF (input_format == AMR_RX_WMF)
+ THEN
+ // Convert incoming packetized raw WMF data to ETS format
+ CALL wmf_to_ets(frame_type = frame_type
+ input_ptr = speech_bits_ptr
+ output_ptr = &dec_ets_input_bfr)
+ MODIFYING(nothing)
+ RETURNING(nothing)
+
+ // Address offset of the start of next frame
+ byte_offset = WmfDecBytesPerFrame[frame_type]
+
+ ELSEIF (input_format == AMR_RX_IF2)
+ THEN
+ // Convert incoming packetized raw IF2 data to ETS format
+ CALL if2_to_ets(frame_type = frame_type
+ input_ptr = speech_bits_ptr
+ output_ptr = &dec_ets_input_bfr)
+ MODIFYING(nothing)
+ RETURNING(nothing)
+
+ // Address offset of the start of next frame
+ byte_offset = If2DecBytesPerFrame[frame_type]
+
+ ENDIF
+
+ // Determine AMR codec mode and AMR RX frame type
+ IF (frame_type <= AMR_122)
+ THEN
+ mode = (enum Mode) frame_type;
+ rx_type = RX_SPEECH_GOOD;
+
+ ELSEIF (frame_type == AMR_SID)
+ THEN
+ // Clear mode store prior to reading mode info from input buffer
+ mode = 0
+
+ FOR i = 0 TO NUM_AMRSID_RXMODE_BITS-1
+
+ mode |= (dec_ets_input_bfr[AMRSID_RXMODE_BIT_OFFSET+i] << i)
+
+ ENDFOR
+
+ IF (dec_ets_input_bfr[AMRSID_RXTYPE_BIT_OFFSET] == 0)
+ THEN
+ rx_type = RX_SID_FIRST
+
+ ELSE
+ rx_type = RX_SID_UPDATE
+
+ ENDIF
+
+ ELSEIF ((frame_type > AMR_SID) && (frame_type < NO_DATA))
+ THEN
+ // Use previous mode
+ mode = decoder_state->prev_mode
+
+ // Unsupported SID frames
+ rx_type = RX_SPEECH_BAD;
+
+ ELSE
+ // Use previous mode
+ mode = decoder_state->prev_mode
+
+ // No data received
+ rx_type = RX_NO_DATA;
+
+ ENDIF
+
+ // Decode ETS frames
+ ELSEIF (input_format == AMR_RX_ETS)
+ THEN
+ // Change type of pointer to incoming raw ETS data
+ ets_word_ptr = (Word16 *) speech_bits_ptr
+
+ // Get RX frame type
+ rx_type = (enum RXFrameType) *ets_word_ptr
+ ets_word_ptr = ets_word_ptr + 1
+
+ // Copy incoming raw ETS data to dec_ets_input_bfr
+ FOR i = 0 TO MAX_SERIAL_SIZE-1
+
+ dec_ets_input_bfr[i] = *ets_word_ptr
+ ets_word_ptr = ets_word_ptr + 1
+
+ ENDFOR
+
+ // Get codec mode
+ IF (rx_type != RX_NO_DATA)
+ THEN
+ mode = (enum Mode) *ets_word_ptr
+
+ ELSE
+ //Use previous mode if no received data
+ mode = decoder_state->prev_mode
+
+ ENDIF
+
+ // Set up byte_offset
+ byte_offset = 2*(MAX_SERIAL_SIZE+2)
+
+ ELSE
+ // Invalid format, return error code
+ byte_offset = -1
+
+ ENDIF
+
+ // Proceed with decoding frame, if there are no errors
+ IF (byte_offset != -1)
+ THEN
+ // Decode a 20 ms frame
+ CALL GSMFrameDecode( st = decoder_state
+ mode = mode
+ serial = dec_ets_input_bfr,
+ frame_type = rx_type,
+ synth = (Word16 *)raw_pcm_buffer);
+ MODIFYING (nothing)
+ RETURNING (Nothing)
+
+ // Save mode for next frame
+ decoder_state->prev_mode = mode
+
+ ENDIF
+
+ RETURN (byte_offset)
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 AMRDecode(
+ void *state_data,
+ enum Frame_Type_3GPP frame_type,
+ UWord8 *speech_bits_ptr,
+ Word16 *raw_pcm_buffer,
+ bitstream_format input_format
+)
+{
+ Word16 *ets_word_ptr;
+ enum Mode mode = (enum Mode)MR475;
+ int modeStore;
+ int tempInt;
+ enum RXFrameType rx_type = RX_NO_DATA;
+ Word16 dec_ets_input_bfr[MAX_SERIAL_SIZE];
+ Word16 i;
+ Word16 byte_offset = -1;
+
+ /* Type cast state_data to Speech_Decode_FrameState rather than passing
+ * that structure type to this function so the structure make up can't
+ * be viewed from higher level functions than this.
+ */
+ Speech_Decode_FrameState *decoder_state
+ = (Speech_Decode_FrameState *) state_data;
+
+ /* Determine type of de-formatting */
+ /* WMF or IF2 frames */
+ if ((input_format == MIME_IETF) | (input_format == IF2))
+ {
+ if (input_format == MIME_IETF)
+ {
+ /* Convert incoming packetized raw WMF data to ETS format */
+ wmf_to_ets(frame_type, speech_bits_ptr, dec_ets_input_bfr);
+
+ /* Address offset of the start of next frame */
+ byte_offset = WmfDecBytesPerFrame[frame_type];
+ }
+ else /* else has to be input_format IF2 */
+ {
+ /* Convert incoming packetized raw IF2 data to ETS format */
+ if2_to_ets(frame_type, speech_bits_ptr, dec_ets_input_bfr);
+
+ /* Address offset of the start of next frame */
+ byte_offset = If2DecBytesPerFrame[frame_type];
+ }
+
+ /* At this point, input data is in ETS format */
+ /* Determine AMR codec mode and AMR RX frame type */
+ if (frame_type <= AMR_122)
+ {
+ mode = (enum Mode) frame_type;
+ rx_type = RX_SPEECH_GOOD;
+ }
+ else if (frame_type == AMR_SID)
+ {
+ /* Clear mode store prior to reading mode info from input buffer */
+ modeStore = 0;
+
+ for (i = 0; i < NUM_AMRSID_RXMODE_BITS; i++)
+ {
+ tempInt = dec_ets_input_bfr[AMRSID_RXMODE_BIT_OFFSET+i] << i;
+ modeStore |= tempInt;
+ }
+ mode = (enum Mode) modeStore;
+
+ /* Get RX frame type */
+ if (dec_ets_input_bfr[AMRSID_RXTYPE_BIT_OFFSET] == 0)
+ {
+ rx_type = RX_SID_FIRST;
+ }
+ else
+ {
+ rx_type = RX_SID_UPDATE;
+ }
+ }
+ else if (frame_type < AMR_NO_DATA)
+ {
+ /* Invalid frame_type, return error code */
+ byte_offset = -1; /* !!! */
+ }
+ else
+ {
+ mode = decoder_state->prev_mode;
+
+ /*
+ * RX_NO_DATA, generate exponential decay from latest valid frame for the first 6 frames
+ * after that, create silent frames
+ */
+ rx_type = RX_NO_DATA;
+
+ }
+
+ }
+
+ /* ETS frames */
+ else if (input_format == ETS)
+ {
+ /* Change type of pointer to incoming raw ETS data */
+ ets_word_ptr = (Word16 *) speech_bits_ptr;
+
+ /* Get RX frame type */
+ rx_type = (enum RXFrameType) * ets_word_ptr;
+ ets_word_ptr++;
+
+ /* Copy incoming raw ETS data to dec_ets_input_bfr */
+ for (i = 0; i < MAX_SERIAL_SIZE; i++)
+ {
+ dec_ets_input_bfr[i] = *ets_word_ptr;
+ ets_word_ptr++;
+ }
+
+ /* Get codec mode */
+ if (rx_type != RX_NO_DATA)
+ {
+ /* Get mode from input bitstream */
+ mode = (enum Mode) * ets_word_ptr;
+ }
+ else
+ {
+ /* Use previous mode if no received data */
+ mode = decoder_state->prev_mode;
+ }
+
+ /* Set up byte_offset */
+ byte_offset = 2 * (MAX_SERIAL_SIZE + 2);
+ }
+ else
+ {
+ /* Invalid input format, return error code */
+ byte_offset = -1;
+ }
+
+ /* Proceed with decoding frame, if there are no errors */
+ if (byte_offset != -1)
+ {
+ /* Decode a 20 ms frame */
+
+#ifndef CONSOLE_DECODER_REF
+ /* Use PV version of sp_dec.c */
+ GSMFrameDecode(decoder_state, mode, dec_ets_input_bfr, rx_type,
+ raw_pcm_buffer);
+
+#else
+ /* Use ETS version of sp_dec.c */
+ Speech_Decode_Frame(decoder_state, mode, dec_ets_input_bfr, rx_type,
+ raw_pcm_buffer);
+
+#endif
+
+ /* Save mode for next frame */
+ decoder_state->prev_mode = mode;
+ }
+
+ return (byte_offset);
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/amrdecode.h b/media/libstagefright/codecs/amrnb/dec/src/amrdecode.h
new file mode 100644
index 0000000..db951b9
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/amrdecode.h
@@ -0,0 +1,166 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./gsm-amr/c/include/amrdecode.h
+
+ Date: 05/23/2001
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added BytesUsed table so that the code can allow for padding
+ at the end of each frame.
+
+ Description: Removed function prototypes for getbits, putbits,
+ put_frame_header_in, and get_frame_header_off. Removed
+ basicop_malloc.h and replaced it with typedef.h in the include
+ section. Fixed table entries for various SID modes. Removed
+ #defines because they are not used by AMRDecode function.
+ Removed tables not used by AMRDecode function.
+
+ Description: The data type Speech_Decode_FrameState is now being passed into
+ this function as a void pointer rather than a structure of type
+ Speech_Decode_FrameState.
+
+ Description: The variable decoder_state was renamed to state_data.
+
+ Description: Updated function prototype and header template.
+
+ Description: Added mode.h and frame_type_3gpp.h to include section, and
+ removed sp_dec.h.
+
+ Description: Removed definition of Changed BytesThisFrame[] table. Added
+ extern declaration for BytesThisFrame[] table.
+
+ Description: Added #define for WMF and IF2. Updated function prototype.
+
+ Description: Moved input format #defines and BytesThisFrame table to
+ dec_input_format_tab.h and dec_input_format_tab.c, respectively.
+ Updated function prototype.
+
+ Description: Updated function prototype of AMRDecode due to the removal of
+ *prev_mode_ptr. Added extern of If2BytesPerFrame
+
+ Description: Added #defines for WMF, IF2, and ETS input formats.
+
+ Description: Changed WmfBytesPerFrame to WmfDecBytesPerFrame, and
+ If2BytesPerFrame to If2DecBytesPerFrame.
+
+ Description: Renamed #defines for input format types to make it unique to the
+ decoder.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the norm_s function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef ARMDECODE_H
+#define ARMDECODE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "frame_type_3gpp.h"
+#include "pvamrnbdecoder_api.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define NUM_AMRSID_RXMODE_BITS 3
+#define AMRSID_RXMODE_BIT_OFFSET 36
+#define AMRSID_RXTYPE_BIT_OFFSET 35
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 WmfDecBytesPerFrame[];
+ extern const Word16 If2DecBytesPerFrame[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ Word16 AMRDecode(
+ void *state_data,
+ enum Frame_Type_3GPP frame_type,
+ UWord8 *speech_bits_ptr,
+ Word16 *raw_pcm_buffer,
+ bitstream_format input_format
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMRDECODE_H_ */
diff --git a/media/libstagefright/codecs/amrnb/dec/src/b_cn_cod.cpp b/media/libstagefright/codecs/amrnb/dec/src/b_cn_cod.cpp
new file mode 100644
index 0000000..e62e483
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/b_cn_cod.cpp
@@ -0,0 +1,516 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/b_cn_cod.c
+ Functions: pseudonoise
+ build_CN_code
+ build_CN_param
+
+ Date: 09/28/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template. Cleaned up code. Passing in a pointer to
+ overflow flag for build_CN_code() and build_CN_param() functions.
+ Removed unnecessary header files.
+ Description: Make chnages per formal review. Fix error introduced during
+ optimization in pseudonoise().
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This module contains functions for comfort noise(CN) generation.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "b_cn_cod.h"
+#include "basic_op.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+#define NB_PULSE 10 /* number of random pulses in DTX operation */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: pseudonoise
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pShift_reg = pointer to Old CN generator shift register state (Word32)
+ no_bits = Number of bits (Word16)
+
+ Outputs:
+ pShift_reg -> Updated CN generator shift register state
+
+ Returns:
+ noise_bits = Generated random integer value (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Generate a random integer value to use in comfort noise generation. The
+ algorithm uses polynomial x^31 + x^3 + 1. Length of the PN sequence
+ is 2^31 - 1
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ b_cn_cod.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 pseudonoise (
+ Word32 *shift_reg, // i/o : Old CN generator shift register state
+ Word16 no_bits // i : Number of bits
+)
+{
+ Word16 noise_bits, Sn, i;
+
+ noise_bits = 0;
+ for (i = 0; i < no_bits; i++)
+ {
+ // State n == 31
+ if ((*shift_reg & 0x00000001L) != 0)
+ {
+ Sn = 1;
+ }
+ else
+ {
+ Sn = 0;
+ }
+
+ // State n == 3
+ if ((*shift_reg & 0x10000000L) != 0)
+ {
+ Sn = Sn ^ 1;
+ }
+ else
+ {
+ Sn = Sn ^ 0;
+ }
+
+ noise_bits = shl (noise_bits, 1);
+ noise_bits = noise_bits | (extract_l (*shift_reg) & 1);
+
+ *shift_reg = L_shr (*shift_reg, 1);
+ if (Sn & 1)
+ {
+ *shift_reg = *shift_reg | 0x40000000L;
+ }
+ }
+ return noise_bits;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Word16 pseudonoise(
+ Word32 *pShift_reg, /* i/o : Old CN generator shift register state */
+ Word16 no_bits /* i : Number of bits */
+)
+{
+ Word16 noise_bits;
+ Word16 Sn;
+ Word16 i;
+ Word16 temp;
+
+ noise_bits = 0;
+
+ for (i = 0; i < no_bits; i++)
+ {
+ /* State n == 31 */
+ if ((*pShift_reg & 0x00000001L) != 0)
+ {
+ Sn = 1;
+ }
+ else
+ {
+ Sn = 0;
+ }
+
+ /* State n == 3 */
+ if ((*pShift_reg & 0x10000000L) != 0)
+ {
+ Sn ^= 1;
+ }
+ else
+ {
+ Sn ^= 0;
+ }
+
+ noise_bits <<= 1;
+
+ temp = (Word16)((*pShift_reg) & 1);
+ noise_bits |= temp;
+
+ *pShift_reg >>= 1;
+ if (Sn & 1)
+ {
+ *pShift_reg |= 0x40000000L;
+ }
+ }
+ return noise_bits;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: build_CN_code
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pSeed = pointer to the Old CN generator shift register state (Word32)
+ cod[] = array to hold the generated CN fixed code vector (Word16)
+ pOverflow = pointer to overflow flag (Flag)
+
+ Outputs:
+ cod[] = generated CN fixed code vector (Word16)
+ pSeed = Updated CN generator shift register state (Word16)
+ pOverflow -> 1 if overflow occured
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+This function computes the comfort noise fixed codebook excitation. The gains
+of the pulses are always +/-1.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ b_cn_cod.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void build_CN_code (
+ Word32 *seed, // i/o : Old CN generator shift register state
+ Word16 cod[] // o : Generated CN fixed codebook vector
+)
+{
+ Word16 i, j, k;
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ cod[i] = 0;
+ }
+
+// The reference ETSI code uses a global flag for Overflow. However in the
+// actual implementation a pointer to the overflow flag is passed into the
+// function so that it can be passed into the basic math functions L_mult()
+// and add()
+
+ for (k = 0; k < NB_PULSE; k++)
+ {
+ i = pseudonoise (seed, 2); // generate pulse position
+ i = shr (extract_l (L_mult (i, 10)), 1);
+ i = add (i, k);
+
+ j = pseudonoise (seed, 1); // generate sign
+
+ if (j > 0)
+ {
+ cod[i] = 4096;
+ }
+ else
+ {
+ cod[i] = -4096;
+ }
+ }
+
+ return;
+}
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void build_CN_code(
+ Word32 *pSeed, /* i/o : Old CN generator shift register state */
+ Word16 cod[], /* o : Generated CN fixed codebook vector */
+ Flag *pOverflow /* i/o : Overflow flag */
+)
+{
+ Word16 i, j, k;
+ Word16 temp;
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ cod[i] = 0;
+ }
+
+ for (k = 0; k < NB_PULSE; k++)
+ {
+ i = pseudonoise(pSeed, 2); /* generate pulse position */
+
+ temp = (Word16)(L_mult(i, 10, pOverflow));
+ i = temp >> 1;
+ i = add(i, k, pOverflow);
+
+ j = pseudonoise(pSeed, 1); /* generate sign */
+
+ if (j > 0)
+ {
+ cod[i] = 4096;
+ }
+ else
+ {
+ cod[i] = -4096;
+ }
+ }
+
+ return;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: build_CN_param
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pSeed = pointer to the Old CN generator shift register state (Word32)
+ n_param = Number of parameters to randomize (Word16)
+ param_size_table = table holding paameter sizes (Word16)
+ param[] = array to hold CN generated paramters (Word16)
+ pOverflow = pointer to overflow flag (Flag)
+
+ Outputs:
+ param[] = CN generated parameters (Word16)
+ pSeed = Updated CN generator shift register state (Word16)
+ pOverflow -> 1 if overflow occured
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+This function randomizes the speech parameters, so that they do not produce
+tonal artifacts if used by ECU.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ b_cn_cod.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+void build_CN_param (
+ Word16 *seed, // i/o : Old CN generator shift register state
+ const Word16 n_param, // i : number of params
+ const Word16 param_size_table[],// i : size of params
+ Word16 parm[] // o : CN Generated params
+ )
+{
+ Word16 i;
+ const Word16 *p;
+
+// The reference ETSI code uses a global flag for Overflow. However in the
+// actual implementation a pointer to the overflow flag is passed into the
+// function so that it can be passed into the basic math functions L_add()
+// and L_mult()
+
+ *seed = extract_l(L_add(L_shr(L_mult(*seed, 31821), 1), 13849L));
+
+ p = &window_200_40[*seed & 0x7F];
+ for(i=0; i< n_param;i++){
+ parm[i] = *p++ & ~(0xFFFF<<param_size_table[i]);
+ }
+}
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void build_CN_param(
+ Word16 *pSeed, /* i/o : Old CN generator shift register state */
+ const Word16 n_param, /* i : number of params */
+ const Word16 param_size_table[],/* i : size of params */
+ Word16 parm[], /* o : CN Generated params */
+ Flag *pOverflow /* i/o : Overflow Flag */
+)
+
+{
+ Word16 i;
+ const Word16 *pTemp;
+ Word32 L_temp;
+ Word16 temp;
+
+ L_temp = L_mult(*pSeed, 31821, pOverflow);
+ L_temp >>= 1;
+
+ *pSeed = (Word16)(L_add(L_temp, 13849L, pOverflow));
+
+ pTemp = &window_200_40[*pSeed & 0x7F];
+
+ for (i = 0; i < n_param; i++)
+ {
+ temp = ~(0xFFFF << param_size_table[i]);
+ parm[i] = *pTemp++ & temp;
+ }
+}
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/b_cn_cod.h b/media/libstagefright/codecs/amrnb/dec/src/b_cn_cod.h
new file mode 100644
index 0000000..743237c
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/b_cn_cod.h
@@ -0,0 +1,171 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/add.h
+
+
+
+
+ Date: 08/11/2000
+
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description: Created separate header file for add function.
+
+ Description: Changed function prototype; pointer to overflow flag is passed
+ in as a parameter.
+
+ Description: Updated copyright section.
+ Changed "overflow" to "pOverflow" in the function prototype.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the comfort noise(CN) generator functions
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef B_CN_COD_H
+#define B_CN_COD_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern Word16 window_200_40[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+
+ ; FUNCTION NAME: pseudonoise
+ ;
+ ; PURPOSE: Generate a random integer value to use in comfort noise
+ ; generation. The algorithm uses polynomial x^31 + x^3 + 1
+ ; (length of PN sequence is 2^31 - 1).
+ ;
+ ----------------------------------------------------------------------------*/
+
+ Word16 pseudonoise(
+ Word32 *pShift_reg, /* i/o : Old CN generator shift register state */
+ Word16 no_bits /* i : Number of bits */
+ );
+
+ /*----------------------------------------------------------------------------
+
+ ; FUNCTION NAME: build_CN_code
+ ;
+ ; PURPOSE: Compute the comfort noise fixed codebook excitation. The
+ ; gains of the pulses are always +/-1.
+ ;
+ ----------------------------------------------------------------------------*/
+
+ void build_CN_code(
+ Word32 *pSeed, /* i/o : Old CN generator shift register state */
+ Word16 cod[], /* o : Generated CN fixed codebook vector */
+ Flag *pOverflow /* i/o : Overflow flag */
+ );
+
+ /*----------------------------------------------------------------------------
+
+ ; FUNCTION NAME: build_CN_param
+ ;
+ ; PURPOSE: Randomize the speech parameters. So that they
+ ; do not produce tonal artifacts if used by ECU.
+ ;
+ ----------------------------------------------------------------------------*/
+
+ void build_CN_param(
+ Word16 *pSeed, /* i/o : Old CN generator shift register state */
+ const Word16 n_param, /* i : number of params */
+ const Word16 param_size_table[], /* i : size of params */
+ Word16 parm[], /* o : CN Generated params */
+ Flag *pOverflow /* i/o : Overflow Flag */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _B_CN_COD_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/bgnscd.cpp b/media/libstagefright/codecs/amrnb/dec/src/bgnscd.cpp
new file mode 100644
index 0000000..e732007
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/bgnscd.cpp
@@ -0,0 +1,589 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+ Pathname: ./audio/gsm-amr/c/src/bgnscd.c
+ Functions:
+ Bgn_scd_reset
+ Bgn_scd
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Background noise source characteristic detector (SCD)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <string.h>
+
+#include "bgnscd.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "copy.h"
+#include "gmed_n.h"
+#include "sqrt_l.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define TRUE 1
+#define FALSE 0
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Bgn_scd_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = points to memory of type Bgn_scdState.
+
+ Outputs:
+ The memory of type Bgn_scdState pointed to by state is set to all
+ zeros.
+
+ Returns:
+ Returns 0 if memory was successfully initialized,
+ otherwise returns -1.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Resets state memory.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ bgnscd.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 Bgn_scd_reset (Bgn_scdState *state)
+{
+ if (state == (Bgn_scdState *) NULL){
+ fprintf(stderr, "Bgn_scd_reset: invalid parameter\n");
+ return -1;
+ }
+
+ // Static vectors to zero
+ Set_zero (state->frameEnergyHist, L_ENERGYHIST);
+
+ // Initialize hangover handling
+ state->bgHangover = 0;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Bgn_scd_reset(Bgn_scdState *state)
+{
+ if (state == (Bgn_scdState *) NULL)
+ {
+ /* fprintf(stderr, "Bgn_scd_reset: invalid parameter\n"); */
+ return(-1);
+ }
+
+ /* Static vectors to zero */
+ memset(state->frameEnergyHist, 0, L_ENERGYHIST*sizeof(Word16));
+
+ /* Initialize hangover handling */
+ state->bgHangover = 0;
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Bgn_scd
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to state variables of type Bgn_scdState
+ ltpGainHist[] = LTP gain history (Word16)
+ speech[] = synthesis speech frame (Word16)
+ voicedHangover = pointer to # of frames after last voiced frame (Word16)
+ pOverflow = pointer to overflow indicator (Flag)
+
+ Outputs:
+ st = function updates the state variables of type Bgn_scdState
+ pointed to by st.
+ voicedHangover = function updates the # of frames after last voiced
+ frame pointed to by voicedHangover.
+ pOverflow = 1 if the basic math function L_add() results in saturation.
+ else pOverflow is zero.
+
+ Returns:
+ inbgNoise = flag if background noise is present (Word16)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Characterize synthesis speech and detect background noise.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ bgnscd.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 Bgn_scd (Bgn_scdState *st, // i : State variables for bgn SCD
+ Word16 ltpGainHist[], // i : LTP gain history
+ Word16 speech[], // o : synthesis speech frame
+ Word16 *voicedHangover // o : # of frames after last
+ voiced frame
+ )
+{
+ Word16 i;
+ Word16 prevVoiced, inbgNoise;
+ Word16 temp;
+ Word16 ltpLimit, frameEnergyMin;
+ Word16 currEnergy, noiseFloor, maxEnergy, maxEnergyLastPart;
+ Word32 s;
+
+ // Update the inBackgroundNoise flag (valid for use in next frame if BFI)
+ // it now works as a energy detector floating on top
+ // not as good as a VAD.
+
+ currEnergy = 0;
+ s = (Word32) 0;
+
+ for (i = 0; i < L_FRAME; i++)
+ {
+ s = L_mac (s, speech[i], speech[i]);
+ }
+
+ s = L_shl(s, 2);
+
+ currEnergy = extract_h (s);
+
+ frameEnergyMin = 32767;
+
+ for (i = 0; i < L_ENERGYHIST; i++)
+ {
+ if (sub(st->frameEnergyHist[i], frameEnergyMin) < 0)
+ frameEnergyMin = st->frameEnergyHist[i];
+ }
+
+ noiseFloor = shl (frameEnergyMin, 4); // Frame Energy Margin of 16
+
+ maxEnergy = st->frameEnergyHist[0];
+ for (i = 1; i < L_ENERGYHIST-4; i++)
+ {
+ if ( sub (maxEnergy, st->frameEnergyHist[i]) < 0)
+ {
+ maxEnergy = st->frameEnergyHist[i];
+ }
+ }
+
+ maxEnergyLastPart = st->frameEnergyHist[2*L_ENERGYHIST/3];
+ for (i = 2*L_ENERGYHIST/3+1; i < L_ENERGYHIST; i++)
+ {
+ if ( sub (maxEnergyLastPart, st->frameEnergyHist[i] ) < 0)
+ {
+ maxEnergyLastPart = st->frameEnergyHist[i];
+ }
+ }
+
+ inbgNoise = 0; // false
+
+ // Do not consider silence as noise
+ // Do not consider continuous high volume as noise
+ // Or if the current noise level is very low
+ // Mark as noise if under current noise limit
+ // OR if the maximum energy is below the upper limit
+
+ if ( (sub(maxEnergy, LOWERNOISELIMIT) > 0) &&
+ (sub(currEnergy, FRAMEENERGYLIMIT) < 0) &&
+ (sub(currEnergy, LOWERNOISELIMIT) > 0) &&
+ ( (sub(currEnergy, noiseFloor) < 0) ||
+ (sub(maxEnergyLastPart, UPPERNOISELIMIT) < 0)))
+ {
+ if (sub(add(st->bgHangover, 1), 30) > 0)
+ {
+ st->bgHangover = 30;
+ } else
+ {
+ st->bgHangover = add(st->bgHangover, 1);
+ }
+ }
+ else
+ {
+ st->bgHangover = 0;
+ }
+
+ // make final decision about frame state , act somewhat cautiosly
+ if (sub(st->bgHangover,1) > 0)
+ inbgNoise = 1; // true
+
+ for (i = 0; i < L_ENERGYHIST-1; i++)
+ {
+ st->frameEnergyHist[i] = st->frameEnergyHist[i+1];
+ }
+ st->frameEnergyHist[L_ENERGYHIST-1] = currEnergy;
+
+ // prepare for voicing decision; tighten the threshold after some
+ time in noise
+ ltpLimit = 13926; // 0.85 Q14
+ if (sub(st->bgHangover, 8) > 0)
+ {
+ ltpLimit = 15565; // 0.95 Q14
+ }
+ if (sub(st->bgHangover, 15) > 0)
+ {
+ ltpLimit = 16383; // 1.00 Q14
+ }
+
+ // weak sort of voicing indication.
+ prevVoiced = 0; // false
+
+ if (sub(gmed_n(&ltpGainHist[4], 5), ltpLimit) > 0)
+ {
+ prevVoiced = 1; // true
+ }
+ if (sub(st->bgHangover, 20) > 0) {
+ if (sub(gmed_n(ltpGainHist, 9), ltpLimit) > 0)
+ {
+ prevVoiced = 1; // true
+ }
+ else
+ {
+ prevVoiced = 0; // false
+ }
+ }
+
+ if (prevVoiced)
+ {
+ *voicedHangover = 0;
+ }
+ else
+ {
+ temp = add(*voicedHangover, 1);
+ if (sub(temp, 10) > 0)
+ {
+ *voicedHangover = 10;
+ }
+ else
+ {
+ *voicedHangover = temp;
+ }
+ }
+
+ return inbgNoise;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Bgn_scd(Bgn_scdState *st, /* i : State variables for bgn SCD */
+ Word16 ltpGainHist[], /* i : LTP gain history */
+ Word16 speech[], /* o : synthesis speech frame */
+ Word16 *voicedHangover,/* o : # of frames after last
+ voiced frame */
+ Flag *pOverflow
+ )
+{
+ Word16 i;
+ Word16 prevVoiced, inbgNoise;
+ Word16 temp;
+ Word16 ltpLimit, frameEnergyMin;
+ Word16 currEnergy, noiseFloor, maxEnergy, maxEnergyLastPart;
+ Word32 s, L_temp;
+
+
+ /* Update the inBackgroundNoise flag (valid for use in next frame if BFI) */
+ /* it now works as a energy detector floating on top */
+ /* not as good as a VAD. */
+
+ s = (Word32) 0;
+
+ for (i = L_FRAME - 1; i >= 0; i--)
+ {
+ L_temp = ((Word32) speech[i]) * speech[i];
+ if (L_temp != (Word32) 0x40000000L)
+ {
+ L_temp = L_temp << 1;
+ }
+ else
+ {
+ L_temp = MAX_32;
+ }
+ s = L_add(s, L_temp, pOverflow);
+ }
+
+ /* s is a sum of squares, so don't need to check for neg overflow */
+ if (s > (Word32)0x1fffffffL)
+ {
+ currEnergy = MAX_16;
+ }
+ else
+ {
+ currEnergy = (Word16)(s >> 14);
+ }
+
+ frameEnergyMin = 32767;
+ for (i = L_ENERGYHIST - 1; i >= 0; i--)
+ {
+ if (st->frameEnergyHist[i] < frameEnergyMin)
+ {
+ frameEnergyMin = st->frameEnergyHist[i];
+ }
+ }
+
+ /* Frame Energy Margin of 16 */
+ L_temp = (Word32)frameEnergyMin << 4;
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ if (L_temp > 0)
+ {
+ noiseFloor = MAX_16;
+ }
+ else
+ {
+ noiseFloor = MIN_16;
+ }
+ }
+ else
+ {
+ noiseFloor = (Word16)(L_temp);
+ }
+
+ maxEnergy = st->frameEnergyHist[0];
+ for (i = L_ENERGYHIST - 5; i >= 1; i--)
+ {
+ if (maxEnergy < st->frameEnergyHist[i])
+ {
+ maxEnergy = st->frameEnergyHist[i];
+ }
+ }
+
+ maxEnergyLastPart = st->frameEnergyHist[2*L_ENERGYHIST/3];
+ for (i = 2 * L_ENERGYHIST / 3 + 1; i < L_ENERGYHIST; i++)
+ {
+ if (maxEnergyLastPart < st->frameEnergyHist[i])
+ {
+ maxEnergyLastPart = st->frameEnergyHist[i];
+ }
+ }
+
+ /* Do not consider silence as noise */
+ /* Do not consider continuous high volume as noise */
+ /* Or if the current noise level is very low */
+ /* Mark as noise if under current noise limit */
+ /* OR if the maximum energy is below the upper limit */
+
+ if ((maxEnergy > LOWERNOISELIMIT) &&
+ (currEnergy < FRAMEENERGYLIMIT) &&
+ (currEnergy > LOWERNOISELIMIT) &&
+ ((currEnergy < noiseFloor) ||
+ (maxEnergyLastPart < UPPERNOISELIMIT)))
+ {
+ if ((st->bgHangover + 1) > 30)
+ {
+ st->bgHangover = 30;
+ }
+ else
+ {
+ st->bgHangover += 1;
+ }
+ }
+ else
+ {
+ st->bgHangover = 0;
+ }
+
+ /* make final decision about frame state , act somewhat cautiosly */
+
+ if (st->bgHangover > 1)
+ {
+ inbgNoise = TRUE;
+ }
+ else
+ {
+ inbgNoise = FALSE;
+ }
+
+ for (i = 0; i < L_ENERGYHIST - 1; i++)
+ {
+ st->frameEnergyHist[i] = st->frameEnergyHist[i+1];
+ }
+ st->frameEnergyHist[L_ENERGYHIST-1] = currEnergy;
+
+ /* prepare for voicing decision; tighten the threshold after some
+ time in noise */
+
+ if (st->bgHangover > 15)
+ {
+ ltpLimit = 16383; /* 1.00 Q14 */
+ }
+ else if (st->bgHangover > 8)
+ {
+ ltpLimit = 15565; /* 0.95 Q14 */
+ }
+ else
+ {
+ ltpLimit = 13926; /* 0.85 Q14 */
+ }
+
+ /* weak sort of voicing indication. */
+ prevVoiced = FALSE;
+
+ if (gmed_n(&ltpGainHist[4], 5) > ltpLimit)
+ {
+ prevVoiced = TRUE;
+ }
+
+ if (st->bgHangover > 20)
+ {
+ if (gmed_n(ltpGainHist, 9) > ltpLimit)
+ {
+ prevVoiced = TRUE;
+ }
+ else
+ {
+ prevVoiced = FALSE;
+ }
+ }
+
+
+ if (prevVoiced)
+ {
+ *voicedHangover = 0;
+ }
+ else
+ {
+ temp = *voicedHangover + 1;
+
+ if (temp > 10)
+ {
+ *voicedHangover = 10;
+ }
+ else
+ {
+ *voicedHangover = temp;
+ }
+ }
+
+ return(inbgNoise);
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/bgnscd.h b/media/libstagefright/codecs/amrnb/dec/src/bgnscd.h
new file mode 100644
index 0000000..41349d9
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/bgnscd.h
@@ -0,0 +1,159 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/bgnscd.h
+
+ Date: 12/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : bgnscd.h
+ Purpose : Background noise source charateristic detector (SCD)
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _BGNSCD_H_
+#define _BGNSCD_H_
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+#define L_ENERGYHIST 60
+#define INV_L_FRAME 102
+
+
+ /* 2*(160*x)^2 / 65536 where x is FLP values 150,5 and 50 */
+#define FRAMEENERGYLIMIT 17578 /* 150 */
+#define LOWERNOISELIMIT 20 /* 5 */
+#define UPPERNOISELIMIT 1953 /* 50 */
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ /* history vector of past synthesis speech energy */
+ Word16 frameEnergyHist[L_ENERGYHIST];
+
+ /* state flags */
+ Word16 bgHangover; /* counter; number of frames after last speech frame */
+
+ } Bgn_scdState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ /*
+ * Function : Bgn_scd_init
+ * Purpose : Allocates initializes state memory
+ * Description : Stores pointer to filter status struct in *st. This
+ * pointer has to be passed to Bgn_scd in each call.
+ * Returns : 0 on success
+ */
+ Word16 Bgn_scd_init(Bgn_scdState **st);
+
+ /*
+ * Function : Bgn_scd_reset
+ * Purpose : Resets state memory
+ * Returns : 0 on success
+ */
+ Word16 Bgn_scd_reset(Bgn_scdState *st);
+
+ /*
+ * Function : Bgn_scd_exit
+ * Purpose : The memory used for state memory is freed
+ * Description : Stores NULL in *s
+ * Returns : void
+ */
+ void Bgn_scd_exit(Bgn_scdState **st);
+
+ /*
+ * Function : Bgn_scd
+ * Purpose : Charaterice synthesis speech and detect background noise
+ * Returns : background noise decision; 0 = bgn, 1 = no bgn
+ */
+ Word16 Bgn_scd(Bgn_scdState *st, /* i : State variables for bgn SCD */
+ Word16 ltpGainHist[], /* i : LTP gain history */
+ Word16 speech[], /* o : synthesis speech frame */
+ Word16 *voicedHangover,/* o : # of frames after last voiced frame */
+ Flag *pOverflow
+ );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BGNSCD_H_ */
diff --git a/media/libstagefright/codecs/amrnb/dec/src/c_g_aver.cpp b/media/libstagefright/codecs/amrnb/dec/src/c_g_aver.cpp
new file mode 100644
index 0000000..91d3982
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/c_g_aver.cpp
@@ -0,0 +1,648 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/c_g_aver.c
+ Functions:
+ Cb_gain_average_reset
+ Cb_gain_average
+
+ Date: 03/28/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Made some changes to the comments to match the comments from
+ other modules.
+
+ Description: Made changes based on comments from the review meeting.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Defined one local variable per line.
+
+ Description: Removed the functions Cb_gain_average_init and
+ Cb_gain_average_exit. The Cb_gain_average related structure is no longer
+ dynamically allocated.
+
+ Description: Passing in pOverflow to comply with changes needed for EPOC
+ Updated the include files for the module.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description:
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains functions that reset and perform
+ codebook gain calculations.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <string.h>
+
+#include "c_g_aver.h"
+#include "typedef.h"
+#include "mode.h"
+#include "cnst.h"
+
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Cb_gain_average_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a structure of type Cb_gain_averageState
+
+ Outputs:
+ Structure pointed to by state is initialized to zeros
+
+ Returns:
+ Returns 0 if memory was successfully initialized,
+ otherwise returns -1.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Resets state memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ c_g_aver.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 Cb_gain_average_reset (Cb_gain_averageState *state)
+{
+ if (state == (Cb_gain_averageState *) NULL){
+ fprintf(stderr, "Cb_gain_average_reset: invalid parameter\n");
+ return -1;
+ }
+
+ // Static vectors to zero
+ Set_zero (state->cbGainHistory, L_CBGAINHIST);
+
+ // Initialize hangover handling
+ state->hangVar = 0;
+ state->hangCount= 0;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Cb_gain_average_reset(Cb_gain_averageState *state)
+{
+ if (state == (Cb_gain_averageState *) NULL)
+ {
+ /* fprint(stderr, "Cb_gain_average_reset: invalid parameter\n"); */
+ return(-1);
+ }
+
+ /* Static vectors to zero */
+ memset(state->cbGainHistory, 0, L_CBGAINHIST*sizeof(Word16));
+
+ /* Initialize hangover handling */
+ state->hangVar = 0;
+ state->hangCount = 0;
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Cb_gain_average
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to structure of type Cb_gain_averageState
+ mode = AMR mode (enum Mode)
+ gain_code = CB gain (Word16)
+ lsp = the LSP for the current frame (Word16)
+ lspAver = the average of LSP for 8 frames (Word16)
+ bfi = bad frame indication flag (Word16)
+ prev_bf = previous bad frame indication flag (Word16)
+ pdfi = potential degraded bad frame ind flag (Word16)
+ prev_pdf = prev pot. degraded bad frame ind flag (Word16)
+ inBackgroundNoise = background noise decision (Word16)
+ voicedHangover = # of frames after last voiced frame (Word16)
+ pOverflow = address of overflow (Flag)
+
+ Returns:
+ cbGainMix = codebook gain (Word16)
+
+ Outputs:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ The mix cb gains for MR475, MR515, MR59, MR67, MR102; gain_code other modes
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ c_g_aver.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 Cb_gain_average (
+ Cb_gain_averageState *st, // i/o : State variables for CB gain avergeing
+ enum Mode mode, // i : AMR mode
+ Word16 gain_code, // i : CB gain Q1
+ Word16 lsp[], // i : The LSP for the current frame Q15
+ Word16 lspAver[], // i : The average of LSP for 8 frames Q15
+ Word16 bfi, // i : bad frame indication flag
+ Word16 prev_bf, // i : previous bad frame indication flag
+ Word16 pdfi, // i : potential degraded bad frame ind flag
+ Word16 prev_pdf, // i : prev pot. degraded bad frame ind flag
+ Word16 inBackgroundNoise, // i : background noise decision
+ Word16 voicedHangover // i : # of frames after last voiced frame
+ )
+{
+ //---------------------------------------------------------*
+ * Compute mixed cb gain, used to make cb gain more *
+ * smooth in background noise for modes 5.15, 5.9 and 6.7 *
+ * states that needs to be updated by all *
+ *---------------------------------------------------------
+ Word16 i;
+ Word16 cbGainMix, diff, tmp_diff, bgMix, cbGainMean;
+ Word32 L_sum;
+ Word16 tmp[M], tmp1, tmp2, shift1, shift2, shift;
+
+ // set correct cbGainMix for MR74, MR795, MR122
+ cbGainMix = gain_code;
+
+ *-------------------------------------------------------*
+ * Store list of CB gain needed in the CB gain *
+ * averaging *
+ *-------------------------------------------------------*
+ for (i = 0; i < (L_CBGAINHIST-1); i++)
+ {
+ st->cbGainHistory[i] = st->cbGainHistory[i+1];
+ }
+ st->cbGainHistory[L_CBGAINHIST-1] = gain_code;
+
+ // compute lsp difference
+ for (i = 0; i < M; i++) {
+ tmp1 = abs_s(sub(lspAver[i], lsp[i])); // Q15
+ shift1 = sub(norm_s(tmp1), 1); // Qn
+ tmp1 = shl(tmp1, shift1); // Q15+Qn
+ shift2 = norm_s(lspAver[i]); // Qm
+ tmp2 = shl(lspAver[i], shift2); // Q15+Qm
+ tmp[i] = div_s(tmp1, tmp2); // Q15+(Q15+Qn)-(Q15+Qm)
+ shift = sub(add(2, shift1), shift2);
+ if (shift >= 0)
+ {
+ tmp[i] = shr(tmp[i], shift); // Q15+Qn-Qm-Qx=Q13
+ }
+ else
+ {
+ tmp[i] = shl(tmp[i], negate(shift)); // Q15+Qn-Qm-Qx=Q13
+ }
+ }
+
+ diff = tmp[0];
+ for (i = 1; i < M; i++) {
+ diff = add(diff, tmp[i]); // Q13
+ }
+
+ // Compute hangover
+ if (sub(diff, 5325) > 0) // 0.65 in Q11
+ {
+ st->hangVar = add(st->hangVar, 1);
+ }
+ else
+ {
+ st->hangVar = 0;
+ }
+
+ if (sub(st->hangVar, 10) > 0)
+ {
+ st->hangCount = 0; // Speech period, reset hangover variable
+ }
+
+ // Compute mix constant (bgMix)
+ bgMix = 8192; // 1 in Q13
+ if ((sub(mode, MR67) <= 0) || (sub(mode, MR102) == 0))
+ // MR475, MR515, MR59, MR67, MR102
+ {
+ // if errors and presumed noise make smoothing probability stronger
+ if (((((pdfi != 0) && (prev_pdf != 0)) || (bfi != 0) || (prev_bf != 0)) &&
+ (sub(voicedHangover, 1) > 0) && (inBackgroundNoise != 0) &&
+ ((sub(mode, MR475) == 0) ||
+ (sub(mode, MR515) == 0) ||
+ (sub(mode, MR59) == 0)) ))
+ {
+ // bgMix = min(0.25, max(0.0, diff-0.55)) / 0.25;
+ tmp_diff = sub(diff, 4506); // 0.55 in Q13
+
+ // max(0.0, diff-0.55)
+ if (tmp_diff > 0)
+ {
+ tmp1 = tmp_diff;
+ }
+ else
+ {
+ tmp1 = 0;
+ }
+
+ // min(0.25, tmp1)
+ if (sub(2048, tmp1) < 0)
+ {
+ bgMix = 8192;
+ }
+ else
+ {
+ bgMix = shl(tmp1, 2);
+ }
+ }
+ else
+ {
+ // bgMix = min(0.25, max(0.0, diff-0.40)) / 0.25;
+ tmp_diff = sub(diff, 3277); // 0.4 in Q13
+
+ // max(0.0, diff-0.40)
+ if (tmp_diff > 0)
+ {
+ tmp1 = tmp_diff;
+ }
+ else
+ {
+ tmp1 = 0;
+ }
+
+ // min(0.25, tmp1)
+ if (sub(2048, tmp1) < 0)
+ {
+ bgMix = 8192;
+ }
+ else
+ {
+ bgMix = shl(tmp1, 2);
+ }
+ }
+
+ if ((sub(st->hangCount, 40) < 0) || (sub(diff, 5325) > 0)) // 0.65 in Q13
+ {
+ bgMix = 8192; // disable mix if too short time since
+ }
+
+ // Smoothen the cb gain trajectory
+ // smoothing depends on mix constant bgMix
+ L_sum = L_mult(6554, st->cbGainHistory[2]); // 0.2 in Q15; L_sum in Q17
+ for (i = 3; i < L_CBGAINHIST; i++)
+ {
+ L_sum = L_mac(L_sum, 6554, st->cbGainHistory[i]);
+ }
+ cbGainMean = pv_round(L_sum); // Q1
+
+ // more smoothing in error and bg noise (NB no DFI used here)
+ if (((bfi != 0) || (prev_bf != 0)) && (inBackgroundNoise != 0) &&
+ ((sub(mode, MR475) == 0) ||
+ (sub(mode, MR515) == 0) ||
+ (sub(mode, MR59) == 0)) )
+ {
+ L_sum = L_mult(4681, st->cbGainHistory[0]); // 0.143 in Q15; L_sum in Q17
+ for (i = 1; i < L_CBGAINHIST; i++)
+ {
+ L_sum = L_mac(L_sum, 4681, st->cbGainHistory[i]);
+ }
+ cbGainMean = pv_round(L_sum); // Q1
+ }
+
+ // cbGainMix = bgMix*cbGainMix + (1-bgMix)*cbGainMean;
+ L_sum = L_mult(bgMix, cbGainMix); // L_sum in Q15
+ L_sum = L_mac(L_sum, 8192, cbGainMean);
+ L_sum = L_msu(L_sum, bgMix, cbGainMean);
+ cbGainMix = pv_round(L_shl(L_sum, 2)); // Q1
+ }
+
+ st->hangCount = add(st->hangCount, 1);
+ return cbGainMix;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Cb_gain_average(
+ Cb_gain_averageState *st, /* i/o : State variables for CB gain averaging */
+ enum Mode mode, /* i : AMR mode */
+ Word16 gain_code, /* i : CB gain Q1 */
+ Word16 lsp[], /* i : The LSP for the current frame Q15 */
+ Word16 lspAver[], /* i : The average of LSP for 8 frames Q15 */
+ Word16 bfi, /* i : bad frame indication flag */
+ Word16 prev_bf, /* i : previous bad frame indication flag */
+ Word16 pdfi, /* i : potential degraded bad frame ind flag */
+ Word16 prev_pdf, /* i : prev pot. degraded bad frame ind flag */
+ Word16 inBackgroundNoise, /* i : background noise decision */
+ Word16 voicedHangover, /* i : # of frames after last voiced frame */
+ Flag *pOverflow
+)
+{
+ Word16 i;
+ Word16 cbGainMix;
+ Word16 diff;
+ Word16 tmp_diff;
+ Word16 bgMix;
+ Word16 cbGainMean;
+ Word32 L_sum;
+ Word16 tmp[M];
+ Word16 tmp1;
+ Word16 tmp2;
+ Word16 shift1;
+ Word16 shift2;
+ Word16 shift;
+
+ /*---------------------------------------------------------*
+ * Compute mixed cb gain, used to make cb gain more *
+ * smooth in background noise for modes 5.15, 5.9 and 6.7 *
+ * states that needs to be updated by all *
+ *---------------------------------------------------------*/
+
+ /* set correct cbGainMix for MR74, MR795, MR122 */
+ cbGainMix = gain_code;
+
+ /*-------------------------------------------------------*
+ * Store list of CB gain needed in the CB gain *
+ * averaging *
+ *-------------------------------------------------------*/
+ for (i = 0; i < (L_CBGAINHIST - 1); i++)
+ {
+ st->cbGainHistory[i] = st->cbGainHistory[i+1];
+ }
+ st->cbGainHistory[L_CBGAINHIST-1] = gain_code;
+
+ diff = 0;
+
+ /* compute lsp difference */
+ for (i = 0; i < M; i++)
+ {
+ tmp1 = abs_s(sub(*(lspAver + i), *(lsp + i), pOverflow));
+ /* Q15 */
+ shift1 = sub(norm_s(tmp1), 1, pOverflow); /* Qn */
+ tmp1 = shl(tmp1, shift1, pOverflow); /* Q15+Qn */
+ shift2 = norm_s(*(lspAver + i)); /* Qm */
+ tmp2 = shl(*(lspAver + i), shift2, pOverflow); /* Q15+Qm */
+ tmp[i] = div_s(tmp1, tmp2); /* Q15+(Q15+Qn)-(Q15+Qm) */
+
+ shift = 2 + shift1 - shift2;
+
+ if (shift >= 0)
+ {
+ *(tmp + i) = shr(*(tmp + i), shift, pOverflow);
+ /* Q15+Qn-Qm-Qx=Q13 */
+ }
+ else
+ {
+ *(tmp + i) = shl(*(tmp + i), negate(shift), pOverflow);
+ /* Q15+Qn-Qm-Qx=Q13 */
+ }
+
+ diff = add(diff, *(tmp + i), pOverflow); /* Q13 */
+ }
+
+ /* Compute hangover */
+
+ if (diff > 5325) /* 0.65 in Q11 */
+ {
+ st->hangVar += 1;
+ }
+ else
+ {
+ st->hangVar = 0;
+ }
+
+
+ if (st->hangVar > 10)
+ {
+ /* Speech period, reset hangover variable */
+ st->hangCount = 0;
+ }
+
+ /* Compute mix constant (bgMix) */
+ bgMix = 8192; /* 1 in Q13 */
+
+ if ((mode <= MR67) || (mode == MR102))
+ /* MR475, MR515, MR59, MR67, MR102 */
+ {
+ /* if errors and presumed noise make smoothing probability stronger */
+
+ if (((((pdfi != 0) && (prev_pdf != 0)) || (bfi != 0) ||
+ (prev_bf != 0))
+ && (voicedHangover > 1)
+ && (inBackgroundNoise != 0)
+ && ((mode == MR475) || (mode == MR515) ||
+ (mode == MR59))))
+ {
+ /* bgMix = min(0.25, max(0.0, diff-0.55)) / 0.25; */
+ tmp_diff = sub(diff, 4506, pOverflow); /* 0.55 in Q13 */
+ }
+ else
+ {
+ /* bgMix = min(0.25, max(0.0, diff-0.40)) / 0.25; */
+ tmp_diff = sub(diff, 3277, pOverflow); /* 0.4 in Q13 */
+ }
+
+ /* max(0.0, diff-0.55) or */
+ /* max(0.0, diff-0.40) */
+ if (tmp_diff > 0)
+ {
+ tmp1 = tmp_diff;
+ }
+ else
+ {
+ tmp1 = 0;
+ }
+
+ /* min(0.25, tmp1) */
+ if (2048 < tmp1)
+ {
+ bgMix = 8192;
+ }
+ else
+ {
+ bgMix = shl(tmp1, 2, pOverflow);
+ }
+
+ if ((st->hangCount < 40) || (diff > 5325)) /* 0.65 in Q13 */
+ {
+ /* disable mix if too short time since */
+ bgMix = 8192;
+ }
+
+ /* Smoothen the cb gain trajectory */
+ /* smoothing depends on mix constant bgMix */
+ L_sum = L_mult(6554, st->cbGainHistory[2], pOverflow);
+ /* 0.2 in Q15; L_sum in Q17 */
+
+ for (i = 3; i < L_CBGAINHIST; i++)
+ {
+ L_sum = L_mac(L_sum, 6554, st->cbGainHistory[i], pOverflow);
+ }
+ cbGainMean = pv_round(L_sum, pOverflow); /* Q1 */
+
+ /* more smoothing in error and bg noise (NB no DFI used here) */
+
+ if (((bfi != 0) || (prev_bf != 0)) && (inBackgroundNoise != 0)
+ && ((mode == MR475) || (mode == MR515)
+ || (mode == MR59)))
+ {
+ /* 0.143 in Q15; L_sum in Q17 */
+ L_sum = L_mult(4681, st->cbGainHistory[0], pOverflow);
+ for (i = 1; i < L_CBGAINHIST; i++)
+ {
+ L_sum =
+ L_mac(L_sum, 4681, st->cbGainHistory[i], pOverflow);
+ }
+ cbGainMean = pv_round(L_sum, pOverflow); /* Q1 */
+ }
+
+ /* cbGainMix = bgMix*cbGainMix + (1-bgMix)*cbGainMean; */
+ /* L_sum in Q15 */
+ L_sum = L_mult(bgMix, cbGainMix, pOverflow);
+ L_sum = L_mac(L_sum, 8192, cbGainMean, pOverflow);
+ L_sum = L_msu(L_sum, bgMix, cbGainMean, pOverflow);
+ cbGainMix = pv_round(L_shl(L_sum, 2, pOverflow), pOverflow); /* Q1 */
+ }
+
+ st->hangCount += 1;
+
+ return (cbGainMix);
+}
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/c_g_aver.h b/media/libstagefright/codecs/amrnb/dec/src/c_g_aver.h
new file mode 100644
index 0000000..0b53753
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/c_g_aver.h
@@ -0,0 +1,163 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/c_g_aver.h
+
+ Date: 12/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : c_g_aver.h
+ Purpose : Background noise source charateristic detector (SCD)
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _C_G_AVER_H_
+#define _C_G_AVER_H_
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "cnst.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+#define L_CBGAINHIST 7
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ /* history vector of past synthesis speech energy */
+ Word16 cbGainHistory[L_CBGAINHIST];
+
+ /* state flags */
+ Word16 hangVar; /* counter; */
+ Word16 hangCount; /* counter; */
+
+ } Cb_gain_averageState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ /*
+ * Function : Cb_gain_average_init
+ * Purpose : Allocates initializes state memory
+ * Description : Stores pointer to filter status struct in *st. This
+ * pointer has to be passed to Cb_gain_average in each call.
+ * Returns : 0 on success
+ */
+ Word16 Cb_gain_average_init(Cb_gain_averageState **st);
+
+ /*
+ * Function : Cb_gain_average_reset
+ * Purpose : Resets state memory
+ * Returns : 0 on success
+ */
+ Word16 Cb_gain_average_reset(Cb_gain_averageState *st);
+
+ /*
+ * Function : Cb_gain_average_exit
+ * Purpose : The memory used for state memory is freed
+ * Description : Stores NULL in *s
+ * Returns : void
+ */
+ void Cb_gain_average_exit(Cb_gain_averageState **st);
+
+ /*
+ * Function : Cb_gain_average
+ * Purpose : Charaterice synthesis speech and detect background noise
+ * Returns : background noise decision; 0 = bgn, 1 = no bgn
+ */
+ Word16 Cb_gain_average(
+ Cb_gain_averageState *st, /* i/o : State variables for CB gain avergeing */
+ enum Mode mode, /* i : AMR mode */
+ Word16 gain_code, /* i : CB gain Q1 */
+ Word16 lsp[], /* i : The LSP for the current frame Q15 */
+ Word16 lspAver[], /* i : The average of LSP for 8 frames Q15 */
+ Word16 bfi, /* i : bad frame indication flag */
+ Word16 prev_bf, /* i : previous bad frame indication flag */
+ Word16 pdfi, /* i : potential degraded bad frame ind flag */
+ Word16 prev_pdf, /* i : prev pot. degraded bad frame ind flag */
+ Word16 inBackgroundNoise, /* i : background noise decision */
+ Word16 voicedHangover, /* i : # of frames after last voiced frame */
+ Flag *pOverflow
+ );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _C_G_AVER_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d1035pf.cpp b/media/libstagefright/codecs/amrnb/dec/src/d1035pf.cpp
new file mode 100644
index 0000000..899daba
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d1035pf.cpp
@@ -0,0 +1,263 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/d1035pf.c
+
+ Date: 04/14/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template. First attempt at
+ optimizing C code.
+
+ Description: Updated file per comments gathered from Phase 2/3 review.
+
+ Description: Synchronized file with UTMS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Removed inclusion of "gray.tab".
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "d1035pf.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define NB_PULSE 10 /* number of pulses */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: dec_10i40_35bits
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ index = buffer containing index of 10 pulses; each element is
+ represented by sign+position
+ cod = buffer of algebraic (fixed) codebook excitation
+
+ Outputs:
+ cod buffer contains the new algebraic codebook excitation
+
+ Returns:
+ None
+
+ Global Variables Used:
+ dgray = gray decoding table
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function builds the innovative codevector from the received index of
+ algebraic codebook. See c1035pf.c for more details about the algebraic
+ codebook structure.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d1035pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void dec_10i40_35bits (
+ Word16 index[], // (i) : index of 10 pulses (sign+position)
+ Word16 cod[] // (o) : algebraic (fixed) codebook excitation
+)
+{
+ Word16 i, j, pos1, pos2, sign, tmp;
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ cod[i] = 0;
+ }
+
+ // decode the positions and signs of pulses and build the codeword
+
+ for (j = 0; j < NB_TRACK; j++)
+ {
+ // compute index i
+
+ tmp = index[j];
+ i = tmp & 7;
+ i = dgray[i];
+
+ i = extract_l (L_shr (L_mult (i, 5), 1));
+ pos1 = add (i, j); // position of pulse "j"
+
+ i = shr (tmp, 3) & 1;
+ if (i == 0)
+ {
+ sign = 4096; // +1.0
+ }
+ else
+ {
+ sign = -4096; // -1.0
+ }
+
+ cod[pos1] = sign;
+
+ // compute index i
+
+ i = index[add (j, 5)] & 7;
+ i = dgray[i];
+ i = extract_l (L_shr (L_mult (i, 5), 1));
+
+ pos2 = add (i, j); // position of pulse "j+5"
+
+ if (sub (pos2, pos1) < 0)
+ {
+ sign = negate (sign);
+ }
+ cod[pos2] = add (cod[pos2], sign);
+ }
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void dec_10i40_35bits(
+ Word16 index[], /* (i) : index of 10 pulses (sign+position) */
+ Word16 cod[] /* (o) : algebraic (fixed) codebook excitation */
+)
+{
+ register Word16 i, j, pos1, pos2;
+ Word16 sign, tmp;
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ *(cod + i) = 0;
+ }
+
+ /* decode the positions and signs of pulses and build the codeword */
+
+ for (j = 0; j < NB_TRACK; j++)
+ {
+ /* compute index i */
+
+ tmp = *(index + j);
+ i = tmp & 7;
+ i = *(dgray + i);
+
+ i = (Word16)(i * 5);
+ pos1 = i + j; /* position of pulse "j" */
+
+ i = (tmp >> 3) & 1;
+
+ if (i == 0)
+ {
+ sign = 4096; /* +1.0 */
+ }
+ else
+ {
+ sign = -4096; /* -1.0 */
+ }
+
+ *(cod + pos1) = sign;
+
+ /* compute index i */
+
+ i = *(index + j + 5) & 7;
+ i = *(dgray + i);
+ i = (Word16)(i * 5);
+
+ pos2 = i + j; /* position of pulse "j+5" */
+
+
+ if (pos2 < pos1)
+ {
+ sign = negate(sign);
+ }
+ *(cod + pos2) += sign;
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d1035pf.h b/media/libstagefright/codecs/amrnb/dec/src/d1035pf.h
new file mode 100644
index 0000000..51f1f42
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d1035pf.h
@@ -0,0 +1,117 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/d1035pf.h
+
+ Date: 09/28/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template. Added extern declaration for dgray[] defined
+ in gray_tbl.c
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains the prototype declaration for dec_10i40_35bits function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef D1035PF_H
+#define D1035PF_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern Word16 dgray[];
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void dec_10i40_35bits(
+ Word16 index[], /* (i) : index of 10 pulses (sign+position) */
+ Word16 cod[] /* (o) : algebraic (fixed) codebook excitation */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _D1035PF_H_ */
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d2_11pf.cpp b/media/libstagefright/codecs/amrnb/dec/src/d2_11pf.cpp
new file mode 100644
index 0000000..e1e544f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d2_11pf.cpp
@@ -0,0 +1,224 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/d2_11pf.c
+ Functions:
+
+ Date: 01/28/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified to place file in the correct template format. Eliminated
+ use of special functions to perform simple mathematical operations.
+
+ Description: Per review comments...
+ (1) Removed include of "count.h" and "basic_op.h"
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "d2_11pf.h"
+#include "typedef.h"
+#include "cnst.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define NB_PULSE 2
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: decode_2i40_11bits
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ sign -- Word16 -- signs of 2 pulses.
+ index -- Word16 -- Positions of the 2 pulses.
+
+ Outputs:
+ cod[] -- array of type Word16 -- algebraic (fixed) codebook excitation
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d2_11pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void decode_2i40_11bits(
+ Word16 sign, /* i : signs of 2 pulses. */
+ Word16 index, /* i : Positions of the 2 pulses. */
+ Word16 cod[] /* o : algebraic (fixed) codebook excitation */
+)
+
+{
+ Word16 i;
+ Word16 j;
+
+ Word16 pos[NB_PULSE];
+
+ /* Decode the positions */
+
+ j = index & 0x1;
+
+ index >>= 1;
+
+ i = index & 0x7;
+
+ pos[0] = i * 5 + j * 2 + 1;
+
+
+
+
+ index >>= 3;
+
+ j = index & 0x3;
+
+ index >>= 2;
+
+ i = index & 0x7;
+
+ if (j == 3)
+ {
+ pos[1] = i * 5 + 4;
+ }
+ else
+ {
+ pos[1] = i * 5 + j;
+ }
+
+
+
+
+ /* decode the signs and build the codeword */
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ cod[i] = 0;
+ }
+
+ for (j = 0; j < NB_PULSE; j++)
+ {
+ i = sign & 1;
+
+ /* This line is equivalent to...
+ *
+ *
+ * if (i == 1)
+ * {
+ * cod[pos[j]] = 8191;
+ * }
+ * if (i == 0)
+ * {
+ * cod[pos[j]] = -8192;
+ * }
+ */
+
+ cod[pos[j]] = i * 16383 - 8192;
+
+ sign >>= 1;
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d2_11pf.h b/media/libstagefright/codecs/amrnb/dec/src/d2_11pf.h
new file mode 100644
index 0000000..aaf2e08
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d2_11pf.h
@@ -0,0 +1,93 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : d2_11pf.h
+* Purpose : Algebraic codebook decoder
+*
+********************************************************************************
+*/
+#ifndef d2_11pf_h
+#define d2_11pf_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ ********************************************************************************
+ * LOCAL VARIABLES AND TABLES
+ ********************************************************************************
+ */
+
+ /*
+ ********************************************************************************
+ * DEFINITION OF DATA TYPES
+ ********************************************************************************
+ */
+
+ /*
+ ********************************************************************************
+ * DECLARATION OF PROTOTYPES
+ ********************************************************************************
+ */
+ /*************************************************************************
+ *
+ * FUNCTION: decode_2i40_11bits (decod_ACELP())
+ *
+ * PURPOSE: Algebraic codebook decoder for 2 pulses coded with 11 bits
+ *
+ *************************************************************************/
+
+ void decode_2i40_11bits(
+ Word16 sign, /* i : signs of 2 pulses. */
+ Word16 index, /* i : Positions of the 2 pulses. */
+ Word16 cod[] /* o : algebraic (fixed) codebook excitation */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d2_9pf.cpp b/media/libstagefright/codecs/amrnb/dec/src/d2_9pf.cpp
new file mode 100644
index 0000000..2c36706
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d2_9pf.cpp
@@ -0,0 +1,248 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/d2_9pf.c
+ Functions: decode_2i40_9bits
+
+ Date: 01/28/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified to place file in the correct template format. Eliminated
+ use of special functions to perform simple mathematical operations, where
+ possible. Added the parameter pOverflow for the basic math operations.
+
+ Description: Per review comments...
+ (1) Removed include of basic_op.h, replaced with shl.h
+ (2) Added pOverflow to the output section of the template
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+
+ FUNCTION: decode_2i40_9bits (decod_ACELP())
+
+ PURPOSE: Algebraic codebook decoder. For details about the encoding see
+ c2_9pf.c
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "d2_9pf.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+#define NB_PULSE 2
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ extern const Word16 startPos[];
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: decode_2i40_11bits
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ sign -- Word16 -- signs of 2 pulses.
+ index -- Word16 -- Positions of the 2 pulses.
+
+ Outputs:
+ cod[] -- array of type Word16 -- algebraic (fixed) codebook excitation
+ pOverflow = pointer to overflow flag
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void decode_2i40_9bits(
+ Word16 subNr, /* i : subframe number */
+ Word16 sign, /* i : signs of 2 pulses. */
+ Word16 index, /* i : Positions of the 2 pulses. */
+ Word16 cod[], /* o : algebraic (fixed) codebook excitation */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word16 j;
+ Word16 k;
+
+ Word16 pos[NB_PULSE];
+
+ /* Decode the positions */
+ /* table bit is the MSB */
+
+ j = (Word16)(index & 64);
+
+ j >>= 3;
+
+ i = index & 7;
+
+ k =
+ shl(
+ subNr,
+ 1,
+ pOverflow);
+
+ k += j;
+
+ /* pos0 =i*5+startPos[j*8+subNr*2] */
+ pos[0] = i * 5 + startPos[k++];
+
+
+ index >>= 3;
+
+ i = index & 7;
+
+ /* pos1 =i*5+startPos[j*8+subNr*2 + 1] */
+ pos[1] = i * 5 + startPos[k];
+
+
+ /* decode the signs and build the codeword */
+
+ for (i = L_SUBFR - 1; i >= 0; i--)
+ {
+ cod[i] = 0;
+ }
+
+ for (j = 0; j < NB_PULSE; j++)
+ {
+ i = sign & 0x1;
+
+ /* This line is equivalent to...
+ *
+ *
+ * if (i == 1)
+ * {
+ * cod[pos[j]] = 8191;
+ * }
+ * if (i == 0)
+ * {
+ * cod[pos[j]] = -8192;
+ * }
+ */
+
+ cod[pos[j]] = i * 16383 - 8192;
+
+ sign >>= 1;
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d2_9pf.h b/media/libstagefright/codecs/amrnb/dec/src/d2_9pf.h
new file mode 100644
index 0000000..38076d8
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d2_9pf.h
@@ -0,0 +1,122 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/d2_9pf.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the d2_9pf.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef d2_9pf_h
+#define d2_9pf_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void decode_2i40_9bits(
+ Word16 subNr, /* i : subframe number */
+ Word16 sign, /* i : signs of 2 pulses. */
+ Word16 index, /* i : Positions of the 2 pulses. */
+ Word16 cod[], /* o : algebraic (fixed) codebook excitation */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _d2_9PF_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d3_14pf.cpp b/media/libstagefright/codecs/amrnb/dec/src/d3_14pf.cpp
new file mode 100644
index 0000000..d1912cf
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d3_14pf.cpp
@@ -0,0 +1,233 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/d3_14pf.c
+ Functions: decode_3i40_14bits
+
+ Date: 01/28/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified to place file in the correct template format. Eliminated
+ use of special functions to perform simple mathematical operations.
+
+ Description: Per review comments...
+ (1) Removed include of "count.h" and "basic_op.h"
+ (2) Updated the pathname to indicate the correct file. (Line 39)
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+
+ FUNCTION: decode_3i40_14bits (decod_ACELP())
+
+ PURPOSE: Algebraic codebook decoder. For details about the encoding see
+ c3_14pf.c
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+#include "d3_14pf.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define NB_PULSE 3 /* number of pulses */
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: decode_3i40_14bits
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ sign -- Word16 -- signs of 3 pulses.
+ index -- Word16 -- Positions of the 3 pulses.
+
+ Outputs:
+ cod[] -- array of type Word16 -- algebraic (fixed) codebook excitation
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void decode_3i40_14bits(
+ Word16 sign, /* i : signs of 3 pulses. */
+ Word16 index, /* i : Positions of the 3 pulses. */
+ Word16 cod[] /* o : algebraic (fixed) codebook excitation */
+)
+{
+ Word16 i;
+ Word16 j;
+
+ Word16 pos[NB_PULSE];
+
+ /* Decode the positions */
+
+ i = index & 0x7;
+
+ pos[0] = i * 5;
+
+
+
+
+
+ index >>= 3;
+
+ j = index & 0x1;
+
+ index >>= 1;
+
+ i = index & 0x7;
+
+ pos[1] = i * 5 + j * 2 + 1;
+
+
+
+
+
+ index >>= 3;
+
+ j = index & 0x1;
+
+ index >>= 1;
+
+ i = index & 0x7;
+
+ pos[2] = i * 5 + j * 2 + 2;
+
+
+ /* decode the signs and build the codeword */
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ cod[i] = 0;
+ }
+
+ for (j = 0; j < NB_PULSE; j++)
+ {
+ i = sign & 1;
+
+ /* This line is equivalent to...
+ *
+ *
+ * if (i == 1)
+ * {
+ * cod[pos[j]] = 8191;
+ * }
+ * if (i == 0)
+ * {
+ * cod[pos[j]] = -8192;
+ * }
+ */
+
+ cod[pos[j]] = i * 16383 - 8192;
+
+ sign >>= 1;
+
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d3_14pf.h b/media/libstagefright/codecs/amrnb/dec/src/d3_14pf.h
new file mode 100644
index 0000000..1e2e0cd
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d3_14pf.h
@@ -0,0 +1,118 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/d2_9pf.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the d3_14pf.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef d3_14pf_h
+#define d3_14pf_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void decode_3i40_14bits(
+ Word16 sign, /* i : signs of 3 pulses. */
+ Word16 index, /* i : Positions of the 3 pulses. */
+ Word16 cod[] /* o : algebraic (fixed) codebook excitation */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _d3_14PF_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d4_17pf.cpp b/media/libstagefright/codecs/amrnb/dec/src/d4_17pf.cpp
new file mode 100644
index 0000000..ece82c0
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d4_17pf.cpp
@@ -0,0 +1,271 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/d4_17pf.c
+ Functions: decode_4i40_17bits
+
+ Date: 01/28/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified to place file in the correct template format. Eliminated
+ use of special functions to perform simple mathematical operations.
+
+ Description: An incorrect comment in the original source lead me to implement
+ the calculation of pos[2] incorrectly. The correct formula is pos2 =i*5+2,
+ not pos2 = i*5 + 1.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+
+ FUNCTION: decode_4i40_17bits (decod_ACELP())
+
+ PURPOSE: Algebraic codebook decoder. For details about the encoding see
+ c4_17pf.c
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "d4_17pf.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+#define NB_PULSE 4 /* number of pulses */
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 dgray[];
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: decode_4i40_17bits
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ sign -- Word16 -- signs of 3 pulses.
+ index -- Word16 -- Positions of the 3 pulses.
+
+ Outputs:
+ cod[] -- array of type Word16 -- algebraic (fixed) codebook excitation
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d4_17pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void decode_4i40_17bits(
+ Word16 sign, /* i : signs of 4 pulses. */
+ Word16 index, /* i : Positions of the 4 pulses. */
+ Word16 cod[] /* o : algebraic (fixed) codebook excitation */
+)
+{
+ Word16 i;
+ Word16 j;
+
+ Word16 pos[NB_PULSE];
+
+ /* Index is a 13-bit value. 3 bits each correspond to the
+ * positions 0-2, with 4 bits allocated for position 3.
+ *
+ *
+ * [][][][] [][][] [][][] [][][]
+ * | | | |
+ * | | | |
+ * pos3 pos2 pos1 pos0
+ */
+
+ /* Decode the positions */
+
+ i = index & 0x7;
+
+ i = dgray[i];
+
+ pos[0] = i * 5; /* pos0 =i*5 */
+
+
+ index >>= 3;
+
+ i = index & 0x7;
+
+ i = dgray[i];
+
+ pos[1] = i * 5 + 1; /* pos1 =i*5+1 */
+
+
+
+ index >>= 3;
+
+ i = index & 0x7;
+
+ i = dgray[i];
+
+ pos[2] = i * 5 + 2; /* pos2 =i*5+2 */
+
+
+
+
+
+ index >>= 3;
+
+ j = index & 0x1;
+
+ index >>= 1;
+
+ i = index & 0x7;
+
+ i = dgray[i];
+
+ pos[3] = i * 5 + 3 + j; /* pos3 =i*5+3+j */
+
+
+ /* decode the signs and build the codeword */
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ cod[i] = 0;
+ }
+
+ for (j = 0; j < NB_PULSE; j++)
+ {
+ i = sign & 0x1;
+
+ /* This line is equivalent to...
+ *
+ *
+ * if (i == 1)
+ * {
+ * cod[pos[j]] = 8191;
+ * }
+ * if (i == 0)
+ * {
+ * cod[pos[j]] = -8192;
+ * }
+ */
+
+ cod[pos[j]] = i * 16383 - 8192;
+
+ sign >>= 1;
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d4_17pf.h b/media/libstagefright/codecs/amrnb/dec/src/d4_17pf.h
new file mode 100644
index 0000000..5dc43f3
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d4_17pf.h
@@ -0,0 +1,119 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/d4_17pf.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the d4_17pf.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef d4_17pf_h
+#define d4_17pf_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void decode_4i40_17bits(
+ Word16 sign, /* i : signs of 4 pulses. */
+ Word16 index, /* i : Positions of the 4 pulses. */
+ Word16 cod[] /* o : algebraic (fixed) codebook excitation */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _d4_17PF_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d8_31pf.cpp b/media/libstagefright/codecs/amrnb/dec/src/d8_31pf.cpp
new file mode 100644
index 0000000..917c47f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d8_31pf.cpp
@@ -0,0 +1,626 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/d8_31pf.c
+ Functions:
+
+
+ Date: 01/28/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified to pass overflow flag through to basic math function.
+ The flag is passed back to the calling function by pointer reference.
+
+ Description: Per review comments...
+ (1) Removed include of "count.h" and "basic_op.h"
+ (2) Added includes of mult.h, shl.h, shr.h, add.h, sub.h, negate.h,
+ L_mult.h, and L_shr.h
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "d8_31pf.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define NB_PULSE 8 /* number of pulses */
+
+/* define values/representation for output codevector and sign */
+#define POS_CODE 8191
+#define NEG_CODE 8191
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: decompress10
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ MSBs -- Word16 -- MSB part of the index
+ LSBs -- Word16 -- LSB part of the index
+ index1 -- Word16 -- index for first pos in pos_index[]
+ index2 -- Word16 -- index for second pos in pos_index[]
+ index3 -- Word16 -- index for third pos in pos_index[]
+
+ Outputs:
+ pos_indx[] -- array of type Word16 -- position of 3 pulses (decompressed)
+
+ pOverflow Flag set when overflow occurs, pointer of type Flag *
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d8_31pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void decompress10(
+ Word16 MSBs, /* i : MSB part of the index */
+ Word16 LSBs, /* i : LSB part of the index */
+ Word16 index1, /* i : index for first pos in pos_index[] */
+ Word16 index2, /* i : index for second pos in pos_index[] */
+ Word16 index3, /* i : index for third pos in pos_index[] */
+ Word16 pos_indx[], /* o : position of 3 pulses (decompressed) */
+ Flag *pOverflow) /* o : Flag set when overflow occurs */
+{
+ Word16 ia;
+ Word16 ib;
+ Word16 ic;
+ Word32 tempWord32;
+
+ /*
+ pos_indx[index1] = ((MSBs-25*(MSBs/25))%5)*2 + (LSBs-4*(LSBs/4))%2;
+ pos_indx[index2] = ((MSBs-25*(MSBs/25))/5)*2 + (LSBs-4*(LSBs/4))/2;
+ pos_indx[index3] = (MSBs/25)*2 + LSBs/4;
+ */
+
+ if (MSBs > 124)
+ {
+ MSBs = 124;
+ }
+
+ ia =
+ mult(
+ MSBs,
+ 1311,
+ pOverflow);
+
+ tempWord32 =
+ L_mult(
+ ia,
+ 25,
+ pOverflow);
+
+
+ ia = (Word16)(MSBs - (tempWord32 >> 1));
+ ib =
+ mult(
+ ia,
+ 6554,
+ pOverflow);
+
+ tempWord32 =
+ L_mult(
+ ib,
+ 5,
+ pOverflow);
+
+ ib = ia - (Word16)(tempWord32 >> 1);
+
+ ib =
+ shl(
+ ib,
+ 1,
+ pOverflow);
+
+
+ ic = LSBs - ((LSBs >> 2) << 2);
+
+
+ pos_indx[index1] = ib + (ic & 1);
+
+
+ ib =
+ mult(
+ ia,
+ 6554,
+ pOverflow);
+
+ ib =
+ shl(
+ ib,
+ 1,
+ pOverflow);
+
+
+ pos_indx[index2] = ib + (ic >> 1);
+
+
+ ib = LSBs >> 2;
+
+ ic =
+ mult(
+ MSBs,
+ 1311,
+ pOverflow);
+
+ ic =
+ shl(
+ ic,
+ 1,
+ pOverflow);
+
+ pos_indx[index3] =
+ add(
+ ib,
+ ic,
+ pOverflow);
+
+ return;
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: decompress_code
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ indx[] -- array of type Word16 -- position and sign of
+ 8 pulses (compressed)
+
+ Outputs:
+ sign_indx[] -- array of type Word16 -- signs of 4 pulses (signs only)
+ pos_indx[] -- array of type Word16 -- position index of 8 pulses
+ (position only)
+ pOverflow pointer to type Flag -- Flag set when overflow occurs
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: decompression of the linear codewords to 4+three indeces
+ one bit from each pulse is made robust to errors by
+ minimizing the phase shift of a bit error.
+ 4 signs (one for each track)
+ i0,i4,i1 => one index (7+3) bits, 3 LSBs more robust
+ i2,i6,i5 => one index (7+3) bits, 3 LSBs more robust
+ i3,i7 => one index (5+2) bits, 2-3 LSbs more robust
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d8_31pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void decompress_code(
+ Word16 indx[], /* i : position and sign of 8 pulses (compressed) */
+ Word16 sign_indx[], /* o : signs of 4 pulses (signs only) */
+ Word16 pos_indx[], /* o : position index of 8 pulses (position only) */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word16 ia;
+ Word16 ib;
+ Word16 MSBs;
+ Word16 LSBs;
+ Word16 MSBs0_24;
+ Word32 tempWord32;
+
+ for (i = 0; i < NB_TRACK_MR102; i++)
+ {
+ sign_indx[i] = indx[i];
+ }
+
+ /*
+ First index: 10x10x10 -> 2x5x2x5x2x5-> 125x2x2x2 -> 7+1x3 bits
+ MSBs = indx[NB_TRACK]/8;
+ LSBs = indx[NB_TRACK]%8;
+ */
+ MSBs = indx[NB_TRACK_MR102] >> 3;
+
+ LSBs = indx[NB_TRACK_MR102] & 0x7;
+
+ decompress10(
+ MSBs,
+ LSBs,
+ 0,
+ 4,
+ 1,
+ pos_indx,
+ pOverflow);
+
+ /*
+ Second index: 10x10x10 -> 2x5x2x5x2x5-> 125x2x2x2 -> 7+1x3 bits
+ MSBs = indx[NB_TRACK+1]/8;
+ LSBs = indx[NB_TRACK+1]%8;
+ */
+ MSBs = indx[NB_TRACK_MR102+1] >> 3;
+
+ LSBs = indx[NB_TRACK_MR102+1] & 0x7;
+
+ decompress10(
+ MSBs,
+ LSBs,
+ 2,
+ 6,
+ 5,
+ pos_indx,
+ pOverflow);
+
+ /*
+ Third index: 10x10 -> 2x5x2x5-> 25x2x2 -> 5+1x2 bits
+ MSBs = indx[NB_TRACK+2]/4;
+ LSBs = indx[NB_TRACK+2]%4;
+ MSBs0_24 = (MSBs*25+12)/32;
+ if ((MSBs0_24/5)%2==1)
+ pos_indx[3] = (4-(MSBs0_24%5))*2 + LSBs%2;
+ else
+ pos_indx[3] = (MSBs0_24%5)*2 + LSBs%2;
+ pos_indx[7] = (MSBs0_24/5)*2 + LSBs/2;
+ */
+
+ MSBs = indx[NB_TRACK_MR102+2] >> 2;
+
+ LSBs = indx[NB_TRACK_MR102+2] & 0x3;
+
+ tempWord32 =
+ L_mult(
+ MSBs,
+ 25,
+ pOverflow);
+
+ ia =
+ (Word16)
+ L_shr(
+ tempWord32,
+ 1,
+ pOverflow);
+
+ ia += 12;
+
+ MSBs0_24 = ia >> 5;
+
+
+ ia =
+ mult(
+ MSBs0_24,
+ 6554,
+ pOverflow);
+
+ ia &= 1;
+
+
+ ib =
+ mult(
+ MSBs0_24,
+ 6554,
+ pOverflow);
+
+ tempWord32 =
+ L_mult(
+ ib,
+ 5,
+ pOverflow);
+
+
+ ib = MSBs0_24 - (Word16)(tempWord32 >> 1);
+
+ if (ia == 1)
+ {
+ ib = 4 - ib;
+
+ }
+
+
+ ib =
+ shl(
+ ib,
+ 1,
+ pOverflow);
+
+ ia = LSBs & 0x1;
+
+ pos_indx[3] =
+ add(
+ ib,
+ ia,
+ pOverflow);
+
+ ia =
+ mult(
+ MSBs0_24,
+ 6554,
+ pOverflow);
+
+ ia =
+ shl(
+ ia,
+ 1,
+ pOverflow);
+
+ pos_indx[7] = ia + (LSBs >> 1);
+
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: dec_8i40_31bits
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ index array of type Word16 -- index of 8 pulses (sign+position)
+
+ Outputs:
+ cod array of type Word16 -- algebraic (fixed) codebook excitation
+ pOverflow pointer to type Flag -- Flag set when overflow occurs
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Builds the innovative codevector from the received
+ index of algebraic codebook.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d8_31pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void dec_8i40_31bits(
+ Word16 index[], /* i : index of 8 pulses (sign+position) */
+ Word16 cod[], /* o : algebraic (fixed) codebook excitation */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word16 j;
+ Word16 pos1;
+ Word16 pos2;
+ Word16 sign;
+
+ Word16 linear_signs[NB_TRACK_MR102];
+ Word16 linear_codewords[NB_PULSE];
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ cod[i] = 0;
+ }
+
+ decompress_code(
+ index,
+ linear_signs,
+ linear_codewords,
+ pOverflow);
+
+ /* decode the positions and signs of pulses and build the codeword */
+ for (j = 0; j < NB_TRACK_MR102; j++) /* NB_TRACK_MR102 = 4 */
+ {
+ /* position of pulse "j" */
+
+ pos1 = (linear_codewords[j] << 2) + j;
+
+
+ if (linear_signs[j] == 0)
+ {
+ sign = POS_CODE; /* +1.0 */
+ }
+ else
+ {
+ sign = -NEG_CODE; /* -1.0 */
+ }
+
+ if (pos1 < L_SUBFR)
+ {
+ cod[pos1] = sign; /* avoid buffer overflow */
+ }
+
+ /* compute index i */
+ /* position of pulse "j+4" */
+
+ pos2 = (linear_codewords[j + 4] << 2) + j;
+
+
+ if (pos2 < pos1)
+ {
+ sign = negate(sign);
+ }
+
+ if (pos2 < L_SUBFR)
+ {
+ cod[pos2] += sign; /* avoid buffer overflow */
+ }
+
+
+ } /* for (j = 0; j < NB_TRACK_MR102; j++) */
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d8_31pf.h b/media/libstagefright/codecs/amrnb/dec/src/d8_31pf.h
new file mode 100644
index 0000000..162685f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d8_31pf.h
@@ -0,0 +1,120 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/d2_9pf.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the d8_31pf.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef d8_31pf_h
+#define d8_31pf_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void dec_8i40_31bits(
+ Word16 index[], /* i : index of 8 pulses (sign+position) */
+ Word16 cod[], /* o : algebraic (fixed) codebook excitation */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _d8_31PF_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d_gain_c.cpp b/media/libstagefright/codecs/amrnb/dec/src/d_gain_c.cpp
new file mode 100644
index 0000000..b6c62f8
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d_gain_c.cpp
@@ -0,0 +1,254 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/d_gain_c.c
+ Functions: d_gain_c
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated include files and intput/output section. Changed .tab
+ files to .c files.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Description:
+
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pred_state = pointer to sturcture type gc_predState. MA predictor state
+ mode = AMR mode (MR795 or MR122) of type enum Mode
+ index = received quantization index of type Word16
+ code[] = pointer to innovation codevector of type Word16
+ pOverflow= pointer to value indicating existence of overflow (Flag)
+
+ Outputs:
+ pred_state = pointer to sturcture type gc_predState. MA predictor state
+ gain_code = pointer to decoded innovation gain of type Word16
+ pOverflow = 1 if there is an overflow else it is zero.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function : d_gain_code
+ Purpose : Decode the fixed codebook gain using the received index.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d_gain_c.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "d_gain_c.h"
+#include "typedef.h"
+#include "mode.h"
+
+#include "oper_32b.h"
+#include "cnst.h"
+#include "log2.h"
+#include "pow2.h"
+#include "gc_pred.h"
+
+#include "basic_op.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL FUNCTION REFERENCES
+ ; Declare functions defined elsewhere and referenced in this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 qua_gain_code[];
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void d_gain_code(
+ gc_predState *pred_state, /* i/o : MA predictor state */
+ enum Mode mode, /* i : AMR mode (MR795 or MR122) */
+ Word16 index, /* i : received quantization index */
+ Word16 code[], /* i : innovation codevector */
+ Word16 *gain_code, /* o : decoded innovation gain */
+ Flag *pOverflow
+)
+{
+ Word16 gcode0, exp, frac;
+ const Word16 *p;
+ Word16 qua_ener_MR122, qua_ener;
+ Word16 exp_inn_en;
+ Word16 frac_inn_en;
+ Word32 L_tmp;
+ Word16 tbl_tmp;
+ Word16 temp;
+ /*-------------- Decode codebook gain ---------------*/
+
+ /*-------------------------------------------------------------------*
+ * predict codebook gain *
+ * ~~~~~~~~~~~~~~~~~~~~~ *
+ * gc0 = Pow2(int(d)+frac(d)) *
+ * = 2^exp + 2^frac *
+ * *
+ *-------------------------------------------------------------------*/
+
+ gc_pred(pred_state, mode, code, &exp, &frac,
+ &exp_inn_en, &frac_inn_en, pOverflow);
+
+ index &= 31; /* index < 32, to avoid buffer overflow */
+ tbl_tmp = index + (index << 1);
+
+ p = &qua_gain_code[tbl_tmp];
+
+ /* Different scalings between MR122 and the other modes */
+ temp = sub((Word16)mode, (Word16)MR122, pOverflow);
+ if (temp == 0)
+ {
+ gcode0 = (Word16)(Pow2(exp, frac, pOverflow)); /* predicted gain */
+ gcode0 = shl(gcode0, 4, pOverflow);
+ *gain_code = shl(mult(gcode0, *p++, pOverflow), 1, pOverflow);
+ }
+ else
+ {
+ gcode0 = (Word16)(Pow2(14, frac, pOverflow));
+ L_tmp = L_mult(*p++, gcode0, pOverflow);
+ L_tmp = L_shr(L_tmp, sub(9, exp, pOverflow), pOverflow);
+ *gain_code = extract_h(L_tmp); /* Q1 */
+ }
+
+ /*-------------------------------------------------------------------*
+ * update table of past quantized energies *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ *-------------------------------------------------------------------*/
+ qua_ener_MR122 = *p++;
+ qua_ener = *p++;
+ gc_pred_update(pred_state, qua_ener_MR122, qua_ener);
+
+ return;
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d_gain_p.cpp b/media/libstagefright/codecs/amrnb/dec/src/d_gain_p.cpp
new file mode 100644
index 0000000..99446db
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d_gain_p.cpp
@@ -0,0 +1,192 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/d_gain_p.c
+ Functions: d_gain_p
+
+ Date: 01/31/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ (1) Removed extra includes
+ (2) Replaced function calls to basic math operations with ANSI C standard
+ mathemtical operations.
+ (3) Placed code in the proper software template.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Description:
+
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ mode -- enumerated type -- AMR mode
+ index -- Word16 -- index of quantization
+ Outputs:
+ None
+
+ Returns:
+ Word16 gain -- (Q14)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function : d_gain_pitch
+ Purpose : Decodes the pitch gain using the received index.
+ output is in Q14
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d_gain_p.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "d_gain_p.h"
+#include "typedef.h"
+#include "mode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL FUNCTION REFERENCES
+ ; Declare functions defined elsewhere and referenced in this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 qua_gain_pitch[];
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Word16 d_gain_pitch( /* return value: gain (Q14) */
+ enum Mode mode, /* i : AMR mode */
+ Word16 index /* i : index of quantization */
+)
+{
+ Word16 gain;
+
+ gain = qua_gain_pitch[index];
+
+ if (mode == MR122)
+ {
+ /* clear 2 LSBits */
+ gain &= 0xFFFC;
+ }
+
+ return gain;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d_plsf.cpp b/media/libstagefright/codecs/amrnb/dec/src/d_plsf.cpp
new file mode 100644
index 0000000..138193f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d_plsf.cpp
@@ -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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/d_plsf.c
+ Functions:
+
+
+ Date: 04/14/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Removed the functions d_plsf_init and d_plsf_exit.
+ The d_plsf related structure is no longer dynamically allocated.
+
+ Description: Removed q_plsf_5.tab from Include section and added
+ q_plsf_5_tbl.h to Include section. Changed "mean_lsf"
+ to "mean_lsf_5" in D_plsf_reset().
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ common part (reset) of LSF decoder
+ module (rest in d_plsf_3.c and d_plsf_5.c)
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "copy.h"
+#include "d_plsf.h"
+#include "q_plsf_5_tbl.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: D_plsf_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to structure of type D_plsf_reset
+
+ Outputs:
+ fields of the structure pointed to by state is initialized to zero
+
+ Returns:
+ return_value = 0, if reset was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Resets state memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d_plsf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int D_plsf_reset (D_plsfState *state)
+{
+ Word16 i;
+
+ if (state == (D_plsfState *) NULL){
+ // fprintf(stderr, "D_plsf_reset: invalid parameter\n");
+ return -1;
+ }
+
+ for (i = 0; i < M; i++){
+ state->past_r_q[i] = 0; // Past quantized prediction error
+ }
+
+ // Past dequantized lsfs
+ Copy(mean_lsf, &state->past_lsf_q[0], M);
+
+ return 0;
+}
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 D_plsf_reset(D_plsfState *state)
+{
+ Word16 i;
+
+ if (state == (D_plsfState *) NULL)
+ {
+ /* fprintf(stderr, "D_plsf_reset: invalid parameter\n"); */
+ return -1;
+ }
+
+ for (i = 0; i < M; i++)
+ {
+ state->past_r_q[i] = 0; /* Past quantized prediction error */
+ }
+
+ /* Past dequantized lsfs */
+ Copy(mean_lsf_5, &state->past_lsf_q[0], M);
+
+ return 0;
+
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d_plsf_3.cpp b/media/libstagefright/codecs/amrnb/dec/src/d_plsf_3.cpp
new file mode 100644
index 0000000..7b31d04
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d_plsf_3.cpp
@@ -0,0 +1,496 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/d_plsf_3.c
+ Functions: D_plsf_3
+
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- Pointer to type struct D_plsfState
+ mode -- enum Mode -- coder mode
+ bfi -- Word16 -- bad frame indicator (set to 1 if a bad frame is received)
+ indice -- Pointer to type Word16 -- quantization indices of
+ 3 submatrices, Q0
+
+ Outputs:
+ st -- Pointer to type struct D_plsfState
+ lsp1_q -- Pointer to type Word16 -- quantized 1st LSP vector Q15
+ pOverflow -- Pointer to type Flag -- Flag set when overflow occurs
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Decodes the LSP parameters using the received quantization
+ indices.1st order MA prediction and split by 3 vector
+ quantization (split-VQ)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d_plsf_3.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "d_plsf.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "lsp_lsf.h"
+#include "reorder.h"
+#include "copy.h"
+#include "q_plsf_3_tbl.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define ALPHA 29491 /* ALPHA -> 0.9 */
+#define ONE_ALPHA 3277 /* ONE_ALPHA-> (1.0-ALPHA) */
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void D_plsf_3(
+ D_plsfState *st, /* i/o: State struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 bfi, /* i : bad frame indicator (set to 1 if a */
+ /* bad frame is received) */
+ Word16 * indice, /* i : quantization indices of 3 submatrices, Q0 */
+ Word16 * lsp1_q, /* o : quantized 1st LSP vector, Q15 */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word16 temp;
+ Word16 index;
+
+ Word16 lsf1_r[M];
+ Word16 lsf1_q[M];
+
+ if (bfi != 0) /* if bad frame */
+ {
+ /* use the past LSFs slightly shifted towards their mean */
+
+ for (i = 0; i < M; i++)
+ {
+ /* lsfi_q[i] = ALPHA*past_lsf_q[i] + ONE_ALPHA*mean_lsf[i]; */
+ temp =
+ mult(
+ st->past_lsf_q[i],
+ ALPHA,
+ pOverflow);
+
+ index =
+ mult(
+ mean_lsf_3[i],
+ ONE_ALPHA,
+ pOverflow);
+
+ lsf1_q[i] =
+ add(
+ index,
+ temp,
+ pOverflow);
+ }
+
+ /* estimate past quantized residual to be used in next frame */
+ if (mode != MRDTX)
+ {
+ for (i = 0; i < M; i++)
+ {
+ /* temp = mean_lsf[i] + past_r2_q[i] * PRED_FAC; */
+
+ temp =
+ mult(
+ st->past_r_q[i],
+ pred_fac_3[i],
+ pOverflow);
+
+ temp =
+ add(
+ mean_lsf_3[i],
+ temp,
+ pOverflow);
+
+ st->past_r_q[i] =
+ sub(
+ lsf1_q[i],
+ temp,
+ pOverflow);
+ }
+
+ } /* if (mode == MRDTX) */
+ else
+ {
+ for (i = 0; i < M; i++)
+ {
+ /* temp = mean_lsf[i] + past_r2_q[i]; */
+
+ temp =
+ add(
+ mean_lsf_3[i],
+ st->past_r_q[i],
+ pOverflow);
+
+ st->past_r_q[i] =
+ sub(
+ lsf1_q[i],
+ temp,
+ pOverflow);
+ }
+ }
+
+ } /* if (bfi != 0) */
+
+ else /* if good LSFs received */
+ {
+
+ Word16 index_limit_1 = 0;
+ Word16 index_limit_2 = (DICO2_SIZE - 1) * 3;
+ Word16 index_limit_3 = 0;
+
+ const Word16 *p_cb1;
+ const Word16 *p_cb2;
+ const Word16 *p_cb3;
+ const Word16 *p_dico;
+
+
+ p_cb2 = dico2_lsf_3; /* size DICO2_SIZE*3 */
+
+ if ((mode == MR475) || (mode == MR515))
+ { /* MR475, MR515 */
+ p_cb1 = dico1_lsf_3; /* size DICO1_SIZE*3 */
+ p_cb3 = mr515_3_lsf; /* size MR515_3_SIZE*4 */
+
+ index_limit_1 = (DICO1_SIZE - 1) * 3;
+ index_limit_3 = (MR515_3_SIZE - 1) * 4;
+
+ }
+ else if (mode == MR795)
+ { /* MR795 */
+ p_cb1 = mr795_1_lsf; /* size MR795_1_SIZE*3 */
+ p_cb3 = dico3_lsf_3; /* size DICO3_SIZE*4 */
+
+ index_limit_1 = (MR795_1_SIZE - 1) * 3;
+ index_limit_3 = (DICO3_SIZE - 1) * 4;
+
+ }
+ else
+ { /* MR59, MR67, MR74, MR102, MRDTX */
+ p_cb1 = dico1_lsf_3; /* size DICO1_SIZE*3 */
+ p_cb3 = dico3_lsf_3; /* size DICO3_SIZE*4 */
+
+ index_limit_1 = (DICO1_SIZE - 1) * 3;
+ index_limit_3 = (DICO3_SIZE - 1) * 4;
+
+ }
+
+ /* decode prediction residuals from 3 received indices */
+
+ index = *indice++;
+
+ /* temp = 3*index; */
+ temp = index + (index << 1);
+
+ if (temp > index_limit_1)
+ {
+ temp = index_limit_1; /* avoid buffer overrun */
+ }
+
+ p_dico = &p_cb1[temp];
+
+ lsf1_r[0] = *p_dico++;
+ lsf1_r[1] = *p_dico++;
+ lsf1_r[2] = *p_dico++;
+
+ index = *indice++;
+
+ if (mode == MR475 || mode == MR515)
+ { /* MR475, MR515 only using every second entry */
+ index <<= 1;
+ }
+
+ /* temp = 3*index */
+ temp = index + (index << 1);
+
+ if (temp > index_limit_2)
+ {
+ temp = index_limit_2; /* avoid buffer overrun */
+ }
+
+ p_dico = &p_cb2[temp];
+
+ lsf1_r[3] = *p_dico++;
+ lsf1_r[4] = *p_dico++;
+ lsf1_r[5] = *p_dico++;
+
+ index = *indice++;
+
+ temp = index << 2;
+
+ if (temp > index_limit_3)
+ {
+ temp = index_limit_3; /* avoid buffer overrun */
+ }
+
+
+ p_dico = &p_cb3[temp];
+
+ lsf1_r[6] = *p_dico++;
+ lsf1_r[7] = *p_dico++;
+ lsf1_r[8] = *p_dico++;
+ lsf1_r[9] = *p_dico++;
+
+ /* Compute quantized LSFs and update the past quantized residual */
+
+ if (mode != MRDTX)
+ {
+ for (i = 0; i < M; i++)
+ {
+ temp =
+ mult(
+ st->past_r_q[i],
+ pred_fac_3[i],
+ pOverflow);
+
+ temp =
+ add(
+ mean_lsf_3[i],
+ temp,
+ pOverflow);
+
+ lsf1_q[i] =
+ add(
+ lsf1_r[i],
+ temp,
+ pOverflow);
+
+ st->past_r_q[i] = lsf1_r[i];
+ }
+ }
+ else
+ {
+ for (i = 0; i < M; i++)
+ {
+ temp =
+ add(
+ mean_lsf_3[i],
+ st->past_r_q[i],
+ pOverflow);
+
+ lsf1_q[i] =
+ add(
+ lsf1_r[i],
+ temp,
+ pOverflow);
+
+ st->past_r_q[i] = lsf1_r[i];
+ }
+ }
+
+ }
+
+ /* verification that LSFs has minimum distance of LSF_GAP Hz */
+
+ Reorder_lsf(
+ lsf1_q,
+ LSF_GAP,
+ M,
+ pOverflow);
+
+ Copy(
+ lsf1_q,
+ st->past_lsf_q,
+ M);
+
+ /* convert LSFs to the cosine domain */
+
+ Lsf_lsp(
+ lsf1_q,
+ lsp1_q,
+ M,
+ pOverflow);
+
+ return;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Init_D_plsf_3
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type D_plsfState
+ index = Word16, past_rq_init[] index [0, 7]
+
+ Outputs:
+ st = pointer to a structure of type D_plsfState
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function initializes the D_plsfState structure.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d_plsf_3.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void Init_D_plsf_3(
+ D_plsfState *st, /* i/o: State struct */
+ Word16 index /* i : past_rq_init[] index [0, 7] */)
+{
+ Copy(
+ &past_rq_init[index * M],
+ st->past_r_q,
+ M);
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/d_plsf_5.cpp b/media/libstagefright/codecs/amrnb/dec/src/d_plsf_5.cpp
new file mode 100644
index 0000000..08b690d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/d_plsf_5.cpp
@@ -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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/d_plsf_5.c
+
+ Date: 04/24/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Made changes based on review meeting.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Updated to accept new parameter, Flag *pOverflow.
+
+ Description:
+ (1) Removed "count.h" and "basic_op.h" and replaced with individual include
+ files (add.h, sub.h, etc.)
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "d_plsf.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "lsp_lsf.h"
+#include "reorder.h"
+#include "cnst.h"
+#include "copy.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+ /* ALPHA -> 0.95 */
+ /* ONE_ALPHA-> (1.0-ALPHA) */
+#define ALPHA 31128
+#define ONE_ALPHA 1639
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ /* These tables are defined in q_plsf_5_tbl.c */
+ extern const Word16 mean_lsf_5[];
+ extern const Word16 dico1_lsf_5[];
+ extern const Word16 dico2_lsf_5[];
+ extern const Word16 dico3_lsf_5[];
+ extern const Word16 dico4_lsf_5[];
+ extern const Word16 dico5_lsf_5[];
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: D_plsf_5
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type D_plsfState
+ bfi = bad frame indicator; set to 1 if a bad frame is received (Word16)
+ indice = pointer to quantization indices of 5 submatrices (Word16)
+ lsp1_q = pointer to the quantized 1st LSP vector (Word16)
+ lsp2_q = pointer to the quantized 2nd LSP vector (Word16)
+
+ Outputs:
+ lsp1_q points to the updated quantized 1st LSP vector
+ lsp2_q points to the updated quantized 2nd LSP vector
+ Flag *pOverflow -- Flag set when overflow occurs.
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function decodes the 2 sets of LSP parameters in a frame using the
+ received quantization indices.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ d_plsf_5.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int D_plsf_5 (
+ D_plsfState *st, // i/o: State variables
+ Word16 bfi, // i : bad frame indicator (set to 1 if a bad
+ frame is received)
+ Word16 *indice, // i : quantization indices of 5 submatrices, Q0
+ Word16 *lsp1_q, // o : quantized 1st LSP vector (M), Q15
+ Word16 *lsp2_q // o : quantized 2nd LSP vector (M), Q15
+)
+{
+ Word16 i;
+ const Word16 *p_dico;
+ Word16 temp, sign;
+ Word16 lsf1_r[M], lsf2_r[M];
+ Word16 lsf1_q[M], lsf2_q[M];
+
+ if (bfi != 0) // if bad frame
+ {
+ // use the past LSFs slightly shifted towards their mean
+
+ for (i = 0; i < M; i++)
+ {
+ // lsfi_q[i] = ALPHA*st->past_lsf_q[i] + ONE_ALPHA*mean_lsf[i];
+
+ lsf1_q[i] = add (mult (st->past_lsf_q[i], ALPHA),
+ mult (mean_lsf[i], ONE_ALPHA));
+
+ lsf2_q[i] = lsf1_q[i];
+ }
+
+ // estimate past quantized residual to be used in next frame
+
+ for (i = 0; i < M; i++)
+ {
+ // temp = mean_lsf[i] + st->past_r_q[i] * LSP_PRED_FAC_MR122;
+
+ temp = add (mean_lsf[i], mult (st->past_r_q[i],
+ LSP_PRED_FAC_MR122));
+
+ st->past_r_q[i] = sub (lsf2_q[i], temp);
+ }
+ }
+ else
+ // if good LSFs received
+ {
+ // decode prediction residuals from 5 received indices
+
+ p_dico = &dico1_lsf[shl (indice[0], 2)];
+ lsf1_r[0] = *p_dico++;
+ lsf1_r[1] = *p_dico++;
+ lsf2_r[0] = *p_dico++;
+ lsf2_r[1] = *p_dico++;
+
+ p_dico = &dico2_lsf[shl (indice[1], 2)];
+ lsf1_r[2] = *p_dico++;
+ lsf1_r[3] = *p_dico++;
+ lsf2_r[2] = *p_dico++;
+ lsf2_r[3] = *p_dico++;
+
+ sign = indice[2] & 1;
+ i = shr (indice[2], 1);
+ p_dico = &dico3_lsf[shl (i, 2)];
+
+ if (sign == 0)
+ {
+ lsf1_r[4] = *p_dico++;
+ lsf1_r[5] = *p_dico++;
+ lsf2_r[4] = *p_dico++;
+ lsf2_r[5] = *p_dico++;
+ }
+ else
+ {
+ lsf1_r[4] = negate (*p_dico++);
+ lsf1_r[5] = negate (*p_dico++);
+ lsf2_r[4] = negate (*p_dico++);
+ lsf2_r[5] = negate (*p_dico++);
+ }
+
+ p_dico = &dico4_lsf[shl (indice[3], 2)];
+ lsf1_r[6] = *p_dico++;
+ lsf1_r[7] = *p_dico++;
+ lsf2_r[6] = *p_dico++;
+ lsf2_r[7] = *p_dico++;
+
+ p_dico = &dico5_lsf[shl (indice[4], 2)];
+ lsf1_r[8] = *p_dico++;
+ lsf1_r[9] = *p_dico++;
+ lsf2_r[8] = *p_dico++;
+ lsf2_r[9] = *p_dico++;
+
+ // Compute quantized LSFs and update the past quantized residual
+ for (i = 0; i < M; i++)
+ {
+ temp = add (mean_lsf[i], mult (st->past_r_q[i],
+ LSP_PRED_FAC_MR122));
+ lsf1_q[i] = add (lsf1_r[i], temp);
+ lsf2_q[i] = add (lsf2_r[i], temp);
+ st->past_r_q[i] = lsf2_r[i];
+ }
+ }
+
+ // verification that LSFs have minimum distance of LSF_GAP Hz
+
+ Reorder_lsf (lsf1_q, LSF_GAP, M);
+ Reorder_lsf (lsf2_q, LSF_GAP, M);
+
+ Copy (lsf2_q, st->past_lsf_q, M);
+
+ // convert LSFs to the cosine domain
+
+ Lsf_lsp (lsf1_q, lsp1_q, M);
+ Lsf_lsp (lsf2_q, lsp2_q, M);
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void D_plsf_5(
+ D_plsfState *st, /* i/o: State variables */
+ Word16 bfi, /* i : bad frame indicator (set to 1 if a bad
+ frame is received) */
+ Word16 *indice, /* i : quantization indices of 5 submatrices, Q0 */
+ Word16 *lsp1_q, /* o : quantized 1st LSP vector (M), Q15 */
+ Word16 *lsp2_q, /* o : quantized 2nd LSP vector (M), Q15 */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ register Word16 i;
+ Word16 temp;
+ Word16 sign;
+
+ const Word16 *p_dico;
+
+ Word16 lsf1_r[M];
+ Word16 lsf2_r[M];
+ Word16 lsf1_q[M];
+ Word16 lsf2_q[M];
+
+ if (bfi != 0) /* if bad frame */
+ {
+ /* use the past LSFs slightly shifted towards their mean */
+
+ for (i = 0; i < M; i++)
+ {
+ /*
+ * lsfi_q[i] = ALPHA*st->past_lsf_q[i] +
+ * ONE_ALPHA*mean_lsf[i];
+ */
+
+ temp =
+ mult(
+ st->past_lsf_q[i],
+ ALPHA,
+ pOverflow);
+
+ sign =
+ mult(
+ *(mean_lsf_5 + i),
+ ONE_ALPHA,
+ pOverflow);
+
+ *(lsf1_q + i) =
+ add(
+ sign,
+ temp,
+ pOverflow);
+
+ *(lsf2_q + i) = *(lsf1_q + i);
+
+ /*
+ * estimate past quantized residual to be used in
+ * next frame
+ */
+
+ /*
+ * temp = mean_lsf[i] +
+ * st->past_r_q[i] * LSP_PRED_FAC_MR122;
+ */
+
+ temp =
+ mult(
+ st->past_r_q[i],
+ LSP_PRED_FAC_MR122,
+ pOverflow);
+
+ temp =
+ add(
+ *(mean_lsf_5 + i),
+ temp,
+ pOverflow);
+
+ st->past_r_q[i] =
+ sub(
+ *(lsf2_q + i),
+ temp,
+ pOverflow);
+ }
+ }
+ else
+ /* if good LSFs received */
+ {
+ /* decode prediction residuals from 5 received indices */
+
+ temp =
+ shl(
+ *(indice),
+ 2,
+ pOverflow);
+
+ p_dico = &dico1_lsf_5[temp];
+
+ *(lsf1_r + 0) = *p_dico++;
+ *(lsf1_r + 1) = *p_dico++;
+ *(lsf2_r + 0) = *p_dico++;
+ *(lsf2_r + 1) = *p_dico++;
+
+ temp =
+ shl(
+ *(indice + 1),
+ 2,
+ pOverflow);
+
+ p_dico = &dico2_lsf_5[temp];
+
+ *(lsf1_r + 2) = *p_dico++;
+ *(lsf1_r + 3) = *p_dico++;
+ *(lsf2_r + 2) = *p_dico++;
+ *(lsf2_r + 3) = *p_dico++;
+
+ sign = *(indice + 2) & 1;
+
+ if (*(indice + 2) < 0)
+ {
+ i = ~(~(*(indice + 2)) >> 1);
+ }
+ else
+ {
+ i = *(indice + 2) >> 1;
+ }
+
+ temp =
+ shl(
+ i,
+ 2,
+ pOverflow);
+
+ p_dico = &dico3_lsf_5[temp];
+
+ if (sign == 0)
+ {
+ *(lsf1_r + 4) = *p_dico++;
+ *(lsf1_r + 5) = *p_dico++;
+ *(lsf2_r + 4) = *p_dico++;
+ *(lsf2_r + 5) = *p_dico++;
+ }
+ else
+ {
+ *(lsf1_r + 4) = negate(*p_dico++);
+ *(lsf1_r + 5) = negate(*p_dico++);
+ *(lsf2_r + 4) = negate(*p_dico++);
+ *(lsf2_r + 5) = negate(*p_dico++);
+ }
+
+ temp =
+ shl(
+ *(indice + 3),
+ 2,
+ pOverflow);
+
+ p_dico = &dico4_lsf_5[temp];
+
+ *(lsf1_r + 6) = *p_dico++;
+ *(lsf1_r + 7) = *p_dico++;
+ *(lsf2_r + 6) = *p_dico++;
+ *(lsf2_r + 7) = *p_dico++;
+
+ temp =
+ shl(
+ *(indice + 4),
+ 2,
+ pOverflow);
+
+ p_dico = &dico5_lsf_5[temp];
+
+ *(lsf1_r + 8) = *p_dico++;
+ *(lsf1_r + 9) = *p_dico++;
+ *(lsf2_r + 8) = *p_dico++;
+ *(lsf2_r + 9) = *p_dico++;
+
+ /* Compute quantized LSFs and update the past quantized
+ residual */
+ for (i = 0; i < M; i++)
+ {
+ temp =
+ mult(
+ st->past_r_q[i],
+ LSP_PRED_FAC_MR122,
+ pOverflow);
+
+ temp =
+ add(
+ *(mean_lsf_5 + i),
+ temp,
+ pOverflow);
+
+ *(lsf1_q + i) =
+ add(
+ *(lsf1_r + i),
+ temp,
+ pOverflow);
+
+ *(lsf2_q + i) =
+ add(
+ *(lsf2_r + i),
+ temp,
+ pOverflow);
+
+ st->past_r_q[i] = *(lsf2_r + i);
+ }
+ }
+
+ /* verification that LSFs have minimum distance of LSF_GAP Hz */
+
+ Reorder_lsf(
+ lsf1_q,
+ LSF_GAP,
+ M,
+ pOverflow);
+
+ Reorder_lsf(
+ lsf2_q,
+ LSF_GAP,
+ M,
+ pOverflow);
+
+ Copy(
+ lsf2_q,
+ st->past_lsf_q,
+ M);
+
+ /* convert LSFs to the cosine domain */
+
+ Lsf_lsp(
+ lsf1_q,
+ lsp1_q,
+ M,
+ pOverflow);
+
+ Lsf_lsp(
+ lsf2_q,
+ lsp2_q,
+ M,
+ pOverflow);
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_amr.cpp b/media/libstagefright/codecs/amrnb/dec/src/dec_amr.cpp
new file mode 100644
index 0000000..be15475
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/dec_amr.cpp
@@ -0,0 +1,2374 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+ Pathname: ./audio/gsm-amr/c/src/dec_amr.c
+ Funtions: Decoder_amr_init
+ Decoder_amr_reset
+ Decoder_amr
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the function used to decode one speech frame using a given
+ codec mode. The functions used to initialize, reset, and exit are also
+ included in this file.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <string.h>
+
+#include "dec_amr.h"
+#include "typedef.h"
+#include "cnst.h"
+#include "copy.h"
+#include "set_zero.h"
+#include "syn_filt.h"
+#include "d_plsf.h"
+#include "agc.h"
+#include "int_lpc.h"
+#include "dec_gain.h"
+#include "dec_lag3.h"
+#include "dec_lag6.h"
+#include "d2_9pf.h"
+#include "d2_11pf.h"
+#include "d3_14pf.h"
+#include "d4_17pf.h"
+#include "d8_31pf.h"
+#include "d1035pf.h"
+#include "pred_lt.h"
+#include "d_gain_p.h"
+#include "d_gain_c.h"
+#include "dec_gain.h"
+#include "ec_gains.h"
+#include "ph_disp.h"
+#include "c_g_aver.h"
+#include "int_lsf.h"
+#include "lsp_lsf.h"
+#include "lsp_avg.h"
+#include "bgnscd.h"
+#include "ex_ctrl.h"
+#include "sqrt_l.h"
+#include "frame.h"
+#include "bitno_tab.h"
+#include "b_cn_cod.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Decoder_amr_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a pointer to structures of type Decoder_amrState
+
+ Outputs:
+ structure pointed to by the pointer which is pointed to by state is
+ initialized to each field's initial values
+
+ state pointer points to the address of the memory allocated by
+ Decoder_amr_init function
+
+ Returns:
+ return_value = 0, if the initialization was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function allocates and initializes state memory used by the Decoder_amr
+ function. It stores the pointer to the filter status structure in state. This
+ pointer has to be passed to Decoder_amr in each call. The function returns
+ 0, if initialization was successful and -1, otherwise.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dec_amr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Decoder_amr_init (Decoder_amrState **state)
+{
+ Decoder_amrState* s;
+ Word16 i;
+
+ if (state == (Decoder_amrState **) NULL){
+ fprintf(stderr, "Decoder_amr_init: invalid parameter\n");
+ return -1;
+ }
+ *state = NULL;
+
+ // allocate memory
+ if ((s= (Decoder_amrState *) malloc(sizeof(Decoder_amrState))) == NULL){
+ fprintf(stderr, "Decoder_amr_init: can not malloc state structure\n");
+ return -1;
+ }
+
+ s->T0_lagBuff = 40;
+ s->inBackgroundNoise = 0;
+ s->voicedHangover = 0;
+ for (i = 0; i < 9; i++)
+ s->ltpGainHistory[i] = 0;
+
+ s->lsfState = NULL;
+ s->ec_gain_p_st = NULL;
+ s->ec_gain_c_st = NULL;
+ s->pred_state = NULL;
+ s->ph_disp_st = NULL;
+ s->dtxDecoderState = NULL;
+
+ if (D_plsf_init(&s->lsfState) ||
+ ec_gain_pitch_init(&s->ec_gain_p_st) ||
+ ec_gain_code_init(&s->ec_gain_c_st) ||
+ gc_pred_init(&s->pred_state) ||
+ Cb_gain_average_init(&s->Cb_gain_averState) ||
+ lsp_avg_init(&s->lsp_avg_st) ||
+ Bgn_scd_init(&s->background_state) ||
+ ph_disp_init(&s->ph_disp_st) ||
+ dtx_dec_init(&s->dtxDecoderState)) {
+ Decoder_amr_exit(&s);
+ return -1;
+ }
+
+ Decoder_amr_reset(s, (enum Mode)0);
+ *state = s;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Decoder_amr_init(Decoder_amrState *s)
+{
+ Word16 i;
+
+ if (s == (Decoder_amrState *) NULL)
+ {
+ /* fprint(stderr, "Decoder_amr_init: invalid parameter\n"); */
+ return(-1);
+ }
+
+ s->T0_lagBuff = 40;
+ s->inBackgroundNoise = 0;
+ s->voicedHangover = 0;
+
+ /* Initialize overflow Flag */
+
+ s->overflow = 0;
+
+ for (i = 0; i < LTP_GAIN_HISTORY_LEN; i++)
+ {
+ s->ltpGainHistory[i] = 0;
+ }
+
+ D_plsf_reset(&s->lsfState);
+ ec_gain_pitch_reset(&s->ec_gain_p_st);
+ ec_gain_code_reset(&s->ec_gain_c_st);
+ Cb_gain_average_reset(&s->Cb_gain_averState);
+ lsp_avg_reset(&s->lsp_avg_st);
+ Bgn_scd_reset(&s->background_state);
+ ph_disp_reset(&s->ph_disp_st);
+ dtx_dec_reset(&s->dtxDecoderState);
+ gc_pred_reset(&s->pred_state);
+
+ Decoder_amr_reset(s, MR475);
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Decoder_amr_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a structure of type Decoder_amrState
+ mode = codec mode (enum Mode)
+
+ Outputs:
+ structure pointed to by state is initialized to its reset value
+
+ Returns:
+ return_value = 0, if reset was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function resets the state memory used by the Decoder_amr function. It
+ returns a 0, if reset was successful and -1, otherwise.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dec_amr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Decoder_amr_reset (Decoder_amrState *state, enum Mode mode)
+{
+ Word16 i;
+
+ if (state == (Decoder_amrState *) NULL){
+ fprintf(stderr, "Decoder_amr_reset: invalid parameter\n");
+ return -1;
+ }
+
+ // Initialize static pointer
+ state->exc = state->old_exc + PIT_MAX + L_INTERPOL;
+
+ // Static vectors to zero
+ Set_zero (state->old_exc, PIT_MAX + L_INTERPOL);
+
+ if (mode != MRDTX)
+ Set_zero (state->mem_syn, M);
+
+ // initialize pitch sharpening
+ state->sharp = SHARPMIN;
+ state->old_T0 = 40;
+
+ // Initialize state->lsp_old []
+
+ if (mode != MRDTX) {
+ Copy(lsp_init_data, &state->lsp_old[0], M);
+ }
+
+ // Initialize memories of bad frame handling
+ state->prev_bf = 0;
+ state->prev_pdf = 0;
+ state->state = 0;
+
+ state->T0_lagBuff = 40;
+ state->inBackgroundNoise = 0;
+ state->voicedHangover = 0;
+ if (mode != MRDTX) {
+ for (i=0;i<9;i++)
+ state->excEnergyHist[i] = 0;
+ }
+
+ for (i = 0; i < 9; i++)
+ state->ltpGainHistory[i] = 0;
+
+ Cb_gain_average_reset(state->Cb_gain_averState);
+ if (mode != MRDTX)
+ lsp_avg_reset(state->lsp_avg_st);
+ D_plsf_reset(state->lsfState);
+ ec_gain_pitch_reset(state->ec_gain_p_st);
+ ec_gain_code_reset(state->ec_gain_c_st);
+
+ if (mode != MRDTX)
+ gc_pred_reset(state->pred_state);
+
+ Bgn_scd_reset(state->background_state);
+ state->nodataSeed = 21845;
+ ph_disp_reset(state->ph_disp_st);
+ if (mode != MRDTX)
+ dtx_dec_reset(state->dtxDecoderState);
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Decoder_amr_reset(Decoder_amrState *state, enum Mode mode)
+{
+ Word16 i;
+
+ if (state == (Decoder_amrState *) NULL)
+ {
+ /* fprint(stderr, "Decoder_amr_reset: invalid parameter\n"); */
+ return(-1);
+ }
+
+ /* Initialize static pointer */
+ state->exc = state->old_exc + PIT_MAX + L_INTERPOL;
+
+ /* Static vectors to zero */
+ memset(state->old_exc, 0, sizeof(Word16)*(PIT_MAX + L_INTERPOL));
+
+ if (mode != MRDTX)
+ {
+ memset(state->mem_syn, 0, sizeof(Word16)*M);
+ }
+ /* initialize pitch sharpening */
+ state->sharp = SHARPMIN;
+ state->old_T0 = 40;
+
+ /* Initialize overflow Flag */
+
+ state->overflow = 0;
+
+ /* Initialize state->lsp_old [] */
+
+ if (mode != MRDTX)
+ {
+ state->lsp_old[0] = 30000;
+ state->lsp_old[1] = 26000;
+ state->lsp_old[2] = 21000;
+ state->lsp_old[3] = 15000;
+ state->lsp_old[4] = 8000;
+ state->lsp_old[5] = 0;
+ state->lsp_old[6] = -8000;
+ state->lsp_old[7] = -15000;
+ state->lsp_old[8] = -21000;
+ state->lsp_old[9] = -26000;
+ }
+
+ /* Initialize memories of bad frame handling */
+ state->prev_bf = 0;
+ state->prev_pdf = 0;
+ state->state = 0;
+
+ state->T0_lagBuff = 40;
+ state->inBackgroundNoise = 0;
+ state->voicedHangover = 0;
+ if (mode != MRDTX)
+ {
+ for (i = 0; i < EXC_ENERGY_HIST_LEN; i++)
+ {
+ state->excEnergyHist[i] = 0;
+ }
+ }
+
+ for (i = 0; i < LTP_GAIN_HISTORY_LEN; i++)
+ {
+ state->ltpGainHistory[i] = 0;
+ }
+
+ Cb_gain_average_reset(&(state->Cb_gain_averState));
+ if (mode != MRDTX)
+ {
+ lsp_avg_reset(&(state->lsp_avg_st));
+ }
+ D_plsf_reset(&(state->lsfState));
+ ec_gain_pitch_reset(&(state->ec_gain_p_st));
+ ec_gain_code_reset(&(state->ec_gain_c_st));
+
+ if (mode != MRDTX)
+ {
+ gc_pred_reset(&(state->pred_state));
+ }
+
+ Bgn_scd_reset(&(state->background_state));
+ state->nodataSeed = 21845;
+ ph_disp_reset(&(state->ph_disp_st));
+ if (mode != MRDTX)
+ {
+ dtx_dec_reset(&(state->dtxDecoderState));
+ }
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Decoder_amr
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type Decoder_amrState
+ mode = codec mode (enum Mode)
+ parm = buffer of synthesis parameters (Word16)
+ frame_type = received frame type (enum RXFrameType)
+ synth = buffer containing synthetic speech (Word16)
+ A_t = buffer containing decoded LP filter in 4 subframes (Word16)
+
+ Outputs:
+ structure pointed to by st contains the newly calculated decoder
+ parameters
+ synth buffer contains the decoded speech samples
+ A_t buffer contains the decoded LP filter parameters
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the decoding of one speech frame for a given codec
+ mode.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dec_amr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Decoder_amr (
+ Decoder_amrState *st, // i/o : State variables
+ enum Mode mode, // i : AMR mode
+ Word16 parm[], // i : vector of synthesis parameters
+ (PRM_SIZE)
+ enum RXFrameType frame_type, // i : received frame type
+ Word16 synth[], // o : synthesis speech (L_FRAME)
+ Word16 A_t[] // o : decoded LP filter in 4 subframes
+ (AZ_SIZE)
+)
+{
+ // LPC coefficients
+
+ Word16 *Az; // Pointer on A_t
+
+ // LSPs
+
+ Word16 lsp_new[M];
+ Word16 lsp_mid[M];
+
+ // LSFs
+
+ Word16 prev_lsf[M];
+ Word16 lsf_i[M];
+
+ // Algebraic codevector
+
+ Word16 code[L_SUBFR];
+
+ // excitation
+
+ Word16 excp[L_SUBFR];
+ Word16 exc_enhanced[L_SUBFR];
+
+ // Scalars
+
+ Word16 i, i_subfr;
+ Word16 T0, T0_frac, index, index_mr475 = 0;
+ Word16 gain_pit, gain_code, gain_code_mix, pit_sharp, pit_flag, pitch_fac;
+ Word16 t0_min, t0_max;
+ Word16 delta_frc_low, delta_frc_range;
+ Word16 tmp_shift;
+ Word16 temp;
+ Word32 L_temp;
+ Word16 flag4;
+ Word16 carefulFlag;
+ Word16 excEnergy;
+ Word16 subfrNr;
+ Word16 evenSubfr = 0;
+
+ Word16 bfi = 0; // bad frame indication flag
+ Word16 pdfi = 0; // potential degraded bad frame flag
+
+ enum DTXStateType newDTXState; // SPEECH , DTX, DTX_MUTE
+
+ // find the new DTX state SPEECH OR DTX
+ newDTXState = rx_dtx_handler(st->dtxDecoderState, frame_type);
+
+ // DTX actions
+ if (sub(newDTXState, SPEECH) != 0 )
+ {
+ Decoder_amr_reset (st, MRDTX);
+
+ dtx_dec(st->dtxDecoderState,
+ st->mem_syn,
+ st->lsfState,
+ st->pred_state,
+ st->Cb_gain_averState,
+ newDTXState,
+ mode,
+ parm, synth, A_t);
+ // update average lsp
+
+ Lsf_lsp(st->lsfState->past_lsf_q, st->lsp_old, M);
+ lsp_avg(st->lsp_avg_st, st->lsfState->past_lsf_q);
+ goto the_end;
+ }
+
+ // SPEECH action state machine
+ if ((sub(frame_type, RX_SPEECH_BAD) == 0) ||
+ (sub(frame_type, RX_NO_DATA) == 0) ||
+ (sub(frame_type, RX_ONSET) == 0))
+ {
+ bfi = 1;
+ if ((sub(frame_type, RX_NO_DATA) == 0) ||
+ (sub(frame_type, RX_ONSET) == 0))
+ {
+ build_CN_param(&st->nodataSeed,
+ prmno[mode],
+ bitno[mode],
+ parm);
+ }
+ }
+ else if (sub(frame_type, RX_SPEECH_DEGRADED) == 0)
+ {
+ pdfi = 1;
+ }
+
+ if (bfi != 0)
+ {
+ st->state = add (st->state, 1);
+ }
+ else if (sub (st->state, 6) == 0)
+
+ {
+ st->state = 5;
+ }
+ else
+ {
+ st->state = 0;
+ }
+
+ if (sub (st->state, 6) > 0)
+ {
+ st->state = 6;
+ }
+
+ // If this frame is the first speech frame after CNI period,
+ // set the BFH state machine to an appropriate state depending
+ // on whether there was DTX muting before start of speech or not
+ // If there was DTX muting, the first speech frame is muted.
+ // If there was no DTX muting, the first speech frame is not
+ // muted. The BFH state machine starts from state 5, however, to
+ // keep the audible noise resulting from a SID frame which is
+ // erroneously interpreted as a good speech frame as small as
+ // possible (the decoder output in this case is quickly muted)
+
+ if (sub(st->dtxDecoderState->dtxGlobalState, DTX) == 0)
+ {
+ st->state = 5;
+ st->prev_bf = 0;
+ }
+ else if (sub(st->dtxDecoderState->dtxGlobalState, DTX_MUTE) == 0)
+ {
+ st->state = 5;
+ st->prev_bf = 1;
+ }
+
+ // save old LSFs for CB gain smoothing
+ Copy (st->lsfState->past_lsf_q, prev_lsf, M);
+
+ // decode LSF parameters and generate interpolated lpc coefficients
+ for the 4 subframes
+ if (sub (mode, MR122) != 0)
+ {
+ D_plsf_3(st->lsfState, mode, bfi, parm, lsp_new);
+
+ // Advance synthesis parameters pointer
+ parm += 3;
+
+ Int_lpc_1to3(st->lsp_old, lsp_new, A_t);
+ }
+ else
+ {
+ D_plsf_5 (st->lsfState, bfi, parm, lsp_mid, lsp_new);
+
+ // Advance synthesis parameters pointer
+ parm += 5;
+
+ Int_lpc_1and3 (st->lsp_old, lsp_mid, lsp_new, A_t);
+ }
+
+ // update the LSPs for the next frame
+ for (i = 0; i < M; i++)
+ {
+ st->lsp_old[i] = lsp_new[i];
+ }
+
+ *------------------------------------------------------------------------*
+ * Loop for every subframe in the analysis frame *
+ *------------------------------------------------------------------------*
+ * The subframe size is L_SUBFR and the loop is repeated L_FRAME/L_SUBFR *
+ * times *
+ * - decode the pitch delay *
+ * - decode algebraic code *
+ * - decode pitch and codebook gains *
+ * - find the excitation and compute synthesis speech *
+ *------------------------------------------------------------------------*
+
+ // pointer to interpolated LPC parameters
+ Az = A_t;
+
+ evenSubfr = 0;
+ subfrNr = -1;
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ subfrNr = add(subfrNr, 1);
+ evenSubfr = sub(1, evenSubfr);
+
+ // flag for first and 3th subframe
+ pit_flag = i_subfr;
+
+ if (sub (i_subfr, L_FRAME_BY2) == 0)
+ {
+ if (sub(mode, MR475) != 0 && sub(mode, MR515) != 0)
+ {
+ pit_flag = 0;
+ }
+ }
+
+ // pitch index
+ index = *parm++;
+
+ *-------------------------------------------------------*
+ * - decode pitch lag and find adaptive codebook vector. *
+ *-------------------------------------------------------*
+
+ if (sub(mode, MR122) != 0)
+ {
+ // flag4 indicates encoding with 4 bit resolution;
+ // this is needed for mode MR475, MR515, MR59 and MR67
+
+ flag4 = 0;
+ if ((sub (mode, MR475) == 0) ||
+ (sub (mode, MR515) == 0) ||
+ (sub (mode, MR59) == 0) ||
+ (sub (mode, MR67) == 0) ) {
+ flag4 = 1;
+ }
+
+ *-------------------------------------------------------*
+ * - get ranges for the t0_min and t0_max *
+ * - only needed in delta decoding *
+ *-------------------------------------------------------*
+
+ delta_frc_low = 5;
+ delta_frc_range = 9;
+
+ if ( sub(mode, MR795) == 0 )
+ {
+ delta_frc_low = 10;
+ delta_frc_range = 19;
+ }
+
+ t0_min = sub(st->old_T0, delta_frc_low);
+ if (sub(t0_min, PIT_MIN) < 0)
+ {
+ t0_min = PIT_MIN;
+ }
+ t0_max = add(t0_min, delta_frc_range);
+ if (sub(t0_max, PIT_MAX) > 0)
+ {
+ t0_max = PIT_MAX;
+ t0_min = sub(t0_max, delta_frc_range);
+ }
+
+ Dec_lag3 (index, t0_min, t0_max, pit_flag, st->old_T0,
+ &T0, &T0_frac, flag4);
+
+ st->T0_lagBuff = T0;
+
+ if (bfi != 0)
+ {
+ if (sub (st->old_T0, PIT_MAX) < 0)
+ { // Graceful pitch
+ st->old_T0 = add(st->old_T0, 1); // degradation
+ }
+ T0 = st->old_T0;
+ T0_frac = 0;
+
+ if ( st->inBackgroundNoise != 0 &&
+ sub(st->voicedHangover, 4) > 0 &&
+ ((sub(mode, MR475) == 0 ) ||
+ (sub(mode, MR515) == 0 ) ||
+ (sub(mode, MR59) == 0) )
+ )
+ {
+ T0 = st->T0_lagBuff;
+ }
+ }
+
+ Pred_lt_3or6 (st->exc, T0, T0_frac, L_SUBFR, 1);
+ }
+ else
+ {
+ Dec_lag6 (index, PIT_MIN_MR122,
+ PIT_MAX, pit_flag, &T0, &T0_frac);
+
+ if ( bfi == 0 && (pit_flag == 0 || sub (index, 61) < 0))
+ {
+ }
+ else
+ {
+ st->T0_lagBuff = T0;
+ T0 = st->old_T0;
+ T0_frac = 0;
+ }
+
+ Pred_lt_3or6 (st->exc, T0, T0_frac, L_SUBFR, 0);
+ }
+
+ *-------------------------------------------------------*
+ * - (MR122 only: Decode pitch gain.) *
+ * - Decode innovative codebook. *
+ * - set pitch sharpening factor *
+ *-------------------------------------------------------*
+
+ if (sub (mode, MR475) == 0 || sub (mode, MR515) == 0)
+ { // MR475, MR515
+ index = *parm++; // index of position
+ i = *parm++; // signs
+
+ decode_2i40_9bits (subfrNr, i, index, code);
+
+ pit_sharp = shl (st->sharp, 1);
+ }
+ else if (sub (mode, MR59) == 0)
+ { // MR59
+ index = *parm++; // index of position
+ i = *parm++; // signs
+
+ decode_2i40_11bits (i, index, code);
+
+ pit_sharp = shl (st->sharp, 1);
+ }
+ else if (sub (mode, MR67) == 0)
+ { // MR67
+ index = *parm++; // index of position
+ i = *parm++; // signs
+
+ decode_3i40_14bits (i, index, code);
+
+ pit_sharp = shl (st->sharp, 1);
+ }
+ else if (sub (mode, MR795) <= 0)
+ { // MR74, MR795
+ index = *parm++; // index of position
+ i = *parm++; // signs
+
+ decode_4i40_17bits (i, index, code);
+
+ pit_sharp = shl (st->sharp, 1);
+ }
+ else if (sub (mode, MR102) == 0)
+ { // MR102
+ dec_8i40_31bits (parm, code);
+ parm += 7;
+
+ pit_sharp = shl (st->sharp, 1);
+ }
+ else
+ { // MR122
+ index = *parm++;
+ if (bfi != 0)
+ {
+ ec_gain_pitch (st->ec_gain_p_st, st->state, &gain_pit);
+ }
+ else
+ {
+ gain_pit = d_gain_pitch (mode, index);
+ }
+ ec_gain_pitch_update (st->ec_gain_p_st, bfi, st->prev_bf,
+ &gain_pit);
+
+ dec_10i40_35bits (parm, code);
+ parm += 10;
+
+ // pit_sharp = gain_pit;
+ // if (pit_sharp > 1.0) pit_sharp = 1.0;
+
+ pit_sharp = shl (gain_pit, 1);
+ }
+
+ *-------------------------------------------------------*
+ * - Add the pitch contribution to code[]. *
+ *-------------------------------------------------------*
+ for (i = T0; i < L_SUBFR; i++)
+ {
+ temp = mult (code[i - T0], pit_sharp);
+ code[i] = add (code[i], temp);
+ }
+
+ *------------------------------------------------------------*
+ * - Decode codebook gain (MR122) or both pitch *
+ * gain and codebook gain (all others) *
+ * - Update pitch sharpening "sharp" with quantized gain_pit *
+ *------------------------------------------------------------*
+
+ if (sub (mode, MR475) == 0)
+ {
+ // read and decode pitch and code gain
+ if (evenSubfr != 0)
+ {
+ index_mr475 = *parm++; // index of gain(s)
+ }
+
+ if (bfi == 0)
+ {
+ Dec_gain(st->pred_state, mode, index_mr475, code,
+ evenSubfr, &gain_pit, &gain_code);
+ }
+ else
+ {
+ ec_gain_pitch (st->ec_gain_p_st, st->state, &gain_pit);
+ ec_gain_code (st->ec_gain_c_st, st->pred_state, st->state,
+ &gain_code);
+ }
+ ec_gain_pitch_update (st->ec_gain_p_st, bfi, st->prev_bf,
+ &gain_pit);
+ ec_gain_code_update (st->ec_gain_c_st, bfi, st->prev_bf,
+ &gain_code);
+
+ pit_sharp = gain_pit;
+ if (sub (pit_sharp, SHARPMAX) > 0)
+ {
+ pit_sharp = SHARPMAX;
+ }
+
+ }
+ else if ((sub (mode, MR74) <= 0) ||
+ (sub (mode, MR102) == 0))
+ {
+ // read and decode pitch and code gain
+ index = *parm++; // index of gain(s)
+
+ if (bfi == 0)
+ {
+ Dec_gain(st->pred_state, mode, index, code,
+ evenSubfr, &gain_pit, &gain_code);
+ }
+ else
+ {
+ ec_gain_pitch (st->ec_gain_p_st, st->state, &gain_pit);
+ ec_gain_code (st->ec_gain_c_st, st->pred_state, st->state,
+ &gain_code);
+ }
+ ec_gain_pitch_update (st->ec_gain_p_st, bfi, st->prev_bf,
+ &gain_pit);
+ ec_gain_code_update (st->ec_gain_c_st, bfi, st->prev_bf,
+ &gain_code);
+
+ pit_sharp = gain_pit;
+ if (sub (pit_sharp, SHARPMAX) > 0)
+ {
+ pit_sharp = SHARPMAX;
+ }
+
+ if (sub (mode, MR102) == 0)
+ {
+ if (sub (st->old_T0, add(L_SUBFR, 5)) > 0)
+ {
+ pit_sharp = shr(pit_sharp, 2);
+ }
+ }
+ }
+ else
+ {
+ // read and decode pitch gain
+ index = *parm++; // index of gain(s)
+
+ if (sub (mode, MR795) == 0)
+ {
+ // decode pitch gain
+ if (bfi != 0)
+ {
+ ec_gain_pitch (st->ec_gain_p_st, st->state, &gain_pit);
+ }
+ else
+ {
+ gain_pit = d_gain_pitch (mode, index);
+ }
+ ec_gain_pitch_update (st->ec_gain_p_st, bfi, st->prev_bf,
+ &gain_pit);
+
+ // read and decode code gain
+ index = *parm++;
+ if (bfi == 0)
+ {
+ d_gain_code (st->pred_state, mode, index, code, &gain_code);
+ }
+ else
+ {
+ ec_gain_code (st->ec_gain_c_st, st->pred_state, st->state,
+ &gain_code);
+ }
+ ec_gain_code_update (st->ec_gain_c_st, bfi, st->prev_bf,
+ &gain_code);
+
+ pit_sharp = gain_pit;
+ if (sub (pit_sharp, SHARPMAX) > 0)
+ {
+ pit_sharp = SHARPMAX;
+ }
+ }
+ else
+ { // MR122
+ if (bfi == 0)
+ {
+ d_gain_code (st->pred_state, mode, index, code, &gain_code);
+ }
+ else
+ {
+ ec_gain_code (st->ec_gain_c_st, st->pred_state, st->state,
+ &gain_code);
+ }
+ ec_gain_code_update (st->ec_gain_c_st, bfi, st->prev_bf,
+ &gain_code);
+
+ pit_sharp = gain_pit;
+ }
+ }
+
+ // store pitch sharpening for next subframe
+ // (for modes which use the previous pitch gain for
+ // pitch sharpening in the search phase)
+ // do not update sharpening in even subframes for MR475
+ if (sub(mode, MR475) != 0 || evenSubfr == 0)
+ {
+ st->sharp = gain_pit;
+ if (sub (st->sharp, SHARPMAX) > 0)
+ {
+ st->sharp = SHARPMAX;
+ }
+ }
+
+ pit_sharp = shl (pit_sharp, 1);
+ if (sub (pit_sharp, 16384) > 0)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ temp = mult (st->exc[i], pit_sharp);
+ L_temp = L_mult (temp, gain_pit);
+ if (sub(mode, MR122)==0)
+ {
+ L_temp = L_shr (L_temp, 1);
+ }
+ excp[i] = pv_round (L_temp);
+ }
+ }
+
+ *-------------------------------------------------------*
+ * - Store list of LTP gains needed in the source *
+ * characteristic detector (SCD) *
+ *-------------------------------------------------------*
+ if ( bfi == 0 )
+ {
+ for (i = 0; i < 8; i++)
+ {
+ st->ltpGainHistory[i] = st->ltpGainHistory[i+1];
+ }
+ st->ltpGainHistory[8] = gain_pit;
+ }
+
+ *-------------------------------------------------------*
+ * - Limit gain_pit if in background noise and BFI *
+ * for MR475, MR515, MR59 *
+ *-------------------------------------------------------*
+
+ if ( (st->prev_bf != 0 || bfi != 0) && st->inBackgroundNoise != 0 &&
+ ((sub(mode, MR475) == 0) ||
+ (sub(mode, MR515) == 0) ||
+ (sub(mode, MR59) == 0))
+ )
+ {
+ if ( sub (gain_pit, 12288) > 0) // if (gain_pit > 0.75) in Q14
+ gain_pit = add( shr( sub(gain_pit, 12288), 1 ), 12288 );
+ // gain_pit = (gain_pit-0.75)/2.0 + 0.75;
+
+ if ( sub (gain_pit, 14745) > 0) // if (gain_pit > 0.90) in Q14
+ {
+ gain_pit = 14745;
+ }
+ }
+
+ *-------------------------------------------------------*
+ * Calculate CB mixed gain *
+ *-------------------------------------------------------*
+ Int_lsf(prev_lsf, st->lsfState->past_lsf_q, i_subfr, lsf_i);
+ gain_code_mix = Cb_gain_average(
+ st->Cb_gain_averState, mode, gain_code,
+ lsf_i, st->lsp_avg_st->lsp_meanSave, bfi,
+ st->prev_bf, pdfi, st->prev_pdf,
+ st->inBackgroundNoise, st->voicedHangover);
+
+ // make sure that MR74, MR795, MR122 have original code_gain
+ if ((sub(mode, MR67) > 0) && (sub(mode, MR102) != 0) )
+ // MR74, MR795, MR122
+ {
+ gain_code_mix = gain_code;
+ }
+
+ *-------------------------------------------------------*
+ * - Find the total excitation. *
+ * - Find synthesis speech corresponding to st->exc[]. *
+ *-------------------------------------------------------*
+ if (sub(mode, MR102) <= 0) // MR475, MR515, MR59, MR67, MR74, MR795, MR102
+ {
+ pitch_fac = gain_pit;
+ tmp_shift = 1;
+ }
+ else // MR122
+ {
+ pitch_fac = shr (gain_pit, 1);
+ tmp_shift = 2;
+ }
+
+ // copy unscaled LTP excitation to exc_enhanced (used in phase
+ * dispersion below) and compute total excitation for LTP feedback
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ exc_enhanced[i] = st->exc[i];
+
+ // st->exc[i] = gain_pit*st->exc[i] + gain_code*code[i];
+ L_temp = L_mult (st->exc[i], pitch_fac);
+ // 12.2: Q0 * Q13
+ // 7.4: Q0 * Q14
+ L_temp = L_mac (L_temp, code[i], gain_code);
+ // 12.2: Q12 * Q1
+ // 7.4: Q13 * Q1
+ L_temp = L_shl (L_temp, tmp_shift); // Q16
+ st->exc[i] = pv_round (L_temp);
+ }
+
+ *-------------------------------------------------------*
+ * - Adaptive phase dispersion *
+ *-------------------------------------------------------*
+ ph_disp_release(st->ph_disp_st); // free phase dispersion adaption
+
+ if ( ((sub(mode, MR475) == 0) ||
+ (sub(mode, MR515) == 0) ||
+ (sub(mode, MR59) == 0)) &&
+ sub(st->voicedHangover, 3) > 0 &&
+ st->inBackgroundNoise != 0 &&
+ bfi != 0 )
+ {
+ ph_disp_lock(st->ph_disp_st); // Always Use full Phase Disp.
+ } // if error in bg noise
+
+ // apply phase dispersion to innovation (if enabled) and
+ compute total excitation for synthesis part
+ ph_disp(st->ph_disp_st, mode,
+ exc_enhanced, gain_code_mix, gain_pit, code,
+ pitch_fac, tmp_shift);
+
+ *-------------------------------------------------------*
+ * - The Excitation control module are active during BFI.*
+ * - Conceal drops in signal energy if in bg noise. *
+ *-------------------------------------------------------*
+
+ L_temp = 0;
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ L_temp = L_mac (L_temp, exc_enhanced[i], exc_enhanced[i] );
+ }
+
+ L_temp = L_shr (L_temp, 1); // excEnergy = sqrt(L_temp) in Q0
+ L_temp = sqrt_l_exp(L_temp, &temp); // function result
+ L_temp = L_shr(L_temp, add( shr(temp, 1), 15));
+ L_temp = L_shr(L_temp, 2); // To cope with 16-bit and
+ excEnergy = extract_l(L_temp); // scaling in ex_ctrl()
+
+ if ( ((sub (mode, MR475) == 0) ||
+ (sub (mode, MR515) == 0) ||
+ (sub (mode, MR59) == 0)) &&
+ sub(st->voicedHangover, 5) > 0 &&
+ st->inBackgroundNoise != 0 &&
+ sub(st->state, 4) < 0 &&
+ ( (pdfi != 0 && st->prev_pdf != 0) ||
+ bfi != 0 ||
+ st->prev_bf != 0) )
+ {
+ carefulFlag = 0;
+ if ( pdfi != 0 && bfi == 0 )
+ {
+ carefulFlag = 1;
+ }
+
+ Ex_ctrl(exc_enhanced,
+ excEnergy,
+ st->excEnergyHist,
+ st->voicedHangover,
+ st->prev_bf,
+ carefulFlag);
+ }
+
+ if ( st->inBackgroundNoise != 0 &&
+ ( bfi != 0 || st->prev_bf != 0 ) &&
+ sub(st->state, 4) < 0 )
+ {
+ ; // do nothing!
+ }
+ else
+ {
+ // Update energy history for all modes
+ for (i = 0; i < 8; i++)
+ {
+ st->excEnergyHist[i] = st->excEnergyHist[i+1];
+ }
+ st->excEnergyHist[8] = excEnergy;
+ }
+ *-------------------------------------------------------*
+ * Excitation control module end. *
+ *-------------------------------------------------------*
+
+ if (sub (pit_sharp, 16384) > 0)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ excp[i] = add (excp[i], exc_enhanced[i]);
+ }
+ agc2 (exc_enhanced, excp, L_SUBFR);
+ Overflow = 0;
+ Syn_filt (Az, excp, &synth[i_subfr], L_SUBFR,
+ st->mem_syn, 0);
+ }
+ else
+ {
+ Overflow = 0;
+ Syn_filt (Az, exc_enhanced, &synth[i_subfr], L_SUBFR,
+ st->mem_syn, 0);
+ }
+
+ if (Overflow != 0) // Test for overflow
+ {
+ for (i = 0; i < PIT_MAX + L_INTERPOL + L_SUBFR; i++)
+ {
+ st->old_exc[i] = shr(st->old_exc[i], 2);
+ }
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ exc_enhanced[i] = shr(exc_enhanced[i], 2);
+ }
+ Syn_filt(Az, exc_enhanced, &synth[i_subfr], L_SUBFR, st->mem_syn, 1);
+ }
+ else
+ {
+ Copy(&synth[i_subfr+L_SUBFR-M], st->mem_syn, M);
+ }
+
+ *--------------------------------------------------*
+ * Update signal for next frame. *
+ * -> shift to the left by L_SUBFR st->exc[] *
+ *--------------------------------------------------*
+
+ Copy (&st->old_exc[L_SUBFR], &st->old_exc[0], PIT_MAX + L_INTERPOL);
+
+ // interpolated LPC parameters for next subframe
+ Az += MP1;
+
+ // store T0 for next subframe
+ st->old_T0 = T0;
+ }
+
+ *-------------------------------------------------------*
+ * Call the Source Characteristic Detector which updates *
+ * st->inBackgroundNoise and st->voicedHangover. *
+ *-------------------------------------------------------*
+
+ st->inBackgroundNoise = Bgn_scd(st->background_state,
+ &(st->ltpGainHistory[0]),
+ &(synth[0]),
+ &(st->voicedHangover) );
+
+ dtx_dec_activity_update(st->dtxDecoderState,
+ st->lsfState->past_lsf_q,
+ synth);
+
+ // store bfi for next subframe
+ st->prev_bf = bfi;
+ st->prev_pdf = pdfi;
+
+ *--------------------------------------------------*
+ * Calculate the LSF averages on the eight *
+ * previous frames *
+ *--------------------------------------------------*
+
+ lsp_avg(st->lsp_avg_st, st->lsfState->past_lsf_q);
+
+the_end:
+ st->dtxDecoderState->dtxGlobalState = newDTXState;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Decoder_amr(
+ Decoder_amrState *st, /* i/o : State variables */
+ enum Mode mode, /* i : AMR mode */
+ Word16 parm[], /* i : vector of synthesis parameters
+ (PRM_SIZE) */
+ enum RXFrameType frame_type, /* i : received frame type */
+ Word16 synth[], /* o : synthesis speech (L_FRAME) */
+ Word16 A_t[] /* o : decoded LP filter in 4 subframes
+ (AZ_SIZE) */
+)
+{
+ /* LPC coefficients */
+
+ Word16 *Az; /* Pointer on A_t */
+
+ /* LSPs */
+
+ Word16 lsp_new[M];
+ Word16 lsp_mid[M];
+
+ /* LSFs */
+
+ Word16 prev_lsf[M];
+ Word16 lsf_i[M];
+
+ /* Algebraic codevector */
+
+ Word16 code[L_SUBFR];
+
+ /* excitation */
+
+ Word16 excp[L_SUBFR];
+ Word16 exc_enhanced[L_SUBFR];
+
+ /* Scalars */
+
+ Word16 i;
+ Word16 i_subfr;
+ Word16 T0;
+ Word16 T0_frac;
+ Word16 index;
+ Word16 index_mr475 = 0;
+ Word16 gain_pit;
+ Word16 gain_code;
+ Word16 gain_code_mix;
+ Word16 pit_sharp;
+ Word16 pit_flag;
+ Word16 pitch_fac;
+ Word16 t0_min;
+ Word16 t0_max;
+ Word16 delta_frc_low;
+ Word16 delta_frc_range;
+ Word16 tmp_shift;
+ Word16 temp;
+ Word32 L_temp;
+ Word16 flag4;
+ Word16 carefulFlag;
+ Word16 excEnergy;
+ Word16 subfrNr;
+ Word16 evenSubfr = 0;
+
+ Word16 bfi = 0; /* bad frame indication flag */
+ Word16 pdfi = 0; /* potential degraded bad frame flag */
+
+ enum DTXStateType newDTXState; /* SPEECH , DTX, DTX_MUTE */
+ Flag *pOverflow = &(st->overflow); /* Overflow flag */
+
+
+ /* find the new DTX state SPEECH OR DTX */
+ newDTXState = rx_dtx_handler(&(st->dtxDecoderState), frame_type, pOverflow);
+
+ /* DTX actions */
+
+ if (newDTXState != SPEECH)
+ {
+ Decoder_amr_reset(st, MRDTX);
+
+ dtx_dec(&(st->dtxDecoderState),
+ st->mem_syn,
+ &(st->lsfState),
+ &(st->pred_state),
+ &(st->Cb_gain_averState),
+ newDTXState,
+ mode,
+ parm, synth, A_t, pOverflow);
+
+ /* update average lsp */
+ Lsf_lsp(
+ st->lsfState.past_lsf_q,
+ st->lsp_old,
+ M,
+ pOverflow);
+
+ lsp_avg(
+ &(st->lsp_avg_st),
+ st->lsfState.past_lsf_q,
+ pOverflow);
+
+ goto the_end;
+ }
+
+ /* SPEECH action state machine */
+ if ((frame_type == RX_SPEECH_BAD) || (frame_type == RX_NO_DATA) ||
+ (frame_type == RX_ONSET))
+ {
+ bfi = 1;
+
+ if ((frame_type == RX_NO_DATA) || (frame_type == RX_ONSET))
+ {
+ build_CN_param(&st->nodataSeed,
+ prmno[mode],
+ bitno[mode],
+ parm,
+ pOverflow);
+ }
+ }
+ else if (frame_type == RX_SPEECH_DEGRADED)
+ {
+ pdfi = 1;
+ }
+
+ if (bfi != 0)
+ {
+ st->state += 1;
+ }
+ else if (st->state == 6)
+
+ {
+ st->state = 5;
+ }
+ else
+ {
+ st->state = 0;
+ }
+
+
+ if (st->state > 6)
+ {
+ st->state = 6;
+ }
+
+ /* If this frame is the first speech frame after CNI period, */
+ /* set the BFH state machine to an appropriate state depending */
+ /* on whether there was DTX muting before start of speech or not */
+ /* If there was DTX muting, the first speech frame is muted. */
+ /* If there was no DTX muting, the first speech frame is not */
+ /* muted. The BFH state machine starts from state 5, however, to */
+ /* keep the audible noise resulting from a SID frame which is */
+ /* erroneously interpreted as a good speech frame as small as */
+ /* possible (the decoder output in this case is quickly muted) */
+
+ if (st->dtxDecoderState.dtxGlobalState == DTX)
+ {
+ st->state = 5;
+ st->prev_bf = 0;
+ }
+ else if (st->dtxDecoderState.dtxGlobalState == DTX_MUTE)
+ {
+ st->state = 5;
+ st->prev_bf = 1;
+ }
+
+ /* save old LSFs for CB gain smoothing */
+ Copy(st->lsfState.past_lsf_q, prev_lsf, M);
+
+ /* decode LSF parameters and generate interpolated lpc coefficients
+ for the 4 subframes */
+
+ if (mode != MR122)
+ {
+ D_plsf_3(
+ &(st->lsfState),
+ mode,
+ bfi,
+ parm,
+ lsp_new,
+ pOverflow);
+
+ /* Advance synthesis parameters pointer */
+ parm += 3;
+
+ Int_lpc_1to3(
+ st->lsp_old,
+ lsp_new,
+ A_t,
+ pOverflow);
+ }
+ else
+ {
+ D_plsf_5(
+ &(st->lsfState),
+ bfi,
+ parm,
+ lsp_mid,
+ lsp_new,
+ pOverflow);
+
+ /* Advance synthesis parameters pointer */
+ parm += 5;
+
+ Int_lpc_1and3(
+ st->lsp_old,
+ lsp_mid,
+ lsp_new,
+ A_t,
+ pOverflow);
+ }
+
+ /* update the LSPs for the next frame */
+ for (i = 0; i < M; i++)
+ {
+ st->lsp_old[i] = lsp_new[i];
+ }
+
+ /*------------------------------------------------------------------------*
+ * Loop for every subframe in the analysis frame *
+ *------------------------------------------------------------------------*
+ * The subframe size is L_SUBFR and the loop is repeated L_FRAME/L_SUBFR *
+ * times *
+ * - decode the pitch delay *
+ * - decode algebraic code *
+ * - decode pitch and codebook gains *
+ * - find the excitation and compute synthesis speech *
+ *------------------------------------------------------------------------*/
+
+ /* pointer to interpolated LPC parameters */
+ Az = A_t;
+
+ evenSubfr = 0;
+ subfrNr = -1;
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ subfrNr += 1;
+ evenSubfr = 1 - evenSubfr;
+
+ /* flag for first and 3th subframe */
+ pit_flag = i_subfr;
+
+
+ if (i_subfr == L_FRAME_BY2)
+ {
+ if ((mode != MR475) && (mode != MR515))
+ {
+ pit_flag = 0;
+ }
+ }
+
+ /* pitch index */
+ index = *parm++;
+
+ /*-------------------------------------------------------*
+ * - decode pitch lag and find adaptive codebook vector. *
+ *-------------------------------------------------------*/
+
+ if (mode != MR122)
+ {
+ /* flag4 indicates encoding with 4 bit resolution; */
+ /* this is needed for mode MR475, MR515, MR59 and MR67 */
+
+ flag4 = 0;
+
+ if ((mode == MR475) || (mode == MR515) || (mode == MR59) ||
+ (mode == MR67))
+ {
+ flag4 = 1;
+ }
+
+ /*-------------------------------------------------------*
+ * - get ranges for the t0_min and t0_max *
+ * - only needed in delta decoding *
+ *-------------------------------------------------------*/
+
+ delta_frc_low = 5;
+ delta_frc_range = 9;
+
+ if (mode == MR795)
+ {
+ delta_frc_low = 10;
+ delta_frc_range = 19;
+ }
+
+ t0_min = sub(st->old_T0, delta_frc_low, pOverflow);
+
+ if (t0_min < PIT_MIN)
+ {
+ t0_min = PIT_MIN;
+ }
+ t0_max = add(t0_min, delta_frc_range, pOverflow);
+
+ if (t0_max > PIT_MAX)
+ {
+ t0_max = PIT_MAX;
+ t0_min = t0_max - delta_frc_range;
+ }
+
+ Dec_lag3(index, t0_min, t0_max, pit_flag, st->old_T0,
+ &T0, &T0_frac, flag4, pOverflow);
+
+ st->T0_lagBuff = T0;
+
+ if (bfi != 0)
+ {
+ if (st->old_T0 < PIT_MAX)
+ { /* Graceful pitch */
+ st->old_T0 += 0; /* degradation */
+ }
+ T0 = st->old_T0;
+ T0_frac = 0;
+
+ if ((st->inBackgroundNoise != 0) && (st->voicedHangover > 4) &&
+ ((mode == MR475) || (mode == MR515) || (mode == MR59)))
+ {
+ T0 = st->T0_lagBuff;
+ }
+ }
+
+ Pred_lt_3or6(st->exc, T0, T0_frac, L_SUBFR, 1, pOverflow);
+ }
+ else
+ {
+ Dec_lag6(index, PIT_MIN_MR122,
+ PIT_MAX, pit_flag, &T0, &T0_frac, pOverflow);
+
+
+ if (!(bfi == 0 && (pit_flag == 0 || index < 61)))
+ {
+ st->T0_lagBuff = T0;
+ T0 = st->old_T0;
+ T0_frac = 0;
+ }
+
+ Pred_lt_3or6(st->exc, T0, T0_frac, L_SUBFR, 0, pOverflow);
+ }
+
+ /*-------------------------------------------------------*
+ * - (MR122 only: Decode pitch gain.) *
+ * - Decode innovative codebook. *
+ * - set pitch sharpening factor *
+ *-------------------------------------------------------*/
+ if ((mode == MR475) || (mode == MR515))
+ { /* MR475, MR515 */
+ index = *parm++; /* index of position */
+ i = *parm++; /* signs */
+
+ decode_2i40_9bits(subfrNr, i, index, code, pOverflow);
+
+ L_temp = (Word32)st->sharp << 1;
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ pit_sharp = (st->sharp > 0) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ pit_sharp = (Word16) L_temp;
+ }
+ }
+ else if (mode == MR59)
+ { /* MR59 */
+ index = *parm++; /* index of position */
+ i = *parm++; /* signs */
+
+ decode_2i40_11bits(i, index, code);
+
+ L_temp = (Word32)st->sharp << 1;
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ pit_sharp = (st->sharp > 0) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ pit_sharp = (Word16) L_temp;
+ }
+ }
+ else if (mode == MR67)
+ { /* MR67 */
+ index = *parm++; /* index of position */
+ i = *parm++; /* signs */
+
+ decode_3i40_14bits(i, index, code);
+
+ L_temp = (Word32)st->sharp << 1;
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ pit_sharp = (st->sharp > 0) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ pit_sharp = (Word16) L_temp;
+ }
+ }
+ else if (mode <= MR795)
+ { /* MR74, MR795 */
+ index = *parm++; /* index of position */
+ i = *parm++; /* signs */
+
+ decode_4i40_17bits(i, index, code);
+
+ L_temp = (Word32)st->sharp << 1;
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ pit_sharp = (st->sharp > 0) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ pit_sharp = (Word16) L_temp;
+ }
+ }
+ else if (mode == MR102)
+ { /* MR102 */
+ dec_8i40_31bits(parm, code, pOverflow);
+ parm += 7;
+
+ L_temp = (Word32)st->sharp << 1;
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ pit_sharp = (st->sharp > 0) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ pit_sharp = (Word16) L_temp;
+ }
+ }
+ else
+ { /* MR122 */
+ index = *parm++;
+
+ if (bfi != 0)
+ {
+ ec_gain_pitch(
+ &(st->ec_gain_p_st),
+ st->state,
+ &gain_pit,
+ pOverflow);
+ }
+ else
+ {
+ gain_pit = d_gain_pitch(mode, index);
+ }
+ ec_gain_pitch_update(
+ &(st->ec_gain_p_st),
+ bfi,
+ st->prev_bf,
+ &gain_pit,
+ pOverflow);
+
+
+ dec_10i40_35bits(parm, code);
+ parm += 10;
+
+ /* pit_sharp = gain_pit; */
+ /* if (pit_sharp > 1.0) pit_sharp = 1.0; */
+
+ L_temp = (Word32)gain_pit << 1;
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ pit_sharp = (gain_pit > 0) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ pit_sharp = (Word16) L_temp;
+ }
+ }
+ /*-------------------------------------------------------*
+ * - Add the pitch contribution to code[]. *
+ *-------------------------------------------------------*/
+ for (i = T0; i < L_SUBFR; i++)
+ {
+ temp = mult(*(code + i - T0), pit_sharp, pOverflow);
+ *(code + i) = add(*(code + i), temp, pOverflow);
+
+ }
+
+ /*------------------------------------------------------------*
+ * - Decode codebook gain (MR122) or both pitch *
+ * gain and codebook gain (all others) *
+ * - Update pitch sharpening "sharp" with quantized gain_pit *
+ *------------------------------------------------------------*/
+ if (mode == MR475)
+ {
+ /* read and decode pitch and code gain */
+
+ if (evenSubfr != 0)
+ {
+ index_mr475 = *parm++; /* index of gain(s) */
+ }
+
+ if (bfi == 0)
+ {
+ Dec_gain(
+ &(st->pred_state),
+ mode,
+ index_mr475,
+ code,
+ evenSubfr,
+ &gain_pit,
+ &gain_code,
+ pOverflow);
+ }
+ else
+ {
+ ec_gain_pitch(
+ &(st->ec_gain_p_st),
+ st->state,
+ &gain_pit,
+ pOverflow);
+
+ ec_gain_code(
+ &(st->ec_gain_c_st),
+ &(st->pred_state),
+ st->state,
+ &gain_code,
+ pOverflow);
+ }
+ ec_gain_pitch_update(
+ &st->ec_gain_p_st,
+ bfi,
+ st->prev_bf,
+ &gain_pit,
+ pOverflow);
+
+ ec_gain_code_update(
+ &st->ec_gain_c_st,
+ bfi,
+ st->prev_bf,
+ &gain_code,
+ pOverflow);
+
+ pit_sharp = gain_pit;
+
+ if (pit_sharp > SHARPMAX)
+ {
+ pit_sharp = SHARPMAX;
+ }
+
+ }
+ else if ((mode <= MR74) || (mode == MR102))
+ {
+ /* read and decode pitch and code gain */
+ index = *parm++; /* index of gain(s) */
+
+ if (bfi == 0)
+ {
+ Dec_gain(
+ &(st->pred_state),
+ mode,
+ index,
+ code,
+ evenSubfr,
+ &gain_pit,
+ &gain_code,
+ pOverflow);
+ }
+ else
+ {
+ ec_gain_pitch(
+ &(st->ec_gain_p_st),
+ st->state,
+ &gain_pit,
+ pOverflow);
+
+ ec_gain_code(
+ &(st->ec_gain_c_st),
+ &(st->pred_state),
+ st->state,
+ &gain_code,
+ pOverflow);
+ }
+
+ ec_gain_pitch_update(
+ &(st->ec_gain_p_st),
+ bfi,
+ st->prev_bf,
+ &gain_pit,
+ pOverflow);
+
+ ec_gain_code_update(
+ &(st->ec_gain_c_st),
+ bfi,
+ st->prev_bf,
+ &gain_code,
+ pOverflow);
+
+ pit_sharp = gain_pit;
+
+ if (pit_sharp > SHARPMAX)
+ {
+ pit_sharp = SHARPMAX;
+ }
+
+ if (mode == MR102)
+ {
+ if (st->old_T0 > (L_SUBFR + 5))
+ {
+ if (pit_sharp < 0)
+ {
+ pit_sharp = ~((~pit_sharp) >> 2);
+ }
+ else
+ {
+ pit_sharp = pit_sharp >> 2;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* read and decode pitch gain */
+ index = *parm++; /* index of gain(s) */
+
+ if (mode == MR795)
+ {
+ /* decode pitch gain */
+ if (bfi != 0)
+ {
+ ec_gain_pitch(
+ &(st->ec_gain_p_st),
+ st->state,
+ &gain_pit,
+ pOverflow);
+ }
+ else
+ {
+ gain_pit = d_gain_pitch(mode, index);
+ }
+ ec_gain_pitch_update(
+ &(st->ec_gain_p_st),
+ bfi,
+ st->prev_bf,
+ &gain_pit,
+ pOverflow);
+
+ /* read and decode code gain */
+ index = *parm++;
+
+ if (bfi == 0)
+ {
+ d_gain_code(
+ &(st->pred_state),
+ mode,
+ index,
+ code,
+ &gain_code,
+ pOverflow);
+ }
+ else
+ {
+ ec_gain_code(
+ &(st->ec_gain_c_st),
+ &(st->pred_state),
+ st->state,
+ &gain_code,
+ pOverflow);
+ }
+
+ ec_gain_code_update(
+ &(st->ec_gain_c_st),
+ bfi,
+ st->prev_bf,
+ &gain_code,
+ pOverflow);
+
+ pit_sharp = gain_pit;
+
+ if (pit_sharp > SHARPMAX)
+ {
+ pit_sharp = SHARPMAX;
+ }
+ }
+ else
+ { /* MR122 */
+
+ if (bfi == 0)
+ {
+ d_gain_code(
+ &(st->pred_state),
+ mode,
+ index,
+ code,
+ &gain_code,
+ pOverflow);
+ }
+ else
+ {
+ ec_gain_code(
+ &(st->ec_gain_c_st),
+ &(st->pred_state),
+ st->state,
+ &gain_code,
+ pOverflow);
+ }
+
+ ec_gain_code_update(
+ &(st->ec_gain_c_st),
+ bfi,
+ st->prev_bf,
+ &gain_code,
+ pOverflow);
+
+ pit_sharp = gain_pit;
+ }
+ }
+
+ /* store pitch sharpening for next subframe */
+ /* (for modes which use the previous pitch gain for */
+ /* pitch sharpening in the search phase) */
+ /* do not update sharpening in even subframes for MR475 */
+ if ((mode != MR475) || (evenSubfr == 0))
+ {
+ st->sharp = gain_pit;
+
+ if (st->sharp > SHARPMAX)
+ {
+ st->sharp = SHARPMAX;
+ }
+ }
+
+ pit_sharp = shl(pit_sharp, 1, pOverflow);
+
+ if (pit_sharp > 16384)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ temp = mult(st->exc[i], pit_sharp, pOverflow);
+ L_temp = L_mult(temp, gain_pit, pOverflow);
+
+ if (mode == MR122)
+ {
+ if (L_temp < 0)
+ {
+ L_temp = ~((~L_temp) >> 1);
+ }
+ else
+ {
+ L_temp = L_temp >> 1;
+ }
+ }
+ *(excp + i) = pv_round(L_temp, pOverflow);
+ }
+ }
+
+ /*-------------------------------------------------------*
+ * - Store list of LTP gains needed in the source *
+ * characteristic detector (SCD) *
+ *-------------------------------------------------------*/
+
+ if (bfi == 0)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ st->ltpGainHistory[i] = st->ltpGainHistory[i+1];
+ }
+ st->ltpGainHistory[8] = gain_pit;
+ }
+
+ /*-------------------------------------------------------*
+ * - Limit gain_pit if in background noise and BFI *
+ * for MR475, MR515, MR59 *
+ *-------------------------------------------------------*/
+
+
+ if ((st->prev_bf != 0 || bfi != 0) && st->inBackgroundNoise != 0 &&
+ ((mode == MR475) || (mode == MR515) || (mode == MR59)))
+ {
+
+ if (gain_pit > 12288) /* if (gain_pit > 0.75) in Q14*/
+ {
+ gain_pit = ((gain_pit - 12288) >> 1) + 12288;
+ /* gain_pit = (gain_pit-0.75)/2.0 + 0.75; */
+ }
+
+ if (gain_pit > 14745) /* if (gain_pit > 0.90) in Q14*/
+ {
+ gain_pit = 14745;
+ }
+ }
+
+ /*-------------------------------------------------------*
+ * Calculate CB mixed gain *
+ *-------------------------------------------------------*/
+ Int_lsf(
+ prev_lsf,
+ st->lsfState.past_lsf_q,
+ i_subfr,
+ lsf_i,
+ pOverflow);
+
+ gain_code_mix =
+ Cb_gain_average(
+ &(st->Cb_gain_averState),
+ mode,
+ gain_code,
+ lsf_i,
+ st->lsp_avg_st.lsp_meanSave,
+ bfi,
+ st->prev_bf,
+ pdfi,
+ st->prev_pdf,
+ st->inBackgroundNoise,
+ st->voicedHangover,
+ pOverflow);
+
+ /* make sure that MR74, MR795, MR122 have original code_gain*/
+ if ((mode > MR67) && (mode != MR102))
+ /* MR74, MR795, MR122 */
+ {
+ gain_code_mix = gain_code;
+ }
+
+ /*-------------------------------------------------------*
+ * - Find the total excitation. *
+ * - Find synthesis speech corresponding to st->exc[]. *
+ *-------------------------------------------------------*/
+ if (mode <= MR102) /* MR475, MR515, MR59, MR67, MR74, MR795, MR102*/
+ {
+ pitch_fac = gain_pit;
+ tmp_shift = 1;
+ }
+ else /* MR122 */
+ {
+ if (gain_pit < 0)
+ {
+ pitch_fac = ~((~gain_pit) >> 1);
+ }
+ else
+ {
+ pitch_fac = gain_pit >> 1;
+ }
+ tmp_shift = 2;
+ }
+
+ /* copy unscaled LTP excitation to exc_enhanced (used in phase
+ * dispersion below) and compute total excitation for LTP feedback
+ */
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ exc_enhanced[i] = st->exc[i];
+
+ /* st->exc[i] = gain_pit*st->exc[i] + gain_code*code[i]; */
+ L_temp = L_mult(st->exc[i], pitch_fac, pOverflow);
+ /* 12.2: Q0 * Q13 */
+ /* 7.4: Q0 * Q14 */
+ L_temp = L_mac(L_temp, code[i], gain_code, pOverflow);
+ /* 12.2: Q12 * Q1 */
+ /* 7.4: Q13 * Q1 */
+ L_temp = L_shl(L_temp, tmp_shift, pOverflow); /* Q16 */
+ st->exc[i] = pv_round(L_temp, pOverflow);
+ }
+
+ /*-------------------------------------------------------*
+ * - Adaptive phase dispersion *
+ *-------------------------------------------------------*/
+ ph_disp_release(&(st->ph_disp_st)); /* free phase dispersion adaption */
+
+
+ if (((mode == MR475) || (mode == MR515) || (mode == MR59)) &&
+ (st->voicedHangover > 3) && (st->inBackgroundNoise != 0) &&
+ (bfi != 0))
+ {
+ ph_disp_lock(&(st->ph_disp_st)); /* Always Use full Phase Disp. */
+ } /* if error in bg noise */
+
+ /* apply phase dispersion to innovation (if enabled) and
+ compute total excitation for synthesis part */
+ ph_disp(
+ &(st->ph_disp_st),
+ mode,
+ exc_enhanced,
+ gain_code_mix,
+ gain_pit,
+ code,
+ pitch_fac,
+ tmp_shift,
+ pOverflow);
+
+ /*-------------------------------------------------------*
+ * - The Excitation control module are active during BFI.*
+ * - Conceal drops in signal energy if in bg noise. *
+ *-------------------------------------------------------*/
+ L_temp = 0;
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ L_temp = L_mac(L_temp, *(exc_enhanced + i), *(exc_enhanced + i), pOverflow);
+ }
+
+ /* excEnergy = sqrt(L_temp) in Q0 */
+ if (L_temp < 0)
+ {
+ L_temp = ~((~L_temp) >> 1);
+ }
+ else
+ {
+ L_temp = L_temp >> 1;
+ }
+
+ L_temp = sqrt_l_exp(L_temp, &temp, pOverflow);
+ /* To cope with 16-bit and scaling in ex_ctrl() */
+ L_temp = L_shr(L_temp, (Word16)((temp >> 1) + 15), pOverflow);
+ if (L_temp < 0)
+ {
+ excEnergy = (Word16)(~((~L_temp) >> 2));
+ }
+ else
+ {
+ excEnergy = (Word16)(L_temp >> 2);
+ }
+
+ if (((mode == MR475) || (mode == MR515) || (mode == MR59)) &&
+ (st->voicedHangover > 5) && (st->inBackgroundNoise != 0) &&
+ (st->state < 4) &&
+ ((pdfi != 0 && st->prev_pdf != 0) || bfi != 0 || st->prev_bf != 0))
+ {
+ carefulFlag = 0;
+
+ if (pdfi != 0 && bfi == 0)
+ {
+ carefulFlag = 1;
+ }
+
+ Ex_ctrl(exc_enhanced,
+ excEnergy,
+ st->excEnergyHist,
+ st->voicedHangover,
+ st->prev_bf,
+ carefulFlag, pOverflow);
+ }
+
+ if (!((st->inBackgroundNoise != 0) && (bfi != 0 || st->prev_bf != 0) &&
+ (st->state < 4)))
+ {
+ /* Update energy history for all modes */
+ for (i = 0; i < 8; i++)
+ {
+ st->excEnergyHist[i] = st->excEnergyHist[i+1];
+ }
+ st->excEnergyHist[8] = excEnergy;
+ }
+ /*-------------------------------------------------------*
+ * Excitation control module end. *
+ *-------------------------------------------------------*/
+ if (pit_sharp > 16384)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ *(excp + i) = add(*(excp + i), *(exc_enhanced + i), pOverflow);
+
+ }
+ agc2(exc_enhanced, excp, L_SUBFR, pOverflow);
+ *pOverflow = 0;
+ Syn_filt(Az, excp, &synth[i_subfr], L_SUBFR,
+ st->mem_syn, 0);
+ }
+ else
+ {
+ *pOverflow = 0;
+ Syn_filt(Az, exc_enhanced, &synth[i_subfr], L_SUBFR,
+ st->mem_syn, 0);
+ }
+
+ if (*pOverflow != 0) /* Test for overflow */
+ {
+ for (i = PIT_MAX + L_INTERPOL + L_SUBFR - 1; i >= 0; i--)
+ {
+ if (st->old_exc[i] < 0)
+ {
+ st->old_exc[i] = ~((~st->old_exc[i]) >> 2);
+ }
+ else
+ {
+ st->old_exc[i] = st->old_exc[i] >> 2;
+ }
+
+ }
+
+ for (i = L_SUBFR - 1; i >= 0; i--)
+ {
+ if (*(exc_enhanced + i) < 0)
+ {
+ *(exc_enhanced + i) = ~((~(*(exc_enhanced + i))) >> 2);
+ }
+ else
+ {
+ *(exc_enhanced + i) = *(exc_enhanced + i) >> 2;
+ }
+ }
+ Syn_filt(Az, exc_enhanced, &synth[i_subfr], L_SUBFR, st->mem_syn, 1);
+ }
+ else
+ {
+ Copy(&synth[i_subfr+L_SUBFR-M], st->mem_syn, M);
+ }
+
+ /*--------------------------------------------------*
+ * Update signal for next frame. *
+ * -> shift to the left by L_SUBFR st->exc[] *
+ *--------------------------------------------------*/
+
+ Copy(&st->old_exc[L_SUBFR], &st->old_exc[0], PIT_MAX + L_INTERPOL);
+
+ /* interpolated LPC parameters for next subframe */
+ Az += MP1;
+
+ /* store T0 for next subframe */
+ st->old_T0 = T0;
+ }
+
+ /*-------------------------------------------------------*
+ * Call the Source Characteristic Detector which updates *
+ * st->inBackgroundNoise and st->voicedHangover. *
+ *-------------------------------------------------------*/
+
+ st->inBackgroundNoise =
+ Bgn_scd(
+ &(st->background_state),
+ &(st->ltpGainHistory[0]),
+ &(synth[0]),
+ &(st->voicedHangover),
+ pOverflow);
+
+ dtx_dec_activity_update(
+ &(st->dtxDecoderState),
+ st->lsfState.past_lsf_q,
+ synth,
+ pOverflow);
+
+ /* store bfi for next subframe */
+ st->prev_bf = bfi;
+ st->prev_pdf = pdfi;
+
+ /*--------------------------------------------------*
+ * Calculate the LSF averages on the eight *
+ * previous frames *
+ *--------------------------------------------------*/
+ lsp_avg(
+ &(st->lsp_avg_st),
+ st->lsfState.past_lsf_q,
+ pOverflow);
+
+the_end:
+ st->dtxDecoderState.dtxGlobalState = newDTXState;
+
+// return(0);
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_amr.h b/media/libstagefright/codecs/amrnb/dec/src/dec_amr.h
new file mode 100644
index 0000000..b04137d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/dec_amr.h
@@ -0,0 +1,206 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/dec_amr.h
+
+ Date: 02/06/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Update function prototype for Decoder_amr(). Include overflow
+ flag in Decode_amrState structure
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : dec_amr.h
+ Purpose : Speech decoder routine.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef DEC_AMR_H
+#define DEC_AMR_H "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+#include "mode.h"
+#include "dtx_dec.h"
+#include "d_plsf.h"
+#include "gc_pred.h"
+#include "ec_gains.h"
+#include "ph_disp.h"
+#include "c_g_aver.h"
+#include "bgnscd.h"
+#include "lsp_avg.h"
+#include "frame.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define EXC_ENERGY_HIST_LEN 9
+#define LTP_GAIN_HISTORY_LEN 9
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct Decoder_amrState
+ {
+ /* Excitation vector */
+ Word16 old_exc[L_SUBFR + PIT_MAX + L_INTERPOL];
+ Word16 *exc;
+
+ /* Lsp (Line spectral pairs) */
+ /* Word16 lsp[M]; */ /* Used by CN codec */
+ Word16 lsp_old[M];
+
+ /* Filter's memory */
+ Word16 mem_syn[M];
+
+ /* pitch sharpening */
+ Word16 sharp;
+ Word16 old_T0;
+
+ /* Memories for bad frame handling */
+ Word16 prev_bf;
+ Word16 prev_pdf;
+ Word16 state;
+ Word16 excEnergyHist[EXC_ENERGY_HIST_LEN];
+
+ /* Variable holding received ltpLag, used in background noise and BFI */
+ Word16 T0_lagBuff;
+
+ /* Variables for the source characteristic detector (SCD) */
+ Word16 inBackgroundNoise;
+ Word16 voicedHangover;
+ Word16 ltpGainHistory[LTP_GAIN_HISTORY_LEN];
+
+ Bgn_scdState background_state;
+ Word16 nodataSeed;
+
+ Cb_gain_averageState Cb_gain_averState;
+ lsp_avgState lsp_avg_st;
+
+ D_plsfState lsfState;
+ ec_gain_pitchState ec_gain_p_st;
+ ec_gain_codeState ec_gain_c_st;
+ gc_predState pred_state;
+ ph_dispState ph_disp_st;
+ dtx_decState dtxDecoderState;
+ Flag overflow;
+ } Decoder_amrState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ /*
+ * Function : Decoder_amr_init
+ * Purpose : Allocates initializes state memory
+ * Description : Stores pointer to filter status struct in *st. This
+ * pointer has to be passed to Decoder_amr in each call.
+ * Returns : 0 on success
+ */
+ Word16 Decoder_amr_init(Decoder_amrState *st);
+
+ /*
+ * Function : Decoder_amr_reset
+ * Purpose : Resets state memory
+ * Returns : 0 on success
+ */
+ Word16 Decoder_amr_reset(Decoder_amrState *st, enum Mode mode);
+
+ /*
+ * Function : Decoder_amr
+ * Purpose : Speech decoder routine.
+ * Returns : 0
+ */
+ void Decoder_amr(
+ Decoder_amrState *st, /* i/o : State variables */
+ enum Mode mode, /* i : AMR mode */
+ Word16 parm[], /* i : vector of synthesis parameters
+ (PRM_SIZE) */
+ enum RXFrameType frame_type, /* i : received frame type */
+ Word16 synth[], /* o : synthesis speech (L_FRAME) */
+ Word16 A_t[] /* o : decoded LP filter in 4 subframes
+ (AZ_SIZE) */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DEC_AMR_H_ */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_gain.cpp b/media/libstagefright/codecs/amrnb/dec/src/dec_gain.cpp
new file mode 100644
index 0000000..ceab48d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/dec_gain.cpp
@@ -0,0 +1,305 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/dec_gain.c
+ Funtions: dec_gain
+
+ Date: 01/31/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updating include file lists, and other things as per review
+ comments.
+
+ Description: Added fixes to the code as per review comments. Removed nested
+ function calls and declared temp2 as a variable.
+
+ Description: A Word32 was being stored improperly in a Word16.
+
+ Description: Removed qua_gain.tab and qgain475.tab from Include section and
+ added qua_gain_tbl.h and qgain475_tab.h to Include section.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Added casting to eliminate warnings
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "dec_gain.h"
+#include "typedef.h"
+#include "mode.h"
+#include "cnst.h"
+#include "pow2.h"
+#include "log2.h"
+#include "gc_pred.h"
+#include "basic_op.h"
+#include "qua_gain_tbl.h"
+#include "qgain475_tab.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: dec_gain
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pred_state = pointer to MA predictor state of type gc_predState
+ index = AMR mode of type enum Mode
+ code[] = pointer to innovative vector of type Word16
+ evenSubfr = Flag for even subframes of type Word16
+ pOverflow = pointer to overflow flag
+
+
+ Outputs:
+ pred_state = pointer to MA predictor state of type gc_predState
+ gain_pit = pointer to pitch gain of type Word16
+ gain_cod = pointer to code gain of type Word16
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ File : dec_gain.c
+ Purpose : Decode the pitch and codebook gains
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ agc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+
+
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+
+void Dec_gain(
+ gc_predState *pred_state, /* i/o: MA predictor state */
+ enum Mode mode, /* i : AMR mode */
+ Word16 index, /* i : index of quantization. */
+ Word16 code[], /* i : Innovative vector. */
+ Word16 evenSubfr, /* i : Flag for even subframes */
+ Word16 * gain_pit, /* o : Pitch gain. */
+ Word16 * gain_cod, /* o : Code gain. */
+ Flag * pOverflow
+)
+{
+ const Word16 *p;
+ Word16 frac;
+ Word16 gcode0;
+ Word16 exp;
+ Word16 qua_ener;
+ Word16 qua_ener_MR122;
+ Word16 g_code;
+ Word32 L_tmp;
+ Word16 temp1;
+ Word16 temp2;
+
+ /* Read the quantized gains (table depends on mode) */
+ index = shl(index, 2, pOverflow);
+
+ if (mode == MR102 || mode == MR74 || mode == MR67)
+ {
+ p = &table_gain_highrates[index];
+
+ *gain_pit = *p++;
+ g_code = *p++;
+ qua_ener_MR122 = *p++;
+ qua_ener = *p;
+ }
+ else
+ {
+ if (mode == MR475)
+ {
+ index += (1 ^ evenSubfr) << 1; /* evenSubfr is 0 or 1 */
+
+ if (index > (MR475_VQ_SIZE*4 - 2))
+ {
+ index = (MR475_VQ_SIZE * 4 - 2); /* avoid possible buffer overflow */
+ }
+
+ p = &table_gain_MR475[index];
+
+ *gain_pit = *p++;
+ g_code = *p++;
+
+ /*---------------------------------------------------------*
+ * calculate predictor update values (not stored in 4.75 *
+ * quantizer table to save space): *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * qua_ener = log2(g) *
+ * qua_ener_MR122 = 20*log10(g) *
+ *---------------------------------------------------------*/
+
+ /* Log2(x Q12) = log2(x) + 12 */
+ temp1 = (Word16) L_deposit_l(g_code);
+ Log2(temp1, &exp, &frac, pOverflow);
+ exp = sub(exp, 12, pOverflow);
+
+ temp1 = shr_r(frac, 5, pOverflow);
+ temp2 = shl(exp, 10, pOverflow);
+ qua_ener_MR122 = add(temp1, temp2, pOverflow);
+
+ /* 24660 Q12 ~= 6.0206 = 20*log10(2) */
+ L_tmp = Mpy_32_16(exp, frac, 24660, pOverflow);
+ L_tmp = L_shl(L_tmp, 13, pOverflow);
+ qua_ener = pv_round(L_tmp, pOverflow);
+ /* Q12 * Q0 = Q13 -> Q10 */
+ }
+ else
+ {
+ p = &table_gain_lowrates[index];
+
+ *gain_pit = *p++;
+ g_code = *p++;
+ qua_ener_MR122 = *p++;
+ qua_ener = *p;
+ }
+ }
+
+ /*-------------------------------------------------------------------*
+ * predict codebook gain *
+ * ~~~~~~~~~~~~~~~~~~~~~ *
+ * gc0 = Pow2(int(d)+frac(d)) *
+ * = 2^exp + 2^frac *
+ * *
+ * gcode0 (Q14) = 2^14*2^frac = gc0 * 2^(14-exp) *
+ *-------------------------------------------------------------------*/
+
+ gc_pred(pred_state, mode, code, &exp, &frac, NULL, NULL, pOverflow);
+
+ gcode0 = (Word16) Pow2(14, frac, pOverflow);
+
+ /*------------------------------------------------------------------*
+ * read quantized gains, update table of past quantized energies *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * st->past_qua_en(Q10) = 20 * Log10(g_fac) / constant *
+ * = Log2(g_fac) *
+ * = qua_ener *
+ * constant = 20*Log10(2) *
+ *------------------------------------------------------------------*/
+
+ L_tmp = L_mult(g_code, gcode0, pOverflow);
+ temp1 = sub(10, exp, pOverflow);
+ L_tmp = L_shr(L_tmp, temp1, pOverflow);
+ *gain_cod = extract_h(L_tmp);
+
+ /* update table of past quantized energies */
+
+ gc_pred_update(pred_state, qua_ener_MR122, qua_ener);
+
+ return;
+}
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_gain.h b/media/libstagefright/codecs/amrnb/dec/src/dec_gain.h
new file mode 100644
index 0000000..b9c6a8d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/dec_gain.h
@@ -0,0 +1,127 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/dec_gain.h
+
+ Date: 01/31/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : dec_gain.h
+ Purpose : Decode the pitch and codebook gains
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _DEC_GAIN_H_
+#define _DEC_GAIN_H_
+#define dec_gain_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "gc_pred.h"
+#include "mode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*
+ * FUNCTION: Dec_gain()
+ * PURPOSE: Decode the pitch and codebook gains
+ */
+ void Dec_gain(
+ gc_predState *pred_state, /* i/o: MA predictor state */
+ enum Mode mode, /* i : AMR mode */
+ Word16 index, /* i : index of quantization. */
+ Word16 code[], /* i : Innovative vector. */
+ Word16 evenSubfr, /* i : Flag for even subframes */
+ Word16 * gain_pit, /* o : Pitch gain. */
+ Word16 * gain_cod, /* o : Code gain. */
+ Flag * pOverflow
+ );
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DEC_GAIN_H_ */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_input_format_tab.cpp b/media/libstagefright/codecs/amrnb/dec/src/dec_input_format_tab.cpp
new file mode 100644
index 0000000..fffbbfd
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/dec_input_format_tab.cpp
@@ -0,0 +1,233 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+ Pathname: .audio/gsm-amr/c/src/dec_input_format_tab.c
+
+ Date: 03/01/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Renamed BytesThisFrame to WmfBytesPerFrame, changed its type
+ from 'const short' to 'const int'. Added If2BytesPerFrame
+ table for IF2 input format. Updated copyright year and I/O
+ definition sections, and added reference document for IF2.
+
+ Description: Renamed WmfBytesPerFrame to WmfDecBytesPerFrame, and
+ If2BytesPerFrame to If2DecBytesPerFrame.
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This file contains the tables of the number of data bytes per codec mode in
+ both WMF and IF2 input formats.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] AMR Speech Codec Frame Structure, 3GPP TS 26.101 version 4.1.0 Release 4,
+ June 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "amrdecode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+ /* Table containing the number of core AMR data bytes for */
+ /* each codec mode for WMF input format(number excludes frame type byte) */
+ const Word16 WmfDecBytesPerFrame[16] =
+ {
+ 12, /* 4.75 */
+ 13, /* 5.15 */
+ 15, /* 5.90 */
+ 17, /* 6.70 */
+ 19, /* 7.40 */
+ 20, /* 7.95 */
+ 26, /* 10.2 */
+ 31, /* 12.2 */
+ 5, /* GsmAmr comfort noise */
+ 6, /* Gsm-Efr comfort noise */
+ 5, /* IS-641 comfort noise */
+ 5, /* Pdc-Efr comfort noise */
+ 0, /* future use */
+ 0, /* future use */
+ 0, /* future use */
+ 0 /* No transmission */
+ };
+
+ /* Table containing the number of core AMR data bytes for */
+ /* each codec mode for IF2 input format. */
+ const Word16 If2DecBytesPerFrame[16] =
+ {
+ 13, /* 4.75 */
+ 14, /* 5.15 */
+ 16, /* 5.90 */
+ 18, /* 6.70 */
+ 19, /* 7.40 */
+ 21, /* 7.95 */
+ 26, /* 10.2 */
+ 31, /* 12.2 */
+ 6, /* GsmAmr comfort noise */
+ 6, /* Gsm-Efr comfort noise */
+ 6, /* IS-641 comfort noise */
+ 6, /* Pdc-Efr comfort noise */
+ 0, /* future use */
+ 0, /* future use */
+ 0, /* future use */
+ 1 /* No transmission */
+ };
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL FUNCTION REFERENCES
+ ; Declare functions defined elsewhere and referenced in this module
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; Define all local variables
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Function body here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Return nothing or data or data pointer
+----------------------------------------------------------------------------*/
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_lag3.cpp b/media/libstagefright/codecs/amrnb/dec/src/dec_lag3.cpp
new file mode 100644
index 0000000..70baaba
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/dec_lag3.cpp
@@ -0,0 +1,407 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/dec_lag3.c
+ Functions: Dec_lag3
+
+ Date: 01/31/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ (1) Updated to accept new parameter, Flag *pOverflow.
+ (2) Placed file in the proper PV Software template.
+
+ Description:
+ (1) Removed "count.h" and "basic_op.h" and replaced with individual include
+ files (add.h, sub.h, etc.)
+
+ Description:
+ (1) Removed optimization -- mult(i, 3, pOverflow) is NOT the same as adding
+ i to itself 3 times. The reason is because the mult function does a
+ right shift by 15, which will obliterate smaller numbers.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ index -- Word16 -- received pitch index
+ t0_min -- Word16 -- minimum of search range
+ t0_max -- Word16 -- maximum of search range
+ i_subfr -- Word16 -- subframe flag
+ T0_prev -- Word16 -- integer pitch delay of last subframe
+ used in 2nd and 4th subframes
+ flag4 -- Word16 -- flag for encoding with 4 bits
+
+ Outputs:
+
+ T0 -- Pointer to type Word16 -- integer part of pitch lag
+ T0_frac -- Pointer to type Word16 -- fractional part of pitch lag
+ pOverflow -- Pointer to type Flag -- Flag set when overflow occurs
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+
+ )
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Decoding of fractional pitch lag with 1/3 resolution.
+ Extract the integer and fraction parts of the pitch lag from
+ the received adaptive codebook index.
+
+ See "Enc_lag3.c" for more details about the encoding procedure.
+
+ The fractional lag in 1st and 3rd subframes is encoded with 8 bits
+ while that in 2nd and 4th subframes is relatively encoded with 4, 5
+ and 6 bits depending on the mode.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dec_lag3.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "dec_lag3.h"
+#include "typedef.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void Dec_lag3(Word16 index, /* i : received pitch index */
+ Word16 t0_min, /* i : minimum of search range */
+ Word16 t0_max, /* i : maximum of search range */
+ Word16 i_subfr, /* i : subframe flag */
+ Word16 T0_prev, /* i : integer pitch delay of last subframe
+ used in 2nd and 4th subframes */
+ Word16 * T0, /* o : integer part of pitch lag */
+ Word16 * T0_frac, /* o : fractional part of pitch lag */
+ Word16 flag4, /* i : flag for encoding with 4 bits */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+ )
+{
+ Word16 i;
+ Word16 tmp_lag;
+
+ if (i_subfr == 0) /* if 1st or 3rd subframe */
+ {
+
+ if (index < 197)
+ {
+
+ tmp_lag = index + 2;
+
+ tmp_lag =
+ mult(
+ tmp_lag,
+ 10923,
+ pOverflow);
+
+ i =
+ add(
+ tmp_lag,
+ 19,
+ pOverflow);
+
+ *T0 = i;
+
+ /* i = 3 * (*T0) */
+
+ i = add(i, i, pOverflow);
+ i = add(i, *T0, pOverflow);
+
+ tmp_lag =
+ sub(
+ index,
+ i,
+ pOverflow);
+
+ *T0_frac =
+ add(
+ tmp_lag,
+ 58,
+ pOverflow);
+ }
+ else
+ {
+ *T0 = index - 112;
+
+ *T0_frac = 0;
+ }
+
+ }
+ else
+ { /* 2nd or 4th subframe */
+
+ if (flag4 == 0)
+ {
+
+ /* 'normal' decoding: either with 5 or 6 bit resolution */
+
+ i =
+ add(
+ index,
+ 2,
+ pOverflow);
+
+ i =
+ mult(
+ i,
+ 10923,
+ pOverflow);
+
+ i =
+ sub(
+ i,
+ 1,
+ pOverflow);
+
+ *T0 =
+ add(
+ i,
+ t0_min,
+ pOverflow);
+
+ /* i = 3* (*T0) */
+ i = add(add(i, i, pOverflow), i, pOverflow);
+
+ tmp_lag =
+ sub(
+ index,
+ 2,
+ pOverflow);
+
+ *T0_frac =
+ sub(
+ tmp_lag,
+ i,
+ pOverflow);
+ }
+ else
+ {
+
+ /* decoding with 4 bit resolution */
+
+ tmp_lag = T0_prev;
+
+ i =
+ sub(
+ tmp_lag,
+ t0_min,
+ pOverflow);
+
+ if (i > 5)
+ {
+ tmp_lag =
+ add(
+ t0_min,
+ 5,
+ pOverflow);
+ }
+
+ i =
+ sub(
+ t0_max,
+ tmp_lag,
+ pOverflow);
+
+ if (i > 4)
+ {
+ tmp_lag =
+ sub(
+ t0_max,
+ 4,
+ pOverflow);
+ }
+
+ if (index < 4)
+ {
+ i =
+ sub(
+ tmp_lag,
+ 5,
+ pOverflow);
+
+ *T0 =
+ add(
+ i,
+ index,
+ pOverflow);
+
+ *T0_frac = 0;
+ }
+ else
+ {
+ /* 4 >= index < 12 */
+ if (index < 12)
+ {
+ i = index - 5;
+
+ i = mult(
+ i,
+ 10923,
+ pOverflow);
+
+ i--;
+
+ *T0 = add(
+ i,
+ tmp_lag,
+ pOverflow);
+
+ i = add(
+ add(
+ i,
+ i,
+ pOverflow),
+ i,
+ pOverflow);
+
+ tmp_lag = index - 9;
+
+ *T0_frac =
+ sub(
+ tmp_lag,
+ i,
+ pOverflow);
+ }
+ else
+ {
+ i = index - 12;
+
+ i =
+ add(
+ i,
+ tmp_lag,
+ pOverflow);
+
+ *T0 =
+ add(
+ i,
+ 1,
+ pOverflow);
+
+ *T0_frac = 0;
+ }
+ }
+
+ } /* end if (decoding with 4 bit resolution) */
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_lag3.h b/media/libstagefright/codecs/amrnb/dec/src/dec_lag3.h
new file mode 100644
index 0000000..e758b92
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/dec_lag3.h
@@ -0,0 +1,127 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/dec_lag3.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the dec_lag3.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef dec_lag3_h
+#define dec_lag3_h "$Id $"
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void Dec_lag3(Word16 index, /* i : received pitch index */
+ Word16 T0_min, /* i : minimum of search range */
+ Word16 T0_max, /* i : maximum of search range */
+ Word16 i_subfr, /* i : subframe flag */
+ Word16 T0_prev, /* i : integer pitch delay of last subframe
+ used in 2nd and 4th subframes */
+ Word16 * T0, /* o : integer part of pitch lag */
+ Word16 * T0_frac, /* o : fractional part of pitch lag */
+ Word16 flag4, /* i : flag for encoding with 4 bits */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DEC_LAG_3_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_lag6.cpp b/media/libstagefright/codecs/amrnb/dec/src/dec_lag6.cpp
new file mode 100644
index 0000000..7dc7a8d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/dec_lag6.cpp
@@ -0,0 +1,337 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/dec_lag6.c
+ Functions: Dec_lag6
+
+ Date: 01/31/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ (1) Updated to accept new parameter, Flag *pOverflow.
+ (2) Placed file in the proper PV Software template.
+
+ Description:
+ (1) Removed "count.h" and "basic_op.h" and replaced with individual include
+ files (add.h, sub.h, etc.)
+
+ Description:
+ (1) Removed optimization -- mult(i, 3, pOverflow) is NOT the same as adding
+ i to itself 3 times. The reason is because the mult function does a
+ right shift by 15, which will obliterate smaller numbers.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ index -- Word16 -- received pitch index
+ pit_min -- Word16 -- minimum pitch lag
+ pit_max -- Word16 -- maximum pitch lag
+ i_subfr -- Word16 -- subframe flag
+ T0 -- Pointer to type Word16 -- integer part of pitch lag
+
+ Outputs:
+
+ T0 -- Pointer to type Word16 -- integer part of pitch lag
+ T0_frac -- Pointer to type Word16 -- fractional part of pitch lag
+ pOverflow -- Pointer to type Flag -- Flag set when overflow occurs
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Decoding of fractional pitch lag with 1/6 resolution.
+ Extract the integer and fraction parts of the pitch lag from
+ the received adaptive codebook index.
+
+ See "Enc_lag6.c" for more details about the encoding procedure.
+
+ The fractional lag in 1st and 3rd subframes is encoded with 9 bits
+ while that in 2nd and 4th subframes is relatively encoded with 6 bits.
+ Note that in relative encoding only 61 values are used. If the
+ decoder receives 61, 62, or 63 as the relative pitch index, it means
+ that a transmission error occurred. In this case, the pitch lag from
+ previous subframe (actually from previous frame) is used.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dec_lag6.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "dec_lag6.h"
+#include "typedef.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void Dec_lag6(
+ Word16 index, /* input : received pitch index */
+ Word16 pit_min, /* input : minimum pitch lag */
+ Word16 pit_max, /* input : maximum pitch lag */
+ Word16 i_subfr, /* input : subframe flag */
+ Word16 *T0, /* in/out: integer part of pitch lag */
+ Word16 *T0_frac, /* output: fractional part of pitch lag */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word16 T0_min;
+ Word16 T0_max;
+ Word16 k;
+ Word16 w;
+
+ if (i_subfr == 0) /* if 1st or 3rd subframe */
+ {
+ if (index < 463)
+ {
+ /* T0 = (index+5)/6 + 17 */
+ i = index + 5;
+ i =
+ mult(
+ i,
+ 5462,
+ pOverflow);
+
+ i =
+ add(
+ i,
+ 17,
+ pOverflow);
+
+ *T0 = i;
+
+ /* i = 3* (*T0) */
+
+ i = add(i, i, pOverflow);
+ i = add(i, *T0, pOverflow);
+
+ /* *T0_frac = index - T0*6 + 105 */
+
+ i =
+ add(
+ i,
+ i,
+ pOverflow);
+
+ i =
+ sub(
+ index,
+ i,
+ pOverflow);
+
+ *T0_frac =
+ add(
+ i,
+ 105,
+ pOverflow);
+ }
+ else
+ {
+ *T0 =
+ sub(
+ index,
+ 368,
+ pOverflow);
+
+ *T0_frac = 0;
+ }
+ }
+ else /* second or fourth subframe */
+ {
+ /* find T0_min and T0_max for 2nd (or 4th) subframe */
+
+ T0_min =
+ sub(
+ *T0,
+ 5,
+ pOverflow);
+
+ if (T0_min < pit_min)
+ {
+ T0_min = pit_min;
+ }
+
+ T0_max =
+ add(
+ T0_min,
+ 9,
+ pOverflow);
+
+ if (T0_max > pit_max)
+ {
+ T0_max = pit_max;
+
+ T0_min =
+ sub(
+ T0_max,
+ 9,
+ pOverflow);
+ }
+
+ /* i = (index+5)/6 - 1 */
+ i =
+ add(
+ index,
+ 5,
+ pOverflow);
+
+ i =
+ mult(
+ i,
+ 5462,
+ pOverflow);
+
+ i =
+ sub(
+ i,
+ 1,
+ pOverflow);
+
+ *T0 =
+ add(
+ i,
+ T0_min,
+ pOverflow);
+
+ /* i = 3* (*T0) */
+
+ w = add(i, i, pOverflow);
+ i = add(i, w, pOverflow);
+
+ i =
+ add(
+ i,
+ i,
+ pOverflow);
+
+ k =
+ sub(
+ index,
+ 3,
+ pOverflow);
+
+ *T0_frac =
+ sub(
+ k,
+ i,
+ pOverflow);
+ }
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dec_lag6.h b/media/libstagefright/codecs/amrnb/dec/src/dec_lag6.h
new file mode 100644
index 0000000..7322bc8
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/dec_lag6.h
@@ -0,0 +1,124 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/dec_lag6.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the dec_lag6.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef dec_lag6_h
+#define dec_lag6_h "$Id $"
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void Dec_lag6(
+ Word16 index, /* input : received pitch index */
+ Word16 pit_min, /* input : minimum pitch lag */
+ Word16 pit_max, /* input : maximum pitch lag */
+ Word16 i_subfr, /* input : subframe flag */
+ Word16 *T0, /* in/out: integer part of pitch lag */
+ Word16 *T0_frac, /* output: fractional part of pitch lag */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DEC_LAG_6_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dtx_dec.cpp b/media/libstagefright/codecs/amrnb/dec/src/dtx_dec.cpp
new file mode 100644
index 0000000..9d04373
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/dtx_dec.cpp
@@ -0,0 +1,1956 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/dtx_dec.c
+ Functions:
+ dtx_dec_reset
+ dtx_dec
+ dtx_dec_activity_update
+ rx_dtx_handler
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ These modules decode the comfort noise when in DTX.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <string.h>
+
+#include "dtx_dec.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "copy.h"
+#include "set_zero.h"
+#include "mode.h"
+#include "log2.h"
+#include "lsp_az.h"
+#include "pow2.h"
+#include "a_refl.h"
+#include "b_cn_cod.h"
+#include "syn_filt.h"
+#include "lsp_lsf.h"
+#include "reorder.h"
+#include "lsp_tab.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define PN_INITIAL_SEED 0x70816958L /* Pseudo noise generator seed value */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/***************************************************
+ * Scaling factors for the lsp variability operation *
+ ***************************************************/
+static const Word16 lsf_hist_mean_scale[M] =
+{
+ 20000,
+ 20000,
+ 20000,
+ 20000,
+ 20000,
+ 18000,
+ 16384,
+ 8192,
+ 0,
+ 0
+};
+
+/*************************************************
+ * level adjustment for different modes Q11 *
+ *************************************************/
+static const Word16 dtx_log_en_adjust[9] =
+{
+ -1023, /* MR475 */
+ -878, /* MR515 */
+ -732, /* MR59 */
+ -586, /* MR67 */
+ -440, /* MR74 */
+ -294, /* MR795 */
+ -148, /* MR102 */
+ 0, /* MR122 */
+ 0, /* MRDTX */
+};
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: dtx_dec_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type dtx_decState
+
+ Outputs:
+ Structure pointed to by st is initialized to a set of initial values.
+
+ Returns:
+ return_value = 0 if memory was successfully initialized,
+ otherwise returns -1 (int)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Reset of state memory for dtx_dec.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dtx_dec.c, UMTS GSM AMR speech codec, R99 - Version 3.3.0, December 12, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int dtx_dec_reset (dtx_decState *st)
+{
+ int i;
+
+ if (st == (dtx_decState *) NULL){
+ fprintf(stderr, "dtx_dec_reset: invalid parameter\n");
+ return -1;
+ }
+
+ st->since_last_sid = 0;
+ st->true_sid_period_inv = (1 << 13);
+
+ st->log_en = 3500;
+ st->old_log_en = 3500;
+ // low level noise for better performance in DTX handover cases
+
+ st->L_pn_seed_rx = PN_INITIAL_SEED;
+
+ // Initialize state->lsp [] and state->lsp_old []
+ Copy(lsp_init_data, &st->lsp[0], M);
+ Copy(lsp_init_data, &st->lsp_old[0], M);
+
+ st->lsf_hist_ptr = 0;
+ st->log_pg_mean = 0;
+ st->log_en_hist_ptr = 0;
+
+ // initialize decoder lsf history
+ Copy(mean_lsf, &st->lsf_hist[0], M);
+
+ for (i = 1; i < DTX_HIST_SIZE; i++)
+ {
+ Copy(&st->lsf_hist[0], &st->lsf_hist[M*i], M);
+ }
+ Set_zero(st->lsf_hist_mean, M*DTX_HIST_SIZE);
+
+ // initialize decoder log frame energy
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ st->log_en_hist[i] = st->log_en;
+ }
+
+ st->log_en_adjust = 0;
+
+ st->dtxHangoverCount = DTX_HANG_CONST;
+ st->decAnaElapsedCount = 32767;
+
+ st->sid_frame = 0;
+ st->valid_data = 0;
+ st->dtxHangoverAdded = 0;
+
+ st->dtxGlobalState = DTX;
+ st->data_updated = 0;
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 dtx_dec_reset(dtx_decState *st)
+{
+ Word16 i;
+
+ if (st == (dtx_decState *) NULL)
+ {
+ /* fprint(stderr, "dtx_dec_reset: invalid parameter\n"); */
+ return(-1);
+ }
+
+ st->since_last_sid = 0;
+ st->true_sid_period_inv = (1 << 13);
+
+ st->log_en = 3500;
+ st->old_log_en = 3500;
+ /* low level noise for better performance in DTX handover cases*/
+
+ st->L_pn_seed_rx = PN_INITIAL_SEED;
+
+ /* Initialize state->lsp [] */
+ st->lsp[0] = 30000;
+ st->lsp[1] = 26000;
+ st->lsp[2] = 21000;
+ st->lsp[3] = 15000;
+ st->lsp[4] = 8000;
+ st->lsp[5] = 0;
+ st->lsp[6] = -8000;
+ st->lsp[7] = -15000;
+ st->lsp[8] = -21000;
+ st->lsp[9] = -26000;
+
+ /* Initialize state->lsp_old [] */
+ st->lsp_old[0] = 30000;
+ st->lsp_old[1] = 26000;
+ st->lsp_old[2] = 21000;
+ st->lsp_old[3] = 15000;
+ st->lsp_old[4] = 8000;
+ st->lsp_old[5] = 0;
+ st->lsp_old[6] = -8000;
+ st->lsp_old[7] = -15000;
+ st->lsp_old[8] = -21000;
+ st->lsp_old[9] = -26000;
+
+ st->lsf_hist_ptr = 0;
+ st->log_pg_mean = 0;
+ st->log_en_hist_ptr = 0;
+
+ /* initialize decoder lsf history */
+ st->lsf_hist[0] = 1384;
+ st->lsf_hist[1] = 2077;
+ st->lsf_hist[2] = 3420;
+ st->lsf_hist[3] = 5108;
+ st->lsf_hist[4] = 6742;
+ st->lsf_hist[5] = 8122;
+ st->lsf_hist[6] = 9863;
+ st->lsf_hist[7] = 11092;
+ st->lsf_hist[8] = 12714;
+ st->lsf_hist[9] = 13701;
+
+ for (i = 1; i < DTX_HIST_SIZE; i++)
+ {
+ Copy(&st->lsf_hist[0], &st->lsf_hist[M*i], M);
+ }
+ memset(st->lsf_hist_mean, 0, sizeof(Word16)*M*DTX_HIST_SIZE);
+
+ /* initialize decoder log frame energy */
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ st->log_en_hist[i] = st->log_en;
+ }
+
+ st->log_en_adjust = 0;
+
+ st->dtxHangoverCount = DTX_HANG_CONST;
+ st->decAnaElapsedCount = 32767;
+
+ st->sid_frame = 0;
+ st->valid_data = 0;
+ st->dtxHangoverAdded = 0;
+
+ st->dtxGlobalState = DTX;
+ st->data_updated = 0;
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: dtx_dec
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type dtx_decState
+ mem_syn = AMR decoder state
+ lsfState = decoder lsf states
+ predState = prediction states
+ averState = CB gain average states
+ new_state = new DTX state
+ mode = AMR mode
+ parm = Vector of synthesis parameters
+
+ Outputs:
+ st points to an updated structure of type dtx_decState
+ mem_syn = AMR decoder state
+ lsfState = decoder lsf states
+ predState = prediction states
+ averState = CB gain average states
+ synth = synthesised speech
+ A_t = decoded LP filter in 4 subframes
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Decode comfort noise when in DTX.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dtx_dec.c, UMTS GSM AMR speech codec, R99 - Version 3.3.0, December 12, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int dtx_dec(
+ dtx_decState *st, // i/o : State struct
+ Word16 mem_syn[], // i/o : AMR decoder state
+ D_plsfState* lsfState, // i/o : decoder lsf states
+ gc_predState* predState, // i/o : prediction states
+ Cb_gain_averageState* averState, // i/o : CB gain average states
+ enum DTXStateType new_state, // i : new DTX state
+ enum Mode mode, // i : AMR mode
+ Word16 parm[], // i : Vector of synthesis parameters
+ Word16 synth[], // o : synthesised speech
+ Word16 A_t[] // o : decoded LP filter in 4 subframes
+ )
+{
+ Word16 log_en_index;
+ Word16 i, j;
+ Word16 int_fac;
+ Word32 L_log_en_int;
+ Word16 lsp_int[M];
+ Word16 log_en_int_e;
+ Word16 log_en_int_m;
+ Word16 level;
+ Word16 acoeff[M + 1];
+ Word16 refl[M];
+ Word16 pred_err;
+ Word16 ex[L_SUBFR];
+ Word16 ma_pred_init;
+ Word16 log_pg_e, log_pg_m;
+ Word16 log_pg;
+ Flag negative;
+ Word16 lsf_mean;
+ Word32 L_lsf_mean;
+ Word16 lsf_variab_index;
+ Word16 lsf_variab_factor;
+ Word16 lsf_int[M];
+ Word16 lsf_int_variab[M];
+ Word16 lsp_int_variab[M];
+ Word16 acoeff_variab[M + 1];
+
+ Word16 lsf[M];
+ Word32 L_lsf[M];
+ Word16 ptr;
+ Word16 tmp_int_length;
+
+
+ // This function is called if synthesis state is not SPEECH
+ // the globally passed inputs to this function are
+ // st->sid_frame
+ // st->valid_data
+ // st->dtxHangoverAdded
+ // new_state (SPEECH, DTX, DTX_MUTE)
+
+ if ((st->dtxHangoverAdded != 0) &&
+ (st->sid_frame != 0))
+ {
+ // sid_first after dtx hangover period
+ // or sid_upd after dtxhangover
+
+ // set log_en_adjust to correct value
+ st->log_en_adjust = dtx_log_en_adjust[mode];
+
+ ptr = add(st->lsf_hist_ptr, M);
+ if (sub(ptr, 80) == 0)
+ {
+ ptr = 0;
+ }
+ Copy( &st->lsf_hist[st->lsf_hist_ptr],&st->lsf_hist[ptr],M);
+
+ ptr = add(st->log_en_hist_ptr,1);
+ if (sub(ptr, DTX_HIST_SIZE) == 0)
+ {
+ ptr = 0;
+ }
+ st->log_en_hist[ptr] = st->log_en_hist[st->log_en_hist_ptr]; // Q11
+
+ // compute mean log energy and lsp
+ // from decoded signal (SID_FIRST)
+ st->log_en = 0;
+ for (i = 0; i < M; i++)
+ {
+ L_lsf[i] = 0;
+ }
+
+ // average energy and lsp
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ st->log_en = add(st->log_en,
+ shr(st->log_en_hist[i],3));
+ for (j = 0; j < M; j++)
+ {
+ L_lsf[j] = L_add(L_lsf[j],
+ L_deposit_l(st->lsf_hist[i * M + j]));
+ }
+ }
+
+ for (j = 0; j < M; j++)
+ {
+ lsf[j] = extract_l(L_shr(L_lsf[j],3)); // divide by 8
+ }
+
+ Lsf_lsp(lsf, st->lsp, M);
+
+ // make log_en speech coder mode independent
+ // added again later before synthesis
+ st->log_en = sub(st->log_en, st->log_en_adjust);
+
+ // compute lsf variability vector
+ Copy(st->lsf_hist, st->lsf_hist_mean, 80);
+
+ for (i = 0; i < M; i++)
+ {
+ L_lsf_mean = 0;
+ // compute mean lsf
+ for (j = 0; j < 8; j++)
+ {
+ L_lsf_mean = L_add(L_lsf_mean,
+ L_deposit_l(st->lsf_hist_mean[i+j*M]));
+ }
+
+ lsf_mean = extract_l(L_shr(L_lsf_mean, 3));
+ // subtract mean and limit to within reasonable limits
+ // moreover the upper lsf's are attenuated
+ for (j = 0; j < 8; j++)
+ {
+ // subtract mean
+ st->lsf_hist_mean[i+j*M] =
+ sub(st->lsf_hist_mean[i+j*M], lsf_mean);
+
+ // attenuate deviation from mean, especially for upper lsf's
+ st->lsf_hist_mean[i+j*M] =
+ mult(st->lsf_hist_mean[i+j*M], lsf_hist_mean_scale[i]);
+
+ // limit the deviation
+ if (st->lsf_hist_mean[i+j*M] < 0)
+ {
+ negative = 1;
+ }
+ else
+ {
+ negative = 0;
+ }
+ st->lsf_hist_mean[i+j*M] = abs_s(st->lsf_hist_mean[i+j*M]);
+
+ // apply soft limit
+ if (sub(st->lsf_hist_mean[i+j*M], 655) > 0)
+ {
+ st->lsf_hist_mean[i+j*M] =
+ add(655, shr(sub(st->lsf_hist_mean[i+j*M], 655), 2));
+ }
+
+ // apply hard limit
+ if (sub(st->lsf_hist_mean[i+j*M], 1310) > 0)
+ {
+ st->lsf_hist_mean[i+j*M] = 1310;
+ }
+ if (negative != 0)
+ {
+ st->lsf_hist_mean[i+j*M] = -st->lsf_hist_mean[i+j*M];
+ }
+
+ }
+ }
+ }
+
+ if (st->sid_frame != 0 )
+ {
+ // Set old SID parameters, always shift
+ // even if there is no new valid_data
+ Copy(st->lsp, st->lsp_old, M);
+ st->old_log_en = st->log_en;
+
+ if (st->valid_data != 0 ) // new data available (no CRC)
+ {
+ // Compute interpolation factor, since the division only works
+ // for values of since_last_sid < 32 we have to limit the
+ // interpolation to 32 frames
+ tmp_int_length = st->since_last_sid;
+ st->since_last_sid = 0;
+
+ if (sub(tmp_int_length, 32) > 0)
+ {
+ tmp_int_length = 32;
+ }
+ if (sub(tmp_int_length, 2) >= 0)
+ {
+ st->true_sid_period_inv = div_s(1 << 10, shl(tmp_int_length, 10));
+ }
+ else
+ {
+ st->true_sid_period_inv = 1 << 14; // 0.5 it Q15
+ }
+
+ Init_D_plsf_3(lsfState, parm[0]); // temporay initialization
+ D_plsf_3(lsfState, MRDTX, 0, &parm[1], st->lsp);
+ Set_zero(lsfState->past_r_q, M); // reset for next speech frame
+
+ log_en_index = parm[4];
+ // Q11 and divide by 4
+ st->log_en = shl(log_en_index, (11 - 2));
+
+ // Subtract 2.5 in Q11
+ st->log_en = sub(st->log_en, (2560 * 2));
+
+ // Index 0 is reserved for silence
+ if (log_en_index == 0)
+ {
+ st->log_en = MIN_16;
+ }
+
+ // no interpolation at startup after coder reset
+ // or when SID_UPD has been received right after SPEECH
+ if ((st->data_updated == 0) ||
+ (sub(st->dtxGlobalState, SPEECH) == 0)
+ )
+ {
+ Copy(st->lsp, st->lsp_old, M);
+ st->old_log_en = st->log_en;
+ }
+ } // endif valid_data
+
+ // initialize gain predictor memory of other modes
+ ma_pred_init = sub(shr(st->log_en,1), 9000);
+ if (ma_pred_init > 0)
+ {
+ ma_pred_init = 0;
+ }
+ if (sub(ma_pred_init, -14436) < 0)
+ {
+ ma_pred_init = -14436;
+ }
+
+ predState->past_qua_en[0] = ma_pred_init;
+ predState->past_qua_en[1] = ma_pred_init;
+ predState->past_qua_en[2] = ma_pred_init;
+ predState->past_qua_en[3] = ma_pred_init;
+
+ // past_qua_en for other modes than MR122
+ ma_pred_init = mult(5443, ma_pred_init);
+ // scale down by factor 20*log10(2) in Q15
+ predState->past_qua_en_MR122[0] = ma_pred_init;
+ predState->past_qua_en_MR122[1] = ma_pred_init;
+ predState->past_qua_en_MR122[2] = ma_pred_init;
+ predState->past_qua_en_MR122[3] = ma_pred_init;
+ } // endif sid_frame
+
+ // CN generation
+ // recompute level adjustment factor Q11
+ // st->log_en_adjust = 0.9*st->log_en_adjust +
+ // 0.1*dtx_log_en_adjust[mode]);
+ st->log_en_adjust = add(mult(st->log_en_adjust, 29491),
+ shr(mult(shl(dtx_log_en_adjust[mode],5),3277),5));
+
+ // Interpolate SID info
+ int_fac = shl(add(1,st->since_last_sid), 10); // Q10
+ int_fac = mult(int_fac, st->true_sid_period_inv); // Q10 * Q15 -> Q10
+
+ // Maximize to 1.0 in Q10
+ if (sub(int_fac, 1024) > 0)
+ {
+ int_fac = 1024;
+ }
+ int_fac = shl(int_fac, 4); // Q10 -> Q14
+
+ L_log_en_int = L_mult(int_fac, st->log_en); // Q14 * Q11->Q26
+ for(i = 0; i < M; i++)
+ {
+ lsp_int[i] = mult(int_fac, st->lsp[i]);// Q14 * Q15 -> Q14
+ }
+
+ int_fac = sub(16384, int_fac); // 1-k in Q14
+
+ // (Q14 * Q11 -> Q26) + Q26 -> Q26
+ L_log_en_int = L_mac(L_log_en_int, int_fac, st->old_log_en);
+ for(i = 0; i < M; i++)
+ {
+ // Q14 + (Q14 * Q15 -> Q14) -> Q14
+ lsp_int[i] = add(lsp_int[i], mult(int_fac, st->lsp_old[i]));
+ lsp_int[i] = shl(lsp_int[i], 1); // Q14 -> Q15
+ }
+
+ // compute the amount of lsf variability
+ lsf_variab_factor = sub(st->log_pg_mean,2457); // -0.6 in Q12
+ // *0.3 Q12*Q15 -> Q12
+ lsf_variab_factor = sub(4096, mult(lsf_variab_factor, 9830));
+
+ // limit to values between 0..1 in Q12
+ if (sub(lsf_variab_factor, 4096) > 0)
+ {
+ lsf_variab_factor = 4096;
+ }
+ if (lsf_variab_factor < 0)
+ {
+ lsf_variab_factor = 0;
+ }
+ lsf_variab_factor = shl(lsf_variab_factor, 3); // -> Q15
+
+ // get index of vector to do variability with
+ lsf_variab_index = pseudonoise(&st->L_pn_seed_rx, 3);
+
+ // convert to lsf
+ Lsp_lsf(lsp_int, lsf_int, M);
+
+ // apply lsf variability
+ Copy(lsf_int, lsf_int_variab, M);
+ for(i = 0; i < M; i++)
+ {
+ lsf_int_variab[i] = add(lsf_int_variab[i],
+ mult(lsf_variab_factor,
+ st->lsf_hist_mean[i+lsf_variab_index*M]));
+ }
+
+ // make sure that LSP's are ordered
+ Reorder_lsf(lsf_int, LSF_GAP, M);
+ Reorder_lsf(lsf_int_variab, LSF_GAP, M);
+
+ // copy lsf to speech decoders lsf state
+ Copy(lsf_int, lsfState->past_lsf_q, M);
+
+ // convert to lsp
+ Lsf_lsp(lsf_int, lsp_int, M);
+ Lsf_lsp(lsf_int_variab, lsp_int_variab, M);
+
+ // Compute acoeffs Q12 acoeff is used for level
+ // normalization and postfilter, acoeff_variab is
+ // used for synthesis filter
+ // by doing this we make sure that the level
+ // in high frequenncies does not jump up and down
+
+ Lsp_Az(lsp_int, acoeff);
+ Lsp_Az(lsp_int_variab, acoeff_variab);
+
+ // For use in postfilter
+ Copy(acoeff, &A_t[0], M + 1);
+ Copy(acoeff, &A_t[M + 1], M + 1);
+ Copy(acoeff, &A_t[2 * (M + 1)], M + 1);
+ Copy(acoeff, &A_t[3 * (M + 1)], M + 1);
+
+ // Compute reflection coefficients Q15
+ A_Refl(&acoeff[1], refl);
+
+ // Compute prediction error in Q15
+ pred_err = MAX_16; // 0.99997 in Q15
+ for (i = 0; i < M; i++)
+ {
+ pred_err = mult(pred_err, sub(MAX_16, mult(refl[i], refl[i])));
+ }
+
+ // compute logarithm of prediction gain
+ Log2(L_deposit_l(pred_err), &log_pg_e, &log_pg_m);
+
+ // convert exponent and mantissa to Word16 Q12
+ log_pg = shl(sub(log_pg_e,15), 12); // Q12
+ log_pg = shr(sub(0,add(log_pg, shr(log_pg_m, 15-12))), 1);
+ st->log_pg_mean = add(mult(29491,st->log_pg_mean),
+ mult(3277, log_pg));
+
+ // Compute interpolated log energy
+ L_log_en_int = L_shr(L_log_en_int, 10); // Q26 -> Q16
+
+ // Add 4 in Q16
+ L_log_en_int = L_add(L_log_en_int, 4 * 65536L);
+
+ // subtract prediction gain
+ L_log_en_int = L_sub(L_log_en_int, L_shl(L_deposit_l(log_pg), 4));
+
+ // adjust level to speech coder mode
+ L_log_en_int = L_add(L_log_en_int,
+ L_shl(L_deposit_l(st->log_en_adjust), 5));
+
+ log_en_int_e = extract_h(L_log_en_int);
+ log_en_int_m = extract_l(L_shr(L_sub(L_log_en_int,
+ L_deposit_h(log_en_int_e)), 1));
+ level = extract_l(Pow2(log_en_int_e, log_en_int_m)); // Q4
+
+ for (i = 0; i < 4; i++)
+ {
+ // Compute innovation vector
+ build_CN_code(&st->L_pn_seed_rx, ex);
+ for (j = 0; j < L_SUBFR; j++)
+ {
+ ex[j] = mult(level, ex[j]);
+ }
+ // Synthesize
+ Syn_filt(acoeff_variab, ex, &synth[i * L_SUBFR], L_SUBFR,
+ mem_syn, 1);
+
+ } // next i
+
+ // reset codebook averaging variables
+ averState->hangVar = 20;
+ averState->hangCount = 0;
+
+ if (sub(new_state, DTX_MUTE) == 0)
+ {
+ // mute comfort noise as it has been quite a long time since
+ * last SID update was performed
+
+ tmp_int_length = st->since_last_sid;
+ if (sub(tmp_int_length, 32) > 0)
+ {
+ tmp_int_length = 32;
+ }
+
+ // safety guard against division by zero
+ if(tmp_int_length <= 0) {
+ tmp_int_length = 8;
+ }
+
+ st->true_sid_period_inv = div_s(1 << 10, shl(tmp_int_length, 10));
+
+ st->since_last_sid = 0;
+ Copy(st->lsp, st->lsp_old, M);
+ st->old_log_en = st->log_en;
+ // subtract 1/8 in Q11 i.e -6/8 dB
+ st->log_en = sub(st->log_en, 256);
+ }
+
+ // reset interpolation length timer
+ // if data has been updated.
+ if ((st->sid_frame != 0) &&
+ ((st->valid_data != 0) ||
+ ((st->valid_data == 0) && (st->dtxHangoverAdded) != 0)))
+ {
+ st->since_last_sid = 0;
+ st->data_updated = 1;
+ }
+
+ return 0;
+}
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void dtx_dec(
+ dtx_decState *st, /* i/o : State struct */
+ Word16 mem_syn[], /* i/o : AMR decoder state */
+ D_plsfState* lsfState, /* i/o : decoder lsf states */
+ gc_predState* predState, /* i/o : prediction states */
+ Cb_gain_averageState* averState, /* i/o : CB gain average states */
+ enum DTXStateType new_state, /* i : new DTX state */
+ enum Mode mode, /* i : AMR mode */
+ Word16 parm[], /* i : Vector of synthesis parameters */
+ Word16 synth[], /* o : synthesised speech */
+ Word16 A_t[], /* o : decoded LP filter in 4 subframes*/
+ Flag *pOverflow
+)
+{
+ Word16 log_en_index;
+ Word16 i;
+ Word16 j;
+ Word16 int_fac;
+ Word32 L_log_en_int;
+ Word16 lsp_int[M];
+ Word16 log_en_int_e;
+ Word16 log_en_int_m;
+ Word16 level;
+ Word16 acoeff[M + 1];
+ Word16 refl[M];
+ Word16 pred_err;
+ Word16 ex[L_SUBFR];
+ Word16 ma_pred_init;
+ Word16 log_pg_e;
+ Word16 log_pg_m;
+ Word16 log_pg;
+ Flag negative;
+ Word16 lsf_mean;
+ Word32 L_lsf_mean;
+ Word16 lsf_variab_index;
+ Word16 lsf_variab_factor;
+ Word16 lsf_int[M];
+ Word16 lsf_int_variab[M];
+ Word16 lsp_int_variab[M];
+ Word16 acoeff_variab[M + 1];
+
+ Word16 lsf[M];
+ Word32 L_lsf[M];
+ Word16 ptr;
+ Word16 tmp_int_length;
+
+ Word32 L_temp;
+ Word16 temp;
+
+ /* This function is called if synthesis state is not SPEECH
+ * the globally passed inputs to this function are
+ * st->sid_frame
+ * st->valid_data
+ * st->dtxHangoverAdded
+ * new_state (SPEECH, DTX, DTX_MUTE)
+ */
+
+ if ((st->dtxHangoverAdded != 0) &&
+ (st->sid_frame != 0))
+ {
+ /* sid_first after dtx hangover period */
+ /* or sid_upd after dtxhangover */
+
+ /* set log_en_adjust to correct value */
+ st->log_en_adjust = dtx_log_en_adjust[mode];
+
+ ptr = st->lsf_hist_ptr + M;
+
+ if (ptr == 80)
+ {
+ ptr = 0;
+ }
+ Copy(&st->lsf_hist[st->lsf_hist_ptr], &st->lsf_hist[ptr], M);
+
+ ptr = st->log_en_hist_ptr + 1;
+
+ if (ptr == DTX_HIST_SIZE)
+ {
+ ptr = 0;
+ }
+
+ st->log_en_hist[ptr] = st->log_en_hist[st->log_en_hist_ptr]; /* Q11 */
+
+ /* compute mean log energy and lsp *
+ * from decoded signal (SID_FIRST) */
+ st->log_en = 0;
+ for (i = M - 1; i >= 0; i--)
+ {
+ L_lsf[i] = 0;
+ }
+
+ /* average energy and lsp */
+ for (i = DTX_HIST_SIZE - 1; i >= 0; i--)
+ {
+ if (st->log_en_hist[i] < 0)
+ {
+ temp = ~((~st->log_en_hist[i]) >> 3);
+ }
+ else
+ {
+ temp = st->log_en_hist[i] >> 3;
+ }
+ st->log_en = add(st->log_en, temp, pOverflow);
+ for (j = M - 1; j >= 0; j--)
+ {
+ L_lsf[j] = L_add(L_lsf[j],
+ L_deposit_l(st->lsf_hist[i * M + j]), pOverflow);
+ }
+ }
+
+ for (j = M - 1; j >= 0; j--)
+ {
+ if (L_lsf[j] < 0)
+ {
+ lsf[j] = (Word16)(~((~L_lsf[j]) >> 3));
+ }
+ else
+ {
+ lsf[j] = (Word16)(L_lsf[j] >> 3);
+ }
+ }
+
+ Lsf_lsp(lsf, st->lsp, M, pOverflow);
+
+ /* make log_en speech coder mode independent */
+ /* added again later before synthesis */
+ st->log_en = sub(st->log_en, st->log_en_adjust, pOverflow);
+
+ /* compute lsf variability vector */
+ Copy(st->lsf_hist, st->lsf_hist_mean, 80);
+
+ for (i = M - 1; i >= 0; i--)
+ {
+ L_lsf_mean = 0;
+ /* compute mean lsf */
+ for (j = 8 - 1; j >= 0; j--)
+ {
+ L_lsf_mean = L_add(L_lsf_mean,
+ L_deposit_l(st->lsf_hist_mean[i+j*M]), pOverflow);
+ }
+
+ if (L_lsf_mean < 0)
+ {
+ lsf_mean = (Word16)(~((~L_lsf_mean) >> 3));
+ }
+ else
+ {
+ lsf_mean = (Word16)(L_lsf_mean >> 3);
+ }
+ /* subtract mean and limit to within reasonable limits *
+ * moreover the upper lsf's are attenuated */
+ for (j = 8 - 1; j >= 0; j--)
+ {
+ /* subtract mean */
+ st->lsf_hist_mean[i+j*M] =
+ sub(st->lsf_hist_mean[i+j*M], lsf_mean, pOverflow);
+
+ /* attenuate deviation from mean, especially for upper lsf's */
+ st->lsf_hist_mean[i+j*M] =
+ mult(st->lsf_hist_mean[i+j*M], lsf_hist_mean_scale[i], pOverflow);
+
+ /* limit the deviation */
+ if (st->lsf_hist_mean[i+j*M] < 0)
+ {
+ negative = 1;
+ }
+ else
+ {
+ negative = 0;
+ }
+ st->lsf_hist_mean[i+j*M] = abs_s(st->lsf_hist_mean[i+j*M]);
+
+ /* apply soft limit */
+ if (st->lsf_hist_mean[i+j*M] > 655)
+ {
+ st->lsf_hist_mean[i+j*M] = 655 + ((st->lsf_hist_mean[i+j*M]
+ - 655) >> 2);
+ }
+
+ /* apply hard limit */
+ if (st->lsf_hist_mean[i+j*M] > 1310)
+ {
+ st->lsf_hist_mean[i+j*M] = 1310;
+ }
+
+ if (negative != 0)
+ {
+ st->lsf_hist_mean[i+j*M] = -st->lsf_hist_mean[i+j*M];
+ }
+ }
+ }
+ }
+
+
+ if (st->sid_frame != 0)
+ {
+ /* Set old SID parameters, always shift */
+ /* even if there is no new valid_data */
+ Copy(st->lsp, st->lsp_old, M);
+ st->old_log_en = st->log_en;
+
+ if (st->valid_data != 0) /* new data available (no CRC) */
+ {
+ /* Compute interpolation factor, since the division only works *
+ * for values of since_last_sid < 32 we have to limit the *
+ * interpolation to 32 frames */
+ tmp_int_length = st->since_last_sid;
+ st->since_last_sid = 0;
+
+ if (tmp_int_length >= 32)
+ {
+ tmp_int_length = 32;
+ }
+
+ L_temp = ((Word32) tmp_int_length) << 10;
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ *pOverflow = 1;
+ L_temp = (Word32)((tmp_int_length > 0) ? MAX_16 : MIN_16);
+ }
+ temp = (Word16) L_temp;
+
+ if (tmp_int_length >= 2)
+ {
+ st->true_sid_period_inv = div_s(1 << 10, temp);
+ }
+ else
+ {
+ st->true_sid_period_inv = 1 << 14; /* 0.5 it Q15 */
+ }
+
+ Init_D_plsf_3(lsfState, parm[0]);
+ D_plsf_3(lsfState, MRDTX, 0, &parm[1], st->lsp, pOverflow);
+ Set_zero(lsfState->past_r_q, M); /* reset for next speech frame */
+
+ log_en_index = parm[4];
+ /* Q11 and divide by 4 */
+ if ((log_en_index > 63) || (log_en_index < -64))
+ {
+ st->log_en = (log_en_index > 0) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ st->log_en = (log_en_index) << (11 - 2);
+ }
+
+ /* Subtract 2.5 in Q11 */
+ st->log_en = sub(st->log_en, (2560 * 2), pOverflow);
+
+ /* Index 0 is reserved for silence */
+ if (log_en_index == 0)
+ {
+ st->log_en = MIN_16;
+ }
+
+ /* no interpolation at startup after coder reset */
+ /* or when SID_UPD has been received right after SPEECH */
+
+ if ((st->data_updated == 0) ||
+ (st->dtxGlobalState == SPEECH))
+ {
+ Copy(st->lsp, st->lsp_old, M);
+ st->old_log_en = st->log_en;
+ }
+ } /* endif valid_data */
+
+ /* initialize gain predictor memory of other modes */
+ if (st->log_en < 0)
+ {
+ temp = ~((~st->log_en) >> 1);
+ }
+ else
+ {
+ temp = st->log_en >> 1;
+ }
+ ma_pred_init = sub(temp, 9000, pOverflow);
+
+ if (ma_pred_init > 0)
+ {
+ ma_pred_init = 0;
+ }
+ else if (ma_pred_init < -14436)
+ {
+ ma_pred_init = -14436;
+ }
+
+ predState->past_qua_en[0] = ma_pred_init;
+ predState->past_qua_en[1] = ma_pred_init;
+ predState->past_qua_en[2] = ma_pred_init;
+ predState->past_qua_en[3] = ma_pred_init;
+
+ /* past_qua_en for other modes than MR122 */
+ ma_pred_init = mult(5443, ma_pred_init, pOverflow);
+ /* scale down by factor 20*log10(2) in Q15 */
+ predState->past_qua_en_MR122[0] = ma_pred_init;
+ predState->past_qua_en_MR122[1] = ma_pred_init;
+ predState->past_qua_en_MR122[2] = ma_pred_init;
+ predState->past_qua_en_MR122[3] = ma_pred_init;
+ } /* endif sid_frame */
+
+ /* CN generation */
+ /* recompute level adjustment factor Q11 *
+ * st->log_en_adjust = 0.9*st->log_en_adjust + *
+ * 0.1*dtx_log_en_adjust[mode]); */
+ if (dtx_log_en_adjust[mode] > 1023)
+ {
+ temp = MAX_16;
+ }
+ else if (dtx_log_en_adjust[mode] < -1024)
+ {
+ temp = MIN_16;
+ }
+ else
+ {
+ temp = mult((Word16)((Word32)dtx_log_en_adjust[mode] << 5), 3277, pOverflow);
+ }
+
+ if (temp < 0)
+ {
+ temp = ~((~temp) >> 5);
+ }
+ else
+ {
+ temp >>= 5;
+ }
+ st->log_en_adjust = add(mult(st->log_en_adjust, 29491, pOverflow), temp, pOverflow);
+
+ /* Interpolate SID info */
+ int_fac = shl(add(1, st->since_last_sid, pOverflow), 10, pOverflow); /* Q10 */
+ int_fac = mult(int_fac, st->true_sid_period_inv, pOverflow); /* Q10 * Q15 -> Q10 */
+
+ /* Maximize to 1.0 in Q10 */
+ if (int_fac > 1024)
+ {
+ int_fac = 16384;
+ }
+ else if (int_fac < -2048)
+ {
+ int_fac = MIN_16;
+ }
+ else
+ {
+ int_fac <<= 4; /* Q10 -> Q14 */
+ }
+
+ L_log_en_int = L_mult(int_fac, st->log_en, pOverflow); /* Q14 * Q11->Q26 */
+ for (i = M - 1; i >= 0; i--)
+ {
+ lsp_int[i] = mult(int_fac, st->lsp[i], pOverflow);/* Q14 * Q15 -> Q14 */
+ }
+
+ int_fac = sub(16384, int_fac, pOverflow); /* 1-k in Q14 */
+
+ /* (Q14 * Q11 -> Q26) + Q26 -> Q26 */
+ L_log_en_int = L_mac(L_log_en_int, int_fac, st->old_log_en, pOverflow);
+ for (i = M - 1; i >= 0; i--)
+ {
+ /* Q14 + (Q14 * Q15 -> Q14) -> Q14 */
+ lsp_int[i] = add(lsp_int[i], mult(int_fac, st->lsp_old[i], pOverflow), pOverflow);
+
+ L_temp = ((Word32) lsp_int[i]) << 1; /* Q14 -> Q15 */
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ *pOverflow = 1;
+ L_temp = (Word32)((lsp_int[i] > 0) ? MAX_16 : MIN_16);
+ }
+ lsp_int[i] = (Word16) L_temp;
+ }
+
+ /* compute the amount of lsf variability */
+ lsf_variab_factor = sub(st->log_pg_mean, 2457, pOverflow); /* -0.6 in Q12 */
+ /* *0.3 Q12*Q15 -> Q12 */
+ lsf_variab_factor = sub(4096, mult(lsf_variab_factor, 9830, pOverflow), pOverflow);
+
+ /* limit to values between 0..1 in Q12 */
+ if (lsf_variab_factor > 4095)
+ {
+ lsf_variab_factor = MAX_16;
+ }
+ else if (lsf_variab_factor < 0)
+ {
+ lsf_variab_factor = 0;
+ }
+ else
+ {
+ lsf_variab_factor <<= 3; /* -> Q15 */
+ }
+
+ /* get index of vector to do variability with */
+ lsf_variab_index = pseudonoise(&st->L_pn_seed_rx, 3);
+
+ /* convert to lsf */
+ Lsp_lsf(lsp_int, lsf_int, M, pOverflow);
+
+ /* apply lsf variability */
+ Copy(lsf_int, lsf_int_variab, M);
+ for (i = M - 1; i >= 0; i--)
+ {
+ lsf_int_variab[i] = add(lsf_int_variab[i],
+ mult(lsf_variab_factor,
+ st->lsf_hist_mean[i+lsf_variab_index*M], pOverflow)
+ , pOverflow);
+ }
+
+ /* make sure that LSP's are ordered */
+ Reorder_lsf(lsf_int, LSF_GAP, M, pOverflow);
+ Reorder_lsf(lsf_int_variab, LSF_GAP, M, pOverflow);
+
+ /* copy lsf to speech decoders lsf state */
+ Copy(lsf_int, lsfState->past_lsf_q, M);
+
+ /* convert to lsp */
+ Lsf_lsp(lsf_int, lsp_int, M, pOverflow);
+ Lsf_lsp(lsf_int_variab, lsp_int_variab, M, pOverflow);
+
+ /* Compute acoeffs Q12 acoeff is used for level *
+ * normalization and postfilter, acoeff_variab is *
+ * used for synthesis filter *
+ * by doing this we make sure that the level *
+ * in high frequenncies does not jump up and down */
+
+ Lsp_Az(lsp_int, acoeff, pOverflow);
+ Lsp_Az(lsp_int_variab, acoeff_variab, pOverflow);
+
+ /* For use in postfilter */
+ Copy(acoeff, &A_t[0], M + 1);
+ Copy(acoeff, &A_t[M + 1], M + 1);
+ Copy(acoeff, &A_t[2 *(M + 1)], M + 1);
+ Copy(acoeff, &A_t[3 *(M + 1)], M + 1);
+
+ /* Compute reflection coefficients Q15 */
+ A_Refl(&acoeff[1], refl, pOverflow);
+
+ /* Compute prediction error in Q15 */
+ pred_err = MAX_16; /* 0.99997 in Q15 */
+ for (i = 0; i < M; i++)
+ {
+ L_temp = (((Word32) refl[i]) * refl[i]) >> 15;
+ if (L_temp <= 0x00007fffL)
+ {
+ temp = MAX_16 - (Word16) L_temp;
+ }
+ else
+ {
+ *pOverflow = 1;
+ temp = 0;
+ }
+ pred_err = mult(pred_err, temp, pOverflow);
+ }
+
+ /* compute logarithm of prediction gain */
+ Log2(L_deposit_l(pred_err), &log_pg_e, &log_pg_m, pOverflow);
+
+ /* convert exponent and mantissa to Word16 Q12 */
+ log_pg = shl(sub(log_pg_e, 15, pOverflow), 12, pOverflow); /* Q12 */
+ log_pg = shr(sub(0, add(log_pg, shr(log_pg_m, 15 - 12, pOverflow),
+ pOverflow), pOverflow), 1, pOverflow);
+ st->log_pg_mean = add(mult(29491, st->log_pg_mean, pOverflow),
+ mult(3277, log_pg, pOverflow), pOverflow);
+
+ /* Compute interpolated log energy */
+ L_log_en_int = L_shr(L_log_en_int, 10, pOverflow); /* Q26 -> Q16 */
+
+ /* Add 4 in Q16 */
+ L_log_en_int = L_add(L_log_en_int, 4 * 65536L, pOverflow);
+
+ /* subtract prediction gain */
+ L_log_en_int = L_sub(L_log_en_int, L_shl(L_deposit_l(log_pg), 4, pOverflow), pOverflow);
+
+ /* adjust level to speech coder mode */
+ L_log_en_int = L_add(L_log_en_int,
+ L_shl(L_deposit_l(st->log_en_adjust), 5, pOverflow), pOverflow);
+
+ log_en_int_e = (Word16)(L_log_en_int >> 16);
+
+ log_en_int_m = (Word16)(L_shr(L_sub(L_log_en_int,
+ L_deposit_h(log_en_int_e), pOverflow), 1, pOverflow));
+ level = (Word16)(Pow2(log_en_int_e, log_en_int_m, pOverflow)); /* Q4 */
+
+ for (i = 0; i < 4; i++)
+ {
+ /* Compute innovation vector */
+ build_CN_code(&st->L_pn_seed_rx, ex, pOverflow);
+ for (j = L_SUBFR - 1; j >= 0; j--)
+ {
+ ex[j] = mult(level, ex[j], pOverflow);
+ }
+ /* Synthesize */
+ Syn_filt(acoeff_variab, ex, &synth[i * L_SUBFR], L_SUBFR,
+ mem_syn, 1);
+
+ } /* next i */
+
+ /* reset codebook averaging variables */
+ averState->hangVar = 20;
+ averState->hangCount = 0;
+
+ if (new_state == DTX_MUTE)
+ {
+ /* mute comfort noise as it has been quite a long time since
+ * last SID update was performed */
+
+ tmp_int_length = st->since_last_sid;
+
+ if (tmp_int_length > 32)
+ {
+ tmp_int_length = 32;
+ }
+ else if (tmp_int_length <= 0)
+ {
+ /* safety guard against division by zero */
+ tmp_int_length = 8;
+ }
+
+ L_temp = ((Word32) tmp_int_length) << 10;
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ *pOverflow = 1;
+ L_temp = (Word32)((tmp_int_length > 0) ? MAX_16 : MIN_16);
+ }
+ temp = (Word16) L_temp;
+
+ st->true_sid_period_inv = div_s(1 << 10, temp);
+
+ st->since_last_sid = 0;
+ Copy(st->lsp, st->lsp_old, M);
+ st->old_log_en = st->log_en;
+ /* subtract 1/8 in Q11 i.e -6/8 dB */
+ st->log_en = sub(st->log_en, 256, pOverflow);
+ }
+
+ /* reset interpolation length timer
+ * if data has been updated. */
+ if ((st->sid_frame != 0) &&
+ ((st->valid_data != 0) ||
+ ((st->valid_data == 0) && (st->dtxHangoverAdded) != 0)))
+ {
+ st->since_last_sid = 0;
+ st->data_updated = 1;
+ }
+
+ return;
+}
+
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: dtx_dec_activity_update
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type dtx_decState
+ lsf =
+ frame =
+
+ Outputs:
+ st points to an updated structure of type dtx_decState
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function updates the DTX parameters.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dtx_dec.c, UMTS GSM AMR speech codec, R99 - Version 3.3.0, December 12, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void dtx_dec_activity_update(dtx_decState *st,
+ Word16 lsf[],
+ Word16 frame[])
+{
+ Word16 i;
+
+ Word32 L_frame_en;
+ Word16 log_en_e, log_en_m, log_en;
+
+ // update lsp history
+ st->lsf_hist_ptr = add(st->lsf_hist_ptr,M);
+ if (sub(st->lsf_hist_ptr, 80) == 0)
+ {
+ st->lsf_hist_ptr = 0;
+ }
+ Copy(lsf, &st->lsf_hist[st->lsf_hist_ptr], M);
+
+ // compute log energy based on frame energy
+ L_frame_en = 0; // Q0
+ for (i=0; i < L_FRAME; i++)
+ {
+ L_frame_en = L_mac(L_frame_en, frame[i], frame[i]);
+ }
+ Log2(L_frame_en, &log_en_e, &log_en_m);
+
+ // convert exponent and mantissa to Word16 Q10
+ log_en = shl(log_en_e, 10); // Q10
+ log_en = add(log_en, shr(log_en_m, 15-10));
+
+ // divide with L_FRAME i.e subtract with log2(L_FRAME) = 7.32193
+ log_en = sub(log_en, 7497+1024);
+
+ // insert into log energy buffer, no division by two as *
+ * log_en in decoder is Q11
+ st->log_en_hist_ptr = add(st->log_en_hist_ptr, 1);
+ if (sub(st->log_en_hist_ptr, DTX_HIST_SIZE) == 0)
+ {
+ st->log_en_hist_ptr = 0;
+ }
+ st->log_en_hist[st->log_en_hist_ptr] = log_en; // Q11
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void dtx_dec_activity_update(dtx_decState *st,
+ Word16 lsf[],
+ Word16 frame[],
+ Flag *pOverflow)
+{
+ Word16 i;
+
+ Word32 L_frame_en;
+ Word32 L_temp;
+ Word16 log_en_e;
+ Word16 log_en_m;
+ Word16 log_en;
+
+ /* update lsp history */
+ st->lsf_hist_ptr += M;
+
+ if (st->lsf_hist_ptr == 80)
+ {
+ st->lsf_hist_ptr = 0;
+ }
+ Copy(lsf, &st->lsf_hist[st->lsf_hist_ptr], M);
+
+ /* compute log energy based on frame energy */
+ L_frame_en = 0; /* Q0 */
+ for (i = L_FRAME - 1; i >= 0; i--)
+ {
+ L_temp = ((Word32) frame[i]) * frame[i];
+ if (L_temp != (Word32) 0x40000000L)
+ {
+ L_temp = L_temp << 1;
+ }
+ else
+ {
+ L_temp = MAX_32;
+ }
+ L_frame_en = L_add(L_frame_en, L_temp, pOverflow);
+ }
+ Log2(L_frame_en, &log_en_e, &log_en_m, pOverflow);
+
+ /* convert exponent and mantissa to Word16 Q10 */
+ L_temp = ((Word32) log_en_e) << 10;
+
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ *pOverflow = 1;
+ L_temp = (Word32)((log_en_e > 0) ? MAX_16 : MIN_16);
+ }
+ log_en_e = (Word16) L_temp;
+
+ if (log_en_m < 0)
+ {
+ log_en_m = ~((~log_en_m) >> 5);
+ }
+ else
+ {
+ log_en_m >>= 5;
+ }
+ log_en = add(log_en_e, log_en_m, pOverflow);
+
+ /* divide with L_FRAME i.e subtract with log2(L_FRAME) = 7.32193 */
+ log_en = sub(log_en, 7497 + 1024, pOverflow);
+
+ /* insert into log energy buffer, no division by two as *
+ * log_en in decoder is Q11 */
+ st->log_en_hist_ptr += 1;
+
+ if (st->log_en_hist_ptr == DTX_HIST_SIZE)
+ {
+ st->log_en_hist_ptr = 0;
+ }
+ st->log_en_hist[st->log_en_hist_ptr] = log_en; /* Q11 */
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: rx_dtx_handler
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type dtx_decState
+ frame_type = RX frame type
+
+ Returns:
+ newState = variable of type DTXStateType
+
+ Outputs:
+ st points to an updated structure of type dtx_decState
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function determines the new state of the decoder based on the frame_type
+ and sets up the decoder parameters according to newState.
+
+ Table of new SPD synthesis states
+
+ | previous SPD_synthesis_state
+ Incoming |
+ frame_type | SPEECH | DTX | DTX_MUTE
+ ---------------------------------------------------------------
+ RX_SPEECH_GOOD , | | |
+ RX_SPEECH_PR_DEGRADED | SPEECH | SPEECH | SPEECH
+ ----------------------------------------------------------------
+ RX_SPEECH_PR_BAD, | | |
+ RX_SPEECH_BAD, | SPEECH | DTX | DTX_MUTE
+ ----------------------------------------------------------------
+ RX_SID_FIRST, | DTX | DTX/(DTX_MUTE)| DTX_MUTE
+ ----------------------------------------------------------------
+ RX_SID_UPDATE, | DTX | DTX | DTX
+ ----------------------------------------------------------------
+ RX_SID_BAD, | DTX | DTX/(DTX_MUTE)| DTX_MUTE
+ ----------------------------------------------------------------
+ RX_NO_DATA | SPEECH | DTX/(DTX_MUTE)| DTX_MUTE
+ |(class2 garb.)| |
+ ----------------------------------------------------------------
+ RX_ONSET | SPEECH | DTX/(DTX_MUTE)| DTX_MUTE
+ |(class2 garb.)| |
+ ----------------------------------------------------------------
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dtx_dec.c, UMTS GSM AMR speech codec, R99 - Version 3.3.0, December 12, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+enum DTXStateType rx_dtx_handler(
+ dtx_decState *st, // i/o : State struct
+ enum RXFrameType frame_type // i : Frame type
+ )
+{
+ enum DTXStateType newState;
+ enum DTXStateType encState;
+
+ // DTX if SID frame or previously in DTX{_MUTE} and (NO_RX OR BAD_SPEECH)
+ if ((sub(frame_type, RX_SID_FIRST) == 0) ||
+ (sub(frame_type, RX_SID_UPDATE) == 0) ||
+ (sub(frame_type, RX_SID_BAD) == 0) ||
+ (((sub(st->dtxGlobalState, DTX) == 0) ||
+ (sub(st->dtxGlobalState, DTX_MUTE) == 0)) &&
+ ((sub(frame_type, RX_NO_DATA) == 0) ||
+ (sub(frame_type, RX_SPEECH_BAD) == 0) ||
+ (sub(frame_type, RX_ONSET) == 0))))
+ {
+ newState = DTX;
+
+ // stay in mute for these input types
+ if ((sub(st->dtxGlobalState, DTX_MUTE) == 0) &&
+ ((sub(frame_type, RX_SID_BAD) == 0) ||
+ (sub(frame_type, RX_SID_FIRST) == 0) ||
+ (sub(frame_type, RX_ONSET) == 0) ||
+ (sub(frame_type, RX_NO_DATA) == 0)))
+ {
+ newState = DTX_MUTE;
+ }
+
+ // evaluate if noise parameters are too old
+ // since_last_sid is reset when CN parameters have been updated
+ st->since_last_sid = add(st->since_last_sid, 1);
+
+ // no update of sid parameters in DTX for a long while
+ // Due to the delayed update of st->since_last_sid counter
+ // SID_UPDATE frames need to be handled separately to avoid
+ // entering DTX_MUTE for late SID_UPDATE frames
+ if((sub(frame_type, RX_SID_UPDATE) != 0) &&
+ (sub(st->since_last_sid, DTX_MAX_EMPTY_THRESH) > 0))
+ {
+ newState = DTX_MUTE;
+ }
+ }
+ else
+ {
+ newState = SPEECH;
+ st->since_last_sid = 0;
+ }
+
+ // reset the decAnaElapsed Counter when receiving CNI data the first
+ // time, to robustify counter missmatch after handover
+ // this might delay the bwd CNI analysis in the new decoder slightly.
+
+ if ((st->data_updated == 0) &&
+ (sub(frame_type, RX_SID_UPDATE) == 0))
+ {
+ st->decAnaElapsedCount = 0;
+ }
+
+ // update the SPE-SPD DTX hangover synchronization
+ // to know when SPE has added dtx hangover
+ st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1);
+ st->dtxHangoverAdded = 0;
+
+ if ((sub(frame_type, RX_SID_FIRST) == 0) ||
+ (sub(frame_type, RX_SID_UPDATE) == 0) ||
+ (sub(frame_type, RX_SID_BAD) == 0) ||
+ (sub(frame_type, RX_ONSET) == 0) ||
+ (sub(frame_type, RX_NO_DATA) == 0))
+ {
+ encState = DTX;
+
+ // In frame errors simulations RX_NO_DATA may occasionally mean that
+ // a speech packet was probably sent by the encoder,
+ // the assumed _encoder_ state should be SPEECH in such cases.
+ if((sub(frame_type, RX_NO_DATA) == 0) &&
+ (sub(newState, SPEECH) == 0))
+ {
+ encState = SPEECH;
+ }
+
+ // Note on RX_ONSET operation differing from RX_NO_DATA operation:
+ // If a RX_ONSET is received in the decoder (by "accident")
+ // it is still most likely that the encoder state
+ // for the "ONSET frame" was DTX.
+
+ }
+ else
+ {
+ encState = SPEECH;
+ }
+
+ if (sub(encState, SPEECH) == 0)
+ {
+ st->dtxHangoverCount = DTX_HANG_CONST;
+ }
+ else
+ {
+ if (sub(st->decAnaElapsedCount, DTX_ELAPSED_FRAMES_THRESH) > 0)
+ {
+ st->dtxHangoverAdded = 1;
+ st->decAnaElapsedCount = 0;
+ st->dtxHangoverCount = 0;
+ }
+ else if (st->dtxHangoverCount == 0)
+ {
+ st->decAnaElapsedCount = 0;
+ }
+ else
+ {
+ st->dtxHangoverCount = sub(st->dtxHangoverCount, 1);
+ }
+ }
+
+ if (sub(newState, SPEECH) != 0)
+ {
+ // DTX or DTX_MUTE
+ // CN data is not in a first SID, first SIDs are marked as SID_BAD
+ // but will do backwards analysis if a hangover period has been added
+ // according to the state machine above
+
+ st->sid_frame = 0;
+ st->valid_data = 0;
+
+ if (sub(frame_type, RX_SID_FIRST) == 0)
+ {
+ st->sid_frame = 1;
+ }
+ else if (sub(frame_type, RX_SID_UPDATE) == 0)
+ {
+ st->sid_frame = 1;
+ st->valid_data = 1;
+ }
+ else if (sub(frame_type, RX_SID_BAD) == 0)
+ {
+ st->sid_frame = 1;
+ st->dtxHangoverAdded = 0; // use old data
+ }
+ }
+
+ return newState;
+ // newState is used by both SPEECH AND DTX synthesis routines
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+enum DTXStateType rx_dtx_handler(
+ dtx_decState *st, /* i/o : State struct */
+ enum RXFrameType frame_type,/* i : Frame type */
+ Flag *pOverflow)
+{
+ enum DTXStateType newState;
+ enum DTXStateType encState;
+
+
+ /* DTX if SID frame or previously in DTX{_MUTE} and (NO_RX OR BAD_SPEECH) */
+
+ if ((frame_type == RX_SID_FIRST) ||
+ (frame_type == RX_SID_UPDATE) ||
+ (frame_type == RX_SID_BAD) ||
+ (((st->dtxGlobalState == DTX) || (st->dtxGlobalState == DTX_MUTE)) &&
+ ((frame_type == RX_NO_DATA) || (frame_type == RX_SPEECH_BAD) ||
+ (frame_type == RX_ONSET))))
+ {
+ newState = DTX;
+
+ /* stay in mute for these input types */
+
+ if ((st->dtxGlobalState == DTX_MUTE) &&
+ ((frame_type == RX_SID_BAD) ||
+ (frame_type == RX_SID_FIRST) ||
+ (frame_type == RX_ONSET) ||
+ (frame_type == RX_NO_DATA)))
+ {
+ newState = DTX_MUTE;
+ }
+
+ /* evaluate if noise parameters are too old */
+ /* since_last_sid is reset when CN parameters have been updated */
+ st->since_last_sid = add(st->since_last_sid, 1, pOverflow);
+
+ /* no update of sid parameters in DTX for a long while */
+ /* Due to the delayed update of st->since_last_sid counter */
+ /* SID_UPDATE frames need to be handled separately to avoid */
+ /* entering DTX_MUTE for late SID_UPDATE frames */
+ if ((frame_type != RX_SID_UPDATE) &&
+ (st->since_last_sid > DTX_MAX_EMPTY_THRESH))
+ {
+ newState = DTX_MUTE;
+ }
+ }
+ else
+ {
+ newState = SPEECH;
+ st->since_last_sid = 0;
+ }
+
+ /*
+ reset the decAnaElapsed Counter when receiving CNI data the first
+ time, to robustify counter missmatch after handover
+ this might delay the bwd CNI analysis in the new decoder slightly.
+ */
+
+ if ((st->data_updated == 0) &&
+ (frame_type == RX_SID_UPDATE))
+ {
+ st->decAnaElapsedCount = 0;
+ }
+
+ /* update the SPE-SPD DTX hangover synchronization */
+ /* to know when SPE has added dtx hangover */
+ st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1, pOverflow);
+ st->dtxHangoverAdded = 0;
+
+ if ((frame_type == RX_SID_FIRST) ||
+ (frame_type == RX_SID_UPDATE) ||
+ (frame_type == RX_SID_BAD) ||
+ (frame_type == RX_ONSET) ||
+ (frame_type == RX_NO_DATA))
+ {
+ encState = DTX;
+
+ /*
+ In frame errors simulations RX_NO_DATA may occasionally mean that
+ a speech packet was probably sent by the encoder,
+ the assumed _encoder_ state should be SPEECH in such cases.
+ */
+ if ((frame_type == RX_NO_DATA) &&
+ (newState == SPEECH))
+ {
+ encState = SPEECH;
+ }
+
+ /*
+ Note on RX_ONSET operation differing from RX_NO_DATA operation:
+ If a RX_ONSET is received in the decoder (by "accident")
+ it is still most likely that the encoder state
+ for the "ONSET frame" was DTX.
+ */
+ }
+ else
+ {
+ encState = SPEECH;
+ }
+
+
+ if (encState == SPEECH)
+ {
+ st->dtxHangoverCount = DTX_HANG_CONST;
+ }
+ else
+ {
+
+ if (st->decAnaElapsedCount > DTX_ELAPSED_FRAMES_THRESH)
+ {
+ st->dtxHangoverAdded = 1;
+ st->decAnaElapsedCount = 0;
+ st->dtxHangoverCount = 0;
+ }
+ else if (st->dtxHangoverCount == 0)
+ {
+ st->decAnaElapsedCount = 0;
+ }
+ else
+ {
+ st->dtxHangoverCount -= 1;
+ }
+ }
+
+ if (newState != SPEECH)
+ {
+ /* DTX or DTX_MUTE
+ * CN data is not in a first SID, first SIDs are marked as SID_BAD
+ * but will do backwards analysis if a hangover period has been added
+ * according to the state machine above
+ */
+
+ st->sid_frame = 0;
+ st->valid_data = 0;
+
+ if (frame_type == RX_SID_FIRST)
+ {
+ st->sid_frame = 1;
+ }
+ else if (frame_type == RX_SID_UPDATE)
+ {
+ st->sid_frame = 1;
+ st->valid_data = 1;
+ }
+ else if (frame_type == RX_SID_BAD)
+ {
+ st->sid_frame = 1;
+ st->dtxHangoverAdded = 0; /* use old data */
+ }
+ }
+
+ /* newState is used by both SPEECH AND DTX synthesis routines */
+ return(newState);
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/dtx_dec.h b/media/libstagefright/codecs/amrnb/dec/src/dtx_dec.h
new file mode 100644
index 0000000..2b5a614
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/dtx_dec.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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/dtx_dec.h
+
+ Date: 02/06/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : dtx_dec.h
+ Purpose : Decode comfort noice when in DTX
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef DTX_DEC_H
+#define DTX_DEC_H
+#define dtx_dec_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "d_plsf.h"
+#include "gc_pred.h"
+#include "c_g_aver.h"
+#include "frame.h"
+#include "dtx_common_def.h"
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ enum DTXStateType {SPEECH = 0, DTX, DTX_MUTE};
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 since_last_sid;
+ Word16 true_sid_period_inv;
+ Word16 log_en;
+ Word16 old_log_en;
+ Word32 L_pn_seed_rx;
+ Word16 lsp[M];
+ Word16 lsp_old[M];
+
+ Word16 lsf_hist[M*DTX_HIST_SIZE];
+ Word16 lsf_hist_ptr;
+ Word16 lsf_hist_mean[M*DTX_HIST_SIZE];
+ Word16 log_pg_mean;
+ Word16 log_en_hist[DTX_HIST_SIZE];
+ Word16 log_en_hist_ptr;
+
+ Word16 log_en_adjust;
+
+ Word16 dtxHangoverCount;
+ Word16 decAnaElapsedCount;
+
+ Word16 sid_frame;
+ Word16 valid_data;
+ Word16 dtxHangoverAdded;
+
+ enum DTXStateType dtxGlobalState; /* contains previous state */
+ /* updated in main decoder */
+
+ Word16 data_updated; /* marker to know if CNI data is ever renewed */
+
+ } dtx_decState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*
+ * Function : dtx_dec_reset
+ * Purpose : Resets state memory
+ * Returns : 0 on success
+ */
+ Word16 dtx_dec_reset(dtx_decState *st);
+
+ /*
+ * Function : dtx_dec
+ * Purpose :
+ * Description :
+ */
+ void dtx_dec(
+ dtx_decState *st, /* i/o : State struct */
+ Word16 mem_syn[], /* i/o : AMR decoder state */
+ D_plsfState* lsfState, /* i/o : decoder lsf states */
+ gc_predState* predState, /* i/o : prediction states */
+ Cb_gain_averageState* averState, /* i/o : CB gain average states */
+ enum DTXStateType new_state, /* i : new DTX state */
+ enum Mode mode, /* i : AMR mode */
+ Word16 parm[], /* i : Vector of synthesis parameters */
+ Word16 synth[], /* o : synthesised speech */
+ Word16 A_t[], /* o : decoded LP filter in 4 subframes*/
+ Flag *pOverflow
+ );
+
+ void dtx_dec_activity_update(dtx_decState *st,
+ Word16 lsf[],
+ Word16 frame[],
+ Flag *pOverflow);
+
+ /*
+ * Function : rx_dtx_handler
+ * Purpose : reads the frame type and checks history
+ * Description : to decide what kind of DTX/CNI action to perform
+ */
+ enum DTXStateType rx_dtx_handler(dtx_decState *st, /* i/o : State struct */
+ enum RXFrameType frame_type,/* i : Frame type */
+ Flag *pOverflow);
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DEC_AMR_H_ */
diff --git a/media/libstagefright/codecs/amrnb/dec/src/ec_gains.cpp b/media/libstagefright/codecs/amrnb/dec/src/ec_gains.cpp
new file mode 100644
index 0000000..e73db62
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/ec_gains.cpp
@@ -0,0 +1,842 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/ec_gain.c
+ Funtions:
+
+ Date: 01/28/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Removed the functions ec_gain_code_init, ec_gain_pitch_init,
+ ech_gain_code_exit, and ec_gain_pitch_exit.
+
+ The ec_gains related structures are no longer dynamically allocated.
+
+ Description: Updated include files and input/output sections.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ These modules execute the code book gains for error concealment. This module
+ contains the init, reset, exit, and "main" functions in this process.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "ec_gains.h"
+#include "typedef.h"
+#include "cnst.h"
+#include "gmed_n.h"
+#include "gc_pred.h"
+#include "basic_op.h"
+
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ extern const Word16 qua_gain_pitch[];
+ extern const Word16 qua_gain_code[];
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ec_gain_code_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a pointer to a structure containing code state data of
+ stucture type ec_gain_codeState
+
+ Outputs:
+ None.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function resets the state data for the ec_gain module.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int ec_gain_code_reset (ec_gain_codeState *state)
+{
+ Word16 i;
+
+ if (state == (ec_gain_codeState *) NULL){
+ // fprintf(stderr, "ec_gain_code_reset: invalid parameter\n");
+ return -1;
+ }
+
+ for ( i = 0; i < 5; i++)
+ state->gbuf[i] = 1;
+ state->past_gain_code = 0;
+ state->prev_gc = 1;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 ec_gain_code_reset(ec_gain_codeState *state)
+{
+ Word16 i;
+
+ if (state == (ec_gain_codeState *) NULL)
+ {
+ /* fprintf(stderr, "ec_gain_code_reset: invalid parameter\n"); */
+ return -1;
+ }
+
+ for (i = 0; i < 5; i++)
+ state->gbuf[i] = 1;
+ state->past_gain_code = 0;
+ state->prev_gc = 1;
+
+ return 0;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ec_gain_code
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a pointer to a structure containing code state data of
+ stucture type ec_gain_codeState
+ pred_state = pointer to MA predictor state of type gc_predState
+ state = state of the state machine of type Word16
+ gain_code = pointer to decoded innovation gain of type Word16
+ pOverflow = pointer to overflow indicator of type Flag
+
+ Outputs:
+ st = pointer to a pointer to a structure containing code state data of
+ stucture type ec_gain_codeState
+ pred_state = pointer to MA predictor state of type gc_predState
+ pOverflow = 1 if there is an overflow else it is zero.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+This function does error concealment using the codebook. Call this function
+only in BFI (instead of normal gain decoding function).
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ec_gain.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ static const Word16 cdown[7] =
+ {
+ 32767, 32112, 32112, 32112,
+ 32112, 32112, 22937
+ };
+
+ Word16 tmp;
+ Word16 qua_ener_MR122;
+ Word16 qua_ener;
+
+ // calculate median of last five gain values
+ tmp = gmed_n (st->gbuf,5);
+
+ // new gain = minimum(median, past_gain) * cdown[state]
+ if (sub (tmp, st->past_gain_code) > 0)
+ {
+ tmp = st->past_gain_code;
+ }
+ tmp = mult (tmp, cdown[state]);
+ *gain_code = tmp;
+
+ // update table of past quantized energies with average of
+ // current values
+
+ gc_pred_average_limited(pred_state, &qua_ener_MR122, &qua_ener);
+ gc_pred_update(pred_state, qua_ener_MR122, qua_ener);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void ec_gain_code(
+ ec_gain_codeState *st, /* i/o : State struct */
+ gc_predState *pred_state, /* i/o : MA predictor state */
+ Word16 state, /* i : state of the state machine */
+ Word16 *gain_code, /* o : decoded innovation gain */
+ Flag *pOverflow
+)
+{
+ static const Word16 cdown[7] =
+ {
+ 32767, 32112, 32112, 32112,
+ 32112, 32112, 22937
+ };
+
+ Word16 tmp;
+ Word16 qua_ener_MR122;
+ Word16 qua_ener;
+
+ /* calculate median of last five gain values */
+ tmp = gmed_n(st->gbuf, 5);
+
+ /* new gain = minimum(median, past_gain) * cdown[state] */
+ if (sub(tmp, st->past_gain_code, pOverflow) > 0)
+ {
+ tmp = st->past_gain_code;
+ }
+ tmp = mult(tmp, cdown[state], pOverflow);
+ *gain_code = tmp;
+
+ /* update table of past quantized energies with average of
+ * current values
+ */
+ gc_pred_average_limited(pred_state, &qua_ener_MR122, &qua_ener, pOverflow);
+ gc_pred_update(pred_state, qua_ener_MR122, qua_ener);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ec_gain_code_update
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a pointer to a structure containing code state data of
+ stucture type ec_gain_codeState
+ bfi = a flag that indicates if the frame is bad of type Word16
+ prev_bf = a flag that indicates if the previous frame was bad of type Word16
+ gain_code = pointer to decoded innovation gain of type Word16
+ pOverflow = pointer to overflow indicator of type Flag
+
+ Outputs:
+ st = pointer to a pointer to a structure containing code state data of
+ stucture type ec_gain_codeState
+ gain_code = pointer to decoded innovation gain of type Word16
+ pOverflow = 1 if there is an overflow else it is zero.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : update the codebook gain concealment state;
+ limit gain_code if the previous frame was bad
+ Call this function always after decoding (or concealing)
+ the gain
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ec_gain.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Word16 i;
+
+ // limit gain_code by previous good gain if previous frame was bad
+ if (bfi == 0)
+ {
+ if (prev_bf != 0)
+ {
+ if (sub (*gain_code, st->prev_gc) > 0)
+ {
+ *gain_code = st->prev_gc;
+ }
+ }
+ st->prev_gc = *gain_code;
+ }
+
+ // update EC states: previous gain, gain buffer
+ st->past_gain_code = *gain_code;
+
+ for (i = 1; i < 5; i++)
+ {
+ st->gbuf[i - 1] = st->gbuf[i];
+ }
+ st->gbuf[4] = *gain_code;
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void ec_gain_code_update(
+ ec_gain_codeState *st, /* i/o : State struct */
+ Word16 bfi, /* i : flag: frame is bad */
+ Word16 prev_bf, /* i : flag: previous frame was bad */
+ Word16 *gain_code, /* i/o : decoded innovation gain */
+ Flag *pOverflow
+)
+{
+ Word16 i;
+
+ /* limit gain_code by previous good gain if previous frame was bad */
+ if (bfi == 0)
+ {
+ if (prev_bf != 0)
+ {
+ if (sub(*gain_code, st->prev_gc, pOverflow) > 0)
+ {
+ *gain_code = st->prev_gc;
+ }
+ }
+ st->prev_gc = *gain_code;
+ }
+
+ /* update EC states: previous gain, gain buffer */
+ st->past_gain_code = *gain_code;
+
+ for (i = 1; i < 5; i++)
+ {
+ st->gbuf[i - 1] = st->gbuf[i];
+ }
+ st->gbuf[4] = *gain_code;
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ec_gain_pitch
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a pointer to a structure containing code
+ state data of stucture type ec_gain_pitchState
+ state = state of the state machine of type Word16
+ pOverflow = pointer to overflow indicator of type Flag
+
+ Outputs:
+ state = pointer to a pointer to a structure containing code
+ state data of stucture type ec_gain_pitchState
+ gain_pitch = pointer to pitch gain (Q14) of type Word16
+ pOverflow = 1 if there is an overflow else it is zero.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function conceals the error using code gain implementation in this
+ function.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ec_gain.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+ static const Word16 pdown[7] =
+ {
+ 32767, 32112, 32112, 26214,
+ 9830, 6553, 6553
+ };
+
+ Word16 tmp;
+
+ // calculate median of last five gains
+ tmp = gmed_n (st->pbuf, 5);
+
+ // new gain = minimum(median, past_gain) * pdown[state]
+ if (sub (tmp, st->past_gain_pit) > 0)
+ {
+ tmp = st->past_gain_pit;
+ }
+ *gain_pitch = mult (tmp, pdown[state]);
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void ec_gain_pitch(
+ ec_gain_pitchState *st, /* i/o : state variables */
+ Word16 state, /* i : state of the state machine */
+ Word16 *gain_pitch, /* o : pitch gain (Q14) */
+ Flag *pOverflow
+)
+{
+ static const Word16 pdown[7] =
+ {
+ 32767, 32112, 32112, 26214,
+ 9830, 6553, 6553
+ };
+
+ Word16 tmp;
+
+ /* calculate median of last five gains */
+ tmp = gmed_n(st->pbuf, 5);
+
+ /* new gain = minimum(median, past_gain) * pdown[state] */
+ if (sub(tmp, st->past_gain_pit, pOverflow) > 0)
+ {
+ tmp = st->past_gain_pit;
+ }
+ *gain_pitch = mult(tmp, pdown[state], pOverflow);
+}
+
+/****************************************************************************/
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ec_gain_pitch_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = state of the state machine of type Word16
+ pOverflow = pointer to overflow indicator of type Flag
+
+ Outputs:
+ state = pointer to a pointer to a structure containing code
+ state data of stucture type ec_gain_pitchState
+ pOverflow = 1 if there is an overflow else it is zero.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function: ec_gain_pitch_reset
+ Purpose: Resets state memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ec_gain.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int ec_gain_pitch_reset (ec_gain_pitchState *state)
+{
+ Word16 i;
+
+ if (state == (ec_gain_pitchState *) NULL){
+ // fprintf(stderr, "ec_gain_pitch_reset: invalid parameter\n");
+ return -1;
+ }
+
+ for(i = 0; i < 5; i++)
+ state->pbuf[i] = 1640;
+ state->past_gain_pit = 0;
+ state->prev_gp = 16384;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 ec_gain_pitch_reset(ec_gain_pitchState *state)
+{
+ Word16 i;
+
+ if (state == (ec_gain_pitchState *) NULL)
+ {
+ /* fprintf(stderr, "ec_gain_pitch_reset: invalid parameter\n"); */
+ return -1;
+ }
+
+ for (i = 0; i < 5; i++)
+ state->pbuf[i] = 1640;
+ state->past_gain_pit = 0;
+ state->prev_gp = 16384;
+
+ return 0;
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ec_gain_pitch_update
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a pointer to a structure containing code
+ state data of stucture type ec_gain_pitchState
+ bfi = flag indicating the frame is bad of type Word16
+ prev_bf = flag indicating the previous frame was bad of type Word16
+ gain_pitch = pointer to pitch gain of type Word16
+ pOverflow = pointer to overflow indicator of type Flag
+
+ Outputs:
+ state = pointer to a pointer to a structure containing code
+ state data of stucture type ec_gain_pitchState
+ gain_pitch = pointer to pitch gain of type Word16
+ pOverflow = 1 if there is an overflow else it is zero.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : update the pitch gain concealment state;
+ limit gain_pitch if the previous frame was bad
+ Call this function always after decoding (or concealing)
+ the gain
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ec_gain.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Word16 i;
+
+ if (bfi == 0)
+ {
+ if (prev_bf != 0)
+ {
+ if (sub (*gain_pitch, st->prev_gp) > 0)
+ {
+ *gain_pitch = st->prev_gp;
+ }
+ }
+ st->prev_gp = *gain_pitch;
+ }
+
+ st->past_gain_pit = *gain_pitch;
+
+ if (sub (st->past_gain_pit, 16384) > 0) // if (st->past_gain_pit > 1.0)
+ {
+ st->past_gain_pit = 16384;
+ }
+ for (i = 1; i < 5; i++)
+ {
+ st->pbuf[i - 1] = st->pbuf[i];
+ }
+ st->pbuf[4] = st->past_gain_pit;
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void ec_gain_pitch_update(
+ ec_gain_pitchState *st, /* i/o : state variables */
+ Word16 bfi, /* i : flag: frame is bad */
+ Word16 prev_bf, /* i : flag: previous frame was bad */
+ Word16 *gain_pitch, /* i/o : pitch gain */
+ Flag *pOverflow
+)
+{
+ Word16 i;
+
+ if (bfi == 0)
+ {
+ if (prev_bf != 0)
+ {
+ if (sub(*gain_pitch, st->prev_gp, pOverflow) > 0)
+ {
+ *gain_pitch = st->prev_gp;
+ }
+ }
+ st->prev_gp = *gain_pitch;
+ }
+
+ st->past_gain_pit = *gain_pitch;
+
+ if (sub(st->past_gain_pit, 16384, pOverflow) > 0)
+ /* if (st->past_gain_pit > 1.0) */
+ {
+ st->past_gain_pit = 16384;
+ }
+ for (i = 1; i < 5; i++)
+ {
+ st->pbuf[i - 1] = st->pbuf[i];
+ }
+ st->pbuf[4] = st->past_gain_pit;
+}
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/ec_gains.h b/media/libstagefright/codecs/amrnb/dec/src/ec_gains.h
new file mode 100644
index 0000000..e05a0af
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/ec_gains.h
@@ -0,0 +1,209 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/ec_gains.h
+
+ Date: 01/28/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : ec_gains.c
+ Purpose: : Error concealment for pitch and codebook gains
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _EC_GAINS_H_
+#define _EC_GAINS_H_
+#define ec_gains_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "gc_pred.h"
+
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 pbuf[5];
+ Word16 past_gain_pit;
+ Word16 prev_gp;
+ } ec_gain_pitchState;
+
+ typedef struct
+ {
+ Word16 gbuf[5];
+ Word16 past_gain_code;
+ Word16 prev_gc;
+ } ec_gain_codeState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*
+ * Function : ec_gain_code_reset
+ * Purpose : Resets state memory
+ *
+ */
+ Word16 ec_gain_code_reset(
+ ec_gain_codeState *state
+ );
+
+
+ /*
+ * Function : ec_gain_code
+ * Purpose : conceal the codebook gain
+ * Call this function only in BFI (instead of normal gain
+ * decoding function)
+ */
+ void ec_gain_code(
+ ec_gain_codeState *st, /* i/o : State struct */
+ gc_predState *pred_state, /* i/o : MA predictor state */
+ Word16 state, /* i : state of the state machine */
+ Word16 *gain_code, /* o : decoded innovation gain */
+ Flag *pOverflow
+ );
+
+ /*
+ * Function : ec_gain_code_update
+ * Purpose : update the codebook gain concealment state;
+ * limit gain_code if the previous frame was bad
+ * Call this function always after decoding (or concealing)
+ * the gain
+ */
+ void ec_gain_code_update(
+ ec_gain_codeState *st, /* i/o : State struct */
+ Word16 bfi, /* i : flag: frame is bad */
+ Word16 prev_bf, /* i : flag: previous frame was bad */
+ Word16 *gain_code, /* i/o : decoded innovation gain */
+ Flag *pOverflow
+ );
+
+
+ /*
+ * Function: ec_gain_pitch_reset
+ * Purpose: Resets state memory
+ */
+ Word16 ec_gain_pitch_reset(
+ ec_gain_pitchState *state
+ );
+
+ /*
+ * Function : ec_gain_pitch_exit
+ * Purpose : The memory used for state memory is freed
+ */
+ void ec_gain_pitch_exit(
+ ec_gain_pitchState **state
+ );
+
+ /*
+ * Function : ec_gain_pitch
+ * Purpose : conceal the pitch gain
+ * Call this function only in BFI (instead of normal gain
+ * decoding function)
+ */
+ void ec_gain_pitch(
+ ec_gain_pitchState *st, /* i/o : state variables */
+ Word16 state, /* i : state of the state machine */
+ Word16 *gain_pitch, /* o : pitch gain (Q14) */
+ Flag *pOverflow
+ );
+
+ /*
+ * Function : ec_gain_pitch_update
+ * Purpose : update the pitch gain concealment state;
+ * limit gain_pitch if the previous frame was bad
+ * Call this function always after decoding (or concealing)
+ * the gain
+ */
+ void ec_gain_pitch_update(
+ ec_gain_pitchState *st, /* i/o : state variables */
+ Word16 bfi, /* i : flag: frame is bad */
+ Word16 prev_bf, /* i : flag: previous frame was bad */
+ Word16 *gain_pitch, /* i/o : pitch gain */
+ Flag *pOverflow
+ );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EC_GAINS_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/ex_ctrl.cpp b/media/libstagefright/codecs/amrnb/dec/src/ex_ctrl.cpp
new file mode 100644
index 0000000..f18054b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/ex_ctrl.cpp
@@ -0,0 +1,219 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/ex_ctrl.c
+ Funtions: ex_ctrl
+
+ Date: 02/08/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "ex_ctrl.h"
+#include "typedef.h"
+#include "cnst.h"
+#include "copy.h"
+#include "set_zero.h"
+#include "gmed_n.h"
+#include "sqrt_l.h"
+#include "basic_op.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ex_ctrl
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ excitation = pointer to current subframe excitation of type Word16
+ excEnergy = Exc. Energy, sqrt(totEx*totEx) of type Word16
+ exEnergyHist = pointer to history of subframe energies of type Word16
+ voicedHangover = # of fr. after last voiced fr of type Word16
+ carefulFlag = restrict dynamic in scaling of type Word16
+ pOverflow = pointer to overflow indicator
+
+ Outputs:
+ pOverflow = 1 if overflow exists in the math functions called by this function.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function : Ex_ctrl
+ Purpose : Charaterice synthesis speech and detect background noise
+ Returns : background noise decision; 0 = no bgn, 1 = bgn
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ex_ctrl.c, 3GPP TS 26.101 version 4.1.0 Release 4, June 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 Ex_ctrl(Word16 excitation[], /*i/o: Current subframe excitation */
+ Word16 excEnergy, /* i : Exc. Energy, sqrt(totEx*totEx)*/
+ Word16 exEnergyHist[], /* i : History of subframe energies */
+ Word16 voicedHangover, /* i : # of fr. after last voiced fr.*/
+ Word16 prevBFI, /* i : Set i previous BFI */
+ Word16 carefulFlag, /* i : Restrict dymamic in scaling */
+ Flag *pOverflow
+ )
+{
+ Word16 i, exp;
+ Word16 testEnergy, scaleFactor, avgEnergy, prevEnergy;
+ Word32 t0;
+
+ /* get target level */
+ avgEnergy = gmed_n(exEnergyHist, 9);
+
+ prevEnergy = shr(add(exEnergyHist[7], exEnergyHist[8], pOverflow) , 1, pOverflow);
+
+ if (exEnergyHist[8] < prevEnergy)
+ {
+ prevEnergy = exEnergyHist[8];
+ }
+
+ /* upscaling to avoid too rapid energy rises for some cases */
+ if ((excEnergy < avgEnergy) && (excEnergy > 5))
+ {
+ testEnergy = shl(prevEnergy, 2, pOverflow); /* testEnergy = 4*prevEnergy; */
+
+ if ((voicedHangover < 7) || prevBFI != 0)
+ {
+ /* testEnergy = 3*prevEnergy */
+ testEnergy = sub(testEnergy, prevEnergy, pOverflow);
+ }
+
+ if (avgEnergy > testEnergy)
+ {
+ avgEnergy = testEnergy;
+ }
+
+ /* scaleFactor=avgEnergy/excEnergy in Q0 (const 29 below)*/
+ exp = norm_s(excEnergy);
+ excEnergy = shl(excEnergy, exp, pOverflow);
+ excEnergy = div_s((Word16) 16383, excEnergy);
+ t0 = L_mult(avgEnergy, excEnergy, pOverflow);
+ t0 = L_shr(t0, sub(20, exp, pOverflow), pOverflow);
+ /* const=30 for t0 in Q0, 20 for Q10 */
+ if (t0 > 32767)
+ {
+ t0 = 32767; /* saturate */
+ }
+ scaleFactor = extract_l(t0);
+
+ /* test if scaleFactor > 3.0 */
+ if (carefulFlag != 0 && (scaleFactor > 3072))
+ {
+ scaleFactor = 3072;
+ }
+
+ /* scale the excitation by scaleFactor */
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ t0 = L_mult(scaleFactor, excitation[i], pOverflow);
+ t0 = L_shr(t0, 11, pOverflow);
+ excitation[i] = extract_l(t0);
+ }
+ }
+
+ return 0;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/ex_ctrl.h b/media/libstagefright/codecs/amrnb/dec/src/ex_ctrl.h
new file mode 100644
index 0000000..11c632e
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/ex_ctrl.h
@@ -0,0 +1,131 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/ex_ctrl.h
+
+ Date: 02/08/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : ex_ctrl.h
+ Purpose : Excitation Control module in background noise
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef ex_ctrl_h
+#define ex_ctrl_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define L_ENERGYHIST 60
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ /*
+ * Function : Ex_ctrl
+ * Purpose : Charaterice synthesis speech and detect background noise
+ * Returns : background noise decision; 0 = bgn, 1 = no bgn
+ */
+ Word16 Ex_ctrl(Word16 excitation[], /*i/o: Current subframe excitation */
+ Word16 excEnergy, /* i : Exc. Energy, sqrt(totEx*totEx)*/
+ Word16 exEnergyHist[], /* i : History of subframe energies */
+ Word16 voicedHangover, /* i : # of fr. after last voiced fr.*/
+ Word16 prevBFI, /* i : Set i previous BFI */
+ Word16 carefulFlag, /* i : Restrict dymamic in scaling */
+ Flag *pOverflow
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ex_ctrl_h_ */
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h b/media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h
new file mode 100644
index 0000000..a9fdb1c
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h
@@ -0,0 +1,170 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm-amr/c/include/gsmamr_dec.h
+
+ Date: 09/10/2001
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Adding comments and removing some tables as per review comments.
+
+ Description: Replace enum Mode with enum Frame_Type_3GPP and updated function
+ prototype of AMRDecode().
+
+ Description: Added back the enum Mode type definition, removed RXFrameType
+ type definition, and updated AMRDecode and GSMInitDecode function
+ prototypes.
+
+ Description: Added #defines for WMF and IF2. Updated AMRDecode function
+ prototype.
+
+ Description: Removed enum Mode type definition and updated AMRDecode function
+ prototype.
+
+ Description: Renamed WMF and IF2 to AMR_WMF and AMR_IF2, respectively. Added
+ #define for AMR_ETS format.
+
+ Description: Rename input format defines to make it unique to the decoder.
+
+ Description: Added comment to describe L_FRAME.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description: Included file "typedefs.h" to avoid re-declaring similar typedef
+ this for OSCL-ed compatibility
+
+ Description: Included file "gsm_amr_typedefs.h" and eliminated re-definition
+ of types UWord8, Word8, Word16
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This header contains all the necessary information needed to allow the gsm amr
+ decoder library to be used properly upon release.
+
+------------------------------------------------------------------------------
+*/
+#ifndef _GSMAMR_DEC_H_
+#define _GSMAMR_DEC_H_
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "gsm_amr_typedefs.h"
+#include "pvamrnbdecoder_api.h"
+#include "frame_type_3gpp.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ----------------------------------------------------------------------------*/
+ /* Number of 13-bit linear PCM samples per 20 ms frame */
+ /* L_FRAME = (8 kHz) * (20 msec) = 160 samples */
+#define L_FRAME 160
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ----------------------------------------------------------------------------*/
+ /*
+ * This function allocates memory for filter structure and initializes state
+ * memory used by the GSM AMR decoder. This function returns zero. It will
+ * return negative one if there is an error.
+ */
+ Word16 GSMInitDecode(void **state_data,
+ Word8 *id);
+
+ /*
+ * AMRDecode steps into the part of the library that decodes the raw data
+ * speech bits for the decoding process. It returns the address offset of
+ * the next frame to be decoded.
+ */
+ Word16 AMRDecode(
+ void *state_data,
+ enum Frame_Type_3GPP frame_type,
+ UWord8 *speech_bits_ptr,
+ Word16 *raw_pcm_buffer,
+ Word16 input_format
+ );
+
+ /*
+ * This function resets the state memory used by the GSM AMR decoder. This
+ * function returns zero. It will return negative one if there is an error.
+ */
+ Word16 Speech_Decode_Frame_reset(void *state_data);
+
+ /*
+ * This function frees up the memory used for the state memory of the
+ * GSM AMR decoder.
+ */
+ void GSMDecodeFrameExit(void **state_data);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GSMAMR_DEC_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/if2_to_ets.cpp b/media/libstagefright/codecs/amrnb/dec/src/if2_to_ets.cpp
new file mode 100644
index 0000000..733c8b8
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/if2_to_ets.cpp
@@ -0,0 +1,196 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+ Pathname: ./audio/gsm-amr/c/src/if2_to_ets.c
+ Funtions: if2_to_ets
+
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "frame_type_3gpp.h"
+#include "if2_to_ets.h"
+#include "typedef.h"
+#include "bitreorder_tab.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: if2_to_ets
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ frame_type_3gpp = decoder speech bit rate (enum Frame_Type_3GPP)
+ if2_input_ptr = pointer to input encoded speech bits in IF2 format (Word8)
+ ets_output_ptr = pointer to output encoded speech bits in ETS format (Word16)
+
+ Outputs:
+ ets_output_ptr = pointer to encoded speech bits in the ETS format (Word16)
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs a transformation on the data buffers. It converts the
+ data format from IF2 to ETS. IF2 is the storage format where the frame type
+ is in the first four bits of the first byte. The upper four bits of that byte
+ contain the first four encoded speech bits for the frame. The following bytes
+ contain the rest of the encoded speech bits. The final byte has padded zeros
+ to make the frame byte aligned. ETS format has the encoded speech
+ bits each separate with only one bit stored in each word.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+AMR Speech Codec Frame Structure", 3GPP TS 26.101 version 4.1.0 Release 4, June 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void if2_to_ets(
+ enum Frame_Type_3GPP frame_type_3gpp,
+ UWord8 *if2_input_ptr,
+ Word16 *ets_output_ptr)
+{
+
+ Word16 i;
+ Word16 j;
+ Word16 x = 0;
+
+ /*
+ * The following section of code accesses bits in the IF2 method of
+ * bit ordering. Each bit is given its own location in the buffer pointed
+ * to by ets_output_ptr. The bits (for modes less than AMR_SID) are
+ * reordered using the tables in bitreorder.c before the data is stored
+ * into the buffer pointed to by ets_output_ptr.
+ */
+
+ if (frame_type_3gpp < AMR_SID)
+ {
+ for (j = 4; j < 8; j++)
+ {
+ ets_output_ptr[reorderBits[frame_type_3gpp][x++]] =
+ (if2_input_ptr[0] >> j) & 0x01;
+ }
+ for (i = 1; i < numCompressedBytes[frame_type_3gpp]; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ if (x >= numOfBits[frame_type_3gpp])
+ {
+ break;
+ }
+ ets_output_ptr[reorderBits[frame_type_3gpp][x++]] =
+ (if2_input_ptr[i] >> j) & 0x01;
+ }
+ }
+ }
+ else
+ {
+ for (j = 4; j < 8; j++)
+ {
+ ets_output_ptr[x++] =
+ (if2_input_ptr[0] >> j) & 0x01;
+ }
+ for (i = 1; i < numCompressedBytes[frame_type_3gpp]; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ ets_output_ptr[x++] =
+ (if2_input_ptr[i] >> j) & 0x01;
+ }
+ }
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/if2_to_ets.h b/media/libstagefright/codecs/amrnb/dec/src/if2_to_ets.h
new file mode 100644
index 0000000..490565d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/if2_to_ets.h
@@ -0,0 +1,124 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/include/src/if2_to_ets.h
+
+ Date: 01/22/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed mode to frame_type_3gpp
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the if2_to_ets function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef IF2_TO_ETS_H
+#define IF2_TO_ETS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "frame_type_3gpp.h"
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void if2_to_ets(enum Frame_Type_3GPP frame_type_3gpp,
+ UWord8 *if2_input_ptr,
+ Word16 *ets_output_ptr);
+
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/dec/src/int_lsf.cpp b/media/libstagefright/codecs/amrnb/dec/src/int_lsf.cpp
new file mode 100644
index 0000000..c5aefe4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/int_lsf.cpp
@@ -0,0 +1,315 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/int_lsf.c
+
+ Date: 04/20/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Put file into template and first pass at optimization.
+
+ Description: Made changes based on comments from the review meeting. Used
+ pointers instead of index addressing in the arrays.
+
+ Description: Added type definition to the input/output section. Fixed tabs.
+ Deleted pseudo-code.
+
+ Description: Synchronized file with UMTS versin 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Modified FOR loops to count down.
+ 2. Made some cosmetic changes in the Pseudo-code section.
+
+ Description: Changed to pass in overflow flag pointer to the add() routine.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "int_lsf.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Int_lsf
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lsf_old = LSF vector at the 4th SF of past frame (Word16)
+ lsf_new = LSF vector at the 4th SF of present frame (Word16)
+ i_subfr = Current subframe (equal to 0,40,80 or 120) (Word16)
+ lsf_out = interpolated LSF parameters for current subframe (Word16)
+
+ Outputs:
+ lsf_out = new interpolated LSF parameters for current subframe
+ pOverflow = pointer of type Flag * to overflow indicator.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function interpolates the LSFs for selected subframe.
+ The 20 ms speech frame is divided into 4 subframes. The LSFs are
+ interpolated at the 1st, 2nd and 3rd subframe and only forwarded
+ at the 4th subframe.
+
+ |------|------|------|------|
+ sf1 sf2 sf3 sf4
+ F0 F1
+
+ sf1: 3/4 F0 + 1/4 F1 sf3: 1/4 F0 + 3/4 F1
+ sf2: 1/2 F0 + 1/2 F1 sf4: F1
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ int_lsf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Int_lsf(
+ Word16 lsf_old[], // i : LSF vector at the 4th SF of past frame
+ Word16 lsf_new[], // i : LSF vector at the 4th SF of present frame
+ Word16 i_subfr, // i : Pointer to current sf (equal to 0,40,80 or 120)
+ Word16 lsf_out[] // o : interpolated LSF parameters for current sf
+)
+{
+ Word16 i;
+
+ if ( i_subfr == 0 )
+ {
+ for (i = 0; i < M; i++) {
+ lsf_out[i] = add(sub(lsf_old[i], shr(lsf_old[i], 2)),
+ shr(lsf_new[i], 2));
+ }
+ }
+ else if ( sub(i_subfr, 40) == 0 )
+ {
+ for (i = 0; i < M; i++) {
+ lsf_out[i] = add(shr(lsf_old[i],1), shr(lsf_new[i], 1) );
+ }
+ }
+ else if ( sub(i_subfr, 80) == 0 )
+ {
+ for (i = 0; i < M; i++) {
+ lsf_out[i] = add(shr(lsf_old[i], 2),
+ sub(lsf_new[i], shr(lsf_new[i], 2)));
+ }
+ }
+ else if ( sub(i_subfr, 120) == 0 )
+ {
+ for (i = 0; i < M; i++) {
+ lsf_out[i] = lsf_new[i];
+ }
+ }
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Int_lsf(
+ Word16 lsf_old[], /* i : LSF vector at the 4th SF of past frame */
+ Word16 lsf_new[], /* i : LSF vector at the 4th SF of present frame */
+ Word16 i_subfr, /* i : Current sf (equal to 0,40,80 or 120) */
+ Word16 lsf_out[], /* o : interpolated LSF parameters for current sf */
+ Flag *pOverflow /* o : flag set if overflow occurs */
+)
+{
+ register Word16 i;
+ register Word16 temp1;
+ register Word16 temp2;
+
+ if (i_subfr == 0)
+ {
+ for (i = M - 1; i >= 0; i--)
+ {
+ if (*(lsf_old + i) < 0)
+ {
+ temp1 = ~(~(*(lsf_old + i)) >> 2);
+ }
+ else
+ {
+ temp1 = *(lsf_old + i) >> 2;
+ }
+ if (*(lsf_new + i) < 0)
+ {
+ temp2 = ~(~(*(lsf_new + i)) >> 2);
+ }
+ else
+ {
+ temp2 = *(lsf_new + i) >> 2;
+ }
+ *(lsf_out + i) = add((Word16)(*(lsf_old + i) - temp1),
+ (Word16)temp2,
+ pOverflow);
+ }
+ }
+
+ else if (i_subfr == 40)
+ {
+ for (i = M - 1; i >= 0; i--)
+ {
+ if (*(lsf_old + i) < 0)
+ {
+ temp1 = ~(~(*(lsf_old + i)) >> 1);
+ }
+ else
+ {
+ temp1 = *(lsf_old + i) >> 1;
+ }
+ if (*(lsf_new + i) < 0)
+ {
+ temp2 = ~(~(*(lsf_new + i)) >> 1);
+ }
+ else
+ {
+ temp2 = *(lsf_new + i) >> 1;
+ }
+ *(lsf_out + i) = add(
+ temp1,
+ temp2,
+ pOverflow);
+ }
+ }
+
+ else if (i_subfr == 80)
+ {
+ for (i = M - 1; i >= 0; i--)
+ {
+ if (*(lsf_old + i) < 0)
+ {
+ temp1 = ~(~(*(lsf_old + i)) >> 2);
+ }
+ else
+ {
+ temp1 = *(lsf_old + i) >> 2;
+ }
+ if (*(lsf_new + i) < 0)
+ {
+ temp2 = ~(~(*(lsf_new + i)) >> 2);
+ }
+ else
+ {
+ temp2 = *(lsf_new + i) >> 2;
+ }
+ *(lsf_out + i) = add((Word16)temp1,
+ (Word16)(*(lsf_new + i) - temp2),
+ pOverflow);
+
+ }
+ }
+
+ else if (i_subfr == 120)
+ {
+ for (i = M - 1; i >= 0; i--)
+ {
+ *(lsf_out + i) = *(lsf_new + i);
+ }
+ }
+
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/lsp_avg.cpp b/media/libstagefright/codecs/amrnb/dec/src/lsp_avg.cpp
new file mode 100644
index 0000000..9b65c7a
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/lsp_avg.cpp
@@ -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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/lsp_avg.c
+ Functions:
+
+
+ Date: 04/14/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Removed the functions lsp_avg_init and lsp_avg_exit.
+ The lsp_avg related structure is no longer dynamically allocated.
+
+ Also, placed code in the proper PV Software Template.
+
+ Description: Per review comments, updated the inputs/outputs section
+ for the function lsp_avg.
+
+ Description: Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description: Per review comments, I added a description of pOverflow
+ to the input/output section of the template. I also removed an unnecessary
+ include file, <stdio.h>
+
+ Description: Removed q_plsf_5.tab from Include section and added
+ q_plsf_5_tbl.h to Include section. Changed "mean_lsf"
+ to "mean_lsf_5" in lsp_avg_reset().
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ LSP averaging and history
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "lsp_avg.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "copy.h"
+#include "q_plsf_5_tbl.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: lsp_avg_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to structure of type lsp_avgState
+
+ Outputs:
+ fields of the structure pointed to by state are initialized.
+
+ Returns:
+ return_value = 0, if reset was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+lsp_avg.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int lsp_avg_reset (lsp_avgState *st)
+{
+ if (st == (lsp_avgState *) NULL){
+ // fprintf(stderr, "lsp_avg_reset: invalid parameter\n");
+ return -1;
+ }
+
+ Copy(mean_lsf, &st->lsp_meanSave[0], M);
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 lsp_avg_reset(lsp_avgState *st)
+{
+ if (st == (lsp_avgState *) NULL)
+ {
+ /* fprintf(stderr, "lsp_avg_reset: invalid parameter\n"); */
+ return -1;
+ }
+
+ Copy(mean_lsf_5, &st->lsp_meanSave[0], M);
+
+ return 0;
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: lsp_avg
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to structure of type lsp_avgState
+ lsp = pointer to Word16, which reflects the state of the state machine
+
+ Outputs:
+ st = pointer to structure of type lsp_avgState
+ pOverflow = pointer to type Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+lsp_avg.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+void lsp_avg (
+ lsp_avgState *st, // i/o : State struct Q15
+ Word16 *lsp // i : state of the state machine Q15
+)
+{
+ Word16 i;
+ Word32 L_tmp; // Q31
+
+ for (i = 0; i < M; i++) {
+
+ // mean = 0.84*mean
+ L_tmp = L_deposit_h(st->lsp_meanSave[i]);
+ L_tmp = L_msu(L_tmp, EXPCONST, st->lsp_meanSave[i]);
+
+ // Add 0.16 of newest LSPs to mean
+ L_tmp = L_mac(L_tmp, EXPCONST, lsp[i]);
+
+ // Save means
+ st->lsp_meanSave[i] = pv_round(L_tmp); // Q15
+ }
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void lsp_avg(
+ lsp_avgState *st, /* i/o : State struct Q15 */
+ Word16 *lsp, /* i : state of the state machine Q15 */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word32 L_tmp; /* Q31 */
+
+ for (i = 0; i < M; i++)
+ {
+
+ /* mean = 0.84*mean */
+ L_tmp = L_deposit_h(st->lsp_meanSave[i]);
+ L_tmp = L_msu(L_tmp, EXPCONST, st->lsp_meanSave[i], pOverflow);
+
+ /* Add 0.16 of newest LSPs to mean */
+ L_tmp = L_mac(L_tmp, EXPCONST, lsp[i], pOverflow);
+
+ /* Save means */
+ st->lsp_meanSave[i] = pv_round(L_tmp, pOverflow); /* Q15 */
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/lsp_avg.h b/media/libstagefright/codecs/amrnb/dec/src/lsp_avg.h
new file mode 100644
index 0000000..b289c08
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/lsp_avg.h
@@ -0,0 +1,136 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/lsp_avg.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Per review comments, I removed the prototype definition
+ of lsp_avg_init and lsp_avg_exit.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the lsp_avg.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef lsp_avg_h
+#define lsp_avg_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define EXPCONST 5243 /* 0.16 in Q15 */
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 lsp_meanSave[M]; /* Averaged LSPs saved for efficiency */
+ } lsp_avgState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ Word16 lsp_avg_reset(
+ lsp_avgState *state
+ );
+
+
+ void lsp_avg(
+ lsp_avgState *st, /* i/o : State struct Q15 */
+ Word16 *lsp, /* i : LSP vector Q15 */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LSP_LSF_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/ph_disp.cpp b/media/libstagefright/codecs/amrnb/dec/src/ph_disp.cpp
new file mode 100644
index 0000000..da5445b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/ph_disp.cpp
@@ -0,0 +1,898 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/ph_disp.c
+ Functions:
+ ph_disp_reset
+ ph_disp_lock
+ ph_disp_release
+ ph_disp
+
+ Date: 04/05/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed template used to PV coding template. First attempt at
+ optimizing C code.
+
+ Description: Updated file per comments gathered from Phase 2/3 review.
+
+ Description: Clarified grouping in the equation to calculated L_temp from the
+ product of state->prevCbGain and ONFACTPLUS1 in the ph_disp
+ function.
+
+ Description: Added setting of Overflow flag in inlined code.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ coding template. Removed unnecessary include files.
+
+ Description: Replaced basic_op.h with the header file of the math functions
+ used in the file.
+
+ Description: Removed the functions ph_disp_init and ph_disp_exit.
+ The ph_disp related structure is no longer dynamically allocated.
+
+ Description: Pass in pointer to overflow flag for EPOC compatibility.
+ Change code for ph_disp() function to reflect this. Remove
+ inclusion of ph_disp.tab. This table will now be referenced
+ externally.
+
+ Description: Optimized ph_disp() to reduce clock cycle usage. Updated
+ copyright year and removed unused files in Include section.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with defined types.
+ Added proper casting (Word32) to some left shifting operations
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the function that performs adaptive phase dispersion of
+ the excitation signal. The phase dispersion initialization, reset, and
+ exit functions are included in this file, as well as, the phase dispersion
+ lock and release functions.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "ph_disp.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ph_disp_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a structure of type ph_dispState
+
+ Outputs:
+ Structure pointed to by state is initialized to zeros
+
+ Returns:
+ return_value = 0, if reset was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function resets the variables used by the phase dispersion function.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ph_disp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int ph_disp_reset (ph_dispState *state)
+{
+ Word16 i;
+
+ if (state == (ph_dispState *) NULL){
+ fprint(stderr, "ph_disp_reset: invalid parameter\n");
+ return -1;
+ }
+ for (i=0; i<PHDGAINMEMSIZE; i++)
+ {
+ state->gainMem[i] = 0;
+ }
+ state->prevState = 0;
+ state->prevCbGain = 0;
+ state->lockFull = 0;
+ state->onset = 0; // assume no onset in start
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 ph_disp_reset(ph_dispState *state)
+{
+ register Word16 i;
+
+ if (state == (ph_dispState *) NULL)
+ {
+ /* fprint(stderr, "ph_disp_reset: invalid parameter\n"); */
+ return(-1);
+ }
+ for (i = 0; i < PHDGAINMEMSIZE; i++)
+ {
+ state->gainMem[i] = 0;
+ }
+ state->prevState = 0;
+ state->prevCbGain = 0;
+ state->lockFull = 0;
+ state->onset = 0; /* assume no onset in start */
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ph_disp_lock
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a structure of type ph_dispState
+
+ Outputs:
+ lockFull field of the structure pointed to by state is set to 1
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function sets the lockFull flag to indicate a lock condition.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ph_disp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void ph_disp_lock (ph_dispState *state)
+{
+ state->lockFull = 1;
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void ph_disp_lock(ph_dispState *state)
+{
+ state->lockFull = 1;
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ph_disp_release
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a structure of type ph_dispState
+
+ Outputs:
+ lockFull field of the structure pointed to by state is set to 0
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function clears the lockFull flag to indicate an unlocked state.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ph_disp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void ph_disp_release (ph_dispState *state)
+{
+ state->lockFull = 0;
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void ph_disp_release(ph_dispState *state)
+{
+ state->lockFull = 0;
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ph_disp
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a structure of type ph_dispState
+ mode = codec mode (enum Mode)
+ x = LTP excitation signal buffer (Word16)
+ cbGain = codebook gain (Word16)
+ ltpGain = LTP gain (Word16)
+ inno = innovation buffer (Word16)
+ pitch_fac = pitch factor used to scale the LTP excitation (Word16)
+ tmp_shift = shift factor applied to sum of scaled LTP excitation and
+ innovation before rounding (Word16)
+ pOverflow = pointer to overflow indicator (Flag)
+
+ Outputs:
+ structure pointed to by state contains the updated gainMem array,
+ prevState, prevCbGain, and onset fields
+ x buffer contains the new excitation signal
+ inno buffer contains the new innovation signal
+ pOverflow -> 1 if there is overflow
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs adaptive phase dispersion, i.e., forming of total
+ excitation for the synthesis part of the decoder.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ph_disp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void ph_disp (
+ ph_dispState *state, // i/o : State struct
+ enum Mode mode, // i : codec mode
+ Word16 x[], // i/o Q0 : in: LTP excitation signal
+ // out: total excitation signal
+ Word16 cbGain, // i Q1 : Codebook gain
+ Word16 ltpGain, // i Q14 : LTP gain
+ Word16 inno[], // i/o Q13 : Innovation vector (Q12 for 12.2)
+ Word16 pitch_fac, // i Q14 : pitch factor used to scale the
+ LTP excitation (Q13 for 12.2)
+ Word16 tmp_shift // i Q0 : shift factor applied to sum of
+ scaled LTP ex & innov. before
+ rounding
+)
+{
+ Word16 i, i1;
+ Word16 tmp1;
+ Word32 L_temp;
+ Word16 impNr; // indicator for amount of disp./filter used
+
+ Word16 inno_sav[L_SUBFR];
+ Word16 ps_poss[L_SUBFR];
+ Word16 j, nze, nPulse, ppos;
+ const Word16 *ph_imp; // Pointer to phase dispersion filter
+
+ // Update LTP gain memory
+ for (i = PHDGAINMEMSIZE-1; i > 0; i--)
+ {
+ state->gainMem[i] = state->gainMem[i-1];
+ }
+ state->gainMem[0] = ltpGain;
+
+ // basic adaption of phase dispersion
+ if (sub(ltpGain, PHDTHR2LTP) < 0) { // if (ltpGain < 0.9)
+ if (sub(ltpGain, PHDTHR1LTP) > 0)
+ { // if (ltpGain > 0.6
+ impNr = 1; // medium dispersion
+ }
+ else
+ {
+ impNr = 0; // maximum dispersion
+ }
+ }
+ else
+ {
+ impNr = 2; // no dispersion
+ }
+
+ // onset indicator
+ // onset = (cbGain > onFact * cbGainMem[0])
+ tmp1 = pv_round(L_shl(L_mult(state->prevCbGain, ONFACTPLUS1), 2));
+ if (sub(cbGain, tmp1) > 0)
+ {
+ state->onset = ONLENGTH;
+ }
+ else
+ {
+ if (state->onset > 0)
+ {
+ state->onset = sub (state->onset, 1);
+ }
+ }
+
+ // if not onset, check ltpGain buffer and use max phase dispersion if
+ half or more of the ltpGain-parameters say so
+ if (state->onset == 0)
+ {
+ // Check LTP gain memory and set filter accordingly
+ i1 = 0;
+ for (i = 0; i < PHDGAINMEMSIZE; i++)
+ {
+ if (sub(state->gainMem[i], PHDTHR1LTP) < 0)
+ {
+ i1 = add (i1, 1);
+ }
+ }
+ if (sub(i1, 2) > 0)
+ {
+ impNr = 0;
+ }
+
+ }
+ // Restrict decrease in phase dispersion to one step if not onset
+ if ((sub(impNr, add(state->prevState, 1)) > 0) && (state->onset == 0))
+ {
+ impNr = sub (impNr, 1);
+ }
+ // if onset, use one step less phase dispersion
+ if((sub(impNr, 2) < 0) && (state->onset > 0))
+ {
+ impNr = add (impNr, 1);
+ }
+
+ // disable for very low levels
+ if(sub(cbGain, 10) < 0)
+ {
+ impNr = 2;
+ }
+
+ if(sub(state->lockFull, 1) == 0)
+ {
+ impNr = 0;
+ }
+
+ // update static memory
+ state->prevState = impNr;
+ state->prevCbGain = cbGain;
+
+ // do phase dispersion for all modes but 12.2 and 7.4;
+ // don't modify the innovation if impNr >=2 (= no phase disp)
+ if (sub(mode, MR122) != 0 &&
+ sub(mode, MR102) != 0 &&
+ sub(mode, MR74) != 0 &&
+ sub(impNr, 2) < 0)
+ {
+ // track pulse positions, save innovation,
+ and initialize new innovation
+ nze = 0;
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ if (inno[i] != 0)
+ {
+ ps_poss[nze] = i;
+ nze = add (nze, 1);
+ }
+ inno_sav[i] = inno[i];
+ inno[i] = 0;
+ }
+ // Choose filter corresponding to codec mode and dispersion criterium
+ if (sub (mode, MR795) == 0)
+ {
+ if (impNr == 0)
+ {
+ ph_imp = ph_imp_low_MR795;
+ }
+ else
+ {
+ ph_imp = ph_imp_mid_MR795;
+ }
+ }
+ else
+ {
+ if (impNr == 0)
+ {
+ ph_imp = ph_imp_low;
+ }
+ else
+ {
+ ph_imp = ph_imp_mid;
+ }
+ }
+
+ // Do phase dispersion of innovation
+ for (nPulse = 0; nPulse < nze; nPulse++)
+ {
+ ppos = ps_poss[nPulse];
+
+ // circular convolution with impulse response
+ j = 0;
+ for (i = ppos; i < L_SUBFR; i++)
+ {
+ // inno[i1] += inno_sav[ppos] * ph_imp[i1-ppos]
+ tmp1 = mult(inno_sav[ppos], ph_imp[j++]);
+ inno[i] = add(inno[i], tmp1);
+ }
+
+ for (i = 0; i < ppos; i++)
+ {
+ // inno[i] += inno_sav[ppos] * ph_imp[L_SUBFR-ppos+i]
+ tmp1 = mult(inno_sav[ppos], ph_imp[j++]);
+ inno[i] = add(inno[i], tmp1);
+ }
+ }
+ }
+
+ // compute total excitation for synthesis part of decoder
+ // (using modified innovation if phase dispersion is active)
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ // x[i] = gain_pit*x[i] + cbGain*code[i];
+ L_temp = L_mult ( x[i], pitch_fac);
+ // 12.2: Q0 * Q13
+ // 7.4: Q0 * Q14
+ L_temp = L_mac (L_temp, inno[i], cbGain);
+ // 12.2: Q12 * Q1
+ // 7.4: Q13 * Q1
+ L_temp = L_shl (L_temp, tmp_shift); // Q16
+ x[i] = pv_round (L_temp);
+ }
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void ph_disp(
+ ph_dispState *state, /* i/o : State struct */
+ enum Mode mode, /* i : codec mode */
+ Word16 x[], /* i/o Q0 : in: LTP excitation signal */
+ /* out: total excitation signal */
+ Word16 cbGain, /* i Q1 : Codebook gain */
+ Word16 ltpGain, /* i Q14 : LTP gain */
+ Word16 inno[], /* i/o Q13 : Innovation vector (Q12 for 12.2) */
+ Word16 pitch_fac, /* i Q14 : pitch factor used to scale the
+ LTP excitation (Q13 for 12.2) */
+ Word16 tmp_shift, /* i Q0 : shift factor applied to sum of
+ scaled LTP ex & innov. before
+ rounding */
+ Flag *pOverflow /* i/o : oveflow indicator */
+)
+{
+ register Word16 i, i1;
+ register Word16 tmp1;
+ Word32 L_temp;
+ Word32 L_temp2;
+ Word16 impNr; /* indicator for amount of disp./filter used */
+
+ Word16 inno_sav[L_SUBFR];
+ Word16 ps_poss[L_SUBFR];
+ register Word16 nze, nPulse;
+ Word16 ppos;
+ const Word16 *ph_imp; /* Pointer to phase dispersion filter */
+
+ Word16 *p_inno;
+ Word16 *p_inno_sav;
+ Word16 *p_x;
+ const Word16 *p_ph_imp;
+ Word16 c_inno_sav;
+
+ /* Update LTP gain memory */
+ /* Unrolled FOR loop below since PHDGAINMEMSIZE is assumed to stay */
+ /* the same. */
+ /* for (i = PHDGAINMEMSIZE-1; i > 0; i--) */
+ /* { */
+ /* state->gainMem[i] = state->gainMem[i-1]; */
+ /* } */
+ state->gainMem[4] = state->gainMem[3];
+ state->gainMem[3] = state->gainMem[2];
+ state->gainMem[2] = state->gainMem[1];
+ state->gainMem[1] = state->gainMem[0];
+ state->gainMem[0] = ltpGain;
+
+ /* basic adaption of phase dispersion */
+
+ if (ltpGain < PHDTHR2LTP) /* if (ltpGain < 0.9) */
+ {
+ if (ltpGain > PHDTHR1LTP)
+ { /* if (ltpGain > 0.6 */
+ impNr = 1; /* medium dispersion */
+ }
+ else
+ {
+ impNr = 0; /* maximum dispersion */
+ }
+ }
+ else
+ {
+ impNr = 2; /* no dispersion */
+ }
+
+ /* onset indicator */
+ /* onset = (cbGain > onFact * cbGainMem[0]) */
+
+ L_temp = ((Word32) state->prevCbGain * ONFACTPLUS1) << 1;
+
+ /* (L_temp << 2) calculation with saturation check */
+ if (L_temp > (Word32) 0X1fffffffL)
+ {
+ *pOverflow = 1;
+ L_temp = MAX_32;
+ }
+ else if (L_temp < (Word32) 0xe0000000L)
+ {
+ *pOverflow = 1;
+ L_temp = MIN_32;
+ }
+ else
+ {
+ L_temp <<= 2;
+ }
+
+ tmp1 = pv_round(L_temp, pOverflow);
+
+ if (cbGain > tmp1)
+ {
+ state->onset = ONLENGTH;
+ }
+ else
+ {
+
+ if (state->onset > 0)
+ {
+ state->onset -= 1;
+ }
+ }
+
+ /* if not onset, check ltpGain buffer and use max phase dispersion if
+ half or more of the ltpGain-parameters say so */
+ if (state->onset == 0)
+ {
+ /* Check LTP gain memory and set filter accordingly */
+ i1 = 0;
+ for (i = 0; i < PHDGAINMEMSIZE; i++)
+ {
+ if (state->gainMem[i] < PHDTHR1LTP)
+ {
+ i1 += 1;
+ }
+ }
+
+ if (i1 > 2)
+ {
+ impNr = 0;
+ }
+ }
+ /* Restrict decrease in phase dispersion to one step if not onset */
+ if ((impNr > ((state->prevState) + 1)) && (state->onset == 0))
+ {
+ impNr -= 1;
+ }
+
+ /* if onset, use one step less phase dispersion */
+ if ((impNr < 2) && (state->onset > 0))
+ {
+ impNr += 1;
+ }
+
+ /* disable for very low levels */
+ if (cbGain < 10)
+ {
+ impNr = 2;
+ }
+
+ if (state->lockFull == 1)
+ {
+ impNr = 0;
+ }
+
+ /* update static memory */
+ state->prevState = impNr;
+ state->prevCbGain = cbGain;
+
+ /* do phase dispersion for all modes but 12.2 and 7.4;
+ don't modify the innovation if impNr >=2 (= no phase disp) */
+ if ((mode != MR122) && (mode != MR102) && (mode != MR74) && (impNr < 2))
+ {
+ /* track pulse positions, save innovation,
+ and initialize new innovation */
+ nze = 0;
+ p_inno = &inno[0];
+ p_inno_sav = &inno_sav[0];
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ if (*(p_inno) != 0)
+ {
+ ps_poss[nze] = i;
+ nze += 1;
+ }
+ *(p_inno_sav++) = *(p_inno);
+ *(p_inno++) = 0;
+ }
+
+ /* Choose filter corresponding to codec mode and dispersion criterium */
+ if (mode == MR795)
+ {
+ if (impNr == 0)
+ {
+ ph_imp = ph_imp_low_MR795;
+ }
+ else
+ {
+ ph_imp = ph_imp_mid_MR795;
+ }
+ }
+ else
+ {
+ if (impNr == 0)
+ {
+ ph_imp = ph_imp_low;
+ }
+ else
+ {
+ ph_imp = ph_imp_mid;
+ }
+ }
+
+ /* Do phase dispersion of innovation */
+ for (nPulse = 0; nPulse < nze; nPulse++)
+ {
+ ppos = ps_poss[nPulse];
+
+ /* circular convolution with impulse response */
+ c_inno_sav = inno_sav[ppos];
+ p_inno = &inno[ppos];
+ p_ph_imp = ph_imp;
+
+ for (i = ppos; i < L_SUBFR; i++)
+ {
+ /* inno[i1] += inno_sav[ppos] * ph_imp[i1-ppos] */
+ L_temp = ((Word32) c_inno_sav * *(p_ph_imp++)) >> 15;
+ tmp1 = (Word16) L_temp;
+ *(p_inno) = add(*(p_inno), tmp1, pOverflow);
+ p_inno += 1;
+ }
+
+ p_inno = &inno[0];
+
+ for (i = 0; i < ppos; i++)
+ {
+ /* inno[i] += inno_sav[ppos] * ph_imp[L_SUBFR-ppos+i] */
+ L_temp = ((Word32) c_inno_sav * *(p_ph_imp++)) >> 15;
+ tmp1 = (Word16) L_temp;
+ *(p_inno) = add(*(p_inno), tmp1, pOverflow);
+ p_inno += 1;
+ }
+ }
+ }
+
+ /* compute total excitation for synthesis part of decoder
+ (using modified innovation if phase dispersion is active) */
+ p_inno = &inno[0];
+ p_x = &x[0];
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ /* x[i] = gain_pit*x[i] + cbGain*code[i]; */
+ L_temp = L_mult(x[i], pitch_fac, pOverflow);
+ /* 12.2: Q0 * Q13 */
+ /* 7.4: Q0 * Q14 */
+ L_temp2 = ((Word32) * (p_inno++) * cbGain) << 1;
+ L_temp = L_add(L_temp, L_temp2, pOverflow);
+ /* 12.2: Q12 * Q1 */
+ /* 7.4: Q13 * Q1 */
+ L_temp = L_shl(L_temp, tmp_shift, pOverflow); /* Q16 */
+ *(p_x++) = pv_round(L_temp, pOverflow);
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/ph_disp.h b/media/libstagefright/codecs/amrnb/dec/src/ph_disp.h
new file mode 100644
index 0000000..58e2e4f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/ph_disp.h
@@ -0,0 +1,192 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/ph_disp.h
+
+
+ Date: 08/11/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template. Updated function prototype declaration for
+ ph_disp(). Included extern declaration for ph_imp_low_MR795 and
+ ph_imp_mid_MR795
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the Phase dispersion of excitation signal ph_disp() function.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PH_DISP_H
+#define PH_DISP_H "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define PHDGAINMEMSIZE 5
+#define PHDTHR1LTP 9830 /* 0.6 in Q14 */
+#define PHDTHR2LTP 14746 /* 0.9 in Q14 */
+#define ONFACTPLUS1 16384 /* 2.0 in Q13 */
+#define ONLENGTH 2
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern Word16 ph_imp_low_MR795[];
+ extern Word16 ph_imp_mid_MR795[];
+ extern Word16 ph_imp_low[];
+ extern Word16 ph_imp_mid[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 gainMem[PHDGAINMEMSIZE];
+ Word16 prevState;
+ Word16 prevCbGain;
+ Word16 lockFull;
+ Word16 onset;
+ } ph_dispState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ;
+ ; Function: ph_disp_reset
+ ; Purpose: Initializes state memory
+ ;
+ ----------------------------------------------------------------------------*/
+ Word16 ph_disp_reset(ph_dispState *state);
+
+ /*----------------------------------------------------------------------------
+ ;
+ ; Function: ph_disp_exit
+ ; Purpose: The memory used for state memory is freed
+ ;
+ ----------------------------------------------------------------------------*/
+ void ph_disp_exit(ph_dispState **state);
+
+ /*----------------------------------------------------------------------------
+ ;
+ ; Function: ph_disp_lock
+ ; Purpose: mark phase dispersion as locked in state struct
+ ;
+ ----------------------------------------------------------------------------*/
+ void ph_disp_lock(ph_dispState *state);
+
+ /*----------------------------------------------------------------------------
+ ;
+ ; Function: ph_disp_release
+ ; Purpose: mark phase dispersion as unlocked in state struct
+ ;
+ ----------------------------------------------------------------------------*/
+
+ void ph_disp_release(ph_dispState *state);
+
+ /*----------------------------------------------------------------------------
+ ;
+ ; Function: ph_disp
+ ; Purpose: perform phase dispersion according to the specified codec
+ ; mode and computes total excitation for synthesis part
+ ; if decoder
+ ;
+ ----------------------------------------------------------------------------*/
+
+ void ph_disp(
+ ph_dispState *state, /* i/o : State struct */
+ enum Mode mode, /* i : codec mode */
+ Word16 x[], /* i/o Q0 : in: LTP excitation signal */
+ /* out: total excitation signal */
+ Word16 cbGain, /* i Q1 : Codebook gain */
+ Word16 ltpGain, /* i Q14 : LTP gain */
+ Word16 inno[], /* i/o Q13 : Innovation vector (Q12 for 12.2) */
+ Word16 pitch_fac, /* i Q14 : pitch factor used to scale the
+ LTP excitation (Q13 for 12.2) */
+ Word16 tmp_shift, /* i Q0 : shift factor applied to sum of
+ scaled LTP ex & innov. before
+ rounding */
+ Flag *pOverflow /* i/o : oveflow indicator */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PH_DISP_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/post_pro.cpp b/media/libstagefright/codecs/amrnb/dec/src/post_pro.cpp
new file mode 100644
index 0000000..ce31793
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/post_pro.cpp
@@ -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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/post_pro.c
+ Functions:
+ Post_Process_reset
+ Post_Process
+
+ Date: 04/03/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template. First attempt at
+ optimizing C code.
+
+ Description: Deleted variables listed in the Local Stores Needed/Modified
+ sections. Optimized the "else" portion of the first "if"
+ statement in Post_Process function.
+
+ Description: Made grouping more explicit in the calculation of
+ signal[i] << 1 in the Post_Process function.
+
+ Description: Added setting of Overflow flag in inlined code.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Replaced basic_op.h with the header file of the math functions
+ used in the file.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Updated copyright year.
+ 2. Fixed typecasting issue with TI C compiler.
+ 3. Used short-hand notation for math operations, e.g., "+=",
+ in the code.
+
+ Description: Removed the functions post_pro_init and post_pro_exit.
+ The post_pro related structure is no longer dynamically allocated.
+
+ Description: Added pOverflow as a passed in variable as per changes needed
+ for the EPOC release.
+
+ Description: Optimized file to reduce clock cycle usage. Updated copyright
+ year and removed unused files in Include section.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the function that performs post-processing on the output
+ speech. Post-processing include filtering the output speech through a second
+ order high pass filter with cutoff frequency of 60 Hz, and up-scaling the
+ output speech by a factor of 2. In addition to the post-processing function
+ itself, a post-processing initialization function, post-processing reset
+ function, and post-processing exit function are also included in this file.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "post_pro.h"
+#include "typedef.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/* filter coefficients (fc = 60 Hz) */
+static const Word16 b[3] = {7699, -15398, 7699};
+static const Word16 a[3] = {8192, 15836, -7667};
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Post_Process_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a structure of type Post_ProcessState
+
+ Outputs:
+ structure pointed to by state will have all its fields initialized
+ to zero
+
+ Returns:
+ return_value = 0, if reset was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function initializes state memory to zero.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ post_pro.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Post_Process_reset (Post_ProcessState *state)
+{
+ if (state == (Post_ProcessState *) NULL){
+ fprint(stderr, "Post_Process_reset: invalid parameter\n");
+ return -1;
+ }
+
+ state->y2_hi = 0;
+ state->y2_lo = 0;
+ state->y1_hi = 0;
+ state->y1_lo = 0;
+ state->x0 = 0;
+ state->x1 = 0;
+
+ return 0;
+}
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Post_Process_reset(Post_ProcessState *state)
+{
+ if (state == (Post_ProcessState *) NULL)
+ {
+ /* fprint(stderr, "Post_Process_reset: invalid parameter\n"); */
+ return(-1);
+ }
+
+ state->y2_hi = 0;
+ state->y2_lo = 0;
+ state->y1_hi = 0;
+ state->y1_lo = 0;
+ state->x0 = 0;
+ state->x1 = 0;
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Post_Process
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type Post_ProcessState
+ signal = buffer containing the input signal (Word16)
+ lg = length of the input signal (Word16)
+ pOverflow = pointer to overflow indicator of type Flag
+
+ Outputs:
+ structure pointed to by st contains new filter input and output values
+ signal buffer contains the HP filtered and up-scaled input signal
+ pOverflow points to 1 if overflow occurs in the math functions called
+ else it points to 0.
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ a = buffer containing filter coefficients
+ b = buffer containing filter coefficients
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs post-processing on the output speech signal. First,
+ the output speech goes through a second order high pass filter with a
+ cutoff frequency of 60 Hz. Then, the filtered output speech is multiplied
+ by a factor of 2. The algorithm implemented follows the following difference
+ equation:
+
+ y[i] = b[0]*x[i]*2 + b[1]*x[i-1]*2 + b[2]*x[i-2]*2 + a[1]*y[i-1] + a[2]*y[i-2];
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ post_pro.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Post_Process (
+ Post_ProcessState *st, //i/o : post process state
+ Word16 signal[], //i/o : signal
+ Word16 lg //i : length of signal
+ )
+{
+ Word16 i, x2;
+ Word32 L_tmp;
+
+ for (i = 0; i < lg; i++)
+ {
+ x2 = st->x1;
+ st->x1 = st->x0;
+ st->x0 = signal[i];
+
+ // y[i] = b[0]*x[i]*2 + b[1]*x[i-1]*2 + b140[2]*x[i-2]/2
+ // + a[1]*y[i-1] + a[2] * y[i-2];
+
+ L_tmp = Mpy_32_16 (st->y1_hi, st->y1_lo, a[1]);
+ L_tmp = L_add (L_tmp, Mpy_32_16 (st->y2_hi, st->y2_lo, a[2]));
+ L_tmp = L_mac (L_tmp, st->x0, b[0]);
+ L_tmp = L_mac (L_tmp, st->x1, b[1]);
+ L_tmp = L_mac (L_tmp, x2, b[2]);
+ L_tmp = L_shl (L_tmp, 2);
+
+ //Multiplication by two of output speech with saturation.
+ signal[i] = pv_round(L_shl(L_tmp, 1));
+
+ st->y2_hi = st->y1_hi;
+ st->y2_lo = st->y1_lo;
+ L_Extract (L_tmp, &st->y1_hi, &st->y1_lo);
+ }
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Post_Process(
+ Post_ProcessState *st, /* i/o : post process state */
+ Word16 signal[], /* i/o : signal */
+ Word16 lg, /* i : length of signal */
+ Flag *pOverflow
+)
+{
+ Word16 i, x2;
+ Word32 L_tmp;
+
+ Word16 *p_signal;
+ Word16 c_a1 = a[1];
+ Word16 c_a2 = a[2];
+ Word16 c_b0 = b[0];
+ Word16 c_b1 = b[1];
+ Word16 c_b2 = b[2];
+
+ p_signal = &signal[0];
+
+ for (i = 0; i < lg; i++)
+ {
+ x2 = st->x1;
+ st->x1 = st->x0;
+ st->x0 = *(p_signal);
+
+ /* y[i] = b[0]*x[i]*2 + b[1]*x[i-1]*2 + b140[2]*x[i-2]/2 */
+ /* + a[1]*y[i-1] + a[2] * y[i-2]; */
+
+ L_tmp = ((Word32) st->y1_hi) * c_a1;
+ L_tmp += (((Word32) st->y1_lo) * c_a1) >> 15;
+ L_tmp += ((Word32) st->y2_hi) * c_a2;
+ L_tmp += (((Word32) st->y2_lo) * c_a2) >> 15;
+ L_tmp += ((Word32) st->x0) * c_b0;
+ L_tmp += ((Word32) st->x1) * c_b1;
+ L_tmp += ((Word32) x2) * c_b2;
+ L_tmp <<= 3;
+
+
+ /* Multiplication by two of output speech with saturation. */
+
+ *(p_signal++) = pv_round(L_shl(L_tmp, 1, pOverflow), pOverflow);
+
+ st->y2_hi = st->y1_hi;
+ st->y2_lo = st->y1_lo;
+
+ st->y1_hi = (Word16)(L_tmp >> 16);
+ st->y1_lo = (Word16)((L_tmp >> 1) - ((Word32) st->y1_hi << 15));
+
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/post_pro.h b/media/libstagefright/codecs/amrnb/dec/src/post_pro.h
new file mode 100644
index 0000000..85e5888
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/post_pro.h
@@ -0,0 +1,140 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/post_pro.h
+
+ Date: 02/04/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : post_pro.h
+ Purpose : Postprocessing of output speech.
+
+ - 2nd order high pass filtering with cut
+ off frequency at 60 Hz.
+ - Multiplication of output by two.
+------------------------------------------------------------------------------
+*/
+
+#ifndef _POST_PRO_H_
+#define _POST_PRO_H_
+#define post_pro_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 y2_hi;
+ Word16 y2_lo;
+ Word16 y1_hi;
+ Word16 y1_lo;
+ Word16 x0;
+ Word16 x1;
+ } Post_ProcessState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ Word16 Post_Process_reset(Post_ProcessState *st);
+ /* reset of Post processing state (i.e. set state memory to zero)
+ returns 0 on success
+ */
+ void Post_Process_exit(Post_ProcessState **st);
+ /* de-initialize Post processing state (i.e. free status struct)
+ stores NULL in *st
+ */
+
+ void Post_Process(
+ Post_ProcessState *st, /* i/o : post process state */
+ Word16 signal[], /* i/o : signal */
+ Word16 lg, /* i : lenght of signal */
+ Flag *pOverflow
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _POST_PRO_H_ */
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/preemph.cpp b/media/libstagefright/codecs/amrnb/dec/src/preemph.cpp
new file mode 100644
index 0000000..9864325
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/preemph.cpp
@@ -0,0 +1,272 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/preemph.c
+ Functions:
+
+ Date: 02/04/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Removed the functions preemphasis_init and preemphasis_exit.
+ The preemphasis related structure is no longer dynamically allocated.
+ Placed file in the appropriate PV Software Template format.
+
+ Description: Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Purpose : Preemphasis filtering
+ Description : Filtering through 1 - g z^-1
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "preemph.h"
+#include "typedef.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: preemphasis_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- double pointer to preemphasisState
+
+ Outputs:
+ st -- double ponter to preemphasisState
+
+ Returns:
+ -1 if an error occurs
+ 0 if OK
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Initializes state memory to zero
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ preemph.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 preemphasis_reset(preemphasisState *state)
+{
+ if (state == (preemphasisState *) NULL)
+ {
+ /* fprintf(stderr, "preemphasis_reset: invalid parameter\n"); */
+ return -1;
+ }
+
+ state->mem_pre = 0;
+
+ return 0;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: preemphasis
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- Pointer to preemphasisState -- preemphasis filter state
+ signal -- array of type Word16 -- input signal overwritten by the output
+ g -- Word16 -- preemphasis coefficient
+ L -- Word16 -- size of filtering
+
+ Outputs:
+ st -- Pointer to preemphasisState -- preemphasis filter state
+ signal -- array of type Word16 -- input signal overwritten by the output
+ pOverflow -- pointer to type Flag -- overflow indicator
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Filtering through 1 - g z^-1
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ preemph.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+
+void preemphasis(
+ preemphasisState *st, /* (i/o) : preemphasis filter state */
+ Word16 *signal, /* (i/o) : input signal overwritten by the output */
+ Word16 g, /* (i) : preemphasis coefficient */
+ Word16 L, /* (i) : size of filtering */
+ Flag *pOverflow /* (o) : overflow indicator */
+)
+{
+ Word16 *p1;
+ Word16 *p2;
+ Word16 temp;
+ Word16 temp2;
+ Word16 i;
+
+ p1 = signal + L - 1;
+ p2 = p1 - 1;
+ temp = *p1;
+
+ for (i = 0; i <= L - 2; i++)
+ {
+ temp2 = mult(g, *(p2--), pOverflow);
+ *p1 = sub(*p1, temp2, pOverflow);
+
+ p1--;
+ }
+
+ temp2 = mult(g, st->mem_pre, pOverflow);
+
+ *p1 = sub(*p1, temp2, pOverflow);
+
+ st->mem_pre = temp;
+
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/preemph.h b/media/libstagefright/codecs/amrnb/dec/src/preemph.h
new file mode 100644
index 0000000..20bab71
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/preemph.h
@@ -0,0 +1,140 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/preemph.h
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the file, preemph.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef preemph_h
+#define preemph_h "$Id $"
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 mem_pre; /* filter state */
+ } preemphasisState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ Word16 preemphasis_reset(preemphasisState *st);
+ /* reset of preemphasis filter (i.e. set state memory to zero)
+ returns 0 on success
+ */
+ void preemphasis_exit(preemphasisState **st);
+ /* de-initialize preemphasis filter (i.e. free status struct)
+ stores NULL in *st
+ */
+
+ void preemphasis(
+ preemphasisState *st, /* (i/o): preemphasis filter state */
+ Word16 *signal, /* (i/o): input signal overwritten by the output */
+ Word16 g, /* (i) : preemphasis coefficient */
+ Word16 L, /* (i) : size of filtering */
+ Flag *pOverflow /* (o) : overflow indicator */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* preemph_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp b/media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp
new file mode 100644
index 0000000..0336990
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/pstfilt.cpp
@@ -0,0 +1,578 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/pstfilt.c
+ Functions:
+ Post_Filter_reset
+ Post_Filter
+
+ Date: 04/14/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed template used to PV coding template. First attempt at
+ optimizing C code.
+
+ Description: Updated file per comments gathered from Phase 2/3 review.
+
+ Description: Added setting of Overflow flag in inlined code.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Replaced basic_op.h with the header file of the math functions
+ used in the file.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Updated copyright year.
+ 2. Modified FOR loops to count down.
+ 3. Fixed typecasting issue with TI C compiler.
+ 4. Added "break" statement after overflow condition occurs.
+
+ Description: Removed the functions pstfilt_init and pstfilt_exit.
+ The pst_filt related structure is no longer dynamically allocated.
+
+ Description: Modified code for EPOC changes where pOverflow is passed in
+ rather than allowing overflow to be a global variable.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with defined types.
+ Added proper casting (Word32) to some left shifting operations
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the function that performs adaptive post-filtering on the
+ synthesized speech. It also contains the functions that initialize, reset,
+ and exit the post-filtering function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <string.h>
+
+#include "pstfilt.h"
+#include "typedef.h"
+#include "mode.h"
+#include "basicop_malloc.h"
+#include "basic_op.h"
+#include "weight_a.h"
+#include "residu.h"
+#include "copy.h"
+#include "syn_filt.h"
+#include "preemph.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define L_H 22 /* size of truncated impulse response of A(z/g1)/A(z/g2) */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/* Spectral expansion factors */
+static const Word16 gamma3_MR122[M] =
+{
+ 22938, 16057, 11240, 7868, 5508,
+ 3856, 2699, 1889, 1322, 925
+};
+
+static const Word16 gamma3[M] =
+{
+ 18022, 9912, 5451, 2998, 1649, 907, 499, 274, 151, 83
+};
+
+static const Word16 gamma4_MR122[M] =
+{
+ 24576, 18432, 13824, 10368, 7776,
+ 5832, 4374, 3281, 2461, 1846
+};
+
+static const Word16 gamma4[M] =
+{
+ 22938, 16057, 11240, 7868, 5508, 3856, 2699, 1889, 1322, 925
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Post_Filter_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to structure of type Post_FilterState
+
+ Outputs:
+ fields of the structure pointed to by state is initialized to zero
+
+ Returns:
+ return_value = 0, if reset was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function initializes the state memory used by the Post_Filter function
+ to zero.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Post_Filter_reset (Post_FilterState *state)
+{
+ if (state == (Post_FilterState *) NULL){
+ fprintf(stderr, "Post_Filter_reset: invalid parameter\n");
+ return -1;
+ }
+
+ Set_zero (state->mem_syn_pst, M);
+ Set_zero (state->res2, L_SUBFR);
+ Set_zero (state->synth_buf, L_FRAME + M);
+ agc_reset(state->agc_state);
+ preemphasis_reset(state->preemph_state);
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Post_Filter_reset(Post_FilterState *state)
+{
+ if (state == (Post_FilterState *) NULL)
+ {
+ /*fprintf(stderr, "Post_Filter_reset: invalid parameter\n"); */
+ return(-1);
+ }
+
+ memset(state->mem_syn_pst, 0, sizeof(Word16)*M);
+ memset(state->res2, 0, sizeof(Word16)*L_SUBFR);
+ memset(state->synth_buf, 0, sizeof(Word16)*(L_FRAME + M));
+ agc_reset(&(state->agc_state));
+ preemphasis_reset(&(state->preemph_state));
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Post_Filter
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type Post_FilterState
+ mode = AMR mode
+ syn = pointer to a buffer containing synthesized speech; upon
+ exiting this function, it will contain the post-filtered
+ synthesized speech
+ Az_4 = pointer to the interpolated LPC parameters for all subframes
+ pOverflow = pointer to overflow indicator of type Flag
+
+ Outputs:
+ fields of the structure pointed to by st contains the updated field
+ values
+ syn buffer contains the post-filtered synthesized speech
+ pOverflow = 1 if overflow occurrs in the math functions called else
+ it is zero.
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs the post-filtering on the synthesized speech. The
+ post-filtering process is described as follows:
+ (1) inverse filtering of syn[] through A(z/0.7) to get res2[]
+ (2) tilt compensation filtering; 1 - MU*k*z^-1
+ (3) synthesis filtering through 1/A(z/0.75)
+ (4) adaptive gain control
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pstfilt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Post_Filter (
+ Post_FilterState *st, // i/o : post filter states
+ enum Mode mode, // i : AMR mode
+ Word16 *syn, // i/o : synthesis speech (postfiltered is output)
+ Word16 *Az_4 // i : interpolated LPC parameters in all subfr.
+)
+{
+ *-------------------------------------------------------------------*
+ * Declaration of parameters *
+ *-------------------------------------------------------------------*
+
+ Word16 Ap3[MP1], Ap4[MP1]; // bandwidth expanded LP parameters
+ Word16 *Az; // pointer to Az_4:
+ // LPC parameters in each subframe
+ Word16 i_subfr; // index for beginning of subframe
+ Word16 h[L_H];
+
+ Word16 i;
+ Word16 temp1, temp2;
+ Word32 L_tmp;
+ Word16 *syn_work = &st->synth_buf[M];
+
+
+ *-----------------------------------------------------*
+ * Post filtering *
+ *-----------------------------------------------------*
+
+ Copy (syn, syn_work , L_FRAME);
+
+ Az = Az_4;
+
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ // Find weighted filter coefficients Ap3[] and ap[4]
+
+ if (sub(mode, MR122) == 0 || sub(mode, MR102) == 0)
+ {
+ Weight_Ai (Az, gamma3_MR122, Ap3);
+ Weight_Ai (Az, gamma4_MR122, Ap4);
+ }
+ else
+ {
+ Weight_Ai (Az, gamma3, Ap3);
+ Weight_Ai (Az, gamma4, Ap4);
+ }
+
+ // filtering of synthesis speech by A(z/0.7) to find res2[]
+
+ Residu (Ap3, &syn_work[i_subfr], st->res2, L_SUBFR);
+
+ // tilt compensation filter
+
+ // impulse response of A(z/0.7)/A(z/0.75)
+
+ Copy (Ap3, h, M + 1);
+ Set_zero (&h[M + 1], L_H - M - 1);
+ Syn_filt (Ap4, h, h, L_H, &h[M + 1], 0);
+
+ // 1st correlation of h[]
+
+ L_tmp = L_mult (h[0], h[0]);
+ for (i = 1; i < L_H; i++)
+ {
+ L_tmp = L_mac (L_tmp, h[i], h[i]);
+ }
+ temp1 = extract_h (L_tmp);
+
+ L_tmp = L_mult (h[0], h[1]);
+ for (i = 1; i < L_H - 1; i++)
+ {
+ L_tmp = L_mac (L_tmp, h[i], h[i + 1]);
+ }
+ temp2 = extract_h (L_tmp);
+
+ if (temp2 <= 0)
+ {
+ temp2 = 0;
+ }
+ else
+ {
+ temp2 = mult (temp2, MU);
+ temp2 = div_s (temp2, temp1);
+ }
+
+ preemphasis (st->preemph_state, st->res2, temp2, L_SUBFR);
+
+ // filtering through 1/A(z/0.75)
+
+ Syn_filt (Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1);
+
+ // scale output to input
+
+ agc (st->agc_state, &syn_work[i_subfr], &syn[i_subfr],
+ AGC_FAC, L_SUBFR);
+
+ Az += MP1;
+ }
+
+ // update syn_work[] buffer
+
+ Copy (&syn_work[L_FRAME - M], &syn_work[-M], M);
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Post_Filter(
+ Post_FilterState *st, /* i/o : post filter states */
+ enum Mode mode, /* i : AMR mode */
+ Word16 *syn, /* i/o : synthesis speech (postfiltered is output) */
+ Word16 *Az_4, /* i : interpolated LPC parameters in all subfr. */
+ Flag *pOverflow
+)
+{
+ Word16 Ap3[MP1];
+ Word16 Ap4[MP1]; /* bandwidth expanded LP parameters */
+ Word16 *Az; /* pointer to Az_4: */
+ /* LPC parameters in each subframe */
+ register Word16 i_subfr; /* index for beginning of subframe */
+ Word16 h[L_H];
+
+ register Word16 i;
+ Word16 temp1;
+ Word16 temp2;
+ Word32 L_tmp;
+ Word32 L_tmp2;
+ Word16 *syn_work = &st->synth_buf[M];
+
+
+ /*-----------------------------------------------------*
+ * Post filtering *
+ *-----------------------------------------------------*/
+
+ Copy(syn, syn_work , L_FRAME);
+
+ Az = Az_4;
+
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ /* Find weighted filter coefficients Ap3[] and ap[4] */
+
+ if (mode == MR122 || mode == MR102)
+ {
+ Weight_Ai(Az, gamma3_MR122, Ap3);
+ Weight_Ai(Az, gamma4_MR122, Ap4);
+ }
+ else
+ {
+ Weight_Ai(Az, gamma3, Ap3);
+ Weight_Ai(Az, gamma4, Ap4);
+ }
+
+ /* filtering of synthesis speech by A(z/0.7) to find res2[] */
+
+ Residu(Ap3, &syn_work[i_subfr], st->res2, L_SUBFR);
+
+ /* tilt compensation filter */
+
+ /* impulse response of A(z/0.7)/A(z/0.75) */
+
+ Copy(Ap3, h, M + 1);
+ memset(&h[M + 1], 0, sizeof(Word16)*(L_H - M - 1));
+ Syn_filt(Ap4, h, h, L_H, &h[M + 1], 0);
+
+ /* 1st correlation of h[] */
+
+ L_tmp = 0;
+
+ for (i = L_H - 1; i >= 0; i--)
+ {
+ L_tmp2 = ((Word32) h[i]) * h[i];
+
+ if (L_tmp2 != (Word32) 0x40000000L)
+ {
+ L_tmp2 = L_tmp2 << 1;
+ }
+ else
+ {
+ *pOverflow = 1;
+ L_tmp2 = MAX_32;
+ break;
+ }
+
+ L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
+ }
+ temp1 = (Word16)(L_tmp >> 16);
+
+ L_tmp = 0;
+
+ for (i = L_H - 2; i >= 0; i--)
+ {
+ L_tmp2 = ((Word32) h[i]) * h[i + 1];
+
+ if (L_tmp2 != (Word32) 0x40000000L)
+ {
+ L_tmp2 = L_tmp2 << 1;
+ }
+ else
+ {
+ *pOverflow = 1;
+ L_tmp2 = MAX_32;
+ break;
+ }
+
+ L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
+ }
+ temp2 = (Word16)(L_tmp >> 16);
+
+ if (temp2 <= 0)
+ {
+ temp2 = 0;
+ }
+ else
+ {
+ L_tmp = (((Word32) temp2) * MU) >> 15;
+
+ /* Sign-extend product */
+ if (L_tmp & (Word32) 0x00010000L)
+ {
+ L_tmp = L_tmp | (Word32) 0xffff0000L;
+ }
+ temp2 = (Word16) L_tmp;
+
+ temp2 = div_s(temp2, temp1);
+ }
+
+ preemphasis(&(st->preemph_state), st->res2, temp2, L_SUBFR, pOverflow);
+
+ /* filtering through 1/A(z/0.75) */
+
+ Syn_filt(Ap4, st->res2, &syn[i_subfr], L_SUBFR, st->mem_syn_pst, 1);
+
+ /* scale output to input */
+
+ agc(&(st->agc_state), &syn_work[i_subfr], &syn[i_subfr],
+ AGC_FAC, L_SUBFR, pOverflow);
+
+ Az += MP1;
+ }
+
+ /* update syn_work[] buffer */
+
+ Copy(&syn_work[L_FRAME - M], &syn_work[-M], M);
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/dec/src/pstfilt.h b/media/libstagefright/codecs/amrnb/dec/src/pstfilt.h
new file mode 100644
index 0000000..29c0d84
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/pstfilt.h
@@ -0,0 +1,143 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/pstfilt.h
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : pstfilt.h
+ Purpose : Performs adaptive postfiltering on the synthesis
+ : speech
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _PSTFILT_H_
+#define _PSTFILT_H_
+#define pstfilt_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "cnst.h"
+#include "preemph.h"
+#include "agc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 res2[L_SUBFR];
+ Word16 mem_syn_pst[M];
+ preemphasisState preemph_state;
+ agcState agc_state;
+ Word16 synth_buf[M + L_FRAME];
+ } Post_FilterState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ Word16 Post_Filter_reset(Post_FilterState *st);
+ /* reset post filter (i.e. set state memory to zero)
+ returns 0 on success
+ */
+
+ void Post_Filter(
+ Post_FilterState *st, /* i/o : post filter states */
+ enum Mode mode, /* i : AMR mode */
+ Word16 *syn, /* i/o : synthesis speech (postfiltered is output) */
+ Word16 *Az_4, /* i : interpolated LPC parameters in all subfr. */
+ Flag *pOverflow
+ );
+ /* filters the signal syn using the parameters in Az_4 to calculate filter
+ coefficients.
+ The filter must be set up using Post_Filter_init prior to the first call
+ to Post_Filter. Post_FilterState is updated to mirror the current state
+ of the filter
+
+ return 0 on success
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PSTFILT_H_ */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/pvgsmamrdecoder.cpp b/media/libstagefright/codecs/amrnb/dec/src/pvgsmamrdecoder.cpp
new file mode 100644
index 0000000..95b0b47
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/pvgsmamrdecoder.cpp
@@ -0,0 +1,77 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+
+#include "PVGSMAMRDecoder.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+OSCL_EXPORT_REF CPVGSMAMRDecoder::CPVGSMAMRDecoder()
+{
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+OSCL_EXPORT_REF CPVGSMAMRDecoder::~CPVGSMAMRDecoder()
+{
+ delete iDecState;
+ iDecState = NULL;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+OSCL_EXPORT_REF int32 CPVGSMAMRDecoder::InitDecoder(void)
+{
+ return GSMInitDecode(&iDecState, (int8*)"Decoder");
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+OSCL_EXPORT_REF int32 CPVGSMAMRDecoder::DecodeFrame(Frame_Type_3GPP aType,
+ uint8* aCompressedBlock,
+ uint8* aAudioBuffer,
+ int32 aFormat)
+{
+ return AMRDecode(iDecState, aType, aCompressedBlock, (Word16*)aAudioBuffer, (Word16) aFormat);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+OSCL_EXPORT_REF int32 CPVGSMAMRDecoder::ResetDecoder(void)
+{
+ return Speech_Decode_Frame_reset(iDecState);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+OSCL_EXPORT_REF void CPVGSMAMRDecoder::TerminateDecoder(void)
+{
+ GSMDecodeFrameExit(&iDecState);
+ iDecState = NULL;
+}
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/qgain475_tab.cpp b/media/libstagefright/codecs/amrnb/dec/src/qgain475_tab.cpp
new file mode 100644
index 0000000..1a08efa
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/qgain475_tab.cpp
@@ -0,0 +1,435 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+
+
+ Filename: /audio/gsm_amr/c/src/qgain475_tab.c
+
+ Date: 12/09/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created this file from the reference, qgain475.tab.
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "qgain475_tab.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+
+ /* The table contains the following data:
+ *
+ * g_pitch(0) (Q14) // for sub-
+ * g_fac(0) (Q12) // frame 0 and 2
+ * g_pitch(1) (Q14) // for sub-
+ * g_fac(2) (Q12) // frame 1 and 3
+ *
+ */
+ const Word16 table_gain_MR475[MR475_VQ_SIZE*4] =
+ {
+ /*g_pit(0), g_fac(0), g_pit(1), g_fac(1) */
+ 812, 128, 542, 140,
+ 2873, 1135, 2266, 3402,
+ 2067, 563, 12677, 647,
+ 4132, 1798, 5601, 5285,
+ 7689, 374, 3735, 441,
+ 10912, 2638, 11807, 2494,
+ 20490, 797, 5218, 675,
+ 6724, 8354, 5282, 1696,
+ 1488, 428, 5882, 452,
+ 5332, 4072, 3583, 1268,
+ 2469, 901, 15894, 1005,
+ 14982, 3271, 10331, 4858,
+ 3635, 2021, 2596, 835,
+ 12360, 4892, 12206, 1704,
+ 13432, 1604, 9118, 2341,
+ 3968, 1538, 5479, 9936,
+ 3795, 417, 1359, 414,
+ 3640, 1569, 7995, 3541,
+ 11405, 645, 8552, 635,
+ 4056, 1377, 16608, 6124,
+ 11420, 700, 2007, 607,
+ 12415, 1578, 11119, 4654,
+ 13680, 1708, 11990, 1229,
+ 7996, 7297, 13231, 5715,
+ 2428, 1159, 2073, 1941,
+ 6218, 6121, 3546, 1804,
+ 8925, 1802, 8679, 1580,
+ 13935, 3576, 13313, 6237,
+ 6142, 1130, 5994, 1734,
+ 14141, 4662, 11271, 3321,
+ 12226, 1551, 13931, 3015,
+ 5081, 10464, 9444, 6706,
+ 1689, 683, 1436, 1306,
+ 7212, 3933, 4082, 2713,
+ 7793, 704, 15070, 802,
+ 6299, 5212, 4337, 5357,
+ 6676, 541, 6062, 626,
+ 13651, 3700, 11498, 2408,
+ 16156, 716, 12177, 751,
+ 8065, 11489, 6314, 2256,
+ 4466, 496, 7293, 523,
+ 10213, 3833, 8394, 3037,
+ 8403, 966, 14228, 1880,
+ 8703, 5409, 16395, 4863,
+ 7420, 1979, 6089, 1230,
+ 9371, 4398, 14558, 3363,
+ 13559, 2873, 13163, 1465,
+ 5534, 1678, 13138, 14771,
+ 7338, 600, 1318, 548,
+ 4252, 3539, 10044, 2364,
+ 10587, 622, 13088, 669,
+ 14126, 3526, 5039, 9784,
+ 15338, 619, 3115, 590,
+ 16442, 3013, 15542, 4168,
+ 15537, 1611, 15405, 1228,
+ 16023, 9299, 7534, 4976,
+ 1990, 1213, 11447, 1157,
+ 12512, 5519, 9475, 2644,
+ 7716, 2034, 13280, 2239,
+ 16011, 5093, 8066, 6761,
+ 10083, 1413, 5002, 2347,
+ 12523, 5975, 15126, 2899,
+ 18264, 2289, 15827, 2527,
+ 16265, 10254, 14651, 11319,
+ 1797, 337, 3115, 397,
+ 3510, 2928, 4592, 2670,
+ 7519, 628, 11415, 656,
+ 5946, 2435, 6544, 7367,
+ 8238, 829, 4000, 863,
+ 10032, 2492, 16057, 3551,
+ 18204, 1054, 6103, 1454,
+ 5884, 7900, 18752, 3468,
+ 1864, 544, 9198, 683,
+ 11623, 4160, 4594, 1644,
+ 3158, 1157, 15953, 2560,
+ 12349, 3733, 17420, 5260,
+ 6106, 2004, 2917, 1742,
+ 16467, 5257, 16787, 1680,
+ 17205, 1759, 4773, 3231,
+ 7386, 6035, 14342, 10012,
+ 4035, 442, 4194, 458,
+ 9214, 2242, 7427, 4217,
+ 12860, 801, 11186, 825,
+ 12648, 2084, 12956, 6554,
+ 9505, 996, 6629, 985,
+ 10537, 2502, 15289, 5006,
+ 12602, 2055, 15484, 1653,
+ 16194, 6921, 14231, 5790,
+ 2626, 828, 5615, 1686,
+ 13663, 5778, 3668, 1554,
+ 11313, 2633, 9770, 1459,
+ 14003, 4733, 15897, 6291,
+ 6278, 1870, 7910, 2285,
+ 16978, 4571, 16576, 3849,
+ 15248, 2311, 16023, 3244,
+ 14459, 17808, 11847, 2763,
+ 1981, 1407, 1400, 876,
+ 4335, 3547, 4391, 4210,
+ 5405, 680, 17461, 781,
+ 6501, 5118, 8091, 7677,
+ 7355, 794, 8333, 1182,
+ 15041, 3160, 14928, 3039,
+ 20421, 880, 14545, 852,
+ 12337, 14708, 6904, 1920,
+ 4225, 933, 8218, 1087,
+ 10659, 4084, 10082, 4533,
+ 2735, 840, 20657, 1081,
+ 16711, 5966, 15873, 4578,
+ 10871, 2574, 3773, 1166,
+ 14519, 4044, 20699, 2627,
+ 15219, 2734, 15274, 2186,
+ 6257, 3226, 13125, 19480,
+ 7196, 930, 2462, 1618,
+ 4515, 3092, 13852, 4277,
+ 10460, 833, 17339, 810,
+ 16891, 2289, 15546, 8217,
+ 13603, 1684, 3197, 1834,
+ 15948, 2820, 15812, 5327,
+ 17006, 2438, 16788, 1326,
+ 15671, 8156, 11726, 8556,
+ 3762, 2053, 9563, 1317,
+ 13561, 6790, 12227, 1936,
+ 8180, 3550, 13287, 1778,
+ 16299, 6599, 16291, 7758,
+ 8521, 2551, 7225, 2645,
+ 18269, 7489, 16885, 2248,
+ 17882, 2884, 17265, 3328,
+ 9417, 20162, 11042, 8320,
+ 1286, 620, 1431, 583,
+ 5993, 2289, 3978, 3626,
+ 5144, 752, 13409, 830,
+ 5553, 2860, 11764, 5908,
+ 10737, 560, 5446, 564,
+ 13321, 3008, 11946, 3683,
+ 19887, 798, 9825, 728,
+ 13663, 8748, 7391, 3053,
+ 2515, 778, 6050, 833,
+ 6469, 5074, 8305, 2463,
+ 6141, 1865, 15308, 1262,
+ 14408, 4547, 13663, 4515,
+ 3137, 2983, 2479, 1259,
+ 15088, 4647, 15382, 2607,
+ 14492, 2392, 12462, 2537,
+ 7539, 2949, 12909, 12060,
+ 5468, 684, 3141, 722,
+ 5081, 1274, 12732, 4200,
+ 15302, 681, 7819, 592,
+ 6534, 2021, 16478, 8737,
+ 13364, 882, 5397, 899,
+ 14656, 2178, 14741, 4227,
+ 14270, 1298, 13929, 2029,
+ 15477, 7482, 15815, 4572,
+ 2521, 2013, 5062, 1804,
+ 5159, 6582, 7130, 3597,
+ 10920, 1611, 11729, 1708,
+ 16903, 3455, 16268, 6640,
+ 9306, 1007, 9369, 2106,
+ 19182, 5037, 12441, 4269,
+ 15919, 1332, 15357, 3512,
+ 11898, 14141, 16101, 6854,
+ 2010, 737, 3779, 861,
+ 11454, 2880, 3564, 3540,
+ 9057, 1241, 12391, 896,
+ 8546, 4629, 11561, 5776,
+ 8129, 589, 8218, 588,
+ 18728, 3755, 12973, 3149,
+ 15729, 758, 16634, 754,
+ 15222, 11138, 15871, 2208,
+ 4673, 610, 10218, 678,
+ 15257, 4146, 5729, 3327,
+ 8377, 1670, 19862, 2321,
+ 15450, 5511, 14054, 5481,
+ 5728, 2888, 7580, 1346,
+ 14384, 5325, 16236, 3950,
+ 15118, 3744, 15306, 1435,
+ 14597, 4070, 12301, 15696,
+ 7617, 1699, 2170, 884,
+ 4459, 4567, 18094, 3306,
+ 12742, 815, 14926, 907,
+ 15016, 4281, 15518, 8368,
+ 17994, 1087, 2358, 865,
+ 16281, 3787, 15679, 4596,
+ 16356, 1534, 16584, 2210,
+ 16833, 9697, 15929, 4513,
+ 3277, 1085, 9643, 2187,
+ 11973, 6068, 9199, 4462,
+ 8955, 1629, 10289, 3062,
+ 16481, 5155, 15466, 7066,
+ 13678, 2543, 5273, 2277,
+ 16746, 6213, 16655, 3408,
+ 20304, 3363, 18688, 1985,
+ 14172, 12867, 15154, 15703,
+ 4473, 1020, 1681, 886,
+ 4311, 4301, 8952, 3657,
+ 5893, 1147, 11647, 1452,
+ 15886, 2227, 4582, 6644,
+ 6929, 1205, 6220, 799,
+ 12415, 3409, 15968, 3877,
+ 19859, 2109, 9689, 2141,
+ 14742, 8830, 14480, 2599,
+ 1817, 1238, 7771, 813,
+ 19079, 4410, 5554, 2064,
+ 3687, 2844, 17435, 2256,
+ 16697, 4486, 16199, 5388,
+ 8028, 2763, 3405, 2119,
+ 17426, 5477, 13698, 2786,
+ 19879, 2720, 9098, 3880,
+ 18172, 4833, 17336, 12207,
+ 5116, 996, 4935, 988,
+ 9888, 3081, 6014, 5371,
+ 15881, 1667, 8405, 1183,
+ 15087, 2366, 19777, 7002,
+ 11963, 1562, 7279, 1128,
+ 16859, 1532, 15762, 5381,
+ 14708, 2065, 20105, 2155,
+ 17158, 8245, 17911, 6318,
+ 5467, 1504, 4100, 2574,
+ 17421, 6810, 5673, 2888,
+ 16636, 3382, 8975, 1831,
+ 20159, 4737, 19550, 7294,
+ 6658, 2781, 11472, 3321,
+ 19397, 5054, 18878, 4722,
+ 16439, 2373, 20430, 4386,
+ 11353, 26526, 11593, 3068,
+ 2866, 1566, 5108, 1070,
+ 9614, 4915, 4939, 3536,
+ 7541, 878, 20717, 851,
+ 6938, 4395, 16799, 7733,
+ 10137, 1019, 9845, 964,
+ 15494, 3955, 15459, 3430,
+ 18863, 982, 20120, 963,
+ 16876, 12887, 14334, 4200,
+ 6599, 1220, 9222, 814,
+ 16942, 5134, 5661, 4898,
+ 5488, 1798, 20258, 3962,
+ 17005, 6178, 17929, 5929,
+ 9365, 3420, 7474, 1971,
+ 19537, 5177, 19003, 3006,
+ 16454, 3788, 16070, 2367,
+ 8664, 2743, 9445, 26358,
+ 10856, 1287, 3555, 1009,
+ 5606, 3622, 19453, 5512,
+ 12453, 797, 20634, 911,
+ 15427, 3066, 17037, 10275,
+ 18883, 2633, 3913, 1268,
+ 19519, 3371, 18052, 5230,
+ 19291, 1678, 19508, 3172,
+ 18072, 10754, 16625, 6845,
+ 3134, 2298, 10869, 2437,
+ 15580, 6913, 12597, 3381,
+ 11116, 3297, 16762, 2424,
+ 18853, 6715, 17171, 9887,
+ 12743, 2605, 8937, 3140,
+ 19033, 7764, 18347, 3880,
+ 20475, 3682, 19602, 3380,
+ 13044, 19373, 10526, 23124
+ };
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] qua_gain.tab, UMTS GSM AMR speech codec,
+ R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/sp_dec.cpp b/media/libstagefright/codecs/amrnb/dec/src/sp_dec.cpp
new file mode 100644
index 0000000..2989b74
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/sp_dec.cpp
@@ -0,0 +1,699 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/sp_dec.c
+ Functions: GSMInitDecode
+ Speech_Decode_Frame_reset
+ GSMDecodeFrameExit
+ GSMFrameDecode
+
+ Date: 08/03/2001
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Add PV coding template. Filled out template sections and
+ reformatted code to follow C coding standard. Removed code that
+ handles SID in GSMFrameDecode.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Updated to more recent PV C coding template.
+ 2. Took out all the tabs in the file and replaced with spaces.
+ 3. Deleted bit_offset from input list of GSMFrameDecode.
+
+ Description: Changing several variables passed into these functions of type
+ Speech_Decode_FrameState to type void.
+
+ Description: Cleaning up brackets and line spacing for statements with
+ brackets as per a review comments.
+
+ Description: Synchronized file with UMTS version 3.2.0. Removed unnecessary
+ include files.
+
+ Description: Removed all references to malloc/free, except for the top-level
+ malloc in GSMInitDecode, and corresponding free in GSMDecodeFrameExit.
+
+ Also, modified function calls throughout to reflect the fact that the members
+ of the structure Decoder_amrState are no longer pointers to be set via
+ malloc, but full-blown structures. (Changes of the type D_plsfState *lsfState
+ to D_plsfState lsfState)
+
+ Description: Created overflow and pass the variable into the decoder.
+
+ Description: Changed inititlaization of the pointer to overflow flag. Removed
+ code related to MOPS counter.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with defined types.
+ Added proper casting (Word32) to some left shifting operations
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the functions that initialize, invoke, reset, and exit
+ the GSM AMR decoder.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+
+#include "sp_dec.h"
+#include "typedef.h"
+#include "cnst.h"
+#include "dec_amr.h"
+#include "pstfilt.h"
+#include "bits2prm.h"
+#include "mode.h"
+#include "post_pro.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: GSMInitDecode
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to an array of pointers to structures of type
+ Speech_Decode_FrameState
+ no_hp_post_MR122 = flag to turn off high-pass post filter for 12.2 kbps
+ mode (Flag)
+ id = pointer to an array whose contents are of type char
+
+ Outputs:
+ decoder_amrState field of the structure pointed to by the pointer pointed
+ to by state is set to NULL
+ post_state field of the structure pointed to by the pointer pointed to
+ by state is set to NULL
+ postHP_state field of the structure pointed to by the pointer pointed to
+ by state is set to NULL
+ no_hp_post_MR122 field of the structure pointed to by the pointer pointed
+ to by state is set to the input no_hp_post_MR122
+
+ Returns:
+ return_value = set to zero, if initialization was successful; -1,
+ otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function allocates memory for filter structure and initializes state
+ memory used by the GSM AMR decoder.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sp_dec.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Note: Original function name of Speech_Decode_Frame_init was changed to
+ GSMInitDecode in the Code section.
+
+int Speech_Decode_Frame_init (Speech_Decode_FrameState **state,
+ char *id)
+{
+ Speech_Decode_FrameState* s;
+
+ if (state == (Speech_Decode_FrameState **) NULL){
+ fprintf(stderr, "Speech_Decode_Frame_init: invalid parameter\n");
+ return -1;
+ }
+ *state = NULL;
+
+ // allocate memory
+ if ((s= (Speech_Decode_FrameState *)
+ malloc(sizeof(Speech_Decode_FrameState))) == NULL) {
+ fprintf(stderr, "Speech_Decode_Frame_init: can not malloc state "
+ "structure\n");
+ return -1;
+ }
+ s->decoder_amrState = NULL;
+ s->post_state = NULL;
+ s->postHP_state = NULL;
+
+ if (Decoder_amr_init(&s->decoder_amrState) ||
+ Post_Filter_init(&s->post_state) ||
+ Post_Process_init(&s->postHP_state) ) {
+ Speech_Decode_Frame_exit(&s);
+ return -1;
+ }
+
+ s->complexityCounter = getCounterId(id);
+
+ Speech_Decode_Frame_reset(s);
+ *state = s;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 GSMInitDecode(void **state_data,
+ Word8 * id)
+{
+ Speech_Decode_FrameState* s;
+ OSCL_UNUSED_ARG(id);
+
+ if (state_data == NULL)
+ {
+ /* fprintf(stderr, "Speech_Decode_Frame_init:
+ invalid parameter\n"); */
+ return (-1);
+ }
+ *state_data = NULL;
+
+ /* allocate memory */
+ if ((s = (Speech_Decode_FrameState *)
+ malloc(sizeof(Speech_Decode_FrameState))) == NULL)
+ {
+ /* fprintf(stderr, "Speech_Decode_Frame_init: can not malloc state "
+ "structure\n"); */
+ return (-1);
+ }
+
+ if (Decoder_amr_init(&s->decoder_amrState)
+ || Post_Process_reset(&s->postHP_state))
+ {
+ Speech_Decode_FrameState *tmp = s;
+ /*
+ * dereferencing type-punned pointer avoid
+ * breaking strict-aliasing rules
+ */
+ void** tempVoid = (void**) tmp;
+ GSMDecodeFrameExit(tempVoid);
+ return (-1);
+ }
+
+
+ Speech_Decode_Frame_reset(s);
+ *state_data = (void *)s;
+
+ return (0);
+}
+
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Speech_Decode_Frame_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to structures of type Speech_Decode_FrameState
+
+ Outputs:
+ None
+
+ Returns:
+ return_value = set to zero if reset was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function resets the state memory used by the GSM AMR decoder.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sp_dec.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Speech_Decode_Frame_reset (Speech_Decode_FrameState *state)
+{
+ if (state == (Speech_Decode_FrameState *) NULL){
+ fprintf(stderr, "Speech_Decode_Frame_reset: invalid parameter\n");
+ return -1;
+ }
+
+ Decoder_amr_reset(state->decoder_amrState, (enum Mode)0);
+ Post_Filter_reset(state->post_state);
+ Post_Process_reset(state->postHP_state);
+
+ state->prev_mode = (enum Mode)0;
+
+ setCounter(state->complexityCounter);
+ Init_WMOPS_counter();
+ setCounter(0); // set counter to global counter
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 Speech_Decode_Frame_reset(void *state_data)
+{
+
+ Speech_Decode_FrameState *state =
+ (Speech_Decode_FrameState *) state_data;
+
+ if (state_data == NULL)
+ {
+ /* fprintf(stderr, "Speech_Decode_Frame_reset:
+ invalid parameter\n"); */
+ return (-1);
+ }
+
+ Decoder_amr_reset(&(state->decoder_amrState), MR475);
+ Post_Filter_reset(&(state->post_state));
+ Post_Process_reset(&(state->postHP_state));
+
+ state->prev_mode = MR475;
+
+ return (0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: GSMDecodeFrameExit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to an array of pointers to structures of type
+ Speech_Decode_FrameState
+
+ Outputs:
+ state contents is set to NULL
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function frees up the memory used for the state memory of the GSM AMR
+ decoder.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sp_dec.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Note: The original function name of Speech_Decode_Frame_exit was changed to
+ GSMDecodeFrameExit in the Code section.
+
+void Speech_Decode_Frame_exit (Speech_Decode_FrameState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ Decoder_amr_exit(&(*state)->decoder_amrState);
+ Post_Filter_exit(&(*state)->post_state);
+ Post_Process_exit(&(*state)->postHP_state);
+
+ setCounter((*state)->complexityCounter);
+ WMOPS_output(0);
+ setCounter(0); // set counter to global counter
+
+ // deallocate memory
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void GSMDecodeFrameExit(void **state_data)
+{
+
+ Speech_Decode_FrameState **state =
+ (Speech_Decode_FrameState **) state_data;
+
+ if (state == NULL || *state == NULL)
+ {
+ return;
+ }
+
+ /* deallocate memory */
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: GSMFrameDecode
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to structures of type Speech_Decode_FrameState
+ mode = GSM AMR codec mode (enum Mode)
+ serial = pointer to the serial bit stream buffer (unsigned char)
+ frame_type = GSM AMR receive frame type (enum RXFrameType)
+ synth = pointer to the output synthesis speech buffer (Word16)
+
+ Outputs:
+ synth contents are truncated to 13 bits if NO13BIT is not defined,
+ otherwise, its contents are left at 16 bits
+
+ Returns:
+ return_value = set to zero (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function is the entry point to the GSM AMR decoder. The following
+ operations are performed on one received frame: First, the codec
+ parameters are parsed from the buffer pointed to by serial according to
+ frame_type. Then the AMR decoder is invoked via a call to Decoder_amr. Post
+ filtering of the decoded data is done via a call to Post_Filter function.
+ Lastly, the decoded data is post-processed via a call to Post_Process
+ function. If NO13BIT is not defined, the contents of the buffer pointed to
+ by synth is truncated to 13 bits. It remains unchanged otherwise.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sp_dec.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Note: The original function name of Speech_Decode_Frame_exit was changed to
+ GSMFrameDecode in the Code section.
+
+int Speech_Decode_Frame (
+ Speech_Decode_FrameState *st, // io: post filter states
+ enum Mode mode, // i : AMR mode
+ Word16 *serial, // i : serial bit stream
+ enum RXFrameType frame_type, // i : Frame type
+ Word16 *synth // o : synthesis speech (postfiltered
+ // output)
+)
+{
+ Word16 parm[MAX_PRM_SIZE + 1]; // Synthesis parameters
+ Word16 Az_dec[AZ_SIZE]; // Decoded Az for post-filter
+ // in 4 subframes
+
+#if !defined(NO13BIT)
+ Word16 i;
+#endif
+
+ setCounter(st->complexityCounter);
+ Reset_WMOPS_counter (); // reset WMOPS counter for the new frame
+
+ // Serial to parameters
+ if ((frame_type == RX_SID_BAD) ||
+ (frame_type == RX_SID_UPDATE)) {
+ // Override mode to MRDTX
+ Bits2prm (MRDTX, serial, parm);
+ } else {
+ Bits2prm (mode, serial, parm);
+ }
+
+ // Synthesis
+ Decoder_amr(st->decoder_amrState, mode, parm, frame_type,
+ synth, Az_dec);
+
+ Post_Filter(st->post_state, mode, synth, Az_dec); // Post-filter
+
+ // post HP filter, and 15->16 bits
+ Post_Process(st->postHP_state, synth, L_FRAME);
+
+#if !defined(NO13BIT)
+ // Truncate to 13 bits
+ for (i = 0; i < L_FRAME; i++)
+ {
+ synth[i] = synth[i] & 0xfff8;
+ }
+#endif
+
+ setCounter(0); // set counter to global counter
+
+ return 0;
+}
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void GSMFrameDecode(
+ Speech_Decode_FrameState *st, /* io: post filter states */
+ enum Mode mode, /* i : AMR mode */
+ Word16 *serial, /* i : serial bit stream */
+ enum RXFrameType frame_type, /* i : Frame type */
+ Word16 *synth) /* o : synthesis speech (postfiltered */
+/* output) */
+
+{
+ Word16 parm[MAX_PRM_SIZE + 1]; /* Synthesis parameters */
+ Word16 Az_dec[AZ_SIZE]; /* Decoded Az for post-filter */
+ /* in 4 subframes */
+ Flag *pOverflow = &(st->decoder_amrState.overflow); /* Overflow flag */
+
+#if !defined(NO13BIT)
+ Word16 i;
+#endif
+
+ /* Serial to parameters */
+ if ((frame_type == RX_SID_BAD) ||
+ (frame_type == RX_SID_UPDATE))
+ {
+ /* Override mode to MRDTX */
+ Bits2prm(MRDTX, serial, parm);
+ }
+ else
+ {
+ Bits2prm(mode, serial, parm);
+ }
+
+ /* Synthesis */
+ Decoder_amr(
+ &(st->decoder_amrState),
+ mode,
+ parm,
+ frame_type,
+ synth,
+ Az_dec);
+
+ /* Post-filter */
+ Post_Filter(
+ &(st->post_state),
+ mode,
+ synth,
+ Az_dec,
+ pOverflow);
+
+ /* post HP filter, and 15->16 bits */
+ Post_Process(
+ &(st->postHP_state),
+ synth,
+ L_FRAME,
+ pOverflow);
+
+#if !defined(NO13BIT)
+ /* Truncate to 13 bits */
+ for (i = 0; i < L_FRAME; i++)
+ {
+ synth[i] = synth[i] & 0xfff8;
+ }
+#endif
+
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/dec/src/sp_dec.h b/media/libstagefright/codecs/amrnb/dec/src/sp_dec.h
new file mode 100644
index 0000000..3150feb
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/sp_dec.h
@@ -0,0 +1,113 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+*****************************************************************************
+*
+* GSM AMR speech codec Version 2.0.0 February 8, 1999
+*
+*****************************************************************************
+*
+* File : sp_dec.h
+* Purpose : Decoding and post filtering of one speech frame.
+*
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+*****************************************************************************
+*/
+#ifndef sp_dec_h
+#define sp_dec_h "$Id $"
+
+/*
+*****************************************************************************
+* INCLUDE FILES
+*****************************************************************************
+*/
+#include "typedef.h"
+#include "cnst.h"
+#include "dec_amr.h"
+#include "pstfilt.h"
+#include "post_pro.h"
+#include "mode.h"
+
+/*
+*****************************************************************************
+* DEFINITION OF DATA TYPES
+*****************************************************************************
+*/
+typedef struct
+{
+ Decoder_amrState decoder_amrState;
+ Post_FilterState post_state;
+ Post_ProcessState postHP_state;
+ enum Mode prev_mode;
+} Speech_Decode_FrameState;
+
+/*
+*****************************************************************************
+* DECLARATION OF PROTOTYPES
+*****************************************************************************
+*/
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+ Word16 GSMInitDecode(void **state_data,
+ Word8 *id);
+ /* initialize one instance of the speech decoder
+ Stores pointer to filter status struct in *st. This pointer has to
+ be passed to Speech_Decode_Frame in each call.
+ returns 0 on success
+ */
+
+ Word16 Speech_Decode_Frame_reset(void *state_data);
+ /* reset speech decoder (i.e. set state memory to zero)
+ returns 0 on success
+ */
+
+ void GSMDecodeFrameExit(void **state_data);
+ /* de-initialize speech decoder (i.e. free status struct)
+ stores NULL in *s
+ */
+
+ void GSMFrameDecode(
+ Speech_Decode_FrameState *st, /* io: post filter states */
+ enum Mode mode, /* i : AMR mode */
+ Word16 *serial, /* i : serial bit stream */
+ enum RXFrameType frame_type, /* i : Frame type */
+ Word16 *synth /* o : synthesis speech (postfiltered */
+ /* output) */
+ );
+ /* return 0 on success
+ */
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/media/libstagefright/codecs/amrnb/dec/src/wmf_to_ets.cpp b/media/libstagefright/codecs/amrnb/dec/src/wmf_to_ets.cpp
new file mode 100644
index 0000000..4dfbb67
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/dec/src/wmf_to_ets.cpp
@@ -0,0 +1,190 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/wmf_to_ets.c
+ Funtions: wmf_to_ets
+
+ Date: 01/21/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changing mode to frame_type_3gpp for DTX support. Modifying for
+ loops for optimized code. Updating as per review comments.
+
+ Description: Changed MRDTX to AMR_SID in the code and added bitreorder_tab.h
+ in the Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "frame_type_3gpp.h"
+#include "wmf_to_ets.h"
+#include "typedef.h"
+#include "bitreorder_tab.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: wmf_to_ets
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ frame_type_3gpp = decoder speech bit rate (enum Frame_Type_3GPP)
+ wmf_input_ptr = pointer to input encoded speech bits in WMF (non-IF2) format
+ (Word8)
+ ets_output_ptr = pointer to output encoded speech bits in ETS format (Word16)
+
+ Outputs:
+ ets_output_ptr = pointer to encoded speech bits in the ETS format (Word16)
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs a transformation on the data buffers. It converts the
+ data format from WMF (non-IF2) (Wireless Multi-media Forum) to ETS (European
+ Telecommunication Standard). WMF format has the encoded speech bits byte
+ aligned with MSB to LSB going left to right. ETS format has the encoded speech
+ bits each separate with only one bit stored in each word.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+AMR Speech Codec Frame Structure", 3GPP TS 26.101 version 4.1.0 Release 4, June 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void wmf_to_ets(
+ enum Frame_Type_3GPP frame_type_3gpp,
+ UWord8 *wmf_input_ptr,
+ Word16 *ets_output_ptr)
+{
+
+ Word16 i;
+
+ /*
+ * The following section of code accesses bits in the WMF method of
+ * bit ordering. Each bit is given its own location in the buffer pointed
+ * to by ets_output_ptr. If the frame_type_3gpp is less than MRDTX then
+ * the elements are reordered within the buffer pointed to by ets_output_ptr.
+ */
+
+ if (frame_type_3gpp < AMR_SID)
+ {
+ /* The table numOfBits[] can be found in bitreorder.c. */
+ for (i = numOfBits[frame_type_3gpp] - 1; i >= 0; i--)
+ {
+ /* The table reorderBits[][] can be found in bitreorder.c. */
+ ets_output_ptr[reorderBits[frame_type_3gpp][i]] =
+ (wmf_input_ptr[i>>3] >> ((~i) & 0x7)) & 0x01;
+ }
+ }
+ else
+ {
+ /* The table numOfBits[] can be found in bitreorder.c. */
+ for (i = numOfBits[frame_type_3gpp] - 1; i >= 0; i--)
+ {
+ ets_output_ptr[i] = (wmf_input_ptr[i>>3] >> ((~i) & 0x7)) & 0x01;
+ }
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.mk b/media/libstagefright/codecs/amrnb/enc/Android.mk
new file mode 100644
index 0000000..28246ae
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/Android.mk
@@ -0,0 +1,102 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ src/amrencode.cpp \
+ src/autocorr.cpp \
+ src/c1035pf.cpp \
+ src/c2_11pf.cpp \
+ src/c2_9pf.cpp \
+ src/c3_14pf.cpp \
+ src/c4_17pf.cpp \
+ src/c8_31pf.cpp \
+ src/calc_cor.cpp \
+ src/calc_en.cpp \
+ src/cbsearch.cpp \
+ src/cl_ltp.cpp \
+ src/cod_amr.cpp \
+ src/convolve.cpp \
+ src/cor_h.cpp \
+ src/cor_h_x.cpp \
+ src/cor_h_x2.cpp \
+ src/corrwght_tab.cpp \
+ src/dtx_enc.cpp \
+ src/enc_lag3.cpp \
+ src/enc_lag6.cpp \
+ src/enc_output_format_tab.cpp \
+ src/ets_to_if2.cpp \
+ src/ets_to_wmf.cpp \
+ src/g_adapt.cpp \
+ src/g_code.cpp \
+ src/g_pitch.cpp \
+ src/gain_q.cpp \
+ src/hp_max.cpp \
+ src/inter_36.cpp \
+ src/inter_36_tab.cpp \
+ src/l_comp.cpp \
+ src/l_extract.cpp \
+ src/l_negate.cpp \
+ src/lag_wind.cpp \
+ src/lag_wind_tab.cpp \
+ src/levinson.cpp \
+ src/lpc.cpp \
+ src/ol_ltp.cpp \
+ src/p_ol_wgh.cpp \
+ src/pitch_fr.cpp \
+ src/pitch_ol.cpp \
+ src/pre_big.cpp \
+ src/pre_proc.cpp \
+ src/prm2bits.cpp \
+ src/q_gain_c.cpp \
+ src/q_gain_p.cpp \
+ src/qgain475.cpp \
+ src/qgain795.cpp \
+ src/qua_gain.cpp \
+ src/s10_8pf.cpp \
+ src/set_sign.cpp \
+ src/sid_sync.cpp \
+ src/sp_enc.cpp \
+ src/spreproc.cpp \
+ src/spstproc.cpp \
+ src/ton_stab.cpp
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/include \
+ $(LOCAL_PATH)/../common/include \
+ $(LOCAL_PATH)/../common
+
+LOCAL_CFLAGS := \
+ -DOSCL_UNUSED_ARG=
+
+LOCAL_MODULE := libstagefright_amrnbenc
+
+include $(BUILD_STATIC_LIBRARY)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ SoftAMRNBEncoder.cpp
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+ frameworks/native/include/media/openmax \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/include \
+ $(LOCAL_PATH)/../common/include \
+ $(LOCAL_PATH)/../common
+
+LOCAL_STATIC_LIBRARIES := \
+ libstagefright_amrnbenc
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright_omx libstagefright_foundation libutils \
+ libstagefright_amrnb_common
+
+LOCAL_MODULE := libstagefright_soft_amrnbenc
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
new file mode 100644
index 0000000..07f8b4f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SoftAMRNBEncoder"
+#include <utils/Log.h>
+
+#include "SoftAMRNBEncoder.h"
+
+#include "gsmamr_enc.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/hexdump.h>
+
+namespace android {
+
+static const int32_t kSampleRate = 8000;
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+SoftAMRNBEncoder::SoftAMRNBEncoder(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SimpleSoftOMXComponent(name, callbacks, appData, component),
+ mEncState(NULL),
+ mSidState(NULL),
+ mBitRate(0),
+ mMode(MR475),
+ mInputSize(0),
+ mInputTimeUs(-1ll),
+ mSawInputEOS(false),
+ mSignalledError(false) {
+ initPorts();
+ CHECK_EQ(initEncoder(), (status_t)OK);
+}
+
+SoftAMRNBEncoder::~SoftAMRNBEncoder() {
+ if (mEncState != NULL) {
+ AMREncodeExit(&mEncState, &mSidState);
+ mEncState = mSidState = NULL;
+ }
+}
+
+void SoftAMRNBEncoder::initPorts() {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+
+ def.nPortIndex = 0;
+ def.eDir = OMX_DirInput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t);
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 1;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ addPort(def);
+
+ def.nPortIndex = 1;
+ def.eDir = OMX_DirOutput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 8192;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 2;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/3gpp");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingAMR;
+
+ addPort(def);
+}
+
+status_t SoftAMRNBEncoder::initEncoder() {
+ if (AMREncodeInit(&mEncState, &mSidState, false /* dtx_enable */) != 0) {
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+OMX_ERRORTYPE SoftAMRNBEncoder::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamAudioPortFormat:
+ {
+ OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+ (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+ if (formatParams->nPortIndex > 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (formatParams->nIndex > 0) {
+ return OMX_ErrorNoMore;
+ }
+
+ formatParams->eEncoding =
+ (formatParams->nPortIndex == 0)
+ ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAMR;
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioAmr:
+ {
+ OMX_AUDIO_PARAM_AMRTYPE *amrParams =
+ (OMX_AUDIO_PARAM_AMRTYPE *)params;
+
+ if (amrParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ amrParams->nChannels = 1;
+ amrParams->nBitRate = mBitRate;
+ amrParams->eAMRBandMode = (OMX_AUDIO_AMRBANDMODETYPE)(mMode + 1);
+ amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
+ amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPcm:
+ {
+ OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eEndian = OMX_EndianBig;
+ pcmParams->bInterleaved = OMX_TRUE;
+ pcmParams->nBitPerSample = 16;
+ pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
+ pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelCF;
+
+ pcmParams->nChannels = 1;
+ pcmParams->nSamplingRate = kSampleRate;
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftAMRNBEncoder::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamStandardComponentRole:
+ {
+ const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+ (const OMX_PARAM_COMPONENTROLETYPE *)params;
+
+ if (strncmp((const char *)roleParams->cRole,
+ "audio_encoder.amrnb",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPortFormat:
+ {
+ const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+ (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+ if (formatParams->nPortIndex > 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (formatParams->nIndex > 0) {
+ return OMX_ErrorNoMore;
+ }
+
+ if ((formatParams->nPortIndex == 0
+ && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
+ || (formatParams->nPortIndex == 1
+ && formatParams->eEncoding != OMX_AUDIO_CodingAMR)) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioAmr:
+ {
+ OMX_AUDIO_PARAM_AMRTYPE *amrParams =
+ (OMX_AUDIO_PARAM_AMRTYPE *)params;
+
+ if (amrParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (amrParams->nChannels != 1
+ || amrParams->eAMRDTXMode != OMX_AUDIO_AMRDTXModeOff
+ || amrParams->eAMRFrameFormat
+ != OMX_AUDIO_AMRFrameFormatFSF
+ || amrParams->eAMRBandMode < OMX_AUDIO_AMRBandModeNB0
+ || amrParams->eAMRBandMode > OMX_AUDIO_AMRBandModeNB7) {
+ return OMX_ErrorUndefined;
+ }
+
+ mBitRate = amrParams->nBitRate;
+ mMode = amrParams->eAMRBandMode - 1;
+
+ amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
+ amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPcm:
+ {
+ OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (pcmParams->nChannels != 1
+ || pcmParams->nSamplingRate != kSampleRate) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+
+ default:
+ return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ }
+}
+
+void SoftAMRNBEncoder::onQueueFilled(OMX_U32 portIndex) {
+ if (mSignalledError) {
+ return;
+ }
+
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+
+ size_t numBytesPerInputFrame = kNumSamplesPerFrame * sizeof(int16_t);
+
+ for (;;) {
+ // We do the following until we run out of buffers.
+
+ while (mInputSize < numBytesPerInputFrame) {
+ // As long as there's still input data to be read we
+ // will drain "kNumSamplesPerFrame" samples
+ // into the "mInputFrame" buffer and then encode those
+ // as a unit into an output buffer.
+
+ if (mSawInputEOS || inQueue.empty()) {
+ return;
+ }
+
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+
+ const void *inData = inHeader->pBuffer + inHeader->nOffset;
+
+ size_t copy = numBytesPerInputFrame - mInputSize;
+ if (copy > inHeader->nFilledLen) {
+ copy = inHeader->nFilledLen;
+ }
+
+ if (mInputSize == 0) {
+ mInputTimeUs = inHeader->nTimeStamp;
+ }
+
+ memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
+ mInputSize += copy;
+
+ inHeader->nOffset += copy;
+ inHeader->nFilledLen -= copy;
+
+ // "Time" on the input buffer has in effect advanced by the
+ // number of audio frames we just advanced nOffset by.
+ inHeader->nTimeStamp +=
+ (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
+
+ if (inHeader->nFilledLen == 0) {
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ ALOGV("saw input EOS");
+ mSawInputEOS = true;
+
+ // Pad any remaining data with zeroes.
+ memset((uint8_t *)mInputFrame + mInputSize,
+ 0,
+ numBytesPerInputFrame - mInputSize);
+
+ mInputSize = numBytesPerInputFrame;
+ }
+
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+
+ inData = NULL;
+ inHeader = NULL;
+ inInfo = NULL;
+ }
+ }
+
+ // At this point we have all the input data necessary to encode
+ // a single frame, all we need is an output buffer to store the result
+ // in.
+
+ if (outQueue.empty()) {
+ return;
+ }
+
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+
+ uint8_t *outPtr = outHeader->pBuffer + outHeader->nOffset;
+ size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
+
+ Frame_Type_3GPP frameType;
+ int res = AMREncode(
+ mEncState, mSidState, (Mode)mMode,
+ mInputFrame, outPtr, &frameType, AMR_TX_WMF);
+
+ CHECK_GE(res, 0);
+ CHECK_LE((size_t)res, outAvailable);
+
+ // Convert header byte from WMF to IETF format.
+ outPtr[0] = ((outPtr[0] << 3) | 4) & 0x7c;
+
+ outHeader->nFilledLen = res;
+ outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
+
+ if (mSawInputEOS) {
+ // We also tag this output buffer with EOS if it corresponds
+ // to the final input buffer.
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+ }
+
+ outHeader->nTimeStamp = mInputTimeUs;
+
+#if 0
+ ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
+ nOutputBytes, mInputTimeUs, outHeader->nFlags);
+
+ hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
+#endif
+
+ outQueue.erase(outQueue.begin());
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+
+ outHeader = NULL;
+ outInfo = NULL;
+
+ mInputSize = 0;
+ }
+}
+
+} // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+ const char *name, const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+ return new android::SoftAMRNBEncoder(name, callbacks, appData, component);
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.h b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.h
new file mode 100644
index 0000000..50178c4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SOFT_AMRNB_ENCODER_H_
+
+#define SOFT_AMRNB_ENCODER_H_
+
+#include "SimpleSoftOMXComponent.h"
+
+namespace android {
+
+struct SoftAMRNBEncoder : public SimpleSoftOMXComponent {
+ SoftAMRNBEncoder(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ virtual ~SoftAMRNBEncoder();
+
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual void onQueueFilled(OMX_U32 portIndex);
+
+private:
+ enum {
+ kNumBuffers = 4,
+ kNumSamplesPerFrame = 160,
+ };
+
+ void *mEncState;
+ void *mSidState;
+
+ OMX_U32 mBitRate;
+ int mMode;
+
+ size_t mInputSize;
+ int16_t mInputFrame[kNumSamplesPerFrame];
+ int64_t mInputTimeUs;
+
+ bool mSawInputEOS;
+ bool mSignalledError;
+
+ void initPorts();
+ status_t initEncoder();
+
+ status_t setAudioParams();
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftAMRNBEncoder);
+};
+
+} // namespace android
+
+#endif // SOFT_AMRNB_ENCODER_H_
diff --git a/media/libstagefright/codecs/amrnb/enc/src/amrencode.cpp b/media/libstagefright/codecs/amrnb/enc/src/amrencode.cpp
new file mode 100644
index 0000000..d07c846
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/amrencode.cpp
@@ -0,0 +1,897 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm-amr/c/src/amrencode.c
+ Functions: AMREncode
+ AMREncodeInit
+ AMREncodeReset
+ AMREncodeExit
+
+ Date: 01/26/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added input_type in the parameter list and updated code to
+ check the type of output formatting to use.
+
+ Description: Corrected typo in Include section.
+
+ Description: Added code to support ETS format.
+
+ Description: Modified file by adding the return of the number of encoder
+ frame bytes.
+
+ Description: Added call to sid_sync function to support TX_NO_DATA case.
+ Added SID type and mode info to ets_output_bfr for ETS SID
+ frames. Created AMREncodeInit, AMREncodeReset, and AMREncodeExit
+ functions.
+
+ Description: Modified design of handling of ETS outputs such that the ETS
+ testvectors could be compared directly to the output of this
+ function.
+
+ Description: Added conditional compile around calls to AMR Encoder interface
+ functions to allow amrencode.c to be used in the ETS reference
+ console.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the functions required to initialize, reset, exit, and
+ invoke the ETS 3GPP GSM AMR encoder.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "cnst.h"
+#include "mode.h"
+#include "frame_type_3gpp.h"
+#include "typedef.h"
+
+#include "amrencode.h"
+#include "ets_to_if2.h"
+#include "ets_to_wmf.h"
+#include "sid_sync.h"
+#include "sp_enc.h"
+
+/*----------------------------------------------------------------------------
+; MACROS [optional]
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES [optional]
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: AMREncodeInit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pEncStructure = pointer containing the pointer to a structure used by
+ the encoder (void)
+ pSidSyncStructure = pointer containing the pointer to a structure used for
+ SID synchronization (void)
+ dtx_enable = flag to turn off or turn on DTX (Flag)
+
+ Outputs:
+ None
+
+ Returns:
+ init_status = 0, if initialization was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ speech_encoder_state = pointer to encoder frame structure
+ (Speech_Encode_FrameState)
+ sid_state = pointer to SID sync structure (sid_syncState)
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function initializes the GSM AMR Encoder library by calling
+ GSMInitEncode and sid_sync_init. If initialization was successful,
+ init_status is set to zero, otherwise, it is set to -1.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ // Initialize GSM AMR Encoder
+ CALL GSMInitEncode(state_data = &pEncStructure,
+ dtx = dtx_enable,
+ id = char_id )
+ MODIFYING(nothing)
+ RETURNING(return_value = enc_init_status)
+
+ // Initialize SID synchronization
+ CALL sid_sync_init(state = &pSidSyncStructure)
+ MODIFYING(nothing)
+ RETURNING(return_value = sid_sync_init_status)
+
+ IF ((enc_init_status != 0) || (sid_sync_init != 0))
+ THEN
+ init_status = -1
+
+ ENDIF
+
+ MODIFY(nothing)
+ RETURN(init_status)
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 AMREncodeInit(
+ void **pEncStructure,
+ void **pSidSyncStructure,
+ Flag dtx_enable)
+{
+ Word16 enc_init_status = 0;
+ Word16 sid_sync_init_status = 0;
+ Word16 init_status = 0;
+
+ /* Initialize GSM AMR Encoder */
+#ifdef CONSOLE_ENCODER_REF
+ /* Change to original ETS input types */
+ Speech_Encode_FrameState **speech_encode_frame =
+ (Speech_Encode_FrameState **)(pEncStructure);
+
+ sid_syncState **sid_sync_state = (sid_syncState **)(pSidSyncStructure);
+
+ /* Use ETS version of sp_enc.c */
+ enc_init_status = Speech_Encode_Frame_init(speech_encode_frame,
+ dtx_enable,
+ (Word8*)"encoder");
+
+ /* Initialize SID synchronization */
+ sid_sync_init_status = sid_sync_init(sid_sync_state);
+
+#else
+ /* Use PV version of sp_enc.c */
+ enc_init_status = GSMInitEncode(pEncStructure,
+ dtx_enable,
+ (Word8*)"encoder");
+
+ /* Initialize SID synchronization */
+ sid_sync_init_status = sid_sync_init(pSidSyncStructure);
+
+
+#endif
+
+ if ((enc_init_status != 0) || (sid_sync_init_status != 0))
+ {
+ init_status = -1;
+ }
+
+ return(init_status);
+}
+
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: AMREncodeReset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pEncStructure = pointer to a structure used by the encoder (void)
+ pSidSyncStructure = pointer to a structure used for SID synchronization
+ (void)
+
+ Outputs:
+ None
+
+ Returns:
+ reset_status = 0, if reset was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ speech_encoder_state = pointer to encoder frame structure
+ (Speech_Encode_FrameState)
+ sid_state = pointer to SID sync structure (sid_syncState)
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function resets the state memory used by the Encoder and SID sync
+ function. If reset was successful, reset_status is set to zero, otherwise,
+ it is set to -1.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ // Reset GSM AMR Encoder
+ CALL Speech_Encode_Frame_reset(state_data = pEncStructure)
+ MODIFYING(nothing)
+ RETURNING(return_value = enc_reset_status)
+
+ // Reset SID synchronization
+ CALL sid_sync_reset(state = pSidSyncStructure)
+ MODIFYING(nothing)
+ RETURNING(return_value = sid_sync_reset_status)
+
+ IF ((enc_reset_status != 0) || (sid_sync_reset_status != 0))
+ THEN
+ reset_status = -1
+
+ ENDIF
+
+ MODIFY(nothing)
+ RETURN(reset_status)
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 AMREncodeReset(
+ void *pEncStructure,
+ void *pSidSyncStructure)
+{
+ Word16 enc_reset_status = 0;
+ Word16 sid_sync_reset_status = 0;
+ Word16 reset_status = 0;
+
+ /* Reset GSM AMR Encoder */
+ enc_reset_status = Speech_Encode_Frame_reset(pEncStructure);
+
+
+ /* Reset SID synchronization */
+ sid_sync_reset_status = sid_sync_reset(pSidSyncStructure);
+
+ if ((enc_reset_status != 0) || (sid_sync_reset_status != 0))
+ {
+ reset_status = -1;
+ }
+
+ return(reset_status);
+}
+
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: AMREncodeExit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pEncStructure = pointer containing the pointer to a structure used by
+ the encoder (void)
+ pSidSyncStructure = pointer containing the pointer to a structure used for
+ SID synchronization (void)
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ speech_encoder_state = pointer to encoder frame structure
+ (Speech_Encode_FrameState)
+ sid_state = pointer to SID sync structure (sid_syncState)
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function frees up the state memory used by the Encoder and SID
+ synchronization function.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ // Exit GSM AMR Encoder
+ CALL GSMEncodeFrameExit(state_data = &pEncStructure)
+ MODIFYING(nothing)
+ RETURNING(nothing)
+
+ // Exit SID synchronization
+ CALL sid_sync_exit(state = &pSidSyncStructure)
+ MODIFYING(nothing)
+ RETURNING(nothing)
+
+ MODIFY(nothing)
+ RETURN(nothing)
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void AMREncodeExit(
+ void **pEncStructure,
+ void **pSidSyncStructure)
+{
+ /* Exit GSM AMR Encoder */
+
+#ifdef CONSOLE_ENCODER_REF
+ /* Change to original ETS input types */
+ Speech_Encode_FrameState ** speech_encode_frame =
+ (Speech_Encode_FrameState **)(pEncStructure);
+
+ sid_syncState ** sid_sync_state = (sid_syncState **)(pSidSyncStructure);
+
+ /* Use ETS version of sp_enc.c */
+ Speech_Encode_Frame_exit(speech_encode_frame);
+
+
+ /* Exit SID synchronization */
+ sid_sync_exit(sid_sync_state);
+
+#else
+
+ /* Use PV version of sp_enc.c */
+ GSMEncodeFrameExit(pEncStructure);
+
+ /* Exit SID synchronization */
+ sid_sync_exit(pSidSyncStructure);
+
+#endif
+
+ return;
+}
+
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: AMREncode
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pEncState = pointer to encoder state structure (void)
+ pSidSyncState = pointer to SID sync state structure (void)
+ mode = codec mode (enum Mode)
+ pEncInput = pointer to the input speech samples (Word16)
+ pEncOutput = pointer to the encoded bit stream (unsigned char)
+ p3gpp_frame_type = pointer to the 3GPP frame type (enum Frame_Type_3GPP)
+ output_format = output format type (Word16); valid values are AMR_WMF,
+ AMR_IF2, and AMR_ETS
+
+ Outputs:
+ pEncOutput buffer contains to the newly encoded bit stream
+ p3gpp_frame_type store contains the new 3GPP frame type
+
+ Returns:
+ num_enc_bytes = number of encoded bytes for a particular
+ mode or -1, if an error occurred (int)
+
+ Global Variables Used:
+ WmfEncBytesPerFrame = table containing the number of encoder frame
+ data bytes per codec mode for WMF output
+ format (const int)
+ If2EncBytesPerFrame = table containing the number of encoder frame
+ data bytes per codec mode for IF2 output
+ format (const int)
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function is the top-level entry point to the GSM AMR Encoder library.
+
+ The following describes the encoding process for WMF or IF2 formatted output
+ data. This functions calls GSMEncodeFrame to encode one frame's worth of
+ input speech samples, and returns the newly encoded bit stream in the buffer
+ pointed to by pEncOutput.Then the function sid_sync is called to determine
+ the transmit frame type. If the transmit frame type is TX_SPEECH_GOOD or
+ TX_SID_FIRST or TX_SID_UPDATE, p3gpp_frame_type will be set to the encoder
+ used mode. For SID frames, the SID type information and mode information are
+ added to the encoded parameter bitstream according to the SID frame format
+ described in [1]. If the transmit frame type is TX_NO_DATA, the store
+ pointed to by p3gpp_frame_type will be set to NO_DATA. Then the output
+ format type (output_format) will be checked to determine the format of the
+ encoded data.
+
+ If output_format is AMR_TX_WMF, the function ets_to_wmf will be called to
+ convert from ETS format (1 bit/word, where 1 word = 16 bits, information in
+ least significant bit) to WMF (aka, non-IF2). The WMF format stores the data
+ in octets. The least significant 4 bits of the first octet contains the 3GPP
+ frame type information and the most significant 4 bits are zeroed out. The
+ succeeding octets contain the packed encoded speech bits. The total number of
+ WMF bytes encoded is obtained from WmfEncBytesPerFrame table and returned via
+ num_enc_bytes.
+
+ If output_format is AMR_TX_IF2, the function if2_to_ets will be called to
+ convert from ETS format to IF2 [1]. The IF2 format stores the data in octets.
+ The least significant nibble of the first octet contains the 3GPP frame type
+ and the most significant nibble contains the first 4 encoded speech bits. The
+ suceeding octets contain the packed encoded speech bits. The total number of
+ IF2 bytes encoded is obtained from If2EncBytesPerFrame table and returned via
+ num_enc_bytes.
+
+ If output_format is AMR_TX_ETS, GSMFrameEncode is called to generate the
+ encoded speech parameters, then, sid_sync is called to determine the transmit
+ frame type. If the transmit frame type is not TX_NO_DATA, then the transmit
+ frame type information is saved in the first location of the ets_output_bfr,
+ followed by the encoded speech parameters. The codec mode information is
+ stored immediately after the MAX_SERIAL_SIZE encoded speech parameters. If
+ the transmit frame type is TX_NO_DATA, the transmit frame type, encoded
+ speech parameters, and codec mode are stored in the same order as before
+ in ets_output_bfr. However, for the no data case, the codec mode is set to
+ -1.
+
+ After all the required information is generated, the 16-bit data generated
+ by the Encoder (in ets_output_bfr) is copied to the buffer pointed to by
+ pEncOutput in the little endian configuration, i.e., least significant byte,
+ followed by most significant byte. The num_enc_bytes is set to
+ 2*(MAX_SERIAL_SIZE+2).
+
+ If output_format is invalid, this function flags the error and sets
+ num_enc_bytes to -1.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] "AMR Speech Codec Frame Structure", 3GPP TS 26.101 version 4.1.0
+ Release 4, June 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ IF ((output_format == AMR_TX_WMF) | (output_format == AMR_TX_IF2))
+ THEN
+ // Encode one speech frame (20 ms)
+ CALL GSMEncodeFrame( state_data = pEncState,
+ mode = mode,
+ new_speech = pEncInput,
+ serial = &ets_output_bfr[0],
+ usedMode = &usedMode )
+ MODIFYING(nothing)
+ RETURNING(return_value = 0)
+
+ // Determine transmit frame type
+ CALL sid_sync(st = pSidSyncState,
+ mode = usedMode
+ tx_frame_type = &tx_frame_type)
+ MODIFYING(nothing)
+ RETURNING(nothing)
+
+ IF (tx_frame_type != TX_NO_DATA)
+ THEN
+ // There is data to transmit
+ *p3gpp_frame_type = (enum Frame_Type_3GPP) usedMode
+
+ // Add SID type and mode info for SID frames
+ IF (*p3gpp_frame_type == AMR_SID)
+ THEN
+ // Add SID type to encoder output buffer
+ IF (tx_frame_type == TX_SID_FIRST)
+ THEN
+ ets_output_bfr[AMRSID_TXTYPE_BIT_OFFSET] &= 0x7f
+
+ ELSEIF (tx_frame_type == TX_SID_UPDATE )
+ THEN
+ ets_output_bfr[AMRSID_TXTYPE_BIT_OFFSET] |= 0x80
+
+ ENDIF
+
+ // Add mode information bits
+ FOR i = 0 TO NUM_AMRSID_TXMODE_BITS-1
+
+ ets_output_bfr[AMRSID_TXMODE_BIT_OFFSET+i] = (mode>>i)&&0x0001
+
+ ENDFOR
+
+ ENDIF
+
+ ELSE
+ // There is no data to transmit
+ *p3gpp_frame_type = NO_DATA
+
+ ENDIF
+
+ // Determine the output format to use
+ IF (output_format == AMR_TX_WMF)
+ THEN
+ // Change output data format to WMF
+ CALL ets_to_wmf( frame_type_3gpp = *p3gpp_frame_type,
+ ets_input_ptr = &ets_output_bfr[0],
+ wmf_output_ptr = pEncOutput )
+ MODIFYING(nothing)
+ RETURNING(nothing)
+
+ // Set up the number of encoded WMF bytes
+ num_enc_bytes = WmfEncBytesPerFrame[(int) *p3gpp_frame_type]
+
+ ELSEIF (output_format == AMR_TX_IF2)
+ THEN
+ // Change output data format to IF2
+ CALL ets_to_if2( frame_type_3gpp = *p3gpp_frame_type,
+ ets_input_ptr = &ets_output_bfr[0],
+ if2_output_ptr = pEncOutput )
+ MODIFYING(nothing)
+ RETURNING(nothing)
+
+ // Set up the number of encoded IF2 bytes
+ num_enc_bytes = If2EncBytesPerFrame[(int) *p3gpp_frame_type]
+
+ ENDIF
+
+ ELSEIF (output_format = AMR_TX_ETS)
+ THEN
+ // Encode one speech frame (20 ms)
+ CALL GSMEncodeFrame( state_data = pEncState,
+ mode = mode,
+ new_speech = pEncInput,
+ serial = &ets_output_bfr[1],
+ usedMode = &usedMode )
+ MODIFYING(nothing)
+ RETURNING(return_value = 0)
+
+ // Save used mode
+ *p3gpp_frame_type = (enum Frame_Type_3GPP) usedMode
+
+ // Determine transmit frame type
+ CALL sid_sync(st = pSidSyncState,
+ mode = usedMode
+ tx_frame_type = &tx_frame_type)
+ MODIFYING(nothing)
+ RETURNING(nothing)
+
+ // Put TX frame type in output buffer
+ ets_output_bfr[0] = tx_frame_type
+
+ // Put mode information after the encoded speech parameters
+ IF (tx_frame_type != TX_NO_DATA)
+ THEN
+ ets_output_bfr[MAX_SERIAL_SIZE+1] = mode
+
+ ELSE
+ ets_output_bfr[MAX_SERIAL_SIZE+1] = -1
+
+ ENDIF
+
+ // Copy output of encoder to pEncOutput buffer
+ ets_output_ptr = (unsigned char *) &ets_output_bfr[0]
+
+ // Copy 16-bit data in 8-bit chunks using Little Endian configuration
+ FOR i = 0 TO (2*(MAX_SERIAL_SIZE+6))-1
+
+ *(pEncOutput+i) = *ets_output_ptr
+ ets_output_ptr = ets_output_ptr + 1
+
+ ENDFOR
+
+ // Set up number of encoded bytes
+ num_enc_bytes = 2*(MAX_SERIAL_SIZE+6)
+
+ ELSE
+ // Invalid output_format, set up error code
+ num_enc_bytes = -1
+
+ ENDIF
+
+ MODIFY (nothing)
+ RETURN (num_enc_bytes)
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 AMREncode(
+ void *pEncState,
+ void *pSidSyncState,
+ enum Mode mode,
+ Word16 *pEncInput,
+ UWord8 *pEncOutput,
+ enum Frame_Type_3GPP *p3gpp_frame_type,
+ Word16 output_format
+)
+{
+ Word16 ets_output_bfr[MAX_SERIAL_SIZE+2];
+ UWord8 *ets_output_ptr;
+ Word16 num_enc_bytes = -1;
+ Word16 i;
+ enum TXFrameType tx_frame_type;
+ enum Mode usedMode = MR475;
+
+ /* Encode WMF or IF2 frames */
+ if ((output_format == AMR_TX_WMF) | (output_format == AMR_TX_IF2))
+ {
+ /* Encode one speech frame (20 ms) */
+
+#ifndef CONSOLE_ENCODER_REF
+
+ /* Use PV version of sp_enc.c */
+ GSMEncodeFrame(pEncState, mode, pEncInput, ets_output_bfr, &usedMode);
+
+#else
+ /* Use ETS version of sp_enc.c */
+ Speech_Encode_Frame(pEncState, mode, pEncInput, ets_output_bfr, &usedMode);
+
+#endif
+
+ /* Determine transmit frame type */
+ sid_sync(pSidSyncState, usedMode, &tx_frame_type);
+
+ if (tx_frame_type != TX_NO_DATA)
+ {
+ /* There is data to transmit */
+ *p3gpp_frame_type = (enum Frame_Type_3GPP) usedMode;
+
+ /* Add SID type and mode info for SID frames */
+ if (*p3gpp_frame_type == AMR_SID)
+ {
+ /* Add SID type to encoder output buffer */
+ if (tx_frame_type == TX_SID_FIRST)
+ {
+ ets_output_bfr[AMRSID_TXTYPE_BIT_OFFSET] &= 0x0000;
+ }
+ else if (tx_frame_type == TX_SID_UPDATE)
+ {
+ ets_output_bfr[AMRSID_TXTYPE_BIT_OFFSET] |= 0x0001;
+ }
+
+ /* Add mode information bits */
+ for (i = 0; i < NUM_AMRSID_TXMODE_BITS; i++)
+ {
+ ets_output_bfr[AMRSID_TXMODE_BIT_OFFSET+i] =
+ (mode >> i) & 0x0001;
+ }
+ }
+ }
+ else
+ {
+ /* This is no data to transmit */
+ *p3gpp_frame_type = (enum Frame_Type_3GPP)AMR_NO_DATA;
+ }
+
+ /* At this point, output format is ETS */
+ /* Determine the output format to use */
+ if (output_format == AMR_TX_WMF)
+ {
+ /* Change output data format to WMF */
+ ets_to_wmf(*p3gpp_frame_type, ets_output_bfr, pEncOutput);
+
+ /* Set up the number of encoded WMF bytes */
+ num_enc_bytes = WmfEncBytesPerFrame[(Word16) *p3gpp_frame_type];
+
+ }
+ else if (output_format == AMR_TX_IF2)
+ {
+ /* Change output data format to IF2 */
+ ets_to_if2(*p3gpp_frame_type, ets_output_bfr, pEncOutput);
+
+ /* Set up the number of encoded IF2 bytes */
+ num_enc_bytes = If2EncBytesPerFrame[(Word16) *p3gpp_frame_type];
+
+ }
+ }
+
+ /* Encode ETS frames */
+ else if (output_format == AMR_TX_ETS)
+ {
+ /* Encode one speech frame (20 ms) */
+
+#ifndef CONSOLE_ENCODER_REF
+
+ /* Use PV version of sp_enc.c */
+ GSMEncodeFrame(pEncState, mode, pEncInput, &ets_output_bfr[1], &usedMode);
+
+#else
+ /* Use ETS version of sp_enc.c */
+ Speech_Encode_Frame(pEncState, mode, pEncInput, &ets_output_bfr[1], &usedMode);
+
+#endif
+
+ /* Save used mode */
+ *p3gpp_frame_type = (enum Frame_Type_3GPP) usedMode;
+
+ /* Determine transmit frame type */
+ sid_sync(pSidSyncState, usedMode, &tx_frame_type);
+
+ /* Put TX frame type in output buffer */
+ ets_output_bfr[0] = tx_frame_type;
+
+ /* Put mode information after the encoded speech parameters */
+ if (tx_frame_type != TX_NO_DATA)
+ {
+ ets_output_bfr[1+MAX_SERIAL_SIZE] = (Word16) mode;
+ }
+ else
+ {
+ ets_output_bfr[1+MAX_SERIAL_SIZE] = -1;
+ }
+
+ /* Copy output of encoder to pEncOutput buffer */
+ ets_output_ptr = (UWord8 *) & ets_output_bfr[0];
+
+ /* Copy 16-bit data in 8-bit chunks */
+ /* using Little Endian configuration */
+ for (i = 0; i < 2*(MAX_SERIAL_SIZE + 2); i++)
+ {
+ *(pEncOutput + i) = *ets_output_ptr;
+ ets_output_ptr += 1;
+ }
+
+ /* Set up the number of encoded bytes */
+ num_enc_bytes = 2 * (MAX_SERIAL_SIZE + 2);
+
+ }
+
+ /* Invalid frame format */
+ else
+ {
+ /* Invalid output format, set up error code */
+ num_enc_bytes = -1;
+ }
+
+ return(num_enc_bytes);
+}
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/amrencode.h b/media/libstagefright/codecs/amrnb/enc/src/amrencode.h
new file mode 100644
index 0000000..1e85db1
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/amrencode.h
@@ -0,0 +1,156 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm-amr/c/include/amrencode.h
+
+ Date: 02/01/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Removed hard tabs from file.
+
+ Description: Added #define for WMF and IF2, and updated function prototype.
+
+ Description: Renamed WMF to AMR_WMF, IF2 to AMR_IF2, and added AMR_ETS.
+
+ Description: Changed output_type to output_format.
+
+ Description: Added external reference to WmfEncBytesPerFrame and
+ If2EncBytesPerFrame tables.
+
+ Description: Updated function prototype for AMREncode(). Added function
+ prototype for AMREncodeInit, AMREncodeReset, and AMREncodeExit.
+ Added #defines for TX SID frame formatting.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains the function prototype of AMREncode.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _AMRENCODE_H_
+#define _AMRENCODE_H_
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "frame_type_3gpp.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+#define NUM_AMRSID_TXMODE_BITS 3
+#define AMRSID_TXMODE_BIT_OFFSET 36
+#define AMRSID_TXTYPE_BIT_OFFSET 35
+
+ /* Output format types */
+#define AMR_TX_WMF 0
+#define AMR_TX_IF2 1
+#define AMR_TX_ETS 2
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+ extern const Word16 WmfEncBytesPerFrame[];
+ extern const Word16 If2EncBytesPerFrame[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ Word16 AMREncodeInit(
+ void **pEncStructure,
+ void **pSidSyncStructure,
+ Flag dtx_enable);
+
+ Word16 AMREncodeReset(
+ void *pEncStructure,
+ void *pSidSyncStructure);
+
+ void AMREncodeExit(
+ void **pEncStructure,
+ void **pSidSyncStructure);
+
+ Word16 AMREncode(
+ void *pEncState,
+ void *pSidSyncState,
+ enum Mode mode,
+ Word16 *pEncInput,
+ UWord8 *pEncOutput,
+ enum Frame_Type_3GPP *p3gpp_frame_type,
+ Word16 output_format
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AMRENCODE_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/autocorr.cpp b/media/libstagefright/codecs/amrnb/enc/src/autocorr.cpp
new file mode 100644
index 0000000..0d3acac
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/autocorr.cpp
@@ -0,0 +1,459 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/autocorr.c
+
+ Date: 05/15/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Put into template...starting optimization.
+
+ Description: Removed call to mult_r routine.
+
+ Description: Modified Input/Output Definitions section to comply with the
+ current template. Fixed tabs.
+
+ Description: Updated Input/Output definitions by making them more
+ descriptive.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Added full pathname of file.
+ 2. Fixed typecasting issue with TI compiler.
+ 3. Modified FOR loops to count down.
+ 4. Added comment to the code.
+
+ Description: Removed extern to global paramter (Flag Overflow) and replaced
+ by passing in a pointer to Overflow. Also, made several small changes to
+ bring code more in line with PV Standards.
+
+ Description:
+ 1. Added pointer to avoid adding offsets in every pass
+ 2. Break last loop in two nested loop to speed up processing
+ 3. Removed extra check for overflow by doing scaling right
+ after overflow is detected.
+ 4. Eliminated calls to basic operations (like extract) not
+ needed because of the nature of the number (all bounded)
+
+ Description:
+ 1. Fixed for:
+ overflow check was looking for positive number before a left
+ shift. When numbers were big enough, positive numbers after
+ shifted became negative, causing a 1/0 division).
+ Fixed so now it checks for numbers lesser than 0x40000000
+ before the left shift
+
+ Description:
+ 1.Modified check for saturation to match bit exact test.
+ Also, when saturation is reached, a faster loop is used
+ (with no energy accumulation) to speed up processing
+
+
+ Description:
+ 1.Added pointer initialization to for loop when saturation
+ is found. This because some compiler ( like Vcpp in release
+ mode) when optimizing code, may remove pointer information
+ once the loop is broken.
+
+ Description: Added casting to eliminate warnings
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Using inlines from fxp_arithmetic.h.
+
+ Description: Replacing fxp_arithmetic.h with basic_op.h.
+
+ Description:
+
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "autocorr.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Autocorr
+----------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ x = buffer of input signals of type Word16
+ m = LPC order of type Word16
+ wind = buffer of window signals of type Word16
+ r_h = buffer containing the high word of the autocorrelation values
+ of type Word16
+ r_l = buffer containing the low word of the autocorrelation values
+ of type Word16
+
+ pOverflow = pointer to variable of type Flag *, which indicates if
+ overflow occurs.
+
+ Outputs:
+ r_h buffer contains the high word of the new autocorrelation values
+ r_l buffer contains the low word of the new autocorrelation values
+ pOverflow -> 1 if overflow occurs.
+
+ Returns:
+ norm = normalized autocorrelation at lag zero of type Word16
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function windows the input signal with the provided window
+ then calculates the autocorrelation values for lags of 0,1,...m,
+ where m is the passed in LPC order.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ autocorr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 Autocorr (
+ Word16 x[], // (i) : Input signal (L_WINDOW)
+ Word16 m, // (i) : LPC order
+ Word16 r_h[], // (o) : Autocorrelations (msb)
+ Word16 r_l[], // (o) : Autocorrelations (lsb)
+ const Word16 wind[] // (i) : window for LPC analysis (L_WINDOW)
+)
+{
+ Word16 i, j, norm;
+ Word16 y[L_WINDOW];
+ Word32 sum;
+ Word16 overfl, overfl_shft;
+
+ // Windowing of signal
+
+ for (i = 0; i < L_WINDOW; i++)
+ {
+ y[i] = mult_r (x[i], wind[i]);
+ }
+
+ // Compute r[0] and test for overflow
+
+ overfl_shft = 0;
+
+ do
+ {
+ overfl = 0;
+ sum = 0L;
+
+ for (i = 0; i < L_WINDOW; i++)
+ {
+ sum = L_mac (sum, y[i], y[i]);
+ }
+
+ // If overflow divide y[] by 4
+
+ if (L_sub (sum, MAX_32) == 0L)
+ {
+ overfl_shft = add (overfl_shft, 4);
+ overfl = 1; // Set the overflow flag
+
+ for (i = 0; i < L_WINDOW; i++)
+ {
+ y[i] = shr (y[i], 2);
+ }
+ }
+ }
+ while (overfl != 0);
+
+ sum = L_add (sum, 1L); // Avoid the case of all zeros
+
+ // Normalization of r[0]
+
+ norm = norm_l (sum);
+ sum = L_shl (sum, norm);
+ L_Extract (sum, &r_h[0], &r_l[0]); // Put in DPF format (see oper_32b)
+
+ // r[1] to r[m]
+
+ for (i = 1; i <= m; i++)
+ {
+ sum = 0;
+
+ for (j = 0; j < L_WINDOW - i; j++)
+ {
+ sum = L_mac (sum, y[j], y[j + i]);
+ }
+
+ sum = L_shl (sum, norm);
+ L_Extract (sum, &r_h[i], &r_l[i]);
+ }
+
+ norm = sub (norm, overfl_shft);
+
+ return norm;
+}
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Autocorr(
+ Word16 x[], /* (i) : Input signal (L_WINDOW) */
+ Word16 m, /* (i) : LPC order */
+ Word16 r_h[], /* (o) : Autocorrelations (msb) */
+ Word16 r_l[], /* (o) : Autocorrelations (lsb) */
+ const Word16 wind[], /* (i) : window for LPC analysis (L_WINDOW) */
+ Flag *pOverflow /* (o) : indicates overflow */
+)
+{
+ register Word16 i;
+ register Word16 j;
+ register Word16 norm;
+
+ Word16 y[L_WINDOW];
+ Word32 sum;
+ Word16 overfl_shft;
+
+
+ /* Added for optimization */
+
+
+ Word16 temp;
+ Word16 *p_x;
+ Word16 *p_y;
+ Word16 *p_y_1;
+ Word16 *p_y_ref;
+ Word16 *p_rh;
+ Word16 *p_rl;
+ const Word16 *p_wind;
+ p_y = y;
+ p_x = x;
+ p_wind = wind;
+ /*
+ * Windowing of the signal
+ */
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ sum = 0L;
+ j = 0;
+
+ for (i = L_WINDOW; i != 0; i--)
+ {
+ temp = (amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_wind++), 0x04000)) >> 15;
+ *(p_y++) = temp;
+
+ sum += ((Word32)temp * temp) << 1;
+ if (sum < 0)
+ {
+ /*
+ * if oveflow exist, then stop accumulation
+ */
+ j = 1;
+ break;
+ }
+
+ }
+ /*
+ * if oveflow existed, complete windowing operation
+ * without computing energy
+ */
+
+ if (j)
+ {
+ p_y = &y[L_WINDOW-i];
+ p_x = &x[L_WINDOW-i];
+ p_wind = &wind[L_WINDOW-i];
+
+ for (; i != 0; i--)
+ {
+ temp = (amrnb_fxp_mac_16_by_16bb((Word32) * (p_x++), (Word32) * (p_wind++), 0x04000)) >> 15;
+ *(p_y++) = temp;
+ }
+ }
+
+
+ /*
+ * Compute r[0] and test for overflow
+ */
+
+ overfl_shft = 0;
+
+ /*
+ * scale down by 1/4 only when needed
+ */
+ while (j == 1)
+ {
+ /* If overflow divide y[] by 4 */
+ /* FYI: For better resolution, we could */
+ /* divide y[] by 2 */
+ overfl_shft += 4;
+ p_y = &y[0];
+ sum = 0L;
+
+ for (i = (L_WINDOW >> 1); i != 0 ; i--)
+ {
+ temp = *p_y >> 2;
+ *(p_y++) = temp;
+ sum += ((Word32)temp * temp) << 1;
+ temp = *p_y >> 2;
+ *(p_y++) = temp;
+ sum += ((Word32)temp * temp) << 1;
+ }
+ if (sum > 0)
+ {
+ j = 0;
+ }
+
+ }
+
+ sum += 1L; /* Avoid the case of all zeros */
+
+ /* Normalization of r[0] */
+
+ norm = norm_l(sum);
+
+ sum <<= norm;
+
+ /* Put in DPF format (see oper_32b) */
+ r_h[0] = (Word16)(sum >> 16);
+ r_l[0] = (Word16)((sum >> 1) - ((Word32)(r_h[0]) << 15));
+
+ /* r[1] to r[m] */
+
+ p_y_ref = &y[L_WINDOW - 1 ];
+ p_rh = &r_h[m];
+ p_rl = &r_l[m];
+
+ for (i = m; i > 0; i--)
+ {
+ sum = 0;
+
+ p_y = &y[L_WINDOW - i - 1];
+ p_y_1 = p_y_ref;
+
+ for (j = (L_WINDOW - i - 1) >> 1; j != 0; j--)
+ {
+ sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
+ sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
+ }
+
+ sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
+
+ if (((L_WINDOW - i - 1) & 1))
+ {
+ sum = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y--), (Word32) * (p_y_1--), sum);
+ }
+
+ sum <<= (norm + 1);
+
+ *(p_rh) = (Word16)(sum >> 16);
+ *(p_rl--) = (Word16)((sum >> 1) - ((Word32) * (p_rh--) << 15));
+
+ }
+
+ norm -= overfl_shft;
+
+ return (norm);
+
+} /* Autocorr */
diff --git a/media/libstagefright/codecs/amrnb/enc/src/autocorr.h b/media/libstagefright/codecs/amrnb/enc/src/autocorr.h
new file mode 100644
index 0000000..6045d6e
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/autocorr.h
@@ -0,0 +1,118 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/autocorr.h
+
+ Date: 01/23/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the autocorr function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef autocorr_h
+#define autocorr_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 Autocorr(
+ Word16 x[], /* (i) : Input signal (L_WINDOW) */
+ Word16 m, /* (i) : LPC order */
+ Word16 r_h[], /* (o) : Autocorrelations (msb) */
+ Word16 r_l[], /* (o) : Autocorrelations (lsb) */
+ const Word16 wind[], /* (i) : window for LPC analysis (L_WINDOW) */
+ Flag *pOverflow /* (o) : indicates overflow */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _AUTO_CORR_H_ */
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c1035pf.cpp b/media/libstagefright/codecs/amrnb/enc/src/c1035pf.cpp
new file mode 100644
index 0000000..d95995c
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/c1035pf.cpp
@@ -0,0 +1,676 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/c1035pf.c
+ Functions: q_p
+ build_code
+ code_10i40_35bits
+
+
+ Date: 09/28/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template. Cleaned up code. Passing in a pointer to
+ overflow flag for build_code() and code_10i40_35bits() functions.
+ Removed unnecessary header files.
+
+ Description:
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated math operations that unnecessary checked for
+ saturation
+ 4. Replaced for-loops with memset()
+
+ Description: Changed function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the function that searches a 35 bit algebraic codebook
+ containing 10 pulses in a frame of 40 samples.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <string.h>
+
+#include "c1035pf.h"
+#include "cnst.h"
+#include "basic_op.h"
+#include "inv_sqrt.h"
+#include "set_sign.h"
+#include "cor_h.h"
+#include "cor_h_x.h"
+#include "s10_8pf.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+#define NB_PULSE 10
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: q_p
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pShift_reg = pointer to Old CN generator shift register state (Word32)
+ no_bits = Number of bits (Word16)
+
+ Outputs:
+ pShift_reg -> Updated CN generator shift register state
+
+ Returns:
+ noise_bits = Generated random integer value (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This is a local function that determnes the index of the pulses by looking up
+ the gray encoder table
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ c1035pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void q_p (
+ Word16 *ind, // Pulse position
+ Word16 n // Pulse number
+)
+{
+ Word16 tmp;
+
+ tmp = *ind;
+
+ if (sub (n, 5) < 0)
+ {
+ *ind = (tmp & 0x8) | gray[tmp & 0x7];
+ }
+ else
+ {
+ *ind = gray[tmp & 0x7];
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void q_p(
+ Word16 *pInd, /* Pulse position */
+ Word16 n /* Pulse number */
+)
+{
+ Word16 tmp;
+
+ tmp = *pInd;
+
+ if (n < 5)
+ {
+ *pInd = (tmp & 0x8) | gray[tmp & 0x7];
+ }
+ else
+ {
+ *pInd = gray[tmp & 0x7];
+ }
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: build_code
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pSeed = pointer to the Old CN generator shift register state (Word32)
+ n_param = Number of parameters to randomize (Word16)
+ param_size_table = table holding paameter sizes (Word16)
+ param[] = array to hold CN generated paramters (Word16)
+ pOverflow = pointer to overflow flag (Flag)
+
+ Outputs:
+ param[] = CN generated parameters (Word16)
+ pSeed = Updated CN generator shift register state (Word16)
+ pOverflow -> 1 if overflow occured
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function builds the codeword, the filtered codeword and index of the
+ codevector, based on the signs and positions of 10 pulses.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ c1035pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+static void build_code (
+ Word16 codvec[], // (i) : position of pulses
+ Word16 sign[], // (i) : sign of d[n]
+ Word16 cod[], // (o) : innovative code vector
+ Word16 h[], // (i) : impulse response of weighted synthesis filter
+ Word16 y[], // (o) : filtered innovative code
+ Word16 indx[] // (o) : index of 10 pulses (sign+position)
+)
+{
+ Word16 i, j, k, track, index, _sign[NB_PULSE];
+ Word16 *p0, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9;
+ Word32 s;
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ cod[i] = 0;
+ }
+ for (i = 0; i < NB_TRACK; i++)
+ {
+ indx[i] = -1;
+ }
+
+ for (k = 0; k < NB_PULSE; k++)
+ {
+ // read pulse position
+ i = codvec[k];
+ // read sign
+ j = sign[i];
+
+ index = mult (i, 6554); // index = pos/5
+ // track = pos%5
+ track = sub (i, extract_l (L_shr (L_mult (index, 5), 1)));
+
+ if (j > 0)
+ {
+ cod[i] = add (cod[i], 4096);
+ _sign[k] = 8192;
+
+ }
+ else
+ {
+ cod[i] = sub (cod[i], 4096);
+ _sign[k] = -8192;
+ index = add (index, 8);
+ }
+
+ if (indx[track] < 0)
+ {
+ indx[track] = index;
+ }
+ else
+ {
+ if (((index ^ indx[track]) & 8) == 0)
+ {
+ // sign of 1st pulse == sign of 2nd pulse
+
+ if (sub (indx[track], index) <= 0)
+ {
+ indx[track + 5] = index;
+ }
+ else
+ {
+ indx[track + 5] = indx[track];
+ indx[track] = index;
+ }
+ }
+ else
+ {
+ // sign of 1st pulse != sign of 2nd pulse
+
+ if (sub ((Word16)(indx[track] & 7), (Word16)(index & 7)) <= 0)
+ {
+ indx[track + 5] = indx[track];
+ indx[track] = index;
+ }
+ else
+ {
+ indx[track + 5] = index;
+ }
+ }
+ }
+ }
+
+ p0 = h - codvec[0];
+ p1 = h - codvec[1];
+ p2 = h - codvec[2];
+ p3 = h - codvec[3];
+ p4 = h - codvec[4];
+ p5 = h - codvec[5];
+ p6 = h - codvec[6];
+ p7 = h - codvec[7];
+ p8 = h - codvec[8];
+ p9 = h - codvec[9];
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ s = 0;
+ s = L_mac (s, *p0++, _sign[0]);
+ s = L_mac (s, *p1++, _sign[1]);
+ s = L_mac (s, *p2++, _sign[2]);
+ s = L_mac (s, *p3++, _sign[3]);
+ s = L_mac (s, *p4++, _sign[4]);
+ s = L_mac (s, *p5++, _sign[5]);
+ s = L_mac (s, *p6++, _sign[6]);
+ s = L_mac (s, *p7++, _sign[7]);
+ s = L_mac (s, *p8++, _sign[8]);
+ s = L_mac (s, *p9++, _sign[9]);
+ y[i] = pv_round (s);
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+static void build_code(
+ Word16 codvec[], /* (i) : position of pulses */
+ Word16 sign[], /* (i) : sign of d[n] */
+ Word16 cod[], /* (o) : innovative code vector */
+ Word16 h[], /* (i) : impulse response of weighted synthesis filter*/
+ Word16 y[], /* (o) : filtered innovative code */
+ Word16 indx[], /* (o) : index of 10 pulses (sign+position) */
+ Flag *pOverflow /* i/o : overflow Flag */
+)
+{
+ Word16 i, k, track, index, _sign[NB_PULSE];
+ Word16 *p0, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9;
+ Word32 s;
+ Word16 temp;
+ Word16 *p__sign;
+ Word16 *p_y;
+ Word16 *p_codvec;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ memset(cod, 0, L_CODE*sizeof(*cod));
+ memset(indx, 0xFF, NB_TRACK*sizeof(*indx));
+
+ p__sign = _sign;
+
+ p0 = &codvec[0];
+
+ for (k = 0; k < NB_PULSE; k++)
+ {
+ /* read pulse position */
+ i = *(p0++);
+ /* read sign */
+
+ index = ((Word32)i * 6554) >> 15; /* index = pos/5 */
+
+ /* track = pos%5 */
+ /* track = sub (i, extract_l (L_shr (L_mult (index, 5), 1))); */
+ track = i - (index * 5);
+
+ if (sign[i] > 0)
+ {
+ cod[i] += 4096;
+ *(p__sign++) = 8192;
+
+ }
+ else
+ {
+ cod[i] -= 4096;
+ *(p__sign++) = -8192;
+ /* index = add (index, 8); */
+ index += 8;
+ }
+
+ p1 = &indx[track];
+
+ temp = *p1;
+
+ if (temp < 0)
+ {
+ *p1 = index;
+ }
+ else
+ {
+ if (((index ^ temp) & 8) == 0)
+ {
+ /* sign of 1st pulse == sign of 2nd pulse */
+
+ /* if (sub (indx[track], index) <= 0) */
+ if (temp <= index)
+ {
+ *(p1 + 5) = index;
+ }
+ else
+ {
+ *(p1 + 5) = temp;
+ *p1 = index;
+ }
+ }
+ else
+ {
+ /* sign of 1st pulse != sign of 2nd pulse */
+
+ /* if (sub ((Word16)(indx[track] & 7), (Word16)(index & 7)) <= 0) */
+ if ((temp & 7) <= (index & 7))
+ {
+ *(p1 + 5) = temp;
+ *p1 = index;
+ }
+ else
+ {
+ *(p1 + 5) = index;
+ }
+ }
+ }
+ }
+
+ p_codvec = &codvec[0];
+
+ p0 = h - *(p_codvec++);
+ p1 = h - *(p_codvec++);
+ p2 = h - *(p_codvec++);
+ p3 = h - *(p_codvec++);
+ p4 = h - *(p_codvec++);
+ p5 = h - *(p_codvec++);
+ p6 = h - *(p_codvec++);
+ p7 = h - *(p_codvec++);
+ p8 = h - *(p_codvec++);
+ p9 = h - *(p_codvec++);
+
+ p_y = y;
+
+ for (i = L_CODE; i != 0; i--)
+ {
+ p__sign = _sign;
+
+ s = (*p0++ * *(p__sign++)) >> 7;
+ s += (*p1++ * *(p__sign++)) >> 7;
+ s += (*p2++ * *(p__sign++)) >> 7;
+ s += (*p3++ * *(p__sign++)) >> 7;
+ s += (*p4++ * *(p__sign++)) >> 7;
+ s += (*p5++ * *(p__sign++)) >> 7;
+ s += (*p6++ * *(p__sign++)) >> 7;
+ s += (*p7++ * *(p__sign++)) >> 7;
+ s += (*p8++ * *(p__sign++)) >> 7;
+ s += (*p9++ * *(p__sign++)) >> 7;
+
+ *(p_y++) = (s + 0x080) >> 8;
+ }
+
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: code_10i40_35bits
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pSeed = pointer to the Old CN generator shift register state (Word32)
+ n_param = Number of parameters to randomize (Word16)
+ param_size_table = table holding paameter sizes (Word16)
+ param[] = array to hold CN generated paramters (Word16)
+ pOverflow = pointer to overflow flag (Flag)
+
+ Outputs:
+ param[] = CN generated parameters (Word16)
+ pSeed = Updated CN generator shift register state (Word16)
+ pOverflow -> 1 if overflow occured
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function searches a 35 bit algebraic codebook containing 10 pulses in a
+ frame of 40 samples.
+
+ The code contains 10 nonzero pulses: i0...i9.
+ All pulses can have two possible amplitudes: +1 or -1.
+ The 40 positions in a subframe are divided into 5 tracks of
+ interleaved positions. Each track contains two pulses.
+ The pulses can have the following possible positions:
+
+ i0, i5 : 0, 5, 10, 15, 20, 25, 30, 35.
+ i1, i6 : 1, 6, 11, 16, 21, 26, 31, 36.
+ i2, i7 : 2, 7, 12, 17, 22, 27, 32, 37.
+ i3, i8 : 3, 8, 13, 18, 23, 28, 33, 38.
+ i4, i9 : 4, 9, 14, 19, 24, 29, 34, 39.
+
+ Each pair of pulses require 1 bit for their signs and 6 bits for their
+ positions (3 bits + 3 bits). This results in a 35 bit codebook.
+ The function determines the optimal pulse signs and positions, builds
+ the codevector, and computes the filtered codevector.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ c1035pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+void code_10i40_35bits (
+ Word16 x[], // (i) : target vector
+ Word16 cn[], // (i) : residual after long term prediction
+ Word16 h[], // (i) : impulse response of weighted synthesis filter
+ // h[-L_subfr..-1] must be set to zero
+ Word16 cod[], // (o) : algebraic (fixed) codebook excitation
+ Word16 y[], // (o) : filtered fixed codebook excitation
+ Word16 indx[] // (o) : index of 10 pulses (sign + position)
+)
+{
+ Word16 ipos[NB_PULSE], pos_max[NB_TRACK], codvec[NB_PULSE];
+ Word16 dn[L_CODE], sign[L_CODE];
+ Word16 rr[L_CODE][L_CODE], i;
+
+ cor_h_x (h, x, dn, 2);
+ set_sign12k2 (dn, cn, sign, pos_max, NB_TRACK, ipos, STEP);
+ cor_h (h, sign, rr);
+
+ search_10and8i40 (NB_PULSE, STEP, NB_TRACK,
+ dn, rr, ipos, pos_max, codvec);
+
+ build_code (codvec, sign, cod, h, y, indx);
+ for (i = 0; i < 10; i++)
+ {
+ q_p (&indx[i], i);
+ }
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void code_10i40_35bits(
+ Word16 x[], /* (i) : target vector */
+ Word16 cn[], /* (i) : residual after long term prediction */
+ Word16 h[], /* (i) : impulse response of weighted synthesis filter
+ h[-L_subfr..-1] must be set to zero */
+ Word16 cod[], /* (o) : algebraic (fixed) codebook excitation */
+ Word16 y[], /* (o) : filtered fixed codebook excitation */
+ Word16 indx[], /* (o) : index of 10 pulses (sign + position) */
+ Flag *pOverflow /* (i/o) : overflow Flag */
+)
+{
+ Word16 ipos[NB_PULSE], pos_max[NB_TRACK], codvec[NB_PULSE];
+ Word16 dn[L_CODE], sign[L_CODE];
+ Word16 rr[L_CODE][L_CODE], i;
+
+ cor_h_x(h, x, dn, 2, pOverflow);
+ set_sign12k2(dn, cn, sign, pos_max, NB_TRACK, ipos, STEP, pOverflow);
+ cor_h(h, sign, rr, pOverflow);
+
+ search_10and8i40(NB_PULSE, STEP, NB_TRACK,
+ dn, rr, ipos, pos_max, codvec, pOverflow);
+
+ build_code(codvec, sign, cod, h, y, indx, pOverflow);
+ for (i = 0; i < 10; i++)
+ {
+ q_p(&indx[i], i);
+ }
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c1035pf.h b/media/libstagefright/codecs/amrnb/enc/src/c1035pf.h
new file mode 100644
index 0000000..be45cbb
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/c1035pf.h
@@ -0,0 +1,124 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/c1035pf.h
+
+ Date: 09/28/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template. Updated function prototype for
+ code_10i40_35bits(). Added extern declaration for gray[] defined
+ in gray_tbl.c
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains the prototype declaration for code_10i40_35bits function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef C1035PF_H
+#define C1035PF_H "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern Word16 gray[];
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void code_10i40_35bits(
+ Word16 x[], /* (i) : target vector */
+ Word16 cn[], /* (i) : residual after long term prediction */
+ Word16 h[], /* (i) : impulse response of weighted synthesis filter
+ h[-L_subfr..-1] must be set to zero */
+ Word16 cod[], /* (o) : algebraic (fixed) codebook excitation */
+ Word16 y[], /* (o) : filtered fixed codebook excitation */
+ Word16 indx[], /* (o) : index of 10 pulses (sign + position) */
+ Flag *pOverflow /* (i/o) : overflow Flag */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _C1035PF_H_ */
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c2_11pf.cpp b/media/libstagefright/codecs/amrnb/enc/src/c2_11pf.cpp
new file mode 100644
index 0000000..87fa9b8
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/c2_11pf.cpp
@@ -0,0 +1,841 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/c2_11pf.c
+ Functions:
+ code_2i40_11bits
+ search_2i40
+ build_code
+
+ Date: 01/28/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified to pass overflow flag through to basic math function.
+ The flag is passed back to the calling function by pointer reference.
+
+ Description: Fixed tabs prior to optimization to make diff'ing easier.
+ Optimized search_2i40() to reduce clock cycle usage.
+
+ Description: Optimized build_code() to reduce clock cycle usage.
+
+ Description: Changed function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Added casting to eliminate warnings
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ *************************************************************************
+ *
+ * FUNCTION: code_2i40_11bits()
+ *
+ * PURPOSE: Searches a 11 bit algebraic codebook containing 2 pulses
+ * in a frame of 40 samples.
+ *
+ * DESCRIPTION:
+ * The code length is 40, containing 2 nonzero pulses: i0...i1.
+ * All pulses can have two possible amplitudes: +1 or -1.
+ * Pulse i0 can have 2x8=16 possible positions, pulse i1 can have
+ * 4x8=32 positions.
+ *
+ * i0 : 1, 6, 11, 16, 21, 26, 31, 36.
+ * 3, 8, 13, 18, 23, 28, 33, 38.
+ * i1 : 0, 5, 10, 15, 20, 25, 30, 35.
+ * 1, 6, 11, 16, 21, 26, 31, 36.
+ * 2, 7, 12, 17, 22, 27, 32, 37.
+ * 4, 9, 14, 19, 24, 29, 34, 39.
+ *
+ *************************************************************************
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "c2_11pf.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "inv_sqrt.h"
+#include "cnst.h"
+#include "cor_h.h"
+#include "set_sign.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define NB_PULSE 2
+
+#define _1_2 (Word16)(32768L/2)
+#define _1_4 (Word16)(32768L/4)
+#define _1_8 (Word16)(32768L/8)
+#define _1_16 (Word16)(32768L/16)
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+static void search_2i40(
+ Word16 dn[], /* i : correlation between target and h[] */
+ Word16 rr[][L_CODE],/* i : matrix of autocorrelation */
+ Word16 codvec[], /* o : algebraic codebook vector */
+ Flag * pOverflow
+);
+
+static Word16 build_code(
+ Word16 codvec[], /* i : algebraic codebook vector */
+ Word16 dn_sign[], /* i : sign of dn[] */
+ Word16 cod[], /* o : algebraic (fixed) codebook excitation */
+ Word16 h[], /* i : impulse response of weighted synthesis filter */
+ Word16 y[], /* o : filtered fixed codebook excitation */
+ Word16 sign[], /* o : sign of 2 pulses */
+ Flag * pOverflow
+);
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+const Word16 startPos1[2] = {1, 3};
+const Word16 startPos2[4] = {0, 1, 2, 4};
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: code_2i40_11bits
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ x, target vector, array of type Word16
+ h, impulse response of weighted synthesis filter, array of type Word16
+ T0, Pitch lag, variable of type Word16
+ pitch_sharp, Last quantized pitch gain, variable of type Word16
+
+ Outputs:
+ code[], Innovative codebook, array of type Word16
+ y[], filtered fixed codebook excitation, array of type Word16
+ sign, Signs of 2 pulses, pointer of type Word16 *
+ pOverflow Flag set when overflow occurs, pointer of type Flag *
+
+ Returns:
+ index
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Searches a 11 bit algebraic codebook containing 2 pulses
+ in a frame of 40 samples.
+
+ The code length is 40, containing 2 nonzero pulses: i0...i1.
+ All pulses can have two possible amplitudes: +1 or -1.
+ Pulse i0 can have 2x8=16 possible positions, pulse i1 can have
+ 4x8=32 positions.
+
+ i0 : 1, 6, 11, 16, 21, 26, 31, 36.
+ 3, 8, 13, 18, 23, 28, 33, 38.
+ i1 : 0, 5, 10, 15, 20, 25, 30, 35.
+ 1, 6, 11, 16, 21, 26, 31, 36.
+ 2, 7, 12, 17, 22, 27, 32, 37.
+ 4, 9, 14, 19, 24, 29, 34, 39.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ c2_11pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 code_2i40_11bits(
+ Word16 x[], /* i : target vector */
+ Word16 h[], /* i : impulse response of weighted synthesis filter */
+ /* h[-L_subfr..-1] must be set to zero. */
+ Word16 T0, /* i : Pitch lag */
+ Word16 pitch_sharp, /* i : Last quantized pitch gain */
+ Word16 code[], /* o : Innovative codebook */
+ Word16 y[], /* o : filtered fixed codebook excitation */
+ Word16 * sign, /* o : Signs of 2 pulses */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 codvec[NB_PULSE];
+ Word16 dn[L_CODE];
+ Word16 dn2[L_CODE];
+ Word16 dn_sign[L_CODE];
+
+ Word16 rr[L_CODE][L_CODE];
+
+ Word16 i;
+ Word16 index;
+ Word16 sharp;
+ Word16 tempWord;
+
+ sharp = pitch_sharp << 1;
+
+ if (T0 < L_CODE)
+ {
+ for (i = T0; i < L_CODE; i++)
+ {
+ tempWord =
+ mult(
+ h[i - T0],
+ sharp,
+ pOverflow);
+
+ h[i] =
+ add(
+ h[i],
+ tempWord,
+ pOverflow);
+ }
+
+ }
+
+ cor_h_x(
+ h,
+ x,
+ dn,
+ 1,
+ pOverflow);
+
+ set_sign(
+ dn,
+ dn_sign,
+ dn2,
+ 8); /* dn2[] not used in this codebook search */
+
+ cor_h(
+ h,
+ dn_sign,
+ rr,
+ pOverflow);
+
+ search_2i40(
+ dn,
+ rr,
+ codvec,
+ pOverflow);
+
+ /* function result */
+
+ index =
+ build_code(
+ codvec,
+ dn_sign,
+ code,
+ h,
+ y,
+ sign,
+ pOverflow);
+
+ /*
+ * Compute innovation vector gain.
+ * Include fixed-gain pitch contribution into code[].
+ */
+
+ if (T0 < L_CODE)
+ {
+ for (i = T0; i < L_CODE; i++)
+ {
+ tempWord =
+ mult(
+ code[i - T0],
+ sharp,
+ pOverflow);
+
+ code[i] =
+ add(
+ code[i],
+ tempWord,
+ pOverflow);
+ }
+ }
+
+ return index;
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: search_2i40
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ dn, correlation between target and h[], array of type Word16
+ rr, matrix of autocorrelation, double-array of type Word16
+
+ Outputs:
+ codvec[], algebraic codebook vector, array of type Word16
+ pOverflow, Flag set when overflow occurs, pointer of type Flag *
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Search the best codevector; determine positions of the 2 pulses
+ in the 40-sample frame.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ c2_11pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void search_2i40(
+ Word16 dn[], /* i : correlation between target and h[] */
+ Word16 rr[][L_CODE], /* i : matrix of autocorrelation */
+ Word16 codvec[], /* o : algebraic codebook vector */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i0;
+ Word16 i1;
+ Word16 ix = 0; /* initialization only needed to keep gcc silent */
+ Word16 track1;
+ Word16 track2;
+ Word16 ipos[NB_PULSE];
+
+ Word16 psk;
+ Word16 ps0;
+ Word16 ps1;
+ Word16 sq;
+ Word16 sq1;
+
+ Word16 alpk;
+ Word16 alp;
+ Word16 alp_16;
+
+ Word32 s;
+ Word32 alp0;
+ Word32 alp1;
+
+ Word16 i;
+ Word16 *p_codvec = &codvec[0];
+
+ psk = -1;
+ alpk = 1;
+
+ for (i = 0; i < NB_PULSE; i++)
+ {
+ *(p_codvec++) = i;
+ }
+
+ /*------------------------------------------------------------------*
+ * main loop: try 2x4 tracks. *
+ *------------------------------------------------------------------*/
+
+ for (track1 = 0; track1 < 2; track1++)
+ {
+ for (track2 = 0; track2 < 4; track2++)
+ {
+ /* fix starting position */
+ ipos[0] = startPos1[track1];
+ ipos[1] = startPos2[track2];
+
+ /*----------------------------------------------------------------*
+ * i0 loop: try 8 positions. *
+ *----------------------------------------------------------------*/
+ for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP)
+ {
+ ps0 = dn[i0];
+
+ /* alp0 = L_mult(rr[i0][i0], _1_4, pOverflow); */
+ alp0 = (Word32) rr[i0][i0] << 14;
+
+ /*-------------------------------------------------------------*
+ * i1 loop: 8 positions. *
+ *-------------------------------------------------------------*/
+
+ sq = -1;
+ alp = 1;
+ ix = ipos[1];
+
+ /*---------------------------------------------------------------*
+ * These index have low complexity address computation because *
+ * they are, in fact, pointers with fixed increment. For example,*
+ * "rr[i0][i2]" is a pointer initialized to "&rr[i0][ipos[2]]" *
+ * and incremented by "STEP". *
+ *---------------------------------------------------------------*/
+
+ for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP)
+ {
+ /* idx increment = STEP */
+ ps1 = add(ps0, dn[i1], pOverflow);
+
+ /* alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1]; */
+
+ /* idx incr = STEP */
+ /* alp1 = L_mac(alp0, rr[i1][i1], _1_4, pOverflow); */
+ alp1 = alp0 + ((Word32) rr[i1][i1] << 14);
+
+ /* idx incr = STEP */
+ /* alp1 = L_mac(alp1, rr[i0][i1], _1_2, pOverflow); */
+ alp1 += (Word32) rr[i0][i1] << 15;
+
+ /* sq1 = mult(ps1, ps1, pOverflow); */
+ sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
+
+ /* alp_16 = pv_round(alp1, pOverflow); */
+ alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
+
+ /* s = L_mult(alp, sq1, pOverflow); */
+ s = ((Word32) alp * sq1) << 1;
+
+ /* s =L_msu(s, sq, alp_16, pOverflow); */
+ s -= (((Word32) sq * alp_16) << 1);
+
+ if (s > 0)
+ {
+ sq = sq1;
+ alp = alp_16;
+ ix = i1;
+ }
+
+ } /* for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP) */
+
+ /* memorize codevector if this one is better than the last one. */
+
+ /* s = L_mult(alpk, sq, pOverflow); */
+ s = ((Word32) alpk * sq) << 1;
+
+ /* s = L_msu(s, psk, alp, pOverflow); */
+ s -= (((Word32) psk * alp) << 1);
+
+ if (s > 0)
+ {
+ psk = sq;
+ alpk = alp;
+ p_codvec = &codvec[0];
+
+ *(p_codvec++) = i0;
+ *(p_codvec) = ix;
+ }
+
+ } /* for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP) */
+
+ } /* for (track2 = 0; track2 < 4; track2++) */
+
+ } /* for (track1 = 0; track1 < 2; track1++) */
+
+ return;
+
+} /* search_2i40 */
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: build_code
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ codvec, position of pulses, array of type Word16
+ dn_sign, sign of pulses, array of type Word16
+ h, impulse response of weighted synthesis filter, Word16 array
+
+ Outputs:
+
+ cod, innovative code vector, array of type Word16
+ y[], filtered innovative code, array of type Word16
+ sign[], sign of 2 pulses, array of type Word16
+ pOverflow, Flag set when overflow occurs, pointer of type Flag *
+
+ Returns:
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Builds the codeword, the filtered codeword and index of the
+ codevector, based on the signs and positions of 2 pulses.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ c2_11pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+static Word16 build_code(
+ Word16 codvec[], /* i : position of pulses */
+ Word16 dn_sign[], /* i : sign of pulses */
+ Word16 cod[], /* o : innovative code vector */
+ Word16 h[], /* i : impulse response of weighted synthesis filter */
+ Word16 y[], /* o : filtered innovative code */
+ Word16 sign[], /* o : sign of 2 pulses */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word16 j;
+ Word16 k;
+ Word16 track;
+ Word16 index;
+ Word16 _sign[NB_PULSE];
+ Word16 indx;
+ Word16 rsign;
+ Word16 tempWord;
+
+ Word16 *p0;
+ Word16 *p1;
+
+ Word32 s;
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ cod[i] = 0;
+ }
+
+ indx = 0;
+ rsign = 0;
+
+ for (k = 0; k < NB_PULSE; k++)
+ {
+ i = codvec[k]; /* read pulse position */
+ j = dn_sign[i]; /* read sign */
+
+ /* index = pos/5 */
+ /* index = mult(i, 6554, pOverflow); */
+ index = (Word16)(((Word32) i * 6554) >> 15);
+
+ /* track = pos%5 */
+ /* tempWord =
+ L_mult(
+ index,
+ 5,
+ pOverflow); */
+ tempWord = ((Word32) index * 5) << 1;
+
+ /* tempWord =
+ L_shr(
+ tempWord,
+ 1,
+ pOverflow); */
+ tempWord >>= 1;
+
+
+ /* track =
+ sub(
+ i,
+ tempWord,
+ pOverflow); */
+ track = i - tempWord;
+
+ tempWord = track;
+
+ if (tempWord == 0)
+ {
+ track = 1;
+
+ /* index =
+ shl(
+ index,
+ 6,
+ pOverflow); */
+ index <<= 6;
+ }
+ else if (track == 1)
+ {
+ tempWord = k;
+
+ if (tempWord == 0)
+ {
+ track = 0;
+ /* index =
+ shl(
+ index,
+ 1,
+ pOverflow); */
+ index <<= 1;
+ }
+ else
+ {
+ track = 1;
+
+ /* tempWord =
+ shl(
+ index,
+ 6,
+ pOverflow); */
+ tempWord = index << 6;
+
+ /* index =
+ add(
+ tempWord,
+ 16,
+ pOverflow); */
+ index = tempWord + 16;
+ }
+ }
+ else if (track == 2)
+ {
+ track = 1;
+
+ /* tempWord =
+ shl(
+ index,
+ 6,
+ pOverflow); */
+ tempWord = index << 6;
+
+ /* index =
+ add(
+ tempWord,
+ 32,
+ pOverflow); */
+ index = tempWord + 32;
+ }
+ else if (track == 3)
+ {
+ track = 0;
+
+ /* tempWord =
+ shl(
+ index,
+ 1,
+ pOverflow); */
+ tempWord = index << 1;
+
+ /* index =
+ add(
+ tempWord,
+ 1,
+ pOverflow); */
+ index = tempWord + 1;
+ }
+ else if (track == 4)
+ {
+ track = 1;
+
+ /* tempWord =
+ shl(
+ index,
+ 6,
+ pOverflow); */
+ tempWord = index << 6;
+
+ /* index =
+ add(
+ tempWord,
+ 48,
+ pOverflow); */
+ index = tempWord + 48;
+ }
+
+ if (j > 0)
+ {
+ cod[i] = 8191;
+ _sign[k] = 32767;
+
+ tempWord =
+ shl(
+ 1,
+ track,
+ pOverflow);
+
+ rsign =
+ add(
+ rsign,
+ tempWord,
+ pOverflow);
+ }
+ else
+ {
+ cod[i] = -8192;
+ _sign[k] = (Word16) - 32768L;
+ }
+
+ indx =
+ add(
+ indx,
+ index,
+ pOverflow);
+ }
+ *sign = rsign;
+
+ p0 = h - codvec[0];
+ p1 = h - codvec[1];
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ s = 0;
+
+ s =
+ L_mac(
+ s,
+ *p0++,
+ _sign[0],
+ pOverflow);
+
+ s =
+ L_mac(
+ s,
+ *p1++,
+ _sign[1],
+ pOverflow);
+
+ y[i] =
+ pv_round(
+ s,
+ pOverflow);
+ }
+
+ return indx;
+}
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c2_11pf.h b/media/libstagefright/codecs/amrnb/enc/src/c2_11pf.h
new file mode 100644
index 0000000..f963ae1
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/c2_11pf.h
@@ -0,0 +1,121 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/c2_11pf.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the c2_11pf.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef c2_11pf_h
+#define c2_11pf_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 code_2i40_11bits(
+ Word16 x[], /* i : target vector */
+ Word16 h[], /* i : impulse response of weighted synthesis filter */
+ /* h[-L_subfr..-1] must be set to zero. */
+ Word16 T0, /* i : Pitch lag */
+ Word16 pitch_sharp, /* i : Last quantized pitch gain */
+ Word16 code[], /* o : Innovative codebook */
+ Word16 y[], /* o : filtered fixed codebook excitation */
+ Word16 * sign, /* o : Signs of 2 pulses */
+ Flag * pOverflow
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _c2_11PF_H_ */
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c2_9pf.cpp b/media/libstagefright/codecs/amrnb/enc/src/c2_9pf.cpp
new file mode 100644
index 0000000..a33cdf74
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/c2_9pf.cpp
@@ -0,0 +1,1219 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/c2_9pf.c
+ Funtions: code_2i40_9bits
+ search_2i40
+ Test_search_2i40
+ build_code
+ Test_build_code
+
+ Date: 05/26/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed template used to PV coding template. First attempt at
+ optimizing C code.
+
+ Description: Updated file per comments gathered from Phase 2/3 review.
+
+ Description: Added setting of Overflow flag in inlined code.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template.
+
+ Description: Replaced basic_op.h with the header files of the math functions
+ used by the file.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Defined one local variable per line.
+
+ Description: Passed in pOverflow flag for EPOC compatibility.
+
+ Description: Optimized search_2i40() to reduce clock cycle usage.
+
+ Description: Removed unnecessary include files and #defines.
+
+ Description: Changed function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the functions that search a 9 bit algebraic codebook
+ containing 2 pulses in a frame of 40 samples.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "c2_9pf.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "inv_sqrt.h"
+#include "cnst.h"
+#include "cor_h.h"
+#include "cor_h_x.h"
+#include "set_sign.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+#define NB_PULSE 2
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ static void search_2i40(
+ Word16 subNr, /* i : subframe number */
+ Word16 dn[], /* i : correlation between target and h[] */
+ Word16 rr[][L_CODE],/* i : matrix of autocorrelation */
+ Word16 codvec[], /* o : algebraic codebook vector */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ static Word16 build_code(
+ Word16 subNr, /* i : subframe number */
+ Word16 codvec[], /* i : algebraic codebook vector */
+ Word16 dn_sign[], /* i : sign of dn[] */
+ Word16 cod[], /* o : algebraic (fixed) codebook excitation */
+ Word16 h[], /* i : impulse response of weighted synthesis filter */
+ Word16 y[], /* o : filtered fixed codebook excitation */
+ Word16 sign[], /* o : sign of 2 pulses */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ const Word16 trackTable[4*5] =
+ {
+ 0, 1, 0, 1, -1, /* subframe 1; track to code;
+ * -1 do not code this position
+ */
+ 0, -1, 1, 0, 1, /* subframe 2 */
+ 0, 1, 0, -1, 1, /* subframe 3 */
+ 0, 1, -1, 0, 1
+ };/* subframe 4 */
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 startPos[];
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: code_2i40_9bits
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ subNr = subframe number (Word16)
+ x = target buffer (Word16)
+ h = buffer containing the impulse response of the
+ weighted synthesis filter; h[-L_subfr .. -1] must be
+ set to zero (Word16)
+ T0 = pitch lag (Word16)
+ pitch_sharp = last quantized pitch gain (Word16)
+ code = buffer containing the innovative codebook (Word16)
+ y = buffer containing the filtered fixed codebook excitation (Word16)
+ sign = pointer to the signs of 2 pulses (Word16)
+
+ Outputs:
+ code buffer contains the new innovation vector gains
+
+ Returns:
+ index = code index (Word16)
+
+ Global Variables Used:
+ Overflow = overflow flag (Flag)
+
+ Local Variables Needed:
+ None
+
+ ------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function searches a 9 bit algebraic codebook containing 2 pulses in a
+ frame of 40 samples.
+
+ The code length is 40, containing 2 nonzero pulses: i0...i1. All pulses can
+ have two possible amplitudes: +1 or -1. Pulse i0 can have 8 possible positions,
+ pulse i1 can have 8 positions. Also coded is which track pair should be used,
+ i.e. first or second pair. Where each pair contains 2 tracks.
+
+ First subframe:
+ first i0 : 0, 5, 10, 15, 20, 25, 30, 35.
+ i1 : 2, 7, 12, 17, 22, 27, 32, 37.
+ second i0 : 1, 6, 11, 16, 21, 26, 31, 36.
+ i1 : 3, 8, 13, 18, 23, 28, 33, 38.
+
+ Second subframe:
+ first i0 : 0, 5, 10, 15, 20, 25, 30, 35.
+ i1 : 3, 8, 13, 18, 23, 28, 33, 38.
+ second i0 : 2, 7, 12, 17, 22, 27, 32, 37.
+ i1 : 4, 9, 14, 19, 24, 29, 34, 39.
+
+ Third subframe:
+ first i0 : 0, 5, 10, 15, 20, 25, 30, 35.
+ i1 : 2, 7, 12, 17, 22, 27, 32, 37.
+ second i0 : 1, 6, 11, 16, 21, 26, 31, 36.
+ i1 : 4, 9, 14, 19, 24, 29, 34, 39.
+
+ Fourth subframe:
+ first i0 : 0, 5, 10, 15, 20, 25, 30, 35.
+ i1 : 3, 8, 13, 18, 23, 28, 33, 38.
+ second i0 : 1, 6, 11, 16, 21, 26, 31, 36.
+ i1 : 4, 9, 14, 19, 24, 29, 34, 39.
+
+ ------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+ ------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+ ------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Word16 code_2i40_9bits(
+ Word16 subNr, // i : subframe number
+ Word16 x[], // i : target vector
+ Word16 h[], // i : impulse response of weighted synthesis filter
+ // h[-L_subfr..-1] must be set to zero.
+ Word16 T0, // i : Pitch lag
+ Word16 pitch_sharp, // i : Last quantized pitch gain
+ Word16 code[], // o : Innovative codebook
+ Word16 y[], // o : filtered fixed codebook excitation
+ Word16 * sign // o : Signs of 2 pulses
+ )
+ {
+ Word16 codvec[NB_PULSE];
+ Word16 dn[L_CODE], dn2[L_CODE], dn_sign[L_CODE];
+ Word16 rr[L_CODE][L_CODE];
+ Word16 i, index, sharp;
+
+ sharp = shl(pitch_sharp, 1);
+ if (sub(T0, L_CODE) < 0)
+ for (i = T0; i < L_CODE; i++) {
+ h[i] = add(h[i], mult(h[i - T0], sharp));
+ }
+ cor_h_x(h, x, dn, 1);
+ set_sign(dn, dn_sign, dn2, 8); // dn2[] not used in this codebook search
+ cor_h(h, dn_sign, rr);
+ search_2i40(subNr, dn, rr, codvec);
+ index = build_code(subNr, codvec, dn_sign, code, h, y, sign);
+
+ *-----------------------------------------------------------------*
+ * Compute innovation vector gain. *
+ * Include fixed-gain pitch contribution into code[]. *
+ *-----------------------------------------------------------------*
+
+ if (sub(T0, L_CODE) < 0)
+ for (i = T0; i < L_CODE; i++) {
+ code[i] = add(code[i], mult(code[i - T0], sharp));
+ }
+ return index;
+ }
+
+ ------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+ ------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+ ------------------------------------------------------------------------------
+ */
+
+ Word16 code_2i40_9bits(
+ Word16 subNr, /* i : subframe number */
+ Word16 x[], /* i : target vector */
+ Word16 h[], /* i : impulse response of weighted synthesis */
+ /* filter h[-L_subfr..-1] must be set to 0. */
+ Word16 T0, /* i : Pitch lag */
+ Word16 pitch_sharp, /* i : Last quantized pitch gain */
+ Word16 code[], /* o : Innovative codebook */
+ Word16 y[], /* o : filtered fixed codebook excitation */
+ Word16 * sign, /* o : Signs of 2 pulses */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ )
+ {
+ Word16 codvec[NB_PULSE];
+ Word16 dn[L_CODE];
+ Word16 dn2[L_CODE];
+ Word16 dn_sign[L_CODE];
+ Word16 rr[L_CODE][L_CODE];
+
+ register Word16 i;
+
+ Word16 index;
+ Word16 sharp;
+ Word16 temp;
+ Word32 L_temp;
+
+ L_temp = ((Word32) pitch_sharp) << 1;
+
+ /* Check for overflow condition */
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ *(pOverflow) = 1;
+ sharp = (pitch_sharp > 0) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ sharp = (Word16) L_temp;
+ }
+
+ if (T0 < L_CODE)
+ {
+ for (i = T0; i < L_CODE; i++)
+ {
+ temp =
+ mult(
+ *(h + i - T0),
+ sharp,
+ pOverflow);
+
+ *(h + i) =
+ add(
+ *(h + i),
+ temp,
+ pOverflow);
+ }
+ }
+
+ cor_h_x(
+ h,
+ x,
+ dn,
+ 1,
+ pOverflow);
+
+ /* dn2[] not used in this codebook search */
+
+ set_sign(
+ dn,
+ dn_sign,
+ dn2,
+ 8);
+
+ cor_h(
+ h,
+ dn_sign,
+ rr,
+ pOverflow);
+
+ search_2i40(
+ subNr,
+ dn,
+ rr,
+ codvec,
+ pOverflow);
+
+ index =
+ build_code(
+ subNr,
+ codvec,
+ dn_sign,
+ code,
+ h,
+ y,
+ sign,
+ pOverflow);
+
+ /*-----------------------------------------------------------------*
+ * Compute innovation vector gain. *
+ * Include fixed-gain pitch contribution into code[]. *
+ *-----------------------------------------------------------------*/
+
+ if (T0 < L_CODE)
+ {
+ for (i = T0; i < L_CODE; i++)
+ {
+ temp =
+ mult(
+ *(code + i - T0),
+ sharp,
+ pOverflow);
+
+ *(code + i) =
+ add(
+ *(code + i),
+ temp,
+ pOverflow);
+ }
+ }
+
+ return(index);
+ }
+
+ /****************************************************************************/
+
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: search_2i40
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ subNr = subframe number (Word16)
+ dn = vector containing the correlation between target and the impulse
+ response of the weighted synthesis filter (Word16)
+ rr = autocorrelation matrix (Word16)
+ codvec = algebraic codebook vector (Word16)
+
+ Outputs:
+ codvec contains the newly calculated codevectors
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ startPos = table containing the start positions used by fixed codebook
+ routines (const Word16)
+
+ ------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function searches the best codevector and determines the positions of
+ the 2 pulses in the 40-sample frame.
+
+ ------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+ ------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+ ------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ static void search_2i40(
+ Word16 subNr, // i : subframe number
+ Word16 dn[], // i : correlation between target and h[]
+ Word16 rr[][L_CODE], // i : matrix of autocorrelation
+ Word16 codvec[] // o : algebraic codebook vector
+ )
+ {
+ Word16 i0, i1;
+ Word16 ix = 0; // initialization only needed to keep gcc silent
+ Word16 track1, ipos[NB_PULSE];
+ Word16 psk, ps0, ps1, sq, sq1;
+ Word16 alpk, alp, alp_16;
+ Word32 s, alp0, alp1;
+ Word16 i;
+
+ psk = -1;
+ alpk = 1;
+ for (i = 0; i < NB_PULSE; i++)
+ {
+ codvec[i] = i;
+ }
+
+ for (track1 = 0; track1 < 2; track1++) {
+ // fix starting position
+
+ ipos[0] = startPos[subNr*2+8*track1];
+ ipos[1] = startPos[subNr*2+1+8*track1];
+
+
+ *----------------------------------------------------------------*
+ * i0 loop: try 8 positions. *
+ *----------------------------------------------------------------*
+
+ for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP) {
+
+ ps0 = dn[i0];
+ alp0 = L_mult(rr[i0][i0], _1_4);
+
+ *----------------------------------------------------------------*
+ * i1 loop: 8 positions. *
+ *----------------------------------------------------------------*
+
+ sq = -1;
+ alp = 1;
+ ix = ipos[1];
+
+ *-------------------------------------------------------------------*
+ * These index have low complexity address computation because *
+ * they are, in fact, pointers with fixed increment. For example, *
+ * "rr[i0][i2]" is a pointer initialized to "&rr[i0][ipos[2]]" *
+ * and incremented by "STEP". *
+ *-------------------------------------------------------------------*
+
+ for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP) {
+ ps1 = add(ps0, dn[i1]); // idx increment = STEP
+
+ // alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1];
+
+ alp1 = L_mac(alp0, rr[i1][i1], _1_4); // idx incr = STEP
+ alp1 = L_mac(alp1, rr[i0][i1], _1_2); // idx incr = STEP
+
+ sq1 = mult(ps1, ps1);
+
+ alp_16 = pv_round(alp1);
+
+ s = L_msu(L_mult(alp, sq1), sq, alp_16);
+
+ if (s > 0) {
+ sq = sq1;
+ alp = alp_16;
+ ix = i1;
+ }
+ }
+
+ *----------------------------------------------------------------*
+ * memorise codevector if this one is better than the last one. *
+ *----------------------------------------------------------------*
+
+ s = L_msu(L_mult(alpk, sq), psk, alp);
+
+ if (s > 0) {
+ psk = sq;
+ alpk = alp;
+ codvec[0] = i0;
+ codvec[1] = ix;
+ }
+ }
+ }
+
+ return;
+ }
+
+ ------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+ ------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+ ------------------------------------------------------------------------------
+ */
+
+ static void search_2i40(
+ Word16 subNr, /* i : subframe number */
+ Word16 dn[], /* i : correlation between target and h[] */
+ Word16 rr[][L_CODE], /* i : matrix of autocorrelation */
+ Word16 codvec[], /* o : algebraic codebook vector */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ )
+ {
+ register Word16 i0;
+ register Word16 i1;
+ Word16 ix = 0; /* initialization only needed to keep gcc silent */
+ register Word16 track1;
+ Word16 ipos[NB_PULSE];
+ Word16 psk;
+ Word16 ps0;
+ Word16 ps1;
+ Word16 sq;
+ Word16 sq1;
+ Word16 alpk;
+ Word16 alp;
+ Word16 alp_16;
+ Word32 s;
+ Word32 alp0;
+ Word32 alp1;
+ register Word16 i;
+ Word32 L_temp;
+ Word16 *p_codvec = &codvec[0];
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ psk = -1;
+ alpk = 1;
+
+ /* Unrolled the following FOR loop to save MIPS */
+ /* for (i = 0; i < NB_PULSE; i++) */
+ /* { */
+ /* *(codvec + i) = i; */
+ /* } */
+
+ *(p_codvec++) = 0;
+ *(p_codvec) = 1;
+
+ for (track1 = 0; track1 < 2; track1++)
+ {
+ /* fix starting position */
+
+ i = (subNr << 1) + (track1 << 3);
+ *ipos = *(startPos + i);
+ *(ipos + 1) = *(startPos + i + 1);
+
+
+ /*----------------------------------------------------------*
+ * i0 loop: try 8 positions. *
+ *----------------------------------------------------------*/
+
+ for (i0 = *ipos; i0 < L_CODE; i0 += STEP)
+ {
+ ps0 = *(dn + i0);
+
+ /* Left shift by 1 converts integer product to */
+ /* fractional product. */
+ alp0 = (Word32) rr[i0][i0] << 14;
+
+ /*--------------------------------------------------*
+ * i1 loop: 8 positions. *
+ *--------------------------------------------------*/
+
+ sq = -1;
+ alp = 1;
+ ix = *(ipos + 1);
+
+ /*--------------------------------------------------*
+ * These index have low complexity address *
+ * computation because they are, in fact, pointers *
+ * with fixed increment. For example, "rr[i0][i2]" *
+ * is a pointer initialized to "&rr[i0][ipos[2]]" *
+ * and incremented by "STEP". *
+ *---------------------------------------------------*/
+
+ for (i1 = *(ipos + 1); i1 < L_CODE; i1 += STEP)
+ {
+ /* idx increment = STEP */
+ /* ps1 = add(ps0, *(dn + i1), pOverflow); */
+ ps1 = ps0 + dn[i1];
+
+ /* alp1 = alp0+rr[i0][i1]+1/2*rr[i1][i1]; */
+
+ /* idx incr = STEP */
+ /* Extra left shift by 1 converts integer */
+ /* product to fractional product */
+ /* alp1 = L_add(alp0, s, pOverflow); */
+ alp1 = alp0 + ((Word32) rr[i1][i1] << 14);
+
+ /* idx incr = STEP */
+ /* Extra left shift by 1 converts integer */
+ /* product to fractional product */
+ /* alp1 = L_add(alp1, s, pOverflow); */
+ alp1 += (Word32) rr[i0][i1] << 15;
+
+ /* sq1 = mult(ps1, ps1, pOverflow); */
+ sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
+
+ /* alp_16 = pv_round(alp1, pOverflow); */
+ alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
+
+ /* L_temp = L_mult(alp, sq1, pOverflow); */
+ L_temp = ((Word32) alp * sq1) << 1;
+
+ /* s = L_msu(L_temp, sq, alp_16, pOverflow); */
+ s = L_temp - (((Word32) sq * alp_16) << 1);
+
+ if (s > 0)
+ {
+ sq = sq1;
+ alp = alp_16;
+ ix = i1;
+ }
+ }
+
+ /* memorize codevector if this one is better than the last one. */
+
+ /* L_temp = L_mult(alpk, sq, pOverflow); */
+ L_temp = ((Word32) alpk * sq) << 1;
+
+ /* s = L_msu(L_temp, psk, alp, pOverflow); */
+ s = L_temp - (((Word32) psk * alp) << 1);
+
+ if (s > 0)
+ {
+ psk = sq;
+ alpk = alp;
+ p_codvec = &codvec[0];
+ *(p_codvec++) = i0;
+ *(p_codvec) = ix;
+ }
+ }
+ }
+
+ return;
+ }
+
+ /****************************************************************************/
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: Test_search_2i40
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ subNr = subframe number (Word16)
+ dn = vector containing the correlation between target and the impulse
+ response of the weighted synthesis filter (Word16)
+ rr = autocorrelation matrix (Word16)
+ codvec = algebraic codebook vector (Word16)
+
+ Outputs:
+ codvec contains the newly calculated codevectors
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ startPos = table containing the start positions used by fixed codebook
+ routines (const Word16)
+
+ ------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function provides external access to the local function search_2i40.
+
+ ------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+ ------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+ ------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ CALL search_2i40 ( subNr = subNr
+ dn = dn
+ rr = rr
+ codvec = codvec )
+ MODIFYING(nothing)
+ RETURNING(nothing)
+
+ ------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+ ------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+ ------------------------------------------------------------------------------
+ */
+
+ void Test_search_2i40(
+ Word16 subNr, /* i : subframe number */
+ Word16 dn[], /* i : correlation between target and h[] */
+ Word16 rr[][L_CODE], /* i : matrix of autocorrelation */
+ Word16 codvec[], /* o : algebraic codebook vector */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ )
+ {
+ /*----------------------------------------------------------------------------
+ CALL search_2i40 ( subNr = subNr
+ dn = dn
+ rr = rr
+ codvec = codvec )
+ MODIFYING(nothing)
+ RETURNING(nothing)
+ ----------------------------------------------------------------------------*/
+ search_2i40(
+ subNr,
+ dn,
+ rr,
+ codvec,
+ pOverflow);
+
+ return;
+ }
+
+ /****************************************************************************/
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: build_code
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ subNr = subframe number (Word16)
+ codvec = vector containing the position of pulses (Word16)
+ dn_sign = vector containing the sign of pulses (Word16)
+ cod = innovative code vector (Word16)
+ h = vector containing the impulse response of the weighted
+ synthesis filter (Word16)
+ y = vector containing the filtered innovative code (Word16)
+ sign = vector containing the sign of 2 pulses (Word16)
+
+ Outputs:
+ cod vector contains the new innovative code
+ y vector contains the new filtered innovative code
+ sign vector contains the sign of 2 pulses
+
+ Returns:
+ indx = codebook index (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ trackTable = table used for tracking codewords (Word16)
+
+ ------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function builds the codeword, the filtered codeword and index of the
+ codevector, based on the signs and positions of 2 pulses.
+
+ ------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+ ------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+ ------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ static Word16 build_code(
+ Word16 subNr, // i : subframe number
+ Word16 codvec[], // i : position of pulses
+ Word16 dn_sign[], // i : sign of pulses
+ Word16 cod[], // o : innovative code vector
+ Word16 h[], // i : impulse response of weighted synthesis filter
+ Word16 y[], // o : filtered innovative code
+ Word16 sign[] // o : sign of 2 pulses
+ )
+ {
+ Word16 i, j, k, track, first, index, _sign[NB_PULSE], indx, rsign;
+ Word16 *p0, *p1, *pt;
+ Word32 s;
+ static Word16 trackTable[4*5] = {
+ 0, 1, 0, 1, -1, // subframe 1; track to code; -1 do not code this position
+ 0, -1, 1, 0, 1, // subframe 2
+ 0, 1, 0, -1, 1, // subframe 3
+ 0, 1, -1, 0, 1};// subframe 4
+
+ pt = &trackTable[add(subNr, shl(subNr, 2))];
+
+ for (i = 0; i < L_CODE; i++) {
+ cod[i] = 0;
+ }
+
+ indx = 0;
+ rsign = 0;
+ for (k = 0; k < NB_PULSE; k++) {
+ i = codvec[k]; // read pulse position
+ j = dn_sign[i]; // read sign
+
+ index = mult(i, 6554); // index = pos/5
+ // track = pos%5
+ track = sub(i, extract_l(L_shr(L_mult(index, 5), 1)));
+
+ first = pt[track];
+
+ if (first == 0) {
+ if (k == 0) {
+ track = 0;
+ } else {
+ track = 1;
+ index = shl(index, 3);
+ }
+ } else {
+ if (k == 0) {
+ track = 0;
+ index = add(index, 64); // table bit is MSB
+ } else {
+ track = 1;
+ index = shl(index, 3);
+ }
+ }
+
+ if (j > 0) {
+ cod[i] = 8191;
+ _sign[k] = 32767;
+ rsign = add(rsign, shl(1, track));
+ } else {
+ cod[i] = -8192;
+ _sign[k] = (Word16) - 32768L;
+ }
+
+ indx = add(indx, index);
+ }
+ *sign = rsign;
+
+ p0 = h - codvec[0];
+ p1 = h - codvec[1];
+
+ for (i = 0; i < L_CODE; i++) {
+ s = 0;
+ s = L_mac(s, *p0++, _sign[0]);
+ s = L_mac(s, *p1++, _sign[1]);
+ y[i] = pv_round(s);
+ }
+
+ return indx;
+ }
+
+ ------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+ ------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+ ------------------------------------------------------------------------------
+ */
+
+ static Word16 build_code(
+ Word16 subNr, /* i : subframe number */
+ Word16 codvec[], /* i : position of pulses */
+ Word16 dn_sign[], /* i : sign of pulses */
+ Word16 cod[], /* o : innovative code vector */
+ Word16 h[], /* i : impulse response of weighted synthesis */
+ /* filter */
+ Word16 y[], /* o : filtered innovative code */
+ Word16 sign[], /* o : sign of 2 pulses */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+ )
+ {
+ register Word16 i;
+ register Word16 j;
+ register Word16 k;
+ register Word16 track;
+ register Word16 first;
+ register Word16 index;
+ register Word16 rsign;
+ Word16 indx;
+ Word16 _sign[NB_PULSE];
+ Word16 *p0;
+ Word16 *p1;
+
+ const Word16 *pt;
+
+ Word32 s;
+
+ pt = trackTable + subNr + (subNr << 2);
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ *(cod + i) = 0;
+ }
+
+ indx = 0;
+ rsign = 0;
+
+ for (k = 0; k < NB_PULSE; k++)
+ {
+ i = *(codvec + k); /* read pulse position */
+ j = *(dn_sign + i); /* read sign */
+
+ s = ((Word32)(i * 6554)) >> 15;
+ index = (Word16) s; /* index = pos/5 */
+
+ track = i - (5 * index); /* track = pos%5 */
+
+ first = *(pt + track);
+
+
+ if (k == 0)
+ {
+ track = 0;
+
+ if (first != 0)
+ {
+ index += 64; /* table bit is MSB */
+ }
+ }
+ else
+ {
+ track = 1;
+ index <<= 3;
+ }
+
+ if (j > 0)
+ {
+ *(cod + i) = 8191;
+ *(_sign + k) = 32767;
+ rsign += (1 << track);
+ }
+ else
+ {
+ *(cod + i) = ~(8192) + 1;
+ *(_sign + k) = (Word16)(~(32768) + 1);
+ }
+
+ indx += index;
+ }
+
+ *sign = rsign;
+
+ p0 = h - *codvec;
+ p1 = h - *(codvec + 1);
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ s = 0;
+ s =
+ L_mult(
+ *p0++,
+ *_sign,
+ pOverflow);
+
+ s =
+ L_mac(
+ s,
+ *p1++,
+ *(_sign + 1),
+ pOverflow);
+
+ *(y + i) =
+ pv_round(
+ s,
+ pOverflow);
+ }
+
+ return(indx);
+ }
+
+ /****************************************************************************/
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: Test_build_code
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ subNr = subframe number (Word16)
+ codvec = vector containing the position of pulses (Word16)
+ dn_sign = vector containing the sign of pulses (Word16)
+ cod = innovative code vector (Word16)
+ h = vector containing the impulse response of the weighted
+ synthesis filter (Word16)
+ y = vector containing the filtered innovative code (Word16)
+ sign = vector containing the sign of 2 pulses (Word16)
+
+ Outputs:
+ cod vector contains the new innovative code
+ y vector contains the new filtered innovative code
+ sign vector contains the sign of 2 pulses
+
+ Returns:
+ indx = codebook index (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ trackTable = table used for tracking codewords (Word16)
+
+ ------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function provides external access to the local function build_code.
+
+ ------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+ ------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c2_9pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+ ------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ CALL build_code ( subNr = subNr
+ codvec = codvec
+ dn_sign = dn_sign
+ cod = cod
+ h = h
+ y = y
+ sign = sign )
+ MODIFYING(nothing)
+ RETURNING(indx)
+
+ ------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+ ------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+ ------------------------------------------------------------------------------
+ */
+
+ Word16 Test_build_code(
+ Word16 subNr, /* i : subframe number */
+ Word16 codvec[], /* i : position of pulses */
+ Word16 dn_sign[], /* i : sign of pulses */
+ Word16 cod[], /* o : innovative code vector */
+ Word16 h[], /* i : impulse response of weighted synthesis */
+ /* filter */
+ Word16 y[], /* o : filtered innovative code */
+ Word16 sign[], /* o : sign of 2 pulses */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ )
+ {
+ Word16 test_index;
+
+ /*----------------------------------------------------------------------------
+ CALL build_code ( subNr = subNr
+ codvec = codvec
+ dn_sign = dn_sign
+ cod = cod
+ h = h
+ y = y
+ sign = sign )
+ MODIFYING(nothing)
+ RETURNING(indx)
+ ----------------------------------------------------------------------------*/
+ test_index =
+ build_code(
+ subNr,
+ codvec,
+ dn_sign,
+ cod,
+ h,
+ y,
+ sign,
+ pOverflow);
+
+ return(test_index);
+ }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c2_9pf.h b/media/libstagefright/codecs/amrnb/enc/src/c2_9pf.h
new file mode 100644
index 0000000..203e1d9
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/c2_9pf.h
@@ -0,0 +1,125 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/c2_9pf.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the c2_9pf.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef c2_9pf_h
+#define c2_9pf_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 code_2i40_9bits(
+ Word16 subNr, /* i : subframe number */
+ Word16 x[], /* i : target vector */
+ Word16 h[], /* i : impulse response of weighted synthesis filter */
+ /* h[-L_subfr..-1] must be set to zero. */
+ Word16 T0, /* i : Pitch lag */
+ Word16 pitch_sharp, /* i : Last quantized pitch gain */
+ Word16 code[], /* o : Innovative codebook */
+ Word16 y[], /* o : filtered fixed codebook excitation */
+ Word16 * sign, /* o : Signs of 2 pulses */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _c2_9PF_H_ */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c3_14pf.cpp b/media/libstagefright/codecs/amrnb/enc/src/c3_14pf.cpp
new file mode 100644
index 0000000..58ab2fa
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/c3_14pf.cpp
@@ -0,0 +1,817 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/c3_14pf.c
+ Functions:
+
+ Date: 05/26/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified to pass overflow flag through to basic math function.
+ The flag is passed back to the calling function by pointer reference.
+
+ Description: Optimized file to reduce clock cycle usage. Updated copyright
+ year. Removed unneccesary include files and added only the
+ include files for the math functions used. Removed unused
+ #defines.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "c3_14pf.h"
+#include "typedef.h"
+#include "inv_sqrt.h"
+#include "cnst.h"
+#include "cor_h.h"
+#include "set_sign.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define NB_PULSE 3
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+static void search_3i40(
+ Word16 dn[], /* i : correlation between target and h[] */
+ Word16 dn2[], /* i : maximum of corr. in each track. */
+ Word16 rr[][L_CODE],/* i : matrix of autocorrelation */
+ Word16 codvec[], /* o : algebraic codebook vector */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+);
+
+static Word16 build_code(
+ Word16 codvec[], /* i : algebraic codebook vector */
+ Word16 dn_sign[], /* i : sign of dn[] */
+ Word16 cod[], /* o : algebraic (fixed) codebook excitation */
+ Word16 h[], /* i : impulse response of weighted synthesis filter */
+ Word16 y[], /* o : filtered fixed codebook excitation */
+ Word16 sign[], /* o : sign of 3 pulses */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+);
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: code_3i40_14bits
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ x[] Array of type Word16 -- target vector
+ h[] Array of type Word16 -- impulse response of weighted synthesis filter
+ h[-L_subfr..-1] must be set to zero.
+
+ T0 Array of type Word16 -- Pitch lag
+ pitch_sharp, Array of type Word16 -- Last quantized pitch gain
+
+ Outputs:
+ code[] Array of type Word16 -- Innovative codebook
+ y[] Array of type Word16 -- filtered fixed codebook excitation
+ * sign Pointer of type Word16 -- Pointer to the signs of 3 pulses
+ pOverflow Pointer to Flag -- set when overflow occurs
+
+ Returns:
+ index
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Searches a 14 bit algebraic codebook containing 3 pulses
+ in a frame of 40 samples.
+
+ DESCRIPTION:
+ The code length is 40, containing 3 nonzero pulses: i0...i2.
+ All pulses can have two possible amplitudes: +1 or -1.
+ Pulse i0 can have 8 possible positions, pulses i1 and i2 can have
+ 2x8=16 positions.
+
+ i0 : 0, 5, 10, 15, 20, 25, 30, 35.
+ i1 : 1, 6, 11, 16, 21, 26, 31, 36.
+ 3, 8, 13, 18, 23, 28, 33, 38.
+ i2 : 2, 7, 12, 17, 22, 27, 32, 37.
+ 4, 9, 14, 19, 24, 29, 34, 39.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c3_14pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 code_3i40_14bits(
+ Word16 x[], /* i : target vector */
+ Word16 h[], /* i : impulse response of weighted synthesis filter */
+ /* h[-L_subfr..-1] must be set to zero. */
+ Word16 T0, /* i : Pitch lag */
+ Word16 pitch_sharp, /* i : Last quantized pitch gain */
+ Word16 code[], /* o : Innovative codebook */
+ Word16 y[], /* o : filtered fixed codebook excitation */
+ Word16 * sign, /* o : Signs of 3 pulses */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 codvec[NB_PULSE];
+ Word16 dn[L_CODE];
+ Word16 dn2[L_CODE];
+ Word16 dn_sign[L_CODE];
+ Word16 rr[L_CODE][L_CODE];
+ Word16 i;
+ Word16 index;
+ Word16 sharp;
+ Word16 tempWord;
+
+ /* sharp = shl(pitch_sharp, 1, pOverflow); */
+ sharp = pitch_sharp << 1;
+
+ if (T0 < L_CODE)
+ {
+ for (i = T0; i < L_CODE; i++)
+ {
+ tempWord =
+ mult(
+ h[i - T0],
+ sharp,
+ pOverflow);
+
+ h[i] =
+ add(
+ h[i],
+ tempWord,
+ pOverflow);
+ }
+ }
+
+ cor_h_x(
+ h,
+ x,
+ dn,
+ 1,
+ pOverflow);
+
+ set_sign(
+ dn,
+ dn_sign,
+ dn2,
+ 6);
+
+ cor_h(
+ h,
+ dn_sign,
+ rr,
+ pOverflow);
+
+ search_3i40(
+ dn,
+ dn2,
+ rr,
+ codvec,
+ pOverflow);
+
+ /* function result */
+ index =
+ build_code(
+ codvec,
+ dn_sign,
+ code,
+ h,
+ y,
+ sign,
+ pOverflow);
+
+ /*-----------------------------------------------------------------*
+ * Compute innovation vector gain. *
+ * Include fixed-gain pitch contribution into code[]. *
+ *-----------------------------------------------------------------*/
+
+ if (T0 < L_CODE)
+ {
+ for (i = T0; i < L_CODE; i++)
+ {
+ tempWord =
+ mult(
+ code[i - T0],
+ sharp,
+ pOverflow);
+
+ code[i] =
+ add(
+ code[i],
+ tempWord,
+ pOverflow);
+ }
+ }
+ return index;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: search_3i40
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ dn[] Array of type Word16 -- correlation between target and h[]
+ dn2[] Array of type Word16 -- maximum of corr. in each track.
+ rr[][L_CODE] Double Array of type Word16 -- autocorrelation matrix
+
+ Outputs:
+ codvec[] Array of type Word16 -- algebraic codebook vector
+ pOverflow Pointer to Flag -- set when overflow occurs
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Search the best codevector; determine positions of the 3 pulses
+ in the 40-sample frame.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c3_14pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+static void search_3i40(
+ Word16 dn[], /* i : correlation between target and h[] */
+ Word16 dn2[], /* i : maximum of corr. in each track. */
+ Word16 rr[][L_CODE], /* i : matrix of autocorrelation */
+ Word16 codvec[], /* o : algebraic codebook vector */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i0;
+ Word16 i1;
+ Word16 i2;
+
+ Word16 ix = 0; /* initialization only needed to keep gcc silent */
+ Word16 ps = 0; /* initialization only needed to keep gcc silent */
+
+ Word16 i;
+ Word16 pos;
+ Word16 track1;
+ Word16 track2;
+ Word16 ipos[NB_PULSE];
+
+ Word16 psk;
+ Word16 ps0;
+ Word16 ps1;
+ Word16 sq;
+ Word16 sq1;
+ Word16 alpk;
+ Word16 alp;
+ Word16 alp_16;
+
+ Word16 *p_codvec = &codvec[0];
+
+ Word32 s;
+ Word32 alp0;
+ Word32 alp1;
+
+ psk = -1;
+ alpk = 1;
+
+ for (i = 0; i < NB_PULSE; i++)
+ {
+ *(p_codvec++) = i;
+ }
+
+ for (track1 = 1; track1 < 4; track1 += 2)
+ {
+ for (track2 = 2; track2 < 5; track2 += 2)
+ {
+ /* fix starting position */
+
+ ipos[0] = 0;
+ ipos[1] = track1;
+ ipos[2] = track2;
+
+ /*------------------------------------------------------------------*
+ * main loop: try 3 tracks. *
+ *------------------------------------------------------------------*/
+
+ for (i = 0; i < NB_PULSE; i++)
+ {
+ /*----------------------------------------------------------------*
+ * i0 loop: try 8 positions. *
+ *----------------------------------------------------------------*/
+
+ /* account for ptr. init. (rr[io]) */
+ for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP)
+ {
+ if (dn2[i0] >= 0)
+ {
+ ps0 = dn[i0];
+
+ /* alp0 = L_mult(rr[i0][i0],_1_4, pOverflow); */
+ alp0 = (Word32) rr[i0][i0] << 14;
+
+ /*----------------------------------------------------------------*
+ * i1 loop: 8 positions. *
+ *----------------------------------------------------------------*/
+
+ sq = -1;
+ alp = 1;
+ ps = 0;
+ ix = ipos[1];
+
+ /* initialize 4 index for next loop. */
+ /*-------------------------------------------------------------------*
+ * These index have low complexity address computation because *
+ * they are, in fact, pointers with fixed increment. For example, *
+ * "rr[i0][i2]" is a pointer initialized to "&rr[i0][ipos[2]]" *
+ * and incremented by "STEP". *
+ *-------------------------------------------------------------------*/
+
+ for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP)
+ {
+ /* idx increment = STEP */
+ /* ps1 = add(ps0, dn[i1], pOverflow); */
+ ps1 = ps0 + dn[i1];
+
+ /* alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1]; */
+
+ /* idx incr = STEP */
+ /* alp1 = L_mac(alp0, rr[i1][i1], _1_4, pOverflow); */
+ alp1 = alp0 + ((Word32) rr[i1][i1] << 14);
+
+ /* idx incr = STEP */
+ /* alp1 = L_mac(alp1, rr[i0][i1], _1_2, pOverflow); */
+ alp1 += (Word32) rr[i0][i1] << 15;
+
+ /* sq1 = mult(ps1, ps1, pOverflow); */
+ sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
+
+ /* alp_16 = pv_round(alp1, pOverflow); */
+ alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
+
+ /* s = L_mult(alp, sq1, pOverflow); */
+ s = ((Word32) alp * sq1) << 1;
+
+ /* s = L_msu(s, sq, alp_16, pOverflow); */
+ s -= (((Word32) sq * alp_16) << 1);
+
+ if (s > 0)
+ {
+ sq = sq1;
+ ps = ps1;
+ alp = alp_16;
+ ix = i1;
+ }
+ }
+ i1 = ix;
+
+ /*----------------------------------------------------------------*
+ * i2 loop: 8 positions. *
+ *----------------------------------------------------------------*/
+
+ ps0 = ps;
+
+ /* alp0 = L_mult(alp, _1_4, pOverflow); */
+ alp0 = (Word32) alp << 14;
+
+ sq = -1;
+ alp = 1;
+ ps = 0;
+ ix = ipos[2];
+
+ /* initialize 4 index for next loop (see i1 loop) */
+
+ for (i2 = ipos[2]; i2 < L_CODE; i2 += STEP)
+ {
+ /* index increment = STEP */
+ /* ps1 = add(ps0, dn[i2], pOverflow); */
+ ps1 = ps0 + dn[i2];
+
+ /* alp1 = alp0 + rr[i0][i2] + rr[i1][i2] + 1/2*rr[i2][i2]; */
+
+ /* idx incr = STEP */
+ /* alp1 = L_mac(alp0, rr[i2][i2], _1_16, pOverflow); */
+ alp1 = alp0 + ((Word32) rr[i2][i2] << 12);
+
+ /* idx incr = STEP */
+ /* alp1 = L_mac(alp1, rr[i1][i2], _1_8, pOverflow); */
+ alp1 += (Word32) rr[i1][i2] << 13;
+
+ /* idx incr = STEP */
+ /* alp1 = L_mac(alp1,rr[i0][i2], _1_8, pOverflow); */
+ alp1 += (Word32) rr[i0][i2] << 13;
+
+ /* sq1 = mult(ps1, ps1, pOverflow); */
+ sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
+
+ /* alp_16 = pv_round(alp1, pOverflow); */
+ alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
+
+ /* s = L_mult(alp, sq1, pOverflow); */
+ s = ((Word32) alp * sq1) << 1;
+
+ /* s = L_msu(s, sq, alp_16, pOverflow); */
+ s -= (((Word32) sq * alp_16) << 1);
+
+ if (s > 0)
+ {
+ sq = sq1;
+ ps = ps1;
+ alp = alp_16;
+ ix = i2;
+ }
+ }
+ i2 = ix;
+
+ /* memorize codevector if this one
+ * is better than the last one.
+ */
+
+ s = L_mult(alpk, sq, pOverflow);
+ //s = ((Word32) alpk * sq) << 1;
+
+ s = L_msu(s, psk, alp, pOverflow);
+ //s -= (((Word32) psk * alp) << 1);
+
+ if (s > 0)
+ {
+ psk = sq;
+ alpk = alp;
+ p_codvec = &codvec[0];
+
+ *(p_codvec++) = i0;
+ *(p_codvec++) = i1;
+ *(p_codvec) = i2;
+ }
+ }
+ }
+ /*----------------------------------------------------------------*
+ * Cyclic permutation of i0, i1 and i2. *
+ *----------------------------------------------------------------*/
+
+ pos = ipos[2];
+ ipos[2] = ipos[1];
+ ipos[1] = ipos[0];
+ ipos[0] = pos;
+ }
+ }
+ }
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: build_code()
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ codvec[] Array of type Word16 -- position of pulses
+ dn_sign[] Array of type Word16 -- sign of pulses
+ h[] Array of type Word16 -- impulse response of
+ weighted synthesis filter
+
+ Outputs:
+ cod[] Array of type Word16 -- innovative code vector
+ y[] Array of type Word16 -- filtered innovative code
+ sign[] Array of type Word16 -- sign of 3 pulses
+ pOverflow Pointer to Flag -- set when overflow occurs
+
+ Returns:
+ indx
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Builds the codeword, the filtered codeword and index of the
+ codevector, based on the signs and positions of 3 pulses.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c3_14pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static Word16
+build_code(
+ Word16 codvec[], /* i : position of pulses */
+ Word16 dn_sign[], /* i : sign of pulses */
+ Word16 cod[], /* o : innovative code vector */
+ Word16 h[], /* i : impulse response of weighted synthesis filter */
+ Word16 y[], /* o : filtered innovative code */
+ Word16 sign[], /* o : sign of 3 pulses */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word16 j;
+ Word16 k;
+ Word16 track;
+ Word16 index;
+ Word16 _sign[NB_PULSE];
+ Word16 indx;
+ Word16 rsign;
+
+ Word16 *p0;
+ Word16 *p1;
+ Word16 *p2;
+
+ Word32 s;
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ cod[i] = 0;
+ }
+
+ indx = 0;
+ rsign = 0;
+
+ for (k = 0; k < NB_PULSE; k++)
+ {
+ i = codvec[k]; /* read pulse position */
+ j = dn_sign[i]; /* read sign */
+
+ /* index = pos/5 */
+ /* index = mult(i, 6554, pOverflow); */
+ index = (Word16)(((Word32) i * 6554) >> 15);
+
+ /* track = pos%5 */
+ /* s = L_mult(index, 5, pOverflow); */
+ s = ((Word32) index * 5) << 1;
+
+ /* s = L_shr(s, 1, pOverflow); */
+ s >>= 1;
+
+ /* track = sub(i, (Word16) s, pOverflow); */
+ track = i - (Word16) s;
+
+ if (track == 1)
+ {
+ /* index = shl(index, 4, pOverflow); */
+ index <<= 4;
+ }
+ else if (track == 2)
+ {
+ track = 2;
+
+ /* index = shl(index, 8, pOverflow); */
+ index <<= 8;
+ }
+ else if (track == 3)
+ {
+ track = 1;
+
+ /* index = shl(index, 4, pOverflow); */
+ index <<= 4;
+
+ /* index = add(index, 8, pOverflow); */
+ index += 8;
+ }
+ else if (track == 4)
+ {
+ track = 2;
+
+ /* index = shl(index, 8, pOverflow); */
+ index <<= 8;
+
+ /* index = add(index, 128, pOverflow); */
+ index += 128;
+ }
+
+ if (j > 0)
+ {
+ cod[i] = 8191;
+ _sign[k] = 32767;
+
+ /* track = shl(1, track, pOverflow); */
+ track = 1 << track;
+
+ /* rsign = add(rsign, track, pOverflow); */
+ rsign += track;
+ }
+ else
+ {
+ cod[i] = -8192;
+ _sign[k] = (Word16) - 32768L;
+ }
+
+ /* indx = add(indx, index, pOverflow); */
+ indx += index;
+ }
+ *sign = rsign;
+
+ p0 = h - codvec[0];
+ p1 = h - codvec[1];
+ p2 = h - codvec[2];
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ s = 0;
+ s =
+ L_mac(
+ s,
+ *p0++,
+ _sign[0],
+ pOverflow);
+
+ s =
+ L_mac(
+ s,
+ *p1++,
+ _sign[1],
+ pOverflow);
+
+ s =
+ L_mac(
+ s,
+ *p2++,
+ _sign[2],
+ pOverflow);
+
+ y[i] =
+ pv_round(
+ s,
+ pOverflow);
+ }
+
+ return indx;
+}
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c3_14pf.h b/media/libstagefright/codecs/amrnb/enc/src/c3_14pf.h
new file mode 100644
index 0000000..15e2f1a
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/c3_14pf.h
@@ -0,0 +1,123 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/c3_14pf.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by c3_14pf.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef c3_14pf_h
+#define c3_14pf_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ Word16 code_3i40_14bits(
+ Word16 x[], /* (i) : target vector */
+ Word16 h[], /* (i) : impulse response of weighted synthesis filter */
+ /* h[-L_subfr..-1] must be set to zero. */
+ Word16 T0, /* (i) : Pitch lag */
+ Word16 pitch_sharp, /* (i) : Last quantized pitch gain */
+ Word16 code[], /* (o) : Innovative codebook */
+ Word16 y[], /* (o) : filtered fixed codebook excitation */
+ Word16 * sign, /* (o) : Signs of 3 pulses */
+ Flag *pOverflow
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _c3_14PF_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c4_17pf.cpp b/media/libstagefright/codecs/amrnb/enc/src/c4_17pf.cpp
new file mode 100644
index 0000000..d52b43b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/c4_17pf.cpp
@@ -0,0 +1,891 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/c4_17pf.c
+ Functions:
+
+ Date: 05/26/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified to pass overflow flag through to basic math function.
+ The flag is passed back to the calling function by pointer reference.
+
+ Description: Optimized functions to further reduce clock cycle usage.
+ Updated copyright year, removed unnecessary include files,
+ and removed unused #defines.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Purpose : Searches a 17 bit algebraic codebook containing 4 pulses
+ in a frame of 40 samples
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "c4_17pf.h"
+#include "typedef.h"
+#include "inv_sqrt.h"
+#include "cnst.h"
+#include "cor_h.h"
+#include "set_sign.h"
+#include "basic_op.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+#define NB_PULSE 4
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ static void search_4i40(
+ Word16 dn[], /* i : correlation between target and h[] */
+ Word16 dn2[], /* i : maximum of corr. in each track. */
+ Word16 rr[][L_CODE],/* i : matrix of autocorrelation */
+ Word16 codvec[], /* o : algebraic codebook vector */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ static Word16 build_code(
+ Word16 codvec[], /* i : algebraic codebook vector */
+ Word16 dn_sign[], /* i : sign of dn[] */
+ Word16 cod[], /* o : algebraic (fixed) codebook excitation */
+ Word16 h[], /* i : impulse response of weighted synthesis filter */
+ Word16 y[], /* o : filtered fixed codebook excitation */
+ Word16 sign[], /* o : index of 4 pulses (position+sign+ampl)*4 */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 gray[];
+ extern const Word16 dgray[];
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: code_4i40_17bits()
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ x[] Array of type Word16 -- target vector
+ h[] Array of type Word16 -- impulse response of weighted synthesis filter
+ h[-L_subfr..-1] must be set to zero.
+
+ T0 Array of type Word16 -- Pitch lag
+ pitch_sharp, Array of type Word16 -- Last quantized pitch gain
+
+ Outputs:
+ code[] Array of type Word16 -- Innovative codebook
+ y[] Array of type Word16 -- filtered fixed codebook excitation
+ * sign Pointer of type Word16 -- Pointer to the signs of 4 pulses
+ pOverflow Pointer to Flag -- set when overflow occurs
+
+ Returns:
+ index
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+
+ ------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Searches a 17 bit algebraic codebook containing 4 pulses
+ in a frame of 40 samples.
+
+ DESCRIPTION:
+ The code length is 40, containing 4 nonzero pulses: i0...i3.
+ All pulses can have two possible amplitudes: +1 or -1.
+ Pulse i0 to i2 can have 8 possible positions, pulse i3 can have
+ 2x8=16 positions.
+
+ i0 : 0, 5, 10, 15, 20, 25, 30, 35.
+ i1 : 1, 6, 11, 16, 21, 26, 31, 36.
+ i2 : 2, 7, 12, 17, 22, 27, 32, 37.
+ i3 : 3, 8, 13, 18, 23, 28, 33, 38.
+ 4, 9, 14, 19, 24, 29, 34, 39.
+
+ ------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+ ------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c3_14pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+ ------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ ------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+ ------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+ ------------------------------------------------------------------------------
+ */
+
+ Word16 code_4i40_17bits(
+ Word16 x[], /* i : target vector */
+ Word16 h[], /* i : impulse response of weighted synthesis filter */
+ /* h[-L_subfr..-1] must be set to zero. */
+ Word16 T0, /* i : Pitch lag */
+ Word16 pitch_sharp, /* i : Last quantized pitch gain */
+ Word16 code[], /* o : Innovative codebook */
+ Word16 y[], /* o : filtered fixed codebook excitation */
+ Word16 * sign, /* o : Signs of 4 pulses */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ )
+ {
+ Word16 codvec[NB_PULSE];
+ Word16 dn[L_CODE];
+ Word16 dn2[L_CODE];
+ Word16 dn_sign[L_CODE];
+
+ Word16 rr[L_CODE][L_CODE];
+ Word16 i;
+ Word16 index;
+ Word16 sharp;
+ Word16 tempWord;
+
+ sharp = pitch_sharp << 1;
+
+ if (T0 < L_CODE)
+ {
+ for (i = T0; i < L_CODE; i++)
+ {
+ tempWord =
+ mult(
+ h[i - T0],
+ sharp,
+ pOverflow);
+
+ h[i] =
+ add(
+ h[i],
+ tempWord,
+ pOverflow);
+ }
+ }
+
+ cor_h_x(
+ h,
+ x,
+ dn,
+ 1,
+ pOverflow);
+
+ set_sign(
+ dn,
+ dn_sign,
+ dn2,
+ 4);
+
+ cor_h(
+ h,
+ dn_sign,
+ rr,
+ pOverflow);
+
+ search_4i40(
+ dn,
+ dn2,
+ rr,
+ codvec,
+ pOverflow);
+
+ /* function result */
+ index =
+ build_code(
+ codvec,
+ dn_sign,
+ code,
+ h,
+ y,
+ sign,
+ pOverflow);
+
+ /*-----------------------------------------------------------------*
+ * Compute innovation vector gain. *
+ * Include fixed-gain pitch contribution into code[]. *
+ *-----------------------------------------------------------------*/
+
+ tempWord = T0 - L_CODE;
+
+ if (tempWord < 0)
+ {
+ for (i = T0; i < L_CODE; i++)
+ {
+ tempWord =
+ mult(
+ code[i - T0],
+ sharp,
+ pOverflow);
+
+ code[i] =
+ add(
+ code[i],
+ tempWord,
+ pOverflow);
+ }
+ }
+
+ return index;
+ }
+ /****************************************************************************/
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: search_4i40()
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ dn[] Array of type Word16 -- correlation between target and h[]
+ dn2[] Array of type Word16 -- maximum of corr. in each track.
+ rr[][L_CODE] Double Array of type Word16 -- autocorrelation matrix
+
+ Outputs:
+ codvec[] Array of type Word16 -- algebraic codebook vector
+ pOverflow Pointer to Flag -- set when overflow occurs
+
+ Returns:
+
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+
+
+ ------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Search the best codevector; determine positions of the 4 pulses
+ in the 40-sample frame.
+
+ ------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+ ------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c4_17pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+ ------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ ------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+ ------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+ ------------------------------------------------------------------------------
+ */
+ static void search_4i40(
+ Word16 dn[], /* i : correlation between target and h[] */
+ Word16 dn2[], /* i : maximum of corr. in each track. */
+ Word16 rr[][L_CODE], /* i : matrix of autocorrelation */
+ Word16 codvec[], /* o : algebraic codebook vector */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ )
+ {
+ Word16 i0;
+ Word16 i1;
+ Word16 i2;
+ Word16 i3;
+
+ Word16 ix = 0; /* initialization only needed to keep gcc silent */
+ Word16 ps = 0; /* initialization only needed to keep gcc silent */
+
+ Word16 i;
+ Word16 pos;
+ Word16 track;
+ Word16 ipos[NB_PULSE];
+
+ Word16 psk;
+ Word16 ps0;
+ Word16 ps1;
+ Word16 sq;
+ Word16 sq1;
+
+ Word16 alpk;
+ Word16 alp;
+ Word16 alp_16;
+ Word16 *p_codvec = &codvec[0];
+
+ Word32 s;
+ Word32 alp0;
+ Word32 alp1;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ /* Default value */
+ psk = -1;
+ alpk = 1;
+ for (i = 0; i < NB_PULSE; i++)
+ {
+ *(p_codvec++) = i;
+ }
+
+ for (track = 3; track < 5; track++)
+ {
+ /* fix starting position */
+
+ ipos[0] = 0;
+ ipos[1] = 1;
+ ipos[2] = 2;
+ ipos[3] = track;
+
+ /*------------------------------------------------------------------*
+ * main loop: try 4 tracks. *
+ *------------------------------------------------------------------*/
+
+ for (i = 0; i < NB_PULSE; i++)
+ {
+ /*----------------------------------------------------------------*
+ * i0 loop: try 4 positions (use position with max of corr.). *
+ *----------------------------------------------------------------*/
+
+ for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP)
+ {
+ if (dn2[i0] >= 0)
+ {
+ ps0 = dn[i0];
+
+ alp0 = (Word32) rr[i0][i0] << 14;
+
+ /*----------------------------------------------------------------*
+ * i1 loop: 8 positions. *
+ *----------------------------------------------------------------*/
+
+ sq = -1;
+ alp = 1;
+ ps = 0;
+ ix = ipos[1];
+
+ /* initialize 4 index for next loop. */
+ /*-------------------------------------------------------------------*
+ * These index have low complexity address computation because *
+ * they are, in fact, pointers with fixed increment. For example, *
+ * "rr[i0][i3]" is a pointer initialized to "&rr[i0][ipos[3]]" *
+ * and incremented by "STEP". *
+ *-------------------------------------------------------------------*/
+
+ for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP)
+ {
+ /* idx increment = STEP */
+ /* ps1 = add(ps0, dn[i1], pOverflow); */
+ ps1 = ps0 + dn[i1];
+
+ /* alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1]; */
+
+ /* alp1 = L_mac(alp0, rr[i1][i1], _1_4, pOverflow); */
+ alp1 = alp0 + ((Word32) rr[i1][i1] << 14);
+
+ /* alp1 = L_mac(alp1, rr[i0][i1], _1_2, pOverflow); */
+ alp1 += (Word32) rr[i0][i1] << 15;
+
+ /* sq1 = mult(ps1, ps1, pOverflow); */
+ sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
+
+ /* alp_16 = pv_round(alp1, pOverflow); */
+ alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
+
+ /* s = L_mult(alp, sq1, pOverflow); */
+ s = ((Word32) alp * sq1) << 1;
+
+ /* s = L_msu(s, sq, alp_16, pOverflow); */
+ s -= (((Word32) sq * alp_16) << 1);
+
+ if (s > 0)
+ {
+ sq = sq1;
+ ps = ps1;
+ alp = alp_16;
+ ix = i1;
+ }
+ }
+ i1 = ix;
+
+ /*----------------------------------------------------------------*
+ * i2 loop: 8 positions. *
+ *----------------------------------------------------------------*/
+
+ ps0 = ps;
+
+ /* alp0 = L_mult(alp, _1_4, pOverflow); */
+ alp0 = (Word32) alp << 14;
+
+ sq = -1;
+ alp = 1;
+ ps = 0;
+ ix = ipos[2];
+
+ /* initialize 4 index for next loop (see i1 loop) */
+
+ for (i2 = ipos[2]; i2 < L_CODE; i2 += STEP)
+ {
+ /* index increment = STEP */
+ /* ps1 = add(ps0, dn[i2], pOverflow); */
+ ps1 = ps0 + dn[i2];
+
+ /* alp1 = alp0 + rr[i0][i2] + rr[i1][i2] + 1/2*rr[i2][i2]; */
+
+ /* idx incr = STEP */
+ /* alp1 = L_mac(alp0, rr[i2][i2], _1_16, pOverflow); */
+ alp1 = alp0 + ((Word32) rr[i2][i2] << 12);
+
+ /* idx incr = STEP */
+ /* alp1 = L_mac(alp1, rr[i1][i2], _1_8, pOverflow); */
+ alp1 += (Word32) rr[i1][i2] << 13;
+
+ /* idx incr = STEP */
+ /* alp1 = L_mac(alp1,rr[i0][i2], _1_8, pOverflow); */
+ alp1 += (Word32) rr[i0][i2] << 13;
+
+ /* sq1 = mult(ps1, ps1, pOverflow); */
+ sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
+
+ /* alp_16 = pv_round(alp1, pOverflow); */
+ alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
+
+ /* s = L_mult(alp, sq1, pOverflow); */
+ s = ((Word32) alp * sq1) << 1;
+
+ /* s = L_msu(s, sq, alp_16, pOverflow); */
+ s -= (((Word32) sq * alp_16) << 1);
+
+ if (s > 0)
+ {
+ sq = sq1;
+ ps = ps1;
+ alp = alp_16;
+ ix = i2;
+ }
+ }
+ i2 = ix;
+
+ /*----------------------------------------------------------------*
+ * i3 loop: 8 positions. *
+ *----------------------------------------------------------------*/
+
+ ps0 = ps;
+ alp0 = L_deposit_h(alp);
+
+ sq = -1;
+ alp = 1;
+ ps = 0;
+ ix = ipos[3];
+
+ /* initialize 5 index for next loop (see i1 loop) */
+
+ for (i3 = ipos[3]; i3 < L_CODE; i3 += STEP)
+ {
+ /* ps1 = add(ps0, dn[i3], pOverflow); */
+ ps1 = ps0 + dn[i3]; /* index increment = STEP */
+
+ /* alp1 = alp0 + rr[i0][i3] + rr[i1][i3] + rr[i2][i3] + 1/2*rr[i3][i3]; */
+
+ /* alp1 = L_mac(alp0, rr[i3][i3], _1_16, pOverflow); */
+ alp1 = alp0 + ((Word32) rr[i3][i3] << 12); /* idx incr = STEP */
+
+ /* alp1 = L_mac(alp1, rr[i2][i3], _1_8, pOverflow); */
+ alp1 += (Word32) rr[i2][i3] << 13; /* idx incr = STEP */
+
+ /* alp1 = L_mac(alp1, rr[i1][i3], _1_8, pOverflow); */
+ alp1 += (Word32) rr[i1][i3] << 13; /* idx incr = STEP */
+
+ /* alp1 = L_mac(alp1, rr[i0][i3], _1_8, pOverflow); */
+ alp1 += (Word32) rr[i0][i3] << 13; /* idx incr = STEP */
+
+ /* sq1 = mult(ps1, ps1, pOverflow); */
+ sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
+
+ /* alp_16 = pv_round(alp1, pOverflow); */
+ alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
+
+ /* s = L_mult(alp, sq1, pOverflow); */
+ s = ((Word32) alp * sq1) << 1;
+
+ /* s = L_msu(s, sq, alp_16, pOverflow); */
+ s -= (((Word32) sq * alp_16) << 1);
+
+ if (s > 0)
+ {
+ sq = sq1;
+ ps = ps1;
+ alp = alp_16;
+ ix = i3;
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ * memorise codevector if this one is better than the last one. *
+ *----------------------------------------------------------------*/
+
+ /* s = L_mult(alpk, sq, pOverflow); */
+ s = ((Word32) alpk * sq) << 1;
+
+ /* s = L_msu(s, psk, alp, pOverflow); */
+ s -= (((Word32) psk * alp) << 1);
+
+ if (s > 0)
+ {
+ psk = sq;
+ alpk = alp;
+ p_codvec = &codvec[0];
+
+ *(p_codvec++) = i0;
+ *(p_codvec++) = i1;
+ *(p_codvec++) = i2;
+ *(p_codvec) = ix;
+ }
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ * Cyclic permutation of i0,i1,i2 and i3. *
+ *----------------------------------------------------------------*/
+
+ pos = ipos[3];
+ ipos[3] = ipos[2];
+ ipos[2] = ipos[1];
+ ipos[1] = ipos[0];
+ ipos[0] = pos;
+ }
+ }
+
+ return;
+ }
+
+
+
+
+ /****************************************************************************/
+
+ /*
+ ------------------------------------------------------------------------------
+ FUNCTION NAME: build_code()
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ codvec[] Array of type Word16 -- position of pulses
+ dn_sign[] Array of type Word16 -- sign of pulses
+ h[] Array of type Word16 -- impulse response of
+ weighted synthesis filter
+
+ Outputs:
+ cod[] Array of type Word16 -- innovative code vector
+ y[] Array of type Word16 -- filtered innovative code
+ sign[] Array of type Word16 -- index of 4 pulses (sign + position)
+ pOverflow Pointer to Flag -- set when overflow occurs
+
+ Returns:
+ indx
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+
+ ------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Builds the codeword, the filtered codeword and index of the
+ codevector, based on the signs and positions of 4 pulses.
+
+ ------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+ ------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c4_17pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+ ------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ ------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+ ------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+ ------------------------------------------------------------------------------
+ */
+
+ static Word16
+ build_code(
+ Word16 codvec[], /* i : position of pulses */
+ Word16 dn_sign[], /* i : sign of pulses */
+ Word16 cod[], /* o : innovative code vector */
+ Word16 h[], /* i : impulse response of weighted synthesis filter */
+ Word16 y[], /* o : filtered innovative code */
+ Word16 sign[], /* o : index of 4 pulses (sign+position) */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ )
+ {
+ Word16 i;
+ Word16 j;
+ Word16 k;
+ Word16 track;
+ Word16 index;
+ Word16 _sign[NB_PULSE];
+ Word16 indx;
+ Word16 rsign;
+
+ Word16 *p0;
+ Word16 *p1;
+ Word16 *p2;
+ Word16 *p3;
+ Word16 *p_cod = &cod[0];
+
+ Word32 s;
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ *(p_cod++) = 0;
+ }
+
+ indx = 0;
+ rsign = 0;
+
+ for (k = 0; k < NB_PULSE; k++)
+ {
+ i = codvec[k]; /* read pulse position */
+ j = dn_sign[i]; /* read sign */
+
+ /* index = pos/5 */
+ /* index = mult(i, 6554, pOverflow); */
+ index = (Word16)(((Word32) i * 6554) >> 15);
+
+ /* track = pos%5 */
+ /* s = L_mult(index, 5, pOverflow); */
+ s = ((Word32) index * 5) << 1;
+
+ /* s = L_shr(s, 1, pOverflow); */
+ s >>= 1;
+
+ /* track = sub(i, (Word16) s, pOverflow); */
+ track = i - (Word16) s;
+
+ index = gray[index];
+
+ if (track == 1)
+ {
+ /* index = shl(index, 3, pOverflow); */
+ index <<= 3;
+ }
+ else if (track == 2)
+ {
+ /* index = shl(index, 6, pOverflow); */
+ index <<= 6;
+ }
+ else if (track == 3)
+ {
+ /* index = shl(index, 10, pOverflow); */
+ index <<= 10;
+ }
+ else if (track == 4)
+ {
+ track = 3;
+
+ /* index = shl(index, 10, pOverflow); */
+ index <<= 10;
+
+ /* index = add(index, 512, pOverflow); */
+ index += 512;
+ }
+
+ if (j > 0)
+ {
+ cod[i] = 8191;
+ _sign[k] = 32767;
+
+ /* track = shl(1, track, pOverflow); */
+ track = 1 << track;
+
+ /* rsign = add(rsign, track, pOverflow); */
+ rsign += track;
+ }
+ else
+ {
+ cod[i] = -8192;
+ _sign[k] = (Word16) - 32768L;
+ }
+
+ /* indx = add(indx, index, pOverflow); */
+ indx += index;
+ }
+ *sign = rsign;
+
+ p0 = h - codvec[0];
+ p1 = h - codvec[1];
+ p2 = h - codvec[2];
+ p3 = h - codvec[3];
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ s = 0;
+ s =
+ L_mac(
+ s,
+ *p0++,
+ _sign[0],
+ pOverflow);
+
+ s =
+ L_mac(
+ s,
+ *p1++,
+ _sign[1],
+ pOverflow);
+
+ s =
+ L_mac(
+ s,
+ *p2++,
+ _sign[2],
+ pOverflow);
+
+ s =
+ L_mac(
+ s,
+ *p3++,
+ _sign[3],
+ pOverflow);
+
+ y[i] =
+ pv_round(
+ s,
+ pOverflow);
+
+ } /* for (i = 0; i < L_CODE; i++) */
+
+ return indx;
+
+ } /* build_code */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c4_17pf.h b/media/libstagefright/codecs/amrnb/enc/src/c4_17pf.h
new file mode 100644
index 0000000..4dc66a9
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/c4_17pf.h
@@ -0,0 +1,123 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/c4_17pf.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the c4_17pf.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef c4_17pf_h
+#define c4_17pf_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 code_4i40_17bits(
+ Word16 x[], /* (i) : target vector */
+ Word16 h[], /* (i) : impulse response of weighted synthesis filter */
+ /* h[-L_subfr..-1] must be set to zero. */
+ Word16 T0, /* (i) : Pitch lag */
+ Word16 pitch_sharp, /* (i) : Last quantized pitch gain */
+ Word16 code[], /* (o) : Innovative codebook */
+ Word16 y[], /* (o) : filtered fixed codebook excitation */
+ Word16 * sign, /* (o) : Signs of 4 pulses */
+ Flag * pOverflow /* (o) : Flag set when overflow occurs */
+ );
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _c4_17PF_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c8_31pf.cpp b/media/libstagefright/codecs/amrnb/enc/src/c8_31pf.cpp
new file mode 100644
index 0000000..07c2efd
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/c8_31pf.cpp
@@ -0,0 +1,828 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/c8_31pf.c
+ Functions:
+
+ Date: 05/26/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified to pass overflow flag through to basic math function.
+ The flag is passed back to the calling function by pointer reference.
+
+ Description: Optimized file to reduce clock cycle usage. Updated copyright
+ year. Removed unnecessary include files and unused #defines.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Purpose : Searches a 31 bit algebraic codebook containing
+ : 8 pulses in a frame of 40 samples.
+ : in the same manner as GSM-EFR
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "c8_31pf.h"
+#include "typedef.h"
+#include "cnst.h"
+#include "inv_sqrt.h"
+#include "cor_h.h"
+#include "cor_h_x2.h"
+#include "set_sign.h"
+#include "s10_8pf.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define NB_PULSE 8
+
+/* define values/representation for output codevector and sign */
+#define POS_CODE 8191
+#define NEG_CODE 8191
+#define POS_SIGN 32767
+#define NEG_SIGN (Word16) (-32768L)
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ codvec[] Array of type Word16 -- position of pulses
+ sign[] Array of type Word16 -- sign of pulses
+ h[] Array of type Word16 -- impulse response of
+ weighted synthesis filter
+ Outputs:
+ cod[] Array of type Word16 -- innovative code vector
+ y[] Array of type Word16 -- filtered innovative code
+ sign_indx[] Array of type Word16 -- signs of 4 pulses (signs only)
+ pos_indx[] Array of type Word16 --
+ position index of 8 pulses(position only)
+
+ pOverflow Pointer to Flag -- set when overflow occurs
+
+ Returns:
+ indx
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c8_31pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*************************************************************************
+ *
+ * FUNCTION: build_code()
+ *
+ * PURPOSE: Builds the codeword, the filtered codeword and a
+ * linear uncombined version of the index of the
+ * codevector, based on the signs and positions of 8 pulses.
+ *
+ *************************************************************************/
+
+static void build_code(
+ Word16 codvec[], /* i : position of pulses */
+ Word16 sign[], /* i : sign of d[n] */
+ Word16 cod[], /* o : innovative code vector */
+ Word16 h[], /* i : impulse response of weighted synthesis filter*/
+ Word16 y[], /* o : filtered innovative code */
+ Word16 sign_indx[], /* o : signs of 4 pulses (signs only) */
+ Word16 pos_indx[], /* o : position index of 8 pulses(position only) */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 i;
+ Word16 j;
+ Word16 k;
+ Word16 track;
+ Word16 sign_index;
+ Word16 pos_index;
+ Word16 _sign[NB_PULSE];
+
+ Word16 *p0;
+ Word16 *p1;
+ Word16 *p2;
+ Word16 *p3;
+ Word16 *p4;
+ Word16 *p5;
+ Word16 *p6;
+ Word16 *p7;
+
+ Word16 *p_cod = &cod[0];
+ Word16 *p_codvec = &codvec[0];
+
+ Word32 s;
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ *(p_cod++) = 0;
+ }
+
+ for (i = 0; i < NB_TRACK_MR102; i++)
+ {
+ pos_indx[i] = -1;
+ sign_indx[i] = -1;
+ }
+
+ for (k = 0; k < NB_PULSE; k++)
+ {
+ /* read pulse position */
+ i = codvec[k];
+ /* read sign */
+ j = sign[i];
+
+ pos_index = i >> 2; /* index = pos/4 */
+
+ track = i & 3; /* track = pos%4 */
+
+ if (j > 0)
+ {
+ cod[i] = (Word16)((Word32) cod[i] + POS_CODE);
+
+ _sign[k] = POS_SIGN;
+ sign_index = 0; /* bit=0 -> positive pulse */
+ }
+ else
+ {
+ cod[i] = (Word16)((Word32) cod[i] - NEG_CODE);
+
+ _sign[k] = NEG_SIGN;
+ sign_index = 1; /* bit=1 => negative pulse */
+ /* index = add (index, 8); 1 = negative old code */
+ }
+
+ if (pos_indx[track] < 0)
+ { /* first set first NB_TRACK pulses */
+ pos_indx[track] = pos_index;
+ sign_indx[track] = sign_index;
+ }
+ else
+ { /* 2nd row of pulses , test if positions needs to be switched */
+ if (((sign_index ^ sign_indx[track]) & 1) == 0)
+ {
+ /* sign of 1st pulse == sign of 2nd pulse */
+
+ if (pos_indx[track] <= pos_index)
+ { /* no swap */
+ pos_indx[track + NB_TRACK_MR102] = pos_index;
+ }
+ else
+ { /* swap*/
+ pos_indx[track + NB_TRACK_MR102] = pos_indx[track];
+
+ pos_indx[track] = pos_index;
+ sign_indx[track] = sign_index;
+ }
+ }
+ else
+ {
+ /* sign of 1st pulse != sign of 2nd pulse */
+
+ if (pos_indx[track] <= pos_index)
+ { /*swap*/
+ pos_indx[track + NB_TRACK_MR102] = pos_indx[track];
+
+ pos_indx[track] = pos_index;
+ sign_indx[track] = sign_index;
+ }
+ else
+ { /*no swap */
+ pos_indx[track + NB_TRACK_MR102] = pos_index;
+ }
+ }
+ }
+ }
+
+ p0 = h - *(p_codvec++);
+ p1 = h - *(p_codvec++);
+ p2 = h - *(p_codvec++);
+ p3 = h - *(p_codvec++);
+ p4 = h - *(p_codvec++);
+ p5 = h - *(p_codvec++);
+ p6 = h - *(p_codvec++);
+ p7 = h - *(p_codvec);
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ s = 0;
+
+ s =
+ L_mac(
+ s,
+ *p0++,
+ _sign[0],
+ pOverflow);
+ s =
+ L_mac(
+ s,
+ *p1++,
+ _sign[1],
+ pOverflow);
+ s =
+ L_mac(
+ s,
+ *p2++,
+ _sign[2],
+ pOverflow);
+ s =
+ L_mac(
+ s,
+ *p3++,
+ _sign[3],
+ pOverflow);
+ s =
+ L_mac(
+ s,
+ *p4++,
+ _sign[4],
+ pOverflow);
+ s =
+ L_mac(
+ s,
+ *p5++,
+ _sign[5],
+ pOverflow);
+ s =
+ L_mac(
+ s,
+ *p6++,
+ _sign[6],
+ pOverflow);
+ s =
+ L_mac(
+ s,
+ *p7++,
+ _sign[7],
+ pOverflow);
+
+ y[i] =
+ pv_round(
+ s,
+ pOverflow);
+
+ } /* for (i = 0; i < L_CODE; i++) */
+
+} /* build_code */
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: compress_code()
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ Outputs:
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ FUNCTION:
+
+ PURPOSE: compression of three indeces [0..9] to one 10 bit index
+ minimizing the phase shift of a bit error.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c8_31pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static Word16 compress10(
+ Word16 pos_indxA, /* i : signs of 4 pulses (signs only) */
+ Word16 pos_indxB, /* i : position index of 8 pulses (pos only) */
+ Word16 pos_indxC, /* i : position and sign of 8 pulses (compressed) */
+ Flag *pOverflow) /* o : Flag set when overflow occurs */
+{
+ Word16 indx;
+ Word16 ia;
+ Word16 ib;
+ Word16 ic;
+
+ Word32 tempWord32;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ ia = pos_indxA >> 1;
+
+ ib = pos_indxB >> 1;
+
+ tempWord32 = ((Word32) ib * 5) << 1;
+
+ tempWord32 = tempWord32 >> 1;
+
+ ib = (Word16) tempWord32;
+
+ ic = pos_indxC >> 1;
+
+ tempWord32 = ((Word32) ic * 25) << 1;
+
+ tempWord32 = tempWord32 >> 1;
+
+ ic = (Word16) tempWord32;
+
+ ib += ic;
+
+ ib += ia;
+
+ indx = ib << 3;
+
+ ia = pos_indxA & 1;
+
+ ib = ((Word16)(pos_indxB & 1)) << 1;
+
+ ic = ((Word16)(pos_indxC & 1)) << 2;
+
+ ib += ic;
+
+ ib += ia;
+
+ indx += ib;
+
+ return indx;
+
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: compress_code()
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ sign_indx Array of type Word16 -- signs of 4 pulses (signs only)
+ pos_indx Array of type Word16 -- position index of 8 pulses
+ (position only)
+
+ Outputs:
+ indx Array of type Word16 -- position and sign of 8 pulses
+ (compressed)
+ pOverflow Pointer to Flag -- set when overflow occurs
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: compression of the linear codewords to 4+three indeces
+ one bit from each pulse is made robust to errors by
+ minimizing the phase shift of a bit error.
+ 4 signs (one for each track)
+ i0,i4,i1 => one index (7+3) bits, 3 LSBs more robust
+ i2,i6,i5 => one index (7+3) bits, 3 LSBs more robust
+ i3,i7 => one index (5+2) bits, 2-3 LSbs more robust
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c3_14pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void compress_code(
+ Word16 sign_indx[], /* i : signs of 4 pulses (signs only) */
+ Word16 pos_indx[], /* i : position index of 8 pulses (position only) */
+ Word16 indx[], /* o : position and sign of 8 pulses (compressed) */
+ Flag *pOverflow) /* o : Flag set when overflow occurs */
+{
+ Word16 i;
+ Word16 ia;
+ Word16 ib;
+ Word16 ic;
+
+ Word16 *p_indx = &indx[0];
+ Word16 *p_sign_indx = &sign_indx[0];
+
+ Word32 tempWord32;
+
+ for (i = 0; i < NB_TRACK_MR102; i++)
+ {
+ *(p_indx++) = *(p_sign_indx++);
+ }
+
+ /* First index
+ indx[NB_TRACK] = (ia/2+(ib/2)*5 +(ic/2)*25)*8 + ia%2 + (ib%2)*2 + (ic%2)*4; */
+
+ indx[NB_TRACK_MR102] =
+ compress10(
+ pos_indx[0],
+ pos_indx[4],
+ pos_indx[1],
+ pOverflow);
+
+ /* Second index
+ indx[NB_TRACK+1] = (ia/2+(ib/2)*5 +(ic/2)*25)*8 + ia%2 + (ib%2)*2 + (ic%2)*4; */
+
+ indx[NB_TRACK_MR102+1] =
+ compress10(
+ pos_indx[2],
+ pos_indx[6],
+ pos_indx[5],
+ pOverflow);
+
+ /*
+ Third index
+ if ((ib/2)%2 == 1)
+ indx[NB_TRACK+2] = ((((4-ia/2) + (ib/2)*5)*32+12)/25)*4 + ia%2 + (ib%2)*2;
+ else
+ indx[NB_TRACK+2] = ((((ia/2) + (ib/2)*5)*32+12)/25)*4 + ia%2 + (ib%2)*2;
+ */
+
+ ib = pos_indx[7] >> 1;
+
+ ib &= 1;
+
+ ia = pos_indx[3] >> 1;
+
+ if (ib == 1)
+ {
+ ia = 4 - ia;
+ }
+
+ ib = pos_indx[7] >> 1;
+
+ tempWord32 = ((Word32) ib * 5) << 1;
+
+ tempWord32 = tempWord32 >> 1;
+
+ ib = (Word16) tempWord32;
+
+ ib += ia;
+
+ ib <<= 5;
+
+ ib += 12;
+
+ ic = (Word16)(((Word32) ib * 1311) >> 15);
+
+ ic <<= 2;
+
+ ia = pos_indx[3] & 1;
+
+ ib = ((Word16)(pos_indx[7] & 1)) << 1;
+
+ ib += ic;
+
+ ib += ia;
+
+ indx[NB_TRACK_MR102+2] = ib;
+
+} /* compress_code */
+
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: code_8i40_31bits()
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ x Array of type Word16 -- target vector
+ cn Array of type Word16 -- residual after long term prediction
+ h Array of type Word16 -- impulse response of weighted synthesis filter
+
+
+ Outputs:
+ cod Array of type Word16 -- algebraic (fixed) codebook excitation
+ y Array of type Word16 -- filtered fixed codebook excitation
+ indx Array of type Word16 -- index of 8 pulses (signs+positions)
+ pOverflow Pointer to Flag -- set when overflow occurs
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ FUNCTION:
+
+ PURPOSE: Searches a 31 bit algebraic codebook containing 8 pulses
+ in a frame of 40 samples.
+
+ DESCRIPTION:
+ The code contains 8 nonzero pulses: i0...i7.
+ All pulses can have two possible amplitudes: +1 or -1.
+ The 40 positions in a subframe are divided into 4 tracks of
+ interleaved positions. Each track contains two pulses.
+ The pulses can have the following possible positions:
+
+ i0, i4 : 0, 4, 8, 12, 16, 20, 24, 28, 32, 36
+ i1, i5 : 1, 5, 9, 13, 17, 21, 25, 29, 33, 37
+ i2, i6 : 2, 6, 10, 14, 18, 22, 26, 30, 34, 38
+ i3, i7 : 3, 7, 11, 15, 19, 23, 27, 31, 35, 39
+
+ Each pair of pulses require 1 bit for their signs. The positions
+ are encoded together 3,3 and 2 resulting in
+ (7+3) + (7+3) + (5+2) bits for their
+ positions. This results in a 31 (4 sign and 27 pos) bit codebook.
+ The function determines the optimal pulse signs and positions, builds
+ the codevector, and computes the filtered codevector.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] c8_31pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void code_8i40_31bits(
+ Word16 x[], /* i : target vector */
+ Word16 cn[], /* i : residual after long term prediction */
+ Word16 h[], /* i : impulse response of weighted synthesis
+ filter */
+ Word16 cod[], /* o : algebraic (fixed) codebook excitation */
+ Word16 y[], /* o : filtered fixed codebook excitation */
+ Word16 indx[], /* o : 7 Word16, index of 8 pulses (signs+positions) */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+)
+{
+ Word16 ipos[NB_PULSE];
+ Word16 pos_max[NB_TRACK_MR102];
+ Word16 codvec[NB_PULSE];
+
+ Word16 dn[L_CODE];
+ Word16 sign[L_CODE];
+
+ Word16 rr[L_CODE][L_CODE];
+ Word16 linear_signs[NB_TRACK_MR102];
+ Word16 linear_codewords[NB_PULSE];
+
+ cor_h_x2(
+ h,
+ x,
+ dn,
+ 2,
+ NB_TRACK_MR102,
+ STEP_MR102,
+ pOverflow);
+
+ /* 2 = use GSMEFR scaling */
+
+ set_sign12k2(
+ dn,
+ cn,
+ sign,
+ pos_max,
+ NB_TRACK_MR102,
+ ipos,
+ STEP_MR102,
+ pOverflow);
+
+ /* same setsign alg as GSM-EFR new constants though*/
+
+ cor_h(
+ h,
+ sign,
+ rr,
+ pOverflow);
+
+ search_10and8i40(
+ NB_PULSE,
+ STEP_MR102,
+ NB_TRACK_MR102,
+ dn,
+ rr,
+ ipos,
+ pos_max,
+ codvec,
+ pOverflow);
+
+ build_code(
+ codvec,
+ sign,
+ cod,
+ h,
+ y,
+ linear_signs,
+ linear_codewords,
+ pOverflow);
+
+ compress_code(
+ linear_signs,
+ linear_codewords,
+ indx,
+ pOverflow);
+
+} /* code_8i40_31bits */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/c8_31pf.h b/media/libstagefright/codecs/amrnb/enc/src/c8_31pf.h
new file mode 100644
index 0000000..03225ce
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/c8_31pf.h
@@ -0,0 +1,122 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/c8_31pf.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the c8_31pf.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef c8_31pf_h
+#define c8_31pf_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void code_8i40_31bits(
+ Word16 x[], /* i : target vector */
+ Word16 cn[], /* i : residual after long term prediction */
+ Word16 h[], /* i : impulse response of weighted synthesis
+ filter */
+ Word16 cod[], /* o : algebraic (fixed) codebook excitation */
+ Word16 y[], /* o : filtered fixed codebook excitation */
+ Word16 indx[], /* o : 7 Word16, index of 8 pulses (signs+positions) */
+ Flag * pOverflow /* o : Flag set when overflow occurs */
+ );
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _c8_31PF_H_ */
diff --git a/media/libstagefright/codecs/amrnb/enc/src/calc_cor.cpp b/media/libstagefright/codecs/amrnb/enc/src/calc_cor.cpp
new file mode 100644
index 0000000..db786a6
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/calc_cor.cpp
@@ -0,0 +1,267 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/calc_cor.c
+
+ Date: 06/12/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Initial Optimization
+
+ Description: Optimize code by calculating two correlation per iteration
+ of the outer loop.
+
+ Description: Delete psedocode
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Defined one local variable per line.
+
+ Description:
+ 1. Eliminated unused include file typedef.h.
+ 2. Replaced array addressing by pointers
+ 3. Unrolled loops to save extra accesses to memory
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Using inline functions from fxp_arithmetic.h for mac operations.
+
+ Description: Replacing fxp_arithmetic.h with basic_op.h.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "calc_cor.h"
+#include "basic_op.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: comp_corr
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ scal_sig = array of input samples. (Word16)
+ L_frame = length of frame used to compute pitch(Word16)
+ lag_max = maximum lag (Word16)
+ lag_min = minimum lag (Word16)
+ corr = pointer to array of correlations corresponding to the selected
+ lags. (Word32)
+
+ Outputs:
+ corr = pointer to array of correlations corresponding to the selected
+ lags. (Word32)
+
+ Returns:
+ none
+
+ Global Variables Used:
+ none
+
+ Local Variables Needed:
+ none
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function calculates all correlations of scal_sig[] in a given delay
+ range.
+
+ The correlation is given by
+
+ cor[t] = <scal_sig[n],scal_sig[n-t]>, t=lag_min,...,lag_max
+
+ The function outputs all of the correlations
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ none
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] calc_cor.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void comp_corr (
+ Word16 scal_sig[], // i : scaled signal.
+ Word16 L_frame, // i : length of frame to compute pitch
+ Word16 lag_max, // i : maximum lag
+ Word16 lag_min, // i : minimum lag
+ Word32 corr[]) // o : correlation of selected lag
+{
+ Word16 i, j;
+ Word16 *p, *p1;
+ Word32 t0;
+
+ for (i = lag_max; i >= lag_min; i--)
+ {
+ p = scal_sig;
+ p1 = &scal_sig[-i];
+ t0 = 0;
+
+ for (j = 0; j < L_frame; j++, p++, p1++)
+ {
+ t0 = L_mac (t0, *p, *p1);
+ }
+ corr[-i] = t0;
+ }
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void comp_corr(
+ Word16 scal_sig[], /* i : scaled signal. */
+ Word16 L_frame, /* i : length of frame to compute pitch */
+ Word16 lag_max, /* i : maximum lag */
+ Word16 lag_min, /* i : minimum lag */
+ Word32 corr[]) /* o : correlation of selected lag */
+{
+
+
+
+
+ /*---------------------------------------------------
+ ; lag_max and lag_min are typically negative numbers
+ -----------------------------------------------------*/
+
+
+ /* PIT_MIN_MR122 18 Minimum pitch lag (MR122 mode) */
+ /* PIT_MIN 20 Minimum pitch lag (all other modes) */
+ /* PIT_MAX 143 Maximum pitch lag */
+
+
+ Word16 i;
+ Word16 j;
+ Word16 *p;
+ Word16 *p1;
+ Word16 *p2;
+ Word16 *p_scal_sig;
+ Word32 t1;
+ Word32 t2;
+ Word32 t3;
+ Word32 t4;
+
+ corr = corr - lag_max ;
+ p_scal_sig = &scal_sig[-lag_max];
+
+ for (i = ((lag_max - lag_min) >> 2) + 1; i > 0; i--)
+ {
+ t1 = 0;
+ t2 = 0;
+ t3 = 0;
+ t4 = 0;
+ p = &scal_sig[0];
+ p1 = p_scal_sig++;
+ p_scal_sig++;
+ p2 = p_scal_sig++;
+ p_scal_sig++;
+ for (j = (L_frame >> 1); j != 0; j--)
+ {
+ t1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p), (Word32) * (p1++), t1);
+ t2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p), (Word32) * (p1), t2);
+ t3 = amrnb_fxp_mac_16_by_16bb((Word32) * (p), (Word32) * (p2++), t3);
+ t4 = amrnb_fxp_mac_16_by_16bb((Word32) * (p++), (Word32) * (p2), t4);
+
+ t1 = amrnb_fxp_mac_16_by_16bb((Word32) * (p), (Word32) * (p1++), t1);
+ t2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p), (Word32) * (p1), t2);
+ t3 = amrnb_fxp_mac_16_by_16bb((Word32) * (p), (Word32) * (p2++), t3);
+ t4 = amrnb_fxp_mac_16_by_16bb((Word32) * (p++), (Word32) * (p2), t4);
+ }
+
+ *(corr++) = t1 << 1;
+ *(corr++) = t2 << 1;
+ *(corr++) = t3 << 1;
+ *(corr++) = t4 << 1;
+
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/calc_cor.h b/media/libstagefright/codecs/amrnb/enc/src/calc_cor.h
new file mode 100644
index 0000000..d4a694b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/calc_cor.h
@@ -0,0 +1,87 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : calc_cor.h
+* Purpose : Calculate all correlations for prior the OL LTP
+*
+********************************************************************************
+*/
+#ifndef calc_cor_h
+#define calc_cor_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ ********************************************************************************
+ * DECLARATION OF PROTOTYPES
+ ********************************************************************************
+ */
+ /*************************************************************************
+ *
+ * FUNCTION: comp_corr
+ *
+ * PURPOSE: Calculate all correlations of scal_sig[] in a given delay
+ * range.
+ *
+ * DESCRIPTION:
+ * The correlation is given by
+ * cor[t] = <scal_sig[n], scal_sig[n-t]>, t=lag_min,...,lag_max
+ * The functions outputs all correlations in the given range
+ *
+ *************************************************************************/
+ void comp_corr(Word16 scal_sig[], /* i : scaled signal. */
+ Word16 L_frame, /* i : length of frame to compute pitch */
+ Word16 lag_max, /* i : maximum lag */
+ Word16 lag_min, /* i : minimum lag */
+ Word32 corr[] /* o : correlation of selected lag */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/enc/src/calc_en.cpp b/media/libstagefright/codecs/amrnb/enc/src/calc_en.cpp
new file mode 100644
index 0000000..6cf6867
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/calc_en.cpp
@@ -0,0 +1,825 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/calc_en.c
+ Funtions: calc_unfilt_energies
+ calc_filt_energies
+ calc_target_energy
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the functions that calculate the energy coefficients
+ for unfiltered and filtered excitation signals, the LTP coding gain, and
+ the target energy.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "calc_en.h"
+#include "typedef.h"
+#include "basicop_malloc.h"
+#include "l_comp.h"
+#include "cnst.h"
+#include "log2.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: calc_unfilt_energies
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ res = LP residual, buffer type Word16
+ exc = LTP excitation (unfiltered), buffer type Word16
+ code = CB innovation (unfiltered), buffer type Word16
+ gain_pit = pitch gain, type Word16
+ L_subfr = Subframe length, type Word16
+ frac_en = energy coefficients (4), fraction part, buffer type Word16
+ exp_en = energy coefficients (4), exponent part, buffer type Word16
+ ltpg = LTP coding gain (log2()), pointer to type Word16
+ pOverflow= pointer to value indicating existence of overflow (Flag)
+
+ Outputs:
+ frac_en buffer containing new fractional parts of energy coefficients
+ exp_en buffer containing new exponential parts of energy coefficients
+ ltpg points to new LTP coding gain
+ pOverflow = 1 if there is an overflow else it is zero.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function calculates several energy coefficients for unfiltered
+ excitation signals and the LTP coding gain
+
+ frac_en[0]*2^exp_en[0] = <res res> LP residual energy
+ frac_en[1]*2^exp_en[1] = <exc exc> LTP residual energy
+ frac_en[2]*2^exp_en[2] = <exc code> LTP/CB innovation dot product
+ frac_en[3]*2^exp_en[3] = <lres lres> LTP residual energy
+ (lres = res - gain_pit*exc)
+ ltpg = log2(LP_res_en / LTP_res_en)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ calc_en.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void
+calc_unfilt_energies(
+ Word16 res[], // i : LP residual, Q0
+ Word16 exc[], // i : LTP excitation (unfiltered), Q0
+ Word16 code[], // i : CB innovation (unfiltered), Q13
+ Word16 gain_pit, // i : pitch gain, Q14
+ Word16 L_subfr, // i : Subframe length
+
+ Word16 frac_en[], // o : energy coefficients (4), fraction part, Q15
+ Word16 exp_en[], // o : energy coefficients (4), exponent part, Q0
+ Word16 *ltpg // o : LTP coding gain (log2()), Q13
+)
+{
+ Word32 s, L_temp;
+ Word16 i, exp, tmp;
+ Word16 ltp_res_en, pred_gain;
+ Word16 ltpg_exp, ltpg_frac;
+
+ // Compute residual energy
+ s = L_mac((Word32) 0, res[0], res[0]);
+ for (i = 1; i < L_subfr; i++)
+ s = L_mac(s, res[i], res[i]);
+
+ // ResEn := 0 if ResEn < 200.0 (= 400 Q1)
+ if (L_sub (s, 400L) < 0)
+ {
+ frac_en[0] = 0;
+ exp_en[0] = -15;
+ }
+ else
+ {
+ exp = norm_l(s);
+ frac_en[0] = extract_h(L_shl(s, exp));
+ exp_en[0] = sub(15, exp);
+ }
+
+ // Compute ltp excitation energy
+ s = L_mac((Word32) 0, exc[0], exc[0]);
+ for (i = 1; i < L_subfr; i++)
+ s = L_mac(s, exc[i], exc[i]);
+
+ exp = norm_l(s);
+ frac_en[1] = extract_h(L_shl(s, exp));
+ exp_en[1] = sub(15, exp);
+
+ // Compute scalar product <exc[],code[]>
+ s = L_mac((Word32) 0, exc[0], code[0]);
+ for (i = 1; i < L_subfr; i++)
+ s = L_mac(s, exc[i], code[i]);
+
+ exp = norm_l(s);
+ frac_en[2] = extract_h(L_shl(s, exp));
+ exp_en[2] = sub(16-14, exp);
+
+ // Compute energy of LTP residual
+ s = 0L;
+ for (i = 0; i < L_subfr; i++)
+ {
+ L_temp = L_mult(exc[i], gain_pit);
+ L_temp = L_shl(L_temp, 1);
+ tmp = sub(res[i], pv_round(L_temp)); // LTP residual, Q0
+ s = L_mac (s, tmp, tmp);
+ }
+
+ exp = norm_l(s);
+ ltp_res_en = extract_h (L_shl (s, exp));
+ exp = sub (15, exp);
+
+ frac_en[3] = ltp_res_en;
+ exp_en[3] = exp;
+
+ // calculate LTP coding gain, i.e. energy reduction LP res -> LTP res
+ if (ltp_res_en > 0 && frac_en[0] != 0)
+ {
+ // gain = ResEn / LTPResEn
+ pred_gain = div_s (shr (frac_en[0], 1), ltp_res_en);
+ exp = sub (exp, exp_en[0]);
+
+ // L_temp = ltpGain * 2^(30 + exp)
+ L_temp = L_deposit_h (pred_gain);
+ // L_temp = ltpGain * 2^27
+ L_temp = L_shr (L_temp, add (exp, 3));
+
+ // Log2 = log2() + 27
+ Log2(L_temp, &ltpg_exp, &ltpg_frac);
+
+ // ltpg = log2(LtpGain) * 2^13 --> range: +- 4 = +- 12 dB
+ L_temp = L_Comp (sub (ltpg_exp, 27), ltpg_frac);
+ *ltpg = pv_round (L_shl (L_temp, 13)); // Q13
+ }
+ else
+ {
+ *ltpg = 0;
+ }
+}
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void calc_unfilt_energies(
+ Word16 res[], /* i : LP residual, Q0 */
+ Word16 exc[], /* i : LTP excitation (unfiltered), Q0 */
+ Word16 code[], /* i : CB innovation (unfiltered), Q13 */
+ Word16 gain_pit, /* i : pitch gain, Q14 */
+ Word16 L_subfr, /* i : Subframe length */
+
+ Word16 frac_en[], /* o : energy coefficients (4), fraction part, Q15 */
+ Word16 exp_en[], /* o : energy coefficients (4), exponent part, Q0 */
+ Word16 *ltpg, /* o : LTP coding gain (log2()), Q13 */
+ Flag *pOverflow
+)
+{
+ Word32 s1; /* Intermediate energy accumulator */
+ Word32 s2; /* Intermediate energy accumulator */
+ Word32 s3; /* Intermediate energy accumulator */
+ Word32 s4; /* Intermediate energy accumulator */
+ Word32 L_temp; /* temporal 32 bits storage */
+
+ Word16 i; /* index used in all loops */
+ Word16 exp; /* nunmber of '0's or '1's before MSB != 0 */
+ Word16 tmp1; /* temporal storage */
+ Word16 tmp2; /* temporal storage */
+ Word16 ltp_res_en;
+ Word16 pred_gain; /* predictor gain */
+ Word16 ltpg_exp; /* LTP gain (exponent) */
+ Word16 ltpg_frac; /* LTP gain (mantissa or fractional part) */
+
+ s1 = 0;
+ s2 = 0;
+ s3 = 0;
+ s4 = 0;
+
+ /*----------------------------------------------------------------------------
+ NOTE: Overflow is expected as a result of multiply and accumulated without
+ scale down the inputs. This modification is not made at this point
+ to have bit exact results with the pre-optimization code. (JT 6/20/00)
+
+ ----------------------------------------------------------------------------*/
+
+ for (i = 0; i < L_subfr; i++)
+ {
+ tmp1 = res[i]; /* avoid multiple accesses to memory */
+ tmp2 = exc[i];
+
+ s1 = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s1); /* Compute residual energy */
+ s2 = amrnb_fxp_mac_16_by_16bb((Word32) tmp2, (Word32) tmp2, s2); /* Compute ltp excitation energy */
+ s3 = amrnb_fxp_mac_16_by_16bb((Word32) tmp2, (Word32) code[i], s3);/* Compute scalar product */
+ /* <exc[],code[]> */
+
+ L_temp = L_mult(tmp2, gain_pit, pOverflow);
+ L_temp = L_shl(L_temp, 1, pOverflow);
+ tmp2 = sub(tmp1, pv_round(L_temp, pOverflow), pOverflow);
+ /* LTP residual, Q0 */
+ s4 = L_mac(s4, tmp2, tmp2, pOverflow);
+ /* Compute energy of LTP residual */
+ }
+ s1 = s1 << 1;
+ s2 = s2 << 1;
+ s3 = s3 << 1;
+
+ if (s1 & MIN_32)
+ {
+ s1 = MAX_32;
+ *pOverflow = 1;
+ }
+
+ /* ResEn := 0 if ResEn < 200.0 (= 400 Q1) */
+ if (s1 < 400L)
+ {
+ frac_en[0] = 0;
+ exp_en[0] = -15;
+ }
+ else
+ {
+ exp = norm_l(s1);
+ frac_en[0] = (Word16)(L_shl(s1, exp, pOverflow) >> 16);
+ exp_en[0] = (15 - exp);
+ }
+
+ if (s2 & MIN_32)
+ {
+ s2 = MAX_32;
+ *pOverflow = 1;
+ }
+
+ exp = norm_l(s2);
+ frac_en[1] = (Word16)(L_shl(s2, exp, pOverflow) >> 16);
+ exp_en[1] = sub(15, exp, pOverflow);
+
+ /* s3 is not always sum of squares */
+ exp = norm_l(s3);
+ frac_en[2] = (Word16)(L_shl(s3, exp, pOverflow) >> 16);
+ exp_en[2] = 2 - exp;
+
+ exp = norm_l(s4);
+ ltp_res_en = (Word16)(L_shl(s4, exp, pOverflow) >> 16);
+ exp = sub(15, exp, pOverflow);
+
+ frac_en[3] = ltp_res_en;
+ exp_en[3] = exp;
+
+ /* calculate LTP coding gain, i.e. energy reduction LP res -> LTP res */
+
+ if (ltp_res_en > 0 && frac_en[0] != 0)
+ {
+ /* gain = ResEn / LTPResEn */
+ pred_gain = div_s(shr(frac_en[0], 1, pOverflow), ltp_res_en);
+ exp = sub(exp, exp_en[0], pOverflow);
+
+ /* L_temp = ltpGain * 2^(30 + exp) */
+ L_temp = (Word32) pred_gain << 16;
+ /* L_temp = ltpGain * 2^27 */
+ L_temp = L_shr(L_temp, (Word16)(exp + 3), pOverflow);
+
+ /* Log2 = log2() + 27 */
+ Log2(L_temp, &ltpg_exp, &ltpg_frac, pOverflow);
+
+ /* ltpg = log2(LtpGain) * 2^13 --> range: +- 4 = +- 12 dB */
+ L_temp = L_Comp(sub(ltpg_exp, 27, pOverflow), ltpg_frac, pOverflow);
+ *ltpg = pv_round(L_shl(L_temp, 13, pOverflow), pOverflow); /* Q13 */
+ }
+ else
+ {
+ *ltpg = 0;
+ }
+
+ return;
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: calc_filt_energies
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ mode = coder mode, type Mode
+ xn = LTP target vector, buffer type Word16
+ xn2 = CB target vector, buffer type Word16
+ y1 = Adaptive codebook, buffer type Word16
+ Y2 = Filtered innovative vector, buffer type Word16
+ g_coeff = Correlations <xn y1> <y1 y1>
+ computed in G_pitch() buffer type Word16
+ frac_coeff = energy coefficients (5), fraction part, buffer type Word16
+ exp_coeff = energy coefficients (5), exponent part, buffer type Word16
+ cod_gain_frac = optimum codebook gain (fraction part), pointer type Word16
+ cod_gain_exp = optimum codebook gain (exponent part), pointer type Word16
+ pOverflow = pointer to overflow indicator (Flag)
+
+ Outputs:
+ frac_coeff contains new fraction part energy coefficients
+ exp_coeff contains new exponent part energy coefficients
+ cod_gain_frac points to the new optimum codebook gain (fraction part)
+ cod_gain_exp points to the new optimum codebook gain (exponent part)
+ pOverflow = 1 if there is an overflow else it is zero.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function calculates several energy coefficients for filtered
+ excitation signals
+
+ Compute coefficients need for the quantization and the optimum
+ codebook gain gcu (for MR475 only).
+
+ coeff[0] = y1 y1
+ coeff[1] = -2 xn y1
+ coeff[2] = y2 y2
+ coeff[3] = -2 xn y2
+ coeff[4] = 2 y1 y2
+
+ gcu = <xn2, y2> / <y2, y2> (0 if <xn2, y2> <= 0)
+
+ Product <y1 y1> and <xn y1> have been computed in G_pitch() and
+ are in vector g_coeff[].
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ calc_en.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void
+calc_filt_energies(
+ enum Mode mode, // i : coder mode
+ Word16 xn[], // i : LTP target vector, Q0
+ Word16 xn2[], // i : CB target vector, Q0
+ Word16 y1[], // i : Adaptive codebook, Q0
+ Word16 Y2[], // i : Filtered innovative vector, Q12
+ Word16 g_coeff[], // i : Correlations <xn y1> <y1 y1>
+ // computed in G_pitch()
+
+ Word16 frac_coeff[],// o : energy coefficients (5), fraction part, Q15
+ Word16 exp_coeff[], // o : energy coefficients (5), exponent part, Q0
+ Word16 *cod_gain_frac,// o: optimum codebook gain (fraction part), Q15
+ Word16 *cod_gain_exp // o: optimum codebook gain (exponent part), Q0
+)
+{
+ Word32 s, ener_init;
+ Word16 i, exp, frac;
+ Word16 y2[L_SUBFR];
+
+ if (sub(mode, MR795) == 0 || sub(mode, MR475) == 0)
+ {
+ ener_init = 0L;
+ }
+ else
+ {
+ ener_init = 1L;
+ }
+
+ for (i = 0; i < L_SUBFR; i++) {
+ y2[i] = shr(Y2[i], 3);
+ }
+
+ frac_coeff[0] = g_coeff[0];
+ exp_coeff[0] = g_coeff[1];
+ frac_coeff[1] = negate(g_coeff[2]); // coeff[1] = -2 xn y1
+ exp_coeff[1] = add(g_coeff[3], 1);
+
+
+ // Compute scalar product <y2[],y2[]>
+
+ s = L_mac(ener_init, y2[0], y2[0]);
+ for (i = 1; i < L_SUBFR; i++)
+ s = L_mac(s, y2[i], y2[i]);
+
+ exp = norm_l(s);
+ frac_coeff[2] = extract_h(L_shl(s, exp));
+ exp_coeff[2] = sub(15 - 18, exp);
+
+ // Compute scalar product -2*<xn[],y2[]>
+
+ s = L_mac(ener_init, xn[0], y2[0]);
+ for (i = 1; i < L_SUBFR; i++)
+ s = L_mac(s, xn[i], y2[i]);
+
+ exp = norm_l(s);
+ frac_coeff[3] = negate(extract_h(L_shl(s, exp)));
+ exp_coeff[3] = sub(15 - 9 + 1, exp);
+
+
+ // Compute scalar product 2*<y1[],y2[]>
+
+ s = L_mac(ener_init, y1[0], y2[0]);
+ for (i = 1; i < L_SUBFR; i++)
+ s = L_mac(s, y1[i], y2[i]);
+
+ exp = norm_l(s);
+ frac_coeff[4] = extract_h(L_shl(s, exp));
+ exp_coeff[4] = sub(15 - 9 + 1, exp);
+
+ if (sub(mode, MR475) == 0 || sub(mode, MR795) == 0)
+ {
+ // Compute scalar product <xn2[],y2[]>
+
+ s = L_mac(ener_init, xn2[0], y2[0]);
+ for (i = 1; i < L_SUBFR; i++)
+ s = L_mac(s, xn2[i], y2[i]);
+
+ exp = norm_l(s);
+ frac = extract_h(L_shl(s, exp));
+ exp = sub(15 - 9, exp);
+
+
+ if (frac <= 0)
+ {
+ *cod_gain_frac = 0;
+ *cod_gain_exp = 0;
+ }
+ else
+ {
+ //
+ gcu = <xn2, y2> / c[2]
+ = (frac>>1)/frac[2] * 2^(exp+1-exp[2])
+ = div_s(frac>>1, frac[2])*2^-15 * 2^(exp+1-exp[2])
+ = div_s * 2^(exp-exp[2]-14)
+
+ *cod_gain_frac = div_s (shr (frac,1), frac_coeff[2]);
+ *cod_gain_exp = sub (sub (exp, exp_coeff[2]), 14);
+
+ }
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void calc_filt_energies(
+ enum Mode mode, /* i : coder mode */
+ Word16 xn[], /* i : LTP target vector, Q0 */
+ Word16 xn2[], /* i : CB target vector, Q0 */
+ Word16 y1[], /* i : Adaptive codebook, Q0 */
+ Word16 Y2[], /* i : Filtered innovative vector, Q12 */
+ Word16 g_coeff[], /* i : Correlations <xn y1> <y1 y1> */
+ /* computed in G_pitch() */
+ Word16 frac_coeff[], /* o : energy coefficients (5), fraction part, Q15 */
+ Word16 exp_coeff[], /* o : energy coefficients (5), exponent part, Q0 */
+ Word16 *cod_gain_frac, /* o : optimum codebook gain (fraction part),Q15 */
+ Word16 *cod_gain_exp, /* o : optimum codebook gain (exponent part), Q0 */
+ Flag *pOverflow
+)
+{
+ Word32 s1; /* Intermediate energy accumulator */
+ Word32 s2; /* Intermediate energy accumulator */
+ Word32 s3; /* Intermediate energy accumulator */
+
+ Word16 i; /* index used in all loops */
+ Word16 exp; /* number of '0's or '1's before MSB != 0 */
+ Word16 frac; /* fractional part */
+ Word16 tmp; /* temporal storage */
+ Word16 scaled_y2[L_SUBFR];
+
+
+ frac_coeff[0] = g_coeff[0];
+ exp_coeff[0] = g_coeff[1];
+ frac_coeff[1] = negate(g_coeff[2]); /* coeff[1] = -2 xn y1 */
+ exp_coeff[1] = add(g_coeff[3], 1, pOverflow);
+
+ if ((mode == MR795) || (mode == MR475))
+ {
+ s1 = 0L;
+ s2 = 0L;
+ s3 = 0L;
+ }
+ else
+ {
+ s1 = 1L;
+ s2 = 1L;
+ s3 = 1L;
+ }
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ /* avoid multiple accesses to memory */
+ tmp = (Y2[i] >> 3);
+ scaled_y2[i] = tmp;
+
+ /* Compute scalar product <scaled_y2[],scaled_y2[]> */
+ s1 = L_mac(s1, tmp, tmp, pOverflow);
+
+ /* Compute scalar product -2*<xn[],scaled_y2[]> */
+ s2 = L_mac(s2, xn[i], tmp, pOverflow);
+
+ /* Compute scalar product 2*<y1[],scaled_y2[]> */
+ s3 = L_mac(s3, y1[i], tmp, pOverflow);
+ }
+
+ exp = norm_l(s1);
+ frac_coeff[2] = (Word16)(L_shl(s1, exp, pOverflow) >> 16);
+ exp_coeff[2] = (-3 - exp);
+
+ exp = norm_l(s2);
+ frac_coeff[3] = negate((Word16)(L_shl(s2, exp, pOverflow) >> 16));
+ exp_coeff[3] = (7 - exp);
+
+ exp = norm_l(s3);
+ frac_coeff[4] = (Word16)(L_shl(s3, exp, pOverflow) >> 16);
+ exp_coeff[4] = sub(7, exp, pOverflow);
+
+
+ if ((mode == MR795) || (mode == MR475))
+ {
+ /* Compute scalar product <xn2[],scaled_y2[]> */
+ s1 = 0L;
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ s1 = amrnb_fxp_mac_16_by_16bb((Word32) xn2[i], (Word32)scaled_y2[i], s1);
+ }
+
+ s1 = s1 << 1;
+
+ exp = norm_l(s1);
+ frac = (Word16)(L_shl(s1, exp, pOverflow) >> 16);
+ exp = (6 - exp);
+
+ if (frac <= 0)
+ {
+ *cod_gain_frac = 0;
+ *cod_gain_exp = 0;
+ }
+ else
+ {
+ /*
+ gcu = <xn2, scaled_y2> / c[2]
+ = (frac>>1)/frac[2] * 2^(exp+1-exp[2])
+ = div_s(frac>>1, frac[2])*2^-15 * 2^(exp+1-exp[2])
+ = div_s * 2^(exp-exp[2]-14)
+ */
+ *cod_gain_frac = div_s(shr(frac, 1, pOverflow), frac_coeff[2]);
+ *cod_gain_exp = ((exp - exp_coeff[2]) - 14);
+ }
+ }
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: calc_target_energy
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ xn = LTP target vector, buffer to type Word16 Q0
+ en_exp = optimum codebook gain (exponent part) pointer to type Word16
+ en_frac = optimum codebook gain (fraction part) pointer to type Word16
+ pOverflow = pointer to overflow indicator (Flag)
+
+ Outputs:
+ en_exp points to new optimum codebook gain (exponent part)
+ en_frac points to new optimum codebook gain (fraction part)
+ pOverflow = 1 if there is an overflow else it is zero.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function calculates the target energy using the formula,
+ en = <xn, xn>
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ calc_en.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void
+calc_target_energy(
+ Word16 xn[], // i: LTP target vector, Q0
+ Word16 *en_exp, // o: optimum codebook gain (exponent part), Q0
+ Word16 *en_frac // o: optimum codebook gain (fraction part), Q15
+)
+{
+ Word32 s;
+ Word16 i, exp;
+
+ // Compute scalar product <xn[], xn[]>
+ s = L_mac(0L, xn[0], xn[0]);
+ for (i = 1; i < L_SUBFR; i++)
+ s = L_mac(s, xn[i], xn[i]);
+
+ // s = SUM 2*xn(i) * xn(i) = <xn xn> * 2
+ exp = norm_l(s);
+ *en_frac = extract_h(L_shl(s, exp));
+ *en_exp = sub(16, exp);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void calc_target_energy(
+ Word16 xn[], /* i: LTP target vector, Q0 */
+ Word16 *en_exp, /* o: optimum codebook gain (exponent part), Q0 */
+ Word16 *en_frac, /* o: optimum codebook gain (fraction part), Q15 */
+ Flag *pOverflow
+)
+{
+ Word32 s; /* Intermediate energy accumulator */
+ Word16 i; /* index used in all loops */
+ Word16 exp;
+
+ /* Compute scalar product <xn[], xn[]> */
+ s = 0;
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ s = amrnb_fxp_mac_16_by_16bb((Word32) xn[i], (Word32) xn[i], s);
+ }
+
+ if (s < 0)
+ {
+ *pOverflow = 1;
+ s = MAX_32;
+ }
+
+ /* s = SUM 2*xn(i) * xn(i) = <xn xn> * 2 */
+ exp = norm_l(s);
+ *en_frac = (Word16)(L_shl(s, exp, pOverflow) >> 16);
+ *en_exp = (16 - exp);
+
+ return;
+}
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/calc_en.h b/media/libstagefright/codecs/amrnb/enc/src/calc_en.h
new file mode 100644
index 0000000..052f5b4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/calc_en.h
@@ -0,0 +1,192 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/c_g_aver.h
+
+ Date: 12/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : calc_en.h
+ Purpose : calculation of energy coefficients for quantizers
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _CALC_EN_H_
+#define _CALC_EN_H_
+#define calc_en_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ /*
+ * FUNCTION: calc_unfilt_energies
+ *
+ * PURPOSE: calculation of several energy coefficients for unfiltered
+ * excitation signals and the LTP coding gain
+ *
+ * frac_en[0]*2^exp_en[0] = <res res> // LP residual energy
+ * frac_en[1]*2^exp_en[1] = <exc exc> // LTP residual energy
+ * frac_en[2]*2^exp_en[2] = <exc code> // LTP/CB innovation dot product
+ * frac_en[3]*2^exp_en[3] = <lres lres> // LTP residual energy
+ * // (lres = res - gain_pit*exc)
+ * ltpg = log2(LP_res_en / LTP_res_en)
+ */
+ void
+ calc_unfilt_energies(
+ Word16 res[], /* i : LP residual, Q0 */
+ Word16 exc[], /* i : LTP excitation (unfiltered), Q0 */
+ Word16 code[], /* i : CB innovation (unfiltered), Q13 */
+ Word16 gain_pit, /* i : pitch gain, Q14 */
+ Word16 L_subfr, /* i : Subframe length */
+
+ Word16 frac_en[], /* o : energy coefficients (3), fraction part, Q15 */
+ Word16 exp_en[], /* o : energy coefficients (3), exponent part, Q0 */
+ Word16 *ltpg, /* o : LTP coding gain (log2()), Q13 */
+ Flag *pOverflow
+ );
+
+ /*
+ * FUNCTION: calc_filt_energies
+ *
+ * PURPOSE: calculation of several energy coefficients for filtered
+ * excitation signals
+ *
+ * Compute coefficients need for the quantization and the optimum
+ * codebook gain gcu (for MR475 only).
+ *
+ * coeff[0] = y1 y1
+ * coeff[1] = -2 xn y1
+ * coeff[2] = y2 y2
+ * coeff[3] = -2 xn y2
+ * coeff[4] = 2 y1 y2
+ *
+ *
+ * gcu = <xn2, y2> / <y2, y2> (0 if <xn2, y2> <= 0)
+ *
+ * Product <y1 y1> and <xn y1> have been computed in G_pitch() and
+ * are in vector g_coeff[].
+ */
+ void
+ calc_filt_energies(
+ enum Mode mode, /* i : coder mode */
+ Word16 xn[], /* i : LTP target vector, Q0 */
+ Word16 xn2[], /* i : CB target vector, Q0 */
+ Word16 y1[], /* i : Adaptive codebook, Q0 */
+ Word16 Y2[], /* i : Filtered innovative vector, Q12 */
+ Word16 g_coeff[], /* i : Correlations <xn y1> <y1 y1> */
+ /* computed in G_pitch() */
+
+ Word16 frac_coeff[],/* o : energy coefficients (5), fraction part, Q15 */
+ Word16 exp_coeff[], /* o : energy coefficients (5), exponent part, Q0 */
+ Word16 *cod_gain_frac,/* o: optimum codebook gain (fraction part), Q15 */
+ Word16 *cod_gain_exp, /* o: optimum codebook gain (exponent part), Q0 */
+ Flag *pOverflow
+ );
+
+ /*
+ * FUNCTION: calc_target_energy
+ *
+ * PURPOSE: calculation of target energy
+ *
+ * en = <xn, xn>
+ */
+ void
+ calc_target_energy(
+ Word16 xn[], /* i: LTP target vector, Q0 */
+ Word16 *en_exp, /* o: optimum codebook gain (exponent part), Q0 */
+ Word16 *en_frac, /* o: optimum codebook gain (fraction part), Q15 */
+ Flag *pOverflow
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CALC_EN_H_ */
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cbsearch.cpp b/media/libstagefright/codecs/amrnb/enc/src/cbsearch.cpp
new file mode 100644
index 0000000..a02b891
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/cbsearch.cpp
@@ -0,0 +1,392 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/cbsearch.c
+ Functions: D_plsf_3
+
+ Date: 01/31/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ (1) Removed "count.h" and "basic_op.h" and replaced with individual include
+ files (add.h, sub.h, etc.)
+ (2) Added pOverflow parameter to code_10i40_35bits()
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+ ------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ x[] -- array of type Word16 -- target vector, Q0
+ h[] -- array of type Word16 -- impulse response of weighted synthesis
+ filter h[-L_subfr..-1] must be set to
+ zero. Q12
+ T0 -- Word16 -- Pitch lag
+ pitch_sharp -- Word16 -- Last quantized pitch gain, Q14
+ gain_pit -- Word16 gain_pit -- Pitch gain, Q14
+ res2[] -- array of type Word16 -- Long term prediction residual, Q0
+ mode -- enum Mode -- coder mode
+ subNr -- Word16 -- subframe number
+
+ Outputs:
+ code[] -- array of type Word16 -- Innovative codebook, Q13
+ y[] -- array of type Word16 -- filtered fixed codebook excitation
+ Q12
+
+ anap -- Double pointer to Word16 -- Signs of the pulses
+
+
+ pOverflow -- pointer to Flag -- Flag set when overflow occurs
+
+ Returns:
+ Zero
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose : Inovative codebook search (find index and gain)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ cbsearch.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "cbsearch.h"
+
+#include "typedef.h"
+#include "c2_9pf.h"
+#include "c2_11pf.h"
+#include "c3_14pf.h"
+#include "c4_17pf.h"
+#include "c8_31pf.h"
+#include "c1035pf.h"
+#include "mode.h"
+#include "basic_op.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void cbsearch(Word16 x[], /* i : target vector, Q0 */
+ Word16 h[], /* i : impulse response of weighted synthesis*/
+ /* filter h[-L_subfr..-1] must be set to */
+ /* zero. Q12 */
+ Word16 T0, /* i : Pitch lag */
+ Word16 pitch_sharp,/* i : Last quantized pitch gain, Q14 */
+ Word16 gain_pit, /* i : Pitch gain, Q14 */
+ Word16 res2[], /* i : Long term prediction residual, Q0 */
+ Word16 code[], /* o : Innovative codebook, Q13 */
+ Word16 y[], /* o : filtered fixed codebook excitation */
+ /* Q12 */
+ Word16 **anap, /* o : Signs of the pulses */
+ enum Mode mode, /* i : coder mode */
+ Word16 subNr, /* i : subframe number */
+ Flag *pOverflow) /* o : Flag set when overflow occurs */
+{
+ Word16 index;
+ Word16 i;
+ Word16 temp;
+ Word16 pit_sharpTmp;
+
+ /* For MR74, the pre and post CB pitch sharpening is included in the
+ * codebook search routine, while for MR122 is it not.
+ */
+
+ if ((mode == MR475) || (mode == MR515))
+ {
+ /* MR475, MR515 */
+ *(*anap)++ =
+ code_2i40_9bits(
+ subNr,
+ x,
+ h,
+ T0,
+ pitch_sharp,
+ code,
+ y,
+ &index,
+ pOverflow);
+
+ *(*anap)++ = index; /* sign index */
+ }
+ else if (mode == MR59)
+ { /* MR59 */
+ *(*anap)++ =
+ code_2i40_11bits(
+ x,
+ h,
+ T0,
+ pitch_sharp,
+ code,
+ y,
+ &index,
+ pOverflow);
+
+ *(*anap)++ = index; /* sign index */
+ }
+ else if (mode == MR67)
+ { /* MR67 */
+ *(*anap)++ =
+ code_3i40_14bits(
+ x,
+ h,
+ T0,
+ pitch_sharp,
+ code,
+ y,
+ &index,
+ pOverflow);
+
+ *(*anap)++ = index; /* sign index */
+ }
+ else if ((mode == MR74) || (mode == MR795))
+ { /* MR74, MR795 */
+ *(*anap)++ =
+ code_4i40_17bits(
+ x,
+ h,
+ T0,
+ pitch_sharp,
+ code,
+ y,
+ &index,
+ pOverflow);
+
+ *(*anap)++ = index; /* sign index */
+ }
+ else if (mode == MR102)
+ { /* MR102 */
+ /*-------------------------------------------------------------*
+ * - include pitch contribution into impulse resp. h1[] *
+ *-------------------------------------------------------------*/
+ /* pit_sharpTmp = pit_sharp; */
+ /* if (pit_sharpTmp > 1.0) pit_sharpTmp = 1.0; */
+
+ pit_sharpTmp =
+ shl(
+ pitch_sharp,
+ 1,
+ pOverflow);
+
+ for (i = T0; i < L_SUBFR; i++)
+ {
+ temp =
+ mult(
+ h[i - T0],
+ pit_sharpTmp,
+ pOverflow);
+
+ h[i] =
+ add(
+ h[i],
+ temp,
+ pOverflow);
+ }
+
+ /*--------------------------------------------------------------*
+ * - Innovative codebook search (find index and gain) *
+ *--------------------------------------------------------------*/
+ code_8i40_31bits(
+ x,
+ res2,
+ h,
+ code,
+ y,
+ *anap,
+ pOverflow);
+
+ *anap += 7;
+
+ /*-------------------------------------------------------*
+ * - Add the pitch contribution to code[]. *
+ *-------------------------------------------------------*/
+ for (i = T0; i < L_SUBFR; i++)
+ {
+ temp =
+ mult(
+ code[i - T0],
+ pit_sharpTmp,
+ pOverflow);
+
+ code[i] =
+ add(
+ code[i],
+ temp,
+ pOverflow);
+ }
+ }
+ else
+ { /* MR122 */
+ /*-------------------------------------------------------------*
+ * - include pitch contribution into impulse resp. h1[] *
+ *-------------------------------------------------------------*/
+
+ /* pit_sharpTmp = gain_pit; */
+ /* if (pit_sharpTmp > 1.0) pit_sharpTmp = 1.0; */
+
+ pit_sharpTmp = shl(gain_pit, 1, pOverflow);
+
+ for (i = T0; i < L_SUBFR; i++)
+ {
+ temp = ((Word32)h[i - T0] * pit_sharpTmp) >> 15;
+ /*
+ mult(
+ h[i - T0],
+ ,
+ pOverflow);
+ */
+ h[i] =
+ add(
+ h[i],
+ temp,
+ pOverflow);
+ }
+ /*--------------------------------------------------------------*
+ * - Innovative codebook search (find index and gain) *
+ *--------------------------------------------------------------*/
+
+ code_10i40_35bits(
+ x,
+ res2,
+ h,
+ code,
+ y,
+ *anap,
+ pOverflow);
+
+ *anap += 10;
+
+ /*-------------------------------------------------------*
+ * - Add the pitch contribution to code[]. *
+ *-------------------------------------------------------*/
+ for (i = T0; i < L_SUBFR; i++)
+ {
+ temp =
+ mult(
+ code[i - T0],
+ pit_sharpTmp,
+ pOverflow);
+
+ code[i] =
+ add(
+ code[i],
+ temp,
+ pOverflow);
+ }
+ }
+
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cbsearch.h b/media/libstagefright/codecs/amrnb/enc/src/cbsearch.h
new file mode 100644
index 0000000..46d149b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/cbsearch.h
@@ -0,0 +1,136 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/dec_lag3.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the cbsearch.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef cbsearch_h
+#define cbsearch_h "$Id $"
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void cbsearch(Word16 x[], /* i : target vector, Q0 */
+ Word16 h[], /* i : impulse response of weighted synthesis */
+ /* filter h[-L_subfr..-1] must be set to */
+ /* zero. Q12 */
+ Word16 T0, /* i : Pitch lag */
+ Word16 pitch_sharp, /* i : Last quantized pitch gain, Q14 */
+ Word16 gain_pit,/* i : Pitch gain, Q14 */
+ Word16 res2[], /* i : Long term prediction residual, Q0 */
+ Word16 code[], /* o : Innovative codebook, Q13 */
+ Word16 y[], /* o : filtered fixed codebook excitation, Q12 */
+ Word16 **anap, /* o : Signs of the pulses */
+ enum Mode mode, /* i : coder mode */
+ Word16 subNr, /* i : subframe number */
+ Flag *pOverflow /* o : Flag set when overflow occurs */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CBSEARCH_H_ */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cl_ltp.cpp b/media/libstagefright/codecs/amrnb/enc/src/cl_ltp.cpp
new file mode 100644
index 0000000..4a05327
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/cl_ltp.cpp
@@ -0,0 +1,763 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/cl_ltp.c
+ Funtions: cl_ltp_init
+ cl_ltp_reset
+ cl_ltp_exit
+ cl_ltp
+
+ Date: 06/07/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed into PV template and optimized.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Removed basic_op.h and oper_32b.h in the include section, and
+ added basicop_malloc.h.
+
+ Description: Fixed typecasting issue in TI C compiler.
+
+ Description: Added pOverflow parameter -- fixed minor template problem.
+
+ Description:
+ 1. Eliminated unused include file typedef.h.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated if-else checks for saturation
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains functions that perform closed-loop fractional pitch
+ search.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+
+#include "cl_ltp.h"
+#include "basicop_malloc.h"
+#include "cnst.h"
+#include "convolve.h"
+#include "g_pitch.h"
+#include "pred_lt.h"
+#include "pitch_fr.h"
+#include "enc_lag3.h"
+#include "enc_lag6.h"
+#include "q_gain_p.h"
+#include "ton_stab.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: cl_ltp_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = Pointer to a pointer to a clLtpState structure
+
+ Outputs:
+ state points to the newly created clLtpState structure.
+
+ Returns:
+ This function returns 0 upon success and -1 upon failure.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Allocates state memory and initializes state memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ cl_ltp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int cl_ltp_init (clLtpState **state)
+{
+ clLtpState* s;
+
+ if (state == (clLtpState **) NULL){
+ fprintf(stderr, "cl_ltp_init: invalid parameter\n");
+ return -1;
+ }
+ *state = NULL;
+
+ // allocate memory
+ if ((s= (clLtpState *) malloc(sizeof(clLtpState))) == NULL){
+ fprintf(stderr, "cl_ltp_init: can not malloc state structure\n");
+ return -1;
+ }
+
+ // init the sub state
+ if (Pitch_fr_init(&s->pitchSt)) {
+ cl_ltp_exit(&s);
+ return -1;
+ }
+
+ cl_ltp_reset(s);
+
+ *state = s;
+
+ return 0;
+}
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 cl_ltp_init(clLtpState **state)
+{
+ clLtpState* s;
+
+ if (state == (clLtpState **) NULL)
+ {
+ /*fprint(stderr, "cl_ltp_init: invalid parameter\n");*/
+ return(-1);
+ }
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (clLtpState *) malloc(sizeof(clLtpState))) == NULL)
+ {
+ /*fprint(stderr, "cl_ltp_init: can not malloc state structure\n");*/
+ return(-1);
+ }
+
+ /* init the sub state */
+ if (Pitch_fr_init(&s->pitchSt))
+ {
+ cl_ltp_exit(&s);
+ return(-1);
+ }
+
+ cl_ltp_reset(s);
+
+ *state = s;
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: cl_ltp_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to the clLtpState structure to be reset
+
+ Outputs:
+ The state structure pointed to by clLtpState *state is reset.
+
+ Returns:
+ The function returns int 0 if successful, -1 otherwise.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Initializes state memory to zero.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ cl_ltp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+ ------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int cl_ltp_reset (clLtpState *state)
+{
+ if (state == (clLtpState *) NULL){
+ fprintf(stderr, "cl_ltp_reset: invalid parameter\n");
+ return -1;
+ }
+
+ // Reset pitch search states
+ Pitch_fr_reset (state->pitchSt);
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 cl_ltp_reset(clLtpState *state)
+{
+ if (state == (clLtpState *) NULL)
+ {
+ /*fprint(stderr, "cl_ltp_reset: invalid parameter\n"); */
+ return(-1);
+ }
+
+ /* Reset pitch search states */
+ Pitch_fr_reset(state->pitchSt);
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: cl_ltp_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ clLtpState **state = Reference to the state object to be freed.
+
+ Outputs:
+ The memory used by the structure which is pointed to by 'state'
+ is freed.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ The memory used for state memory is freed
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ cl_ltp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void cl_ltp_exit (clLtpState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ // dealloc members
+ Pitch_fr_exit(&(*state)->pitchSt);
+
+ // deallocate memory
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void cl_ltp_exit(clLtpState **state)
+{
+ if (state == NULL || *state == NULL)
+ {
+ return;
+ }
+
+ /* dealloc members */
+ Pitch_fr_exit(&(*state)->pitchSt);
+
+ /* deallocate memory */
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: cl_ltp
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ clSt = pointer to the clLtpState struct
+ tonSt = pointer to the tonStabState structure
+ mode = codec mode value, of type enum Mode
+ frameOffset = offset to subframe (Word16)
+ T_op = pointer to buffer of open loop pitch lags (Word16)
+ h1 = pointer to impulse response vector (Word16)
+ exc = pointer to excitation vector (Word16)
+ res2 = pointer to long term prediction residual (Word16)
+ xn = pointer to target vector for pitch search (Word16)
+ lsp_flag = LSP resonance flag (Word16)
+
+ Outputs:
+ clSt = pointer to the clLtpState struct
+ tonSt = pointer to the tonStabState structure
+ exc = pointer to excitation vector (Word16)
+ res2 = pointer to long term prediction residual (Word16)
+ xn2 = pointer to target vector for codebook search (Word16)
+ yl = pointer to buffer of filtered adaptive excitation (Word16)
+ T0 = pointer to pitch delay (integer part) (Word16)
+ T0_frac = pointer to pitch delay (fractional part) (Word16)
+ gain_pit = pointer to pitch gain (Word16)
+ g_coeff = pointer to array of correlations between xn, y1, & y2 (Word16)
+ anap = pointer to pointer to analysis parameters (Word16)
+ gp_limit = pointer to the pitch gain limit (Word16)
+ pOverflow = pointer to overflow indicator (Flag)
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs closed-loop fractional pitch search.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ cl_ltp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE FOR cl_ltp
+
+int cl_ltp (
+ clLtpState *clSt, // i/o : State struct
+ tonStabState *tonSt, // i/o : State struct
+ enum Mode mode, // i : coder mode
+ Word16 frameOffset, // i : Offset to subframe
+ Word16 T_op[], // i : Open loop pitch lags
+ Word16 *h1, // i : Impulse response vector Q12
+ Word16 *exc, // i/o : Excitation vector Q0
+ Word16 res2[], // i/o : Long term prediction residual Q0
+ Word16 xn[], // i : Target vector for pitch search Q0
+ Word16 lsp_flag, // i : LSP resonance flag
+ Word16 xn2[], // o : Target vector for codebook search Q0
+ Word16 y1[], // o : Filtered adaptive excitation Q0
+ Word16 *T0, // o : Pitch delay (integer part)
+ Word16 *T0_frac, // o : Pitch delay (fractional part)
+ Word16 *gain_pit, // o : Pitch gain Q14
+ Word16 g_coeff[], // o : Correlations between xn, y1, & y2
+ Word16 **anap, // o : Analysis parameters
+ Word16 *gp_limit // o : pitch gain limit
+)
+{
+ Word16 i;
+ Word16 index;
+ Word32 L_temp; // temporarily variable
+ Word16 resu3; // flag for upsample resolution
+ Word16 gpc_flag;
+
+ *----------------------------------------------------------------------*
+ * Closed-loop fractional pitch search *
+ *----------------------------------------------------------------------*
+ *T0 = Pitch_fr(clSt->pitchSt,
+ mode, T_op, exc, xn, h1,
+ L_SUBFR, frameOffset,
+ T0_frac, &resu3, &index);
+
+ *(*anap)++ = index;
+
+ *-----------------------------------------------------------------*
+ * - find unity gain pitch excitation (adapitve codebook entry) *
+ * with fractional interpolation. *
+ * - find filtered pitch exc. y1[]=exc[] convolve with h1[]) *
+ * - compute pitch gain and limit between 0 and 1.2 *
+ * - update target vector for codebook search *
+ * - find LTP residual. *
+ *-----------------------------------------------------------------*
+
+ Pred_lt_3or6(exc, *T0, *T0_frac, L_SUBFR, resu3);
+
+ Convolve(exc, h1, y1, L_SUBFR);
+
+ // gain_pit is Q14 for all modes
+ *gain_pit = G_pitch(mode, xn, y1, g_coeff, L_SUBFR);
+
+
+ // check if the pitch gain should be limit due to resonance in LPC filter
+ gpc_flag = 0;
+ *gp_limit = MAX_16;
+ if ((lsp_flag != 0) &&
+ (sub(*gain_pit, GP_CLIP) > 0))
+ {
+ gpc_flag = check_gp_clipping(tonSt, *gain_pit);
+ }
+
+ // special for the MR475, MR515 mode; limit the gain to 0.85 to
+ // cope with bit errors in the decoder in a better way.
+ if ((sub (mode, MR475) == 0) || (sub (mode, MR515) == 0)) {
+ if ( sub (*gain_pit, 13926) > 0) {
+ *gain_pit = 13926; // 0.85 in Q14
+ }
+
+ if (gpc_flag != 0) {
+ *gp_limit = GP_CLIP;
+ }
+ }
+ else
+ {
+ if (gpc_flag != 0)
+ {
+ *gp_limit = GP_CLIP;
+ *gain_pit = GP_CLIP;
+ }
+ // For MR122, gain_pit is quantized here and not in gainQuant
+ if (sub(mode, MR122)==0)
+ {
+ *(*anap)++ = q_gain_pitch(MR122, *gp_limit, gain_pit,
+ NULL, NULL);
+ }
+ }
+
+ // update target vector und evaluate LTP residual
+ for (i = 0; i < L_SUBFR; i++) {
+ L_temp = L_mult(y1[i], *gain_pit);
+ L_temp = L_shl(L_temp, 1);
+ xn2[i] = sub(xn[i], extract_h(L_temp));
+
+ L_temp = L_mult(exc[i], *gain_pit);
+ L_temp = L_shl(L_temp, 1);
+ res2[i] = sub(res2[i], extract_h(L_temp));
+ }
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void cl_ltp(
+ clLtpState *clSt, /* i/o : State struct */
+ tonStabState *tonSt, /* i/o : State struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 frameOffset, /* i : Offset to subframe */
+ Word16 T_op[], /* i : Open loop pitch lags */
+ Word16 *h1, /* i : Impulse response vector Q12 */
+ Word16 *exc, /* i/o : Excitation vector Q0 */
+ Word16 res2[], /* i/o : Long term prediction residual Q0 */
+ Word16 xn[], /* i : Target vector for pitch search Q0 */
+ Word16 lsp_flag, /* i : LSP resonance flag */
+ Word16 xn2[], /* o : Target vector for codebook search Q0 */
+ Word16 yl[], /* o : Filtered adaptive excitation Q0 */
+ Word16 *T0, /* o : Pitch delay (integer part) */
+ Word16 *T0_frac, /* o : Pitch delay (fractional part) */
+ Word16 *gain_pit, /* o : Pitch gain Q14 */
+ Word16 g_coeff[], /* o : Correlations between xn, y1, & y2 */
+ Word16 **anap, /* o : Analysis parameters */
+ Word16 *gp_limit, /* o : pitch gain limit */
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ register Word16 i;
+ Word16 index;
+ Word32 L_temp; /* temporarily variable */
+ Word16 resu3; /* flag for upsample resolution */
+ Word16 gpc_flag;
+
+ Word16 temp;
+ Word16 *p_exc;
+ Word16 *p_xn;
+ Word16 *p_xn2;
+ Word16 *p_yl;
+
+ /*----------------------------------------------------------------------*
+ * Closed-loop fractional pitch search *
+ *----------------------------------------------------------------------*/
+ *T0 =
+ Pitch_fr(
+ clSt->pitchSt,
+ mode,
+ T_op,
+ exc,
+ xn,
+ h1,
+ L_SUBFR,
+ frameOffset,
+ T0_frac,
+ &resu3,
+ &index,
+ pOverflow);
+
+ *(*anap)++ = index;
+
+ /*-----------------------------------------------------------------*
+ * - find unity gain pitch excitation (adapitve codebook entry) *
+ * with fractional interpolation. *
+ * - find filtered pitch exc. y1[]=exc[] convolve with h1[]) *
+ * - compute pitch gain and limit between 0 and 1.2 *
+ * - update target vector for codebook search *
+ * - find LTP residual. *
+ *-----------------------------------------------------------------*/
+
+ Pred_lt_3or6(
+ exc,
+ *T0,
+ *T0_frac,
+ L_SUBFR,
+ resu3,
+ pOverflow);
+
+ Convolve(exc, h1, yl, L_SUBFR);
+
+ /* gain_pit is Q14 for all modes */
+ *gain_pit =
+ G_pitch(
+ mode,
+ xn,
+ yl,
+ g_coeff,
+ L_SUBFR,
+ pOverflow);
+
+
+ /* check if the pitch gain should be limit due to resonance in LPC filter */
+ gpc_flag = 0;
+ *gp_limit = MAX_16;
+
+ if ((lsp_flag != 0) && ((Word32)(*gain_pit) > GP_CLIP))
+ {
+ gpc_flag = check_gp_clipping(tonSt, *gain_pit, pOverflow);
+ }
+
+ /* special for the MR475, MR515 mode; limit the gain to 0.85 to */
+ /* cope with bit errors in the decoder in a better way. */
+
+ if ((mode == MR475) || (mode == MR515))
+ {
+ *gain_pit = ((Word32) * gain_pit > 13926) ? 13926 : *gain_pit;
+
+ if (gpc_flag != 0)
+ {
+ *gp_limit = GP_CLIP;
+ }
+ }
+ else
+ {
+ if (gpc_flag != 0)
+ {
+ *gp_limit = GP_CLIP;
+ *gain_pit = GP_CLIP;
+ }
+ /* For MR122, gain_pit is quantized here and not in gainQuant */
+ if (mode == MR122)
+ {
+ *(*anap)++ =
+ q_gain_pitch(
+ MR122,
+ *gp_limit,
+ gain_pit,
+ NULL,
+ NULL,
+ pOverflow);
+ }
+ }
+
+
+ p_exc = &exc[0];
+ p_xn = &xn[0];
+ p_xn2 = &xn2[0];
+ p_yl = &yl[0];
+
+ temp = *gain_pit;
+
+ /* update target vector und evaluate LTP residual */
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ L_temp = ((Word32) * (p_yl++) * temp) >> 14;
+ *(p_xn2++) = *(p_xn++) - (Word16)L_temp;
+
+ L_temp = ((Word32) * (p_exc++) * temp) >> 14;
+ res2[i] -= (Word16)L_temp;
+ }
+
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cl_ltp.h b/media/libstagefright/codecs/amrnb/enc/src/cl_ltp.h
new file mode 100644
index 0000000..3e9b587
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/cl_ltp.h
@@ -0,0 +1,163 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/cl_ltp.h
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the cl_ltp.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef cl_ltp_h
+#define cl_ltp_h "$Id $"
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "pitch_fr.h"
+#include "ton_stab.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /* state variable */
+ typedef struct
+ {
+ Pitch_frState *pitchSt;
+ } clLtpState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 cl_ltp_init(clLtpState **st);
+ /* initialize one instance of the pre processing state.
+ Stores pointer to filter status struct in *st. This pointer has to
+ be passed to cl_ltp in each call.
+ returns 0 on success
+ */
+
+ Word16 cl_ltp_reset(clLtpState *st);
+ /* reset of pre processing state (i.e. set state memory to zero)
+ returns 0 on success
+ */
+ void cl_ltp_exit(clLtpState **st);
+ /* de-initialize pre processing state (i.e. free status struct)
+ stores NULL in *st
+ */
+
+ void cl_ltp(
+ clLtpState *clSt, /* i/o : State struct */
+ tonStabState *tonSt, /* i/o : State struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 frameOffset, /* i : Offset to subframe */
+ Word16 T_op[], /* i : Open loop pitch lags */
+ Word16 *h1, /* i : Impulse response vector Q12 */
+ Word16 *exc, /* i/o : Excitation vector Q0 */
+ Word16 res2[], /* i/o : Long term prediction residual Q0 */
+ Word16 xn[], /* i : Target vector for pitch search Q0 */
+ Word16 lsp_flag, /* i : LSP resonance flag */
+ Word16 xn2[], /* o : Target vector for codebook search Q0 */
+ Word16 y1[], /* o : Filtered adaptive excitation Q0 */
+ Word16 *T0, /* o : Pitch delay (integer part) */
+ Word16 *T0_frac, /* o : Pitch delay (fractional part) */
+ Word16 *gain_pit, /* o : Pitch gain Q14 */
+ Word16 g_coeff[], /* o : Correlations between xn, y1, & y2 */
+ Word16 **anap, /* o : Analysis parameters */
+ Word16 *gp_limit, /* o : pitch gain limit */
+ Flag *pOverflow /* o : overflow indicator */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CL_LTP_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cod_amr.cpp b/media/libstagefright/codecs/amrnb/enc/src/cod_amr.cpp
new file mode 100644
index 0000000..8468131
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/cod_amr.cpp
@@ -0,0 +1,1608 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/cod_amr.c
+ Funtions: cod_amr_init
+ cod_amr_reset
+ cod_amr_exit
+ cod_amr_first
+ cod_amr
+
+ Date: 06/09/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Made changes based on comments from the review meeting.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Added initialization of the overflow flag in cod_amr_init()
+ and in cod_amr_reset(). This overflow flag is now part of
+ the cod_amrState structure.
+
+ Description: Cleaned up INCLUDES. removed inclusion of basic_op.h and repeat
+ inclusion of copy.h
+
+ Description: Updated function call to dtx_enc
+
+ Description: For cod_amr_first() and cod_amr()
+ 1. Replaced copy() function with memcpy()
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ These functions comprise the main encoder routine operating on a frame basis.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+#include <string.h>
+
+#include "cod_amr.h"
+#include "typedef.h"
+#include "cnst.h"
+#include "copy.h"
+#include "qua_gain.h"
+#include "lpc.h"
+#include "lsp.h"
+#include "pre_big.h"
+#include "ol_ltp.h"
+#include "p_ol_wgh.h"
+#include "spreproc.h"
+#include "cl_ltp.h"
+#include "pred_lt.h"
+#include "spstproc.h"
+#include "cbsearch.h"
+#include "gain_q.h"
+#include "convolve.h"
+#include "ton_stab.h"
+#include "vad.h"
+#include "dtx_enc.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/* Spectral expansion factors */
+
+static const Word16 gamma1[M] =
+{
+ 30802, 28954, 27217, 25584, 24049,
+ 22606, 21250, 19975, 18777, 17650
+};
+
+/* gamma1 differs for the 12k2 coder */
+static const Word16 gamma1_12k2[M] =
+{
+ 29491, 26542, 23888, 21499, 19349,
+ 17414, 15672, 14105, 12694, 11425
+};
+
+static const Word16 gamma2[M] =
+{
+ 19661, 11797, 7078, 4247, 2548,
+ 1529, 917, 550, 330, 198
+};
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: cod_amr_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a pointer to a structure of type cod_amrState
+
+ Outputs:
+ Structure pointed to by the pointer pointed to by state is
+ initialized to its reset value
+ state points to the allocated memory
+
+ Returns:
+ Returns 0 if memory was successfully initialized,
+ otherwise returns -1.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function allocates memory and initializes state variables.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ cod_amr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int cod_amr_init (cod_amrState **state, Flag dtx)
+{
+ cod_amrState* s;
+
+ if (state == (cod_amrState **) NULL){
+ fprintf(stderr, "cod_amr_init: invalid parameter\n");
+ return -1;
+ }
+ *state = NULL;
+
+ // allocate memory
+ if ((s= (cod_amrState *) malloc(sizeof(cod_amrState))) == NULL){
+ fprintf(stderr, "cod_amr_init: can not malloc state structure\n");
+ return -1;
+ }
+
+ s->lpcSt = NULL;
+ s->lspSt = NULL;
+ s->clLtpSt = NULL;
+ s->gainQuantSt = NULL;
+ s->pitchOLWghtSt = NULL;
+ s->tonStabSt = NULL;
+ s->vadSt = NULL;
+ s->dtx_encSt = NULL;
+ s->dtx = dtx;
+
+ // Init sub states
+ if (cl_ltp_init(&s->clLtpSt) ||
+ lsp_init(&s->lspSt) ||
+ gainQuant_init(&s->gainQuantSt) ||
+ p_ol_wgh_init(&s->pitchOLWghtSt) ||
+ ton_stab_init(&s->tonStabSt) ||
+#ifndef VAD2
+ vad1_init(&s->vadSt) ||
+#else
+ vad2_init(&s->vadSt) ||
+#endif
+ dtx_enc_init(&s->dtx_encSt) ||
+ lpc_init(&s->lpcSt)) {
+ cod_amr_exit(&s);
+ return -1;
+ }
+
+ cod_amr_reset(s);
+
+ *state = s;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 cod_amr_init(cod_amrState **state, Flag dtx)
+{
+ cod_amrState* s;
+
+ if (state == (cod_amrState **) NULL)
+ {
+ /* fprint(stderr, "cod_amr_init: invalid parameter\n"); */
+ return(-1);
+ }
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (cod_amrState *) malloc(sizeof(cod_amrState))) == NULL)
+ {
+ /* fprint(stderr, "cod_amr_init:
+ can not malloc state structure\n"); */
+ return(-1);
+ }
+
+ s->lpcSt = NULL;
+ s->lspSt = NULL;
+ s->clLtpSt = NULL;
+ s->gainQuantSt = NULL;
+ s->pitchOLWghtSt = NULL;
+ s->tonStabSt = NULL;
+ s->vadSt = NULL;
+ s->dtx_encSt = NULL;
+ s->dtx = dtx;
+
+ /* Initialize overflow Flag */
+
+ s->overflow = 0;
+
+
+ /* Init sub states */
+ if (cl_ltp_init(&s->clLtpSt) ||
+ lsp_init(&s->lspSt) ||
+ gainQuant_init(&s->gainQuantSt) ||
+ p_ol_wgh_init(&s->pitchOLWghtSt) ||
+ ton_stab_init(&s->tonStabSt) ||
+#ifndef VAD2
+ vad1_init(&s->vadSt) ||
+#else
+ vad2_init(&s->vadSt) ||
+#endif
+ dtx_enc_init(&s->dtx_encSt) ||
+ lpc_init(&s->lpcSt))
+ {
+ cod_amr_exit(&s);
+ return(-1);
+ }
+
+ cod_amr_reset(s);
+
+ *state = s;
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: cod_amr_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a structure of type cod_amrState
+
+ Outputs:
+ Structure pointed to by state is initialized to initial values.
+
+ Returns:
+ Returns 0 if memory was successfully initialized,
+ otherwise returns -1.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function resets the state memory for cod_amr.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ cod_amr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int cod_amr_reset (cod_amrState *st)
+{
+ Word16 i;
+
+ if (st == (cod_amrState *) NULL){
+ fprintf(stderr, "cod_amr_reset: invalid parameter\n");
+ return -1;
+ }
+
+ *-----------------------------------------------------------------------*
+ * Initialize pointers to speech vector. *
+ *-----------------------------------------------------------------------*
+
+ st->new_speech = st->old_speech + L_TOTAL - L_FRAME; // New speech
+
+ st->speech = st->new_speech - L_NEXT; // Present frame
+
+ st->p_window = st->old_speech + L_TOTAL - L_WINDOW; // For LPC window
+ st->p_window_12k2 = st->p_window - L_NEXT; // EFR LPC window: no lookahead
+
+ // Initialize static pointers
+
+ st->wsp = st->old_wsp + PIT_MAX;
+ st->exc = st->old_exc + PIT_MAX + L_INTERPOL;
+ st->zero = st->ai_zero + MP1;
+ st->error = st->mem_err + M;
+ st->h1 = &st->hvec[L_SUBFR];
+
+ // Static vectors to zero
+
+ Set_zero(st->old_speech, L_TOTAL);
+ Set_zero(st->old_exc, PIT_MAX + L_INTERPOL);
+ Set_zero(st->old_wsp, PIT_MAX);
+ Set_zero(st->mem_syn, M);
+ Set_zero(st->mem_w, M);
+ Set_zero(st->mem_w0, M);
+ Set_zero(st->mem_err, M);
+ Set_zero(st->zero, L_SUBFR);
+ Set_zero(st->hvec, L_SUBFR); // set to zero "h1[-L_SUBFR..-1]"
+
+ // OL LTP states
+ for (i = 0; i < 5; i++)
+ {
+ st->old_lags[i] = 40;
+ }
+
+ // Reset lpc states
+ lpc_reset(st->lpcSt);
+
+ // Reset lsp states
+ lsp_reset(st->lspSt);
+
+ // Reset clLtp states
+ cl_ltp_reset(st->clLtpSt);
+
+ gainQuant_reset(st->gainQuantSt);
+
+ p_ol_wgh_reset(st->pitchOLWghtSt);
+
+ ton_stab_reset(st->tonStabSt);
+
+#ifndef VAD2
+ vad1_reset(st->vadSt);
+#else
+ vad2_reset(st->vadSt);
+#endif
+
+ dtx_enc_reset(st->dtx_encSt);
+
+ st->sharp = SHARPMIN;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 cod_amr_reset(cod_amrState *st)
+{
+ Word16 i;
+
+ if (st == (cod_amrState *) NULL)
+ {
+ /* fprint(stderr, "cod_amr_reset: invalid parameter\n"); */
+ return(-1);
+ }
+
+ /*-----------------------------------------------------------------------*
+ * Initialize pointers to speech vector. *
+ *-----------------------------------------------------------------------*/
+
+ st->new_speech = st->old_speech + L_TOTAL - L_FRAME; /* New speech */
+
+ st->speech = st->new_speech - L_NEXT; /* Present frame */
+
+ st->p_window = st->old_speech + L_TOTAL - L_WINDOW; /* For LPC window */
+ st->p_window_12k2 = st->p_window - L_NEXT; /* EFR LPC window: no lookahead */
+
+ /* Initialize static pointers */
+
+ st->wsp = st->old_wsp + PIT_MAX;
+ st->exc = st->old_exc + PIT_MAX + L_INTERPOL;
+ st->zero = st->ai_zero + MP1;
+ st->error = st->mem_err + M;
+ st->h1 = &st->hvec[L_SUBFR];
+
+ /* Initialize overflow Flag */
+
+ st->overflow = 0;
+
+ /* Static vectors to zero */
+ memset(st->old_speech, 0, sizeof(Word16)*L_TOTAL);
+ memset(st->old_exc, 0, sizeof(Word16)*(PIT_MAX + L_INTERPOL));
+ memset(st->old_wsp, 0, sizeof(Word16)*PIT_MAX);
+ memset(st->mem_syn, 0, sizeof(Word16)*M);
+ memset(st->mem_w, 0, sizeof(Word16)*M);
+ memset(st->mem_w0, 0, sizeof(Word16)*M);
+ memset(st->mem_err, 0, sizeof(Word16)*M);
+ memset(st->zero, 0, sizeof(Word16)*L_SUBFR);
+ memset(st->hvec, 0, sizeof(Word16)*L_SUBFR); /* set to zero "h1[-L_SUBFR..-1]" */
+
+ /* OL LTP states */
+ for (i = 0; i < 5; i++)
+ {
+ st->old_lags[i] = 40;
+ }
+
+ /* Reset lpc states */
+ lpc_reset(st->lpcSt);
+
+ /* Reset lsp states */
+ lsp_reset(st->lspSt);
+
+ /* Reset clLtp states */
+ cl_ltp_reset(st->clLtpSt);
+
+ gainQuant_reset(st->gainQuantSt);
+
+ p_ol_wgh_reset(st->pitchOLWghtSt);
+
+ ton_stab_reset(st->tonStabSt);
+
+#ifndef VAD2
+ vad1_reset(st->vadSt);
+#else
+ vad2_reset(st->vadSt);
+#endif
+
+ dtx_enc_reset(st->dtx_encSt);
+
+ st->sharp = SHARPMIN;
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: cod_amr_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a pointer to a structure of type cod_amrState
+
+ Outputs:
+ state points to a NULL address
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function frees the memory used for state memory.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ cod_amr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void cod_amr_exit (cod_amrState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ // dealloc members
+ lpc_exit(&(*state)->lpcSt);
+ lsp_exit(&(*state)->lspSt);
+ gainQuant_exit(&(*state)->gainQuantSt);
+ cl_ltp_exit(&(*state)->clLtpSt);
+ p_ol_wgh_exit(&(*state)->pitchOLWghtSt);
+ ton_stab_exit(&(*state)->tonStabSt);
+#ifndef VAD2
+ vad1_exit(&(*state)->vadSt);
+#else
+ vad2_exit(&(*state)->vadSt);
+#endif
+ dtx_enc_exit(&(*state)->dtx_encSt);
+
+ // deallocate memory
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void cod_amr_exit(cod_amrState **state)
+{
+ if (state == NULL || *state == NULL)
+ {
+ return;
+ }
+
+ /* dealloc members */
+ lpc_exit(&(*state)->lpcSt);
+ lsp_exit(&(*state)->lspSt);
+ gainQuant_exit(&(*state)->gainQuantSt);
+ cl_ltp_exit(&(*state)->clLtpSt);
+ p_ol_wgh_exit(&(*state)->pitchOLWghtSt);
+ ton_stab_exit(&(*state)->tonStabSt);
+#ifndef VAD2
+ vad1_exit(&(*state)->vadSt);
+#else
+ vad2_exit(&(*state)->vadSt);
+#endif
+ dtx_enc_exit(&(*state)->dtx_encSt);
+
+ /* deallocate memory */
+ free(*state); // BX
+ *state = NULL;
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: cod_amr_first
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type cod_amrState
+ new_speech = pointer to buffer of length L_FRAME that contains
+ the speech input (Word16)
+
+ Outputs:
+ The structure of type cod_amrState pointed to by st is updated.
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function copes with look-ahead and calls cod_amr.
+ No input argument are passed to this function. However, before
+ calling this function, 40 new speech data should be copied to the
+ vector new_speech[]. This is a global pointer which is declared in
+ this file (it points to the end of speech buffer minus 200).
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ cod_amr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int cod_amr_first(cod_amrState *st, // i/o : State struct
+ Word16 new_speech[]) // i : speech input (L_FRAME)
+{
+ Copy(new_speech,&st->new_speech[-L_NEXT], L_NEXT);
+ // Copy(new_speech,st->new_speech,L_FRAME);
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 cod_amr_first(cod_amrState *st, /* i/o : State struct */
+ Word16 new_speech[]) /* i : speech input (L_FRAME) */
+{
+
+ memcpy(&st->new_speech[-L_NEXT], new_speech, L_NEXT*sizeof(Word16));
+
+ /* Copy(new_speech,st->new_speech,L_FRAME); */
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: cod_amr
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type cod_amrState
+ mode = AMR mode of type enum Mode
+ new_speech = pointer to buffer of length L_FRAME that contains
+ the speech input of type Word16
+ ana = pointer to the analysis parameters of type Word16
+ usedMode = pointer to the used mode of type enum Mode
+ synth = pointer to a buffer containing the local synthesis speech of
+ type Word16
+
+ Outputs:
+ The structure of type cod_amrState pointed to by st is updated.
+ The analysis parameter buffer pointed to by ana is updated.
+ The value pointed to by usedMode is updated.
+ The local synthesis speech buffer pointed to by synth is updated.
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function is the main encoder routine. It is called every 20 ms speech
+ frame, operating on the newly read 160 speech samples. It performs the
+ principle encoding functions to produce the set of encoded parameters
+ which include the LSP, adaptive codebook, and fixed codebook
+ quantization indices (addresses and gains).
+
+ Before calling this function, 160 new speech data should be copied to the
+ vector new_speech[]. This is a global pointer which is declared in
+ this file (it points to the end of speech buffer minus 160).
+
+ The outputs of the function are:
+ ana[]: vector of analysis parameters.
+ synth[]: Local synthesis speech (for debugging purposes)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ cod_amr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int cod_amr(
+ cod_amrState *st, // i/o : State struct
+ enum Mode mode, // i : AMR mode
+ Word16 new_speech[], // i : speech input (L_FRAME)
+ Word16 ana[], // o : Analysis parameters
+ enum Mode *usedMode, // o : used mode
+ Word16 synth[] // o : Local synthesis
+)
+{
+ // LPC coefficients
+ Word16 A_t[(MP1) * 4]; // A(z) unquantized for the 4 subframes
+ Word16 Aq_t[(MP1) * 4]; // A(z) quantized for the 4 subframes
+ Word16 *A, *Aq; // Pointer on A_t and Aq_t
+ Word16 lsp_new[M];
+
+ // Other vectors
+ Word16 xn[L_SUBFR]; // Target vector for pitch search
+ Word16 xn2[L_SUBFR]; // Target vector for codebook search
+ Word16 code[L_SUBFR]; // Fixed codebook excitation
+ Word16 y1[L_SUBFR]; // Filtered adaptive excitation
+ Word16 y2[L_SUBFR]; // Filtered fixed codebook excitation
+ Word16 gCoeff[6]; // Correlations between xn, y1, & y2:
+ Word16 res[L_SUBFR]; // Short term (LPC) prediction residual
+ Word16 res2[L_SUBFR]; // Long term (LTP) prediction residual
+
+ // Vector and scalars needed for the MR475
+ Word16 xn_sf0[L_SUBFR]; // Target vector for pitch search
+ Word16 y2_sf0[L_SUBFR]; // Filtered codebook innovation
+ Word16 code_sf0[L_SUBFR]; // Fixed codebook excitation
+ Word16 h1_sf0[L_SUBFR]; // The impulse response of sf0
+ Word16 mem_syn_save[M]; // Filter memory
+ Word16 mem_w0_save[M]; // Filter memory
+ Word16 mem_err_save[M]; // Filter memory
+ Word16 sharp_save; // Sharpening
+ Word16 evenSubfr; // Even subframe indicator
+ Word16 T0_sf0 = 0; // Integer pitch lag of sf0
+ Word16 T0_frac_sf0 = 0; // Fractional pitch lag of sf0
+ Word16 i_subfr_sf0 = 0; // Position in exc[] for sf0
+ Word16 gain_pit_sf0; // Quantized pitch gain for sf0
+ Word16 gain_code_sf0; // Quantized codebook gain for sf0
+
+ // Scalars
+ Word16 i_subfr, subfrNr;
+ Word16 T_op[L_FRAME/L_FRAME_BY2];
+ Word16 T0, T0_frac;
+ Word16 gain_pit, gain_code;
+
+ // Flags
+ Word16 lsp_flag = 0; // indicates resonance in LPC filter
+ Word16 gp_limit; // pitch gain limit value
+ Word16 vad_flag; // VAD decision flag
+ Word16 compute_sid_flag; // SID analysis flag
+
+ Copy(new_speech, st->new_speech, L_FRAME);
+
+ *usedMode = mode;
+
+ // DTX processing
+ if (st->dtx)
+ { // no test() call since this if is only in simulation env
+ // Find VAD decision
+
+#ifdef VAD2
+ vad_flag = vad2 (st->new_speech, st->vadSt);
+ vad_flag = vad2 (st->new_speech+80, st->vadSt) || vad_flag;
+#else
+ vad_flag = vad1(st->vadSt, st->new_speech);
+#endif
+
+ // NB! usedMode may change here
+ compute_sid_flag = tx_dtx_handler(st->dtx_encSt,
+ vad_flag,
+ usedMode);
+ }
+ else
+ {
+ compute_sid_flag = 0;
+ }
+
+ *------------------------------------------------------------------------*
+ * - Perform LPC analysis: *
+ * * autocorrelation + lag windowing *
+ * * Levinson-durbin algorithm to find a[] *
+ * * convert a[] to lsp[] *
+ * * quantize and code the LSPs *
+ * * find the interpolated LSPs and convert to a[] for all *
+ * subframes (both quantized and unquantized) *
+ *------------------------------------------------------------------------*
+
+ // LP analysis
+ lpc(st->lpcSt, mode, st->p_window, st->p_window_12k2, A_t);
+
+
+ // From A(z) to lsp. LSP quantization and interpolation
+ lsp(st->lspSt, mode, *usedMode, A_t, Aq_t, lsp_new, &ana);
+
+
+ // Buffer lsp's and energy
+ dtx_buffer(st->dtx_encSt,
+ lsp_new,
+ st->new_speech);
+
+ // Check if in DTX mode
+ if (sub(*usedMode, MRDTX) == 0)
+ {
+ dtx_enc(st->dtx_encSt,
+ compute_sid_flag,
+ st->lspSt->qSt,
+ st->gainQuantSt->gc_predSt,
+ &ana);
+
+ Set_zero(st->old_exc, PIT_MAX + L_INTERPOL);
+ Set_zero(st->mem_w0, M);
+ Set_zero(st->mem_err, M);
+ Set_zero(st->zero, L_SUBFR);
+ Set_zero(st->hvec, L_SUBFR); // set to zero "h1[-L_SUBFR..-1]"
+ // Reset lsp states
+ lsp_reset(st->lspSt);
+ Copy(lsp_new, st->lspSt->lsp_old, M);
+ Copy(lsp_new, st->lspSt->lsp_old_q, M);
+
+ // Reset clLtp states
+ cl_ltp_reset(st->clLtpSt);
+ st->sharp = SHARPMIN;
+ }
+ else
+ {
+ // check resonance in the filter
+ lsp_flag = check_lsp(st->tonStabSt, st->lspSt->lsp_old);
+ }
+
+ *----------------------------------------------------------------------*
+ * - Find the weighted input speech w_sp[] for the whole speech frame *
+ * - Find the open-loop pitch delay for first 2 subframes *
+ * - Set the range for searching closed-loop pitch in 1st subframe *
+ * - Find the open-loop pitch delay for last 2 subframes *
+ *----------------------------------------------------------------------*
+
+#ifdef VAD2
+ if (st->dtx)
+ { // no test() call since this if is only in simulation env
+ st->vadSt->L_Rmax = 0;
+ st->vadSt->L_R0 = 0;
+ }
+#endif
+ for(subfrNr = 0, i_subfr = 0;
+ subfrNr < L_FRAME/L_FRAME_BY2;
+ subfrNr++, i_subfr += L_FRAME_BY2)
+ {
+ // Pre-processing on 80 samples
+ pre_big(mode, gamma1, gamma1_12k2, gamma2, A_t, i_subfr, st->speech,
+ st->mem_w, st->wsp);
+
+ if ((sub(mode, MR475) != 0) && (sub(mode, MR515) != 0))
+ {
+ // Find open loop pitch lag for two subframes
+ ol_ltp(st->pitchOLWghtSt, st->vadSt, mode, &st->wsp[i_subfr],
+ &T_op[subfrNr], st->old_lags, st->ol_gain_flg, subfrNr,
+ st->dtx);
+ }
+ }
+
+ if ((sub(mode, MR475) == 0) || (sub(mode, MR515) == 0))
+ {
+ // Find open loop pitch lag for ONE FRAME ONLY
+ // search on 160 samples
+
+ ol_ltp(st->pitchOLWghtSt, st->vadSt, mode, &st->wsp[0], &T_op[0],
+ st->old_lags, st->ol_gain_flg, 1, st->dtx);
+ T_op[1] = T_op[0];
+ }
+
+#ifdef VAD2
+ if (st->dtx)
+ { // no test() call since this if is only in simulation env
+ LTP_flag_update(st->vadSt, mode);
+ }
+#endif
+
+#ifndef VAD2
+ // run VAD pitch detection
+ if (st->dtx)
+ { // no test() call since this if is only in simulation env
+ vad_pitch_detection(st->vadSt, T_op);
+ }
+#endif
+
+ if (sub(*usedMode, MRDTX) == 0)
+ {
+ goto the_end;
+ }
+
+ *------------------------------------------------------------------------*
+ * 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. *
+ * - find the weighted LPC coefficients *
+ * - find the LPC residual signal res[] *
+ * - 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 *
+ * - update the impulse response h1[] by including fixed-gain pitch *
+ * - find target vector for codebook search *
+ * - codebook search *
+ * - encode codebook address *
+ * - VQ of pitch and codebook gains *
+ * - find synthesis speech *
+ * - update states of weighting filter *
+ *------------------------------------------------------------------------*
+
+ A = A_t; // pointer to interpolated LPC parameters
+ Aq = Aq_t; // pointer to interpolated quantized LPC parameters
+
+ evenSubfr = 0;
+ subfrNr = -1;
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ subfrNr = add(subfrNr, 1);
+ evenSubfr = sub(1, evenSubfr);
+
+ // Save states for the MR475 mode
+ if ((evenSubfr != 0) && (sub(*usedMode, MR475) == 0))
+ {
+ Copy(st->mem_syn, mem_syn_save, M);
+ Copy(st->mem_w0, mem_w0_save, M);
+ Copy(st->mem_err, mem_err_save, M);
+ sharp_save = st->sharp;
+ }
+
+ *-----------------------------------------------------------------*
+ * - Preprocessing of subframe *
+ *-----------------------------------------------------------------*
+ if (sub(*usedMode, MR475) != 0)
+ {
+ subframePreProc(*usedMode, gamma1, gamma1_12k2,
+ gamma2, A, Aq, &st->speech[i_subfr],
+ st->mem_err, st->mem_w0, st->zero,
+ st->ai_zero, &st->exc[i_subfr],
+ st->h1, xn, res, st->error);
+ }
+ else
+ { // MR475
+ subframePreProc(*usedMode, gamma1, gamma1_12k2,
+ gamma2, A, Aq, &st->speech[i_subfr],
+ st->mem_err, mem_w0_save, st->zero,
+ st->ai_zero, &st->exc[i_subfr],
+ st->h1, xn, res, st->error);
+
+ // save impulse response (modified in cbsearch)
+ if (evenSubfr != 0)
+ {
+ Copy (st->h1, h1_sf0, L_SUBFR);
+ }
+ }
+
+ // copy the LP residual (res2 is modified in the CL LTP search)
+ Copy (res, res2, L_SUBFR);
+
+
+ *-----------------------------------------------------------------*
+ * - Closed-loop LTP search *
+ *-----------------------------------------------------------------*
+ cl_ltp(st->clLtpSt, st->tonStabSt, *usedMode, i_subfr, T_op, st->h1,
+ &st->exc[i_subfr], res2, xn, lsp_flag, xn2, y1,
+ &T0, &T0_frac, &gain_pit, gCoeff, &ana,
+ &gp_limit);
+
+ // update LTP lag history
+ if ((subfrNr == 0) && (st->ol_gain_flg[0] > 0))
+ {
+ st->old_lags[1] = T0;
+ }
+
+ if ((sub(subfrNr, 3) == 0) && (st->ol_gain_flg[1] > 0))
+ {
+ st->old_lags[0] = T0;
+ }
+
+
+ *-----------------------------------------------------------------*
+ * - Inovative codebook search (find index and gain) *
+ *-----------------------------------------------------------------*
+ cbsearch(xn2, st->h1, T0, st->sharp, gain_pit, res2,
+ code, y2, &ana, *usedMode, subfrNr);
+
+ *------------------------------------------------------*
+ * - Quantization of gains. *
+ *------------------------------------------------------*
+ gainQuant(st->gainQuantSt, *usedMode, res, &st->exc[i_subfr], code,
+ xn, xn2, y1, y2, gCoeff, evenSubfr, gp_limit,
+ &gain_pit_sf0, &gain_code_sf0,
+ &gain_pit, &gain_code, &ana);
+
+ // update gain history
+ update_gp_clipping(st->tonStabSt, gain_pit);
+
+ if (sub(*usedMode, MR475) != 0)
+ {
+ // Subframe Post Porcessing
+ subframePostProc(st->speech, *usedMode, i_subfr, gain_pit,
+ gain_code, Aq, synth, xn, code, y1, y2, st->mem_syn,
+ st->mem_err, st->mem_w0, st->exc, &st->sharp);
+ }
+ else
+ {
+ if (evenSubfr != 0)
+ {
+ i_subfr_sf0 = i_subfr;
+ Copy(xn, xn_sf0, L_SUBFR);
+ Copy(y2, y2_sf0, L_SUBFR);
+ Copy(code, code_sf0, L_SUBFR);
+ T0_sf0 = T0;
+ T0_frac_sf0 = T0_frac;
+
+ // Subframe Post Porcessing
+ subframePostProc(st->speech, *usedMode, i_subfr, gain_pit,
+ gain_code, Aq, synth, xn, code, y1, y2,
+ mem_syn_save, st->mem_err, mem_w0_save,
+ st->exc, &st->sharp);
+ st->sharp = sharp_save;
+ }
+ else
+ {
+ // update both subframes for the MR475
+
+ // Restore states for the MR475 mode
+ Copy(mem_err_save, st->mem_err, M);
+
+ // re-build excitation for sf 0
+ Pred_lt_3or6(&st->exc[i_subfr_sf0], T0_sf0, T0_frac_sf0,
+ L_SUBFR, 1);
+ Convolve(&st->exc[i_subfr_sf0], h1_sf0, y1, L_SUBFR);
+
+ Aq -= MP1;
+ subframePostProc(st->speech, *usedMode, i_subfr_sf0,
+ gain_pit_sf0, gain_code_sf0, Aq,
+ synth, xn_sf0, code_sf0, y1, y2_sf0,
+ st->mem_syn, st->mem_err, st->mem_w0, st->exc,
+ &sharp_save); // overwrites sharp_save
+ Aq += MP1;
+
+ // re-run pre-processing to get xn right (needed by postproc)
+ // (this also reconstructs the unsharpened h1 for sf 1)
+ subframePreProc(*usedMode, gamma1, gamma1_12k2,
+ gamma2, A, Aq, &st->speech[i_subfr],
+ st->mem_err, st->mem_w0, st->zero,
+ st->ai_zero, &st->exc[i_subfr],
+ st->h1, xn, res, st->error);
+
+ // re-build excitation sf 1 (changed if lag < L_SUBFR)
+ Pred_lt_3or6(&st->exc[i_subfr], T0, T0_frac, L_SUBFR, 1);
+ Convolve(&st->exc[i_subfr], st->h1, y1, L_SUBFR);
+
+ subframePostProc(st->speech, *usedMode, i_subfr, gain_pit,
+ gain_code, Aq, synth, xn, code, y1, y2,
+ st->mem_syn, st->mem_err, st->mem_w0,
+ st->exc, &st->sharp);
+ }
+ }
+
+
+ A += MP1; // interpolated LPC parameters for next subframe
+ Aq += MP1;
+ }
+
+ Copy(&st->old_exc[L_FRAME], &st->old_exc[0], PIT_MAX + L_INTERPOL);
+
+the_end:
+
+ *--------------------------------------------------*
+ * Update signal for next frame. *
+ *--------------------------------------------------*
+ Copy(&st->old_wsp[L_FRAME], &st->old_wsp[0], PIT_MAX);
+
+ Copy(&st->old_speech[L_FRAME], &st->old_speech[0], L_TOTAL - L_FRAME);
+
+ return 0;
+}
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 cod_amr(
+ cod_amrState *st, /* i/o : State struct */
+ enum Mode mode, /* i : AMR mode */
+ Word16 new_speech[], /* i : speech input (L_FRAME) */
+ Word16 ana[], /* o : Analysis parameters */
+ enum Mode *usedMode, /* o : used mode */
+ Word16 synth[] /* o : Local synthesis */
+)
+{
+ /* LPC coefficients */
+ Word16 A_t[(MP1) * 4]; /* A(z) unquantized for the 4 subframes */
+ Word16 Aq_t[(MP1) * 4]; /* A(z) quantized for the 4 subframes */
+ Word16 *A, *Aq; /* Pointer on A_t and Aq_t */
+ Word16 lsp_new[M];
+
+ /* Other vectors */
+ Word16 xn[L_SUBFR]; /* Target vector for pitch search */
+ Word16 xn2[L_SUBFR]; /* Target vector for codebook search */
+ Word16 code[L_SUBFR]; /* Fixed codebook excitation */
+ Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 y2[L_SUBFR]; /* Filtered fixed codebook excitation */
+ Word16 gCoeff[6]; /* Correlations between xn, y1, & y2: */
+ Word16 res[L_SUBFR]; /* Short term (LPC) prediction residual */
+ Word16 res2[L_SUBFR]; /* Long term (LTP) prediction residual */
+
+ /* Vector and scalars needed for the MR475 */
+ Word16 xn_sf0[L_SUBFR]; /* Target vector for pitch search */
+ Word16 y2_sf0[L_SUBFR]; /* Filtered codebook innovation */
+ Word16 code_sf0[L_SUBFR]; /* Fixed codebook excitation */
+ Word16 h1_sf0[L_SUBFR]; /* The impulse response of sf0 */
+ Word16 mem_syn_save[M]; /* Filter memory */
+ Word16 mem_w0_save[M]; /* Filter memory */
+ Word16 mem_err_save[M]; /* Filter memory */
+ Word16 sharp_save; /* Sharpening */
+ Word16 evenSubfr; /* Even subframe indicator */
+ Word16 T0_sf0 = 0; /* Integer pitch lag of sf0 */
+ Word16 T0_frac_sf0 = 0; /* Fractional pitch lag of sf0 */
+ Word16 i_subfr_sf0 = 0; /* Position in exc[] for sf0 */
+ Word16 gain_pit_sf0; /* Quantized pitch gain for sf0 */
+ Word16 gain_code_sf0; /* Quantized codebook gain for sf0 */
+
+ /* Scalars */
+ Word16 i_subfr, subfrNr;
+ Word16 T_op[L_FRAME/L_FRAME_BY2];
+ Word16 T0, T0_frac;
+ Word16 gain_pit, gain_code;
+
+ /* Flags */
+ Word16 lsp_flag = 0; /* indicates resonance in LPC filter */
+ Word16 gp_limit; /* pitch gain limit value */
+ Word16 vad_flag; /* VAD decision flag */
+ Word16 compute_sid_flag; /* SID analysis flag */
+ Flag *pOverflow = &(st->overflow); /* Overflow flag */
+
+
+ memcpy(st->new_speech, new_speech, L_FRAME*sizeof(Word16));
+
+ *usedMode = mode;
+
+ /* DTX processing */
+ if (st->dtx)
+ {
+ /* Find VAD decision */
+#ifdef VAD2
+ vad_flag = vad2(st->new_speech, st->vadSt, pOverflow);
+ vad_flag = vad2(st->new_speech + 80, st->vadSt, pOverflow) || vad_flag;
+#else
+ vad_flag = vad1(st->vadSt, st->new_speech, pOverflow);
+#endif
+
+ /* NB! usedMode may change here */
+ compute_sid_flag = tx_dtx_handler(st->dtx_encSt,
+ vad_flag,
+ usedMode, pOverflow);
+ }
+ else
+ {
+ compute_sid_flag = 0;
+ }
+
+ /*------------------------------------------------------------------------*
+ * - Perform LPC analysis: *
+ * * autocorrelation + lag windowing *
+ * * Levinson-durbin algorithm to find a[] *
+ * * convert a[] to lsp[] *
+ * * quantize and code the LSPs *
+ * * find the interpolated LSPs and convert to a[] for all *
+ * subframes (both quantized and unquantized) *
+ *------------------------------------------------------------------------*/
+
+ /* LP analysis */
+ lpc(st->lpcSt, mode, st->p_window, st->p_window_12k2, A_t, pOverflow);
+
+ /* From A(z) to lsp. LSP quantization and interpolation */
+ lsp(st->lspSt, mode, *usedMode, A_t, Aq_t, lsp_new, &ana, pOverflow);
+
+ /* Buffer lsp's and energy */
+ dtx_buffer(st->dtx_encSt,
+ lsp_new,
+ st->new_speech, pOverflow);
+
+ /* Check if in DTX mode */
+
+ if (*usedMode == MRDTX)
+ {
+ dtx_enc(st->dtx_encSt,
+ compute_sid_flag,
+ st->lspSt->qSt,
+ &(st->gainQuantSt->gc_predSt),
+ &ana, pOverflow);
+
+ memset(st->old_exc, 0, sizeof(Word16)*(PIT_MAX + L_INTERPOL));
+ memset(st->mem_w0, 0, sizeof(Word16)*M);
+ memset(st->mem_err, 0, sizeof(Word16)*M);
+ memset(st->zero, 0, sizeof(Word16)*L_SUBFR);
+ memset(st->hvec, 0, sizeof(Word16)*L_SUBFR); /* set to zero "h1[-L_SUBFR..-1]" */
+ /* Reset lsp states */
+ lsp_reset(st->lspSt);
+
+ memcpy(st->lspSt->lsp_old, lsp_new, M*sizeof(Word16));
+ memcpy(st->lspSt->lsp_old_q, lsp_new, M*sizeof(Word16));
+
+ /* Reset clLtp states */
+ cl_ltp_reset(st->clLtpSt);
+ st->sharp = SHARPMIN;
+ }
+ else
+ {
+ /* check resonance in the filter */
+ lsp_flag = check_lsp(st->tonStabSt, st->lspSt->lsp_old, pOverflow);
+ }
+
+ /*----------------------------------------------------------------------*
+ * - Find the weighted input speech w_sp[] for the whole speech frame *
+ * - Find the open-loop pitch delay for first 2 subframes *
+ * - Set the range for searching closed-loop pitch in 1st subframe *
+ * - Find the open-loop pitch delay for last 2 subframes *
+ *----------------------------------------------------------------------*/
+
+#ifdef VAD2
+ if (st->dtx)
+ {
+ st->vadSt->L_Rmax = 0;
+ st->vadSt->L_R0 = 0;
+ }
+#endif
+
+ for (subfrNr = 0, i_subfr = 0;
+ subfrNr < L_FRAME / L_FRAME_BY2;
+ subfrNr++, i_subfr += L_FRAME_BY2)
+ {
+ /* Pre-processing on 80 samples */
+ pre_big(mode, gamma1, gamma1_12k2, gamma2, A_t, i_subfr, st->speech,
+ st->mem_w, st->wsp, pOverflow);
+
+
+ if ((mode != MR475) && (mode != MR515))
+ {
+ /* Find open loop pitch lag for two subframes */
+ ol_ltp(st->pitchOLWghtSt, st->vadSt, mode, &st->wsp[i_subfr],
+ &T_op[subfrNr], st->old_lags, st->ol_gain_flg, subfrNr,
+ st->dtx, pOverflow);
+ }
+ }
+
+ if ((mode == MR475) || (mode == MR515))
+ {
+ /* Find open loop pitch lag for ONE FRAME ONLY */
+ /* search on 160 samples */
+
+ ol_ltp(st->pitchOLWghtSt, st->vadSt, mode, &st->wsp[0], &T_op[0],
+ st->old_lags, st->ol_gain_flg, 1, st->dtx, pOverflow);
+ T_op[1] = T_op[0];
+ }
+
+#ifdef VAD2
+ if (st->dtx)
+ {
+ LTP_flag_update(st->vadSt, (Word16) mode, pOverflow);
+ }
+#endif
+
+#ifndef VAD2
+ /* run VAD pitch detection */
+ if (st->dtx)
+ {
+ vad_pitch_detection(st->vadSt, T_op, pOverflow);
+ }
+#endif
+
+ if (*usedMode == MRDTX)
+ {
+ goto the_end;
+ }
+
+ /*------------------------------------------------------------------------*
+ * 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. *
+ * - find the weighted LPC coefficients *
+ * - find the LPC residual signal res[] *
+ * - 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 *
+ * - update the impulse response h1[] by including fixed-gain pitch *
+ * - find target vector for codebook search *
+ * - codebook search *
+ * - encode codebook address *
+ * - VQ of pitch and codebook gains *
+ * - find synthesis speech *
+ * - update states of weighting filter *
+ *------------------------------------------------------------------------*/
+
+ A = A_t; /* pointer to interpolated LPC parameters */
+ Aq = Aq_t; /* pointer to interpolated quantized LPC parameters */
+
+ evenSubfr = 0;
+ subfrNr = -1;
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ subfrNr++;
+ evenSubfr = 1 - evenSubfr;
+
+ /* Save states for the MR475 mode */
+
+ if ((evenSubfr != 0) && (*usedMode == MR475))
+ {
+ memcpy(mem_syn_save, st->mem_syn, M*sizeof(Word16));
+ memcpy(mem_w0_save, st->mem_w0, M*sizeof(Word16));
+ memcpy(mem_err_save, st->mem_err, M*sizeof(Word16));
+
+ sharp_save = st->sharp;
+ }
+
+ /*-----------------------------------------------------------------*
+ * - Preprocessing of subframe *
+ *-----------------------------------------------------------------*/
+
+ if (*usedMode != MR475)
+ {
+ subframePreProc(*usedMode, gamma1, gamma1_12k2,
+ gamma2, A, Aq, &st->speech[i_subfr],
+ st->mem_err, st->mem_w0, st->zero,
+ st->ai_zero, &st->exc[i_subfr],
+ st->h1, xn, res, st->error);
+ }
+ else
+ { /* MR475 */
+ subframePreProc(*usedMode, gamma1, gamma1_12k2,
+ gamma2, A, Aq, &st->speech[i_subfr],
+ st->mem_err, mem_w0_save, st->zero,
+ st->ai_zero, &st->exc[i_subfr],
+ st->h1, xn, res, st->error);
+
+ /* save impulse response (modified in cbsearch) */
+
+ if (evenSubfr != 0)
+ {
+ memcpy(h1_sf0, st->h1, L_SUBFR*sizeof(Word16));
+
+ }
+ }
+
+ /* copy the LP residual (res2 is modified in the CL LTP search) */
+ memcpy(res2, res, L_SUBFR*sizeof(Word16));
+
+ /*-----------------------------------------------------------------*
+ * - Closed-loop LTP search *
+ *-----------------------------------------------------------------*/
+ cl_ltp(st->clLtpSt, st->tonStabSt, *usedMode, i_subfr, T_op, st->h1,
+ &st->exc[i_subfr], res2, xn, lsp_flag, xn2, y1,
+ &T0, &T0_frac, &gain_pit, gCoeff, &ana,
+ &gp_limit, pOverflow);
+
+ /* update LTP lag history */
+
+ if ((subfrNr == 0) && (st->ol_gain_flg[0] > 0))
+ {
+ st->old_lags[1] = T0;
+ }
+
+
+ if ((subfrNr == 3) && (st->ol_gain_flg[1] > 0))
+ {
+ st->old_lags[0] = T0;
+ }
+
+ /*-----------------------------------------------------------------*
+ * - Inovative codebook search (find index and gain) *
+ *-----------------------------------------------------------------*/
+ cbsearch(xn2, st->h1, T0, st->sharp, gain_pit, res2,
+ code, y2, &ana, *usedMode, subfrNr, pOverflow);
+
+ /*------------------------------------------------------*
+ * - Quantization of gains. *
+ *------------------------------------------------------*/
+ gainQuant(st->gainQuantSt, *usedMode, res, &st->exc[i_subfr], code,
+ xn, xn2, y1, y2, gCoeff, evenSubfr, gp_limit,
+ &gain_pit_sf0, &gain_code_sf0,
+ &gain_pit, &gain_code, &ana, pOverflow);
+
+ /* update gain history */
+ update_gp_clipping(st->tonStabSt, gain_pit, pOverflow);
+
+
+ if (*usedMode != MR475)
+ {
+ /* Subframe Post Porcessing */
+ subframePostProc(st->speech, *usedMode, i_subfr, gain_pit,
+ gain_code, Aq, synth, xn, code, y1, y2, st->mem_syn,
+ st->mem_err, st->mem_w0, st->exc, &st->sharp, pOverflow);
+ }
+ else
+ {
+
+ if (evenSubfr != 0)
+ {
+ i_subfr_sf0 = i_subfr;
+
+ memcpy(xn_sf0, xn, L_SUBFR*sizeof(Word16));
+ memcpy(y2_sf0, y2, L_SUBFR*sizeof(Word16));
+ memcpy(code_sf0, code, L_SUBFR*sizeof(Word16));
+
+ T0_sf0 = T0;
+ T0_frac_sf0 = T0_frac;
+
+ /* Subframe Post Porcessing */
+ subframePostProc(st->speech, *usedMode, i_subfr, gain_pit,
+ gain_code, Aq, synth, xn, code, y1, y2,
+ mem_syn_save, st->mem_err, mem_w0_save,
+ st->exc, &st->sharp, pOverflow);
+ st->sharp = sharp_save;
+ }
+ else
+ {
+ /* update both subframes for the MR475 */
+
+ /* Restore states for the MR475 mode */
+ memcpy(st->mem_err, mem_err_save, M*sizeof(Word16));
+
+
+ /* re-build excitation for sf 0 */
+ Pred_lt_3or6(&st->exc[i_subfr_sf0], T0_sf0, T0_frac_sf0,
+ L_SUBFR, 1, pOverflow);
+ Convolve(&st->exc[i_subfr_sf0], h1_sf0, y1, L_SUBFR);
+
+ Aq -= MP1;
+ subframePostProc(st->speech, *usedMode, i_subfr_sf0,
+ gain_pit_sf0, gain_code_sf0, Aq,
+ synth, xn_sf0, code_sf0, y1, y2_sf0,
+ st->mem_syn, st->mem_err, st->mem_w0, st->exc,
+ &sharp_save, pOverflow); /* overwrites sharp_save */
+ Aq += MP1;
+
+ /* re-run pre-processing to get xn right (needed by postproc) */
+ /* (this also reconstructs the unsharpened h1 for sf 1) */
+ subframePreProc(*usedMode, gamma1, gamma1_12k2,
+ gamma2, A, Aq, &st->speech[i_subfr],
+ st->mem_err, st->mem_w0, st->zero,
+ st->ai_zero, &st->exc[i_subfr],
+ st->h1, xn, res, st->error);
+
+ /* re-build excitation sf 1 (changed if lag < L_SUBFR) */
+ Pred_lt_3or6(&st->exc[i_subfr], T0, T0_frac, L_SUBFR, 1, pOverflow);
+ Convolve(&st->exc[i_subfr], st->h1, y1, L_SUBFR);
+
+ subframePostProc(st->speech, *usedMode, i_subfr, gain_pit,
+ gain_code, Aq, synth, xn, code, y1, y2,
+ st->mem_syn, st->mem_err, st->mem_w0,
+ st->exc, &st->sharp, pOverflow);
+ }
+ }
+
+ A += MP1; /* interpolated LPC parameters for next subframe */
+ Aq += MP1;
+ }
+
+ memcpy(&st->old_exc[0], &st->old_exc[L_FRAME], (PIT_MAX + L_INTERPOL)*sizeof(Word16));
+
+the_end:
+
+ /*--------------------------------------------------*
+ * Update signal for next frame. *
+ *--------------------------------------------------*/
+
+ memcpy(&st->old_wsp[0], &st->old_wsp[L_FRAME], PIT_MAX*sizeof(Word16));
+ memcpy(&st->old_speech[0], &st->old_speech[L_FRAME], (L_TOTAL - L_FRAME)*sizeof(Word16));
+
+ return(0);
+}
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cod_amr.h b/media/libstagefright/codecs/amrnb/enc/src/cod_amr.h
new file mode 100644
index 0000000..7360c0a
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/cod_amr.h
@@ -0,0 +1,275 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/cod_amr.h
+
+ Date: 02/07/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added overflow flag as an element to the cod_amrState data
+ structure. Corrected the function prototype declaration for
+ cod_amr().
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : cod_amr.h
+ Purpose : Main encoder routine operating on a frame basis.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef cod_amr_h
+#define cod_amr_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+#include "mode.h"
+#include "lpc.h"
+#include "lsp.h"
+#include "cl_ltp.h"
+#include "gain_q.h"
+#include "p_ol_wgh.h"
+#include "ton_stab.h"
+#include "vad.h"
+#include "dtx_enc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ /*-----------------------------------------------------------*
+ * Coder constant parameters (defined in "cnst.h") *
+ *-----------------------------------------------------------*
+ * L_WINDOW : LPC analysis window size. *
+ * L_NEXT : Samples of next frame needed for autocor. *
+ * L_FRAME : Frame size. *
+ * L_FRAME_BY2 : Half the frame size. *
+ * L_SUBFR : Sub-frame size. *
+ * M : LPC order. *
+ * MP1 : LPC order+1 *
+ * L_TOTAL7k4 : Total size of speech buffer. *
+ * PIT_MIN7k4 : Minimum pitch lag. *
+ * PIT_MAX : Maximum pitch lag. *
+ * L_INTERPOL : Length of filter for interpolation *
+ *-----------------------------------------------------------*/
+ typedef struct
+ {
+ /* Speech vector */
+ Word16 old_speech[L_TOTAL];
+ Word16 *speech, *p_window, *p_window_12k2;
+ Word16 *new_speech; /* Global variable */
+
+ /* Weight speech vector */
+ Word16 old_wsp[L_FRAME + PIT_MAX];
+ Word16 *wsp;
+
+ /* OL LTP states */
+ Word16 old_lags[5];
+ Word16 ol_gain_flg[2];
+
+ /* Excitation vector */
+ Word16 old_exc[L_FRAME + PIT_MAX + L_INTERPOL];
+ Word16 *exc;
+
+ /* Zero vector */
+ Word16 ai_zero[L_SUBFR + MP1];
+ Word16 *zero;
+
+ /* Impulse response vector */
+ Word16 *h1;
+ Word16 hvec[L_SUBFR * 2];
+
+ /* Substates */
+ lpcState *lpcSt;
+ lspState *lspSt;
+ clLtpState *clLtpSt;
+ gainQuantState *gainQuantSt;
+ pitchOLWghtState *pitchOLWghtSt;
+ tonStabState *tonStabSt;
+ vadState *vadSt;
+ Flag dtx;
+ dtx_encState *dtx_encSt;
+
+ /* Filter's memory */
+ Word16 mem_syn[M], mem_w0[M], mem_w[M];
+ Word16 mem_err[M + L_SUBFR], *error;
+
+ Word16 sharp;
+
+ /* Overflow flag */
+ Flag overflow;
+
+ } cod_amrState;
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ /*
+ **************************************************************************
+ *
+ * Function : cod_amr_init
+ * Purpose : Allocates memory and initializes state variables
+ * Description : Stores pointer to filter status struct in *st. This
+ * pointer has to be passed to cod_amr in each call.
+ * - initilize pointers to speech buffer
+ * - initialize static pointers
+ * - set static vectors to zero
+ * Returns : 0 on success
+ *
+ **************************************************************************
+ */
+ Word16 cod_amr_init(cod_amrState **st, Flag dtx);
+
+ /*
+ **************************************************************************
+ *
+ * Function : cod_amr_reset
+ * Purpose : Resets state memory
+ * Returns : 0 on success
+ *
+ **************************************************************************
+ */
+ Word16 cod_amr_reset(cod_amrState *st);
+
+ /*
+ **************************************************************************
+ *
+ * Function : cod_amr_exit
+ * Purpose : The memory used for state memory is freed
+ * Description : Stores NULL in *st
+ *
+ **************************************************************************
+ */
+ void cod_amr_exit(cod_amrState **st);
+
+ /***************************************************************************
+ * FUNCTION: cod_amr_first
+ *
+ * PURPOSE: Copes with look-ahead.
+ *
+ * INPUTS:
+ * No input argument are passed to this function. However, before
+ * calling this function, 40 new speech data should be copied to the
+ * vector new_speech[]. This is a global pointer which is declared in
+ * this file (it points to the end of speech buffer minus 200).
+ *
+ ***************************************************************************/
+
+ Word16 cod_amr_first(cod_amrState *st, /* i/o : State struct */
+ Word16 new_speech[] /* i : speech input (L_FRAME) */
+ );
+
+ /***************************************************************************
+ * FUNCTION: cod_amr
+ *
+ * PURPOSE: Main encoder routine.
+ *
+ * DESCRIPTION: This function is called every 20 ms speech frame,
+ * operating on the newly read 160 speech samples. It performs the
+ * principle encoding functions to produce the set of encoded parameters
+ * which include the LSP, adaptive codebook, and fixed codebook
+ * quantization indices (addresses and gains).
+ *
+ * INPUTS:
+ * No input argument are passed to this function. However, before
+ * calling this function, 160 new speech data should be copied to the
+ * vector new_speech[]. This is a global pointer which is declared in
+ * this file (it points to the end of speech buffer minus 160).
+ *
+ * OUTPUTS:
+ *
+ * ana[]: vector of analysis parameters.
+ * synth[]: Local synthesis speech (for debugging purposes)
+ *
+ ***************************************************************************/
+
+ Word16 cod_amr(cod_amrState *st, /* i/o : State struct */
+ enum Mode mode, /* i : AMR mode */
+ Word16 new_speech[], /* i : speech input (L_FRAME) */
+ Word16 ana[], /* o : Analysis parameters */
+ enum Mode *usedMode, /* o : used mode */
+ Word16 synth[] /* o : Local synthesis */
+ );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _cod_amr_h_ */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/convolve.cpp b/media/libstagefright/codecs/amrnb/enc/src/convolve.cpp
new file mode 100644
index 0000000..e9ce7ba
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/convolve.cpp
@@ -0,0 +1,245 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/convolve.c
+
+ Date: 06/19/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Optimize for speed. Update to code template.
+
+ Description: Added author name and date, fixed tabs, and added missing
+ sections. Updated Input/Output section.
+
+ Description: Optimized code by calculating two convolution sums per iteration
+ of the outer loop, thereby, decreasing outer loop count by 2.
+ Updated input/output definitions to be the same as the assembly
+ file (convolve.asm). Left Pseudo-code section blank.
+
+ Description: Deleted semi-colon in the Pointers modified section.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Fixed typecasting issue with TI C compiler.
+ 2. Modified FOR loop to count down, wherever applicable.
+
+ Description: Made the following changes
+ 1. Unrolled the correlation loop.
+ 2. Performed 2 correlation per pass per sample to avoid recalling
+ the same data twice.
+ 3. Eliminated math operations that check for saturation.
+
+ Description:
+ 1. Modified loop counter, extra unrolling did speed up code
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Using inlines from fxp_arithmetic.h .
+
+ Description: Replacing fxp_arithmetic.h with basic_op.h.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "convolve.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Convolve
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ x = pointer to input vector of L elements of type Word16
+ h = pointer to the filter's impulse response vector of L elements
+ of type Word16
+ y = pointer to the output vector of L elements of type Word16 used for
+ storing the convolution of x and h;
+ L = Length of the convolution; type definition is Word16
+
+ Outputs:
+ y buffer contains the new convolution output
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Perform the convolution between two vectors x[] and h[] and write the result
+ in the vector y[]. All vectors are of length L and only the first L samples
+ of the convolution are computed.
+
+ The convolution is given by:
+
+ y[n] = sum_{i=0}^{n} x[i] h[n-i], n=0,...,L-1
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ convolve.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Convolve (
+ Word16 x[], // (i) : input vector
+ Word16 h[], // (i) : impulse response
+ Word16 y[], // (o) : output vector
+ Word16 L // (i) : vector size
+)
+{
+ Word16 i, n;
+ Word32 s;
+
+ for (n = 0; n < L; n++)
+ {
+ s = 0; move32 ();
+ for (i = 0; i <= n; i++)
+ {
+ s = L_mac (s, x[i], h[n - i]);
+ }
+ s = L_shl (s, 3);
+ y[n] = extract_h (s); move16 ();
+ }
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Convolve(
+ Word16 x[], /* (i) : input vector */
+ Word16 h[], /* (i) : impulse response */
+ Word16 y[], /* (o) : output vector */
+ Word16 L /* (i) : vector size */
+)
+{
+ register Word16 i, n;
+ Word32 s1, s2;
+
+
+ for (n = 1; n < L; n = n + 2)
+ {
+
+ h = h + n;
+
+ s2 = ((Word32) * (x)) * *(h--);
+ s1 = ((Word32) * (x++)) * *(h);
+
+ for (i = (n - 1) >> 1; i != 0; i--)
+ {
+ s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (x), (Word32) * (h--), s2);
+ s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (x++), (Word32) * (h), s1);
+ s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (x), (Word32) * (h--), s2);
+ s1 = amrnb_fxp_mac_16_by_16bb((Word32) * (x++), (Word32) * (h), s1);
+ }
+
+ s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (x), (Word32) * (h), s2);
+
+ *(y++) = (Word16)(s1 >> 12);
+ *(y++) = (Word16)(s2 >> 12);
+
+ x = x - n;
+
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/convolve.h b/media/libstagefright/codecs/amrnb/enc/src/convolve.h
new file mode 100644
index 0000000..1f2b503
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/convolve.h
@@ -0,0 +1,83 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : convolve.h
+* Purpose : Perform the convolution between two vectors x[]
+* : and h[] and write the result in the vector y[].
+* : All vectors are of length L and only the first
+* : L samples of the convolution are computed.
+*
+********************************************************************************
+*/
+#ifndef convolve_h
+#define convolve_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ ********************************************************************************
+ * DEFINITION OF DATA TYPES
+ ********************************************************************************
+ */
+
+ /*
+ ********************************************************************************
+ * DECLARATION OF PROTOTYPES
+ ********************************************************************************
+ */
+ void Convolve(
+ Word16 x[], /* (i) : input vector */
+ Word16 h[], /* (i) : impulse response */
+ Word16 y[], /* (o) : output vector */
+ Word16 L /* (i) : vector size */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h.cpp b/media/libstagefright/codecs/amrnb/enc/src/cor_h.cpp
new file mode 100644
index 0000000..e46d99f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/cor_h.cpp
@@ -0,0 +1,429 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/cor_h.c
+
+ Date: 06/12/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template. First attempt at
+ optimizing C code.
+
+ Description: Used MAX_16 and MIN_16 when checking the result of Inv_sqrt.
+ Synced up to the new template.
+
+ Description: Added setting of Overflow flag in inlined code.
+
+ Description: Took out cor_h_x function and put it in its own file. Sync'ed
+ up with the single_func_template.c template. Delete version
+ ID variable.
+
+ Description: Synchronized file with UTMS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Fixed portion of the code that builds the rr[] matrix. There
+ was an error in the original inlining of code that caused
+ the code to be not bit-exact with UMTS version 3.2.0.
+
+ Description: Added calls to L_add() and mult() in the code to handle overflow
+ scenario. Moved cor_h.h after cnst.h in the Include section.
+ Doing this allows the unit test to build using the cnst.h in the
+ /test/include directory. Fixed initialization of the accumulator
+ in the first calculation of the sum of squares.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Used #define value instead of hard-coded numbers in the code.
+ 2. Fixed typecasting issue with TI C compiler.
+ 3. Removed typecasting of 0x00008000L in the call to L_add.
+
+ Description: Changed pOverflow from a global variable into a function
+ parameter.
+
+ Description:
+ 1. Added pointer to avoid adding offsets in every pass
+ 2. Eliminate variables defined as registers
+ 3. Removed extra check for overflow by doing scaling right
+ after overflow is detected.
+ 4. Eliminated calls to basic operations (like extract) not
+ needed because of the nature of the number (all bounded)
+ 5. Eliminated duplicate loop accessing same data
+ 6. Simplified matrix addressing by use of pointers
+
+ Description:
+ 1. Eliminated unused include files.
+ 2. Access twice the number of points when delaing with matrices
+ and in the process only 3 pointers (instead of 4) are needed
+ 3. Replaced array addressing (array sign[]) by pointers
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Using inlines from fxp_arithmetic.h .
+
+ Description: Replacing fxp_arithmetic.h with basic_op.h.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "cnst.h"
+#include "cor_h.h"
+#include "basicop_malloc.h"
+#include "inv_sqrt.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: cor_h
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ h = vector containing the impulse response of the weighted synthesis
+ filter; vector contents are of type Word16; vector length is
+ 2 * L_SUBFR
+ sign = vector containing the sign information for the correlation
+ values; vector contents are of type Word16; vector length is
+ L_CODE
+ rr = autocorrelation matrix; matrix contents are of type Word16;
+ matrix dimension is L_CODE by L_CODE
+
+ Outputs:
+ rr contents are the newly calculated autocorrelation values
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes correlations of the impulse response (h) needed for
+ the codebook search, and includes the sign information into the correlations.
+
+ The correlations are given by:
+ rr[i][j] = sum_{n=i}^{L-1} h[n-i] h[n-j]; i>=j; i,j=0,...,L-1
+
+ The sign information is included by:
+ rr[i][j] = rr[i][j]*sign[i]*sign[j]
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ cor_h.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void cor_h (
+ Word16 h[], // (i) : impulse response of weighted synthesis
+ filter
+ Word16 sign[], // (i) : sign of d[n]
+ Word16 rr[][L_CODE] // (o) : matrix of autocorrelation
+)
+{
+ Word16 i, j, k, dec, h2[L_CODE];
+ Word32 s;
+
+ // Scaling for maximum precision
+
+ s = 2;
+ for (i = 0; i < L_CODE; i++)
+ s = L_mac (s, h[i], h[i]);
+
+ j = sub (extract_h (s), 32767);
+ if (j == 0)
+ {
+ for (i = 0; i < L_CODE; i++)
+ {
+ h2[i] = shr (h[i], 1);
+ }
+ }
+ else
+ {
+ s = L_shr (s, 1);
+ k = extract_h (L_shl (Inv_sqrt (s), 7));
+ k = mult (k, 32440); // k = 0.99*k
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ h2[i] = pv_round (L_shl (L_mult (h[i], k), 9));
+ }
+ }
+
+ // build matrix rr[]
+ s = 0;
+ i = L_CODE - 1;
+ for (k = 0; k < L_CODE; k++, i--)
+ {
+ s = L_mac (s, h2[k], h2[k]);
+ rr[i][i] = pv_round (s);
+ }
+
+ for (dec = 1; dec < L_CODE; dec++)
+ {
+ s = 0;
+ j = L_CODE - 1;
+ i = sub (j, dec);
+ for (k = 0; k < (L_CODE - dec); k++, i--, j--)
+ {
+ s = L_mac (s, h2[k], h2[k + dec]);
+ rr[j][i] = mult (pv_round (s), mult (sign[i], sign[j]));
+ rr[i][j] = rr[j][i];
+ }
+ }
+}
+
+---------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void cor_h(
+ Word16 h[], /* (i) : impulse response of weighted synthesis
+ filter */
+ Word16 sign[], /* (i) : sign of d[n] */
+ Word16 rr[][L_CODE], /* (o) : matrix of autocorrelation */
+ Flag *pOverflow
+)
+{
+ register Word16 i;
+ register Word16 dec;
+
+ Word16 h2[L_CODE];
+ Word32 s;
+ Word32 s2;
+ Word16 tmp1;
+ Word16 tmp2;
+ Word16 tmp11;
+ Word16 tmp22;
+
+ Word16 *p_h;
+ Word16 *p_h2;
+ Word16 *rr1;
+ Word16 *rr2;
+ Word16 *rr3;
+ Word16 *p_rr_ref1;
+ Word16 *p_sign1;
+ Word16 *p_sign2;
+
+ /* Scaling for maximum precision */
+
+ /* Initialize accumulator to 1 since left shift happens */
+ /* after the accumulation of the sum of squares (original */
+ /* code initialized s to 2) */
+ s = 1;
+ p_h = h;
+
+ for (i = (L_CODE >> 1); i != 0 ; i--)
+ {
+ tmp1 = *(p_h++);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s);
+ tmp1 = *(p_h++);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s);
+
+ }
+
+ s <<= 1;
+
+ if (s & MIN_32)
+ {
+ p_h2 = h2;
+ p_h = h;
+
+ for (i = (L_CODE >> 1); i != 0; i--)
+ {
+ *(p_h2++) = *(p_h++) >> 1;
+ *(p_h2++) = *(p_h++) >> 1;
+ }
+ }
+ else
+ {
+
+ s >>= 1;
+
+ s = Inv_sqrt(s, pOverflow);
+
+ if (s < (Word32) 0x00ffffffL)
+ {
+ /* k = 0.99*k */
+ dec = (Word16)(((s >> 9) * 32440) >> 15);
+ }
+ else
+ {
+ dec = 32440; /* 0.99 */
+ }
+
+ p_h = h;
+ p_h2 = h2;
+
+ for (i = (L_CODE >> 1); i != 0; i--)
+ {
+ *(p_h2++) = (Word16)((amrnb_fxp_mac_16_by_16bb((Word32) * (p_h++), (Word32) dec, 0x020L)) >> 6);
+ *(p_h2++) = (Word16)((amrnb_fxp_mac_16_by_16bb((Word32) * (p_h++), (Word32) dec, 0x020L)) >> 6);
+ }
+ }
+ /* build matrix rr[] */
+
+ s = 0;
+
+ p_h2 = h2;
+
+ rr1 = &rr[L_CODE-1][L_CODE-1];
+
+ for (i = L_CODE >> 1; i != 0 ; i--)
+ {
+ tmp1 = *(p_h2++);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s);
+ *rr1 = (Word16)((s + 0x00004000L) >> 15);
+ rr1 -= (L_CODE + 1);
+ tmp1 = *(p_h2++);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) tmp1, (Word32) tmp1, s);
+ *rr1 = (Word16)((s + 0x00004000L) >> 15);
+ rr1 -= (L_CODE + 1);
+ }
+
+
+ p_rr_ref1 = rr[L_CODE-1];
+
+ for (dec = 1; dec < L_CODE; dec += 2)
+ {
+ rr1 = &p_rr_ref1[L_CODE-1-dec];
+
+ rr2 = &rr[L_CODE-1-dec][L_CODE-1];
+ rr3 = &rr[L_CODE-1-(dec+1)][L_CODE-1];
+
+ s = 0;
+ s2 = 0;
+
+ p_sign1 = &sign[L_CODE - 1];
+ p_sign2 = &sign[L_CODE - 1 - dec];
+
+ p_h2 = h2;
+ p_h = &h2[dec];
+
+ for (i = (L_CODE - dec - 1); i != 0 ; i--)
+ {
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_h2), (Word32) * (p_h++), s);
+ s2 = amrnb_fxp_mac_16_by_16bb((Word32) * (p_h2++), (Word32) * (p_h), s2);
+
+ tmp1 = (Word16)((s + 0x00004000L) >> 15);
+ tmp11 = (Word16)((s2 + 0x00004000L) >> 15);
+
+ tmp2 = ((Word32) * (p_sign1) * *(p_sign2--)) >> 15;
+ tmp22 = ((Word32) * (p_sign1--) * *(p_sign2)) >> 15;
+
+ *rr2 = ((Word32) tmp1 * tmp2) >> 15;
+ *(rr1--) = *rr2;
+ *rr1 = ((Word32) tmp11 * tmp22) >> 15;
+ *rr3 = *rr1;
+
+ rr1 -= (L_CODE);
+ rr2 -= (L_CODE + 1);
+ rr3 -= (L_CODE + 1);
+
+ }
+
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_h2), (Word32) * (p_h), s);
+
+ tmp1 = (Word16)((s + 0x00004000L) >> 15);
+
+ tmp2 = ((Word32) * (p_sign1) * *(p_sign2)) >> 15;
+ *rr1 = ((Word32) tmp1 * tmp2) >> 15;
+
+ *rr2 = *rr1;
+
+ rr1 -= (L_CODE + 1);
+ rr2 -= (L_CODE + 1);
+
+ }
+
+ return;
+
+}
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h.h b/media/libstagefright/codecs/amrnb/enc/src/cor_h.h
new file mode 100644
index 0000000..59b9d68
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/cor_h.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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef COR_H_H
+#define COR_H_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+#include "cor_h_x.h" /* Used by legacy files */
+#include "cor_h_x2.h" /* Used by legacy files */
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void cor_h(
+ Word16 h[], /* (i) : impulse response of weighted synthesis
+ filter */
+ Word16 sign[], /* (i) : sign of d[n] */
+ Word16 rr[][L_CODE], /* (o) : matrix of autocorrelation */
+ Flag *pOverflow
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h_x.cpp b/media/libstagefright/codecs/amrnb/enc/src/cor_h_x.cpp
new file mode 100644
index 0000000..beb2aec
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/cor_h_x.cpp
@@ -0,0 +1,320 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/cor_h_x.c
+
+ Date: 09/07/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created a separate file for cor_h_x function.
+
+ Description: Synchronized file with UMTS versin 3.2.0. Updated coding
+ template.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Modified FOR loop in the code to count down.
+ 2. Fixed typecasting issue with TI C compiler.
+
+ Description: Added call to round() and L_shl() functions in the last FOR
+ loop to make code bit-exact. Updated copyright year.
+
+ Description: Modified to pass pOverflow in via a pointer, rather than
+ invoking it as a global variable.
+
+ Description: Made the following changes
+ 1. Unrolled the correlation loop and add mechanism control
+ to compute odd or even number of computations.
+ 2. Use pointer to avoid continuos addresses calculation
+ 2. Eliminated math operations that check for saturation.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+#include "cor_h_x.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: cor_h_x
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ h = vector containing the impulse response of the weighted synthesis
+ filter; vector contents are of type Word16; vector length is
+ 2 * L_SUBFR
+ x = target signal vector; vector contents are of type Word16; vector
+ length is L_SUBFR
+ dn = vector containing the correlation between the target and the
+ impulse response; vector contents are of type Word16; vector
+ length is L_CODE
+ sf = scaling factor of type Word16 ; 2 when mode is MR122, 1 for all
+ other modes
+
+ Outputs:
+ dn contents are the newly calculated correlation values
+
+ pOverflow = pointer of type Flag * to overflow indicator.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes the correlation between the target signal (x) and the
+ impulse response (h).
+
+ The correlation is given by: d[n] = sum_{i=n}^{L-1} x[i] h[i-n],
+ where: n=0,...,L-1
+
+ d[n] is normalized such that the sum of 5 maxima of d[n] corresponding to
+ each position track does not saturate.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ cor_h.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void cor_h_x (
+ Word16 h[], // (i): impulse response of weighted synthesis filter
+ Word16 x[], // (i): target
+ Word16 dn[], // (o): correlation between target and h[]
+ Word16 sf // (i): scaling factor: 2 for 12.2, 1 for others
+)
+{
+ cor_h_x2(h, x, dn, sf, NB_TRACK, STEP);
+}
+
+
+void cor_h_x2 (
+ Word16 h[], // (i): impulse response of weighted synthesis filter
+ Word16 x[], // (i): target
+ Word16 dn[], // (o): correlation between target and h[]
+ Word16 sf, // (i): scaling factor: 2 for 12.2, 1 for others
+ Word16 nb_track,// (i): the number of ACB tracks
+ Word16 step // (i): step size from one pulse position to the next
+ in one track
+)
+{
+ Word16 i, j, k;
+ Word32 s, y32[L_CODE], max, tot;
+
+ // first keep the result on 32 bits and find absolute maximum
+
+ tot = 5;
+
+ for (k = 0; k < nb_track; k++)
+ {
+ max = 0;
+ for (i = k; i < L_CODE; i += step)
+ {
+ s = 0;
+ for (j = i; j < L_CODE; j++)
+ s = L_mac (s, x[j], h[j - i]);
+
+ y32[i] = s;
+
+ s = L_abs (s);
+ if (L_sub (s, max) > (Word32) 0L)
+ max = s;
+ }
+ tot = L_add (tot, L_shr (max, 1));
+ }
+
+ j = sub (norm_l (tot), sf);
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ dn[i] = pv_round (L_shl (y32[i], j));
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void cor_h_x(
+ Word16 h[], /* (i): impulse response of weighted synthesis filter */
+ Word16 x[], /* (i): target */
+ Word16 dn[], /* (o): correlation between target and h[] */
+ Word16 sf, /* (i): scaling factor: 2 for 12.2, 1 for others */
+ Flag *pOverflow /* (o): pointer to overflow flag */
+)
+{
+ register Word16 i;
+ register Word16 j;
+ register Word16 k;
+
+ Word32 s;
+ Word32 y32[L_CODE];
+ Word32 max;
+ Word32 tot;
+
+ Word16 *p_x;
+ Word16 *p_ptr;
+ Word32 *p_y32;
+
+
+ tot = 5;
+ for (k = 0; k < NB_TRACK; k++) /* NB_TRACK = 5 */
+ {
+ max = 0;
+ for (i = k; i < L_CODE; i += STEP) /* L_CODE = 40; STEP = 5 */
+ {
+ s = 0;
+ p_x = &x[i];
+ p_ptr = h;
+
+ for (j = (L_CODE - i - 1) >> 1; j != 0; j--)
+ {
+ s += ((Word32) * (p_x++) * *(p_ptr++)) << 1;
+ s += ((Word32) * (p_x++) * *(p_ptr++)) << 1;
+ }
+
+ s += ((Word32) * (p_x++) * *(p_ptr++)) << 1;
+
+ if (!((L_CODE - i) & 1)) /* if even number of iterations */
+ {
+ s += ((Word32) * (p_x++) * *(p_ptr++)) << 1;
+ }
+
+ y32[i] = s;
+
+ if (s < 0)
+ {
+ s = -s;
+ }
+
+ if (s > max)
+ {
+ max = s;
+ }
+ }
+
+ tot += (max >> 1);
+ }
+
+
+ j = norm_l(tot) - sf;
+
+ p_ptr = dn;
+ p_y32 = y32;;
+
+ for (i = L_CODE >> 1; i != 0; i--)
+ {
+ s = L_shl(*(p_y32++), j, pOverflow);
+ *(p_ptr++) = (s + 0x00008000) >> 16;
+ s = L_shl(*(p_y32++), j, pOverflow);
+ *(p_ptr++) = (s + 0x00008000) >> 16;
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h_x.h b/media/libstagefright/codecs/amrnb/enc/src/cor_h_x.h
new file mode 100644
index 0000000..66ada72
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/cor_h_x.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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains prototype declaration for cor_h_x function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef COR_H_X_H
+#define COR_H_X_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void cor_h_x(
+ Word16 h[], /* (i): impulse response of weighted synthesis filter */
+ Word16 x[], /* (i): target */
+ Word16 dn[], /* (o): correlation between target and h[] */
+ Word16 sf, /* (i): scaling factor: 2 for 12.2, 1 for others */
+ Flag *pOverflow /* (o): pointer to overflow flag */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.cpp b/media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.cpp
new file mode 100644
index 0000000..da60640
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.cpp
@@ -0,0 +1,282 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/cor_h_x2.c
+
+ Date: 11/07/2001
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created a separate file for cor_h_x2 function.
+
+ Description: Fixed typecasting issue with TI C compiler and defined one
+ local variable per line. Updated copyright year.
+
+ Description: Added #define for log2(32) = 5.
+
+ Description: Added call to round() and L_shl() functions in the last FOR
+ loop to make code bit-exact.
+
+ Description: Added pOverflow as a variable that's passed in for the EPOC
+ modifications.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Using intrinsics from fxp_arithmetic.h .
+
+ Description: Replacing fxp_arithmetic.h with basic_op.h.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+#include "cor_h_x.h"
+#include "cor_h_x2.h" // BX
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define LOG2_OF_32 5
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: cor_h_x2
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ h = vector containing the impulse response of the weighted synthesis
+ filter; vector contents are of type Word16; vector length is
+ 2 * L_SUBFR
+ x = target signal vector; vector contents are of type Word16; vector
+ length is L_SUBFR
+ dn = vector containing the correlation between the target and the
+ impulse response; vector contents are of type Word16; vector
+ length is L_CODE
+ sf = scaling factor of type Word16 ; 2 when mode is MR122, 1 for all
+ other modes
+ nb_track = number of ACB tracks (Word16)
+ step = step size between pulses in one track (Word16)
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ dn contents are the newly calculated correlation values
+ pOverflow = 1 if the math functions called by cor_h_x2 result in overflow
+ else zero.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes the correlation between the target signal (x) and the
+ impulse response (h).
+
+ The correlation is given by: d[n] = sum_{i=n}^{L-1} x[i] h[i-n],
+ where: n=0,...,L-1
+
+ d[n] is normalized such that the sum of 5 maxima of d[n] corresponding to
+ each position track does not saturate.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ cor_h.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+The original etsi reference code uses a global flag Overflow. However, in the
+actual implementation a pointer to a the overflow flag is passed in.
+
+void cor_h_x2 (
+ Word16 h[], // (i): impulse response of weighted synthesis filter
+ Word16 x[], // (i): target
+ Word16 dn[], // (o): correlation between target and h[]
+ Word16 sf, // (i): scaling factor: 2 for 12.2, 1 for others
+ Word16 nb_track,// (i): the number of ACB tracks
+ Word16 step // (i): step size from one pulse position to the next
+ in one track
+)
+{
+ Word16 i, j, k;
+ Word32 s, y32[L_CODE], max, tot;
+
+ // first keep the result on 32 bits and find absolute maximum
+
+ tot = 5;
+
+ for (k = 0; k < nb_track; k++)
+ {
+ max = 0;
+ for (i = k; i < L_CODE; i += step)
+ {
+ s = 0;
+ for (j = i; j < L_CODE; j++)
+ s = L_mac (s, x[j], h[j - i]);
+
+ y32[i] = s;
+
+ s = L_abs (s);
+ if (L_sub (s, max) > (Word32) 0L)
+ max = s;
+ }
+ tot = L_add (tot, L_shr (max, 1));
+ }
+
+ j = sub (norm_l (tot), sf);
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ dn[i] = pv_round (L_shl (y32[i], j));
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void cor_h_x2(
+ Word16 h[], /* (i): impulse response of weighted synthesis filter */
+ Word16 x[], /* (i): target */
+ Word16 dn[], /* (o): correlation between target and h[] */
+ Word16 sf, /* (i): scaling factor: 2 for 12.2, 1 for others */
+ Word16 nb_track,/* (i): the number of ACB tracks */
+ Word16 step, /* (i): step size from one pulse position to the next
+ in one track */
+ Flag *pOverflow
+)
+{
+ register Word16 i;
+ register Word16 j;
+ register Word16 k;
+ Word32 s;
+ Word32 y32[L_CODE];
+ Word32 max;
+ Word32 tot;
+
+
+ /* first keep the result on 32 bits and find absolute maximum */
+ tot = LOG2_OF_32;
+ for (k = 0; k < nb_track; k++)
+ {
+ max = 0;
+ for (i = k; i < L_CODE; i += step)
+ {
+ s = 0;
+
+ for (j = i; j < L_CODE; j++)
+ {
+ s = amrnb_fxp_mac_16_by_16bb((Word32)x[j], (Word32)h[j-i], s);
+ }
+
+ s = s << 1;
+ y32[i] = s;
+ s = L_abs(s);
+
+ if (s > max)
+ {
+ max = s;
+ }
+ }
+ tot = (tot + (max >> 1));
+ }
+
+ j = sub(norm_l(tot), sf, pOverflow);
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ dn[i] = pv_round(L_shl(y32[i], j, pOverflow), pOverflow);
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.h b/media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.h
new file mode 100644
index 0000000..f2b482c
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/cor_h_x2.h
@@ -0,0 +1,121 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/include/cor_h_x2.h
+
+ Date: 11/07/2001
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Created separate header file for cor_h_x2.
+
+ Description: Added pOverflow for EPOC modifications
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains prototype declaration for cor_h_x2 function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef COR_H_X2_H
+#define COR_H_X2_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void cor_h_x2(
+ Word16 h[], /* (i): impulse response of weighted synthesis filter */
+ Word16 x[], /* (i): target */
+ Word16 dn[], /* (o): correlation between target and h[] */
+ Word16 sf, /* (i): scaling factor: 2 for 12.2, 1 for others */
+ Word16 nb_track,/* (i): the number of ACB tracks */
+ Word16 step, /* (i): step size from one pulse position to the next
+ in one track */
+ Flag *pOverflow
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _COR_H_X2_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/corrwght_tab.cpp b/media/libstagefright/codecs/amrnb/enc/src/corrwght_tab.cpp
new file mode 100644
index 0000000..b3ed02d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/corrwght_tab.cpp
@@ -0,0 +1,199 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+
+
+
+ Filename: /audio/gsm_amr/c/src/corrwght_tab.c
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the tables for correlation weights
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "p_ol_wgh.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here. Include conditional
+ ; compile variables also.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; [Variable declaration - defined here and used outside this module]
+ ----------------------------------------------------------------------------*/
+ const Word16 corrweight[251] =
+ {
+ 20473, 20506, 20539, 20572, 20605, 20644, 20677,
+ 20716, 20749, 20788, 20821, 20860, 20893, 20932,
+ 20972, 21011, 21050, 21089, 21129, 21168, 21207,
+ 21247, 21286, 21332, 21371, 21417, 21456, 21502,
+ 21542, 21588, 21633, 21679, 21725, 21771, 21817,
+ 21863, 21909, 21961, 22007, 22059, 22105, 22158,
+ 22210, 22263, 22315, 22367, 22420, 22472, 22531,
+ 22584, 22643, 22702, 22761, 22820, 22879, 22938,
+ 23003, 23062, 23128, 23193, 23252, 23324, 23390,
+ 23455, 23527, 23600, 23665, 23744, 23816, 23888,
+ 23967, 24045, 24124, 24202, 24288, 24366, 24451,
+ 24537, 24628, 24714, 24805, 24904, 24995, 25094,
+ 25192, 25297, 25395, 25500, 25611, 25723, 25834,
+ 25952, 26070, 26188, 26313, 26444, 26575, 26706,
+ 26844, 26988, 27132, 27283, 27440, 27597, 27761,
+ 27931, 28108, 28285, 28475, 28665, 28869, 29078,
+ 29295, 29524, 29760, 30002, 30258, 30527, 30808,
+ 31457, 32767, 32767, 32767, 32767, 32767,
+ 32767, 32767, 31457, 30808, 30527, 30258, 30002,
+ 29760, 29524, 29295, 29078, 28869, 28665, 28475,
+ 28285, 28108, 27931, 27761, 27597, 27440, 27283,
+ 27132, 26988, 26844, 26706, 26575, 26444, 26313,
+ 26188, 26070, 25952, 25834, 25723, 25611, 25500,
+ 25395, 25297, 25192, 25094, 24995, 24904, 24805,
+ 24714, 24628, 24537, 24451, 24366, 24288, 24202,
+ 24124, 24045, 23967, 23888, 23816, 23744, 23665,
+ 23600, 23527, 23455, 23390, 23324, 23252, 23193,
+ 23128, 23062, 23003, 22938, 22879, 22820, 22761,
+ 22702, 22643, 22584, 22531, 22472, 22420, 22367,
+ 22315, 22263, 22210, 22158, 22105, 22059, 22007,
+ 21961, 21909, 21863, 21817, 21771, 21725, 21679,
+ 21633, 21588, 21542, 21502, 21456, 21417, 21371,
+ 21332, 21286, 21247, 21207, 21168, 21129, 21089,
+ 21050, 21011, 20972, 20932, 20893, 20860, 20821,
+ 20788, 20749, 20716, 20677, 20644, 20605, 20572,
+ 20539, 20506, 20473, 20434, 20401, 20369, 20336
+ };
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ None
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] corrwght.tab, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/dtx_enc.cpp b/media/libstagefright/codecs/amrnb/enc/src/dtx_enc.cpp
new file mode 100644
index 0000000..276e590
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/dtx_enc.cpp
@@ -0,0 +1,1163 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/dtx_enc.c
+ Funtions: dtx_enc_init
+ dtx_enc_reset
+ dtx_enc_exit
+ dtx_enc
+ dtx_buffer
+ tx_dtx_handler
+
+ Date: 06/08/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template. First attempt at
+ optimizing C code.
+
+ Description: Updated file per comments gathered from Phase 2/3 review.
+ Synched up with new template (Inputs/Outputs section). Deleted
+ lines leftover from original code prior to the code section of
+ dtx_enc_exit function. Deleted confusing comment in the log_en
+ calculation in dtx_enc function. Restructured IF statement in
+ the calculation of the sum of squares of speech signals in
+ dtx_buffer.
+
+ Description: Added setting of Overflow flag in inlined code.
+
+ Description: Synchronized file with UTMS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Modified FOR loops to count down.
+ 2. Fixed typecasting issue with TI C compiler.
+ 3. Fixed comment in dtx_enc pseudo-code.
+ 4. Added dtx_enc code comment pertaining to possible assembly
+ implementation.
+
+ Description: Added calls to add() in tx_dtx_handler. Updated copyright year.
+
+ Description: Pass in pointer to overflow flag to all functions requiring this
+ flag. This is to make the library EPOC compatible.
+
+ Description: For dtx_enc_reset() only
+ 1. Replaced copy() with memcpy.
+ 2. Eliminated include file copy.h
+ 3. Eliminated printf statement
+ For dtx_buffer()
+ 1. Replaced copy() with memcpy.
+ 2. Eliminated math operations that unnecessary checked for
+ saturation, in some cases this by shifting before adding and
+ in other cases by evaluating the operands
+ 3. Unrolled loop to speed up execution
+
+ Description: For dtx_buffer()
+ 1. Modified scaling and added check for saturation. Previous
+ scaling was correct but altered precision, this cause bit
+ exactness test failure.
+
+ Description: For dtx_buffer()
+ 1. Modified scaling and saturation checks. Previous
+ scaling was correct but altered precision, this cause bit
+ exactness test failure for dtx vad2.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the various functions that perform the computation of the
+ Silence Indicator (SID) parameters when in Discontinuous Transmission (DTX)
+ mode.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+#include <string.h>
+
+#include "dtx_enc.h"
+#include "q_plsf.h"
+#include "typedef.h"
+#include "mode.h"
+#include "basic_op.h"
+#include "log2.h"
+#include "lsp_lsf.h"
+#include "reorder.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+extern Word32 L_add(register Word32 L_var1, register Word32 L_var2, Flag *pOverflow);
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: dtx_enc_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to an array of pointers to structures of type
+ dtx_encState
+
+ Outputs:
+ pointer pointed to by st is set to the address of the allocated
+ memory
+
+ Returns:
+ return_value = 0, if initialization was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function allocates the state memory used by the dtx_enc function.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dtx_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int dtx_enc_init (dtx_encState **st)
+{
+ 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 *) malloc(sizeof(dtx_encState))) == NULL){
+ fprintf(stderr, "dtx_enc_init: can not malloc state structure\n");
+ return -1;
+ }
+
+ dtx_enc_reset(s);
+ *st = s;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 dtx_enc_init(dtx_encState **st)
+{
+ dtx_encState* s;
+
+ if (st == (dtx_encState **) NULL)
+ {
+ return(-1);
+ }
+
+ *st = NULL;
+
+ /* allocate memory */
+ if ((s = (dtx_encState *) malloc(sizeof(dtx_encState))) == NULL)
+ {
+ return(-1);
+ }
+
+ dtx_enc_reset(s);
+ *st = s;
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: dtx_enc_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to structures of type dtx_encState
+
+ Outputs:
+ structure pointed to by st is initialized to its reset value
+
+ Returns:
+ return_value = 1, if reset was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ lsp_init_data = table containing LSP initialization values;
+ table elements are constants of type Word16;
+ table length is M
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function initializes the fields of the state memory used by dtx_enc
+ to their reset values.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dtx_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int dtx_enc_reset (dtx_encState *st)
+{
+ Word16 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;
+ st->init_lsf_vq_index = 0;
+ st->lsp_index[0] = 0;
+ st->lsp_index[1] = 0;
+ st->lsp_index[2] = 0;
+
+ // Init lsp_hist[]
+ for(i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ Copy(lsp_init_data, &st->lsp_hist[i * M], M);
+ }
+
+ // Reset energy history
+ Set_zero(st->log_en_hist, M);
+
+ st->dtxHangoverCount = DTX_HANG_CONST;
+ st->decAnaElapsedCount = 32767;
+
+ return 1;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 dtx_enc_reset(dtx_encState *st)
+{
+ Word16 i;
+
+ if (st == (dtx_encState *) NULL)
+ {
+ return(-1);
+ }
+
+ st->hist_ptr = 0;
+ st->log_en_index = 0;
+ st->init_lsf_vq_index = 0;
+ st->lsp_index[0] = 0;
+ st->lsp_index[1] = 0;
+ st->lsp_index[2] = 0;
+
+ /* Init lsp_hist[] */
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ memcpy(&st->lsp_hist[i * M], lsp_init_data, M*sizeof(Word16));
+ }
+
+ /* Reset energy history */
+ memset(st->log_en_hist, 0, sizeof(Word16)*M);
+ st->dtxHangoverCount = DTX_HANG_CONST;
+ st->decAnaElapsedCount = 32767;
+
+ return(1);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: dtx_enc_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to an array of pointers to structures of type
+ dtx_encState
+
+ Outputs:
+ st points to the NULL address
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function deallocates the state memory used by dtx_enc function.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dtx_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void dtx_enc_exit (dtx_encState **st)
+{
+ if (st == NULL || *st == NULL)
+ return;
+
+ // deallocate memory
+ free(*st);
+ *st = NULL;
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void dtx_enc_exit(dtx_encState **st)
+{
+ if (st == NULL || *st == NULL)
+ {
+ return;
+ }
+
+ /* deallocate memory */
+ free(*st);
+ *st = NULL;
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: dtx_enc
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to structures of type dtx_encState
+ computeSidFlag = compute SID flag of type Word16
+ qSt = pointer to structures of type Q_plsfState
+ predState = pointer to structures of type gc_predState
+ anap = pointer to an array of pointers to analysis parameters of
+ type Word16
+
+ Outputs:
+ structure pointed to by st contains the newly calculated SID
+ parameters
+ structure pointed to by predState contains the new logarithmic frame
+ energy
+ pointer pointed to by anap points to the location of the new
+ logarithmic frame energy and new LSPs
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function calculates the SID parameters when in the DTX mode.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dtx_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int dtx_enc(dtx_encState *st, // i/o : State struct
+ Word16 computeSidFlag, // i : compute SID
+ Q_plsfState *qSt, // i/o : Qunatizer state struct
+ gc_predState* predState, // i/o : State struct
+ Word16 **anap // o : analysis parameters
+ )
+{
+ Word16 i,j;
+ Word16 log_en;
+ Word16 lsf[M];
+ Word16 lsp[M];
+ Word16 lsp_q[M];
+ Word32 L_lsp[M];
+
+ // VOX mode computation of SID parameters
+ if ((computeSidFlag != 0) ||
+ (st->log_en_index == 0))
+ {
+ // compute new SID frame if safe i.e don't
+ // compute immediately after a talk spurt
+ log_en = 0;
+ for (i = 0; i < M; i++)
+ {
+ L_lsp[i] = 0;
+ }
+
+ // average energy and lsp
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ log_en = add(log_en,
+ shr(st->log_en_hist[i],2));
+
+ for (j = 0; j < M; j++)
+ {
+ L_lsp[j] = L_add(L_lsp[j],
+ L_deposit_l(st->lsp_hist[i * M + j]));
+ }
+ }
+
+ log_en = shr(log_en, 1);
+ for (j = 0; j < M; j++)
+ {
+ lsp[j] = extract_l(L_shr(L_lsp[j], 3)); // divide by 8
+ }
+
+ // quantize logarithmic energy to 6 bits
+ st->log_en_index = add(log_en, 2560); // +2.5 in Q10
+ st->log_en_index = add(st->log_en_index, 128); // add 0.5/4 in Q10
+ st->log_en_index = shr(st->log_en_index, 8);
+
+ if (sub(st->log_en_index, 63) > 0)
+ {
+ st->log_en_index = 63;
+ }
+ if (st->log_en_index < 0)
+ {
+ st->log_en_index = 0;
+ }
+
+ // update gain predictor memory
+ log_en = shl(st->log_en_index, -2+10); // Q11 and divide by 4
+ log_en = sub(log_en, 2560); // add 2.5 in Q11
+
+ log_en = sub(log_en, 9000);
+ if (log_en > 0)
+ {
+ log_en = 0;
+ }
+ if (sub(log_en, -14436) < 0)
+ {
+ log_en = -14436;
+ }
+
+ // past_qua_en for other modes than MR122
+ predState->past_qua_en[0] = log_en;
+ predState->past_qua_en[1] = log_en;
+ predState->past_qua_en[2] = log_en;
+ predState->past_qua_en[3] = log_en;
+
+ // scale down by factor 20*log10(2) in Q15
+ log_en = mult(5443, log_en);
+
+ // past_qua_en for mode MR122
+ predState->past_qua_en_MR122[0] = log_en;
+ predState->past_qua_en_MR122[1] = log_en;
+ predState->past_qua_en_MR122[2] = log_en;
+ predState->past_qua_en_MR122[3] = log_en;
+
+ // make sure that LSP's are ordered
+ Lsp_lsf(lsp, lsf, M);
+ Reorder_lsf(lsf, LSF_GAP, M);
+ Lsf_lsp(lsf, lsp, M);
+
+ // Quantize lsp and put on parameter list
+ Q_plsf_3(qSt, MRDTX, lsp, lsp_q, st->lsp_index,
+ &st->init_lsf_vq_index);
+ }
+
+ *(*anap)++ = st->init_lsf_vq_index; // 3 bits
+
+ *(*anap)++ = st->lsp_index[0]; // 8 bits
+ *(*anap)++ = st->lsp_index[1]; // 9 bits
+ *(*anap)++ = st->lsp_index[2]; // 9 bits
+
+
+ *(*anap)++ = st->log_en_index; // 6 bits
+ // = 35 bits
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void dtx_enc(dtx_encState *st, /* i/o : State struct */
+ Word16 computeSidFlag, /* i : compute SID */
+ Q_plsfState *qSt, /* i/o : Qunatizer state struct */
+ gc_predState* predState, /* i/o : State struct */
+ Word16 **anap, /* o : analysis parameters */
+ Flag *pOverflow /* i/o : overflow indicator */
+ )
+{
+ register Word16 i, j;
+ Word16 temp;
+ Word16 log_en;
+ Word16 lsf[M];
+ Word16 lsp[M];
+ Word16 lsp_q[M];
+ Word32 L_lsp[M];
+
+ /* VOX mode computation of SID parameters */
+
+ if ((computeSidFlag != 0) ||
+ (st->log_en_index == 0))
+ {
+ /* compute new SID frame if safe i.e don't
+ * compute immediately after a talk spurt */
+ log_en = 0;
+ for (i = M - 1; i >= 0; i--)
+ {
+ L_lsp[i] = 0;
+ }
+
+ /* average energy and lsp */
+ for (i = DTX_HIST_SIZE - 1; i >= 0; i--)
+ {
+ if (st->log_en_hist[i] < 0)
+ {
+ temp = ~((~(st->log_en_hist[i])) >> 2);
+ }
+ else
+ {
+ temp = st->log_en_hist[i] >> 2;
+ }
+ log_en = add(log_en, temp, pOverflow);
+
+ for (j = M - 1; j >= 0; j--)
+ {
+ L_lsp[j] = L_add(L_lsp[j],
+ (Word32)(st->lsp_hist[i * M + j]),
+ pOverflow);
+ }
+ }
+
+ if (log_en < 0)
+ {
+ log_en = ~((~log_en) >> 1);
+ }
+ else
+ {
+ log_en = log_en >> 1;
+ }
+
+ for (j = M - 1; j >= 0; j--)
+ {
+ /* divide by 8 */
+ if (L_lsp[j] < 0)
+ {
+ lsp[j] = (Word16)(~((~L_lsp[j]) >> 3));
+ }
+ else
+ {
+ lsp[j] = (Word16)(L_lsp[j] >> 3);
+ }
+ }
+
+ /* quantize logarithmic energy to 6 bits */
+ /* +2.5 in Q10 */
+ st->log_en_index = add(log_en, 2560, pOverflow);
+ /* add 0.5/4 in Q10 */
+ st->log_en_index = add(st->log_en_index, 128, pOverflow);
+ if (st->log_en_index < 0)
+ {
+ st->log_en_index = ~((~st->log_en_index) >> 8);
+ }
+ else
+ {
+ st->log_en_index = st->log_en_index >> 8;
+ }
+
+ /*---------------------------------------------*/
+ /* Limit to max and min allowable 6-bit values */
+ /* Note: For assembly implementation, use the */
+ /* following: */
+ /* if(st->long_en_index >> 6 != 0) */
+ /* { */
+ /* if(st->long_en_index < 0) */
+ /* { */
+ /* st->long_en_index = 0 */
+ /* } */
+ /* else */
+ /* { */
+ /* st->long_en_index = 63 */
+ /* } */
+ /* } */
+ /*---------------------------------------------*/
+ if (st->log_en_index > 63)
+ {
+ st->log_en_index = 63;
+ }
+ else if (st->log_en_index < 0)
+ {
+ st->log_en_index = 0;
+ }
+
+ /* update gain predictor memory */
+ /* Q11 and divide by 4 */
+ log_en = (Word16)(((Word32) st->log_en_index) << (-2 + 10));
+
+ log_en = sub(log_en, 11560, pOverflow);
+
+ if (log_en > 0)
+ {
+ log_en = 0;
+ }
+ else if (log_en < -14436)
+ {
+ log_en = -14436;
+ }
+
+ /* past_qua_en for other modes than MR122 */
+ predState->past_qua_en[0] = log_en;
+ predState->past_qua_en[1] = log_en;
+ predState->past_qua_en[2] = log_en;
+ predState->past_qua_en[3] = log_en;
+
+ /* scale down by factor 20*log10(2) in Q15 */
+ log_en = (Word16)(((Word32)(5443 * log_en)) >> 15);
+
+ /* past_qua_en for mode MR122 */
+ predState->past_qua_en_MR122[0] = log_en;
+ predState->past_qua_en_MR122[1] = log_en;
+ predState->past_qua_en_MR122[2] = log_en;
+ predState->past_qua_en_MR122[3] = log_en;
+
+ /* make sure that LSP's are ordered */
+ Lsp_lsf(lsp, lsf, M, pOverflow);
+ Reorder_lsf(lsf, LSF_GAP, M, pOverflow);
+ Lsf_lsp(lsf, lsp, M, pOverflow);
+
+ /* Quantize lsp and put on parameter list */
+ Q_plsf_3(qSt, MRDTX, lsp, lsp_q, st->lsp_index,
+ &st->init_lsf_vq_index, pOverflow);
+ }
+
+ *(*anap)++ = st->init_lsf_vq_index; /* 3 bits */
+ *(*anap)++ = st->lsp_index[0]; /* 8 bits */
+ *(*anap)++ = st->lsp_index[1]; /* 9 bits */
+ *(*anap)++ = st->lsp_index[2]; /* 9 bits */
+ *(*anap)++ = st->log_en_index; /* 6 bits */
+ /* = 35 bits */
+
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: dtx_buffer
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to structures of type dtx_encState
+ lsp_new = LSP vector whose elements are of type Word16; vector
+ length is M
+ speech = vector of speech samples of type Word16; vector length is
+ BFR_SIZE_GSM
+
+ Outputs:
+ structure pointed to by st contains the new LSPs and logarithmic
+ frame energy
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function handles the DTX buffer.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dtx_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int dtx_buffer(dtx_encState *st, // i/o : State struct
+ Word16 lsp_new[], // i : LSP vector
+ Word16 speech[] // i : speech samples
+)
+{
+ Word16 i;
+ Word32 L_frame_en;
+ Word16 log_en_e;
+ Word16 log_en_m;
+ Word16 log_en;
+
+ // update pointer to circular buffer
+ st->hist_ptr = add(st->hist_ptr, 1);
+ if (sub(st->hist_ptr, DTX_HIST_SIZE) == 0)
+ {
+ st->hist_ptr = 0;
+ }
+
+ // copy lsp vector into buffer
+ Copy(lsp_new, &st->lsp_hist[st->hist_ptr * M], M);
+
+ // compute log energy based on frame energy
+ L_frame_en = 0; // Q0
+ for (i=0; i < L_FRAME; i++)
+ {
+ L_frame_en = L_mac(L_frame_en, speech[i], speech[i]);
+ }
+ Log2(L_frame_en, &log_en_e, &log_en_m);
+
+ // convert exponent and mantissa to Word16 Q10
+ log_en = shl(log_en_e, 10); // Q10
+ log_en = add(log_en, shr(log_en_m, 15-10));
+
+ // divide with L_FRAME i.e subtract with log2(L_FRAME) = 7.32193
+ log_en = sub(log_en, 8521);
+
+ // insert into log energy buffer with division by 2
+ log_en = shr(log_en, 1);
+ st->log_en_hist[st->hist_ptr] = log_en; // Q10
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void dtx_buffer(dtx_encState *st, /* i/o : State struct */
+ Word16 lsp_new[], /* i : LSP vector */
+ Word16 speech[], /* i : speech samples */
+ Flag *pOverflow /* i/o : overflow indicator */
+ )
+{
+
+ register Word16 i;
+ Word32 L_frame_en;
+ Word32 L_temp;
+ Word16 log_en_e;
+ Word16 log_en_m;
+ Word16 log_en;
+ Word16 *p_speech = &speech[0];
+
+ /* update pointer to circular buffer */
+ st->hist_ptr += 1;
+
+ if (st->hist_ptr == DTX_HIST_SIZE)
+ {
+ st->hist_ptr = 0;
+ }
+
+ /* copy lsp vector into buffer */
+ memcpy(&st->lsp_hist[st->hist_ptr * M], lsp_new, M*sizeof(Word16));
+
+ /* compute log energy based on frame energy */
+ L_frame_en = 0; /* Q0 */
+
+ for (i = L_FRAME; i != 0; i--)
+ {
+ L_frame_en += (((Word32) * p_speech) * *(p_speech)) << 1;
+ p_speech++;
+ if (L_frame_en < 0)
+ {
+ L_frame_en = MAX_32;
+ break;
+ }
+ }
+
+ Log2(L_frame_en, &log_en_e, &log_en_m, pOverflow);
+
+ /* convert exponent and mantissa to Word16 Q10 */
+ /* Q10 */
+ L_temp = ((Word32) log_en_e) << 10;
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ *pOverflow = 1;
+ log_en = (log_en_e > 0) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ log_en = (Word16) L_temp;
+ }
+
+ log_en += log_en_m >> (15 - 10);
+
+ /* divide with L_FRAME i.e subtract with log2(L_FRAME) = 7.32193 */
+ log_en -= 8521;
+
+ /* insert into log energy buffer with division by 2 */
+
+ st->log_en_hist[st->hist_ptr] = log_en >> 1; /* Q10 */
+
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: tx_dtx_handler
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to structures of type dtx_encState
+ vad_flag = VAD decision flag of type Word16
+ usedMode = pointer to the currently used mode of type enum Mode
+
+ Outputs:
+ structure pointed to by st contains the newly calculated speech
+ hangover
+
+ Returns:
+ compute_new_sid_possible = flag to indicate a change in the
+ used mode; store type is Word16
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function adds extra speech hangover to analyze speech on the decoding
+ side.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ dtx_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 tx_dtx_handler(dtx_encState *st, // i/o : State struct
+ Word16 vad_flag, // i : vad decision
+ enum Mode *usedMode // i/o : mode changed or not
+ )
+{
+ Word16 compute_new_sid_possible;
+
+ // this state machine is in synch with the GSMEFR txDtx machine
+ st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1);
+
+ compute_new_sid_possible = 0;
+
+ 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;
+ compute_new_sid_possible = 1;
+ }
+ 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 compute_new_sid_possible;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 tx_dtx_handler(dtx_encState *st, /* i/o : State struct */
+ Word16 vad_flag, /* i : vad decision */
+ enum Mode *usedMode, /* i/o : mode changed or not */
+ Flag *pOverflow /* i/o : overflow indicator */
+ )
+{
+ Word16 compute_new_sid_possible;
+ Word16 count;
+
+ /* this state machine is in synch with the GSMEFR txDtx machine */
+ st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1, pOverflow);
+
+ compute_new_sid_possible = 0;
+
+ 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;
+ compute_new_sid_possible = 1;
+ }
+ else
+ { /* in possible analysis hangover */
+ st->dtxHangoverCount -= 1;
+
+ /* decAnaElapsedCount + dtxHangoverCount < */
+ /* DTX_ELAPSED_FRAMES_THRESH */
+ count = add(st->decAnaElapsedCount, st->dtxHangoverCount,
+ pOverflow);
+ if (count < DTX_ELAPSED_FRAMES_THRESH)
+ {
+ *usedMode = MRDTX;
+ /* if short time since decoder update, */
+ /* do not add extra HO */
+ }
+ }
+ }
+
+ return(compute_new_sid_possible);
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/dtx_enc.h b/media/libstagefright/codecs/amrnb/enc/src/dtx_enc.h
new file mode 100644
index 0000000..5bb168d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/dtx_enc.h
@@ -0,0 +1,209 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/dtx_enc.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : dtx_enc.h
+ Purpose : DTX mode computation of SID parameters
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef dtx_enc_h
+#define dtx_enc_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+#include "q_plsf.h"
+#include "gc_pred.h"
+#include "mode.h"
+#include "dtx_common_def.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+ extern const Word16 lsp_init_data[];
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 lsp_hist[M * DTX_HIST_SIZE];
+ Word16 log_en_hist[DTX_HIST_SIZE];
+ Word16 hist_ptr;
+ Word16 log_en_index;
+ Word16 init_lsf_vq_index;
+ Word16 lsp_index[3];
+
+ /* DTX handler stuff */
+ Word16 dtxHangoverCount;
+ Word16 decAnaElapsedCount;
+
+ } dtx_encState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ /*
+ **************************************************************************
+ * Function : dtx_enc_init
+ * Purpose : Allocates memory and initializes state variables
+ * Description : Stores pointer to filter status struct in *st. This
+ * pointer has to be passed to dtx_enc in each call.
+ * Returns : 0 on success
+ *
+ **************************************************************************
+ */
+ Word16 dtx_enc_init(dtx_encState **st);
+
+ /*
+ **************************************************************************
+ *
+ * Function : dtx_enc_reset
+ * Purpose : Resets state memory
+ * Returns : 0 on success
+ *
+ **************************************************************************
+ */
+ Word16 dtx_enc_reset(dtx_encState *st);
+
+ /*
+ **************************************************************************
+ *
+ * Function : dtx_enc_exit
+ * Purpose : The memory used for state memory is freed
+ * Description : Stores NULL in *st
+ *
+ **************************************************************************
+ */
+ void dtx_enc_exit(dtx_encState **st);
+
+ /*
+ **************************************************************************
+ *
+ * Function : dtx_enc
+ * Purpose :
+ * Description :
+ *
+ **************************************************************************
+ */
+ void dtx_enc(dtx_encState *st, /* i/o : State struct */
+ Word16 computeSidFlag, /* i : compute SID */
+ Q_plsfState *qSt, /* i/o : Qunatizer state struct */
+ gc_predState* predState, /* i/o : State struct */
+ Word16 **anap, /* o : analysis parameters */
+ Flag *pOverflow /* i/o : overflow indicator */
+ );
+
+ /*
+ **************************************************************************
+ *
+ * Function : dtx_buffer
+ * Purpose : handles the DTX buffer
+ *
+ **************************************************************************
+ */
+ void dtx_buffer(dtx_encState *st, /* i/o : State struct */
+ Word16 lsp_new[], /* i : LSP vector */
+ Word16 speech[], /* i : speech samples */
+ Flag *pOverflow /* i/o : overflow indicator */
+ );
+
+ /*
+ **************************************************************************
+ *
+ * Function : tx_dtx_handler
+ * Purpose : adds extra speech hangover to analyze speech on the decoding side.
+ * Description : returns 1 when a new SID analysis may be made
+ * otherwise it adds the appropriate hangover after a sequence
+ * with out updates of SID parameters .
+ *
+ **************************************************************************
+ */
+ Word16 tx_dtx_handler(dtx_encState *st, /* i/o : State struct */
+ Word16 vad_flag, /* i : vad decision */
+ enum Mode *usedMode, /* i/o : mode changed or not */
+ Flag *pOverflow /* i/o : overflow indicator */
+ );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _dtx_enc_h_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/enc_lag3.cpp b/media/libstagefright/codecs/amrnb/enc/src/enc_lag3.cpp
new file mode 100644
index 0000000..a1fc008
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/enc_lag3.cpp
@@ -0,0 +1,356 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/enc_lag3.c
+ Functions:
+
+ Date: 01/28/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "enc_lag3.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: enc_lag3
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ T0 = Pitch delay of type Word16
+ T0_frac = Fractional pitch delay of type Word16
+ T0_prev = Integer pitch delay of last subframe of type Word16
+ T0_min = minimum of search range of type Word16
+ T0_max = maximum of search range of type Word16
+ delta_flag = Flag for 1st (or 3rd) subframe of type Word16
+ flag4 = Flag for encoding with 4 bits of type Word16
+ pOverflow = pointer indicating overflow of type Flag
+
+ Outputs:
+ pOverflow = 1 if there is an overflow else it is zero.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function implements the encoding of fractional pitch lag with
+ 1/3 resolution.
+
+ * FUNCTION: Enc_lag3
+ *
+ * PURPOSE: Encoding of fractional pitch lag with 1/3 resolution.
+ *
+ * DESCRIPTION:
+ * First and third subframes:
+ * --------------------------
+ * The pitch range is divided as follows:
+ * 19 1/3 to 84 2/3 resolution 1/3
+ * 85 to 143 resolution 1
+ *
+ * The period is encoded with 8 bits.
+ * For the range with fractions:
+ * index = (T-19)*3 + frac - 1;
+ * where T=[19..85] and frac=[-1,0,1]
+ * and for the integer only range
+ * index = (T - 85) + 197; where T=[86..143]
+ *
+ * Second and fourth subframes:
+ * ----------------------------
+ * For the 2nd and 4th subframes a resolution of 1/3 is always used,
+ * and the search range is relative to the lag in previous subframe.
+ * If t0 is the lag in the previous subframe then
+ * t_min=t0-5 and t_max=t0+4 and the range is given by
+ * t_min - 2/3 to t_max + 2/3
+ *
+ * The period in the 2nd (and 4th) subframe is encoded with 5 bits:
+ * index = (T-(t_min-1))*3 + frac - 1;
+ * where T=[t_min-1..t_max+1]
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ enc_lag3.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Word16 index, i, tmp_ind, uplag;
+ Word16 tmp_lag;
+
+ if (delta_flag == 0)
+ { // if 1st or 3rd subframe
+
+ // encode pitch delay (with fraction)
+
+ if (sub (T0, 85) <= 0)
+ {
+ // index = T0*3 - 58 + T0_frac
+ i = add (add (T0, T0), T0);
+ index = add (sub (i, 58), T0_frac);
+ }
+ else
+ {
+ index = add (T0, 112);
+ }
+ }
+ else
+ { // if second or fourth subframe
+ if (flag4 == 0) {
+
+ // 'normal' encoding: either with 5 or 6 bit resolution
+
+ // index = 3*(T0 - T0_min) + 2 + T0_frac
+ i = sub (T0, T0_min);
+ i = add (add (i, i), i);
+ index = add (add (i, 2), T0_frac);
+ }
+ else {
+
+ // encoding with 4 bit resolution
+
+ tmp_lag = T0_prev;
+
+ if ( sub( sub(tmp_lag, T0_min), 5) > 0)
+ tmp_lag = add (T0_min, 5);
+ if ( sub( sub(T0_max, tmp_lag), 4) > 0)
+ tmp_lag = sub (T0_max, 4);
+
+ uplag = add (add (add (T0, T0), T0), T0_frac);
+
+ i = sub (tmp_lag, 2);
+ tmp_ind = add (add (i, i), i);
+
+ if (sub (tmp_ind, uplag) >= 0) {
+ index = add (sub (T0, tmp_lag), 5);
+ }
+ else {
+
+ i = add (tmp_lag, 1);
+ i = add (add (i, i), i);
+
+ if (sub (i, uplag) > 0) {
+
+ index = add ( sub (uplag, tmp_ind), 3);
+ }
+ else {
+
+ index = add (sub (T0, tmp_lag), 11);
+ }
+ }
+
+ } // end if (encoding with 4 bit resolution)
+ } // end if (second of fourth subframe)
+
+ return index;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+
+Word16 Enc_lag3( /* o : Return index of encoding */
+ Word16 T0, /* i : Pitch delay */
+ Word16 T0_frac, /* i : Fractional pitch delay */
+ Word16 T0_prev, /* i : Integer pitch delay of last subframe */
+ Word16 T0_min, /* i : minimum of search range */
+ Word16 T0_max, /* i : maximum of search range */
+ Word16 delta_flag, /* i : Flag for 1st (or 3rd) subframe */
+ Word16 flag4, /* i : Flag for encoding with 4 bits */
+ Flag *pOverflow
+)
+{
+ Word16 index, i, tmp_ind, uplag;
+ Word16 tmp_lag;
+ Word16 temp1;
+ Word16 temp2;
+
+
+
+ if (delta_flag == 0)
+ { /* if 1st or 3rd subframe */
+
+ /* encode pitch delay (with fraction) */
+ temp1 = sub(T0, 85, pOverflow);
+ if (temp1 <= 0)
+ {
+ /* index = T0*3 - 58 + T0_frac */
+ temp2 = add(T0, T0, pOverflow);
+ i = add(temp2, T0, pOverflow);
+ temp2 = sub(i, 58, pOverflow);
+ index = add(temp2, T0_frac, pOverflow);
+ }
+ else
+ {
+ index = add(T0, 112, pOverflow);
+ }
+ }
+ else
+ { /* if second or fourth subframe */
+ if (flag4 == 0)
+ {
+
+ /* 'normal' encoding: either with 5 or 6 bit resolution */
+
+ /* index = 3*(T0 - T0_min) + 2 + T0_frac */
+ i = sub(T0, T0_min, pOverflow);
+ temp2 = add(i, i, pOverflow);
+ i = add(temp2, i, pOverflow);
+ temp2 = add(i, 2, pOverflow);
+ index = add(temp2, T0_frac, pOverflow);
+ }
+ else
+ {
+
+ /* encoding with 4 bit resolution */
+
+ tmp_lag = T0_prev;
+ temp1 = sub(tmp_lag, T0_min, pOverflow);
+ temp2 = sub(temp1, 5, pOverflow);
+ if (temp2 > 0)
+ tmp_lag = add(T0_min, 5, pOverflow);
+ temp1 = sub(T0_max, tmp_lag, pOverflow);
+ temp2 = sub(temp1, 4, pOverflow);
+ if (temp2 > 0)
+ tmp_lag = sub(T0_max, 4, pOverflow);
+
+ temp1 = add(T0, T0, pOverflow);
+ temp2 = add(temp1, T0, pOverflow);
+ uplag = add(temp2, T0_frac, pOverflow);
+
+ i = sub(tmp_lag, 2, pOverflow);
+ temp1 = add(i, i, pOverflow);
+ tmp_ind = add(temp1, i, pOverflow);
+
+ temp1 = sub(tmp_ind, uplag, pOverflow);
+ if (temp1 >= 0)
+ {
+ temp1 = sub(T0, tmp_lag, pOverflow);
+ index = add(temp1, 5, pOverflow);
+ }
+ else
+ {
+
+ i = add(tmp_lag, 1, pOverflow);
+ temp1 = add(i, i, pOverflow);
+ i = add(temp1, i, pOverflow);
+
+ if (sub(i, uplag, pOverflow) > 0)
+ {
+ temp1 = sub(uplag, tmp_ind, pOverflow);
+ index = add(temp1, 3, pOverflow);
+ }
+ else
+ {
+ temp1 = sub(T0, tmp_lag, pOverflow);
+ index = add(temp1, 11, pOverflow);
+ }
+ }
+
+ } /* end if (encoding with 4 bit resolution) */
+ } /* end if (second of fourth subframe) */
+
+ return index;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/enc_lag3.h b/media/libstagefright/codecs/amrnb/enc/src/enc_lag3.h
new file mode 100644
index 0000000..949cd97
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/enc_lag3.h
@@ -0,0 +1,125 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/enc_lag3.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : enc_lag3.h
+ Purpose : Encoding of fractional pitch lag with 1/3 resolution.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _ENC_LAG3_H_
+#define _ENC_LAG3_H_
+#define enc_lag3_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 past_gain;
+ } agcState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ Word16
+ Enc_lag3( /* o : Return index of encoding */
+ Word16 T0, /* i : Pitch delay */
+ Word16 T0_frac, /* i : Fractional pitch delay */
+ Word16 T0_prev, /* i : Integer pitch delay of last subframe */
+ Word16 T0_min, /* i : minimum of search range */
+ Word16 T0_max, /* i : maximum of search range */
+ Word16 delta_flag, /* i : Flag for 1st (or 3rd) subframe */
+ Word16 flag4, /* i : Flag for encoding with 4 bits */
+ Flag *pOverflow
+ );
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ENC_LAG3_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/enc_lag6.cpp b/media/libstagefright/codecs/amrnb/enc/src/enc_lag6.cpp
new file mode 100644
index 0000000..2c7863e
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/enc_lag6.cpp
@@ -0,0 +1,230 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/enc_lag6.c
+ Functions:
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+ Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description:
+ (1) Removed optimization -- mult(i, 6, pOverflow) is NOT the same as adding
+ i to itself 6 times. The reason is because the mult function does a
+ right shift by 15, which will obliterate smaller numbers.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "enc_lag6.h"
+#include "typedef.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Enc_lag6
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ T0 -- Word16 -- Pitch delay
+ T0_frac -- Word16 -- Fractional pitch delay
+ T0_min -- Word16 -- minimum of search range
+ delta_flag -- Word16 -- Flag for 1st (or 3rd) subframe
+
+ Outputs:
+ pOverflow -- Pointer to Flag -- overflow indicator
+
+ Returns:
+ Word16 -- Return index of encoding
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Encoding of fractional pitch lag with 1/6 resolution.
+
+ DESCRIPTION:
+ First and third subframes:
+ --------------------------
+ The pitch range is divided as follows:
+ 17 3/6 to 94 3/6 resolution 1/6
+ 95 to 143 resolution 1
+
+ The period is encoded with 9 bits.
+ For the range with fractions:
+ index = (T-17)*6 + frac - 3;
+ where T=[17..94] and frac=[-2,-1,0,1,2,3]
+ and for the integer only range
+ index = (T - 95) + 463; where T=[95..143]
+
+ Second and fourth subframes:
+ ----------------------------
+ For the 2nd and 4th subframes a resolution of 1/6 is always used,
+ and the search range is relative to the lag in previous subframe.
+ If t0 is the lag in the previous subframe then
+ t_min=t0-5 and t_max=t0+4 and the range is given by
+ (t_min-1) 3/6 to (t_max) 3/6
+
+ The period in the 2nd (and 4th) subframe is encoded with 6 bits:
+ index = (T-(t_min-1))*6 + frac - 3;
+ where T=[t_min-1..t_max] and frac=[-2,-1,0,1,2,3]
+
+ Note that only 61 values are used. If the decoder receives 61, 62,
+ or 63 as the relative pitch index, it means that a transmission
+ error occurred and the pitch from previous subframe should be used.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ enc_lag6.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Enc_lag6( /* o : Return index of encoding */
+ Word16 T0, /* i : Pitch delay */
+ Word16 T0_frac, /* i : Fractional pitch delay */
+ Word16 T0_min, /* i : minimum of search range */
+ Word16 delta_flag, /* i : Flag for 1st (or 3rd) subframe */
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ Word16 index;
+ Word16 i;
+ Word16 temp;
+
+ if (delta_flag == 0) /* if 1st or 3rd subframe */
+ {
+ /* encode pitch delay (with fraction) */
+ if (T0 <= 94)
+ {
+ /* index = T0*6 - 105 + T0_frac */
+ i = 6 * T0 - 105;
+
+ index = add(i, T0_frac, pOverflow);
+ }
+ else
+ {
+ index = add(T0, 368, pOverflow);
+ }
+
+ }
+ else
+ /* if second or fourth subframe */
+ {
+ /* index = 6*(T0-T0_min) + 3 + T0_frac */
+ temp = sub(T0, T0_min, pOverflow);
+
+ i = add(temp, temp, pOverflow);
+ i = add(temp, i, pOverflow);
+ i = add(i, i, pOverflow);
+
+ i = add(i, 3, pOverflow);
+
+ index = add(i, T0_frac, pOverflow);
+ }
+
+ return index;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/enc_lag6.h b/media/libstagefright/codecs/amrnb/enc/src/enc_lag6.h
new file mode 100644
index 0000000..0438321
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/enc_lag6.h
@@ -0,0 +1,122 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/enc_lag6.h
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the file, enc_lag6.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef enc_lag6_h
+#define enc_lag6_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 Enc_lag6( /* o : Return index of encoding */
+ Word16 T0, /* i : Pitch delay */
+ Word16 T0_frac, /* i : Fractional pitch delay */
+ Word16 T0_min, /* i : minimum of search range */
+ Word16 delta_flag, /* i : Flag for 1st (or 3rd) subframe */
+ Flag *pOverflow /* o : Overflow indicator */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* enc_lag6_h */
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/enc_output_format_tab.cpp b/media/libstagefright/codecs/amrnb/enc/src/enc_output_format_tab.cpp
new file mode 100644
index 0000000..4551fd7
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/enc_output_format_tab.cpp
@@ -0,0 +1,232 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+ Pathname: .audio/gsm-amr/c/src/enc_output_format_tab.c
+
+ Date: 03/08/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved WMFBytesUsed and IF2BytesUsed tables from gsmamr_enc.h.
+ Changed their type definition to 'const int'. Renamed tables to
+ WmfEncBytesPerFrame and If2EncBytesPerFrame.
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition.
+
+ Description: Put "extern" back.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This file contains the tables of the number of data bytes per codec mode in
+ both WMF and IF2 output formats.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] AMR Speech Codec Frame Structure, 3GPP TS 26.101 version 4.1.0 Release 4,
+ June 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "amrencode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+ /* Number of data bytes in an encoder frame for each codec mode */
+ /* for WMF output format. */
+ /* Each entry is the sum of the 3GPP frame type byte and the */
+ /* number of packed core AMR data bytes */
+ const Word16 WmfEncBytesPerFrame[16] =
+ {
+ 13, /* 4.75 */
+ 14, /* 5.15 */
+ 16, /* 5.90 */
+ 18, /* 6.70 */
+ 20, /* 7.40 */
+ 21, /* 7.95 */
+ 27, /* 10.2 */
+ 32, /* 12.2 */
+ 6, /* GsmAmr comfort noise */
+ 7, /* Gsm-Efr comfort noise */
+ 6, /* IS-641 comfort noise */
+ 6, /* Pdc-Efr comfort noise */
+ 0, /* future use */
+ 0, /* future use */
+ 0, /* future use */
+ 1 /* No transmission */
+ };
+
+
+ /* Number of data bytes in an encoder frame for each codec mode */
+ /* for IF2 output format */
+ const Word16 If2EncBytesPerFrame[16] =
+ {
+ 13, /* 4.75 */
+ 14, /* 5.15 */
+ 16, /* 5.90 */
+ 18, /* 6.70 */
+ 19, /* 7.40 */
+ 21, /* 7.95 */
+ 26, /* 10.2 */
+ 31, /* 12.2 */
+ 6, /* GsmAmr comfort noise */
+ 6, /* Gsm-Efr comfort noise */
+ 6, /* IS-641 comfort noise */
+ 6, /* Pdc-Efr comfort noise */
+ 0, /* future use */
+ 0, /* future use */
+ 0, /* future use */
+ 1 /* No transmission */
+ };
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL FUNCTION REFERENCES
+ ; Declare functions defined elsewhere and referenced in this module
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; Define all local variables
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Function body here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Return nothing or data or data pointer
+----------------------------------------------------------------------------*/
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ets_to_if2.cpp b/media/libstagefright/codecs/amrnb/enc/src/ets_to_if2.cpp
new file mode 100644
index 0000000..01b8627
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/ets_to_if2.cpp
@@ -0,0 +1,242 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+ Pathname: ./audio/gsm-amr/c/src/ets_to_if2.c
+ Funtions: ets_to_if2
+
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "frame_type_3gpp.h"
+#include "ets_to_if2.h"
+#include "typedef.h"
+#include "bitreorder_tab.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ets_to_if2
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ frame_type_3gpp = decoder speech bit rate (enum Frame_Type_3GPP)
+ ets_input_ptr = pointer to input encoded speech bits in ETS format (Word16)
+ if2_output_ptr = pointer to output encoded speech bits in IF2 format (UWord8)
+
+ Outputs:
+ if2_output_ptr = pointer to encoded speech bits in the IF2 format (UWord8)
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs a transformation on the data buffers. It converts the
+ data format from ETS (European Telecommunication Standard) to IF2. ETS format
+ has the encoded speech bits each separate with only one bit stored in each
+ word. IF2 is the storage format where the frame type is in the first four bits
+ of the first byte. The upper four bits of that byte contain the first four
+ encoded speech bits for the frame. The following bytes contain the rest of
+ the encoded speech bits. The final byte has padded zeros to make the frame
+ byte aligned.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+AMR Speech Codec Frame Structure", 3GPP TS 26.101 version 4.1.0 Release 4, June 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void ets_to_if2(
+ enum Frame_Type_3GPP frame_type_3gpp,
+ Word16 *ets_input_ptr,
+ UWord8 *if2_output_ptr)
+{
+ Word16 i;
+ Word16 k;
+ Word16 j = 0;
+ Word16 *ptr_temp;
+ Word16 bits_left;
+ UWord8 accum;
+
+ if (frame_type_3gpp < AMR_SID)
+ {
+ if2_output_ptr[j++] = (UWord8)(frame_type_3gpp) |
+ (ets_input_ptr[reorderBits[frame_type_3gpp][0]] << 4) |
+ (ets_input_ptr[reorderBits[frame_type_3gpp][1]] << 5) |
+ (ets_input_ptr[reorderBits[frame_type_3gpp][2]] << 6) |
+ (ets_input_ptr[reorderBits[frame_type_3gpp][3]] << 7);
+
+ for (i = 4; i < numOfBits[frame_type_3gpp] - 7;)
+ {
+ if2_output_ptr[j] =
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]];
+ if2_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 1;
+ if2_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 2;
+ if2_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 3;
+ if2_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 4;
+ if2_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 5;
+ if2_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 6;
+ if2_output_ptr[j++] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 7;
+ }
+
+ bits_left = 4 + numOfBits[frame_type_3gpp] -
+ ((4 + numOfBits[frame_type_3gpp]) & 0xFFF8);
+
+ if (bits_left != 0)
+ {
+ if2_output_ptr[j] = 0;
+
+ for (k = 0; k < bits_left; k++)
+ {
+ if2_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << k;
+ }
+ }
+ }
+ else
+ {
+ if (frame_type_3gpp != AMR_NO_DATA)
+ {
+ /* First octet contains 3GPP frame type and */
+ /* first 4 bits of encoded parameters */
+ if2_output_ptr[j++] = (UWord8)(frame_type_3gpp) |
+ (ets_input_ptr[0] << 4) | (ets_input_ptr[1] << 5) |
+ (ets_input_ptr[2] << 6) | (ets_input_ptr[3] << 7);
+ ptr_temp = &ets_input_ptr[4];
+
+ bits_left = ((4 + numOfBits[frame_type_3gpp]) & 0xFFF8);
+
+ for (i = (bits_left - 7) >> 3; i > 0; i--)
+ {
+ accum = (UWord8) * (ptr_temp++);
+ accum |= (UWord8) * (ptr_temp++) << 1;
+ accum |= (UWord8) * (ptr_temp++) << 2;
+ accum |= (UWord8) * (ptr_temp++) << 3;
+ accum |= (UWord8) * (ptr_temp++) << 4;
+ accum |= (UWord8) * (ptr_temp++) << 5;
+ accum |= (UWord8) * (ptr_temp++) << 6;
+ accum |= (UWord8) * (ptr_temp++) << 7;
+
+ if2_output_ptr[j++] = accum;
+ }
+
+ bits_left = 4 + numOfBits[frame_type_3gpp] - bits_left;
+
+ if (bits_left != 0)
+ {
+ if2_output_ptr[j] = 0;
+
+ for (i = 0; i < bits_left; i++)
+ {
+ if2_output_ptr[j] |= (ptr_temp[i] << i);
+ }
+ }
+ }
+ else
+ {
+ /* When there is no data, LSnibble of first octet */
+ /* is the 3GPP frame type, MSnibble is zeroed out */
+ if2_output_ptr[j++] = (UWord8)(frame_type_3gpp);
+ }
+
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ets_to_if2.h b/media/libstagefright/codecs/amrnb/enc/src/ets_to_if2.h
new file mode 100644
index 0000000..d85bcc9
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/ets_to_if2.h
@@ -0,0 +1,121 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/include/src/ets_to_if2.h
+
+ Date: 01/23/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the ets_to_if2 function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef ETS_TO_IF2_H
+#define ETS_TO_IF2_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mode.h"
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void ets_to_if2(enum Frame_Type_3GPP mode,
+ Word16 *ets_input_ptr,
+ UWord8 *if2_output_ptr);
+
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ets_to_wmf.cpp b/media/libstagefright/codecs/amrnb/enc/src/ets_to_wmf.cpp
new file mode 100644
index 0000000..9da3fb8
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/ets_to_wmf.cpp
@@ -0,0 +1,244 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/ets_to_wmf.c
+ Funtions: ets_to_wmf
+
+ Date: 01/23/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Modified code as per review comments regarding things such as
+ adding the tables in bitreorder_tab.c to the Global section of
+ the input/output section of the template and removing the #define
+ of 244 since it wasn't needed in this function.
+
+ Description: Fixed the loop that packs the last octet of the WMF output.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "ets_to_wmf.h"
+#include "typedef.h"
+#include "bitreorder_tab.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ets_to_wmf
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ frame_type_3gpp = decoder speech bit rate (enum Frame_Type_3GPP)
+ ets_input_ptr = pointer to input encoded speech bits in ETS format (Word16)
+ wmf_output_ptr = pointer to output encoded speech bits in WMF format(UWord8)
+
+ Outputs:
+ wmf_output_ptr = pointer to encoded speech bits in the WMF format (UWord8)
+
+ Returns:
+ None
+
+ Global Variables Used:
+ numOfBits = table of values that describe the number of bits per frame for
+ each 3GPP frame type mode. The table is type const Word16 and has
+ NUM_MODES elements. This table is located in bitreorder_tab.c.
+ reorderBits = table of pointers that point to tables used to reorder the
+ encoded speech bits when converting from ETS to WMF or IF2
+ format. The table is of type const Word16 * and contains
+ NUM_MODES-1 elements. This table is located in bitreorder_tab.c.
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs a transformation on the data buffers. It converts the
+ data format from ETS (European Telecommunication Standard) to WMF (wireless
+ multimedia forum). ETS format has the encoded speech bits each separate with
+ only one bit stored in each word. WMF is the storage format where the frame
+ type is in the first four bits of the first byte. This first byte has the
+ upper four bits as padded zeroes. The following bytes contain the rest of the
+ encoded speech bits. The final byte has padded zeros to make the frame byte
+ aligned.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void ets_to_wmf(
+ enum Frame_Type_3GPP frame_type_3gpp,
+ Word16 *ets_input_ptr,
+ UWord8 *wmf_output_ptr)
+{
+ Word16 i;
+ Word16 k = 0;
+ Word16 j = 0;
+ Word16 *ptr_temp;
+ Word16 bits_left;
+ UWord8 accum;
+
+ if (frame_type_3gpp < AMR_SID)
+ {
+ wmf_output_ptr[j++] = (UWord8)(frame_type_3gpp) & 0x0f;
+
+ for (i = 0; i < numOfBits[frame_type_3gpp] - 7;)
+ {
+ wmf_output_ptr[j] =
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 7;
+ wmf_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 6;
+ wmf_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 5;
+ wmf_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 4;
+ wmf_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 3;
+ wmf_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 2;
+ wmf_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << 1;
+ wmf_output_ptr[j++] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]];
+ }
+
+ bits_left = numOfBits[frame_type_3gpp] -
+ (numOfBits[frame_type_3gpp] & 0xFFF8);
+
+ wmf_output_ptr[j] = 0;
+
+ for (k = 0; k < bits_left; k++)
+ {
+ wmf_output_ptr[j] |=
+ (UWord8) ets_input_ptr[reorderBits[frame_type_3gpp][i++]] << (7 - k);
+
+ }
+ }
+ else
+ {
+ wmf_output_ptr[j++] = (UWord8)(frame_type_3gpp) & 0x0f;
+
+ ptr_temp = &ets_input_ptr[0];
+
+ for (i = numOfBits[frame_type_3gpp] - 7; i > 0; i -= 8)
+ {
+ accum = (UWord8) * (ptr_temp++) << 7;
+ accum |= (UWord8) * (ptr_temp++) << 6;
+ accum |= (UWord8) * (ptr_temp++) << 5;
+ accum |= (UWord8) * (ptr_temp++) << 4;
+ accum |= (UWord8) * (ptr_temp++) << 3;
+ accum |= (UWord8) * (ptr_temp++) << 2;
+ accum |= (UWord8) * (ptr_temp++) << 1;
+ accum |= (UWord8) * (ptr_temp++);
+
+ wmf_output_ptr[j++] = accum;
+ }
+
+ bits_left = numOfBits[frame_type_3gpp] -
+ (numOfBits[frame_type_3gpp] & 0xFFF8);
+
+ wmf_output_ptr[j] = 0;
+
+ for (i = 0; i < bits_left; i++)
+ {
+ wmf_output_ptr[j] |= *(ptr_temp++) << (7 - i);
+ }
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ets_to_wmf.h b/media/libstagefright/codecs/amrnb/enc/src/ets_to_wmf.h
new file mode 100644
index 0000000..a018fcf
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/ets_to_wmf.h
@@ -0,0 +1,123 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/include/src/ets_to_wmf.h
+
+ Date: 02/22/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Corrected the copyright year.
+
+ Description: Updated template to make it build in Symbian. Updated copyright
+ year.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the ets_to_wmf function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef ETS_TO_WMF_H
+#define ETS_TO_WMF_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "frame_type_3gpp.h"
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void ets_to_wmf(enum Frame_Type_3GPP frame_type_3gpp,
+ Word16 *ets_input_ptr,
+ UWord8 *wmf_output_ptr);
+
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/enc/src/g_adapt.cpp b/media/libstagefright/codecs/amrnb/enc/src/g_adapt.cpp
new file mode 100644
index 0000000..712a7fd
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/g_adapt.cpp
@@ -0,0 +1,522 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/g_adapt.c
+ Functions:
+
+ Date: 02/04/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+ Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+
+#include "g_adapt.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "cnst.h"
+#include "gmed_n.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define LTP_GAIN_THR1 2721 /* 2721 Q13 = 0.3322 ~= 1.0 / (10*log10(2)) */
+#define LTP_GAIN_THR2 5443 /* 5443 Q13 = 0.6644 ~= 2.0 / (10*log10(2)) */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: gain_adapt_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- double pointer to GainAdaptState
+
+ Outputs:
+ st -- double ponter to GainAdaptState
+
+ Returns:
+ -1 if an error occurs during memory initialization
+ 0 if OK
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Allocates state memory and initializes state memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ g_adapt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 gain_adapt_init(GainAdaptState **st)
+{
+ GainAdaptState* s;
+
+ if (st == (GainAdaptState **) NULL)
+ {
+ /* fprintf(stderr, "gain_adapt_init: invalid parameter\n"); */
+ return -1;
+ }
+ *st = NULL;
+
+ /* allocate memory */
+ if ((s = (GainAdaptState *) malloc(sizeof(GainAdaptState))) == NULL)
+ {
+ /* fprintf(stderr, "gain_adapt_init: can't malloc state structure\n"); */
+ return -1;
+ }
+ gain_adapt_reset(s);
+ *st = s;
+
+ return 0;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: gain_adapt_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- double pointer to GainAdaptState
+
+ Outputs:
+ st -- double ponter to GainAdaptState
+
+ Returns:
+ -1 if an error occurs
+ 0 if OK
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Initializes state memory to zero
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ g_adapt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 gain_adapt_reset(GainAdaptState *st)
+{
+ Word16 i;
+
+ if (st == (GainAdaptState *) NULL)
+ {
+ /* fprintf(stderr, "gain_adapt_reset: invalid parameter\n"); */
+ return -1;
+ }
+
+ st->onset = 0;
+ st->prev_alpha = 0;
+ st->prev_gc = 0;
+
+ for (i = 0; i < LTPG_MEM_SIZE; i++)
+ {
+ st->ltpg_mem[i] = 0;
+ }
+
+ return 0;
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: gain_adapt_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- double pointer to GainAdaptState
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ The memory used for state memory is freed
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ g_adapt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void gain_adapt_exit(GainAdaptState **st)
+{
+ if (st == NULL || *st == NULL)
+ return;
+
+ /* deallocate memory */
+ free(*st);
+ *st = NULL;
+
+ return;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: gain_adapt
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- double pointer to GainAdaptState
+ ltpg -- Word16 -- ltp coding gain (log2()), Q13
+ gain_cod -- Word16 -- code gain, Q1
+
+ Outputs:
+ alpha -- Pointer to Word16 -- gain adaptation factor, Q15
+ pOverflow -- Pointer to Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Purpose: calculate pitch/codebook gain adaptation factor alpha
+ (and update the adaptor state)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ g_adapt.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void gain_adapt(
+ GainAdaptState *st, /* i : state struct */
+ Word16 ltpg, /* i : ltp coding gain (log2()), Q13 */
+ Word16 gain_cod, /* i : code gain, Q1 */
+ Word16 *alpha, /* o : gain adaptation factor, Q15 */
+ Flag *pOverflow
+)
+{
+ Word16 adapt; /* adaptdation status; 0, 1, or 2 */
+ Word16 result; /* alpha factor, Q13 */
+ Word16 filt; /* median-filtered LTP coding gain, Q13 */
+ Word16 tmp;
+ Word16 i;
+
+ /* basic adaptation */
+ if (ltpg <= LTP_GAIN_THR1)
+ {
+ adapt = 0;
+ }
+ else
+ {
+ if (ltpg <= LTP_GAIN_THR2)
+ {
+ adapt = 1;
+ }
+ else
+ {
+ adapt = 2;
+ }
+ }
+
+ /*
+ * // onset indicator
+ * if ((cbGain > onFact * cbGainMem[0]) && (cbGain > 100.0))
+ * onset = 8;
+ * else
+ * if (onset)
+ * onset--;
+ */
+ /* tmp = cbGain / onFact; onFact = 2.0; 200 Q1 = 100.0 */
+ tmp = shr_r(gain_cod, 1, pOverflow);
+
+ if ((tmp > st->prev_gc) && (gain_cod > 200))
+ {
+ st->onset = 8;
+ }
+ else
+ {
+ if (st->onset != 0)
+ {
+ st->onset = sub(st->onset, 1, pOverflow);
+ }
+ }
+
+ /*
+ * // if onset, increase adaptor state
+ * if (onset && (gainAdapt < 2)) gainAdapt++;
+ */
+ if ((st->onset != 0) && (adapt < 2))
+ {
+ adapt = add(adapt, 1, pOverflow);
+ }
+
+ st->ltpg_mem[0] = ltpg;
+ filt = gmed_n(st->ltpg_mem, 5); /* function result */
+
+ if (adapt == 0)
+ {
+ if (filt > 5443) /* 5443 Q13 = 0.66443... */
+ {
+ result = 0;
+ }
+ else
+ {
+ if (filt < 0)
+ {
+ result = 16384; /* 16384 Q15 = 0.5 */
+ }
+ else
+ { /* result = 0.5 - 0.75257499*filt */
+ /* result (Q15) = 16384 - 24660 * (filt << 2) */
+ filt = shl(filt, 2, pOverflow); /* Q15 */
+ result = mult(24660, filt, pOverflow);
+ result = sub(16384, result, pOverflow);
+ }
+ }
+ }
+ else
+ {
+ result = 0;
+ }
+ /*
+ * if (prevAlpha == 0.0) result = 0.5 * (result + prevAlpha);
+ */
+ if (st->prev_alpha == 0)
+ {
+ result = shr(result, 1, pOverflow);
+ }
+
+ /* store the result */
+ *alpha = result;
+
+ /* update adapter state memory */
+ st->prev_alpha = result;
+ st->prev_gc = gain_cod;
+
+ for (i = LTPG_MEM_SIZE - 1; i > 0; i--)
+ {
+ st->ltpg_mem[i] = st->ltpg_mem[i-1];
+ }
+ /* mem[0] is just present for convenience in calling the gmed_n[5]
+ * function above. The memory depth is really LTPG_MEM_SIZE-1.
+ */
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/g_adapt.h b/media/libstagefright/codecs/amrnb/enc/src/g_adapt.h
new file mode 100644
index 0000000..2ea508b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/g_adapt.h
@@ -0,0 +1,159 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/g_adapt.h
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the file, g_adapt.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef g_adapt_h
+#define g_adapt_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+#define LTPG_MEM_SIZE 5 /* number of stored past LTP coding gains + 1 */
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 onset; /* onset state, Q0 */
+ Word16 prev_alpha; /* previous adaptor output, Q15 */
+ Word16 prev_gc; /* previous code gain, Q1 */
+
+ Word16 ltpg_mem[LTPG_MEM_SIZE]; /* LTP coding gain history, Q13 */
+ /* (ltpg_mem[0] not used for history) */
+ } GainAdaptState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 gain_adapt_init(GainAdaptState **st);
+ /* initialize one instance of the gain adaptor
+ Stores pointer to state struct in *st. This pointer has to
+ be passed to gain_adapt and gain_adapt_update in each call.
+ returns 0 on success
+ */
+
+ Word16 gain_adapt_reset(GainAdaptState *st);
+ /* reset of gain adaptor state (i.e. set state memory to zero)
+ returns 0 on success
+ */
+
+ void gain_adapt_exit(GainAdaptState **st);
+ /* de-initialize gain adaptor state (i.e. free state struct)
+ stores NULL in *st
+ */
+
+ /*************************************************************************
+ *
+ * Function: gain_adapt()
+ * Purpose: calculate pitch/codebook gain adaptation factor alpha
+ * (and update the adaptor state)
+ *
+ **************************************************************************
+ */
+ void gain_adapt(
+ GainAdaptState *st, /* i : state struct */
+ Word16 ltpg, /* i : ltp coding gain (log2()), Q */
+ Word16 gain_cod, /* i : code gain, Q13 */
+ Word16 *alpha, /* o : gain adaptation factor, Q15 */
+ Flag *pOverflow /* o : overflow indicator */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/g_code.cpp b/media/libstagefright/codecs/amrnb/enc/src/g_code.cpp
new file mode 100644
index 0000000..f937cb7
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/g_code.cpp
@@ -0,0 +1,322 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/g_code.c
+
+ Date: 01/31/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: The return of L_mult was being stored in a Word16 before it was
+ being operated on (extract_h). Data loss happened here.
+
+ Description:
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated math operations that unnecessary checked for
+ saturation, in some cases this by shifting before adding and
+ in other cases by evaluating the operands
+ 4. Unrolled loops to speed up processing
+ 5. Eliminated calls to shifts left and right functions by adding
+ if-else statements that do the same faster.
+
+ Description: Added casting to eliminate warnings
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: 1. Using inlines from fxp_arithmetic.h
+ 2. Removing a compiler warning.
+
+ Description: Replacing fxp_arithmetic.h with basic_op.h.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "g_code.h"
+#include "cnst.h"
+#include "basic_op.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: G_code
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ xn2[] = target vector (Word16)
+ y2[] = filtered innovation vector
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the innovative gain calculation resulted in overflow
+
+ Returns:
+ gain = Gain of Innovation code (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes the innovative codebook gain.
+
+ The innovative codebook gain is given by
+ g = <x[], y[]> / <y[], y[]>
+
+ where x[] is the target vector, y[] is the filtered innovative codevector,
+ and <> denotes dot product.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] g_code.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 G_code ( // out : Gain of innovation code
+ Word16 xn2[], // in : target vector
+ Word16 y2[] // in : filtered innovation vector
+)
+{
+ Word16 i;
+ Word16 xy, yy, exp_xy, exp_yy, gain;
+ Word16 scal_y2[L_SUBFR];
+ Word32 s;
+
+// The original ETSI implementation uses a global overflow flag. However in
+// actual implementation a pointer to Overflow flag is passed into the
+// function for access by the low level math functions.
+
+ // Scale down Y[] by 2 to avoid overflow
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ scal_y2[i] = shr (y2[i], 1);
+ }
+
+ // Compute scalar product <X[],Y[]>
+
+ s = 1L; // Avoid case of all zeros
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ s = L_mac (s, xn2[i], scal_y2[i]);
+ }
+ exp_xy = norm_l (s);
+ xy = extract_h (L_shl (s, exp_xy));
+
+ // If (xy < 0) gain = 0
+
+ if (xy <= 0)
+ return ((Word16) 0);
+
+ // Compute scalar product <Y[],Y[]>
+
+ s = 0L;
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ s = L_mac (s, scal_y2[i], scal_y2[i]);
+ }
+ exp_yy = norm_l (s);
+ yy = extract_h (L_shl (s, exp_yy));
+
+ // compute gain = xy/yy
+
+ xy = shr (xy, 1); // Be sure xy < yy
+ gain = div_s (xy, yy);
+
+ // Denormalization of division
+ i = add (exp_xy, 5); // 15-1+9-18 = 5
+ i = sub (i, exp_yy);
+
+ gain = shl (shr (gain, i), 1); // Q0 -> Q1/
+
+ return (gain);
+}
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word16 G_code( /* o : Gain of innovation code */
+ Word16 xn2[], /* i : target vector */
+ Word16 y2[], /* i : filtered innovation vector */
+ Flag *pOverflow /* i/o : overflow flag */
+)
+{
+ Word16 i;
+ Word16 xy, yy, exp_xy, exp_yy, gain;
+ Word32 s;
+
+ Word16 *p_xn2 = xn2;
+ Word16 *p_y2 = y2;
+ Word16 temp;
+ Word32 temp2;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ /* Compute scalar product <X[],Y[]> */
+ s = 0;
+
+ for (i = (L_SUBFR >> 2); i != 0 ; i--)
+ {
+ temp2 = (Word32)(*(p_y2++) >> 1);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn2++), temp2, s);
+ temp2 = (Word32)(*(p_y2++) >> 1);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn2++), temp2, s);
+ temp2 = (Word32)(*(p_y2++) >> 1);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn2++), temp2, s);
+ temp2 = (Word32)(*(p_y2++) >> 1);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn2++), temp2, s);
+ }
+ s <<= 1;
+ exp_xy = norm_l(s + 1); /* Avoid case of all zeros, add 1 */
+
+ if (exp_xy < 17) /* extra right shift to be sure xy < yy */
+ {
+ xy = (Word16)(s >> (17 - exp_xy));
+ }
+ else
+ {
+ xy = (Word16)(s << (exp_xy - 17));
+ }
+
+ /* If (xy < 0) gain = 0 */
+
+ if (xy <= 0)
+ {
+ return ((Word16) 0);
+ }
+
+ /* Compute scalar product <Y[],Y[]> */
+
+ s = 0L;
+ p_y2 = y2;
+
+ for (i = (L_SUBFR >> 1); i != 0 ; i--)
+ {
+ temp = *(p_y2++) >> 1;
+ s += ((Word32) temp * temp) >> 2;
+ temp = *(p_y2++) >> 1;
+ s += ((Word32) temp * temp) >> 2;
+ }
+ s <<= 3;
+ exp_yy = norm_l(s);
+
+ if (exp_yy < 16)
+ {
+ yy = (Word16)(s >> (16 - exp_yy));
+ }
+ else
+ {
+ yy = (Word16)(s << (exp_yy - 16));
+ }
+
+ gain = div_s(xy, yy);
+
+ /* Denormalization of division */
+ i = exp_xy + 5; /* 15-1+9-18 = 5 */
+ i -= exp_yy;
+
+ // gain = shl (shr (gain, i), 1); /* Q0 -> Q1 */
+
+ if (i > 1)
+ {
+ gain >>= i - 1;
+ }
+ else
+ {
+ gain <<= 1 - i;
+ }
+
+
+ return (gain);
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/g_code.h b/media/libstagefright/codecs/amrnb/enc/src/g_code.h
new file mode 100644
index 0000000..c62cba6
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/g_code.h
@@ -0,0 +1,116 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/g_code.h
+
+
+ Date: 01/31/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the G_code() function.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef G_CODE_H
+#define G_CODE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 G_code( /* o : Gain of innovation code */
+ Word16 xn2[], /* i : target vector */
+ Word16 y2[], /* i : filtered innovation vector */
+ Flag *pOverflow /* i/o : overflow flag */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _G_CODE_H */
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/g_pitch.cpp b/media/libstagefright/codecs/amrnb/enc/src/g_pitch.cpp
new file mode 100644
index 0000000..f6235ad
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/g_pitch.cpp
@@ -0,0 +1,464 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/g_pitch.c
+
+ Date: 06/12/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed into template and began to optimize.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Replaced basic_op.h and oper_32b.h with the header files of the
+ math functions used in the file. Fixed typecasting issue with
+ TI compiler.
+
+ Description: Passing in pointer to overflow flag for EPOC compatibility. .
+
+ Description:
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated math operations that unnecessary checked for
+ saturation, in some cases this by shifting before adding and
+ in other cases by evaluating the operands
+ 4. Unrolled loops to speed up processing
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Using inlines from fxp_arithmetic.h .
+
+ Description: Replacing fxp_arithmetic.h with basic_op.h.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "g_pitch.h"
+#include "mode.h"
+#include "cnst.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: G_pitch
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ mode = AMR mode (enum Mode)
+ xn = pointer to pitch target buffer (Word16)
+ y1 = pointer to filtered adaptive codebook buffer (Word16)
+ g_coeff = pointer to buffer of correlations needed for gain quantization
+ (Word16)
+ L_subfr = length of subframe (Word16)
+ pOverflow = pointer to overflow flag (Flag)
+
+ Outputs:
+ g_coeff contains the mantissa and exponent of the two dot products.
+ pOverflow -> 1 if an overflow occurs
+
+ Returns:
+ gain = ratio of dot products.(Word16)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes the pitch (adaptive codebook) gain. The adaptive
+ codebook gain is given by
+
+ g = <x[], y[]> / <y[], y[]>
+
+ where: x[] is the target vector
+ y[] is the filtered adaptive codevector
+ <> denotes dot product.
+
+ The gain is limited to the range [0,1.2] (=0..19661 Q14)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ g_pitch.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 G_pitch ( // o : Gain of pitch lag saturated to 1.2
+ enum Mode mode, // i : AMR mode
+ Word16 xn[], // i : Pitch target.
+ Word16 y1[], // i : Filtered adaptive codebook.
+ Word16 g_coeff[], // i : Correlations need for gain quantization
+ Word16 L_subfr // i : Length of subframe.
+)
+{
+ Word16 i;
+ Word16 xy, yy, exp_xy, exp_yy, gain;
+ Word32 s;
+
+ Word16 scaled_y1[L_SUBFR]; // Usually dynamic allocation of (L_subfr)
+
+ // divide "y1[]" by 4 to avoid overflow
+
+// The reference ETSI code uses a global overflow Flag. However in the actual
+// implementation a pointer to the overflow flag is passed into the function.
+
+ for (i = 0; i < L_subfr; i++)
+ {
+ scaled_y1[i] = shr (y1[i], 2);
+ }
+
+ // Compute scalar product <y1[],y1[]>
+
+ // Q12 scaling / MR122
+ Overflow = 0;
+ s = 1L; // Avoid case of all zeros
+ for (i = 0; i < L_subfr; i++)
+ {
+ s = L_mac (s, y1[i], y1[i]);
+ }
+ if (Overflow == 0) // Test for overflow
+ {
+ exp_yy = norm_l (s);
+ yy = pv_round (L_shl (s, exp_yy));
+ }
+ else
+ {
+ s = 1L; // Avoid case of all zeros
+ for (i = 0; i < L_subfr; i++)
+ {
+ s = L_mac (s, scaled_y1[i], scaled_y1[i]);
+ }
+ exp_yy = norm_l (s);
+ yy = pv_round (L_shl (s, exp_yy));
+ exp_yy = sub (exp_yy, 4);
+ }
+
+ // Compute scalar product <xn[],y1[]>
+
+ Overflow = 0;
+ s = 1L; // Avoid case of all zeros
+
+ for (i = 0; i < L_subfr; i++)
+ {
+ s = L_mac(s, xn[i], y1[i]);
+ }
+ if (Overflow == 0)
+ {
+ exp_xy = norm_l (s);
+ xy = pv_round (L_shl (s, exp_xy));
+ }
+ else
+ {
+ s = 1L; // Avoid case of all zeros
+ for (i = 0; i < L_subfr; i++)
+ {
+ s = L_mac (s, xn[i], scaled_y1[i]);
+ }
+ exp_xy = norm_l (s);
+ xy = pv_round (L_shl (s, exp_xy));
+ exp_xy = sub (exp_xy, 2);
+ }
+
+ g_coeff[0] = yy;
+ g_coeff[1] = sub (15, exp_yy);
+ g_coeff[2] = xy;
+ g_coeff[3] = sub (15, exp_xy);
+
+ // If (xy < 4) gain = 0
+
+ i = sub (xy, 4);
+
+ if (i < 0)
+ return ((Word16) 0);
+
+ // compute gain = xy/yy
+
+ xy = shr (xy, 1); // Be sure xy < yy
+ gain = div_s (xy, yy);
+
+ i = sub (exp_xy, exp_yy); // Denormalization of division
+ gain = shr (gain, i);
+
+ // if(gain >1.2) gain = 1.2
+
+ if (sub (gain, 19661) > 0)
+ {
+ gain = 19661;
+ }
+
+ if (sub(mode, MR122) == 0)
+ {
+ // clear 2 LSBits
+ gain = gain & 0xfffC;
+ }
+
+ return (gain);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 G_pitch( /* o : Gain of pitch lag saturated to 1.2 */
+ enum Mode mode, /* i : AMR mode */
+ Word16 xn[], /* i : Pitch target. Q0 */
+ Word16 y1[], /* i : Filtered adaptive codebook. Q12 */
+ Word16 g_coeff[], /* i : Correlations need for gain quantization */
+ Word16 L_subfr, /* i : Length of subframe. */
+ Flag *pOverflow /* i/o : Overflow flag */
+)
+{
+
+ Word16 i;
+ Word16 xy;
+ Word16 yy;
+ Word16 exp_xy;
+ Word16 exp_yy;
+ Word16 gain;
+ Word16 tmp;
+ Word32 s;
+ Word32 s1;
+ Word32 L_temp; /* Use this as an intermediate value */
+ Word16 *p_xn = &xn[0];
+ Word16 *p_y1 = &y1[0];
+
+ /* Compute scalar product <y1[],y1[]> */
+
+ /* Q12 scaling / MR122 */
+ *pOverflow = 0;
+ s = 0;
+
+ for (i = L_subfr >> 2; i != 0; i--)
+ {
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
+ p_y1++;
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
+ p_y1++;
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
+ p_y1++;
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_y1), (Word32) * (p_y1), s);
+ p_y1++;
+ }
+ if ((s >= 0) & (s < 0x40000000))
+ {
+ s <<= 1;
+ s += 1; /* Avoid case of all zeros */
+
+ exp_yy = norm_l(s); /* Note 0<=exp_yy <= 31 */
+ L_temp = s << exp_yy;
+ yy = pv_round(L_temp, pOverflow);
+ }
+ else
+ {
+ s = 0; /* Avoid case of all zeros */
+ p_y1 = &y1[0];
+ for (i = (L_subfr >> 1); i != 0; i--)
+ {
+ tmp = *(p_y1++) >> 2;
+ s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s);
+ tmp = *(p_y1++) >> 2;
+ s = amrnb_fxp_mac_16_by_16bb((Word32) tmp, (Word32) tmp, s);
+ }
+
+ s <<= 1;
+ s += 1; /* Avoid case of all zeros */
+
+ exp_yy = norm_l(s);
+ L_temp = s << exp_yy;
+ yy = pv_round(L_temp, pOverflow);
+ exp_yy = exp_yy - 4;
+
+ }
+
+ /* Compute scalar product <xn[],y1[]> */
+
+ s = 0;
+ p_y1 = &y1[0];
+ *pOverflow = 0;
+
+ for (i = L_subfr; i != 0; i--)
+ {
+ L_temp = ((Word32) * (p_xn++) * *(p_y1++));
+ s1 = s;
+ s = s1 + L_temp;
+
+ if ((s1 ^ L_temp) > 0)
+ {
+ if ((s1 ^ s) < 0)
+ {
+ *pOverflow = 1;
+ break;
+ }
+ }
+ }
+
+ if (!(*pOverflow))
+ {
+
+ s <<= 1;
+ s += 1; /* Avoid case of all zeros */
+
+ exp_xy = norm_l(s); /* Note 0<=exp_yy <= 31 */
+ L_temp = s << exp_xy;
+ xy = pv_round(L_temp, pOverflow);
+ }
+ else
+ {
+ s = 0; /* Avoid case of all zeros */
+ p_y1 = &y1[0];
+ for (i = (L_subfr >> 2); i != 0; i--)
+ {
+ L_temp = (Word32)(*(p_y1++) >> 2);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
+ L_temp = (Word32)(*(p_y1++) >> 2);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
+ L_temp = (Word32)(*(p_y1++) >> 2);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
+ L_temp = (Word32)(*(p_y1++) >> 2);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (p_xn++), L_temp, s);
+ }
+
+ s <<= 1;
+ s += 1; /* Avoid case of all zeros */
+
+ exp_xy = norm_l(s);
+ L_temp = s << exp_xy;
+ xy = pv_round(L_temp, pOverflow);
+ exp_xy = exp_xy - 4;
+
+ }
+
+ g_coeff[0] = yy;
+ g_coeff[1] = 15 - exp_yy;
+ g_coeff[2] = xy;
+ g_coeff[3] = 15 - exp_xy;
+
+ /* If (xy < 4) gain = 0 */
+ if (xy < 4)
+ {
+ return ((Word16) 0);
+ }
+
+ /* compute gain = xy/yy */
+ /* Be sure xy < yy */
+
+ xy = xy >> 1;
+
+ gain = div_s(xy, yy);
+
+ i = exp_xy - exp_yy; /* Denormalization of division */
+
+ gain = shr(gain, i, pOverflow);
+
+
+ /* if(gain >1.2) gain = 1.2 */
+ if (gain > 19661)
+ {
+ gain = 19661;
+ }
+
+ if (mode == MR122)
+ {
+ /* clear 2 LSBits */
+ gain = gain & 0xfffC;
+ }
+
+ return(gain);
+
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/g_pitch.h b/media/libstagefright/codecs/amrnb/enc/src/g_pitch.h
new file mode 100644
index 0000000..6ea06ea
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/g_pitch.h
@@ -0,0 +1,119 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/g_pitch.h
+
+
+ Date: 02/01/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the G_pitch() function.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef G_PITCH_H
+#define G_PITCH_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mode.h"
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 G_pitch( /* o : Gain of pitch lag saturated to 1.2 */
+ enum Mode mode, /* i : AMR mode */
+ Word16 xn[], /* i : Pitch target. */
+ Word16 y1[], /* i : Filtered adaptive codebook. */
+ Word16 g_coeff[], /* i : Correlations need for gain quantization */
+ Word16 L_subfr, /* i : Length of subframe. */
+ Flag *pOverflow /* i/o : Overflow flag */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _G_PITCH_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/gain_q.cpp b/media/libstagefright/codecs/amrnb/enc/src/gain_q.cpp
new file mode 100644
index 0000000..e44e4bc
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/gain_q.cpp
@@ -0,0 +1,747 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/gain_q.c
+ Functions:
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+ Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description: Removed everything associated with gc_pred_init
+ and gc_pred_exit. gc_pred_exit was simply removed -- gc_pred_init
+ was replaced with calls to gc_pred_reset. This is because the gc_pred
+ related structures are no longer dynamically allocated via malloc.
+
+ Description: For gainQuant()
+ 1. Replaced gc_pred_copy() with memcpy.
+ 2. Eliminated unused include file gc_pred.h.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Quantazation of gains
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+#include <string.h>
+
+#include "gain_q.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "qua_gain.h"
+#include "cnst.h"
+#include "mode.h"
+#include "g_code.h"
+#include "q_gain_c.h"
+#include "calc_en.h"
+#include "qgain795.h"
+#include "qgain475.h"
+#include "set_zero.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define NPRED 4 /* number of prediction taps */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: gainQuant_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- double pointer to gainQuantState
+
+ Outputs:
+ st -- double ponter to gainQuantState
+
+ Returns:
+ -1 if an error occurs during memory initialization
+ 0 if OK
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Allocates state memory and initializes state memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ gain_q.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 gainQuant_init(gainQuantState **state)
+{
+ gainQuantState* s;
+
+ if (state == (gainQuantState **) NULL)
+ {
+ /* fprintf(stderr, "gainQuant_init: invalid parameter\n"); */
+ return -1;
+ }
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (gainQuantState *) malloc(sizeof(gainQuantState))) == NULL)
+ {
+ /* fprintf(stderr, "gainQuant_init: can not malloc state structure\n"); */
+ return -1;
+ }
+
+ s->gain_idx_ptr = NULL;
+
+ s->adaptSt = NULL;
+
+ /* Init sub states */
+ if (gc_pred_reset(&s->gc_predSt)
+ || gc_pred_reset(&s->gc_predUnqSt)
+ || gain_adapt_init(&s->adaptSt))
+ {
+ gainQuant_exit(&s);
+ return -1;
+ }
+
+ gainQuant_reset(s);
+ *state = s;
+
+ return 0;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: gainQuant_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- double pointer to gainQuantState
+
+ Outputs:
+ st -- double ponter to gainQuantState
+
+ Returns:
+ -1 if an error occurs
+ 0 if OK
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Initializes state memory to zero
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ gain_q.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 gainQuant_reset(gainQuantState *state)
+{
+
+ if (state == (gainQuantState *) NULL)
+ {
+ /* fprintf(stderr, "gainQuant_reset: invalid parameter\n"); */
+ return -1;
+ }
+
+ state->sf0_exp_gcode0 = 0;
+ state->sf0_frac_gcode0 = 0;
+ state->sf0_exp_target_en = 0;
+ state->sf0_frac_target_en = 0;
+
+ Set_zero(state->sf0_exp_coeff, 5);
+ Set_zero(state->sf0_frac_coeff, 5);
+ state->gain_idx_ptr = NULL;
+
+ gc_pred_reset(&(state->gc_predSt));
+ gc_pred_reset(&(state->gc_predUnqSt));
+ gain_adapt_reset(state->adaptSt);
+
+ return 0;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: gainQuant_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- double pointer to gainQuantState
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ The memory used for state memory is freed
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ gain_q.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void gainQuant_exit(gainQuantState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ gain_adapt_exit(&(*state)->adaptSt);
+
+ /* deallocate memory */
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: gainQuant
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st -- pointer to gainQuantState
+ mode -- enum Mode -- coder mode
+ res -- Word16 array -- LP residual, Q0
+ exc -- Word16 array -- LTP excitation (unfiltered), Q0
+ code -- Word16 array -- CB innovation (unfiltered), Q13
+ (unsharpened for MR475)
+ xn -- Word16 array -- Target vector.
+ xn2 -- Word16 array -- Target vector.
+ y1 -- Word16 array -- Adaptive codebook.
+ Y2 -- Word16 array -- Filtered innovative vector.
+ g_coeff -- Word16 array -- Correlations <xn y1> <y1 y1>
+ Compute in G_pitch().
+
+ even_subframe -- Word16 -- even subframe indicator flag
+ gp_limit -- Word16 -- pitch gain limit
+ gain_pit -- Word16 Pointer -- Pitch gain.
+
+ Outputs:
+ st -- pointer to gainQuantState
+ sf0_gain_pit -- Word16 Pointer -- Pitch gain sf 0. MR475
+ sf0_gain_cod -- Word16 Pointer -- Code gain sf 0. MR475
+ gain_pit -- Word16 Pointer -- Pitch gain.
+ gain_cod -- Word16 Pointer -- Code gain.
+ MR475: gain_* unquantized in even
+ subframes, quantized otherwise
+
+ anap -- Word16 Double Pointer -- Index of quantization
+
+ pOverflow -- Flag Pointer -- overflow indicator
+
+ Returns:
+ Zero
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Quantazation of gains
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ gain_q.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+
+
+void gainQuant(
+ gainQuantState *st, /* i/o : State struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 res[], /* i : LP residual, Q0 */
+ Word16 exc[], /* i : LTP excitation (unfiltered), Q0 */
+ Word16 code[], /* i : CB innovation (unfiltered), Q13 */
+ /* (unsharpened for MR475) */
+ Word16 xn[], /* i : Target vector. */
+ Word16 xn2[], /* i : Target vector. */
+ Word16 y1[], /* i : Adaptive codebook. */
+ Word16 Y2[], /* i : Filtered innovative vector. */
+ Word16 g_coeff[], /* i : Correlations <xn y1> <y1 y1> */
+ /* Compute in G_pitch(). */
+ Word16 even_subframe, /* i : even subframe indicator flag */
+ Word16 gp_limit, /* i : pitch gain limit */
+ Word16 *sf0_gain_pit, /* o : Pitch gain sf 0. MR475 */
+ Word16 *sf0_gain_cod, /* o : Code gain sf 0. MR475 */
+ Word16 *gain_pit, /* i/o : Pitch gain. */
+ Word16 *gain_cod, /* o : Code gain. */
+ /* MR475: gain_* unquantized in even */
+ /* subframes, quantized otherwise */
+ Word16 **anap, /* o : Index of quantization */
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ Word16 exp_gcode0;
+ Word16 frac_gcode0;
+ Word16 qua_ener_MR122;
+ Word16 qua_ener;
+ Word16 frac_coeff[5];
+ Word16 exp_coeff[5];
+ Word16 exp_en;
+ Word16 frac_en;
+ Word16 cod_gain_exp;
+ Word16 cod_gain_frac;
+ Word16 temp;
+
+ if (mode == MR475)
+ {
+ if (even_subframe != 0)
+ {
+ /* save position in output parameter stream and current
+ state of codebook gain predictor */
+ st->gain_idx_ptr = (*anap)++;
+
+// gc_pred_copy(&(st->gc_predSt), &(st->gc_predUnqSt));
+
+ memcpy(st->gc_predUnqSt.past_qua_en,
+ st->gc_predSt.past_qua_en,
+ NPRED*sizeof(Word16));
+ memcpy(st->gc_predUnqSt.past_qua_en_MR122,
+ st->gc_predSt.past_qua_en_MR122,
+ NPRED*sizeof(Word16));
+
+
+ /* predict codebook gain (using "unquantized" predictor)*/
+ /* (note that code[] is unsharpened in MR475) */
+ gc_pred(
+ &(st->gc_predUnqSt),
+ mode,
+ code,
+ &st->sf0_exp_gcode0,
+ &st->sf0_frac_gcode0,
+ &exp_en,
+ &frac_en,
+ pOverflow);
+
+ /* calculate energy coefficients for quantization
+ and store them in state structure (will be used
+ in next subframe when real quantizer is run) */
+ calc_filt_energies(
+ mode,
+ xn,
+ xn2,
+ y1,
+ Y2,
+ g_coeff,
+ st->sf0_frac_coeff,
+ st->sf0_exp_coeff,
+ &cod_gain_frac,
+ &cod_gain_exp,
+ pOverflow);
+
+ /* store optimum codebook gain (Q1) */
+ temp =
+ add(
+ cod_gain_exp,
+ 1,
+ pOverflow);
+
+ *gain_cod =
+ shl(
+ cod_gain_frac,
+ temp,
+ pOverflow);
+
+ calc_target_energy(
+ xn,
+ &st->sf0_exp_target_en,
+ &st->sf0_frac_target_en,
+ pOverflow);
+
+ /* calculate optimum codebook gain and update
+ "unquantized" predictor */
+ MR475_update_unq_pred(
+ &(st->gc_predUnqSt),
+ st->sf0_exp_gcode0,
+ st->sf0_frac_gcode0,
+ cod_gain_exp,
+ cod_gain_frac,
+ pOverflow);
+
+ /* the real quantizer is not run here... */
+ }
+ else
+ {
+ /* predict codebook gain (using "unquantized" predictor) */
+ /* (note that code[] is unsharpened in MR475) */
+ gc_pred(
+ &(st->gc_predUnqSt),
+ mode,
+ code,
+ &exp_gcode0,
+ &frac_gcode0,
+ &exp_en,
+ &frac_en,
+ pOverflow);
+
+ /* calculate energy coefficients for quantization */
+ calc_filt_energies(
+ mode,
+ xn,
+ xn2,
+ y1,
+ Y2,
+ g_coeff,
+ frac_coeff,
+ exp_coeff,
+ &cod_gain_frac,
+ &cod_gain_exp,
+ pOverflow);
+
+ calc_target_energy(
+ xn,
+ &exp_en,
+ &frac_en,
+ pOverflow);
+
+ /* run real (4-dim) quantizer and update real gain predictor */
+ *st->gain_idx_ptr =
+ MR475_gain_quant(
+ &(st->gc_predSt),
+ st->sf0_exp_gcode0,
+ st->sf0_frac_gcode0,
+ st->sf0_exp_coeff,
+ st->sf0_frac_coeff,
+ st->sf0_exp_target_en,
+ st->sf0_frac_target_en,
+ code,
+ exp_gcode0,
+ frac_gcode0,
+ exp_coeff,
+ frac_coeff,
+ exp_en,
+ frac_en,
+ gp_limit,
+ sf0_gain_pit,
+ sf0_gain_cod,
+ gain_pit,
+ gain_cod,
+ pOverflow);
+ }
+ }
+ else
+ {
+ /*-------------------------------------------------------------------*
+ * predict codebook gain and quantize *
+ * (also compute normalized CB innovation energy for MR795) *
+ *-------------------------------------------------------------------*/
+ gc_pred(
+ &(st->gc_predSt),
+ mode,
+ code,
+ &exp_gcode0,
+ &frac_gcode0,
+ &exp_en,
+ &frac_en,
+ pOverflow);
+
+ if (mode == MR122)
+ {
+ *gain_cod =
+ G_code(
+ xn2,
+ Y2,
+ pOverflow);
+
+ *(*anap)++ =
+ q_gain_code(
+ mode,
+ exp_gcode0,
+ frac_gcode0,
+ gain_cod,
+ &qua_ener_MR122,
+ &qua_ener,
+ pOverflow);
+ }
+ else
+ {
+ /* calculate energy coefficients for quantization */
+ calc_filt_energies(
+ mode,
+ xn,
+ xn2,
+ y1,
+ Y2,
+ g_coeff,
+ frac_coeff,
+ exp_coeff,
+ &cod_gain_frac,
+ &cod_gain_exp,
+ pOverflow);
+
+ if (mode == MR795)
+ {
+ MR795_gain_quant(
+ st->adaptSt,
+ res,
+ exc,
+ code,
+ frac_coeff,
+ exp_coeff,
+ exp_en,
+ frac_en,
+ exp_gcode0,
+ frac_gcode0,
+ L_SUBFR,
+ cod_gain_frac,
+ cod_gain_exp,
+ gp_limit,
+ gain_pit,
+ gain_cod,
+ &qua_ener_MR122,
+ &qua_ener,
+ anap,
+ pOverflow);
+ }
+ else
+ {
+ *(*anap)++ =
+ Qua_gain(
+ mode,
+ exp_gcode0,
+ frac_gcode0,
+ frac_coeff,
+ exp_coeff,
+ gp_limit,
+ gain_pit,
+ gain_cod,
+ &qua_ener_MR122,
+ &qua_ener,
+ pOverflow);
+ }
+ }
+
+ /*------------------------------------------------------------------*
+ * update table of past quantized energies *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * st->past_qua_en(Q10) = 20 * Log10(qua_gain_code) / constant *
+ * = Log2(qua_gain_code) *
+ * = qua_ener *
+ * constant = 20*Log10(2) *
+ *------------------------------------------------------------------*/
+ gc_pred_update(
+ &(st->gc_predSt),
+ qua_ener_MR122,
+ qua_ener);
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/gain_q.h b/media/libstagefright/codecs/amrnb/enc/src/gain_q.h
new file mode 100644
index 0000000..a5c7f4e
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/gain_q.h
@@ -0,0 +1,182 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/gain_q.h
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow.
+
+ Description: Changed definition of...
+
+ gc_predState gc_predSt;
+ gc_predState gc_predUnqSt;
+
+ in the structure typedef. These are no longer pointers, which avoids
+ the need to malloc memory for the pointers. They are, rather, the actual
+ structure declared within the gainQuantState structure.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the file, gain_q.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef gain_q_h
+#define gain_q_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "gc_pred.h"
+#include "g_adapt.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 sf0_exp_gcode0;
+ Word16 sf0_frac_gcode0;
+ Word16 sf0_exp_target_en;
+ Word16 sf0_frac_target_en;
+ Word16 sf0_exp_coeff[5];
+ Word16 sf0_frac_coeff[5];
+ Word16 *gain_idx_ptr;
+
+ gc_predState gc_predSt;
+ gc_predState gc_predUnqSt;
+ GainAdaptState *adaptSt;
+ } gainQuantState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 gainQuant_init(gainQuantState **st);
+ /* initialize one instance of the pre processing state.
+ Stores pointer to filter status struct in *st. This pointer has to
+ be passed to gainQuant in each call.
+ returns 0 on success
+ */
+ Word16 gainQuant_reset(gainQuantState *st);
+ /* reset of pre processing state (i.e. set state memory to zero)
+ returns 0 on success
+ */
+ void gainQuant_exit(gainQuantState **st);
+ /* de-initialize pre processing state (i.e. free status struct)
+ stores NULL in *st
+ */
+
+ void gainQuant(
+ gainQuantState *st, /* i/o : State struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 res[], /* i : LP residual, Q0 */
+ Word16 exc[], /* i : LTP excitation (unfiltered), Q0 */
+ Word16 code[], /* i : CB innovation (unfiltered), Q13 */
+ /* (unsharpened for MR475) */
+ Word16 xn[], /* i : Target vector. */
+ Word16 xn2[], /* i : Target vector. */
+ Word16 y1[], /* i : Adaptive codebook. */
+ Word16 Y2[], /* i : Filtered innovative vector. */
+ Word16 g_coeff[], /* i : Correlations <xn y1> <y1 y1> */
+ /* Compute in G_pitch(). */
+ Word16 even_subframe, /* i : even subframe indicator flag */
+ Word16 gp_limit, /* i : pitch gain limit */
+ Word16 *sf0_gain_pit, /* o : Pitch gain sf 0. MR475 */
+ Word16 *sf0_gain_cod, /* o : Code gain sf 0. MR475 */
+ Word16 *gain_pit, /* i/o : Pitch gain. */
+ Word16 *gain_cod, /* o : Code gain. */
+ /* MR475: gain_* unquantized in even */
+ /* subframes, quantized otherwise */
+ Word16 **anap, /* o : Index of quantization */
+ Flag *pOverflow /* o : overflow indicator */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* gain_q_h */
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/gsmamr_enc.h b/media/libstagefright/codecs/amrnb/enc/src/gsmamr_enc.h
new file mode 100644
index 0000000..67c7aa3
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/gsmamr_enc.h
@@ -0,0 +1,193 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm-amr/c/include/gsmamr_enc.h
+
+ Date: 09/26/2001
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changing code as per review comments. These changes include
+ removing unnecessary tables and changing function descriptions.
+ The comments were changed to "slash-star" rather than double
+ slash, and some wordings of comments were corrected.
+
+ Description: Replaced GSMEncodeFrame function prototype with that of
+ AMREncode. Updated copyright year.
+
+ Description: Added #define for WMF and IF2, and updated function prototype
+ of AMREncode.
+
+ Description: Renamed WMF and IF2 to AMR_WMF and AMR_IF2, respectively. Added
+ AMR_ETS, and changed output_type to output_format in the
+ function prototype of AMREncode(). Removed function prototypes
+ for frame_header_move() and reverse_bits() since they are not
+ needed anymore.
+
+ Description: Moved WMFBytesUsed and IF2BytesUsed tables to
+ enc_output_format_tab.c.
+
+ Description: Added function prototypes for init, reset, and exit functions
+ in amrencode.c. Renamed output format #defines so that it it
+ unique to the encoder.
+
+ Description: Added comment to describe L_FRAME.
+
+ Description: Added Frame_Type_3GPP type definition.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This header contains all the necessary information needed to use the
+ GSM AMR encoder library.
+
+------------------------------------------------------------------------------
+*/
+#ifndef _GSMAMR_ENC_H_
+#define _GSMAMR_ENC_H_
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "gsm_amr_typedefs.h"
+#include "frame_type_3gpp.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ----------------------------------------------------------------------------*/
+ /* Number of 13-bit linear PCM samples per 20 ms frame */
+ /* L_FRAME = (8 kHz) * (20 msec) = 160 samples */
+#define L_FRAME 160
+
+ /* Output format types */
+#define AMR_TX_WMF 0
+#define AMR_TX_IF2 1
+#define AMR_TX_ETS 2
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ enum Mode
+ {
+ MR475 = 0,/* 4.75 kbps */
+ MR515, /* 5.15 kbps */
+ MR59, /* 5.90 kbps */
+ MR67, /* 6.70 kbps */
+ MR74, /* 7.40 kbps */
+ MR795, /* 7.95 kbps */
+ MR102, /* 10.2 kbps */
+ MR122, /* 12.2 kbps */
+ MRDTX, /* DTX */
+ N_MODES /* Not Used */
+ };
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ----------------------------------------------------------------------------*/
+ /* AMREncodeInit initializes the GSM AMR Encoder library by calling
+ * GSMInitEncode and sid_sync_init. If initialization was successful,
+ * init_status is set to zero, otherwise, it is set to -1.
+ */
+ int AMREncodeInit(
+ void **pEncStructure,
+ void **pSidSyncStructure,
+ Flag dtx_enable);
+
+ /* AMREncodeReset resets the state memory used by the Encoder and SID sync
+ * function. If reset was successful, reset_status is set to zero, otherwise,
+ * it is set to -1.
+ */
+ int AMREncodeReset(
+ void *pEncStructure,
+ void *pSidSyncStructure);
+
+ /* AMREncodeExit frees up the state memory used by the Encoder and SID
+ * synchronization function.
+ */
+ void AMREncodeExit(
+ void **pEncStructure,
+ void **pSidSyncStructure);
+
+ /*
+ * AMREncode is the entry point to the ETS Encoder library that encodes the raw
+ * data speech bits and converts the encoded bitstream into either an IF2-
+ * formatted bitstream, WMF-formatted bitstream, or ETS-formatted bitstream,
+ * depending on the the value of output_format. A zero is returned on success.
+ */
+ int AMREncode(
+ void *pEncState,
+ void *pSidSyncState,
+ enum Mode mode,
+ Word16 *pEncInput,
+ unsigned char *pEncOutput,
+ enum Frame_Type_3GPP *p3gpp_frame_type,
+ Word16 output_format
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _GSMAMR_DEC_H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/hp_max.cpp b/media/libstagefright/codecs/amrnb/enc/src/hp_max.cpp
new file mode 100644
index 0000000..d086594
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/hp_max.cpp
@@ -0,0 +1,332 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/hp_max.c
+
+ Date: 02/01/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "hp_max.h"
+#include "basic_op.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: hp_max
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ corr[] = correlation vector (Word16)
+ scal_sig[] = scaled signal vector (Word16)
+ L_frame = length of frame to compute pitch (Word16
+ lag_max = maximum lag (Word16)
+ lag_min = minimum lag (Word16)
+ cor_hp_max = pointer to max high-pass filtered norm. correlation (Word16)
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ cor_hp_max contains max high-pass filtered norm. correlation (Word16)
+ pOverflow -> 1 if the maximum correlation computation resulted in overflow
+
+ Returns:
+ 0 (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function finds the maximum high-pass filtered correlation of scal_sig[]
+ in a given delay range.
+
+ The correlation is given by
+ corr[t] = <scal_sig[n],scal_sig[n-t]>, t=lag_min,...,lag_max
+ The functions outputs the maximum high-pass filtered correlation after
+ normalization.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] hp_max.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 hp_max (
+ Word32 corr[], // i : correlation vector
+ Word16 scal_sig[], // i : scaled signal
+ Word16 L_frame, // i : length of frame to compute pitch
+ Word16 lag_max, // i : maximum lag
+ Word16 lag_min, // i : minimum lag
+ Word16 *cor_hp_max) // o : max high-pass filtered norm. correlation
+{
+ Word16 i;
+ Word16 *p, *p1;
+ Word32 max, t0, t1;
+ Word16 max16, t016, cor_max;
+ Word16 shift, shift1, shift2;
+
+ max = MIN_32;
+ t0 = 0L;
+* The reference ETSI code uses a global flag for Overflow inside the math functions
+* saturate(). In the actual implementation a pointer to Overflow flag is passed in
+* as a parameter to the function
+
+ for (i = lag_max-1; i > lag_min; i--)
+ {
+ // high-pass filtering
+ t0 = L_sub (L_sub(L_shl(corr[-i], 1), corr[-i-1]), corr[-i+1]);
+ t0 = L_abs (t0);
+
+ if (L_sub (t0, max) >= 0)
+ {
+ max = t0;
+ }
+ }
+
+ // compute energy
+ p = scal_sig;
+ p1 = &scal_sig[0];
+ t0 = 0L;
+ for (i = 0; i < L_frame; i++, p++, p1++)
+ {
+ t0 = L_mac (t0, *p, *p1);
+ }
+
+ p = scal_sig;
+ p1 = &scal_sig[-1];
+ t1 = 0L;
+ for (i = 0; i < L_frame; i++, p++, p1++)
+ {
+ t1 = L_mac (t1, *p, *p1);
+ }
+
+ // high-pass filtering
+ t0 = L_sub(L_shl(t0, 1), L_shl(t1, 1));
+ t0 = L_abs (t0);
+
+ // max/t0
+ shift1 = sub(norm_l(max), 1);
+ max16 = extract_h(L_shl(max, shift1));
+ shift2 = norm_l(t0);
+ t016 = extract_h(L_shl(t0, shift2));
+
+ if (t016 != 0)
+ {
+ cor_max = div_s(max16, t016);
+ }
+ else
+ {
+ cor_max = 0;
+ }
+
+ shift = sub(shift1, shift2);
+
+ if (shift >= 0)
+ {
+ *cor_hp_max = shr(cor_max, shift); // Q15
+ }
+ else
+ {
+ *cor_hp_max = shl(cor_max, negate(shift)); // Q15
+ }
+
+ return 0;
+}
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word16 hp_max(
+ Word32 corr[], /* i : correlation vector. */
+ Word16 scal_sig[], /* i : scaled signal. */
+ Word16 L_frame, /* i : length of frame to compute pitch */
+ Word16 lag_max, /* i : maximum lag */
+ Word16 lag_min, /* i : minimum lag */
+ Word16 *cor_hp_max, /* o : max high-pass filtered norm. correlation */
+ Flag *pOverflow /* i/o : overflow Flag */
+)
+{
+ Word16 i;
+ Word16 *p, *p1;
+ Word32 max, t0, t1;
+ Word16 max16, t016, cor_max;
+ Word16 shift, shift1, shift2;
+ Word32 L_temp;
+
+ max = MIN_32;
+ t0 = 0L;
+
+ for (i = lag_max - 1; i > lag_min; i--)
+ {
+ /* high-pass filtering */
+ t0 = L_shl(corr[-i], 1, pOverflow);
+ L_temp = L_sub(t0, corr[-i-1], pOverflow);
+ t0 = L_sub(L_temp, corr[-i+1], pOverflow);
+ t0 = L_abs(t0);
+
+ if (t0 >= max)
+ {
+ max = t0;
+ }
+ }
+
+ /* compute energy */
+ p = scal_sig;
+ p1 = &scal_sig[0];
+ t0 = 0L;
+ for (i = 0; i < L_frame; i++, p++, p1++)
+ {
+ t0 = L_mac(t0, *p, *p1, pOverflow);
+ }
+
+ p = scal_sig;
+ p1 = &scal_sig[-1];
+ t1 = 0L;
+ for (i = 0; i < L_frame; i++, p++, p1++)
+ {
+ t1 = L_mac(t1, *p, *p1, pOverflow);
+ }
+
+ /* high-pass filtering */
+ L_temp = L_shl(t0, 1, pOverflow);
+ t1 = L_shl(t1, 1, pOverflow);
+ t0 = L_sub(L_temp, t1, pOverflow);
+ t0 = L_abs(t0);
+
+ /* max/t0 */
+ /* shift1 = sub(norm_l(max), 1);
+ max16 = extract_h(L_shl(max, shift1));
+ shift2 = norm_l(t0);
+ t016 = extract_h(L_shl(t0, shift2)); */
+
+ t016 = norm_l(max);
+ shift1 = sub(t016, 1, pOverflow);
+
+ L_temp = L_shl(max, shift1, pOverflow);
+ max16 = (Word16)(L_temp >> 16);
+
+ shift2 = norm_l(t0);
+ L_temp = L_shl(t0, shift2, pOverflow);
+ t016 = (Word16)(L_temp >> 16);
+
+ if (t016 != 0)
+ {
+ cor_max = div_s(max16, t016);
+ }
+ else
+ {
+ cor_max = 0;
+ }
+
+ shift = sub(shift1, shift2, pOverflow);
+
+ if (shift >= 0)
+ {
+ *cor_hp_max = shr(cor_max, shift, pOverflow); /* Q15 */
+ }
+ else
+ {
+ *cor_hp_max = shl(cor_max, negate(shift), pOverflow); /* Q15 */
+ }
+
+ return 0;
+}
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/hp_max.h b/media/libstagefright/codecs/amrnb/enc/src/hp_max.h
new file mode 100644
index 0000000..b668924
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/hp_max.h
@@ -0,0 +1,116 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/hp_max.h
+
+ Date: 02/01/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : hp_max.h
+ Purpose : Find the maximum correlation of scal_sig[] in a given
+ delay range.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef HP_MAX_H
+#define HP_MAX_H "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ Word16 hp_max(
+ Word32 corr[], /* i : correlation vector. */
+ Word16 scal_sig[], /* i : scaled signal. */
+ Word16 L_frame, /* i : length of frame to compute pitch */
+ Word16 lag_max, /* i : maximum lag */
+ Word16 lag_min, /* i : minimum lag */
+ Word16 *cor_hp_max, /* o : max high-pass filtered norm. correlation */
+ Flag *pOverflow /* i/o : overflow Flag */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HP_MAX_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/inter_36.cpp b/media/libstagefright/codecs/amrnb/enc/src/inter_36.cpp
new file mode 100644
index 0000000..87766a9
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/inter_36.cpp
@@ -0,0 +1,250 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/inter_36.c
+
+ Date: 01/31/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated math operations that unnecessary checked for
+ saturation
+ 4. Unrolled loops to speed up processing, use decrement loops
+ 5. Eliminated call to round by proper initialization
+
+ Description: Added casting to eliminate warnings
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Using intrinsics from fxp_arithmetic.h .
+
+ Description: Replacing fxp_arithmetic.h with basic_op.h.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "inter_36.h"
+#include "cnst.h"
+#include "inter_36_tab.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define UP_SAMP_MAX 6
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: inter_36
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pX = pointer to input vector of type Word16
+ frac = fraction (-2..2 for 3*, -3..3 for 6*) of type Word16
+ flag3 = if set, upsampling rate = 3 (6 otherwise) of type Word16
+ pOverflow = pointer to overflow flag
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ File : inter_36.c
+ Purpose : Interpolating the normalized correlation
+ : with 1/3 or 1/6 resolution.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ inter_36.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Word16 i, k;
+ Word16 *x1, *x2;
+ const Word16 *c1, *c2;
+ Word32 s;
+
+ if (flag3 != 0)
+ {
+ frac = shl (frac, 1); // inter_3[k] = inter_6[2*k] -> k' = 2*k
+ }
+
+ if (frac < 0)
+ {
+ frac = add (frac, UP_SAMP_MAX);
+ x--;
+ }
+
+ x1 = &x[0];
+ x2 = &x[1];
+ c1 = &inter_6[frac];
+ c2 = &inter_6[sub (UP_SAMP_MAX, frac)];
+
+ s = 0;
+ for (i = 0, k = 0; i < L_INTER_SRCH; i++, k += UP_SAMP_MAX)
+ {
+ s = L_mac (s, x1[-i], c1[k]);
+ s = L_mac (s, x2[i], c2[k]);
+ }
+
+ return pv_round (s);
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 Interpol_3or6( /* o : interpolated value */
+ Word16 *pX, /* i : input vector */
+ Word16 frac, /* i : fraction (-2..2 for 3*, -3..3 for 6*) */
+ Word16 flag3, /* i : if set, upsampling rate = 3 (6 otherwise) */
+ Flag *pOverflow
+)
+{
+ Word16 i;
+ Word16 k;
+ Word16 *pX1;
+ Word16 *pX2;
+ const Word16 *pC1;
+ const Word16 *pC2;
+ Word32 s;
+ Word16 temp1;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ if (flag3 != 0)
+ {
+ frac <<= 1;
+ /* inter_3[k] = inter_6[2*k] -> k' = 2*k */
+ }
+
+ if (frac < 0)
+ {
+ frac += UP_SAMP_MAX;
+ pX--;
+ }
+
+ pX1 = &pX[0];
+ pX2 = &pX[1];
+ pC1 = &inter_6[frac];
+ temp1 = UP_SAMP_MAX - frac;
+ pC2 = &inter_6[temp1];
+
+ s = 0x04000;
+ k = 0;
+
+ for (i = (L_INTER_SRCH >> 1); i != 0; i--)
+ {
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (pX1--), (Word32) pC1[k], s);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (pX2++), (Word32) pC2[k], s);
+ k += UP_SAMP_MAX;
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (pX1--), (Word32) pC1[k], s);
+ s = amrnb_fxp_mac_16_by_16bb((Word32) * (pX2++), (Word32) pC2[k], s);
+ k <<= 1;
+ }
+
+ return((Word16)(s >> 15));
+}
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/inter_36.h b/media/libstagefright/codecs/amrnb/enc/src/inter_36.h
new file mode 100644
index 0000000..f35a5c5
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/inter_36.h
@@ -0,0 +1,117 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/inter_36.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : inter_36.h
+ Purpose : Interpolating the normalized correlation
+ : with 1/3 or 1/6 resolution.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _INTER_36_H_
+#define _INTER_36_H_
+#define inter_36_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ Word16 Interpol_3or6( /* (o) : interpolated value */
+ Word16 *x, /* (i) : input vector */
+ Word16 frac, /* (i) : fraction (-2..2 for 3*, -3..3 for 6*) */
+ Word16 flag3, /* (i) : if set, upsampling rate = 3 (6 otherwise) */
+ Flag *pOverflow
+ );
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _INTER_36_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.cpp b/media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.cpp
new file mode 100644
index 0000000..c8d7b13
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.cpp
@@ -0,0 +1,213 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+ Pathname: .audio/gsm-amr/c/src/inter_36_tab.c
+
+ Date: 02/01/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed tables from static const to just const.
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition. Removed corresponding header file from Include
+ section.
+
+ Description: Put "extern" back.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ File : inter_36.tab
+ Purpose : Tables for interpolating the normalized correlation
+ with 1/3 or 1/6 resolution.
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+#include "inter_36_tab.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+#define UP_SAMP_MAX 6
+#define FIR_SIZE (UP_SAMP_MAX*L_INTER_SRCH+1)
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+ /* 1/6 resolution interpolation filter (-3 dB at 3600 Hz) */
+ /* Note: The IS641 (7.4) 1/3 resolution filter is simply a subsampled
+ version of the 1/6 resolution filter, i.e. it uses
+ every second coefficient:
+
+ inter_3[k] = inter_6[2*k], 0 <= k <= 3*L_INTER_SRCH
+ */
+
+ const Word16 inter_6[FIR_SIZE] =
+ {
+ 29519,
+ 28316, 24906, 19838, 13896, 7945, 2755,
+ -1127, -3459, -4304, -3969, -2899, -1561,
+ -336, 534, 970, 1023, 823, 516,
+ 220, 0, -131, -194, -215, 0
+ };
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL FUNCTION REFERENCES
+ ; Declare functions defined elsewhere and referenced in this module
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; Define all local variables
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Function body here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Return nothing or data or data pointer
+----------------------------------------------------------------------------*/
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.h b/media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.h
new file mode 100644
index 0000000..21ade69
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/inter_36_tab.h
@@ -0,0 +1,113 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+ Pathname: .audio/gsm-amr/c/include/inter_36_tab.h
+
+ Date: 02/01/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file declares a table BytesUsed.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef INTER_36_TAB_H
+#define INTER_36_TAB_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 inter_6[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/l_comp.cpp b/media/libstagefright/codecs/amrnb/enc/src/l_comp.cpp
new file mode 100644
index 0000000..64be4dd
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/l_comp.cpp
@@ -0,0 +1,162 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ hi = 16 bit signed integer (Word16) whose value falls in
+ the range : 0x8000 <= hi <= 0x7fff.
+ lo = 16 bit signed integer (Word16) whose value falls in
+ the range : 0x8000 <= lo <= 0x7fff.
+
+ Outputs:
+ pOverflow = 1 if overflow happens in a math function called by this function.
+ L_out = 32-bit result of (hi<<16 + lo<<1).
+
+ Returns:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function composes a 32 bit integer from two 16 bit double precision
+ format (DPF) numbers hi and lo by the following operation:
+ 1. Deposit hi into the 16 MS bits of the 32 bit output L_out.
+ 2. Shift lo left by 1.
+ 3. Add results from 1 and 2 with saturation to return the 32 bit result
+ L_out.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] oper_32b.c, ETS Version 2.0.0, February 8, 1999
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "l_comp.h"
+#include "basic_op.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+Word32 L_Comp(Word16 hi, Word16 lo, Flag *pOverflow)
+{
+
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ Word32 L_32;
+ Word32 temp32;
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ L_32 = L_deposit_h(hi);
+
+ temp32 = L_mac(L_32, lo, 1, pOverflow);
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+
+ return (temp32); /* = hi<<16 + lo<<1 */
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/l_extract.cpp b/media/libstagefright/codecs/amrnb/enc/src/l_extract.cpp
new file mode 100644
index 0000000..6add299
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/l_extract.cpp
@@ -0,0 +1,174 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+
+
+
+ Filename: /audio/gsm_amr/c/src/l_extract.c
+
+ Date: 09/07/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template. Changed function interface to pass in a
+ pointer to overflow flag into the function instead of using a
+ global flag. Changed names of function parameters for clarity.
+ Removed inclusion of unwanted header files.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: L_extract
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var = 32 bit signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_32 <= 0x7fff ffff.
+
+ pL_var_hi = pointer to the most significant word of L_var (Word16).
+
+ pL_var_lo = pointer to the least significant word of L_var shifted
+ to the left by 1 (Word16).
+
+ pOverflow = pointer to overflow (Flag)
+
+ Outputs:
+ pOverflow -> 1 if the 32 bit add operation resulted in overflow
+ pL_var_hi -> MS word of L_32.
+ pL_var_lo -> LS word of L_32 shifted left by 1.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function extracts two 16-bit double precision format (DPF) numbers
+ from a 32-bit integer. The MS word of L_var will be stored in the location
+ pointed to by pL_var_hi and the shifted LS word of L_var will be stored in
+ the location pointed to by pL_var_lo.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] L_extract() function in oper_32b.c, UMTS GSM AMR speech codec, R99 -
+ Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void L_Extract(Word32 L_var,
+ Word16 *pL_var_hi,
+ Word16 *pL_var_lo,
+ Flag *pOverflow)
+{
+
+ Word32 temp;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ temp = (L_var >> 16);
+
+ *(pL_var_hi) = (Word16) temp;
+ *(pL_var_lo) = (Word16)((L_var >> 1) - (temp << 15));
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/l_negate.cpp b/media/libstagefright/codecs/amrnb/enc/src/l_negate.cpp
new file mode 100644
index 0000000..588abbb
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/l_negate.cpp
@@ -0,0 +1,166 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ L_var1 = 32 bit long signed integer (Word32) whose value falls
+ in the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ L_var1 = 32-bit negation of input
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function negates the 32 bit variable, L_var1, with saturation; saturate
+ in the case where input is -2147483648 (0x8000 0000).
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] basicop2.c, ETS Version 2.0.0, February 8, 1999
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word32 L_negate (Word32 L_var1)
+{
+ Word32 L_var_out;
+
+ L_var_out = (L_var1 == MIN_32) ? MAX_32 : -L_var1;
+#if (WMOPS)
+ multiCounter[currCounter].L_negate++;
+#endif
+ return (L_var_out);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+Word32 L_negate(register Word32 L_var1)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ L_var1 = (L_var1 == MIN_32) ? MAX_32 : -L_var1;
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return (L_var1);
+}
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/lag_wind.cpp b/media/libstagefright/codecs/amrnb/enc/src/lag_wind.cpp
new file mode 100644
index 0000000..0b2d2a1
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/lag_wind.cpp
@@ -0,0 +1,195 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/lag_wind.c
+
+ Date: 01/31/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated l_extract() function call
+
+ Description: Added casting to eliminate warnings
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "lag_wind.h"
+#include "lag_wind_tab.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: lag_wind
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ m = LPC order of type Word16
+ r_h[] = pointer to autocorrelations (msb) of type Word16
+ r_l[] = pointer to autocorrelations (lsb) of type Word16
+ pOverflow = pointer to overflow flag
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ File : lag_wind.c
+ Purpose : Lag windowing of autocorrelations.
+
+ FUNCTION: Lag_window()
+
+ PURPOSE: Lag windowing of autocorrelations.
+
+ DESCRIPTION:
+ r[i] = r[i]*lag_wind[i], i=1,...,10
+
+ r[i] and lag_wind[i] are in special double precision format.
+ See "oper_32b.c" for the format.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lag_wind.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Word16 i;
+ Word32 x;
+
+ for (i = 1; i <= m; i++)
+ {
+ x = Mpy_32 (r_h[i], r_l[i], lag_h[i - 1], lag_l[i - 1], pOverflow);
+ L_Extract (x, &r_h[i], &r_l[i], pOverflow);
+ }
+ return;
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void Lag_window(
+ Word16 m, /* (i) : LPC order */
+ Word16 r_h[], /* (i/o) : Autocorrelations (msb) */
+ Word16 r_l[], /* (i/o) : Autocorrelations (lsb) */
+ Flag *pOverflow
+)
+{
+ Word16 i;
+ Word32 x;
+ const Word16 *p_lag_h = &lag_h[0];
+ const Word16 *p_lag_l = &lag_l[0];
+ Word16 *p_r_h = &r_h[1];
+ Word16 *p_r_l = &r_l[1];
+
+ for (i = m; i != 0 ; i--)
+ {
+ x = Mpy_32(*(p_r_h), *(p_r_l), *(p_lag_h++), *(p_lag_l++), pOverflow);
+ *(p_r_h) = (Word16)(x >> 16);
+ *(p_r_l++) = (x >> 1) - (*(p_r_h++) << 15);
+ }
+
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/lag_wind.h b/media/libstagefright/codecs/amrnb/enc/src/lag_wind.h
new file mode 100644
index 0000000..4928ac4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/lag_wind.h
@@ -0,0 +1,117 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/lag_wind.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : lag_wind.h
+ Purpose : Lag windowing of autocorrelations.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _LAG_WIND_H_
+#define _LAG_WIND_H_
+#define lag_wind_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ void Lag_window(
+ Word16 m, /* (i) : LPC order */
+ Word16 r_h[], /* (i/o) : Autocorrelations (msb) */
+ Word16 r_l[], /* (i/o) : Autocorrelations (lsb) */
+ Flag *pOverflow
+ );
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LAG_WIND_H_ */
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.cpp b/media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.cpp
new file mode 100644
index 0000000..b0f5b3a
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.cpp
@@ -0,0 +1,233 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+ Pathname: .audio/gsm-amr/c/src/lag_wind_tab.c
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus and removed "extern" from table
+ definition. Removed corresponding header file from Include
+ section.
+
+ Description: Put "extern" back.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ None
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ File : lag_wind.tab
+ Purpose : Table of lag_window for autocorrelation.
+
+ *-----------------------------------------------------*
+ | Table of lag_window for autocorrelation. |
+ | |
+ | noise floor = 1.0001 = (0.9999 on r[1] ..r[10]) |
+ | Bandwitdh expansion = 60 Hz |
+ | |
+ | |
+ | lag_wind[0] = 1.00000000 (not stored) |
+ | lag_wind[1] = 0.99879038 |
+ | lag_wind[2] = 0.99546897 |
+ | lag_wind[3] = 0.98995781 |
+ | lag_wind[4] = 0.98229337 |
+ | lag_wind[5] = 0.97252619 |
+ | lag_wind[6] = 0.96072036 |
+ | lag_wind[7] = 0.94695264 |
+ | lag_wind[8] = 0.93131179 |
+ | lag_wind[9] = 0.91389757 |
+ | lag_wind[10]= 0.89481968 |
+ -------------------------------------------------------
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ None
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "lag_wind_tab.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+ const Word16 lag_h[10] =
+ {
+ 32728,
+ 32619,
+ 32438,
+ 32187,
+ 31867,
+ 31480,
+ 31029,
+ 30517,
+ 29946,
+ 29321
+ };
+
+ const Word16 lag_l[10] =
+ {
+ 11904,
+ 17280,
+ 30720,
+ 25856,
+ 24192,
+ 28992,
+ 24384,
+ 7360,
+ 19520,
+ 14784
+ };
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL FUNCTION REFERENCES
+ ; Declare functions defined elsewhere and referenced in this module
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; Define all local variables
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Function body here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Return nothing or data or data pointer
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.h b/media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.h
new file mode 100644
index 0000000..c210932
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/lag_wind_tab.h
@@ -0,0 +1,112 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+ Pathname: .audio/gsm-amr/c/include/lag_wind_tab.h
+
+ Date: 01/31/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added #ifdef __cplusplus after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file declares tables used by lag_wind.c.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef LAG_WIND_TAB_H
+#define LAG_WIND_TAB_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 lag_h[];
+ extern const Word16 lag_l[];
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/levinson.cpp b/media/libstagefright/codecs/amrnb/enc/src/levinson.cpp
new file mode 100644
index 0000000..001897b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/levinson.cpp
@@ -0,0 +1,824 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/levinson.c
+ Funtions: Levinson_init
+ Levinson_reset
+ Levinson_exit
+ Levinson
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the function the implements the Levinson-Durbin algorithm
+ using double-precision arithmetic. This file also includes functions to
+ initialize, allocate, and deallocate memory used by the Levinson function.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+#include <string.h>
+
+#include "levinson.h"
+#include "basicop_malloc.h"
+#include "basic_op.h"
+#include "div_32.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Levinson_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to an array of pointers to structures of type
+ LevinsonState
+
+ Outputs:
+ pointer pointed to by state points to the newly allocated memory to
+ be used by Levinson function
+
+ Returns:
+ return_value = 0, if initialization was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function allocates and initializes the state memory used by the
+ Levinson function.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ levinson.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Levinson_init (LevinsonState **state)
+{
+ LevinsonState* s;
+
+ if (state == (LevinsonState **) NULL){
+ //fprint(stderr, "Levinson_init: invalid parameter\n");
+ return -1;
+ }
+ *state = NULL;
+
+ // allocate memory
+ if ((s= (LevinsonState *) malloc(sizeof(LevinsonState))) == NULL){
+ //fprint(stderr, "Levinson_init: can not malloc state structure\n");
+ return -1;
+ }
+
+ Levinson_reset(s);
+ *state = s;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Levinson_init(LevinsonState **state)
+{
+ LevinsonState* s;
+
+ if (state == (LevinsonState **) NULL)
+ {
+ /* fprint(stderr, "Levinson_init: invalid parameter\n"); */
+ return(-1);
+ }
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (LevinsonState *) malloc(sizeof(LevinsonState))) == NULL)
+ {
+ /* fprint(stderr, "Levinson_init:
+ can not malloc state structure\n"); */
+ return(-1);
+ }
+
+ Levinson_reset(s);
+ *state = s;
+
+ return(0);
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Levinson_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to structures of type LevinsonState
+
+ Outputs:
+ old_A field of structure pointed to by state is initialized to 4096
+ (first location) and the rest to zeros
+
+ Returns:
+ return_value = 0, if reset was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function initializes the state memory used by the Levinson function to
+ zero.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ levinson.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Levinson_reset (LevinsonState *state)
+{
+ Word16 i;
+
+ if (state == (LevinsonState *) NULL){
+ fprint(stderr, "Levinson_reset: invalid parameter\n");
+ return -1;
+ }
+
+ state->old_A[0] = 4096;
+ for(i = 1; i < M + 1; i++)
+ state->old_A[i] = 0;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Levinson_reset(LevinsonState *state)
+{
+ Word16 i;
+
+ if (state == (LevinsonState *) NULL)
+ {
+ /* fprint(stderr, "Levinson_reset: invalid parameter\n"); */
+ return(-1);
+ }
+
+ state->old_A[0] = 4096;
+ for (i = 1; i < M + 1; i++)
+ {
+ state->old_A[i] = 0;
+ }
+
+ return(0);
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Levinson_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to an array of pointers to structures of type
+ LevinsonState
+
+ Outputs:
+ pointer pointed to by state is set to the NULL address
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function deallocates the state memory used by the Levinson function.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ levinson.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Levinson_exit (LevinsonState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ // deallocate memory
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Levinson_exit(LevinsonState **state)
+{
+ if (state == NULL || *state == NULL)
+ {
+ return;
+ }
+
+ /* deallocate memory */
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Levinson
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to structures of type LevinsonState
+ Rh = vector containing most significant byte of
+ autocorrelation values (Word16)
+ Rl = vector containing least significant byte of
+ autocorrelation values (Word16)
+ A = vector of LPC coefficients (10th order) (Word16)
+ rc = vector containing first four reflection coefficients (Word16)
+ pOverflow = pointer to overflow indicator (Flag)
+
+ Outputs:
+ A contains the newly calculated LPC coefficients
+ rc contains the newly calculated reflection coefficients
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function implements the Levinson-Durbin algorithm using double-
+ precision arithmetic. This is used to compute the Linear Predictive (LP)
+ filter parameters from the speech autocorrelation values.
+
+ The algorithm implemented is as follows:
+ A[0] = 1
+ K = -R[1]/R[0]
+ A[1] = K
+ Alpha = R[0] * (1-K**2]
+
+ FOR i = 2 to M
+
+ S = SUM ( R[j]*A[i-j] ,j=1,i-1 ) + R[i]
+ K = -S / Alpha
+
+ FOR j = 1 to i-1
+ An[j] = A[j] + K*A[i-j] where An[i] = new A[i]
+ ENDFOR
+
+ An[i]=K
+ Alpha=Alpha * (1-K**2)
+
+ END
+
+ where:
+ R[i] = autocorrelations
+ A[i] = filter coefficients
+ K = reflection coefficient
+ Alpha = prediction gain
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ levinson.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Levinson (
+ LevinsonState *st,
+ Word16 Rh[], // i : Rh[m+1] Vector of autocorrelations (msb)
+ Word16 Rl[], // i : Rl[m+1] Vector of autocorrelations (lsb)
+ Word16 A[], // o : A[m] LPC coefficients (m = 10)
+ Word16 rc[] // o : rc[4] First 4 reflection coefficients
+)
+{
+ Word16 i, j;
+ Word16 hi, lo;
+ Word16 Kh, Kl; // reflexion 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
+
+ // K = A[1] = -R[1] / R[0]
+
+ t1 = L_Comp (Rh[1], Rl[1]);
+ t2 = L_abs (t1); // abs R[1]
+ t0 = Div_32 (t2, Rh[0], Rl[0]); // R[1]/R[0]
+ if (t1 > 0)
+ t0 = L_negate (t0); // -R[1]/R[0]
+ L_Extract (t0, &Kh, &Kl); // K in DPF
+
+ rc[0] = pv_round (t0);
+
+ t0 = L_shr (t0, 4); // A[1] in
+ L_Extract (t0, &Ah[1], &Al[1]); // A[1] in DPF
+
+ // Alpha = R[0] * (1-K**2)
+
+ t0 = Mpy_32 (Kh, Kl, Kh, Kl); // K*K
+ t0 = L_abs (t0); // Some case <0 !!
+ t0 = L_sub ((Word32) 0x7fffffffL, t0); // 1 - K*K
+ L_Extract (t0, &hi, &lo); // DPF format
+ t0 = Mpy_32 (Rh[0], Rl[0], hi, lo); // Alpha in
+
+ // Normalize Alpha
+
+ alp_exp = norm_l (t0);
+ t0 = L_shl (t0, alp_exp);
+ L_Extract (t0, &alp_h, &alp_l); // DPF format
+
+ *--------------------------------------*
+ * 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 = L_add (t0, Mpy_32 (Rh[j], Rl[j], Ah[i - j], Al[i - j]));
+ }
+ t0 = L_shl (t0, 4);
+
+ t1 = L_Comp (Rh[i], Rl[i]);
+ t0 = L_add (t0, t1); // add R[i]
+
+ // K = -t0 / Alpha
+
+ t1 = L_abs (t0);
+ t2 = Div_32 (t1, alp_h, alp_l); // abs(t0)/Alpha
+ if (t0 > 0)
+ t2 = L_negate (t2); // K =-t0/Alpha
+ t2 = L_shl (t2, alp_exp); // denormalize; compare to Alpha
+ L_Extract (t2, &Kh, &Kl); // K in DPF
+
+ if (sub (i, 5) < 0)
+ {
+ rc[i - 1] = pv_round (t2);
+ }
+ // Test for unstable filter. If unstable keep old A(z)
+
+ if (sub (abs_s (Kh), 32750) > 0)
+ {
+ for (j = 0; j <= M; j++)
+ {
+ A[j] = st->old_A[j];
+ }
+
+ for (j = 0; j < 4; j++)
+ {
+ rc[j] = 0;
+ }
+
+ return 0;
+ }
+ *------------------------------------------*
+ * 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 = L_add(t0, L_Comp(Ah[j], Al[j]));
+ L_Extract (t0, &Anh[j], &Anl[j]);
+ }
+ t2 = L_shr (t2, 4);
+ L_Extract (t2, &Anh[i], &Anl[i]);
+
+ // Alpha = Alpha * (1-K**2)
+
+ t0 = Mpy_32 (Kh, Kl, Kh, Kl); // K*K
+ t0 = L_abs (t0); // Some case <0 !!
+ t0 = L_sub ((Word32) 0x7fffffffL, t0); // 1 - K*K
+ L_Extract (t0, &hi, &lo); // DPF format
+ t0 = Mpy_32 (alp_h, alp_l, hi, lo);
+
+ // Normalize Alpha
+
+ j = norm_l (t0);
+ t0 = L_shl (t0, j);
+ L_Extract (t0, &alp_h, &alp_l); // DPF format
+ alp_exp = add (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];
+ }
+ }
+
+ A[0] = 4096;
+ for (i = 1; i <= M; i++)
+ {
+ t0 = L_Comp (Ah[i], Al[i]);
+ st->old_A[i] = A[i] = pv_round (L_shl (t0, 1));
+ }
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Levinson(
+ LevinsonState *st,
+ Word16 Rh[], /* i : Rh[m+1] Vector of autocorrelations (msb) */
+ Word16 Rl[], /* i : Rl[m+1] Vector of autocorrelations (lsb) */
+ Word16 A[], /* o : A[m] LPC coefficients (m = 10) */
+ Word16 rc[], /* o : rc[4] First 4 reflection coefficients */
+ Flag *pOverflow
+)
+{
+ register Word16 i;
+ register Word16 j;
+ Word16 hi;
+ Word16 lo;
+ Word16 Kh; /* reflexion coefficient; hi and lo */
+ Word16 Kl;
+ Word16 alp_h; /* Prediction gain; hi lo and exponent*/
+ Word16 alp_l;
+ Word16 alp_exp;
+ Word16 Ah[M + 1]; /* LPC coef. in double prec. */
+ Word16 Al[M + 1];
+ Word16 Anh[M + 1]; /* LPC coef.for next iteration in */
+ Word16 Anl[M + 1]; /* double prec. */
+ register Word32 t0; /* temporary variable */
+ register Word32 t1; /* temporary variable */
+ register Word32 t2; /* temporary variable */
+
+ Word16 *p_Rh;
+ Word16 *p_Rl;
+ Word16 *p_Ah;
+ Word16 *p_Al;
+ Word16 *p_Anh;
+ Word16 *p_Anl;
+ Word16 *p_A;
+
+ /* K = A[1] = -R[1] / R[0] */
+ t1 = ((Word32) * (Rh + 1)) << 16;
+ t1 += *(Rl + 1) << 1;
+
+ t2 = L_abs(t1); /* abs R[1] - required by Div_32 */
+ t0 = Div_32(t2, *Rh, *Rl, pOverflow); /* R[1]/R[0] */
+
+ if (t1 > 0)
+ {
+ t0 = L_negate(t0); /* -R[1]/R[0] */
+ }
+
+ /* K in DPF */
+ Kh = (Word16)(t0 >> 16);
+ Kl = (Word16)((t0 >> 1) - ((Word32)(Kh) << 15));
+
+ *rc = pv_round(t0, pOverflow);
+
+ t0 = t0 >> 4;
+
+ /* A[1] in DPF */
+ *(Ah + 1) = (Word16)(t0 >> 16);
+
+ *(Al + 1) = (Word16)((t0 >> 1) - ((Word32)(*(Ah + 1)) << 15));
+
+ /* Alpha = R[0] * (1-K**2) */
+ t0 = Mpy_32(Kh, Kl, Kh, Kl, pOverflow); /* K*K */
+ t0 = L_abs(t0); /* Some case <0 !! */
+ t0 = 0x7fffffffL - t0; /* 1 - K*K */
+
+ /* DPF format */
+ hi = (Word16)(t0 >> 16);
+ lo = (Word16)((t0 >> 1) - ((Word32)(hi) << 15));
+
+ t0 = Mpy_32(*Rh, *Rl, hi, lo, pOverflow); /* Alpha in */
+
+ /* Normalize Alpha */
+
+ alp_exp = norm_l(t0);
+ t0 = t0 << alp_exp;
+
+ /* DPF format */
+ alp_h = (Word16)(t0 >> 16);
+ alp_l = (Word16)((t0 >> 1) - ((Word32)(alp_h) << 15));
+
+ /*--------------------------------------*
+ * 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;
+ p_Rh = &Rh[1];
+ p_Rl = &Rl[1];
+ p_Ah = &Ah[i-1];
+ p_Al = &Al[i-1];
+ for (j = 1; j < i; j++)
+ {
+ t0 += (((Word32) * (p_Rh)* *(p_Al--)) >> 15);
+ t0 += (((Word32) * (p_Rl++)* *(p_Ah)) >> 15);
+ t0 += ((Word32) * (p_Rh++)* *(p_Ah--));
+ }
+
+ t0 = t0 << 5;
+
+ t1 = ((Word32) * (Rh + i) << 16) + ((Word32)(*(Rl + i)) << 1);
+ t0 += t1;
+
+ /* K = -t0 / Alpha */
+
+ t1 = L_abs(t0);
+ t2 = Div_32(t1, alp_h, alp_l, pOverflow); /* abs(t0)/Alpha */
+
+ if (t0 > 0)
+ {
+ t2 = L_negate(t2); /* K =-t0/Alpha */
+ }
+
+ t2 = L_shl(t2, alp_exp, pOverflow); /* denormalize; compare to Alpha */
+ Kh = (Word16)(t2 >> 16);
+ Kl = (Word16)((t2 >> 1) - ((Word32)(Kh) << 15));
+
+ if (i < 5)
+ {
+ *(rc + i - 1) = (Word16)((t2 + 0x00008000L) >> 16);
+ }
+ /* Test for unstable filter. If unstable keep old A(z) */
+ if ((abs_s(Kh)) > 32750)
+ {
+ memcpy(A, &(st->old_A[0]), sizeof(Word16)*(M + 1));
+ memset(rc, 0, sizeof(Word16)*4);
+ return(0);
+ }
+ /*------------------------------------------*
+ * Compute new LPC coeff. -> An[i] *
+ * An[j]= A[j] + K*A[i-j] , j=1 to i-1 *
+ * An[i]= K *
+ *------------------------------------------*/
+ p_Ah = &Ah[i-1];
+ p_Al = &Al[i-1];
+ p_Anh = &Anh[1];
+ p_Anl = &Anl[1];
+ for (j = 1; j < i; j++)
+ {
+ t0 = (((Word32)Kh* *(p_Al--)) >> 15);
+ t0 += (((Word32)Kl* *(p_Ah)) >> 15);
+ t0 += ((Word32)Kh* *(p_Ah--));
+
+ t0 += (Ah[j] << 15) + Al[j];
+
+ *(p_Anh) = (Word16)(t0 >> 15);
+ *(p_Anl++) = (Word16)(t0 - ((Word32)(*(p_Anh++)) << 15));
+ }
+
+ *(p_Anh) = (Word16)(t2 >> 20);
+ *(p_Anl) = (Word16)((t2 >> 5) - ((Word32)(*(Anh + i)) << 15));
+
+ /* Alpha = Alpha * (1-K**2) */
+
+ t0 = Mpy_32(Kh, Kl, Kh, Kl, pOverflow); /* K*K */
+ t0 = L_abs(t0); /* Some case <0 !! */
+ t0 = 0x7fffffffL - t0; /* 1 - K*K */
+
+ hi = (Word16)(t0 >> 16);
+ lo = (Word16)((t0 >> 1) - ((Word32)(hi) << 15));
+
+ t0 = (((Word32)alp_h * lo) >> 15);
+ t0 += (((Word32)alp_l * hi) >> 15);
+ t0 += ((Word32)alp_h * hi);
+
+ t0 <<= 1;
+ /* Normalize Alpha */
+
+ j = norm_l(t0);
+ t0 <<= j;
+ alp_h = (Word16)(t0 >> 16);
+ alp_l = (Word16)((t0 >> 1) - ((Word32)(alp_h) << 15));
+ alp_exp += j; /* Add normalization to alp_exp */
+
+ /* A[j] = An[j] */
+ memcpy(&Ah[1], &Anh[1], sizeof(Word16)*i);
+ memcpy(&Al[1], &Anl[1], sizeof(Word16)*i);
+ }
+
+ p_A = &A[0];
+ *(p_A++) = 4096;
+ p_Ah = &Ah[1];
+ p_Al = &Al[1];
+
+ for (i = 1; i <= M; i++)
+ {
+ t0 = ((Word32) * (p_Ah++) << 15) + *(p_Al++);
+ st->old_A[i] = *(p_A++) = (Word16)((t0 + 0x00002000) >> 14);
+ }
+
+ return(0);
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/levinson.h b/media/libstagefright/codecs/amrnb/enc/src/levinson.h
new file mode 100644
index 0000000..65ba481
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/levinson.h
@@ -0,0 +1,143 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/levinson.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+ Description: 1. Modified "int" definition by Word16
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : lag_wind.h
+ Purpose : Lag windowing of autocorrelations.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _LEVINSON_H_
+#define _LEVINSON_H_
+#define levinson_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 old_A[M + 1]; /* Last A(z) for case of unstable filter */
+ } LevinsonState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ Word16 Levinson_init(LevinsonState **st);
+ /* initialize one instance of the pre processing state.
+ Stores pointer to filter status struct in *st. This pointer has to
+ be passed to Levinson in each call.
+ returns 0 on success
+ */
+
+ Word16 Levinson_reset(LevinsonState *st);
+ /* reset of pre processing state (i.e. set state memory to zero)
+ returns 0 on success
+ */
+ void Levinson_exit(LevinsonState **st);
+ /* de-initialize pre processing state (i.e. free status struct)
+ stores NULL in *st
+ */
+
+ Word16 Levinson(
+ LevinsonState *st,
+ Word16 Rh[], /* i : Rh[m+1] Vector of autocorrelations (msb) */
+ Word16 Rl[], /* i : Rl[m+1] Vector of autocorrelations (lsb) */
+ Word16 A[], /* o : A[m] LPC coefficients (m = 10) */
+ Word16 rc[], /* o : rc[4] First 4 reflection coefficients */
+ Flag *pOverflow
+ );
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LEVINSON_H_ */
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/lpc.cpp b/media/libstagefright/codecs/amrnb/enc/src/lpc.cpp
new file mode 100644
index 0000000..3c1a4bc
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/lpc.cpp
@@ -0,0 +1,542 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/lpc.c
+
+ Date: 01/31/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updating includes and making code more simple as per comments.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+
+#include "lpc.h"
+#include "typedef.h"
+#include "oper_32b.h"
+#include "autocorr.h"
+#include "lag_wind.h"
+#include "levinson.h"
+#include "cnst.h"
+#include "mode.h"
+#include "window_tab.h"
+#include "sub.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: lpc_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to pointer of state data of type lpcState
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function initializes the state data for the LPC module.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lpc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+ lpcState* s;
+
+ if (state == (lpcState **) NULL){
+ // fprintf(stderr, "lpc_init: invalid parameter\n");
+ return -1;
+ }
+ *state = NULL;
+
+ // allocate memory
+ if ((s= (lpcState *) malloc(sizeof(lpcState))) == NULL){
+ // fprintf(stderr, "lpc_init: can not malloc state structure\n");
+ return -1;
+ }
+
+ s->levinsonSt = NULL;
+
+ // Init sub states
+ if (Levinson_init(&s->levinsonSt)) {
+ lpc_exit(&s);
+ return -1;
+ }
+
+
+ lpc_reset(s);
+ *state = s;
+
+ return 0;
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 lpc_init(lpcState **state)
+{
+ lpcState* s;
+
+ if (state == (lpcState **) NULL)
+ {
+ /* fprintf(stderr, "lpc_init: invalid parameter\n"); */
+ return -1;
+ }
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (lpcState *) malloc(sizeof(lpcState))) == NULL)
+ {
+ /* fprintf(stderr, "lpc_init: can not malloc state structure\n"); */
+ return -1;
+ }
+
+ s->levinsonSt = NULL;
+
+ /* Init sub states */
+ if (Levinson_init(&s->levinsonSt))
+ {
+ lpc_exit(&s);
+ return -1;
+ }
+
+ lpc_reset(s);
+ *state = s;
+
+ return 0;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: lpc_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to pointer of state data of type lpcState
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function resets the state data for the LPC module.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lpc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ if (state == (lpcState *) NULL){
+ // fprintf(stderr, "lpc_reset: invalid parameter\n");
+ return -1;
+ }
+
+ Levinson_reset(state->levinsonSt);
+
+ return 0;
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 lpc_reset(lpcState *state)
+{
+
+ if (state == (lpcState *) NULL)
+ {
+ /* fprintf(stderr, "lpc_reset: invalid parameter\n"); */
+ return -1;
+ }
+
+ Levinson_reset(state->levinsonSt);
+
+ return 0;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: lpc_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to pointer of state data of type lpcState
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function frees the state data for the LPC module.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lpc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+ if (state == NULL || *state == NULL)
+ return;
+
+ Levinson_exit(&(*state)->levinsonSt);
+
+ // deallocate memory
+ free(*state);
+ *state = NULL;
+
+ return;
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void lpc_exit(lpcState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ Levinson_exit(&(*state)->levinsonSt);
+
+ /* deallocate memory */
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: lpc
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to state data of type lpcState
+ mode = coder mode of type enum Mode
+ x[] = pointer to input signal (Q15) of type Word16
+ x_12k2[] = pointer to input signal (EFR) (Q15) of type Word16
+ pOverflow = pointer to overflow indicator of type Flag
+
+ Outputs:
+ a[] = pointer to predictor coefficients (Q12) of type Word16
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function executes the LPC functionality for GSM AMR.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ lpc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Word16 rc[4]; // First 4 reflection coefficients Q15
+ Word16 rLow[MP1], rHigh[MP1]; // Autocorrelations low and hi
+ // No fixed Q value but normalized
+ // so that overflow is avoided
+
+ if ( sub ((Word16)mode, (Word16)MR122) == 0)
+ {
+ // Autocorrelations
+ Autocorr(x_12k2, M, rHigh, rLow, window_160_80);
+ // Lag windowing
+ Lag_window(M, rHigh, rLow);
+ // Levinson Durbin
+ Levinson(st->levinsonSt, rHigh, rLow, &a[MP1], rc);
+
+ // Autocorrelations
+ Autocorr(x_12k2, M, rHigh, rLow, window_232_8);
+ // Lag windowing
+ Lag_window(M, rHigh, rLow);
+ // Levinson Durbin
+ Levinson(st->levinsonSt, rHigh, rLow, &a[MP1 * 3], rc);
+ }
+ else
+ {
+ // Autocorrelations
+ Autocorr(x, M, rHigh, rLow, window_200_40);
+ // Lag windowing
+ Lag_window(M, rHigh, rLow);
+ // Levinson Durbin
+ Levinson(st->levinsonSt, rHigh, rLow, &a[MP1 * 3], rc);
+ }
+
+ return 0;
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void lpc(
+ lpcState *st, /* i/o: State struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 x[], /* i : Input signal Q15 */
+ Word16 x_12k2[], /* i : Input signal (EFR) Q15 */
+ Word16 a[], /* o : predictor coefficients Q12 */
+ Flag *pOverflow
+)
+{
+ Word16 rc[4]; /* First 4 reflection coefficients Q15 */
+ Word16 rLow[MP1], rHigh[MP1]; /* Autocorrelations low and hi */
+ /* No fixed Q value but normalized */
+ /* so that overflow is avoided */
+
+ if (mode == MR122)
+ {
+ /* Autocorrelations */
+ Autocorr(x_12k2, M, rHigh, rLow, window_160_80, pOverflow);
+ /* Lag windowing */
+ Lag_window(M, rHigh, rLow, pOverflow);
+ /* Levinson Durbin */
+ Levinson(st->levinsonSt, rHigh, rLow, &a[MP1], rc, pOverflow);
+
+ /* Autocorrelations */
+ Autocorr(x_12k2, M, rHigh, rLow, window_232_8, pOverflow);
+ /* Lag windowing */
+ Lag_window(M, rHigh, rLow, pOverflow);
+ /* Levinson Durbin */
+ Levinson(st->levinsonSt, rHigh, rLow, &a[MP1 * 3], rc, pOverflow);
+ }
+ else
+ {
+ /* Autocorrelations */
+ Autocorr(x, M, rHigh, rLow, window_200_40, pOverflow);
+ /* Lag windowing */
+ Lag_window(M, rHigh, rLow, pOverflow);
+ /* Levinson Durbin */
+ Levinson(st->levinsonSt, rHigh, rLow, &a[MP1 * 3], rc, pOverflow);
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/lpc.h b/media/libstagefright/codecs/amrnb/enc/src/lpc.h
new file mode 100644
index 0000000..705a1d4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/lpc.h
@@ -0,0 +1,147 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/lpc.h
+
+ Date: 01/29/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : lpc.h
+ Purpose : 2 LP analyses centered at 2nd and 4th subframe
+ for mode 12.2. For all other modes a
+ LP analysis centered at 4th subframe is
+ performed.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _LPC_H_
+#define _LPC_H_
+#define lpc_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "levinson.h"
+#include "mode.h"
+
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ LevinsonState *levinsonSt;
+ } lpcState;
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ Word16 lpc_init(lpcState **st);
+ /* initialize one instance of the pre processing state.
+ Stores pointer to filter status struct in *st. This pointer has to
+ be passed to lpc in each call.
+ returns 0 on success
+ */
+
+ Word16 lpc_reset(lpcState *st);
+ /* reset of pre processing state (i.e. set state memory to zero)
+ returns 0 on success
+ */
+ void lpc_exit(lpcState **st);
+ /* de-initialize pre processing state (i.e. free status struct)
+ stores NULL in *st
+ */
+
+ void lpc(
+ lpcState *st, /* i/o: State struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 x[], /* i : Input signal Q15 */
+ Word16 x_12k2[], /* i : Input signal (EFR) Q15 */
+ Word16 a[], /* o : predictor coefficients Q12 */
+ Flag *pOverflow
+ );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LPC_H_ */
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ol_ltp.cpp b/media/libstagefright/codecs/amrnb/enc/src/ol_ltp.cpp
new file mode 100644
index 0000000..7d034e0
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/ol_ltp.cpp
@@ -0,0 +1,246 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/ol_ltp.c
+ Funtions: ol_ltp
+
+ Date: 04/18/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Adding pOverflow to the functions to remove global variables.
+ These changes are needed for the EPOC releases. Cleaned up code.
+ Updated template.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "ol_ltp.h"
+#include "cnst.h"
+#include "pitch_ol.h"
+#include "p_ol_wgh.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ol_ltp
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to pitchOLWghtState structure
+ vadSt = pointer to a vadState structure
+ mode = coder mode (Mode)
+ wsp = pointer to buffer of signal used to compute the Open loop pitch
+ T_op = pointer to open loop pitch lag
+ old_lags = pointer to history with old stored Cl lags (Word16)
+ ol_gain_flg = pointer to OL gain flag (Word16)
+ idx = 16 bit value specifies the frame index
+ dtx = Data of type 'Flag' used for dtx. Use dtx=1, do not use dtx=0
+ pOverflow = pointer to Overflow indicator (Flag)
+
+ Outputs:
+ pOverflow -> 1 if processing this funvction results in satuaration
+
+ Returns:
+ Zero
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes the open loop pitch lag.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ol_ltp.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int ol_ltp(
+ pitchOLWghtState *st, // i/o : State struct
+ vadState *vadSt, // i/o : VAD state struct
+ enum Mode mode, // i : coder mode
+ Word16 wsp[], // i : signal used to compute the OL pitch, Q0
+ // uses signal[-pit_max] to signal[-1]
+ Word16 *T_op, // o : open loop pitch lag, Q0
+ Word16 old_lags[], // i : history with old stored Cl lags
+ Word16 ol_gain_flg[], // i : OL gain flag
+ Word16 idx, // i : index
+ Flag dtx // i : dtx flag; use dtx=1, do not use dtx=0
+ )
+{
+ if (sub ((Word16)mode, (Word16)MR102) != 0 )
+ {
+ ol_gain_flg[0] = 0;
+ ol_gain_flg[1] = 0;
+ }
+
+ if (sub ((Word16)mode, (Word16)MR475) == 0 || sub ((Word16)mode, (Word16)MR515) == 0 )
+ {
+ *T_op = Pitch_ol(vadSt, mode, wsp, PIT_MIN, PIT_MAX, L_FRAME, idx, dtx);
+ }
+ else
+ {
+ if ( sub ((Word16)mode, (Word16)MR795) <= 0 )
+ {
+ *T_op = Pitch_ol(vadSt, mode, wsp, PIT_MIN, PIT_MAX, L_FRAME_BY2,
+ idx, dtx);
+ }
+ else if ( sub ((Word16)mode, (Word16)MR102) == 0 )
+ {
+ *T_op = Pitch_ol_wgh(st, vadSt, wsp, PIT_MIN, PIT_MAX, L_FRAME_BY2,
+ old_lags, ol_gain_flg, idx, dtx);
+ }
+ else
+ {
+ *T_op = Pitch_ol(vadSt, mode, wsp, PIT_MIN_MR122, PIT_MAX,
+ L_FRAME_BY2, idx, dtx);
+ }
+ }
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void ol_ltp(
+ pitchOLWghtState *st, /* i/o : State struct */
+ vadState *vadSt, /* i/o : VAD state struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 wsp[], /* i : signal used to compute the OL pitch, Q0 */
+ /* uses signal[-pit_max] to signal[-1] */
+ Word16 *T_op, /* o : open loop pitch lag, Q0 */
+ Word16 old_lags[], /* i : history with old stored Cl lags */
+ Word16 ol_gain_flg[], /* i : OL gain flag */
+ Word16 idx, /* i : index */
+ Flag dtx, /* i : dtx flag; use dtx=1, do not use dtx=0 */
+ Flag *pOverflow /* i/o : overflow indicator */
+)
+{
+ if ((mode != MR102))
+ {
+ ol_gain_flg[0] = 0;
+ ol_gain_flg[1] = 0;
+ }
+
+ if ((mode == MR475) || (mode == MR515))
+ {
+ *T_op = Pitch_ol(vadSt, mode, wsp, PIT_MIN, PIT_MAX, L_FRAME, idx, dtx,
+ pOverflow);
+ }
+ else
+ {
+ if (mode <= MR795)
+ {
+ *T_op = Pitch_ol(vadSt, mode, wsp, PIT_MIN, PIT_MAX, L_FRAME_BY2,
+ idx, dtx, pOverflow);
+ }
+ else if (mode == MR102)
+ {
+ *T_op = Pitch_ol_wgh(st, vadSt, wsp, PIT_MIN, PIT_MAX, L_FRAME_BY2,
+ old_lags, ol_gain_flg, idx, dtx, pOverflow);
+ }
+ else
+ {
+ *T_op = Pitch_ol(vadSt, mode, wsp, PIT_MIN_MR122, PIT_MAX,
+ L_FRAME_BY2, idx, dtx, pOverflow);
+ }
+ }
+
+}
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ol_ltp.h b/media/libstagefright/codecs/amrnb/enc/src/ol_ltp.h
new file mode 100644
index 0000000..f8c1481
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/ol_ltp.h
@@ -0,0 +1,125 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/ol_ltp.h
+
+ Date: 02/06/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : ol_ltp.h
+ Purpose : Compute the open loop pitch lag.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef OL_LTP_H
+#define OL_LTP_H "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "p_ol_wgh.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ void ol_ltp(
+ pitchOLWghtState *st, /* i/o : State struct */
+ vadState *vadSt, /* i/o : VAD state struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 wsp[], /* i : signal used to compute the OL pitch, Q0 */
+ /* uses signal[-pit_max] to signal[-1] */
+ Word16 *T_op, /* o : open loop pitch lag, Q0 */
+ Word16 old_lags[], /* i : history with old stored Cl lags */
+ Word16 ol_gain_flg[], /* i : OL gain flag */
+ Word16 idx, /* i : index */
+ Flag dtx, /* i : dtx flag; use dtx=1, do not use dtx=0 */
+ Flag *pOverflow /* i/o : overflow Flag */
+ );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OL_LTP_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/p_ol_wgh.cpp b/media/libstagefright/codecs/amrnb/enc/src/p_ol_wgh.cpp
new file mode 100644
index 0000000..68d7345
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/p_ol_wgh.cpp
@@ -0,0 +1,989 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/p_ol_wgh.c
+ Funtions: p_ol_wgh_init
+ p_ol_wgh_reset
+ p_ol_wgh_exit
+ Lag_max
+ Pitch_ol_wgh
+
+ Date: 02/05/2002
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: t0 was not being declared as Word32.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ The modules in this file compute the open loop pitch lag with weighting.
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+
+#include "p_ol_wgh.h"
+#include "typedef.h"
+#include "cnst.h"
+#include "basic_op.h"
+#include "gmed_n.h"
+#include "inv_sqrt.h"
+#include "vad1.h"
+#include "calc_cor.h"
+#include "hp_max.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: p_ol_wgh_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs
+ state = pointer to a pointer of structure type pitchOLWghtState
+
+ Outputs:
+ None
+
+ Returns:
+ 0 if the memory allocation is a success
+ -1 if the memory allocation fails
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function allocates state memory and initializes state memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ p_ol_wgh.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int p_ol_wgh_init (pitchOLWghtState **state)
+{
+ pitchOLWghtState* s;
+
+ if (state == (pitchOLWghtState **) NULL){
+ // fprintf(stderr, "p_ol_wgh_init: invalid parameter\n");
+ return -1;
+ }
+ *state = NULL;
+
+ // allocate memory
+ if ((s= (pitchOLWghtState *) malloc(sizeof(pitchOLWghtState))) == NULL){
+ // fprintf(stderr, "p_ol_wgh_init: can not malloc state structure\n");
+ return -1;
+ }
+
+ p_ol_wgh_reset(s);
+
+ *state = s;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 p_ol_wgh_init(pitchOLWghtState **state)
+{
+ pitchOLWghtState* s;
+
+ if (state == (pitchOLWghtState **) NULL)
+ {
+ /* fprintf(stderr, "p_ol_wgh_init: invalid parameter\n"); */
+ return -1;
+ }
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (pitchOLWghtState *) malloc(sizeof(pitchOLWghtState))) == NULL)
+ {
+ /* fprintf(stderr, "p_ol_wgh_init: can not malloc state structure\n"); */
+ return -1;
+ }
+
+ p_ol_wgh_reset(s);
+
+ *state = s;
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+; End Function: p_ol_wgh_init
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: p_ol_wgh_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs
+ st = pointer to structure type pitchOLWghtState
+
+ Outputs:
+ None
+
+ Returns:
+ 0 if the memory initialization is a success
+ -1 if the memory initialization fails
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function initializes state memory to zero
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ p_ol_wgh.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int p_ol_wgh_reset (pitchOLWghtState *st)
+{
+ if (st == (pitchOLWghtState *) NULL){
+ // fprintf(stderr, "p_ol_wgh_reset: invalid parameter\n");
+ return -1;
+ }
+
+ // Reset pitch search states
+ st->old_T0_med = 40;
+ st->ada_w = 0;
+ st->wght_flg = 0;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 p_ol_wgh_reset(pitchOLWghtState *st)
+{
+ if (st == (pitchOLWghtState *) NULL)
+ {
+ /* fprintf(stderr, "p_ol_wgh_reset: invalid parameter\n"); */
+ return -1;
+ }
+
+ /* Reset pitch search states */
+ st->old_T0_med = 40;
+ st->ada_w = 0;
+ st->wght_flg = 0;
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+; End Function: p_ol_wgh_reset
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: p_ol_wgh_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs
+ st = pointer to a pointer of structure type pitchOLWghtState
+
+ Outputs:
+ None
+
+ Returns:
+ 0 if the memory initialization is a success
+ -1 if the memory initialization fails
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function frees the memory used for state memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ p_ol_wgh.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void p_ol_wgh_exit (pitchOLWghtState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ // deallocate memory
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void p_ol_wgh_exit(pitchOLWghtState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ /* deallocate memory */
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+
+/*----------------------------------------------------------------------------
+; End Function: p_ol_wgh_exit
+----------------------------------------------------------------------------*/
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Lag_max
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ corr = pointer to buffer of correlation values (Word32)
+ scal_sig = pointer to buffer of scaled signal values (Word16)
+ scal_fac = scaled signal factor (Word16)
+ scal_flag = EFR compatible scaling flag (Word16)
+ L_frame = length of frame to compute pitch (Word16)
+ lag_max = maximum lag (Word16)
+ lag_min = minimum lag (Word16)
+ cor_max = pointer to the normalized correlation of selected lag (Word16)
+ rmax = pointer to max(<s[i]*s[j]>), (Word32)
+ r0 = pointer to the residual energy (Word32)
+ dtx = dtx flag; equal to 1, if dtx is enabled, 0, otherwise (Flag)
+ pOverflow = Pointer to overflow (Flag)
+
+ Outputs:
+ cor_max contains the newly calculated normalized correlation of the
+ selected lag
+ rmax contains the newly calculated max(<s[i]*s[j]>)
+ r0 contains the newly calculated residual energy
+ pOverflow -> 1 if the math functions called by this routine saturate.
+
+ Returns:
+ p_max = lag of the max correlation found (Word16)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function finds the lag that has maximum correlation of scal_sig[] in a
+ given delay range.
+ The correlation is given by
+ cor[t] = <scal_sig[n],scal_sig[n-t]>, t=lag_min,...,lag_max
+ The functions outputs the maximum correlation after normalization and the
+ corresponding lag.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ p_ol_wgh.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+static Word16 Lag_max ( // o : lag found
+ vadState *vadSt, // i/o : VAD state struct
+ Word32 corr[], // i : correlation vector.
+ Word16 scal_sig[], // i : scaled signal.
+ Word16 L_frame, // i : length of frame to compute pitch
+ Word16 lag_max, // i : maximum lag
+ Word16 lag_min, // i : minimum lag
+ Word16 old_lag, // i : old open-loop lag
+ Word16 *cor_max, // o : normalized correlation of selected lag
+ Word16 wght_flg, // i : is weighting function used
+ Word16 *gain_flg, // o : open-loop flag
+ Flag dtx // i : dtx flag; use dtx=1, do not use dtx=0
+ )
+{
+ Word16 i, j;
+ Word16 *p, *p1;
+ Word32 max, t0;
+ Word16 t0_h, t0_l;
+ Word16 p_max;
+ const Word16 *ww, *we;
+ Word32 t1;
+
+ ww = &corrweight[250];
+ we = &corrweight[123 + lag_max - old_lag];
+
+ max = MIN_32;
+ p_max = lag_max;
+
+ for (i = lag_max; i >= lag_min; i--)
+ {
+ t0 = corr[-i];
+
+ // Weighting of the correlation function.
+ L_Extract (corr[-i], &t0_h, &t0_l);
+ t0 = Mpy_32_16 (t0_h, t0_l, *ww);
+ ww--;
+ if (wght_flg > 0) {
+ // Weight the neighbourhood of the old lag
+ L_Extract (t0, &t0_h, &t0_l);
+ t0 = Mpy_32_16 (t0_h, t0_l, *we);
+ we--;
+ }
+
+ if (L_sub (t0, max) >= 0)
+ {
+ max = t0;
+ p_max = i;
+ }
+ }
+
+ p = &scal_sig[0];
+ p1 = &scal_sig[-p_max];
+ t0 = 0;
+ t1 = 0;
+
+ for (j = 0; j < L_frame; j++, p++, p1++)
+ {
+ t0 = L_mac (t0, *p, *p1);
+ t1 = L_mac (t1, *p1, *p1);
+ }
+
+ if (dtx)
+ { // no test() call since this if is only in simulation env
+#ifdef VAD2
+ vadSt->L_Rmax = L_add(vadSt->L_Rmax, t0); // Save max correlation
+ vadSt->L_R0 = L_add(vadSt->L_R0, t1); // Save max energy
+#else
+ // update and detect tone
+ vad_tone_detection_update (vadSt, 0);
+ vad_tone_detection (vadSt, t0, t1);
+#endif
+ }
+
+ // gain flag is set according to the open_loop gain
+ // is t2/t1 > 0.4 ?
+ *gain_flg = pv_round(L_msu(t0, pv_round(t1), 13107));
+
+ *cor_max = 0;
+
+ return (p_max);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static Word16 Lag_max( /* o : lag found */
+ vadState *vadSt, /* i/o : VAD state struct */
+ Word32 corr[], /* i : correlation vector. */
+ Word16 scal_sig[], /* i : scaled signal. */
+ Word16 L_frame, /* i : length of frame to compute pitch */
+ Word16 lag_max, /* i : maximum lag */
+ Word16 lag_min, /* i : minimum lag */
+ Word16 old_lag, /* i : old open-loop lag */
+ Word16 *cor_max, /* o : normalized correlation of selected lag */
+ Word16 wght_flg, /* i : is weighting function used */
+ Word16 *gain_flg, /* o : open-loop flag */
+ Flag dtx, /* i : dtx flag; use dtx=1, do not use dtx=0 */
+ Flag *pOverflow /* o : overflow flag */
+)
+{
+ Word16 i;
+ Word16 j;
+ Word16 *p;
+ Word16 *p1;
+ Word32 max;
+ Word32 t0;
+ Word16 t0_h;
+ Word16 t0_l;
+ Word16 p_max;
+ const Word16 *ww;
+ const Word16 *we;
+ Word32 t1;
+ Word16 temp;
+
+ ww = &corrweight[250];
+ we = &corrweight[123 + lag_max - old_lag];
+
+ max = MIN_32;
+ p_max = lag_max;
+
+ for (i = lag_max; i >= lag_min; i--)
+ {
+ t0 = corr[-i];
+
+ /* Weighting of the correlation function. */
+ L_Extract(corr[-i], &t0_h, &t0_l, pOverflow);
+ t0 = Mpy_32_16(t0_h, t0_l, *ww, pOverflow);
+ ww--;
+ if (wght_flg > 0)
+ {
+ /* Weight the neighbourhood of the old lag. */
+ L_Extract(t0, &t0_h, &t0_l, pOverflow);
+ t0 = Mpy_32_16(t0_h, t0_l, *we, pOverflow);
+ we--;
+ }
+
+ /* if (L_sub (t0, max) >= 0) */
+ if (t0 >= max)
+ {
+ max = t0;
+ p_max = i;
+ }
+ }
+ p = &scal_sig[0];
+ p1 = &scal_sig[-p_max];
+ t0 = 0;
+ t1 = 0;
+
+ for (j = 0; j < L_frame; j++, p++, p1++)
+ {
+ t0 = L_mac(t0, *p, *p1, pOverflow);
+ t1 = L_mac(t1, *p1, *p1, pOverflow);
+ }
+
+ if (dtx)
+ { /* no test() call since this if is only in simulation env */
+#ifdef VAD2
+ /* Save max correlation */
+ vadSt->L_Rmax = L_add(vadSt->L_Rmax, t0, pOverflow);
+ /* Save max energy */
+ vadSt->L_R0 = L_add(vadSt->L_R0, t1, pOverflow);
+#else
+ /* update and detect tone */
+ vad_tone_detection_update(vadSt, 0, pOverflow);
+ vad_tone_detection(vadSt, t0, t1, pOverflow);
+#endif
+ }
+
+ /* gain flag is set according to the open_loop gain */
+ /* is t2/t1 > 0.4 ? */
+ temp = pv_round(t1, pOverflow);
+ t1 = L_msu(t0, temp, 13107, pOverflow);
+ *gain_flg = pv_round(t1, pOverflow);
+
+ *cor_max = 0;
+
+ return (p_max);
+}
+/*----------------------------------------------------------------------------
+; End Function: Lag_max
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Pitch_ol_wgh
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to pitchOLWghtState structure
+ vadSt = pointer to a vadState structure
+ signal = pointer to buffer of signal used to compute the open loop
+ pitch where signal[-pit_max] to signal[-1] should be known
+ pit_min = 16 bit value specifies the minimum pitch lag
+ pit_max = 16 bit value specifies the maximum pitch lag
+ L_frame = 16 bit value specifies the length of frame to compute pitch
+ old_lags = pointer to history with old stored Cl lags (Word16)
+ ol_gain_flg = pointer to OL gain flag (Word16)
+ idx = 16 bit value specifies the frame index
+ dtx = Data of type 'Flag' used for dtx. Use dtx=1, do not use dtx=0
+ pOverflow = pointer to Overflow indicator (Flag)
+ Outputs
+ st = The pitchOLWghtState may be modified
+ vadSt = The vadSt state structure may be modified.
+ pOverflow -> 1 if the math functions invoked by this routine saturate.
+
+ Returns:
+ p_max1 = 16 bit value representing the open loop pitch lag.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs an open-loop pitch search with weighting
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pitch_ol.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 Pitch_ol_wgh ( // o : open loop pitch lag
+ pitchOLWghtState *st, // i/o : State struct
+ vadState *vadSt, // i/o : VAD state struct/
+ Word16 signal[], // i : signal used to compute the open loop pitch
+ // signal[-pit_max] to signal[-1] should be known
+ Word16 pit_min, // i : minimum pitch lag
+ Word16 pit_max, // i : maximum pitch lag
+ Word16 L_frame, // i : length of frame to compute pitch
+ Word16 old_lags[], // i : history with old stored Cl lags
+ Word16 ol_gain_flg[], // i : OL gain flag
+ Word16 idx, // i : index
+ Flag dtx // i : dtx flag; use dtx=1, do not use dtx=0
+ )
+{
+ Word16 i;
+ Word16 max1;
+ Word16 p_max1;
+ Word32 t0;
+#ifndef VAD2
+ Word16 corr_hp_max;
+#endif
+ Word32 corr[PIT_MAX+1], *corr_ptr;
+
+ // Scaled signal
+ Word16 scaled_signal[PIT_MAX + L_FRAME];
+ Word16 *scal_sig;
+
+ scal_sig = &scaled_signal[pit_max];
+
+ t0 = 0L;
+ for (i = -pit_max; i < L_frame; i++)
+ {
+ t0 = L_mac (t0, signal[i], signal[i]);
+ }
+ //
+ // Scaling of input signal
+ //
+ // if Overflow -> scal_sig[i] = signal[i]>>2
+ // else if t0 < 1^22 -> scal_sig[i] = signal[i]<<2
+ // else -> scal_sig[i] = signal[i]
+
+ //
+ // Verification for risk of overflow.
+ //
+
+ // Test for overflow
+ if (L_sub (t0, MAX_32) == 0L)
+ {
+ for (i = -pit_max; i < L_frame; i++)
+ {
+ scal_sig[i] = shr (signal[i], 3);
+ }
+ }
+ else if (L_sub (t0, (Word32) 1048576L) < (Word32) 0)
+ {
+ for (i = -pit_max; i < L_frame; i++)
+ {
+ scal_sig[i] = shl (signal[i], 3);
+ }
+ }
+ else
+ {
+ for (i = -pit_max; i < L_frame; i++)
+ {
+ scal_sig[i] = signal[i];
+ }
+ }
+
+ // calculate all coreelations of scal_sig, from pit_min to pit_max
+ corr_ptr = &corr[pit_max];
+ comp_corr (scal_sig, L_frame, pit_max, pit_min, corr_ptr);
+
+ p_max1 = Lag_max (vadSt, corr_ptr, scal_sig, L_frame, pit_max, pit_min,
+ st->old_T0_med, &max1, st->wght_flg, &ol_gain_flg[idx],
+ dtx);
+
+ if (ol_gain_flg[idx] > 0)
+ {
+ // Calculate 5-point median of previous lag
+ for (i = 4; i > 0; i--) // Shift buffer
+ {
+ old_lags[i] = old_lags[i-1];
+ }
+ old_lags[0] = p_max1;
+ st->old_T0_med = gmed_n (old_lags, 5);
+ st->ada_w = 32767; // Q15 = 1.0
+ }
+ else
+ {
+ st->old_T0_med = p_max1;
+ st->ada_w = mult(st->ada_w, 29491); // = ada_w = ada_w * 0.9
+ }
+
+ if (sub(st->ada_w, 9830) < 0) // ada_w - 0.3
+ {
+ st->wght_flg = 0;
+ }
+ else
+ {
+ st->wght_flg = 1;
+ }
+
+#ifndef VAD2
+ if (dtx)
+ { // no test() call since this if is only in simulation env
+ if (sub(idx, 1) == 0)
+ {
+ // calculate max high-passed filtered correlation of all lags
+ hp_max (corr_ptr, scal_sig, L_frame, pit_max, pit_min, &corr_hp_max);
+
+ // update complex background detector
+ vad_complex_detection_update(vadSt, corr_hp_max);
+ }
+ }
+#endif
+
+ return (p_max1);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Pitch_ol_wgh( /* o : open loop pitch lag */
+ pitchOLWghtState *st, /* i/o : State struct */
+ vadState *vadSt, /* i/o : VAD state struct */
+ Word16 signal[], /* i : signal used to compute the open loop pitch */
+ /* signal[-pit_max] to signal[-1] should be known */
+ Word16 pit_min, /* i : minimum pitch lag */
+ Word16 pit_max, /* i : maximum pitch lag */
+ Word16 L_frame, /* i : length of frame to compute pitch */
+ Word16 old_lags[], /* i : history with old stored Cl lags */
+ Word16 ol_gain_flg[], /* i : OL gain flag */
+ Word16 idx, /* i : index */
+ Flag dtx, /* i : dtx flag; use dtx=1, do not use dtx=0 */
+ Flag *pOverflow /* o : overflow flag */
+)
+{
+ Word16 i;
+ Word16 max1;
+ Word16 p_max1;
+ Word32 t0;
+#ifndef VAD2
+ Word16 corr_hp_max;
+#endif
+ Word32 corr[PIT_MAX+1], *corr_ptr;
+
+ /* Scaled signal */
+ Word16 scaled_signal[PIT_MAX + L_FRAME];
+ Word16 *scal_sig;
+
+ scal_sig = &scaled_signal[pit_max];
+
+ t0 = 0L;
+ for (i = -pit_max; i < L_frame; i++)
+ {
+ t0 = L_mac(t0, signal[i], signal[i], pOverflow);
+ }
+ /*--------------------------------------------------------*
+ * Scaling of input signal. *
+ * *
+ * if Overflow -> scal_sig[i] = signal[i]>>2 *
+ * else if t0 < 1^22 -> scal_sig[i] = signal[i]<<2 *
+ * else -> scal_sig[i] = signal[i] *
+ *--------------------------------------------------------*/
+
+ /*--------------------------------------------------------*
+ * Verification for risk of overflow. *
+ *--------------------------------------------------------*/
+
+ /* Test for overflow */
+ if (L_sub(t0, MAX_32, pOverflow) == 0L)
+ {
+ for (i = -pit_max; i < L_frame; i++)
+ {
+ scal_sig[i] = shr(signal[i], 3, pOverflow);
+ }
+ }
+ else if (L_sub(t0, (Word32) 1048576L, pOverflow) < (Word32) 0)
+ {
+ for (i = -pit_max; i < L_frame; i++)
+ {
+ scal_sig[i] = shl(signal[i], 3, pOverflow);
+ }
+ }
+ else
+ {
+ for (i = -pit_max; i < L_frame; i++)
+ {
+ scal_sig[i] = signal[i];
+ }
+ }
+
+ /* calculate all coreelations of scal_sig, from pit_min to pit_max */
+ corr_ptr = &corr[pit_max];
+ comp_corr(scal_sig, L_frame, pit_max, pit_min, corr_ptr);
+
+ p_max1 = Lag_max(vadSt, corr_ptr, scal_sig, L_frame, pit_max, pit_min,
+ st->old_T0_med, &max1, st->wght_flg, &ol_gain_flg[idx],
+ dtx, pOverflow);
+
+ if (ol_gain_flg[idx] > 0)
+ {
+ /* Calculate 5-point median of previous lags */
+ for (i = 4; i > 0; i--) /* Shift buffer */
+ {
+ old_lags[i] = old_lags[i-1];
+ }
+ old_lags[0] = p_max1;
+ st->old_T0_med = gmed_n(old_lags, 5);
+ st->ada_w = 32767; /* Q15 = 1.0 */
+ }
+ else
+ {
+ st->old_T0_med = p_max1;
+ /* = ada_w = ada_w * 0.9 */
+ st->ada_w = mult(st->ada_w, 29491, pOverflow);
+ }
+
+ if (sub(st->ada_w, 9830, pOverflow) < 0) /* ada_w - 0.3 */
+ {
+ st->wght_flg = 0;
+ }
+ else
+ {
+ st->wght_flg = 1;
+ }
+
+#ifndef VAD2
+ if (dtx)
+ { /* no test() call since this if is only in simulation env */
+ if (sub(idx, 1, pOverflow) == 0)
+ {
+ /* calculate max high-passed filtered correlation of all lags */
+ hp_max(corr_ptr, scal_sig, L_frame, pit_max, pit_min, &corr_hp_max, pOverflow);
+
+ /* update complex background detector */
+ vad_complex_detection_update(vadSt, corr_hp_max);
+ }
+ }
+#endif
+
+ return (p_max1);
+}
+
+/*----------------------------------------------------------------------------
+; End Function: Pitch_ol_wgh
+----------------------------------------------------------------------------*/
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp b/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp
new file mode 100644
index 0000000..5a846fa
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.cpp
@@ -0,0 +1,1609 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/pitch_fr.c
+ Functions:
+
+
+ Date: 02/04/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added pOverflow as a passed in value to searchFrac and made
+ other fixes to the code regarding simple syntax fixes. Removed
+ the include of stio.h.
+
+ Description: *lag-- decrements the pointer. (*lag)-- decrements what is
+ pointed to. The latter is what the coder intended, but the former is
+ the coding instruction that was used.
+
+ Description: A common problem -- a comparison != 0 was inadvertantly replaced
+ by a comparison == 0.
+
+
+ Description: For Norm_Corr() and getRange()
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated math operations that unnecessary checked for
+ saturation, in some cases this by shifting before adding and
+ in other cases by evaluating the operands
+ 4. Unrolled loops to speed up processing, use decrement loops
+ 5. Replaced extract_l() call with equivalent code
+ 6. Modified scaling threshold and group all shifts (avoiding
+ successive shifts)
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Removed compiler warnings.
+
+ Description:
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ File : pitch_fr.c
+ Purpose : Find the pitch period with 1/3 or 1/6 subsample
+ : resolution (closed loop).
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+
+#include "pitch_fr.h"
+#include "oper_32b.h"
+#include "cnst.h"
+#include "enc_lag3.h"
+#include "enc_lag6.h"
+#include "inter_36.h"
+#include "inv_sqrt.h"
+#include "convolve.h"
+
+#include "basic_op.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+ * mode dependent parameters used in Pitch_fr()
+ * Note: order of MRxx in 'enum Mode' is important!
+ */
+static const struct
+{
+ Word16 max_frac_lag; /* lag up to which fractional lags are used */
+ Word16 flag3; /* enable 1/3 instead of 1/6 fract. resolution */
+ Word16 first_frac; /* first fractional to check */
+ Word16 last_frac; /* last fractional to check */
+ Word16 delta_int_low; /* integer lag below TO to start search from */
+ Word16 delta_int_range; /* integer range around T0 */
+ Word16 delta_frc_low; /* fractional below T0 */
+ Word16 delta_frc_range; /* fractional range around T0 */
+ Word16 pit_min; /* minimum pitch */
+} mode_dep_parm[N_MODES] =
+{
+ /* MR475 */ { 84, 1, -2, 2, 5, 10, 5, 9, PIT_MIN },
+ /* MR515 */ { 84, 1, -2, 2, 5, 10, 5, 9, PIT_MIN },
+ /* MR59 */ { 84, 1, -2, 2, 3, 6, 5, 9, PIT_MIN },
+ /* MR67 */ { 84, 1, -2, 2, 3, 6, 5, 9, PIT_MIN },
+ /* MR74 */ { 84, 1, -2, 2, 3, 6, 5, 9, PIT_MIN },
+ /* MR795 */ { 84, 1, -2, 2, 3, 6, 10, 19, PIT_MIN },
+ /* MR102 */ { 84, 1, -2, 2, 3, 6, 5, 9, PIT_MIN },
+ /* MR122 */ { 94, 0, -3, 3, 3, 6, 5, 9, PIT_MIN_MR122 }
+};
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Norm_Corr
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ exc[] = pointer to buffer of type Word16
+ xn[] = pointer to buffer of type Word16
+ h[] = pointer to buffer of type Word16
+ L_subfr = length of sub frame (Word16)
+ t_min = the minimum table value of type Word16
+ t_max = the maximum table value of type Word16
+ corr_norm[] = pointer to buffer of type Word16
+
+ Outputs:
+ pOverflow = 1 if the math functions called result in overflow else zero.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ FUNCTION: Norm_Corr()
+
+ PURPOSE: Find the normalized correlation between the target vector
+ and the filtered past excitation.
+
+ DESCRIPTION:
+ The normalized correlation is given by the correlation between the
+ target and filtered past excitation divided by the square root of
+ the energy of filtered excitation.
+ corr[k] = <x[], y_k[]>/sqrt(y_k[],y_k[])
+ where x[] is the target vector and y_k[] is the filtered past
+ excitation at delay k.
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pitch_fr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+static void Norm_Corr (Word16 exc[], Word16 xn[], Word16 h[], Word16 L_subfr,
+ Word16 t_min, Word16 t_max, Word16 corr_norm[])
+{
+ Word16 i, j, k;
+ Word16 corr_h, corr_l, norm_h, norm_l;
+ Word32 s;
+
+ // Usally dynamic allocation of (L_subfr)
+ Word16 excf[L_SUBFR];
+ Word16 scaling, h_fac, *s_excf, scaled_excf[L_SUBFR];
+
+ k = -t_min;
+
+ // compute the filtered excitation for the first delay t_min
+
+ Convolve (&exc[k], h, excf, L_subfr);
+
+ // scale "excf[]" to avoid overflow
+
+ for (j = 0; j < L_subfr; j++) {
+ scaled_excf[j] = shr (excf[j], 2);
+ }
+
+ // Compute 1/sqrt(energy of excf[])
+
+ s = 0;
+ for (j = 0; j < L_subfr; j++) {
+ s = L_mac (s, excf[j], excf[j]);
+ }
+ if (L_sub (s, 67108864L) <= 0) { // if (s <= 2^26)
+ s_excf = excf;
+ h_fac = 15 - 12;
+ scaling = 0;
+ }
+ else {
+ // "excf[]" is divided by 2
+ s_excf = scaled_excf;
+ h_fac = 15 - 12 - 2;
+ scaling = 2;
+ }
+
+ // loop for every possible period
+
+ for (i = t_min; i <= t_max; i++) {
+ // Compute 1/sqrt(energy of excf[])
+
+ s = 0;
+ for (j = 0; j < L_subfr; j++) {
+ s = L_mac (s, s_excf[j], s_excf[j]);
+ }
+
+ s = Inv_sqrt (s);
+ L_Extract (s, &norm_h, &norm_l);
+
+ // Compute correlation between xn[] and excf[]
+
+ s = 0;
+ for (j = 0; j < L_subfr; j++) {
+ s = L_mac (s, xn[j], s_excf[j]);
+ }
+ L_Extract (s, &corr_h, &corr_l);
+
+ // Normalize correlation = correlation * (1/sqrt(energy))
+
+ s = Mpy_32 (corr_h, corr_l, norm_h, norm_l);
+
+ corr_norm[i] = extract_h (L_shl (s, 16));
+
+ // modify the filtered excitation excf[] for the next iteration
+
+ if (sub (i, t_max) != 0) {
+ k--;
+ for (j = L_subfr - 1; j > 0; j--) {
+ s = L_mult (exc[k], h[j]);
+ s = L_shl (s, h_fac);
+ s_excf[j] = add (extract_h (s), s_excf[j - 1]);
+ }
+ s_excf[0] = shr (exc[k], scaling);
+ }
+ }
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void Norm_Corr(Word16 exc[],
+ Word16 xn[],
+ Word16 h[],
+ Word16 L_subfr,
+ Word16 t_min,
+ Word16 t_max,
+ Word16 corr_norm[],
+ Flag *pOverflow)
+{
+ Word16 i;
+ Word16 j;
+ Word16 k;
+ Word16 corr_h;
+ Word16 corr_l;
+ Word16 norm_h;
+ Word16 norm_l;
+ Word32 s;
+ Word32 s2;
+ Word16 excf[L_SUBFR];
+ Word16 scaling;
+ Word16 h_fac;
+ Word16 *s_excf;
+ Word16 scaled_excf[L_SUBFR];
+ Word16 *p_s_excf;
+ Word16 *p_excf;
+ Word16 temp;
+ Word16 *p_x;
+ Word16 *p_h;
+
+ k = -t_min;
+
+ /* compute the filtered excitation for the first delay t_min */
+
+ Convolve(&exc[k], h, excf, L_subfr);
+
+ /* scale "excf[]" to avoid overflow */
+ s = 0;
+ p_s_excf = scaled_excf;
+ p_excf = excf;
+
+ for (j = (L_subfr >> 1); j != 0; j--)
+ {
+ temp = *(p_excf++);
+ *(p_s_excf++) = temp >> 2;
+ s += (Word32) temp * temp;
+ temp = *(p_excf++);
+ *(p_s_excf++) = temp >> 2;
+ s += (Word32) temp * temp;
+ }
+
+
+ if (s <= (67108864L >> 1))
+ {
+ s_excf = excf;
+ h_fac = 12;
+ scaling = 0;
+ }
+ else
+ {
+ /* "excf[]" is divided by 2 */
+ s_excf = scaled_excf;
+ h_fac = 14;
+ scaling = 2;
+ }
+
+ /* loop for every possible period */
+
+ for (i = t_min; i <= t_max; i++)
+ {
+ /* Compute 1/sqrt(energy of excf[]) */
+
+ s = s2 = 0;
+ p_x = xn;
+ p_s_excf = s_excf;
+ j = L_subfr >> 1;
+
+ while (j--)
+ {
+ s += (Word32) * (p_x++) * *(p_s_excf);
+ s2 += ((Word32)(*(p_s_excf)) * (*(p_s_excf)));
+ p_s_excf++;
+ s += (Word32) * (p_x++) * *(p_s_excf);
+ s2 += ((Word32)(*(p_s_excf)) * (*(p_s_excf)));
+ p_s_excf++;
+ }
+
+ s2 = s2 << 1;
+ s2 = Inv_sqrt(s2, pOverflow);
+ norm_h = (Word16)(s2 >> 16);
+ norm_l = (Word16)((s2 >> 1) - (norm_h << 15));
+ corr_h = (Word16)(s >> 15);
+ corr_l = (Word16)((s) - (corr_h << 15));
+
+ /* Normalize correlation = correlation * (1/sqrt(energy)) */
+
+ s = Mpy_32(corr_h, corr_l, norm_h, norm_l, pOverflow);
+
+ corr_norm[i] = (Word16) s ;
+
+ /* modify the filtered excitation excf[] for the next iteration */
+ if (i != t_max)
+ {
+ k--;
+ temp = exc[k];
+ p_s_excf = &s_excf[L_subfr - 1];
+ p_h = &h[L_subfr - 1];
+
+ p_excf = &s_excf[L_subfr - 2];
+ for (j = (L_subfr - 1) >> 1; j != 0; j--)
+ {
+ s = ((Word32) temp * *(p_h--)) >> h_fac;
+ *(p_s_excf--) = (Word16) s + *(p_excf--);
+ s = ((Word32) temp * *(p_h--)) >> h_fac;
+ *(p_s_excf--) = (Word16) s + *(p_excf--);
+ }
+
+ s = ((Word32) temp * *(p_h)) >> h_fac;
+ *(p_s_excf--) = (Word16) s + *(p_excf);
+
+ *(p_s_excf) = temp >> scaling;
+ }
+
+ }
+ return;
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: searchFrac
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ lag = pointer to integer pitch of type Word16
+ frac = pointer to starting point of search fractional pitch of type Word16
+ last_frac = endpoint of search of type Word16
+ corr[] = pointer to normalized correlation of type Word16
+ flag3 = subsample resolution (3: =1 / 6: =0) of type Word16
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ FUNCTION: searchFrac()
+
+ PURPOSE: Find fractional pitch
+
+ DESCRIPTION:
+ The function interpolates the normalized correlation at the
+ fractional positions around lag T0. The position at which the
+ interpolation function reaches its maximum is the fractional pitch.
+ Starting point of the search is frac, end point is last_frac.
+ frac is overwritten with the fractional pitch.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pitch_fr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+static void searchFrac (
+ Word16 *lag, // i/o : integer pitch
+ Word16 *frac, // i/o : start point of search -
+ fractional pitch
+ Word16 last_frac, // i : endpoint of search
+ Word16 corr[], // i : normalized correlation
+ Word16 flag3 // i : subsample resolution
+ (3: =1 / 6: =0)
+)
+{
+ Word16 i;
+ Word16 max;
+ Word16 corr_int;
+
+ // Test the fractions around T0 and choose the one which maximizes
+ // the interpolated normalized correlation.
+
+ max = Interpol_3or6 (&corr[*lag], *frac, flag3); // function result
+
+ for (i = add (*frac, 1); i <= last_frac; i++) {
+ corr_int = Interpol_3or6 (&corr[*lag], i, flag3);
+ if (sub (corr_int, max) > 0) {
+ max = corr_int;
+ *frac = i;
+ }
+ }
+
+ if (flag3 == 0) {
+ // Limit the fraction value in the interval [-2,-1,0,1,2,3]
+
+ if (sub (*frac, -3) == 0) {
+ *frac = 3;
+ *lag = sub (*lag, 1);
+ }
+ }
+ else {
+ // limit the fraction value between -1 and 1
+
+ if (sub (*frac, -2) == 0) {
+ *frac = 1;
+ *lag = sub (*lag, 1);
+ }
+ if (sub (*frac, 2) == 0) {
+ *frac = -1;
+ *lag = add (*lag, 1);
+ }
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void searchFrac(
+ Word16 *lag, /* i/o : integer pitch */
+ Word16 *frac, /* i/o : start point of search -
+ fractional pitch */
+ Word16 last_frac, /* i : endpoint of search */
+ Word16 corr[], /* i : normalized correlation */
+ Word16 flag3, /* i : subsample resolution
+ (3: =1 / 6: =0) */
+ Flag *pOverflow
+)
+{
+ Word16 i;
+ Word16 max;
+ Word16 corr_int;
+
+ /* Test the fractions around T0 and choose the one which maximizes */
+ /* the interpolated normalized correlation. */
+
+ max = Interpol_3or6(&corr[*lag], *frac, flag3, pOverflow);
+ /* function result */
+
+ for (i = *frac + 1; i <= last_frac; i++)
+ {
+ corr_int = Interpol_3or6(&corr[*lag], i, flag3, pOverflow);
+ if (corr_int > max)
+ {
+ max = corr_int;
+ *frac = i;
+ }
+ }
+
+ if (flag3 == 0)
+ {
+ /* Limit the fraction value in the interval [-2,-1,0,1,2,3] */
+
+ if (*frac == -3)
+ {
+ *frac = 3;
+ (*lag)--;
+ }
+ }
+ else
+ {
+ /* limit the fraction value between -1 and 1 */
+
+ if (*frac == -2)
+ {
+ *frac = 1;
+ (*lag)--;
+ }
+ if (*frac == 2)
+ {
+ *frac = -1;
+ (*lag)++;
+ }
+ }
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: getRange
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ T0 = integer pitch of type Word16
+ delta_low = search start offset of type Word16
+ delta_range = search range of type Word16
+ pitmin = minimum pitch of type Word16
+ pitmax = maximum pitch of type Word16
+ t0_min = search range minimum of type Word16
+ t0_max = search range maximum of type Word16
+
+ Outputs:
+ pOverflow = 1 if the math functions called result in overflow else zero.
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ FUNCTION: getRange()
+
+ PURPOSE: Sets range around open-loop pitch or integer pitch of last subframe
+
+ DESCRIPTION:
+ Takes integer pitch T0 and calculates a range around it with
+ t0_min = T0-delta_low and t0_max = (T0-delta_low) + delta_range
+ t0_min and t0_max are bounded by pitmin and pitmax
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pitch_fr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+static void getRange (
+ Word16 T0, // i : integer pitch
+ Word16 delta_low, // i : search start offset
+ Word16 delta_range, // i : search range
+ Word16 pitmin, // i : minimum pitch
+ Word16 pitmax, // i : maximum pitch
+ Word16 *t0_min, // o : search range minimum
+ Word16 *t0_max) // o : search range maximum
+{
+ *t0_min = sub(T0, delta_low);
+ if (sub(*t0_min, pitmin) < 0) {
+ *t0_min = pitmin;
+ }
+ *t0_max = add(*t0_min, delta_range);
+ if (sub(*t0_max, pitmax) > 0) {
+ *t0_max = pitmax;
+ *t0_min = sub(*t0_max, delta_range);
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+static void getRange(
+ Word16 T0, /* i : integer pitch */
+ Word16 delta_low, /* i : search start offset */
+ Word16 delta_range, /* i : search range */
+ Word16 pitmin, /* i : minimum pitch */
+ Word16 pitmax, /* i : maximum pitch */
+ Word16 *t0_min, /* o : search range minimum */
+ Word16 *t0_max, /* o : search range maximum */
+ Flag *pOverflow)
+{
+
+ Word16 temp;
+ OSCL_UNUSED_ARG(pOverflow);
+
+ temp = *t0_min;
+ temp = T0 - delta_low;
+ if (temp < pitmin)
+ {
+ temp = pitmin;
+ }
+ *t0_min = temp;
+
+ temp += delta_range;
+ if (temp > pitmax)
+ {
+ temp = pitmax;
+ *t0_min = pitmax - delta_range;
+ }
+ *t0_max = temp;
+
+}
+
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Pitch_fr_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a pointer of structure type Pitch_fr_State.
+
+ Outputs:
+ None
+
+ Returns:
+ Returns a zero if successful and -1 if not successful.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function: Pitch_fr_init
+ Purpose: Allocates state memory and initializes state memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pitch_fr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Pitch_fr_init (Pitch_frState **state)
+{
+ Pitch_frState* s;
+
+ if (state == (Pitch_frState **) NULL){
+ // fprintf(stderr, "Pitch_fr_init: invalid parameter\n");
+ return -1;
+ }
+ *state = NULL;
+
+ // allocate memory
+ if ((s= (Pitch_frState *) malloc(sizeof(Pitch_frState))) == NULL){
+ // fprintf(stderr, "Pitch_fr_init: can not malloc state structure\n");
+ return -1;
+ }
+
+ Pitch_fr_reset(s);
+ *state = s;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 Pitch_fr_init(Pitch_frState **state)
+{
+ Pitch_frState* s;
+
+ if (state == (Pitch_frState **) NULL)
+ {
+ /* fprintf(stderr, "Pitch_fr_init: invalid parameter\n"); */
+ return -1;
+ }
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (Pitch_frState *) malloc(sizeof(Pitch_frState))) == NULL)
+ {
+ /* fprintf(stderr, "Pitch_fr_init: can not malloc state structure\n"); */
+ return -1;
+ }
+
+ Pitch_fr_reset(s);
+ *state = s;
+
+ return 0;
+}
+
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Pitch_fr_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a pointer of structure type Pitch_fr_State.
+
+ Outputs:
+ None
+
+ Returns:
+ Returns a zero if successful and -1 if not successful.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function: Pitch_fr_reset
+ Purpose: Initializes state memory to zero
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pitch_fr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Pitch_fr_reset (Pitch_frState *state)
+{
+
+ if (state == (Pitch_frState *) NULL){
+ // fprintf(stderr, "Pitch_fr_reset: invalid parameter\n");
+ return -1;
+ }
+
+ state->T0_prev_subframe = 0;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 Pitch_fr_reset(Pitch_frState *state)
+{
+
+ if (state == (Pitch_frState *) NULL)
+ {
+ /* fprintf(stderr, "Pitch_fr_reset: invalid parameter\n"); */
+ return -1;
+ }
+
+ state->T0_prev_subframe = 0;
+
+ return 0;
+}
+
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Pitch_fr_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a pointer of structure type Pitch_fr_State.
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function: Pitch_fr_exit
+ Purpose: The memory for state is freed.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pitch_fr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Pitch_fr_exit (Pitch_frState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ // deallocate memory
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void Pitch_fr_exit(Pitch_frState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ /* deallocate memory */
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Pitch_fr
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to stat structure of type Pitch_frState
+ mode = codec mode of type enum Mode
+ T_op[] = pointer to open loop pitch lags of type Word16
+ exc[] = pointer to excitation buffer of type Word16
+ xn[] = pointer to target vector of type Word16
+ h[] = pointer to impulse response of synthesis and weighting filters
+ of type Word16
+ L_subfr = length of subframe of type Word16
+ i_subfr = subframe offset of type Word16
+
+ Outputs:
+ pit_frac = pointer to pitch period (fractional) of type Word16
+ resu3 = pointer to subsample resolution of type Word16
+ ana_index = pointer to index of encoding of type Word16
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ FUNCTION: Pitch_fr()
+
+ PURPOSE: Find the pitch period with 1/3 or 1/6 subsample resolution
+ (closed loop).
+
+ DESCRIPTION:
+ - find the normalized correlation between the target and filtered
+ past excitation in the search range.
+ - select the delay with maximum normalized correlation.
+ - interpolate the normalized correlation at fractions -3/6 to 3/6
+ with step 1/6 around the chosen delay.
+ - The fraction which gives the maximum interpolated value is chosen.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pitch_fr.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 Pitch_fr ( // o : pitch period (integer)
+ Pitch_frState *st, // i/o : State struct
+ enum Mode mode, // i : codec mode
+ Word16 T_op[], // i : open loop pitch lags
+ Word16 exc[], // i : excitation buffer Q0
+ Word16 xn[], // i : target vector Q0
+ Word16 h[], // i : impulse response of synthesis and
+ weighting filters Q12
+ Word16 L_subfr, // i : Length of subframe
+ Word16 i_subfr, // i : subframe offset
+ Word16 *pit_frac, // o : pitch period (fractional)
+ Word16 *resu3, // o : subsample resolution 1/3 (=1) or 1/6 (=0)
+ Word16 *ana_index // o : index of encoding
+)
+{
+ Word16 i;
+ Word16 t_min, t_max;
+ Word16 t0_min, t0_max;
+ Word16 max, lag, frac;
+ Word16 tmp_lag;
+ Word16 *corr;
+ Word16 corr_v[40]; // Total length = t0_max-t0_min+1+2*L_INTER_SRCH
+
+ Word16 max_frac_lag;
+ Word16 flag3, flag4;
+ Word16 last_frac;
+ Word16 delta_int_low, delta_int_range;
+ Word16 delta_frc_low, delta_frc_range;
+ Word16 pit_min;
+ Word16 frame_offset;
+ Word16 delta_search;
+
+ //-----------------------------------------------------------------------
+ // set mode specific variables
+ //----------------------------------------------------------------------
+
+ max_frac_lag = mode_dep_parm[mode].max_frac_lag;
+ flag3 = mode_dep_parm[mode].flag3;
+ frac = mode_dep_parm[mode].first_frac;
+ last_frac = mode_dep_parm[mode].last_frac;
+ delta_int_low = mode_dep_parm[mode].delta_int_low;
+ delta_int_range = mode_dep_parm[mode].delta_int_range;
+
+ delta_frc_low = mode_dep_parm[mode].delta_frc_low;
+ delta_frc_range = mode_dep_parm[mode].delta_frc_range;
+ pit_min = mode_dep_parm[mode].pit_min;
+
+ //-----------------------------------------------------------------------
+ // decide upon full or differential search
+ //-----------------------------------------------------------------------
+
+ delta_search = 1;
+
+ if ((i_subfr == 0) || (sub(i_subfr,L_FRAME_BY2) == 0)) {
+
+ // Subframe 1 and 3
+
+ if (((sub((Word16)mode, (Word16)MR475) != 0) && (sub((Word16)mode,
+ (Word16)MR515) != 0)) ||
+ (sub(i_subfr,L_FRAME_BY2) != 0)) {
+
+ // set t0_min, t0_max for full search
+ // this is *not* done for mode MR475, MR515 in subframe 3
+
+ delta_search = 0; // no differential search
+
+ // calculate index into T_op which contains the open-loop
+ // pitch estimations for the 2 big subframes
+
+ frame_offset = 1;
+ if (i_subfr == 0)
+ frame_offset = 0;
+
+ // get T_op from the corresponding half frame and
+ // set t0_min, t0_max
+
+ getRange (T_op[frame_offset], delta_int_low, delta_int_range,
+ pit_min, PIT_MAX, &t0_min, &t0_max);
+ }
+ else {
+
+ // mode MR475, MR515 and 3. Subframe: delta search as well
+ getRange (st->T0_prev_subframe, delta_frc_low, delta_frc_range,
+ pit_min, PIT_MAX, &t0_min, &t0_max);
+ }
+ }
+ else {
+
+ // for Subframe 2 and 4
+ // get range around T0 of previous subframe for delta search
+
+ getRange (st->T0_prev_subframe, delta_frc_low, delta_frc_range,
+ pit_min, PIT_MAX, &t0_min, &t0_max);
+ }
+
+ //-----------------------------------------------------------------------
+ Find interval to compute normalized correlation
+ -----------------------------------------------------------------------
+
+ t_min = sub (t0_min, L_INTER_SRCH);
+ t_max = add (t0_max, L_INTER_SRCH);
+
+ corr = &corr_v[-t_min];
+
+ //-----------------------------------------------------------------------
+ Compute normalized correlation between target and filtered excitation
+ -----------------------------------------------------------------------
+
+ Norm_Corr (exc, xn, h, L_subfr, t_min, t_max, corr);
+
+ //-----------------------------------------------------------------------
+ Find integer pitch
+ -----------------------------------------------------------------------
+
+ max = corr[t0_min];
+ lag = t0_min;
+
+ for (i = t0_min + 1; i <= t0_max; i++) {
+ if (sub (corr[i], max) >= 0) {
+ max = corr[i];
+ lag = i;
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ Find fractional pitch
+ -----------------------------------------------------------------------
+ if ((delta_search == 0) && (sub (lag, max_frac_lag) > 0)) {
+
+ // full search and integer pitch greater than max_frac_lag
+ // fractional search is not needed, set fractional to zero
+
+ frac = 0;
+ }
+ else {
+
+ // if differential search AND mode MR475 OR MR515 OR MR59 OR MR67
+ // then search fractional with 4 bits resolution
+
+ if ((delta_search != 0) &&
+ ((sub ((Word16)mode, (Word16)MR475) == 0) ||
+ (sub ((Word16)mode, (Word16)MR515) == 0) ||
+ (sub ((Word16)mode, (Word16)MR59) == 0) ||
+ (sub ((Word16)mode, (Word16)MR67) == 0))) {
+
+ // modify frac or last_frac according to position of last
+ // integer pitch: either search around integer pitch,
+ // or only on left or right side
+
+ tmp_lag = st->T0_prev_subframe;
+ if ( sub( sub(tmp_lag, t0_min), 5) > 0)
+ tmp_lag = add (t0_min, 5);
+ if ( sub( sub(t0_max, tmp_lag), 4) > 0)
+ tmp_lag = sub (t0_max, 4);
+
+ if ((sub (lag, tmp_lag) == 0) ||
+ (sub (lag, sub(tmp_lag, 1)) == 0)) {
+
+ // normal search in fractions around T0
+
+ searchFrac (&lag, &frac, last_frac, corr, flag3);
+
+ }
+ else if (sub (lag, sub (tmp_lag, 2)) == 0) {
+ // limit search around T0 to the right side
+ frac = 0;
+ searchFrac (&lag, &frac, last_frac, corr, flag3);
+ }
+ else if (sub (lag, add(tmp_lag, 1)) == 0) {
+ // limit search around T0 to the left side
+ last_frac = 0;
+ searchFrac (&lag, &frac, last_frac, corr, flag3);
+ }
+ else {
+ // no fractional search
+ frac = 0;
+ }
+ }
+ else
+ // test the fractions around T0
+ searchFrac (&lag, &frac, last_frac, corr, flag3);
+ }
+
+ //-----------------------------------------------------------------------
+ // encode pitch
+ //-----------------------------------------------------------------------
+
+ if (flag3 != 0) {
+ // flag4 indicates encoding with 4 bit resolution;
+ // this is needed for mode MR475, MR515 and MR59
+
+ flag4 = 0;
+ if ( (sub ((Word16)mode, (Word16)MR475) == 0) ||
+ (sub ((Word16)mode, (Word16)MR515) == 0) ||
+ (sub ((Word16)mode, (Word16)MR59) == 0) ||
+ (sub ((Word16)mode, (Word16)MR67) == 0) ) {
+ flag4 = 1;
+ }
+
+ // encode with 1/3 subsample resolution
+
+ *ana_index = Enc_lag3(lag, frac, st->T0_prev_subframe,
+ t0_min, t0_max, delta_search, flag4);
+ // function result
+
+ }
+ else
+ {
+ // encode with 1/6 subsample resolution
+
+ *ana_index = Enc_lag6(lag, frac, t0_min, delta_search);
+ // function result
+ }
+
+ //-----------------------------------------------------------------------
+ // update state variables
+ //-----------------------------------------------------------------------
+
+ st->T0_prev_subframe = lag;
+
+ //-----------------------------------------------------------------------
+ // update output variables
+ //-----------------------------------------------------------------------
+
+ *resu3 = flag3;
+
+ *pit_frac = frac;
+
+ return (lag);
+}
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 Pitch_fr( /* o : pitch period (integer) */
+ Pitch_frState *st, /* i/o : State struct */
+ enum Mode mode, /* i : codec mode */
+ Word16 T_op[], /* i : open loop pitch lags */
+ Word16 exc[], /* i : excitation buffer Q0 */
+ Word16 xn[], /* i : target vector Q0 */
+ Word16 h[], /* i : impulse response of synthesis and
+ weighting filters Q12 */
+ Word16 L_subfr, /* i : Length of subframe */
+ Word16 i_subfr, /* i : subframe offset */
+ Word16 *pit_frac, /* o : pitch period (fractional) */
+ Word16 *resu3, /* o : subsample resolution 1/3 (=1) or 1/6 (=0) */
+ Word16 *ana_index, /* o : index of encoding */
+ Flag *pOverflow
+)
+{
+ Word16 i;
+ Word16 t_min;
+ Word16 t_max;
+ Word16 t0_min = 0;
+ Word16 t0_max;
+ Word16 max;
+ Word16 lag;
+ Word16 frac;
+ Word16 tmp_lag;
+ Word16 *corr;
+ Word16 corr_v[40]; /* Total length = t0_max-t0_min+1+2*L_INTER_SRCH */
+
+ Word16 max_frac_lag;
+ Word16 flag3;
+ Word16 flag4;
+ Word16 last_frac;
+ Word16 delta_int_low;
+ Word16 delta_int_range;
+ Word16 delta_frc_low;
+ Word16 delta_frc_range;
+ Word16 pit_min;
+ Word16 frame_offset;
+ Word16 delta_search;
+
+ /*-----------------------------------------------------------------------*
+ * set mode specific variables *
+ *-----------------------------------------------------------------------*/
+
+ max_frac_lag = mode_dep_parm[mode].max_frac_lag;
+ flag3 = mode_dep_parm[mode].flag3;
+ frac = mode_dep_parm[mode].first_frac;
+ last_frac = mode_dep_parm[mode].last_frac;
+ delta_int_low = mode_dep_parm[mode].delta_int_low;
+ delta_int_range = mode_dep_parm[mode].delta_int_range;
+
+ delta_frc_low = mode_dep_parm[mode].delta_frc_low;
+ delta_frc_range = mode_dep_parm[mode].delta_frc_range;
+ pit_min = mode_dep_parm[mode].pit_min;
+
+ /*-----------------------------------------------------------------------*
+ * decide upon full or differential search *
+ *-----------------------------------------------------------------------*/
+
+ delta_search = 1;
+
+ if ((i_subfr == 0) || (i_subfr == L_FRAME_BY2))
+ {
+
+ /* Subframe 1 and 3 */
+
+ if (((mode != MR475) && (mode != MR515)) || (i_subfr != L_FRAME_BY2))
+ {
+
+ /* set t0_min, t0_max for full search */
+ /* this is *not* done for mode MR475, MR515 in subframe 3 */
+
+ delta_search = 0; /* no differential search */
+
+ /* calculate index into T_op which contains the open-loop */
+ /* pitch estimations for the 2 big subframes */
+
+ frame_offset = 1;
+ if (i_subfr == 0)
+ frame_offset = 0;
+
+ /* get T_op from the corresponding half frame and */
+ /* set t0_min, t0_max */
+
+ getRange(T_op[frame_offset], delta_int_low, delta_int_range,
+ pit_min, PIT_MAX, &t0_min, &t0_max, pOverflow);
+ }
+ else
+ {
+
+ /* mode MR475, MR515 and 3. Subframe: delta search as well */
+ getRange(st->T0_prev_subframe, delta_frc_low, delta_frc_range,
+ pit_min, PIT_MAX, &t0_min, &t0_max, pOverflow);
+ }
+ }
+ else
+ {
+
+ /* for Subframe 2 and 4 */
+ /* get range around T0 of previous subframe for delta search */
+
+ getRange(st->T0_prev_subframe, delta_frc_low, delta_frc_range,
+ pit_min, PIT_MAX, &t0_min, &t0_max, pOverflow);
+ }
+
+ /*-----------------------------------------------------------------------*
+ * Find interval to compute normalized correlation *
+ *-----------------------------------------------------------------------*/
+
+ t_min = sub(t0_min, L_INTER_SRCH, pOverflow);
+ t_max = add(t0_max, L_INTER_SRCH, pOverflow);
+
+ corr = &corr_v[-t_min];
+
+ /*-----------------------------------------------------------------------*
+ * Compute normalized correlation between target and filtered excitation *
+ *-----------------------------------------------------------------------*/
+
+ Norm_Corr(exc, xn, h, L_subfr, t_min, t_max, corr, pOverflow);
+
+ /*-----------------------------------------------------------------------*
+ * Find integer pitch *
+ *-----------------------------------------------------------------------*/
+
+ max = corr[t0_min];
+ lag = t0_min;
+
+ for (i = t0_min + 1; i <= t0_max; i++)
+ {
+ if (corr[i] >= max)
+ {
+ max = corr[i];
+ lag = i;
+ }
+ }
+
+ /*-----------------------------------------------------------------------*
+ * Find fractional pitch *
+ *-----------------------------------------------------------------------*/
+ if ((delta_search == 0) && (lag > max_frac_lag))
+ {
+
+ /* full search and integer pitch greater than max_frac_lag */
+ /* fractional search is not needed, set fractional to zero */
+
+ frac = 0;
+ }
+ else
+ {
+
+ /* if differential search AND mode MR475 OR MR515 OR MR59 OR MR67 */
+ /* then search fractional with 4 bits resolution */
+
+ if ((delta_search != 0) &&
+ ((mode == MR475) || (mode == MR515) ||
+ (mode == MR59) || (mode == MR67)))
+ {
+
+ /* modify frac or last_frac according to position of last */
+ /* integer pitch: either search around integer pitch, */
+ /* or only on left or right side */
+
+ tmp_lag = st->T0_prev_subframe;
+ if (sub(sub(tmp_lag, t0_min, pOverflow), 5, pOverflow) > 0)
+ tmp_lag = add(t0_min, 5, pOverflow);
+ if (sub(sub(t0_max, tmp_lag, pOverflow), 4, pOverflow) > 0)
+ tmp_lag = sub(t0_max, 4, pOverflow);
+
+ if ((lag == tmp_lag) || (lag == (tmp_lag - 1)))
+ {
+
+ /* normal search in fractions around T0 */
+
+ searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow);
+
+ }
+ else if (lag == (tmp_lag - 2))
+ {
+ /* limit search around T0 to the right side */
+ frac = 0;
+ searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow);
+ }
+ else if (lag == (tmp_lag + 1))
+ {
+ /* limit search around T0 to the left side */
+ last_frac = 0;
+ searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow);
+ }
+ else
+ {
+ /* no fractional search */
+ frac = 0;
+ }
+ }
+ else
+ /* test the fractions around T0 */
+ searchFrac(&lag, &frac, last_frac, corr, flag3, pOverflow);
+ }
+
+ /*-----------------------------------------------------------------------*
+ * encode pitch *
+ *-----------------------------------------------------------------------*/
+
+ if (flag3 != 0)
+ {
+ /* flag4 indicates encoding with 4 bit resolution; */
+ /* this is needed for mode MR475, MR515 and MR59 */
+
+ flag4 = 0;
+ if ((mode == MR475) || (mode == MR515) ||
+ (mode == MR59) || (mode == MR67))
+ {
+ flag4 = 1;
+ }
+
+ /* encode with 1/3 subsample resolution */
+
+ *ana_index = Enc_lag3(lag, frac, st->T0_prev_subframe,
+ t0_min, t0_max, delta_search, flag4, pOverflow);
+ /* function result */
+
+ }
+ else
+ {
+ /* encode with 1/6 subsample resolution */
+
+ *ana_index = Enc_lag6(lag, frac, t0_min, delta_search, pOverflow);
+ /* function result */
+ }
+
+ /*-----------------------------------------------------------------------*
+ * update state variables *
+ *-----------------------------------------------------------------------*/
+
+ st->T0_prev_subframe = lag;
+
+ /*-----------------------------------------------------------------------*
+ * update output variables *
+ *-----------------------------------------------------------------------*/
+
+ *resu3 = flag3;
+
+ *pit_frac = frac;
+
+ return (lag);
+}
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.h b/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.h
new file mode 100644
index 0000000..5e87cc9
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/pitch_fr.h
@@ -0,0 +1,148 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/pitch_fr.h
+
+ Date: 02/04/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : pitch_fr.h
+ Purpose : Find the pitch period with 1/3 or 1/6 subsample
+ : resolution (closed loop).
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _PITCH_FR_H_
+#define _PITCH_FR_H_
+#define pitch_fr_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 T0_prev_subframe; /* integer pitch lag of previous sub-frame */
+ } Pitch_frState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ Word16 Pitch_fr_init(Pitch_frState **st);
+ /* initialize one instance of the pre processing state.
+ Stores pointer to filter status struct in *st. This pointer has to
+ be passed to Pitch_fr in each call.
+ returns 0 on success
+ */
+
+ Word16 Pitch_fr_reset(Pitch_frState *st);
+ /* reset of pre processing state (i.e. set state memory to zero)
+ returns 0 on success
+ */
+
+ void Pitch_fr_exit(Pitch_frState **st);
+ /* de-initialize pre processing state (i.e. free status struct)
+ stores NULL in *st
+ */
+
+ Word16 Pitch_fr( /* o : pitch period (integer) */
+ Pitch_frState *st, /* i/o : State struct */
+ enum Mode mode, /* i : codec mode */
+ Word16 T_op[], /* i : open loop pitch lags */
+ Word16 exc[], /* i : excitation buffer */
+ Word16 xn[], /* i : target vector */
+ Word16 h[], /* i : impulse response of synthesis and
+ weighting filters */
+ Word16 L_subfr, /* i : Length of subframe */
+ Word16 i_subfr, /* i : subframe offset */
+ Word16 *pit_frac, /* o : pitch period (fractional) */
+ Word16 *resu3, /* o : subsample resolution 1/3 (=1) or 1/6 (=0) */
+ Word16 *ana_index, /* o : index of encoding */
+ Flag *pOverflow
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PITCH_FR_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pitch_ol.cpp b/media/libstagefright/codecs/amrnb/enc/src/pitch_ol.cpp
new file mode 100644
index 0000000..d3a2ec0
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/pitch_ol.cpp
@@ -0,0 +1,1213 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/pitch_ol.c
+ Funtions: Pitch_ol
+ Lag_max
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ The modules in this file compute the open loop pitch lag.
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <string.h>
+
+#include "pitch_ol.h"
+#include "typedef.h"
+#include "basicop_malloc.h"
+#include "cnst.h"
+#include "inv_sqrt.h"
+#include "vad.h"
+#include "calc_cor.h"
+#include "hp_max.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define THRESHOLD 27853
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Lag_max
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS (If VAD2 is defined)
+
+ Inputs
+ corr = pointer to buffer of correlation values (Word32)
+ scal_sig = pointer to buffer of scaled signal values (Word16)
+ scal_fac = scaled signal factor (Word16)
+ scal_flag = EFR compatible scaling flag (Word16)
+ L_frame = length of frame to compute pitch (Word16)
+ lag_max = maximum lag (Word16)
+ lag_min = minimum lag (Word16)
+ cor_max = pointer to the normalized correlation of selected lag (Word16)
+ rmax = pointer to max(<s[i]*s[j]>), (Word32)
+ r0 = pointer to the residual energy (Word32)
+ dtx = dtx flag; equal to 1, if dtx is enabled, 0, otherwise (Flag)
+
+ Outputs:
+ cor_max contains the newly calculated normalized correlation of the
+ selected lag
+ rmax contains the newly calculated max(<s[i]*s[j]>)
+ r0 contains the newly calculated residual energy
+
+ Returns:
+ p_max = lag of the max correlation found (Word16)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS (If VAD2 is not defined)
+
+ Inputs
+ vadSt = pointer to a vadState structure
+ corr = pointer to buffer of correlation values (Word32)
+ scal_sig = pointer to buffer of scaled signal values (Word16)
+ scal_fac = scaled signal factor (Word16)
+ scal_flag = EFR compatible scaling flag (Word16)
+ L_frame = length of frame to compute pitch (Word16)
+ lag_max = maximum lag (Word16)
+ lag_min = minimum lag (Word16)
+ cor_max = pointer to the normalized correlation of selected lag (Word16)
+ dtx = dtx flag; equal to 1, if dtx is enabled, 0, otherwise (Flag)
+ pOverflow = pointer to overflow indicator (Flag)
+
+ Outputs:
+ cor_max contains the newly calculated normalized correlation of the
+ selected lag
+ vadSt contains the updated VAD state parameters
+ pOverflow -> 1 if the math operations called by this routine saturate
+
+ Returns:
+ p_max = lag of the max correlation found (Word16)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Find the lag that has maximum correlation of scal_sig in a given delay range.
+ The correlation is given by:
+
+ cor[t] = <scal_sig[n],scal_sig[n-t]>, t=lag_min,...,lag_max
+
+ The function returns the maximum correlation after normalization and the
+ corresponding lag.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pitch_ol.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+#ifdef VAD2
+static Word16 Lag_max ( // o : lag found
+ Word32 corr[], // i : correlation vector.
+ Word16 scal_sig[], // i : scaled signal.
+ Word16 scal_fac, // i : scaled signal factor.
+ Word16 scal_flag, // i : if 1 use EFR compatible scaling
+ Word16 L_frame, // i : length of frame to compute pitch
+ Word16 lag_max, // i : maximum lag
+ Word16 lag_min, // i : minimum lag
+ Word16 *cor_max, // o : normalized correlation of selected lag
+ Word32 *rmax, // o : max(<s[i]*s[j]>)
+ Word32 *r0, // o : residual energy
+ Flag dtx // i : dtx flag; use dtx=1, do not use dtx=0
+ )
+#else
+static Word16 Lag_max ( // o : lag found
+ vadState *vadSt, // i/o : VAD state struct
+ Word32 corr[], // i : correlation vector.
+ Word16 scal_sig[], // i : scaled signal.
+ Word16 scal_fac, // i : scaled signal factor.
+ Word16 scal_flag, // i : if 1 use EFR compatible scaling
+ Word16 L_frame, // i : length of frame to compute pitch
+ Word16 lag_max, // i : maximum lag
+ Word16 lag_min, // i : minimum lag
+ Word16 *cor_max, // o : normalized correlation of selected lag
+ Flag dtx // i : dtx flag; use dtx=1, do not use dtx=0
+ )
+#endif
+{
+ Word16 i, j;
+ Word16 *p;
+ Word32 max, t0;
+ Word16 max_h, max_l, ener_h, ener_l;
+ Word16 p_max = 0; // initialization only needed to keep gcc silent
+
+ max = MIN_32;
+ p_max = lag_max;
+
+ for (i = lag_max, j = (PIT_MAX-lag_max-1); i >= lag_min; i--, j--)
+ {
+ if (L_sub (corr[-i], max) >= 0)
+ {
+ max = corr[-i];
+ p_max = i;
+ }
+ }
+
+ // compute energy
+
+ t0 = 0;
+ p = &scal_sig[-p_max];
+ for (i = 0; i < L_frame; i++, p++)
+ {
+ t0 = L_mac (t0, *p, *p);
+ }
+ // 1/sqrt(energy)
+
+ if (dtx)
+ { // no test() call since this if is only in simulation env
+#ifdef VAD2
+ *rmax = max;
+ *r0 = t0;
+#else
+ // check tone
+ vad_tone_detection (vadSt, max, t0);
+#endif
+ }
+
+ t0 = Inv_sqrt (t0);
+
+ if (scal_flag)
+ {
+ t0 = L_shl (t0, 1);
+ }
+
+ // max = max/sqrt(energy)
+
+ L_Extract (max, &max_h, &max_l);
+ L_Extract (t0, &ener_h, &ener_l);
+
+ t0 = Mpy_32 (max_h, max_l, ener_h, ener_l);
+
+ if (scal_flag)
+ {
+ t0 = L_shr (t0, scal_fac);
+ *cor_max = extract_h (L_shl (t0, 15)); // divide by 2
+ }
+ else
+ {
+ *cor_max = extract_l(t0);
+ }
+
+ return (p_max);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+#ifdef VAD2
+static Word16 Lag_max( /* o : lag found */
+ Word32 corr[], /* i : correlation vector. */
+ Word16 scal_sig[], /* i : scaled signal. */
+ Word16 scal_fac, /* i : scaled signal factor. */
+ Word16 scal_flag, /* i : if 1 use EFR compatible scaling */
+ Word16 L_frame, /* i : length of frame to compute pitch */
+ Word16 lag_max, /* i : maximum lag */
+ Word16 lag_min, /* i : minimum lag */
+ Word16 *cor_max, /* o : normalized correlation of selected lag */
+ Word32 *rmax, /* o : max(<s[i]*s[j]>) */
+ Word32 *r0, /* o : residual energy */
+ Flag dtx, /* i : dtx flag; use dtx=1, do not use dtx=0 */
+ Flag *pOverflow /* i/o : overflow Flag */
+)
+#else
+static Word16 Lag_max( /* o : lag found */
+ vadState *vadSt, /* i/o : VAD state struct */
+ Word32 corr[], /* i : correlation vector. */
+ Word16 scal_sig[], /* i : scaled signal. */
+ Word16 scal_fac, /* i : scaled signal factor. */
+ Word16 scal_flag, /* i : if 1 use EFR compatible scaling */
+ Word16 L_frame, /* i : length of frame to compute pitch */
+ Word16 lag_max, /* i : maximum lag */
+ Word16 lag_min, /* i : minimum lag */
+ Word16 *cor_max, /* o : normalized correlation of selected lag */
+ Flag dtx, /* i : dtx flag; use dtx=1, do not use dtx=0 */
+ Flag *pOverflow /* i/o : overflow Flag */
+)
+#endif
+{
+ register Word16 i;
+ Word16 *p;
+ Word32 max;
+ Word32 t0;
+ Word16 max_h;
+ Word16 max_l;
+ Word16 ener_h;
+ Word16 ener_l;
+ Word16 p_max = 0; /* initialization only needed to keep gcc silent */
+ Word32 L_temp;
+ Word32 L_temp_2;
+ Word32 L_temp_3;
+ Word32 *p_corr = &corr[-lag_max];
+
+ max = MIN_32;
+ p_max = lag_max;
+
+ for (i = lag_max; i >= lag_min; i--)
+ {
+ /* The negative array index is equivalent to a negative */
+ /* address offset, i.e., corr[-i] == *(corr - i) */
+ if (*(p_corr++) >= max)
+ {
+ p_corr--;
+ max = *(p_corr++);
+ p_max = i;
+ }
+ }
+
+ /* compute energy */
+
+ t0 = 0;
+
+ /* The negative array index is equivalent to a negative */
+ /* address offset, i.e., scal_sig[-p_max] == *(scal_sig - p_max) */
+ p = &scal_sig[-p_max];
+ for (i = (L_frame >> 2); i != 0; i--)
+ {
+ t0 = amrnb_fxp_mac_16_by_16bb((Word32) * (p), (Word32) * (p), t0);
+ p++;
+ t0 = amrnb_fxp_mac_16_by_16bb((Word32) * (p), (Word32) * (p), t0);
+ p++;
+ t0 = amrnb_fxp_mac_16_by_16bb((Word32) * (p), (Word32) * (p), t0);
+ p++;
+ t0 = amrnb_fxp_mac_16_by_16bb((Word32) * (p), (Word32) * (p), t0);
+ p++;
+ }
+
+ t0 <<= 1;
+ /* 1/sqrt(energy) */
+
+ if (dtx)
+ { /* no test() call since this if is only in simulation env */
+ /* check tone */
+#ifdef VAD2
+ *rmax = max;
+ *r0 = t0;
+#else
+ /* check tone */
+ vad_tone_detection(vadSt, max, t0, pOverflow);
+#endif
+ }
+
+ t0 = Inv_sqrt(t0, pOverflow);
+
+ if (scal_flag)
+ {
+ if (t0 > (Word32) 0x3fffffffL)
+ {
+ t0 = MAX_32;
+ }
+ else
+ {
+ t0 = t0 << 1;
+ }
+ }
+
+ /* max = max/sqrt(energy) */
+ /* The following code is an inlined version of */
+ /* L_Extract (max, &max_h, &max_l), i.e. */
+ /* */
+ /* *max_h = extract_h (max); */
+ max_h = (Word16)(max >> 16);
+
+ /* L_temp_2 = L_shr(max,1), which is used in */
+ /* the calculation of *max_l (see next operation) */
+ L_temp_2 = max >> 1;
+
+ /* *max_l = extract_l (L_msu (L_shr (max, 1), *max_h, 16384)); */
+ L_temp_3 = (Word32)(max_h << 15);
+
+ L_temp = L_temp_2 - L_temp_3;
+
+ max_l = (Word16)L_temp;
+
+ /* The following code is an inlined version of */
+ /* L_Extract (t0, &ener_h, &ener_l), i.e. */
+ /* */
+ /* *ener_h = extract_h (t0); */
+ ener_h = (Word16)(t0 >> 16);
+
+ /* L_temp_2 = L_shr(t0,1), which is used in */
+ /* the calculation of *ener_l (see next operation) */
+
+ L_temp_2 = t0 >> 1;
+
+ L_temp_3 = (Word32)(ener_h << 15);
+
+ L_temp = L_temp_2 - L_temp_3;
+
+ ener_l = (Word16)L_temp;
+
+ t0 = Mpy_32(max_h, max_l, ener_h, ener_l, pOverflow);
+
+ if (scal_flag)
+ {
+ t0 = L_shr(t0, scal_fac, pOverflow);
+
+ if (t0 > (Word32) 0X0000FFFFL)
+ {
+ *cor_max = MAX_16;
+ }
+ else if (t0 < (Word32) 0xFFFF0000L)
+ {
+ *cor_max = MIN_16;
+ }
+ else
+ {
+ *cor_max = (Word16)(t0 >> 1);
+ }
+ }
+ else
+ {
+ *cor_max = (Word16)t0;
+ }
+
+ return (p_max);
+}
+
+/*----------------------------------------------------------------------------
+; End Function: Lag_max
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Lag_max_wrapper
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs
+ corr = pointer to buffer of correlation values (Word32)
+ scal_sig = pointer to buffer of scaled signal values (Word16)
+ scal_fac = scaled signal factor (Word16)
+ scal_flag = EFR compatible scaling flag (Word16)
+ L_frame = length of frame to compute pitch (Word16)
+ lag_max = maximum lag (Word16)
+ lag_min = minimum lag (Word16)
+ cor_max = pointer to the normalized correlation of selected lag (Word16)
+ rmax = pointer to max(<s[i]*s[j]>), (Word32)
+ r0 = pointer to the residual energy (Word32)
+ dtx = dtx flag; equal to 1, if dtx is enabled, 0, otherwise (Flag)
+ pOverflow = pointer to overflow indicator (Flag)
+
+ Outputs:
+ cor_max contains the newly calculated normalized correlation of the
+ selected lag
+ rmax contains the newly calculated max(<s[i]*s[j]>)
+ r0 contains the newly calculated residual energy
+ pOverflow -> 1 if the math operations called by this routine saturate
+
+ Returns:
+ p_max = lag of the max correlation found (Word16)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS (If VAD2 is not defined)
+
+ Inputs
+ vadSt = pointer to a vadState structure
+ corr = pointer to buffer of correlation values (Word32)
+ scal_sig = pointer to buffer of scaled signal values (Word16)
+ scal_fac = scaled signal factor (Word16)
+ scal_flag = EFR compatible scaling flag (Word16)
+ L_frame = length of frame to compute pitch (Word16)
+ lag_max = maximum lag (Word16)
+ lag_min = minimum lag (Word16)
+ cor_max = pointer to the normalized correlation of selected lag (Word16)
+ dtx = dtx flag; equal to 1, if dtx is enabled, 0, otherwise (Flag)
+ pOverflow = pointer to overflow indicator (Flag)
+
+ Outputs:
+ cor_max contains the newly calculated normalized correlation of the
+ selected lag
+ vadSt contains the updated VAD state parameters
+ pOverflow -> 1 if the math operations called by this routine saturate
+
+ Returns:
+ p_max = lag of the max correlation found (Word16)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function provides external access to the local function Lag_max.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pitch_ol.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+#ifdef VAD2
+ CALL Lag_max(corr = corr
+ scal_sig = scal_sig
+ scal_fac = scal_fac
+ scal_flag = scal_flag
+ L_frame = L_frame
+ lag_max = lag_max
+ lag_min = lag_min
+ cor_max = cor_max
+ rmax = rmax
+ r0 = r0
+ dtx = dtx
+ pOverflow = pOverflow)
+ MODIFYING(nothing)
+ RETURNING(temp)
+
+#else
+ CALL Lag_max(vadSt = vadSt
+ corr = corr
+ scal_sig = scal_sig
+ scal_fac = scal_fac
+ scal_flag = scal_flag
+ L_frame = L_frame
+ lag_max = lag_max
+ lag_min = lag_min
+ cor_max = cor_max
+ dtx = dtx
+ pOverflow = pOverflow)
+ MODIFYING(nothing)
+ RETURNING(temp)
+
+#endif
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+#ifdef VAD2
+Word16 Lag_max_wrapper( /* o : lag found */
+ Word32 corr[], /* i : correlation vector. */
+ Word16 scal_sig[], /* i : scaled signal. */
+ Word16 scal_fac, /* i : scaled signal factor. */
+ Word16 scal_flag, /* i : if 1 use EFR compatible scaling */
+ Word16 L_frame, /* i : length of frame to compute pitch */
+ Word16 lag_max, /* i : maximum lag */
+ Word16 lag_min, /* i : minimum lag */
+ Word16 *cor_max, /* o : normalized correlation of selected lag */
+ Word32 *rmax, /* o : max(<s[i]*s[j]>) */
+ Word32 *r0, /* o : residual energy */
+ Flag dtx, /* i : dtx flag; use dtx=1, do not use dtx=0 */
+ Flag *pOverflow /* i/o : overflow Flag */
+)
+{
+ Word16 temp;
+
+ temp = Lag_max(corr, scal_sig, scal_fac, scal_flag, L_frame, lag_max,
+ lag_min, cor_max, rmax, r0, dtx, pOverflow);
+
+ return(temp);
+}
+
+#else
+Word16 Lag_max_wrapper( /* o : lag found */
+ vadState *vadSt, /* i/o : VAD state struct */
+ Word32 corr[], /* i : correlation vector. */
+ Word16 scal_sig[], /* i : scaled signal. */
+ Word16 scal_fac, /* i : scaled signal factor. */
+ Word16 scal_flag, /* i : if 1 use EFR compatible scaling */
+ Word16 L_frame, /* i : length of frame to compute pitch */
+ Word16 lag_max, /* i : maximum lag */
+ Word16 lag_min, /* i : minimum lag */
+ Word16 *cor_max, /* o : normalized correlation of selected lag */
+ Flag dtx, /* i : dtx flag; use dtx=1, do not use dtx=0 */
+ Flag *pOverflow /* i/o : overflow Flag */
+)
+{
+ Word16 temp;
+
+ temp = Lag_max(vadSt, corr, scal_sig, scal_fac, scal_flag, L_frame,
+ lag_max, lag_min, cor_max, dtx, pOverflow);
+
+ return(temp);
+}
+
+#endif
+
+/*----------------------------------------------------------------------------
+; End Function: Lag_max_wrapper
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Pitch_ol
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ vadSt = pointer to a vadState structure
+ mode = data of type enum Mode specifies the mode.
+ signal = pointer to buffer of signal used to compute the open loop
+ pitch
+ where signal[-pit_max] to signal[-1] should be known
+ pit_min = 16 bit value specifies the minimum pitch lag
+ pit_max = 16 bit value specifies the maximum pitch lag
+ L_frame = 16 bit value specifies the length of frame to compute pitch
+ idx = 16 bit value specifies the frame index
+ dtx = Data of type 'Flag' used for dtx. Use dtx=1, do not use dtx=0
+ pOverflow = pointer to overflow indicator (Flag)
+
+ Outputs
+ vadSt = The vadSt state structure may be modified.
+ pOverflow -> 1 if the math operations called by this routine saturate
+
+ Returns:
+ p_max1 = 16 bit value representing the open loop pitch lag.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function computes the open loop pitch lag based on the perceptually
+ weighted speech signal. This is done in the following steps:
+ - find three maxima of the correlation <sw[n],sw[n-T]>,
+ dividing the search range into three parts:
+ pit_min ... 2*pit_min-1
+ 2*pit_min ... 4*pit_min-1
+ 4*pit_min ... pit_max
+ - divide each maximum by <sw[n-t], sw[n-t]> where t is the delay at
+ that maximum correlation.
+ - select the delay of maximum normalized correlation (among the
+ three candidates) while favoring the lower delay ranges.
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pitch_ol.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 Pitch_ol ( // o : open loop pitch lag
+ vadState *vadSt, // i/o : VAD state struct
+ enum Mode mode, // i : coder mode
+ Word16 signal[], // i : signal used to compute the open loop pitch
+ // signal[-pit_max] to signal[-1] should be known
+ Word16 pit_min, // i : minimum pitch lag
+ Word16 pit_max, // i : maximum pitch lag
+ Word16 L_frame, // i : length of frame to compute pitch
+ Word16 idx, // i : frame index
+ Flag dtx // i : dtx flag; use dtx=1, do not use dtx=0
+ )
+{
+ Word16 i, j;
+ Word16 max1, max2, max3;
+ Word16 p_max1, p_max2, p_max3;
+ Word16 scal_flag = 0;
+ Word32 t0;
+#ifdef VAD2
+ Word32 r01, r02, r03;
+ Word32 rmax1, rmax2, rmax3;
+#else
+ Word16 corr_hp_max;
+#endif
+ Word32 corr[PIT_MAX+1], *corr_ptr;
+
+ // Scaled signal
+
+ Word16 scaled_signal[L_FRAME + PIT_MAX];
+ Word16 *scal_sig, scal_fac;
+
+#ifndef VAD2
+ if (dtx)
+ { // no test() call since this if is only in simulation env
+ // update tone detection
+ if ((sub(mode, MR475) == 0) || (sub(mode, MR515) == 0))
+ {
+ vad_tone_detection_update (vadSt, 1);
+ }
+ else
+ {
+ vad_tone_detection_update (vadSt, 0);
+ }
+ }
+#endif
+
+ scal_sig = &scaled_signal[pit_max];
+
+ t0 = 0L;
+ for (i = -pit_max; i < L_frame; i++)
+ {
+ t0 = L_mac (t0, signal[i], signal[i]);
+ }
+
+ *--------------------------------------------------------*
+ * Scaling of input signal. *
+ * *
+ * if Overflow -> scal_sig[i] = signal[i]>>3 *
+ * else if t0 < 1^20 -> scal_sig[i] = signal[i]<<3 *
+ * else -> scal_sig[i] = signal[i] *
+ *--------------------------------------------------------*
+
+ *--------------------------------------------------------*
+ * Verification for risk of overflow. *
+ *--------------------------------------------------------*
+
+ if (L_sub (t0, MAX_32) == 0L) // Test for overflow
+ {
+ for (i = -pit_max; i < L_frame; i++)
+ {
+ scal_sig[i] = shr (signal[i], 3);
+ }
+ scal_fac = 3;
+ }
+ else if (L_sub (t0, (Word32) 1048576L) < (Word32) 0)
+ // if (t0 < 2^20)
+ {
+ for (i = -pit_max; i < L_frame; i++)
+ {
+ scal_sig[i] = shl (signal[i], 3);
+ }
+ scal_fac = -3;
+ }
+ else
+ {
+ for (i = -pit_max; i < L_frame; i++)
+ {
+ scal_sig[i] = signal[i];
+ }
+ scal_fac = 0;
+ }
+
+ // calculate all coreelations of scal_sig, from pit_min to pit_max
+ corr_ptr = &corr[pit_max];
+ comp_corr (scal_sig, L_frame, pit_max, pit_min, corr_ptr);
+
+ *--------------------------------------------------------------------*
+ * The pitch lag search is divided in three sections. *
+ * Each section cannot have a pitch multiple. *
+ * We find a maximum for each section. *
+ * We compare the maximum of each section by favoring small lags. *
+ * *
+ * First section: lag delay = pit_max downto 4*pit_min *
+ * Second section: lag delay = 4*pit_min-1 downto 2*pit_min *
+ * Third section: lag delay = 2*pit_min-1 downto pit_min *
+ *--------------------------------------------------------------------*
+
+ // mode dependent scaling in Lag_max
+ if (sub(mode, MR122) == 0)
+ {
+ scal_flag = 1;
+ }
+ else
+ {
+ scal_flag = 0;
+ }
+
+#ifdef VAD2
+ j = shl (pit_min, 2);
+ p_max1 = Lag_max (corr_ptr, scal_sig, scal_fac, scal_flag, L_frame,
+ pit_max, j, &max1, &rmax1, &r01, dtx);
+
+ i = sub (j, 1);
+ j = shl (pit_min, 1);
+ p_max2 = Lag_max (corr_ptr, scal_sig, scal_fac, scal_flag, L_frame,
+ i, j, &max2, &rmax2, &r02, dtx);
+
+ i = sub (j, 1);
+ p_max3 = Lag_max (corr_ptr, scal_sig, scal_fac, scal_flag, L_frame,
+ i, pit_min, &max3, &rmax3, &r03, dtx);
+#else
+ j = shl (pit_min, 2);
+ p_max1 = Lag_max (vadSt, corr_ptr, scal_sig, scal_fac, scal_flag, L_frame,
+ pit_max, j, &max1, dtx);
+
+ i = sub (j, 1);
+ j = shl (pit_min, 1);
+ p_max2 = Lag_max (vadSt, corr_ptr, scal_sig, scal_fac, scal_flag, L_frame,
+ i, j, &max2, dtx);
+
+ i = sub (j, 1);
+ p_max3 = Lag_max (vadSt, corr_ptr, scal_sig, scal_fac, scal_flag, L_frame,
+ i, pit_min, &max3, dtx);
+
+ if (dtx)
+ { // no test() call since this if is only in simulation env
+ if (sub(idx, 1) == 0)
+ {
+ // calculate max high-passed filtered correlation of all lags
+ hp_max (corr_ptr, scal_sig, L_frame, pit_max, pit_min, &corr_hp_max);
+
+ // update complex background detector
+ vad_complex_detection_update(vadSt, corr_hp_max);
+ }
+ }
+#endif
+
+ *--------------------------------------------------------------------*
+ * Compare the 3 sections maximum, and favor small lag. *
+ *--------------------------------------------------------------------*
+
+ if (sub (mult (max1, THRESHOLD), max2) < 0)
+ {
+ max1 = max2;
+ p_max1 = p_max2;
+#ifdef VAD2
+ if (dtx)
+ {
+ rmax1 = rmax2;
+ r01 = r02;
+#endif
+ }
+ if (sub (mult (max1, THRESHOLD), max3) < 0)
+ {
+ p_max1 = p_max3;
+#ifdef VAD2
+ if (dtx)
+ {
+ rmax1 = rmax3;
+ r01 = r03;
+ }
+#endif
+ }
+
+#ifdef VAD2
+ if (dtx)
+ {
+ vadSt->L_Rmax = L_add(vadSt->L_Rmax, rmax1); // Save max correlation
+ vadSt->L_R0 = L_add(vadSt->L_R0, r01); // Save max energy
+ }
+#endif
+
+ return (p_max1);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Pitch_ol( /* o : open loop pitch lag */
+ vadState *vadSt, /* i/o : VAD state struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 signal[], /* i : signal used to compute the open loop pitch */
+ /* signal[-pit_max] to signal[-1] should be known */
+ Word16 pit_min, /* i : minimum pitch lag */
+ Word16 pit_max, /* i : maximum pitch lag */
+ Word16 L_frame, /* i : length of frame to compute pitch */
+ Word16 idx, /* i : frame index */
+ Flag dtx, /* i : dtx flag; use dtx=1, do not use dtx=0 */
+ Flag *pOverflow /* i/o : overflow Flag */
+)
+{
+ Word16 i;
+ Word16 j;
+ Word16 max1;
+ Word16 max2;
+ Word16 max3;
+ Word16 p_max1;
+ Word16 p_max2;
+ Word16 p_max3;
+ Word16 scal_flag = 0;
+ Word32 t0;
+
+#ifdef VAD2
+ Word32 r01;
+ Word32 r02;
+ Word32 r03;
+ Word32 rmax1;
+ Word32 rmax2;
+ Word32 rmax3;
+#else
+ Word16 corr_hp_max;
+#endif
+ Word32 corr[PIT_MAX+1];
+ Word32 *corr_ptr;
+
+ /* Scaled signal */
+
+ Word16 scaled_signal[L_FRAME + PIT_MAX];
+ Word16 *scal_sig;
+ Word16 *p_signal;
+ Word16 scal_fac;
+ Word32 L_temp;
+
+#ifndef VAD2
+ if (dtx)
+ { /* no test() call since this if is only in simulation env */
+ /* update tone detection */
+ if ((mode == MR475) || (mode == MR515))
+ {
+ vad_tone_detection_update(vadSt, 1, pOverflow);
+ }
+ else
+ {
+ vad_tone_detection_update(vadSt, 0, pOverflow);
+ }
+ }
+#endif
+
+
+ t0 = 0L;
+ p_signal = &signal[-pit_max];
+
+ for (i = -pit_max; i < L_frame; i++)
+ {
+ t0 += (((Word32) * (p_signal)) * *(p_signal)) << 1;
+ p_signal++;
+ if (t0 < 0)
+ {
+ t0 = MAX_32;
+ break;
+ }
+
+ }
+
+ /*--------------------------------------------------------*
+ * Scaling of input signal. *
+ * *
+ * if Overflow -> scal_sig[i] = signal[i]>>3 *
+ * else if t0 < 1^20 -> scal_sig[i] = signal[i]<<3 *
+ * else -> scal_sig[i] = signal[i] *
+ *--------------------------------------------------------*/
+
+ /*--------------------------------------------------------*
+ * Verification for risk of overflow. *
+ *--------------------------------------------------------*/
+
+ scal_sig = &scaled_signal[0];
+ p_signal = &signal[-pit_max];
+
+ if (t0 == MAX_32) /* Test for overflow */
+ {
+
+ for (i = (pit_max + L_frame) >> 1; i != 0; i--)
+ {
+ *(scal_sig++) = (Word16)(((Word32) * (p_signal++) >> 3));
+ *(scal_sig++) = (Word16)(((Word32) * (p_signal++) >> 3));
+ }
+
+ if ((pit_max + L_frame) & 1)
+ {
+ *(scal_sig) = (Word16)(((Word32) * (p_signal) >> 3));
+ }
+
+ scal_fac = 3;
+ }
+ else if (t0 < (Word32)1048576L)
+ /* if (t0 < 2^20) */
+ {
+ for (i = (pit_max + L_frame) >> 1; i != 0; i--)
+ {
+ *(scal_sig++) = (Word16)(((Word32) * (p_signal++) << 3));
+ *(scal_sig++) = (Word16)(((Word32) * (p_signal++) << 3));
+ }
+
+ if ((pit_max + L_frame) & 1)
+ {
+ *(scal_sig) = (Word16)(((Word32) * (p_signal) << 3));
+ }
+ scal_fac = -3;
+ }
+ else
+ {
+
+ memcpy(scal_sig, p_signal, (L_frame + pit_max)*sizeof(*signal));
+ scal_fac = 0;
+ }
+
+ /* calculate all coreelations of scal_sig, from pit_min to pit_max */
+ corr_ptr = &corr[pit_max];
+
+ scal_sig = &scaled_signal[pit_max];
+
+ comp_corr(scal_sig, L_frame, pit_max, pit_min, corr_ptr);
+
+ /*--------------------------------------------------------------------*
+ * The pitch lag search is divided in three sections. *
+ * Each section cannot have a pitch multiple. *
+ * We find a maximum for each section. *
+ * We compare the maximum of each section by favoring small lags. *
+ * *
+ * First section: lag delay = pit_max downto 4*pit_min *
+ * Second section: lag delay = 4*pit_min-1 downto 2*pit_min *
+ * Third section: lag delay = 2*pit_min-1 downto pit_min *
+ *--------------------------------------------------------------------*/
+
+ /* mode dependent scaling in Lag_max */
+
+ if (mode == MR122)
+ {
+ scal_flag = 1;
+ }
+ else
+ {
+ scal_flag = 0;
+ }
+
+#ifdef VAD2
+ L_temp = ((Word32)pit_min) << 2;
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ *pOverflow = 1;
+ j = (pit_min > 0) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ j = (Word16)L_temp;
+ }
+
+ p_max1 = Lag_max(corr_ptr, scal_sig, scal_fac, scal_flag, L_frame,
+ pit_max, j, &max1, &rmax1, &r01, dtx, pOverflow);
+
+ i = j - 1;
+
+ j = pit_min << 1;
+
+ p_max2 = Lag_max(corr_ptr, scal_sig, scal_fac, scal_flag, L_frame,
+ i, j, &max2, &rmax2, &r02, dtx, pOverflow);
+
+ i = j - 1;
+
+ p_max3 = Lag_max(corr_ptr, scal_sig, scal_fac, scal_flag, L_frame,
+ i, pit_min, &max3, &rmax3, &r03, dtx, pOverflow);
+
+#else
+ L_temp = ((Word32)pit_min) << 2;
+ if (L_temp != (Word32)((Word16) L_temp))
+ {
+ *pOverflow = 1;
+ j = (pit_min > 0) ? MAX_16 : MIN_16;
+ }
+ else
+ {
+ j = (Word16)L_temp;
+ }
+
+ p_max1 = Lag_max(vadSt, corr_ptr, scal_sig, scal_fac, scal_flag, L_frame,
+ pit_max, j, &max1, dtx, pOverflow);
+
+ i = j - 1;
+
+
+ j = pit_min << 1;
+
+
+ p_max2 = Lag_max(vadSt, corr_ptr, scal_sig, scal_fac, scal_flag, L_frame,
+ i, j, &max2, dtx, pOverflow);
+
+ i = j - 1;
+ p_max3 = Lag_max(vadSt, corr_ptr, scal_sig, scal_fac, scal_flag, L_frame,
+ i, pit_min, &max3, dtx, pOverflow);
+
+ if (dtx)
+ { /* no test() call since this if is only in simulation env */
+
+ if (idx == 1)
+ {
+ /* calculate max high-passed filtered correlation of all lags */
+ hp_max(corr_ptr, scal_sig, L_frame, pit_max, pit_min, &corr_hp_max,
+ pOverflow);
+
+ /* update complex background detector */
+ vad_complex_detection_update(vadSt, corr_hp_max);
+ }
+ }
+#endif
+
+ /*--------------------------------------------------------------------*
+ * Compare the 3 sections maximum, and favor small lag. *
+ *--------------------------------------------------------------------*/
+
+ i = mult(max1, THRESHOLD, pOverflow);
+
+ if (i < max2)
+ {
+ max1 = max2;
+ p_max1 = p_max2;
+
+#ifdef VAD2
+ if (dtx)
+ {
+ rmax1 = rmax2;
+ r01 = r02;
+ }
+#endif
+ }
+
+ i = mult(max1, THRESHOLD, pOverflow);
+
+ if (i < max3)
+ {
+ p_max1 = p_max3;
+
+#ifdef VAD2
+ if (dtx)
+ {
+ rmax1 = rmax3;
+ r01 = r03;
+ }
+#endif
+ }
+
+#ifdef VAD2
+ if (dtx)
+ {
+ /* Save max correlation */
+ vadSt->L_Rmax = L_add(vadSt->L_Rmax, rmax1, pOverflow);
+ /* Save max energy */
+ vadSt->L_R0 = L_add(vadSt->L_R0, r01, pOverflow);
+ }
+#endif
+
+ return (p_max1);
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pitch_ol.h b/media/libstagefright/codecs/amrnb/enc/src/pitch_ol.h
new file mode 100644
index 0000000..df7f307
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/pitch_ol.h
@@ -0,0 +1,122 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/pitch_ol.h
+
+ Date: 02/06/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : pitch_ol.h
+ Purpose : Compute the open loop pitch lag.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PITCH_OL_H
+#define PITCH_OL_H "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "vad.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ Word16 Pitch_ol( /* o : open loop pitch lag */
+ vadState *vadSt, /* i/o : VAD state struct */
+ enum Mode mode, /* i : coder mode */
+ Word16 signal[], /* i : signal used to compute the open loop pitch */
+ /* signal[-pit_max] to signal[-1] should be known */
+ Word16 pit_min, /* i : minimum pitch lag */
+ Word16 pit_max, /* i : maximum pitch lag */
+ Word16 L_frame, /* i : length of frame to compute pitch */
+ Word16 idx, /* i : frame index */
+ Flag dtx, /* i : dtx flag; use dtx=1, do not use dtx=0 */
+ Flag *pOverflow /* i/o : overflow Flag */
+ );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PITCH_OL_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pre_big.cpp b/media/libstagefright/codecs/amrnb/enc/src/pre_big.cpp
new file mode 100644
index 0000000..02544cf
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/pre_big.cpp
@@ -0,0 +1,210 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/pre_big.c
+ Functions:
+
+ Date: 02/04/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+ Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Big subframe (2 subframes) preprocessing
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pre_big.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "syn_filt.h"
+#include "weight_a.h"
+#include "residu.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: pre_big
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ mode = enum Mode -- coder mode
+ gamma1 = array of type const Word16 -- spectral exp. factor 1
+ gamma1_12k2 = array of type const Word16 -- spectral exp. factor 1 for EFR
+ gamma2 = array of type const Word16 -- spectral exp. factor 2
+ A_t = array of type Word16 -- A(z) unquantized, for 4 subframes, Q12
+ frameOffset = Word16 -- Start position in speech vector, Q0
+ speech[] = array of type Word16 -- speech, Q0
+
+ Outputs:
+ mem_w = array of type Word16 -- synthesis filter memory state, Q0
+ wsp = array of type Word16 -- weighted speech Q0
+ pOverflow = pointer of type Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pre_big.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void pre_big(
+ enum Mode mode, /* i : coder mode */
+ const Word16 gamma1[], /* i : spectral exp. factor 1 */
+ const Word16 gamma1_12k2[],/* i : spectral exp. factor 1 for EFR */
+ const Word16 gamma2[], /* i : spectral exp. factor 2 */
+ Word16 A_t[], /* i : A(z) unquantized, for 4 subframes, Q12 */
+ Word16 frameOffset, /* i : Start position in speech vector, Q0 */
+ Word16 speech[], /* i : speech, Q0 */
+ Word16 mem_w[], /* i/o: synthesis filter memory state, Q0 */
+ Word16 wsp[], /* o : weighted speech Q0 */
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ Word16 Ap1[MP1]; /* A(z) with spectral expansion */
+ Word16 Ap2[MP1]; /* A(z) with spectral expansion */
+ const Word16 *g1; /* Pointer to correct gammma1 vector */
+ Word16 aOffset;
+ Word16 i;
+
+ if (mode <= MR795)
+ {
+ g1 = gamma1;
+ }
+ else
+ {
+ g1 = gamma1_12k2;
+ }
+
+ if (frameOffset > 0)
+ {
+ aOffset = 2 * MP1;
+ }
+ else
+ {
+ aOffset = 0;
+ }
+
+ /* process two subframes (which form the "big" subframe) */
+ for (i = 0; i < 2; i++)
+ {
+ Weight_Ai(&A_t[aOffset], g1, Ap1);
+ Weight_Ai(&A_t[aOffset], gamma2, Ap2);
+ Residu(Ap1, &speech[frameOffset], &wsp[frameOffset], L_SUBFR);
+
+ Syn_filt(Ap2, &wsp[frameOffset], &wsp[frameOffset], L_SUBFR, mem_w, 1);
+
+ aOffset = add(aOffset, MP1, pOverflow);
+
+ frameOffset = add(frameOffset, L_SUBFR, pOverflow);
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pre_big.h b/media/libstagefright/codecs/amrnb/enc/src/pre_big.h
new file mode 100644
index 0000000..6b47bfe
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/pre_big.h
@@ -0,0 +1,131 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/pre_big.h
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the file, pre_big.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef pre_big_h
+#define pre_big_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "cnst.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void pre_big(
+ enum Mode mode, /* i : coder mode */
+ const Word16 gamma1[], /* i : spectral exp. factor 1 */
+ const Word16 gamma1_12k2[],/* i : spectral exp. factor 1 for EFR */
+ const Word16 gamma2[], /* i : spectral exp. factor 2 */
+ Word16 A_t[], /* i : A(z) unquantized, for 4 subframes, Q12 */
+ Word16 frameOffset, /* i : Start position in speech vector, Q0 */
+ Word16 speech[], /* i : speech, Q0 */
+ Word16 mem_w[], /* i/o: synthesis filter memory state, Q0 */
+ Word16 wsp[], /* o : weighted speech Q0 */
+ Flag *pOverflow /* o : overflow indicator */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _H_ */
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pre_proc.cpp b/media/libstagefright/codecs/amrnb/enc/src/pre_proc.cpp
new file mode 100644
index 0000000..fdc2440
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/pre_proc.cpp
@@ -0,0 +1,589 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/pre_proc.c
+ Funtions: Pre_Process_init
+ Pre_Process_reset
+ Pre_Process_exit
+ Pre_Process
+
+ Date: 05/17/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Put the file into our template structure.
+
+ Description: First pass optimization.
+
+ Description: Made changes based on comments from review meeting.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Removed basic_op.h from the Include section. It is not used.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Fixed typecasting issue with TI C compiler.
+ 2. Modified FOR loop to count down.
+ 3. Cosmetic changes to the code to make address post-increment
+ clearer.
+ 4. Removed unnecessary typecasting in the multiply-accumulate
+ portion of FOR loop body.
+ 5. Removed "static" in table definitions.
+ 6. Updated copyright year.
+
+ Description: For Pre_Process()
+ 1. Replaced variables (containing filter coefficients) with
+ constants, to avoid extra register swaping.
+ 2. Changed to decrement loop
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ These modules handle the preprocessing of input speech.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+
+#include "pre_proc.h"
+#include "typedef.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Pre_Process_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to an array of pointer to structures of type
+ Pre_ProcessState
+
+ Outputs:
+ Structure pointed to by the pointer pointed to by state is
+ initialized to its reset value
+ state points to the allocated memory
+
+ Returns:
+ return_value = 0 if memory was successfully initialized,
+ otherwise returns -1.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Allocates state memory and initializes state memory.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pre_proc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Pre_Process_init (Pre_ProcessState **state)
+{
+ Pre_ProcessState* s;
+
+ if (state == (Pre_ProcessState **) NULL){
+ fprintf(stderr, "Pre_Process_init: invalid parameter\n");
+ return -1;
+ }
+ *state = NULL;
+
+ // allocate memory
+ if ((s= (Pre_ProcessState *) malloc(sizeof(Pre_ProcessState))) == NULL){
+ fprintf(stderr, "Pre_Process_init: can not malloc state structure\n");
+ return -1;
+ }
+
+ Pre_Process_reset(s);
+ *state = s;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Pre_Process_init(Pre_ProcessState **state)
+{
+ Pre_ProcessState* s;
+
+ if (state == (Pre_ProcessState **) NULL)
+ {
+ /* fprintf(stderr, "Pre_Process_init: invalid parameter\n"); */
+ return(-1);
+ }
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (Pre_ProcessState *) malloc(sizeof(Pre_ProcessState))) == NULL)
+ {
+ /* fprintf(stderr, "Pre_Process_init:
+ can not malloc state structure\n"); */
+ return(-1);
+ }
+
+ Pre_Process_reset(s);
+ *state = s;
+
+ return(0);
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Pre_Process_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to structure of type Pre_ProcessState
+
+ Outputs:
+ Structure pointed to by state is initialized to zero.
+
+ Returns:
+ return_value = 0 if memory was successfully reset,
+ otherwise returns -1.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Initializes state memory to zero.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pre_proc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Pre_Process_reset (Pre_ProcessState *state)
+{
+ if (state == (Pre_ProcessState *) NULL){
+ fprintf(stderr, "Pre_Process_reset: invalid parameter\n");
+ return -1;
+ }
+
+ state->y2_hi = 0;
+ state->y2_lo = 0;
+ state->y1_hi = 0;
+ state->y1_lo = 0;
+ state->x0 = 0;
+ state->x1 = 0;
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Pre_Process_reset(Pre_ProcessState *state)
+{
+ if (state == (Pre_ProcessState *) NULL)
+ {
+ /* fprintf(stderr, "Pre_Process_reset: invalid parameter\n"); */
+ return(-1);
+ }
+
+ state->y2_hi = 0;
+ state->y2_lo = 0;
+ state->y1_hi = 0;
+ state->y1_lo = 0;
+ state->x0 = 0;
+ state->x1 = 0;
+
+ return(0);
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Pre_Process_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = a pointer to an array of pointers to structures of
+ type Pre_ProcessState
+
+ Outputs:
+ state points to a NULL address
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ The memory used for state memory is freed.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pre_proc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Pre_Process_exit (Pre_ProcessState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ // deallocate memory
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Pre_Process_exit(Pre_ProcessState **state)
+{
+ if (state == NULL || *state == NULL)
+ {
+ return;
+ }
+
+ /* deallocate memory */
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Pre_Process
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = a pointer to a structure of type Pre_ProcessState
+ signal = input/output signal (Word16)
+ lg = length of signal (Word16)
+
+ Outputs:
+ st points to the updated structure
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ a = points to a buffer of filter coefficients
+ b = points to a buffer of filter coefficients
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This module performs the preprocessing of the input speech.
+ The signal is passed through a 2nd order high pass filtering with cut off
+ frequency at 80 Hz. The input is divided by two in the filtering process.
+
+ y[i] = b[0]*x[i]/2 + b[1]*x[i-1]/2 + b[2]*x[i-2]/2
+ + a[1]*y[i-1] + a[2]*y[i-2];
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ pre_proc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Pre_Process (
+ Pre_ProcessState *st,
+ Word16 signal[], // input/output signal
+ Word16 lg) // lenght of signal
+{
+ Word16 i, x2;
+ Word32 L_tmp;
+
+ for (i = 0; i < lg; i++)
+ {
+ x2 = st->x1;
+ st->x1 = st->x0;
+ st->x0 = signal[i];
+
+ // y[i] = b[0]*x[i]/2 + b[1]*x[i-1]/2 + b140[2]*x[i-2]/2
+ // + a[1]*y[i-1] + a[2] * y[i-2];
+
+ L_tmp = Mpy_32_16 (st->y1_hi, st->y1_lo, a[1]);
+ L_tmp = L_add (L_tmp, Mpy_32_16 (st->y2_hi, st->y2_lo, a[2]));
+ L_tmp = L_mac (L_tmp, st->x0, b[0]);
+ L_tmp = L_mac (L_tmp, st->x1, b[1]);
+ L_tmp = L_mac (L_tmp, x2, b[2]);
+ L_tmp = L_shl (L_tmp, 3);
+ signal[i] = pv_round (L_tmp);
+
+ st->y2_hi = st->y1_hi;
+ st->y2_lo = st->y1_lo;
+ L_Extract (L_tmp, &st->y1_hi, &st->y1_lo);
+ }
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+/*
+ filter coefficients (fc = 80 Hz, coeff. b[] is divided by 2)
+ const Word16 b[3] = {1899, -3798, 1899};
+ const Word16 a[3] = {4096, 7807, -3733};
+
+*/
+
+void Pre_Process(
+ Pre_ProcessState *st,
+ Word16 signal[], /* input/output signal */
+ Word16 lg) /* length of signal */
+{
+ register Word16 i;
+ Word16 x_n_2;
+ Word16 x_n_1;
+ Word32 L_tmp;
+ Word16 *p_signal = signal;
+
+ x_n_2 = st->x1;
+ x_n_1 = st->x0;
+
+ for (i = lg; i != 0; i--)
+ {
+
+
+ /* y[i] = b[0]*x[i]/2 + b[1]*x[i-1]/2 + b140[2]*x[i-2]/2 */
+ /* + a[1]*y[i-1] + a[2] * y[i-2]; */
+
+ L_tmp = ((Word32) st->y1_hi) * 7807;
+ L_tmp += (Word32)(((Word32) st->y1_lo * 7807) >> 15);
+
+ L_tmp += ((Word32) st->y2_hi) * (-3733);
+ st->y2_hi = st->y1_hi;
+ L_tmp += (Word32)(((Word32) st->y2_lo * (-3733)) >> 15);
+ st->y2_lo = st->y1_lo;
+
+ L_tmp += ((Word32) x_n_2) * 1899;
+ x_n_2 = x_n_1;
+ L_tmp += ((Word32) x_n_1) * (-3798);
+ x_n_1 = *(p_signal);
+ L_tmp += ((Word32) x_n_1) * 1899;
+
+
+ *(p_signal++) = (Word16)((L_tmp + 0x0000800L) >> 12);
+
+ st->y1_hi = (Word16)(L_tmp >> 12);
+ st->y1_lo = (Word16)((L_tmp << 3) - ((Word32)(st->y1_hi) << 15));
+
+ }
+
+ st->x1 = x_n_2;
+ st->x0 = x_n_1;
+
+ return;
+}
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/pre_proc.h b/media/libstagefright/codecs/amrnb/enc/src/pre_proc.h
new file mode 100644
index 0000000..abe676f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/pre_proc.h
@@ -0,0 +1,114 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : pre_proc.h
+* Purpose : Preprocessing of input speech.
+*
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+********************************************************************************
+*/
+#ifndef pre_proc_h
+#define pre_proc_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ ********************************************************************************
+ * LOCAL VARIABLES AND TABLES
+ ********************************************************************************
+ */
+
+ /*
+ ********************************************************************************
+ * DEFINITION OF DATA TYPES
+ ********************************************************************************
+ */
+ typedef struct
+ {
+ Word16 y2_hi;
+ Word16 y2_lo;
+ Word16 y1_hi;
+ Word16 y1_lo;
+ Word16 x0;
+ Word16 x1;
+ } Pre_ProcessState;
+
+ /*
+ ********************************************************************************
+ * DECLARATION OF PROTOTYPES
+ ********************************************************************************
+ */
+
+ Word16 Pre_Process_init(Pre_ProcessState **st);
+ /* initialize one instance of the pre processing state.
+ Stores pointer to filter status struct in *st. This pointer has to
+ be passed to Pre_Process in each call.
+ returns 0 on success
+ */
+
+ Word16 Pre_Process_reset(Pre_ProcessState *st);
+ /* reset of pre processing state (i.e. set state memory to zero)
+ returns 0 on success
+ */
+ void Pre_Process_exit(Pre_ProcessState **st);
+ /* de-initialize pre processing state (i.e. free status struct)
+ stores NULL in *st
+ */
+
+ void Pre_Process(
+ Pre_ProcessState *st,
+ Word16 signal[], /* Input/output signal */
+ Word16 lg /* Lenght of signal */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/enc/src/prm2bits.cpp b/media/libstagefright/codecs/amrnb/enc/src/prm2bits.cpp
new file mode 100644
index 0000000..9088f7d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/prm2bits.cpp
@@ -0,0 +1,310 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+
+
+
+ Filename: /audio/gsm_amr/c/src/prm2bits.c
+
+ Date: 02/04/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Improved the code as per review comments.
+
+ Description: For Int2bin() and Prm2bits()
+ 1. Eliminated unused include file typedef.h.
+ 2. Replaced array addressing by pointers
+ 3. Changed to decrement loops
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "prm2bits.h"
+#include "mode.h"
+#include "bitno_tab.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+#define MASK 0x0001
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Int2bin
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ value = value to be converted to binary of type Word16
+ no_of_bits = number of bits associated with value of type Word16
+
+ Outputs:
+ bitstream = pointer to address where bits are written of type Word16
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ FUNCTION: Int2bin
+
+ PURPOSE: convert integer to binary and write the bits to the array
+ bitstream[]. The most significant bits are written first.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ prm2bits.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+static void Int2bin (
+ Word16 value, // input : value to be converted to binary
+ Word16 no_of_bits, // input : number of bits associated with value
+ Word16 *bitstream // output: address where bits are written
+)
+{
+ Word16 *pt_bitstream, i, bit;
+
+ pt_bitstream = &bitstream[no_of_bits];
+
+ for (i = 0; i < no_of_bits; i++)
+ {
+ bit = value & MASK;
+ if (bit == 0)
+ {
+ *--pt_bitstream = BIT_0;
+ }
+ else
+ {
+ *--pt_bitstream = BIT_1;
+ }
+ value = shr (value, 1);
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+static void Int2bin(
+ Word16 value, /* input : value to be converted to binary */
+ Word16 no_of_bits, /* input : number of bits associated with value */
+ Word16 *bitstream /* output: address where bits are written */
+)
+{
+ Word16 *pt_bitstream;
+ Word16 i;
+
+ pt_bitstream = &bitstream[no_of_bits-1];
+
+ for (i = no_of_bits; i != 0; i--)
+ {
+ *(pt_bitstream--) = value & MASK;
+ value >>= 1;
+ }
+
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: prm2bits
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ mode = AMR mode of type enum Mode
+ prm[] = pointer to analysis parameters of type Word16
+
+ Outputs:
+ bits[] = pointer to serial bits of type Word16
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ FUNCTION: Prm2bits
+
+ PURPOSE: converts the encoder parameter vector into a vector of serial
+ bits.
+
+ DESCRIPTION: depending on the mode, different numbers of parameters
+ (with differing numbers of bits) are processed. Details
+ are found in bitno.tab
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ prm2bits.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void Prm2bits (
+ enum Mode mode, // i : AMR mode
+ Word16 prm[], // i : analysis parameters (size <= MAX_PRM_SIZE)
+ Word16 bits[] // o : serial bits (size <= MAX_SERIAL_SIZE)
+)
+{
+ Word16 i;
+
+ for (i = 0; i < prmno[mode]; i++)
+ {
+ Int2bin (prm[i], bitno[mode][i], bits);
+ bits += bitno[mode][i];
+ add(0,0); // account for above pointer update
+ }
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void Prm2bits(
+ enum Mode mode, /* i : AMR mode */
+ Word16 prm[], /* i : analysis parameters (size <= MAX_PRM_SIZE) */
+ Word16 bits[] /* o : serial bits (size <= MAX_SERIAL_SIZE) */
+)
+{
+ Word16 i;
+ const Word16 *p_mode;
+ Word16 *p_prm;
+
+ p_mode = &bitno[mode][0];
+ p_prm = &prm[0];
+
+ for (i = prmno[mode]; i != 0; i--)
+ {
+ Int2bin(*(p_prm++), *(p_mode), bits);
+ bits += *(p_mode++);
+ }
+
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/prm2bits.h b/media/libstagefright/codecs/amrnb/enc/src/prm2bits.h
new file mode 100644
index 0000000..8ad11a8
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/prm2bits.h
@@ -0,0 +1,81 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+********************************************************************************
+*
+* GSM AMR-NB speech codec R98 Version 7.5.0 March 2, 2001
+* R99 Version 3.2.0
+* REL-4 Version 4.0.0
+*
+********************************************************************************
+*
+* File : prm2bits.h
+* Purpose : Converts the encoder parameter vector into a
+* : vector of serial bits.
+*
+********************************************************************************
+*/
+#ifndef prm2bits_h
+#define prm2bits_h "$Id $"
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+#include "mode.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*
+ ********************************************************************************
+ * DEFINITION OF DATA TYPES
+ ********************************************************************************
+ */
+
+ /*
+ ********************************************************************************
+ * DECLARATION OF PROTOTYPES
+ ********************************************************************************
+ */
+ void Prm2bits(
+ enum Mode mode, /* i : AMR mode */
+ Word16 prm[], /* input : analysis parameters */
+ Word16 bits[] /* output: serial bits */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrnb/enc/src/q_gain_c.cpp b/media/libstagefright/codecs/amrnb/enc/src/q_gain_c.cpp
new file mode 100644
index 0000000..c58b687
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/q_gain_c.cpp
@@ -0,0 +1,293 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/q_gain_c.c
+ Functions: q_gain_code
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+ Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description:
+ (1) Removed optimization -- mult(i, 3, pOverflow) is NOT the same as adding
+ i to itself 3 times. The reason is because the mult function does a
+ right shift by 15, which will obliterate smaller numbers.
+
+ Description:
+ 1. Eliminated unused include files.
+ 2. Eliminated math operations that unnecessary checked for
+ saturation by evaluating the operands
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Scalar quantization of the innovative codebook gain.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "q_gain_c.h"
+#include "mode.h"
+#include "oper_32b.h"
+#include "basic_op.h"
+#include "log2.h"
+#include "pow2.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+#define NB_QUA_CODE 32
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 qua_gain_code[NB_QUA_CODE*3];
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: q_gain_code
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ mode -- enum Mode -- AMR mode
+ exp_gcode0 -- Word16 -- predicted CB gain (exponent), Q0
+ frac_gcode0 -- Word16 -- predicted CB gain (fraction), Q15
+ gain -- Pointer to Word16 -- quantized fixed codebook gain, Q1
+
+ Outputs:
+ gain -- Pointer to Word16 -- quantized fixed codebook gain, Q1
+
+ qua_ener_MR122 -- Pointer to Word16 -- quantized energy error, Q10
+ (for MR122 MA predictor update)
+
+ qua_ener -- Pointer to Word16 -- quantized energy error, Q10
+ (for other MA predictor update)
+
+ pOverflow -- Pointer to Flag -- overflow indicator
+ Returns:
+ quantization index -- Word16 -- Q0
+
+ Global Variables Used:
+ qua_gain_code[]
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Scalar quantization of the innovative codebook gain.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ q_gain_c.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 q_gain_code( /* o : quantization index, Q0 */
+ enum Mode mode, /* i : AMR mode */
+ Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
+ Word16 frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
+ Word16 *gain, /* i/o: quantized fixed codebook gain, Q1 */
+ Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */
+ /* (for MR122 MA predictor update) */
+ Word16 *qua_ener, /* o : quantized energy error, Q10 */
+ /* (for other MA predictor update) */
+ Flag *pOverflow
+)
+{
+ const Word16 *p;
+ Word16 i;
+ Word16 index;
+ Word16 gcode0;
+ Word16 err;
+ Word16 err_min;
+ Word16 g_q0;
+ Word16 temp;
+
+ if (mode == MR122)
+ {
+ g_q0 = *gain >> 1; /* Q1 -> Q0 */
+ }
+ else
+ {
+ g_q0 = *gain;
+ }
+
+ /*-------------------------------------------------------------------*
+ * predicted codebook gain *
+ * ~~~~~~~~~~~~~~~~~~~~~~~ *
+ * gc0 = Pow2(int(d)+frac(d)) *
+ * = 2^exp + 2^frac *
+ * *
+ *-------------------------------------------------------------------*/
+
+ gcode0 = (Word16) Pow2(exp_gcode0, frac_gcode0, pOverflow); /* predicted gain */
+
+ if (mode == MR122)
+ {
+ gcode0 = shl(gcode0, 4, pOverflow);
+ }
+ else
+ {
+ gcode0 = shl(gcode0, 5, pOverflow);
+ }
+
+ /*-------------------------------------------------------------------*
+ * Search for best quantizer *
+ *-------------------------------------------------------------------*/
+
+ p = &qua_gain_code[0];
+ err_min = ((Word32)gcode0 * *(p++)) >> 15;
+ err_min = g_q0 - err_min;
+ if (err_min < 0)
+ {
+ err_min = -err_min;
+ }
+
+ p += 2; /* skip quantized energy errors */
+ index = 0;
+
+ for (i = 1; i < NB_QUA_CODE; i++)
+ {
+ err = ((Word32)gcode0 * *(p++)) >> 15;
+ err = g_q0 - err;
+
+ if (err < 0)
+ {
+ err = -err;
+ }
+
+ p += 2; /* skip quantized energy error */
+
+ if (err < err_min)
+ {
+ err_min = err;
+ index = i;
+ }
+ }
+
+ temp = index + (index << 1);
+
+ p = &qua_gain_code[temp];
+
+ temp = (gcode0 * *(p++)) >> 15;
+ if (mode == MR122)
+ {
+ *gain = temp << 1;
+ }
+ else
+ {
+ *gain = temp;
+ }
+
+ /* quantized error energies (for MA predictor update) */
+ *qua_ener_MR122 = *p++;
+ *qua_ener = *p;
+
+ return index;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/q_gain_c.h b/media/libstagefright/codecs/amrnb/enc/src/q_gain_c.h
new file mode 100644
index 0000000..621143d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/q_gain_c.h
@@ -0,0 +1,136 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/q_gain.h
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the file, q_gain.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef q_gain_c_h
+#define q_gain_c_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "gc_pred.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*--------------------------------------------------------------------------*
+ * Function q_gain_code() *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * Scalar quantization of the innovative codebook gain. *
+ * *
+ * gc_pred() is used for MA prediction of the innovation energy *
+ *--------------------------------------------------------------------------*/
+ Word16 q_gain_code( /* o : quantization index, Q0 */
+ enum Mode mode, /* i : AMR mode */
+ Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
+ Word16 frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
+ Word16 *gain, /* i/o: quantized fixed codebook gain, Q1 */
+ Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */
+ /* (for MR122 MA predictor update) */
+ Word16 *qua_ener, /* o : quantized energy error, Q10 */
+ /* (for other MA predictor update) */
+ Flag *pOverflow
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* q_gain_c_h */
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/q_gain_p.cpp b/media/libstagefright/codecs/amrnb/enc/src/q_gain_p.cpp
new file mode 100644
index 0000000..c1aff6b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/q_gain_p.cpp
@@ -0,0 +1,267 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/q_gain_p.c
+ Functions: q_gain_pitch
+
+ Date: 02/04/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+ Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "q_gain_p.h"
+#include "typedef.h"
+#include "oper_32b.h"
+#include "cnst.h"
+#include "basic_op.h"
+
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+#define NB_QUA_PITCH 16
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 qua_gain_pitch[NB_QUA_PITCH];
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: q_gain_pitch
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ mode -- enum Mode -- AMR mode
+ gp_limit -- Word16 -- pitch gain limit
+ gain -- Pointer to Word16 -- Pitch gain (unquant/quant), Q14
+
+ Outputs:
+ gain -- Pointer to Word16 -- Pitch gain (unquant/quant), Q14
+
+ gain_cand -- Array of type Word16 -- pitch gain candidates (3),
+ MR795 only, Q14
+
+ gain_cind -- Array of type Word16 -- pitch gain cand. indices (3),
+ MR795 only, Q0
+
+ pOverflow -- Pointer to Flag -- overflow indicator
+
+ Returns:
+ Word16 -- index of quantization
+
+ Global Variables Used:
+ qua_gain_pitch
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ q_gain_p.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 q_gain_pitch( /* Return index of quantization */
+ enum Mode mode, /* i : AMR mode */
+ Word16 gp_limit, /* i : pitch gain limit */
+ Word16 *gain, /* i/o: Pitch gain (unquant/quant), Q14 */
+ Word16 gain_cand[], /* o : pitch gain candidates (3), MR795 only, Q14 */
+ Word16 gain_cind[], /* o : pitch gain cand. indices (3),MR795 only, Q0 */
+ Flag *pOverflow
+)
+{
+ Word16 i;
+ Word16 index;
+ Word16 err;
+ Word16 err_min;
+
+ err_min = sub(*gain, qua_gain_pitch[0], pOverflow);
+ err_min = abs_s(err_min);
+
+ index = 0;
+
+ for (i = 1; i < NB_QUA_PITCH; i++)
+ {
+ if (qua_gain_pitch[i] <= gp_limit)
+ {
+ err = sub(*gain, qua_gain_pitch[i], pOverflow);
+ err = abs_s(err);
+
+ if (err < err_min)
+ {
+ err_min = err;
+ index = i;
+ }
+ }
+ }
+
+ if (mode == MR795)
+ {
+ /* in MR795 mode, compute three gain_pit candidates around the index
+ * found in the quantization loop: the index found and the two direct
+ * neighbours, except for the extreme cases (i=0 or i=NB_QUA_PITCH-1),
+ * where the direct neighbour and the neighbour to that is used.
+ */
+ Word16 ii;
+
+ if (index == 0)
+ {
+ ii = index;
+ }
+ else
+ {
+ if (index == (NB_QUA_PITCH - 1) ||
+ (qua_gain_pitch[index+1] > gp_limit))
+ {
+ ii = index - 2;
+ }
+ else
+ {
+ ii = index - 1;
+ }
+ }
+
+ /* store candidate indices and values */
+ for (i = 0; i < 3; i++)
+ {
+ gain_cind[i] = ii;
+ gain_cand[i] = qua_gain_pitch[ii];
+
+ ii = add(ii, 1, pOverflow);
+ }
+
+ *gain = qua_gain_pitch[index];
+ }
+ else
+ {
+ /* in MR122 mode, just return the index and gain pitch found.
+ * If bitexactness is required, mask away the two LSBs (because
+ * in the original EFR, gain_pit was scaled Q12)
+ */
+ if (mode == MR122)
+ {
+ /* clear 2 LSBits */
+ *gain = qua_gain_pitch[index] & 0xFFFC;
+ }
+ else
+ {
+ *gain = qua_gain_pitch[index];
+ }
+ }
+ return index;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/q_gain_p.h b/media/libstagefright/codecs/amrnb/enc/src/q_gain_p.h
new file mode 100644
index 0000000..233ccb0
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/q_gain_p.h
@@ -0,0 +1,124 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/q_gain_p.h
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the file, q_gain_p.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef q_gain_p_h
+#define q_gain_p_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ Word16 q_gain_pitch( /* Return index of quantization */
+ enum Mode mode, /* i : AMR mode */
+ Word16 gp_limit, /* i : pitch gain limit */
+ Word16 *gain, /* i/o: Pitch gain (unquant/quant), Q14 */
+ Word16 gain_cand[], /* o : pitch gain candidates (3), MR795 only, Q14 */
+ Word16 gain_cind[], /* o : pitch gain cand. indices (3),MR795 only, Q0 */
+ Flag *pOverflow
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* q_gain_p_h */
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp b/media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp
new file mode 100644
index 0000000..f8da589
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/qgain475.cpp
@@ -0,0 +1,1445 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/qgain475.c
+ Funtions: MR475_quant_store_results
+ MR475_update_unq_pred
+ MR475_gain_quant
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ These modules handle the quantization of pitch and codebook gains for MR475.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "qgain475.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "mode.h"
+#include "cnst.h"
+#include "pow2.h"
+#include "log2.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define MR475_VQ_SIZE 256
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/* The table contains the following data:
+ *
+ * g_pitch(0) (Q14) // for sub-
+ * g_fac(0) (Q12) // frame 0 and 2
+ * g_pitch(1) (Q14) // for sub-
+ * g_fac(2) (Q12) // frame 1 and 3
+ *
+ */
+static const Word16 table_gain_MR475[MR475_VQ_SIZE*4] =
+{
+ /*g_pit(0), g_fac(0), g_pit(1), g_fac(1) */
+ 812, 128, 542, 140,
+ 2873, 1135, 2266, 3402,
+ 2067, 563, 12677, 647,
+ 4132, 1798, 5601, 5285,
+ 7689, 374, 3735, 441,
+ 10912, 2638, 11807, 2494,
+ 20490, 797, 5218, 675,
+ 6724, 8354, 5282, 1696,
+ 1488, 428, 5882, 452,
+ 5332, 4072, 3583, 1268,
+ 2469, 901, 15894, 1005,
+ 14982, 3271, 10331, 4858,
+ 3635, 2021, 2596, 835,
+ 12360, 4892, 12206, 1704,
+ 13432, 1604, 9118, 2341,
+ 3968, 1538, 5479, 9936,
+ 3795, 417, 1359, 414,
+ 3640, 1569, 7995, 3541,
+ 11405, 645, 8552, 635,
+ 4056, 1377, 16608, 6124,
+ 11420, 700, 2007, 607,
+ 12415, 1578, 11119, 4654,
+ 13680, 1708, 11990, 1229,
+ 7996, 7297, 13231, 5715,
+ 2428, 1159, 2073, 1941,
+ 6218, 6121, 3546, 1804,
+ 8925, 1802, 8679, 1580,
+ 13935, 3576, 13313, 6237,
+ 6142, 1130, 5994, 1734,
+ 14141, 4662, 11271, 3321,
+ 12226, 1551, 13931, 3015,
+ 5081, 10464, 9444, 6706,
+ 1689, 683, 1436, 1306,
+ 7212, 3933, 4082, 2713,
+ 7793, 704, 15070, 802,
+ 6299, 5212, 4337, 5357,
+ 6676, 541, 6062, 626,
+ 13651, 3700, 11498, 2408,
+ 16156, 716, 12177, 751,
+ 8065, 11489, 6314, 2256,
+ 4466, 496, 7293, 523,
+ 10213, 3833, 8394, 3037,
+ 8403, 966, 14228, 1880,
+ 8703, 5409, 16395, 4863,
+ 7420, 1979, 6089, 1230,
+ 9371, 4398, 14558, 3363,
+ 13559, 2873, 13163, 1465,
+ 5534, 1678, 13138, 14771,
+ 7338, 600, 1318, 548,
+ 4252, 3539, 10044, 2364,
+ 10587, 622, 13088, 669,
+ 14126, 3526, 5039, 9784,
+ 15338, 619, 3115, 590,
+ 16442, 3013, 15542, 4168,
+ 15537, 1611, 15405, 1228,
+ 16023, 9299, 7534, 4976,
+ 1990, 1213, 11447, 1157,
+ 12512, 5519, 9475, 2644,
+ 7716, 2034, 13280, 2239,
+ 16011, 5093, 8066, 6761,
+ 10083, 1413, 5002, 2347,
+ 12523, 5975, 15126, 2899,
+ 18264, 2289, 15827, 2527,
+ 16265, 10254, 14651, 11319,
+ 1797, 337, 3115, 397,
+ 3510, 2928, 4592, 2670,
+ 7519, 628, 11415, 656,
+ 5946, 2435, 6544, 7367,
+ 8238, 829, 4000, 863,
+ 10032, 2492, 16057, 3551,
+ 18204, 1054, 6103, 1454,
+ 5884, 7900, 18752, 3468,
+ 1864, 544, 9198, 683,
+ 11623, 4160, 4594, 1644,
+ 3158, 1157, 15953, 2560,
+ 12349, 3733, 17420, 5260,
+ 6106, 2004, 2917, 1742,
+ 16467, 5257, 16787, 1680,
+ 17205, 1759, 4773, 3231,
+ 7386, 6035, 14342, 10012,
+ 4035, 442, 4194, 458,
+ 9214, 2242, 7427, 4217,
+ 12860, 801, 11186, 825,
+ 12648, 2084, 12956, 6554,
+ 9505, 996, 6629, 985,
+ 10537, 2502, 15289, 5006,
+ 12602, 2055, 15484, 1653,
+ 16194, 6921, 14231, 5790,
+ 2626, 828, 5615, 1686,
+ 13663, 5778, 3668, 1554,
+ 11313, 2633, 9770, 1459,
+ 14003, 4733, 15897, 6291,
+ 6278, 1870, 7910, 2285,
+ 16978, 4571, 16576, 3849,
+ 15248, 2311, 16023, 3244,
+ 14459, 17808, 11847, 2763,
+ 1981, 1407, 1400, 876,
+ 4335, 3547, 4391, 4210,
+ 5405, 680, 17461, 781,
+ 6501, 5118, 8091, 7677,
+ 7355, 794, 8333, 1182,
+ 15041, 3160, 14928, 3039,
+ 20421, 880, 14545, 852,
+ 12337, 14708, 6904, 1920,
+ 4225, 933, 8218, 1087,
+ 10659, 4084, 10082, 4533,
+ 2735, 840, 20657, 1081,
+ 16711, 5966, 15873, 4578,
+ 10871, 2574, 3773, 1166,
+ 14519, 4044, 20699, 2627,
+ 15219, 2734, 15274, 2186,
+ 6257, 3226, 13125, 19480,
+ 7196, 930, 2462, 1618,
+ 4515, 3092, 13852, 4277,
+ 10460, 833, 17339, 810,
+ 16891, 2289, 15546, 8217,
+ 13603, 1684, 3197, 1834,
+ 15948, 2820, 15812, 5327,
+ 17006, 2438, 16788, 1326,
+ 15671, 8156, 11726, 8556,
+ 3762, 2053, 9563, 1317,
+ 13561, 6790, 12227, 1936,
+ 8180, 3550, 13287, 1778,
+ 16299, 6599, 16291, 7758,
+ 8521, 2551, 7225, 2645,
+ 18269, 7489, 16885, 2248,
+ 17882, 2884, 17265, 3328,
+ 9417, 20162, 11042, 8320,
+ 1286, 620, 1431, 583,
+ 5993, 2289, 3978, 3626,
+ 5144, 752, 13409, 830,
+ 5553, 2860, 11764, 5908,
+ 10737, 560, 5446, 564,
+ 13321, 3008, 11946, 3683,
+ 19887, 798, 9825, 728,
+ 13663, 8748, 7391, 3053,
+ 2515, 778, 6050, 833,
+ 6469, 5074, 8305, 2463,
+ 6141, 1865, 15308, 1262,
+ 14408, 4547, 13663, 4515,
+ 3137, 2983, 2479, 1259,
+ 15088, 4647, 15382, 2607,
+ 14492, 2392, 12462, 2537,
+ 7539, 2949, 12909, 12060,
+ 5468, 684, 3141, 722,
+ 5081, 1274, 12732, 4200,
+ 15302, 681, 7819, 592,
+ 6534, 2021, 16478, 8737,
+ 13364, 882, 5397, 899,
+ 14656, 2178, 14741, 4227,
+ 14270, 1298, 13929, 2029,
+ 15477, 7482, 15815, 4572,
+ 2521, 2013, 5062, 1804,
+ 5159, 6582, 7130, 3597,
+ 10920, 1611, 11729, 1708,
+ 16903, 3455, 16268, 6640,
+ 9306, 1007, 9369, 2106,
+ 19182, 5037, 12441, 4269,
+ 15919, 1332, 15357, 3512,
+ 11898, 14141, 16101, 6854,
+ 2010, 737, 3779, 861,
+ 11454, 2880, 3564, 3540,
+ 9057, 1241, 12391, 896,
+ 8546, 4629, 11561, 5776,
+ 8129, 589, 8218, 588,
+ 18728, 3755, 12973, 3149,
+ 15729, 758, 16634, 754,
+ 15222, 11138, 15871, 2208,
+ 4673, 610, 10218, 678,
+ 15257, 4146, 5729, 3327,
+ 8377, 1670, 19862, 2321,
+ 15450, 5511, 14054, 5481,
+ 5728, 2888, 7580, 1346,
+ 14384, 5325, 16236, 3950,
+ 15118, 3744, 15306, 1435,
+ 14597, 4070, 12301, 15696,
+ 7617, 1699, 2170, 884,
+ 4459, 4567, 18094, 3306,
+ 12742, 815, 14926, 907,
+ 15016, 4281, 15518, 8368,
+ 17994, 1087, 2358, 865,
+ 16281, 3787, 15679, 4596,
+ 16356, 1534, 16584, 2210,
+ 16833, 9697, 15929, 4513,
+ 3277, 1085, 9643, 2187,
+ 11973, 6068, 9199, 4462,
+ 8955, 1629, 10289, 3062,
+ 16481, 5155, 15466, 7066,
+ 13678, 2543, 5273, 2277,
+ 16746, 6213, 16655, 3408,
+ 20304, 3363, 18688, 1985,
+ 14172, 12867, 15154, 15703,
+ 4473, 1020, 1681, 886,
+ 4311, 4301, 8952, 3657,
+ 5893, 1147, 11647, 1452,
+ 15886, 2227, 4582, 6644,
+ 6929, 1205, 6220, 799,
+ 12415, 3409, 15968, 3877,
+ 19859, 2109, 9689, 2141,
+ 14742, 8830, 14480, 2599,
+ 1817, 1238, 7771, 813,
+ 19079, 4410, 5554, 2064,
+ 3687, 2844, 17435, 2256,
+ 16697, 4486, 16199, 5388,
+ 8028, 2763, 3405, 2119,
+ 17426, 5477, 13698, 2786,
+ 19879, 2720, 9098, 3880,
+ 18172, 4833, 17336, 12207,
+ 5116, 996, 4935, 988,
+ 9888, 3081, 6014, 5371,
+ 15881, 1667, 8405, 1183,
+ 15087, 2366, 19777, 7002,
+ 11963, 1562, 7279, 1128,
+ 16859, 1532, 15762, 5381,
+ 14708, 2065, 20105, 2155,
+ 17158, 8245, 17911, 6318,
+ 5467, 1504, 4100, 2574,
+ 17421, 6810, 5673, 2888,
+ 16636, 3382, 8975, 1831,
+ 20159, 4737, 19550, 7294,
+ 6658, 2781, 11472, 3321,
+ 19397, 5054, 18878, 4722,
+ 16439, 2373, 20430, 4386,
+ 11353, 26526, 11593, 3068,
+ 2866, 1566, 5108, 1070,
+ 9614, 4915, 4939, 3536,
+ 7541, 878, 20717, 851,
+ 6938, 4395, 16799, 7733,
+ 10137, 1019, 9845, 964,
+ 15494, 3955, 15459, 3430,
+ 18863, 982, 20120, 963,
+ 16876, 12887, 14334, 4200,
+ 6599, 1220, 9222, 814,
+ 16942, 5134, 5661, 4898,
+ 5488, 1798, 20258, 3962,
+ 17005, 6178, 17929, 5929,
+ 9365, 3420, 7474, 1971,
+ 19537, 5177, 19003, 3006,
+ 16454, 3788, 16070, 2367,
+ 8664, 2743, 9445, 26358,
+ 10856, 1287, 3555, 1009,
+ 5606, 3622, 19453, 5512,
+ 12453, 797, 20634, 911,
+ 15427, 3066, 17037, 10275,
+ 18883, 2633, 3913, 1268,
+ 19519, 3371, 18052, 5230,
+ 19291, 1678, 19508, 3172,
+ 18072, 10754, 16625, 6845,
+ 3134, 2298, 10869, 2437,
+ 15580, 6913, 12597, 3381,
+ 11116, 3297, 16762, 2424,
+ 18853, 6715, 17171, 9887,
+ 12743, 2605, 8937, 3140,
+ 19033, 7764, 18347, 3880,
+ 20475, 3682, 19602, 3380,
+ 13044, 19373, 10526, 23124
+};
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: MR475_quant_store_results
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pred_st = pointer to structure of type gc_predState
+ p = pointer to selected quantizer table entry (const Word16)
+ gcode0 = predicted CB gain (Word16)
+ exp_gcode0 = exponent of predicted CB gain (Word16)
+ gain_pit = pointer to Pitch gain (Word16)
+ gain_cod = pointer to Code gain (Word16)
+
+ Outputs:
+ pred_st points to the updated structure of type gc_predState
+ gain_pit points to Pitch gain
+ gain_cod points to Code gain
+ pOverflow points to overflow indicator (Flag)
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function calculates the final fixed codebook gain and the predictor
+ update values, and updates the gain predictor.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ qgain475.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+static void MR475_quant_store_results(
+
+ gc_predState *pred_st, // i/o: gain predictor state struct
+ const Word16 *p, // i : pointer to selected quantizer table entry
+ Word16 gcode0, // i : predicted CB gain, Q(14 - exp_gcode0)
+ Word16 exp_gcode0, // i : exponent of predicted CB gain, Q0
+ Word16 *gain_pit, // o : Pitch gain, Q14
+ Word16 *gain_cod // o : Code gain, Q1
+)
+{
+
+ Word16 g_code, exp, frac, tmp;
+ Word32 L_tmp;
+
+ Word16 qua_ener_MR122; // o : quantized energy error, MR122 version Q10
+ Word16 qua_ener; // o : quantized energy error, Q10
+
+ // Read the quantized gains
+ *gain_pit = *p++;
+ g_code = *p++;
+
+ //------------------------------------------------------------------*
+ * calculate final fixed codebook gain: *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * gc = gc0 * g *
+ *------------------------------------------------------------------
+
+ L_tmp = L_mult(g_code, gcode0);
+ L_tmp = L_shr(L_tmp, sub(10, exp_gcode0));
+ *gain_cod = extract_h(L_tmp);
+
+ //------------------------------------------------------------------*
+ * calculate predictor update values and update gain predictor: *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * qua_ener = log2(g) *
+ * qua_ener_MR122 = 20*log10(g) *
+ *------------------------------------------------------------------
+
+ Log2 (L_deposit_l (g_code), &exp, &frac); // Log2(x Q12) = log2(x) + 12
+ exp = sub(exp, 12);
+
+ tmp = shr_r (frac, 5);
+ qua_ener_MR122 = add (tmp, shl (exp, 10));
+
+ L_tmp = Mpy_32_16(exp, frac, 24660); // 24660 Q12 ~= 6.0206 = 20*log10(2)
+ qua_ener = pv_round (L_shl (L_tmp, 13)); // Q12 * Q0 = Q13 -> Q10
+
+ gc_pred_update(pred_st, qua_ener_MR122, qua_ener);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void MR475_quant_store_results(
+ gc_predState *pred_st, /* i/o: gain predictor state struct */
+ const Word16 *p, /* i : pointer to selected quantizer table entry */
+ Word16 gcode0, /* i : predicted CB gain, Q(14 - exp_gcode0) */
+ Word16 exp_gcode0, /* i : exponent of predicted CB gain, Q0 */
+ Word16 *gain_pit, /* o : Pitch gain, Q14 */
+ Word16 *gain_cod, /* o : Code gain, Q1 */
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ Word16 g_code;
+ Word16 exp;
+ Word16 frac;
+ Word16 tmp;
+ Word32 L_tmp;
+
+ Word16 qua_ener_MR122; /* o : quantized energy error, MR122 version Q10 */
+ Word16 qua_ener; /* o : quantized energy error, Q10 */
+
+
+ /* Read the quantized gains */
+ *gain_pit = *p++;
+ g_code = *p++;
+
+ /*------------------------------------------------------------------*
+ * calculate final fixed codebook gain: *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * gc = gc0 * g *
+ *------------------------------------------------------------------*/
+
+ L_tmp = ((Word32) g_code * gcode0) << 1;
+ tmp = 10 - exp_gcode0;
+ L_tmp = L_shr(L_tmp, tmp, pOverflow);
+ *gain_cod = (Word16)(L_tmp >> 16);
+
+ /*------------------------------------------------------------------*
+ * calculate predictor update values and update gain predictor: *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * qua_ener = log2(g) *
+ * qua_ener_MR122 = 20*log10(g) *
+ *------------------------------------------------------------------*/
+
+ /* Log2(x Q12) = log2(x) + 12 */
+ Log2((Word32) g_code, &exp, &frac, pOverflow);
+ exp -= 12;
+
+ tmp = shr_r(frac, 5, pOverflow);
+ qua_ener_MR122 = exp << 10;
+ qua_ener_MR122 = tmp + qua_ener_MR122;
+
+ /* 24660 Q12 ~= 6.0206 = 20*log10(2) */
+ L_tmp = Mpy_32_16(exp, frac, 24660, pOverflow);
+ L_tmp = L_tmp << 13;
+
+ /* Q12 * Q0 = Q13 -> Q10 */
+ qua_ener = (Word16)((L_tmp + (Word32) 0x00008000L) >> 16);
+
+ gc_pred_update(pred_st, qua_ener_MR122, qua_ener);
+
+ return;
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: MR475_update_unq_pred
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pred_st = pointer to structure of type gc_predState
+ exp_gcode0 = predicted CB gain (exponent MSW) (Word16)
+ frac_gcode0 = predicted CB gain (exponent LSW) (Word16)
+ cod_gain_exp = optimum codebook gain (exponent)(Word16)
+ cod_gain_frac = optimum codebook gain (fraction) (Word16)
+
+ Outputs:
+ pred_st points to the updated structure of type gc_predState
+ pOverflow points to overflow indicator (Flag)
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This module uses the optimum codebook gain and updates the "unquantized"
+ gain predictor with the (bounded) prediction error.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ qgain475.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void
+MR475_update_unq_pred(
+ gc_predState *pred_st, // i/o: gain predictor state struct
+ Word16 exp_gcode0, // i : predicted CB gain (exponent MSW), Q0
+ Word16 frac_gcode0, // i : predicted CB gain (exponent LSW), Q15
+ Word16 cod_gain_exp, // i : optimum codebook gain (exponent), Q0
+ Word16 cod_gain_frac // i : optimum codebook gain (fraction), Q15
+)
+{
+ Word16 tmp, exp, frac;
+ Word16 qua_ener, qua_ener_MR122;
+ Word32 L_tmp;
+
+ // calculate prediction error factor (given optimum CB gain gcu):
+ // predErrFact = gcu / gcode0
+ // (limit to MIN_PRED_ERR_FACT <= predErrFact <= MAX_PRED_ERR_FACT
+ // -> limit qua_ener*)
+ //
+ // calculate prediction error (log):
+ //
+ // qua_ener_MR122 = log2(predErrFact)
+ // qua_ener = 20*log10(predErrFact)
+
+ if (cod_gain_frac <= 0)
+ {
+ // if gcu <= 0 -> predErrFact = 0 < MIN_PRED_ERR_FACT
+ // -> set qua_ener(_MR122) directly
+ qua_ener = MIN_QUA_ENER;
+ qua_ener_MR122 = MIN_QUA_ENER_MR122;
+ }
+ else
+ {
+ // convert gcode0 from DPF to standard fraction/exponent format
+ // with normalized frac, i.e. 16384 <= frac <= 32767
+ // Note: exponent correction (exp=exp-14) is done after div_s
+ frac_gcode0 = extract_l (Pow2 (14, frac_gcode0));
+
+ // make sure cod_gain_frac < frac_gcode0 for div_s
+ if (sub(cod_gain_frac, frac_gcode0) >= 0)
+ {
+ cod_gain_frac = shr (cod_gain_frac, 1);
+ cod_gain_exp = add (cod_gain_exp, 1);
+ }
+
+ // predErrFact
+ // = gcu / gcode0
+ // = cod_gain_frac/frac_gcode0 * 2^(cod_gain_exp-(exp_gcode0-14))
+ // = div_s (c_g_f, frac_gcode0)*2^-15 * 2^(c_g_e-exp_gcode0+14)
+ // = div_s * 2^(cod_gain_exp-exp_gcode0 - 1)
+
+ frac = div_s (cod_gain_frac, frac_gcode0);
+ tmp = sub (sub (cod_gain_exp, exp_gcode0), 1);
+
+ Log2 (L_deposit_l (frac), &exp, &frac);
+ exp = add (exp, tmp);
+
+ // calculate prediction error (log2, Q10)
+ qua_ener_MR122 = shr_r (frac, 5);
+ qua_ener_MR122 = add (qua_ener_MR122, shl (exp, 10));
+
+ if (sub(qua_ener_MR122, MIN_QUA_ENER_MR122) < 0)
+ {
+ qua_ener = MIN_QUA_ENER;
+ qua_ener_MR122 = MIN_QUA_ENER_MR122;
+ }
+ else if (sub(qua_ener_MR122, MAX_QUA_ENER_MR122) > 0)
+ {
+ qua_ener = MAX_QUA_ENER;
+ qua_ener_MR122 = MAX_QUA_ENER_MR122;
+ }
+ else
+ {
+ // calculate prediction error (20*log10, Q10)
+ L_tmp = Mpy_32_16(exp, frac, 24660);
+ // 24660 Q12 ~= 6.0206 = 20*log10(2)
+ qua_ener = pv_round (L_shl (L_tmp, 13));
+ // Q12 * Q0 = Q13 -> Q26 -> Q10
+ }
+ }
+
+ // update MA predictor memory
+ gc_pred_update(pred_st, qua_ener_MR122, qua_ener);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void MR475_update_unq_pred(
+ gc_predState *pred_st, /* i/o: gain predictor state struct */
+ Word16 exp_gcode0, /* i : predicted CB gain (exponent MSW), Q0 */
+ Word16 frac_gcode0, /* i : predicted CB gain (exponent LSW), Q15 */
+ Word16 cod_gain_exp, /* i : optimum codebook gain (exponent), Q0 */
+ Word16 cod_gain_frac, /* i : optimum codebook gain (fraction), Q15 */
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ Word16 tmp;
+ Word16 exp;
+ Word16 frac;
+ Word16 qua_ener;
+ Word16 qua_ener_MR122;
+ Word32 L_tmp;
+
+ /* calculate prediction error factor (given optimum CB gain gcu):
+ *
+ * predErrFact = gcu / gcode0
+ * (limit to MIN_PRED_ERR_FACT <= predErrFact <= MAX_PRED_ERR_FACT
+ * -> limit qua_ener*)
+ *
+ * calculate prediction error (log):
+ *
+ * qua_ener_MR122 = log2(predErrFact)
+ * qua_ener = 20*log10(predErrFact)
+ *
+ */
+
+ if (cod_gain_frac <= 0)
+ {
+ /* if gcu <= 0 -> predErrFact = 0 < MIN_PRED_ERR_FACT */
+ /* -> set qua_ener(_MR122) directly */
+ qua_ener = MIN_QUA_ENER;
+ qua_ener_MR122 = MIN_QUA_ENER_MR122;
+ }
+ else
+ {
+ /* convert gcode0 from DPF to standard fraction/exponent format */
+ /* with normalized frac, i.e. 16384 <= frac <= 32767 */
+ /* Note: exponent correction (exp=exp-14) is done after div_s */
+ frac_gcode0 = (Word16)(Pow2(14, frac_gcode0, pOverflow));
+
+ /* make sure cod_gain_frac < frac_gcode0 for div_s */
+ if (cod_gain_frac >= frac_gcode0)
+ {
+ cod_gain_frac >>= 1;
+ cod_gain_exp += 1;
+ }
+
+ /*
+ predErrFact
+ = gcu / gcode0
+ = cod_gain_frac/frac_gcode0 * 2^(cod_gain_exp-(exp_gcode0-14))
+ = div_s (c_g_f, frac_gcode0)*2^-15 * 2^(c_g_e-exp_gcode0+14)
+ = div_s * 2^(cod_gain_exp-exp_gcode0 - 1)
+ */
+ frac = div_s(cod_gain_frac, frac_gcode0);
+ tmp = cod_gain_exp - exp_gcode0;
+ tmp -= 1;
+
+ Log2((Word32) frac, &exp, &frac, pOverflow);
+ exp += tmp;
+
+ /* calculate prediction error (log2, Q10) */
+ qua_ener_MR122 = shr_r(frac, 5, pOverflow);
+ tmp = exp << 10;
+ qua_ener_MR122 += tmp;
+
+ if (qua_ener_MR122 > MAX_QUA_ENER_MR122)
+ {
+ qua_ener = MAX_QUA_ENER;
+ qua_ener_MR122 = MAX_QUA_ENER_MR122;
+ }
+ else
+ {
+ /* calculate prediction error (20*log10, Q10) */
+ L_tmp = Mpy_32_16(exp, frac, 24660, pOverflow);
+ /* 24660 Q12 ~= 6.0206 = 20*log10(2) */
+ L_tmp = L_shl(L_tmp, 13, pOverflow);
+ qua_ener = pv_round(L_tmp, pOverflow);
+
+ /* Q12 * Q0 = Q13 -> Q26 -> Q10 */
+ }
+ }
+
+ /* update MA predictor memory */
+ gc_pred_update(pred_st, qua_ener_MR122, qua_ener);
+
+
+ return;
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: MR475_gain_quant
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ pred_st = pointer to structure of type gc_predState
+ sf0_exp_gcode0 = predicted CB gain (exponent) (Word16)
+ f0_frac_gcode0 = predicted CB gain (fraction) (Word16)
+ sf0_exp_coeff = energy coeff. (exponent part) (Word16)
+ sf0_frac_coeff = energy coeff. ((fraction part) (Word16)
+ sf0_exp_target_en = exponent of target energy (Word16)
+ sf0_frac_target_en = fraction of target energy (Word16)
+ sf1_code_nosharp = innovative codebook vector (Word16)
+ sf1_exp_gcode0 = predicted CB gain (exponent) (Word16)
+ sf1_frac_gcode0 = predicted CB gain (fraction) (Word16)
+ sf1_exp_coeff = energy coeff. (exponent part) (Word16)
+ sf1_frac_coeff = energy coeff. (fraction part) (Word16)
+ sf1_exp_target_en = exponent of target energy (Word16)
+ sf1_frac_target_en = fraction of target energy (Word16)
+ gp_limit = pitch gain limit (Word16)
+ sf0_gain_pit = pointer to Pitch gain (Word16)
+ sf0_gain_cod = pointer to Code gain (Word16)
+ sf1_gain_pit = pointer to Pitch gain (Word16)
+ sf1_gain_cod = pointer to Code gain (Word16)
+
+ Outputs:
+ pred_st points to the updated structure of type gc_predState
+ sf0_gain_pit points to Pitch gain
+ sf0_gain_cod points to Code gain
+ sf1_gain_pit points to Pitch gain
+ sf1_gain_cod points to Code gain
+
+ Returns:
+ index = index of quantization
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This module provides quantization of pitch and codebook gains for two
+ subframes using the predicted codebook gain.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ qgain475.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16
+MR475_gain_quant( // o : index of quantization.
+ gc_predState *pred_st, // i/o: gain predictor state struct
+
+ // data from subframe 0 (or 2)
+ Word16 sf0_exp_gcode0, // i : predicted CB gain (exponent), Q0
+ Word16 sf0_frac_gcode0, // i : predicted CB gain (fraction), Q15
+ Word16 sf0_exp_coeff[], // i : energy coeff. (5), exponent part, Q0
+ Word16 sf0_frac_coeff[], // i : energy coeff. (5), fraction part, Q15
+ // (frac_coeff and exp_coeff computed in
+ // calc_filt_energies())
+ Word16 sf0_exp_target_en, // i : exponent of target energy, Q0
+ Word16 sf0_frac_target_en, // i : fraction of target energy, Q15
+
+ // data from subframe 1 (or 3)
+ Word16 sf1_code_nosharp[], // i : innovative codebook vector (L_SUBFR)
+ // (whithout pitch sharpening)
+ Word16 sf1_exp_gcode0, // i : predicted CB gain (exponent), Q0
+ Word16 sf1_frac_gcode0, // i : predicted CB gain (fraction), Q15
+ Word16 sf1_exp_coeff[], // i : energy coeff. (5), exponent part, Q0
+ Word16 sf1_frac_coeff[], // i : energy coeff. (5), fraction part, Q15
+ // (frac_coeff and exp_coeff computed in
+ // calc_filt_energies())
+ Word16 sf1_exp_target_en, // i : exponent of target energy, Q0
+ Word16 sf1_frac_target_en, // i : fraction of target energy, Q15
+
+ Word16 gp_limit, // i : pitch gain limit
+
+ Word16 *sf0_gain_pit, // o : Pitch gain, Q14
+ Word16 *sf0_gain_cod, // o : Code gain, Q1
+
+ Word16 *sf1_gain_pit, // o : Pitch gain, Q14
+ Word16 *sf1_gain_cod // o : Code gain, Q1
+)
+{
+ const Word16 *p;
+ Word16 i, index = 0;
+ Word16 tmp;
+ Word16 exp;
+ Word16 sf0_gcode0, sf1_gcode0;
+ Word16 g_pitch, g2_pitch, g_code, g2_code, g_pit_cod;
+ Word16 coeff[10], coeff_lo[10], exp_max[10]; // 0..4: sf0; 5..9: sf1
+ Word32 L_tmp, dist_min;
+
+ *-------------------------------------------------------------------*
+ * predicted codebook gain *
+ * ~~~~~~~~~~~~~~~~~~~~~~~ *
+ * gc0 = 2^exp_gcode0 + 2^frac_gcode0 *
+ * *
+ * gcode0 (Q14) = 2^14*2^frac_gcode0 = gc0 * 2^(14-exp_gcode0) *
+ *-------------------------------------------------------------------*
+
+ sf0_gcode0 = extract_l(Pow2(14, sf0_frac_gcode0));
+ sf1_gcode0 = extract_l(Pow2(14, sf1_frac_gcode0));
+
+ * For each subframe, the error energy (sum) to be minimized consists
+ * of five terms, t[0..4].
+ *
+ * t[0] = gp^2 * <y1 y1>
+ * t[1] = -2*gp * <xn y1>
+ * t[2] = gc^2 * <y2 y2>
+ * t[3] = -2*gc * <xn y2>
+ * t[4] = 2*gp*gc * <y1 y2>
+ *
+
+ // sf 0
+ // determine the scaling exponent for g_code: ec = ec0 - 11
+ exp = sub(sf0_exp_gcode0, 11);
+
+ // calculate exp_max[i] = s[i]-1
+ exp_max[0] = sub(sf0_exp_coeff[0], 13);
+ exp_max[1] = sub(sf0_exp_coeff[1], 14);
+ exp_max[2] = add(sf0_exp_coeff[2], add(15, shl(exp, 1)));
+ exp_max[3] = add(sf0_exp_coeff[3], exp);
+ exp_max[4] = add(sf0_exp_coeff[4], add(1, exp));
+
+ // sf 1
+ // determine the scaling exponent for g_code: ec = ec0 - 11
+ exp = sub(sf1_exp_gcode0, 11);
+
+ // calculate exp_max[i] = s[i]-1
+ exp_max[5] = sub(sf1_exp_coeff[0], 13);
+ exp_max[6] = sub(sf1_exp_coeff[1], 14);
+ exp_max[7] = add(sf1_exp_coeff[2], add(15, shl(exp, 1)));
+ exp_max[8] = add(sf1_exp_coeff[3], exp);
+ exp_max[9] = add(sf1_exp_coeff[4], add(1, exp));
+
+ *-------------------------------------------------------------------*
+ * Gain search equalisation: *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * The MSE for the two subframes is weighted differently if there *
+ * is a big difference in the corresponding target energies *
+ *-------------------------------------------------------------------*
+
+ // make the target energy exponents the same by de-normalizing the
+ // fraction of the smaller one. This is necessary to be able to compare
+ // them
+
+ exp = sf0_exp_target_en - sf1_exp_target_en;
+ if (exp > 0)
+ {
+ sf1_frac_target_en = shr (sf1_frac_target_en, exp);
+ }
+ else
+ {
+ sf0_frac_target_en = shl (sf0_frac_target_en, exp);
+ }
+
+ // assume no change of exponents
+ exp = 0;
+
+ // test for target energy difference; set exp to +1 or -1 to scale
+ // up/down coefficients for sf 1
+
+ tmp = shr_r (sf1_frac_target_en, 1); // tmp = ceil(0.5*en(sf1))
+ if (sub (tmp, sf0_frac_target_en) > 0) // tmp > en(sf0)?
+ {
+ // target_energy(sf1) > 2*target_energy(sf0)
+ // -> scale up MSE(sf0) by 2 by adding 1 to exponents 0..4
+ exp = 1;
+ }
+ else
+ {
+ tmp = shr (add (sf0_frac_target_en, 3), 2); // tmp=ceil(0.25*en(sf0))
+ if (sub (tmp, sf1_frac_target_en) > 0) // tmp > en(sf1)?
+ {
+ // target_energy(sf1) < 0.25*target_energy(sf0)
+ // -> scale down MSE(sf0) by 0.5 by subtracting 1 from
+ // coefficients 0..4
+ exp = -1;
+ }
+ }
+
+ for (i = 0; i < 5; i++)
+ {
+ exp_max[i] = add (exp_max[i], exp);
+ }
+
+ *-------------------------------------------------------------------*
+ * Find maximum exponent: *
+ * ~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * For the sum operation, all terms must have the same scaling; *
+ * that scaling should be low enough to prevent overflow. There- *
+ * fore, the maximum scale is determined and all coefficients are *
+ * re-scaled: *
+ * *
+ * exp = max(exp_max[i]) + 1; *
+ * e = exp_max[i]-exp; e <= 0! *
+ * c[i] = c[i]*2^e *
+ *-------------------------------------------------------------------*
+
+ exp = exp_max[0];
+ for (i = 1; i < 10; i++)
+ {
+ if (sub(exp_max[i], exp) > 0)
+ {
+ exp = exp_max[i];
+ }
+ }
+ exp = add(exp, 1); // To avoid overflow
+
+ p = &sf0_frac_coeff[0];
+ for (i = 0; i < 5; i++) {
+ tmp = sub(exp, exp_max[i]);
+ L_tmp = L_deposit_h(*p++);
+ L_tmp = L_shr(L_tmp, tmp);
+ L_Extract(L_tmp, &coeff[i], &coeff_lo[i]);
+ }
+ p = &sf1_frac_coeff[0];
+ for (; i < 10; i++) {
+ tmp = sub(exp, exp_max[i]);
+ L_tmp = L_deposit_h(*p++);
+ L_tmp = L_shr(L_tmp, tmp);
+ L_Extract(L_tmp, &coeff[i], &coeff_lo[i]);
+ }
+
+ //-------------------------------------------------------------------*
+ * Codebook search: *
+ * ~~~~~~~~~~~~~~~~ *
+ * *
+ * For each pair (g_pitch, g_fac) in the table calculate the *
+ * terms t[0..4] and sum them up; the result is the mean squared *
+ * error for the quantized gains from the table. The index for the *
+ * minimum MSE is stored and finally used to retrieve the quantized *
+ * gains *
+ *-------------------------------------------------------------------
+
+ // start with "infinite" MSE
+ dist_min = MAX_32;
+
+ p = &table_gain_MR475[0];
+
+ for (i = 0; i < MR475_VQ_SIZE; i++)
+ {
+ // subframe 0 (and 2) calculations
+ g_pitch = *p++;
+ g_code = *p++;
+
+ g_code = mult(g_code, sf0_gcode0);
+ g2_pitch = mult(g_pitch, g_pitch);
+ g2_code = mult(g_code, g_code);
+ g_pit_cod = mult(g_code, g_pitch);
+
+ L_tmp = Mpy_32_16( coeff[0], coeff_lo[0], g2_pitch);
+ L_tmp = Mac_32_16(L_tmp, coeff[1], coeff_lo[1], g_pitch);
+ L_tmp = Mac_32_16(L_tmp, coeff[2], coeff_lo[2], g2_code);
+ L_tmp = Mac_32_16(L_tmp, coeff[3], coeff_lo[3], g_code);
+ L_tmp = Mac_32_16(L_tmp, coeff[4], coeff_lo[4], g_pit_cod);
+
+ tmp = sub (g_pitch, gp_limit);
+
+ // subframe 1 (and 3) calculations
+ g_pitch = *p++;
+ g_code = *p++;
+
+ if (tmp <= 0 && sub(g_pitch, gp_limit) <= 0)
+ {
+ g_code = mult(g_code, sf1_gcode0);
+ g2_pitch = mult(g_pitch, g_pitch);
+ g2_code = mult(g_code, g_code);
+ g_pit_cod = mult(g_code, g_pitch);
+
+ L_tmp = Mac_32_16(L_tmp, coeff[5], coeff_lo[5], g2_pitch);
+ L_tmp = Mac_32_16(L_tmp, coeff[6], coeff_lo[6], g_pitch);
+ L_tmp = Mac_32_16(L_tmp, coeff[7], coeff_lo[7], g2_code);
+ L_tmp = Mac_32_16(L_tmp, coeff[8], coeff_lo[8], g_code);
+ L_tmp = Mac_32_16(L_tmp, coeff[9], coeff_lo[9], g_pit_cod);
+
+ // store table index if MSE for this index is lower
+ than the minimum MSE seen so far
+ if (L_sub(L_tmp, dist_min) < (Word32) 0)
+ {
+ dist_min = L_tmp;
+ index = i;
+ }
+ }
+ }
+
+ *------------------------------------------------------------------*
+ * read quantized gains and update MA predictor memories *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ *------------------------------------------------------------------*
+
+ // for subframe 0, the pre-calculated gcode0/exp_gcode0 are the same
+ // as those calculated from the "real" predictor using quantized gains
+ tmp = shl(index, 2);
+ MR475_quant_store_results(pred_st,
+ &table_gain_MR475[tmp],
+ sf0_gcode0,
+ sf0_exp_gcode0,
+ sf0_gain_pit,
+ sf0_gain_cod);
+
+ // calculate new predicted gain for subframe 1 (this time using
+ // the real, quantized gains)
+ gc_pred(pred_st, MR475, sf1_code_nosharp,
+ &sf1_exp_gcode0, &sf1_frac_gcode0,
+ &sf0_exp_gcode0, &sf0_gcode0); // last two args are dummy
+ sf1_gcode0 = extract_l(Pow2(14, sf1_frac_gcode0));
+
+ tmp = add (tmp, 2);
+ MR475_quant_store_results(pred_st,
+ &table_gain_MR475[tmp],
+ sf1_gcode0,
+ sf1_exp_gcode0,
+ sf1_gain_pit,
+ sf1_gain_cod);
+
+ return index;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 MR475_gain_quant( /* o : index of quantization. */
+ gc_predState *pred_st, /* i/o: gain predictor state struct */
+
+ /* data from subframe 0 (or 2) */
+ Word16 sf0_exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
+ Word16 sf0_frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
+ Word16 sf0_exp_coeff[], /* i : energy coeff. (5), exponent part, Q0 */
+ Word16 sf0_frac_coeff[], /* i : energy coeff. (5), fraction part, Q15 */
+ /* (frac_coeff and exp_coeff computed in */
+ /* calc_filt_energies()) */
+ Word16 sf0_exp_target_en, /* i : exponent of target energy, Q0 */
+ Word16 sf0_frac_target_en, /* i : fraction of target energy, Q15 */
+
+ /* data from subframe 1 (or 3) */
+ Word16 sf1_code_nosharp[], /* i : innovative codebook vector (L_SUBFR) */
+ /* (whithout pitch sharpening) */
+ Word16 sf1_exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
+ Word16 sf1_frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
+ Word16 sf1_exp_coeff[], /* i : energy coeff. (5), exponent part, Q0 */
+ Word16 sf1_frac_coeff[], /* i : energy coeff. (5), fraction part, Q15 */
+ /* (frac_coeff and exp_coeff computed in */
+ /* calc_filt_energies()) */
+ Word16 sf1_exp_target_en, /* i : exponent of target energy, Q0 */
+ Word16 sf1_frac_target_en, /* i : fraction of target energy, Q15 */
+
+ Word16 gp_limit, /* i : pitch gain limit */
+
+ Word16 *sf0_gain_pit, /* o : Pitch gain, Q14 */
+ Word16 *sf0_gain_cod, /* o : Code gain, Q1 */
+
+ Word16 *sf1_gain_pit, /* o : Pitch gain, Q14 */
+ Word16 *sf1_gain_cod, /* o : Code gain, Q1 */
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ const Word16 *p;
+ Word16 i;
+ Word16 index = 0;
+ Word16 tmp;
+ Word16 exp;
+ Word16 sf0_gcode0;
+ Word16 sf1_gcode0;
+ Word16 g_pitch;
+ Word16 g2_pitch;
+ Word16 g_code;
+ Word16 g2_code;
+ Word16 g_pit_cod;
+ Word16 coeff[10];
+ Word16 coeff_lo[10];
+ Word16 exp_max[10]; /* 0..4: sf0; 5..9: sf1 */
+ Word32 L_tmp;
+ Word32 dist_min;
+
+ /*-------------------------------------------------------------------*
+ * predicted codebook gain *
+ * ~~~~~~~~~~~~~~~~~~~~~~~ *
+ * gc0 = 2^exp_gcode0 + 2^frac_gcode0 *
+ * *
+ * gcode0 (Q14) = 2^14*2^frac_gcode0 = gc0 * 2^(14-exp_gcode0) *
+ *-------------------------------------------------------------------*/
+
+ sf0_gcode0 = (Word16)(Pow2(14, sf0_frac_gcode0, pOverflow));
+ sf1_gcode0 = (Word16)(Pow2(14, sf1_frac_gcode0, pOverflow));
+
+ /*
+ * For each subframe, the error energy (sum) to be minimized consists
+ * of five terms, t[0..4].
+ *
+ * t[0] = gp^2 * <y1 y1>
+ * t[1] = -2*gp * <xn y1>
+ * t[2] = gc^2 * <y2 y2>
+ * t[3] = -2*gc * <xn y2>
+ * t[4] = 2*gp*gc * <y1 y2>
+ *
+ */
+
+ /* sf 0 */
+ /* determine the scaling exponent for g_code: ec = ec0 - 11 */
+ exp = sf0_exp_gcode0 - 11;
+
+ /* calculate exp_max[i] = s[i]-1 */
+ exp_max[0] = (sf0_exp_coeff[0] - 13);
+ exp_max[1] = (sf0_exp_coeff[1] - 14);
+ exp_max[2] = (sf0_exp_coeff[2] + (15 + (exp << 1)));
+ exp_max[3] = (sf0_exp_coeff[3] + exp);
+ exp_max[4] = (sf0_exp_coeff[4] + (1 + exp));
+
+ /* sf 1 */
+ /* determine the scaling exponent for g_code: ec = ec0 - 11 */
+ exp = sf1_exp_gcode0 - 11;
+
+ /* calculate exp_max[i] = s[i]-1 */
+ exp_max[5] = (sf1_exp_coeff[0] - 13);
+ exp_max[6] = (sf1_exp_coeff[1] - 14);
+ exp_max[7] = (sf1_exp_coeff[2] + (15 + (exp << 1)));
+ exp_max[8] = (sf1_exp_coeff[3] + exp);
+ exp_max[9] = (sf1_exp_coeff[4] + (1 + exp));
+
+ /*-------------------------------------------------------------------*
+ * Gain search equalisation: *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * The MSE for the two subframes is weighted differently if there *
+ * is a big difference in the corresponding target energies *
+ *-------------------------------------------------------------------*/
+
+ /* make the target energy exponents the same by de-normalizing the
+ fraction of the smaller one. This is necessary to be able to compare
+ them
+ */
+ exp = sf0_exp_target_en - sf1_exp_target_en;
+ if (exp > 0)
+ {
+ sf1_frac_target_en >>= exp;
+ }
+ else
+ {
+ sf0_frac_target_en >>= (-exp);
+ }
+
+ /* assume no change of exponents */
+ exp = 0;
+
+ /* test for target energy difference; set exp to +1 or -1 to scale
+ * up/down coefficients for sf 1
+ */
+ tmp = shr_r(sf1_frac_target_en, 1, pOverflow); /* tmp = ceil(0.5*en(sf1)) */
+
+ if (tmp > sf0_frac_target_en) /* tmp > en(sf0)? */
+ {
+ /*
+ * target_energy(sf1) > 2*target_energy(sf0)
+ * -> scale up MSE(sf0) by 2 by adding 1 to exponents 0..4
+ */
+ exp = 1;
+ }
+ else
+ {
+ tmp = ((sf0_frac_target_en + 3) >> 2); /* tmp=ceil(0.25*en(sf0)) */
+
+ if (tmp > sf1_frac_target_en) /* tmp > en(sf1)? */
+ {
+ /*
+ * target_energy(sf1) < 0.25*target_energy(sf0)
+ * -> scale down MSE(sf0) by 0.5 by subtracting 1 from
+ * coefficients 0..4
+ */
+ exp = -1;
+ }
+ }
+
+ for (i = 0; i < 5; i++)
+ {
+ exp_max[i] += exp;
+ }
+
+ /*-------------------------------------------------------------------*
+ * Find maximum exponent: *
+ * ~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * For the sum operation, all terms must have the same scaling; *
+ * that scaling should be low enough to prevent overflow. There- *
+ * fore, the maximum scale is determined and all coefficients are *
+ * re-scaled: *
+ * *
+ * exp = max(exp_max[i]) + 1; *
+ * e = exp_max[i]-exp; e <= 0! *
+ * c[i] = c[i]*2^e *
+ *-------------------------------------------------------------------*/
+
+ exp = exp_max[0];
+ for (i = 9; i > 0; i--)
+ {
+ if (exp_max[i] > exp)
+ {
+ exp = exp_max[i];
+ }
+ }
+ exp++; /* To avoid overflow */
+
+ p = &sf0_frac_coeff[0];
+ for (i = 0; i < 5; i++)
+ {
+ tmp = (exp - exp_max[i]);
+ L_tmp = ((Word32)(*p++) << 16);
+ L_tmp = L_shr(L_tmp, tmp, pOverflow);
+ coeff[i] = (Word16)(L_tmp >> 16);
+ coeff_lo[i] = (Word16)((L_tmp >> 1) - ((L_tmp >> 16) << 15));
+ }
+ p = &sf1_frac_coeff[0];
+ for (; i < 10; i++)
+ {
+ tmp = exp - exp_max[i];
+ L_tmp = ((Word32)(*p++) << 16);
+ L_tmp = L_shr(L_tmp, tmp, pOverflow);
+ coeff[i] = (Word16)(L_tmp >> 16);
+ coeff_lo[i] = (Word16)((L_tmp >> 1) - ((L_tmp >> 16) << 15));
+ }
+
+
+ /*-------------------------------------------------------------------*
+ * Codebook search: *
+ * ~~~~~~~~~~~~~~~~ *
+ * *
+ * For each pair (g_pitch, g_fac) in the table calculate the *
+ * terms t[0..4] and sum them up; the result is the mean squared *
+ * error for the quantized gains from the table. The index for the *
+ * minimum MSE is stored and finally used to retrieve the quantized *
+ * gains *
+ *-------------------------------------------------------------------*/
+
+ /* start with "infinite" MSE */
+ dist_min = MAX_32;
+
+ p = &table_gain_MR475[0];
+
+ for (i = 0; i < MR475_VQ_SIZE; i++)
+ {
+ /* subframe 0 (and 2) calculations */
+ g_pitch = *p++;
+ g_code = *p++;
+
+ /* Need to be there OKA */
+ g_code = (Word16)(((Word32) g_code * sf0_gcode0) >> 15);
+ g2_pitch = (Word16)(((Word32) g_pitch * g_pitch) >> 15);
+ g2_code = (Word16)(((Word32) g_code * g_code) >> 15);
+ g_pit_cod = (Word16)(((Word32) g_code * g_pitch) >> 15);
+
+
+ L_tmp = Mpy_32_16(coeff[0], coeff_lo[0], g2_pitch, pOverflow) +
+ Mpy_32_16(coeff[1], coeff_lo[1], g_pitch, pOverflow) +
+ Mpy_32_16(coeff[2], coeff_lo[2], g2_code, pOverflow) +
+ Mpy_32_16(coeff[3], coeff_lo[3], g_code, pOverflow) +
+ Mpy_32_16(coeff[4], coeff_lo[4], g_pit_cod, pOverflow);
+
+ tmp = (g_pitch - gp_limit);
+
+ /* subframe 1 (and 3) calculations */
+ g_pitch = *p++;
+ g_code = *p++;
+
+ if ((tmp <= 0) && (g_pitch <= gp_limit))
+ {
+ g_code = (Word16)(((Word32) g_code * sf1_gcode0) >> 15);
+ g2_pitch = (Word16)(((Word32) g_pitch * g_pitch) >> 15);
+ g2_code = (Word16)(((Word32) g_code * g_code) >> 15);
+ g_pit_cod = (Word16)(((Word32) g_code * g_pitch) >> 15);
+
+ L_tmp += (Mpy_32_16(coeff[5], coeff_lo[5], g2_pitch, pOverflow) +
+ Mpy_32_16(coeff[6], coeff_lo[6], g_pitch, pOverflow) +
+ Mpy_32_16(coeff[7], coeff_lo[7], g2_code, pOverflow) +
+ Mpy_32_16(coeff[8], coeff_lo[8], g_code, pOverflow) +
+ Mpy_32_16(coeff[9], coeff_lo[9], g_pit_cod, pOverflow));
+
+ /* store table index if MSE for this index is lower
+ than the minimum MSE seen so far */
+ if (L_tmp < dist_min)
+ {
+ dist_min = L_tmp;
+ index = i;
+ }
+ }
+ }
+
+ /*------------------------------------------------------------------*
+ * read quantized gains and update MA predictor memories *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ *------------------------------------------------------------------*/
+
+ /* for subframe 0, the pre-calculated gcode0/exp_gcode0 are the same
+ as those calculated from the "real" predictor using quantized gains */
+ tmp = index << 2;
+ MR475_quant_store_results(pred_st,
+ &table_gain_MR475[tmp],
+ sf0_gcode0,
+ sf0_exp_gcode0,
+ sf0_gain_pit,
+ sf0_gain_cod,
+ pOverflow);
+
+ /* calculate new predicted gain for subframe 1 (this time using
+ the real, quantized gains) */
+ gc_pred(pred_st, MR475, sf1_code_nosharp,
+ &sf1_exp_gcode0, &sf1_frac_gcode0,
+ &sf0_exp_gcode0, &sf0_gcode0, /* dummy args */
+ pOverflow);
+
+ sf1_gcode0 = (Word16)(Pow2(14, sf1_frac_gcode0, pOverflow));
+
+ tmp += 2;
+ MR475_quant_store_results(
+ pred_st,
+ &table_gain_MR475[tmp],
+ sf1_gcode0,
+ sf1_exp_gcode0,
+ sf1_gain_pit,
+ sf1_gain_cod,
+ pOverflow);
+
+ return(index);
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/qgain475.h b/media/libstagefright/codecs/amrnb/enc/src/qgain475.h
new file mode 100644
index 0000000..3f1f03f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/qgain475.h
@@ -0,0 +1,180 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm-amr/c/include/qgain475.h
+
+ Date: 01/04/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template and copied #defines from qgain475.c file.
+
+ Description: Changed to include pOverflow as a function parameter for all
+ functions in qgain475.c
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains the defines and function prototypes used in the
+ quantization of pitch and codebook gains for MR475.
+
+------------------------------------------------------------------------------
+*/
+#ifndef _QGAIN475_H_
+#define _QGAIN475_H_
+#define qgain475_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "gc_pred.h"
+#include "mode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+ /* minimum allowed gain code prediction error: 102.887/4096 = 0.0251189 */
+#define MIN_QUA_ENER ( -5443) /* Q10 <-> log2 (0.0251189) */
+#define MIN_QUA_ENER_MR122 (-32768) /* Q10 <-> 20*log10(0.0251189) */
+
+ /* minimum allowed gain code prediction error: 32000/4096 = 7.8125 */
+#define MAX_QUA_ENER ( 3037) /* Q10 <-> log2 (7.8125) */
+#define MAX_QUA_ENER_MR122 ( 18284) /* Q10 <-> 20*log10(7.8125) */
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+
+ /*************************************************************************
+ *
+ * FUNCTION: MR475_update_unq_pred()
+ *
+ * PURPOSE: use optimum codebook gain and update "unquantized"
+ * gain predictor with the (bounded) prediction error
+ *
+ *************************************************************************/
+ void
+ MR475_update_unq_pred(
+ gc_predState *pred_st, /* i/o: gain predictor state struct */
+ Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
+ Word16 frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
+ Word16 cod_gain_exp, /* i : optimum codebook gain (exponent), Q0 */
+ Word16 cod_gain_frac, /* i : optimum codebook gain (fraction), Q15 */
+ Flag *pOverflow /* o : overflow indicator */
+ );
+
+ /*************************************************************************
+ *
+ * FUNCTION: MR475_gain_quant()
+ *
+ * PURPOSE: Quantization of pitch and codebook gains for two subframes
+ * (using predicted codebook gain)
+ *
+ *************************************************************************/
+
+ Word16
+ MR475_gain_quant( /* o : index of quantization. */
+ gc_predState *pred_st, /* i/o: gain predictor state struct */
+
+ /* data from subframe 0 (or 2) */
+ Word16 sf0_exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
+ Word16 sf0_frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
+ Word16 sf0_exp_coeff[], /* i : energy coeff. (5), exponent part, Q0 */
+ Word16 sf0_frac_coeff[], /* i : energy coeff. (5), fraction part, Q15 */
+ /* (frac_coeff and exp_coeff computed in */
+ /* calc_filt_energies()) */
+ Word16 sf0_exp_target_en, /* i : exponent of target energy, Q0 */
+ Word16 sf0_frac_target_en, /* i : fraction of target energy, Q15 */
+
+ /* data from subframe 1 (or 3) */
+ Word16 sf1_code_nosharp[], /* i : innovative codebook vector (L_SUBFR) */
+ /* (whithout pitch sharpening) */
+ Word16 sf1_exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
+ Word16 sf1_frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
+ Word16 sf1_exp_coeff[], /* i : energy coeff. (5), exponent part, Q0 */
+ Word16 sf1_frac_coeff[], /* i : energy coeff. (5), fraction part, Q15 */
+ /* (frac_coeff and exp_coeff computed in */
+ /* calc_filt_energies()) */
+ Word16 sf1_exp_target_en, /* i : exponent of target energy, Q0 */
+ Word16 sf1_frac_target_en, /* i : fraction of target energy, Q15 */
+
+ Word16 gp_limit, /* i : pitch gain limit */
+
+ Word16 *sf0_gain_pit, /* o : Pitch gain, Q14 */
+ Word16 *sf0_gain_cod, /* o : Code gain, Q1 */
+
+ Word16 *sf1_gain_pit, /* o : Pitch gain, Q14 */
+ Word16 *sf1_gain_cod, /* o : Code gain, Q1 */
+ Flag *pOverflow /* o : overflow indicator */
+ );
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _QGAIN475_H_ */
diff --git a/media/libstagefright/codecs/amrnb/enc/src/qgain795.cpp b/media/libstagefright/codecs/amrnb/enc/src/qgain795.cpp
new file mode 100644
index 0000000..d09fbe3
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/qgain795.cpp
@@ -0,0 +1,904 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/qgain795.c
+ Functions: MR795_gain_code_quant3
+ MR795_gain_code_quant_mod
+ MR795_gain_quant
+
+ Date: 02/04/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+ Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description:
+ (1) Removed optimization -- mult(i, 3, pOverflow) is NOT the same as adding
+ i to itself 3 times. The reason is because the mult function does a
+ right shift by 15, which will obliterate smaller numbers.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "qgain795.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "log2.h"
+#include "pow2.h"
+#include "sqrt_l.h"
+#include "g_adapt.h"
+#include "calc_en.h"
+#include "q_gain_p.h"
+
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+#define NB_QUA_CODE 32
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 qua_gain_code[NB_QUA_CODE*3];
+
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: MR795_gain_code_quant3
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ exp_gcode0 -- Word16 -- predicted CB gain (exponent), Q0
+ gcode0 -- Word16 -- predicted CB gain (norm.)
+ g_pitch_cand[] -- Word16 array -- Pitch gain candidates (3), Q14
+ g_pitch_cind[] -- Word16 array -- Pitch gain cand. indices (3), Q0
+ frac_coeff[] -- Word16 array -- coefficients (5), Q15
+ exp_coeff[] -- Word16 array -- energy coefficients (5), Q0
+ coefficients from calc_filt_ener()
+
+ Outputs:
+ gain_pit -- Pointer to Word16 -- Pitch gain, Q14
+ gain_pit_ind -- Pointer to Word16 -- Pitch gain index, Q0
+ gain_cod -- Pointer to Word16 -- Code gain, Q1
+ gain_cod_ind -- Pointer to Word16 -- Code gain index, Q0
+ qua_ener_MR122 -- Pointer to Word16 -- quantized energy error, Q10
+ (for MR122 MA predictor update)
+
+ qua_ener -- Pointer to Word16 -- quantized energy error, Q10
+ (for other MA predictor update)
+
+ pOverflow -- Pointer to Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Pre-quantization of codebook gains, given three possible
+ LTP gains (using predicted codebook gain)
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ qgain795.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static void
+MR795_gain_code_quant3(
+ Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
+ Word16 gcode0, /* i : predicted CB gain (norm.), Q14 */
+ Word16 g_pitch_cand[], /* i : Pitch gain candidates (3), Q14 */
+ Word16 g_pitch_cind[], /* i : Pitch gain cand. indices (3), Q0 */
+ Word16 frac_coeff[], /* i : coefficients (5), Q15 */
+ Word16 exp_coeff[], /* i : energy coefficients (5), Q0 */
+ /* coefficients from calc_filt_ener()*/
+ Word16 *gain_pit, /* o : Pitch gain, Q14 */
+ Word16 *gain_pit_ind, /* o : Pitch gain index, Q0 */
+ Word16 *gain_cod, /* o : Code gain, Q1 */
+ Word16 *gain_cod_ind, /* o : Code gain index, Q0 */
+ Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */
+ /* (for MR122 MA predictor update) */
+ Word16 *qua_ener, /* o : quantized energy error, Q10 */
+ /* (for other MA predictor update) */
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ const Word16 *p;
+ Word16 i;
+ Word16 j;
+ Word16 cod_ind;
+ Word16 pit_ind;
+ Word16 e_max;
+ Word16 exp_code;
+ Word16 g_pitch;
+ Word16 g2_pitch;
+ Word16 g_code;
+ Word16 g2_code_h;
+ Word16 g2_code_l;
+ Word16 g_pit_cod_h;
+ Word16 g_pit_cod_l;
+ Word16 coeff[5];
+ Word16 coeff_lo[5];
+ Word16 exp_max[5];
+ Word32 L_tmp;
+ Word32 L_tmp0;
+ Word32 dist_min;
+
+ /*
+ * The error energy (sum) to be minimized consists of five terms, t[0..4].
+ *
+ * t[0] = gp^2 * <y1 y1>
+ * t[1] = -2*gp * <xn y1>
+ * t[2] = gc^2 * <y2 y2>
+ * t[3] = -2*gc * <xn y2>
+ * t[4] = 2*gp*gc * <y1 y2>
+ *
+ */
+
+ /* determine the scaling exponent for g_code: ec = ec0 - 10 */
+ exp_code = sub(exp_gcode0, 10, pOverflow);
+
+ /* calculate exp_max[i] = s[i]-1 */
+ exp_max[0] = sub(exp_coeff[0], 13, pOverflow);
+ exp_max[1] = sub(exp_coeff[1], 14, pOverflow);
+ exp_max[2] = add(exp_coeff[2], add(15, shl(exp_code, 1, pOverflow), pOverflow), pOverflow);
+ exp_max[3] = add(exp_coeff[3], exp_code, pOverflow);
+ exp_max[4] = add(exp_coeff[4], add(exp_code, 1, pOverflow), pOverflow);
+
+
+ /*-------------------------------------------------------------------*
+ * Find maximum exponent: *
+ * ~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * For the sum operation, all terms must have the same scaling; *
+ * that scaling should be low enough to prevent overflow. There- *
+ * fore, the maximum scale is determined and all coefficients are *
+ * re-scaled: *
+ * *
+ * e_max = max(exp_max[i]) + 1; *
+ * e = exp_max[i]-e_max; e <= 0! *
+ * c[i] = c[i]*2^e *
+ *-------------------------------------------------------------------*/
+
+ e_max = exp_max[0];
+ for (i = 1; i < 5; i++) /* implemented flattened */
+ {
+ if (exp_max[i] > e_max)
+ {
+ e_max = exp_max[i];
+ }
+ }
+
+ e_max = add(e_max, 1, pOverflow); /* To avoid overflow */
+
+ for (i = 0; i < 5; i++)
+ {
+ j = sub(e_max, exp_max[i], pOverflow);
+ L_tmp = L_deposit_h(frac_coeff[i]);
+ L_tmp = L_shr(L_tmp, j, pOverflow);
+ L_Extract(L_tmp, &coeff[i], &coeff_lo[i], pOverflow);
+ }
+
+
+ /*-------------------------------------------------------------------*
+ * Codebook search: *
+ * ~~~~~~~~~~~~~~~~ *
+ * *
+ * For each of the candiates LTP gains in g_pitch_cand[], the terms *
+ * t[0..4] are calculated from the values in the table (and the *
+ * pitch gain candidate) and summed up; the result is the mean *
+ * squared error for the LPT/CB gain pair. The index for the mini- *
+ * mum MSE is stored and finally used to retrieve the quantized CB *
+ * gain *
+ *-------------------------------------------------------------------*/
+
+ /* start with "infinite" MSE */
+ dist_min = MAX_32;
+ cod_ind = 0;
+ pit_ind = 0;
+
+ /* loop through LTP gain candidates */
+ for (j = 0; j < 3; j++)
+ {
+ /* pre-calculate terms only dependent on pitch gain */
+ g_pitch = g_pitch_cand[j];
+ g2_pitch = mult(g_pitch, g_pitch, pOverflow);
+ L_tmp0 = Mpy_32_16(coeff[0], coeff_lo[0], g2_pitch, pOverflow);
+ L_tmp0 = Mac_32_16(L_tmp0, coeff[1], coeff_lo[1], g_pitch, pOverflow);
+
+ p = &qua_gain_code[0];
+ for (i = 0; i < NB_QUA_CODE; i++)
+ {
+ g_code = *p++; /* this is g_fac Q11 */
+ p++; /* skip log2(g_fac) */
+ p++; /* skip 20*log10(g_fac) */
+
+ g_code = mult(g_code, gcode0, pOverflow);
+
+ L_tmp = L_mult(g_code, g_code, pOverflow);
+ L_Extract(L_tmp, &g2_code_h, &g2_code_l, pOverflow);
+
+ L_tmp = L_mult(g_code, g_pitch, pOverflow);
+ L_Extract(L_tmp, &g_pit_cod_h, &g_pit_cod_l, pOverflow);
+
+ L_tmp = Mac_32(L_tmp0, coeff[2], coeff_lo[2],
+ g2_code_h, g2_code_l, pOverflow);
+ L_tmp = Mac_32_16(L_tmp, coeff[3], coeff_lo[3],
+ g_code, pOverflow);
+ L_tmp = Mac_32(L_tmp, coeff[4], coeff_lo[4],
+ g_pit_cod_h, g_pit_cod_l, pOverflow);
+
+ /* store table index if MSE for this index is lower
+ than the minimum MSE seen so far; also store the
+ pitch gain for this (so far) lowest MSE */
+ if (L_tmp < dist_min)
+ {
+ dist_min = L_tmp;
+ cod_ind = i;
+ pit_ind = j;
+ }
+ }
+ }
+
+ /*------------------------------------------------------------------*
+ * read quantized gains and new values for MA predictor memories *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ *------------------------------------------------------------------*/
+
+ /* Read the quantized gains */
+ p = &qua_gain_code[
+ add(add(cod_ind, cod_ind, pOverflow), cod_ind, pOverflow)];
+
+ g_code = *p++;
+ *qua_ener_MR122 = *p++;
+ *qua_ener = *p;
+
+ /*------------------------------------------------------------------*
+ * calculate final fixed codebook gain: *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * gc = gc0 * g *
+ *------------------------------------------------------------------*/
+
+ L_tmp = L_mult(g_code, gcode0, pOverflow);
+ L_tmp = L_shr(L_tmp, sub(9, exp_gcode0, pOverflow), pOverflow);
+ *gain_cod = extract_h(L_tmp);
+ *gain_cod_ind = cod_ind;
+ *gain_pit = g_pitch_cand[pit_ind];
+ *gain_pit_ind = g_pitch_cind[pit_ind];
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: MR795_gain_code_quant_mod
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ gain_pit -- Word16 -- pitch gain, Q14
+ exp_gcode0 -- Word16 -- predicted CB gain (exponent), Q0
+ gcode0 -- Word16 -- predicted CB gain (norm.), Q14
+ frac_en[] -- Word16 array -- energy coefficients (4), fraction part, Q15
+ exp_en[] -- Word16 array -- energy coefficients (4), exponent part, Q0
+ alpha -- Word16 -- gain adaptor factor (>0), Q15
+
+ gain_cod_unq -- Word16 -- Code gain (unquantized)
+ (scaling: Q10 - exp_gcode0)
+
+ gain_cod -- Pointer to Word16 -- Code gain (pre-/quantized), Q1
+
+ Outputs:
+ qua_ener_MR122 -- Pointer to Word16 -- quantized energy error, Q10
+ (for MR122 MA predictor update)
+ qua_ener -- Pointer to Word16 -- quantized energy error, Q10
+ (for other MA predictor update)
+ pOverflow -- Pointer to Flag -- overflow indicator
+
+ Returns:
+ index of quantization (Word16)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ PURPOSE: Modified quantization of the MR795 codebook gain
+
+ Uses pre-computed energy coefficients in frac_en[]/exp_en[]
+
+ frac_en[0]*2^exp_en[0] = <res res> // LP residual energy
+ frac_en[1]*2^exp_en[1] = <exc exc> // LTP residual energy
+ frac_en[2]*2^exp_en[2] = <exc code> // LTP/CB innovation dot product
+ frac_en[3]*2^exp_en[3] = <code code> // CB innovation energy
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ qgain795.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+static Word16
+MR795_gain_code_quant_mod( /* o : index of quantization. */
+ Word16 gain_pit, /* i : pitch gain, Q14 */
+ Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
+ Word16 gcode0, /* i : predicted CB gain (norm.), Q14 */
+ Word16 frac_en[], /* i : energy coefficients (4),
+ fraction part, Q15 */
+ Word16 exp_en[], /* i : energy coefficients (4),
+ eponent part, Q0 */
+ Word16 alpha, /* i : gain adaptor factor (>0), Q15 */
+ Word16 gain_cod_unq, /* i : Code gain (unquantized) */
+ /* (scaling: Q10 - exp_gcode0) */
+ Word16 *gain_cod, /* i/o: Code gain (pre-/quantized), Q1 */
+ Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */
+ /* (for MR122 MA predictor update) */
+ Word16 *qua_ener, /* o : quantized energy error, Q10 */
+ /* (for other MA predictor update) */
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ const Word16 *p;
+ Word16 i;
+ Word16 index;
+ Word16 tmp;
+ Word16 one_alpha;
+ Word16 exp;
+ Word16 e_max;
+
+ Word16 g2_pitch;
+ Word16 g_code;
+ Word16 g2_code_h;
+ Word16 g2_code_l;
+ Word16 d2_code_h;
+ Word16 d2_code_l;
+ Word16 coeff[5];
+ Word16 coeff_lo[5];
+ Word16 exp_coeff[5];
+ Word32 L_tmp;
+ Word32 L_t0;
+ Word32 L_t1;
+ Word32 dist_min;
+ Word16 gain_code;
+
+ /*
+ Steps in calculation of the error criterion (dist):
+ ---------------------------------------------------
+
+ underlined = constant; alp = FLP value of alpha, alpha = FIP
+ ----------
+
+
+ ExEn = gp^2 * LtpEn + 2.0*gp*gc[i] * XC + gc[i]^2 * InnEn;
+ ------------ ------ -- -----
+
+ aExEn= alp * ExEn
+ = alp*gp^2*LtpEn + 2.0*alp*gp*XC* gc[i] + alp*InnEn* gc[i]^2
+ -------------- ------------- ---------
+
+ = t[1] + t[2] + t[3]
+
+ dist = d1 + d2;
+
+ d1 = (1.0 - alp) * InnEn * (gcu - gc[i])^2 = t[4]
+ ------------------- ---
+
+ d2 = alp * (ResEn - 2.0 * sqrt(ResEn*ExEn) + ExEn);
+ --- ----- --- -----
+
+ = alp * (sqrt(ExEn) - sqrt(ResEn))^2
+ --- -----------
+
+ = (sqrt(aExEn) - sqrt(alp*ResEn))^2
+ ---------------
+
+ = (sqrt(aExEn) - t[0] )^2
+ ----
+
+ */
+
+ /*
+ * calculate scalings of the constant terms
+ */
+ gain_code = shl(*gain_cod, sub(10, exp_gcode0, pOverflow), pOverflow); /* Q1 -> Q11 (-ec0) */
+ g2_pitch = mult(gain_pit, gain_pit, pOverflow); /* Q14 -> Q13 */
+ /* 0 < alpha <= 0.5 => 0.5 <= 1-alpha < 1, i.e one_alpha is normalized */
+ one_alpha = add(sub(32767, alpha, pOverflow), 1, pOverflow); /* 32768 - alpha */
+
+
+ /* alpha <= 0.5 -> mult. by 2 to keep precision; compensate in exponent */
+ L_t1 = L_mult(alpha, frac_en[1], pOverflow);
+ L_t1 = L_shl(L_t1, 1, pOverflow);
+ tmp = extract_h(L_t1);
+
+ /* directly store in 32 bit variable because no further mult. required */
+ L_t1 = L_mult(tmp, g2_pitch, pOverflow);
+ exp_coeff[1] = sub(exp_en[1], 15, pOverflow);
+
+
+ tmp = extract_h(L_shl(L_mult(alpha, frac_en[2], pOverflow), 1, pOverflow));
+ coeff[2] = mult(tmp, gain_pit, pOverflow);
+ exp = sub(exp_gcode0, 10, pOverflow);
+ exp_coeff[2] = add(exp_en[2], exp, pOverflow);
+
+
+ /* alpha <= 0.5 -> mult. by 2 to keep precision; compensate in exponent */
+ coeff[3] = extract_h(L_shl(L_mult(alpha, frac_en[3], pOverflow), 1, pOverflow));
+ exp = sub(shl(exp_gcode0, 1, pOverflow), 7, pOverflow);
+ exp_coeff[3] = add(exp_en[3], exp, pOverflow);
+
+
+ coeff[4] = mult(one_alpha, frac_en[3], pOverflow);
+ exp_coeff[4] = add(exp_coeff[3], 1, pOverflow);
+
+
+ L_tmp = L_mult(alpha, frac_en[0], pOverflow);
+ /* sqrt_l returns normalized value and 2*exponent
+ -> result = val >> (exp/2)
+ exp_coeff holds 2*exponent for c[0] */
+ /* directly store in 32 bit variable because no further mult. required */
+ L_t0 = sqrt_l_exp(L_tmp, &exp, pOverflow); /* normalization included in sqrt_l_exp */
+ exp = add(exp, 47, pOverflow);
+ exp_coeff[0] = sub(exp_en[0], exp, pOverflow);
+
+ /*
+ * Determine the maximum exponent occuring in the distance calculation
+ * and adjust all fractions accordingly (including a safety margin)
+ *
+ */
+
+ /* find max(e[1..4],e[0]+31) */
+ e_max = add(exp_coeff[0], 31, pOverflow);
+ for (i = 1; i <= 4; i++)
+ {
+ if (exp_coeff[i] > e_max)
+ {
+ e_max = exp_coeff[i];
+ }
+ }
+
+ /* scale c[1] (requires no further multiplication) */
+ tmp = sub(e_max, exp_coeff[1], pOverflow);
+ L_t1 = L_shr(L_t1, tmp, pOverflow);
+
+ /* scale c[2..4] (used in Mpy_32_16 in the quantizer loop) */
+ for (i = 2; i <= 4; i++)
+ {
+ tmp = sub(e_max, exp_coeff[i], pOverflow);
+ L_tmp = L_deposit_h(coeff[i]);
+ L_tmp = L_shr(L_tmp, tmp, pOverflow);
+ L_Extract(L_tmp, &coeff[i], &coeff_lo[i], pOverflow);
+ }
+
+ /* scale c[0] (requires no further multiplication) */
+ exp = sub(e_max, 31, pOverflow); /* new exponent */
+ tmp = sub(exp, exp_coeff[0], pOverflow);
+ L_t0 = L_shr(L_t0, shr(tmp, 1, pOverflow), pOverflow);
+ /* perform correction by 1/sqrt(2) if exponent difference is odd */
+ if ((tmp & 0x1) != 0)
+ {
+ L_Extract(L_t0, &coeff[0], &coeff_lo[0], pOverflow);
+ L_t0 = Mpy_32_16(coeff[0], coeff_lo[0],
+ 23170, pOverflow); /* 23170 Q15 = 1/sqrt(2)*/
+ }
+
+ /* search the quantizer table for the lowest value
+ of the search criterion */
+ dist_min = MAX_32;
+ index = 0;
+ p = &qua_gain_code[0];
+
+ for (i = 0; i < NB_QUA_CODE; i++)
+ {
+ g_code = *p++; /* this is g_fac (Q11) */
+ p++; /* skip log2(g_fac) */
+ p++; /* skip 20*log10(g_fac) */
+ g_code = mult(g_code, gcode0, pOverflow);
+
+ /* only continue if gc[i] < 2.0*gc
+ which is equiv. to g_code (Q10-ec0) < gain_code (Q11-ec0) */
+
+ if (g_code >= gain_code)
+ {
+ break;
+ }
+
+ L_tmp = L_mult(g_code, g_code, pOverflow);
+ L_Extract(L_tmp, &g2_code_h, &g2_code_l, pOverflow);
+
+ tmp = sub(g_code, gain_cod_unq, pOverflow);
+ L_tmp = L_mult(tmp, tmp, pOverflow);
+ L_Extract(L_tmp, &d2_code_h, &d2_code_l, pOverflow);
+
+ /* t2, t3, t4 */
+ L_tmp = Mac_32_16(L_t1, coeff[2], coeff_lo[2], g_code, pOverflow);
+ L_tmp = Mac_32(L_tmp, coeff[3], coeff_lo[3], g2_code_h, g2_code_l, pOverflow);
+
+ L_tmp = sqrt_l_exp(L_tmp, &exp, pOverflow);
+ L_tmp = L_shr(L_tmp, shr(exp, 1, pOverflow), pOverflow);
+
+ /* d2 */
+ tmp = pv_round(L_sub(L_tmp, L_t0, pOverflow), pOverflow);
+ L_tmp = L_mult(tmp, tmp, pOverflow);
+
+ /* dist */
+ L_tmp = Mac_32(L_tmp, coeff[4], coeff_lo[4], d2_code_h, d2_code_l, pOverflow);
+
+ /* store table index if distance measure for this
+ index is lower than the minimum seen so far */
+ if (L_tmp < dist_min)
+ {
+ dist_min = L_tmp;
+ index = i;
+ }
+ }
+
+ /*------------------------------------------------------------------*
+ * read quantized gains and new values for MA predictor memories *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ *------------------------------------------------------------------*/
+
+ /* Read the quantized gains */
+ p = &qua_gain_code[add(add(index, index, pOverflow), index, pOverflow)];
+ g_code = *p++;
+ *qua_ener_MR122 = *p++;
+ *qua_ener = *p;
+
+ /*------------------------------------------------------------------*
+ * calculate final fixed codebook gain: *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * gc = gc0 * g *
+ *------------------------------------------------------------------*/
+
+ L_tmp = L_mult(g_code, gcode0, pOverflow);
+ L_tmp = L_shr(L_tmp, sub(9, exp_gcode0, pOverflow), pOverflow);
+ *gain_cod = extract_h(L_tmp);
+
+ return index;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: MR795_gain_quant
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+MR795_gain_quant(
+
+
+ Inputs:
+ adapt_st -- Pointer to GainAdaptState -- gain adapter state structure
+ res -- Word16 array -- LP residual, Q0
+ exc -- Word16 array -- LTP excitation (unfiltered), Q0
+ code -- Word16 array -- CB innovation (unfiltered), Q13
+ frac_coeff -- Word16 array -- coefficients (5), Q15
+ exp_coeff -- Word16 array -- energy coefficients (5), Q0
+ coefficients from calc_filt_ener()
+ exp_code_en -- Word16 -- innovation energy (exponent), Q0
+ frac_code_en -- Word16 -- innovation energy (fraction), Q15
+ exp_gcode0 -- Word16 -- predicted CB gain (exponent), Q0
+ frac_gcode0 -- Word16 -- predicted CB gain (fraction), Q15
+ L_subfr -- Word16 -- Subframe length
+ cod_gain_frac -- Word16 -- opt. codebook gain (fraction),Q15
+ cod_gain_exp -- Word16 -- opt. codebook gain (exponent), Q0
+ gp_limit -- Word16 -- pitch gain limit
+ gain_pit -- Pointer to Word16 -- Pitch gain, Q14
+
+ Output
+ adapt_st -- Pointer to GainAdaptState -- gain adapter state structure
+ gain_pit -- Pointer to Word16 -- Pitch gain, Q14
+
+ gain_pit -- Pointer to Word16 -- Pitch gain, Q14
+ gain_cod -- Pointer to Word16 -- Code gain, Q1
+ qua_ener_MR122 -- Pointer to Word16 -- quantized energy error, Q10
+ (for MR122 MA predictor update)
+
+ qua_ener -- Pointer to Word16 -- quantized energy error, Q10
+ (for other MA predictor update)
+
+ anap -- Double Pointer to Word16 -- Index of quantization
+ (first gain pitch, then code pitch)
+
+ pOverflow -- Pointer to Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ pitch and codebook quantization for MR795
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ qgain795.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void
+MR795_gain_quant(
+ GainAdaptState *adapt_st, /* i/o: gain adapter state structure */
+ Word16 res[], /* i : LP residual, Q0 */
+ Word16 exc[], /* i : LTP excitation (unfiltered), Q0 */
+ Word16 code[], /* i : CB innovation (unfiltered), Q13 */
+ Word16 frac_coeff[], /* i : coefficients (5), Q15 */
+ Word16 exp_coeff[], /* i : energy coefficients (5), Q0 */
+ /* coefficients from calc_filt_ener() */
+ Word16 exp_code_en, /* i : innovation energy (exponent), Q0 */
+ Word16 frac_code_en, /* i : innovation energy (fraction), Q15 */
+ Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
+ Word16 frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
+ Word16 L_subfr, /* i : Subframe length */
+ Word16 cod_gain_frac, /* i : opt. codebook gain (fraction),Q15 */
+ Word16 cod_gain_exp, /* i : opt. codebook gain (exponent), Q0 */
+ Word16 gp_limit, /* i : pitch gain limit */
+ Word16 *gain_pit, /* i/o: Pitch gain, Q14 */
+ Word16 *gain_cod, /* o : Code gain, Q1 */
+ Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */
+ /* (for MR122 MA predictor update) */
+ Word16 *qua_ener, /* o : quantized energy error, Q10 */
+ /* (for other MA predictor update) */
+ Word16 **anap, /* o : Index of quantization */
+ /* (first gain pitch, then code pitch)*/
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ Word16 frac_en[4];
+ Word16 exp_en[4];
+ Word16 ltpg, alpha, gcode0;
+ Word16 g_pitch_cand[3]; /* pitch gain candidates Q14 */
+ Word16 g_pitch_cind[3]; /* pitch gain indices Q0 */
+ Word16 gain_pit_index;
+ Word16 gain_cod_index;
+ Word16 exp;
+ Word16 gain_cod_unq; /* code gain (unq.) Q(10-exp_gcode0) */
+
+
+ /* get list of candidate quantized pitch gain values
+ * and corresponding quantization indices
+ */
+ gain_pit_index = q_gain_pitch(MR795, gp_limit, gain_pit,
+ g_pitch_cand, g_pitch_cind, pOverflow);
+
+ /*-------------------------------------------------------------------*
+ * predicted codebook gain *
+ * ~~~~~~~~~~~~~~~~~~~~~~~ *
+ * gc0 = 2^exp_gcode0 + 2^frac_gcode0 *
+ * *
+ * gcode0 (Q14) = 2^14*2^frac_gcode0 = gc0 * 2^(14-exp_gcode0) *
+ *-------------------------------------------------------------------*/
+ gcode0 = (Word16)(Pow2(14, frac_gcode0, pOverflow)); /* Q14 */
+
+ /* pre-quantization of codebook gain
+ * (using three pitch gain candidates);
+ * result: best guess of pitch gain and code gain
+ */
+ MR795_gain_code_quant3(
+ exp_gcode0, gcode0, g_pitch_cand, g_pitch_cind,
+ frac_coeff, exp_coeff,
+ gain_pit, &gain_pit_index, gain_cod, &gain_cod_index,
+ qua_ener_MR122, qua_ener, pOverflow);
+
+ /* calculation of energy coefficients and LTP coding gain */
+ calc_unfilt_energies(res, exc, code, *gain_pit, L_subfr,
+ frac_en, exp_en, &ltpg, pOverflow);
+
+ /* run gain adaptor, calculate alpha factor to balance LTP/CB gain
+ * (this includes the gain adaptor update)
+ * Note: ltpg = 0 if frac_en[0] == 0, so the update is OK in that case
+ */
+ gain_adapt(adapt_st, ltpg, *gain_cod, &alpha, pOverflow);
+
+ /* if this is a very low energy signal (threshold: see
+ * calc_unfilt_energies) or alpha <= 0 then don't run the modified quantizer
+ */
+ if (frac_en[0] != 0 && alpha > 0)
+ {
+ /* innovation energy <cod cod> was already computed in gc_pred() */
+ /* (this overwrites the LtpResEn which is no longer needed) */
+ frac_en[3] = frac_code_en;
+ exp_en[3] = exp_code_en;
+
+ /* store optimum codebook gain in Q(10-exp_gcode0) */
+ exp = add(sub(cod_gain_exp, exp_gcode0, pOverflow), 10, pOverflow);
+ gain_cod_unq = shl(cod_gain_frac, exp, pOverflow);
+
+ /* run quantization with modified criterion */
+ gain_cod_index = MR795_gain_code_quant_mod(
+ *gain_pit, exp_gcode0, gcode0,
+ frac_en, exp_en, alpha, gain_cod_unq,
+ gain_cod, qua_ener_MR122, qua_ener, pOverflow); /* function result */
+ }
+
+ *(*anap)++ = gain_pit_index;
+ *(*anap)++ = gain_cod_index;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/qgain795.h b/media/libstagefright/codecs/amrnb/enc/src/qgain795.h
new file mode 100644
index 0000000..b739dad
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/qgain795.h
@@ -0,0 +1,143 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/qgain795.h
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the file, qgain795.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef qgain795_h
+#define qgain795_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "g_adapt.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void
+ MR795_gain_quant(
+ GainAdaptState *adapt_st, /* i/o: gain adapter state structure */
+ Word16 res[], /* i : LP residual, Q0 */
+ Word16 exc[], /* i : LTP excitation (unfiltered), Q0 */
+ Word16 code[], /* i : CB innovation (unfiltered), Q13 */
+ Word16 frac_coeff[], /* i : coefficients (5), Q15 */
+ Word16 exp_coeff[], /* i : energy coefficients (5), Q0 */
+ /* coefficients from calc_filt_ener() */
+ Word16 exp_code_en, /* i : innovation energy (exponent), Q0 */
+ Word16 frac_code_en, /* i : innovation energy (fraction), Q15 */
+ Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
+ Word16 frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
+ Word16 L_subfr, /* i : Subframe length */
+ Word16 cod_gain_frac, /* i : opt. codebook gain (fraction),Q15 */
+ Word16 cod_gain_exp, /* i : opt. codebook gain (exponent), Q0 */
+ Word16 gp_limit, /* i : pitch gain limit */
+ Word16 *gain_pit, /* i/o: Pitch gain (unquant/quant), Q14 */
+ Word16 *gain_cod, /* o : Code gain, Q1 */
+ Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */
+ /* (for MR122 MA predictor update) */
+ Word16 *qua_ener, /* o : quantized energy error, Q10 */
+ /* (for other MA predictor update) */
+ Word16 **anap, /* o : Index of quantization */
+ /* (first gain pitch, then code pitch)*/
+ Flag *pOverflow /* o : overflow indicator */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* qgain795_H_ */
+
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/qua_gain.cpp b/media/libstagefright/codecs/amrnb/enc/src/qua_gain.cpp
new file mode 100644
index 0000000..740abcb
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/qua_gain.cpp
@@ -0,0 +1,400 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/qua_gain.c
+ Functions:
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+ Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description: Changed include files to lowercase.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Added #ifdef __cplusplus around extern'ed table.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Quantization of pitch and codebook gains.
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "qua_gain.h"
+#include "typedef.h"
+#include "basic_op.h"
+
+#include "mode.h"
+#include "cnst.h"
+#include "pow2.h"
+#include "gc_pred.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here. Include conditional
+ ; compile variables also.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; LOCAL VARIABLE DEFINITIONS
+ ; Variable declaration - defined here and used outside this module
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+ extern const Word16 table_gain_lowrates[];
+ extern const Word16 table_gain_highrates[];
+
+ /*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME:
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+ Inputs:
+ mode -- enum Mode -- AMR mode
+ Word16 exp_gcode0 -- Word16 -- predicted CB gain (exponent), Q0
+ Word16 frac_gcode0 -- Word16 -- predicted CB gain (fraction), Q15
+ Word16 frac_coeff -- Word16 Array -- energy coeff. (5), fraction part, Q15
+ Word16 exp_coeff -- Word16 Array -- energy coeff. (5), exponent part, Q0
+ (frac_coeff and exp_coeff computed in
+ calc_filt_energies())
+
+ Word16 gp_limit -- Word16 -- pitch gain limit
+
+ Outputs:
+ Word16 *gain_pit -- Pointer to Word16 -- Pitch gain, Q14
+ Word16 *gain_cod -- Pointer to Word16 -- Code gain, Q1
+ Word16 *qua_ener_MR122 -- Pointer to Word16 -- quantized energy error, Q10
+ (for MR122 MA predictor update)
+ Word16 *qua_ener -- Pointer to Word16 -- quantized energy error, Q10
+ (for other MA predictor update)
+ Flag *pOverflow -- Pointer to Flag -- overflow indicator
+
+ Returns:
+ Word16 -- index of quantization.
+
+ Global Variables Used:
+
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Quantization of pitch and codebook gains.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ qua_gain.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+
+Word16
+Qua_gain( /* o : index of quantization. */
+ enum Mode mode, /* i : AMR mode */
+ Word16 exp_gcode0, /* i : predicted CB gain (exponent), Q0 */
+ Word16 frac_gcode0, /* i : predicted CB gain (fraction), Q15 */
+ Word16 frac_coeff[], /* i : energy coeff. (5), fraction part, Q15 */
+ Word16 exp_coeff[], /* i : energy coeff. (5), exponent part, Q0 */
+ /* (frac_coeff and exp_coeff computed in */
+ /* calc_filt_energies()) */
+ Word16 gp_limit, /* i : pitch gain limit */
+ Word16 *gain_pit, /* o : Pitch gain, Q14 */
+ Word16 *gain_cod, /* o : Code gain, Q1 */
+ Word16 *qua_ener_MR122, /* o : quantized energy error, Q10 */
+ /* (for MR122 MA predictor update) */
+ Word16 *qua_ener, /* o : quantized energy error, Q10 */
+ /* (for other MA predictor update) */
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ const Word16 *p;
+ Word16 i;
+ Word16 j;
+ Word16 index = 0;
+ Word16 gcode0;
+ Word16 e_max;
+ Word16 temp;
+ Word16 exp_code;
+ Word16 g_pitch;
+ Word16 g2_pitch;
+ Word16 g_code;
+ Word16 g2_code;
+ Word16 g_pit_cod;
+ Word16 coeff[5];
+ Word16 coeff_lo[5];
+ Word16 exp_max[5];
+ Word32 L_tmp;
+ Word32 L_tmp2;
+ Word32 dist_min;
+ const Word16 *table_gain;
+ Word16 table_len;
+
+ if (mode == MR102 || mode == MR74 || mode == MR67)
+ {
+ table_len = VQ_SIZE_HIGHRATES;
+ table_gain = table_gain_highrates;
+ }
+ else
+ {
+ table_len = VQ_SIZE_LOWRATES;
+ table_gain = table_gain_lowrates;
+ }
+
+ /*-------------------------------------------------------------------*
+ * predicted codebook gain *
+ * ~~~~~~~~~~~~~~~~~~~~~~~ *
+ * gc0 = 2^exp_gcode0 + 2^frac_gcode0 *
+ * *
+ * gcode0 (Q14) = 2^14*2^frac_gcode0 = gc0 * 2^(14-exp_gcode0) *
+ *-------------------------------------------------------------------*/
+
+ gcode0 = (Word16)(Pow2(14, frac_gcode0, pOverflow));
+
+ /*-------------------------------------------------------------------*
+ * Scaling considerations: *
+ * ~~~~~~~~~~~~~~~~~~~~~~~ *
+ *-------------------------------------------------------------------*/
+
+ /*
+ * The error energy (sum) to be minimized consists of five terms, t[0..4].
+ *
+ * t[0] = gp^2 * <y1 y1>
+ * t[1] = -2*gp * <xn y1>
+ * t[2] = gc^2 * <y2 y2>
+ * t[3] = -2*gc * <xn y2>
+ * t[4] = 2*gp*gc * <y1 y2>
+ *
+ */
+
+ /* determine the scaling exponent for g_code: ec = ec0 - 11 */
+ exp_code = sub(exp_gcode0, 11, pOverflow);
+
+ /* calculate exp_max[i] = s[i]-1 */
+ exp_max[0] = sub(exp_coeff[0], 13, pOverflow);
+ exp_max[1] = sub(exp_coeff[1], 14, pOverflow);
+
+ temp = shl(exp_code, 1, pOverflow);
+ temp = add(15, temp, pOverflow);
+ exp_max[2] = add(exp_coeff[2], temp, pOverflow);
+
+ exp_max[3] = add(exp_coeff[3], exp_code, pOverflow);
+
+ temp = add(1, exp_code, pOverflow);
+ exp_max[4] = add(exp_coeff[4], temp, pOverflow);
+
+
+ /*-------------------------------------------------------------------*
+ * Find maximum exponent: *
+ * ~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * For the sum operation, all terms must have the same scaling; *
+ * that scaling should be low enough to prevent overflow. There- *
+ * fore, the maximum scale is determined and all coefficients are *
+ * re-scaled: *
+ * *
+ * e_max = max(exp_max[i]) + 1; *
+ * e = exp_max[i]-e_max; e <= 0! *
+ * c[i] = c[i]*2^e *
+ *-------------------------------------------------------------------*/
+
+ e_max = exp_max[0];
+ for (i = 1; i < 5; i++)
+ {
+ if (exp_max[i] > e_max)
+ {
+ e_max = exp_max[i];
+ }
+ }
+
+ e_max = add(e_max, 1, pOverflow); /* To avoid overflow */
+
+ for (i = 0; i < 5; i++)
+ {
+ j = sub(e_max, exp_max[i], pOverflow);
+ L_tmp = L_deposit_h(frac_coeff[i]);
+ L_tmp = L_shr(L_tmp, j, pOverflow);
+ L_Extract(L_tmp, &coeff[i], &coeff_lo[i], pOverflow);
+ }
+
+
+ /*-------------------------------------------------------------------*
+ * Codebook search: *
+ * ~~~~~~~~~~~~~~~~ *
+ * *
+ * For each pair (g_pitch, g_fac) in the table calculate the *
+ * terms t[0..4] and sum them up; the result is the mean squared *
+ * error for the quantized gains from the table. The index for the *
+ * minimum MSE is stored and finally used to retrieve the quantized *
+ * gains *
+ *-------------------------------------------------------------------*/
+
+ /* start with "infinite" MSE */
+ dist_min = MAX_32;
+
+ p = &table_gain[0];
+
+ for (i = 0; i < table_len; i++)
+ {
+ g_pitch = *p++;
+ g_code = *p++; /* this is g_fac */
+ p++; /* skip log2(g_fac) */
+ p++; /* skip 20*log10(g_fac) */
+
+ if (g_pitch <= gp_limit)
+ {
+ g_code = mult(g_code, gcode0, pOverflow);
+ g2_pitch = mult(g_pitch, g_pitch, pOverflow);
+ g2_code = mult(g_code, g_code, pOverflow);
+ g_pit_cod = mult(g_code, g_pitch, pOverflow);
+
+ L_tmp = Mpy_32_16(coeff[0], coeff_lo[0], g2_pitch, pOverflow);
+ L_tmp2 = Mpy_32_16(coeff[1], coeff_lo[1], g_pitch, pOverflow);
+ L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
+
+ L_tmp2 = Mpy_32_16(coeff[2], coeff_lo[2], g2_code, pOverflow);
+ L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
+
+ L_tmp2 = Mpy_32_16(coeff[3], coeff_lo[3], g_code, pOverflow);
+ L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
+
+ L_tmp2 = Mpy_32_16(coeff[4], coeff_lo[4], g_pit_cod, pOverflow);
+ L_tmp = L_add(L_tmp, L_tmp2, pOverflow);
+
+ /* store table index if MSE for this index is lower
+ than the minimum MSE seen so far */
+ if (L_tmp < dist_min)
+ {
+ dist_min = L_tmp;
+ index = i;
+ }
+ }
+ }
+
+ /*------------------------------------------------------------------*
+ * read quantized gains and new values for MA predictor memories *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ *------------------------------------------------------------------*/
+
+ /* Read the quantized gains */
+ p = &table_gain[shl(index, 2, pOverflow)];
+ *gain_pit = *p++;
+ g_code = *p++;
+ *qua_ener_MR122 = *p++;
+ *qua_ener = *p;
+
+ /*------------------------------------------------------------------*
+ * calculate final fixed codebook gain: *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * gc = gc0 * g *
+ *------------------------------------------------------------------*/
+
+ L_tmp = L_mult(g_code, gcode0, pOverflow);
+ temp = sub(10, exp_gcode0, pOverflow);
+ L_tmp = L_shr(L_tmp, temp, pOverflow);
+
+ *gain_cod = extract_h(L_tmp);
+
+ return index;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/s10_8pf.cpp b/media/libstagefright/codecs/amrnb/enc/src/s10_8pf.cpp
new file mode 100644
index 0000000..352b611
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/s10_8pf.cpp
@@ -0,0 +1,990 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/s10_8pf.c
+ Funtions: search_10and8i40
+
+ Date: 04/18/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Adding pOverflow to the functions to remove global variables.
+ These changes are needed for the EPOC releases. Cleaned up code.
+ Updated template.
+
+ Description: Changed temp to temp32. When temp was only 16 bits it was not
+ holding the 32 bit value returned from the functions. Some
+ variables were also being declared as Word16 rather than Word32
+ as they were suposed to be.
+
+ Description: Changed copyright year. Removed all calls to math functions by
+ inlining them, and removed all unnecessary files in the Include
+ section.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Removed all #defines.
+ 2. Used a pointer to &codvec[0] instead of array indexing.
+ 3. Removed multiple data casting in the code.
+
+ Description:
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers, this by taking
+ advantage of the fact that the autocrrelation matrix is
+ a toeplitz matrix, so r[i][j] = r[j][i], then a single
+ pointer can be used to address a matrix. The use of this
+ is not uniform along the function (due to compiler limitations:
+ handling so many variables in this file) so the use
+ of this is pointer optimizations is limited to places
+ where the ARM compiler provides the lesses numer of cycles
+ 3. Eliminated use of intermediate variables to accelerate
+ comparisons (like in the nested loops)
+ 4. Introduced array temp1[], to pre-calculate the elements
+ used in the nested loops, in this way the calculation is
+ not repeated in every loop iteration. This is done for
+ loops i3-i5-i7 and i9
+ 5. Use array Index[] to store indexes i1:i9, and then use memcpy
+ to update indexes.
+ 6. Eliminated shifts by modifying the way number are rounded,
+ this does not have any effect in ARM processors but may help
+ other compilers
+
+ Description:
+ 1. When storing indexes, added memcpy() to support the rates
+ that use this function: 12.2 (already done) and 10.2 (missing).
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <string.h>
+
+#include "s10_8pf.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: search_10and8i40
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ nbPulse = nbPulses to find (Word16)
+ step = step size (Word16)
+ nbTracks = nbTracks (Word16)
+ dn[] = correlation between target and h[] (Word16)
+ rr[][] = matrix of autocorrelation (Word16)
+ ipos[] = starting position of each pulse (Word16)
+ pos_max[] = Position of maximum dn[] (Word16)
+ codvec[] = Algebraic codebook vector (Word16)
+ pOverflow = pointer to Overflow flag (Flag)
+
+ Outputs:
+ codvec[] = Algebraic codebook vector (Word16)
+ pOverflow -> 1 if processing this funvction results in satuaration
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function searches for the best codevector; It determines the positions
+ of the 10/8 pulses in the 40-sample frame.
+
+ search_10and8i40 (10,5,5,dn, rr, ipos, pos_max, codvec); for GSMEFR
+ search_10and8i40 (8, 4,4,dn, rr, ipos, pos_max, codvec); for 10.2
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ s10_8pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void search_10and8i40 (
+ Word16 nbPulse, // i : nbpulses to find
+ Word16 step, // i : stepsize
+ Word16 nbTracks, // i : nbTracks
+ Word16 dn[], // i : correlation between target and h[]
+ Word16 rr[][L_CODE], // i : matrix of autocorrelation
+ Word16 ipos[], // i : starting position for each pulse
+ Word16 pos_max[], // i : position of maximum of dn[]
+ Word16 codvec[] // o : algebraic codebook vector
+)
+{
+ Word16 i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
+ Word16 i, j, k, pos, ia, ib;
+ Word16 psk, ps, ps0, ps1, ps2, sq, sq2;
+ Word16 alpk, alp, alp_16;
+ Word16 rrv[L_CODE];
+ Word32 s, alp0, alp1, alp2;
+ Word16 gsmefrFlag;
+
+
+ if (sub(nbPulse, 10) == 0)
+ {
+ gsmefrFlag=1;
+ }
+ else
+ {
+ gsmefrFlag=0;
+ }
+
+ // fix i0 on maximum of correlation position
+ i0 = pos_max[ipos[0]];
+
+ //
+ // i1 loop: *
+ //
+
+ // Default value
+
+ psk = -1;
+ alpk = 1;
+ for (i = 0; i < nbPulse; i++)
+ {
+ codvec[i] = i;
+ }
+
+ for (i = 1; i < nbTracks; i++)
+ {
+ i1 = pos_max[ipos[1]];
+ ps0 = add (dn[i0], dn[i1]);
+ alp0 = L_mult (rr[i0][i0], _1_16);
+ alp0 = L_mac (alp0, rr[i1][i1], _1_16);
+ alp0 = L_mac (alp0, rr[i0][i1], _1_8);
+
+ //
+ // i2 and i3 loop
+ //
+
+ for (i3 = ipos[3]; i3 < L_CODE; i3 += step)
+ {
+ s = L_mult (rr[i3][i3], _1_8); // index incr= step+L_CODE
+ s = L_mac (s, rr[i0][i3], _1_4); // index increment = step
+ s = L_mac (s, rr[i1][i3], _1_4); // index increment = step
+ rrv[i3] = pv_round (s);
+ }
+
+ // Default value
+ sq = -1;
+ alp = 1;
+ ps = 0;
+ ia = ipos[2];
+ ib = ipos[3];
+
+ for (i2 = ipos[2]; i2 < L_CODE; i2 += step)
+ {
+ // index increment = step
+ ps1 = add (ps0, dn[i2]);
+
+ // index incr= step+L_CODE
+ alp1 = L_mac (alp0, rr[i2][i2], _1_16);
+
+ // index increment = step
+ alp1 = L_mac (alp1, rr[i0][i2], _1_8);
+
+ // index increment = step
+ alp1 = L_mac (alp1, rr[i1][i2], _1_8);
+
+ for (i3 = ipos[3]; i3 < L_CODE; i3 += step)
+ {
+ // index increment = step
+ ps2 = add (ps1, dn[i3]);
+
+ // index increment = step
+ alp2 = L_mac (alp1, rrv[i3], _1_2);
+
+ // index increment = step
+ alp2 = L_mac (alp2, rr[i2][i3], _1_8);
+
+ sq2 = mult (ps2, ps2);
+
+ alp_16 = pv_round (alp2);
+
+ s = L_msu (L_mult (alp, sq2), sq, alp_16);
+
+ if (s > 0)
+ {
+ sq = sq2;
+ ps = ps2;
+ alp = alp_16;
+ ia = i2;
+ ib = i3;
+ }
+ }
+ }
+ i2 = ia;
+ i3 = ib;
+
+ //
+ // i4 and i5 loop:
+ //
+
+ ps0 = ps;
+ alp0 = L_mult (alp, _1_2);
+
+ for (i5 = ipos[5]; i5 < L_CODE; i5 += step)
+ {
+ s = L_mult (rr[i5][i5], _1_8);
+ s = L_mac (s, rr[i0][i5], _1_4);
+ s = L_mac (s, rr[i1][i5], _1_4);
+ s = L_mac (s, rr[i2][i5], _1_4);
+ s = L_mac (s, rr[i3][i5], _1_4);
+ rrv[i5] = pv_round (s);
+ }
+
+ // Default value
+ sq = -1;
+ alp = 1;
+ ps = 0;
+ ia = ipos[4];
+ ib = ipos[5];
+
+ for (i4 = ipos[4]; i4 < L_CODE; i4 += step)
+ {
+ ps1 = add (ps0, dn[i4]);
+
+ alp1 = L_mac (alp0, rr[i4][i4], _1_32);
+ alp1 = L_mac (alp1, rr[i0][i4], _1_16);
+ alp1 = L_mac (alp1, rr[i1][i4], _1_16);
+ alp1 = L_mac (alp1, rr[i2][i4], _1_16);
+ alp1 = L_mac (alp1, rr[i3][i4], _1_16);
+
+ for (i5 = ipos[5]; i5 < L_CODE; i5 += step)
+ {
+ ps2 = add (ps1, dn[i5]);
+
+ alp2 = L_mac (alp1, rrv[i5], _1_4);
+ alp2 = L_mac (alp2, rr[i4][i5], _1_16);
+
+ sq2 = mult (ps2, ps2);
+
+ alp_16 = pv_round (alp2);
+
+ s = L_msu (L_mult (alp, sq2), sq, alp_16);
+
+ if (s > 0)
+ {
+ sq = sq2;
+ ps = ps2;
+ alp = alp_16;
+ ia = i4;
+ ib = i5;
+ }
+ }
+ }
+ i4 = ia;
+ i5 = ib;
+
+ //
+ // i6 and i7 loop:
+ //
+
+ ps0 = ps;
+ alp0 = L_mult (alp, _1_2);
+
+ for (i7 = ipos[7]; i7 < L_CODE; i7 += step)
+ {
+ s = L_mult (rr[i7][i7], _1_16);
+ s = L_mac (s, rr[i0][i7], _1_8);
+ s = L_mac (s, rr[i1][i7], _1_8);
+ s = L_mac (s, rr[i2][i7], _1_8);
+ s = L_mac (s, rr[i3][i7], _1_8);
+ s = L_mac (s, rr[i4][i7], _1_8);
+ s = L_mac (s, rr[i5][i7], _1_8);
+ rrv[i7] = pv_round (s);
+ }
+
+ // Default value
+ sq = -1;
+ alp = 1;
+ ps = 0;
+ ia = ipos[6];
+ ib = ipos[7];
+
+ for (i6 = ipos[6]; i6 < L_CODE; i6 += step)
+ {
+ ps1 = add (ps0, dn[i6]);
+
+ alp1 = L_mac (alp0, rr[i6][i6], _1_64);
+ alp1 = L_mac (alp1, rr[i0][i6], _1_32);
+ alp1 = L_mac (alp1, rr[i1][i6], _1_32);
+ alp1 = L_mac (alp1, rr[i2][i6], _1_32);
+ alp1 = L_mac (alp1, rr[i3][i6], _1_32);
+ alp1 = L_mac (alp1, rr[i4][i6], _1_32);
+ alp1 = L_mac (alp1, rr[i5][i6], _1_32);
+
+ for (i7 = ipos[7]; i7 < L_CODE; i7 += step)
+ {
+ ps2 = add (ps1, dn[i7]);
+
+ alp2 = L_mac (alp1, rrv[i7], _1_4);
+ alp2 = L_mac (alp2, rr[i6][i7], _1_32);
+
+ sq2 = mult (ps2, ps2);
+
+ alp_16 = pv_round (alp2);
+
+ s = L_msu (L_mult (alp, sq2), sq, alp_16);
+
+ if (s > 0)
+ {
+ sq = sq2;
+ ps = ps2;
+ alp = alp_16;
+ ia = i6;
+ ib = i7;
+ }
+ }
+ }
+ i6 = ia;
+ i7 = ib;
+
+ // now finished searching a set of 8 pulses
+
+ if(gsmefrFlag != 0){
+ // go on with the two last pulses for GSMEFR
+ //
+ // i8 and i9 loop:
+ //
+
+ ps0 = ps;
+ alp0 = L_mult (alp, _1_2);
+
+ for (i9 = ipos[9]; i9 < L_CODE; i9 += step)
+ {
+ s = L_mult (rr[i9][i9], _1_16);
+ s = L_mac (s, rr[i0][i9], _1_8);
+ s = L_mac (s, rr[i1][i9], _1_8);
+ s = L_mac (s, rr[i2][i9], _1_8);
+ s = L_mac (s, rr[i3][i9], _1_8);
+ s = L_mac (s, rr[i4][i9], _1_8);
+ s = L_mac (s, rr[i5][i9], _1_8);
+ s = L_mac (s, rr[i6][i9], _1_8);
+ s = L_mac (s, rr[i7][i9], _1_8);
+ rrv[i9] = pv_round (s);
+ }
+
+ // Default value
+ sq = -1;
+ alp = 1;
+ ps = 0;
+ ia = ipos[8];
+ ib = ipos[9];
+
+ for (i8 = ipos[8]; i8 < L_CODE; i8 += step)
+ {
+ ps1 = add (ps0, dn[i8]);
+
+ alp1 = L_mac (alp0, rr[i8][i8], _1_128);
+ alp1 = L_mac (alp1, rr[i0][i8], _1_64);
+ alp1 = L_mac (alp1, rr[i1][i8], _1_64);
+ alp1 = L_mac (alp1, rr[i2][i8], _1_64);
+ alp1 = L_mac (alp1, rr[i3][i8], _1_64);
+ alp1 = L_mac (alp1, rr[i4][i8], _1_64);
+ alp1 = L_mac (alp1, rr[i5][i8], _1_64);
+ alp1 = L_mac (alp1, rr[i6][i8], _1_64);
+ alp1 = L_mac (alp1, rr[i7][i8], _1_64);
+
+ for (i9 = ipos[9]; i9 < L_CODE; i9 += step)
+ {
+ ps2 = add (ps1, dn[i9]);
+
+ alp2 = L_mac (alp1, rrv[i9], _1_8);
+ alp2 = L_mac (alp2, rr[i8][i9], _1_64);
+
+ sq2 = mult (ps2, ps2);
+
+ alp_16 = pv_round (alp2);
+
+ s = L_msu (L_mult (alp, sq2), sq, alp_16);
+
+ if (s > 0)
+ {
+ sq = sq2;
+ ps = ps2;
+ alp = alp_16;
+ ia = i8;
+ ib = i9;
+ }
+ }
+ }
+ } // end gsmefrFlag
+
+ //
+ // test and memorise if this combination is better than the last one/
+ //
+
+ s = L_msu (L_mult (alpk, sq), psk, alp);
+
+ if (s > 0)
+ {
+ psk = sq;
+ alpk = alp;
+ codvec[0] = i0;
+ codvec[1] = i1;
+ codvec[2] = i2;
+ codvec[3] = i3;
+ codvec[4] = i4;
+ codvec[5] = i5;
+ codvec[6] = i6;
+ codvec[7] = i7;
+
+ if (gsmefrFlag != 0)
+ {
+ codvec[8] = ia;
+ codvec[9] = ib;
+ }
+ }
+
+ //
+ // Cyclic permutation of i1,i2,i3,i4,i5,i6,i7,(i8 and i9)/
+ //
+
+ pos = ipos[1];
+ for (j = 1, k = 2; k < nbPulse; j++, k++)
+ {
+ ipos[j] = ipos[k];
+ }
+ ipos[sub(nbPulse,1)] = pos;
+ } // end 1..nbTracks loop
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void search_10and8i40(
+ Word16 nbPulse, /* i : nbpulses to find */
+ Word16 step, /* i : stepsize */
+ Word16 nbTracks, /* i : nbTracks */
+ Word16 dn[], /* i : correlation between target and h[] */
+ Word16 rr[][L_CODE], /* i : matrix of autocorrelation */
+ Word16 ipos[], /* i : starting position for each pulse */
+ Word16 pos_max[], /* i : position of maximum of dn[] */
+ Word16 codvec[], /* o : algebraic codebook vector */
+ Flag *pOverflow /* i/o : overflow flag */
+)
+{
+ Word16 i0, i1, i2, i3, i4, i5, i6, i7, i9;
+ Word16 i, j, k/*, m*/;
+ Word16 pos, ia, ib;
+ Word16 psk;
+ Word16 sq, sq2;
+ Word16 alpk, alp, alp_16;
+ Word32 s;
+ Word32 alp0, alp1, alp2;
+ Word16 gsmefrFlag;
+ Word16 *p_codvec = codvec;
+ Word16 *p_temp2;
+
+ Word16 temp1[2*L_CODE];
+ Word16 *p_temp1;
+ Word16 ps2;
+ Word16 ps1;
+ Word16 ps;
+ Word16 ps0;
+
+ Word16 index[10];
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ if (nbPulse == 10)
+ {
+ gsmefrFlag = 1;
+ }
+ else
+ {
+ gsmefrFlag = 0;
+ }
+
+ /* fix i0 on maximum of correlation position */
+ i0 = pos_max[ipos[0]];
+ index[0] = i0;
+ /*------------------------------------------------------------------*
+ * i1 loop: *
+ *------------------------------------------------------------------*/
+
+ /* Default value */
+ psk = -1;
+ alpk = 1;
+ for (i = 0; i < nbPulse; i++)
+ {
+ *(p_codvec++) = i;
+ }
+
+ for (i = 1; i < nbTracks; i++)
+ {
+ i1 = pos_max[ipos[1]];
+ index[1] = i1;
+
+ /* ps0 = add (dn[i0], dn[i1], pOverflow);*/
+ ps0 = (Word16)((Word32) dn[i0] + dn[i1]);
+
+ /* alp0 = L_mult (rr[i0][i0], _1_16, pOverflow); */
+ alp0 = (Word32) rr[i0][i0] << 12;
+
+ /* alp0 = L_mac (alp0, rr[i1][i1], _1_16, pOverflow); */
+ alp0 += (Word32) rr[i1][i1] << 12;
+
+ /* alp0 = L_mac (alp0, rr[i0][i1], _1_8, pOverflow); */
+ alp0 += (Word32) rr[i0][i1] << 13;
+ alp0 += 0x00008000L;
+
+ /*----------------------------------------------------------------*
+ * i2 and i3 loop: *
+ *----------------------------------------------------------------*/
+
+ p_temp1 = temp1;
+ for (i3 = ipos[3]; i3 < L_CODE; i3 += step)
+ {
+ p_temp2 = &rr[i3][0];
+ s = (Word32) * (p_temp2 + i3) >> 1;
+ s += (Word32) * (p_temp2 + i0);
+ s += (Word32) * (p_temp2 + i1);
+ *(p_temp1++) = ps0 + dn[i3];
+ *(p_temp1++) = (Word16)((s + 2) >> 2);
+ }
+
+ /* Default value */
+ sq = -1;
+ alp = 1;
+ ps = 0;
+ ia = ipos[2];
+ ib = ipos[3];
+
+ s = (alp0 >> 12);
+
+ for (j = ipos[2]; j < L_CODE; j += step)
+ {
+ /* index increment = step */
+ p_temp2 = &rr[j][0];
+
+ alp1 = (s + (Word32) * (p_temp2 + j)) >> 1;
+
+ alp1 += (Word32) * (p_temp2 + i0);
+
+ alp1 += (Word32) * (p_temp2 + i1);
+
+ p_temp1 = temp1;
+ ps1 = dn[j];
+
+
+ for (i3 = ipos[3]; i3 < L_CODE; i3 += step)
+ {
+ /* index increment = step */
+ ps2 = ps1 + *(p_temp1++);
+
+ sq2 = (Word16)(((Word32) ps2 * ps2) >> 15);
+
+ alp2 = (alp1 + p_temp2[i3]) >> 2;
+ alp2 = (alp2 + *(p_temp1++)) >> 1; /* alp2 is always > 0 */
+ if (((Word32) sq2 * alp) > ((Word32) sq * alp2))
+ {
+ sq = sq2;
+ ps = ps2;
+ alp = (Word16)alp2;
+ ia = j;
+ ib = i3;
+ }
+ }
+
+ }
+ i2 = ia;
+ i3 = ib;
+ index[2] = ia;
+ index[3] = ib;
+
+ /*----------------------------------------------------------------*
+ * i4 and i5 loop: *
+ *----------------------------------------------------------------*/
+
+ alp0 = ((Word32) alp << 15) + 0x00008000L;
+ p_temp1 = temp1;
+
+ for (i5 = ipos[5]; i5 < L_CODE; i5 += step)
+ {
+ p_temp2 = &rr[i5][0];
+ s = (Word32) * (p_temp2 + i5) >> 1;
+ s += (Word32) * (p_temp2 + i0);
+ s += (Word32) * (p_temp2 + i1);
+ s += (Word32) * (p_temp2 + i2);
+ s += (Word32) * (p_temp2 + i3);
+
+ *(p_temp1++) = ps + dn[i5];
+ *(p_temp1++) = (Word16)((s + 2) >> 2);
+ }
+
+ /* Default value */
+ sq = -1;
+ alp = 1;
+ ps = 0;
+ ia = ipos[4];
+ ib = ipos[5];
+
+ for (j = ipos[4]; j < L_CODE; j += step)
+ {
+ /* ps1 = add (ps0, dn[i4], pOverflow); */
+ p_temp2 = &rr[j][0];
+
+ /* alp1 = L_mac (alp0, rr[i4][i4], _1_32, pOverflow); */
+ alp1 = alp0 + ((Word32) * (p_temp2 + j) << 11);
+
+ /* alp1 = L_mac (alp1, rr[i0][i4], _1_16, pOverflow); */
+ alp1 += (Word32) * (p_temp2 + i0) << 12;
+
+ /* alp1 = L_mac (alp1, rr[i1][i4], _1_16, pOverflow); */
+ alp1 += (Word32) * (p_temp2 + i1) << 12;
+
+ /* alp1 = L_mac (alp1, rr[i2][i4], _1_16, pOverflow); */
+ alp1 += (Word32) * (p_temp2 + i2) << 12;
+
+ /* alp1 = L_mac (alp1, rr[i3][i4], _1_16, pOverflow); */
+ alp1 += (Word32) * (p_temp2 + i3) << 12;
+
+ p_temp1 = temp1;
+ ps1 = dn[j];
+
+ for (i5 = ipos[5]; i5 < L_CODE; i5 += step)
+ {
+ ps2 = ps1 + *(p_temp1++);
+
+ alp2 = alp1 + ((Word32) * (p_temp2 + i5) << 12);
+
+ alp_16 = (Word16)((alp2 + ((Word32) * (p_temp1++) << 14)) >> 16);
+ sq2 = (Word16)(((Word32) ps2 * ps2) >> 15);
+
+ if (((Word32) sq2 * alp) > ((Word32) sq * alp_16))
+ {
+ sq = sq2;
+ ps = ps2;
+ alp = alp_16;
+ ia = j;
+ ib = i5;
+ }
+
+ }
+ }
+ i4 = ia;
+ i5 = ib;
+ index[4] = ia;
+ index[5] = ib;
+
+ /*----------------------------------------------------------------*
+ * i6 and i7 loop: *
+ *----------------------------------------------------------------*/
+
+ alp0 = ((Word32) alp << 15) + 0x00008000L;
+
+ p_temp1 = temp1;
+
+ for (i7 = ipos[7]; i7 < L_CODE; i7 += step)
+ {
+ s = (Word32) rr[i7][i7] >> 1;
+ s += (Word32) rr[i0][i7];
+ s += (Word32) rr[i1][i7];
+ s += (Word32) rr[i2][i7];
+ s += (Word32) rr[i3][i7];
+ s += (Word32) rr[i4][i7];
+ s += (Word32) rr[i5][i7];
+ *(p_temp1++) = ps + dn[i7];
+ *(p_temp1++) = (Word16)((s + 4) >> 3);
+ }
+
+
+ /* Default value */
+ sq = -1;
+ alp = 1;
+ ps = 0;
+ ia = ipos[6];
+ ib = ipos[7];
+
+ for (j = ipos[6]; j < L_CODE; j += step)
+ {
+ /* ps1 = add (ps0, dn[i6], pOverflow); */
+
+ p_temp2 = (Word16 *) & rr[j];
+
+ /* alp1 = L_mac (alp0, rr[i6][i6], _1_64, pOverflow); */
+ alp1 = alp0 + ((Word32) * (p_temp2 + j) << 10);
+
+ /* alp1 = L_mac (alp1, rr[i0][i6], _1_32, pOverflow); */
+ alp1 += (Word32) * (p_temp2 + i0) << 11;
+
+
+ /* alp1 = L_mac (alp1, rr[i1][i6], _1_32, pOverflow); */
+ alp1 += (Word32) * (p_temp2 + i1) << 11;
+
+ /* alp1 = L_mac (alp1, rr[i2][i6], _1_32, pOverflow); */
+ alp1 += (Word32) * (p_temp2 + i2) << 11;
+
+ /* alp1 = L_mac (alp1, rr[i3][i6], _1_32, pOverflow); */
+ alp1 += (Word32) * (p_temp2 + i3) << 11;
+
+ /* alp1 = L_mac (alp1, rr[i4][i6], _1_32, pOverflow); */
+ alp1 += (Word32) * (p_temp2 + i4) << 11;
+
+ /* alp1 = L_mac (alp1, rr[i5][i6], _1_32, pOverflow); */
+ alp1 += (Word32) * (p_temp2 + i5) << 11;
+
+ p_temp1 = temp1;
+ ps1 = dn[j];
+
+ for (i7 = ipos[7]; i7 < L_CODE; i7 += step)
+ {
+ ps2 = ps1 + *(p_temp1++);
+
+ alp2 = alp1 + ((Word32) * (p_temp2 + i7) << 11);
+
+ alp_16 = (Word16)((alp2 + ((Word32) * (p_temp1++) << 14)) >> 16);
+
+ sq2 = (Word16)(((Word32) ps2 * ps2) >> 15);
+
+ if (((Word32) sq2 * alp) > ((Word32) sq * alp_16))
+ {
+ sq = sq2;
+ ps = ps2;
+ alp = alp_16;
+ ia = j;
+ ib = i7;
+ }
+ }
+ }
+
+ i6 = ia;
+ i7 = ib;
+ index[6] = ia;
+ index[7] = ib;
+
+ /* now finished searching a set of 8 pulses */
+
+ if (gsmefrFlag != 0)
+ {
+ /* go on with the two last pulses for GSMEFR */
+ /*----------------------------------------------------------------*
+ * i8 and i9 loop: *
+ *----------------------------------------------------------------*/
+
+ alp0 = ((Word32) alp << 15) + 0x00008000L;
+
+ p_temp1 = temp1;
+
+ for (i9 = ipos[9]; i9 < L_CODE; i9 += step)
+ {
+ s = (Word32) rr[i9][i9] >> 1;
+ s += (Word32) rr[i0][i9];
+ s += (Word32) rr[i1][i9];
+ s += (Word32) rr[i2][i9];
+ s += (Word32) rr[i3][i9];
+ s += (Word32) rr[i4][i9];
+ s += (Word32) rr[i5][i9];
+ s += (Word32) rr[i6][i9];
+ s += (Word32) rr[i7][i9];
+
+ *(p_temp1++) = ps + dn[i9];
+ *(p_temp1++) = (Word16)((s + 4) >> 3);
+ }
+
+ /* Default value */
+ sq = -1;
+ alp = 1;
+ ps = 0;
+ ia = ipos[8];
+ ib = ipos[9];
+
+ for (j = ipos[8]; j < L_CODE; j += step)
+ {
+ /* ps1 = add (ps0, dn[i8], pOverflow); */
+ p_temp2 = &rr[j][0];
+
+ /* alp1 = L_mac (alp0, rr[i8][i8], _1_128, pOverflow); */
+ alp1 = alp0 + ((Word32) * (p_temp2 + j) << 9);
+
+ /* alp1 = L_mac (alp1, rr[i0][i8], _1_64, pOverflow); */
+ alp1 += (Word32) rr[i0][j] << 10;
+
+ /* alp1 = L_mac (alp1, rr[i1][i8], _1_64, pOverflow); */
+ alp1 += (Word32) rr[i1][j] << 10;
+
+ /* alp1 = L_mac (alp1, rr[i2][i8], _1_64, pOverflow); */
+ alp1 += (Word32) rr[i2][j] << 10;
+
+ /* alp1 = L_mac (alp1, rr[i3][i8], _1_64, pOverflow); */
+ alp1 += (Word32) rr[i3][j] << 10;
+
+ /* alp1 = L_mac (alp1, rr[i4][i8], _1_64, pOverflow); */
+ alp1 += (Word32) rr[i4][j] << 10;
+
+ /* alp1 = L_mac (alp1, rr[i5][i8], _1_64, pOverflow); */
+ alp1 += (Word32) rr[i5][j] << 10;
+
+ /* alp1 = L_mac (alp1, rr[i6][i8], _1_64, pOverflow); */
+ alp1 += (Word32) rr[i6][j] << 10;
+
+ /* alp1 = L_mac (alp1, rr[i7][i8], _1_64, pOverflow); */
+ alp1 += (Word32) rr[i7][j] << 10;
+
+ p_temp1 = temp1;
+ ps1 = dn[j];
+
+ for (i9 = ipos[9]; i9 < L_CODE; i9 += step)
+ {
+ /* ps2 = add (ps1, dn[i9], pOverflow); */
+ ps2 = ps1 + *(p_temp1++);
+
+ /* sq2 = mult (ps2, ps2, pOverflow); */
+ sq2 = (Word16)(((Word32) ps2 * ps2) >> 15);
+
+ /* alp2 = L_mac (alp1, rrv[i9], _1_8, pOverflow); */
+ alp2 = alp1 + ((Word32) * (p_temp2 + i9) << 10) ;
+
+ /* alp2 = L_mac (alp2, rr[i8][i9], _1_64, pOverflow); */
+ alp_16 = (Word16)((alp2 + ((Word32) * (p_temp1++) << 13)) >> 16);
+
+ if (((Word32) sq2 * alp) > ((Word32) sq * alp_16))
+ {
+ sq = sq2;
+ ps = ps2;
+ alp = alp_16;
+ ia = j;
+ ib = i9;
+ }
+ }
+ }
+
+ index[8] = ia;
+ index[9] = ib;
+
+ }/* end gsmefrFlag */
+
+ /*---------------------------------------------------------------- *
+ * test and memorise if this combination is better than the last one.*
+ *----------------------------------------------------------------*/
+
+ if (((Word32) alpk * sq) > ((Word32) psk * alp))
+ {
+ psk = sq;
+ alpk = alp;
+
+ if (gsmefrFlag != 0)
+ {
+ memcpy(codvec, index, (2*NB_TRACK)*sizeof(*index));
+ }
+ else
+ {
+ memcpy(codvec, index, (2*NB_TRACK_MR102)*sizeof(*index));
+ }
+
+ }
+ /*----------------------------------------------------------------*
+ * Cyclic permutation of i1,i2,i3,i4,i5,i6,i7,(i8 and i9). *
+ *----------------------------------------------------------------*/
+
+ pos = ipos[1];
+ for (j = 1, k = 2; k < nbPulse; j++, k++)
+ {
+ ipos[j] = ipos[k];
+ }
+ ipos[nbPulse-1] = pos;
+ } /* end 1..nbTracks loop*/
+}
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/s10_8pf.h b/media/libstagefright/codecs/amrnb/enc/src/s10_8pf.h
new file mode 100644
index 0000000..7591f5f
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/s10_8pf.h
@@ -0,0 +1,128 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/s10_8pf.h
+
+
+
+
+ Date: 08/11/2000
+
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description: Changed function prototype; pointer to overflow flag is passed
+ in as a parameter. Updated template
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the s10_8pf module.
+------------------------------------------------------------------------------
+*/
+
+#ifndef S10_8PF_H
+#define S10_8PF_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+#include "cnst.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void search_10and8i40(
+ Word16 nbPulse, /* i : nbpulses to find */
+ Word16 step, /* i : stepsize */
+ Word16 nbTracks, /* i : nbTracks */
+ Word16 dn[], /* i : correlation between target and h[] */
+ Word16 rr[][L_CODE], /* i : matrix of autocorrelation */
+ Word16 ipos[], /* i : starting position for each pulse */
+ Word16 pos_max[], /* i : position of maximum of dn[] */
+ Word16 codvec[], /* o : algebraic codebook vector */
+ Flag *pOverflow /* i/o : Overflow flag */
+ );
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _S10_8PF_H_ */
diff --git a/media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp b/media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp
new file mode 100644
index 0000000..d626de3
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/set_sign.cpp
@@ -0,0 +1,609 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/set_sign.c
+ Funtions: set_sign
+ set_sign12k2
+
+ Date: 05/26/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed into PV template and optimized.
+
+ Description: Synchronized file with UMTS version 3.2.0. Updated coding
+ template. Removed unnecessary include files.
+
+ Description: Replaced basic_op.h with the header files of the math functions
+ used in the file.
+
+ Description: Made the following changes per comments from Phase 2/3 review:
+ 1. Modified certain FOR loops to count down.
+ 2. Modified code for further optimization.
+
+ Description: Modified FOR loops in set_sign12k2 to count up. The FOR loops
+ affected are the loop that calculates the starting position of
+ each incoming pulse, and the loop that calculates the position
+ of the max correlation. Updated copyright year.
+
+ Description: Passing in pointer to overflow flag for EPOC compatibility.
+
+ Description: For set_sign12k2()
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated math operations that unnecessary checked for
+ saturation, this by evaluating the operands
+ 4. Replaced loop counter with decrement loops
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Changed round function name to pv_round to avoid conflict with
+ round function in C standard library.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This module contains the functions set_sign and set_sign12k2.
+ These functions are used to build a sign vector according
+ to the values in the input arrays. These functions also
+ find the position in the input codes of the maximum correlation
+ and the starting position for each pulse.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "set_sign.h"
+#include "basic_op.h"
+#include "inv_sqrt.h"
+#include "cnst.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: set_sign
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ dn = buffer of correlation values (Word16)
+ sign = buffer containing sign of dn elements (Word16)
+ dn2 = buffer containing the maximum of correlation in each track.(Word16)
+ n = number of maximum correlations in dn2 (Word16)
+
+ Returns:
+ None
+
+ Outputs:
+ dn buffer is modified to contain the absolute value of its input
+ sign buffer is modified to contain the sign information for the
+ values in dn buffer
+ dn2 buffer is modified to denote the location of the maximum
+ correlation for each track.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+ This function builds sign vector according to dn buffer It also finds
+ the position of maximum of correlation in each track and the starting
+ position for each pulse.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ set_sign.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void set_sign(Word16 dn[], i/o : correlation between target and h[]
+ Word16 sign[], o : sign of dn[]
+ Word16 dn2[], o : maximum of correlation in each track.
+ Word16 n i : # of maximum correlations in dn2[]
+)
+{
+ Word16 i, j, k;
+ Word16 val, min;
+ Word16 pos = 0; //initialization only needed to keep gcc silent
+
+ // set sign according to dn[]
+
+ for (i = 0; i < L_CODE; i++) {
+ val = dn[i];
+
+ if (val >= 0) {
+ sign[i] = 32767;
+ } else {
+ sign[i] = -32767;
+ val = negate(val);
+ }
+ dn[i] = val; // modify dn[] according to the fixed sign
+ dn2[i] = val;
+ }
+
+ // keep 8-n maximum positions/8 of each track and store it in dn2[]
+
+ for (i = 0; i < NB_TRACK; i++)
+ {
+ for (k = 0; k < (8-n); k++)
+ {
+ min = 0x7fff;
+ for (j = i; j < L_CODE; j += STEP)
+ {
+ if (dn2[j] >= 0)
+ {
+ val = sub(dn2[j], min);
+
+ if (val < 0)
+ {
+ min = dn2[j];
+ pos = j;
+ }
+ }
+ }
+ dn2[pos] = -1;
+ }
+ }
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void set_sign(Word16 dn[], /* i/o : correlation between target and h[] */
+ Word16 sign[], /* o : sign of dn[] */
+ Word16 dn2[], /* o : maximum of correlation in each track. */
+ Word16 n /* i : # of maximum correlations in dn2[] */
+ )
+{
+ register Word16 i, j, k;
+ Word16 val, min;
+ Word16 pos = 0; /* initialization only needed to keep gcc silent */
+
+ /* set sign according to dn[] */
+ for (i = L_CODE - 1; i >= 0; i--)
+ {
+ val = dn[i];
+
+ if (val >= 0)
+ {
+ sign[i] = 32767;
+ }
+ else
+ {
+ sign[i] = -32767;
+ val = negate(val);
+ dn[i] = val; /* modify dn[] according to the fixed sign */
+ }
+
+ dn2[i] = val;
+ }
+
+ /* keep 8-n maximum positions/8 of each track and store it in dn2[] */
+
+ for (i = 0; i < NB_TRACK; i++)
+ {
+ for (k = 0; k < (8 - n); k++)
+ {
+ min = 0x7fff;
+ for (j = i; j < L_CODE; j += STEP)
+ {
+ if (dn2[j] >= 0)
+ {
+ if (dn2[j] < min)
+ {
+ min = dn2[j];
+ pos = j;
+ }
+ }
+ }
+ dn2[pos] = -1;
+ }
+ }
+
+ return;
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: set_sign12k2()
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ dn = buffer of correlation values (Word16)
+ cn = buffer of residual after long term prediction (Word16)
+ sign = sign of correlation buffer elements (Word16)
+ pos_max = buffer containing position of maximum correlation (Word16)
+ nb_track = number of tracks (Word16)
+ ipos = buffer containing the starting position for each pulse (Word16)
+ step = step size in the tracks (Word16)
+ pOverflow = pointer to Overflow flag (Flag)
+
+ Outputs:
+ sign buffer contains the sign of correlation values
+ dn buffer contains the sign-adjusted correlation values
+ pos_max buffer contains the maximum correlation position
+ ipos buffer contains the starting position of each pulse
+ pOverflow -> 1 if the math operations called by this function result in
+ saturation
+
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function builds the sign vector according to dn and cn, and modifies
+ dn to include the sign information (dn[i]=sign[i]*dn[i]). It also finds
+ the position of maximum of correlation in each track and the starting
+ position for each pulse.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ set_sign.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void set_sign12k2 (
+ Word16 dn[], //i/o : correlation between target and h[]
+ Word16 cn[], //i : residual after long term prediction
+ Word16 sign[], //o : sign of d[n]
+ Word16 pos_max[], //o : position of maximum correlation
+ Word16 nb_track, //i : number of tracks tracks
+ Word16 ipos[], //o : starting position for each pulse
+ Word16 step //i : the step size in the tracks
+)
+{
+ Word16 i, j;
+ Word16 val, cor, k_cn, k_dn, max, max_of_all;
+ Word16 pos = 0; // initialization only needed to keep gcc silent
+ Word16 en[L_CODE]; // correlation vector
+ Word32 s;
+
+ // The reference ETSI code uses a global flag for Overflow. However in the
+ // actual implementation a pointer to the overflow flag is passed in. This
+ // pointer is passed into the basic math functions called by this routine.
+
+ // calculate energy for normalization of cn[] and dn[]
+
+ s = 256;
+ for (i = 0; i < L_CODE; i++)
+ {
+ s = L_mac (s, cn[i], cn[i]);
+ }
+ s = Inv_sqrt (s);
+ k_cn = extract_h (L_shl (s, 5));
+
+ s = 256;
+ for (i = 0; i < L_CODE; i++)
+ {
+ s = L_mac (s, dn[i], dn[i]);
+ }
+ s = Inv_sqrt (s);
+ k_dn = extract_h (L_shl (s, 5));
+
+ for (i = 0; i < L_CODE; i++)
+ {
+ val = dn[i];
+ cor = pv_round (L_shl (L_mac (L_mult (k_cn, cn[i]), k_dn, val), 10));
+
+ if (cor >= 0)
+ {
+ sign[i] = 32767; // sign = +1
+ }
+ else
+ {
+ sign[i] = -32767; // sign = -1
+ cor = negate (cor);
+ val = negate (val);
+ }
+ // modify dn[] according to the fixed sign
+ dn[i] = val;
+ en[i] = cor;
+ }
+
+ max_of_all = -1;
+ for (i = 0; i < nb_track; i++)
+ {
+ max = -1;
+
+ for (j = i; j < L_CODE; j += step)
+ {
+ cor = en[j];
+ val = sub (cor, max);
+
+ if (val > 0)
+ {
+ max = cor;
+ pos = j;
+ }
+ }
+ // store maximum correlation position
+ pos_max[i] = pos;
+ val = sub (max, max_of_all);
+
+ if (val > 0)
+ {
+ max_of_all = max;
+ // starting position for i0
+ ipos[0] = i;
+ }
+ }
+
+ //
+ // Set starting position of each pulse.
+ //
+
+ pos = ipos[0];
+ ipos[nb_track] = pos;
+
+ for (i = 1; i < nb_track; i++)
+ {
+ pos = add (pos, 1);
+
+ if (sub (pos, nb_track) >= 0)
+ {
+ pos = 0;
+ }
+ ipos[i] = pos;
+ ipos[add(i, nb_track)] = pos;
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void set_sign12k2(
+ Word16 dn[], /* i/o : correlation between target and h[] */
+ Word16 cn[], /* i : residual after long term prediction */
+ Word16 sign[], /* o : sign of d[n] */
+ Word16 pos_max[], /* o : position of maximum correlation */
+ Word16 nb_track, /* i : number of tracks tracks */
+ Word16 ipos[], /* o : starting position for each pulse */
+ Word16 step, /* i : the step size in the tracks */
+ Flag *pOverflow /* i/o: overflow flag */
+)
+{
+ Word16 i, j;
+ Word16 val;
+ Word16 cor;
+ Word16 k_cn;
+ Word16 k_dn;
+ Word16 max;
+ Word16 max_of_all;
+ Word16 pos = 0; /* initialization only needed to keep gcc silent */
+ Word16 en[L_CODE]; /* correlation vector */
+ Word32 s;
+ Word32 t;
+ Word32 L_temp;
+ Word16 *p_cn;
+ Word16 *p_dn;
+ Word16 *p_sign;
+ Word16 *p_en;
+
+ /* calculate energy for normalization of cn[] and dn[] */
+
+ s = 256;
+ t = 256;
+ p_cn = cn;
+ p_dn = dn; /* crosscorrelation values do not have strong peaks, so
+ scaling applied in cor_h_x (sf=2) guaranteed that the
+ mac of the energy for this vector will not overflow */
+
+ for (i = L_CODE; i != 0; i--)
+ {
+ val = *(p_cn++);
+ s = L_mac(s, val, val, pOverflow);
+ val = *(p_dn++);
+ t += ((Word32) val * val) << 1;
+ }
+ s = Inv_sqrt(s, pOverflow);
+ k_cn = (Word16)((L_shl(s, 5, pOverflow)) >> 16);
+
+ t = Inv_sqrt(t, pOverflow);
+ k_dn = (Word16)(t >> 11);
+
+ p_cn = &cn[L_CODE-1];
+ p_sign = &sign[L_CODE-1];
+ p_en = &en[L_CODE-1];
+
+ for (i = L_CODE - 1; i >= 0; i--)
+ {
+ L_temp = ((Word32)k_cn * *(p_cn--)) << 1;
+ val = dn[i];
+ s = L_mac(L_temp, k_dn, val, pOverflow);
+ L_temp = L_shl(s, 10, pOverflow);
+ cor = pv_round(L_temp, pOverflow);
+
+ if (cor >= 0)
+ {
+ *(p_sign--) = 32767; /* sign = +1 */
+ }
+ else
+ {
+ *(p_sign--) = -32767; /* sign = -1 */
+ cor = negate(cor);
+
+ /* modify dn[] according to the fixed sign */
+ dn[i] = negate(val);
+ }
+
+ *(p_en--) = cor;
+ }
+
+ max_of_all = -1;
+ for (i = 0; i < nb_track; i++)
+ {
+ max = -1;
+
+ for (j = i; j < L_CODE; j += step)
+ {
+ cor = en[j];
+ if (cor > max)
+ {
+ max = cor;
+ pos = j;
+ }
+ }
+ /* store maximum correlation position */
+ pos_max[i] = pos;
+ if (max > max_of_all)
+ {
+ max_of_all = max;
+ /* starting position for i0 */
+ ipos[0] = i;
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ * Set starting position of each pulse. *
+ *----------------------------------------------------------------*/
+
+ pos = ipos[0];
+ ipos[nb_track] = pos;
+
+ for (i = 1; i < nb_track; i++)
+ {
+ pos++;
+
+ if (pos >= nb_track)
+ {
+ pos = 0;
+ }
+ ipos[ i] = pos;
+ ipos[ i + nb_track] = pos;
+ }
+
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/set_sign.h b/media/libstagefright/codecs/amrnb/enc/src/set_sign.h
new file mode 100644
index 0000000..7b0185a
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/set_sign.h
@@ -0,0 +1,127 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/set_sign.h
+
+ Date: 08/11/2000
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description: Changed function prototype for set_sign12k2(); pointer to
+ overflow flag is passed in as a parameter.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the set_sign() and set_sign12k2() function.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef SET_SIGN_H
+#define SET_SIGN_H "@(#)$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "basicop_malloc.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void set_sign(Word16 dn[], /* i/o : correlation between target and h[] */
+ Word16 sign[], /* o : sign of dn[] */
+ Word16 dn2[], /* o : maximum of correlation in each track. */
+ Word16 n /* i : # of maximum correlations in dn2[] */
+ );
+
+ void set_sign12k2(
+ Word16 dn[], /* i/o : correlation between target and h[] */
+ Word16 cn[], /* i : residual after long term prediction */
+ Word16 sign[], /* o : sign of d[n] */
+ Word16 pos_max[], /* o : position of maximum correlation */
+ Word16 nb_track, /* i : number of tracks tracks */
+ Word16 ipos[], /* o : starting position for each pulse */
+ Word16 step, /* i : the step size in the tracks */
+ Flag *pOverflow /* i/o : overflow flag */
+ );
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SET_SIGN_H_ */
diff --git a/media/libstagefright/codecs/amrnb/enc/src/sid_sync.cpp b/media/libstagefright/codecs/amrnb/enc/src/sid_sync.cpp
new file mode 100644
index 0000000..3e744f6
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/sid_sync.cpp
@@ -0,0 +1,544 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm-amr/c/src/sid_sync.c
+ Functions: sid_sync_init
+ sid_sync_reset
+ sid_sync_exit
+ sid_sync_set_handover_debt
+ sid_sync
+
+ Date: 03/13/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Changed type definition of state pointer to 'void' for
+ sid_sync_init, sid_sync_reset, sid_sync_exit, and sid_sync.
+ Updated to PV coding template.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the functions that initialize, reset, exit, and perform
+ SID synchronization.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "mode.h"
+#include "sid_sync.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; [Define module specific macros here]
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; [Include all pre-processor statements here. Include conditional
+; compile variables also.]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; [List function prototypes here]
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; [Variable declaration - defined here and used outside this module]
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: sid_sync_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer containing a pointer to the state structure used for
+ SID synchronization (void)
+
+ Outputs:
+ None
+
+ Returns:
+ return_value = status of sid_sync_reset function; -1, if state is pointing
+ to a NULL address (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function initialize one instance of the sid_sync module. It stores
+ the pointer to state struct in *st. This pointer has to be passed to sid_sync
+ in each call. This function returns 0 on success, otherwise, -1.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sid_sync.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 sid_sync_init(void **state)
+{
+ sid_syncState* s;
+
+ if (state == NULL)
+ {
+ /* fprintf(stderr, "sid_sync_init:invalid state parameter\n"); */
+ return -1;
+ }
+
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (sid_syncState *)
+ malloc(sizeof(sid_syncState))) == NULL)
+ {
+ /* fprintf(stderr,
+ "sid_sync_init: "
+ "can not malloc state structure\n"); */
+ return -1;
+ }
+ s->sid_update_rate = 8;
+
+ *state = (void *)s;
+
+ return(sid_sync_reset(s));
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: sid_sync_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to the state structure used for SID synchronization (void)
+
+ Outputs:
+ None
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs a reset of the sid_sync module by setting the state
+ memory to zero.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sid_sync.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+Word16 sid_sync_reset(void *st)
+{
+ sid_syncState *state = (sid_syncState *) st;
+
+ state->sid_update_counter = 3;
+ state->sid_handover_debt = 0;
+ state->prev_ft = TX_SPEECH_GOOD;
+
+ return 0;
+}
+
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: sid_sync_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer containing a pointer to the state structure used for
+ SID synchronization (void)
+
+ Outputs:
+ None
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function frees up the state structure used by sid_sync function. It
+ stores NULL in *state.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sid_sync.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void sid_sync_exit(void **state)
+{
+ sid_syncState **st = (sid_syncState **) state;
+
+ if (st == NULL || *st == NULL)
+ {
+ return;
+ }
+
+ /* deallocate memory */
+ free(*st);
+ *st = NULL;
+
+ return;
+
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: sid_sync_set_handover_debt
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to the state structure used for SID synchronization
+ (sid_syncState)
+ debtFrames = number of handover debt frames (Word16)
+
+ Outputs:
+ st->sid_handover_debt is set to debtFrames
+
+ Returns:
+ return_value = 0
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function updates the handover debt to debtFrames. Extra SID_UPD are
+ scheduled to update remote decoder CNI states, right after an handover.
+ This is primarily for use on MS UL side.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sid_sync.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void sid_sync_set_handover_debt(sid_syncState *st,
+ Word16 debtFrames)
+{
+ /* debtFrames >= 0 */
+ st->sid_handover_debt = debtFrames;
+ return;
+}
+
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: sid_sync
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to the state structure used for SID synchronization
+ (sid_syncState)
+ mode = codec mode (enum Mode)
+ tx_frame_type = pointer to TX frame type store (enum TXFrameType)
+
+ Outputs:
+ tx_frame_type contains the new TX frame type
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs SID frame synchronization to ensure that the mode
+ only switches to a neighbouring mode.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sid_sync.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+void sid_sync(void *state,
+ enum Mode mode,
+ enum TXFrameType *tx_frame_type)
+{
+
+ sid_syncState *st = (sid_syncState *) state;
+
+ if (mode == MRDTX)
+ {
+
+ st->sid_update_counter--;
+
+ if (st->prev_ft == TX_SPEECH_GOOD)
+ {
+ *tx_frame_type = TX_SID_FIRST;
+ st->sid_update_counter = 3;
+ }
+ else
+ {
+ /* TX_SID_UPDATE or TX_NO_DATA */
+ if ((st->sid_handover_debt > 0) &&
+ (st->sid_update_counter > 2))
+ {
+ /* ensure extra updates are properly delayed after
+ a possible SID_FIRST */
+ *tx_frame_type = TX_SID_UPDATE;
+ st->sid_handover_debt--;
+ }
+ else
+ {
+ if (st->sid_update_counter == 0)
+ {
+ *tx_frame_type = TX_SID_UPDATE;
+ st->sid_update_counter = st->sid_update_rate;
+ }
+ else
+ {
+ *tx_frame_type = TX_NO_DATA;
+ }
+ }
+ }
+ }
+ else
+ {
+ st->sid_update_counter = st->sid_update_rate ;
+ *tx_frame_type = TX_SPEECH_GOOD;
+ }
+ st->prev_ft = *tx_frame_type;
+}
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/sid_sync.h b/media/libstagefright/codecs/amrnb/enc/src/sid_sync.h
new file mode 100644
index 0000000..c3cb1cf
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/sid_sync.h
@@ -0,0 +1,147 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm-amr/c/include/sid_sync.h
+
+ Date: 03/13/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Added PV coding template sections to 3GPP version 3.2.0.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains the type definition and function prototypes used by the
+ SID synchronization functions.
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef _SID_SYNC_H_
+#define _SID_SYNC_H_
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "frame.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+#define sid_sync_h "$Id $"
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Word16 sid_update_rate; /* Send SID Update every sid_update_rate frame */
+ Word16 sid_update_counter; /* Number of frames since last SID */
+ Word16 sid_handover_debt; /* Number of extra SID_UPD frames to schedule*/
+ enum TXFrameType prev_ft;
+ } sid_syncState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ /* initialize one instance of the sid_sync module
+ Stores pointer to state struct in *st. This pointer has to
+ be passed to sid_sync in each call.
+ returns 0 on success
+ */
+ Word16 sid_sync_init(void **st);
+
+ /* reset of sid_sync module (i.e. set state memory to zero)
+ returns 0 on success
+ */
+ Word16 sid_sync_reset(void *st);
+
+ /* de-initialize sid_sync module (i.e. free status struct)
+ stores NULL in *st
+ */
+ void sid_sync_exit(void **st);
+
+ /* update handover debt
+ debtFrames extra SID_UPD are scheduled .
+ to update remote decoder CNI states, right after an handover.
+ (primarily for use on MS UL side )
+ */
+ void sid_sync_set_handover_debt(sid_syncState *st, /* i/o: sid_sync state */
+ Word16 debtFrames);
+
+ /* To ensure that the mode only switches to a neighbouring mode */
+ void sid_sync(void *st ,
+ enum Mode mode,
+ enum TXFrameType *tx_frame_type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SID_SYNC_H_ */
diff --git a/media/libstagefright/codecs/amrnb/enc/src/sp_enc.cpp b/media/libstagefright/codecs/amrnb/enc/src/sp_enc.cpp
new file mode 100644
index 0000000..77ae9de
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/sp_enc.cpp
@@ -0,0 +1,754 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/sp_enc.c
+ Funtions: GSMInitEncode
+ Speech_Encode_Frame_reset
+ GSMEncodeFrameExit
+ Speech_Encode_Frame_First
+ GSMEncodeFrame
+
+ Date: 02/07/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Cleaned up INCLUDES. removed inclusion of basic_op.h and count.h.
+
+
+ Description: Revert back to Speech_Encode_Frame_reset() and
+ Speech_Encode_Frame_First
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ These functions comprise the pre filtering and encoding of one speech frame.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+
+#include "sp_enc.h"
+#include "typedef.h"
+#include "cnst.h"
+#include "set_zero.h"
+#include "pre_proc.h"
+#include "prm2bits.h"
+#include "mode.h"
+#include "cod_amr.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: GSMInitEncode
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+ Inputs:
+ state = pointer to an array of pointers to structures of type
+ Speech_Decode_FrameState
+ dtx = flag to turn off or turn on DTX (Flag)
+ id = pointer to an array whose contents are of type char
+
+ Outputs:
+ pre_state field of the structure pointed to by the pointer pointed to
+ by state is set to NULL
+ cod_amr_state field of the structure pointed to by the pointer pointed to
+ by state is set to NULL
+ dtx field of the structure pointed to by the pointer pointed to by state
+ is set to the input dtx
+
+ Returns:
+ return_value = set to zero, if initialization was successful; -1,
+ otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function allocates memory for filter structure and initializes state
+ memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sp_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+ Note: Original function name of Speech_Encode_Frame_init was changed to
+ GSMInitEncode in the Code section.
+
+int Speech_Encode_Frame_init (void **state_data,
+ Flag dtx,
+ char *id)
+{
+ Speech_Encode_FrameState* s;
+
+ if (state_data == NULL){
+ fprintf(stderr, "Speech_Encode_Frame_init: invalid parameter\n");
+ return -1;
+ }
+ *state_data = NULL;
+
+ // allocate memory
+ if ((s= (Speech_Encode_FrameState *) malloc(sizeof(Speech_Encode_FrameState))) == NULL){
+ fprintf(stderr, "Speech_Encode_Frame_init: can not malloc state "
+ "structure\n");
+ return -1;
+ }
+
+ s->complexityCounter = getCounterId(id);
+
+ s->pre_state = NULL;
+ s->cod_amr_state = NULL;
+ s->dtx = dtx;
+
+ if (Pre_Process_init(&s->pre_state) ||
+ cod_amr_init(&s->cod_amr_state, s->dtx)) {
+ GSMEncodeFrameExit(&s);
+ return -1;
+ }
+
+ Speech_Encode_Frame_reset(s);
+ *state_data = (void *)s;
+
+ return 0;
+}
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 GSMInitEncode(void **state_data,
+ Flag dtx,
+ Word8 *id)
+{
+ Speech_Encode_FrameState* s;
+
+ OSCL_UNUSED_ARG(id);
+
+ if (state_data == NULL)
+ {
+ /* fprintf(stderr, "Speech_Encode_Frame_init: invalid parameter\n"); */
+ return -1;
+ }
+ *state_data = NULL;
+
+ /* allocate memory */
+ if ((s = (Speech_Encode_FrameState *) malloc(sizeof(Speech_Encode_FrameState))) == NULL)
+ {
+ /* fprintf(stderr, "Speech_Encode_Frame_init: can not malloc state "
+ "structure\n"); */
+ return -1;
+ }
+
+ s->pre_state = NULL;
+ s->cod_amr_state = NULL;
+ s->dtx = dtx;
+
+ if (Pre_Process_init(&s->pre_state) ||
+ cod_amr_init(&s->cod_amr_state, s->dtx))
+ {
+ Speech_Encode_FrameState** temp = &s;
+ GSMEncodeFrameExit((void**)temp);
+ return -1;
+ }
+
+ Speech_Encode_Frame_reset(s);
+ *state_data = (void *)s;
+
+ return 0;
+}
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Speech_Encode_Frame_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to structures of type Speech_Decode_FrameState
+
+ Outputs:
+ None
+
+ Returns:
+ return_value = set to zero if reset was successful; -1, otherwise (int)
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function resets state memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sp_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Speech_Encode_Frame_reset (void *state_data)
+{
+
+ Speech_Encode_FrameState *state =
+ (Speech_Encode_FrameState *) state_data;
+
+ if (state_data == NULL){
+ fprintf(stderr, "Speech_Encode_Frame_reset
+ : invalid parameter\n");
+ return -1;
+ }
+
+ Pre_Process_reset(state->pre_state);
+ cod_amr_reset(state->cod_amr_state);
+
+ setCounter(state->complexityCounter);
+ Init_WMOPS_counter();
+ setCounter(0); // set counter to global counter
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 Speech_Encode_Frame_reset(void *state_data)
+{
+
+ Speech_Encode_FrameState *state =
+ (Speech_Encode_FrameState *) state_data;
+
+ if (state_data == NULL)
+ {
+ /* fprintf(stderr, "Speech_Encode_Frame_reset
+ : invalid parameter\n"); */
+ return -1;
+ }
+
+ Pre_Process_reset(state->pre_state);
+ cod_amr_reset(state->cod_amr_state);
+
+ return 0;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: GSMEncodeFrameExit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to a pointer to a structure of type cod_amrState
+
+ Outputs:
+ state points to a NULL address
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function frees the memory used for state memory.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sp_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Note: Original function name of Speech_Encode_Frame_exit was changed to
+ GSMEncodeFrameExit in the Code section.
+
+void Speech_Encode_Frame_exit (void **state_data)
+{
+
+ Speech_Encode_FrameState **state =
+ (Speech_Encode_FrameState **) state_data;
+
+ if (state == NULL || *state == NULL)
+ return;
+
+ Pre_Process_exit(&(*state)->pre_state);
+ cod_amr_exit(&(*state)->cod_amr_state);
+
+ setCounter((*state)->complexityCounter);
+ WMOPS_output(0);
+ setCounter(0); // set counter to global counter
+
+ // deallocate memory
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void GSMEncodeFrameExit(void **state_data)
+{
+
+ Speech_Encode_FrameState **state =
+ (Speech_Encode_FrameState **) state_data;
+
+ if (state == NULL || *state == NULL)
+ return;
+
+ Pre_Process_exit(&(*state)->pre_state);
+ cod_amr_exit(&(*state)->cod_amr_state);
+
+ /* deallocate memory */
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: Speech_Encode_Frame_First
+------------------------------------------------------------------------------
+
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to a structure of type Speech_Encode_FrameState that contains
+ the post filter states
+ new_speech = pointer to buffer of length L_FRAME that contains
+ the speech input (Word16)
+
+ Outputs:
+ The structure of type Speech_Encode_FrameState pointed to by st is updated.
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function encodes the first frame of speech. It calls the pre-processing
+ filter and the first frame encoder.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sp_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int Speech_Encode_Frame_First (
+ Speech_Encode_FrameState *st, // i/o : post filter states
+ Word16 *new_speech) // i : speech input
+{
+#if !defined(NO13BIT)
+ Word16 i;
+#endif
+
+ setCounter(st->complexityCounter);
+
+#if !defined(NO13BIT)
+ // Delete the 3 LSBs (13-bit input)
+ for (i = 0; i < L_NEXT; i++)
+ {
+ new_speech[i] = new_speech[i] & 0xfff8;
+ }
+#endif
+
+ // filter + downscaling
+ Pre_Process (st->pre_state, new_speech, L_NEXT);
+
+ cod_amr_first(st->cod_amr_state, new_speech);
+
+ Init_WMOPS_counter (); // reset WMOPS counter for the new frame
+
+ return 0;
+}
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void Speech_Encode_Frame_First(
+ Speech_Encode_FrameState *st, /* i/o : post filter states */
+ Word16 *new_speech) /* i : speech input */
+{
+#if !defined(NO13BIT)
+ Word16 i;
+#endif
+
+#if !defined(NO13BIT)
+ /* Delete the 3 LSBs (13-bit input) */
+ for (i = 0; i < L_NEXT; i++)
+ {
+ new_speech[i] = new_speech[i] & 0xfff8;
+ }
+#endif
+
+ /* filter + downscaling */
+ Pre_Process(st->pre_state, new_speech, L_NEXT);
+
+ cod_amr_first(st->cod_amr_state, new_speech);
+
+ return;
+}
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: cod_amr
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state_data = a void pointer to the post filter states
+ mode = AMR mode of type enum Mode
+ new_speech = pointer to buffer of length L_FRAME that contains
+ the speech input of type Word16
+ serial = pointer to the serial bit stream of type Word16
+ usedMode = pointer to the used mode of type enum Mode
+
+ Outputs:
+ serial -> encoded serial bit stream
+ The value pointed to by usedMode is updated.
+
+ Returns:
+ return_value = 0 (int)
+
+ Global Variables Used:
+ None.
+
+ Local Variables Needed:
+ None.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function is the entry point to the GSM AMR encoder. The following
+ operations are performed to generate one encoded frame: First, the incoming
+ audio samples are passed through the pre-processing filter where they are
+ filtered and downscaled. A call is then made to the main encoder cod_amr().
+ This generates the set of encoded parameters which include the LSP, adaptive
+ codebook, and fixed codebook quantization indices (addresses and gains). The
+ generated parameters are then converted to serial bits.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ sp_enc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+ Note: Original function name of Speech_Encode_Frame was changed to
+ GSMEncodeFrame in the Code section.
+
+int Speech_Encode_Frame (
+ void *state_data, // i/o : post filter states
+ enum Mode mode, // i : speech coder mode
+ Word16 *new_speech, // i : speech input
+ Word16 *serial, // o : serial bit stream
+ enum Mode *usedMode // o : used speech coder mode
+ )
+{
+
+ Speech_Encode_FrameState *st =
+ (Speech_Encode_FrameState *) state_data;
+
+ Word16 prm[MAX_PRM_SIZE]; // Analysis parameters
+ Word16 syn[L_FRAME]; // Buffer for synthesis speech
+ Word16 i;
+
+ setCounter(st->complexityCounter);
+ Reset_WMOPS_counter (); // reset WMOPS counter for the new frame
+ // initialize the serial output frame to zero
+ for (i = 0; i < MAX_SERIAL_SIZE; i++)
+ {
+ serial[i] = 0;
+ }
+#if !defined(NO13BIT)
+ // Delete the 3 LSBs (13-bit input)
+ for (i = 0; i < L_FRAME; i++)
+ {
+ new_speech[i] = new_speech[i] & 0xfff8;
+
+
+ }
+#endif
+
+ // filter + downscaling
+ Pre_Process (st->pre_state, new_speech, L_FRAME);
+
+ // Call the speech encoder
+ cod_amr(st->cod_amr_state, mode, new_speech, prm, usedMode, syn);
+
+ // Parameters to serial bits
+ Prm2bits (*usedMode, prm, &serial[0]);
+
+ fwc();
+ setCounter(0); // set counter to global counter
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void GSMEncodeFrame(
+ void *state_data, /* i/o : post filter states */
+ enum Mode mode, /* i : speech coder mode */
+ Word16 *new_speech, /* i : speech input */
+ Word16 *serial, /* o : serial bit stream */
+ enum Mode *usedMode /* o : used speech coder mode */
+)
+{
+
+ Speech_Encode_FrameState *st =
+ (Speech_Encode_FrameState *) state_data;
+
+ Word16 prm[MAX_PRM_SIZE]; /* Analysis parameters. */
+ Word16 syn[L_FRAME]; /* Buffer for synthesis speech */
+ Word16 i;
+
+ /* initialize the serial output frame to zero */
+ for (i = 0; i < MAX_SERIAL_SIZE; i++)
+ {
+ serial[i] = 0;
+ }
+#if !defined(NO13BIT)
+ /* Delete the 3 LSBs (13-bit input) */
+ for (i = 0; i < L_FRAME; i++)
+ {
+ new_speech[i] = new_speech[i] & 0xfff8;
+ }
+#endif
+
+ /* filter + downscaling */
+ Pre_Process(st->pre_state, new_speech, L_FRAME);
+
+ /* Call the speech encoder */
+ cod_amr(st->cod_amr_state, mode, new_speech, prm, usedMode, syn);
+
+ /* Parameters to serial bits */
+ Prm2bits(*usedMode, prm, &serial[0]);
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/sp_enc.h b/media/libstagefright/codecs/amrnb/enc/src/sp_enc.h
new file mode 100644
index 0000000..8eb2a9b
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/sp_enc.h
@@ -0,0 +1,154 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/src/include/sp_enc.h
+
+ Date: 02/07/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template. Changed the function names of
+ Speech_Encode_Frame_reset and Speech_Encode_Frame_first to
+ GSMEncodeFrameReset and GSMEncodeFrameFirst respectively for
+ consistency.
+
+ Description: Reverted back to old function names Speech_Encode_Frame_reset()
+ and Speech_Encode_Frame_First()
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : sp_enc.h
+ Purpose : Encoding of one speech frame
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef sp_enc_h
+#define sp_enc_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "cnst.h"
+#include "pre_proc.h"
+#include "mode.h"
+#include "cod_amr.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; [Define module specific macros here]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; [Include all pre-processor statements here.]
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; [Declare variables used in this module but defined elsewhere]
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef struct
+ {
+ Pre_ProcessState *pre_state;
+ cod_amrState *cod_amr_state;
+ Flag dtx;
+ } Speech_Encode_FrameState;
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; [List function prototypes here]
+ ----------------------------------------------------------------------------*/
+ /* initialize one instance of the speech encoder
+ Stores pointer to filter status struct in *st. This pointer has to
+ be passed to Speech_Encode_Frame in each call.
+ returns 0 on success */
+ Word16 GSMInitEncode(void **state_data,
+ Flag dtx,
+ Word8 *id);
+
+
+ /* reset speech encoder (i.e. set state memory to zero)
+ returns 0 on success */
+ Word16 Speech_Encode_Frame_reset(void *state_data);
+
+ /* de-initialize speech encoder (i.e. free status struct)
+ stores NULL in *s */
+ void GSMEncodeFrameExit(void **state_data);
+
+ void Speech_Encode_Frame_First(
+ Speech_Encode_FrameState *st, /* i/o : post filter states */
+ Word16 *new_speech); /* i : speech input */
+
+ void GSMEncodeFrame(
+ void *state_data, /* i/o : encoder states */
+ enum Mode mode, /* i : speech coder mode */
+ Word16 *new_speech, /* i : input speech */
+ Word16 *serial, /* o : serial bit stream */
+ enum Mode *usedMode /* o : used speech coder mode */
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _sp_enc_h_ */
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/spreproc.cpp b/media/libstagefright/codecs/amrnb/enc/src/spreproc.cpp
new file mode 100644
index 0000000..71d645a
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/spreproc.cpp
@@ -0,0 +1,234 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/spreproc.c
+ Functions: subframePreProc
+
+ Date: 02/06/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+ Eliminated unnecessary use of the sub() function.
+
+ Description:
+ 1. Replaced copy() and for-loop with more efficient memcpy().
+ 2. Eliminated unused include file copy.h.
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <string.h>
+
+#include "spreproc.h"
+#include "typedef.h"
+#include "weight_a.h"
+#include "syn_filt.h"
+#include "residu.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: subframePreProc
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ mode -- enum Mode -- coder mode
+ gamma1 -- const Word16 array -- spectral exp. factor 1
+ gamma1_12k2 -- const Word16 array -- spectral exp. factor 1 for EFR
+ gamma2 -- const Word16 array -- spectral exp. factor 2
+ A -- Pointer to Word16 -- A(z) unquantized for the 4 subframes
+ Aq -- Pointer to Word16 -- A(z) quantized for the 4 subframes
+ speech -- Pointer to Word16 -- speech segment
+ mem_err -- Pointer to Word16 -- pointer to error signal
+ mem_w0 -- Pointer to Word16 -- memory of weighting filter
+ zero -- Pointer to Word16 -- pointer to zero vector
+
+ Outputs:
+ ai_zero -- Word16 array -- history of weighted synth. filter
+ exc -- Word16 array -- long term prediction residual
+ h1 -- Word16 array -- impulse response
+ xn -- Word16 array -- target vector for pitch search
+ res2 -- Word16 array -- long term prediction residual
+ error -- Word16 array -- error of LPC synthesis filter
+
+ Returns:
+ Zero
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ spreproc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void subframePreProc(
+ enum Mode mode, /* i : coder mode */
+ const Word16 gamma1[], /* i : spectral exp. factor 1 */
+ const Word16 gamma1_12k2[],/* i : spectral exp. factor 1 for EFR */
+ const Word16 gamma2[], /* i : spectral exp. factor 2 */
+ Word16 *A, /* i : A(z) unquantized for the 4 subframes */
+ Word16 *Aq, /* i : A(z) quantized for the 4 subframes */
+ Word16 *speech, /* i : speech segment */
+ Word16 *mem_err, /* i : pointer to error signal */
+ Word16 *mem_w0, /* i : memory of weighting filter */
+ Word16 *zero, /* i : pointer to zero vector */
+ Word16 ai_zero[], /* o : history of weighted synth. filter */
+ Word16 exc[], /* o : long term prediction residual */
+ Word16 h1[], /* o : impulse response */
+ Word16 xn[], /* o : target vector for pitch search */
+ Word16 res2[], /* o : long term prediction residual */
+ Word16 error[] /* o : error of LPC synthesis filter */
+)
+{
+ Word16 Ap1[MP1]; /* A(z) with spectral expansion */
+ Word16 Ap2[MP1]; /* A(z) with spectral expansion */
+ const Word16 *g1; /* Pointer to correct gammma1 vector */
+
+ /* mode specific pointer to gamma1 values */
+ if (mode == MR122 || mode == MR102)
+ {
+ g1 = gamma1_12k2;
+ }
+ else
+ {
+ g1 = gamma1;
+ }
+
+ /* Find the weighted LPC coefficients for the weighting filter. */
+ Weight_Ai(A, g1, Ap1);
+ Weight_Ai(A, gamma2, Ap2);
+
+ memcpy(ai_zero, Ap1, (M + 1)*sizeof(Word16));
+
+
+ Syn_filt(Aq, ai_zero, h1, L_SUBFR, zero, 0);
+ Syn_filt(Ap2, h1, h1, L_SUBFR, zero, 0);
+
+ /*
+ *
+ * Find the target vector for pitch search:
+ *
+ */
+
+ /* LPC residual */
+ Residu(Aq, speech, res2, L_SUBFR);
+
+ memcpy(exc, res2, L_SUBFR*sizeof(Word16));
+
+ Syn_filt(Aq, exc, error, L_SUBFR, mem_err, 0);
+
+ Residu(Ap1, error, xn, L_SUBFR);
+
+ /* target signal xn[]*/
+ Syn_filt(Ap2, xn, xn, L_SUBFR, mem_w0, 0);
+
+ return;
+
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/spreproc.h b/media/libstagefright/codecs/amrnb/enc/src/spreproc.h
new file mode 100644
index 0000000..77d35fc
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/spreproc.h
@@ -0,0 +1,135 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/spreproc.h
+
+ Date: 02/06/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the file, spreproc.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef spreproc_h
+#define spreproc_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "cnst.h"
+#include "mode.h"
+#include "typedef.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ void subframePreProc(
+ enum Mode mode, /* i : coder mode */
+ const Word16 gamma1[], /* i : spectral exp. factor 1 */
+ const Word16 gamma1_12k2[],/* i : spectral exp. factor 1 for EFR */
+ const Word16 gamma2[], /* i : spectral exp. factor 2 */
+ Word16 *A, /* i : A(z) unquantized for the 4 subframes */
+ Word16 *Aq, /* i : A(z) quantized for the 4 subframes */
+ Word16 *speech, /* i : speech segment */
+ Word16 *mem_err, /* i : pointer to error signal */
+ Word16 *mem_w0, /* i : memory of weighting filter */
+ Word16 *zero, /* i : pointer to zero vector */
+ Word16 ai_zero[], /* o : history of weighted synth. filter */
+ Word16 exc[], /* o : long term prediction residual */
+ Word16 h1[], /* o : impulse response */
+ Word16 xn[], /* o : target vector for pitch search */
+ Word16 res2[], /* o : long term prediction residual */
+ Word16 error[] /* o : error of LPC synthesis filter */
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* spreproc_h */
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/spstproc.cpp b/media/libstagefright/codecs/amrnb/enc/src/spstproc.cpp
new file mode 100644
index 0000000..b9574aa
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/spstproc.cpp
@@ -0,0 +1,314 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/spstproc.c
+ Functions: subframePostProc
+
+ Date: 02/06/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Updated template used to PV coding template.
+ Changed to accept the pOverflow flag for EPOC compatibility.
+
+ Description:
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated math operations that unnecessary checked for
+ saturation
+ 4. Replaced loop counter with decrement loops
+
+ Description: Added casting to eliminate warnings
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ Subframe post processing
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "spstproc.h"
+#include "syn_filt.h"
+#include "cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: subframePostProc
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+ Inputs:
+ speech -- Pointer to Word16 -- speech segment
+ mode -- enum Mode -- coder mode
+ i_subfr -- Word16 -- Subframe nr
+ gain_pit -- Word16 -- Pitch gain Q14
+ gain_code -- Word16 -- Decoded innovation gain
+ Aq -- Pointer to Word16 -- A(z) quantized for the 4 subframes
+ synth -- Word16 Array -- Local synthesis
+ xn -- Word16 Array -- Target vector for pitch search
+ code -- Word16 Array -- Fixed codebook exitation
+ y1 -- Word16 Array -- Filtered adaptive exitation
+ y2 -- Word16 Array -- Filtered fixed codebook excitation
+ mem_syn -- Pointer to Word16 -- memory of synthesis filter
+
+ Outputs:
+ mem_syn -- Pointer to Word16 -- memory of synthesis filter
+ mem_err -- Pointer to Word16 -- pointer to error signal
+ mem_w0 -- Pointer to Word16 -- memory of weighting filter
+ exc -- Pointer to Word16 -- long term prediction residual
+ sharp -- Pointer to Word16 -- pitch sharpening value
+ pOverflow -- Pointer to Flag -- overflow indicator
+
+ Returns:
+ None
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ spstproc.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void subframePostProc(
+ Word16 *speech, /* i : speech segment */
+ enum Mode mode, /* i : coder mode */
+ Word16 i_subfr, /* i : Subframe nr */
+ Word16 gain_pit, /* i : Pitch gain Q14 */
+ Word16 gain_code, /* i : Decoded innovation gain */
+ Word16 *Aq, /* i : A(z) quantized for the 4 subframes */
+ Word16 synth[], /* i : Local snthesis */
+ Word16 xn[], /* i : Target vector for pitch search */
+ Word16 code[], /* i : Fixed codebook exitation */
+ Word16 y1[], /* i : Filtered adaptive exitation */
+ Word16 y2[], /* i : Filtered fixed codebook excitation */
+ Word16 *mem_syn, /* i/o : memory of synthesis filter */
+ Word16 *mem_err, /* o : pointer to error signal */
+ Word16 *mem_w0, /* o : memory of weighting filter */
+ Word16 *exc, /* o : long term prediction residual */
+ Word16 *sharp, /* o : pitch sharpening value */
+ Flag *pOverflow /* o : overflow indicator */
+)
+{
+ Word16 i;
+ Word16 j;
+ Word16 temp;
+ Word32 L_temp;
+ Word32 L_temp2;
+ Word16 tempShift;
+ Word16 kShift;
+ Word16 pitch_fac;
+ Word16 *p_exc;
+ Word16 *p_code;
+
+ OSCL_UNUSED_ARG(pOverflow);
+
+ if (mode != MR122)
+ {
+ tempShift = 1;
+ kShift = 16 - 2 - 1;
+ pitch_fac = gain_pit;
+ }
+ else
+ {
+ tempShift = 2;
+ kShift = 16 - 4 - 1;
+ pitch_fac = gain_pit >> 1;
+ }
+
+ /*------------------------------------------------------------*
+ * - Update pitch sharpening "sharp" with quantized gain_pit *
+ *------------------------------------------------------------*/
+
+ if (gain_pit < SHARPMAX)
+ {
+ *sharp = gain_pit;
+ }
+ else
+ {
+ *sharp = SHARPMAX;
+ }
+
+ /*------------------------------------------------------*
+ * - Find the total excitation *
+ * - find synthesis speech corresponding to exc[] *
+ * - update filters memories for finding the target *
+ * vector in the next subframe *
+ * (update error[-m..-1] and mem_w_err[]) *
+ *------------------------------------------------------*/
+
+ p_exc = &exc[ i_subfr];
+ p_code = &code[0];
+
+ for (i = L_SUBFR >> 1; i != 0 ; i--)
+ {
+ /* exc[i] = gain_pit*exc[i] + gain_code*code[i]; */
+
+ /*
+ * 12k2 others
+ * ---------------------------------
+ * exc Q0 Q0
+ * gain_pit Q14 Q14
+ * pitch_fac Q13 Q14
+ * product: Q14 Q15
+ *
+ * code Q12 Q13
+ * gain_code Q1 Q1
+ * product Q14 Q15
+ * sum Q14 Q15
+ *
+ * tempShift 2 1
+ * sum<<tempShift Q16 Q16
+ * result -> exc Q0 Q0
+ */
+ L_temp = ((Word32) * (p_exc++) * pitch_fac) << 1;
+ L_temp2 = ((Word32) * (p_exc--) * pitch_fac) << 1;
+ L_temp += ((Word32) * (p_code++) * gain_code) << 1;
+ L_temp2 += ((Word32) * (p_code++) * gain_code) << 1;
+ L_temp <<= tempShift;
+ L_temp2 <<= tempShift;
+ *(p_exc++) = (Word16)((L_temp + 0x08000L) >> 16);
+ *(p_exc++) = (Word16)((L_temp2 + 0x08000L) >> 16);
+
+ }
+
+ Syn_filt(
+ Aq,
+ &exc[i_subfr],
+ &synth[i_subfr],
+ L_SUBFR,
+ mem_syn,
+ 1);
+
+ for (i = L_SUBFR - M, j = 0; i < L_SUBFR; i++, j++)
+ {
+ mem_err[j] = speech[i_subfr + i] - synth[i_subfr + i];
+
+ /*
+ * 12k2 others
+ * ---------------------------------
+ * y1 Q0 Q0
+ * gain_pit Q14 Q14
+ * product Q15 Q15
+ * shifted prod. Q16 Q16
+ * temp Q0 Q0
+ *
+ * y2 Q10 Q12
+ * gain_code Q1 Q1
+ * product Q12 Q14
+ * kshift 4 2
+ * shifted prod. Q16 Q16
+ * k Q0 Q0
+ * mem_w0,xn,sum Q0 Q0
+ */
+
+ L_temp = ((Word32)y1[i] * gain_pit);
+ temp = (Word16)(L_temp >> 14);
+
+ L_temp = ((Word32)y2[i] * gain_code);
+ temp += (Word16)(L_temp >> kShift);
+
+ mem_w0[j] = xn[i] - temp;
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrnb/enc/src/spstproc.h b/media/libstagefright/codecs/amrnb/enc/src/spstproc.h
new file mode 100644
index 0000000..edc43e4
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/spstproc.h
@@ -0,0 +1,136 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/spstproc.h
+
+ Date: 02/06/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Placed header file in the proper template format. Added
+ parameter pOverflow for the basic math ops.
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file contains all the constant definitions and prototype definitions
+ needed by the file, spstproc.c
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef spstproc_h
+#define spstproc_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void subframePostProc(
+ Word16 *speech, /* i : speech segment */
+ enum Mode mode, /* i : coder mode */
+ Word16 i_subfr, /* i : Subframe nr */
+ Word16 gain_pit, /* i : Pitch gain Q14 */
+ Word16 gain_code, /* i : Decoded innovation gain */
+ Word16 *Aq, /* i : A(z) quantized for the 4 subframes */
+ Word16 synth[], /* i : Local snthesis */
+ Word16 xn[], /* i : Target vector for pitch search */
+ Word16 code[], /* i : Fixed codebook exitation */
+ Word16 y1[], /* i : Filtered adaptive exitation */
+ Word16 y2[], /* i : Filtered fixed codebook excitation */
+ Word16 *mem_syn, /* i/o : memory of synthesis filter */
+ Word16 *mem_err, /* o : pointer to error signal */
+ Word16 *mem_w0, /* o : memory of weighting filter */
+ Word16 *exc, /* o : long term prediction residual */
+ Word16 *sharp, /* o : pitch sharpening value */
+ Flag *pOverflow
+ );
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* spstproc_h */
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ton_stab.cpp b/media/libstagefright/codecs/amrnb/enc/src/ton_stab.cpp
new file mode 100644
index 0000000..455a510
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/ton_stab.cpp
@@ -0,0 +1,801 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./audio/gsm-amr/c/src/ton_stab.c
+ Funtions:
+
+ Date: 02/06/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: For check_lsp()
+ 1. Eliminated unused include files.
+ 2. Replaced array addressing by pointers
+ 3. Eliminated math operations that unnecessary checked for
+ saturation this by evaluating the operands
+ For update_gp_clipping()
+ 1. Replaced copy() with more efficient memcpy()
+ 2. Replaced right shift function with right shift
+
+ Description: Replaced OSCL mem type functions and eliminated include
+ files that now are chosen by OSCL definitions
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description:
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include <stdlib.h>
+
+#include "ton_stab.h"
+#include "oper_32b.h"
+#include "cnst.h"
+#include "set_zero.h"
+#include "basic_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL VARIABLE DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ton_stab_init
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to pointer to structure type tonStabState.
+
+ Outputs:
+ None
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function: ton_stab_init
+ Purpose: Allocates state memory and initializes state memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ton_stab.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int ton_stab_init (tonStabState **state)
+{
+ tonStabState* s;
+
+ if (state == (tonStabState **) NULL){
+ // fprintf(stderr, "ton_stab_init: invalid parameter\n");
+ return -1;
+ }
+ *state = NULL;
+
+ // allocate memory
+ if ((s= (tonStabState *) malloc(sizeof(tonStabState))) == NULL){
+ // fprintf(stderr, "ton_stab_init: can not malloc state structure\n");
+ return -1;
+ }
+
+ ton_stab_reset(s);
+
+ *state = s;
+
+ return 0;
+}
+
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 ton_stab_init(tonStabState **state)
+{
+ tonStabState* s;
+
+ if (state == (tonStabState **) NULL)
+ {
+ /* fprintf(stderr, "ton_stab_init: invalid parameter\n"); */
+ return -1;
+ }
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (tonStabState *) malloc(sizeof(tonStabState))) == NULL)
+ {
+ /* fprintf(stderr, "ton_stab_init: can not malloc state structure\n"); */
+ return -1;
+ }
+
+ ton_stab_reset(s);
+
+ *state = s;
+
+ return 0;
+}
+
+/****************************************************************************/
+
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ton_stab_reset
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ st = pointer to pointer to structure type tonStabState.
+
+ Outputs:
+ None
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function: ton_stab_reset
+ Purpose: Initializes state memory to zero
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ton_stab.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+int ton_stab_reset (tonStabState *st)
+{
+ if (st == (tonStabState *) NULL){
+ // fprintf(stderr, "ton_stab_init: invalid parameter\n");
+ return -1;
+ }
+
+ // initialize tone stabilizer state
+ st->count = 0;
+ Set_zero(st->gp, N_FRAME); // Init Gp_Clipping
+
+ return 0;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 ton_stab_reset(tonStabState *st)
+{
+ if (st == (tonStabState *) NULL)
+ {
+ /* fprintf(stderr, "ton_stab_init: invalid parameter\n"); */
+ return -1;
+ }
+
+ /* initialize tone stabilizer state */
+ st->count = 0;
+ Set_zero(st->gp, N_FRAME); /* Init Gp_Clipping */
+
+ return 0;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: ton_stab_exit
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to pointer to structure type tonStabState.
+
+ Outputs:
+ None
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function: ton_stab_exit
+ Purpose: The memory used for state memory is freed
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ton_stab.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void ton_stab_exit (tonStabState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ // deallocate memory
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void ton_stab_exit(tonStabState **state)
+{
+ if (state == NULL || *state == NULL)
+ return;
+
+ /* deallocate memory */
+ free(*state);
+ *state = NULL;
+
+ return;
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: check_lsp
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to pointer to structure type tonStabState.
+ lsp = pointer to unquantized LSPs of type Word16
+
+ Outputs:
+ pOverflow = 1 if there is an overflow else it is zero.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function: check_lsp()
+ Purpose: Check the LSP's to detect resonances
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ton_stab.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 check_lsp(tonStabState *st, // i/o : State struct
+ Word16 *lsp // i : unquantized LSP's
+)
+{
+ Word16 i, dist, dist_min1, dist_min2, dist_th;
+
+ // Check for a resonance:
+ // Find minimum distance between lsp[i] and lsp[i+1]
+
+ dist_min1 = MAX_16;
+ for (i = 3; i < M-2; i++)
+ {
+ dist = sub(lsp[i], lsp[i+1]);
+
+ if (sub(dist, dist_min1) < 0)
+ {
+ dist_min1 = dist;
+ }
+ }
+
+ dist_min2 = MAX_16;
+ for (i = 1; i < 3; i++)
+ {
+ dist = sub(lsp[i], lsp[i+1]);
+
+ if (sub(dist, dist_min2) < 0)
+ {
+ dist_min2 = dist;
+ }
+ }
+
+ if (sub(lsp[1], 32000) > 0)
+ {
+ dist_th = 600;
+ }
+ else if (sub(lsp[1], 30500) > 0)
+ {
+ dist_th = 800;
+ }
+ else
+ {
+ dist_th = 1100;
+ }
+
+ if (sub(dist_min1, 1500) < 0 ||
+ sub(dist_min2, dist_th) < 0)
+ {
+ st->count = add(st->count, 1);
+ }
+ else
+ {
+ st->count = 0;
+ }
+
+ // Need 12 consecutive frames to set the flag
+ if (sub(st->count, 12) >= 0)
+ {
+ st->count = 12;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 check_lsp(tonStabState *st, /* i/o : State struct */
+ Word16 *lsp, /* i : unquantized LSP's */
+ Flag *pOverflow
+ )
+{
+ Word16 i;
+ Word16 dist;
+ Word16 dist_min1;
+ Word16 dist_min2;
+ Word16 dist_th;
+ Word16 *p_lsp = &lsp[3];
+ Word16 *p_lsp_1 = &lsp[4];
+
+ OSCL_UNUSED_ARG(pOverflow);
+ /* Check for a resonance: */
+ /* Find minimum distance between lsp[i] and lsp[i+1] */
+
+ dist_min1 = MAX_16;
+ for (i = 3; i < M - 2; i++)
+ {
+ dist = *(p_lsp++) - *(p_lsp_1++);
+
+ if (dist < dist_min1)
+ {
+ dist_min1 = dist;
+ }
+ }
+
+ dist_min2 = MAX_16;
+ p_lsp = &lsp[1];
+ p_lsp_1 = &lsp[2];
+
+ for (i = 1; i < 3; i++)
+ {
+ dist = *(p_lsp++) - *(p_lsp_1++);
+
+ if (dist < dist_min2)
+ {
+ dist_min2 = dist;
+ }
+ }
+
+ if (lsp[1] > 32000)
+ {
+ dist_th = 600;
+ }
+ else if (lsp[1] > 30500)
+ {
+ dist_th = 800;
+ }
+ else
+ {
+ dist_th = 1100;
+ }
+
+ if ((dist_min1 < 1500) || (dist_min2 < dist_th))
+ {
+ st->count++;
+ }
+ else
+ {
+ st->count = 0;
+ }
+
+ /* Need 12 consecutive frames to set the flag */
+ if (st->count >= 12)
+ {
+ st->count = 12;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: check_gp_clipping
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to pointer to structure type tonStabState.
+ g_pitch = pitch gain of type Word16
+
+ Outputs:
+ pOverflow = 1 if there is an overflow else it is zero.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function: Check_Gp_Clipping()
+ Purpose: Verify that the sum of the last (N_FRAME+1) pitch
+ gains is under a certain threshold.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ton_stab.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+Word16 check_gp_clipping(tonStabState *st, // i/o : State struct
+ Word16 g_pitch // i : pitch gain
+)
+{
+ Word16 i, sum;
+
+ sum = shr(g_pitch, 3); // Division by 8
+ for (i = 0; i < N_FRAME; i++)
+ {
+ sum = add(sum, st->gp[i]);
+ }
+
+ if (sub(sum, GP_CLIP) > 0)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+Word16 check_gp_clipping(tonStabState *st, /* i/o : State struct */
+ Word16 g_pitch, /* i : pitch gain */
+ Flag *pOverflow
+ )
+{
+ Word16 i;
+ Word16 sum;
+
+ sum = shr(g_pitch, 3, pOverflow); /* Division by 8 */
+ for (i = 0; i < N_FRAME; i++)
+ {
+ sum = add(sum, st->gp[i], pOverflow);
+ }
+
+ if (sum > GP_CLIP)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: update_gp_clipping
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ state = pointer to pointer to structure type tonStabState.
+ g_pitch = pitch gain of type Word16
+
+ Outputs:
+ pOverflow = 1 if there is an overflow else it is zero.
+
+ Returns:
+ None.
+
+ Global Variables Used:
+ None
+
+ Local Variables Needed:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Function: Update_Gp_Clipping()
+ Purpose: Update past pitch gain memory
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ton_stab.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+void update_gp_clipping(tonStabState *st, // i/o : State struct
+ Word16 g_pitch // i : pitch gain
+)
+{
+ Copy(&st->gp[1], &st->gp[0], N_FRAME-1);
+ st->gp[N_FRAME-1] = shr(g_pitch, 3);
+}
+
+------------------------------------------------------------------------------
+ RESOURCES USED [optional]
+
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ HEAP MEMORY USED: x bytes
+
+ STACK MEMORY USED: x bytes
+
+ CLOCK CYCLES: (cycle count equation for this function) + (variable
+ used to represent cycle count for each subroutine
+ called)
+ where: (cycle count variable) = cycle count for [subroutine
+ name]
+
+------------------------------------------------------------------------------
+ CAUTION [optional]
+ [State any special notes, constraints or cautions for users of this function]
+
+------------------------------------------------------------------------------
+*/
+
+void update_gp_clipping(tonStabState *st, /* i/o : State struct */
+ Word16 g_pitch, /* i : pitch gain */
+ Flag *pOverflow
+ )
+{
+ OSCL_UNUSED_ARG(pOverflow);
+ int i;
+ for (i = 0; i < N_FRAME - 1; i++)
+ {
+ st->gp[i] = st->gp[i+1];
+ }
+ st->gp[N_FRAME-1] = g_pitch >> 3;
+}
+
diff --git a/media/libstagefright/codecs/amrnb/enc/src/ton_stab.h b/media/libstagefright/codecs/amrnb/enc/src/ton_stab.h
new file mode 100644
index 0000000..fb06e64
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/enc/src/ton_stab.h
@@ -0,0 +1,155 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.073
+ ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: /audio/gsm_amr/c/include/ton_stab.h
+
+ Date: 02/05/2002
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description: Replaced "int" and/or "char" with OSCL defined types.
+
+ Description: Moved _cplusplus #ifdef after Include section.
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ File : ton_stab.h
+ Purpose : Tone stabilization routines
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef TON_STAB_H
+#define TON_STAB_H
+#define ton_stab_h "$Id $"
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "typedef.h"
+#include "mode.h"
+#include "cnst.h"
+
+/*--------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ /* state variable */
+ typedef struct
+ {
+ /* counters */
+ Word16 count;
+ /* gain history Q11 */
+ Word16 gp[N_FRAME];
+ } tonStabState;
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+ Word16 ton_stab_init(tonStabState **st);
+ /* initialize one instance of the pre processing state.
+ Stores pointer to filter status struct in *st. This pointer has to
+ be passed to ton_stab in each call.
+ returns 0 on success
+ */
+
+ Word16 ton_stab_reset(tonStabState *st);
+ /* reset of pre processing state (i.e. set state memory to zero)
+ returns 0 on success
+ */
+
+ void ton_stab_exit(tonStabState **st);
+ /* de-initialize pre processing state (i.e. free status struct)
+ stores NULL in *st
+ */
+
+ Word16 check_lsp(tonStabState *st, /* i/o : State struct */
+ Word16 *lsp, /* i : unquantized LSP's */
+ Flag *pOverflow
+ );
+
+ Word16 check_gp_clipping(tonStabState *st, /* i/o : State struct */
+ Word16 g_pitch, /* i : pitch gain */
+ Flag *pOverflow
+ );
+
+ void update_gp_clipping(tonStabState *st, /* i/o : State struct */
+ Word16 g_pitch, /* i : pitch gain */
+ Flag *pOverflow
+ );
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TON_STAB_H_ */
+
+
+
+
diff --git a/media/libstagefright/codecs/amrnb/patent_disclaimer.txt b/media/libstagefright/codecs/amrnb/patent_disclaimer.txt
new file mode 100644
index 0000000..b4bf11d
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/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/amrwb/Android.mk b/media/libstagefright/codecs/amrwb/Android.mk
new file mode 100644
index 0000000..c9e1c25
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/Android.mk
@@ -0,0 +1,55 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ src/agc2_amr_wb.cpp \
+ src/band_pass_6k_7k.cpp \
+ src/dec_acelp_2p_in_64.cpp \
+ src/dec_acelp_4p_in_64.cpp \
+ src/dec_alg_codebook.cpp \
+ src/dec_gain2_amr_wb.cpp \
+ src/deemphasis_32.cpp \
+ src/dtx_decoder_amr_wb.cpp \
+ src/get_amr_wb_bits.cpp \
+ src/highpass_400hz_at_12k8.cpp \
+ src/highpass_50hz_at_12k8.cpp \
+ src/homing_amr_wb_dec.cpp \
+ src/interpolate_isp.cpp \
+ src/isf_extrapolation.cpp \
+ src/isp_az.cpp \
+ src/isp_isf.cpp \
+ src/lagconceal.cpp \
+ src/low_pass_filt_7k.cpp \
+ src/median5.cpp \
+ src/mime_io.cpp \
+ src/noise_gen_amrwb.cpp \
+ src/normalize_amr_wb.cpp \
+ src/oversamp_12k8_to_16k.cpp \
+ src/phase_dispersion.cpp \
+ src/pit_shrp.cpp \
+ src/pred_lt4.cpp \
+ src/preemph_amrwb_dec.cpp \
+ src/pvamrwb_math_op.cpp \
+ src/pvamrwbdecoder.cpp \
+ src/q_gain2_tab.cpp \
+ src/qisf_ns.cpp \
+ src/qisf_ns_tab.cpp \
+ src/qpisf_2s.cpp \
+ src/qpisf_2s_tab.cpp \
+ src/scale_signal.cpp \
+ src/synthesis_amr_wb.cpp \
+ src/voice_factor.cpp \
+ src/wb_syn_filt.cpp \
+ src/weight_amrwb_lpc.cpp
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/include
+
+LOCAL_CFLAGS := \
+ -DOSCL_UNUSED_ARG= -DOSCL_IMPORT_REF=
+
+LOCAL_MODULE := libstagefright_amrwbdec
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/amrwb/include/pvamrwbdecoder_api.h b/media/libstagefright/codecs/amrwb/include/pvamrwbdecoder_api.h
new file mode 100644
index 0000000..eca5ae0
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/include/pvamrwbdecoder_api.h
@@ -0,0 +1,154 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+ Name: pvamrwbdecoder_api.h
+
+ Date: 05/02/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Main header file for the Packet Video AMR Wide Band decoder library. The
+ constants, structures, and functions defined within this file, along with
+ a basic data types header file, is all that is needed to use and communicate
+ with the library. The internal data structures within the library are
+ purposely hidden.
+
+ ---* Need description of the input buffering. *-------
+
+ ---* Need an example of calling the library here *----
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (Normally header files do not have a reference section)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef _PVAMRWBDECODER_API_H
+#define _PVAMRWBDECODER_API_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+#define AMR_WB_PCM_FRAME 320 /* Frame size at 16kHz */
+
+
+#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 KAMRWB_NB_BITS_MAX NBBITS_24k
+#define KAMRWB_NB_BYTES_MAX ((KAMRWB_NB_BITS_MAX>>3)+1)
+
+#define NUM_OF_MODES 10
+
+
+ static const int16 AMR_WB_COMPRESSED[NUM_OF_MODES] =
+ {
+ NBBITS_7k,
+ NBBITS_9k,
+ NBBITS_12k,
+ NBBITS_14k,
+ NBBITS_16k,
+ NBBITS_18k,
+ NBBITS_20k,
+ NBBITS_23k,
+ NBBITS_24k,
+ NBBITS_SID
+ };
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* PVMP4AUDIODECODER_API_H */
+
+
diff --git a/media/libstagefright/codecs/amrwb/patent_disclaimer.txt b/media/libstagefright/codecs/amrwb/patent_disclaimer.txt
new file mode 100644
index 0000000..b4bf11d
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/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/amrwb/src/agc2_amr_wb.cpp b/media/libstagefright/codecs/amrwb/src/agc2_amr_wb.cpp
new file mode 100644
index 0000000..2e53d13
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/agc2_amr_wb.cpp
@@ -0,0 +1,190 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: agc2_amr_wb.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 * sig_in, (i) : postfilter input signal
+ int16 * sig_out, (i/o) : postfilter output signal
+ int16 l_trm (i) : subframe size
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Performs adaptive gain control
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwb_math_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void agc2_amr_wb(
+ int16 * sig_in, /* (i) : postfilter input signal */
+ int16 * sig_out, /* (i/o) : postfilter output signal */
+ int16 l_trm /* (i) : subframe size */
+)
+{
+
+ int16 i, exp;
+ int16 gain_in, gain_out, g0;
+ int32 s;
+
+ int16 temp;
+
+ /* calculate gain_out with exponent */
+
+ temp = sig_out[0] >> 2;
+ s = fxp_mul_16by16(temp, temp) << 1;
+ for (i = 1; i < l_trm; i++)
+ {
+ temp = sig_out[i] >> 2;
+ s = mac_16by16_to_int32(s, temp, temp);
+ }
+
+
+ if (s == 0)
+ {
+ return;
+ }
+ exp = normalize_amr_wb(s) - 1;
+ gain_out = amr_wb_round(s << exp);
+
+ /* calculate gain_in with exponent */
+
+ temp = sig_in[0] >> 2;
+ s = mul_16by16_to_int32(temp, temp);
+ for (i = 1; i < l_trm; i++)
+ {
+ temp = sig_in[i] >> 2;
+ s = mac_16by16_to_int32(s, temp, temp);
+ }
+
+
+ if (s == 0)
+ {
+ g0 = 0;
+ }
+ else
+ {
+ i = normalize_amr_wb(s);
+ gain_in = amr_wb_round(s << i);
+ exp -= i;
+
+ /*
+ * g0 = sqrt(gain_in/gain_out)
+ */
+
+ s = div_16by16(gain_out, gain_in);
+ s = shl_int32(s, 7); /* s = gain_out / gain_in */
+ s = shr_int32(s, exp); /* add exponent */
+
+ s = one_ov_sqrt(s);
+ g0 = amr_wb_round(shl_int32(s, 9));
+ }
+ /* sig_out(n) = gain(n) sig_out(n) */
+
+ for (i = 0; i < l_trm; i++)
+ {
+ sig_out[i] = extract_h(shl_int32(fxp_mul_16by16(sig_out[i], g0), 3));
+
+ }
+
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrwb/src/band_pass_6k_7k.cpp b/media/libstagefright/codecs/amrwb/src/band_pass_6k_7k.cpp
new file mode 100644
index 0000000..97c7402
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/band_pass_6k_7k.cpp
@@ -0,0 +1,240 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: band_pass_6k_7k.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 signal[], input signal / output is divided by 16
+ int16 lg, lenght of signal
+ int16 mem[] in/out: memory (size=30)
+ int16 x[] scratch mem ( size= 60)
+
+------------------------------------------------------------------------------
+ FUNCTION 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
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_acelp.h"
+#include "pvamrwbdecoder_cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define L_FIR 30
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/* filter coefficients (gain=4.0) */
+
+const int16 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
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void band_pass_6k_7k_init(int16 mem[]) /* mem[30] */
+{
+ pv_memset((void *)mem, 0, L_FIR*sizeof(*mem));
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void band_pass_6k_7k(
+ int16 signal[], /* input: signal */
+ int16 lg, /* input: length of input */
+ int16 mem[], /* in/out: memory (size=30) */
+ int16 x[]
+)
+{
+ int16 i, j;
+ int32 L_tmp1;
+ int32 L_tmp2;
+ int32 L_tmp3;
+ int32 L_tmp4;
+
+ int16 *pt_sign = signal;
+
+ pv_memcpy((void *)x, (void *)mem, L_FIR*sizeof(*x));
+
+
+ for (i = 0; i < lg >> 2; i++)
+ {
+
+ x[(i<<2) + L_FIR ] = *(pt_sign) >> 2; /* gain of filter = 4 */
+ x[(i<<2) + L_FIR + 1] = *(pt_sign + 1) >> 2; /* gain of filter = 4 */
+ x[(i<<2) + L_FIR + 2] = *(pt_sign + 2) >> 2; /* gain of filter = 4 */
+ x[(i<<2) + L_FIR + 3] = *(pt_sign + 3) >> 2; /* gain of filter = 4 */
+
+ L_tmp1 = 0x00004000;
+ L_tmp2 = 0x00004000;
+ L_tmp3 = 0x00004000;
+ L_tmp4 = 0x00004000;
+
+ L_tmp1 -= ((int32)x[(i<<2)+L_FIR ] << 5);
+ L_tmp2 -= ((int32)x[(i<<2)+L_FIR+1] << 5);
+ L_tmp3 -= ((int32)x[(i<<2)+L_FIR+2] << 5);
+ L_tmp4 -= ((int32)x[(i<<2)+L_FIR+3] << 5);
+
+ L_tmp1 -= ((int32)x[(i<<2)] << 5);
+ L_tmp2 -= ((int32)x[(i<<2)+1] << 5);
+ L_tmp3 -= ((int32)x[(i<<2)+2] << 5);
+ L_tmp4 -= ((int32)x[(i<<2)+3] << 5);
+
+
+ for (j = 1; j < L_FIR - 1; j += 4)
+ {
+ int16 tmp1 = x[(i<<2)+j ];
+ int16 tmp2 = x[(i<<2)+j+1];
+ int16 tmp3 = x[(i<<2)+j+2];
+
+ L_tmp1 = fxp_mac_16by16(tmp1, fir_6k_7k[j ], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(tmp2, fir_6k_7k[j ], L_tmp2);
+ L_tmp1 = fxp_mac_16by16(tmp2, fir_6k_7k[j+1], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(tmp3, fir_6k_7k[j+1], L_tmp2);
+ L_tmp3 = fxp_mac_16by16(tmp3, fir_6k_7k[j ], L_tmp3);
+ L_tmp1 = fxp_mac_16by16(tmp3, fir_6k_7k[j+2], L_tmp1);
+
+ tmp1 = x[(i<<2)+j+3];
+ tmp2 = x[(i<<2)+j+4];
+
+ L_tmp2 = fxp_mac_16by16(tmp1, fir_6k_7k[j+2], L_tmp2);
+ L_tmp4 = fxp_mac_16by16(tmp1, fir_6k_7k[j ], L_tmp4);
+ L_tmp3 = fxp_mac_16by16(tmp1, fir_6k_7k[j+1], L_tmp3);
+ L_tmp1 = fxp_mac_16by16(tmp1, fir_6k_7k[j+3], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(tmp2, fir_6k_7k[j+3], L_tmp2);
+ L_tmp4 = fxp_mac_16by16(tmp2, fir_6k_7k[j+1], L_tmp4);
+ L_tmp3 = fxp_mac_16by16(tmp2, fir_6k_7k[j+2], L_tmp3);
+
+ tmp1 = x[(i<<2)+j+5];
+ tmp2 = x[(i<<2)+j+6];
+
+ L_tmp4 = fxp_mac_16by16(tmp1, fir_6k_7k[j+2], L_tmp4);
+ L_tmp3 = fxp_mac_16by16(tmp1, fir_6k_7k[j+3], L_tmp3);
+ L_tmp4 = fxp_mac_16by16(tmp2, fir_6k_7k[j+3], L_tmp4);
+
+ }
+
+ L_tmp1 = fxp_mac_16by16(x[(i<<2)+j ], fir_6k_7k[L_FIR-1 ], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(x[(i<<2)+j+1], fir_6k_7k[L_FIR-1 ], L_tmp2);
+ L_tmp3 = fxp_mac_16by16(x[(i<<2)+j+2], fir_6k_7k[L_FIR-1 ], L_tmp3);
+ L_tmp4 = fxp_mac_16by16(x[(i<<2)+j+3], fir_6k_7k[L_FIR-1 ], L_tmp4);
+
+
+ *(pt_sign++) = (int16)(L_tmp1 >> 15);
+ *(pt_sign++) = (int16)(L_tmp2 >> 15);
+ *(pt_sign++) = (int16)(L_tmp3 >> 15);
+ *(pt_sign++) = (int16)(L_tmp4 >> 15);
+
+ }
+
+ pv_memcpy((void *)mem, (void *)(x + lg), L_FIR*sizeof(*mem));
+
+}
+
diff --git a/media/libstagefright/codecs/amrwb/src/dec_acelp_2p_in_64.cpp b/media/libstagefright/codecs/amrwb/src/dec_acelp_2p_in_64.cpp
new file mode 100644
index 0000000..740bc16
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/dec_acelp_2p_in_64.cpp
@@ -0,0 +1,157 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: dec_acelp_2p_in_64.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 index, (i): 12 bits index
+ int16 code[] (o): Q9 algebraic (fixed) codebook excitation
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ 12 bits algebraic codebook decoder.
+ 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.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define L_CODE 64 /* codevector length */
+#define NB_TRACK 2 /* number of track */
+#define NB_POS 32 /* number of position */
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void dec_acelp_2p_in_64(
+ int16 index, /* (i): 12 bits index */
+ int16 code[] /* (o): Q9 algebraic (fixed) codebook excitation */
+)
+{
+ int16 i;
+
+ pv_memset(code, 0, L_CODE*sizeof(*code));
+
+ /* decode the positions and signs of pulses and build the codeword */
+
+ i = (index >> 5) & 0x003E;
+
+ if (((index >> 6) & NB_POS) == 0)
+ {
+ code[i] = 512;
+ }
+ else
+ {
+ code[i] = -512;
+ }
+
+ i = ((index & 0x001F) << 1) + 1;
+
+ if ((index & NB_POS) == 0)
+ {
+ code[i] = 512;
+ }
+ else
+ {
+ code[i] = -512;
+ }
+
+}
diff --git a/media/libstagefright/codecs/amrwb/src/dec_acelp_4p_in_64.cpp b/media/libstagefright/codecs/amrwb/src/dec_acelp_4p_in_64.cpp
new file mode 100644
index 0000000..4868822
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/dec_acelp_4p_in_64.cpp
@@ -0,0 +1,265 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: dec_acelp_4p_in_64.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 index[], (i) : index (20): 5+5+5+5 = 20 bits.
+ (i) : index (36): 9+9+9+9 = 36 bits.
+ (i) : index (44): 13+9+13+9 = 44 bits.
+ (i) : index (52): 13+13+13+13 = 52 bits.
+ (i) : index (64): 2+2+2+2+14+14+14+14 = 64 bits.
+ (i) : index (72): 10+2+10+2+10+14+10+14 = 72 bits.
+ (i) : index (88): 11+11+11+11+11+11+11+11 = 88 bits.
+ int16 nbbits, (i) : 20, 36, 44, 52, 64, 72 or 88 bits
+ int16 code[] (o) Q9: algebraic (fixed) codebook excitation
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ 20, 36, 44, 52, 64, 72, 88 bits algebraic codebook decoder.
+ 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.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+
+#include "q_pulse.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define L_CODE 64 /* codevector length */
+#define NB_TRACK 4 /* number of track */
+#define NB_POS 16 /* number of position */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void add_pulses(int16 pos[], int16 nb_pulse, int16 track, int16 code[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void dec_acelp_4p_in_64(
+ int16 index[], /* (i) : index (20): 5+5+5+5 = 20 bits. */
+ /* (i) : index (36): 9+9+9+9 = 36 bits. */
+ /* (i) : index (44): 13+9+13+9 = 44 bits. */
+ /* (i) : index (52): 13+13+13+13 = 52 bits. */
+ /* (i) : index (64): 2+2+2+2+14+14+14+14 = 64 bits. */
+ /* (i) : index (72): 10+2+10+2+10+14+10+14 = 72 bits. */
+ /* (i) : index (88): 11+11+11+11+11+11+11+11 = 88 bits. */
+ int16 nbbits, /* (i) : 20, 36, 44, 52, 64, 72 or 88 bits */
+ int16 code[] /* (o) Q9: algebraic (fixed) codebook excitation */
+)
+{
+ int16 k, pos[6];
+ int32 L_index;
+ pv_memset(code, 0, L_CODE*sizeof(*code));
+
+ /* decode the positions and signs of pulses and build the codeword */
+
+
+ switch (nbbits)
+ {
+ case 20:
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ L_index = index[k];
+ dec_1p_N1(L_index, 4, 0, pos);
+ add_pulses(pos, 1, k, code);
+ }
+ break;
+
+ case 36:
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ L_index = index[k];
+ dec_2p_2N1(L_index, 4, 0, pos);
+ add_pulses(pos, 2, k, code);
+ }
+ break;
+ case 44:
+ for (k = 0; k < NB_TRACK - 2; k++)
+ {
+ L_index = index[k];
+ dec_3p_3N1(L_index, 4, 0, pos);
+ add_pulses(pos, 3, k, code);
+ }
+ for (k = 2; k < NB_TRACK; k++)
+ {
+ L_index = index[k];
+ dec_2p_2N1(L_index, 4, 0, pos);
+ add_pulses(pos, 2, k, code);
+ }
+ break;
+ case 52:
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ L_index = index[k];
+ dec_3p_3N1(L_index, 4, 0, pos);
+ add_pulses(pos, 3, k, code);
+ }
+ break;
+ case 64:
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ L_index = ((int32)index[k] << 14) + index[k + NB_TRACK];
+ dec_4p_4N(L_index, 4, 0, pos);
+ add_pulses(pos, 4, k, code);
+ }
+ break;
+ case 72:
+ for (k = 0; k < NB_TRACK - 2; k++)
+ {
+ L_index = ((int32)index[k] << 10) + index[k + NB_TRACK];
+ dec_5p_5N(L_index, 4, 0, pos);
+ add_pulses(pos, 5, k, code);
+ }
+ for (k = 2; k < NB_TRACK; k++)
+ {
+ L_index = ((int32)index[k] << 14) + index[k + NB_TRACK];
+ dec_4p_4N(L_index, 4, 0, pos);
+ add_pulses(pos, 4, k, code);
+ }
+ break;
+ case 88:
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ L_index = ((int32)index[k] << 11) + index[k + NB_TRACK];
+ dec_6p_6N_2(L_index, 4, 0, pos);
+ add_pulses(pos, 6, k, code);
+ }
+ default:
+ break;
+ }
+
+
+}
+
+
+
+void add_pulses(int16 pos[], int16 nb_pulse, int16 track, int16 code[])
+{
+ int16 i, k;
+
+ for (k = 0; k < nb_pulse; k++)
+ {
+ /* i = ((pos[k] & (NB_POS-1))*NB_TRACK) + track; */
+ i = ((pos[k] & (NB_POS - 1)) << 2) + track;
+
+ if ((pos[k] & NB_POS) == 0)
+ {
+ code[i] += 512;
+ }
+ else
+ {
+ code[i] -= 512;
+ }
+ }
+
+}
diff --git a/media/libstagefright/codecs/amrwb/src/dec_alg_codebook.cpp b/media/libstagefright/codecs/amrwb/src/dec_alg_codebook.cpp
new file mode 100644
index 0000000..44fdc09
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/dec_alg_codebook.cpp
@@ -0,0 +1,392 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: dec_alg_codebook.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ decoding of algebraic codebook
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "q_pulse.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define NB_POS 16 /* pos in track, mask for sign bit */
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void dec_1p_N1(int32 index, int16 N, int16 offset, int16 pos[])
+{
+ int16 pos1;
+ int32 mask, i;
+
+ mask = ((1 << N) - 1);
+ /*-------------------------------------------------------*
+ * Decode 1 pulse with N+1 bits: *
+ *-------------------------------------------------------*/
+ pos1 = ((index & mask) + offset);
+
+ i = ((index >> N) & 1L); /* i = ((index >> N) & 1); */
+
+ if (i == 1)
+ {
+ pos1 += NB_POS;
+ }
+ pos[0] = pos1;
+
+}
+
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void dec_2p_2N1(int32 index, int16 N, int16 offset, int16 pos[])
+{
+ int16 pos1, pos2, tmp;
+ int32 mask, i;
+
+ mask = (int32)(sub_int16(shl_int16(1, N), 1)); /* mask = ((1<<N)-1); */
+ /*-------------------------------------------------------*
+ * Decode 2 pulses with 2*N+1 bits: *
+ *-------------------------------------------------------*/
+ /* pos1 = (((index >> N) & mask) + offset); */
+ pos1 = (int16)(add_int32((shr_int32(index, N) & mask), (int32)(offset)));
+ tmp = shl_int16(N, 1);
+ i = (index >> tmp) & 1L; /* i = (index >> (2*N)) & 1; */
+ pos2 = add_int16((int16)(index & mask), offset); /* pos2 = ((index & mask) + offset); */
+
+ if (pos2 < pos1) /* ((pos2 - pos1) < 0) */
+ {
+ if (i == 1)
+ { /* (i == 1) */
+ pos1 += NB_POS; /* pos1 += NB_POS; */
+ }
+ else
+ {
+ pos2 += NB_POS; /* pos2 += NB_POS; */
+ }
+ }
+ else
+ {
+ if (i == 1)
+ { /* (i == 1) */
+ pos1 += NB_POS; /* pos1 += NB_POS; */
+ pos2 += NB_POS; /* pos2 += NB_POS; */
+ }
+ }
+
+ pos[0] = pos1;
+ pos[1] = pos2;
+
+ return;
+}
+
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void dec_3p_3N1(int32 index, int16 N, int16 offset, int16 pos[])
+{
+ int16 j, tmp;
+ int32 mask, idx;
+
+ /*-------------------------------------------------------*
+ * Decode 3 pulses with 3*N+1 bits: *
+ *-------------------------------------------------------*/
+ tmp = sub_int16(shl_int16(N, 1), 1); /* mask = ((1<<((2*N)-1))-1); */
+
+ mask = ((1 << ((2 * N) - 1)) - 1);
+
+ idx = index & mask;
+ j = offset;
+ tmp = (N << 1) - 1;
+
+
+ if (((index >> tmp) & 1L) != 0L)
+ { /* if (((index >> ((2*N)-1)) & 1) == 1){ */
+ j += (1 << (N - 1)); /* j += (1<<(N-1)); */
+ }
+ dec_2p_2N1(idx, (int16)(N - 1), j, pos);
+
+ mask = ((1 << (N + 1)) - 1);
+ tmp = N << 1; /* idx = (index >> (2*N)) & mask; */
+ idx = (index >> tmp) & mask;
+
+ dec_1p_N1(idx, N, offset, pos + 2);
+
+ return;
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void dec_4p_4N1(int32 index, int16 N, int16 offset, int16 pos[])
+{
+ int16 j, tmp;
+ int32 mask, idx;
+
+ /*-------------------------------------------------------*
+ * Decode 4 pulses with 4*N+1 bits: *
+ *-------------------------------------------------------*/
+ tmp = (N << 1) - 1;
+ mask = (1L << tmp) - 1L;
+ idx = index & mask;
+ j = offset;
+ tmp = (N << 1) - 1;
+
+
+ if (((index >> tmp) & 1L) != 0L)
+ { /* (((index >> ((2*N)-1)) & 1) == 1) */
+ j += (1 << (N - 1)); /* j += (1<<(N-1)); */
+ }
+ dec_2p_2N1(idx, (int16)(N - 1), j, pos);
+
+
+ tmp = (N << 1) + 1; /* mask = ((1<<((2*N)+1))-1); */
+ mask = (1L << tmp) - 1L;
+ idx = (index >> (N << 1)) & mask; /* idx = (index >> (2*N)) & mask; */
+ dec_2p_2N1(idx, N, offset, pos + 2); /* dec_2p_2N1(idx, N, offset, pos+2); */
+
+ return;
+}
+
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void dec_4p_4N(int32 index, int16 N, int16 offset, int16 pos[])
+{
+ int16 j, n_1, tmp;
+
+ /*-------------------------------------------------------*
+ * Decode 4 pulses with 4*N bits: *
+ *-------------------------------------------------------*/
+
+ n_1 = N - 1;
+ j = offset + (1 << n_1); /* j = offset + (1 << n_1); */
+
+ tmp = (N << 2) - 2;
+
+ switch ((index >> tmp) & 3)
+ { /* ((index >> ((4*N)-2)) & 3) */
+ case 0:
+ tmp = (n_1 << 2) + 1;
+
+ if ((index >> tmp) & 1)
+ { /* (((index >> ((4*n_1)+1)) & 1) == 0) */
+ dec_4p_4N1(index, n_1, j, pos);
+ }
+ else
+ {
+ dec_4p_4N1(index, n_1, offset, pos);
+ }
+ break;
+ case 1:
+ tmp = (3 * n_1) + 1; /* dec_1p_N1((index>>((3*n_1)+1)), n_1, offset, pos) */
+ dec_1p_N1(index >> tmp, n_1, offset, pos);
+ dec_3p_3N1(index, n_1, j, pos + 1);
+ break;
+ case 2:
+ tmp = (n_1 << 1) + 1; /* dec_2p_2N1((index>>((2*n_1)+1)), n_1, offset, pos); */
+ dec_2p_2N1(index >> tmp, n_1, offset, pos);
+ dec_2p_2N1(index, n_1, j, pos + 2);
+ break;
+ case 3:
+ tmp = n_1 + 1; /* dec_3p_3N1((index>>(n_1+1)), n_1, offset, pos); */
+ dec_3p_3N1(index >> tmp, n_1, offset, pos);
+ dec_1p_N1(index, n_1, j, pos + 3);
+ break;
+ }
+ return;
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void dec_5p_5N(int32 index, int16 N, int16 offset, int16 pos[])
+{
+ int16 j, n_1, tmp;
+ int32 idx;
+
+ /*-------------------------------------------------------*
+ * Decode 5 pulses with 5*N bits: *
+ *-------------------------------------------------------*/
+
+ n_1 = (int16)(N - 1);
+ j = add_int16(offset, shl_int16(1, n_1)); /* j = offset + (1 << n_1); */
+ tmp = (N << 1) + 1; /* idx = (index >> ((2*N)+1)); */
+ idx = index >> tmp;
+ tmp = (5 * N) - 1; /* ((5*N)-1)) */
+
+
+ if ((index >> tmp) & 1) /* ((index >> ((5*N)-1)) & 1) */
+ {
+ dec_3p_3N1(idx, n_1, j, pos);
+ dec_2p_2N1(index, N, offset, pos + 3);
+ }
+ else
+ {
+ dec_3p_3N1(idx, n_1, offset, pos);
+ dec_2p_2N1(index, N, offset, pos + 3);
+ }
+ return;
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void dec_6p_6N_2(int32 index, int16 N, int16 offset, int16 pos[])
+{
+ int16 j, n_1, offsetA, offsetB;
+
+ n_1 = N - 1;
+ j = offset + (1 << n_1); /* j = offset + (1 << n_1); */
+
+
+ /* !! N and n_1 are constants -> it doesn't need to be operated by Basic Operators */
+
+ offsetA = offsetB = j;
+
+ if (((index >> (6*N - 5)) & 1L) == 0)
+ { /* if (((index >> ((6*N)-5)) & 1) == 0) */
+ offsetA = offset;
+ }
+ else
+ {
+ offsetB = offset;
+ }
+
+
+ switch ((index >> (6*N - 4)) & 3)
+ { /* (index >> ((6*N)-4)) & 3 */
+ case 0:
+ dec_5p_5N(index >> N, n_1, offsetA, pos); /* dec_5p_5N(index>>N, n_1, offsetA, pos); */
+ dec_1p_N1(index, n_1, offsetA, pos + 5);
+ break;
+ case 1:
+ dec_5p_5N(index >> N, n_1, offsetA, pos); /* dec_5p_5N(index>>N, n_1, offsetA, pos); */
+ dec_1p_N1(index, n_1, offsetB, pos + 5);
+ break;
+ case 2:
+ dec_4p_4N(index >> (2*n_1 + 1), n_1, offsetA, pos); /* dec_4p_4N(index>>((2*n_1)+1 ), n_1, offsetA, pos); */
+ dec_2p_2N1(index, n_1, offsetB, pos + 4);
+ break;
+ case 3:
+ dec_3p_3N1(index >> (3*n_1 + 1), n_1, offset, pos); /* dec_3p_3N1(index>>((3*n_1)+ 1), n_1, offset, pos); */
+ dec_3p_3N1(index, n_1, j, pos + 3);
+ break;
+ }
+ return;
+}
diff --git a/media/libstagefright/codecs/amrwb/src/dec_gain2_amr_wb.cpp b/media/libstagefright/codecs/amrwb/src/dec_gain2_amr_wb.cpp
new file mode 100644
index 0000000..8cae559
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/dec_gain2_amr_wb.cpp
@@ -0,0 +1,404 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: dec_gain2_amr_wb.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 index, (i) : index of quantization.
+ int16 nbits, (i) : number of bits (6 or 7)
+ int16 code[], (i) Q9 : Innovative vector.
+ int16 L_subfr, (i) : Subframe lenght.
+ int16 * gain_pit, (o) Q14 : Pitch gain.
+ int32 * gain_cod, (o) Q16 : Code gain.
+ int16 bfi, (i) : bad frame indicator
+ int16 prev_bfi, (i) : Previous BF indicator
+ int16 state, (i) : State of BFH
+ int16 unusable_frame, (i) : UF indicator
+ int16 vad_hist, (i) : number of non-speech frames
+ int16 * mem (i/o) : static memory (4 words)
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Decode the pitch and codebook gains
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwb_math_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+
+#include "qisf_ns.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define MEAN_ENER 30
+#define PRED_ORDER 4
+
+#define L_LTPHIST 5
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+const int16 pdown_unusable[7] = {32767, 31130, 29491, 24576, 7537, 1638, 328};
+const int16 cdown_unusable[7] = {32767, 16384, 8192, 8192, 8192, 4915, 3277};
+
+const int16 pdown_usable[7] = {32767, 32113, 31457, 24576, 7537, 1638, 328};
+const int16 cdown_usable[7] = {32767, 32113, 32113, 32113, 32113, 32113, 22938};
+
+
+/* MA prediction coeff ={0.5, 0.4, 0.3, 0.2} in Q13 */
+const int16 pred[PRED_ORDER] = {4096, 3277, 2458, 1638};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+/* output :static memory (4 words) */
+void dec_gain2_amr_wb_init(int16 * mem)
+{
+
+ /* 4nd order quantizer energy predictor (init to -14.0 in Q10) */
+ mem[0] = -14336; /* past_qua_en[0] */
+ mem[1] = -14336; /* past_qua_en[1] */
+ mem[2] = -14336; /* past_qua_en[2] */
+ mem[3] = -14336; /* past_qua_en[3] */
+ /* 4 *past_gain_pit */
+ /* 5 *past_gain_code */
+ /* 6 *prev_gc */
+ /* next 5 pbuf[] */
+ /* next 5 gbuf[] */
+ /* next 5 pbuf2[] */
+ pv_memset((void *)&mem[4], 0, 18*sizeof(*mem));
+
+ mem[22] = 21845;
+
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void dec_gain2_amr_wb(
+ int16 index, /* (i) : index of quantization. */
+ int16 nbits, /* (i) : number of bits (6 or 7) */
+ int16 code[], /* (i) Q9 : Innovative vector. */
+ int16 L_subfr, /* (i) : Subframe lenght. */
+ int16 * gain_pit, /* (o) Q14 : Pitch gain. */
+ int32 * gain_cod, /* (o) Q16 : Code gain. */
+ int16 bfi, /* (i) : bad frame indicator */
+ int16 prev_bfi, /* (i) : Previous BF indicator */
+ int16 state, /* (i) : State of BFH */
+ int16 unusable_frame, /* (i) : UF indicator */
+ int16 vad_hist, /* (i) : number of non-speech frames */
+ int16 * mem /* (i/o) : static memory (4 words) */
+)
+{
+ const int16 *p;
+ int16 *past_gain_pit, *past_gain_code, *past_qua_en, *gbuf, *pbuf, *prev_gc;
+ int16 *pbuf2;
+ int16 i, tmp, exp, frac, gcode0, exp_gcode0, qua_ener, gcode_inov;
+ int16 tmp1, g_code;
+ int16 tmp2;
+ int32 L_tmp;
+
+ past_qua_en = mem;
+ past_gain_pit = mem + 4;
+ past_gain_code = mem + 5;
+ prev_gc = mem + 6;
+ pbuf = mem + 7;
+ gbuf = mem + 12;
+ pbuf2 = mem + 17;
+
+ /*
+ * Find energy of code and compute:
+ *
+ * L_tmp = 1.0 / sqrt(energy of code/ L_subfr)
+ */
+
+ L_tmp = Dot_product12(code, code, L_subfr, &exp);
+ exp -= 24; /* exp: -18 (code in Q9), -6 (/L_subfr) */
+
+ one_ov_sqrt_norm(&L_tmp, &exp);
+
+ gcode_inov = extract_h(shl_int32(L_tmp, exp - 3)); /* g_code_inov in Q12 */
+
+ /*
+ * Case of erasure.
+ */
+
+ if (bfi != 0)
+ {
+ tmp = median5(&pbuf[2]);
+ *past_gain_pit = tmp;
+
+ if (*past_gain_pit > 15565)
+ {
+ *past_gain_pit = 15565; /* 0.95 in Q14 */
+
+ }
+
+ if (unusable_frame != 0)
+ {
+ *gain_pit = mult_int16(pdown_unusable[state], *past_gain_pit);
+ }
+ else
+ {
+ *gain_pit = mult_int16(pdown_usable[state], *past_gain_pit);
+ }
+ tmp = median5(&gbuf[2]);
+
+ if (vad_hist > 2)
+ {
+ *past_gain_code = tmp;
+ }
+ else
+ {
+
+ if (unusable_frame != 0)
+ {
+ *past_gain_code = mult_int16(cdown_unusable[state], tmp);
+ }
+ else
+ {
+ *past_gain_code = mult_int16(cdown_usable[state], tmp);
+ }
+ }
+
+ /* update table of past quantized energies */
+
+ tmp = past_qua_en[3];
+ tmp1 = past_qua_en[2];
+ L_tmp = tmp;
+ L_tmp += tmp1;
+ past_qua_en[3] = tmp;
+ tmp = past_qua_en[1];
+ tmp1 = past_qua_en[0];
+ L_tmp += tmp;
+ L_tmp += tmp1;
+ past_qua_en[2] = tmp;
+ qua_ener = (int16)(L_tmp >> 3);
+ past_qua_en[1] = tmp1;
+
+
+ qua_ener -= 3072; /* -3 in Q10 */
+
+ if (qua_ener < -14336)
+ {
+ qua_ener = -14336; /* -14 in Q10 */
+ }
+
+ past_qua_en[0] = qua_ener;
+
+
+ for (i = 1; i < 5; i++)
+ {
+ gbuf[i - 1] = gbuf[i];
+ pbuf[i - 1] = pbuf[i];
+ }
+ gbuf[4] = *past_gain_code;
+ pbuf[4] = *past_gain_pit;
+
+
+ /* adjust gain according to energy of code */
+ /* past_gain_code(Q3) * gcode_inov(Q12) => Q16 */
+ *gain_cod = mul_16by16_to_int32(*past_gain_code, gcode_inov);
+
+ return;
+ }
+ /*
+ * Compute gcode0
+ * = Sum(i=0,1) pred[i]*past_qua_en[i] + mean_ener - ener_code
+ */
+
+ L_tmp = L_deposit_h(MEAN_ENER); /* MEAN_ENER in Q16 */
+ L_tmp = shl_int32(L_tmp, 8); /* From Q16 to Q24 */
+ L_tmp = mac_16by16_to_int32(L_tmp, pred[0], past_qua_en[0]); /* Q13*Q10 -> Q24 */
+ L_tmp = mac_16by16_to_int32(L_tmp, pred[1], past_qua_en[1]); /* Q13*Q10 -> Q24 */
+ L_tmp = mac_16by16_to_int32(L_tmp, pred[2], past_qua_en[2]); /* Q13*Q10 -> Q24 */
+ L_tmp = mac_16by16_to_int32(L_tmp, pred[3], past_qua_en[3]); /* 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 = ((int32)gcode0 * 5443) >> 7; /* *0.166096 in Q15 -> Q24 */
+
+ int32_to_dpf(L_tmp, &exp_gcode0, &frac); /* Extract exponant of gcode0 */
+
+ gcode0 = (int16)(power_of_2(14, frac)); /* Put 14 as exponant so that */
+ /* output of Pow2() will be: */
+ /* 16384 < Pow2() <= 32767 */
+ exp_gcode0 -= 14;
+
+ /* Read the quantized gains */
+
+ if (nbits == 6)
+ {
+ p = &t_qua_gain6b[index<<1];
+ }
+ else
+ {
+ p = &t_qua_gain7b[index<<1];
+ }
+ *gain_pit = *p++; /* selected pitch gain in Q14 */
+ g_code = *p++; /* selected code gain in Q11 */
+
+ L_tmp = mul_16by16_to_int32(g_code, gcode0); /* Q11*Q0 -> Q12 */
+ L_tmp = shl_int32(L_tmp, exp_gcode0 + 4); /* Q12 -> Q16 */
+
+ *gain_cod = L_tmp; /* gain of code in Q16 */
+
+ if (prev_bfi == 1)
+ {
+ L_tmp = mul_16by16_to_int32(*prev_gc, 5120); /* prev_gc(Q3) * 1.25(Q12) = Q16 */
+ /* if((*gain_cod > ((*prev_gc) * 1.25)) && (*gain_cod > 100.0)) */
+
+ if ((*gain_cod > L_tmp) && (*gain_cod > 6553600))
+ {
+ *gain_cod = L_tmp;
+ }
+ }
+ /* keep past gain code in Q3 for frame erasure (can saturate) */
+ *past_gain_code = amr_wb_round(shl_int32(*gain_cod, 3));
+ *past_gain_pit = *gain_pit;
+
+
+ *prev_gc = *past_gain_code;
+ tmp = gbuf[1];
+ tmp1 = pbuf[1];
+ tmp2 = pbuf2[1];
+ for (i = 1; i < 5; i++)
+ {
+ gbuf[i - 1] = tmp;
+ pbuf[i - 1] = tmp1;
+ pbuf2[i - 1] = tmp2;
+ tmp = gbuf[i];
+ tmp1 = pbuf[i];
+ tmp2 = pbuf2[i];
+ }
+ gbuf[4] = *past_gain_code;
+ pbuf[4] = *past_gain_pit;
+ pbuf2[4] = *past_gain_pit;
+
+
+ /* adjust gain according to energy of code */
+ int32_to_dpf(*gain_cod, &exp, &frac);
+ L_tmp = mul_32by16(exp, frac, gcode_inov);
+
+ *gain_cod = shl_int32(L_tmp, 3); /* gcode_inov in Q12 */
+
+
+ past_qua_en[3] = past_qua_en[2];
+ past_qua_en[2] = past_qua_en[1];
+ past_qua_en[1] = past_qua_en[0];
+
+ /*
+ * qua_ener = 20*log10(g_code)
+ * = 6.0206*log2(g_code)
+ * = 6.0206*(log2(g_codeQ11) - 11)
+ */
+ L_tmp = (int32)g_code;
+ amrwb_log_2(L_tmp, &exp, &frac);
+ exp -= 11;
+ L_tmp = mul_32by16(exp, frac, 24660); /* x 6.0206 in Q12 */
+
+ /* update table of past quantized energies */
+
+ past_qua_en[0] = (int16)(L_tmp >> 3); /* result in Q10 */
+
+ return;
+}
+
+
diff --git a/media/libstagefright/codecs/amrwb/src/deemphasis_32.cpp b/media/libstagefright/codecs/amrwb/src/deemphasis_32.cpp
new file mode 100644
index 0000000..b80555b
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/deemphasis_32.cpp
@@ -0,0 +1,166 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: deemphasis_32.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 x_hi[], (i) : input signal (bit31..16)
+ int16 x_lo[], (i) : input signal (bit15..4)
+ int16 y[], (o) : output signal (x16)
+ int16 mu, (i) Q15 : deemphasis factor
+ int16 L, (i) : vector size
+ int16 * mem (i/o) : memory (y[-1])
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ 32-bits filtering through 1/(1-mu z^-1)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ Deemphasis H(z) = 1/(1 - 0.68z^(-1)) where mu = 0.67999 in Q15
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwb_math_op.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void deemphasis_32(
+ int16 x_hi[], /* (i) : input signal (bit31..16) */
+ int16 x_lo[], /* (i) : input signal (bit15..4) */
+ int16 y[], /* (o) : output signal (x16) */
+ int16 mu, /* (i) Q15 : deemphasis factor */
+ int16 L, /* (i) : vector size */
+ int16 * mem /* (i/o) : memory (y[-1]) */
+)
+{
+ int16 i;
+ int32 L_tmp;
+ int16 lo, hi;
+
+ L_tmp = ((int32)x_hi[0]) << 16;
+ L_tmp += ((int32)x_lo[0]) << 4;
+ L_tmp = shl_int32(L_tmp, 3);
+
+ L_tmp = fxp_mac_16by16(*mem, mu, L_tmp),
+
+ L_tmp = shl_int32(L_tmp, 1); /* saturation can occur here */
+ y[0] = amr_wb_round(L_tmp);
+
+ lo = x_lo[1];
+ hi = x_hi[1];
+ for (i = 1; i < L - 1; i++)
+ {
+ L_tmp = ((int32)hi) << 16;
+ L_tmp += ((int32)lo) << 4;
+ L_tmp = shl_int32(L_tmp, 3);
+ L_tmp = fxp_mac_16by16(y[i - 1], mu, L_tmp),
+ L_tmp = shl_int32(L_tmp, 1); /* saturation can occur here */
+ y[i] = amr_wb_round(L_tmp);
+ lo = x_lo[i+1];
+ hi = x_hi[i+1];
+ }
+ L_tmp = ((int32)hi) << 16;
+ L_tmp += ((int32)lo) << 4;
+ L_tmp = shl_int32(L_tmp, 3);
+ L_tmp = fxp_mac_16by16(y[i - 1], mu, L_tmp),
+ L_tmp = shl_int32(L_tmp, 1); /* saturation can occur here */
+ y[i] = amr_wb_round(L_tmp);
+
+ *mem = y[L - 1];
+
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrwb/src/dtx.h b/media/libstagefright/codecs/amrwb/src/dtx.h
new file mode 100644
index 0000000..a81f089
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/dtx.h
@@ -0,0 +1,242 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./cpp/include/dtx.h
+
+ Date: 01/04/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+ Static memory, constants and frametypes for the DTX
+------------------------------------------------------------------------------
+*/
+#ifndef DTX_H
+#define DTX_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES AND SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+#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
+ {
+ int16 isf_hist[M * DTX_HIST_SIZE];
+ int16 log_en_hist[DTX_HIST_SIZE];
+ int16 hist_ptr;
+ int16 log_en_index;
+ int16 cng_seed;
+
+ /* DTX handler stuff */
+ int16 dtxHangoverCount;
+ int16 decAnaElapsedCount;
+ int32 D[28];
+ int32 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
+ *****************************************************************************/
+
+ typedef struct
+ {
+ int16 since_last_sid;
+ int16 true_sid_period_inv;
+ int16 log_en;
+ int16 old_log_en;
+ int16 level;
+ int16 isf[M];
+ int16 isf_old[M];
+ int16 cng_seed;
+
+ int16 isf_hist[M * DTX_HIST_SIZE];
+ int16 log_en_hist[DTX_HIST_SIZE];
+ int16 hist_ptr;
+
+ int16 dtxHangoverCount;
+ int16 decAnaElapsedCount;
+
+ int16 sid_frame;
+ int16 valid_data;
+ int16 dtxHangoverAdded;
+
+ int16 dtxGlobalState; /* contains previous state */
+ /* updated in main decoder */
+
+ int16 data_updated; /* marker to know if CNI data is ever renewed */
+
+ int16 dither_seed;
+ int16 CN_dith;
+
+ } dtx_decState;
+
+ int16 dtx_enc_init(dtx_encState ** st, int16 isf_init[]);
+ int16 dtx_enc_reset(dtx_encState * st, int16 isf_init[]);
+ void dtx_enc_exit(dtx_encState ** st);
+
+ int16 dtx_enc(
+ dtx_encState * st, /* i/o : State struct */
+ int16 isf[M], /* o : CN ISF vector */
+ int16 * exc2, /* o : CN excitation */
+ int16 ** prms
+ );
+
+ int16 dtx_buffer(
+ dtx_encState * st, /* i/o : State struct */
+ int16 isf_new[], /* i : isf vector */
+ int32 enr, /* i : residual energy (in L_FRAME) */
+ int16 codec_mode
+ );
+
+ void tx_dtx_handler(dtx_encState * st, /* i/o : State struct */
+ int16 vad_flag, /* i : vad decision */
+ int16 * usedMode /* i/o : mode changed or not */
+ );
+
+ void Qisf_ns(
+ int16 * isf1, /* input : ISF in the frequency domain (0..0.5) */
+ int16 * isf_q, /* output: quantized ISF */
+ int16 * indice /* output: quantization indices */
+ );
+
+
+ int16 dtx_dec_amr_wb_reset(dtx_decState * st, const int16 isf_init[]);
+
+ int16 dtx_dec_amr_wb(
+ dtx_decState * st, /* i/o : State struct */
+ int16 * exc2, /* o : CN excitation */
+ int16 new_state, /* i : New DTX state */
+ int16 isf[], /* o : CN ISF vector */
+ int16 ** prms
+ );
+
+ void dtx_dec_amr_wb_activity_update(
+ dtx_decState * st,
+ int16 isf[],
+ int16 exc[]);
+
+
+ int16 rx_amr_wb_dtx_handler(
+ dtx_decState * st, /* i/o : State struct */
+ int16 frame_type /* i : Frame type */
+ );
+
+ void Disf_ns(
+ int16 * indice, /* input: quantization indices */
+ int16 * isf_q /* input : ISF in the frequency domain (0..0.5) */
+ );
+
+ void aver_isf_history(
+ int16 isf_old[],
+ int16 indices[],
+ int32 isf_aver[]
+ );
+ void find_frame_indices(
+ int16 isf_old_tx[],
+ int16 indices[],
+ dtx_encState * st
+ );
+
+ int16 dithering_control(
+ dtx_encState * st
+ );
+ void CN_dithering(
+ int16 isf[M],
+ int32 * L_log_en_int,
+ int16 * dither_seed
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DTX_H */
+
+
diff --git a/media/libstagefright/codecs/amrwb/src/dtx_decoder_amr_wb.cpp b/media/libstagefright/codecs/amrwb/src/dtx_decoder_amr_wb.cpp
new file mode 100644
index 0000000..7c798cc
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/dtx_decoder_amr_wb.cpp
@@ -0,0 +1,984 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: dtx_decoder_amr_wb.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ DTX functions
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwb_math_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h" /* prototype of functions */
+#include "get_amr_wb_bits.h"
+#include "dtx.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+/*
+ * Function : dtx_dec_amr_wb_reset
+ */
+int16 dtx_dec_amr_wb_reset(dtx_decState * st, const int16 isf_init[])
+{
+ int16 i;
+
+
+ if (st == (dtx_decState *) NULL)
+ {
+ /* dtx_dec_amr_wb_reset invalid parameter */
+ return (-1);
+ }
+ st->since_last_sid = 0;
+ st->true_sid_period_inv = (1 << 13); /* 0.25 in Q15 */
+
+ st->log_en = 3500;
+ st->old_log_en = 3500;
+ /* low level noise for better performance in DTX handover cases */
+
+ st->cng_seed = RANDOM_INITSEED;
+
+ st->hist_ptr = 0;
+
+ /* Init isf_hist[] and decoder log frame energy */
+ pv_memcpy((void *)st->isf, (void *)isf_init, M*sizeof(*isf_init));
+
+ pv_memcpy((void *)st->isf_old, (void *)isf_init, M*sizeof(*isf_init));
+
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ pv_memcpy((void *)&st->isf_hist[i * M], (void *)isf_init, M*sizeof(*isf_init));
+ st->log_en_hist[i] = st->log_en;
+ }
+
+ st->dtxHangoverCount = DTX_HANG_CONST;
+ st->decAnaElapsedCount = 32767;
+
+ st->sid_frame = 0;
+ st->valid_data = 0;
+ st->dtxHangoverAdded = 0;
+
+ st->dtxGlobalState = SPEECH;
+ st->data_updated = 0;
+
+ st->dither_seed = RANDOM_INITSEED;
+ st->CN_dith = 0;
+
+ return 0;
+}
+
+
+/*
+ Table of new SPD synthesis states
+
+ | previous SPD_synthesis_state
+ Incoming |
+ frame_type | SPEECH | DTX | DTX_MUTE
+ ---------------------------------------------------------------
+ RX_SPEECH_GOOD , | | |
+ RX_SPEECH_PR_DEGRADED | SPEECH | SPEECH | SPEECH
+ ----------------------------------------------------------------
+ RX_SPEECH_BAD, | SPEECH | DTX | DTX_MUTE
+ ----------------------------------------------------------------
+ RX_SID_FIRST, | DTX | DTX/(DTX_MUTE)| DTX_MUTE
+ ----------------------------------------------------------------
+ RX_SID_UPDATE, | DTX | DTX | DTX
+ ----------------------------------------------------------------
+ RX_SID_BAD, | DTX | DTX/(DTX_MUTE)| DTX_MUTE
+ ----------------------------------------------------------------
+ RX_NO_DATA, | SPEECH | DTX/(DTX_MUTE)| DTX_MUTE
+ RX_SPARE |(class2 garb.)| |
+ ----------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*
+ * Function : dtx_dec_amr_wb
+ */
+int16 dtx_dec_amr_wb(
+ dtx_decState * st, /* i/o : State struct */
+ int16 * exc2, /* o : CN excitation */
+ int16 new_state, /* i : New DTX state */
+ int16 isf[], /* o : CN ISF vector */
+ int16 ** prms
+)
+{
+ int16 log_en_index;
+ int16 ind[7];
+ int16 i, j;
+ int16 int_fac;
+ int16 gain;
+
+ int32 L_isf[M], L_log_en_int, level32, ener32;
+ int16 ptr;
+ int16 tmp_int_length;
+ int16 tmp, exp, exp0, log_en_int_e, log_en_int_m, level;
+
+ /* This function is called if synthesis state is not SPEECH the globally passed inputs to this function
+ * are st->sid_frame st->valid_data st->dtxHangoverAdded new_state (SPEECH, DTX, DTX_MUTE) */
+
+ if ((st->dtxHangoverAdded != 0) &&
+ (st->sid_frame != 0))
+ {
+ /* sid_first after dtx hangover period */
+ /* or sid_upd after dtxhangover */
+
+ /* consider twice the last frame */
+ ptr = st->hist_ptr + 1;
+
+ if (ptr == DTX_HIST_SIZE)
+ ptr = 0;
+
+ pv_memcpy((void *)&st->isf_hist[ptr * M], (void *)&st->isf_hist[st->hist_ptr * M], M*sizeof(*st->isf_hist));
+
+ st->log_en_hist[ptr] = st->log_en_hist[st->hist_ptr];
+
+ /* compute mean log energy and isf from decoded signal (SID_FIRST) */
+ st->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 */
+ st->log_en = add_int16(st->log_en, st->log_en_hist[i]);
+
+ for (j = 0; j < M; j++)
+ {
+ L_isf[j] = add_int32(L_isf[j], (int32)(st->isf_hist[i * M + j]));
+ }
+ }
+
+ /* st->log_en in Q9 */
+ st->log_en >>= 1;
+
+ /* Add 2 in Q9, in order to have only positive values for Pow2 */
+ /* this value is subtracted back after Pow2 function */
+ st->log_en += 1024;
+
+ if (st->log_en < 0)
+ st->log_en = 0;
+
+ for (j = 0; j < M; j++)
+ {
+ st->isf[j] = (int16)(L_isf[j] >> 3); /* divide by 8 */
+ }
+
+ }
+
+ if (st->sid_frame != 0)
+ {
+ /* Set old SID parameters, always shift */
+ /* even if there is no new valid_data */
+
+ pv_memcpy((void *)st->isf_old, (void *)st->isf, M*sizeof(*st->isf));
+
+ st->old_log_en = st->log_en;
+
+ if (st->valid_data != 0) /* new data available (no CRC) */
+ {
+ /* st->true_sid_period_inv = 1.0f/st->since_last_sid; */
+ /* Compute interpolation factor, since the division only works * for values of since_last_sid <
+ * 32 we have to limit the * interpolation to 32 frames */
+ tmp_int_length = st->since_last_sid;
+
+
+ if (tmp_int_length > 32)
+ {
+ tmp_int_length = 32;
+ }
+
+ if (tmp_int_length >= 2)
+ {
+ st->true_sid_period_inv = div_16by16(1 << 10, shl_int16(tmp_int_length, 10));
+ }
+ else
+ {
+ st->true_sid_period_inv = 1 << 14; /* 0.5 it Q15 */
+ }
+
+ ind[0] = Serial_parm(6, prms);
+ ind[1] = Serial_parm(6, prms);
+ ind[2] = Serial_parm(6, prms);
+ ind[3] = Serial_parm(5, prms);
+ ind[4] = Serial_parm(5, prms);
+
+ Disf_ns(ind, st->isf);
+
+ log_en_index = Serial_parm(6, prms);
+
+ /* read background noise stationarity information */
+ st->CN_dith = Serial_parm_1bit(prms);
+
+ /* st->log_en = (float)log_en_index / 2.625 - 2.0; */
+ /* log2(E) in Q9 (log2(E) lies in between -2:22) */
+ st->log_en = shl_int16(log_en_index, 15 - 6);
+
+ /* Divide by 2.625 */
+ st->log_en = mult_int16(st->log_en, 12483);
+ /* Subtract 2 in Q9 is done later, after Pow2 function */
+
+ /* no interpolation at startup after coder reset */
+ /* or when SID_UPD has been received right after SPEECH */
+
+ if ((st->data_updated == 0) || (st->dtxGlobalState == SPEECH))
+ {
+ pv_memcpy((void *)st->isf_old, (void *)st->isf, M*sizeof(*st->isf));
+
+ st->old_log_en = st->log_en;
+ }
+ } /* endif valid_data */
+ } /* endif sid_frame */
+
+
+ if ((st->sid_frame != 0) && (st->valid_data != 0))
+ {
+ st->since_last_sid = 0;
+ }
+ /* Interpolate SID info */
+ int_fac = shl_int16(st->since_last_sid, 10); /* Q10 */
+ int_fac = mult_int16(int_fac, st->true_sid_period_inv); /* Q10 * Q15 -> Q10 */
+
+ /* Maximize to 1.0 in Q10 */
+
+ if (int_fac > 1024)
+ {
+ int_fac = 1024;
+ }
+ int_fac = shl_int16(int_fac, 4); /* Q10 -> Q14 */
+
+ L_log_en_int = mul_16by16_to_int32(int_fac, st->log_en); /* Q14 * Q9 -> Q24 */
+
+ for (i = 0; i < M; i++)
+ {
+ isf[i] = mult_int16(int_fac, st->isf[i]);/* Q14 * Q15 -> Q14 */
+ }
+
+ int_fac = 16384 - int_fac; /* 1-k in Q14 */
+
+ /* ( Q14 * Q9 -> Q24 ) + Q24 -> Q24 */
+ L_log_en_int = mac_16by16_to_int32(L_log_en_int, int_fac, st->old_log_en);
+
+ for (i = 0; i < M; i++)
+ {
+ /* Q14 + (Q14 * Q15 -> Q14) -> Q14 */
+ isf[i] = add_int16(isf[i], mult_int16(int_fac, st->isf_old[i]));
+ isf[i] = shl_int16(isf[i], 1); /* Q14 -> Q15 */
+ }
+
+ /* If background noise is non-stationary, insert comfort noise dithering */
+ if (st->CN_dith != 0)
+ {
+ CN_dithering(isf, &L_log_en_int, &st->dither_seed);
+ }
+ /* L_log_en_int corresponds to log2(E)+2 in Q24, i.e log2(gain)+1 in Q25 */
+ /* Q25 -> Q16 */
+ L_log_en_int >>= 9;
+
+ /* Find integer part */
+ log_en_int_e = extract_h(L_log_en_int);
+
+ /* Find fractional part */
+ log_en_int_m = (int16)(sub_int32(L_log_en_int, L_deposit_h(log_en_int_e)) >> 1);
+
+ /* Subtract 2 from L_log_en_int 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 += 15;
+
+ /* level = (float)( pow( 2.0f, log_en ) ); */
+ level32 = power_of_2(log_en_int_e, log_en_int_m); /* Q16 */
+
+ exp0 = normalize_amr_wb(level32);
+ level32 <<= exp0; /* level in Q31 */
+ exp0 = 15 - exp0;
+ level = (int16)(level32 >> 16); /* level in Q15 */
+
+ /* generate white noise vector */
+ for (i = 0; i < L_FRAME; i++)
+ {
+ exc2[i] = noise_gen_amrwb(&(st->cng_seed)) >> 4;
+ }
+
+ /* gain = level / sqrt(ener) * sqrt(L_FRAME) */
+
+ /* energy of generated excitation */
+ ener32 = Dot_product12(exc2, exc2, L_FRAME, &exp);
+
+ one_ov_sqrt_norm(&ener32, &exp);
+
+ gain = extract_h(ener32);
+
+ gain = mult_int16(level, gain); /* gain in Q15 */
+
+ exp += exp0;
+
+ /* Multiply by sqrt(L_FRAME)=16, i.e. shift left by 4 */
+ exp += 4;
+
+ for (i = 0; i < L_FRAME; i++)
+ {
+ tmp = mult_int16(exc2[i], gain); /* Q0 * Q15 */
+ exc2[i] = shl_int16(tmp, exp);
+ }
+
+
+ if (new_state == DTX_MUTE)
+ {
+ /* mute comfort noise as it has been quite a long time since last SID update was performed */
+
+ tmp_int_length = st->since_last_sid;
+
+ if (tmp_int_length > 32)
+ {
+ tmp_int_length = 32;
+ }
+
+ st->true_sid_period_inv = div_16by16(1 << 10, shl_int16(tmp_int_length, 10));
+
+ st->since_last_sid = 0;
+ st->old_log_en = st->log_en;
+ /* subtract 1/8 in Q9 (energy), i.e -3/8 dB */
+ st->log_en -= 64;
+ }
+ /* reset interpolation length timer if data has been updated. */
+
+ if ((st->sid_frame != 0) &&
+ ((st->valid_data != 0) ||
+ ((st->valid_data == 0) && (st->dtxHangoverAdded) != 0)))
+ {
+ st->since_last_sid = 0;
+ st->data_updated = 1;
+ }
+ return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void dtx_dec_amr_wb_activity_update(
+ dtx_decState * st,
+ int16 isf[],
+ int16 exc[])
+{
+ int16 i;
+
+ int32 L_frame_en;
+ int16 log_en_e, log_en_m, log_en;
+
+
+ st->hist_ptr++;
+
+ if (st->hist_ptr == DTX_HIST_SIZE)
+ {
+ st->hist_ptr = 0;
+ }
+ pv_memcpy((void *)&st->isf_hist[st->hist_ptr * M], (void *)isf, M*sizeof(*isf));
+
+
+ /* compute log energy based on excitation frame energy in Q0 */
+ L_frame_en = 0;
+ for (i = 0; i < L_FRAME; i++)
+ {
+ L_frame_en = mac_16by16_to_int32(L_frame_en, exc[i], exc[i]);
+ }
+ L_frame_en >>= 1;
+
+ /* log_en = (float)log10(L_frame_en/(float)L_FRAME)/(float)log10(2.0f); */
+ amrwb_log_2(L_frame_en, &log_en_e, &log_en_m);
+
+ /* convert exponent and mantissa to int16 Q7. Q7 is used to simplify averaging in dtx_enc */
+ log_en = shl_int16(log_en_e, 7); /* Q7 */
+ log_en += log_en_m >> 8;
+
+ /* Divide by L_FRAME = 256, i.e subtract 8 in Q7 = 1024 */
+ log_en -= 1024;
+
+ /* insert into log energy buffer */
+ st->log_en_hist[st->hist_ptr] = log_en;
+
+ return;
+}
+
+
+/*
+ Table of new SPD synthesis states
+
+ | previous SPD_synthesis_state
+ Incoming |
+ frame_type | SPEECH | DTX | DTX_MUTE
+ ---------------------------------------------------------------
+ RX_SPEECH_GOOD , | | |
+ RX_SPEECH_PR_DEGRADED | SPEECH | SPEECH | SPEECH
+ ----------------------------------------------------------------
+ RX_SPEECH_BAD, | SPEECH | DTX | DTX_MUTE
+ ----------------------------------------------------------------
+ RX_SID_FIRST, | DTX | DTX/(DTX_MUTE)| DTX_MUTE
+ ----------------------------------------------------------------
+ RX_SID_UPDATE, | DTX | DTX | DTX
+ ----------------------------------------------------------------
+ RX_SID_BAD, | DTX | DTX/(DTX_MUTE)| DTX_MUTE
+ ----------------------------------------------------------------
+ RX_NO_DATA, | SPEECH | DTX/(DTX_MUTE)| DTX_MUTE
+ RX_SPARE |(class2 garb.)| |
+ ----------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+int16 rx_amr_wb_dtx_handler(
+ dtx_decState * st, /* i/o : State struct */
+ int16 frame_type /* i : Frame type */
+)
+{
+ int16 newState;
+ int16 encState;
+
+ /* DTX if SID frame or previously in DTX{_MUTE} and (NO_RX OR BAD_SPEECH) */
+
+
+
+ if ((frame_type == RX_SID_FIRST) ||
+ (frame_type == RX_SID_UPDATE) ||
+ (frame_type == RX_SID_BAD) ||
+ (((st->dtxGlobalState == DTX) ||
+ (st->dtxGlobalState == DTX_MUTE)) &&
+ ((frame_type == RX_NO_DATA) ||
+ (frame_type == RX_SPEECH_BAD) ||
+ (frame_type == RX_SPEECH_LOST))))
+ {
+ newState = DTX;
+
+ /* stay in mute for these input types */
+
+ if ((st->dtxGlobalState == DTX_MUTE) &&
+ ((frame_type == RX_SID_BAD) ||
+ (frame_type == RX_SID_FIRST) ||
+ (frame_type == RX_SPEECH_LOST) ||
+ (frame_type == RX_NO_DATA)))
+ {
+ newState = DTX_MUTE;
+ }
+ /* evaluate if noise parameters are too old */
+ /* since_last_sid is reset when CN parameters have been updated */
+ st->since_last_sid = add_int16(st->since_last_sid, 1);
+
+ /* no update of sid parameters in DTX for a long while */
+
+ if (st->since_last_sid > DTX_MAX_EMPTY_THRESH)
+ {
+ newState = DTX_MUTE;
+ }
+ }
+ else
+ {
+ newState = SPEECH;
+ st->since_last_sid = 0;
+ }
+
+ /* reset the decAnaElapsed Counter when receiving CNI data the first time, to robustify counter missmatch
+ * after handover this might delay the bwd CNI analysis in the new decoder slightly. */
+
+ if ((st->data_updated == 0) &&
+ (frame_type == RX_SID_UPDATE))
+ {
+ st->decAnaElapsedCount = 0;
+ }
+ /* update the SPE-SPD DTX hangover synchronization */
+ /* to know when SPE has added dtx hangover */
+ st->decAnaElapsedCount = add_int16(st->decAnaElapsedCount, 1);
+ st->dtxHangoverAdded = 0;
+
+
+ if ((frame_type == RX_SID_FIRST) ||
+ (frame_type == RX_SID_UPDATE) ||
+ (frame_type == RX_SID_BAD) ||
+ (frame_type == RX_NO_DATA))
+ {
+ encState = DTX;
+ }
+ else
+ {
+ encState = SPEECH;
+ }
+
+
+ if (encState == SPEECH)
+ {
+ st->dtxHangoverCount = DTX_HANG_CONST;
+ }
+ else
+ {
+
+ if (st->decAnaElapsedCount > DTX_ELAPSED_FRAMES_THRESH)
+ {
+ st->dtxHangoverAdded = 1;
+ st->decAnaElapsedCount = 0;
+ st->dtxHangoverCount = 0;
+ }
+ else if (st->dtxHangoverCount == 0)
+ {
+ st->decAnaElapsedCount = 0;
+ }
+ else
+ {
+ st->dtxHangoverCount--;
+ }
+ }
+
+ if (newState != SPEECH)
+ {
+ /* DTX or DTX_MUTE CN data is not in a first SID, first SIDs are marked as SID_BAD but will do
+ * backwards analysis if a hangover period has been added according to the state machine above */
+
+ st->sid_frame = 0;
+ st->valid_data = 0;
+
+
+ if (frame_type == RX_SID_FIRST)
+ {
+ st->sid_frame = 1;
+ }
+ else if (frame_type == RX_SID_UPDATE)
+ {
+ st->sid_frame = 1;
+ st->valid_data = 1;
+ }
+ else if (frame_type == RX_SID_BAD)
+ {
+ st->sid_frame = 1;
+ st->dtxHangoverAdded = 0; /* use old data */
+ }
+ }
+ return newState;
+ /* newState is used by both SPEECH AND DTX synthesis routines */
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void aver_isf_history(
+ int16 isf_old[],
+ int16 indices[],
+ int32 isf_aver[]
+)
+{
+ int16 i, j, k;
+ int16 isf_tmp[2 * M];
+ int32 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 = add_int32(L_tmp, (int32)(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;
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void find_frame_indices(
+ int16 isf_old_tx[],
+ int16 indices[],
+ dtx_encState * st
+)
+{
+ int32 L_tmp, summin, summax, summax2nd;
+ int16 i, j, tmp;
+ int16 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 += tmp;
+ st->sumD[i] = sub_int32(st->sumD[i], st->D[j]);
+ tmp--;
+ }
+
+ /* 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 -= tmp)
+ {
+ tmp++;
+ 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--;
+
+ if (ptr < 0)
+ {
+ ptr = DTX_HIST_SIZE_MIN_ONE;
+ }
+ L_tmp = 0;
+ for (j = 0; j < M; j++)
+ {
+ tmp = sub_int16(isf_old_tx[st->hist_ptr * M + j], isf_old_tx[ptr * M + j]);
+ L_tmp = mac_16by16_to_int32(L_tmp, tmp, tmp);
+ }
+ st->D[i - 1] = L_tmp;
+
+ /* Update also the column sums. */
+ st->sumD[0] = add_int32(st->sumD[0], st->D[i - 1]);
+ st->sumD[i] = add_int32(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 (st->sumD[i] > summax)
+ {
+ indices[0] = i;
+ summax = st->sumD[i];
+ }
+
+ if (st->sumD[i] < summin)
+ {
+ 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 ((st->sumD[i] > summax2nd) && (i != indices[0]))
+ {
+ indices[1] = i;
+ summax2nd = st->sumD[i];
+ }
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ indices[i] = sub_int16(st->hist_ptr, indices[i]);
+
+ if (indices[i] < 0)
+ {
+ indices[i] = add_int16(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 = normalize_amr_wb(summax);
+ summax <<= tmp;
+ summin <<= tmp;
+ L_tmp = mul_16by16_to_int32(amr_wb_round(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 = shl_int32(summax2nd, tmp);
+ L_tmp = mul_16by16_to_int32(amr_wb_round(summax2nd), INV_MED_THRESH);
+
+ if (L_tmp <= summin)
+ {
+ indices[1] = -1;
+ }
+ return;
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+int16 dithering_control(dtx_encState * st)
+{
+ int16 i, tmp, mean, CN_dith, gain_diff;
+ int32 ISF_diff;
+
+ /* determine how stationary the spectrum of background noise is */
+ ISF_diff = 0;
+ for (i = 0; i < 8; i++)
+ {
+ ISF_diff = add_int32(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_int16(mean, st->log_en_hist[i]);
+ }
+ mean >>= 3;
+ gain_diff = 0;
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ tmp = sub_int16(st->log_en_hist[i], mean);
+ tmp = tmp - (tmp < 0);
+
+ gain_diff += tmp ^(tmp >> 15); /* tmp ^sign(tmp) */;
+ }
+ if (gain_diff > GAIN_THR)
+ {
+ CN_dith = 1;
+ }
+ return CN_dith;
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void CN_dithering(
+ int16 isf[M],
+ int32 * L_log_en_int,
+ int16 * dither_seed
+)
+{
+ int16 temp, temp1, i, dither_fac, rand_dith;
+ int16 rand_dith2;
+
+ /* Insert comfort noise dithering for energy parameter */
+ rand_dith = noise_gen_amrwb(dither_seed) >> 1;
+ rand_dith2 = noise_gen_amrwb(dither_seed) >> 1;
+ rand_dith += rand_dith2;
+ *L_log_en_int = add_int32(*L_log_en_int, mul_16by16_to_int32(rand_dith, GAIN_FACTOR));
+
+ if (*L_log_en_int < 0)
+ {
+ *L_log_en_int = 0;
+ }
+ /* Insert comfort noise dithering for spectral parameters (ISF-vector) */
+ dither_fac = ISF_FACTOR_LOW;
+
+ rand_dith = noise_gen_amrwb(dither_seed) >> 1;
+ rand_dith2 = noise_gen_amrwb(dither_seed) >> 1;
+ rand_dith += rand_dith2;
+ temp = add_int16(isf[0], mult_int16_r(rand_dith, dither_fac));
+
+ /* Make sure that isf[0] will not get negative values */
+ if (temp < ISF_GAP)
+ {
+ isf[0] = ISF_GAP;
+ }
+ else
+ {
+ isf[0] = temp;
+ }
+
+ for (i = 1; i < M - 1; i++)
+ {
+ dither_fac = add_int16(dither_fac, ISF_FACTOR_STEP);
+
+ rand_dith = noise_gen_amrwb(dither_seed) >> 1;
+ rand_dith2 = noise_gen_amrwb(dither_seed) >> 1;
+ rand_dith += rand_dith2;
+ temp = add_int16(isf[i], mult_int16_r(rand_dith, dither_fac));
+ temp1 = sub_int16(temp, isf[i - 1]);
+
+ /* Make sure that isf spacing remains at least ISF_DITH_GAP Hz */
+ if (temp1 < ISF_DITH_GAP)
+ {
+ isf[i] = isf[i - 1] + ISF_DITH_GAP;
+ }
+ else
+ {
+ isf[i] = temp;
+ }
+ }
+
+ /* Make sure that isf[M-2] will not get values above 16384 */
+ if (isf[M - 2] > 16384)
+ {
+ isf[M - 2] = 16384;
+ }
+ return;
+}
diff --git a/media/libstagefright/codecs/amrwb/src/e_pv_amrwbdec.h b/media/libstagefright/codecs/amrwb/src/e_pv_amrwbdec.h
new file mode 100644
index 0000000..251a3ce
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/e_pv_amrwbdec.h
@@ -0,0 +1,136 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+
+ Filename: e_pv_amrwbdec.h
+ Funtions:
+
+
+ Date: 05/03/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef E_PV_AMRWBDEC_H
+#define E_PV_AMRWBDEC_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvamrwbdecoder_cnst.h" /* coder constant parameters */
+#include "dtx.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+typedef struct
+{
+ int16 old_exc[PIT_MAX + L_INTERPOL]; /* old excitation vector */
+ int16 ispold[M]; /* old isp (immittance spectral pairs)*/
+ int16 isfold[M]; /* old isf (frequency domain) */
+ int16 isf_buf[L_MEANBUF * M]; /* isf buffer(frequency domain) */
+ int16 past_isfq[M]; /* past isf quantizer */
+ int16 tilt_code; /* tilt of code */
+ int16 Q_old; /* old scaling factor */
+ int16 Qsubfr[4]; /* old maximum scaling factor */
+ int32 L_gc_thres; /* threshold for noise enhancer */
+ int16 mem_syn_hi[M]; /* modified synthesis memory (MSB) */
+ int16 mem_syn_lo[M]; /* modified synthesis memory (LSB) */
+ int16 mem_deemph; /* speech deemph filter memory */
+ int16 mem_sig_out[6]; /* hp50 filter memory for synthesis */
+ int16 mem_oversamp[2 * L_FILT]; /* synthesis oversampled filter memory */
+ int16 mem_syn_hf[M16k]; /* HF synthesis memory */
+ int16 mem_hf[2 * L_FILT16k]; /* HF band-pass filter memory */
+ int16 mem_hf2[2 * L_FILT16k]; /* HF band-pass filter memory */
+ int16 mem_hf3[2 * L_FILT16k]; /* HF band-pass filter memory */
+ int16 seed; /* random memory for frame erasure */
+ int16 seed2; /* random memory for HF generation */
+ int16 old_T0; /* old pitch lag */
+ int16 old_T0_frac; /* old pitch fraction lag */
+ int16 lag_hist[5];
+ int16 dec_gain[23]; /* gain decoder memory */
+ int16 seed3; /* random memory for lag concealment */
+ int16 disp_mem[8]; /* phase dispersion memory */
+ int16 mem_hp400[6]; /* hp400 filter memory for synthesis */
+
+ int16 prev_bfi;
+ int16 state;
+ int16 first_frame;
+ dtx_decState dtx_decSt;
+ int16 vad_hist;
+
+} Decoder_State;
+
+typedef struct
+{
+ Decoder_State state;
+ int16 ScratchMem[L_SUBFR + L_SUBFR16k + ((L_SUBFR + M + M16k +1)<<1) + \
+ (2*L_FRAME + 1) + PIT_MAX + L_INTERPOL + NB_SUBFR*(M+1) \
+ + 3*(M+L_SUBFR) + M16k];
+} PV_AmrWbDec;
+
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
diff --git a/media/libstagefright/codecs/amrwb/src/get_amr_wb_bits.cpp b/media/libstagefright/codecs/amrwb/src/get_amr_wb_bits.cpp
new file mode 100644
index 0000000..b325e8f
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/get_amr_wb_bits.cpp
@@ -0,0 +1,164 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: get_amr_wb_bits.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 no_of_bits, input : number of bits
+ int16 ** prms bitstream pointer
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Returns no_of_bits from serial bit stream
+ Serial_parm -> convert serial stream to parameters
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "get_amr_wb_bits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+int16 Serial_parm( /* Return the parameter */
+ int16 no_of_bits, /* input : number of bits */
+ int16 ** prms
+)
+{
+ int16 value = 0;
+ int16 i;
+
+ for (i = no_of_bits >> 1; i != 0; i--)
+ {
+ value <<= 2;
+
+ if (*((*prms)++) == BIT_1)
+ {
+ value |= 2;
+ }
+
+ if (*((*prms)++) == BIT_1)
+ {
+ value |= 1;
+ }
+
+ }
+
+ if (no_of_bits&1)
+ {
+ value <<= 1;
+
+ if (*((*prms)++) == BIT_1)
+ {
+ value |= 1;
+ }
+
+ }
+
+ return (value);
+}
+
+
+int16 Serial_parm_1bit(int16 ** prms) /* Return the parameter */
+{
+ int16 value = 0;
+
+ if (*((*prms)++) == BIT_1)
+ {
+ value = 1;
+ }
+ return (value);
+}
diff --git a/media/libstagefright/codecs/amrwb/src/get_amr_wb_bits.h b/media/libstagefright/codecs/amrwb/src/get_amr_wb_bits.h
new file mode 100644
index 0000000..48e43db
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/get_amr_wb_bits.h
@@ -0,0 +1,60 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*--------------------------------------------------------------------------*
+ * get_amr_wb_bits.h *
+ *--------------------------------------------------------------------------*
+ * Number of bits for different modes *
+ *--------------------------------------------------------------------------*/
+
+#ifndef GET_AMR_WB_BITS_H
+#define GET_AMR_WB_BITS_H
+
+
+#include "pv_amr_wb_type_defs.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ int16 Serial_parm( /* Return the parameter */
+ int16 no_of_bits, /* input : number of bits */
+ int16 ** prms
+ );
+
+ int16 Serial_parm_1bit( /* Return the parameter */
+ int16 ** prms
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/amrwb/src/highpass_400hz_at_12k8.cpp b/media/libstagefright/codecs/amrwb/src/highpass_400hz_at_12k8.cpp
new file mode 100644
index 0000000..6503454
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/highpass_400hz_at_12k8.cpp
@@ -0,0 +1,201 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: highpass_400Hz_at_12k8.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 signal[], input signal / output is divided by 16
+ int16 lg, lenght of signal
+ int16 mem[] filter memory [6]
+
+
+------------------------------------------------------------------------------
+ FUNCTION 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];
+
+ int16 b[3] = {3660, -7320, 3660}; in Q12
+ int16 a[3] = {4096, 7320, -3540}; in Q12
+
+ float --> b[3] = {0.893554687, -1.787109375, 0.893554687};
+ a[3] = {1.000000000, 1.787109375, -0.864257812};
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwb_math_op.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+/* Initialization of static values */
+
+void highpass_400Hz_at_12k8_init(int16 mem[])
+{
+ pv_memset((void *)mem, 0, 6*sizeof(*mem));
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void highpass_400Hz_at_12k8(
+ int16 signal[], /* input signal / output is divided by 16 */
+ int16 lg, /* lenght of signal */
+ int16 mem[] /* filter memory [6] */
+)
+{
+ int16 i, x2;
+ int16 y2_hi, y2_lo, y1_hi, y1_lo, x0, x1;
+ int32 L_tmp1;
+ int32 L_tmp2;
+
+ y2_hi = mem[0];
+ y2_lo = mem[1];
+ y1_hi = mem[2];
+ y1_lo = mem[3];
+ x0 = mem[4];
+ x1 = mem[5];
+
+ for (i = 0; i < lg; i++)
+ {
+
+ /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[0]*x[i-2] */
+ /* + a[0]*y[i-1] + a[1] * y[i-2]; */
+
+ L_tmp1 = fxp_mac_16by16(y1_lo, 29280, 8192L);
+ L_tmp2 = fxp_mul_16by16(y1_hi, 29280);
+ L_tmp1 = fxp_mac_16by16(y2_lo, -14160, L_tmp1);
+ L_tmp2 = fxp_mac_16by16(y2_hi, -14160, L_tmp2);
+ x2 = x1;
+ x1 = x0;
+ x0 = signal[i];
+ L_tmp2 = fxp_mac_16by16(x2, 915, L_tmp2);
+ L_tmp2 = fxp_mac_16by16(x1, -1830, L_tmp2);
+ L_tmp2 = fxp_mac_16by16(x0, 915, L_tmp2);
+
+ L_tmp1 = (L_tmp1 >> 13) + (L_tmp2 << 2); /* coeff Q12 --> Q13 */
+
+ y2_hi = y1_hi;
+ y2_lo = y1_lo;
+ /* signal is divided by 16 to avoid overflow in energy computation */
+ signal[i] = (int16)((L_tmp1 + 0x00008000) >> 16);
+
+ y1_hi = (int16)(L_tmp1 >> 16);
+ y1_lo = (int16)((L_tmp1 - (y1_hi << 16)) >> 1);
+
+
+ }
+
+
+ mem[0] = y2_hi;
+ mem[1] = y2_lo;
+ mem[2] = y1_hi;
+ mem[3] = y1_lo;
+ mem[4] = x0;
+ mem[5] = x1;
+
+}
+
+
diff --git a/media/libstagefright/codecs/amrwb/src/highpass_50hz_at_12k8.cpp b/media/libstagefright/codecs/amrwb/src/highpass_50hz_at_12k8.cpp
new file mode 100644
index 0000000..c70c163
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/highpass_50hz_at_12k8.cpp
@@ -0,0 +1,205 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: highpass_50Hz_at_12k8.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 signal[], input signal / output is divided by 16
+ int16 lg, lenght of signal
+ int16 mem[] filter memory [6]
+
+
+------------------------------------------------------------------------------
+ FUNCTION 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];
+
+ int16 b[3] = {4053, -8106, 4053}; in Q12
+ int16 a[3] = {8192, 16211, -8021}; in Q12
+
+ float --> b[3] = {0.989501953, -1.979003906, 0.989501953};
+ a[3] = {1.000000000, 1.978881836, -0.979125977};
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwb_math_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void highpass_50Hz_at_12k8_init(int16 mem[])
+{
+ pv_memset((void *)mem, 0, 6*sizeof(*mem));
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void highpass_50Hz_at_12k8(
+ int16 signal[], /* input/output signal */
+ int16 lg, /* lenght of signal */
+ int16 mem[] /* filter memory [6] */
+)
+{
+ int16 i, x2;
+ int16 y2_hi, y2_lo, y1_hi, y1_lo, x0, x1;
+ int32 L_tmp1;
+ int32 L_tmp2;
+ int16 *pt_sign = signal;
+
+ y2_hi = mem[0];
+ y2_lo = mem[1];
+ y1_hi = mem[2];
+ y1_lo = mem[3];
+ x0 = mem[4];
+ x1 = mem[5];
+
+
+ for (i = lg; i != 0; i--)
+ {
+
+ /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[0]*x[i-2] */
+ /* + a[0]*y[i-1] + a[1] * y[i-2]; */
+
+ L_tmp1 = fxp_mac_16by16(y1_lo, 16211, 8192L);
+ L_tmp1 = fxp_mac_16by16(y2_lo, -8021, L_tmp1);
+ L_tmp2 = fxp_mul_16by16(y1_hi, 32422);
+ L_tmp2 = fxp_mac_16by16(y2_hi, -16042, L_tmp2);
+
+ x2 = x1;
+ x1 = x0;
+ x0 = *pt_sign;
+ L_tmp2 = fxp_mac_16by16(x2, 8106, L_tmp2);
+ L_tmp2 = fxp_mac_16by16(x1, -16212, L_tmp2);
+ L_tmp2 = fxp_mac_16by16(x0, 8106, L_tmp2);
+
+
+ L_tmp1 = ((L_tmp1 >> 14) + L_tmp2) << 2;
+
+ y2_hi = y1_hi;
+ y2_lo = y1_lo;
+ y1_hi = (int16)(L_tmp1 >> 16);
+ y1_lo = (int16)((L_tmp1 - (y1_hi << 16)) >> 1);
+
+ /* coeff Q14 --> Q15 with saturation */
+ *(pt_sign++) = amr_wb_shl1_round(L_tmp1);
+
+ }
+
+
+ mem[0] = y2_hi;
+ mem[1] = y2_lo;
+ mem[2] = y1_hi;
+ mem[3] = y1_lo;
+ mem[4] = x0;
+ mem[5] = x1;
+
+}
+
diff --git a/media/libstagefright/codecs/amrwb/src/homing_amr_wb_dec.cpp b/media/libstagefright/codecs/amrwb/src/homing_amr_wb_dec.cpp
new file mode 100644
index 0000000..f032a08
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/homing_amr_wb_dec.cpp
@@ -0,0 +1,370 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: homing_amr_wb_dec.cpp
+
+ Date: 4/25/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+
+
+
+INPUT AND OUTPUT DEFINITIONS
+
+Input
+ int16 input_frame[], 16-bit input frame
+ int16 mode 16-bit mode
+ int16 nparms 16-bit number of parameters
+Returns
+ Int16 i number of leading zeros on x
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Performs the homing routines
+
+ int16 dhf_test(int16 input_frame[], int16 mode, int16 nparms)
+ int16 decoder_homing_frame_test(int16 input_frame[], int16 mode)
+ int16 decoder_homing_frame_test_first(int16 input_frame[], int16 mode)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "get_amr_wb_bits.h"
+#include "pvamrwbdecoder_api.h"
+#include "pvamrwbdecoder.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#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
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ int16 dhf_test(int16 input_frame[], int32 mode, int16 nparms);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+static const int16 prmnofsf[NUM_OF_SPMODES] =
+{
+ 63, 81, 100,
+ 108, 116, 128,
+ 136, 152, 156
+};
+
+
+static const int16 dfh_M7k[PRMN_7k] =
+{
+ 3168, 29954, 29213, 16121,
+ 64, 13440, 30624, 16430,
+ 19008
+};
+
+static const int16 dfh_M9k[PRMN_9k] =
+{
+ 3168, 31665, 9943, 9123,
+ 15599, 4358, 20248, 2048,
+ 17040, 27787, 16816, 13888
+};
+
+static const int16 dfh_M12k[PRMN_12k] =
+{
+ 3168, 31665, 9943, 9128,
+ 3647, 8129, 30930, 27926,
+ 18880, 12319, 496, 1042,
+ 4061, 20446, 25629, 28069,
+ 13948
+};
+
+static const int16 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 int16 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 int16 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 int16 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 int16 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 int16 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
+};
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+int16 dhf_test(int16 input_frame[], int32 mode, int16 nparms)
+{
+ int16 i, j, tmp, shift;
+ int16 param[DHF_PARMS_MAX];
+ int16 *prms;
+
+ /* overall table with the parameters of the
+ decoder homing frames for all modes */
+
+ const int16 *dhf[] =
+ {
+ dfh_M7k,
+ dfh_M9k,
+ dfh_M12k,
+ dfh_M14k,
+ dfh_M16k,
+ dfh_M18k,
+ dfh_M20k,
+ dfh_M23k,
+ dfh_M24k,
+ dfh_M24k
+ };
+
+ prms = input_frame;
+ j = 0;
+ i = 0;
+
+ if (mode != MRDTX)
+ {
+ if (mode != MODE_24k)
+ {
+ /* convert the received serial bits */
+ tmp = nparms - 15;
+ while (tmp > j)
+ {
+ param[i] = Serial_parm(15, &prms);
+ j += 15;
+ i++;
+ }
+ tmp = nparms - j;
+ param[i] = Serial_parm(tmp, &prms);
+ shift = 15 - tmp;
+ param[i] = shl_int16(param[i], shift);
+ }
+ else
+ {
+ /*If mode is 23.85Kbit/s, remove high band energy bits */
+ for (i = 0; i < 10; i++)
+ {
+ param[i] = Serial_parm(15, &prms);
+ }
+ param[10] = Serial_parm(15, &prms) & 0x61FF;
+
+ for (i = 11; i < 17; i++)
+ {
+ param[i] = Serial_parm(15, &prms);
+ }
+ param[17] = Serial_parm(15, &prms) & 0xE0FF;
+
+ for (i = 18; i < 24; i++)
+ {
+ param[i] = Serial_parm(15, &prms);
+ }
+ param[24] = Serial_parm(15, &prms) & 0x7F0F;
+
+ for (i = 25; i < 31; i++)
+ {
+ param[i] = Serial_parm(15, &prms);
+ }
+
+ tmp = Serial_parm(8, &prms);
+ param[31] = shl_int16(tmp, 7);
+ shift = 0;
+ }
+
+ /* check if the parameters matches the parameters of the corresponding decoder homing frame */
+ tmp = i;
+ j = 0;
+ for (i = 0; i < tmp; i++)
+ {
+ j = (param[i] ^ dhf[mode][i]);
+ if (j)
+ {
+ break;
+ }
+ }
+ tmp = 0x7fff;
+ tmp >>= shift;
+ tmp = shl_int16(tmp, shift);
+ tmp = (dhf[mode][i] & tmp);
+ tmp = (param[i] ^ tmp);
+ j = (int16)(j | tmp);
+
+ }
+ else
+ {
+ j = 1;
+ }
+
+ return (!j);
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+int16 pvDecoder_AmrWb_homing_frame_test(int16 input_frame[], int16 mode)
+{
+ /* perform test for COMPLETE parameter frame */
+ return dhf_test(input_frame, mode, AMR_WB_COMPRESSED[mode]);
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+int16 pvDecoder_AmrWb_homing_frame_test_first(int16 input_frame[], int16 mode)
+{
+ /* perform test for FIRST SUBFRAME of parameter frame ONLY */
+ return dhf_test(input_frame, mode, prmnofsf[mode]);
+}
diff --git a/media/libstagefright/codecs/amrwb/src/interpolate_isp.cpp b/media/libstagefright/codecs/amrwb/src/interpolate_isp.cpp
new file mode 100644
index 0000000..3ccebdb
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/interpolate_isp.cpp
@@ -0,0 +1,146 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: interpolate_isp.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 isp_old[], input : isps from past frame
+ int16 isp_new[], input : isps from present frame
+ const int16 frac[], input : fraction for 3 first subfr (Q15)
+ int16 Az[] output: LP coefficients in 4 subframes
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Interpolation of the LP parameters in 4 subframes
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define MP1 (M+1)
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void interpolate_isp(
+ int16 isp_old[], /* input : isps from past frame */
+ int16 isp_new[], /* input : isps from present frame */
+ const int16 frac[], /* input : fraction for 3 first subfr (Q15) */
+ int16 Az[] /* output: LP coefficients in 4 subframes */
+)
+{
+ int16 i, k, fac_old, fac_new;
+ int16 isp[M];
+ int32 L_tmp;
+
+ for (k = 0; k < 3; k++)
+ {
+ fac_new = frac[k];
+ fac_old = add_int16(sub_int16(32767, fac_new), 1); /* 1.0 - fac_new */
+
+ for (i = 0; i < M; i++)
+ {
+ L_tmp = mul_16by16_to_int32(isp_old[i], fac_old);
+ L_tmp = mac_16by16_to_int32(L_tmp, isp_new[i], fac_new);
+ isp[i] = amr_wb_round(L_tmp);
+ }
+ 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/amrwb/src/isf_extrapolation.cpp b/media/libstagefright/codecs/amrwb/src/isf_extrapolation.cpp
new file mode 100644
index 0000000..72d353a
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/isf_extrapolation.cpp
@@ -0,0 +1,274 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: isf_extrapolation.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 HfIsf[] (i/o) isf vector
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Conversion of 16th-order 12.8kHz ISF vector
+ into 20th-order 16kHz ISF vector
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+#include "pvamrwb_math_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define INV_LENGTH 2731 /* 1/12 */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void isf_extrapolation(int16 HfIsf[])
+{
+ int16 IsfDiff[M - 2];
+ int32 IsfCorr[3];
+ int32 L_tmp;
+ int16 coeff, mean, tmp, tmp2, tmp3;
+ int16 exp, exp2, hi, lo;
+ int16 i, MaxCorr;
+
+ HfIsf[M16k - 1] = HfIsf[M - 1];
+
+ /* Difference vector */
+ for (i = 1; i < (M - 1); i++)
+ {
+ IsfDiff[i - 1] = sub_int16(HfIsf[i], HfIsf[i - 1]);
+ }
+ L_tmp = 0;
+
+ /* Mean of difference vector */
+ for (i = 3; i < (M - 1); i++)
+ {
+ L_tmp = mac_16by16_to_int32(L_tmp, IsfDiff[i - 1], INV_LENGTH);
+
+ }
+ mean = amr_wb_round(L_tmp);
+
+ IsfCorr[0] = 0;
+
+ tmp = 0;
+ for (i = 0; i < (M - 2); i++)
+ {
+ if (IsfDiff[i] > tmp)
+ {
+ tmp = IsfDiff[i];
+ }
+ }
+ exp = norm_s(tmp);
+ for (i = 0; i < (M - 2); i++)
+ {
+ IsfDiff[i] = shl_int16(IsfDiff[i], exp);
+ }
+ mean = shl_int16(mean, exp);
+ for (i = 7; i < (M - 2); i++)
+ {
+ tmp2 = sub_int16(IsfDiff[i], mean);
+ tmp3 = sub_int16(IsfDiff[i - 2], mean);
+ L_tmp = mul_16by16_to_int32(tmp2, tmp3);
+ int32_to_dpf(L_tmp, &hi, &lo);
+ L_tmp = mpy_dpf_32(hi, lo, hi, lo);
+ IsfCorr[0] = add_int32(IsfCorr[0], L_tmp);
+ }
+ IsfCorr[1] = 0;
+ for (i = 7; i < (M - 2); i++)
+ {
+ tmp2 = sub_int16(IsfDiff[i], mean);
+ tmp3 = sub_int16(IsfDiff[i - 3], mean);
+ L_tmp = mul_16by16_to_int32(tmp2, tmp3);
+ int32_to_dpf(L_tmp, &hi, &lo);
+ L_tmp = mpy_dpf_32(hi, lo, hi, lo);
+ IsfCorr[1] = add_int32(IsfCorr[1], L_tmp);
+ }
+ IsfCorr[2] = 0;
+ for (i = 7; i < (M - 2); i++)
+ {
+ tmp2 = sub_int16(IsfDiff[i], mean);
+ tmp3 = sub_int16(IsfDiff[i - 4], mean);
+ L_tmp = mul_16by16_to_int32(tmp2, tmp3);
+ int32_to_dpf(L_tmp, &hi, &lo);
+ L_tmp = mpy_dpf_32(hi, lo, hi, lo);
+ IsfCorr[2] = add_int32(IsfCorr[2], L_tmp);
+ }
+
+ if (IsfCorr[0] > IsfCorr[1])
+ {
+ MaxCorr = 0;
+ }
+ else
+ {
+ MaxCorr = 1;
+ }
+
+
+ if (IsfCorr[2] > IsfCorr[MaxCorr])
+ {
+ MaxCorr = 2;
+ }
+
+ MaxCorr++; /* Maximum correlation of difference vector */
+
+ for (i = M - 1; i < (M16k - 1); i++)
+ {
+ tmp = sub_int16(HfIsf[i - 1 - MaxCorr], HfIsf[i - 2 - MaxCorr]);
+ HfIsf[i] = add_int16(HfIsf[i - 1], tmp);
+ }
+
+ /* tmp=7965+(HfIsf[2]-HfIsf[3]-HfIsf[4])/6; */
+ tmp = add_int16(HfIsf[4], HfIsf[3]);
+ tmp = sub_int16(HfIsf[2], tmp);
+ tmp = mult_int16(tmp, 5461);
+ tmp += 20390;
+
+
+ if (tmp > 19456)
+ { /* Maximum value of ISF should be at most 7600 Hz */
+ tmp = 19456;
+ }
+ tmp = sub_int16(tmp, HfIsf[M - 2]);
+ tmp2 = sub_int16(HfIsf[M16k - 2], HfIsf[M - 2]);
+
+ exp2 = norm_s(tmp2);
+ exp = norm_s(tmp);
+ exp--;
+ tmp <<= exp;
+ tmp2 <<= exp2;
+ coeff = div_16by16(tmp, tmp2); /* Coefficient for stretching the ISF vector */
+ exp = exp2 - exp;
+
+ for (i = M - 1; i < (M16k - 1); i++)
+ {
+ tmp = mult_int16(sub_int16(HfIsf[i], HfIsf[i - 1]), coeff);
+ IsfDiff[i - (M - 1)] = shl_int16(tmp, exp);
+ }
+
+ for (i = M; i < (M16k - 1); i++)
+ {
+ /* The difference between ISF(n) and ISF(n-2) should be at least 500 Hz */
+ tmp = IsfDiff[i - (M - 1)] + IsfDiff[i - M] - 1280;
+
+ if (tmp < 0)
+ {
+
+ if (IsfDiff[i - (M - 1)] > IsfDiff[i - M])
+ {
+ IsfDiff[i - M] = 1280 - IsfDiff[i - (M - 1)];
+ }
+ else
+ {
+ IsfDiff[i - (M - 1)] = 1280 - IsfDiff[i - M];
+ }
+ }
+ }
+
+ for (i = M - 1; i < (M16k - 1); i++)
+ {
+ HfIsf[i] = add_int16(HfIsf[i - 1], IsfDiff[i - (M - 1)]);
+ }
+
+ for (i = 0; i < (M16k - 1); i++)
+ {
+ HfIsf[i] = mult_int16(HfIsf[i], 26214); /* Scale the ISF vector correctly for 16000 kHz */
+ }
+
+ Isf_isp(HfIsf, HfIsf, M16k);
+
+ return;
+}
+
+
diff --git a/media/libstagefright/codecs/amrwb/src/isp_az.cpp b/media/libstagefright/codecs/amrwb/src/isp_az.cpp
new file mode 100644
index 0000000..40093f5
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/isp_az.cpp
@@ -0,0 +1,403 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: isp_az.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 isp[], (i) Q15 : Immittance spectral pairs
+ int16 a[], (o) Q12 : predictor coefficients (order=M)
+ int16 m, (i) : order
+ int16 adaptive_scaling (i) 0 : adaptive scaling disabled
+ 1 : adaptive scaling enabled
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Compute the LPC coefficients from isp (order=M)
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+#include "pvamrwb_math_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define NC (M/2)
+#define NC16k (M16k/2)
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void Get_isp_pol(int16 * isp, int32 * f, int16 n);
+ void Get_isp_pol_16kHz(int16 * isp, int32 * f, int16 n);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void Isp_Az(
+ int16 isp[], /* (i) Q15 : Immittance spectral pairs */
+ int16 a[], /* (o) Q12 : predictor coefficients (order=M) */
+ int16 m, /* (i) : order */
+ int16 adaptive_scaling /* (i) 0 : adaptive scaling disabled */
+ /* 1 : adaptive scaling enabled */
+)
+{
+ int16 i, j;
+ int32 f1[NC16k + 1], f2[NC16k];
+ int16 nc;
+ int32 t0;
+ int32 t1;
+ int16 q, q_sug;
+ int32 tmax;
+
+ nc = m >> 1;
+
+
+ if (nc > 8)
+ {
+ Get_isp_pol_16kHz(&isp[0], f1, nc);
+ for (i = 0; i <= nc; i++)
+ {
+ f1[i] = shl_int32(f1[i], 2);
+ }
+ Get_isp_pol_16kHz(&isp[1], f2, nc - 1);
+ for (i = 0; i <= nc - 1; i++)
+ {
+ f2[i] = shl_int32(f2[i], 2);
+ }
+ }
+ else
+ {
+ Get_isp_pol(&isp[0], f1, nc);
+ Get_isp_pol(&isp[1], f2, nc - 1);
+ }
+
+ /*
+ * Multiply F2(z) by (1 - z^-2)
+ */
+
+ for (i = nc - 1; i > 1; i--)
+ {
+ 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]); */
+
+ /* f2[i] *= (1.0 - isp[M-1]); */
+ t0 = f1[i];
+ t1 = f2[i];
+ t0 = fxp_mul32_by_16b(t0, isp[m - 1]) << 1;
+ t1 = fxp_mul32_by_16b(t1, isp[m - 1]) << 1;
+ f1[i] += t0;
+ f2[i] -= t1;
+
+ }
+
+ /*
+ * 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;
+ j = m - 1;
+ for (i = 1; i < nc; i++)
+ {
+ /* a[i] = 0.5*(f1[i] + f2[i]); */
+
+ t0 = add_int32(f1[i], f2[i]); /* f1[i] + f2[i] */
+ /* compute t1 = abs(t0) */
+ t1 = t0 - (t0 < 0);
+ t1 = t1 ^(t1 >> 31); /* t1 = t1 ^sign(t1) */
+
+ tmax |= t1;
+ /* from Q23 to Q12 and * 0.5 */
+ a[i] = (int16)((t0 >> 12) + ((t0 >> 11) & 1));
+
+
+ /* a[j] = 0.5*(f1[i] - f2[i]); */
+
+ t0 = sub_int32(f1[i], f2[i]); /* f1[i] - f2[i] */
+ /* compute t1 = abs(t0) */
+ t1 = t0 - (t0 < 0);
+ t1 = t1 ^(t1 >> 31); /* t1 = t1 ^sign(t1) */
+
+ tmax |= t1;
+
+ /* from Q23 to Q12 and * 0.5 */
+ a[j--] = (int16)((t0 >> 12) + ((t0 >> 11) & 1));
+
+ }
+
+ /* rescale data if overflow has occured and reprocess the loop */
+
+
+ if (adaptive_scaling == 1)
+ {
+ q = 4 - normalize_amr_wb(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 = add_int32(f1[i], f2[i]); /* f1[i] + f2[i] */
+ /* from Q23 to Q12 and * 0.5 */
+ a[i] = (int16)((t0 >> q_sug) + ((t0 >> (q_sug - 1)) & 1));
+
+
+ /* a[j] = 0.5*(f1[i] - f2[i]); */
+
+ t0 = sub_int32(f1[i], f2[i]); /* f1[i] - f2[i] */
+ /* from Q23 to Q12 and * 0.5 */
+ a[j] = (int16)((t0 >> q_sug) + ((t0 >> (q_sug - 1)) & 1));
+
+ }
+ a[0] >>= q;
+ }
+ else
+ {
+ q_sug = 12;
+ q = 0;
+ }
+
+ /* a[NC] = 0.5*f1[NC]*(1.0 + isp[M-1]); */
+
+
+ t0 = (int32)(((int64)f1[nc] * isp[m - 1]) >> 16) << 1;
+
+
+ t0 = add_int32(f1[nc], t0);
+
+ /* from Q23 to Q12 and * 0.5 */
+ a[nc] = (int16)((t0 >> q_sug) + ((t0 >> (q_sug - 1)) & 1));
+ a[m] = shr_rnd(isp[m - 1], (3 + q)); /* from Q15 to Q12 */
+
+ /* a[m] = isp[m-1]; */
+
+
+ return;
+}
+
+
+
+/*
+Get_isp_pol
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ 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)
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ 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.
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void Get_isp_pol(int16 * isp, int32 * f, int16 n)
+{
+ int16 i, j;
+ int32 t0;
+
+
+ /* All computation in Q23 */
+
+ f[0] = 0x00800000; /* f[0] = 1.0; in Q23 */
+ f[1] = -isp[0] << 9; /* 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++)
+ {
+
+ t0 = fxp_mul32_by_16b(f[-1], *isp);
+ t0 = shl_int32(t0, 2);
+
+ *f -= t0; /* *f -= t0 */
+ *(f) += f[-2]; /* *f += f[-2] */
+ f--;
+
+
+ }
+ *f -= *isp << 9;
+
+ f += i; /* Advance f pointer */
+ isp += 2; /* Advance isp pointer */
+ }
+}
+
+void Get_isp_pol_16kHz(int16 * isp, int32 * f, int16 n)
+{
+ int16 i, j;
+ int32 t0;
+
+ /* All computation in Q23 */
+
+ f[0] = 0x00200000; /* f[0] = 0.25; in Q23 */
+
+ f[1] = -isp[0] << 7; /* f[1] = -0.5*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--)
+ {
+ t0 = fxp_mul32_by_16b(f[-1], *isp);
+ t0 = shl_int32(t0, 2);
+
+ *f -= t0; /* *f -= t0 */
+ *f += f[-2]; /* *f += f[-2] */
+ }
+ *f -= *isp << 7;
+ f += i; /* Advance f pointer */
+ isp += 2; /* Advance isp pointer */
+ }
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrwb/src/isp_isf.cpp b/media/libstagefright/codecs/amrwb/src/isp_isf.cpp
new file mode 100644
index 0000000..0552733
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/isp_isf.cpp
@@ -0,0 +1,175 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: isp_isf.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 isf[], (i) Q15 : isf[m] normalized (range: 0.0<=val<=0.5)
+ int16 isp[], (o) Q15 : isp[m] (range: -1<=val<1)
+ int16 m (i) : LPC order
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Isf_isp Transformation isf to isp
+
+ The transformation from isf[i] to isp[i] is
+ approximated by a look-up table and interpolation.
+
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/* Look-up table for transformations */
+
+/* table of cos(x) in Q15 */
+
+static const int16 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
+};
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void Isf_isp(
+ int16 isf[], /* (i) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */
+ int16 isp[], /* (o) Q15 : isp[m] (range: -1<=val<1) */
+ int16 m /* (i) : LPC order */
+)
+{
+ int16 i, ind, offset;
+ int32 L_tmp;
+
+ for (i = 0; i < m - 1; i++)
+ {
+ isp[i] = isf[i];
+ }
+ isp[m - 1] = shl_int16(isf[m - 1], 1);
+
+ for (i = 0; i < m; i++)
+ {
+ ind = isp[i] >> 7; /* ind = b7-b15 of isf[i] */
+ offset = (isp[i] & 0x007f); /* offset = b0-b6 of isf[i] */
+
+ /* isp[i] = table[ind]+ ((table[ind+1]-table[ind])*offset) / 128 */
+
+ L_tmp = mul_16by16_to_int32(table[ind + 1] - table[ind], offset);
+ isp[i] = add_int16(table[ind], (int16)(L_tmp >> 8));
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrwb/src/lagconceal.cpp b/media/libstagefright/codecs/amrwb/src/lagconceal.cpp
new file mode 100644
index 0000000..c699808
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/lagconceal.cpp
@@ -0,0 +1,364 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: lagconceal.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 gain_hist[], (i) : Gain history
+ int16 lag_hist[], (i) : Subframe size
+ int16 * T0, (i/o): current lag
+ int16 * old_T0, (i/o): previous lag
+ int16 * seed,
+ int16 unusable_frame
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Concealment of LTP lags during bad frames
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define L_LTPHIST 5
+#define ONE_PER_3 10923
+#define ONE_PER_LTPHIST 6554
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+void insertion_sort(int16 array[], int16 n);
+void insert(int16 array[], int16 num, int16 x);
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void Init_Lagconc(int16 lag_hist[])
+{
+ int16 i;
+
+ for (i = 0; i < L_LTPHIST; i++)
+ {
+ lag_hist[i] = 64;
+ }
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void lagconceal(
+ int16 gain_hist[], /* (i) : Gain history */
+ int16 lag_hist[], /* (i) : Subframe size */
+ int16 * T0,
+ int16 * old_T0,
+ int16 * seed,
+ int16 unusable_frame
+)
+{
+ int16 maxLag, minLag, lastLag, lagDif, meanLag = 0;
+ int16 lag_hist2[L_LTPHIST] = {0};
+ int16 i, tmp, tmp2;
+ int16 minGain, lastGain, secLastGain;
+ int16 D, D2;
+
+ /* Is lag index such that it can be aplied directly or does it has to be subtituted */
+
+ lastGain = gain_hist[4];
+ secLastGain = gain_hist[3];
+
+ lastLag = lag_hist[0];
+
+ /******* SMALLEST history lag *******/
+ minLag = lag_hist[0];
+ /******* BIGGEST history lag *******/
+ maxLag = lag_hist[0];
+ for (i = 1; i < L_LTPHIST; i++)
+ {
+ if (lag_hist[i] < minLag)
+ {
+ minLag = lag_hist[i];
+ }
+ if (lag_hist[i] > maxLag)
+ {
+ maxLag = lag_hist[i];
+ }
+ }
+ /***********SMALLEST history gain***********/
+ minGain = gain_hist[0];
+ for (i = 1; i < L_LTPHIST; i++)
+ {
+
+ if (gain_hist[i] < minGain)
+ {
+ minGain = gain_hist[i];
+ }
+ }
+ /***Difference between MAX and MIN lag**/
+ lagDif = sub_int16(maxLag, minLag);
+
+
+ if (unusable_frame != 0)
+ {
+ /* LTP-lag for RX_SPEECH_LOST */
+ /**********Recognition of the LTP-history*********/
+
+ if ((minGain > 8192) && (lagDif < 10))
+ {
+ *T0 = *old_T0;
+ }
+ else if (lastGain > 8192 && secLastGain > 8192)
+ {
+ *T0 = lag_hist[0];
+ }
+ else
+ {
+ /********SORT************/
+ /* The sorting of the lag history */
+ for (i = 0; i < L_LTPHIST; i++)
+ {
+ lag_hist2[i] = lag_hist[i];
+ }
+ insertion_sort(lag_hist2, 5);
+
+ /* Lag is weighted towards bigger lags */
+ /* and random variation is added */
+ lagDif = sub_int16(lag_hist2[4], lag_hist2[2]);
+
+
+ if (lagDif > 40)
+ {
+ lagDif = 40;
+ }
+
+ D = noise_gen_amrwb(seed); /* D={-1, ...,1} */
+ /* D2={-lagDif/2..lagDif/2} */
+ tmp = lagDif >> 1;
+ D2 = mult_int16(tmp, D);
+ tmp = add_int16(add_int16(lag_hist2[2], lag_hist2[3]), lag_hist2[4]);
+ *T0 = add_int16(mult_int16(tmp, ONE_PER_3), D2);
+ }
+ /* New lag is not allowed to be bigger or smaller than last lag values */
+
+ if (*T0 > maxLag)
+ {
+ *T0 = maxLag;
+ }
+
+ if (*T0 < minLag)
+ {
+ *T0 = minLag;
+ }
+ }
+ else
+ {
+ /* LTP-lag for RX_BAD_FRAME */
+
+ /***********MEAN lag**************/
+ meanLag = 0;
+ for (i = 0; i < L_LTPHIST; i++)
+ {
+ meanLag = add_int16(meanLag, lag_hist[i]);
+ }
+ meanLag = mult_int16(meanLag, ONE_PER_LTPHIST);
+
+ tmp = *T0 - maxLag;
+ tmp2 = *T0 - lastLag;
+
+ if ((lagDif < 10) && (*T0 > (minLag - 5)) && (tmp < 5))
+ {
+ *T0 = *T0;
+ }
+ else if ((lastGain > 8192) && (secLastGain > 8192) && ((tmp2 + 10) > 0 && tmp2 < 10))
+ {
+ *T0 = *T0;
+ }
+ else if ((minGain < 6554) && (lastGain == minGain) && (*T0 > minLag && *T0 < maxLag))
+ {
+ *T0 = *T0;
+ }
+ else if ((lagDif < 70) && (*T0 > minLag) && (*T0 < maxLag))
+ {
+ *T0 = *T0;
+ }
+ else if ((*T0 > meanLag) && (*T0 < maxLag))
+ {
+ *T0 = *T0;
+ }
+ else
+ {
+
+
+ if ((minGain > 8192) & (lagDif < 10))
+ {
+ *T0 = lag_hist[0];
+ }
+ else if ((lastGain > 8192) && (secLastGain > 8192))
+ {
+ *T0 = lag_hist[0];
+ }
+ else
+ {
+ /********SORT************/
+ /* The sorting of the lag history */
+ for (i = 0; i < L_LTPHIST; i++)
+ {
+ lag_hist2[i] = lag_hist[i];
+ }
+ insertion_sort(lag_hist2, 5);
+
+ /* Lag is weighted towards bigger lags */
+ /* and random variation is added */
+ lagDif = sub_int16(lag_hist2[4], lag_hist2[2]);
+
+ if (lagDif > 40)
+ {
+ lagDif = 40;
+ }
+
+ D = noise_gen_amrwb(seed); /* D={-1,.., 1} */
+ /* D2={-lagDif/2..lagDif/2} */
+ tmp = lagDif >> 1;
+ D2 = mult_int16(tmp, D);
+ tmp = add_int16(add_int16(lag_hist2[2], lag_hist2[3]), lag_hist2[4]);
+ *T0 = add_int16(mult_int16(tmp, ONE_PER_3), D2);
+ }
+ /* New lag is not allowed to be bigger or smaller than last lag values */
+
+ if (*T0 > maxLag)
+ {
+ *T0 = maxLag;
+ }
+
+ if (*T0 < minLag)
+ {
+ *T0 = minLag;
+ }
+ }
+ }
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void insertion_sort(int16 array[], int16 n)
+{
+ int16 i;
+
+ for (i = 0; i < n; i++)
+ {
+ insert(array, i, array[i]);
+ }
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void insert(int16 array[], int16 n, int16 x)
+{
+ int16 i;
+
+ for (i = (n - 1); i >= 0; i--)
+ {
+
+ if (x < array[i])
+ {
+ array[i + 1] = array[i];
+ }
+ else
+ {
+ break;
+ }
+ }
+ array[i + 1] = x;
+}
diff --git a/media/libstagefright/codecs/amrwb/src/low_pass_filt_7k.cpp b/media/libstagefright/codecs/amrwb/src/low_pass_filt_7k.cpp
new file mode 100644
index 0000000..ec1d6e0
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/low_pass_filt_7k.cpp
@@ -0,0 +1,220 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: low_pass_filt_7k.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 signal[], input signal / output is divided by 16
+ int16 lg, lenght of signal
+ int16 mem[] in/out: memory (size=30)
+ int16 x[] scratch mem ( size= 60)
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ 15th order high pass 7kHz FIR filter
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define L_FIR 30
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const int16 fir_7k[L_FIR+1] =
+{
+ -21, 47, -89, 146, -203,
+ 229, -177, 0, 335, -839,
+ 1485, -2211, 2931, -3542, 3953,
+ 28682, 3953, -3542, 2931, -2211,
+ 1485, -839, 335, 0, -177,
+ 229, -203, 146, -89, 47,
+ -21
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void low_pass_filt_7k_init(int16 mem[]) /* mem[30] */
+{
+ pv_memset((void *)mem, 0, (L_FIR)*sizeof(*mem));
+
+ return;
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void low_pass_filt_7k(
+ int16 signal[], /* input: signal */
+ int16 lg, /* input: length of input */
+ int16 mem[], /* in/out: memory (size=30) */
+ int16 x[]
+)
+{
+ int16 i, j;
+ int32 L_tmp1;
+ int32 L_tmp2;
+ int32 L_tmp3;
+ int32 L_tmp4;
+
+ pv_memcpy((void *)x, (void *)mem, (L_FIR)*sizeof(*x));
+
+ for (i = 0; i < lg >> 2; i++)
+ {
+ x[(i<<2) + L_FIR ] = signal[(i<<2)];
+ x[(i<<2) + L_FIR + 1] = signal[(i<<2)+1];
+ x[(i<<2) + L_FIR + 2] = signal[(i<<2)+2];
+ x[(i<<2) + L_FIR + 3] = signal[(i<<2)+3];
+
+ L_tmp1 = fxp_mac_16by16(x[(i<<2)] + signal[(i<<2)], fir_7k[0], 0x00004000);
+ L_tmp2 = fxp_mac_16by16(x[(i<<2)+1] + signal[(i<<2)+1], fir_7k[0], 0x00004000);
+ L_tmp3 = fxp_mac_16by16(x[(i<<2)+2] + signal[(i<<2)+2], fir_7k[0], 0x00004000);
+ L_tmp4 = fxp_mac_16by16(x[(i<<2)+3] + signal[(i<<2)+3], fir_7k[0], 0x00004000);
+
+ for (j = 1; j < L_FIR - 1; j += 4)
+ {
+
+
+ int16 tmp1 = x[(i<<2)+j ];
+ int16 tmp2 = x[(i<<2)+j+1];
+ int16 tmp3 = x[(i<<2)+j+2];
+
+ L_tmp1 = fxp_mac_16by16(tmp1, fir_7k[j ], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(tmp2, fir_7k[j ], L_tmp2);
+ L_tmp1 = fxp_mac_16by16(tmp2, fir_7k[j+1], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(tmp3, fir_7k[j+1], L_tmp2);
+ L_tmp3 = fxp_mac_16by16(tmp3, fir_7k[j ], L_tmp3);
+ L_tmp1 = fxp_mac_16by16(tmp3, fir_7k[j+2], L_tmp1);
+
+ tmp1 = x[(i<<2)+j+3];
+ tmp2 = x[(i<<2)+j+4];
+
+ L_tmp2 = fxp_mac_16by16(tmp1, fir_7k[j+2], L_tmp2);
+ L_tmp4 = fxp_mac_16by16(tmp1, fir_7k[j ], L_tmp4);
+ L_tmp3 = fxp_mac_16by16(tmp1, fir_7k[j+1], L_tmp3);
+ L_tmp1 = fxp_mac_16by16(tmp1, fir_7k[j+3], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(tmp2, fir_7k[j+3], L_tmp2);
+ L_tmp4 = fxp_mac_16by16(tmp2, fir_7k[j+1], L_tmp4);
+ L_tmp3 = fxp_mac_16by16(tmp2, fir_7k[j+2], L_tmp3);
+
+ tmp1 = x[(i<<2)+j+5];
+ tmp2 = x[(i<<2)+j+6];
+
+ L_tmp4 = fxp_mac_16by16(tmp1, fir_7k[j+2], L_tmp4);
+ L_tmp3 = fxp_mac_16by16(tmp1, fir_7k[j+3], L_tmp3);
+ L_tmp4 = fxp_mac_16by16(tmp2, fir_7k[j+3], L_tmp4);
+
+ }
+
+ L_tmp1 = fxp_mac_16by16(x[(i<<2)+j ], fir_7k[j ], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(x[(i<<2)+j+1], fir_7k[j ], L_tmp2);
+ L_tmp3 = fxp_mac_16by16(x[(i<<2)+j+2], fir_7k[j ], L_tmp3);
+ L_tmp4 = fxp_mac_16by16(x[(i<<2)+j+3], fir_7k[j ], L_tmp4);
+
+ signal[(i<<2)] = (int16)(L_tmp1 >> 15);
+ signal[(i<<2)+1] = (int16)(L_tmp2 >> 15);
+ signal[(i<<2)+2] = (int16)(L_tmp3 >> 15);
+ signal[(i<<2)+3] = (int16)(L_tmp4 >> 15);
+
+ }
+
+ pv_memcpy((void *)mem, (void *)(x + lg), (L_FIR)*sizeof(*mem));
+
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrwb/src/median5.cpp b/media/libstagefright/codecs/amrwb/src/median5.cpp
new file mode 100644
index 0000000..b922de5
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/median5.cpp
@@ -0,0 +1,180 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: median5.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ INPUT
+ X[-2:2] 16-bit integers.
+
+ RETURN VALUE
+ The median of {X[-2], X[-1],..., X[2]}.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Returns the median of the set {X[-2], X[-1],..., X[2]},
+ whose elements are 16-bit integers.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_acelp.h"
+#include "pvamrwb_math_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+int16 median5(int16 x[])
+{
+ int16 x1, x2, x3, x4, x5;
+ int16 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);
+}
+
+
diff --git a/media/libstagefright/codecs/amrwb/src/mime_io.cpp b/media/libstagefright/codecs/amrwb/src/mime_io.cpp
new file mode 100644
index 0000000..e1966c6
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/mime_io.cpp
@@ -0,0 +1,729 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+ Pathname: ./src/mime_io.cpp
+
+ Date: 05/07/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ [input_variable_name] = [description of the input to module, its type
+ definition, and length (when applicable)]
+
+ Local Stores/Buffers/Pointers Needed:
+ [local_store_name] = [description of the local store, its type
+ definition, and length (when applicable)]
+ [local_buffer_name] = [description of the local buffer, its type
+ definition, and length (when applicable)]
+ [local_ptr_name] = [description of the local pointer, its type
+ definition, and length (when applicable)]
+
+ Global Stores/Buffers/Pointers Needed:
+ [global_store_name] = [description of the global store, its type
+ definition, and length (when applicable)]
+ [global_buffer_name] = [description of the global buffer, its type
+ definition, and length (when applicable)]
+ [global_ptr_name] = [description of the global pointer, its type
+ definition, and length (when applicable)]
+
+ Outputs:
+ [return_variable_name] = [description of data/pointer returned
+ by module, its type definition, and length
+ (when applicable)]
+
+ Pointers and Buffers Modified:
+ [variable_bfr_ptr] points to the [describe where the
+ variable_bfr_ptr points to, its type definition, and length
+ (when applicable)]
+ [variable_bfr] contents are [describe the new contents of
+ variable_bfr]
+
+ Local Stores Modified:
+ [local_store_name] = [describe new contents, its type
+ definition, and length (when applicable)]
+
+ Global Stores Modified:
+ [global_store_name] = [describe new contents, its type
+ definition, and length (when applicable)]
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ [Describe what the module does by using the variable names
+ listed in the Input and Output Definitions Section above.]
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ [List requirements to be satisfied by this module.]
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [List all references used in designing this module.]
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ ------------------------------------------------------------------------------
+ RESOURCES USED
+
+ STACK USAGE:
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES:
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_api.h"
+#include "pvamrwbdecoder.h"
+#include "pvamrwbdecoder_mem_funcs.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "dtx.h"
+#include "mime_io.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define MRSID 9
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+const uint8 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 */
+const int16 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 */
+const int16 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 */
+const int16 unused_size[16] = {4, 7, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0};
+
+/* sorting tables for all modes */
+
+const int16 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
+};
+
+const int16 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
+};
+
+const int16 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
+};
+
+const int16 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
+};
+
+const int16 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
+};
+
+const int16 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
+};
+
+const int16 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
+};
+
+const int16 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
+};
+
+const int16 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
+};
+
+const int16 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
+};
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void mime_unsorting(uint8 unsorted_bits[],
+ int16 sorted_bits_into_int16[],
+ int16 * frame_type,
+ int16 * mode,
+ uint8 quality,
+ RX_State_wb *st)
+{
+
+ int16 i;
+ int16 j;
+ uint8 temp = 0;
+ uint8 *unsorted_bits_ptr = (uint8*)unsorted_bits;
+
+ /* pointer table for bit sorting tables */
+ const int16 *AmrWbSortingTables[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
+ };
+
+ const int16 * pt_AmrWbSortingTables = AmrWbSortingTables[*mode];
+
+ /* clear compressed speech bit buffer */
+ pv_memset(sorted_bits_into_int16,
+ 0,
+ unpacked_size[*mode]*sizeof(*sorted_bits_into_int16));
+
+ /* unpack and unsort speech or SID bits */
+
+
+ for (i = unpacked_size[*mode] >> 3; i != 0; i--)
+ {
+ temp = *(unsorted_bits_ptr++);
+
+ for (j = 2; j != 0; j--)
+ {
+ switch (temp & 0xf0)
+ {
+ case 0xf0:
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ break;
+ case 0xe0:
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ pt_AmrWbSortingTables++;
+ break;
+ case 0xd0:
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ pt_AmrWbSortingTables++;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ break;
+ case 0xc0:
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ pt_AmrWbSortingTables += 2;
+ break;
+ case 0xb0:
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ pt_AmrWbSortingTables++;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ break;
+ case 0xa0:
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ pt_AmrWbSortingTables++;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ pt_AmrWbSortingTables++;
+ break;
+ case 0x90:
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ pt_AmrWbSortingTables += 2;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ break;
+ case 0x80:
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ pt_AmrWbSortingTables += 3;
+ break;
+ case 0x70:
+ pt_AmrWbSortingTables++;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ break;
+ case 0x60:
+ pt_AmrWbSortingTables++;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ pt_AmrWbSortingTables++;
+ break;
+ case 0x50:
+ pt_AmrWbSortingTables++;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ pt_AmrWbSortingTables++;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ break;
+ case 0x40:
+ pt_AmrWbSortingTables++;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ pt_AmrWbSortingTables += 2;
+ break;
+ case 0x30:
+ pt_AmrWbSortingTables += 2;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ break;
+ case 0x20:
+ pt_AmrWbSortingTables += 2;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ pt_AmrWbSortingTables++;
+ break;
+ case 0x10:
+ pt_AmrWbSortingTables += 3;
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ break;
+ default:
+ pt_AmrWbSortingTables += 4;
+ break;
+ }
+ temp <<= 4;
+ }
+ }
+
+ if (unpacked_size[*mode] % 4)
+ {
+ temp <<= 1;
+
+ if (temp & 0x80)
+ {
+ sorted_bits_into_int16[*(pt_AmrWbSortingTables++)] = BIT_1;
+ }
+ }
+
+ /* set frame type */
+ switch (*mode)
+ {
+ case MODE_7k:
+ case MODE_9k:
+ case MODE_12k:
+ case MODE_14k:
+ case MODE_16k:
+ case MODE_18k:
+ case MODE_20k:
+ case MODE_23k:
+ case MODE_24k:
+ if (quality)
+ {
+ *frame_type = RX_SPEECH_GOOD;
+ }
+ else
+ {
+ *frame_type = RX_SPEECH_BAD;
+ }
+ break;
+
+ case MRSID:
+ if (quality)
+ {
+ if (temp & 0x80)
+ {
+ *frame_type = RX_SID_UPDATE;
+ }
+ else
+ {
+ *frame_type = RX_SID_FIRST;
+ }
+ }
+ else
+ {
+ *frame_type = RX_SID_BAD;
+ }
+
+ /* set mode index */
+ *mode = st->prev_mode;
+ break;
+ case 14: /* SPEECH_LOST */
+ *frame_type = RX_SPEECH_LOST;
+ *mode = st->prev_mode;
+ break;
+ case 15: /* NO_DATA */
+ *frame_type = RX_NO_DATA;
+ *mode = st->prev_mode;
+ break;
+ default: /* replace frame with unused mode index by NO_DATA frame */
+ *frame_type = RX_NO_DATA;
+ *mode = st->prev_mode;
+ break;
+ }
+
+ st->prev_mode = *mode;
+
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwb/src/mime_io.h b/media/libstagefright/codecs/amrwb/src/mime_io.h
new file mode 100644
index 0000000..3be1d9c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/mime_io.h
@@ -0,0 +1,124 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./cpp/include/mime_io.h
+
+ Date: 01/04/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef MIME_IO_H
+#define MIME_IO_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+----------------------------------------------------------------------------*/
+
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+----------------------------------------------------------------------------*/
+extern const uint8 toc_byte[16];
+
+/* number of speech bits for all modes */
+extern const int16 unpacked_size[16];
+
+/* size of packed frame for each mode, excluding TOC byte */
+extern const int16 packed_size[16];
+
+/* number of unused speech bits in packed format for each mode */
+extern const int16 unused_size[16];
+
+/* sorting tables for all modes */
+
+extern const int16 sort_660[132];
+
+extern const int16 sort_885[177];
+
+extern const int16 sort_1265[253];
+
+extern const int16 sort_1425[285];
+
+extern const int16 sort_1585[317];
+
+extern const int16 sort_1825[365];
+
+extern const int16 sort_1985[397];
+
+extern const int16 sort_2305[461];
+
+extern const int16 sort_2385[477];
+
+extern const int16 sort_SID[35];
+
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+#endif /* MIME_IO_H */
diff --git a/media/libstagefright/codecs/amrwb/src/noise_gen_amrwb.cpp b/media/libstagefright/codecs/amrwb/src/noise_gen_amrwb.cpp
new file mode 100644
index 0000000..2c1059f
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/noise_gen_amrwb.cpp
@@ -0,0 +1,118 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: noise_gen_amrwb.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 * seed seed for the random ng
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Signed 16 bits random generator
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+int16 noise_gen_amrwb(int16 * seed)
+{
+ /* int16 seed = 21845; */
+ *seed = (int16)fxp_mac_16by16(*seed, 31821, 13849L);
+
+ return (*seed);
+}
diff --git a/media/libstagefright/codecs/amrwb/src/normalize_amr_wb.cpp b/media/libstagefright/codecs/amrwb/src/normalize_amr_wb.cpp
new file mode 100644
index 0000000..0325311
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/normalize_amr_wb.cpp
@@ -0,0 +1,183 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: normalize_amr_wb.cpp
+
+ Date: 12/10/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+ Int32 x 32-bit integer non-zero input
+Returns
+ Int16 i number of leading zeros on x
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Returns number of leading zeros on the non-zero input
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "normalize_amr_wb.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+#if defined(PV_ARM_V5)
+#elif defined(PV_ARM_GCC_V5)
+
+/* function is inlined in header file */
+
+
+#else
+
+int16 normalize_amr_wb(int32 x)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int16 i;
+
+
+ if (x > 0x0FFFFFFF)
+ {
+ i = 0; /* most likely case */
+ }
+ else if (x > 0x00FFFFFF)
+ {
+ i = 3; /* second most likely case */
+ }
+ else if (x > 0x0000FFFF)
+ {
+ i = x > 0x000FFFFF ? 7 : 11;
+ }
+ else
+ {
+ if (x > 0x000000FF)
+ {
+ i = x > 0x00000FFF ? 15 : 19;
+ }
+ else
+ {
+ i = x > 0x0000000F ? 23 : 27;
+ }
+ }
+
+
+ x <<= i;
+
+ switch (x & 0x78000000)
+ {
+ case 0x08000000:
+ i += 3;
+ break;
+
+ case 0x18000000:
+ case 0x10000000:
+ i += 2;
+ break;
+ case 0x28000000:
+ case 0x20000000:
+ case 0x38000000:
+ case 0x30000000:
+ i++;
+
+ default:
+ ;
+ }
+
+ return i;
+
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/amrwb/src/normalize_amr_wb.h b/media/libstagefright/codecs/amrwb/src/normalize_amr_wb.h
new file mode 100644
index 0000000..e4c80ef
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/normalize_amr_wb.h
@@ -0,0 +1,120 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./c/include/normalize_amr_wb.h
+
+ Date: 12/10/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef NORMALIZE_AMR_WB_H
+#define NORMALIZE_AMR_WB_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES AND SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+#if defined(PV_ARM_V5)
+
+__inline int16 normalize_amr_wb(int32 x)
+{
+ int32 y;
+ __asm
+ {
+ clz y, x;
+ sub y, y, #1
+ }
+ return (y);
+}
+
+
+#elif defined(PV_ARM_GCC_V5)
+
+
+__inline int16 normalize_amr_wb(int32 x)
+{
+ register int32 y;
+ register int32 ra = x;
+
+
+ asm volatile(
+ "clz %0, %1\n\t"
+ "sub %0, %0, #1"
+ : "=&r*i"(y)
+ : "r"(ra));
+ return (y);
+
+}
+
+#else
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ int16 normalize_amr_wb(int32 x);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+#endif /* PV_NORMALIZE_H */
diff --git a/media/libstagefright/codecs/amrwb/src/oversamp_12k8_to_16k.cpp b/media/libstagefright/codecs/amrwb/src/oversamp_12k8_to_16k.cpp
new file mode 100644
index 0000000..806851e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/oversamp_12k8_to_16k.cpp
@@ -0,0 +1,342 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: oversamp_12k8_to_16k.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 signal[], input signal / output is divided by 16
+ int16 lg, lenght of signal
+ int16 mem[] in/out: memory (size=30)
+ int16 x[] scratch mem ( size= 60)
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Oversamp_16k : oversampling from 12.8kHz to 16kHz.
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_acelp.h"
+#include "pvamrwbdecoder_cnst.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define FAC4 4
+#define FAC5 5
+#define INV_FAC5 6554 /* 1/5 in Q15 */
+#define DOWN_FAC 26215 /* 4/5 in Q15 */
+#define UP_FAC 20480 /* 5/4 in Q14 */
+#define NB_COEF_DOWN 15
+#define NB_COEF_UP 12
+#define N_LOOP_COEF_UP 4
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ /* Local functions */
+
+ void AmrWbUp_samp(
+ int16 * sig_d, /* input: signal to oversampling */
+ int16 * sig_u, /* output: oversampled signal */
+ int16 L_frame /* input: length of output */
+ );
+
+
+ int16 AmrWbInterpol( /* return result of interpolation */
+ int16 * x, /* input vector */
+ const int16 * fir, /* filter coefficient */
+ int16 nb_coef /* number of coefficients */
+ );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+
+/* 1/5 resolution interpolation filter (in Q14) */
+/* -1.5dB @ 6kHz, -6dB @ 6.4kHz, -10dB @ 6.6kHz,
+ -20dB @ 6.9kHz, -25dB @ 7kHz, -55dB @ 8kHz */
+
+
+const int16 fir_up[4][24] =
+{
+
+ {
+ -1, 12, -33, 68, -119, 191,
+ -291, 430, -634, 963, -1616, 3792,
+ 15317, -2496, 1288, -809, 542, -369,
+ 247, -160, 96, -52, 23, -6,
+ },
+ {
+ -4, 24, -62, 124, -213, 338,
+ -510, 752, -1111, 1708, -2974, 8219,
+ 12368, -3432, 1881, -1204, 812, -552,
+ 368, -235, 139, -73, 30, -7,
+ },
+ {
+ -7, 30, -73, 139, -235, 368,
+ -552, 812, -1204, 1881, -3432, 12368,
+ 8219, -2974, 1708, -1111, 752, -510,
+ 338, -213, 124, -62, 24, -4,
+ },
+ {
+ -6, 23, -52, 96, -160, 247,
+ -369, 542, -809, 1288, -2496, 15317,
+ 3792, -1616, 963, -634, 430, -291,
+ 191, -119, 68, -33, 12, -1,
+ }
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+/* output: memory (2*NB_COEF_UP) set to zeros */
+void oversamp_12k8_to_16k_init(int16 mem[])
+{
+ pv_memset((void *)mem, 0, (2*NB_COEF_UP)*sizeof(*mem));
+
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void oversamp_12k8_to_16k(
+ int16 sig12k8[], /* input: signal to oversampling */
+ int16 lg, /* input: length of input */
+ int16 sig16k[], /* output: oversampled signal */
+ int16 mem[], /* in/out: memory (2*NB_COEF_UP) */
+ int16 signal[]
+)
+{
+ int16 lg_up;
+
+ pv_memcpy((void *)signal,
+ (void *)mem,
+ (2*NB_COEF_UP)*sizeof(*mem));
+
+ pv_memcpy((void *)(signal + (2*NB_COEF_UP)),
+ (void *)sig12k8,
+ lg*sizeof(*sig12k8));
+
+ lg_up = lg + (lg >> 2); /* 5/4 of lg */
+
+ AmrWbUp_samp(signal + NB_COEF_UP, sig16k, lg_up);
+
+ pv_memcpy((void *)mem,
+ (void *)(signal + lg),
+ (2*NB_COEF_UP)*sizeof(*signal));
+
+ return;
+}
+
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void AmrWbUp_samp(
+ int16 * sig_d, /* input: signal to oversampling */
+ int16 * sig_u, /* output: oversampled signal */
+ int16 L_frame /* input: length of output */
+)
+{
+
+ int32 i;
+ int16 frac, j;
+ int16 * pt_sig_u = sig_u;
+
+ frac = 1;
+ for (j = 0; j < L_frame; j++)
+ {
+ i = ((int32)j * INV_FAC5) >> 13; /* integer part = pos * 1/5 */
+
+ frac--;
+ if (frac)
+ {
+ *(pt_sig_u++) = AmrWbInterpol(&sig_d[i],
+ fir_up[(FAC5-1) - frac],
+ N_LOOP_COEF_UP);
+ }
+ else
+ {
+ *(pt_sig_u++) = sig_d[i+12 - NB_COEF_UP ];
+ frac = FAC5;
+ }
+ }
+
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+/* Fractional interpolation of signal at position (frac/resol) */
+
+
+int16 AmrWbInterpol( /* return result of interpolation */
+ int16 * x, /* input vector */
+ const int16 *fir, /* filter coefficient */
+ int16 nb_coef /* number of coefficients */
+)
+{
+ int32 L_sum;
+ const int16 *pt_fir = fir;
+
+ int16 tmp1, tmp2, tmp3, tmp4;
+ int16 *pt_x = x - nb_coef - (nb_coef << 1) + 1;
+
+
+ tmp1 = *(pt_x++);
+ tmp2 = *(pt_x++);
+ tmp3 = *(pt_x++);
+ tmp4 = *(pt_x++);
+ L_sum = fxp_mac_16by16(tmp1, *(pt_fir++), 0x00002000L);
+ L_sum = fxp_mac_16by16(tmp2, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp3, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp4, *(pt_fir++), L_sum);
+ tmp1 = *(pt_x++);
+ tmp2 = *(pt_x++);
+ tmp3 = *(pt_x++);
+ tmp4 = *(pt_x++);
+ L_sum = fxp_mac_16by16(tmp1, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp2, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp3, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp4, *(pt_fir++), L_sum);
+ tmp1 = *(pt_x++);
+ tmp2 = *(pt_x++);
+ tmp3 = *(pt_x++);
+ tmp4 = *(pt_x++);
+ L_sum = fxp_mac_16by16(tmp1, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp2, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp3, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp4, *(pt_fir++), L_sum);
+ tmp1 = *(pt_x++);
+ tmp2 = *(pt_x++);
+ tmp3 = *(pt_x++);
+ tmp4 = *(pt_x++);
+ L_sum = fxp_mac_16by16(tmp1, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp2, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp3, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp4, *(pt_fir++), L_sum);
+ tmp1 = *(pt_x++);
+ tmp2 = *(pt_x++);
+ tmp3 = *(pt_x++);
+ tmp4 = *(pt_x++);
+ L_sum = fxp_mac_16by16(tmp1, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp2, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp3, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp4, *(pt_fir++), L_sum);
+ tmp1 = *(pt_x++);
+ tmp2 = *(pt_x++);
+ tmp3 = *(pt_x++);
+ tmp4 = *(pt_x++);
+ L_sum = fxp_mac_16by16(tmp1, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp2, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp3, *(pt_fir++), L_sum);
+ L_sum = fxp_mac_16by16(tmp4, *(pt_fir++), L_sum);
+
+
+ L_sum = shl_int32(L_sum, 2); /* saturation can occur here */
+
+ return ((int16)(L_sum >> 16));
+}
+
diff --git a/media/libstagefright/codecs/amrwb/src/phase_dispersion.cpp b/media/libstagefright/codecs/amrwb/src/phase_dispersion.cpp
new file mode 100644
index 0000000..7b08a40
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/phase_dispersion.cpp
@@ -0,0 +1,261 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: phase_dispersion.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 gain_code, (i) Q0 : gain of code
+ int16 gain_pit, (i) Q14 : gain of pitch
+ int16 code[], (i/o) : code vector
+ int16 mode, (i) : level, 0=hi, 1=lo, 2=off
+ int16 disp_mem[], (i/o) : static memory (size = 8)
+ int16 ScratchMem[]
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ post-processing to enhance noise in low bit rate.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_mem_funcs.h"
+#include "pvamrwbdecoder_acelp.h"
+#include "pvamrwb_math_op.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define pitch_0_9 14746 /* 0.9 in Q14 */
+#define pitch_0_6 9830 /* 0.6 in Q14 */
+#define L_SUBFR 64
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+/* impulse response with phase dispersion */
+
+/* 2.0 - 6.4 kHz phase dispersion */
+static const int16 ph_imp_low[L_SUBFR] =
+{
+ 20182, 9693, 3270, -3437, 2864, -5240, 1589, -1357,
+ 600, 3893, -1497, -698, 1203, -5249, 1199, 5371,
+ -1488, -705, -2887, 1976, 898, 721, -3876, 4227,
+ -5112, 6400, -1032, -4725, 4093, -4352, 3205, 2130,
+ -1996, -1835, 2648, -1786, -406, 573, 2484, -3608,
+ 3139, -1363, -2566, 3808, -639, -2051, -541, 2376,
+ 3932, -6262, 1432, -3601, 4889, 370, 567, -1163,
+ -2854, 1914, 39, -2418, 3454, 2975, -4021, 3431
+};
+
+/* 3.2 - 6.4 kHz phase dispersion */
+static const int16 ph_imp_mid[L_SUBFR] =
+{
+ 24098, 10460, -5263, -763, 2048, -927, 1753, -3323,
+ 2212, 652, -2146, 2487, -3539, 4109, -2107, -374,
+ -626, 4270, -5485, 2235, 1858, -2769, 744, 1140,
+ -763, -1615, 4060, -4574, 2982, -1163, 731, -1098,
+ 803, 167, -714, 606, -560, 639, 43, -1766,
+ 3228, -2782, 665, 763, 233, -2002, 1291, 1871,
+ -3470, 1032, 2710, -4040, 3624, -4214, 5292, -4270,
+ 1563, 108, -580, 1642, -2458, 957, 544, 2540
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void phase_dispersion(
+ int16 gain_code, /* (i) Q0 : gain of code */
+ int16 gain_pit, /* (i) Q14 : gain of pitch */
+ int16 code[], /* (i/o) : code vector */
+ int16 mode, /* (i) : level, 0=hi, 1=lo, 2=off */
+ int16 disp_mem[], /* (i/o) : static memory (size = 8) */
+ int16 ScratchMem[]
+)
+{
+ int16 i, j, state;
+ int16 *prev_gain_pit, *prev_gain_code, *prev_state;
+ int16 *code2 = ScratchMem;
+
+ prev_state = disp_mem;
+ prev_gain_code = disp_mem + 1;
+ prev_gain_pit = disp_mem + 2;
+
+ pv_memset((void *)code2, 0, (2*L_SUBFR)*sizeof(*code2));
+
+
+ if (gain_pit < pitch_0_6)
+ {
+ state = 0;
+ }
+ else if (gain_pit < pitch_0_9)
+ {
+ state = 1;
+ }
+ else
+ {
+ state = 2;
+ }
+
+ for (i = 5; i > 0; i--)
+ {
+ prev_gain_pit[i] = prev_gain_pit[i - 1];
+ }
+ prev_gain_pit[0] = gain_pit;
+
+ if (sub_int16(gain_code, *prev_gain_code) > shl_int16(*prev_gain_code, 1))
+ {
+ /* onset */
+ if (state < 2)
+ {
+ state++;
+ }
+ }
+ else
+ {
+ j = 0;
+ for (i = 0; i < 6; i++)
+ {
+ if (prev_gain_pit[i] < pitch_0_6)
+ {
+ j++;
+ }
+ }
+
+ if (j > 2)
+ {
+ state = 0;
+ }
+ if (state > *prev_state + 1)
+ {
+ state--;
+ }
+ }
+
+ *prev_gain_code = gain_code;
+ *prev_state = state;
+
+ /* circular convolution */
+
+ state += mode; /* level of dispersion */
+
+ if (state == 0)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ if (code[i] != 0)
+ {
+ for (j = 0; j < L_SUBFR; j++)
+ {
+ code2[i + j] = add_int16(code2[i + j], mult_int16_r(code[i], ph_imp_low[j]));
+ }
+ }
+ }
+ }
+ else if (state == 1)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ if (code[i] != 0)
+ {
+ for (j = 0; j < L_SUBFR; j++)
+ {
+ code2[i + j] = add_int16(code2[i + j], mult_int16_r(code[i], ph_imp_mid[j]));
+ }
+ }
+ }
+ }
+ if (state < 2)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ code[i] = add_int16(code2[i], code2[i + L_SUBFR]);
+ }
+ }
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrwb/src/pit_shrp.cpp b/media/libstagefright/codecs/amrwb/src/pit_shrp.cpp
new file mode 100644
index 0000000..4bfcf9c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pit_shrp.cpp
@@ -0,0 +1,132 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: pit_shrp.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 * x, in/out: impulse response (or algebraic code)
+ int16 pit_lag, input : pitch lag
+ int16 sharp, input : pitch sharpening factor (Q15)
+ int16 L_subfr input : subframe size
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Performs Pitch sharpening routine
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void Pit_shrp(
+ int16 * x, /* in/out: impulse response (or algebraic code) */
+ int16 pit_lag, /* input : pitch lag */
+ int16 sharp, /* input : pitch sharpening factor (Q15) */
+ int16 L_subfr /* input : subframe size */
+)
+{
+ int16 i;
+ int32 L_tmp;
+
+ for (i = pit_lag; i < L_subfr; i++)
+ {
+ L_tmp = mac_16by16_to_int32((int32)x[i] << 16, x[i - pit_lag], sharp);
+ x[i] = amr_wb_round(L_tmp);
+
+ }
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrwb/src/pred_lt4.cpp b/media/libstagefright/codecs/amrwb/src/pred_lt4.cpp
new file mode 100644
index 0000000..d5a7984
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pred_lt4.cpp
@@ -0,0 +1,267 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: pred_lt4.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 signal[], input signal / output is divided by 16
+ int16 lg, lenght of signal
+ int16 mem[] in/out: memory (size=30)
+ int16 x[] scratch mem ( size= 60)
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Compute the result of long term prediction with fractionnal
+ interpolation of resolution 1/4.
+
+ On return exc[0..L_subfr-1] contains the interpolated signal
+ (adaptive codebook excitation)
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define UP_SAMP 4
+#define L_INTERPOL2 16
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/* 1/4 resolution interpolation filter (-3 dB at 0.856*fs/2) in Q14 */
+
+
+const int16 inter4_2[UP_SAMP][ 2*L_INTERPOL2] =
+{
+ {
+ 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
+ }
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void Pred_lt4(
+ int16 exc[], /* in/out: excitation buffer */
+ int16 T0, /* input : integer pitch lag */
+ int16 frac, /* input : fraction of lag */
+ int16 L_subfr /* input : subframe size */
+)
+{
+ int16 i, j, *pt_exc;
+ int32 L_sum1;
+ int32 L_sum2;
+ int32 L_sum3;
+ int32 L_sum4;
+ pt_exc = &exc[-T0];
+
+ const int16 *pt_inter4_2;
+
+ frac = -frac;
+
+ if (frac < 0)
+ {
+ frac += UP_SAMP;
+ pt_exc--;
+
+ }
+ pt_exc -= (L_INTERPOL2 - 1);
+
+ pt_inter4_2 = inter4_2[UP_SAMP-1 - frac];
+
+ for (j = 0; j < (L_subfr >> 2); j++)
+ {
+
+ L_sum1 = 0x00002000; /* pre-roundig */
+ L_sum2 = 0x00002000;
+ L_sum3 = 0x00002000;
+ L_sum4 = 0x00002000;
+
+ for (i = 0; i < L_INTERPOL2 << 1; i += 4)
+ {
+ int16 tmp1 = pt_exc[i ];
+ int16 tmp2 = pt_exc[i+1];
+ int16 tmp3 = pt_exc[i+2];
+
+
+ L_sum1 = fxp_mac_16by16(tmp1, pt_inter4_2[i ], L_sum1);
+ L_sum2 = fxp_mac_16by16(tmp2, pt_inter4_2[i ], L_sum2);
+ L_sum1 = fxp_mac_16by16(tmp2, pt_inter4_2[i+1], L_sum1);
+ L_sum2 = fxp_mac_16by16(tmp3, pt_inter4_2[i+1], L_sum2);
+ L_sum3 = fxp_mac_16by16(tmp3, pt_inter4_2[i ], L_sum3);
+ L_sum1 = fxp_mac_16by16(tmp3, pt_inter4_2[i+2], L_sum1);
+
+ tmp1 = pt_exc[i+3];
+ tmp2 = pt_exc[i+4];
+
+ L_sum4 = fxp_mac_16by16(tmp1, pt_inter4_2[i ], L_sum4);
+ L_sum3 = fxp_mac_16by16(tmp1, pt_inter4_2[i+1], L_sum3);
+ L_sum2 = fxp_mac_16by16(tmp1, pt_inter4_2[i+2], L_sum2);
+ L_sum1 = fxp_mac_16by16(tmp1, pt_inter4_2[i+3], L_sum1);
+ L_sum4 = fxp_mac_16by16(tmp2, pt_inter4_2[i+1], L_sum4);
+ L_sum2 = fxp_mac_16by16(tmp2, pt_inter4_2[i+3], L_sum2);
+ L_sum3 = fxp_mac_16by16(tmp2, pt_inter4_2[i+2], L_sum3);
+
+ tmp1 = pt_exc[i+5];
+ tmp2 = pt_exc[i+6];
+
+ L_sum4 = fxp_mac_16by16(tmp1, pt_inter4_2[i+2], L_sum4);
+ L_sum3 = fxp_mac_16by16(tmp1, pt_inter4_2[i+3], L_sum3);
+ L_sum4 = fxp_mac_16by16(tmp2, pt_inter4_2[i+3], L_sum4);
+
+ }
+
+
+
+ exc[(j<<2)] = (int16)(L_sum1 >> 14);
+ exc[(j<<2)+1] = (int16)(L_sum2 >> 14);
+ exc[(j<<2)+2] = (int16)(L_sum3 >> 14);
+ exc[(j<<2)+3] = (int16)(L_sum4 >> 14);
+
+ pt_exc += 4;
+
+ }
+
+ if (L_subfr&1)
+ {
+ L_sum1 = 0x00002000;
+
+ for (i = 0; i < 2*L_INTERPOL2; i += 4)
+ {
+ int16 tmp1 = pt_exc[i ];
+ int16 tmp2 = pt_exc[i+1];
+ L_sum1 = fxp_mac_16by16(tmp1, pt_inter4_2[i ], L_sum1);
+ L_sum1 = fxp_mac_16by16(tmp2, pt_inter4_2[i+1], L_sum1);
+ tmp1 = pt_exc[i+2];
+ tmp2 = pt_exc[i+3];
+ L_sum1 = fxp_mac_16by16(tmp1, pt_inter4_2[i+2], L_sum1);
+ L_sum1 = fxp_mac_16by16(tmp2, pt_inter4_2[i+3], L_sum1);
+
+ }
+
+ exc[(j<<2)] = (int16)((L_sum1) >> 14);
+
+ }
+
+
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrwb/src/preemph_amrwb_dec.cpp b/media/libstagefright/codecs/amrwb/src/preemph_amrwb_dec.cpp
new file mode 100644
index 0000000..3eb5cda
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/preemph_amrwb_dec.cpp
@@ -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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: preemph_amrwb_dec.cpp
+
+ Date: 12/10/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 x[], (i/o) : input signal overwritten by the output
+ int16 mu, (i) Q15 : preemphasis coefficient
+ int16 lg (i) : lenght of filtering
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Preemphasis: filtering through 1 - g z^-1
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void preemph_amrwb_dec(
+ int16 x[], /* (i/o) : input signal overwritten by the output */
+ int16 mu, /* (i) Q15 : preemphasis coefficient */
+ int16 lg /* (i) : lenght of filtering */
+)
+{
+ int16 i;
+ int32 L_tmp;
+
+ for (i = lg - 1; i != 0; i--)
+ {
+ L_tmp = msu_16by16_from_int32((int32)x[i] << 16, x[i - 1], mu);
+ x[i] = amr_wb_round(L_tmp);
+ }
+
+}
+
diff --git a/media/libstagefright/codecs/amrwb/src/pv_amr_wb_type_defs.h b/media/libstagefright/codecs/amrwb/src/pv_amr_wb_type_defs.h
new file mode 100644
index 0000000..1ebcb86
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pv_amr_wb_type_defs.h
@@ -0,0 +1,173 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./cpp/include/pv_amr_wb_type_defs.h
+
+ Date: 12/12/2006
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file was derived from a number of standards bodies. The type
+ definitions below were created from some of the best practices observed
+ in the standards bodies.
+
+ This file is dependent on limits.h for defining the bit widths. In an
+ ANSI C environment limits.h is expected to always be present and contain
+ the following definitions:
+
+ SCHAR_MIN
+ SCHAR_MAX
+ UCHAR_MAX
+
+ INT_MAX
+ INT_MIN
+ UINT_MAX
+
+ SHRT_MIN
+ SHRT_MAX
+ USHRT_MAX
+
+ LONG_MIN
+ LONG_MAX
+ ULONG_MAX
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PV_AMR_WB_TYPE_DEFS_H
+#define PV_AMR_WB_TYPE_DEFS_H
+
+#include <stdint.h>
+
+typedef int8_t Word8;
+typedef uint8_t UWord8;
+
+/*----------------------------------------------------------------------------
+; Define generic signed and unsigned int
+----------------------------------------------------------------------------*/
+typedef signed int Int;
+
+typedef unsigned int UInt;
+
+/*----------------------------------------------------------------------------
+; Define 16 bit signed and unsigned words
+----------------------------------------------------------------------------*/
+
+#ifndef INT16_MIN
+#define INT16_MIN (-32768)
+#endif
+
+#ifndef INT16_MAX
+#define INT16_MAX 32767
+#endif
+
+/*----------------------------------------------------------------------------
+; Define 32 bit signed and unsigned words
+----------------------------------------------------------------------------*/
+
+
+
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647 - 1)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX 2147483647
+#endif
+
+
+#ifndef UINT32_MIN
+#define UINT32_MIN 0
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX 0xffffffff
+#endif
+
+
+/*----------------------------------------------------------------------------
+; Define 64 bit signed and unsigned words
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Define boolean type
+----------------------------------------------------------------------------*/
+
+#ifndef Flag
+typedef Int Flag;
+#endif
+
+#ifndef Bool
+typedef Int Bool;
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef OFF
+#define OFF 0
+#endif
+#ifndef ON
+#define ON 1
+#endif
+
+#ifndef NO
+#define NO 0
+#endif
+#ifndef YES
+#define YES 1
+#endif
+
+#ifndef SUCCESS
+#define SUCCESS 0
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
+typedef uint8_t uint8;
+
+#endif /* PV_AMR_WB_TYPE_DEFS_H */
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.cpp b/media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.cpp
new file mode 100644
index 0000000..d1ec790
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.cpp
@@ -0,0 +1,627 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*___________________________________________________________________________
+
+ This file contains mathematic operations in fixed point.
+
+ mult_int16_r() : Same as mult_int16 with rounding
+ shr_rnd() : Same as shr(var1,var2) but with rounding
+ div_16by16() : fractional integer division
+ one_ov_sqrt() : Compute 1/sqrt(L_x)
+ one_ov_sqrt_norm() : Compute 1/sqrt(x)
+ power_of_2() : power of 2
+ Dot_product12() : Compute scalar product of <x[],y[]> using accumulator
+ Isqrt() : inverse square root (16 bits precision).
+ amrwb_log_2() : log2 (16 bits precision).
+
+ 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:
+
+ int32 L_32 : standard signed 32 bits format
+ int16 hi, lo : L_32 = hi<<16 + lo<<1 (DPF - Double Precision Format)
+ int32 frac, int16 exp : L_32 = frac << exp-31 (normalised format)
+ int16 int, frac : L_32 = int.frac (fractional format)
+ ----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwb_math_op.h"
+
+
+/*----------------------------------------------------------------------------
+
+ Function Name : mult_int16_r
+
+ Purpose :
+
+ Same as mult_int16 with rounding, i.e.:
+ mult_int16_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and
+ mult_int16_r(-32768,-32768) = 32767.
+
+ Complexity weight : 2
+
+ Inputs :
+
+ var1
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ var2
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ Outputs :
+
+ none
+
+ Return Value :
+
+ var_out
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var_out <= 0x0000 7fff.
+ ----------------------------------------------------------------------------*/
+
+int16 mult_int16_r(int16 var1, int16 var2)
+{
+ int32 L_product_arr;
+
+ L_product_arr = (int32) var1 * (int32) var2; /* product */
+ L_product_arr += (int32) 0x00004000L; /* round */
+ L_product_arr >>= 15; /* shift */
+ if ((L_product_arr >> 15) != (L_product_arr >> 31))
+ {
+ L_product_arr = (L_product_arr >> 31) ^ MAX_16;
+ }
+
+ return ((int16)L_product_arr);
+}
+
+
+
+/*----------------------------------------------------------------------------
+
+ Function Name : shr_rnd
+
+ 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_int16(shr(var1,var2),1),shr(var1,sub(var2,1))))
+ is equal to zero
+ then
+ shr_rnd(var1,var2) = shr(var1,var2)
+ else
+ shr_rnd(var1,var2) = add_int16(shr(var1,var2),1)
+ - If var2 is less than or equal to zero :
+ shr_rnd(var1,var2) = shr(var1,var2).
+
+ Complexity weight : 2
+
+ Inputs :
+
+ var1
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ var2
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0x0000 0000 <= var2 <= 0x0000 7fff.
+
+ Outputs :
+
+ none
+
+ Return Value :
+
+ var_out
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var_out <= 0x0000 7fff.
+ ----------------------------------------------------------------------------*/
+
+int16 shr_rnd(int16 var1, int16 var2)
+{
+ int16 var_out;
+
+ var_out = (int16)(var1 >> (var2 & 0xf));
+ if (var2)
+ {
+ if ((var1 & ((int16) 1 << (var2 - 1))) != 0)
+ {
+ var_out++;
+ }
+ }
+ return (var_out);
+}
+
+
+/*----------------------------------------------------------------------------
+
+ Function Name : div_16by16
+
+ 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 (int16) whose value falls in the
+ range : 0x0000 0000 <= var1 <= var2 and var2 != 0.
+
+ var2
+ 16 bit short signed integer (int16) whose value falls in the
+ range : var1 <= var2 <= 0x0000 7fff and var2 != 0.
+
+ Outputs :
+
+ none
+
+ Return Value :
+
+ var_out
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0x0000 0000 <= var_out <= 0x0000 7fff.
+ It's a Q15 value (point between b15 and b14).
+ ----------------------------------------------------------------------------*/
+
+int16 div_16by16(int16 var1, int16 var2)
+{
+
+ int16 var_out = 0;
+ register int16 iteration;
+ int32 L_num;
+ int32 L_denom;
+ int32 L_denom_by_2;
+ int32 L_denom_by_4;
+
+ if ((var1 > var2) || (var1 < 0))
+ {
+ return 0; // used to exit(0);
+ }
+ if (var1)
+ {
+ if (var1 != var2)
+ {
+
+ L_num = (int32) var1;
+ L_denom = (int32) var2;
+ L_denom_by_2 = (L_denom << 1);
+ L_denom_by_4 = (L_denom << 2);
+ for (iteration = 5; iteration > 0; iteration--)
+ {
+ var_out <<= 3;
+ L_num <<= 3;
+
+ if (L_num >= L_denom_by_4)
+ {
+ L_num -= L_denom_by_4;
+ var_out |= 4;
+ }
+
+ if (L_num >= L_denom_by_2)
+ {
+ L_num -= L_denom_by_2;
+ var_out |= 2;
+ }
+
+ if (L_num >= (L_denom))
+ {
+ L_num -= (L_denom);
+ var_out |= 1;
+ }
+
+ }
+ }
+ else
+ {
+ var_out = MAX_16;
+ }
+ }
+
+ return (var_out);
+
+}
+
+
+
+/*----------------------------------------------------------------------------
+
+ Function Name : one_ov_sqrt
+
+ 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
+ ----------------------------------------------------------------------------*/
+int32 one_ov_sqrt( /* (o) Q31 : output value (range: 0<=val<1) */
+ int32 L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */
+)
+{
+ int16 exp;
+ int32 L_y;
+
+ exp = normalize_amr_wb(L_x);
+ L_x <<= exp; /* L_x is normalized */
+ exp = 31 - exp;
+
+ one_ov_sqrt_norm(&L_x, &exp);
+
+ L_y = shl_int32(L_x, exp); /* denormalization */
+
+ return (L_y);
+}
+
+/*----------------------------------------------------------------------------
+
+ Function Name : one_ov_sqrt_norm
+
+ 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 const int16 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 one_ov_sqrt_norm(
+ int32 * frac, /* (i/o) Q31: normalized value (1.0 < frac <= 0.5) */
+ int16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */
+)
+{
+ int16 i, a, tmp;
+
+
+ if (*frac <= (int32) 0)
+ {
+ *exp = 0;
+ *frac = 0x7fffffffL;
+ return;
+ }
+
+ if ((*exp & 1) == 1) /* If exponant odd -> shift right */
+ *frac >>= 1;
+
+ *exp = negate_int16((*exp - 1) >> 1);
+
+ *frac >>= 9;
+ i = extract_h(*frac); /* Extract b25-b31 */
+ *frac >>= 1;
+ a = (int16)(*frac); /* Extract b10-b24 */
+ a = (int16)(a & (int16) 0x7fff);
+
+ i -= 16;
+
+ *frac = L_deposit_h(table_isqrt[i]); /* table[i] << 16 */
+ tmp = table_isqrt[i] - table_isqrt[i + 1]; /* table[i] - table[i+1]) */
+
+ *frac = msu_16by16_from_int32(*frac, tmp, a); /* frac -= tmp*a*2 */
+
+ return;
+}
+
+/*----------------------------------------------------------------------------
+
+ Function Name : power_2()
+
+ L_x = pow(2.0, exponant.fraction) (exponant = interger part)
+ = pow(2.0, 0.fraction) << exponant
+
+ Algorithm:
+
+ The function power_2(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)
+ ----------------------------------------------------------------------------*/
+const int16 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
+};
+
+int32 power_of_2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */
+ int16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */
+ int16 fraction /* (i) Q15 : Fractionnal part. (range: 0.0<=val<1.0) */
+)
+{
+ int16 exp, i, a, tmp;
+ int32 L_x;
+
+ L_x = fraction << 5; /* L_x = fraction<<6 */
+ i = (fraction >> 10); /* Extract b10-b16 of fraction */
+ a = (int16)(L_x); /* Extract b0-b9 of fraction */
+ a = (int16)(a & (int16) 0x7fff);
+
+ L_x = ((int32)table_pow2[i]) << 15; /* table[i] << 16 */
+ tmp = table_pow2[i] - table_pow2[i + 1]; /* table[i] - table[i+1] */
+ L_x -= ((int32)tmp * a); /* L_x -= tmp*a*2 */
+
+ exp = 29 - exponant ;
+
+ if (exp)
+ {
+ L_x = ((L_x >> exp) + ((L_x >> (exp - 1)) & 1));
+ }
+
+ 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
+ ----------------------------------------------------------------------------*/
+
+int32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */
+ int16 x[], /* (i) 12bits: x vector */
+ int16 y[], /* (i) 12bits: y vector */
+ int16 lg, /* (i) : vector length */
+ int16 * exp /* (o) : exponent of result (0..+30) */
+)
+{
+ int16 i, sft;
+ int32 L_sum;
+ int16 *pt_x = x;
+ int16 *pt_y = y;
+
+ L_sum = 1L;
+
+
+ for (i = lg >> 3; i != 0; i--)
+ {
+ L_sum = mac_16by16_to_int32(L_sum, *(pt_x++), *(pt_y++));
+ L_sum = mac_16by16_to_int32(L_sum, *(pt_x++), *(pt_y++));
+ L_sum = mac_16by16_to_int32(L_sum, *(pt_x++), *(pt_y++));
+ L_sum = mac_16by16_to_int32(L_sum, *(pt_x++), *(pt_y++));
+ L_sum = mac_16by16_to_int32(L_sum, *(pt_x++), *(pt_y++));
+ L_sum = mac_16by16_to_int32(L_sum, *(pt_x++), *(pt_y++));
+ L_sum = mac_16by16_to_int32(L_sum, *(pt_x++), *(pt_y++));
+ L_sum = mac_16by16_to_int32(L_sum, *(pt_x++), *(pt_y++));
+ }
+
+ /* Normalize acc in Q31 */
+
+ sft = normalize_amr_wb(L_sum);
+ L_sum <<= sft;
+
+ *exp = 30 - sft; /* exponent = 0..30 */
+
+ return (L_sum);
+}
+
+/* Table for Log2() */
+const int16 Log2_norm_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
+};
+
+/*----------------------------------------------------------------------------
+ *
+ * FUNCTION: Lg2_normalized()
+ *
+ * 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 Lg2_normalized(
+ int32 L_x, /* (i) : input value (normalized) */
+ int16 exp, /* (i) : norm_l (L_x) */
+ int16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */
+ int16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+)
+{
+ int16 i, a, tmp;
+ int32 L_y;
+
+ if (L_x <= (int32) 0)
+ {
+ *exponent = 0;
+ *fraction = 0;;
+ return;
+ }
+
+ *exponent = 30 - exp;
+
+ L_x >>= 9;
+ i = extract_h(L_x); /* Extract b25-b31 */
+ L_x >>= 1;
+ a = (int16)(L_x); /* Extract b10-b24 of fraction */
+ a &= 0x7fff;
+
+ i -= 32;
+
+ L_y = L_deposit_h(Log2_norm_table[i]); /* table[i] << 16 */
+ tmp = Log2_norm_table[i] - Log2_norm_table[i + 1]; /* table[i] - table[i+1] */
+ L_y = msu_16by16_from_int32(L_y, tmp, a); /* L_y -= tmp*a*2 */
+
+ *fraction = extract_h(L_y);
+
+ return;
+}
+
+
+
+/*----------------------------------------------------------------------------
+ *
+ * FUNCTION: amrwb_log_2()
+ *
+ * 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 Lg2_normalized().
+ *
+ ----------------------------------------------------------------------------*/
+void amrwb_log_2(
+ int32 L_x, /* (i) : input value */
+ int16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */
+ int16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+)
+{
+ int16 exp;
+
+ exp = normalize_amr_wb(L_x);
+ Lg2_normalized(shl_int32(L_x, exp), exp, exponent, fraction);
+}
+
+
+/*****************************************************************************
+ *
+ * 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. *
+ *****************************************************************************
+*/
+
+
+/*----------------------------------------------------------------------------
+ *
+ * Function int32_to_dpf()
+ *
+ * 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 int32_to_dpf(int32 L_32, int16 *hi, int16 *lo)
+{
+ *hi = (int16)(L_32 >> 16);
+ *lo = (int16)((L_32 - (*hi << 16)) >> 1);
+ return;
+}
+
+
+/*----------------------------------------------------------------------------
+ * Function mpy_dpf_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
+ *
+ ----------------------------------------------------------------------------*/
+
+int32 mpy_dpf_32(int16 hi1, int16 lo1, int16 hi2, int16 lo2)
+{
+ int32 L_32;
+
+ L_32 = mul_16by16_to_int32(hi1, hi2);
+ L_32 = mac_16by16_to_int32(L_32, mult_int16(hi1, lo2), 1);
+ L_32 = mac_16by16_to_int32(L_32, mult_int16(lo1, hi2), 1);
+
+ return (L_32);
+}
+
+
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.h b/media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.h
new file mode 100644
index 0000000..8951e5c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwb_math_op.h
@@ -0,0 +1,132 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./src/pvamrwb_math_op.h
+
+ Date: 01/04/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PVAMRWB_MATH_OP_H
+#define PVAMRWB_MATH_OP_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; DEFINES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ int32 one_ov_sqrt( /* (o) Q31 : output value (range: 0<=val<1) */
+ int32 L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */
+ );
+ void one_ov_sqrt_norm(
+ int32 * frac, /* (i/o) Q31: normalized value (1.0 < frac <= 0.5) */
+ int16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */
+ );
+ int32 power_of_2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */
+ int16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */
+ int16 fraction /* (i) Q15 : Fractionnal part. (range: 0.0<=val<1.0) */
+ );
+ int32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */
+ int16 x[], /* (i) 12bits: x vector */
+ int16 y[], /* (i) 12bits: y vector */
+ int16 lg, /* (i) : vector length */
+ int16 * exp /* (o) : exponent of result (0..+30) */
+ );
+
+
+ void amrwb_log_2(
+ int32 L_x, /* (i) : input value */
+ int16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */
+ int16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1)*/
+ );
+
+ void Lg2_normalized(
+ int32 L_x, /* (i) : input value (normalized) */
+ int16 exp, /* (i) : norm_l (L_x) */
+ int16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */
+ int16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+ );
+
+
+ int16 mult_int16_r(int16 var1, int16 var2); /* Mult with round, 2 */
+ int16 shr_rnd(int16 var1, int16 var2); /* Shift right with round, 2 */
+
+ int16 div_16by16(int16 var1, int16 var2); /* Short division, 18 */
+
+
+ void int32_to_dpf(int32 L_32, int16 *hi, int16 *lo);
+ int32 mpy_dpf_32(int16 hi1, int16 lo1, int16 hi2, int16 lo2);
+
+
+#define norm_s( x) (normalize_amr_wb( x) - 16)
+
+
+#define extract_h( x) (int16)(x>>16)
+#define L_deposit_h( x) (int32)(x<<16)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* PVAMRWB_MATH_OP_H */
+
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp
new file mode 100644
index 0000000..b8cfefa
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.cpp
@@ -0,0 +1,1149 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: pvamrwbdecoder.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 mode, input : used mode
+ int16 prms[], input : parameter vector
+ int16 synth16k[], output: synthesis speech
+ int16 * frame_length, output: lenght of the frame
+ void *spd_state, i/o : State structure
+ int16 frame_type, input : received frame type
+ int16 ScratchMem[]
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Performs the main decoder routine AMR WB ACELP coding algorithm with 20 ms
+ speech frames for wideband speech signals.
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_mem_funcs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+#include "e_pv_amrwbdec.h"
+#include "get_amr_wb_bits.h"
+#include "pvamrwb_math_op.h"
+#include "pvamrwbdecoder_api.h"
+#include "pvamrwbdecoder.h"
+#include "synthesis_amr_wb.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/* LPC interpolation coef {0.45, 0.8, 0.96, 1.0}; in Q15 */
+static const int16 interpol_frac[NB_SUBFR] = {14746, 26214, 31457, 32767};
+
+
+/* isp tables for initialization */
+
+static const int16 isp_init[M] =
+{
+ 32138, 30274, 27246, 23170, 18205, 12540, 6393, 0,
+ -6393, -12540, -18205, -23170, -27246, -30274, -32138, 1475
+};
+
+static const int16 isf_init[M] =
+{
+ 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192,
+ 9216, 10240, 11264, 12288, 13312, 14336, 15360, 3840
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ FUNCTION DESCRIPTION pvDecoder_AmrWb_Init
+
+ Initialization of variables for the decoder section.
+
+----------------------------------------------------------------------------*/
+
+
+
+
+void pvDecoder_AmrWb_Init(void **spd_state, void *pt_st, int16 **ScratchMem)
+{
+ /* Decoder states */
+ Decoder_State *st = &(((PV_AmrWbDec *)pt_st)->state);
+
+ *ScratchMem = ((PV_AmrWbDec *)pt_st)->ScratchMem;
+ /*
+ * Init dtx decoding
+ */
+ dtx_dec_amr_wb_reset(&(st->dtx_decSt), isf_init);
+
+ pvDecoder_AmrWb_Reset((void *) st, 1);
+
+ *spd_state = (void *) st;
+
+ return;
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvDecoder_AmrWb_Reset(void *st, int16 reset_all)
+{
+ int16 i;
+
+ Decoder_State *dec_state;
+
+ dec_state = (Decoder_State *) st;
+
+ pv_memset((void *)dec_state->old_exc,
+ 0,
+ (PIT_MAX + L_INTERPOL)*sizeof(*dec_state->old_exc));
+
+ pv_memset((void *)dec_state->past_isfq,
+ 0,
+ M*sizeof(*dec_state->past_isfq));
+
+
+ dec_state->old_T0_frac = 0; /* old pitch value = 64.0 */
+ dec_state->old_T0 = 64;
+ dec_state->first_frame = 1;
+ dec_state->L_gc_thres = 0;
+ dec_state->tilt_code = 0;
+
+ pv_memset((void *)dec_state->disp_mem,
+ 0,
+ 8*sizeof(*dec_state->disp_mem));
+
+
+ /* scaling memories for excitation */
+ dec_state->Q_old = Q_MAX;
+ dec_state->Qsubfr[3] = Q_MAX;
+ dec_state->Qsubfr[2] = Q_MAX;
+ dec_state->Qsubfr[1] = Q_MAX;
+ dec_state->Qsubfr[0] = Q_MAX;
+
+ if (reset_all != 0)
+ {
+ /* routines initialization */
+
+ dec_gain2_amr_wb_init(dec_state->dec_gain);
+ oversamp_12k8_to_16k_init(dec_state->mem_oversamp);
+ band_pass_6k_7k_init(dec_state->mem_hf);
+ low_pass_filt_7k_init(dec_state->mem_hf3);
+ highpass_50Hz_at_12k8_init(dec_state->mem_sig_out);
+ highpass_400Hz_at_12k8_init(dec_state->mem_hp400);
+ Init_Lagconc(dec_state->lag_hist);
+
+ /* isp initialization */
+
+ pv_memcpy((void *)dec_state->ispold, (void *)isp_init, M*sizeof(*isp_init));
+
+ pv_memcpy((void *)dec_state->isfold, (void *)isf_init, M*sizeof(*isf_init));
+ for (i = 0; i < L_MEANBUF; i++)
+ {
+ pv_memcpy((void *)&dec_state->isf_buf[i * M],
+ (void *)isf_init,
+ M*sizeof(*isf_init));
+ }
+ /* variable initialization */
+
+ dec_state->mem_deemph = 0;
+
+ dec_state->seed = 21845; /* init random with 21845 */
+ dec_state->seed2 = 21845;
+ dec_state->seed3 = 21845;
+
+ dec_state->state = 0;
+ dec_state->prev_bfi = 0;
+
+ /* Static vectors to zero */
+
+ pv_memset((void *)dec_state->mem_syn_hf,
+ 0,
+ M16k*sizeof(*dec_state->mem_syn_hf));
+
+ pv_memset((void *)dec_state->mem_syn_hi,
+ 0,
+ M*sizeof(*dec_state->mem_syn_hi));
+
+ pv_memset((void *)dec_state->mem_syn_lo,
+ 0,
+ M*sizeof(*dec_state->mem_syn_lo));
+
+
+ dtx_dec_amr_wb_reset(&(dec_state->dtx_decSt), isf_init);
+ dec_state->vad_hist = 0;
+
+ }
+ return;
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+int32 pvDecoder_AmrWbMemRequirements()
+{
+ return(sizeof(PV_AmrWbDec));
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/* Main decoder routine. */
+
+int32 pvDecoder_AmrWb(
+ int16 mode, /* input : used mode */
+ int16 prms[], /* input : parameter vector */
+ int16 synth16k[], /* output: synthesis speech */
+ int16 * frame_length, /* output: lenght of the frame */
+ void *spd_state, /* i/o : State structure */
+ int16 frame_type, /* input : received frame type */
+ int16 ScratchMem[]
+)
+{
+
+ /* Decoder states */
+ Decoder_State *st;
+
+ int16 *ScratchMem2 = &ScratchMem[ L_SUBFR + L_SUBFR16k + ((L_SUBFR + M + M16k +1)<<1)];
+
+
+ /* Excitation vector */
+
+
+ int16 *old_exc = ScratchMem2;
+
+ int16 *Aq = &old_exc[(L_FRAME + 1) + PIT_MAX + L_INTERPOL];/* A(z) quantized for the 4 subframes */
+
+ int16 *ispnew = &Aq[NB_SUBFR * (M + 1)];/* immittance spectral pairs at 4nd sfr */
+ int16 *isf = &ispnew[M]; /* ISF (frequency domain) at 4nd sfr */
+ int16 *isf_tmp = &isf[M];
+ int16 *code = &isf_tmp[M]; /* algebraic codevector */
+ int16 *excp = &code[L_SUBFR];
+ int16 *exc2 = &excp[L_SUBFR]; /* excitation vector */
+ int16 *HfIsf = &exc2[L_FRAME];
+
+
+ int16 *exc;
+
+ /* LPC coefficients */
+
+ int16 *p_Aq; /* ptr to A(z) for the 4 subframes */
+
+
+
+ int16 fac, stab_fac, voice_fac, Q_new = 0;
+ int32 L_tmp, L_gain_code;
+
+ /* Scalars */
+
+ int16 i, j, i_subfr, index, ind[8], tmp;
+ int32 max;
+ int16 T0, T0_frac, pit_flag, T0_max, select, T0_min = 0;
+ int16 gain_pit, gain_code;
+ int16 newDTXState, bfi, unusable_frame, nb_bits;
+ int16 vad_flag;
+ int16 pit_sharp;
+
+ int16 corr_gain = 0;
+
+ st = (Decoder_State *) spd_state;
+
+ /* mode verification */
+
+ nb_bits = AMR_WB_COMPRESSED[mode];
+
+ *frame_length = AMR_WB_PCM_FRAME;
+
+ /* find the new DTX state SPEECH OR DTX */
+ newDTXState = rx_amr_wb_dtx_handler(&(st->dtx_decSt), frame_type);
+
+
+ if (newDTXState != SPEECH)
+ {
+ dtx_dec_amr_wb(&(st->dtx_decSt), exc2, newDTXState, isf, &prms);
+ }
+ /* SPEECH action state machine */
+
+ if ((frame_type == RX_SPEECH_BAD) ||
+ (frame_type == RX_SPEECH_PROBABLY_DEGRADED))
+ {
+ /* bfi for all index, bits are not usable */
+ bfi = 1;
+ unusable_frame = 0;
+ }
+ else if ((frame_type == RX_NO_DATA) ||
+ (frame_type == RX_SPEECH_LOST))
+ {
+ /* bfi only for lsf, gains and pitch period */
+ bfi = 1;
+ unusable_frame = 1;
+ }
+ else
+ {
+ bfi = 0;
+ unusable_frame = 0;
+ }
+
+ if (bfi != 0)
+ {
+ st->state += 1;
+
+ if (st->state > 6)
+ {
+ st->state = 6;
+ }
+ }
+ else
+ {
+ st->state >>= 1;
+ }
+
+ /* If this frame is the first speech frame after CNI period,
+ * set the BFH state machine to an appropriate state depending
+ * on whether there was DTX muting before start of speech or not
+ * If there was DTX muting, the first speech frame is muted.
+ * If there was no DTX muting, the first speech frame is not
+ * muted. The BFH state machine starts from state 5, however, to
+ * keep the audible noise resulting from a SID frame which is
+ * erroneously interpreted as a good speech frame as small as
+ * possible (the decoder output in this case is quickly muted)
+ */
+
+ if (st->dtx_decSt.dtxGlobalState == DTX)
+ {
+ st->state = 5;
+ st->prev_bfi = 0;
+ }
+ else if (st->dtx_decSt.dtxGlobalState == DTX_MUTE)
+ {
+ st->state = 5;
+ st->prev_bfi = 1;
+ }
+
+ if (newDTXState == SPEECH)
+ {
+ vad_flag = Serial_parm_1bit(&prms);
+
+ if (bfi == 0)
+ {
+ if (vad_flag == 0)
+ {
+ st->vad_hist = add_int16(st->vad_hist, 1);
+ }
+ else
+ {
+ st->vad_hist = 0;
+ }
+ }
+ }
+ /*
+ * DTX-CNG
+ */
+
+ if (newDTXState != SPEECH) /* CNG mode */
+ {
+ /* increase slightly energy of noise below 200 Hz */
+
+ /* Convert ISFs to the cosine domain */
+ Isf_isp(isf, ispnew, M);
+
+ Isp_Az(ispnew, Aq, M, 1);
+
+ pv_memcpy((void *)isf_tmp, (void *)st->isfold, M*sizeof(*isf_tmp));
+
+
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ j = i_subfr >> 6;
+
+ for (i = 0; i < M; i++)
+ {
+ L_tmp = mul_16by16_to_int32(isf_tmp[i], sub_int16(32767, interpol_frac[j]));
+ L_tmp = mac_16by16_to_int32(L_tmp, isf[i], interpol_frac[j]);
+ HfIsf[i] = amr_wb_round(L_tmp);
+ }
+
+ synthesis_amr_wb(Aq,
+ &exc2[i_subfr],
+ 0,
+ &synth16k[i_subfr *5/4],
+ (short) 1,
+ HfIsf,
+ nb_bits,
+ newDTXState,
+ st,
+ bfi,
+ ScratchMem);
+ }
+
+ /* reset speech coder memories */
+ pvDecoder_AmrWb_Reset(st, 0);
+
+ pv_memcpy((void *)st->isfold, (void *)isf, M*sizeof(*isf));
+
+ st->prev_bfi = bfi;
+ st->dtx_decSt.dtxGlobalState = newDTXState;
+
+ return 0;
+ }
+ /*
+ * ACELP
+ */
+
+ /* copy coder memory state into working space (internal memory for DSP) */
+
+ pv_memcpy((void *)old_exc, (void *)st->old_exc, (PIT_MAX + L_INTERPOL)*sizeof(*old_exc));
+
+ exc = old_exc + PIT_MAX + L_INTERPOL;
+
+ /* Decode the ISFs */
+
+ if (nb_bits > NBBITS_7k) /* all rates but 6.6 Kbps */
+ {
+ ind[0] = Serial_parm(8, &prms); /* index of 1st ISP subvector */
+ ind[1] = Serial_parm(8, &prms); /* index of 2nd ISP subvector */
+ ind[2] = Serial_parm(6, &prms); /* index of 3rd ISP subvector */
+ ind[3] = Serial_parm(7, &prms); /* index of 4th ISP subvector */
+ ind[4] = Serial_parm(7, &prms); /* index of 5th ISP subvector */
+ ind[5] = Serial_parm(5, &prms); /* index of 6th ISP subvector */
+ ind[6] = Serial_parm(5, &prms); /* index of 7th ISP subvector */
+
+ Dpisf_2s_46b(ind, isf, st->past_isfq, st->isfold, st->isf_buf, bfi, 1);
+ }
+ else
+ {
+ ind[0] = Serial_parm(8, &prms);
+ ind[1] = Serial_parm(8, &prms);
+ ind[2] = Serial_parm(14, &prms);
+ ind[3] = ind[2] & 0x007F;
+ ind[2] >>= 7;
+ ind[4] = Serial_parm(6, &prms);
+
+ Dpisf_2s_36b(ind, isf, st->past_isfq, st->isfold, st->isf_buf, bfi, 1);
+ }
+
+ /* Convert ISFs to the cosine domain */
+
+ Isf_isp(isf, ispnew, M);
+
+ if (st->first_frame != 0)
+ {
+ st->first_frame = 0;
+ pv_memcpy((void *)st->ispold, (void *)ispnew, M*sizeof(*ispnew));
+
+ }
+ /* Find the interpolated ISPs and convert to a[] for all subframes */
+ interpolate_isp(st->ispold, ispnew, interpol_frac, Aq);
+
+ /* update ispold[] for the next frame */
+ pv_memcpy((void *)st->ispold, (void *)ispnew, M*sizeof(*ispnew));
+
+ /* Check stability on isf : distance between old isf and current isf */
+
+ L_tmp = 0;
+ for (i = 0; i < M - 1; i++)
+ {
+ tmp = sub_int16(isf[i], st->isfold[i]);
+ L_tmp = mac_16by16_to_int32(L_tmp, tmp, tmp);
+ }
+ tmp = extract_h(shl_int32(L_tmp, 8));
+ tmp = mult_int16(tmp, 26214); /* tmp = L_tmp*0.8/256 */
+
+ tmp = 20480 - tmp; /* 1.25 - tmp */
+ stab_fac = shl_int16(tmp, 1); /* Q14 -> Q15 with saturation */
+
+ if (stab_fac < 0)
+ {
+ stab_fac = 0;
+ }
+ pv_memcpy((void *)isf_tmp, (void *)st->isfold, M*sizeof(*isf_tmp));
+
+ pv_memcpy((void *)st->isfold, (void *)isf, M*sizeof(*isf));
+
+ /*
+ * Loop for every subframe in the analysis frame
+ *
+ * The subframe size is L_SUBFR and the loop is repeated L_FRAME/L_SUBFR
+ * times
+ * - decode the pitch delay and filter mode
+ * - decode algebraic code
+ * - decode pitch and codebook gains
+ * - find voicing factor and tilt of code for next subframe.
+ * - find the excitation and compute synthesis speech
+ */
+
+ p_Aq = Aq; /* pointer to interpolated LPC parameters */
+
+
+ /*
+ * Sub process next 3 subframes
+ */
+
+
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ pit_flag = i_subfr;
+
+
+ if ((i_subfr == 2*L_SUBFR) && (nb_bits > NBBITS_7k))
+ {
+ pit_flag = 0; /* set to 0 for 3rd subframe, <=> is not 6.6 kbps */
+ }
+ /*-------------------------------------------------*
+ * - Decode pitch lag *
+ * Lag indeces received also in case of BFI, *
+ * so that the parameter pointer stays in sync. *
+ *-------------------------------------------------*/
+
+ if (pit_flag == 0)
+ {
+
+ if (nb_bits <= NBBITS_9k)
+ {
+ index = Serial_parm(8, &prms);
+
+ if (index < (PIT_FR1_8b - PIT_MIN) * 2)
+ {
+ T0 = PIT_MIN + (index >> 1);
+ T0_frac = sub_int16(index, shl_int16(sub_int16(T0, PIT_MIN), 1));
+ T0_frac = shl_int16(T0_frac, 1);
+ }
+ else
+ {
+ T0 = add_int16(index, PIT_FR1_8b - ((PIT_FR1_8b - PIT_MIN) * 2));
+ T0_frac = 0;
+ }
+ }
+ else
+ {
+ index = Serial_parm(9, &prms);
+
+ if (index < (PIT_FR2 - PIT_MIN) * 4)
+ {
+ T0 = PIT_MIN + (index >> 2);
+ T0_frac = sub_int16(index, shl_int16(sub_int16(T0, PIT_MIN), 2));
+ }
+ else if (index < (((PIT_FR2 - PIT_MIN) << 2) + ((PIT_FR1_9b - PIT_FR2) << 1)))
+ {
+ index -= (PIT_FR2 - PIT_MIN) << 2;
+ T0 = PIT_FR2 + (index >> 1);
+ T0_frac = sub_int16(index, shl_int16(sub_int16(T0, PIT_FR2), 1));
+ T0_frac = shl_int16(T0_frac, 1);
+ }
+ else
+ {
+ T0 = add_int16(index, (PIT_FR1_9b - ((PIT_FR2 - PIT_MIN) * 4) - ((PIT_FR1_9b - PIT_FR2) * 2)));
+ T0_frac = 0;
+ }
+ }
+
+ /* 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 = PIT_MAX - 15;
+ }
+ }
+ else
+ { /* if subframe 2 or 4 */
+
+ if (nb_bits <= NBBITS_9k)
+ {
+ index = Serial_parm(5, &prms);
+
+ T0 = T0_min + (index >> 1);
+ T0_frac = sub_int16(index, shl_int16(T0 - T0_min, 1));
+ T0_frac = shl_int16(T0_frac, 1);
+ }
+ else
+ {
+ index = Serial_parm(6, &prms);
+
+ T0 = T0_min + (index >> 2);
+ T0_frac = sub_int16(index, shl_int16(T0 - T0_min, 2));
+ }
+ }
+
+ /* check BFI after pitch lag decoding */
+
+ if (bfi != 0) /* if frame erasure */
+ {
+ lagconceal(&(st->dec_gain[17]), st->lag_hist, &T0, &(st->old_T0), &(st->seed3), unusable_frame);
+ T0_frac = 0;
+ }
+ /*
+ * Find the pitch gain, the interpolation filter
+ * and the adaptive codebook vector.
+ */
+
+ Pred_lt4(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1);
+
+
+ if (unusable_frame)
+ {
+ select = 1;
+ }
+ else
+ {
+
+ if (nb_bits <= NBBITS_9k)
+ {
+ select = 0;
+ }
+ else
+ {
+ select = Serial_parm_1bit(&prms);
+ }
+ }
+
+
+ if (select == 0)
+ {
+ /* find pitch excitation with lp filter */
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ L_tmp = ((int32) exc[i-1+i_subfr] + exc[i+1+i_subfr]);
+ L_tmp *= 5898;
+ L_tmp += ((int32) exc[i+i_subfr] * 20972);
+
+ code[i] = amr_wb_round(L_tmp << 1);
+ }
+ pv_memcpy((void *)&exc[i_subfr], (void *)code, L_SUBFR*sizeof(*code));
+
+ }
+ /*
+ * Decode innovative codebook.
+ * Add the fixed-gain pitch contribution to code[].
+ */
+
+ if (unusable_frame != 0)
+ {
+ /* the innovative code doesn't need to be scaled (see Q_gain2) */
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ code[i] = noise_gen_amrwb(&(st->seed)) >> 3;
+ }
+ }
+ else if (nb_bits <= NBBITS_7k)
+ {
+ ind[0] = Serial_parm(12, &prms);
+ dec_acelp_2p_in_64(ind[0], code);
+ }
+ else if (nb_bits <= NBBITS_9k)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ ind[i] = Serial_parm(5, &prms);
+ }
+ dec_acelp_4p_in_64(ind, 20, code);
+ }
+ else if (nb_bits <= NBBITS_12k)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ ind[i] = Serial_parm(9, &prms);
+ }
+ dec_acelp_4p_in_64(ind, 36, code);
+ }
+ else if (nb_bits <= NBBITS_14k)
+ {
+ ind[0] = Serial_parm(13, &prms);
+ ind[1] = Serial_parm(13, &prms);
+ ind[2] = Serial_parm(9, &prms);
+ ind[3] = Serial_parm(9, &prms);
+ dec_acelp_4p_in_64(ind, 44, code);
+ }
+ else if (nb_bits <= NBBITS_16k)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ ind[i] = Serial_parm(13, &prms);
+ }
+ dec_acelp_4p_in_64(ind, 52, code);
+ }
+ else if (nb_bits <= NBBITS_18k)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ ind[i] = Serial_parm(2, &prms);
+ }
+ for (i = 4; i < 8; i++)
+ {
+ ind[i] = Serial_parm(14, &prms);
+ }
+ dec_acelp_4p_in_64(ind, 64, code);
+ }
+ else if (nb_bits <= NBBITS_20k)
+ {
+ ind[0] = Serial_parm(10, &prms);
+ ind[1] = Serial_parm(10, &prms);
+ ind[2] = Serial_parm(2, &prms);
+ ind[3] = Serial_parm(2, &prms);
+ ind[4] = Serial_parm(10, &prms);
+ ind[5] = Serial_parm(10, &prms);
+ ind[6] = Serial_parm(14, &prms);
+ ind[7] = Serial_parm(14, &prms);
+ dec_acelp_4p_in_64(ind, 72, code);
+ }
+ else
+ {
+ for (i = 0; i < 8; i++)
+ {
+ ind[i] = Serial_parm(11, &prms);
+ }
+
+ dec_acelp_4p_in_64(ind, 88, code);
+ }
+
+ preemph_amrwb_dec(code, st->tilt_code, L_SUBFR);
+
+ tmp = T0;
+
+ if (T0_frac > 2)
+ {
+ tmp++;
+ }
+ Pit_shrp(code, tmp, PIT_SHARP, L_SUBFR);
+
+ /*
+ * Decode codebooks gains.
+ */
+
+ if (nb_bits <= NBBITS_9k)
+ {
+ index = Serial_parm(6, &prms); /* codebook gain index */
+
+ dec_gain2_amr_wb(index,
+ 6,
+ code,
+ L_SUBFR,
+ &gain_pit,
+ &L_gain_code,
+ bfi,
+ st->prev_bfi,
+ st->state,
+ unusable_frame,
+ st->vad_hist,
+ st->dec_gain);
+ }
+ else
+ {
+ index = Serial_parm(7, &prms); /* codebook gain index */
+
+ dec_gain2_amr_wb(index,
+ 7,
+ code,
+ L_SUBFR,
+ &gain_pit,
+ &L_gain_code,
+ bfi,
+ st->prev_bfi,
+ st->state,
+ unusable_frame,
+ st->vad_hist,
+ st->dec_gain);
+ }
+
+ /* find best scaling to perform on excitation (Q_new) */
+
+ tmp = st->Qsubfr[0];
+ for (i = 1; i < 4; i++)
+ {
+ if (st->Qsubfr[i] < tmp)
+ {
+ tmp = st->Qsubfr[i];
+ }
+ }
+
+ /* limit scaling (Q_new) to Q_MAX: see pv_amr_wb_cnst.h and syn_filt_32() */
+
+ if (tmp > Q_MAX)
+ {
+ tmp = Q_MAX;
+ }
+ Q_new = 0;
+ L_tmp = L_gain_code; /* L_gain_code in Q16 */
+
+
+ while ((L_tmp < 0x08000000L) && (Q_new < tmp))
+ {
+ L_tmp <<= 1;
+ Q_new += 1;
+
+ }
+ gain_code = amr_wb_round(L_tmp); /* scaled gain_code with Qnew */
+
+ scale_signal(exc + i_subfr - (PIT_MAX + L_INTERPOL),
+ PIT_MAX + L_INTERPOL + L_SUBFR,
+ (int16)(Q_new - st->Q_old));
+
+ st->Q_old = Q_new;
+
+
+ /*
+ * Update parameters for the next subframe.
+ * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced)
+ */
+
+
+ if (bfi == 0)
+ {
+ /* LTP-Lag history update */
+ for (i = 4; i > 0; i--)
+ {
+ st->lag_hist[i] = st->lag_hist[i - 1];
+ }
+ st->lag_hist[0] = T0;
+
+ st->old_T0 = T0;
+ st->old_T0_frac = 0; /* Remove fraction in case of BFI */
+ }
+ /* find voice factor in Q15 (1=voiced, -1=unvoiced) */
+
+ /*
+ * Scale down by 1/8
+ */
+ for (i = L_SUBFR - 1; i >= 0; i--)
+ {
+ exc2[i] = (exc[i_subfr + i] + (0x0004 * (exc[i_subfr + i] != MAX_16))) >> 3;
+ }
+
+
+ /* post processing of excitation elements */
+
+ if (nb_bits <= NBBITS_9k)
+ {
+ pit_sharp = shl_int16(gain_pit, 1);
+
+ if (pit_sharp > 16384)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ tmp = mult_int16(exc2[i], pit_sharp);
+ L_tmp = mul_16by16_to_int32(tmp, gain_pit);
+ L_tmp >>= 1;
+ excp[i] = amr_wb_round(L_tmp);
+ }
+ }
+ }
+ else
+ {
+ pit_sharp = 0;
+ }
+
+ voice_fac = voice_factor(exc2, -3, 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;
+
+ /*
+ * - Find the total excitation.
+ * - Find synthesis speech corresponding to exc[].
+ * - Find maximum value of excitation for next scaling
+ */
+
+ pv_memcpy((void *)exc2, (void *)&exc[i_subfr], L_SUBFR*sizeof(*exc2));
+ max = 1;
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ L_tmp = mul_16by16_to_int32(code[i], gain_code);
+ L_tmp = shl_int32(L_tmp, 5);
+ L_tmp = mac_16by16_to_int32(L_tmp, exc[i + i_subfr], gain_pit);
+ L_tmp = shl_int32(L_tmp, 1);
+ tmp = amr_wb_round(L_tmp);
+ exc[i + i_subfr] = tmp;
+ tmp = tmp - (tmp < 0);
+ max |= tmp ^(tmp >> 15); /* |= tmp ^sign(tmp) */
+ }
+
+
+ /* tmp = scaling possible according to max value of excitation */
+ tmp = add_int16(norm_s(max), Q_new) - 1;
+
+ st->Qsubfr[3] = st->Qsubfr[2];
+ st->Qsubfr[2] = st->Qsubfr[1];
+ st->Qsubfr[1] = st->Qsubfr[0];
+ st->Qsubfr[0] = tmp;
+
+ /*
+ * phase dispersion to enhance noise in low bit rate
+ */
+
+
+ if (nb_bits <= NBBITS_7k)
+ {
+ j = 0; /* high dispersion for rate <= 7.5 kbit/s */
+ }
+ else if (nb_bits <= NBBITS_9k)
+ {
+ j = 1; /* low dispersion for rate <= 9.6 kbit/s */
+ }
+ else
+ {
+ j = 2; /* no dispersion for rate > 9.6 kbit/s */
+ }
+
+ /* L_gain_code in Q16 */
+
+ phase_dispersion((int16)(L_gain_code >> 16),
+ gain_pit,
+ code,
+ j,
+ st->disp_mem,
+ ScratchMem);
+
+ /*
+ * 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 = mult_int16(stab_fac, tmp);
+
+ L_tmp = L_gain_code;
+
+ if (L_tmp < st->L_gc_thres)
+ {
+ L_tmp += fxp_mul32_by_16b(L_gain_code, 6226) << 1;
+
+ if (L_tmp > st->L_gc_thres)
+ {
+ L_tmp = st->L_gc_thres;
+ }
+ }
+ else
+ {
+ L_tmp = fxp_mul32_by_16b(L_gain_code, 27536) << 1;
+
+ if (L_tmp < st->L_gc_thres)
+ {
+ L_tmp = st->L_gc_thres;
+ }
+ }
+ st->L_gc_thres = L_tmp;
+
+ L_gain_code = fxp_mul32_by_16b(L_gain_code, (32767 - fac)) << 1;
+
+
+ L_gain_code = add_int32(L_gain_code, fxp_mul32_by_16b(L_tmp, fac) << 1);
+
+ /*
+ * 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 */
+
+ /* build excitation */
+
+ gain_code = amr_wb_round(shl_int32(L_gain_code, Q_new));
+
+ L_tmp = (int32)(code[0] << 16);
+ L_tmp = msu_16by16_from_int32(L_tmp, code[1], tmp);
+ L_tmp = mul_16by16_to_int32(amr_wb_round(L_tmp), gain_code);
+ L_tmp = shl_int32(L_tmp, 5);
+ L_tmp = mac_16by16_to_int32(L_tmp, exc2[0], gain_pit);
+ L_tmp = shl_int32(L_tmp, 1); /* saturation can occur here */
+ exc2[0] = amr_wb_round(L_tmp);
+
+
+ for (i = 1; i < L_SUBFR - 1; i++)
+ {
+ L_tmp = (int32)(code[i] << 16);
+ L_tmp = msu_16by16_from_int32(L_tmp, (code[i + 1] + code[i - 1]), tmp);
+ L_tmp = mul_16by16_to_int32(amr_wb_round(L_tmp), gain_code);
+ L_tmp = shl_int32(L_tmp, 5);
+ L_tmp = mac_16by16_to_int32(L_tmp, exc2[i], gain_pit);
+ L_tmp = shl_int32(L_tmp, 1); /* saturation can occur here */
+ exc2[i] = amr_wb_round(L_tmp);
+ }
+
+ L_tmp = (int32)(code[L_SUBFR - 1] << 16);
+ L_tmp = msu_16by16_from_int32(L_tmp, code[L_SUBFR - 2], tmp);
+ L_tmp = mul_16by16_to_int32(amr_wb_round(L_tmp), gain_code);
+ L_tmp = shl_int32(L_tmp, 5);
+ L_tmp = mac_16by16_to_int32(L_tmp, exc2[L_SUBFR - 1], gain_pit);
+ L_tmp = shl_int32(L_tmp, 1); /* saturation can occur here */
+ exc2[L_SUBFR - 1] = amr_wb_round(L_tmp);
+
+
+
+ if (nb_bits <= NBBITS_9k)
+ {
+ if (pit_sharp > 16384)
+ {
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ excp[i] = add_int16(excp[i], exc2[i]);
+ }
+ agc2_amr_wb(exc2, excp, L_SUBFR);
+ pv_memcpy((void *)exc2, (void *)excp, L_SUBFR*sizeof(*exc2));
+
+ }
+ }
+ if (nb_bits <= NBBITS_7k)
+ {
+ j = i_subfr >> 6;
+ for (i = 0; i < M; i++)
+ {
+ L_tmp = mul_16by16_to_int32(isf_tmp[i], sub_int16(32767, interpol_frac[j]));
+ L_tmp = mac_16by16_to_int32(L_tmp, isf[i], interpol_frac[j]);
+ HfIsf[i] = amr_wb_round(L_tmp);
+ }
+ }
+ else
+ {
+ pv_memset((void *)st->mem_syn_hf,
+ 0,
+ (M16k - M)*sizeof(*st->mem_syn_hf));
+ }
+
+ if (nb_bits >= NBBITS_24k)
+ {
+ corr_gain = Serial_parm(4, &prms);
+ }
+ else
+ {
+ corr_gain = 0;
+ }
+
+ synthesis_amr_wb(p_Aq,
+ exc2,
+ Q_new,
+ &synth16k[i_subfr + (i_subfr>>2)],
+ corr_gain,
+ HfIsf,
+ nb_bits,
+ newDTXState,
+ st,
+ bfi,
+ ScratchMem);
+
+ p_Aq += (M + 1); /* interpolated LPC parameters for next subframe */
+ }
+
+ /*
+ * Update signal for next frame.
+ * -> save past of exc[]
+ * -> save pitch parameters
+ */
+
+ pv_memcpy((void *)st->old_exc,
+ (void *)&old_exc[L_FRAME],
+ (PIT_MAX + L_INTERPOL)*sizeof(*old_exc));
+
+ scale_signal(exc, L_FRAME, (int16)(-Q_new));
+
+ dtx_dec_amr_wb_activity_update(&(st->dtx_decSt), isf, exc);
+
+ st->dtx_decSt.dtxGlobalState = newDTXState;
+
+ st->prev_bfi = bfi;
+
+ return 0;
+}
+
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.h b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.h
new file mode 100644
index 0000000..c40bc10
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder.h
@@ -0,0 +1,158 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+ Name: pvamrwbdecoder.h
+
+ Date: 05/02/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Main header file for the Packet Video AMR Wide Band decoder library. The
+ constants, structures, and functions defined within this file, along with
+ a basic data types header file, is all that is needed to use and communicate
+ with the library. The internal data structures within the library are
+ purposely hidden.
+
+ ---* Need description of the input buffering. *-------
+
+ ---* Need an example of calling the library here *----
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (Normally header files do not have a reference section)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef _PVAMRWBDECODER_H
+#define _PVAMRWBDECODER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_amr_wb_type_defs.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; MACROS
+ ; Define module specific macros here
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+typedef struct
+{
+ int16 prev_ft;
+ int16 prev_mode;
+} RX_State_wb;
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ void pvDecoder_AmrWb_Init(void **spd_state, void *st, int16 ** ScratchMem);
+
+ int32 pvDecoder_AmrWb(
+ int16 mode, /* input : used mode */
+ int16 prms[], /* input : parameter vector */
+ int16 synth16k[], /* output: synthesis speech */
+ int16 * frame_length, /* output: lenght of the frame */
+ void *spd_state, /* i/o : State structure */
+ int16 frame_type, /* input : received frame type */
+ int16 ScratchMem[]
+ );
+
+ void pvDecoder_AmrWb_Reset(void *st, int16 reset_all);
+
+ int16 pvDecoder_AmrWb_homing_frame_test(int16 input_frame[], int16 mode);
+
+ int16 pvDecoder_AmrWb_homing_frame_test_first(int16 input_frame[], int16 mode);
+
+ int32 pvDecoder_AmrWbMemRequirements();
+
+ void mime_unsorting(uint8 packet[],
+ int16 compressed_data[],
+ int16 *frame_type,
+ int16 *mode,
+ uint8 q,
+ RX_State_wb *st);
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* PVMP4AUDIODECODER_API_H */
+
+
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_acelp.h b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_acelp.h
new file mode 100644
index 0000000..5967115
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_acelp.h
@@ -0,0 +1,329 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./cpp/include/pvamrwbdecoder_acelp.h
+
+ Date: 01/04/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PVAMRWBDECODER_ACELP_H
+#define PVAMRWBDECODER_ACELP_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_mem_funcs.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*-----------------------------------------------------------------*
+ * LPC prototypes *
+ *-----------------------------------------------------------------*/
+
+ void isf_extrapolation(int16 HfIsf[]);
+
+ void Init_Lagconc(int16 lag_hist[]);
+ void lagconceal(
+ int16 gain_hist[], /* (i) : Gain history */
+ int16 lag_hist[], /* (i) : Subframe size */
+ int16 * T0,
+ int16 * old_T0,
+ int16 * seed,
+ int16 unusable_frame
+ );
+
+ void agc2_amr_wb(
+ int16 * sig_in, /* input : postfilter input signal */
+ int16 * sig_out, /* in/out: postfilter output signal */
+ int16 l_trm /* input : subframe size */
+ );
+
+ void low_pass_filt_7k_init(int16 mem[]);
+ void low_pass_filt_7k(
+ int16 signal[], /* input: signal */
+ int16 lg, /* input: length of input */
+ int16 mem[], /* in/out: memory (size=30) */
+ int16 x[]
+ );
+
+ int16 median5(int16 x[]);
+
+ void Isp_Az(
+ int16 isp[], /* (i) Q15 : Immittance spectral pairs */
+ int16 a[], /* (o) Q12 : predictor coefficients (order = M) */
+ int16 m,
+ int16 adaptive_scaling /* (i) 0 : adaptive scaling disabled */
+ /* 1 : adaptive scaling enabled */
+ );
+ void Isf_isp(
+ int16 isf[], /* (i) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */
+ int16 isp[], /* (o) Q15 : isp[m] (range: -1<=val<1) */
+ int16 m /* (i) : LPC order */
+ );
+ void interpolate_isp(
+ int16 isp_old[], /* input : isps from past frame */
+ int16 isp_new[], /* input : isps from present frame */
+ const int16 frac[], /* input : fraction for 3 first subfr (Q15) */
+ int16 Az[] /* output: LP coefficients in 4 subframes */
+ );
+ void weight_amrwb_lpc(
+ int16 a[], /* (i) Q12 : a[m+1] LPC coefficients */
+ int16 ap[], /* (o) Q12 : Spectral expanded LPC coefficients */
+ int16 gamma, /* (i) Q15 : Spectral expansion factor. */
+ int16 m /* (i) : LPC order. */
+ );
+
+
+ /*-----------------------------------------------------------------*
+ * isf quantizers *
+ *-----------------------------------------------------------------*/
+
+ void Disf_ns(
+ int16 * indice, /* input: quantization indices */
+ int16 * isf_q /* input : ISF in the frequency domain (0..0.5) */
+ );
+
+ void Dpisf_2s_46b(
+ int16 * indice, /* input: quantization indices */
+ int16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */
+ int16 * past_isfq, /* i/0 : past ISF quantizer */
+ int16 * isfold, /* input : past quantized ISF */
+ int16 * isf_buf, /* input : isf buffer */
+ int16 bfi, /* input : Bad frame indicator */
+ int16 enc_dec
+ );
+ void Dpisf_2s_36b(
+ int16 * indice, /* input: quantization indices */
+ int16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */
+ int16 * past_isfq, /* i/0 : past ISF quantizer */
+ int16 * isfold, /* input : past quantized ISF */
+ int16 * isf_buf, /* input : isf buffer */
+ int16 bfi, /* input : Bad frame indicator */
+ int16 enc_dec
+ );
+
+
+ void Reorder_isf(
+ int16 * isf, /* (i/o) Q15: ISF in the frequency domain (0..0.5) */
+ int16 min_dist, /* (i) Q15 : minimum distance to keep */
+ int16 n /* (i) : number of ISF */
+ );
+
+ /*-----------------------------------------------------------------*
+ * filter prototypes *
+ *-----------------------------------------------------------------*/
+
+ void oversamp_12k8_to_16k_init(
+ int16 mem[] /* output: memory (2*NB_COEF_UP) set to zeros */
+ );
+ void oversamp_12k8_to_16k(
+ int16 sig12k8[], /* input: signal to oversampling */
+ int16 lg, /* input: length of input */
+ int16 sig16k[], /* output: oversampled signal */
+ int16 mem[], /* in/out: memory (2*NB_COEF_UP) */
+ int16 signal[]
+ );
+
+ void highpass_50Hz_at_12k8_init(int16 mem[]);
+ void highpass_50Hz_at_12k8(
+ int16 signal[], /* input/output signal */
+ int16 lg, /* lenght of signal */
+ int16 mem[] /* filter memory [6] */
+ );
+ void highpass_400Hz_at_12k8_init(int16 mem[]);
+ void highpass_400Hz_at_12k8(
+ int16 signal[], /* input/output signal */
+ int16 lg, /* lenght of signal */
+ int16 mem[] /* filter memory [6] */
+ );
+
+ void band_pass_6k_7k_init(int16 mem[]);
+ void band_pass_6k_7k(
+ int16 signal[], /* input: signal */
+ int16 lg, /* input: length of input */
+ int16 mem[], /* in/out: memory (size=30) */
+ int16 x[]
+ );
+
+
+ void preemph_amrwb_dec(
+ int16 x[], /* (i/o) : input signal overwritten by the output */
+ int16 mu, /* (i) Q15 : preemphasis coefficient */
+ int16 lg /* (i) : lenght of filtering */
+ );
+
+ void deemphasis_32(
+ int16 x_hi[], /* (i) : input signal (bit31..16) */
+ int16 x_lo[], /* (i) : input signal (bit15..4) */
+ int16 y[], /* (o) : output signal (x16) */
+ int16 mu, /* (i) Q15 : deemphasis factor */
+ int16 L, /* (i) : vector size */
+ int16 * mem /* (i/o) : memory (y[-1]) */
+ );
+
+
+ void wb_syn_filt(
+ int16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ int16 m, /* (i) : order of LP filter */
+ int16 x[], /* (i) : input signal */
+ int16 y[], /* (o) : output signal */
+ int16 lg, /* (i) : size of filtering */
+ int16 mem[], /* (i/o) : memory associated with this filtering. */
+ int16 update, /* (i) : 0=no update, 1=update of memory. */
+ int16 y_buf[]
+ );
+ void Syn_filt_32(
+ int16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ int16 m, /* (i) : order of LP filter */
+ int16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */
+ int16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */
+ int16 sig_hi[], /* (o) /16 : synthesis high */
+ int16 sig_lo[], /* (o) /16 : synthesis low */
+ int16 lg /* (i) : size of filtering */
+ );
+
+ /*-----------------------------------------------------------------*
+ * pitch prototypes *
+ *-----------------------------------------------------------------*/
+
+
+ void Pred_lt4(
+ int16 exc[], /* in/out: excitation buffer */
+ int16 T0, /* input : integer pitch lag */
+ int16 frac, /* input : fraction of lag */
+ int16 L_subfr /* input : subframe size */
+ );
+
+ /*-----------------------------------------------------------------*
+ * gain prototypes *
+ *-----------------------------------------------------------------*/
+
+
+ void dec_gain2_amr_wb_init(
+ int16 * mem /* output : memory (4 words) */
+ );
+ void dec_gain2_amr_wb(
+ int16 index, /* (i) :index of quantization. */
+ int16 nbits, /* (i) : number of bits (6 or 7) */
+ int16 code[], /* (i) Q9 :Innovative vector. */
+ int16 L_subfr, /* (i) :Subframe lenght. */
+ int16 * gain_pit, /* (o) Q14 :Pitch gain. */
+ int32 * gain_cod, /* (o) Q16 :Code gain. */
+ int16 bfi, /* (i) :bad frame indicator */
+ int16 prev_bfi, /* (i) : Previous BF indicator */
+ int16 state, /* (i) : State of BFH */
+ int16 unusable_frame, /* (i) : UF indicator */
+ int16 vad_hist, /* (i) :number of non-speech frames */
+ int16 * mem /* (i/o) : memory (4 words) */
+ );
+
+ /*-----------------------------------------------------------------*
+ * acelp prototypes *
+ *-----------------------------------------------------------------*/
+
+ void dec_acelp_2p_in_64(
+ int16 index, /* (i) : 12 bits index */
+ int16 code[] /* (o) :Q9 algebraic (fixed) codebook excitation */
+ );
+
+ void dec_acelp_4p_in_64(
+ int16 index[], /* (i) : index (20): 5+5+5+5 = 20 bits. */
+ /* (i) : index (36): 9+9+9+9 = 36 bits. */
+ /* (i) : index (44): 13+9+13+9 = 44 bits. */
+ /* (i) : index (52): 13+13+13+13 = 52 bits. */
+ /* (i) : index (64): 2+2+2+2+14+14+14+14 = 64 bits. */
+ /* (i) : index (72): 10+2+10+2+10+14+10+14 = 72 bits. */
+ /* (i) : index (88): 11+11+11+11+11+11+11+11 = 88 bits. */
+ int16 nbbits, /* (i) : 20, 36, 44, 52, 64, 72 or 88 bits */
+ int16 code[] /* (o) Q9: algebraic (fixed) codebook excitation */
+ );
+ void Pit_shrp(
+ int16 * x, /* in/out: impulse response (or algebraic code) */
+ int16 pit_lag, /* input : pitch lag */
+ int16 sharp, /* input : pitch sharpening factor (Q15) */
+ int16 L_subfr /* input : subframe size */
+ );
+
+
+ /*-----------------------------------------------------------------*
+ * others prototypes *
+ *-----------------------------------------------------------------*/
+
+ int16 voice_factor( /* (o) Q15 : factor (-1=unvoiced to 1=voiced) */
+ int16 exc[], /* (i) Q_exc: pitch excitation */
+ int16 Q_exc, /* (i) : exc format */
+ int16 gain_pit, /* (i) Q14 : gain of pitch */
+ int16 code[], /* (i) Q9 : Fixed codebook excitation */
+ int16 gain_code, /* (i) Q0 : gain of code */
+ int16 L_subfr /* (i) : subframe length */
+ );
+
+ void scale_signal(
+ int16 x[], /* (i/o) : signal to scale */
+ int16 lg, /* (i) : size of x[] */
+ int16 exp /* (i) : exponent: x = round(x << exp) */
+ );
+
+ int16 noise_gen_amrwb(int16 * seed);
+
+
+ void phase_dispersion(
+ int16 gain_code, /* (i) Q0 : gain of code */
+ int16 gain_pit, /* (i) Q14 : gain of pitch */
+ int16 code[], /* (i/o) : code vector */
+ int16 mode, /* (i) : level, 0=hi, 1=lo, 2=off */
+ int16 disp_mem[], /* (i/o) : memory (size = 8) */
+ int16 ScratchMem[]
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ACELP_H */
+
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op.h b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op.h
new file mode 100644
index 0000000..df239d2
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op.h
@@ -0,0 +1,249 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./src/pvamrwbdecoder_basic_op.h
+
+ Date: 05/07/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+
+#ifndef PVAMRWBDECODER_BASIC_OP_H
+#define PVAMRWBDECODER_BASIC_OP_H
+
+
+#include "normalize_amr_wb.h"
+
+
+#define MAX_32 (int32)0x7fffffffL
+#define MIN_32 (int32)0x80000000L
+
+#define MAX_16 (int16)+32767 /* 0x7fff */
+#define MIN_16 (int16)-32768 /* 0x8000 */
+
+
+
+
+/*----------------------------------------------------------------------------
+ Function Name : negate_int16
+
+ Negate var1 with saturation, saturate in the case where input is -32768:
+ negate(var1) = sub(0,var1).
+
+ Inputs :
+ var1
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0x8000 <= var1 <= 0x7fff.
+
+ Outputs :
+ none
+
+ Return Value :
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0x8000 <= var_out <= 0x7fff.
+ ----------------------------------------------------------------------------*/
+
+__inline int16 negate_int16(int16 var1)
+{
+ return (((var1 == MIN_16) ? MAX_16 : -var1));
+}
+
+
+/*----------------------------------------------------------------------------
+
+ Function Name : shl_int16
+
+ 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.
+
+ Inputs :
+ var1
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0x8000 <= var1 <= 0x7fff.
+
+ var2
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0x8000 <= var1 <= 0x7fff.
+
+ Return Value :
+ var_out
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0x8000 <= var_out <= 0x7fff.
+ ----------------------------------------------------------------------------*/
+
+__inline int16 shl_int16(int16 var1, int16 var2)
+{
+ int16 var_out;
+
+ if (var2 < 0)
+ {
+ var2 = (-var2) & (0xf);
+ var_out = var1 >> var2;
+ }
+ else
+ {
+ var2 &= 0xf;
+ var_out = var1 << var2;
+ if (var_out >> var2 != var1)
+ {
+ var_out = (var1 >> 15) ^ MAX_16;
+ }
+ }
+ return (var_out);
+}
+
+
+/*----------------------------------------------------------------------------
+
+ Function Name : shl_int32
+
+ 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.
+
+ Inputs :
+ L_var1 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ var2
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 8000 <= var2 <= 7fff.
+ Return Value :
+ 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+
+ ----------------------------------------------------------------------------*/
+
+__inline int32 shl_int32(int32 L_var1, int16 var2)
+{
+ int32 L_var_out;
+
+ if (var2 > 0)
+ {
+ L_var_out = L_var1 << var2;
+ if (L_var_out >> var2 != L_var1)
+ {
+ L_var_out = (L_var1 >> 31) ^ MAX_32;
+ }
+ }
+ else
+ {
+ var2 = (-var2) & (0xf);
+ L_var_out = L_var1 >> var2;
+ }
+
+ return (L_var_out);
+}
+
+
+/*----------------------------------------------------------------------------
+
+ Function Name : shr_int32
+
+ 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.
+
+ Inputs :
+ L_var1 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ var2
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 8000 <= var2 <= 7fff.
+ Return Value :
+ 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+
+ ----------------------------------------------------------------------------*/
+
+__inline int32 shr_int32(int32 L_var1, int16 var2)
+{
+ int32 L_var_out;
+
+ if (var2 >= 0)
+ {
+ L_var_out = L_var1 >> (var2 & 0x1f);
+ }
+ else
+ {
+ var2 = (int16)(-var2);
+ var2 &= 0x1f;
+ L_var_out = L_var1 << var2;
+ if (L_var_out >> var2 != L_var1)
+ {
+ L_var_out = (L_var1 >> 31) ^ MAX_32;
+ }
+
+ }
+ return (L_var_out);
+}
+
+
+
+
+
+
+#if defined(PV_ARM_V5)
+
+#include "pvamrwbdecoder_basic_op_armv5.h"
+
+#elif defined(PV_ARM_GCC_V5)
+
+#include "pvamrwbdecoder_basic_op_gcc_armv5.h"
+
+#else
+
+#ifndef C_EQUIVALENT
+#define C_EQUIVALENT // default to C_EQUIVALENT
+#endif
+
+#include "pvamrwbdecoder_basic_op_cequivalent.h"
+
+#endif
+
+
+#endif /* PVAMRWBDECODER_BASIC_OP_H */
+
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_armv5.h b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_armv5.h
new file mode 100644
index 0000000..c800a2e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_armv5.h
@@ -0,0 +1,253 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./src/pvamrwbdecoder_basic_op_armv5.h
+
+ Date: 05/07/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PVAMRWBDECODER_BASIC_OP_ARMV5_H
+#define PVAMRWBDECODER_BASIC_OP_ARMV5_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+
+
+
+#if defined(PV_ARM_V5)
+
+ __inline int16 add_int16(int16 var1, int16 var2)
+ {
+ int32 L_var_out;
+ int32 L_var_aux;
+
+ __asm
+ {
+ mov L_var_out, var1, lsl #16
+ mov L_var_aux, var2, lsl #16
+ qadd L_var_out, L_var_out, L_var_aux
+ mov L_var_out, L_var_out, asr #16
+
+ }
+ return L_var_out;
+ }
+
+
+ __inline int16 sub_int16(int16 var1, int16 var2)
+ {
+ int32 L_var_out;
+ int32 L_var_aux;
+
+ __asm
+ {
+ mov L_var_out, var1, lsl #16
+ mov L_var_aux, var2, lsl #16
+ qsub L_var_out, L_var_out, L_var_aux
+ mov L_var_out, L_var_out, asr #16
+
+ }
+ return L_var_out;
+ }
+
+
+ __inline int32 add_int32(int32 L_var1, int32 L_var2)
+ {
+ int32 L_var_out;
+
+ __asm
+ {
+ qadd L_var_out, L_var1, L_var2
+ }
+ return L_var_out;
+ }
+
+
+ __inline int32 mac_16by16_to_int32(int32 L_var3, int16 var1, int16 var2)
+ {
+ int32 L_var_out;
+
+
+ __asm
+ {
+ smulbb L_var_out, var1, var2
+ qdadd L_var_out, L_var3, L_var_out
+ }
+ return L_var_out;
+ }
+
+ __inline int32 sub_int32(int32 L_var1, int32 L_var2)
+ {
+ int32 L_var_out;
+
+ __asm
+ {
+ qsub L_var_out, L_var1, L_var2
+ }
+ return L_var_out;
+ }
+
+ __inline int32 msu_16by16_from_int32(int32 L_var3, int16 var1, int16 var2)
+ {
+ int32 L_var_out;
+
+
+ __asm
+ {
+ smulbb L_var_out, var1, var2
+ qdsub L_var_out, L_var3, L_var_out
+ }
+ return L_var_out;
+ }
+
+ __inline int32 mul_16by16_to_int32(int16 var1, int16 var2)
+ {
+ int32 L_var_out;
+
+ __asm
+ {
+ smulbb L_var_out, var1, var2
+ qadd L_var_out, L_var_out, L_var_out
+ }
+ return L_var_out;
+ }
+
+ __inline int16 mult_int16(int16 var1, int16 var2)
+ {
+ int32 L_var_out;
+
+ __asm
+ {
+ smulbb L_var_out, var1, var2
+ mov L_var_out, L_var_out, asr #15
+ }
+ return L_var_out;
+ }
+
+
+ __inline int16 amr_wb_round(int32 L_var1)
+ {
+ int32 L_var_out;
+
+ __asm
+ {
+ qadd L_var_out, L_var1, (int32) 0x00008000L
+ mov L_var_out, L_var_out, asr #16
+ }
+ return L_var_out;
+ }
+
+
+
+ __inline int16 amr_wb_shl1_round(int32 L_var1)
+ {
+ int32 L_var_out;
+
+ __asm
+ {
+ qadd L_var_out, L_var1, L_var1
+ qadd L_var_out, L_var_out, (int32) 0x00008000L
+ mov L_var_out, L_var_out, asr #16
+ }
+ return L_var_out;
+ }
+
+ __inline int32 mul_32by16(int16 hi, int16 lo, int16 n)
+ {
+ int32 H_32;
+ int32 L_32;
+ __asm
+ {
+ smulbb H_32, hi, n
+ smulbb L_32, lo, n
+ add H_32, H_32, L_32, asr #15
+ qadd H_32, H_32, H_32
+ }
+
+ return (H_32);
+ }
+
+ __inline int32 fxp_mac_16by16(const int16 var1, const int16 var2, int32 L_add)
+ {
+ __asm
+ {
+ smlabb L_add, var1, var2, L_add
+ }
+ return (L_add);
+ }
+
+ __inline int32 fxp_mul_16by16(int16 var1, const int16 var2)
+ {
+ int32 L_mult;
+ __asm
+ {
+ smulbb L_mult, var1, var2
+ }
+ return (L_mult);
+ }
+
+ __inline int32 fxp_mul32_by_16b(int32 L_var1, const int32 L_var2)
+ {
+ int32 L_mult;
+ __asm
+ {
+ smulwb L_mult, L_var1, L_var2
+ }
+
+ return L_mult;
+ }
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+#endif /* PVAMRWBDECODER_BASIC_OP_ARMV5_H */
+
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_cequivalent.h b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_cequivalent.h
new file mode 100644
index 0000000..7fd680d
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_cequivalent.h
@@ -0,0 +1,545 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./src/pvamrwbdecoder_basic_op_cequivalent.h
+
+ Date: 05/07/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+#ifndef PVAMRWBDECODER_BASIC_OP_CEQUIVALENT_H
+#define PVAMRWBDECODER_BASIC_OP_CEQUIVALENT_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#include "normalize_amr_wb.h"
+
+#if defined(C_EQUIVALENT)
+
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : add_int16
+
+ 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.
+
+ Inputs :
+ var1
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ var2
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ Outputs :
+ none
+
+ Return Value :
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var_out <= 0x0000 7fff.
+
+ ----------------------------------------------------------------------------*/
+ __inline int16 add_int16(int16 var1, int16 var2)
+ {
+ int32 L_sum;
+
+ L_sum = (int32) var1 + var2;
+ if ((L_sum >> 15) != (L_sum >> 31))
+ {
+ L_sum = (L_sum >> 31) ^ MAX_16;
+ }
+ return ((int16)(L_sum));
+ }
+
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : sub_int16
+
+ 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.
+
+ Inputs :
+
+ var1
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ var2
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ Outputs :
+ none
+
+ Return Value :
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var_out <= 0x0000 7fff.
+
+ ----------------------------------------------------------------------------*/
+ __inline int16 sub_int16(int16 var1, int16 var2)
+ {
+ int32 L_diff;
+
+ L_diff = (int32) var1 - var2;
+ if ((L_diff >> 15) != (L_diff >> 31))
+ {
+ L_diff = (L_diff >> 31) ^ MAX_16;
+ }
+ return ((int16)(L_diff));
+ }
+
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : mult_int16
+
+ Performs the multiplication of var1 by var2 and gives a 16 bit result
+ which is scaled i.e.:
+ mult_int16(var1,var2) = extract_l(L_shr((var1 times var2),15)) and
+ mult_int16(-32768,-32768) = 32767.
+
+ Inputs :
+ var1
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ var2
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+
+ Return Value :
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var_out <= 0x0000 7fff.
+
+ ----------------------------------------------------------------------------*/
+
+ __inline int16 mult_int16(int16 var1, int16 var2)
+ {
+ int32 L_product;
+
+ L_product = ((int32) var1 * (int32) var2) >> 15;
+
+ if ((L_product >> 15) != (L_product >> 31))
+ {
+ L_product = (L_product >> 31) ^ MAX_16;
+ }
+
+ return ((int16)L_product);
+ }
+
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : add_int32
+
+ 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.
+
+ Inputs :
+
+ L_var1 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+
+ L_var2 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+
+
+ Return Value :
+ L_var_out
+ 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+
+ ----------------------------------------------------------------------------*/
+
+
+ __inline int32 add_int32(int32 L_var1, int32 L_var2)
+ {
+ int32 L_var_out;
+
+ L_var_out = L_var1 + L_var2;
+
+ if (((L_var1 ^ L_var2) & MIN_32) == 0) /* same sign ? */
+ {
+ if ((L_var_out ^ L_var1) & MIN_32) /* addition matches sign ? */
+ {
+ L_var_out = (L_var1 >> 31) ^ MAX_32;
+ }
+ }
+ return (L_var_out);
+ }
+
+
+
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : sub_int32
+
+ 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.
+
+ Inputs :
+
+ L_var1 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+
+ L_var2 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+
+
+ Return Value :
+ L_var_out
+ 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+
+ ----------------------------------------------------------------------------*/
+
+
+ __inline int32 sub_int32(int32 L_var1, int32 L_var2)
+ {
+ int32 L_var_out;
+
+ L_var_out = L_var1 - L_var2;
+
+ if (((L_var1 ^ L_var2) & MIN_32) != 0) /* different sign ? */
+ {
+ if ((L_var_out ^ L_var1) & MIN_32) /* difference matches sign ? */
+ {
+ L_var_out = (L_var1 >> 31) ^ MAX_32;
+ }
+ }
+ return (L_var_out);
+ }
+
+
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : mac_16by16_to_int32
+
+ 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)).
+
+ Inputs :
+
+ L_var3 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+
+ var1
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ var2
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+
+ Return Value :
+ 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+
+ ----------------------------------------------------------------------------*/
+
+
+ __inline int32 mac_16by16_to_int32(int32 L_var3, int16 var1, int16 var2)
+ {
+ int32 L_var_out;
+ int32 L_mul;
+
+ L_mul = ((int32) var1 * (int32) var2);
+
+ if (L_mul != 0x40000000)
+ {
+ L_mul <<= 1;
+ }
+ else
+ {
+ L_mul = MAX_32; /* saturation */
+ }
+
+ L_var_out = L_var3 + L_mul;
+
+ if (((L_mul ^ L_var3) & MIN_32) == 0) /* same sign ? */
+ {
+ if ((L_var_out ^ L_var3) & MIN_32) /* addition matches sign ? */
+ {
+ L_var_out = (L_var3 >> 31) ^ MAX_32;
+ }
+ }
+
+ return (L_var_out);
+ }
+
+
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : msu_16by16_from_int32
+
+ 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)).
+
+ Inputs :
+
+ L_var3 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.
+
+ var1
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ var2
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+
+ Return Value :
+ 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+
+ ----------------------------------------------------------------------------*/
+
+ __inline int32 msu_16by16_from_int32(int32 L_var3, int16 var1, int16 var2)
+ {
+ int32 L_var_out;
+ int32 L_mul;
+
+ L_mul = ((int32) var1 * (int32) var2);
+
+ if (L_mul != 0x40000000)
+ {
+ L_mul <<= 1;
+ }
+ else
+ {
+ L_mul = MAX_32; /* saturation */
+ }
+
+ L_var_out = L_var3 - L_mul;
+
+ if (((L_mul ^ L_var3) & MIN_32) != 0) /* different sign ? */
+ {
+ if ((L_var_out ^ L_var3) & MIN_32) /* difference matches sign ? */
+ {
+ L_var_out = (L_var3 >> 31) ^ MAX_32;
+ }
+ }
+
+ return (L_var_out);
+ }
+
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : mul_16by16_to_int32
+
+ mul_16by16_to_int32 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.
+
+ Inputs :
+ var1
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ var2
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var1 <= 0x0000 7fff.
+
+ Return Value :
+ 32 bit long signed integer (int32) whose value falls in the
+ range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.
+
+ ----------------------------------------------------------------------------*/
+
+
+ __inline int32 mul_16by16_to_int32(int16 var1, int16 var2)
+ {
+ int32 L_mul;
+
+ L_mul = ((int32) var1 * (int32) var2);
+
+ if (L_mul != 0x40000000)
+ {
+ L_mul <<= 1;
+ }
+ else
+ {
+ L_mul = MAX_32; /* saturation */
+ }
+
+ return (L_mul);
+
+ }
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : amr_wb_round
+
+ 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))
+
+ Inputs :
+ L_var1
+ 32 bit long signed integer (int32 ) whose value falls in the
+ range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ Return Value :
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var_out <= 0x0000 7fff.
+
+ ----------------------------------------------------------------------------*/
+ __inline int16 amr_wb_round(int32 L_var1)
+ {
+ if (L_var1 != MAX_32)
+ {
+ L_var1 += 0x00008000L;
+ }
+ return ((int16)(L_var1 >> 16));
+ }
+
+
+ /*----------------------------------------------------------------------------
+
+ Function Name : amr_wb_shl1_round
+
+ Shift the 32 bit input number to the left by 1, round up the result and
+ shift down by 16
+ amr_wb_shl1_round(L_var1) = round(L_shl(L_var1,1))
+
+ Inputs :
+ L_var1
+ 32 bit long signed integer (int32 ) whose value falls in the
+ range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.
+
+ Return Value :
+ 16 bit short signed integer (int16) whose value falls in the
+ range : 0xffff 8000 <= var_out <= 0x0000 7fff.
+
+ ----------------------------------------------------------------------------*/
+ __inline int16 amr_wb_shl1_round(int32 L_var1)
+ {
+ int16 var_out;
+
+ if ((L_var1 << 1) >> 1 == L_var1)
+ {
+ var_out = (int16)((L_var1 + 0x00004000) >> 15);
+ }
+ else
+ {
+ var_out = (int16)(((L_var1 >> 31) ^ MAX_32) >> 16);
+ }
+
+ return (var_out);
+ }
+
+ /*----------------------------------------------------------------------------
+ Function Name : mul_32by16
+
+ 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
+
+ Inputs :
+
+ hi hi part of 32 bit number.
+ lo lo part of 32 bit number.
+ n 16 bit number.
+
+ ----------------------------------------------------------------------------*/
+
+
+ __inline int32 mul_32by16(int16 hi, int16 lo, int16 n)
+ {
+ return (((((int32)hi*n)) + ((((int32)lo*n) >> 15))) << 1);
+ }
+
+ __inline int32 fxp_mac_16by16(int16 var1, int16 var2, int32 L_add)
+ {
+
+ L_add += (int32)var1 * var2;
+
+ return L_add;
+ }
+
+ __inline int32 fxp_mul_16by16(int16 var1, const int16 var2)
+ {
+ int32 L_mul = (int32)var1 * var2;
+
+ return L_mul;
+ }
+
+ __inline int32 fxp_mul32_by_16b(int32 L_var1, const int32 L_var2)
+ {
+
+ int32 L_mul = (int32)(((int64)L_var1 * (L_var2 << 16)) >> 32);
+
+ return L_mul;
+ }
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif /* PVAMRWBDECODER_BASIC_OP_CEQUIVALENT_H */
+
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_gcc_armv5.h b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_gcc_armv5.h
new file mode 100644
index 0000000..741b584
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_basic_op_gcc_armv5.h
@@ -0,0 +1,319 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./src/pvamrwbdecoder_basic_op_gcc_armv5.h
+
+ Date: 05/07/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PVAMRWBDECODER_BASIC_OP_GCC_ARMV5_H
+#define PVAMRWBDECODER_BASIC_OP_GCC_ARMV5_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#if (defined(PV_ARM_GCC_V5)||defined(PV_ARM_GCC_V4))
+
+ static inline int16 sub_int16(int16 var1, int16 var2)
+ {
+ register int32 L_var_out;
+ register int32 L_var_aux;
+ register int32 ra = (int32)var1;
+ register int32 rb = (int32)var2;
+
+ asm volatile(
+ "mov %0, %2, lsl #16\n"
+ "mov %1, %3, lsl #16\n"
+ "qsub %0, %0, %1\n"
+ "mov %0, %0, asr #16"
+ : "=&r*i"(L_var_out),
+ "=&r*i"(L_var_aux)
+ : "r"(ra),
+ "r"(rb));
+
+ return (int16)L_var_out;
+
+ }
+
+ static inline int16 add_int16(int16 var1, int16 var2)
+{
+ register int32 L_var_out;
+ register int32 L_var_aux;
+ register int32 ra = (int32)var1;
+ register int32 rb = (int32)var2;
+
+ asm volatile(
+ "mov %0, %2, lsl #16\n"
+ "mov %1, %3, lsl #16\n"
+ "qadd %0, %0, %1\n"
+ "mov %0, %0, asr #16"
+ : "=&r*i"(L_var_out),
+ "=&r*i"(L_var_aux)
+ : "r"(ra),
+ "r"(rb));
+
+ return (int16)L_var_out;
+
+ }
+
+ static inline int32 mul_32by16(int16 hi, int16 lo, int16 n)
+{
+ register int32 H_32;
+ register int32 L_32;
+ register int32 ra = (int32)hi;
+ register int32 rb = (int32)lo;
+ register int32 rc = (int32)n;
+
+
+ asm volatile(
+ "smulbb %0, %2, %4\n"
+ "smulbb %1, %3, %4\n"
+ "add %0, %0, %1, asr #15\n"
+ "qadd %0, %0, %0"
+ : "=&r*i"(H_32),
+ "=&r*i"(L_32)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return H_32;
+ }
+
+
+ static inline int32 sub_int32(int32 L_var1, int32 L_var2)
+{
+ register int32 L_var_out;
+ register int32 ra = L_var1;
+ register int32 rb = L_var2;
+
+ asm volatile(
+ "qsub %0, %1, %2"
+ : "=&r*i"(L_var_out)
+ : "r"(ra),
+ "r"(rb));
+
+ return L_var_out;
+ }
+
+ static inline int32 add_int32(int32 L_var1, int32 L_var2)
+{
+ register int32 L_var_out;
+ register int32 ra = L_var1;
+ register int32 rb = L_var2;
+
+ asm volatile(
+ "qadd %0, %1, %2"
+ : "=&r*i"(L_var_out)
+ : "r"(ra),
+ "r"(rb));
+
+ return L_var_out;
+ }
+
+ static inline int32 msu_16by16_from_int32(int32 L_var3, int16 var1, int16 var2)
+{
+ register int32 L_var_out;
+ register int32 ra = (int32)var1;
+ register int32 rb = (int32)var2;
+ register int32 rc = L_var3;
+
+ asm volatile(
+ "smulbb %0, %1, %2\n"
+ "qdsub %0, %3, %0"
+ : "=&r*i"(L_var_out)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return L_var_out;
+ }
+
+
+ static inline int32 mac_16by16_to_int32(int32 L_var3, int16 var1, int16 var2)
+{
+ register int32 L_var_out;
+ register int32 ra = (int32)var1;
+ register int32 rb = (int32)var2;
+ register int32 rc = L_var3;
+
+ asm volatile(
+ "smulbb %0, %1, %2\n"
+ "qdadd %0, %3, %0"
+ : "=&r*i"(L_var_out)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return L_var_out;
+ }
+
+
+ static inline int32 mul_16by16_to_int32(int16 var1, int16 var2)
+{
+ register int32 L_var_out;
+ register int32 ra = (int32)var1;
+ register int32 rb = (int32)var2;
+
+ asm volatile(
+ "smulbb %0, %1, %2\n"
+ "qadd %0, %0, %0"
+ : "=&r*i"(L_var_out)
+ : "r"(ra),
+ "r"(rb));
+
+ return L_var_out;
+ }
+
+
+ static inline int16 mult_int16(int16 var1, int16 var2)
+{
+ register int32 L_var_out;
+ register int32 ra = (int32)var1;
+ register int32 rb = (int32)var2;
+
+ asm volatile(
+ "smulbb %0, %1, %2\n"
+ "mov %0, %0, asr #15"
+ : "=&r*i"(L_var_out)
+ : "r"(ra),
+ "r"(rb));
+
+ return (int16)L_var_out;
+ }
+
+ static inline int16 amr_wb_round(int32 L_var1)
+{
+ register int32 L_var_out;
+ register int32 ra = (int32)L_var1;
+ register int32 rb = (int32)0x00008000L;
+
+ asm volatile(
+ "qadd %0, %1, %2\n"
+ "mov %0, %0, asr #16"
+ : "=&r*i"(L_var_out)
+ : "r"(ra),
+ "r"(rb));
+ return (int16)L_var_out;
+ }
+
+ static inline int16 amr_wb_shl1_round(int32 L_var1)
+{
+ register int32 L_var_out;
+ register int32 ra = (int32)L_var1;
+ register int32 rb = (int32)0x00008000L;
+
+ asm volatile(
+ "qadd %0, %1, %1\n"
+ "qadd %0, %0, %2\n"
+ "mov %0, %0, asr #16"
+ : "=&r*i"(L_var_out)
+ : "r"(ra),
+ "r"(rb));
+ return (int16)L_var_out;
+ }
+
+
+ static inline int32 fxp_mac_16by16(const int16 L_var1, const int16 L_var2, int32 L_add)
+{
+ register int32 tmp;
+ register int32 ra = (int32)L_var1;
+ register int32 rb = (int32)L_var2;
+ register int32 rc = (int32)L_add;
+
+ asm volatile(
+ "smlabb %0, %1, %2, %3"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+ return (tmp);
+ }
+
+ static inline int32 fxp_mul_16by16bb(int16 L_var1, const int16 L_var2)
+{
+ register int32 tmp;
+ register int32 ra = (int32)L_var1;
+ register int32 rb = (int32)L_var2;
+
+ asm volatile(
+ "smulbb %0, %1, %2"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb));
+ return (tmp);
+ }
+
+
+#define fxp_mul_16by16(a, b) fxp_mul_16by16bb( a, b)
+
+
+ static inline int32 fxp_mul32_by_16(int32 L_var1, const int32 L_var2)
+{
+ register int32 tmp;
+ register int32 ra = (int32)L_var1;
+ register int32 rb = (int32)L_var2;
+
+ asm volatile(
+ "smulwb %0, %1, %2"
+ : "=&r*i"(tmp)
+ : "r"(ra),
+ "r"(rb));
+ return (tmp);
+ }
+
+#define fxp_mul32_by_16b( a, b) fxp_mul32_by_16( a, b)
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+#endif /* PVAMRWBDECODER_BASIC_OP_GCC_ARMV5_H */
+
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_cnst.h b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_cnst.h
new file mode 100644
index 0000000..ecf1bf3
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_cnst.h
@@ -0,0 +1,142 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+ Name: pvamrwbdecoder_cnst.h
+
+ Date: 05/02/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Main header file for the Packet Video AMR Wide Band decoder library. The
+ constants, structures, and functions defined within this file, along with
+ a basic data types header file, is all that is needed to use and communicate
+ with the library. The internal data structures within the library are
+ purposely hidden.
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ (Normally header files do not have a reference section)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+
+#ifndef PVAMRWBDECODER_CNST_H
+#define PVAMRWBDECODER_CNST_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+#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 (int16)0x0008 /* homing frame pattern */
+
+#define BIT_0 (int16)-127
+#define BIT_1 (int16)127
+#define BIT_0_ITU (int16)0x007F
+#define BIT_1_ITU (int16)0x0081
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+#endif
diff --git a/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_mem_funcs.h b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_mem_funcs.h
new file mode 100644
index 0000000..e348916
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/pvamrwbdecoder_mem_funcs.h
@@ -0,0 +1,67 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: pvamrwbdecoder_mem_funcs.h
+ Funtions:
+
+
+ Date: 05/04/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+
+#ifndef PVAMRWBDECODER_MEM_FUNCS_H
+#define PVAMRWBDECODER_MEM_FUNCS_H
+
+#include <string.h>
+
+
+#define pv_memset(to, c, n) memset(to, c, n)
+
+
+#define pv_memcpy(to, from, n) memcpy(to, from, n)
+#define pv_memmove(to, from, n) memmove(to, from, n)
+#define pv_memcmp(p, q, n) memcmp(p, q, n)
+
+
+
+#endif
diff --git a/media/libstagefright/codecs/amrwb/src/q_gain2_tab.cpp b/media/libstagefright/codecs/amrwb/src/q_gain2_tab.cpp
new file mode 100644
index 0000000..92c235f
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/q_gain2_tab.cpp
@@ -0,0 +1,244 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+#include "qisf_ns.h"
+
+
+/*
+ * Tables for function q_gain2()
+ *
+ * g_pitch(Q14), g_code(Q11)
+ *
+ * pitch gain are ordered in table to reduce complexity
+ * during quantization of gains.
+ */
+
+
+
+
+const int16 t_qua_gain6b[NB_QUA_GAIN6B*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
+};
+
+const int16 t_qua_gain7b[NB_QUA_GAIN7B*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/amrwb/src/q_pulse.h b/media/libstagefright/codecs/amrwb/src/q_pulse.h
new file mode 100644
index 0000000..0ac52b3
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/q_pulse.h
@@ -0,0 +1,79 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./cpp/include/q_pulse.h
+
+ Date: 01/04/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ Coding and decoding of algebraic codebook
+------------------------------------------------------------------------------
+*/
+
+#ifndef Q_PULSE_H
+#define Q_PULSE_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ void dec_1p_N1(int32 index, int16 N, int16 offset, int16 pos[]);
+ void dec_2p_2N1(int32 index, int16 N, int16 offset, int16 pos[]);
+ void dec_3p_3N1(int32 index, int16 N, int16 offset, int16 pos[]);
+ void dec_4p_4N1(int32 index, int16 N, int16 offset, int16 pos[]);
+ void dec_4p_4N(int32 index, int16 N, int16 offset, int16 pos[]);
+ void dec_5p_5N(int32 index, int16 N, int16 offset, int16 pos[]);
+ void dec_6p_6N_2(int32 index, int16 N, int16 offset, int16 pos[]);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Q_PULSE_H */
diff --git a/media/libstagefright/codecs/amrwb/src/qisf_ns.cpp b/media/libstagefright/codecs/amrwb/src/qisf_ns.cpp
new file mode 100644
index 0000000..07e342b
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/qisf_ns.cpp
@@ -0,0 +1,145 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: qisf_ns.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 indice[] : indices of the selected codebook entries
+ int16 isf[] : quantized ISFs (in frequency domain)
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Coding/Decoding of ISF parameters for background noise.
+
+ The ISF vector is quantized using VQ with split-by-5
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_acelp.h"
+#include "qisf_ns.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void Disf_ns(
+ int16 * indice, /* input: quantization indices */
+ int16 * isf_q /* input: ISF in the frequency domain (0..0.5)*/
+)
+{
+ int16 i;
+
+ isf_q[0] = dico1_isf_noise[(indice[0] << 1)];
+ isf_q[1] = dico1_isf_noise[(indice[0] << 1) + 1];
+
+ for (i = 0; i < 3; i++)
+ {
+ isf_q[i + 2] = dico2_isf_noise[(indice[1] << 1) + indice[1] + i];
+ isf_q[i + 5] = dico3_isf_noise[(indice[2] << 1) + indice[2] + i];
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ isf_q[i + 8] = dico4_isf_noise[(indice[3] << 2) + i];
+ isf_q[i + 12] = dico5_isf_noise[(indice[4] << 2) + i];
+ }
+
+ for (i = 0; i < ORDER; i++)
+ {
+ isf_q[i] = add_int16(isf_q[i], mean_isf_noise[i]);
+ }
+
+ Reorder_isf(isf_q, ISF_GAP, ORDER);
+
+}
diff --git a/media/libstagefright/codecs/amrwb/src/qisf_ns.h b/media/libstagefright/codecs/amrwb/src/qisf_ns.h
new file mode 100644
index 0000000..4e9f67e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/qisf_ns.h
@@ -0,0 +1,113 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./cpp/include/qisf_ns.h
+
+ Date: 01/04/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef QISF_NS_H
+#define QISF_NS_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; DEFINES
+----------------------------------------------------------------------------*/
+
+
+#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
+
+#define NB_QUA_GAIN6B 64 /* Number of quantization level */
+#define NB_QUA_GAIN7B 128 /* Number of quantization level */
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+----------------------------------------------------------------------------*/
+extern const int16 mean_isf_noise[ORDER];
+extern const int16 dico1_isf_noise[SIZE_BK_NOISE1*2];
+extern const int16 dico2_isf_noise[SIZE_BK_NOISE2*3];
+extern const int16 dico3_isf_noise[SIZE_BK_NOISE3*3];
+extern const int16 dico4_isf_noise[SIZE_BK_NOISE4*4];
+extern const int16 dico5_isf_noise[SIZE_BK_NOISE5*4];
+
+extern const int16 t_qua_gain6b[NB_QUA_GAIN6B*2];
+extern const int16 t_qua_gain7b[NB_QUA_GAIN7B*2];
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+#endif /* QISF_NS_H */
diff --git a/media/libstagefright/codecs/amrwb/src/qisf_ns_tab.cpp b/media/libstagefright/codecs/amrwb/src/qisf_ns_tab.cpp
new file mode 100644
index 0000000..e5630e8
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/qisf_ns_tab.cpp
@@ -0,0 +1,367 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+ * qisf_ns_tab.cpp
+ *
+ * Quantization tables for split by 5 VQ of ISFs for a background
+ * noise database
+ * Version whith no prediction
+ */
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "qisf_ns.h"
+
+
+/* means of ISFs */
+const int16 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
+ */
+
+
+const int16 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
+ */
+
+const int16 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
+ */
+
+const int16 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
+ */
+
+const int16 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
+ */
+
+const int16 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/amrwb/src/qpisf_2s.cpp b/media/libstagefright/codecs/amrwb/src/qpisf_2s.cpp
new file mode 100644
index 0000000..0d465c6
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/qpisf_2s.cpp
@@ -0,0 +1,350 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: qpisf_2s.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 * seed seed for the random ng
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Coding/Decoding of ISF parameters with prediction.
+
+ 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.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+
+#include "qisf_ns.h"
+#include "qpisf_2s.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#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 */
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+/*-------------------------------------------------------------------*
+ * routine: Disf_2s_46b() *
+ * ~~~~~~~~~ *
+ * Decoding of ISF parameters *
+ *-------------------------------------------------------------------*/
+
+void Dpisf_2s_46b(
+ int16 * indice, /* input: quantization indices */
+ int16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */
+ int16 * past_isfq,/* i/0 : past ISF quantizer */
+ int16 * isfold, /* input : past quantized ISF */
+ int16 * isf_buf, /* input : isf buffer */
+ int16 bfi, /* input : Bad frame indicator */
+ int16 enc_dec
+)
+{
+ int16 ref_isf[M];
+ int16 i, j, tmp;
+ int32 L_tmp;
+
+
+ if (bfi == 0) /* Good frame */
+ {
+ for (i = 0; i < 9; i++)
+ {
+ isf_q[i] = dico1_isf[(indice[0] << 3) + indice[0] + i];
+ }
+ for (i = 0; i < 7; i++)
+ {
+ isf_q[i + 9] = dico2_isf[(indice[1] << 3) - indice[1] + i];
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ isf_q[i] += dico21_isf[indice[2] * 3 + i];
+ isf_q[i + 3] += dico22_isf[indice[3] * 3 + i];
+ isf_q[i + 6] += dico23_isf[indice[4] * 3 + i];
+ isf_q[i + 9] += dico24_isf[indice[5] * 3 + i];
+ isf_q[i + 12] += dico25_isf[(indice[6] << 2) + i];
+ }
+
+ isf_q[i + 12] += dico25_isf[(indice[6] << 2) + i];
+
+ for (i = 0; i < ORDER; i++)
+ {
+ tmp = isf_q[i];
+ isf_q[i] += mean_isf[i];
+ isf_q[i] += ((int32)MU * past_isfq[i]) >> 15;
+ 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 = mul_16by16_to_int32(mean_isf[i], 8192);
+ for (j = 0; j < L_MEANBUF; j++)
+ {
+ L_tmp = mac_16by16_to_int32(L_tmp, isf_buf[j * M + i], 8192);
+ }
+ ref_isf[i] = amr_wb_round(L_tmp);
+ }
+
+ /* use the past ISFs slightly shifted towards their mean */
+ for (i = 0; i < ORDER; i++)
+ {
+ isf_q[i] = add_int16(mult_int16(ALPHA, isfold[i]), mult_int16(ONE_ALPHA, ref_isf[i]));
+ }
+
+ /* estimate past quantized residual to be used in next frame */
+
+ for (i = 0; i < ORDER; i++)
+ {
+ tmp = add_int16(ref_isf[i], mult_int16(past_isfq[i], MU)); /* predicted ISF */
+ past_isfq[i] = sub_int16(isf_q[i], tmp);
+ past_isfq[i] >>= 1; /* past_isfq[i] *= 0.5 */
+ }
+
+ }
+
+ Reorder_isf(isf_q, ISF_GAP, ORDER);
+}
+
+/*
+ * routine: Disf_2s_36b()
+ * ~~~~~~~~~
+ * Decoding of ISF parameters
+ */
+
+void Dpisf_2s_36b(
+ int16 * indice, /* input: quantization indices */
+ int16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */
+ int16 * past_isfq, /* i/0 : past ISF quantizer */
+ int16 * isfold, /* input : past quantized ISF */
+ int16 * isf_buf, /* input : isf buffer */
+ int16 bfi, /* input : Bad frame indicator */
+ int16 enc_dec
+)
+{
+ int16 ref_isf[M];
+ int16 i, j, tmp;
+ int32 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] = add_int16(dico2_isf[indice[1] * 7 + i], dico23_isf_36b[indice[4] * 7 + i]);
+ }
+
+ for (i = 0; i < 5; i++)
+ {
+ isf_q[i] = add_int16(isf_q[i], dico21_isf_36b[indice[2] * 5 + i]);
+ }
+ for (i = 0; i < 4; i++)
+ {
+ isf_q[i + 5] = add_int16(isf_q[i + 5], dico22_isf_36b[(indice[3] << 2) + i]);
+ }
+
+ for (i = 0; i < ORDER; i++)
+ {
+ tmp = isf_q[i];
+ isf_q[i] = add_int16(tmp, mean_isf[i]);
+ isf_q[i] = add_int16(isf_q[i], mult_int16(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 = mul_16by16_to_int32(mean_isf[i], 8192);
+ for (j = 0; j < L_MEANBUF; j++)
+ {
+ L_tmp = mac_16by16_to_int32(L_tmp, isf_buf[j * M + i], 8192);
+ }
+
+ ref_isf[i] = amr_wb_round(L_tmp);
+ }
+
+ /* use the past ISFs slightly shifted towards their mean */
+ for (i = 0; i < ORDER; i++)
+ {
+ isf_q[i] = add_int16(mult_int16(ALPHA, isfold[i]), mult_int16(ONE_ALPHA, ref_isf[i]));
+ }
+
+ /* estimate past quantized residual to be used in next frame */
+
+ for (i = 0; i < ORDER; i++)
+ {
+ tmp = add_int16(ref_isf[i], mult_int16(past_isfq[i], MU)); /* predicted ISF */
+ past_isfq[i] = sub_int16(isf_q[i], tmp);
+ past_isfq[i] >>= 1; /* past_isfq[i] *= 0.5 */
+ }
+ }
+
+ Reorder_isf(isf_q, ISF_GAP, ORDER);
+
+ return;
+}
+
+/*
+ * procedure Reorder_isf()
+ * ~~~~~~~~~~~~~
+ * 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(
+ int16 * isf, /* (i/o) Q15: ISF in the frequency domain (0..0.5) */
+ int16 min_dist, /* (i) Q15 : minimum distance to keep */
+ int16 n /* (i) : number of ISF */
+)
+{
+ int16 i, isf_min;
+
+ isf_min = min_dist;
+
+ for (i = 0; i < n - 1; i++)
+ {
+ if (isf[i] < isf_min)
+ {
+ isf[i] = isf_min;
+ }
+ isf_min = add_int16(isf[i], min_dist);
+ }
+
+ return;
+}
+
diff --git a/media/libstagefright/codecs/amrwb/src/qpisf_2s.h b/media/libstagefright/codecs/amrwb/src/qpisf_2s.h
new file mode 100644
index 0000000..61f8c06
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/qpisf_2s.h
@@ -0,0 +1,117 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./cpp/include/qpisf_2s.h
+
+ Date: 01/04/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef QPISF_2S_H
+#define QPISF_2S_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "qisf_ns.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+----------------------------------------------------------------------------*/
+
+#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
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+----------------------------------------------------------------------------*/
+extern const int16 mean_isf[ORDER];
+extern const int16 dico1_isf[SIZE_BK1*9];
+extern const int16 dico2_isf[SIZE_BK2*7];
+extern const int16 dico21_isf[SIZE_BK21*3];
+extern const int16 dico22_isf[SIZE_BK22*3];
+extern const int16 dico23_isf[SIZE_BK23*3];
+extern const int16 dico24_isf[SIZE_BK24*3];
+extern const int16 dico25_isf[SIZE_BK25*4];
+extern const int16 dico21_isf_36b[SIZE_BK21_36b*5];
+extern const int16 dico22_isf_36b[SIZE_BK22_36b*4];
+extern const int16 dico23_isf_36b[SIZE_BK23_36b*7];
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+#endif /* QPISF_2S_H */
diff --git a/media/libstagefright/codecs/amrwb/src/qpisf_2s_tab.cpp b/media/libstagefright/codecs/amrwb/src/qpisf_2s_tab.cpp
new file mode 100644
index 0000000..d57522e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/qpisf_2s_tab.cpp
@@ -0,0 +1,1383 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*-------------------------------------------------------------------*
+ * qpisf_2s_tab.cpp
+ *-------------------------------------------------------------------*
+ * Quantization tables for two-stage of ISFs (split by 2 in 1st stage)
+ * Version whith prediction MU = 0.25
+ *-------------------------------------------------------------------*/
+
+#include "qisf_ns.h"
+#include "qpisf_2s.h"
+
+
+
+
+/* means of ISFs */
+const int16 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
+ */
+
+const int16 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
+ *------------------------------------------------*/
+
+const int16 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
+ */
+
+
+const int16 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
+ */
+
+
+const int16 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
+ */
+
+
+const int16 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
+ */
+
+const int16 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
+ */
+
+const int16 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
+ */
+
+const int16 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
+};
+
+const int16 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
+};
+
+const int16 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/amrwb/src/scale_signal.cpp b/media/libstagefright/codecs/amrwb/src/scale_signal.cpp
new file mode 100644
index 0000000..b2b02b1
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/scale_signal.cpp
@@ -0,0 +1,154 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: scale_signal.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 signal[], (i/o) : signal to scale
+ int16 lg, (i) : size of x[]
+ int16 exp (i) : exponent: x = round(x << exp)
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Scale signal to get maximum of dynamic range
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void scale_signal(
+ int16 x[], /* (i/o) : signal to scale */
+ int16 lg, /* (i) : size of x[] */
+ int16 exp /* (i) : exponent: x = round(x << exp) */
+)
+{
+ int16 i;
+ int16 tmp;
+ int16 *pt_x;
+
+
+ int32 L_tmp;
+
+
+ if (exp > 0)
+ {
+ for (i = 0; i < lg; i++)
+ {
+ L_tmp = shl_int32(((int32)x[i] << 16), exp); /* saturation can occur here */
+ x[i] = amr_wb_round(L_tmp);
+ }
+ }
+ else if (exp < 0)
+ {
+ exp = -exp;
+ exp &= 0xf;
+ tmp = (int16)(0x00008000 >> (16 - exp));
+ pt_x = x;
+
+ for (i = lg >> 1; i != 0; i--)
+ {
+ *(pt_x) = add_int16(*(pt_x), tmp) >> exp;
+ pt_x++;
+ *(pt_x) = add_int16(*(pt_x), tmp) >> exp;
+ pt_x++;
+ }
+
+ }
+ return;
+}
diff --git a/media/libstagefright/codecs/amrwb/src/synthesis_amr_wb.cpp b/media/libstagefright/codecs/amrwb/src/synthesis_amr_wb.cpp
new file mode 100644
index 0000000..c3aa887
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/synthesis_amr_wb.cpp
@@ -0,0 +1,440 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: synthesis_amr_wb.cpp
+
+ Date: 05/04/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 Aq[], A(z) : quantized Az
+ int16 exc[], (i) : excitation at 12kHz
+ int16 Q_new, (i) : scaling performed on exc
+ int16 synth16k[], (o) : 16kHz synthesis signal
+ int16 prms, (i) : compressed amr wb
+ int16 HfIsf[],
+ int16 nb_bits,
+ int16 newDTXState,
+ Decoder_State * st, (i/o) : State structure
+ int16 bfi, (i) : bad frame indicator
+ int16 *ScratchMem
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Synthesis of signal at 16kHz with HF extension
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_mem_funcs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+#include "e_pv_amrwbdec.h"
+#include "get_amr_wb_bits.h"
+#include "pvamrwb_math_op.h"
+#include "pvamrwbdecoder_api.h"
+#include "synthesis_amr_wb.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+/* High Band encoding */
+const int16 HP_gain[16] =
+{
+ 3624, 4673, 5597, 6479, 7425, 8378, 9324, 10264,
+ 11210, 12206, 13391, 14844, 16770, 19655, 24289, 32728
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void synthesis_amr_wb(
+ int16 Aq[], /* A(z) : quantized Az */
+ int16 exc[], /* (i) : excitation at 12kHz */
+ int16 Q_new, /* (i) : scaling performed on exc */
+ int16 synth16k[], /* (o) : 16kHz synthesis signal */
+ int16 prms, /* (i) : parameter */
+ int16 HfIsf[],
+ int16 nb_bits,
+ int16 newDTXState,
+ Decoder_State * st, /* (i/o) : State structure */
+ int16 bfi, /* (i) : bad frame indicator */
+ int16 *ScratchMem
+)
+{
+ int16 i, fac, exp;
+ int16 tmp;
+ int16 ener, exp_ener;
+ int32 L_tmp;
+ int32 L_tmp2;
+
+ int16 HF_corr_gain;
+ int16 HF_gain_ind;
+ int16 gain1, gain2;
+
+ int16 *pt_synth;
+ int16 *pt_HF;
+ int16 *synth_hi = ScratchMem;
+ int16 *synth_lo = &ScratchMem[M + L_SUBFR];
+ int16 *synth = &synth_lo[M + L_SUBFR];
+ int16 *HF = &synth[L_SUBFR];
+ int16 *Ap = &HF[L_SUBFR16k]; /* High Frequency vector */
+ int16 *HfA = &Ap[M16k + 1];
+ int16 *pt_tmp;
+
+ /*------------------------------------------------------------*
+ * speech synthesis *
+ * ~~~~~~~~~~~~~~~~ *
+ * - Find synthesis speech corresponding to exc2[]. *
+ * - Perform fixed deemphasis and hp 50hz filtering. *
+ * - Oversampling from 12.8kHz to 16kHz. *
+ *------------------------------------------------------------*/
+
+ pv_memcpy((void *)synth_hi,
+ (void *)st->mem_syn_hi,
+ M*sizeof(*synth_hi));
+
+ pv_memcpy((void *)synth_lo,
+ (void *)st->mem_syn_lo,
+ M*sizeof(*synth_lo));
+
+ Syn_filt_32(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR);
+
+ pv_memcpy((void *)st->mem_syn_hi,
+ (void *)(synth_hi + L_SUBFR),
+ M*sizeof(*st->mem_syn_hi));
+
+ pv_memcpy((void *)st->mem_syn_lo,
+ (void *)(synth_lo + L_SUBFR),
+ M*sizeof(*st->mem_syn_lo));
+
+ deemphasis_32(synth_hi + M,
+ synth_lo + M,
+ synth,
+ PREEMPH_FAC,
+ L_SUBFR,
+ &(st->mem_deemph));
+
+ highpass_50Hz_at_12k8(synth,
+ L_SUBFR,
+ st->mem_sig_out);
+
+ oversamp_12k8_to_16k(synth,
+ L_SUBFR,
+ synth16k,
+ st->mem_oversamp,
+ ScratchMem);
+
+ /*
+ * 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 */
+ pt_tmp = HF;
+ for (i = L_SUBFR16k >> 2; i != 0 ; i--)
+ {
+ *(pt_tmp++) = noise_gen_amrwb(&(st->seed2)) >> 3;
+ *(pt_tmp++) = noise_gen_amrwb(&(st->seed2)) >> 3;
+ *(pt_tmp++) = noise_gen_amrwb(&(st->seed2)) >> 3;
+ *(pt_tmp++) = noise_gen_amrwb(&(st->seed2)) >> 3;
+ }
+ /* energy of excitation */
+
+ pt_tmp = exc;
+
+ for (i = L_SUBFR >> 2; i != 0; i--)
+ {
+ *(pt_tmp) = add_int16(*(pt_tmp), 0x0004) >> 3;
+ pt_tmp++;
+ *(pt_tmp) = add_int16(*(pt_tmp), 0x0004) >> 3;
+ pt_tmp++;
+ *(pt_tmp) = add_int16(*(pt_tmp), 0x0004) >> 3;
+ pt_tmp++;
+ *(pt_tmp) = add_int16(*(pt_tmp), 0x0004) >> 3;
+ pt_tmp++;
+ }
+
+
+ Q_new -= 3;
+
+ ener = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp_ener));
+ exp_ener -= Q_new << 1;
+
+ /* set energy of white noise to energy of excitation */
+
+ tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp));
+
+ if (tmp > ener)
+ {
+ tmp >>= 1; /* Be sure tmp < ener */
+ exp += 1;
+ }
+ L_tmp = L_deposit_h(div_16by16(tmp, ener)); /* result is normalized */
+ exp -= exp_ener;
+ one_ov_sqrt_norm(&L_tmp, &exp);
+ L_tmp = shl_int32(L_tmp, exp + 1); /* L_tmp x 2, L_tmp in Q31 */
+
+ tmp = (int16)(L_tmp >> 16); /* tmp = 2 x sqrt(ener_exc/ener_hf) */
+
+
+
+ pt_tmp = HF;
+ for (i = L_SUBFR16k >> 2; i != 0 ; i--)
+ {
+ *(pt_tmp) = (int16)(fxp_mul_16by16(*(pt_tmp), tmp) >> 15);
+ pt_tmp++;
+ *(pt_tmp) = (int16)(fxp_mul_16by16(*(pt_tmp), tmp) >> 15);
+ pt_tmp++;
+ *(pt_tmp) = (int16)(fxp_mul_16by16(*(pt_tmp), tmp) >> 15);
+ pt_tmp++;
+ *(pt_tmp) = (int16)(fxp_mul_16by16(*(pt_tmp), tmp) >> 15);
+ pt_tmp++;
+ }
+
+ /* find tilt of synthesis speech (tilt: 1=voiced, -1=unvoiced) */
+
+ highpass_400Hz_at_12k8(synth, L_SUBFR, st->mem_hp400);
+
+ L_tmp = 1L;
+ L_tmp2 = 1L;
+
+
+ L_tmp = mac_16by16_to_int32(L_tmp, synth[0], synth[0]);
+
+ for (i = 1; i < L_SUBFR; i++)
+ {
+ L_tmp = mac_16by16_to_int32(L_tmp, synth[i], synth[i ]);
+ L_tmp2 = mac_16by16_to_int32(L_tmp2, synth[i], synth[i - 1]);
+ }
+
+
+ exp = normalize_amr_wb(L_tmp);
+
+ ener = (int16)((L_tmp << exp) >> 16); /* ener = r[0] */
+ tmp = (int16)((L_tmp2 << exp) >> 16); /* tmp = r[1] */
+
+ if (tmp > 0)
+ {
+ fac = div_16by16(tmp, ener);
+ }
+ else
+ {
+ fac = 0;
+ }
+
+ /* modify energy of white noise according to synthesis tilt */
+ gain1 = 32767 - fac;
+ gain2 = mult_int16(gain1, 20480);
+ gain2 = shl_int16(gain2, 1);
+
+ if (st->vad_hist > 0)
+ {
+ tmp = gain2 - 1;
+ }
+ else
+ {
+ tmp = gain1 - 1;
+ }
+
+
+ if (tmp != 0)
+ {
+ tmp++;
+ }
+
+ if (tmp < 3277)
+ {
+ tmp = 3277; /* 0.1 in Q15 */
+
+ }
+
+
+ if ((nb_bits >= NBBITS_24k) && (bfi == 0))
+ {
+ /* HF correction gain */
+ HF_gain_ind = prms;
+ HF_corr_gain = HP_gain[HF_gain_ind];
+
+ pt_tmp = HF;
+ for (i = L_SUBFR16k >> 2; i != 0 ; i--)
+ {
+ *(pt_tmp) = mult_int16(*(pt_tmp), HF_corr_gain) << 1;
+ pt_tmp++;
+ *(pt_tmp) = mult_int16(*(pt_tmp), HF_corr_gain) << 1;
+ pt_tmp++;
+ *(pt_tmp) = mult_int16(*(pt_tmp), HF_corr_gain) << 1;
+ pt_tmp++;
+ *(pt_tmp) = mult_int16(*(pt_tmp), HF_corr_gain) << 1;
+ pt_tmp++;
+ }
+
+ /* HF gain */
+ }
+ else
+ {
+ pt_tmp = HF;
+ for (i = L_SUBFR16k >> 2; i != 0 ; i--)
+ {
+ *(pt_tmp) = mult_int16(*(pt_tmp), tmp);
+ pt_tmp++;
+ *(pt_tmp) = mult_int16(*(pt_tmp), tmp);
+ pt_tmp++;
+ *(pt_tmp) = mult_int16(*(pt_tmp), tmp);
+ pt_tmp++;
+ *(pt_tmp) = mult_int16(*(pt_tmp), tmp);
+ pt_tmp++;
+ }
+ }
+
+
+ if ((nb_bits <= NBBITS_7k) && (newDTXState == SPEECH))
+ {
+ isf_extrapolation(HfIsf);
+ Isp_Az(HfIsf, HfA, M16k, 0);
+
+ weight_amrwb_lpc(HfA, Ap, 29491, M16k); /* fac=0.9 */
+
+ wb_syn_filt(Ap,
+ M16k,
+ HF,
+ HF,
+ L_SUBFR16k,
+ st->mem_syn_hf,
+ 1,
+ ScratchMem);
+ }
+ else
+ {
+ /* synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz */
+ weight_amrwb_lpc(Aq, Ap, 19661, M); /* fac=0.6 */
+
+ wb_syn_filt(Ap,
+ M,
+ HF,
+ HF,
+ L_SUBFR16k,
+ st->mem_syn_hf + (M16k - M),
+ 1,
+ ScratchMem);
+ }
+
+ /* noise Band Pass filtering (1ms of delay) */
+ band_pass_6k_7k(HF,
+ L_SUBFR16k,
+ st->mem_hf,
+ ScratchMem);
+
+
+ if (nb_bits >= NBBITS_24k)
+ {
+ /* Low Pass filtering (7 kHz) */
+ low_pass_filt_7k(HF,
+ L_SUBFR16k,
+ st->mem_hf3,
+ ScratchMem);
+ }
+ /* add filtered HF noise to speech synthesis */
+
+ pt_synth = synth16k;
+ pt_HF = HF;
+
+ for (i = L_SUBFR16k >> 1; i != 0; i--)
+ {
+ *(pt_synth) = add_int16(*(pt_synth), *(pt_HF++)); /* check 16 bit saturation */
+ pt_synth++;
+ *(pt_synth) = add_int16(*(pt_synth), *(pt_HF++));
+ pt_synth++;
+ }
+
+}
+
diff --git a/media/libstagefright/codecs/amrwb/src/synthesis_amr_wb.h b/media/libstagefright/codecs/amrwb/src/synthesis_amr_wb.h
new file mode 100644
index 0000000..4bfc3c5
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/synthesis_amr_wb.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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Pathname: ./cpp/include/synthesis_amr_wb.h
+
+ Date: 05/04/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef SYNTHESIS_AMR_WB_H
+#define SYNTHESIS_AMR_WB_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES AND SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void synthesis_amr_wb(
+ int16 Aq[], /* A(z) : quantized Az */
+ int16 exc[], /* (i) : excitation at 12kHz */
+ int16 Q_new, /* (i) : scaling performed on exc */
+ int16 synth16k[], /* (o) : 16kHz synthesis signal */
+ int16 prms, /* (i) : parameter */
+ int16 HfIsf[],
+ int16 nb_bits,
+ int16 newDTXState,
+ Decoder_State * st, /* (i/o) : State structure */
+ int16 bfi, /* (i) : bad frame indicator */
+ int16 * ScratchMemory
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif /* PV_NORMALIZE_H */
diff --git a/media/libstagefright/codecs/amrwb/src/voice_factor.cpp b/media/libstagefright/codecs/amrwb/src/voice_factor.cpp
new file mode 100644
index 0000000..6153c67
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/voice_factor.cpp
@@ -0,0 +1,175 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: voice_factor.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 exc[], (i) Q_exc : pitch excitation
+ int16 Q_exc, (i) : exc format
+ int16 gain_pit, (i) Q14 : gain of pitch
+ int16 code[], (i) Q9 : Fixed codebook excitation
+ int16 gain_code, (i) Q0 : gain of code
+ int16 L_subfr (i) : subframe length
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Find the voicing factor (1=voice to -1=unvoiced).
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwb_math_op.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+int16 voice_factor( /* (o) Q15 : factor (-1=unvoiced to 1=voiced) */
+ int16 exc[], /* (i) Q_exc : pitch excitation */
+ int16 Q_exc, /* (i) : exc format */
+ int16 gain_pit, /* (i) Q14 : gain of pitch */
+ int16 code[], /* (i) Q9 : Fixed codebook excitation */
+ int16 gain_code, /* (i) Q0 : gain of code */
+ int16 L_subfr /* (i) : subframe length */
+)
+{
+ int16 i, tmp, exp, ener1, exp1, ener2, exp2;
+ int32 L_tmp;
+
+ ener1 = extract_h(Dot_product12(exc, exc, L_subfr, &exp1));
+ exp1 = sub_int16(exp1, Q_exc << 1);
+ L_tmp = mul_16by16_to_int32(gain_pit, gain_pit);
+ exp = normalize_amr_wb(L_tmp);
+
+ tmp = (int16)((L_tmp << exp) >> 16);
+ ener1 = mult_int16(ener1, tmp);
+ exp1 -= (exp + 10); /* 10 -> gain_pit Q14 to Q9 */
+
+ ener2 = extract_h(Dot_product12(code, code, L_subfr, &exp2));
+
+ exp = norm_s(gain_code);
+ tmp = shl_int16(gain_code, exp);
+ tmp = mult_int16(tmp, tmp);
+ ener2 = mult_int16(ener2, tmp);
+ exp2 -= (exp << 1);
+
+ i = exp1 - exp2;
+
+
+ if (i >= 0)
+ {
+ ener1 >>= 1;
+ ener2 >>= (i + 1);
+ }
+ else
+ {
+ ener1 >>= (1 - i);
+ ener2 >>= 1;
+ }
+
+ tmp = ener1 - ener2;
+ ener1 += ener2 + 1;
+
+
+ if (tmp >= 0)
+ {
+ tmp = div_16by16(tmp, ener1);
+ }
+ else
+ {
+ tmp = negate_int16(div_16by16(negate_int16(tmp), ener1));
+ }
+
+ return (tmp);
+}
diff --git a/media/libstagefright/codecs/amrwb/src/wb_syn_filt.cpp b/media/libstagefright/codecs/amrwb/src/wb_syn_filt.cpp
new file mode 100644
index 0000000..e1af6d4
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/wb_syn_filt.cpp
@@ -0,0 +1,307 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: wb_syn_filt.cpp
+
+ Date: 05/08/2004
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+wb_syn_filt
+
+ int16 a[], (i) Q12 : a[m+1] prediction coefficients
+ int16 m, (i) : order of LP filter
+ int16 x[], (i) : input signal
+ int16 y[], (o) : output signal
+ int16 lg, (i) : size of filtering
+ int16 mem[], (i/o) : memory associated with this filtering.
+ int16 update, (i) : 0=no update, 1=update of memory.
+ int16 y_buf[]
+
+Syn_filt_32
+
+ int16 a[], (i) Q12 : a[m+1] prediction coefficients
+ int16 m, (i) : order of LP filter
+ int16 exc[], (i) Qnew: excitation (exc[i] >> Qnew)
+ int16 Qnew, (i) : exc scaling = 0(min) to 8(max)
+ int16 sig_hi[], (o) /16 : synthesis high
+ int16 sig_lo[], (o) /16 : synthesis low
+ int16 lg (i) : size of filtering
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Do the synthesis filtering 1/A(z) 16 and 32-bits version
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_mem_funcs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwb_math_op.h"
+#include "pvamrwbdecoder_cnst.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void wb_syn_filt(
+ int16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ int16 m, /* (i) : order of LP filter */
+ int16 x[], /* (i) : input signal */
+ int16 y[], /* (o) : output signal */
+ int16 lg, /* (i) : size of filtering */
+ int16 mem[], /* (i/o) : memory associated with this filtering. */
+ int16 update, /* (i) : 0=no update, 1=update of memory. */
+ int16 y_buf[]
+)
+{
+
+ int16 i, j;
+ int32 L_tmp1;
+ int32 L_tmp2;
+ int32 L_tmp3;
+ int32 L_tmp4;
+ int16 *yy;
+
+ /* copy initial filter states into synthesis buffer */
+ pv_memcpy(y_buf, mem, m*sizeof(*yy));
+
+ yy = &y_buf[m];
+
+ /* Do the filtering. */
+
+ for (i = 0; i < lg >> 2; i++)
+ {
+ L_tmp1 = -((int32)x[(i<<2)] << 11);
+ L_tmp2 = -((int32)x[(i<<2)+1] << 11);
+ L_tmp3 = -((int32)x[(i<<2)+2] << 11);
+ L_tmp4 = -((int32)x[(i<<2)+3] << 11);
+
+ /* a[] uses Q12 and abs(a) =< 1 */
+
+ L_tmp1 = fxp_mac_16by16(yy[(i<<2) -3], a[3], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(yy[(i<<2) -2], a[3], L_tmp2);
+ L_tmp1 = fxp_mac_16by16(yy[(i<<2) -2], a[2], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(yy[(i<<2) -1], a[2], L_tmp2);
+ L_tmp1 = fxp_mac_16by16(yy[(i<<2) -1], a[1], L_tmp1);
+
+ for (j = 4; j < m; j += 2)
+ {
+ L_tmp1 = fxp_mac_16by16(yy[(i<<2)-1 - j], a[j+1], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(yy[(i<<2) - j], a[j+1], L_tmp2);
+ L_tmp1 = fxp_mac_16by16(yy[(i<<2) - j], a[j ], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(yy[(i<<2)+1 - j], a[j ], L_tmp2);
+ L_tmp3 = fxp_mac_16by16(yy[(i<<2)+1 - j], a[j+1], L_tmp3);
+ L_tmp4 = fxp_mac_16by16(yy[(i<<2)+2 - j], a[j+1], L_tmp4);
+ L_tmp3 = fxp_mac_16by16(yy[(i<<2)+2 - j], a[j ], L_tmp3);
+ L_tmp4 = fxp_mac_16by16(yy[(i<<2)+3 - j], a[j ], L_tmp4);
+ }
+
+ L_tmp1 = fxp_mac_16by16(yy[(i<<2) - j], a[j], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(yy[(i<<2)+1 - j], a[j], L_tmp2);
+ L_tmp3 = fxp_mac_16by16(yy[(i<<2)+2 - j], a[j], L_tmp3);
+ L_tmp4 = fxp_mac_16by16(yy[(i<<2)+3 - j], a[j], L_tmp4);
+
+ L_tmp1 = shl_int32(L_tmp1, 4);
+
+ y[(i<<2)] = yy[(i<<2)] = amr_wb_round(-L_tmp1);
+
+ L_tmp2 = fxp_mac_16by16(yy[(i<<2)], a[1], L_tmp2);
+
+ L_tmp2 = shl_int32(L_tmp2, 4);
+
+ y[(i<<2)+1] = yy[(i<<2)+1] = amr_wb_round(-L_tmp2);
+
+ L_tmp3 = fxp_mac_16by16(yy[(i<<2) - 1], a[3], L_tmp3);
+ L_tmp4 = fxp_mac_16by16(yy[(i<<2)], a[3], L_tmp4);
+ L_tmp3 = fxp_mac_16by16(yy[(i<<2)], a[2], L_tmp3);
+ L_tmp4 = fxp_mac_16by16(yy[(i<<2) + 1], a[2], L_tmp4);
+ L_tmp3 = fxp_mac_16by16(yy[(i<<2) + 1], a[1], L_tmp3);
+
+ L_tmp3 = shl_int32(L_tmp3, 4);
+
+ y[(i<<2)+2] = yy[(i<<2)+2] = amr_wb_round(-L_tmp3);
+
+ L_tmp4 = fxp_mac_16by16(yy[(i<<2)+2], a[1], L_tmp4);
+
+ L_tmp4 = shl_int32(L_tmp4, 4);
+
+ y[(i<<2)+3] = yy[(i<<2)+3] = amr_wb_round(-L_tmp4);
+ }
+
+
+ /* Update memory if required */
+
+ if (update)
+ {
+ pv_memcpy(mem, &y[lg - m], m*sizeof(*y));
+ }
+
+ return;
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void Syn_filt_32(
+ int16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ int16 m, /* (i) : order of LP filter */
+ int16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */
+ int16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */
+ int16 sig_hi[], /* (o) /16 : synthesis high */
+ int16 sig_lo[], /* (o) /16 : synthesis low */
+ int16 lg /* (i) : size of filtering */
+)
+{
+ int16 i, k, a0;
+ int32 L_tmp1;
+ int32 L_tmp2;
+ int32 L_tmp3;
+ int32 L_tmp4;
+
+ a0 = 9 - Qnew; /* input / 16 and >>Qnew */
+
+ /* Do the filtering. */
+
+ for (i = 0; i < lg >> 1; i++)
+ {
+
+ L_tmp3 = 0;
+ L_tmp4 = 0;
+
+ L_tmp1 = fxp_mul_16by16(sig_lo[(i<<1) - 1], a[1]);
+ L_tmp2 = fxp_mul_16by16(sig_hi[(i<<1) - 1], a[1]);
+
+ for (k = 2; k < m; k += 2)
+ {
+
+ L_tmp1 = fxp_mac_16by16(sig_lo[(i<<1)-1 - k], a[k+1], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(sig_hi[(i<<1)-1 - k], a[k+1], L_tmp2);
+ L_tmp1 = fxp_mac_16by16(sig_lo[(i<<1) - k], a[k ], L_tmp1);
+ L_tmp2 = fxp_mac_16by16(sig_hi[(i<<1) - k], a[k ], L_tmp2);
+ L_tmp3 = fxp_mac_16by16(sig_lo[(i<<1) - k], a[k+1], L_tmp3);
+ L_tmp4 = fxp_mac_16by16(sig_hi[(i<<1) - k], a[k+1], L_tmp4);
+ L_tmp3 = fxp_mac_16by16(sig_lo[(i<<1)+1 - k], a[k ], L_tmp3);
+ L_tmp4 = fxp_mac_16by16(sig_hi[(i<<1)+1 - k], a[k ], L_tmp4);
+ }
+
+ L_tmp1 = -fxp_mac_16by16(sig_lo[(i<<1) - k], a[k], L_tmp1);
+ L_tmp3 = fxp_mac_16by16(sig_lo[(i<<1)+1 - k], a[k], L_tmp3);
+ L_tmp2 = fxp_mac_16by16(sig_hi[(i<<1) - k], a[k], L_tmp2);
+ L_tmp4 = fxp_mac_16by16(sig_hi[(i<<1)+1 - k], a[k], L_tmp4);
+
+
+
+ L_tmp1 >>= 11; /* -4 : sig_lo[i] << 4 */
+
+ L_tmp1 += (int32)exc[(i<<1)] << a0;
+
+ L_tmp1 -= (L_tmp2 << 1);
+ /* sig_hi = bit16 to bit31 of synthesis */
+ L_tmp1 = shl_int32(L_tmp1, 3); /* ai in Q12 */
+
+ sig_hi[(i<<1)] = (int16)(L_tmp1 >> 16);
+
+ L_tmp4 = fxp_mac_16by16((int16)(L_tmp1 >> 16), a[1], L_tmp4);
+
+ /* sig_lo = bit4 to bit15 of synthesis */
+ /* L_tmp1 >>= 4 : sig_lo[i] >> 4 */
+ sig_lo[(i<<1)] = (int16)((L_tmp1 >> 4) - ((L_tmp1 >> 16) << 12));
+
+ L_tmp3 = fxp_mac_16by16(sig_lo[(i<<1)], a[1], L_tmp3);
+ L_tmp3 = -L_tmp3 >> 11;
+
+ L_tmp3 += (int32)exc[(i<<1)+1] << a0;
+
+ L_tmp3 -= (L_tmp4 << 1);
+ /* sig_hi = bit16 to bit31 of synthesis */
+ L_tmp3 = shl_int32(L_tmp3, 3); /* ai in Q12 */
+ sig_hi[(i<<1)+1] = (int16)(L_tmp3 >> 16);
+
+ /* sig_lo = bit4 to bit15 of synthesis */
+ /* L_tmp1 >>= 4 : sig_lo[i] >> 4 */
+ sig_lo[(i<<1)+1] = (int16)((L_tmp3 >> 4) - (sig_hi[(i<<1)+1] << 12));
+ }
+
+}
+
+
diff --git a/media/libstagefright/codecs/amrwb/src/weight_amrwb_lpc.cpp b/media/libstagefright/codecs/amrwb/src/weight_amrwb_lpc.cpp
new file mode 100644
index 0000000..63d2e00
--- /dev/null
+++ b/media/libstagefright/codecs/amrwb/src/weight_amrwb_lpc.cpp
@@ -0,0 +1,135 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/****************************************************************************************
+Portions of this file are derived from the following 3GPP standard:
+
+ 3GPP TS 26.173
+ ANSI-C code for the Adaptive Multi-Rate - Wideband (AMR-WB) speech codec
+ Available from http://www.3gpp.org
+
+(C) 2007, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
+Permission to distribute, modify and use this file under the standard license
+terms listed above has been obtained from the copyright holder.
+****************************************************************************************/
+/*
+------------------------------------------------------------------------------
+
+
+
+ Filename: weight_amrwb_lpc.cpp
+
+ Date: 05/08/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ int16 a[], (i) Q12 : a[m+1] LPC coefficients
+ int16 ap[], (o) Q12 : Spectral expanded LPC coefficients
+ int16 gamma, (i) Q15 : Spectral expansion factor.
+ int16 m (i) : LPC order.
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Weighting of LPC coefficients.
+ ap[i] = a[i] (gamma i)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_amr_wb_type_defs.h"
+#include "pvamrwbdecoder_basic_op.h"
+#include "pvamrwbdecoder_acelp.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void weight_amrwb_lpc(
+ int16 a[], /* (i) Q12 : a[m+1] LPC coefficients */
+ int16 ap[], /* (o) Q12 : Spectral expanded LPC coefficients */
+ int16 gamma, /* (i) Q15 : Spectral expansion factor. */
+ int16 m /* (i) : LPC order. */
+)
+{
+ int16 i, fac;
+ int32 roundFactor = 0x00004000L;
+ ap[0] = a[0];
+ fac = gamma;
+ for (i = 1; i < m; i++)
+ {
+ ap[i] = (int16)(fxp_mac_16by16(a[i], fac, roundFactor) >> 15);
+ fac = (int16)(fxp_mac_16by16(fac, gamma, roundFactor) >> 15);
+ }
+ ap[i] = (int16)(fxp_mac_16by16(a[i], fac, roundFactor) >> 15);
+
+ return;
+}
diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk
new file mode 100644
index 0000000..d3c3041
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/Android.mk
@@ -0,0 +1,141 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include frameworks/base/media/libstagefright/codecs/common/Config.mk
+
+
+
+LOCAL_SRC_FILES := \
+ 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)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ SoftAMRWBEncoder.cpp
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+ frameworks/base/media/libstagefright/codecs/common/include \
+ frameworks/native/include/media/openmax
+
+LOCAL_STATIC_LIBRARIES := \
+ libstagefright_amrwbenc
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright_omx libstagefright_foundation libutils \
+ libstagefright_enc_common
+
+LOCAL_MODULE := libstagefright_soft_amrwbenc
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_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..4ff5f10
--- /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("libstagefright.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..85ddceb
--- /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 \
+ ../../common/cmnMemory.c
+
+LOCAL_MODULE_TAGS := debug
+LOCAL_MODULE := AMRWBEncTest
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_CFLAGS := $(VO_CFLAGS)
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright \
+ libdl
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/ \
+ $(LOCAL_PATH)/../../common \
+ $(LOCAL_PATH)/../../common/include
+
+include $(BUILD_EXECUTABLE)
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
new file mode 100644
index 0000000..9ccb49c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SoftAMRWBEncoder"
+#include <utils/Log.h>
+
+#include "SoftAMRWBEncoder.h"
+
+#include "cmnMemory.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/hexdump.h>
+
+namespace android {
+
+static const int32_t kSampleRate = 16000;
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+SoftAMRWBEncoder::SoftAMRWBEncoder(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SimpleSoftOMXComponent(name, callbacks, appData, component),
+ mEncoderHandle(NULL),
+ mApiHandle(NULL),
+ mMemOperator(NULL),
+ mBitRate(0),
+ mMode(VOAMRWB_MD66),
+ mInputSize(0),
+ mInputTimeUs(-1ll),
+ mSawInputEOS(false),
+ mSignalledError(false) {
+ initPorts();
+ CHECK_EQ(initEncoder(), (status_t)OK);
+}
+
+SoftAMRWBEncoder::~SoftAMRWBEncoder() {
+ if (mEncoderHandle != NULL) {
+ CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
+ mEncoderHandle = NULL;
+ }
+
+ delete mApiHandle;
+ mApiHandle = NULL;
+
+ delete mMemOperator;
+ mMemOperator = NULL;
+}
+
+void SoftAMRWBEncoder::initPorts() {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+
+ def.nPortIndex = 0;
+ def.eDir = OMX_DirInput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t);
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 1;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ addPort(def);
+
+ def.nPortIndex = 1;
+ def.eDir = OMX_DirOutput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 8192;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 2;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/amr-wb");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingAMR;
+
+ addPort(def);
+}
+
+status_t SoftAMRWBEncoder::initEncoder() {
+ mApiHandle = new VO_AUDIO_CODECAPI;
+
+ if (VO_ERR_NONE != voGetAMRWBEncAPI(mApiHandle)) {
+ ALOGE("Failed to get api handle");
+ return UNKNOWN_ERROR;
+ }
+
+ mMemOperator = new VO_MEM_OPERATOR;
+ 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)) {
+ ALOGE("Failed to init AMRWB encoder");
+ return UNKNOWN_ERROR;
+ }
+
+ VOAMRWBFRAMETYPE type = VOAMRWB_RFC3267;
+ if (VO_ERR_NONE != mApiHandle->SetParam(
+ mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &type)) {
+ ALOGE("Failed to set AMRWB encoder frame type to %d", type);
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+OMX_ERRORTYPE SoftAMRWBEncoder::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamAudioPortFormat:
+ {
+ OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+ (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+ if (formatParams->nPortIndex > 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (formatParams->nIndex > 0) {
+ return OMX_ErrorNoMore;
+ }
+
+ formatParams->eEncoding =
+ (formatParams->nPortIndex == 0)
+ ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAMR;
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioAmr:
+ {
+ OMX_AUDIO_PARAM_AMRTYPE *amrParams =
+ (OMX_AUDIO_PARAM_AMRTYPE *)params;
+
+ if (amrParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ amrParams->nChannels = 1;
+ amrParams->nBitRate = mBitRate;
+
+ amrParams->eAMRBandMode =
+ (OMX_AUDIO_AMRBANDMODETYPE)(mMode + OMX_AUDIO_AMRBandModeWB0);
+
+ amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
+ amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPcm:
+ {
+ OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eEndian = OMX_EndianBig;
+ pcmParams->bInterleaved = OMX_TRUE;
+ pcmParams->nBitPerSample = 16;
+ pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
+ pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelCF;
+
+ pcmParams->nChannels = 1;
+ pcmParams->nSamplingRate = kSampleRate;
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftAMRWBEncoder::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamStandardComponentRole:
+ {
+ const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+ (const OMX_PARAM_COMPONENTROLETYPE *)params;
+
+ if (strncmp((const char *)roleParams->cRole,
+ "audio_encoder.amrwb",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPortFormat:
+ {
+ const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
+ (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
+
+ if (formatParams->nPortIndex > 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (formatParams->nIndex > 0) {
+ return OMX_ErrorNoMore;
+ }
+
+ if ((formatParams->nPortIndex == 0
+ && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
+ || (formatParams->nPortIndex == 1
+ && formatParams->eEncoding != OMX_AUDIO_CodingAMR)) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioAmr:
+ {
+ OMX_AUDIO_PARAM_AMRTYPE *amrParams =
+ (OMX_AUDIO_PARAM_AMRTYPE *)params;
+
+ if (amrParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (amrParams->nChannels != 1
+ || amrParams->eAMRDTXMode != OMX_AUDIO_AMRDTXModeOff
+ || amrParams->eAMRFrameFormat
+ != OMX_AUDIO_AMRFrameFormatFSF
+ || amrParams->eAMRBandMode < OMX_AUDIO_AMRBandModeWB0
+ || amrParams->eAMRBandMode > OMX_AUDIO_AMRBandModeWB8) {
+ return OMX_ErrorUndefined;
+ }
+
+ mBitRate = amrParams->nBitRate;
+
+ mMode = (VOAMRWBMODE)(
+ amrParams->eAMRBandMode - OMX_AUDIO_AMRBandModeWB0);
+
+ amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
+ amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
+
+ if (VO_ERR_NONE !=
+ mApiHandle->SetParam(
+ mEncoderHandle, VO_PID_AMRWB_MODE, &mMode)) {
+ ALOGE("Failed to set AMRWB encoder mode to %d", mMode);
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPcm:
+ {
+ OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (pcmParams->nChannels != 1
+ || pcmParams->nSamplingRate != (OMX_U32)kSampleRate) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+
+ default:
+ return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ }
+}
+
+void SoftAMRWBEncoder::onQueueFilled(OMX_U32 portIndex) {
+ if (mSignalledError) {
+ return;
+ }
+
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+
+ size_t numBytesPerInputFrame = kNumSamplesPerFrame * sizeof(int16_t);
+
+ for (;;) {
+ // We do the following until we run out of buffers.
+
+ while (mInputSize < numBytesPerInputFrame) {
+ // As long as there's still input data to be read we
+ // will drain "kNumSamplesPerFrame" samples
+ // into the "mInputFrame" buffer and then encode those
+ // as a unit into an output buffer.
+
+ if (mSawInputEOS || inQueue.empty()) {
+ return;
+ }
+
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+
+ const void *inData = inHeader->pBuffer + inHeader->nOffset;
+
+ size_t copy = numBytesPerInputFrame - mInputSize;
+ if (copy > inHeader->nFilledLen) {
+ copy = inHeader->nFilledLen;
+ }
+
+ if (mInputSize == 0) {
+ mInputTimeUs = inHeader->nTimeStamp;
+ }
+
+ memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
+ mInputSize += copy;
+
+ inHeader->nOffset += copy;
+ inHeader->nFilledLen -= copy;
+
+ // "Time" on the input buffer has in effect advanced by the
+ // number of audio frames we just advanced nOffset by.
+ inHeader->nTimeStamp +=
+ (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
+
+ if (inHeader->nFilledLen == 0) {
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ ALOGV("saw input EOS");
+ mSawInputEOS = true;
+
+ // Pad any remaining data with zeroes.
+ memset((uint8_t *)mInputFrame + mInputSize,
+ 0,
+ numBytesPerInputFrame - mInputSize);
+
+ mInputSize = numBytesPerInputFrame;
+ }
+
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+
+ inData = NULL;
+ inHeader = NULL;
+ inInfo = NULL;
+ }
+ }
+
+ // At this point we have all the input data necessary to encode
+ // a single frame, all we need is an output buffer to store the result
+ // in.
+
+ if (outQueue.empty()) {
+ return;
+ }
+
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+
+ uint8_t *outPtr = outHeader->pBuffer + outHeader->nOffset;
+ size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
+
+ VO_CODECBUFFER inputData;
+ memset(&inputData, 0, sizeof(inputData));
+ inputData.Buffer = (unsigned char *) mInputFrame;
+ inputData.Length = mInputSize;
+
+ CHECK_EQ(VO_ERR_NONE,
+ mApiHandle->SetInputData(mEncoderHandle, &inputData));
+
+ VO_CODECBUFFER outputData;
+ memset(&outputData, 0, sizeof(outputData));
+ VO_AUDIO_OUTPUTINFO outputInfo;
+ memset(&outputInfo, 0, sizeof(outputInfo));
+
+ outputData.Buffer = outPtr;
+ outputData.Length = outAvailable;
+ VO_U32 ret = mApiHandle->GetOutputData(
+ mEncoderHandle, &outputData, &outputInfo);
+ CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL);
+
+ outHeader->nFilledLen = outputData.Length;
+ outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
+
+ if (mSawInputEOS) {
+ // We also tag this output buffer with EOS if it corresponds
+ // to the final input buffer.
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+ }
+
+ outHeader->nTimeStamp = mInputTimeUs;
+
+#if 0
+ ALOGI("sending %ld bytes of data (time = %lld us, flags = 0x%08lx)",
+ outHeader->nFilledLen, mInputTimeUs, outHeader->nFlags);
+
+ hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
+#endif
+
+ outQueue.erase(outQueue.begin());
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+
+ outHeader = NULL;
+ outInfo = NULL;
+
+ mInputSize = 0;
+ }
+}
+
+} // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+ const char *name, const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+ return new android::SoftAMRWBEncoder(name, callbacks, appData, component);
+}
diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.h b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.h
new file mode 100644
index 0000000..d0c1dab
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SOFT_AMRWB_ENCODER_H_
+
+#define SOFT_AMRWB_ENCODER_H_
+
+#include "SimpleSoftOMXComponent.h"
+
+#include "voAMRWB.h"
+
+struct VO_AUDIO_CODECAPI;
+struct VO_MEM_OPERATOR;
+
+namespace android {
+
+struct SoftAMRWBEncoder : public SimpleSoftOMXComponent {
+ SoftAMRWBEncoder(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ virtual ~SoftAMRWBEncoder();
+
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual void onQueueFilled(OMX_U32 portIndex);
+
+private:
+ enum {
+ kNumBuffers = 4,
+ kNumSamplesPerFrame = 320,
+ };
+
+ void *mEncoderHandle;
+ VO_AUDIO_CODECAPI *mApiHandle;
+ VO_MEM_OPERATOR *mMemOperator;
+
+ OMX_U32 mBitRate;
+ VOAMRWBMODE mMode;
+
+ size_t mInputSize;
+ int16_t mInputFrame[kNumSamplesPerFrame];
+ int64_t mInputTimeUs;
+
+ bool mSawInputEOS;
+ bool mSignalledError;
+
+ void initPorts();
+ status_t initEncoder();
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftAMRWBEncoder);
+};
+
+} // namespace android
+
+#endif // SOFT_AMRWB_ENCODER_H_
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..5a1e536
--- /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..f42a27c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
@@ -0,0 +1,1090 @@
+/*
+ ** 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 */
+
+
+#define static_vo static __inline
+
+#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..e880684
--- /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..5395d2d
--- /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..53ca55e
--- /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..0bdda67
--- /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..658d28d
--- /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..560a997
--- /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..e399fb8
--- /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..865eea0
--- /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 */
+
+static const 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) */
+
+static const 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..9c73357
--- /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..b065eb4
--- /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..85fa73c
--- /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..3a6f963
--- /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..7b6196b
--- /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..442786a
--- /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..7b485ea
--- /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..7a0f564
--- /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..4a13f16
--- /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..d74ec8e
--- /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..bc36489
--- /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..b5d5280
--- /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..43c47e9
--- /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..b6b4e81
--- /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..4c1d0f0
--- /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..f08a678
--- /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..0062584
--- /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..6822f48
--- /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..04fd318
--- /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..282db92
--- /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..4aa317e
--- /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..856ada8
--- /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..49bdc2b
--- /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..3f4930c
--- /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..71bb532
--- /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..2d4c7cc
--- /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..e0b338d
--- /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..5ff0964
--- /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..b300224
--- /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..0c287a4
--- /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..1d5893f
--- /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..8230944
--- /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..14ba828
--- /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..4263cd4
--- /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..e786dde
--- /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..8efa9fb
--- /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..8904289
--- /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..6b782cb
--- /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..394fa83
--- /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..e45daac
--- /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..5731bdb
--- /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..8c477ca
--- /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..43db27a
--- /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..e78dc1f
--- /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..18698e2
--- /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..1ecc11f
--- /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/convolve.c b/media/libstagefright/codecs/amrwbenc/src/convolve.c
new file mode 100644
index 0000000..acba532
--- /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..d9245ed
--- /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..3b88514
--- /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..0c49d6b
--- /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..2cfaced
--- /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..d681f2e
--- /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..800b3f9
--- /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..565040f
--- /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..a6f9701
--- /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..c1c7b83
--- /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..8e66eb0
--- /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..bc1ec49
--- /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..1119bc7
--- /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..30a8bbd
--- /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..b4ba408
--- /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..49c622c
--- /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..4b2f8ed
--- /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..0f65541
--- /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..1d5d076
--- /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..7affbb2
--- /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..3b7853f
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/mem_align.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: mem_align.c
+
+ Content: Memory alloc alignments functions
+
+*******************************************************************************/
+
+
+#include "mem_align.h"
+#ifdef _MSC_VER
+#include <stddef.h>
+#else
+#include <stdint.h>
+#endif
+
+/*****************************************************************************
+*
+* 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 *) ((intptr_t) (tmp + alignment - 1) &
+ (~((intptr_t) (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..27cad76
--- /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..b8174b9
--- /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..6f55b8f
--- /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..0d66c31
--- /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..8404cf9
--- /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..c867bf7
--- /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..e8ca043
--- /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..80a0b73
--- /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..fc2f00d
--- /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..c711cd0
--- /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..b896863
--- /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..b0c04b5
--- /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..418cc06
--- /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..780f009
--- /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..1bda05a
--- /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..96779fd
--- /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..76ab1b1
--- /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..ea9da52
--- /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)
+ {
+ 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..d890044
--- /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..13dd2aa
--- /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..a02b48d
--- /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/Android.mk b/media/libstagefright/codecs/avc/Android.mk
new file mode 100644
index 0000000..2e43120
--- /dev/null
+++ b/media/libstagefright/codecs/avc/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/avc/common/Android.mk b/media/libstagefright/codecs/avc/common/Android.mk
new file mode 100644
index 0000000..22dee15
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ src/deblock.cpp \
+ src/dpb.cpp \
+ src/fmo.cpp \
+ src/mb_access.cpp \
+ src/reflist.cpp
+
+LOCAL_MODULE := libstagefright_avc_common
+
+LOCAL_CFLAGS := -DOSCL_EXPORT_REF= -DOSCL_IMPORT_REF=
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/include
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/avc/common/include/avc_types.h b/media/libstagefright/codecs/avc/common/include/avc_types.h
new file mode 100644
index 0000000..ec8b6de
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/include/avc_types.h
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+#ifndef AVC_TYPES_H_
+
+#define AVC_TYPES_H_
+
+#include <stdint.h>
+
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef int16_t int16;
+typedef uint32_t uint32;
+typedef int32_t int32;
+typedef unsigned int uint;
+
+#endif // AVC_TYPES_H_
diff --git a/media/libstagefright/codecs/avc/common/include/avcapi_common.h b/media/libstagefright/codecs/avc/common/include/avcapi_common.h
new file mode 100644
index 0000000..3331689
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/include/avcapi_common.h
@@ -0,0 +1,274 @@
+/* ------------------------------------------------------------------
+ * 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 common type definitions and enumerations used by AVC encoder
+and decoder libraries which are exposed to the users.
+@publishedAll
+*/
+
+#ifndef AVCAPI_COMMON_H_INCLUDED
+#define AVCAPI_COMMON_H_INCLUDED
+
+#include "avc_types.h"
+
+#define PV_MEMORY_POOL
+/**
+This is common return status.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_NO_BUFFER = -2,
+ AVC_MEMORY_FAIL = -1,
+ AVC_FAIL = 0,
+ AVC_SUCCESS = 1,
+ AVC_PICTURE_OUTPUT_READY = 2
+} AVCStatus;
+
+/**
+This enumeration is for profiles. The value follows the profile_idc in sequence
+parameter set rbsp. See Annex A.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_BASELINE = 66,
+ AVC_MAIN = 77,
+ AVC_EXTENDED = 88,
+ AVC_HIGH = 100,
+ AVC_HIGH10 = 110,
+ AVC_HIGH422 = 122,
+ AVC_HIGH444 = 144
+} AVCProfile;
+
+/**
+This enumeration is for levels. The value follows the level_idc in sequence
+parameter set rbsp. See Annex A.
+@published All
+*/
+typedef enum
+{
+ AVC_LEVEL_AUTO = 0,
+ AVC_LEVEL1_B = 9,
+ AVC_LEVEL1 = 10,
+ AVC_LEVEL1_1 = 11,
+ AVC_LEVEL1_2 = 12,
+ AVC_LEVEL1_3 = 13,
+ AVC_LEVEL2 = 20,
+ AVC_LEVEL2_1 = 21,
+ AVC_LEVEL2_2 = 22,
+ AVC_LEVEL3 = 30,
+ AVC_LEVEL3_1 = 31,
+ AVC_LEVEL3_2 = 32,
+ AVC_LEVEL4 = 40,
+ AVC_LEVEL4_1 = 41,
+ AVC_LEVEL4_2 = 42,
+ AVC_LEVEL5 = 50,
+ AVC_LEVEL5_1 = 51
+} AVCLevel;
+
+/**
+This enumeration follows Table 7-1 for NAL unit type codes.
+This may go to avccommon_api.h later (external common).
+@publishedAll
+*/
+typedef enum
+{
+ AVC_NALTYPE_SLICE = 1, /* non-IDR non-data partition */
+ AVC_NALTYPE_DPA = 2, /* data partition A */
+ AVC_NALTYPE_DPB = 3, /* data partition B */
+ AVC_NALTYPE_DPC = 4, /* data partition C */
+ AVC_NALTYPE_IDR = 5, /* IDR NAL */
+ AVC_NALTYPE_SEI = 6, /* supplemental enhancement info */
+ AVC_NALTYPE_SPS = 7, /* sequence parameter set */
+ AVC_NALTYPE_PPS = 8, /* picture parameter set */
+ AVC_NALTYPE_AUD = 9, /* access unit delimiter */
+ AVC_NALTYPE_EOSEQ = 10, /* end of sequence */
+ AVC_NALTYPE_EOSTREAM = 11, /* end of stream */
+ AVC_NALTYPE_FILL = 12 /* filler data */
+} AVCNalUnitType;
+
+/**
+This enumeration specifies debug logging type.
+This may go to avccommon_api.h later (external common).
+@publishedAll
+*/
+typedef enum
+{
+ AVC_LOGTYPE_ERROR = 0,
+ AVC_LOGTYPE_WARNING = 1,
+ AVC_LOGTYPE_INFO = 2
+} AVCLogType;
+
+/**
+This enumerate the status of certain flags.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_OFF = 0,
+ AVC_ON = 1
+} AVCFlag;
+
+/**
+This structure contains input information.
+Note, this structure is identical to AVCDecOutput for now.
+*/
+typedef struct tagAVCFrameIO
+{
+ /** A unique identification number for a particular instance of this structure.
+ To remain unchanged by the application between the time when it is given to the
+ library and the time when the library returns it back. */
+ uint32 id;
+
+ /** Array of pointers to Y,Cb,Cr content in 4:2:0 format. For AVC decoding,
+ this memory is allocated by the AVC decoder library. For AVC encoding, only the
+ memory for original unencoded frame is allocated by the application. Internal
+ memory is also allocated by the AVC encoder library. */
+ uint8 *YCbCr[3];
+
+ /** In/Out: Coded width of the luma component, it has to be multiple of 16. */
+ int pitch;
+
+ /** In/Out: Coded height of the luma component, must be multiple of 16. */
+ int height;
+
+ /** In/Out: Display width, less than picth */
+ int clip_width;
+
+ /** In/Out: Display height, less than height */
+ int clip_height;
+
+ /** Input: Origin of the display area [0]=>row, [1]=>column */
+ int clip_origin[2];
+
+ /** Output: Frame number in de/encoding order (not necessary)*/
+ uint32 coding_order;
+
+ /** Output: Frame number in displaying order (this may or may not be associated with the POC at all!!!). */
+ uint32 disp_order;
+
+ /** In/Out: Flag for use for reference or not. */
+ uint is_reference;
+
+ /** In/Out: Coding timestamp in msec (not display timestamp) */
+ uint32 coding_timestamp;
+
+ /* there could be something else here such as format, DON (decoding order number)
+ if available thru SEI, etc. */
+} AVCFrameIO;
+
+
+/** CALLBACK FUNCTION TO BE IMPLEMENTED BY APPLICATION */
+/** In AVCDecControls structure, userData is a pointer to an object with the following
+ member functions.
+*/
+
+
+/** @brief Decoded picture buffers (DPB) must be allocated or re-allocated before an
+ IDR frame is decoded. If PV_MEMORY_POOL is not defined, AVC lib will allocate DPB
+ internally which cannot be shared with the application. In that case, this function
+ will not be called.
+ @param userData The same value of userData in AVCHandle object.
+ @param frame_size_in_mbs The size of each frame in number of macroblocks.
+ @param num_frames The number of frames in DPB.
+ @return 1 for success, 0 for fail (cannot allocate DPB)
+*/
+
+typedef int (*FunctionType_DPBAlloc)(void *userData, uint frame_size_in_mbs, uint num_buffers);
+
+/** @brief AVC library calls this function is reserve a memory of one frame from the DPB.
+ Once reserved, this frame shall not be deleted or over-written by the app.
+ @param userData The same value of userData in AVCHandle object.
+ @param indx Index of a frame in DPB (AVC library keeps track of the index).
+ @param yuv The address of the yuv pointer returned to the AVC lib.
+ @return 1 for success, 0 for fail (no frames available to bind).
+ */
+typedef int (*FunctionType_FrameBind)(void *userData, int indx, uint8 **yuv);
+
+/** @brief AVC library calls this function once a bound frame is not needed for decoding
+ operation (falls out of the sliding window, or marked unused for reference).
+ @param userData The same value of userData in AVCHandle object.
+ @param indx Index of frame to be unbound (AVC library keeps track of the index).
+ @return none.
+*/
+typedef void (*FuctionType_FrameUnbind)(void *userData, int);
+
+/** Pointer to malloc function for general memory allocation, so that application can keep track of
+ memory usage.
+\param "size" "Size of requested memory in bytes."
+\param "attribute" "Some value specifying types, priority, etc. of the memory."
+\return "The address of the allocated memory casted to int"
+*/
+typedef int (*FunctionType_Malloc)(void *userData, int32 size, int attribute);
+
+/** Function pointer to free
+\param "mem" "Pointer to the memory to be freed casted to int"
+\return "void"
+*/
+typedef void (*FunctionType_Free)(void *userData, int mem);
+
+/** Debug logging information is returned to the application thru this function.
+\param "type" "Type of logging message, see definition of AVCLogType."
+\param "string1" "Logging message."
+\param "string2" "To be defined."
+*/
+typedef void (*FunctionType_DebugLog)(uint32 *userData, AVCLogType type, char *string1, int val1, int val2);
+
+/**
+This structure has to be allocated and maintained by the user of the library.
+This structure is used as a handle to the library object.
+*/
+typedef struct tagAVCHandle
+{
+ /** A pointer to the internal data structure. Users have to make sure that this value
+ is NULL at the beginning.
+ */
+ void *AVCObject;
+
+ /** A pointer to user object which has the following member functions used for
+ callback purpose. !!! */
+ void *userData;
+
+ /** Pointers to functions implemented by the users of AVC library */
+ FunctionType_DPBAlloc CBAVC_DPBAlloc;
+
+ FunctionType_FrameBind CBAVC_FrameBind;
+
+ FuctionType_FrameUnbind CBAVC_FrameUnbind;
+
+ FunctionType_Malloc CBAVC_Malloc;
+
+ FunctionType_Free CBAVC_Free;
+
+ FunctionType_DebugLog CBAVC_DebugLog;
+
+ /** Flag to enable debugging */
+ uint32 debugEnable;
+
+} AVCHandle;
+
+
+
+#ifdef PVDEBUGMSG_LOG
+#define DEBUG_LOG(a,b,c,d,e) CBAVC_DebugLog(a,b,c,d,e)
+#else
+#define DEBUG_LOG(a,b,c,d,e)
+#endif
+
+#endif /* _AVCAPI_COMMON_H_ */
diff --git a/media/libstagefright/codecs/avc/common/include/avcint_common.h b/media/libstagefright/codecs/avc/common/include/avcint_common.h
new file mode 100644
index 0000000..465e604
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/include/avcint_common.h
@@ -0,0 +1,882 @@
+/* ------------------------------------------------------------------
+ * 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 common code shared between AVC decoder and AVC encoder for
+internal use only.
+@publishedAll
+*/
+
+#ifndef AVCINT_COMMON_H_INCLUDED
+#define AVCINT_COMMON_H_INCLUDED
+
+#ifndef AVCAPI_COMMON_H_INCLUDED
+#include "avcapi_common.h"
+#endif
+
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+
+
+/**
+Mathematic functions defined in subclause 5.7.
+Can be replaced with assembly instructions for speedup.
+@publishedAll
+*/
+#define AVC_ABS(x) (((x)<0)? -(x) : (x))
+#define AVC_SIGN(x) (((x)<0)? -1 : 1)
+#define AVC_SIGN0(x) (((x)<0)? -1 : (((x)>0) ? 1 : 0))
+#define AVC_MAX(x,y) ((x)>(y)? (x):(y))
+#define AVC_MIN(x,y) ((x)<(y)? (x):(y))
+#define AVC_MEDIAN(A,B,C) ((A) > (B) ? ((A) < (C) ? (A) : (B) > (C) ? (B) : (C)): (B) < (C) ? (B) : (C) > (A) ? (C) : (A))
+#define AVC_CLIP3(a,b,x) (AVC_MAX(a,AVC_MIN(x,b))) /* clip x between a and b */
+#define AVC_CLIP(x) AVC_CLIP3(0,255,x)
+#define AVC_FLOOR(x) ((int)(x))
+#define AVC_RASTER_SCAN(x,y,n) ((x)+(y)*(n))
+#define AVC_ROUND(x) (AVC_SIGN(x)*AVC_FLOOR(AVC_ABS(x)+0.5))
+#define AVC_INVERSE_RASTER_SCAN(a,b,c,d,e) (((e)==0)? (((a)%((d)/(b)))*(b)): (((a)/((d)/(b)))*(c)))
+/* a:block address, b:block width, c:block height, d:total_width, e:x or y coordinate */
+
+#define DEFAULT_ATTR 0 /* default memory attribute */
+#define FAST_MEM_ATTR 1 /* fast memory attribute */
+
+
+/* This section is for definition of constants. */
+#define MB_SIZE 16
+#define BLOCK_SIZE 4
+#define EMULATION_PREVENTION_THREE_BYTE 0x3
+#define NUM_PIXELS_IN_MB (24*16)
+#define NUM_BLKS_IN_MB 24
+
+#define AVCNumI4PredMode 9
+#define AVCNumI16PredMode 4
+#define AVCNumIChromaMode 4
+
+/* constants used in the structures below */
+#define MAXIMUMVALUEOFcpb_cnt 32 /* used in HRDParams */
+#define MAX_NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE 255 /* used in SeqParamSet */
+#define MAX_NUM_SLICE_GROUP 8 /* used in PicParamSet */
+#define MAX_REF_PIC_LIST_REORDERING 32 /* 32 is maximum according to Annex A, SliceHeader */
+#define MAX_DEC_REF_PIC_MARKING 64 /* 64 is the maximum possible given the max num ref pictures to 31. */
+#define MAX_FS (16+1) /* pre-defined size of frame store array */
+#define MAX_LEVEL_IDX 15 /* only 15 levels defined for now */
+#define MAX_REF_PIC_LIST 33 /* max size of the RefPicList0 and RefPicList1 */
+
+
+/**
+Architectural related macros.
+@publishedAll
+*/
+#ifdef USE_PRED_BLOCK
+#define MB_BASED_DEBLOCK
+#endif
+
+/**
+Picture type, PV created.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_FRAME = 3
+} AVCPictureType;
+
+/**
+This slice type follows Table 7-3. The bottom 5 items may not needed.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_P_SLICE = 0,
+ AVC_B_SLICE = 1,
+ AVC_I_SLICE = 2,
+ AVC_SP_SLICE = 3,
+ AVC_SI_SLICE = 4,
+ AVC_P_ALL_SLICE = 5,
+ AVC_B_ALL_SLICE = 6,
+ AVC_I_ALL_SLICE = 7,
+ AVC_SP_ALL_SLICE = 8,
+ AVC_SI_ALL_SLICE = 9
+} AVCSliceType;
+
+/**
+Types of the macroblock and partition. PV Created.
+@publishedAll
+*/
+typedef enum
+{
+ /* intra */
+ AVC_I4,
+ AVC_I16,
+ AVC_I_PCM,
+ AVC_SI4,
+
+ /* inter for both P and B*/
+ AVC_BDirect16,
+ AVC_P16,
+ AVC_P16x8,
+ AVC_P8x16,
+ AVC_P8,
+ AVC_P8ref0,
+ AVC_SKIP
+} AVCMBMode;
+
+/**
+Enumeration for sub-macroblock mode, interpreted from sub_mb_type.
+@publishedAll
+*/
+typedef enum
+{
+ /* for sub-partition mode */
+ AVC_BDirect8,
+ AVC_8x8,
+ AVC_8x4,
+ AVC_4x8,
+ AVC_4x4
+} AVCSubMBMode;
+
+/**
+Mode of prediction of partition or sub-partition. PV Created.
+Do not change the order!!! Used in table look-up mode prediction in
+vlc.c.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_Pred_L0 = 0,
+ AVC_Pred_L1,
+ AVC_BiPred,
+ AVC_Direct
+} AVCPredMode;
+
+
+/**
+Mode of intra 4x4 prediction. Table 8-2
+@publishedAll
+*/
+typedef enum
+{
+ AVC_I4_Vertical = 0,
+ AVC_I4_Horizontal,
+ AVC_I4_DC,
+ AVC_I4_Diagonal_Down_Left,
+ AVC_I4_Diagonal_Down_Right,
+ AVC_I4_Vertical_Right,
+ AVC_I4_Horizontal_Down,
+ AVC_I4_Vertical_Left,
+ AVC_I4_Horizontal_Up
+} AVCIntra4x4PredMode;
+
+/**
+Mode of intra 16x16 prediction. Table 8-3
+@publishedAll
+*/
+typedef enum
+{
+ AVC_I16_Vertical = 0,
+ AVC_I16_Horizontal,
+ AVC_I16_DC,
+ AVC_I16_Plane
+} AVCIntra16x16PredMode;
+
+
+/**
+Mode of intra chroma prediction. Table 8-4
+@publishedAll
+*/
+typedef enum
+{
+ AVC_IC_DC = 0,
+ AVC_IC_Horizontal,
+ AVC_IC_Vertical,
+ AVC_IC_Plane
+} AVCIntraChromaPredMode;
+
+/**
+Type of residual going to residual_block_cavlc function, PV created.
+@publishedAll
+*/
+typedef enum
+{
+ AVC_Luma,
+ AVC_Intra16DC,
+ AVC_Intra16AC,
+ AVC_ChromaDC,
+ AVC_ChromaAC
+} AVCResidualType;
+
+
+/**
+This structure contains VUI parameters as specified in Annex E.
+Some variables may be removed from the structure if they are found to be useless to store.
+@publishedAll
+*/
+typedef struct tagHRDParams
+{
+ uint cpb_cnt_minus1; /* ue(v), range 0..31 */
+ uint bit_rate_scale; /* u(4) */
+ uint cpb_size_scale; /* u(4) */
+ uint32 bit_rate_value_minus1[MAXIMUMVALUEOFcpb_cnt];/* ue(v), range 0..2^32-2 */
+ uint32 cpb_size_value_minus1[MAXIMUMVALUEOFcpb_cnt]; /* ue(v), range 0..2^32-2 */
+ uint cbr_flag[MAXIMUMVALUEOFcpb_cnt]; /* u(1) */
+ uint initial_cpb_removal_delay_length_minus1; /* u(5), default 23 */
+ uint cpb_removal_delay_length_minus1; /* u(5), default 23 */
+ uint dpb_output_delay_length_minus1; /* u(5), default 23 */
+ uint time_offset_length; /* u(5), default 24 */
+} AVCHRDParams;
+
+/**
+This structure contains VUI parameters as specified in Annex E.
+Some variables may be removed from the structure if they are found to be useless to store.
+@publishedAll
+*/
+typedef struct tagVUIParam
+{
+ uint aspect_ratio_info_present_flag; /* u(1) */
+ uint aspect_ratio_idc; /* u(8), table E-1 */
+ uint sar_width; /* u(16) */
+ uint sar_height; /* u(16) */
+ uint overscan_info_present_flag; /* u(1) */
+ uint overscan_appropriate_flag; /* u(1) */
+ uint video_signal_type_present_flag; /* u(1) */
+ uint video_format; /* u(3), Table E-2, default 5, unspecified */
+ uint video_full_range_flag; /* u(1) */
+ uint colour_description_present_flag; /* u(1) */
+ uint colour_primaries; /* u(8), Table E-3, default 2, unspecified */
+ uint transfer_characteristics; /* u(8), Table E-4, default 2, unspecified */
+ uint matrix_coefficients; /* u(8), Table E-5, default 2, unspecified */
+ uint chroma_location_info_present_flag; /* u(1) */
+ uint chroma_sample_loc_type_top_field; /* ue(v), Fig. E-1range 0..5, default 0 */
+ uint chroma_sample_loc_type_bottom_field; /* ue(v) */
+ uint timing_info_present_flag; /* u(1) */
+ uint num_units_in_tick; /* u(32), must be > 0 */
+ uint time_scale; /* u(32), must be > 0 */
+ uint fixed_frame_rate_flag; /* u(1), Eq. C-13 */
+ uint nal_hrd_parameters_present_flag; /* u(1) */
+ AVCHRDParams nal_hrd_parameters; /* hrd_paramters */
+ uint vcl_hrd_parameters_present_flag; /* u(1) */
+ AVCHRDParams vcl_hrd_parameters; /* hrd_paramters */
+ /* if ((nal_hrd_parameters_present_flag || (vcl_hrd_parameters_present_flag)) */
+ uint low_delay_hrd_flag; /* u(1) */
+ uint pic_struct_present_flag;
+ uint bitstream_restriction_flag; /* u(1) */
+ uint motion_vectors_over_pic_boundaries_flag; /* u(1) */
+ uint max_bytes_per_pic_denom; /* ue(v), default 2 */
+ uint max_bits_per_mb_denom; /* ue(v), range 0..16, default 1 */
+ uint log2_max_mv_length_vertical; /* ue(v), range 0..16, default 16 */
+ uint log2_max_mv_length_horizontal; /* ue(v), range 0..16, default 16 */
+ uint max_dec_frame_reordering; /* ue(v) */
+ uint max_dec_frame_buffering; /* ue(v) */
+} AVCVUIParams;
+
+
+/**
+This structure contains information in a sequence parameter set NAL.
+Some variables may be removed from the structure if they are found to be useless to store.
+@publishedAll
+*/
+typedef struct tagSeqParamSet
+{
+ uint Valid; /* indicates the parameter set is valid */
+
+ uint profile_idc; /* u(8) */
+ uint constrained_set0_flag; /* u(1) */
+ uint constrained_set1_flag; /* u(1) */
+ uint constrained_set2_flag; /* u(1) */
+ uint constrained_set3_flag; /* u(1) */
+ uint level_idc; /* u(8) */
+ uint seq_parameter_set_id; /* ue(v), range 0..31 */
+ uint log2_max_frame_num_minus4; /* ue(v), range 0..12 */
+ uint pic_order_cnt_type; /* ue(v), range 0..2 */
+ /* if( pic_order_cnt_type == 0 ) */
+ uint log2_max_pic_order_cnt_lsb_minus4; /* ue(v), range 0..12 */
+ /* else if( pic_order_cnt_type == 1 ) */
+ uint delta_pic_order_always_zero_flag; /* u(1) */
+ int32 offset_for_non_ref_pic; /* se(v) */
+ int32 offset_for_top_to_bottom_field; /* se(v) */
+ uint num_ref_frames_in_pic_order_cnt_cycle; /* ue(v) , range 0..255 */
+ /* for( i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ ) */
+ int32 offset_for_ref_frame[MAX_NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE]; /* se(v) */
+ uint num_ref_frames; /* ue(v), range 0..16 */
+ uint gaps_in_frame_num_value_allowed_flag; /* u(1) */
+ uint pic_width_in_mbs_minus1; /* ue(v) */
+ uint pic_height_in_map_units_minus1; /* ue(v) */
+ uint frame_mbs_only_flag; /* u(1) */
+ /* if( !frame_mbs_only_flag ) */
+ uint mb_adaptive_frame_field_flag; /* u(1) */
+ uint direct_8x8_inference_flag; /* u(1), must be 1 when frame_mbs_only_flag is 0 */
+ uint frame_cropping_flag; /* u(1) */
+ /* if( frmae_cropping_flag) */
+ uint frame_crop_left_offset; /* ue(v) */
+ uint frame_crop_right_offset; /* ue(v) */
+ uint frame_crop_top_offset; /* ue(v) */
+ uint frame_crop_bottom_offset; /* ue(v) */
+ uint vui_parameters_present_flag; /* u(1) */
+// uint nal_hrd_parameters_present_flag;
+// uint vcl_hrd_parameters_present_flag;
+// AVCHRDParams *nal_hrd_parameters;
+// AVCHRDParams *vcl_hrd_parameters;
+ AVCVUIParams vui_parameters; /* AVCVUIParam */
+} AVCSeqParamSet;
+
+/**
+This structure contains information in a picture parameter set NAL.
+Some variables may be removed from the structure if they are found to be useless to store.
+@publishedAll
+*/
+typedef struct tagPicParamSet
+{
+ uint pic_parameter_set_id; /* ue(v), range 0..255 */
+ uint seq_parameter_set_id; /* ue(v), range 0..31 */
+ uint entropy_coding_mode_flag; /* u(1) */
+ uint pic_order_present_flag; /* u(1) */
+ uint num_slice_groups_minus1; /* ue(v), range in Annex A */
+ /* if( num_slice_groups_minus1 > 0) */
+ uint slice_group_map_type; /* ue(v), range 0..6 */
+ /* if( slice_group_map_type = = 0 ) */
+ /* for(0:1:num_slice_groups_minus1) */
+ uint run_length_minus1[MAX_NUM_SLICE_GROUP]; /* ue(v) */
+ /* else if( slice_group_map_type = = 2 ) */
+ /* for(0:1:num_slice_groups_minus1-1) */
+ uint top_left[MAX_NUM_SLICE_GROUP-1]; /* ue(v) */
+ uint bottom_right[MAX_NUM_SLICE_GROUP-1]; /* ue(v) */
+ /* else if( slice_group_map_type = = 3 || 4 || 5 */
+ uint slice_group_change_direction_flag; /* u(1) */
+ uint slice_group_change_rate_minus1; /* ue(v) */
+ /* else if( slice_group_map_type = = 6 ) */
+ uint pic_size_in_map_units_minus1; /* ue(v) */
+ /* for(0:1:pic_size_in_map_units_minus1) */
+ uint *slice_group_id; /* complete MBAmap u(v) */
+ uint num_ref_idx_l0_active_minus1; /* ue(v), range 0..31 */
+ uint num_ref_idx_l1_active_minus1; /* ue(v), range 0..31 */
+ uint weighted_pred_flag; /* u(1) */
+ uint weighted_bipred_idc; /* u(2), range 0..2 */
+ int pic_init_qp_minus26; /* se(v), range -26..25 */
+ int pic_init_qs_minus26; /* se(v), range -26..25 */
+ int chroma_qp_index_offset; /* se(v), range -12..12 */
+ uint deblocking_filter_control_present_flag; /* u(1) */
+ uint constrained_intra_pred_flag; /* u(1) */
+ uint redundant_pic_cnt_present_flag; /* u(1) */
+} AVCPicParamSet;
+
+
+/**
+This structure contains slice header information.
+Some variables may be removed from the structure if they are found to be useless to store.
+@publishedAll
+*/
+typedef struct tagSliceHeader
+{
+ uint first_mb_in_slice; /* ue(v) */
+ AVCSliceType slice_type; /* ue(v), Table 7-3, range 0..9 */
+ uint pic_parameter_set_id; /* ue(v), range 0..255 */
+ uint frame_num; /* u(v), see log2max_frame_num_minus4 */
+ /* if( !frame_mbs_only_flag) */
+ uint field_pic_flag; /* u(1) */
+ /* if(field_pic_flag) */
+ uint bottom_field_flag; /* u(1) */
+ /* if(nal_unit_type == 5) */
+ uint idr_pic_id; /* ue(v), range 0..65535 */
+ /* if(pic_order_cnt_type==0) */
+ uint pic_order_cnt_lsb; /* u(v), range 0..MaxPicOrderCntLsb-1 */
+ /* if(pic_order_present_flag && !field_pic_flag) */
+ int32 delta_pic_order_cnt_bottom; /* se(v) */
+ /* if(pic_order_cnt_type==1 && !delta_pic_order_always_zero_flag) */
+ /* if(pic_order_present_flag && !field_pic_flag) */
+ int32 delta_pic_order_cnt[2];
+ /* if(redundant_pic_cnt_present_flag) */
+ uint redundant_pic_cnt; /* ue(v), range 0..127 */
+ /* if(slice_type == B) */
+ uint direct_spatial_mv_pred_flag; /* u(1) */
+ /* if(slice_type == P || slice_type==SP || slice_type==B) */
+ uint num_ref_idx_active_override_flag; /* u(1) */
+ /* if(num_ref_idx_active_override_flag) */
+ uint num_ref_idx_l0_active_minus1; /* ue(v) */
+ /* if(slie_type == B) */
+ uint num_ref_idx_l1_active_minus1; /* ue(v) */
+
+ /* ref_pic_list_reordering() */
+ uint ref_pic_list_reordering_flag_l0; /* u(1) */
+ uint reordering_of_pic_nums_idc_l0[MAX_REF_PIC_LIST_REORDERING]; /* ue(v), range 0..3 */
+ uint abs_diff_pic_num_minus1_l0[MAX_REF_PIC_LIST_REORDERING]; /* ue(v) */
+ uint long_term_pic_num_l0[MAX_REF_PIC_LIST_REORDERING]; /* ue(v) */
+ uint ref_pic_list_reordering_flag_l1; /* u(1) */
+ uint reordering_of_pic_nums_idc_l1[MAX_REF_PIC_LIST_REORDERING]; /* ue(v), range 0..3 */
+ uint abs_diff_pic_num_minus1_l1[MAX_REF_PIC_LIST_REORDERING]; /* ue(v) */
+ uint long_term_pic_num_l1[MAX_REF_PIC_LIST_REORDERING]; /* ue(v) */
+
+ /* end ref_pic_list_reordering() */
+ /* if(nal_ref_idc!=0) */
+ /* dec_ref_pic_marking() */
+ uint no_output_of_prior_pics_flag; /* u(1) */
+ uint long_term_reference_flag; /* u(1) */
+ uint adaptive_ref_pic_marking_mode_flag; /* u(1) */
+ uint memory_management_control_operation[MAX_DEC_REF_PIC_MARKING]; /* ue(v), range 0..6 */
+ uint difference_of_pic_nums_minus1[MAX_DEC_REF_PIC_MARKING]; /* ue(v) */
+ uint long_term_pic_num[MAX_DEC_REF_PIC_MARKING]; /* ue(v) */
+ uint long_term_frame_idx[MAX_DEC_REF_PIC_MARKING]; /* ue(v) */
+ uint max_long_term_frame_idx_plus1[MAX_DEC_REF_PIC_MARKING]; /* ue(v) */
+ /* end dec_ref_pic_marking() */
+ /* if(entropy_coding_mode_flag && slice_type!=I && slice_type!=SI) */
+ uint cabac_init_idc; /* ue(v), range 0..2 */
+ int slice_qp_delta; /* se(v), range 0..51 */
+ /* if(slice_type==SP || slice_type==SI) */
+ /* if(slice_type==SP) */
+ uint sp_for_switch_flag; /* u(1) */
+ int slice_qs_delta; /* se(v) */
+
+ /* if(deblocking_filter_control_present_flag)*/
+ uint disable_deblocking_filter_idc; /* ue(v), range 0..2 */
+ /* if(disable_deblocking_filter_idc!=1) */
+ int slice_alpha_c0_offset_div2; /* se(v), range -6..6, default 0 */
+ int slice_beta_offset_div_2; /* se(v), range -6..6, default 0 */
+ /* if(num_slice_groups_minus1>0 && slice_group_map_type>=3 && slice_group_map_type<=5)*/
+ uint slice_group_change_cycle; /* u(v), use ceil(log2(PicSizeInMapUnits/SliceGroupChangeRate + 1)) bits*/
+
+} AVCSliceHeader;
+
+/**
+This struct contains information about the neighboring pixel.
+@publishedAll
+*/
+typedef struct tagPixPos
+{
+ int available;
+ int mb_addr; /* macroblock address of the current pixel, see below */
+ int x; /* x,y positions of current pixel relative to the macroblock mb_addr */
+ int y;
+ int pos_x; /* x,y positions of current pixel relative to the picture. */
+ int pos_y;
+} AVCPixelPos;
+
+typedef struct tagNeighborAvailability
+{
+ int left;
+ int top; /* macroblock address of the current pixel, see below */
+ int top_right; /* x,y positions of current pixel relative to the macroblock mb_addr */
+} AVCNeighborAvailability;
+
+
+/**
+This structure contains picture data and related information necessary to be used as
+reference frame.
+@publishedAll
+*/
+typedef struct tagPictureData
+{
+ uint16 RefIdx; /* index used for reference frame */
+ uint8 *Sl; /* derived from base_dpb in AVCFrameStore */
+ uint8 *Scb; /* for complementary fields, YUV are interlaced */
+ uint8 *Scr; /* Sl of top_field and bottom_fields will be one line apart and the
+ stride will be 2 times the width. */
+ /* For non-complementary field, the above still applies. A special
+ output formatting is required. */
+
+ /* Then, necessary variables that need to be stored */
+ AVCPictureType picType; /* frame, top-field or bot-field */
+ /*bool*/
+ uint isReference;
+ /*bool*/
+ uint isLongTerm;
+ int PicOrderCnt;
+ int PicNum;
+ int LongTermPicNum;
+
+ int width; /* how many pixel per line */
+ int height;/* how many line */
+ int pitch; /* how many pixel between the line */
+
+ uint padded; /* flag for being padded */
+
+} AVCPictureData;
+
+/**
+This structure contains information for frame storage.
+@publishedAll
+*/
+typedef struct tagFrameStore
+{
+ uint8 *base_dpb; /* base pointer for the YCbCr */
+
+ int IsReference; /* 0=not used for ref; 1=top used; 2=bottom used; 3=both fields (or frame) used */
+ int IsLongTerm; /* 0=not used for ref; 1=top used; 2=bottom used; 3=both fields (or frame) used */
+ /* if IsLongTerm is true, IsReference can be ignored. */
+ /* if IsReference is true, IsLongterm will be checked for short-term or long-term. */
+ /* IsUsed must be true to enable the validity of IsReference and IsLongTerm */
+
+ int IsOutputted; /* has it been outputted via AVCDecGetOutput API, then don't output it again,
+ wait until it is returned. */
+ AVCPictureData frame;
+
+ int FrameNum;
+ int FrameNumWrap;
+ int LongTermFrameIdx;
+ int PicOrderCnt; /* of the frame, smaller of the 2 fields */
+
+} AVCFrameStore;
+
+/**
+This structure maintains the actual memory for the decoded picture buffer (DPB) which is
+allocated at the beginning according to profile/level.
+Once decoded_picture_buffer is allocated, Sl,Scb,Scr in
+AVCPictureData structure just point to the address in decoded_picture_buffer.
+used_size maintains the used space.
+NOTE:: In order to maintain contiguous memory space, memory equal to a single frame is
+assigned at a time. Two opposite fields reside in the same frame memory.
+
+ |-------|---|---|---|xxx|-------|xxx|---|-------| decoded_picture_buffer
+ frame top bot top frame bot frame
+ 0 1 1 2 3 4 5
+
+ bot 2 and top 4 do not exist, the memory is not used.
+
+@publishedAll
+*/
+typedef struct tagDecPicBuffer
+{
+ uint8 *decoded_picture_buffer; /* actual memory */
+ uint32 dpb_size; /* size of dpb in bytes */
+ uint32 used_size; /* used size */
+ struct tagFrameStore *fs[MAX_FS]; /* list of frame stored, actual buffer */
+ int num_fs; /* size of fs */
+
+} AVCDecPicBuffer;
+
+
+/**
+This structure contains macroblock related variables.
+@publishedAll
+*/
+typedef struct tagMacroblock
+{
+ AVCIntraChromaPredMode intra_chroma_pred_mode; /* ue(v) */
+
+ int32 mvL0[16]; /* motion vectors, 16 bit packed (x,y) per element */
+ int32 mvL1[16];
+ int16 ref_idx_L0[4];
+ int16 ref_idx_L1[4];
+ uint16 RefIdx[4]; /* ref index, has value of AVCPictureData->RefIdx */
+ /* stored data */
+ /*bool*/
+ uint mb_intra; /* intra flag */
+ /*bool*/
+ uint mb_bottom_field;
+
+ AVCMBMode mbMode; /* type of MB prediction */
+ AVCSubMBMode subMbMode[4]; /* for each 8x8 partition */
+
+ uint CBP; /* CodeBlockPattern */
+ AVCIntra16x16PredMode i16Mode; /* Intra16x16PredMode */
+ AVCIntra4x4PredMode i4Mode[16]; /* Intra4x4PredMode, in raster scan order */
+ int NumMbPart; /* number of partition */
+ AVCPredMode MBPartPredMode[4][4]; /* prediction mode [MBPartIndx][subMBPartIndx] */
+ int MbPartWidth;
+ int MbPartHeight;
+ int NumSubMbPart[4]; /* for each 8x8 partition */
+ int SubMbPartWidth[4]; /* for each 8x8 partition */
+ int SubMbPartHeight[4]; /* for each 8x8 partition */
+
+ uint8 nz_coeff[NUM_BLKS_IN_MB]; /* [blk_y][blk_x], Chroma is [4..5][0...3], see predict_nnz() function */
+
+ int QPy; /* Luma QP */
+ int QPc; /* Chroma QP */
+ int QSc; /* Chroma QP S-picture */
+
+ int slice_id; // MC slice
+} AVCMacroblock;
+
+
+/**
+This structure contains common internal variables between the encoder and decoder
+such that some functions can be shared among them.
+@publishedAll
+*/
+typedef struct tagCommonObj
+{
+ /* put these 2 up here to make sure they are word-aligned */
+ int16 block[NUM_PIXELS_IN_MB]; /* for transformed residue coefficient */
+ uint8 *pred_block; /* pointer to prediction block, could point to a frame */
+#ifdef USE_PRED_BLOCK
+ uint8 pred[688]; /* for prediction */
+ /* Luma [0-399], Cb [400-543], Cr[544-687] */
+#endif
+ int pred_pitch; /* either equal to 20 or to frame pitch */
+
+ /* temporary buffers for intra prediction */
+ /* these variables should remain inside fast RAM */
+#ifdef MB_BASED_DEBLOCK
+ uint8 *intra_pred_top; /* a row of pixel for intra prediction */
+ uint8 intra_pred_left[17]; /* a column of pixel for intra prediction */
+ uint8 *intra_pred_top_cb;
+ uint8 intra_pred_left_cb[9];
+ uint8 *intra_pred_top_cr;
+ uint8 intra_pred_left_cr[9];
+#endif
+ /* pointer to the prediction area for intra prediction */
+ uint8 *pintra_pred_top; /* pointer to the top intra prediction value */
+ uint8 *pintra_pred_left; /* pointer to the left intra prediction value */
+ uint8 intra_pred_topleft; /* the [-1,-1] neighboring pixel */
+ uint8 *pintra_pred_top_cb;
+ uint8 *pintra_pred_left_cb;
+ uint8 intra_pred_topleft_cb;
+ uint8 *pintra_pred_top_cr;
+ uint8 *pintra_pred_left_cr;
+ uint8 intra_pred_topleft_cr;
+
+ int QPy;
+ int QPc;
+ int QPy_div_6;
+ int QPy_mod_6;
+ int QPc_div_6;
+ int QPc_mod_6;
+ /**** nal_unit ******/
+ /* previously in AVCNALUnit format */
+ uint NumBytesInRBSP;
+ int forbidden_bit;
+ int nal_ref_idc;
+ AVCNalUnitType nal_unit_type;
+ AVCNalUnitType prev_nal_unit_type;
+ /*bool*/
+ uint slice_data_partitioning; /* flag when nal_unit_type is between 2 and 4 */
+ /**** ******** ******/
+ AVCSliceType slice_type;
+ AVCDecPicBuffer *decPicBuf; /* decoded picture buffer */
+
+ AVCSeqParamSet *currSeqParams; /* the currently used one */
+
+ AVCPicParamSet *currPicParams; /* the currently used one */
+ uint seq_parameter_set_id;
+ /* slice header */
+ AVCSliceHeader *sliceHdr; /* slice header param syntax variables */
+
+ AVCPictureData *currPic; /* pointer to current picture */
+ AVCFrameStore *currFS; /* pointer to current frame store */
+ AVCPictureType currPicType; /* frame, top-field or bot-field */
+ /*bool*/
+ uint newPic; /* flag for new picture */
+ uint newSlice; /* flag for new slice */
+ AVCPictureData *prevRefPic; /* pointer to previous picture */
+
+ AVCMacroblock *mblock; /* array of macroblocks covering entire picture */
+ AVCMacroblock *currMB; /* pointer to current macroblock */
+ uint mbNum; /* number of current MB */
+ int mb_x; /* x-coordinate of the current mbNum */
+ int mb_y; /* y-coordinate of the current mbNum */
+
+ /* For internal operation, scratch memory for MV, prediction, transform, etc.*/
+ uint32 cbp4x4; /* each bit represent nonzero 4x4 block in reverse raster scan order */
+ /* starting from luma, Cb and Cr, lsb toward msb */
+ int mvd_l0[4][4][2]; /* [mbPartIdx][subMbPartIdx][compIdx], se(v) */
+ int mvd_l1[4][4][2]; /* [mbPartIdx][subMbPartIdx][compIdx], se(v) */
+
+ int mbAddrA, mbAddrB, mbAddrC, mbAddrD; /* address of neighboring MBs */
+ /*bool*/
+ uint mbAvailA, mbAvailB, mbAvailC, mbAvailD; /* availability */
+ /*bool*/
+ uint intraAvailA, intraAvailB, intraAvailC, intraAvailD; /* for intra mode */
+ /***********************************************/
+ /* The following variables are defined in the draft. */
+ /* They may need to be stored in PictureData structure and used for reference. */
+ /* In that case, just move or copy it to AVCDecPictureData structure. */
+
+ int padded_size; /* size of extra padding to a frame */
+
+ uint MaxFrameNum; /*2^(log2_max_frame_num_minus4+4), range 0.. 2^16-1 */
+ uint MaxPicOrderCntLsb; /*2^(log2_max_pic_order_cnt_lsb_minus4+4), 0..2^16-1 */
+ uint PicWidthInMbs; /*pic_width_in_mbs_minus1+1 */
+ uint PicWidthInSamplesL; /* PicWidthInMbs*16 */
+ uint PicWidthInSamplesC; /* PicWIdthInMbs*8 */
+ uint PicHeightInMapUnits; /* pic_height_in_map_units_minus1+1 */
+ uint PicSizeInMapUnits; /* PicWidthInMbs*PicHeightInMapUnits */
+ uint FrameHeightInMbs; /*(2-frame_mbs_only_flag)*PicHeightInMapUnits */
+
+ uint SliceGroupChangeRate; /* slice_group_change_rate_minus1 + 1 */
+
+ /* access unit */
+ uint primary_pic_type; /* u(3), Table 7-2, kinda informative only */
+
+ /* slice data partition */
+ uint slice_id; /* ue(v) */
+
+ uint UnusedShortTermFrameNum;
+ uint PrevRefFrameNum;
+ uint MbaffFrameFlag; /* (mb_adaptive_frame_field_flag && !field_pic_flag) */
+ uint PicHeightInMbs; /* FrameHeightInMbs/(1+field_pic_flag) */
+ int PicHeightInSamplesL; /* PicHeightInMbs*16 */
+ int PicHeightInSamplesC; /* PicHeightInMbs*8 */
+ uint PicSizeInMbs; /* PicWidthInMbs*PicHeightInMbs */
+ uint level_idc;
+ int numMBs;
+ uint MaxPicNum;
+ uint CurrPicNum;
+ int QSy; /* 26+pic_init_qp_minus26+slice_qs_delta */
+ int FilterOffsetA;
+ int FilterOffsetB;
+ uint MapUnitsInSliceGroup0; /* Min(slie_group_change_cycle*SliceGroupChangeRate,PicSizeInMapUnits) */
+ /* dec_ref_pic_marking */
+ int MaxLongTermFrameIdx;
+ int LongTermFrameIdx;
+
+ /* POC related variables */
+ /*bool*/
+ uint mem_mgr_ctrl_eq_5; /* if memory_management_control_operation equal to 5 flag */
+ int PicOrderCnt;
+ int BottomFieldOrderCnt, TopFieldOrderCnt;
+ /* POC mode 0 */
+ int prevPicOrderCntMsb;
+ uint prevPicOrderCntLsb;
+ int PicOrderCntMsb;
+ /* POC mode 1 */
+ int prevFrameNumOffset, FrameNumOffset;
+ uint prevFrameNum;
+ int absFrameNum;
+ int picOrderCntCycleCnt, frameNumInPicOrderCntCycle;
+ int expectedDeltaPerPicOrderCntCycle;
+ int expectedPicOrderCnt;
+
+ /* FMO */
+ int *MbToSliceGroupMap; /* to be re-calculate at the beginning */
+
+ /* ref pic list */
+ AVCPictureData *RefPicList0[MAX_REF_PIC_LIST]; /* list 0 */
+ AVCPictureData *RefPicList1[MAX_REF_PIC_LIST]; /* list 1 */
+ AVCFrameStore *refFrameList0ShortTerm[32];
+ AVCFrameStore *refFrameList1ShortTerm[32];
+ AVCFrameStore *refFrameListLongTerm[32];
+ int refList0Size;
+ int refList1Size;
+
+ /* slice data semantics*/
+ int mb_skip_run; /* ue(v) */
+ /*uint mb_skip_flag;*/ /* ae(v) */
+ /* uint end_of_slice_flag;*//* ae(v) */
+ /***********************************************/
+
+ /* function pointers */
+ int (*is_short_ref)(AVCPictureData *s);
+ int (*is_long_ref)(AVCPictureData *s);
+
+} AVCCommonObj;
+
+/**
+Commonly used constant arrays.
+@publishedAll
+*/
+/**
+Zigzag scan from 1-D to 2-D. */
+const static uint8 ZZ_SCAN[16] = {0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15};
+/* Zigzag scan from 1-D to 2-D output to block[24][16]. */
+const static uint8 ZZ_SCAN_BLOCK[16] = {0, 1, 16, 32, 17, 2, 3, 18, 33, 48, 49, 34, 19, 35, 50, 51};
+
+/**
+From zigzag to raster for luma DC value */
+const static uint8 ZIGZAG2RASTERDC[16] = {0, 4, 64, 128, 68, 8, 12, 72, 132, 192, 196, 136, 76, 140, 200, 204};
+
+
+/**
+Mapping from coding scan block indx to raster scan block index */
+const static int blkIdx2blkX[16] = {0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3};
+const static int blkIdx2blkY[16] = {0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3};
+/** from [blk8indx][blk4indx] to raster scan index */
+const static int blkIdx2blkXY[4][4] = {{0, 1, 4, 5}, {2, 3, 6, 7}, {8, 9, 12, 13}, {10, 11, 14, 15}};
+
+/*
+Availability of the neighboring top-right block relative to the current block. */
+const static int BlkTopRight[16] = {2, 2, 2, 3, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0};
+
+/**
+Table 8-13 Specification of QPc as a function of qPI. */
+const static uint8 mapQPi2QPc[52] = {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, 29, 30, 31, 32, 32, 33, 34, 34, 35, 35, 36, 36,
+ 37, 37, 37, 38, 38, 38, 39, 39, 39, 39
+ };
+
+/**
+See 8.5.5 equation (8-252 and 8-253) the definition of v matrix. */
+/* in zigzag scan */
+const static int dequant_coefres[6][16] =
+{
+ {10, 13, 13, 10, 16, 10, 13, 13, 13, 13, 16, 10, 16, 13, 13, 16},
+ {11, 14, 14, 11, 18, 11, 14, 14, 14, 14, 18, 11, 18, 14, 14, 18},
+ {13, 16, 16, 13, 20, 13, 16, 16, 16, 16, 20, 13, 20, 16, 16, 20},
+ {14, 18, 18, 14, 23, 14, 18, 18, 18, 18, 23, 14, 23, 18, 18, 23},
+ {16, 20, 20, 16, 25, 16, 20, 20, 20, 20, 25, 16, 25, 20, 20, 25},
+ {18, 23, 23, 18, 29, 18, 23, 23, 23, 23, 29, 18, 29, 23, 23, 29}
+};
+
+/**
+From jm7.6 block.c. (in zigzag scan) */
+const static int quant_coef[6][16] =
+{
+ {13107, 8066, 8066, 13107, 5243, 13107, 8066, 8066, 8066, 8066, 5243, 13107, 5243, 8066, 8066, 5243},
+ {11916, 7490, 7490, 11916, 4660, 11916, 7490, 7490, 7490, 7490, 4660, 11916, 4660, 7490, 7490, 4660},
+ {10082, 6554, 6554, 10082, 4194, 10082, 6554, 6554, 6554, 6554, 4194, 10082, 4194, 6554, 6554, 4194},
+ {9362, 5825, 5825, 9362, 3647, 9362, 5825, 5825, 5825, 5825, 3647, 9362, 3647, 5825, 5825, 3647},
+ {8192, 5243, 5243, 8192, 3355, 8192, 5243, 5243, 5243, 5243, 3355, 8192, 3355, 5243, 5243, 3355},
+ {7282, 4559, 4559, 7282, 2893, 7282, 4559, 4559, 4559, 4559, 2893, 7282, 2893, 4559, 4559, 2893}
+};
+
+/**
+Convert scan from raster scan order to block decoding order and
+from block decoding order to raster scan order. Same table!!!
+*/
+const static uint8 ras2dec[16] = {0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15};
+
+/* mapping from level_idc to index map */
+const static uint8 mapLev2Idx[61] = {255, 255, 255, 255, 255, 255, 255, 255, 255, 1,
+ 0, 1, 2, 3, 255, 255, 255, 255, 255, 255,
+ 4, 5, 6, 255, 255, 255, 255, 255, 255, 255,
+ 7, 8, 9, 255, 255, 255, 255, 255, 255, 255,
+ 10, 11, 12, 255, 255, 255, 255, 255, 255, 255,
+ 13, 14, 255, 255, 255, 255, 255, 255, 255, 255
+ };
+/* map back from index to Level IDC */
+const static uint8 mapIdx2Lev[MAX_LEVEL_IDX] = {10, 11, 12, 13, 20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51};
+
+/**
+from the index map to the MaxDPB value times 2 */
+const static int32 MaxDPBX2[MAX_LEVEL_IDX] = {297, 675, 1782, 1782, 1782, 3564, 6075, 6075,
+ 13500, 15360, 24576, 24576, 24576, 82620, 138240
+ };
+
+/* map index to the max frame size */
+const static int MaxFS[MAX_LEVEL_IDX] = {99, 396, 396, 396, 396, 792, 1620, 1620, 3600, 5120,
+ 8192, 8192, 8192, 22080, 36864
+ };
+
+/* map index to max MB processing rate */
+const static int32 MaxMBPS[MAX_LEVEL_IDX] = {1485, 3000, 6000, 11880, 11880, 19800, 20250, 40500,
+ 108000, 216000, 245760, 245760, 491520, 589824, 983040
+ };
+
+/* map index to max video bit rate */
+const static uint32 MaxBR[MAX_LEVEL_IDX] = {64, 192, 384, 768, 2000, 4000, 4000, 10000, 14000, 20000,
+ 20000, 50000, 50000, 135000, 240000
+ };
+
+/* map index to max CPB size */
+const static uint32 MaxCPB[MAX_LEVEL_IDX] = {175, 500, 1000, 2000, 2000, 4000, 4000, 10000, 14000,
+ 20000, 25000, 62500, 62500, 135000, 240000
+ };
+
+/* map index to max vertical MV range */
+const static int MaxVmvR[MAX_LEVEL_IDX] = {64, 128, 128, 128, 128, 256, 256, 256, 512, 512, 512, 512, 512, 512, 512};
+
+#endif /* _AVCINT_COMMON_H_ */
diff --git a/media/libstagefright/codecs/avc/common/include/avclib_common.h b/media/libstagefright/codecs/avc/common/include/avclib_common.h
new file mode 100644
index 0000000..cbbf0c6
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/include/avclib_common.h
@@ -0,0 +1,557 @@
+/* ------------------------------------------------------------------
+ * 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 common encoder/decoder library.
+@publishedAll
+*/
+#ifndef AVCCOMMON_LIB_H_INCLUDED
+#define AVCCOMMON_LIB_H_INCLUDED
+
+#include <stdlib.h>
+
+#ifndef AVCINT_COMMON_H_INCLUDED
+#include "avcint_common.h"
+#endif
+
+/*----------- deblock.c --------------*/
+/**
+This function performs conditional deblocking on a complete picture.
+\param "video" "Pointer to AVCCommonObj."
+\return "AVC_SUCCESS for success and AVC_FAIL otherwise."
+*/
+OSCL_IMPORT_REF AVCStatus DeblockPicture(AVCCommonObj *video);
+
+/**
+This function performs MB-based deblocking when MB_BASED_DEBLOCK
+is defined at compile time.
+\param "video" "Pointer to AVCCommonObj."
+\return "AVC_SUCCESS for success and AVC_FAIL otherwise."
+*/
+void MBInLoopDeblock(AVCCommonObj *video);
+
+
+/*---------- dpb.c --------------------*/
+/**
+This function is called everytime a new sequence is detected.
+\param "avcHandle" "Pointer to AVCHandle."
+\param "video" "Pointer to AVCCommonObj."
+\param "padding" "Flag specifying whether padding in luma component is needed (used for encoding)."
+\return "AVC_SUCCESS or AVC_FAIL."
+*/
+OSCL_IMPORT_REF AVCStatus AVCConfigureSequence(AVCHandle *avcHandle, AVCCommonObj *video, bool padding);
+
+/**
+This function allocates and initializes the decoded picture buffer structure based on
+the profile and level for the first sequence parameter set. Currently,
+it does not allow changing in profile/level for subsequent SPS.
+\param "avcHandle" "Pointer to AVCHandle."
+\param "video" "Pointer to AVCCommonObj."
+\param "FrameHeightInMbs" "Height of the frame in the unit of MBs."
+\param "PicWidthInMbs" "Width of the picture in the unit of MBs."
+\param "padding" "Flag specifying whether padding in luma component is needed (used for encoding)."
+\return "AVC_SUCCESS or AVC_FAIL."
+*/
+AVCStatus InitDPB(AVCHandle *avcHandle, AVCCommonObj *video, int FrameHeightInMbs, int PicWidthInMbs, bool padding);
+
+/**
+This function frees the DPB memory.
+\param "avcHandle" "Pointer to AVCHandle."
+\param "video" "Pointer to AVCCommonObj."
+\return "AVC_SUCCESS or AVC_FAIL."
+*/
+OSCL_IMPORT_REF AVCStatus CleanUpDPB(AVCHandle *avcHandle, AVCCommonObj *video);
+
+/**
+This function finds empty frame in the decoded picture buffer to be used for the
+current picture, initializes the corresponding picture structure with Sl, Scb, Scr,
+width, height and pitch.
+\param "avcHandle" "Pointer to the main handle object."
+\param "video" "Pointer to AVCCommonObj."
+\return "AVC_SUCCESS or AVC_FAIL."
+*/
+OSCL_IMPORT_REF AVCStatus DPBInitBuffer(AVCHandle *avcHandle, AVCCommonObj *video);
+/**
+This function finds empty frame in the decoded picture buffer to be used for the
+current picture, initializes the corresponding picture structure with Sl, Scb, Scr,
+width, height and pitch.
+\param "video" "Pointer to AVCCommonObj."
+\param "CurrPicNum" "Current picture number (only used in decoder)."
+\return "AVC_SUCCESS or AVC_FAIL."
+*/
+
+OSCL_IMPORT_REF void DPBInitPic(AVCCommonObj *video, int CurrPicNum);
+
+/**
+This function releases the current frame back to the available pool for skipped frame after encoding.
+\param "avcHandle" "Pointer to the main handle object."
+\param "video" "Pointer to the AVCCommonObj."
+\return "void."
+*/
+OSCL_IMPORT_REF void DPBReleaseCurrentFrame(AVCHandle *avcHandle, AVCCommonObj *video);
+
+/**
+This function performs decoded reference picture marking process and store the current picture to the
+corresponding frame storage in the decoded picture buffer.
+\param "avcHandle" "Pointer to the main handle object."
+\param "video" "Pointer to the AVCCommonObj."
+\return "AVC_SUCCESS or AVC_FAIL."
+*/
+OSCL_IMPORT_REF AVCStatus StorePictureInDPB(AVCHandle *avcHandle, AVCCommonObj *video);
+
+/**
+This function perform sliding window operation on the reference picture lists, see subclause 8.2.5.3.
+It removes short-term ref frames with smallest FrameNumWrap from the reference list.
+\param "avcHandle" "Pointer to the main handle object."
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\return "AVC_SUCCESS or AVC_FAIL (contradicting values or scenario as in the Note in the draft)."
+*/
+AVCStatus sliding_window_process(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb);
+
+
+/**
+This function perform adaptive memory marking operation on the reference picture lists,
+see subclause 8.2.5.4. It calls other functions for specific operations.
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "sliceHdr" "Pointer to the AVCSliceHeader."
+\return "AVC_SUCCESS or AVC_FAIL (contradicting values or scenario as in the Note in the draft)."
+*/
+AVCStatus adaptive_memory_marking(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, AVCSliceHeader *sliceHdr);
+
+/**
+This function performs memory management control operation 1, marking a short-term picture
+as unused for reference. See subclause 8.2.5.4.1.
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "difference_of_pic_nums_minus1" "From the syntax in dec_ref_pic_marking()."
+*/
+void MemMgrCtrlOp1(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, int difference_of_pic_nums_minus1);
+
+/**
+This function performs memory management control operation 2, marking a long-term picture
+as unused for reference. See subclause 8.2.5.4.2.
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "field_pic_flag" "Flag whether the current picture is field or not."
+\param "long_term_pic_num" "From the syntax in dec_ref_pic_marking()."
+*/
+void MemMgrCtrlOp2(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, int long_term_pic_num);
+
+/**
+This function performs memory management control operation 3, assigning a LongTermFrameIdx to
+a short-term reference picture. See subclause 8.2.5.4.3.
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "difference_of_pic_nums_minus1" "From the syntax in dec_ref_pic_marking()."
+\param "long_term_pic_num" "From the syntax in dec_ref_pic_marking()."
+*/
+void MemMgrCtrlOp3(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint difference_of_pic_nums_minus1,
+ uint long_term_frame_idx);
+
+/**
+This function performs memory management control operation 4, getting new MaxLongTermFrameIdx.
+ See subclause 8.2.5.4.4.
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "max_long_term_frame_idx_plus1" "From the syntax in dec_ref_pic_marking()."
+*/
+void MemMgrCtrlOp4(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint max_long_term_frame_idx_plus1);
+
+/**
+This function performs memory management control operation 5, marking all reference pictures
+as unused for reference and set MaxLongTermFrameIdx to no long-termframe indices.
+ See subclause 8.2.5.4.5.
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+*/
+void MemMgrCtrlOp5(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb);
+
+/**
+This function performs memory management control operation 6, assigning a long-term frame index
+to the current picture. See subclause 8.2.5.4.6.
+\param "video" "Pointer to the AVCCommonObj."
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "long_term_frame_idx" "From the syntax in dec_ref_pic_marking()."
+*/
+void MemMgrCtrlOp6(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint long_term_frame_idx);
+
+/**
+This function mark a long-term ref frame with a specific frame index as unused for reference.
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "long_term_frame_idx" "To look for"
+*/
+void unmark_long_term_frame_for_reference_by_frame_idx(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, uint long_term_frame_idx);
+
+/**
+This function mark a long-term ref field with a specific frame index as unused for reference except
+a frame that contains a picture with picNumX.
+\param "dpb" "Pointer to the AVCDecPicBuffer."
+\param "long_term_frame_idx" "To look for."
+\param "picNumX" "To look for."
+*/
+void unmark_long_term_field_for_reference_by_frame_idx(AVCCommonObj *video, AVCDecPicBuffer *dpb, uint long_term_frame_indx, int picNumX);
+
+/**
+This function mark a frame to unused for reference.
+\param "fs" "Pointer to AVCFrameStore to be unmarked."
+*/
+void unmark_for_reference(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, uint idx);
+
+void update_ref_list(AVCDecPicBuffer *dpb);
+
+
+/*---------- fmo.c --------------*/
+/**
+This function initializes flexible macroblock reordering.
+\param "video" "Pointer to AVCCommonObj."
+\return "AVC_SUCCESS for success and AVC_FAIL otherwise."
+*/
+OSCL_IMPORT_REF AVCStatus FMOInit(AVCCommonObj *video);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following the interleaved slice group map type.
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "run_length_minus1" "Array of the run-length."
+\param "num_slice_groups_minus_1" "Number of slice group minus 1."
+\param "PicSizeInMapUnit" "Size of the picture in number Map units."
+\return "Void."
+*/
+void FmoGenerateType0MapUnitMap(int *mapUnitToSliceGroupMap, uint *run_length_minus1, uint num_slice_groups_minus1, uint PicSizeInMapUnits);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following the dispersed slice group map type.
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "PicWidthInMbs" "Width of the luma picture in macroblock unit."
+\param "num_slice_groups_minus_1" "Number of slice group minus 1."
+\param "PicSizeInMapUnit" "Size of the picture in number Map units."
+\return "Void."
+*/
+void FmoGenerateType1MapUnitMap(int *mapUnitToSliceGroupMap, int PicWidthInMbs, uint num_slice_groups_minus1, uint PicSizeInMapUnits);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following the foreground with left-over slice group map type.
+\param "pps" "Pointer to AVCPicParamSets structure."
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "PicWidthInMbs" "Width of the luma picture in macroblock unit."
+\param "num_slice_groups_minus_1" "Number of slice group minus 1."
+\param "PicSizeInMapUnit" "Size of the picture in number Map units."
+\return "Void."
+*/
+void FmoGenerateType2MapUnitMap(AVCPicParamSet *pps, int *mapUnitToSliceGroupMap, int PicWidthInMbs,
+ uint num_slice_groups_minus1, uint PicSizeInMapUnits);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following the box-out slice group map type.
+\param "pps" "Pointer to AVCPicParamSets structure."
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "PicWidthInMbs" "Width of the luma picture in macroblock unit."
+\return "Void."
+*/
+void FmoGenerateType3MapUnitMap(AVCCommonObj *video, AVCPicParamSet* pps, int *mapUnitToSliceGroupMap,
+ int PicWidthInMbs);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following the raster scan slice group map type.
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "MapUnitsInSliceGroup0" "Derived in subclause 7.4.3."
+\param "slice_group_change_direction_flag" "A value from the slice header."
+\param "PicSizeInMapUnit" "Size of the picture in number Map units."
+\return "void"
+*/
+void FmoGenerateType4MapUnitMap(int *mapUnitToSliceGroupMap, int MapUnitsInSliceGroup0,
+ int slice_group_change_direction_flag, uint PicSizeInMapUnits);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following wipe slice group map type.
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "video" "Pointer to AVCCommonObj structure."
+\param "slice_group_change_direction_flag" "A value from the slice header."
+\param "PicSizeInMapUnit" "Size of the picture in number Map units."
+\return "void"
+*/
+void FmoGenerateType5MapUnitMap(int *mapUnitsToSliceGroupMap, AVCCommonObj *video,
+ int slice_group_change_direction_flag, uint PicSizeInMapUnits);
+
+/**
+This function fills up an array that maps Map unit to the slice group
+following wipe slice group map type.
+\param "mapUnitToSliceGroupMap" "Array of slice group mapping."
+\param "slice_group_id" "Array of slice_group_id from AVCPicParamSet structure."
+\param "PicSizeInMapUnit" "Size of the picture in number Map units."
+\return "void"
+*/
+void FmoGenerateType6MapUnitMap(int *mapUnitsToSliceGroupMap, int *slice_group_id, uint PicSizeInMapUnits);
+
+/*------------- itrans.c --------------*/
+/**
+This function performs transformation of the Intra16x16DC value according to
+subclause 8.5.6.
+\param "block" "Pointer to the video->block[0][0][0]."
+\param "QPy" "Quantization parameter."
+\return "void."
+*/
+void Intra16DCTrans(int16 *block, int Qq, int Rq);
+
+/**
+This function performs transformation of a 4x4 block according to
+subclause 8.5.8.
+\param "block" "Pointer to the origin of transform coefficient area."
+\param "pred" "Pointer to the origin of predicted area."
+\param "cur" "Pointer to the origin of the output area."
+\param "width" "Pitch of cur."
+\return "void."
+*/
+void itrans(int16 *block, uint8 *pred, uint8 *cur, int width);
+
+/*
+This function is the same one as itrans except for chroma.
+\param "block" "Pointer to the origin of transform coefficient area."
+\param "pred" "Pointer to the origin of predicted area."
+\param "cur" "Pointer to the origin of the output area."
+\param "width" "Pitch of cur."
+\return "void."
+*/
+void ictrans(int16 *block, uint8 *pred, uint8 *cur, int width);
+
+/**
+This function performs transformation of the DCChroma value according to
+subclause 8.5.7.
+\param "block" "Pointer to the video->block[0][0][0]."
+\param "QPc" "Quantization parameter."
+\return "void."
+*/
+void ChromaDCTrans(int16 *block, int Qq, int Rq);
+
+/**
+This function copies a block from pred to cur.
+\param "pred" "Pointer to prediction block."
+\param "cur" "Pointer to the current YUV block."
+\param "width" "Pitch of cur memory."
+\param "pred_pitch" "Pitch for pred memory.
+\return "void."
+*/
+void copy_block(uint8 *pred, uint8 *cur, int width, int pred_pitch);
+
+/*--------- mb_access.c ----------------*/
+/**
+This function initializes the neighboring information before start macroblock decoding.
+\param "video" "Pointer to AVCCommonObj."
+\param "mbNum" "The current macroblock index."
+\param "currMB" "Pointer to the current AVCMacroblock structure."
+\return "void"
+*/
+OSCL_IMPORT_REF void InitNeighborAvailability(AVCCommonObj *video, int mbNum);
+
+/**
+This function checks whether the requested neighboring macroblock is available.
+\param "MbToSliceGroupMap" "Array containing the slice group ID mapping to MB index."
+\param "PicSizeInMbs" "Size of the picture in number of MBs."
+\param "mbAddr" "Neighboring macroblock index to check."
+\param "currMbAddr" "Current macroblock index."
+\return "TRUE if the neighboring MB is available, FALSE otherwise."
+*/
+bool mb_is_available(AVCMacroblock *mblock, uint PicSizeInMbs, int mbAddr, int currMbAddr);
+
+/**
+This function performs prediction of the nonzero coefficient for a luma block (i,j).
+\param "video" "Pointer to AVCCommonObj."
+\param "i" "Block index, horizontal."
+\param "j" "Block index, vertical."
+\return "Predicted number of nonzero coefficient."
+*/
+OSCL_IMPORT_REF int predict_nnz(AVCCommonObj *video, int i, int j);
+
+/**
+This function performs prediction of the nonzero coefficient for a chroma block (i,j).
+\param "video" "Pointer to AVCCommonObj."
+\param "i" "Block index, horizontal."
+\param "j" "Block index, vertical."
+\return "Predicted number of nonzero coefficient."
+*/
+OSCL_IMPORT_REF int predict_nnz_chroma(AVCCommonObj *video, int i, int j);
+
+/**
+This function calculates the predicted motion vectors for the current macroblock.
+\param "video" "Pointer to AVCCommonObj."
+\param "encFlag" "Boolean whether this function is used by encoder or decoder."
+\return "void."
+*/
+OSCL_IMPORT_REF void GetMotionVectorPredictor(AVCCommonObj *video, int encFlag);
+
+/*---------- reflist.c -----------------*/
+/**
+This function initializes reference picture list used in INTER prediction
+at the beginning of each slice decoding. See subclause 8.2.4.
+\param "video" "Pointer to AVCCommonObj."
+\return "void"
+Output is video->RefPicList0, video->RefPicList1, video->refList0Size and video->refList1Size.
+*/
+OSCL_IMPORT_REF void RefListInit(AVCCommonObj *video);
+
+/**
+This function generates picture list from frame list. Used when current picture is field.
+see subclause 8.2.4.2.5.
+\param "video" "Pointer to AVCCommonObj."
+\param "IsL1" "Is L1 list?"
+\param "long_term" "Is long-term prediction?"
+\return "void"
+*/
+void GenPicListFromFrameList(AVCCommonObj *video, int IsL1, int long_term);
+
+/**
+This function performs reference picture list reordering according to the
+ref_pic_list_reordering() syntax. See subclause 8.2.4.3.
+\param "video" "Pointer to AVCCommonObj."
+\return "AVC_SUCCESS or AVC_FAIL"
+Output is video->RefPicList0, video->RefPicList1, video->refList0Size and video->refList1Size.
+*/
+OSCL_IMPORT_REF AVCStatus ReOrderList(AVCCommonObj *video);
+
+/**
+This function performs reference picture list reordering according to the
+ref_pic_list_reordering() syntax regardless of list 0 or list 1. See subclause 8.2.4.3.
+\param "video" "Pointer to AVCCommonObj."
+\param "isL1" "Is list 1 or not."
+\return "AVC_SUCCESS or AVC_FAIL"
+Output is video->RefPicList0 and video->refList0Size or video->RefPicList1 and video->refList1Size.
+*/
+AVCStatus ReorderRefPicList(AVCCommonObj *video, int isL1);
+
+/**
+This function performs reordering process of reference picture list for short-term pictures.
+See subclause 8.2.4.3.1.
+\param "video" "Pointer to AVCCommonObj."
+\param "picNumLX" "picNumLX of an entry in the reference list."
+\param "refIdxLX" "Pointer to the current entry index in the reference."
+\param "isL1" "Is list 1 or not."
+\return "AVC_SUCCESS or AVC_FAIL"
+*/
+AVCStatus ReorderShortTerm(AVCCommonObj *video, int picNumLX, int *refIdxLX, int isL1);
+
+/**
+This function performs reordering process of reference picture list for long-term pictures.
+See subclause 8.2.4.3.2.
+\param "video" "Pointer to AVCCommonObj."
+\param "LongTermPicNum" "LongTermPicNum of an entry in the reference list."
+\param "refIdxLX" "Pointer to the current entry index in the reference."
+\param "isL1" "Is list 1 or not."
+\return "AVC_SUCCESS or AVC_FAIL"
+*/
+AVCStatus ReorderLongTerm(AVCCommonObj *video, int LongTermPicNum, int *refIdxLX, int isL1);
+
+/**
+This function gets the pictures in DPB according to the PicNum.
+\param "video" "Pointer to AVCCommonObj."
+\param "picNum" "PicNum of the picture we are looking for."
+\return "Pointer to the AVCPictureData or NULL if not found"
+*/
+AVCPictureData* GetShortTermPic(AVCCommonObj *video, int picNum);
+
+/**
+This function gets the pictures in DPB according to the LongtermPicNum.
+\param "video" "Pointer to AVCCommonObj."
+\param "LongtermPicNum" "LongtermPicNum of the picture we are looking for."
+\return "Pointer to the AVCPictureData."
+*/
+AVCPictureData* GetLongTermPic(AVCCommonObj *video, int LongtermPicNum);
+
+/**
+This function indicates whether the picture is used for short-term reference or not.
+\param "s" "Pointer to AVCPictureData."
+\return "1 if it is used for short-term, 0 otherwise."
+*/
+int is_short_ref(AVCPictureData *s);
+
+/**
+This function indicates whether the picture is used for long-term reference or not.
+\param "s" "Pointer to AVCPictureData."
+\return "1 if it is used for long-term, 0 otherwise."
+*/
+int is_long_ref(AVCPictureData *s);
+
+/**
+This function sorts array of pointers to AVCPictureData in descending order of
+the PicNum value.
+\param "data" "Array of pointers to AVCPictureData."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortPicByPicNum(AVCPictureData *data[], int num);
+
+/**
+This function sorts array of pointers to AVCPictureData in ascending order of
+the PicNum value.
+\param "data" "Array of pointers to AVCPictureData."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortPicByPicNumLongTerm(AVCPictureData *data[], int num);
+
+/**
+This function sorts array of pointers to AVCFrameStore in descending order of
+the FrameNumWrap value.
+\param "data" "Array of pointers to AVCFrameStore."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortFrameByFrameNumWrap(AVCFrameStore *data[], int num);
+
+/**
+This function sorts array of pointers to AVCFrameStore in ascending order of
+the LongTermFrameIdx value.
+\param "data" "Array of pointers to AVCFrameStore."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortFrameByLTFrameIdx(AVCFrameStore *data[], int num);
+
+/**
+This function sorts array of pointers to AVCPictureData in descending order of
+the PicOrderCnt value.
+\param "data" "Array of pointers to AVCPictureData."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortPicByPOC(AVCPictureData *data[], int num, int descending);
+
+/**
+This function sorts array of pointers to AVCPictureData in ascending order of
+the LongTermPicNum value.
+\param "data" "Array of pointers to AVCPictureData."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortPicByLTPicNum(AVCPictureData *data[], int num);
+
+/**
+This function sorts array of pointers to AVCFrameStore in descending order of
+the PicOrderCnt value.
+\param "data" "Array of pointers to AVCFrameStore."
+\param "num" "Size of the array."
+\return "void"
+*/
+void SortFrameByPOC(AVCFrameStore *data[], int num, int descending);
+
+
+#endif /* _AVCCOMMON_LIB_H_ */
diff --git a/media/libstagefright/codecs/avc/common/src/deblock.cpp b/media/libstagefright/codecs/avc/common/src/deblock.cpp
new file mode 100644
index 0000000..5ed4c82
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/src/deblock.cpp
@@ -0,0 +1,1666 @@
+/* ------------------------------------------------------------------
+ * 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 <string.h>
+
+#include "avclib_common.h"
+
+#define MAX_QP 51
+#define MB_BLOCK_SIZE 16
+
+// NOTE: these 3 tables are for funtion GetStrength() only
+const static int ININT_STRENGTH[4] = {0x04040404, 0x03030303, 0x03030303, 0x03030303};
+
+
+// NOTE: these 3 tables are for funtion EdgeLoop() only
+// NOTE: to change the tables below for instance when the QP doubling is changed from 6 to 8 values
+
+const static int ALPHA_TABLE[52] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 5, 6, 7, 8, 9, 10, 12, 13, 15, 17, 20, 22, 25, 28, 32, 36, 40, 45, 50, 56, 63, 71, 80, 90, 101, 113, 127, 144, 162, 182, 203, 226, 255, 255} ;
+const static int BETA_TABLE[52] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18} ;
+const static int CLIP_TAB[52][5] =
+{
+ { 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, 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, 1, 1}, { 0, 0, 0, 1, 1}, { 0, 0, 0, 1, 1}, { 0, 0, 0, 1, 1}, { 0, 0, 1, 1, 1}, { 0, 0, 1, 1, 1}, { 0, 1, 1, 1, 1},
+ { 0, 1, 1, 1, 1}, { 0, 1, 1, 1, 1}, { 0, 1, 1, 1, 1}, { 0, 1, 1, 2, 2}, { 0, 1, 1, 2, 2}, { 0, 1, 1, 2, 2}, { 0, 1, 1, 2, 2}, { 0, 1, 2, 3, 3},
+ { 0, 1, 2, 3, 3}, { 0, 2, 2, 3, 3}, { 0, 2, 2, 4, 4}, { 0, 2, 3, 4, 4}, { 0, 2, 3, 4, 4}, { 0, 3, 3, 5, 5}, { 0, 3, 4, 6, 6}, { 0, 3, 4, 6, 6},
+ { 0, 4, 5, 7, 7}, { 0, 4, 5, 8, 8}, { 0, 4, 6, 9, 9}, { 0, 5, 7, 10, 10}, { 0, 6, 8, 11, 11}, { 0, 6, 8, 13, 13}, { 0, 7, 10, 14, 14}, { 0, 8, 11, 16, 16},
+ { 0, 9, 12, 18, 18}, { 0, 10, 13, 20, 20}, { 0, 11, 15, 23, 23}, { 0, 13, 17, 25, 25}
+};
+
+// NOTE: this table is only QP clipping, index = QP + video->FilterOffsetA/B, clipped to [0, 51]
+// video->FilterOffsetA/B is in {-12, 12]
+const static int QP_CLIP_TAB[76] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // [-12, 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, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // [1, 51]
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51 // [52,63]
+};
+
+static void DeblockMb(AVCCommonObj *video, int mb_x, int mb_y, uint8 *SrcY, uint8 *SrcU, uint8 *SrcV);
+//static void GetStrength(AVCCommonObj *video, uint8 *Strength, AVCMacroblock* MbP, AVCMacroblock* MbQ, int dir, int edge);
+static void GetStrength_Edge0(uint8 *Strength, AVCMacroblock* MbP, AVCMacroblock* MbQ, int dir);
+static void GetStrength_VerticalEdges(uint8 *Strength, AVCMacroblock* MbQ);
+static void GetStrength_HorizontalEdges(uint8 Strength[12], AVCMacroblock* MbQ);
+static void EdgeLoop_Luma_vertical(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch);
+static void EdgeLoop_Luma_horizontal(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch);
+static void EdgeLoop_Chroma_vertical(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch);
+static void EdgeLoop_Chroma_horizontal(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch);
+
+/*
+ *****************************************************************************************
+ * \brief Filter all macroblocks in order of increasing macroblock address.
+ *****************************************************************************************
+*/
+
+OSCL_EXPORT_REF AVCStatus DeblockPicture(AVCCommonObj *video)
+{
+ uint i, j;
+ int pitch = video->currPic->pitch, pitch_c, width;
+ uint8 *SrcY, *SrcU, *SrcV;
+
+ SrcY = video->currPic->Sl; // pointers to source
+ SrcU = video->currPic->Scb;
+ SrcV = video->currPic->Scr;
+ pitch_c = pitch >> 1;
+ width = video->currPic->width;
+
+ for (i = 0; i < video->PicHeightInMbs; i++)
+ {
+ for (j = 0; j < video->PicWidthInMbs; j++)
+ {
+ DeblockMb(video, j, i, SrcY, SrcU, SrcV);
+ // update SrcY, SrcU, SrcV
+ SrcY += MB_BLOCK_SIZE;
+ SrcU += (MB_BLOCK_SIZE >> 1);
+ SrcV += (MB_BLOCK_SIZE >> 1);
+ }
+
+ SrcY += ((pitch << 4) - width);
+ SrcU += ((pitch_c << 3) - (width >> 1));
+ SrcV += ((pitch_c << 3) - (width >> 1));
+ }
+
+ return AVC_SUCCESS;
+}
+
+#ifdef MB_BASED_DEBLOCK
+/*
+ *****************************************************************************************
+ * \brief Filter one macroblocks in a fast macroblock memory and copy it to frame
+ *****************************************************************************************
+*/
+void MBInLoopDeblock(AVCCommonObj *video)
+{
+ AVCPictureData *currPic = video->currPic;
+#ifdef USE_PRED_BLOCK
+ uint8 *predCb, *predCr, *pred_block;
+ int i, j, dst_width, dst_height, dst_widthc, dst_heightc;
+#endif
+ int pitch = currPic->pitch;
+ int x_pos = video->mb_x;
+ int y_pos = video->mb_y;
+ uint8 *curL, *curCb, *curCr;
+ int offset;
+
+ offset = (y_pos << 4) * pitch;
+
+ curL = currPic->Sl + offset + (x_pos << 4);
+
+ offset >>= 2;
+ offset += (x_pos << 3);
+
+ curCb = currPic->Scb + offset;
+ curCr = currPic->Scr + offset;
+
+#ifdef USE_PRED_BLOCK
+ pred_block = video->pred;
+
+ /* 1. copy neighboring pixels from frame to the video->pred_block */
+ if (y_pos) /* not the 0th row */
+ {
+ /* copy to the top 4 lines of the macroblock */
+ curL -= (pitch << 2); /* go back 4 lines */
+
+ memcpy(pred_block + 4, curL, 16);
+ curL += pitch;
+ memcpy(pred_block + 24, curL, 16);
+ curL += pitch;
+ memcpy(pred_block + 44, curL, 16);
+ curL += pitch;
+ memcpy(pred_block + 64, curL, 16);
+ curL += pitch;
+
+ curCb -= (pitch << 1); /* go back 4 lines chroma */
+ curCr -= (pitch << 1);
+
+ pred_block += 400;
+
+ memcpy(pred_block + 4, curCb, 8);
+ curCb += (pitch >> 1);
+ memcpy(pred_block + 16, curCb, 8);
+ curCb += (pitch >> 1);
+ memcpy(pred_block + 28, curCb, 8);
+ curCb += (pitch >> 1);
+ memcpy(pred_block + 40, curCb, 8);
+ curCb += (pitch >> 1);
+
+ pred_block += 144;
+ memcpy(pred_block + 4, curCr, 8);
+ curCr += (pitch >> 1);
+ memcpy(pred_block + 16, curCr, 8);
+ curCr += (pitch >> 1);
+ memcpy(pred_block + 28, curCr, 8);
+ curCr += (pitch >> 1);
+ memcpy(pred_block + 40, curCr, 8);
+ curCr += (pitch >> 1);
+
+ pred_block = video->pred;
+ }
+
+ /* 2. perform deblocking. */
+ DeblockMb(video, x_pos, y_pos, pred_block + 84, pred_block + 452, pred_block + 596);
+
+ /* 3. copy it back to the frame and update pred_block */
+ predCb = pred_block + 400;
+ predCr = predCb + 144;
+
+ /* find the range of the block inside pred_block to be copied back */
+ if (y_pos) /* the first row */
+ {
+ curL -= (pitch << 2);
+ curCb -= (pitch << 1);
+ curCr -= (pitch << 1);
+
+ dst_height = 20;
+ dst_heightc = 12;
+ }
+ else
+ {
+ pred_block += 80;
+ predCb += 48;
+ predCr += 48;
+ dst_height = 16;
+ dst_heightc = 8;
+ }
+
+ if (x_pos) /* find the width */
+ {
+ curL -= 4;
+ curCb -= 4;
+ curCr -= 4;
+ if (x_pos == (int)(video->PicWidthInMbs - 1))
+ {
+ dst_width = 20;
+ dst_widthc = 12;
+ }
+ else
+ {
+ dst_width = 16;
+ dst_widthc = 8;
+ }
+ }
+ else
+ {
+ pred_block += 4;
+ predCb += 4;
+ predCr += 4;
+ dst_width = 12;
+ dst_widthc = 4;
+ }
+
+ /* perform copy */
+ for (j = 0; j < dst_height; j++)
+ {
+ memcpy(curL, pred_block, dst_width);
+ curL += pitch;
+ pred_block += 20;
+ }
+ for (j = 0; j < dst_heightc; j++)
+ {
+ memcpy(curCb, predCb, dst_widthc);
+ memcpy(curCr, predCr, dst_widthc);
+ curCb += (pitch >> 1);
+ curCr += (pitch >> 1);
+ predCb += 12;
+ predCr += 12;
+ }
+
+ if (x_pos != (int)(video->PicWidthInMbs - 1)) /* now copy from the right-most 4 columns to the left-most 4 columns */
+ {
+ pred_block = video->pred;
+ for (i = 0; i < 20; i += 4)
+ {
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 16));
+ pred_block += 20;
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 16));
+ pred_block += 20;
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 16));
+ pred_block += 20;
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 16));
+ pred_block += 20;
+ }
+
+ for (i = 0; i < 24; i += 4)
+ {
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 8));
+ pred_block += 12;
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 8));
+ pred_block += 12;
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 8));
+ pred_block += 12;
+ *((uint32*)pred_block) = *((uint32*)(pred_block + 8));
+ pred_block += 12;
+ }
+
+ }
+#else
+ DeblockMb(video, x_pos, y_pos, curL, curCb, curCr);
+#endif
+
+ return ;
+}
+#endif
+
+/*
+ *****************************************************************************************
+ * \brief Deblocking filter for one macroblock.
+ *****************************************************************************************
+ */
+
+void DeblockMb(AVCCommonObj *video, int mb_x, int mb_y, uint8 *SrcY, uint8 *SrcU, uint8 *SrcV)
+{
+ AVCMacroblock *MbP, *MbQ;
+ int edge, QP, QPC;
+ int filterLeftMbEdgeFlag = (mb_x != 0);
+ int filterTopMbEdgeFlag = (mb_y != 0);
+ int pitch = video->currPic->pitch;
+ int indexA, indexB, tmp;
+ int Alpha, Beta, Alpha_c, Beta_c;
+ int mbNum = mb_y * video->PicWidthInMbs + mb_x;
+ int *clipTable, *clipTable_c, *qp_clip_tab;
+ uint8 Strength[16];
+ void* str;
+
+ MbQ = &(video->mblock[mbNum]); // current Mb
+
+
+ // If filter is disabled, return
+ if (video->sliceHdr->disable_deblocking_filter_idc == 1) return;
+
+ if (video->sliceHdr->disable_deblocking_filter_idc == 2)
+ {
+ // don't filter at slice boundaries
+ filterLeftMbEdgeFlag = mb_is_available(video->mblock, video->PicSizeInMbs, mbNum - 1, mbNum);
+ filterTopMbEdgeFlag = mb_is_available(video->mblock, video->PicSizeInMbs, mbNum - video->PicWidthInMbs, mbNum);
+ }
+
+ /* NOTE: edge=0 and edge=1~3 are separate cases because of the difference of MbP, index A and indexB calculation */
+ /* for edge = 1~3, MbP, indexA and indexB remain the same, and thus there is no need to re-calculate them for each edge */
+
+ qp_clip_tab = (int *)QP_CLIP_TAB + 12;
+
+ /* 1.VERTICAL EDGE + MB BOUNDARY (edge = 0) */
+ if (filterLeftMbEdgeFlag)
+ {
+ MbP = MbQ - 1;
+ //GetStrength(video, Strength, MbP, MbQ, 0, 0); // Strength for 4 blks in 1 stripe, 0 => vertical edge
+ GetStrength_Edge0(Strength, MbP, MbQ, 0);
+
+ str = (void*)Strength; //de-ref type-punned pointer fix
+ if (*((uint32*)str)) // only if one of the 4 Strength bytes is != 0
+ {
+ QP = (MbP->QPy + MbQ->QPy + 1) >> 1; // Average QP of the two blocks;
+ indexA = QP + video->FilterOffsetA;
+ indexB = QP + video->FilterOffsetB;
+ indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
+ indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
+
+ Alpha = ALPHA_TABLE[indexA];
+ Beta = BETA_TABLE[indexB];
+ clipTable = (int *) CLIP_TAB[indexA];
+
+ if (Alpha > 0 && Beta > 0)
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Luma_vertical(SrcY, Strength, Alpha, Beta, clipTable, 20);
+#else
+ EdgeLoop_Luma_vertical(SrcY, Strength, Alpha, Beta, clipTable, pitch);
+#endif
+
+ QPC = (MbP->QPc + MbQ->QPc + 1) >> 1;
+ indexA = QPC + video->FilterOffsetA;
+ indexB = QPC + video->FilterOffsetB;
+ indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
+ indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
+
+ Alpha = ALPHA_TABLE[indexA];
+ Beta = BETA_TABLE[indexB];
+ clipTable = (int *) CLIP_TAB[indexA];
+ if (Alpha > 0 && Beta > 0)
+ {
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Chroma_vertical(SrcU, Strength, Alpha, Beta, clipTable, 12);
+ EdgeLoop_Chroma_vertical(SrcV, Strength, Alpha, Beta, clipTable, 12);
+#else
+ EdgeLoop_Chroma_vertical(SrcU, Strength, Alpha, Beta, clipTable, pitch >> 1);
+ EdgeLoop_Chroma_vertical(SrcV, Strength, Alpha, Beta, clipTable, pitch >> 1);
+#endif
+ }
+ }
+
+ } /* end of: if(filterLeftMbEdgeFlag) */
+
+ /* 2.VERTICAL EDGE (no boundary), the edges are all inside a MB */
+ /* First calculate the necesary parameters all at once, outside the loop */
+ MbP = MbQ;
+
+ indexA = MbQ->QPy + video->FilterOffsetA;
+ indexB = MbQ->QPy + video->FilterOffsetB;
+ // index
+ indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
+ indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
+
+ Alpha = ALPHA_TABLE[indexA];
+ Beta = BETA_TABLE[indexB];
+ clipTable = (int *)CLIP_TAB[indexA];
+
+ /* Save Alpha, Beta and clipTable for future use, with the obselete variables filterLeftMbEdgeFlag, mbNum amd tmp */
+ filterLeftMbEdgeFlag = Alpha;
+ mbNum = Beta;
+ tmp = (int)clipTable;
+
+ indexA = MbQ->QPc + video->FilterOffsetA;
+ indexB = MbQ->QPc + video->FilterOffsetB;
+ indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
+ indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
+
+ Alpha_c = ALPHA_TABLE[indexA];
+ Beta_c = BETA_TABLE[indexB];
+ clipTable_c = (int *)CLIP_TAB[indexA];
+
+ GetStrength_VerticalEdges(Strength + 4, MbQ); // Strength for 4 blks in 1 stripe, 0 => vertical edge
+
+ for (edge = 1; edge < 4; edge++) // 4 vertical strips of 16 pel
+ {
+ //GetStrength_VerticalEdges(video, Strength, MbP, MbQ, 0, edge); // Strength for 4 blks in 1 stripe, 0 => vertical edge
+ if (*((int*)(Strength + (edge << 2)))) // only if one of the 4 Strength bytes is != 0
+ {
+ if (Alpha > 0 && Beta > 0)
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Luma_vertical(SrcY + (edge << 2), Strength + (edge << 2), Alpha, Beta, clipTable, 20);
+#else
+ EdgeLoop_Luma_vertical(SrcY + (edge << 2), Strength + (edge << 2), Alpha, Beta, clipTable, pitch);
+#endif
+
+ if (!(edge & 1) && Alpha_c > 0 && Beta_c > 0)
+ {
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Chroma_vertical(SrcU + (edge << 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, 12);
+ EdgeLoop_Chroma_vertical(SrcV + (edge << 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, 12);
+#else
+ EdgeLoop_Chroma_vertical(SrcU + (edge << 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, pitch >> 1);
+ EdgeLoop_Chroma_vertical(SrcV + (edge << 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, pitch >> 1);
+#endif
+ }
+ }
+
+ } //end edge
+
+
+
+ /* 3.HORIZONTAL EDGE + MB BOUNDARY (edge = 0) */
+ if (filterTopMbEdgeFlag)
+ {
+ MbP = MbQ - video->PicWidthInMbs;
+ //GetStrength(video, Strength, MbP, MbQ, 1, 0); // Strength for 4 blks in 1 stripe, 0 => vertical edge
+ GetStrength_Edge0(Strength, MbP, MbQ, 1);
+ str = (void*)Strength; //de-ref type-punned pointer fix
+ if (*((uint32*)str)) // only if one of the 4 Strength bytes is != 0
+ {
+ QP = (MbP->QPy + MbQ->QPy + 1) >> 1; // Average QP of the two blocks;
+ indexA = QP + video->FilterOffsetA;
+ indexB = QP + video->FilterOffsetB;
+ indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
+ indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
+
+ Alpha = ALPHA_TABLE[indexA];
+ Beta = BETA_TABLE[indexB];
+ clipTable = (int *)CLIP_TAB[indexA];
+
+ if (Alpha > 0 && Beta > 0)
+ {
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Luma_horizontal(SrcY, Strength, Alpha, Beta, clipTable, 20);
+#else
+ EdgeLoop_Luma_horizontal(SrcY, Strength, Alpha, Beta, clipTable, pitch);
+#endif
+ }
+
+ QPC = (MbP->QPc + MbQ->QPc + 1) >> 1;
+ indexA = QPC + video->FilterOffsetA;
+ indexB = QPC + video->FilterOffsetB;
+ indexA = qp_clip_tab[indexA]; // IClip(0, MAX_QP, QP+video->FilterOffsetA)
+ indexB = qp_clip_tab[indexB]; // IClip(0, MAX_QP, QP+video->FilterOffsetB)
+
+ Alpha = ALPHA_TABLE[indexA];
+ Beta = BETA_TABLE[indexB];
+ clipTable = (int *)CLIP_TAB[indexA];
+ if (Alpha > 0 && Beta > 0)
+ {
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Chroma_horizontal(SrcU, Strength, Alpha, Beta, clipTable, 12);
+ EdgeLoop_Chroma_horizontal(SrcV, Strength, Alpha, Beta, clipTable, 12);
+#else
+ EdgeLoop_Chroma_horizontal(SrcU, Strength, Alpha, Beta, clipTable, pitch >> 1);
+ EdgeLoop_Chroma_horizontal(SrcV, Strength, Alpha, Beta, clipTable, pitch >> 1);
+#endif
+ }
+ }
+
+ } /* end of: if(filterTopMbEdgeFlag) */
+
+
+ /* 4.HORIZONTAL EDGE (no boundary), the edges are inside a MB */
+ MbP = MbQ;
+
+ /* Recover Alpha, Beta and clipTable for edge!=0 with the variables filterLeftMbEdgeFlag, mbNum and tmp */
+ /* Note that Alpha_c, Beta_c and clipTable_c for chroma is already calculated */
+ Alpha = filterLeftMbEdgeFlag;
+ Beta = mbNum;
+ clipTable = (int *)tmp;
+
+ GetStrength_HorizontalEdges(Strength + 4, MbQ); // Strength for 4 blks in 1 stripe, 0 => vertical edge
+
+ for (edge = 1; edge < 4; edge++) // 4 horicontal strips of 16 pel
+ {
+ //GetStrength(video, Strength, MbP, MbQ, 1, edge); // Strength for 4 blks in 1 stripe 1 => horizontal edge
+ if (*((int*)(Strength + (edge << 2)))) // only if one of the 4 Strength bytes is != 0
+ {
+ if (Alpha > 0 && Beta > 0)
+ {
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Luma_horizontal(SrcY + (edge << 2)*20, Strength + (edge << 2), Alpha, Beta, clipTable, 20);
+#else
+ EdgeLoop_Luma_horizontal(SrcY + (edge << 2)*pitch, Strength + (edge << 2), Alpha, Beta, clipTable, pitch);
+#endif
+ }
+
+ if (!(edge & 1) && Alpha_c > 0 && Beta_c > 0)
+ {
+#ifdef USE_PRED_BLOCK
+ EdgeLoop_Chroma_horizontal(SrcU + (edge << 1)*12, Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, 12);
+ EdgeLoop_Chroma_horizontal(SrcV + (edge << 1)*12, Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, 12);
+#else
+ EdgeLoop_Chroma_horizontal(SrcU + (edge << 1)*(pitch >> 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, pitch >> 1);
+ EdgeLoop_Chroma_horizontal(SrcV + (edge << 1)*(pitch >> 1), Strength + (edge << 2), Alpha_c, Beta_c, clipTable_c, pitch >> 1);
+#endif
+ }
+ }
+
+ } //end edge
+
+ return;
+}
+
+/*
+ *****************************************************************************************************
+ * \brief returns a buffer of 4 Strength values for one stripe in a mb (for different Frame types)
+ *****************************************************************************************************
+*/
+
+void GetStrength_Edge0(uint8 *Strength, AVCMacroblock* MbP, AVCMacroblock* MbQ, int dir)
+{
+ int tmp;
+ int16 *ptrQ, *ptrP;
+ void* vptr;
+ uint8 *pStrength;
+ void* refIdx;
+
+ if (MbP->mbMode == AVC_I4 || MbP->mbMode == AVC_I16 ||
+ MbQ->mbMode == AVC_I4 || MbQ->mbMode == AVC_I16)
+ {
+
+ *((int*)Strength) = ININT_STRENGTH[0]; // Start with Strength=3. or Strength=4 for Mb-edge
+
+ }
+ else // if not intra or SP-frame
+ {
+ *((int*)Strength) = 0;
+
+ if (dir == 0) // Vertical Edge 0
+ {
+
+ //1. Check the ref_frame_id
+ refIdx = (void*) MbQ->RefIdx; //de-ref type-punned pointer fix
+ ptrQ = (int16*)refIdx;
+ refIdx = (void*)MbP->RefIdx; //de-ref type-punned pointer fix
+ ptrP = (int16*)refIdx;
+ pStrength = Strength;
+ if (ptrQ[0] != ptrP[1]) pStrength[0] = 1;
+ if (ptrQ[2] != ptrP[3]) pStrength[2] = 1;
+ pStrength[1] = pStrength[0];
+ pStrength[3] = pStrength[2];
+
+ //2. Check the non-zero coeff blocks (4x4)
+ if (MbQ->nz_coeff[0] != 0 || MbP->nz_coeff[3] != 0) pStrength[0] = 2;
+ if (MbQ->nz_coeff[4] != 0 || MbP->nz_coeff[7] != 0) pStrength[1] = 2;
+ if (MbQ->nz_coeff[8] != 0 || MbP->nz_coeff[11] != 0) pStrength[2] = 2;
+ if (MbQ->nz_coeff[12] != 0 || MbP->nz_coeff[15] != 0) pStrength[3] = 2;
+
+ //3. Only need to check the mv difference
+ vptr = (void*)MbQ->mvL0; // for deref type-punned pointer
+ ptrQ = (int16*)vptr;
+ ptrP = (int16*)(MbP->mvL0 + 3); // points to 4x4 block #3 (the 4th column)
+
+ // 1st blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pStrength++;
+ ptrQ += 8;
+ ptrP += 8;
+
+ // 2nd blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pStrength++;
+ ptrQ += 8;
+ ptrP += 8;
+
+ // 3rd blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pStrength++;
+ ptrQ += 8;
+ ptrP += 8;
+
+ // 4th blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+ }
+ else // Horizontal Edge 0
+ {
+
+ //1. Check the ref_frame_id
+ refIdx = (void*)MbQ->RefIdx; //de-ref type-punned pointer
+ ptrQ = (int16*)refIdx;
+ refIdx = (void*)MbP->RefIdx; //de-ref type-punned pointer
+ ptrP = (int16*)refIdx;
+ pStrength = Strength;
+ if (ptrQ[0] != ptrP[2]) pStrength[0] = 1;
+ if (ptrQ[1] != ptrP[3]) pStrength[2] = 1;
+ pStrength[1] = pStrength[0];
+ pStrength[3] = pStrength[2];
+
+ //2. Check the non-zero coeff blocks (4x4)
+ if (MbQ->nz_coeff[0] != 0 || MbP->nz_coeff[12] != 0) pStrength[0] = 2;
+ if (MbQ->nz_coeff[1] != 0 || MbP->nz_coeff[13] != 0) pStrength[1] = 2;
+ if (MbQ->nz_coeff[2] != 0 || MbP->nz_coeff[14] != 0) pStrength[2] = 2;
+ if (MbQ->nz_coeff[3] != 0 || MbP->nz_coeff[15] != 0) pStrength[3] = 2;
+
+ //3. Only need to check the mv difference
+ vptr = (void*)MbQ->mvL0;
+ ptrQ = (int16*)vptr;
+ ptrP = (int16*)(MbP->mvL0 + 12); // points to 4x4 block #12 (the 4th row)
+
+ // 1st blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pStrength++;
+ ptrQ += 2;
+ ptrP += 2;
+
+ // 2nd blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pStrength++;
+ ptrQ += 2;
+ ptrP += 2;
+
+ // 3rd blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pStrength++;
+ ptrQ += 2;
+ ptrP += 2;
+
+ // 4th blk
+ if (*pStrength == 0)
+ {
+ // check |mv difference| >= 4
+ tmp = *ptrQ++ - *ptrP++;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *ptrQ-- - *ptrP--;
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ } /* end of: else if(dir == 0) */
+
+ } /* end of: if( !(MbP->mbMode == AVC_I4 ...) */
+}
+
+
+void GetStrength_VerticalEdges(uint8 *Strength, AVCMacroblock* MbQ)
+{
+ int idx, tmp;
+ int16 *ptr, *pmvx, *pmvy;
+ uint8 *pnz;
+ uint8 *pStrength, *pStr;
+ void* refIdx;
+
+ if (MbQ->mbMode == AVC_I4 || MbQ->mbMode == AVC_I16)
+ {
+ *((int*)Strength) = ININT_STRENGTH[1]; // Start with Strength=3. or Strength=4 for Mb-edge
+ *((int*)(Strength + 4)) = ININT_STRENGTH[2];
+ *((int*)(Strength + 8)) = ININT_STRENGTH[3];
+ }
+ else // Not intra or SP-frame
+ {
+
+ *((int*)Strength) = 0; // for non-intra MB, strength = 0, 1 or 2.
+ *((int*)(Strength + 4)) = 0;
+ *((int*)(Strength + 8)) = 0;
+
+ //1. Check the ref_frame_id
+ refIdx = (void*)MbQ->RefIdx; //de-ref type-punned pointer fix
+ ptr = (int16*)refIdx;
+ pStrength = Strength;
+ if (ptr[0] != ptr[1]) pStrength[4] = 1;
+ if (ptr[2] != ptr[3]) pStrength[6] = 1;
+ pStrength[5] = pStrength[4];
+ pStrength[7] = pStrength[6];
+
+ //2. Check the nz_coeff block and mv difference
+ pmvx = (int16*)(MbQ->mvL0 + 1); // points to 4x4 block #1,not #0
+ pmvy = pmvx + 1;
+ for (idx = 0; idx < 4; idx += 2) // unroll the loop, make 4 iterations to 2
+ {
+ // first/third row : 1,2,3 or 9,10,12
+ // Strength = 2 for a whole row
+ pnz = MbQ->nz_coeff + (idx << 2);
+ if (*pnz++ != 0) *pStrength = 2;
+ if (*pnz++ != 0)
+ {
+ *pStrength = 2;
+ *(pStrength + 4) = 2;
+ }
+ if (*pnz++ != 0)
+ {
+ *(pStrength + 4) = 2;
+ *(pStrength + 8) = 2;
+ }
+ if (*pnz != 0) *(pStrength + 8) = 2;
+
+ // Then Strength = 1
+ if (*pStrength == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *pmvy - *(pmvy - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pmvx += 2;
+ pmvy += 2;
+ pStr = pStrength + 4;
+
+ if (*pStr == 0)
+ {
+ //check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ pmvx += 2;
+ pmvy += 2;
+ pStr = pStrength + 8;
+
+ if (*pStr == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ // Second/fourth row: 5,6,7 or 14,15,16
+ // Strength = 2 for a whole row
+ pnz = MbQ->nz_coeff + ((idx + 1) << 2);
+ if (*pnz++ != 0) *(pStrength + 1) = 2;
+ if (*pnz++ != 0)
+ {
+ *(pStrength + 1) = 2;
+ *(pStrength + 5) = 2;
+ }
+ if (*pnz++ != 0)
+ {
+ *(pStrength + 5) = 2;
+ *(pStrength + 9) = 2;
+ }
+ if (*pnz != 0) *(pStrength + 9) = 2;
+
+ // Then Strength = 1
+ pmvx += 4;
+ pmvy += 4;
+ pStr = pStrength + 1;
+ if (*pStr == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ pmvx += 2;
+ pmvy += 2;
+ pStr = pStrength + 5;
+
+ if (*pStr == 0)
+ {
+ //check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ pmvx += 2;
+ pmvy += 2;
+ pStr = pStrength + 9;
+
+ if (*pStr == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 2);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ // update some variables for the next two rows
+ pmvx += 4;
+ pmvy += 4;
+ pStrength += 2;
+
+ } /* end of: for(idx=0; idx<2; idx++) */
+
+ } /* end of: else if( MbQ->mbMode == AVC_I4 ...) */
+}
+
+
+void GetStrength_HorizontalEdges(uint8 Strength[12], AVCMacroblock* MbQ)
+{
+ int idx, tmp;
+ int16 *ptr, *pmvx, *pmvy;
+ uint8 *pStrength, *pStr;
+ void* refIdx;
+
+ if (MbQ->mbMode == AVC_I4 || MbQ->mbMode == AVC_I16)
+ {
+ *((int*)Strength) = ININT_STRENGTH[1]; // Start with Strength=3. or Strength=4 for Mb-edge
+ *((int*)(Strength + 4)) = ININT_STRENGTH[2];
+ *((int*)(Strength + 8)) = ININT_STRENGTH[3];
+ }
+ else // Not intra or SP-frame
+ {
+
+ *((int*)Strength) = 0; // for non-intra MB, strength = 0, 1 or 2.
+ *((int*)(Strength + 4)) = 0; // for non-intra MB, strength = 0, 1 or 2.
+ *((int*)(Strength + 8)) = 0; // for non-intra MB, strength = 0, 1 or 2.
+
+
+ //1. Check the ref_frame_id
+ refIdx = (void*) MbQ->RefIdx; // de-ref type-punned fix
+ ptr = (int16*) refIdx;
+ pStrength = Strength;
+ if (ptr[0] != ptr[2]) pStrength[4] = 1;
+ if (ptr[1] != ptr[3]) pStrength[6] = 1;
+ pStrength[5] = pStrength[4];
+ pStrength[7] = pStrength[6];
+
+ //2. Check the nz_coeff block and mv difference
+ pmvx = (int16*)(MbQ->mvL0 + 4); // points to 4x4 block #4,not #0
+ pmvy = pmvx + 1;
+ for (idx = 0; idx < 4; idx += 2) // unroll the loop, make 4 iterations to 2
+ {
+ // first/third row : 1,2,3 or 9,10,12
+ // Strength = 2 for a whole row
+ if (MbQ->nz_coeff[idx] != 0) *pStrength = 2;
+ if (MbQ->nz_coeff[4+idx] != 0)
+ {
+ *pStrength = 2;
+ *(pStrength + 4) = 2;
+ }
+ if (MbQ->nz_coeff[8+idx] != 0)
+ {
+ *(pStrength + 4) = 2;
+ *(pStrength + 8) = 2;
+ }
+ if (MbQ->nz_coeff[12+idx] != 0) *(pStrength + 8) = 2;
+
+ // Then Strength = 1
+ if (*pStrength == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+
+ tmp = *pmvy - *(pmvy - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStrength = 1;
+ }
+
+ pmvx += 8;
+ pmvy += 8;
+ pStr = pStrength + 4;
+
+ if (*pStr == 0)
+ {
+ //check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ pmvx += 8;
+ pmvy += 8;
+ pStr = pStrength + 8;
+
+ if (*pStr == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ // Second/fourth row: 5,6,7 or 14,15,16
+ // Strength = 2 for a whole row
+ if (MbQ->nz_coeff[idx+1] != 0) *(pStrength + 1) = 2;
+ if (MbQ->nz_coeff[4+idx+1] != 0)
+ {
+ *(pStrength + 1) = 2;
+ *(pStrength + 5) = 2;
+ }
+ if (MbQ->nz_coeff[8+idx+1] != 0)
+ {
+ *(pStrength + 5) = 2;
+ *(pStrength + 9) = 2;
+ }
+ if (MbQ->nz_coeff[12+idx+1] != 0) *(pStrength + 9) = 2;
+
+ // Then Strength = 1
+ pmvx -= 14;
+ pmvy -= 14; // -14 = -16 + 2
+ pStr = pStrength + 1;
+ if (*pStr == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ pmvx += 8;
+ pmvy += 8;
+ pStr = pStrength + 5;
+
+ if (*pStr == 0)
+ {
+ //check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ pmvx += 8;
+ pmvy += 8;
+ pStr = pStrength + 9;
+
+ if (*pStr == 0)
+ {
+ //within the same 8x8 block, no need to check the reference id
+ //only need to check the |mv difference| >= 4
+ tmp = *pmvx - *(pmvx - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+
+ tmp = *pmvy - *(pmvy - 8);
+ if (tmp < 0) tmp = -tmp;
+ if (tmp >= 4) *pStr = 1;
+ }
+
+ // update some variables for the next two rows
+ pmvx -= 14;
+ pmvy -= 14; // -14 = -16 + 2
+ pStrength += 2;
+
+ } /* end of: for(idx=0; idx<2; idx++) */
+
+ } /* end of: else if( MbQ->mbMode == AVC_I4 ...) */
+}
+
+/*
+ *****************************************************************************************
+ * \brief Filters one edge of 16 (luma) or 8 (chroma) pel
+ *****************************************************************************************
+*/
+
+void EdgeLoop_Luma_horizontal(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch)
+{
+ int pel, ap = 0, aq = 0, Strng;
+ int C0, c0, dif, AbsDelta, tmp, tmp1;
+ int L2 = 0, L1, L0, R0, R1, R2 = 0, RL0;
+
+
+ if (Strength[0] == 4) /* INTRA strong filtering */
+ {
+ for (pel = 0; pel < 16; pel++)
+ {
+ R0 = SrcPtr[0];
+ R1 = SrcPtr[pitch];
+ L0 = SrcPtr[-pitch];
+ L1 = SrcPtr[-(pitch<<1)];
+
+ // |R0 - R1| < Beta
+ tmp1 = R0 - R1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp = (tmp1 - Beta);
+
+ //|L0 - L1| < Beta
+ tmp1 = L0 - L1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ //|R0 - L0| < Alpha
+ AbsDelta = R0 - L0;
+ if (AbsDelta < 0) AbsDelta = -AbsDelta;
+ tmp &= (AbsDelta - Alpha);
+
+ if (tmp < 0)
+ {
+ AbsDelta -= ((Alpha >> 2) + 2);
+ R2 = SrcPtr[pitch<<1]; //inc2
+ L2 = SrcPtr[-(pitch+(pitch<<1))]; // -inc3
+
+ // |R0 - R2| < Beta && |R0 - L0| < (Alpha/4 + 2)
+ tmp = R0 - R2;
+ if (tmp < 0) tmp = -tmp;
+ aq = AbsDelta & (tmp - Beta);
+
+ // |L0 - L2| < Beta && |R0 - L0| < (Alpha/4 + 2)
+ tmp = L0 - L2;
+ if (tmp < 0) tmp = -tmp;
+ ap = AbsDelta & (tmp - Beta);
+
+ if (aq < 0)
+ {
+ tmp = R1 + R0 + L0;
+ SrcPtr[0] = (L1 + (tmp << 1) + R2 + 4) >> 3;
+ tmp += R2;
+ SrcPtr[pitch] = (tmp + 2) >> 2;
+ SrcPtr[pitch<<1] = (((SrcPtr[(pitch+(pitch<<1))] + R2) << 1) + tmp + 4) >> 3;
+ }
+ else
+ SrcPtr[0] = ((R1 << 1) + R0 + L1 + 2) >> 2;
+
+ if (ap < 0)
+ {
+ tmp = L1 + R0 + L0;
+ SrcPtr[-pitch] = (R1 + (tmp << 1) + L2 + 4) >> 3;
+ tmp += L2;
+ SrcPtr[-(pitch<<1)] = (tmp + 2) >> 2;
+ SrcPtr[-(pitch+(pitch<<1))] = (((SrcPtr[-(pitch<<2)] + L2) << 1) + tmp + 4) >> 3;
+ }
+ else
+ SrcPtr[-pitch] = ((L1 << 1) + L0 + R1 + 2) >> 2;
+
+ } /* if(tmp < 0) */
+
+ SrcPtr ++; // Increment to next set of pixel
+
+ } /* end of: for(pel=0; pel<16; pel++) */
+
+ } /* if(Strength[0] == 4) */
+
+ else /* Normal filtering */
+ {
+ for (pel = 0; pel < 16; pel++)
+ {
+ Strng = Strength[pel >> 2];
+ if (Strng)
+ {
+ R0 = SrcPtr[0];
+ R1 = SrcPtr[pitch];
+ L0 = SrcPtr[-pitch];
+ L1 = SrcPtr[-(pitch<<1)]; // inc2
+
+ //|R0 - L0| < Alpha
+ tmp1 = R0 - L0;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp = (tmp1 - Alpha);
+
+ // |R0 - R1| < Beta
+ tmp1 = R0 - R1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ //|L0 - L1| < Beta
+ tmp1 = L0 - L1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ if (tmp < 0)
+ {
+ R2 = SrcPtr[pitch<<1]; //inc2
+ L2 = SrcPtr[-(pitch+(pitch<<1))]; // -inc3
+
+ // |R0 - R2| < Beta
+ tmp = R0 - R2;
+ if (tmp < 0) tmp = -tmp;
+ aq = tmp - Beta;
+
+ // |L0 - L2| < Beta
+ tmp = L0 - L2;
+ if (tmp < 0) tmp = -tmp;
+ ap = tmp - Beta;
+
+
+ c0 = C0 = clipTable[Strng];
+ if (ap < 0) c0++;
+ if (aq < 0) c0++;
+
+ //dif = IClip(-c0, c0, ((Delta << 2) + (L1 - R1) + 4) >> 3);
+ dif = (((R0 - L0) << 2) + (L1 - R1) + 4) >> 3;
+ tmp = dif + c0;
+ if ((uint)tmp > (uint)c0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ dif = (tmp & (c0 << 1)) - c0;
+ }
+
+ //SrcPtr[0] = (uint8)IClip(0, 255, R0 - dif);
+ //SrcPtr[-inc] = (uint8)IClip(0, 255, L0 + dif);
+ RL0 = R0 + L0;
+ R0 -= dif;
+ L0 += dif;
+ if ((uint)R0 > 255)
+ {
+ tmp = ~(R0 >> 31);
+ R0 = tmp & 255;
+ }
+ if ((uint)L0 > 255)
+ {
+ tmp = ~(L0 >> 31);
+ L0 = tmp & 255;
+ }
+ SrcPtr[-pitch] = L0;
+ SrcPtr[0] = R0;
+
+ if (C0 != 0) /* Multiple zeros in the clip tables */
+ {
+ if (aq < 0) // SrcPtr[inc] += IClip(-C0, C0,(R2 + ((RL0 + 1) >> 1) - (R1<<1)) >> 1);
+ {
+ R2 = (R2 + ((RL0 + 1) >> 1) - (R1 << 1)) >> 1;
+ tmp = R2 + C0;
+ if ((uint)tmp > (uint)C0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ R2 = (tmp & (C0 << 1)) - C0;
+ }
+ SrcPtr[pitch] += R2;
+ }
+
+ if (ap < 0) //SrcPtr[-inc2] += IClip(-C0, C0,(L2 + ((RL0 + 1) >> 1) - (L1<<1)) >> 1);
+ {
+ L2 = (L2 + ((RL0 + 1) >> 1) - (L1 << 1)) >> 1;
+ tmp = L2 + C0;
+ if ((uint)tmp > (uint)C0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ L2 = (tmp & (C0 << 1)) - C0;
+ }
+ SrcPtr[-(pitch<<1)] += L2;
+ }
+ }
+
+ } /* if(tmp < 0) */
+
+ } /* end of: if((Strng = Strength[pel >> 2])) */
+
+ SrcPtr ++; // Increment to next set of pixel
+
+ } /* for(pel=0; pel<16; pel++) */
+
+ } /* else if(Strength[0] == 4) */
+}
+
+void EdgeLoop_Luma_vertical(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch)
+{
+ int pel, ap = 1, aq = 1;
+ int C0, c0, dif, AbsDelta, Strng, tmp, tmp1;
+ int L2 = 0, L1, L0, R0, R1, R2 = 0;
+ uint8 *ptr, *ptr1;
+ register uint R_in, L_in;
+ uint R_out, L_out;
+
+
+ if (Strength[0] == 4) /* INTRA strong filtering */
+ {
+
+ for (pel = 0; pel < 16; pel++)
+ {
+
+ // Read 8 pels
+ R_in = *((uint *)SrcPtr); // R_in = {R3, R2, R1, R0}
+ L_in = *((uint *)(SrcPtr - 4)); // L_in = {L0, L1, L2, L3}
+ R1 = (R_in >> 8) & 0xff;
+ R0 = R_in & 0xff;
+ L0 = L_in >> 24;
+ L1 = (L_in >> 16) & 0xff;
+
+ // |R0 - R1| < Beta
+ tmp1 = (R_in & 0xff) - R1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp = (tmp1 - Beta);
+
+
+ //|L0 - L1| < Beta
+ tmp1 = (L_in >> 24) - L1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ //|R0 - L0| < Alpha
+ AbsDelta = (R_in & 0xff) - (L_in >> 24);
+ if (AbsDelta < 0) AbsDelta = -AbsDelta;
+ tmp &= (AbsDelta - Alpha);
+
+ if (tmp < 0)
+ {
+ AbsDelta -= ((Alpha >> 2) + 2);
+ R2 = (R_in >> 16) & 0xff;
+ L2 = (L_in >> 8) & 0xff;
+
+ // |R0 - R2| < Beta && |R0 - L0| < (Alpha/4 + 2)
+ tmp1 = (R_in & 0xff) - R2;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ aq = AbsDelta & (tmp1 - Beta);
+
+ // |L0 - L2| < Beta && |R0 - L0| < (Alpha/4 + 2)
+ tmp1 = (L_in >> 24) - L2;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ ap = AbsDelta & (tmp1 - Beta);
+
+
+ ptr = SrcPtr;
+ if (aq < 0)
+ {
+ R_out = (R_in >> 24) << 24; // Keep R3 at the fourth byte
+
+ tmp = R0 + L0 + R1;
+ R_out |= (((tmp << 1) + L1 + R2 + 4) >> 3);
+ tmp += R2;
+ R_out |= (((tmp + 2) >> 2) << 8);
+ tmp1 = ((R_in >> 24) + R2) << 1;
+ R_out |= (((tmp1 + tmp + 4) >> 3) << 16);
+
+ *((uint *)SrcPtr) = R_out;
+ }
+ else
+ *ptr = ((R1 << 1) + R0 + L1 + 2) >> 2;
+
+
+ if (ap < 0)
+ {
+ L_out = (L_in << 24) >> 24; // Keep L3 at the first byte
+
+ tmp = R0 + L0 + L1;
+ L_out |= ((((tmp << 1) + R1 + L2 + 4) >> 3) << 24);
+ tmp += L2;
+ L_out |= (((tmp + 2) >> 2) << 16);
+ tmp1 = ((L_in & 0xff) + L2) << 1;
+ L_out |= (((tmp1 + tmp + 4) >> 3) << 8);
+
+ *((uint *)(SrcPtr - 4)) = L_out;
+ }
+ else
+ *(--ptr) = ((L1 << 1) + L0 + R1 + 2) >> 2;
+
+ } /* if(tmp < 0) */
+
+ SrcPtr += pitch; // Increment to next set of pixel
+
+ } /* end of: for(pel=0; pel<16; pel++) */
+
+ } /* if(Strength[0] == 4) */
+
+ else /* Normal filtering */
+ {
+
+ for (pel = 0; pel < 16; pel++)
+ {
+ Strng = Strength[pel >> 2];
+ if (Strng)
+ {
+ // Read 8 pels
+ R_in = *((uint *)SrcPtr); // R_in = {R3, R2, R1, R0}
+ L_in = *((uint *)(SrcPtr - 4)); // L_in = {L0, L1, L2, L3}
+ R1 = (R_in >> 8) & 0xff;
+ R0 = R_in & 0xff;
+ L0 = L_in >> 24;
+ L1 = (L_in >> 16) & 0xff;
+
+ //|R0 - L0| < Alpha
+ tmp = R0 - L0;
+ if (tmp < 0) tmp = -tmp;
+ tmp -= Alpha;
+
+ // |R0 - R1| < Beta
+ tmp1 = R0 - R1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ //|L0 - L1| < Beta
+ tmp1 = L0 - L1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ if (tmp < 0)
+ {
+ L2 = SrcPtr[-3];
+ R2 = SrcPtr[2];
+
+ // |R0 - R2| < Beta
+ tmp = R0 - R2;
+ if (tmp < 0) tmp = -tmp;
+ aq = tmp - Beta;
+
+ // |L0 - L2| < Beta
+ tmp = L0 - L2;
+ if (tmp < 0) tmp = -tmp;
+ ap = tmp - Beta;
+
+
+ c0 = C0 = clipTable[Strng];
+ if (ap < 0) c0++;
+ if (aq < 0) c0++;
+
+ //dif = IClip(-c0, c0, ((Delta << 2) + (L1 - R1) + 4) >> 3);
+ dif = (((R0 - L0) << 2) + (L1 - R1) + 4) >> 3;
+ tmp = dif + c0;
+ if ((uint)tmp > (uint)c0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ dif = (tmp & (c0 << 1)) - c0;
+ }
+
+ ptr = SrcPtr;
+ ptr1 = SrcPtr - 1;
+ //SrcPtr[0] = (uint8)IClip(0, 255, R0 - dif);
+ //SrcPtr[-inc] = (uint8)IClip(0, 255, L0 + dif);
+ R_in = R0 - dif;
+ L_in = L0 + dif; /* cannot re-use R0 and L0 here */
+ if ((uint)R_in > 255)
+ {
+ tmp = ~((int)R_in >> 31);
+ R_in = tmp & 255;
+ }
+ if ((uint)L_in > 255)
+ {
+ tmp = ~((int)L_in >> 31);
+ L_in = tmp & 255;
+ }
+ *ptr1-- = L_in;
+ *ptr++ = R_in;
+
+ if (C0 != 0) // Multiple zeros in the clip tables
+ {
+ if (ap < 0) //SrcPtr[-inc2] += IClip(-C0, C0,(L2 + ((RL0 + 1) >> 1) - (L1<<1)) >> 1);
+ {
+ L2 = (L2 + ((R0 + L0 + 1) >> 1) - (L1 << 1)) >> 1;
+ tmp = L2 + C0;
+ if ((uint)tmp > (uint)C0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ L2 = (tmp & (C0 << 1)) - C0;
+ }
+ *ptr1 += L2;
+ }
+
+ if (aq < 0) // SrcPtr[inc] += IClip(-C0, C0,(R2 + ((RL0 + 1) >> 1) - (R1<<1)) >> 1);
+ {
+ R2 = (R2 + ((R0 + L0 + 1) >> 1) - (R1 << 1)) >> 1;
+ tmp = R2 + C0;
+ if ((uint)tmp > (uint)C0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ R2 = (tmp & (C0 << 1)) - C0;
+ }
+ *ptr += R2;
+ }
+ }
+
+ } /* if(tmp < 0) */
+
+ } /* end of: if((Strng = Strength[pel >> 2])) */
+
+ SrcPtr += pitch; // Increment to next set of pixel
+
+ } /* for(pel=0; pel<16; pel++) */
+
+ } /* else if(Strength[0] == 4) */
+
+}
+
+void EdgeLoop_Chroma_vertical(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch)
+{
+ int pel, Strng;
+ int c0, dif;
+ int L1, L0, R0, R1, tmp, tmp1;
+ uint8 *ptr;
+ uint R_in, L_in;
+
+
+ for (pel = 0; pel < 16; pel++)
+ {
+ Strng = Strength[pel>>2];
+ if (Strng)
+ {
+ // Read 8 pels
+ R_in = *((uint *)SrcPtr); // R_in = {R3, R2, R1, R0}
+ L_in = *((uint *)(SrcPtr - 4)); // L_in = {L0, L1, L2, L3}
+ R1 = (R_in >> 8) & 0xff;
+ R0 = R_in & 0xff;
+ L0 = L_in >> 24;
+ L1 = (L_in >> 16) & 0xff;
+
+ // |R0 - R1| < Beta
+ tmp1 = R0 - R1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp = (tmp1 - Beta);
+
+ //|L0 - L1| < Beta
+ tmp1 = L0 - L1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ //|R0 - L0| < Alpha
+ tmp1 = R0 - L0;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Alpha);
+
+ if (tmp < 0)
+ {
+ ptr = SrcPtr;
+ if (Strng == 4) /* INTRA strong filtering */
+ {
+ *ptr-- = ((R1 << 1) + R0 + L1 + 2) >> 2;
+ *ptr = ((L1 << 1) + L0 + R1 + 2) >> 2;
+ }
+ else /* normal filtering */
+ {
+ c0 = clipTable[Strng] + 1;
+ //dif = IClip(-c0, c0, ((Delta << 2) + (L1 - R1) + 4) >> 3);
+ dif = (((R0 - L0) << 2) + (L1 - R1) + 4) >> 3;
+ tmp = dif + c0;
+ if ((uint)tmp > (uint)c0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ dif = (tmp & (c0 << 1)) - c0;
+ }
+
+ //SrcPtr[0] = (uint8)IClip(0, 255, R0 - dif);
+ //SrcPtr[-inc] = (uint8)IClip(0, 255, L0 + dif);
+ L0 += dif;
+ R0 -= dif;
+ if ((uint)L0 > 255)
+ {
+ tmp = ~(L0 >> 31);
+ L0 = tmp & 255;
+ }
+ if ((uint)R0 > 255)
+ {
+ tmp = ~(R0 >> 31);
+ R0 = tmp & 255;
+ }
+
+ *ptr-- = R0;
+ *ptr = L0;
+ }
+ }
+ pel ++;
+ SrcPtr += pitch; // Increment to next set of pixel
+
+ } /* end of: if((Strng = Strength[pel >> 2])) */
+ else
+ {
+ pel += 3;
+ SrcPtr += (pitch << 1); //PtrInc << 1;
+ }
+
+ } /* end of: for(pel=0; pel<16; pel++) */
+}
+
+
+void EdgeLoop_Chroma_horizontal(uint8* SrcPtr, uint8 *Strength, int Alpha, int Beta, int *clipTable, int pitch)
+{
+ int pel, Strng;
+ int c0, dif;
+ int L1, L0, R0, R1, tmp, tmp1;
+
+ for (pel = 0; pel < 16; pel++)
+ {
+ Strng = Strength[pel>>2];
+ if (Strng)
+ {
+ R0 = SrcPtr[0];
+ L0 = SrcPtr[-pitch];
+ L1 = SrcPtr[-(pitch<<1)]; //inc2
+ R1 = SrcPtr[pitch];
+
+ // |R0 - R1| < Beta
+ tmp1 = R0 - R1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp = (tmp1 - Beta);
+
+ //|L0 - L1| < Beta
+ tmp1 = L0 - L1;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Beta);
+
+ //|R0 - L0| < Alpha
+ tmp1 = R0 - L0;
+ if (tmp1 < 0) tmp1 = -tmp1;
+ tmp &= (tmp1 - Alpha);
+
+ if (tmp < 0)
+ {
+ if (Strng == 4) /* INTRA strong filtering */
+ {
+ SrcPtr[0] = ((R1 << 1) + R0 + L1 + 2) >> 2;
+ SrcPtr[-pitch] = ((L1 << 1) + L0 + R1 + 2) >> 2;
+ }
+ else /* normal filtering */
+ {
+ c0 = clipTable[Strng] + 1;
+ //dif = IClip(-c0, c0, ((Delta << 2) + (L1 - R1) + 4) >> 3);
+ dif = (((R0 - L0) << 2) + (L1 - R1) + 4) >> 3;
+ tmp = dif + c0;
+ if ((uint)tmp > (uint)c0 << 1)
+ {
+ tmp = ~(tmp >> 31);
+ dif = (tmp & (c0 << 1)) - c0;
+ }
+
+ //SrcPtr[-inc] = (uint8)IClip(0, 255, L0 + dif);
+ //SrcPtr[0] = (uint8)IClip(0, 255, R0 - dif);
+ L0 += dif;
+ R0 -= dif;
+ if ((uint)L0 > 255)
+ {
+ tmp = ~(L0 >> 31);
+ L0 = tmp & 255;
+ }
+ if ((uint)R0 > 255)
+ {
+ tmp = ~(R0 >> 31);
+ R0 = tmp & 255;
+ }
+ SrcPtr[0] = R0;
+ SrcPtr[-pitch] = L0;
+ }
+ }
+
+ pel ++;
+ SrcPtr ++; // Increment to next set of pixel
+
+ } /* end of: if((Strng = Strength[pel >> 2])) */
+ else
+ {
+ pel += 3;
+ SrcPtr += 2;
+ }
+
+ } /* end of: for(pel=0; pel<16; pel++) */
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/avc/common/src/dpb.cpp b/media/libstagefright/codecs/avc/common/src/dpb.cpp
new file mode 100644
index 0000000..2c4c7da
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/src/dpb.cpp
@@ -0,0 +1,724 @@
+/* ------------------------------------------------------------------
+ * 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 "avclib_common.h"
+
+#define DPB_MEM_ATTR 0
+
+AVCStatus InitDPB(AVCHandle *avcHandle, AVCCommonObj *video, int FrameHeightInMbs, int PicWidthInMbs, bool padding)
+{
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int level, framesize, num_fs;
+ void *userData = avcHandle->userData;
+#ifndef PV_MEMORY_POOL
+ uint32 addr;
+#endif
+ uint16 refIdx = 0;
+ level = video->currSeqParams->level_idc;
+
+ for (num_fs = 0; num_fs < MAX_FS; num_fs++)
+ {
+ dpb->fs[num_fs] = NULL;
+ }
+
+ framesize = (int)(((FrameHeightInMbs * PicWidthInMbs) << 7) * 3);
+ if (padding)
+ {
+ video->padded_size = (int)((((FrameHeightInMbs + 2) * (PicWidthInMbs + 2)) << 7) * 3) - framesize;
+ }
+ else
+ {
+ video->padded_size = 0;
+ }
+
+#ifndef PV_MEMORY_POOL
+ if (dpb->decoded_picture_buffer)
+ {
+ avcHandle->CBAVC_Free(userData, (int)dpb->decoded_picture_buffer);
+ dpb->decoded_picture_buffer = NULL;
+ }
+#endif
+ /* need to allocate one extra frame for current frame, DPB only defines for reference frames */
+
+ dpb->num_fs = (uint32)(MaxDPBX2[mapLev2Idx[level]] << 2) / (3 * FrameHeightInMbs * PicWidthInMbs) + 1;
+ if (dpb->num_fs > MAX_FS)
+ {
+ dpb->num_fs = MAX_FS;
+ }
+
+ if (video->currSeqParams->num_ref_frames + 1 > (uint32)dpb->num_fs)
+ {
+ dpb->num_fs = video->currSeqParams->num_ref_frames + 1;
+ }
+
+ dpb->dpb_size = dpb->num_fs * (framesize + video->padded_size);
+// dpb->dpb_size = (uint32)MaxDPBX2[mapLev2Idx[level]]*512 + framesize;
+
+#ifndef PV_MEMORY_POOL
+ dpb->decoded_picture_buffer = (uint8*) avcHandle->CBAVC_Malloc(userData, dpb->dpb_size, 100/*DPB_MEM_ATTR*/);
+
+ if (dpb->decoded_picture_buffer == NULL || dpb->decoded_picture_buffer&0x3) // not word aligned
+ return AVC_MEMORY_FAIL;
+#endif
+ dpb->used_size = 0;
+ num_fs = 0;
+
+ while (num_fs < dpb->num_fs)
+ {
+ /* fs is an array pointers to AVCDecPicture */
+ dpb->fs[num_fs] = (AVCFrameStore*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCFrameStore), 101/*DEFAULT_ATTR*/);
+ if (dpb->fs[num_fs] == NULL)
+ {
+ return AVC_MEMORY_FAIL;
+ }
+#ifndef PV_MEMORY_POOL
+ /* assign the actual memory for Sl, Scb, Scr */
+ dpb->fs[num_fs]->base_dpb = dpb->decoded_picture_buffer + dpb->used_size;
+#endif
+ dpb->fs[num_fs]->IsReference = 0;
+ dpb->fs[num_fs]->IsLongTerm = 0;
+ dpb->fs[num_fs]->IsOutputted = 3;
+ dpb->fs[num_fs]->frame.RefIdx = refIdx++; /* this value will remain unchanged through out the encoding session */
+ dpb->fs[num_fs]->frame.picType = AVC_FRAME;
+ dpb->fs[num_fs]->frame.isLongTerm = 0;
+ dpb->fs[num_fs]->frame.isReference = 0;
+ video->RefPicList0[num_fs] = &(dpb->fs[num_fs]->frame);
+ dpb->fs[num_fs]->frame.padded = 0;
+ dpb->used_size += (framesize + video->padded_size);
+ num_fs++;
+ }
+
+ return AVC_SUCCESS;
+}
+
+OSCL_EXPORT_REF AVCStatus AVCConfigureSequence(AVCHandle *avcHandle, AVCCommonObj *video, bool padding)
+{
+ void *userData = avcHandle->userData;
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int framesize, ii; /* size of one frame */
+ uint PicWidthInMbs, PicHeightInMapUnits, FrameHeightInMbs, PicSizeInMapUnits;
+ uint num_fs;
+ /* derived variables from SPS */
+ PicWidthInMbs = video->currSeqParams->pic_width_in_mbs_minus1 + 1;
+ PicHeightInMapUnits = video->currSeqParams->pic_height_in_map_units_minus1 + 1 ;
+ FrameHeightInMbs = (2 - video->currSeqParams->frame_mbs_only_flag) * PicHeightInMapUnits ;
+ PicSizeInMapUnits = PicWidthInMbs * PicHeightInMapUnits ;
+
+ if (video->PicSizeInMapUnits != PicSizeInMapUnits || video->currSeqParams->level_idc != video->level_idc)
+ {
+ /* make sure you mark all the frames as unused for reference for flushing*/
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ dpb->fs[ii]->IsReference = 0;
+ dpb->fs[ii]->IsOutputted |= 0x02;
+ }
+
+ num_fs = (uint32)(MaxDPBX2[(uint32)mapLev2Idx[video->currSeqParams->level_idc]] << 2) / (3 * PicSizeInMapUnits) + 1;
+ if (num_fs >= MAX_FS)
+ {
+ num_fs = MAX_FS;
+ }
+#ifdef PV_MEMORY_POOL
+ if (padding)
+ {
+ avcHandle->CBAVC_DPBAlloc(avcHandle->userData,
+ PicSizeInMapUnits + ((PicWidthInMbs + 2) << 1) + (PicHeightInMapUnits << 1), num_fs);
+ }
+ else
+ {
+ avcHandle->CBAVC_DPBAlloc(avcHandle->userData, PicSizeInMapUnits, num_fs);
+ }
+#endif
+ CleanUpDPB(avcHandle, video);
+ if (InitDPB(avcHandle, video, FrameHeightInMbs, PicWidthInMbs, padding) != AVC_SUCCESS)
+ {
+ return AVC_FAIL;
+ }
+ /* Allocate video->mblock upto PicSizeInMbs and populate the structure such as the neighboring MB pointers. */
+ framesize = (FrameHeightInMbs * PicWidthInMbs);
+ if (video->mblock)
+ {
+ avcHandle->CBAVC_Free(userData, (uint32)video->mblock);
+ video->mblock = NULL;
+ }
+ video->mblock = (AVCMacroblock*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCMacroblock) * framesize, DEFAULT_ATTR);
+ if (video->mblock == NULL)
+ {
+ return AVC_FAIL;
+ }
+ for (ii = 0; ii < framesize; ii++)
+ {
+ video->mblock[ii].slice_id = -1;
+ }
+ /* Allocate memory for intra prediction */
+#ifdef MB_BASED_DEBLOCK
+ video->intra_pred_top = (uint8*) avcHandle->CBAVC_Malloc(userData, PicWidthInMbs << 4, FAST_MEM_ATTR);
+ if (video->intra_pred_top == NULL)
+ {
+ return AVC_FAIL;
+ }
+ video->intra_pred_top_cb = (uint8*) avcHandle->CBAVC_Malloc(userData, PicWidthInMbs << 3, FAST_MEM_ATTR);
+ if (video->intra_pred_top_cb == NULL)
+ {
+ return AVC_FAIL;
+ }
+ video->intra_pred_top_cr = (uint8*) avcHandle->CBAVC_Malloc(userData, PicWidthInMbs << 3, FAST_MEM_ATTR);
+ if (video->intra_pred_top_cr == NULL)
+ {
+ return AVC_FAIL;
+ }
+
+#endif
+ /* Allocate slice group MAP map */
+
+ if (video->MbToSliceGroupMap)
+ {
+ avcHandle->CBAVC_Free(userData, (uint32)video->MbToSliceGroupMap);
+ video->MbToSliceGroupMap = NULL;
+ }
+ video->MbToSliceGroupMap = (int*) avcHandle->CBAVC_Malloc(userData, sizeof(uint) * PicSizeInMapUnits * 2, 7/*DEFAULT_ATTR*/);
+ if (video->MbToSliceGroupMap == NULL)
+ {
+ return AVC_FAIL;
+ }
+ video->PicSizeInMapUnits = PicSizeInMapUnits;
+ video->level_idc = video->currSeqParams->level_idc;
+
+ }
+ return AVC_SUCCESS;
+}
+
+OSCL_EXPORT_REF AVCStatus CleanUpDPB(AVCHandle *avcHandle, AVCCommonObj *video)
+{
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int ii;
+ void *userData = avcHandle->userData;
+
+ for (ii = 0; ii < MAX_FS; ii++)
+ {
+ if (dpb->fs[ii] != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)dpb->fs[ii]);
+ dpb->fs[ii] = NULL;
+ }
+ }
+#ifndef PV_MEMORY_POOL
+ if (dpb->decoded_picture_buffer)
+ {
+ avcHandle->CBAVC_Free(userData, (int)dpb->decoded_picture_buffer);
+ dpb->decoded_picture_buffer = NULL;
+ }
+#endif
+ dpb->used_size = 0;
+ dpb->dpb_size = 0;
+
+ return AVC_SUCCESS;
+}
+
+OSCL_EXPORT_REF AVCStatus DPBInitBuffer(AVCHandle *avcHandle, AVCCommonObj *video)
+{
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int ii, status;
+
+ /* Before doing any decoding, check if there's a frame memory available */
+ /* look for next unused dpb->fs, or complementary field pair */
+ /* video->currPic is assigned to this */
+
+ /* There's also restriction on the frame_num, see page 59 of JVT-I1010.doc. */
+
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ /* looking for the one not used or not reference and has been outputted */
+ if (dpb->fs[ii]->IsReference == 0 && dpb->fs[ii]->IsOutputted == 3)
+ {
+ video->currFS = dpb->fs[ii];
+#ifdef PV_MEMORY_POOL
+ status = avcHandle->CBAVC_FrameBind(avcHandle->userData, ii, &(video->currFS->base_dpb));
+ if (status == AVC_FAIL)
+ {
+ return AVC_NO_BUFFER; /* this should not happen */
+ }
+#endif
+ break;
+ }
+ }
+ if (ii == dpb->num_fs)
+ {
+ return AVC_PICTURE_OUTPUT_READY; /* no empty frame available */
+ }
+ return AVC_SUCCESS;
+}
+
+OSCL_EXPORT_REF void DPBInitPic(AVCCommonObj *video, int CurrPicNum)
+{
+ int offset = 0;
+ int offsetc = 0;
+ int luma_framesize;
+ /* this part has to be set here, assuming that slice header and POC have been decoded. */
+ /* used in GetOutput API */
+ video->currFS->PicOrderCnt = video->PicOrderCnt;
+ video->currFS->FrameNum = video->sliceHdr->frame_num;
+ video->currFS->FrameNumWrap = CurrPicNum; // MC_FIX
+ /* initialize everything to zero */
+ video->currFS->IsOutputted = 0;
+ video->currFS->IsReference = 0;
+ video->currFS->IsLongTerm = 0;
+ video->currFS->frame.isReference = FALSE;
+ video->currFS->frame.isLongTerm = FALSE;
+
+ /* initialize the pixel pointer to NULL */
+ video->currFS->frame.Sl = video->currFS->frame.Scb = video->currFS->frame.Scr = NULL;
+
+ /* determine video->currPic */
+ /* assign dbp->base_dpb to fs[i]->frame.Sl, Scb, Scr .*/
+ /* For PicSizeInMbs, see DecodeSliceHeader() */
+
+ video->currPic = &(video->currFS->frame);
+
+ video->currPic->padded = 0; // reset this flag to not-padded
+
+ if (video->padded_size)
+ {
+ offset = ((video->PicWidthInSamplesL + 32) << 4) + 16; // offset to the origin
+ offsetc = (offset >> 2) + 4;
+ luma_framesize = (int)((((video->FrameHeightInMbs + 2) * (video->PicWidthInMbs + 2)) << 8));
+ }
+ else
+ luma_framesize = video->PicSizeInMbs << 8;
+
+
+ video->currPic->Sl = video->currFS->base_dpb + offset;
+ video->currPic->Scb = video->currFS->base_dpb + luma_framesize + offsetc;
+ video->currPic->Scr = video->currPic->Scb + (luma_framesize >> 2);
+ video->currPic->pitch = video->PicWidthInSamplesL + (video->padded_size == 0 ? 0 : 32);
+
+
+ video->currPic->height = video->PicHeightInSamplesL;
+ video->currPic->width = video->PicWidthInSamplesL;
+ video->currPic->PicNum = CurrPicNum;
+}
+
+/* to release skipped frame after encoding */
+OSCL_EXPORT_REF void DPBReleaseCurrentFrame(AVCHandle *avcHandle, AVCCommonObj *video)
+{
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int ii;
+
+ video->currFS->IsOutputted = 3; // return this buffer.
+
+#ifdef PV_MEMORY_POOL /* for non-memory pool, no need to do anything */
+
+ /* search for current frame index */
+ ii = dpb->num_fs;
+ while (ii--)
+ {
+ if (dpb->fs[ii] == video->currFS)
+ {
+ avcHandle->CBAVC_FrameUnbind(avcHandle->userData, ii);
+ break;
+ }
+ }
+#endif
+
+ return ;
+}
+
+/* see subclause 8.2.5.1 */
+OSCL_EXPORT_REF AVCStatus StorePictureInDPB(AVCHandle *avcHandle, AVCCommonObj *video)
+{
+ AVCStatus status;
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ int ii, num_ref;
+
+ /* number 1 of 8.2.5.1, we handle gaps in frame_num differently without using the memory */
+ /* to be done!!!! */
+
+ /* number 3 of 8.2.5.1 */
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii] != video->currFS) /* not current frame */
+ {
+ dpb->fs[ii]->IsReference = 0; /* mark as unused for reference */
+ dpb->fs[ii]->IsLongTerm = 0; /* but still used until output */
+ dpb->fs[ii]->IsOutputted |= 0x02;
+#ifdef PV_MEMORY_POOL
+ if (dpb->fs[ii]->IsOutputted == 3)
+ {
+ avcHandle->CBAVC_FrameUnbind(avcHandle->userData, ii);
+ }
+#endif
+ }
+ }
+
+ video->currPic->isReference = TRUE;
+ video->currFS->IsReference = 3;
+
+ if (sliceHdr->long_term_reference_flag == 0)
+ {
+ video->currPic->isLongTerm = FALSE;
+ video->currFS->IsLongTerm = 0;
+ video->MaxLongTermFrameIdx = -1;
+ }
+ else
+ {
+ video->currPic->isLongTerm = TRUE;
+ video->currFS->IsLongTerm = 3;
+ video->currFS->LongTermFrameIdx = 0;
+ video->MaxLongTermFrameIdx = 0;
+ }
+ if (sliceHdr->no_output_of_prior_pics_flag)
+ {
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii] != video->currFS) /* not current frame */
+ {
+ dpb->fs[ii]->IsOutputted = 3;
+#ifdef PV_MEMORY_POOL
+ avcHandle->CBAVC_FrameUnbind(avcHandle->userData, ii);
+#endif
+ }
+ }
+ }
+ video->mem_mgr_ctrl_eq_5 = TRUE; /* flush reference frames MC_FIX */
+ }
+ else
+ {
+ if (video->currPic->isReference == TRUE)
+ {
+ if (sliceHdr->adaptive_ref_pic_marking_mode_flag == 0)
+ {
+ status = sliding_window_process(avcHandle, video, dpb); /* we may have to do this after adaptive_memory_marking */
+ }
+ else
+ {
+ status = adaptive_memory_marking(avcHandle, video, dpb, sliceHdr);
+ }
+ if (status != AVC_SUCCESS)
+ {
+ return status;
+ }
+ }
+ }
+ /* number 4 of 8.2.5.1 */
+ /* This basically says every frame must be at least used for short-term ref. */
+ /* Need to be revisited!!! */
+ /* look at insert_picture_in_dpb() */
+
+
+
+ if (video->nal_unit_type != AVC_NALTYPE_IDR && video->currPic->isLongTerm == FALSE)
+ {
+ if (video->currPic->isReference)
+ {
+ video->currFS->IsReference = 3;
+ }
+ else
+ {
+ video->currFS->IsReference = 0;
+ }
+ video->currFS->IsLongTerm = 0;
+ }
+
+ /* check if number of reference frames doesn't exceed num_ref_frames */
+ num_ref = 0;
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii]->IsReference)
+ {
+ num_ref++;
+ }
+ }
+
+ if (num_ref > (int)video->currSeqParams->num_ref_frames)
+ {
+ return AVC_FAIL; /* out of range */
+ }
+
+ return AVC_SUCCESS;
+}
+
+
+AVCStatus sliding_window_process(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb)
+{
+ int ii, numShortTerm, numLongTerm;
+ int32 MinFrameNumWrap;
+ int MinIdx;
+
+
+ numShortTerm = 0;
+ numLongTerm = 0;
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii] != video->currFS) /* do not count the current frame */
+ {
+ if (dpb->fs[ii]->IsLongTerm)
+ {
+ numLongTerm++;
+ }
+ else if (dpb->fs[ii]->IsReference)
+ {
+ numShortTerm++;
+ }
+ }
+ }
+
+ while (numShortTerm + numLongTerm >= (int)video->currSeqParams->num_ref_frames)
+ {
+ /* get short-term ref frame with smallest PicOrderCnt */
+ /* this doesn't work for all I-slice clip since PicOrderCnt will not be initialized */
+
+ MinFrameNumWrap = 0x7FFFFFFF;
+ MinIdx = -1;
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii]->IsReference && !dpb->fs[ii]->IsLongTerm)
+ {
+ if (dpb->fs[ii]->FrameNumWrap < MinFrameNumWrap)
+ {
+ MinFrameNumWrap = dpb->fs[ii]->FrameNumWrap;
+ MinIdx = ii;
+ }
+ }
+ }
+ if (MinIdx < 0) /* something wrong, impossible */
+ {
+ return AVC_FAIL;
+ }
+
+ /* mark the frame with smallest PicOrderCnt to be unused for reference */
+ dpb->fs[MinIdx]->IsReference = 0;
+ dpb->fs[MinIdx]->IsLongTerm = 0;
+ dpb->fs[MinIdx]->frame.isReference = FALSE;
+ dpb->fs[MinIdx]->frame.isLongTerm = FALSE;
+ dpb->fs[MinIdx]->IsOutputted |= 0x02;
+#ifdef PV_MEMORY_POOL
+ if (dpb->fs[MinIdx]->IsOutputted == 3)
+ {
+ avcHandle->CBAVC_FrameUnbind(avcHandle->userData, MinIdx);
+ }
+#endif
+ numShortTerm--;
+ }
+ return AVC_SUCCESS;
+}
+
+/* see subclause 8.2.5.4 */
+AVCStatus adaptive_memory_marking(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, AVCSliceHeader *sliceHdr)
+{
+ int ii;
+
+ ii = 0;
+ while (ii < MAX_DEC_REF_PIC_MARKING && sliceHdr->memory_management_control_operation[ii] != 0)
+ {
+ switch (sliceHdr->memory_management_control_operation[ii])
+ {
+ case 1:
+ MemMgrCtrlOp1(avcHandle, video, dpb, sliceHdr->difference_of_pic_nums_minus1[ii]);
+ // update_ref_list(dpb);
+ break;
+ case 2:
+ MemMgrCtrlOp2(avcHandle, dpb, sliceHdr->long_term_pic_num[ii]);
+ break;
+ case 3:
+ MemMgrCtrlOp3(avcHandle, video, dpb, sliceHdr->difference_of_pic_nums_minus1[ii], sliceHdr->long_term_frame_idx[ii]);
+ break;
+ case 4:
+ MemMgrCtrlOp4(avcHandle, video, dpb, sliceHdr->max_long_term_frame_idx_plus1[ii]);
+ break;
+ case 5:
+ MemMgrCtrlOp5(avcHandle, video, dpb);
+ video->currFS->FrameNum = 0; //
+ video->currFS->PicOrderCnt = 0;
+ break;
+ case 6:
+ MemMgrCtrlOp6(avcHandle, video, dpb, sliceHdr->long_term_frame_idx[ii]);
+ break;
+ }
+ ii++;
+ }
+
+ if (ii == MAX_DEC_REF_PIC_MARKING)
+ {
+ return AVC_FAIL; /* exceed the limit */
+ }
+
+ return AVC_SUCCESS;
+}
+
+
+/* see subclause 8.2.5.4.1, mark short-term picture as "unused for reference" */
+void MemMgrCtrlOp1(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, int difference_of_pic_nums_minus1)
+{
+ int picNumX, ii;
+
+ picNumX = video->CurrPicNum - (difference_of_pic_nums_minus1 + 1);
+
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii]->IsReference == 3 && dpb->fs[ii]->IsLongTerm == 0)
+ {
+ if (dpb->fs[ii]->frame.PicNum == picNumX)
+ {
+ unmark_for_reference(avcHandle, dpb, ii);
+ return ;
+ }
+ }
+ }
+
+ return ;
+}
+
+/* see subclause 8.2.5.4.2 mark long-term picture as "unused for reference" */
+void MemMgrCtrlOp2(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, int long_term_pic_num)
+{
+ int ii;
+
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii]->IsLongTerm == 3)
+ {
+ if (dpb->fs[ii]->frame.LongTermPicNum == long_term_pic_num)
+ {
+ unmark_for_reference(avcHandle, dpb, ii);
+ }
+ }
+ }
+}
+
+/* see subclause 8.2.5.4.3 assign LongTermFrameIdx to a short-term ref picture */
+void MemMgrCtrlOp3(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint difference_of_pic_nums_minus1,
+ uint long_term_frame_idx)
+{
+ int picNumX, ii;
+
+ picNumX = video->CurrPicNum - (difference_of_pic_nums_minus1 + 1);
+
+ /* look for fs[i] with long_term_frame_idx */
+
+ unmark_long_term_frame_for_reference_by_frame_idx(avcHandle, dpb, long_term_frame_idx);
+
+
+ /* now mark the picture with picNumX to long term frame idx */
+
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii]->IsReference == 3)
+ {
+ if ((dpb->fs[ii]->frame.isLongTerm == FALSE) && (dpb->fs[ii]->frame.PicNum == picNumX))
+ {
+ dpb->fs[ii]->LongTermFrameIdx = long_term_frame_idx;
+ dpb->fs[ii]->frame.LongTermPicNum = long_term_frame_idx;
+
+ dpb->fs[ii]->frame.isLongTerm = TRUE;
+
+ dpb->fs[ii]->IsLongTerm = 3;
+ return;
+ }
+ }
+ }
+
+}
+
+/* see subclause 8.2.5.4.4, MaxLongTermFrameIdx */
+void MemMgrCtrlOp4(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint max_long_term_frame_idx_plus1)
+{
+ int ii;
+
+ video->MaxLongTermFrameIdx = max_long_term_frame_idx_plus1 - 1;
+
+ /* then mark long term frame with exceeding LongTermFrameIdx to unused for reference. */
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+ if (dpb->fs[ii]->IsLongTerm && dpb->fs[ii] != video->currFS)
+ {
+ if (dpb->fs[ii]->LongTermFrameIdx > video->MaxLongTermFrameIdx)
+ {
+ unmark_for_reference(avcHandle, dpb, ii);
+ }
+ }
+ }
+}
+
+/* see subclause 8.2.5.4.5 mark all reference picture as "unused for reference" and setting
+MaxLongTermFrameIdx to "no long-term frame indices" */
+void MemMgrCtrlOp5(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb)
+{
+ int ii;
+
+ video->MaxLongTermFrameIdx = -1;
+ for (ii = 0; ii < dpb->num_fs; ii++) /* including the current frame ??????*/
+ {
+ if (dpb->fs[ii] != video->currFS) // MC_FIX
+ {
+ unmark_for_reference(avcHandle, dpb, ii);
+ }
+ }
+
+ video->mem_mgr_ctrl_eq_5 = TRUE;
+}
+
+/* see subclause 8.2.5.4.6 assing long-term frame index to the current picture */
+void MemMgrCtrlOp6(AVCHandle *avcHandle, AVCCommonObj *video, AVCDecPicBuffer *dpb, uint long_term_frame_idx)
+{
+
+ unmark_long_term_frame_for_reference_by_frame_idx(avcHandle, dpb, long_term_frame_idx);
+ video->currFS->IsLongTerm = 3;
+ video->currFS->IsReference = 3;
+
+ video->currPic->isLongTerm = TRUE;
+ video->currPic->isReference = TRUE;
+ video->currFS->LongTermFrameIdx = long_term_frame_idx;
+}
+
+
+void unmark_for_reference(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, uint idx)
+{
+
+ AVCFrameStore *fs = dpb->fs[idx];
+ fs->frame.isReference = FALSE;
+ fs->frame.isLongTerm = FALSE;
+
+ fs->IsLongTerm = 0;
+ fs->IsReference = 0;
+ fs->IsOutputted |= 0x02;
+#ifdef PV_MEMORY_POOL
+ if (fs->IsOutputted == 3)
+ {
+ avcHandle->CBAVC_FrameUnbind(avcHandle->userData, idx);
+ }
+#endif
+ return ;
+}
+
+void unmark_long_term_frame_for_reference_by_frame_idx(AVCHandle *avcHandle, AVCDecPicBuffer *dpb, uint long_term_frame_idx)
+{
+ int ii;
+ for (ii = 0; ii < dpb->num_fs; ii++)
+ {
+
+ if (dpb->fs[ii]->IsLongTerm && (dpb->fs[ii]->LongTermFrameIdx == (int)long_term_frame_idx))
+ {
+ unmark_for_reference(avcHandle, dpb, ii);
+ }
+
+ }
+}
+
+
diff --git a/media/libstagefright/codecs/avc/common/src/fmo.cpp b/media/libstagefright/codecs/avc/common/src/fmo.cpp
new file mode 100644
index 0000000..d66eba3
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/src/fmo.cpp
@@ -0,0 +1,249 @@
+/* ------------------------------------------------------------------
+ * 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 <string.h>
+
+#include "avclib_common.h"
+
+/* see subclause 8.2.2 Decoding process for macroblock to slice group map */
+OSCL_EXPORT_REF AVCStatus FMOInit(AVCCommonObj *video)
+{
+ AVCPicParamSet *currPPS = video->currPicParams;
+ int *MbToSliceGroupMap = video->MbToSliceGroupMap;
+ int PicSizeInMapUnits = video->PicSizeInMapUnits;
+ int PicWidthInMbs = video->PicWidthInMbs;
+
+ if (currPPS->num_slice_groups_minus1 == 0)
+ {
+ memset(video->MbToSliceGroupMap, 0, video->PicSizeInMapUnits*sizeof(uint));
+ }
+ else
+ {
+ switch (currPPS->slice_group_map_type)
+ {
+ case 0:
+ FmoGenerateType0MapUnitMap(MbToSliceGroupMap, currPPS->run_length_minus1, currPPS->num_slice_groups_minus1, PicSizeInMapUnits);
+ break;
+ case 1:
+ FmoGenerateType1MapUnitMap(MbToSliceGroupMap, PicWidthInMbs, currPPS->num_slice_groups_minus1, PicSizeInMapUnits);
+ break;
+ case 2:
+ FmoGenerateType2MapUnitMap(currPPS, MbToSliceGroupMap, PicWidthInMbs, currPPS->num_slice_groups_minus1, PicSizeInMapUnits);
+ break;
+ case 3:
+ FmoGenerateType3MapUnitMap(video, currPPS, MbToSliceGroupMap, PicWidthInMbs);
+ break;
+ case 4:
+ FmoGenerateType4MapUnitMap(MbToSliceGroupMap, video->MapUnitsInSliceGroup0, currPPS->slice_group_change_direction_flag, PicSizeInMapUnits);
+ break;
+ case 5:
+ FmoGenerateType5MapUnitMap(MbToSliceGroupMap, video, currPPS->slice_group_change_direction_flag, PicSizeInMapUnits);
+ break;
+ case 6:
+ FmoGenerateType6MapUnitMap(MbToSliceGroupMap, (int*)currPPS->slice_group_id, PicSizeInMapUnits);
+ break;
+ default:
+ return AVC_FAIL; /* out of range, shouldn't come this far */
+ }
+ }
+
+ return AVC_SUCCESS;
+}
+
+/* see subclause 8.2.2.1 interleaved slice group map type*/
+void FmoGenerateType0MapUnitMap(int *mapUnitToSliceGroupMap, uint *run_length_minus1, uint num_slice_groups_minus1, uint PicSizeInMapUnits)
+{
+ uint iGroup, j;
+ uint i = 0;
+ do
+ {
+ for (iGroup = 0;
+ (iGroup <= num_slice_groups_minus1) && (i < PicSizeInMapUnits);
+ i += run_length_minus1[iGroup++] + 1)
+ {
+ for (j = 0; j <= run_length_minus1[ iGroup ] && i + j < PicSizeInMapUnits; j++)
+ mapUnitToSliceGroupMap[i+j] = iGroup;
+ }
+ }
+ while (i < PicSizeInMapUnits);
+}
+
+/* see subclause 8.2.2.2 dispersed slice group map type*/
+void FmoGenerateType1MapUnitMap(int *mapUnitToSliceGroupMap, int PicWidthInMbs, uint num_slice_groups_minus1, uint PicSizeInMapUnits)
+{
+ uint i;
+ for (i = 0; i < PicSizeInMapUnits; i++)
+ {
+ mapUnitToSliceGroupMap[i] = ((i % PicWidthInMbs) + (((i / PicWidthInMbs) * (num_slice_groups_minus1 + 1)) / 2))
+ % (num_slice_groups_minus1 + 1);
+ }
+}
+
+/* see subclause 8.2.2.3 foreground with left-over slice group map type */
+void FmoGenerateType2MapUnitMap(AVCPicParamSet *pps, int *mapUnitToSliceGroupMap, int PicWidthInMbs,
+ uint num_slice_groups_minus1, uint PicSizeInMapUnits)
+{
+ int iGroup;
+ uint i, x, y;
+ uint yTopLeft, xTopLeft, yBottomRight, xBottomRight;
+
+ for (i = 0; i < PicSizeInMapUnits; i++)
+ {
+ mapUnitToSliceGroupMap[ i ] = num_slice_groups_minus1;
+ }
+
+ for (iGroup = num_slice_groups_minus1 - 1 ; iGroup >= 0; iGroup--)
+ {
+ yTopLeft = pps->top_left[ iGroup ] / PicWidthInMbs;
+ xTopLeft = pps->top_left[ iGroup ] % PicWidthInMbs;
+ yBottomRight = pps->bottom_right[ iGroup ] / PicWidthInMbs;
+ xBottomRight = pps->bottom_right[ iGroup ] % PicWidthInMbs;
+ for (y = yTopLeft; y <= yBottomRight; y++)
+ {
+ for (x = xTopLeft; x <= xBottomRight; x++)
+ {
+ mapUnitToSliceGroupMap[ y * PicWidthInMbs + x ] = iGroup;
+ }
+ }
+ }
+}
+
+
+/* see subclause 8.2.2.4 box-out slice group map type */
+/* follow the text rather than the JM, it's quite different. */
+void FmoGenerateType3MapUnitMap(AVCCommonObj *video, AVCPicParamSet* pps, int *mapUnitToSliceGroupMap,
+ int PicWidthInMbs)
+{
+ uint i, k;
+ int leftBound, topBound, rightBound, bottomBound;
+ int x, y, xDir, yDir;
+ int mapUnitVacant;
+ uint PicSizeInMapUnits = video->PicSizeInMapUnits;
+ uint MapUnitsInSliceGroup0 = video->MapUnitsInSliceGroup0;
+
+ for (i = 0; i < PicSizeInMapUnits; i++)
+ {
+ mapUnitToSliceGroupMap[ i ] = 1;
+ }
+
+ x = (PicWidthInMbs - pps->slice_group_change_direction_flag) / 2;
+ y = (video->PicHeightInMapUnits - pps->slice_group_change_direction_flag) / 2;
+
+ leftBound = x;
+ topBound = y;
+ rightBound = x;
+ bottomBound = y;
+
+ xDir = pps->slice_group_change_direction_flag - 1;
+ yDir = pps->slice_group_change_direction_flag;
+
+ for (k = 0; k < MapUnitsInSliceGroup0; k += mapUnitVacant)
+ {
+ mapUnitVacant = (mapUnitToSliceGroupMap[ y * PicWidthInMbs + x ] == 1);
+ if (mapUnitVacant)
+ {
+ mapUnitToSliceGroupMap[ y * PicWidthInMbs + x ] = 0;
+ }
+
+ if (xDir == -1 && x == leftBound)
+ {
+ leftBound = AVC_MAX(leftBound - 1, 0);
+ x = leftBound;
+ xDir = 0;
+ yDir = 2 * pps->slice_group_change_direction_flag - 1;
+ }
+ else if (xDir == 1 && x == rightBound)
+ {
+ rightBound = AVC_MIN(rightBound + 1, (int)PicWidthInMbs - 1);
+ x = rightBound;
+ xDir = 0;
+ yDir = 1 - 2 * pps->slice_group_change_direction_flag;
+ }
+ else if (yDir == -1 && y == topBound)
+ {
+ topBound = AVC_MAX(topBound - 1, 0);
+ y = topBound;
+ xDir = 1 - 2 * pps->slice_group_change_direction_flag;
+ yDir = 0;
+ }
+ else if (yDir == 1 && y == bottomBound)
+ {
+ bottomBound = AVC_MIN(bottomBound + 1, (int)video->PicHeightInMapUnits - 1);
+ y = bottomBound;
+ xDir = 2 * pps->slice_group_change_direction_flag - 1;
+ yDir = 0;
+ }
+ else
+ {
+ x = x + xDir;
+ y = y + yDir;
+ }
+ }
+}
+
+/* see subclause 8.2.2.5 raster scan slice group map types */
+void FmoGenerateType4MapUnitMap(int *mapUnitToSliceGroupMap, int MapUnitsInSliceGroup0, int slice_group_change_direction_flag, uint PicSizeInMapUnits)
+{
+ uint sizeOfUpperLeftGroup = slice_group_change_direction_flag ? (PicSizeInMapUnits - MapUnitsInSliceGroup0) : MapUnitsInSliceGroup0;
+
+ uint i;
+
+ for (i = 0; i < PicSizeInMapUnits; i++)
+ if (i < sizeOfUpperLeftGroup)
+ mapUnitToSliceGroupMap[ i ] = 1 - slice_group_change_direction_flag;
+ else
+ mapUnitToSliceGroupMap[ i ] = slice_group_change_direction_flag;
+
+}
+
+/* see subclause 8.2.2.6, wipe slice group map type. */
+void FmoGenerateType5MapUnitMap(int *mapUnitToSliceGroupMap, AVCCommonObj *video,
+ int slice_group_change_direction_flag, uint PicSizeInMapUnits)
+{
+ int PicWidthInMbs = video->PicWidthInMbs;
+ int PicHeightInMapUnits = video->PicHeightInMapUnits;
+ int MapUnitsInSliceGroup0 = video->MapUnitsInSliceGroup0;
+ int sizeOfUpperLeftGroup = slice_group_change_direction_flag ? (PicSizeInMapUnits - MapUnitsInSliceGroup0) : MapUnitsInSliceGroup0;
+ int i, j, k = 0;
+
+ for (j = 0; j < PicWidthInMbs; j++)
+ {
+ for (i = 0; i < PicHeightInMapUnits; i++)
+ {
+ if (k++ < sizeOfUpperLeftGroup)
+ {
+ mapUnitToSliceGroupMap[ i * PicWidthInMbs + j ] = 1 - slice_group_change_direction_flag;
+ }
+ else
+ {
+ mapUnitToSliceGroupMap[ i * PicWidthInMbs + j ] = slice_group_change_direction_flag;
+ }
+ }
+ }
+}
+
+/* see subclause 8.2.2.7, explicit slice group map */
+void FmoGenerateType6MapUnitMap(int *mapUnitToSliceGroupMap, int *slice_group_id, uint PicSizeInMapUnits)
+{
+ uint i;
+ for (i = 0; i < PicSizeInMapUnits; i++)
+ {
+ mapUnitToSliceGroupMap[i] = slice_group_id[i];
+ }
+}
+
+
diff --git a/media/libstagefright/codecs/avc/common/src/mb_access.cpp b/media/libstagefright/codecs/avc/common/src/mb_access.cpp
new file mode 100644
index 0000000..414b8f7
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/src/mb_access.cpp
@@ -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.
+ * -------------------------------------------------------------------
+ */
+#include <string.h>
+
+#include "avclib_common.h"
+
+OSCL_EXPORT_REF void InitNeighborAvailability(AVCCommonObj *video, int mbNum)
+{
+ int PicWidthInMbs = video->PicWidthInMbs;
+
+ // do frame-only and postpone intraAvail calculattion
+ video->mbAddrA = mbNum - 1;
+ video->mbAddrB = mbNum - PicWidthInMbs;
+ video->mbAddrC = mbNum - PicWidthInMbs + 1;
+ video->mbAddrD = mbNum - PicWidthInMbs - 1;
+
+ video->mbAvailA = video->mbAvailB = video->mbAvailC = video->mbAvailD = 0;
+ if (video->mb_x)
+ {
+ video->mbAvailA = (video->mblock[video->mbAddrA].slice_id == video->currMB->slice_id);
+ if (video->mb_y)
+ {
+ video->mbAvailD = (video->mblock[video->mbAddrD].slice_id == video->currMB->slice_id);
+ }
+ }
+
+ if (video->mb_y)
+ {
+ video->mbAvailB = (video->mblock[video->mbAddrB].slice_id == video->currMB->slice_id);
+ if (video->mb_x < (PicWidthInMbs - 1))
+ {
+ video->mbAvailC = (video->mblock[video->mbAddrC].slice_id == video->currMB->slice_id);
+ }
+ }
+ return ;
+}
+
+bool mb_is_available(AVCMacroblock *mblock, uint PicSizeInMbs, int mbAddr, int currMbAddr)
+{
+ if (mbAddr < 0 || mbAddr >= (int)PicSizeInMbs)
+ {
+ return FALSE;
+ }
+
+ if (mblock[mbAddr].slice_id != mblock[currMbAddr].slice_id)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+OSCL_EXPORT_REF int predict_nnz(AVCCommonObj *video, int i, int j)
+{
+ int pred_nnz = 0;
+ int cnt = 1;
+ AVCMacroblock *tempMB;
+
+ /* left block */
+ /*getLuma4x4Neighbour(video, mb_nr, i, j, -1, 0, &pix);
+ leftMB = video->mblock + pix.mb_addr; */
+ /* replace the above with below (won't work for field decoding), 1/19/04 */
+
+ if (i)
+ {
+ pred_nnz = video->currMB->nz_coeff[(j<<2)+i-1];
+ }
+ else
+ {
+ if (video->mbAvailA)
+ {
+ tempMB = video->mblock + video->mbAddrA;
+ pred_nnz = tempMB->nz_coeff[(j<<2)+3];
+ }
+ else
+ {
+ cnt = 0;
+ }
+ }
+
+
+ /* top block */
+ /*getLuma4x4Neighbour(video, mb_nr, i, j, 0, -1, &pix);
+ topMB = video->mblock + pix.mb_addr;*/
+ /* replace the above with below (won't work for field decoding), 1/19/04 */
+
+ if (j)
+ {
+ pred_nnz += video->currMB->nz_coeff[((j-1)<<2)+i];
+ cnt++;
+ }
+ else
+ {
+ if (video->mbAvailB)
+ {
+ tempMB = video->mblock + video->mbAddrB;
+ pred_nnz += tempMB->nz_coeff[12+i];
+ cnt++;
+ }
+ }
+
+
+ if (cnt == 2)
+ {
+ pred_nnz = (pred_nnz + 1) >> 1;
+ }
+
+ return pred_nnz;
+
+}
+
+
+OSCL_EXPORT_REF int predict_nnz_chroma(AVCCommonObj *video, int i, int j)
+{
+ int pred_nnz = 0;
+ int cnt = 1;
+ AVCMacroblock *tempMB;
+
+ /* left block */
+ /*getChroma4x4Neighbour(video, mb_nr, i%2, j-4, -1, 0, &pix);
+ leftMB = video->mblock + pix.mb_addr;*/
+ /* replace the above with below (won't work for field decoding), 1/19/04 */
+ if (i&1)
+ {
+ pred_nnz = video->currMB->nz_coeff[(j<<2)+i-1];
+
+ }
+ else
+ {
+ if (video->mbAvailA)
+ {
+ tempMB = video->mblock + video->mbAddrA;
+ pred_nnz = tempMB->nz_coeff[(j<<2)+i+1];
+ }
+ else
+ {
+ cnt = 0;
+ }
+ }
+
+
+ /* top block */
+ /*getChroma4x4Neighbour(video, mb_nr, i%2, j-4, 0, -1, &pix);
+ topMB = video->mblock + pix.mb_addr;*/
+ /* replace the above with below (won't work for field decoding), 1/19/04 */
+
+ if (j&1)
+ {
+ pred_nnz += video->currMB->nz_coeff[((j-1)<<2)+i];
+ cnt++;
+ }
+ else
+ {
+ if (video->mbAvailB)
+ {
+ tempMB = video->mblock + video->mbAddrB;
+ pred_nnz += tempMB->nz_coeff[20+i];
+ cnt++;
+ }
+
+ }
+
+ if (cnt == 2)
+ {
+ pred_nnz = (pred_nnz + 1) >> 1;
+ }
+
+ return pred_nnz;
+}
+
+OSCL_EXPORT_REF void GetMotionVectorPredictor(AVCCommonObj *video, int encFlag)
+{
+ AVCMacroblock *currMB = video->currMB;
+ AVCMacroblock *MB_A, *MB_B, *MB_C, *MB_D;
+ int block_x, block_y, block_x_1, block_y_1, new_block_x;
+ int mbPartIdx, subMbPartIdx, offset_indx;
+ int16 *mv, pmv_x, pmv_y;
+ int nmSubMbHeight, nmSubMbWidth, mbPartIdx_X, mbPartIdx_Y;
+ int avail_a, avail_b, avail_c;
+ const static uint32 C = 0x5750;
+ int i, j, offset_MbPart_indx, refIdxLXA, refIdxLXB, refIdxLXC = 0, curr_ref_idx;
+ int pmv_A_x, pmv_B_x, pmv_C_x = 0, pmv_A_y, pmv_B_y, pmv_C_y = 0;
+
+ /* we have to take care of Intra/skip blocks somewhere, i.e. set MV to 0 and set ref to -1! */
+ /* we have to populate refIdx as well */
+
+
+ MB_A = &video->mblock[video->mbAddrA];
+ MB_B = &video->mblock[video->mbAddrB];
+
+
+ if (currMB->mbMode == AVC_SKIP /* && !encFlag */) /* only for decoder */
+ {
+ currMB->ref_idx_L0[0] = currMB->ref_idx_L0[1] = currMB->ref_idx_L0[2] = currMB->ref_idx_L0[3] = 0;
+ if (video->mbAvailA && video->mbAvailB)
+ {
+ 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))
+ {
+ memset(currMB->mvL0, 0, sizeof(int32)*16);
+ return;
+ }
+ }
+ else
+ {
+ memset(currMB->mvL0, 0, sizeof(int32)*16);
+ return;
+ }
+ video->mvd_l0[0][0][0] = 0;
+ video->mvd_l0[0][0][1] = 0;
+ }
+
+ MB_C = &video->mblock[video->mbAddrC];
+ MB_D = &video->mblock[video->mbAddrD];
+
+ offset_MbPart_indx = 0;
+ for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+ {
+ offset_indx = 0;
+ nmSubMbHeight = currMB->SubMbPartHeight[mbPartIdx] >> 2;
+ nmSubMbWidth = currMB->SubMbPartWidth[mbPartIdx] >> 2;
+ mbPartIdx_X = ((mbPartIdx + offset_MbPart_indx) & 1) << 1;
+ mbPartIdx_Y = (mbPartIdx + offset_MbPart_indx) & 2;
+
+ for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
+ {
+ block_x = mbPartIdx_X + ((subMbPartIdx + offset_indx) & 1);
+ block_y = mbPartIdx_Y + (((subMbPartIdx + offset_indx) >> 1) & 1);
+
+ block_x_1 = block_x - 1;
+ block_y_1 = block_y - 1;
+ refIdxLXA = refIdxLXB = refIdxLXC = -1;
+ pmv_A_x = pmv_A_y = pmv_B_x = pmv_B_y = pmv_C_x = pmv_C_y = 0;
+
+ if (block_x)
+ {
+ avail_a = 1;
+ refIdxLXA = currMB->ref_idx_L0[(block_y & 2) + (block_x_1 >> 1)];
+ mv = (int16*)(currMB->mvL0 + (block_y << 2) + block_x_1);
+ pmv_A_x = *mv++;
+ pmv_A_y = *mv;
+ }
+ else
+ {
+ avail_a = video->mbAvailA;
+ if (avail_a)
+ {
+ refIdxLXA = MB_A->ref_idx_L0[(block_y & 2) + 1];
+ mv = (int16*)(MB_A->mvL0 + (block_y << 2) + 3);
+ pmv_A_x = *mv++;
+ pmv_A_y = *mv;
+ }
+ }
+
+ if (block_y)
+ {
+ avail_b = 1;
+ refIdxLXB = currMB->ref_idx_L0[(block_y_1 & 2) + (block_x >> 1)];
+ mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + block_x);
+ pmv_B_x = *mv++;
+ pmv_B_y = *mv;
+ }
+
+ else
+ {
+ avail_b = video->mbAvailB;
+ if (avail_b)
+ {
+ refIdxLXB = MB_B->ref_idx_L0[2 + (block_x >> 1)];
+ mv = (int16*)(MB_B->mvL0 + 12 + block_x);
+ pmv_B_x = *mv++;
+ pmv_B_y = *mv;
+ }
+ }
+
+ new_block_x = block_x + (currMB->SubMbPartWidth[mbPartIdx] >> 2) - 1;
+ avail_c = (C >> ((block_y << 2) + new_block_x)) & 0x1;
+
+ if (avail_c)
+ {
+ /* it guaranteed that block_y > 0 && new_block_x<3 ) */
+ refIdxLXC = currMB->ref_idx_L0[(block_y_1 & 2) + ((new_block_x+1) >> 1)];
+ mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + (new_block_x + 1));
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ else
+ {
+ if (block_y == 0 && new_block_x < 3)
+ {
+ avail_c = video->mbAvailB;
+ if (avail_c)
+ {
+ refIdxLXC = MB_B->ref_idx_L0[2 + ((new_block_x+1)>>1)];
+ mv = (int16*)(MB_B->mvL0 + 12 + (new_block_x + 1));
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+ else if (block_y == 0 && new_block_x == 3)
+ {
+ avail_c = video->mbAvailC;
+ if (avail_c)
+ {
+ refIdxLXC = MB_C->ref_idx_L0[2];
+ mv = (int16*)(MB_C->mvL0 + 12);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+
+ if (avail_c == 0)
+ { /* check D */
+ if (block_x && block_y)
+ {
+ avail_c = 1;
+ refIdxLXC = currMB->ref_idx_L0[(block_y_1 & 2) + (block_x_1 >> 1)];
+ mv = (int16*)(currMB->mvL0 + (block_y_1 << 2) + block_x_1);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ else if (block_y)
+ {
+ avail_c = video->mbAvailA;
+ if (avail_c)
+ {
+ refIdxLXC = MB_A->ref_idx_L0[(block_y_1 & 2) + 1];
+ mv = (int16*)(MB_A->mvL0 + (block_y_1 << 2) + 3);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+ else if (block_x)
+ {
+ avail_c = video->mbAvailB;
+ if (avail_c)
+ {
+ refIdxLXC = MB_B->ref_idx_L0[2 + (block_x_1 >> 1)];
+ mv = (int16*)(MB_B->mvL0 + 12 + block_x_1);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+ else
+ {
+ avail_c = video->mbAvailD;
+ if (avail_c)
+ {
+ refIdxLXC = MB_D->ref_idx_L0[3];
+ mv = (int16*)(MB_D->mvL0 + 15);
+ pmv_C_x = *mv++;
+ pmv_C_y = *mv;
+ }
+ }
+ }
+ }
+
+ offset_indx = currMB->SubMbPartWidth[mbPartIdx] >> 3;
+
+ curr_ref_idx = currMB->ref_idx_L0[(block_y & 2) + (block_x >> 1)];
+
+ if (avail_a && !(avail_b || avail_c))
+ {
+ pmv_x = pmv_A_x;
+ pmv_y = pmv_A_y;
+ }
+ else if (((curr_ref_idx == refIdxLXA) + (curr_ref_idx == refIdxLXB) + (curr_ref_idx == refIdxLXC)) == 1)
+ {
+ if (curr_ref_idx == refIdxLXA)
+ {
+ pmv_x = pmv_A_x;
+ pmv_y = pmv_A_y;
+ }
+ else if (curr_ref_idx == refIdxLXB)
+ {
+ pmv_x = pmv_B_x;
+ pmv_y = pmv_B_y;
+ }
+ else
+ {
+ pmv_x = pmv_C_x;
+ pmv_y = pmv_C_y;
+ }
+ }
+ else
+ {
+ pmv_x = AVC_MEDIAN(pmv_A_x, pmv_B_x, pmv_C_x);
+ pmv_y = AVC_MEDIAN(pmv_A_y, pmv_B_y, pmv_C_y);
+ }
+
+ /* overwrite if special case */
+ if (currMB->NumMbPart == 2)
+ {
+ if (currMB->MbPartWidth == 16)
+ {
+ if (mbPartIdx == 0)
+ {
+ if (refIdxLXB == curr_ref_idx)
+ {
+ pmv_x = pmv_B_x;
+ pmv_y = pmv_B_y;
+ }
+ }
+ else if (refIdxLXA == curr_ref_idx)
+ {
+ pmv_x = pmv_A_x;
+ pmv_y = pmv_A_y;
+ }
+ }
+ else
+ {
+ if (mbPartIdx == 0)
+ {
+ if (refIdxLXA == curr_ref_idx)
+ {
+ pmv_x = pmv_A_x;
+ pmv_y = pmv_A_y;
+ }
+ }
+ else if (refIdxLXC == curr_ref_idx)
+ {
+ pmv_x = pmv_C_x;
+ pmv_y = pmv_C_y;
+ }
+ }
+ }
+
+ mv = (int16*)(currMB->mvL0 + block_x + (block_y << 2));
+
+ if (encFlag) /* calculate residual MV video->mvd_l0 */
+ {
+ video->mvd_l0[mbPartIdx][subMbPartIdx][0] = *mv++ - pmv_x;
+ video->mvd_l0[mbPartIdx][subMbPartIdx][1] = *mv++ - pmv_y;
+ }
+ else /* calculate original MV currMB->mvL0 */
+ {
+ pmv_x += video->mvd_l0[mbPartIdx][subMbPartIdx][0];
+ pmv_y += video->mvd_l0[mbPartIdx][subMbPartIdx][1];
+
+ for (i = 0; i < nmSubMbHeight; i++)
+ {
+ for (j = 0; j < nmSubMbWidth; j++)
+ {
+ *mv++ = pmv_x;
+ *mv++ = pmv_y;
+ }
+ mv += (8 - (j << 1));
+ }
+ }
+ }
+ offset_MbPart_indx = currMB->MbPartWidth >> 4;
+
+ }
+}
+
+
diff --git a/media/libstagefright/codecs/avc/common/src/reflist.cpp b/media/libstagefright/codecs/avc/common/src/reflist.cpp
new file mode 100644
index 0000000..4ddc7dd
--- /dev/null
+++ b/media/libstagefright/codecs/avc/common/src/reflist.cpp
@@ -0,0 +1,596 @@
+/* ------------------------------------------------------------------
+ * 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 "avclib_common.h"
+
+/** see subclause 8.2.4 Decoding process for reference picture lists construction. */
+OSCL_EXPORT_REF void RefListInit(AVCCommonObj *video)
+{
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int slice_type = video->slice_type;
+ int i, list0idx;
+
+ AVCPictureData *tmp_s;
+
+ list0idx = 0;
+
+ if (slice_type == AVC_I_SLICE)
+ {
+ video->refList0Size = 0;
+ video->refList1Size = 0;
+
+ /* we still have to calculate FrameNumWrap to make sure that all I-slice clip
+ can perform sliding_window_operation properly. */
+
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if ((dpb->fs[i]->IsReference == 3) && (!dpb->fs[i]->IsLongTerm))
+ {
+ /* subclause 8.2.4.1 Decoding process for picture numbers. */
+ if (dpb->fs[i]->FrameNum > (int)sliceHdr->frame_num)
+ {
+ dpb->fs[i]->FrameNumWrap = dpb->fs[i]->FrameNum - video->MaxFrameNum;
+ }
+ else
+ {
+ dpb->fs[i]->FrameNumWrap = dpb->fs[i]->FrameNum;
+ }
+ dpb->fs[i]->frame.PicNum = dpb->fs[i]->FrameNumWrap;
+ }
+ }
+
+
+ return ;
+ }
+ if (slice_type == AVC_P_SLICE)
+ {
+ /* Calculate FrameNumWrap and PicNum */
+
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if ((dpb->fs[i]->IsReference == 3) && (!dpb->fs[i]->IsLongTerm))
+ {
+ /* subclause 8.2.4.1 Decoding process for picture numbers. */
+ if (dpb->fs[i]->FrameNum > (int)sliceHdr->frame_num)
+ {
+ dpb->fs[i]->FrameNumWrap = dpb->fs[i]->FrameNum - video->MaxFrameNum;
+ }
+ else
+ {
+ dpb->fs[i]->FrameNumWrap = dpb->fs[i]->FrameNum;
+ }
+ dpb->fs[i]->frame.PicNum = dpb->fs[i]->FrameNumWrap;
+ video->RefPicList0[list0idx++] = &(dpb->fs[i]->frame);
+ }
+ }
+
+ if (list0idx == 0)
+ {
+ dpb->fs[0]->IsReference = 3;
+ video->RefPicList0[0] = &(dpb->fs[0]->frame);
+ list0idx = 1;
+ }
+ /* order list 0 by PicNum from max to min, see subclause 8.2.4.2.1 */
+ SortPicByPicNum(video->RefPicList0, list0idx);
+ video->refList0Size = list0idx;
+
+ /* long term handling */
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if (dpb->fs[i]->IsLongTerm == 3)
+ {
+ /* subclause 8.2.4.1 Decoding process for picture numbers. */
+ dpb->fs[i]->frame.LongTermPicNum = dpb->fs[i]->LongTermFrameIdx;
+ video->RefPicList0[list0idx++] = &(dpb->fs[i]->frame);
+ }
+ }
+
+ /* order PicNum from min to max, see subclause 8.2.4.2.1 */
+ SortPicByPicNumLongTerm(&(video->RefPicList0[video->refList0Size]), list0idx - video->refList0Size);
+ video->refList0Size = list0idx;
+
+
+ video->refList1Size = 0;
+ }
+
+
+ if ((video->refList0Size == video->refList1Size) && (video->refList0Size > 1))
+ {
+ /* check if lists are identical, if yes swap first two elements of listX[1] */
+ /* last paragraph of subclause 8.2.4.2.4 */
+
+ for (i = 0; i < video->refList0Size; i++)
+ {
+ if (video->RefPicList0[i] != video->RefPicList1[i])
+ {
+ break;
+ }
+ }
+ if (i == video->refList0Size)
+ {
+ tmp_s = video->RefPicList1[0];
+ video->RefPicList1[0] = video->RefPicList1[1];
+ video->RefPicList1[1] = tmp_s;
+ }
+ }
+
+ /* set max size */
+ video->refList0Size = AVC_MIN(video->refList0Size, (int)video->sliceHdr->num_ref_idx_l0_active_minus1 + 1);
+ video->refList1Size = AVC_MIN(video->refList1Size, (int)video->sliceHdr->num_ref_idx_l1_active_minus1 + 1);
+
+ return ;
+}
+/* see subclause 8.2.4.3 */
+OSCL_EXPORT_REF AVCStatus ReOrderList(AVCCommonObj *video)
+{
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCStatus status = AVC_SUCCESS;
+ int slice_type = video->slice_type;
+
+ if (slice_type != AVC_I_SLICE)
+ {
+ if (sliceHdr->ref_pic_list_reordering_flag_l0)
+ {
+ status = ReorderRefPicList(video, 0);
+ if (status != AVC_SUCCESS)
+ return status;
+ }
+ if (video->refList0Size == 0)
+ {
+ return AVC_FAIL;
+ }
+ }
+ return status;
+}
+
+AVCStatus ReorderRefPicList(AVCCommonObj *video, int isL1)
+{
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCStatus status;
+
+ int *list_size;
+ int num_ref_idx_lX_active_minus1;
+ uint *remapping_of_pic_nums_idc;
+ int *abs_diff_pic_num_minus1;
+ int *long_term_pic_idx;
+ int i;
+ int maxPicNum, currPicNum, picNumLXNoWrap, picNumLXPred, picNumLX;
+ int refIdxLX = 0;
+ void* tmp;
+
+ if (!isL1) /* list 0 */
+ {
+ list_size = &(video->refList0Size);
+ num_ref_idx_lX_active_minus1 = sliceHdr->num_ref_idx_l0_active_minus1;
+ remapping_of_pic_nums_idc = sliceHdr->reordering_of_pic_nums_idc_l0;
+ tmp = (void*)sliceHdr->abs_diff_pic_num_minus1_l0;
+ abs_diff_pic_num_minus1 = (int*) tmp;
+ tmp = (void*)sliceHdr->long_term_pic_num_l0;
+ long_term_pic_idx = (int*) tmp;
+ }
+ else
+ {
+ list_size = &(video->refList1Size);
+ num_ref_idx_lX_active_minus1 = sliceHdr->num_ref_idx_l1_active_minus1;
+ remapping_of_pic_nums_idc = sliceHdr->reordering_of_pic_nums_idc_l1;
+ tmp = (void*) sliceHdr->abs_diff_pic_num_minus1_l1;
+ abs_diff_pic_num_minus1 = (int*) tmp;
+ tmp = (void*) sliceHdr->long_term_pic_num_l1;
+ long_term_pic_idx = (int*)tmp;
+ }
+
+ maxPicNum = video->MaxPicNum;
+ currPicNum = video->CurrPicNum;
+
+ picNumLXPred = currPicNum; /* initial value */
+
+ for (i = 0; remapping_of_pic_nums_idc[i] != 3; i++)
+ {
+ if ((remapping_of_pic_nums_idc[i] > 3) || (i >= MAX_REF_PIC_LIST_REORDERING))
+ {
+ return AVC_FAIL; /* out of range */
+ }
+ /* see subclause 8.2.4.3.1 */
+ if (remapping_of_pic_nums_idc[i] < 2)
+ {
+ if (remapping_of_pic_nums_idc[i] == 0)
+ {
+ if (picNumLXPred - (abs_diff_pic_num_minus1[i] + 1) < 0)
+ picNumLXNoWrap = picNumLXPred - (abs_diff_pic_num_minus1[i] + 1) + maxPicNum;
+ else
+ picNumLXNoWrap = picNumLXPred - (abs_diff_pic_num_minus1[i] + 1);
+ }
+ else /* (remapping_of_pic_nums_idc[i] == 1) */
+ {
+ if (picNumLXPred + (abs_diff_pic_num_minus1[i] + 1) >= maxPicNum)
+ picNumLXNoWrap = picNumLXPred + (abs_diff_pic_num_minus1[i] + 1) - maxPicNum;
+ else
+ picNumLXNoWrap = picNumLXPred + (abs_diff_pic_num_minus1[i] + 1);
+ }
+ picNumLXPred = picNumLXNoWrap; /* prediction for the next one */
+
+ if (picNumLXNoWrap > currPicNum)
+ picNumLX = picNumLXNoWrap - maxPicNum;
+ else
+ picNumLX = picNumLXNoWrap;
+
+ status = ReorderShortTerm(video, picNumLX, &refIdxLX, isL1);
+ if (status != AVC_SUCCESS)
+ {
+ return status;
+ }
+ }
+ else /* (remapping_of_pic_nums_idc[i] == 2), subclause 8.2.4.3.2 */
+ {
+ status = ReorderLongTerm(video, long_term_pic_idx[i], &refIdxLX, isL1);
+ if (status != AVC_SUCCESS)
+ {
+ return status;
+ }
+ }
+ }
+ /* that's a definition */
+ *list_size = num_ref_idx_lX_active_minus1 + 1;
+
+ return AVC_SUCCESS;
+}
+
+/* see subclause 8.2.4.3.1 */
+AVCStatus ReorderShortTerm(AVCCommonObj *video, int picNumLX, int *refIdxLX, int isL1)
+{
+ int cIdx, nIdx;
+ int num_ref_idx_lX_active_minus1;
+ AVCPictureData *picLX, **RefPicListX;
+
+ if (!isL1) /* list 0 */
+ {
+ RefPicListX = video->RefPicList0;
+ num_ref_idx_lX_active_minus1 = video->sliceHdr->num_ref_idx_l0_active_minus1;
+ }
+ else
+ {
+ RefPicListX = video->RefPicList1;
+ num_ref_idx_lX_active_minus1 = video->sliceHdr->num_ref_idx_l1_active_minus1;
+ }
+
+ picLX = GetShortTermPic(video, picNumLX);
+
+ if (picLX == NULL)
+ {
+ return AVC_FAIL;
+ }
+ /* Note RefPicListX has to access element number num_ref_idx_lX_active */
+ /* There could be access violation here. */
+ if (num_ref_idx_lX_active_minus1 + 1 >= MAX_REF_PIC_LIST)
+ {
+ return AVC_FAIL;
+ }
+
+ for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX; cIdx--)
+ {
+ RefPicListX[ cIdx ] = RefPicListX[ cIdx - 1];
+ }
+
+ RefPicListX[(*refIdxLX)++ ] = picLX;
+
+ nIdx = *refIdxLX;
+
+ for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1; cIdx++)
+ {
+ if (RefPicListX[ cIdx ])
+ {
+ if ((RefPicListX[ cIdx ]->isLongTerm) || ((int)RefPicListX[ cIdx ]->PicNum != picNumLX))
+ {
+ RefPicListX[ nIdx++ ] = RefPicListX[ cIdx ];
+ }
+ }
+ }
+ return AVC_SUCCESS;
+}
+
+/* see subclause 8.2.4.3.2 */
+AVCStatus ReorderLongTerm(AVCCommonObj *video, int LongTermPicNum, int *refIdxLX, int isL1)
+{
+ AVCPictureData **RefPicListX;
+ int num_ref_idx_lX_active_minus1;
+ int cIdx, nIdx;
+ AVCPictureData *picLX;
+
+ if (!isL1) /* list 0 */
+ {
+ RefPicListX = video->RefPicList0;
+ num_ref_idx_lX_active_minus1 = video->sliceHdr->num_ref_idx_l0_active_minus1;
+ }
+ else
+ {
+ RefPicListX = video->RefPicList1;
+ num_ref_idx_lX_active_minus1 = video->sliceHdr->num_ref_idx_l1_active_minus1;
+ }
+
+ picLX = GetLongTermPic(video, LongTermPicNum);
+ if (picLX == NULL)
+ {
+ return AVC_FAIL;
+ }
+ /* Note RefPicListX has to access element number num_ref_idx_lX_active */
+ /* There could be access violation here. */
+ if (num_ref_idx_lX_active_minus1 + 1 >= MAX_REF_PIC_LIST)
+ {
+ return AVC_FAIL;
+ }
+ for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX; cIdx--)
+ RefPicListX[ cIdx ] = RefPicListX[ cIdx - 1];
+
+ RefPicListX[(*refIdxLX)++ ] = picLX;
+
+ nIdx = *refIdxLX;
+
+ for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1; cIdx++)
+ {
+ if ((!RefPicListX[ cIdx ]->isLongTerm) || ((int)RefPicListX[ cIdx ]->LongTermPicNum != LongTermPicNum))
+ {
+ RefPicListX[ nIdx++ ] = RefPicListX[ cIdx ];
+ }
+ }
+ return AVC_SUCCESS;
+}
+
+
+AVCPictureData* GetShortTermPic(AVCCommonObj *video, int picNum)
+{
+ int i;
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+
+ if (dpb->fs[i]->IsReference == 3)
+ {
+ if ((dpb->fs[i]->frame.isLongTerm == FALSE) && (dpb->fs[i]->frame.PicNum == picNum))
+ {
+ return &(dpb->fs[i]->frame);
+ }
+ }
+
+ }
+
+ return NULL;
+}
+
+AVCPictureData* GetLongTermPic(AVCCommonObj *video, int LongtermPicNum)
+{
+ AVCDecPicBuffer *dpb = video->decPicBuf;
+ int i;
+
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+
+ if (dpb->fs[i]->IsReference == 3)
+ {
+ if ((dpb->fs[i]->frame.isLongTerm == TRUE) && (dpb->fs[i]->frame.LongTermPicNum == LongtermPicNum))
+ {
+ return &(dpb->fs[i]->frame);
+ }
+ }
+
+ }
+ return NULL;
+}
+
+int is_short_ref(AVCPictureData *s)
+{
+ return ((s->isReference) && !(s->isLongTerm));
+}
+
+int is_long_ref(AVCPictureData *s)
+{
+ return ((s->isReference) && (s->isLongTerm));
+}
+
+
+/* sort by PicNum, descending order */
+void SortPicByPicNum(AVCPictureData *data[], int num)
+{
+ int i, j;
+ AVCPictureData *temp;
+
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->PicNum > data[i]->PicNum)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+
+ return ;
+}
+
+/* sort by PicNum, ascending order */
+void SortPicByPicNumLongTerm(AVCPictureData *data[], int num)
+{
+ int i, j;
+ AVCPictureData *temp;
+
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->LongTermPicNum < data[i]->LongTermPicNum)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+
+ return ;
+}
+
+
+/* sort by FrameNumWrap, descending order */
+void SortFrameByFrameNumWrap(AVCFrameStore *data[], int num)
+{
+ int i, j;
+ AVCFrameStore *temp;
+
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->FrameNumWrap > data[i]->FrameNumWrap)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+
+ return ;
+}
+
+/* sort frames by LongTermFrameIdx, ascending order */
+void SortFrameByLTFrameIdx(AVCFrameStore *data[], int num)
+{
+ int i, j;
+ AVCFrameStore *temp;
+
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->LongTermFrameIdx < data[i]->LongTermFrameIdx)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+
+ return ;
+}
+
+/* sort PictureData by POC in descending order */
+void SortPicByPOC(AVCPictureData *data[], int num, int descending)
+{
+ int i, j;
+ AVCPictureData *temp;
+
+ if (descending)
+ {
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->PicOrderCnt > data[i]->PicOrderCnt)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->PicOrderCnt < data[i]->PicOrderCnt)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+ }
+ return ;
+}
+
+/* sort PictureData by LongTermPicNum in ascending order */
+void SortPicByLTPicNum(AVCPictureData *data[], int num)
+{
+ int i, j;
+ AVCPictureData *temp;
+
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->LongTermPicNum < data[i]->LongTermPicNum)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+
+ return ;
+}
+
+/* sort by PicOrderCnt, descending order */
+void SortFrameByPOC(AVCFrameStore *data[], int num, int descending)
+{
+ int i, j;
+ AVCFrameStore *temp;
+
+ if (descending)
+ {
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->PicOrderCnt > data[i]->PicOrderCnt)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < num - 1; i++)
+ {
+ for (j = i + 1; j < num; j++)
+ {
+ if (data[j]->PicOrderCnt < data[i]->PicOrderCnt)
+ {
+ temp = data[j];
+ data[j] = data[i];
+ data[i] = temp;
+ }
+ }
+ }
+ }
+
+ return ;
+}
+
+
diff --git a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
new file mode 100644
index 0000000..7533f07
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
@@ -0,0 +1,619 @@
+/*
+ * 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/foundation/ADebug.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+static status_t ConvertOmxAvcProfileToAvcSpecProfile(
+ int32_t omxProfile, AVCProfile* pvProfile) {
+ ALOGV("ConvertOmxAvcProfileToAvcSpecProfile: %d", omxProfile);
+ switch (omxProfile) {
+ case OMX_VIDEO_AVCProfileBaseline:
+ *pvProfile = AVC_BASELINE;
+ return OK;
+ default:
+ ALOGE("Unsupported omx profile: %d", omxProfile);
+ }
+ return BAD_VALUE;
+}
+
+static status_t ConvertOmxAvcLevelToAvcSpecLevel(
+ int32_t omxLevel, AVCLevel *pvLevel) {
+ ALOGV("ConvertOmxAvcLevelToAvcSpecLevel: %d", omxLevel);
+ AVCLevel level = AVC_LEVEL5_1;
+ switch (omxLevel) {
+ case OMX_VIDEO_AVCLevel1:
+ level = AVC_LEVEL1_B;
+ break;
+ case OMX_VIDEO_AVCLevel1b:
+ level = AVC_LEVEL1;
+ break;
+ case OMX_VIDEO_AVCLevel11:
+ level = AVC_LEVEL1_1;
+ break;
+ case OMX_VIDEO_AVCLevel12:
+ level = AVC_LEVEL1_2;
+ break;
+ case OMX_VIDEO_AVCLevel13:
+ level = AVC_LEVEL1_3;
+ break;
+ case OMX_VIDEO_AVCLevel2:
+ level = AVC_LEVEL2;
+ break;
+ case OMX_VIDEO_AVCLevel21:
+ level = AVC_LEVEL2_1;
+ break;
+ case OMX_VIDEO_AVCLevel22:
+ level = AVC_LEVEL2_2;
+ break;
+ case OMX_VIDEO_AVCLevel3:
+ level = AVC_LEVEL3;
+ break;
+ case OMX_VIDEO_AVCLevel31:
+ level = AVC_LEVEL3_1;
+ break;
+ case OMX_VIDEO_AVCLevel32:
+ level = AVC_LEVEL3_2;
+ break;
+ case OMX_VIDEO_AVCLevel4:
+ level = AVC_LEVEL4;
+ break;
+ case OMX_VIDEO_AVCLevel41:
+ level = AVC_LEVEL4_1;
+ break;
+ case OMX_VIDEO_AVCLevel42:
+ level = AVC_LEVEL4_2;
+ break;
+ case OMX_VIDEO_AVCLevel5:
+ level = AVC_LEVEL5;
+ break;
+ case OMX_VIDEO_AVCLevel51:
+ level = AVC_LEVEL5_1;
+ break;
+ default:
+ ALOGE("Unknown omx level: %d", omxLevel);
+ return BAD_VALUE;
+ }
+ *pvLevel = level;
+ return OK;
+}
+
+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),
+ mPrevTimestampUs(-1),
+ mStarted(false),
+ mInputBuffer(NULL),
+ mInputFrameData(NULL),
+ mGroup(NULL) {
+
+ ALOGI("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() {
+ ALOGV("Destruct software AVCEncoder");
+ if (mStarted) {
+ stop();
+ }
+
+ delete mEncParams;
+ delete mHandle;
+}
+
+status_t AVCEncoder::initCheck(const sp<MetaData>& meta) {
+ ALOGV("initCheck");
+ CHECK(meta->findInt32(kKeyWidth, &mVideoWidth));
+ CHECK(meta->findInt32(kKeyHeight, &mVideoHeight));
+ CHECK(meta->findInt32(kKeyFrameRate, &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) {
+ ALOGE("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) {
+ ALOGE("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);
+ }
+ ALOGV("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)) {
+ if (OK != ConvertOmxAvcProfileToAvcSpecProfile(
+ profile, &mEncParams->profile)) {
+ return BAD_VALUE;
+ }
+ }
+ if (meta->findInt32(kKeyVideoLevel, &level)) {
+ if (OK != ConvertOmxAvcLevelToAvcSpecLevel(
+ level, &mEncParams->level)) {
+ return BAD_VALUE;
+ }
+ }
+
+
+ mFormat = new MetaData;
+ mFormat->setInt32(kKeyWidth, mVideoWidth);
+ mFormat->setInt32(kKeyHeight, mVideoHeight);
+ mFormat->setInt32(kKeyBitRate, mVideoBitRate);
+ mFormat->setInt32(kKeyFrameRate, mVideoFrameRate);
+ mFormat->setInt32(kKeyColorFormat, mVideoColorFormat);
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+ mFormat->setCString(kKeyDecoderComponent, "AVCEncoder");
+ return OK;
+}
+
+status_t AVCEncoder::start(MetaData *params) {
+ ALOGV("start");
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mStarted) {
+ ALOGW("Call start() when encoder already started");
+ return OK;
+ }
+
+ AVCEnc_Status err;
+ err = PVAVCEncInitialize(mHandle, mEncParams, NULL, NULL);
+ if (err != AVCENC_SUCCESS) {
+ ALOGE("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() {
+ ALOGV("stop");
+ if (!mStarted) {
+ ALOGW("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() {
+ ALOGV("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() {
+ ALOGV("getFormat");
+ return mFormat;
+}
+
+status_t AVCEncoder::read(
+ MediaBuffer **out, const ReadOptions *options) {
+
+ CHECK(!options);
+ *out = NULL;
+
+ MediaBuffer *outputBuffer;
+ CHECK_EQ((status_t)OK, mGroup->acquire_buffer(&outputBuffer));
+ uint8_t *outPtr = (uint8_t *) outputBuffer->data();
+ uint32_t dataLength = outputBuffer->size();
+
+ if (!mSpsPpsHeaderReceived && mNumInputFrames < 0) {
+ // 4 bytes are reserved for holding the start code 0x00000001
+ // of the sequence parameter set at the beginning.
+ outPtr += 4;
+ dataLength -= 4;
+ }
+
+ int32_t type;
+ AVCEnc_Status encoderStatus = AVCENC_SUCCESS;
+
+ // Combine SPS and PPS and place them in the very first output buffer
+ // SPS and PPS are separated by start code 0x00000001
+ // Assume that we have exactly one SPS and exactly one PPS.
+ while (!mSpsPpsHeaderReceived && mNumInputFrames <= 0) {
+ 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:
+ ++mNumInputFrames;
+ memcpy((uint8_t *)outputBuffer->data(), "\x00\x00\x00\x01", 4);
+ outputBuffer->set_range(0, dataLength + 4);
+ outPtr += (dataLength + 4); // 4 bytes for next start code
+ dataLength = outputBuffer->size() -
+ (outputBuffer->range_length() + 4);
+ break;
+ case AVC_NALTYPE_PPS:
+ ++mNumInputFrames;
+ memcpy(((uint8_t *) outputBuffer->data()) +
+ outputBuffer->range_length(),
+ "\x00\x00\x00\x01", 4);
+ outputBuffer->set_range(0,
+ dataLength + outputBuffer->range_length() + 4);
+ outputBuffer->meta_data()->setInt32(kKeyIsCodecConfig, 1);
+ outputBuffer->meta_data()->setInt64(kKeyTime, 0);
+ *out = outputBuffer;
+ return OK;
+ default:
+ ALOGE("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) {
+ if (err != ERROR_END_OF_STREAM) {
+ ALOGE("Failed to read input video frame: %d", err);
+ }
+ outputBuffer->release();
+ return err;
+ }
+
+ if (mInputBuffer->size() - ((mVideoWidth * mVideoHeight * 3) >> 1) != 0) {
+ outputBuffer->release();
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ return UNKNOWN_ERROR;
+ }
+
+ int64_t timeUs;
+ CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ outputBuffer->meta_data()->setInt64(kKeyTime, timeUs);
+
+ // When the timestamp of the current sample is the same as
+ // that of the previous sample, the encoding of the sample
+ // is bypassed, and the output length is set to 0.
+ if (mNumInputFrames >= 1 && mPrevTimestampUs == timeUs) {
+ // Frame arrives too late
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ outputBuffer->set_range(0, 0);
+ *out = outputBuffer;
+ return OK;
+ }
+
+ // Don't accept out-of-order samples
+ CHECK(mPrevTimestampUs < timeUs);
+ mPrevTimestampUs = 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(NULL == PVAVCEncGetOverrunBuffer(mHandle));
+ } else if (encoderStatus == AVCENC_PICTURE_READY) {
+ CHECK(NULL == PVAVCEncGetOverrunBuffer(mHandle));
+ if (mIsIDRFrame) {
+ outputBuffer->meta_data()->setInt32(kKeyIsSyncFrame, mIsIDRFrame);
+ mIsIDRFrame = 0;
+ ALOGV("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..54cc9b1
--- /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)/frameworks/base/media/libstagefright/include \
+ $(TOP)/frameworks/native/include/media/openmax
+
+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/avc/patent_disclaimer.txt b/media/libstagefright/codecs/avc/patent_disclaimer.txt
new file mode 100644
index 0000000..b4bf11d
--- /dev/null
+++ b/media/libstagefright/codecs/avc/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/common/Android.mk b/media/libstagefright/codecs/common/Android.mk
new file mode 100644
index 0000000..af8795a
--- /dev/null
+++ b/media/libstagefright/codecs/common/Android.mk
@@ -0,0 +1,33 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+
+
+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..187f25c
--- /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..aa52bd9
--- /dev/null
+++ b/media/libstagefright/codecs/common/cmnMemory.c
@@ -0,0 +1,71 @@
+/*
+ ** 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 <stdlib.h>
+#include <string.h>
+
+//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..0308dfa
--- /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..9ecb142
--- /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..d3eb537
--- /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..d8628ee
--- /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..320a2f8
--- /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..5f659ab
--- /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 _MSC_VER
+/** 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/g711/Android.mk b/media/libstagefright/codecs/g711/Android.mk
new file mode 100644
index 0000000..2e43120
--- /dev/null
+++ b/media/libstagefright/codecs/g711/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/g711/dec/Android.mk b/media/libstagefright/codecs/g711/dec/Android.mk
new file mode 100644
index 0000000..42706a5
--- /dev/null
+++ b/media/libstagefright/codecs/g711/dec/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ SoftG711.cpp
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+ frameworks/native/include/media/openmax
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright libstagefright_omx libstagefright_foundation libutils
+
+LOCAL_MODULE := libstagefright_soft_g711dec
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
new file mode 100644
index 0000000..bcdd3c7
--- /dev/null
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SoftG711"
+#include <utils/Log.h>
+
+#include "SoftG711.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+
+namespace android {
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+SoftG711::SoftG711(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SimpleSoftOMXComponent(name, callbacks, appData, component),
+ mIsMLaw(true),
+ mNumChannels(1),
+ mSignalledError(false) {
+ if (!strcmp(name, "OMX.google.g711.alaw.decoder")) {
+ mIsMLaw = false;
+ } else {
+ CHECK(!strcmp(name, "OMX.google.g711.mlaw.decoder"));
+ }
+
+ initPorts();
+}
+
+SoftG711::~SoftG711() {
+}
+
+void SoftG711::initPorts() {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+
+ def.nPortIndex = 0;
+ def.eDir = OMX_DirInput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 8192;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 1;
+
+ def.format.audio.cMIMEType =
+ const_cast<char *>(
+ mIsMLaw
+ ? MEDIA_MIMETYPE_AUDIO_G711_MLAW
+ : MEDIA_MIMETYPE_AUDIO_G711_ALAW);
+
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingG711;
+
+ addPort(def);
+
+ def.nPortIndex = 1;
+ def.eDir = OMX_DirOutput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t);
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 2;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ addPort(def);
+}
+
+OMX_ERRORTYPE SoftG711::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamAudioPcm:
+ {
+ OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex > 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eEndian = OMX_EndianBig;
+ pcmParams->bInterleaved = OMX_TRUE;
+ pcmParams->nBitPerSample = 16;
+ pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
+ pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+ pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+
+ pcmParams->nChannels = mNumChannels;
+ pcmParams->nSamplingRate = 8000;
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftG711::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamAudioPcm:
+ {
+ OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (pcmParams->nChannels < 1 || pcmParams->nChannels > 2) {
+ return OMX_ErrorUndefined;
+ }
+
+ if(pcmParams->nPortIndex == 0) {
+ mNumChannels = pcmParams->nChannels;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamStandardComponentRole:
+ {
+ const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+ (const OMX_PARAM_COMPONENTROLETYPE *)params;
+
+ if (mIsMLaw) {
+ if (strncmp((const char *)roleParams->cRole,
+ "audio_decoder.g711mlaw",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+ } else {
+ if (strncmp((const char *)roleParams->cRole,
+ "audio_decoder.g711alaw",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ }
+}
+
+void SoftG711::onQueueFilled(OMX_U32 portIndex) {
+ if (mSignalledError) {
+ return;
+ }
+
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+
+ while (!inQueue.empty() && !outQueue.empty()) {
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+
+ outHeader->nFilledLen = 0;
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+
+ outQueue.erase(outQueue.begin());
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+ return;
+ }
+
+ if (inHeader->nFilledLen > kMaxNumSamplesPerFrame) {
+ ALOGE("input buffer too large (%ld).", inHeader->nFilledLen);
+
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ }
+
+ const uint8_t *inputptr = inHeader->pBuffer + inHeader->nOffset;
+
+ if (mIsMLaw) {
+ DecodeMLaw(
+ reinterpret_cast<int16_t *>(outHeader->pBuffer),
+ inputptr, inHeader->nFilledLen);
+ } else {
+ DecodeALaw(
+ reinterpret_cast<int16_t *>(outHeader->pBuffer),
+ inputptr, inHeader->nFilledLen);
+ }
+
+ outHeader->nTimeStamp = inHeader->nTimeStamp;
+ outHeader->nOffset = 0;
+ outHeader->nFilledLen = inHeader->nFilledLen * sizeof(int16_t);
+ outHeader->nFlags = 0;
+
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+
+ outInfo->mOwnedByUs = false;
+ outQueue.erase(outQueue.begin());
+ outInfo = NULL;
+ notifyFillBufferDone(outHeader);
+ outHeader = NULL;
+ }
+}
+
+// static
+void SoftG711::DecodeALaw(
+ int16_t *out, const uint8_t *in, size_t inSize) {
+ while (inSize-- > 0) {
+ int32_t x = *in++;
+
+ int32_t ix = x ^ 0x55;
+ ix &= 0x7f;
+
+ int32_t iexp = ix >> 4;
+ int32_t mant = ix & 0x0f;
+
+ if (iexp > 0) {
+ mant += 16;
+ }
+
+ mant = (mant << 4) + 8;
+
+ if (iexp > 1) {
+ mant = mant << (iexp - 1);
+ }
+
+ *out++ = (x > 127) ? mant : -mant;
+ }
+}
+
+// static
+void SoftG711::DecodeMLaw(
+ int16_t *out, const uint8_t *in, size_t inSize) {
+ while (inSize-- > 0) {
+ int32_t x = *in++;
+
+ int32_t mantissa = ~x;
+ int32_t exponent = (mantissa >> 4) & 7;
+ int32_t segment = exponent + 1;
+ mantissa &= 0x0f;
+
+ int32_t step = 4 << segment;
+
+ int32_t abs = (0x80l << exponent) + step * mantissa + step / 2 - 4 * 33;
+
+ *out++ = (x < 0x80) ? -abs : abs;
+ }
+}
+
+} // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+ const char *name, const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+ return new android::SoftG711(name, callbacks, appData, component);
+}
+
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.h b/media/libstagefright/codecs/g711/dec/SoftG711.h
new file mode 100644
index 0000000..bff0c68
--- /dev/null
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SOFT_G711_H_
+
+#define SOFT_G711_H_
+
+#include "SimpleSoftOMXComponent.h"
+
+namespace android {
+
+struct SoftG711 : public SimpleSoftOMXComponent {
+ SoftG711(const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ virtual ~SoftG711();
+
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual void onQueueFilled(OMX_U32 portIndex);
+
+private:
+ enum {
+ kNumBuffers = 4,
+ kMaxNumSamplesPerFrame = 16384,
+ };
+
+ bool mIsMLaw;
+ OMX_U32 mNumChannels;
+ bool mSignalledError;
+
+ void initPorts();
+
+ static void DecodeALaw(int16_t *out, const uint8_t *in, size_t inSize);
+ static void DecodeMLaw(int16_t *out, const uint8_t *in, size_t inSize);
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftG711);
+};
+
+} // namespace android
+
+#endif // SOFT_G711_H_
+
diff --git a/media/libstagefright/codecs/m4v_h263/Android.mk b/media/libstagefright/codecs/m4v_h263/Android.mk
new file mode 100644
index 0000000..2e43120
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/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/m4v_h263/dec/Android.mk b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
new file mode 100644
index 0000000..8c245d1
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/Android.mk
@@ -0,0 +1,75 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ src/adaptive_smooth_no_mmx.cpp \
+ src/bitstream.cpp \
+ src/block_idct.cpp \
+ src/cal_dc_scaler.cpp \
+ src/chvr_filter.cpp \
+ src/chv_filter.cpp \
+ src/combined_decode.cpp \
+ src/conceal.cpp \
+ src/datapart_decode.cpp \
+ src/dcac_prediction.cpp \
+ src/dec_pred_intra_dc.cpp \
+ src/deringing_chroma.cpp \
+ src/deringing_luma.cpp \
+ src/find_min_max.cpp \
+ src/get_pred_adv_b_add.cpp \
+ src/get_pred_outside.cpp \
+ src/idct.cpp \
+ src/idct_vca.cpp \
+ src/mb_motion_comp.cpp \
+ src/mb_utils.cpp \
+ src/packet_util.cpp \
+ src/post_filter.cpp \
+ src/post_proc_semaphore.cpp \
+ src/pp_semaphore_chroma_inter.cpp \
+ src/pp_semaphore_luma.cpp \
+ src/pvdec_api.cpp \
+ src/scaling_tab.cpp \
+ src/vlc_decode.cpp \
+ src/vlc_dequant.cpp \
+ src/vlc_tab.cpp \
+ src/vop.cpp \
+ src/zigzag_tab.cpp
+
+
+LOCAL_MODULE := libstagefright_m4vh263dec
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/include \
+ $(TOP)/frameworks/base/media/libstagefright/include \
+ $(TOP)/frameworks/native/include/media/openmax
+
+LOCAL_CFLAGS := -DOSCL_EXPORT_REF= -DOSCL_IMPORT_REF=
+
+include $(BUILD_STATIC_LIBRARY)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ SoftMPEG4.cpp
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/include \
+ frameworks/base/media/libstagefright/include \
+ frameworks/native/include/media/openmax
+
+LOCAL_CFLAGS := -DOSCL_EXPORT_REF= -DOSCL_IMPORT_REF=
+
+LOCAL_STATIC_LIBRARIES := \
+ libstagefright_m4vh263dec
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright libstagefright_omx libstagefright_foundation libutils
+
+LOCAL_MODULE := libstagefright_soft_mpeg4dec
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
new file mode 100644
index 0000000..a34a0ca
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -0,0 +1,597 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SoftMPEG4"
+#include <utils/Log.h>
+
+#include "SoftMPEG4.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/IOMX.h>
+
+#include "mp4dec_api.h"
+
+namespace android {
+
+static const CodecProfileLevel kM4VProfileLevels[] = {
+ { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0 },
+ { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0b },
+ { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level1 },
+ { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level2 },
+ { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level3 },
+};
+
+static const CodecProfileLevel kH263ProfileLevels[] = {
+ { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level10 },
+ { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level20 },
+ { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level30 },
+ { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45 },
+ { OMX_VIDEO_H263ProfileISWV2, OMX_VIDEO_H263Level10 },
+ { OMX_VIDEO_H263ProfileISWV2, OMX_VIDEO_H263Level20 },
+ { OMX_VIDEO_H263ProfileISWV2, OMX_VIDEO_H263Level30 },
+ { OMX_VIDEO_H263ProfileISWV2, OMX_VIDEO_H263Level45 },
+};
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+SoftMPEG4::SoftMPEG4(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SimpleSoftOMXComponent(name, callbacks, appData, component),
+ mMode(MODE_MPEG4),
+ mHandle(new tagvideoDecControls),
+ mInputBufferCount(0),
+ mWidth(352),
+ mHeight(288),
+ mCropLeft(0),
+ mCropTop(0),
+ mCropRight(mWidth - 1),
+ mCropBottom(mHeight - 1),
+ mSignalledError(false),
+ mInitialized(false),
+ mFramesConfigured(false),
+ mNumSamplesOutput(0),
+ mOutputPortSettingsChange(NONE) {
+ if (!strcmp(name, "OMX.google.h263.decoder")) {
+ mMode = MODE_H263;
+ } else {
+ CHECK(!strcmp(name, "OMX.google.mpeg4.decoder"));
+ }
+
+ initPorts();
+ CHECK_EQ(initDecoder(), (status_t)OK);
+}
+
+SoftMPEG4::~SoftMPEG4() {
+ if (mInitialized) {
+ PVCleanUpVideoDecoder(mHandle);
+ }
+
+ delete mHandle;
+ mHandle = NULL;
+}
+
+void SoftMPEG4::initPorts() {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+
+ def.nPortIndex = 0;
+ def.eDir = OMX_DirInput;
+ def.nBufferCountMin = kNumInputBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 8192;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainVideo;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 1;
+
+ def.format.video.cMIMEType =
+ (mMode == MODE_MPEG4)
+ ? const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG4)
+ : const_cast<char *>(MEDIA_MIMETYPE_VIDEO_H263);
+
+ def.format.video.pNativeRender = NULL;
+ def.format.video.nFrameWidth = mWidth;
+ def.format.video.nFrameHeight = mHeight;
+ def.format.video.nStride = def.format.video.nFrameWidth;
+ def.format.video.nSliceHeight = def.format.video.nFrameHeight;
+ def.format.video.nBitrate = 0;
+ def.format.video.xFramerate = 0;
+ def.format.video.bFlagErrorConcealment = OMX_FALSE;
+
+ def.format.video.eCompressionFormat =
+ mMode == MODE_MPEG4 ? OMX_VIDEO_CodingMPEG4 : OMX_VIDEO_CodingH263;
+
+ def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
+ def.format.video.pNativeWindow = NULL;
+
+ addPort(def);
+
+ def.nPortIndex = 1;
+ def.eDir = OMX_DirOutput;
+ def.nBufferCountMin = kNumOutputBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainVideo;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 2;
+
+ def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
+ def.format.video.pNativeRender = NULL;
+ def.format.video.nFrameWidth = mWidth;
+ def.format.video.nFrameHeight = mHeight;
+ def.format.video.nStride = def.format.video.nFrameWidth;
+ def.format.video.nSliceHeight = def.format.video.nFrameHeight;
+ def.format.video.nBitrate = 0;
+ def.format.video.xFramerate = 0;
+ def.format.video.bFlagErrorConcealment = OMX_FALSE;
+ def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+ def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
+ def.format.video.pNativeWindow = NULL;
+
+ def.nBufferSize =
+ (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2;
+
+ addPort(def);
+}
+
+status_t SoftMPEG4::initDecoder() {
+ memset(mHandle, 0, sizeof(tagvideoDecControls));
+ return OK;
+}
+
+OMX_ERRORTYPE SoftMPEG4::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
+
+ if (formatParams->nPortIndex > 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (formatParams->nIndex != 0) {
+ return OMX_ErrorNoMore;
+ }
+
+ if (formatParams->nPortIndex == 0) {
+ formatParams->eCompressionFormat =
+ (mMode == MODE_MPEG4)
+ ? OMX_VIDEO_CodingMPEG4 : OMX_VIDEO_CodingH263;
+
+ formatParams->eColorFormat = OMX_COLOR_FormatUnused;
+ formatParams->xFramerate = 0;
+ } else {
+ CHECK_EQ(formatParams->nPortIndex, 1u);
+
+ formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
+ formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
+ formatParams->xFramerate = 0;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamVideoProfileLevelQuerySupported:
+ {
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
+ (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params;
+
+ if (profileLevel->nPortIndex != 0) { // Input port only
+ ALOGE("Invalid port index: %ld", profileLevel->nPortIndex);
+ return OMX_ErrorUnsupportedIndex;
+ }
+
+ size_t index = profileLevel->nProfileIndex;
+ if (mMode == MODE_H263) {
+ size_t nProfileLevels =
+ sizeof(kH263ProfileLevels) / sizeof(kH263ProfileLevels[0]);
+ if (index >= nProfileLevels) {
+ return OMX_ErrorNoMore;
+ }
+
+ profileLevel->eProfile = kH263ProfileLevels[index].mProfile;
+ profileLevel->eLevel = kH263ProfileLevels[index].mLevel;
+ } else {
+ size_t nProfileLevels =
+ sizeof(kM4VProfileLevels) / sizeof(kM4VProfileLevels[0]);
+ if (index >= nProfileLevels) {
+ return OMX_ErrorNoMore;
+ }
+
+ profileLevel->eProfile = kM4VProfileLevels[index].mProfile;
+ profileLevel->eLevel = kM4VProfileLevels[index].mLevel;
+ }
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftMPEG4::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamStandardComponentRole:
+ {
+ const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+ (const OMX_PARAM_COMPONENTROLETYPE *)params;
+
+ if (mMode == MODE_MPEG4) {
+ if (strncmp((const char *)roleParams->cRole,
+ "video_decoder.mpeg4",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+ } else {
+ if (strncmp((const char *)roleParams->cRole,
+ "video_decoder.h263",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
+
+ if (formatParams->nPortIndex > 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (formatParams->nIndex != 0) {
+ return OMX_ErrorNoMore;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftMPEG4::getConfig(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexConfigCommonOutputCrop:
+ {
+ OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)params;
+
+ if (rectParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ rectParams->nLeft = mCropLeft;
+ rectParams->nTop = mCropTop;
+ rectParams->nWidth = mCropRight - mCropLeft + 1;
+ rectParams->nHeight = mCropBottom - mCropTop + 1;
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return OMX_ErrorUnsupportedIndex;
+ }
+}
+
+void SoftMPEG4::onQueueFilled(OMX_U32 portIndex) {
+ if (mSignalledError || mOutputPortSettingsChange != NONE) {
+ return;
+ }
+
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+
+ while (!inQueue.empty() && outQueue.size() == kNumOutputBuffers) {
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+
+ PortInfo *port = editPortInfo(1);
+
+ OMX_BUFFERHEADERTYPE *outHeader =
+ port->mBuffers.editItemAt(mNumSamplesOutput & 1).mHeader;
+
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+
+ ++mInputBufferCount;
+
+ outHeader->nFilledLen = 0;
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+
+ List<BufferInfo *>::iterator it = outQueue.begin();
+ while ((*it)->mHeader != outHeader) {
+ ++it;
+ }
+
+ BufferInfo *outInfo = *it;
+ outInfo->mOwnedByUs = false;
+ outQueue.erase(it);
+ outInfo = NULL;
+
+ notifyFillBufferDone(outHeader);
+ outHeader = NULL;
+ return;
+ }
+
+ uint8_t *bitstream = inHeader->pBuffer + inHeader->nOffset;
+
+ if (!mInitialized) {
+ uint8_t *vol_data[1];
+ int32_t vol_size = 0;
+
+ vol_data[0] = NULL;
+
+ if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+ vol_data[0] = bitstream;
+ vol_size = inHeader->nFilledLen;
+ }
+
+ MP4DecodingMode mode =
+ (mMode == MODE_MPEG4) ? MPEG4_MODE : H263_MODE;
+
+ Bool success = PVInitVideoDecoder(
+ mHandle, vol_data, &vol_size, 1, mWidth, mHeight, mode);
+
+ if (!success) {
+ ALOGW("PVInitVideoDecoder failed. Unsupported content?");
+
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
+ MP4DecodingMode actualMode = PVGetDecBitstreamMode(mHandle);
+ if (mode != actualMode) {
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
+ PVSetPostProcType((VideoDecControls *) mHandle, 0);
+
+ if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+ }
+
+ mInitialized = true;
+
+ if (mode == MPEG4_MODE && portSettingsChanged()) {
+ return;
+ }
+
+ continue;
+ }
+
+ if (!mFramesConfigured) {
+ PortInfo *port = editPortInfo(1);
+ OMX_BUFFERHEADERTYPE *outHeader = port->mBuffers.editItemAt(1).mHeader;
+
+ PVSetReferenceYUV(mHandle, outHeader->pBuffer);
+
+ mFramesConfigured = true;
+ }
+
+ uint32_t useExtTimestamp = (inHeader->nOffset == 0);
+
+ // decoder deals in ms, OMX in us.
+ uint32_t timestamp =
+ useExtTimestamp ? (inHeader->nTimeStamp + 500) / 1000 : 0xFFFFFFFF;
+
+ int32_t bufferSize = inHeader->nFilledLen;
+
+ // The PV decoder is lying to us, sometimes it'll claim to only have
+ // consumed a subset of the buffer when it clearly consumed all of it.
+ // ignore whatever it says...
+ int32_t tmp = bufferSize;
+
+ if (PVDecodeVideoFrame(
+ mHandle, &bitstream, &timestamp, &tmp,
+ &useExtTimestamp,
+ outHeader->pBuffer) != PV_TRUE) {
+ ALOGE("failed to decode video frame.");
+
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
+
+ if (portSettingsChanged()) {
+ return;
+ }
+
+ // decoder deals in ms, OMX in us.
+ outHeader->nTimeStamp = timestamp * 1000;
+
+ CHECK_LE(bufferSize, inHeader->nFilledLen);
+ inHeader->nOffset += inHeader->nFilledLen - bufferSize;
+ inHeader->nFilledLen = bufferSize;
+
+ if (inHeader->nFilledLen == 0) {
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+ }
+
+ ++mInputBufferCount;
+
+ outHeader->nOffset = 0;
+ outHeader->nFilledLen = (mWidth * mHeight * 3) / 2;
+ outHeader->nFlags = 0;
+
+ List<BufferInfo *>::iterator it = outQueue.begin();
+ while ((*it)->mHeader != outHeader) {
+ ++it;
+ }
+
+ BufferInfo *outInfo = *it;
+ outInfo->mOwnedByUs = false;
+ outQueue.erase(it);
+ outInfo = NULL;
+
+ notifyFillBufferDone(outHeader);
+ outHeader = NULL;
+
+ ++mNumSamplesOutput;
+ }
+}
+
+bool SoftMPEG4::portSettingsChanged() {
+ int32_t disp_width, disp_height;
+ PVGetVideoDimensions(mHandle, &disp_width, &disp_height);
+
+ int32_t buf_width, buf_height;
+ PVGetBufferDimensions(mHandle, &buf_width, &buf_height);
+
+ CHECK_LE(disp_width, buf_width);
+ CHECK_LE(disp_height, buf_height);
+
+ ALOGV("disp_width = %d, disp_height = %d, buf_width = %d, buf_height = %d",
+ disp_width, disp_height, buf_width, buf_height);
+
+ if (mCropRight != disp_width - 1
+ || mCropBottom != disp_height - 1) {
+ mCropLeft = 0;
+ mCropTop = 0;
+ mCropRight = disp_width - 1;
+ mCropBottom = disp_height - 1;
+
+ notify(OMX_EventPortSettingsChanged,
+ 1,
+ OMX_IndexConfigCommonOutputCrop,
+ NULL);
+ }
+
+ if (buf_width != mWidth || buf_height != mHeight) {
+ mWidth = buf_width;
+ mHeight = buf_height;
+
+ updatePortDefinitions();
+
+ if (mMode == MODE_H263) {
+ PVCleanUpVideoDecoder(mHandle);
+
+ uint8_t *vol_data[1];
+ int32_t vol_size = 0;
+
+ vol_data[0] = NULL;
+ if (!PVInitVideoDecoder(
+ mHandle, vol_data, &vol_size, 1, mWidth, mHeight,
+ H263_MODE)) {
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return true;
+ }
+ }
+
+ mFramesConfigured = false;
+
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+ return true;
+ }
+
+ return false;
+}
+
+void SoftMPEG4::onPortFlushCompleted(OMX_U32 portIndex) {
+ if (portIndex == 0 && mInitialized) {
+ CHECK_EQ((int)PVResetVideoDecoder(mHandle), (int)PV_TRUE);
+ }
+}
+
+void SoftMPEG4::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
+ if (portIndex != 1) {
+ return;
+ }
+
+ switch (mOutputPortSettingsChange) {
+ case NONE:
+ break;
+
+ case AWAITING_DISABLED:
+ {
+ CHECK(!enabled);
+ mOutputPortSettingsChange = AWAITING_ENABLED;
+ break;
+ }
+
+ default:
+ {
+ CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
+ CHECK(enabled);
+ mOutputPortSettingsChange = NONE;
+ break;
+ }
+ }
+}
+
+void SoftMPEG4::updatePortDefinitions() {
+ OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef;
+ def->format.video.nFrameWidth = mWidth;
+ def->format.video.nFrameHeight = mHeight;
+ def->format.video.nStride = def->format.video.nFrameWidth;
+ def->format.video.nSliceHeight = def->format.video.nFrameHeight;
+
+ def = &editPortInfo(1)->mDef;
+ def->format.video.nFrameWidth = mWidth;
+ def->format.video.nFrameHeight = mHeight;
+ def->format.video.nStride = def->format.video.nFrameWidth;
+ def->format.video.nSliceHeight = def->format.video.nFrameHeight;
+
+ def->nBufferSize =
+ (((def->format.video.nFrameWidth + 15) & -16)
+ * ((def->format.video.nFrameHeight + 15) & -16) * 3) / 2;
+}
+
+} // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+ const char *name, const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+ return new android::SoftMPEG4(name, callbacks, appData, component);
+}
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
new file mode 100644
index 0000000..dff08a7
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SOFT_MPEG4_H_
+
+#define SOFT_MPEG4_H_
+
+#include "SimpleSoftOMXComponent.h"
+
+struct tagvideoDecControls;
+
+namespace android {
+
+struct SoftMPEG4 : public SimpleSoftOMXComponent {
+ SoftMPEG4(const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ virtual ~SoftMPEG4();
+
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual OMX_ERRORTYPE getConfig(OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual void onQueueFilled(OMX_U32 portIndex);
+ virtual void onPortFlushCompleted(OMX_U32 portIndex);
+ virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled);
+
+private:
+ enum {
+ kNumInputBuffers = 4,
+ kNumOutputBuffers = 2,
+ };
+
+ enum {
+ MODE_MPEG4,
+ MODE_H263,
+
+ } mMode;
+
+ tagvideoDecControls *mHandle;
+
+ size_t mInputBufferCount;
+
+ int32_t mWidth, mHeight;
+ int32_t mCropLeft, mCropTop, mCropRight, mCropBottom;
+
+ bool mSignalledError;
+ bool mInitialized;
+ bool mFramesConfigured;
+
+ int32_t mNumSamplesOutput;
+
+ enum {
+ NONE,
+ AWAITING_DISABLED,
+ AWAITING_ENABLED
+ } mOutputPortSettingsChange;
+
+ void initPorts();
+ status_t initDecoder();
+
+ void updatePortDefinitions();
+ bool portSettingsChanged();
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftMPEG4);
+};
+
+} // namespace android
+
+#endif // SOFT_MPEG4_H_
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h b/media/libstagefright/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h
new file mode 100644
index 0000000..ec6871f
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h
@@ -0,0 +1,67 @@
+/* ------------------------------------------------------------------
+ * 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 M4V_H263_DECODER_PV_TYPES_H_
+#define M4V_H263_DECODER_PV_TYPES_H_
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h> // for free, malloc, etc
+
+// 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;
+
+// Redefine the oscl memory management routines
+#define oscl_memcpy memcpy
+#define oscl_memset memset
+#define oscl_malloc malloc
+#define oscl_free free
+#define oscl_memcmp memcmp
+#define OSCL_DELETE(ptr) { delete(ptr); }
+
+// Request status values. These are negative so that
+// they won't conflict with system error codes.
+const int32 OSCL_REQUEST_ERR_NONE = 0;
+const int32 OSCL_REQUEST_PENDING = (-0x7fffffff);
+const int32 OSCL_REQUEST_ERR_CANCEL = (-1);
+const int32 OSCL_REQUEST_ERR_GENERAL = (-2);
+
+// Request status type
+class OsclAOStatus
+{
+ public:
+ OsclAOStatus();
+ OsclAOStatus(int32 aStatus);
+ int32 operator=(int32 aStatus);
+ int32 operator==(int32 aStatus) const;
+ int32 operator!=(int32 aStatus) const;
+ int32 operator>=(int32 aStatus) const;
+ int32 operator<=(int32 aStatus) const;
+ int32 operator>(int32 aStatus) const;
+ int32 operator<(int32 aStatus) const;
+ int32 Value() const;
+ private:
+ int32 iStatus;
+};
+
+#endif // M4V_H263_DECODER_PV_TYPES_H_
diff --git a/media/libstagefright/codecs/m4v_h263/dec/include/mp4dec_api.h b/media/libstagefright/codecs/m4v_h263/dec/include/mp4dec_api.h
new file mode 100644
index 0000000..24a50ce
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/include/mp4dec_api.h
@@ -0,0 +1,181 @@
+/* ------------------------------------------------------------------
+ * 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 _MP4DEC_API_H_
+#define _MP4DEC_API_H_
+
+#include "m4vh263_decoder_pv_types.h"
+
+#define PV_TOLERATE_VOL_ERRORS
+#define PV_MEMORY_POOL
+
+#ifndef _PV_TYPES_
+#define _PV_TYPES_
+
+typedef uint Bool;
+
+#define PV_CODEC_INIT 0
+#define PV_CODEC_STOP 1
+#endif
+
+#define PV_TRUE 1
+#define PV_FALSE 0
+
+/* flag for post-processing 4/25/00 */
+
+#ifdef DEC_NOPOSTPROC
+#undef PV_POSTPROC_ON /* enable compilation of post-processing code */
+#else
+#define PV_POSTPROC_ON
+#endif
+
+#define PV_NO_POST_PROC 0
+#define PV_DEBLOCK 1
+#define PV_DERING 2
+
+
+
+#include "visual_header.h" // struct VolInfo is defined
+
+
+/**@name Structure and Data Types
+ * These type definitions specify the input / output from the PVMessage
+ * library.
+ */
+
+/*@{*/
+/* The application has to allocate space for this structure */
+typedef struct tagOutputFrame
+{
+ uint8 *data; /* pointer to output YUV buffer */
+ uint32 timeStamp; /* time stamp */
+} OutputFrame;
+
+typedef struct tagApplicationData
+{
+ int layer; /* current video layer */
+ void *object; /* some optional data field */
+} applicationData;
+
+/* Application controls, this structed shall be allocated */
+/* and initialized in the application. */
+typedef struct tagvideoDecControls
+{
+ /* The following fucntion pointer is copied to BitstreamDecVideo structure */
+ /* upon initialization and never used again. */
+ int (*readBitstreamData)(uint8 *buf, int nbytes_required, void *appData);
+ applicationData appData;
+
+ uint8 *outputFrame;
+ void *videoDecoderData; /* this is an internal pointer that is only used */
+ /* in the decoder library. */
+#ifdef PV_MEMORY_POOL
+ int32 size;
+#endif
+ int nLayers;
+ /* pointers to VOL data for frame-based decoding. */
+ uint8 *volbuf[2]; /* maximum of 2 layers for now */
+ int32 volbuf_size[2];
+
+} VideoDecControls;
+
+typedef enum
+{
+ H263_MODE = 0, MPEG4_MODE, UNKNOWN_MODE
+} MP4DecodingMode;
+
+typedef enum
+{
+ MP4_I_FRAME, MP4_P_FRAME, MP4_B_FRAME, MP4_BAD_FRAME
+} MP4FrameType;
+
+typedef struct tagVopHeaderInfo
+{
+ int currLayer;
+ uint32 timestamp;
+ MP4FrameType frameType;
+ int refSelCode;
+ int16 quantizer;
+} VopHeaderInfo;
+
+/*--------------------------------------------------------------------------*
+ * VideoRefCopyInfo:
+ * OMAP DSP specific typedef structure, to support the user (ARM) copying
+ * of a Reference Frame into the Video Decoder.
+ *--------------------------------------------------------------------------*/
+typedef struct tagVideoRefCopyInfoPtr
+{
+ uint8 *yChan; /* The Y component frame the user can copy a new reference to */
+ uint8 *uChan; /* The U component frame the user can copy a new reference to */
+ uint8 *vChan; /* The V component frame the user can copy a new reference to */
+ uint8 *currentVop; /* The Vop for video the user can copy a new reference to */
+} VideoRefCopyInfoPtr;
+
+typedef struct tagVideoRefCopyInfoData
+{
+ int16 width; /* Width */
+ int16 height; /* Height */
+ int16 realWidth; /* Non-padded width, not a multiple of 16. */
+ int16 realHeight; /* Non-padded height, not a multiple of 16. */
+} VideoRefCopyInfoData;
+
+typedef struct tagVideoRefCopyInfo
+{
+ VideoRefCopyInfoData data;
+ VideoRefCopyInfoPtr ptrs;
+} VideoRefCopyInfo;
+
+/*@}*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ OSCL_IMPORT_REF Bool PVInitVideoDecoder(VideoDecControls *decCtrl, uint8 *volbuf[], int32 *volbuf_size, int nLayers, int width, int height, MP4DecodingMode mode);
+ Bool PVAllocVideoData(VideoDecControls *decCtrl, int width, int height, int nLayers);
+ OSCL_IMPORT_REF Bool PVCleanUpVideoDecoder(VideoDecControls *decCtrl);
+ Bool PVResetVideoDecoder(VideoDecControls *decCtrl);
+ OSCL_IMPORT_REF void PVSetReferenceYUV(VideoDecControls *decCtrl, uint8 *refYUV);
+ Bool PVDecSetReference(VideoDecControls *decCtrl, uint8 *refYUV, uint32 timestamp);
+ Bool PVDecSetEnhReference(VideoDecControls *decCtrl, uint8 *refYUV, uint32 timestamp);
+ OSCL_IMPORT_REF Bool PVDecodeVideoFrame(VideoDecControls *decCtrl, uint8 *bitstream[], uint32 *timestamp, int32 *buffer_size, uint use_ext_timestamp[], uint8* currYUV);
+ Bool PVDecodeVopHeader(VideoDecControls *decCtrl, uint8 *buffer[], uint32 timestamp[], int32 buffer_size[], VopHeaderInfo *header_info, uint use_ext_timestamp[], uint8 *currYUV);
+ Bool PVDecodeVopBody(VideoDecControls *decCtrl, int32 buffer_size[]);
+ void PVDecPostProcess(VideoDecControls *decCtrl, uint8 *outputYUV);
+ OSCL_IMPORT_REF void PVGetVideoDimensions(VideoDecControls *decCtrl, int32 *display_width, int32 *display_height);
+ OSCL_IMPORT_REF void PVGetBufferDimensions(VideoDecControls *decCtrl, int32 *buf_width, int32 *buf_height);
+ OSCL_IMPORT_REF void PVSetPostProcType(VideoDecControls *decCtrl, int mode);
+ uint32 PVGetVideoTimeStamp(VideoDecControls *decoderControl);
+ int PVGetDecBitrate(VideoDecControls *decCtrl);
+ int PVGetDecFramerate(VideoDecControls *decCtrl);
+ uint8 *PVGetDecOutputFrame(VideoDecControls *decCtrl);
+ int PVGetLayerID(VideoDecControls *decCtrl);
+ int32 PVGetDecMemoryUsage(VideoDecControls *decCtrl);
+ OSCL_IMPORT_REF MP4DecodingMode PVGetDecBitstreamMode(VideoDecControls *decCtrl);
+ Bool PVExtractVolHeader(uint8 *video_buffer, uint8 *vol_header, int32 *vol_header_size);
+ int32 PVLocateFrameHeader(uint8 *video_buffer, int32 vop_size);
+ int32 PVLocateH263FrameHeader(uint8 *video_buffer, int32 vop_size);
+ Bool PVGetVolInfo(VideoDecControls *decCtrl, VolInfo *pVolInfo); // BX 6/24/04
+ Bool IsIntraFrame(VideoDecControls *decoderControl);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _MP4DEC_API_H_ */
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/include/visual_header.h b/media/libstagefright/codecs/m4v_h263/dec/include/visual_header.h
new file mode 100644
index 0000000..48da0dc
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/include/visual_header.h
@@ -0,0 +1,51 @@
+/* ------------------------------------------------------------------
+ * 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 _VISUAL_HEADER_H
+#define _VISUAL_HEADER_H
+
+#ifndef _PV_TYPES_ // In order to compile in MDF wrapper
+#define _PV_TYPES_
+
+#include "m4vh263_decoder_pv_types.h"
+
+typedef uint Bool;
+
+#endif // #ifndef _PV_TYPES_
+
+
+typedef struct tagVolInfo
+{
+ int32 shortVideoHeader; /* shortVideoHeader mode */
+
+ /* Error Resilience Flags */
+ int32 errorResDisable; /* VOL disable error resilence mode(Use Resynch markers) */
+ int32 useReverseVLC; /* VOL reversible VLCs */
+ int32 dataPartitioning; /* VOL data partitioning */
+
+ /* Parameters used for scalability */
+ int32 scalability; /* VOL scalability (flag) */
+
+ int32 nbitsTimeIncRes; /* number of bits for time increment () */
+
+ int32 profile_level_id; /* profile and level */
+
+
+} VolInfo;
+
+#endif // #ifndef _VISUAL_HEADER_H
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/adaptive_smooth_no_mmx.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/adaptive_smooth_no_mmx.cpp
new file mode 100644
index 0000000..e2761eb
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/adaptive_smooth_no_mmx.cpp
@@ -0,0 +1,421 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+ Description: Separated modules into one function per file and put into
+ new template.
+
+ Description: Optimizing C code and adding comments. Also changing variable
+ names to make them more meaningful.
+
+ Who: Date:
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ Rec_Y = pointer to 0th position in buffer containing luminance values
+ of type uint8.
+ y_start = value of y coordinate of type int that specifies the first
+ row of pixels to be used in the filter algorithm.
+ x_start = value of x coordinate of type int that specifies the first
+ column of pixels to be used in the filter algorithm.
+ y_blk_start = value of the y coordinate of type int that specifies the
+ row of pixels which contains the start of a block. The row
+ specified by y_blk_start+BLK_SIZE is the last row of pixels
+ that are used in the filter algorithm.
+ x_blk_start = value of the x coordinate of type int that specifies the
+ column of pixels which contains the start of a block. The
+ column specified by x_blk_start+BLK_SIZE is the last column of
+ pixels that are used in the filter algorithm.
+ thr = value of type int that is compared to the elements in Rec_Y to
+ determine if a particular value in Rec_Y will be modified by
+ the filter or not
+ width = value of type int that specifies the width of the display
+ in pixels (or pels, equivalently).
+ max_diff = value of type int that specifies the value that may be added
+ or subtracted from the pixel in Rec_Y that is being filtered
+ if the filter algorithm decides to change that particular
+ pixel's luminance value.
+
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ Buffer pointed to by Rec_Y is modified with the filtered
+ luminance values.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function implements a motion compensated noise filter using adaptive
+ weighted averaging of luminance values. *Rec_Y contains the luminance values
+ that are being filtered.
+
+ The picture below depicts a 3x3 group of pixel luminance values. The "u", "c",
+ and "l" stand for "upper", "center" and "lower", respectively. The location
+ of pelc0 is specified by x_start and y_start in the 1-D array "Rec_Y" as
+ follows (assuming x_start=0):
+
+ location of pelc0 = [(y_start+1) * width] + x_start
+
+ Moving up or down 1 row (moving from pelu2 to pelc2, for example) is done by
+ incrementing or decrementing "width" elements within Rec_Y.
+
+ The coordinates of the upper left hand corner of a block (not the group of
+ 9 pixels depicted in the figure below) is specified by
+ (y_blk_start, x_blk_start). The width and height of the block is BLKSIZE.
+ (y_start,x_start) may be specified independently of (y_blk_start, x_blk_start).
+
+ (y_start,x_start)
+ -----------|--------------------------
+ | | | | |
+ | X | pelu1 | pelu2 |
+ | pelu0 | | |
+ | | | |
+ --------------------------------------
+ | | | |
+ | pelc0 | pelc1 | pelc2 |
+ | | | |
+ | | | |
+ --------------------------------------
+ | | | |
+ | pell0 | pell1 | pell2 |
+ | | | |
+ | | | |
+ --------------------------------------
+
+ The filtering of the luminance values is achieved by comparing the 9
+ luminance values to a threshold value ("thr") and then changing the
+ luminance value of pelc1 if all of the values are above or all of the values
+ are below the threshold. The amount that the luminance value is changed
+ depends on a weighted sum of the 9 luminance values. The position of Pelc1
+ is then advanced to the right by one (as well as all of the surrounding pixels)
+ and the same calculation is performed again for the luminance value of the new
+ Pelc1. This continues row-wise until pixels in the last row of the block are
+ filtered.
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ None.
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ ..\corelibs\decoder\common\src\post_proc.c
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+#include "post_proc.h"
+#include "mp4def.h"
+
+#define OSCL_DISABLE_WARNING_CONV_POSSIBLE_LOSS_OF_DATA
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+#ifdef PV_POSTPROC_ON
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void AdaptiveSmooth_NoMMX(
+ uint8 *Rec_Y, /* i/o */
+ int y_start, /* i */
+ int x_start, /* i */
+ int y_blk_start, /* i */
+ int x_blk_start, /* i */
+ int thr, /* i */
+ int width, /* i */
+ int max_diff /* i */
+)
+{
+
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int sign_v[15];
+ int sum_v[15];
+ int *sum_V_ptr;
+ int *sign_V_ptr;
+ uint8 pelu;
+ uint8 pelc;
+ uint8 pell;
+ uint8 *pelp;
+ uint8 oldrow[15];
+ int sum;
+ int sum1;
+ uint8 *Rec_Y_ptr;
+ int32 addr_v;
+ int row_cntr;
+ int col_cntr;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* first row
+ */
+ addr_v = (int32)(y_start + 1) * width; /* y coord of 1st element in the row /
+ /containing pelc pixel / */
+ Rec_Y_ptr = &Rec_Y[addr_v + x_start]; /* initializing pointer to
+ / pelc0 position */
+ sum_V_ptr = &sum_v[0]; /* initializing pointer to 0th element of array
+ / that will contain weighted sums of pixel
+ / luminance values */
+ sign_V_ptr = &sign_v[0]; /* initializing pointer to 0th element of
+ / array that will contain sums that indicate
+ / how many of the 9 pixels are above or below
+ / the threshold value (thr) */
+ pelp = &oldrow[0]; /* initializing pointer to the 0th element of array
+ / that will contain current values of pelc that
+ / are saved and used as values of pelu when the
+ / next row of pixels are filtered */
+
+ pelu = *(Rec_Y_ptr - width); /* assigning value of pelu0 to pelu */
+ *pelp++ = pelc = *Rec_Y_ptr; /* assigning value of pelc0 to pelc and
+ / storing this value in pelp which
+ / will be used as value of pelu0 when
+ / next row is filtered */
+ pell = *(Rec_Y_ptr + width); /* assigning value of pell0 to pell */
+ Rec_Y_ptr++; /* advancing pointer from pelc0 to pelc1 */
+ *sum_V_ptr++ = pelu + (pelc << 1) + pell; /* weighted sum of pelu0,
+ / pelc0 and pell0 */
+ /* sum of 0's and 1's (0 if pixel value is below thr, 1 if value
+ /is above thr) */
+ *sign_V_ptr++ = INDEX(pelu, thr) + INDEX(pelc, thr) + INDEX(pell, thr);
+
+
+ pelu = *(Rec_Y_ptr - width); /* assigning value of pelu1 to pelu */
+ *pelp++ = pelc = *Rec_Y_ptr; /* assigning value of pelc1 to pelc and
+ / storing this value in pelp which
+ / will be used as the value of pelu1 when
+ / next row is filtered */
+ pell = *(Rec_Y_ptr + width); /* assigning value of pell1 to pell */
+ Rec_Y_ptr++; /* advancing pointer from pelc1 to pelc2 */
+ *sum_V_ptr++ = pelu + (pelc << 1) + pell; /* weighted sum of pelu1,
+ / pelc1 and pell1 */
+ /* sum of 0's and 1's (0 if pixel value is below thr, 1 if value
+ /is above thr) */
+ *sign_V_ptr++ = INDEX(pelu, thr) + INDEX(pelc, thr) + INDEX(pell, thr);
+
+ /* The loop below performs the filtering for the first row of
+ / pixels in the region. It steps across the remaining pixels in
+ / the row and alters the luminance value of pelc1 if necessary,
+ / depending on the luminance values of the adjacent pixels*/
+
+ for (col_cntr = (x_blk_start + BLKSIZE - 1) - x_start; col_cntr > 0; col_cntr--)
+ {
+ pelu = *(Rec_Y_ptr - width); /* assigning value of pelu2 to
+ / pelu */
+ *pelp++ = pelc = *Rec_Y_ptr; /* assigning value of pelc2 to pelc
+ / and storing this value in pelp
+ / which will be used as value of pelu2
+ / when next row is filtered */
+ pell = *(Rec_Y_ptr + width); /* assigning value of pell2 to pell */
+
+ /* weighted sum of pelu1, pelc1 and pell1 */
+ *sum_V_ptr = pelu + (pelc << 1) + pell;
+ /* sum of 0's and 1's (0 if pixel value is below thr,
+ /1 if value is above thr) */
+ *sign_V_ptr = INDEX(pelu, thr) + INDEX(pelc, thr) +
+ INDEX(pell, thr);
+ /* the value of sum1 indicates how many of the 9 pixels'
+ /luminance values are above or equal to thr */
+ sum1 = *(sign_V_ptr - 2) + *(sign_V_ptr - 1) + *sign_V_ptr;
+
+ /* alter the luminance value of pelc1 if all 9 luminance values
+ /are above or equal to thr or if all 9 values are below thr */
+ if (sum1 == 0 || sum1 == 9)
+ {
+ /* sum is a weighted average of the 9 pixel luminance
+ /values */
+ sum = (*(sum_V_ptr - 2) + (*(sum_V_ptr - 1) << 1) +
+ *sum_V_ptr + 8) >> 4;
+
+ Rec_Y_ptr--; /* move pointer back to pelc1 */
+ /* If luminance value of pelc1 is larger than
+ / sum by more than max_diff, then subract max_diff
+ / from luminance value of pelc1*/
+ if ((int)(*Rec_Y_ptr - sum) > max_diff)
+ {
+ sum = *Rec_Y_ptr - max_diff;
+ }
+ /* If luminance value of pelc1 is smaller than
+ / sum by more than max_diff, then add max_diff
+ / to luminance value of pelc1*/
+ else if ((int)(*Rec_Y_ptr - sum) < -max_diff)
+ {
+ sum = *Rec_Y_ptr + max_diff;
+ }
+ *Rec_Y_ptr++ = sum; /* assign value of sum to pelc1
+ and advance pointer to pelc2 */
+ }
+ Rec_Y_ptr++; /* advance pointer to new value of pelc2
+ / old pelc2 is now treated as pelc1*/
+ sum_V_ptr++; /* pointer is advanced so next weighted sum may
+ / be saved */
+ sign_V_ptr++; /* pointer is advanced so next sum of 0's and
+ / 1's may be saved */
+ }
+
+ /* The nested loops below perform the filtering for the remaining rows */
+
+ addr_v = (y_start + 2) * width; /* advance addr_v to the next row
+ / (corresponding to pell0)*/
+ /* The outer loop steps throught the rows. */
+ for (row_cntr = (y_blk_start + BLKSIZE) - (y_start + 2); row_cntr > 0; row_cntr--)
+ {
+ Rec_Y_ptr = &Rec_Y[addr_v + x_start]; /* advance pointer to
+ /the old pell0, which has become the new pelc0 */
+ addr_v += width; /* move addr_v down 1 row */
+ sum_V_ptr = &sum_v[0]; /* re-initializing pointer */
+ sign_V_ptr = &sign_v[0]; /* re-initilaizing pointer */
+ pelp = &oldrow[0]; /* re-initializing pointer */
+
+ pelu = *pelp; /* setting pelu0 to old value of pelc0 */
+ *pelp++ = pelc = *Rec_Y_ptr;
+ pell = *(Rec_Y_ptr + width);
+ Rec_Y_ptr++;
+ *sum_V_ptr++ = pelu + (pelc << 1) + pell;
+ *sign_V_ptr++ = INDEX(pelu, thr) + INDEX(pelc, thr) +
+ INDEX(pell, thr);
+
+ pelu = *pelp; /* setting pelu1 to old value of pelc1 */
+ *pelp++ = pelc = *Rec_Y_ptr;
+ pell = *(Rec_Y_ptr + width);
+ Rec_Y_ptr++;
+ *sum_V_ptr++ = pelu + (pelc << 1) + pell;
+ *sign_V_ptr++ = INDEX(pelu, thr) + INDEX(pelc, thr) +
+ INDEX(pell, thr);
+ /* The inner loop steps through the columns */
+ for (col_cntr = (x_blk_start + BLKSIZE - 1) - x_start; col_cntr > 0; col_cntr--)
+ {
+ pelu = *pelp; /* setting pelu2 to old value of pelc2 */
+ *pelp++ = pelc = *Rec_Y_ptr;
+ pell = *(Rec_Y_ptr + width);
+
+ *sum_V_ptr = pelu + (pelc << 1) + pell;
+ *sign_V_ptr = INDEX(pelu, thr) + INDEX(pelc, thr) +
+ INDEX(pell, thr);
+
+ sum1 = *(sign_V_ptr - 2) + *(sign_V_ptr - 1) + *sign_V_ptr;
+ /* the "if" statement below is the same as the one in
+ / the first loop */
+ if (sum1 == 0 || sum1 == 9)
+ {
+ sum = (*(sum_V_ptr - 2) + (*(sum_V_ptr - 1) << 1) +
+ *sum_V_ptr + 8) >> 4;
+
+ Rec_Y_ptr--;
+ if ((int)(*Rec_Y_ptr - sum) > max_diff)
+ {
+ sum = *Rec_Y_ptr - max_diff;
+ }
+ else if ((int)(*Rec_Y_ptr - sum) < -max_diff)
+ {
+ sum = *Rec_Y_ptr + max_diff;
+ }
+ *Rec_Y_ptr++ = (uint8) sum;
+ }
+ Rec_Y_ptr++;
+ sum_V_ptr++;
+ sign_V_ptr++;
+ }
+ }
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+#endif
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.cpp
new file mode 100644
index 0000000..37250f3
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.cpp
@@ -0,0 +1,1001 @@
+/* ------------------------------------------------------------------
+ * 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 "bitstream.h"
+#include "mp4dec_lib.h"
+
+
+#define OSCL_DISABLE_WARNING_CONDITIONAL_IS_CONSTANT
+/* to mask the n least significant bits of an integer */
+static const uint32 msk[33] =
+{
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007,
+ 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
+ 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
+ 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
+ 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
+ 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
+ 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
+ 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
+ 0xffffffff
+};
+
+
+/* ======================================================================== */
+/* Function : BitstreamFillCache() */
+/* Date : 08/29/2000 */
+/* Purpose : Read more bitstream data into buffer & the 24-byte cache. */
+/* This function is different from BitstreamFillBuffer in */
+/* that the buffer is the frame-based buffer provided by */
+/* the application. */
+/* In/out : */
+/* Return : PV_SUCCESS if successed, PV_FAIL if failed. */
+/* Modified : 4/16/01 : removed return of PV_END_OF_BUFFER */
+/* ======================================================================== */
+PV_STATUS BitstreamFillCache(BitstreamDecVideo *stream)
+{
+ uint8 *bitstreamBuffer = stream->bitstreamBuffer;
+ uint8 *v;
+ int num_bits, i;
+
+ stream->curr_word |= (stream->next_word >> stream->incnt); // stream->incnt cannot be 32
+ stream->next_word <<= (31 - stream->incnt);
+ stream->next_word <<= 1;
+ num_bits = stream->incnt_next + stream->incnt;
+ if (num_bits >= 32)
+ {
+ stream->incnt_next -= (32 - stream->incnt);
+ stream->incnt = 32;
+ return PV_SUCCESS;
+ }
+ /* this check can be removed if there is additional extra 4 bytes at the end of the bitstream */
+ v = bitstreamBuffer + stream->read_point;
+
+ if (stream->read_point > stream->data_end_pos - 4)
+ {
+ if (stream->data_end_pos <= stream->read_point)
+ {
+ stream->incnt = num_bits;
+ stream->incnt_next = 0;
+ return PV_SUCCESS;
+ }
+
+ stream->next_word = 0;
+
+ for (i = 0; i < stream->data_end_pos - stream->read_point; i++)
+ {
+ stream->next_word |= (v[i] << ((3 - i) << 3));
+ }
+
+ stream->read_point = stream->data_end_pos;
+ stream->curr_word |= (stream->next_word >> num_bits); // this is safe
+
+ stream->next_word <<= (31 - num_bits);
+ stream->next_word <<= 1;
+ num_bits = i << 3;
+ stream->incnt += stream->incnt_next;
+ stream->incnt_next = num_bits - (32 - stream->incnt);
+ if (stream->incnt_next < 0)
+ {
+ stream->incnt += num_bits;
+ stream->incnt_next = 0;
+ }
+ else
+ {
+ stream->incnt = 32;
+ }
+ return PV_SUCCESS;
+ }
+
+ stream->next_word = ((uint32)v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3];
+ stream->read_point += 4;
+
+ stream->curr_word |= (stream->next_word >> num_bits); // this is safe
+ stream->next_word <<= (31 - num_bits);
+ stream->next_word <<= 1;
+ stream->incnt_next += stream->incnt;
+ stream->incnt = 32;
+ return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/* Function : BitstreamReset() */
+/* Date : 08/29/2000 */
+/* Purpose : Initialize the bitstream buffer for frame-based decoding. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+void BitstreamReset(BitstreamDecVideo *stream, uint8 *buffer, int32 buffer_size)
+{
+ /* set up frame-based bitstream buffer */
+ oscl_memset(stream, 0, sizeof(BitstreamDecVideo));
+ stream->data_end_pos = buffer_size;
+ stream->bitstreamBuffer = buffer;
+}
+
+
+/* ======================================================================== */
+/* Function : BitstreamOpen() */
+/* Purpose : Initialize the bitstream data structure. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+int BitstreamOpen(BitstreamDecVideo *stream, int)
+{
+ int buffer_size = 0;
+ /* set up linear bitstream buffer */
+// stream->currentBytePos = 0;
+ stream->data_end_pos = 0;
+
+ stream->incnt = 0;
+ stream->incnt_next = 0;
+ stream->bitcnt = 0;
+ stream->curr_word = stream->next_word = 0;
+ stream->read_point = stream->data_end_pos;
+ return buffer_size;
+}
+
+
+/* ======================================================================== */
+/* Function : BitstreamClose() */
+/* Purpose : Cleanup the bitstream data structure. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+void BitstreamClose(BitstreamDecVideo *)
+{
+ return;
+}
+
+
+/***********************************************************CommentBegin******
+*
+* -- BitstreamShowBits32HC
+* Shows 32 bits
+***********************************************************CommentEnd********/
+
+PV_STATUS BitstreamShowBits32HC(BitstreamDecVideo *stream, uint32 *code)
+{
+ PV_STATUS status = PV_SUCCESS;
+
+ if (stream->incnt < 32)
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+ }
+ *code = stream->curr_word;
+ return status;
+}
+
+/***********************************************************CommentBegin******
+*
+* -- BitstreamShowBits32
+* Shows upto and including 31 bits
+***********************************************************CommentEnd********/
+PV_STATUS BitstreamShowBits32(BitstreamDecVideo *stream, int nbits, uint32 *code)
+{
+ PV_STATUS status = PV_SUCCESS;
+
+ if (stream->incnt < nbits)
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+ }
+ *code = stream->curr_word >> (32 - nbits);
+ return status;
+}
+
+
+#ifndef PV_BS_INLINE
+/*========================================================================= */
+/* Function: BitstreamShowBits16() */
+/* Date: 12/18/2000 */
+/* Purpose: To see the next "nbits"(nbits<=16) bitstream bits */
+/* without advancing the read pointer */
+/* */
+/* =========================================================================*/
+PV_STATUS BitstreamShowBits16(BitstreamDecVideo *stream, int nbits, uint *code)
+{
+ PV_STATUS status = PV_SUCCESS;
+
+
+ if (stream->incnt < nbits)
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+ }
+
+ *code = stream->curr_word >> (32 - nbits);
+ return status;
+}
+
+
+/*========================================================================= */
+/* Function: BitstreamShow15Bits() */
+/* Date: 01/23/2001 */
+/* Purpose: To see the next 15 bitstream bits */
+/* without advancing the read pointer */
+/* */
+/* =========================================================================*/
+PV_STATUS BitstreamShow15Bits(BitstreamDecVideo *stream, uint *code)
+{
+ PV_STATUS status = PV_SUCCESS;
+
+ if (stream->incnt < 15)
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+ }
+ *code = stream->curr_word >> 17;
+ return status;
+}
+/*========================================================================= */
+/* Function: BitstreamShow13Bits */
+/* Date: 050923 */
+/* Purpose: Faciliate and speed up showing 13 bit from bitstream */
+/* used in VlcTCOEFF decoding */
+/* Modified: */
+/* =========================================================================*/
+PV_STATUS BitstreamShow13Bits(BitstreamDecVideo *stream, uint *code)
+{
+ PV_STATUS status = PV_SUCCESS;
+
+ if (stream->incnt < 13)
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+ }
+ *code = stream->curr_word >> 19;
+ return status;
+}
+
+uint BitstreamReadBits16_INLINE(BitstreamDecVideo *stream, int nbits)
+{
+ uint code;
+ PV_STATUS status;
+
+ if (stream->incnt < nbits)
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+ }
+ code = stream->curr_word >> (32 - nbits);
+ PV_BitstreamFlushBits(stream, nbits);
+ return code;
+}
+
+
+uint BitstreamRead1Bits_INLINE(BitstreamDecVideo *stream)
+{
+ PV_STATUS status = PV_SUCCESS;
+ uint code;
+
+
+ if (stream->incnt < 1)
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+ }
+ code = stream->curr_word >> 31;
+ PV_BitstreamFlushBits(stream, 1);
+
+ return code;
+}
+
+#endif
+
+/* ======================================================================== */
+/* Function : BitstreamReadBits16() */
+/* Purpose : Read bits (nbits <=16) from bitstream buffer. */
+/* In/out : */
+/* Return : */
+/* ======================================================================== */
+uint BitstreamReadBits16(BitstreamDecVideo *stream, int nbits)
+{
+ uint code;
+
+ if (stream->incnt < nbits)
+ {
+ /* frame-based decoding */
+ BitstreamFillCache(stream);
+ }
+ code = stream->curr_word >> (32 - nbits);
+ PV_BitstreamFlushBits(stream, nbits);
+ return code;
+}
+
+/* ======================================================================== */
+/* Function : BitstreamRead1Bits() */
+/* Date : 10/23/2000 */
+/* Purpose : Faciliate and speed up reading 1 bit from bitstream. */
+/* In/out : */
+/* Return : */
+/* ======================================================================== */
+
+uint BitstreamRead1Bits(BitstreamDecVideo *stream)
+{
+ uint code;
+
+ if (stream->incnt < 1)
+ {
+ /* frame-based decoding */
+ BitstreamFillCache(stream);
+ }
+ code = stream->curr_word >> 31;
+ PV_BitstreamFlushBits(stream, 1);
+
+ return code;
+}
+
+/* ======================================================================== */
+/* Function : PV_BitstreamFlushBitsCheck() */
+/* Purpose : Flush nbits bits from bitstream buffer. Check for cache */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+PV_STATUS PV_BitstreamFlushBitsCheck(BitstreamDecVideo *stream, int nbits)
+{
+ PV_STATUS status = PV_SUCCESS;
+
+ stream->bitcnt += nbits;
+ stream->incnt -= nbits;
+ if (stream->incnt < 0)
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+
+ if (stream->incnt < 0)
+ {
+ stream->bitcnt += stream->incnt;
+ stream->incnt = 0;
+ }
+ }
+ stream->curr_word <<= nbits;
+ return status;
+}
+
+/* ======================================================================== */
+/* Function : BitstreamReadBits32() */
+/* Purpose : Read bits from bitstream buffer. */
+/* In/out : */
+/* Return : */
+/* ======================================================================== */
+uint32 BitstreamReadBits32(BitstreamDecVideo *stream, int nbits)
+{
+ uint32 code;
+
+ if (stream->incnt < nbits)
+ {
+ /* frame-based decoding */
+ BitstreamFillCache(stream);
+ }
+ code = stream->curr_word >> (32 - nbits);
+ PV_BitstreamFlushBits(stream, nbits);
+ return code;
+}
+
+uint32 BitstreamReadBits32HC(BitstreamDecVideo *stream)
+{
+ uint32 code;
+
+ BitstreamShowBits32HC(stream, &code);
+ stream->bitcnt += 32;
+ stream->incnt = 0;
+ stream->curr_word = 0;
+ return code;
+}
+
+/* ======================================================================== */
+/* Function : BitstreamCheckEndBuffer() */
+/* Date : 03/30/2001 */
+/* Purpose : Check to see if we are at the end of buffer */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+PV_STATUS BitstreamCheckEndBuffer(BitstreamDecVideo *stream)
+{
+ if (stream->read_point >= stream->data_end_pos && stream->incnt <= 0) return PV_END_OF_VOP;
+ return PV_SUCCESS;
+}
+
+
+PV_STATUS PV_BitstreamShowBitsByteAlign(BitstreamDecVideo *stream, int nbits, uint32 *code)
+{
+ PV_STATUS status = PV_SUCCESS;
+
+ int n_stuffed;
+
+ n_stuffed = 8 - (stream->bitcnt & 0x7); /* 07/05/01 */
+
+ if (stream->incnt < (nbits + n_stuffed))
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+ }
+
+ *code = (stream->curr_word << n_stuffed) >> (32 - nbits);
+ return status;
+}
+
+#ifdef PV_ANNEX_IJKT_SUPPORT
+PV_STATUS PV_BitstreamShowBitsByteAlignNoForceStuffing(BitstreamDecVideo *stream, int nbits, uint32 *code)
+{
+ PV_STATUS status = PV_SUCCESS;
+
+ int n_stuffed;
+
+ n_stuffed = (8 - (stream->bitcnt & 0x7)) & 7;
+
+ if (stream->incnt < (nbits + n_stuffed))
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+ }
+
+ *code = (stream->curr_word << n_stuffed) >> (32 - nbits);
+ return status;
+}
+#endif
+
+PV_STATUS PV_BitstreamByteAlign(BitstreamDecVideo *stream)
+{
+ PV_STATUS status = PV_SUCCESS;
+ int n_stuffed;
+
+ n_stuffed = 8 - (stream->bitcnt & 0x7); /* 07/05/01 */
+
+ /* We have to make sure we have enough bits in the cache. 08/15/2000 */
+ if (stream->incnt < n_stuffed)
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+ }
+
+
+ stream->bitcnt += n_stuffed;
+ stream->incnt -= n_stuffed;
+ stream->curr_word <<= n_stuffed;
+ if (stream->incnt < 0)
+ {
+ stream->bitcnt += stream->incnt;
+ stream->incnt = 0;
+ }
+ return status;
+}
+
+
+PV_STATUS BitstreamByteAlignNoForceStuffing(BitstreamDecVideo *stream)
+{
+ uint n_stuffed;
+
+ n_stuffed = (8 - (stream->bitcnt & 0x7)) & 0x7; /* 07/05/01 */
+
+ stream->bitcnt += n_stuffed;
+ stream->incnt -= n_stuffed;
+
+ if (stream->incnt < 0)
+ {
+ stream->bitcnt += stream->incnt;
+ stream->incnt = 0;
+ }
+ stream->curr_word <<= n_stuffed;
+ return PV_SUCCESS;
+}
+
+
+/* ==================================================================== */
+/* Function : getPointer() */
+/* Date : 10/98 */
+/* Purpose : get current position of file pointer */
+/* In/out : */
+/* Return : */
+/* ==================================================================== */
+int32 getPointer(BitstreamDecVideo *stream)
+{
+ return stream->bitcnt;
+}
+
+
+
+
+/* ====================================================================== /
+Function : movePointerTo()
+Date : 05/14/2004
+Purpose : move bitstream pointer to a desired position
+In/out :
+Return :
+Modified :
+/ ====================================================================== */
+PV_STATUS movePointerTo(BitstreamDecVideo *stream, int32 pos)
+{
+ int32 byte_pos;
+ if (pos < 0)
+ {
+ pos = 0;
+ }
+
+ byte_pos = pos >> 3;
+
+ if (byte_pos > stream->data_end_pos)
+ {
+ byte_pos = stream->data_end_pos;
+ }
+
+ stream->read_point = byte_pos & -4;
+ stream->bitcnt = stream->read_point << 3;;
+ stream->curr_word = 0;
+ stream->next_word = 0;
+ stream->incnt = 0;
+ stream->incnt_next = 0;
+ BitstreamFillCache(stream);
+ PV_BitstreamFlushBits(stream, ((pos & 0x7) + ((byte_pos & 0x3) << 3)));
+ return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/* Function : validStuffing() */
+/* Date : 04/11/2000 */
+/* Purpose : Check whether we have valid stuffing at current position. */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : 12/18/2000 : changed the pattern type to uint */
+/* 04/01/2001 : removed PV_END_OF_BUFFER */
+/* ======================================================================== */
+Bool validStuffing(BitstreamDecVideo *stream)
+{
+ uint n_stuffed;
+ uint pattern;
+
+
+ n_stuffed = 8 - (stream->bitcnt & 0x7);
+ BitstreamShowBits16(stream, n_stuffed, &pattern);
+ if (pattern == msk[n_stuffed-1]) return PV_TRUE;
+ return PV_FALSE;
+}
+#ifdef PV_ANNEX_IJKT_SUPPORT
+Bool validStuffing_h263(BitstreamDecVideo *stream)
+{
+ uint n_stuffed;
+ uint pattern;
+
+
+ n_stuffed = (8 - (stream->bitcnt & 0x7)) & 7; // stream->incnt % 8
+ if (n_stuffed == 0)
+ {
+ return PV_TRUE;
+ }
+ BitstreamShowBits16(stream, n_stuffed, &pattern);
+ if (pattern == 0) return PV_TRUE;
+ return PV_FALSE;
+}
+#endif
+
+
+/* ======================================================================== */
+/* Function : PVSearchNextH263Frame() */
+/* Date : 04/08/2005 */
+/* Purpose : search for 0x00 0x00 0x80 */
+/* In/out : */
+/* Return : PV_SUCCESS if succeeded or PV_END_OF_VOP if failed */
+/* Modified : */
+/* ======================================================================== */
+PV_STATUS PVSearchNextH263Frame(BitstreamDecVideo *stream)
+{
+ PV_STATUS status = PV_SUCCESS;
+ uint8 *ptr;
+ int32 i;
+ int32 initial_byte_aligned_position = (stream->bitcnt + 7) >> 3;
+
+ ptr = stream->bitstreamBuffer + initial_byte_aligned_position;
+
+ i = PVLocateH263FrameHeader(ptr, stream->data_end_pos - initial_byte_aligned_position);
+ if (stream->data_end_pos <= initial_byte_aligned_position + i)
+ {
+ status = PV_END_OF_VOP;
+ }
+ (void)movePointerTo(stream, ((i + initial_byte_aligned_position) << 3)); /* ptr + i */
+ return status;
+}
+
+
+/* ======================================================================== */
+/* Function : PVSearchNextM4VFrame() */
+/* Date : 04/08/2005 */
+/* Purpose : search for 0x00 0x00 0x01 and move the pointer to the */
+/* beginning of the start code */
+/* In/out : */
+/* Return : PV_SUCCESS if succeeded or PV_END_OF_VOP if failed */
+/* Modified : */
+/* ======================================================================== */
+
+PV_STATUS PVSearchNextM4VFrame(BitstreamDecVideo *stream)
+{
+ PV_STATUS status = PV_SUCCESS;
+ uint8 *ptr;
+ int32 i;
+ int32 initial_byte_aligned_position = (stream->bitcnt + 7) >> 3;
+
+ ptr = stream->bitstreamBuffer + initial_byte_aligned_position;
+
+ i = PVLocateFrameHeader(ptr, stream->data_end_pos - initial_byte_aligned_position);
+ if (stream->data_end_pos <= initial_byte_aligned_position + i)
+ {
+ status = PV_END_OF_VOP;
+ }
+ (void)movePointerTo(stream, ((i + initial_byte_aligned_position) << 3)); /* ptr + i */
+ return status;
+}
+
+
+
+void PVLocateM4VFrameBoundary(BitstreamDecVideo *stream)
+{
+ uint8 *ptr;
+ int32 byte_pos = (stream->bitcnt >> 3);
+
+ stream->searched_frame_boundary = 1;
+ ptr = stream->bitstreamBuffer + byte_pos;
+
+ stream->data_end_pos = PVLocateFrameHeader(ptr, (int32)stream->data_end_pos - byte_pos) + byte_pos;
+}
+
+void PVLocateH263FrameBoundary(BitstreamDecVideo *stream)
+{
+ uint8 *ptr;
+ int32 byte_pos = (stream->bitcnt >> 3);
+
+ stream->searched_frame_boundary = 1;
+ ptr = stream->bitstreamBuffer + byte_pos;
+
+ stream->data_end_pos = PVLocateH263FrameHeader(ptr, (int32)stream->data_end_pos - byte_pos) + byte_pos;
+}
+
+/* ======================================================================== */
+/* Function : quickSearchVideoPacketHeader() */
+/* Date : 05/08/2000 */
+/* Purpose : Quick search for the next video packet header */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* ======================================================================== */
+PV_STATUS quickSearchVideoPacketHeader(BitstreamDecVideo *stream, int marker_length)
+{
+ PV_STATUS status = PV_SUCCESS;
+ uint32 tmpvar;
+
+
+ if (stream->searched_frame_boundary == 0)
+ {
+ PVLocateM4VFrameBoundary(stream);
+ }
+
+ do
+ {
+ status = BitstreamCheckEndBuffer(stream);
+ if (status == PV_END_OF_VOP) break;
+ PV_BitstreamShowBitsByteAlign(stream, marker_length, &tmpvar);
+ if (tmpvar == RESYNC_MARKER) break;
+ PV_BitstreamFlushBits(stream, 8);
+ }
+ while (status == PV_SUCCESS);
+
+ return status;
+}
+#ifdef PV_ANNEX_IJKT_SUPPORT
+PV_STATUS quickSearchH263SliceHeader(BitstreamDecVideo *stream)
+{
+ PV_STATUS status = PV_SUCCESS;
+ uint32 tmpvar;
+
+
+ if (stream->searched_frame_boundary == 0)
+ {
+ PVLocateH263FrameBoundary(stream);
+ }
+
+ do
+ {
+ status = BitstreamCheckEndBuffer(stream);
+ if (status == PV_END_OF_VOP) break;
+ PV_BitstreamShowBitsByteAlignNoForceStuffing(stream, 17, &tmpvar);
+ if (tmpvar == RESYNC_MARKER) break;
+ PV_BitstreamFlushBits(stream, 8);
+ }
+ while (status == PV_SUCCESS);
+
+ return status;
+}
+#endif
+/* ======================================================================== */
+/* The following functions are for Error Concealment. */
+/* ======================================================================== */
+
+/****************************************************/
+// 01/22/99 Quick search of Resync Marker
+// (actually the first part of it, i.e. 16 0's and a 1.
+
+/* We are not using the fastest algorithm possible. What this function does is
+to locate 11 consecutive 0's and then check if the 5 bits before them and
+the 1 bit after them are all 1's.
+*/
+
+// Table used for quick search of markers. Gives the last `1' in
+// 4 bits. The MSB is bit #1, the LSB is bit #4.
+const int lastOne[] =
+{
+ 0, 4, 3, 4, 2, 4, 3, 4,
+ 1, 4, 3, 4, 2, 4, 3, 4
+};
+
+// Table used for quick search of markers. Gives the last `0' in
+// 4 bits. The MSB is bit #1, the LSB is bit #4.
+/*const int lastZero[]=
+{
+ 4, 3, 4, 2, 4, 3, 4, 1,
+ 4, 3, 4, 2, 4, 3, 4, 0
+};
+*/
+// Table used for quick search of markers. Gives the first `0' in
+// 4 bits. The MSB is bit #1, the LSB is bit #4.
+const int firstZero[] =
+{
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 3, 3, 4, 0
+};
+
+// Table used for quick search of markers. Gives the first `1' in
+// 4 bits. The MSB is bit #1, the LSB is bit #4.
+const int firstOne[] =
+{
+ 0, 4, 3, 3, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+
+/* ======================================================================== */
+/* Function : quickSearchMarkers() */
+/* Date : 01/25/99 */
+/* Purpose : Quick search for Motion marker */
+/* In/out : */
+/* Return : Boolean true of false */
+/* Modified : 12/18/2000 : 32-bit version */
+/* ======================================================================== */
+PV_STATUS quickSearchMotionMarker(BitstreamDecVideo *stream)
+// MM: (11111000000000001)
+{
+ PV_STATUS status;
+ uint32 tmpvar, tmpvar2;
+
+ if (stream->searched_frame_boundary == 0)
+ {
+ PVLocateM4VFrameBoundary(stream);
+ }
+
+ while (TRUE)
+ {
+ status = BitstreamCheckEndBuffer(stream);
+ if (status == PV_END_OF_VOP) return PV_END_OF_VOP;
+
+ BitstreamShowBits32(stream, 17, &tmpvar);
+ if (!tmpvar) return PV_FAIL;
+
+ if (tmpvar & 1) // Check if the 17th bit from the curr bit pos is a '1'
+ {
+ if (tmpvar == MOTION_MARKER_COMB)
+ {
+ return PV_SUCCESS; // Found
+ }
+ else
+ {
+ tmpvar >>= 1;
+ tmpvar &= 0xF;
+ PV_BitstreamFlushBits(stream, (int)(12 + firstZero[tmpvar]));
+ }
+ }
+ else
+ {
+ // 01/25/99 Get the first 16 bits
+ tmpvar >>= 1;
+ tmpvar2 = tmpvar & 0xF;
+
+ // 01/26/99 Check bits #13 ~ #16
+ if (tmpvar2)
+ {
+ PV_BitstreamFlushBits(stream, (int)(7 + lastOne[tmpvar2]));
+ }
+ else
+ {
+ tmpvar >>= 4;
+ tmpvar2 = tmpvar & 0xF;
+
+ // 01/26/99 Check bits #9 ~ #12
+ if (tmpvar2)
+ {
+ PV_BitstreamFlushBits(stream, (int)(3 + lastOne[tmpvar2]));
+ }
+ else
+ {
+ tmpvar >>= 4;
+ tmpvar2 = tmpvar & 0xF;
+
+ // 01/26/99 Check bits #5 ~ #8
+ // We don't need to check further
+ // for the first 5 bits should be all 1's
+ if (lastOne[tmpvar2] < 2)
+ {
+ /* we already have too many consecutive 0's. */
+ /* Go directly pass the last of the 17 bits. */
+ PV_BitstreamFlushBits(stream, 17);
+ }
+ else
+ {
+ PV_BitstreamFlushBits(stream, (int)(lastOne[tmpvar2] - 1));
+ }
+ }
+ }
+ }
+
+ }
+}
+
+/* ======================================================================== */
+/* Function : quickSearchDCM() */
+/* Date : 01/22/99 */
+/* Purpose : Quick search for DC Marker */
+/* We are not using the fastest algorithm possible. What this */
+/* function does is to locate 11 consecutive 0's and then */
+/* check if the 7 bits before them and the 1 bit after them */
+/* are correct. (actually the first part of it, i.e. 16 0's */
+/* and a 1. */
+/* In/out : */
+/* Return : Boolean true of false */
+/* Modified : 12/18/2000 : 32-bit version */
+/* ======================================================================== */
+PV_STATUS quickSearchDCM(BitstreamDecVideo *stream)
+// DCM: (110 1011 0000 0000 0001)
+{
+ PV_STATUS status;
+ uint32 tmpvar, tmpvar2;
+
+ if (stream->searched_frame_boundary == 0)
+ {
+ PVLocateM4VFrameBoundary(stream);
+ }
+
+ while (TRUE)
+ {
+ status = BitstreamCheckEndBuffer(stream);
+ if (status == PV_END_OF_VOP) return PV_END_OF_VOP;
+ BitstreamShowBits32(stream, 19, &tmpvar);
+
+ if (tmpvar & 1) // Check if the 17th bit from the curr bit pos is a '1'
+ {
+ if (tmpvar == DC_MARKER)
+ {
+ return PV_SUCCESS; // Found
+ }
+ else
+ {
+ // 01/25/99 We treat the last of the 19 bits as its 7th bit (which is
+ // also a `1'
+ PV_BitstreamFlushBits(stream, 12);
+ }
+ }
+ else
+ {
+ tmpvar >>= 1;
+ tmpvar2 = tmpvar & 0xF;
+
+ if (tmpvar2)
+ {
+ PV_BitstreamFlushBits(stream, (int)(7 + lastOne[tmpvar2]));
+ }
+ else
+ {
+ tmpvar >>= 4;
+ tmpvar2 = tmpvar & 0xF;
+ if (tmpvar2)
+ {
+ PV_BitstreamFlushBits(stream, (int)(3 + lastOne[tmpvar2]));
+ }
+ else
+ {
+ tmpvar >>= 4;
+ tmpvar2 = tmpvar & 0xF;
+ if (lastOne[tmpvar2] < 2)
+ {
+ /* we already have too many consecutive 0's. */
+ /* Go directly pass the last of the 17 bits. */
+ PV_BitstreamFlushBits(stream, 19);
+ }
+ else
+ {
+ PV_BitstreamFlushBits(stream, (int)(lastOne[tmpvar2] - 1));
+ }
+ }
+ }
+ }
+ }
+}
+
+/* ======================================================================== */
+/* Function : quickSearchGOBHeader() 0000 0000 0000 0000 1 */
+/* Date : 07/06/01 */
+/* Purpose : Quick search of GOBHeader (not byte aligned) */
+/* In/out : */
+/* Return : Integer value indicates type of marker found */
+/* Modified : */
+/* ======================================================================== */
+PV_STATUS quickSearchGOBHeader(BitstreamDecVideo *stream)
+{
+ PV_STATUS status;
+ int byte0, byte1, byte2, shift, tmpvar;
+
+ BitstreamByteAlignNoForceStuffing(stream);
+
+ if (stream->searched_frame_boundary == 0)
+ {
+ PVLocateH263FrameBoundary(stream);
+ }
+
+ while (TRUE)
+ {
+ status = BitstreamCheckEndBuffer(stream);
+ if (status == PV_END_OF_VOP) return PV_END_OF_VOP;
+
+ if (stream->incnt < 24)
+ {
+ status = BitstreamFillCache(stream);
+ }
+
+
+ byte1 = (stream->curr_word << 8) >> 24;
+ if (byte1 == 0)
+ {
+ byte2 = (stream->curr_word << 16) >> 24;
+ if (byte2)
+ {
+ tmpvar = byte2 >> 4;
+
+ if (tmpvar)
+ {
+ shift = 9 - firstOne[tmpvar];
+ }
+ else
+ {
+ shift = 5 - firstOne[byte2];
+ }
+ byte0 = stream->curr_word >> 24;
+ if ((byte0 & msk[shift]) == 0)
+ {
+ PV_BitstreamFlushBits(stream, 8 - shift);
+ return PV_SUCCESS;
+ }
+ PV_BitstreamFlushBits(stream, 8); /* third_byte is not zero */
+ }
+ }
+
+ PV_BitstreamFlushBits(stream, 8);
+ }
+}
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.h b/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.h
new file mode 100644
index 0000000..d52fa87
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/bitstream.h
@@ -0,0 +1,174 @@
+/* ------------------------------------------------------------------
+ * 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_D_H_
+#define _BITSTREAM_D_H_
+
+#include "mp4dec_lib.h" /* video decoder function prototypes */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#define PV_BS_INLINE /* support inline bitstream functions */
+
+#define PV_BitstreamFlushBits(A,B) {(A)->bitcnt += (B); (A)->incnt -= (B); (A)->curr_word <<= (B);}
+
+ PV_STATUS BitstreamFillBuffer(BitstreamDecVideo *stream);
+ PV_STATUS BitstreamFillCache(BitstreamDecVideo *stream);
+ void BitstreamReset(BitstreamDecVideo *stream, uint8 *buffer, int32 buffer_size);
+ int BitstreamOpen(BitstreamDecVideo *stream, int layer);
+ void BitstreamClose(BitstreamDecVideo *stream);
+
+ PV_STATUS BitstreamShowBits32(BitstreamDecVideo *stream, int nbits, uint32 *code);
+ uint32 BitstreamReadBits32(BitstreamDecVideo *stream, int nbits);
+
+ uint BitstreamReadBits16(BitstreamDecVideo *stream, int nbits);
+ uint BitstreamRead1Bits(BitstreamDecVideo *stream);
+#ifndef PV_BS_INLINE
+ PV_STATUS BitstreamShowBits16(BitstreamDecVideo *stream, int nbits, uint *code);
+ PV_STATUS BitstreamShow15Bits(BitstreamDecVideo *stream, uint *code);
+ PV_STATUS BitstreamShow13Bits(BitstreamDecVideo *stream, uint *code);
+ uint BitstreamReadBits16_INLINE(BitstreamDecVideo *stream, int nbits);
+ uint BitstreamRead1Bits_INLINE(BitstreamDecVideo *stream);
+#else
+ __inline PV_STATUS BitstreamShowBits16(BitstreamDecVideo *stream, int nbits, uint *code)
+ {
+ PV_STATUS status = PV_SUCCESS;
+
+
+ if (stream->incnt < nbits)
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+ }
+
+ *code = stream->curr_word >> (32 - nbits);
+ return status;
+ }
+
+
+
+ /* =========================================================================*/
+ __inline PV_STATUS BitstreamShow15Bits(BitstreamDecVideo *stream, uint *code)
+ {
+ PV_STATUS status = PV_SUCCESS;
+
+ if (stream->incnt < 15)
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+ }
+ *code = stream->curr_word >> 17;
+ return status;
+ }
+
+
+ __inline PV_STATUS BitstreamShow13Bits(BitstreamDecVideo *stream, uint *code)
+ {
+ PV_STATUS status = PV_SUCCESS;
+
+ if (stream->incnt < 13)
+ {
+ /* frame-based decoding */
+ status = BitstreamFillCache(stream);
+ }
+ *code = stream->curr_word >> 19;
+ return status;
+ }
+ __inline uint BitstreamReadBits16_INLINE(BitstreamDecVideo *stream, int nbits)
+ {
+ uint code;
+
+ if (stream->incnt < nbits)
+ {
+ /* frame-based decoding */
+ BitstreamFillCache(stream);
+ }
+ code = stream->curr_word >> (32 - nbits);
+ PV_BitstreamFlushBits(stream, nbits);
+ return code;
+ }
+
+
+ __inline uint BitstreamRead1Bits_INLINE(BitstreamDecVideo *stream)
+ {
+ uint code;
+
+ if (stream->incnt < 1)
+ {
+ /* frame-based decoding */
+ BitstreamFillCache(stream);
+ }
+ code = stream->curr_word >> 31;
+ PV_BitstreamFlushBits(stream, 1);
+
+ return code;
+ }
+
+#endif
+
+
+
+
+
+
+
+ PV_STATUS PV_BitstreamFlushBitsCheck(BitstreamDecVideo *stream, int nbits);
+
+ uint32 BitstreamReadBits32HC(BitstreamDecVideo *stream);
+ PV_STATUS BitstreamShowBits32HC(BitstreamDecVideo *stream, uint32 *code);
+
+
+
+ PV_STATUS BitstreamCheckEndBuffer(BitstreamDecVideo *stream);
+
+ PV_STATUS PV_BitstreamShowBitsByteAlign(BitstreamDecVideo *stream, int nbits, uint32 *code);
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ PV_STATUS PV_BitstreamShowBitsByteAlignNoForceStuffing(BitstreamDecVideo *stream, int nbits, uint32 *code);
+ Bool validStuffing_h263(BitstreamDecVideo *stream);
+ PV_STATUS quickSearchH263SliceHeader(BitstreamDecVideo *stream);
+#endif
+ PV_STATUS PV_BitstreamByteAlign(BitstreamDecVideo *stream);
+ PV_STATUS BitstreamByteAlignNoForceStuffing(BitstreamDecVideo *stream);
+ Bool validStuffing(BitstreamDecVideo *stream);
+
+ PV_STATUS movePointerTo(BitstreamDecVideo *stream, int32 pos);
+ PV_STATUS PVSearchNextM4VFrame(BitstreamDecVideo *stream);
+ PV_STATUS PVSearchNextH263Frame(BitstreamDecVideo *stream);
+ PV_STATUS quickSearchVideoPacketHeader(BitstreamDecVideo *stream, int marker_length);
+
+
+ /* for error concealment & soft-decoding */
+ void PVLocateM4VFrameBoundary(BitstreamDecVideo *stream);
+ void PVSearchH263FrameBoundary(BitstreamDecVideo *stream);
+
+ PV_STATUS quickSearchMotionMarker(BitstreamDecVideo *stream);
+ PV_STATUS quickSearchDCM(BitstreamDecVideo *stream);
+ PV_STATUS quickSearchGOBHeader(BitstreamDecVideo *stream);
+ void BitstreamShowBuffer(BitstreamDecVideo *stream, int32 startbit, int32 endbit, uint8 *bitBfr);
+
+ /* 10/8/98 New prototyps. */
+ int32 getPointer(BitstreamDecVideo *stream);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _BITSTREAM_D_H_ */
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/block_idct.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/block_idct.cpp
new file mode 100644
index 0000000..a75483a
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/block_idct.cpp
@@ -0,0 +1,911 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ [input_variable_name] = [description of the input to module, its type
+ definition, and length (when applicable)]
+
+ Local Stores/Buffers/Pointers Needed:
+ [local_store_name] = [description of the local store, its type
+ definition, and length (when applicable)]
+ [local_buffer_name] = [description of the local buffer, its type
+ definition, and length (when applicable)]
+ [local_ptr_name] = [description of the local pointer, its type
+ definition, and length (when applicable)]
+
+ Global Stores/Buffers/Pointers Needed:
+ [global_store_name] = [description of the global store, its type
+ definition, and length (when applicable)]
+ [global_buffer_name] = [description of the global buffer, its type
+ definition, and length (when applicable)]
+ [global_ptr_name] = [description of the global pointer, its type
+ definition, and length (when applicable)]
+
+ Outputs:
+ [return_variable_name] = [description of data/pointer returned
+ by module, its type definition, and length
+ (when applicable)]
+
+ Pointers and Buffers Modified:
+ [variable_bfr_ptr] points to the [describe where the
+ variable_bfr_ptr points to, its type definition, and length
+ (when applicable)]
+ [variable_bfr] contents are [describe the new contents of
+ variable_bfr]
+
+ Local Stores Modified:
+ [local_store_name] = [describe new contents, its type
+ definition, and length (when applicable)]
+
+ Global Stores Modified:
+ [global_store_name] = [describe new contents, its type
+ definition, and length (when applicable)]
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+#include "idct.h"
+#include "motion_comp.h"
+
+#define OSCL_DISABLE_WARNING_CONV_POSSIBLE_LOSS_OF_DATA
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+/* private prototypes */
+static void idctrow(int16 *blk, uint8 *pred, uint8 *dst, int width);
+static void idctrow_intra(int16 *blk, PIXEL *, int width);
+static void idctcol(int16 *blk);
+
+#ifdef FAST_IDCT
+// mapping from nz_coefs to functions to be used
+
+
+// ARM4 does not allow global data when they are not constant hence
+// an array of function pointers cannot be considered as array of constants
+// (actual addresses are only known when the dll is loaded).
+// So instead of arrays of function pointers, we'll store here
+// arrays of rows or columns and then call the idct function
+// corresponding to such the row/column number:
+
+
+static void (*const idctcolVCA[10][4])(int16*) =
+{
+ {&idctcol1, &idctcol0, &idctcol0, &idctcol0},
+ {&idctcol1, &idctcol1, &idctcol0, &idctcol0},
+ {&idctcol2, &idctcol1, &idctcol0, &idctcol0},
+ {&idctcol3, &idctcol1, &idctcol0, &idctcol0},
+ {&idctcol3, &idctcol2, &idctcol0, &idctcol0},
+ {&idctcol3, &idctcol2, &idctcol1, &idctcol0},
+ {&idctcol3, &idctcol2, &idctcol1, &idctcol1},
+ {&idctcol3, &idctcol2, &idctcol2, &idctcol1},
+ {&idctcol3, &idctcol3, &idctcol2, &idctcol1},
+ {&idctcol4, &idctcol3, &idctcol2, &idctcol1}
+};
+
+
+static void (*const idctrowVCA[10])(int16*, uint8*, uint8*, int) =
+{
+ &idctrow1,
+ &idctrow2,
+ &idctrow2,
+ &idctrow2,
+ &idctrow2,
+ &idctrow3,
+ &idctrow4,
+ &idctrow4,
+ &idctrow4,
+ &idctrow4
+};
+
+
+static void (*const idctcolVCA2[16])(int16*) =
+{
+ &idctcol0, &idctcol4, &idctcol3, &idctcol4,
+ &idctcol2, &idctcol4, &idctcol3, &idctcol4,
+ &idctcol1, &idctcol4, &idctcol3, &idctcol4,
+ &idctcol2, &idctcol4, &idctcol3, &idctcol4
+};
+
+static void (*const idctrowVCA2[8])(int16*, uint8*, uint8*, int) =
+{
+ &idctrow1, &idctrow4, &idctrow3, &idctrow4,
+ &idctrow2, &idctrow4, &idctrow3, &idctrow4
+};
+
+static void (*const idctrowVCA_intra[10])(int16*, PIXEL *, int) =
+{
+ &idctrow1_intra,
+ &idctrow2_intra,
+ &idctrow2_intra,
+ &idctrow2_intra,
+ &idctrow2_intra,
+ &idctrow3_intra,
+ &idctrow4_intra,
+ &idctrow4_intra,
+ &idctrow4_intra,
+ &idctrow4_intra
+};
+
+static void (*const idctrowVCA2_intra[8])(int16*, PIXEL *, int) =
+{
+ &idctrow1_intra, &idctrow4_intra, &idctrow3_intra, &idctrow4_intra,
+ &idctrow2_intra, &idctrow4_intra, &idctrow3_intra, &idctrow4_intra
+};
+#endif
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void MBlockIDCT(VideoDecData *video)
+{
+ Vop *currVop = video->currVop;
+ MacroBlock *mblock = video->mblock;
+ PIXEL *c_comp;
+ PIXEL *cu_comp;
+ PIXEL *cv_comp;
+ int x_pos = video->mbnum_col;
+ int y_pos = video->mbnum_row;
+ int width, width_uv;
+ int32 offset;
+ width = video->width;
+ width_uv = width >> 1;
+ offset = (int32)(y_pos << 4) * width + (x_pos << 4);
+
+ c_comp = currVop->yChan + offset;
+ cu_comp = currVop->uChan + (offset >> 2) + (x_pos << 2);
+ cv_comp = currVop->vChan + (offset >> 2) + (x_pos << 2);
+
+ BlockIDCT_intra(mblock, c_comp, 0, width);
+ BlockIDCT_intra(mblock, c_comp + 8, 1, width);
+ BlockIDCT_intra(mblock, c_comp + (width << 3), 2, width);
+ BlockIDCT_intra(mblock, c_comp + (width << 3) + 8, 3, width);
+ BlockIDCT_intra(mblock, cu_comp, 4, width_uv);
+ BlockIDCT_intra(mblock, cv_comp, 5, width_uv);
+}
+
+
+void BlockIDCT_intra(
+ MacroBlock *mblock, PIXEL *c_comp, int comp, int width)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int16 *coeff_in = mblock->block[comp];
+#ifdef INTEGER_IDCT
+#ifdef FAST_IDCT /* VCA IDCT using nzcoefs and bitmaps*/
+ int i, bmapr;
+ int nz_coefs = mblock->no_coeff[comp];
+ uint8 *bitmapcol = mblock->bitmapcol[comp];
+ uint8 bitmaprow = mblock->bitmaprow[comp];
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ if (nz_coefs <= 10)
+ {
+ bmapr = (nz_coefs - 1);
+
+ (*(idctcolVCA[bmapr]))(coeff_in);
+ (*(idctcolVCA[bmapr][1]))(coeff_in + 1);
+ (*(idctcolVCA[bmapr][2]))(coeff_in + 2);
+ (*(idctcolVCA[bmapr][3]))(coeff_in + 3);
+
+ (*idctrowVCA_intra[nz_coefs-1])(coeff_in, c_comp, width);
+ }
+ else
+ {
+ i = 8;
+ while (i--)
+ {
+ bmapr = (int)bitmapcol[i];
+ if (bmapr)
+ {
+ if ((bmapr&0xf) == 0) /* 07/18/01 */
+ {
+ (*(idctcolVCA2[bmapr>>4]))(coeff_in + i);
+ }
+ else
+ {
+ idctcol(coeff_in + i);
+ }
+ }
+ }
+ if ((bitmapcol[4] | bitmapcol[5] | bitmapcol[6] | bitmapcol[7]) == 0)
+ {
+ bitmaprow >>= 4;
+ (*(idctrowVCA2_intra[(int)bitmaprow]))(coeff_in, c_comp, width);
+ }
+ else
+ {
+ idctrow_intra(coeff_in, c_comp, width);
+ }
+ }
+#else
+ void idct_intra(int *block, uint8 *comp, int width);
+ idct_intra(coeff_in, c_comp, width);
+#endif
+#else
+ void idctref_intra(int *block, uint8 *comp, int width);
+ idctref_intra(coeff_in, c_comp, width);
+#endif
+
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+
+/* 08/04/05, no residue, just copy from pred to output */
+void Copy_Blk_to_Vop(uint8 *dst, uint8 *pred, int width)
+{
+ /* copy 4 bytes at a time */
+ width -= 4;
+ *((uint32*)dst) = *((uint32*)pred);
+ *((uint32*)(dst += 4)) = *((uint32*)(pred += 4));
+ *((uint32*)(dst += width)) = *((uint32*)(pred += 12));
+ *((uint32*)(dst += 4)) = *((uint32*)(pred += 4));
+ *((uint32*)(dst += width)) = *((uint32*)(pred += 12));
+ *((uint32*)(dst += 4)) = *((uint32*)(pred += 4));
+ *((uint32*)(dst += width)) = *((uint32*)(pred += 12));
+ *((uint32*)(dst += 4)) = *((uint32*)(pred += 4));
+ *((uint32*)(dst += width)) = *((uint32*)(pred += 12));
+ *((uint32*)(dst += 4)) = *((uint32*)(pred += 4));
+ *((uint32*)(dst += width)) = *((uint32*)(pred += 12));
+ *((uint32*)(dst += 4)) = *((uint32*)(pred += 4));
+ *((uint32*)(dst += width)) = *((uint32*)(pred += 12));
+ *((uint32*)(dst += 4)) = *((uint32*)(pred += 4));
+ *((uint32*)(dst += width)) = *((uint32*)(pred += 12));
+ *((uint32*)(dst += 4)) = *((uint32*)(pred += 4));
+
+ return ;
+}
+
+/* 08/04/05 compute IDCT and add prediction at the end */
+void BlockIDCT(
+ uint8 *dst, /* destination */
+ uint8 *pred, /* prediction block, pitch 16 */
+ int16 *coeff_in, /* DCT data, size 64 */
+ int width, /* width of dst */
+ int nz_coefs,
+ uint8 *bitmapcol,
+ uint8 bitmaprow
+)
+{
+#ifdef INTEGER_IDCT
+#ifdef FAST_IDCT /* VCA IDCT using nzcoefs and bitmaps*/
+ int i, bmapr;
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ if (nz_coefs <= 10)
+ {
+ bmapr = (nz_coefs - 1);
+ (*(idctcolVCA[bmapr]))(coeff_in);
+ (*(idctcolVCA[bmapr][1]))(coeff_in + 1);
+ (*(idctcolVCA[bmapr][2]))(coeff_in + 2);
+ (*(idctcolVCA[bmapr][3]))(coeff_in + 3);
+
+ (*idctrowVCA[nz_coefs-1])(coeff_in, pred, dst, width);
+ return ;
+ }
+ else
+ {
+ i = 8;
+
+ while (i--)
+ {
+ bmapr = (int)bitmapcol[i];
+ if (bmapr)
+ {
+ if ((bmapr&0xf) == 0) /* 07/18/01 */
+ {
+ (*(idctcolVCA2[bmapr>>4]))(coeff_in + i);
+ }
+ else
+ {
+ idctcol(coeff_in + i);
+ }
+ }
+ }
+ if ((bitmapcol[4] | bitmapcol[5] | bitmapcol[6] | bitmapcol[7]) == 0)
+ {
+ (*(idctrowVCA2[bitmaprow>>4]))(coeff_in, pred, dst, width);
+ }
+ else
+ {
+ idctrow(coeff_in, pred, dst, width);
+ }
+ return ;
+ }
+#else // FAST_IDCT
+ void idct(int *block, uint8 *pred, uint8 *dst, int width);
+ idct(coeff_in, pred, dst, width);
+ return;
+#endif // FAST_IDCT
+#else // INTEGER_IDCT
+ void idctref(int *block, uint8 *pred, uint8 *dst, int width);
+ idctref(coeff_in, pred, dst, width);
+ return;
+#endif // INTEGER_IDCT
+
+}
+/*----------------------------------------------------------------------------
+; End Function: block_idct
+----------------------------------------------------------------------------*/
+
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: idctrow
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS FOR idctrow
+
+ Inputs:
+ [input_variable_name] = [description of the input to module, its type
+ definition, and length (when applicable)]
+
+ Local Stores/Buffers/Pointers Needed:
+ [local_store_name] = [description of the local store, its type
+ definition, and length (when applicable)]
+ [local_buffer_name] = [description of the local buffer, its type
+ definition, and length (when applicable)]
+ [local_ptr_name] = [description of the local pointer, its type
+ definition, and length (when applicable)]
+
+ Global Stores/Buffers/Pointers Needed:
+ [global_store_name] = [description of the global store, its type
+ definition, and length (when applicable)]
+ [global_buffer_name] = [description of the global buffer, its type
+ definition, and length (when applicable)]
+ [global_ptr_name] = [description of the global pointer, its type
+ definition, and length (when applicable)]
+
+ Outputs:
+ [return_variable_name] = [description of data/pointer returned
+ by module, its type definition, and length
+ (when applicable)]
+
+ Pointers and Buffers Modified:
+ [variable_bfr_ptr] points to the [describe where the
+ variable_bfr_ptr points to, its type definition, and length
+ (when applicable)]
+ [variable_bfr] contents are [describe the new contents of
+ variable_bfr]
+
+ Local Stores Modified:
+ [local_store_name] = [describe new contents, its type
+ definition, and length (when applicable)]
+
+ Global Stores Modified:
+ [global_store_name] = [describe new contents, its type
+ definition, and length (when applicable)]
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION FOR idctrow
+
+------------------------------------------------------------------------------
+ REQUIREMENTS FOR idctrow
+
+------------------------------------------------------------------------------
+ REFERENCES FOR idctrow
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE FOR idctrow
+
+------------------------------------------------------------------------------
+ RESOURCES USED FOR idctrow
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; Function Code FOR idctrow
+----------------------------------------------------------------------------*/
+void idctrow(
+ int16 *blk, uint8 *pred, uint8 *dst, int width
+)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* row (horizontal) IDCT
+ *
+ * 7 pi 1 dst[k] = sum c[l] * src[l] * cos( -- *
+ * ( k + - ) * l ) l=0 8 2
+ *
+ * where: c[0] = 128 c[1..7] = 128*sqrt(2) */
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ width -= 4;
+ dst -= width;
+ pred -= 12;
+ 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] = 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 += 12)); /* 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*)(dst += width)) = 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*)(dst += 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+
+void idctrow_intra(
+ int16 *blk, PIXEL *comp, int width
+)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8, temp;
+ int i = 8;
+ int offset = width;
+ int32 word;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* row (horizontal) IDCT
+ *
+ * 7 pi 1 dst[k] = sum c[l] * src[l] * cos( -- *
+ * ( k + - ) * l ) l=0 8 2
+ *
+ * where: c[0] = 128 c[1..7] = 128*sqrt(2) */
+ while (i--)
+ {
+ x1 = (int32)blk[4] << 8;
+ blk[4] = 0;
+ x2 = blk[6];
+ blk[6] = 0;
+ x3 = blk[2];
+ blk[2] = 0;
+ x4 = blk[1];
+ blk[1] = 0;
+ x5 = blk[7];
+ blk[7] = 0;
+ x6 = blk[5];
+ blk[5] = 0;
+ x7 = blk[3];
+ blk[3] = 0;
+#ifndef FAST_IDCT
+ /* shortcut */ /* covered by idctrow1 01/9/2001 */
+ if (!(x1 | x2 | x3 | x4 | x5 | x6 | x7))
+ {
+ blk[0] = blk[1] = blk[2] = blk[3] = blk[4] = blk[5] = blk[6] = blk[7] = (blk[0] + 32) >> 6;
+ return;
+ }
+#endif
+ x0 = ((int32)blk[0] << 8) + 8192;
+ blk[0] = 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 */
+ word = ((x7 + x1) >> 14);
+ CLIP_RESULT(word)
+
+ temp = ((x3 + x2) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 8);
+
+ temp = ((x0 + x4) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 16);
+
+ temp = ((x8 + x6) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 24);
+ *((int32*)(comp)) = word;
+
+ word = ((x8 - x6) >> 14);
+ CLIP_RESULT(word)
+
+ temp = ((x0 - x4) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 8);
+
+ temp = ((x3 - x2) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 16);
+
+ temp = ((x7 - x1) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 24);
+ *((int32*)(comp + 4)) = word;
+ comp += offset;
+
+ blk += B_SIZE;
+ }
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+
+/*----------------------------------------------------------------------------
+; End Function: idctrow
+----------------------------------------------------------------------------*/
+
+
+/****************************************************************************/
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: idctcol
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS FOR idctcol
+
+ Inputs:
+ [input_variable_name] = [description of the input to module, its type
+ definition, and length (when applicable)]
+
+ Local Stores/Buffers/Pointers Needed:
+ [local_store_name] = [description of the local store, its type
+ definition, and length (when applicable)]
+ [local_buffer_name] = [description of the local buffer, its type
+ definition, and length (when applicable)]
+ [local_ptr_name] = [description of the local pointer, its type
+ definition, and length (when applicable)]
+
+ Global Stores/Buffers/Pointers Needed:
+ [global_store_name] = [description of the global store, its type
+ definition, and length (when applicable)]
+ [global_buffer_name] = [description of the global buffer, its type
+ definition, and length (when applicable)]
+ [global_ptr_name] = [description of the global pointer, its type
+ definition, and length (when applicable)]
+
+ Outputs:
+ [return_variable_name] = [description of data/pointer returned
+ by module, its type definition, and length
+ (when applicable)]
+
+ Pointers and Buffers Modified:
+ [variable_bfr_ptr] points to the [describe where the
+ variable_bfr_ptr points to, its type definition, and length
+ (when applicable)]
+ [variable_bfr] contents are [describe the new contents of
+ variable_bfr]
+
+ Local Stores Modified:
+ [local_store_name] = [describe new contents, its type
+ definition, and length (when applicable)]
+
+ Global Stores Modified:
+ [global_store_name] = [describe new contents, its type
+ definition, and length (when applicable)]
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION FOR idctcol
+
+------------------------------------------------------------------------------
+ REQUIREMENTS FOR idctcol
+
+------------------------------------------------------------------------------
+ REFERENCES FOR idctcol
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE FOR idctcol
+
+------------------------------------------------------------------------------
+ RESOURCES USED FOR idctcol
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; Function Code FOR idctcol
+----------------------------------------------------------------------------*/
+void idctcol(
+ int16 *blk
+)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* column (vertical) IDCT
+ *
+ * 7 pi 1 dst[8*k] = sum c[l] * src[8*l] *
+ * cos( -- * ( k + - ) * l ) l=0 8 2
+ *
+ * where: c[0] = 1/1024 c[1..7] = (1/1024)*sqrt(2) */
+ x1 = (int32)blk[32] << 11;
+ x2 = blk[48];
+ x3 = blk[16];
+ x4 = blk[8];
+ x5 = blk[56];
+ x6 = blk[40];
+ x7 = blk[24];
+#ifndef FAST_IDCT
+ /* shortcut */ /* covered by idctcolumn1 01/9/2001 */
+ if (!(x1 | x2 | x3 | x4 | x5 | x6 | x7))
+ {
+ blk[0] = blk[8] = blk[16] = blk[24] = blk[32] = blk[40] = blk[48] = blk[56]
+ = blk[0] << 3;
+ return;
+ }
+#endif
+
+ 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 nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+/*----------------------------------------------------------------------------
+; End Function: idctcol
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp
new file mode 100644
index 0000000..85889d3
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp
@@ -0,0 +1,182 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ [input_variable_name] = [description of the input to module, its type
+ definition, and length (when applicable)]
+
+ Local Stores/Buffers/Pointers Needed:
+ [local_store_name] = [description of the local store, its type
+ definition, and length (when applicable)]
+ [local_buffer_name] = [description of the local buffer, its type
+ definition, and length (when applicable)]
+ [local_ptr_name] = [description of the local pointer, its type
+ definition, and length (when applicable)]
+
+ Global Stores/Buffers/Pointers Needed:
+ [global_store_name] = [description of the global store, its type
+ definition, and length (when applicable)]
+ [global_buffer_name] = [description of the global buffer, its type
+ definition, and length (when applicable)]
+ [global_ptr_name] = [description of the global pointer, its type
+ definition, and length (when applicable)]
+
+ Outputs:
+ [return_variable_name] = [description of data/pointer returned
+ by module, its type definition, and length
+ (when applicable)]
+
+ Pointers and Buffers Modified:
+ [variable_bfr_ptr] points to the [describe where the
+ variable_bfr_ptr points to, its type definition, and length
+ (when applicable)]
+ [variable_bfr] contents are [describe the new contents of
+ variable_bfr]
+
+ Local Stores Modified:
+ [local_store_name] = [describe new contents, its type
+ definition, and length (when applicable)]
+
+ Global Stores Modified:
+ [global_store_name] = [describe new contents, its type
+ definition, and length (when applicable)]
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This module calculates the DC quantization scale according
+ to the incoming Q and type.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ [List requirements to be satisfied by this module.]
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [List all references used in designing this module.]
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+#include "vlc_decode.h"
+#include "bitstream.h"
+#include "zigzag.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+int cal_dc_scaler(
+ int QP,
+ int type)
+{
+
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int dc_scaler;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ if (type == LUMINANCE_DC_TYPE)
+ {
+ 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 (type == CHROMINANCE_DC_TYPE), there is no other types. */
+ {
+ if (QP > 0 && QP < 5) dc_scaler = 8;
+ else if (QP > 4 && QP < 25) dc_scaler = (QP + 13) >> 1;
+ else dc_scaler = QP - 6;
+ }
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return dc_scaler;
+}
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/chv_filter.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/chv_filter.cpp
new file mode 100644
index 0000000..6593b48
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/chv_filter.cpp
@@ -0,0 +1,654 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ [input_variable_name] = [description of the input to module, its type
+ definition, and length (when applicable)]
+
+ Local Stores/Buffers/Pointers Needed:
+ [local_store_name] = [description of the local store, its type
+ definition, and length (when applicable)]
+ [local_buffer_name] = [description of the local buffer, its type
+ definition, and length (when applicable)]
+ [local_ptr_name] = [description of the local pointer, its type
+ definition, and length (when applicable)]
+
+ Global Stores/Buffers/Pointers Needed:
+ [global_store_name] = [description of the global store, its type
+ definition, and length (when applicable)]
+ [global_buffer_name] = [description of the global buffer, its type
+ definition, and length (when applicable)]
+ [global_ptr_name] = [description of the global pointer, its type
+ definition, and length (when applicable)]
+
+ Outputs:
+ [return_variable_name] = [description of data/pointer returned
+ by module, its type definition, and length
+ (when applicable)]
+
+ Pointers and Buffers Modified:
+ [variable_bfr_ptr] points to the [describe where the
+ variable_bfr_ptr points to, its type definition, and length
+ (when applicable)]
+ [variable_bfr] contents are [describe the new contents of
+ variable_bfr]
+
+ Local Stores Modified:
+ [local_store_name] = [describe new contents, its type
+ definition, and length (when applicable)]
+
+ Global Stores Modified:
+ [global_store_name] = [describe new contents, its type
+ definition, and length (when applicable)]
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ For fast Deblock filtering
+ Newer version (macroblock based processing)
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+ [List requirements to be satisfied by this module.]
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [List all references used in designing this module.]
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+ RESOURCES USED
+ When the code is written for a specific target processor the
+ the resources used should be documented below.
+
+ STACK USAGE: [stack count for this module] + [variable to represent
+ stack usage for each subroutine called]
+
+ where: [stack usage variable] = stack usage for [subroutine
+ name] (see [filename].ext)
+
+ DATA MEMORY USED: x words
+
+ PROGRAM MEMORY USED: x words
+
+ CLOCK CYCLES: [cycle count equation for this module] + [variable
+ used to represent cycle count for each subroutine
+ called]
+
+ where: [cycle count variable] = cycle count for [subroutine
+ name] (see [filename].ext)
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+#include "post_proc.h"
+
+#define OSCL_DISABLE_WARNING_CONV_POSSIBLE_LOSS_OF_DATA
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+//#define FILTER_LEN_8
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+
+----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+#ifdef PV_POSTPROC_ON
+
+/*************************************************************************
+ Function prototype : void CombinedHorzVertFilter( uint8 *rec,
+ int width,
+ int height,
+ int *QP_store,
+ int chr,
+ uint8 *pp_mod)
+ Parameters :
+ rec : pointer to the decoded frame buffer.
+ width : width of decoded frame.
+ height : height of decoded frame
+ QP_store: pointer to the array of QP corresponding to the decoded frame.
+ It had only one value for each MB.
+ chr : luma or color indication
+ == 0 luma
+ == 1 color
+ pp_mod : The semphore used for deblocking
+
+ Remark : The function do the deblocking on decoded frames.
+ First based on the semaphore info., it is divided into hard and soft filtering.
+ To differentiate real and fake edge, it then check the difference with QP to
+ decide whether to do the filtering or not.
+
+*************************************************************************/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void CombinedHorzVertFilter(
+ uint8 *rec,
+ int width,
+ int height,
+ int16 *QP_store,
+ int chr,
+ uint8 *pp_mod)
+{
+
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int br, bc, mbr, mbc;
+ int QP = 1;
+ uint8 *ptr, *ptr_e;
+ int pp_w, pp_h;
+ int brwidth;
+
+ int jVal0, jVal1, jVal2;
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ pp_w = (width >> 3);
+ pp_h = (height >> 3);
+
+ for (mbr = 0; mbr < pp_h; mbr += 2) /* row of blocks */
+ {
+ brwidth = mbr * pp_w; /* number of blocks above current block row */
+ for (mbc = 0; mbc < pp_w; mbc += 2) /* col of blocks */
+ {
+ if (!chr)
+ QP = QP_store[(brwidth>>2) + (mbc>>1)]; /* QP is per MB based value */
+
+ /********* for each block **************/
+ /****************** Horiz. Filtering ********************/
+ for (br = mbr + 1; br < mbr + 3; br++) /* 2x2 blocks */
+ {
+ brwidth += pp_w; /* number of blocks above & left current block row */
+ /* the profile on ARM920T shows separate these two boundary check is faster than combine them */
+ if (br < pp_h) /* boundary : don't do it on the lowest row block */
+ for (bc = mbc; bc < mbc + 2; bc++)
+ {
+ /****** check boundary for deblocking ************/
+ if (bc < pp_w) /* boundary : don't do it on the most right col block */
+ {
+ ptr = rec + (brwidth << 6) + (bc << 3);
+ jVal0 = brwidth + bc;
+ if (chr) QP = QP_store[jVal0];
+
+ ptr_e = ptr + 8; /* pointer to where the loop ends */
+
+ if (((pp_mod[jVal0]&0x02)) && ((pp_mod[jVal0-pp_w]&0x02)))
+ {
+ /* Horiz Hard filter */
+ do
+ {
+ jVal0 = *(ptr - width); /* C */
+ jVal1 = *ptr; /* D */
+ jVal2 = jVal1 - jVal0;
+
+ if (((jVal2 > 0) && (jVal2 < (QP << 1)))
+ || ((jVal2 < 0) && (jVal2 > -(QP << 1)))) /* (D-C) compared with 2QP */
+ {
+ /* differentiate between real and fake edge */
+ jVal0 = ((jVal0 + jVal1) >> 1); /* (D+C)/2 */
+ *(ptr - width) = (uint8)(jVal0); /* C */
+ *ptr = (uint8)(jVal0); /* D */
+
+ jVal0 = *(ptr - (width << 1)); /* B */
+ jVal1 = *(ptr + width); /* E */
+ jVal2 = jVal1 - jVal0; /* E-B */
+
+ if (jVal2 > 0)
+ {
+ jVal0 += ((jVal2 + 3) >> 2);
+ jVal1 -= ((jVal2 + 3) >> 2);
+ *(ptr - (width << 1)) = (uint8)jVal0; /* store B */
+ *(ptr + width) = (uint8)jVal1; /* store E */
+ }
+ else if (jVal2)
+ {
+ jVal0 -= ((3 - jVal2) >> 2);
+ jVal1 += ((3 - jVal2) >> 2);
+ *(ptr - (width << 1)) = (uint8)jVal0; /* store B */
+ *(ptr + width) = (uint8)jVal1; /* store E */
+ }
+
+ jVal0 = *(ptr - (width << 1) - width); /* A */
+ jVal1 = *(ptr + (width << 1)); /* F */
+ jVal2 = jVal1 - jVal0; /* (F-A) */
+
+ if (jVal2 > 0)
+ {
+ jVal0 += ((jVal2 + 7) >> 3);
+ jVal1 -= ((jVal2 + 7) >> 3);
+ *(ptr - (width << 1) - width) = (uint8)(jVal0);
+ *(ptr + (width << 1)) = (uint8)(jVal1);
+ }
+ else if (jVal2)
+ {
+ jVal0 -= ((7 - jVal2) >> 3);
+ jVal1 += ((7 - jVal2) >> 3);
+ *(ptr - (width << 1) - width) = (uint8)(jVal0);
+ *(ptr + (width << 1)) = (uint8)(jVal1);
+ }
+ }/* a3_0 > 2QP */
+ }
+ while (++ptr < ptr_e);
+ }
+ else /* Horiz soft filter*/
+ {
+ do
+ {
+ jVal0 = *(ptr - width); /* B */
+ jVal1 = *ptr; /* C */
+ jVal2 = jVal1 - jVal0; /* C-B */
+
+ if (((jVal2 > 0) && (jVal2 < (QP)))
+ || ((jVal2 < 0) && (jVal2 > -(QP)))) /* (C-B) compared with QP */
+ {
+
+ jVal0 = ((jVal0 + jVal1) >> 1); /* (B+C)/2 cannot overflow; ceil() */
+ *(ptr - width) = (uint8)(jVal0); /* B = (B+C)/2 */
+ *ptr = (uint8)jVal0; /* C = (B+C)/2 */
+
+ jVal0 = *(ptr - (width << 1)); /* A */
+ jVal1 = *(ptr + width); /* D */
+ jVal2 = jVal1 - jVal0; /* D-A */
+
+
+ if (jVal2 > 0)
+ {
+ jVal1 -= ((jVal2 + 7) >> 3);
+ jVal0 += ((jVal2 + 7) >> 3);
+ *(ptr - (width << 1)) = (uint8)jVal0; /* A */
+ *(ptr + width) = (uint8)jVal1; /* D */
+ }
+ else if (jVal2)
+ {
+ jVal1 += ((7 - jVal2) >> 3);
+ jVal0 -= ((7 - jVal2) >> 3);
+ *(ptr - (width << 1)) = (uint8)jVal0; /* A */
+ *(ptr + width) = (uint8)jVal1; /* D */
+ }
+ }
+ }
+ while (++ptr < ptr_e);
+ } /* Soft filter*/
+ }/* boundary checking*/
+ }/*bc*/
+ }/*br*/
+ brwidth -= (pp_w << 1);
+ /****************** Vert. Filtering ********************/
+ for (br = mbr; br < mbr + 2; br++)
+ {
+ if (br < pp_h)
+ for (bc = mbc + 1; bc < mbc + 3; bc++)
+ {
+ /****** check boundary for deblocking ************/
+ if (bc < pp_w)
+ {
+ ptr = rec + (brwidth << 6) + (bc << 3);
+ jVal0 = brwidth + bc;
+ if (chr) QP = QP_store[jVal0];
+
+ ptr_e = ptr + (width << 3);
+
+ if (((pp_mod[jVal0-1]&0x01)) && ((pp_mod[jVal0]&0x01)))
+ {
+ /* Vert Hard filter */
+ do
+ {
+ jVal1 = *ptr; /* D */
+ jVal0 = *(ptr - 1); /* C */
+ jVal2 = jVal1 - jVal0; /* D-C */
+
+ if (((jVal2 > 0) && (jVal2 < (QP << 1)))
+ || ((jVal2 < 0) && (jVal2 > -(QP << 1))))
+ {
+ jVal1 = (jVal0 + jVal1) >> 1; /* (C+D)/2 */
+ *ptr = jVal1;
+ *(ptr - 1) = jVal1;
+
+ jVal1 = *(ptr + 1); /* E */
+ jVal0 = *(ptr - 2); /* B */
+ jVal2 = jVal1 - jVal0; /* E-B */
+
+ if (jVal2 > 0)
+ {
+ jVal1 -= ((jVal2 + 3) >> 2); /* E = E -(E-B)/4 */
+ jVal0 += ((jVal2 + 3) >> 2); /* B = B +(E-B)/4 */
+ *(ptr + 1) = jVal1;
+ *(ptr - 2) = jVal0;
+ }
+ else if (jVal2)
+ {
+ jVal1 += ((3 - jVal2) >> 2); /* E = E -(E-B)/4 */
+ jVal0 -= ((3 - jVal2) >> 2); /* B = B +(E-B)/4 */
+ *(ptr + 1) = jVal1;
+ *(ptr - 2) = jVal0;
+ }
+
+ jVal1 = *(ptr + 2); /* F */
+ jVal0 = *(ptr - 3); /* A */
+
+ jVal2 = jVal1 - jVal0; /* (F-A) */
+
+ if (jVal2 > 0)
+ {
+ jVal1 -= ((jVal2 + 7) >> 3); /* F -= (F-A)/8 */
+ jVal0 += ((jVal2 + 7) >> 3); /* A += (F-A)/8 */
+ *(ptr + 2) = jVal1;
+ *(ptr - 3) = jVal0;
+ }
+ else if (jVal2)
+ {
+ jVal1 -= ((jVal2 - 7) >> 3); /* F -= (F-A)/8 */
+ jVal0 += ((jVal2 - 7) >> 3); /* A += (F-A)/8 */
+ *(ptr + 2) = jVal1;
+ *(ptr - 3) = jVal0;
+ }
+ } /* end of ver hard filetering */
+ }
+ while ((ptr += width) < ptr_e);
+ }
+ else /* Vert soft filter*/
+ {
+ do
+ {
+ jVal1 = *ptr; /* C */
+ jVal0 = *(ptr - 1); /* B */
+ jVal2 = jVal1 - jVal0;
+
+ if (((jVal2 > 0) && (jVal2 < (QP)))
+ || ((jVal2 < 0) && (jVal2 > -(QP))))
+ {
+
+ jVal1 = (jVal0 + jVal1 + 1) >> 1;
+ *ptr = jVal1; /* C */
+ *(ptr - 1) = jVal1; /* B */
+
+ jVal1 = *(ptr + 1); /* D */
+ jVal0 = *(ptr - 2); /* A */
+ jVal2 = (jVal1 - jVal0); /* D- A */
+
+ if (jVal2 > 0)
+ {
+ jVal1 -= (((jVal2) + 7) >> 3); /* D -= (D-A)/8 */
+ jVal0 += (((jVal2) + 7) >> 3); /* A += (D-A)/8 */
+ *(ptr + 1) = jVal1;
+ *(ptr - 2) = jVal0;
+
+ }
+ else if (jVal2)
+ {
+ jVal1 += ((7 - (jVal2)) >> 3); /* D -= (D-A)/8 */
+ jVal0 -= ((7 - (jVal2)) >> 3); /* A += (D-A)/8 */
+ *(ptr + 1) = jVal1;
+ *(ptr - 2) = jVal0;
+ }
+ }
+ }
+ while ((ptr += width) < ptr_e);
+ } /* Soft filter*/
+ } /* boundary*/
+ } /*bc*/
+ brwidth += pp_w;
+ }/*br*/
+ brwidth -= (pp_w << 1);
+ }/*mbc*/
+ brwidth += (pp_w << 1);
+ }/*mbr*/
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+void CombinedHorzVertFilter_NoSoftDeblocking(
+ uint8 *rec,
+ int width,
+ int height,
+ int16 *QP_store,
+ int chr,
+ uint8 *pp_mod)
+{
+
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int br, bc, mbr, mbc;
+ int QP = 1;
+ uint8 *ptr, *ptr_e;
+ int pp_w, pp_h;
+ int brwidth;
+
+ int jVal0, jVal1, jVal2;
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ pp_w = (width >> 3);
+ pp_h = (height >> 3);
+
+ for (mbr = 0; mbr < pp_h; mbr += 2) /* row of blocks */
+ {
+ brwidth = mbr * pp_w; /* number of blocks above current block row */
+ for (mbc = 0; mbc < pp_w; mbc += 2) /* col of blocks */
+ {
+ if (!chr)
+ QP = QP_store[(brwidth>>2) + (mbc>>1)]; /* QP is per MB based value */
+
+ /********* for each block **************/
+ /****************** Horiz. Filtering ********************/
+ for (br = mbr + 1; br < mbr + 3; br++) /* 2x2 blocks */
+ {
+ brwidth += pp_w; /* number of blocks above & left current block row */
+ /* the profile on ARM920T shows separate these two boundary check is faster than combine them */
+ if (br < pp_h) /* boundary : don't do it on the lowest row block */
+ for (bc = mbc; bc < mbc + 2; bc++)
+ {
+ /****** check boundary for deblocking ************/
+ if (bc < pp_w) /* boundary : don't do it on the most right col block */
+ {
+ ptr = rec + (brwidth << 6) + (bc << 3);
+ jVal0 = brwidth + bc;
+ if (chr) QP = QP_store[jVal0];
+
+ ptr_e = ptr + 8; /* pointer to where the loop ends */
+
+ if (((pp_mod[jVal0]&0x02)) && ((pp_mod[jVal0-pp_w]&0x02)))
+ {
+ /* Horiz Hard filter */
+ do
+ {
+ jVal0 = *(ptr - width); /* C */
+ jVal1 = *ptr; /* D */
+ jVal2 = jVal1 - jVal0;
+
+ if (((jVal2 > 0) && (jVal2 < (QP << 1)))
+ || ((jVal2 < 0) && (jVal2 > -(QP << 1)))) /* (D-C) compared with 2QP */
+ {
+ /* differentiate between real and fake edge */
+ jVal0 = ((jVal0 + jVal1) >> 1); /* (D+C)/2 */
+ *(ptr - width) = (uint8)(jVal0); /* C */
+ *ptr = (uint8)(jVal0); /* D */
+
+ jVal0 = *(ptr - (width << 1)); /* B */
+ jVal1 = *(ptr + width); /* E */
+ jVal2 = jVal1 - jVal0; /* E-B */
+
+ if (jVal2 > 0)
+ {
+ jVal0 += ((jVal2 + 3) >> 2);
+ jVal1 -= ((jVal2 + 3) >> 2);
+ *(ptr - (width << 1)) = (uint8)jVal0; /* store B */
+ *(ptr + width) = (uint8)jVal1; /* store E */
+ }
+ else if (jVal2)
+ {
+ jVal0 -= ((3 - jVal2) >> 2);
+ jVal1 += ((3 - jVal2) >> 2);
+ *(ptr - (width << 1)) = (uint8)jVal0; /* store B */
+ *(ptr + width) = (uint8)jVal1; /* store E */
+ }
+
+ jVal0 = *(ptr - (width << 1) - width); /* A */
+ jVal1 = *(ptr + (width << 1)); /* F */
+ jVal2 = jVal1 - jVal0; /* (F-A) */
+
+ if (jVal2 > 0)
+ {
+ jVal0 += ((jVal2 + 7) >> 3);
+ jVal1 -= ((jVal2 + 7) >> 3);
+ *(ptr - (width << 1) - width) = (uint8)(jVal0);
+ *(ptr + (width << 1)) = (uint8)(jVal1);
+ }
+ else if (jVal2)
+ {
+ jVal0 -= ((7 - jVal2) >> 3);
+ jVal1 += ((7 - jVal2) >> 3);
+ *(ptr - (width << 1) - width) = (uint8)(jVal0);
+ *(ptr + (width << 1)) = (uint8)(jVal1);
+ }
+ }/* a3_0 > 2QP */
+ }
+ while (++ptr < ptr_e);
+ }
+
+ }/* boundary checking*/
+ }/*bc*/
+ }/*br*/
+ brwidth -= (pp_w << 1);
+ /****************** Vert. Filtering ********************/
+ for (br = mbr; br < mbr + 2; br++)
+ {
+ if (br < pp_h)
+ for (bc = mbc + 1; bc < mbc + 3; bc++)
+ {
+ /****** check boundary for deblocking ************/
+ if (bc < pp_w)
+ {
+ ptr = rec + (brwidth << 6) + (bc << 3);
+ jVal0 = brwidth + bc;
+ if (chr) QP = QP_store[jVal0];
+
+ ptr_e = ptr + (width << 3);
+
+ if (((pp_mod[jVal0-1]&0x01)) && ((pp_mod[jVal0]&0x01)))
+ {
+ /* Vert Hard filter */
+ do
+ {
+ jVal1 = *ptr; /* D */
+ jVal0 = *(ptr - 1); /* C */
+ jVal2 = jVal1 - jVal0; /* D-C */
+
+ if (((jVal2 > 0) && (jVal2 < (QP << 1)))
+ || ((jVal2 < 0) && (jVal2 > -(QP << 1))))
+ {
+ jVal1 = (jVal0 + jVal1) >> 1; /* (C+D)/2 */
+ *ptr = jVal1;
+ *(ptr - 1) = jVal1;
+
+ jVal1 = *(ptr + 1); /* E */
+ jVal0 = *(ptr - 2); /* B */
+ jVal2 = jVal1 - jVal0; /* E-B */
+
+ if (jVal2 > 0)
+ {
+ jVal1 -= ((jVal2 + 3) >> 2); /* E = E -(E-B)/4 */
+ jVal0 += ((jVal2 + 3) >> 2); /* B = B +(E-B)/4 */
+ *(ptr + 1) = jVal1;
+ *(ptr - 2) = jVal0;
+ }
+ else if (jVal2)
+ {
+ jVal1 += ((3 - jVal2) >> 2); /* E = E -(E-B)/4 */
+ jVal0 -= ((3 - jVal2) >> 2); /* B = B +(E-B)/4 */
+ *(ptr + 1) = jVal1;
+ *(ptr - 2) = jVal0;
+ }
+
+ jVal1 = *(ptr + 2); /* F */
+ jVal0 = *(ptr - 3); /* A */
+
+ jVal2 = jVal1 - jVal0; /* (F-A) */
+
+ if (jVal2 > 0)
+ {
+ jVal1 -= ((jVal2 + 7) >> 3); /* F -= (F-A)/8 */
+ jVal0 += ((jVal2 + 7) >> 3); /* A += (F-A)/8 */
+ *(ptr + 2) = jVal1;
+ *(ptr - 3) = jVal0;
+ }
+ else if (jVal2)
+ {
+ jVal1 -= ((jVal2 - 7) >> 3); /* F -= (F-A)/8 */
+ jVal0 += ((jVal2 - 7) >> 3); /* A += (F-A)/8 */
+ *(ptr + 2) = jVal1;
+ *(ptr - 3) = jVal0;
+ }
+ } /* end of ver hard filetering */
+ }
+ while ((ptr += width) < ptr_e);
+ }
+
+ } /* boundary*/
+ } /*bc*/
+ brwidth += pp_w;
+ }/*br*/
+ brwidth -= (pp_w << 1);
+ }/*mbc*/
+ brwidth += (pp_w << 1);
+ }/*mbr*/
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+#endif
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/chvr_filter.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/chvr_filter.cpp
new file mode 100644
index 0000000..795cf71
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/chvr_filter.cpp
@@ -0,0 +1,565 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_lib.h"
+#include "post_proc.h"
+
+#ifdef PV_POSTPROC_ON
+
+void CombinedHorzVertRingFilter(
+ uint8 *rec,
+ int width,
+ int height,
+ int16 *QP_store,
+ int chr,
+ uint8 *pp_mod)
+{
+
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int index, counter;
+ int br, bc, incr, mbr, mbc;
+ int QP = 1;
+ int v[5];
+ uint8 *ptr, *ptr_c, *ptr_n;
+ int w1, w2, w3, w4;
+ int pp_w, pp_h, brwidth;
+ int sum, delta;
+ int a3_0, a3_1, a3_2, A3_0;
+ /* for Deringing Threshold approach (MPEG4)*/
+ int max_diff, thres, v0, h0, min_blk, max_blk;
+ int cnthflag;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* Calculate the width and height of the area in blocks (divide by 8) */
+ pp_w = (width >> 3);
+ pp_h = (height >> 3);
+
+ /* Set up various values needed for updating pointers into rec */
+ w1 = width; /* Offset to next row in pixels */
+ w2 = width << 1; /* Offset to two rows in pixels */
+ w3 = w1 + w2; /* Offset to three rows in pixels */
+ w4 = w2 << 1; /* Offset to four rows in pixels */
+ incr = width - BLKSIZE; /* Offset to next row after processing block */
+
+ /* Work through the area hortizontally by two rows per step */
+ for (mbr = 0; mbr < pp_h; mbr += 2)
+ {
+ /* brwidth contains the block number of the leftmost block
+ * of the current row */
+ brwidth = mbr * pp_w;
+
+ /* Work through the area vertically by two columns per step */
+ for (mbc = 0; mbc < pp_w; mbc += 2)
+ {
+ /* if the data is luminance info, get the correct
+ * quantization paramenter. One parameter per macroblock */
+ if (!chr)
+ {
+ /* brwidth/4 is the macroblock number and mbc/2 is the macroblock col number*/
+ QP = QP_store[(brwidth>>2) + (mbc>>1)];
+ }
+
+ /****************** Horiz. Filtering ********************/
+ /* Process four blocks for the filtering */
+ /********************************************************/
+ /* Loop over two rows of blocks */
+ for (br = mbr + 1; br < mbr + 3; br++) /* br is the row counter in blocks */
+ {
+ /* Set brwidth to the first (leftmost) block number of the next row */
+ /* brwidth is used as an index when counting blocks */
+ brwidth += pp_w;
+
+ /* Loop over two columns of blocks in the row */
+ for (bc = mbc; bc < mbc + 2; bc++) /* bc is the column counter in blocks */
+ {
+ /****** check boundary for deblocking ************/
+ /* Execute if the row and column counters are within the area */
+ if (br < pp_h && bc < pp_w)
+ {
+ /* Set the ptr to the first pixel of the first block of the second row
+ * brwidth * 64 is the pixel row offset
+ * bc * 8 is the pixel column offset */
+ ptr = rec + (brwidth << 6) + (bc << 3);
+
+ /* Set the index to the current block of the second row counting in blocks */
+ index = brwidth + bc;
+
+ /* if the data is chrominance info, get the correct
+ * quantization paramenter. One parameter per block. */
+ if (chr)
+ {
+ QP = QP_store[index];
+ }
+
+ /* Execute hard horizontal filter if semaphore for horizontal deblocking
+ * is set for the current block and block immediately above it */
+ if (((pp_mod[index]&0x02) != 0) && ((pp_mod[index-pp_w]&0x02) != 0))
+ { /* Hard filter */
+
+ /* Set HorzHflag (bit 4) in the pp_mod location */
+ pp_mod[index-pp_w] |= 0x10; /* 4/26/00 reuse pp_mod for HorzHflag*/
+
+ /* Filter across the 8 pixels of the block */
+ for (index = BLKSIZE; index > 0; index--)
+ {
+ /* Difference between the current pixel and the pixel above it */
+ a3_0 = *ptr - *(ptr - w1);
+
+ /* if the magnitude of the difference is greater than the KThH threshold
+ * and within the quantization parameter, apply hard filter */
+ if ((a3_0 > KThH || a3_0 < -KThH) && a3_0<QP && a3_0> -QP)
+ {
+ ptr_c = ptr - w3; /* Points to pixel three rows above */
+ ptr_n = ptr + w1; /* Points to pixel one row below */
+ v[0] = (int)(*(ptr_c - w3));
+ v[1] = (int)(*(ptr_c - w2));
+ v[2] = (int)(*(ptr_c - w1));
+ v[3] = (int)(*ptr_c);
+ v[4] = (int)(*(ptr_c + w1));
+
+ sum = v[0]
+ + v[1]
+ + v[2]
+ + *ptr_c
+ + v[4]
+ + (*(ptr_c + w2))
+ + (*(ptr_c + w3)); /* Current pixel */
+
+ delta = (sum + *ptr_c + 4) >> 3; /* Average pixel values with rounding */
+ *(ptr_c) = (uint8) delta;
+
+ /* Move pointer down one row of pixels (points to pixel two rows
+ * above current pixel) */
+ ptr_c += w1;
+
+ for (counter = 0; counter < 5; counter++)
+ {
+ /* Subtract off highest pixel and add in pixel below */
+ sum = sum - v[counter] + *ptr_n;
+ /* Average the pixel values with rounding */
+ delta = (sum + *ptr_c + 4) >> 3;
+ *ptr_c = (uint8)(delta);
+
+ /* Increment pointers to next pixel row */
+ ptr_c += w1;
+ ptr_n += w1;
+ }
+ }
+ /* Increment pointer to next pixel */
+ ++ptr;
+ } /* index*/
+ }
+ else
+ { /* soft filter*/
+
+ /* Clear HorzHflag (bit 4) in the pp_mod location */
+ pp_mod[index-pp_w] &= 0xef; /* reset 1110,1111 */
+
+ for (index = BLKSIZE; index > 0; index--)
+ {
+ /* Difference between the current pixel and the pixel above it */
+ a3_0 = *(ptr) - *(ptr - w1);
+
+ /* if the magnitude of the difference is greater than the KTh threshold,
+ * apply soft filter */
+ if ((a3_0 > KTh || a3_0 < -KTh))
+ {
+
+ /* Sum of weighted differences */
+ a3_0 += ((*(ptr - w2) - *(ptr + w1)) << 1) + (a3_0 << 2);
+
+ /* Check if sum is less than the quantization parameter */
+ if (PV_ABS(a3_0) < (QP << 3))
+ {
+ a3_1 = *(ptr - w2) - *(ptr - w3);
+ a3_1 += ((*(ptr - w4) - *(ptr - w1)) << 1) + (a3_1 << 2);
+
+ a3_2 = *(ptr + w2) - *(ptr + w1);
+ a3_2 += ((*(ptr) - *(ptr + w3)) << 1) + (a3_2 << 2);
+
+ A3_0 = PV_ABS(a3_0) - PV_MIN(PV_ABS(a3_1), PV_ABS(a3_2));
+
+ if (A3_0 > 0)
+ {
+ A3_0 += A3_0 << 2;
+ A3_0 = (A3_0 + 32) >> 6;
+ if (a3_0 > 0)
+ {
+ A3_0 = -A3_0;
+ }
+
+ delta = (*(ptr - w1) - *(ptr)) >> 1;
+ if (delta >= 0)
+ {
+ if (delta >= A3_0)
+ {
+ delta = PV_MAX(A3_0, 0);
+ }
+ }
+ else
+ {
+ if (A3_0 > 0)
+ {
+ delta = 0;
+ }
+ else
+ {
+ delta = PV_MAX(A3_0, delta);
+ }
+ }
+
+ *(ptr - w1) = (uint8)(*(ptr - w1) - delta);
+ *(ptr) = (uint8)(*(ptr) + delta);
+ }
+ } /*threshold*/
+ }
+ /* Increment pointer to next pixel */
+ ++ptr;
+ } /*index*/
+ } /* Soft filter*/
+ }/* boundary checking*/
+ }/*bc*/
+ }/*br*/
+ brwidth -= (pp_w << 1);
+
+
+ /****************** Vert. Filtering *********************/
+ /* Process four blocks for the filtering */
+ /********************************************************/
+ /* Loop over two rows of blocks */
+ for (br = mbr; br < mbr + 2; br++) /* br is the row counter in blocks */
+ {
+ for (bc = mbc + 1; bc < mbc + 3; bc++) /* bc is the column counter in blocks */
+ {
+ /****** check boundary for deblocking ************/
+ /* Execute if the row and column counters are within the area */
+ if (br < pp_h && bc < pp_w)
+ {
+ /* Set the ptr to the first pixel of the first block of the second row
+ * brwidth * 64 is the pixel row offset
+ * bc * 8 is the pixel column offset */
+ ptr = rec + (brwidth << 6) + (bc << 3);
+
+ /* Set the index to the current block of the second row counting in blocks */
+ index = brwidth + bc;
+
+ /* if the data is chrominance info, get the correct
+ * quantization paramenter. One parameter per block. */
+ if (chr)
+ {
+ QP = QP_store[index];
+ }
+
+ /* Execute hard vertical filter if semaphore for vertical deblocking
+ * is set for the current block and block immediately left of it */
+ if (((pp_mod[index-1]&0x01) != 0) && ((pp_mod[index]&0x01) != 0))
+ { /* Hard filter */
+
+ /* Set VertHflag (bit 5) in the pp_mod location of previous block*/
+ pp_mod[index-1] |= 0x20; /* 4/26/00 reuse pp_mod for VertHflag*/
+
+ /* Filter across the 8 pixels of the block */
+ for (index = BLKSIZE; index > 0; index--)
+ {
+ /* Difference between the current pixel
+ * and the pixel to left of it */
+ a3_0 = *ptr - *(ptr - 1);
+
+ /* if the magnitude of the difference is greater than the KThH threshold
+ * and within the quantization parameter, apply hard filter */
+ if ((a3_0 > KThH || a3_0 < -KThH) && a3_0<QP && a3_0> -QP)
+ {
+ ptr_c = ptr - 3;
+ ptr_n = ptr + 1;
+ v[0] = (int)(*(ptr_c - 3));
+ v[1] = (int)(*(ptr_c - 2));
+ v[2] = (int)(*(ptr_c - 1));
+ v[3] = (int)(*ptr_c);
+ v[4] = (int)(*(ptr_c + 1));
+
+ sum = v[0]
+ + v[1]
+ + v[2]
+ + *ptr_c
+ + v[4]
+ + (*(ptr_c + 2))
+ + (*(ptr_c + 3));
+
+ delta = (sum + *ptr_c + 4) >> 3;
+ *(ptr_c) = (uint8) delta;
+
+ /* Move pointer down one pixel to the right */
+ ptr_c += 1;
+ for (counter = 0; counter < 5; counter++)
+ {
+ /* Subtract off highest pixel and add in pixel below */
+ sum = sum - v[counter] + *ptr_n;
+ /* Average the pixel values with rounding */
+ delta = (sum + *ptr_c + 4) >> 3;
+ *ptr_c = (uint8)(delta);
+
+ /* Increment pointers to next pixel */
+ ptr_c += 1;
+ ptr_n += 1;
+ }
+ }
+ /* Increment pointers to next pixel row */
+ ptr += w1;
+ } /* index*/
+ }
+ else
+ { /* soft filter*/
+
+ /* Clear VertHflag (bit 5) in the pp_mod location */
+ pp_mod[index-1] &= 0xdf; /* reset 1101,1111 */
+ for (index = BLKSIZE; index > 0; index--)
+ {
+ /* Difference between the current pixel and the pixel above it */
+ a3_0 = *(ptr) - *(ptr - 1);
+
+ /* if the magnitude of the difference is greater than the KTh threshold,
+ * apply soft filter */
+ if ((a3_0 > KTh || a3_0 < -KTh))
+ {
+
+ /* Sum of weighted differences */
+ a3_0 += ((*(ptr - 2) - *(ptr + 1)) << 1) + (a3_0 << 2);
+
+ /* Check if sum is less than the quantization parameter */
+ if (PV_ABS(a3_0) < (QP << 3))
+ {
+ a3_1 = *(ptr - 2) - *(ptr - 3);
+ a3_1 += ((*(ptr - 4) - *(ptr - 1)) << 1) + (a3_1 << 2);
+
+ a3_2 = *(ptr + 2) - *(ptr + 1);
+ a3_2 += ((*(ptr) - *(ptr + 3)) << 1) + (a3_2 << 2);
+
+ A3_0 = PV_ABS(a3_0) - PV_MIN(PV_ABS(a3_1), PV_ABS(a3_2));
+
+ if (A3_0 > 0)
+ {
+ A3_0 += A3_0 << 2;
+ A3_0 = (A3_0 + 32) >> 6;
+ if (a3_0 > 0)
+ {
+ A3_0 = -A3_0;
+ }
+
+ delta = (*(ptr - 1) - *(ptr)) >> 1;
+ if (delta >= 0)
+ {
+ if (delta >= A3_0)
+ {
+ delta = PV_MAX(A3_0, 0);
+ }
+ }
+ else
+ {
+ if (A3_0 > 0)
+ {
+ delta = 0;
+ }
+ else
+ {
+ delta = PV_MAX(A3_0, delta);
+ }
+ }
+
+ *(ptr - 1) = (uint8)(*(ptr - 1) - delta);
+ *(ptr) = (uint8)(*(ptr) + delta);
+ }
+ } /*threshold*/
+ }
+ ptr += w1;
+ } /*index*/
+ } /* Soft filter*/
+ } /* boundary*/
+ } /*bc*/
+ /* Increment pointer to next row of pixels */
+ brwidth += pp_w;
+ }/*br*/
+ brwidth -= (pp_w << 1);
+
+ /****************** Deringing ***************************/
+ /* Process four blocks for the filtering */
+ /********************************************************/
+ /* Loop over two rows of blocks */
+ for (br = mbr; br < mbr + 2; br++)
+ {
+ /* Loop over two columns of blocks in the row */
+ for (bc = mbc; bc < mbc + 2; bc++)
+ {
+ /* Execute if the row and column counters are within the area */
+ if (br < pp_h && bc < pp_w)
+ {
+ /* Set the index to the current block */
+ index = brwidth + bc;
+
+ /* Execute deringing if semaphore for deringing (bit-3 of pp_mod)
+ * is set for the current block */
+ if ((pp_mod[index]&0x04) != 0)
+ {
+ /* Don't process deringing if on an edge block */
+ if (br > 0 && bc > 0 && br < pp_h - 1 && bc < pp_w - 1)
+ {
+ /* cnthflag = weighted average of HorzHflag of current,
+ * one above, previous blocks*/
+ cnthflag = ((pp_mod[index] & 0x10) +
+ (pp_mod[index-pp_w] & 0x10) +
+ ((pp_mod[index-1] >> 1) & 0x10) +
+ ((pp_mod[index] >> 1) & 0x10)) >> 4; /* 4/26/00*/
+
+ /* Do the deringing if decision flags indicate it's necessary */
+ if (cnthflag < 3)
+ {
+ /* if the data is chrominance info, get the correct
+ * quantization paramenter. One parameter per block. */
+ if (chr)
+ {
+ QP = QP_store[index];
+ }
+
+ /* Set amount to change luminance if it needs to be changed
+ * based on quantization parameter */
+ max_diff = (QP >> 2) + 4;
+
+ /* Set pointer to first pixel of current block */
+ ptr = rec + (brwidth << 6) + (bc << 3);
+
+ /* Find minimum and maximum value of pixel block */
+ FindMaxMin(ptr, &min_blk, &max_blk, incr);
+
+ /* threshold determination */
+ thres = (max_blk + min_blk + 1) >> 1;
+
+ /* If pixel range is greater or equal than DERING_THR, smooth the region */
+ if ((max_blk - min_blk) >= DERING_THR) /*smooth 8x8 region*/
+#ifndef NoMMX
+ {
+ /* smooth all pixels in the block*/
+ DeringAdaptiveSmoothMMX(ptr, width, thres, max_diff);
+ }
+#else
+ {
+ /* Setup the starting point of the region to smooth */
+ v0 = (br << 3) - 1;
+ h0 = (bc << 3) - 1;
+
+ /*smooth 8x8 region*/
+ AdaptiveSmooth_NoMMX(rec, v0, h0, v0 + 1, h0 + 1, thres, width, max_diff);
+ }
+#endif
+ }/*cnthflag*/
+ } /*dering br==1 or bc==1 (boundary block)*/
+ else /* Process the boundary blocks */
+ {
+ /* Decide to perform deblocking based on the semaphore flags
+ * of the neighboring blocks in each case. A certain number of
+ * hard filtering flags have to be set in order to signal need
+ * for smoothing */
+ if (br > 0 && br < pp_h - 1)
+ {
+ if (bc > 0)
+ {
+ cnthflag = ((pp_mod[index-pp_w] & 0x10) +
+ (pp_mod[index] & 0x10) +
+ ((pp_mod[index-1] >> 1) & 0x10)) >> 4;
+ }
+ else
+ {
+ cnthflag = ((pp_mod[index] & 0x10) +
+ (pp_mod[index-pp_w] & 0x10) +
+ ((pp_mod[index] >> 1) & 0x10)) >> 4;
+ }
+ }
+ else if (bc > 0 && bc < pp_w - 1)
+ {
+ if (br > 0)
+ {
+ cnthflag = ((pp_mod[index-pp_w] & 0x10) +
+ ((pp_mod[index-1] >> 1) & 0x10) +
+ ((pp_mod[index] >> 1) & 0x10)) >> 4;
+ }
+ else
+ {
+ cnthflag = ((pp_mod[index] & 0x10) +
+ ((pp_mod[index-1] >> 1) & 0x10) +
+ ((pp_mod[index] >> 1) & 0x10)) >> 4;
+ }
+ }
+ else /* at the corner do default*/
+ {
+ cnthflag = 0;
+ }
+
+ /* Do the deringing if decision flags indicate it's necessary */
+ if (cnthflag < 2)
+ {
+
+ /* if the data is chrominance info, get the correct
+ * quantization paramenter. One parameter per block. */
+ if (chr)
+ {
+ QP = QP_store[index];
+ }
+
+ /* Set amount to change luminance if it needs to be changed
+ * based on quantization parameter */
+ max_diff = (QP >> 2) + 4;
+
+ /* Set pointer to first pixel of current block */
+ ptr = rec + (brwidth << 6) + (bc << 3);
+
+ /* Find minimum and maximum value of pixel block */
+ FindMaxMin(ptr, &min_blk, &max_blk, incr);
+
+ /* threshold determination */
+ thres = (max_blk + min_blk + 1) >> 1;
+
+ /* Setup the starting point of the region to smooth
+ * This is going to be a 4x4 region */
+ v0 = (br << 3) + 1;
+ h0 = (bc << 3) + 1;
+
+ /* If pixel range is greater or equal than DERING_THR, smooth the region */
+ if ((max_blk - min_blk) >= DERING_THR)
+ {
+ /* Smooth 4x4 region */
+ AdaptiveSmooth_NoMMX(rec, v0, h0, v0 - 3, h0 - 3, thres, width, max_diff);
+ }
+ }/*cnthflag*/
+ } /* br==0, bc==0*/
+ } /* dering*/
+ } /*boundary condition*/
+ }/*bc*/
+ brwidth += pp_w;
+ }/*br*/
+ brwidth -= (pp_w << 1);
+ }/*mbc*/
+ brwidth += (pp_w << 1);
+ }/*mbr*/
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return ;
+}
+#endif
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/combined_decode.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/combined_decode.cpp
new file mode 100644
index 0000000..6499233
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/combined_decode.cpp
@@ -0,0 +1,840 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_lib.h" /* video decoder function prototypes */
+#include "vlc_decode.h"
+#include "bitstream.h"
+#include "scaling.h"
+#include "mbtype_mode.h"
+
+#define OSCL_DISABLE_WARNING_CONDITIONAL_IS_CONSTANT
+/* ======================================================================== */
+/* Function : DecodeFrameCombinedMode() */
+/* Purpose : Decode a frame of MPEG4 bitstream in combined mode. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* */
+/* 03/30/2000 : Cleaned up and optimized the code. */
+/* 03/31/2000 : Added proper handling of MB stuffing. */
+/* 04/13/2000 : Rewrote this combined mode path completely */
+/* so that it handles "Combined Mode With Error */
+/* Resilience." Now the code resembles the */
+/* pseudo codes in MPEG-4 standard better. */
+/* 10/13/2000 : Add fast VLC+dequant */
+/* 04/13/2001 : fix MB_stuffing */
+/* 08/07/2001 : remove MBzero */
+/* ======================================================================== */
+PV_STATUS DecodeFrameCombinedMode(VideoDecData *video)
+{
+ PV_STATUS status;
+ int mbnum;
+ Vop *currVop = video->currVop;
+ BitstreamDecVideo *stream = video->bitstream;
+ int shortVideoHeader = video->shortVideoHeader;
+ int16 QP, *QPMB = video->QPMB;
+ uint8 *Mode = video->headerInfo.Mode;
+ int nTotalMB = video->nTotalMB;
+ int nMBPerRow = video->nMBPerRow;
+ int slice_counter;
+ uint32 tmpvar, long_zero_bits;
+ uint code;
+ int valid_stuffing;
+ int resync_marker_length;
+ int stuffing_length;
+
+ /* add this for error resilient, 05/18/2000 */
+ int32 startPacket;
+ int mb_start;
+ /* copy and pad to prev_Vop for INTER coding */
+ switch (currVop->predictionType)
+ {
+ case I_VOP :
+// oscl_memset(Mode, MODE_INTRA, sizeof(uint8)*nTotalMB);
+ resync_marker_length = 17;
+ stuffing_length = 9;
+ break;
+ case P_VOP :
+ oscl_memset(video->motX, 0, sizeof(MOT)*4*nTotalMB);
+ oscl_memset(video->motY, 0, sizeof(MOT)*4*nTotalMB);
+// oscl_memset(Mode, MODE_INTER, sizeof(uint8)*nTotalMB);
+ resync_marker_length = 16 + currVop->fcodeForward;
+ stuffing_length = 10;
+ break;
+ default :
+ mp4dec_log("DecodeFrameCombinedMode(): Vop type not supported.\n");
+ return PV_FAIL;
+ }
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ if (video->shortVideoHeader)
+ {
+ if (video->advanced_INTRA)
+ {
+ if (video->modified_quant)
+ {
+ video->vlcDecCoeffIntra = &VlcDecTCOEFShortHeader_AnnexIT;
+ video->vlcDecCoeffInter = &VlcDecTCOEFShortHeader_AnnexT;
+ }
+ else
+ {
+ video->vlcDecCoeffIntra = &VlcDecTCOEFShortHeader_AnnexI;
+ video->vlcDecCoeffInter = &VlcDecTCOEFShortHeader;
+ }
+ }
+ else
+ {
+ if (video->modified_quant)
+ {
+ video->vlcDecCoeffInter = video->vlcDecCoeffIntra = &VlcDecTCOEFShortHeader_AnnexT;
+ }
+ else
+ {
+ video->vlcDecCoeffInter = video->vlcDecCoeffIntra = &VlcDecTCOEFShortHeader;
+ }
+ }
+ }
+
+#endif
+
+ /** Initialize sliceNo ***/
+ mbnum = slice_counter = 0;
+// oscl_memset(video->sliceNo, 0, sizeof(uint8)*nTotalMB);
+ QP = video->currVop->quantizer;
+
+ do
+ {
+ /* This section is equivalent to motion_shape_texture() */
+ /* in the MPEG-4 standard. 04/13/2000 */
+ mb_start = mbnum;
+ video->usePrevQP = 0; /* 04/27/01 */
+ startPacket = getPointer(stream);
+
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ if (video->modified_quant)
+ {
+ video->QP_CHR = MQ_chroma_QP_table[QP];
+ }
+ else
+ {
+ video->QP_CHR = QP; /* ANNEX_T */
+ }
+#endif
+ /* remove any stuffing bits */
+ BitstreamShowBits16(stream, stuffing_length, &code);
+ while (code == 1)
+ {
+ PV_BitstreamFlushBits(stream, stuffing_length);
+ BitstreamShowBits16(stream, stuffing_length, &code);
+ }
+
+ do
+ {
+ /* we need video->mbnum in lower level functions */
+ video->mbnum = mbnum;
+ video->mbnum_row = PV_GET_ROW(mbnum, nMBPerRow);
+ video->mbnum_col = mbnum - video->mbnum_row * nMBPerRow;
+ /* assign slice number for each macroblocks */
+ video->sliceNo[mbnum] = (uint8) slice_counter;
+
+ /* decode COD, MCBPC, ACpred_flag, CPBY and DQUANT */
+ /* We have to discard stuffed MB header */
+ status = GetMBheader(video, &QP);
+
+ if (status != PV_SUCCESS)
+ {
+ VideoDecoderErrorDetected(video);
+ video->mbnum = mb_start;
+ movePointerTo(stream, (startPacket & -8));
+ break;
+ }
+
+ /* Store the QP value for later use in AC prediction */
+ QPMB[mbnum] = QP;
+
+ if (Mode[mbnum] != MODE_SKIPPED)
+ {
+ /* decode the DCT coeficients for the MB */
+ status = GetMBData(video);
+ if (status != PV_SUCCESS)
+ {
+ VideoDecoderErrorDetected(video);
+ video->mbnum = mb_start;
+ movePointerTo(stream, (startPacket & -8));
+ break;
+ }
+ }
+ else /* MODE_SKIPPED */
+ {
+ SkippedMBMotionComp(video); /* 08/04/05 */
+ }
+ // Motion compensation and put video->mblock->pred_block
+ mbnum++;
+
+ /* remove any stuffing bits */
+ BitstreamShowBits16(stream, stuffing_length, &code);
+ while (code == 1)
+ {
+ PV_BitstreamFlushBits(stream, stuffing_length);
+ BitstreamShowBits16(stream, stuffing_length, &code);
+ }
+
+ /* have we reached the end of the video packet or vop? */
+ if (shortVideoHeader)
+ {
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ if (!video->slice_structure)
+ {
+#endif
+ if (mbnum >= (int)(video->mbnum_row + 1)*video->nMBinGOB) /* 10/11/01 */
+ {
+ if (mbnum >= nTotalMB) return PV_SUCCESS;
+ status = BitstreamShowBits32(stream, GOB_RESYNC_MARKER_LENGTH, &tmpvar);
+
+ if (tmpvar == GOB_RESYNC_MARKER)
+ {
+ break;
+ }
+ else
+ {
+ status = PV_BitstreamShowBitsByteAlign(stream, GOB_RESYNC_MARKER_LENGTH, &tmpvar);
+ if (tmpvar == GOB_RESYNC_MARKER) break;
+ }
+ }
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ }
+ else
+ {
+
+ if (mbnum >= nTotalMB) /* in case no valid stuffing 06/23/01 */
+ {
+ valid_stuffing = validStuffing_h263(stream);
+ if (valid_stuffing == 0)
+ {
+ VideoDecoderErrorDetected(video);
+ ConcealPacket(video, mb_start, nTotalMB, slice_counter);
+ }
+ return PV_SUCCESS;
+ }
+ /* ANNEX_K */
+ PV_BitstreamShowBitsByteAlignNoForceStuffing(stream, 17, &tmpvar);
+ if (tmpvar == RESYNC_MARKER)
+ {
+ valid_stuffing = validStuffing_h263(stream);
+ if (valid_stuffing)
+ break; /* 06/21/01 */
+ }
+
+ }
+#endif
+ }
+ else
+ {
+ if (mbnum >= nTotalMB) /* in case no valid stuffing 06/23/01 */
+ {
+ /* 11/01/2002 if we are at the end of the frame and there is some garbage data
+ at the end of the frame (i.e. no next startcode) break if the stuffing is valid */
+ valid_stuffing = validStuffing(stream);
+ if (valid_stuffing == 0)
+ {
+ /* end 11/01/2002 */
+ VideoDecoderErrorDetected(video);
+ ConcealPacket(video, mb_start, nTotalMB, slice_counter);
+ }
+ PV_BitstreamByteAlign(stream);
+ return PV_SUCCESS;
+ }
+
+ status = PV_BitstreamShowBitsByteAlign(stream, 23, &tmpvar); /* this call is valid for f_code < 8 */
+ long_zero_bits = !tmpvar;
+
+ if ((tmpvar >> (23 - resync_marker_length)) == RESYNC_MARKER || long_zero_bits)
+ {
+ valid_stuffing = validStuffing(stream);
+ if (valid_stuffing)
+ break; /* 06/21/01 */
+ }
+
+ }
+ }
+ while (TRUE);
+
+ if (shortVideoHeader)
+ { /* We need to check newgob to refresh quantizer */
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ if (!video->slice_structure)
+ {
+#endif
+ while ((status = PV_GobHeader(video)) == PV_FAIL)
+ {
+ if ((status = quickSearchGOBHeader(stream)) != PV_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ mbnum = currVop->gobNumber * video->nMBinGOB;
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ }
+ else
+ {
+ while ((status = PV_H263SliceHeader(video, &mbnum)) == PV_FAIL)
+ {
+ if ((status = quickSearchH263SliceHeader(stream)) != PV_SUCCESS)
+ {
+ break;
+ }
+ }
+ }
+
+#endif
+ }
+ else
+ {
+ while ((status = PV_ReadVideoPacketHeader(video, &mbnum)) == PV_FAIL)
+ {
+ if ((status = quickSearchVideoPacketHeader(stream, resync_marker_length)) != PV_SUCCESS)
+ {
+ break;
+ }
+ }
+ }
+
+ if (status == PV_END_OF_VOP)
+ {
+ mbnum = nTotalMB;
+ }
+
+ if (mbnum > video->mbnum + 1)
+ {
+ ConcealPacket(video, video->mbnum, mbnum, slice_counter);
+ }
+ QP = video->currVop->quantizer;
+ slice_counter++;
+ if (mbnum >= nTotalMB) break;
+
+ }
+ while (TRUE);
+ return PV_SUCCESS;
+}
+
+
+/* ============================================================================ */
+/* Function : GetMBHeader() */
+/* Purpose : Decode MB header, not_coded, mcbpc, ac_pred_flag, cbpy, dquant. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* */
+/* 3/29/00 : Changed the returned value and optimized the code. */
+/* 4/01/01 : new ACDC prediction structure */
+/* ============================================================================ */
+PV_STATUS GetMBheader(VideoDecData *video, int16 *QP)
+{
+ BitstreamDecVideo *stream = video->bitstream;
+ int mbnum = video->mbnum;
+ uint8 *Mode = video->headerInfo.Mode;
+ int x_pos = video->mbnum_col;
+ typeDCStore *DC = video->predDC + mbnum;
+ typeDCACStore *DCAC_row = video->predDCAC_row + x_pos;
+ typeDCACStore *DCAC_col = video->predDCAC_col;
+ const static int16 DQ_tab[4] = { -1, -2, 1, 2};
+
+ int CBPY, CBPC;
+ int MBtype, VopType;
+ int MCBPC;
+ uint DQUANT;
+ int comp;
+ Bool mb_coded;
+
+ VopType = video->currVop->predictionType;
+ mb_coded = ((VopType == I_VOP) ? TRUE : !BitstreamRead1Bits_INLINE(stream));
+
+ if (!mb_coded)
+ {
+ /* skipped macroblock */
+ Mode[mbnum] = MODE_SKIPPED;
+ //oscl_memset(DCAC_row, 0, sizeof(typeDCACStore)); /* SKIPPED_ACDC */
+ //oscl_memset(DCAC_col, 0, sizeof(typeDCACStore));
+ ZERO_OUT_64BYTES(DCAC_row);
+ ZERO_OUT_64BYTES(DCAC_col); /* 08/12/05 */
+
+ for (comp = 0; comp < 6; comp++)
+ {
+ (*DC)[comp] = mid_gray;
+ }
+ }
+ else
+ {
+ /* coded macroblock */
+ if (VopType == I_VOP)
+ {
+ MCBPC = PV_VlcDecMCBPC_com_intra(stream);
+ }
+ else
+ {
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ if (!video->deblocking)
+ {
+ MCBPC = PV_VlcDecMCBPC_com_inter(stream);
+ }
+ else
+ {
+ MCBPC = PV_VlcDecMCBPC_com_inter_H263(stream);
+ }
+#else
+ MCBPC = PV_VlcDecMCBPC_com_inter(stream);
+#endif
+ }
+
+ if (VLC_ERROR_DETECTED(MCBPC))
+ {
+ return PV_FAIL;
+ }
+
+ Mode[mbnum] = (uint8)(MBtype = MBtype_mode[MCBPC & 7]);
+ CBPC = (MCBPC >> 4) & 3;
+
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ if (MBtype & INTRA_MASK)
+ {
+ if (!video->shortVideoHeader)
+ {
+ video->acPredFlag[mbnum] = (uint8) BitstreamRead1Bits(stream);
+ }
+ else
+ {
+ if (video->advanced_INTRA)
+ {
+ if (!BitstreamRead1Bits(stream))
+ {
+ video->acPredFlag[mbnum] = 0;
+ }
+ else
+ {
+ video->acPredFlag[mbnum] = 1;
+ if (BitstreamRead1Bits(stream))
+ {
+ video->mblock->direction = 0;
+ }
+ else
+ {
+ video->mblock->direction = 1;
+ }
+ }
+ }
+ else
+ {
+ video->acPredFlag[mbnum] = 0;
+ }
+ }
+ }
+#else
+ if ((MBtype & INTRA_MASK) && !video->shortVideoHeader)
+ {
+ video->acPredFlag[mbnum] = (uint8) BitstreamRead1Bits_INLINE(stream);
+ }
+ else
+ {
+ video->acPredFlag[mbnum] = 0;
+ }
+#endif
+ CBPY = PV_VlcDecCBPY(stream, MBtype & INTRA_MASK); /* INTRA || INTRA_Q */
+ if (CBPY < 0)
+ {
+ return PV_FAIL;
+ }
+
+ // GW 04/23/99
+ video->headerInfo.CBP[mbnum] = (uint8)(CBPY << 2 | (CBPC & 3));
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ if (MBtype & Q_MASK)
+ {
+ if (!video->modified_quant)
+ {
+ DQUANT = BitstreamReadBits16(stream, 2);
+ *QP += DQ_tab[DQUANT];
+
+ if (*QP < 1) *QP = 1;
+ else if (*QP > 31) *QP = 31;
+ video->QP_CHR = *QP; /* ANNEX_T */
+ }
+ else
+ {
+ if (BitstreamRead1Bits(stream))
+ {
+ if (BitstreamRead1Bits(stream))
+ {
+ *QP += DQ_tab_Annex_T_11[*QP];
+ }
+ else
+ {
+ *QP += DQ_tab_Annex_T_10[*QP];
+ }
+ if (*QP < 1) *QP = 1;
+ else if (*QP > 31) *QP = 31;
+ }
+ else
+ {
+ *QP = (int16)BitstreamReadBits16(stream, 5);
+ }
+ video->QP_CHR = MQ_chroma_QP_table[*QP];
+ }
+ }
+#else
+ if (MBtype & Q_MASK)
+ {
+ DQUANT = BitstreamReadBits16(stream, 2);
+ *QP += DQ_tab[DQUANT];
+
+ if (*QP < 1) *QP = 1;
+ else if (*QP > 31) *QP = 31;
+ }
+#endif
+ }
+ return PV_SUCCESS;
+}
+
+
+
+
+
+/***********************************************************CommentBegin******
+* 3/10/00 : initial modification to the
+* new PV-Decoder Lib format.
+* 4/2/2000 : Cleanup and error-handling modification. This
+* function has been divided into several sub-functions for
+* better coding style and maintainance reason. I also
+* greatly shrunk the code size here.
+* 9/18/2000 : VlcDecode+Dequant optimization *
+* 4/01/2001 : new ACDC prediction structure
+* 3/29/2002 : removed GetIntraMB and GetInterMB
+***********************************************************CommentEnd********/
+PV_STATUS GetMBData(VideoDecData *video)
+{
+ BitstreamDecVideo *stream = video->bitstream;
+ int mbnum = video->mbnum;
+ MacroBlock *mblock = video->mblock;
+ int16 *dataBlock;
+ PIXEL *c_comp;
+ uint mode = video->headerInfo.Mode[mbnum];
+ uint CBP = video->headerInfo.CBP[mbnum];
+ typeDCStore *DC = video->predDC + mbnum;
+ int intra_dc_vlc_thr = video->currVop->intraDCVlcThr;
+ int16 QP = video->QPMB[mbnum];
+ int16 QP_tmp = QP;
+ int width = video->width;
+ int comp;
+ int switched;
+ int ncoeffs[6] = {0, 0, 0, 0, 0, 0};
+ int *no_coeff = mblock->no_coeff;
+ int16 DC_coeff;
+ PV_STATUS status;
+
+#ifdef PV_POSTPROC_ON
+ /* post-processing */
+ uint8 *pp_mod[6];
+ int TotalMB = video->nTotalMB;
+ int MB_in_width = video->nMBPerRow;
+#endif
+ int y_pos = video->mbnum_row;
+ int x_pos = video->mbnum_col;
+ int32 offset = (int32)(y_pos << 4) * width + (x_pos << 4);
+
+ /* Decode each 8-by-8 blocks. comp 0 ~ 3 are luminance blocks, 4 ~ 5 */
+ /* are chrominance blocks. 04/03/2000. */
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ {
+ /** post-processing ***/
+ pp_mod[0] = video->pstprcTypCur + (y_pos << 1) * (MB_in_width << 1) + (x_pos << 1);
+ pp_mod[1] = pp_mod[0] + 1;
+ pp_mod[2] = pp_mod[0] + (MB_in_width << 1);
+ pp_mod[3] = pp_mod[2] + 1;
+ pp_mod[4] = video->pstprcTypCur + (TotalMB << 2) + mbnum;
+ pp_mod[5] = pp_mod[4] + TotalMB;
+ }
+#endif
+
+ /* oscl_memset(mblock->block, 0, sizeof(typeMBStore)); Aug 9,2005 */
+
+ if (mode & INTRA_MASK) /* MODE_INTRA || MODE_INTRA_Q */
+ {
+ switched = 0;
+ if (intra_dc_vlc_thr)
+ {
+ if (video->usePrevQP)
+ QP_tmp = video->QPMB[mbnum-1]; /* running QP 04/26/01 */
+
+ switched = (intra_dc_vlc_thr == 7 || QP_tmp >= intra_dc_vlc_thr * 2 + 11);
+ }
+
+ mblock->DCScalarLum = cal_dc_scaler(QP, LUMINANCE_DC_TYPE); /* 3/01/01 */
+ mblock->DCScalarChr = cal_dc_scaler(QP, CHROMINANCE_DC_TYPE);
+
+ for (comp = 0; comp < 6; comp++)
+ {
+ dataBlock = mblock->block[comp]; /* 10/20/2000 */
+
+ if (video->shortVideoHeader)
+ {
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ if (!video->advanced_INTRA)
+ {
+#endif
+ DC_coeff = (int16) BitstreamReadBits16_INLINE(stream, 8);
+
+ if ((DC_coeff & 0x7f) == 0) /* 128 & 0 */
+ {
+ /* currently we will only signal FAIL for 128. We will ignore the 0 case */
+ if (DC_coeff == 128)
+ {
+ return PV_FAIL;
+ }
+ else
+ {
+ VideoDecoderErrorDetected(video);
+ }
+ }
+ if (DC_coeff == 255)
+ {
+ DC_coeff = 128;
+ }
+ dataBlock[0] = (int16) DC_coeff;
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ }
+#endif
+ ncoeffs[comp] = VlcDequantH263IntraBlock_SH(video, comp, mblock->bitmapcol[comp], &mblock->bitmaprow[comp]);
+
+ }
+ else
+ {
+ if (switched == 0)
+ {
+ status = PV_DecodePredictedIntraDC(comp, stream, &DC_coeff);
+ if (status != PV_SUCCESS) return PV_FAIL;
+
+ dataBlock[0] = (int16) DC_coeff;
+ }
+ ncoeffs[comp] = VlcDequantH263IntraBlock(video, comp,
+ switched, mblock->bitmapcol[comp], &mblock->bitmaprow[comp]);
+ }
+
+ if (VLC_ERROR_DETECTED(ncoeffs[comp]))
+ {
+ if (switched)
+ return PV_FAIL;
+ else
+ {
+ ncoeffs[comp] = 1;
+ oscl_memset((dataBlock + 1), 0, sizeof(int16)*63);
+ }
+ }
+ no_coeff[comp] = ncoeffs[comp];
+
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[comp] = (uint8) PostProcSemaphore(dataBlock);
+#endif
+ }
+ MBlockIDCT(video);
+ }
+ else /* INTER modes */
+ { /* moved it here Aug 15, 2005 */
+ /* decode the motion vector (if there are any) */
+ status = PV_GetMBvectors(video, mode);
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+
+
+ MBMotionComp(video, CBP);
+ c_comp = video->currVop->yChan + offset;
+
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ for (comp = 0; comp < 4; comp++)
+ {
+ (*DC)[comp] = mid_gray;
+ if (CBP & (1 << (5 - comp)))
+ {
+ ncoeffs[comp] = VlcDequantH263InterBlock(video, comp, mblock->bitmapcol[comp], &mblock->bitmaprow[comp]);
+ if (VLC_ERROR_DETECTED(ncoeffs[comp])) return PV_FAIL;
+
+ BlockIDCT(c_comp + (comp&2)*(width << 2) + 8*(comp&1), mblock->pred_block + (comp&2)*64 + 8*(comp&1), mblock->block[comp], width, ncoeffs[comp],
+ mblock->bitmapcol[comp], mblock->bitmaprow[comp]);
+
+#ifdef PV_POSTPROC_ON
+ /* for inter just test for ringing */
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[comp] = (uint8)((ncoeffs[comp] > 3) ? 4 : 0);
+#endif
+ }
+ else
+ {
+ /* no IDCT for all zeros blocks 03/28/2002 */
+ /* BlockIDCT(); */
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[comp] = 0;
+#endif
+ }
+ }
+
+ video->QPMB[mbnum] = video->QP_CHR; /* ANNEX_T */
+
+
+
+ (*DC)[4] = mid_gray;
+ if (CBP & 2)
+ {
+ ncoeffs[4] = VlcDequantH263InterBlock(video, 4, mblock->bitmapcol[4], &mblock->bitmaprow[4]);
+ if (VLC_ERROR_DETECTED(ncoeffs[4])) return PV_FAIL;
+
+ BlockIDCT(video->currVop->uChan + (offset >> 2) + (x_pos << 2), mblock->pred_block + 256, mblock->block[4], width >> 1, ncoeffs[4],
+ mblock->bitmapcol[4], mblock->bitmaprow[4]);
+
+#ifdef PV_POSTPROC_ON
+ /* for inter just test for ringing */
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[4] = (uint8)((ncoeffs[4] > 3) ? 4 : 0);
+#endif
+ }
+ else
+ {
+ /* no IDCT for all zeros blocks 03/28/2002 */
+ /* BlockIDCT(); */
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[4] = 0;
+#endif
+ }
+ (*DC)[5] = mid_gray;
+ if (CBP & 1)
+ {
+ ncoeffs[5] = VlcDequantH263InterBlock(video, 5, mblock->bitmapcol[5], &mblock->bitmaprow[5]);
+ if (VLC_ERROR_DETECTED(ncoeffs[5])) return PV_FAIL;
+
+ BlockIDCT(video->currVop->vChan + (offset >> 2) + (x_pos << 2), mblock->pred_block + 264, mblock->block[5], width >> 1, ncoeffs[5],
+ mblock->bitmapcol[5], mblock->bitmaprow[5]);
+
+#ifdef PV_POSTPROC_ON
+ /* for inter just test for ringing */
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[5] = (uint8)((ncoeffs[5] > 3) ? 4 : 0);
+#endif
+ }
+ else
+ {
+ /* no IDCT for all zeros blocks 03/28/2002 */
+ /* BlockIDCT(); */
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[5] = 0;
+#endif
+ }
+ video->QPMB[mbnum] = QP; /* restore the QP values ANNEX_T*/
+#else
+ for (comp = 0; comp < 4; comp++)
+ {
+ (*DC)[comp] = mid_gray;
+ if (CBP & (1 << (5 - comp)))
+ {
+ ncoeffs[comp] = VlcDequantH263InterBlock(video, comp, mblock->bitmapcol[comp], &mblock->bitmaprow[comp]);
+ if (VLC_ERROR_DETECTED(ncoeffs[comp])) return PV_FAIL;
+
+ BlockIDCT(c_comp + (comp&2)*(width << 2) + 8*(comp&1), mblock->pred_block + (comp&2)*64 + 8*(comp&1), mblock->block[comp], width, ncoeffs[comp],
+ mblock->bitmapcol[comp], mblock->bitmaprow[comp]);
+
+#ifdef PV_POSTPROC_ON
+ /* for inter just test for ringing */
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[comp] = (uint8)((ncoeffs[comp] > 3) ? 4 : 0);
+#endif
+ }
+ else
+ {
+ /* no IDCT for all zeros blocks 03/28/2002 */
+ /* BlockIDCT(); */
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[comp] = 0;
+#endif
+ }
+ }
+
+ (*DC)[4] = mid_gray;
+ if (CBP & 2)
+ {
+ ncoeffs[4] = VlcDequantH263InterBlock(video, 4, mblock->bitmapcol[4], &mblock->bitmaprow[4]);
+ if (VLC_ERROR_DETECTED(ncoeffs[4])) return PV_FAIL;
+
+ BlockIDCT(video->currVop->uChan + (offset >> 2) + (x_pos << 2), mblock->pred_block + 256, mblock->block[4], width >> 1, ncoeffs[4],
+ mblock->bitmapcol[4], mblock->bitmaprow[4]);
+
+#ifdef PV_POSTPROC_ON
+ /* for inter just test for ringing */
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[4] = (uint8)((ncoeffs[4] > 3) ? 4 : 0);
+#endif
+ }
+ else
+ {
+ /* no IDCT for all zeros blocks 03/28/2002 */
+ /* BlockIDCT(); */
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[4] = 0;
+#endif
+ }
+ (*DC)[5] = mid_gray;
+ if (CBP & 1)
+ {
+ ncoeffs[5] = VlcDequantH263InterBlock(video, 5, mblock->bitmapcol[5], &mblock->bitmaprow[5]);
+ if (VLC_ERROR_DETECTED(ncoeffs[5])) return PV_FAIL;
+
+ BlockIDCT(video->currVop->vChan + (offset >> 2) + (x_pos << 2), mblock->pred_block + 264, mblock->block[5], width >> 1, ncoeffs[5],
+ mblock->bitmapcol[5], mblock->bitmaprow[5]);
+
+#ifdef PV_POSTPROC_ON
+ /* for inter just test for ringing */
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[5] = (uint8)((ncoeffs[5] > 3) ? 4 : 0);
+#endif
+ }
+ else
+ {
+ /* no IDCT for all zeros blocks 03/28/2002 */
+ /* BlockIDCT(); */
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[5] = 0;
+#endif
+#endif // PV_ANNEX_IJKT_SUPPORT
+
+
+
+
+
+
+ }
+
+ video->usePrevQP = 1; /* should be set after decoding the first Coded 04/27/01 */
+ return PV_SUCCESS;
+}
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
new file mode 100644
index 0000000..e9ead01
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
@@ -0,0 +1,193 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_lib.h" /* video decoder function prototypes */
+#include "vlc_decode.h"
+#include "bitstream.h"
+#include "scaling.h"
+
+/* ====================================================================== /
+Function : ConcealTexture_I()
+Date : 06/12/2001
+Purpose : Conceal texture for I-partition
+In/out :
+Return :
+Modified :
+/ ====================================================================== */
+void ConcealTexture_I(VideoDecData *video, int32 startFirstPartition, int mb_start, int mb_stop, int slice_counter)
+{
+ int mbnum;
+ BitstreamDecVideo *stream = video->bitstream;
+ int16 QP;
+ int intra_dc_vlc_thr = video->currVop->intraDCVlcThr;
+
+ movePointerTo(stream, startFirstPartition);
+
+ video->usePrevQP = 0;
+ for (mbnum = mb_start; mbnum < mb_stop; mbnum++)
+ {
+ video->mbnum = mbnum;
+ video->mbnum_row = PV_GET_ROW(mbnum, video->nMBPerRow);
+ video->mbnum_col = mbnum - video->mbnum_row * video->nMBPerRow;
+ video->sliceNo[mbnum] = (uint8) slice_counter;
+ QP = video->QPMB[mbnum];
+ PV_VlcDecMCBPC_com_intra(stream);
+ GetMBheaderDataPart_DQUANT_DC(video, &QP);
+
+ if (intra_dc_vlc_thr)
+ {
+ if (video->usePrevQP)
+ QP = video->QPMB[mbnum-1];
+ if (intra_dc_vlc_thr == 7 || QP >= intra_dc_vlc_thr*2 + 11) /* if switched then conceal from previous frame */
+ {
+ ConcealPacket(video, mbnum, mb_stop, slice_counter);
+ video->mbnum = mb_stop - 1;
+ video->mbnum_row = PV_GET_ROW(video->mbnum, video->nMBPerRow);
+ video->mbnum_col = video->mbnum - video->mbnum_row * video->nMBPerRow;
+ break;
+ }
+ }
+
+ video->headerInfo.CBP[mbnum] = 0;
+ video->acPredFlag[mbnum] = 0;
+ GetMBData_DataPart(video);
+ video->usePrevQP = 1;
+ }
+ return;
+}
+
+/* ====================================================================== /
+Function : ConcealTexture_P()
+Date : 05/16/2000
+Purpose : Conceal texture for P-partition
+In/out :
+Return :
+/ ====================================================================== */
+
+void ConcealTexture_P(VideoDecData *video, int mb_start, int mb_stop, int slice_counter)
+{
+ int mbnum;
+
+ for (mbnum = mb_start; mbnum < mb_stop; mbnum++)
+ {
+ video->mbnum = mbnum;
+ video->mbnum_row = PV_GET_ROW(mbnum, video->nMBPerRow);
+ video->mbnum_col = mbnum - video->mbnum_row * video->nMBPerRow;
+ video->sliceNo[mbnum] = (uint8) slice_counter;
+ oscl_memset(video->mblock->block, 0, sizeof(typeMBStore));
+ /* to get rid of dark region caused by INTRA blocks */
+ /* 05/19/2000 */
+ if (video->headerInfo.Mode[mbnum] & INTER_MASK)
+ {
+ MBMotionComp(video, 0);
+ }
+ else
+ {
+ video->headerInfo.Mode[mbnum] = MODE_SKIPPED;
+ SkippedMBMotionComp(video);
+ }
+ }
+
+ return;
+}
+
+/***************************************************************
+Function: ConcealPacket
+Purpose : Conceal motion and texture of a packet by direct
+copying from previous frame.
+Returned: void
+Modified:
+*************************************************************/
+void ConcealPacket(VideoDecData *video,
+ int mb_start,
+ int mb_stop,
+ int slice_counter)
+{
+ int i;
+ for (i = mb_start; i < mb_stop; i++)
+ {
+ CopyVopMB(video->currVop, video->concealFrame, i, video->width, video->height);
+ video->sliceNo[i] = (uint8) slice_counter;
+ video->headerInfo.Mode[i] = MODE_SKIPPED;
+ }
+
+ return;
+}
+
+/****************************************************************************
+Function: CopyVopMB
+Purpose : Fill a macroblock with previous Vop.
+Returned : void
+Modified: 6/04/2001 rewrote the function
+ copies from concealFrame
+****************************************************************************/
+void CopyVopMB(Vop *curr, uint8 *prevFrame, int mbnum, int width_Y, int height)
+{
+ int width_C = width_Y >> 1;
+ int row = MB_SIZE;
+ uint8 *y1, *y2, *u1, *u2, *v1, *v2;
+ int xpos, ypos, MB_in_width;
+ int32 lumstart, chrstart, size;
+
+ MB_in_width = (width_Y + 15) >> 4;
+ ypos = PV_GET_ROW(mbnum, MB_in_width);
+ xpos = mbnum - ypos * MB_in_width;
+ lumstart = (ypos << 4) * (int32)width_Y + (xpos << 4);
+ chrstart = (ypos << 3) * (int32)width_C + (xpos << 3);
+
+ size = (int32)height * width_Y;
+
+ y1 = curr->yChan + lumstart;
+ u1 = curr->uChan + chrstart;
+ v1 = curr->vChan + chrstart;
+ y2 = prevFrame + lumstart;
+ u2 = prevFrame + size + chrstart;
+ v2 = prevFrame + size + (size >> 2) + chrstart;
+ while (row)
+ {
+ oscl_memcpy(y1, y2, MB_SIZE);
+ y1 += width_Y;
+ y2 += width_Y;
+ oscl_memcpy(y1, y2, MB_SIZE);
+ y1 += width_Y;
+ y2 += width_Y;
+ oscl_memcpy(y1, y2, MB_SIZE);
+ y1 += width_Y;
+ y2 += width_Y;
+ oscl_memcpy(y1, y2, MB_SIZE);
+ y1 += width_Y;
+ y2 += width_Y;
+
+ oscl_memcpy(u1, u2, B_SIZE);
+ u1 += width_C;
+ u2 += width_C;
+ oscl_memcpy(u1, u2, B_SIZE);
+ u1 += width_C;
+ u2 += width_C;
+
+ oscl_memcpy(v1, v2, B_SIZE);
+ v1 += width_C;
+ v2 += width_C;
+ oscl_memcpy(v1, v2, B_SIZE);
+ v1 += width_C;
+ v2 += width_C;
+
+ row -= 4;
+ }
+ return;
+} /* CopyVopMB */
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/datapart_decode.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/datapart_decode.cpp
new file mode 100644
index 0000000..00db04b
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/datapart_decode.cpp
@@ -0,0 +1,794 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_lib.h"
+#include "vlc_decode.h"
+#include "bitstream.h"
+#include "scaling.h"
+#include "mbtype_mode.h"
+#include "idct.h"
+
+#define OSCL_DISABLE_WARNING_CONDITIONAL_IS_CONSTANT
+/* ======================================================================== */
+/* Function : DecodeFrameDataPartMode() */
+/* Purpose : Decode a frame of MPEG4 bitstream in datapartitioning mode. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* */
+/* 04/25/2000 : Rewrite the data partitioning path completely */
+/* according to the pseudo codes in MPEG-4 */
+/* standard. */
+/* Modified : 09/18/2000 add fast VlcDecode+Dequant */
+/* 04/17/2001 cleanup */
+/* ======================================================================== */
+PV_STATUS DecodeFrameDataPartMode(VideoDecData *video)
+{
+ PV_STATUS status;
+ Vop *currVop = video->currVop;
+ BitstreamDecVideo *stream = video->bitstream;
+
+ int nMBPerRow = video->nMBPerRow;
+
+ int vopType = currVop->predictionType;
+ int mbnum;
+ int nTotalMB = video->nTotalMB;
+ int slice_counter;
+ int resync_marker_length;
+
+ /* copy and pad to prev_Vop for INTER coding */
+ switch (vopType)
+ {
+ case I_VOP :
+// oscl_memset(Mode, MODE_INTRA, sizeof(uint8)*nTotalMB);
+ resync_marker_length = 17;
+ break;
+ case P_VOP :
+ oscl_memset(video->motX, 0, sizeof(MOT)*4*nTotalMB);
+ oscl_memset(video->motY, 0, sizeof(MOT)*4*nTotalMB);
+// oscl_memset(Mode, MODE_INTER, sizeof(uint8)*nTotalMB);
+ resync_marker_length = 16 + currVop->fcodeForward;
+ break;
+ default :
+ mp4dec_log("DecodeFrameDataPartMode(): Vop type not supported.\n");
+ return PV_FAIL;
+ }
+
+ /** Initialize sliceNo ***/
+ mbnum = slice_counter = 0;
+// oscl_memset(video->sliceNo, 0, sizeof(uint8)*nTotalMB);
+
+ do
+ {
+ /* This section is equivalent to motion_shape_texture() */
+ /* in the MPEG-4 standard. 04/13/2000 */
+ video->mbnum = mbnum;
+ video->mbnum_row = PV_GET_ROW(mbnum, nMBPerRow); /* This is needed if nbnum is read from the packet header */
+ video->mbnum_col = mbnum - video->mbnum_row * nMBPerRow;
+
+ switch (vopType)
+ {
+ case I_VOP :
+ status = DecodeDataPart_I_VideoPacket(video, slice_counter);
+ break;
+
+ case P_VOP :
+ status = DecodeDataPart_P_VideoPacket(video, slice_counter);
+ break;
+
+ default :
+ mp4dec_log("DecodeFrameDataPartMode(): Vop type not supported.\n");
+ return PV_FAIL;
+ }
+
+ while ((status = PV_ReadVideoPacketHeader(video, &mbnum)) == PV_FAIL)
+ {
+ if ((status = quickSearchVideoPacketHeader(stream, resync_marker_length)) != PV_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ if (status == PV_END_OF_VOP)
+ {
+ mbnum = nTotalMB;
+ }
+
+ if (mbnum > video->mbnum + 1)
+ {
+ ConcealPacket(video, video->mbnum, mbnum, slice_counter);
+ }
+ slice_counter++;
+ if (mbnum >= nTotalMB)
+ {
+ break;
+ }
+
+
+ }
+ while (TRUE);
+
+ return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/* Function : DecodeDataPart_I_VideoPacket() */
+/* Date : 04/25/2000 */
+/* Purpose : Decode Data Partitioned Mode Video Packet in I-VOP */
+/* In/out : */
+/* Return : PV_SUCCESS if successed, PV_FAIL if failed. */
+/* Modified : 09/18/2000 add fast VlcDecode+Dequant */
+/* 04/01/2001 fixed MB_stuffing, removed unnecessary code */
+/* ======================================================================== */
+PV_STATUS DecodeDataPart_I_VideoPacket(VideoDecData *video, int slice_counter)
+{
+ PV_STATUS status;
+ uint8 *Mode = video->headerInfo.Mode;
+ BitstreamDecVideo *stream = video->bitstream;
+ int nTotalMB = video->nTotalMB;
+ int mbnum, mb_start, mb_end;
+ int16 QP, *QPMB = video->QPMB;
+ int MBtype, MCBPC, CBPY;
+ uint32 tmpvar;
+ uint code;
+ int nMBPerRow = video->nMBPerRow;
+ Bool valid_stuffing;
+ int32 startSecondPart, startFirstPart = getPointer(stream);
+
+ /* decode the first partition */
+ QP = video->currVop->quantizer;
+ mb_start = mbnum = video->mbnum;
+ video->usePrevQP = 0; /* 04/27/01 */
+
+
+ BitstreamShowBits16(stream, 9, &code);
+ while (code == 1)
+ {
+ PV_BitstreamFlushBits(stream, 9);
+ BitstreamShowBits16(stream, 9, &code);
+ }
+
+ do
+ {
+ /* decode COD, MCBPC, ACpred_flag, CPBY and DQUANT */
+ MCBPC = PV_VlcDecMCBPC_com_intra(stream);
+
+ if (!VLC_ERROR_DETECTED(MCBPC))
+ {
+ Mode[mbnum] = (uint8)(MBtype = MBtype_mode[MCBPC & 7]);
+ video->headerInfo.CBP[mbnum] = (uint8)((MCBPC >> 4) & 3);
+ status = GetMBheaderDataPart_DQUANT_DC(video, &QP);
+ video->usePrevQP = 1; /* set it after the first coded MB 04/27/01 */
+ }
+ else
+ {
+ /* Report the error to the application. 06/20/2000 */
+ VideoDecoderErrorDetected(video);
+ video->mbnum = mb_start;
+ movePointerTo(stream, startFirstPart);
+ return PV_FAIL;
+ }
+
+ video->sliceNo[mbnum] = (uint8) slice_counter;
+ QPMB[mbnum] = QP;
+ video->mbnum = ++mbnum;
+
+ BitstreamShowBits16(stream, 9, &code);
+ while (code == 1)
+ {
+ PV_BitstreamFlushBits(stream, 9);
+ BitstreamShowBits16(stream, 9, &code);
+ }
+ /* have we reached the end of the video packet or vop? */
+ status = BitstreamShowBits32(stream, DC_MARKER_LENGTH, &tmpvar);
+
+ }
+ while (tmpvar != DC_MARKER && video->mbnum < nTotalMB);
+
+ if (tmpvar == DC_MARKER)
+ {
+ PV_BitstreamFlushBits(stream, DC_MARKER_LENGTH);
+ }
+ else
+ {
+ status = quickSearchDCM(stream);
+ if (status == PV_SUCCESS)
+ {
+ /* only way you can end up being here is in the last packet,and there is stuffing at
+ the end of the first partition */
+ PV_BitstreamFlushBits(stream, DC_MARKER_LENGTH);
+ }
+ else
+ {
+ /* Report the error to the application. 06/20/2000 */
+ VideoDecoderErrorDetected(video);
+ movePointerTo(stream, startFirstPart);
+ video->mbnum = mb_start;
+ /* concealment will be taken care of in the upper layer */
+ return PV_FAIL;
+ }
+ }
+
+ /* decode the second partition */
+ startSecondPart = getPointer(stream);
+
+ mb_end = video->mbnum;
+
+ for (mbnum = mb_start; mbnum < mb_end; mbnum++)
+ {
+ MBtype = Mode[mbnum];
+ /* No skipped mode in I-packets 3/1/2001 */
+ video->mbnum = mbnum;
+
+ video->mbnum_row = PV_GET_ROW(mbnum, nMBPerRow); /* This is needed if nbnum is read from the packet header */
+ video->mbnum_col = mbnum - video->mbnum_row * nMBPerRow;
+ /* there is always acdcpred in DataPart mode 04/10/01 */
+ video->acPredFlag[mbnum] = (uint8) BitstreamRead1Bits(stream);
+
+ CBPY = PV_VlcDecCBPY(stream, MBtype & INTRA_MASK); /* MODE_INTRA || MODE_INTRA_Q */
+ if (CBPY < 0)
+ {
+ /* Report the error to the application. 06/20/2000 */
+ VideoDecoderErrorDetected(video);
+ movePointerTo(stream, startSecondPart); /* */
+ /* Conceal packet, 05/15/2000 */
+ ConcealTexture_I(video, startFirstPart, mb_start, mb_end, slice_counter);
+ return PV_FAIL;
+ }
+
+ video->headerInfo.CBP[mbnum] |= (uint8)(CBPY << 2);
+ }
+
+ video->usePrevQP = 0;
+
+ for (mbnum = mb_start; mbnum < mb_end; mbnum++)
+ {
+ video->mbnum = mbnum;
+
+ video->mbnum_row = PV_GET_ROW(mbnum , nMBPerRow); /* This is needed if nbnum is read from the packet header */
+ video->mbnum_col = mbnum - video->mbnum_row * nMBPerRow;
+ /* No skipped mode in I-packets 3/1/2001 */
+ /* decode the DCT coeficients for the MB */
+ status = GetMBData_DataPart(video);
+ if (status != PV_SUCCESS)
+ {
+ /* Report the error to the application. 06/20/2000 */
+ VideoDecoderErrorDetected(video);
+ movePointerTo(stream, startSecondPart); /* */
+ /* Conceal packet, 05/15/2000 */
+ ConcealTexture_I(video, startFirstPart, mb_start, mb_end, slice_counter);
+ return status;
+ }
+ video->usePrevQP = 1; /* 04/27/01 should be set after decoding first MB */
+ }
+
+ valid_stuffing = validStuffing(stream);
+ if (!valid_stuffing)
+ {
+ VideoDecoderErrorDetected(video);
+ movePointerTo(stream, startSecondPart);
+ ConcealTexture_I(video, startFirstPart, mb_start, mb_end, slice_counter);
+ return PV_FAIL;
+ }
+ return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/* Function : DecodeDataPart_P_VideoPacket() */
+/* Date : 04/25/2000 */
+/* Purpose : Decode Data Partitioned Mode Video Packet in P-VOP */
+/* In/out : */
+/* Return : PV_SUCCESS if successed, PV_FAIL if failed. */
+/* Modified : 09/18/2000, fast VlcDecode+Dequant */
+/* 04/13/2001, fixed MB_stuffing, new ACDC pred structure, */
+/* cleanup */
+/* 08/07/2001, remove MBzero */
+/* ======================================================================== */
+PV_STATUS DecodeDataPart_P_VideoPacket(VideoDecData *video, int slice_counter)
+{
+ PV_STATUS status;
+ uint8 *Mode = video->headerInfo.Mode;
+ BitstreamDecVideo *stream = video->bitstream;
+ int nTotalMB = video->nTotalMB;
+ int mbnum, mb_start, mb_end;
+ int16 QP, *QPMB = video->QPMB;
+ int MBtype, CBPY;
+ Bool valid_stuffing;
+ int intra_MB;
+ uint32 tmpvar;
+ uint code;
+ int32 startFirstPart, startSecondPart;
+ int nMBPerRow = video->nMBPerRow;
+ uint8 *pbyte;
+ /* decode the first partition */
+ startFirstPart = getPointer(stream);
+ mb_start = video->mbnum;
+ video->usePrevQP = 0; /* 04/27/01 */
+
+ BitstreamShowBits16(stream, 10, &code);
+ while (code == 1)
+ {
+ PV_BitstreamFlushBits(stream, 10);
+ BitstreamShowBits16(stream, 10, &code);
+ }
+
+ do
+ {
+ /* decode COD, MCBPC, ACpred_flag, CPBY and DQUANT */
+ /* We have to discard stuffed MB header */
+
+ status = GetMBheaderDataPart_P(video);
+
+ if (status != PV_SUCCESS)
+ {
+ /* Report the error to the application. 06/20/2000 */
+ VideoDecoderErrorDetected(video);
+ movePointerTo(stream, startFirstPart);
+ video->mbnum = mb_start;
+ return PV_FAIL;
+ }
+
+ /* we must update slice_counter before motion vector decoding. */
+ video->sliceNo[video->mbnum] = (uint8) slice_counter;
+
+ if (Mode[video->mbnum] & INTER_MASK) /* INTER || INTER_Q || INTER_4V */
+ {
+ /* decode the motion vector (if there are any) */
+ status = PV_GetMBvectors(video, Mode[video->mbnum]);
+ if (status != PV_SUCCESS)
+ {
+ /* Report the error to the application. 06/20/2000 */
+ VideoDecoderErrorDetected(video);
+ movePointerTo(stream, startFirstPart);
+ video->mbnum = mb_start;
+ return PV_FAIL;
+ }
+ }
+ video->mbnum++;
+
+ video->mbnum_row = PV_GET_ROW(video->mbnum, nMBPerRow); /* This is needed if mbnum is read from the packet header */
+ video->mbnum_col = video->mbnum - video->mbnum_row * nMBPerRow;
+
+ BitstreamShowBits16(stream, 10, &code);
+ while (code == 1)
+ {
+ PV_BitstreamFlushBits(stream, 10);
+ BitstreamShowBits16(stream, 10, &code);
+ }
+ /* have we reached the end of the video packet or vop? */
+ status = BitstreamShowBits32(stream, MOTION_MARKER_COMB_LENGTH, &tmpvar);
+ /* if (status != PV_SUCCESS && status != PV_END_OF_BUFFER) return status; */
+ }
+ while (tmpvar != MOTION_MARKER_COMB && video->mbnum < nTotalMB);
+
+ if (tmpvar == MOTION_MARKER_COMB)
+ {
+ PV_BitstreamFlushBits(stream, MOTION_MARKER_COMB_LENGTH);
+ }
+ else
+ {
+ status = quickSearchMotionMarker(stream);
+ if (status == PV_SUCCESS)
+ {
+ /* only way you can end up being here is in the last packet,and there is stuffing at
+ the end of the first partition */
+ PV_BitstreamFlushBits(stream, MOTION_MARKER_COMB_LENGTH);
+ }
+ else
+ {
+ /* Report the error to the application. 06/20/2000 */
+ VideoDecoderErrorDetected(video);
+ movePointerTo(stream, startFirstPart);
+ video->mbnum = mb_start;
+ /* concealment will be taken care of in the upper layer */
+ return PV_FAIL;
+ }
+ }
+
+ /* decode the second partition */
+ startSecondPart = getPointer(stream);
+ QP = video->currVop->quantizer;
+
+ mb_end = video->mbnum;
+
+ for (mbnum = mb_start; mbnum < mb_end; mbnum++)
+ {
+ MBtype = Mode[mbnum];
+
+ if (MBtype == MODE_SKIPPED)
+ {
+ QPMB[mbnum] = QP; /* 03/01/01 */
+ continue;
+ }
+ intra_MB = (MBtype & INTRA_MASK); /* (MBtype == MODE_INTRA || MBtype == MODE_INTRA_Q) */
+ video->mbnum = mbnum;
+ video->mbnum_row = PV_GET_ROW(mbnum, nMBPerRow); /* This is needed if nbnum is read from the packet header */
+ video->mbnum_col = mbnum - video->mbnum_row * nMBPerRow;
+
+ /* there is always acdcprediction in DataPart mode 04/10/01 */
+ if (intra_MB)
+ {
+ video->acPredFlag[mbnum] = (uint8) BitstreamRead1Bits_INLINE(stream);
+ }
+
+ CBPY = PV_VlcDecCBPY(stream, intra_MB);
+ if (CBPY < 0)
+ {
+ /* Report the error to the application. 06/20/2000 */
+ VideoDecoderErrorDetected(video);
+ /* Conceal second partition, 5/15/2000 */
+ movePointerTo(stream, startSecondPart);
+ ConcealTexture_P(video, mb_start, mb_end, slice_counter);
+ return PV_FAIL;
+ }
+
+ video->headerInfo.CBP[mbnum] |= (uint8)(CBPY << 2);
+ if (intra_MB || MBtype == MODE_INTER_Q) /* 04/26/01 */
+ {
+ status = GetMBheaderDataPart_DQUANT_DC(video, &QP);
+ if (status != PV_SUCCESS) return status;
+ }
+ video->usePrevQP = 1; /* 04/27/01 */
+ QPMB[mbnum] = QP;
+ }
+
+ video->usePrevQP = 0; /* 04/27/01 */
+
+ for (mbnum = mb_start; mbnum < mb_end; mbnum++)
+ {
+ video->mbnum = mbnum;
+ video->mbnum_row = PV_GET_ROW(mbnum, nMBPerRow); /* This is needed if nbnum is read from the packet header */
+ video->mbnum_col = mbnum - video->mbnum_row * nMBPerRow;
+
+
+ if (Mode[mbnum] != MODE_SKIPPED)
+ {
+ /* decode the DCT coeficients for the MB */
+ status = GetMBData_DataPart(video);
+ if (status != PV_SUCCESS)
+ {
+ /* Report the error to the application. 06/20/2000 */
+ VideoDecoderErrorDetected(video);
+
+ /* Conceal second partition, 5/15/2000 */
+ movePointerTo(stream, startSecondPart);
+ ConcealTexture_P(video, mb_start, mb_end, slice_counter);
+ return status;
+ }
+ video->usePrevQP = 1; /* 04/27/01 */
+ }
+ else
+ { // SKIPPED
+
+ /* Motion compensation and put it to video->mblock->pred_block */
+ SkippedMBMotionComp(video);
+
+ //oscl_memset(video->predDCAC_row + video->mbnum_col, 0, sizeof(typeDCACStore)); /* SKIPPED_ACDC */
+ //oscl_memset(video->predDCAC_col, 0, sizeof(typeDCACStore));
+ /* 08/08/2005 */
+ pbyte = (uint8*)(video->predDCAC_row + video->mbnum_col);
+ ZERO_OUT_64BYTES(pbyte);
+ pbyte = (uint8*)(video->predDCAC_col);
+ ZERO_OUT_64BYTES(pbyte);
+
+ }
+ }
+
+ valid_stuffing = validStuffing(stream); /* */
+ if (!valid_stuffing)
+ {
+ VideoDecoderErrorDetected(video);
+ movePointerTo(stream, startSecondPart); /* */
+ ConcealTexture_P(video, mb_start, mb_end, slice_counter);
+
+ return PV_FAIL;
+ }
+ return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/* Function : GetMBheaderDataPart_DQUANT_DC() */
+/* Date : 04/26/2000 */
+/* Purpose : Decode DQUANT and DC in Data Partitioned Mode for both */
+/* I-VOP and P-VOP. */
+/* In/out : */
+/* Return : PV_SUCCESS if successed, PV_FAIL if failed. */
+/* Modified : 02/13/2001 new ACDC prediction structure, */
+/* cleanup */
+/* ======================================================================== */
+PV_STATUS GetMBheaderDataPart_DQUANT_DC(VideoDecData *video, int16 *QP)
+{
+ PV_STATUS status = PV_SUCCESS;
+ BitstreamDecVideo *stream = video->bitstream;
+ int mbnum = video->mbnum;
+ int intra_dc_vlc_thr = video->currVop->intraDCVlcThr;
+ uint8 *Mode = video->headerInfo.Mode;
+ int MBtype = Mode[mbnum];
+ typeDCStore *DC = video->predDC + mbnum;
+ int comp;
+ Bool switched;
+ uint DQUANT;
+ int16 QP_tmp;
+
+ const static int DQ_tab[4] = { -1, -2, 1, 2};
+
+ if (MBtype & Q_MASK) /* INTRA_Q || INTER_Q */
+ {
+ DQUANT = BitstreamReadBits16(stream, 2);
+ *QP += DQ_tab[DQUANT];
+
+ if (*QP < 1) *QP = 1;
+ else if (*QP > 31) *QP = 31;
+ }
+ if (MBtype & INTRA_MASK) /* INTRA || INTRA_Q */ /* no switch, code DC separately */
+ {
+ QP_tmp = *QP; /* running QP 04/26/01*/
+ switched = 0;
+ if (intra_dc_vlc_thr) /* 04/27/01 */
+ {
+ if (video->usePrevQP)
+ QP_tmp = video->QPMB[mbnum-1];
+ switched = (intra_dc_vlc_thr == 7 || QP_tmp >= intra_dc_vlc_thr * 2 + 11);
+ }
+ if (!switched)
+ {
+ for (comp = 0; comp < 6; comp++)
+ {
+ status = PV_DecodePredictedIntraDC(comp, stream, (*DC + comp)); /* 03/01/01 */
+ if (status != PV_SUCCESS) return PV_FAIL;
+ }
+ }
+ else
+ {
+ for (comp = 0; comp < 6; comp++)
+ {
+ (*DC)[comp] = 0; /* 04/26/01 needed for switched case*/
+ }
+ }
+ }
+ return status;
+}
+
+
+/***********************************************************CommentBegin******
+* 04/25/2000 : Initial modification to the new PV Lib format.
+* 04/17/2001 : new ACDC pred structure
+***********************************************************CommentEnd********/
+PV_STATUS GetMBheaderDataPart_P(VideoDecData *video)
+{
+ BitstreamDecVideo *stream = video->bitstream;
+ int mbnum = video->mbnum;
+ uint8 *Mode = video->headerInfo.Mode;
+ typeDCStore *DC = video->predDC + mbnum;
+ uint no_dct_flag;
+ int comp;
+ int MCBPC;
+
+ no_dct_flag = BitstreamRead1Bits_INLINE(stream);
+
+ if (no_dct_flag)
+ {
+ /* skipped macroblock */
+ Mode[mbnum] = MODE_SKIPPED;
+
+ for (comp = 0; comp < 6; comp++)
+ {
+ (*DC)[comp] = mid_gray;
+ /* ACDC REMOVE AC coefs are set in DecodeDataPart_P */
+ }
+ }
+ else
+ {
+ /* coded macroblock */
+ MCBPC = PV_VlcDecMCBPC_com_inter(stream);
+
+ if (VLC_ERROR_DETECTED(MCBPC))
+ {
+ return PV_FAIL;
+ }
+
+ Mode[mbnum] = (uint8)MBtype_mode[MCBPC & 7];
+ video->headerInfo.CBP[mbnum] = (uint8)((MCBPC >> 4) & 3);
+ }
+
+ return PV_SUCCESS;
+}
+
+
+/***********************************************************CommentBegin******
+* 04/17/01 new ACDC pred structure, reorganized code, cleanup
+***********************************************************CommentEnd********/
+PV_STATUS GetMBData_DataPart(VideoDecData *video)
+{
+ int mbnum = video->mbnum;
+ int16 *dataBlock;
+ MacroBlock *mblock = video->mblock;
+ int QP = video->QPMB[mbnum];
+ int32 offset;
+ PIXEL *c_comp;
+ int width = video->width;
+ int intra_dc_vlc_thr = video->currVop->intraDCVlcThr;
+ uint CBP = video->headerInfo.CBP[mbnum];
+ uint8 mode = video->headerInfo.Mode[mbnum];
+ int x_pos = video->mbnum_col;
+ typeDCStore *DC = video->predDC + mbnum;
+ int ncoeffs[6], *no_coeff = mblock->no_coeff;
+ int comp;
+ Bool switched;
+ int QP_tmp = QP;
+
+ int y_pos = video->mbnum_row;
+#ifdef PV_POSTPROC_ON
+ uint8 *pp_mod[6];
+ int TotalMB = video->nTotalMB;
+ int MB_in_width = video->nMBPerRow;
+#endif
+
+
+
+ /*****
+ * Decoding of the 6 blocks (depending on transparent pattern)
+ *****/
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ {
+ /** post-processing ***/
+ pp_mod[0] = video->pstprcTypCur + (y_pos << 1) * (MB_in_width << 1) + (x_pos << 1);
+ pp_mod[1] = pp_mod[0] + 1;
+ pp_mod[2] = pp_mod[0] + (MB_in_width << 1);
+ pp_mod[3] = pp_mod[2] + 1;
+ pp_mod[4] = video->pstprcTypCur + (TotalMB << 2) + mbnum;
+ pp_mod[5] = pp_mod[4] + TotalMB;
+ }
+#endif
+
+ /* oscl_memset(mblock->block, 0, sizeof(typeMBStore)); Aug 9,2005 */
+
+ if (mode & INTRA_MASK) /* MODE_INTRA || mode == MODE_INTRA_Q */
+ {
+ switched = 0;
+ if (intra_dc_vlc_thr)
+ {
+ if (video->usePrevQP)
+ QP_tmp = video->QPMB[mbnum-1]; /* running QP 04/26/01 */
+
+ switched = (intra_dc_vlc_thr == 7 || QP_tmp >= intra_dc_vlc_thr * 2 + 11);
+ }
+
+ mblock->DCScalarLum = cal_dc_scaler(QP, LUMINANCE_DC_TYPE); /* ACDC 03/01/01 */
+ mblock->DCScalarChr = cal_dc_scaler(QP, CHROMINANCE_DC_TYPE);
+
+ for (comp = 0; comp < 6; comp++)
+ {
+ dataBlock = mblock->block[comp]; /*, 10/20/2000 */
+
+ dataBlock[0] = (*DC)[comp];
+
+ ncoeffs[comp] = VlcDequantH263IntraBlock(video, comp,
+ switched, mblock->bitmapcol[comp], &mblock->bitmaprow[comp]);
+
+ if (VLC_ERROR_DETECTED(ncoeffs[comp])) /* */
+ {
+ if (switched)
+ return PV_FAIL;
+ else
+ {
+ ncoeffs[comp] = 1;
+ oscl_memset((dataBlock + 1), 0, sizeof(int16)*63);
+ }
+ }
+ no_coeff[comp] = ncoeffs[comp];
+ /* modified to new semaphore for post-proc */
+ // Future work:: can be combined in the dequant function
+ // @todo Deblocking Semaphore for INTRA block
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[comp] = (uint8) PostProcSemaphore(dataBlock);
+#endif
+ }
+ MBlockIDCT(video);
+ }
+ else /* MODE INTER*/
+ {
+
+
+
+
+ MBMotionComp(video, CBP);
+ offset = (int32)(y_pos << 4) * width + (x_pos << 4);
+ c_comp = video->currVop->yChan + offset;
+
+
+ for (comp = 0; comp < 4; comp++)
+ {
+ (*DC)[comp] = mid_gray;
+
+ if (CBP & (1 << (5 - comp)))
+ {
+ ncoeffs[comp] = VlcDequantH263InterBlock(video, comp,
+ mblock->bitmapcol[comp], &mblock->bitmaprow[comp]);
+ if (VLC_ERROR_DETECTED(ncoeffs[comp]))
+ return PV_FAIL;
+
+
+ BlockIDCT(c_comp + (comp&2)*(width << 2) + 8*(comp&1), mblock->pred_block + (comp&2)*64 + 8*(comp&1), mblock->block[comp], width, ncoeffs[comp],
+ mblock->bitmapcol[comp], mblock->bitmaprow[comp]);
+
+ }
+ else
+ {
+ ncoeffs[comp] = 0;
+ }
+
+ /* @todo Deblocking Semaphore for INTRA block, for inter just test for ringing */
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[comp] = (uint8)((ncoeffs[comp] > 3) ? 4 : 0);
+#endif
+ }
+
+ (*DC)[4] = mid_gray;
+ if (CBP & 2)
+ {
+ ncoeffs[4] = VlcDequantH263InterBlock(video, 4,
+ mblock->bitmapcol[4], &mblock->bitmaprow[4]);
+ if (VLC_ERROR_DETECTED(ncoeffs[4]))
+ return PV_FAIL;
+
+ BlockIDCT(video->currVop->uChan + (offset >> 2) + (x_pos << 2), mblock->pred_block + 256, mblock->block[4], width >> 1, ncoeffs[4],
+ mblock->bitmapcol[4], mblock->bitmaprow[4]);
+
+ }
+ else
+ {
+ ncoeffs[4] = 0;
+ }
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[4] = (uint8)((ncoeffs[4] > 3) ? 4 : 0);
+#endif
+ (*DC)[5] = mid_gray;
+ if (CBP & 1)
+ {
+ ncoeffs[5] = VlcDequantH263InterBlock(video, 5,
+ mblock->bitmapcol[5], &mblock->bitmaprow[5]);
+ if (VLC_ERROR_DETECTED(ncoeffs[5]))
+ return PV_FAIL;
+
+ BlockIDCT(video->currVop->vChan + (offset >> 2) + (x_pos << 2), mblock->pred_block + 264, mblock->block[5], width >> 1, ncoeffs[5],
+ mblock->bitmapcol[5], mblock->bitmaprow[5]);
+
+ }
+ else
+ {
+ ncoeffs[5] = 0;
+ }
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ *pp_mod[5] = (uint8)((ncoeffs[5] > 3) ? 4 : 0);
+#endif
+
+
+
+
+ /* Motion compensation and put it to video->mblock->pred_block */
+ }
+ return PV_SUCCESS;
+}
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/dcac_prediction.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/dcac_prediction.cpp
new file mode 100644
index 0000000..2a8bf1e
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/dcac_prediction.cpp
@@ -0,0 +1,368 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+#include "vlc_decode.h"
+#include "bitstream.h"
+#include "zigzag.h"
+#include "scaling.h"
+
+void doDCACPrediction(
+ VideoDecData *video,
+ int comp,
+ int16 *q_block,
+ int *direction
+)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int i;
+ int mbnum = video->mbnum;
+ int nMBPerRow = video->nMBPerRow;
+ int x_pos = video->mbnum_col;
+ int y_pos = video->mbnum_row;
+ int16 *AC_tmp;
+ int QP_tmp;
+ int16 *QP_store = video->QPMB + mbnum;
+ int QP = video->QPMB[mbnum];
+ int QP_half = QP >> 1;
+ int32 val;
+ int flag_0 = FALSE, flag_1 = FALSE;
+ uint8 *slice_nb = video->sliceNo;
+ typeDCStore *DC_store = video->predDC + mbnum;
+ typeDCACStore *DCAC_row = video->predDCAC_row + x_pos;
+ typeDCACStore *DCAC_col = video->predDCAC_col;
+
+ uint ACpred_flag = (uint) video->acPredFlag[mbnum];
+
+ int left_bnd, up_bnd;
+
+ 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; /* 0: HORIZONTAL, 1: VERTICAL */
+ int block_A, block_B, block_C;
+ int DC_pred;
+ int y_offset, x_offset, x_tab, y_tab, z_tab; /* speedup coefficients */
+ int b_xtab, b_ytab;
+
+ if (!comp && x_pos && !(video->headerInfo.Mode[mbnum-1]&INTRA_MASK)) /* not intra */
+ {
+ oscl_memset(DCAC_col, 0, sizeof(typeDCACStore));
+ }
+ if (!comp && y_pos && !(video->headerInfo.Mode[mbnum-nMBPerRow]&INTRA_MASK)) /* not intra */
+ {
+ oscl_memset(DCAC_row, 0, sizeof(typeDCACStore));
+ }
+
+ y_offset = Ypos[comp] * nMBPerRow;
+ 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];
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* Find the direction of prediction and the DC prediction */
+
+ if (x_pos == 0 && y_pos == 0)
+ { /* top left corner */
+ block_A = (comp == 1 || comp == 3) ? flag_0 = TRUE, DC_store[0][x_tab] : mid_gray;
+ block_B = (comp == 3) ? DC_store[x_offset][z_tab] : mid_gray;
+ block_C = (comp == 2 || comp == 3) ? flag_1 = TRUE, DC_store[0][y_tab] : mid_gray;
+ }
+ else if (x_pos == 0)
+ { /* left edge */
+ up_bnd = Pos0[comp] && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow];
+
+ block_A = (comp == 1 || comp == 3) ? flag_0 = TRUE, DC_store[0][x_tab] : mid_gray;
+ block_B = ((comp == 1 && up_bnd) || comp == 3) ? DC_store[y_offset+x_offset][z_tab] : mid_gray;
+ block_C = (comp == 2 || comp == 3 || up_bnd) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
+ }
+ else if (y_pos == 0)
+ { /* top row */
+ left_bnd = Pos1[comp] && slice_nb[mbnum] == slice_nb[mbnum-1];
+
+ block_A = (comp == 1 || comp == 3 || left_bnd) ? flag_0 = TRUE, DC_store[x_offset][x_tab] : mid_gray;
+ block_B = ((comp == 2 && left_bnd) || comp == 3) ? DC_store[y_offset + x_offset][z_tab] : mid_gray;
+ block_C = (comp == 2 || comp == 3) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
+ }
+ else
+ {
+ up_bnd = Pos0[comp] && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow];
+ left_bnd = Pos1[comp] && slice_nb[mbnum] == slice_nb[mbnum-1];
+
+ block_A = (comp == 1 || comp == 3 || left_bnd) ? flag_0 = TRUE, DC_store[x_offset][x_tab] : mid_gray;
+ block_B = (((comp == 0 || comp == 4 || comp == 5) && slice_nb[mbnum] == slice_nb[mbnum-1-nMBPerRow]) ||
+ (comp == 1 && up_bnd) || (comp == 2 && left_bnd) || (comp == 3)) ? DC_store[y_offset+x_offset][z_tab] : mid_gray;
+ block_C = (comp == 2 || comp == 3 || up_bnd) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
+ }
+
+
+ if ((PV_ABS((block_A - block_B))) < (PV_ABS((block_B - block_C))))
+ {
+ DC_pred = block_C;
+ *direction = 1;
+ if (ACpred_flag == 1)
+ {
+ if (flag_1)
+ {
+ AC_tmp = DCAC_row[0][b_xtab];
+ QP_tmp = QP_store[y_offset];
+ if (QP_tmp == QP)
+ {
+ for (i = 1; i < 8; i++)
+ {
+ q_block[i] = *AC_tmp++;
+ }
+ }
+ else
+ {
+ for (i = 1; i < 8; i++)
+ {
+ val = (int32)(*AC_tmp++) * QP_tmp;
+ q_block[i] = (val < 0) ? (int16)((val - QP_half) / QP) : (int16)((val + QP_half) / QP);
+ /* Vertical, top ROW of block C */
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ DC_pred = block_A;
+ *direction = 0;
+ if (ACpred_flag == 1)
+ {
+ if (flag_0)
+ {
+ AC_tmp = DCAC_col[0][b_ytab];
+ QP_tmp = QP_store[x_offset];
+ if (QP_tmp == QP)
+ {
+ for (i = 1; i < 8; i++)
+ {
+ q_block[i<<3] = *AC_tmp++;
+ }
+ }
+ else
+ {
+ for (i = 1; i < 8; i++)
+ {
+ val = (int32)(*AC_tmp++) * QP_tmp;
+ q_block[i<<3] = (val < 0) ? (int16)((val - QP_half) / QP) : (int16)((val + QP_half) / QP);
+ /* Vertical, top ROW of block C */
+ }
+ }
+ }
+ }
+ }
+
+ /* Now predict the DC coefficient */
+ QP_tmp = (comp < 4) ? video->mblock->DCScalarLum : video->mblock->DCScalarChr;
+ q_block[0] += (int16)((DC_pred + (QP_tmp >> 1)) * scale[QP_tmp] >> 18);
+// q_block[0] += (DC_pred+(QP_tmp>>1))/QP_tmp;
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+#ifdef PV_ANNEX_IJKT_SUPPORT
+void doDCACPrediction_I(
+ VideoDecData *video,
+ int comp,
+ int16 *q_block
+)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int mbnum = video->mbnum;
+ int nMBPerRow = video->nMBPerRow;
+ int x_pos = video->mbnum_col;
+ int y_pos = video->mbnum_row;
+ int16 *AC_tmp;
+ int flag_0 = FALSE, flag_1 = FALSE;
+ uint8 *slice_nb = video->sliceNo;
+ typeDCStore *DC_store = video->predDC + mbnum;
+ typeDCACStore *DCAC_row = video->predDCAC_row + x_pos;
+ typeDCACStore *DCAC_col = video->predDCAC_col;
+ int left_bnd, up_bnd;
+ uint8 *mode = video->headerInfo.Mode;
+ uint ACpred_flag = (uint) video->acPredFlag[mbnum];
+
+
+
+ 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};
+
+ /* 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; /* 0: HORIZONTAL, 1: VERTICAL */
+ int block_A, block_C;
+ int y_offset, x_offset, x_tab, y_tab; /* speedup coefficients */
+ int b_xtab, b_ytab;
+ y_offset = Ypos[comp] * nMBPerRow;
+ x_offset = Xpos[comp];
+ x_tab = Xtab[comp];
+ y_tab = Ytab[comp];
+
+ b_xtab = B_Xtab[comp];
+ b_ytab = B_Ytab[comp];
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* Find the direction of prediction and the DC prediction */
+
+ if (x_pos == 0 && y_pos == 0)
+ { /* top left corner */
+ block_A = (comp == 1 || comp == 3) ? flag_0 = TRUE, DC_store[0][x_tab] : mid_gray;
+ block_C = (comp == 2 || comp == 3) ? flag_1 = TRUE, DC_store[0][y_tab] : mid_gray;
+ }
+ else if (x_pos == 0)
+ { /* left edge */
+ up_bnd = (Pos0[comp] && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])
+ && (mode[mbnum-nMBPerRow] == MODE_INTRA || mode[mbnum-nMBPerRow] == MODE_INTRA_Q);;
+
+ block_A = (comp == 1 || comp == 3) ? flag_0 = TRUE, DC_store[0][x_tab] : mid_gray;
+ block_C = (comp == 2 || comp == 3 || up_bnd) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
+ }
+ else if (y_pos == 0)
+ { /* top row */
+ left_bnd = (Pos1[comp] && slice_nb[mbnum] == slice_nb[mbnum-1])
+ && (mode[mbnum-1] == MODE_INTRA || mode[mbnum-1] == MODE_INTRA_Q);
+
+ block_A = (comp == 1 || comp == 3 || left_bnd) ? flag_0 = TRUE, DC_store[x_offset][x_tab] : mid_gray;
+ block_C = (comp == 2 || comp == 3) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
+ }
+ else
+ {
+ up_bnd = (Pos0[comp] && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])
+ && (mode[mbnum-nMBPerRow] == MODE_INTRA || mode[mbnum-nMBPerRow] == MODE_INTRA_Q);
+ left_bnd = (Pos1[comp] && slice_nb[mbnum] == slice_nb[mbnum-1])
+ && (mode[mbnum-1] == MODE_INTRA || mode[mbnum-1] == MODE_INTRA_Q);
+
+ block_A = (comp == 1 || comp == 3 || left_bnd) ? flag_0 = TRUE, DC_store[x_offset][x_tab] : mid_gray;
+ block_C = (comp == 2 || comp == 3 || up_bnd) ? flag_1 = TRUE, DC_store[y_offset][y_tab] : mid_gray;
+ }
+
+ if (ACpred_flag == 0)
+ {
+ if (flag_0 == TRUE)
+ {
+ if (flag_1 == TRUE)
+ {
+ q_block[0] = (int16)((block_A + block_C) >> 1);
+ }
+ else
+ {
+ q_block[0] = (int16)block_A;
+ }
+ }
+ else
+ {
+ if (flag_1 == TRUE)
+ {
+ q_block[0] = (int16)block_C;
+ }
+ else
+ {
+ q_block[0] = mid_gray;
+ }
+ }
+
+ }
+ else
+ {
+ if (video->mblock->direction == 1)
+ {
+ if (flag_1 == TRUE)
+ {
+ q_block[0] = (int16)block_C;
+
+ AC_tmp = DCAC_row[0][b_xtab];
+ q_block[1] = AC_tmp[0];
+ q_block[2] = AC_tmp[1];
+ q_block[3] = AC_tmp[2];
+ q_block[4] = AC_tmp[3];
+ q_block[5] = AC_tmp[4];
+ q_block[6] = AC_tmp[5];
+ q_block[7] = AC_tmp[6];
+ }
+ else
+ {
+ q_block[0] = mid_gray;
+ }
+ }
+ else
+ {
+ if (flag_0 == TRUE)
+ {
+ q_block[0] = (int16)block_A;
+
+ AC_tmp = DCAC_col[0][b_ytab];
+ q_block[8] = AC_tmp[0];
+ q_block[16] = AC_tmp[1];
+ q_block[24] = AC_tmp[2];
+ q_block[32] = AC_tmp[3];
+ q_block[40] = AC_tmp[4];
+ q_block[48] = AC_tmp[5];
+ q_block[56] = AC_tmp[6];
+ }
+ else
+ {
+ q_block[0] = mid_gray;
+ }
+ }
+ }
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+#endif
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp
new file mode 100644
index 0000000..c19c23a
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp
@@ -0,0 +1,75 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_lib.h"
+#include "vlc_decode.h"
+#include "bitstream.h"
+#include "zigzag.h"
+
+PV_STATUS PV_DecodePredictedIntraDC(
+ int compnum,
+ BitstreamDecVideo *stream,
+ int16 *INTRADC_delta)
+{
+
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ PV_STATUS status = PV_SUCCESS;
+ uint DC_size;
+ uint code;
+ int first_bit;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* read DC size 2 - 8 bits */
+ status = PV_VlcDecIntraDCPredSize(stream, compnum, &DC_size);
+
+ if (status == PV_SUCCESS)
+ {
+ if (DC_size == 0)
+ {
+ *INTRADC_delta = 0;
+ }
+ else
+ {
+ /* read delta DC 0 - 8 bits */
+ code = (int) BitstreamReadBits16_INLINE(stream, DC_size);
+
+ first_bit = code >> (DC_size - 1);
+
+ if (first_bit == 0)
+ {
+ /* negative delta INTRA DC */
+ *INTRADC_delta = code ^((1 << DC_size) - 1);
+ *INTRADC_delta = -(*INTRADC_delta);
+ }
+ else
+ { /* positive delta INTRA DC */
+ *INTRADC_delta = code;
+ }
+ if (DC_size > 8) BitstreamRead1Bits_INLINE(stream);
+ }
+ }
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return status;
+}
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/deringing_chroma.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/deringing_chroma.cpp
new file mode 100644
index 0000000..ce779b0
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/deringing_chroma.cpp
@@ -0,0 +1,215 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_lib.h"
+#include "post_proc.h"
+
+#ifdef PV_POSTPROC_ON
+
+void Deringing_Chroma(
+ uint8 *Rec_C,
+ int width,
+ int height,
+ int16 *QP_store,
+ int,
+ uint8 *pp_mod
+)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int thres;
+ int v_blk, h_blk;
+ int max_diff;
+ int v_pel, h_pel;
+ int max_blk, min_blk;
+ int v0, h0;
+ uint8 *ptr;
+ int sum, sum1, incr;
+ int32 addr_v;
+ int sign_v[10], sum_v[10];
+ int *ptr2, *ptr3;
+ uint8 pelu, pelc, pell;
+ incr = width - BLKSIZE;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* chrominance */
+ /* Do the first line (7 pixels at a time => Don't use MMX)*/
+ for (h_blk = 0; h_blk < width; h_blk += BLKSIZE)
+ {
+ max_diff = (QP_store[h_blk>>3] >> 2) + 4;
+ ptr = &Rec_C[h_blk];
+ max_blk = min_blk = *ptr;
+ FindMaxMin(ptr, &min_blk, &max_blk, width);
+ h0 = ((h_blk - 1) >= 1) ? (h_blk - 1) : 1;
+
+ if (max_blk - min_blk >= 4)
+ {
+ thres = (max_blk + min_blk + 1) >> 1;
+
+
+ for (v_pel = 1; v_pel < BLKSIZE - 1; v_pel++)
+ {
+ addr_v = (int32)v_pel * width;
+ ptr = &Rec_C[addr_v + h0 - 1];
+ ptr2 = &sum_v[0];
+ ptr3 = &sign_v[0];
+
+ pelu = *(ptr - width);
+ pelc = *ptr;
+ pell = *(ptr + width);
+ ptr++;
+ *ptr2++ = pelu + (pelc << 1) + pell;
+ *ptr3++ = INDEX(pelu, thres) + INDEX(pelc, thres) + INDEX(pell, thres);
+
+ pelu = *(ptr - width);
+ pelc = *ptr;
+ pell = *(ptr + width);
+ ptr++;
+ *ptr2++ = pelu + (pelc << 1) + pell;
+ *ptr3++ = INDEX(pelu, thres) + INDEX(pelc, thres) + INDEX(pell, thres);
+
+ for (h_pel = h0; h_pel < h_blk + BLKSIZE - 1; h_pel++)
+ {
+ pelu = *(ptr - width);
+ pelc = *ptr;
+ pell = *(ptr + width);
+
+ *ptr2 = pelu + (pelc << 1) + pell;
+ *ptr3 = INDEX(pelu, thres) + INDEX(pelc, thres) + INDEX(pell, thres);
+
+ sum1 = *(ptr3 - 2) + *(ptr3 - 1) + *ptr3;
+ if (sum1 == 0 || sum1 == 9)
+ {
+ sum = (*(ptr2 - 2) + (*(ptr2 - 1) << 1) + *ptr2 + 8) >> 4;
+
+ ptr--;
+ if (PV_ABS(*ptr - sum) > max_diff)
+ {
+ if (sum > *ptr)
+ sum = *ptr + max_diff;
+ else
+ sum = *ptr - max_diff;
+ }
+ *ptr++ = (uint8) sum;
+ }
+ ptr++;
+ ptr2++;
+ ptr3++;
+ }
+ }
+ }
+ }
+
+ for (v_blk = BLKSIZE; v_blk < height; v_blk += BLKSIZE)
+ {
+ v0 = v_blk - 1;
+ /* Do the first block (pixels=7 => No MMX) */
+ max_diff = (QP_store[((((int32)v_blk*width)>>3))>>3] >> 2) + 4;
+ ptr = &Rec_C[(int32)v_blk * width];
+ max_blk = min_blk = *ptr;
+ FindMaxMin(ptr, &min_blk, &max_blk, incr);
+
+ if (max_blk - min_blk >= 4)
+ {
+ thres = (max_blk + min_blk + 1) >> 1;
+
+ for (v_pel = v0; v_pel < v_blk + BLKSIZE - 1; v_pel++)
+ {
+ addr_v = v_pel * width;
+ ptr = &Rec_C[addr_v];
+ ptr2 = &sum_v[0];
+ ptr3 = &sign_v[0];
+
+ pelu = *(ptr - width);
+ pelc = *ptr;
+ pell = *(ptr + width);
+ ptr++;
+ *ptr2++ = pelu + (pelc << 1) + pell;
+ *ptr3++ = INDEX(pelu, thres) + INDEX(pelc, thres) + INDEX(pell, thres);
+
+ pelu = *(ptr - width);
+ pelc = *ptr;
+ pell = *(ptr + width);
+ ptr++;
+ *ptr2++ = pelu + (pelc << 1) + pell;
+ *ptr3++ = INDEX(pelu, thres) + INDEX(pelc, thres) + INDEX(pell, thres);
+
+ for (h_pel = 1; h_pel < BLKSIZE - 1; h_pel++)
+ {
+ pelu = *(ptr - width);
+ pelc = *ptr;
+ pell = *(ptr + width);
+
+ *ptr2 = pelu + (pelc << 1) + pell;
+ *ptr3 = INDEX(pelu, thres) + INDEX(pelc, thres) + INDEX(pell, thres);
+
+ sum1 = *(ptr3 - 2) + *(ptr3 - 1) + *ptr3;
+ if (sum1 == 0 || sum1 == 9)
+ {
+ sum = (*(ptr2 - 2) + (*(ptr2 - 1) << 1) + *ptr2 + 8) >> 4;
+
+ ptr--;
+ if (PV_ABS(*ptr - sum) > max_diff)
+ {
+ if (sum > *ptr)
+ sum = *ptr + max_diff;
+ else
+ sum = *ptr - max_diff;
+ }
+ *ptr++ = (uint8) sum;
+ }
+ ptr++;
+ ptr2++;
+ ptr3++;
+ }
+ }
+ }
+
+
+ /* Do the rest in MMX */
+ for (h_blk = BLKSIZE; h_blk < width; h_blk += BLKSIZE)
+ {
+ if ((pp_mod[(v_blk/8)*(width/8)+h_blk/8]&0x4) != 0)
+ {
+ max_diff = (QP_store[((((int32)v_blk*width)>>3)+h_blk)>>3] >> 2) + 4;
+ ptr = &Rec_C[(int32)v_blk * width + h_blk];
+ max_blk = min_blk = *ptr;
+ FindMaxMin(ptr, &min_blk, &max_blk, incr);
+ h0 = h_blk - 1;
+
+ if (max_blk - min_blk >= 4)
+ {
+ thres = (max_blk + min_blk + 1) >> 1;
+#ifdef NoMMX
+ AdaptiveSmooth_NoMMX(Rec_C, v0, h0, v_blk, h_blk, thres, width, max_diff);
+#else
+ DeringAdaptiveSmoothMMX(&Rec_C[(int32)v0*width+h0], width, thres, max_diff);
+#endif
+ }
+ }
+ }
+ } /* macroblock level */
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+#endif
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/deringing_luma.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/deringing_luma.cpp
new file mode 100644
index 0000000..b5574b4
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/deringing_luma.cpp
@@ -0,0 +1,231 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_lib.h"
+#include "post_proc.h"
+
+#ifdef PV_POSTPROC_ON
+
+void Deringing_Luma(
+ uint8 *Rec_Y,
+ int width,
+ int height,
+ int16 *QP_store,
+ int,
+ uint8 *pp_mod)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int thres[4], range[4], max_range_blk, max_thres_blk;
+ int MB_V, MB_H, BLK_V, BLK_H;
+ int v_blk, h_blk;
+ int max_diff;
+ int max_blk, min_blk;
+ int v0, h0;
+ uint8 *ptr;
+ int thr, blks, incr;
+ int mb_indx, blk_indx;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ incr = width - BLKSIZE;
+
+ /* Dering the first line of macro blocks */
+ for (MB_H = 0; MB_H < width; MB_H += MBSIZE)
+ {
+ max_diff = (QP_store[(MB_H)>>4] >> 2) + 4;
+
+ /* threshold determination */
+ max_range_blk = max_thres_blk = 0;
+ blks = 0;
+
+ for (BLK_V = 0; BLK_V < MBSIZE; BLK_V += BLKSIZE)
+ {
+ for (BLK_H = 0; BLK_H < MBSIZE; BLK_H += BLKSIZE)
+ {
+ ptr = &Rec_Y[(int32)(BLK_V) * width + MB_H + BLK_H];
+ FindMaxMin(ptr, &min_blk, &max_blk, incr);
+
+ thres[blks] = (max_blk + min_blk + 1) >> 1;
+ range[blks] = max_blk - min_blk;
+
+ if (range[blks] >= max_range_blk)
+ {
+ max_range_blk = range[blks];
+ max_thres_blk = thres[blks];
+ }
+ blks++;
+ }
+ }
+
+ blks = 0;
+ for (v_blk = 0; v_blk < MBSIZE; v_blk += BLKSIZE)
+ {
+ v0 = ((v_blk - 1) >= 1) ? (v_blk - 1) : 1;
+ for (h_blk = MB_H; h_blk < MB_H + MBSIZE; h_blk += BLKSIZE)
+ {
+ h0 = ((h_blk - 1) >= 1) ? (h_blk - 1) : 1;
+
+ /* threshold rearrangement for flat region adjacent to non-flat region */
+ if (range[blks]<32 && max_range_blk >= 64)
+ thres[blks] = max_thres_blk;
+
+ /* threshold rearrangement for deblocking
+ (blockiness annoying at DC dominant region) */
+ if (max_range_blk >= 16)
+ {
+ /* adaptive smoothing */
+ thr = thres[blks];
+
+ AdaptiveSmooth_NoMMX(Rec_Y, v0, h0, v_blk, h_blk,
+ thr, width, max_diff);
+ }
+ blks++;
+ } /* block level (Luminance) */
+ }
+ } /* macroblock level */
+
+
+ /* Do the rest of the macro-block-lines */
+ for (MB_V = MBSIZE; MB_V < height; MB_V += MBSIZE)
+ {
+ /* First macro-block */
+ max_diff = (QP_store[((((int32)MB_V*width)>>4))>>4] >> 2) + 4;
+ /* threshold determination */
+ max_range_blk = max_thres_blk = 0;
+ blks = 0;
+ for (BLK_V = 0; BLK_V < MBSIZE; BLK_V += BLKSIZE)
+ {
+ for (BLK_H = 0; BLK_H < MBSIZE; BLK_H += BLKSIZE)
+ {
+ ptr = &Rec_Y[(int32)(MB_V + BLK_V) * width + BLK_H];
+ FindMaxMin(ptr, &min_blk, &max_blk, incr);
+ thres[blks] = (max_blk + min_blk + 1) >> 1;
+ range[blks] = max_blk - min_blk;
+
+ if (range[blks] >= max_range_blk)
+ {
+ max_range_blk = range[blks];
+ max_thres_blk = thres[blks];
+ }
+ blks++;
+ }
+ }
+
+ blks = 0;
+ for (v_blk = MB_V; v_blk < MB_V + MBSIZE; v_blk += BLKSIZE)
+ {
+ v0 = v_blk - 1;
+ for (h_blk = 0; h_blk < MBSIZE; h_blk += BLKSIZE)
+ {
+ h0 = ((h_blk - 1) >= 1) ? (h_blk - 1) : 1;
+
+ /* threshold rearrangement for flat region adjacent to non-flat region */
+ if (range[blks]<32 && max_range_blk >= 64)
+ thres[blks] = max_thres_blk;
+
+ /* threshold rearrangement for deblocking
+ (blockiness annoying at DC dominant region) */
+ if (max_range_blk >= 16)
+ {
+ /* adaptive smoothing */
+ thr = thres[blks];
+
+ AdaptiveSmooth_NoMMX(Rec_Y, v0, h0, v_blk, h_blk,
+ thr, width, max_diff);
+ }
+ blks++;
+ }
+ } /* block level (Luminance) */
+
+ /* Rest of the macro-blocks */
+ for (MB_H = MBSIZE; MB_H < width; MB_H += MBSIZE)
+ {
+ max_diff = (QP_store[((((int32)MB_V*width)>>4)+MB_H)>>4] >> 2) + 4;
+
+ /* threshold determination */
+ max_range_blk = max_thres_blk = 0;
+ blks = 0;
+
+ mb_indx = (MB_V / 8) * (width / 8) + MB_H / 8;
+ for (BLK_V = 0; BLK_V < MBSIZE; BLK_V += BLKSIZE)
+ {
+ for (BLK_H = 0; BLK_H < MBSIZE; BLK_H += BLKSIZE)
+ {
+ blk_indx = mb_indx + (BLK_V / 8) * width / 8 + BLK_H / 8;
+ /* Update based on pp_mod only */
+ if ((pp_mod[blk_indx]&0x4) != 0)
+ {
+ ptr = &Rec_Y[(int32)(MB_V + BLK_V) * width + MB_H + BLK_H];
+ FindMaxMin(ptr, &min_blk, &max_blk, incr);
+ thres[blks] = (max_blk + min_blk + 1) >> 1;
+ range[blks] = max_blk - min_blk;
+
+ if (range[blks] >= max_range_blk)
+ {
+ max_range_blk = range[blks];
+ max_thres_blk = thres[blks];
+ }
+ }
+ blks++;
+ }
+ }
+
+ blks = 0;
+ for (v_blk = MB_V; v_blk < MB_V + MBSIZE; v_blk += BLKSIZE)
+ {
+ v0 = v_blk - 1;
+ mb_indx = (v_blk / 8) * (width / 8);
+ for (h_blk = MB_H; h_blk < MB_H + MBSIZE; h_blk += BLKSIZE)
+ {
+ h0 = h_blk - 1;
+ blk_indx = mb_indx + h_blk / 8;
+ if ((pp_mod[blk_indx]&0x4) != 0)
+ {
+ /* threshold rearrangement for flat region adjacent to non-flat region */
+ if (range[blks]<32 && max_range_blk >= 64)
+ thres[blks] = max_thres_blk;
+
+ /* threshold rearrangement for deblocking
+ (blockiness annoying at DC dominant region) */
+ if (max_range_blk >= 16)
+ {
+ /* adaptive smoothing */
+ thr = thres[blks];
+#ifdef NoMMX
+ AdaptiveSmooth_NoMMX(Rec_Y, v0, h0, v_blk, h_blk,
+ thr, width, max_diff);
+#else
+ DeringAdaptiveSmoothMMX(&Rec_Y[v0*width+h0],
+ width, thr, max_diff);
+#endif
+ }
+ }
+ blks++;
+ }
+ } /* block level (Luminance) */
+ } /* macroblock level */
+ } /* macroblock level */
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+#endif
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/find_min_max.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/find_min_max.cpp
new file mode 100644
index 0000000..a357ea6
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/find_min_max.cpp
@@ -0,0 +1,176 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ input_ptr = pointer to the buffer containing values of type UChar
+ in a 2D block of data.
+ min_ptr = pointer to the minimum value of type Int to be found in a
+ square block of size BLKSIZE contained in 2D block of data.
+ max_ptr = pointer to the maximum value of type Int to be found in a
+ square block of size BLKSIZE contained in 2D block of data.
+ incr = value of type Int representing the width of 2D block of data.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ min_ptr points to the found minimum value in the square block of
+ size BLKSIZE contained in 2D block of data.
+
+ max_ptr points to the found maximum value in the square block of
+ size BLKSIZE contained in 2D block of data.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function finds the maximum and the minimum values in a square block of
+ data of size BLKSIZE * BLKSIZE. The data is contained in the buffer which
+ represents a 2D block of data that is larger than BLKSIZE * BLKSIZE.
+ This is illustrated below.
+
+ mem loc x + 00h -> o o o o o o o o o o o o o o o o
+ mem loc x + 10h -> o o o o o X X X X X X X X o o o
+ mem loc x + 20h -> o o o o o X X X X X X X X o o o
+ mem loc x + 30h -> o o o o o X X X X X X X X o o o
+ mem loc x + 40h -> o o o o o X X X X X X X X o o o
+ mem loc x + 50h -> o o o o o X X X X X X X X o o o
+ mem loc x + 60h -> o o o o o X X X X X X X X o o o
+ mem loc x + 70h -> o o o o o X X X X X X X X o o o
+ mem loc x + 80h -> o o o o o X X X X X X X X o o o
+ mem loc x + 90h -> o o o o o o o o o o o o o o o o
+ mem loc x + A0h -> o o o o o o o o o o o o o o o o
+ mem loc x + B0h -> o o o o o o o o o o o o o o o o
+
+For illustration purposes, the diagram assumes that BLKSIZE is equal to 8
+but this is not a requirement. In this diagram, the buffer starts at
+location x but the input pointer, input_ptr, passed into this function
+would be the first row of data to be searched which is at x + 15h. The
+value of incr passed onto this function represents the amount the input_ptr
+needs to be incremented to point to the next row of data.
+
+This function compares each value in a row to the current maximum and
+minimum. After each row, input_ptr is incremented to point to the next row.
+This is repeated until all rows have been processed. When the search is
+complete the location pointed to by min_ptr contains the minimum value
+found and the location pointed to by max_ptr contains the maximum value found.
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+#include "post_proc.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+#ifdef PV_POSTPROC_ON
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void FindMaxMin(
+ uint8 *input_ptr,
+ int *min_ptr,
+ int *max_ptr,
+ int incr)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ register uint i, j;
+ register int min, max;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ max = min = *input_ptr;
+ /* incr = incr - BLKSIZE; */ /* 09/06/2001, already passed in as width - BLKSIZE */
+
+ for (i = BLKSIZE; i > 0; i--)
+ {
+ for (j = BLKSIZE; j > 0; j--)
+ {
+ if (*input_ptr > max)
+ {
+ max = *input_ptr;
+ }
+ else if (*input_ptr < min)
+ {
+ min = *input_ptr;
+ }
+ input_ptr += 1;
+ }
+
+ /* set pointer to the beginning of the next row*/
+ input_ptr += incr;
+ }
+
+ *max_ptr = max;
+ *min_ptr = min;
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+#endif
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp
new file mode 100644
index 0000000..e23f23d
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp
@@ -0,0 +1,1190 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ xpos = x half-pixel of (x,y) coordinates within a VOP; motion
+ compensated coordinates; native type
+ ypos = y half-pixel of (x,y) coordinates within a VOP; motion
+ compensated coordinates; native type
+ comp = pointer to 8-bit compensated prediction values within a VOP;
+ computed by this module (i/o); full-pel resolution
+ c_prev = pointer to previous 8-bit prediction values within a VOP;
+ values range from (0-255); full-pel resolution
+ sh_d = pointer to residual values used to compensate the predicted
+ value; values range from (-512 to 511); full-pel resolution
+ width = width of the VOP in pixels (x axis); full-pel resolution
+ rnd1 = rounding value for case when one dimension uses half-pel
+ resolution
+ rnd2 = rounding value for case when two dimensions uses half-pel
+ resolution
+ CBP = flag indicating whether residual is all zeros
+ (0 -> all zeros, 1 -> not all zeros)
+ outside_flag = flag indicating whether motion vector is outside the
+ VOP (0 -> inside, 1 -> outside)
+
+ Outputs:
+ returns 1
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Pointers and Buffers Modified:
+ comp = buffer contains newly computed compensated prediction values
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Compute pixel values for a block in the current VOP. The prediction
+ values are generated by averaging pixel values in the previous VOP; the
+ block position in the previous frame is computed from the current block's
+ motion vector. The computed pixel values are then computed by adding the
+ prediction values to the block residual values.
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+#include "motion_comp.h"
+
+#define OSCL_DISABLE_WARNING_CONV_POSSIBLE_LOSS_OF_DATA
+
+int GetPredAdvancedBy0x0(
+ uint8 *prev, /* i */
+ uint8 *pred_block, /* i */
+ int width, /* i */
+ int pred_width_rnd /* i */
+)
+{
+ uint i; /* loop variable */
+ int offset, offset2;
+ uint32 pred_word, word1, word2;
+ int tmp;
+
+ /* initialize offset to adjust pixel counter */
+ /* the next row; full-pel resolution */
+ offset = width - B_SIZE; /* offset for prev */
+ offset2 = (pred_width_rnd >> 1) - 4; /* offset for pred_block */
+
+ tmp = (uint32)prev & 0x3;
+ pred_block -= offset2; /* preset */
+
+ if (tmp == 0) /* word-aligned */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ *((uint32*)(pred_block += offset2)) = *((uint32*)prev);
+ *((uint32*)(pred_block += 4)) = *((uint32*)(prev + 4));
+ prev += width;
+ }
+ return 1;
+ }
+ else if (tmp == 1) /* first position */
+ {
+ prev--; /* word-aligned */
+
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((uint32*)prev); /* read 4 bytes, b4 b3 b2 b1 */
+ word2 = *((uint32*)(prev += 4)); /* read 4 bytes, b8 b7 b6 b5 */
+ word1 >>= 8; /* 0 b4 b3 b2 */
+ pred_word = word1 | (word2 << 24); /* b5 b4 b3 b2 */
+ *((uint32*)(pred_block += offset2)) = pred_word;
+
+ word1 = *((uint32*)(prev += 4)); /* b12 b11 b10 b9 */
+ word2 >>= 8; /* 0 b8 b7 b6 */
+ pred_word = word2 | (word1 << 24); /* b9 b8 b7 b6 */
+ *((uint32*)(pred_block += 4)) = pred_word;
+
+ prev += offset;
+ }
+
+ return 1;
+ }
+ else if (tmp == 2) /* second position */
+ {
+ prev -= 2; /* word1-aligned */
+
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((uint32*)prev); /* read 4 bytes, b4 b3 b2 b1 */
+ word2 = *((uint32*)(prev += 4)); /* read 4 bytes, b8 b7 b6 b5 */
+ word1 >>= 16; /* 0 0 b4 b3 */
+ pred_word = word1 | (word2 << 16); /* b6 b5 b4 b3 */
+ *((uint32*)(pred_block += offset2)) = pred_word;
+
+ word1 = *((uint32*)(prev += 4)); /* b12 b11 b10 b9 */
+ word2 >>= 16; /* 0 0 b8 b7 */
+ pred_word = word2 | (word1 << 16); /* b10 b9 b8 b7 */
+ *((uint32*)(pred_block += 4)) = pred_word;
+
+
+ prev += offset;
+ }
+
+ return 1;
+ }
+ else /* third position */
+ {
+ prev -= 3; /* word1-aligned */
+
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((uint32*)prev); /* read 4 bytes, b4 b3 b2 b1 */
+ word2 = *((uint32*)(prev += 4)); /* read 4 bytes, b8 b7 b6 b5 */
+ word1 >>= 24; /* 0 0 0 b4 */
+ pred_word = word1 | (word2 << 8); /* b7 b6 b5 b4 */
+ *((uint32*)(pred_block += offset2)) = pred_word;
+
+ word1 = *((uint32*)(prev += 4)); /* b12 b11 b10 b9 */
+ word2 >>= 24; /* 0 0 0 b8 */
+ pred_word = word2 | (word1 << 8); /* b11 b10 b9 b8 */
+ *((uint32*)(pred_block += 4)) = pred_word;
+
+ prev += offset;
+ }
+
+ return 1;
+ }
+}
+
+/**************************************************************************/
+int GetPredAdvancedBy0x1(
+ uint8 *prev, /* i */
+ uint8 *pred_block, /* i */
+ int width, /* i */
+ int pred_width_rnd /* i */
+)
+{
+ uint i; /* loop variable */
+ int offset, offset2;
+ uint32 word1, word2, word3, word12;
+ int tmp;
+ int rnd1;
+ uint32 mask;
+
+ /* initialize offset to adjust pixel counter */
+ /* the next row; full-pel resolution */
+ offset = width - B_SIZE; /* offset for prev */
+ offset2 = (pred_width_rnd >> 1) - 4; /* offset of pred_block */
+
+ rnd1 = pred_width_rnd & 1;
+
+ /* Branch based on pixel location (half-pel or full-pel) for x and y */
+ pred_block -= offset2; /* preset */
+
+ tmp = (uint32)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 = *((uint32*)prev); /* b4 b3 b2 b1 */
+ word2 = *((uint32*)(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;
+ *((uint32*)(pred_block += offset2)) = word1; /* write 4 pixels */
+
+ word1 = *((uint32*)(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;
+ *((uint32*)(pred_block += 4)) = word2; /* write 4 pixels */
+
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 == 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((uint32*)prev); /* b4 b3 b2 b1 */
+
+ word2 = *((uint32*)(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;
+ *((uint32*)(pred_block += offset2)) = word1; /* write 4 pixels */
+
+ word1 = *((uint32*)(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;
+ *((uint32*)(pred_block += 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 = *((uint32*)prev); /* b3 b2 b1 b0 */
+ word2 = *((uint32*)(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;
+ *((uint32*)(pred_block += offset2)) = word1; /* write 4 pixels */
+
+ word1 = *((uint32*)(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;
+ *((uint32*)(pred_block += 4)) = word2; /* write 4 pixels */
+
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 = 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((uint32*)prev); /* b3 b2 b1 b0 */
+
+ word2 = *((uint32*)(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;
+ *((uint32*)(pred_block += offset2)) = word1; /* write 4 pixels */
+
+ word1 = *((uint32*)(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;
+ *((uint32*)(pred_block += 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 = *((uint32*)prev); /* b2 b1 b0 bN1 */
+ word2 = *((uint32*)(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;
+ *((uint32*)(pred_block += offset2)) = word1; /* write 4 pixels */
+
+ word1 = *((uint32*)(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;
+ *((uint32*)(pred_block += 4)) = word2; /* write 4 pixels */
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 == 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((uint32*)prev); /* b2 b1 b0 bN1 */
+ word2 = *((uint32*)(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;
+ *((uint32*)(pred_block += offset2)) = word1; /* write 4 pixels */
+
+ word1 = *((uint32*)(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;
+ *((uint32*)(pred_block += 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 = *((uint32*)prev); /* b1 b0 bN1 bN2 */
+ word2 = *((uint32*)(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;
+ *((uint32*)(pred_block += offset2)) = word1; /* write 4 pixels */
+
+ word1 = *((uint32*)(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;
+ *((uint32*)(pred_block += 4)) = word2; /* write 4 pixels */
+ prev += offset;
+ }
+ return 1;
+ }
+ else
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((uint32*)prev); /* b1 b0 bN1 bN2 */
+ word2 = *((uint32*)(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;
+ *((uint32*)(pred_block += offset2)) = word1; /* write 4 pixels */
+
+ word1 = *((uint32*)(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;
+ *((uint32*)(pred_block += 4)) = word2; /* write 4 pixels */
+ prev += offset;
+ }
+ return 1;
+ }
+ }
+}
+
+/**************************************************************************/
+int GetPredAdvancedBy1x0(
+ uint8 *prev, /* i */
+ uint8 *pred_block, /* i */
+ int width, /* i */
+ int pred_width_rnd /* i */
+)
+{
+ uint i; /* loop variable */
+ int offset, offset2;
+ uint32 word1, word2, word3, word12, word22;
+ int tmp;
+ int rnd1;
+ uint32 mask;
+
+ /* initialize offset to adjust pixel counter */
+ /* the next row; full-pel resolution */
+ offset = width - B_SIZE; /* offset for prev */
+ offset2 = (pred_width_rnd >> 1) - 4; /* offset for pred_block */
+
+ rnd1 = pred_width_rnd & 1;
+
+ /* Branch based on pixel location (half-pel or full-pel) for x and y */
+ pred_block -= offset2; /* preset */
+
+ tmp = (uint32)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 = *((uint32*)(prev += 4));
+ word2 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += offset2)) = word1;
+ word1 = *((uint32*)(prev += 4));
+ word2 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += 4)) = word1;
+
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 = 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((uint32*)(prev += 4));
+ word2 = *((uint32*)(prev + width));
+ word3 = word1 & word2; /* rnd1 = 0; */
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word2 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word2 >> 1);
+ word1 += word3;
+ *((uint32*)(pred_block += offset2)) = word1;
+ word1 = *((uint32*)(prev += 4));
+ word2 = *((uint32*)(prev + width));
+ word3 = word1 & word2; /* rnd1 = 0; */
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word2 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word2 >> 1);
+ word1 += word3;
+ *((uint32*)(pred_block += 4)) = word1;
+
+ prev += offset;
+ }
+ return 1;
+ }
+ }
+ else if (tmp == 1)
+ {
+ prev--; /* word-aligned */
+ if (rnd1 == 1)
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word12 = *((uint32*)prev); /* read b4 b3 b2 b1 */
+ word22 = *((uint32*)(prev + width));
+
+ word1 = *((uint32*)(prev += 4)); /* read b8 b7 b6 b5 */
+ word2 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += offset2)) = word12;
+
+ word12 = *((uint32*)(prev += 4)); /* read b12 b11 b10 b9 */
+ word22 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += 4)) = word1;
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 = 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word12 = *((uint32*)prev); /* read b4 b3 b2 b1 */
+ word22 = *((uint32*)(prev + width));
+
+ word1 = *((uint32*)(prev += 4)); /* read b8 b7 b6 b5 */
+ word2 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += offset2)) = word12;
+
+ word12 = *((uint32*)(prev += 4)); /* read b12 b11 b10 b9 */
+ word22 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += 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 = *((uint32*)prev); /* read b4 b3 b2 b1 */
+ word22 = *((uint32*)(prev + width));
+
+ word1 = *((uint32*)(prev += 4)); /* read b8 b7 b6 b5 */
+ word2 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += offset2)) = word12;
+
+ word12 = *((uint32*)(prev += 4)); /* read b12 b11 b10 b9 */
+ word22 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += 4)) = word1;
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 = 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word12 = *((uint32*)prev); /* read b4 b3 b2 b1 */
+ word22 = *((uint32*)(prev + width));
+
+ word1 = *((uint32*)(prev += 4)); /* read b8 b7 b6 b5 */
+ word2 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += offset2)) = word12;
+
+ word12 = *((uint32*)(prev += 4)); /* read b12 b11 b10 b9 */
+ word22 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += 4)) = word1;
+ prev += offset;
+ }
+
+ return 1;
+ }
+ }
+ else /* tmp == 3 */
+ {
+ prev -= 3; /* word-aligned */
+ if (rnd1 == 1)
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word12 = *((uint32*)prev); /* read b4 b3 b2 b1 */
+ word22 = *((uint32*)(prev + width));
+
+ word1 = *((uint32*)(prev += 4)); /* read b8 b7 b6 b5 */
+ word2 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += offset2)) = word12;
+
+ word12 = *((uint32*)(prev += 4)); /* read b12 b11 b10 b9 */
+ word22 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += 4)) = word1;
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 = 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word12 = *((uint32*)prev); /* read b4 b3 b2 b1 */
+ word22 = *((uint32*)(prev + width));
+
+ word1 = *((uint32*)(prev += 4)); /* read b8 b7 b6 b5 */
+ word2 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += offset2)) = word12;
+
+ word12 = *((uint32*)(prev += 4)); /* read b12 b11 b10 b9 */
+ word22 = *((uint32*)(prev + width));
+ 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;
+ *((uint32*)(pred_block += 4)) = word1;
+ prev += offset;
+ }
+ return 1;
+ } /* rnd */
+ } /* tmp */
+}
+
+/**********************************************************************************/
+int GetPredAdvancedBy1x1(
+ uint8 *prev, /* i */
+ uint8 *pred_block, /* i */
+ int width, /* i */
+ int pred_width_rnd /* i */
+)
+{
+ uint i; /* loop variable */
+ int offset, offset2;
+ uint32 x1, x2, x1m, x2m, y1, y2, y1m, y2m; /* new way */
+ int tmp;
+ int rnd1, rnd2;
+ uint32 mask;
+
+ /* initialize offset to adjust pixel counter */
+ /* the next row; full-pel resolution */
+ offset = width - B_SIZE; /* offset for prev */
+ offset2 = (pred_width_rnd >> 1) - 8; /* offset for pred_block */
+
+ rnd1 = pred_width_rnd & 1;
+
+ rnd2 = rnd1 + 1;
+ rnd2 |= (rnd2 << 8);
+ rnd2 |= (rnd2 << 16);
+
+ mask = 0x3F;
+ mask |= (mask << 8);
+ mask |= (mask << 16); /* 0x3f3f3f3f */
+
+ tmp = (uint32)prev & 3;
+
+ pred_block -= 4; /* preset */
+
+ if (tmp == 0) /* word-aligned */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ x1 = *((uint32*)prev); /* load a3 a2 a1 a0 */
+ x2 = *((uint32*)(prev + width)); /* load b3 b2 b1 b0, another line */
+ y1 = *((uint32*)(prev += 4)); /* a7 a6 a5 a4 */
+ y2 = *((uint32*)(prev + width)); /* 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 = *((uint32*)(prev += 4)); /* a11 a10 a9 a8 */
+ y2 = *((uint32*)(prev + width)); /* 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);
+ *((uint32*)(pred_block += 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);
+ *((uint32*)(pred_block += 4)) = y1m; /* save y1m */
+
+ pred_block += offset2;
+ prev += offset;
+ }
+
+ return 1;
+ }
+ else if (tmp == 1)
+ {
+ prev--; /* to word-aligned */
+ for (i = B_SIZE; i > 0; i--)
+ {
+ x1 = *((uint32*)prev); /* load a3 a2 a1 a0 */
+ x2 = *((uint32*)(prev + width)); /* load b3 b2 b1 b0, another line */
+ y1 = *((uint32*)(prev += 4)); /* a7 a6 a5 a4 */
+ y2 = *((uint32*)(prev + width)); /* 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 = *((uint32*)(prev += 4)); /* a11 a10 a9 a8 */
+ y2 = *((uint32*)(prev + width)); /* 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);
+ *((uint32*)(pred_block += 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);
+ *((uint32*)(pred_block += 4)) = y1m; /* save y1m */
+
+ pred_block += offset2;
+ prev += offset;
+ }
+ return 1;
+ }
+ else if (tmp == 2)
+ {
+ prev -= 2; /* to word-aligned */
+ for (i = B_SIZE; i > 0; i--)
+ {
+ x1 = *((uint32*)prev); /* load a3 a2 a1 a0 */
+ x2 = *((uint32*)(prev + width)); /* load b3 b2 b1 b0, another line */
+ y1 = *((uint32*)(prev += 4)); /* a7 a6 a5 a4 */
+ y2 = *((uint32*)(prev + width)); /* 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 = *((uint32*)(prev += 4)); /* a11 a10 a9 a8 */
+ y2 = *((uint32*)(prev + width)); /* 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);
+ *((uint32*)(pred_block += 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);
+ *((uint32*)(pred_block += 4)) = y1m; /* save y1m */
+
+ pred_block += offset2;
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* tmp == 3 */
+ {
+ prev -= 3; /* to word-aligned */
+ for (i = B_SIZE; i > 0; i--)
+ {
+ x1 = *((uint32*)prev); /* load a3 a2 a1 a0 */
+ x2 = *((uint32*)(prev + width)); /* load b3 b2 b1 b0, another line */
+ y1 = *((uint32*)(prev += 4)); /* a7 a6 a5 a4 */
+ y2 = *((uint32*)(prev + width)); /* 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 = *((uint32*)(prev += 4)); /* a11 a10 a9 a8 */
+ y2 = *((uint32*)(prev + width)); /* 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);
+ *((uint32*)(pred_block += 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);
+ *((uint32*)(pred_block += 4)) = y1m; /* save y1m */
+
+ pred_block += offset2;
+ prev += offset;
+ }
+ return 1;
+ }
+}
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_outside.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_outside.cpp
new file mode 100644
index 0000000..9cd9022
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/get_pred_outside.cpp
@@ -0,0 +1,514 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ xpos = x half-pixel of (x,y) coordinates within a VOP; motion
+ compensated coordinates; native data type
+ ypos = y half-pixel of (x,y) coordinates within a VOP; motion
+ compensated coordinates; native data type
+ comp = pointer to 8-bit compensated prediction values within a VOP;
+ computed by this module (i/o); full-pel resolution; 8-bit data
+ c_prev = pointer to previous 8-bit prediction values within a VOP;
+ values range from (0-255); full-pel resolution; 8-bit data
+ sh_d = pointer to residual values used to compensate the predicted
+ value; values range from (-512 to 511); full-pel resolution;
+ native data type
+ width = width of the VOP in pixels (x axis); full-pel resolution;
+ native data type
+ height = height of the VOP in pixels (y axis); full-pel resolution;
+ native data type
+ rnd1 = rounding value for case when one dimension uses half-pel
+ resolution; native data type
+ rnd2 = rounding value for case when two dimensions uses half-pel
+ resolution; native data type
+
+ Outputs:
+ returns 1
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Pointers and Buffers Modified:
+ comp = buffer contains newly computed compensated prediction values
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Summary:
+
+ This function performs motion compensated prediction for the case where
+ the motion vector points to a block outside the VOP. The function interpolates
+ the pixels that are outside the VOP using the boundary pixels for the block.
+ Once the values are interpolated, the pixel values are computed for a block
+ in the current VOP. The prediction values are generated by averaging pixel
+ values in the previous VOP; the block position in the previous frame is
+ computed from the current block's motion vector. The computed pixel values
+ are calculated by adding the prediction values to the block residual values.
+
+ Details:
+
+ First, this functions determines which VOP boundary(ies) the motion vector
+ is outside, i.e., left, right, top, bottom. xpos is compared to the left and
+ right boundaries; ypos is compared to the top and bottom boundaries. The number
+ of block pixels inside the the boundary in the x and y directions are stored
+ in endx and endy, respectively. If the entire block is inside the x or y
+ boundary, the respectively end is set to 0.
+
+ After the boundaries are tested, any pixels lying outside a boundary are
+ interpolated from the boundary pixels. For example, if the block is outside the
+ bottom boundary, boundary pixels alone the bottom of the VOP as used to
+ interpolated those pixels lying outside the bottom boundary. The interpolation
+ used is a simple column-wise or row-wise copy of the boundary pixels (inside the
+ block) depending on which boundary the block is outside. In our example, each
+ boundary pixel would be copied column-wise to the pixel beneath it. If the
+ block was outside right boundary, the boundary pixels would be copied row-wise
+ to the pixel to the right of it. If the block was outside both an x and y
+ boundary, the boundary pixels would be copied row-wise for the portion of the
+ block outside the x boundary, and column-wise for the portion of the block
+ outside the y boundary. And so on.
+
+ Once the pixel interpolation is complete, the motion compensated output values
+ (comp[]) are calculed from the motion compensated prediction (pred[])values and
+ the residual values (sh_d[]) of the current frame. The prediction values are
+ generated by averaging pixel values in the previous VOP; the block position in
+ the previous frame is computed from the current block's motion vector. The
+ computed pixel values are calculated by adding the prediction values to the
+ block residual values.
+
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+#include "motion_comp.h"
+
+#define PAD_CORNER { temp = *prev; \
+ temp |= (temp<<8); \
+ temp |= (temp<<16); \
+ *((uint32*)ptr) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp; }
+
+#define PAD_ROW { temp = *((uint32*)prev); \
+ temp2 = *((uint32*)(prev+4)); \
+ *((uint32*)ptr) = temp;\
+ *((uint32*)(ptr+4)) = temp2; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp2;\
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp2;\
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp2;\
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp2;\
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp2;\
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp2;\
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp2;}
+
+#define PAD_EXTRA_4x8 { temp = *((uint32*)(prev+8)); \
+ *((uint32*)ptr) = temp; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+=16)) = temp; }
+
+#define PAD_COL { temp = *prev; \
+ temp|=(temp<<8); temp|=(temp<<16); \
+ *((uint32*)ptr) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ temp = *(prev+=16); \
+ temp|=(temp<<8); temp|=(temp<<16); \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ temp = *(prev+=16); \
+ temp|=(temp<<8); temp|=(temp<<16); \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ temp = *(prev+=16); \
+ temp|=(temp<<8); temp|=(temp<<16); \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ temp = *(prev+=16); \
+ temp|=(temp<<8); temp|=(temp<<16); \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ temp = *(prev+=16); \
+ temp|=(temp<<8); temp|=(temp<<16); \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ temp = *(prev+=16); \
+ temp|=(temp<<8); temp|=(temp<<16); \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp; \
+ temp = *(prev+=16); \
+ temp|=(temp<<8); temp|=(temp<<16); \
+ *((uint32*)(ptr+=16)) = temp; \
+ *((uint32*)(ptr+4)) = temp;}
+
+/* copy 8x8 block */
+#define COPY_BLOCK { *((uint32*)ptr) = *((uint32*)prev); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); }
+
+#define COPY_12x8 { *((uint32*)ptr) = *((uint32*)prev); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); \
+ *((uint32*)(ptr+=16)) = *((uint32*)(prev+=width)); \
+ *((uint32*)(ptr+4)) = *((uint32*)(prev+4)); \
+ *((uint32*)(ptr+8)) = *((uint32*)(prev+8)); }
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+int GetPredOutside(
+ int xpos, /* i */
+ int ypos, /* i */
+ uint8 *c_prev, /* i */
+ uint8 *pred_block, /* i */
+ int width, /* i */
+ int height, /* i */
+ int rnd1, /* i */
+ int pred_width
+)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ uint8 *prev; /* pointers to adjacent pixels in the */
+ uint8 pred[256]; /* storage for padded pixel values, 16x16 */
+ uint8 *ptr;
+ int xoffset;
+ uint32 temp, temp2;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* saturate xpos and ypos */
+ if (xpos < -16) xpos = -16;
+ if (xpos > ((width - 1) << 1)) xpos = (width - 1) << 1;
+ if (ypos < -16) ypos = -16;
+ if (ypos > ((height - 1) << 1)) ypos = (height - 1) << 1;
+
+ if (xpos < 0)
+ {
+ if (ypos < 0) /* pad top left of frame */
+ {
+ /* copy the block */
+ ptr = pred + (8 << 4) + 8;
+ prev = c_prev;
+ COPY_BLOCK
+
+ /* pad the corner */
+ ptr = pred;
+ prev = pred + (8 << 4) + 8;
+ PAD_CORNER
+
+ /* pad top */
+ ptr = pred + 8;
+ prev = pred + (8 << 4) + 8;
+ PAD_ROW
+
+ /* pad left */
+ ptr = pred + (8 << 4);
+ prev = pred + (8 << 4) + 8;
+ PAD_COL
+
+
+ ptr = pred + (((ypos >> 1) + 8) << 4) + (xpos >> 1) + 8;
+
+ GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
+
+ return 1;
+ }
+ else if ((ypos >> 1) < (height - B_SIZE)) /* pad left of frame */
+ {
+ /* copy block */
+ ptr = pred + 8;
+ prev = c_prev + (ypos >> 1) * width;
+ COPY_BLOCK
+ /* copy extra line */
+ *((uint32*)(ptr += 16)) = *((uint32*)(prev += width));
+ *((uint32*)(ptr + 4)) = *((uint32*)(prev + 4));
+
+ /* pad left */
+ ptr = pred;
+ prev = pred + 8;
+ PAD_COL
+ /* pad extra line */
+ temp = *(prev += 16);
+ temp |= (temp << 8);
+ temp |= (temp << 16);
+ *((uint32*)(ptr += 16)) = temp;
+ *((uint32*)(ptr + 4)) = temp;
+
+ ptr = pred + 8 + (xpos >> 1);
+
+ GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
+
+ return 1;
+ }
+ else /* pad bottom left of frame */
+ {
+ /* copy the block */
+ ptr = pred + 8; /* point to the center */
+ prev = c_prev + width * (height - 8);
+ COPY_BLOCK
+
+ /* pad the corner */
+ ptr = pred + (8 << 4);
+ prev = ptr - 8;
+ PAD_CORNER
+
+ /* pad bottom */
+ ptr = pred + (8 << 4) + 8;
+ prev = ptr - 16;
+ PAD_ROW
+
+ /* pad left */
+ ptr = pred ;
+ prev = ptr + 8;
+ PAD_COL
+
+ ptr = pred + 8 + (((ypos >> 1) - (height - 8)) << 4) + (xpos >> 1);
+
+ GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
+
+ return 1;
+ }
+ }
+ else if ((xpos >> 1) < (width - B_SIZE))
+ {
+ if (ypos < 0) /* pad top of frame */
+ {
+ xoffset = xpos >> 1;
+ xoffset = xoffset & 0x3; /* word align ptr */
+
+ /* copy block */
+ ptr = pred + (8 << 4);
+ prev = c_prev + (xpos >> 1) - xoffset;
+
+ if (xoffset || (xpos&1)) /* copy extra 4x8 */
+ {
+ COPY_12x8
+ }
+ else
+ {
+ COPY_BLOCK
+ }
+
+ /* pad top */
+ ptr = pred;
+ prev = pred + (8 << 4);
+ PAD_ROW
+ if (xoffset || (xpos&1)) /* pad extra 4x8 */
+ {
+ ptr = pred + 8;
+ PAD_EXTRA_4x8
+ }
+
+ ptr = pred + (((ypos >> 1) + 8) << 4) + xoffset;
+
+ GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
+
+ return 1;
+ }
+ else /* pad bottom of frame */
+ {
+ xoffset = xpos >> 1;
+ xoffset = xoffset & 0x3; /* word align ptr */
+ /* copy block */
+ ptr = pred ;
+ prev = c_prev + width * (height - 8) + (xpos >> 1) - xoffset;
+ if (xoffset || (xpos&1))
+ {
+ COPY_12x8
+ }
+ else
+ {
+ COPY_BLOCK
+ }
+
+ /* pad bottom */
+ ptr = pred + (8 << 4);
+ prev = ptr - 16;
+ PAD_ROW
+ if (xoffset || (xpos&1))
+ {
+ ptr = pred + (8 << 4) + 8;
+ PAD_EXTRA_4x8
+ }
+
+ ptr = pred + (((ypos >> 1) - (height - 8)) << 4) + xoffset;
+
+ GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
+
+ return 1;
+ }
+ }
+ else
+ {
+ if (ypos < 0) /* pad top right of frame */
+ {
+ /* copy block */
+ ptr = pred + (8 << 4);
+ prev = c_prev + width - 8;
+ COPY_BLOCK
+
+ /* pad top-right */
+ ptr = pred + 8;
+ prev = pred + (8 << 4) + 7;
+ PAD_CORNER
+
+ /* pad top */
+ ptr = pred ;
+ prev = pred + (8 << 4);
+ PAD_ROW;
+
+ /* pad right */
+ ptr = pred + (8 << 4) + 8;
+ prev = ptr - 1;
+ PAD_COL;
+
+ ptr = pred + ((8 + (ypos >> 1)) << 4) + (8 - (width - (xpos >> 1)));
+
+ GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
+
+ return 1;
+ }
+ else if ((ypos >> 1) < (height - B_SIZE)) /* pad right of frame */
+ {
+ /* copy block */
+ ptr = pred;
+ prev = c_prev + (ypos >> 1) * width + width - 8;
+ COPY_BLOCK
+ /* copy extra line */
+ *((uint32*)(ptr += 16)) = *((uint32*)(prev += width));
+ *((uint32*)(ptr + 4)) = *((uint32*)(prev + 4));
+
+ /* pad right */
+ ptr = pred + 8;
+ prev = ptr - 1;
+ PAD_COL;
+ /* pad extra line */
+ temp = *(prev += 16);
+ temp |= (temp << 8);
+ temp |= (temp << 16);
+ *((uint32*)(ptr += 16)) = temp;
+ *((uint32*)(ptr + 4)) = temp;
+
+
+ ptr = pred + 8 - (width - (xpos >> 1));
+
+ GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
+
+ return 1;
+
+ }
+ else /* pad bottom right of frame */
+ {
+ /* copy block */
+ ptr = pred;
+ prev = c_prev + width * (height - 8) + width - 8;
+ COPY_BLOCK
+
+ /* pad bottom-right */
+ ptr = pred + (8 << 4) + 8;
+ prev = ptr - 17;
+ PAD_CORNER
+
+ /* pad right */
+ ptr = pred + 8;
+ prev = ptr - 1;
+ PAD_COL
+
+ /* pad bottom */
+ ptr = pred + (8 << 4);
+ prev = ptr - 16;
+ PAD_ROW
+
+ ptr = pred + 8 - (width - (xpos >> 1)) + ((8 - (height - (ypos >> 1))) << 4);
+
+ GetPredAdvBTable[ypos&1][xpos&1](ptr, pred_block, 16, (pred_width << 1) | rnd1);
+
+ return 1;
+ }
+ }
+}
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/idct.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/idct.cpp
new file mode 100644
index 0000000..2e932a4
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/idct.cpp
@@ -0,0 +1,579 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ MODULE DESCRIPTION
+
+ This file contains the functions that transform an 8r8 image block from
+ dequantized DCT coefficients to spatial domain pirel values by calculating
+ inverse discrete cosine transform (IDCT).
+
+------------------------------------------------------------------------------
+*/
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+#include "idct.h"
+#include "motion_comp.h"
+#ifndef FAST_IDCT
+
+/*
+------------------------------------------------------------------------------
+ FUNCTION NAME: idct
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS FOR idct
+
+ Inputs:
+ blk = pointer to the buffer containing the dequantized DCT
+ coefficients of type int for an 8r8 image block;
+ values range from (-2048, 2047) which defined as standard.
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ blk points to the found IDCT values for an 8r8 image block.
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION FOR idct
+
+ This function transforms an 8r8 image block from dequantized DCT coefficients
+ (F(u,v)) to spatial domain pirel values (f(r,y)) by performing the two
+ dimensional inverse discrete cosine transform (IDCT).
+
+ _7_ _7_ C(u) C(v)
+ f(r,y) = \ \ F(u,v)---- ----cos[(2r+1)*u*pi/16]cos[(2y+1)*v*pi/16]
+ /__ /__ 2 2
+ u=0 v=0
+
+ where C(i) = 1/sqrt(2) if i=0
+ C(i) = 1 otherwise
+
+ 2-D IDCT can be separated as horizontal(row-wise) and vertical(column-wise)
+ 1-D IDCTs. Therefore, 2-D IDCT values are found by the following two steps:
+ 1. Find horizontal 1-D IDCT values for each row from 8r8 dequantized DCT
+ coefficients by row IDCT operation.
+
+ _7_ C(u)
+ g(r,v) = \ F(u,v) ---- cos[(2r+1)*u*pi/16]
+ /__ 2
+ u=0
+
+ 2. Find vertical 1-D IDCT values for each column from the results of 1
+ by column IDCT operation.
+
+ _7_ C(v)
+ f(r,y) = \ g(r,v) ---- cos[(2y+1)*v*pi/16]
+ /__ 2
+ v=0
+
+------------------------------------------------------------------------------
+ REQUIREMENTS FOR idct
+
+ None
+
+------------------------------------------------------------------------------
+*/
+/* REFERENCES FOR idct */
+/* idct.c, inverse fast discrete cosine transform
+ inverse two dimensional DCT, Chen-Wang algorithm
+ (cf. IEEE ASSP-32, pp. 803-816, Aug. 1984)
+ 32-bit integer arithmetic (8 bit coefficients)
+ 11 mults, 29 adds per DCT
+ sE, 18.8.91
+
+ coefficients ertended to 12 bit for IEEE1180-1990
+ compliance sE, 2.1.94
+*/
+
+
+/*----------------------------------------------------------------------------
+; Function Code FOR idct
+----------------------------------------------------------------------------*/
+void idct_intra(
+ int *blk, uint8 *comp, int width
+)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int i;
+ int32 tmpBLK[64];
+ int32 *tmpBLK32 = &tmpBLK[0];
+ int32 r0, r1, r2, r3, r4, r5, r6, r7, r8; /* butterfly nodes */
+ int32 a;
+ int offset = width - 8;
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* two dimensional inverse discrete cosine transform */
+
+
+ /* column (vertical) IDCT */
+ for (i = B_SIZE - 1; i >= 0; i--)
+ {
+ /* initialize butterfly nodes at first stage */
+
+ r1 = blk[B_SIZE * 4 + i] << 11;
+ /* since row IDCT results have net left shift by 3 */
+ /* this left shift by 8 gives net left shift by 11 */
+ /* in order to maintain the same scale as that of */
+ /* coefficients Wi */
+
+ r2 = blk[B_SIZE * 6 + i];
+ r3 = blk[B_SIZE * 2 + i];
+ r4 = blk[B_SIZE * 1 + i];
+ r5 = blk[B_SIZE * 7 + i];
+ r6 = blk[B_SIZE * 5 + i];
+ r7 = blk[B_SIZE * 3 + i];
+
+ if (!(r1 | r2 | r3 | r4 | r5 | r6 | r7))
+ {
+ /* shortcut */
+ /* execute if values of g(r,1) to g(r,7) in a column*/
+ /* are all zeros */
+
+ /* make output of IDCT >>3 or scaled by 1/8 and */
+ /* with the proper rounding */
+ a = (blk[B_SIZE * 0 + i]) << 3;
+ tmpBLK32[B_SIZE * 0 + i] = a;
+ tmpBLK32[B_SIZE * 1 + i] = a;
+ tmpBLK32[B_SIZE * 2 + i] = a;
+ tmpBLK32[B_SIZE * 3 + i] = a;
+ tmpBLK32[B_SIZE * 4 + i] = a;
+ tmpBLK32[B_SIZE * 5 + i] = a;
+ tmpBLK32[B_SIZE * 6 + i] = a;
+ tmpBLK32[B_SIZE * 7 + i] = a;
+ }
+ else
+ {
+ r0 = (blk[8 * 0 + i] << 11) + 128;
+
+ /* first stage */
+
+ r8 = W7 * (r4 + r5);
+ r4 = (r8 + (W1 - W7) * r4);
+ /* Multiplication with Wi increases the net left */
+ /* shift from 11 to 14,we have to shift back by 3*/
+ r5 = (r8 - (W1 + W7) * r5);
+ r8 = W3 * (r6 + r7);
+ r6 = (r8 - (W3 - W5) * r6);
+ r7 = (r8 - (W3 + W5) * r7);
+
+ /* second stage */
+ r8 = r0 + r1;
+ r0 -= r1;
+
+ r1 = W6 * (r3 + r2);
+ r2 = (r1 - (W2 + W6) * r2);
+ r3 = (r1 + (W2 - W6) * r3);
+
+ r1 = r4 + r6;
+ r4 -= r6;
+ r6 = r5 + r7;
+ r5 -= r7;
+
+ /* third stage */
+ r7 = r8 + r3;
+ r8 -= r3;
+ r3 = r0 + r2;
+ r0 -= r2;
+ r2 = (181 * (r4 + r5) + 128) >> 8; /* rounding */
+ r4 = (181 * (r4 - r5) + 128) >> 8;
+
+ /* fourth stage */
+ /* net shift of IDCT is >>3 after the following */
+ /* shift operation, it makes output of 2-D IDCT */
+ /* scaled by 1/8, that is scaled twice by */
+ /* 1/(2*sqrt(2)) for row IDCT and column IDCT. */
+ /* see detail analysis in design doc. */
+ tmpBLK32[0 + i] = (r7 + r1) >> 8;
+ tmpBLK32[(1<<3) + i] = (r3 + r2) >> 8;
+ tmpBLK32[(2<<3) + i] = (r0 + r4) >> 8;
+ tmpBLK32[(3<<3) + i] = (r8 + r6) >> 8;
+ tmpBLK32[(4<<3) + i] = (r8 - r6) >> 8;
+ tmpBLK32[(5<<3) + i] = (r0 - r4) >> 8;
+ tmpBLK32[(6<<3) + i] = (r3 - r2) >> 8;
+ tmpBLK32[(7<<3) + i] = (r7 - r1) >> 8;
+ }
+ }
+ /* row (horizontal) IDCT */
+ for (i = 0 ; i < B_SIZE; i++)
+ {
+ /* initialize butterfly nodes at the first stage */
+
+ r1 = ((int32)tmpBLK32[4+(i<<3)]) << 8;
+ /* r1 left shift by 11 is to maintain the same */
+ /* scale as that of coefficients (W1,...W7) */
+ /* since blk[4] won't multiply with Wi. */
+ /* see detail diagram in design document. */
+
+ r2 = tmpBLK32[6+(i<<3)];
+ r3 = tmpBLK32[2+(i<<3)];
+ r4 = tmpBLK32[1+(i<<3)];
+ r5 = tmpBLK32[7+(i<<3)];
+ r6 = tmpBLK32[5+(i<<3)];
+ r7 = tmpBLK32[3+(i<<3)];
+
+ if (!(r1 | r2 | r3 | r4 | r5 | r6 | r7))
+ {
+ /* shortcut */
+ /* execute if values of F(1,v) to F(7,v) in a row*/
+ /* are all zeros */
+
+ /* output of row IDCT scaled by 8 */
+ a = (((int32)tmpBLK32[0+(i<<3)] + 32) >> 6);
+ CLIP_RESULT(a)
+ *comp++ = a;
+ *comp++ = a;
+ *comp++ = a;
+ *comp++ = a;
+ *comp++ = a;
+ *comp++ = a;
+ *comp++ = a;
+ *comp++ = a;
+
+ comp += offset;
+ }
+
+ else
+ {
+ /* for proper rounding in the fourth stage */
+ r0 = (((int32)tmpBLK32[0+(i<<3)]) << 8) + 8192;
+
+ /* first stage */
+
+ r8 = W7 * (r4 + r5) + 4;
+ r4 = (r8 + (W1 - W7) * r4) >> 3;
+ r5 = (r8 - (W1 + W7) * r5) >> 3;
+
+ r8 = W3 * (r6 + r7) + 4;
+ r6 = (r8 - (W3 - W5) * r6) >> 3;
+ r7 = (r8 - (W3 + W5) * r7) >> 3;
+
+ /* second stage */
+ r8 = r0 + r1;
+ r0 -= r1;
+
+ r1 = W6 * (r3 + r2) + 4;
+ r2 = (r1 - (W2 + W6) * r2) >> 3;
+ r3 = (r1 + (W2 - W6) * r3) >> 3;
+
+ r1 = r4 + r6;
+ r4 -= r6;
+ r6 = r5 + r7;
+ r5 -= r7;
+
+ /* third stage */
+ r7 = r8 + r3;
+ r8 -= r3;
+ r3 = r0 + r2;
+ r0 -= r2;
+ r2 = (181 * (r4 + r5) + 128) >> 8; /* rounding */
+ r4 = (181 * (r4 - r5) + 128) >> 8;
+
+ /* fourth stage */
+ /* net shift of this function is <<3 after the */
+ /* following shift operation, it makes output of */
+ /* row IDCT scaled by 8 to retain 3 bits precision*/
+ a = ((r7 + r1) >> 14);
+ CLIP_RESULT(a)
+ *comp++ = a;
+ a = ((r3 + r2) >> 14);
+ CLIP_RESULT(a)
+ *comp++ = a;
+ a = ((r0 + r4) >> 14);
+ CLIP_RESULT(a)
+ *comp++ = a;
+ a = ((r8 + r6) >> 14);
+ CLIP_RESULT(a)
+ *comp++ = a;
+ a = ((r8 - r6) >> 14);
+ CLIP_RESULT(a)
+ *comp++ = a;
+ a = ((r0 - r4) >> 14);
+ CLIP_RESULT(a)
+ *comp++ = a;
+ a = ((r3 - r2) >> 14);
+ CLIP_RESULT(a)
+ *comp++ = a;
+ a = ((r7 - r1) >> 14);
+ CLIP_RESULT(a)
+ *comp++ = a;
+
+ comp += offset;
+ }
+ }
+
+
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+
+void idct(
+ int *blk, uint8 *pred, uint8 *dst, int width)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int i;
+ int32 tmpBLK[64];
+ int32 *tmpBLK32 = &tmpBLK[0];
+ int32 r0, r1, r2, r3, r4, r5, r6, r7, r8; /* butterfly nodes */
+ int32 a;
+ int res;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* two dimensional inverse discrete cosine transform */
+
+
+ /* column (vertical) IDCT */
+ for (i = B_SIZE - 1; i >= 0; i--)
+ {
+ /* initialize butterfly nodes at first stage */
+
+ r1 = blk[B_SIZE * 4 + i] << 11;
+ /* since row IDCT results have net left shift by 3 */
+ /* this left shift by 8 gives net left shift by 11 */
+ /* in order to maintain the same scale as that of */
+ /* coefficients Wi */
+
+ r2 = blk[B_SIZE * 6 + i];
+ r3 = blk[B_SIZE * 2 + i];
+ r4 = blk[B_SIZE * 1 + i];
+ r5 = blk[B_SIZE * 7 + i];
+ r6 = blk[B_SIZE * 5 + i];
+ r7 = blk[B_SIZE * 3 + i];
+
+ if (!(r1 | r2 | r3 | r4 | r5 | r6 | r7))
+ {
+ /* shortcut */
+ /* execute if values of g(r,1) to g(r,7) in a column*/
+ /* are all zeros */
+
+ /* make output of IDCT >>3 or scaled by 1/8 and */
+ /* with the proper rounding */
+ a = (blk[B_SIZE * 0 + i]) << 3;
+ tmpBLK32[B_SIZE * 0 + i] = a;
+ tmpBLK32[B_SIZE * 1 + i] = a;
+ tmpBLK32[B_SIZE * 2 + i] = a;
+ tmpBLK32[B_SIZE * 3 + i] = a;
+ tmpBLK32[B_SIZE * 4 + i] = a;
+ tmpBLK32[B_SIZE * 5 + i] = a;
+ tmpBLK32[B_SIZE * 6 + i] = a;
+ tmpBLK32[B_SIZE * 7 + i] = a;
+ }
+ else
+ {
+ r0 = (blk[8 * 0 + i] << 11) + 128;
+
+ /* first stage */
+
+ r8 = W7 * (r4 + r5);
+ r4 = (r8 + (W1 - W7) * r4);
+ /* Multiplication with Wi increases the net left */
+ /* shift from 11 to 14,we have to shift back by 3*/
+ r5 = (r8 - (W1 + W7) * r5);
+ r8 = W3 * (r6 + r7);
+ r6 = (r8 - (W3 - W5) * r6);
+ r7 = (r8 - (W3 + W5) * r7);
+
+ /* second stage */
+ r8 = r0 + r1;
+ r0 -= r1;
+
+ r1 = W6 * (r3 + r2);
+ r2 = (r1 - (W2 + W6) * r2);
+ r3 = (r1 + (W2 - W6) * r3);
+
+ r1 = r4 + r6;
+ r4 -= r6;
+ r6 = r5 + r7;
+ r5 -= r7;
+
+ /* third stage */
+ r7 = r8 + r3;
+ r8 -= r3;
+ r3 = r0 + r2;
+ r0 -= r2;
+ r2 = (181 * (r4 + r5) + 128) >> 8; /* rounding */
+ r4 = (181 * (r4 - r5) + 128) >> 8;
+
+ /* fourth stage */
+ /* net shift of IDCT is >>3 after the following */
+ /* shift operation, it makes output of 2-D IDCT */
+ /* scaled by 1/8, that is scaled twice by */
+ /* 1/(2*sqrt(2)) for row IDCT and column IDCT. */
+ /* see detail analysis in design doc. */
+ tmpBLK32[0 + i] = (r7 + r1) >> 8;
+ tmpBLK32[(1<<3) + i] = (r3 + r2) >> 8;
+ tmpBLK32[(2<<3) + i] = (r0 + r4) >> 8;
+ tmpBLK32[(3<<3) + i] = (r8 + r6) >> 8;
+ tmpBLK32[(4<<3) + i] = (r8 - r6) >> 8;
+ tmpBLK32[(5<<3) + i] = (r0 - r4) >> 8;
+ tmpBLK32[(6<<3) + i] = (r3 - r2) >> 8;
+ tmpBLK32[(7<<3) + i] = (r7 - r1) >> 8;
+ }
+ }
+ /* row (horizontal) IDCT */
+ for (i = B_SIZE - 1; i >= 0; i--)
+ {
+ /* initialize butterfly nodes at the first stage */
+
+ r1 = ((int32)tmpBLK32[4+(i<<3)]) << 8;
+ /* r1 left shift by 11 is to maintain the same */
+ /* scale as that of coefficients (W1,...W7) */
+ /* since blk[4] won't multiply with Wi. */
+ /* see detail diagram in design document. */
+
+ r2 = tmpBLK32[6+(i<<3)];
+ r3 = tmpBLK32[2+(i<<3)];
+ r4 = tmpBLK32[1+(i<<3)];
+ r5 = tmpBLK32[7+(i<<3)];
+ r6 = tmpBLK32[5+(i<<3)];
+ r7 = tmpBLK32[3+(i<<3)];
+
+ if (!(r1 | r2 | r3 | r4 | r5 | r6 | r7))
+ {
+ /* shortcut */
+ /* execute if values of F(1,v) to F(7,v) in a row*/
+ /* are all zeros */
+
+ /* output of row IDCT scaled by 8 */
+ a = (tmpBLK32[0+(i<<3)] + 32) >> 6;
+ blk[0+(i<<3)] = a;
+ blk[1+(i<<3)] = a;
+ blk[2+(i<<3)] = a;
+ blk[3+(i<<3)] = a;
+ blk[4+(i<<3)] = a;
+ blk[5+(i<<3)] = a;
+ blk[6+(i<<3)] = a;
+ blk[7+(i<<3)] = a;
+
+ }
+
+ else
+ {
+ /* for proper rounding in the fourth stage */
+ r0 = (((int32)tmpBLK32[0+(i<<3)]) << 8) + 8192;
+
+ /* first stage */
+
+ r8 = W7 * (r4 + r5) + 4;
+ r4 = (r8 + (W1 - W7) * r4) >> 3;
+ r5 = (r8 - (W1 + W7) * r5) >> 3;
+
+ r8 = W3 * (r6 + r7) + 4;
+ r6 = (r8 - (W3 - W5) * r6) >> 3;
+ r7 = (r8 - (W3 + W5) * r7) >> 3;
+
+ /* second stage */
+ r8 = r0 + r1;
+ r0 -= r1;
+
+ r1 = W6 * (r3 + r2) + 4;
+ r2 = (r1 - (W2 + W6) * r2) >> 3;
+ r3 = (r1 + (W2 - W6) * r3) >> 3;
+
+ r1 = r4 + r6;
+ r4 -= r6;
+ r6 = r5 + r7;
+ r5 -= r7;
+
+ /* third stage */
+ r7 = r8 + r3;
+ r8 -= r3;
+ r3 = r0 + r2;
+ r0 -= r2;
+ r2 = (181 * (r4 + r5) + 128) >> 8; /* rounding */
+ r4 = (181 * (r4 - r5) + 128) >> 8;
+
+ /* fourth stage */
+ /* net shift of this function is <<3 after the */
+ /* following shift operation, it makes output of */
+ /* row IDCT scaled by 8 to retain 3 bits precision*/
+ blk[0+(i<<3)] = (r7 + r1) >> 14;
+ blk[1+(i<<3)] = (r3 + r2) >> 14;
+ blk[2+(i<<3)] = (r0 + r4) >> 14;
+ blk[3+(i<<3)] = (r8 + r6) >> 14;
+ blk[4+(i<<3)] = (r8 - r6) >> 14;
+ blk[5+(i<<3)] = (r0 - r4) >> 14;
+ blk[6+(i<<3)] = (r3 - r2) >> 14;
+ blk[7+(i<<3)] = (r7 - r1) >> 14;
+ }
+ /* add with prediction , 08/03/05 */
+ res = (*pred++ + block[0+(i<<3)]);
+ CLIP_RESULT(res);
+ *dst++ = res;
+ res = (*pred++ + block[1+(i<<3)]);
+ CLIP_RESULT(res);
+ *dst++ = res;
+ res = (*pred++ + block[2+(i<<3)]);
+ CLIP_RESULT(res);
+ *dst++ = res;
+ res = (*pred++ + block[3+(i<<3)]);
+ CLIP_RESULT(res);
+ *dst++ = res;
+ res = (*pred++ + block[4+(i<<3)]);
+ CLIP_RESULT(res);
+ *dst++ = res;
+ res = (*pred++ + block[5+(i<<3)]);
+ CLIP_RESULT(res);
+ *dst++ = res;
+ res = (*pred++ + block[6+(i<<3)]);
+ CLIP_RESULT(res);
+ *dst++ = res;
+ res = (*pred++ + block[7+(i<<3)]);
+ CLIP_RESULT(res);
+ *dst++ = res;
+
+ pred += 8;
+ dst += (width - 8);
+ }
+
+
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+
+#endif
+/*----------------------------------------------------------------------------
+; End Function: idct
+----------------------------------------------------------------------------*/
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/idct.h b/media/libstagefright/codecs/m4v_h263/dec/src/idct.h
new file mode 100644
index 0000000..8edb654
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/idct.h
@@ -0,0 +1,118 @@
+/* ------------------------------------------------------------------
+ * 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 idct_h
+#define idct_h
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define INTEGER_IDCT
+
+#ifdef FAST_IDCT
+#ifndef INTEGER_IDCT
+#define INTEGER_IDCT
+#endif
+#endif
+
+#ifdef FAST_IDCT
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ void idctrow0(int16 *blk, uint8 *pred, uint8 *dst, int width);
+ void idctrow1(int16 *blk, uint8 *pred, uint8 *dst, int width);
+ void idctrow2(int16 *blk, uint8 *pred, uint8 *dst, int width);
+ void idctrow3(int16 *blk, uint8 *pred, uint8 *dst, int width);
+ void idctrow4(int16 *blk, uint8 *pred, uint8 *dst, int width);
+ void idctcol0(int16 *blk);
+ void idctcol1(int16 *blk);
+ void idctcol2(int16 *blk);
+ void idctcol3(int16 *blk);
+ void idctcol4(int16 *blk);
+
+ void idctrow0_intra(int16 *blk, PIXEL *comp, int width);
+ void idctrow1_intra(int16 *blk, PIXEL *comp, int width);
+ void idctrow2_intra(int16 *blk, PIXEL *comp, int width);
+ void idctrow3_intra(int16 *blk, PIXEL *comp, int width);
+ void idctrow4_intra(int16 *blk, PIXEL *comp, int width);
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+/* this code assumes ">>" to be a two's-complement arithmetic */
+/* right shift: (-2)>>1 == -1 , (-3)>>1 == -2 */
+
+/* a positive real constant is converted to an integer scaled by 2048 */
+/* or equivalent to left shift by 11 */
+
+#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) */
+#define W1mW7 2276
+#define W1pW7 3406
+#define W5mW3 -799
+#define mW3mW5 -4017
+#define mW2mW6 -3784
+#define W2mW6 1568
+
+/* left shift by 11 is to maintain the accuracy of the decimal point */
+/* for the transform coefficients (W1,...W7) */
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/idct_vca.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/idct_vca.cpp
new file mode 100644
index 0000000..f35ce4f
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/idct_vca.cpp
@@ -0,0 +1,660 @@
+/* ------------------------------------------------------------------
+ * 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 "idct.h"
+#include "motion_comp.h"
+
+#ifdef FAST_IDCT
+
+/****************************************************************
+* vca_idct.c : created 6/1/99 for several options
+* of hard-coded reduced idct function (using nz_coefs)
+******************************************************************/
+
+/*****************************************************/
+//pretested version
+void idctrow0(int16 *, uint8 *, uint8 *, int)
+{
+ return ;
+}
+void idctcol0(int16 *)
+{
+ return ;
+}
+
+void idctrow1(int16 *blk, uint8 *pred, uint8 *dst, int width)
+{
+ /* shortcut */
+ 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 */
+ width -= 4;
+ dst -= width;
+ pred -= 12;
+ blk -= 8;
+
+ while (i--)
+ {
+ tmp = (*(blk += 8) + 32) >> 6;
+ *blk = 0;
+
+ pred_word = *((uint32*)(pred += 12)); /* 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*)(dst += width)) = 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*)(dst += 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return;
+}
+
+void idctcol1(int16 *blk)
+{ /* shortcut */
+ blk[0] = blk[8] = blk[16] = blk[24] = blk[32] = blk[40] = blk[48] = blk[56] =
+ blk[0] << 3;
+ return;
+}
+
+void idctrow2(int16 *blk, uint8 *pred, uint8 *dst, int width)
+{
+ 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 */
+ width -= 4;
+ dst -= width;
+ pred -= 12;
+ 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 += 12)); /* 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*)(dst += width)) = 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*)(dst += 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return ;
+}
+
+void idctcol2(int16 *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 idctrow3(int16 *blk, uint8 *pred, uint8 *dst, int width)
+{
+ 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 */
+ width -= 4;
+ dst -= width;
+ pred -= 12;
+ 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 += 12)); /* 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*)(dst += width)) = 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*)(dst += 4)) = dst_word; /* save 4 bytes to dst */
+ }
+
+ return ;
+}
+
+void idctcol3(int16 *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 idctrow4(int16 *blk, uint8 *pred, uint8 *dst, int width)
+{
+ 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 */
+ width -= 4;
+ dst -= width;
+ pred -= 12;
+ 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 += 12)); /* 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*)(dst += width)) = 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*)(dst += 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return ;
+}
+
+void idctcol4(int16 *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 ;
+}
+
+void idctrow0_intra(int16 *, PIXEL *, int)
+{
+ return ;
+}
+
+void idctrow1_intra(int16 *blk, PIXEL *comp, int width)
+{
+ /* shortcut */
+ int32 tmp;
+ int i = 8;
+ int offset = width;
+ uint32 word;
+
+ comp -= offset;
+ while (i--)
+ {
+ tmp = ((blk[0] + 32) >> 6);
+ blk[0] = 0;
+ CLIP_RESULT(tmp)
+
+ word = (tmp << 8) | tmp;
+ word = (word << 16) | word;
+
+ *((uint32*)(comp += offset)) = word;
+ *((uint32*)(comp + 4)) = word;
+
+
+
+
+ blk += B_SIZE;
+ }
+ return;
+}
+
+void idctrow2_intra(int16 *blk, PIXEL *comp, int width)
+{
+ int32 x0, x1, x2, x4, x5, temp;
+ int i = 8;
+ int offset = width;
+ int32 word;
+
+ comp -= offset;
+ while (i--)
+ {
+ /* shortcut */
+ x4 = blk[1];
+ blk[1] = 0;
+ x0 = ((int32)blk[0] << 8) + 8192;
+ blk[0] = 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 */
+ word = ((x0 + x4) >> 14);
+ CLIP_RESULT(word)
+
+ temp = ((x0 + x2) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 8);
+ temp = ((x0 + x1) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 16);
+ temp = ((x0 + x5) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 24);
+ *((int32*)(comp += offset)) = word;
+
+ word = ((x0 - x5) >> 14);
+ CLIP_RESULT(word)
+ temp = ((x0 - x1) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 8);
+ temp = ((x0 - x2) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 16);
+ temp = ((x0 - x4) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 24);
+ *((int32*)(comp + 4)) = word;
+
+ blk += B_SIZE;
+ }
+ return ;
+}
+
+void idctrow3_intra(int16 *blk, PIXEL *comp, int width)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8, temp;
+ int i = 8;
+ int offset = width;
+ int32 word;
+
+ comp -= offset;
+
+ while (i--)
+ {
+ x2 = blk[2];
+ blk[2] = 0;
+ x1 = blk[1];
+ blk[1] = 0;
+ x0 = ((int32)blk[0] << 8) + 8192;
+ blk[0] = 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;
+
+ word = ((x0 + x1) >> 14);
+ CLIP_RESULT(word)
+ temp = ((x4 + x7) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 8);
+
+
+ temp = ((x6 + x5) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 16);
+
+ temp = ((x2 + x3) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 24);
+ *((int32*)(comp += offset)) = word;
+
+ word = ((x2 - x3) >> 14);
+ CLIP_RESULT(word)
+
+ temp = ((x6 - x5) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 8);
+
+ temp = ((x4 - x7) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 16);
+
+ temp = ((x0 - x1) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 24);
+ *((int32*)(comp + 4)) = word;
+
+ blk += B_SIZE;
+ }
+ return ;
+}
+
+void idctrow4_intra(int16 *blk, PIXEL *comp, int width)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8, temp;
+ int i = 8;
+ int offset = width;
+ int32 word;
+
+ comp -= offset;
+
+ while (i--)
+ {
+ x2 = blk[2];
+ blk[2] = 0;
+ x1 = blk[1];
+ blk[1] = 0;
+ x3 = blk[3];
+ blk[3] = 0;
+ x0 = ((int32)blk[0] << 8) + 8192;
+ blk[0] = 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;
+
+ word = ((x0 + x1) >> 14);
+ CLIP_RESULT(word)
+
+ temp = ((x4 + x7) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 8);
+
+
+ temp = ((x6 + x5) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 16);
+
+ temp = ((x2 + x3) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 24);
+ *((int32*)(comp += offset)) = word;
+
+ word = ((x2 - x3) >> 14);
+ CLIP_RESULT(word)
+
+ temp = ((x6 - x5) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 8);
+
+ temp = ((x4 - x7) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 16);
+
+ temp = ((x0 - x1) >> 14);
+ CLIP_RESULT(temp)
+ word = word | (temp << 24);
+ *((int32*)(comp + 4)) = word;
+
+ blk += B_SIZE;
+ }
+
+ return ;
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/max_level.h b/media/libstagefright/codecs/m4v_h263/dec/src/max_level.h
new file mode 100644
index 0000000..2d59c73
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/max_level.h
@@ -0,0 +1,149 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+* ------------------------------------------------------------------- *
+* MPEG-4 Simple Profile Video Decoder *
+* ------------------------------------------------------------------- *
+*
+* This software module was originally developed by
+*
+* Michael Wollborn (TUH / 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
+*
+*****************************************************************************
+
+This is a header file for "vlc_decode.c". The table data actually resides
+in "vlc_tab.c".
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+
+#ifndef max_level_H
+#define max_level_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4def.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ extern const int intra_max_level[2][NCOEFF_BLOCK];
+
+ extern const int inter_max_level[2][NCOEFF_BLOCK];
+
+ extern const int intra_max_run0[28];
+
+
+ extern const int intra_max_run1[9];
+
+ extern const int inter_max_run0[13];
+
+
+ extern const int inter_max_run1[4];
+
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/mb_motion_comp.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
new file mode 100644
index 0000000..fbc7be1
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
@@ -0,0 +1,623 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ video = pointer to structure of type VideoDecData
+
+ Local Stores/Buffers/Pointers Needed:
+ roundtab16 = rounding table
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ video->currVop->yChan contents are the newly calculated luminance
+ data
+ video->currVop->uChan contents are the newly calculated chrominance
+ b data
+ video->currVop->vChan contents are the newly calculated chrominance
+ r data
+ video->pstprcTypCur contents are the updated semaphore propagation
+ values
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function performs high level motion compensation on the luminance and
+ chrominance data. It sets up all the parameters required by the functions
+ that perform luminance and chrominance prediction and it initializes the
+ pointer to the post processing semaphores of a given block. It also checks
+ the motion compensation mode in order to determine which luminance or
+ chrominance prediction functions to call and determines how the post
+ processing semaphores are updated.
+
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+#include "motion_comp.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+/* 09/29/2000 bring this from mp4def.h */
+// const static int roundtab4[] = {0,1,1,1};
+// const static int roundtab8[] = {0,0,1,1,1,1,1,2};
+/*** 10/30 for TPS */
+// const static int roundtab12[] = {0,0,0,1,1,1,1,1,1,1,2,2};
+/* 10/30 for TPS ***/
+const static int roundtab16[] = {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2};
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+/** modified 3 August 2005 to do prediction and put the results in
+video->mblock->pred_block, no adding with residue */
+
+void MBMotionComp(
+ VideoDecData *video,
+ int CBP
+)
+{
+
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ /* Previous Video Object Plane */
+ Vop *prev = video->prevVop;
+
+ /* Current Macroblock (MB) in the VOP */
+ int mbnum = video->mbnum;
+
+ /* Number of MB per data row */
+ int MB_in_width = video->nMBPerRow;
+ int ypos, xpos;
+ PIXEL *c_comp, *c_prev;
+ PIXEL *cu_comp, *cu_prev;
+ PIXEL *cv_comp, *cv_prev;
+ int height, width, pred_width;
+ int imv, mvwidth;
+ int32 offset;
+ uint8 mode;
+ uint8 *pred_block, *pred;
+
+ /* Motion vector (dx,dy) in half-pel resolution */
+ int dx, dy;
+
+ MOT px[4], py[4];
+ int xpred, ypred;
+ int xsum;
+ int round1;
+#ifdef PV_POSTPROC_ON // 2/14/2001
+ /* Total number of pixels in the VOL */
+ int32 size = (int32) video->nTotalMB << 8;
+ uint8 *pp_dec_y, *pp_dec_u;
+ int ll[4];
+ int tmp = 0;
+ uint8 msk_deblock = 0;
+#endif
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* Set rounding type */
+ /* change from array to single 09/29/2000 */
+ round1 = (int)(1 - video->currVop->roundingType);
+
+ /* width of luminance data in pixels (y axis) */
+ width = video->width;
+
+ /* heigth of luminance data in pixels (x axis) */
+ height = video->height;
+
+ /* number of blocks per row */
+ mvwidth = MB_in_width << 1;
+
+ /* starting y position in current MB; origin of MB */
+ ypos = video->mbnum_row << 4 ;
+ /* starting x position in current MB; origin of MB */
+ xpos = video->mbnum_col << 4 ;
+
+ /* offset to (x,y) position in current luminance MB */
+ /* in pixel resolution */
+ /* ypos*width -> row, +x -> column */
+ offset = (int32)ypos * width + xpos;
+
+ /* get mode for current MB */
+ mode = video->headerInfo.Mode[mbnum];
+
+ /* block index */
+ /* imv = (xpos/8) + ((ypos/8) * mvwidth) */
+ imv = (offset >> 6) - (xpos >> 6) + (xpos >> 3);
+ if (mode & INTER_1VMASK)
+ {
+ dx = px[0] = px[1] = px[2] = px[3] = video->motX[imv];
+ dy = py[0] = py[1] = py[2] = py[3] = video->motY[imv];
+ if ((dx & 3) == 0)
+ {
+ dx = dx >> 1;
+ }
+ else
+ {
+ /* x component of MV is or'ed for rounding (?) */
+ dx = (dx >> 1) | 1;
+ }
+
+ /* y component of motion vector; divide by 2 for to */
+ /* convert to full-pel resolution. */
+ if ((dy & 3) == 0)
+ {
+ dy = dy >> 1;
+ }
+ else
+ {
+ /* y component of MV is or'ed for rounding (?) */
+ dy = (dy >> 1) | 1;
+ }
+ }
+ else
+ {
+ px[0] = video->motX[imv];
+ px[1] = video->motX[imv+1];
+ px[2] = video->motX[imv+mvwidth];
+ px[3] = video->motX[imv+mvwidth+1];
+ xsum = px[0] + px[1] + px[2] + px[3];
+ dx = PV_SIGN(xsum) * (roundtab16[(PV_ABS(xsum)) & 0xF] +
+ (((PV_ABS(xsum)) >> 4) << 1));
+ py[0] = video->motY[imv];
+ py[1] = video->motY[imv+1];
+ py[2] = video->motY[imv+mvwidth];
+ py[3] = video->motY[imv+mvwidth+1];
+ xsum = py[0] + py[1] + py[2] + py[3];
+ dy = PV_SIGN(xsum) * (roundtab16[(PV_ABS(xsum)) & 0xF] +
+ (((PV_ABS(xsum)) >> 4) << 1));
+ }
+
+ /* Pointer to previous luminance frame */
+ c_prev = prev->yChan;
+
+ pred_block = video->mblock->pred_block;
+
+ /* some blocks have no residue or INTER4V */
+ /*if (mode == MODE_INTER4V) 05/08/15 */
+ /* Motion Compensation for an 8x8 block within a MB */
+ /* (4 MV per MB) */
+
+
+
+ /* Call function that performs luminance prediction */
+ /* luminance_pred_mode_inter4v(xpos, ypos, px, py, c_prev,
+ video->mblock->pred_block, width, height,
+ round1, mvwidth, &xsum, &ysum);*/
+ c_comp = video->currVop->yChan + offset;
+
+
+ xpred = (int)((xpos << 1) + px[0]);
+ ypred = (int)((ypos << 1) + py[0]);
+
+ if ((CBP >> 5)&1)
+ {
+ pred = pred_block;
+ pred_width = 16;
+ }
+ else
+ {
+ pred = c_comp;
+ pred_width = width;
+ }
+
+ /* check whether the MV points outside the frame */
+ if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) &&
+ ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE)))
+ { /*****************************/
+ /* (x,y) is inside the frame */
+ /*****************************/
+ ;
+ GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width),
+ pred, width, (pred_width << 1) | round1);
+ }
+ else
+ { /******************************/
+ /* (x,y) is outside the frame */
+ /******************************/
+ GetPredOutside(xpred, ypred, c_prev,
+ pred, width, height, round1, pred_width);
+ }
+
+
+ /* Compute prediction values over current luminance MB */
+ /* (blocks 1); add motion vector prior to input; */
+ /* add 8 to x_pos to advance to next block */
+ xpred = (int)(((xpos + B_SIZE) << 1) + px[1]);
+ ypred = (int)((ypos << 1) + py[1]);
+
+ if ((CBP >> 4)&1)
+ {
+ pred = pred_block + 8;
+ pred_width = 16;
+ }
+ else
+ {
+ pred = c_comp + 8;
+ pred_width = width;
+ }
+
+ /* check whether the MV points outside the frame */
+ if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) &&
+ ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE)))
+ { /*****************************/
+ /* (x,y) is inside the frame */
+ /*****************************/
+ GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width),
+ pred, width, (pred_width << 1) | round1);
+ }
+ else
+ { /******************************/
+ /* (x,y) is outside the frame */
+ /******************************/
+ GetPredOutside(xpred, ypred, c_prev,
+ pred, width, height, round1, pred_width);
+ }
+
+
+
+ /* Compute prediction values over current luminance MB */
+ /* (blocks 2); add motion vector prior to input */
+ /* add 8 to y_pos to advance to block on next row */
+ xpred = (int)((xpos << 1) + px[2]);
+ ypred = (int)(((ypos + B_SIZE) << 1) + py[2]);
+
+ if ((CBP >> 3)&1)
+ {
+ pred = pred_block + 128;
+ pred_width = 16;
+ }
+ else
+ {
+ pred = c_comp + (width << 3);
+ pred_width = width;
+ }
+
+ /* check whether the MV points outside the frame */
+ if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) &&
+ ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE)))
+ { /*****************************/
+ /* (x,y) is inside the frame */
+ /*****************************/
+ GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width),
+ pred, width, (pred_width << 1) | round1);
+ }
+ else
+ { /******************************/
+ /* (x,y) is outside the frame */
+ /******************************/
+ GetPredOutside(xpred, ypred, c_prev,
+ pred, width, height, round1, pred_width);
+ }
+
+
+
+ /* Compute prediction values over current luminance MB */
+ /* (blocks 3); add motion vector prior to input; */
+ /* add 8 to x_pos and y_pos to advance to next block */
+ /* on next row */
+ xpred = (int)(((xpos + B_SIZE) << 1) + px[3]);
+ ypred = (int)(((ypos + B_SIZE) << 1) + py[3]);
+
+ if ((CBP >> 2)&1)
+ {
+ pred = pred_block + 136;
+ pred_width = 16;
+ }
+ else
+ {
+ pred = c_comp + (width << 3) + 8;
+ pred_width = width;
+ }
+
+ /* check whether the MV points outside the frame */
+ if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) &&
+ ypred >= 0 && ypred <= ((height << 1) - (2*B_SIZE)))
+ { /*****************************/
+ /* (x,y) is inside the frame */
+ /*****************************/
+ GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*width),
+ pred, width, (pred_width << 1) | round1);
+ }
+ else
+ { /******************************/
+ /* (x,y) is outside the frame */
+ /******************************/
+ GetPredOutside(xpred, ypred, c_prev,
+ pred, width, height, round1, pred_width);
+ }
+ /* Call function to set de-blocking and de-ringing */
+ /* semaphores for luminance */
+
+#ifdef PV_POSTPROC_ON
+ if (video->postFilterType != PV_NO_POST_PROC)
+ {
+ if (mode&INTER_1VMASK)
+ {
+ pp_dec_y = video->pstprcTypCur + imv;
+ ll[0] = 1;
+ ll[1] = mvwidth - 1;
+ ll[2] = 1;
+ ll[3] = -mvwidth - 1;
+ msk_deblock = pp_semaphore_luma(xpred, ypred, pp_dec_y,
+ video->pstprcTypPrv, ll, &tmp, px[0], py[0], mvwidth,
+ width, height);
+
+ pp_dec_u = video->pstprcTypCur + (size >> 6) +
+ ((imv + (xpos >> 3)) >> 2);
+
+ pp_semaphore_chroma_inter(xpred, ypred, pp_dec_u,
+ video->pstprcTypPrv, dx, dy, mvwidth, height, size,
+ tmp, msk_deblock);
+ }
+ else
+ {
+ /* Post-processing mode (MBM_INTER8) */
+ /* deblocking and deringing) */
+ pp_dec_y = video->pstprcTypCur + imv;
+ *pp_dec_y = 4;
+ *(pp_dec_y + 1) = 4;
+ *(pp_dec_y + mvwidth) = 4;
+ *(pp_dec_y + mvwidth + 1) = 4;
+ pp_dec_u = video->pstprcTypCur + (size >> 6) +
+ ((imv + (xpos >> 3)) >> 2);
+ *pp_dec_u = 4;
+ pp_dec_u[size>>8] = 4;
+ }
+ }
+#endif
+
+
+ /* xpred and ypred calculation for Chrominance is */
+ /* in full-pel resolution. */
+
+ /* Chrominance */
+ /* width of chrominance data in pixels (y axis) */
+ width >>= 1;
+
+ /* heigth of chrominance data in pixels (x axis) */
+ height >>= 1;
+
+ /* Pointer to previous chrominance b frame */
+ cu_prev = prev->uChan;
+
+ /* Pointer to previous chrominance r frame */
+ cv_prev = prev->vChan;
+
+ /* x position in prediction data offset by motion vector */
+ /* xpred calculation for Chrominance is in full-pel */
+ /* resolution. */
+ xpred = xpos + dx;
+
+ /* y position in prediction data offset by motion vector */
+ /* ypred calculation for Chrominance is in full-pel */
+ /* resolution. */
+ ypred = ypos + dy;
+
+ cu_comp = video->currVop->uChan + (offset >> 2) + (xpos >> 2);
+ cv_comp = video->currVop->vChan + (offset >> 2) + (xpos >> 2);
+
+ /* Call function that performs chrominance prediction */
+ /* chrominance_pred(xpred, ypred, cu_prev, cv_prev,
+ pred_block, width_uv, height_uv,
+ round1);*/
+ if (xpred >= 0 && xpred <= ((width << 1) - (2*B_SIZE)) && ypred >= 0 &&
+ ypred <= ((height << 1) - (2*B_SIZE)))
+ {
+ /*****************************/
+ /* (x,y) is inside the frame */
+ /*****************************/
+ if ((CBP >> 1)&1)
+ {
+ pred = pred_block + 256;
+ pred_width = 16;
+ }
+ else
+ {
+ pred = cu_comp;
+ pred_width = width;
+ }
+
+ /* Compute prediction for Chrominance b (block[4]) */
+ GetPredAdvBTable[ypred&1][xpred&1](cu_prev + (xpred >> 1) + ((ypred >> 1)*width),
+ pred, width, (pred_width << 1) | round1);
+
+ if (CBP&1)
+ {
+ pred = pred_block + 264;
+ pred_width = 16;
+ }
+ else
+ {
+ pred = cv_comp;
+ pred_width = width;
+ }
+ /* Compute prediction for Chrominance r (block[5]) */
+ GetPredAdvBTable[ypred&1][xpred&1](cv_prev + (xpred >> 1) + ((ypred >> 1)*width),
+ pred, width, (pred_width << 1) | round1);
+
+ return ;
+ }
+ else
+ {
+ /******************************/
+ /* (x,y) is outside the frame */
+ /******************************/
+ if ((CBP >> 1)&1)
+ {
+ pred = pred_block + 256;
+ pred_width = 16;
+ }
+ else
+ {
+ pred = cu_comp;
+ pred_width = width;
+ }
+
+ /* Compute prediction for Chrominance b (block[4]) */
+ GetPredOutside(xpred, ypred, cu_prev,
+ pred, width, height, round1, pred_width);
+
+ if (CBP&1)
+ {
+ pred = pred_block + 264;
+ pred_width = 16;
+ }
+ else
+ {
+ pred = cv_comp;
+ pred_width = width;
+ }
+
+ /* Compute prediction for Chrominance r (block[5]) */
+ GetPredOutside(xpred, ypred, cv_prev,
+ pred, width, height, round1, pred_width);
+
+ return ;
+ }
+
+}
+
+/*** special function for skipped macroblock, Aug 15, 2005 */
+void SkippedMBMotionComp(
+ VideoDecData *video
+)
+{
+ Vop *prev = video->prevVop;
+ Vop *comp;
+ int ypos, xpos;
+ PIXEL *c_comp, *c_prev;
+ PIXEL *cu_comp, *cu_prev;
+ PIXEL *cv_comp, *cv_prev;
+ int width, width_uv;
+ int32 offset;
+#ifdef PV_POSTPROC_ON // 2/14/2001
+ int imv;
+ int32 size = (int32) video->nTotalMB << 8;
+ uint8 *pp_dec_y, *pp_dec_u;
+ uint8 *pp_prev1;
+ int mvwidth = video->nMBPerRow << 1;
+#endif
+
+ width = video->width;
+ width_uv = width >> 1;
+ ypos = video->mbnum_row << 4 ;
+ xpos = video->mbnum_col << 4 ;
+ offset = (int32)ypos * width + xpos;
+
+
+ /* zero motion compensation for previous frame */
+ /*mby*width + mbx;*/
+ c_prev = prev->yChan + offset;
+ /*by*width_uv + bx;*/
+ cu_prev = prev->uChan + (offset >> 2) + (xpos >> 2);
+ /*by*width_uv + bx;*/
+ cv_prev = prev->vChan + (offset >> 2) + (xpos >> 2);
+
+ comp = video->currVop;
+
+ c_comp = comp->yChan + offset;
+ cu_comp = comp->uChan + (offset >> 2) + (xpos >> 2);
+ cv_comp = comp->vChan + (offset >> 2) + (xpos >> 2);
+
+
+ /* Copy previous reconstructed frame into the current frame */
+ PutSKIPPED_MB(c_comp, c_prev, width);
+ PutSKIPPED_B(cu_comp, cu_prev, width_uv);
+ PutSKIPPED_B(cv_comp, cv_prev, width_uv);
+
+ /* 10/24/2000 post_processing semaphore generation */
+#ifdef PV_POSTPROC_ON // 2/14/2001
+ if (video->postFilterType != PV_NO_POST_PROC)
+ {
+ imv = (offset >> 6) - (xpos >> 6) + (xpos >> 3);
+ /* Post-processing mode (copy previous MB) */
+ pp_prev1 = video->pstprcTypPrv + imv;
+ pp_dec_y = video->pstprcTypCur + imv;
+ *pp_dec_y = *pp_prev1;
+ *(pp_dec_y + 1) = *(pp_prev1 + 1);
+ *(pp_dec_y + mvwidth) = *(pp_prev1 + mvwidth);
+ *(pp_dec_y + mvwidth + 1) = *(pp_prev1 + mvwidth + 1);
+
+ /* chrominance */
+ /*4*MB_in_width*MB_in_height*/
+ pp_prev1 = video->pstprcTypPrv + (size >> 6) +
+ ((imv + (xpos >> 3)) >> 2);
+ pp_dec_u = video->pstprcTypCur + (size >> 6) +
+ ((imv + (xpos >> 3)) >> 2);
+ *pp_dec_u = *pp_prev1;
+ pp_dec_u[size>>8] = pp_prev1[size>>8];
+ }
+#endif
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+
+ return;
+}
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/mb_utils.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/mb_utils.cpp
new file mode 100644
index 0000000..25a31b7
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/mb_utils.cpp
@@ -0,0 +1,133 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_lib.h"
+
+/* ====================================================================== /
+ Function : PutSKIPPED_MB()
+ Date : 04/03/2000
+/ ====================================================================== */
+
+void PutSKIPPED_MB(uint8 *comp, uint8 *prev, int width)
+{
+ int32 *temp0, *temp1;
+ int row;
+ row = MB_SIZE;
+
+
+ while (row)
+ {
+ temp0 = (int32 *)prev;
+ temp1 = (int32 *)comp;
+
+ temp1[0] = temp0[0];
+ temp1[1] = temp0[1];
+ temp1[2] = temp0[2];
+ temp1[3] = temp0[3];
+
+ comp += width;
+ prev += width;
+
+ temp0 = (int32 *)prev;
+ temp1 = (int32 *)comp;
+
+ temp1[0] = temp0[0];
+ temp1[1] = temp0[1];
+ temp1[2] = temp0[2];
+ temp1[3] = temp0[3];
+
+ comp += width;
+ prev += width;
+
+ temp0 = (int32 *)prev;
+ temp1 = (int32 *)comp;
+ temp1[0] = temp0[0];
+ temp1[1] = temp0[1];
+ temp1[2] = temp0[2];
+ temp1[3] = temp0[3];
+
+
+ comp += width;
+ prev += width;
+
+ temp0 = (int32 *)prev;
+ temp1 = (int32 *)comp;
+ temp1[0] = temp0[0];
+ temp1[1] = temp0[1];
+ temp1[2] = temp0[2];
+ temp1[3] = temp0[3];
+
+ comp += width;
+ prev += width;
+ row -= 4;
+ }
+}
+
+
+/* ====================================================================== /
+ Function : PutSKIPPED_B()
+ Date : 04/03/2000
+/ ====================================================================== */
+
+void PutSKIPPED_B(uint8 *comp, uint8 *prev, int width)
+{
+ int32 *temp0, *temp1;
+ int row;
+
+ row = B_SIZE;
+ while (row)
+ {
+ temp0 = (int32 *)prev;
+ temp1 = (int32 *)comp;
+
+ temp1[0] = temp0[0];
+ temp1[1] = temp0[1];
+
+ comp += width;
+ prev += width;
+
+ temp0 = (int32 *)prev;
+ temp1 = (int32 *)comp;
+
+ temp1[0] = temp0[0];
+ temp1[1] = temp0[1];
+
+ comp += width;
+ prev += width;
+
+ temp0 = (int32 *)prev;
+ temp1 = (int32 *)comp;
+
+ temp1[0] = temp0[0];
+ temp1[1] = temp0[1];
+
+ comp += width;
+ prev += width;
+
+ temp0 = (int32 *)prev;
+ temp1 = (int32 *)comp;
+
+ temp1[0] = temp0[0];
+ temp1[1] = temp0[1];
+
+ comp += width;
+ prev += width;
+ row -= 4;
+ }
+}
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/mbtype_mode.h b/media/libstagefright/codecs/m4v_h263/dec/src/mbtype_mode.h
new file mode 100644
index 0000000..c45bb5f
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/mbtype_mode.h
@@ -0,0 +1,37 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+const static int MBtype_mode[] =
+{
+ MODE_INTER,
+ MODE_INTER_Q,
+ MODE_INTER4V,
+ MODE_INTRA,
+ MODE_INTRA_Q,
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ MODE_INTER4V_Q,
+#endif
+ MODE_SKIPPED
+};
+#ifdef PV_ANNEX_IJKT_SUPPORT
+const static int16 DQ_tab_Annex_T_10[32] = {0, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3};
+const static int16 DQ_tab_Annex_T_11[32] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, -5};
+const static int16 MQ_chroma_QP_table[32] = {0, 1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13,
+ 14, 14, 14, 14, 14, 15, 15, 15, 15, 15
+ };
+#endif
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/motion_comp.h b/media/libstagefright/codecs/m4v_h263/dec/src/motion_comp.h
new file mode 100644
index 0000000..0c12f20
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/motion_comp.h
@@ -0,0 +1,108 @@
+/* ------------------------------------------------------------------
+ * 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 motion_comp_h
+#define motion_comp_h
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+/* CBP Mask defines used in chrominance prediction */
+#define CBP_MASK_CHROMA_BLK4 0x2
+#define CBP_MASK_CHROMA_BLK5 0x1
+
+/* CBP Mask defines used in luminance prediction (MODE_INTER4V) */
+#define CBP_MASK_BLK0_MODE_INTER4V 0x20
+#define CBP_MASK_BLK1_MODE_INTER4V 0x10
+#define CBP_MASK_BLK2_MODE_INTER4V 0x08
+#define CBP_MASK_BLK3_MODE_INTER4V 0x04
+
+/* CBP Mask defines used in luminance prediction (MODE_INTER or MODE_INTER_Q) */
+#define CBP_MASK_MB_MODE_INTER 0x3c
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define CLIP_RESULT(x) if(x & -256){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);
+
+#define ADD_AND_CLIP(x,y) { x9 = ~(x>>8); \
+ if(x9!=-1){ \
+ x9 = ((uint32)x9)>>24; \
+ y = x9|(y<<8); \
+ } \
+ else \
+ { \
+ y = x|(y<<8); \
+ } \
+ }
+
+
+ static int (*const GetPredAdvBTable[2][2])(uint8*, uint8*, int, int) =
+ {
+ {&GetPredAdvancedBy0x0, &GetPredAdvancedBy0x1},
+ {&GetPredAdvancedBy1x0, &GetPredAdvancedBy1x1}
+ };
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/mp4dec_lib.h b/media/libstagefright/codecs/m4v_h263/dec/src/mp4dec_lib.h
new file mode 100644
index 0000000..9cd4edc
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/mp4dec_lib.h
@@ -0,0 +1,334 @@
+/* ------------------------------------------------------------------
+ * 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 _MP4DECLIB_H_
+#define _MP4DECLIB_H_
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4def.h" /* typedef */
+#include "mp4lib_int.h" /* main video structure */
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+ /* defined in pvdec_api.c, these function are not supposed to be */
+ /* exposed to programmers outside PacketVideo. 08/15/2000. */
+ uint VideoDecoderErrorDetected(VideoDecData *video);
+
+#ifdef ENABLE_LOG
+ void m4vdec_dprintf(char *format, ...);
+#define mp4dec_log(message) m4vdec_dprintf(message)
+#else
+#define mp4dec_log(message)
+#endif
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in frame_buffer.c */
+ PV_STATUS FillFrameBufferNew(BitstreamDecVideo *stream);
+ PV_STATUS FillFrameBuffer(BitstreamDecVideo *stream, int short_header);
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in dc_ac_pred.c */
+ int cal_dc_scaler(int QP, int type);
+ PV_STATUS PV_DecodePredictedIntraDC(int compnum, BitstreamDecVideo *stream,
+ int16 *IntraDC_delta);
+
+ void doDCACPrediction(VideoDecData *video, int comp, int16 *q_block,
+ int *direction);
+
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ void doDCACPrediction_I(VideoDecData *video, int comp, int16 *q_block);
+#endif
+ /*--------------------------------------------------------------------------*/
+ /* defined in block_idct.c */
+ void MBlockIDCTAdd(VideoDecData *video, int nz_coefs[]);
+
+ void BlockIDCT(uint8 *dst, uint8 *pred, int16 *blk, int width, int nzcoefs,
+ uint8 *bitmapcol, uint8 bitmaprow);
+
+ void MBlockIDCT(VideoDecData *video);
+ void BlockIDCT_intra(MacroBlock *mblock, PIXEL *c_comp, int comp, int width_offset);
+ /*--------------------------------------------------------------------------*/
+ /* defined in combined_decode.c */
+ PV_STATUS DecodeFrameCombinedMode(VideoDecData *video);
+ PV_STATUS GetMBheader(VideoDecData *video, int16 *QP);
+ PV_STATUS GetMBData(VideoDecData *video);
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in datapart_decode.c */
+ PV_STATUS DecodeFrameDataPartMode(VideoDecData *video);
+ PV_STATUS GetMBheaderDataPart_DQUANT_DC(VideoDecData *video, int16 *QP);
+ PV_STATUS GetMBheaderDataPart_P(VideoDecData *video);
+ PV_STATUS DecodeDataPart_I_VideoPacket(VideoDecData *video, int slice_counter);
+ PV_STATUS DecodeDataPart_P_VideoPacket(VideoDecData *video, int slice_counter);
+ PV_STATUS GetMBData_DataPart(VideoDecData *video);
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in packet_util.c */
+ PV_STATUS PV_ReadVideoPacketHeader(VideoDecData *video, int *next_MB);
+ PV_STATUS RecoverPacketError(BitstreamDecVideo *stream, int marker_length, int32 *nextVop);
+ PV_STATUS RecoverGOBError(BitstreamDecVideo *stream, int marker_length, int32 *vopPos);
+ PV_STATUS PV_GobHeader(VideoDecData *video);
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ PV_STATUS PV_H263SliceHeader(VideoDecData *videoInt, int *next_MB);
+#endif
+ /*--------------------------------------------------------------------------*/
+ /* defined in motion_comp.c */
+ void MBMotionComp(VideoDecData *video, int CBP);
+ void SkippedMBMotionComp(VideoDecData *video);
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in chrominance_pred.c */
+ void chrominance_pred(
+ int xpred, /* i */
+ int ypred, /* i */
+ uint8 *cu_prev, /* i */
+ uint8 *cv_prev, /* i */
+ uint8 *pred_block, /* i */
+ int width_uv, /* i */
+ int height_uv, /* i */
+ int round1
+ );
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in luminance_pred_mode_inter.c */
+ void luminance_pred_mode_inter(
+ int xpred, /* i */
+ int ypred, /* i */
+ uint8 *c_prev, /* i */
+ uint8 *pred_block, /* i */
+ int width, /* i */
+ int height, /* i */
+ int round1
+ );
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in luminance_pred_mode_inter4v.c */
+ void luminance_pred_mode_inter4v(
+ int xpos, /* i */
+ int ypos, /* i */
+ MOT *px, /* i */
+ MOT *py, /* i */
+ uint8 *c_prev, /* i */
+ uint8 *pred_block, /* i */
+ int width, /* i */
+ int height, /* i */
+ int round1, /* i */
+ int mvwidth, /* i */
+ int *xsum_ptr, /* i/o */
+ int *ysum_ptr /* i/o */
+ );
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in pp_semaphore_chroma_inter.c */
+#ifdef PV_POSTPROC_ON
+ void pp_semaphore_chroma_inter(
+ int xpred, /* i */
+ int ypred, /* i */
+ uint8 *pp_dec_u, /* i/o */
+ uint8 *pstprcTypPrv, /* i */
+ int dx, /* i */
+ int dy, /* i */
+ int mvwidth, /* i */
+ int height, /* i */
+ int32 size, /* i */
+ int mv_loc, /* i */
+ uint8 msk_deblock /* i */
+ );
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in pp_semaphore_luma.c */
+ uint8 pp_semaphore_luma(
+ int xpred, /* i */
+ int ypred, /* i */
+ uint8 *pp_dec_y, /* i/o */
+ uint8 *pstprcTypPrv, /* i */
+ int *ll, /* i */
+ int *mv_loc, /* i/o */
+ int dx, /* i */
+ int dy, /* i */
+ int mvwidth, /* i */
+ int width, /* i */
+ int height /* i */
+ );
+#endif
+ /*--------------------------------------------------------------------------*/
+ /* defined in get_pred_adv_mb_add.c */
+ int GetPredAdvancedMB(
+ int xpos,
+ int ypos,
+ uint8 *c_prev,
+ uint8 *pred_block,
+ int width,
+ int rnd1
+ );
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in get_pred_adv_b_add.c */
+ int GetPredAdvancedBy0x0(
+ uint8 *c_prev, /* i */
+ uint8 *pred_block, /* i */
+ int width, /* i */
+ int pred_width_rnd /* i */
+ );
+
+ int GetPredAdvancedBy0x1(
+ uint8 *c_prev, /* i */
+ uint8 *pred_block, /* i */
+ int width, /* i */
+ int pred_width_rnd /* i */
+ );
+
+ int GetPredAdvancedBy1x0(
+ uint8 *c_prev, /* i */
+ uint8 *pred_block, /* i */
+ int width, /* i */
+ int pred_width_rnd /* i */
+ );
+
+ int GetPredAdvancedBy1x1(
+ uint8 *c_prev, /* i */
+ uint8 *pred_block, /* i */
+ int width, /* i */
+ int pred_width_rnd /* i */
+ );
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in get_pred_outside.c */
+ int GetPredOutside(
+ int xpos,
+ int ypos,
+ uint8 *c_prev,
+ uint8 *pred_block,
+ int width,
+ int height,
+ int rnd1,
+ int pred_width
+ );
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in find_pmvsErrRes.c */
+ void mv_prediction(VideoDecData *video, int block, MOT *mvx, MOT *mvy);
+
+ /*--------------------------------------------------------------------------*/
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in mb_utils.c */
+ void Copy_MB_into_Vop(uint8 *comp, int yChan[][NCOEFF_BLOCK], int width);
+ void Copy_B_into_Vop(uint8 *comp, int cChan[], int width);
+ void PutSKIPPED_MB(uint8 *comp, uint8 *c_prev, int width);
+ void PutSKIPPED_B(uint8 *comp, uint8 *c_prev, int width);
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in vop.c */
+ PV_STATUS DecodeGOVHeader(BitstreamDecVideo *stream, uint32 *time_base);
+ PV_STATUS DecodeVOLHeader(VideoDecData *video, int layer);
+ PV_STATUS DecodeVOPHeader(VideoDecData *video, Vop *currVop, Bool use_ext_tiemstamp);
+ PV_STATUS DecodeShortHeader(VideoDecData *video, Vop *currVop);
+ PV_STATUS PV_DecodeVop(VideoDecData *video);
+ uint32 CalcVopDisplayTime(Vol *currVol, Vop *currVop, int shortVideoHeader);
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in post_proc.c */
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ void H263_Deblock(uint8 *rec, int width, int height, int16 *QP_store, uint8 *mode, int chr, int T);
+#endif
+ int PostProcSemaphore(int16 *q_block);
+ void PostFilter(VideoDecData *video, int filer_type, uint8 *output);
+ void FindMaxMin(uint8 *ptr, int *min, int *max, int incr);
+ void DeringAdaptiveSmoothMMX(uint8 *img, int incr, int thres, int mxdf);
+ void AdaptiveSmooth_NoMMX(uint8 *Rec_Y, int v0, int h0, int v_blk, int h_blk,
+ int thr, int width, int max_diff);
+ void Deringing_Luma(uint8 *Rec_Y, int width, int height, int16 *QP_store,
+ int Combined, uint8 *pp_mod);
+ void Deringing_Chroma(uint8 *Rec_C, int width, int height, int16 *QP_store,
+ int Combined, uint8 *pp_mod);
+ void CombinedHorzVertFilter(uint8 *rec, int width, int height, int16 *QP_store,
+ int chr, uint8 *pp_mod);
+ void CombinedHorzVertFilter_NoSoftDeblocking(uint8 *rec, int width, int height, int16 *QP_store,
+ int chr, uint8 *pp_mod);
+ void CombinedHorzVertRingFilter(uint8 *rec, int width, int height,
+ int16 *QP_store, int chr, uint8 *pp_mod);
+
+ /*--------------------------------------------------------------------------*/
+ /* defined in conceal.c */
+ void ConcealTexture_I(VideoDecData *video, int32 startFirstPartition, int mb_start, int mb_stop,
+ int slice_counter);
+ void ConcealTexture_P(VideoDecData *video, int mb_start, int mb_stop,
+ int slice_counter);
+ void ConcealPacket(VideoDecData *video, int mb_start, int mb_stop,
+ int slice_counter);
+ void CopyVopMB(Vop *curr, uint8 *prev, int mbnum, int width, int height);
+
+ /* define in vlc_dequant.c , 09/18/2000*/
+#ifdef PV_SUPPORT_MAIN_PROFILE
+ int VlcDequantMpegIntraBlock(void *video, int comp, int switched,
+ uint8 *bitmapcol, uint8 *bitmaprow);
+ int VlcDequantMpegInterBlock(void *video, int comp,
+ uint8 *bitmapcol, uint8 *bitmaprow);
+#endif
+ int VlcDequantH263IntraBlock(VideoDecData *video, int comp, int switched,
+ uint8 *bitmapcol, uint8 *bitmaprow);
+ int VlcDequantH263IntraBlock_SH(VideoDecData *video, int comp,
+ uint8 *bitmapcol, uint8 *bitmaprow);
+ int VlcDequantH263InterBlock(VideoDecData *video, int comp,
+ uint8 *bitmapcol, uint8 *bitmaprow);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/mp4def.h b/media/libstagefright/codecs/m4v_h263/dec/src/mp4def.h
new file mode 100644
index 0000000..3388d89
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/mp4def.h
@@ -0,0 +1,167 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_api.h"
+
+typedef enum
+{
+ PV_SUCCESS,
+ PV_FAIL,
+ PV_MB_STUFFING, /* hit Macroblock_Stuffing */
+ PV_END_OF_VOP, /* hit End_of_Video_Object_Plane */
+ PV_END_OF_MB /* hit End_of_Macroblock */
+#ifdef PV_TOLERATE_VOL_ERRORS
+ , PV_BAD_VOLHEADER
+#endif
+} PV_STATUS;
+
+typedef uint8 PIXEL;
+typedef int16 MOT; /* : "int" type runs faster on RISC machine */
+
+#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 PV_MEDIAN(A,B,C) ((A) > (B) ? ((A) < (C) ? (A) : (B) > (C) ? (B) : (C)): (B) < (C) ? (B) : (C) > (A) ? (C) : (A))
+/* You don't want to use ((x>UB)?UB:(x<LB)?LB:x) for the clipping */
+/* because it will use one extra comparison if the compiler is */
+/* not well-optimized. 04/19/2000. */
+#define CLIP_THE_RANGE(x,LB,UB) if (x<LB) x = LB; else if (x>UB) x = UB
+
+#define MODE_INTRA 0x08 //01000
+#define MODE_INTRA_Q 0x09 //01001
+#define MODE_SKIPPED 0x10 //10000
+#define MODE_INTER4V 0x14 //10100
+#define MODE_INTER 0x16 //10110
+#define MODE_INTER_Q 0x17 //10111
+#define MODE_INTER4V_Q 0x15 //10101
+#define INTER_1VMASK 0x2
+#define Q_MASK 0x1
+#define INTRA_MASK 0x8
+#define INTER_MASK 0x4
+
+
+#define I_VOP 0
+#define P_VOP 1
+#define B_VOP 2
+
+#define LUMINANCE_DC_TYPE 1
+#define CHROMINANCE_DC_TYPE 2
+
+#define START_CODE_LENGTH 32
+
+/* 11/30/98 */
+#define NoMarkerFound -1
+#define FoundRM 1 /* Resync Marker */
+#define FoundVSC 2 /* VOP_START_CODE. */
+#define FoundGSC 3 /* GROUP_START_CODE */
+#define FoundEOB 4 /* EOB_CODE */
+
+/* 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 VISUAL_OBJECT_SEQUENCE_START_CODE 0x01B0
+#define VISUAL_OBJECT_SEQUENCE_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
+#define BLK_PER_MB 4 /* Number of blocks per MB */
+
+/* VLC decoding related definitions */
+#define VLC_ERROR (-1)
+#define VLC_ESCAPE 7167
+
+
+/* macro utility */
+#define ZERO_OUT_64BYTES(x) { *((uint32*)x) = *(((uint32*)(x))+1) = \
+ *(((uint32*)(x))+2) = *(((uint32*)(x))+3) = \
+ *(((uint32*)(x))+4) = *(((uint32*)(x))+5) = \
+ *(((uint32*)(x))+6) = *(((uint32*)(x))+7) = \
+ *(((uint32*)(x))+8) = *(((uint32*)(x))+9) = \
+ *(((uint32*)(x))+10) = *(((uint32*)(x))+11) = \
+ *(((uint32*)(x))+12) = *(((uint32*)(x))+13) = \
+ *(((uint32*)(x))+14) = *(((uint32*)(x))+15) = 0; }
+
+
+
+#endif /* _PVDECDEF_H_ */
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/mp4lib_int.h b/media/libstagefright/codecs/m4v_h263/dec/src/mp4lib_int.h
new file mode 100644
index 0000000..d6754a7
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/mp4lib_int.h
@@ -0,0 +1,296 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_api.h" // extra structure
+
+#undef ENABLE_LOG
+#define BITRATE_AVERAGE_WINDOW 4
+#define FRAMERATE_SCALE ((BITRATE_AVERAGE_WINDOW-1)*10000L)
+#define FAST_IDCT /* , for fast Variable complexity IDCT */
+//#define PV_DEC_EXTERNAL_IDCT /* for separate IDCT (i.e. no direct access to output frame) */
+#define PV_ANNEX_IJKT_SUPPORT
+#define mid_gray 1024
+
+typedef struct tagBitstream
+{
+ /* function that reteive data from outside the library. 04/11/2000 */
+ /* In frame-based decoding mode, this shall be NULL. 08/29/2000 */
+ uint32 curr_word;
+ uint32 next_word;
+ uint8 *bitstreamBuffer; /* pointer to buffer memory */
+ int32 read_point; /* starting point in the buffer to be read to cache */
+ int incnt; /* bit left in cached */
+ int incnt_next;
+ uint32 bitcnt; /* total bit read so-far (from inbfr)*/
+ int32 data_end_pos; /*should be added , 06/07/2000 */
+ int searched_frame_boundary;
+} BitstreamDecVideo, *LPBitstreamDecVideo;
+
+/* complexity estimation parameters */
+typedef struct tagComplexity_Est
+{
+ uint8 text_1; /* texture_complexity_estimation_set_1 */
+ uint8 text_2; /* texture_complexity_estimation_set_2 */
+ uint8 mc; /* motion_compensation_complexity */
+} Complexity_Est;
+
+
+typedef struct tagVop
+{
+ PIXEL *yChan; /* The Y component */
+ PIXEL *uChan; /* The U component */
+ PIXEL *vChan; /* The V component */
+
+ uint32 timeStamp; /* Vop TimeStamp in msec */
+
+ /* Actual syntax elements for VOP (standard) */
+ int predictionType; /* VOP prediction type */
+ uint timeInc; /* VOP time increment (relative to last mtb) */
+ int vopCoded;
+ int roundingType;
+ int intraDCVlcThr;
+ int16 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 ETR;
+} Vop;
+
+typedef struct tagVol
+{
+ int volID; /* VOL identifier (for tracking) */
+ uint timeIncrementResolution;/* VOL time increment */
+ int nbitsTimeIncRes; /* number of bits for time increment */
+ uint timeInc_offset; /* timeInc offset for multiple VOP in a packet */
+ uint32 moduloTimeBase; /* internal decoder clock */
+ int fixedVopRate;
+ BitstreamDecVideo *bitstream; /* library bitstream buffer (input buffer) */
+
+ int complexity_estDisable; /* VOL disable complexity estimation */
+ int complexity_estMethod; /* VOL complexity estimation method */
+ Complexity_Est complexity; /* complexity estimation flags */
+
+ /* Error Resilience Flags */
+ int errorResDisable; /* VOL disable error resilence mode */
+ /* (Use Resynch markers) */
+ int useReverseVLC; /* VOL reversible VLCs */
+ int dataPartitioning; /* VOL data partitioning */
+
+ /* Bit depth */
+ uint bitsPerPixel;
+// int mid_gray; /* 2^(bits_per_pixel+2) */
+
+ /* Quantization related parameters */
+ int quantPrecision; /* Quantizer precision */
+ uint 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 */
+ /* profile and level */
+ int32 profile_level_id; /* 8-bit profile and level */ // 6/17/04
+
+} Vol;
+
+
+typedef int16 typeMBStore[6][NCOEFF_BLOCK];
+
+typedef struct tagMacroBlock
+{
+ typeMBStore block; /* blocks */ /* ACDC */
+ uint8 pred_block[384]; /* prediction block, Aug 3,2005 */
+ uint8 bitmapcol[6][8];
+ uint8 bitmaprow[6];
+ int no_coeff[6];
+ int DCScalarLum; /* Luminance DC Scalar */
+ int DCScalarChr; /* Chrominance DC Scalar */
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ int direction;
+#endif
+} MacroBlock;
+
+typedef struct tagHeaderInfoDecVideo
+{
+ uint8 *Mode; /* Modes INTRA/INTER/etc. */
+ uint8 *CBP; /* MCBPC/CBPY stuff */
+} HeaderInfoDecVideo;
+
+
+/************************************************************/
+/* VLC structures */
+/************************************************************/
+typedef struct tagTcoef
+{
+ uint last;
+ uint run;
+ int level;
+ uint sign;
+} Tcoef, *LPTcoef;
+
+
+
+typedef struct tagVLCtab
+{
+ int32 val;
+ int32 len;
+} VLCtab, *LPVLCtab;
+
+typedef struct tagVLCshorttab
+{
+ int16 val;
+ int16 len;
+} VLCshorttab, *LPVLCshorttab ; /* for space saving, Antoine Nguyen*/
+
+typedef struct tagVLCtab2
+{
+ uint8 run;
+ uint8 level;
+ uint8 last;
+ uint8 len;
+} VLCtab2, *LPVLCtab2; /* 10/24/2000 */
+
+/* This type is designed for fast access of DC/AC */
+/* prediction data. If the compiler is smart */
+/* enough, it will use shifting for indexing. */
+/* 04/14/2000. */
+
+typedef int16 typeDCStore[6]; /* ACDC */
+typedef int16 typeDCACStore[4][8];
+
+
+
+/* Global structure that can be passed around */
+typedef struct tagVideoDecData
+{
+ BitstreamDecVideo *bitstream; /* library bitstream buffer (input buffer) */
+ /* Data For Layers (Scalability) */
+ Vol **vol; /* Data stored for each VOL */
+
+ /* Data used for reconstructing frames */
+ Vop *currVop; /* Current VOP (frame) */
+ Vop *prevVop; /* Previous VOP (frame) */
+ /* Data used to facilitate multiple layer decoding. 05/04/2000 */
+ Vop *prevEnhcVop; /* New change to rid of memcpy(). 04/24/2001 */
+ Vop **vopHeader; /* one for each layer. 08/29/2000 */
+
+ /* I/O structures */
+ MacroBlock *mblock; /* Macroblock data structure */
+ uint8 *acPredFlag; /* */
+
+ /* scratch memory used in data partitioned mode */
+ typeDCStore *predDC; /* The DC coeffs for each MB */
+ typeDCACStore *predDCAC_row;
+ typeDCACStore *predDCAC_col;
+
+ int usePrevQP; /* running QP decision switch */
+ uint8 *sliceNo; /* Slice indicator for each MB */
+ /* changed this to a 1D */
+ /* array for optimization */
+ MOT *motX; /* Motion vector in X direction */
+ MOT *motY; /* Motion vector in Y direction */
+ HeaderInfoDecVideo headerInfo; /* MB Header information */
+ int16 *QPMB; /* Quantizer value for each MB */
+
+ uint8 *pstprcTypCur; /* Postprocessing type for current frame */
+ uint8 *pstprcTypPrv; /* Postprocessing type for previous frame */
+ /* scratch memory used in all modes */
+ int mbnum; /* Macroblock number */
+ uint mbnum_row;
+ int mbnum_col;
+ /* I added these variables since they are used a lot. 04/13/2000 */
+ int nMBPerRow, nMBPerCol; /* number of MBs in each row & column */
+ int nTotalMB;
+ /* 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 Dimensions */
+ int width; /* Width */
+ int height; /* Height */
+ int displayWidth; /* Handle image whose size is not a multiple of 16. */
+ int displayHeight; /* This is the actual size. 08/09/2000 */
+ int32 size;
+ /* Miscellaneous data points to be passed */
+ int frame_idx; /* Current frame ID */
+ int frameRate; /* Output frame Rate (over 10 seconds) */
+ int32 duration;
+ uint32 currTimestamp;
+ int currLayer; /* Current frame layer */
+ int shortVideoHeader; /* shortVideoHeader mode */
+ int intra_acdcPredDisable; /* VOL disable INTRA DC prediction */
+ int numberOfLayers; /* Number of Layers */
+ /* Frame to be used for concealment 07/07/2001 */
+ uint8 *concealFrame;
+ int vop_coding_type;
+ /* framerate and bitrate statistics counters. 08/23/2000 */
+ int32 nBitsPerVop[BITRATE_AVERAGE_WINDOW];
+ uint32 prevTimestamp[BITRATE_AVERAGE_WINDOW];
+ int nBitsForMBID; /* how many bits required for MB number? */
+ /* total data memory used by the docder library. 08/23/2000 */
+ int32 memoryUsage;
+
+ /* flag to turn on/off error concealment or soft decoding */
+ int errorConcealment;
+
+ /* Application controls */
+ VideoDecControls *videoDecControls;
+ int postFilterType; /* Postfilter mode 04/25/00 */
+
+
+
+ PV_STATUS(*vlcDecCoeffIntra)(BitstreamDecVideo *stream, Tcoef *pTcoef/*, int intra_luma*/);
+ PV_STATUS(*vlcDecCoeffInter)(BitstreamDecVideo *stream, Tcoef *pTcoef);
+ int initialized;
+
+ /* Annex IJKT */
+ int deblocking;
+ int slice_structure;
+ int modified_quant;
+ int advanced_INTRA;
+ int16 QP_CHR; /* ANNEX_T */
+} VideoDecData;
+
+/* for fast VLC+Dequant 10/12/2000*/
+typedef int (*VlcDequantBlockFuncP)(void *video, int comp, int switched,
+ uint8 *bitmaprow, uint8 *bitmapcol);
+
+//////////////////////////////////////////////////////////////
+// Decoder structures //
+//////////////////////////////////////////////////////////////
+#endif /* _MP4LIB_INT_H_ */
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/packet_util.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/packet_util.cpp
new file mode 100644
index 0000000..48414d7
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/packet_util.cpp
@@ -0,0 +1,252 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_lib.h"
+#include "vlc_decode.h"
+#include "bitstream.h"
+
+
+/***********************************************************CommentBegin******
+* 04/13/2000 : initial modification to the new PV-Decoder
+* Lib format.
+* 04/16/2001 : Removed PV_END_OF_BUFFER case, error resilience
+***********************************************************CommentEnd********/
+PV_STATUS PV_ReadVideoPacketHeader(VideoDecData *video, int *next_MB)
+{
+ PV_STATUS status;
+ Vol *currVol = video->vol[video->currLayer];
+ Vop *currVop = video->currVop;
+ BitstreamDecVideo *stream = video->bitstream;
+ int fcode_forward;
+ int resync_marker_length;
+ int nbits = video->nBitsForMBID;
+ uint32 tmpvar32;
+ uint tmpvar16;
+ int16 quantizer;
+ int nTotalMB = video->nTotalMB;
+
+ fcode_forward = currVop->fcodeForward;
+ resync_marker_length = 17;
+
+ if (currVop->predictionType != I_VOP) resync_marker_length = 16 + fcode_forward;
+
+ status = PV_BitstreamShowBitsByteAlign(stream, resync_marker_length, &tmpvar32);
+ /* if (status != PV_SUCCESS && status != PV_END_OF_BUFFER) return status; */
+ if (tmpvar32 == RESYNC_MARKER)
+ {
+// DecNextStartCode(stream);
+ PV_BitstreamByteAlign(stream);
+ BitstreamReadBits32(stream, resync_marker_length);
+
+ *next_MB = (int) BitstreamReadBits16(stream, nbits);
+// if (*next_MB <= video->mbnum) /* needs more investigation */
+// *next_MB = video->mbnum+1;
+
+ if (*next_MB >= nTotalMB) /* fix 04/05/01 */
+ {
+ *next_MB = video->mbnum + 1;
+ if (*next_MB >= nTotalMB) /* this check is needed */
+ *next_MB = nTotalMB - 1;
+ }
+ quantizer = (int16) BitstreamReadBits16(stream, currVol->quantPrecision);
+ if (quantizer == 0) return PV_FAIL; /* 04/03/01 */
+
+ currVop->quantizer = quantizer;
+
+ /* if we have HEC, read some redundant VOP header information */
+ /* this part needs improvement 04/05/01 */
+ if (BitstreamRead1Bits(stream))
+ {
+ int time_base = -1;
+
+ /* modulo_time_base (? bits) */
+ do
+ {
+ time_base++;
+ tmpvar16 = BitstreamRead1Bits(stream);
+ }
+ while (tmpvar16 == 1);
+
+ /* marker bit */
+ BitstreamRead1Bits(stream);
+
+ /* vop_time_increment (1-15 bits) */
+ BitstreamReadBits16(stream, currVol->nbitsTimeIncRes);
+
+ /* marker bit */
+ BitstreamRead1Bits(stream);
+
+ /* vop_prediction_type (2 bits) */
+ BitstreamReadBits16(stream, 2);
+
+ /* Added intra_dc_vlc_thr reading */
+ BitstreamReadBits16(stream, 3);
+
+ /* fcodes */
+ if (currVop->predictionType != I_VOP)
+ {
+ fcode_forward = (int) BitstreamReadBits16(stream, 3);
+
+ if (currVop->predictionType == B_VOP)
+ {
+ BitstreamReadBits16(stream, 3);
+ }
+ }
+
+ }
+ }
+ else
+ {
+ PV_BitstreamByteAlign(stream); /* */
+ status = BitstreamCheckEndBuffer(stream); /* return end_of_VOP 03/30/01 */
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+ status = BitstreamShowBits32HC(stream, &tmpvar32); /* 07/07/01 */
+ /* -16 = 0xFFFFFFF0*/
+ if ((tmpvar32 & 0xFFFFFFF0) == VISUAL_OBJECT_SEQUENCE_START_CODE) /* start code mask 00 00 01 */
+
+ {
+ /* we don't have to check for legl stuffing here. 05/08/2000 */
+ return PV_END_OF_VOP;
+ }
+ else
+ {
+ return PV_FAIL;
+ }
+ }
+
+ return PV_SUCCESS;
+}
+
+
+
+/***********************************************************CommentBegin******
+* 3/10/00 : initial modification to the
+* new PV-Decoder Lib format.
+* 04/17/01 : remove PV_END_OF_BUFFER, error checking
+***********************************************************CommentEnd********/
+PV_STATUS PV_GobHeader(VideoDecData *video)
+{
+ uint32 tmpvar;
+ Vop *currVop = video->currVop;
+ BitstreamDecVideo *stream = video->bitstream;
+ int quantPrecision = 5;
+ int16 quantizer;
+
+ BitstreamShowBits32(stream, GOB_RESYNC_MARKER_LENGTH, &tmpvar);
+
+ if (tmpvar != GOB_RESYNC_MARKER)
+ {
+ PV_BitstreamShowBitsByteAlign(stream, GOB_RESYNC_MARKER_LENGTH, &tmpvar);
+
+ if (tmpvar != GOB_RESYNC_MARKER)
+ {
+ return PV_FAIL;
+ }
+ else
+ PV_BitstreamByteAlign(stream); /* if bytealigned GOBHEADER search is performed */
+ /* then no more noforcestuffing */
+ }
+
+ /* we've got a GOB header info here */
+ BitstreamShowBits32(stream, GOB_RESYNC_MARKER_LENGTH + 5, &tmpvar);
+ tmpvar &= 0x1F;
+
+ if (tmpvar == 0)
+ {
+ return PV_END_OF_VOP;
+ }
+
+ if (tmpvar == 31)
+ {
+ PV_BitstreamFlushBits(stream, GOB_RESYNC_MARKER_LENGTH + 5);
+ BitstreamByteAlignNoForceStuffing(stream);
+ return PV_END_OF_VOP;
+ }
+
+ PV_BitstreamFlushBits(stream, GOB_RESYNC_MARKER_LENGTH + 5);
+ currVop->gobNumber = (int) tmpvar;
+ if (currVop->gobNumber >= video->nGOBinVop) return PV_FAIL;
+ currVop->gobFrameID = (int) BitstreamReadBits16(stream, 2);
+ quantizer = (int16) BitstreamReadBits16(stream, quantPrecision);
+ if (quantizer == 0) return PV_FAIL; /* 04/03/01 */
+
+ currVop->quantizer = quantizer;
+ return PV_SUCCESS;
+}
+#ifdef PV_ANNEX_IJKT_SUPPORT
+PV_STATUS PV_H263SliceHeader(VideoDecData *video, int *next_MB)
+{
+ PV_STATUS status;
+ uint32 tmpvar;
+ Vop *currVop = video->currVop;
+ BitstreamDecVideo *stream = video->bitstream;
+ int nTotalMB = video->nTotalMB;
+ int16 quantizer;
+
+ PV_BitstreamShowBitsByteAlignNoForceStuffing(stream, 17, &tmpvar);
+ if (tmpvar == RESYNC_MARKER)
+ {
+ BitstreamByteAlignNoForceStuffing(stream);
+ PV_BitstreamFlushBits(stream, 17);
+ if (!BitstreamRead1Bits(stream))
+ {
+ return PV_FAIL;
+ }
+ *next_MB = BitstreamReadBits16(stream, video->nBitsForMBID);
+ if (*next_MB >= nTotalMB) /* fix 04/05/01 */
+ {
+ *next_MB = video->mbnum + 1;
+ if (*next_MB >= nTotalMB) /* this check is needed */
+ *next_MB = nTotalMB - 1;
+ }
+ /* we will not parse sebp2 for large pictures 3GPP */
+ quantizer = (int16) BitstreamReadBits16(stream, 5);
+ if (quantizer == 0) return PV_FAIL;
+
+ currVop->quantizer = quantizer;
+ if (!BitstreamRead1Bits(stream))
+ {
+ return PV_FAIL;
+ }
+ currVop->gobFrameID = (int) BitstreamReadBits16(stream, 2);
+ }
+ else
+ {
+ status = BitstreamCheckEndBuffer(stream); /* return end_of_VOP 03/30/01 */
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+ PV_BitstreamShowBitsByteAlign(stream, SHORT_VIDEO_START_MARKER_LENGTH, &tmpvar);
+
+ if (tmpvar == SHORT_VIDEO_START_MARKER)
+ {
+ /* we don't have to check for legal stuffing here. 05/08/2000 */
+ return PV_END_OF_VOP;
+ }
+ else
+ {
+ return PV_FAIL;
+ }
+ }
+ return PV_SUCCESS;
+}
+#endif
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/post_filter.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/post_filter.cpp
new file mode 100644
index 0000000..b36050c
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/post_filter.cpp
@@ -0,0 +1,585 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_lib.h"
+
+#ifdef PV_ANNEX_IJKT_SUPPORT
+#include "motion_comp.h"
+#include "mbtype_mode.h"
+const static int STRENGTH_tab[] = {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12};
+#endif
+
+#ifdef PV_POSTPROC_ON
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void PostFilter(
+ VideoDecData *video,
+ int filter_type,
+ uint8 *output)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ uint8 *pp_mod;
+ int16 *QP_store;
+ int combined_with_deblock_filter;
+ int nTotalMB = video->nTotalMB;
+ int width, height;
+ int32 size;
+ int softDeblocking;
+ uint8 *decodedFrame = video->videoDecControls->outputFrame;
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ width = video->width;
+ height = video->height;
+ size = (int32)width * height;
+
+ oscl_memcpy(output, decodedFrame, size);
+ oscl_memcpy(output + size, decodedFrame + size, (size >> 2));
+ oscl_memcpy(output + size + (size >> 2), decodedFrame + size + (size >> 2), (size >> 2));
+
+ if (filter_type == 0)
+ return;
+
+ /* The softDecoding cutoff corresponds to ~93000 bps for QCIF 15fps clip */
+ if (PVGetDecBitrate(video->videoDecControls) > (100*video->frameRate*(size >> 12))) // MC_sofDeblock
+ softDeblocking = FALSE;
+ else
+ softDeblocking = TRUE;
+
+ combined_with_deblock_filter = filter_type & PV_DEBLOCK;
+ QP_store = video->QPMB;
+
+ /* Luma */
+ pp_mod = video->pstprcTypCur;
+
+ if ((filter_type & PV_DEBLOCK) && (filter_type & PV_DERING))
+ {
+ CombinedHorzVertRingFilter(output, width, height, QP_store, 0, pp_mod);
+ }
+ else
+ {
+ if (filter_type & PV_DEBLOCK)
+ {
+ if (softDeblocking)
+ {
+ CombinedHorzVertFilter(output, width, height,
+ QP_store, 0, pp_mod);
+ }
+ else
+ {
+ CombinedHorzVertFilter_NoSoftDeblocking(output, width, height,
+ QP_store, 0, pp_mod);
+ }
+ }
+ if (filter_type & PV_DERING)
+ {
+ Deringing_Luma(output, width, height, QP_store,
+ combined_with_deblock_filter, pp_mod);
+
+ }
+ }
+
+ /* Chroma */
+
+ pp_mod += (nTotalMB << 2);
+ output += size;
+
+ if ((filter_type & PV_DEBLOCK) && (filter_type & PV_DERING))
+ {
+ CombinedHorzVertRingFilter(output, (int)(width >> 1), (int)(height >> 1), QP_store, (int) 1, pp_mod);
+ }
+ else
+ {
+ if (filter_type & PV_DEBLOCK)
+ {
+ if (softDeblocking)
+ {
+ CombinedHorzVertFilter(output, (int)(width >> 1),
+ (int)(height >> 1), QP_store, (int) 1, pp_mod);
+ }
+ else
+ {
+ CombinedHorzVertFilter_NoSoftDeblocking(output, (int)(width >> 1),
+ (int)(height >> 1), QP_store, (int) 1, pp_mod);
+ }
+ }
+ if (filter_type & PV_DERING)
+ {
+ Deringing_Chroma(output, (int)(width >> 1),
+ (int)(height >> 1), QP_store,
+ combined_with_deblock_filter, pp_mod);
+ }
+ }
+
+ pp_mod += nTotalMB;
+ output += (size >> 2);
+
+ if ((filter_type & PV_DEBLOCK) && (filter_type & PV_DERING))
+ {
+ CombinedHorzVertRingFilter(output, (int)(width >> 1), (int)(height >> 1), QP_store, (int) 1, pp_mod);
+ }
+ else
+ {
+ if (filter_type & PV_DEBLOCK)
+ {
+ if (softDeblocking)
+ {
+ CombinedHorzVertFilter(output, (int)(width >> 1),
+ (int)(height >> 1), QP_store, (int) 1, pp_mod);
+ }
+ else
+ {
+ CombinedHorzVertFilter_NoSoftDeblocking(output, (int)(width >> 1),
+ (int)(height >> 1), QP_store, (int) 1, pp_mod);
+ }
+ }
+ if (filter_type & PV_DERING)
+ {
+ Deringing_Chroma(output, (int)(width >> 1),
+ (int)(height >> 1), QP_store,
+ combined_with_deblock_filter, pp_mod);
+ }
+ }
+
+ /* swap current pp_mod to prev_frame pp_mod */
+ pp_mod = video->pstprcTypCur;
+ video->pstprcTypCur = video->pstprcTypPrv;
+ video->pstprcTypPrv = pp_mod;
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+#endif
+
+
+#ifdef PV_ANNEX_IJKT_SUPPORT
+void H263_Deblock(uint8 *rec,
+ int width,
+ int height,
+ int16 *QP_store,
+ uint8 *mode,
+ int chr, int annex_T)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int i, j, k;
+ uint8 *rec_y;
+ int tmpvar;
+ int mbnum, strength, A_D, d1_2, d1, d2, A, B, C, D, b_size;
+ int d, offset, nMBPerRow, nMBPerCol, width2 = (width << 1);
+ /* MAKE SURE I-VOP INTRA MACROBLOCKS ARE SET TO NON-SKIPPED MODE*/
+ mbnum = 0;
+
+ if (chr)
+ {
+ nMBPerRow = width >> 3;
+ nMBPerCol = height >> 3;
+ b_size = 8;
+ }
+ else
+ {
+ nMBPerRow = width >> 4;
+ nMBPerCol = height >> 4;
+ b_size = 16;
+ }
+
+
+ /********************************* VERTICAL FILTERING ****************************/
+ /* vertical filtering of mid sections no need to check neighboring QP's etc */
+ if (!chr)
+ {
+ rec_y = rec + (width << 3);
+ for (i = 0; i < (height >> 4); i++)
+ {
+ for (j = 0; j < (width >> 4); j++)
+ {
+ if (mode[mbnum] != MODE_SKIPPED)
+ {
+ k = 16;
+ strength = STRENGTH_tab[QP_store[mbnum]];
+ while (k--)
+ {
+ A = *(rec_y - width2);
+ D = *(rec_y + width);
+ A_D = A - D;
+ C = *rec_y;
+ B = *(rec_y - width);
+ d = (((C - B) << 2) + A_D);
+
+ if (d < 0)
+ {
+ d1 = -(-d >> 3);
+ if (d1 < -(strength << 1))
+ {
+ d1 = 0;
+ }
+ else if (d1 < -strength)
+ {
+ d1 = -d1 - (strength << 1);
+ }
+ d1_2 = -d1 >> 1;
+ }
+ else
+ {
+ d1 = d >> 3;
+ if (d1 > (strength << 1))
+ {
+ d1 = 0;
+ }
+ else if (d1 > strength)
+ {
+ d1 = (strength << 1) - d1;
+ }
+ d1_2 = d1 >> 1;
+ }
+
+ if (A_D < 0)
+ {
+ d2 = -(-A_D >> 2);
+ if (d2 < -d1_2)
+ {
+ d2 = -d1_2;
+ }
+ }
+ else
+ {
+ d2 = A_D >> 2;
+ if (d2 > d1_2)
+ {
+ d2 = d1_2;
+ }
+ }
+
+ *(rec_y - width2) = A - d2;
+ tmpvar = B + d1;
+ CLIP_RESULT(tmpvar)
+ *(rec_y - width) = tmpvar;
+ tmpvar = C - d1;
+ CLIP_RESULT(tmpvar)
+ *rec_y = tmpvar;
+ *(rec_y + width) = D + d2;
+ rec_y++;
+ }
+ }
+ else
+ {
+ rec_y += b_size;
+ }
+ mbnum++;
+ }
+ rec_y += (15 * width);
+
+ }
+ }
+
+ /* VERTICAL boundary blocks */
+
+
+ rec_y = rec + width * b_size;
+
+ mbnum = nMBPerRow;
+ for (i = 0; i < nMBPerCol - 1; i++)
+ {
+ for (j = 0; j < nMBPerRow; j++)
+ {
+ if (mode[mbnum] != MODE_SKIPPED || mode[mbnum - nMBPerRow] != MODE_SKIPPED)
+ {
+ k = b_size;
+ if (mode[mbnum] != MODE_SKIPPED)
+ {
+ strength = STRENGTH_tab[(annex_T ? MQ_chroma_QP_table[QP_store[mbnum]] : QP_store[mbnum])];
+ }
+ else
+ {
+ strength = STRENGTH_tab[(annex_T ? MQ_chroma_QP_table[QP_store[mbnum - nMBPerRow]] : QP_store[mbnum - nMBPerRow])];
+ }
+
+ while (k--)
+ {
+ A = *(rec_y - width2);
+ D = *(rec_y + width);
+ A_D = A - D;
+ C = *rec_y;
+ B = *(rec_y - width);
+ d = (((C - B) << 2) + A_D);
+
+ if (d < 0)
+ {
+ d1 = -(-d >> 3);
+ if (d1 < -(strength << 1))
+ {
+ d1 = 0;
+ }
+ else if (d1 < -strength)
+ {
+ d1 = -d1 - (strength << 1);
+ }
+ d1_2 = -d1 >> 1;
+ }
+ else
+ {
+ d1 = d >> 3;
+ if (d1 > (strength << 1))
+ {
+ d1 = 0;
+ }
+ else if (d1 > strength)
+ {
+ d1 = (strength << 1) - d1;
+ }
+ d1_2 = d1 >> 1;
+ }
+
+ if (A_D < 0)
+ {
+ d2 = -(-A_D >> 2);
+ if (d2 < -d1_2)
+ {
+ d2 = -d1_2;
+ }
+ }
+ else
+ {
+ d2 = A_D >> 2;
+ if (d2 > d1_2)
+ {
+ d2 = d1_2;
+ }
+ }
+
+ *(rec_y - width2) = A - d2;
+ tmpvar = B + d1;
+ CLIP_RESULT(tmpvar)
+ *(rec_y - width) = tmpvar;
+ tmpvar = C - d1;
+ CLIP_RESULT(tmpvar)
+ *rec_y = tmpvar;
+ *(rec_y + width) = D + d2;
+ rec_y++;
+ }
+ }
+ else
+ {
+ rec_y += b_size;
+ }
+ mbnum++;
+ }
+ rec_y += ((b_size - 1) * width);
+
+ }
+
+
+ /***************************HORIZONTAL FILTERING ********************************************/
+ mbnum = 0;
+ /* HORIZONTAL INNER */
+ if (!chr)
+ {
+ rec_y = rec + 8;
+ offset = width * b_size - b_size;
+
+ for (i = 0; i < nMBPerCol; i++)
+ {
+ for (j = 0; j < nMBPerRow; j++)
+ {
+ if (mode[mbnum] != MODE_SKIPPED)
+ {
+ k = 16;
+ strength = STRENGTH_tab[QP_store[mbnum]];
+ while (k--)
+ {
+ A = *(rec_y - 2);
+ D = *(rec_y + 1);
+ A_D = A - D;
+ C = *rec_y;
+ B = *(rec_y - 1);
+ d = (((C - B) << 2) + A_D);
+
+ if (d < 0)
+ {
+ d1 = -(-d >> 3);
+ if (d1 < -(strength << 1))
+ {
+ d1 = 0;
+ }
+ else if (d1 < -strength)
+ {
+ d1 = -d1 - (strength << 1);
+ }
+ d1_2 = -d1 >> 1;
+ }
+ else
+ {
+ d1 = d >> 3;
+ if (d1 > (strength << 1))
+ {
+ d1 = 0;
+ }
+ else if (d1 > strength)
+ {
+ d1 = (strength << 1) - d1;
+ }
+ d1_2 = d1 >> 1;
+ }
+
+ if (A_D < 0)
+ {
+ d2 = -(-A_D >> 2);
+ if (d2 < -d1_2)
+ {
+ d2 = -d1_2;
+ }
+ }
+ else
+ {
+ d2 = A_D >> 2;
+ if (d2 > d1_2)
+ {
+ d2 = d1_2;
+ }
+ }
+
+ *(rec_y - 2) = A - d2;
+ tmpvar = B + d1;
+ CLIP_RESULT(tmpvar)
+ *(rec_y - 1) = tmpvar;
+ tmpvar = C - d1;
+ CLIP_RESULT(tmpvar)
+ *rec_y = tmpvar;
+ *(rec_y + 1) = D + d2;
+ rec_y += width;
+ }
+ rec_y -= offset;
+ }
+ else
+ {
+ rec_y += b_size;
+ }
+ mbnum++;
+ }
+ rec_y += (15 * width);
+
+ }
+ }
+
+
+
+ /* HORIZONTAL EDGE */
+ rec_y = rec + b_size;
+ offset = width * b_size - b_size;
+ mbnum = 1;
+ for (i = 0; i < nMBPerCol; i++)
+ {
+ for (j = 0; j < nMBPerRow - 1; j++)
+ {
+ if (mode[mbnum] != MODE_SKIPPED || mode[mbnum-1] != MODE_SKIPPED)
+ {
+ k = b_size;
+ if (mode[mbnum] != MODE_SKIPPED)
+ {
+ strength = STRENGTH_tab[(annex_T ? MQ_chroma_QP_table[QP_store[mbnum]] : QP_store[mbnum])];
+ }
+ else
+ {
+ strength = STRENGTH_tab[(annex_T ? MQ_chroma_QP_table[QP_store[mbnum - 1]] : QP_store[mbnum - 1])];
+ }
+
+ while (k--)
+ {
+ A = *(rec_y - 2);
+ D = *(rec_y + 1);
+ A_D = A - D;
+ C = *rec_y;
+ B = *(rec_y - 1);
+ d = (((C - B) << 2) + A_D);
+
+ if (d < 0)
+ {
+ d1 = -(-d >> 3);
+ if (d1 < -(strength << 1))
+ {
+ d1 = 0;
+ }
+ else if (d1 < -strength)
+ {
+ d1 = -d1 - (strength << 1);
+ }
+ d1_2 = -d1 >> 1;
+ }
+ else
+ {
+ d1 = d >> 3;
+ if (d1 > (strength << 1))
+ {
+ d1 = 0;
+ }
+ else if (d1 > strength)
+ {
+ d1 = (strength << 1) - d1;
+ }
+ d1_2 = d1 >> 1;
+ }
+
+ if (A_D < 0)
+ {
+ d2 = -(-A_D >> 2);
+ if (d2 < -d1_2)
+ {
+ d2 = -d1_2;
+ }
+ }
+ else
+ {
+ d2 = A_D >> 2;
+ if (d2 > d1_2)
+ {
+ d2 = d1_2;
+ }
+ }
+
+ *(rec_y - 2) = A - d2;
+ tmpvar = B + d1;
+ CLIP_RESULT(tmpvar)
+ *(rec_y - 1) = tmpvar;
+ tmpvar = C - d1;
+ CLIP_RESULT(tmpvar)
+ *rec_y = tmpvar;
+ *(rec_y + 1) = D + d2;
+ rec_y += width;
+ }
+ rec_y -= offset;
+ }
+ else
+ {
+ rec_y += b_size;
+ }
+ mbnum++;
+ }
+ rec_y += ((width * (b_size - 1)) + b_size);
+ mbnum++;
+ }
+
+ return;
+}
+#endif
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/post_proc.h b/media/libstagefright/codecs/m4v_h263/dec/src/post_proc.h
new file mode 100644
index 0000000..091fdaf
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/post_proc.h
@@ -0,0 +1,75 @@
+/* ------------------------------------------------------------------
+ * 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 post_proc_H
+#define post_proc_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define UPDATE_PV_MAXPV_MIN(p,max,min) if ((p) > max) max=(p); else if ((p) < min) min = (p);
+
+#define INDEX(x,thr) (((x)>=thr)?1:0)
+#define BLKSIZE 8
+#define MBSIZE 16
+#define DERING_THR 16
+
+/* version for fast Deblock filtering*/
+#define KTh 4 /*threshold for soft filtering*/
+#define KThH 4 /*threshold for hard filtering */
+
+#define NoMMX
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/post_proc_semaphore.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/post_proc_semaphore.cpp
new file mode 100644
index 0000000..3abc6be
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/post_proc_semaphore.cpp
@@ -0,0 +1,247 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ q_block = pointer to buffer of inverse quantized DCT coefficients of type
+ int for intra-VOP mode or buffer of residual data of type int
+ for inter-VOP mode
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ postmode = post processing semaphore with the vertical deblocking,
+ horizontal deblocking, and deringing bits set up accordingly
+
+ Pointers and Buffers Modified:
+ None
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This function sets up the postmode semaphore based on the contents of the
+ buffer pointed to by q_block. The function starts out with the assumption
+ that all entries of q_block, except for the first entry (q_block[0]), are
+ zero. This case can induce horizontal and vertical blocking artifacts,
+ therefore, both horizontal and vertical deblocking bits are enabled.
+
+ The following conditions are tested when setting up the horizontal/vertical
+ deblocking and deringing bits:
+ 1. When only the elements of the top row of the B_SIZE x B_SIZE block
+ (q_block[n], n = 0,..., B_SIZE-1) are non-zero, vertical blocking artifacts
+ may result, therefore, only the vertical deblocking bit is enabled.
+ Otherwise, the vertical deblocking bit is disabled.
+ 2. When only the elements of the far left column of the B_SIZE x B_SIZE block
+ (q_block[n*B_SIZE], n = 0, ..., B_SIZE-1) are non-zero, horizontal blocking
+ artifacts may result, therefore, only the horizontal deblocking bit is
+ enabled. Otherwise, the horizontal deblocking bit is disabled.
+ 3. If any non-zero elements exist in positions other than q_block[0],
+ q_block[1], or q_block[B_SIZE], the deringing bit is enabled. Otherwise,
+ it is disabled.
+
+ The 3 least significant bits of postmode defines vertical or horizontal
+ deblocking and deringing.
+
+ The valid values are shown below:
+ -------------------------------------------------------
+ | Type | Enabled | Disabled |
+ -------------------------------------------------------
+ | Vertical Deblocking (Bit #0) | 1 | 0 |
+ -------------------------------------------------------
+ | Horizontal Deblocking (Bit #1) | 1 | 0 |
+ -------------------------------------------------------
+ | Deringing (Bit #2) | 1 | 0 |
+ -------------------------------------------------------
+
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_lib.h"
+#include "mp4def.h"
+#include "post_proc.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+#ifdef PV_POSTPROC_ON
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+int PostProcSemaphore(
+ int16 *q_block)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int i, j;
+
+ /* Set default value to vertical and horizontal deblocking enabled */
+ /* Initial assumption is that only q_block[0] element is non-zero, */
+ /* therefore, vertical and horizontal deblocking bits are set to 1 */
+ int postmode = 0x3;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* Vertical deblocking bit is enabled when only the entire top row of */
+ /* the B_SIZE x B_SIZE block, i.e., q_block[n], n = 0,..., B_SIZE-1, */
+ /* are non-zero. Since initial assumption is that all elements, except */
+ /* q_block[0], is zero, we need to check the remaining elements in the */
+ /* top row to determine if all or some are non-zero. */
+ if (q_block[1] != 0)
+ {
+ /* At this point, q_block[0] and q_block[1] are non-zero, while */
+ /* q_block[n], n = 2,..., B_SIZE-1, are zero. Therefore, we */
+ /* need to disable vertical deblocking */
+ postmode &= 0xE;
+ }
+
+ for (i = 2; i < B_SIZE; i++)
+ {
+ if (q_block[i])
+ {
+ /* Check if q_block[n], n = 2,..., B_SIZE-1, are non-zero.*/
+ /* If any of them turn out to be non-zero, we need to */
+ /* disable vertical deblocking. */
+ postmode &= 0xE;
+
+ /* Deringing is enabled if any nonzero elements exist in */
+ /* positions other than q_block[0], q_block[1] or */
+ /* q_block[B_SIZE]. */
+ postmode |= 0x4;
+
+ break;
+ }
+ }
+
+ /* Horizontal deblocking bit is enabled when only the entire far */
+ /* left column, i.e., q_block[n*B_SIZE], n = 0, ..., B_SIZE-1, */
+ /* are non-zero. Since initial assumption is that all elements, */
+ /* except q_block[0], is zero, we need to check the remaining */
+ /* elements in the far left column to determine if all or some */
+ /* are non-zero. */
+ if (q_block[B_SIZE])
+ {
+ /* At this point, only q_block[0] and q_block[B_SIZE] are non-zero, */
+ /* while q_block[n*B_SIZE], n = 2, 3,..., B_SIZE-1, are zero. */
+ /* Therefore, we need to disable horizontal deblocking. */
+ postmode &= 0xD;
+ }
+
+ for (i = 16; i < NCOEFF_BLOCK; i += B_SIZE)
+ {
+ if (q_block[i])
+ {
+ /* Check if q_block[n], n = 2*B_SIZE,...,(B_SIZE-1)*B_SIZE, */
+ /* are non-zero. If any of them turn out to be non-zero, */
+ /* we need to disable horizontal deblocking. */
+ postmode &= 0xD;
+
+ /* Deringing is enabled if any nonzero elements exist in */
+ /* positions other than q_block[0], q_block[1] or */
+ /* q_block[B_SIZE]. */
+ postmode |= 0x4;
+
+ break;
+ }
+ }
+
+ /* At this point, only the first row and far left column elements */
+ /* have been tested. If deringing bit is still not set at this */
+ /* point, check the rest of q_block to determine if the elements */
+ /* are non-zero. If all elements, besides q_block[0], q_block[1], */
+ /* or q_block[B_SIZE] are non-zero, deringing bit must be set */
+ if ((postmode & 0x4) == 0)
+ {
+ for (i = 1; i < B_SIZE; i++)
+ {
+ for (j = 1; j < B_SIZE; j++)
+ {
+ if (q_block[(i<<3)+j])
+ {
+ /* At this point, q_block[0] and another q_block */
+ /* element are non-zero, therefore, we need to */
+ /* disable vertical and horizontal deblocking */
+ postmode &= 0xC;
+
+ /* Deringing is enabled if any nonzero elements exist in */
+ /* positions other than q_block[0], q_block[1] or */
+ /* q_block[B_SIZE]. */
+ postmode |= 0x4;
+
+ /* Set outer FOR loop count to B_SIZE to get out of */
+ /* outer FOR loop */
+ i = B_SIZE;
+
+ /* Get out of inner FOR loop */
+ break;
+ }
+ }
+ }
+ }
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return (postmode);
+}
+
+#endif
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/pp_semaphore_chroma_inter.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/pp_semaphore_chroma_inter.cpp
new file mode 100644
index 0000000..7c20222
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/pp_semaphore_chroma_inter.cpp
@@ -0,0 +1,262 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ xpred = x-axis coordinate of the block used for prediction (int)
+ ypred = y-axis coordinate of the block used for prediction (int)
+ pp_dec_u = pointer to the post processing semaphore for chrominance
+ (uint8)
+ pstprcTypPrv = pointer the previous frame's post processing type
+ (uint8)
+ dx = horizontal component of the motion vector (int)
+ dy = vertical component of the motion vector (int)
+ mvwidth = number of blocks per row in the luminance VOP (int)
+ height = luminance VOP height in pixels (int)
+ size = total number of pixel in the current luminance VOP (int)
+ mv_loc = flag indicating location of the motion compensated
+ (x,y) position with respect to the luminance MB (int);
+ 0 -> inside MB, 1 -> outside MB
+ msk_deblock = flag indicating whether to perform deblocking
+ (msk_deblock = 0) or not (msk_deblock = 1) (uint8)
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ None
+
+ Pointers and Buffers Modified:
+ pp_dec_u contents are the updated semaphore propagation data
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This functions performs post processing semaphore propagation processing
+ after chrominance prediction in interframe processing mode.
+
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_api.h"
+#include "mp4def.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+#ifdef PV_POSTPROC_ON
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ /*----------------------------------------------------------------------------
+ ; FUNCTION CODE
+ ----------------------------------------------------------------------------*/
+ void pp_semaphore_chroma_inter(
+ int xpred, /* i */
+ int ypred, /* i */
+ uint8 *pp_dec_u, /* i/o */
+ uint8 *pstprcTypPrv, /* i */
+ int dx, /* i */
+ int dy, /* i */
+ int mvwidth, /* i */
+ int height, /* i */
+ int32 size, /* i */
+ int mv_loc, /* i */
+ uint8 msk_deblock /* i */
+ )
+ {
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int mmvy, mmvx, nmvy, nmvx;
+ uint8 *pp_prev1, *pp_prev2, *pp_prev3, *pp_prev4;
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+
+ /* 09/28/2000, modify semaphore propagation to */
+ /* accommodate smart indexing */
+ mmvx = xpred >> 4; /* block x coor */
+ nmvx = mmvx;
+
+ mmvy = ypred >> 4; /* block y coor */
+ nmvy = mmvy;
+
+ /* Check if MV is outside the frame */
+ if (mv_loc == 1)
+ {
+ /* Perform boundary check */
+ if (nmvx < 0)
+ {
+ nmvx = 0;
+ }
+ else if (nmvx > mvwidth - 1)
+ {
+ nmvx = mvwidth - 1;
+ }
+
+ if (nmvy < 0)
+ {
+ nmvy = 0;
+ }
+ else if (nmvy > (height >> 4) - 1)
+ {
+ nmvy = (height >> 4) - 1;
+ }
+ }
+
+ /* Calculate pointer to first chrominance b semaphores in */
+ /* pstprcTypPrv, i.e., first chrominance b semaphore is in */
+ /* (pstprcTypPrv + (size>>6)). */
+ /* Since total number of chrominance blocks per row in a VOP */
+ /* is half of the total number of luminance blocks per row in a */
+ /* VOP, we use (mvwidth >> 1) when calculating the row offset. */
+ pp_prev1 = pstprcTypPrv + (size >> 6) + nmvx + nmvy * (mvwidth >> 1) ;
+
+ /* Check if MV is a multiple of 16 */
+ /* 1/5/01, make sure it doesn't go out of bound */
+ if (((dy&0xF) != 0) && (mmvy + 1 < (height >> 4) - 1))
+ { /* dy is not a multiple of 16 */
+
+ /* pp_prev3 is the block below pp_prev1 block */
+ pp_prev3 = pp_prev1 + (mvwidth >> 1);
+ }
+ else
+ { /* dy is a multiple of 16 */
+ pp_prev3 = pp_prev1;
+ }
+
+ /* 1/5/01, make sure it doesn't go out of bound */
+ if (((dx&0xF) != 0) && (mmvx + 1 < (mvwidth >> 1) - 1))
+ { /* dx is not a multiple of 16 */
+
+ /* pp_prev2 is the block to the right of pp_prev1 block */
+ pp_prev2 = pp_prev1 + 1;
+
+ /* pp_prev4 is the block to the right of the block */
+ /* below pp_prev1 block */
+ pp_prev4 = pp_prev3 + 1;
+ }
+ else
+ { /* dx is a multiple of 16 */
+
+ pp_prev2 = pp_prev1;
+ pp_prev4 = pp_prev3;
+ }
+
+ /* Advance offset to location of first Chrominance R semaphore in */
+ /* pstprcTypPrv. Since the number of pixels in a Chrominance VOP */
+ /* is (number of pixels in Luminance VOP/4), and there are 64 */
+ /* pixels in an 8x8 Chrominance block, the offset can be */
+ /* calculated as: */
+ /* mv_loc = (number of pixels in Luminance VOP/(4*64)) */
+ /* = size/256 = size>>8 */
+ mv_loc = (size >> 8);
+
+ /* 11/3/00, change the propagation for deblocking */
+ if (msk_deblock == 0)
+ {
+
+ /* Deblocking semaphore propagation for Chrominance */
+ /* b semaphores */
+ *(pp_dec_u) = 0;
+
+ /* Advance offset to point to Chrominance r semaphores */
+ pp_dec_u += mv_loc;
+
+ /* Deblocking semaphore propagation for Chrominance */
+ /* r semaphores */
+ *(pp_dec_u) = 0;
+ }
+ else
+ {
+ /* Deringing semaphore propagation for Chrominance B block */
+ if ((*(pp_dec_u)&4) == 0)
+ {
+ *(pp_dec_u) |= ((*(pp_prev1) | *(pp_prev2) |
+ *(pp_prev3) | *(pp_prev4)) & 0x4);
+ }
+
+ /* Advance offset to point to Chrominance r semaphores */
+ pp_dec_u += mv_loc;
+ pp_prev1 += mv_loc;
+ pp_prev2 += mv_loc;
+ pp_prev3 += mv_loc;
+ pp_prev4 += mv_loc;
+
+ /* Deringing semaphore propagation for Chrominance R */
+ if ((*(pp_dec_u)&4) == 0)
+ {
+ *(pp_dec_u) |= ((*(pp_prev1) | *(pp_prev2) |
+ *(pp_prev3) | *(pp_prev4)) & 0x4);
+ }
+ }
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+ }
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/pp_semaphore_luma.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/pp_semaphore_luma.cpp
new file mode 100644
index 0000000..b3a1ebd
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/pp_semaphore_luma.cpp
@@ -0,0 +1,378 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ xpred = x-axis coordinate of the MB used for prediction (int)
+ ypred = y-axis coordinate of the MB used for prediction (int)
+ pp_dec_y = pointer to the post processing semaphore for current
+ luminance frame (uint8)
+ pstprcTypPrv = pointer the previous frame's post processing type
+ (uint8)
+ ll = pointer to the buffer (int)
+ mv_loc = flag indicating location of the motion compensated
+ (x,y) position with respect to the luminance MB (int);
+ 0 -> inside MB, 1 -> outside MB
+ dx = horizontal component of the motion vector (int)
+ dy = vertical component of the motion vector (int)
+ mvwidth = number of blocks per row (int)
+ width = luminance VOP width in pixels (int)
+ height = luminance VOP height in pixels (int)
+
+ Local Stores/Buffers/Pointers Needed:
+ None
+
+ Global Stores/Buffers/Pointers Needed:
+ None
+
+ Outputs:
+ msk_deblock = flag that indicates whether deblocking is to be
+ performed (msk_deblock = 0) or not (msk_deblock =
+ 1) (uint8)
+
+ Pointers and Buffers Modified:
+ pp_dec_y contents are the updated semapohore propagation data
+
+ Local Stores Modified:
+ None
+
+ Global Stores Modified:
+ None
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ This functions performs post processing semaphore propagation processing
+ after luminance prediction.
+
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4dec_api.h"
+#include "mp4def.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+#ifdef PV_POSTPROC_ON
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ /*----------------------------------------------------------------------------
+ ; FUNCTION CODE
+ ----------------------------------------------------------------------------*/
+ uint8 pp_semaphore_luma(
+ int xpred, /* i */
+ int ypred, /* i */
+ uint8 *pp_dec_y, /* i/o */
+ uint8 *pstprcTypPrv, /* i */
+ int *ll, /* i */
+ int *mv_loc, /* i/o */
+ int dx, /* i */
+ int dy, /* i */
+ int mvwidth, /* i */
+ int width, /* i */
+ int height /* i */
+ )
+ {
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int kk, mmvy, mmvx, nmvx, nmvy;
+ uint8 *pp_prev1, *pp_prev2, *pp_prev3, *pp_prev4;
+ uint8 msk_deblock = 0; /* 11/3/00 */
+
+ /*----------------------------------------------------------------------------
+ ; Function body here
+ ----------------------------------------------------------------------------*/
+ /* Interframe Processing - 1 MV per MB */
+
+ /* check whether the MV points outside the frame */
+ if (xpred >= 0 && xpred <= ((width << 1) - (2*MB_SIZE)) && ypred >= 0 &&
+ ypred <= ((height << 1) - (2*MB_SIZE)))
+ { /*****************************/
+ /* (x,y) is inside the frame */
+ /*****************************/
+
+ /* 10/24/2000 post_processing semaphore */
+ /* generation */
+
+ /* 10/23/2000 no boundary checking*/
+ *mv_loc = 0;
+
+ /* Calculate block x coordinate. Divide by 16 is for */
+ /* converting half-pixel resolution to block */
+ mmvx = xpred >> 4;
+
+ /* Calculate block y coordinate. Divide by 16 is for */
+ /* converting half-pixel resolution to block */
+ mmvy = ypred >> 4;
+
+ /* Find post processing semaphore location for block */
+ /* used for prediction, i.e., */
+ /* pp_prev1 = &pstprcTypPrv[mmvy*mvwidth][mmvx] */
+ pp_prev1 = pstprcTypPrv + mmvx + mmvy * mvwidth;
+
+ /* Check if MV is a multiple of 16 */
+ if ((dx&0xF) != 0)
+ { /* dx is not a multiple of 16 */
+
+ /* pp_prev2 is the block to the right of */
+ /* pp_prev1 block */
+ pp_prev2 = pp_prev1 + 1;
+
+ if ((dy&0xF) != 0)
+ { /* dy is not a multiple of 16 */
+
+ /* pp_prev3 is the block below */
+ /* pp_prev1 block */
+ pp_prev3 = pp_prev1 + mvwidth;
+ }
+ else
+ { /* dy is a multiple of 16 */
+
+ pp_prev3 = pp_prev1;
+ }
+
+ /* pp_prev4 is the block to the right of */
+ /* pp_prev3 block. */
+ pp_prev4 = pp_prev3 + 1;
+ }
+ else
+ { /* dx is a multiple of 16 */
+
+ pp_prev2 = pp_prev1;
+
+ if ((dy&0xF) != 0)
+ { /* dy is not a multiple of 16 */
+
+ /* pp_prev3 is the block below */
+ /* pp_prev1 block. */
+ pp_prev3 = pp_prev1 + mvwidth;
+ }
+ else
+ { /* dy is a multiple of 16 */
+
+ pp_prev3 = pp_prev1;
+ msk_deblock = 0x3;
+ }
+
+ pp_prev4 = pp_prev3;
+ }
+
+ /* Perform post processing semaphore propagation for each */
+ /* of the 4 blocks in a MB. */
+ for (kk = 0; kk < 4; kk++)
+ {
+ /* Deringing semaphore propagation */
+ if ((*(pp_dec_y) & 4) == 0)
+ {
+ *(pp_dec_y) |= ((*(pp_prev1) | *(pp_prev2) |
+ *(pp_prev3) | *(pp_prev4)) & 0x4);
+ }
+ /* Deblocking semaphore propagation */
+ /* 11/3/00, change the propagation for deblocking */
+ if (msk_deblock == 0)
+ {
+ *(pp_dec_y) = 0;
+ }
+
+ pp_dec_y += ll[kk];
+ pp_prev1 += ll[kk];
+ pp_prev2 += ll[kk];
+ pp_prev3 += ll[kk];
+ pp_prev4 += ll[kk];
+ }
+
+ }
+ else
+ { /******************************/
+ /* (x,y) is outside the frame */
+ /******************************/
+
+ /* 10/24/2000 post_processing semaphore */
+ /* generation */
+
+ /* 10/23/2000 boundary checking*/
+ *mv_loc = 1;
+
+ /* Perform post processing semaphore propagation for each */
+ /* of the 4 blocks in a MB. */
+ for (kk = 0; kk < 4; kk++)
+ {
+ /* Calculate block x coordinate and round (?). */
+ /* Divide by 16 is for converting half-pixel */
+ /* resolution to block. */
+ mmvx = (xpred + ((kk & 1) << 3)) >> 4;
+ nmvx = mmvx;
+
+ /* Calculate block y coordinate and round (?). */
+ /* Divide by 16 is for converting half-pixel */
+ /* resolution to block. */
+ mmvy = (ypred + ((kk & 2) << 2)) >> 4;
+ nmvy = mmvy;
+
+ /* Perform boundary checking */
+ if (nmvx < 0)
+ {
+ nmvx = 0;
+ }
+ else if (nmvx > mvwidth - 1)
+ {
+ nmvx = mvwidth - 1;
+ }
+
+ if (nmvy < 0)
+ {
+ nmvy = 0;
+ }
+ else if (nmvy > (height >> 3) - 1)
+ {
+ nmvy = (height >> 3) - 1;
+ }
+
+ /* Find post processing semaphore location for block */
+ /* used for prediction, i.e., */
+ /* pp_prev1 = &pstprcTypPrv[nmvy*mvwidth][nmvx] */
+ pp_prev1 = pstprcTypPrv + nmvx + nmvy * mvwidth;
+
+ /* Check if x component of MV is a multiple of 16 */
+ /* and check if block x coordinate is out of bounds */
+ if (((dx&0xF) != 0) && (mmvx + 1 < mvwidth - 1))
+ { /* dx is not a multiple of 16 and the block */
+ /* x coordinate is within the bounds */
+
+ /* pp_prev2 is the block to the right of */
+ /* pp_prev1 block */
+ pp_prev2 = pp_prev1 + 1;
+
+ /* Check if y component of MV is a multiple */
+ /* of 16 and check if block y coordinate is */
+ /* out of bounds */
+ if (((dy&0xF) != 0) && (mmvy + 1 < (height >> 3) - 1))
+ { /* dy is not a multiple of 16 and */
+ /* the block y coordinate is */
+ /* within the bounds */
+
+ /* pp_prev3 is the block below */
+ /* pp_prev1 block */
+ pp_prev3 = pp_prev1 + mvwidth;
+
+ /* all prediction are from different blocks */
+ msk_deblock = 0x3;
+ }
+ else
+ { /* dy is a multiple of 16 or the block */
+ /* y coordinate is out of bounds */
+
+ pp_prev3 = pp_prev1;
+ }
+
+ /* pp_prev4 is the block to the right of */
+ /* pp_prev3 block. */
+ pp_prev4 = pp_prev3 + 1;
+ }
+ else
+ { /* dx is a multiple of 16 or the block x */
+ /* coordinate is out of bounds */
+
+ pp_prev2 = pp_prev1;
+
+ /* Check if y component of MV is a multiple */
+ /* of 16 and check if block y coordinate is */
+ /* out of bounds */
+ if (((dy&0xF) != 0) && (mmvy + 1 < (height >> 3) - 1))
+ { /* dy is not a multiple of 16 and */
+ /* the block y coordinate is */
+ /* within the bounds */
+
+ /* pp_prev3 is the block below */
+ /* pp_prev1 block. */
+ pp_prev3 = pp_prev1 + mvwidth;
+ }
+ else
+ { /* dy is a multiple of 16 or the block */
+ /* y coordinate is out of bounds */
+
+ pp_prev3 = pp_prev1;
+ }
+
+ pp_prev4 = pp_prev3;
+ }
+
+ /* Deringing semaphore propagation */
+ if ((*(pp_dec_y)&4) == 0)
+ {
+ *(pp_dec_y) |= ((*(pp_prev1) |
+ *(pp_prev2) | *(pp_prev3) |
+ *(pp_prev4)) & 0x4);
+ }
+ /* Deblocking semaphore propagation */
+ /* 11/3/00, change the propaga= */
+ /* tion for deblocking */
+ if (msk_deblock == 0)
+ {
+ *(pp_dec_y) = 0;
+ }
+
+ pp_dec_y += ll[kk];
+ }
+ }
+
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return (msk_deblock);
+ }
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
new file mode 100644
index 0000000..844bd14
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/pvdec_api.cpp
@@ -0,0 +1,1702 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_lib.h"
+#include "vlc_decode.h"
+#include "bitstream.h"
+
+#define OSCL_DISABLE_WARNING_CONDITIONAL_IS_CONSTANT
+
+#ifdef DEC_INTERNAL_MEMORY_OPT
+#define QCIF_MBS 99
+#define QCIF_BS (4*QCIF_MBS)
+#define QCIF_MB_ROWS 11
+extern uint8 IMEM_sliceNo[QCIF_MBS];
+extern uint8 IMEM_acPredFlag[QCIF_MBS];
+extern uint8 IMEM_headerInfo_Mode[QCIF_MBS];
+extern uint8 IMEM_headerInfo_CBP[QCIF_MBS];
+extern int IMEM_headerInfo_QPMB[QCIF_MBS];
+extern MacroBlock IMEM_mblock;
+extern MOT IMEM_motX[QCIF_BS];
+extern MOT IMEM_motY[QCIF_BS];
+extern BitstreamDecVideo IMEM_BitstreamDecVideo[4];
+extern typeDCStore IMEM_predDC[QCIF_MBS];
+extern typeDCACStore IMEM_predDCAC_col[QCIF_MB_ROWS+1];
+
+extern VideoDecData IMEM_VideoDecData[1];
+extern Vop IMEM_currVop[1];
+extern Vop IMEM_prevVop[1];
+extern PIXEL IMEM_currVop_yChan[QCIF_MBS*128*3];
+extern PIXEL IMEM_prevVop_yChan[QCIF_MBS*128*3];
+extern uint8 IMEM_pstprcTypCur[6*QCIF_MBS];
+extern uint8 IMEM_pstprcTypPrv[6*QCIF_MBS];
+
+
+extern Vop IMEM_vopHEADER[2];
+extern Vol IMEM_VOL[2];
+extern Vop IMEM_vopHeader[2][1];
+extern Vol IMEM_vol[2][1];
+
+#endif
+
+/* ======================================================================== */
+/* Function : PVInitVideoDecoder() */
+/* Date : 04/11/2000, 08/29/2000 */
+/* Purpose : Initialization of the MPEG-4 video decoder library. */
+/* The return type is Bool instead of PV_STATUS because */
+/* we don't want to expose PV_STATUS to (outside) programmers */
+/* that use our decoder library SDK. */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVInitVideoDecoder(VideoDecControls *decCtrl, uint8 *volbuf[],
+ int32 *volbuf_size, int nLayers, int width, int height, MP4DecodingMode mode)
+{
+ VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
+ Bool status = PV_TRUE;
+ int idx;
+ BitstreamDecVideo *stream;
+
+
+ oscl_memset(decCtrl, 0, sizeof(VideoDecControls)); /* fix a size bug. 03/28/2001 */
+ decCtrl->nLayers = nLayers;
+ for (idx = 0; idx < nLayers; idx++)
+ {
+ decCtrl->volbuf[idx] = volbuf[idx];
+ decCtrl->volbuf_size[idx] = volbuf_size[idx];
+ }
+
+ /* memory allocation & initialization */
+#ifdef DEC_INTERNAL_MEMORY_OPT
+ video = IMEM_VideoDecData;
+#else
+ video = (VideoDecData *) oscl_malloc(sizeof(VideoDecData));
+#endif
+ if (video != NULL)
+ {
+ oscl_memset(video, 0, sizeof(VideoDecData));
+ video->memoryUsage = sizeof(VideoDecData);
+ video->numberOfLayers = nLayers;
+#ifdef DEC_INTERNAL_MEMORY_OPT
+ video->vol = (Vol **) IMEM_VOL;
+#else
+ video->vol = (Vol **) oscl_malloc(nLayers * sizeof(Vol *));
+#endif
+ if (video->vol == NULL) status = PV_FALSE;
+ video->memoryUsage += nLayers * sizeof(Vol *);
+
+
+ /* we need to setup this pointer for the application to */
+ /* pass it around. */
+ decCtrl->videoDecoderData = (void *) video;
+ video->videoDecControls = decCtrl; /* yes. we have a cyclic */
+ /* references here :) */
+
+ /* Allocating Vop space, this has to change when we add */
+ /* spatial scalability to the decoder */
+#ifdef DEC_INTERNAL_MEMORY_OPT
+ video->currVop = IMEM_currVop;
+ if (video->currVop == NULL) status = PV_FALSE;
+ else oscl_memset(video->currVop, 0, sizeof(Vop));
+ video->prevVop = IMEM_prevVop;
+ if (video->prevVop == NULL) status = PV_FALSE;
+ else oscl_memset(video->prevVop, 0, sizeof(Vop));
+ video->memoryUsage += (sizeof(Vop) * 2);
+ video->vopHeader = (Vop **) IMEM_vopHEADER;
+#else
+
+ video->currVop = (Vop *) oscl_malloc(sizeof(Vop));
+ if (video->currVop == NULL) status = PV_FALSE;
+ else oscl_memset(video->currVop, 0, sizeof(Vop));
+ video->prevVop = (Vop *) oscl_malloc(sizeof(Vop));
+ if (video->prevVop == NULL) status = PV_FALSE;
+ else oscl_memset(video->prevVop, 0, sizeof(Vop));
+ video->memoryUsage += (sizeof(Vop) * 2);
+
+ video->vopHeader = (Vop **) oscl_malloc(sizeof(Vop *) * nLayers);
+#endif
+ if (video->vopHeader == NULL) status = PV_FALSE;
+ else oscl_memset(video->vopHeader, 0, sizeof(Vop *)*nLayers);
+ video->memoryUsage += (sizeof(Vop *) * nLayers);
+
+ video->initialized = PV_FALSE;
+ /* Decode the header to get all information to allocate data */
+ if (status == PV_TRUE)
+ {
+ /* initialize decoded frame counter. 04/24/2001 */
+ video->frame_idx = -1;
+
+
+ for (idx = 0; idx < nLayers; idx++)
+ {
+
+#ifdef DEC_INTERNAL_MEMORY_OPT
+ video->vopHeader[idx] = IMEM_vopHeader[idx];
+#else
+ video->vopHeader[idx] = (Vop *) oscl_malloc(sizeof(Vop));
+#endif
+ if (video->vopHeader[idx] == NULL)
+ {
+ status = PV_FALSE;
+ break;
+ }
+ else
+ {
+ oscl_memset(video->vopHeader[idx], 0, sizeof(Vop));
+ video->vopHeader[idx]->timeStamp = 0;
+ video->memoryUsage += (sizeof(Vop));
+ }
+#ifdef DEC_INTERNAL_MEMORY_OPT
+ video->vol[idx] = IMEM_vol[idx];
+ video->memoryUsage += sizeof(Vol);
+ oscl_memset(video->vol[idx], 0, sizeof(Vol));
+ if (video->vol[idx] == NULL) status = PV_FALSE;
+ stream = IMEM_BitstreamDecVideo;
+#else
+ video->vol[idx] = (Vol *) oscl_malloc(sizeof(Vol));
+ if (video->vol[idx] == NULL)
+ {
+ status = PV_FALSE;
+ break;
+ }
+ else
+ {
+ video->memoryUsage += sizeof(Vol);
+ oscl_memset(video->vol[idx], 0, sizeof(Vol));
+ }
+
+ stream = (BitstreamDecVideo *) oscl_malloc(sizeof(BitstreamDecVideo));
+#endif
+ video->memoryUsage += sizeof(BitstreamDecVideo);
+ if (stream == NULL)
+ {
+ status = PV_FALSE;
+ break;
+ }
+ else
+ {
+ int32 buffer_size;
+ if ((buffer_size = BitstreamOpen(stream, idx)) < 0)
+ {
+ mp4dec_log("InitVideoDecoder(): Can't allocate bitstream buffer.\n");
+ status = PV_FALSE;
+ break;
+ }
+ video->memoryUsage += buffer_size;
+ video->vol[idx]->bitstream = stream;
+ video->vol[idx]->volID = idx;
+ video->vol[idx]->timeInc_offset = 0; /* 11/12/01 */
+ video->vlcDecCoeffIntra = &VlcDecTCOEFShortHeader;
+ video->vlcDecCoeffInter = &VlcDecTCOEFShortHeader;
+ if (mode == MPEG4_MODE)
+ {
+ /* Set up VOL header bitstream for frame-based decoding. 08/30/2000 */
+ BitstreamReset(stream, decCtrl->volbuf[idx], decCtrl->volbuf_size[idx]);
+
+ switch (DecodeVOLHeader(video, idx))
+ {
+ case PV_SUCCESS :
+ if (status == PV_TRUE)
+ status = PV_TRUE; /* we want to make sure that if first layer is bad, second layer is good return PV_FAIL */
+ else
+ status = PV_FALSE;
+ break;
+#ifdef PV_TOLERATE_VOL_ERRORS
+ case PV_BAD_VOLHEADER:
+ status = PV_TRUE;
+ break;
+#endif
+ default :
+ status = PV_FALSE;
+ break;
+ }
+
+ }
+ else
+ {
+ video->shortVideoHeader = PV_TRUE;
+ }
+
+ if (video->shortVideoHeader == PV_TRUE)
+ {
+ mode = H263_MODE;
+ /* Set max width and height. In H.263 mode, we use */
+ /* volbuf_size[0] to pass in width and volbuf_size[1] */
+ /* to pass in height. 04/23/2001 */
+ video->prevVop->temporalRef = 0; /* 11/12/01 */
+ /* Compute some convenience variables: 04/23/2001 */
+ video->vol[idx]->quantType = 0;
+ video->vol[idx]->quantPrecision = 5;
+ video->vol[idx]->errorResDisable = 1;
+ video->vol[idx]->dataPartitioning = 0;
+ video->vol[idx]->useReverseVLC = 0;
+ video->intra_acdcPredDisable = 1;
+ video->vol[idx]->scalability = 0;
+ video->size = (int32)width * height;
+
+ video->displayWidth = video->width = width;
+ video->displayHeight = video->height = height;
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ video->modified_quant = 0;
+ video->advanced_INTRA = 0;
+ video->deblocking = 0;
+ video->slice_structure = 0;
+#endif
+ }
+
+ }
+ }
+
+ }
+ if (status != PV_FALSE)
+ {
+ status = PVAllocVideoData(decCtrl, width, height, nLayers);
+ video->initialized = PV_TRUE;
+ }
+ }
+ else
+ {
+ status = PV_FALSE;
+ }
+
+ if (status == PV_FALSE) PVCleanUpVideoDecoder(decCtrl);
+
+ return status;
+}
+
+Bool PVAllocVideoData(VideoDecControls *decCtrl, int width, int height, int nLayers)
+{
+ VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
+ Bool status = PV_TRUE;
+ int nTotalMB;
+ int nMBPerRow;
+ int32 size;
+
+ if (video->shortVideoHeader == PV_TRUE)
+ {
+ video->displayWidth = video->width = width;
+ video->displayHeight = video->height = height;
+
+ video->nMBPerRow =
+ video->nMBinGOB = video->width / MB_SIZE;
+ video->nMBPerCol =
+ video->nGOBinVop = video->height / MB_SIZE;
+ video->nTotalMB =
+ video->nMBPerRow * video->nMBPerCol;
+ }
+
+ size = (int32)sizeof(PIXEL) * video->width * video->height;
+#ifdef PV_MEMORY_POOL
+ decCtrl->size = size;
+#else
+#ifdef DEC_INTERNAL_MEMORY_OPT
+ video->currVop->yChan = IMEM_currVop_yChan; /* Allocate memory for all VOP OKA 3/2/1*/
+ if (video->currVop->yChan == NULL) status = PV_FALSE;
+ video->currVop->uChan = video->currVop->yChan + size;
+ video->currVop->vChan = video->currVop->uChan + (size >> 2);
+
+ video->prevVop->yChan = IMEM_prevVop_yChan; /* Allocate memory for all VOP OKA 3/2/1*/
+ if (video->prevVop->yChan == NULL) status = PV_FALSE;
+ video->prevVop->uChan = video->prevVop->yChan + size;
+ video->prevVop->vChan = video->prevVop->uChan + (size >> 2);
+#else
+ video->currVop->yChan = (PIXEL *) oscl_malloc(size * 3 / 2); /* Allocate memory for all VOP OKA 3/2/1*/
+ if (video->currVop->yChan == NULL) status = PV_FALSE;
+
+ video->currVop->uChan = video->currVop->yChan + size;
+ video->currVop->vChan = video->currVop->uChan + (size >> 2);
+ video->prevVop->yChan = (PIXEL *) oscl_malloc(size * 3 / 2); /* Allocate memory for all VOP OKA 3/2/1*/
+ if (video->prevVop->yChan == NULL) status = PV_FALSE;
+
+ video->prevVop->uChan = video->prevVop->yChan + size;
+ video->prevVop->vChan = video->prevVop->uChan + (size >> 2);
+#endif
+ video->memoryUsage += (size * 3);
+#endif // MEMORY_POOL
+ /* Note that baseVop, enhcVop is only used to hold enhancement */
+ /* layer header information. 05/04/2000 */
+ if (nLayers > 1)
+ {
+ video->prevEnhcVop = (Vop *) oscl_malloc(sizeof(Vop));
+ video->memoryUsage += (sizeof(Vop));
+ if (video->prevEnhcVop == NULL)
+ {
+ status = PV_FALSE;
+ }
+ else
+ {
+ oscl_memset(video->prevEnhcVop, 0, sizeof(Vop));
+#ifndef PV_MEMORY_POOL
+ video->prevEnhcVop->yChan = (PIXEL *) oscl_malloc(size * 3 / 2); /* Allocate memory for all VOP OKA 3/2/1*/
+ if (video->prevEnhcVop->yChan == NULL) status = PV_FALSE;
+ video->prevEnhcVop->uChan = video->prevEnhcVop->yChan + size;
+ video->prevEnhcVop->vChan = video->prevEnhcVop->uChan + (size >> 2);
+ video->memoryUsage += (3 * size / 2);
+#endif
+ }
+ }
+
+ /* Allocating space for slices, AC prediction flag, and */
+ /* AC/DC prediction storage */
+ nTotalMB = video->nTotalMB;
+ nMBPerRow = video->nMBPerRow;
+
+#ifdef DEC_INTERNAL_MEMORY_OPT
+ video->sliceNo = (uint8 *)(IMEM_sliceNo);
+ if (video->sliceNo == NULL) status = PV_FALSE;
+ video->memoryUsage += nTotalMB;
+ video->acPredFlag = (uint8 *)(IMEM_acPredFlag);
+ if (video->acPredFlag == NULL) status = PV_FALSE;
+ video->memoryUsage += (nTotalMB);
+ video->predDC = (typeDCStore *)(IMEM_predDC);
+ if (video->predDC == NULL) status = PV_FALSE;
+ video->memoryUsage += (nTotalMB * sizeof(typeDCStore));
+ video->predDCAC_col = (typeDCACStore *)(IMEM_predDCAC_col);
+ if (video->predDCAC_col == NULL) status = PV_FALSE;
+ video->memoryUsage += ((nMBPerRow + 1) * sizeof(typeDCACStore));
+ video->predDCAC_row = video->predDCAC_col + 1;
+ video->headerInfo.Mode = (uint8 *)(IMEM_headerInfo_Mode);
+ if (video->headerInfo.Mode == NULL) status = PV_FALSE;
+ video->memoryUsage += nTotalMB;
+ video->headerInfo.CBP = (uint8 *)(IMEM_headerInfo_CBP);
+ if (video->headerInfo.CBP == NULL) status = PV_FALSE;
+ video->memoryUsage += nTotalMB;
+ video->QPMB = (int *)(IMEM_headerInfo_QPMB);
+ if (video->QPMB == NULL) status = PV_FALSE;
+ video->memoryUsage += (nTotalMB * sizeof(int));
+ video->mblock = &IMEM_mblock;
+ if (video->mblock == NULL) status = PV_FALSE;
+ oscl_memset(video->mblock->block, 0, sizeof(int16)*6*NCOEFF_BLOCK); // Aug 23,2005
+
+ video->memoryUsage += sizeof(MacroBlock);
+ video->motX = (MOT *)(IMEM_motX);
+ if (video->motX == NULL) status = PV_FALSE;
+ video->motY = (MOT *)(IMEM_motY);
+ if (video->motY == NULL) status = PV_FALSE;
+ video->memoryUsage += (sizeof(MOT) * 8 * nTotalMB);
+#else
+ video->sliceNo = (uint8 *) oscl_malloc(nTotalMB);
+ if (video->sliceNo == NULL) status = PV_FALSE;
+ video->memoryUsage += nTotalMB;
+
+ video->acPredFlag = (uint8 *) oscl_malloc(nTotalMB * sizeof(uint8));
+ if (video->acPredFlag == NULL) status = PV_FALSE;
+ video->memoryUsage += (nTotalMB);
+
+ video->predDC = (typeDCStore *) oscl_malloc(nTotalMB * sizeof(typeDCStore));
+ if (video->predDC == NULL) status = PV_FALSE;
+ video->memoryUsage += (nTotalMB * sizeof(typeDCStore));
+
+ video->predDCAC_col = (typeDCACStore *) oscl_malloc((nMBPerRow + 1) * sizeof(typeDCACStore));
+ if (video->predDCAC_col == NULL) status = PV_FALSE;
+ video->memoryUsage += ((nMBPerRow + 1) * sizeof(typeDCACStore));
+
+ /* 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 */
+
+ /* Allocating HeaderInfo structure & Quantizer array */
+ video->headerInfo.Mode = (uint8 *) oscl_malloc(nTotalMB);
+ if (video->headerInfo.Mode == NULL) status = PV_FALSE;
+ video->memoryUsage += nTotalMB;
+ video->headerInfo.CBP = (uint8 *) oscl_malloc(nTotalMB);
+ if (video->headerInfo.CBP == NULL) status = PV_FALSE;
+ video->memoryUsage += nTotalMB;
+ video->QPMB = (int16 *) oscl_malloc(nTotalMB * sizeof(int16));
+ if (video->QPMB == NULL) status = PV_FALSE;
+ video->memoryUsage += (nTotalMB * sizeof(int));
+
+ /* Allocating macroblock space */
+ video->mblock = (MacroBlock *) oscl_malloc(sizeof(MacroBlock));
+ if (video->mblock == NULL)
+ {
+ status = PV_FALSE;
+ }
+ else
+ {
+ oscl_memset(video->mblock->block, 0, sizeof(int16)*6*NCOEFF_BLOCK); // Aug 23,2005
+
+ video->memoryUsage += sizeof(MacroBlock);
+ }
+ /* Allocating motion vector space */
+ video->motX = (MOT *) oscl_malloc(sizeof(MOT) * 4 * nTotalMB);
+ if (video->motX == NULL) status = PV_FALSE;
+ video->motY = (MOT *) oscl_malloc(sizeof(MOT) * 4 * nTotalMB);
+ if (video->motY == NULL) status = PV_FALSE;
+ video->memoryUsage += (sizeof(MOT) * 8 * nTotalMB);
+#endif
+
+#ifdef PV_POSTPROC_ON
+ /* Allocating space for post-processing Mode */
+#ifdef DEC_INTERNAL_MEMORY_OPT
+ video->pstprcTypCur = IMEM_pstprcTypCur;
+ video->memoryUsage += (nTotalMB * 6);
+ if (video->pstprcTypCur == NULL)
+ {
+ status = PV_FALSE;
+ }
+ else
+ {
+ oscl_memset(video->pstprcTypCur, 0, 4*nTotalMB + 2*nTotalMB);
+ }
+
+ video->pstprcTypPrv = IMEM_pstprcTypPrv;
+ video->memoryUsage += (nTotalMB * 6);
+ if (video->pstprcTypPrv == NULL)
+ {
+ status = PV_FALSE;
+ }
+ else
+ {
+ oscl_memset(video->pstprcTypPrv, 0, nTotalMB*6);
+ }
+
+#else
+ video->pstprcTypCur = (uint8 *) oscl_malloc(nTotalMB * 6);
+ video->memoryUsage += (nTotalMB * 6);
+ if (video->pstprcTypCur == NULL)
+ {
+ status = PV_FALSE;
+ }
+ else
+ {
+ oscl_memset(video->pstprcTypCur, 0, 4*nTotalMB + 2*nTotalMB);
+ }
+
+ video->pstprcTypPrv = (uint8 *) oscl_malloc(nTotalMB * 6);
+ video->memoryUsage += (nTotalMB * 6);
+ if (video->pstprcTypPrv == NULL)
+ {
+ status = PV_FALSE;
+ }
+ else
+ {
+ oscl_memset(video->pstprcTypPrv, 0, nTotalMB*6);
+ }
+
+#endif
+
+#endif
+
+ /* initialize the decoder library */
+ video->prevVop->predictionType = I_VOP;
+ video->prevVop->timeStamp = 0;
+#ifndef PV_MEMORY_POOL
+ oscl_memset(video->prevVop->yChan, 16, sizeof(uint8)*size); /* 10/31/01 */
+ oscl_memset(video->prevVop->uChan, 128, sizeof(uint8)*size / 2);
+
+ oscl_memset(video->currVop->yChan, 0, sizeof(uint8)*size*3 / 2);
+ if (nLayers > 1)
+ {
+ oscl_memset(video->prevEnhcVop->yChan, 0, sizeof(uint8)*size*3 / 2);
+ video->prevEnhcVop->timeStamp = 0;
+ }
+ video->concealFrame = video->prevVop->yChan; /* 07/07/2001 */
+ decCtrl->outputFrame = video->prevVop->yChan; /* 06/19/2002 */
+#endif
+
+ /* always start from base layer */
+ video->currLayer = 0;
+ return status;
+}
+
+/* ======================================================================== */
+/* Function : PVResetVideoDecoder() */
+/* Date : 01/14/2002 */
+/* Purpose : Reset video timestamps */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* ======================================================================== */
+Bool PVResetVideoDecoder(VideoDecControls *decCtrl)
+{
+ VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
+ int idx;
+
+ for (idx = 0; idx < decCtrl->nLayers; idx++)
+ {
+ video->vopHeader[idx]->timeStamp = 0;
+ }
+ video->prevVop->timeStamp = 0;
+ if (decCtrl->nLayers > 1)
+ video->prevEnhcVop->timeStamp = 0;
+
+ oscl_memset(video->mblock->block, 0, sizeof(int16)*6*NCOEFF_BLOCK); // Aug 23,2005
+
+ return PV_TRUE;
+}
+
+
+/* ======================================================================== */
+/* Function : PVCleanUpVideoDecoder() */
+/* Date : 04/11/2000, 08/29/2000 */
+/* Purpose : Cleanup of the MPEG-4 video decoder library. */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVCleanUpVideoDecoder(VideoDecControls *decCtrl)
+{
+ int idx;
+ VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
+#ifdef DEC_INTERNAL_MEMORY_OPT
+ if (video)
+ {
+#ifdef PV_POSTPROC_ON
+ video->pstprcTypCur = NULL;
+ video->pstprcTypPrv = NULL;
+#endif
+
+ video->acPredFlag = NULL;
+ video->sliceNo = NULL;
+ video->motX = NULL;
+ video->motY = NULL;
+ video->mblock = NULL;
+ video->QPMB = NULL;
+ video->predDC = NULL;
+ video->predDCAC_row = NULL;
+ video->predDCAC_col = NULL;
+ video->headerInfo.Mode = NULL;
+ video->headerInfo.CBP = NULL;
+ if (video->numberOfLayers > 1)
+ {
+ if (video->prevEnhcVop)
+ {
+ video->prevEnhcVop->uChan = NULL;
+ video->prevEnhcVop->vChan = NULL;
+ if (video->prevEnhcVop->yChan) oscl_free(video->prevEnhcVop->yChan);
+ oscl_free(video->prevEnhcVop);
+ }
+ }
+ if (video->currVop)
+ {
+ video->currVop->uChan = NULL;
+ video->currVop->vChan = NULL;
+ if (video->currVop->yChan)
+ video->currVop->yChan = NULL;
+ video->currVop = NULL;
+ }
+ if (video->prevVop)
+ {
+ video->prevVop->uChan = NULL;
+ video->prevVop->vChan = NULL;
+ if (video->prevVop->yChan)
+ video->prevVop->yChan = NULL;
+ video->prevVop = NULL;
+ }
+
+ if (video->vol)
+ {
+ for (idx = 0; idx < video->numberOfLayers; idx++)
+ {
+ if (video->vol[idx])
+ {
+ BitstreamClose(video->vol[idx]->bitstream);
+ video->vol[idx]->bitstream = NULL;
+ video->vol[idx] = NULL;
+ }
+ video->vopHeader[idx] = NULL;
+
+ }
+ video->vol = NULL;
+ video->vopHeader = NULL;
+ }
+
+ video = NULL;
+ decCtrl->videoDecoderData = NULL;
+ }
+
+#else
+
+ if (video)
+ {
+#ifdef PV_POSTPROC_ON
+ if (video->pstprcTypCur) oscl_free(video->pstprcTypCur);
+ if (video->pstprcTypPrv) oscl_free(video->pstprcTypPrv);
+#endif
+ if (video->predDC) oscl_free(video->predDC);
+ video->predDCAC_row = NULL;
+ if (video->predDCAC_col) oscl_free(video->predDCAC_col);
+ if (video->motX) oscl_free(video->motX);
+ if (video->motY) oscl_free(video->motY);
+ if (video->mblock) oscl_free(video->mblock);
+ if (video->QPMB) oscl_free(video->QPMB);
+ if (video->headerInfo.Mode) oscl_free(video->headerInfo.Mode);
+ if (video->headerInfo.CBP) oscl_free(video->headerInfo.CBP);
+ if (video->sliceNo) oscl_free(video->sliceNo);
+ if (video->acPredFlag) oscl_free(video->acPredFlag);
+
+ if (video->numberOfLayers > 1)
+ {
+ if (video->prevEnhcVop)
+ {
+ video->prevEnhcVop->uChan = NULL;
+ video->prevEnhcVop->vChan = NULL;
+ if (video->prevEnhcVop->yChan) oscl_free(video->prevEnhcVop->yChan);
+ oscl_free(video->prevEnhcVop);
+ }
+ }
+ if (video->currVop)
+ {
+
+#ifndef PV_MEMORY_POOL
+ video->currVop->uChan = NULL;
+ video->currVop->vChan = NULL;
+ if (video->currVop->yChan)
+ oscl_free(video->currVop->yChan);
+#endif
+ oscl_free(video->currVop);
+ }
+ if (video->prevVop)
+ {
+#ifndef PV_MEMORY_POOL
+ video->prevVop->uChan = NULL;
+ video->prevVop->vChan = NULL;
+ if (video->prevVop->yChan)
+ oscl_free(video->prevVop->yChan);
+#endif
+ oscl_free(video->prevVop);
+ }
+
+ if (video->vol)
+ {
+ for (idx = 0; idx < video->numberOfLayers; idx++)
+ {
+ if (video->vol[idx])
+ {
+ if (video->vol[idx]->bitstream)
+ {
+ BitstreamClose(video->vol[idx]->bitstream);
+ oscl_free(video->vol[idx]->bitstream);
+ }
+ oscl_free(video->vol[idx]);
+ }
+
+ }
+ oscl_free(video->vol);
+ }
+
+ for (idx = 0; idx < video->numberOfLayers; idx++)
+ {
+ if (video->vopHeader[idx]) oscl_free(video->vopHeader[idx]);
+ }
+
+ if (video->vopHeader) oscl_free(video->vopHeader);
+
+ oscl_free(video);
+ decCtrl->videoDecoderData = NULL;
+ }
+#endif
+ return PV_TRUE;
+}
+/* ======================================================================== */
+/* Function : PVGetVideoDimensions() */
+/* Date : 040505 */
+/* Purpose : */
+/* In/out : */
+/* Return : the display_width and display_height of */
+/* the frame in the current layer. */
+/* Note : This is not a macro or inline function because we do */
+/* not want to expose our internal data structure. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF void PVGetVideoDimensions(VideoDecControls *decCtrl, int32 *display_width, int32 *display_height)
+{
+ VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
+ *display_width = video->displayWidth;
+ *display_height = video->displayHeight;
+}
+
+OSCL_EXPORT_REF void PVGetBufferDimensions(VideoDecControls *decCtrl, int32 *width, int32 *height) {
+ VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
+ *width = video->width;
+ *height = video->height;
+}
+
+/* ======================================================================== */
+/* Function : PVGetVideoTimeStamp() */
+/* Date : 04/27/2000, 08/29/2000 */
+/* Purpose : */
+/* In/out : */
+/* Return : current time stamp in millisecond. */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+uint32 PVGetVideoTimeStamp(VideoDecControls *decCtrl)
+{
+ VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
+ return video->currTimestamp;
+}
+
+
+/* ======================================================================== */
+/* Function : PVSetPostProcType() */
+/* Date : 07/07/2000 */
+/* Purpose : */
+/* In/out : */
+/* Return : Set post-processing filter type. */
+/* Note : */
+/* Modified : . 08/29/2000 changes the name for consistency. */
+/* ======================================================================== */
+OSCL_EXPORT_REF void PVSetPostProcType(VideoDecControls *decCtrl, int mode)
+{
+ VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
+ video->postFilterType = mode;
+}
+
+
+/* ======================================================================== */
+/* Function : PVGetDecBitrate() */
+/* Date : 08/23/2000 */
+/* Purpose : */
+/* In/out : */
+/* Return : This function returns the average bits per second. */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+int PVGetDecBitrate(VideoDecControls *decCtrl)
+{
+ VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
+ int idx;
+ int32 sum = 0;
+
+ for (idx = 0; idx < BITRATE_AVERAGE_WINDOW; idx++)
+ {
+ sum += video->nBitsPerVop[idx];
+ }
+ sum = (sum * video->frameRate) / (10 * BITRATE_AVERAGE_WINDOW);
+ return (int) sum;
+}
+
+
+/* ======================================================================== */
+/* Function : PVGetDecFramerate() */
+/* Date : 08/23/2000 */
+/* Purpose : */
+/* In/out : */
+/* Return : This function returns the average frame per 10 second. */
+/* Note : The fps can be calculated by PVGetDecFramerate()/10 */
+/* Modified : */
+/* ======================================================================== */
+int PVGetDecFramerate(VideoDecControls *decCtrl)
+{
+ VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
+
+ return video->frameRate;
+}
+
+/* ======================================================================== */
+/* Function : PVGetOutputFrame() */
+/* Date : 05/07/2001 */
+/* Purpose : */
+/* In/out : */
+/* Return : This function returns the pointer to the output frame */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+uint8 *PVGetDecOutputFrame(VideoDecControls *decCtrl)
+{
+ return decCtrl->outputFrame;
+}
+
+/* ======================================================================== */
+/* Function : PVGetLayerID() */
+/* Date : 07/09/2001 */
+/* Purpose : */
+/* In/out : */
+/* Return : This function returns decoded frame layer id (BASE/ENHANCE) */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+int PVGetLayerID(VideoDecControls *decCtrl)
+{
+ VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
+ return video->currLayer;
+}
+/* ======================================================================== */
+/* Function : PVGetDecMemoryUsage() */
+/* Date : 08/23/2000 */
+/* Purpose : */
+/* In/out : */
+/* Return : This function returns the amount of memory used. */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+int32 PVGetDecMemoryUsage(VideoDecControls *decCtrl)
+{
+ VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
+ return video->memoryUsage;
+}
+
+
+/* ======================================================================== */
+/* Function : PVGetDecBitstreamMode() */
+/* Date : 08/23/2000 */
+/* Purpose : */
+/* In/out : */
+/* Return : This function returns the decoding mode of the baselayer */
+/* bitstream. */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF MP4DecodingMode PVGetDecBitstreamMode(VideoDecControls *decCtrl)
+{
+ VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
+ if (video->shortVideoHeader)
+ {
+ return H263_MODE;
+ }
+ else
+ {
+ return MPEG4_MODE;
+ }
+}
+
+
+/* ======================================================================== */
+/* Function : PVExtractVolHeader() */
+/* Date : 08/29/2000 */
+/* Purpose : */
+/* In/out : */
+/* Return : Extract vol header of the bitstream from buffer[]. */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+Bool PVExtractVolHeader(uint8 *video_buffer, uint8 *vol_header, int32 *vol_header_size)
+{
+ int idx = -1;
+ uint8 start_code_prefix[] = { 0x00, 0x00, 0x01 };
+ uint8 h263_prefix[] = { 0x00, 0x00, 0x80 };
+
+ if (oscl_memcmp(h263_prefix, video_buffer, 3) == 0) /* we have short header stream */
+ {
+ oscl_memcpy(vol_header, video_buffer, 32);
+ *vol_header_size = 32;
+ return TRUE;
+ }
+ else
+ {
+ if (oscl_memcmp(start_code_prefix, video_buffer, 3) ||
+ (video_buffer[3] != 0xb0 && video_buffer[3] >= 0x20)) return FALSE;
+
+ do
+ {
+ idx++;
+ while (oscl_memcmp(start_code_prefix, video_buffer + idx, 3))
+ {
+ idx++;
+ if (idx + 3 >= *vol_header_size) goto quit;
+ }
+ }
+ while (video_buffer[idx+3] != 0xb3 && video_buffer[idx+3] != 0xb6);
+
+ oscl_memcpy(vol_header, video_buffer, idx);
+ *vol_header_size = idx;
+ return TRUE;
+ }
+
+quit:
+ oscl_memcpy(vol_header, video_buffer, *vol_header_size);
+ return FALSE;
+}
+
+
+/* ======================================================================== */
+/* Function : PVLocateFrameHeader() */
+/* Date : 04/8/2005 */
+/* Purpose : */
+/* In/out : */
+/* Return : Return the offset to the first SC in the buffer */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+int32 PVLocateFrameHeader(uint8 *ptr, int32 size)
+{
+ int count = 0;
+ int32 i = size;
+
+ if (size < 1)
+ {
+ return 0;
+ }
+ while (i--)
+ {
+ if ((count > 1) && (*ptr == 0x01))
+ {
+ i += 2;
+ break;
+ }
+
+ if (*ptr++)
+ count = 0;
+ else
+ count++;
+ }
+ return (size - (i + 1));
+}
+
+
+/* ======================================================================== */
+/* Function : PVLocateH263FrameHeader() */
+/* Date : 04/8/2005 */
+/* Purpose : */
+/* In/out : */
+/* Return : Return the offset to the first SC in the buffer */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+int32 PVLocateH263FrameHeader(uint8 *ptr, int32 size)
+{
+ int count = 0;
+ int32 i = size;
+
+ if (size < 1)
+ {
+ return 0;
+ }
+
+ while (i--)
+ {
+ if ((count > 1) && ((*ptr & 0xFC) == 0x80))
+ {
+ i += 2;
+ break;
+ }
+
+ if (*ptr++)
+ count = 0;
+ else
+ count++;
+ }
+ return (size - (i + 1));
+}
+
+
+/* ======================================================================== */
+/* Function : PVDecodeVideoFrame() */
+/* Date : 08/29/2000 */
+/* Purpose : Decode one video frame and return a YUV-12 image. */
+/* In/out : */
+/* Return : */
+/* Note : */
+/* Modified : 04/17/2001 removed PV_EOS, PV_END_OF_BUFFER */
+/* : 08/22/2002 break up into 2 functions PVDecodeVopHeader and */
+/* PVDecodeVopBody */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVDecodeVideoFrame(VideoDecControls *decCtrl, uint8 *buffer[],
+ uint32 timestamp[], int32 buffer_size[], uint use_ext_timestamp[], uint8 *currYUV)
+{
+ PV_STATUS status = PV_FAIL;
+ VopHeaderInfo header_info;
+
+ status = (PV_STATUS)PVDecodeVopHeader(decCtrl, buffer, timestamp, buffer_size, &header_info, use_ext_timestamp, currYUV);
+ if (status != PV_TRUE)
+ return PV_FALSE;
+
+ if (PVDecodeVopBody(decCtrl, buffer_size) != PV_TRUE)
+ {
+ return PV_FALSE;
+ }
+
+ return PV_TRUE;
+}
+
+/* ======================================================================== */
+/* Function : PVDecodeVopHeader() */
+/* Date : 08/22/2002 */
+/* Purpose : Determine target layer and decode vop header, modified from */
+/* original PVDecodeVideoFrame. */
+/* In/out : */
+/* Return : */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+Bool PVDecodeVopHeader(VideoDecControls *decCtrl, uint8 *buffer[],
+ uint32 timestamp[], int32 buffer_size[], VopHeaderInfo *header_info, uint use_ext_timestamp [], uint8 *currYUV)
+{
+ VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
+ Vol *currVol;
+ Vop *currVop = video->currVop;
+ Vop **vopHeader = video->vopHeader;
+ BitstreamDecVideo *stream;
+
+ int target_layer;
+
+#ifdef PV_SUPPORT_TEMPORAL_SCALABILITY
+ PV_STATUS status = PV_FAIL;
+ int idx;
+ int32 display_time;
+
+ /* decide which frame to decode next */
+ if (decCtrl->nLayers > 1)
+ {
+ display_time = target_layer = -1;
+ for (idx = 0; idx < decCtrl->nLayers; idx++)
+ {
+ /* do we have data for this layer? */
+ if (buffer_size[idx] <= 0)
+ {
+ timestamp[idx] = -1;
+ continue;
+ }
+
+ /* did the application provide a timestamp for this vop? */
+ if (timestamp[idx] < 0)
+ {
+ if (vopHeader[idx]->timeStamp < 0)
+ {
+ /* decode the timestamp in the bitstream */
+ video->currLayer = idx;
+ stream = video->vol[idx]->bitstream;
+ BitstreamReset(stream, buffer[idx], buffer_size[idx]);
+
+ while ((status = DecodeVOPHeader(video, vopHeader[idx], FALSE)) != PV_SUCCESS)
+ {
+ /* Try to find a VOP header in the buffer. 08/30/2000. */
+ if (PVSearchNextM4VFrame(stream) != PV_SUCCESS)
+ {
+ /* if we don't have data for enhancement layer, */
+ /* don't just stop. 09/07/2000. */
+ buffer_size[idx] = 0;
+ break;
+ }
+ }
+ if (status == PV_SUCCESS)
+ {
+ vopHeader[idx]->timeStamp =
+ timestamp[idx] = CalcVopDisplayTime(video->vol[idx], vopHeader[idx], video->shortVideoHeader);
+ if (idx == 0) vopHeader[idx]->refSelectCode = 1;
+ }
+ }
+ else
+ {
+ /* We've decoded this vop header in the previous run already. */
+ timestamp[idx] = vopHeader[idx]->timeStamp;
+ }
+ }
+
+ /* Use timestamps to select the next VOP to be decoded */
+ if (timestamp[idx] >= 0 && (display_time < 0 || display_time > timestamp[idx]))
+ {
+ display_time = timestamp[idx];
+ target_layer = idx;
+ }
+ else if (display_time == timestamp[idx])
+ {
+ /* we have to handle either SNR or spatial scalability here. */
+ }
+ }
+ if (target_layer < 0) return PV_FALSE;
+
+ /* set up for decoding the target layer */
+ video->currLayer = target_layer;
+ currVol = video->vol[target_layer];
+ video->bitstream = stream = currVol->bitstream;
+
+ /* We need to decode the vop header if external timestamp */
+ /* is provided. 10/04/2000 */
+ if (vopHeader[target_layer]->timeStamp < 0)
+ {
+ stream = video->vol[target_layer]->bitstream;
+ BitstreamReset(stream, buffer[target_layer], buffer_size[target_layer]);
+
+ while (DecodeVOPHeader(video, vopHeader[target_layer], TRUE) != PV_SUCCESS)
+ {
+ /* Try to find a VOP header in the buffer. 08/30/2000. */
+ if (PVSearchNextM4VFrame(stream) != PV_SUCCESS)
+ {
+ /* if we don't have data for enhancement layer, */
+ /* don't just stop. 09/07/2000. */
+ buffer_size[target_layer] = 0;
+ break;
+ }
+ }
+ video->vol[target_layer]->timeInc_offset = vopHeader[target_layer]->timeInc;
+ video->vol[target_layer]->moduloTimeBase = timestamp[target_layer];
+ vopHeader[target_layer]->timeStamp = timestamp[target_layer];
+ if (target_layer == 0) vopHeader[target_layer]->refSelectCode = 1;
+ }
+ }
+ else /* base layer only decoding */
+ {
+#endif
+ video->currLayer = target_layer = 0;
+ currVol = video->vol[0];
+ video->bitstream = stream = currVol->bitstream;
+ if (buffer_size[0] <= 0) return PV_FALSE;
+ BitstreamReset(stream, buffer[0], buffer_size[0]);
+
+ if (video->shortVideoHeader)
+ {
+ while (DecodeShortHeader(video, vopHeader[0]) != PV_SUCCESS)
+ {
+ if (PVSearchNextH263Frame(stream) != PV_SUCCESS)
+ {
+ /* There is no vop header in the buffer, */
+ /* clean bitstream buffer. 2/5/2001 */
+ buffer_size[0] = 0;
+ if (video->initialized == PV_FALSE)
+ {
+ video->displayWidth = video->width = 0;
+ video->displayHeight = video->height = 0;
+ }
+ return PV_FALSE;
+ }
+ }
+
+ if (use_ext_timestamp[0])
+ {
+ /* MTB for H263 is absolute TR */
+ /* following line is equivalent to round((timestamp[0]*30)/1001); 11/13/2001 */
+ video->vol[0]->moduloTimeBase = 30 * ((timestamp[0] + 17) / 1001) + (30 * ((timestamp[0] + 17) % 1001) / 1001);
+ vopHeader[0]->timeStamp = timestamp[0];
+ }
+ else
+ vopHeader[0]->timeStamp = CalcVopDisplayTime(currVol, vopHeader[0], video->shortVideoHeader);
+ }
+ else
+ {
+ while (DecodeVOPHeader(video, vopHeader[0], FALSE) != PV_SUCCESS)
+ {
+ /* Try to find a VOP header in the buffer. 08/30/2000. */
+ if (PVSearchNextM4VFrame(stream) != PV_SUCCESS)
+ {
+ /* There is no vop header in the buffer, */
+ /* clean bitstream buffer. 2/5/2001 */
+ buffer_size[0] = 0;
+ return PV_FALSE;
+ }
+ }
+
+ if (use_ext_timestamp[0])
+ {
+ video->vol[0]->timeInc_offset = vopHeader[0]->timeInc;
+ video->vol[0]->moduloTimeBase = timestamp[0]; /* 11/12/2001 */
+ vopHeader[0]->timeStamp = timestamp[0];
+ }
+ else
+ {
+ vopHeader[0]->timeStamp = CalcVopDisplayTime(currVol, vopHeader[0], video->shortVideoHeader);
+ }
+ }
+
+ /* set up some base-layer only parameters */
+ vopHeader[0]->refSelectCode = 1;
+#ifdef PV_SUPPORT_TEMPORAL_SCALABILITY
+ }
+#endif
+ timestamp[target_layer] = video->currTimestamp = vopHeader[target_layer]->timeStamp;
+#ifdef PV_MEMORY_POOL
+ vopHeader[target_layer]->yChan = (PIXEL *)currYUV;
+ vopHeader[target_layer]->uChan = (PIXEL *)currYUV + decCtrl->size;
+ vopHeader[target_layer]->vChan = (PIXEL *)(vopHeader[target_layer]->uChan) + (decCtrl->size >> 2);
+#else
+ vopHeader[target_layer]->yChan = currVop->yChan;
+ vopHeader[target_layer]->uChan = currVop->uChan;
+ vopHeader[target_layer]->vChan = currVop->vChan;
+#endif
+ oscl_memcpy(currVop, vopHeader[target_layer], sizeof(Vop));
+
+#ifdef PV_SUPPORT_TEMPORAL_SCALABILITY
+ vopHeader[target_layer]->timeStamp = -1;
+#endif
+ /* put header info into the structure */
+ header_info->currLayer = target_layer;
+ header_info->timestamp = video->currTimestamp;
+ header_info->frameType = (MP4FrameType)currVop->predictionType;
+ header_info->refSelCode = vopHeader[target_layer]->refSelectCode;
+ header_info->quantizer = currVop->quantizer;
+ /***************************************/
+
+ return PV_TRUE;
+}
+
+
+/* ======================================================================== */
+/* Function : PVDecodeVopBody() */
+/* Date : 08/22/2002 */
+/* Purpose : Decode vop body after the header is decoded, modified from */
+/* original PVDecodeVideoFrame. */
+/* In/out : */
+/* Return : */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+Bool PVDecodeVopBody(VideoDecControls *decCtrl, int32 buffer_size[])
+{
+ PV_STATUS status = PV_FAIL;
+ VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
+ int target_layer = video->currLayer;
+ Vol *currVol = video->vol[target_layer];
+ Vop *currVop = video->currVop;
+ Vop *prevVop = video->prevVop;
+ Vop *tempVopPtr;
+ int bytes_consumed = 0; /* Record how many bits we used in the buffer. 04/24/2001 */
+
+ int idx;
+
+ if (currVop->vopCoded == 0) /* 07/03/2001 */
+ {
+ PV_BitstreamByteAlign(currVol->bitstream);
+ /* We should always clear up bitstream buffer. 10/10/2000 */
+ bytes_consumed = (getPointer(currVol->bitstream) + 7) >> 3;
+
+ if (bytes_consumed > currVol->bitstream->data_end_pos)
+ {
+ bytes_consumed = currVol->bitstream->data_end_pos;
+ }
+
+ if (bytes_consumed < buffer_size[target_layer])
+ {
+ /* If we only consume part of the bits in the buffer, take those */
+ /* out. 04/24/2001 */
+ /* oscl_memcpy(buffer[target_layer], buffer[target_layer]+bytes_consumed,
+ (buffer_size[target_layer]-=bytes_consumed)); */
+ buffer_size[target_layer] -= bytes_consumed;
+ }
+ else
+ {
+ buffer_size[target_layer] = 0;
+ }
+#ifdef PV_MEMORY_POOL
+
+ if (target_layer)
+ {
+ if (video->prevEnhcVop->timeStamp > video->prevVop->timeStamp)
+ {
+ video->prevVop = video->prevEnhcVop;
+ }
+ }
+
+ oscl_memcpy(currVop->yChan, video->prevVop->yChan, (decCtrl->size*3) / 2);
+
+ video->prevVop = prevVop;
+
+ video->concealFrame = currVop->yChan; /* 07/07/2001 */
+
+ video->vop_coding_type = currVop->predictionType; /* 07/09/01 */
+
+ decCtrl->outputFrame = currVop->yChan;
+
+ /* Swap VOP pointers. No enhc. frame oscl_memcpy() anymore! 04/24/2001 */
+ if (target_layer)
+ {
+ tempVopPtr = video->prevEnhcVop;
+ video->prevEnhcVop = video->currVop;
+ video->currVop = tempVopPtr;
+ }
+ else
+ {
+ tempVopPtr = video->prevVop;
+ video->prevVop = video->currVop;
+ video->currVop = tempVopPtr;
+ }
+#else
+ if (target_layer) /* this is necessary to avoid flashback problems 06/21/2002*/
+ {
+ video->prevEnhcVop->timeStamp = currVop->timeStamp;
+ }
+ else
+ {
+ video->prevVop->timeStamp = currVop->timeStamp;
+ }
+#endif
+ video->vop_coding_type = currVop->predictionType; /* 07/09/01 */
+ /* the following is necessary to avoid displaying an notCoded I-VOP at the beginning of a session
+ or after random positioning 07/03/02*/
+ if (currVop->predictionType == I_VOP)
+ {
+ video->vop_coding_type = P_VOP;
+ }
+
+
+ return PV_TRUE;
+ }
+ /* ======================================================= */
+ /* Decode vop body (if there is no error in the header!) */
+ /* ======================================================= */
+
+ /* first, we need to select a reference frame */
+ if (decCtrl->nLayers > 1)
+ {
+ if (currVop->predictionType == I_VOP)
+ {
+ /* do nothing here */
+ }
+ else if (currVop->predictionType == P_VOP)
+ {
+ switch (currVop->refSelectCode)
+ {
+ case 0 : /* most recently decoded enhancement vop */
+ /* Setup video->prevVop before we call PV_DecodeVop(). 04/24/2001 */
+ if (video->prevEnhcVop->timeStamp >= video->prevVop->timeStamp)
+ video->prevVop = video->prevEnhcVop;
+ break;
+
+ case 1 : /* most recently displayed base-layer vop */
+ if (target_layer)
+ {
+ if (video->prevEnhcVop->timeStamp > video->prevVop->timeStamp)
+ video->prevVop = video->prevEnhcVop;
+ }
+ break;
+
+ case 2 : /* next base-layer vop in display order */
+ break;
+
+ case 3 : /* temporally coincident base-layer vop (no MV's) */
+ break;
+ }
+ }
+ else /* we have a B-Vop */
+ {
+ mp4dec_log("DecodeVideoFrame(): B-VOP not supported.\n");
+ }
+ }
+
+ /* This is for the calculation of the frame rate and bitrate. */
+ idx = ++video->frame_idx % BITRATE_AVERAGE_WINDOW;
+
+ /* Calculate bitrate for this layer. 08/23/2000 */
+ status = PV_DecodeVop(video);
+ video->nBitsPerVop[idx] = getPointer(currVol->bitstream);
+ video->prevTimestamp[idx] = currVop->timeStamp;
+
+ /* restore video->prevVop after PV_DecodeVop(). 04/24/2001 */
+// if (currVop->refSelectCode == 0) video->prevVop = prevVop;
+ video->prevVop = prevVop;
+
+ /* Estimate the frame rate. 08/23/2000 */
+ video->duration = video->prevTimestamp[idx];
+ video->duration -= video->prevTimestamp[(++idx)%BITRATE_AVERAGE_WINDOW];
+ if (video->duration > 0)
+ { /* Only update framerate when the timestamp is right */
+ video->frameRate = (int)(FRAMERATE_SCALE) / video->duration;
+ }
+
+ /* We should always clear up bitstream buffer. 10/10/2000 */
+ bytes_consumed = (getPointer(currVol->bitstream) + 7) >> 3; /* 11/4/03 */
+
+ if (bytes_consumed > currVol->bitstream->data_end_pos)
+ {
+ bytes_consumed = currVol->bitstream->data_end_pos;
+ }
+
+ if (bytes_consumed < buffer_size[target_layer])
+ {
+ /* If we only consume part of the bits in the buffer, take those */
+ /* out. 04/24/2001 */
+ /* oscl_memcpy(buffer[target_layer], buffer[target_layer]+bytes_consumed,
+ (buffer_size[target_layer]-=bytes_consumed)); */
+ buffer_size[target_layer] -= bytes_consumed;
+ }
+ else
+ {
+ buffer_size[target_layer] = 0;
+ }
+ switch (status)
+ {
+ case PV_FAIL :
+ return PV_FALSE; /* this will take care of concealment if we lose whole frame */
+
+ case PV_END_OF_VOP :
+ /* we may want to differenciate PV_END_OF_VOP and PV_SUCCESS */
+ /* in the future. 05/10/2000 */
+
+ case PV_SUCCESS :
+ /* Nohting is wrong :). */
+
+
+ video->concealFrame = video->currVop->yChan; /* 07/07/2001 */
+
+ video->vop_coding_type = video->currVop->predictionType; /* 07/09/01 */
+
+ decCtrl->outputFrame = video->currVop->yChan;
+
+ /* Swap VOP pointers. No enhc. frame oscl_memcpy() anymore! 04/24/2001 */
+ if (target_layer)
+ {
+ tempVopPtr = video->prevEnhcVop;
+ video->prevEnhcVop = video->currVop;
+ video->currVop = tempVopPtr;
+ }
+ else
+ {
+ tempVopPtr = video->prevVop;
+ video->prevVop = video->currVop;
+ video->currVop = tempVopPtr;
+ }
+ break;
+
+ default :
+ /* This will never happen */
+ break;
+ }
+
+ return PV_TRUE;
+}
+
+#ifdef PV_MEMORY_POOL
+OSCL_EXPORT_REF void PVSetReferenceYUV(VideoDecControls *decCtrl, uint8 *YUV)
+{
+ VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
+ video->prevVop->yChan = (PIXEL *)YUV;
+ video->prevVop->uChan = (PIXEL *)YUV + video->size;
+ video->prevVop->vChan = (PIXEL *)video->prevVop->uChan + (decCtrl->size >> 2);
+ oscl_memset(video->prevVop->yChan, 16, sizeof(uint8)*decCtrl->size); /* 10/31/01 */
+ oscl_memset(video->prevVop->uChan, 128, sizeof(uint8)*decCtrl->size / 2);
+ video->concealFrame = video->prevVop->yChan; /* 07/07/2001 */
+ decCtrl->outputFrame = video->prevVop->yChan; /* 06/19/2002 */
+}
+#endif
+
+
+/* ======================================================================== */
+/* Function : VideoDecoderErrorDetected() */
+/* Date : 06/20/2000 */
+/* Purpose : */
+/* In/out : */
+/* Return : This function will be called everytime an error int the */
+/* bitstream is detected. */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+uint VideoDecoderErrorDetected(VideoDecData *)
+{
+ /* This is only used for trapping bitstream error for debuging */
+ return 0;
+}
+
+#ifdef ENABLE_LOG
+#include <stdio.h>
+#include <stdarg.h>
+/* ======================================================================== */
+/* Function : m4vdec_dprintf() */
+/* Date : 08/15/2000 */
+/* Purpose : This is a function that logs messages in the mpeg4 video */
+/* decoder. We can call the standard PacketVideo PVMessage */
+/* from inside this function if necessary. */
+/* In/out : */
+/* Return : */
+/* Note : To turn on the logging, LOG_MP4DEC_MESSAGE must be defined */
+/* when compiling this file (only this file). */
+/* Modified : */
+/* ======================================================================== */
+void m4vdec_dprintf(char *format, ...)
+{
+ FILE *log_fp;
+ va_list args;
+ va_start(args, format);
+
+ /* open the log file */
+ log_fp = fopen("\\mp4dec_log.txt", "a+");
+ if (log_fp == NULL) return;
+ /* output the message */
+ vfprintf(log_fp, format, args);
+ fclose(log_fp);
+
+ va_end(args);
+}
+#endif
+
+
+/* ======================================================================== */
+/* Function : IsIntraFrame() */
+/* Date : 05/29/2000 */
+/* Purpose : */
+/* In/out : */
+/* Return : The most recently decoded frame is an Intra frame. */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+Bool IsIntraFrame(VideoDecControls *decCtrl)
+{
+ VideoDecData *video = (VideoDecData *)decCtrl->videoDecoderData;
+ return (video->vop_coding_type == I_VOP);
+}
+
+/* ======================================================================== */
+/* Function : PVDecPostProcess() */
+/* Date : 01/09/2002 */
+/* Purpose : PostProcess one video frame and return a YUV-12 image. */
+/* In/out : */
+/* Return : */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+void PVDecPostProcess(VideoDecControls *decCtrl, uint8 *outputYUV)
+{
+ uint8 *outputBuffer;
+#ifdef PV_POSTPROC_ON
+ VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
+ int32 tmpvar;
+ if (outputYUV)
+ {
+ outputBuffer = outputYUV;
+ }
+ else
+ {
+ if (video->postFilterType)
+ {
+ outputBuffer = video->currVop->yChan;
+ }
+ else
+ {
+ outputBuffer = decCtrl->outputFrame;
+ }
+ }
+
+ if (video->postFilterType)
+ {
+ /* Post-processing, */
+ PostFilter(video, video->postFilterType, outputBuffer);
+ }
+ else
+ {
+ if (outputYUV)
+ {
+ /* Copy decoded frame to the output buffer. */
+ tmpvar = (int32)video->width * video->height;
+ oscl_memcpy(outputBuffer, decCtrl->outputFrame, tmpvar*3 / 2); /* 3/3/01 */
+ }
+ }
+#else
+ outputBuffer = decCtrl->outputFrame;
+ outputYUV;
+#endif
+ decCtrl->outputFrame = outputBuffer;
+ return;
+}
+
+
+/* ======================================================================== */
+/* Function : PVDecSetReference(VideoDecControls *decCtrl, uint8 *refYUV, */
+/* int32 timestamp) */
+/* Date : 07/22/2003 */
+/* Purpose : Get YUV reference frame from external source. */
+/* In/out : YUV 4-2-0 frame containing new reference frame in the same */
+/* : dimension as original, i.e., doesn't have to be multiple of 16 !!!. */
+/* Return : */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+Bool PVDecSetReference(VideoDecControls *decCtrl, uint8 *refYUV, uint32 timestamp)
+{
+ VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
+ Vop *prevVop = video->prevVop;
+ int width = video->width;
+ uint8 *dstPtr, *orgPtr, *dstPtr2, *orgPtr2;
+ int32 size = (int32)width * video->height;
+
+
+ /* set new parameters */
+ prevVop->timeStamp = timestamp;
+ prevVop->predictionType = I_VOP;
+
+ dstPtr = prevVop->yChan;
+ orgPtr = refYUV;
+ oscl_memcpy(dstPtr, orgPtr, size);
+ dstPtr = prevVop->uChan;
+ dstPtr2 = prevVop->vChan;
+ orgPtr = refYUV + size;
+ orgPtr2 = orgPtr + (size >> 2);
+ oscl_memcpy(dstPtr, orgPtr, (size >> 2));
+ oscl_memcpy(dstPtr2, orgPtr2, (size >> 2));
+
+ video->concealFrame = video->prevVop->yChan;
+ video->vop_coding_type = I_VOP;
+ decCtrl->outputFrame = video->prevVop->yChan;
+
+ return PV_TRUE;
+}
+
+/* ======================================================================== */
+/* Function : PVDecSetEnhReference(VideoDecControls *decCtrl, uint8 *refYUV, */
+/* int32 timestamp) */
+/* Date : 07/23/2003 */
+/* Purpose : Get YUV enhance reference frame from external source. */
+/* In/out : YUV 4-2-0 frame containing new reference frame in the same */
+/* : dimension as original, i.e., doesn't have to be multiple of 16 !!!. */
+/* Return : */
+/* Note : */
+/* Modified : */
+/* ======================================================================== */
+Bool PVDecSetEnhReference(VideoDecControls *decCtrl, uint8 *refYUV, uint32 timestamp)
+{
+ VideoDecData *video = (VideoDecData *) decCtrl->videoDecoderData;
+ Vop *prevEnhcVop = video->prevEnhcVop;
+ uint8 *dstPtr, *orgPtr, *dstPtr2, *orgPtr2;
+ int32 size = (int32) video->width * video->height;
+
+ if (video->numberOfLayers <= 1)
+ return PV_FALSE;
+
+
+ /* set new parameters */
+ prevEnhcVop->timeStamp = timestamp;
+ prevEnhcVop->predictionType = I_VOP;
+
+ dstPtr = prevEnhcVop->yChan;
+ orgPtr = refYUV;
+ oscl_memcpy(dstPtr, orgPtr, size);
+ dstPtr = prevEnhcVop->uChan;
+ dstPtr2 = prevEnhcVop->vChan;
+ orgPtr = refYUV + size;
+ orgPtr2 = orgPtr + (size >> 2);
+ oscl_memcpy(dstPtr, orgPtr, (size >> 2));
+ oscl_memcpy(dstPtr2, orgPtr2, (size >> 2));
+ video->concealFrame = video->prevEnhcVop->yChan;
+ video->vop_coding_type = I_VOP;
+ decCtrl->outputFrame = video->prevEnhcVop->yChan;
+
+ return PV_TRUE;
+}
+
+
+/* ======================================================================== */
+/* Function : PVGetVolInfo() */
+/* Date : 08/06/2003 */
+/* Purpose : Get the vol info(only base-layer). */
+/* In/out : */
+/* Return : */
+/* Note : */
+/* Modified : 06/24/2004 */
+/* ======================================================================== */
+Bool PVGetVolInfo(VideoDecControls *decCtrl, VolInfo *pVolInfo)
+{
+ Vol *currVol;
+
+ if (pVolInfo == NULL || decCtrl == NULL || decCtrl->videoDecoderData == NULL ||
+ ((VideoDecData *)decCtrl->videoDecoderData)->vol[0] == NULL) return PV_FALSE;
+
+ currVol = ((VideoDecData *)(decCtrl->videoDecoderData))->vol[0];
+
+ // get the VOL info
+ pVolInfo->shortVideoHeader = (int32)((VideoDecData *)(decCtrl->videoDecoderData))->shortVideoHeader;
+ pVolInfo->dataPartitioning = (int32)currVol->dataPartitioning;
+ pVolInfo->errorResDisable = (int32)currVol->errorResDisable;
+ pVolInfo->useReverseVLC = (int32)currVol->useReverseVLC;
+ pVolInfo->scalability = (int32)currVol->scalability;
+ pVolInfo->nbitsTimeIncRes = (int32)currVol->nbitsTimeIncRes;
+ pVolInfo->profile_level_id = (int32)currVol->profile_level_id;
+
+ return PV_TRUE;
+}
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/scaling.h b/media/libstagefright/codecs/m4v_h263/dec/src/scaling.h
new file mode 100644
index 0000000..26abbae
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/scaling.h
@@ -0,0 +1,52 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ extern const int32 scale[63];
+
+#define PV_GET_ROW(a,b) ((a) / (b))
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/scaling_tab.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/scaling_tab.cpp
new file mode 100644
index 0000000..a1f95aa
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/scaling_tab.cpp
@@ -0,0 +1,88 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "mp4dec_api.h"
+#include "mp4def.h"
+#include "scaling.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/* this scaling can be used for dividing values up to 3292 07/10/01 */
+const int32 scale[63] = {0, 262145, 131073, 87382, 65537, 52430, 43692, 37450, 32769, 29128,
+ 26215, 23832, 21846, 20166, 18726, 17477, 16385, 15421, 14565, 13798,
+ 13108, 12484, 11917, 11399, 10924, 10487, 10083, 9710, 9363, 9040,
+ 8739, 8457, 8193, 7945, 7711, 7491, 7283, 7086, 6900, 6723, 6555, 6395,
+ 6243, 6097, 5959, 5826, 5700, 5579, 5462, 5351, 5244, 5141, 5042, 4947, 4856,
+ 4767, 4682, 4600, 4521, 4444, 4370, 4298, 4229
+ };
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Define all local variables
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Function body here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Return nothing or data or data pointer
+----------------------------------------------------------------------------*/
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_dec_tab.h b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_dec_tab.h
new file mode 100644
index 0000000..404cc8b
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_dec_tab.h
@@ -0,0 +1,215 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+* ------------------------------------------------------------------- *
+* MPEG-4 Simple Profile Video Decoder *
+* ------------------------------------------------------------------- *
+*
+* This software module was originally developed by
+*
+* Paulo Nunes (IST / ACTS-MoMuSyS)
+*
+* and edited by
+*
+* Robert Danielsen (Telenor / 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) 1996
+*
+*****************************************************************************
+***********************************************************HeaderBegin*******
+*
+* File: vlc_dec_tab.h
+*
+* Author: Paulo Nunes (IST) - Paulo.Nunes@it.ist.utl.pt
+* Created: 1-Mar-96
+*
+* Description: This file contains the VLC tables for module which deals
+* with VLC decoding.
+*
+* Notes: This file was created based on tmndecode
+* Written by Karl Olav Lillevold <kol@nta.no>,
+* 1995 Telenor R&D.
+* Donated to the Momusys-project as background code by
+* Telenor.
+*
+* based on mpeg2decode, (C) 1994, MPEG Software Simulation Group
+* and mpeg2play, (C) 1994 Stefan Eckart
+* <stefan@lis.e-technik.tu-muenchen.de>
+*
+*
+* Modified: 9-May-96 Paulo Nunes: Reformatted. New headers.
+* 14-May-96 Paulo Nunes: Changed TMNMVtabs according to VM2.1.
+* 04.11.96 Robert Danielsen: Added three new tables for coding
+* of Intra luminance coefficients (VM 4.0)
+* 01.05.97 Luis Ducla-Soares: added VM7.0 Reversible VLC tables (RVLC).
+* 13.05.97 Minhua Zhou: added VlC tables for CBPYtab2 CBPYtab3,
+* revised CBPYtab
+*
+***********************************************************HeaderEnd*********
+
+This module is a header file for "vlc_decode.c". The table data actually
+resides in "vlc_tab.c".
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef vlc_dec_tab_H
+#define vlc_dec_tab_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "mp4def.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ extern const VLCshorttab PV_TMNMVtab0[];
+
+ extern const VLCshorttab PV_TMNMVtab1[];
+
+ extern const VLCshorttab PV_TMNMVtab2[];
+
+ extern const VLCshorttab PV_MCBPCtab[];
+
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ extern const VLCshorttab PV_MCBPCtab1[];
+#endif
+ extern const VLCshorttab PV_MCBPCtabintra[];
+
+ /* Table for separate mode MCBPC, for coding DQUANT-flag and CBPC */
+
+ extern const VLCshorttab MCBPCtab_sep[32];
+
+ extern const VLCshorttab PV_CBPYtab[48];
+
+ extern const VLCshorttab CBPYtab2[16];
+
+ extern const VLCshorttab CBPYtab3[64];
+
+ extern const VLCtab2 PV_DCT3Dtab0[];
+
+
+ extern const VLCtab2 PV_DCT3Dtab1[];
+
+
+ extern const VLCtab2 PV_DCT3Dtab2[];
+
+ /* New tables for Intra luminance blocks */
+
+ extern const VLCtab2 PV_DCT3Dtab3[];
+
+ extern const VLCtab2 PV_DCT3Dtab4[];
+
+ extern const VLCtab2 PV_DCT3Dtab5[];
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ /* Annex I tables */
+ extern const VLCtab2 PV_DCT3Dtab6[];
+
+ extern const VLCtab2 PV_DCT3Dtab7[];
+
+ extern const VLCtab2 PV_DCT3Dtab8[];
+#endif
+ /* RVLC tables */
+ extern const int ptrRvlcTab[];
+
+ extern const VLCtab2 RvlcDCTtabIntra[];
+
+ extern const VLCtab2 RvlcDCTtabInter[];
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp
new file mode 100644
index 0000000..f7192b1
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.cpp
@@ -0,0 +1,1636 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+* ------------------------------------------------------------------- *
+* MPEG-4 Simple Profile Video Decoder *
+* ------------------------------------------------------------------- *
+*
+* This software module was originally developed by
+*
+* Paulo Nunes (IST / ACTS-MoMuSyS)
+* Robert Danielsen (Telenor / 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) 1996
+*
+*****************************************************************************/
+
+/***********************************************************HeaderBegin*******
+*
+* File: vlc_dec.c
+*
+* Author: Paulo Nunes (IST) - Paulo.Nunes@lx.it.pt
+* Created: 1-Mar-96
+*
+* Description: This file contains the VLC functions needed to decode a
+* bitstream.
+*
+* Notes:
+* The functions contained in this file were adapted from
+* tmndecode
+* Written by Karl Olav Lillevold <kol@nta.no>,
+* 1995 Telenor R&D.
+* Donated to the Momusys-project as background code by
+* Telenor.
+*
+* based on mpeg2decode, (C) 1994, MPEG Software Simulation Group
+* and mpeg2play, (C) 1994 Stefan Eckart
+* <stefan@lis.e-technik.tu-muenchen.de>
+*
+*
+* Modified: 9-May-96 Paulo Nunes: Reformatted. New headers.
+* 17-Jan-97 Jan De Lameillieure (HHI) : corrected in
+* 01.05.97 Luis Ducla-Soares: added RvlcDecTCOEF() to allow decoding
+* of Reversible VLCs.
+* 09.03.98 Paulo Nunes: Cleaning.
+*
+***********************************************************HeaderEnd*********/
+
+#include "mp4dec_lib.h"
+#include "vlc_dec_tab.h"
+#include "vlc_decode.h"
+#include "bitstream.h"
+#include "max_level.h"
+
+
+/* ====================================================================== /
+ Function : DecodeUserData()
+ Date : 04/10/2000
+ History :
+ Modified : 04/16/2001 : removed status checking of PV_BitstreamFlushBits
+
+ This is simply a realization of the user_data() function
+ in the ISO/IEC 14496-2 manual.
+/ ====================================================================== */
+PV_STATUS DecodeUserData(BitstreamDecVideo *stream)
+{
+ PV_STATUS status;
+ uint32 code;
+
+ BitstreamReadBits32HC(stream);
+ BitstreamShowBits32(stream, 24, &code);
+
+ while (code != 1)
+ {
+ /* Discard user data for now. 04/05/2000 */
+ BitstreamReadBits16(stream, 8);
+ BitstreamShowBits32(stream, 24, &code);
+ status = BitstreamCheckEndBuffer(stream);
+ if (status == PV_END_OF_VOP) return status; /* 03/19/2002 */
+ }
+ return PV_SUCCESS;
+}
+
+
+
+/***********************************************************CommentBegin******
+*
+* 3/10/00 : initial modification to the
+* new PV-Decoder Lib format.
+* 3/29/00 : added return code check to some functions and
+* optimize the code.
+*
+***********************************************************CommentEnd********/
+PV_STATUS PV_GetMBvectors(VideoDecData *video, uint mode)
+{
+ PV_STATUS status;
+ BitstreamDecVideo *stream = video->bitstream;
+ int f_code_f = video->currVop->fcodeForward;
+ int vlc_code_mag;
+
+
+ MOT *mot_x = video->motX;
+ MOT *mot_y = video->motY;
+
+ int k, offset;
+ int x_pos = video->mbnum_col;
+ int y_pos = video->mbnum_row;
+ int doubleWidth = video->nMBPerRow << 1;
+ int pos = (x_pos + y_pos * doubleWidth) << 1;
+ MOT mvx = 0, mvy = 0;
+
+
+ if (f_code_f == 1)
+ {
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ if (mode == MODE_INTER4V || mode == MODE_INTER4V_Q)
+#else
+ if (mode == MODE_INTER4V)
+#endif
+ {
+ for (k = 0; k < 4; k++)
+ {
+ offset = (k & 1) + (k >> 1) * doubleWidth;
+ mv_prediction(video, k, &mvx, &mvy);
+ /* decode component x */
+ status = PV_VlcDecMV(stream, &vlc_code_mag);
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+
+ mvx += (MOT)vlc_code_mag;
+ mvx = (MOT)(((mvx + 32) & 0x3F) - 32);
+
+
+ status = PV_VlcDecMV(stream, &vlc_code_mag);
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+
+ mvy += (MOT)vlc_code_mag;
+ mvy = (MOT)(((mvy + 32) & 0x3F) - 32);
+
+ mot_x[pos+offset] = (MOT) mvx;
+ mot_y[pos+offset] = (MOT) mvy;
+ }
+ }
+ else
+ {
+ mv_prediction(video, 0, &mvx, &mvy);
+ /* For PVOPs, field appears only in MODE_INTER & MODE_INTER_Q */
+ status = PV_VlcDecMV(stream, &vlc_code_mag);
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+
+ mvx += (MOT)vlc_code_mag;
+ mvx = (MOT)(((mvx + 32) & 0x3F) - 32);
+
+
+ status = PV_VlcDecMV(stream, &vlc_code_mag);
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+
+
+ mvy += (MOT)vlc_code_mag;
+ mvy = (MOT)(((mvy + 32) & 0x3F) - 32);
+
+
+ mot_x[pos] = mot_x[pos+1] = (MOT) mvx;
+ mot_y[pos] = mot_y[pos+1] = (MOT) mvy;
+ pos += doubleWidth;
+ mot_x[pos] = mot_x[pos+1] = (MOT) mvx;
+ mot_y[pos] = mot_y[pos+1] = (MOT) mvy;
+ }
+ }
+ else
+ {
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ if (mode == MODE_INTER4V || mode == MODE_INTER4V_Q)
+#else
+ if (mode == MODE_INTER4V)
+#endif
+ {
+ for (k = 0; k < 4; k++)
+ {
+ offset = (k & 1) + (k >> 1) * doubleWidth;
+ mv_prediction(video, k, &mvx, &mvy);
+ status = PV_DecodeMBVec(stream, &mvx, &mvy, f_code_f);
+ mot_x[pos+offset] = (MOT) mvx;
+ mot_y[pos+offset] = (MOT) mvy;
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+ }
+ }
+ else
+ {
+ mv_prediction(video, 0, &mvx, &mvy);
+ /* For PVOPs, field appears only in MODE_INTER & MODE_INTER_Q */
+ status = PV_DecodeMBVec(stream, &mvx, &mvy, f_code_f);
+ mot_x[pos] = mot_x[pos+1] = (MOT) mvx;
+ mot_y[pos] = mot_y[pos+1] = (MOT) mvy;
+ pos += doubleWidth;
+ mot_x[pos] = mot_x[pos+1] = (MOT) mvx;
+ mot_y[pos] = mot_y[pos+1] = (MOT) mvy;
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+ }
+ }
+ return PV_SUCCESS;
+}
+
+
+/***********************************************************CommentBegin******
+* 3/10/00 : initial modification to the
+* new PV-Decoder Lib format.
+* 3/29/00 : added return code check to some functions
+* 5/10/00 : check whether the decoded vector is legal.
+* 4/17/01 : use MOT type
+***********************************************************CommentEnd********/
+PV_STATUS PV_DecodeMBVec(BitstreamDecVideo *stream, MOT *mv_x, MOT *mv_y, int f_code_f)
+{
+ PV_STATUS status;
+ int vlc_code_magx, vlc_code_magy;
+ int residualx = 0, residualy = 0;
+
+ /* decode component x */
+ status = PV_VlcDecMV(stream, &vlc_code_magx);
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+
+ if (vlc_code_magx)
+ {
+ residualx = (int) BitstreamReadBits16_INLINE(stream, (int)(f_code_f - 1));
+ }
+
+
+ /* decode component y */
+ status = PV_VlcDecMV(stream, &vlc_code_magy);
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+
+ if (vlc_code_magy)
+ {
+ residualy = (int) BitstreamReadBits16_INLINE(stream, (int)(f_code_f - 1));
+ }
+
+
+ if (PV_DeScaleMVD(f_code_f, residualx, vlc_code_magx, mv_x) != PV_SUCCESS)
+ {
+ return PV_FAIL;
+ }
+
+ if (PV_DeScaleMVD(f_code_f, residualy, vlc_code_magy, mv_y) != PV_SUCCESS)
+ {
+ return PV_FAIL;
+ }
+
+ return PV_SUCCESS;
+}
+
+
+/***********************************************************CommentBegin******
+* 3/31/2000 : initial modification to the new PV-Decoder Lib format.
+* 5/10/2000 : check to see if the decoded vector falls within
+* the legal fcode range.
+*
+***********************************************************CommentEnd********/
+PV_STATUS PV_DeScaleMVD(
+ int f_code, /* <-- MV range in 1/2 units: 1=32,2=64,...,7=2048 */
+ int residual, /* <-- part of the MV Diff. FLC coded */
+ int vlc_code_mag, /* <-- part of the MV Diff. VLC coded */
+ MOT *vector /* --> Obtained MV component in 1/2 units */
+)
+{
+ int half_range = (1 << (f_code + 4));
+ int mask = (half_range << 1) - 1;
+ int diff_vector;
+
+
+ if (vlc_code_mag == 0)
+ {
+ diff_vector = vlc_code_mag;
+ }
+ else
+ {
+ diff_vector = ((PV_ABS(vlc_code_mag) - 1) << (f_code - 1)) + residual + 1;
+ if (vlc_code_mag < 0)
+ {
+ diff_vector = -diff_vector;
+ }
+ }
+
+ *vector += (MOT)(diff_vector);
+
+ *vector = (MOT)((*vector + half_range) & mask) - half_range;
+
+ return PV_SUCCESS;
+}
+
+
+
+void mv_prediction(
+ VideoDecData *video,
+ int block,
+ MOT *mvx,
+ MOT *mvy
+)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ MOT *motxdata = video->motX;
+ MOT *motydata = video->motY;
+ int mbnum_col = video->mbnum_col;
+ int mbnum_row = video->mbnum_row;
+ uint8 *slice_nb = video->sliceNo;
+ int nMBPerRow = video->nMBPerRow;
+ int nMVPerRow = nMBPerRow << 1;
+ int mbnum = video->mbnum;
+ int p1x = 0, p2x = 0, p3x = 0;
+ int p1y = 0, p2y = 0, p3y = 0;
+ int rule1 = 0, rule2 = 0, rule3 = 0;
+ int indx;
+
+ indx = ((mbnum_col << 1) + (block & 1)) + ((mbnum_row << 1) + (block >> 1)) * nMVPerRow - 1; /* left block */
+
+ if (block & 1) /* block 1, 3 */
+ {
+ p1x = motxdata[indx];
+ p1y = motydata[indx];
+ rule1 = 1;
+ }
+ else /* block 0, 2 */
+ {
+ if (mbnum_col > 0 && slice_nb[mbnum] == slice_nb[mbnum-1])
+ {
+ p1x = motxdata[indx];
+ p1y = motydata[indx];
+ rule1 = 1;
+ }
+ }
+
+ indx = indx + 1 - nMVPerRow; /* upper_block */
+ if (block >> 1)
+ {
+ indx -= (block & 1);
+ p2x = motxdata[indx];
+ p2y = motydata[indx];
+ p3x = motxdata[indx + 1];
+ p3y = motydata[indx + 1];
+ rule2 = rule3 = 1;
+ }
+ else
+ { /* block 0,1 */
+ if (mbnum_row)
+ {
+ if (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])
+ {
+ p2x = motxdata[indx];
+ p2y = motydata[indx];
+ rule2 = 1;
+ }
+ if (mbnum_col < nMBPerRow - 1 && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow+1])
+ {
+ indx = indx + 2 - (block & 1);
+ p3x = motxdata[indx];
+ p3y = motydata[indx];
+ rule3 = 1;
+ }
+ }
+ }
+
+ if (rule1 + rule2 + rule3 > 1)
+ {
+ *mvx = (MOT)PV_MEDIAN(p1x, p2x, p3x);
+ *mvy = (MOT)PV_MEDIAN(p1y, p2y, p3y);
+ }
+ else if (rule1 + rule2 + rule3 == 1)
+ {
+ /* two of three are zero */
+ *mvx = (MOT)(p1x + p2x + p3x);
+ *mvy = (MOT)(p1y + p2y + p3y);
+ }
+ else
+ {
+ /* all MBs are outside the VOP */
+ *mvx = *mvy = 0;
+ }
+ /*----------------------------------------------------------------------------
+ ; Return nothing or data or data pointer
+ ----------------------------------------------------------------------------*/
+ return;
+}
+
+/***********************************************************CommentBegin******
+*
+* 3/30/2000 : initial modification to the new PV-Decoder Lib format.
+* 4/16/2001 : removed checking of status for PV_BitstreamFlushBits
+***********************************************************CommentEnd********/
+
+PV_STATUS PV_VlcDecMV(BitstreamDecVideo *stream, int *mv)
+{
+ PV_STATUS status = PV_SUCCESS;
+ uint code;
+
+ BitstreamShow13Bits(stream, &code);
+
+ if (code >> 12)
+ {
+ *mv = 0; /* Vector difference = 0 */
+ PV_BitstreamFlushBits(stream, 1);
+ return PV_SUCCESS;
+ }
+
+ if (code >= 512)
+ {
+ code = (code >> 8) - 2;
+ PV_BitstreamFlushBits(stream, PV_TMNMVtab0[code].len + 1);
+ *mv = PV_TMNMVtab0[code].val;
+ return status;
+ }
+
+ if (code >= 128)
+ {
+ code = (code >> 2) - 32;
+ PV_BitstreamFlushBits(stream, PV_TMNMVtab1[code].len + 1);
+ *mv = PV_TMNMVtab1[code].val;
+ return status;
+ }
+
+ if (code < 4)
+ {
+ *mv = -1;
+ return PV_FAIL;
+ }
+
+ code -= 4;
+
+ PV_BitstreamFlushBits(stream, PV_TMNMVtab2[code].len + 1);
+
+ *mv = PV_TMNMVtab2[code].val;
+ return status;
+}
+
+
+/***********************************************************CommentBegin******
+* 3/30/2000 : initial modification to the new PV-Decoder Lib
+* format and the change of error-handling method.
+* 4/16/01 : removed status checking of PV_BitstreamFlushBits
+***********************************************************CommentEnd********/
+
+int PV_VlcDecMCBPC_com_intra(BitstreamDecVideo *stream)
+{
+ uint code;
+
+ BitstreamShowBits16(stream, 9, &code);
+
+
+ if (code < 8)
+ {
+ return VLC_CODE_ERROR;
+ }
+
+ code >>= 3;
+
+ if (code >= 32)
+ {
+ PV_BitstreamFlushBits(stream, 1);
+ return 3;
+ }
+
+ PV_BitstreamFlushBits(stream, PV_MCBPCtabintra[code].len);
+
+ return PV_MCBPCtabintra[code].val;
+}
+
+
+/***********************************************************CommentBegin******
+*
+* 3/30/2000 : initial modification to the new PV-Decoder Lib
+* format and the change of error-handling method.
+* 4/16/2001 : removed checking of return status of PV_BitstreamFlushBits
+***********************************************************CommentEnd********/
+
+int PV_VlcDecMCBPC_com_inter(BitstreamDecVideo *stream)
+{
+ uint code;
+
+ BitstreamShowBits16(stream, 9, &code);
+
+ if (code == 0)
+ {
+ return VLC_CODE_ERROR;
+ }
+ else if (code >= 256)
+ {
+ PV_BitstreamFlushBits(stream, 1);
+ return 0;
+ }
+
+ PV_BitstreamFlushBits(stream, PV_MCBPCtab[code].len);
+ return PV_MCBPCtab[code].val;
+}
+
+#ifdef PV_ANNEX_IJKT_SUPPORT
+int PV_VlcDecMCBPC_com_inter_H263(BitstreamDecVideo *stream)
+{
+ uint code;
+
+ BitstreamShow13Bits(stream, &code);
+
+ if (code == 0)
+ {
+ return VLC_CODE_ERROR;
+ }
+ else if (code >= 4096)
+ {
+ PV_BitstreamFlushBits(stream, 1);
+ return 0;
+ }
+ if (code >= 16)
+ {
+ PV_BitstreamFlushBits(stream, PV_MCBPCtab[code >> 4].len);
+ return PV_MCBPCtab[code >> 4].val;
+ }
+ else
+ {
+ PV_BitstreamFlushBits(stream, PV_MCBPCtab1[code - 8].len);
+ return PV_MCBPCtab1[code - 8].val;
+ }
+}
+#endif
+/***********************************************************CommentBegin******
+* 3/30/2000 : initial modification to the new PV-Decoder Lib
+* format and the change of error-handling method.
+* 4/16/2001 : removed status checking for PV_BitstreamFlushBits
+***********************************************************CommentEnd********/
+
+int PV_VlcDecCBPY(BitstreamDecVideo *stream, int intra)
+{
+ int CBPY = 0;
+ uint code;
+
+ BitstreamShowBits16(stream, 6, &code);
+
+
+ if (code < 2)
+ {
+ return -1;
+ }
+ else if (code >= 48)
+ {
+ PV_BitstreamFlushBits(stream, 2);
+ CBPY = 15;
+ }
+ else
+ {
+ PV_BitstreamFlushBits(stream, PV_CBPYtab[code].len);
+ CBPY = PV_CBPYtab[code].val;
+ }
+
+ if (intra == 0) CBPY = 15 - CBPY;
+ CBPY = CBPY & 15;
+ return CBPY;
+}
+
+
+/***********************************************************CommentBegin******
+* 3/31/2000 : initial modification to the new PV-Decoder Lib format.
+*
+* 8/23/2000 : optimize the function by removing unnecessary BitstreamShowBits()
+* function calls.
+*
+* 9/6/2000 : change the API to check for end-of-buffer for proper
+* termination of decoding process.
+***********************************************************CommentEnd********/
+PV_STATUS PV_VlcDecIntraDCPredSize(BitstreamDecVideo *stream, int compnum, uint *DC_size)
+{
+ PV_STATUS status = PV_FAIL; /* 07/09/01 */
+ uint code;
+
+ *DC_size = 0;
+ if (compnum < 4) /* luminance block */
+ {
+
+ BitstreamShowBits16(stream, 11, &code);
+
+ if (code == 1)
+ {
+ *DC_size = 12;
+ PV_BitstreamFlushBits(stream, 11);
+ return PV_SUCCESS;
+ }
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 11;
+ PV_BitstreamFlushBits(stream, 10);
+ return PV_SUCCESS;
+ }
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 10;
+ PV_BitstreamFlushBits(stream, 9);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 9;
+ PV_BitstreamFlushBits(stream, 8);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 8;
+ PV_BitstreamFlushBits(stream, 7);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 7;
+ PV_BitstreamFlushBits(stream, 6);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 6;
+ PV_BitstreamFlushBits(stream, 5);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 5;
+ PV_BitstreamFlushBits(stream, 4);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 4;
+ PV_BitstreamFlushBits(stream, 3);
+ return PV_SUCCESS;
+ }
+ else if (code == 2)
+ {
+ *DC_size = 3;
+ PV_BitstreamFlushBits(stream, 3);
+ return PV_SUCCESS;
+ }
+ else if (code == 3)
+ {
+ *DC_size = 0;
+ PV_BitstreamFlushBits(stream, 3);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 2)
+ {
+ *DC_size = 2;
+ PV_BitstreamFlushBits(stream, 2);
+ return PV_SUCCESS;
+ }
+ else if (code == 3)
+ {
+ *DC_size = 1;
+ PV_BitstreamFlushBits(stream, 2);
+ return PV_SUCCESS;
+ }
+ }
+ else /* chrominance block */
+ {
+
+ BitstreamShow13Bits(stream, &code);
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 12;
+ PV_BitstreamFlushBits(stream, 12);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 11;
+ PV_BitstreamFlushBits(stream, 11);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 10;
+ PV_BitstreamFlushBits(stream, 10);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 9;
+ PV_BitstreamFlushBits(stream, 9);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 8;
+ PV_BitstreamFlushBits(stream, 8);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 7;
+ PV_BitstreamFlushBits(stream, 7);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 6;
+ PV_BitstreamFlushBits(stream, 6);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 5;
+ PV_BitstreamFlushBits(stream, 5);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 4;
+ PV_BitstreamFlushBits(stream, 4);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ if (code == 1)
+ {
+ *DC_size = 3;
+ PV_BitstreamFlushBits(stream, 3);
+ return PV_SUCCESS;
+ }
+
+ code >>= 1;
+ {
+ *DC_size = (int)(3 - code);
+ PV_BitstreamFlushBits(stream, 2);
+ return PV_SUCCESS;
+ }
+ }
+
+ return status;
+}
+
+/***********************************************************CommentBegin******
+*
+*
+* 3/30/2000 : initial modification to the new PV-Decoder Lib
+* format and the change of error-handling method.
+*
+***********************************************************CommentEnd********/
+
+
+
+PV_STATUS VlcDecTCOEFIntra(BitstreamDecVideo *stream, Tcoef *pTcoef)
+{
+ uint code;
+ const VLCtab2 *tab;
+
+ BitstreamShow13Bits(stream, &code);
+
+ /* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFIntra */
+ /* if(GetTcoeffIntra(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
+ if (code >= 1024)
+ {
+ tab = &PV_DCT3Dtab3[(code >> 6) - 16];
+ }
+ else
+ {
+ if (code >= 256)
+ {
+ tab = &PV_DCT3Dtab4[(code >> 3) - 32];
+ }
+ else
+ {
+ if (code >= 16)
+ {
+ tab = &PV_DCT3Dtab5[(code>>1) - 8];
+ }
+ else
+ {
+ return PV_FAIL;
+ }
+ }
+ }
+
+ PV_BitstreamFlushBits(stream, tab->len + 1);
+ pTcoef->sign = (code >> (12 - tab->len)) & 1;
+ pTcoef->run = (uint) tab->run; //(tab->val >> 8) & 255;
+ pTcoef->level = (int) tab->level; //tab->val & 255;
+ pTcoef->last = (uint) tab->last; //(tab->val >> 16) & 1;
+
+
+ /* the following is modified for 3-mode escape -- boon */
+ if (tab->level != 0xFF)
+ {
+ return PV_SUCCESS;
+ }
+
+ //if (((tab->run<<8)|(tab->level)|(tab->last<<16)) == VLC_ESCAPE_CODE)
+
+ if (!pTcoef->sign)
+ {
+ /* first escape mode. level is offset */
+ BitstreamShow13Bits(stream, &code);
+
+ /* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFIntra */
+ /* if(GetTcoeffIntra(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
+ if (code >= 1024)
+ {
+ tab = &PV_DCT3Dtab3[(code >> 6) - 16];
+ }
+ else
+ {
+ if (code >= 256)
+ {
+ tab = &PV_DCT3Dtab4[(code >> 3) - 32];
+ }
+ else
+ {
+ if (code >= 16)
+ {
+ tab = &PV_DCT3Dtab5[(code>>1) - 8];
+ }
+ else
+ {
+ return PV_FAIL;
+ }
+ }
+ }
+
+ PV_BitstreamFlushBits(stream, tab->len + 1);
+
+ /* sign bit */
+ pTcoef->sign = (code >> (12 - tab->len)) & 1;
+ pTcoef->run = (uint)tab->run; //(tab->val >> 8) & 255;
+ pTcoef->level = (int)tab->level; //tab->val & 255;
+ pTcoef->last = (uint)tab->last; //(tab->val >> 16) & 1;
+
+
+ /* need to add back the max level */
+ if ((pTcoef->last == 0 && pTcoef->run > 14) || (pTcoef->last == 1 && pTcoef->run > 20))
+ {
+ return PV_FAIL;
+ }
+ pTcoef->level = pTcoef->level + intra_max_level[pTcoef->last][pTcoef->run];
+
+
+ }
+ else
+ {
+ uint run_offset;
+ run_offset = BitstreamRead1Bits_INLINE(stream);
+
+ if (!run_offset)
+ {
+ /* second escape mode. run is offset */
+ BitstreamShow13Bits(stream, &code);
+
+ /* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFIntra */
+ /* if(GetTcoeffIntra(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
+ if (code >= 1024)
+ {
+ tab = &PV_DCT3Dtab3[(code >> 6) - 16];
+ }
+ else
+ {
+ if (code >= 256)
+ {
+ tab = &PV_DCT3Dtab4[(code >> 3) - 32];
+ }
+ else
+ {
+ if (code >= 16)
+ {
+ tab = &PV_DCT3Dtab5[(code>>1) - 8];
+ }
+ else
+ {
+ return PV_FAIL;
+ }
+ }
+ }
+
+ PV_BitstreamFlushBits(stream, tab->len + 1);
+ /* sign bit */
+ pTcoef->sign = (code >> (12 - tab->len)) & 1;
+ pTcoef->run = (uint)tab->run; //(tab->val >> 8) & 255;
+ pTcoef->level = (int)tab->level; //tab->val & 255;
+ pTcoef->last = (uint)tab->last; //(tab->val >> 16) & 1;
+
+
+
+ /* need to add back the max run */
+ if (pTcoef->last)
+ {
+ if (pTcoef->level > 8)
+ {
+ return PV_FAIL;
+ }
+ pTcoef->run = pTcoef->run + intra_max_run1[pTcoef->level] + 1;
+ }
+ else
+ {
+ if (pTcoef->level > 27)
+ {
+ return PV_FAIL;
+ }
+ pTcoef->run = pTcoef->run + intra_max_run0[pTcoef->level] + 1;
+ }
+
+
+ }
+ else
+ {
+
+ code = BitstreamReadBits16_INLINE(stream, 8);
+ pTcoef->last = code >> 7;
+ pTcoef->run = (code >> 1) & 0x3F;
+ pTcoef->level = (int)(BitstreamReadBits16_INLINE(stream, 13) >> 1);
+
+ if (pTcoef->level >= 2048)
+ {
+ pTcoef->sign = 1;
+ pTcoef->level = 4096 - pTcoef->level;
+ }
+ else
+ {
+ pTcoef->sign = 0;
+ }
+ } /* flc */
+ }
+
+ return PV_SUCCESS;
+
+} /* VlcDecTCOEFIntra */
+
+PV_STATUS VlcDecTCOEFInter(BitstreamDecVideo *stream, Tcoef *pTcoef)
+{
+ uint code;
+ const VLCtab2 *tab;
+
+ BitstreamShow13Bits(stream, &code);
+
+ /* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFInter */
+ /* if(GetTcoeffInter(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
+ if (code >= 1024)
+ {
+ tab = &PV_DCT3Dtab0[(code >> 6) - 16];
+ }
+ else
+ {
+ if (code >= 256)
+ {
+ tab = &PV_DCT3Dtab1[(code >> 3) - 32];
+ }
+ else
+ {
+ if (code >= 16)
+ {
+ tab = &PV_DCT3Dtab2[(code>>1) - 8];
+ }
+ else
+ {
+ return PV_FAIL;
+ }
+ }
+ }
+ PV_BitstreamFlushBits(stream, tab->len + 1);
+ pTcoef->sign = (code >> (12 - tab->len)) & 1;
+ pTcoef->run = (uint)tab->run; //(tab->val >> 4) & 255;
+ pTcoef->level = (int)tab->level; //tab->val & 15;
+ pTcoef->last = (uint)tab->last; //(tab->val >> 12) & 1;
+
+ /* the following is modified for 3-mode escape -- boon */
+ if (tab->run != 0xBF)
+ {
+ return PV_SUCCESS;
+ }
+ //if (((tab->run<<4)|(tab->level)|(tab->last<<12)) == VLC_ESCAPE_CODE)
+
+
+ if (!pTcoef->sign)
+ {
+ /* first escape mode. level is offset */
+ BitstreamShow13Bits(stream, &code);
+
+ /* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFInter */
+ /* if(GetTcoeffInter(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
+ if (code >= 1024)
+ {
+ tab = &PV_DCT3Dtab0[(code >> 6) - 16];
+ }
+ else
+ {
+ if (code >= 256)
+ {
+ tab = &PV_DCT3Dtab1[(code >> 3) - 32];
+ }
+ else
+ {
+ if (code >= 16)
+ {
+ tab = &PV_DCT3Dtab2[(code>>1) - 8];
+ }
+ else
+ {
+ return PV_FAIL;
+ }
+ }
+ }
+ PV_BitstreamFlushBits(stream, tab->len + 1);
+ pTcoef->sign = (code >> (12 - tab->len)) & 1;
+ pTcoef->run = (uint)tab->run; //(tab->val >> 4) & 255;
+ pTcoef->level = (int)tab->level; //tab->val & 15;
+ pTcoef->last = (uint)tab->last; //(tab->val >> 12) & 1;
+
+ /* need to add back the max level */
+ if ((pTcoef->last == 0 && pTcoef->run > 26) || (pTcoef->last == 1 && pTcoef->run > 40))
+ {
+ return PV_FAIL;
+ }
+ pTcoef->level = pTcoef->level + inter_max_level[pTcoef->last][pTcoef->run];
+ }
+ else
+ {
+ uint run_offset;
+ run_offset = BitstreamRead1Bits_INLINE(stream);
+
+ if (!run_offset)
+ {
+ /* second escape mode. run is offset */
+ BitstreamShow13Bits(stream, &code);
+
+ /* 10/17/2000, perform a little bit better on ARM by putting the whole function in VlcDecTCOEFFInter */
+ /*if(GetTcoeffInter(code,pTcoef,&tab,stream)!=PV_SUCCESS) return status;*/
+ if (code >= 1024)
+ {
+ tab = &PV_DCT3Dtab0[(code >> 6) - 16];
+ }
+ else
+ {
+ if (code >= 256)
+ {
+ tab = &PV_DCT3Dtab1[(code >> 3) - 32];
+ }
+ else
+ {
+ if (code >= 16)
+ {
+ tab = &PV_DCT3Dtab2[(code>>1) - 8];
+ }
+ else
+ {
+ return PV_FAIL;
+ }
+ }
+ }
+ PV_BitstreamFlushBits(stream, tab->len + 1);
+ pTcoef->sign = (code >> (12 - tab->len)) & 1;
+ pTcoef->run = (uint)tab->run; //(tab->val >> 4) & 255;
+ pTcoef->level = (int)tab->level; //tab->val & 15;
+ pTcoef->last = (uint)tab->last; //(tab->val >> 12) & 1;
+
+ /* need to add back the max run */
+ if (pTcoef->last)
+ {
+ if (pTcoef->level > 3)
+ {
+ return PV_FAIL;
+ }
+ pTcoef->run = pTcoef->run + inter_max_run1[pTcoef->level] + 1;
+ }
+ else
+ {
+ if (pTcoef->level > 12)
+ {
+ return PV_FAIL;
+ }
+ pTcoef->run = pTcoef->run + inter_max_run0[pTcoef->level] + 1;
+ }
+ }
+ else
+ {
+
+ code = BitstreamReadBits16_INLINE(stream, 8);
+ pTcoef->last = code >> 7;
+ pTcoef->run = (code >> 1) & 0x3F;
+ pTcoef->level = (int)(BitstreamReadBits16_INLINE(stream, 13) >> 1);
+
+
+
+ if (pTcoef->level >= 2048)
+ {
+ pTcoef->sign = 1;
+ pTcoef->level = 4096 - pTcoef->level;
+ }
+ else
+ {
+ pTcoef->sign = 0;
+ }
+ } /* flc */
+ }
+
+ return PV_SUCCESS;
+
+} /* VlcDecTCOEFInter */
+
+/*=======================================================
+ Function: VlcDecTCOEFShortHeader()
+ Date : 04/27/99
+ Purpose : New function used in decoding of video planes
+ with short header
+ Modified: 05/23/2000
+ for new decoder structure.
+=========================================================*/
+PV_STATUS VlcDecTCOEFShortHeader(BitstreamDecVideo *stream, Tcoef *pTcoef/*, int intra*/)
+{
+ uint code;
+ const VLCtab2 *tab;
+
+ BitstreamShow13Bits(stream, &code);
+
+ /*intra = 0;*/
+
+ if (code >= 1024) tab = &PV_DCT3Dtab0[(code >> 6) - 16];
+ else
+ {
+ if (code >= 256) tab = &PV_DCT3Dtab1[(code >> 3) - 32];
+ else
+ {
+ if (code >= 16) tab = &PV_DCT3Dtab2[(code>>1) - 8];
+ else return PV_FAIL;
+ }
+ }
+
+ PV_BitstreamFlushBits(stream, tab->len + 1);
+ pTcoef->sign = (code >> (12 - tab->len)) & 1;
+ pTcoef->run = (uint)tab->run;//(tab->val >> 4) & 255;
+ pTcoef->level = (int)tab->level;//tab->val & 15;
+ pTcoef->last = (uint)tab->last;//(tab->val >> 12) & 1;
+
+ /* the following is modified for 3-mode escape -- boon */
+ if (((tab->run << 4) | (tab->level) | (tab->last << 12)) != VLC_ESCAPE_CODE) /* ESCAPE */
+ {
+ return PV_SUCCESS;
+ }
+
+
+ /* escape mode 4 - H.263 type */
+ pTcoef->last = pTcoef->sign; /* Last */
+ pTcoef->run = BitstreamReadBits16_INLINE(stream, 6); /* Run */
+ pTcoef->level = (int) BitstreamReadBits16_INLINE(stream, 8); /* Level */
+
+ if (pTcoef->level == 0 || pTcoef->level == 128)
+ {
+ return PV_FAIL;
+ }
+
+ if (pTcoef->level > 128)
+ {
+ pTcoef->sign = 1;
+ pTcoef->level = 256 - pTcoef->level;
+ }
+ else
+ {
+ pTcoef->sign = 0;
+ }
+
+
+
+ return PV_SUCCESS;
+
+} /* VlcDecTCOEFShortHeader */
+
+#ifdef PV_ANNEX_IJKT_SUPPORT
+PV_STATUS VlcDecTCOEFShortHeader_AnnexI(BitstreamDecVideo *stream, Tcoef *pTcoef/*, int intra*/)
+{
+ uint code;
+ const VLCtab2 *tab;
+
+ BitstreamShow13Bits(stream, &code);
+
+ /*intra = 0;*/
+
+ if (code >= 1024) tab = &PV_DCT3Dtab6[(code >> 6) - 16];
+ else
+ {
+ if (code >= 256) tab = &PV_DCT3Dtab7[(code >> 3) - 32];
+ else
+ {
+ if (code >= 16) tab = &PV_DCT3Dtab8[(code>>1) - 8];
+ else return PV_FAIL;
+ }
+ }
+
+ PV_BitstreamFlushBits(stream, tab->len + 1);
+ pTcoef->sign = (code >> (12 - tab->len)) & 1;
+ pTcoef->run = (uint)tab->run;//(tab->val >> 4) & 255;
+ pTcoef->level = (int)tab->level;//tab->val & 15;
+ pTcoef->last = (uint)tab->last;//(tab->val >> 12) & 1;
+
+ /* the following is modified for 3-mode escape -- boon */
+ if (((tab->run << 6) | (tab->level) | (tab->last << 12)) != VLC_ESCAPE_CODE) /* ESCAPE */
+ {
+ return PV_SUCCESS;
+ }
+ /* escape mode 4 - H.263 type */
+ pTcoef->last = pTcoef->sign; /* Last */
+ pTcoef->run = BitstreamReadBits16(stream, 6); /* Run */
+ pTcoef->level = (int) BitstreamReadBits16(stream, 8); /* Level */
+
+ if (pTcoef->level == 0 || pTcoef->level == 128)
+ {
+ return PV_FAIL;
+ }
+
+
+ if (pTcoef->level > 128)
+ {
+ pTcoef->sign = 1;
+ pTcoef->level = 256 - pTcoef->level;
+ }
+ else pTcoef->sign = 0;
+
+
+
+ return PV_SUCCESS;
+
+} /* VlcDecTCOEFShortHeader_AnnexI */
+
+PV_STATUS VlcDecTCOEFShortHeader_AnnexT(BitstreamDecVideo *stream, Tcoef *pTcoef/*, int intra*/)
+{
+ uint code;
+ const VLCtab2 *tab;
+
+ BitstreamShow13Bits(stream, &code);
+
+ /*intra = 0;*/
+
+ if (code >= 1024) tab = &PV_DCT3Dtab0[(code >> 6) - 16];
+ else
+ {
+ if (code >= 256) tab = &PV_DCT3Dtab1[(code >> 3) - 32];
+ else
+ {
+ if (code >= 16) tab = &PV_DCT3Dtab2[(code>>1) - 8];
+ else return PV_FAIL;
+ }
+ }
+
+ PV_BitstreamFlushBits(stream, tab->len + 1);
+ pTcoef->sign = (code >> (12 - tab->len)) & 1;
+ pTcoef->run = (uint)tab->run;//(tab->val >> 4) & 255;
+ pTcoef->level = (int)tab->level;//tab->val & 15;
+ pTcoef->last = (uint)tab->last;//(tab->val >> 12) & 1;
+
+ /* the following is modified for 3-mode escape -- */
+ if (((tab->run << 4) | (tab->level) | (tab->last << 12)) != VLC_ESCAPE_CODE) /* ESCAPE */
+ {
+ return PV_SUCCESS;
+ }
+ /* escape mode 4 - H.263 type */
+ pTcoef->last = pTcoef->sign; /* Last */
+ pTcoef->run = BitstreamReadBits16(stream, 6); /* Run */
+ pTcoef->level = (int) BitstreamReadBits16(stream, 8); /* Level */
+
+ if (pTcoef->level == 0)
+ {
+ return PV_FAIL;
+ }
+
+ if (pTcoef->level >= 128)
+ {
+ pTcoef->sign = 1;
+ pTcoef->level = 256 - pTcoef->level;
+ }
+ else
+ {
+ pTcoef->sign = 0;
+ }
+
+ if (pTcoef->level == 128)
+ {
+ code = BitstreamReadBits16(stream, 11); /* ANNEX_T */
+
+ code = (code >> 6 & 0x1F) | (code << 5 & 0x7ff);
+ if (code > 1024)
+ {
+ pTcoef->sign = 1;
+ pTcoef->level = (2048 - code);
+ }
+ else
+ {
+ pTcoef->sign = 0;
+ pTcoef->level = code;
+ }
+ }
+
+ return PV_SUCCESS;
+
+} /* VlcDecTCOEFShortHeader */
+
+
+PV_STATUS VlcDecTCOEFShortHeader_AnnexIT(BitstreamDecVideo *stream, Tcoef *pTcoef/*, int intra*/)
+{
+ uint code;
+ const VLCtab2 *tab;
+
+ BitstreamShow13Bits(stream, &code);
+
+ /*intra = 0;*/
+
+ if (code >= 1024) tab = &PV_DCT3Dtab6[(code >> 6) - 16];
+ else
+ {
+ if (code >= 256) tab = &PV_DCT3Dtab7[(code >> 3) - 32];
+ else
+ {
+ if (code >= 16) tab = &PV_DCT3Dtab8[(code>>1) - 8];
+ else return PV_FAIL;
+ }
+ }
+
+ PV_BitstreamFlushBits(stream, tab->len + 1);
+ pTcoef->sign = (code >> (12 - tab->len)) & 1;
+ pTcoef->run = (uint)tab->run;//(tab->val >> 4) & 255;
+ pTcoef->level = (int)tab->level;//tab->val & 15;
+ pTcoef->last = (uint)tab->last;//(tab->val >> 12) & 1;
+
+ /* the following is modified for 3-mode escape -- */
+ if (((tab->run << 6) | (tab->level) | (tab->last << 12)) != VLC_ESCAPE_CODE) /* ESCAPE */
+ {
+ return PV_SUCCESS;
+ }
+ /* escape mode 4 - H.263 type */
+ pTcoef->last = pTcoef->sign; /* Last */
+ pTcoef->run = BitstreamReadBits16(stream, 6); /* Run */
+ pTcoef->level = (int) BitstreamReadBits16(stream, 8); /* Level */
+
+ if (pTcoef->level == 0)
+ {
+ return PV_FAIL;
+ }
+
+ if (pTcoef->level >= 128)
+ {
+ pTcoef->sign = 1;
+ pTcoef->level = 256 - pTcoef->level;
+ }
+ else
+ {
+ pTcoef->sign = 0;
+ }
+
+ if (pTcoef->level == 128)
+ {
+ code = BitstreamReadBits16(stream, 11); /* ANNEX_T */
+
+ code = (code >> 6 & 0x1F) | (code << 5 & 0x7ff);
+ if (code > 1024)
+ {
+ pTcoef->sign = 1;
+ pTcoef->level = (2048 - code);
+ }
+ else
+ {
+ pTcoef->sign = 0;
+ pTcoef->level = code;
+ }
+ }
+
+
+ return PV_SUCCESS;
+
+} /* VlcDecTCOEFShortHeader_AnnexI */
+#endif
+/***********************************************************CommentBegin******
+* 3/30/2000 : initial modification to the new PV-Decoder Lib
+* format and the change of error-handling method.
+* The coefficient is now returned thru a pre-
+* initialized parameters for speedup.
+*
+***********************************************************CommentEnd********/
+
+
+PV_STATUS RvlcDecTCOEFInter(BitstreamDecVideo *stream, Tcoef *pTcoef)
+{
+ uint code, mask;
+ const VLCtab2 *tab2;
+ int count, len, num[2] = {0, 0} /* 01/30/01 */;
+
+ mask = 0x4000; /* mask 100000000000000 */
+ BitstreamShow15Bits(stream, &code); /* 03/07/01 */
+
+ len = 1;
+
+ // 09/20/99 Escape mode
+ /// Bitstream Exchange
+ if (code < 2048)
+ {
+ PV_BitstreamFlushBits(stream, 5);
+ pTcoef->last = BitstreamRead1Bits_INLINE(stream);
+ pTcoef->run = BitstreamReadBits16_INLINE(stream, 6);
+ // 09/20/99 New marker bit
+ PV_BitstreamFlushBits(stream, 1);
+ // 09/20/99 The length for LEVEL used to be 7 in the old version
+ pTcoef->level = (int)(BitstreamReadBits16_INLINE(stream, 12) >> 1);
+ // 09/20/99 Another new marker bit
+// PV_BitstreamFlushBitsCheck(stream, 1);
+ pTcoef->sign = BitstreamReadBits16_INLINE(stream, 5) & 0x1; /* fix 3/13/01 */
+ return PV_SUCCESS;
+ }
+
+ if (code & mask)
+ {
+ count = 1;
+ while (mask && count > 0) /* fix 3/28/01 */
+ {
+ mask = mask >> 1;
+ if (code & mask)
+ count--;
+ else
+ num[0]++; /* number of zeros in the middle */
+ len++;
+ }
+ }
+ else
+ {
+ count = 2;
+ while (mask && count > 0) /* fix 3/28/01 */
+ {
+ mask = mask >> 1;
+ if (!(code & mask))
+ count--;
+ else
+ num[count-1]++; /* number of ones in the middle */
+ len++;
+ }
+ }
+
+ code = code & 0x7fff;
+ code = code >> (15 - (len + 1));
+
+ /* 1/30/01, add fast decoding algorithm here */
+ /* code is in two forms : 0xxxx0xxx00 or 0xxx0xxx01
+ num[1] and num[0] x
+ or : 1xxxxx10 or 1xxxxx11
+ num[0] x */
+
+ /* len+1 is the length of the above */
+
+ if (num[1] > 10 || num[0] > 11) /* invalid RVLC code */
+ return PV_FAIL;
+
+ if (code&(1 << len))
+ tab2 = RvlcDCTtabInter + 146 + (num[0] << 1) + (code & 1);
+ else
+ tab2 = RvlcDCTtabInter + ptrRvlcTab[num[1]] + (num[0] << 1) + (code & 1);
+
+ PV_BitstreamFlushBits(stream, (int) tab2->len);
+ pTcoef->run = (uint)tab2->run;//(tab->val >> 8) & 255;
+ pTcoef->level = (int)tab2->level;//tab->val & 255;
+ pTcoef->last = (uint)tab2->last;//(tab->val >> 16) & 1;
+
+ pTcoef->sign = BitstreamRead1Bits_INLINE(stream);
+ return PV_SUCCESS;
+} /* RvlcDecTCOEFInter */
+
+PV_STATUS RvlcDecTCOEFIntra(BitstreamDecVideo *stream, Tcoef *pTcoef)
+{
+ uint code, mask;
+ const VLCtab2 *tab2;
+ int count, len, num[2] = {0, 0} /* 01/30/01 */;
+
+ mask = 0x4000; /* mask 100000000000000 */
+ BitstreamShow15Bits(stream, &code);
+
+ len = 1;
+
+ // 09/20/99 Escape mode
+ /// Bitstream Exchange
+ if (code < 2048)
+ {
+ PV_BitstreamFlushBits(stream, 5);
+ pTcoef->last = BitstreamRead1Bits_INLINE(stream);
+ pTcoef->run = BitstreamReadBits16_INLINE(stream, 6);
+ // 09/20/99 New marker bit
+ PV_BitstreamFlushBits(stream, 1);
+ // 09/20/99 The length for LEVEL used to be 7 in the old version
+ pTcoef->level = (int)(BitstreamReadBits16_INLINE(stream, 12) >> 1);
+ // 09/20/99 Another new marker bit
+// PV_BitstreamFlushBitsCheck(stream, 1);
+ pTcoef->sign = BitstreamReadBits16_INLINE(stream, 5) & 0x1; /* fix 03/13/01 */
+ return PV_SUCCESS;
+ }
+
+ if (code & mask)
+ {
+ count = 1;
+ while (mask && count > 0) /* fix 03/28/01 */
+ {
+ mask = mask >> 1;
+ if (code & mask)
+ count--;
+ else
+ num[0]++; /* number of zeros in the middle */
+ len++;
+ }
+ }
+ else
+ {
+ count = 2;
+ while (mask && count > 0) /* fix 03/28/01 */
+ {
+ mask = mask >> 1;
+ if (!(code & mask))
+ count--;
+ else
+ num[count-1]++; /* number of ones in the middle */
+ len++;
+ }
+ }
+
+ code = code & 0x7fff;
+ code = code >> (15 - (len + 1));
+
+ /* 1/30/01, add fast decoding algorithm here */
+ /* code is in two forms : 0xxxx0xxx00 or 0xxx0xxx01
+ num[1] and num[0] x
+ or : 1xxxxx10 or 1xxxxx11
+ num[0] x */
+
+ /* len+1 is the length of the above */
+
+ if (num[1] > 10 || num[0] > 11) /* invalid RVLC code */
+ return PV_FAIL;
+
+ if (code & (1 << len))
+ tab2 = RvlcDCTtabIntra + 146 + (num[0] << 1) + (code & 1);
+ else
+ tab2 = RvlcDCTtabIntra + ptrRvlcTab[num[1]] + (num[0] << 1) + (code & 1);
+
+ PV_BitstreamFlushBits(stream, (int) tab2->len);
+ pTcoef->run = (uint)tab2->run;//(tab->val >> 8) & 255;
+ pTcoef->level = (int)tab2->level;//tab->val & 255;
+ pTcoef->last = (uint)tab2->last;//(tab->val >> 16) & 1;
+
+ pTcoef->sign = BitstreamRead1Bits_INLINE(stream);
+ return PV_SUCCESS;
+} /* RvlcDecTCOEFIntra */
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.h b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.h
new file mode 100644
index 0000000..a804606
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_decode.h
@@ -0,0 +1,122 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+-------------------------------------------------------------------
+ MPEG-4 Simple Profile Video Decoder
+-------------------------------------------------------------------
+*
+* This software module was originally developed by
+*
+* Paulo Nunes (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) 1996
+*
+*****************************************************************************/
+
+/***********************************************************HeaderBegin*******
+*
+* File: vlc_dec.h
+*
+* Author: Paulo Nunes (IST) - Paulo.Nunes@lx.it.pt
+* Created:
+*
+* Description: This is the header file for the "vlcdec" module.
+*
+* Notes:
+*
+* Modified: 9-May-96 Paulo Nunes: Reformatted. New headers.
+*
+* ================= PacketVideo Modification ================================
+*
+* 3/30/00 : initial modification to the
+* new PV-Decoder Lib format.
+*
+***********************************************************CommentEnd********/
+
+
+#ifndef _VLCDECODE_H_
+#define _VLCDECODE_H_
+
+#include "mp4lib_int.h"
+
+#define VLC_ERROR_DETECTED(x) ((x) < 0)
+#define VLC_IO_ERROR -1
+#define VLC_CODE_ERROR -2
+#define VLC_MB_STUFFING -4
+#define VLC_NO_LAST_BIT -5
+
+#define VLC_ESCAPE_CODE 7167
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+ PV_STATUS DecodeUserData(BitstreamDecVideo *stream);
+ PV_STATUS PV_GetMBvectors(VideoDecData *, uint mode);
+ PV_STATUS PV_DecodeMBVec(BitstreamDecVideo *stream, MOT *mv_x, MOT *mv_y, int f_code_f);
+ PV_STATUS PV_DeScaleMVD(int f_code, int residual, int vlc_code_mag, MOT *vector);
+
+ PV_STATUS PV_VlcDecMV(BitstreamDecVideo *stream, int *mv);
+ int PV_VlcDecMCBPC_com_intra(BitstreamDecVideo *stream);
+ int PV_VlcDecMCBPC_com_inter(BitstreamDecVideo *stream);
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ int PV_VlcDecMCBPC_com_inter_H263(BitstreamDecVideo *stream);
+ PV_STATUS VlcDecTCOEFShortHeader_AnnexI(BitstreamDecVideo *stream, Tcoef *pTcoef);
+ PV_STATUS VlcDecTCOEFShortHeader_AnnexT(BitstreamDecVideo *stream, Tcoef *pTcoef); /* ANNEX_T */
+ PV_STATUS VlcDecTCOEFShortHeader_AnnexIT(BitstreamDecVideo *stream, Tcoef *pTcoef);
+#endif
+ int PV_VlcDecCBPY(BitstreamDecVideo *stream, int intra);
+
+ PV_STATUS VlcDecTCOEFIntra(BitstreamDecVideo *stream, Tcoef *pTcoef);
+ PV_STATUS VlcDecTCOEFInter(BitstreamDecVideo *stream, Tcoef *pTcoef);
+ PV_STATUS VlcDecTCOEFShortHeader(BitstreamDecVideo *stream, Tcoef *pTcoef);
+ PV_STATUS RvlcDecTCOEFIntra(BitstreamDecVideo *stream, Tcoef *pTcoef);
+ PV_STATUS RvlcDecTCOEFInter(BitstreamDecVideo *stream, Tcoef *pTcoef);
+ PV_STATUS PV_VlcDecIntraDCPredSize(BitstreamDecVideo *stream, int compnum, uint *DC_size);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_dequant.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_dequant.cpp
new file mode 100644
index 0000000..db13a48
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_dequant.cpp
@@ -0,0 +1,1152 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_lib.h"
+#include "vlc_decode.h"
+#include "zigzag.h"
+
+
+typedef PV_STATUS(*VlcDecFuncP)(BitstreamDecVideo *stream, Tcoef *pTcoef);
+static const uint8 AC_rowcol[64] = { 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1,
+ };
+static const uint8 mask[8] = /* for fast bitmap */
+ {128, 64, 32, 16, 8, 4, 2, 1};
+
+
+
+/***********************************************************CommentBegin******
+*
+* -- VlcDequantMpegBlock -- Decodes the DCT coefficients of one 8x8 block and perform
+ dequantization using Mpeg mode.
+ Date: 08/08/2000
+
+ Modified: 3/21/01
+ Added pre IDCT clipping, new ACDC prediction structure, ACDC prediction clipping,
+ 16-bit int case, removed multiple zigzaging
+******************************************************************************/
+
+#ifdef PV_SUPPORT_MAIN_PROFILE
+int VlcDequantMpegIntraBlock(void *vid, int comp, int switched,
+ uint8 *bitmapcol, uint8 *bitmaprow)
+{
+ VideoDecData *video = (VideoDecData*) vid;
+ Vol *currVol = video->vol[video->currLayer];
+ BitstreamDecVideo *stream = video->bitstream;
+ int16 *datablock = video->mblock->block[comp]; /* 10/20/2000, assume it has been reset of all-zero !!!*/
+ int mbnum = video->mbnum;
+ uint CBP = video->headerInfo.CBP[mbnum];
+ int QP = video->QPMB[mbnum];
+ typeDCStore *DC = video->predDC + mbnum;
+ int x_pos = video->mbnum_col;
+ typeDCACStore *DCAC_row = video->predDCAC_row + x_pos;
+ typeDCACStore *DCAC_col = video->predDCAC_col;
+ uint ACpred_flag = (uint) video->acPredFlag[mbnum];
+
+ /*** VLC *****/
+ int i, j, k;
+ Tcoef run_level;
+ int last, return_status;
+ VlcDecFuncP vlcDecCoeff;
+ int direction;
+ const int *inv_zigzag;
+ /*** Quantizer ****/
+ int dc_scaler;
+ int sum;
+ int *qmat;
+ int32 temp;
+
+ const int B_Xtab[6] = {0, 1, 0, 1, 2, 3};
+ const int B_Ytab[6] = {0, 0, 1, 1, 2, 3};
+
+ int16 *dcac_row, *dcac_col;
+
+ dcac_row = (*DCAC_row)[B_Xtab[comp]];
+ dcac_col = (*DCAC_col)[B_Ytab[comp]];
+
+
+ i = 1 - switched;
+
+#ifdef FAST_IDCT
+ *((uint32*)bitmapcol) = *((uint32*)(bitmapcol + 4)) = 0;
+ *bitmaprow = 0;
+#endif
+
+
+ /* select which Huffman table to be used */
+ vlcDecCoeff = video->vlcDecCoeffIntra;
+
+ dc_scaler = (comp < 4) ? video->mblock->DCScalarLum : video->mblock->DCScalarChr;
+
+ /* enter the zero run decoding loop */
+ sum = 0;
+ qmat = currVol->iqmat;
+
+ /* perform only VLC decoding */
+ /* We cannot do DCACrecon before VLC decoding. 10/17/2000 */
+ doDCACPrediction(video, comp, datablock, &direction);
+ if (!ACpred_flag) direction = 0;
+ inv_zigzag = zigzag_inv + (ACpred_flag << 6) + (direction << 6);
+ if (CBP & (1 << (5 - comp)))
+ {
+ do
+ {
+ return_status = (*vlcDecCoeff)(stream, &run_level);
+ if (return_status != PV_SUCCESS)
+ {
+ last = 1;/* 11/1/2000 let it slips undetected, just like
+ in original version */
+ i = VLC_ERROR;
+ ACpred_flag = 0; /* no of coefficients should not get reset 03/07/2002 */
+ break;
+ }
+
+ i += run_level.run;
+ last = run_level.last;
+ if (i >= 64)
+ {
+ /* i = NCOEFF_BLOCK; */ /* 11/1/00 */
+ ACpred_flag = 0; /* no of coefficients should not get reset 03/07/2002 */
+ i = VLC_NO_LAST_BIT;
+ last = 1;
+ break;
+ }
+
+ k = inv_zigzag[i];
+
+ if (run_level.sign == 1)
+ {
+ datablock[k] -= run_level.level;
+ }
+ else
+ {
+ datablock[k] += run_level.level;
+ }
+
+ if (AC_rowcol[k])
+ {
+ temp = (int32)datablock[k] * qmat[k] * QP;
+ temp = (temp + (0x7 & (temp >> 31))) >> 3;
+ if (temp > 2047) temp = 2047;
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int) temp;
+
+#ifdef FAST_IDCT
+ bitmapcol[k&0x7] |= mask[k>>3];
+#endif
+ sum ^= temp;
+ }
+
+ i++;
+ }
+ while (!last);
+
+ }
+ else
+ {
+ i = 1; /* 04/26/01 needed for switched case */
+ }
+ ///// NEED TO DEQUANT THOSE PREDICTED AC COEFF
+ /* dequantize the rest of AC predicted coeff that haven't been dequant */
+ if (ACpred_flag)
+ {
+
+ i = NCOEFF_BLOCK; /* otherwise, FAST IDCT won't work correctly, 10/18/2000 */
+
+ if (!direction) /* check vertical */
+ {
+ dcac_row[0] = datablock[1];
+ dcac_row[1] = datablock[2];
+ dcac_row[2] = datablock[3];
+ dcac_row[3] = datablock[4];
+ dcac_row[4] = datablock[5];
+ dcac_row[5] = datablock[6];
+ dcac_row[6] = datablock[7];
+
+ for (j = 0, k = 8; k < 64; k += 8, j++)
+ {
+ if (dcac_col[j] = datablock[k])
+ { /* ACDC clipping 03/26/01 */
+ if (datablock[k] > 2047) dcac_col[j] = 2047;
+ else if (datablock[k] < -2048) dcac_col[j] = -2048;
+
+ temp = (int32)dcac_col[j] * qmat[k] * QP;
+ temp = (temp + (0x7 & (temp >> 31))) >> 3; /* 03/26/01*/
+ if (temp > 2047) temp = 2047;
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int)temp;
+ sum ^= temp; /* 7/5/01 */
+#ifdef FAST_IDCT
+ bitmapcol[0] |= mask[k>>3];
+#endif
+
+ }
+ }
+ for (k = 1; k < 8; k++)
+ {
+ if (datablock[k])
+ {
+ temp = (int32)datablock[k] * qmat[k] * QP;
+ temp = (temp + (0x7 & (temp >> 31))) >> 3; /* 03/26/01*/
+ if (temp > 2047) temp = 2047;
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int)temp;
+ sum ^= temp; /* 7/5/01 */
+#ifdef FAST_IDCT
+ bitmapcol[k] |= 128;
+#endif
+
+ }
+ }
+
+ }
+ else
+ {
+
+ dcac_col[0] = datablock[8];
+ dcac_col[1] = datablock[16];
+ dcac_col[2] = datablock[24];
+ dcac_col[3] = datablock[32];
+ dcac_col[4] = datablock[40];
+ dcac_col[5] = datablock[48];
+ dcac_col[6] = datablock[56];
+
+
+ for (j = 0, k = 1; k < 8; k++, j++)
+ {
+ if (dcac_row[j] = datablock[k])
+ { /* ACDC clipping 03/26/01 */
+ if (datablock[k] > 2047) dcac_row[j] = 2047;
+ else if (datablock[k] < -2048) dcac_row[j] = -2048;
+
+ temp = (int32)dcac_row[j] * qmat[k] * QP;
+ temp = (temp + (0x7 & (temp >> 31))) >> 3; /* 03/26/01 */
+ if (temp > 2047) temp = 2047;
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int)temp;
+ sum ^= temp;
+#ifdef FAST_IDCT
+ bitmapcol[k] |= 128;
+#endif
+
+ }
+ }
+
+ for (k = 8; k < 64; k += 8)
+ {
+ if (datablock[k])
+ {
+ temp = (int32)datablock[k] * qmat[k] * QP;
+ temp = (temp + (0x7 & (temp >> 31))) >> 3; /* 03/26/01 */
+ if (temp > 2047) temp = 2047;
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int)temp;
+ sum ^= temp;
+#ifdef FAST_IDCT
+ bitmapcol[0] |= mask[k>>3];
+#endif
+ }
+ }
+
+ }
+ }
+ else
+ {
+
+ /* Store the qcoeff-values needed later for prediction */
+
+ dcac_row[0] = datablock[1]; /* ACDC, no need for clipping */
+ dcac_row[1] = datablock[2];
+ dcac_row[2] = datablock[3];
+ dcac_row[3] = datablock[4];
+ dcac_row[4] = datablock[5];
+ dcac_row[5] = datablock[6];
+ dcac_row[6] = datablock[7];
+
+ dcac_col[0] = datablock[8];
+ dcac_col[1] = datablock[16];
+ dcac_col[2] = datablock[24];
+ dcac_col[3] = datablock[32];
+ dcac_col[4] = datablock[40];
+ dcac_col[5] = datablock[48];
+ dcac_col[6] = datablock[56];
+
+ for (k = 1; k < 8; k++)
+ {
+ if (datablock[k])
+ {
+ temp = (int32)datablock[k] * qmat[k] * QP;
+ temp = (temp + (0x7 & (temp >> 31))) >> 3; /* 03/26/01*/
+ if (temp > 2047) temp = 2047;
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int)temp;
+ sum ^= temp; /* 7/5/01 */
+#ifdef FAST_IDCT
+ bitmapcol[k] |= 128;
+#endif
+
+ }
+ }
+ for (k = 8; k < 64; k += 8)
+ {
+ if (datablock[k])
+ {
+ temp = (int32)datablock[k] * qmat[k] * QP;
+ temp = (temp + (0x7 & (temp >> 31))) >> 3; /* 03/26/01 */
+ if (temp > 2047) temp = 2047;
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int)temp;
+ sum ^= temp;
+#ifdef FAST_IDCT
+ bitmapcol[0] |= mask[k>>3];
+#endif
+ }
+ }
+
+ }
+
+
+
+ if (datablock[0])
+ {
+ temp = (int32)datablock[0] * dc_scaler;
+ if (temp > 2047) temp = 2047; /* 03/14/01 */
+ else if (temp < -2048) temp = -2048;
+ datablock[0] = (int)temp;
+ sum ^= temp;
+#ifdef FAST_IDCT
+ bitmapcol[0] |= 128;
+#endif
+ }
+
+ if ((sum & 1) == 0)
+ {
+ datablock[63] = datablock[63] ^ 0x1;
+#ifdef FAST_IDCT /* 7/5/01, need to update bitmap */
+ if (datablock[63])
+ bitmapcol[7] |= 1;
+#endif
+ i = (-64 & i) | NCOEFF_BLOCK; /* if i > -1 then i is set to NCOEFF_BLOCK */
+ }
+
+
+#ifdef FAST_IDCT
+ if (i > 10)
+ {
+ for (k = 1; k < 4; k++)
+ {
+ if (bitmapcol[k] != 0)
+ {
+ (*bitmaprow) |= mask[k];
+ }
+ }
+ }
+#endif
+
+ /* Store the qcoeff-values needed later for prediction */
+ (*DC)[comp] = datablock[0];
+ return i;
+
+}
+
+
+/***********************************************************CommentBegin******
+*
+* -- VlcDequantMpegInterBlock -- Decodes the DCT coefficients of one 8x8 block and perform
+ dequantization using Mpeg mode for INTER block.
+ Date: 08/08/2000
+ Modified: 3/21/01
+ clean up, added clipping, 16-bit int case, new ACDC prediction
+******************************************************************************/
+
+
+int VlcDequantMpegInterBlock(void *vid, int comp,
+ uint8 *bitmapcol, uint8 *bitmaprow)
+{
+ VideoDecData *video = (VideoDecData*) vid;
+ BitstreamDecVideo *stream = video->bitstream;
+ Vol *currVol = video->vol[video->currLayer];
+ int16 *datablock = video->mblock->block[comp]; /* 10/20/2000, assume it has been reset of all-zero !!!*/
+ int mbnum = video->mbnum;
+ int QP = video->QPMB[mbnum];
+ /*** VLC *****/
+ int i, k;
+ Tcoef run_level;
+ int last, return_status;
+ VlcDecFuncP vlcDecCoeff;
+
+ /*** Quantizer ****/
+ int sum;
+ int *qmat;
+
+ int32 temp;
+
+ i = 0 ;
+
+#ifdef FAST_IDCT
+ *((uint32*)bitmapcol) = *((uint32*)(bitmapcol + 4)) = 0;
+ *bitmaprow = 0;
+#endif
+
+ /* select which Huffman table to be used */
+ vlcDecCoeff = video->vlcDecCoeffInter;
+
+ /* enter the zero run decoding loop */
+ sum = 0;
+ qmat = currVol->niqmat;
+ do
+ {
+ return_status = (*vlcDecCoeff)(stream, &run_level);
+ if (return_status != PV_SUCCESS)
+ {
+ last = 1;/* 11/1/2000 let it slips undetected, just like
+ in original version */
+ i = VLC_ERROR;
+ sum = 1; /* no of coefficients should not get reset 03/07/2002 */
+ break;
+ }
+
+ i += run_level.run;
+ last = run_level.last;
+ if (i >= 64)
+ {
+ /* i = NCOEFF_BLOCK; */ /* 11/1/00 */
+ //return VLC_NO_LAST_BIT;
+ i = VLC_NO_LAST_BIT;
+ last = 1;
+ sum = 1; /* no of coefficients should not get reset 03/07/2002 */
+ break;
+ }
+
+ k = zigzag_inv[i];
+
+ if (run_level.sign == 1)
+ {
+ temp = (-(int32)(2 * run_level.level + 1) * qmat[k] * QP + 15) >> 4; /* 03/23/01 */
+ if (temp < -2048) temp = - 2048;
+ }
+ else
+ {
+ temp = ((int32)(2 * run_level.level + 1) * qmat[k] * QP) >> 4; /* 03/23/01 */
+ if (temp > 2047) temp = 2047;
+ }
+
+ datablock[k] = (int)temp;
+
+#ifdef FAST_IDCT
+ bitmapcol[k&0x7] |= mask[k>>3];
+#endif
+ sum ^= temp;
+
+ i++;
+ }
+ while (!last);
+
+ if ((sum & 1) == 0)
+ {
+ datablock[63] = datablock[63] ^ 0x1;
+#ifdef FAST_IDCT /* 7/5/01, need to update bitmap */
+ if (datablock[63])
+ bitmapcol[7] |= 1;
+#endif
+ i = NCOEFF_BLOCK;
+ }
+
+
+#ifdef FAST_IDCT
+ if (i > 10)
+ {
+ for (k = 1; k < 4; k++) /* 07/19/01 */
+ {
+ if (bitmapcol[k] != 0)
+ {
+ (*bitmaprow) |= mask[k];
+ }
+ }
+ }
+#endif
+
+ return i;
+}
+#endif
+/***********************************************************CommentBegin******
+*
+* -- VlcDequantIntraH263Block -- Decodes the DCT coefficients of one 8x8 block and perform
+ dequantization in H.263 mode for INTRA block.
+ Date: 08/08/2000
+ Modified: 3/21/01
+ clean up, added clipping, 16-bit int case, removed multiple zigzaging
+******************************************************************************/
+
+
+int VlcDequantH263IntraBlock(VideoDecData *video, int comp, int switched,
+ uint8 *bitmapcol, uint8 *bitmaprow)
+{
+ BitstreamDecVideo *stream = video->bitstream;
+ int16 *datablock = video->mblock->block[comp]; /* 10/20/2000, assume it has been reset of all-zero !!!*/
+ int32 temp;
+ int mbnum = video->mbnum;
+ uint CBP = video->headerInfo.CBP[mbnum];
+ int QP = video->QPMB[mbnum];
+ typeDCStore *DC = video->predDC + mbnum;
+ int x_pos = video->mbnum_col;
+ typeDCACStore *DCAC_row = video->predDCAC_row + x_pos;
+ typeDCACStore *DCAC_col = video->predDCAC_col;
+ uint ACpred_flag = (uint) video->acPredFlag[mbnum];
+
+ /*** VLC *****/
+ int i, j, k;
+ Tcoef run_level;
+ int last, return_status;
+ VlcDecFuncP vlcDecCoeff;
+ int direction;
+ const int *inv_zigzag;
+
+ /*** Quantizer ****/
+ int dc_scaler;
+ int sgn_coeff;
+
+
+
+ const int B_Xtab[6] = {0, 1, 0, 1, 2, 3};
+ const int B_Ytab[6] = {0, 0, 1, 1, 2, 3};
+
+ int16 *dcac_row, *dcac_col;
+
+ dcac_row = (*DCAC_row)[B_Xtab[comp]];
+ dcac_col = (*DCAC_col)[B_Ytab[comp]];
+
+#ifdef FAST_IDCT
+ *((uint32*)bitmapcol) = *((uint32*)(bitmapcol + 4)) = 0;
+ *bitmaprow = 0;
+#endif
+ /* select which Huffman table to be used */
+ vlcDecCoeff = video->vlcDecCoeffIntra;
+
+ dc_scaler = (comp < 4) ? video->mblock->DCScalarLum : video->mblock->DCScalarChr;
+
+ /* perform only VLC decoding */
+ doDCACPrediction(video, comp, datablock, &direction);
+ if (!ACpred_flag) direction = 0;
+
+ inv_zigzag = zigzag_inv + (ACpred_flag << 6) + (direction << 6); /* 04/17/01 */
+
+ i = 1;
+ if (CBP & (1 << (5 - comp)))
+ {
+ i = 1 - switched;
+ do
+ {
+ return_status = (*vlcDecCoeff)(stream, &run_level);
+ if (return_status != PV_SUCCESS)
+ {
+ last = 1;/* 11/1/2000 let it slips undetected, just like
+ in original version */
+ i = VLC_ERROR;
+ ACpred_flag = 0; /* no of coefficients should not get reset 03/07/2002 */
+ break;
+ }
+
+ i += run_level.run;
+ last = run_level.last;
+ if (i >= 64)
+ {
+ ACpred_flag = 0; /* no of coefficients should not get reset 03/07/2002 */
+ i = VLC_NO_LAST_BIT;
+ last = 1;
+ break;
+ }
+
+ k = inv_zigzag[i];
+
+ if (run_level.sign == 1)
+ {
+ datablock[k] -= run_level.level;
+ sgn_coeff = -1;
+ }
+ else
+ {
+ datablock[k] += run_level.level;
+ sgn_coeff = 1;
+ }
+
+
+ if (AC_rowcol[k]) /* 10/25/2000 */
+ {
+ temp = (int32)QP * (2 * datablock[k] + sgn_coeff) - sgn_coeff + (QP & 1) * sgn_coeff;
+ if (temp > 2047) temp = 2047; /* 03/14/01 */
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int16) temp;
+
+#ifdef FAST_IDCT
+ bitmapcol[k&0x7] |= mask[k>>3];
+#endif
+ }
+
+ i++;
+ }
+ while (!last);
+
+ }
+
+ ///// NEED TO DEQUANT THOSE PREDICTED AC COEFF
+ /* dequantize the rest of AC predicted coeff that haven't been dequant */
+ if (ACpred_flag)
+ {
+
+ i = NCOEFF_BLOCK; /* otherwise, FAST IDCT won't work correctly, 10/18/2000 */
+
+ if (!direction) /* check vertical */
+ {
+
+ dcac_row[0] = datablock[1];
+ dcac_row[1] = datablock[2];
+ dcac_row[2] = datablock[3];
+ dcac_row[3] = datablock[4];
+ dcac_row[4] = datablock[5];
+ dcac_row[5] = datablock[6];
+ dcac_row[6] = datablock[7];
+
+ for (j = 0, k = 8; k < 64; k += 8, j++)
+ {
+ dcac_col[j] = datablock[k];
+ if (dcac_col[j])
+ {
+ if (datablock[k] > 0)
+ {
+ if (datablock[k] > 2047) dcac_col[j] = 2047;
+ sgn_coeff = 1;
+ }
+ else
+ {
+ if (datablock[k] < -2048) dcac_col[j] = -2048;
+ sgn_coeff = -1;
+ }
+ temp = (int32)QP * (2 * datablock[k] + sgn_coeff) - sgn_coeff + (QP & 1) * sgn_coeff;
+ if (temp > 2047) temp = 2047; /* 03/14/01 */
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int16) temp;
+#ifdef FAST_IDCT
+ bitmapcol[0] |= mask[k>>3];
+#endif
+
+ }
+ }
+
+ for (k = 1; k < 8; k++)
+ {
+ if (datablock[k])
+ {
+ sgn_coeff = (datablock[k] > 0) ? 1 : -1;
+ temp = (int32)QP * (2 * datablock[k] + sgn_coeff) - sgn_coeff + (QP & 1) * sgn_coeff;
+ if (temp > 2047) temp = 2047; /* 03/14/01 */
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int16) temp;
+#ifdef FAST_IDCT
+ bitmapcol[k] |= 128;
+#endif
+
+ }
+ }
+ }
+ else
+ {
+
+ dcac_col[0] = datablock[8];
+ dcac_col[1] = datablock[16];
+ dcac_col[2] = datablock[24];
+ dcac_col[3] = datablock[32];
+ dcac_col[4] = datablock[40];
+ dcac_col[5] = datablock[48];
+ dcac_col[6] = datablock[56];
+
+
+ for (j = 0, k = 1; k < 8; k++, j++)
+ {
+ dcac_row[j] = datablock[k];
+ if (dcac_row[j])
+ {
+ if (datablock[k] > 0)
+ {
+ if (datablock[k] > 2047) dcac_row[j] = 2047;
+ sgn_coeff = 1;
+ }
+ else
+ {
+ if (datablock[k] < -2048) dcac_row[j] = -2048;
+ sgn_coeff = -1;
+ }
+
+ temp = (int32)QP * (2 * datablock[k] + sgn_coeff) - sgn_coeff + (QP & 1) * sgn_coeff;
+ if (temp > 2047) temp = 2047; /* 03/14/01 */
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int) temp;
+#ifdef FAST_IDCT
+ bitmapcol[k] |= 128;
+#endif
+
+ }
+ }
+ for (k = 8; k < 64; k += 8)
+ {
+ if (datablock[k])
+ {
+ sgn_coeff = (datablock[k] > 0) ? 1 : -1;
+ temp = (int32)QP * (2 * datablock[k] + sgn_coeff) - sgn_coeff + (QP & 1) * sgn_coeff;
+ if (temp > 2047) temp = 2047; /* 03/14/01 */
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int16) temp;
+#ifdef FAST_IDCT
+ bitmapcol[0] |= mask[k>>3];
+#endif
+ }
+ }
+
+ }
+ }
+ else
+ {
+ dcac_row[0] = datablock[1];
+ dcac_row[1] = datablock[2];
+ dcac_row[2] = datablock[3];
+ dcac_row[3] = datablock[4];
+ dcac_row[4] = datablock[5];
+ dcac_row[5] = datablock[6];
+ dcac_row[6] = datablock[7];
+
+ dcac_col[0] = datablock[8];
+ dcac_col[1] = datablock[16];
+ dcac_col[2] = datablock[24];
+ dcac_col[3] = datablock[32];
+ dcac_col[4] = datablock[40];
+ dcac_col[5] = datablock[48];
+ dcac_col[6] = datablock[56];
+
+ for (k = 1; k < 8; k++)
+ {
+ if (datablock[k])
+ {
+ sgn_coeff = (datablock[k] > 0) ? 1 : -1;
+ temp = (int32)QP * (2 * datablock[k] + sgn_coeff) - sgn_coeff + (QP & 1) * sgn_coeff;
+ if (temp > 2047) temp = 2047; /* 03/14/01 */
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int16) temp;
+#ifdef FAST_IDCT
+ bitmapcol[k] |= 128;
+#endif
+ }
+ }
+ for (k = 8; k < 64; k += 8)
+ {
+ if (datablock[k])
+ {
+ sgn_coeff = (datablock[k] > 0) ? 1 : -1;
+ temp = (int32)QP * (2 * datablock[k] + sgn_coeff) - sgn_coeff + (QP & 1) * sgn_coeff;
+ if (temp > 2047) temp = 2047; /* 03/14/01 */
+ else if (temp < -2048) temp = -2048;
+ datablock[k] = (int16) temp;
+#ifdef FAST_IDCT
+ bitmapcol[0] |= mask[k>>3];
+#endif
+ }
+ }
+ }
+ if (datablock[0])
+ {
+#ifdef FAST_IDCT
+ bitmapcol[0] |= 128;
+#endif
+
+ temp = (int32)datablock[0] * dc_scaler;
+ if (temp > 2047) temp = 2047; /* 03/14/01 */
+ else if (temp < -2048) temp = -2048;
+ datablock[0] = (int16)temp;
+ }
+
+
+#ifdef FAST_IDCT
+ if (i > 10)
+ {
+ for (k = 1; k < 4; k++) /* if i > 10 then k = 0 does not matter */
+ {
+ if (bitmapcol[k] != 0)
+ {
+ (*bitmaprow) |= mask[k]; /* (1<<(7-i)); */
+ }
+ }
+ }
+#endif
+
+ /* Store the qcoeff-values needed later for prediction */
+ (*DC)[comp] = datablock[0];
+ return i;
+}
+
+int VlcDequantH263IntraBlock_SH(VideoDecData *video, int comp, uint8 *bitmapcol, uint8 *bitmaprow)
+{
+ BitstreamDecVideo *stream = video->bitstream;
+ int16 *datablock = video->mblock->block[comp]; /*, 10/20/2000, assume it has been reset of all-zero !!!*/
+ int32 temp;
+ int mbnum = video->mbnum;
+ uint CBP = video->headerInfo.CBP[mbnum];
+ int16 QP = video->QPMB[mbnum];
+ typeDCStore *DC = video->predDC + mbnum;
+ int x_pos = video->mbnum_col;
+ typeDCACStore *DCAC_row = video->predDCAC_row + x_pos;
+ typeDCACStore *DCAC_col = video->predDCAC_col;
+ uint ACpred_flag = (uint) video->acPredFlag[mbnum];
+
+ /*** VLC *****/
+ int i, k;
+ Tcoef run_level;
+ int last, return_status;
+ VlcDecFuncP vlcDecCoeff;
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ int direction;
+ const int *inv_zigzag;
+#endif
+ /*** Quantizer ****/
+
+
+
+ const int B_Xtab[6] = {0, 1, 0, 1, 2, 3};
+ const int B_Ytab[6] = {0, 0, 1, 1, 2, 3};
+
+ int16 *dcac_row, *dcac_col;
+
+ dcac_row = (*DCAC_row)[B_Xtab[comp]];
+ dcac_col = (*DCAC_col)[B_Ytab[comp]];
+ i = 1;
+
+#ifdef FAST_IDCT
+ *((uint32*)bitmapcol) = *((uint32*)(bitmapcol + 4)) = 0;
+ *bitmaprow = 0;
+#endif
+
+ /* select which Huffman table to be used */
+ vlcDecCoeff = video->vlcDecCoeffIntra;
+
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ if (comp > 3) /* ANNEX_T */
+ {
+ QP = video->QP_CHR;
+ }
+ if (!video->advanced_INTRA)
+ {
+#endif
+
+ if ((CBP & (1 << (5 - comp))) == 0)
+ {
+#ifdef FAST_IDCT
+ bitmapcol[0] = 128;
+ bitmapcol[1] = bitmapcol[2] = bitmapcol[3] = bitmapcol[4] = bitmapcol[5] = bitmapcol[6] = bitmapcol[7] = 0;
+#endif
+ datablock[0] <<= 3; /* no need to clip */
+ return 1;//ncoeffs;
+ }
+ else
+ {
+ /* enter the zero run decoding loop */
+ do
+ {
+ return_status = (*vlcDecCoeff)(stream, &run_level);
+ if (return_status != PV_SUCCESS)
+ {
+ last = 1;/* 11/1/2000 let it slips undetected, just like
+ in original version */
+ i = VLC_ERROR;
+ break;
+ }
+
+ i += run_level.run;
+ last = run_level.last;
+ if (i >= 64)
+ {
+ /* i = NCOEFF_BLOCK; */ /* 11/1/00 */
+ i = VLC_NO_LAST_BIT;
+ last = 1;
+ break;
+ }
+ k = zigzag_inv[i];
+
+ if (run_level.sign == 0)
+ {
+ temp = (int32)QP * (2 * run_level.level + 1) - 1 + (QP & 1);
+ if (temp > 2047) temp = 2047;
+ }
+ else
+ {
+ temp = -(int32)QP * (2 * run_level.level + 1) + 1 - (QP & 1);
+ if (temp < -2048) temp = -2048;
+ }
+
+
+ datablock[k] = (int16) temp;
+
+#ifdef FAST_IDCT
+ bitmapcol[k&0x7] |= mask[k>>3];
+#endif
+ i++;
+ }
+ while (!last);
+
+ }
+ /* no ACDC prediction when ACDC disable */
+ if (datablock[0])
+ {
+#ifdef FAST_IDCT
+ bitmapcol[0] |= 128;
+#endif
+ datablock[0] <<= 3; /* no need to clip 09/18/2001 */
+ }
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ }
+ else /* advanced_INTRA mode */
+ {
+ i = 1;
+ doDCACPrediction_I(video, comp, datablock);
+ /* perform only VLC decoding */
+ if (!ACpred_flag)
+ {
+ direction = 0;
+ }
+ else
+ {
+ direction = video->mblock->direction;
+ }
+
+ inv_zigzag = zigzag_inv + (ACpred_flag << 6) + (direction << 6); /* 04/17/01 */
+
+ if (CBP & (1 << (5 - comp)))
+ {
+ i = 0;
+ do
+ {
+ return_status = (*vlcDecCoeff)(stream, &run_level);
+ if (return_status != PV_SUCCESS)
+ {
+ last = 1;/* 11/1/2000 let it slips undetected, just like
+ in original version */
+ i = VLC_ERROR;
+ ACpred_flag = 0; /* no of coefficients should not get reset 03/07/2002 */
+ break;
+ }
+
+ i += run_level.run;
+ last = run_level.last;
+ if (i >= 64)
+ {
+ /* i = NCOEFF_BLOCK; */ /* 11/1/00 */
+ ACpred_flag = 0; /* no of coefficients should not get reset 03/07/2002 */
+ i = VLC_NO_LAST_BIT;
+ last = 1;
+ break;
+ }
+
+ k = inv_zigzag[i];
+
+ if (run_level.sign == 0)
+ {
+ datablock[k] += (int16)QP * 2 * run_level.level;
+ if (datablock[k] > 2047) datablock[k] = 2047;
+ }
+ else
+ {
+ datablock[k] -= (int16)QP * 2 * run_level.level;
+ if (datablock[k] < -2048) datablock[k] = -2048;
+ }
+#ifdef FAST_IDCT
+ bitmapcol[k&0x7] |= mask[k>>3];
+#endif
+
+ i++;
+ }
+ while (!last);
+
+ }
+ ///// NEED TO DEQUANT THOSE PREDICTED AC COEFF
+ /* dequantize the rest of AC predicted coeff that haven't been dequant */
+
+ if (ACpred_flag)
+ {
+ i = NCOEFF_BLOCK;
+ for (k = 1; k < 8; k++)
+ {
+ if (datablock[k])
+ {
+ bitmapcol[k] |= 128;
+ }
+
+ if (datablock[k<<3])
+ {
+ bitmapcol[0] |= mask[k];
+ }
+ }
+ }
+
+ dcac_row[0] = datablock[1];
+ dcac_row[1] = datablock[2];
+ dcac_row[2] = datablock[3];
+ dcac_row[3] = datablock[4];
+ dcac_row[4] = datablock[5];
+ dcac_row[5] = datablock[6];
+ dcac_row[6] = datablock[7];
+
+ dcac_col[0] = datablock[8];
+ dcac_col[1] = datablock[16];
+ dcac_col[2] = datablock[24];
+ dcac_col[3] = datablock[32];
+ dcac_col[4] = datablock[40];
+ dcac_col[5] = datablock[48];
+ dcac_col[6] = datablock[56];
+
+ if (datablock[0])
+ {
+#ifdef FAST_IDCT
+ bitmapcol[0] |= 128;
+#endif
+
+ datablock[0] |= 1;
+ if (datablock[0] < 0)
+ {
+ datablock[0] = 0;
+ }
+ }
+ }
+#endif
+
+#ifdef FAST_IDCT
+ if (i > 10)
+ {
+ for (k = 1; k < 4; k++) /* if i > 10 then k = 0 does not matter */
+ {
+ if (bitmapcol[k] != 0)
+ {
+ (*bitmaprow) |= mask[k]; /* (1<<(7-i)); */
+ }
+ }
+ }
+#endif
+
+ /* Store the qcoeff-values needed later for prediction */
+ (*DC)[comp] = datablock[0];
+ return i;
+}
+
+/***********************************************************CommentBegin******
+*
+* -- VlcDequantInterH263Block -- Decodes the DCT coefficients of one 8x8 block and perform
+ dequantization in H.263 mode for INTER block.
+ Date: 08/08/2000
+ Modified: 3/21/01
+ clean up, added clipping, 16-bit int case
+******************************************************************************/
+
+
+int VlcDequantH263InterBlock(VideoDecData *video, int comp,
+ uint8 *bitmapcol, uint8 *bitmaprow)
+{
+ BitstreamDecVideo *stream = video->bitstream;
+ int16 *datablock = video->mblock->block[comp]; /* 10/20/2000, assume it has been reset of all-zero !!!*/
+ int32 temp;
+ int mbnum = video->mbnum;
+ int QP = video->QPMB[mbnum];
+
+ /*** VLC *****/
+ int i, k;
+ Tcoef run_level;
+ int last, return_status;
+ VlcDecFuncP vlcDecCoeff;
+
+ /*** Quantizer ****/
+
+
+ i = 0;
+
+#ifdef FAST_IDCT
+ *((uint32*)bitmapcol) = *((uint32*)(bitmapcol + 4)) = 0;
+ *bitmaprow = 0;
+#endif
+
+ /* select which Huffman table to be used */
+ vlcDecCoeff = video->vlcDecCoeffInter;
+
+ /* enter the zero run decoding loop */
+ do
+ {
+ return_status = (*vlcDecCoeff)(stream, &run_level);
+ if (return_status != PV_SUCCESS)
+ {
+
+
+ last = 1;/* 11/1/2000 let it slips undetected, just like
+ in original version */
+ i = -1;
+ break;
+ }
+
+ i += run_level.run;
+ last = run_level.last;
+ if (i >= 64)
+ {
+ i = -1;
+ last = 1;
+ break;
+ }
+
+ if (run_level.sign == 0)
+ {
+ temp = (int32)QP * (2 * run_level.level + 1) - 1 + (QP & 1);
+ if (temp > 2047) temp = 2047;
+
+ }
+ else
+ {
+ temp = -(int32)QP * (2 * run_level.level + 1) + 1 - (QP & 1);
+ if (temp < -2048) temp = -2048;
+ }
+
+ k = zigzag_inv[i];
+ datablock[k] = (int16)temp;
+#ifdef FAST_IDCT
+ bitmapcol[k&0x7] |= mask[k>>3];
+#endif
+ i++;
+ }
+ while (!last);
+
+#ifdef FAST_IDCT
+ if (i > 10) /* 07/19/01 */
+ {
+ for (k = 1; k < 4; k++) /* if (i > 10 ) k = 0 does not matter */
+ {
+ if (bitmapcol[k] != 0)
+ {
+ (*bitmaprow) |= mask[k]; /* (1<<(7-i)); */
+ }
+ }
+ }
+#endif
+ return i;
+}
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vlc_tab.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_tab.cpp
new file mode 100644
index 0000000..704992f
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vlc_tab.cpp
@@ -0,0 +1,835 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_api.h"
+#include "mp4def.h"
+#include "mp4lib_int.h"
+#include "vlc_dec_tab.h"
+#include "max_level.h"
+
+
+const int intra_max_level[2][NCOEFF_BLOCK] =
+{
+ {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
+ }
+};
+
+
+const int inter_max_level[2][NCOEFF_BLOCK] =
+{
+ {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}
+};
+
+
+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
+ };
+
+
+const int intra_max_run1[9] = { 999, 20, 6,
+ 1, 0, 0,
+ 0, 0, 0
+ };
+
+const int inter_max_run0[13] = { 999,
+ 26, 10, 6, 2, 1, 1,
+ 0, 0, 0, 0, 0, 0
+ };
+
+
+const int inter_max_run1[4] = { 999, 40, 1, 0 };
+
+const VLCshorttab PV_TMNMVtab0[] =
+{
+ {3, 4}, { -3, 4}, {2, 3}, {2, 3}, { -2, 3}, { -2, 3}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
+ { -1, 2}, { -1, 2}, { -1, 2}, { -1, 2}
+};
+
+const VLCshorttab PV_TMNMVtab1[] =
+{
+ {12, 10}, { -12, 10}, {11, 10}, { -11, 10}, {10, 9}, {10, 9}, { -10, 9}, { -10, 9},
+ {9, 9}, {9, 9}, { -9, 9}, { -9, 9}, {8, 9}, {8, 9}, { -8, 9}, { -8, 9}, {7, 7}, {7, 7},
+ {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, {7, 7}, { -7, 7}, { -7, 7}, { -7, 7}, { -7, 7},
+ { -7, 7}, { -7, 7}, { -7, 7}, { -7, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7}, {6, 7},
+ {6, 7}, {6, 7}, { -6, 7}, { -6, 7}, { -6, 7}, { -6, 7}, { -6, 7}, { -6, 7}, { -6, 7},
+ { -6, 7}, {5, 7}, {5, 7}, {5, 7}, {5, 7}, {5, 7}, {5, 7}, {5, 7}, {5, 7}, { -5, 7},
+ { -5, 7}, { -5, 7}, { -5, 7}, { -5, 7}, { -5, 7}, { -5, 7}, { -5, 7}, {4, 6}, {4, 6}, {4, 6},
+ {4, 6}, {4, 6}, {4, 6}, {4, 6}, {4, 6}, {4, 6}, {4, 6}, {4, 6}, {4, 6}, {4, 6}, {4, 6},
+ {4, 6}, {4, 6}, { -4, 6}, { -4, 6}, { -4, 6}, { -4, 6}, { -4, 6}, { -4, 6}, { -4, 6},
+ { -4, 6}, { -4, 6}, { -4, 6}, { -4, 6}, { -4, 6}, { -4, 6}, { -4, 6}, { -4, 6}, { -4, 6}
+};
+
+const VLCshorttab PV_TMNMVtab2[] =
+{
+ {32, 12}, { -32, 12}, {31, 12}, { -31, 12}, {30, 11}, {30, 11}, { -30, 11}, { -30, 11},
+ {29, 11}, {29, 11}, { -29, 11}, { -29, 11}, {28, 11}, {28, 11}, { -28, 11}, { -28, 11},
+ {27, 11}, {27, 11}, { -27, 11}, { -27, 11}, {26, 11}, {26, 11}, { -26, 11}, { -26, 11},
+ {25, 11}, {25, 11}, { -25, 11}, { -25, 11}, {24, 10}, {24, 10}, {24, 10}, {24, 10},
+ { -24, 10}, { -24, 10}, { -24, 10}, { -24, 10}, {23, 10}, {23, 10}, {23, 10}, {23, 10},
+ { -23, 10}, { -23, 10}, { -23, 10}, { -23, 10}, {22, 10}, {22, 10}, {22, 10}, {22, 10},
+ { -22, 10}, { -22, 10}, { -22, 10}, { -22, 10}, {21, 10}, {21, 10}, {21, 10}, {21, 10},
+ { -21, 10}, { -21, 10}, { -21, 10}, { -21, 10}, {20, 10}, {20, 10}, {20, 10}, {20, 10},
+ { -20, 10}, { -20, 10}, { -20, 10}, { -20, 10}, {19, 10}, {19, 10}, {19, 10}, {19, 10},
+ { -19, 10}, { -19, 10}, { -19, 10}, { -19, 10}, {18, 10}, {18, 10}, {18, 10}, {18, 10},
+ { -18, 10}, { -18, 10}, { -18, 10}, { -18, 10}, {17, 10}, {17, 10}, {17, 10}, {17, 10},
+ { -17, 10}, { -17, 10}, { -17, 10}, { -17, 10}, {16, 10}, {16, 10}, {16, 10}, {16, 10},
+ { -16, 10}, { -16, 10}, { -16, 10}, { -16, 10}, {15, 10}, {15, 10}, {15, 10}, {15, 10},
+ { -15, 10}, { -15, 10}, { -15, 10}, { -15, 10}, {14, 10}, {14, 10}, {14, 10}, {14, 10},
+ { -14, 10}, { -14, 10}, { -14, 10}, { -14, 10}, {13, 10}, {13, 10}, {13, 10}, {13, 10},
+ { -13, 10}, { -13, 10}, { -13, 10}, { -13, 10}
+};
+
+const VLCshorttab PV_MCBPCtab[] =
+{
+ {VLC_ERROR, 0},
+ {255, 9}, {52, 9}, {36, 9}, {20, 9}, {49, 9}, {35, 8}, {35, 8}, {19, 8}, {19, 8},
+ {50, 8}, {50, 8}, {51, 7}, {51, 7}, {51, 7}, {51, 7}, {34, 7}, {34, 7}, {34, 7},
+ {34, 7}, {18, 7}, {18, 7}, {18, 7}, {18, 7}, {33, 7}, {33, 7}, {33, 7}, {33, 7},
+ {17, 7}, {17, 7}, {17, 7}, {17, 7}, {4, 6}, {4, 6}, {4, 6}, {4, 6}, {4, 6},
+ {4, 6}, {4, 6}, {4, 6}, {48, 6}, {48, 6}, {48, 6}, {48, 6}, {48, 6}, {48, 6},
+ {48, 6}, {48, 6}, {3, 5}, {3, 5}, {3, 5}, {3, 5}, {3, 5}, {3, 5}, {3, 5},
+ {3, 5}, {3, 5}, {3, 5}, {3, 5}, {3, 5}, {3, 5}, {3, 5}, {3, 5}, {3, 5},
+ {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4},
+ {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4},
+ {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4},
+ {32, 4}, {32, 4}, {32, 4}, {32, 4}, {32, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4},
+ {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4},
+ {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4},
+ {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4}, {16, 4},
+ {16, 4}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
+ {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
+ {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
+ {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
+ {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
+ {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
+ {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3}, {2, 3},
+ {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3},
+ {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3},
+ {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3},
+ {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3},
+ {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3},
+ {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3},
+ {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3},
+ {1, 3}, {1, 3}, {1, 3}
+};
+
+#ifdef PV_ANNEX_IJKT_SUPPORT
+const VLCshorttab PV_MCBPCtab1[] =
+{
+ {5, 11}, {5, 11}, {5, 11}, {5, 11}, {21, 13}, {21, 13}, {37, 13}, {53, 13},
+};
+#endif
+const VLCshorttab PV_MCBPCtabintra[] =
+{
+ {VLC_ERROR, 0},
+ {20, 6}, {36, 6}, {52, 6}, {4, 4}, {4, 4}, {4, 4},
+ {4, 4}, {19, 3}, {19, 3}, {19, 3}, {19, 3}, {19, 3},
+ {19, 3}, {19, 3}, {19, 3}, {35, 3}, {35, 3}, {35, 3},
+ {35, 3}, {35, 3}, {35, 3}, {35, 3}, {35, 3}, {51, 3},
+ {51, 3}, {51, 3}, {51, 3}, {51, 3}, {51, 3}, {51, 3},
+ {51, 3}
+};
+
+
+
+const VLCshorttab PV_CBPYtab[48] =
+{
+ {VLC_ERROR, 0}, {VLC_ERROR, 0}, {6, 6}, {9, 6}, {8, 5}, {8, 5}, {4, 5}, {4, 5},
+ {2, 5}, {2, 5}, {1, 5}, {1, 5}, {0, 4}, {0, 4}, {0, 4}, {0, 4},
+ {12, 4}, {12, 4}, {12, 4}, {12, 4}, {10, 4}, {10, 4}, {10, 4}, {10, 4},
+ {14, 4}, {14, 4}, {14, 4}, {14, 4}, {5, 4}, {5, 4}, {5, 4}, {5, 4},
+ {13, 4}, {13, 4}, {13, 4}, {13, 4}, {3, 4}, {3, 4}, {3, 4}, {3, 4},
+ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {7, 4}, {7, 4}, {7, 4}, {7, 4}
+};
+
+
+
+const VLCtab2 PV_DCT3Dtab0[] =
+{
+ {0x8, 1, 1, 7}, {0x7, 1, 1, 7}, {0x6, 1, 1, 7}, {0x5, 1, 1, 7}, {0xc, 1, 0, 7}, {0xb, 1, 0, 7},
+ {0xa, 1, 0, 7}, {0x0, 4, 0, 7}, {0x4, 1, 1, 6}, {0x4, 1, 1, 6}, {0x3, 1, 1, 6}, {0x3, 1, 1, 6},
+ {0x2, 1, 1, 6}, {0x2, 1, 1, 6}, {0x1, 1, 1, 6}, {0x1, 1, 1, 6}, {0x9, 1, 0, 6}, {0x9, 1, 0, 6},
+ {0x8, 1, 0, 6}, {0x8, 1, 0, 6}, {0x7, 1, 0, 6}, {0x7, 1, 0, 6}, {0x6, 1, 0, 6}, {0x6, 1, 0, 6},
+ {0x1, 2, 0, 6}, {0x1, 2, 0, 6}, {0x0, 3, 0, 6}, {0x0, 3, 0, 6}, {0x5, 1, 0, 5}, {0x5, 1, 0, 5},
+ {0x5, 1, 0, 5}, {0x5, 1, 0, 5}, {0x4, 1, 0, 5}, {0x4, 1, 0, 5}, {0x4, 1, 0, 5}, {0x4, 1, 0, 5},
+ {0x3, 1, 0, 5}, {0x3, 1, 0, 5}, {0x3, 1, 0, 5}, {0x3, 1, 0, 5}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4},
+ {0x0, 1, 1, 4}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x1, 1, 0, 3}, {0x1, 1, 0, 3}, {0x1, 1, 0, 3}, {0x1, 1, 0, 3},
+ {0x1, 1, 0, 3}, {0x1, 1, 0, 3}, {0x1, 1, 0, 3}, {0x1, 1, 0, 3}, {0x1, 1, 0, 3}, {0x1, 1, 0, 3},
+ {0x1, 1, 0, 3}, {0x1, 1, 0, 3}, {0x1, 1, 0, 3}, {0x1, 1, 0, 3}, {0x1, 1, 0, 3}, {0x1, 1, 0, 3},
+ {0x2, 1, 0, 4}, {0x2, 1, 0, 4}, {0x2, 1, 0, 4}, {0x2, 1, 0, 4}, {0x2, 1, 0, 4}, {0x2, 1, 0, 4},
+ {0x2, 1, 0, 4}, {0x2, 1, 0, 4}, {0x0, 2, 0, 4}, {0x0, 2, 0, 4}, {0x0, 2, 0, 4}, {0x0, 2, 0, 4},
+ {0x0, 2, 0, 4}, {0x0, 2, 0, 4}, {0x0, 2, 0, 4}, {0x0, 2, 0, 4}
+};
+
+
+const VLCtab2 PV_DCT3Dtab1[] =
+{
+ {0x0, 9, 0, 10}, {0x0, 8, 0, 10}, {0x18, 1, 1, 9}, {0x18, 1, 1, 9}, {0x17, 1, 1, 9}, {0x17, 1, 1, 9},
+ {0x16, 1, 1, 9}, {0x16, 1, 1, 9}, {0x15, 1, 1, 9}, {0x15, 1, 1, 9}, {0x14, 1, 1, 9}, {0x14, 1, 1, 9},
+ {0x13, 1, 1, 9}, {0x13, 1, 1, 9}, {0x12, 1, 1, 9}, {0x12, 1, 1, 9}, {0x11, 1, 1, 9}, {0x11, 1, 1, 9},
+ {0x0, 2, 1, 9}, {0x0, 2, 1, 9}, {0x16, 1, 0, 9}, {0x16, 1, 0, 9}, {0x15, 1, 0, 9}, {0x15, 1, 0, 9},
+ {0x14, 1, 0, 9}, {0x14, 1, 0, 9}, {0x13, 1, 0, 9}, {0x13, 1, 0, 9}, {0x12, 1, 0, 9}, {0x12, 1, 0, 9},
+ {0x11, 1, 0, 9}, {0x11, 1, 0, 9}, {0x10, 1, 0, 9}, {0x10, 1, 0, 9}, {0xf, 1, 0, 9}, {0xf, 1, 0, 9},
+ {0x4, 2, 0, 9}, {0x4, 2, 0, 9}, {0x3, 2, 0, 9}, {0x3, 2, 0, 9}, {0x0, 7, 0, 9}, {0x0, 7, 0, 9},
+ {0x0, 6, 0, 9}, {0x0, 6, 0, 9}, {0x10, 1, 1, 8}, {0x10, 1, 1, 8}, {0x10, 1, 1, 8}, {0x10, 1, 1, 8},
+ {0xf, 1, 1, 8}, {0xf, 1, 1, 8}, {0xf, 1, 1, 8}, {0xf, 1, 1, 8}, {0xe, 1, 1, 8}, {0xe, 1, 1, 8},
+ {0xe, 1, 1, 8}, {0xe, 1, 1, 8}, {0xd, 1, 1, 8}, {0xd, 1, 1, 8}, {0xd, 1, 1, 8}, {0xd, 1, 1, 8},
+ {0xc, 1, 1, 8}, {0xc, 1, 1, 8}, {0xc, 1, 1, 8}, {0xc, 1, 1, 8}, {0xb, 1, 1, 8}, {0xb, 1, 1, 8},
+ {0xb, 1, 1, 8}, {0xb, 1, 1, 8}, {0xa, 1, 1, 8}, {0xa, 1, 1, 8}, {0xa, 1, 1, 8}, {0xa, 1, 1, 8},
+ {0x9, 1, 1, 8}, {0x9, 1, 1, 8}, {0x9, 1, 1, 8}, {0x9, 1, 1, 8}, {0xe, 1, 0, 8}, {0xe, 1, 0, 8},
+ {0xe, 1, 0, 8}, {0xe, 1, 0, 8}, {0xd, 1, 0, 8}, {0xd, 1, 0, 8}, {0xd, 1, 0, 8}, {0xd, 1, 0, 8},
+ {0x2, 2, 0, 8}, {0x2, 2, 0, 8}, {0x2, 2, 0, 8}, {0x2, 2, 0, 8}, {0x1, 3, 0, 8}, {0x1, 3, 0, 8},
+ {0x1, 3, 0, 8}, {0x1, 3, 0, 8}, {0x0, 5, 0, 8}, {0x0, 5, 0, 8}, {0x0, 5, 0, 8}, {0x0, 5, 0, 8}
+};
+
+
+const VLCtab2 PV_DCT3Dtab2[] =
+{
+ {0x1, 2, 1, 11}, {0x1, 2, 1, 11}, {0x0, 3, 1, 11}, {0x0, 3, 1, 11}, {0x0, 0xb, 0, 11}, {0x0, 0xb, 0, 11},
+ {0x0, 0xa, 0, 11}, {0x0, 0xa, 0, 11}, {0x1c, 1, 1, 10}, {0x1c, 1, 1, 10}, {0x1c, 1, 1, 10}, {0x1c, 1, 1, 10},
+ {0x1b, 1, 1, 10}, {0x1b, 1, 1, 10}, {0x1b, 1, 1, 10}, {0x1b, 1, 1, 10}, {0x1a, 1, 1, 10}, {0x1a, 1, 1, 10},
+ {0x1a, 1, 1, 10}, {0x1a, 1, 1, 10}, {0x19, 1, 1, 10}, {0x19, 1, 1, 10}, {0x19, 1, 1, 10}, {0x19, 1, 1, 10},
+ {0x9, 2, 0, 10}, {0x9, 2, 0, 10}, {0x9, 2, 0, 10}, {0x9, 2, 0, 10}, {0x8, 2, 0, 10}, {0x8, 2, 0, 10},
+ {0x8, 2, 0, 10}, {0x8, 2, 0, 10}, {0x7, 2, 0, 10}, {0x7, 2, 0, 10}, {0x7, 2, 0, 10}, {0x7, 2, 0, 10},
+ {0x6, 2, 0, 10}, {0x6, 2, 0, 10}, {0x6, 2, 0, 10}, {0x6, 2, 0, 10}, {0x5, 2, 0, 10}, {0x5, 2, 0, 10},
+ {0x5, 2, 0, 10}, {0x5, 2, 0, 10}, {0x3, 3, 0, 10}, {0x3, 3, 0, 10}, {0x3, 3, 0, 10}, {0x3, 3, 0, 10},
+ {0x2, 3, 0, 10}, {0x2, 3, 0, 10}, {0x2, 3, 0, 10}, {0x2, 3, 0, 10}, {0x1, 4, 0, 10}, {0x1, 4, 0, 10},
+ {0x1, 4, 0, 10}, {0x1, 4, 0, 10}, {0x0, 0xc, 0, 11}, {0x0, 0xc, 0, 11}, {0x1, 5, 0, 11}, {0x1, 5, 0, 11},
+ {0x17, 1, 0, 11}, {0x17, 1, 0, 11}, {0x18, 1, 0, 11}, {0x18, 1, 0, 11}, {0x1d, 1, 1, 11}, {0x1d, 1, 1, 11},
+ {0x1e, 1, 1, 11}, {0x1e, 1, 1, 11}, {0x1f, 1, 1, 11}, {0x1f, 1, 1, 11}, {0x20, 1, 1, 11}, {0x20, 1, 1, 11},
+ {0x1, 6, 0, 12}, {0x2, 4, 0, 12}, {0x4, 3, 0, 12}, {0x5, 3, 0, 12}, {0x6, 3, 0, 12}, {0xa, 2, 0, 12},
+ {0x19, 1, 0, 12}, {0x1a, 1, 0, 12}, {0x21, 1, 1, 12}, {0x22, 1, 1, 12}, {0x23, 1, 1, 12}, {0x24, 1, 1, 12},
+ {0x25, 1, 1, 12}, {0x26, 1, 1, 12}, {0x27, 1, 1, 12}, {0x28, 1, 1, 12}, {0xbf, 0xf, 1, 7},
+ {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7},
+ {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7},
+ {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7},
+ {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7},
+ {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7}, {0xbf, 0xf, 1, 7},
+ {0xbf, 0xf, 1, 7}
+};
+
+/* New tables for Intra luminance blocks */
+
+const VLCtab2 PV_DCT3Dtab3[] =
+{
+ {0x4, 1, 1, 7}, {0x3, 1, 1, 7}, {0x6, 1, 0, 7}, {0x5, 1, 1, 7},
+ {0x7, 1, 0, 7}, {0x2, 2, 0, 7}, {0x1, 3, 0, 7}, {0x0, 9, 0, 7},
+ {0x0, 2, 1, 6}, {0x0, 2, 1, 6}, {0x5, 1, 0, 6}, {0x5, 1, 0, 6},
+ {0x2, 1, 1, 6}, {0x2, 1, 1, 6}, {0x1, 1, 1, 6}, {0x1, 1, 1, 6},
+ {0x4, 1, 0, 6}, {0x4, 1, 0, 6}, {0x3, 1, 0, 6}, {0x3, 1, 0, 6},
+ {0x0, 8, 0, 6}, {0x0, 8, 0, 6}, {0x0, 7, 0, 6}, {0x0, 7, 0, 6},
+ {0x1, 2, 0, 6}, {0x1, 2, 0, 6}, {0x0, 6, 0, 6}, {0x0, 6, 0, 6},
+ {0x2, 1, 0, 5}, {0x2, 1, 0, 5}, {0x2, 1, 0, 5}, {0x2, 1, 0, 5},
+ {0x0, 5, 0, 5}, {0x0, 5, 0, 5}, {0x0, 5, 0, 5}, {0x0, 5, 0, 5},
+ {0x0, 4, 0, 5}, {0x0, 4, 0, 5}, {0x0, 4, 0, 5}, {0x0, 4, 0, 5},
+ {0x0, 1, 1, 4}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4},
+ {0x0, 1, 1, 4}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3},
+ {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3},
+ {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3},
+ {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3},
+ {0x1, 1, 0, 4}, {0x1, 1, 0, 4}, {0x1, 1, 0, 4}, {0x1, 1, 0, 4},
+ {0x1, 1, 0, 4}, {0x1, 1, 0, 4}, {0x1, 1, 0, 4}, {0x1, 1, 0, 4},
+ {0x0, 3, 0, 4}, {0x0, 3, 0, 4}, {0x0, 3, 0, 4}, {0x0, 3, 0, 4},
+ {0x0, 3, 0, 4}, {0x0, 3, 0, 4}, {0x0, 3, 0, 4}, {0x0, 3, 0, 4}
+};
+
+const VLCtab2 PV_DCT3Dtab4[] =
+{
+ {0x0, 0x12, 0, 10}, {0x0, 0x11, 0, 10}, {0xe, 1, 1, 9}, {0xe, 1, 1, 9},
+ {0xd, 1, 1, 9}, {0xd, 1, 1, 9}, {0xc, 1, 1, 9}, {0xc, 1, 1, 9},
+ {0xb, 1, 1, 9}, {0xb, 1, 1, 9}, {0xa, 1, 1, 9}, {0xa, 1, 1, 9},
+ {0x1, 2, 1, 9}, {0x1, 2, 1, 9}, {0x0, 4, 1, 9}, {0x0, 4, 1, 9},
+ {0xc, 1, 0, 9}, {0xc, 1, 0, 9}, {0xb, 1, 0, 9}, {0xb, 1, 0, 9},
+ {0x7, 2, 0, 9}, {0x7, 2, 0, 9}, {0x6, 2, 0, 9}, {0x6, 2, 0, 9},
+ {0x5, 2, 0, 9}, {0x5, 2, 0, 9}, {0x3, 3, 0, 9}, {0x3, 3, 0, 9},
+ {0x2, 3, 0, 9}, {0x2, 3, 0, 9}, {0x1, 6, 0, 9}, {0x1, 6, 0, 9},
+ {0x1, 5, 0, 9}, {0x1, 5, 0, 9}, {0x0, 0x10, 0, 9}, {0x0, 0x10, 0, 9},
+ {0x4, 2, 0, 9}, {0x4, 2, 0, 9}, {0x0, 0xf, 0, 9}, {0x0, 0xf, 0, 9},
+ {0x0, 0xe, 0, 9}, {0x0, 0xe, 0, 9}, {0x0, 0xd, 0, 9}, {0x0, 0xd, 0, 9},
+ {0x8, 1, 1, 8}, {0x8, 1, 1, 8}, {0x8, 1, 1, 8}, {0x8, 1, 1, 8},
+ {0x7, 1, 1, 8}, {0x7, 1, 1, 8}, {0x7, 1, 1, 8}, {0x7, 1, 1, 8},
+ {0x6, 1, 1, 8}, {0x6, 1, 1, 8}, {0x6, 1, 1, 8}, {0x6, 1, 1, 8},
+ {0x0, 3, 1, 8}, {0x0, 3, 1, 8}, {0x0, 3, 1, 8}, {0x0, 3, 1, 8},
+ {0xa, 1, 0, 8}, {0xa, 1, 0, 8}, {0xa, 1, 0, 8}, {0xa, 1, 0, 8},
+ {0x9, 1, 0, 8}, {0x9, 1, 0, 8}, {0x9, 1, 0, 8}, {0x9, 1, 0, 8},
+ {0x8, 1, 0, 8}, {0x8, 1, 0, 8}, {0x8, 1, 0, 8}, {0x8, 1, 0, 8},
+ {0x9, 1, 1, 8}, {0x9, 1, 1, 8}, {0x9, 1, 1, 8}, {0x9, 1, 1, 8},
+ {0x3, 2, 0, 8}, {0x3, 2, 0, 8}, {0x3, 2, 0, 8}, {0x3, 2, 0, 8},
+ {0x1, 4, 0, 8}, {0x1, 4, 0, 8}, {0x1, 4, 0, 8}, {0x1, 4, 0, 8},
+ {0x0, 0xc, 0, 8}, {0x0, 0xc, 0, 8}, {0x0, 0xc, 0, 8}, {0x0, 0xc, 0, 8},
+ {0x0, 0xb, 0, 8}, {0x0, 0xb, 0, 8}, {0x0, 0xb, 0, 8}, {0x0, 0xb, 0, 8},
+ {0x0, 0xa, 0, 8}, {0x0, 0xa, 0, 8}, {0x0, 0xa, 0, 8}, {0x0, 0xa, 0, 8}
+};
+
+const VLCtab2 PV_DCT3Dtab5[] =
+{
+ {0x0, 7, 1, 11}, {0x0, 7, 1, 11}, {0x0, 6, 1, 11}, {0x0, 6, 1, 11},
+ {0x0, 0x16, 0, 11}, {0x0, 0x16, 0, 11}, {0x0, 0x15, 0, 11}, {0x0, 0x15, 0, 11},
+ {0x2, 2, 1, 10}, {0x2, 2, 1, 10}, {0x2, 2, 1, 10}, {0x2, 2, 1, 10},
+ {0x1, 3, 1, 10}, {0x1, 3, 1, 10}, {0x1, 3, 1, 10}, {0x1, 3, 1, 10},
+ {0x0, 5, 1, 10}, {0x0, 5, 1, 10}, {0x0, 5, 1, 10}, {0x0, 5, 1, 10},
+ {0xd, 1, 0, 10}, {0xd, 1, 0, 10}, {0xd, 1, 0, 10}, {0xd, 1, 0, 10},
+ {0x5, 3, 0, 10}, {0x5, 3, 0, 10}, {0x5, 3, 0, 10}, {0x5, 3, 0, 10},
+ {0x8, 2, 0, 10}, {0x8, 2, 0, 10}, {0x8, 2, 0, 10}, {0x8, 2, 0, 10},
+ {0x4, 3, 0, 10}, {0x4, 3, 0, 10}, {0x4, 3, 0, 10}, {0x4, 3, 0, 10},
+ {0x3, 4, 0, 10}, {0x3, 4, 0, 10}, {0x3, 4, 0, 10}, {0x3, 4, 0, 10},
+ {0x2, 4, 0, 10}, {0x2, 4, 0, 10}, {0x2, 4, 0, 10}, {0x2, 4, 0, 10},
+ {0x1, 7, 0, 10}, {0x1, 7, 0, 10}, {0x1, 7, 0, 10}, {0x1, 7, 0, 10},
+ {0x0, 0x14, 0, 10}, {0x0, 0x14, 0, 10}, {0x0, 0x14, 0, 10}, {0x0, 0x14, 0, 10},
+ {0x0, 0x13, 0, 10}, {0x0, 0x13, 0, 10}, {0x0, 0x13, 0, 10}, {0x0, 0x13, 0, 10},
+ {0x0, 0x17, 0, 11}, {0x0, 0x17, 0, 11}, {0x0, 0x18, 0, 11}, {0x0, 0x18, 0, 11},
+ {0x1, 8, 0, 11}, {0x1, 8, 0, 11}, {0x9, 2, 0, 11}, {0x9, 2, 0, 11},
+ {0x3, 2, 1, 11}, {0x3, 2, 1, 11}, {0x4, 2, 1, 11}, {0x4, 2, 1, 11},
+ {0xf, 1, 1, 11}, {0xf, 1, 1, 11}, {0x10, 1, 1, 11}, {0x10, 1, 1, 11},
+ {0, 0x19, 0, 12}, {0, 0x1a, 0, 12}, {0, 0x1b, 0, 12}, {1, 9, 0, 12},
+ {0x6, 3, 0, 12}, {0x1, 0xa, 0, 12}, {0x2, 5, 0, 12}, {0x7, 3, 0, 12},
+ {0xe, 1, 0, 12}, {0x0, 8, 1, 12}, {0x5, 2, 1, 12}, {0x6, 2, 1, 12},
+ {0x11, 1, 1, 12}, {0x12, 1, 1, 12}, {0x13, 1, 1, 12}, {0x14, 1, 1, 12},
+ {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7},
+ {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7},
+ {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7},
+ {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7},
+ {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7},
+ {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7},
+ {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7},
+ {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}, {0x1b, 0xff, 0, 7}
+};
+
+#ifdef PV_ANNEX_IJKT_SUPPORT
+const VLCtab2 PV_DCT3Dtab6[] =
+{
+ {0x0, 3, 1, 7}, {0x4, 1, 1, 7}, {0x6, 1, 1, 7}, {0x5, 1, 1, 7}, {0x1, 3, 0, 7}, {0x2, 2, 0, 7},
+ {0x0, 9, 0, 7}, {0x5, 1, 0, 7}, {0x0, 2, 1, 6}, {0x0, 2, 1, 6}, {0x3, 1, 1, 6}, {0x3, 1, 1, 6},
+ {0x2, 1, 1, 6}, {0x2, 1, 1, 6}, {0x1, 1, 1, 6}, {0x1, 1, 1, 6}, {0x0, 6, 0, 6}, {0x0, 6, 0, 6},
+ {0x0, 7, 0, 6}, {0x0, 7, 0, 6}, {0x0, 8, 0, 6}, {0x0, 8, 0, 6}, {0x4, 1, 0, 6}, {0x4, 1, 0, 6},
+ {0x1, 2, 0, 6}, {0x1, 2, 0, 6}, {0x3, 1, 0, 6}, {0x3, 1, 0, 6}, {0x2, 1, 0, 5}, {0x2, 1, 0, 5},
+ {0x2, 1, 0, 5}, {0x2, 1, 0, 5}, {0x0, 4, 0, 5}, {0x0, 4, 0, 5}, {0x0, 4, 0, 5}, {0x0, 4, 0, 5},
+ {0x0, 5, 0, 5}, {0x0, 5, 0, 5}, {0x0, 5, 0, 5}, {0x0, 5, 0, 5}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4},
+ {0x0, 1, 1, 4}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4}, {0x0, 1, 1, 4},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 1, 0, 2},
+ {0x0, 1, 0, 2}, {0x0, 1, 0, 2}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3},
+ {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3},
+ {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3}, {0x0, 2, 0, 3},
+ {0x0, 3, 0, 4}, {0x0, 3, 0, 4}, {0x0, 3, 0, 4}, {0x0, 3, 0, 4}, {0x0, 3, 0, 4}, {0x0, 3, 0, 4},
+ {0x0, 3, 0, 4}, {0x0, 3, 0, 4}, {0x1, 1, 0, 4}, {0x1, 1, 0, 4}, {0x1, 1, 0, 4}, {0x1, 1, 0, 4},
+ {0x1, 1, 0, 4}, {0x1, 1, 0, 4}, {0x1, 1, 0, 4}, {0x1, 1, 0, 4}
+};
+
+const VLCtab2 PV_DCT3Dtab7[] =
+{
+ {0xb, 1, 0, 10}, {0xa, 1, 0, 10}, {0x0, 5, 1, 9}, {0x0, 5, 1, 9}, {0x0, 6, 1, 9}, {0x0, 6, 1, 9},
+ {0x1, 2, 1, 9}, {0x1, 2, 1, 9}, {0x2, 2, 1, 9}, {0x2, 2, 1, 9}, {0xf, 1, 1, 9}, {0xf, 1, 1, 9},
+ {0x10, 1, 1, 9}, {0x10, 1, 1, 9}, {0x12, 1, 1, 9}, {0x12, 1, 1, 9}, {0x11, 1, 1, 9}, {0x11, 1, 1, 9},
+ {0xe, 1, 1, 9}, {0xe, 1, 1, 9}, {0x0, 13, 0, 9}, {0x0, 13, 0, 9}, {0x0, 14, 0, 9}, {0x0, 14, 0, 9},
+ {0x0, 15, 0, 9}, {0x0, 15, 0, 9}, {0x0, 16, 0, 9}, {0x0, 16, 0, 9}, {0x0, 17, 0, 9}, {0x0, 17, 0, 9},
+ {0x0, 18, 0, 9}, {0x0, 18, 0, 9}, {0x0, 11, 0, 9}, {0x0, 11, 0, 9}, {0x0, 12, 0, 9}, {0x0, 12, 0, 9},
+ {0x5, 2, 0, 9}, {0x5, 2, 0, 9}, {0x4, 2, 0, 9}, {0x4, 2, 0, 9}, {0x9, 1, 0, 9}, {0x9, 1, 0, 9},
+ {0x8, 1, 0, 9}, {0x8, 1, 0, 9}, {0x0, 4, 1, 8}, {0x0, 4, 1, 8}, {0x0, 4, 1, 8}, {0x0, 4, 1, 8},
+ {0x7, 1, 1, 8}, {0x7, 1, 1, 8}, {0x7, 1, 1, 8}, {0x7, 1, 1, 8}, {0x8, 1, 1, 8}, {0x8, 1, 1, 8},
+ {0x8, 1, 1, 8}, {0x8, 1, 1, 8}, {0xd, 1, 1, 8}, {0xd, 1, 1, 8}, {0xd, 1, 1, 8}, {0xd, 1, 1, 8},
+ {0xc, 1, 1, 8}, {0xc, 1, 1, 8}, {0xc, 1, 1, 8}, {0xc, 1, 1, 8}, {0xb, 1, 1, 8}, {0xb, 1, 1, 8},
+ {0xb, 1, 1, 8}, {0xb, 1, 1, 8}, {0xa, 1, 1, 8}, {0xa, 1, 1, 8}, {0xa, 1, 1, 8}, {0xa, 1, 1, 8},
+ {0x9, 1, 1, 8}, {0x9, 1, 1, 8}, {0x9, 1, 1, 8}, {0x9, 1, 1, 8}, {0x0, 10, 0, 8}, {0x0, 10, 0, 8},
+ {0x0, 10, 0, 8}, {0x0, 10, 0, 8}, {0x6, 1, 0, 8}, {0x6, 1, 0, 8}, {0x6, 1, 0, 8}, {0x6, 1, 0, 8},
+ {0x3, 2, 0, 8}, {0x3, 2, 0, 8}, {0x3, 2, 0, 8}, {0x3, 2, 0, 8}, {0x1, 4, 0, 8}, {0x1, 4, 0, 8},
+ {0x1, 4, 0, 8}, {0x1, 4, 0, 8}, {0x7, 1, 0, 8}, {0x7, 1, 0, 8}, {0x7, 1, 0, 8}, {0x7, 1, 0, 8}
+};
+
+
+const VLCtab2 PV_DCT3Dtab8[] =
+{
+ {0x13, 0x1, 1, 11}, {0x13, 0x1, 1, 11}, {0x14, 0x1, 1, 11}, {0x14, 0x1, 1, 11}, {0x9, 0x2, 0, 11}, {0x9, 0x2, 0, 11},
+ {0x4, 0x3, 0, 11}, {0x4, 0x3, 0, 11}, {0x0, 0x7, 1, 10}, {0x0, 0x7, 1, 10}, {0x0, 0x7, 1, 10}, {0x0, 0x7, 1, 10},
+ {0x1, 0x3, 1, 10}, {0x1, 0x3, 1, 10}, {0x1, 0x3, 1, 10}, {0x1, 0x3, 1, 10}, {0x3, 0x2, 1, 10}, {0x3, 0x2, 1, 10},
+ {0x3, 0x2, 1, 10}, {0x3, 0x2, 1, 10}, {0x4, 0x2, 1, 10}, {0x4, 0x2, 1, 10}, {0x4, 0x2, 1, 10}, {0x4, 0x2, 1, 10},
+ {0xc, 0x1, 0, 10}, {0xc, 0x1, 0, 10}, {0xc, 0x1, 0, 10}, {0xc, 0x1, 0, 10}, {0x2, 0x4, 0, 10}, {0x2, 0x4, 0, 10},
+ {0x2, 0x4, 0, 10}, {0x2, 0x4, 0, 10}, {0x8, 0x2, 0, 10}, {0x8, 0x2, 0, 10}, {0x8, 0x2, 0, 10}, {0x8, 0x2, 0, 10},
+ {0x7, 0x2, 0, 10}, {0x7, 0x2, 0, 10}, {0x7, 0x2, 0, 10}, {0x7, 0x2, 0, 10}, {0x6, 0x2, 0, 10}, {0x6, 0x2, 0, 10},
+ {0x6, 0x2, 0, 10}, {0x6, 0x2, 0, 10}, {0x3, 0x3, 0, 10}, {0x3, 0x3, 0, 10}, {0x3, 0x3, 0, 10}, {0x3, 0x3, 0, 10},
+ {0x2, 0x3, 0, 10}, {0x2, 0x3, 0, 10}, {0x2, 0x3, 0, 10}, {0x2, 0x3, 0, 10}, {0x1, 0x5, 0, 10}, {0x1, 0x5, 0, 10},
+ {0x1, 0x5, 0, 10}, {0x1, 0x5, 0, 10}, {0xd, 0x1, 0, 11}, {0xd, 0x1, 0, 11}, {0x1, 0x6, 0, 11}, {0x1, 0x6, 0, 11},
+ {0x0, 0x14, 0, 11}, {0x0, 0x14, 0, 11}, {0x0, 0x13, 0, 11}, {0x0, 0x13, 0, 11}, {0x2, 0x3, 1, 11}, {0x2, 0x3, 1, 11},
+ {0x1, 0x4, 1, 11}, {0x1, 0x4, 1, 11}, {0x0, 0x9, 1, 11}, {0x0, 0x9, 1, 11}, {0x0, 0x8, 1, 11}, {0x0, 0x8, 1, 11},
+ {0x1, 0x7, 0, 12}, {0x3, 0x4, 0, 12}, {0x5, 0x3, 0, 12}, {0x0, 0x19, 0, 12}, {0x0, 0x18, 0, 12}, {0x0, 0x17, 0, 12},
+ {0x0, 0x16, 0, 12}, {0x0, 0x15, 0, 12}, {0x15, 0x1, 1, 12}, {0x16, 0x1, 1, 12}, {0x17, 0x1, 1, 12}, {0x7, 0x2, 1, 12},
+ {0x6, 0x2, 1, 12}, {0x5, 0x2, 1, 12}, {0x3, 0x3, 1, 12}, {0x0, 0xa, 1, 12}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7},
+ {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7},
+ {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7},
+ {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7},
+ {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7},
+ {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}, {0x2f, 0x3f, 1, 7}
+};
+#endif
+/* RVLC tables */
+const int ptrRvlcTab[11] = {0, 24, 46, 66, 84, 100, 114, 126, 134, 140, 144};
+
+const VLCtab2 RvlcDCTtabIntra[170] = /* 00xxxx00 or 00xxxx01 */
+{
+ {27, 255, 0, 5}, /* 0000 is escape code */
+ {1, 1, 0, 4},
+ {2, 1, 0, 5},
+ {3, 1, 0, 5},
+ {4, 1, 0, 6},
+ {5, 1, 0, 6},
+ {6, 1, 0, 7},
+ {7, 1, 0, 7},
+ {8, 1, 0, 8},
+ {9, 1, 0, 8},
+ {10, 1, 0, 9},
+ {5, 2, 0, 9},
+ {11, 1, 0, 10},
+ {12, 1, 0, 10},
+ {13, 1, 0, 11},
+ {9, 2, 0, 11},
+ {10, 2, 0, 12},
+ {4, 4, 0, 12},
+ {14, 1, 0, 13},
+ {15, 1, 0, 13},
+ {16, 1, 0, 14},
+ {17, 1, 0, 14},
+ {0, 27, 0, 15},
+ {3, 9, 0, 15},
+ /* 010xxxx00 or 010xxxx01 */
+ {1, 2, 0, 5},
+ {0, 4, 0, 5},
+ {0, 5, 0, 6},
+ {0, 6, 0, 6},
+ {2, 2, 0, 7},
+ {1, 3, 0, 7},
+ {3, 2, 0, 8},
+ {4, 2, 0, 8},
+ {2, 3, 0, 9},
+ {3, 3, 0, 9},
+ {6, 2, 0, 10},
+ {7, 2, 0, 10},
+ {5, 3, 0, 11},
+ {6, 3, 0, 11},
+ {5, 4, 0, 12},
+ {6, 4, 0, 12},
+ {11, 2, 0, 13},
+ {8, 3, 0, 13},
+ {18, 1, 0, 14},
+ {8, 4, 0, 14},
+ {6, 5, 0, 15},
+ {7, 5, 0, 15},
+ /* 0110xxxx00 or 0110xxxx01 */
+ {3, 1, 1, 6},
+ {4, 1, 1, 6},
+ {0, 7, 0, 7},
+ {7, 1, 1, 7},
+ {1, 4, 0, 8},
+ {1, 5, 0, 8},
+ {1, 6, 0, 9},
+ {0, 10, 0, 9},
+ {8, 2, 0, 10},
+ {4, 3, 0, 10},
+ {7, 3, 0, 11},
+ {3, 4, 0, 11},
+ {3, 5, 0, 12},
+ {4, 5, 0, 12},
+ {9, 3, 0, 13},
+ {7, 4, 0, 13},
+ {5, 5, 0, 14},
+ {4, 6, 0, 14},
+ {9, 4, 0, 15},
+ {12, 2, 0, 15},
+ /* 01110xxxx00 or 01110xxxx01 */
+ {8, 1, 1, 7},
+ {9, 1, 1, 7},
+ {0, 8, 0, 8},
+ {0, 9, 0, 8},
+ {0, 11, 0, 9},
+ {1, 2, 1, 9},
+ {2, 4, 0, 10},
+ {1, 7, 0, 10},
+ {2, 5, 0, 11},
+ {2, 6, 0, 11},
+ {1, 10, 0, 12},
+ {0, 18, 0, 12},
+ {3, 6, 0, 13},
+ {2, 7, 0, 13},
+ {5, 6, 0, 14},
+ {3, 7, 0, 14},
+ {19, 1, 0, 15},
+ {1, 5, 1, 15},
+ /* 011110xxxx00 or 011110xxxx01 */
+ {0, 2, 1, 8},
+ {12, 1, 1, 8},
+ {15, 1, 1, 9},
+ {16, 1, 1, 9},
+ {0, 12, 0, 10},
+ {0, 13, 0, 10},
+ {1, 8, 0, 11},
+ {1, 9, 0, 11},
+ {0, 19, 0, 12},
+ {0, 22, 0, 12},
+ {2, 8, 0, 13},
+ {2, 9, 0, 13},
+ {3, 8, 0, 14},
+ {2, 10, 0, 14},
+ {2, 3, 1, 15},
+ {13, 2, 1, 15},
+ /* 0111110xxxx00 or 0111110xxxx01 */
+ {17, 1, 1, 9},
+ {18, 1, 1, 9},
+ {0, 14, 0, 10},
+ {21, 1, 1, 10},
+ {0, 15, 0, 11},
+ {0, 16, 0, 11},
+ {1, 3, 1, 12},
+ {3, 2, 1, 12},
+ {1, 11, 0, 13},
+ {0, 20, 0, 13},
+ {2, 11, 0, 14},
+ {1, 12, 0, 14},
+ {41, 1, 1, 15},
+ {42, 1, 1, 15},
+ /* 01111110xxxx00 or 01111110xxxx01 */
+ {22, 1, 1, 10},
+ {23, 1, 1, 10},
+ {0, 17, 0, 11},
+ {0, 3, 1, 11},
+ {4, 2, 1, 12},
+ {29, 1, 1, 12},
+ {0, 21, 0, 13},
+ {0, 23, 0, 13},
+ {1, 13, 0, 14},
+ {0, 24, 0, 14},
+ {43, 1, 1, 15},
+ {44, 1, 1, 15},
+ /* 011111110xxxx00 or 011111110xxxx01 */
+ {2, 2, 1, 11},
+ {26, 1, 1, 11},
+ {30, 1, 1, 12},
+ {31, 1, 1, 12},
+ {0, 4, 1, 13},
+ {5, 2, 1, 13},
+ {0, 25, 0, 14},
+ {0, 26, 0, 14},
+ /* 0111111110xxxx00 or 0111111110xxxx01 */
+ {32, 1, 1, 12},
+ {33, 1, 1, 12},
+ {6, 2, 1, 13},
+ {7, 2, 1, 13},
+ {0, 5, 1, 14},
+ {1, 4, 1, 14},
+ /* 01111111110xxxx00 or 01111111110xxxx01 */
+ {8, 2, 1, 13},
+ {9, 2, 1, 13},
+ {10, 2, 1, 14},
+ {11, 2, 1, 14},
+ /* 011111111110xxxx00 or 011111111110xxxx01 */
+ {12, 2, 1, 14},
+ {38, 1, 1, 14},
+ /* 1xxxx10 or 1xxxx11 from 11 zeros to 0 zeros*/
+ {0, 1, 0, 3},
+ {0, 2, 0, 3},
+ {0, 3, 0, 4},
+ {0, 1, 1, 4},
+ {1, 1, 1, 5},
+ {2, 1, 1, 5},
+ {5, 1, 1, 6},
+ {6, 1, 1, 6},
+ {10, 1, 1, 7},
+ {11, 1, 1, 7},
+ {13, 1, 1, 8},
+ {14, 1, 1, 8},
+ {19, 1, 1, 9},
+ {20, 1, 1, 9},
+ {24, 1, 1, 10},
+ {25, 1, 1, 10},
+ {27, 1, 1, 11},
+ {28, 1, 1, 11},
+ {34, 1, 1, 12},
+ {35, 1, 1, 12},
+ {36, 1, 1, 13},
+ {37, 1, 1, 13},
+ {39, 1, 1, 14},
+ {40, 1, 1, 14}
+};
+
+const VLCtab2 RvlcDCTtabInter[170] = /* 00xxxx00 or 00xxxx01 */
+{
+ {27, 255, 0, 5}, /* 0000 is escape code */
+ {0, 2, 0, 4},
+ {0, 3, 0, 5},
+ {3, 1, 0, 5},
+ {1, 2, 0, 6},
+ {6, 1, 0, 6},
+ {0, 4, 0, 7},
+ {2, 2, 0, 7},
+ {0, 5, 0, 8},
+ {0, 6, 0, 8},
+ {0, 7, 0, 9},
+ {1, 4, 0, 9},
+ {0, 8, 0, 10},
+ {0, 9, 0, 10},
+ {0, 10, 0, 11},
+ {0, 11, 0, 11},
+ {0, 12, 0, 12},
+ {1, 7, 0, 12},
+ {0, 13, 0, 13},
+ {0, 14, 0, 13},
+ {0, 17, 0, 14},
+ {0, 18, 0, 14},
+ {0, 19, 0, 15},
+ {3, 7, 0, 15},
+ /* 010xxxx00 or 010xxxx01 */
+ {4, 1, 0, 5},
+ {5, 1, 0, 5},
+ {7, 1, 0, 6},
+ {8, 1, 0, 6},
+ {9, 1, 0, 7},
+ {10, 1, 0, 7},
+ {1, 3, 0, 8},
+ {3, 2, 0, 8},
+ {2, 3, 0, 9},
+ {5, 2, 0, 9},
+ {1, 5, 0, 10},
+ {3, 3, 0, 10},
+ {1, 6, 0, 11},
+ {2, 4, 0, 11},
+ {2, 5, 0, 12},
+ {3, 4, 0, 12},
+ {0, 15, 0, 13},
+ {0, 16, 0, 13},
+ {1, 9, 0, 14},
+ {1, 10, 0, 14},
+ {4, 5, 0, 15},
+ {7, 4, 0, 15},
+ /* 0110xxxx00 or 0110xxxx01 */
+ {3, 1, 1, 6},
+ {4, 1, 1, 6},
+ {11, 1, 0, 7},
+ {7, 1, 1, 7},
+ {4, 2, 0, 8},
+ {12, 1, 0, 8},
+ {15, 1, 0, 9},
+ {16, 1, 0, 9},
+ {6, 2, 0, 10},
+ {7, 2, 0, 10},
+ {4, 3, 0, 11},
+ {5, 3, 0, 11},
+ {6, 3, 0, 12},
+ {7, 3, 0, 12},
+ {1, 8, 0, 13},
+ {3, 5, 0, 13},
+ {2, 6, 0, 14},
+ {2, 7, 0, 14},
+ {17, 2, 0, 15},
+ {37, 1, 0, 15},
+ /* 01110xxxx00 or 01110xxxx01 */
+ {8, 1, 1, 7},
+ {9, 1, 1, 7},
+ {13, 1, 0, 8},
+ {14, 1, 0, 8},
+ {17, 1, 0, 9},
+ {1, 2, 1, 9},
+ {8, 2, 0, 10},
+ {9, 2, 0, 10},
+ {10, 2, 0, 11},
+ {21, 1, 0, 11},
+ {11, 2, 0, 12},
+ {27, 1, 0, 12},
+ {4, 4, 0, 13},
+ {5, 4, 0, 13},
+ {3, 6, 0, 14},
+ {6, 4, 0, 14},
+ {38, 1, 0, 15},
+ {1, 5, 1, 15},
+ /* 011110xxxx00 or 011110xxxx01 */
+ {0, 2, 1, 8},
+ {12, 1, 1, 8},
+ {15, 1, 1, 9},
+ {16, 1, 1, 9},
+ {18, 1, 0, 10},
+ {19, 1, 0, 10},
+ {22, 1, 0, 11},
+ {23, 1, 0, 11},
+ {28, 1, 0, 12},
+ {29, 1, 0, 12},
+ {8, 3, 0, 13},
+ {12, 2, 0, 13},
+ {9, 3, 0, 14},
+ {13, 2, 0, 14},
+ {2, 3, 1, 15},
+ {13, 2, 1, 15},
+ /* 0111110xxxx00 or 0111110xxxx01 */
+ {17, 1, 1, 9},
+ {18, 1, 1, 9},
+ {20, 1, 0, 10},
+ {21, 1, 1, 10},
+ {24, 1, 0, 11},
+ {25, 1, 0, 11},
+ {1, 3, 1, 12},
+ {3, 2, 1, 12},
+ {30, 1, 0, 13},
+ {31, 1, 0, 13},
+ {14, 2, 0, 14},
+ {15, 2, 0, 14},
+ {41, 1, 1, 15},
+ {42, 1, 1, 15},
+ /* 01111110xxxx00 or 01111110xxxx01 */
+ {22, 1, 1, 10},
+ {23, 1, 1, 10},
+ {26, 1, 0, 11},
+ {0, 3, 1, 11},
+ {4, 2, 1, 12},
+ {29, 1, 1, 12},
+ {32, 1, 0, 13},
+ {33, 1, 0, 13},
+ {16, 2, 0, 14},
+ {34, 1, 0, 14},
+ {43, 1, 1, 15},
+ {44, 1, 1, 15},
+ /* 011111110xxxx00 or 011111110xxxx01 */
+ {2, 2, 1, 11},
+ {26, 1, 1, 11},
+ {30, 1, 1, 12},
+ {31, 1, 1, 12},
+ {0, 4, 1, 13},
+ {5, 2, 1, 13},
+ {35, 1, 0, 14},
+ {36, 1, 0, 14},
+ /* 0111111110xxxx00 or 0111111110xxxx01 */
+ {32, 1, 1, 12},
+ {33, 1, 1, 12},
+ {6, 2, 1, 13},
+ {7, 2, 1, 13},
+ {0, 5, 1, 14},
+ {1, 4, 1, 14},
+ /* 01111111110xxxx00 or 01111111110xxxx01 */
+ {8, 2, 1, 13},
+ {9, 2, 1, 13},
+ {10, 2, 1, 14},
+ {11, 2, 1, 14},
+ /* 011111111110xxxx00 or 011111111110xxxx01 */
+ {12, 2, 1, 14},
+ {38, 1, 1, 14},
+ /* 1xxxx10 or 1xxxx11 from 11 zeros to 0 zeros*/
+ {0, 1, 0, 3},
+ {1, 1, 0, 3},
+ {2, 1, 0, 4},
+ {0, 1, 1, 4},
+ {1, 1, 1, 5},
+ {2, 1, 1, 5},
+ {5, 1, 1, 6},
+ {6, 1, 1, 6},
+ {10, 1, 1, 7},
+ {11, 1, 1, 7},
+ {13, 1, 1, 8},
+ {14, 1, 1, 8},
+ {19, 1, 1, 9},
+ {20, 1, 1, 9},
+ {24, 1, 1, 10},
+ {25, 1, 1, 10},
+ {27, 1, 1, 11},
+ {28, 1, 1, 11},
+ {34, 1, 1, 12},
+ {35, 1, 1, 12},
+ {36, 1, 1, 13},
+ {37, 1, 1, 13},
+ {39, 1, 1, 14},
+ {40, 1, 1, 14}
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Define all local variables
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Function body here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Return nothing or data or data pointer
+----------------------------------------------------------------------------*/
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
new file mode 100644
index 0000000..b3c350f
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
@@ -0,0 +1,1643 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_lib.h"
+#include "bitstream.h"
+#include "vlc_decode.h"
+#include "zigzag.h"
+
+#define OSCL_DISABLE_WARNING_CONV_POSSIBLE_LOSS_OF_DATA
+
+#ifdef PV_SUPPORT_MAIN_PROFILE
+/* 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
+};
+#endif
+
+/* ======================================================================== */
+/* Function : CalcNumBits() */
+/* Purpose : */
+/* In/out : */
+/* Return : Calculate the minimum number of bits required to */
+/* represent x. */
+/* Note : This is an equivalent implementation of */
+/* (long)ceil(log((double)x)/log(2.0)) */
+/* Modified : */
+/* ======================================================================== */
+int CalcNumBits(uint x)
+{
+ int i = 1;
+ while (x >>= 1) i++;
+ return i;
+}
+
+
+
+/***********************************************************CommentBegin******
+*
+* -- DecodeVolHeader -- Decode the header of a VOL
+*
+* 04/10/2000 : initial modification to the new PV-Decoder Lib format.
+* 10/12/2001 : reject non compliant bitstreams
+*
+***********************************************************CommentEnd********/
+PV_STATUS DecodeVOLHeader(VideoDecData *video, int layer)
+{
+ PV_STATUS status;
+ Vol *currVol;
+ BitstreamDecVideo *stream;
+ uint32 tmpvar, vol_shape;
+ uint32 startCode;
+#ifdef PV_SUPPORT_MAIN_PROFILE
+ int *qmat, i, j;
+#endif
+ int version_id = 1;
+#ifdef PV_TOLERATE_VOL_ERRORS
+ uint32 profile = 0x01;
+#endif
+ /* There's a "currLayer" variable inside videoDecData. */
+ /* However, we don't maintain it until we decode frame data. 04/05/2000 */
+ currVol = video->vol[layer];
+ stream = currVol->bitstream;
+ currVol->moduloTimeBase = 0;
+
+ /* Determine which start code for the decoder to begin with */
+ status = BitstreamShowBits32HC(stream, &startCode);
+
+ if (startCode == VISUAL_OBJECT_SEQUENCE_START_CODE)
+ { /* Bitstream Exhchange Fix 9/99 */
+ /* Bitstream Exchange requires we allow start with Video Object Sequence */
+ /* visual_object_sequence_start_code */
+ (void) BitstreamReadBits32HC(stream);
+ tmpvar = (uint32) BitstreamReadBits16(stream, 8); /* profile */
+#ifndef PV_TOLERATE_VOL_ERRORS
+ if (layer) /* */
+ {
+ /* support SSPL0-2 */
+ if (tmpvar != 0x10 && tmpvar != 0x11 && tmpvar != 0x12 &&
+ tmpvar != 0xA1 && tmpvar != 0xA2 && tmpvar != 0xA3/* Core SP@L1-L3 */)
+ return PV_FAIL;
+ }
+ else
+ {
+ /* support SPL0-3 & SSPL0-2 */
+ if (tmpvar != 0x01 && tmpvar != 0x02 && tmpvar != 0x03 && tmpvar != 0x08 &&
+ tmpvar != 0x10 && tmpvar != 0x11 && tmpvar != 0x12 &&
+ tmpvar != 0x21 && tmpvar != 0x22 && /* Core Profile Levels */
+ tmpvar != 0xA1 && tmpvar != 0xA2 && tmpvar != 0xA3 &&
+ tmpvar != 0xF0 && tmpvar != 0xF1 && /* Advanced Simple Profile Levels*/
+ tmpvar != 0xF2 && tmpvar != 0xF3 &&
+ tmpvar != 0xF4 && tmpvar != 0xF5)
+ return PV_FAIL;
+ }
+#else
+ profile = tmpvar;
+#endif
+
+ // save the profile and level for the query
+ currVol->profile_level_id = (uint)tmpvar; // 6/10/04
+
+
+
+ status = BitstreamShowBits32HC(stream, &tmpvar);
+ if (tmpvar == USER_DATA_START_CODE)
+ {
+ /* Something has to be done with user data 11/11/99 */
+ status = DecodeUserData(stream);
+ if (status != PV_SUCCESS) return PV_FAIL;
+ }
+ /* visual_object_start_code */
+ BitstreamShowBits32HC(stream, &tmpvar);
+ if (tmpvar != VISUAL_OBJECT_START_CODE)
+ {
+ do
+ {
+ /* Search for VOL_HEADER */
+ status = PVSearchNextM4VFrame(stream); /* search 0x00 0x00 0x01 */
+ if (status != PV_SUCCESS) return PV_FAIL; /* breaks the loop */
+ BitstreamShowBits32(stream, VOL_START_CODE_LENGTH, &tmpvar);
+ PV_BitstreamFlushBits(stream, 8);
+ }
+ while (tmpvar != VOL_START_CODE);
+ goto decode_vol;
+ }
+ else
+ {
+ BitstreamReadBits32HC(stream);
+ }
+
+ /* is_visual_object_identifier */
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+ if (tmpvar)
+ {
+ /* visual_object_verid */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 4);
+ /* visual_object_priority */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 3);
+ }
+ /* visual_object_type */
+ BitstreamShowBits32(stream, 4, &tmpvar);
+ if (tmpvar == 1)
+ { /* video_signal_type */
+ PV_BitstreamFlushBits(stream, 4);
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+ if (tmpvar == 1)
+ {
+ /* video_format */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 3);
+ /* video_range */
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+ /* color_description */
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+ if (tmpvar == 1)
+ {
+ /* color_primaries */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 8);
+ /* transfer_characteristics */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 8);
+ /* matrix_coefficients */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 8);
+ }
+ }
+ }
+ else
+ {
+ do
+ {
+ /* Search for VOL_HEADER */
+ status = PVSearchNextM4VFrame(stream); /* search 0x00 0x00 0x01 */
+ if (status != PV_SUCCESS) return PV_FAIL; /* breaks the loop */
+ BitstreamShowBits32(stream, VOL_START_CODE_LENGTH, &tmpvar);
+ PV_BitstreamFlushBits(stream, 8);
+ }
+ while (tmpvar != VOL_START_CODE);
+ goto decode_vol;
+ }
+
+ /* next_start_code() */
+ status = PV_BitstreamByteAlign(stream); /* 10/12/01 */
+ status = BitstreamShowBits32HC(stream, &tmpvar);
+
+ if (tmpvar == USER_DATA_START_CODE)
+ {
+ /* Something has to be done to deal with user data (parse it) 11/11/99 */
+ status = DecodeUserData(stream);
+ if (status != PV_SUCCESS) return PV_FAIL;
+ }
+ status = BitstreamShowBits32(stream, 27, &tmpvar); /* 10/12/01 */
+ }
+ else
+ {
+ /* tmpvar = 0; */ /* 10/12/01 */
+ status = BitstreamShowBits32(stream, 27, &tmpvar); /* uncomment this line if you want
+ to start decoding with a
+ video_object_start_code */
+ }
+
+ if (tmpvar == VO_START_CODE)
+ {
+ /*****
+ *
+ * Read the VOL header entries from the bitstream
+ *
+ *****/
+ /* video_object_start_code */
+ tmpvar = BitstreamReadBits32(stream, 27);
+ tmpvar = (uint32) BitstreamReadBits16(stream, 5);
+
+
+ /* video_object_layer_start_code */
+ BitstreamShowBits32(stream, VOL_START_CODE_LENGTH, &tmpvar);
+ if (tmpvar != VOL_START_CODE)
+ {
+ status = BitstreamCheckEndBuffer(stream);
+ if (status == PV_END_OF_VOP)
+ {
+ video->shortVideoHeader = TRUE;
+ return PV_SUCCESS;
+ }
+ else
+ {
+ do
+ {
+ /* Search for VOL_HEADER */
+ status = PVSearchNextM4VFrame(stream);/* search 0x00 0x00 0x01 */
+ if (status != PV_SUCCESS) return PV_FAIL; /* breaks the loop */
+ BitstreamShowBits32(stream, VOL_START_CODE_LENGTH, &tmpvar);
+ PV_BitstreamFlushBits(stream, 8); /* advance the byte ptr */
+ }
+ while (tmpvar != VOL_START_CODE);
+ }
+ }
+ else
+ {
+ PV_BitstreamFlushBits(stream, 8);
+ }
+
+decode_vol:
+ PV_BitstreamFlushBits(stream, VOL_START_CODE_LENGTH - 8);
+ video->shortVideoHeader = 0;
+
+ /* vol_id (4 bits) */
+ currVol->volID = (int) BitstreamReadBits16(stream, 4);
+
+ /* RandomAccessible flag */
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+
+ /* object type */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 8); /* */
+
+#ifdef PV_TOLERATE_VOL_ERRORS
+ if (tmpvar == 0)
+ {
+ if (layer) /* */
+ {
+ /* support SSPL0-2 */
+ if (profile != 0x10 && profile != 0x11 && profile != 0x12)
+ return PV_FAIL;
+ tmpvar = 0x02;
+ }
+ else
+ {
+ /* support SPL0-3 & SSPL0-2 */
+ if (profile != 0x01 && profile != 0x02 && profile != 0x03 && profile != 0x08 &&
+ profile != 0x10 && profile != 0x11 && profile != 0x12)
+ return PV_FAIL;
+ tmpvar = 0x01;
+ }
+ profile |= 0x0100;
+ }
+#endif
+
+ if (layer)
+ {
+ if (tmpvar != 0x02) return PV_FAIL;
+ }
+ else
+ {
+ if (tmpvar != 0x01) return PV_FAIL;
+ }
+
+ /* version id specified? */
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+ if (tmpvar == 1)
+ {
+ /* version ID */
+ version_id = (uint32) BitstreamReadBits16(stream, 4);
+ /* priority */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 3);
+
+ }
+
+ /* aspect ratio info */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 4);
+ if (tmpvar == 0) return PV_FAIL;
+ if (tmpvar == 0xf /* extended_par */)
+ {
+ /* width */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 8);
+ /* height */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 8);
+ }
+
+
+ /* control parameters present? */
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+
+ /* Get the parameters (skipped) */
+ /* 03/10/99 */
+ if (tmpvar)
+ {
+ /* chroma_format */
+ tmpvar = BitstreamReadBits16(stream, 2);
+ if (tmpvar != 1) return PV_FAIL;
+ /* low_delay */
+ tmpvar = BitstreamRead1Bits(stream);
+
+ /* vbv_parameters present? */
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+ if (tmpvar)
+ {
+ /* first_half_bit_rate */
+ BitstreamReadBits16(stream, 15);
+ if (!BitstreamRead1Bits(stream)) return PV_FAIL;
+ /* latter_half_bit_rate */
+ BitstreamReadBits16(stream, 15);
+ if (!BitstreamRead1Bits(stream)) return PV_FAIL;
+ /* first_half_vbv_buffer_size */
+ BitstreamReadBits16(stream, 15);
+ if (!BitstreamRead1Bits(stream)) return PV_FAIL;
+ /* latter_half_vbv_buffer_size */
+ BitstreamReadBits16(stream, 3);
+ /* first_half_vbv_occupancy */
+ BitstreamReadBits16(stream, 11);
+ if (!BitstreamRead1Bits(stream)) return PV_FAIL;
+ /* latter_half_vbv_occupancy */
+ BitstreamReadBits16(stream, 15);
+ if (!BitstreamRead1Bits(stream)) return PV_FAIL;
+ }
+ }
+
+ /* video_object_layer_shape (2 bits), only 00 (rect) is supported for now */
+ vol_shape = (uint32) BitstreamReadBits16(stream, 2);
+ if (vol_shape) return PV_FAIL;
+
+ /* marker bit, 03/10/99 */
+ if (!BitstreamRead1Bits(stream)) return PV_FAIL;
+
+ /* vop_time_increment_resolution */
+ currVol->timeIncrementResolution = BitstreamReadBits16(stream, 16);
+ if (currVol->timeIncrementResolution == 0) return PV_FAIL;
+
+ /* . since nbitsTimeIncRes will be used over and over again, */
+ /* we should put it in Vol structure. 04/12/2000. */
+ currVol->nbitsTimeIncRes = CalcNumBits((uint)currVol->timeIncrementResolution - 1);
+
+ if (!BitstreamRead1Bits(stream)) return PV_FAIL;
+
+ /* fixed_vop_rate */
+ currVol->fixedVopRate = (int) BitstreamRead1Bits(stream);
+ if (currVol->fixedVopRate)
+ {
+ /* fixed_vop_time_increment */
+ tmpvar = BitstreamReadBits16(stream, currVol->nbitsTimeIncRes);
+ }
+
+ /* marker bit */
+ if (!BitstreamRead1Bits(stream)) return PV_FAIL;
+
+ /* video_object_layer_width (13 bits) */
+ video->displayWidth = video->width = (int) BitstreamReadBits16(stream, 13);
+
+ /* round up to a multiple of MB_SIZE. 08/09/2000 */
+ video->width = (video->width + 15) & -16;
+// video->displayWidth += (video->displayWidth & 0x1); /* displayed image should be even size */
+
+ /* marker bit */
+ if (!BitstreamRead1Bits(stream)) return PV_FAIL;
+
+ /* video_object_layer_height (13 bits) */
+ video->displayHeight = video->height = (int) BitstreamReadBits16(stream, 13);
+
+ /* round up to a multiple of MB_SIZE. 08/09/2000 */
+ video->height = (video->height + 15) & -16;
+// video->displayHeight += (video->displayHeight & 0x1); /* displayed image should be even size */
+ if (!BitstreamRead1Bits(stream)) return PV_FAIL;
+
+ /* 03/10/99 */
+ /* interlaced */
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+ if (tmpvar != 0)
+ {
+ mp4dec_log("DecodeVOLHeader(): Interlaced video is not supported.\n");
+ return PV_FAIL;
+ }
+
+ /* obmc_disable */
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+ if (tmpvar == 0) return PV_FAIL;
+
+ if (version_id == 1)
+ {
+ /* sprite_enable (1 bits) */
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+ if (tmpvar)
+ {
+ mp4dec_log("DecodeVOLHeader(): Sprite is not supported.\n");
+ return PV_FAIL;
+ }
+ }
+ else
+ {
+ /* For version 2, vol_sprite_usage has two bits. */
+ /* sprite_enable */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 2);
+ if (tmpvar)
+ {
+ mp4dec_log("DecodeVOLHeader(): Sprite is not supported.\n");
+ return PV_FAIL;
+ }
+ }
+
+ /* not_8_bit */
+ if (BitstreamRead1Bits(stream))
+ {
+ /* quant_precision */
+ currVol->quantPrecision = BitstreamReadBits16(stream, 4);
+ /* bits_per_pixel */
+ currVol->bitsPerPixel = BitstreamReadBits16(stream, 4);
+ mp4dec_log("DecodeVOLHeader(): not an 8-bit stream.\n"); // For the time being we do not support != 8 bits
+
+ return PV_FAIL;
+ }
+ else
+ {
+ currVol->quantPrecision = 5;
+ currVol->bitsPerPixel = 8;
+ }
+
+ /* quant_type (1 bit) */
+ currVol->quantType = BitstreamRead1Bits(stream);
+ if (currVol->quantType)
+ {
+#ifdef PV_SUPPORT_MAIN_PROFILE
+ /* load quantization matrices. 5/22/2000 */
+ /* load_intra_quant_mat (1 bit) */
+ qmat = currVol->iqmat;
+ currVol->loadIntraQuantMat = BitstreamRead1Bits(stream);
+ if (currVol->loadIntraQuantMat)
+ {
+ /* intra_quant_mat (8*64 bits) */
+ i = 0;
+ do
+ {
+ qmat[*(zigzag_inv+i)] = (int) BitstreamReadBits16(stream, 8);
+ }
+ while ((qmat[*(zigzag_inv+i)] != 0) && (++i < 64));
+
+ for (j = i; j < 64; j++)
+ qmat[*(zigzag_inv+j)] = qmat[*(zigzag_inv+i-1)];
+ }
+ else
+ {
+ oscl_memcpy(qmat, mpeg_iqmat_def, 64*sizeof(int));
+ }
+
+ qmat[0] = 0; /* necessary for switched && MPEG quant 07/09/01 */
+
+ /* load_nonintra_quant_mat (1 bit) */
+ qmat = currVol->niqmat;
+ currVol->loadNonIntraQuantMat = BitstreamRead1Bits(stream);
+ if (currVol->loadNonIntraQuantMat)
+ {
+ /* nonintra_quant_mat (8*64 bits) */
+ i = 0;
+ do
+ {
+ qmat[*(zigzag_inv+i)] = (int) BitstreamReadBits16(stream, 8);
+ }
+ while ((qmat[*(zigzag_inv+i)] != 0) && (++i < 64));
+
+ for (j = i; j < 64; j++)
+ qmat[*(zigzag_inv+j)] = qmat[*(zigzag_inv+i-1)];
+ }
+ else
+ {
+ oscl_memcpy(qmat, mpeg_nqmat_def, 64*sizeof(int));
+ }
+#else
+ return PV_FAIL;
+#endif
+ }
+
+ if (version_id != 1)
+ {
+ /* quarter_sample enabled */
+ tmpvar = BitstreamRead1Bits(stream);
+ if (tmpvar) return PV_FAIL;
+ }
+
+ /* complexity_estimation_disable */
+ currVol->complexity_estDisable = BitstreamRead1Bits(stream);
+ if (currVol->complexity_estDisable == 0)
+ {
+ currVol->complexity_estMethod = BitstreamReadBits16(stream, 2);
+
+ if (currVol->complexity_estMethod < 2)
+ {
+ /* shape_complexity_estimation_disable */
+ tmpvar = BitstreamRead1Bits(stream);
+ if (tmpvar == 0)
+ {
+ mp4dec_log("DecodeVOLHeader(): Shape Complexity estimation is not supported.\n");
+ return PV_FAIL;
+ }
+ /* texture_complexity_estimation_set_1_disable */
+ tmpvar = BitstreamRead1Bits(stream);
+ if (tmpvar == 0)
+ {
+ currVol->complexity.text_1 = BitstreamReadBits16(stream, 4);
+ }
+ /* marker bit */
+ if (!BitstreamRead1Bits(stream)) return PV_FAIL;
+ /* texture_complexity_estimation_set_2_disable */
+ tmpvar = BitstreamRead1Bits(stream);
+ if (tmpvar == 0)
+ {
+ currVol->complexity.text_2 = BitstreamReadBits16(stream, 4);
+ }
+ /* motion_compensation_complexity_disable */
+ tmpvar = BitstreamRead1Bits(stream);
+ if (tmpvar == 0)
+ {
+ currVol->complexity.mc = BitstreamReadBits16(stream, 6);
+ }
+ /* marker bit */
+ if (!BitstreamRead1Bits(stream)) return PV_FAIL;
+
+ if (currVol->complexity_estMethod == 1)
+ { /* version2_complexity_estimation_disable */
+ tmpvar = BitstreamRead1Bits(stream);
+ if (tmpvar == 0)
+ {
+ mp4dec_log("DecodeVOLHeader(): sadct, quarter pel not supported.\n");
+ return PV_FAIL;
+ }
+ }
+ }
+ }
+
+ /* 03/10/99 */
+ /* resync_marker_disable */
+ currVol->errorResDisable = (int) BitstreamRead1Bits(stream);
+ /* data_partititioned */
+ currVol->dataPartitioning = (int) BitstreamRead1Bits(stream);
+
+ video->vlcDecCoeffIntra = &VlcDecTCOEFIntra;
+ video->vlcDecCoeffInter = &VlcDecTCOEFInter;
+
+ if (currVol->dataPartitioning)
+ {
+ if (layer) return PV_FAIL; /* */
+ /* reversible_vlc */
+ currVol->useReverseVLC = (int)BitstreamRead1Bits(stream);
+ if (currVol->useReverseVLC)
+ {
+ video->vlcDecCoeffIntra = &RvlcDecTCOEFIntra;
+ video->vlcDecCoeffInter = &RvlcDecTCOEFInter;
+ }
+ currVol->errorResDisable = 0;
+ }
+ else
+ {
+ currVol->useReverseVLC = 0;
+ }
+
+ if (version_id != 1)
+ {
+ /* newpred_enable */
+ tmpvar = BitstreamRead1Bits(stream);
+ if (tmpvar) return PV_FAIL;
+
+ /* reduced_resolution_vop */
+ tmpvar = BitstreamRead1Bits(stream);
+ if (tmpvar) return PV_FAIL;
+
+ }
+
+ /* Intra AC/DC prediction is always true */
+ video->intra_acdcPredDisable = 0;
+ /* scalability */
+ currVol->scalability = (int) BitstreamRead1Bits(stream);
+
+ if (currVol->scalability)
+ {
+ if (layer == 0) return PV_FAIL; /* */
+ /* hierarchy_type: 1 : temporal, 0 : spatial */
+ /* 03/10/99 */
+ currVol->scalType = (int) BitstreamRead1Bits(stream); /* */
+ if (!currVol->scalType) return PV_FAIL;
+
+ /* ref_layer_id (4 bits) */
+ currVol->refVolID = (int) BitstreamReadBits16(stream, 4);
+ if (layer) /* */
+ {
+ if (currVol->refVolID != video->vol[0]->volID) return PV_FAIL;
+ }
+ /* ref_layer_sampling_direc (1 bits) */
+ /* 1 : ref. layer has higher resolution */
+ /* 0 : ref. layer has equal or lower resolution */
+ currVol->refSampDir = (int) BitstreamRead1Bits(stream);
+ if (currVol->refSampDir) return PV_FAIL;
+
+ /* hor_sampling_factor_n (5 bits) */
+ currVol->horSamp_n = (int) BitstreamReadBits16(stream, 5);
+
+ /* hor_sampling_factor_m (5 bits) */
+ currVol->horSamp_m = (int) BitstreamReadBits16(stream, 5);
+
+ if (currVol->horSamp_m == 0) return PV_FAIL;
+ if (currVol->horSamp_n != currVol->horSamp_m) return PV_FAIL;
+
+ /* ver_sampling_factor_n (5 bits) */
+ currVol->verSamp_n = (int) BitstreamReadBits16(stream, 5);
+
+ /* ver_sampling_factor_m (5 bits) */
+ currVol->verSamp_m = (int) BitstreamReadBits16(stream, 5);
+
+ if (currVol->verSamp_m == 0) return PV_FAIL;
+ if (currVol->verSamp_n != currVol->verSamp_m) return PV_FAIL;
+
+
+ /* enhancement_type: 1 : partial region, 0 : full region */
+ /* 04/10/2000: we only support full region enhancement layer. */
+ if (BitstreamRead1Bits(stream)) return PV_FAIL;
+ }
+
+ PV_BitstreamByteAlign(stream);
+
+ status = BitstreamShowBits32HC(stream, &tmpvar);
+
+ /* if we hit the end of buffer, tmpvar == 0. 08/30/2000 */
+ if (tmpvar == USER_DATA_START_CODE)
+ {
+ status = DecodeUserData(stream);
+ /* you should not check for status here 03/19/2002 */
+ status = PV_SUCCESS;
+ }
+
+ /* Compute some convenience variables: 04/13/2000 */
+ video->nMBPerRow = video->width / MB_SIZE;
+ video->nMBPerCol = video->height / MB_SIZE;
+ video->nTotalMB = video->nMBPerRow * video->nMBPerCol;
+ video->nBitsForMBID = CalcNumBits((uint)video->nTotalMB - 1);
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ video->modified_quant = 0;
+ video->advanced_INTRA = 0;
+ video->deblocking = 0;
+ video->slice_structure = 0;
+#endif
+ }
+ else
+ {
+ /* SHORT_HEADER */
+ status = BitstreamShowBits32(stream, SHORT_VIDEO_START_MARKER_LENGTH, &tmpvar);
+
+ if (tmpvar == SHORT_VIDEO_START_MARKER)
+ {
+ video->shortVideoHeader = TRUE;
+ }
+ else
+ {
+ do
+ {
+ /* Search for VOL_HEADER */
+ status = PVSearchNextM4VFrame(stream); /* search 0x00 0x00 0x01 */
+ if (status != PV_SUCCESS) return PV_FAIL; /* breaks the loop */
+ BitstreamShowBits32(stream, VOL_START_CODE_LENGTH, &tmpvar);
+ PV_BitstreamFlushBits(stream, 8);
+ }
+ while (tmpvar != VOL_START_CODE);
+ goto decode_vol;
+ }
+ }
+#ifdef PV_TOLERATE_VOL_ERRORS
+ if (profile > 0xFF || profile == 0)
+ {
+ return PV_BAD_VOLHEADER;
+ }
+#endif
+
+ return status;
+}
+
+
+/***********************************************************CommentBegin******
+*
+* -- DecodeGOV -- Decodes the Group of VOPs from bitstream
+*
+* 04/20/2000 initial modification to the new PV-Decoder Lib format.
+*
+***********************************************************CommentEnd********/
+PV_STATUS DecodeGOVHeader(BitstreamDecVideo *stream, uint32 *time_base)
+{
+ uint32 tmpvar, time_s;
+ int closed_gov, broken_link;
+
+ /* group_start_code (32 bits) */
+// tmpvar = BitstreamReadBits32(stream, 32);
+
+ /* hours */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 5);
+ time_s = tmpvar * 3600;
+
+ /* minutes */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 6);
+ time_s += tmpvar * 60;
+
+ /* marker bit */
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+
+ /* seconds */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 6);
+ time_s += tmpvar;
+
+ /* We have to check the timestamp here. If the sync timestamp is */
+ /* earlier than the previous timestamp or longer than 60 sec. */
+ /* after the previous timestamp, assume the GOV header is */
+ /* corrupted. 05/12/2000 */
+ *time_base = time_s; /* 02/27/2002 */
+// *time_base = *time_base/1000;
+// tmpvar = time_s - *time_base;
+// if (tmpvar <= 60) *time_base = time_s;
+// else return PV_FAIL;
+
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+ closed_gov = tmpvar;
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+ broken_link = tmpvar;
+
+ if ((closed_gov == 0) && (broken_link == 1))
+ {
+ return PV_SUCCESS; /* 03/15/2002 you can also return PV_FAIL */
+ }
+
+ PV_BitstreamByteAlign(stream);
+
+ BitstreamShowBits32HC(stream, &tmpvar);
+
+ while (tmpvar == USER_DATA_START_CODE) /* 03/15/2002 */
+ {
+ DecodeUserData(stream);
+ BitstreamShowBits32HC(stream, &tmpvar);
+ }
+
+ return PV_SUCCESS;
+}
+
+/***********************************************************CommentBegin******
+*
+* -- DecodeVopHeader -- Decodes the VOPheader information from the bitstream
+*
+* 04/12/2000 Initial port to the new PV decoder library format.
+* 05/10/2000 Error resilient decoding of vop header.
+*
+***********************************************************CommentEnd********/
+PV_STATUS DecodeVOPHeader(VideoDecData *video, Vop *currVop, Bool use_ext_timestamp)
+{
+ PV_STATUS status = PV_SUCCESS;
+ Vol *currVol = video->vol[video->currLayer];
+ BitstreamDecVideo *stream = currVol->bitstream;
+ uint32 tmpvar;
+ int time_base;
+
+ /*****
+ * Read the VOP header from the bitstream (No shortVideoHeader Mode here!)
+ *****/
+ BitstreamShowBits32HC(stream, &tmpvar);
+
+ /* check if we have a GOV header here. 08/30/2000 */
+ if (tmpvar == GROUP_START_CODE)
+ {
+ tmpvar = BitstreamReadBits32HC(stream);
+// rewindBitstream(stream, START_CODE_LENGTH); /* for backward compatibility */
+ status = DecodeGOVHeader(stream, &tmpvar);
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+// use_ext_timestamp = TRUE; /* 02/08/2002 */
+ /* We should have a VOP header following the GOV header. 03/15/2001 */
+ BitstreamShowBits32HC(stream, &tmpvar);
+ }
+#ifdef PV_SUPPORT_TEMPORAL_SCALABILITY
+ currVop->timeStamp = -1;
+#endif
+ if (tmpvar == VOP_START_CODE)
+ {
+ tmpvar = BitstreamReadBits32HC(stream);
+ }
+ else
+ {
+ PV_BitstreamFlushBits(stream, 8); // advance by a byte
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+
+
+ /* vop_prediction_type (2 bits) */
+ currVop->predictionType = (int) BitstreamReadBits16(stream, 2);
+
+ /* modulo_time_base (? bits) */
+ time_base = -1;
+ do
+ {
+ time_base++;
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+ }
+ while (tmpvar == 1);
+
+
+
+ if (!use_ext_timestamp)
+ {
+ currVol->moduloTimeBase += 1000 * time_base; /* milliseconds based MTB 11/12/01 */
+ }
+
+ /* marker_bit (1 bit) */
+ if (!BitstreamRead1Bits(stream))
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+ /* vop_time_increment (1-15 bits) in Nov_Compliant (1-16 bits) */
+ /* we always assumes fixed vop rate here */
+ currVop->timeInc = BitstreamReadBits16(stream, currVol->nbitsTimeIncRes);
+
+
+ /* marker_bit (1 bit) */
+ if (!BitstreamRead1Bits(stream))
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+ /* vop_coded */
+ currVop->vopCoded = (int) BitstreamRead1Bits(stream);
+
+
+ if (currVop->vopCoded == 0)
+ {
+ status = PV_SUCCESS;
+ goto return_point;
+ }
+
+
+ /* read vop_rounding_type */
+ if (currVop->predictionType == P_VOP)
+ {
+ currVop->roundingType = (int) BitstreamRead1Bits(stream);
+ }
+ else
+ {
+ currVop->roundingType = 0;
+ }
+
+ if (currVol->complexity_estDisable == 0)
+ {
+ if (currVol->complexity_estMethod < 2) /* OCT 2002 */
+ {
+ if ((currVol->complexity.text_1 >> 3) & 0x1) /* intra */
+ BitstreamReadBits16(stream, 8);
+ if (currVol->complexity.text_1 & 0x1) /* not_coded */
+ BitstreamReadBits16(stream, 8);
+ if ((currVol->complexity.text_2 >> 3) & 0x1) /* dct_coefs */
+ BitstreamReadBits16(stream, 8);
+ if ((currVol->complexity.text_2 >> 2) & 0x1) /* dct_lines */
+ BitstreamReadBits16(stream, 8);
+ if ((currVol->complexity.text_2 >> 1) & 0x1) /* vlc_symbols */
+ BitstreamReadBits16(stream, 8);
+ if (currVol->complexity.text_2 & 0x1) /* vlc_bits */
+ BitstreamReadBits16(stream, 4);
+
+ if (currVop->predictionType != I_VOP)
+ {
+ if ((currVol->complexity.text_1 >> 2) & 0x1) /* inter */
+ BitstreamReadBits16(stream, 8);
+ if ((currVol->complexity.text_1 >> 1) & 0x1) /* inter_4v */
+ BitstreamReadBits16(stream, 8);
+ if ((currVol->complexity.mc >> 5) & 0x1) /* apm */
+ BitstreamReadBits16(stream, 8);
+ if ((currVol->complexity.mc >> 4) & 0x1) /* npm */
+ BitstreamReadBits16(stream, 8);
+ /* interpolate_mc_q */
+ if ((currVol->complexity.mc >> 2) & 0x1) /* forw_back_mc_q */
+ BitstreamReadBits16(stream, 8);
+ if ((currVol->complexity.mc >> 1) & 0x1) /* halfpel2 */
+ BitstreamReadBits16(stream, 8);
+ if (currVol->complexity.mc & 0x1) /* halfpel4 */
+ BitstreamReadBits16(stream, 8);
+ }
+ if (currVop->predictionType == B_VOP)
+ {
+ if ((currVol->complexity.mc >> 3) & 0x1) /* interpolate_mc_q */
+ BitstreamReadBits16(stream, 8);
+ }
+ }
+ }
+
+ /* read intra_dc_vlc_thr */
+ currVop->intraDCVlcThr = (int) BitstreamReadBits16(stream, 3);
+
+ /* read vop_quant (currVol->quantPrecision bits) */
+ currVop->quantizer = (int16) BitstreamReadBits16(stream, currVol->quantPrecision);
+ if (currVop->quantizer == 0)
+ {
+ currVop->quantizer = video->prevVop->quantizer;
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+
+ /* read vop_fcode_forward */
+ if (currVop->predictionType != I_VOP)
+ {
+ tmpvar = (uint32) BitstreamReadBits16(stream, 3);
+ if (tmpvar < 1)
+ {
+ currVop->fcodeForward = 1;
+ status = PV_FAIL;
+ goto return_point;
+ }
+ currVop->fcodeForward = tmpvar;
+ }
+ else
+ {
+ currVop->fcodeForward = 0;
+ }
+
+ /* read vop_fcode_backward */
+ if (currVop->predictionType == B_VOP)
+ {
+ tmpvar = (uint32) BitstreamReadBits16(stream, 3);
+ if (tmpvar < 1)
+ {
+ currVop->fcodeBackward = 1;
+ status = PV_FAIL;
+ goto return_point;
+ }
+ currVop->fcodeBackward = tmpvar;
+ }
+ else
+ {
+ currVop->fcodeBackward = 0;
+ }
+
+ if (currVol->scalability)
+ {
+ currVop->refSelectCode = (int) BitstreamReadBits16(stream, 2);
+ }
+
+return_point:
+ return status;
+}
+
+
+/***********************************************************CommentBegin******
+*
+* -- VideoPlaneWithShortHeader -- Decodes the short_video_header information from the bitstream
+* Modified :
+ 04/23/2001. Remove the codes related to the
+ "first pass" decoding. We use a different function
+ to set up the decoder now.
+***********************************************************CommentEnd********/
+PV_STATUS DecodeShortHeader(VideoDecData *video, Vop *currVop)
+{
+ PV_STATUS status = PV_SUCCESS;
+ Vol *currVol = video->vol[0];
+ BitstreamDecVideo *stream = currVol->bitstream;
+ uint32 tmpvar;
+ int32 size;
+
+ int extended_PTYPE = FALSE;
+ int UFEP = 0, custom_PFMT = 0, custom_PCF = 0;
+
+ status = BitstreamShowBits32(stream, SHORT_VIDEO_START_MARKER_LENGTH, &tmpvar);
+
+ if (tmpvar != SHORT_VIDEO_START_MARKER)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+
+ PV_BitstreamFlushBits(stream, SHORT_VIDEO_START_MARKER_LENGTH);
+
+ /* Temporal reference. Using vop_time_increment_resolution = 30000 */
+ tmpvar = (uint32) BitstreamReadBits16(stream, 8);
+ currVop->temporalRef = (int) tmpvar;
+
+
+ currVop->timeInc = 0xff & (256 + currVop->temporalRef - video->prevVop->temporalRef);
+ currVol->moduloTimeBase += currVop->timeInc; /* mseconds 11/12/01 */
+ /* Marker Bit */
+ if (!BitstreamRead1Bits(stream))
+ {
+ mp4dec_log("DecodeShortHeader(): Marker bit wrong.\n");
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+ /* Zero Bit */
+ if (BitstreamRead1Bits(stream))
+ {
+ mp4dec_log("DecodeShortHeader(): Zero bit wrong.\n");
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+ /*split_screen_indicator*/
+ if (BitstreamRead1Bits(stream))
+ {
+ mp4dec_log("DecodeShortHeader(): Split Screen not supported.\n");
+ VideoDecoderErrorDetected(video);
+ }
+
+ /*document_freeze_camera*/
+ if (BitstreamRead1Bits(stream))
+ {
+ mp4dec_log("DecodeShortHeader(): Freeze Camera not supported.\n");
+ VideoDecoderErrorDetected(video);
+ }
+
+ /*freeze_picture_release*/
+ if (BitstreamRead1Bits(stream))
+ {
+ mp4dec_log("DecodeShortHeader(): Freeze Release not supported.\n");
+ VideoDecoderErrorDetected(video);
+ }
+ /* source format */
+ switch (BitstreamReadBits16(stream, 3))
+ {
+ case 1:
+ if (video->size < 128*96)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ video->displayWidth = video->width = 128;
+ video->displayHeight = video->height = 96;
+ break;
+
+ case 2:
+ if (video->size < 176*144)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ video->displayWidth = video->width = 176;
+ video->displayHeight = video->height = 144;
+ break;
+
+ case 3:
+ if (video->size < 352*288)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ video->displayWidth = video->width = 352;
+ video->displayHeight = video->height = 288;
+ break;
+
+ case 4:
+ if (video->size < 704*576)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ video->displayWidth = video->width = 704;
+ video->displayHeight = video->height = 576;
+ break;
+
+ case 5:
+ if (video->size < 1408*1152)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ video->displayWidth = video->width = 1408;
+ video->displayHeight = video->height = 1152;
+ break;
+
+ case 7:
+ extended_PTYPE = TRUE;
+ break;
+
+ default:
+ /* Msg("H.263 source format not legal\n"); */
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+
+ currVop->roundingType = 0;
+
+ if (extended_PTYPE == FALSE)
+ {
+ currVop->predictionType = (int) BitstreamRead1Bits(stream);
+
+ /* four_reserved_zero_bits */
+ if (BitstreamReadBits16(stream, 4))
+ {
+ mp4dec_log("DecodeShortHeader(): Reserved bits wrong.\n");
+ status = PV_FAIL;
+ goto return_point;
+ }
+ }
+ else
+ {
+ UFEP = BitstreamReadBits16(stream, 3);
+ if (UFEP == 1)
+ {
+ /* source format */
+ switch (BitstreamReadBits16(stream, 3))
+ {
+ case 1:
+ if (video->size < 128*96)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ video->displayWidth = video->width = 128;
+ video->displayHeight = video->height = 96;
+ break;
+
+ case 2:
+ if (video->size < 176*144)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ video->displayWidth = video->width = 176;
+ video->displayHeight = video->height = 144;
+ break;
+
+ case 3:
+ if (video->size < 352*288)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ video->displayWidth = video->width = 352;
+ video->displayHeight = video->height = 288;
+ break;
+
+ case 4:
+ if (video->size < 704*576)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ video->displayWidth = video->width = 704;
+ video->displayHeight = video->height = 576;
+ break;
+
+ case 5:
+ if (video->size < 1408*1152)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ video->displayWidth = video->width = 1408;
+ video->displayHeight = video->height = 1152;
+ break;
+
+ case 6:
+ custom_PFMT = TRUE;
+ break;
+
+ default:
+ /* Msg("H.263 source format not legal\n"); */
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+ custom_PCF = BitstreamRead1Bits(stream);
+ /* unrestricted MV */
+ if (BitstreamRead1Bits(stream))
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ /* SAC */
+ if (BitstreamRead1Bits(stream))
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+ /* AP */
+ if (BitstreamRead1Bits(stream))
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+ video->advanced_INTRA = BitstreamRead1Bits(stream);
+
+ video->deblocking = BitstreamRead1Bits(stream);
+
+ video->slice_structure = BitstreamRead1Bits(stream);
+
+ /* RPS, ISD, AIV */
+ if (BitstreamReadBits16(stream, 3))
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ video->modified_quant = BitstreamRead1Bits(stream);
+
+ /* Marker Bit and reserved*/
+ if (BitstreamReadBits16(stream, 4) != 8)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ }
+#ifndef PV_ANNEX_IJKT_SUPPORT
+ if (video->advanced_INTRA | video->deblocking | video->modified_quant | video->modified_quant)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+#endif
+
+ if (UFEP == 0 || UFEP == 1)
+ {
+ tmpvar = BitstreamReadBits16(stream, 3);
+ if (tmpvar > 1)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ currVop->predictionType = tmpvar;
+ /* RPR */
+ if (BitstreamRead1Bits(stream))
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+ /* RRU */
+ if (BitstreamRead1Bits(stream))
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ currVop->roundingType = (int) BitstreamRead1Bits(stream);
+ if (BitstreamReadBits16(stream, 3) != 1)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ }
+ else
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ /* CPM */
+ if (BitstreamRead1Bits(stream))
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ /* CPFMT */
+ if (custom_PFMT == 1 && UFEP == 1)
+ {
+ /* aspect ratio */
+ tmpvar = BitstreamReadBits16(stream, 4);
+ if (tmpvar == 0)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ /* Extended PAR */
+ if (tmpvar == 0xF)
+ {
+ /* Read par_width and par_height but do nothing */
+ /* par_width */
+ tmpvar = BitstreamReadBits16(stream, 8);
+
+ /* par_height */
+ tmpvar = BitstreamReadBits16(stream, 8);
+ }
+ tmpvar = BitstreamReadBits16(stream, 9);
+
+ video->displayWidth = (tmpvar + 1) << 2;
+ video->width = (video->displayWidth + 15) & -16;
+ /* marker bit */
+ if (!BitstreamRead1Bits(stream))
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ tmpvar = BitstreamReadBits16(stream, 9);
+ if (tmpvar == 0)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ video->displayHeight = tmpvar << 2;
+ video->height = (video->displayHeight + 15) & -16;
+
+ if (video->height * video->width > video->size)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+ video->nTotalMB = video->width / MB_SIZE * video->height / MB_SIZE;
+
+ if (video->nTotalMB <= 48)
+ {
+ video->nBitsForMBID = 6;
+ }
+ else if (video->nTotalMB <= 99)
+ {
+ video->nBitsForMBID = 7;
+ }
+ else if (video->nTotalMB <= 396)
+ {
+ video->nBitsForMBID = 9;
+ }
+ else if (video->nTotalMB <= 1584)
+ {
+ video->nBitsForMBID = 11;
+ }
+ else if (video->nTotalMB <= 6336)
+ {
+ video->nBitsForMBID = 13 ;
+ }
+ else if (video->nTotalMB <= 9216)
+ {
+ video->nBitsForMBID = 14 ;
+ }
+ else
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ }
+ if (UFEP == 1 && custom_PCF == 1)
+ {
+ BitstreamRead1Bits(stream);
+
+ tmpvar = BitstreamReadBits16(stream, 7);
+ if (tmpvar == 0)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ }
+
+ if (custom_PCF == 1)
+ {
+ currVop->ETR = BitstreamReadBits16(stream, 2);
+ }
+
+ if (UFEP == 1 && video->slice_structure == 1)
+ {
+ /* SSS */
+ tmpvar = BitstreamReadBits16(stream, 2);
+ if (tmpvar != 0)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ }
+ }
+
+ /* Recalculate number of macroblocks per row & col since */
+ /* the frame size can change. 04/23/2001. */
+ video->nMBinGOB = video->nMBPerRow = video->width / MB_SIZE;
+ video->nGOBinVop = video->nMBPerCol = video->height / MB_SIZE;
+ video->nTotalMB = video->nMBPerRow * video->nMBPerCol;
+ if (custom_PFMT == 0 || UFEP == 0)
+ {
+ video->nBitsForMBID = CalcNumBits((uint)video->nTotalMB - 1); /* otherwise calculate above */
+ }
+ size = (int32)video->width * video->height;
+ if (video->currVop->predictionType == P_VOP && size > video->videoDecControls->size)
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+ video->videoDecControls->size = size;
+ video->currVop->uChan = video->currVop->yChan + size;
+ video->currVop->vChan = video->currVop->uChan + (size >> 2);
+ video->prevVop->uChan = video->prevVop->yChan + size;
+ video->prevVop->vChan = video->prevVop->uChan + (size >> 2);
+
+
+ currVop->quantizer = (int16) BitstreamReadBits16(stream, 5);
+
+ if (currVop->quantizer == 0) /* 04/03/01 */
+ {
+ currVop->quantizer = video->prevVop->quantizer;
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+
+ /* Zero bit */
+ if (extended_PTYPE == FALSE)
+ {
+ if (BitstreamRead1Bits(stream))
+ {
+ mp4dec_log("DecodeShortHeader(): Zero bit wrong.\n");
+ status = PV_FAIL;
+ goto return_point;
+ }
+ }
+ /* pei */
+ tmpvar = (uint32) BitstreamRead1Bits(stream);
+
+ while (tmpvar)
+ {
+ tmpvar = (uint32) BitstreamReadBits16(stream, 8); /* "PSPARE" */
+ tmpvar = (uint32) BitstreamRead1Bits(stream); /* "PEI" */
+ }
+
+ if (video->slice_structure) /* ANNEX_K */
+ {
+ if (!BitstreamRead1Bits(stream)) /* SEPB1 */
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+ // if (currVol->nBitsForMBID //
+ if (BitstreamReadBits16(stream, video->nBitsForMBID))
+ {
+ status = PV_FAIL; /* no ASO, RS support for Annex K */
+ goto return_point;
+ }
+
+ if (!BitstreamRead1Bits(stream)) /*SEPB3 */
+ {
+ status = PV_FAIL;
+ goto return_point;
+ }
+
+ }
+ /* Setting of other VOP-header parameters */
+ currVop->gobNumber = 0;
+ currVop->vopCoded = 1;
+
+ currVop->intraDCVlcThr = 0;
+ currVop->gobFrameID = 0; /* initial value, 05/22/00 */
+ currVol->errorResDisable = 0;
+ /*PutVopInterlaced(0,curr_vop); no implemented yet */
+ if (currVop->predictionType != I_VOP)
+ currVop->fcodeForward = 1;
+ else
+ currVop->fcodeForward = 0;
+
+return_point:
+
+ return status;
+}
+/***********************************************************CommentBegin******
+*
+* -- PV_DecodeVop -- Decodes the VOP information from the bitstream
+*
+* 04/12/2000
+* Initial port to the new PV decoder library format.
+* This function is different from the one in MoMuSys MPEG-4
+* visual decoder. We handle combined mode with or withput
+* error resilience and H.263 mode through the sam path now.
+*
+* 05/04/2000
+* Added temporal scalability to the decoder.
+*
+***********************************************************CommentEnd********/
+PV_STATUS PV_DecodeVop(VideoDecData *video)
+{
+ Vol *currVol = video->vol[video->currLayer];
+ PV_STATUS status;
+ uint32 tmpvar;
+
+ /*****
+ * Do scalable or non-scalable decoding of the current VOP
+ *****/
+
+ if (!currVol->scalability)
+ {
+ if (currVol->dataPartitioning)
+ {
+ /* Data partitioning mode comes here */
+ status = DecodeFrameDataPartMode(video);
+ }
+ else
+ {
+ /* Combined mode with or without error resilience */
+ /* and short video header comes here. */
+ status = DecodeFrameCombinedMode(video);
+ }
+ }
+ else
+ {
+#ifdef DO_NOT_FOLLOW_STANDARD
+ /* according to the standard, only combined mode is allowed */
+ /* in the enhancement layer. 06/01/2000. */
+ if (currVol->dataPartitioning)
+ {
+ /* Data partitioning mode comes here */
+ status = DecodeFrameDataPartMode(video);
+ }
+ else
+ {
+ /* Combined mode with or without error resilience */
+ /* and short video header comes here. */
+ status = DecodeFrameCombinedMode(video);
+ }
+#else
+ status = DecodeFrameCombinedMode(video);
+#endif
+ }
+
+ /* This part is for consuming Visual_object_sequence_end_code and EOS Code */ /* 10/15/01 */
+ if (!video->shortVideoHeader)
+ {
+ /* at this point bitstream is expected to be byte aligned */
+ BitstreamByteAlignNoForceStuffing(currVol->bitstream);
+
+ status = BitstreamShowBits32HC(currVol->bitstream, &tmpvar); /* 07/07/01 */
+ if (tmpvar == VISUAL_OBJECT_SEQUENCE_END_CODE)/* VOS_END_CODE */
+ {
+ PV_BitstreamFlushBits(currVol->bitstream, 16);
+ PV_BitstreamFlushBits(currVol->bitstream, 16);
+ }
+
+ }
+ else
+ {
+#ifdef PV_ANNEX_IJKT_SUPPORT
+ if (video->deblocking)
+ {
+ H263_Deblock(video->currVop->yChan, video->width, video->height, video->QPMB, video->headerInfo.Mode, 0, 0);
+ H263_Deblock(video->currVop->uChan, video->width >> 1, video->height >> 1, video->QPMB, video->headerInfo.Mode, 1, video->modified_quant);
+ H263_Deblock(video->currVop->vChan, video->width >> 1, video->height >> 1, video->QPMB, video->headerInfo.Mode, 1, video->modified_quant);
+ }
+#endif
+ /* Read EOS code for shortheader bitstreams */
+ status = BitstreamShowBits32(currVol->bitstream, 22, &tmpvar);
+ if (tmpvar == SHORT_VIDEO_END_MARKER)
+ {
+ PV_BitstreamFlushBits(currVol->bitstream, 22);
+ }
+ else
+ {
+ status = PV_BitstreamShowBitsByteAlign(currVol->bitstream, 22, &tmpvar);
+ if (tmpvar == SHORT_VIDEO_END_MARKER)
+ {
+ PV_BitstreamByteAlign(currVol->bitstream);
+ PV_BitstreamFlushBits(currVol->bitstream, 22);
+ }
+ }
+ }
+ return status;
+}
+
+
+/***********************************************************CommentBegin******
+*
+* -- CalcVopDisplayTime -- calculate absolute time when VOP is to be displayed
+*
+* 04/12/2000 Initial port to the new PV decoder library format.
+*
+***********************************************************CommentEnd********/
+uint32 CalcVopDisplayTime(Vol *currVol, Vop *currVop, int shortVideoHeader)
+{
+ uint32 display_time;
+
+
+ /*****
+ * Calculate the time when the VOP is to be displayed next
+ *****/
+
+ if (!shortVideoHeader)
+ {
+ display_time = (uint32)(currVol->moduloTimeBase + (((int32)currVop->timeInc - (int32)currVol->timeInc_offset) * 1000) / ((int32)currVol->timeIncrementResolution)); /* 11/12/2001 */
+ if (currVop->timeStamp >= display_time)
+ {
+ display_time += 1000; /* this case is valid if GOVHeader timestamp is ignored */
+ }
+ }
+ else
+ {
+ display_time = (uint32)(currVol->moduloTimeBase * 33 + (currVol->moduloTimeBase * 11) / 30); /* 11/12/2001 */
+ }
+
+ return(display_time);
+}
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/zigzag.h b/media/libstagefright/codecs/m4v_h263/dec/src/zigzag.h
new file mode 100644
index 0000000..4690a18
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/zigzag.h
@@ -0,0 +1,72 @@
+/* ------------------------------------------------------------------
+ * 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 zigzag_H
+#define zigzag_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ extern const int zigzag_inv[3*NCOEFF_BLOCK];
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; GLOBAL FUNCTION DEFINITIONS
+ ; Function Prototype declaration
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; END
+ ----------------------------------------------------------------------------*/
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/zigzag_tab.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/zigzag_tab.cpp
new file mode 100644
index 0000000..33dbb14
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/zigzag_tab.cpp
@@ -0,0 +1,110 @@
+/* ------------------------------------------------------------------
+ * 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 "mp4dec_api.h"
+#include "mp4def.h"
+#include "zigzag.h"
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const int zigzag_inv[3*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,
+//};
+
+ /* Vertical inverse zigzag */
+//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,
+//};
+ /* Horizontal inverse zigzag*/
+//const static Int zizag_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
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Define all local variables
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Function body here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; Return nothing or data or data pointer
+----------------------------------------------------------------------------*/
+
+
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..2b7c938
--- /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)/frameworks/base/media/libstagefright/include \
+ $(TOP)/frameworks/native/include/media/openmax
+
+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..20b0f8d
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
@@ -0,0 +1,487 @@
+/*
+ * 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/foundation/ADebug.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+static status_t ConvertOmxProfileLevel(
+ MP4EncodingMode mode,
+ int32_t omxProfile,
+ int32_t omxLevel,
+ ProfileLevelType* pvProfileLevel) {
+ ALOGV("ConvertOmxProfileLevel: %d/%d/%d", mode, omxProfile, omxLevel);
+ ProfileLevelType profileLevel;
+ if (mode == H263_MODE) {
+ switch (omxProfile) {
+ case OMX_VIDEO_H263ProfileBaseline:
+ if (omxLevel > OMX_VIDEO_H263Level45) {
+ ALOGE("Unsupported level (%d) for H263", omxLevel);
+ return BAD_VALUE;
+ } else {
+ ALOGW("PV does not support level configuration for H263");
+ profileLevel = CORE_PROFILE_LEVEL2;
+ break;
+ }
+ break;
+ default:
+ ALOGE("Unsupported profile (%d) for H263", omxProfile);
+ return BAD_VALUE;
+ }
+ } else { // MPEG4
+ switch (omxProfile) {
+ case OMX_VIDEO_MPEG4ProfileSimple:
+ switch (omxLevel) {
+ case OMX_VIDEO_MPEG4Level0b:
+ profileLevel = SIMPLE_PROFILE_LEVEL0;
+ break;
+ case OMX_VIDEO_MPEG4Level1:
+ profileLevel = SIMPLE_PROFILE_LEVEL1;
+ break;
+ case OMX_VIDEO_MPEG4Level2:
+ profileLevel = SIMPLE_PROFILE_LEVEL2;
+ break;
+ case OMX_VIDEO_MPEG4Level3:
+ profileLevel = SIMPLE_PROFILE_LEVEL3;
+ break;
+ default:
+ ALOGE("Unsupported level (%d) for MPEG4 simple profile",
+ omxLevel);
+ return BAD_VALUE;
+ }
+ break;
+ case OMX_VIDEO_MPEG4ProfileSimpleScalable:
+ switch (omxLevel) {
+ case OMX_VIDEO_MPEG4Level0b:
+ profileLevel = SIMPLE_SCALABLE_PROFILE_LEVEL0;
+ break;
+ case OMX_VIDEO_MPEG4Level1:
+ profileLevel = SIMPLE_SCALABLE_PROFILE_LEVEL1;
+ break;
+ case OMX_VIDEO_MPEG4Level2:
+ profileLevel = SIMPLE_SCALABLE_PROFILE_LEVEL2;
+ break;
+ default:
+ ALOGE("Unsupported level (%d) for MPEG4 simple "
+ "scalable profile", omxLevel);
+ return BAD_VALUE;
+ }
+ break;
+ case OMX_VIDEO_MPEG4ProfileCore:
+ switch (omxLevel) {
+ case OMX_VIDEO_MPEG4Level1:
+ profileLevel = CORE_PROFILE_LEVEL1;
+ break;
+ case OMX_VIDEO_MPEG4Level2:
+ profileLevel = CORE_PROFILE_LEVEL2;
+ break;
+ default:
+ ALOGE("Unsupported level (%d) for MPEG4 core "
+ "profile", omxLevel);
+ return BAD_VALUE;
+ }
+ break;
+ case OMX_VIDEO_MPEG4ProfileCoreScalable:
+ switch (omxLevel) {
+ case OMX_VIDEO_MPEG4Level1:
+ profileLevel = CORE_SCALABLE_PROFILE_LEVEL1;
+ break;
+ case OMX_VIDEO_MPEG4Level2:
+ profileLevel = CORE_SCALABLE_PROFILE_LEVEL2;
+ break;
+ case OMX_VIDEO_MPEG4Level3:
+ profileLevel = CORE_SCALABLE_PROFILE_LEVEL3;
+ break;
+ default:
+ ALOGE("Unsupported level (%d) for MPEG4 core "
+ "scalable profile", omxLevel);
+ return BAD_VALUE;
+ }
+ break;
+ default:
+ ALOGE("Unsupported MPEG4 profile (%d)", omxProfile);
+ return BAD_VALUE;
+ }
+ }
+
+ *pvProfileLevel = profileLevel;
+ return OK;
+}
+
+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),
+ mPrevTimestampUs(-1),
+ mStarted(false),
+ mInputBuffer(NULL),
+ mInputFrameData(NULL),
+ mGroup(NULL) {
+
+ ALOGI("Construct software M4vH263Encoder");
+
+ mHandle = new tagvideoEncControls;
+ memset(mHandle, 0, sizeof(tagvideoEncControls));
+
+ mInitCheck = initCheck(meta);
+}
+
+M4vH263Encoder::~M4vH263Encoder() {
+ ALOGV("Destruct software M4vH263Encoder");
+ if (mStarted) {
+ stop();
+ }
+
+ delete mEncParams;
+ delete mHandle;
+}
+
+status_t M4vH263Encoder::initCheck(const sp<MetaData>& meta) {
+ ALOGV("initCheck");
+ CHECK(meta->findInt32(kKeyWidth, &mVideoWidth));
+ CHECK(meta->findInt32(kKeyHeight, &mVideoHeight));
+ CHECK(meta->findInt32(kKeyFrameRate, &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) {
+ ALOGE("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) {
+ ALOGE("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)) {
+ ALOGE("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 profile, level;
+ if (meta->findInt32(kKeyVideoProfile, &profile) &&
+ meta->findInt32(kKeyVideoLevel, &level)) {
+ if (OK != ConvertOmxProfileLevel(
+ mEncParams->encMode, profile, level,
+ &mEncParams->profile_level)) {
+ return BAD_VALUE;
+ }
+ }
+
+ 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(kKeyFrameRate, mVideoFrameRate);
+ mFormat->setInt32(kKeyColorFormat, mVideoColorFormat);
+
+ mFormat->setCString(kKeyMIMEType, mime);
+ mFormat->setCString(kKeyDecoderComponent, "M4vH263Encoder");
+ return OK;
+}
+
+status_t M4vH263Encoder::start(MetaData *params) {
+ ALOGV("start");
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mStarted) {
+ ALOGW("Call start() when encoder already started");
+ return OK;
+ }
+
+ if (!PVInitVideoEncoder(mHandle, mEncParams)) {
+ ALOGE("Failed to initialize the encoder");
+ return UNKNOWN_ERROR;
+ }
+
+ mGroup = new MediaBufferGroup();
+ int32_t maxSize;
+ if (!PVGetMaxVideoFrameSize(mHandle, &maxSize)) {
+ maxSize = 256 * 1024; // Magic #
+ }
+ ALOGV("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() {
+ ALOGV("stop");
+ if (!mStarted) {
+ ALOGW("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() {
+ ALOGV("getFormat");
+ return mFormat;
+}
+
+status_t M4vH263Encoder::read(
+ MediaBuffer **out, const ReadOptions *options) {
+
+ *out = NULL;
+
+ MediaBuffer *outputBuffer;
+ CHECK_EQ((status_t)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)) {
+ ALOGE("Failed to get VOL header");
+ return UNKNOWN_ERROR;
+ }
+ ALOGV("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
+ status_t err = mSource->read(&mInputBuffer, options);
+ if (OK != err) {
+ if (err != ERROR_END_OF_STREAM) {
+ ALOGE("Failed to read from data source");
+ }
+ outputBuffer->release();
+ return err;
+ }
+
+ if (mInputBuffer->size() - ((mVideoWidth * mVideoHeight * 3) >> 1) != 0) {
+ outputBuffer->release();
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ return UNKNOWN_ERROR;
+ }
+
+ int64_t timeUs;
+ CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+
+ // When the timestamp of the current sample is the same as that
+ // of the previous sample, encoding of the current sample is
+ // bypassed, and the output length of the sample is set to 0
+ if (mNumInputFrames >= 1 &&
+ (mNextModTimeUs > timeUs || mPrevTimestampUs == timeUs)) {
+ // Frame arrives too late
+ outputBuffer->set_range(0, 0);
+ *out = outputBuffer;
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ return OK;
+ }
+
+ // Don't accept out-of-order samples
+ CHECK(mPrevTimestampUs < timeUs);
+ mPrevTimestampUs = timeUs;
+
+ // 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)) {
+ ALOGE("Failed to encode frame or get hink track at frame %lld",
+ mNumInputFrames);
+ outputBuffer->release();
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ return UNKNOWN_ERROR;
+ }
+ CHECK(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/m4v_h263/patent_disclaimer.txt b/media/libstagefright/codecs/m4v_h263/patent_disclaimer.txt
new file mode 100644
index 0000000..b4bf11d
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/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/mp3dec/Android.mk b/media/libstagefright/codecs/mp3dec/Android.mk
new file mode 100644
index 0000000..ed51aa5
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/Android.mk
@@ -0,0 +1,81 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ src/pvmp3_normalize.cpp \
+ src/pvmp3_alias_reduction.cpp \
+ src/pvmp3_crc.cpp \
+ src/pvmp3_decode_header.cpp \
+ src/pvmp3_decode_huff_cw.cpp \
+ src/pvmp3_getbits.cpp \
+ src/pvmp3_dequantize_sample.cpp \
+ src/pvmp3_framedecoder.cpp \
+ src/pvmp3_get_main_data_size.cpp \
+ src/pvmp3_get_side_info.cpp \
+ src/pvmp3_get_scale_factors.cpp \
+ src/pvmp3_mpeg2_get_scale_data.cpp \
+ src/pvmp3_mpeg2_get_scale_factors.cpp \
+ src/pvmp3_mpeg2_stereo_proc.cpp \
+ src/pvmp3_huffman_decoding.cpp \
+ src/pvmp3_huffman_parsing.cpp \
+ src/pvmp3_tables.cpp \
+ src/pvmp3_imdct_synth.cpp \
+ src/pvmp3_mdct_6.cpp \
+ src/pvmp3_dct_6.cpp \
+ src/pvmp3_poly_phase_synthesis.cpp \
+ src/pvmp3_equalizer.cpp \
+ src/pvmp3_seek_synch.cpp \
+ src/pvmp3_stereo_proc.cpp \
+ src/pvmp3_reorder.cpp \
+
+ifeq ($(TARGET_ARCH),arm)
+LOCAL_SRC_FILES += \
+ src/asm/pvmp3_polyphase_filter_window_gcc.s \
+ src/asm/pvmp3_mdct_18_gcc.s \
+ src/asm/pvmp3_dct_9_gcc.s \
+ src/asm/pvmp3_dct_16_gcc.s
+else
+LOCAL_SRC_FILES += \
+ src/pvmp3_polyphase_filter_window.cpp \
+ src/pvmp3_mdct_18.cpp \
+ src/pvmp3_dct_9.cpp \
+ src/pvmp3_dct_16.cpp
+endif
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/include
+
+LOCAL_CFLAGS := \
+ -DOSCL_UNUSED_ARG=
+
+LOCAL_MODULE := libstagefright_mp3dec
+
+LOCAL_ARM_MODE := arm
+
+include $(BUILD_STATIC_LIBRARY)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ SoftMP3.cpp
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+ frameworks/native/include/media/openmax \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/include
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright libstagefright_omx libstagefright_foundation libutils
+
+LOCAL_STATIC_LIBRARIES := \
+ libstagefright_mp3dec
+
+LOCAL_MODULE := libstagefright_soft_mp3dec
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
new file mode 100644
index 0000000..92009ee
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SoftMP3"
+#include <utils/Log.h>
+
+#include "SoftMP3.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+
+#include "include/pvmp3decoder_api.h"
+
+namespace android {
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+SoftMP3::SoftMP3(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SimpleSoftOMXComponent(name, callbacks, appData, component),
+ mConfig(new tPVMP3DecoderExternal),
+ mDecoderBuf(NULL),
+ mAnchorTimeUs(0),
+ mNumFramesOutput(0),
+ mNumChannels(2),
+ mSamplingRate(44100),
+ mSignalledError(false),
+ mOutputPortSettingsChange(NONE) {
+ initPorts();
+ initDecoder();
+}
+
+SoftMP3::~SoftMP3() {
+ if (mDecoderBuf != NULL) {
+ free(mDecoderBuf);
+ mDecoderBuf = NULL;
+ }
+
+ delete mConfig;
+ mConfig = NULL;
+}
+
+void SoftMP3::initPorts() {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+
+ def.nPortIndex = 0;
+ def.eDir = OMX_DirInput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 8192;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 1;
+
+ def.format.audio.cMIMEType =
+ const_cast<char *>(MEDIA_MIMETYPE_AUDIO_MPEG);
+
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingMP3;
+
+ addPort(def);
+
+ def.nPortIndex = 1;
+ def.eDir = OMX_DirOutput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = kOutputBufferSize;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 2;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ addPort(def);
+}
+
+void SoftMP3::initDecoder() {
+ mConfig->equalizerType = flat;
+ mConfig->crcEnabled = false;
+
+ uint32_t memRequirements = pvmp3_decoderMemRequirements();
+ mDecoderBuf = malloc(memRequirements);
+
+ pvmp3_InitDecoder(mConfig, mDecoderBuf);
+ mIsFirst = true;
+}
+
+OMX_ERRORTYPE SoftMP3::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamAudioPcm:
+ {
+ OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex > 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eEndian = OMX_EndianBig;
+ pcmParams->bInterleaved = OMX_TRUE;
+ pcmParams->nBitPerSample = 16;
+ pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
+ pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+ pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+
+ pcmParams->nChannels = mNumChannels;
+ pcmParams->nSamplingRate = mSamplingRate;
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftMP3::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamStandardComponentRole:
+ {
+ const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+ (const OMX_PARAM_COMPONENTROLETYPE *)params;
+
+ if (strncmp((const char *)roleParams->cRole,
+ "audio_decoder.mp3",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ }
+}
+
+void SoftMP3::onQueueFilled(OMX_U32 portIndex) {
+ if (mSignalledError || mOutputPortSettingsChange != NONE) {
+ return;
+ }
+
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+
+ while (!inQueue.empty() && !outQueue.empty()) {
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+
+ // pad the end of the stream with 529 samples, since that many samples
+ // were trimmed off the beginning when decoding started
+ outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
+ memset(outHeader->pBuffer, 0, outHeader->nFilledLen);
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+
+ outQueue.erase(outQueue.begin());
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+ return;
+ }
+
+ if (inHeader->nOffset == 0) {
+ mAnchorTimeUs = inHeader->nTimeStamp;
+ mNumFramesOutput = 0;
+ }
+
+ mConfig->pInputBuffer =
+ inHeader->pBuffer + inHeader->nOffset;
+
+ mConfig->inputBufferCurrentLength = inHeader->nFilledLen;
+ mConfig->inputBufferMaxLength = 0;
+ mConfig->inputBufferUsedLength = 0;
+
+ mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
+
+ mConfig->pOutputBuffer =
+ reinterpret_cast<int16_t *>(outHeader->pBuffer);
+
+ ERROR_CODE decoderErr;
+ if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf))
+ != NO_DECODING_ERROR) {
+ ALOGV("mp3 decoder returned error %d", decoderErr);
+
+ if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR ||
+ mConfig->outputFrameSize == 0) {
+ ALOGE("mp3 decoder returned error %d", decoderErr);
+
+ if (mConfig->outputFrameSize == 0) {
+ ALOGE("Output frame size is 0");
+ }
+
+ notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
+ mSignalledError = true;
+ return;
+ }
+
+ // This is recoverable, just ignore the current frame and
+ // play silence instead.
+ memset(outHeader->pBuffer,
+ 0,
+ mConfig->outputFrameSize * sizeof(int16_t));
+
+ mConfig->inputBufferUsedLength = inHeader->nFilledLen;
+ } else if (mConfig->samplingRate != mSamplingRate
+ || mConfig->num_channels != mNumChannels) {
+ mSamplingRate = mConfig->samplingRate;
+ mNumChannels = mConfig->num_channels;
+
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+ return;
+ }
+
+ if (mIsFirst) {
+ mIsFirst = false;
+ // The decoder delay is 529 samples, so trim that many samples off
+ // the start of the first output buffer. This essentially makes this
+ // decoder have zero delay, which the rest of the pipeline assumes.
+ outHeader->nOffset = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
+ outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t) - outHeader->nOffset;
+ } else {
+ outHeader->nOffset = 0;
+ outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t);
+ }
+
+ outHeader->nTimeStamp =
+ mAnchorTimeUs
+ + (mNumFramesOutput * 1000000ll) / mConfig->samplingRate;
+
+ outHeader->nFlags = 0;
+
+ CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength);
+
+ inHeader->nOffset += mConfig->inputBufferUsedLength;
+ inHeader->nFilledLen -= mConfig->inputBufferUsedLength;
+
+ mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;
+
+ if (inHeader->nFilledLen == 0) {
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+ }
+
+ outInfo->mOwnedByUs = false;
+ outQueue.erase(outQueue.begin());
+ outInfo = NULL;
+ notifyFillBufferDone(outHeader);
+ outHeader = NULL;
+ }
+}
+
+void SoftMP3::onPortFlushCompleted(OMX_U32 portIndex) {
+ if (portIndex == 0) {
+ // Make sure that the next buffer output does not still
+ // depend on fragments from the last one decoded.
+ pvmp3_InitDecoder(mConfig, mDecoderBuf);
+ mIsFirst = true;
+ }
+}
+
+void SoftMP3::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
+ if (portIndex != 1) {
+ return;
+ }
+
+ switch (mOutputPortSettingsChange) {
+ case NONE:
+ break;
+
+ case AWAITING_DISABLED:
+ {
+ CHECK(!enabled);
+ mOutputPortSettingsChange = AWAITING_ENABLED;
+ break;
+ }
+
+ default:
+ {
+ CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
+ CHECK(enabled);
+ mOutputPortSettingsChange = NONE;
+ break;
+ }
+ }
+}
+
+} // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+ const char *name, const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+ return new android::SoftMP3(name, callbacks, appData, component);
+}
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.h b/media/libstagefright/codecs/mp3dec/SoftMP3.h
new file mode 100644
index 0000000..3a05466
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SOFT_MP3_H_
+
+#define SOFT_MP3_H_
+
+#include "SimpleSoftOMXComponent.h"
+
+struct tPVMP3DecoderExternal;
+
+namespace android {
+
+struct SoftMP3 : public SimpleSoftOMXComponent {
+ SoftMP3(const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ virtual ~SoftMP3();
+
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual void onQueueFilled(OMX_U32 portIndex);
+ virtual void onPortFlushCompleted(OMX_U32 portIndex);
+ virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled);
+
+private:
+ enum {
+ kNumBuffers = 4,
+ kOutputBufferSize = 4608 * 2,
+ kPVMP3DecoderDelay = 529 // frames
+ };
+
+ tPVMP3DecoderExternal *mConfig;
+ void *mDecoderBuf;
+ int64_t mAnchorTimeUs;
+ int64_t mNumFramesOutput;
+
+ int32_t mNumChannels;
+ int32_t mSamplingRate;
+
+ bool mIsFirst;
+ bool mSignalledError;
+
+ enum {
+ NONE,
+ AWAITING_DISABLED,
+ AWAITING_ENABLED
+ } mOutputPortSettingsChange;
+
+ void initPorts();
+ void initDecoder();
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftMP3);
+};
+
+} // namespace android
+
+#endif // SOFT_MP3_H_
+
+
diff --git a/media/libstagefright/codecs/mp3dec/include/mp3_decoder_selection.h b/media/libstagefright/codecs/mp3dec/include/mp3_decoder_selection.h
new file mode 100644
index 0000000..e287433
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/include/mp3_decoder_selection.h
@@ -0,0 +1,30 @@
+/* ------------------------------------------------------------------
+ * 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 mp3_decoder_selection.h
+ * \brief select mp3 decoder
+ *
+ */
+
+#ifndef MP3_DECODER_SELECTION_H
+#define MP3_DECODER_SELECTION_H
+
+
+#define NEW_PV_MP3_DECODER 1 // 1 == PV mp3 decoder
+
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/include/pvmp3_audio_type_defs.h b/media/libstagefright/codecs/mp3dec/include/pvmp3_audio_type_defs.h
new file mode 100644
index 0000000..2d94384
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/include/pvmp3_audio_type_defs.h
@@ -0,0 +1,77 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_audio_type_defs.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file was derived from a number of standards bodies. The type
+ definitions below were created from some of the best practices observed
+ in the standards bodies.
+
+ This file is dependent on limits.h for defining the bit widths. In an
+ ANSI C environment limits.h is expected to always be present and contain
+ the following definitions:
+
+ SCHAR_MIN
+ SCHAR_MAX
+ UCHAR_MAX
+
+ INT_MAX
+ INT_MIN
+ UINT_MAX
+
+ SHRT_MIN
+ SHRT_MAX
+ USHRT_MAX
+
+ LONG_MIN
+ LONG_MAX
+ ULONG_MAX
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PVMP3_AUDIO_TYPE_DEFS_H
+#define PVMP3_AUDIO_TYPE_DEFS_H
+
+#include <stdint.h>
+
+typedef int8_t int8;
+typedef uint8_t uint8;
+typedef int16_t int16;
+typedef uint16_t uint16;
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int64_t int64;
+typedef uint64_t uint64;
+
+typedef int32_t Int32;
+
+#endif /* PVMP3_AUDIO_TYPE_DEFS_H */
diff --git a/media/libstagefright/codecs/mp3dec/include/pvmp3decoder_api.h b/media/libstagefright/codecs/mp3dec/include/pvmp3decoder_api.h
new file mode 100644
index 0000000..1568e7c
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/include/pvmp3decoder_api.h
@@ -0,0 +1,259 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3decoder_api.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure tPVMP3DecoderExternal
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3DECODER_API_H
+#define PVMP3DECODER_API_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_audio_type_defs.h"
+#include "pvmp3_dec_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; DEFINES
+ ; Include all pre-processor statements here.
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; EXTERNAL VARIABLES REFERENCES
+ ; Declare variables used in this module but defined elsewhere
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; SIMPLE TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /*----------------------------------------------------------------------------
+ ; ENUMERATED TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+ typedef enum
+ {
+ flat = 0,
+ bass_boost = 1,
+ rock = 2,
+ pop = 3,
+ jazz = 4,
+ classical = 5,
+ talk = 6,
+ flat_ = 7
+
+ } e_equalization;
+
+
+
+ typedef enum ERROR_CODE
+ {
+ NO_DECODING_ERROR = 0,
+ UNSUPPORTED_LAYER = 1,
+ UNSUPPORTED_FREE_BITRATE = 2,
+ FILE_OPEN_ERROR = 3, /* error opening file */
+ CHANNEL_CONFIG_ERROR = 4, /* error in channel configuration */
+ SYNTHESIS_WINDOW_ERROR = 5, /* error in synthesis window table */
+ READ_FILE_ERROR = 6, /* error reading input file */
+ SIDE_INFO_ERROR = 7, /* error in side info */
+ HUFFMAN_TABLE_ERROR = 8, /* error in Huffman table */
+ COMMAND_LINE_ERROR = 9, /* error in command line */
+ MEMORY_ALLOCATION_ERROR = 10, /* error allocating memory */
+ NO_ENOUGH_MAIN_DATA_ERROR = 11,
+ SYNCH_LOST_ERROR = 12,
+ OUTPUT_BUFFER_TOO_SMALL = 13 /* output buffer can't hold output */
+ } ERROR_CODE;
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ typedef struct
+#ifdef __cplusplus
+ tPVMP3DecoderExternal
+#endif
+ {
+
+ /*
+ * INPUT:
+ * Pointer to the input buffer that contains the encoded bistream data.
+ * The data is filled in such that the first bit transmitted is
+ * the most-significant bit (MSB) of the first array element.
+ * The buffer is accessed in a linear fashion for speed, and the number of
+ * bytes consumed varies frame to frame.
+ * The calling environment can change what is pointed to between calls to
+ * the decode function, library, as long as the inputBufferCurrentLength,
+ * and inputBufferUsedLength are updated too. Also, any remaining bits in
+ * the old buffer must be put at the beginning of the new buffer.
+ */
+ uint8 *pInputBuffer;
+
+ /*
+ * INPUT:
+ * Number of valid bytes in the input buffer, set by the calling
+ * function. After decoding the bitstream the library checks to
+ * see if it when past this value; it would be to prohibitive to
+ * check after every read operation. This value is not modified by
+ * the MP3 library.
+ */
+ int32 inputBufferCurrentLength;
+
+ /*
+ * INPUT/OUTPUT:
+ * Number of elements used by the library, initially set to zero by
+ * the function pvmp3_resetDecoder(), and modified by each
+ * call to pvmp3_framedecoder().
+ */
+ int32 inputBufferUsedLength;
+
+ /*
+ * OUTPUT:
+ * holds the predicted frame size. It used on the test console, for parsing
+ * purposes.
+ */
+ uint32 CurrentFrameLength;
+
+ /*
+ * INPUT:
+ * This variable holds the type of equalization used
+ *
+ *
+ */
+ e_equalization equalizerType;
+
+
+ /*
+ * INPUT:
+ * The actual size of the buffer.
+ * This variable is not used by the library, but is used by the
+ * console test application. This parameter could be deleted
+ * if this value was passed into these function.
+ */
+ int32 inputBufferMaxLength;
+
+ /*
+ * OUTPUT:
+ * The number of channels decoded from the bitstream.
+ */
+ int16 num_channels;
+
+ /*
+ * OUTPUT:
+ * The number of channels decoded from the bitstream.
+ */
+ int16 version;
+
+ /*
+ * OUTPUT:
+ * The sampling rate decoded from the bitstream, in units of
+ * samples/second.
+ */
+ int32 samplingRate;
+
+ /*
+ * OUTPUT:
+ * This value is the bitrate in units of bits/second. IT
+ * is calculated using the number of bits consumed for the current frame,
+ * and then multiplying by the sampling_rate, divided by points in a frame.
+ * This value can changes frame to frame.
+ */
+ int32 bitRate;
+
+ /*
+ * INPUT/OUTPUT:
+ * In: Inform decoder how much more room is available in the output buffer in int16 samples
+ * Out: Size of the output frame in 16-bit words, This value depends on the mp3 version
+ */
+ int32 outputFrameSize;
+
+ /*
+ * INPUT:
+ * Flag to enable/disable crc error checking
+ */
+ int32 crcEnabled;
+
+ /*
+ * OUTPUT:
+ * This value is used to accumulate bit processed and compute an estimate of the
+ * bitrate. For debugging purposes only, as it will overflow for very long clips
+ */
+ uint32 totalNumberOfBitsUsed;
+
+
+ /*
+ * INPUT: (but what is pointed to is an output)
+ * Pointer to the output buffer to hold the 16-bit PCM audio samples.
+ * If the output is stereo, both left and right channels will be stored
+ * in this one buffer.
+ */
+
+ int16 *pOutputBuffer;
+
+ } tPVMP3DecoderExternal;
+
+uint32 pvmp3_decoderMemRequirements(void);
+
+void pvmp3_InitDecoder(tPVMP3DecoderExternal *pExt,
+ void *pMem);
+
+void pvmp3_resetDecoder(void *pMem);
+
+ERROR_CODE pvmp3_framedecoder(tPVMP3DecoderExternal *pExt,
+ void *pMem);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/mp3dec/patent_disclaimer.txt b/media/libstagefright/codecs/mp3dec/patent_disclaimer.txt
new file mode 100644
index 0000000..b4bf11d
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/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/mp3dec/src/asm/pvmp3_dct_16_gcc.s b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s
new file mode 100644
index 0000000..f83732b
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s
@@ -0,0 +1,474 @@
+@ ------------------------------------------------------------------
+@ 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: pvmp3_dct_16_gcc.s
+@
+@
+@------------------------------------------------------------------------------
+@ REVISION HISTORY
+@
+@
+@ Who: Date: MM/DD/YYYY
+@ Description:
+@
+@------------------------------------------------------------------------------
+
+.arm
+
+.align 4
+
+.text
+
+.extern pvmp3_dct_16
+.extern pvmp3_merge_in_place_N32
+.extern pvmp3_split
+
+
+
+@------------------------------------------------------------------------------
+
+.global pvmp3_dct_16
+
+pvmp3_dct_16:
+ stmfd sp!,{r0,r1,r4-r11,lr}
+ ldr r1,[r0]
+ ldr r3,[r0,#0x3c]
+ ldr r12,constant1
+ sub r2,r1,r3
+ smull lr,r2,r12,r2
+ sub sp,sp,#0x1c
+ str r2,[sp,#0x14]
+ ldr r2,[r0,#0x1c]
+ ldr r12,[r0,#0x20]
+ add r1,r1,r3
+ sub r3,r2,r12
+ ldr lr,constant2
+ mov r3,r3,lsl #3
+ smull r4,r3,lr,r3
+ ldr r6,constant5
+ str r3,[sp]
+ add r3,r2,r12
+ sub r2,r1,r3
+ ldr r12,constant3
+ add r3,r1,r3
+ smull lr,r2,r12,r2
+ ldr r12,[r0,#0x38]
+ ldr r1,[r0,#4]
+ ldr lr,constant4
+ sub r4,r1,r12
+ add r1,r1,r12
+ ldr r12,[r0,#0x18]
+ smull r4,r5,lr,r4
+ ldr lr,[r0,#0x24]
+ ldr r10,constant10
+ sub r4,r12,lr
+ mov r4,r4,lsl #1
+ smull r7,r4,r6,r4
+ add r12,r12,lr
+ add r7,r1,r12
+ sub r12,r1,r12
+ ldr r1,constant6
+ str r4,[sp,#4]
+ smull r12,r4,r1,r12
+ ldr r1,[r0,#8]
+ ldr r12,[r0,#0x34]
+ ldr r6,constant7
+ sub lr,r1,r12
+ smull r8,lr,r6,lr
+ add r1,r1,r12
+ str lr,[sp,#0x10]
+ ldr r12,[r0,#0x14]
+ ldr lr,[r0,#0x28]
+ ldr r8,constant8
+ sub r6,r12,lr
+ mov r6,r6,lsl #1
+ smull r9,r6,r8,r6
+ add r12,r12,lr
+ ldr r9,constant9
+ add r8,r1,r12
+ sub r12,r1,r12
+ smull r12,lr,r9,r12
+ ldr r12,[r0,#0x30]
+ ldr r1,[r0,#0xc]
+ sub r9,r1,r12
+ smull r11,r9,r10,r9
+ add r12,r1,r12
+ str r9,[sp,#0xc]
+ ldr r9,[r0,#0x10]
+ ldr r10,constant11
+ str r9,[sp,#0x18]
+ ldr r1,[r0,#0x2c]
+ sub r9,r9,r1
+ smull r11,r9,r10,r9
+ ldr r10,constant12
+ str r9,[sp,#8]
+ ldr r9,[sp,#0x18]
+ ldr r11,constant14
+ add r9,r9,r1
+ add r1,r12,r9
+ sub r12,r12,r9
+ mov r12,r12,lsl #2
+ smull r9,r12,r10,r12
+ ldr r10,constant13
+ add r9,r3,r1
+ sub r1,r3,r1
+ smull r1,r3,r10,r1
+ sub r1,r7,r8
+ mov r1,r1,lsl #1
+ smull r1,r10,r11,r1
+ add r1,r7,r8
+ add r8,r9,r1
+ sub r7,r9,r1
+ mov r8,r8,asr #1
+ ldr r1,constant15
+ str r8,[r0]
+ smull r7,r8,r1,r7
+ sub r7,r3,r10
+ str r8,[r0,#0x20]
+ mov r7,r7,lsl #1
+ smull r8,r7,r1,r7
+ add r3,r3,r10
+ add r3,r3,r7
+ str r3,[r0,#0x10]
+ sub r3,r2,r12
+ str r7,[r0,#0x30]
+ add r2,r2,r12
+ ldr r7,constant13
+ sub r12,r4,lr
+ mov r3,r3,lsl #1
+ smull r8,r3,r7,r3
+ add lr,r4,lr
+ sub r4,r2,lr
+ mov r12,r12,lsl #2
+ smull r7,r12,r11,r12
+ add lr,lr,r2
+ sub r2,r3,r12
+ mov r2,r2,lsl #1
+ smull r7,r2,r1,r2
+ mov r4,r4,lsl #1
+ add r12,r12,r2
+ add r3,r12,r3
+ smull r7,r4,r1,r4
+ add r12,r3,lr
+ add r3,r3,r4
+ str r3,[r0,#0x18]
+ add r3,r2,r4
+ str r2,[r0,#0x38]
+ str r3,[r0,#0x28]
+ str r12,[r0,#8]
+ ldr r2,[sp,#0x14]
+ ldr r3,[sp,#0]
+ ldr lr,[sp,#4]
+ sub r2,r2,r3
+ ldr r3,constant3
+ mov r2,r2,lsl #1
+ smull r12,r2,r3,r2
+ ldr r3,[sp,#0x14]
+ ldr r12,[sp,#0]
+ ldr r4,constant6
+ add r12,r3,r12
+ ldr r3,[sp,#4]
+ sub lr,r5,lr
+ mov lr,lr,lsl #1
+ add r3,r5,r3
+ smull r5,lr,r4,lr
+ ldr r4,[sp,#0x10]
+ ldr r5,[sp,#0x10]
+ add r4,r4,r6
+ sub r5,r5,r6
+ ldr r6,constant9
+ mov r5,r5,lsl #1
+ smull r7,r5,r6,r5
+ ldr r6,[sp,#8]
+ ldr r9,[sp,#0xc]
+ ldr r10,constant12
+ sub r6,r9,r6
+ mov r6,r6,lsl #3
+ smull r7,r6,r10,r6
+ ldr r8,[sp,#0x20]
+ ldr r7,[sp,#8]
+ cmp r8,#0
+ add r7,r9,r7
+
+ bne no_flag_proc
+ rsb r12,r12,#0
+ rsb r2,r2,#0
+ rsb r3,r3,#0
+ rsb lr,lr,#0
+ rsb r4,r4,#0
+ rsb r5,r5,#0
+ rsb r7,r7,#0
+ rsb r6,r6,#0
+no_flag_proc:
+
+ sub r8,r2,r6
+ add r2,r6,r2
+ sub r6,r12,r7
+ ldr r9,constant13
+ add r12,r12,r7
+ sub r7,r3,r4
+ mov r6,r6,lsl #1
+ mov r8,r8,lsl #1
+ smull r10,r8,r9,r8
+ add r3,r3,r4
+ smull r10,r6,r9,r6
+ sub r4,lr,r5
+ mov r7,r7,lsl #2
+ smull r9,r7,r11,r7
+ add lr,lr,r5
+ sub r5,r6,r7
+ add r6,r6,r7
+ sub r7,r12,r3
+ add r3,r12,r3
+ sub r12,r2,lr
+ mov r4,r4,lsl #2
+ smull r9,r4,r11,r4
+ add lr,r2,lr
+ sub r2,r8,r4
+ mov r2,r2,lsl #1
+ mov r5,r5,lsl #1
+ mov r12,r12,lsl #1
+ mov r7,r7,lsl #1
+ smull r9,r5,r1,r5
+ smull r9,r2,r1,r2
+ add r6,r6,r5
+ smull r9,r7,r1,r7
+ smull r9,r12,r1,r12
+ add r1,r4,r2
+ add r1,r1,r8
+ add lr,lr,r1
+ add r3,r3,lr
+ str r3,[r0,#4]
+ add r3,r6,lr
+ str r3,[r0,#0xc]
+ add r1,r1,r12
+ add r3,r6,r1
+ add r1,r7,r1
+ str r1,[r0,#0x1c]
+ str r3,[r0,#0x14]
+ add r1,r12,r2
+ add r3,r7,r1
+ add r1,r5,r1
+ str r1,[r0,#0x2c]
+ str r3,[r0,#0x24]!
+ add r1,r5,r2
+ str r1,[r0,#0x10]
+ str r2,[r0,#0x18]
+ add sp,sp,#0x24
+ ldmfd sp!,{r4-r11,pc}
+
+
+
+@------------------------------------------------------------------------------
+
+.global pvmp3_merge_in_place_N32
+
+
+
+pvmp3_merge_in_place_N32:
+ stmfd sp!,{r4,lr}
+ ldr r1,[r0,#0x1c]
+ ldr r2,[r0,#0x38]
+ str r1,[r0,#0x38]
+ ldr r1,[r0,#0x18]
+ ldr r3,[r0,#0x30]
+ str r1,[r0,#0x30]
+ ldr r12,[r0,#0x14]
+ ldr r1,[r0,#0x28]
+ str r12,[r0,#0x28]
+ ldr r12,[r0,#0x10]
+ ldr lr,[r0,#0x20]
+ str r12,[r0,#0x20]
+ ldr r12,[r0,#0xc]
+ str r12,[r0,#0x18]
+ ldr r12,[r0,#8]
+ str r12,[r0,#0x10]
+ ldr r12,[r0,#4]
+ str r12,[r0,#8]
+ ldr r4,[r0,#0x40]
+ ldr r12,[r0,#0x44]
+ add r4,r4,r12
+ str r4,[r0,#4]
+ str lr,[r0,#0x40]
+ ldr lr,[r0,#0x48]
+ add r12,lr,r12
+ str r12,[r0,#0xc]
+ ldr r12,[r0,#0x4c]
+ add lr,r12,lr
+ str lr,[r0,#0x14]
+ ldr lr,[r0,#0x24]
+ str lr,[r0,#0x48]
+ ldr lr,[r0,#0x50]
+ add r12,lr,r12
+ str r12,[r0,#0x1c]
+ ldr r12,[r0,#0x54]
+ str r1,[r0,#0x50]
+ add lr,r12,lr
+ str lr,[r0,#0x24]
+ ldr r1,[r0,#0x58]
+ ldr r4,[r0,#0x2c]
+ ldr lr,[r0,#0x34]
+ add r12,r1,r12
+ str r12,[r0,#0x2c]
+ ldr r12,[r0,#0x5c]
+ add r1,r12,r1
+ str r1,[r0,#0x34]
+ str r4,[r0,#0x58]
+ ldr r1,[r0,#0x60]
+ ldr r4,[r0,#0x3c]
+ add r12,r1,r12
+ str r12,[r0,#0x3c]
+ ldr r12,[r0,#0x64]
+ add r1,r12,r1
+ str r1,[r0,#0x44]
+ ldr r1,[r0,#0x68]
+ add r12,r1,r12
+ str r12,[r0,#0x4c]
+ ldr r12,[r0,#0x6c]
+ add r1,r12,r1
+ str r1,[r0,#0x54]
+ ldr r1,[r0,#0x70]
+ str r3,[r0,#0x60]
+ add r12,r1,r12
+ str r12,[r0,#0x5c]
+ ldr r3,[r0,#0x74]
+ add r1,r3,r1
+ str r1,[r0,#0x64]
+ str lr,[r0,#0x68]
+ ldr r1,[r0,#0x78]
+ str r2,[r0,#0x70]
+ add r3,r1,r3
+ str r3,[r0,#0x6c]
+ ldr r2,[r0,#0x7c]
+ add r1,r1,r2
+ str r1,[r0,#0x74]
+ str r4,[r0,#0x78]
+ ldmfd sp!,{r4,pc}
+
+
+@------------------------------------------------------------------------------
+
+.global pvmp3_split
+
+
+pvmp3_split:
+ stmfd sp!,{r4,r5,lr}
+ ldr r2,constant16
+ sub r1,r0,#4
+ mov r3,#3
+loop1:
+ ldr r12,[r0]
+ ldr lr,[r1]
+ ldr r4,[r2],#-4
+ add r5,lr,r12
+ sub r12,lr,r12
+ smull r12,lr,r4,r12
+ str r5,[r1],#-4
+ mov r12,r12,lsr #27
+ add r12,r12,lr,lsl #5
+ str r12,[r0],#4
+ ldr r12,[r0]
+ ldr lr,[r1]
+ ldr r4,[r2],#-4
+ add r5,lr,r12
+ sub r12,lr,r12
+ smull r12,lr,r4,r12
+ str r5,[r1],#-4
+ mov r12,r12,lsr #27
+ add r12,r12,lr,lsl #5
+ str r12,[r0],#4
+ subs r3,r3,#1
+ bne loop1
+ mov r3,#5
+loop2:
+ ldr r12,[r0]
+ ldr lr,[r1]
+ ldr r4,[r2],#-4
+ add r5,lr,r12
+ sub r12,lr,r12
+ mov r12,r12,lsl #1
+ smull lr,r12,r4,r12
+ str r5,[r1],#-4
+ str r12,[r0],#4
+ ldr r12,[r0]
+ ldr lr,[r1]
+ ldr r4,[r2],#-4
+ add r5,lr,r12
+ sub r12,lr,r12
+ mov r12,r12,lsl #1
+ smull lr,r12,r4,r12
+ str r5,[r1],#-4
+ str r12,[r0],#4
+ subs r3,r3,#1
+ bne loop2
+ ldmfd sp!,{r4,r5,pc}
+constant1:
+ .word 0x404f4680
+constant2:
+ .word 0x519e4e00
+constant3:
+ .word 0x4140fb80
+constant4:
+ .word 0x42e13c00
+constant5:
+ .word 0x6e3c9300
+constant6:
+ .word 0x4cf8de80
+constant7:
+ .word 0x48919f80
+constant8:
+ .word 0x43e22480
+constant9:
+ .word 0x73326b80
+constant10:
+ .word 0x52cb0e80
+constant11:
+ .word 0x64e24000
+constant12:
+ .word 0x52036780
+constant13:
+ .word 0x4545ea00
+constant14:
+ .word 0x539eba80
+constant15:
+ .word 0x5a827980
+constant16:
+ .word CosTable_dct32 + 60
+
+
+
+CosTable_dct32:
+ .word 0x4013c280
+ .word 0x40b34580
+ .word 0x41fa2d80
+ .word 0x43f93400
+ .word 0x46cc1c00
+ .word 0x4a9d9d00
+ .word 0x4fae3700
+ .word 0x56601e80
+ .word 0x5f4cf700
+ .word 0x6b6fcf00
+ .word 0x07c7d1d8
+ .word 0x095b0350
+ .word 0x0bdf91b0
+ .word 0x107655e0
+ .word 0x1b42c840
+ .word 0x51852300
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_arm.s b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_arm.s
new file mode 100644
index 0000000..3a6dd4f
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_arm.s
@@ -0,0 +1,210 @@
+; ------------------------------------------------------------------
+; 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: pvmp3_dct_9.s
+;
+;------------------------------------------------------------------------------
+; REVISION HISTORY
+;
+;
+; Who: Date: MM/DD/YYYY
+; Description:
+;
+;------------------------------------------------------------------------------
+
+ AREA |.drectve|, DRECTVE
+
+ DCB "-defaultlib:coredll.lib "
+ DCB "-defaultlib:corelibc.lib "
+
+ IMPORT pvmp3_mdct_18 ; pvmp3_mdct_18.cpp
+
+;------------------------------------------------------------------------------
+
+ AREA |.rdata|, DATA, READONLY
+ % 4
+
+
+;------------------------------------------------------------------------------
+
+ AREA |.text|, CODE, READONLY
+
+
+;------------------------------------------------------------------------------
+
+ EXPORT |pvmp3_dct_9|
+
+|pvmp3_dct_9| PROC
+ stmfd sp!,{r4-r10,lr}
+ ldr r2, [r0, #0x20]
+ ldr r3, [r0]
+ ldr r12,[r0, #4]
+ add r1,r2,r3
+ sub lr,r2,r3
+ ldr r3,[r0, #0x1c]
+ ldr r4,[r0, #0x18]
+ add r2,r3,r12
+ ldr r5,[r0,#8]
+ sub r3,r3,r12
+ add r12,r4,r5
+ sub r4,r4,r5
+ ldr r5,[r0, #0x14]
+ ldr r7,[r0, #0xc]
+ ldr r9,[r0, #0x10]
+ add r6,r5,r7
+ sub r5,r5,r7
+ add r7,r1,r12
+ add r8,r9,r2
+ add r7,r7,r6
+ add r10,r7,r8
+ rsb r7,r8,r7,asr #1
+ str r7,[r0, #0x18]
+ rsb r2,r9,r2,asr #1
+ str r10,[r0]
+ ldr r11,|cos_2pi_9|
+ rsb r7,r2,#0
+
+ mov r9,r1,lsl #1
+ mov r1,r9 ;;;;;; !!!!!!
+ mov r8,r7
+
+; vec[4] = fxp_mac32_Q32( vec[4], tmp0<<1, cos_2pi_9);
+
+ smlal r1,r8,r11,r9
+ ldr r10,|cos_4pi_9|
+ ldr r11,|cos_pi_9|
+
+; vec[8] = fxp_mac32_Q32( vec[8], tmp0<<1, cos_4pi_9);
+
+ smlal r1,r7,r10,r9
+
+
+
+; vec[2] = fxp_mac32_Q32( vec[2], tmp0<<1, cos_pi_9);
+
+ smlal r9,r2,r11,r9
+ mov r1,r12,lsl #1
+ rsb r9,r10,#0
+ ldr r11,|cos_5pi_9|
+
+ smlal r12,r2,r9,r1
+
+
+
+; vec[2] = fxp_mac32_Q32( vec[2], tmp2<<1, cos_5pi_9);
+
+ ldr r9,|cos_2pi_9|
+ mov r12,r1 ;;;;;; !!!!!!
+ smlal r12,r8,r11,r1
+
+
+; vec[8] = fxp_mac32_Q32( vec[8], tmp2<<1, cos_2pi_9);
+
+ smlal r1,r7,r9,r1
+ mov r1,r6,lsl #1
+ smlal r12,r7,r11,r1
+ and r6,r10,r11,asr #14
+ smlal r12,r8,r6,r1
+ ldr r10,|cos_11pi_18|
+ add r12,r11,r6
+ smlal r1,r2,r12,r1
+ ldr r9,|cos_8pi_9|
+ str r2,[r0,#8]
+ mov r1,r5,lsl #1
+
+; vec[8] = fxp_mac32_Q32( vec[8], tmp3<<1, cos_8pi_9);
+
+ smull r2,r6,r9,r1
+ str r7,[r0,#0x20]
+ mov r2,r4,lsl #1
+ ldr r7,|cos_13pi_18|
+ smlal r12,r6,r10,r2
+
+ mov r3,r3,lsl #1
+
+; vec[5] = fxp_mac32_Q32( vec[5], tmp8<<1, cos_13pi_18);
+
+ smlal r12,r6,r7,r3
+ add r4,r5,r4
+ mov r12,lr,lsl #1
+ sub lr,r4,lr
+ ldr r7,|cos_17pi_18|
+ str r8,[r0, #0x10]
+ ldr r4,|cos_pi_6|
+
+ mov lr,lr,lsl #1
+
+; vec[1] = fxp_mac32_Q32( vec[1], tmp8<<1, cos_17pi_18);
+
+ smlal r8,r6,r7,r12
+
+; vec[3] = fxp_mul32_Q32((tmp5 + tmp6 - tmp8)<<1, cos_pi_6);
+
+ smull r5,lr,r4,lr
+ str r6,[r0, #4]
+ str lr,[r0, #0xc]
+
+
+; vec[5] = fxp_mul32_Q32(tmp5<<1, cos_17pi_18);
+ smull r5,lr,r7,r1
+ rsb r6,r9,#0
+; vec[5] = fxp_mac32_Q32( vec[5], tmp6<<1, cos_7pi_18);
+ smlal r5,lr,r6,r2
+; vec[5] = fxp_mac32_Q32( vec[5], tmp7<<1, cos_pi_6);
+ smlal r5,lr,r4,r3
+; vec[5] = fxp_mac32_Q32( vec[5], tmp8<<1, cos_13pi_18);
+ smlal r5,lr,r10,r12
+ str lr,[r0, #0x14]
+ rsb lr,r10,#0
+
+; vec[7] = fxp_mul32_Q32(tmp5<<1, cos_5pi_18);
+ smull r5,r1,lr,r1
+; vec[7] = fxp_mac32_Q32( vec[7], tmp6<<1, cos_17pi_18);
+ smlal r2,r1,r7,r2
+; vec[7] = fxp_mac32_Q32( vec[7], tmp7<<1, cos_pi_6);
+ smlal r3,r1,r4,r3
+; vec[7] = fxp_mac32_Q32( vec[7], tmp8<<1, cos_11pi_18);
+ smlal r12,r1,r9,r12
+ str r1,[r0, #0x1c]
+ ldmfd sp!,{r4-r10,pc}
+|cos_2pi_9|
+ DCD 0x620dbe80
+|cos_4pi_9|
+ DCD 0x163a1a80
+|cos_pi_9|
+ DCD 0x7847d900
+|cos_5pi_9|
+ DCD 0x87b82700
+|cos_8pi_9|
+ DCD 0xd438af00
+|cos_11pi_18|
+ DCD 0xadb92280
+|cos_13pi_18|
+ DCD 0x91261480
+|cos_17pi_18|
+ DCD 0x81f1d200
+|cos_pi_6|
+ DCD 0x6ed9eb80
+ ENDP
+
+
+
+
+
+ END
diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s
new file mode 100644
index 0000000..618c50e
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s
@@ -0,0 +1,193 @@
+@ ------------------------------------------------------------------
+@ 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: pvmp3_dct_9_gcc.s
+@
+@------------------------------------------------------------------------------
+@ REVISION HISTORY
+@
+@
+@ Who: Date: MM/DD/YYYY
+@ Description:
+@
+@------------------------------------------------------------------------------
+
+.arm
+
+.align 4
+
+.text
+
+
+@------------------------------------------------------------------------------
+
+.global pvmp3_dct_9
+
+pvmp3_dct_9:
+ stmfd sp!,{r4-r11,lr}
+ ldr r2, [r0, #0x20]
+ ldr r3, [r0, #0]
+ ldr r12,[r0, #4]
+ add r1,r2,r3
+ sub lr,r2,r3
+ ldr r3,[r0, #0x1c]
+ ldr r4,[r0, #0x18]
+ add r2,r3,r12
+ ldr r5,[r0,#8]
+ sub r3,r3,r12
+ add r12,r4,r5
+ sub r4,r4,r5
+ ldr r5,[r0, #0x14]
+ ldr r7,[r0, #0xc]
+ ldr r9,[r0, #0x10]
+ add r6,r5,r7
+ sub r5,r5,r7
+ add r7,r1,r12
+ add r8,r9,r2
+ add r7,r7,r6
+ add r10,r7,r8
+ rsb r7,r8,r7,asr #1
+ str r7,[r0, #0x18]
+ rsb r2,r9,r2,asr #1
+ str r10,[r0,#0]
+ ldr r11,cos_2pi_9
+ rsb r7,r2,#0
+
+ ldr r10,cos_4pi_9
+ mov r9,r1,lsl #1
+ mov r8,r7
+
+@ vec[4] = fxp_mac32_Q32( vec[4], tmp0<<1, cos_2pi_9)@
+
+ smlal r1,r8,r11,r9
+ ldr r11,cos_pi_9
+ mov r1,r9 @@@@@@ !!!!!!
+
+@ vec[8] = fxp_mac32_Q32( vec[8], tmp0<<1, cos_4pi_9)@
+
+ smlal r1,r7,r10,r9
+
+ mov r1,r12,lsl #1
+
+
+@ vec[2] = fxp_mac32_Q32( vec[2], tmp0<<1, cos_pi_9)@
+
+ smlal r9,r2,r11,r9
+ rsb r9,r10,#0
+ ldr r11,cos_5pi_9
+
+ smlal r12,r2,r9,r1
+
+
+
+@ vec[2] = fxp_mac32_Q32( vec[2], tmp2<<1, cos_5pi_9)@
+
+ ldr r9,cos_2pi_9
+ mov r12,r1 @@@@@@ !!!!!!
+ smlal r12,r8,r11,r1
+
+
+@ vec[8] = fxp_mac32_Q32( vec[8], tmp2<<1, cos_2pi_9)@
+
+ smlal r1,r7,r9,r1
+ mov r1,r6,lsl #1
+ smlal r12,r7,r11,r1
+ and r6,r10,r11,asr #14
+ smlal r12,r8,r6,r1
+ ldr r10,cos_11pi_18
+ add r12,r11,r6
+ smlal r1,r2,r12,r1
+ ldr r9,cos_8pi_9
+ str r2,[r0,#8]
+ mov r1,r5,lsl #1
+
+@ vec[8] = fxp_mac32_Q32( vec[8], tmp3<<1, cos_8pi_9)@
+
+ smull r2,r6,r9,r1
+ str r7,[r0,#0x20]
+ mov r2,r4,lsl #1
+ ldr r7,cos_13pi_18
+ smlal r12,r6,r10,r2
+
+ mov r3,r3,lsl #1
+
+@ vec[5] = fxp_mac32_Q32( vec[5], tmp8<<1, cos_13pi_18)@
+
+ smlal r12,r6,r7,r3
+ add r4,r5,r4
+ mov r12,lr,lsl #1
+ sub lr,r4,lr
+ ldr r7,cos_17pi_18
+ str r8,[r0, #0x10]
+ ldr r4,cos_pi_6
+
+ mov lr,lr,lsl #1
+
+@ vec[1] = fxp_mac32_Q32( vec[1], tmp8<<1, cos_17pi_18)@
+
+ smlal r8,r6,r7,r12
+
+@ vec[3] = fxp_mul32_Q32((tmp5 + tmp6 - tmp8)<<1, cos_pi_6)@
+
+ smull r5,lr,r4,lr
+ str r6,[r0, #4]
+ str lr,[r0, #0xc]
+
+
+@ vec[5] = fxp_mul32_Q32(tmp5<<1, cos_17pi_18)@
+ smull r5,lr,r7,r1
+ rsb r6,r9,#0
+@ vec[5] = fxp_mac32_Q32( vec[5], tmp6<<1, cos_7pi_18)@
+ smlal r5,lr,r6,r2
+@ vec[5] = fxp_mac32_Q32( vec[5], tmp7<<1, cos_pi_6)@
+ smlal r5,lr,r4,r3
+@ vec[5] = fxp_mac32_Q32( vec[5], tmp8<<1, cos_13pi_18)@
+ smlal r5,lr,r10,r12
+ str lr,[r0, #0x14]
+ rsb lr,r10,#0
+
+@ vec[7] = fxp_mul32_Q32(tmp5<<1, cos_5pi_18)@
+ smull r5,r1,lr,r1
+@ vec[7] = fxp_mac32_Q32( vec[7], tmp6<<1, cos_17pi_18)@
+ smlal r2,r1,r7,r2
+@ vec[7] = fxp_mac32_Q32( vec[7], tmp7<<1, cos_pi_6)@
+ smlal r3,r1,r4,r3
+@ vec[7] = fxp_mac32_Q32( vec[7], tmp8<<1, cos_11pi_18)@
+ smlal r12,r1,r9,r12
+ str r1,[r0, #0x1c]
+ ldmfd sp!,{r4-r11,pc}
+cos_2pi_9:
+ .word 0x620dbe80
+cos_4pi_9:
+ .word 0x163a1a80
+cos_pi_9:
+ .word 0x7847d900
+cos_5pi_9:
+ .word 0x87b82700
+cos_8pi_9:
+ .word 0xd438af00
+cos_11pi_18:
+ .word 0xadb92280
+cos_13pi_18:
+ .word 0x91261480
+cos_17pi_18:
+ .word 0x81f1d200
+cos_pi_6:
+ .word 0x6ed9eb80
+
diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_arm.s b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_arm.s
new file mode 100644
index 0000000..9401d8c
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_arm.s
@@ -0,0 +1,369 @@
+; ------------------------------------------------------------------
+; 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: pvmp3_dct_18.s
+;
+;------------------------------------------------------------------------------
+; REVISION HISTORY
+;
+;
+; Who: Date: MM/DD/YYYY
+; Description:
+;
+;------------------------------------------------------------------------------
+
+ EXPORT pvmp3_mdct_18
+
+ IMPORT ||Lib$$Request$$armlib|| [WEAK]
+ IMPORT ||Lib$$Request$$cpplib|| [WEAK]
+ IMPORT pvmp3_dct_9
+
+
+;------------------------------------------------------------------------------
+
+ AREA |.text|, CODE, READONLY, ALIGN=2
+
+
+;------------------------------------------------------------------------------
+
+|pvmp3_mdct_18| PROC
+ stmfd sp!,{r4-r10,lr}
+ mov r7,r2
+ ldr r2,table
+ mov r6,r1
+ add r3,r2,#0x24
+ add r12,r3,#0x44
+ add r1,r0,#0x44
+ mov r5,r0
+
+; for ( i=9; i!=0; i--)
+; {
+
+ mov r4,#9
+Loop_1
+
+; tmp = *(pt_vec);
+; tmp1 = *(pt_vec_o);
+
+ ldr lr,[r0] ;; tmp == lr
+ ldr r8,[r3],#4 ;; tmp1 == r8
+
+; tmp = fxp_mul32_Q32( tmp<<1, *(pt_cos++ ));
+; tmp1 = fxp_mul32_Q27( tmp1, *(pt_cos_x--));
+
+ mov lr,lr,lsl #1
+ smull r10,lr,r8,lr
+ ldr r8,[r12],#-4
+ ldr r9,[r1]
+ subs r4,r4,#1
+ smull r9,r10,r8,r9
+ mov r8,r9,lsr #27
+ add r8,r8,r10,lsl #5
+
+; *(pt_vec++) = tmp + tmp1 ;
+; *(pt_vec_o--) = fxp_mul32_Q28( (tmp - tmp1), *(pt_cos_split++));
+
+ add r9,lr,r8
+ sub r8,lr,r8
+ ldr lr,[r2],#4
+ str r9,[r0],#4
+ smull r8,r9,lr,r8
+ mov lr,r8,lsr #28
+ add lr,lr,r9,lsl #4
+ str lr,[r1],#-4
+ bne Loop_1
+
+; }
+
+ mov r0,r5 ;; r0 = vec
+ bl pvmp3_dct_9
+ add r0,r5,#0x24 ;; r0 = &vec[9]
+ bl pvmp3_dct_9
+
+ ldr r0,[r5,#0x20]
+ ldr r2,[r5,#0x40]
+ str r0,[r5,#0x40]
+ ldr r0,[r5,#0x1c]
+ ldr r3,[r5,#0x38]
+ str r0,[r5,#0x38]
+ ldr r1,[r5,#0x18]
+ ldr r0,[r5,#0x30]
+ str r1,[r5,#0x30]
+ ldr r12,[r5,#0x14]
+ ldr r1,[r5,#0x28]
+ str r12,[r5,#0x28]
+ ldr r12,[r5,#0x10]
+ str r12,[r5,#0x20]
+ ldr r12,[r5,#0xc]
+ str r12,[r5,#0x18]
+ ldr r12,[r5,#8]
+ str r12,[r5,#0x10]
+ ldr r12,[r5,#4]
+ str r12,[r5,#8]
+ ldr r12,[r5,#0x24]
+ sub r12,r12,r1
+ str r12,[r5,#4]
+ ldr r12,[r5,#0x2c]
+ sub r1,r12,r1
+ str r1,[r5,#0xc]
+ sub r1,r12,r0
+ str r1,[r5,#0x14]
+ ldr r1,[r5,#0x34]
+ sub r0,r1,r0
+ str r0,[r5,#0x1c]
+ sub r0,r1,r3
+ str r0,[r5,#0x24]
+ ldr r1,[r5,#0x3c]
+ sub r3,r1,r3
+ sub r1,r1,r2
+ str r1,[r5,#0x34]
+ str r3,[r5,#0x2c]
+ ldr r1,[r5,#0x44]
+ sub r1,r1,r2
+ str r1,[r5,#0x3c]
+ ldr r12,[r5,#0]
+
+Loop_2
+ add r1,r5,r4,lsl #2
+ ldr r2,[r1,#0x28]
+ ldr r3,[r6,r4,lsl #2]
+ add r0,r0,r2
+ str r0,[r1,#0x28]
+ ldr lr,[r7,r4,lsl #2]
+ ldr r1,[r1,#4]
+ smlal r0,r3,lr,r0
+ mov r0,r2
+ add r2,r12,r1
+ rsb r2,r2,#0
+ str r3,[r5,r4,lsl #2]
+ str r2,[r6,r4,lsl #2]
+ add r4,r4,#1
+ cmp r4,#6
+ mov r12,r1
+
+ blt Loop_2
+
+ ldr r1,[r5,#0x40]
+ ldr r2,[r6,#0x18]
+ add r3,r0,r1
+ str r3,[r5,#0x40]
+ ldr lr,[r7,r4,lsl #2]
+ mov r3,r3,lsl #1
+ ldr r0,[r5,#0x1c]
+ smlal r3,r2,lr,r3
+ add r3,r12,r0
+ str r2,[r5,#0x18]
+ ldr r2,[r6,#0x1c]
+ rsb r3,r3,#0
+ str r3,[r6,#0x18]
+ ldr r3,[r5,#0x20]
+ add r0,r3,r0
+ rsb r0,r0,#0
+ str r0,[r6,#0x1c]
+ ldr r3,[r5,#0x44]
+ ldr r0,[r6,#0x20]
+ add r3,r3,r1
+ mov r1,r2
+ ldr r10,[r7,#0x1c]
+ mov r2,r3,lsl #1
+ smlal r12,r1,r10,r2
+ str r1,[r5,#0x1c]
+ ldr r1,[r5,#0x20]
+ ldr r3,[r5,#0x24]
+ add r1,r1,r3
+ rsb r1,r1,#0
+ str r1,[r6,#0x20]
+ ldr r1,[r5,#0x44]
+ ldr r3,[r7,#0x20]
+ mov r1,r1,lsl #1
+ smlal r12,r0,r3,r1
+ ldr lr,[r7,#0x24]
+ ldr r3,[r6,#0x24]
+ str r0,[r5,#0x20]
+ smlal r1,r3,lr,r1
+ ldr r0,[r6,#0x40]
+ ldr r12,[r6,#0x44]
+ str r3,[r5,#0x24]
+ ldr r1,[r5,#0x28]
+ ldr r3,[r7,#0x44]
+ mov r1,r1,lsl #1
+ smlal r1,r12,r3,r1
+ ldr r1,[r5,#0x40]
+ str r12,[r5,#0x44]
+ rsb r8,r1,#0
+ str r8,[r5,#0x28]
+ ldr r1,[r5,#0x2c]
+ ldr r3,[r7,#0x40]
+ mov r1,r1,lsl #1
+ smlal r1,r0,r3,r1
+ str r0,[r5,#0x40]
+ ldr r0,[r5,#0x3c]
+ ldr r1,[r6,#0x38]
+ ldr r3,[r6,#0x3c]
+ rsb r9,r0,#0
+ str r9,[r5,#0x2c]
+ ldr r0,[r5,#0x30]
+ ldr r12,[r7,#0x3c]
+ mov r0,r0,lsl #1
+ smlal r0,r3,r12,r0
+ str r3,[r5,#0x3c]
+ ldr r0,[r5,#0x38]
+ rsb r0,r0,#0
+ str r0,[r5,#0x30]
+ ldr r3,[r5,#0x34]
+ ldr r12,[r7,#0x38]
+ mov r3,r3,lsl #1
+ smlal r3,r1,r12,r3
+ mov r0,r0,lsl #1
+ str r1,[r5,#0x38]
+ ldr r4,[r7,#0x34]
+ ldr r1,[r6,#0x34]
+ ldr r3,[r6,#0x30]
+ smlal r0,r1,r4,r0
+ ldr r12,[r6,#0x2c]
+ ldr lr,[r6,#0x28]
+ str r1,[r5,#0x34]
+ ldr r1,[r7,#0x30]
+ mov r0,r9,lsl #1
+ smlal r0,r3,r1,r0
+ mov r0,r8,lsl #1
+ ldr r1,[r7,#0x2c]
+ str r3,[r5,#0x30]
+ smlal r0,r12,r1,r0
+ ldr r0,[r7,#0x28]
+ str r12,[r5,#0x2c]
+ smlal r2,lr,r0,r2
+ str lr,[r5,#0x28]
+ ldr r1,[r6,#4]
+ ldr r12,[r7,#0x48]
+ mov r2,r1,lsl #1
+ ldr r1,[r6,#0x20]
+ ldr r0,[r6]
+ mov r1,r1,lsl #1
+ smull r4,lr,r12,r1
+ ldr r3,[r6,#0x1c]
+ str lr,[r6]
+ ldr r12,[r7,#0x4c]
+ mov r3,r3,lsl #1
+ smull r4,lr,r12,r3
+ mov r0,r0,lsl #1
+ ldr r12,[r7,#0x64]
+ str lr,[r6,#4]
+ smull r4,lr,r12,r2
+ ldr r12,[r7,#0x68]
+ str lr,[r6,#0x1c]
+ smull r4,lr,r12,r0
+ ldr r12,[r7,#0x6c]
+ str lr,[r6,#0x20]
+ smull lr,r0,r12,r0
+ ldr r12,[r7,#0x70]
+ str r0,[r6,#0x24]
+ smull r0,r2,r12,r2
+ ldr r0,[r7,#0x88]
+ str r2,[r6,#0x28]
+ smull r3,r2,r0,r3
+ ldr r0,[r7,#0x8c]
+ str r2,[r6,#0x40]
+ smull r2,r1,r0,r1
+ str r1,[r6,#0x44]
+ ldr r0,[r6,#0x18]
+ ldr lr,[r7,#0x50]
+ mov r1,r0,lsl #1
+ ldr r0,[r6,#0x14]
+ smull r5,r4,lr,r1
+ ldr r12,[r6,#0x10]
+ mov r3,r0,lsl #1
+ ldr r0,[r6,#0xc]
+ mov r12,r12,lsl #1
+ mov r2,r0,lsl #1
+ ldr r0,[r6,#8]
+ str r4,[r6,#8]
+ ldr lr,[r7,#0x54]
+ mov r0,r0,lsl #1
+ smull r5,r4,lr,r3
+ ldr lr,[r7,#0x58]
+ str r4,[r6,#0xc]
+ smull r5,r4,lr,r12
+ ldr lr,[r7,#0x5c]
+ str r4,[r6,#0x10]
+ smull r5,r4,lr,r2
+ ldr lr,[r7,#0x60]
+ str r4,[r6,#0x14]
+ smull r5,r4,lr,r0
+ ldr lr,[r7,#0x74]
+ str r4,[r6,#0x18]
+ smull r4,r0,lr,r0
+ ldr lr,[r7,#0x78]
+ str r0,[r6,#0x2c]
+ smull r0,r2,lr,r2
+ ldr r0,[r7,#0x7c]
+ str r2,[r6,#0x30]
+ smull r12,r2,r0,r12
+ ldr r0,[r7,#0x80]
+ str r2,[r6,#0x34]
+ smull r3,r2,r0,r3
+ ldr r0,[r7,#0x84]
+ str r2,[r6,#0x38]
+ smull r2,r1,r0,r1
+ str r1,[r6,#0x3c]
+ ldmfd sp!,{r4-r10,pc}
+table
+ DCD ||.constdata$1||
+ ENDP
+
+;------------------------------------------------------------------------------
+
+ AREA |.constdata|, DATA, READONLY, ALIGN=2
+
+;------------------------------------------------------------------------------
+
+||.constdata$1||
+cosTerms_dct18
+ DCD 0x0807d2b0
+ DCD 0x08483ee0
+ DCD 0x08d3b7d0
+ DCD 0x09c42570
+ DCD 0x0b504f30
+ DCD 0x0df29440
+ DCD 0x12edfb20
+ DCD 0x1ee8dd40
+ DCD 0x5bca2a00
+cosTerms_1_ov_cos_phi
+ DCD 0x400f9c00
+ DCD 0x408d6080
+ DCD 0x418dcb80
+ DCD 0x431b1a00
+ DCD 0x4545ea00
+ DCD 0x48270680
+ DCD 0x4be25480
+ DCD 0x50ab9480
+ DCD 0x56ce4d80
+ DCD 0x05ebb630
+ DCD 0x06921a98
+ DCD 0x0771d3a8
+ DCD 0x08a9a830
+ DCD 0x0a73d750
+ DCD 0x0d4d5260
+ DCD 0x127b1ca0
+ DCD 0x1ea52b40
+ DCD 0x5bb3cc80
+
+
+
+ END
diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s
new file mode 100644
index 0000000..96230c5
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s
@@ -0,0 +1,359 @@
+@ ------------------------------------------------------------------
+@ 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: pvmp3_dct_18_gcc.s
+@
+@------------------------------------------------------------------------------
+@ REVISION HISTORY
+@
+@
+@ Who: Date: MM/DD/YYYY
+@ Description:
+@
+@------------------------------------------------------------------------------
+
+.arm
+
+.align 4
+
+.text
+
+.extern pvmp3_dct_9
+
+@------------------------------------------------------------------------------
+
+.global pvmp3_mdct_18
+
+pvmp3_mdct_18:
+ stmfd sp!,{r4-r11,lr}
+ mov r7,r2
+ ldr r2,table
+ mov r6,r1
+ add r3,r2,#0x24
+ add r12,r3,#0x44
+ add r1,r0,#0x44
+ mov r5,r0
+
+@ for ( i=9@ i!=0@ i--)
+@ {
+
+ mov r4,#9
+Loop_1:
+
+@ tmp = *(pt_vec)
+@ tmp1 = *(pt_vec_o)
+
+ ldr lr,[r0] @@ tmp == lr
+ ldr r8,[r3],#4 @@ tmp1 == r8
+
+@ tmp = fxp_mul32_Q32( tmp<<1, *(pt_cos++ ))
+@ tmp1 = fxp_mul32_Q27( tmp1, *(pt_cos_x--))
+
+ mov lr,lr,lsl #1
+ smull r10,lr,r8,lr
+ ldr r8,[r12],#-4
+ ldr r9,[r1]
+ subs r4,r4,#1
+ smull r9,r10,r8,r9
+ mov r8,r9,lsr #27
+ add r8,r8,r10,lsl #5
+
+@ *(pt_vec++) = tmp + tmp1
+@ *(pt_vec_o--) = fxp_mul32_Q28( (tmp - tmp1), *(pt_cos_split++))
+
+ add r9,lr,r8
+ sub r8,lr,r8
+ ldr lr,[r2],#4
+ str r9,[r0],#4
+ smull r8,r9,lr,r8
+ mov lr,r8,lsr #28
+ add lr,lr,r9,lsl #4
+ str lr,[r1],#-4
+ bne Loop_1
+
+@ }
+
+ mov r0,r5 @@ r0 = vec
+ bl pvmp3_dct_9
+ add r0,r5,#0x24 @@ r0 = &vec[9]
+ bl pvmp3_dct_9
+
+ ldr r0,[r5,#0x20]
+ ldr r2,[r5,#0x40]
+ str r0,[r5,#0x40]
+ ldr r0,[r5,#0x1c]
+ ldr r3,[r5,#0x38]
+ str r0,[r5,#0x38]
+ ldr r1,[r5,#0x18]
+ ldr r0,[r5,#0x30]
+ str r1,[r5,#0x30]
+ ldr r12,[r5,#0x14]
+ ldr r1,[r5,#0x28]
+ str r12,[r5,#0x28]
+ ldr r12,[r5,#0x10]
+ str r12,[r5,#0x20]
+ ldr r12,[r5,#0xc]
+ str r12,[r5,#0x18]
+ ldr r12,[r5,#8]
+ str r12,[r5,#0x10]
+ ldr r12,[r5,#4]
+ str r12,[r5,#8]
+ ldr r12,[r5,#0x24]
+ sub r12,r12,r1
+ str r12,[r5,#4]
+ ldr r12,[r5,#0x2c]
+ sub r1,r12,r1
+ str r1,[r5,#0xc]
+ sub r1,r12,r0
+ str r1,[r5,#0x14]
+ ldr r1,[r5,#0x34]
+ sub r0,r1,r0
+ str r0,[r5,#0x1c]
+ sub r0,r1,r3
+ str r0,[r5,#0x24]
+ ldr r1,[r5,#0x3c]
+ sub r3,r1,r3
+ sub r1,r1,r2
+ str r1,[r5,#0x34]
+ str r3,[r5,#0x2c]
+ ldr r1,[r5,#0x44]
+ sub r1,r1,r2
+ str r1,[r5,#0x3c]
+ ldr r12,[r5,#0]
+
+Loop_2:
+ add r1,r5,r4,lsl #2
+ ldr r2,[r1,#0x28]
+ ldr r3,[r6,r4,lsl #2]
+ add r0,r0,r2
+ str r0,[r1,#0x28]
+ ldr lr,[r7,r4,lsl #2]
+ ldr r1,[r1,#4]
+ smlal r0,r3,lr,r0
+ mov r0,r2
+ add r2,r12,r1
+ rsb r2,r2,#0
+ str r3,[r5,r4,lsl #2]
+ str r2,[r6,r4,lsl #2]
+ add r4,r4,#1
+ cmp r4,#6
+ mov r12,r1
+
+ blt Loop_2
+
+ ldr r1,[r5,#0x40]
+ ldr r2,[r6,#0x18]
+ add r3,r0,r1
+ str r3,[r5,#0x40]
+ ldr lr,[r7,r4,lsl #2]
+ mov r3,r3,lsl #1
+ ldr r0,[r5,#0x1c]
+ smlal r3,r2,lr,r3
+ add r3,r12,r0
+ str r2,[r5,#0x18]
+ ldr r2,[r6,#0x1c]
+ rsb r3,r3,#0
+ str r3,[r6,#0x18]
+ ldr r3,[r5,#0x20]
+ add r0,r3,r0
+ rsb r0,r0,#0
+ str r0,[r6,#0x1c]
+ ldr r3,[r5,#0x44]
+ ldr r0,[r6,#0x20]
+ add r3,r3,r1
+ mov r1,r2
+ ldr r10,[r7,#0x1c]
+ mov r2,r3,lsl #1
+ smlal r12,r1,r10,r2
+ str r1,[r5,#0x1c]
+ ldr r1,[r5,#0x20]
+ ldr r3,[r5,#0x24]
+ add r1,r1,r3
+ rsb r1,r1,#0
+ str r1,[r6,#0x20]
+ ldr r1,[r5,#0x44]
+ ldr r3,[r7,#0x20]
+ mov r1,r1,lsl #1
+ smlal r12,r0,r3,r1
+ ldr lr,[r7,#0x24]
+ ldr r3,[r6,#0x24]
+ str r0,[r5,#0x20]
+ smlal r1,r3,lr,r1
+ ldr r0,[r6,#0x40]
+ ldr r12,[r6,#0x44]
+ str r3,[r5,#0x24]
+ ldr r1,[r5,#0x28]
+ ldr r3,[r7,#0x44]
+ mov r1,r1,lsl #1
+ smlal r1,r12,r3,r1
+ ldr r1,[r5,#0x40]
+ str r12,[r5,#0x44]
+ rsb r8,r1,#0
+ str r8,[r5,#0x28]
+ ldr r1,[r5,#0x2c]
+ ldr r3,[r7,#0x40]
+ mov r1,r1,lsl #1
+ smlal r1,r0,r3,r1
+ str r0,[r5,#0x40]
+ ldr r0,[r5,#0x3c]
+ ldr r1,[r6,#0x38]
+ ldr r3,[r6,#0x3c]
+ rsb r9,r0,#0
+ str r9,[r5,#0x2c]
+ ldr r0,[r5,#0x30]
+ ldr r12,[r7,#0x3c]
+ mov r0,r0,lsl #1
+ smlal r0,r3,r12,r0
+ str r3,[r5,#0x3c]
+ ldr r0,[r5,#0x38]
+ rsb r0,r0,#0
+ str r0,[r5,#0x30]
+ ldr r3,[r5,#0x34]
+ ldr r12,[r7,#0x38]
+ mov r3,r3,lsl #1
+ smlal r3,r1,r12,r3
+ mov r0,r0,lsl #1
+ str r1,[r5,#0x38]
+ ldr r4,[r7,#0x34]
+ ldr r1,[r6,#0x34]
+ ldr r3,[r6,#0x30]
+ smlal r0,r1,r4,r0
+ ldr r12,[r6,#0x2c]
+ ldr lr,[r6,#0x28]
+ str r1,[r5,#0x34]
+ ldr r1,[r7,#0x30]
+ mov r0,r9,lsl #1
+ smlal r0,r3,r1,r0
+ mov r0,r8,lsl #1
+ ldr r1,[r7,#0x2c]
+ str r3,[r5,#0x30]
+ smlal r0,r12,r1,r0
+ ldr r0,[r7,#0x28]
+ str r12,[r5,#0x2c]
+ smlal r2,lr,r0,r2
+ str lr,[r5,#0x28]
+ ldr r1,[r6,#4]
+ ldr r12,[r7,#0x48]
+ mov r2,r1,lsl #1
+ ldr r1,[r6,#0x20]
+ ldr r0,[r6,#0]
+ mov r1,r1,lsl #1
+ smull r4,lr,r12,r1
+ ldr r3,[r6,#0x1c]
+ str lr,[r6,#0]
+ ldr r12,[r7,#0x4c]
+ mov r3,r3,lsl #1
+ smull r4,lr,r12,r3
+ mov r0,r0,lsl #1
+ ldr r12,[r7,#0x64]
+ str lr,[r6,#4]
+ smull r4,lr,r12,r2
+ ldr r12,[r7,#0x68]
+ str lr,[r6,#0x1c]
+ smull r4,lr,r12,r0
+ ldr r12,[r7,#0x6c]
+ str lr,[r6,#0x20]
+ smull lr,r0,r12,r0
+ ldr r12,[r7,#0x70]
+ str r0,[r6,#0x24]
+ smull r0,r2,r12,r2
+ ldr r0,[r7,#0x88]
+ str r2,[r6,#0x28]
+ smull r3,r2,r0,r3
+ ldr r0,[r7,#0x8c]
+ str r2,[r6,#0x40]
+ smull r2,r1,r0,r1
+ str r1,[r6,#0x44]
+ ldr r0,[r6,#0x18]
+ ldr lr,[r7,#0x50]
+ mov r1,r0,lsl #1
+ ldr r0,[r6,#0x14]
+ smull r5,r4,lr,r1
+ mov r3,r0,lsl #1
+ ldr r0,[r6,#0x10]
+ mov r12,r0,lsl #1
+ ldr r0,[r6,#0xc]
+ mov r2,r0,lsl #1
+ ldr r0,[r6,#8]
+ str r4,[r6,#8]
+ ldr lr,[r7,#0x54]
+ mov r0,r0,lsl #1
+ smull r5,r4,lr,r3
+ ldr lr,[r7,#0x58]
+ str r4,[r6,#0xc]
+ smull r5,r4,lr,r12
+ ldr lr,[r7,#0x5c]
+ str r4,[r6,#0x10]
+ smull r5,r4,lr,r2
+ ldr lr,[r7,#0x60]
+ str r4,[r6,#0x14]
+ smull r5,r4,lr,r0
+ ldr lr,[r7,#0x74]
+ str r4,[r6,#0x18]
+ smull r4,r0,lr,r0
+ ldr lr,[r7,#0x78]
+ str r0,[r6,#0x2c]
+ smull r0,r2,lr,r2
+ ldr r0,[r7,#0x7c]
+ str r2,[r6,#0x30]
+ smull r12,r2,r0,r12
+ ldr r0,[r7,#0x80]
+ str r2,[r6,#0x34]
+ smull r3,r2,r0,r3
+ ldr r0,[r7,#0x84]
+ str r2,[r6,#0x38]
+ smull r2,r1,r0,r1
+ str r1,[r6,#0x3c]
+ ldmfd sp!,{r4-r11,pc}
+table:
+ .word constdata$1
+
+@------------------------------------------------------------------------------
+
+constdata$1:
+cosTerms_dct18:
+ .word 0x0807d2b0
+ .word 0x08483ee0
+ .word 0x08d3b7d0
+ .word 0x09c42570
+ .word 0x0b504f30
+ .word 0x0df29440
+ .word 0x12edfb20
+ .word 0x1ee8dd40
+ .word 0x5bca2a00
+cosTerms_1_ov_cos_phi:
+ .word 0x400f9c00
+ .word 0x408d6080
+ .word 0x418dcb80
+ .word 0x431b1a00
+ .word 0x4545ea00
+ .word 0x48270680
+ .word 0x4be25480
+ .word 0x50ab9480
+ .word 0x56ce4d80
+ .word 0x05ebb630
+ .word 0x06921a98
+ .word 0x0771d3a8
+ .word 0x08a9a830
+ .word 0x0a73d750
+ .word 0x0d4d5260
+ .word 0x127b1ca0
+ .word 0x1ea52b40
+ .word 0x5bb3cc80
+
diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_wm.asm b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_wm.asm
new file mode 100644
index 0000000..5be75d4
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_mdct_18_wm.asm
@@ -0,0 +1,366 @@
+; ------------------------------------------------------------------
+; 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: pvmp3_dct_18.s
+;
+;------------------------------------------------------------------------------
+; REVISION HISTORY
+;
+;
+; Who: Date: MM/DD/YYYY
+; Description:
+;
+;------------------------------------------------------------------------------
+
+ EXPORT |pvmp3_mdct_18|
+
+ IMPORT pvmp3_dct_9
+
+
+;------------------------------------------------------------------------------
+
+ AREA |.text|, CODE, READONLY, ALIGN=2
+
+
+;------------------------------------------------------------------------------
+
+|pvmp3_mdct_18| PROC
+ stmfd sp!,{r4-r10,lr}
+ mov r7,r2
+ ldr r2,table
+ mov r6,r1
+ add r3,r2,#0x24
+ add r12,r3,#0x44
+ add r1,r0,#0x44
+ mov r5,r0
+
+; for ( i=9; i!=0; i--)
+; {
+
+ mov r4,#9
+Loop_1
+
+; tmp = *(pt_vec);
+; tmp1 = *(pt_vec_o);
+
+ ldr lr,[r0] ;; tmp == lr
+ ldr r8,[r3],#4 ;; tmp1 == r8
+
+; tmp = fxp_mul32_Q32( tmp<<1, *(pt_cos++ ));
+; tmp1 = fxp_mul32_Q27( tmp1, *(pt_cos_x--));
+
+ mov lr,lr,lsl #1
+ smull r10,lr,r8,lr
+ ldr r8,[r12],#-4
+ ldr r9,[r1]
+ subs r4,r4,#1
+ smull r9,r10,r8,r9
+ mov r8,r9,lsr #27
+ add r8,r8,r10,lsl #5
+
+; *(pt_vec++) = tmp + tmp1 ;
+; *(pt_vec_o--) = fxp_mul32_Q28( (tmp - tmp1), *(pt_cos_split++));
+
+ add r9,lr,r8
+ sub r8,lr,r8
+ ldr lr,[r2],#4
+ str r9,[r0],#4
+ smull r8,r9,lr,r8
+ mov lr,r8,lsr #28
+ add lr,lr,r9,lsl #4
+ str lr,[r1],#-4
+ bne Loop_1
+
+; }
+
+ mov r0,r5 ;; r0 = vec
+ bl pvmp3_dct_9
+ add r0,r5,#0x24 ;; r0 = &vec[9]
+ bl pvmp3_dct_9
+
+ ldr r0,[r5,#0x20]
+ ldr r2,[r5,#0x40]
+ str r0,[r5,#0x40]
+ ldr r0,[r5,#0x1c]
+ ldr r3,[r5,#0x38]
+ str r0,[r5,#0x38]
+ ldr r1,[r5,#0x18]
+ ldr r0,[r5,#0x30]
+ str r1,[r5,#0x30]
+ ldr r12,[r5,#0x14]
+ ldr r1,[r5,#0x28]
+ str r12,[r5,#0x28]
+ ldr r12,[r5,#0x10]
+ str r12,[r5,#0x20]
+ ldr r12,[r5,#0xc]
+ str r12,[r5,#0x18]
+ ldr r12,[r5,#8]
+ str r12,[r5,#0x10]
+ ldr r12,[r5,#4]
+ str r12,[r5,#8]
+ ldr r12,[r5,#0x24]
+ sub r12,r12,r1
+ str r12,[r5,#4]
+ ldr r12,[r5,#0x2c]
+ sub r1,r12,r1
+ str r1,[r5,#0xc]
+ sub r1,r12,r0
+ str r1,[r5,#0x14]
+ ldr r1,[r5,#0x34]
+ sub r0,r1,r0
+ str r0,[r5,#0x1c]
+ sub r0,r1,r3
+ str r0,[r5,#0x24]
+ ldr r1,[r5,#0x3c]
+ sub r3,r1,r3
+ sub r1,r1,r2
+ str r1,[r5,#0x34]
+ str r3,[r5,#0x2c]
+ ldr r1,[r5,#0x44]
+ sub r1,r1,r2
+ str r1,[r5,#0x3c]
+ ldr r12,[r5,#0]
+
+Loop_2
+ add r1,r5,r4,lsl #2
+ ldr r2,[r1,#0x28]
+ ldr r3,[r6,r4,lsl #2]
+ add r0,r0,r2
+ str r0,[r1,#0x28]
+ ldr lr,[r7,r4,lsl #2]
+ ldr r1,[r1,#4]
+ smlal r0,r3,lr,r0
+ mov r0,r2
+ add r2,r12,r1
+ rsb r2,r2,#0
+ str r3,[r5,r4,lsl #2]
+ str r2,[r6,r4,lsl #2]
+ add r4,r4,#1
+ cmp r4,#6
+ mov r12,r1
+
+ blt Loop_2
+
+ ldr r1,[r5,#0x40]
+ ldr r2,[r6,#0x18]
+ add r3,r0,r1
+ str r3,[r5,#0x40]
+ ldr lr,[r7,r4,lsl #2]
+ mov r3,r3,lsl #1
+ ldr r0,[r5,#0x1c]
+ smlal r3,r2,lr,r3
+ add r3,r12,r0
+ str r2,[r5,#0x18]
+ ldr r2,[r6,#0x1c]
+ rsb r3,r3,#0
+ str r3,[r6,#0x18]
+ ldr r3,[r5,#0x20]
+ add r0,r3,r0
+ rsb r0,r0,#0
+ str r0,[r6,#0x1c]
+ ldr r3,[r5,#0x44]
+ ldr r0,[r6,#0x20]
+ add r3,r3,r1
+ mov r1,r2
+ ldr r10,[r7,#0x1c]
+ mov r2,r3,lsl #1
+ smlal r12,r1,r10,r2
+ str r1,[r5,#0x1c]
+ ldr r1,[r5,#0x20]
+ ldr r3,[r5,#0x24]
+ add r1,r1,r3
+ rsb r1,r1,#0
+ str r1,[r6,#0x20]
+ ldr r1,[r5,#0x44]
+ ldr r3,[r7,#0x20]
+ mov r1,r1,lsl #1
+ smlal r12,r0,r3,r1
+ ldr lr,[r7,#0x24]
+ ldr r3,[r6,#0x24]
+ str r0,[r5,#0x20]
+ smlal r1,r3,lr,r1
+ ldr r0,[r6,#0x40]
+ ldr r12,[r6,#0x44]
+ str r3,[r5,#0x24]
+ ldr r1,[r5,#0x28]
+ ldr r3,[r7,#0x44]
+ mov r1,r1,lsl #1
+ smlal r1,r12,r3,r1
+ ldr r1,[r5,#0x40]
+ str r12,[r5,#0x44]
+ rsb r8,r1,#0
+ str r8,[r5,#0x28]
+ ldr r1,[r5,#0x2c]
+ ldr r3,[r7,#0x40]
+ mov r1,r1,lsl #1
+ smlal r1,r0,r3,r1
+ str r0,[r5,#0x40]
+ ldr r0,[r5,#0x3c]
+ ldr r1,[r6,#0x38]
+ ldr r3,[r6,#0x3c]
+ rsb r9,r0,#0
+ str r9,[r5,#0x2c]
+ ldr r0,[r5,#0x30]
+ ldr r12,[r7,#0x3c]
+ mov r0,r0,lsl #1
+ smlal r0,r3,r12,r0
+ str r3,[r5,#0x3c]
+ ldr r0,[r5,#0x38]
+ rsb r0,r0,#0
+ str r0,[r5,#0x30]
+ ldr r3,[r5,#0x34]
+ ldr r12,[r7,#0x38]
+ mov r3,r3,lsl #1
+ smlal r3,r1,r12,r3
+ mov r0,r0,lsl #1
+ str r1,[r5,#0x38]
+ ldr r4,[r7,#0x34]
+ ldr r1,[r6,#0x34]
+ ldr r3,[r6,#0x30]
+ smlal r0,r1,r4,r0
+ ldr r12,[r6,#0x2c]
+ ldr lr,[r6,#0x28]
+ str r1,[r5,#0x34]
+ ldr r1,[r7,#0x30]
+ mov r0,r9,lsl #1
+ smlal r0,r3,r1,r0
+ mov r0,r8,lsl #1
+ ldr r1,[r7,#0x2c]
+ str r3,[r5,#0x30]
+ smlal r0,r12,r1,r0
+ ldr r0,[r7,#0x28]
+ str r12,[r5,#0x2c]
+ smlal r2,lr,r0,r2
+ str lr,[r5,#0x28]
+ ldr r1,[r6,#4]
+ ldr r12,[r7,#0x48]
+ mov r2,r1,lsl #1
+ ldr r1,[r6,#0x20]
+ ldr r0,[r6]
+ mov r1,r1,lsl #1
+ smull r4,lr,r12,r1
+ ldr r3,[r6,#0x1c]
+ str lr,[r6]
+ ldr r12,[r7,#0x4c]
+ mov r3,r3,lsl #1
+ smull r4,lr,r12,r3
+ mov r0,r0,lsl #1
+ ldr r12,[r7,#0x64]
+ str lr,[r6,#4]
+ smull r4,lr,r12,r2
+ ldr r12,[r7,#0x68]
+ str lr,[r6,#0x1c]
+ smull r4,lr,r12,r0
+ ldr r12,[r7,#0x6c]
+ str lr,[r6,#0x20]
+ smull lr,r0,r12,r0
+ ldr r12,[r7,#0x70]
+ str r0,[r6,#0x24]
+ smull r0,r2,r12,r2
+ ldr r0,[r7,#0x88]
+ str r2,[r6,#0x28]
+ smull r3,r2,r0,r3
+ ldr r0,[r7,#0x8c]
+ str r2,[r6,#0x40]
+ smull r2,r1,r0,r1
+ str r1,[r6,#0x44]
+ ldr r0,[r6,#0x18]
+ ldr lr,[r7,#0x50]
+ mov r1,r0,lsl #1
+ ldr r0,[r6,#0x14]
+ smull r5,r4,lr,r1
+ ldr r12,[r6,#0x10]
+ mov r3,r0,lsl #1
+ ldr r0,[r6,#0xc]
+ mov r12,r12,lsl #1
+ mov r2,r0,lsl #1
+ ldr r0,[r6,#8]
+ str r4,[r6,#8]
+ ldr lr,[r7,#0x54]
+ mov r0,r0,lsl #1
+ smull r5,r4,lr,r3
+ ldr lr,[r7,#0x58]
+ str r4,[r6,#0xc]
+ smull r5,r4,lr,r12
+ ldr lr,[r7,#0x5c]
+ str r4,[r6,#0x10]
+ smull r5,r4,lr,r2
+ ldr lr,[r7,#0x60]
+ str r4,[r6,#0x14]
+ smull r5,r4,lr,r0
+ ldr lr,[r7,#0x74]
+ str r4,[r6,#0x18]
+ smull r4,r0,lr,r0
+ ldr lr,[r7,#0x78]
+ str r0,[r6,#0x2c]
+ smull r0,r2,lr,r2
+ ldr r0,[r7,#0x7c]
+ str r2,[r6,#0x30]
+ smull r12,r2,r0,r12
+ ldr r0,[r7,#0x80]
+ str r2,[r6,#0x34]
+ smull r3,r2,r0,r3
+ ldr r0,[r7,#0x84]
+ str r2,[r6,#0x38]
+ smull r2,r1,r0,r1
+ str r1,[r6,#0x3c]
+ ldmfd sp!,{r4-r10,pc}
+table
+ DCD cosTerms_dct18
+ ENDP
+
+;------------------------------------------------------------------------------
+
+ AREA |.constdata|, DATA, READONLY, ALIGN=2
+
+;------------------------------------------------------------------------------
+
+cosTerms_dct18
+ DCD 0x0807d2b0
+ DCD 0x08483ee0
+ DCD 0x08d3b7d0
+ DCD 0x09c42570
+ DCD 0x0b504f30
+ DCD 0x0df29440
+ DCD 0x12edfb20
+ DCD 0x1ee8dd40
+ DCD 0x5bca2a00
+cosTerms_1_ov_cos_phi
+ DCD 0x400f9c00
+ DCD 0x408d6080
+ DCD 0x418dcb80
+ DCD 0x431b1a00
+ DCD 0x4545ea00
+ DCD 0x48270680
+ DCD 0x4be25480
+ DCD 0x50ab9480
+ DCD 0x56ce4d80
+ DCD 0x05ebb630
+ DCD 0x06921a98
+ DCD 0x0771d3a8
+ DCD 0x08a9a830
+ DCD 0x0a73d750
+ DCD 0x0d4d5260
+ DCD 0x127b1ca0
+ DCD 0x1ea52b40
+ DCD 0x5bb3cc80
+
+
+
+ END
diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_arm.s b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_arm.s
new file mode 100644
index 0000000..abec599
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_arm.s
@@ -0,0 +1,237 @@
+; ------------------------------------------------------------------
+; 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: pvmp3_polyphase_filter_window.s
+;
+;------------------------------------------------------------------------------
+; REVISION HISTORY
+;
+;
+; Who: Date: MM/DD/YYYY
+; Description:
+;
+;------------------------------------------------------------------------------
+
+ EXPORT pvmp3_polyphase_filter_window
+
+ IMPORT ||Lib$$Request$$armlib|| [WEAK]
+ IMPORT ||Lib$$Request$$cpplib|| [WEAK]
+ IMPORT pqmfSynthWin
+
+
+
+;------------------------------------------------------------------------------
+
+ AREA |.text|, CODE, READONLY, ALIGN=2
+
+
+;------------------------------------------------------------------------------
+
+|pvmp3_polyphase_filter_window| PROC
+
+ stmfd sp!,{r0-r2,r4-r11,lr}
+
+ sub sp,sp,#4
+ ldr r2,[sp,#0xc]
+ ldr r1,PolyPh_filter_coeff
+
+ sub r2,r2,#1
+ mov r10,#1
+ str r2,[sp]
+
+; Accumulators r9, r11::> Initialization
+
+Loop_j
+ mov r9, #0x20
+ mov r11, #0x20
+ mov r4, #0x10
+Loop_i
+ add r2,r4,r10
+ add r3,r0,r2,lsl #2
+ sub r2,r4,r10
+ ldr r5,[r3]
+ ldr lr,[r1]
+ add r12,r0,r2,lsl #2
+ ldr r6,[r12,#0x780]
+ smlal r2,r9,lr,r5
+ smlal r2,r11,lr,r6
+ ldr r2,[r1,#4]
+ ldr r7,[r12,#0x80]
+ smlal r5,r11,r2,r5
+ smull r6,r5,r2,r6
+ sub r9,r9,r5
+ ldr r5,[r1,#8]
+ ldr r8,[r3,#0x700]
+ add r4,r4,#0x200
+ smlal r6,r9,r5,r7
+ smull r6,r2,r5,r8
+ ldr r5,[r1,#0xc]
+ sub r11,r11,r2
+ smlal r8,r9,r5,r8
+ smlal r7,r11,r5,r7
+ ldr r5,[r3,#0x100]
+ ldr r2,[r1,#0x10]
+ ldr r6,[r12,#0x680]
+ smlal lr,r9,r2,r5
+ smlal lr,r11,r2,r6
+ ldr r2,[r1,#0x14]
+ ldr r7,[r12,#0x180]
+ smlal r5,r11,r2,r5
+ smull r6,r5,r2,r6
+ ldr r6,[r1,#0x18]
+ ldr r8,[r3,#0x600]
+ sub r9,r9,r5
+ smlal r5,r9,r6,r7
+ smull r2,r5,r6,r8
+ ldr r6,[r1,#0x1c]
+ sub r11,r11,r5
+ smlal r8,r9,r6,r8
+ ldr r2,[r1,#0x20]
+ ldr r5,[r3,#0x200]
+ smlal r7,r11,r6,r7
+ ldr r6,[r12,#0x580]
+ smlal lr,r9,r2,r5
+ smlal lr,r11,r2,r6
+ ldr r2,[r1,#0x24]
+ ldr r7,[r12,#0x280]
+ smlal r5,r11,r2,r5
+ smull r6,r5,r2,r6
+ ldr r6,[r1,#0x28]
+ ldr r8,[r3,#0x500]
+ sub r9,r9,r5
+ smlal r5,r9,r6,r7
+ smull r2,r5,r6,r8
+ ldr r6,[r1,#0x2c]
+ sub r11,r11,r5
+
+ smlal r8,r9,r6,r8
+ smlal r7,r11,r6,r7
+ ldr r5,[r3,#0x300]
+ ldr r8,[r1,#0x30]
+ ldr r6,[r12,#0x480]
+ smlal r7,r9,r8,r5
+ smlal r7,r11,r8,r6
+ ldr r8,[r1,#0x34]
+ ldr r12,[r12,#0x380]
+ smlal r5,r11,r8,r5
+ smull r6,r5,r8,r6
+ ldr r6,[r1,#0x38]
+
+
+ ldr r3,[r3,#0x400]
+ sub r9,r9,r5
+ smlal r7,r9,r6,r12
+ smull r8,r7,r6,r3
+ cmp r4,#0x210
+ sub r11,r11,r7
+
+ ldr r2,[r1,#0x3c]
+ add r1,r1,#0x40
+ smlal r3,r9,r2,r3
+ smlal r12,r11,r2,r12
+
+ blt Loop_i
+
+ mov r3,r9, asr #6
+ mov r4,r3, asr #15
+ teq r4,r3, asr #31
+ ldr r12,LOW_16BITS
+ ldr r2,[sp]
+ eorne r3,r12,r3,asr #31
+ ldr r4,[sp,#8]
+ mov r2,r10,lsl r2
+ add r4,r4,r2,lsl #1
+ strh r3,[r4]
+
+ mov r3,r11,asr #6
+ mov r4,r3,asr #15
+ teq r4,r3,asr #31
+ eorne r3,r12,r3,asr #31
+ ldr r12,[sp,#0xc]
+ ldr r11,[sp,#8]
+ rsb r2,r2,r12,lsl #5
+ add r2,r11,r2,lsl #1
+ strh r3,[r2]
+
+ add r10,r10,#1
+ cmp r10,#0x10
+ blt Loop_j
+
+; Accumulators r4, r5 Initialization
+
+ mov r4,#0x20
+ mov r5,#0x20
+ mov r3,#0x10
+PolyPh_filter_loop2
+ add r2,r0,r3,lsl #2
+ ldr r12,[r2]
+ ldr r8,[r1]
+ ldr r6,[r2,#0x80]
+ smlal r12,r4,r8,r12
+ ldr r12,[r1,#4]
+ ldr r7,[r2,#0x40]
+ smlal r6,r4,r12,r6
+
+ ldr r12,[r1,#8]
+ ldr r6,[r2,#0x180]
+ smlal r7,r5,r12,r7
+ ldr r12,[r2,#0x100]
+ ldr r7,[r1,#0xc]
+ ldr r2,[r2,#0x140]
+ smlal r12,r4,r7,r12
+ ldr r12,[r1,#0x10]
+ add r3,r3,#0x80
+ smlal r6,r4,r12,r6
+ ldr r6,[r1,#0x14]
+ cmp r3,#0x210
+ smlal r2,r5,r6,r2
+ add r1,r1,#0x18
+
+ blt PolyPh_filter_loop2
+ mov r0,r4,asr #6
+ mov r2,r0,asr #15
+ teq r2,r0,asr #31
+ ldrne r12,LOW_16BITS
+ ldr r1,[sp,#8]
+ eorne r0,r12,r0,asr #31
+ strh r0,[r1,#0]
+ mov r0,r5,asr #6
+ mov r2,r0,asr #15
+ teq r2,r0,asr #31
+ ldrne r12,LOW_16BITS
+ ldr r2,[sp]
+ mov r1,#0x10
+ eorne r0,r12,r0,asr #31
+ ldr r12,[sp,#8]
+ mov r1,r1,lsl r2
+ add r1,r12,r1,lsl #1
+ strh r0,[r1]
+ add sp,sp,#0x10
+ ldmfd sp!,{r4-r11,pc}
+
+
+PolyPh_filter_coeff
+ DCD pqmfSynthWin
+LOW_16BITS
+ DCD 0x00007fff
+
+ ENDP
+
+
+ END
diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
new file mode 100644
index 0000000..4f45737
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
@@ -0,0 +1,230 @@
+@ ------------------------------------------------------------------
+@ 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: pvmp3_polyphase_filter_window.s
+@
+@------------------------------------------------------------------------------
+@ REVISION HISTORY
+@
+@
+@ Who: Date: MM/DD/YYYY
+@ Description:
+@
+@------------------------------------------------------------------------------
+
+.arm
+
+.align 4
+
+.text
+
+.extern pqmfSynthWin
+
+
+
+@------------------------------------------------------------------------------
+
+.global pvmp3_polyphase_filter_window
+
+pvmp3_polyphase_filter_window:
+ stmfd sp!,{r0-r2,r4-r11,lr}
+
+ sub sp,sp,#4
+ ldr r2,[sp,#0xc]
+ ldr r1,PolyPh_filter_coeff
+
+ sub r2,r2,#1
+ mov r10,#1
+ str r2,[sp]
+
+@ Accumulators r9, r11::> Initialization
+
+Loop_j:
+ mov r9, #0x20
+ mov r11, #0x20
+ mov r4, #0x10
+Loop_i:
+ add r2,r4,r10
+ add r3,r0,r2,lsl #2
+ sub r2,r4,r10
+ ldr r5,[r3]
+ ldr lr,[r1]
+ add r12,r0,r2,lsl #2
+ ldr r6,[r12,#0x780]
+ smlal r2,r9,lr,r5
+ smlal r2,r11,lr,r6
+ ldr r2,[r1,#4]
+ ldr r7,[r12,#0x80]
+ smlal r5,r11,r2,r5
+ smull r6,r5,r2,r6
+ sub r9,r9,r5
+ ldr r5,[r1,#8]
+ ldr r8,[r3,#0x700]
+ add r4,r4,#0x200
+ smlal r6,r9,r5,r7
+ smull r6,r2,r5,r8
+ ldr r5,[r1,#0xc]
+ sub r11,r11,r2
+ smlal r8,r9,r5,r8
+ smlal r7,r11,r5,r7
+ ldr r5,[r3,#0x100]
+ ldr r2,[r1,#0x10]
+ ldr r6,[r12,#0x680]
+ smlal lr,r9,r2,r5
+ smlal lr,r11,r2,r6
+ ldr r2,[r1,#0x14]
+ ldr r7,[r12,#0x180]
+ smlal r5,r11,r2,r5
+ smull r6,r5,r2,r6
+ ldr r6,[r1,#0x18]
+ ldr r8,[r3,#0x600]
+ sub r9,r9,r5
+ smlal r5,r9,r6,r7
+ smull r2,r5,r6,r8
+ ldr r6,[r1,#0x1c]
+ sub r11,r11,r5
+ smlal r8,r9,r6,r8
+ ldr r2,[r1,#0x20]
+ ldr r5,[r3,#0x200]
+ smlal r7,r11,r6,r7
+ ldr r6,[r12,#0x580]
+ smlal lr,r9,r2,r5
+ smlal lr,r11,r2,r6
+ ldr r2,[r1,#0x24]
+ ldr r7,[r12,#0x280]
+ smlal r5,r11,r2,r5
+ smull r6,r5,r2,r6
+ ldr r6,[r1,#0x28]
+ ldr r8,[r3,#0x500]
+ sub r9,r9,r5
+ smlal r5,r9,r6,r7
+ smull r2,r5,r6,r8
+ ldr r6,[r1,#0x2c]
+ sub r11,r11,r5
+
+ smlal r8,r9,r6,r8
+ smlal r7,r11,r6,r7
+ ldr r5,[r3,#0x300]
+ ldr r8,[r1,#0x30]
+ ldr r6,[r12,#0x480]
+ smlal r7,r9,r8,r5
+ smlal r7,r11,r8,r6
+ ldr r8,[r1,#0x34]
+ ldr r12,[r12,#0x380]
+ smlal r5,r11,r8,r5
+ smull r6,r5,r8,r6
+ ldr r6,[r1,#0x38]
+
+
+ ldr r3,[r3,#0x400]
+ sub r9,r9,r5
+ smlal r7,r9,r6,r12
+ smull r8,r7,r6,r3
+ cmp r4,#0x210
+ sub r11,r11,r7
+
+ ldr r2,[r1,#0x3c]
+ add r1,r1,#0x40
+ smlal r3,r9,r2,r3
+ smlal r12,r11,r2,r12
+
+ blt Loop_i
+
+ mov r3,r9, asr #6
+ mov r4,r3, asr #15
+ teq r4,r3, asr #31
+ ldr r12,LOW_16BITS
+ ldr r2,[sp]
+ eorne r3,r12,r3,asr #31
+ ldr r4,[sp,#8]
+ mov r2,r10,lsl r2
+ add r4,r4,r2,lsl #1
+ strh r3,[r4]
+
+ mov r3,r11,asr #6
+ mov r4,r3,asr #15
+ teq r4,r3,asr #31
+ eorne r3,r12,r3,asr #31
+ ldr r12,[sp,#0xc]
+ ldr r11,[sp,#8]
+ rsb r2,r2,r12,lsl #5
+ add r2,r11,r2,lsl #1
+ strh r3,[r2]
+
+ add r10,r10,#1
+ cmp r10,#0x10
+ blt Loop_j
+
+@ Accumulators r4, r5 Initialization
+
+ mov r4,#0x20
+ mov r5,#0x20
+ mov r3,#0x10
+PolyPh_filter_loop2:
+ add r2,r0,r3,lsl #2
+ ldr r12,[r2]
+ ldr r8,[r1]
+ ldr r6,[r2,#0x80]
+ smlal r12,r4,r8,r12
+ ldr r12,[r1,#4]
+ ldr r7,[r2,#0x40]
+ smlal r6,r4,r12,r6
+
+ ldr r12,[r1,#8]
+ ldr r6,[r2,#0x180]
+ smlal r7,r5,r12,r7
+ ldr r12,[r2,#0x100]
+ ldr r7,[r1,#0xc]
+ ldr r2,[r2,#0x140]
+ smlal r12,r4,r7,r12
+ ldr r12,[r1,#0x10]
+ add r3,r3,#0x80
+ smlal r6,r4,r12,r6
+ ldr r6,[r1,#0x14]
+ cmp r3,#0x210
+ smlal r2,r5,r6,r2
+ add r1,r1,#0x18
+
+ blt PolyPh_filter_loop2
+ mov r0,r4,asr #6
+ mov r2,r0,asr #15
+ teq r2,r0,asr #31
+ ldrne r12,LOW_16BITS
+ ldr r1,[sp,#8]
+ eorne r0,r12,r0,asr #31
+ strh r0,[r1,#0]
+ mov r0,r5,asr #6
+ mov r2,r0,asr #15
+ teq r2,r0,asr #31
+ ldrne r12,LOW_16BITS
+ ldr r2,[sp]
+ mov r1,#0x10
+ eorne r0,r12,r0,asr #31
+ ldr r12,[sp,#8]
+ mov r1,r1,lsl r2
+ add r1,r12,r1,lsl #1
+ strh r0,[r1]
+ add sp,sp,#0x10
+ ldmfd sp!,{r4-r11,pc}
+
+PolyPh_filter_coeff:
+ .word pqmfSynthWin
+LOW_16BITS:
+ .word 0x00007fff
+
diff --git a/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_wm.asm b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_wm.asm
new file mode 100644
index 0000000..f957267
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_wm.asm
@@ -0,0 +1,231 @@
+; ------------------------------------------------------------------
+; 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: pvmp3_polyphase_filter_window.s
+;
+;------------------------------------------------------------------------------
+; REVISION HISTORY
+;
+;
+; Who: Date: MM/DD/YYYY
+; Description:
+;
+;------------------------------------------------------------------------------
+
+ CODE32
+
+ AREA |.drectve|, DRECTVE
+
+ EXPORT |pvmp3_polyphase_filter_window|
+ IMPORT |pqmfSynthWin|
+
+ AREA |.pdata|, PDATA
+
+ AREA |.text|, CODE, ARM
+
+|pvmp3_polyphase_filter_window| PROC
+ stmfd sp!,{r0-r2,r4-r11,lr}
+
+ sub sp,sp,#4
+ ldr r2,[sp,#0xc]
+ ldr r1,PolyPh_filter_coeff
+
+ sub r2,r2,#1
+ mov r10,#1
+ str r2,[sp]
+
+; Accumulators r9, r11::> Initialization
+
+Loop_j
+ mov r9, #0x20
+ mov r11, #0x20
+ mov r4, #0x10
+Loop_i
+ add r2,r4,r10
+ add r3,r0,r2,lsl #2
+ sub r2,r4,r10
+ ldr r5,[r3]
+ ldr lr,[r1]
+ add r12,r0,r2,lsl #2
+ ldr r6,[r12,#0x780]
+ smlal r2,r9,lr,r5
+ smlal r2,r11,lr,r6
+ ldr r2,[r1,#4]
+ ldr r7,[r12,#0x80]
+ smlal r5,r11,r2,r5
+ smull r6,r5,r2,r6
+ sub r9,r9,r5
+ ldr r5,[r1,#8]
+ ldr r8,[r3,#0x700]
+ add r4,r4,#0x200
+ smlal r6,r9,r5,r7
+ smull r6,r2,r5,r8
+ ldr r5,[r1,#0xc]
+ sub r11,r11,r2
+ smlal r8,r9,r5,r8
+ smlal r7,r11,r5,r7
+ ldr r5,[r3,#0x100]
+ ldr r2,[r1,#0x10]
+ ldr r6,[r12,#0x680]
+ smlal lr,r9,r2,r5
+ smlal lr,r11,r2,r6
+ ldr r2,[r1,#0x14]
+ ldr r7,[r12,#0x180]
+ smlal r5,r11,r2,r5
+ smull r6,r5,r2,r6
+ ldr r6,[r1,#0x18]
+ ldr r8,[r3,#0x600]
+ sub r9,r9,r5
+ smlal r5,r9,r6,r7
+ smull r2,r5,r6,r8
+ ldr r6,[r1,#0x1c]
+ sub r11,r11,r5
+ smlal r8,r9,r6,r8
+ ldr r2,[r1,#0x20]
+ ldr r5,[r3,#0x200]
+ smlal r7,r11,r6,r7
+ ldr r6,[r12,#0x580]
+ smlal lr,r9,r2,r5
+ smlal lr,r11,r2,r6
+ ldr r2,[r1,#0x24]
+ ldr r7,[r12,#0x280]
+ smlal r5,r11,r2,r5
+ smull r6,r5,r2,r6
+ ldr r6,[r1,#0x28]
+ ldr r8,[r3,#0x500]
+ sub r9,r9,r5
+ smlal r5,r9,r6,r7
+ smull r2,r5,r6,r8
+ ldr r6,[r1,#0x2c]
+ sub r11,r11,r5
+
+ smlal r8,r9,r6,r8
+ smlal r7,r11,r6,r7
+ ldr r5,[r3,#0x300]
+ ldr r8,[r1,#0x30]
+ ldr r6,[r12,#0x480]
+ smlal r7,r9,r8,r5
+ smlal r7,r11,r8,r6
+ ldr r8,[r1,#0x34]
+ ldr r12,[r12,#0x380]
+ smlal r5,r11,r8,r5
+ smull r6,r5,r8,r6
+ ldr r6,[r1,#0x38]
+
+
+ ldr r3,[r3,#0x400]
+ sub r9,r9,r5
+ smlal r7,r9,r6,r12
+ smull r8,r7,r6,r3
+ cmp r4,#0x210
+ sub r11,r11,r7
+
+ ldr r2,[r1,#0x3c]
+ add r1,r1,#0x40
+ smlal r3,r9,r2,r3
+ smlal r12,r11,r2,r12
+
+ blt Loop_i
+
+ mov r3,r9, asr #6
+ mov r4,r3, asr #15
+ teq r4,r3, asr #31
+ ldr r12,LOW_16BITS
+ ldr r2,[sp]
+ eorne r3,r12,r3,asr #31
+ ldr r4,[sp,#8]
+ mov r2,r10,lsl r2
+ add r4,r4,r2,lsl #1
+ strh r3,[r4]
+
+ mov r3,r11,asr #6
+ mov r4,r3,asr #15
+ teq r4,r3,asr #31
+ eorne r3,r12,r3,asr #31
+ ldr r12,[sp,#0xc]
+ ldr r11,[sp,#8]
+ rsb r2,r2,r12,lsl #5
+ add r2,r11,r2,lsl #1
+ strh r3,[r2]
+
+ add r10,r10,#1
+ cmp r10,#0x10
+ blt Loop_j
+
+; Accumulators r4, r5 Initialization
+
+ mov r4,#0x20
+ mov r5,#0x20
+ mov r3,#0x10
+PolyPh_filter_loop2
+ add r2,r0,r3,lsl #2
+ ldr r12,[r2]
+ ldr r8,[r1]
+ ldr r6,[r2,#0x80]
+ smlal r12,r4,r8,r12
+ ldr r12,[r1,#4]
+ ldr r7,[r2,#0x40]
+ smlal r6,r4,r12,r6
+
+ ldr r12,[r1,#8]
+ ldr r6,[r2,#0x180]
+ smlal r7,r5,r12,r7
+ ldr r12,[r2,#0x100]
+ ldr r7,[r1,#0xc]
+ ldr r2,[r2,#0x140]
+ smlal r12,r4,r7,r12
+ ldr r12,[r1,#0x10]
+ add r3,r3,#0x80
+ smlal r6,r4,r12,r6
+ ldr r6,[r1,#0x14]
+ cmp r3,#0x210
+ smlal r2,r5,r6,r2
+ add r1,r1,#0x18
+
+ blt PolyPh_filter_loop2
+ mov r0,r4,asr #6
+ mov r2,r0,asr #15
+ teq r2,r0,asr #31
+ ldrne r12,LOW_16BITS
+ ldr r1,[sp,#8]
+ eorne r0,r12,r0,asr #31
+ strh r0,[r1,#0]
+ mov r0,r5,asr #6
+ mov r2,r0,asr #15
+ teq r2,r0,asr #31
+ ldrne r12,LOW_16BITS
+ ldr r2,[sp]
+ mov r1,#0x10
+ eorne r0,r12,r0,asr #31
+ ldr r12,[sp,#8]
+ mov r1,r1,lsl r2
+ add r1,r12,r1,lsl #1
+ strh r0,[r1]
+ add sp,sp,#0x10
+ ldmfd sp!,{r4-r11,pc}
+
+
+PolyPh_filter_coeff
+ DCD pqmfSynthWin
+LOW_16BITS
+ DCD 0x00007fff
+
+ ENDP ; |pvmp3_polyphase_filter_window|
+ END
+
diff --git a/media/libstagefright/codecs/mp3dec/src/mp3_mem_funcs.h b/media/libstagefright/codecs/mp3dec/src/mp3_mem_funcs.h
new file mode 100644
index 0000000..46e8022
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/mp3_mem_funcs.h
@@ -0,0 +1,81 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: mp3_mem_funcs.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+------------------------------------------------------------------------------
+
+
+----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+
+#ifndef MP3_MEM_FUNCS_H
+#define MP3_MEM_FUNCS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include <string.h>
+
+#include "pvmp3_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES AND SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+#define pv_memset(to, c, n) memset(to, c, n)
+
+
+#define pv_memcpy(to, from, n) memcpy(to, from, n)
+#define pv_memmove(to, from, n) memmove(to, from, n)
+#define pv_memcmp(p, q, n) memcmp(p, q, n)
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+
+#endif
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3_huffman.h b/media/libstagefright/codecs/mp3dec/src/pv_mp3_huffman.h
new file mode 100644
index 0000000..31102ea
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pv_mp3_huffman.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pv_mp3_huffman.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+*/
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+
+#ifndef PV_MP3_HUFFMAN_H
+#define PV_MP3_HUFFMAN_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_audio_type_defs.h"
+#include "s_mp3bits.h"
+#include "s_tmp3dec_file.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES AND SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ int32 pvmp3_huffman_parsing(int32 is[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ granuleInfo *grInfo,
+ tmp3dec_file *pVars,
+ int32 part2_start,
+ mp3Header *info);
+
+
+ void pvmp3_huffman_quad_decoding(struct huffcodetab *h,
+ int32 *is,
+ tmp3Bits *pMainData);
+
+ void pvmp3_huffman_pair_decoding(struct huffcodetab *h,
+ int32 *is,
+ tmp3Bits *pMainData);
+
+
+ void pvmp3_huffman_pair_decoding_linbits(struct huffcodetab *h,
+ int32 *is,
+ tmp3Bits *pMainData);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op.h b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op.h
new file mode 100644
index 0000000..f14e2de
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op.h
@@ -0,0 +1,84 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pv_mp3dec_fxd_op.h
+
+ Date: 09/21/2007
+
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file select the associated fixed point functions with the OS/ARCH.
+
+
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PV_MP3DEC_FXD_OP_H
+#define PV_MP3DEC_FXD_OP_H
+
+#include "pvmp3_audio_type_defs.h"
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#if (defined(PV_ARM_V5)||defined(PV_ARM_V4))
+
+#include "pv_mp3dec_fxd_op_arm.h"
+
+#elif (defined(PV_ARM_GCC_V5)||defined(PV_ARM_GCC_V4))
+
+#include "pv_mp3dec_fxd_op_arm_gcc.h"
+
+#elif (defined(PV_ARM_MSC_EVC_V5)||defined(PV_ARM_MSC_EVC_V4))
+
+#include "pv_mp3dec_fxd_op_msc_evc.h"
+
+#else
+
+#ifndef C_EQUIVALENT
+#define C_EQUIVALENT
+#endif
+
+#include "pv_mp3dec_fxd_op_c_equivalent.h"
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif /* PV_MP3DEC_FXD_OP_H */
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h
new file mode 100644
index 0000000..76a8229
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h
@@ -0,0 +1,203 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Pathname: ./cpp/include/pv_mp3dec_fxd_op_arm.h
+
+ Date: 08/20/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file select the associated fixed point functions with the OS/ARCH.
+
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PV_MP3DEC_FXD_OP_ARM
+#define PV_MP3DEC_FXD_OP_ARM
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "pvmp3_audio_type_defs.h"
+
+
+#if (defined(PV_ARM_V5)||defined(PV_ARM_V4))
+
+
+ __inline Int32 fxp_mul32_Q30(const Int32 L_var1, const Int32 L_var2)
+ {
+
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_lo, result64_lo, lsr #30
+ add result64_hi, result64_lo, result64_hi, asl #2
+ }
+ return (result64_hi);
+ }
+
+ __inline Int32 fxp_mac32_Q30(const Int32 L_var1, const Int32 L_var2, Int32 L_add)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ add L_add, L_add, result64_hi, asl #2
+ add L_add, L_add, result64_lo, lsr #30
+ }
+ return (L_add);
+ }
+
+
+
+#define Qfmt_31(a) (Int32)(a*0x7FFFFFFF + (a>=0?0.5F:-0.5F))
+
+
+
+ __inline Int32 fxp_mul32_Q32(Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ __asm
+ {
+ smull L_var1, result64_hi, L_var2, L_var1
+ }
+ return (result64_hi);
+ }
+
+ __inline Int32 fxp_mul32_Q28(const Int32 L_var1, const Int32 L_var2)
+ {
+
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_lo, result64_lo, lsr #28
+ add result64_hi, result64_lo, result64_hi, asl #4
+ }
+ return (result64_hi);
+ }
+
+
+ __inline Int32 fxp_mul32_Q27(const Int32 L_var1, const Int32 L_var2)
+ {
+
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_lo, result64_lo, lsr #27
+ add result64_hi, result64_lo, result64_hi, asl #5
+ }
+ return (result64_hi);
+ }
+
+
+ __inline Int32 fxp_mul32_Q26(Int32 L_var1, Int32 L_var2)
+ {
+
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_lo, result64_lo, lsr #26
+ add result64_hi, result64_lo, result64_hi, asl #6
+ }
+ return (result64_hi);
+ }
+
+
+
+ __inline Int32 fxp_mac32_Q32(Int32 L_add, Int32 L_var1, const Int32 L_var2)
+ {
+ __asm
+ {
+ smlal L_var1, L_add, L_var2, L_var1
+ }
+ return L_add;
+ }
+
+
+ __inline Int32 fxp_msb32_Q32(Int32 L_sub, Int32 L_var1, Int32 L_var2)
+ {
+
+ __asm
+ {
+ smull L_var2, L_var1, L_var2, L_var1
+ sub L_sub, L_sub, L_var1
+ }
+ return L_sub;
+ }
+
+
+ __inline Int32 fxp_mul32_Q29(const Int32 L_var1, const Int32 L_var2)
+ {
+ Int32 result64_hi;
+ Int32 result64_lo;
+ __asm
+ {
+ smull result64_lo, result64_hi, L_var2, L_var1
+ mov result64_lo, result64_lo, lsr #29
+ add result64_hi, result64_lo, result64_hi, asl #3
+ }
+ return (result64_hi);
+ }
+
+
+ __inline int32 pv_abs(int32 a)
+ {
+ Int32 b;
+ /*
+ b = a - (a<0);
+ a = b ^ sign(b)
+ */
+ __asm
+ {
+ sub b, a, a, lsr #31
+ eor a, b, b, asr #31
+ }
+ return (a);
+ }
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* PV_MP3DEC_FXD_OP_ARM */
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h
new file mode 100644
index 0000000..71fbd20
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h
@@ -0,0 +1,252 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Pathname: ./cpp/include/pv_mp3dec_fxd_op_arm_gcc.h
+
+ Date: 08/20/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file select the associated fixed point functions with the OS/ARCH.
+
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PV_MP3DEC_FXD_OP_ARM_GCC_H
+#define PV_MP3DEC_FXD_OP_ARM_GCC_H
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "pvmp3_audio_type_defs.h"
+
+
+#if (defined(PV_ARM_GCC_V5)||defined(PV_ARM_GCC_V4))
+
+#define Qfmt_31(a) (int32)(a*0x7FFFFFFF + (a>=0?0.5F:-0.5F))
+
+#define Qfmt15(x) (Int16)(x*((int32)1<<15) + (x>=0?0.5F:-0.5F))
+
+ static inline int32 fxp_mul32_Q30(const int32 a, const int32 b)
+ {
+ int32 result64_hi;
+ int32 result64_lo;
+ register int32 ra = (int32)a;
+ register int32 rb = (int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %1, %1, lsr #30\n\t"
+ "add %0, %1, %0, asl #2"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+ return (result64_hi);
+ }
+
+
+ static inline int32 fxp_mac32_Q30(const int32 a, const int32 b, int32 L_add)
+{
+ int32 result64_hi;
+ int32 result64_lo;
+ register int32 ra = (int32)a;
+ register int32 rb = (int32)b;
+ register int32 rc = (int32)L_add;
+
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "add %4, %4, %0, asl #2\n\t"
+ "add %0, %4, %1, lsr #30"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (result64_hi);
+ }
+
+
+
+ static inline int32 fxp_mul32_Q32(const int32 a, const int32 b)
+{
+ int32 result64_hi;
+ int32 result64_lo;
+ register int32 ra = (int32)a;
+ register int32 rb = (int32)b;
+ asm volatile(
+ "smull %1, %0, %2, %3"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+
+ return (result64_hi);
+ }
+
+
+ static inline int32 fxp_mul32_Q29(const int32 a, const int32 b)
+{
+ int32 result64_hi;
+ int32 result64_lo;
+ register int32 ra = (int32)a;
+ register int32 rb = (int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %1, %1, lsr #29\n\t"
+ "add %0, %1, %0, asl #3"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+ return (result64_hi);
+
+ }
+
+ static inline int32 fxp_mul32_Q28(const int32 a, const int32 b)
+{
+
+ int32 result64_hi;
+ int32 result64_lo;
+ register int32 ra = (int32)a;
+ register int32 rb = (int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %1, %1, lsr #28\n\t"
+ "add %0, %1, %0, asl #4"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+ return (result64_hi);
+
+ }
+
+
+ static inline int32 fxp_mul32_Q27(const int32 a, const int32 b)
+{
+ int32 result64_hi;
+ int32 result64_lo;
+ register int32 ra = (int32)a;
+ register int32 rb = (int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %1, %1, lsr #27\n\t"
+ "add %0, %1, %0, asl #5"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+ return (result64_hi);
+
+ }
+
+
+ static inline int32 fxp_mul32_Q26(const int32 a, const int32 b)
+{
+ int32 result64_hi;
+ int32 result64_lo;
+ register int32 ra = (int32)a;
+ register int32 rb = (int32)b;
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "mov %1, %1, lsr #26\n\t"
+ "add %0, %1, %0, asl #6"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb));
+ return (result64_hi);
+
+ }
+
+
+
+ static inline int32 fxp_mac32_Q32(int32 L_add, const int32 a, const int32 b)
+{
+
+ int32 result64_hi;
+ int32 result64_lo;
+ register int32 ra = (int32)a;
+ register int32 rb = (int32)b;
+ register int32 rc = (int32)L_add;
+
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "add %0, %0, %4"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+ return (result64_hi);
+ }
+
+ static inline int32 fxp_msb32_Q32(int32 L_sub, const int32 a, const int32 b)
+{
+ int32 result64_hi;
+ int32 result64_lo;
+ register int32 ra = (int32)a;
+ register int32 rb = (int32)b;
+ register int32 rc = (int32)L_sub;
+
+ asm volatile("smull %1, %0, %2, %3\n\t"
+ "sub %0, %4, %0"
+ : "=&r*i"(result64_hi),
+ "=&r*i"(result64_lo)
+ : "r"(ra),
+ "r"(rb),
+ "r"(rc));
+
+
+ return (result64_hi);
+ }
+
+
+ __inline int32 pv_abs(int32 x)
+{
+ register int32 z;
+ register int32 y;
+ register int32 ra = x;
+ asm volatile(
+ "sub %0, %2, %2, lsr #31\n\t"
+ "eor %1, %0, %0, asr #31"
+ : "=&r*i"(z),
+ "=&r*i"(y)
+ : "r"(ra));
+
+ return (y);
+ }
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* PV_MP3DEC_FXD_OP_ARM_GCC_H */
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
new file mode 100644
index 0000000..ba43820
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
@@ -0,0 +1,123 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Pathname: ./cpp/include/pv_mp3dec_fxd_op_c_equivalent.h
+
+ Date: 12/06/2005
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PV_MP3DEC_FXD_OP_C_EQUIVALENT
+#define PV_MP3DEC_FXD_OP_C_EQUIVALENT
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "pvmp3_audio_type_defs.h"
+#define Qfmt_31(a) (Int32)((float)a*0x7FFFFFFF)
+
+#define Qfmt15(x) (Int16)(x*((Int32)1<<15) + (x>=0?0.5F:-0.5F))
+
+
+
+ __inline int32 pv_abs(int32 a)
+ {
+ int32 b = (a < 0) ? -a : a;
+ return b;
+ }
+
+
+
+
+ __inline Int32 fxp_mul32_Q30(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 30);
+ }
+
+ __inline Int32 fxp_mac32_Q30(const Int32 a, const Int32 b, Int32 L_add)
+ {
+ return (L_add + (Int32)(((int64)(a) * b) >> 30));
+ }
+
+ __inline Int32 fxp_mul32_Q32(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 32);
+ }
+
+
+ __inline Int32 fxp_mul32_Q28(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 28);
+ }
+
+ __inline Int32 fxp_mul32_Q27(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 27);
+ }
+
+ __inline Int32 fxp_mul32_Q26(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 26);
+ }
+
+
+ __inline Int32 fxp_mac32_Q32(Int32 L_add, const Int32 a, const Int32 b)
+ {
+ return (L_add + (Int32)(((int64)(a) * b) >> 32));
+ }
+
+ __inline Int32 fxp_msb32_Q32(Int32 L_sub, const Int32 a, const Int32 b)
+ {
+ return (L_sub - ((Int32)(((int64)(a) * b) >> 32)));
+ }
+
+
+ __inline Int32 fxp_mul32_Q29(const Int32 a, const Int32 b)
+ {
+ return (Int32)(((int64)(a) * b) >> 29);
+ }
+
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* PV_MP3DEC_FXD_OP_C_EQUIVALENT */
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h
new file mode 100644
index 0000000..271e6b7
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h
@@ -0,0 +1,132 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Pathname: ./cpp/include/pv_mp3dec_fxd_op_msc_evc.h
+
+ Date: 08/20/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This file select the associated fixed point functions with the OS/ARCH.
+
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PV_MP3DEC_FXD_OP_MSC_EVC_H
+#define PV_MP3DEC_FXD_OP_MSC_EVC_H
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "pvmp3_audio_type_defs.h"
+
+
+#if (defined(PV_ARM_MSC_EVC_V5)||defined(PV_ARM_MSC_EVC_V4))
+#include "armintr.h"
+#include "cmnintrin.h"
+
+
+ __inline int32 fxp_mul32_Q30(const int32 a, const int32 b)
+ {
+ return (int32)(((int64)(a) * b) >> 30);
+ }
+
+
+ __inline int32 fxp_mac32_Q30(const int32 a, const int32 b, int32 L_add)
+ {
+ return (L_add + (int32)(((int64)(a) * b) >> 30));
+ }
+
+
+#define Qfmt_31(a) (int32)(a*0x7FFFFFFF + (a>=0?0.5F:-0.5F))
+
+#define Qfmt15(x) (Int16)(x*((int32)1<<15) + (x>=0?0.5F:-0.5F))
+
+#define fxp_mul32_Q32( a, b) _MulHigh( b, a)
+
+
+
+ __inline int32 fxp_mul32_Q28(const int32 a, const int32 b)
+ {
+ return (int32)(((int64)(a) * b) >> 28);
+ }
+
+
+ __inline int32 fxp_mul32_Q27(const int32 a, const int32 b)
+ {
+ return (int32)(((int64)(a) * b) >> 27);
+ }
+
+
+
+ __inline int32 fxp_mul32_Q26(const int32 a, const int32 b)
+ {
+ return (int32)(((int64)(a) * b) >> 26);
+ }
+
+
+ __inline int32 fxp_mac32_Q32(int32 L_add, const int32 a, const int32 b)
+ {
+ return (L_add + _MulHigh(b, a));
+ }
+
+
+ __inline int32 fxp_msb32_Q32(int32 L_sub, const int32 a, const int32 b)
+ {
+ return (L_sub - _MulHigh(b, a));
+ }
+
+
+
+ __inline int32 fxp_mul32_Q29(const int32 a, const int32 b)
+ {
+ return (int32)(((int64)(a) * b) >> 29);
+ }
+
+
+
+ __inline int32 pv_abs(int32 a)
+ {
+ int32 b = (a < 0) ? -a : a;
+ return b;
+ }
+
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* PV_MP3DEC_FXD_OP_MSC_EVC_H */
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
new file mode 100644
index 0000000..32c76c6
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
@@ -0,0 +1,261 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_alias_reduction.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+ int32 *input_buffer, Ptr to fequency lines of current channel
+ struct gr_info_s *gr_info, structure with granuke information for the
+ input
+ mp3Header *info mp3 header information
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Alias Reduction
+
+
+
+ Alias reduction before processing by the IMDCT
+
+ Csi +
+ >---------0---------0-------->
+ \ / -
+ Cai \ /
+ \ /
+ \ /
+ \
+ / \
+ Cai / \
+ / \ +
+ >--------0---------0---------->
+ Csi +
+
+ Aliasing Butterfly
+ Alias reduction is not applied to short blocks
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+ 1 ci
+ csi = ---------------- csi = ----------------
+ sqrt( 1 + (ci^2)) sqrt( 1 + (ci^2))
+
+
+ ci = -0.6, -0.535, -0.33, -0.185, -0.095, -0.041, -0.0142, -0.0037
+
+ ------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_alias_reduction.h"
+#include "pv_mp3dec_fxd_op.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define NUM_BUTTERFLIES 8
+
+#define Q31_fmt(a) (int32(double(0x7FFFFFFF)*a))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const int32 c_signal [ NUM_BUTTERFLIES ] =
+{
+
+ Q31_fmt(0.85749292571254f), Q31_fmt(0.88174199731771f),
+ Q31_fmt(0.94962864910273f), Q31_fmt(0.98331459249179f),
+ Q31_fmt(0.99551781606759f), Q31_fmt(0.99916055817815f),
+ Q31_fmt(0.99989919524445f), Q31_fmt(0.99999315507028f)
+
+};
+
+
+const int32 c_alias [ NUM_BUTTERFLIES ] =
+{
+
+ Q31_fmt(-0.51449575542753f), Q31_fmt(-0.47173196856497f),
+ Q31_fmt(-0.31337745420390f), Q31_fmt(-0.18191319961098f),
+ Q31_fmt(-0.09457419252642f), Q31_fmt(-0.04096558288530f),
+ Q31_fmt(-0.01419856857247f), Q31_fmt(-0.00369997467376f)
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_alias_reduction(int32 *input_buffer, /* Ptr to spec values of current channel */
+ granuleInfo *gr_info,
+ int32 *used_freq_lines,
+ mp3Header *info)
+{
+ int32 *ptr1;
+ int32 *ptr2;
+ int32 *ptr3;
+ int32 *ptr4;
+ const int32 *ptr_csi;
+ const int32 *ptr_csa;
+ int32 sblim;
+
+ int32 i, j;
+
+ *used_freq_lines = fxp_mul32_Q32(*used_freq_lines << 16, (int32)(0x7FFFFFFF / (float)18 - 1.0f)) >> 15;
+
+
+ if (gr_info->window_switching_flag && gr_info->block_type == 2)
+ {
+ if (gr_info->mixed_block_flag)
+ {
+ sblim = ((info->version_x == MPEG_2_5) && (info->sampling_frequency == 2)) ? 3 : 1;
+ }
+ else
+ {
+ return; /* illegal parameter */
+ }
+ }
+ else
+ {
+ sblim = *used_freq_lines + 1;
+
+ if (sblim > SUBBANDS_NUMBER - 1)
+ {
+ sblim = SUBBANDS_NUMBER - 1; /* default */
+ }
+
+ }
+
+
+ ptr3 = &input_buffer[17];
+ ptr4 = &input_buffer[18];
+ ptr_csi = c_signal;
+ ptr_csa = c_alias;
+
+ /* NUM_BUTTERFLIES (=8) butterflies between each pair of sub-bands*/
+
+ for (i = NUM_BUTTERFLIES >> 1; i != 0; i--)
+ {
+ int32 csi1 = *ptr_csi++;
+ int32 csi2 = *ptr_csi++;
+ int32 csa1 = *ptr_csa++;
+ int32 csa2 = *ptr_csa++;
+
+ ptr1 = ptr3;
+ ptr3 -= 2;
+ ptr2 = ptr4;
+ ptr4 += 2;
+
+ /*
+ * "sblim" alias-reduction operations between each
+ * pair of sub-bands
+ */
+
+ for (j = sblim >> 1; j != 0; j--)
+ {
+ int32 y = *ptr2;
+ int32 x = *ptr1 << 1;
+ *ptr1-- = fxp_msb32_Q32(fxp_mul32_Q32(x, csi1), y << 1, csa1);
+ *ptr2++ = fxp_mac32_Q32(fxp_mul32_Q32(y << 1, csi1), x, csa1);
+ y = *ptr2;
+ x = *ptr1 << 1;
+ *ptr1 = fxp_msb32_Q32(fxp_mul32_Q32(x, csi2), y << 1, csa2);
+ *ptr2 = fxp_mac32_Q32(fxp_mul32_Q32(y << 1, csi2), x, csa2);
+ ptr1 += 19;
+ ptr2 += 17;
+ y = *ptr2;
+ x = *ptr1 << 1;
+ *ptr1-- = fxp_msb32_Q32(fxp_mul32_Q32(x, csi1), y << 1, csa1);
+ *ptr2++ = fxp_mac32_Q32(fxp_mul32_Q32(y << 1, csi1), x, csa1);
+ y = *ptr2;
+ x = *ptr1 << 1;
+ *ptr1 = fxp_msb32_Q32(fxp_mul32_Q32(x, csi2), y << 1, csa2);
+ *ptr2 = fxp_mac32_Q32(fxp_mul32_Q32(y << 1, csi2), x, csa2);
+ ptr1 += 19;
+ ptr2 += 17;
+
+ }
+
+ if (sblim & 1)
+ {
+ int32 x = *ptr1 << 1;
+ int32 y = *ptr2;
+ *ptr1-- = fxp_msb32_Q32(fxp_mul32_Q32(x, csi1), y << 1, csa1);
+ *ptr2++ = fxp_mac32_Q32(fxp_mul32_Q32(y << 1, csi1), x, csa1);
+
+ x = *ptr1 << 1;
+ y = *ptr2;
+ *ptr1 = fxp_msb32_Q32(fxp_mul32_Q32(x, csi2), y << 1, csa2);
+ *ptr2 = fxp_mac32_Q32(fxp_mul32_Q32(y << 1, csi2), x, csa2);
+ }
+ }
+
+}
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.h
new file mode 100644
index 0000000..2292d5f
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_alias_reduction.h
@@ -0,0 +1,100 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_alias_reduction.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_ALIAS_REDUCTION_H
+#define PVMP3_ALIAS_REDUCTION_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void pvmp3_alias_reduction(int32 *input_buffer,
+ granuleInfo *gr_info,
+ int32 *used_freq_lines,
+ mp3Header *info);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_crc.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_crc.cpp
new file mode 100644
index 0000000..20d0d82
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_crc.cpp
@@ -0,0 +1,161 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_crc.cpp
+
+ Functions:
+ getbits_crc
+ calculate_crc
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+getbits_crc
+
+Input
+ tbits *inputStream, bit stream structure
+ int32 neededBits, number of bits to read from the bit stream
+ uint32 *crc, memory location holding calculated crc value
+ uint32 crc_enabled flag to enable/disable crc checking
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+calculate_crc
+
+Input
+ uint32 data, data vector
+ uint32 length, number of element upon the crc will be calculated
+ uint32 *crc, memory location holding calculated crc value
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+ ------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_getbits.h"
+#include "pvmp3_crc.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+uint32 getbits_crc(tmp3Bits *inputStream, /* bit stream structure */
+ int32 neededBits, /* number of bits to read from the bit stream */
+ uint32 *crc,
+ uint32 crc_enabled)
+{
+ uint32 bits = getNbits(inputStream, neededBits);
+
+ if (crc_enabled)
+ {
+ calculate_crc(bits, neededBits, crc);
+ }
+ return(bits);
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void calculate_crc(uint32 data,
+ uint32 length,
+ uint32 *crc)
+{
+ uint32 carry;
+ uint32 masking = 1 << length;
+
+ while ((masking >>= 1))
+ {
+ carry = *crc & 0x8000;
+ *crc <<= 1;
+ if (!carry ^ !(data & masking))
+ {
+ *crc ^= CRC16_POLYNOMIAL;
+ }
+ }
+ *crc &= 0xffff;
+}
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_crc.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_crc.h
new file mode 100644
index 0000000..b7c277a
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_crc.h
@@ -0,0 +1,110 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_crc.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_CRC_H
+#define PVMP3_CRC_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_audio_type_defs.h"
+#include "s_mp3bits.h"
+#include "pvmp3decoder_api.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define CRC16_POLYNOMIAL 0x8005
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ uint32 getbits_crc(tmp3Bits *inputStream,
+ int32 neededBits,
+ uint32 *crc,
+ uint32 crc_enabled);
+
+
+ void calculate_crc(uint32 data,
+ uint32 length,
+ uint32 *crc);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_16.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_16.cpp
new file mode 100644
index 0000000..a71efc4
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_16.cpp
@@ -0,0 +1,410 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_dct_16.cpp
+
+ Functions:
+ dct_16
+ pv_merge_in_place_N32
+ pv_split
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ dct_16
+
+Input
+ int32 vec[], input vector length 16
+ Int flag processing direction: forward (1), backward ( 0)
+ Returns
+
+ int32 vec[], dct length 16
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ pv_merge_in_place_N32
+
+Input
+ int32 vec[], input vector length 16
+
+ Returns
+
+ int32 vec[], merged output of two dct 16 to create a dct 32
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ pv_split
+
+Input
+ int32 vec[], input vector length 16
+
+ Returns
+
+ int32 vec[], splitted even/odd and pre processing rotation
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ dct 16 and tools to assemble a dct32 output
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+#if ( !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4) )
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_dct_16.h"
+#include "pv_mp3dec_fxd_op.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define Qfmt(a) (int32)(a*((int32)1<<27))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const int32 CosTable_dct32[16] =
+{
+ Qfmt_31(0.50060299823520F) , Qfmt_31(0.50547095989754F) ,
+ Qfmt_31(0.51544730992262F) , Qfmt_31(0.53104259108978F) ,
+ Qfmt_31(0.55310389603444F) , Qfmt_31(0.58293496820613F) ,
+ Qfmt_31(0.62250412303566F) , Qfmt_31(0.67480834145501F) ,
+ Qfmt_31(0.74453627100230F) , Qfmt_31(0.83934964541553F) ,
+
+ Qfmt(0.97256823786196F) , Qfmt(1.16943993343288F) ,
+ Qfmt(1.48416461631417F) , Qfmt(2.05778100995341F) ,
+ Qfmt(3.40760841846872F) , Qfmt(10.19000812354803F)
+};
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_dct_16(int32 vec[], int32 flag)
+{
+ int32 tmp0;
+ int32 tmp1;
+ int32 tmp2;
+ int32 tmp3;
+ int32 tmp4;
+ int32 tmp5;
+ int32 tmp6;
+ int32 tmp7;
+ int32 tmp_o0;
+ int32 tmp_o1;
+ int32 tmp_o2;
+ int32 tmp_o3;
+ int32 tmp_o4;
+ int32 tmp_o5;
+ int32 tmp_o6;
+ int32 tmp_o7;
+ int32 itmp_e0;
+ int32 itmp_e1;
+ int32 itmp_e2;
+
+ /* split input vector */
+
+ tmp_o0 = fxp_mul32_Q32((vec[ 0] - vec[15]), Qfmt_31(0.50241928618816F));
+ tmp0 = vec[ 0] + vec[15];
+
+ tmp_o7 = fxp_mul32_Q32((vec[ 7] - vec[ 8]) << 3, Qfmt_31(0.63764357733614F));
+ tmp7 = vec[ 7] + vec[ 8];
+
+ itmp_e0 = fxp_mul32_Q32((tmp0 - tmp7), Qfmt_31(0.50979557910416F));
+ tmp7 = (tmp0 + tmp7);
+
+ tmp_o1 = fxp_mul32_Q32((vec[ 1] - vec[14]), Qfmt_31(0.52249861493969F));
+ tmp1 = vec[ 1] + vec[14];
+
+ tmp_o6 = fxp_mul32_Q32((vec[ 6] - vec[ 9]) << 1, Qfmt_31(0.86122354911916F));
+ tmp6 = vec[ 6] + vec[ 9];
+
+
+
+ itmp_e1 = (tmp1 + tmp6);
+ tmp6 = fxp_mul32_Q32((tmp1 - tmp6), Qfmt_31(0.60134488693505F));
+
+
+
+ tmp_o2 = fxp_mul32_Q32((vec[ 2] - vec[13]), Qfmt_31(0.56694403481636F));
+ tmp2 = vec[ 2] + vec[13];
+ tmp_o5 = fxp_mul32_Q32((vec[ 5] - vec[10]) << 1, Qfmt_31(0.53033884299517F));
+ tmp5 = vec[ 5] + vec[10];
+
+ itmp_e2 = (tmp2 + tmp5);
+ tmp5 = fxp_mul32_Q32((tmp2 - tmp5), Qfmt_31(0.89997622313642F));
+
+ tmp_o3 = fxp_mul32_Q32((vec[ 3] - vec[12]), Qfmt_31(0.64682178335999F));
+ tmp3 = vec[ 3] + vec[12];
+ tmp_o4 = fxp_mul32_Q32((vec[ 4] - vec[11]), Qfmt_31(0.78815462345125F));
+ tmp4 = vec[ 4] + vec[11];
+
+ tmp1 = (tmp3 + tmp4);
+ tmp4 = fxp_mul32_Q32((tmp3 - tmp4) << 2, Qfmt_31(0.64072886193538F));
+
+ /* split even part of tmp_e */
+
+ tmp0 = (tmp7 + tmp1);
+ tmp1 = fxp_mul32_Q32((tmp7 - tmp1), Qfmt_31(0.54119610014620F));
+
+ tmp3 = fxp_mul32_Q32((itmp_e1 - itmp_e2) << 1, Qfmt_31(0.65328148243819F));
+ tmp7 = (itmp_e1 + itmp_e2);
+
+ vec[ 0] = (tmp0 + tmp7) >> 1;
+ vec[ 8] = fxp_mul32_Q32((tmp0 - tmp7), Qfmt_31(0.70710678118655F));
+ tmp0 = fxp_mul32_Q32((tmp1 - tmp3) << 1, Qfmt_31(0.70710678118655F));
+ vec[ 4] = tmp1 + tmp3 + tmp0;
+ vec[12] = tmp0;
+
+ /* split odd part of tmp_e */
+
+ tmp1 = fxp_mul32_Q32((itmp_e0 - tmp4) << 1, Qfmt_31(0.54119610014620F));
+ tmp7 = itmp_e0 + tmp4;
+
+ tmp3 = fxp_mul32_Q32((tmp6 - tmp5) << 2, Qfmt_31(0.65328148243819F));
+ tmp6 += tmp5;
+
+ tmp4 = fxp_mul32_Q32((tmp7 - tmp6) << 1, Qfmt_31(0.70710678118655F));
+ tmp6 += tmp7;
+ tmp7 = fxp_mul32_Q32((tmp1 - tmp3) << 1, Qfmt_31(0.70710678118655F));
+
+ tmp1 += tmp3 + tmp7;
+ vec[ 2] = tmp1 + tmp6;
+ vec[ 6] = tmp1 + tmp4;
+ vec[10] = tmp7 + tmp4;
+ vec[14] = tmp7;
+
+
+ // dct8;
+
+ tmp1 = fxp_mul32_Q32((tmp_o0 - tmp_o7) << 1, Qfmt_31(0.50979557910416F));
+ tmp7 = tmp_o0 + tmp_o7;
+
+ tmp6 = tmp_o1 + tmp_o6;
+ tmp_o1 = fxp_mul32_Q32((tmp_o1 - tmp_o6) << 1, Qfmt_31(0.60134488693505F));
+
+ tmp5 = tmp_o2 + tmp_o5;
+ tmp_o5 = fxp_mul32_Q32((tmp_o2 - tmp_o5) << 1, Qfmt_31(0.89997622313642F));
+
+ tmp0 = fxp_mul32_Q32((tmp_o3 - tmp_o4) << 3, Qfmt_31(0.6407288619354F));
+ tmp4 = tmp_o3 + tmp_o4;
+
+ if (!flag)
+ {
+ tmp7 = -tmp7;
+ tmp1 = -tmp1;
+ tmp6 = -tmp6;
+ tmp_o1 = -tmp_o1;
+ tmp5 = -tmp5;
+ tmp_o5 = -tmp_o5;
+ tmp4 = -tmp4;
+ tmp0 = -tmp0;
+ }
+
+
+ tmp2 = fxp_mul32_Q32((tmp1 - tmp0) << 1, Qfmt_31(0.54119610014620F));
+ tmp0 += tmp1;
+ tmp1 = fxp_mul32_Q32((tmp7 - tmp4) << 1, Qfmt_31(0.54119610014620F));
+ tmp7 += tmp4;
+ tmp4 = fxp_mul32_Q32((tmp6 - tmp5) << 2, Qfmt_31(0.65328148243819F));
+ tmp6 += tmp5;
+ tmp5 = fxp_mul32_Q32((tmp_o1 - tmp_o5) << 2, Qfmt_31(0.65328148243819F));
+ tmp_o1 += tmp_o5;
+
+
+ vec[13] = fxp_mul32_Q32((tmp1 - tmp4) << 1, Qfmt_31(0.70710678118655F));
+ vec[ 5] = tmp1 + tmp4 + vec[13];
+
+ vec[ 9] = fxp_mul32_Q32((tmp7 - tmp6) << 1, Qfmt_31(0.70710678118655F));
+ vec[ 1] = tmp7 + tmp6;
+
+ tmp4 = fxp_mul32_Q32((tmp0 - tmp_o1) << 1, Qfmt_31(0.70710678118655F));
+ tmp0 += tmp_o1;
+ tmp6 = fxp_mul32_Q32((tmp2 - tmp5) << 1, Qfmt_31(0.70710678118655F));
+ tmp2 += tmp5 + tmp6;
+ tmp0 += tmp2;
+
+ vec[ 1] += tmp0;
+ vec[ 3] = tmp0 + vec[ 5];
+ tmp2 += tmp4;
+ vec[ 5] = tmp2 + vec[ 5];
+ vec[ 7] = tmp2 + vec[ 9];
+ tmp4 += tmp6;
+ vec[ 9] = tmp4 + vec[ 9];
+ vec[11] = tmp4 + vec[13];
+ vec[13] = tmp6 + vec[13];
+ vec[15] = tmp6;
+
+}
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void pvmp3_merge_in_place_N32(int32 vec[])
+{
+
+
+ int32 temp0;
+ int32 temp1;
+ int32 temp2;
+ int32 temp3;
+
+ temp0 = vec[14];
+ vec[14] = vec[ 7];
+ temp1 = vec[12];
+ vec[12] = vec[ 6];
+ temp2 = vec[10];
+ vec[10] = vec[ 5];
+ temp3 = vec[ 8];
+ vec[ 8] = vec[ 4];
+ vec[ 6] = vec[ 3];
+ vec[ 4] = vec[ 2];
+ vec[ 2] = vec[ 1];
+
+ vec[ 1] = (vec[16] + vec[17]);
+ vec[16] = temp3;
+ vec[ 3] = (vec[18] + vec[17]);
+ vec[ 5] = (vec[19] + vec[18]);
+ vec[18] = vec[9];
+
+ vec[ 7] = (vec[20] + vec[19]);
+ vec[ 9] = (vec[21] + vec[20]);
+ vec[20] = temp2;
+ temp2 = vec[13];
+ temp3 = vec[11];
+ vec[11] = (vec[22] + vec[21]);
+ vec[13] = (vec[23] + vec[22]);
+ vec[22] = temp3;
+ temp3 = vec[15];
+
+ vec[15] = (vec[24] + vec[23]);
+ vec[17] = (vec[25] + vec[24]);
+ vec[19] = (vec[26] + vec[25]);
+ vec[21] = (vec[27] + vec[26]);
+ vec[23] = (vec[28] + vec[27]);
+ vec[24] = temp1;
+ vec[25] = (vec[29] + vec[28]);
+ vec[26] = temp2;
+ vec[27] = (vec[30] + vec[29]);
+ vec[28] = temp0;
+ vec[29] = (vec[30] + vec[31]);
+ vec[30] = temp3;
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+void pvmp3_split(int32 *vect)
+{
+
+ int32 i;
+ const int32 *pt_cosTerms = &CosTable_dct32[15];
+ int32 *pt_vect = vect;
+ int32 *pt_vect_2 = pt_vect - 1;
+
+ for (i = 3; i != 0; i--)
+ {
+ int32 tmp2 = *(pt_vect);
+ int32 tmp1 = *(pt_vect_2);
+ int32 cosx = *(pt_cosTerms--);
+ *(pt_vect_2--) = (tmp1 + tmp2);
+ *(pt_vect++) = fxp_mul32_Q27((tmp1 - tmp2), cosx);
+
+ tmp2 = *(pt_vect);
+ tmp1 = *(pt_vect_2);
+ cosx = *(pt_cosTerms--);
+ *(pt_vect_2--) = (tmp1 + tmp2);
+ *(pt_vect++) = fxp_mul32_Q27((tmp1 - tmp2), cosx);
+
+ }
+
+ for (i = 5; i != 0; i--)
+ {
+ int32 tmp2 = *(pt_vect);
+ int32 tmp1 = *(pt_vect_2);
+ int32 cosx = *(pt_cosTerms--);
+ *(pt_vect_2--) = (tmp1 + tmp2);
+ *(pt_vect++) = fxp_mul32_Q32((tmp1 - tmp2) << 1, cosx);
+
+ tmp2 = *(pt_vect);
+ tmp1 = *(pt_vect_2);
+ cosx = *(pt_cosTerms--);
+ *(pt_vect_2--) = (tmp1 + tmp2);
+ *(pt_vect++) = fxp_mul32_Q32((tmp1 - tmp2) << 1, cosx);
+ }
+
+}
+
+#endif
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_16.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_16.h
new file mode 100644
index 0000000..e8bf76e
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_16.h
@@ -0,0 +1,102 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_dct_16.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_DCT_16_H
+#define PVMP3_DCT_16_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void pvmp3_dct_16(int32 vec[], int32 flag);
+
+ void pvmp3_merge_in_place_N32(int32 vec[]);
+
+ void pvmp3_split(int32 *vect);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_6.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_6.cpp
new file mode 100644
index 0000000..4c5fb03
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_6.cpp
@@ -0,0 +1,152 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_dct6.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+ Int32 vec[] vector of 6 32-bit integers
+Returns
+ Int32 vec[] dct computation in-place
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Returns the dct of length 6 of the input vector
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_audio_type_defs.h"
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_mdct_6.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define Qfmt30(a) (Int32)(a*((Int32)1<<30) + (a>=0?0.5F:-0.5F))
+
+#define cos_pi_6 Qfmt30( 0.86602540378444f)
+#define cos_2_pi_6 Qfmt30( 0.5f)
+#define cos_7_pi_12 Qfmt30( -0.25881904510252f)
+#define cos_3_pi_12 Qfmt30( 0.70710678118655f)
+#define cos_11_pi_12 Qfmt30( -0.96592582628907f)
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_dct_6(int32 vec[])
+{
+
+ Int32 tmp0;
+ Int32 tmp1;
+ Int32 tmp2;
+ Int32 tmp3;
+ Int32 tmp4;
+ Int32 tmp5;
+
+
+ /* split input vector */
+
+ tmp0 = vec[5] + vec[0];
+ tmp5 = vec[5] - vec[0];
+ tmp1 = vec[4] + vec[1];
+ tmp4 = vec[4] - vec[1];
+ tmp2 = vec[3] + vec[2];
+ tmp3 = vec[3] - vec[2];
+
+ vec[0] = tmp0 + tmp2 ;
+ vec[2] = fxp_mul32_Q30(tmp0 - tmp2, cos_pi_6);
+ vec[4] = (vec[0] >> 1) - tmp1;
+ vec[0] += tmp1;
+
+ tmp0 = fxp_mul32_Q30(tmp3, cos_7_pi_12);
+ tmp0 = fxp_mac32_Q30(tmp4, -cos_3_pi_12, tmp0);
+ vec[1] = fxp_mac32_Q30(tmp5, cos_11_pi_12, tmp0);
+
+ vec[3] = fxp_mul32_Q30((tmp3 + tmp4 - tmp5), cos_3_pi_12);
+ tmp0 = fxp_mul32_Q30(tmp3, cos_11_pi_12);
+ tmp0 = fxp_mac32_Q30(tmp4, cos_3_pi_12, tmp0);
+ vec[5] = fxp_mac32_Q30(tmp5, cos_7_pi_12, tmp0);
+
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp
new file mode 100644
index 0000000..ce3ec64
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_dct_9.cpp
@@ -0,0 +1,167 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_dct_9.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+ int32 vec[] vector of 9 32-bit integers
+Returns
+ int32 vec[] dct computation in-place
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Returns the dct of length 9 of the input vector
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+#if ( !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4) && !defined(PV_ARM_V5) && !defined(PV_ARM_V4) )
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_audio_type_defs.h"
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_mdct_18.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define Qfmt31(a) (int32)(a*(0x7FFFFFFF))
+
+#define cos_pi_9 Qfmt31( 0.93969262078591f)
+#define cos_2pi_9 Qfmt31( 0.76604444311898f)
+#define cos_4pi_9 Qfmt31( 0.17364817766693f)
+#define cos_5pi_9 Qfmt31(-0.17364817766693f)
+#define cos_7pi_9 Qfmt31(-0.76604444311898f)
+#define cos_8pi_9 Qfmt31(-0.93969262078591f)
+#define cos_pi_6 Qfmt31( 0.86602540378444f)
+#define cos_5pi_6 Qfmt31(-0.86602540378444f)
+#define cos_5pi_18 Qfmt31( 0.64278760968654f)
+#define cos_7pi_18 Qfmt31( 0.34202014332567f)
+#define cos_11pi_18 Qfmt31(-0.34202014332567f)
+#define cos_13pi_18 Qfmt31(-0.64278760968654f)
+#define cos_17pi_18 Qfmt31(-0.98480775301221f)
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_dct_9(int32 vec[])
+{
+
+ /* split input vector */
+
+ int32 tmp0 = vec[8] + vec[0];
+ int32 tmp8 = vec[8] - vec[0];
+ int32 tmp1 = vec[7] + vec[1];
+ int32 tmp7 = vec[7] - vec[1];
+ int32 tmp2 = vec[6] + vec[2];
+ int32 tmp6 = vec[6] - vec[2];
+ int32 tmp3 = vec[5] + vec[3];
+ int32 tmp5 = vec[5] - vec[3];
+
+ vec[0] = (tmp0 + tmp2 + tmp3) + (tmp1 + vec[4]);
+ vec[6] = ((tmp0 + tmp2 + tmp3) >> 1) - (tmp1 + vec[4]);
+ vec[2] = (tmp1 >> 1) - vec[4];
+ vec[4] = -vec[2];
+ vec[8] = -vec[2];
+ vec[4] = fxp_mac32_Q32(vec[4], tmp0 << 1, cos_2pi_9);
+ vec[8] = fxp_mac32_Q32(vec[8], tmp0 << 1, cos_4pi_9);
+ vec[2] = fxp_mac32_Q32(vec[2], tmp0 << 1, cos_pi_9);
+ vec[2] = fxp_mac32_Q32(vec[2], tmp2 << 1, cos_5pi_9);
+ vec[4] = fxp_mac32_Q32(vec[4], tmp2 << 1, cos_8pi_9);
+ vec[8] = fxp_mac32_Q32(vec[8], tmp2 << 1, cos_2pi_9);
+ vec[8] = fxp_mac32_Q32(vec[8], tmp3 << 1, cos_8pi_9);
+ vec[4] = fxp_mac32_Q32(vec[4], tmp3 << 1, cos_4pi_9);
+ vec[2] = fxp_mac32_Q32(vec[2], tmp3 << 1, cos_7pi_9);
+
+ vec[1] = fxp_mul32_Q32(tmp5 << 1, cos_11pi_18);
+ vec[1] = fxp_mac32_Q32(vec[1], tmp6 << 1, cos_13pi_18);
+ vec[1] = fxp_mac32_Q32(vec[1], tmp7 << 1, cos_5pi_6);
+ vec[1] = fxp_mac32_Q32(vec[1], tmp8 << 1, cos_17pi_18);
+ vec[3] = fxp_mul32_Q32((tmp5 + tmp6 - tmp8) << 1, cos_pi_6);
+ vec[5] = fxp_mul32_Q32(tmp5 << 1, cos_17pi_18);
+ vec[5] = fxp_mac32_Q32(vec[5], tmp6 << 1, cos_7pi_18);
+ vec[5] = fxp_mac32_Q32(vec[5], tmp7 << 1, cos_pi_6);
+ vec[5] = fxp_mac32_Q32(vec[5], tmp8 << 1, cos_13pi_18);
+ vec[7] = fxp_mul32_Q32(tmp5 << 1, cos_5pi_18);
+ vec[7] = fxp_mac32_Q32(vec[7], tmp6 << 1, cos_17pi_18);
+ vec[7] = fxp_mac32_Q32(vec[7], tmp7 << 1, cos_pi_6);
+ vec[7] = fxp_mac32_Q32(vec[7], tmp8 << 1, cos_11pi_18);
+
+}
+
+
+
+#endif // If not assembly
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dec_defs.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_dec_defs.h
new file mode 100644
index 0000000..6cf8e3e
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_dec_defs.h
@@ -0,0 +1,199 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_dec_defs.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file has the mp3 decoder common defines.
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_DEC_DEFS_H
+#define PVMP3_DEC_DEFS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_audio_type_defs.h"
+#include "pvmp3decoder_api.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+#define module(x, POW2) ((x)&(POW2-1))
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define BUFSIZE 8192 // big enough to hold 4608 bytes == biggest mp3 frame
+
+#define CHAN 2
+#define GRAN 2
+
+
+#define SUBBANDS_NUMBER 32
+#define FILTERBANK_BANDS 18
+#define HAN_SIZE 512
+
+
+/* MPEG Header Definitions - ID Bit Values */
+
+#define MPEG_1 0
+#define MPEG_2 1
+#define MPEG_2_5 2
+#define INVALID_VERSION -1
+
+/* MPEG Header Definitions - Mode Values */
+
+#define MPG_MD_STEREO 0
+#define MPG_MD_JOINT_STEREO 1
+#define MPG_MD_DUAL_CHANNEL 2
+#define MPG_MD_MONO 3
+
+
+
+#define LEFT 0
+#define RIGHT 1
+
+
+#define SYNC_WORD (int32)0x7ff
+#define SYNC_WORD_LNGTH 11
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /*----------------------------------------------------------------------------
+ ; STRUCTURES TYPEDEF'S
+ ----------------------------------------------------------------------------*/
+
+ /* Header Information Structure */
+
+ typedef struct
+ {
+ int32 version_x;
+ int32 layer_description;
+ int32 error_protection;
+ int32 bitrate_index;
+ int32 sampling_frequency;
+ int32 padding;
+ int32 extension;
+ int32 mode;
+ int32 mode_ext;
+ int32 copyright;
+ int32 original;
+ int32 emphasis;
+ } mp3Header;
+
+
+ /* Layer III side information. */
+
+ typedef struct
+ {
+ uint32 part2_3_length;
+ uint32 big_values;
+ int32 global_gain;
+ uint32 scalefac_compress;
+ uint32 window_switching_flag;
+ uint32 block_type;
+ uint32 mixed_block_flag;
+ uint32 table_select[3];
+ uint32 subblock_gain[3];
+ uint32 region0_count;
+ uint32 region1_count;
+ uint32 preflag;
+ uint32 scalefac_scale;
+ uint32 count1table_select;
+
+ } granuleInfo;
+
+ typedef struct
+ {
+ uint32 scfsi[4];
+ granuleInfo gran[2];
+
+ } channelInfo;
+
+ /* Layer III side info. */
+
+ typedef struct
+ {
+ uint32 main_data_begin;
+ uint32 private_bits;
+ channelInfo ch[2];
+
+ } mp3SideInfo;
+
+ /* Layer III scale factors. */
+ typedef struct
+ {
+ int32 l[23]; /* [cb] */
+ int32 s[3][13]; /* [window][cb] */
+
+ } mp3ScaleFactors;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp
new file mode 100644
index 0000000..d443b7c
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp
@@ -0,0 +1,194 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_decode_header.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+ tbits *inputStream, bit stream
+ mp3Header *info,
+ uint32 *crc
+ Returns
+
+ mp3Header *info, structure holding the parsed mp3 header info
+ uint32 *crc initialized crc computation
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ gets mp3 header information
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_decode_header.h"
+#include "pvmp3_crc.h"
+#include "pvmp3_getbits.h"
+#include "pvmp3_seek_synch.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+ERROR_CODE pvmp3_decode_header(tmp3Bits *inputStream,
+ mp3Header *info,
+ uint32 *crc)
+{
+
+ ERROR_CODE err = NO_DECODING_ERROR;
+ uint32 temp;
+
+ /*
+ * Verify that at least the header is complete
+ * Note that SYNC_WORD_LNGTH is in unit of bits, but inputBufferCurrentLength
+ * is in unit of bytes.
+ */
+ if (inputStream->inputBufferCurrentLength < ((SYNC_WORD_LNGTH + 21) >> 3))
+ {
+ return NO_ENOUGH_MAIN_DATA_ERROR;
+ }
+
+ /*
+ * MPEG Audio Version ID
+ */
+ temp = getUpTo17bits(inputStream, SYNC_WORD_LNGTH);
+ if ((temp & SYNC_WORD) != SYNC_WORD)
+ {
+ err = pvmp3_header_sync(inputStream);
+
+ if (err != NO_DECODING_ERROR)
+ {
+ return err;
+ }
+ }
+
+ temp = getNbits(inputStream, 21); // to avoid multiple bitstream accesses
+
+
+ switch (temp >> 19) /* 2 */
+ {
+ case 0:
+ info->version_x = MPEG_2_5;
+ break;
+ case 2:
+ info->version_x = MPEG_2;
+ break;
+ case 3:
+ info->version_x = MPEG_1;
+ break;
+ default:
+ info->version_x = INVALID_VERSION;
+ err = UNSUPPORTED_LAYER;
+ break;
+ }
+
+ info->layer_description = 4 - ((temp << 13) >> 30); /* 2 */
+ info->error_protection = !((temp << 15) >> 31); /* 1 */
+
+ if (info->error_protection)
+ {
+ *crc = 0xffff; /* CRC start value */
+ calculate_crc((temp << 16) >> 16, 16, crc);
+ }
+
+ info->bitrate_index = (temp << 16) >> 28; /* 4 */
+ info->sampling_frequency = (temp << 20) >> 30; /* 2 */
+ info->padding = (temp << 22) >> 31; /* 1 */
+ info->extension = (temp << 23) >> 31; /* 1 */
+ info->mode = (temp << 24) >> 30; /* 2 */
+ info->mode_ext = (temp << 26) >> 30; /* 2 */
+ info->copyright = (temp << 27) >> 31; /* 1 */
+ info->original = (temp << 28) >> 31; /* 1 */
+ info->emphasis = (temp << 30) >> 30; /* 2 */
+
+
+ if (!info->bitrate_index || info->sampling_frequency == 3)
+ {
+ err = UNSUPPORTED_FREE_BITRATE;
+ }
+
+ return(err);
+}
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.h
new file mode 100644
index 0000000..2c2e89e
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.h
@@ -0,0 +1,101 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_decode_header.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_DECODE_HEADER_H
+#define PVMP3_DECODE_HEADER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_audio_type_defs.h"
+#include "pvmp3_dec_defs.h"
+#include "s_mp3bits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ ERROR_CODE pvmp3_decode_header(tmp3Bits *inputStream,
+ mp3Header *info,
+ uint32 *crc);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp
new file mode 100644
index 0000000..6e45a18
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp
@@ -0,0 +1,758 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_decode_huff_cw.cpp
+
+ Funtions:
+ pvmp3_decode_huff_cw_tab0
+ pvmp3_decode_huff_cw_tab1
+ pvmp3_decode_huff_cw_tab2
+ pvmp3_decode_huff_cw_tab3
+ pvmp3_decode_huff_cw_tab5
+ pvmp3_decode_huff_cw_tab6
+ pvmp3_decode_huff_cw_tab7
+ pvmp3_decode_huff_cw_tab8
+ pvmp3_decode_huff_cw_tab9
+ pvmp3_decode_huff_cw_tab10
+ pvmp3_decode_huff_cw_tab11
+ pvmp3_decode_huff_cw_tab12
+ pvmp3_decode_huff_cw_tab13
+ pvmp3_decode_huff_cw_tab15
+ pvmp3_decode_huff_cw_tab16
+ pvmp3_decode_huff_cw_tab24
+ pvmp3_decode_huff_cw_tab32
+ pvmp3_decode_huff_cw_tab33
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ BITS *pMainData = pointer to input mp3 Main data bit stream
+
+
+ Outputs:
+ cw = bit field extracted from a leaf entry of packed mp3 Huffman Tables
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ These functions are used to decode huffman codewords from the input
+ bitstream using combined binary search and look-up table approach.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+ [2] Introduction to Algorithms,
+ Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest.
+ The MIT press, 1990
+
+ [3] "Selecting an Optimal Huffman Decoder for AAC",
+ Vladimir Z. Mesarovic, et al.
+ AES 111th Convention, September 21-24, 2001, New York, USA
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_tables.h"
+#include "pvmp3_getbits.h"
+#include "pvmp3_decode_huff_cw.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+uint16 pvmp3_decode_huff_cw_tab0(tmp3Bits *pMainData)
+{
+ OSCL_UNUSED_ARG(pMainData);
+ return(0);
+
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab1(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo9bits(pMainData, 3); /* hufftable1 */
+
+ cw = *(huffTable_1 + tmp);
+ pMainData->usedBits -= (3 - (cw & 0xFF));
+ return(cw >> 8);
+
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab2(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo9bits(pMainData, 6); /* huffTable_2,3 */
+
+ if (tmp >> 3)
+ {
+ tmp = (tmp >> 3) - 1;
+ }
+ else
+ {
+ tmp = tmp + 7;
+ }
+
+ cw = *(huffTable_2 + tmp);
+ pMainData->usedBits -= (6 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab3(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo9bits(pMainData, 6); /* huffTable_2,3 */
+
+ if (tmp >> 3)
+ {
+ tmp = (tmp >> 3) - 1;
+ }
+ else
+ {
+ tmp = tmp + 7;
+ }
+
+ cw = *(huffTable_3 + tmp);
+ pMainData->usedBits -= (6 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab5(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo9bits(pMainData, 8); /* huffTable_5 */
+
+ if ((tmp >> 5))
+ {
+ tmp = (tmp >> 5) - 1;
+ }
+ else if ((tmp >> 1) >= 2)
+ {
+ tmp = (tmp >> 1) - 2 + 7;
+ }
+ else
+ {
+ tmp = (tmp & 3) + 21;
+ }
+
+ cw = *(huffTable_5 + tmp);
+ pMainData->usedBits -= (8 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab6(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo9bits(pMainData, 7); /* huffTable_6 */
+ if ((tmp >> 3) >= 3)
+ {
+ tmp = (tmp >> 3) - 3;
+ }
+ else if (tmp >> 1)
+ {
+ tmp = (tmp >> 1) - 1 + 13;
+ }
+ else
+ {
+ tmp = tmp + 24;
+ }
+
+ cw = *(huffTable_6 + tmp);
+ pMainData->usedBits -= (7 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab7(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo17bits(pMainData, 10); /* huffTable_7 */
+ if ((tmp >> 7) >= 2)
+ {
+ tmp = (tmp >> 7) - 2;
+ }
+ else if ((tmp >> 4) >= 7)
+ {
+ tmp = (tmp >> 4) - 7 + 6;
+ }
+ else if ((tmp >> 1) >= 2)
+ {
+ tmp = (tmp >> 1) - 2 + 15;
+ }
+ else
+ {
+ tmp = (tmp & 3) + 69;
+ }
+
+ cw = *(huffTable_7 + tmp);
+ pMainData->usedBits -= (10 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab8(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo17bits(pMainData, 11); /* huffTable_8 */
+ if ((tmp >> 7) >= 2)
+ {
+ tmp = (tmp >> 7) - 2;
+ }
+ else if ((tmp >> 5) >= 5)
+ {
+ tmp = (tmp >> 5) - 5 + 14;
+ }
+ else if ((tmp >> 2) >= 3)
+ {
+ tmp = (tmp >> 2) - 3 + 17;
+ }
+ else
+ {
+ tmp = (tmp) + 54;
+ }
+
+ cw = *(huffTable_8 + tmp);
+ pMainData->usedBits -= (11 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab9(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo9bits(pMainData, 9); /* huffTable_9 */
+ if ((tmp >> 5) >= 5)
+ {
+ tmp = (tmp >> 5) - 5;
+ }
+ else if ((tmp >> 3) >= 6)
+ {
+ tmp = (tmp >> 3) - 6 + 11;
+ }
+ else if ((tmp >> 1) >= 4)
+ {
+ tmp = (tmp >> 1) - 4 + 25;
+ }
+ else
+ {
+ tmp = tmp + 45;
+ }
+
+ cw = *(huffTable_9 + tmp);
+ pMainData->usedBits -= (9 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab10(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo17bits(pMainData, 11); /* huffTable_10 */
+ if (tmp >> 10)
+ {
+ tmp = (tmp >> 10) - 1;
+ }
+ else if ((tmp >> 7) >= 3)
+ {
+ tmp = (tmp >> 7) - 3 + 1;
+ }
+ else if ((tmp >> 5) >= 8)
+ {
+ tmp = (tmp >> 5) - 8 + 6;
+ }
+ else if ((tmp >> 3) >= 18)
+ {
+ tmp = (tmp >> 3) - 18 + 10;
+ }
+ else if ((tmp >> 2) >= 24)
+ {
+ tmp = (tmp >> 2) - 24 + 24;
+ }
+ else if ((tmp >> 1) >= 12)
+ {
+ tmp = (tmp >> 1) - 12 + 36;
+ }
+ else
+ {
+ tmp = (tmp) + 72;
+ }
+
+ cw = *(huffTable_10 + tmp);
+ pMainData->usedBits -= (11 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab11(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo17bits(pMainData, 11); /* huffTable_11 */
+ if ((tmp >> 8) >= 3)
+ {
+ tmp = (tmp >> 8) - 3;
+ }
+ else if ((tmp >> 6) >= 7)
+ {
+ tmp = (tmp >> 6) - 7 + 5;
+ }
+ else if ((tmp >> 3) >= 32)
+ {
+ tmp = (tmp >> 3) - 32 + 10;
+ }
+ else if ((tmp >> 2) >= 10)
+ {
+ tmp = (tmp >> 2) - 10 + 34;
+ }
+ else if ((tmp >> 1) >= 8)
+ {
+ tmp = (tmp >> 1) - 8 + 88;
+ }
+ else
+ {
+ tmp = (tmp & 0xFF) + 100;
+ }
+ cw = *(huffTable_11 + tmp);
+ pMainData->usedBits -= (11 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab12(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo17bits(pMainData, 10); /* huffTable_12 */
+ if ((tmp >> 7) >= 5)
+ {
+ tmp = (tmp >> 7) - 5;
+ }
+ else if ((tmp >> 5) >= 12)
+ {
+ tmp = (tmp >> 5) - 12 + 3;
+ }
+ else if ((tmp >> 4) >= 17)
+ {
+ tmp = (tmp >> 4) - 17 + 11;
+ }
+ else if ((tmp >> 2) >= 32)
+ {
+ tmp = (tmp >> 2) - 32 + 18;
+ }
+ else if ((tmp >> 1) >= 16)
+ {
+ tmp = (tmp >> 1) - 16 + 54;
+ }
+ else
+ {
+ tmp = (tmp & 0x1F) + 102;
+
+ }
+ cw = *(huffTable_12 + tmp);
+ pMainData->usedBits -= (10 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab13(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getNbits(pMainData, 19); /* huffTable_13 */
+ if (tmp >> 18)
+ {
+ tmp = 0;
+ }
+ else if ((tmp >> 15) >= 4)
+ {
+ tmp = (tmp >> 15) - 4 + 1;
+ }
+ else if ((tmp >> 11) >= 32)
+ {
+ tmp = (tmp >> 11) - 32 + 5;
+ }
+ else if ((tmp >> 9) >= 64)
+ {
+ tmp = (tmp >> 9) - 64 + 37;
+ }
+ else if ((tmp >> 8) >= 64)
+ {
+ tmp = (tmp >> 8) - 64 + 101;
+ }
+ else if ((tmp >> 7) >= 64)
+ {
+ tmp = (tmp >> 7) - 64 + 165;
+ }
+ else if ((tmp >> 6) >= 32)
+ {
+ tmp = (tmp >> 6) - 32 + 229;
+ }
+ else if ((tmp >> 5) >= 32)
+ {
+ tmp = (tmp >> 5) - 32 + 325;
+ }
+ else if ((tmp >> 4) >= 32)
+ {
+ tmp = (tmp >> 4) - 32 + 357;
+ }
+ else if ((tmp >> 3) >= 32)
+ {
+ tmp = (tmp >> 3) - 32 + 389;
+ }
+ else if ((tmp >> 2) >= 2)
+ {
+ tmp = (tmp >> 2) - 2 + 421;
+ }
+ else
+ {
+ tmp = (tmp & 0x7) + 483;
+ }
+
+ cw = *(huffTable_13 + tmp);
+ pMainData->usedBits -= (19 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab15(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo17bits(pMainData, 13); /* huffTable_15 */
+ if ((tmp >> 9) >= 10)
+ {
+ tmp = (tmp >> 9) - 10;
+ }
+ else if ((tmp >> 6) >= 39)
+ {
+ tmp = (tmp >> 6) - 39 + 6;
+ }
+ else if ((tmp >> 4) >= 62)
+ {
+ tmp = (tmp >> 4) - 62 + 47;
+ }
+ else if ((tmp >> 3) >= 60)
+ {
+ tmp = (tmp >> 3) - 60 + 141;
+ }
+ else if ((tmp >> 2) >= 64)
+ {
+ tmp = (tmp >> 2) - 64 + 205;
+ }
+ else if ((tmp >> 1) >= 32)
+ {
+ tmp = (tmp >> 1) - 32 + 261;
+ }
+ else
+ {
+ tmp = (tmp & 0x3f) + 357;
+ }
+
+ cw = *(huffTable_15 + tmp);
+ pMainData->usedBits -= (13 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab16(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo17bits(pMainData, 17); /* huffTable_16 */
+ if (tmp >> 16)
+ {
+ tmp = 0;
+ }
+ else if ((tmp >> 13) >= 4)
+ {
+ tmp = (tmp >> 13) - 4 + 1;
+ }
+ else if ((tmp >> 9) >= 38)
+ {
+ tmp = (tmp >> 9) - 38 + 5;
+ }
+ else if ((tmp >> 7) >= 94)
+ {
+ tmp = (tmp >> 7) - 94 + 31;
+ }
+ else if ((tmp >> 5) >= 214)
+ {
+ tmp = (tmp >> 5) - 214 + 89;
+ }
+ else if ((tmp >> 3) >= 704)
+ {
+ if ((tmp >> 4) >= 384)
+ {
+ tmp = (tmp >> 4) - 384 + 315;
+ }
+ else
+ {
+ tmp = (tmp >> 3) - 704 + 251;
+ }
+ }
+ else if ((tmp >> 8) >= 14)
+ {
+ tmp = (tmp >> 8) - 14 + 359;
+ }
+ else if ((tmp) >= 3456)
+ {
+ if ((tmp >> 2) >= 868)
+ {
+ tmp = (tmp >> 2) - 868 + 383;
+ }
+ else
+ {
+ tmp = (tmp) - 3456 + 367;
+ }
+ }
+ else
+ {
+ tmp = ((tmp >> 6) & 0x3f) + 411;
+ }
+
+ cw = *(huffTable_16 + tmp);
+ pMainData->usedBits -= (17 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab24(tmp3Bits *pMainData)
+{
+ uint32 tmp;
+ uint16 cw;
+
+ tmp = getUpTo17bits(pMainData, 12); /* huffTable_24 */
+ if ((tmp >> 6) >= 41)
+ {
+ tmp = (tmp >> 6) - 41;
+ }
+ else if ((tmp >> 3) >= 218)
+ {
+ tmp = (tmp >> 3) - 218 + 23;
+ }
+ else if ((tmp >> 2) >= 336)
+ {
+ tmp = (tmp >> 2) - 336 + 133;
+ }
+ else if ((tmp >> 1) >= 520)
+ {
+ tmp = (tmp >> 1) - 520 + 233;
+ }
+ else if ((tmp) >= 1024)
+ {
+ tmp = (tmp) - 1024 + 385;
+ }
+ else if ((tmp >> 1) >= 352)
+ {
+ if ((tmp >> 8) == 3)
+ {
+ tmp = (tmp >> 8) - 3 + 433;
+ }
+ else
+ {
+ tmp = (tmp >> 1) - 352 + 401;
+ }
+ }
+ else
+ {
+ tmp = ((tmp >> 4) & 0x3f) + 434;
+ }
+
+ cw = *(huffTable_24 + tmp);
+ pMainData->usedBits -= (12 - (cw & 0xFF));
+
+ return(cw >> 8);
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+uint16 pvmp3_decode_huff_cw_tab32(tmp3Bits *pMainData)
+{
+ uint32 tmp = getUpTo9bits(pMainData, 6); /* huffTable_32 */
+ if ((tmp >> 5))
+ {
+ pMainData->usedBits -= 5;
+ return(0);
+ }
+ else
+ {
+ uint16 cw = *(huffTable_32 + (tmp & 0x1f));
+ pMainData->usedBits -= (6 - (cw & 0xFF));
+
+ return(cw >> 8);
+ }
+
+}
+
+
+uint16 pvmp3_decode_huff_cw_tab33(tmp3Bits *pMainData)
+{
+
+ uint16 tmp = getUpTo9bits(pMainData, 4); /* huffTable_33 */
+
+ return((0x0f - tmp));
+}
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_huff_cw.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_huff_cw.h
new file mode 100644
index 0000000..941ca6d
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_decode_huff_cw.h
@@ -0,0 +1,114 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_decode_huff_cw.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_DECODE_HUFF_CW_H
+#define PVMP3_DECODE_HUFF_CW_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_audio_type_defs.h"
+#include "pvmp3_dec_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ uint16 pvmp3_decode_huff_cw_tab0(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab1(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab2(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab3(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab5(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab6(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab7(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab8(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab9(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab10(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab11(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab12(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab13(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab15(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab16(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab24(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab32(tmp3Bits *);
+ uint16 pvmp3_decode_huff_cw_tab33(tmp3Bits *);
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp
new file mode 100644
index 0000000..69e1987
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp
@@ -0,0 +1,452 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_dequantize_sample.cpp
+
+ Functions:
+ power_1_third
+ pvmp3_dequantize_sample
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+power_1_third
+int32 power_1_third( int32 xx)
+
+Input
+ int32 xx, int32 in the [0, 8192] range
+
+ Returns
+
+ int32 xx^(1/3) int32 Q26 number representing
+ the 1/3 power of the input
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+pvmp3_dequantize_sample
+
+Input
+ int32 is[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ mp3ScaleFactors *scalefac, scale factor structure
+ struct gr_info_s *gr_info, granule structure informatiom
+ mp3Header *info mp3 header info
+
+ Returns
+
+ int32 is[SUBBANDS_NUMBER*FILTERBANK_BANDS], dequantize output as (.)^(4/3)
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ dequantize sample
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_dequantize_sample.h"
+#include "pvmp3_normalize.h"
+#include "mp3_mem_funcs.h"
+#include "pvmp3_tables.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define Q30_fmt(a)(int32(double(0x40000000)*a))
+#define Q29_fmt(a)(int32(double(0x20000000)*a))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const int32 pretab[22] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0};
+
+const int32 pow_2_1_fourth[4] =
+{
+ Q30_fmt(1.0), Q30_fmt(1.18920711500272),
+ Q30_fmt(1.41421356237310), Q30_fmt(1.68179283050743)
+};
+
+const int32 two_cubic_roots[7] =
+{
+ Q29_fmt(0), Q29_fmt(1.25992104989487),
+ Q29_fmt(1.58740105196820), Q29_fmt(2.00000000000000),
+ Q29_fmt(2.51984209978975), Q29_fmt(3.17480210393640),
+ Q29_fmt(3.99999999999999)
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+int32 power_1_third(int32 xx)
+{
+
+ if (xx <= 512)
+ {
+ return (power_one_third[xx] >> 1);
+ }
+ else
+ {
+ if (xx >> 15)
+ {
+ return 0x7FFFFFFF; /* saturate any value over 32767 */
+ }
+ else
+ {
+ int32 x = xx;
+ int32 m = 22 - pvmp3_normalize(xx);
+
+ xx >>= m;
+ xx = (power_one_third[xx]) + (((power_one_third[xx+1] - power_one_third[xx]) >> m) * (x & ((1 << m) - 1)));
+ return (fxp_mul32_Q30(xx, two_cubic_roots[m]));
+ }
+
+ }
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+void pvmp3_dequantize_sample(int32 is[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ mp3ScaleFactors *scalefac,
+ granuleInfo *gr_info,
+ int32 used_freq_lines,
+ mp3Header *info)
+{
+ int32 ss;
+ int32 cb = 0;
+ int32 global_gain;
+ int32 sfreq = info->sampling_frequency + info->version_x + (info->version_x << 1);
+
+ /* apply formula per block type */
+
+ if (gr_info->window_switching_flag && (gr_info->block_type == 2))
+ {
+ int32 next_cb_boundary;
+ int32 cb_begin = 0;
+ int32 cb_width = 0;
+ int32 mixstart = 8; /* added 2003/08/21 efs */
+
+ if (info->version_x != MPEG_1)
+ {
+ mixstart = 6; /* different value in MPEG2 LSF */
+ }
+
+ if (gr_info->mixed_block_flag)
+ {
+ next_cb_boundary = mp3_sfBandIndex[sfreq].l[1]; /* LONG blocks: 0,1,3 */
+ }
+ else
+ {
+ next_cb_boundary = mp3_sfBandIndex[sfreq].s[1] * 3; /* pure SHORT block */
+ cb_width = 0;
+ }
+
+ global_gain = gr_info->global_gain;
+ int32 two_raise_one_fourth = pow_2_1_fourth[global_gain&0x3];
+ global_gain = 12 + (global_gain >> 2);
+
+ for (ss = 0 ; ss < used_freq_lines ; ss++)
+ {
+ if (ss == next_cb_boundary)
+ {
+ cb++; /* critical band counter */
+ if (gr_info->mixed_block_flag)
+ {
+ if (next_cb_boundary == mp3_sfBandIndex[sfreq].l[mixstart])
+ {
+ next_cb_boundary = mp3_sfBandIndex[sfreq].s[4] * 3;
+
+ cb_begin = mp3_sfBandIndex[sfreq].s[3] * 3;
+ cb_width = 3;
+ cb = 3;
+ }
+ else if (ss < mp3_sfBandIndex[sfreq].l[mixstart])
+ {
+ next_cb_boundary = mp3_sfBandIndex[sfreq].l[cb+1];
+ }
+ else
+ {
+ next_cb_boundary = mp3_sfBandIndex[sfreq].s[cb+1] * 3;
+
+ cb_width = cb;
+ cb_begin = mp3_sfBandIndex[sfreq].s[cb] * 3;
+ }
+
+ if (ss < 2*FILTERBANK_BANDS)
+ { /* 1st 2 subbands of switched blocks */
+ global_gain = (gr_info->global_gain);
+ global_gain -= (1 + gr_info->scalefac_scale) *
+ (scalefac->l[cb] + gr_info->preflag * pretab[cb]) << 1;
+
+ two_raise_one_fourth = pow_2_1_fourth[global_gain&0x3];
+ global_gain = 12 + (global_gain >> 2);
+ }
+ }
+ else
+ {
+ next_cb_boundary = mp3_sfBandIndex[sfreq].s[cb+1] * 3;
+ cb_width = cb;
+ cb_begin = mp3_sfBandIndex[sfreq].s[cb] * 3;
+ }
+
+ } /* end-if ( ss == next_cb_boundary) */
+
+ /* Do long/short dependent scaling operations. */
+ if ((gr_info->mixed_block_flag == 0) || (gr_info->mixed_block_flag && (ss >= 2*FILTERBANK_BANDS)))
+ {
+ int32 temp2 = fxp_mul32_Q32((ss - cb_begin) << 16, mp3_shortwindBandWidths[sfreq][cb_width]);
+ temp2 = (temp2 + 1) >> 15;
+
+ global_gain = (gr_info->global_gain);
+ global_gain -= gr_info->subblock_gain[temp2] << 3;
+ global_gain -= (1 + gr_info->scalefac_scale) * (scalefac->s[temp2][cb] << 1);
+
+ two_raise_one_fourth = pow_2_1_fourth[global_gain&0x3];
+ global_gain = 12 + (global_gain >> 2);
+
+ }
+
+
+ /*
+ * xr[sb][ss] = 2^(global_gain/4)
+ */
+
+ /* Scale quantized value. */
+
+ /* 0 < abs(is[ss]) < 8192 */
+
+ int32 tmp = fxp_mul32_Q30((is[ss] << 16), power_1_third(pv_abs(is[ ss])));
+
+ tmp = fxp_mul32_Q30(tmp, two_raise_one_fourth);
+
+ if (global_gain < 0)
+ {
+ int32 temp = - global_gain;
+ if (temp < 32)
+ {
+ is[ss] = (tmp >> temp);
+ }
+ else
+ {
+ is[ss] = 0;
+ }
+ }
+ else
+ {
+ is[ss] = (tmp << global_gain);
+ }
+
+ } /* for (ss=0 ; ss < used_freq_lines ; ss++) */
+
+ }
+ else
+ {
+
+ for (cb = 0 ; cb < 22 ; cb++)
+ {
+
+ /* Compute overall (global) scaling. */
+
+ global_gain = (gr_info->global_gain);
+
+ global_gain -= (1 + gr_info->scalefac_scale) *
+ (scalefac->l[cb] + gr_info->preflag * pretab[cb]) << 1;
+
+
+ int32 two_raise_one_fourth = pow_2_1_fourth[global_gain&0x3];
+ global_gain = 12 + (global_gain >> 2);
+
+ /*
+ * xr[sb][ss] = 2^(global_gain/4)
+ */
+
+ /* Scale quantized value. */
+
+ if (used_freq_lines >= mp3_sfBandIndex[sfreq].l[cb+1])
+ {
+ if (global_gain <= 0)
+ {
+ global_gain = - global_gain;
+ if (global_gain < 32)
+ {
+ for (ss = mp3_sfBandIndex[sfreq].l[cb]; ss < mp3_sfBandIndex[sfreq].l[cb+1]; ss += 2)
+ {
+ int32 tmp = is[ss];
+ if (tmp)
+ {
+ tmp = fxp_mul32_Q30((tmp << 16), power_1_third(pv_abs(tmp)));
+ is[ss] = fxp_mul32_Q30(tmp, two_raise_one_fourth) >> global_gain;
+ }
+ tmp = is[ss+1];
+ if (tmp)
+ {
+ tmp = fxp_mul32_Q30((tmp << 16), power_1_third(pv_abs(tmp)));
+ is[ss+1] = fxp_mul32_Q30(tmp, two_raise_one_fourth) >> global_gain;
+ }
+ }
+ }
+ else
+ {
+ pv_memset(&is[ mp3_sfBandIndex[sfreq].l[cb]],
+ 0,
+ (mp3_sfBandIndex[sfreq].l[cb+1] - mp3_sfBandIndex[sfreq].l[cb])*sizeof(*is));
+ }
+ }
+ else
+ {
+ for (ss = mp3_sfBandIndex[sfreq].l[cb]; ss < mp3_sfBandIndex[sfreq].l[cb+1]; ss += 2)
+ {
+ int32 tmp = is[ss];
+ if (tmp)
+ {
+ tmp = fxp_mul32_Q30((tmp << 16), power_1_third(pv_abs(tmp)));
+ is[ss] = fxp_mul32_Q30(tmp, two_raise_one_fourth) << global_gain;
+ }
+
+ tmp = is[ss+1];
+ if (tmp)
+ {
+ tmp = fxp_mul32_Q30((tmp << 16), power_1_third(pv_abs(tmp)));
+ is[ss+1] = fxp_mul32_Q30(tmp, two_raise_one_fourth) << global_gain;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (global_gain <= 0)
+ {
+ global_gain = - global_gain;
+ if (global_gain < 32)
+ {
+ for (ss = mp3_sfBandIndex[sfreq].l[cb]; ss < used_freq_lines; ss += 2)
+ {
+ int32 tmp = is[ss];
+ if (tmp)
+ {
+ tmp = fxp_mul32_Q30((tmp << 16), power_1_third(pv_abs(tmp)));
+ is[ss] = fxp_mul32_Q30(tmp, two_raise_one_fourth) >> global_gain;
+ }
+ tmp = is[ss+1];
+ if (tmp)
+ {
+ tmp = fxp_mul32_Q30((tmp << 16), power_1_third(pv_abs(tmp)));
+ is[ss+1] = fxp_mul32_Q30(tmp, two_raise_one_fourth) >> global_gain;
+ }
+ }
+
+ }
+ else
+ {
+ pv_memset(&is[ mp3_sfBandIndex[sfreq].l[cb]],
+ 0,
+ (mp3_sfBandIndex[sfreq].l[cb+1] - mp3_sfBandIndex[sfreq].l[cb])*sizeof(*is));
+ }
+ }
+ else
+ {
+ for (ss = mp3_sfBandIndex[sfreq].l[cb]; ss < used_freq_lines; ss++)
+ {
+ int32 tmp = is[ss];
+
+ if (tmp)
+ {
+ tmp = fxp_mul32_Q30((tmp << 16), power_1_third(pv_abs(tmp)));
+ is[ss] = fxp_mul32_Q30(tmp, two_raise_one_fourth) << global_gain;
+ }
+ }
+ }
+
+ cb = 22; // force breaking out of the loop
+
+ } /* if ( used_freq_lines >= mp3_sfBandIndex[sfreq].l[cb+1]) */
+
+ } /* for (cb=0 ; cb < 22 ; cb++) */
+
+ } /* if (gr_info->window_switching_flag && (gr_info->block_type == 2)) */
+
+
+ pv_memset(&is[used_freq_lines],
+ 0,
+ (FILTERBANK_BANDS*SUBBANDS_NUMBER - used_freq_lines)*sizeof(*is));
+
+}
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_dequantize_sample.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_dequantize_sample.h
new file mode 100644
index 0000000..9393eb1
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_dequantize_sample.h
@@ -0,0 +1,106 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_dequantize_sample.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_DEQUANTIZE_SAMPLE_H
+#define PVMP3_DEQUANTIZE_SAMPLE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_audio_type_defs.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ int32 power_1_third(int32 xx);
+
+ void pvmp3_dequantize_sample(int32 is[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ mp3ScaleFactors *scalefac,
+ granuleInfo *gr_info,
+ int32 num_lines,
+ mp3Header *info);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_equalizer.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_equalizer.cpp
new file mode 100644
index 0000000..f4a4efb
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_equalizer.cpp
@@ -0,0 +1,415 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_equalizer.cpp
+
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Input
+ int32 *inData, pointer to the spectrum frequency-line
+ e_equalization equalizerType, equalization mode
+ int32 *pt_work_buff
+
+ Output
+ int32 *pt_work_buff pointer to the equalized frequency-line
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Equalizer
+ Each subband sample is scaled according to a spectrum shape setting
+ defined by "equalizerType"
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_equalizer.h"
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_dec_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define LEVEL__0__dB 0.999999970f
+#define LEVEL__1_5dB 0.841395142f
+#define LEVEL__3__dB 0.707106781f
+#define LEVEL__4_5dB 0.595662143f
+#define LEVEL__6__dB 0.500000000f
+#define LEVEL__7_5dB 0.421696503f
+#define LEVEL__9__dB 0.353553393f
+#define LEVEL_12__dB 0.250000000f
+#define LEVEL_15__dB 0.176776695f
+#define LEVEL_18__dB 0.125000000f
+#define LEVEL_21__dB 0.088388347f
+#define LEVEL_30__dB 0.031250000f
+#define LEVEL_45__dB 0.005524271f
+#define LEVEL_60__dB 0.000976562f
+
+#define Qmf31( x) (int32)(x*(float)0x7FFFFFFF)
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+const int32 equalizerTbl[8][SUBBANDS_NUMBER] =
+{
+ /* FLAT */
+ {
+ Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB)
+ },
+ /* BASS BOOST */
+ {
+ Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__1_5dB), Qmf31(LEVEL__3__dB),
+
+ Qmf31(LEVEL__4_5dB), Qmf31(LEVEL__6__dB),
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+ Qmf31(LEVEL__6__dB)
+ },
+ /* ROCK */
+ {
+ Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__1_5dB), Qmf31(LEVEL__3__dB),
+
+ Qmf31(LEVEL__4_5dB), Qmf31(LEVEL__6__dB),
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__1_5dB),
+
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB)
+ },
+ /* POP */
+ {
+ Qmf31(LEVEL__6__dB),
+
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+
+ Qmf31(LEVEL__1_5dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+
+ Qmf31(LEVEL__9__dB), Qmf31(LEVEL__9__dB),
+ Qmf31(LEVEL__9__dB), Qmf31(LEVEL__9__dB),
+ Qmf31(LEVEL__9__dB), Qmf31(LEVEL__9__dB),
+ Qmf31(LEVEL__9__dB), Qmf31(LEVEL__9__dB),
+ Qmf31(LEVEL__9__dB), Qmf31(LEVEL__9__dB),
+ Qmf31(LEVEL__9__dB), Qmf31(LEVEL__9__dB),
+ Qmf31(LEVEL__9__dB), Qmf31(LEVEL__9__dB),
+ Qmf31(LEVEL__9__dB), Qmf31(LEVEL__9__dB),
+ Qmf31(LEVEL__9__dB)
+ },
+ /* JAZZ */
+ {
+ Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+
+ Qmf31(LEVEL__9__dB), Qmf31(LEVEL__9__dB),
+ Qmf31(LEVEL__9__dB), Qmf31(LEVEL__9__dB),
+
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__1_5dB),
+
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB)
+ },
+ /* CLASSICAL */
+ {
+ Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__9__dB), Qmf31(LEVEL__9__dB),
+
+ Qmf31(LEVEL__9__dB), Qmf31(LEVEL__9__dB),
+ Qmf31(LEVEL__9__dB), Qmf31(LEVEL__9__dB),
+
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__1_5dB),
+
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB)
+ },
+ /* TALK */
+ {
+ Qmf31(LEVEL__9__dB),
+
+ Qmf31(LEVEL__6__dB), Qmf31(LEVEL__6__dB),
+
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__1_5dB),
+
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB), Qmf31(LEVEL__3__dB),
+ Qmf31(LEVEL__3__dB)
+ },
+ /* FLAT */
+ {
+ Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB), Qmf31(LEVEL__0__dB),
+ Qmf31(LEVEL__0__dB)
+ }
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_equalizer(int32 *circ_buffer,
+ e_equalization equalizerType,
+ int32 *work_buff)
+{
+
+ if (equalizerType == flat)
+ {
+ for (int32 band = 0; band < FILTERBANK_BANDS; band += 2)
+ {
+
+ int32 *pt_work_buff = &work_buff[band];
+ int32 *inData = &circ_buffer[544 - (band<<5)];
+
+ int32 i;
+ for (i = 0; i < SUBBANDS_NUMBER*FILTERBANK_BANDS; i += FILTERBANK_BANDS << 2)
+ {
+ int32 temp1 = (pt_work_buff[ i ]);
+ int32 temp2 = (pt_work_buff[ i + FILTERBANK_BANDS ]);
+ int32 temp3 = (pt_work_buff[ i + 2*FILTERBANK_BANDS ]);
+ int32 temp4 = (pt_work_buff[ i + 3*FILTERBANK_BANDS ]);
+ *(inData++) = temp1;
+ *(inData++) = temp2;
+ *(inData++) = temp3;
+ *(inData++) = temp4;
+ }
+
+ inData -= SUBBANDS_NUMBER << 1;
+ pt_work_buff++;
+
+ for (i = 0; i < SUBBANDS_NUMBER*FILTERBANK_BANDS; i += FILTERBANK_BANDS << 2)
+ {
+ int32 temp1 = (pt_work_buff[ i ]);
+ int32 temp2 = (pt_work_buff[ i + FILTERBANK_BANDS ]);
+ int32 temp3 = (pt_work_buff[ i + 2*FILTERBANK_BANDS ]);
+ int32 temp4 = (pt_work_buff[ i + 3*FILTERBANK_BANDS ]);
+ *(inData++) = temp1;
+ *(inData++) = temp2;
+ *(inData++) = temp3;
+ *(inData++) = temp4;
+ }
+ }
+ }
+ else
+ {
+ const int32 *pt_equalizer = equalizerTbl[equalizerType&7];
+
+
+ for (int32 band = 0; band < FILTERBANK_BANDS; band += 3)
+ {
+ int32 *inData = &circ_buffer[544 - (band<<5)];
+
+ int32 *pt_work_buff = &work_buff[band];
+ int32 i;
+
+ for (i = 0; i < SUBBANDS_NUMBER*FILTERBANK_BANDS; i += FILTERBANK_BANDS << 2)
+ {
+ int32 temp1 = (pt_work_buff[ i ]);
+ int32 temp2 = (pt_work_buff[ i + FILTERBANK_BANDS ]);
+ int32 temp3 = (pt_work_buff[ i + 2*FILTERBANK_BANDS ]);
+ int32 temp4 = (pt_work_buff[ i + 3*FILTERBANK_BANDS ]);
+ *(inData++) = fxp_mul32_Q32(temp1 << 1, *(pt_equalizer++));
+ *(inData++) = fxp_mul32_Q32(temp2 << 1, *(pt_equalizer++));
+ *(inData++) = fxp_mul32_Q32(temp3 << 1, *(pt_equalizer++));
+ *(inData++) = fxp_mul32_Q32(temp4 << 1, *(pt_equalizer++));
+ }
+
+ pt_equalizer -= SUBBANDS_NUMBER;
+
+ inData -= SUBBANDS_NUMBER << 1;
+ pt_work_buff++;
+
+ for (i = 0; i < SUBBANDS_NUMBER*FILTERBANK_BANDS; i += FILTERBANK_BANDS << 2)
+ {
+ int32 temp1 = (pt_work_buff[ i ]);
+ int32 temp2 = (pt_work_buff[ i + FILTERBANK_BANDS ]);
+ int32 temp3 = (pt_work_buff[ i + 2*FILTERBANK_BANDS ]);
+ int32 temp4 = (pt_work_buff[ i + 3*FILTERBANK_BANDS ]);
+ *(inData++) = fxp_mul32_Q32(temp1 << 1, *(pt_equalizer++));
+ *(inData++) = fxp_mul32_Q32(temp2 << 1, *(pt_equalizer++));
+ *(inData++) = fxp_mul32_Q32(temp3 << 1, *(pt_equalizer++));
+ *(inData++) = fxp_mul32_Q32(temp4 << 1, *(pt_equalizer++));
+ }
+ pt_equalizer -= SUBBANDS_NUMBER;
+
+ }
+ }
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_equalizer.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_equalizer.h
new file mode 100644
index 0000000..bbf134f
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_equalizer.h
@@ -0,0 +1,101 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_equalizer.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_EQUALIZER_H
+#define PVMP3_EQUALIZER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_audio_type_defs.h"
+#include "pvmp3decoder_api.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void pvmp3_equalizer(int32 *inData,
+ e_equalization equalizerType,
+ int32 *pt_work_buff);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
new file mode 100644
index 0000000..26bc25c
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
@@ -0,0 +1,834 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_framedecoder.cpp
+
+ Functions:
+ pvmp3_framedecoder
+ pvmp3_InitDecoder
+ pvmp3_resetDecoder
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+ pExt = pointer to the external interface structure. See the file
+ pvmp3decoder_api.h for a description of each field.
+ Data type of pointer to a tPVMP3DecoderExternal
+ structure.
+
+ pMem = void pointer to hide the internal implementation of the library
+ It is cast back to a tmp3dec_file structure. This structure
+ contains information that needs to persist between calls to
+ this function, or is too big to be placed on the stack, even
+ though the data is only needed during execution of this function
+ Data type void pointer, internally pointer to a tmp3dec_file
+ structure.
+
+
+ Outputs:
+ status = ERROR condition. see structure ERROR_CODE
+
+ Pointers and Buffers Modified:
+ pMem contents are modified.
+ pExt: (more detail in the file pvmp3decoder_api.h)
+ inputBufferUsedLength - number of array elements used up by the stream.
+ samplingRate - sampling rate in samples per sec
+ bitRate - bit rate in bits per second, varies frame to frame.
+
+
+
+------------------------------------------------------------------------------
+ FUNCTIONS DESCRIPTION
+
+ pvmp3_framedecoder
+ frame decoder library driver
+ pvmp3_InitDecoder
+ Decoder Initialization
+ pvmp3_resetDecoder
+ Reset Decoder
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+
+#include "pvmp3_framedecoder.h"
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_poly_phase_synthesis.h"
+#include "pvmp3_tables.h"
+#include "pvmp3_imdct_synth.h"
+#include "pvmp3_alias_reduction.h"
+#include "pvmp3_reorder.h"
+#include "pvmp3_dequantize_sample.h"
+#include "pvmp3_stereo_proc.h"
+#include "pvmp3_mpeg2_stereo_proc.h"
+#include "pvmp3_get_side_info.h"
+#include "pvmp3_get_scale_factors.h"
+#include "pvmp3_mpeg2_get_scale_factors.h"
+#include "pvmp3_decode_header.h"
+#include "pvmp3_get_main_data_size.h"
+#include "s_tmp3dec_file.h"
+#include "pvmp3_getbits.h"
+#include "mp3_mem_funcs.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+ERROR_CODE pvmp3_framedecoder(tPVMP3DecoderExternal *pExt,
+ void *pMem)
+{
+
+ ERROR_CODE errorCode = NO_DECODING_ERROR;
+
+ int32 crc_error_count = 0;
+ uint32 sent_crc = 0;
+ uint32 computed_crc = 0;
+
+ tmp3dec_chan *pChVars[CHAN];
+ tmp3dec_file *pVars = (tmp3dec_file *)pMem;
+
+ mp3Header info_data;
+ mp3Header *info = &info_data;
+
+ pVars->inputStream.pBuffer = pExt->pInputBuffer;
+
+
+ pVars->inputStream.usedBits = pExt->inputBufferUsedLength << 3;
+ pVars->inputStream.inputBufferCurrentLength = pExt->inputBufferCurrentLength;
+
+
+ errorCode = pvmp3_decode_header(&pVars->inputStream,
+ info,
+ &computed_crc);
+
+ if (errorCode != NO_DECODING_ERROR)
+ {
+ pExt->outputFrameSize = 0;
+ return errorCode;
+ }
+
+ pVars->num_channels = (info->mode == MPG_MD_MONO) ? 1 : 2;
+ pExt->num_channels = pVars->num_channels;
+
+ int32 outputFrameSize = (info->version_x == MPEG_1) ?
+ 2 * SUBBANDS_NUMBER * FILTERBANK_BANDS :
+ SUBBANDS_NUMBER * FILTERBANK_BANDS;
+
+ outputFrameSize = (info->mode == MPG_MD_MONO) ? outputFrameSize : outputFrameSize << 1;
+
+
+ /*
+ * Check if output buffer has enough room to hold output PCM
+ */
+ if (pExt->outputFrameSize >= outputFrameSize)
+ {
+ pExt->outputFrameSize = outputFrameSize;
+ }
+ else
+ {
+ pExt->outputFrameSize = 0;
+ return OUTPUT_BUFFER_TOO_SMALL;
+ }
+
+
+ pChVars[ LEFT] = &pVars->perChan[ LEFT];
+ pChVars[RIGHT] = &pVars->perChan[RIGHT];
+
+
+
+
+ if (info->error_protection)
+ {
+ /*
+ * Get crc content
+ */
+ sent_crc = getUpTo17bits(&pVars->inputStream, 16);
+ }
+
+
+ if (info->layer_description == 3)
+ {
+ int32 gr;
+ int32 ch;
+ uint32 main_data_end;
+ int32 bytes_to_discard;
+ int16 *ptrOutBuffer = pExt->pOutputBuffer;
+
+ /*
+ * Side Information must be extracted from the bitstream and store for use
+ * during the decoded of the associated frame
+ */
+
+ errorCode = pvmp3_get_side_info(&pVars->inputStream,
+ &pVars->sideInfo,
+ info,
+ &computed_crc);
+
+ if (errorCode != NO_DECODING_ERROR)
+ {
+ pExt->outputFrameSize = 0;
+ return errorCode;
+ }
+
+ /*
+ * If CRC was sent, check that matches the one got while parsing data
+ * disable crc if this is the desired mode
+ */
+ if (info->error_protection)
+ {
+ if ((computed_crc != sent_crc) && pExt->crcEnabled)
+ {
+ crc_error_count++;
+ }
+ }
+
+ /*
+ * main data (scalefactors, Huffman coded, etc,) are not necessarily located
+ * adjacent to the side-info. Beginning of main data is located using
+ * field "main_data_begin" of the current frame. The length does not include
+ * header and side info.
+ * "main_data_begin" points to the first bit of main data of a frame. It is a negative
+ * offset in bytes from the first byte of the sync word
+ * main_data_begin = 0 <===> main data start rigth after side info.
+ */
+
+ int32 temp = pvmp3_get_main_data_size(info, pVars);
+
+
+ /*
+ * Check if available data holds a full frame, if not flag an error
+ */
+
+ if ((uint32)pVars->predicted_frame_size > pVars->inputStream.inputBufferCurrentLength)
+ {
+ pExt->outputFrameSize = 0;
+ return NO_ENOUGH_MAIN_DATA_ERROR;
+ }
+
+ /*
+ * Fill in internal circular buffer
+ */
+ fillMainDataBuf(pVars, temp);
+
+
+ main_data_end = pVars->mainDataStream.usedBits >> 3; /* in bytes */
+ if ((main_data_end << 3) < pVars->mainDataStream.usedBits)
+ {
+ main_data_end++;
+ pVars->mainDataStream.usedBits = main_data_end << 3;
+ }
+
+
+ bytes_to_discard = pVars->frame_start - pVars->sideInfo.main_data_begin - main_data_end;
+
+
+ if (main_data_end > BUFSIZE) /* check overflow on the buffer */
+ {
+ pVars->frame_start -= BUFSIZE;
+
+ pVars->mainDataStream.usedBits -= (BUFSIZE << 3);
+ }
+
+ pVars->frame_start += temp;
+
+
+ if (bytes_to_discard < 0 || crc_error_count)
+ {
+ /*
+ * Not enough data to decode, then we should avoid reading this
+ * data ( getting/ignoring sido info and scale data)
+ * Main data could be located in the previous frame, so an unaccounted
+ * frame can cause incorrect processing
+ * Just run the polyphase filter to "clean" the history buffer
+ */
+ errorCode = NO_ENOUGH_MAIN_DATA_ERROR;
+
+ /*
+ * Clear the input to these filters
+ */
+
+ pv_memset((void*)pChVars[RIGHT]->work_buf_int32,
+ 0,
+ SUBBANDS_NUMBER*FILTERBANK_BANDS*sizeof(pChVars[RIGHT]->work_buf_int32[0]));
+
+ pv_memset((void*)pChVars[LEFT]->work_buf_int32,
+ 0,
+ SUBBANDS_NUMBER*FILTERBANK_BANDS*sizeof(pChVars[LEFT]->work_buf_int32[0]));
+
+ /* clear circular buffers, to avoid any glitch */
+ pv_memset((void*)&pChVars[ LEFT]->circ_buffer[576],
+ 0,
+ 480*sizeof(pChVars[ LEFT]->circ_buffer[0]));
+ pv_memset((void*)&pChVars[RIGHT]->circ_buffer[576],
+ 0,
+ 480*sizeof(pChVars[RIGHT]->circ_buffer[0]));
+
+ pChVars[ LEFT]->used_freq_lines = 575;
+ pChVars[RIGHT]->used_freq_lines = 575;
+
+ }
+ else
+ {
+ pVars->mainDataStream.usedBits += (bytes_to_discard << 3);
+ }
+
+ /*
+ * if (fr_ps->header->version_x == MPEG_1), use 2 granules, otherwise just 1
+ */
+ for (gr = 0; gr < (1 + !(info->version_x)); gr++)
+ {
+ if (errorCode != NO_ENOUGH_MAIN_DATA_ERROR)
+ {
+ for (ch = 0; ch < pVars->num_channels; ch++)
+ {
+ int32 part2_start = pVars->mainDataStream.usedBits;
+
+ if (info->version_x == MPEG_1)
+ {
+
+ pvmp3_get_scale_factors(&pVars->scaleFactors[ch],
+ &pVars->sideInfo,
+ gr,
+ ch,
+ &pVars->mainDataStream);
+ }
+ else
+ {
+ int32 * tmp = pVars->Scratch_mem;
+ pvmp3_mpeg2_get_scale_factors(&pVars->scaleFactors[ch],
+ &pVars->sideInfo,
+ gr,
+ ch,
+ info,
+ (uint32 *)tmp,
+ &pVars->mainDataStream);
+ }
+
+ pChVars[ch]->used_freq_lines = pvmp3_huffman_parsing(pChVars[ch]->work_buf_int32,
+ &pVars->sideInfo.ch[ch].gran[gr],
+ pVars,
+ part2_start,
+ info);
+
+
+ pvmp3_dequantize_sample(pChVars[ch]->work_buf_int32,
+ &pVars->scaleFactors[ch],
+ &pVars->sideInfo.ch[ch].gran[gr],
+ pChVars[ch]->used_freq_lines,
+ info);
+
+
+
+
+ } /* for (ch=0; ch<stereo; ch++) */
+
+ if (pVars->num_channels == 2)
+ {
+
+ int32 used_freq_lines = (pChVars[ LEFT]->used_freq_lines >
+ pChVars[RIGHT]->used_freq_lines) ?
+ pChVars[ LEFT]->used_freq_lines :
+ pChVars[RIGHT]->used_freq_lines;
+
+ pChVars[ LEFT]->used_freq_lines = used_freq_lines;
+ pChVars[RIGHT]->used_freq_lines = used_freq_lines;
+
+ if (info->version_x == MPEG_1)
+ {
+ pvmp3_stereo_proc(pChVars[ LEFT]->work_buf_int32,
+ pChVars[RIGHT]->work_buf_int32,
+ &pVars->scaleFactors[RIGHT],
+ &pVars->sideInfo.ch[LEFT].gran[gr],
+ used_freq_lines,
+ info);
+ }
+ else
+ {
+ int32 * tmp = pVars->Scratch_mem;
+ pvmp3_mpeg2_stereo_proc(pChVars[ LEFT]->work_buf_int32,
+ pChVars[RIGHT]->work_buf_int32,
+ &pVars->scaleFactors[RIGHT],
+ &pVars->sideInfo.ch[ LEFT].gran[gr],
+ &pVars->sideInfo.ch[RIGHT].gran[gr],
+ (uint32 *)tmp,
+ used_freq_lines,
+ info);
+ }
+ }
+
+ } /* if ( errorCode != NO_ENOUGH_MAIN_DATA_ERROR) */
+
+ for (ch = 0; ch < pVars->num_channels; ch++)
+ {
+
+ pvmp3_reorder(pChVars[ch]->work_buf_int32,
+ &pVars->sideInfo.ch[ch].gran[gr],
+ &pChVars[ ch]->used_freq_lines,
+ info,
+ pVars->Scratch_mem);
+
+ pvmp3_alias_reduction(pChVars[ch]->work_buf_int32,
+ &pVars->sideInfo.ch[ch].gran[gr],
+ &pChVars[ ch]->used_freq_lines,
+ info);
+
+
+ /*
+ * IMDCT
+ */
+ /* set mxposition
+ * In case of mixed blocks, # of bands with long
+ * blocks (2 or 4) else 0
+ */
+ uint16 mixedBlocksLongBlocks = 0; /* 0 = long or short, 2=mixed, 4=mixed 2.5@8000 */
+ if (pVars->sideInfo.ch[ch].gran[gr].mixed_block_flag &&
+ pVars->sideInfo.ch[ch].gran[gr].window_switching_flag)
+ {
+ if ((info->version_x == MPEG_2_5) && (info->sampling_frequency == 2))
+ {
+ mixedBlocksLongBlocks = 4; /* mpeg2.5 @ 8 KHz */
+ }
+ else
+ {
+ mixedBlocksLongBlocks = 2;
+ }
+ }
+
+ pvmp3_imdct_synth(pChVars[ch]->work_buf_int32,
+ pChVars[ch]->overlap,
+ pVars->sideInfo.ch[ch].gran[gr].block_type,
+ mixedBlocksLongBlocks,
+ pChVars[ ch]->used_freq_lines,
+ pVars->Scratch_mem);
+
+
+ /*
+ * Polyphase synthesis
+ */
+
+ pvmp3_poly_phase_synthesis(pChVars[ch],
+ pVars->num_channels,
+ pExt->equalizerType,
+ &ptrOutBuffer[ch]);
+
+
+ }/* end ch loop */
+
+ ptrOutBuffer += pVars->num_channels * SUBBANDS_NUMBER * FILTERBANK_BANDS;
+ } /* for (gr=0;gr<Max_gr;gr++) */
+
+ /* skip ancillary data */
+ if (info->bitrate_index > 0)
+ { /* if not free-format */
+
+ int32 ancillary_data_lenght = pVars->predicted_frame_size << 3;
+
+ ancillary_data_lenght -= pVars->inputStream.usedBits;
+
+ /* skip ancillary data */
+ if (ancillary_data_lenght > 0)
+ {
+ pVars->inputStream.usedBits += ancillary_data_lenght;
+ }
+
+ }
+
+ /*
+ * This overrides a possible NO_ENOUGH_MAIN_DATA_ERROR
+ */
+ errorCode = NO_DECODING_ERROR;
+
+ }
+ else
+ {
+ /*
+ * The info on the header leads to an unsupported layer, more data
+ * will not fix this, so this is a bad frame,
+ */
+
+ pExt->outputFrameSize = 0;
+ return UNSUPPORTED_LAYER;
+ }
+
+ pExt->inputBufferUsedLength = pVars->inputStream.usedBits >> 3;
+ pExt->totalNumberOfBitsUsed += pVars->inputStream.usedBits;
+ pExt->version = info->version_x;
+ pExt->samplingRate = mp3_s_freq[info->version_x][info->sampling_frequency];
+ pExt->bitRate = mp3_bitrate[pExt->version][info->bitrate_index];
+
+
+ /*
+ * Always verify buffer overrun condition
+ */
+
+ if (pExt->inputBufferUsedLength > pExt->inputBufferCurrentLength)
+ {
+ pExt->outputFrameSize = 0;
+ errorCode = NO_ENOUGH_MAIN_DATA_ERROR;
+ }
+
+ return errorCode;
+
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+__inline void fillDataBuf(tmp3Bits *pMainData,
+ uint32 val) /* val to write into the buffer */
+{
+ pMainData->pBuffer[module(pMainData->offset++, BUFSIZE)] = (uint8)val;
+}
+
+
+void fillMainDataBuf(void *pMem, int32 temp)
+{
+ tmp3dec_file *pVars = (tmp3dec_file *)pMem;
+
+
+ int32 offset = (pVars->inputStream.usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
+
+ /*
+ * Check if input circular buffer boundaries need to be enforced
+ */
+ if ((offset + temp) < BUFSIZE)
+ {
+ uint8 * ptr = pVars->inputStream.pBuffer + offset;
+
+ offset = pVars->mainDataStream.offset;
+
+ /*
+ * Check if main data circular buffer boundaries need to be enforced
+ */
+ if ((offset + temp) < BUFSIZE)
+ {
+ pv_memcpy((pVars->mainDataStream.pBuffer + offset), ptr, temp*sizeof(uint8));
+ pVars->mainDataStream.offset += temp;
+ }
+ else
+ {
+ int32 tmp1 = *(ptr++);
+ for (int32 nBytes = temp >> 1; nBytes != 0; nBytes--) /* read main data. */
+ {
+ int32 tmp2 = *(ptr++);
+ fillDataBuf(&pVars->mainDataStream, tmp1);
+ fillDataBuf(&pVars->mainDataStream, tmp2);
+ tmp1 = *(ptr++);
+ }
+
+ if (temp&1)
+ {
+ fillDataBuf(&pVars->mainDataStream, tmp1);
+ }
+
+ /* adjust circular buffer counter */
+ pVars->mainDataStream.offset = module(pVars->mainDataStream.offset, BUFSIZE);
+ }
+ }
+ else
+ {
+ for (int32 nBytes = temp >> 1; nBytes != 0; nBytes--) /* read main data. */
+ {
+ fillDataBuf(&pVars->mainDataStream, *(pVars->inputStream.pBuffer + module(offset++ , BUFSIZE)));
+ fillDataBuf(&pVars->mainDataStream, *(pVars->inputStream.pBuffer + module(offset++ , BUFSIZE)));
+ }
+ if (temp&1)
+ {
+ fillDataBuf(&pVars->mainDataStream, *(pVars->inputStream.pBuffer + module(offset , BUFSIZE)));
+ }
+ }
+
+
+ pVars->inputStream.usedBits += (temp) << INBUF_ARRAY_INDEX_SHIFT;
+}
+
+
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+uint32 pvmp3_decoderMemRequirements(void)
+{
+ uint32 size;
+
+ size = (uint32) sizeof(tmp3dec_file);
+ return (size);
+}
+
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_decode_huff_cw.h"
+
+void pvmp3_InitDecoder(tPVMP3DecoderExternal *pExt,
+ void *pMem)
+{
+
+ tmp3dec_file *pVars;
+ huffcodetab *pHuff;
+
+ pVars = (tmp3dec_file *)pMem;
+
+ pVars->num_channels = 0;
+
+ pExt->totalNumberOfBitsUsed = 0;
+ pExt->inputBufferCurrentLength = 0;
+ pExt->inputBufferUsedLength = 0;
+
+ pVars->mainDataStream.offset = 0;
+
+ pv_memset((void*)pVars->mainDataBuffer,
+ 0,
+ BUFSIZE*sizeof(*pVars->mainDataBuffer));
+
+
+ pVars->inputStream.pBuffer = pExt->pInputBuffer;
+
+ /*
+ * Initialize huffman decoding table
+ */
+
+ pHuff = pVars->ht;
+ pHuff[0].linbits = 0;
+ pHuff[0].pdec_huff_tab = pvmp3_decode_huff_cw_tab0;
+ pHuff[1].linbits = 0;
+ pHuff[1].pdec_huff_tab = pvmp3_decode_huff_cw_tab1;
+ pHuff[2].linbits = 0;
+ pHuff[2].pdec_huff_tab = pvmp3_decode_huff_cw_tab2;
+ pHuff[3].linbits = 0;
+ pHuff[3].pdec_huff_tab = pvmp3_decode_huff_cw_tab3;
+ pHuff[4].linbits = 0;
+ pHuff[4].pdec_huff_tab = pvmp3_decode_huff_cw_tab0; /* tbl 4 is not used */
+ pHuff[5].linbits = 4;
+ pHuff[5].pdec_huff_tab = pvmp3_decode_huff_cw_tab5;
+ pHuff[6].linbits = 0;
+ pHuff[6].pdec_huff_tab = pvmp3_decode_huff_cw_tab6;
+ pHuff[7].linbits = 0;
+ pHuff[7].pdec_huff_tab = pvmp3_decode_huff_cw_tab7;
+ pHuff[8].linbits = 0;
+ pHuff[8].pdec_huff_tab = pvmp3_decode_huff_cw_tab8;
+ pHuff[9].linbits = 0;
+ pHuff[9].pdec_huff_tab = pvmp3_decode_huff_cw_tab9;
+ pHuff[10].linbits = 0;
+ pHuff[10].pdec_huff_tab = pvmp3_decode_huff_cw_tab10;
+ pHuff[11].linbits = 0;
+ pHuff[11].pdec_huff_tab = pvmp3_decode_huff_cw_tab11;
+ pHuff[12].linbits = 0;
+ pHuff[12].pdec_huff_tab = pvmp3_decode_huff_cw_tab12;
+ pHuff[13].linbits = 0;
+ pHuff[13].pdec_huff_tab = pvmp3_decode_huff_cw_tab13;
+ pHuff[14].linbits = 0;
+ pHuff[14].pdec_huff_tab = pvmp3_decode_huff_cw_tab0; /* tbl 14 is not used */
+ pHuff[15].linbits = 0;
+ pHuff[15].pdec_huff_tab = pvmp3_decode_huff_cw_tab15;
+ pHuff[16].linbits = 1;
+ pHuff[16].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
+ pHuff[17].linbits = 2;
+ pHuff[17].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
+ pHuff[18].linbits = 3;
+ pHuff[18].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
+ pHuff[19].linbits = 4;
+ pHuff[19].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
+ pHuff[20].linbits = 6;
+ pHuff[20].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
+ pHuff[21].linbits = 8;
+ pHuff[21].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
+ pHuff[22].linbits = 10;
+ pHuff[22].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
+ pHuff[23].linbits = 13;
+ pHuff[23].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
+ pHuff[24].linbits = 4;
+ pHuff[24].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
+ pHuff[25].linbits = 5;
+ pHuff[25].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
+ pHuff[26].linbits = 6;
+ pHuff[26].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
+ pHuff[27].linbits = 7;
+ pHuff[27].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
+ pHuff[28].linbits = 8;
+ pHuff[28].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
+ pHuff[29].linbits = 9;
+ pHuff[29].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
+ pHuff[30].linbits = 11;
+ pHuff[30].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
+ pHuff[31].linbits = 13;
+ pHuff[31].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
+ pHuff[32].linbits = 0;
+ pHuff[32].pdec_huff_tab = pvmp3_decode_huff_cw_tab32;
+ pHuff[33].linbits = 0;
+ pHuff[33].pdec_huff_tab = pvmp3_decode_huff_cw_tab33;
+
+ /*
+ * Initialize polysynthesis circular buffer mechanism
+ */
+ /* clear buffers */
+
+ pvmp3_resetDecoder(pMem);
+
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void pvmp3_resetDecoder(void *pMem)
+{
+
+ tmp3dec_file *pVars;
+ tmp3dec_chan *pChVars[CHAN];
+
+ pVars = (tmp3dec_file *)pMem;
+ pChVars[ LEFT] = &pVars->perChan[ LEFT];
+ pChVars[RIGHT] = &pVars->perChan[RIGHT];
+
+ pVars->frame_start = 0;
+
+ pVars->mainDataStream.offset = 0;
+
+ pVars->mainDataStream.pBuffer = pVars->mainDataBuffer;
+ pVars->mainDataStream.usedBits = 0;
+
+
+ pVars->inputStream.usedBits = 0; // in bits
+
+
+ pChVars[ LEFT]->used_freq_lines = 575;
+ pChVars[RIGHT]->used_freq_lines = 575;
+
+
+ /*
+ * Initialize polysynthesis circular buffer mechanism
+ */
+
+ pv_memset((void*)&pChVars[ LEFT]->circ_buffer[576],
+ 0,
+ 480*sizeof(pChVars[ LEFT]->circ_buffer[0]));
+ pv_memset((void*)&pChVars[RIGHT]->circ_buffer[576],
+ 0,
+ 480*sizeof(pChVars[RIGHT]->circ_buffer[0]));
+
+
+ pv_memset((void*)pChVars[ LEFT]->overlap,
+ 0,
+ SUBBANDS_NUMBER*FILTERBANK_BANDS*sizeof(pChVars[ LEFT]->overlap[0]));
+
+
+ pv_memset((void*)pChVars[ RIGHT]->overlap,
+ 0,
+ SUBBANDS_NUMBER*FILTERBANK_BANDS*sizeof(pChVars[ RIGHT]->overlap[0]));
+
+
+
+
+
+ /*
+ * Clear all the structures
+ */
+
+
+ pv_memset((void*)&pVars->scaleFactors[RIGHT],
+ 0,
+ sizeof(mp3ScaleFactors));
+
+ pv_memset((void*)&pVars->scaleFactors[LEFT],
+ 0,
+ sizeof(mp3ScaleFactors));
+
+ pv_memset((void*)&pVars->sideInfo,
+ 0,
+ sizeof(mp3SideInfo));
+
+ pv_memset((void*)&pVars->sideInfo,
+ 0,
+ sizeof(mp3SideInfo));
+
+}
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.h
new file mode 100644
index 0000000..f6d4a35
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.h
@@ -0,0 +1,115 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_framedecoder.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_FRAMEDECODER_H
+#define PVMP3_FRAMEDECODER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_audio_type_defs.h"
+#include "pvmp3decoder_api.h"
+#include "s_mp3bits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ ERROR_CODE pvmp3_framedecoder(tPVMP3DecoderExternal *pExt,
+ void *pMem);
+
+
+
+ uint32 pvmp3_decoderMemRequirements(void);
+
+ void pvmp3_InitDecoder(tPVMP3DecoderExternal *pExt,
+ void *pMem);
+
+
+ void pvmp3_resetDecoder(void *pMem);
+
+
+ void fillMainDataBuf(void *pMem, int32 temp);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp
new file mode 100644
index 0000000..423a7b1
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp
@@ -0,0 +1,180 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_get_main_data_size.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Input
+ mp3Header *info, pointer to mp3 header info structure
+ tmp3dec_file *pVars
+ contains information that needs to persist
+ between calls to this function, or is too big to
+ be placed on the stack, even though the data is
+ only needed during execution of this function
+
+ Returns
+
+ main data frame size
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ get main data frame size
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_tables.h"
+#include "pvmp3_get_main_data_size.h"
+#include "pv_mp3dec_fxd_op.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+int32 pvmp3_get_main_data_size(mp3Header *info,
+ tmp3dec_file *pVars)
+{
+
+
+ int32 numBytes = fxp_mul32_Q28(mp3_bitrate[info->version_x][info->bitrate_index] << 20,
+ inv_sfreq[info->sampling_frequency]);
+
+
+ numBytes >>= (20 - info->version_x);
+
+ /*
+ * Remove the size of the side information from the main data total
+ */
+ if (info->version_x == MPEG_1)
+ {
+ pVars->predicted_frame_size = numBytes;
+ if (info->mode == MPG_MD_MONO)
+ {
+ numBytes -= 17;
+ }
+ else
+ {
+ numBytes -= 32;
+ }
+ }
+ else
+ {
+ numBytes >>= 1;
+ pVars->predicted_frame_size = numBytes;
+
+ if (info->mode == MPG_MD_MONO)
+ {
+ numBytes -= 9;
+ }
+ else
+ {
+ numBytes -= 17;
+ }
+ }
+
+ if (info->padding)
+ {
+ numBytes++;
+ pVars->predicted_frame_size++;
+ }
+
+ if (info->error_protection)
+ {
+ numBytes -= 6;
+ }
+ else
+ {
+ numBytes -= 4;
+ }
+
+
+ if (numBytes < 0)
+ {
+ numBytes = 0;
+ }
+
+ return(numBytes);
+}
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_main_data_size.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_main_data_size.h
new file mode 100644
index 0000000..8e9eaa8
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_main_data_size.h
@@ -0,0 +1,101 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_get_main_data_size.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_GET_MAIN_DATA_SIZE_H
+#define PVMP3_GET_MAIN_DATA_SIZE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_audio_type_defs.h"
+#include "s_tmp3dec_file.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ int32 pvmp3_get_main_data_size(mp3Header *info,
+ tmp3dec_file *pVars);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp
new file mode 100644
index 0000000..f1a3ff8
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp
@@ -0,0 +1,226 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_get_scale_factors.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Input
+ mp3ScaleFactors *scalefac,
+ mp3SideInfo *si, side info
+ int32 gr, granule
+ int32 ch, channel
+ tbits *pMainData bit stream
+
+ Returns
+
+ mp3ScaleFactors *scalefac, scale factors
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ get scale factors
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_get_scale_factors.h"
+#include "pvmp3_getbits.h"
+#include "mp3_mem_funcs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define Qfmt_28(a)(int32(double(0x10000000)*a))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const int32 slen[2][16] =
+{
+ {0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4},
+ {0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3}
+};
+
+const struct
+{
+ int32 l[5];
+ int32 s[3];
+} sfbtable =
+{
+ {0, 6, 11, 16, 21},
+ {0, 6, 12}
+};
+
+const int32 long_sfbtable[4] = { 6, 5, 5, 5};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_get_scale_factors(mp3ScaleFactors *scalefac,
+ mp3SideInfo *si,
+ int32 gr,
+ int32 ch,
+ tmp3Bits *pMainData)
+{
+ int32 sfb;
+ int32 i;
+ int32 window;
+ granuleInfo *gr_info = &(si->ch[ch].gran[gr]);
+
+ if (gr_info->window_switching_flag && (gr_info->block_type == 2))
+ {
+ if (gr_info->mixed_block_flag)
+ { /* MIXED */
+ for (sfb = 0; sfb < 8; sfb++)
+ {
+ scalefac->l[sfb] = getNbits(pMainData, slen[0][gr_info->scalefac_compress]);
+ }
+
+ for (sfb = 3; sfb < 6; sfb++)
+ {
+ for (window = 0; window < 3; window++)
+ {
+ scalefac->s[window][sfb] = getNbits(pMainData, slen[0][gr_info->scalefac_compress]);
+ }
+ }
+ for (sfb = 6; sfb < 12; sfb++)
+ {
+ for (window = 0; window < 3; window++)
+ {
+ scalefac->s[window][sfb] = getNbits(pMainData, slen[1][gr_info->scalefac_compress]);
+ }
+ }
+ }
+ else
+ { /* SHORT*/
+ for (i = 0; i < 2; i++)
+ {
+ for (sfb = sfbtable.s[i]; sfb < sfbtable.s[i+1]; sfb++)
+ {
+ for (window = 0; window < 3; window++)
+ {
+ scalefac->s[window][sfb] = getNbits(pMainData, slen[i][gr_info->scalefac_compress]);
+ }
+ }
+ }
+ }
+
+ scalefac->s[0][12] = 0; /* sfb = 12 win= 0 */
+ scalefac->s[1][12] = 0; /* sfb = 12 win= 1 */
+ scalefac->s[2][12] = 0; /* sfb = 12 win= 2 */
+ }
+ else
+ { /* LONG types 0,1,3 */
+
+ int32 *ptr = &scalefac->l[0];
+
+ for (i = 0; i < 4; i++)
+ {
+ int32 tmp4 = long_sfbtable[i];
+
+ if ((si->ch[ch].scfsi[i] == 0) || (gr == 0))
+ {
+ int32 tmp1 = slen[(i>>1)][gr_info->scalefac_compress];
+
+ if (tmp1)
+ {
+ int32 tmp2 = tmp1 * tmp4;
+ uint32 tmp3 = getNbits(pMainData, tmp2);
+ tmp4 = 32 - tmp1;
+ for (; tmp2 > 0; tmp2 -= tmp1)
+ {
+ *(ptr++) = (tmp3 << (32 - tmp2)) >> tmp4;
+ }
+ }
+ else
+ {
+ for (sfb = tmp4; sfb != 0; sfb--)
+ {
+ *(ptr++) = 0;
+ }
+
+ }
+ }
+ else
+ {
+ ptr += tmp4;
+ }
+ }
+ scalefac->l[21] = 0;
+ scalefac->l[22] = 0;
+ }
+}
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_scale_factors.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_scale_factors.h
new file mode 100644
index 0000000..d4f262b
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_scale_factors.h
@@ -0,0 +1,104 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_get_scale_factors.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_GET_SCALE_FACTORS_H
+#define PVMP3_GET_SCALE_FACTORS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_audio_type_defs.h"
+#include "s_mp3bits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void pvmp3_get_scale_factors(mp3ScaleFactors *scalefac,
+ mp3SideInfo *si,
+ int32 gr,
+ int32 ch,
+ tmp3Bits *pMainData);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
new file mode 100644
index 0000000..7eaa860
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
@@ -0,0 +1,285 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_get_side_info.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+ mp3SideInfo *si,
+ mp3Header *info, mp3 header information
+ uint32 *crc initialized crc value (if enabled)
+
+
+ Returns
+
+ mp3SideInfo *si, side information
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ acquires side information
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_get_side_info.h"
+#include "pvmp3_crc.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+ERROR_CODE pvmp3_get_side_info(tmp3Bits *inputStream,
+ mp3SideInfo *si,
+ mp3Header *info,
+ uint32 *crc)
+{
+ int32 ch, gr;
+ uint32 tmp;
+
+ int stereo = (info->mode == MPG_MD_MONO) ? 1 : 2;
+
+ if (info->version_x == MPEG_1)
+ {
+ if (stereo == 1)
+ {
+ tmp = getbits_crc(inputStream, 14, crc, info->error_protection);
+ si->main_data_begin = (tmp << 18) >> 23; /* 9 */
+ si->private_bits = (tmp << 23) >> 27; /* 5 */
+ }
+ else
+ {
+ tmp = getbits_crc(inputStream, 12, crc, info->error_protection);
+ si->main_data_begin = (tmp << 20) >> 23; /* 9 */
+ si->private_bits = (tmp << 23) >> 29; /* 3 */
+
+ }
+
+ for (ch = 0; ch < stereo; ch++)
+ {
+ tmp = getbits_crc(inputStream, 4, crc, info->error_protection);
+ si->ch[ch].scfsi[0] = (tmp << 28) >> 31; /* 1 */
+ si->ch[ch].scfsi[1] = (tmp << 29) >> 31; /* 1 */
+ si->ch[ch].scfsi[2] = (tmp << 30) >> 31; /* 1 */
+ si->ch[ch].scfsi[3] = tmp & 1; /* 1 */
+ }
+
+ for (gr = 0; gr < 2 ; gr++)
+ {
+ for (ch = 0; ch < stereo; ch++)
+ {
+ si->ch[ch].gran[gr].part2_3_length = getbits_crc(inputStream, 12, crc, info->error_protection);
+ tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
+
+ si->ch[ch].gran[gr].big_values = (tmp << 10) >> 23; /* 9 */
+ si->ch[ch].gran[gr].global_gain = ((tmp << 19) >> 24) - 210; /* 8 */
+ si->ch[ch].gran[gr].scalefac_compress = (tmp << 27) >> 28; /* 4 */
+ si->ch[ch].gran[gr].window_switching_flag = tmp & 1; /* 1 */
+
+ if (si->ch[ch].gran[gr].window_switching_flag)
+ {
+ tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
+
+ si->ch[ch].gran[gr].block_type = (tmp << 10) >> 30; /* 2 */;
+ si->ch[ch].gran[gr].mixed_block_flag = (tmp << 12) >> 31; /* 1 */;
+
+ si->ch[ch].gran[gr].table_select[0] = (tmp << 13) >> 27; /* 5 */;
+ si->ch[ch].gran[gr].table_select[1] = (tmp << 18) >> 27; /* 5 */;
+
+ si->ch[ch].gran[gr].subblock_gain[0] = (tmp << 23) >> 29; /* 3 */;
+ si->ch[ch].gran[gr].subblock_gain[1] = (tmp << 26) >> 29; /* 3 */;
+ si->ch[ch].gran[gr].subblock_gain[2] = (tmp << 29) >> 29; /* 3 */;
+
+ /* Set region_count parameters since they are implicit in this case. */
+
+ if (si->ch[ch].gran[gr].block_type == 0)
+ {
+ return(SIDE_INFO_ERROR);
+ }
+ else if ((si->ch[ch].gran[gr].block_type == 2)
+ && (si->ch[ch].gran[gr].mixed_block_flag == 0))
+ {
+ si->ch[ch].gran[gr].region0_count = 8; /* MI 9; */
+ si->ch[ch].gran[gr].region1_count = 12;
+ }
+ else
+ {
+ si->ch[ch].gran[gr].region0_count = 7; /* MI 8; */
+ si->ch[ch].gran[gr].region1_count = 13;
+ }
+ }
+ else
+ {
+ tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
+
+ si->ch[ch].gran[gr].table_select[0] = (tmp << 10) >> 27; /* 5 */;
+ si->ch[ch].gran[gr].table_select[1] = (tmp << 15) >> 27; /* 5 */;
+ si->ch[ch].gran[gr].table_select[2] = (tmp << 20) >> 27; /* 5 */;
+
+ si->ch[ch].gran[gr].region0_count = (tmp << 25) >> 28; /* 4 */;
+ si->ch[ch].gran[gr].region1_count = (tmp << 29) >> 29; /* 3 */;
+
+ si->ch[ch].gran[gr].block_type = 0;
+ }
+
+ tmp = getbits_crc(inputStream, 3, crc, info->error_protection);
+ si->ch[ch].gran[gr].preflag = (tmp << 29) >> 31; /* 1 */
+ si->ch[ch].gran[gr].scalefac_scale = (tmp << 30) >> 31; /* 1 */
+ si->ch[ch].gran[gr].count1table_select = tmp & 1; /* 1 */
+ }
+ }
+ }
+ else /* Layer 3 LSF */
+ {
+ si->main_data_begin = getbits_crc(inputStream, 8, crc, info->error_protection);
+ si->private_bits = getbits_crc(inputStream, stereo, crc, info->error_protection);
+
+ for (ch = 0; ch < stereo; ch++)
+ {
+ tmp = getbits_crc(inputStream, 21, crc, info->error_protection);
+ si->ch[ch].gran[0].part2_3_length = (tmp << 11) >> 20; /* 12 */
+ si->ch[ch].gran[0].big_values = (tmp << 23) >> 23; /* 9 */
+
+ tmp = getbits_crc(inputStream, 18, crc, info->error_protection);
+ si->ch[ch].gran[0].global_gain = ((tmp << 14) >> 24) - 210; /* 8 */
+ si->ch[ch].gran[0].scalefac_compress = (tmp << 22) >> 23; /* 9 */
+ si->ch[ch].gran[0].window_switching_flag = tmp & 1; /* 1 */
+
+ if (si->ch[ch].gran[0].window_switching_flag)
+ {
+
+ tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
+
+ si->ch[ch].gran[0].block_type = (tmp << 10) >> 30; /* 2 */;
+ si->ch[ch].gran[0].mixed_block_flag = (tmp << 12) >> 31; /* 1 */;
+
+ si->ch[ch].gran[0].table_select[0] = (tmp << 13) >> 27; /* 5 */;
+ si->ch[ch].gran[0].table_select[1] = (tmp << 18) >> 27; /* 5 */;
+
+ si->ch[ch].gran[0].subblock_gain[0] = (tmp << 23) >> 29; /* 3 */;
+ si->ch[ch].gran[0].subblock_gain[1] = (tmp << 26) >> 29; /* 3 */;
+ si->ch[ch].gran[0].subblock_gain[2] = (tmp << 29) >> 29; /* 3 */;
+
+ /* Set region_count parameters since they are implicit in this case. */
+
+ if (si->ch[ch].gran[0].block_type == 0)
+ {
+ return(SIDE_INFO_ERROR);
+ }
+ else if ((si->ch[ch].gran[0].block_type == 2)
+ && (si->ch[ch].gran[0].mixed_block_flag == 0))
+ {
+ si->ch[ch].gran[0].region0_count = 8; /* MI 9; */
+ si->ch[ch].gran[0].region1_count = 12;
+ }
+ else
+ {
+ si->ch[ch].gran[0].region0_count = 7; /* MI 8; */
+ si->ch[ch].gran[0].region1_count = 13;
+ }
+ }
+ else
+ {
+ tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
+
+ si->ch[ch].gran[0].table_select[0] = (tmp << 10) >> 27; /* 5 */;
+ si->ch[ch].gran[0].table_select[1] = (tmp << 15) >> 27; /* 5 */;
+ si->ch[ch].gran[0].table_select[2] = (tmp << 20) >> 27; /* 5 */;
+
+ si->ch[ch].gran[0].region0_count = (tmp << 25) >> 28; /* 4 */;
+ si->ch[ch].gran[0].region1_count = (tmp << 29) >> 29; /* 3 */;
+
+ si->ch[ch].gran[0].block_type = 0;
+ }
+
+ tmp = getbits_crc(inputStream, 2, crc, info->error_protection);
+ si->ch[ch].gran[0].scalefac_scale = tmp >> 1; /* 1 */
+ si->ch[ch].gran[0].count1table_select = tmp & 1; /* 1 */
+
+ }
+ }
+ return (NO_DECODING_ERROR);
+}
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.h
new file mode 100644
index 0000000..2d6ccd8
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.h
@@ -0,0 +1,102 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_get_side_info.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_GET_SIDE_INFO_H
+#define PVMP3_GET_SIDE_INFO_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_audio_type_defs.h"
+#include "s_mp3bits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ ERROR_CODE pvmp3_get_side_info(tmp3Bits *inputStream,
+ mp3SideInfo *si,
+ mp3Header *info,
+ uint32 *crc);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp
new file mode 100644
index 0000000..8ff7953
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.cpp
@@ -0,0 +1,257 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_getbits.cpp
+
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ tmp3Bits *inputStream, structure holding the input stream parameters
+ int32 neededBits number of bits to read from the bit stream
+
+ Outputs:
+
+ word parsed from teh bitstream, with size neededBits-bits,
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_getbits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+uint32 getNbits(tmp3Bits *ptBitStream,
+ int32 neededBits) /* number of bits to read from the bitstream (up to 25) */
+{
+
+ uint32 offset;
+ uint32 bitIndex;
+ uint8 Elem; /* Needs to be same type as pInput->pBuffer */
+ uint8 Elem1;
+ uint8 Elem2;
+ uint8 Elem3;
+ uint32 returnValue = 0;
+
+ if (!neededBits)
+ {
+ return (returnValue);
+ }
+
+ offset = (ptBitStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
+
+ Elem = *(ptBitStream->pBuffer + module(offset , BUFSIZE));
+ Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+ Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
+ Elem3 = *(ptBitStream->pBuffer + module(offset + 3, BUFSIZE));
+
+
+ returnValue = (((uint32)(Elem)) << 24) |
+ (((uint32)(Elem1)) << 16) |
+ (((uint32)(Elem2)) << 8) |
+ ((uint32)(Elem3));
+
+ /* Remove extra high bits by shifting up */
+ bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
+
+ /* This line is faster than to mask off the high bits. */
+ returnValue <<= bitIndex;
+
+ /* Move the field down. */
+ returnValue >>= (32 - neededBits);
+
+ ptBitStream->usedBits += neededBits;
+
+ return (returnValue);
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+uint16 getUpTo9bits(tmp3Bits *ptBitStream,
+ int32 neededBits) /* number of bits to read from the bit stream 2 to 9 */
+{
+
+ uint32 offset;
+ uint32 bitIndex;
+ uint8 Elem; /* Needs to be same type as pInput->pBuffer */
+ uint8 Elem1;
+ uint16 returnValue;
+
+ offset = (ptBitStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
+
+ Elem = *(ptBitStream->pBuffer + module(offset , BUFSIZE));
+ Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+
+
+ returnValue = (((uint16)(Elem)) << 8) |
+ ((uint16)(Elem1));
+
+ /* Remove extra high bits by shifting up */
+ bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
+
+ ptBitStream->usedBits += neededBits;
+ /* This line is faster than to mask off the high bits. */
+ returnValue = (returnValue << (bitIndex));
+
+ /* Move the field down. */
+
+ return (uint16)(returnValue >> (16 - neededBits));
+
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+uint32 getUpTo17bits(tmp3Bits *ptBitStream,
+ int32 neededBits) /* number of bits to read from the bit stream 2 to 8 */
+{
+
+ uint32 offset;
+ uint32 bitIndex;
+ uint8 Elem; /* Needs to be same type as pInput->pBuffer */
+ uint8 Elem1;
+ uint8 Elem2;
+ uint32 returnValue;
+
+ offset = (ptBitStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
+
+ Elem = *(ptBitStream->pBuffer + module(offset , BUFSIZE));
+ Elem1 = *(ptBitStream->pBuffer + module(offset + 1, BUFSIZE));
+ Elem2 = *(ptBitStream->pBuffer + module(offset + 2, BUFSIZE));
+
+
+ returnValue = (((uint32)(Elem)) << 16) |
+ (((uint32)(Elem1)) << 8) |
+ ((uint32)(Elem2));
+
+ /* Remove extra high bits by shifting up */
+ bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
+
+ ptBitStream->usedBits += neededBits;
+ /* This line is faster than to mask off the high bits. */
+ returnValue = 0xFFFFFF & (returnValue << (bitIndex));
+
+ /* Move the field down. */
+
+ return (uint32)(returnValue >> (24 - neededBits));
+
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+uint8 get1bit(tmp3Bits *ptBitStream) /* number of bits to read from the bit stream */
+{
+
+ uint32 offset;
+ uint32 bitIndex;
+ uint8 returnValue;
+
+ offset = (ptBitStream->usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
+
+ returnValue = *(ptBitStream->pBuffer + module(offset , BUFSIZE));
+
+ /* Remove extra high bits by shifting up */
+ bitIndex = module(ptBitStream->usedBits, INBUF_BIT_WIDTH);
+ ptBitStream->usedBits++;
+
+ /* This line is faster than to mask off the high bits. */
+ returnValue = (returnValue << (bitIndex));
+
+ return (uint8)(returnValue >> 7);
+
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h
new file mode 100644
index 0000000..b058b00
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_getbits.h
@@ -0,0 +1,112 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_getbits.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_GETBITS_H
+#define PVMP3_GETBITS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_dec_defs.h"
+#include "s_mp3bits.h"
+#include "pvmp3_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define INBUF_ARRAY_INDEX_SHIFT (3)
+#define INBUF_BIT_WIDTH (1<<(INBUF_ARRAY_INDEX_SHIFT))
+#define INBUF_BIT_MODULO_MASK ((INBUF_BIT_WIDTH)-1)
+
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ uint32 getNbits(tmp3Bits *pMainData,
+ int32 neededBits);
+
+ uint16 getUpTo9bits(tmp3Bits *pMainData,
+ int32 neededBits);
+
+ uint32 getUpTo17bits(tmp3Bits *pMainData,
+ int32 neededBits);
+
+ uint8 get1bit(tmp3Bits *pMainData);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp
new file mode 100644
index 0000000..5d58cd2
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp
@@ -0,0 +1,304 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_huffman_decoding.cpp
+
+ Funtions:
+ pvmp3_huffman_quad_decoding
+ pvmp3_huffman_pair_decoding
+ pvmp3_huffman_pair_decoding_linbits
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ struct huffcodetab *h, pointer to huffman code record
+ int32 *x, returns decoded x value
+ int32 *y, returns decoded y value
+ int32 *v, returns decoded v value (only in quad function)
+ int32 *w, returns decoded w value (only in quad function)
+ tbits *pMainData bit stream
+
+ Outputs:
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ These functions are used to decode huffman codewords from the input
+ bitstream using combined binary search and look-up table approach.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_dec_defs.h"
+#include "pv_mp3_huffman.h"
+#include "pvmp3_getbits.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void pvmp3_huffman_quad_decoding(struct huffcodetab *h,
+ int32 *is,
+ tmp3Bits *pMainData)
+{
+
+ int32 x;
+ int32 y;
+ int32 v;
+ int32 w;
+
+ y = (*h->pdec_huff_tab)(pMainData);
+
+
+ if (y)
+ {
+ v = (y >> 3);
+
+ if (v)
+ {
+ if (get1bit(pMainData))
+ {
+ v = -v;
+ }
+ }
+ w = (y >> 2) & 1;
+ if (w)
+ {
+ if (get1bit(pMainData))
+ {
+ w = -w;
+ }
+ }
+ x = (y >> 1) & 1;
+ if (x)
+ {
+ if (get1bit(pMainData))
+ {
+ x = -x;
+ }
+ }
+ y = y & 1;
+ if (y)
+ {
+ if (get1bit(pMainData))
+ {
+ y = -y;
+ }
+ }
+
+ }
+ else
+ {
+ v = 0;
+ w = 0;
+ x = 0;
+
+ }
+
+ *is = v;
+ *(is + 1) = w;
+ *(is + 2) = x;
+ *(is + 3) = y;
+
+}
+
+
+
+void pvmp3_huffman_pair_decoding(struct huffcodetab *h, /* pointer to huffman code record */
+ int32 *is,
+ tmp3Bits *pMainData)
+{
+ /* Lookup in Huffman table. */
+ int32 x;
+ int32 y;
+
+ uint16 cw = (*h->pdec_huff_tab)(pMainData);
+
+ /* Process sign and escape encodings for dual tables. */
+
+
+ if (cw)
+ {
+ x = cw >> 4;
+
+ if (x)
+ {
+ if (get1bit(pMainData))
+ {
+ x = -x;
+ }
+ y = cw & 0xf;
+ if (y && get1bit(pMainData))
+ {
+ y = -y;
+ }
+
+ }
+ else
+ {
+ y = cw & 0xf;
+ if (get1bit(pMainData))
+ {
+ y = -y;
+ }
+ }
+
+ *is = x;
+ *(is + 1) = y;
+ }
+ else
+ {
+ *is = 0;
+ *(is + 1) = 0;
+ }
+
+
+
+}
+
+
+
+
+void pvmp3_huffman_pair_decoding_linbits(struct huffcodetab *h, /* pointer to huffman code record */
+ int32 *is,
+ tmp3Bits *pMainData)
+{
+ int32 x;
+ int32 y;
+
+ uint16 cw;
+ /* Lookup in Huffman table. */
+
+
+ cw = (*h->pdec_huff_tab)(pMainData);
+ x = cw >> 4;
+
+ /* Process sign and escape encodings for dual tables. */
+
+
+ if (15 == (uint32)x)
+ {
+ int32 tmp = getUpTo17bits(pMainData, (h->linbits + 1));
+ x += tmp >> 1;
+ if (tmp&1)
+ {
+ x = -x;
+ }
+ }
+ else if (x)
+ {
+ if (get1bit(pMainData))
+ {
+ x = -x;
+ }
+ }
+
+ y = cw & 0xf;
+ if (15 == (uint32)y)
+ {
+ int32 tmp = getUpTo17bits(pMainData, (h->linbits + 1));
+ y += tmp >> 1;
+ if (tmp&1)
+ {
+ y = -y;
+ }
+ }
+ else if (y)
+ {
+ if (get1bit(pMainData))
+ {
+ y = -y;
+ }
+ }
+
+ *is = x;
+ *(is + 1) = y;
+
+}
+
+
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp
new file mode 100644
index 0000000..ff815dc
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp
@@ -0,0 +1,328 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_huffman_decoding.cpp
+
+ Funtions:
+ pvmp3_huffman_quad_decoding
+ pvmp3_huffman_pair_decoding
+ pvmp3_huffman_pair_decoding_linbits
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+ int32 is[],
+ granuleInfo *grInfo, information for the given channel and granule
+ tmp3dec_file *pVars, decoder state structure
+ int32 part2_start, index to beginning of part 2 data
+ mp3Header *info mp3 header info
+
+ Outputs:
+ int32 is[], uncompressed data
+
+ Return:
+ non zero frequency lines
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ These functions are used to decode huffman codewords from the input
+ bitstream using combined binary search and look-up table approach.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_mp3_huffman.h"
+#include "s_mp3bits.h"
+#include "mp3_mem_funcs.h"
+#include "pvmp3_tables.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+int32 pvmp3_huffman_parsing(int32 is[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ granuleInfo *grInfo,
+ tmp3dec_file *pVars,
+ int32 part2_start,
+ mp3Header *info)
+
+
+{
+ int32 i;
+ int32 region1Start;
+ int32 region2Start;
+ int32 sfreq;
+ uint32 grBits;
+ void(*pt_huff)(struct huffcodetab *, int32 *, tmp3Bits *);
+ struct huffcodetab *h;
+
+ tmp3Bits *pMainData = &pVars->mainDataStream;
+
+
+ /*int32 bt = (*si).ch[ch].gr[gr].window_switching_flag && ((*si).ch[ch].gr[gr].block_type == 2);*/
+
+ sfreq = info->sampling_frequency + info->version_x + (info->version_x << 1);
+
+ /* Find region boundary for short block case. */
+
+
+ if ((grInfo->window_switching_flag) && (grInfo->block_type == 2))
+ {
+ if (info->version_x == MPEG_1)
+ {
+ /* Region2. */
+ region1Start = 12;
+ }
+ else
+ {
+ /* Region2. */
+ i = grInfo->region0_count + 1;
+ region1Start = mp3_sfBandIndex[sfreq].s[i/3];
+ }
+
+ region1Start += region1Start << 1;
+ region2Start = 576; /* No Region2 for short block case. */
+ }
+ else
+ { /* Find region boundary for long block case. */
+ i = grInfo->region0_count + 1;
+ region1Start = mp3_sfBandIndex[sfreq].l[i];
+ region2Start = mp3_sfBandIndex[sfreq].l[i + grInfo->region1_count + 1];
+ }
+
+ /* Read bigvalues area. */
+
+
+ if (grInfo->big_values > (FILTERBANK_BANDS*SUBBANDS_NUMBER >> 1))
+ {
+ grInfo->big_values = (FILTERBANK_BANDS * SUBBANDS_NUMBER >> 1);
+ }
+
+ if ((grInfo->big_values << 1) > (uint32)region2Start)
+ {
+ h = &(pVars->ht[grInfo->table_select[0]]);
+ if (h->linbits)
+ {
+ pt_huff = pvmp3_huffman_pair_decoding_linbits;
+ }
+ else
+ {
+ pt_huff = pvmp3_huffman_pair_decoding;
+ }
+
+ for (i = 0; i < region1Start; i += 2)
+ {
+ (*pt_huff)(h, &is[i], pMainData);
+ }
+
+ h = &(pVars->ht[grInfo->table_select[1]]);
+ if (h->linbits)
+ {
+ pt_huff = pvmp3_huffman_pair_decoding_linbits;
+ }
+ else
+ {
+ pt_huff = pvmp3_huffman_pair_decoding;
+ }
+
+ for (; i < region2Start; i += 2)
+ {
+ (*pt_huff)(h, &is[i], pMainData);
+ }
+
+ h = &(pVars->ht[grInfo->table_select[2]]);
+ if (h->linbits)
+ {
+ pt_huff = pvmp3_huffman_pair_decoding_linbits;
+ }
+ else
+ {
+ pt_huff = pvmp3_huffman_pair_decoding;
+ }
+
+ for (; (uint32)i < (grInfo->big_values << 1); i += 2)
+ {
+ (*pt_huff)(h, &is[i], pMainData);
+ }
+ }
+ else if ((grInfo->big_values << 1) > (uint32)region1Start)
+ {
+ h = &(pVars->ht[grInfo->table_select[0]]);
+ if (h->linbits)
+ {
+ pt_huff = pvmp3_huffman_pair_decoding_linbits;
+ }
+ else
+ {
+ pt_huff = pvmp3_huffman_pair_decoding;
+ }
+ for (i = 0; i < region1Start; i += 2)
+ {
+ (*pt_huff)(h, &is[i], pMainData);
+ }
+
+ h = &(pVars->ht[grInfo->table_select[1]]);
+ if (h->linbits)
+ {
+ pt_huff = pvmp3_huffman_pair_decoding_linbits;
+ }
+ else
+ {
+ pt_huff = pvmp3_huffman_pair_decoding;
+ }
+ for (; (uint32)i < (grInfo->big_values << 1); i += 2)
+ {
+ (*pt_huff)(h, &is[i], pMainData);
+ }
+ }
+ else
+ {
+ h = &(pVars->ht[grInfo->table_select[0]]);
+ if (h->linbits)
+ {
+ pt_huff = pvmp3_huffman_pair_decoding_linbits;
+ }
+ else
+ {
+ pt_huff = pvmp3_huffman_pair_decoding;
+ }
+
+ for (i = 0; (uint32)i < (grInfo->big_values << 1); i += 2)
+ {
+ (*pt_huff)(h, &is[i], pMainData);
+ }
+ }
+
+
+
+ /* Read count1 area. */
+ h = &(pVars->ht[grInfo->count1table_select+32]);
+
+ grBits = part2_start + grInfo->part2_3_length;
+
+ while ((pMainData->usedBits < grBits) &&
+ (i < FILTERBANK_BANDS*SUBBANDS_NUMBER - 4))
+ {
+ pvmp3_huffman_quad_decoding(h, &is[i], pMainData);
+ i += 4;
+ }
+
+ if ((pMainData->usedBits < grBits) &&
+ (i < FILTERBANK_BANDS*SUBBANDS_NUMBER))
+ {
+ pvmp3_huffman_quad_decoding(h, &is[i], pMainData);
+ i += 4;
+
+ if ((i - 2) >= FILTERBANK_BANDS*SUBBANDS_NUMBER)
+ {
+ i -= 2;
+ is[i] = 0;
+ is[(i+1)] = 0;
+ }
+ }
+
+ if (pMainData->usedBits > grBits)
+ {
+ i -= 4;
+
+ if (i < 0 || i > FILTERBANK_BANDS*SUBBANDS_NUMBER - 4)
+ {
+ /* illegal parameters may cause invalid access, set i to 0 */
+ i = 0;
+ }
+
+ is[i] = 0;
+ is[(i+1)] = 0;
+ is[(i+2)] = 0;
+ is[(i+3)] = 0;
+
+ }
+
+ pMainData->usedBits = grBits;
+
+ return (i);
+
+}
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_imdct_synth.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_imdct_synth.cpp
new file mode 100644
index 0000000..11961d1
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_imdct_synth.cpp
@@ -0,0 +1,376 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_imdct_synth.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Input
+ int32 in[], Pointer to spec values of current channel
+ int32 overlap[], Pointer to overlap values of current channel
+ uint32 blk_type, Block type
+ int16 mx_band, In case of mixed blocks, # of bands with long
+ blocks (2 or 4) else 0
+ int32 *Scratch_mem
+ Returns
+
+ int32 in[],
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ The frequency lines are preprocessed by the "alias reduction" scheme
+ and fed into the IMDCT matrix, each 18 into one transform block.
+ The first half of the output values are added to the stored overlap
+ values from the last block. These values are new output values and
+ are input values for the polyphase filterbank. The second half of the
+ output values is stored for overlap with the next data granule.
+ The number of windowed samples is 12 for short blocks, and 36 for long
+ blocks
+
+Windowing
+
+ Depending on window_switching_flag[gr][ch], block_type[gr][ch] and
+ mixed_block_flag[gr][ch] different shapes of windows are used.
+ normal window
+ start window
+ stop window
+ short windows
+ Each of the three short blocks is windowed separately.
+ The windowed short blocks must be overlapped and concatenated.
+
+Overlapping and adding with previous block
+
+ The first half (18 values) of the current block (36 values) has to be
+ overlapped with the second half of the previous block. The second half
+ of the current block has to be stored for overlapping with the next block
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_imdct_synth.h"
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_mdct_18.h"
+#include "pvmp3_mdct_6.h"
+#include "mp3_mem_funcs.h"
+
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define LONG 0
+#define START 1
+#define SHORT 2
+#define STOP 3
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+/*
+ * sin(pi/36*(k+0.5)),k=0..35
+ */
+
+const int32 normal_win[36] =
+{
+ Qfmt_31(0.08723877473068f), Qfmt_31(0.26105238444010f), Qfmt_31(0.43287922787620f),
+ Qfmt_31(0.60141159900854f), Qfmt_31(0.76536686473018f), Qfmt_31(0.92349722647006f),
+ Qfmt_31(0.53729960834682f), Qfmt_31(0.60876142900872f), Qfmt_31(0.67559020761566f),
+ Qfmt_31(-0.73727733681012f), Qfmt_31(-0.79335334029124f), Qfmt_31(0.84339144581289f),
+ Qfmt_31(0.88701083317822f), Qfmt_31(0.92387953251129f), Qfmt_31(-0.95371695074823f),
+ Qfmt_31(-0.97629600711993f), Qfmt_31(-0.99144486137381f), Qfmt_31(-0.99904822158186f),
+ Qfmt_31(0.99904822158186f), Qfmt_31(0.99144486137381f), Qfmt_31(0.97629600711993f),
+ Qfmt_31(0.95371695074823f), Qfmt_31(0.92387953251129f), Qfmt_31(0.88701083317822f),
+ Qfmt_31(0.84339144581289f), Qfmt_31(0.79335334029124f), Qfmt_31(0.73727733681012f),
+ Qfmt_31(0.67559020761566f), Qfmt_31(0.60876142900872f), Qfmt_31(0.53729960834682f),
+ Qfmt_31(0.46174861323503f), Qfmt_31(0.38268343236509f), Qfmt_31(0.30070579950427f),
+ Qfmt_31(0.21643961393810f), Qfmt_31(0.13052619222005f), Qfmt_31(0.04361938736534f)
+};
+
+
+const int32 start_win[36] =
+{
+ /* k=0..17 sin(pi/36*(k+0.5)), */
+ Qfmt_31(0.08723877473068f), Qfmt_31(0.26105238444010f), Qfmt_31(0.43287922787620f),
+ Qfmt_31(0.60141159900854f), Qfmt_31(0.76536686473018f), Qfmt_31(0.92349722647006f),
+ Qfmt_31(0.53729960834682f), Qfmt_31(0.60876142900872f), Qfmt_31(0.67559020761566f),
+ Qfmt_31(-0.73727733681012f), Qfmt_31(-0.79335334029124f), Qfmt_31(0.84339144581289f),
+ Qfmt_31(0.88701083317822f), Qfmt_31(0.92387953251129f), Qfmt_31(-0.95371695074823f),
+ Qfmt_31(-0.97629600711993f), Qfmt_31(-0.99144486137381f), Qfmt_31(-0.99904822158186f),
+
+ Qfmt_31(0.99999990000000f), Qfmt_31(0.99999990000000f), Qfmt_31(0.99999990000000f),
+ Qfmt_31(0.99999990000000f), Qfmt_31(0.99999990000000f), Qfmt_31(0.99999990000000f),
+ /* k=24..29; sin(pi/12*(k-18+0.5)) */
+ Qfmt_31(0.99144486137381f), Qfmt_31(0.92387953251129f), Qfmt_31(0.79335334029124f),
+ Qfmt_31(0.60876142900872f), Qfmt_31(0.38268343236509f), Qfmt_31(0.13052619222005f),
+
+ Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f),
+ Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f)
+};
+
+
+const int32 stop_win[36] =
+{
+ Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f),
+ Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f), Qfmt_31(0.00000000000000f),
+ /* k=6..11; sin(pi/12*(k-6+0.5)) */
+ Qfmt_31(0.13052619222005f), Qfmt_31(0.38268343236509f), Qfmt_31(0.60876142900872f),
+ Qfmt_31(-0.79335334029124f), Qfmt_31(-0.92387953251129f), Qfmt_31(0.99144486137381f),
+
+ Qfmt_31(0.99999990000000f), Qfmt_31(0.99999990000000f), Qfmt_31(-0.99999990000000f),
+ Qfmt_31(-0.99999990000000f), Qfmt_31(-0.99999990000000f), Qfmt_31(-0.99999990000000f),
+ /* k=18..35 sin(pi/36*(k+0.5)), */
+ Qfmt_31(0.99904822158186f), Qfmt_31(0.99144486137381f), Qfmt_31(0.97629600711993f),
+ Qfmt_31(0.95371695074823f), Qfmt_31(0.92387953251129f), Qfmt_31(0.88701083317822f),
+ Qfmt_31(0.84339144581289f), Qfmt_31(0.79335334029124f), Qfmt_31(0.73727733681012f),
+ Qfmt_31(0.67559020761566f), Qfmt_31(0.60876142900872f), Qfmt_31(0.53729960834682f),
+ Qfmt_31(0.46174861323503f), Qfmt_31(0.38268343236509f), Qfmt_31(0.30070579950427f),
+ Qfmt_31(0.21643961393810f), Qfmt_31(0.13052619222005f), Qfmt_31(0.04361938736534f)
+};
+
+
+const int32 short_win[12] =
+{
+ /* k=0..11; sin(pi/12*(k+0.5)) */
+ Qfmt_31(0.13052619222005f), Qfmt_31(0.38268343236509f), Qfmt_31(0.60876142900872f),
+ Qfmt_31(0.79335334029124f), Qfmt_31(0.92387953251129f), Qfmt_31(0.99144486137381f),
+ Qfmt_31(0.99144486137381f), Qfmt_31(0.92387953251129f), Qfmt_31(0.79335334029124f),
+ Qfmt_31(0.60876142900872f), Qfmt_31(0.38268343236509f), Qfmt_31(0.13052619222005f),
+};
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_imdct_synth(int32 in[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 overlap[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ uint32 blk_type,
+ int16 mx_band,
+ int32 used_freq_lines,
+ int32 *Scratch_mem)
+{
+
+ int32 band;
+ int32 bands2process = used_freq_lines + 2;
+
+ if (bands2process > SUBBANDS_NUMBER)
+ {
+ bands2process = SUBBANDS_NUMBER; /* default */
+ }
+
+
+ /*
+ * in case of mx_poly_band> 0, do
+ * long transforms
+ */
+
+
+ for (band = 0; band < bands2process; band++)
+ {
+ uint32 current_blk_type = (band < mx_band) ? LONG : blk_type;
+
+ int32 * out = in + (band * FILTERBANK_BANDS);
+ int32 * history = overlap + (band * FILTERBANK_BANDS);
+
+ switch (current_blk_type)
+ {
+ case LONG:
+
+ pvmp3_mdct_18(out, history, normal_win);
+
+ break;
+
+ case START:
+
+ pvmp3_mdct_18(out, history, start_win);
+
+ break;
+
+ case STOP:
+
+ pvmp3_mdct_18(out, history, stop_win);
+
+ break;
+
+ case SHORT:
+ {
+ int32 *tmp_prev_ovr = &Scratch_mem[FILTERBANK_BANDS];
+ int32 i;
+
+ for (i = 0; i < 6; i++)
+ {
+ Scratch_mem[i ] = out[(i*3)];
+ Scratch_mem[6 +i] = out[(i*3) + 1];
+ Scratch_mem[12 +i] = out[(i*3) + 2];
+ }
+
+ pvmp3_mdct_6(&Scratch_mem[ 0], &tmp_prev_ovr[ 0]);
+ pvmp3_mdct_6(&Scratch_mem[ 6], &tmp_prev_ovr[ 6]);
+ pvmp3_mdct_6(&Scratch_mem[12], &tmp_prev_ovr[12]);
+
+ for (i = 0; i < 6; i++)
+ {
+ int32 temp = history[i];
+ /* next iteration overlap */
+ history[i] = fxp_mul32_Q32(tmp_prev_ovr[ 6+i] << 1, short_win[6+i]);
+ history[i] += fxp_mul32_Q32(Scratch_mem[12+i] << 1, short_win[ i]);
+ out[i] = temp;
+ }
+
+ for (i = 0; i < 6; i++)
+ {
+ out[i+6] = fxp_mul32_Q32(Scratch_mem[i] << 1, short_win[i]);
+ out[i+6] += history[i+6];
+ /* next iteration overlap */
+ history[i+6] = fxp_mul32_Q32(tmp_prev_ovr[12+i] << 1, short_win[6+i]);
+
+ }
+ for (i = 0; i < 6; i++)
+ {
+ out[i+12] = fxp_mul32_Q32(tmp_prev_ovr[ i] << 1, short_win[6+i]);
+ out[i+12] += fxp_mul32_Q32(Scratch_mem[6+i] << 1, short_win[ i]);
+ out[i+12] += history[i+12];
+ history[12+i] = 0;
+ }
+ }
+
+ break;
+ }
+
+ /*
+ * Compensation for frequency inversion of polyphase filterbank
+ * every odd time sample of every odd odd subband is mulitplied by -1 before
+ * processing by the polyphase filter
+ */
+
+ if (band & 1)
+ {
+ for (int32 slot = 1; slot < FILTERBANK_BANDS; slot += 6)
+ {
+ int32 temp1 = out[slot ];
+ int32 temp2 = out[slot+2];
+ int32 temp3 = out[slot+4];
+ out[slot ] = -temp1;
+ out[slot+2] = -temp2;
+ out[slot+4] = -temp3;
+ }
+ }
+ }
+
+
+ for (band = bands2process; band < SUBBANDS_NUMBER; band++)
+ {
+ int32 * out = in + (band * FILTERBANK_BANDS);
+ int32 * history = overlap + (band * FILTERBANK_BANDS);
+ int32 slot;
+
+ if (band & 1)
+ {
+ for (slot = 0; slot < FILTERBANK_BANDS; slot += 6)
+ {
+ int32 temp1 = history[slot ];
+ int32 temp2 = history[slot+1];
+ int32 temp3 = history[slot+2];
+ out[slot ] = temp1;
+ out[slot+1] = -temp2;
+ out[slot+2] = temp3;
+
+ temp1 = history[slot+3];
+ temp2 = history[slot+4];
+ temp3 = history[slot+5];
+ out[slot+3] = -temp1;
+ out[slot+4] = temp2;
+ out[slot+5] = -temp3;
+ }
+ }
+ else
+ {
+ for (slot = 0; slot < FILTERBANK_BANDS; slot += 3)
+ {
+ int32 temp1 = history[slot ];
+ int32 temp2 = history[slot+1];
+ int32 temp3 = history[slot+2];
+ out[slot ] = temp1;
+ out[slot+1] = temp2;
+ out[slot+2] = temp3;
+ }
+ }
+
+ pv_memset(history, 0, FILTERBANK_BANDS*sizeof(*overlap));
+ }
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_imdct_synth.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_imdct_synth.h
new file mode 100644
index 0000000..ea42e49
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_imdct_synth.h
@@ -0,0 +1,102 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_imdct_synth.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+*/
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+
+#ifndef PVMP3_IMDCT_SYNTH_H
+#define PVMP3_IMDCT_SYNTH_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES AND SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void pvmp3_imdct_synth(int32 in[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 overlap[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ uint32 blk_type,
+ int16 mx_band,
+ int32 used_freq_lines,
+ int32 *Scratch_mem);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_18.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_18.cpp
new file mode 100644
index 0000000..09a735b
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_18.cpp
@@ -0,0 +1,289 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: mdct_18.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+ int32 vec[], input vector of length 18
+ int32 *history input for overlap and add, vector updated with
+ next overlap and add values
+ const int32 *window sine window used in the mdct, three types are allowed
+ noraml, start and stop
+Returns
+ none mdct computation in-place
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Returns the mdct of length 18 of the input vector, as well as the overlap
+ vector for next iteration ( on history[])
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+#if ( !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4) && !defined(PV_ARM_V5) && !defined(PV_ARM_V4) )
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_mdct_18.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const int32 cosTerms_dct18[9] =
+{
+ Qfmt(0.50190991877167f), Qfmt(0.51763809020504f), Qfmt(0.55168895948125f),
+ Qfmt(0.61038729438073f), Qfmt(0.70710678118655f), Qfmt(0.87172339781055f),
+ Qfmt(1.18310079157625f), Qfmt(1.93185165257814f), Qfmt(5.73685662283493f)
+};
+
+
+const int32 cosTerms_1_ov_cos_phi[18] =
+{
+
+ Qfmt1(0.50047634258166f), Qfmt1(0.50431448029008f), Qfmt1(0.51213975715725f),
+ Qfmt1(0.52426456257041f), Qfmt1(0.54119610014620f), Qfmt1(0.56369097343317f),
+ Qfmt1(0.59284452371708f), Qfmt1(0.63023620700513f), Qfmt1(0.67817085245463f),
+
+ Qfmt2(0.74009361646113f), Qfmt2(0.82133981585229f), Qfmt2(0.93057949835179f),
+ Qfmt2(1.08284028510010f), Qfmt2(1.30656296487638f), Qfmt2(1.66275476171152f),
+ Qfmt2(2.31011315767265f), Qfmt2(3.83064878777019f), Qfmt2(11.46279281302667f)
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+void pvmp3_mdct_18(int32 vec[], int32 *history, const int32 *window)
+{
+ int32 i;
+ int32 tmp;
+ int32 tmp1;
+ int32 tmp2;
+ int32 tmp3;
+ int32 tmp4;
+
+
+
+ const int32 *pt_cos_split = cosTerms_dct18;
+ const int32 *pt_cos = cosTerms_1_ov_cos_phi;
+ const int32 *pt_cos_x = &cosTerms_1_ov_cos_phi[17];
+ int32 *pt_vec = vec;
+ int32 *pt_vec_o = &vec[17];
+
+
+ for (i = 9; i != 0; i--)
+ {
+ tmp = *(pt_vec);
+ tmp1 = *(pt_vec_o);
+ tmp = fxp_mul32_Q32(tmp << 1, *(pt_cos++));
+ tmp1 = fxp_mul32_Q27(tmp1, *(pt_cos_x--));
+ *(pt_vec++) = tmp + tmp1 ;
+ *(pt_vec_o--) = fxp_mul32_Q28((tmp - tmp1), *(pt_cos_split++));
+ }
+
+
+ pvmp3_dct_9(vec); // Even terms
+ pvmp3_dct_9(&vec[9]); // Odd terms
+
+
+ tmp3 = vec[16]; //
+ vec[16] = vec[ 8];
+ tmp4 = vec[14]; //
+ vec[14] = vec[ 7];
+ tmp = vec[12];
+ vec[12] = vec[ 6];
+ tmp2 = vec[10]; // vec[10]
+ vec[10] = vec[ 5];
+ vec[ 8] = vec[ 4];
+ vec[ 6] = vec[ 3];
+ vec[ 4] = vec[ 2];
+ vec[ 2] = vec[ 1];
+ vec[ 1] = vec[ 9] - tmp2; // vec[9] + vec[10]
+ vec[ 3] = vec[11] - tmp2;
+ vec[ 5] = vec[11] - tmp;
+ vec[ 7] = vec[13] - tmp;
+ vec[ 9] = vec[13] - tmp4;
+ vec[11] = vec[15] - tmp4;
+ vec[13] = vec[15] - tmp3;
+ vec[15] = vec[17] - tmp3;
+
+
+ /* overlap and add */
+
+ tmp2 = vec[0];
+ tmp3 = vec[9];
+
+ for (i = 0; i < 6; i++)
+ {
+ tmp = history[ i];
+ tmp4 = vec[i+10];
+ vec[i+10] = tmp3 + tmp4;
+ tmp1 = vec[i+1];
+ vec[ i] = fxp_mac32_Q32(tmp, (vec[i+10]), window[ i]);
+ tmp3 = tmp4;
+ history[i ] = -(tmp2 + tmp1);
+ tmp2 = tmp1;
+ }
+
+ tmp = history[ 6];
+ tmp4 = vec[16];
+ vec[16] = tmp3 + tmp4;
+ tmp1 = vec[7];
+ vec[ 6] = fxp_mac32_Q32(tmp, vec[16] << 1, window[ i]);
+ tmp = history[ 7];
+ history[6] = -(tmp2 + tmp1);
+ history[7] = -(tmp1 + vec[8]);
+
+ tmp1 = history[ 8];
+ tmp4 = vec[17] + tmp4;
+ vec[ 7] = fxp_mac32_Q32(tmp, tmp4 << 1, window[ 7]);
+ history[8] = -(vec[8] + vec[9]);
+ vec[ 8] = fxp_mac32_Q32(tmp1, vec[17] << 1, window[ 8]);
+
+ tmp = history[9];
+ tmp1 = history[17];
+ tmp2 = history[16];
+ vec[ 9] = fxp_mac32_Q32(tmp, vec[17] << 1, window[ 9]);
+
+ vec[17] = fxp_mac32_Q32(tmp1, vec[10] << 1, window[17]);
+ vec[10] = -vec[ 16];
+ vec[16] = fxp_mac32_Q32(tmp2, vec[11] << 1, window[16]);
+ tmp1 = history[15];
+ tmp2 = history[14];
+ vec[11] = -vec[ 15];
+ vec[15] = fxp_mac32_Q32(tmp1, vec[12] << 1, window[15]);
+ vec[12] = -vec[ 14];
+ vec[14] = fxp_mac32_Q32(tmp2, vec[13] << 1, window[14]);
+
+ tmp = history[13];
+ tmp1 = history[12];
+ tmp2 = history[11];
+ tmp3 = history[10];
+ vec[13] = fxp_mac32_Q32(tmp, vec[12] << 1, window[13]);
+ vec[12] = fxp_mac32_Q32(tmp1, vec[11] << 1, window[12]);
+ vec[11] = fxp_mac32_Q32(tmp2, vec[10] << 1, window[11]);
+ vec[10] = fxp_mac32_Q32(tmp3, tmp4 << 1, window[10]);
+
+
+ /* next iteration overlap */
+
+ tmp1 = history[ 8];
+ tmp3 = history[ 7];
+ tmp2 = history[ 1];
+ tmp = history[ 0];
+ tmp1 <<= 1;
+ tmp3 <<= 1;
+
+ history[ 0] = fxp_mul32_Q32(tmp1, window[18]);
+ history[17] = fxp_mul32_Q32(tmp1, window[35]);
+ history[ 1] = fxp_mul32_Q32(tmp3, window[19]);
+ history[16] = fxp_mul32_Q32(tmp3, window[34]);
+
+ tmp2 <<= 1;
+ tmp <<= 1;
+ history[ 7] = fxp_mul32_Q32(tmp2, window[25]);
+ history[10] = fxp_mul32_Q32(tmp2, window[28]);
+ history[ 8] = fxp_mul32_Q32(tmp, window[26]);
+ history[ 9] = fxp_mul32_Q32(tmp, window[27]);
+
+ tmp1 = history[ 6];
+ tmp3 = history[ 5];
+ tmp4 = history[ 4];
+ tmp2 = history[ 3];
+ tmp = history[ 2];
+
+ tmp1 <<= 1;
+ tmp3 <<= 1;
+ tmp4 <<= 1;
+
+ history[ 2] = fxp_mul32_Q32(tmp1, window[20]);
+ history[15] = fxp_mul32_Q32(tmp1, window[33]);
+ history[ 3] = fxp_mul32_Q32(tmp3, window[21]);
+ history[14] = fxp_mul32_Q32(tmp3, window[32]);
+ history[ 4] = fxp_mul32_Q32(tmp4, window[22]);
+ history[13] = fxp_mul32_Q32(tmp4, window[31]);
+ tmp2 <<= 1;
+ tmp <<= 1;
+ history[ 5] = fxp_mul32_Q32(tmp2, window[23]);
+ history[12] = fxp_mul32_Q32(tmp2, window[30]);
+ history[ 6] = fxp_mul32_Q32(tmp, window[24]);
+ history[11] = fxp_mul32_Q32(tmp, window[29]);
+}
+
+#endif // If not assembly
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_18.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_18.h
new file mode 100644
index 0000000..e497aee
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_18.h
@@ -0,0 +1,109 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Pathname: ./include/pvmp3_mdct_18.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines function mdct_18, dct9, mdct_6 and dct_6
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef MDCT_18_H
+#define MDCT_18_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define Qfmt(a) (Int32)(a*((Int32)1<<28) )
+#define Qfmt1(a) (Int32)(a*((Int32)0x7FFFFFFF))
+#define Qfmt2(a) (Int32)(a*((Int32)1<<27))
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void pvmp3_mdct_18(int32 vec[], int32 *history, const int32 *window);
+
+ void pvmp3_dct_9(int32 vec[]);
+
+ void pvmp3_mdct_6(int32 vec[], int32 *overlap);
+
+ void pvmp3_dct_6(int32 vec[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_6.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_6.cpp
new file mode 100644
index 0000000..6a72aad
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_6.cpp
@@ -0,0 +1,165 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+ Filename: mdct_18.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+ int32 vec[], input vector of length 6
+ int32 *history input for overlap and add, vector updated with
+ next overlap and add values
+Returns
+ none mdct computation in-place
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Returns the mdct of length 6 of the input vector, as well as the overlap
+ vector for next iteration ( on history[])
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_mdct_6.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define QFORMAT 29
+#define Qfmt29(a) (int32)(a*((int32)1<<QFORMAT) + (a>=0?0.5F:-0.5F))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+/*
+ * (1./(2*cos((pi/(2*N))*(2*i+1)))), N = 12, i = [0:N/2-1]
+ */
+
+const int32 cosTerms_1_ov_cos_phi_N6[6] =
+{
+
+ Qfmt29(0.50431448029008f), Qfmt29(0.54119610014620f),
+ Qfmt29(0.63023620700513f), Qfmt29(0.82133981585229f),
+ Qfmt29(1.30656296487638f), Qfmt29(3.83064878777019f)
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+void pvmp3_mdct_6(int32 vec[], int32 *history)
+{
+ int32 i;
+ int32 tmp;
+ int32 tmp1;
+ int32 tmp2;
+
+ int32 *pt_vec = vec;
+ int32 *pt_vec_o = vec;
+ const int32 *pt_cos = cosTerms_1_ov_cos_phi_N6;
+
+ for (i = 2; i != 0; i--)
+ {
+ tmp = *(pt_vec++);
+ tmp1 = *(pt_vec++);
+ tmp2 = *(pt_vec++);
+ *(pt_vec_o++) = fxp_mul32_Q29(tmp, *(pt_cos++));
+ *(pt_vec_o++) = fxp_mul32_Q29(tmp1, *(pt_cos++));
+ *(pt_vec_o++) = fxp_mul32_Q29(tmp2, *(pt_cos++));
+ }
+
+
+ pvmp3_dct_6(vec); // Even terms
+
+
+ tmp = -(vec[0] + vec[1]);
+ history[3] = tmp;
+ history[2] = tmp;
+ tmp = -(vec[1] + vec[2]);
+ vec[0] = vec[3] + vec[4];
+ vec[1] = vec[4] + vec[5];
+ history[4] = tmp;
+ history[1] = tmp;
+ tmp = -(vec[2] + vec[3]);
+ vec[4] = -vec[1];
+ history[5] = tmp;
+ history[0] = tmp;
+
+ vec[2] = vec[5];
+ vec[3] = -vec[5];
+ vec[5] = -vec[0];
+
+}
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_6.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_6.h
new file mode 100644
index 0000000..6ba53d7
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_mdct_6.h
@@ -0,0 +1,106 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Pathname: ./include/pvmp3_mdct_6.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines function mdct_18, dct9, mdct_6 and dct_6
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_MDCT_6_H
+#define PVMP3_MDCT_6_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define Qfmt(a) (Int32)(a*((Int32)1<<28) )
+#define Qfmt1(a) (Int32)(a*((Int32)0x7FFFFFFF))
+#define Qfmt2(a) (Int32)(a*((Int32)1<<27))
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ void pvmp3_mdct_6(int32 vec[], int32 *overlap);
+
+ void pvmp3_dct_6(int32 vec[]);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp
new file mode 100644
index 0000000..ee42dc5
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp
@@ -0,0 +1,247 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_mpeg2_get_scale_data.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+ mp3SideInfo *si, side information
+ int32 gr, granule
+ int32 ch, channel
+ mp3Header *info, mp3 header information
+ uint32 *scalefac_buffer,
+ uint32 *scalefac_IIP_buffer,
+ tbits *pMainData bit stream Data
+
+ Returns
+
+ uint32 *scalefac_buffer, acquired scale band data
+ uint32 *scalefac_IIP_buffer, auxiliary scale data
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ get scale data for mpeg2 layer III LSF extension
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_mpeg2_get_scale_data.h"
+#include "pvmp3_getbits.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+const uint32 nr_of_sfb_block[6][3][4] =
+{ {{ 6, 5, 5, 5}, { 9, 9, 9, 9}, { 6, 9, 9, 9}},
+ {{ 6, 5, 7, 3}, { 9, 9, 12, 6}, { 6, 9, 12, 6}},
+ {{11, 10, 0, 0}, { 18, 18, 0, 0}, {15, 18, 0, 0}},
+ {{ 7, 7, 7, 0}, { 12, 12, 12, 0}, { 6, 15, 12, 0}},
+ {{ 6, 6, 6, 3}, { 12, 9, 9, 6}, { 6, 12, 9, 6}},
+ {{ 8, 8, 5, 0}, { 15, 12, 9, 0}, { 6, 18, 9, 0}}
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_mpeg2_get_scale_data(mp3SideInfo *si,
+ int32 gr,
+ int32 ch,
+ mp3Header *info,
+ uint32 *scalefac_buffer,
+ uint32 *scalefac_IIP_buffer,
+ tmp3Bits *pMainData)
+{
+ int16 i;
+ int16 j;
+ int16 k;
+ int16 blocktypenumber = 0;
+ int16 blocknumber = 0;
+
+ granuleInfo *gr_info = &(si->ch[ch].gran[gr]);
+ uint32 scalefac_comp, int_scalefac_comp, new_slen[4];
+
+ scalefac_comp = gr_info->scalefac_compress;
+
+
+
+ if ((((info->mode_ext &1)) && (ch == 1)))
+ {
+ /* intensity_scale = scalefac_comp %2; */
+ int_scalefac_comp = scalefac_comp >> 1;
+
+ if (int_scalefac_comp < 180)
+ {
+ new_slen[0] = int_scalefac_comp / 36;
+ new_slen[1] = (int_scalefac_comp % 36) / 6;
+ new_slen[2] = int_scalefac_comp % 6;
+ blocknumber = 3;
+ }
+ else if (int_scalefac_comp < 244)
+ {
+ int_scalefac_comp -= 180;
+ new_slen[0] = (int_scalefac_comp & 63) >> 4;
+ new_slen[1] = (int_scalefac_comp & 15) >> 2;
+ new_slen[2] = int_scalefac_comp & 3;
+ blocknumber = 4;
+ }
+ else if (int_scalefac_comp <= 255)
+ {
+ int_scalefac_comp -= 244;
+ new_slen[0] = (int_scalefac_comp) / 3;
+ new_slen[1] = (int_scalefac_comp) % 3;
+ new_slen[2] = 0;
+ blocknumber = 5;
+ }
+ new_slen[3] = 0;
+ si->ch[ch].gran[gr].preflag = 0;
+ }
+ else
+ {
+ if (scalefac_comp < 400)
+ {
+ new_slen[0] = (scalefac_comp >> 4) / 5;
+ new_slen[1] = (scalefac_comp >> 4) % 5;
+ new_slen[2] = (scalefac_comp & 15) >> 2 ;
+ new_slen[3] = (scalefac_comp & 3);
+ si->ch[ch].gran[gr].preflag = 0;
+
+ blocknumber = 0;
+ }
+ else if (scalefac_comp < 500)
+ {
+ scalefac_comp -= 400;
+ new_slen[0] = (scalefac_comp >> 2) / 5;
+ new_slen[1] = (scalefac_comp >> 2) % 5;
+ new_slen[2] = scalefac_comp & 3;
+ new_slen[3] = 0;
+ si->ch[ch].gran[gr].preflag = 0;
+ blocknumber = 1;
+ }
+ else if (scalefac_comp < 512)
+ {
+ scalefac_comp -= 500;
+ new_slen[0] = scalefac_comp / 3;
+ new_slen[1] = scalefac_comp % 3;
+ new_slen[2] = 0 ;
+ new_slen[3] = 0;
+ si->ch[ch].gran[gr].preflag = 1;
+ blocknumber = 2;
+ }
+ }
+
+ if (gr_info->block_type == 2)
+ {
+ if (gr_info->mixed_block_flag)
+ {
+ blocktypenumber = 2;
+ }
+ else
+ {
+ blocktypenumber = 1;
+ }
+ }
+
+ k = 0;
+ for (i = 0; i < 4; i++)
+ {
+ if (new_slen[i])
+ {
+ for (j = 0; j < (int16)nr_of_sfb_block[blocknumber][blocktypenumber][i]; j++)
+ {
+ scalefac_buffer[k] = getNbits(pMainData, new_slen[i]);
+ scalefac_IIP_buffer[k] = (1L << new_slen[i]) - 1;
+ k++;
+ }
+ }
+ else
+ {
+ for (j = 0; j < (int16)nr_of_sfb_block[blocknumber][blocktypenumber][i]; j++)
+ {
+ scalefac_buffer[k] = 0;
+ scalefac_IIP_buffer[k] = 0;
+ k++;
+ }
+ }
+ }
+}
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h
new file mode 100644
index 0000000..630ed61
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h
@@ -0,0 +1,105 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_mpeg2_get_scale_data.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_MPEG2_GET_SCALE_DATA_H
+#define PVMP3_MPEG2_GET_SCALE_DATA_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_audio_type_defs.h"
+#include "s_mp3bits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void pvmp3_mpeg2_get_scale_data(mp3SideInfo *si,
+ int32 gr,
+ int32 ch,
+ mp3Header *info,
+ uint32 *scalefac_buffer,
+ uint32 *scalefac_IIP_buffer,
+ tmp3Bits *pMainData);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp
new file mode 100644
index 0000000..e4d29d6
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp
@@ -0,0 +1,202 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_mpeg2_get_scale_factors.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+
+ mp3ScaleFactors *scalefac,
+ mp3SideInfo *si, side information
+ int32 gr, granule
+ int32 ch, channel
+ mp3Header *info, mp3 header information
+ uint32 *scalefac_IIP_buffer, auxiliary scale data
+ tbits *pMainData bit stream Data
+
+ Returns
+
+ III_scalefac_t *scalefac, scale factor
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ get scale factor for mpe2 layer III LSF extension
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_mpeg2_get_scale_factors.h"
+#include "pvmp3_mpeg2_get_scale_data.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_mpeg2_get_scale_factors(mp3ScaleFactors *scalefac,
+ mp3SideInfo *si,
+ int32 gr,
+ int32 ch,
+ mp3Header *info,
+ uint32 *scalefac_IIP_buffer,
+ tmp3Bits *pMainData)
+{
+
+ int32 sfb;
+ int32 k = 0;
+ int32 window;
+ uint32 *scalefac_buffer = &scalefac_IIP_buffer[56];
+
+ granuleInfo *gr_info = &(si->ch[ch].gran[gr]);
+
+ pvmp3_mpeg2_get_scale_data(si,
+ gr,
+ ch,
+ info,
+ (uint32 *)scalefac_buffer,
+ (uint32 *)scalefac_IIP_buffer,
+ pMainData);
+
+
+ if (gr_info->window_switching_flag && (gr_info->block_type == 2))
+ {
+ if (gr_info->mixed_block_flag)
+ {
+ for (sfb = 0; sfb < 6; sfb++)
+ {
+ scalefac->l[sfb] = scalefac_buffer[sfb];
+ }
+
+
+ k = 6;
+ for (sfb = 3; sfb < 12; sfb++)
+ {
+ for (window = 0; window < 3; window++)
+ {
+ scalefac->s[window][sfb] = scalefac_buffer[k];
+ k++;
+ }
+ }
+
+
+ /* adjust position of "illegal position" information in scalefac_IIP_buffer[] */
+ /* in mixed blocks mode for short sfb, move them 3 places up. efs 3002-07-04 */
+ for (sfb = 11; sfb >= 3; sfb--)
+ {
+ scalefac_IIP_buffer[3*sfb + 2] = scalefac_IIP_buffer[3*sfb - 1];
+ scalefac_IIP_buffer[3*sfb + 1] = scalefac_IIP_buffer[3*sfb - 2];
+ scalefac_IIP_buffer[3*sfb ] = scalefac_IIP_buffer[3*sfb - 3];
+
+ }
+ }
+ else
+ { /* SHORT*/
+ for (sfb = 0; sfb < 12; sfb++)
+ {
+ for (window = 0; window < 3; window++)
+ {
+ scalefac->s[window][sfb] = scalefac_buffer[k];
+ k++;
+ }
+ }
+ }
+
+ scalefac->s[0][12] = 0;
+ scalefac->s[1][12] = 0;
+ scalefac->s[2][12] = 0;
+
+ }
+ else
+ { /* LONG types 0,1,3 */
+ for (sfb = 0; sfb < 21; sfb++)
+ {
+ scalefac->l[sfb] = scalefac_buffer[sfb];
+ }
+ scalefac->l[21] = 0;
+ scalefac->l[22] = 0;
+
+ }
+}
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h
new file mode 100644
index 0000000..46d16b3
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h
@@ -0,0 +1,105 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_mpeg2_get_scale_factors.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_MPEG2_GET_SCALE_FACTORS_H
+#define PVMP3_MPEG2_GET_SCALE_FACTORS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_audio_type_defs.h"
+#include "s_mp3bits.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void pvmp3_mpeg2_get_scale_factors(mp3ScaleFactors *scalefac,
+ mp3SideInfo *si,
+ int32 gr,
+ int32 ch,
+ mp3Header *info,
+ uint32 *scalefac_IIP_buffer,
+ tmp3Bits *pMainData);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp
new file mode 100644
index 0000000..c79062c
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp
@@ -0,0 +1,700 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_mpeg2_stereo_proc.cpp
+
+ Functions:
+
+ pvmp3_st_intensity_ver2
+ pvmp3_mpeg2_stereo_proc
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+
+------------------------------------------------------------------------------
+
+pvmp3_st_intensity_ver2
+
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+
+ int32 xr[], input channel
+ int32 xl[],
+ int32 m, selecting index: io = 2(1/4) (m=0), io = 2(1/8) (m=1)
+ int32 is_pos, index on table is_pos_pow_eitgh_root_of_2
+ int32 Start, Location of first element where stereo intensity is applied
+ int32 Number number of elements affected
+
+ Returns
+
+ int32 xl[], generated stereo channel
+
+
+
+
+------------------------------------------------------------------------------
+
+pvmp3_mpeg2_stereo_proc
+
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+
+ int32 xr[], input channel
+ int32 xl[],
+ mp3ScaleFactors *scalefac, scale factors structure for Right channel
+ granuleInfo *gr_info_l, granule structure for the left channel
+ granuleInfo *gr_info_r, granule structure for the rigth channel
+ uint32 *scalefac_IIP_buffer, auxiliary scale factor vector
+ mp3Header *info mp3 header info
+ Returns
+
+ int32 xl[], generated stereo channel
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ stereo processing for mpeg2 layer III LSF extension
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_mpeg2_stereo_proc.h"
+#include "pvmp3_stereo_proc.h"
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_tables.h"
+#include "mp3_mem_funcs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+#define Q31_fmt(a) (int32(double(0x7FFFFFFF)*a))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+const int32 is_pos_pow_eitgh_root_of_2[8] =
+{
+ /* --- 2^(1/8) ----- */
+ Q31_fmt(1.00000000000000), Q31_fmt(0.91700404320467), Q31_fmt(0.84089641525371),
+ Q31_fmt(0.77110541270397), Q31_fmt(0.70710678118655), Q31_fmt(0.64841977732550),
+ Q31_fmt(0.59460355750136), Q31_fmt(0.54525386633263)
+};
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_st_intensity_ver2(int32 xr[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 xl[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 m,
+ int32 is_pos,
+ int32 Start,
+ int32 Number)
+{
+ int32 k[2];
+
+ /* pow(io, ((is_pos + 1)>>1)); io = 2(1/4) (m=0), io = 2(1/8) (m=1) */
+ k[0] = is_pos_pow_eitgh_root_of_2[((is_pos+1)&(3+(m<<2)))<<(1-m)] >> ((is_pos + 1) >> (2 + m));
+ /* pow(io, (is_pos>>1)); io = 2(1/4) (m=0), io = 2(1/8) (m=1) */
+ k[1] = is_pos_pow_eitgh_root_of_2[(is_pos&(3+(m<<2)))<<(1-m)] >> (is_pos >> (2 + m));
+
+
+ int32 *pt_xr = &xr[Start];
+ int32 *pt_xl = &xl[Start];
+
+ if (is_pos == 0) /* 0 < is_pos < 31 */
+ {
+ pv_memcpy(pt_xl, pt_xr, Number*sizeof(*pt_xr));
+ }
+ else if (is_pos & 1)
+ {
+ for (int32 i = Number >> 1; i != 0; i--)
+ {
+ *(pt_xl++) = (*pt_xr);
+ *(pt_xr) = fxp_mul32_Q32((*pt_xr) << 1, k[0]);
+ pt_xr++;
+ *(pt_xl++) = (*pt_xr);
+ *(pt_xr) = fxp_mul32_Q32((*pt_xr) << 1, k[0]);
+ pt_xr++;
+ }
+ if (Number&1)
+ {
+ *(pt_xl) = (*pt_xr);
+ *(pt_xr) = fxp_mul32_Q32((*pt_xr) << 1, k[0]);
+ }
+ }
+ else
+ {
+ for (int32 i = Number >> 1; i != 0; i--)
+ {
+ *(pt_xl++) = fxp_mul32_Q32((*(pt_xr++)) << 1, k[1]);
+ *(pt_xl++) = fxp_mul32_Q32((*(pt_xr++)) << 1, k[1]);
+ }
+ if (Number&1)
+ {
+ *(pt_xl) = fxp_mul32_Q32((*pt_xr) << 1, k[1]);
+ }
+ }
+
+}
+
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void pvmp3_mpeg2_stereo_proc(int32 xr[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 xl[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ mp3ScaleFactors *scalefac_R,
+ granuleInfo *gr_info_l,
+ granuleInfo *gr_info_r,
+ uint32 *scalefac_IIP_buffer,
+ int32 used_freq_lines,
+ mp3Header *info)
+{
+
+ int32 sfreq;
+ int32 sb;
+ int32 ss;
+ int32 sfbNo;
+ int32 sfbStart;
+ int32 sfb;
+ int32 sfbTemp;
+ int32 i;
+ int32 j;
+ int32 io;
+
+
+ int32 i_stereo = (info->mode == MPG_MD_JOINT_STEREO) &&
+ (info->mode_ext & 0x1);
+
+ int32 ms_stereo = (info->mode == MPG_MD_JOINT_STEREO) &&
+ (info->mode_ext & 0x2);
+
+
+ if (i_stereo)
+ {
+ if (gr_info_r->scalefac_compress & 1)
+ {
+ io = 0; /* 2^(-1/4) */
+ }
+ else
+ {
+ io = 1; /* 2^(-1/8) */
+ }
+
+ sfreq = info->version_x + (info->version_x << 1);
+ sfreq += info->sampling_frequency;
+
+ if (gr_info_l->window_switching_flag && (gr_info_l->block_type == 2))
+ {
+ if (gr_info_l->mixed_block_flag)
+ {
+ /*
+ * mixed blocks processing
+ */
+ i = 31;
+ ss = 17;
+ sb = -1;
+
+ while (i >= 0)
+ {
+ if (xl[(i*FILTERBANK_BANDS) + ss])
+ {
+ sb = (i << 4) + (i << 1) + ss;
+ i = -1;
+ }
+ else
+ {
+ ss--;
+ if (ss < 0)
+ {
+ i--;
+ ss = 17;
+ }
+ }
+ } /* now sb is the number of highest line with value != 0 */
+ /* can be between -1 (all lines zero) and 575 (no line zero) */
+
+ if (sb < 36) /* was (sb <= 36) */
+ {
+ /*
+ * mixed blocks processing: intensity bound inside long blocks
+ */
+ /* 1. long blocks up to intensity border: Stereo or M/S */
+ if (mp3_sfBandIndex[sfreq].l[4] <= sb)
+ {
+ i = 4;
+ }
+ else
+ {
+ i = 0;
+ }
+
+ while (mp3_sfBandIndex[sfreq].l[i] <= sb)
+ {
+ i++;
+ }
+ sfbTemp = i; /* from that (long) sfb on we have intensity stereo */
+
+ sfbNo = mp3_sfBandIndex[sfreq].l[sfbTemp]; /* number of lines to process */
+
+ /* from sfbStart up sfbNo lines do ms_stereo or normal stereo */
+ if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, 0, sfbNo);
+ }
+
+ /* 2. long blocks from intensity border up to sfb band 6: intensity */
+ /* calc. MPEG_1_2_Factor[0], MPEG_1_2_Factor[1] */
+
+ for (sfb = sfbTemp; sfb < 6; sfb++)
+ {
+ sfbStart = mp3_sfBandIndex[sfreq].l[sfb]; /* = Start in 0 ... 575 */
+ sfbNo = mp3_sfBandIndex[sfreq].l[sfb+1] - mp3_sfBandIndex[sfreq].l[sfb]; /* No of lines to process */
+
+ if ((uint32)(scalefac_R->l[sfb]) != scalefac_IIP_buffer[sfb])
+ {
+ pvmp3_st_intensity_ver2(xr, xl, io, scalefac_R->l[sfb], sfbStart, sfbNo);
+ }
+ else if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+ }
+
+ /* 3. now process all sfb with short blocks (3...12), all in intensity mode */
+
+ for (j = 0; j < 3; j++)
+ {
+ /* first calculate directional factors for intensity stereo,
+ * for all sfb in intensity mode, but only
+ * if they do not have "illegal" position:
+ */
+ /* to do this for all sfb we have to get information for last scale factor band:
+ * here we clearly have more than one sfb in intensity mode,
+ * so copy factors and legal/illegal information from sfb11 to sfb12
+ */
+ (scalefac_R->s[j][12]) = (scalefac_R->s[j][11]);
+ scalefac_IIP_buffer[36 + j] = scalefac_IIP_buffer[33 + j]; /* legal/illegal in sfb 12 same as in sfb 11 */
+
+ for (sfb = 3; sfb < 13; sfb++)
+ {
+ sfbNo = mp3_sfBandIndex[sfreq].s[sfb+1] - mp3_sfBandIndex[sfreq].s[sfb]; /* No of lines to process */
+ sfbStart = 3 * mp3_sfBandIndex[sfreq].s[sfb] + j * sfbNo;
+
+ if ((uint32)(scalefac_R->s[j][sfb]) != scalefac_IIP_buffer[3*sfb + j])
+ {
+ pvmp3_st_intensity_ver2(xr, xl, io, scalefac_R->s[j][sfb], sfbStart, sfbNo);
+ }
+ else if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+ }
+ } /* for (j = 0; j < 3; j++) */
+ }
+ else /* else then (sb >= 36) */
+ {
+ /*
+ * mixed blocks processing: intensity bound outside long blocks
+ */
+
+ /* 2. short blocks, do for all 3 */
+ /* ------------------------------ */
+ for (j = 0; j < 3; j++)
+ {
+ int32 sfbcnt = -1;
+
+ for (sfb = 12; sfb >= 3; sfb--)
+ {
+ int32 lines = mp3_sfBandIndex[sfreq].s[sfb+1] - mp3_sfBandIndex[sfreq].s[sfb];
+
+ i = 3 * mp3_sfBandIndex[sfreq].s[sfb] + (j + 1) * lines - 1;
+
+ while (lines > 0)
+ {
+ if (xl[i])
+ {
+ sfbcnt = sfb;
+ sfb = -10;
+ lines = -10;
+ }
+ lines--;
+ i--;
+ }
+ }
+
+ sfbcnt += 1;
+ if (sfbcnt < 3)
+ {
+ sfbcnt = 3; /* should not be necessary */
+ }
+
+ sfbTemp = sfbcnt; /* from this (short) sfb on we have intensity mode */
+ /* can have values between 3 (all short sfb in intensity) */
+ /* and 13 (no short sfb in intensity mode) */
+
+ /* 3. from sfbTemp to last sfb calculate is_ratio values: */
+ /* first calculate directional factors for intensity stereo, */
+ /* for all sfb in intensity mode, but only */
+ /* if they do not have "illegal" position: */
+
+ /* to do this for all sfb we have to get information for last scale factor band: */
+ /* get factors for last scale factor band: */
+ /* more than one sfb in intensity mode,
+ copy factors and legal/illegal information from sfb11 to sfb12 */
+ if (sfbTemp < 12)
+ {
+ (scalefac_R->s[j][12]) = (scalefac_R->s[j][11]);
+ scalefac_IIP_buffer[36 + j] = scalefac_IIP_buffer[33 + j]; /* legal/illegal in sfb 12 same as in sfb 11 */
+ }
+ else if (sfbTemp == sfb)
+ /* only sfb 12 in intensity mode, use factors corresponding to is_pos[12] == 0 */
+ {
+ (scalefac_R->s[j][12]) = 0;
+ scalefac_IIP_buffer[36 + j] = 1; /* the scf value 0 in sfb12 is "legal" */
+ }
+ /* if sfbTemp > sfb (no sfb in intensity mode): do nothing */
+
+
+ /* 4. do normal stereo or MS stereo from sfb 3 to < sfbTemp: */
+ for (sfb = 3; sfb < sfbTemp; sfb++)
+ {
+ sfbNo = mp3_sfBandIndex[sfreq].s[sfb+1] - mp3_sfBandIndex[sfreq].s[sfb];
+ sfbStart = 3 * mp3_sfBandIndex[sfreq].s[sfb] + j * sfbNo;
+
+ if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+ }
+
+ /* 5. now intensity stereo processing of the remaining sfb's: */
+
+ for (sfb = sfbTemp; sfb < 13; sfb++)
+ {
+ sfbNo = mp3_sfBandIndex[sfreq].s[sfb+1] - mp3_sfBandIndex[sfreq].s[sfb]; /* No of lines to process */
+ sfbStart = 3 * mp3_sfBandIndex[sfreq].s[sfb] + j * sfbNo;
+ if ((uint32)(scalefac_R->s[j][sfb]) != scalefac_IIP_buffer[3*sfb + j])
+ {
+ pvmp3_st_intensity_ver2(xr, xl, io, scalefac_R->s[j][sfb], sfbStart, sfbNo);
+ }
+ else if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+ }
+ /* end of correction by efs 2003-07-04 */
+ } /* for (j = 0; j < 3; j++) */
+
+
+ /* long blocks 0 up to sfb band 6: no intensity */
+
+ sfbNo = mp3_sfBandIndex[sfreq].l[6]; /* number of lines to process */
+ if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, 0, sfbNo);
+ }
+
+ } /* if intensity bound inside or outside long blocks */
+ } /* if (gr_info->mixed_block_flag) */
+ else
+ {
+ /*
+ * short block processing
+ */
+ for (j = 0; j < 3; j++)
+ {
+ int32 sfbcnt = -1;
+
+ for (sfb = 12; sfb >= 0; sfb--)
+ {
+ int32 lines = mp3_sfBandIndex[sfreq].s[sfb+1] - mp3_sfBandIndex[sfreq].s[sfb];
+ i = 3 * mp3_sfBandIndex[sfreq].s[sfb] + (j + 1) * lines - 1;
+
+ while (lines > 0)
+ {
+ if (xl[i])
+ {
+ sfbcnt = sfb;
+ sfb = -10;
+ lines = -10;
+ }
+ lines--;
+ i--;
+ }
+ }
+
+ sfbcnt += 1;
+
+ /* start of corrected version by efs 2003-07-04 */
+ sfbTemp = sfbcnt; /* from this (short) sfb on we have intensity mode */
+ /* can have values between 3 (all short sfb in intensity) */
+ /* and 13 (no short sfb in intensity mode) */
+
+ /* first calculate directional factors for intensity stereo,
+ for all sfb in intensity mode, but only
+ if they do not have "illegal" position: */
+
+ /* to do this for all sfb we have to get information for last scale factor band: */
+ /* get factors for last scale factor band: */
+ /* more than one sfb in intensity mode,
+ copy factors and legal/illegal information from sfb11 to sfb12 */
+ if (sfbTemp < 12)
+ {
+ (scalefac_R->s[j][12]) = (scalefac_R->s[j][11]);
+ scalefac_IIP_buffer[36 + j] = scalefac_IIP_buffer[33 + j]; /* legal/illegal in sfb 12 same as in sfb 11 */
+ }
+ else if (sfbTemp == 12)
+ /* only sfb 12 in intensity mode, use factors corresponding to is_pos[12] == 0 */
+ {
+ (scalefac_R->s[j][12]) = 0;
+ scalefac_IIP_buffer[36 + j] = 1; /* the scf value 0 in sfb12 is "legal" */
+ }
+ /* if sfbTemp > sfb (no sfb in intensity mode): do nothing */
+
+
+ /* Now process audio samples */
+ /* first process lower sfb's not in intensity mode */
+ for (sfb = 0; sfb < sfbTemp; sfb++)
+ {
+ sfbNo = mp3_sfBandIndex[sfreq].s[sfb+1] - mp3_sfBandIndex[sfreq].s[sfb];
+ sfbStart = 3 * mp3_sfBandIndex[sfreq].s[sfb] + j * sfbNo;
+
+ if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+ }
+
+ /* now intensity stereo processing of the remaining sfb's: */
+ for (sfb = sfbTemp; sfb < 13; sfb++)
+ {
+ sfbNo = mp3_sfBandIndex[sfreq].s[sfb+1] - mp3_sfBandIndex[sfreq].s[sfb]; /* No of lines to process */
+ sfbStart = 3 * mp3_sfBandIndex[sfreq].s[sfb] + j * sfbNo;
+
+ if ((uint32)(scalefac_R->s[j][sfb]) != scalefac_IIP_buffer[3*sfb + j])
+ {
+ pvmp3_st_intensity_ver2(xr, xl, io, scalefac_R->s[j][sfb], sfbStart, sfbNo);
+ }
+ else if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+ }
+
+ } /* for (j = 0; j < 3; j++) */
+
+ } /* end of else ( gr_info->mixed_block_flag) */
+
+ } /* if (gr_info->window_switching_flag && (gr_info->block_type == 2)) */
+ else
+ {
+ /*
+ * long block processing
+ */
+ i = 31;
+ ss = 17;
+ sb = 0;
+
+ while (i >= 0)
+ {
+ if (xl[(i*FILTERBANK_BANDS) + ss])
+ {
+ sb = (i << 4) + (i << 1) + ss;
+ /* i = -1 patched RF 24-09-2002 */
+ i = -2;
+ }
+ else
+ {
+ ss--;
+ if (ss < 0)
+ {
+ i--;
+ ss = 17;
+ }
+ }
+ }
+
+ /* patched RF 24-09-2002 */
+ if (sb)
+ {
+ if (mp3_sfBandIndex[sfreq].l[14] <= sb)
+ {
+ i = 14;
+ }
+ else if (mp3_sfBandIndex[sfreq].l[7] <= sb)
+ {
+ i = 7;
+ }
+ else
+ {
+ i = 0;
+ }
+
+ while (mp3_sfBandIndex[sfreq].l[i] <= sb)
+ {
+ i++;
+ }
+ }
+
+ else
+ {
+ if (i == -1)
+ {
+ /* all xr[1][][] are 0: set IS bound sfb to 0 */
+ i = 0;
+ }
+ else
+ {
+ /* xr[1][0][0] is unequal 0 and all others are 0: set IS bound sfb to 1 */
+ i = 1;
+ }
+ }
+ /* corrected version by efs 2003-07-04 */
+ sfbTemp = i; /* from this (long) sfb on we have intensity mode */
+ /* can have values between 0 (all long sfb in intensity) */
+ /* and 22 (no long sfb in intensity mode) */
+
+ /* first calculate directional factors for intensity stereo,
+ for all sfb in intensity mode, but only if they
+ do not have "illegal" position: */
+
+ /* to do this for all sfb we have to get information for last scale factor band: */
+ if (sfbTemp < 21)
+ /* more than one sfb in intensity mode, */
+ /* copy factors and legal/illegal information from sfb20 to sfb21 */
+ {
+ (scalefac_R->l[21]) = (scalefac_R->l[20]);
+ scalefac_IIP_buffer[21] = scalefac_IIP_buffer[20]; /* legal/illegal in sfb 21 same as in sfb 20 */
+ }
+ else if (sfbTemp == 21)
+ /* only sfb 21 in intensity mode, is_pos[21] = 0 */
+ {
+ (scalefac_R->l[21]) = 0;
+ scalefac_IIP_buffer[21] = 1; /* the scf value 0 in sfb21 is "legal" */
+ }
+ /* if sfbTemp > 21 (no sfb in intensity mode): do nothing */
+
+
+ /* Now process audio samples */
+ /* first process lower sfb's not in intensity mode */
+
+ sfbNo = mp3_sfBandIndex[sfreq].l[sfbTemp] - mp3_sfBandIndex[sfreq].l[0];
+ sfbStart = mp3_sfBandIndex[sfreq].l[0];
+
+ if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+
+ /* now intensity stereo processing of the remaining sfb's: */
+ for (sfb = sfbTemp; sfb < 22; sfb++)
+ {
+ sfbNo = mp3_sfBandIndex[sfreq].l[sfb+1] - mp3_sfBandIndex[sfreq].l[sfb]; /* number of lines to process */
+ sfbStart = mp3_sfBandIndex[sfreq].l[sfb]; /* start of sfb */
+
+ if ((uint32)(scalefac_R->l[sfb]) != scalefac_IIP_buffer[sfb]) /* "legal" position ? */
+ {
+ pvmp3_st_intensity_ver2(xr, xl, io, scalefac_R->l[sfb], sfbStart, sfbNo);
+ }
+ else if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+
+ } /* for (sfb = sfbTemp; sfb < 22; sfb++) */
+
+ } /* if (gr_info->window_switching_flag && (gr_info->block_type == 2)) */
+
+ } /* if (i_stereo) */
+ else
+ {
+ /*
+ * normal or ms stereo processing
+ */
+ if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, 0, used_freq_lines);
+ }
+
+ } /* if (i_stereo) */
+
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h
new file mode 100644
index 0000000..7db0c53
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h
@@ -0,0 +1,112 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_mpeg2_stereo_proc.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_MPEG2_STEREO_PROC_H
+#define PVMP3_MPEG2_STEREO_PROC_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void pvmp3_mpeg2_stereo_proc(int32 xr[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 xl[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ mp3ScaleFactors *scalefac,
+ granuleInfo *gr_info_l,
+ granuleInfo *gr_info_r,
+ uint32 *scalefac_IIP_buffer,
+ int32 used_freq_lines,
+ mp3Header *info);
+
+
+ void pvmp3_st_intensity_ver2(int32 xr[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 xl[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 m,
+ int32 is_pos,
+ int32 Start,
+ int32 Number);
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.cpp
new file mode 100644
index 0000000..e579bbd
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.cpp
@@ -0,0 +1,173 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_normalize.cpp
+
+ Date: 10/02/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+ Int32 x 32-bit integer non-zero input
+Returns
+ Int32 i number of leading zeros on x
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ Returns number of leading zeros on the non-zero input
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_audio_type_defs.h"
+#include "pvmp3_normalize.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+#if (defined(PV_ARM_V5)||defined(PV_ARM_V4))
+#elif (defined(PV_ARM_GCC_V5)||defined(PV_ARM_GCC_V4))
+
+
+/* function is inlined in header file */
+
+
+#else
+
+int32 pvmp3_normalize(int32 x)
+{
+ /*----------------------------------------------------------------------------
+ ; Define all local variables
+ ----------------------------------------------------------------------------*/
+ int32 i;
+
+
+ if (x > 0x0FFFFFFF)
+ {
+ i = 0; /* most likely case */
+ }
+ else if (x > 0x00FFFFFF)
+ {
+ i = 3; /* second most likely case */
+ }
+ else if (x > 0x0000FFFF)
+ {
+ i = x > 0x000FFFFF ? 7 : 11;
+ }
+ else
+ {
+ if (x > 0x000000FF)
+ {
+ i = x > 0x00000FFF ? 15 : 19;
+ }
+ else
+ {
+ i = x > 0x0000000F ? 23 : 27;
+ }
+ }
+
+
+ x <<= i;
+
+ switch (x & 0x78000000)
+ {
+ case 0x08000000:
+ i += 3;
+ break;
+
+ case 0x18000000:
+ case 0x10000000:
+ i += 2;
+ break;
+ case 0x28000000:
+ case 0x20000000:
+ case 0x38000000:
+ case 0x30000000:
+ i++;
+
+ default:
+ ;
+ }
+
+ return i;
+
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.h
new file mode 100644
index 0000000..5471771
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_normalize.h
@@ -0,0 +1,108 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_normalize.h
+
+ Date: 10/02/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PVMP3_NORMALIZE_H
+#define PVMP3_NORMALIZE_H
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES AND SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+#if (defined(PV_ARM_V5)||defined(PV_ARM_V4))
+
+__inline int32 pvmp3_normalize(int32 x)
+{
+ int32 y;
+ __asm
+ {
+ clz y, x;
+ sub y, y, #1
+ }
+ return (y);
+}
+
+
+#elif (defined(PV_ARM_GCC_V5)||defined(PV_ARM_GCC_V4))
+
+__inline int32 pvmp3_normalize(int32 x)
+{
+ register int32 y;
+ register int32 ra = x;
+
+
+ asm volatile(
+ "clz %0, %1\n\t"
+ "sub %0, %0, #1"
+ : "=&r*i"(y)
+ : "r"(ra));
+ return (y);
+
+}
+
+#else
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ int32 pvmp3_normalize(int32 x);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+#endif /* PV_NORMALIZE_H */
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp
new file mode 100644
index 0000000..33c8e61
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp
@@ -0,0 +1,187 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_poly_phase_synthesis.cpp
+
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Input
+ tmp3dec_chan *pChVars, decoder state structure per channel
+ int32 numChannels, number of channels
+ e_equalization equalizerType, equalization mode
+ int16 *outPcm pointer to the PCM output data
+
+ Output
+ int16 *outPcm pointer to the PCM output data
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ polyphase synthesis
+ Each time the subband samples for all 32 polyphase subbands of one
+ channel have been calculated, they can be applied to the synthesis
+ subband filter and 32 consecutive audio samples can be calculated
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_poly_phase_synthesis.h"
+#include "pvmp3_polyphase_filter_window.h"
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_dct_16.h"
+#include "pvmp3_equalizer.h"
+#include "mp3_mem_funcs.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_poly_phase_synthesis(tmp3dec_chan *pChVars,
+ int32 numChannels,
+ e_equalization equalizerType,
+ int16 *outPcm)
+{
+ /*
+ * Equalizer
+ */
+ pvmp3_equalizer(pChVars->circ_buffer,
+ equalizerType,
+ pChVars->work_buf_int32);
+
+
+ int16 * ptr_out = outPcm;
+
+
+ for (int32 band = 0; band < FILTERBANK_BANDS; band += 2)
+ {
+ int32 *inData = &pChVars->circ_buffer[544 - (band<<5)];
+
+ /*
+ * DCT 32
+ */
+
+ pvmp3_split(&inData[16]);
+
+ pvmp3_dct_16(&inData[16], 0);
+ pvmp3_dct_16(inData, 1); // Even terms
+
+ pvmp3_merge_in_place_N32(inData);
+
+ pvmp3_polyphase_filter_window(inData,
+ ptr_out,
+ numChannels);
+
+ inData -= SUBBANDS_NUMBER;
+
+ /*
+ * DCT 32
+ */
+
+ pvmp3_split(&inData[16]);
+
+ pvmp3_dct_16(&inData[16], 0);
+ pvmp3_dct_16(inData, 1); // Even terms
+
+ pvmp3_merge_in_place_N32(inData);
+
+ pvmp3_polyphase_filter_window(inData,
+ ptr_out + (numChannels << 5),
+ numChannels);
+
+ ptr_out += (numChannels << 6);
+
+ inData -= SUBBANDS_NUMBER;
+
+ }/* end band loop */
+
+ pv_memmove(&pChVars->circ_buffer[576],
+ pChVars->circ_buffer,
+ 480*sizeof(*pChVars->circ_buffer));
+
+}
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h
new file mode 100644
index 0000000..166cffd
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h
@@ -0,0 +1,102 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_poly_phase_synthesis.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_POLY_PHASE_SYNTHESIS_H
+#define PVMP3_POLY_PHASE_SYNTHESIS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_audio_type_defs.h"
+#include "s_tmp3dec_chan.h"
+#include "pvmp3decoder_api.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void pvmp3_poly_phase_synthesis(tmp3dec_chan *pChVars,
+ int32 numChannels,
+ e_equalization equalizerType,
+ int16 *outPcm);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp
new file mode 100644
index 0000000..8380437
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp
@@ -0,0 +1,239 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_polyphase_filter_window.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+
+Input
+ int32 *synth_buffer, synthesis input buffer
+ int16 *outPcm, generated output ( 32 values)
+ int32 numChannels number of channels
+ Returns
+
+ int16 *outPcm
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ apply polyphase filter window
+ Input 32 subband samples
+ Calculate 64 values
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+#if ( !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4) && !defined(PV_ARM_V5) && !defined(PV_ARM_V4) )
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_polyphase_filter_window.h"
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_tables.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module1 specific macros here
+----------------------------------------------------------------------------*/
+
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module1
+----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module_x
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module_x but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_polyphase_filter_window(int32 *synth_buffer,
+ int16 *outPcm,
+ int32 numChannels)
+{
+ int32 sum1;
+ int32 sum2;
+ const int32 *winPtr = pqmfSynthWin;
+ int32 i;
+
+
+ for (int16 j = 1; j < SUBBANDS_NUMBER / 2; j++)
+ {
+ sum1 = 0x00000020;
+ sum2 = 0x00000020;
+
+
+ for (i = (SUBBANDS_NUMBER >> 1);
+ i < HAN_SIZE + (SUBBANDS_NUMBER >> 1);
+ i += SUBBANDS_NUMBER << 4)
+ {
+ int32 *pt_1 = &synth_buffer[ i+j];
+ int32 *pt_2 = &synth_buffer[ i-j];
+ int32 temp1 = pt_1[ 0];
+ int32 temp3 = pt_2[ SUBBANDS_NUMBER*15 ];
+ int32 temp2 = pt_2[ SUBBANDS_NUMBER* 1 ];
+ int32 temp4 = pt_1[ SUBBANDS_NUMBER*14 ];
+
+ sum1 = fxp_mac32_Q32(sum1, temp1, winPtr[ 0]);
+ sum2 = fxp_mac32_Q32(sum2, temp3, winPtr[ 0]);
+ sum2 = fxp_mac32_Q32(sum2, temp1, winPtr[ 1]);
+ sum1 = fxp_msb32_Q32(sum1, temp3, winPtr[ 1]);
+ sum1 = fxp_mac32_Q32(sum1, temp2, winPtr[ 2]);
+ sum2 = fxp_msb32_Q32(sum2, temp4, winPtr[ 2]);
+ sum2 = fxp_mac32_Q32(sum2, temp2, winPtr[ 3]);
+ sum1 = fxp_mac32_Q32(sum1, temp4, winPtr[ 3]);
+
+ temp1 = pt_1[ SUBBANDS_NUMBER* 2];
+ temp3 = pt_2[ SUBBANDS_NUMBER*13];
+ temp2 = pt_2[ SUBBANDS_NUMBER* 3];
+ temp4 = pt_1[ SUBBANDS_NUMBER*12];
+
+ sum1 = fxp_mac32_Q32(sum1, temp1, winPtr[ 4]);
+ sum2 = fxp_mac32_Q32(sum2, temp3, winPtr[ 4]);
+ sum2 = fxp_mac32_Q32(sum2, temp1, winPtr[ 5]);
+ sum1 = fxp_msb32_Q32(sum1, temp3, winPtr[ 5]);
+ sum1 = fxp_mac32_Q32(sum1, temp2, winPtr[ 6]);
+ sum2 = fxp_msb32_Q32(sum2, temp4, winPtr[ 6]);
+ sum2 = fxp_mac32_Q32(sum2, temp2, winPtr[ 7]);
+ sum1 = fxp_mac32_Q32(sum1, temp4, winPtr[ 7]);
+
+ temp1 = pt_1[ SUBBANDS_NUMBER* 4 ];
+ temp3 = pt_2[ SUBBANDS_NUMBER*11 ];
+ temp2 = pt_2[ SUBBANDS_NUMBER* 5 ];
+ temp4 = pt_1[ SUBBANDS_NUMBER*10 ];
+
+ sum1 = fxp_mac32_Q32(sum1, temp1, winPtr[ 8]);
+ sum2 = fxp_mac32_Q32(sum2, temp3, winPtr[ 8]);
+ sum2 = fxp_mac32_Q32(sum2, temp1, winPtr[ 9]);
+ sum1 = fxp_msb32_Q32(sum1, temp3, winPtr[ 9]);
+ sum1 = fxp_mac32_Q32(sum1, temp2, winPtr[10]);
+ sum2 = fxp_msb32_Q32(sum2, temp4, winPtr[10]);
+ sum2 = fxp_mac32_Q32(sum2, temp2, winPtr[11]);
+ sum1 = fxp_mac32_Q32(sum1, temp4, winPtr[11]);
+
+ temp1 = pt_1[ SUBBANDS_NUMBER*6 ];
+ temp3 = pt_2[ SUBBANDS_NUMBER*9 ];
+ temp2 = pt_2[ SUBBANDS_NUMBER*7 ];
+ temp4 = pt_1[ SUBBANDS_NUMBER*8 ];
+
+ sum1 = fxp_mac32_Q32(sum1, temp1, winPtr[12]);
+ sum2 = fxp_mac32_Q32(sum2, temp3, winPtr[12]);
+ sum2 = fxp_mac32_Q32(sum2, temp1, winPtr[13]);
+ sum1 = fxp_msb32_Q32(sum1, temp3, winPtr[13]);
+ sum1 = fxp_mac32_Q32(sum1, temp2, winPtr[14]);
+ sum2 = fxp_msb32_Q32(sum2, temp4, winPtr[14]);
+ sum2 = fxp_mac32_Q32(sum2, temp2, winPtr[15]);
+ sum1 = fxp_mac32_Q32(sum1, temp4, winPtr[15]);
+
+ winPtr += 16;
+ }
+
+
+
+ int32 k = j << (numChannels - 1);
+ outPcm[k] = saturate16(sum1 >> 6);
+ outPcm[(numChannels<<5) - k] = saturate16(sum2 >> 6);
+ }
+
+
+
+ sum1 = 0x00000020;
+ sum2 = 0x00000020;
+
+
+ for (i = 16; i < HAN_SIZE + 16; i += (SUBBANDS_NUMBER << 2))
+ {
+ int32 *pt_synth = &synth_buffer[i];
+ int32 temp1 = pt_synth[ 0 ];
+ int32 temp2 = pt_synth[ SUBBANDS_NUMBER ];
+ int32 temp3 = pt_synth[ SUBBANDS_NUMBER/2];
+
+ sum1 = fxp_mac32_Q32(sum1, temp1, winPtr[0]) ;
+ sum1 = fxp_mac32_Q32(sum1, temp2, winPtr[1]) ;
+ sum2 = fxp_mac32_Q32(sum2, temp3, winPtr[2]) ;
+
+ temp1 = pt_synth[ SUBBANDS_NUMBER<<1 ];
+ temp2 = pt_synth[ 3*SUBBANDS_NUMBER ];
+ temp3 = pt_synth[ SUBBANDS_NUMBER*5/2];
+
+ sum1 = fxp_mac32_Q32(sum1, temp1, winPtr[3]) ;
+ sum1 = fxp_mac32_Q32(sum1, temp2, winPtr[4]) ;
+ sum2 = fxp_mac32_Q32(sum2, temp3, winPtr[5]) ;
+
+ winPtr += 6;
+ }
+
+
+ outPcm[0] = saturate16(sum1 >> 6);
+ outPcm[(SUBBANDS_NUMBER/2)<<(numChannels-1)] = saturate16(sum2 >> 6);
+
+
+}
+
+#endif // If not assembly
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h
new file mode 100644
index 0000000..b9eccad
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h
@@ -0,0 +1,138 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_decode_header.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_POLYPHASE_FILTER_WINDOW_H
+#define PVMP3_POLYPHASE_FILTER_WINDOW_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_audio_type_defs.h"
+#include "s_tmp3dec_chan.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define MAX_16BITS_INT 0x7FFF
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#if (defined(PV_ARM_V5)||defined(PV_ARM_V4))
+
+
+ __inline int16 saturate16(int32 sample)
+ {
+ int32 a;
+ int32 b = 31;
+ __asm
+ {
+ mov a, sample, asr#15
+ teq a, sample, asr b
+ eorne sample, MAX_16BITS_INT, sample, asr#31
+ }
+ return sample ;
+ }
+
+#else
+
+ inline int16 saturate16(int32 sample)
+ {
+
+ if ((sample >> 15) ^(sample >> 31))
+ {
+ sample = MAX_16BITS_INT ^(sample >> 31);
+ }
+ return sample;
+
+ }
+#endif
+
+
+ void pvmp3_polyphase_filter_window(int32 *synth_buffer,
+ int16 *outPcm,
+ int32 numChannels);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.cpp
new file mode 100644
index 0000000..286c636
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.cpp
@@ -0,0 +1,197 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_reorder.cpp
+
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+ Inputs:
+
+ int32 xr[ ], rescaled data
+ struct gr_info_s *gr_info, granule structure
+ mp3Header *info, mp3 header info
+ int32 Scratch_mem[198] for temporary usage
+
+ Outputs:
+
+ int32 xr[ ], reordered data
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ If short blocks are used (block_type[gr][ch]=='10'), the rescaled data
+ xr[scf_band][window][freq_line] shall be reordered in polyphase subband
+ order, xr[subband][window][freq_line], prior to the IMDCT operation.
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_reorder.h"
+#include "pvmp3_tables.h"
+#include "mp3_mem_funcs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_reorder(int32 xr[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ granuleInfo *gr_info,
+ int32 *used_freq_lines,
+ mp3Header *info,
+ int32 Scratch_mem[198])
+{
+ int32 sfreq = info->version_x + (info->version_x << 1);
+ sfreq += info->sampling_frequency;
+
+ if (gr_info->window_switching_flag && (gr_info->block_type == 2))
+ {
+ int32 sfb_lines;
+ int32 freq;
+ int32 src_line;
+ int32 sfb;
+ if (gr_info->mixed_block_flag)
+ {
+ /* REORDERING FOR REST SWITCHED SHORT */
+ sfb = 3; /* no reorder for low 2 subbands */
+ src_line = 36;
+ }
+ else
+ { /* pure short */
+ sfb = 0;
+ src_line = 0;
+ }
+ int16 ct = src_line;
+
+ for (; sfb < 13; sfb++)
+ {
+ if (*used_freq_lines > 3*mp3_sfBandIndex[sfreq].s[sfb+1])
+ {
+ sfb_lines = mp3_sfBandIndex[sfreq].s[sfb+1] - mp3_sfBandIndex[sfreq].s[sfb];
+
+ for (freq = 0; freq < 3*sfb_lines; freq += 3)
+ {
+ int32 tmp1 = xr[src_line];
+ int32 tmp2 = xr[src_line+(sfb_lines)];
+ int32 tmp3 = xr[src_line+(sfb_lines<<1)];
+ src_line++;
+ Scratch_mem[freq ] = tmp1;
+ Scratch_mem[freq+1] = tmp2;
+ Scratch_mem[freq+2] = tmp3;
+ }
+ src_line += (sfb_lines << 1);
+
+ pv_memcpy(&xr[ct], Scratch_mem, sfb_lines*3*sizeof(int32));
+ ct += sfb_lines + (sfb_lines << 1);
+
+ }
+ else
+ {
+
+ sfb_lines = mp3_sfBandIndex[sfreq].s[sfb+1] - mp3_sfBandIndex[sfreq].s[sfb];
+
+ for (freq = 0; freq < 3*sfb_lines; freq += 3)
+ {
+ int32 tmp1 = xr[src_line];
+ int32 tmp2 = xr[src_line+(sfb_lines)];
+ int32 tmp3 = xr[src_line+(sfb_lines<<1)];
+ src_line++;
+ Scratch_mem[freq ] = tmp1;
+ Scratch_mem[freq+1] = tmp2;
+ Scratch_mem[freq+2] = tmp3;
+ }
+
+ pv_memcpy(&xr[ct], Scratch_mem, sfb_lines*3*sizeof(int32));
+
+ *used_freq_lines = mp3_sfBandIndex[sfreq].s[sfb+1] * 3;
+
+ sfb = 13; /* force out of the for-loop */
+ }
+ }
+ }
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.h
new file mode 100644
index 0000000..5248951
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_reorder.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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_reorder.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_REORDER_H
+#define PVMP3_REORDER_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void pvmp3_reorder(int32 xr[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ granuleInfo *gr_info,
+ int32 *used_freq_lines,
+ mp3Header *info,
+ int32 Scratch_mem[198]);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_seek_synch.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_seek_synch.cpp
new file mode 100644
index 0000000..82faafd
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_seek_synch.cpp
@@ -0,0 +1,308 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_seek_synch.cpp
+
+ Functions:
+ pvmp3_seek_synch
+ pvmp3_header_sync
+
+
+ Date: 9/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+pvmp3_frame_synch
+
+Input
+ pExt = pointer to the external interface structure. See the file
+ pvmp3decoder_api.h for a description of each field.
+ Data type of pointer to a tPVMP3DecoderExternal
+ structure.
+
+ pMem = void pointer to hide the internal implementation of the library
+ It is cast back to a tmp3dec_file structure. This structure
+ contains information that needs to persist between calls to
+ this function, or is too big to be placed on the stack, even
+ though the data is only needed during execution of this function
+ Data type void pointer, internally pointer to a tmp3dec_file
+ structure.
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ search mp3 sync word, when found, it verifies, based on header parameters,
+ the locations of the very next sync word,
+ - if fails, then indicates a false sync,
+ - otherwise, it confirm synchronization of at least 2 consecutives frames
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_seek_synch.h"
+#include "pvmp3_getbits.h"
+#include "s_tmp3dec_file.h"
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_tables.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+
+ERROR_CODE pvmp3_frame_synch(tPVMP3DecoderExternal *pExt,
+ void *pMem) /* bit stream structure */
+{
+ uint16 val;
+ ERROR_CODE err;
+
+ tmp3dec_file *pVars;
+
+ pVars = (tmp3dec_file *)pMem;
+
+ pVars->inputStream.pBuffer = pExt->pInputBuffer;
+ pVars->inputStream.usedBits = (pExt->inputBufferUsedLength << 3); // in bits
+
+
+ pVars->inputStream.inputBufferCurrentLength = (pExt->inputBufferCurrentLength); // in bits
+
+ err = pvmp3_header_sync(&pVars->inputStream);
+
+ if (err == NO_DECODING_ERROR)
+ {
+ /* validate synchronization by checking two consecutive sync words */
+
+ // to avoid multiple bitstream accesses
+ uint32 temp = getNbits(&pVars->inputStream, 21);
+ // put back whole header
+ pVars->inputStream.usedBits -= 21 + SYNC_WORD_LNGTH;
+
+ int32 version;
+
+ switch (temp >> 19) /* 2 */
+ {
+ case 0:
+ version = MPEG_2_5;
+ break;
+ case 2:
+ version = MPEG_2;
+ break;
+ case 3:
+ version = MPEG_1;
+ break;
+ default:
+ version = INVALID_VERSION;
+ break;
+ }
+
+ int32 freq_index = (temp << 20) >> 30;
+
+ if (version != INVALID_VERSION && (freq_index != 3))
+ {
+ int32 numBytes = fxp_mul32_Q28(mp3_bitrate[version][(temp<<16)>>28] << 20,
+ inv_sfreq[freq_index]);
+
+ numBytes >>= (20 - version);
+
+ if (version != MPEG_1)
+ {
+ numBytes >>= 1;
+ }
+ if ((temp << 22) >> 31)
+ {
+ numBytes++;
+ }
+
+ if (numBytes > (int32)pVars->inputStream.inputBufferCurrentLength)
+ {
+ /* frame should account for padding and 2 bytes to check sync */
+ pExt->CurrentFrameLength = numBytes + 3;
+ return (SYNCH_LOST_ERROR);
+ }
+ else if (numBytes == (int32)pVars->inputStream.inputBufferCurrentLength)
+ {
+ /* No enough data to validate, but current frame appears to be correct ( EOF case) */
+ pExt->inputBufferUsedLength = pVars->inputStream.usedBits >> 3;
+ return (NO_DECODING_ERROR);
+ }
+ else
+ {
+
+ int32 offset = pVars->inputStream.usedBits + ((numBytes) << 3);
+
+ offset >>= INBUF_ARRAY_INDEX_SHIFT;
+ uint8 *pElem = pVars->inputStream.pBuffer + offset;
+ uint16 tmp1 = *(pElem++);
+ uint16 tmp2 = *(pElem);
+
+ val = (tmp1 << 3);
+ val |= (tmp2 >> 5);
+ }
+ }
+ else
+ {
+ val = 0; // force mismatch
+ }
+
+ if (val == SYNC_WORD)
+ {
+ pExt->inputBufferUsedLength = pVars->inputStream.usedBits >> 3; /// !!!!!
+ err = NO_DECODING_ERROR;
+ }
+ else
+ {
+ pExt->inputBufferCurrentLength = 0;
+ err = SYNCH_LOST_ERROR;
+ }
+ }
+ else
+ {
+ pExt->inputBufferCurrentLength = 0;
+ }
+
+ return(err);
+
+}
+
+/*
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+------------------------------------------------------------------------------
+ INPUT AND OUTPUT DEFINITIONS
+
+pvmp3_header_sync
+
+Input
+ tmp3Bits *inputStream, structure holding the input stream parameters
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ search mp3 sync word
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+
+ERROR_CODE pvmp3_header_sync(tmp3Bits *inputStream)
+{
+ uint16 val;
+ uint32 availableBits = (inputStream->inputBufferCurrentLength << 3); // in bits
+
+ // byte aligment
+ inputStream->usedBits = (inputStream->usedBits + 7) & 8;
+
+ val = (uint16)getUpTo17bits(inputStream, SYNC_WORD_LNGTH);
+
+ while (((val&SYNC_WORD) != SYNC_WORD) && (inputStream->usedBits < availableBits))
+ {
+ val <<= 8;
+ val |= getUpTo9bits(inputStream, 8);
+ }
+
+ if ((val&SYNC_WORD) == SYNC_WORD && (inputStream->usedBits < availableBits))
+ {
+ return(NO_DECODING_ERROR);
+ }
+ else
+ {
+ return(SYNCH_LOST_ERROR);
+ }
+
+}
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_seek_synch.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_seek_synch.h
new file mode 100644
index 0000000..8097cee
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_seek_synch.h
@@ -0,0 +1,106 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_seek_synch.h
+
+ Date: 09/21/2007
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_SEEK_SYNCH_H
+#define PVMP3_SEEK_SYNCH_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_audio_type_defs.h"
+#include "pvmp3decoder_api.h"
+#include "s_tmp3dec_file.h"
+#include "pvmp3_dec_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ ERROR_CODE pvmp3_frame_synch(tPVMP3DecoderExternal *pExt,
+ void *pMem);
+
+ ERROR_CODE pvmp3_header_sync(tmp3Bits *inputStream);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif /* DECODE_READ_INPUT_H */
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
new file mode 100644
index 0000000..d69a46d
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
@@ -0,0 +1,676 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_stereo_proc.cpp
+
+ Functions:
+
+ pvmp3_st_mid_side
+ pvmp3_st_intensity
+ pvmp3_stereo_proc
+
+------------------------------------------------------------------------------
+
+pvmp3_st_mid_side
+
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+
+ int32 xr[], input channel
+ int32 xl[],
+ int32 Start, Location of first element where stereo intensity is applied
+ int32 Number number of elements affected
+
+ Returns
+
+ int32 xl[], generated stereo channel
+
+
+------------------------------------------------------------------------------
+
+pvmp3_st_intensity
+
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+
+ int32 xr[], input channel
+ int32 xl[],
+ int32 is_pos, index to table is_ratio_factor[]
+ int32 Start, Location of first element where stereo intensity is applied
+ int32 Number number of elements affected
+
+ Returns
+
+ int32 xl[], generated stereo channel
+
+
+------------------------------------------------------------------------------
+
+pvmp3_stereo_proc
+
+ INPUT AND OUTPUT DEFINITIONS
+
+Input
+
+ int32 xr[], input channel
+ int32 xl[],
+ mp3ScaleFactors *scalefac, scale factors structure
+ struct gr_info_s *gr_info, granule structure
+ mp3Header *info mp3 header info
+ Returns
+
+ int32 xl[], generated stereo channel
+
+
+------------------------------------------------------------------------------
+ FUNCTION DESCRIPTION
+
+ stereo processing for mpeg1 layer III
+ After requantization, the reconstructed values are processed for ms_stereo
+ or intensity_stereo modes or both, before passing them to the synthesis
+ filterbank
+
+ In ms_stereo mode the values of the normalized middle/side channels
+ M[l] and S[l] are transmitted instead of the left/right channel values
+ L[l] and R[l]. From here, L[l] and R[l] are reconstructed
+
+ Intensity_stereo is done by specifying the magnitude (via the
+ scalefactors of the left channel) and a stereo position is_pos[sfb],
+ which is transmitted instead of scalefactors of the right channel.
+ The stereo position is used to derive the left and right channel signals
+
+------------------------------------------------------------------------------
+ REQUIREMENTS
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+ PSEUDO-CODE
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_stereo_proc.h"
+#include "pv_mp3dec_fxd_op.h"
+#include "pvmp3_tables.h"
+
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+#define N31 31
+
+#define Q31_fmt(a) (int32(double(0x7FFFFFFF)*a))
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+/*
+ * TmpFac= tan(is_pos * (PI /12));
+ *
+ * TmpFac /= (1 + TmpFac);
+ *
+ */
+
+const int32 is_ratio_factor[8] = {0,
+ Q31_fmt(0.21132486540519), Q31_fmt(0.36602540378444), Q31_fmt(0.50000000000000),
+ Q31_fmt(0.63397459621556), Q31_fmt(0.78867513459481), Q31_fmt(1.00000000000000),
+ 0
+ };
+
+/*----------------------------------------------------------------------------
+; EXTERNAL FUNCTION REFERENCES
+; Declare functions defined elsewhere and referenced in this module
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_st_mid_side(int32 xr[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 xl[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 Start,
+ int32 Number)
+{
+
+ int32 *pt_xr = &xr[Start];
+ int32 *pt_xl = &xl[Start];
+
+ for (int32 i = Number >> 1; i != 0; i--)
+ {
+ int32 xxr = *(pt_xr) << 1;
+ int32 xxl = *(pt_xl) << 1;
+ *(pt_xr++) = fxp_mul32_Q32((xxr + xxl), Q31_fmt(0.70710678118655)); /* Sum */
+ *(pt_xl++) = fxp_mul32_Q32((xxr - xxl), Q31_fmt(0.70710678118655)); /* Diff */
+ xxr = *(pt_xr) << 1;
+ xxl = *(pt_xl) << 1;
+ *(pt_xr++) = fxp_mul32_Q32((xxr + xxl), Q31_fmt(0.70710678118655)); /* Sum */
+ *(pt_xl++) = fxp_mul32_Q32((xxr - xxl), Q31_fmt(0.70710678118655)); /* Diff */
+ }
+
+
+ if (Number&1)
+ {
+ int32 xxr = *(pt_xr) << 1;
+ int32 xxl = *(pt_xl) << 1;
+ *(pt_xr) = fxp_mul32_Q32((xxr + xxl), Q31_fmt(0.70710678118655)); /* Sum */
+ *(pt_xl) = fxp_mul32_Q32((xxr - xxl), Q31_fmt(0.70710678118655)); /* Diff */
+ }
+
+}
+
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+
+void pvmp3_st_intensity(int32 xr[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 xl[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 is_pos,
+ int32 Start,
+ int32 Number)
+{
+
+ int32 TmpFac = is_ratio_factor[ is_pos & 7];
+
+ int32 *pt_xr = &xr[Start];
+ int32 *pt_xl = &xl[Start];
+
+ for (int32 i = Number >> 1; i != 0; i--)
+ {
+ int32 tmp = fxp_mul32_Q32((*pt_xr) << 1, TmpFac);
+ *(pt_xl++) = (*pt_xr) - tmp;
+ *(pt_xr++) = tmp;
+ tmp = fxp_mul32_Q32((*pt_xr) << 1, TmpFac);
+ *(pt_xl++) = (*pt_xr) - tmp;
+ *(pt_xr++) = tmp;
+ }
+
+ if (Number&1)
+ {
+ int32 tmp = fxp_mul32_Q32((*pt_xr) << 1, TmpFac);
+ *(pt_xl) = (*pt_xr) - tmp;
+ *(pt_xr) = tmp;
+ }
+
+}
+
+/*----------------------------------------------------------------------------
+; FUNCTION CODE
+----------------------------------------------------------------------------*/
+void pvmp3_stereo_proc(int32 xr[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 xl[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ mp3ScaleFactors *scalefac,
+ granuleInfo *gr_info,
+ int32 used_freq_lines,
+ mp3Header *info)
+{
+
+
+ int32 sb;
+ int32 ss;
+ int32 sfbNo;
+ int32 sfbStart;
+
+ int32 sfb;
+ int32 sfbTemp;
+ int32 i;
+ int32 j;
+
+
+ int32 i_stereo = (info->mode == MPG_MD_JOINT_STEREO) &&
+ (info->mode_ext & 0x1);
+
+ int32 ms_stereo = (info->mode == MPG_MD_JOINT_STEREO) &&
+ (info->mode_ext & 0x2);
+
+ int32 sfreq = info->version_x + (info->version_x << 1);
+ sfreq += info->sampling_frequency;
+
+
+
+
+ if (i_stereo)
+ {
+ if (gr_info->window_switching_flag && (gr_info->block_type == 2))
+ {
+ if (gr_info->mixed_block_flag)
+ {
+ /*
+ * mixed blocks processing
+ */
+ i = 31;
+ ss = 17;
+ sb = 0;
+ while (i >= 0)
+ {
+ if (xl[(i*FILTERBANK_BANDS) + ss])
+ {
+ sb = (i << 4) + (i << 1) + ss;
+ i = -1;
+ }
+ else
+ {
+ ss--;
+ if (ss < 0)
+ {
+ i--;
+ ss = 17;
+ }
+ }
+ }
+
+ if (sb < 36)
+ {
+ /*
+ * mixed blocks processing: intensity bound inside long blocks
+ */
+ /* 1. long blocks up to intensity border: not intensity */
+
+ if (mp3_sfBandIndex[sfreq].l[4] <= sb)
+ {
+ sfb = 4;
+ }
+ else
+ {
+ sfb = 0;
+ }
+
+ while (mp3_sfBandIndex[sfreq].l[sfb] < sb)
+ {
+ sfb++;
+ }
+
+ /* from that sfb on intensity stereo */
+ sfbTemp = sfb; /* save for later use */
+
+ sfbStart = mp3_sfBandIndex[sfreq].l[sfb];
+
+ /* from 0 up to sfbStart do ms_stereo or normal stereo */
+
+ if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, 0, sfbStart);
+ }
+
+ /* 2. long blocks from intensity border up to sfb band 8: intensity */
+ /* calc. is_ratio */
+
+
+ /* Start of intensity stereo of remaining sfc bands: */
+ for (; sfbTemp < 8; sfbTemp++)
+ {
+ sfbStart = mp3_sfBandIndex[sfreq].l[sfbTemp]; /* = Start in 0 ... 575 */
+ sfbNo = mp3_sfBandIndex[sfreq].l[sfbTemp+1] - mp3_sfBandIndex[sfreq].l[sfbTemp]; /* No of lines to process */
+
+ if (scalefac->l[sfbTemp] != 7)
+ {
+ pvmp3_st_intensity(xr, xl, scalefac->l[sfbTemp], sfbStart, sfbNo);
+ }
+ else if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+
+ } /* for (; sfbTemp < 8; sfbTemp++) */
+
+ for (j = 0; j < 3; j++)
+ {
+ /* 3. short blocks from sfbcnt to last sfb do intensity stereo */
+ for (sfbTemp = 3; sfbTemp < 13; sfbTemp++)
+ {
+ sfbNo = mp3_sfBandIndex[sfreq].s[sfbTemp+1] - mp3_sfBandIndex[sfreq].s[sfbTemp]; /* No of lines to process */
+ sfbStart = 3 * mp3_sfBandIndex[sfreq].s[sfbTemp] + j * sfbNo;
+
+ if (scalefac->s[j][sfbTemp] != 7)
+ {
+ pvmp3_st_intensity(xr, xl, scalefac->s[j][sfbTemp], sfbStart, sfbNo);
+ }
+ else if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+
+ } /* for (; sfbTemp < 22; sfbTemp++) */
+ } /* for (j = 0; j < 3; j++) */
+ }
+ else /* else for (sb >= 36) */
+ {
+ /*
+ * mixed blocks processing: intensity bound outside long blocks
+ */
+
+
+ /*
+ * 2. short blocks from sfb band 3 up to intensity border: normal stereo, ms stereo and intensity
+ */
+ for (j = 0; j < 3; j++)
+ {
+ int32 sfbcnt;
+ sfbcnt = -1;
+
+ for (sfb = 12; sfb >= 3; sfb--)
+ {
+ int32 lines;
+ lines = mp3_sfBandIndex[sfreq].s[sfb+1] - mp3_sfBandIndex[sfreq].s[sfb];
+ i = 3 * mp3_sfBandIndex[sfreq].s[sfb] + (j + 1) * lines - 1;
+
+ while (lines > 0)
+ {
+ if (xl[i])
+ {
+ sfbcnt = sfb;
+ sfb = -10;
+ lines = -10;
+ }
+ lines--;
+ i--;
+ }
+ }
+
+ sfbcnt += 1;
+ if (sfbcnt < 3)
+ {
+ sfbcnt = 3;
+ }
+
+ sfbTemp = sfbcnt; /* for later use */
+
+
+ /*
+ * do normal stereo or MS stereo from sfb 3 to < sfbcnt:
+ */
+ for (sb = 3; sb < sfbcnt; sb++)
+ {
+ sfbNo = mp3_sfBandIndex[sfreq].s[sb+1] - mp3_sfBandIndex[sfreq].s[sb];
+ sfbStart = 3 * mp3_sfBandIndex[sfreq].s[sb] + j * sfbNo;
+
+ if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+
+ }
+
+ /* from sfbcnt to last sfb do intensity stereo */
+ for (; sfbTemp < 13; sfbTemp++)
+ {
+ sfbNo = mp3_sfBandIndex[sfreq].s[sfbTemp+1] - mp3_sfBandIndex[sfreq].s[sfbTemp]; /* No of lines to process */
+ sfbStart = 3 * mp3_sfBandIndex[sfreq].s[sfbTemp] + j * sfbNo;
+
+ if (scalefac->s[j][sfbTemp] != 7)
+ {
+ pvmp3_st_intensity(xr, xl, scalefac->s[j][sfbTemp], sfbStart, sfbNo);
+ }
+ else if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+
+ } /* for (; sfbTemp < 22; sfbTemp++) */
+
+ } /* for (j = 0; j < 3; j++) */
+
+ /* 1. long blocks up to sfb band 8: not intensity */
+ /* from 0 to sfb 8 ms_stereo or normal stereo */
+
+ sfbStart = mp3_sfBandIndex[sfreq].l[8];
+
+ if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, 0, sfbStart);
+ }
+
+ }
+ } /* if (gr_info->mixed_block_flag) */
+ else
+ {
+ /*
+ * short block processing
+ */
+ for (j = 0; j < 3; j++)
+ {
+ int32 sfbcnt = -1;
+
+ for (sfb = 12; sfb >= 0; sfb--)
+ {
+ int32 lines = mp3_sfBandIndex[sfreq].s[sfb+1] - mp3_sfBandIndex[sfreq].s[sfb];
+ i = 3 * mp3_sfBandIndex[sfreq].s[sfb] + (j + 1) * lines - 1;
+
+ while (lines > 0)
+ {
+ if (xl[i])
+ {
+ sfbcnt = sfb;
+ sfb = -10;
+ lines = -10;
+ }
+ lines--;
+ i--;
+ }
+ }
+
+ sfbcnt += 1;
+ sfbTemp = sfbcnt; /* for later use */
+
+ /* do normal stereo or MS stereo from 0 to sfbcnt */
+ for (sb = 0; sb < sfbcnt; sb++)
+ {
+ sfbNo = mp3_sfBandIndex[sfreq].s[sb+1] - mp3_sfBandIndex[sfreq].s[sb];
+ sfbStart = 3 * mp3_sfBandIndex[sfreq].s[sb] + j * sfbNo;
+
+ if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+ }
+
+
+ /* from sfbcnt to last sfb do intensity stereo */
+ for (; sfbTemp < 13; sfbTemp++)
+ {
+ sfbNo = mp3_sfBandIndex[sfreq].s[sfbTemp+1] - mp3_sfBandIndex[sfreq].s[sfbTemp]; /* No of lines to process */
+ sfbStart = 3 * mp3_sfBandIndex[sfreq].s[sfbTemp] + j * sfbNo;
+
+ if (scalefac->s[j][sfbTemp] != 7)
+ {
+ pvmp3_st_intensity(xr, xl, scalefac->s[j][sfbTemp], sfbStart, sfbNo);
+ }
+ else if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+
+ } /* for (; sfbTemp < 22; sfbTemp++) */
+
+ } /* for (j = 0; j < 3; j++) */
+
+ } /* if( gr_info->mixed_block_flag) */
+
+
+
+ } /* if (gr_info->window_switching_flag && (gr_info->block_type == 2)) */
+ else
+ {
+ /*
+ * long block processing
+ */
+ i = 31;
+ ss = 17;
+ sb = 0;
+
+ while (i >= 0)
+ {
+ if (xl[(i*FILTERBANK_BANDS) + ss] != 0)
+ {
+ sb = (i << 4) + (i << 1) + ss;
+ i = -2;
+ }
+ else
+ {
+ ss--;
+ if (ss < 0)
+ {
+ i--;
+ ss = 17;
+ }
+ }
+ }
+
+ if (sb)
+ {
+ if (mp3_sfBandIndex[sfreq].l[14] <= sb)
+ {
+ sfb = 14;
+ }
+ else if (mp3_sfBandIndex[sfreq].l[7] <= sb)
+ {
+ sfb = 7;
+ }
+ else
+ {
+ sfb = 0;
+ }
+
+
+ while (mp3_sfBandIndex[sfreq].l[sfb] <= sb)
+ {
+ sfb++;
+ }
+ }
+ else
+ {
+ if (i == -1)
+ {
+ /* all xr[1][][] are 0: set IS bound sfb to 0 */
+ sfb = 0;
+ }
+ else
+ {
+ /* xr[1][0][0] is unequal 0 and all others are 0: set IS bound sfb to 1 */
+ sfb = 1;
+ }
+ }
+
+ sfbTemp = sfb; /* save for later use */
+
+
+ sfbStart = mp3_sfBandIndex[sfreq].l[sfb];
+
+ /* from 0 to sfbStart ms_stereo or normal stereo */
+ if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, 0, sfbStart);
+ }
+
+ /* now intensity stereo of the remaining sfb's: */
+ for (; sfb < 21; sfb++)
+ {
+ sfbStart = mp3_sfBandIndex[sfreq].l[sfb];
+ sfbNo = mp3_sfBandIndex[sfreq].l[sfb+1] - mp3_sfBandIndex[sfreq].l[sfb]; /* No of lines to process */
+
+ if (scalefac->l[sfb] != 7)
+ {
+ pvmp3_st_intensity(xr, xl, scalefac->l[sfb], sfbStart, sfbNo);
+ }
+ else if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+
+ } /* for (; sfbTemp < 22; sfbTemp++) */
+
+
+
+ sfbStart = mp3_sfBandIndex[sfreq].l[21];
+ sfbNo = mp3_sfBandIndex[sfreq].l[22] - mp3_sfBandIndex[sfreq].l[21]; /* No of lines to process */
+
+ if (scalefac->l[21] != 7)
+ {
+ if (sfbTemp < 21)
+ {
+ sfbTemp = scalefac->l[20];
+ }
+ else
+ {
+ sfbTemp = 0; /* if scalefac[20] is not an intensity position, is_pos = 0 */
+ }
+
+ pvmp3_st_intensity(xr, xl, sfbTemp, sfbStart, sfbNo);
+ }
+ else if (ms_stereo)
+ {
+ pvmp3_st_mid_side(xr, xl, sfbStart, sfbNo);
+ }
+
+ } /* if (gr_info->window_switching_flag && (gr_info->block_type == 2)) */
+
+
+ } /* if (i_stereo) */
+ else
+ {
+ /*
+ * normal or ms stereo processing
+ */
+ if (ms_stereo)
+ {
+
+ pvmp3_st_mid_side(xr, xl, 0, used_freq_lines);
+
+ }
+
+ } /* if (i_stereo) */
+
+}
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.h
new file mode 100644
index 0000000..bfaf1a1
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.h
@@ -0,0 +1,114 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_stereo_proc.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef PVMP3_STEREO_PROC_H
+#define PVMP3_STEREO_PROC_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_dec_defs.h"
+#include "pvmp3_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ void pvmp3_stereo_proc(int32 xr[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 xl[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ mp3ScaleFactors *scalefac,
+ granuleInfo *gr_info,
+ int32 used_freq_lines,
+ mp3Header *info);
+
+ void pvmp3_st_intensity(int32 xr[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 xl[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 is_pos,
+ int32 Start,
+ int32 Number);
+
+ void pvmp3_st_mid_side(int32 xr[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 xl[SUBBANDS_NUMBER*FILTERBANK_BANDS],
+ int32 Start,
+ int32 Number);
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_tables.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_tables.cpp
new file mode 100644
index 0000000..90e524a
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_tables.cpp
@@ -0,0 +1,2934 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: pvmp3_tables.cpp
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+
+ Description:
+
+
+------------------------------------------------------------------------------
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+------------------------------------------------------------------------------
+*/
+
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_tables.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here. Include conditional
+; compile variables also.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; LOCAL STORE/BUFFER/POINTER DEFINITIONS
+; Variable declaration - defined here and used outside this module
+----------------------------------------------------------------------------*/
+
+const int32 mp3_s_freq[4][4] =
+{
+ {44100, 48000, 32000, 0},
+ {22050, 24000, 16000, 0},
+ {11025, 12000, 8000, 0}
+}; // MPEG-2.5
+
+
+/*
+ * 144000./s_freq
+ */
+const int32 inv_sfreq[4] =
+{
+ Qfmt_28(3.26530612244898),
+ Qfmt_28(3.0),
+ Qfmt_28(4.5),
+ 0
+};
+
+
+/* 1: MPEG-1, 0: MPEG-2 LSF, 1995-07-11 shn */
+
+
+const int16 mp3_bitrate[3][15] =
+{
+ {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320},
+ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160},
+ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}
+};
+
+
+const mp3_scaleFactorBandIndex mp3_sfBandIndex[9] =
+{
+
+ /* MPEG 1 */
+
+ {{0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 52, 62, 74, 90, 110, 134, 162, 196, 238, 288, 342, 418, 576},
+ {0, 4, 8, 12, 16, 22, 30, 40, 52, 66, 84, 106, 136, 192}},
+ {{0, 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 60, 72, 88, 106, 128, 156, 190, 230, 276, 330, 384, 576},
+ {0, 4, 8, 12, 16, 22, 28, 38, 50, 64, 80, 100, 126, 192}},
+ {{0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 54, 66, 82, 102, 126, 156, 194, 240, 296, 364, 448, 550, 576},
+ {0, 4, 8, 12, 16, 22, 30, 42, 58, 78, 104, 138, 180, 192}},
+
+ /* MPEG 2 - LSF */
+
+ {{0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576},
+ {0, 4, 8, 12, 18, 24, 32, 42, 56, 74, 100, 132, 174, 192}},
+ {{0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 114, 136, 162, 194, 232, 278, 332, 394, 464, 540, 576},
+ {0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 136, 180, 192}},
+ {{0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576},
+ {0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192}},
+
+ /* MPEG 2.5 extension */
+
+ {{0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576},
+ {0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192}},
+ {{0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576},
+ {0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192}},
+ {{0, 12, 24, 36, 48, 60, 72, 88, 108, 132, 160, 192, 232, 280, 336, 400, 476, 566, 568, 570, 572, 574, 576},
+ {0, 8, 16, 24, 36, 52, 72, 96, 124, 160, 162, 164, 166, 192}}
+
+};
+
+#define INV_Q31( x) (int32)(0x7FFFFFFF/(float)x - 1.0f)
+
+const int32 mp3_shortwindBandWidths[9][13] =
+{
+ { INV_Q31(4), INV_Q31(4), INV_Q31(4), INV_Q31(4), INV_Q31(6), INV_Q31(8), INV_Q31(10),
+ INV_Q31(12), INV_Q31(14), INV_Q31(18), INV_Q31(22), INV_Q31(30), INV_Q31(56)},
+ { INV_Q31(4), INV_Q31(4), INV_Q31(4), INV_Q31(4), INV_Q31(6), INV_Q31(6), INV_Q31(10),
+ INV_Q31(12), INV_Q31(14), INV_Q31(16), INV_Q31(20), INV_Q31(26), INV_Q31(66)},
+ { INV_Q31(4), INV_Q31(4), INV_Q31(4), INV_Q31(4), INV_Q31(6), INV_Q31(8), INV_Q31(12),
+ INV_Q31(16), INV_Q31(20), INV_Q31(26), INV_Q31(34), INV_Q31(42), INV_Q31(12)},
+ { INV_Q31(4), INV_Q31(4), INV_Q31(4), INV_Q31(6), INV_Q31(6), INV_Q31(8), INV_Q31(10),
+ INV_Q31(14), INV_Q31(18), INV_Q31(26), INV_Q31(32), INV_Q31(42), INV_Q31(18)},
+ { INV_Q31(4), INV_Q31(4), INV_Q31(4), INV_Q31(6), INV_Q31(8), INV_Q31(10), INV_Q31(12),
+ INV_Q31(14), INV_Q31(18), INV_Q31(24), INV_Q31(32), INV_Q31(44), INV_Q31(12)},
+ { INV_Q31(4), INV_Q31(4), INV_Q31(4), INV_Q31(6), INV_Q31(8), INV_Q31(10), INV_Q31(12),
+ INV_Q31(14), INV_Q31(18), INV_Q31(24), INV_Q31(30), INV_Q31(40), INV_Q31(18)},
+ { INV_Q31(4), INV_Q31(4), INV_Q31(4), INV_Q31(6), INV_Q31(8), INV_Q31(10), INV_Q31(12),
+ INV_Q31(14), INV_Q31(18), INV_Q31(24), INV_Q31(30), INV_Q31(40), INV_Q31(18)},
+ { INV_Q31(4), INV_Q31(4), INV_Q31(4), INV_Q31(6), INV_Q31(8), INV_Q31(10), INV_Q31(12),
+ INV_Q31(14), INV_Q31(18), INV_Q31(24), INV_Q31(30), INV_Q31(40), INV_Q31(18)},
+ { INV_Q31(8), INV_Q31(8), INV_Q31(8), INV_Q31(12), INV_Q31(16), INV_Q31(20), INV_Q31(24),
+ INV_Q31(28), INV_Q31(36), INV_Q31(2), INV_Q31(2), INV_Q31(2), INV_Q31(26)}
+};
+
+
+#define Q30_fmt(a) (int32((0x40000000)*a))
+
+const int32 pqmfSynthWin[(HAN_SIZE/2) + 8] =
+{
+ Q30_fmt(-0.000015259F), Q30_fmt(0.000396729F), Q30_fmt(0.000473022F), Q30_fmt(0.003173828F),
+ Q30_fmt(0.003326416F), Q30_fmt(0.006118770F), Q30_fmt(0.007919310F), Q30_fmt(0.031478880F),
+ Q30_fmt(0.030517578F), Q30_fmt(0.073059080F), Q30_fmt(0.084182740F), Q30_fmt(0.108856200F),
+ Q30_fmt(0.090927124F), Q30_fmt(0.543823240F), Q30_fmt(0.600219727F), Q30_fmt(1.144287109F),
+
+ Q30_fmt(-0.000015259F), Q30_fmt(0.000366211F), Q30_fmt(0.000534058F), Q30_fmt(0.003082275F),
+ Q30_fmt(0.003387451F), Q30_fmt(0.005294800F), Q30_fmt(0.008865360F), Q30_fmt(0.031738280F),
+ Q30_fmt(0.029785160F), Q30_fmt(0.067520140F), Q30_fmt(0.089706420F), Q30_fmt(0.116577150F),
+ Q30_fmt(0.080688480F), Q30_fmt(0.515609740F), Q30_fmt(0.628295900F), Q30_fmt(1.142211914F),
+
+ Q30_fmt(-0.000015259F), Q30_fmt(0.000320435F), Q30_fmt(0.000579834F), Q30_fmt(0.002990723F),
+ Q30_fmt(0.003433228F), Q30_fmt(0.004486080F), Q30_fmt(0.009841920F), Q30_fmt(0.031845090F),
+ Q30_fmt(0.028884890F), Q30_fmt(0.061996460F), Q30_fmt(0.095169070F), Q30_fmt(0.123474120F),
+ Q30_fmt(0.069595340F), Q30_fmt(0.487472530F), Q30_fmt(0.656219480F), Q30_fmt(1.138763428F),
+
+ Q30_fmt(-0.000015259F), Q30_fmt(0.000289917F), Q30_fmt(0.000625610F), Q30_fmt(0.002899170F),
+ Q30_fmt(0.003463745F), Q30_fmt(0.003723140F), Q30_fmt(0.010849000F), Q30_fmt(0.031814580F),
+ Q30_fmt(0.027801510F), Q30_fmt(0.056533810F), Q30_fmt(0.100540160F), Q30_fmt(0.129577640F),
+ Q30_fmt(0.057617190F), Q30_fmt(0.459472660F), Q30_fmt(0.683914180F), Q30_fmt(1.133926392F),
+
+ Q30_fmt(-0.000015259F), Q30_fmt(0.000259399F), Q30_fmt(0.000686646F), Q30_fmt(0.002792358F),
+ Q30_fmt(0.003479004F), Q30_fmt(0.003005981F), Q30_fmt(0.011886600F), Q30_fmt(0.031661990F),
+ Q30_fmt(0.026535030F), Q30_fmt(0.051132200F), Q30_fmt(0.105819700F), Q30_fmt(0.134887700F),
+ Q30_fmt(0.044784550F), Q30_fmt(0.431655880F), Q30_fmt(0.711318970F), Q30_fmt(1.127746582F),
+
+ Q30_fmt(-0.000015259F), Q30_fmt(0.000244141F), Q30_fmt(0.000747681F), Q30_fmt(0.002685547F),
+ Q30_fmt(0.003479004F), Q30_fmt(0.002334595F), Q30_fmt(0.012939450F), Q30_fmt(0.031387330F),
+ Q30_fmt(0.025085450F), Q30_fmt(0.045837400F), Q30_fmt(0.110946660F), Q30_fmt(0.139450070F),
+ Q30_fmt(0.031082153F), Q30_fmt(0.404083250F), Q30_fmt(0.738372800F), Q30_fmt(1.120223999F),
+
+ Q30_fmt(-0.000030518F), Q30_fmt(0.000213623F), Q30_fmt(0.000808716F), Q30_fmt(0.002578735F),
+ Q30_fmt(0.003463745F), Q30_fmt(0.001693726F), Q30_fmt(0.014022830F), Q30_fmt(0.031005860F),
+ Q30_fmt(0.023422240F), Q30_fmt(0.040634160F), Q30_fmt(0.115921020F), Q30_fmt(0.143264770F),
+ Q30_fmt(0.016510010F), Q30_fmt(0.376800540F), Q30_fmt(0.765029907F), Q30_fmt(1.111373901F),
+
+ Q30_fmt(-0.000030518F), Q30_fmt(0.000198364F), Q30_fmt(0.000885010F), Q30_fmt(0.002456665F),
+ Q30_fmt(0.003417969F), Q30_fmt(0.001098633F), Q30_fmt(0.015121460F), Q30_fmt(0.030532840F),
+ Q30_fmt(0.021575930F), Q30_fmt(0.035552980F), Q30_fmt(0.120697020F), Q30_fmt(0.146362300F),
+ Q30_fmt(0.001068120F), Q30_fmt(0.349868770F), Q30_fmt(0.791213990F), Q30_fmt(1.101211548F),
+
+ Q30_fmt(-0.000030518F), Q30_fmt(0.000167847F), Q30_fmt(0.000961304F), Q30_fmt(0.002349854F),
+ Q30_fmt(0.003372192F), Q30_fmt(0.000549316F), Q30_fmt(0.016235350F), Q30_fmt(0.029937740F),
+ Q30_fmt(0.019531250F), Q30_fmt(0.030609130F), Q30_fmt(0.125259400F), Q30_fmt(0.148773190F),
+ Q30_fmt(-0.015228270F), Q30_fmt(0.323318480F), Q30_fmt(0.816864010F), Q30_fmt(1.089782715F),
+
+ Q30_fmt(-0.000030518F), Q30_fmt(0.000152588F), Q30_fmt(0.001037598F), Q30_fmt(0.002243042F),
+ Q30_fmt(0.003280640F), Q30_fmt(0.000030518F), Q30_fmt(0.017349240F), Q30_fmt(0.029281620F),
+ Q30_fmt(0.017257690F), Q30_fmt(0.025817870F), Q30_fmt(0.129562380F), Q30_fmt(0.150497440F),
+ Q30_fmt(-0.032379150F), Q30_fmt(0.297210693F), Q30_fmt(0.841949463F), Q30_fmt(1.077117920F),
+
+ Q30_fmt(-0.000045776F), Q30_fmt(0.000137329F), Q30_fmt(0.001113892F), Q30_fmt(0.002120972F),
+ Q30_fmt(0.003173828F), Q30_fmt(-0.000442505F), Q30_fmt(0.018463130F), Q30_fmt(0.028533940F),
+ Q30_fmt(0.014801030F), Q30_fmt(0.021179200F), Q30_fmt(0.133590700F), Q30_fmt(0.151596070F),
+ Q30_fmt(-0.050354000F), Q30_fmt(0.271591190F), Q30_fmt(0.866363530F), Q30_fmt(1.063217163F),
+
+ Q30_fmt(-0.000045776F), Q30_fmt(0.000122070F), Q30_fmt(0.001205444F), Q30_fmt(0.002014160F),
+ Q30_fmt(0.003051758F), Q30_fmt(-0.000869751F), Q30_fmt(0.019577030F), Q30_fmt(0.027725220F),
+ Q30_fmt(0.012115480F), Q30_fmt(0.016708370F), Q30_fmt(0.137298580F), Q30_fmt(0.152069090F),
+ Q30_fmt(-0.069168090F), Q30_fmt(0.246505740F), Q30_fmt(0.890090940F), Q30_fmt(1.048156738F),
+
+ Q30_fmt(-0.000061035F), Q30_fmt(0.000106812F), Q30_fmt(0.001296997F), Q30_fmt(0.001907349F),
+ Q30_fmt(0.002883911F), Q30_fmt(-0.001266479F), Q30_fmt(0.020690920F), Q30_fmt(0.026840210F),
+ Q30_fmt(0.009231570F), Q30_fmt(0.012420650F), Q30_fmt(0.140670780F), Q30_fmt(0.151962280F),
+ Q30_fmt(-0.088775630F), Q30_fmt(0.221984860F), Q30_fmt(0.913055420F), Q30_fmt(1.031936646F),
+
+ Q30_fmt(-0.000061035F), Q30_fmt(0.000106812F), Q30_fmt(0.001388550F), Q30_fmt(0.001785278F),
+ Q30_fmt(0.002700806F), Q30_fmt(-0.001617432F), Q30_fmt(0.021789550F), Q30_fmt(0.025909420F),
+ Q30_fmt(0.006134030F), Q30_fmt(0.008316040F), Q30_fmt(0.143676760F), Q30_fmt(0.151306150F),
+ Q30_fmt(-0.109161380F), Q30_fmt(0.198059080F), Q30_fmt(0.935195920F), Q30_fmt(1.014617920F),
+
+ Q30_fmt(-0.000076294F), Q30_fmt(0.000091553F), Q30_fmt(0.001480103F), Q30_fmt(0.001693726F),
+ Q30_fmt(0.002487183F), Q30_fmt(-0.001937866F), Q30_fmt(0.022857670F), Q30_fmt(0.024932860F),
+ Q30_fmt(0.002822880F), Q30_fmt(0.004394530F), Q30_fmt(0.146255490F), Q30_fmt(0.150115970F),
+ Q30_fmt(-0.130310060F), Q30_fmt(0.174789430F), Q30_fmt(0.956481930F), Q30_fmt(0.996246338F),
+
+ Q30_fmt(0.000000000F), Q30_fmt(0.000442505F), Q30_fmt(0.001586910F), Q30_fmt(0.003250122F),
+ Q30_fmt(0.007003780F), Q30_fmt(0.023910525F), Q30_fmt(0.031082153F), Q30_fmt(0.078628545F),
+ Q30_fmt(0.148422240F), Q30_fmt(0.100311279F), Q30_fmt(0.572036740F), Q30_fmt(0.976852417F),
+ Q30_fmt(1.144989014F), Q30_fmt(-0.572036745F), Q30_fmt(-0.152206421F), Q30_fmt(0.100311279F),
+
+ Q30_fmt(-0.078628540F), Q30_fmt(-0.000686646F), Q30_fmt(0.031082153F), Q30_fmt(-0.007003785F),
+ Q30_fmt(0.002227783F), Q30_fmt(0.003250122F), Q30_fmt(-0.000442500F), Q30_fmt(-0.000076294F),
+};
+
+
+
+
+
+const uint16 huffTable_1[8] =
+{
+ 0x1103, 0x0103, 0x1002, 0x1002,
+ 0x0001, 0x0001, 0x0001, 0x0001
+};
+
+const uint16 huffTable_2[15] =
+{
+ 0x1103, 0x0103, 0x1003, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x2206,
+ 0x0206, 0x1205, 0x1205, 0x2105,
+ 0x2105, 0x2005, 0x2005
+};
+
+const uint16 huffTable_3[15] =
+{
+
+ 0x1003, 0x1102, 0x1102, 0x0102,
+ 0x0102, 0x0002, 0x0002, 0x2206,
+ 0x0206, 0x1205, 0x1205, 0x2105,
+ 0x2105, 0x2005, 0x2005
+};
+
+const uint16 huffTable_5[25] =
+{
+
+ 0x1103, 0x0103, 0x1003, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x3106,
+ 0x3106, 0x1307, 0x0307, 0x3007,
+ 0x2207, 0x1206, 0x1206, 0x2106,
+ 0x2106, 0x0206, 0x0206, 0x2006,
+ 0x2006, 0x3308, 0x2308, 0x3207,
+ 0x3207
+};
+
+
+const uint16 huffTable_6[26] =
+{
+
+ 0x1204, 0x2104, 0x2004, 0x0103,
+ 0x0103, 0x1102, 0x1102, 0x1102,
+ 0x1102, 0x1003, 0x1003, 0x0003,
+ 0x0003, 0x2306, 0x3206, 0x3006,
+ 0x1305, 0x1305, 0x3105, 0x3105,
+ 0x2205, 0x2205, 0x0205, 0x0205,
+ 0x3307, 0x0307
+};
+
+
+
+const uint16 huffTable_7[73] =
+{
+ 0x0103,
+ 0x1003,
+ 0x0001,
+ 0x0001,
+ 0x0001,
+ 0x0001,
+ 0x1206,
+ 0x2105,
+ 0x2105,
+ 0x0206,
+ 0x2006,
+ 0x1104,
+ 0x1104,
+ 0x1104,
+ 0x1104,
+ 0x3509,
+ 0x4409,
+ 0x2509,
+ 0x5209,
+ 0x1508,
+ 0x1508,
+ 0x5108,
+ 0x5108,
+ 0x0509,
+ 0x3409,
+ 0x5008,
+ 0x5008,
+ 0x4309,
+ 0x3309,
+ 0x2408,
+ 0x2408,
+ 0x4208,
+ 0x4208,
+ 0x1407,
+ 0x1407,
+ 0x1407,
+ 0x1407,
+ 0x4107,
+ 0x4107,
+ 0x4107,
+ 0x4107,
+ 0x4007,
+ 0x4007,
+ 0x4007,
+ 0x4007,
+ 0x0408,
+ 0x0408,
+ 0x2308,
+ 0x2308,
+ 0x3208,
+ 0x3208,
+ 0x0308,
+ 0x0308,
+ 0x1307,
+ 0x1307,
+ 0x1307,
+ 0x1307,
+ 0x3107,
+ 0x3107,
+ 0x3107,
+ 0x3107,
+ 0x3007,
+ 0x3007,
+ 0x3007,
+ 0x3007,
+ 0x2207,
+ 0x2207,
+ 0x2207,
+ 0x2207,
+ 0x550a,
+ 0x450a,
+ 0x540a,
+ 0x530a
+};
+
+const uint16 huffTable_8[66] =
+{
+ 0x1204,
+ 0x2104,
+ 0x1102,
+ 0x1102,
+ 0x1102,
+ 0x1102,
+ 0x0103,
+ 0x0103,
+ 0x1003,
+ 0x1003,
+ 0x0002,
+ 0x0002,
+ 0x0002,
+ 0x0002,
+ 0x2206,
+ 0x0206,
+ 0x2006,
+ 0x2509,
+ 0x5209,
+ 0x0509,
+ 0x1508,
+ 0x1508,
+ 0x5108,
+ 0x5108,
+ 0x3409,
+ 0x4309,
+ 0x5009,
+ 0x3309,
+ 0x2408,
+ 0x2408,
+ 0x4208,
+ 0x4208,
+ 0x1408,
+ 0x1408,
+ 0x4107,
+ 0x4107,
+ 0x4107,
+ 0x4107,
+ 0x0408,
+ 0x0408,
+ 0x4008,
+ 0x4008,
+ 0x2308,
+ 0x2308,
+ 0x3208,
+ 0x3208,
+ 0x1308,
+ 0x1308,
+ 0x3108,
+ 0x3108,
+ 0x0308,
+ 0x0308,
+ 0x3008,
+ 0x3008,
+ 0x550b,
+ 0x540b,
+ 0x450a,
+ 0x450a,
+ 0x5309,
+ 0x5309,
+ 0x5309,
+ 0x5309,
+ 0x350a,
+ 0x350a,
+ 0x440a,
+ 0x440a
+
+};
+
+
+const uint16 huffTable_9[53] =
+{
+ 0x1204,
+ 0x2104,
+ 0x2004,
+ 0x1103,
+ 0x1103,
+ 0x0103,
+ 0x0103,
+ 0x1003,
+ 0x1003,
+ 0x0003,
+ 0x0003,
+ 0x1406,
+ 0x4106,
+ 0x2306,
+ 0x3206,
+ 0x1305,
+ 0x1305,
+ 0x3105,
+ 0x3105,
+ 0x0306,
+ 0x3006,
+ 0x2205,
+ 0x2205,
+ 0x0205,
+ 0x0205,
+ 0x4408,
+ 0x2508,
+ 0x5208,
+ 0x1508,
+ 0x5107,
+ 0x5107,
+ 0x3407,
+ 0x3407,
+ 0x4307,
+ 0x4307,
+ 0x5008,
+ 0x0408,
+ 0x2407,
+ 0x2407,
+ 0x4207,
+ 0x4207,
+ 0x3307,
+ 0x3307,
+ 0x4007,
+ 0x4007,
+ 0x5509,
+ 0x4509,
+ 0x3508,
+ 0x3508,
+ 0x5308,
+ 0x5308,
+ 0x5409,
+ 0x0509
+
+};
+
+
+const uint16 huffTable_10[96] =
+{
+ 0x0001,
+ 0x1104,
+ 0x0103,
+ 0x0103,
+ 0x1003,
+ 0x1003,
+ 0x1206,
+ 0x2106,
+ 0x0206,
+ 0x2006,
+ 0x1408,
+ 0x4108,
+ 0x4008,
+ 0x2308,
+ 0x3208,
+ 0x0308,
+ 0x1307,
+ 0x1307,
+ 0x3107,
+ 0x3107,
+ 0x3007,
+ 0x3007,
+ 0x2207,
+ 0x2207,
+ 0x1608,
+ 0x1608,
+ 0x6108,
+ 0x6108,
+ 0x6008,
+ 0x6008,
+ 0x0509,
+ 0x5009,
+ 0x2409,
+ 0x4209,
+ 0x3309,
+ 0x0409,
+ 0x2709,
+ 0x2709,
+ 0x7209,
+ 0x7209,
+ 0x640a,
+ 0x070a,
+ 0x7009,
+ 0x7009,
+ 0x6209,
+ 0x6209,
+ 0x450a,
+ 0x350a,
+ 0x0609,
+ 0x0609,
+ 0x530a,
+ 0x440a,
+ 0x1708,
+ 0x1708,
+ 0x1708,
+ 0x1708,
+ 0x7108,
+ 0x7108,
+ 0x7108,
+ 0x7108,
+ 0x3609,
+ 0x3609,
+ 0x2609,
+ 0x2609,
+ 0x250a,
+ 0x520a,
+ 0x1509,
+ 0x1509,
+ 0x5109,
+ 0x5109,
+ 0x340a,
+ 0x430a,
+ 0x770b,
+ 0x670b,
+ 0x760b,
+ 0x570b,
+ 0x750b,
+ 0x660b,
+ 0x470a,
+ 0x470a,
+ 0x740a,
+ 0x740a,
+ 0x560a,
+ 0x560a,
+ 0x650a,
+ 0x650a,
+ 0x370a,
+ 0x370a,
+ 0x730a,
+ 0x730a,
+ 0x460a,
+ 0x460a,
+ 0x550b,
+ 0x540b,
+ 0x630a,
+ 0x630a
+};
+
+
+const uint16 huffTable_11[116] =
+{
+ 0x1103,
+ 0x0103,
+ 0x1003,
+ 0x0002,
+ 0x0002,
+ 0x2105,
+ 0x1204, /* 0100 */
+ 0x1204, /* 010 */
+ 0x0205, /* 01010 */
+ 0x2005, /* 01011 */
+ 0x1408, /* 10 */
+ 0x4108, /* 00 */
+ 0x0408, /* 0 0 */
+ 0x4008, /* 0 1 */
+ 0x2307, /* 0 */
+ 0x2307, /* */
+ 0x3207, /* 1 */
+ 0x3207, /* */
+ 0x1306, /* 010 */
+ 0x1306, /* 01 */
+ 0x1306, /* 01 */
+ 0x1306, /* 01 */
+ 0x3106, /* 011 */
+ 0x3106, /* 01 */
+ 0x3106, /* 01 */
+ 0x3106, /* 01 */
+ 0x0307, /* 1000 */
+ 0x0307, /* 100 */
+ 0x3007, /* 1 */
+ 0x3007, /* 100 */
+ 0x2206, /* 101 */
+ 0x2206, /* 10 */
+ 0x2206, /* 10 */
+ 0x2206, /* 10 */
+ 0x2708,
+ 0x2708, /* 000 0 */
+ 0x7208, /* 000 10 */
+ 0x7208, /* 000 1 */
+ 0x6409, /* 000 110 */
+ 0x0709,
+ 0x7107,
+ 0x7107,
+ 0x7107, /* 00 0 */
+ 0x7107, /* 00 0 */
+ 0x1708,
+ 0x1708, /* 00 01 */
+ 0x7008,
+ 0x7008,
+ 0x3608,
+ 0x3608, /* 00 10 */
+ 0x6308, /* 00 101 */
+ 0x6308, /* 00 10 */
+ 0x6008,
+ 0x6008, /* 00 11 */
+ 0x4409,
+ 0x2509,
+ 0x5209, /* 0 */
+ 0x0509, /* 0 00 */
+ 0x1508, /* 0 0 */
+ 0x1508, /* 0 000 */
+ 0x6207, /* 0 */
+ 0x6207, /* 0 00 */
+ 0x6207, /* 0 00 */
+ 0x6207, /* 0 00 */
+ 0x2608,
+ 0x2608, /* 0 010 */
+ 0x0608,
+ 0x0608,
+ 0x1607,
+ 0x1607,
+ 0x1607,
+ 0x1607,
+ 0x6107,
+ 0x6107,
+ 0x6107,
+ 0x6107,
+ 0x5108,
+ 0x5108,
+ 0x3408,
+ 0x3408,
+ 0x5008,
+ 0x5008,
+ 0x4309,
+ 0x3309,
+ 0x2408,
+ 0x2408, /* 0 111 */
+ 0x4208, /* 0 1111 */
+ 0x4208, /* 0 111 */
+ 0x560a,
+ 0x650a,
+ 0x3709,
+ 0x3709,
+ 0x7309,
+ 0x7309,
+ 0x4609,
+ 0x4609,
+ 0x450a,
+ 0x540a, /* 000 0 */
+ 0x350a, /* 000 0 */
+ 0x530a, /* 000 1 */
+ 0x770a,
+ 0x770a,
+ 0x670a,
+ 0x670a,
+ 0x760a, /* 0 */
+ 0x760a, /* */
+ 0x750a, /* 1 */
+ 0x750a, /* */
+ 0x660a, /* 00 */
+ 0x660a, /* 0 */
+ 0x470a, /* 01 */
+ 0x470a, /* 0 */
+ 0x740a, /* 10 */
+ 0x740a, /* 1 */
+ 0x570b, /* 110 */
+ 0x550b /* 111 */
+
+};
+
+const uint16 huffTable_12[134] =
+{
+
+ 0x1103, /* 101 */
+ 0x0103, /* 110 */
+ 0x1003, /* 111 */
+ 0x1204,
+ 0x1204, /* 011 */
+ 0x2104, /* 0111 */
+ 0x2104, /* 011 */
+ 0x0205, /* 10000 */
+ 0x2005, /* 10 */
+ 0x0004, /* 1 */
+ 0x0004, /* 100 */
+ 0x3006,
+ 0x1305, /* 01 */
+ 0x1305, /* 0100 */
+ 0x3105,
+ 0x3105,
+ 0x2205,
+ 0x2205, /* 0101 */
+ 0x1507,
+ 0x1507, /* 000 */
+ 0x5107, /* 0 */
+ 0x5107, /* 000 */
+ 0x3407, /* 0 */
+ 0x3407, /* */
+ 0x4307, /* 1 */
+ 0x4307, /* */
+ 0x5008,
+ 0x0408,
+ 0x2407,
+ 0x2407, /* 010 */
+ 0x4207,
+ 0x4207,
+ 0x1407, /* 0111 */
+ 0x1407, /* 011 */
+ 0x3306,
+ 0x3306,
+ 0x3306,
+ 0x3306,
+ 0x4106,
+ 0x4106,
+ 0x4106,
+ 0x4106,
+ 0x2306,
+ 0x2306,
+ 0x2306,
+ 0x2306,
+ 0x3206,
+ 0x3206,
+ 0x3206,
+ 0x3206,
+ 0x4007,
+ 0x4007,
+ 0x0307,
+ 0x0307, /* 010000 */
+ 0x7208,
+ 0x7208, /* 00 00 */
+ 0x4608, /* 00 */
+ 0x4608, /* 00 00 */
+ 0x6408,
+ 0x6408, /* 00 01 */
+ 0x1708, /* 00 011 */
+ 0x1708,
+ 0x7108, /* 00 100 */
+ 0x7108,
+ 0x0709,
+ 0x7009,
+ 0x3608,
+ 0x3608, /* 00 11 */
+ 0x6308,
+ 0x6308,
+ 0x4508,
+ 0x4508,
+ 0x5408, /* 0 0 */
+ 0x5408, /* 0 000 */
+ 0x4408, /* 0 0 */
+ 0x4408, /* 0 */
+ 0x0609, /* 0 10 */
+ 0x0509, /* 0 11 */
+ 0x2607,
+ 0x2607,
+ 0x2607,
+ 0x2607,
+ 0x6207,
+ 0x6207,
+ 0x6207,
+ 0x6207,
+ 0x6107,
+ 0x6107,
+ 0x6107,
+ 0x6107,
+ 0x1608, /* 0 1010 */
+ 0x1608, /* 0 101 */
+ 0x6008, /* 0 1011 */
+ 0x6008, /* 0 101 */
+ 0x3508,
+ 0x3508, /* 0 110 */
+ 0x5308, /* 0 1101 */
+ 0x5308, /* 0 110 */
+ 0x2508,
+ 0x2508, /* 0 111 */
+ 0x5208, /* 0 1111 */
+ 0x5208, /* 0 111 */
+ 0x770a,
+ 0x670a,
+ 0x7609, /* */
+ 0x7609,
+ 0x5709, /* 0 */
+ 0x5709, /* */
+ 0x7509, /* 1 */
+ 0x7509, /* */
+ 0x6609,
+ 0x6609,
+ 0x4709, /* 0000 01 */
+ 0x4709, /* 0000 0 */
+ 0x7409,
+ 0x7409, /* 0000 1 */
+ 0x6509,
+ 0x6509, /* 0000 1 */
+ 0x5608,
+ 0x5608,
+ 0x5608,
+ 0x5608,
+ 0x3708,
+ 0x3708,
+ 0x3708,
+ 0x3708,
+ 0x7309, /* 000 100 */
+ 0x7309, /* 000 10 */
+ 0x5509,
+ 0x5509, /* 000 10 */
+ 0x2708,
+ 0x2708,
+ 0x2708,
+ 0x2708,
+};
+
+
+
+const uint16 huffTable_13[491] =
+{
+ 0x0001,
+ 0x1104,
+ 0x0104,
+ 0x1003,
+ 0x1003,
+ 0x4107,
+ 0x4107,
+ 0x0408,
+ 0x4008,
+ 0x2308,
+ 0x3208,
+ 0x1307,
+ 0x1307,
+ 0x3107,
+ 0x3107,
+ 0x0307,
+ 0x0307,
+ 0x3007,
+ 0x3007,
+ 0x2207,
+ 0x2207,
+ 0x1206,
+ 0x1206,
+ 0x1206,
+ 0x1206,
+ 0x2106,
+ 0x2106,
+ 0x2106,
+ 0x2106,
+ 0x0206,
+ 0x0206,
+ 0x0206,
+ 0x0206,
+ 0x2006,
+ 0x2006,
+ 0x2006,
+ 0x2006,
+ 0x370a,
+ 0x270a, /* 0 000 */
+ 0x1709, /* 0 00 */
+ 0x1709,
+ 0x7109,
+ 0x7109, /* 0 0 */
+ 0x550a,
+ 0x070a, /* 0 0 11 */
+ 0x700a,
+ 0x360a, /* 0 */
+ 0x630a,
+ 0x450a, /* 0 011 */
+ 0x540a,
+ 0x260a, /* 0 101 */
+ 0x620a,
+ 0x350a, /* 0 111 */
+ 0x8108,
+ 0x8108, /* 0 010 */
+ 0x8108,
+ 0x8108, /* 0 010 */
+ 0x0809,
+ 0x0809, /* 0 0101 */
+ 0x8009,
+ 0x8009, /* 0 0101 */
+ 0x1609,
+ 0x1609, /* 0 0110 */
+ 0x6109,
+ 0x6109, /* 0 0110 */
+ 0x0609,
+ 0x0609, /* 0 0111 */
+ 0x6009,
+ 0x6009, /* 0 0111 */
+ 0x530a,
+ 0x440a, /* 0 100 */
+ 0x2509,
+ 0x2509, /* 0 1000 */
+ 0x5209,
+ 0x5209, /* 0 1 */
+ 0x0509,
+ 0x0509, /* 0 1 */
+ 0x1508,
+ 0x1508, /* 0 101 */
+ 0x1508,
+ 0x1508, /* 0 101 */
+ 0x5108,
+ 0x5108, /* 0 101 */
+ 0x5108,
+ 0x5108, /* 0 101 */
+ 0x3409,
+ 0x3409, /* 0 1100 */
+ 0x4309,
+ 0x4309, /* 0 1100 */
+ 0x5009,
+ 0x5009, /* 0 1101 */
+ 0x2409,
+ 0x2409, /* 0 1101 */
+ 0x4209,
+ 0x4209, /* 0 1110 */
+ 0x3309,
+ 0x3309, /* 0 1110 */
+ 0x1408,
+ 0x1408, /* 0 111 */
+ 0x1408,
+ 0x1408, /* 0 111 */
+ 0x1a0a,
+ 0x1a0a,
+ 0xa10a, /* 00 00 */
+ 0xa10a,
+ 0x0a0b,
+ 0x680b,
+ 0xa00a,
+ 0xa00a,
+ 0x860b,
+ 0x490b,
+ 0x930a,
+ 0x930a,
+ 0x390b,
+ 0x580b,
+ 0x850b,
+ 0x670b,
+ 0x290a,
+ 0x290a,
+ 0x920a,
+ 0x920a,
+ 0x570b,
+ 0x750b,
+ 0x380a,
+ 0x380a,
+ 0x830a,
+ 0x830a,
+ 0x660b,
+ 0x470b,
+ 0x740b,
+ 0x560b,
+ 0x650b,
+ 0x730b,
+ 0x1909,
+ 0x1909,
+ 0x1909,
+ 0x1909,
+ 0x9109,
+ 0x9109,
+ 0x9109,
+ 0x9109,
+ 0x090a, /* 00 10100 */
+ 0x090a,
+ 0x900a, /* 00 10101 */
+ 0x900a,
+ 0x480a, /* 00 10110 */
+ 0x480a,
+ 0x840a, /* 00 10111 */
+ 0x840a,
+ 0x720a, /* 00 11000 */
+ 0x720a,
+ 0x460b, /* 00 11 0 */
+ 0x640b,
+ 0x2809,
+ 0x2809,
+ 0x2809,
+ 0x2809,
+ 0x8209,
+ 0x8209,
+ 0x8209,
+ 0x8209,
+ 0x1809,
+ 0x1809,
+ 0x1809,
+ 0x1809,
+ 0xc10b,
+ 0xc10b, /* 000 0000 */
+ 0x980c,
+ 0x0c0c, /* 000 00 1 */
+ 0xc00b,
+ 0xc00b, /* 000 0 */
+ 0xb40c,
+ 0x6a0c, /* 000 0 11 */
+ 0xa60c,
+ 0x790c, /* 000 */
+ 0x3b0b,
+ 0x3b0b, /* 000 0 */
+ 0xb30b,
+ 0xb30b, /* 000 1 */
+ 0x880c,
+ 0x5a0c, /* 000 111 */
+ 0x2b0b,
+ 0x2b0b, /* 000 0100 */
+ 0xa50c,
+ 0x690c, /* 000 01 1 */
+ 0xa40b,
+ 0xa40b, /* 000 0101 */
+ 0x780c,
+ 0x870c,
+ 0x940b,
+ 0x940b, /* 000 0110 */
+ 0x770c,
+ 0x760c, /* 000 011011 */
+ 0xb20a,
+ 0xb20a, /* 000 011 */
+ 0xb20a,
+ 0xb20a, /* 000 011 */
+ 0x1b0a,
+ 0x1b0a, /* 000 100 */
+ 0x1b0a,
+ 0x1b0a, /* 000 100 */
+ 0xb10a,
+ 0xb10a,
+ 0xb10a, /* 000 100 */
+ 0xb10a, /* 000 100 */
+ 0x0b0b, /* 000 10100 */
+ 0x0b0b, /* 000 1010 */
+ 0xb00b,
+ 0xb00b, /* 000 1010 */
+ 0x960b, /* 000 10110 */
+ 0x960b, /* 000 1011 */
+ 0x4a0b,
+ 0x4a0b, /* 000 1011 */
+ 0x3a0b, /* 000 11000 */
+ 0x3a0b, /* 000 1100 */
+ 0xa30b, /* 000 11 */
+ 0xa30b, /* 000 1100 */
+ 0x590b,
+ 0x590b, /* 000 1101 */
+ 0x950b, /* 000 11011 */
+ 0x950b, /* 000 1101 */
+ 0x2a0a,
+ 0x2a0a,
+ 0x2a0a,
+ 0x2a0a,
+ 0xa20a,
+ 0xa20a,
+ 0xa20a,
+ 0xa20a,
+ 0xf00c,
+ 0xf00c, /* 000 */
+ 0xba0d,
+ 0xe50d, /* 0 1 */
+ 0xe40d,
+ 0x8c0d, /* 01 */
+ 0x6d0d,
+ 0xe30d, /* 11 */
+ 0xe20c, /* 0100 */
+ 0xe20c,
+ 0x2e0d, /* 01010 */
+ 0x0e0d,
+ 0x1e0c, /* 0110 */
+ 0x1e0c,
+ 0xe10c, /* 0111 */
+ 0xe10c,
+ 0xe00d, /* 10000 */
+ 0x5d0d,
+ 0xd50d, /* 1 0 */
+ 0x7c0d,
+ 0xc70d,
+ 0x4d0d,
+ 0x8b0d,
+ 0xb80d,
+ 0xd40d,
+ 0x9a0d,
+ 0xa90d,
+ 0x6c0d,
+ 0xc60c,
+ 0xc60c,
+ 0x3d0c,
+ 0x3d0c, /* 111 */
+ 0xd30d, /* 0000 */
+ 0x7b0d,
+ 0x2d0c,
+ 0x2d0c,
+ 0xd20c,
+ 0xd20c,
+ 0x1d0c,
+ 0x1d0c,
+ 0xb70c,
+ 0xb70c, /* 0000 0 */
+ 0x5c0d,
+ 0xc50d, /* 0000 011 */
+ 0x990d,
+ 0x7a0d,
+ 0xc30c,
+ 0xc30c, /* 0000 1 */
+ 0xa70d,
+ 0x970d,
+ 0x4b0c,
+ 0x4b0c,
+ 0xd10b,
+ 0xd10b,
+ 0xd10b, /* 0000 010 */
+ 0xd10b,
+ 0x0d0c,
+ 0x0d0c,
+ 0xd00c,
+ 0xd00c,
+ 0x8a0c,
+ 0x8a0c,
+ 0xa80c,
+ 0xa80c,
+ 0x4c0c,
+ 0x4c0c,
+ 0xc40c,
+ 0xc40c,
+ 0x6b0c,
+ 0x6b0c, /* 0000 1 */
+ 0xb60c, /* 0000 1 1 */
+ 0xb60c, /* 0000 1 */
+ 0x3c0b,
+ 0x3c0b,
+ 0x3c0b,
+ 0x3c0b,
+ 0x2c0b, /* 0000 1011 */
+ 0x2c0b, /* 0000 101 */
+ 0x2c0b, /* 0000 101 */
+ 0x2c0b, /* 0000 101 */
+ 0xc20b,
+ 0xc20b,
+ 0xc20b,
+ 0xc20b,
+ 0x5b0b, /* 0000 1101 */
+ 0x5b0b,
+ 0x5b0b, /* 0000 110 */
+ 0x5b0b, /* 0000 110 */
+ 0xb50c,
+ 0xb50c,
+ 0x890c,
+ 0x890c, /* 0000 1110 */
+ 0x1c0b,
+ 0x1c0b,
+ 0x1c0b,
+ 0x1c0b,
+ 0x2f0d,
+ 0x2f0d, /* 000 */
+ 0xf20d, /* 0 */
+ 0xf20d, /* 000 */
+ 0x6e0e, /* 00 */
+ 0x9c0e, /* 01 */
+ 0x0f0d, /* 1 */
+ 0x0f0d, /* */
+ 0xc90e,
+ 0x5e0e, /* 01 */
+ 0xab0d, /* 0101 */
+ 0xab0d,
+ 0x7d0e, /* 01100 */
+ 0xd70e,
+ 0x4e0d, /* 0111 */
+ 0x4e0d,
+ 0xc80e,
+ 0xd60e, /* 10 */
+ 0x3e0d,
+ 0x3e0d, /* 100 */
+ 0xb90d,
+ 0xb90d, /* 101 */
+ 0x9b0e,
+ 0xaa0e, /* 10111 */
+ 0x1f0c,
+ 0x1f0c, /* 11 */
+ 0x1f0c, /* 11 */
+ 0x1f0c,
+ 0xf10c, /* 111 */
+ 0xf10c, /* 11 */
+ 0xf10c, /* 11 */
+ 0xf10c, /* 11 */
+ 0xe80e,
+ 0xe80e,
+ 0x5f0e,
+ 0x5f0e,
+ 0x9d0e,
+ 0x9d0e,
+ 0xd90e,
+ 0xd90e, /* 0000000 */
+ 0xf50e,
+ 0xf50e,
+ 0xe70e,
+ 0xe70e,
+ 0xac0e,
+ 0xac0e,
+ 0xbb0e,
+ 0xbb0e,
+ 0x4f0e,
+ 0x4f0e,
+ 0xf40e, /* 0000000 1 */
+ 0xf40e,
+ 0xca0f,
+ 0xe60f,
+ 0xf30e,
+ 0xf30e, /* 0000000 101 */
+ 0x3f0d,
+ 0x3f0d, /* 0000000 11 */
+ 0x3f0d,
+ 0x3f0d, /* 0000000 11 */
+ 0x8d0e,
+ 0x8d0e,
+ 0xd80e, /* 0000000 1111 */
+ 0xd80e,
+ 0x8f0f,
+ 0x8f0f, /* 00000000 000 */
+ 0xf80f, /* 00000000 0 */
+ 0xf80f,
+ 0xcc0f, /* 00000000 0 */
+ 0xcc0f,
+ 0xae10,
+ 0x9e10, /* 00000000 11 */
+ 0x8e0f,
+ 0x8e0f,
+ 0x7f10,
+ 0x7e10,
+ 0xf70e, /* 00000000 011 */
+ 0xf70e,
+ 0xf70e,
+ 0xf70e, /* 00000000 01 */
+ 0xda0e,
+ 0xda0e, /* 00000000 10 */
+ 0xda0e,
+ 0xda0e, /* 00000000 10 */
+ 0xad0f,
+ 0xad0f, /* 00000000 101 */
+ 0xbc0f,
+ 0xbc0f, /* 00000000 101 */
+ 0xcb0f,
+ 0xcb0f, /* 00000000 110 */
+ 0xf60f,
+ 0xf60f, /* 00000000 110 */
+ 0x6f0e,
+ 0x6f0e, /* 00000000 11 */
+ 0x6f0e, /* 00000000 11 */
+ 0x6f0e, /* 00000000 11 */
+ 0xff10,
+ 0xff10,
+ 0xef10,
+ 0xef10, /* 000000000000 */
+ 0xdf10, /* 000000000000 1 */
+ 0xdf10, /* 000000000000 */
+ 0xee10, /* 00000000000 00 */
+ 0xee10, /* 00000000000 0 */
+ 0xcf10, /* 00000000000 01 */
+ 0xcf10,
+ 0xde10, /* 00000000000 10 */
+ 0xde10,
+ 0xbf10, /* 00000000000 11 */
+ 0xbf10, /* 00000000000 1 */
+ 0xfb10,
+ 0xfb10,
+ 0xce10,
+ 0xce10, /* 0000000000 00 */
+ 0xdc10, /* 0000000000 010 */
+ 0xdc10,
+ 0xaf11,
+ 0xe911,
+ 0xec0f, /* 0000000000 10 */
+ 0xec0f, /* 0000000000 1 */
+ 0xec0f, /* 0000000000 1 */
+ 0xec0f, /* 0000000000 1 */
+ 0xdd0f, /* 0000000000 11 */
+ 0xdd0f, /* 0000000000 1 */
+ 0xdd0f, /* 0000000000 1 */
+ 0xdd0f, /* 0000000000 1 */
+ 0xfa10, /* 000000000 0000 */
+ 0xfa10, /* 000000000 000 */
+ 0xcd10, /* 000000000 0 */
+ 0xcd10, /* 000000000 000 */
+ 0xbe0f, /* 000000000 */
+ 0xbe0f,
+ 0xbe0f,
+ 0xbe0f,
+ 0xeb0f,
+ 0xeb0f,
+ 0xeb0f,
+ 0xeb0f, /* 000000000 01 */
+ 0x9f0f, /* 000000000 011 */
+ 0x9f0f, /* 000000000 01 */
+ 0x9f0f,
+ 0x9f0f,
+ 0xf90f, /* 000000000 100 */
+ 0xf90f, /* 000000000 10 */
+ 0xf90f, /* 000000000 10 */
+ 0xf90f, /* 000000000 10 */
+ 0xea0f, /* 000000000 101 */
+ 0xea0f, /* 000000000 10 */
+ 0xea0f, /* 000000000 10 */
+ 0xea0f, /* 000000000 10 */
+ 0xbd0f, /* 000000000 110 */
+ 0xbd0f, /* 000000000 11 */
+ 0xbd0f, /* 000000000 11 */
+ 0xbd0f, /* 000000000 11 */
+ 0xdb0f, /* 000000000 111 */
+ 0xdb0f, /* 000000000 11 */
+ 0xdb0f, /* 000000000 11 */
+ 0xdb0f, /* 000000000 11 */
+ 0xfe13,
+ 0xfc13,
+ 0xfd12,
+ 0xfd12,
+ 0xed11,
+ 0xed11,
+ 0xed11,
+ 0xed11
+
+};
+
+
+
+const uint16 huffTable_15[421] =
+{
+ 0x1103,
+ 0x1103,
+ 0x0104,
+ 0x1004,
+ 0x0003, /* 111 */
+ 0x0003, /* 11 */
+ 0x3407,
+ 0x4307,
+ 0x2407, /* 0101 */
+ 0x4207, /* 0101010 */
+ 0x3307,
+ 0x4106, /* 010110 */
+ 0x4106,
+ 0x1407, /* 0101110 */
+ 0x0407,
+ 0x2306, /* 011000 */
+ 0x2306,
+ 0x3206, /* 011 */
+ 0x3206,
+ 0x4007,
+ 0x0307,
+ 0x1306, /* 011011 */
+ 0x1306, /* 01101 */
+ 0x3106, /* 011100 */
+ 0x3106, /* 01110 */
+ 0x3006, /* 011101 */
+ 0x3006, /* 01110 */
+ 0x2205, /* 01111 */
+ 0x2205, /* 0111 */
+ 0x2205, /* 0111 */
+ 0x2205, /* 0111 */
+ 0x1205, /* 10000 */
+ 0x1205, /* 1000 */
+ 0x1205, /* 1000 */
+ 0x1205, /* 1000 */
+ 0x2105, /* 10 */
+ 0x2105, /* 1000 */
+ 0x2105, /* 1000 */
+ 0x2105, /* 1000 */
+ 0x0205,
+ 0x0205, /* 1 */
+ 0x0205, /* 1 */
+ 0x0205, /* 1 */
+ 0x2005, /* 1 1 */
+ 0x2005, /* 1 */
+ 0x2005, /* 1 */
+ 0x2005, /* 1 */
+ 0x5809,
+ 0x8509,
+ 0x2909, /* */
+ 0x6709, /* 000 */
+ 0x7609, /* 00 0 */
+ 0x9209, /* 00 1 */
+ 0x9108, /* 0 0 */
+ 0x9108, /* 0 */
+ 0x1909, /* 0 10 */
+ 0x9009, /* 0 11 */
+ 0x4809, /* 000 */
+ 0x8409, /* */
+ 0x5709, /* 010 */
+ 0x7509, /* 011 */
+ 0x3809, /* 100 */
+ 0x8309, /* 101 */
+ 0x6609, /* 110 */
+ 0x4709, /* 111 */
+ 0x2808,
+ 0x2808, /* 0100 */
+ 0x8208, /* 01 */
+ 0x8208, /* 0100 */
+ 0x1808, /* 01010 */
+ 0x1808, /* 0101 */
+ 0x8108, /* 01011 */
+ 0x8108, /* 0101 */
+ 0x7409,
+ 0x0809, /* 011 */
+ 0x8009, /* 011010 */
+ 0x5609,
+ 0x6509, /* 011100 */
+ 0x3709,
+ 0x7309, /* 011110 */
+ 0x4609,
+ 0x2708, /* 10000 */
+ 0x2708, /* 1000 */
+ 0x7208, /* 10 */
+ 0x7208, /* 1000 */
+ 0x6408, /* 1 0 */
+ 0x6408, /* 1 */
+ 0x1708, /* 1 1 */
+ 0x1708, /* 1 */
+ 0x5508, /* 10100 */
+ 0x5508,
+ 0x7108, /* 10101 */
+ 0x7108,
+ 0x0709, /* 101100 */
+ 0x7009, /* 101101 */
+ 0x3608, /* 10111 */
+ 0x3608, /* 1011 */
+ 0x6308, /* 11000 */
+ 0x6308, /* 1100 */
+ 0x4508, /* 11 */
+ 0x4508, /* 1100 */
+ 0x5408, /* 11010 */
+ 0x5408, /* 1101 */
+ 0x2608, /* 11011 */
+ 0x2608, /* 1101 */
+ 0x6208, /* 11100 */
+ 0x6208, /* 1110 */
+ 0x1608, /* 11101 */
+ 0x1608, /* 1110 */
+ 0x0609, /* 111100 */
+ 0x6009, /* 111101 */
+ 0x3508, /* 11111 */
+ 0x3508, /* 1111 */
+ 0x6107,
+ 0x6107,
+ 0x6107,
+ 0x6107,
+ 0x5308, /* 0100 0 */
+ 0x5308, /* 0100 */
+ 0x4408, /* 0100 1 */
+ 0x4408, /* 0100 */
+ 0x2507, /* 010 0 */
+ 0x2507, /* 010 */
+ 0x2507, /* 010 */
+ 0x2507, /* 010 */
+ 0x5207, /* 010 1 */
+ 0x5207, /* 010 */
+ 0x5207, /* 010 */
+ 0x5207, /* 010 */
+ 0x1507, /* 01 00 */
+ 0x1507, /* 01 0 */
+ 0x1507, /* 01 0 */
+ 0x1507, /* 01 0 */
+ 0x5107, /* 01 01 */
+ 0x5107, /* 01 0 */
+ 0x5107, /* 01 0 */
+ 0x5107, /* 01 0 */
+ 0x0508, /* 01 100 */
+ 0x0508, /* 01 10 */
+ 0x5008, /* 01 101 */
+ 0x5008, /* 01 10 */
+ 0xc209,
+ 0xc209,
+ 0x2c0a, /* 00 11110 */
+ 0x5b0a,
+ 0xb50a, /* 0 */
+ 0x1c0a, /* 0 000 */
+ 0x890a, /* 0 00 0 */
+ 0x980a,
+ 0xc10a, /* 0 0 00 */
+ 0x4b0a, /* 0 0 01 */
+ 0xb40a, /* 0 0 10 */
+ 0x6a0a, /* 0 0 11 */
+ 0x3b0a, /* 0 000 */
+ 0x790a, /* 0 */
+ 0xb309, /* 0 01 */
+ 0xb309, /* 0 0 */
+ 0x970a, /* 0 100 */
+ 0x880a, /* 0 101 */
+ 0x2b0a, /* 0 110 */
+ 0x5a0a, /* 0 111 */
+ 0xb209, /* 0 01000 */
+ 0xb209, /* 0 0100 */
+ 0xa50a, /* 0 01 0 */
+ 0x1b0a, /* 0 01 1 */
+ 0xb109, /* 0 01010 */
+ 0xb109, /* 0 0101 */
+ 0xb00a, /* 0 010110 */
+ 0x690a, /* 0 010111 */
+ 0x960a, /* 0 011000 */
+ 0x4a0a, /* 0 011 */
+ 0xa40a, /* 0 011010 */
+ 0x780a, /* 0 011011 */
+ 0x870a, /* 0 011100 */
+ 0x3a0a, /* 0 011101 */
+ 0xa309, /* 0 01111 */
+ 0xa309, /* 0 0111 */
+ 0x5909, /* 0 10000 */
+ 0x5909, /* 0 1000 */
+ 0x9509, /* 0 10 */
+ 0x9509, /* 0 1000 */
+ 0x2a09, /* 0 1 0 */
+ 0x2a09, /* 0 1 */
+ 0xa209, /* 0 1 1 */
+ 0xa209, /* 0 1 */
+ 0x1a09, /* 0 10100 */
+ 0x1a09, /* 0 1010 */
+ 0xa109, /* 0 10101 */
+ 0xa109, /* 0 1010 */
+ 0x0a0a, /* 0 101100 */
+ 0xa00a, /* 0 101101 */
+ 0x6809, /* 0 10111 */
+ 0x6809, /* 0 1011 */
+ 0x8609, /* 0 11000 */
+ 0x8609, /* 0 1100 */
+ 0x4909, /* 0 11 */
+ 0x4909, /* 0 1100 */
+ 0x9409, /* 0 11010 */
+ 0x9409, /* 0 1101 */
+ 0x3909, /* 0 11011 */
+ 0x3909, /* 0 1101 */
+ 0x9309, /* 0 11100 */
+ 0x9309, /* 0 1110 */
+ 0x770a, /* 0 111010 */
+ 0x090a, /* 0 111011 */
+ 0x7c0b,
+ 0xc70b, /* 00 000 */
+ 0x4d0b, /* 00 00 0 */
+ 0x8b0b, /* 00 00 1 */
+ 0xd40a, /* 00 0 0 */
+ 0xd40a, /* 00 0 */
+ 0xb80b, /* 00 0 10 */
+ 0x9a0b, /* 00 0 11 */
+ 0xa90b, /* 00 000 */
+ 0x6c0b, /* 00 */
+ 0xc60b, /* 00 010 */
+ 0x3d0b, /* 00 011 */
+ 0xd30a, /* 00 10 */
+ 0xd30a, /* 00 1 */
+ 0xd20a, /* 00 11 */
+ 0xd20a, /* 00 1 */
+ 0x2d0b, /* 00 010000 */
+ 0x0d0b, /* 00 010 */
+ 0x1d0a, /* 00 01 */
+ 0x1d0a, /* 00 0100 */
+ 0x7b0a, /* 00 01010 */
+ 0x7b0a, /* 00 0101 */
+ 0xb70a, /* 00 01011 */
+ 0xb70a, /* 00 0101 */
+ 0xd10a, /* 00 01100 */
+ 0xd10a, /* 00 0110 */
+ 0x5c0b, /* 00 011010 */
+ 0xd00b, /* 00 011011 */
+ 0xc50a, /* 00 01110 */
+ 0xc50a, /* 00 0111 */
+ 0x8a0a, /* 00 01111 */
+ 0x8a0a, /* 00 0111 */
+ 0xa80a, /* 00 10000 */
+ 0xa80a, /* 00 1000 */
+ 0x4c0a, /* 00 10 */
+ 0x4c0a, /* 00 1000 */
+ 0xc40a, /* 00 1 0 */
+ 0xc40a, /* 00 1 */
+ 0x6b0a, /* 00 1 1 */
+ 0x6b0a, /* 00 1 */
+ 0xb60a, /* 00 10100 */
+ 0xb60a, /* 00 1010 */
+ 0x990b, /* 00 101010 */
+ 0x0c0b, /* 00 101011 */
+ 0x3c0a, /* 00 10110 */
+ 0x3c0a, /* 00 1011 */
+ 0xc30a, /* 00 10111 */
+ 0xc30a, /* 00 1011 */
+ 0x7a0a, /* 00 11000 */
+ 0x7a0a, /* 00 1100 */
+ 0xa70a, /* 00 11 */
+ 0xa70a, /* 00 1100 */
+ 0xa60a, /* 00 11010 */
+ 0xa60a, /* 00 1101 */
+ 0xc00b, /* 00 110110 */
+ 0x0b0b, /* 00 110111 */
+ 0xcb0b,
+ 0xcb0b, /* 0000 000 */
+ 0xf60b, /* 0000 0 */
+ 0xf60b, /* 0000 000 */
+ 0x8e0c, /* 0000 00 */
+ 0xe80c, /* 0000 01 */
+ 0x5f0c, /* 0000 10 */
+ 0x9d0c, /* 0000 11 */
+ 0xf50b, /* 0000 0100 */
+ 0xf50b, /* 0000 010 */
+ 0x7e0b, /* 0000 0101 */
+ 0x7e0b, /* 0000 010 */
+ 0xe70b, /* 0000 0110 */
+ 0xe70b, /* 0000 011 */
+ 0xac0b, /* 0000 0111 */
+ 0xac0b, /* 0000 011 */
+ 0xca0b, /* 0000 1000 */
+ 0xca0b, /* 0000 100 */
+ 0xbb0b, /* 0000 1 */
+ 0xbb0b, /* 0000 100 */
+ 0xd90c, /* 0000 10100 */
+ 0x8d0c, /* 0000 10101 */
+ 0x4f0b, /* 0000 1011 */
+ 0x4f0b, /* 0000 101 */
+ 0xf40b, /* 0000 1100 */
+ 0xf40b, /* 0000 110 */
+ 0x3f0b, /* 0000 1101 */
+ 0x3f0b, /* 0000 110 */
+ 0xf30b, /* 0000 1110 */
+ 0xf30b, /* 0000 111 */
+ 0xd80b, /* 0000 1111 */
+ 0xd80b, /* 0000 111 */
+ 0xe60b, /* 000 */
+ 0xe60b, /* 000 0000 */
+ 0x2f0b, /* 000 00 */
+ 0x2f0b, /* 000 0000 */
+ 0xf20b, /* 000 0 0 */
+ 0xf20b, /* 000 0 */
+ 0x6e0c, /* 000 0 10 */
+ 0xf00c, /* 000 0 11 */
+ 0x1f0b, /* 000 00 */
+ 0x1f0b, /* 000 0 */
+ 0xf10b, /* 000 01 */
+ 0xf10b, /* 000 0 */
+ 0x9c0b, /* 000 10 */
+ 0x9c0b, /* 000 1 */
+ 0xc90b, /* 000 11 */
+ 0xc90b, /* 000 1 */
+ 0x5e0b, /* 000 01000 */
+ 0x5e0b, /* 000 0100 */
+ 0xab0b, /* 000 01 */
+ 0xab0b, /* 000 0100 */
+ 0xba0b, /* 000 01010 */
+ 0xba0b, /* 000 0101 */
+ 0xe50b, /* 000 01011 */
+ 0xe50b, /* 000 0101 */
+ 0x7d0b, /* 000 01100 */
+ 0x7d0b, /* 000 0110 */
+ 0xd70b, /* 000 01101 */
+ 0xd70b,
+ 0x4e0b, /* 000 01110 */
+ 0x4e0b,
+ 0xe40b, /* 000 01111 */
+ 0xe40b, /* 000 0111 */
+ 0x8c0b,
+ 0x8c0b, /* 000 1000 */
+ 0xc80b, /* 000 10 */
+ 0xc80b,
+ 0x3e0b, /* 000 1 0 */
+ 0x3e0b, /* 000 1 */
+ 0x6d0b,
+ 0x6d0b, /* 000 1 */
+ 0xd60b, /* 000 10100 */
+ 0xd60b, /* 000 1010 */
+ 0xe30b,
+ 0xe30b, /* 000 1010 */
+ 0x9b0b, /* 000 10110 */
+ 0x9b0b, /* 000 1011 */
+ 0xb90b,
+ 0xb90b, /* 000 1011 */
+ 0x2e0b, /* 000 11000 */
+ 0x2e0b, /* 000 1100 */
+ 0xaa0b,
+ 0xaa0b, /* 000 1100 */
+ 0xe20b,
+ 0xe20b, /* 000 1101 */
+ 0x1e0b,
+ 0x1e0b, /* 000 1101 */
+ 0xe10b,
+ 0xe10b, /* 000 1110 */
+ 0x0e0c,
+ 0xe00c, /* 000 111011 */
+ 0x5d0b,
+ 0x5d0b, /* 000 1111 */
+ 0xd50b,
+ 0xd50b, /* 000 1111 */
+ 0xff0d,
+ 0xef0d,
+ 0xfe0d,
+ 0xdf0d,
+ 0xee0c,
+ 0xee0c,
+ 0xfd0d,
+ 0xcf0d,
+ 0xfc0d,
+ 0xde0d,
+ 0xed0d,
+ 0xbf0d,
+ 0xfb0c,
+ 0xfb0c,
+ 0xce0d,
+ 0xec0d,
+ 0xdd0c, /* 000 */
+ 0xdd0c, /* 00 */
+ 0xaf0c, /* */
+ 0xaf0c, /* 00 */
+ 0xfa0c, /* 010 */
+ 0xfa0c, /* 01 */
+ 0xbe0c, /* 011 */
+ 0xbe0c, /* 01 */
+ 0xeb0c, /* 100 */
+ 0xeb0c, /* 10 */
+ 0xcd0c, /* 101 */
+ 0xcd0c, /* 10 */
+ 0xdc0c, /* 110 */
+ 0xdc0c, /* 11 */
+ 0x9f0c, /* 111 */
+ 0x9f0c, /* 11 */
+ 0xf90c, /* 0000 */
+ 0xf90c, /* 000 */
+ 0xea0c, /* 0 */
+ 0xea0c, /* 000 */
+ 0xbd0c, /* 0 */
+ 0xbd0c, /* */
+ 0xdb0c, /* 1 */
+ 0xdb0c, /* */
+ 0x8f0c, /* 0100 */
+ 0x8f0c, /* 010 */
+ 0xf80c, /* 0101 */
+ 0xf80c, /* 010 */
+ 0xcc0c,
+ 0xcc0c, /* 011 */
+ 0x9e0c, /* 0111 */
+ 0x9e0c, /* 011 */
+ 0xe90c, /* 1000 */
+ 0xe90c, /* 100 */
+ 0x7f0c, /* 1 */
+ 0x7f0c,
+ 0xf70c, /* 1010 */
+ 0xf70c, /* 101 */
+ 0xad0c, /* 1011 */
+ 0xad0c, /* 101 */
+ 0xda0c, /* 1100 */
+ 0xda0c, /* 110 */
+ 0xbc0c,
+ 0xbc0c, /* 110 */
+ 0x6f0c, /* 1110 */
+ 0x6f0c, /* 111 */
+ 0xae0d, /* 11110 */
+ 0x0f0d
+};
+
+const uint16 huffTable_16[465] =
+{
+ 0x0001,
+ 0x1104,
+ 0x0104,
+ 0x1003,
+ 0x1003,
+ 0x2308,
+ 0x3208, /* 11 */
+ 0x1307, /* 0100 */
+ 0x1307, /* 010 */
+ 0x3107,
+ 0x3107,
+ 0x0308,
+ 0x3008,
+ 0x2207, /* 0111 */
+ 0x2207, /* 011 */
+ 0x1206, /* 100 */
+ 0x1206, /* 10 */
+ 0x1206, /* 10 */
+ 0x1206, /* 10 */
+ 0x2106, /* 101 */
+ 0x2106, /* 10 */
+ 0x2106, /* 10 */
+ 0x2106, /* 10 */
+ 0x0206,
+ 0x0206,
+ 0x0206,
+ 0x0206,
+ 0x2006,
+ 0x2006,
+ 0x2006,
+ 0x2006,
+ 0x1709,
+ 0x1709, /* 0 0111 */
+ 0x7109, /* 0 10000 */
+ 0x7109, /* 0 1000 */
+ 0x700a, /* 0 10 0 */
+ 0x360a, /* 0 10 1 */
+ 0x630a, /* 0 1 00 */
+ 0x450a, /* 0 1 01 */
+ 0x540a, /* 0 1 10 */
+ 0x260a, /* 0 1 11 */
+ 0x6209, /* 0 10100 */
+ 0x6209, /* 0 1010 */
+ 0x1609,
+ 0x1609,
+ 0x6109, /* 0 10110 */
+ 0x6109, /* 0 1011 */
+ 0x060a, /* 0 101110 */
+ 0x600a,
+ 0x5309,
+ 0x5309, /* 0 1100 */
+ 0x350a, /* 0 11 0 */
+ 0x440a, /* 0 11 1 */
+ 0x2509, /* 0 11010 */
+ 0x2509, /* 0 1101 */
+ 0x5209, /* 0 11011 */
+ 0x5209, /* 0 1101 */
+ 0x5108,
+ 0x5108,
+ 0x5108,
+ 0x5108,
+ 0x1509,
+ 0x1509, /* 0 1111 */
+ 0x0509, /* 0 11111 */
+ 0x0509, /* 0 1111 */
+ 0x3409, /* */
+ 0x3409, /* */
+ 0x4309, /* 000 */
+ 0x4309, /* */
+ 0x5009, /* 00 0 */
+ 0x5009, /* 00 */
+ 0x2409, /* 00 1 */
+ 0x2409, /* 00 */
+ 0x4209, /* 0 00 */
+ 0x4209, /* 0 0 */
+ 0x3309, /* 0 01 */
+ 0x3309, /* 0 0 */
+ 0x1408, /* 0 1 */
+ 0x1408, /* 0 */
+ 0x1408, /* 0 */
+ 0x1408, /* 0 */
+ 0x4108, /* 00 */
+ 0x4108, /* 0 */
+ 0x4108, /* 0 */
+ 0x4108, /* 0 */
+ 0x0409, /* 010 */
+ 0x0409, /* 01 */
+ 0x4009, /* 011 */
+ 0x4009, /* 01 */
+ 0x1d0b,
+ 0x1d0b, /* 00 10101 */
+ 0xc40c, /* 00 1011000 */
+ 0x6b0c, /* 00 1011 */
+ 0xc30c, /* 00 1011010 */
+ 0xa70c, /* 00 1011011 */
+ 0x2c0b, /* 00 101110 */
+ 0x2c0b, /* 00 10111 */
+ 0xc20c, /* 00 1011110 */
+ 0xb50c, /* 00 1011111 */
+ 0xc10c, /* 00 1100000 */
+ 0x0c0c, /* 00 1100 */
+ 0x4b0c, /* 00 110 0 */
+ 0xb40c, /* 00 110 1 */
+ 0x6a0c, /* 00 11 00 */
+ 0xa60c, /* 00 11 01 */
+ 0xb30b, /* 00 11 1 */
+ 0xb30b, /* 00 11 */
+ 0x5a0c, /* 00 1101000 */
+ 0xa50c, /* 00 1101 */
+ 0x2b0b, /* 00 110101 */
+ 0x2b0b, /* 00 11010 */
+ 0xb20b, /* 00 110110 */
+ 0xb20b, /* 00 11011 */
+ 0x1b0b, /* 00 110111 */
+ 0x1b0b, /* 00 11011 */
+ 0xb10b, /* 00 111000 */
+ 0xb10b, /* 00 11100 */
+ 0x0b0c, /* 00 111 0 */
+ 0xb00c, /* 00 111 1 */
+ 0x690c, /* 00 1110100 */
+ 0x960c, /* 00 1110101 */
+ 0x4a0c, /* 00 1110110 */
+ 0xa40c, /* 00 1110111 */
+ 0x780c, /* 00 1111000 */
+ 0x870c, /* 00 1111 */
+ 0xa30b, /* 00 111101 */
+ 0xa30b, /* 00 11110 */
+ 0x3a0c, /* 00 1111100 */
+ 0x590c, /* 00 1111101 */
+ 0x2a0b, /* 00 111111 */
+ 0x2a0b, /* 00 11111 */
+ 0x950c, /* 0 00000000 */
+ 0x680c, /* 0 */
+ 0xa10b, /* 0 0000 */
+ 0xa10b, /* 0 */
+ 0x860c, /* 0 000 00 */
+ 0x770c, /* 0 000 01 */
+ 0x940b, /* 0 000 1 */
+ 0x940b, /* 0 000 */
+ 0x490c, /* 0 00 000 */
+ 0x570c, /* 0 00 */
+ 0x670b, /* 0 00 01 */
+ 0x670b, /* 0 00 0 */
+ 0xa20a, /* 0 00 1 */
+ 0xa20a, /* 0 00 */
+ 0xa20a, /* 0 00 */
+ 0xa20a, /* 0 00 */
+ 0x1a0a, /* 0 0 00 */
+ 0x1a0a, /* 0 0 0 */
+ 0x1a0a, /* 0 0 0 */
+ 0x1a0a, /* 0 0 0 */
+ 0x0a0b, /* 0 0 010 */
+ 0x0a0b, /* 0 0 01 */
+ 0xa00b, /* 0 0 011 */
+ 0xa00b, /* 0 0 01 */
+ 0x390b, /* 0 0 100 */
+ 0x390b, /* 0 0 10 */
+ 0x930b, /* 0 0 101 */
+ 0x930b, /* 0 0 10 */
+ 0x580b, /* 0 0 110 */
+ 0x580b, /* 0 0 11 */
+ 0x850b, /* 0 0 111 */
+ 0x850b, /* 0 0 11 */
+ 0x290a, /* 0 000 */
+ 0x290a, /* 0 00 */
+ 0x290a, /* 0 00 */
+ 0x290a, /* 0 00 */
+ 0x920a, /* 0 */
+ 0x920a, /* 0 00 */
+ 0x920a, /* 0 00 */
+ 0x920a, /* 0 00 */
+ 0x760b, /* 0 0100 */
+ 0x760b, /* 0 010 */
+ 0x090b, /* 0 0101 */
+ 0x090b, /* 0 010 */
+ 0x190a, /* 0 011 */
+ 0x190a, /* 0 01 */
+ 0x190a, /* 0 01 */
+ 0x190a, /* 0 01 */
+ 0x910a, /* 0 100 */
+ 0x910a, /* 0 10 */
+ 0x910a, /* 0 10 */
+ 0x910a, /* 0 10 */
+ 0x900b, /* 0 1010 */
+ 0x900b, /* 0 101 */
+ 0x480b, /* 0 1011 */
+ 0x480b, /* 0 101 */
+ 0x840b, /* 0 1100 */
+ 0x840b, /* 0 110 */
+ 0x750b, /* 0 1101 */
+ 0x750b, /* 0 110 */
+ 0x380b, /* 0 1110 */
+ 0x380b, /* 0 111 */
+ 0x830b, /* 0 1111 */
+ 0x830b, /* 0 111 */
+ 0x660b, /* 0 0100000 */
+ 0x660b, /* 0 010000 */
+ 0x280b, /* 0 0100 */
+ 0x280b, /* 0 010000 */
+ 0x820a, /* 0 010 */
+ 0x820a, /* 0 01000 */
+ 0x820a, /* 0 01000 */
+ 0x820a, /* 0 01000 */
+ 0x470b, /* 0 01 00 */
+ 0x470b, /* 0 01 0 */
+ 0x740b, /* 0 01 01 */
+ 0x740b, /* 0 01 0 */
+ 0x180a, /* 0 01 1 */
+ 0x180a, /* 0 01 */
+ 0x180a, /* 0 01 */
+ 0x180a, /* 0 01 */
+ 0x810a, /* 0 010100 */
+ 0x810a, /* 0 01010 */
+ 0x810a, /* 0 01010 */
+ 0x810a, /* 0 01010 */
+ 0x800a, /* 0 010101 */
+ 0x800a, /* 0 01010 */
+ 0x800a, /* 0 01010 */
+ 0x800a, /* 0 01010 */
+ 0x080b, /* 0 0101100 */
+ 0x080b, /* 0 010110 */
+ 0x560b, /* 0 0101101 */
+ 0x560b, /* 0 010110 */
+ 0x370a, /* 0 010111 */
+ 0x370a, /* 0 01011 */
+ 0x370a, /* 0 01011 */
+ 0x370a, /* 0 01011 */
+ 0x730a, /* 0 011000 */
+ 0x730a, /* 0 01100 */
+ 0x730a, /* 0 01100 */
+ 0x730a, /* 0 01100 */
+ 0x650b, /* 0 011 0 */
+ 0x650b, /* 0 011 */
+ 0x460b, /* 0 011 1 */
+ 0x460b, /* 0 011 */
+ 0x270a, /* 0 011010 */
+ 0x270a, /* 0 01101 */
+ 0x270a, /* 0 01101 */
+ 0x270a, /* 0 01101 */
+ 0x720a, /* 0 011011 */
+ 0x720a, /* 0 01101 */
+ 0x720a, /* 0 01101 */
+ 0x720a, /* 0 01101 */
+ 0x640b, /* 0 0111000 */
+ 0x640b, /* 0 011100 */
+ 0x550b, /* 0 0111 */
+ 0x550b, /* 0 011100 */
+ 0x070a, /* 0 011101 */
+ 0x070a, /* 0 01110 */
+ 0x070a, /* 0 01110 */
+ 0x070a, /* 0 01110 */
+ 0x9e0d,
+ 0x9e0d, /* 00 0110000 */
+ 0xbc0e, /* 00 01100 0 */
+ 0xcb0e, /* 00 01100 1 */
+ 0x8e0e, /* 00 0110 00 */
+ 0xe80e, /* 00 0110 01 */
+ 0x9d0e, /* 00 0110 10 */
+ 0xe70e, /* 00 0110 11 */
+ 0xbb0e, /* 00 011 000 */
+ 0x8d0e, /* 00 011 */
+ 0xd80e, /* 00 011 010 */
+ 0x6e0e, /* 00 011 011 */
+ 0xe60d, /* 00 011 10 */
+ 0xe60d, /* 00 011 1 */
+ 0x9c0d, /* 00 011 11 */
+ 0x9c0d, /* 00 011 1 */
+ 0xab0e, /* 00 011010000 */
+ 0xba0e, /* 00 011010 */
+ 0xe50e, /* 00 01101 0 */
+ 0xd70e, /* 00 01101 1 */
+ 0x4e0d, /* 00 01101010 */
+ 0x4e0d, /* 00 0110101 */
+ 0xe40e, /* 00 011010110 */
+ 0x8c0e, /* 00 011010111 */
+ 0xc80d, /* 00 01101100 */
+ 0xc80d, /* 00 0110110 */
+ 0x3e0d, /* 00 01101101 */
+ 0x3e0d, /* 00 0110110 */
+ 0x6d0d, /* 00 01101110 */
+ 0x6d0d, /* 00 0110111 */
+ 0xd60e, /* 00 011011110 */
+ 0x9b0e, /* 00 011011111 */
+ 0xb90e, /* 00 011100000 */
+ 0xaa0e, /* 00 011100 */
+ 0xe10d, /* 00 01110 */
+ 0xe10d, /* 00 0111000 */
+ 0xd40d, /* 00 0111 0 */
+ 0xd40d, /* 00 0111 */
+ 0xb80e, /* 00 0111 10 */
+ 0xa90e, /* 00 0111 11 */
+ 0x7b0d, /* 00 01110100 */
+ 0x7b0d, /* 00 0111010 */
+ 0xb70e, /* 00 011101010 */
+ 0xd00e, /* 00 011101011 */
+ 0xe30c, /* 00 0111011 */
+ 0xe30c, /* 00 011101 */
+ 0xe30c, /* 00 011101 */
+ 0xe30c, /* 00 011101 */
+ 0x0e0d, /* 00 01111000 */
+ 0x0e0d, /* 00 0111100 */
+ 0xe00d, /* 00 01111 */
+ 0xe00d, /* 00 0111100 */
+ 0x5d0d, /* 00 01111010 */
+ 0x5d0d, /* 00 0111101 */
+ 0xd50d, /* 00 01111011 */
+ 0xd50d, /* 00 0111101 */
+ 0x7c0d, /* 00 01111100 */
+ 0x7c0d, /* 00 0111110 */
+ 0xc70d, /* 00 01111101 */
+ 0xc70d, /* 00 0111110 */
+ 0x4d0d, /* 00 01111110 */
+ 0x4d0d, /* 00 0111111 */
+ 0x8b0d, /* 00 01111111 */
+ 0x8b0d, /* 00 0111111 */
+ 0x9a0d,
+ 0x6c0d, /* 00 10000 */
+ 0xc60d, /* 00 1000 0 */
+ 0x3d0d, /* 00 1000 1 */
+ 0x5c0d, /* 00 100 00 */
+ 0xc50d, /* 00 100 01 */
+ 0x0d0c, /* 00 100 1 */
+ 0x0d0c, /* 00 100 */
+ 0x8a0d, /* 00 10 000 */
+ 0xa80d, /* 00 10 */
+ 0x990d, /* 00 10 010 */
+ 0x4c0d, /* 00 10 011 */
+ 0xb60d, /* 00 10 100 */
+ 0x7a0d, /* 00 10 101 */
+ 0x3c0c, /* 00 10 11 */
+ 0x3c0c, /* 00 10 1 */
+ 0x5b0d, /* 00 1 0000 */
+ 0x890d, /* 00 1 0 */
+ 0x1c0c, /* 00 1 */
+ 0x1c0c, /* 00 1 00 */
+ 0xc00c, /* 00 1 010 */
+ 0xc00c, /* 00 1 01 */
+ 0x980d, /* 00 1 0110 */
+ 0x790d, /* 00 1 0111 */
+ 0xe20b, /* 00 1 10 */
+ 0xe20b, /* 00 1 1 */
+ 0xe20b, /* 00 1 1 */
+ 0xe20b, /* 00 1 1 */
+ 0x2e0c, /* 00 1 110 */
+ 0x2e0c, /* 00 1 11 */
+ 0x1e0c, /* 00 1 111 */
+ 0x1e0c, /* 00 1 11 */
+ 0xd30c, /* 00 1010000 */
+ 0xd30c, /* 00 101000 */
+ 0x2d0c, /* 00 1010 */
+ 0x2d0c, /* 00 101000 */
+ 0xd20c, /* 00 101 0 */
+ 0xd20c, /* 00 101 */
+ 0xd10c, /* 00 101 1 */
+ 0xd10c, /* 00 101 */
+ 0x3b0c, /* 00 1010100 */
+ 0x3b0c, /* 00 101010 */
+ 0x970d, /* 00 10101010 */
+ 0x880d, /* 00 10101011 */
+ 0xf208,
+ 0xf208, /* 000 1 */
+ 0x2f09, /* 00 0000 */
+ 0x0f09, /* 00 0 */
+ 0x1f08, /* 00 */
+ 0x1f08, /* 00 00 */
+ 0xf108, /* 00 010 */
+ 0xf108, /* 00 01 */
+ 0xce10,
+ 0xce10, /* 000 101100000 */
+ 0xec11, /* 000 1011000 0 */
+ 0xdd11, /* 000 1011000 1 */
+ 0xde0f, /* 000 101100 */
+ 0xde0f, /* 000 10110000 */
+ 0xde0f, /* 000 10110000 */
+ 0xde0f, /* 000 10110000 */
+ 0xe90f, /* 000 10110 0 */
+ 0xe90f, /* 000 10110 */
+ 0xe90f, /* 000 10110 */
+ 0xe90f, /* 000 10110 */
+ 0xea10, /* 000 10110 10 */
+ 0xea10, /* 000 10110 1 */
+ 0xd910, /* 000 10110 11 */
+ 0xd910, /* 000 10110 1 */
+ 0xee0e,
+ 0xee0e, /* 000 1011 */
+ 0xed0f, /* 000 1011 10 */
+ 0xeb0f, /* 000 1011 11 */
+ 0xbe0e, /* 000 10110100 */
+ 0xbe0e, /* 000 1011010 */
+ 0xcd0e, /* 000 10110101 */
+ 0xcd0e, /* 000 1011010 */
+ 0xdc0f, /* 000 101101100 */
+ 0xdb0f, /* 000 101101101 */
+ 0xae0e, /* 000 10110111 */
+ 0xae0e, /* 000 1011011 */
+ 0xcc0e, /* 000 10111000 */
+ 0xcc0e, /* 000 1011100 */
+ 0xad0f, /* 000 10111 0 */
+ 0xda0f, /* 000 10111 1 */
+ 0x7e0f, /* 000 101110100 */
+ 0xac0f, /* 000 101110101 */
+ 0xca0e, /* 000 10111011 */
+ 0xca0e, /* 000 1011101 */
+ 0xc90f, /* 000 101111000 */
+ 0x7d0f, /* 000 101111 */
+ 0x5e0e, /* 000 10111101 */
+ 0x5e0e, /* 000 1011110 */
+ 0xbd0d, /* 000 1011111 */
+ 0xbd0d, /* 000 101111 */
+ 0xbd0d, /* 000 101111 */
+ 0xbd0d, /* 000 101111 */
+ 0xef0b,
+ 0xfe0b, /* 00000000 */
+ 0xdf0b, /* 0000000 0 */
+ 0xfd0b, /* 0000000 1 */
+ 0xcf0b, /* 00 */
+ 0xfc0b, /* 01 */
+ 0xbf0b, /* 10 */
+ 0xfb0b, /* 11 */
+ 0xaf0a, /* 00 */
+ 0xaf0a, /* 0 */
+ 0xfa0b, /* 010 */
+ 0x9f0b, /* 011 */
+ 0xf90b, /* 100 */
+ 0xf80b, /* 101 */
+ 0x8f0a, /* 11 */
+ 0x8f0a, /* 1 */
+ 0x7f0a, /* 0000 000 */
+ 0x7f0a, /* 0000 00 */
+ 0xf70a, /* 0000 */
+ 0xf70a, /* 0000 00 */
+ 0x6f0a, /* 0000 010 */
+ 0x6f0a, /* 0000 01 */
+ 0xf60a, /* 0000 011 */
+ 0xf60a, /* 0000 01 */
+ 0xff08, /* 0000 1 */
+ 0xff08, /* 0000 */
+ 0xff08, /* 0000 */
+ 0xff08, /* 0000 */
+ 0xff08, /* 0000 */
+ 0xff08, /* 0000 */
+ 0xff08, /* 0000 */
+ 0xff08, /* 0000 */
+ 0x5f0a, /* 000 0000 */
+ 0x5f0a, /* 000 000 */
+ 0xf50a, /* 000 0 */
+ 0xf50a, /* 000 000 */
+ 0x4f09, /* 000 */
+ 0x4f09, /* 000 00 */
+ 0x4f09, /* 000 00 */
+ 0x4f09, /* 000 00 */
+ 0xf409, /* 000 010 */
+ 0xf409, /* 000 01 */
+ 0xf409, /* 000 01 */
+ 0xf409, /* 000 01 */
+ 0xf309, /* 000 011 */
+ 0xf309, /* 000 01 */
+ 0xf309, /* 000 01 */
+ 0xf309, /* 000 01 */
+ 0xf009, /* 000 100 */
+ 0xf009, /* 000 10 */
+ 0xf009, /* 000 10 */
+ 0xf009, /* 000 10 */
+ 0x3f0a,
+ 0x3f0a
+};
+
+
+
+const uint16 huffTable_24[478] =
+{
+
+ 0x2206, /* 101 */
+ 0x1205, /* 10101 */
+ 0x1205, /* 1010 */
+ 0x2105, /* 10110 */
+ 0x2105, /* 1011 */
+ 0x0206, /* 101110 */
+ 0x2006, /* 101111 */
+ 0x1104,
+ 0x1104,
+ 0x1104,
+ 0x1104,
+ 0x0104,
+ 0x0104,
+ 0x0104,
+ 0x0104,
+ 0x1004,
+ 0x1004,
+ 0x1004,
+ 0x1004,
+ 0x0004,
+ 0x0004,
+ 0x0004,
+ 0x0004,
+ 0x7308,
+ 0x7308,
+ 0x3709,
+ 0x2709,
+ 0x7208,
+ 0x7208,
+ 0x4608, /* 01110000 */
+ 0x4608, /* 0111000 */
+ 0x6408, /* 01110 */
+ 0x6408, /* 0111000 */
+ 0x5508, /* 0111 0 */
+ 0x5508, /* 0111 */
+ 0x7108, /* 0111 1 */
+ 0x7108, /* 0111 */
+ 0x3608, /* 01110100 */
+ 0x3608, /* 0111010 */
+ 0x6308, /* 01110101 */
+ 0x6308, /* 0111010 */
+ 0x4508, /* 01110110 */
+ 0x4508, /* 0111011 */
+ 0x5408, /* 01110111 */
+ 0x5408, /* 0111011 */
+ 0x2608, /* 01111000 */
+ 0x2608, /* 0111100 */
+ 0x6208, /* 01111 */
+ 0x6208, /* 0111100 */
+ 0x1608, /* 01111010 */
+ 0x1608, /* 0111101 */
+ 0x6108, /* 01111011 */
+ 0x6108, /* 0111101 */
+ 0x0609, /* 011111000 */
+ 0x6009, /* 011111 */
+ 0x3508, /* 01111101 */
+ 0x3508, /* 0111110 */
+ 0x5308, /* 01111110 */
+ 0x5308, /* 0111111 */
+ 0x4408, /* 01111111 */
+ 0x4408, /* 0111111 */
+ 0x2508, /* 10000000 */
+ 0x2508, /* 1000000 */
+ 0x5208, /* 10000 */
+ 0x5208, /* 1000000 */
+ 0x1508, /* 1000 0 */
+ 0x1508, /* 1000 */
+ 0x0509, /* 1000 10 */
+ 0x5009, /* 1000 11 */
+ 0x5107, /* 100 0 */
+ 0x5107, /* 100 */
+ 0x5107, /* 100 */
+ 0x5107, /* 100 */
+ 0x3408, /* 100 10 */
+ 0x3408, /* 100 1 */
+ 0x4308, /* 100 11 */
+ 0x4308, /* 100 1 */
+ 0x2407, /* 10 00 */
+ 0x2407, /* 10 0 */
+ 0x2407, /* 10 0 */
+ 0x2407, /* 10 0 */
+ 0x4207, /* 10 01 */
+ 0x4207, /* 10 0 */
+ 0x4207, /* 10 0 */
+ 0x4207, /* 10 0 */
+ 0x3307, /* 10 10 */
+ 0x3307, /* 10 1 */
+ 0x3307, /* 10 1 */
+ 0x3307, /* 10 1 */
+ 0x1407, /* 10 11 */
+ 0x1407, /* 10 1 */
+ 0x1407, /* 10 1 */
+ 0x1407, /* 10 1 */
+ 0x4107, /* 1 000 */
+ 0x4107, /* 1 00 */
+ 0x4107, /* 1 00 */
+ 0x4107, /* 1 00 */
+ 0x0408, /* 1 0 */
+ 0x0408, /* 1 */
+ 0x4008, /* 1 1 */
+ 0x4008, /* 1 */
+ 0x2307, /* 1 010 */
+ 0x2307, /* 1 01 */
+ 0x2307, /* 1 01 */
+ 0x2307, /* 1 01 */
+ 0x3207, /* 1 011 */
+ 0x3207, /* 1 01 */
+ 0x3207, /* 1 01 */
+ 0x3207, /* 1 01 */
+ 0x1306, /* 1 10 */
+ 0x1306, /* 1 1 */
+ 0x1306, /* 1 1 */
+ 0x1306, /* 1 1 */
+ 0x1306, /* 1 1 */
+ 0x1306, /* 1 1 */
+ 0x1306, /* 1 1 */
+ 0x1306, /* 1 1 */
+ 0x3106, /* 1 11 */
+ 0x3106, /* 1 1 */
+ 0x3106, /* 1 1 */
+ 0x3106, /* 1 1 */
+ 0x3106, /* 1 1 */
+ 0x3106, /* 1 1 */
+ 0x3106, /* 1 1 */
+ 0x3106, /* 1 1 */
+ 0x0307, /* 1010000 */
+ 0x0307, /* 101000 */
+ 0x0307, /* 101000 */
+ 0x0307, /* 101000 */
+ 0x3007, /* 1010 */
+ 0x3007, /* 101000 */
+ 0x3007, /* 101000 */
+ 0x3007, /* 101000 */
+ 0xb309,
+ 0xb309,
+ 0x8809, /* 010101 */
+ 0x8809, /* 01010100 */
+ 0x2b0a, /* 0101010100 */
+ 0x5a0a, /* 0101010101 */
+ 0xb209, /* 010101011 */
+ 0xb209, /* 01010101 */
+ 0xa50a, /* 0101011000 */
+ 0x1b0a, /* 0101011 */
+ 0xb10a, /* 0101011010 */
+ 0x690a, /* 0101011011 */
+ 0x9609, /* 010101110 */
+ 0x9609, /* 01010111 */
+ 0xa409, /* 010101111 */
+ 0xa409, /* 01010111 */
+ 0x4a0a, /* 0101100000 */
+ 0x780a, /* 0101100 */
+ 0x8709, /* 010110 */
+ 0x8709, /* 01011000 */
+ 0x3a09, /* 01011 0 */
+ 0x3a09, /* 01011 */
+ 0xa309, /* 01011 1 */
+ 0xa309, /* 01011 */
+ 0x5909, /* 010110100 */
+ 0x5909, /* 01011010 */
+ 0x9509, /* 010110101 */
+ 0x9509, /* 01011010 */
+ 0x2a09, /* 010110110 */
+ 0x2a09, /* 01011011 */
+ 0xa209, /* 010110111 */
+ 0xa209, /* 01011011 */
+ 0xa109, /* 010111000 */
+ 0xa109, /* 01011100 */
+ 0x6809, /* 010111 */
+ 0x6809, /* 01011100 */
+ 0x8609, /* 010111010 */
+ 0x8609, /* 01011101 */
+ 0x7709, /* 010111011 */
+ 0x7709, /* 01011101 */
+ 0x4909, /* 010111100 */
+ 0x4909, /* 01011110 */
+ 0x9409, /* 010111101 */
+ 0x9409, /* 01011110 */
+ 0x3909, /* 010111110 */
+ 0x3909, /* 01011111 */
+ 0x9309, /* 010111111 */
+ 0x9309, /* 01011111 */
+ 0x5809, /* 011000000 */
+ 0x5809, /* 01100000 */
+ 0x8509, /* 011000 */
+ 0x8509, /* 01100000 */
+ 0x2909, /* 01100 0 */
+ 0x2909, /* 01100 */
+ 0x6709, /* 01100 1 */
+ 0x6709, /* 01100 */
+ 0x7609, /* 0110 00 */
+ 0x7609, /* 0110 0 */
+ 0x9209, /* 0110 01 */
+ 0x9209, /* 0110 0 */
+ 0x1909, /* 0110 10 */
+ 0x1909, /* 0110 1 */
+ 0x9109, /* 0110 11 */
+ 0x9109, /* 0110 1 */
+ 0x4809, /* 011 000 */
+ 0x4809, /* 011 00 */
+ 0x8409, /* 011 */
+ 0x8409, /* 011 00 */
+ 0x5709, /* 011 010 */
+ 0x5709, /* 011 01 */
+ 0x7509, /* 011 011 */
+ 0x7509, /* 011 01 */
+ 0x3809, /* 011 100 */
+ 0x3809, /* 011 10 */
+ 0x8309, /* 011 101 */
+ 0x8309, /* 011 10 */
+ 0x6609, /* 011 110 */
+ 0x6609, /* 011 11 */
+ 0x2809, /* 011 111 */
+ 0x2809, /* 011 11 */
+ 0x8209, /* 011010000 */
+ 0x8209, /* 01101000 */
+ 0x1809, /* 011010 */
+ 0x1809, /* 01101000 */
+ 0x4709, /* 01101 0 */
+ 0x4709, /* 01101 */
+ 0x7409, /* 01101 1 */
+ 0x7409, /* 01101 */
+ 0x8109, /* 011010100 */
+ 0x8109, /* 01101010 */
+ 0x080a, /* 0110101010 */
+ 0x800a, /* 0110101011 */
+ 0x5609, /* 011010110 */
+ 0x5609, /* 01101011 */
+ 0x6509, /* 011010111 */
+ 0x6509, /* 01101011 */
+ 0x1709, /* 011011000 */
+ 0x1709, /* 01101100 */
+ 0x070a, /* 011011 0 */
+ 0x700a, /* 011011 1 */
+ 0x6e0b,
+ 0x9c0b,
+ 0xc90a, /* 01000 01 */
+ 0xc90a, /* 01000 0 */
+ 0x5e0a, /* 01000 10 */
+ 0x5e0a, /* 01000 1 */
+ 0xba0a, /* 01000 11 */
+ 0xba0a, /* 01000 1 */
+ 0xe50a, /* 0100 000 */
+ 0xe50a, /* 0100 00 */
+ 0xab0b, /* 0100 0 */
+ 0x7d0b, /* 0100 1 */
+ 0xd70a, /* 0100 010 */
+ 0xd70a, /* 0100 01 */
+ 0xe40a, /* 0100 011 */
+ 0xe40a, /* 0100 01 */
+ 0x8c0a, /* 0100 100 */
+ 0x8c0a,
+ 0xc80a,
+ 0xc80a,
+ 0x4e0b, /* 0100 1100 */
+ 0x2e0b, /* 0100 1101 */
+ 0x3e0a, /* 0100 111 */
+ 0x3e0a, /* 0100 11 */
+ 0x6d0a, /* 010 0000 */
+ 0x6d0a, /* 010 000 */
+ 0xd60a, /* 010 0 */
+ 0xd60a, /* 010 000 */
+ 0xe30a, /* 010 0 */
+ 0xe30a, /* 010 */
+ 0x9b0a, /* 010 1 */
+ 0x9b0a, /* 010 */
+ 0xb90a, /* 010 0100 */
+ 0xb90a, /* 010 010 */
+ 0xaa0a, /* 010 0101 */
+ 0xaa0a,
+ 0xe20a,
+ 0xe20a,
+ 0x1e0a,
+ 0x1e0a,
+ 0xe10a,
+ 0xe10a,
+ 0x5d0a,
+ 0x5d0a,
+ 0xd50a,
+ 0xd50a,
+ 0x7c0a,
+ 0x7c0a,
+ 0xc70a,
+ 0xc70a,
+ 0x4d0a,
+ 0x4d0a,
+ 0x8b0a,
+ 0x8b0a,
+ 0xb80a,
+ 0xb80a,
+ 0xd40a,
+ 0xd40a,
+ 0x9a0a,
+ 0x9a0a,
+ 0xa90a, /* 01 0 0 */
+ 0xa90a, /* 01 0 */
+ 0x6c0a, /* 01 0 1 */
+ 0x6c0a, /* 01 0 */
+ 0xc60a, /* 01 00 */
+ 0xc60a, /* 01 0 */
+ 0x3d0a, /* 01 01 */
+ 0x3d0a, /* 01 0 */
+ 0xd30a, /* 01 10 */
+ 0xd30a, /* 01 1 */
+ 0x2d0a, /* 01 11 */
+ 0x2d0a, /* 01 1 */
+ 0xd20a,
+ 0xd20a,
+ 0x1d0a, /* 01 01 */
+ 0x1d0a, /* 01 0100 */
+ 0x7b0a, /* 01 01010 */
+ 0x7b0a, /* 01 0101 */
+ 0xb70a, /* 01 01011 */
+ 0xb70a,
+ 0xd10a,
+ 0xd10a, /* 01 0110 */
+ 0x5c0a, /* 01 01101 */
+ 0x5c0a, /* 01 0110 */
+ 0xc50a, /* 01 01110 */
+ 0xc50a, /* 01 0111 */
+ 0x8a0a, /* 01 01111 */
+ 0x8a0a, /* 01 0111 */
+ 0xa80a, /* 01 10000 */
+ 0xa80a, /* 01 1000 */
+ 0x990a, /* 01 10 */
+ 0x990a, /* 01 1000 */
+ 0x4c0a, /* 01 1 0 */
+ 0x4c0a, /* 01 1 */
+ 0xc40a, /* 01 1 1 */
+ 0xc40a, /* 01 1 */
+ 0x6b0a, /* 01 10100 */
+ 0x6b0a, /* 01 1010 */
+ 0xb60a, /* 01 10101 */
+ 0xb60a, /* 01 1010 */
+ 0xd00b, /* 01 101100 */
+ 0x0c0b, /* 01 101101 */
+ 0x3c0a, /* 01 10111 */
+ 0x3c0a, /* 01 1011 */
+ 0xc30a, /* 01 11000 */
+ 0xc30a, /* 01 1100 */
+ 0x7a0a, /* 01 11 */
+ 0x7a0a, /* 01 1100 */
+ 0xa70a, /* 01 11010 */
+ 0xa70a, /* 01 1101 */
+ 0x2c0a, /* 01 11011 */
+ 0x2c0a, /* 01 1101 */
+ 0xc20a, /* 01 11100 */
+ 0xc20a, /* 01 1110 */
+ 0x5b0a, /* 01 11101 */
+ 0x5b0a, /* 01 1110 */
+ 0xb50a, /* 01 11110 */
+ 0xb50a, /* 01 1111 */
+ 0x1c0a,
+ 0x1c0a,
+ 0x890a,
+ 0x890a,
+ 0x980a,
+ 0x980a,
+ 0xc10a, /* 010100 0 */
+ 0xc10a, /* 010100 */
+ 0x4b0a, /* 010100 1 */
+ 0x4b0a, /* 010100 */
+ 0xc00b, /* 01010 000 */
+ 0x0b0b, /* 01010 */
+ 0x3b0a, /* 01010 01 */
+ 0x3b0a, /* 01010 0 */
+ 0xb00b, /* 01010 100 */
+ 0x0a0b, /* 01010 101 */
+ 0x1a0a, /* 01010 11 */
+ 0x1a0a, /* 01010 1 */
+ 0xb409, /* 0101 00 */
+ 0xb409, /* 0101 0 */
+ 0xb409, /* 0101 0 */
+ 0xb409, /* 0101 0 */
+ 0x6a0a, /* 0101 010 */
+ 0x6a0a, /* 0101 01 */
+ 0xa60a, /* 0101 011 */
+ 0xa60a, /* 0101 01 */
+ 0x790a, /* 0101 100 */
+ 0x790a, /* 0101 10 */
+ 0x970a, /* 0101 101 */
+ 0x970a, /* 0101 10 */
+ 0xa00b, /* 0101 1100 */
+ 0x090b, /* 0101 1101 */
+ 0x900a, /* 0101 111 */
+ 0x900a, /* 0101 11 */
+ 0xca0b,
+ 0xca0b,
+ 0xbb0b,
+ 0xbb0b,
+ 0x8d0b,
+ 0x8d0b, /* 0100000 */
+ 0xd80b, /* 0100000 1 */
+ 0xd80b, /* 0100000 */
+ 0x0e0c, /* 010000 000 */
+ 0xe00c, /* 010000 */
+ 0x0d0b, /* 010000 01 */
+ 0x0d0b, /* 010000 0 */
+ 0xe60a, /* 010000 1 */
+ 0xe60a, /* 010000 */
+ 0xe60a, /* 010000 */
+ 0xe60a, /* 010000 */
+ 0x0f09, /* 011000 401 */
+ 0x0f09, /* 01100 */
+ 0x0f09, /* 01100 */
+ 0x0f09, /* 01100 */
+ 0xee0b, /* 011 00 */
+ 0xde0b, /* 011 01 */
+ 0xed0b, /* 011 10 */
+ 0xce0b, /* 011 11 */
+ 0xec0b, /* 01101000 */
+ 0xdd0b, /* 01101 */
+ 0xbe0b, /* 01101010 */
+ 0xeb0b, /* 01101011 */
+ 0xcd0b, /* 01101100 */
+ 0xdc0b, /* 01101101 */
+ 0xae0b, /* 01101110 */
+ 0xea0b, /* 01101111 */
+ 0xbd0b, /* 01110000 */
+ 0xdb0b, /* 01110 */
+ 0xcc0b, /* 0111 0 */
+ 0x9e0b, /* 0111 1 */
+ 0xe90b, /* 01110100 */
+ 0xad0b, /* 01110101 */
+ 0xda0b, /* 01110110 */
+ 0xbc0b, /* 01110111 */
+ 0xcb0b, /* 01111000 */
+ 0x8e0b,
+ 0xe80b,
+ 0x9d0b,
+ 0xd90b,
+ 0x7e0b,
+ 0xe70b,
+ 0xac0b,
+ 0xff04,
+ 0xef08,
+ 0xfe08,
+ 0xdf08, /* 0000 0 */
+ 0xfd08, /* 0000 1 */
+ 0xcf08, /* 000 00 */
+ 0xfc08, /* 000 01 */
+ 0xbf08, /* 000 10 */
+ 0xfb08, /* 000 11 */
+ 0xfa07, /* 00 00 */
+ 0xfa07, /* 00 0 */
+ 0xaf08, /* 00 010 */
+ 0x9f08, /* 00 011 */
+ 0xf907, /* 00 10 */
+ 0xf907, /* 00 1 */
+ 0xf807, /* 00 11 */
+ 0xf807, /* 00 1 */
+ 0x8f08,
+ 0x7f08, /* 0 0 */
+ 0xf707, /* 0 */
+ 0xf707, /* 0 00 */
+ 0x6f07, /* 0 010 */
+ 0x6f07, /* 0 01 */
+ 0xf607, /* 0 011 */
+ 0xf607, /* 0 01 */
+ 0x5f07,
+ 0x5f07, /* 0 10 */
+ 0xf507, /* 0 101 */
+ 0xf507, /* 0 10 */
+ 0x4f07, /* 0 110 */
+ 0x4f07, /* 0 11 */
+ 0xf407, /* 0 111 */
+ 0xf407, /* 0 11 */
+ 0x3f07,
+ 0x3f07,
+ 0xf307, /* 0 */
+ 0xf307,
+ 0x2f07, /* 0 */
+ 0x2f07, /* */
+ 0xf207, /* 1 */
+ 0xf207, /* */
+ 0xf107,
+ 0xf107,
+ 0x1f08,
+ 0xf008
+
+};
+
+
+const uint16 huffTable_32[33] =
+{
+
+ 0x0b06,
+ 0x0f06,
+ 0x0d06,
+ 0x0e06,
+ 0x0706,
+ 0x0506,
+ 0x0905,
+ 0x0905,
+ 0x0605,
+ 0x0605,
+ 0x0305,
+ 0x0305,
+ 0x0a05,
+ 0x0a05,
+ 0x0c05,
+ 0x0c05,
+ 0x0204,
+ 0x0204,
+ 0x0204,
+ 0x0204,
+ 0x0104,
+ 0x0104,
+ 0x0104,
+ 0x0104,
+ 0x0404,
+ 0x0404,
+ 0x0404,
+ 0x0404,
+ 0x0804,
+ 0x0804,
+ 0x0804,
+ 0x0804,
+ 0x0001
+
+};
+
+
+/*
+ * MM = 512; z = [0:(MM)]; a = z.^(1/3);
+ * Table is in Q27
+ */
+const int32 power_one_third[513] =
+{
+
+ 0x00000000, 0x08000000, 0x0A14517D, 0x0B89BA25,
+ 0x0CB2FF53, 0x0DAE07DE, 0x0E897685, 0x0F4DAEDD,
+ 0x10000000, 0x10A402FD, 0x113C4841, 0x11CAB613,
+ 0x1250BFE2, 0x12CF8890, 0x1347F8AB, 0x13BACD65,
+ 0x1428A2FA, 0x1491FC15, 0x14F74744, 0x1558E2F7,
+ 0x15B72095, 0x161246D7, 0x166A9399, 0x16C03D55,
+ 0x17137449, 0x17646369, 0x17B33124, 0x18000000,
+ 0x184AEF29, 0x18941AD8, 0x18DB9CB7, 0x19218C2E,
+ 0x1965FEA5, 0x19A907C2, 0x19EAB998, 0x1A2B24D0,
+ 0x1A6A58D5, 0x1AA863EE, 0x1AE5535D, 0x1B213377,
+ 0x1B5C0FBD, 0x1B95F2EC, 0x1BCEE70F, 0x1C06F590,
+ 0x1C3E2745, 0x1C74847A, 0x1CAA1501, 0x1CDEE035,
+ 0x1D12ED0B, 0x1D464212, 0x1D78E582, 0x1DAADD3A,
+ 0x1DDC2ECF, 0x1E0CDF8C, 0x1E3CF476, 0x1E6C7257,
+ 0x1E9B5DBA, 0x1EC9BAF6, 0x1EF78E2C, 0x1F24DB4E,
+ 0x1F51A620, 0x1F7DF23C, 0x1FA9C314, 0x1FD51BF2,
+ 0x20000000, 0x202A7244, 0x205475A6, 0x207E0CEE,
+ 0x20A73ACA, 0x20D001CC, 0x20F8646D, 0x2120650E,
+ 0x214805FA, 0x216F4963, 0x2196316C, 0x21BCC020,
+ 0x21E2F77A, 0x2208D961, 0x222E67AD, 0x2253A425,
+ 0x22789082, 0x229D2E6E, 0x22C17F82, 0x22E5854F,
+ 0x23094155, 0x232CB509, 0x234FE1D5, 0x2372C918,
+ 0x23956C26, 0x23B7CC47, 0x23D9EABB, 0x23FBC8B9,
+ 0x241D676E, 0x243EC7FF, 0x245FEB86, 0x2480D319,
+ 0x24A17FC3, 0x24C1F28B, 0x24E22C6C, 0x25022E5F,
+ 0x2521F954, 0x25418E33, 0x2560EDE2, 0x2580193E,
+ 0x259F111F, 0x25BDD657, 0x25DC69B4, 0x25FACBFE,
+ 0x2618FDF8, 0x26370060, 0x2654D3EF, 0x2672795C,
+ 0x268FF156, 0x26AD3C8A, 0x26CA5BA2, 0x26E74F41,
+ 0x27041808, 0x2720B695, 0x273D2B81, 0x27597762,
+ 0x27759ACB, 0x2791964B, 0x27AD6A6F, 0x27C917C0,
+ 0x27E49EC5, 0x28000000, 0x281B3BF3, 0x2836531B,
+ 0x285145F3, 0x286C14F5, 0x2886C096, 0x28A1494B,
+ 0x28BBAF85, 0x28D5F3B3, 0x28F01641, 0x290A179B,
+ 0x2923F82A, 0x293DB854, 0x2957587E, 0x2970D90A,
+ 0x298A3A59, 0x29A37CCA, 0x29BCA0BB, 0x29D5A687,
+ 0x29EE8E87, 0x2A075914, 0x2A200684, 0x2A38972C,
+ 0x2A510B5F, 0x2A696370, 0x2A819FAE, 0x2A99C069,
+ 0x2AB1C5ED, 0x2AC9B088, 0x2AE18085, 0x2AF9362C,
+ 0x2B10D1C6, 0x2B28539B, 0x2B3FBBEF, 0x2B570B09,
+ 0x2B6E412B, 0x2B855E97, 0x2B9C6390, 0x2BB35056,
+ 0x2BCA2527, 0x2BE0E242, 0x2BF787E4, 0x2C0E1649,
+ 0x2C248DAD, 0x2C3AEE4A, 0x2C513859, 0x2C676C13,
+ 0x2C7D89AF, 0x2C939164, 0x2CA98368, 0x2CBF5FF1,
+ 0x2CD52731, 0x2CEAD95E, 0x2D0076A9, 0x2D15FF45,
+ 0x2D2B7363, 0x2D40D332, 0x2D561EE4, 0x2D6B56A7,
+ 0x2D807AAA, 0x2D958B19, 0x2DAA8823, 0x2DBF71F4,
+ 0x2DD448B7, 0x2DE90C98, 0x2DFDBDC0, 0x2E125C5C,
+ 0x2E26E892, 0x2E3B628D, 0x2E4FCA75, 0x2E642070,
+ 0x2E7864A8, 0x2E8C9741, 0x2EA0B862, 0x2EB4C831,
+ 0x2EC8C6D3, 0x2EDCB46C, 0x2EF09121, 0x2F045D14,
+ 0x2F18186A, 0x2F2BC345, 0x2F3F5DC7, 0x2F52E812,
+ 0x2F666247, 0x2F79CC88, 0x2F8D26F4, 0x2FA071AC,
+ 0x2FB3ACD0, 0x2FC6D87F, 0x2FD9F4D7, 0x2FED01F8,
+ 0x30000000, 0x3012EF0C, 0x3025CF39, 0x3038A0A6,
+ 0x304B636D, 0x305E17AD, 0x3070BD81, 0x30835504,
+ 0x3095DE51, 0x30A85985, 0x30BAC6B9, 0x30CD2609,
+ 0x30DF778D, 0x30F1BB60, 0x3103F19C, 0x31161A59,
+ 0x312835B0, 0x313A43BA, 0x314C4490, 0x315E3849,
+ 0x31701EFD, 0x3181F8C4, 0x3193C5B4, 0x31A585E6,
+ 0x31B7396F, 0x31C8E066, 0x31DA7AE1, 0x31EC08F6,
+ 0x31FD8ABC, 0x320F0047, 0x322069AC, 0x3231C702,
+ 0x3243185C, 0x32545DCF, 0x32659770, 0x3276C552,
+ 0x3287E78A, 0x3298FE2C, 0x32AA094A, 0x32BB08F9,
+ 0x32CBFD4A, 0x32DCE652, 0x32EDC423, 0x32FE96D0,
+ 0x330F5E6A, 0x33201B04, 0x3330CCB0, 0x33417380,
+ 0x33520F85, 0x3362A0D0, 0x33732774, 0x3383A380,
+ 0x33941506, 0x33A47C17, 0x33B4D8C4, 0x33C52B1B,
+ 0x33D5732F, 0x33E5B10F, 0x33F5E4CA, 0x34060E71,
+ 0x34162E14, 0x342643C1, 0x34364F88, 0x34465178,
+ 0x345649A1, 0x34663810, 0x34761CD6, 0x3485F800,
+ 0x3495C99D, 0x34A591BB, 0x34B55069, 0x34C505B4,
+ 0x34D4B1AB, 0x34E4545B, 0x34F3EDD2, 0x35037E1D,
+ 0x3513054B, 0x35228367, 0x3531F881, 0x354164A3,
+ 0x3550C7DC, 0x35602239, 0x356F73C5, 0x357EBC8E,
+ 0x358DFCA0, 0x359D3408, 0x35AC62D1, 0x35BB8908,
+ 0x35CAA6B9, 0x35D9BBF0, 0x35E8C8B9, 0x35F7CD20,
+ 0x3606C92F, 0x3615BCF3, 0x3624A878, 0x36338BC8,
+ 0x364266EE, 0x365139F6, 0x366004EC, 0x366EC7D9,
+ 0x367D82C9, 0x368C35C6, 0x369AE0DC, 0x36A98414,
+ 0x36B81F7A, 0x36C6B317, 0x36D53EF7, 0x36E3C323,
+ 0x36F23FA5, 0x3700B488, 0x370F21D5, 0x371D8797,
+ 0x372BE5D7, 0x373A3CA0, 0x37488BF9, 0x3756D3EF,
+ 0x37651489, 0x37734DD1, 0x37817FD1, 0x378FAA92,
+ 0x379DCE1D, 0x37ABEA7C, 0x37B9FFB7, 0x37C80DD7,
+ 0x37D614E6, 0x37E414EC, 0x37F20DF1, 0x38000000,
+ 0x380DEB20, 0x381BCF5A, 0x3829ACB6, 0x3837833D,
+ 0x384552F8, 0x38531BEE, 0x3860DE28, 0x386E99AF,
+ 0x387C4E89, 0x3889FCC0, 0x3897A45B, 0x38A54563,
+ 0x38B2DFDF, 0x38C073D7, 0x38CE0152, 0x38DB885A,
+ 0x38E908F4, 0x38F68329, 0x3903F701, 0x39116483,
+ 0x391ECBB6, 0x392C2CA1, 0x3939874D, 0x3946DBC0,
+ 0x39542A01, 0x39617218, 0x396EB40C, 0x397BEFE4,
+ 0x398925A7, 0x3996555C, 0x39A37F09, 0x39B0A2B7,
+ 0x39BDC06A, 0x39CAD82B, 0x39D7EA01, 0x39E4F5F0,
+ 0x39F1FC01, 0x39FEFC3A, 0x3A0BF6A2, 0x3A18EB3E,
+ 0x3A25DA16, 0x3A32C32F, 0x3A3FA691, 0x3A4C8441,
+ 0x3A595C46, 0x3A662EA6, 0x3A72FB67, 0x3A7FC28F,
+ 0x3A8C8425, 0x3A99402E, 0x3AA5F6B1, 0x3AB2A7B3,
+ 0x3ABF533A, 0x3ACBF94D, 0x3AD899F1, 0x3AE5352C,
+ 0x3AF1CB03, 0x3AFE5B7D, 0x3B0AE6A0, 0x3B176C70,
+ 0x3B23ECF3, 0x3B306830, 0x3B3CDE2C, 0x3B494EEB,
+ 0x3B55BA74, 0x3B6220CC, 0x3B6E81F9, 0x3B7ADE00,
+ 0x3B8734E5, 0x3B9386B0, 0x3B9FD364, 0x3BAC1B07,
+ 0x3BB85D9E, 0x3BC49B2F, 0x3BD0D3BE, 0x3BDD0751,
+ 0x3BE935ED, 0x3BF55F97, 0x3C018453, 0x3C0DA427,
+ 0x3C19BF17, 0x3C25D52A, 0x3C31E662, 0x3C3DF2C6,
+ 0x3C49FA5B, 0x3C55FD24, 0x3C61FB27, 0x3C6DF468,
+ 0x3C79E8ED, 0x3C85D8B9, 0x3C91C3D2, 0x3C9DAA3C,
+ 0x3CA98BFC, 0x3CB56915, 0x3CC1418E, 0x3CCD156A,
+ 0x3CD8E4AE, 0x3CE4AF5E, 0x3CF0757F, 0x3CFC3714,
+ 0x3D07F423, 0x3D13ACB0, 0x3D1F60BF, 0x3D2B1055,
+ 0x3D36BB75, 0x3D426224, 0x3D4E0466, 0x3D59A23F,
+ 0x3D653BB4, 0x3D70D0C8, 0x3D7C6180, 0x3D87EDE0,
+ 0x3D9375EC, 0x3D9EF9A8, 0x3DAA7918, 0x3DB5F43F,
+ 0x3DC16B23, 0x3DCCDDC7, 0x3DD84C2E, 0x3DE3B65D,
+ 0x3DEF1C58, 0x3DFA7E22, 0x3E05DBC0, 0x3E113535,
+ 0x3E1C8A85, 0x3E27DBB3, 0x3E3328C4, 0x3E3E71BB,
+ 0x3E49B69C, 0x3E54F76B, 0x3E60342B, 0x3E6B6CE0,
+ 0x3E76A18D, 0x3E81D237, 0x3E8CFEE0, 0x3E98278D,
+ 0x3EA34C40, 0x3EAE6CFE, 0x3EB989CA, 0x3EC4A2A8,
+ 0x3ECFB79A, 0x3EDAC8A5, 0x3EE5D5CB, 0x3EF0DF10,
+ 0x3EFBE478, 0x3F06E606, 0x3F11E3BE, 0x3F1CDDA2,
+ 0x3F27D3B6, 0x3F32C5FD, 0x3F3DB47B, 0x3F489F32,
+ 0x3F538627, 0x3F5E695C, 0x3F6948D5, 0x3F742494,
+ 0x3F7EFC9D, 0x3F89D0F3, 0x3F94A19A, 0x3F9F6E94,
+ 0x3FAA37E4, 0x3FB4FD8E, 0x3FBFBF94, 0x3FCA7DFB,
+ 0x3FD538C4, 0x3FDFEFF3, 0x3FEAA38A, 0x3FF5538E,
+ 0x40000000
+};
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_tables.h b/media/libstagefright/codecs/mp3dec/src/pvmp3_tables.h
new file mode 100644
index 0000000..b54c5bf
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_tables.h
@@ -0,0 +1,124 @@
+/* ------------------------------------------------------------------
+ * 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: pvmp3_tables.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+------------------------------------------------------------------------------
+*/
+
+#ifndef PVMP3_TABLES_H
+#define PVMP3_TABLES_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+
+#include "pvmp3_dec_defs.h"
+#include "pv_mp3_huffman.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES AND SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+#define Qfmt_28(a) (int32(double(0x10000000)*a))
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+typedef struct
+{
+ int16 l[23];
+ int16 s[14];
+} mp3_scaleFactorBandIndex;
+
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ extern const int32 mp3_s_freq[4][4];
+ extern const int32 inv_sfreq[4];
+ extern const int16 mp3_bitrate[3][15];
+ extern const int32 power_one_third[513];
+
+ extern const mp3_scaleFactorBandIndex mp3_sfBandIndex[9];
+ extern const int32 mp3_shortwindBandWidths[9][13];
+ extern const int32 pqmfSynthWin[(HAN_SIZE/2) + 8];
+
+
+ extern const uint16 huffTable_1[];
+ extern const uint16 huffTable_2[];
+ extern const uint16 huffTable_3[];
+ extern const uint16 huffTable_5[];
+ extern const uint16 huffTable_6[];
+ extern const uint16 huffTable_7[];
+ extern const uint16 huffTable_8[];
+ extern const uint16 huffTable_9[];
+ extern const uint16 huffTable_10[];
+ extern const uint16 huffTable_11[];
+ extern const uint16 huffTable_12[];
+ extern const uint16 huffTable_13[];
+ extern const uint16 huffTable_15[];
+ extern const uint16 huffTable_16[];
+ extern const uint16 huffTable_24[];
+ extern const uint16 huffTable_32[];
+ extern const uint16 huffTable_33[];
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+#endif
diff --git a/media/libstagefright/codecs/mp3dec/src/s_huffcodetab.h b/media/libstagefright/codecs/mp3dec/src/s_huffcodetab.h
new file mode 100644
index 0000000..874943d
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/s_huffcodetab.h
@@ -0,0 +1,98 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: s_huffcodetab.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+
+------------------------------------------------------------------------------
+ REFERENCES
+
+ [1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
+ ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
+
+----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_HUFFCODETAB_H
+#define S_HUFFCODETAB_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+#define HUFF_TBL 34
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+struct huffcodetab
+{
+ uint32 linbits; /*number of linbits */
+ uint16(*pdec_huff_tab)(tmp3Bits *);
+};
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/s_mp3bits.h b/media/libstagefright/codecs/mp3dec/src/s_mp3bits.h
new file mode 100644
index 0000000..b905b9a
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/s_mp3bits.h
@@ -0,0 +1,107 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: s_mp3bits.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, BITS
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_MP3BITS_H
+#define S_MP3BITS_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_audio_type_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+/*
+ * Name: BITS
+ * Description: Holds information for processing the input data buffer
+ * as a "stream". The data is in packed format.
+ * Fields:
+ * pBuffer - pointer to the beginning of the buffer. If the data type of
+ * this changes, make sure to update the constants in ibstream.h
+ * usedBits - number of bits read thus far from the buffer. Bit 0 is
+ * the LSB of pBuffer[0].
+ */
+
+
+typedef struct
+{
+ uint8 *pBuffer;
+ uint32 usedBits;
+ uint32 inputBufferCurrentLength;
+ uint32 offset;
+} tmp3Bits;
+
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+#endif
+
diff --git a/media/libstagefright/codecs/mp3dec/src/s_tmp3dec_chan.h b/media/libstagefright/codecs/mp3dec/src/s_tmp3dec_chan.h
new file mode 100644
index 0000000..6eb8835
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/s_tmp3dec_chan.h
@@ -0,0 +1,110 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: s_tmp3dec_chan.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, tmp3dec_chan.
+ This structure contains information per channel that needs to persist
+ between calls
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_TMP3DEC_CHAN_H
+#define S_TMP3DEC_CHAN_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "pvmp3_audio_type_defs.h"
+#include "pvmp3_dec_defs.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ typedef struct
+ {
+ int32 used_freq_lines;
+ int32 overlap[SUBBANDS_NUMBER*FILTERBANK_BANDS];
+ int32 work_buf_int32[SUBBANDS_NUMBER*FILTERBANK_BANDS]; /* working buffer */
+ int32 circ_buffer[480 + 576];
+
+ } tmp3dec_chan;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+#endif
+
+
diff --git a/media/libstagefright/codecs/mp3dec/src/s_tmp3dec_file.h b/media/libstagefright/codecs/mp3dec/src/s_tmp3dec_file.h
new file mode 100644
index 0000000..611e08f
--- /dev/null
+++ b/media/libstagefright/codecs/mp3dec/src/s_tmp3dec_file.h
@@ -0,0 +1,118 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+------------------------------------------------------------------------------
+ PacketVideo Corp.
+ MP3 Decoder Library
+
+ Filename: s_tmp3dec_file.h
+
+ Date: 09/21/2007
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+
+ Description:
+
+------------------------------------------------------------------------------
+ INCLUDE DESCRIPTION
+
+ This include file defines the structure, tmp3dec_file.
+ This structure contains information that needs to persist between calls
+
+------------------------------------------------------------------------------
+*/
+
+/*----------------------------------------------------------------------------
+; CONTINUE ONLY IF NOT ALREADY DEFINED
+----------------------------------------------------------------------------*/
+#ifndef S_TMP3DEC_FILE_H
+#define S_TMP3DEC_FILE_H
+
+/*----------------------------------------------------------------------------
+; INCLUDES
+----------------------------------------------------------------------------*/
+#include "s_tmp3dec_chan.h"
+#include "s_mp3bits.h"
+#include "s_huffcodetab.h"
+
+/*----------------------------------------------------------------------------
+; MACROS
+; Define module specific macros here
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; DEFINES
+; Include all pre-processor statements here.
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; EXTERNAL VARIABLES REFERENCES
+; Declare variables used in this module but defined elsewhere
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; SIMPLE TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; ENUMERATED TYPEDEF'S
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; STRUCTURES TYPEDEF'S
+----------------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ typedef struct
+ {
+ int32 num_channels;
+ int32 predicted_frame_size;
+ int32 frame_start;
+ int32 Scratch_mem[198];
+ tmp3dec_chan perChan[CHAN];
+ mp3ScaleFactors scaleFactors[CHAN];
+ mp3SideInfo sideInfo;
+ tmp3Bits mainDataStream;
+ uint8 mainDataBuffer[BUFSIZE];
+ tmp3Bits inputStream;
+ huffcodetab ht[HUFF_TBL];
+ } tmp3dec_file;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+; GLOBAL FUNCTION DEFINITIONS
+; Function Prototype declaration
+----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+; END
+----------------------------------------------------------------------------*/
+
+#endif
+
+
+
+
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..2997228
--- /dev/null
+++ b/media/libstagefright/codecs/on2/dec/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ SoftVPX.cpp
+
+LOCAL_C_INCLUDES := \
+ $(TOP)/external/libvpx \
+ $(TOP)/external/libvpx/vpx_codec \
+ $(TOP)/external/libvpx/vpx_ports \
+ frameworks/base/media/libstagefright/include \
+ frameworks/native/include/media/openmax \
+
+LOCAL_STATIC_LIBRARIES := \
+ libvpx
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright libstagefright_omx libstagefright_foundation libutils
+
+LOCAL_MODULE := libstagefright_soft_vpxdec
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.cpp b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
new file mode 100644
index 0000000..bf9ab3a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.cpp
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SoftVPX"
+#include <utils/Log.h>
+
+#include "SoftVPX.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+
+#include "vpx/vpx_decoder.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vp8dx.h"
+
+namespace android {
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+SoftVPX::SoftVPX(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SimpleSoftOMXComponent(name, callbacks, appData, component),
+ mCtx(NULL),
+ mWidth(320),
+ mHeight(240),
+ mOutputPortSettingsChange(NONE) {
+ initPorts();
+ CHECK_EQ(initDecoder(), (status_t)OK);
+}
+
+SoftVPX::~SoftVPX() {
+ vpx_codec_destroy((vpx_codec_ctx_t *)mCtx);
+ delete (vpx_codec_ctx_t *)mCtx;
+ mCtx = NULL;
+}
+
+void SoftVPX::initPorts() {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+
+ def.nPortIndex = 0;
+ def.eDir = OMX_DirInput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 256 * 1024;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainVideo;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 1;
+
+ def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VPX);
+ def.format.video.pNativeRender = NULL;
+ def.format.video.nFrameWidth = mWidth;
+ def.format.video.nFrameHeight = mHeight;
+ def.format.video.nStride = def.format.video.nFrameWidth;
+ def.format.video.nSliceHeight = def.format.video.nFrameHeight;
+ def.format.video.nBitrate = 0;
+ def.format.video.xFramerate = 0;
+ def.format.video.bFlagErrorConcealment = OMX_FALSE;
+ def.format.video.eCompressionFormat = OMX_VIDEO_CodingVPX;
+ def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
+ def.format.video.pNativeWindow = NULL;
+
+ addPort(def);
+
+ def.nPortIndex = 1;
+ def.eDir = OMX_DirOutput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainVideo;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 2;
+
+ def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
+ def.format.video.pNativeRender = NULL;
+ def.format.video.nFrameWidth = mWidth;
+ def.format.video.nFrameHeight = mHeight;
+ def.format.video.nStride = def.format.video.nFrameWidth;
+ def.format.video.nSliceHeight = def.format.video.nFrameHeight;
+ def.format.video.nBitrate = 0;
+ def.format.video.xFramerate = 0;
+ def.format.video.bFlagErrorConcealment = OMX_FALSE;
+ def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+ def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
+ def.format.video.pNativeWindow = NULL;
+
+ def.nBufferSize =
+ (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2;
+
+ addPort(def);
+}
+
+static int GetCPUCoreCount() {
+ int cpuCoreCount = 1;
+#if defined(_SC_NPROCESSORS_ONLN)
+ cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
+#else
+ // _SC_NPROC_ONLN must be defined...
+ cpuCoreCount = sysconf(_SC_NPROC_ONLN);
+#endif
+ CHECK(cpuCoreCount >= 1);
+ ALOGV("Number of CPU cores: %d", cpuCoreCount);
+ return cpuCoreCount;
+}
+
+status_t SoftVPX::initDecoder() {
+ mCtx = new vpx_codec_ctx_t;
+ vpx_codec_err_t vpx_err;
+ vpx_codec_dec_cfg_t cfg;
+ memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t));
+ cfg.threads = GetCPUCoreCount();
+ if ((vpx_err = vpx_codec_dec_init(
+ (vpx_codec_ctx_t *)mCtx, &vpx_codec_vp8_dx_algo, &cfg, 0))) {
+ ALOGE("on2 decoder failed to initialize. (%d)", vpx_err);
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+OMX_ERRORTYPE SoftVPX::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
+
+ if (formatParams->nPortIndex > 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (formatParams->nIndex != 0) {
+ return OMX_ErrorNoMore;
+ }
+
+ if (formatParams->nPortIndex == 0) {
+ formatParams->eCompressionFormat = OMX_VIDEO_CodingVPX;
+ formatParams->eColorFormat = OMX_COLOR_FormatUnused;
+ formatParams->xFramerate = 0;
+ } else {
+ CHECK_EQ(formatParams->nPortIndex, 1u);
+
+ formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
+ formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
+ formatParams->xFramerate = 0;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftVPX::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamStandardComponentRole:
+ {
+ const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+ (const OMX_PARAM_COMPONENTROLETYPE *)params;
+
+ if (strncmp((const char *)roleParams->cRole,
+ "video_decoder.vpx",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
+
+ if (formatParams->nPortIndex > 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (formatParams->nIndex != 0) {
+ return OMX_ErrorNoMore;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ }
+}
+
+void SoftVPX::onQueueFilled(OMX_U32 portIndex) {
+ if (mOutputPortSettingsChange != NONE) {
+ return;
+ }
+
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+
+ while (!inQueue.empty() && !outQueue.empty()) {
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+
+ outHeader->nFilledLen = 0;
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+
+ outQueue.erase(outQueue.begin());
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+ return;
+ }
+
+ if (vpx_codec_decode(
+ (vpx_codec_ctx_t *)mCtx,
+ inHeader->pBuffer + inHeader->nOffset,
+ inHeader->nFilledLen,
+ NULL,
+ 0)) {
+ ALOGE("on2 decoder failed to decode frame.");
+
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ return;
+ }
+
+ vpx_codec_iter_t iter = NULL;
+ vpx_image_t *img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);
+
+ if (img != NULL) {
+ CHECK_EQ(img->fmt, IMG_FMT_I420);
+
+ int32_t width = img->d_w;
+ int32_t height = img->d_h;
+
+ if (width != mWidth || height != mHeight) {
+ mWidth = width;
+ mHeight = height;
+
+ updatePortDefinitions();
+
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+ return;
+ }
+
+ outHeader->nOffset = 0;
+ outHeader->nFilledLen = (width * height * 3) / 2;
+ outHeader->nFlags = 0;
+ outHeader->nTimeStamp = inHeader->nTimeStamp;
+
+ const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y];
+ uint8_t *dst = outHeader->pBuffer;
+ 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;
+ }
+
+ outInfo->mOwnedByUs = false;
+ outQueue.erase(outQueue.begin());
+ outInfo = NULL;
+ notifyFillBufferDone(outHeader);
+ outHeader = NULL;
+ }
+
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+ }
+}
+
+void SoftVPX::onPortFlushCompleted(OMX_U32 portIndex) {
+}
+
+void SoftVPX::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
+ if (portIndex != 1) {
+ return;
+ }
+
+ switch (mOutputPortSettingsChange) {
+ case NONE:
+ break;
+
+ case AWAITING_DISABLED:
+ {
+ CHECK(!enabled);
+ mOutputPortSettingsChange = AWAITING_ENABLED;
+ break;
+ }
+
+ default:
+ {
+ CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
+ CHECK(enabled);
+ mOutputPortSettingsChange = NONE;
+ break;
+ }
+ }
+}
+
+void SoftVPX::updatePortDefinitions() {
+ OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef;
+ def->format.video.nFrameWidth = mWidth;
+ def->format.video.nFrameHeight = mHeight;
+ def->format.video.nStride = def->format.video.nFrameWidth;
+ def->format.video.nSliceHeight = def->format.video.nFrameHeight;
+
+ def = &editPortInfo(1)->mDef;
+ def->format.video.nFrameWidth = mWidth;
+ def->format.video.nFrameHeight = mHeight;
+ def->format.video.nStride = def->format.video.nFrameWidth;
+ def->format.video.nSliceHeight = def->format.video.nFrameHeight;
+
+ def->nBufferSize =
+ (def->format.video.nFrameWidth
+ * def->format.video.nFrameHeight * 3) / 2;
+}
+
+} // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+ const char *name, const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+ return new android::SoftVPX(name, callbacks, appData, component);
+}
+
diff --git a/media/libstagefright/codecs/on2/dec/SoftVPX.h b/media/libstagefright/codecs/on2/dec/SoftVPX.h
new file mode 100644
index 0000000..3e814a2
--- /dev/null
+++ b/media/libstagefright/codecs/on2/dec/SoftVPX.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SOFT_VPX_H_
+
+#define SOFT_VPX_H_
+
+#include "SimpleSoftOMXComponent.h"
+
+namespace android {
+
+struct SoftVPX : public SimpleSoftOMXComponent {
+ SoftVPX(const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ virtual ~SoftVPX();
+
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual void onQueueFilled(OMX_U32 portIndex);
+ virtual void onPortFlushCompleted(OMX_U32 portIndex);
+ virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled);
+
+private:
+ enum {
+ kNumBuffers = 4
+ };
+
+ void *mCtx;
+
+ int32_t mWidth;
+ int32_t mHeight;
+
+ enum {
+ NONE,
+ AWAITING_DISABLED,
+ AWAITING_ENABLED
+ } mOutputPortSettingsChange;
+
+ void initPorts();
+ status_t initDecoder();
+
+ void updatePortDefinitions();
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftVPX);
+};
+
+} // namespace android
+
+#endif // SOFT_VPX_H_
diff --git a/media/libstagefright/codecs/on2/h264dec/Android.mk b/media/libstagefright/codecs/on2/h264dec/Android.mk
new file mode 100644
index 0000000..43c20f0
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/Android.mk
@@ -0,0 +1,127 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_SRC_FILES := \
+ ./source/h264bsd_transform.c \
+ ./source/h264bsd_util.c \
+ ./source/h264bsd_byte_stream.c \
+ ./source/h264bsd_seq_param_set.c \
+ ./source/h264bsd_pic_param_set.c \
+ ./source/h264bsd_slice_header.c \
+ ./source/h264bsd_slice_data.c \
+ ./source/h264bsd_macroblock_layer.c \
+ ./source/h264bsd_stream.c \
+ ./source/h264bsd_vlc.c \
+ ./source/h264bsd_cavlc.c \
+ ./source/h264bsd_nal_unit.c \
+ ./source/h264bsd_neighbour.c \
+ ./source/h264bsd_storage.c \
+ ./source/h264bsd_slice_group_map.c \
+ ./source/h264bsd_intra_prediction.c \
+ ./source/h264bsd_inter_prediction.c \
+ ./source/h264bsd_reconstruct.c \
+ ./source/h264bsd_dpb.c \
+ ./source/h264bsd_image.c \
+ ./source/h264bsd_deblocking.c \
+ ./source/h264bsd_conceal.c \
+ ./source/h264bsd_vui.c \
+ ./source/h264bsd_pic_order_cnt.c \
+ ./source/h264bsd_decoder.c \
+ ./source/H264SwDecApi.c \
+ SoftAVC.cpp \
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/./inc \
+ frameworks/base/media/libstagefright/include \
+ frameworks/native/include/media/openmax \
+
+MY_ASM := \
+ ./source/arm_neon_asm_gcc/h264bsdWriteMacroblock.S \
+ ./source/arm_neon_asm_gcc/h264bsdClearMbLayer.S \
+ ./source/arm_neon_asm_gcc/h264bsdFillRow7.S \
+ ./source/arm_neon_asm_gcc/h264bsdCountLeadingZeros.S \
+ ./source/arm_neon_asm_gcc/h264bsdFlushBits.S
+
+
+MY_OMXDL_C_SRC := \
+ ./omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c \
+ ./omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c \
+ ./omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c \
+ ./omxdl/arm_neon/vc/m4p10/src/armVCM4P10_CAVLCTables.c \
+ ./omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c \
+ ./omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c \
+ ./omxdl/arm_neon/src/armCOMM_Bitstream.c \
+ ./omxdl/arm_neon/src/armCOMM.c
+
+MY_OMXDL_ASM_SRC := \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingChroma_unsafe_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingLuma_unsafe_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Interpolate_Chroma_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Align_unsafe_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Copy_unsafe_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_InterpolateLuma_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Average_4x_Align_unsafe_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_QuantTables_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_TransformResidual4x4_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_UnpackBlock4x4_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantLumaDCFromPair_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_16x16_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_4x4_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntraChroma_8x8_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S \
+ ./omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S \
+
+
+ifeq ($(ARCH_ARM_HAVE_NEON),true)
+ LOCAL_ARM_NEON := true
+# LOCAL_CFLAGS := -std=c99 -D._NEON -D._OMXDL
+ LOCAL_CFLAGS := -DH264DEC_NEON -DH264DEC_OMXDL
+ LOCAL_SRC_FILES += $(MY_ASM) $(MY_OMXDL_C_SRC) $(MY_OMXDL_ASM_SRC)
+ LOCAL_C_INCLUDES += $(LOCAL_PATH)/./source/arm_neon_asm_gcc
+ LOCAL_C_INCLUDES += $(LOCAL_PATH)/./omxdl/arm_neon/api \
+ $(LOCAL_PATH)/./omxdl/arm_neon/vc/api \
+ $(LOCAL_PATH)/./omxdl/arm_neon/vc/m4p10/api
+endif
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright libstagefright_omx libstagefright_foundation libutils \
+
+LOCAL_MODULE := libstagefright_soft_h264dec
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
+#####################################################################
+# test utility: decoder
+#####################################################################
+##
+## Test application
+##
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := ./source/DecTestBench.c
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/inc
+
+LOCAL_SHARED_LIBRARIES := libstagefright_soft_h264dec
+
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_MODULE := decoder
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
new file mode 100644
index 0000000..6c3f834
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
@@ -0,0 +1,561 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SoftAVC"
+#include <utils/Log.h>
+
+#include "SoftAVC.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/IOMX.h>
+
+
+namespace android {
+
+static const CodecProfileLevel kProfileLevels[] = {
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel32 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel4 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel42 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel5 },
+ { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel51 },
+};
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+SoftAVC::SoftAVC(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SimpleSoftOMXComponent(name, callbacks, appData, component),
+ mHandle(NULL),
+ mInputBufferCount(0),
+ mWidth(320),
+ mHeight(240),
+ mPictureSize(mWidth * mHeight * 3 / 2),
+ mCropLeft(0),
+ mCropTop(0),
+ mCropWidth(mWidth),
+ mCropHeight(mHeight),
+ mFirstPicture(NULL),
+ mFirstPictureId(-1),
+ mPicId(0),
+ mHeadersDecoded(false),
+ mEOSStatus(INPUT_DATA_AVAILABLE),
+ mOutputPortSettingsChange(NONE),
+ mSignalledError(false) {
+ initPorts();
+ CHECK_EQ(initDecoder(), (status_t)OK);
+}
+
+SoftAVC::~SoftAVC() {
+ H264SwDecRelease(mHandle);
+ mHandle = NULL;
+
+ while (mPicToHeaderMap.size() != 0) {
+ OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.editValueAt(0);
+ mPicToHeaderMap.removeItemsAt(0);
+ delete header;
+ header = NULL;
+ }
+ List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
+ List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
+ CHECK(outQueue.empty());
+ CHECK(inQueue.empty());
+
+ delete[] mFirstPicture;
+}
+
+void SoftAVC::initPorts() {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+
+ def.nPortIndex = kInputPortIndex;
+ def.eDir = OMX_DirInput;
+ def.nBufferCountMin = kNumInputBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 8192;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainVideo;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 1;
+
+ def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_AVC);
+ def.format.video.pNativeRender = NULL;
+ def.format.video.nFrameWidth = mWidth;
+ def.format.video.nFrameHeight = mHeight;
+ def.format.video.nStride = def.format.video.nFrameWidth;
+ def.format.video.nSliceHeight = def.format.video.nFrameHeight;
+ def.format.video.nBitrate = 0;
+ def.format.video.xFramerate = 0;
+ def.format.video.bFlagErrorConcealment = OMX_FALSE;
+ def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
+ def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
+ def.format.video.pNativeWindow = NULL;
+
+ addPort(def);
+
+ def.nPortIndex = kOutputPortIndex;
+ def.eDir = OMX_DirOutput;
+ def.nBufferCountMin = kNumOutputBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainVideo;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 2;
+
+ def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
+ def.format.video.pNativeRender = NULL;
+ def.format.video.nFrameWidth = mWidth;
+ def.format.video.nFrameHeight = mHeight;
+ def.format.video.nStride = def.format.video.nFrameWidth;
+ def.format.video.nSliceHeight = def.format.video.nFrameHeight;
+ def.format.video.nBitrate = 0;
+ def.format.video.xFramerate = 0;
+ def.format.video.bFlagErrorConcealment = OMX_FALSE;
+ def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
+ def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
+ def.format.video.pNativeWindow = NULL;
+
+ def.nBufferSize =
+ (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2;
+
+ addPort(def);
+}
+
+status_t SoftAVC::initDecoder() {
+ // Force decoder to output buffers in display order.
+ if (H264SwDecInit(&mHandle, 0) == H264SWDEC_OK) {
+ return OK;
+ }
+ return UNKNOWN_ERROR;
+}
+
+OMX_ERRORTYPE SoftAVC::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
+
+ if (formatParams->nPortIndex > kOutputPortIndex) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (formatParams->nIndex != 0) {
+ return OMX_ErrorNoMore;
+ }
+
+ if (formatParams->nPortIndex == kInputPortIndex) {
+ formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC;
+ formatParams->eColorFormat = OMX_COLOR_FormatUnused;
+ formatParams->xFramerate = 0;
+ } else {
+ CHECK(formatParams->nPortIndex == kOutputPortIndex);
+
+ formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
+ formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
+ formatParams->xFramerate = 0;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamVideoProfileLevelQuerySupported:
+ {
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
+ (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params;
+
+ if (profileLevel->nPortIndex != kInputPortIndex) {
+ ALOGE("Invalid port index: %ld", profileLevel->nPortIndex);
+ return OMX_ErrorUnsupportedIndex;
+ }
+
+ size_t index = profileLevel->nProfileIndex;
+ size_t nProfileLevels =
+ sizeof(kProfileLevels) / sizeof(kProfileLevels[0]);
+ if (index >= nProfileLevels) {
+ return OMX_ErrorNoMore;
+ }
+
+ profileLevel->eProfile = kProfileLevels[index].mProfile;
+ profileLevel->eLevel = kProfileLevels[index].mLevel;
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftAVC::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamStandardComponentRole:
+ {
+ const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+ (const OMX_PARAM_COMPONENTROLETYPE *)params;
+
+ if (strncmp((const char *)roleParams->cRole,
+ "video_decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamVideoPortFormat:
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
+ (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
+
+ if (formatParams->nPortIndex > kOutputPortIndex) {
+ return OMX_ErrorUndefined;
+ }
+
+ if (formatParams->nIndex != 0) {
+ return OMX_ErrorNoMore;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftAVC::getConfig(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexConfigCommonOutputCrop:
+ {
+ OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)params;
+
+ if (rectParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ rectParams->nLeft = mCropLeft;
+ rectParams->nTop = mCropTop;
+ rectParams->nWidth = mCropWidth;
+ rectParams->nHeight = mCropHeight;
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return OMX_ErrorUnsupportedIndex;
+ }
+}
+
+void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
+ if (mSignalledError || mOutputPortSettingsChange != NONE) {
+ return;
+ }
+
+ if (mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
+ return;
+ }
+
+ List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
+ List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
+ H264SwDecRet ret = H264SWDEC_PIC_RDY;
+ bool portSettingsChanged = false;
+ while ((mEOSStatus != INPUT_DATA_AVAILABLE || !inQueue.empty())
+ && outQueue.size() == kNumOutputBuffers) {
+
+ if (mEOSStatus == INPUT_EOS_SEEN) {
+ drainAllOutputBuffers();
+ return;
+ }
+
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+ ++mPicId;
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+ mEOSStatus = INPUT_EOS_SEEN;
+ continue;
+ }
+
+ OMX_BUFFERHEADERTYPE *header = new OMX_BUFFERHEADERTYPE;
+ memset(header, 0, sizeof(OMX_BUFFERHEADERTYPE));
+ header->nTimeStamp = inHeader->nTimeStamp;
+ header->nFlags = inHeader->nFlags;
+ mPicToHeaderMap.add(mPicId, header);
+ inQueue.erase(inQueue.begin());
+
+ H264SwDecInput inPicture;
+ H264SwDecOutput outPicture;
+ memset(&inPicture, 0, sizeof(inPicture));
+ inPicture.dataLen = inHeader->nFilledLen;
+ inPicture.pStream = inHeader->pBuffer + inHeader->nOffset;
+ inPicture.picId = mPicId;
+ inPicture.intraConcealmentMethod = 1;
+ H264SwDecPicture decodedPicture;
+
+ while (inPicture.dataLen > 0) {
+ ret = H264SwDecDecode(mHandle, &inPicture, &outPicture);
+ if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY ||
+ ret == H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY) {
+ inPicture.dataLen -= (u32)(outPicture.pStrmCurrPos - inPicture.pStream);
+ inPicture.pStream = outPicture.pStrmCurrPos;
+ if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY) {
+ mHeadersDecoded = true;
+ H264SwDecInfo decoderInfo;
+ CHECK(H264SwDecGetInfo(mHandle, &decoderInfo) == H264SWDEC_OK);
+
+ if (handlePortSettingChangeEvent(&decoderInfo)) {
+ portSettingsChanged = true;
+ }
+
+ if (decoderInfo.croppingFlag &&
+ handleCropRectEvent(&decoderInfo.cropParams)) {
+ portSettingsChanged = true;
+ }
+ }
+ } else {
+ if (portSettingsChanged) {
+ if (H264SwDecNextPicture(mHandle, &decodedPicture, 0)
+ == H264SWDEC_PIC_RDY) {
+
+ // Save this output buffer; otherwise, it will be
+ // lost during dynamic port reconfiguration because
+ // OpenMAX client will delete _all_ output buffers
+ // in the process.
+ saveFirstOutputBuffer(
+ decodedPicture.picId,
+ (uint8_t *)decodedPicture.pOutputPicture);
+ }
+ }
+ inPicture.dataLen = 0;
+ if (ret < 0) {
+ ALOGE("Decoder failed: %d", ret);
+
+ notify(OMX_EventError, OMX_ErrorUndefined,
+ ERROR_MALFORMED, NULL);
+
+ mSignalledError = true;
+ return;
+ }
+ }
+ }
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+
+ if (portSettingsChanged) {
+ portSettingsChanged = false;
+ return;
+ }
+
+ if (mFirstPicture && !outQueue.empty()) {
+ drainOneOutputBuffer(mFirstPictureId, mFirstPicture);
+ delete[] mFirstPicture;
+ mFirstPicture = NULL;
+ mFirstPictureId = -1;
+ }
+
+ while (!outQueue.empty() &&
+ mHeadersDecoded &&
+ H264SwDecNextPicture(mHandle, &decodedPicture, 0)
+ == H264SWDEC_PIC_RDY) {
+
+ int32_t picId = decodedPicture.picId;
+ uint8_t *data = (uint8_t *) decodedPicture.pOutputPicture;
+ drainOneOutputBuffer(picId, data);
+ }
+ }
+}
+
+bool SoftAVC::handlePortSettingChangeEvent(const H264SwDecInfo *info) {
+ if (mWidth != info->picWidth || mHeight != info->picHeight) {
+ mWidth = info->picWidth;
+ mHeight = info->picHeight;
+ mPictureSize = mWidth * mHeight * 3 / 2;
+ mCropWidth = mWidth;
+ mCropHeight = mHeight;
+ updatePortDefinitions();
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+ return true;
+ }
+
+ return false;
+}
+
+bool SoftAVC::handleCropRectEvent(const CropParams *crop) {
+ if (mCropLeft != crop->cropLeftOffset ||
+ mCropTop != crop->cropTopOffset ||
+ mCropWidth != crop->cropOutWidth ||
+ mCropHeight != crop->cropOutHeight) {
+ mCropLeft = crop->cropLeftOffset;
+ mCropTop = crop->cropTopOffset;
+ mCropWidth = crop->cropOutWidth;
+ mCropHeight = crop->cropOutHeight;
+
+ notify(OMX_EventPortSettingsChanged, 1,
+ OMX_IndexConfigCommonOutputCrop, NULL);
+
+ return true;
+ }
+ return false;
+}
+
+void SoftAVC::saveFirstOutputBuffer(int32_t picId, uint8_t *data) {
+ CHECK(mFirstPicture == NULL);
+ mFirstPictureId = picId;
+
+ mFirstPicture = new uint8_t[mPictureSize];
+ memcpy(mFirstPicture, data, mPictureSize);
+}
+
+void SoftAVC::drainOneOutputBuffer(int32_t picId, uint8_t* data) {
+ List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
+ BufferInfo *outInfo = *outQueue.begin();
+ outQueue.erase(outQueue.begin());
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+ OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId);
+ outHeader->nTimeStamp = header->nTimeStamp;
+ outHeader->nFlags = header->nFlags;
+ outHeader->nFilledLen = mPictureSize;
+ memcpy(outHeader->pBuffer + outHeader->nOffset,
+ data, mPictureSize);
+ mPicToHeaderMap.removeItem(picId);
+ delete header;
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+}
+
+bool SoftAVC::drainAllOutputBuffers() {
+ List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
+ H264SwDecPicture decodedPicture;
+
+ while (!outQueue.empty()) {
+ BufferInfo *outInfo = *outQueue.begin();
+ outQueue.erase(outQueue.begin());
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+ if (mHeadersDecoded &&
+ H264SWDEC_PIC_RDY ==
+ H264SwDecNextPicture(mHandle, &decodedPicture, 1 /* flush */)) {
+
+ int32_t picId = decodedPicture.picId;
+ CHECK(mPicToHeaderMap.indexOfKey(picId) >= 0);
+
+ memcpy(outHeader->pBuffer + outHeader->nOffset,
+ decodedPicture.pOutputPicture,
+ mPictureSize);
+
+ OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId);
+ outHeader->nTimeStamp = header->nTimeStamp;
+ outHeader->nFlags = header->nFlags;
+ outHeader->nFilledLen = mPictureSize;
+ mPicToHeaderMap.removeItem(picId);
+ delete header;
+ } else {
+ outHeader->nTimeStamp = 0;
+ outHeader->nFilledLen = 0;
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+ mEOSStatus = OUTPUT_FRAMES_FLUSHED;
+ }
+
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+ }
+
+ return true;
+}
+
+void SoftAVC::onPortFlushCompleted(OMX_U32 portIndex) {
+ if (portIndex == kInputPortIndex) {
+ mEOSStatus = INPUT_DATA_AVAILABLE;
+ }
+}
+
+void SoftAVC::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
+ switch (mOutputPortSettingsChange) {
+ case NONE:
+ break;
+
+ case AWAITING_DISABLED:
+ {
+ CHECK(!enabled);
+ mOutputPortSettingsChange = AWAITING_ENABLED;
+ break;
+ }
+
+ default:
+ {
+ CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
+ CHECK(enabled);
+ mOutputPortSettingsChange = NONE;
+ break;
+ }
+ }
+}
+
+void SoftAVC::updatePortDefinitions() {
+ OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef;
+ def->format.video.nFrameWidth = mWidth;
+ def->format.video.nFrameHeight = mHeight;
+ def->format.video.nStride = def->format.video.nFrameWidth;
+ def->format.video.nSliceHeight = def->format.video.nFrameHeight;
+
+ def = &editPortInfo(1)->mDef;
+ def->format.video.nFrameWidth = mWidth;
+ def->format.video.nFrameHeight = mHeight;
+ def->format.video.nStride = def->format.video.nFrameWidth;
+ def->format.video.nSliceHeight = def->format.video.nFrameHeight;
+
+ def->nBufferSize =
+ (def->format.video.nFrameWidth
+ * def->format.video.nFrameHeight * 3) / 2;
+}
+
+} // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+ const char *name, const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+ return new android::SoftAVC(name, callbacks, appData, component);
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
new file mode 100644
index 0000000..879b014
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SOFT_AVC_H_
+
+#define SOFT_AVC_H_
+
+#include "SimpleSoftOMXComponent.h"
+#include <utils/KeyedVector.h>
+
+#include "H264SwDecApi.h"
+#include "basetype.h"
+
+namespace android {
+
+struct SoftAVC : public SimpleSoftOMXComponent {
+ SoftAVC(const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ virtual ~SoftAVC();
+
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual OMX_ERRORTYPE getConfig(OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual void onQueueFilled(OMX_U32 portIndex);
+ virtual void onPortFlushCompleted(OMX_U32 portIndex);
+ virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled);
+
+private:
+ enum {
+ kInputPortIndex = 0,
+ kOutputPortIndex = 1,
+ kNumInputBuffers = 8,
+ kNumOutputBuffers = 2,
+ };
+
+ enum EOSStatus {
+ INPUT_DATA_AVAILABLE,
+ INPUT_EOS_SEEN,
+ OUTPUT_FRAMES_FLUSHED,
+ };
+
+ void *mHandle;
+
+ size_t mInputBufferCount;
+
+ uint32_t mWidth, mHeight, mPictureSize;
+ uint32_t mCropLeft, mCropTop;
+ uint32_t mCropWidth, mCropHeight;
+
+ uint8_t *mFirstPicture;
+ int32_t mFirstPictureId;
+
+ int32_t mPicId; // Which output picture is for which input buffer?
+
+ // OMX_BUFFERHEADERTYPE may be overkill, but it is convenient
+ // for tracking the following fields: nFlags, nTimeStamp, etc.
+ KeyedVector<int32_t, OMX_BUFFERHEADERTYPE *> mPicToHeaderMap;
+ bool mHeadersDecoded;
+
+ EOSStatus mEOSStatus;
+
+ enum OutputPortSettingChange {
+ NONE,
+ AWAITING_DISABLED,
+ AWAITING_ENABLED
+ };
+ OutputPortSettingChange mOutputPortSettingsChange;
+
+ bool mSignalledError;
+
+ void initPorts();
+ status_t initDecoder();
+ void updatePortDefinitions();
+ bool drainAllOutputBuffers();
+ void drainOneOutputBuffer(int32_t picId, uint8_t *data);
+ void saveFirstOutputBuffer(int32_t pidId, uint8_t *data);
+ bool handleCropRectEvent(const CropParams* crop);
+ bool handlePortSettingChangeEvent(const H264SwDecInfo *info);
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftAVC);
+};
+
+} // namespace android
+
+#endif // SOFT_AVC_H_
+
diff --git a/media/libstagefright/codecs/on2/h264dec/inc/H264SwDecApi.h b/media/libstagefright/codecs/on2/h264dec/inc/H264SwDecApi.h
new file mode 100755
index 0000000..fe112bc
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/inc/H264SwDecApi.h
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include Headers
+
+ 2. Enumerations used as a return value or a parameter.
+ 2.1. API's return value enumerations.
+
+ 3. User Structures
+ 3.1. Structures for H264SwDecDecode() parameters.
+ 3.2. Structures for information interchange with
+ DEC API and user application.
+
+ 4. Prototypes of Decoder API functions
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDECAPI_H
+#define H264SWDECAPI_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*------------------------------------------------------------------------------
+ 1. Include Headers
+------------------------------------------------------------------------------*/
+
+ #include "basetype.h"
+
+/*------------------------------------------------------------------------------
+ 2.1. API's return value enumerations.
+------------------------------------------------------------------------------*/
+
+ typedef enum
+ {
+ H264SWDEC_OK = 0,
+ H264SWDEC_STRM_PROCESSED = 1,
+ H264SWDEC_PIC_RDY,
+ H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY,
+ H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY,
+ H264SWDEC_PARAM_ERR = -1,
+ H264SWDEC_STRM_ERR = -2,
+ H264SWDEC_NOT_INITIALIZED = -3,
+ H264SWDEC_MEMFAIL = -4,
+ H264SWDEC_INITFAIL = -5,
+ H264SWDEC_HDRS_NOT_RDY = -6,
+ H264SWDEC_EVALUATION_LIMIT_EXCEEDED = -7
+ } H264SwDecRet;
+
+/*------------------------------------------------------------------------------
+ 3.1. Structures for H264SwDecDecode() parameters.
+------------------------------------------------------------------------------*/
+
+ /* typedef of the Decoder instance */
+ typedef void *H264SwDecInst;
+
+ /* Input structure */
+ typedef struct
+ {
+ u8 *pStream; /* Pointer to stream to be decoded */
+ u32 dataLen; /* Number of bytes to be decoded */
+ u32 picId; /* Identifier for the picture to be decoded */
+ u32 intraConcealmentMethod; /* 0 = Gray concealment for intra
+ 1 = Reference concealment for intra */
+
+ } H264SwDecInput;
+
+
+ /* Output structure */
+ typedef struct
+ {
+ u8 *pStrmCurrPos; /* Pointer to stream position where decoder
+ ended up */
+ } H264SwDecOutput;
+
+ /* Output structure for H264SwDecNextPicture */
+ typedef struct
+ {
+ u32 *pOutputPicture; /* Pointer to the picture, YUV format */
+ u32 picId; /* Identifier of the picture to be displayed*/
+ u32 isIdrPicture; /* Flag to indicate if the picture is an
+ IDR picture */
+ u32 nbrOfErrMBs; /* Number of concealed MB's in the picture */
+ } H264SwDecPicture;
+
+/*------------------------------------------------------------------------------
+ 3.2. Structures for information interchange with DEC API
+ and user application.
+------------------------------------------------------------------------------*/
+
+ typedef struct
+ {
+ u32 cropLeftOffset;
+ u32 cropOutWidth;
+ u32 cropTopOffset;
+ u32 cropOutHeight;
+ } CropParams;
+
+ typedef struct
+ {
+ u32 profile;
+ u32 picWidth;
+ u32 picHeight;
+ u32 videoRange;
+ u32 matrixCoefficients;
+ u32 parWidth;
+ u32 parHeight;
+ u32 croppingFlag;
+ CropParams cropParams;
+ } H264SwDecInfo;
+
+ /* Version information */
+ typedef struct
+ {
+ u32 major; /* Decoder API major version */
+ u32 minor; /* Dncoder API minor version */
+ } H264SwDecApiVersion;
+
+/*------------------------------------------------------------------------------
+ 4. Prototypes of Decoder API functions
+------------------------------------------------------------------------------*/
+
+ H264SwDecRet H264SwDecDecode(H264SwDecInst decInst,
+ H264SwDecInput *pInput,
+ H264SwDecOutput *pOutput);
+
+ H264SwDecRet H264SwDecInit(H264SwDecInst *decInst,
+ u32 noOutputReordering);
+
+ H264SwDecRet H264SwDecNextPicture(H264SwDecInst decInst,
+ H264SwDecPicture *pOutput,
+ u32 endOfStream);
+
+ H264SwDecRet H264SwDecGetInfo(H264SwDecInst decInst,
+ H264SwDecInfo *pDecInfo);
+
+ void H264SwDecRelease(H264SwDecInst decInst);
+
+ H264SwDecApiVersion H264SwDecGetAPIVersion(void);
+
+ /* function prototype for API trace */
+ void H264SwDecTrace(char *);
+
+ /* function prototype for memory allocation */
+ void* H264SwDecMalloc(u32 size);
+
+ /* function prototype for memory free */
+ void H264SwDecFree(void *ptr);
+
+ /* function prototype for memory copy */
+ void H264SwDecMemcpy(void *dest, void *src, u32 count);
+
+ /* function prototype for memset */
+ void H264SwDecMemset(void *ptr, i32 value, u32 count);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H264SWDECAPI_H */
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/inc/basetype.h b/media/libstagefright/codecs/on2/h264dec/inc/basetype.h
new file mode 100755
index 0000000..63d5653
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/inc/basetype.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+
+#ifndef BASETYPE_H_INCLUDED
+#define BASETYPE_H_INCLUDED
+
+
+#ifdef __arm
+#define VOLATILE volatile
+#else
+#define VOLATILE
+#endif
+
+typedef unsigned char u8;
+typedef signed char i8;
+typedef unsigned short u16;
+typedef signed short i16;
+typedef unsigned int u32;
+typedef signed int i32;
+
+#if defined(VC1SWDEC_16BIT) || defined(MP4ENC_ARM11)
+typedef unsigned short u16x;
+typedef signed short i16x;
+#else
+typedef unsigned int u16x;
+typedef signed int i16x;
+#endif
+
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#endif /* BASETYPE_H_INCLUDED */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/ARM_DELIVERY.TXT b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/ARM_DELIVERY.TXT
new file mode 100644
index 0000000..5ce70ca
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/ARM_DELIVERY.TXT
@@ -0,0 +1,63 @@
+The contents of this transaction was created by Hedley Francis
+of ARM on 19-Feb-2008.
+
+It contains the ARM data versions listed below.
+
+This data, unless otherwise stated, is ARM Proprietary and access to it
+is subject to the agreements indicated below.
+
+If you experience problems with this data, please contact ARM support
+quoting transaction reference <97413>.
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+- OX001-SW-98010-r0p0-00bet1
+ Video codecs - optimised code
+ V6 optimized code release for Hantro (Ver 1.0.2)
+ internal access
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+This transaction contains deliverables which are designated as being of
+beta release status (BET).
+
+Beta release status has a particular meaning to ARM of which the recipient
+must be aware. Beta is a pre-release status indicating that the deliverable
+so described is believed to robustly demonstrate specified behaviour, to be
+consistent across its included aspects and be ready for general deployment.
+But Beta also indicates that pre-release reliability trials are ongoing and
+that it is possible residual defects or errors in operation, consistency
+and documentation may still be encountered. The recipient should consider
+this position when using this Beta material supplied. ARM will normally
+attempt to provide fixes or a work-around for defects identified by the
+recipient, but the provision or timeliness of this support cannot be
+guaranteed. ARM shall not be responsible for direct or consequential
+damages as a result of encountering one or more of these residual defects.
+By accepting a Beta release, the recipient agrees to these constraints and
+to providing reasonable information to ARM to enable the replication of the
+defects identified by the recipient. The specific Beta version supplied
+will not be supported after release of a later or higher status version.
+It should be noted that Support for the Beta release of the deliverable
+will only be provided by ARM to a recipient who has a current support and
+maintenance contract for the deliverable.
+
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+In addition to the data versions listed above, this transaction contains
+two additional files at the top level.
+
+The first is this file, ARM_DELIVERY_97413.TXT, which is the delivery
+note.
+
+The second is ARM_MANIFEST_97413.TXT which contains a manifest of all the
+files included in this transaction, together with their checksums.
+
+The checksums provided are calculated using the RSA Data Security, Inc.
+MD5 Message-Digest Algorithm.
+
+The checksums can be used to verify the integrity of this data using the
+"md5sum" tool (which is part of the GNU "textutils" package) by running:
+
+ % md5sum --check ARM_MANIFEST_97413.TXT
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/ARM_MANIFEST.TXT b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/ARM_MANIFEST.TXT
new file mode 100644
index 0000000..9b2238b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/ARM_MANIFEST.TXT
@@ -0,0 +1,91 @@
+ OX001-SW-98010-r0p0-00bet1/
+ OX001-SW-98010-r0p0-00bet1/api/
+e049791cfab6060a08cbac7b3ad767d6 OX001-SW-98010-r0p0-00bet1/api/armCOMM_s.h
+ed798face25497b2703ede736d6d52b6 OX001-SW-98010-r0p0-00bet1/api/omxtypes_s.h
+4eebd63af087376811d6749f0646b864 OX001-SW-98010-r0p0-00bet1/api/armCOMM_BitDec_s.h
+43cf46c2cf2fe1f93c615b57bcbe4809 OX001-SW-98010-r0p0-00bet1/api/armCOMM.h
+8f248ceaac8f602e277a521b679dcbbe OX001-SW-98010-r0p0-00bet1/api/armCOMM_IDCTTable.h
+53f2ae8a98495f05e26a4cf862a7f750 OX001-SW-98010-r0p0-00bet1/api/armCOMM_Version.h
+3a2f420ddf6a1b950470bd0f5ebd5c62 OX001-SW-98010-r0p0-00bet1/api/armCOMM_IDCT_s.h
+511c0bb534fe223599e2c84eff24c9ed OX001-SW-98010-r0p0-00bet1/api/armCOMM_MaskTable.h
+8971932d56eed6b1ad1ba507f0bff5f0 OX001-SW-98010-r0p0-00bet1/api/armCOMM_Bitstream.h
+f87fedd9ca432fefa757008176864ef8 OX001-SW-98010-r0p0-00bet1/api/armOMX.h
+8e49899a428822c36ef9dd94e0e05f18 OX001-SW-98010-r0p0-00bet1/api/omxtypes.h
+694281d11af52f88e6f9d4cb226ac8a7 OX001-SW-98010-r0p0-00bet1/build_vc.pl
+e72d96c0a415459748df9807f3dae72f OX001-SW-98010-r0p0-00bet1/filelist_vc.txt
+ OX001-SW-98010-r0p0-00bet1/src/
+5eeae659a29477f5c52296d24afffd3c OX001-SW-98010-r0p0-00bet1/src/armCOMM_IDCTTable.c
+d64cdcf38f7749dc7f77465e5b7d356d OX001-SW-98010-r0p0-00bet1/src/armCOMM_MaskTable.c
+ OX001-SW-98010-r0p0-00bet1/vc/
+ OX001-SW-98010-r0p0-00bet1/vc/m4p10/
+ OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/
+e7e0c320978564a7c9b2c723749a98d6 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_CAVLCTables.c
+4adcd0df081990bdfc4729041a2a9152 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
+852e0404142965dc1f3aa7f00ee5127b OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
+7054151c5bfea6b5e74feee86b2d7b01 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
+38944c5e0bba01e32ff349c2c87c71b2 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_DequantTables_s.s
+32ff4b8be62e2f0f3e764b83c1e5e2fd OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
+90b0e6a04e764902c0a0903640c10b32 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
+28a19ae4fe2258628080d6a89bb54b91 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
+98e196b9e1ffebaf91f62ea9d17fb97d OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
+01ba60eff66ea49a4f833ce6279f8e2f OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
+f301d5a95e07354f593ea5747c01cb0a OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
+44c9ef21e840a100301f7d7a4189957c OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
+a33b03bbd3352d24ed744769e12bb87d OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
+00c20bfda67bb86096b615fc17c94b35 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
+2ddcaf60a8ea1e6e6b77737f768bfb9d OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_QuantTables_s.s
+c3002aad5600f872b70a5d7fe3915846 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
+a2900f2c47f1c61d20bd6c1eda33d6d4 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
+e4fecd66bc47f07539bc308935e84a1f OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
+78815c9df50ba53131bb22d2b829e3c3 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
+1909ae312ac79a03a5fac1d1e8bc0291 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
+3d2c48580655928065de7839866d9bc4 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
+23aa2fdf155d4fa6ff745eab6e01f32b OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
+97f20a93c481d7f6173d919f41e415bd OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
+becd512da202436286811b6aec061f47 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
+dd24a99ae3cd842dcacaf31d47de88b3 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
+c2d995f787b6f44ef10c751c12d1935f OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
+3628fbdf0cd217c287b6ccc94135d06e OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
+4a52b3e9e268b8a8f07829bf500d03af OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
+11249f8a98c5d4b84cb5575b0e37ca9c OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
+3599b1074330965c8ca285d164efccff OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
+3339e026c7de655d9400949eb5e51451 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
+cc4a6f32db0b72a91d3f278f6855df69 OX001-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
+ OX001-SW-98010-r0p0-00bet1/vc/m4p10/api/
+6e530ddaa7c2b57ffe88162c020cb662 OX001-SW-98010-r0p0-00bet1/vc/m4p10/api/armVCM4P10_CAVLCTables.h
+ OX001-SW-98010-r0p0-00bet1/vc/m4p2/
+ OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/
+cdf412920c2037a725d0420002b6752e OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_Clip8_s.s
+dba9824e959b21d401cac925e68a11a6 OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
+b559b71d5c94627f10e616fb72c0cefc OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
+4fba4c431a783a78a2eb6497a94ac967 OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
+1e4c3be8c5eddc00c9f05e83bcf315ef OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
+1b0b2990c2669dfb87cf6b810611c01b OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
+1c9b87abf3283e957816b3937c680701 OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
+4fe1afca659a9055fc1172e58f78a506 OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
+2ea067f0436f91ba1351edaf411cb4ea OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_Lookup_Tables.c
+acb92be1dbcdb3ebe824cbe9e28d03bf OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
+a6b41f01b1df7dd656ebdba3084bfa2a OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
+293a48a648a3085456e6665bb7366fad OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_SetPredDir_s.s
+ffe6b96c74d4881f4d3c8de8cc737797 OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
+437dfa204508850d61d4b87091446e9f OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
+ff5915d181bfd2cd2f0bd588bd2300dc OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
+6775eb0c561dbab965c60f85b08c96fd OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
+a0d85f4f517c945a4c9317ac021f2d08 OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
+386020dee8b725c7fe2526f1fc211d7d OX001-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
+ OX001-SW-98010-r0p0-00bet1/vc/m4p2/api/
+4624e7c838e10a249abcc3d3f4f40748 OX001-SW-98010-r0p0-00bet1/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
+65e1057d04e2cb844559dc9f6e09795a OX001-SW-98010-r0p0-00bet1/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
+ OX001-SW-98010-r0p0-00bet1/vc/src/
+e627b3346b0dc9aff14446005ce0fa43 OX001-SW-98010-r0p0-00bet1/vc/src/armVC_Version.c
+ OX001-SW-98010-r0p0-00bet1/vc/api/
+7ca94b1c33ac0211e17d38baadd7d1dd OX001-SW-98010-r0p0-00bet1/vc/api/armVC.h
+12cf7596edbbf6048b626d15e8d0ed48 OX001-SW-98010-r0p0-00bet1/vc/api/omxVC.h
+11726e286a81257cb45f5547fb4d374c OX001-SW-98010-r0p0-00bet1/vc/api/omxVC_s.h
+a5b2af605c319cd2491319e430741377 OX001-SW-98010-r0p0-00bet1/vc/api/armVCCOMM_s.h
+ OX001-SW-98010-r0p0-00bet1/vc/comm/
+ OX001-SW-98010-r0p0-00bet1/vc/comm/src/
+50cca6954c447b012ab39ca7872e5e8f OX001-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_Copy16x16_s.s
+d1c3bce77fc5774c899b447d13f02cd0 OX001-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_Copy8x8_s.s
+fdac1d1bad3fd23c880beb39bc2e89aa OX001-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
+6d9adc2be5bd0311591030d0c6df771c ARM_DELIVERY_97413.TXT
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM.h
new file mode 100644
index 0000000..2ed86a4
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM.h
@@ -0,0 +1,785 @@
+/**
+ *
+ * File Name: armCOMM.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armCOMM.h
+ * Brief: Declares Common APIs/Data Types used across OpenMAX API's
+ *
+ */
+
+
+#ifndef _armCommon_H_
+#define _armCommon_H_
+
+#include "omxtypes.h"
+
+typedef struct
+{
+ OMX_F32 Re; /** Real part */
+ OMX_F32 Im; /** Imaginary part */
+
+} OMX_FC32; /** single precision floating point complex number */
+
+typedef struct
+{
+ OMX_F64 Re; /** Real part */
+ OMX_F64 Im; /** Imaginary part */
+
+} OMX_FC64; /** double precision floating point complex number */
+
+
+/* Used by both IP and IC domains for 8x8 JPEG blocks. */
+typedef OMX_S16 ARM_BLOCK8x8[64];
+
+
+#include "armOMX.h"
+
+#define armPI (OMX_F64)(3.1415926535897932384626433832795)
+
+/***********************************************************************/
+
+/* Compiler extensions */
+#ifdef ARM_DEBUG
+/* debug version */
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#define armError(str) {printf((str)); printf("\n"); exit(-1);}
+#define armWarn(str) {printf((str)); printf("\n");}
+#define armIgnore(a) ((void)a)
+#define armAssert(a) assert(a)
+#else
+/* release version */
+#define armError(str) ((void) (str))
+#define armWarn(str) ((void) (str))
+#define armIgnore(a) ((void) (a))
+#define armAssert(a) ((void) (a))
+#endif /* ARM_DEBUG */
+
+/* Arithmetic operations */
+
+#define armMin(a,b) ( (a) > (b) ? (b):(a) )
+#define armMax(a,b) ( (a) > (b) ? (a):(b) )
+#define armAbs(a) ( (a) < 0 ? -(a):(a) )
+
+/* Alignment operation */
+
+#define armAlignToBytes(Ptr,N) (Ptr + ( ((N-(int)Ptr)&(N-1)) / sizeof(*Ptr) ))
+#define armAlignTo2Bytes(Ptr) armAlignToBytes(Ptr,2)
+#define armAlignTo4Bytes(Ptr) armAlignToBytes(Ptr,4)
+#define armAlignTo8Bytes(Ptr) armAlignToBytes(Ptr,8)
+#define armAlignTo16Bytes(Ptr) armAlignToBytes(Ptr,16)
+
+/* Error and Alignment check */
+
+#define armRetArgErrIf(condition, code) if(condition) { return (code); }
+#define armRetDataErrIf(condition, code) if(condition) { return (code); }
+
+#ifndef ALIGNMENT_DOESNT_MATTER
+#define armIsByteAligned(Ptr,N) ((((int)(Ptr)) % N)==0)
+#define armNotByteAligned(Ptr,N) ((((int)(Ptr)) % N)!=0)
+#else
+#define armIsByteAligned(Ptr,N) (1)
+#define armNotByteAligned(Ptr,N) (0)
+#endif
+
+#define armIs2ByteAligned(Ptr) armIsByteAligned(Ptr,2)
+#define armIs4ByteAligned(Ptr) armIsByteAligned(Ptr,4)
+#define armIs8ByteAligned(Ptr) armIsByteAligned(Ptr,8)
+#define armIs16ByteAligned(Ptr) armIsByteAligned(Ptr,16)
+
+#define armNot2ByteAligned(Ptr) armNotByteAligned(Ptr,2)
+#define armNot4ByteAligned(Ptr) armNotByteAligned(Ptr,4)
+#define armNot8ByteAligned(Ptr) armNotByteAligned(Ptr,8)
+#define armNot16ByteAligned(Ptr) armNotByteAligned(Ptr,16)
+#define armNot32ByteAligned(Ptr) armNotByteAligned(Ptr,32)
+
+/**
+ * Function: armRoundFloatToS16_ref/armRoundFloatToS32_ref/armRoundFloatToS64
+ *
+ * Description:
+ * Converts a double precision value into a short int/int after rounding
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S16/OMX_S32 format
+ *
+ */
+
+OMX_S16 armRoundFloatToS16 (OMX_F64 Value);
+OMX_S32 armRoundFloatToS32 (OMX_F64 Value);
+OMX_S64 armRoundFloatToS64 (OMX_F64 Value);
+
+/**
+ * Function: armSatRoundFloatToS16_ref/armSatRoundFloatToS32
+ *
+ * Description:
+ * Converts a double precision value into a short int/int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S16/OMX_S32 format
+ *
+ */
+
+OMX_S16 armSatRoundFloatToS16 (OMX_F64 Value);
+OMX_S32 armSatRoundFloatToS32 (OMX_F64 Value);
+
+/**
+ * Function: armSatRoundFloatToU16_ref/armSatRoundFloatToU32
+ *
+ * Description:
+ * Converts a double precision value into a unsigned short int/int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_U16/OMX_U32 format
+ *
+ */
+
+OMX_U16 armSatRoundFloatToU16 (OMX_F64 Value);
+OMX_U32 armSatRoundFloatToU32 (OMX_F64 Value);
+
+/**
+ * Function: armSignCheck
+ *
+ * Description:
+ * Checks the sign of a variable:
+ * returns 1 if it is Positive
+ * returns 0 if it is 0
+ * returns -1 if it is Negative
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] var Variable to be checked
+ *
+ * Return Value:
+ * OMX_INT -- returns 1 if it is Positive
+ * returns 0 if it is 0
+ * returns -1 if it is Negative
+ */
+
+OMX_INT armSignCheck (OMX_S16 var);
+
+/**
+ * Function: armClip
+ *
+ * Description: Clips the input between MAX and MIN value
+ *
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] Min lower bound
+ * [in] Max upper bound
+ * [in] src variable to the clipped
+ *
+ * Return Value:
+ * OMX_S32 -- returns clipped value
+ */
+
+OMX_S32 armClip (
+ OMX_INT min,
+ OMX_INT max,
+ OMX_S32 src
+ );
+
+/**
+ * Function: armClip_F32
+ *
+ * Description: Clips the input between MAX and MIN value
+ *
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] Min lower bound
+ * [in] Max upper bound
+ * [in] src variable to the clipped
+ *
+ * Return Value:
+ * OMX_F32 -- returns clipped value
+ */
+
+OMX_F32 armClip_F32 (
+ OMX_F32 min,
+ OMX_F32 max,
+ OMX_F32 src
+ );
+
+/**
+ * Function: armShiftSat_F32
+ *
+ * Description: Divides a float value by 2^shift and
+ * saturates it for unsigned value range for satBits.
+ * Second parameter is like "shifting" the corresponding
+ * integer value. Takes care of rounding while clipping the final
+ * value.
+ *
+ * Parameters:
+ * [in] v Number to be operated upon
+ * [in] shift Divides the input "v" by "2^shift"
+ * [in] satBits Final range is [0, 2^satBits)
+ *
+ * Return Value:
+ * OMX_S32 -- returns "shifted" saturated value
+ */
+
+OMX_U32 armShiftSat_F32(
+ OMX_F32 v,
+ OMX_INT shift,
+ OMX_INT satBits
+ );
+
+/**
+ * Functions: armSwapElem
+ *
+ * Description:
+ * This function swaps two elements at the specified pointer locations.
+ * The size of each element could be anything as specified by <elemSize>
+ *
+ * Return Value:
+ * OMXResult -- Error status from the function
+ */
+OMXResult armSwapElem(OMX_U8 *pBuf1, OMX_U8 *pBuf2, OMX_INT elemSize);
+
+
+/**
+ * Function: armMedianOf3
+ *
+ * Description: Finds the median of three numbers
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] fEntry First entry
+ * [in] sEntry second entry
+ * [in] tEntry Third entry
+ *
+ * Return Value:
+ * OMX_S32 -- returns the median value
+ */
+
+OMX_S32 armMedianOf3 (
+ OMX_S32 fEntry,
+ OMX_S32 sEntry,
+ OMX_S32 tEntry
+ );
+
+/**
+ * Function: armLogSize
+ *
+ * Description: Finds the size of a positive value and returns the same
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] value Positive value
+ *
+ * Return Value:
+ * OMX_U8 -- returns the size of the positive value
+ */
+
+OMX_U8 armLogSize (
+ OMX_U16 value
+ );
+
+/***********************************************************************/
+ /* Saturating Arithmetic operations */
+
+/**
+ * Function :armSatAdd_S32()
+ *
+ * Description :
+ * Returns the result of saturated addition of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ *
+ **/
+
+OMX_S32 armSatAdd_S32(
+ OMX_S32 Value1,
+ OMX_S32 Value2
+ );
+
+/**
+ * Function :armSatAdd_S64()
+ *
+ * Description :
+ * Returns the result of saturated addition of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ *
+ **/
+
+OMX_S64 armSatAdd_S64(
+ OMX_S64 Value1,
+ OMX_S64 Value2
+ );
+
+/** Function :armSatSub_S32()
+ *
+ * Description :
+ * Returns the result of saturated substraction of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatSub_S32(
+ OMX_S32 Value1,
+ OMX_S32 Value2
+ );
+
+/**
+ * Function :armSatMac_S32()
+ *
+ * Description :
+ * Returns the result of Multiplication of Value1 and Value2 and subesquent saturated
+ * accumulation with Mac
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ * [in] Mac Accumulator
+ *
+ * Return:
+ * [out] Result of operation
+ **/
+
+OMX_S32 armSatMac_S32(
+ OMX_S32 Mac,
+ OMX_S16 Value1,
+ OMX_S16 Value2
+ );
+
+/**
+ * Function :armSatMac_S16S32_S32
+ *
+ * Description :
+ * Returns the result of saturated MAC operation of the three inputs delayElem, filTap , mac
+ *
+ * mac = mac + Saturate_in_32Bits(delayElem * filTap)
+ *
+ * Parametrs:
+ * [in] delayElem First 32 bit Operand
+ * [in] filTap Second 16 bit Operand
+ * [in] mac Result of MAC operation
+ *
+ * Return:
+ * [out] mac Result of operation
+ *
+ **/
+
+OMX_S32 armSatMac_S16S32_S32(
+ OMX_S32 mac,
+ OMX_S32 delayElem,
+ OMX_S16 filTap );
+
+/**
+ * Function :armSatRoundRightShift_S32_S16
+ *
+ * Description :
+ * Returns the result of rounded right shift operation of input by the scalefactor
+ *
+ * output = Saturate_in_16Bits( ( RightShift( (Round(input) , scaleFactor ) )
+ *
+ * Parametrs:
+ * [in] input The input to be operated on
+ * [in] scaleFactor The shift number
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+
+OMX_S16 armSatRoundRightShift_S32_S16(
+ OMX_S32 input,
+ OMX_INT scaleFactor);
+
+/**
+ * Function :armSatRoundLeftShift_S32()
+ *
+ * Description :
+ * Returns the result of saturating left-shift operation on input
+ * Or rounded Right shift if the input Shift is negative.
+ *
+ * Parametrs:
+ * [in] Value Operand
+ * [in] shift Operand for shift operation
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatRoundLeftShift_S32(
+ OMX_S32 Value,
+ OMX_INT shift
+ );
+
+/**
+ * Function :armSatRoundLeftShift_S64()
+ *
+ * Description :
+ * Returns the result of saturating left-shift operation on input
+ * Or rounded Right shift if the input Shift is negative.
+ *
+ * Parametrs:
+ * [in] Value Operand
+ * [in] shift Operand for shift operation
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S64 armSatRoundLeftShift_S64(
+ OMX_S64 Value,
+ OMX_INT shift
+ );
+
+/**
+ * Function :armSatMulS16S32_S32()
+ *
+ * Description :
+ * Returns the result of a S16 data type multiplied with an S32 data type
+ * in a S32 container
+ *
+ * Parametrs:
+ * [in] input1 Operand 1
+ * [in] input2 Operand 2
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+
+OMX_S32 armSatMulS16S32_S32(
+ OMX_S16 input1,
+ OMX_S32 input2);
+
+/**
+ * Function :armSatMulS32S32_S32()
+ *
+ * Description :
+ * Returns the result of a S32 data type multiplied with an S32 data type
+ * in a S32 container
+ *
+ * Parametrs:
+ * [in] input1 Operand 1
+ * [in] input2 Operand 2
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatMulS32S32_S32(
+ OMX_S32 input1,
+ OMX_S32 input2);
+
+
+/**
+ * Function :armIntDivAwayFromZero()
+ *
+ * Description : Integer division with rounding to the nearest integer.
+ * Half-integer values are rounded away from zero
+ * unless otherwise specified. For example 3//2 is rounded
+ * to 2, and -3//2 is rounded to -2.
+ *
+ * Parametrs:
+ * [in] Num Operand 1
+ * [in] Deno Operand 2
+ *
+ * Return:
+ * [out] Result of operation input1//input2
+ *
+ **/
+
+OMX_S32 armIntDivAwayFromZero (OMX_S32 Num, OMX_S32 Deno);
+
+
+/***********************************************************************/
+/*
+ * Debugging macros
+ *
+ */
+
+
+/*
+ * Definition of output stream - change to stderr if necessary
+ */
+#define DEBUG_STREAM stdout
+
+/*
+ * Debug printf macros, one for each argument count.
+ * Add more if needed.
+ */
+#ifdef DEBUG_ON
+#include <stdio.h>
+
+#define DEBUG_PRINTF_0(a) fprintf(DEBUG_STREAM, a)
+#define DEBUG_PRINTF_1(a, b) fprintf(DEBUG_STREAM, a, b)
+#define DEBUG_PRINTF_2(a, b, c) fprintf(DEBUG_STREAM, a, b, c)
+#define DEBUG_PRINTF_3(a, b, c, d) fprintf(DEBUG_STREAM, a, b, c, d)
+#define DEBUG_PRINTF_4(a, b, c, d, e) fprintf(DEBUG_STREAM, a, b, c, d, e)
+#define DEBUG_PRINTF_5(a, b, c, d, e, f) fprintf(DEBUG_STREAM, a, b, c, d, e, f)
+#define DEBUG_PRINTF_6(a, b, c, d, e, f, g) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g)
+#define DEBUG_PRINTF_7(a, b, c, d, e, f, g, h) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h)
+#define DEBUG_PRINTF_8(a, b, c, d, e, f, g, h, i) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i)
+#define DEBUG_PRINTF_9(a, b, c, d, e, f, g, h, i, j) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j)
+#define DEBUG_PRINTF_10(a, b, c, d, e, f, g, h, i, j, k) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k)
+#define DEBUG_PRINTF_11(a, b, c, d, e, f, g, h, i, j, k, l) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k, l)
+#define DEBUG_PRINTF_12(a, b, c, d, e, f, g, h, i, j, k, l, m) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k, l, m)
+#define DEBUG_PRINTF_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k, l, m, n)
+#define DEBUG_PRINTF_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
+#else /* DEBUG_ON */
+#define DEBUG_PRINTF_0(a)
+#define DEBUG_PRINTF_1(a, b)
+#define DEBUG_PRINTF_2(a, b, c)
+#define DEBUG_PRINTF_3(a, b, c, d)
+#define DEBUG_PRINTF_4(a, b, c, d, e)
+#define DEBUG_PRINTF_5(a, b, c, d, e, f)
+#define DEBUG_PRINTF_6(a, b, c, d, e, f, g)
+#define DEBUG_PRINTF_7(a, b, c, d, e, f, g, h)
+#define DEBUG_PRINTF_8(a, b, c, d, e, f, g, h, i)
+#define DEBUG_PRINTF_9(a, b, c, d, e, f, g, h, i, j)
+#define DEBUG_PRINTF_10(a, b, c, d, e, f, g, h, i, j, k)
+#define DEBUG_PRINTF_11(a, b, c, d, e, f, g, h, i, j, k, l)
+#define DEBUG_PRINTF_12(a, b, c, d, e, f, g, h, i, j, k, l, m)
+#define DEBUG_PRINTF_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n)
+#define DEBUG_PRINTF_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
+#endif /* DEBUG_ON */
+
+
+/*
+ * Domain and sub domain definitions
+ *
+ * In order to turn on debug for an entire domain or sub-domain
+ * at compile time, one of the DEBUG_DOMAIN_* below may be defined,
+ * which will activate debug in all of the defines it contains.
+ */
+
+#ifdef DEBUG_DOMAIN_AC
+#define DEBUG_OMXACAAC_DECODECHANPAIRELT_MPEG4
+#define DEBUG_OMXACAAC_DECODECHANPAIRELT
+#define DEBUG_OMXACAAC_DECODEDATSTRELT
+#define DEBUG_OMXACAAC_DECODEFILLELT
+#define DEBUG_OMXACAAC_DECODEISSTEREO_S32
+#define DEBUG_OMXACAAC_DECODEMSPNS_S32
+#define DEBUG_OMXACAAC_DECODEMSSTEREO_S32_I
+#define DEBUG_OMXACAAC_DECODEPRGCFGELT
+#define DEBUG_OMXACAAC_DECODETNS_S32_I
+#define DEBUG_OMXACAAC_DEINTERLEAVESPECTRUM_S32
+#define DEBUG_OMXACAAC_ENCODETNS_S32_I
+#define DEBUG_OMXACAAC_LONGTERMPREDICT_S32
+#define DEBUG_OMXACAAC_LONGTERMRECONSTRUCT_S32
+#define DEBUG_OMXACAAC_MDCTFWD_S32
+#define DEBUG_OMXACAAC_MDCTINV_S32_S16
+#define DEBUG_OMXACAAC_NOISELESSDECODE
+#define DEBUG_OMXACAAC_QUANTINV_S32_I
+#define DEBUG_OMXACAAC_UNPACKADIFHEADER
+#define DEBUG_OMXACAAC_UNPACKADTSFRAMEHEADER
+#define DEBUG_OMXACMP3_HUFFMANDECODESFBMBP_S32
+#define DEBUG_OMXACMP3_HUFFMANDECODESFB_S32
+#define DEBUG_OMXACMP3_HUFFMANDECODE_S32
+#define DEBUG_OMXACMP3_MDCTINV_S32
+#define DEBUG_OMXACMP3_REQUANTIZESFB_S32_I
+#define DEBUG_OMXACMP3_REQUANTIZE_S32_I
+#define DEBUG_OMXACMP3_SYNTHPQMF_S32_S16
+#define DEBUG_OMXACMP3_UNPACKFRAMEHEADER
+#define DEBUG_OMXACMP3_UNPACKSCALEFACTORS_S8
+#define DEBUG_OMXACMP3_UNPACKSIDEINFO
+#endif /* DEBUG_DOMAIN_AC */
+
+
+#ifdef DEBUG_DOMAIN_VC
+#define DEBUG_OMXVCM4P10_AVERAGE_16X
+#define DEBUG_OMXVCM4P10_AVERAGE_4X
+#define DEBUG_OMXVCM4P10_AVERAGE_8X
+#define DEBUG_OMXVCM4P10_DEBLOCKCHROMA_U8_C1IR
+#define DEBUG_OMXVCM4P10_DEBLOCKLUMA_U8_C1IR
+#define DEBUG_OMXVCM4P10_DECODECHROMADCCOEFFSTOPAIRCAVLC_U8
+#define DEBUG_OMXVCM4P10_DECODECOEFFSTOPAIRCAVLC_U8
+#define DEBUG_OMXVCM4P10_DEQUANTTRANSFORMACFROMPAIR_U8_S16_C1_DLX
+#define DEBUG_OMXVCM4P10_EXPANDFRAME
+#define DEBUG_OMXVCM4P10_FILTERDEBLOCKINGCHROMA_HOREDGE_U8_C1IR
+#define DEBUG_OMXVCM4P10_FILTERDEBLOCKINGCHROMA_VEREDGE_U8_C1IR
+#define DEBUG_OMXVCM4P10_FILTERDEBLOCKINGLUMA_HOREDGE_U8_C1IR
+#define DEBUG_OMXVCM4P10_FILTERDEBLOCKINGLUMA_VEREDGE_U8_C1IR
+#define DEBUG_OMXVCM4P10_PREDICTINTRACHROMA8X8_U8_C1R
+#define DEBUG_OMXVCM4P10_PREDICTINTRA_16X16_U8_C1R
+#define DEBUG_OMXVCM4P10_PREDICTINTRA_4X4_U8_C1R
+#define DEBUG_OMXVCM4P10_SADQUAR_16X
+#define DEBUG_OMXVCM4P10_SADQUAR_4X
+#define DEBUG_OMXVCM4P10_SADQUAR_8X
+#define DEBUG_OMXVCM4P10_SAD_16X
+#define DEBUG_OMXVCM4P10_SAD_4X
+#define DEBUG_OMXVCM4P10_SAD_8X
+#define DEBUG_OMXVCM4P10_SATD_4X4
+#define DEBUG_OMXVCM4P10_TRANSFORMDEQUANTCHROMADCFROMPAIR_U8_S16_C1
+#define DEBUG_OMXVCM4P10_TRANSFORMDEQUANTLUMADCFROMPAIR_U8_S16_C1
+#define DEBUG_OMXVCM4P10_TRANSFORMQUANT_CHROMADC
+#define DEBUG_OMXVCM4P10_TRANSFORMQUANT_LUMADC
+#define DEBUG_OMXVCM4P2_BLOCKMATCH_HALF_16X16
+#define DEBUG_OMXVCM4P2_BLOCKMATCH_HALF_8X8
+#define DEBUG_OMXVCM4P2_BLOCKMATCH_INTEGER_16X16
+#define DEBUG_OMXVCM4P2_BLOCKMATCH_INTEGER_8X8
+#define DEBUG_OMXVCM4P2_COMPUTETEXTUREERRORBLOCK_SAD_U8_S16
+#define DEBUG_OMXVCM4P2_COMPUTETEXTUREERRORBLOCK_U8_S16
+#define DEBUG_OMXVCM4P2_DCT8X8BLKDLX
+#define DEBUG_OMXVCM4P2_DECODEBLOCKCOEF_INTER_S16
+#define DEBUG_OMXVCM4P2_DECODEPADMV_PVOP
+#define DEBUG_OMXVCM4P2_DECODEVLCZIGZAG_INTER_S16
+#define DEBUG_OMXVCM4P2_DECODEVLCZIGZAG_INTRAACVLC_S16
+#define DEBUG_OMXVCM4P2_DECODEVLCZIGZAG_INTRADCVLC_S16
+#define DEBUG_OMXVCM4P2_ENCODEMV_U8_S16
+#define DEBUG_OMXVCM4P2_ENCODEVLCZIGZAG_INTER_S16
+#define DEBUG_OMXVCM4P2_ENCODEVLCZIGZAG_INTRAACVLC_S16
+#define DEBUG_OMXVCM4P2_ENCODEVLCZIGZAG_INTRADCVLC_S16
+#define DEBUG_OMXVCM4P2_FINDMVPRED
+#define DEBUG_OMXVCM4P2_IDCT8X8BLKDLX
+#define DEBUG_OMXVCM4P2_LIMITMVTORECT
+#define DEBUG_OMXVCM4P2_MOTIONESTIMATIONMB
+#define DEBUG_OMXVCM4P2_PADMBGRAY_U8
+#define DEBUG_OMXVCM4P2_PADMBHORIZONTAL_U8
+#define DEBUG_OMXVCM4P2_PADMBVERTICAL_U8
+#define DEBUG_OMXVCM4P2_PADMV
+#define DEBUG_OMXVCM4P2_QUANTINTER_S16_I
+#define DEBUG_OMXVCM4P2_QUANTINTRA_S16_I
+#define DEBUG_OMXVCM4P2_QUANTINVINTER_S16_I
+#define DEBUG_OMXVCM4P2_QUANTINVINTRA_S16_I
+#define DEBUG_OMXVCM4P2_TRANSRECBLOCKCEOF_INTER
+#define DEBUG_OMXVCM4P2_TRANSRECBLOCKCEOF_INTRA
+#endif /* DEBUG_DOMAIN_VC */
+
+
+#ifdef DEBUG_DOMAIN_IC
+/* To be filled in */
+#endif /* DEBUG_DOMAIN_IC */
+
+
+#ifdef DEBUG_DOMAIN_SP
+#define DEBUG_OMXACSP_DOTPROD_S16
+#define DEBUG_OMXACSP_BLOCKEXP_S16
+#define DEBUG_OMXACSP_BLOCKEXP_S32
+#define DEBUG_OMXACSP_COPY_S16
+#define DEBUG_OMXACSP_DOTPROD_S16
+#define DEBUG_OMXACSP_DOTPROD_S16_SFS
+#define DEBUG_OMXACSP_FFTFWD_CTOC_SC16_SFS
+#define DEBUG_OMXACSP_FFTFWD_CTOC_SC32_SFS
+#define DEBUG_OMXACSP_FFTFWD_RTOCCS_S16S32_SFS
+#define DEBUG_OMXACSP_FFTFWD_RTOCCS_S32_SFS
+#define DEBUG_OMXACSP_FFTGETBUFSIZE_C_SC16
+#define DEBUG_OMXACSP_FFTGETBUFSIZE_C_SC32
+#define DEBUG_OMXACSP_FFTGETBUFSIZE_R_S16_S32
+#define DEBUG_OMXACSP_FFTGETBUFSIZE_R_S32
+#define DEBUG_OMXACSP_FFTINIT_C_SC16
+#define DEBUG_OMXACSP_FFTINIT_C_SC32
+#define DEBUG_OMXACSP_FFTINIT_R_S16_S32
+#define DEBUG_OMXACSP_FFTINIT_R_S32
+#define DEBUG_OMXACSP_FFTINV_CCSTOR_S32S16_SFS
+#define DEBUG_OMXACSP_FFTINV_CCSTOR_S32_SFS
+#define DEBUG_OMXACSP_FFTINV_CTOC_SC16_SFS
+#define DEBUG_OMXACSP_FFTINV_CTOC_SC32_SFS
+#define DEBUG_OMXACSP_FILTERMEDIAN_S32_I
+#define DEBUG_OMXACSP_FILTERMEDIAN_S32
+#define DEBUG_OMXACSP_FIRONE_DIRECT_S16_ISFS
+#define DEBUG_OMXACSP_FIRONE_DIRECT_S16_I
+#define DEBUG_OMXACSP_FIRONE_DIRECT_S16
+#define DEBUG_OMXACSP_FIRONE_DIRECT_S16_SFS
+#define DEBUG_OMXACSP_FIR_DIRECT_S16_ISFS
+#define DEBUG_OMXACSP_FIR_DIRECT_S16_I
+#define DEBUG_OMXACSP_FIR_DIRECT_S16
+#define DEBUG_OMXACSP_FIR_DIRECT_S16_SFS
+#define DEBUG_OMXACSP_IIRONE_BIQUADDIRECT_S16_I
+#define DEBUG_OMXACSP_IIRONE_BIQUADDIRECT_S16
+#define DEBUG_OMXACSP_IIRONE_DIRECT_S16_I
+#define DEBUG_OMXACSP_IIRONE_DIRECT_S16
+#define DEBUG_OMXACSP_IIR_BIQUADDIRECT_S16_I
+#define DEBUG_OMXACSP_IIR_BIQUADDIRECT_S16
+#define DEBUG_OMXACSP_IIR_DIRECT_S16_I
+#define DEBUG_OMXACSP_IIR_DIRECT_S16
+#endif /* DEBUG_DOMAIN_SP */
+
+
+#ifdef DEBUG_DOMAIN_IP
+#define DEBUG_OMXIPBM_ADDC_U8_C1R_SFS
+#define DEBUG_OMXIPBM_COPY_U8_C1R
+#define DEBUG_OMXIPBM_COPY_U8_C3R
+#define DEBUG_OMXIPBM_MIRROR_U8_C1R
+#define DEBUG_OMXIPBM_MULC_U8_C1R_SFS
+#define DEBUG_OMXIPCS_COLORTWISTQ14_U8_C3R
+#define DEBUG_OMXIPCS_RGB565TOYCBCR420LS_MCU_U16_S16_C3P3R
+#define DEBUG_OMXIPCS_RGB565TOYCBCR422LS_MCU_U16_S16_C3P3R
+#define DEBUG_OMXIPCS_RGB565TOYCBCR444LS_MCU_U16_S16_C3P3R
+#define DEBUG_OMXIPCS_RGBTOYCBCR420LS_MCU_U8_S16_C3P3R
+#define DEBUG_OMXIPCS_RGBTOYCBCR422LS_MCU_U8_S16_C3P3R
+#define DEBUG_OMXIPCS_RGBTOYCBCR444LS_MCU_U8_S16_C3P3R
+#define DEBUG_OMXIPCS_YCBCR420RSZROT_U8_P3R
+#define DEBUG_OMXIPCS_YCBCR420TORGB565LS_MCU_S16_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCR420TORGB565_U8_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCR420TORGBLS_MCU_S16_U8_P3C3R
+#define DEBUG_OMXIPCS_YCBCR422RSZCSCROTRGB_U8_C2R
+#define DEBUG_OMXIPCS_YCBCR422RSZROT_U8_P3R
+#define DEBUG_OMXIPCS_YCBCR422TORGB565LS_MCU_S16_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCR422TORGB565_U8_U16_C2C3R
+#define DEBUG_OMXIPCS_YCBCR422TORGBLS_MCU_S16_U8_P3C3R
+#define DEBUG_OMXIPCS_YCBCR422TORGB_U8_C2C3R
+#define DEBUG_OMXIPCS_YCBCR422TOYCBCR420ROTATE_U8_C2P3R
+#define DEBUG_OMXIPCS_YCBCR422TOYCBCR420ROTATE_U8_P3R
+#define DEBUG_OMXIPCS_YCBCR444TORGB565LS_MCU_S16_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCR444TORGBLS_MCU_S16_U8_P3C3R
+#define DEBUG_OMXIPCS_YCBCRTORGB565_U8_U16_C3R
+#define DEBUG_OMXIPCS_YCBCRTORGB565_U8_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCRTORGB_U8_C3R
+#define DEBUG_OMXIPPP_GETCENTRALMOMENT_S64
+#define DEBUG_OMXIPPP_GETSPATIALMOMENT_S64
+#define DEBUG_OMXIPPP_MOMENTGETSTATESIZE_S64
+#define DEBUG_OMXIPPP_MOMENTINIT_S64
+#define DEBUG_OMXIPPP_MOMENTS64S_U8_C1R
+#define DEBUG_OMXIPPP_MOMENTS64S_U8_C3R
+#endif /* DEBUG_DOMAIN_IP */
+
+
+#endif /* _armCommon_H_ */
+
+/*End of File*/
+
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_BitDec_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_BitDec_s.h
new file mode 100644
index 0000000..abb98fc
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_BitDec_s.h
@@ -0,0 +1,670 @@
+;//
+;//
+;// File Name: armCOMM_BitDec_s.h
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// OpenMAX optimized bitstream decode module
+;//
+;// You must include armCOMM_s.h before including this file
+;//
+;// This module provides macros to perform assembly optimized fixed and
+;// variable length decoding from a read-only bitstream. The variable
+;// length decode modules take as input a pointer to a table of 16-bit
+;// entries of the following format.
+;//
+;// VLD Table Entry format
+;//
+;// 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+;// +------------------------------------------------+
+;// | Len | Symbol | 1 |
+;// +------------------------------------------------+
+;// | Offset | 0 |
+;// +------------------------------------------------+
+;//
+;// If the table entry is a leaf entry then bit 0 set:
+;// Len = Number of bits overread (0 to 7)
+;// Symbol = Symbol payload (unsigned 12 bits)
+;//
+;// If the table entry is an internal node then bit 0 is clear:
+;// Offset = Number of (16-bit) half words from the table
+;// start to the next table node
+;//
+;// The table is accessed by successive lookup up on the
+;// next Step bits of the input bitstream until a leaf node
+;// is obtained. The Step sizes are supplied to the VLD macro.
+;//
+;// USAGE:
+;//
+;// To use any of the macros in this package, first call:
+;//
+;// M_BD_INIT ppBitStream, pBitOffset, pBitStream, RBitBuffer, RBitCount, Tmp
+;//
+;// This caches the current bitstream position and next available
+;// bits in registers pBitStream, RBitBuffer, RBitCount. These registers
+;// are reserved for use by the bitstream decode package until you
+;// call M_BD_FINI.
+;//
+;// Next call the following macro(s) as many times as you need:
+;//
+;// M_BD_LOOK8 - Look ahead constant 1<=N<=8 bits into the bitstream
+;// M_BD_LOOK16 - Look ahead constant 1<=N<=16 bits into the bitstream
+;// M_BD_READ8 - Read constant 1<=N<=8 bits from the bitstream
+;// M_BD_READ16 - Read constant 1<=N<=16 bits from the bitstream
+;// M_BD_VREAD8 - Read variable 1<=N<=8 bits from the bitstream
+;// M_BD_VREAD16 - Read variable 1<=N<=16 bits from the bitstream
+;// M_BD_VLD - Perform variable length decode using lookup table
+;//
+;// Finally call the macro:
+;//
+;// M_BD_FINI ppBitStream, pBitOffset
+;//
+;// This writes the bitstream state back to memory.
+;//
+;// The three bitstream cache register names are assigned to the following global
+;// variables:
+;//
+
+ GBLS pBitStream ;// Register name for pBitStream
+ GBLS BitBuffer ;// Register name for BitBuffer
+ GBLS BitCount ;// Register name for BitCount
+
+;//
+;// These register variables must have a certain defined state on entry to every bitstream
+;// macro (except M_BD_INIT) and on exit from every bitstream macro (except M_BD_FINI).
+;// The state may depend on implementation.
+;//
+;// For the default (ARM11) implementation the following hold:
+;// pBitStream - points to the first byte not held in the BitBuffer
+;// BitBuffer - is a cache of (4 bytes) 32 bits, bit 31 the first bit
+;// BitCount - is offset (from the top bit) to the next unused bitstream bit
+;// 0<=BitCount<=15 (so BitBuffer holds at least 17 unused bits)
+;//
+;//
+
+ ;// Bitstream Decode initialise
+ ;//
+ ;// Initialises the bitstream decode global registers from
+ ;// bitstream pointers. This macro is split into 3 parts to enable
+ ;// scheduling.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $ppBitStream - pointer to pointer to the next bitstream byte
+ ;// $pBitOffset - pointer to the number of bits used in the current byte (0..7)
+ ;// $RBitStream - register to use for pBitStream (can be $ppBitStream)
+ ;// $RBitBuffer - register to use for BitBuffer
+ ;// $RBitCount - register to use for BitCount (can be $pBitOffset)
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $T1,$T2,$T3 - registers that must be preserved between calls to
+ ;// M_BD_INIT1 and M_BD_INIT2
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_INIT0 $ppBitStream, $pBitOffset, $RBitStream, $RBitBuffer, $RBitCount
+
+pBitStream SETS "$RBitStream"
+BitBuffer SETS "$RBitBuffer"
+BitCount SETS "$RBitCount"
+
+ ;// load inputs
+ LDR $pBitStream, [$ppBitStream]
+ LDR $BitCount, [$pBitOffset]
+ MEND
+
+ MACRO
+ M_BD_INIT1 $T1, $T2, $T3
+ LDRB $T2, [$pBitStream, #2]
+ LDRB $T1, [$pBitStream, #1]
+ LDRB $BitBuffer, [$pBitStream], #3
+ ADD $BitCount, $BitCount, #8
+ MEND
+
+ MACRO
+ M_BD_INIT2 $T1, $T2, $T3
+ ORR $T2, $T2, $T1, LSL #8
+ ORR $BitBuffer, $T2, $BitBuffer, LSL #16
+ MEND
+
+ ;//
+ ;// Look ahead fixed 1<=N<=8 bits without consuming any bits
+ ;// The next bits will be placed at bit 31..24 of destination register
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits to look
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the next N bits of the bitstream
+ ;// $T1 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_LOOK8 $Symbol, $N
+ ASSERT ($N>=1):LAND:($N<=8)
+ MOV $Symbol, $BitBuffer, LSL $BitCount
+ MEND
+
+ ;//
+ ;// Look ahead fixed 1<=N<=16 bits without consuming any bits
+ ;// The next bits will be placed at bit 31..16 of destination register
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits to look
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the next N bits of the bitstream
+ ;// $T1 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_LOOK16 $Symbol, $N, $T1
+ ASSERT ($N >= 1):LAND:($N <= 16)
+ MOV $Symbol, $BitBuffer, LSL $BitCount
+ MEND
+
+ ;//
+ ;// Skips fixed 1<=N<=8 bits from the bitstream, advancing the bitstream pointer
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $T1 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_SKIP8 $N, $T1
+ ASSERT ($N>=1):LAND:($N<=8)
+ SUBS $BitCount, $BitCount, #(8-$N)
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+
+ ;//
+ ;// Read fixed 1<=N<=8 bits from the bitstream, advancing the bitstream pointer
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits to read
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the next N bits of the bitstream
+ ;// $T1 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_READ8 $Symbol, $N, $T1
+ ASSERT ($N>=1):LAND:($N<=8)
+ MOVS $Symbol, $BitBuffer, LSL $BitCount
+ SUBS $BitCount, $BitCount, #(8-$N)
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ MOV $Symbol, $Symbol, LSR #(32-$N)
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+ ;//
+ ;// Read fixed 1<=N<=16 bits from the bitstream, advancing the bitstream pointer
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits to read
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the next N bits of the bitstream
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_READ16 $Symbol, $N, $T1, $T2
+ ASSERT ($N>=1):LAND:($N<=16)
+ ASSERT $Symbol<>$T1
+ IF ($N<=8)
+ M_BD_READ8 $Symbol, $N, $T1
+ ELSE
+ ;// N>8 so we will be able to refill at least one byte
+ LDRB $T1, [$pBitStream], #1
+ MOVS $Symbol, $BitBuffer, LSL $BitCount
+ ORR $BitBuffer, $T1, $BitBuffer, LSL #8
+ SUBS $BitCount, $BitCount, #(16-$N)
+ LDRCSB $T1, [$pBitStream], #1
+ MOV $Symbol, $Symbol, LSR #(32-$N)
+ ADDCC $BitCount, $BitCount, #8
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ ENDIF
+ MEND
+
+ ;//
+ ;// Skip variable 1<=N<=8 bits from the bitstream, advancing the bitstream pointer.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits. 1<=N<=8
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_VSKIP8 $N, $T1
+ ADD $BitCount, $BitCount, $N
+ SUBS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+ ;//
+ ;// Skip variable 1<=N<=16 bits from the bitstream, advancing the bitstream pointer.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits. 1<=N<=16
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_VSKIP16 $N, $T1, $T2
+ ADD $BitCount, $BitCount, $N
+ SUBS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ SUBCSS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+ ;//
+ ;// Read variable 1<=N<=8 bits from the bitstream, advancing the bitstream pointer.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits to read. 1<=N<=8
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the next N bits of the bitstream
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_VREAD8 $Symbol, $N, $T1, $T2
+ MOV $Symbol, $BitBuffer, LSL $BitCount
+ ADD $BitCount, $BitCount, $N
+ SUBS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ RSB $T2, $N, #32
+ ADDCC $BitCount, $BitCount, #8
+ MOV $Symbol, $Symbol, LSR $T2
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+
+ ;//
+ ;// Read variable 1<=N<=16 bits from the bitstream, advancing the bitstream pointer.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits to read. 1<=N<=16
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the next N bits of the bitstream
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_VREAD16 $Symbol, $N, $T1, $T2
+ MOV $Symbol, $BitBuffer, LSL $BitCount
+ ADD $BitCount, $BitCount, $N
+ SUBS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ RSB $T2, $N, #32
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ SUBCSS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ MOV $Symbol, $Symbol, LSR $T2
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+
+ ;//
+ ;// Decode a code of the form 0000...001 where there
+ ;// are N zeros before the 1 and N<=15 (code length<=16)
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the number of zeros before the next 1
+ ;// >=16 is an illegal code
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_CLZ16 $Symbol, $T1, $T2
+ MOVS $Symbol, $BitBuffer, LSL $BitCount
+ CLZ $Symbol, $Symbol
+ ADD $BitCount, $BitCount, $Symbol
+ SUBS $BitCount, $BitCount, #7 ;// length is Symbol+1
+ LDRCSB $T1, [$pBitStream], #1
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ SUBCSS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+ ;//
+ ;// Decode a code of the form 1111...110 where there
+ ;// are N ones before the 0 and N<=15 (code length<=16)
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the number of zeros before the next 1
+ ;// >=16 is an illegal code
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_CLO16 $Symbol, $T1, $T2
+ MOV $Symbol, $BitBuffer, LSL $BitCount
+ MVN $Symbol, $Symbol
+ CLZ $Symbol, $Symbol
+ ADD $BitCount, $BitCount, $Symbol
+ SUBS $BitCount, $BitCount, #7 ;// length is Symbol+1
+ LDRCSB $T1, [$pBitStream], #1
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ SUBCSS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+
+ ;//
+ ;// Variable Length Decode module
+ ;//
+ ;// Decodes one VLD Symbol from a bitstream and refill the bitstream
+ ;// buffer.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $pVLDTable - pointer to VLD decode table of 16-bit entries.
+ ;// The format is described above at the start of
+ ;// this file.
+ ;// $S0 - The number of bits to look up for the first step
+ ;// 1<=$S0<=8
+ ;// $S1 - The number of bits to look up for each subsequent
+ ;// step 1<=$S1<=$S0.
+ ;//
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - decoded VLD symbol value
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_VLD $Symbol, $T1, $T2, $pVLDTable, $S0, $S1
+ ASSERT (1<=$S0):LAND:($S0<=8)
+ ASSERT (1<=$S1):LAND:($S1<=$S0)
+
+ ;// Note 0<=BitCount<=15 on entry and exit
+
+ MOVS $T1, $BitBuffer, LSL $BitCount ;// left align next bits
+ MOVS $Symbol, #(2<<$S0)-2 ;// create mask
+ AND $Symbol, $Symbol, $T1, LSR #(31-$S0) ;// 2*(next $S0 bits)
+ SUBS $BitCount, $BitCount, #8 ;// CS if buffer can be filled
+01
+ LDRCSB $T1, [$pBitStream], #1 ;// load refill byte
+ LDRH $Symbol, [$pVLDTable, $Symbol] ;// load table entry
+ ADDCC $BitCount, $BitCount, #8 ;// refill not possible
+ ADD $BitCount, $BitCount, #$S0 ;// assume $S0 bits used
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8 ;// merge in refill byte
+ MOVS $T1, $Symbol, LSR #1 ;// CS=leaf entry
+ BCS %FT02
+
+ MOVS $T1, $BitBuffer, LSL $BitCount ;// left align next bit
+ IF (2*$S0-$S1<=8)
+ ;// Can combine refill check and -S0+S1 and keep $BitCount<=15
+ SUBS $BitCount, $BitCount, #8+($S0-$S1)
+ ELSE
+ ;// Separate refill check and -S0+S1 offset
+ SUBS $BitCount, $BitCount, #8
+ SUB $BitCount, $BitCount, #($S0-$S1)
+ ENDIF
+ ADD $Symbol, $Symbol, $T1, LSR #(31-$S1) ;// add 2*(next $S1 bits) to
+ BIC $Symbol, $Symbol, #1 ;// table offset
+ B %BT01 ;// load next table entry
+02
+ ;// BitCount range now depend on the route here
+ ;// if (first step) S0 <= BitCount <= 7+S0 <=15
+ ;// else if (2*S0-S1<=8) S0 <= BitCount <= 7+(2*S0-S1) <=15
+ ;// else S1 <= BitCount <= 7+S1 <=15
+
+ SUB $BitCount, $BitCount, $Symbol, LSR#13
+ BIC $Symbol, $T1, #0xF000
+ MEND
+
+
+ ;// Add an offset number of bits
+ ;//
+ ;// Outputs destination byte and bit index values which corresponds to an offset number of bits
+ ;// from the current location. This is used to compare bitstream positions using. M_BD_CMP.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $Offset - Offset to be added in bits.
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $ByteIndex - Destination pBitStream pointer after adding the Offset.
+ ;// This value will be 4 byte ahead and needs to subtract by 4 to get exact
+ ;// pointer (as in M_BD_FINI). But for using with M_BD_CMP subtract is not needed.
+ ;// $BitIndex - Destination BitCount after the addition of Offset number of bits
+ ;//
+ MACRO
+ M_BD_ADD $ByteIndex, $BitIndex, $Offset
+
+ ;// ($ByteIndex,$BitIndex) = Current position + $Offset bits
+ ADD $Offset, $Offset, $BitCount
+ AND $BitIndex, $Offset, #7
+ ADD $ByteIndex, $pBitStream, $Offset, ASR #3
+ MEND
+
+ ;// Move bitstream pointers to the location given
+ ;//
+ ;// Outputs destination byte and bit index values which corresponds to
+ ;// the current location given (calculated using M_BD_ADD).
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;// $ByteIndex - Destination pBitStream pointer after move.
+ ;// This value will be 4 byte ahead and needs to subtract by 4 to get exact
+ ;// pointer (as in M_BD_FINI).
+ ;// $BitIndex - Destination BitCount after the move
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $pBitStream \
+ ;// } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_MOV $ByteIndex, $BitIndex
+
+ ;// ($pBitStream, $Offset) = ($ByteIndex,$BitIndex)
+ MOV $BitCount, $BitIndex
+ MOV $pBitStream, $ByteIndex
+ MEND
+
+ ;// Bitstream Compare
+ ;//
+ ;// Compares bitstream position with that of a destination position. Destination position
+ ;// is held in two input registers which are calculated using M_BD_ADD macro
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $ByteIndex - Destination pBitStream pointer, (4 byte ahead as described in M_BD_ADD)
+ ;// $BitIndex - Destination BitCount
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// FLAGS - GE if destination is reached, LT = is destination is ahead
+ ;// $T1 - corrupted temp/scratch register
+ ;//
+ MACRO
+ M_BD_CMP $ByteIndex, $BitIndex, $T1
+
+ ;// Return flags set by (current positon)-($ByteIndex,$BitIndex)
+ ;// so GE means that we have reached the indicated position
+
+ ADD $T1, $pBitStream, $BitCount, LSR #3
+ CMP $T1, $ByteIndex
+ AND $T1, $BitCount, #7
+ CMPEQ $T1, $BitIndex
+ MEND
+
+
+ ;// Bitstream Decode finalise
+ ;//
+ ;// Writes back the bitstream state to the bitstream pointers
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $ppBitStream - pointer to pointer to the next bitstream byte
+ ;// $pBitOffset - pointer to the number of bits used in the current byte (0..7)
+ ;// $pBitStream \
+ ;// $BitBuffer } these register are corrupted
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_FINI $ppBitStream, $pBitOffset
+
+ ;// Advance pointer by the number of free bits in the buffer
+ ADD $pBitStream, $pBitStream, $BitCount, LSR#3
+ AND $BitCount, $BitCount, #7
+
+ ;// Now move back 32 bits to reach the first usued bit
+ SUB $pBitStream, $pBitStream, #4
+
+ ;// Store out bitstream state
+ STR $BitCount, [$pBitOffset]
+ STR $pBitStream, [$ppBitStream]
+ MEND
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_Bitstream.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_Bitstream.h
new file mode 100644
index 0000000..4f9bc3b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_Bitstream.h
@@ -0,0 +1,212 @@
+/**
+ *
+ * File Name: armCOMM_Bitstream.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armCOMM_Bitstream.h
+ * Brief: Declares common API's/Data types used across the OpenMax Encoders/Decoders.
+ *
+ */
+
+#ifndef _armCodec_H_
+#define _armCodec_H_
+
+#include "omxtypes.h"
+
+typedef struct {
+ OMX_U8 codeLen;
+ OMX_U32 codeWord;
+} ARM_VLC32;
+
+/* The above should be renamed as "ARM_VLC32" */
+
+/**
+ * Function: armLookAheadBits()
+ *
+ * Description:
+ * Get the next N bits from the bitstream without advancing the bitstream pointer
+ *
+ * Parameters:
+ * [in] **ppBitStream
+ * [in] *pOffset
+ * [in] N=1...32
+ *
+ * Returns Value
+ */
+
+OMX_U32 armLookAheadBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N);
+
+/**
+ * Function: armGetBits()
+ *
+ * Description:
+ * Read N bits from the bitstream
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ * [in] N=1..32
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ * Returns Value
+ */
+
+OMX_U32 armGetBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N);
+
+/**
+ * Function: armByteAlign()
+ *
+ * Description:
+ * Align the pointer *ppBitStream to the next byte boundary
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ *
+ **/
+
+OMXVoid armByteAlign(const OMX_U8 **ppBitStream,OMX_INT *pOffset);
+
+/**
+ * Function: armSkipBits()
+ *
+ * Description:
+ * Skip N bits from the value at *ppBitStream
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ * [in] N
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ *
+ **/
+
+OMXVoid armSkipBits(const OMX_U8 **ppBitStream,OMX_INT *pOffset,OMX_INT N);
+
+/***************************************
+ * Variable bit length Decode
+ ***************************************/
+
+/**
+ * Function: armUnPackVLC32()
+ *
+ * Description:
+ * Variable length decode of variable length symbol (max size 32 bits) read from
+ * the bit stream pointed by *ppBitStream at *pOffset by using the table
+ * pointed by pCodeBook
+ *
+ * Parameters:
+ * [in] **ppBitStream
+ * [in] *pOffset
+ * [in] pCodeBook
+ *
+ * [out] **ppBitStream
+ * [out] *pOffset
+ *
+ * Returns : Code Book Index if successfull.
+ * : "ARM_NO_CODEBOOK_INDEX = 0xFFFF" if search fails.
+ **/
+
+#define ARM_NO_CODEBOOK_INDEX (OMX_U16)(0xFFFF)
+
+OMX_U16 armUnPackVLC32(
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pOffset,
+ const ARM_VLC32 *pCodeBook
+);
+
+/***************************************
+ * Fixed bit length Encode
+ ***************************************/
+
+/**
+ * Function: armPackBits
+ *
+ * Description:
+ * Pack a VLC code word into the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte
+ * in the bit stream.
+ * [in] pOffset pointer to the bit position in the byte
+ * pointed by *ppBitStream. Valid within 0
+ * to 7.
+ * [in] codeWord Code word that need to be inserted in to the
+ * bitstream
+ * [in] codeLength Length of the code word valid range 1...32
+ *
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMX_RESULT result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armPackBits (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pOffset,
+ OMX_U32 codeWord,
+ OMX_INT codeLength
+);
+
+/***************************************
+ * Variable bit length Encode
+ ***************************************/
+
+/**
+ * Function: armPackVLC32
+ *
+ * Description:
+ * Pack a VLC code word into the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte
+ * in the bit stream.
+ * [in] pBitOffset pointer to the bit position in the byte
+ * pointed by *ppBitStream. Valid within 0
+ * to 7.
+ * [in] code VLC code word that need to be inserted in to the
+ * bitstream
+ *
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMX_RESULT result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armPackVLC32 (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ ARM_VLC32 code
+);
+
+#endif /*_armCodec_H_*/
+
+/*End of File*/
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCTTable.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCTTable.h
new file mode 100644
index 0000000..d5db32f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCTTable.h
@@ -0,0 +1,40 @@
+/**
+ *
+ *
+ * File Name: armCOMM_IDCTTable.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File : armCOMM_IDCTTable.h
+ * Description : Contains declarations of tables for IDCT calculation.
+ *
+ */
+
+#ifndef _armCOMM_IDCTTable_H_
+#define _armCOMM_IDCTTable_H_
+
+#include "omxtypes.h"
+
+ /* Table of s(u)*A(u)*A(v)/16 at Q15
+ * s(u)=1.0 0 <= u <= 5
+ * s(6)=2.0
+ * s(7)=4.0
+ * A(0) = 2*sqrt(2)
+ * A(u) = 4*cos(u*pi/16) for (u!=0)
+ */
+extern const OMX_U16 armCOMM_IDCTPreScale [64];
+extern const OMX_U16 armCOMM_IDCTCoef [4];
+
+#endif /* _armCOMM_IDCTTable_H_ */
+
+
+/* End of File */
+
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCT_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCT_s.h
new file mode 100644
index 0000000..03f7137
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_IDCT_s.h
@@ -0,0 +1,1445 @@
+;//
+;// This confidential and proprietary software may be used only as
+;// authorised by a licensing agreement from ARM Limited
+;// (C) COPYRIGHT 2004 ARM Limited
+;// ALL RIGHTS RESERVED
+;// The entire notice above must be reproduced on all authorised
+;// copies and copies may only be made to the extent permitted
+;// by a licensing agreement from ARM Limited.
+;//
+;// IDCT_s.s
+;//
+;// Inverse DCT module
+;//
+;//
+;// ALGORITHM DESCRIPTION
+;//
+;// The 8x8 2D IDCT is performed by calculating a 1D IDCT for each
+;// column and then a 1D IDCT for each row.
+;//
+;// The 8-point 1D IDCT is defined by
+;// f(x) = (C(0)*T(0)*c(0,x) + ... + C(7)*T(7)*c(7,x))/2
+;//
+;// C(u) = 1/sqrt(2) if u=0 or 1 if u!=0
+;// c(u,x) = cos( (2x+1)*u*pi/16 )
+;//
+;// We compute the 8-point 1D IDCT using the reverse of
+;// the Arai-Agui-Nakajima flow graph which we split into
+;// 5 stages named in reverse order to identify with the
+;// forward DCT. Direct inversion of the forward formulae
+;// in file FDCT_s.s gives:
+;//
+;// IStage 5: j(u) = T(u)*A(u) [ A(u)=4*C(u)*c(u,0) ]
+;// [ A(0) = 2*sqrt(2)
+;// A(u) = 4*cos(u*pi/16) for (u!=0) ]
+;//
+;// IStage 4: i0 = j0 i1 = j4
+;// i3 = (j2+j6)/2 i2 = (j2-j6)/2
+;// i7 = (j5+j3)/2 i4 = (j5-j3)/2
+;// i5 = (j1+j7)/2 i6 = (j1-j7)/2
+;//
+;// IStage 3: h0 = (i0+i1)/2 h1 = (i0-i1)/2
+;// h2 = (i2*sqrt2)-i3 h3 = i3
+;// h4 = cos(pi/8)*i4 + sin(pi/8)*i6
+;// h6 = -sin(pi/8)*i4 + cos(pi/8)*i6
+;// [ The above two lines rotate by -(pi/8) ]
+;// h5 = (i5-i7)/sqrt2 h7 = (i5+i7)/2
+;//
+;// IStage 2: g0 = (h0+h3)/2 g3 = (h0-h3)/2
+;// g1 = (h1+h2)/2 g2 = (h1-h2)/2
+;// g7 = h7 g6 = h6 - h7
+;// g5 = h5 - g6 g4 = h4 - g5
+;//
+;// IStage 1: f0 = (g0+g7)/2 f7 = (g0-g7)/2
+;// f1 = (g1+g6)/2 f6 = (g1-g6)/2
+;// f2 = (g2+g5)/2 f5 = (g2-g5)/2
+;// f3 = (g3+g4)/2 f4 = (g3-g4)/2
+;//
+;// Note that most coefficients are halved 3 times during the
+;// above calculation. We can rescale the algorithm dividing
+;// the input by 8 to remove the halvings.
+;//
+;// IStage 5: j(u) = T(u)*A(u)/8
+;//
+;// IStage 4: i0 = j0 i1 = j4
+;// i3 = j2 + j6 i2 = j2 - j6
+;// i7 = j5 + j3 i4 = j5 - j3
+;// i5 = j1 + j7 i6 = j1 - j7
+;//
+;// IStage 3: h0 = i0 + i1 h1 = i0 - i1
+;// h2 = (i2*sqrt2)-i3 h3 = i3
+;// h4 = 2*( cos(pi/8)*i4 + sin(pi/8)*i6)
+;// h6 = 2*(-sin(pi/8)*i4 + cos(pi/8)*i6)
+;// h5 = (i5-i7)*sqrt2 h7 = i5 + i7
+;//
+;// IStage 2: g0 = h0 + h3 g3 = h0 - h3
+;// g1 = h1 + h2 g2 = h1 - h2
+;// g7 = h7 g6 = h6 - h7
+;// g5 = h5 - g6 g4 = h4 - g5
+;//
+;// IStage 1: f0 = g0 + g7 f7 = g0 - g7
+;// f1 = g1 + g6 f6 = g1 - g6
+;// f2 = g2 + g5 f5 = g2 - g5
+;// f3 = g3 + g4 f4 = g3 - g4
+;//
+;// Note:
+;// 1. The scaling by A(u)/8 can often be combined with inverse
+;// quantization. The column and row scalings can be combined.
+;// 2. The flowgraph in the AAN paper has h4,g6 negated compared
+;// to the above code but is otherwise identical.
+;// 3. The rotation by -pi/8 can be peformed using three multiplies
+;// Eg c*i4+s*i6 = (i6-i4)*s + (c+s)*i4
+;// -s*i4+c*i6 = (i6-i4)*s + (c-s)*i6
+;// 4. If |T(u)|<=1 then from the IDCT definition,
+;// |f(x)| <= ((1/sqrt2) + |c(1,x)| + .. + |c(7,x)|)/2
+;// = ((1/sqrt2) + cos(pi/16) + ... + cos(7*pi/16))/2
+;// = ((1/sqrt2) + (cot(pi/32)-1)/2)/2
+;// = (1 + cos(pi/16) + cos(2pi/16) + cos(3pi/16))/sqrt(2)
+;// = (approx)2.64
+;// So the max gain of the 2D IDCT is ~x7.0 = 3 bits.
+;// The table below shows input patterns generating the maximum
+;// value of |f(u)| for input in the range |T(x)|<=1. M=-1, P=+1
+;// InputPattern Max |f(x)|
+;// PPPPPPPP |f0| = 2.64
+;// PPPMMMMM |f1| = 2.64
+;// PPMMMPPP |f2| = 2.64
+;// PPMMPPMM |f3| = 2.64
+;// PMMPPMMP |f4| = 2.64
+;// PMMPMMPM |f5| = 2.64
+;// PMPPMPMP |f6| = 2.64
+;// PMPMPMPM |f7| = 2.64
+;// Note that this input pattern is the transpose of the
+;// corresponding max input patter for the FDCT.
+
+;// Arguments
+
+pSrc RN 0 ;// source data buffer
+Stride RN 1 ;// destination stride in bytes
+pDest RN 2 ;// destination data buffer
+pScale RN 3 ;// pointer to scaling table
+
+
+ ;// DCT Inverse Macro
+ ;// The DCT code should be parametrized according
+ ;// to the following inputs:
+ ;// $outsize = "u8" : 8-bit unsigned data saturated (0 to +255)
+ ;// "s9" : 16-bit signed data saturated to 9-bit (-256 to +255)
+ ;// "s16" : 16-bit signed data not saturated (max size ~+/-14273)
+ ;// $inscale = "s16" : signed 16-bit aan-scale table, Q15 format, with 4 byte alignment
+ ;// "s32" : signed 32-bit aan-scale table, Q23 format, with 4 byte alignment
+ ;//
+ ;// Inputs:
+ ;// pSrc = r0 = Pointer to input data
+ ;// Range is -256 to +255 (9-bit)
+ ;// Stride = r1 = Stride between input lines
+ ;// pDest = r2 = Pointer to output data
+ ;// pScale = r3 = Pointer to aan-scale table in the format defined by $inscale
+
+
+
+ MACRO
+ M_IDCT $outsize, $inscale, $stride
+ LCLA SHIFT
+
+
+ IF ARM1136JS
+
+;// REGISTER ALLOCATION
+;// This is hard since we have 8 values, 9 free registers and each
+;// butterfly requires a temporary register. We also want to
+;// maintain register order so we can use LDM/STM. The table below
+;// summarises the register allocation that meets all these criteria.
+;// a=1stcol, b=2ndcol, f,g,h,i are dataflow points described above.
+;//
+;// r1 a01 g0 h0
+;// r4 b01 f0 g1 h1 i0
+;// r5 a23 f1 g2 i1
+;// r6 b23 f2 g3 h2 i2
+;// r7 a45 f3 h3 i3
+;// r8 b45 f4 g4 h4 i4
+;// r9 a67 f5 g5 h5 i5
+;// r10 b67 f6 g6 h6 i6
+;// r11 f7 g7 h7 i7
+;//
+ra01 RN 1
+rb01 RN 4
+ra23 RN 5
+rb23 RN 6
+ra45 RN 7
+rb45 RN 8
+ra67 RN 9
+rb67 RN 10
+rtmp RN 11
+csPiBy8 RN 12 ;// [ (Sin(pi/8)@Q15), (Cos(pi/8)@Q15) ]
+LoopRR2 RN 14 ;// [ LoopNumber<<13 , (1/Sqrt(2))@Q15 ]
+;// Transpose allocation
+xft RN ra01
+xf0 RN rb01
+xf1 RN ra23
+xf2 RN rb23
+xf3 RN ra45
+xf4 RN rb45
+xf5 RN ra67
+xf6 RN rb67
+xf7 RN rtmp
+;// IStage 1 allocation
+xg0 RN xft
+xg1 RN xf0
+xg2 RN xf1
+xg3 RN xf2
+xgt RN xf3
+xg4 RN xf4
+xg5 RN xf5
+xg6 RN xf6
+xg7 RN xf7
+;// IStage 2 allocation
+xh0 RN xg0
+xh1 RN xg1
+xht RN xg2
+xh2 RN xg3
+xh3 RN xgt
+xh4 RN xg4
+xh5 RN xg5
+xh6 RN xg6
+xh7 RN xg7
+;// IStage 3,4 allocation
+xit RN xh0
+xi0 RN xh1
+xi1 RN xht
+xi2 RN xh2
+xi3 RN xh3
+xi4 RN xh4
+xi5 RN xh5
+xi6 RN xh6
+xi7 RN xh7
+
+ M_STR pDest, ppDest
+ IF "$stride"="s"
+ M_STR Stride, pStride
+ ENDIF
+ M_ADR pDest, pBlk
+ LDR csPiBy8, =0x30fc7642
+ LDR LoopRR2, =0x00005a82
+
+v6_idct_col$_F
+ ;// Load even values
+ LDR xi4, [pSrc], #4 ;// j0
+ LDR xi5, [pSrc, #4*16-4] ;// j4
+ LDR xi6, [pSrc, #2*16-4] ;// j2
+ LDR xi7, [pSrc, #6*16-4] ;// j6
+
+ ;// Scale Even Values
+ IF "$inscale"="s16" ;// 16x16 mul
+SHIFT SETA 12
+ LDR xi0, [pScale], #4
+ LDR xi1, [pScale, #4*16-4]
+ LDR xi2, [pScale, #2*16-4]
+ MOV xit, #1<<(SHIFT-1)
+ SMLABB xi3, xi0, xi4, xit
+ SMLATT xi4, xi0, xi4, xit
+ SMLABB xi0, xi1, xi5, xit
+ SMLATT xi5, xi1, xi5, xit
+ MOV xi3, xi3, ASR #SHIFT
+ PKHBT xi4, xi3, xi4, LSL #(16-SHIFT)
+ LDR xi3, [pScale, #6*16-4]
+ SMLABB xi1, xi2, xi6, xit
+ SMLATT xi6, xi2, xi6, xit
+ MOV xi0, xi0, ASR #SHIFT
+ PKHBT xi5, xi0, xi5, LSL #(16-SHIFT)
+ SMLABB xi2, xi3, xi7, xit
+ SMLATT xi7, xi3, xi7, xit
+ MOV xi1, xi1, ASR #SHIFT
+ PKHBT xi6, xi1, xi6, LSL #(16-SHIFT)
+ MOV xi2, xi2, ASR #SHIFT
+ PKHBT xi7, xi2, xi7, LSL #(16-SHIFT)
+ ENDIF
+ IF "$inscale"="s32" ;// 32x16 mul
+SHIFT SETA (12+8-16)
+ MOV xit, #1<<(SHIFT-1)
+ LDR xi0, [pScale], #8
+ LDR xi1, [pScale, #0*32+4-8]
+ LDR xi2, [pScale, #4*32-8]
+ LDR xi3, [pScale, #4*32+4-8]
+ SMLAWB xi0, xi0, xi4, xit
+ SMLAWT xi1, xi1, xi4, xit
+ SMLAWB xi2, xi2, xi5, xit
+ SMLAWT xi3, xi3, xi5, xit
+ MOV xi0, xi0, ASR #SHIFT
+ PKHBT xi4, xi0, xi1, LSL #(16-SHIFT)
+ MOV xi2, xi2, ASR #SHIFT
+ PKHBT xi5, xi2, xi3, LSL #(16-SHIFT)
+ LDR xi0, [pScale, #2*32-8]
+ LDR xi1, [pScale, #2*32+4-8]
+ LDR xi2, [pScale, #6*32-8]
+ LDR xi3, [pScale, #6*32+4-8]
+ SMLAWB xi0, xi0, xi6, xit
+ SMLAWT xi1, xi1, xi6, xit
+ SMLAWB xi2, xi2, xi7, xit
+ SMLAWT xi3, xi3, xi7, xit
+ MOV xi0, xi0, ASR #SHIFT
+ PKHBT xi6, xi0, xi1, LSL #(16-SHIFT)
+ MOV xi2, xi2, ASR #SHIFT
+ PKHBT xi7, xi2, xi3, LSL #(16-SHIFT)
+ ENDIF
+
+ ;// Load odd values
+ LDR xi0, [pSrc, #1*16-4] ;// j1
+ LDR xi1, [pSrc, #7*16-4] ;// j7
+ LDR xi2, [pSrc, #5*16-4] ;// j5
+ LDR xi3, [pSrc, #3*16-4] ;// j3
+
+ IF {TRUE}
+ ;// shortcut if odd values 0
+ TEQ xi0, #0
+ TEQEQ xi1, #0
+ TEQEQ xi2, #0
+ TEQEQ xi3, #0
+ BEQ v6OddZero$_F
+ ENDIF
+
+ ;// Store scaled even values
+ STMIA pDest, {xi4, xi5, xi6, xi7}
+
+ ;// Scale odd values
+ IF "$inscale"="s16"
+ ;// Perform AAN Scale
+ LDR xi4, [pScale, #1*16-4]
+ LDR xi5, [pScale, #7*16-4]
+ LDR xi6, [pScale, #5*16-4]
+ SMLABB xi7, xi0, xi4, xit
+ SMLATT xi0, xi0, xi4, xit
+ SMLABB xi4, xi1, xi5, xit
+ SMLATT xi1, xi1, xi5, xit
+ MOV xi7, xi7, ASR #SHIFT
+ PKHBT xi0, xi7, xi0, LSL #(16-SHIFT)
+ LDR xi7, [pScale, #3*16-4]
+ SMLABB xi5, xi2, xi6, xit
+ SMLATT xi2, xi2, xi6, xit
+ MOV xi4, xi4, ASR #SHIFT
+ PKHBT xi1, xi4, xi1, LSL #(16-SHIFT)
+ SMLABB xi6, xi3, xi7, xit
+ SMLATT xi3, xi3, xi7, xit
+ MOV xi5, xi5, ASR #SHIFT
+ PKHBT xi2, xi5, xi2, LSL #(16-SHIFT)
+ MOV xi6, xi6, ASR #SHIFT
+ PKHBT xi3, xi6, xi3, LSL #(16-SHIFT)
+ ENDIF
+ IF "$inscale"="s32" ;// 32x16 mul
+ LDR xi4, [pScale, #1*32-8]
+ LDR xi5, [pScale, #1*32+4-8]
+ LDR xi6, [pScale, #7*32-8]
+ LDR xi7, [pScale, #7*32+4-8]
+ SMLAWB xi4, xi4, xi0, xit
+ SMLAWT xi5, xi5, xi0, xit
+ SMLAWB xi6, xi6, xi1, xit
+ SMLAWT xi7, xi7, xi1, xit
+ MOV xi4, xi4, ASR #SHIFT
+ PKHBT xi0, xi4, xi5, LSL #(16-SHIFT)
+ MOV xi6, xi6, ASR #SHIFT
+ PKHBT xi1, xi6, xi7, LSL #(16-SHIFT)
+ LDR xi4, [pScale, #5*32-8]
+ LDR xi5, [pScale, #5*32+4-8]
+ LDR xi6, [pScale, #3*32-8]
+ LDR xi7, [pScale, #3*32+4-8]
+ SMLAWB xi4, xi4, xi2, xit
+ SMLAWT xi5, xi5, xi2, xit
+ SMLAWB xi6, xi6, xi3, xit
+ SMLAWT xi7, xi7, xi3, xit
+ MOV xi4, xi4, ASR #SHIFT
+ PKHBT xi2, xi4, xi5, LSL #(16-SHIFT)
+ MOV xi6, xi6, ASR #SHIFT
+ PKHBT xi3, xi6, xi7, LSL #(16-SHIFT)
+ ENDIF
+
+ SHADD16 xi5, xi0, xi1 ;// (j1+j7)/2
+ SSUB16 xi6, xi0, xi1 ;// j1-j7
+ SHADD16 xi7, xi2, xi3 ;// (j5+j3)/2
+ SSUB16 xi4, xi2, xi3 ;// j5-j3
+
+ SSUB16 xi3, xi5, xi7 ;// (i5-i7)/2
+
+ PKHBT xi0, xi6, xi4, LSL#16 ;// [i4,i6] row a
+ PKHTB xi1, xi4, xi6, ASR#16 ;// [i4,i6] row b
+
+ SMUADX xi2, xi0, csPiBy8 ;// rowa by [c,s]
+ SMUADX xi4, xi1, csPiBy8 ;// rowb by [c,s]
+ SMUSD xi0, xi0, csPiBy8 ;// rowa by [-s,c]
+ SMUSD xi6, xi1, csPiBy8 ;// rowb by [-s,c]
+
+ SMULBB xi1, xi3, LoopRR2
+ SMULTB xi3, xi3, LoopRR2
+
+ PKHTB xh4, xi4, xi2, ASR#16 ;// h4/4
+ PKHTB xh6, xi6, xi0, ASR#16 ;// h6/4
+ SHADD16 xh7, xi5, xi7 ;// (i5+i7)/4
+
+ ;// xi0,xi1,xi2,xi3 now free
+ ;// IStage 4,3, rows 2to3 x1/2
+
+ MOV xi3, xi3, LSL #1
+ PKHTB xh5, xi3, xi1, ASR#15 ;// h5/4
+ LDRD xi0, [pDest, #8] ;// j2,j6 scaled
+
+ ;// IStage 2, rows4to7
+ SSUB16 xg6, xh6, xh7
+ SSUB16 xg5, xh5, xg6
+ SSUB16 xg4, xh4, xg5
+
+ SSUB16 xi2, xi0, xi1 ;// (j2-j6)
+ SHADD16 xi3, xi0, xi1 ;// (j2+j6)/2
+
+ SMULBB xi0, xi2, LoopRR2
+ SMULTB xi2, xi2, LoopRR2
+
+ MOV xi2, xi2, LSL #1
+ PKHTB xh2, xi2, xi0, ASR#15 ;// i2*sqrt(2)/4
+
+ ;// xi0, xi1 now free
+ ;// IStage 4,3 rows 0to1 x 1/2
+ LDRD xi0, [pDest] ;// j0, j4 scaled
+ SSUB16 xh2, xh2, xi3
+ ADDS LoopRR2, LoopRR2, #2<<29 ;// done two rows
+
+ SHADD16 xh0, xi0, xi1
+ SHSUB16 xh1, xi0, xi1
+
+ ;// IStage 2 rows 0to3 x 1/2
+ SHSUB16 xg2, xh1, xh2
+ SHADD16 xg1, xh1, xh2
+ SHSUB16 xg3, xh0, xh3
+ SHADD16 xg0, xh0, xh3
+
+ ;// IStage 1 all rows
+ SADD16 xf3, xg3, xg4
+ SSUB16 xf4, xg3, xg4
+ SADD16 xf2, xg2, xg5
+ SSUB16 xf5, xg2, xg5
+ SADD16 xf1, xg1, xg6
+ SSUB16 xf6, xg1, xg6
+ SADD16 xf0, xg0, xg7
+ SSUB16 xf7, xg0, xg7
+
+ ;// Transpose, store and loop
+ PKHBT ra01, xf0, xf1, LSL #16
+ PKHTB rb01, xf1, xf0, ASR #16
+
+ PKHBT ra23, xf2, xf3, LSL #16
+ PKHTB rb23, xf3, xf2, ASR #16
+
+ PKHBT ra45, xf4, xf5, LSL #16
+ PKHTB rb45, xf5, xf4, ASR #16
+
+ PKHBT ra67, xf6, xf7, LSL #16
+ STMIA pDest!, {ra01, ra23, ra45, ra67}
+ PKHTB rb67, xf7, xf6, ASR #16
+ STMIA pDest!, {rb01, rb23, rb45, rb67}
+ BCC v6_idct_col$_F
+
+ SUB pSrc, pDest, #(64*2)
+ M_LDR pDest, ppDest
+ IF "$stride"="s"
+ M_LDR pScale, pStride
+ ENDIF
+ B v6_idct_row$_F
+
+v6OddZero$_F
+ SSUB16 xi2, xi6, xi7 ;// (j2-j6)
+ SHADD16 xi3, xi6, xi7 ;// (j2+j6)/2
+
+ SMULBB xi0, xi2, LoopRR2
+ SMULTB xi2, xi2, LoopRR2
+
+ MOV xi2, xi2, LSL #1
+ PKHTB xh2, xi2, xi0, ASR#15 ;// i2*sqrt(2)/4
+ SSUB16 xh2, xh2, xi3
+
+ ;// xi0, xi1 now free
+ ;// IStage 4,3 rows 0to1 x 1/2
+
+ SHADD16 xh0, xi4, xi5
+ SHSUB16 xh1, xi4, xi5
+
+ ;// IStage 2 rows 0to3 x 1/2
+ SHSUB16 xg2, xh1, xh2
+ SHADD16 xg1, xh1, xh2
+ SHSUB16 xg3, xh0, xh3
+ SHADD16 xg0, xh0, xh3
+
+ ;// IStage 1 all rows
+ MOV xf3, xg3
+ MOV xf4, xg3
+ MOV xf2, xg2
+ MOV xf5, xg2
+ MOV xf1, xg1
+ MOV xf6, xg1
+ MOV xf0, xg0
+ MOV xf7, xg0
+
+ ;// Transpose
+ PKHBT ra01, xf0, xf1, LSL #16
+ PKHTB rb01, xf1, xf0, ASR #16
+
+ PKHBT ra23, xf2, xf3, LSL #16
+ PKHTB rb23, xf3, xf2, ASR #16
+
+ PKHBT ra45, xf4, xf5, LSL #16
+ PKHTB rb45, xf5, xf4, ASR #16
+
+ PKHBT ra67, xf6, xf7, LSL #16
+ PKHTB rb67, xf7, xf6, ASR #16
+
+ STMIA pDest!, {ra01, ra23, ra45, ra67}
+ ADDS LoopRR2, LoopRR2, #2<<29 ;// done two rows
+ STMIA pDest!, {rb01, rb23, rb45, rb67}
+
+ BCC v6_idct_col$_F
+ SUB pSrc, pDest, #(64*2)
+ M_LDR pDest, ppDest
+ IF "$stride"="s"
+ M_LDR pScale, pStride
+ ENDIF
+
+
+v6_idct_row$_F
+ ;// IStage 4,3, rows4to7 x1/4
+ LDR xit, =0x00010001 ;// rounding constant
+ LDR xi0, [pSrc, #1*16] ;// j1
+ LDR xi1, [pSrc, #7*16] ;// 4*j7
+ LDR xi2, [pSrc, #5*16] ;// j5
+ LDR xi3, [pSrc, #3*16] ;// j3
+
+ SHADD16 xi1, xi1, xit ;// 2*j7
+ SHADD16 xi1, xi1, xit ;// j7
+
+ SHADD16 xi5, xi0, xi1 ;// (j1+j7)/2
+ SSUB16 xi6, xi0, xi1 ;// j1-j7
+ SHADD16 xi7, xi2, xi3 ;// (j5+j3)/2
+ SSUB16 xi4, xi2, xi3 ;// j5-j3
+
+ SSUB16 xi3, xi5, xi7 ;// (i5-i7)/2
+
+ PKHBT xi0, xi6, xi4, LSL#16 ;// [i4,i6] row a
+ PKHTB xi1, xi4, xi6, ASR#16 ;// [i4,i6] row b
+
+ SMUADX xi2, xi0, csPiBy8 ;// rowa by [c,s]
+ SMUADX xi4, xi1, csPiBy8 ;// rowb by [c,s]
+ SMUSD xi0, xi0, csPiBy8 ;// rowa by [-s,c]
+ SMUSD xi6, xi1, csPiBy8 ;// rowb by [-s,c]
+
+ SMULBB xi1, xi3, LoopRR2
+ SMULTB xi3, xi3, LoopRR2
+
+ PKHTB xh4, xi4, xi2, ASR#16 ;// h4/4
+ PKHTB xh6, xi6, xi0, ASR#16 ;// h6/4
+ SHADD16 xh7, xi5, xi7 ;// (i5+i7)/4
+
+ MOV xi3, xi3, LSL #1
+ PKHTB xh5, xi3, xi1, ASR#15 ;// h5/4
+
+ ;// xi0,xi1,xi2,xi3 now free
+ ;// IStage 4,3, rows 2to3 x1/2
+
+ LDR xi0, [pSrc, #2*16] ;// j2
+ LDR xi1, [pSrc, #6*16] ;// 2*j6
+
+ ;// IStage 2, rows4to7
+ SSUB16 xg6, xh6, xh7
+ SSUB16 xg5, xh5, xg6
+ SSUB16 xg4, xh4, xg5
+
+ SHADD16 xi1, xi1, xit ;// j6
+ SSUB16 xi2, xi0, xi1 ;// (j2-j6)
+ SHADD16 xi3, xi0, xi1 ;// (j2+j6)/2
+
+ SMULBB xi0, xi2, LoopRR2
+ SMULTB xi2, xi2, LoopRR2
+
+ MOV xi2, xi2, LSL #1
+
+ PKHTB xh2, xi2, xi0, ASR#15 ;// i2*sqrt(2)/4
+
+ ;// xi0, xi1 now free
+ ;// IStage 4,3 rows 0to1 x 1/2
+ LDR xi1, [pSrc, #4*16] ;// j4
+ LDR xi0, [pSrc], #4 ;// j0
+
+ SSUB16 xh2, xh2, xi3
+ ADDS LoopRR2, LoopRR2, #2<<29 ;// done two rows
+
+ ADD xi0, xi0, xit, LSL #2 ;// ensure correct round
+ SHADD16 xh0, xi0, xi1 ;// of DC result
+ SHSUB16 xh1, xi0, xi1
+
+ ;// IStage 2 rows 0to3 x 1/2
+ SHSUB16 xg2, xh1, xh2
+ SHADD16 xg1, xh1, xh2
+ SHSUB16 xg3, xh0, xh3
+ SHADD16 xg0, xh0, xh3
+
+ ;// IStage 1 all rows
+ SHADD16 xf3, xg3, xg4
+ SHSUB16 xf4, xg3, xg4
+ SHADD16 xf2, xg2, xg5
+ SHSUB16 xf5, xg2, xg5
+ SHADD16 xf1, xg1, xg6
+ SHSUB16 xf6, xg1, xg6
+ SHADD16 xf0, xg0, xg7
+ SHSUB16 xf7, xg0, xg7
+
+ ;// Saturate
+ IF ("$outsize"="u8")
+ USAT16 xf0, #8, xf0
+ USAT16 xf1, #8, xf1
+ USAT16 xf2, #8, xf2
+ USAT16 xf3, #8, xf3
+ USAT16 xf4, #8, xf4
+ USAT16 xf5, #8, xf5
+ USAT16 xf6, #8, xf6
+ USAT16 xf7, #8, xf7
+ ENDIF
+ IF ("$outsize"="s9")
+ SSAT16 xf0, #9, xf0
+ SSAT16 xf1, #9, xf1
+ SSAT16 xf2, #9, xf2
+ SSAT16 xf3, #9, xf3
+ SSAT16 xf4, #9, xf4
+ SSAT16 xf5, #9, xf5
+ SSAT16 xf6, #9, xf6
+ SSAT16 xf7, #9, xf7
+ ENDIF
+
+ ;// Transpose to Row, Pack and store
+ IF ("$outsize"="u8")
+ ORR xf0, xf0, xf1, LSL #8 ;// [ b1 b0 a1 a0 ]
+ ORR xf2, xf2, xf3, LSL #8 ;// [ b3 b2 a3 a2 ]
+ ORR xf4, xf4, xf5, LSL #8 ;// [ b5 b4 a5 a4 ]
+ ORR xf6, xf6, xf7, LSL #8 ;// [ b7 b6 a7 a6 ]
+ PKHBT ra01, xf0, xf2, LSL #16
+ PKHTB rb01, xf2, xf0, ASR #16
+ PKHBT ra23, xf4, xf6, LSL #16
+ PKHTB rb23, xf6, xf4, ASR #16
+ STMIA pDest, {ra01, ra23}
+ IF "$stride"="s"
+ ADD pDest, pDest, pScale
+ STMIA pDest, {rb01, rb23}
+ ADD pDest, pDest, pScale
+ ELSE
+ ADD pDest, pDest, #($stride)
+ STMIA pDest, {rb01, rb23}
+ ADD pDest, pDest, #($stride)
+ ENDIF
+ ENDIF
+ IF ("$outsize"="s9"):LOR:("$outsize"="s16")
+ PKHBT ra01, xf0, xf1, LSL #16
+ PKHTB rb01, xf1, xf0, ASR #16
+
+ PKHBT ra23, xf2, xf3, LSL #16
+ PKHTB rb23, xf3, xf2, ASR #16
+
+ PKHBT ra45, xf4, xf5, LSL #16
+ PKHTB rb45, xf5, xf4, ASR #16
+
+ PKHBT ra67, xf6, xf7, LSL #16
+ PKHTB rb67, xf7, xf6, ASR #16
+
+ STMIA pDest, {ra01, ra23, ra45, ra67}
+ IF "$stride"="s"
+ ADD pDest, pDest, pScale
+ STMIA pDest, {rb01, rb23, rb45, rb67}
+ ADD pDest, pDest, pScale
+ ELSE
+ ADD pDest, pDest, #($stride)
+ STMIA pDest, {rb01, rb23, rb45, rb67}
+ ADD pDest, pDest, #($stride)
+ ENDIF
+ ENDIF
+
+ BCC v6_idct_row$_F
+ ENDIF ;// ARM1136JS
+
+
+ IF CortexA8
+
+Src0 EQU 7
+Src1 EQU 8
+Src2 EQU 9
+Src3 EQU 10
+Src4 EQU 11
+Src5 EQU 12
+Src6 EQU 13
+Src7 EQU 14
+Tmp EQU 15
+
+qXj0 QN Src0.S16
+qXj1 QN Src1.S16
+qXj2 QN Src2.S16
+qXj3 QN Src3.S16
+qXj4 QN Src4.S16
+qXj5 QN Src5.S16
+qXj6 QN Src6.S16
+qXj7 QN Src7.S16
+qXjt QN Tmp.S16
+
+dXj0lo DN (Src0*2).S16
+dXj0hi DN (Src0*2+1).S16
+dXj1lo DN (Src1*2).S16
+dXj1hi DN (Src1*2+1).S16
+dXj2lo DN (Src2*2).S16
+dXj2hi DN (Src2*2+1).S16
+dXj3lo DN (Src3*2).S16
+dXj3hi DN (Src3*2+1).S16
+dXj4lo DN (Src4*2).S16
+dXj4hi DN (Src4*2+1).S16
+dXj5lo DN (Src5*2).S16
+dXj5hi DN (Src5*2+1).S16
+dXj6lo DN (Src6*2).S16
+dXj6hi DN (Src6*2+1).S16
+dXj7lo DN (Src7*2).S16
+dXj7hi DN (Src7*2+1).S16
+dXjtlo DN (Tmp*2).S16
+dXjthi DN (Tmp*2+1).S16
+
+qXi0 QN qXj0
+qXi1 QN qXj4
+qXi2 QN qXj2
+qXi3 QN qXj7
+qXi4 QN qXj5
+qXi5 QN qXjt
+qXi6 QN qXj1
+qXi7 QN qXj6
+qXit QN qXj3
+
+dXi0lo DN dXj0lo
+dXi0hi DN dXj0hi
+dXi1lo DN dXj4lo
+dXi1hi DN dXj4hi
+dXi2lo DN dXj2lo
+dXi2hi DN dXj2hi
+dXi3lo DN dXj7lo
+dXi3hi DN dXj7hi
+dXi4lo DN dXj5lo
+dXi4hi DN dXj5hi
+dXi5lo DN dXjtlo
+dXi5hi DN dXjthi
+dXi6lo DN dXj1lo
+dXi6hi DN dXj1hi
+dXi7lo DN dXj6lo
+dXi7hi DN dXj6hi
+dXitlo DN dXj3lo
+dXithi DN dXj3hi
+
+qXh0 QN qXit
+qXh1 QN qXi0
+qXh2 QN qXi2
+qXh3 QN qXi3
+qXh4 QN qXi7
+qXh5 QN qXi5
+qXh6 QN qXi4
+qXh7 QN qXi1
+qXht QN qXi6
+
+dXh0lo DN dXitlo
+dXh0hi DN dXithi
+dXh1lo DN dXi0lo
+dXh1hi DN dXi0hi
+dXh2lo DN dXi2lo
+dXh2hi DN dXi2hi
+dXh3lo DN dXi3lo
+dXh3hi DN dXi3hi
+dXh4lo DN dXi7lo
+dXh4hi DN dXi7hi
+dXh5lo DN dXi5lo
+dXh5hi DN dXi5hi
+dXh6lo DN dXi4lo
+dXh6hi DN dXi4hi
+dXh7lo DN dXi1lo
+dXh7hi DN dXi1hi
+dXhtlo DN dXi6lo
+dXhthi DN dXi6hi
+
+qXg0 QN qXh2
+qXg1 QN qXht
+qXg2 QN qXh1
+qXg3 QN qXh0
+qXg4 QN qXh4
+qXg5 QN qXh5
+qXg6 QN qXh6
+qXg7 QN qXh7
+qXgt QN qXh3
+
+qXf0 QN qXg6
+qXf1 QN qXg5
+qXf2 QN qXg4
+qXf3 QN qXgt
+qXf4 QN qXg3
+qXf5 QN qXg2
+qXf6 QN qXg1
+qXf7 QN qXg0
+qXft QN qXg7
+
+
+qXt0 QN 1.S32
+qXt1 QN 2.S32
+qT0lo QN 1.S32
+qT0hi QN 2.S32
+qT1lo QN 3.S32
+qT1hi QN 4.S32
+qScalelo QN 5.S32 ;// used to read post scale values
+qScalehi QN 6.S32
+qTemp0 QN 5.S32
+qTemp1 QN 6.S32
+
+
+Scale1 EQU 6
+Scale2 EQU 15
+qScale1 QN Scale1.S16
+qScale2 QN Scale2.S16
+dScale1lo DN (Scale1*2).S16
+dScale1hi DN (Scale1*2+1).S16
+dScale2lo DN (Scale2*2).S16
+dScale2hi DN (Scale2*2+1).S16
+
+dCoefs DN 0.S16 ;// Scale coefficients in format {[0] [C] [S] [InvSqrt2]}
+InvSqrt2 DN dCoefs[0] ;// 1/sqrt(2) in Q15
+S DN dCoefs[1] ;// Sin(PI/8) in Q15
+C DN dCoefs[2] ;// Cos(PI/8) in Q15
+
+pTemp RN 12
+
+
+ IMPORT armCOMM_IDCTCoef
+
+ VLD1 {qXj0,qXj1}, [pSrc @64]!
+ VLD1 {qXj2,qXj3}, [pSrc @64]!
+ VLD1 {qXj4,qXj5}, [pSrc @64]!
+ VLD1 {qXj6,qXj7}, [pSrc @64]!
+
+ ;// Load PreScale and multiply with Src
+ ;// IStage 4
+
+ IF "$inscale"="s16" ;// 16X16 Mul
+ M_IDCT_PRESCALE16
+ ENDIF
+
+ IF "$inscale"="s32" ;// 32X32 ,ul
+ M_IDCT_PRESCALE32
+ ENDIF
+
+ ;// IStage 3
+ VQRDMULH qXi2, qXi2, InvSqrt2 ;// i2/sqrt(2)
+ VHADD qXh0, qXi0, qXi1 ;// (i0+i1)/2
+ VHSUB qXh1, qXi0, qXi1 ;// (i0-i1)/2
+ VHADD qXh7, qXi5, qXi7 ;// (i5+i7)/4
+ VSUB qXh5, qXi5, qXi7 ;// (i5-i7)/2
+ VQRDMULH qXh5, qXh5, InvSqrt2 ;// h5/sqrt(2)
+ VSUB qXh2, qXi2, qXi3 ;// h2, h3
+
+ VMULL qXt0, dXi4lo, C ;// c*i4
+ VMLAL qXt0, dXi6lo, S ;// c*i4+s*i6
+ VMULL qXt1, dXi4hi, C
+ VMLAL qXt1, dXi6hi, S
+ VSHRN dXh4lo, qXt0, #16 ;// h4
+ VSHRN dXh4hi, qXt1, #16
+
+ VMULL qXt0, dXi6lo, C ;// c*i6
+ VMLSL qXt0, dXi4lo, S ;// -s*i4 + c*h6
+ VMULL qXt1, dXi6hi, C
+ VMLSL qXt1, dXi4hi, S
+ VSHRN dXh6lo, qXt0, #16 ;// h6
+ VSHRN dXh6hi, qXt1, #16
+
+ ;// IStage 2
+ VSUB qXg6, qXh6, qXh7
+ VSUB qXg5, qXh5, qXg6
+ VSUB qXg4, qXh4, qXg5
+ VHADD qXg1, qXh1, qXh2 ;// (h1+h2)/2
+ VHSUB qXg2, qXh1, qXh2 ;// (h1-h2)/2
+ VHADD qXg0, qXh0, qXh3 ;// (h0+h3)/2
+ VHSUB qXg3, qXh0, qXh3 ;// (h0-h3)/2
+
+ ;// IStage 1 all rows
+ VADD qXf3, qXg3, qXg4
+ VSUB qXf4, qXg3, qXg4
+ VADD qXf2, qXg2, qXg5
+ VSUB qXf5, qXg2, qXg5
+ VADD qXf1, qXg1, qXg6
+ VSUB qXf6, qXg1, qXg6
+ VADD qXf0, qXg0, qXg7
+ VSUB qXf7, qXg0, qXg7
+
+ ;// Transpose, store and loop
+XTR0 EQU Src5
+XTR1 EQU Tmp
+XTR2 EQU Src6
+XTR3 EQU Src7
+XTR4 EQU Src3
+XTR5 EQU Src0
+XTR6 EQU Src1
+XTR7 EQU Src2
+XTRt EQU Src4
+
+qA0 QN XTR0.S32 ;// for XTRpose
+qA1 QN XTR1.S32
+qA2 QN XTR2.S32
+qA3 QN XTR3.S32
+qA4 QN XTR4.S32
+qA5 QN XTR5.S32
+qA6 QN XTR6.S32
+qA7 QN XTR7.S32
+
+dB0 DN XTR0*2+1 ;// for using VSWP
+dB1 DN XTR1*2+1
+dB2 DN XTR2*2+1
+dB3 DN XTR3*2+1
+dB4 DN XTR4*2
+dB5 DN XTR5*2
+dB6 DN XTR6*2
+dB7 DN XTR7*2
+
+
+ VTRN qXf0, qXf1
+ VTRN qXf2, qXf3
+ VTRN qXf4, qXf5
+ VTRN qXf6, qXf7
+ VTRN qA0, qA2
+ VTRN qA1, qA3
+ VTRN qA4, qA6
+ VTRN qA5, qA7
+ VSWP dB0, dB4
+ VSWP dB1, dB5
+ VSWP dB2, dB6
+ VSWP dB3, dB7
+
+
+qYj0 QN qXf0
+qYj1 QN qXf1
+qYj2 QN qXf2
+qYj3 QN qXf3
+qYj4 QN qXf4
+qYj5 QN qXf5
+qYj6 QN qXf6
+qYj7 QN qXf7
+qYjt QN qXft
+
+dYj0lo DN (XTR0*2).S16
+dYj0hi DN (XTR0*2+1).S16
+dYj1lo DN (XTR1*2).S16
+dYj1hi DN (XTR1*2+1).S16
+dYj2lo DN (XTR2*2).S16
+dYj2hi DN (XTR2*2+1).S16
+dYj3lo DN (XTR3*2).S16
+dYj3hi DN (XTR3*2+1).S16
+dYj4lo DN (XTR4*2).S16
+dYj4hi DN (XTR4*2+1).S16
+dYj5lo DN (XTR5*2).S16
+dYj5hi DN (XTR5*2+1).S16
+dYj6lo DN (XTR6*2).S16
+dYj6hi DN (XTR6*2+1).S16
+dYj7lo DN (XTR7*2).S16
+dYj7hi DN (XTR7*2+1).S16
+dYjtlo DN (XTRt*2).S16
+dYjthi DN (XTRt*2+1).S16
+
+qYi0 QN qYj0
+qYi1 QN qYj4
+qYi2 QN qYj2
+qYi3 QN qYj7
+qYi4 QN qYj5
+qYi5 QN qYjt
+qYi6 QN qYj1
+qYi7 QN qYj6
+qYit QN qYj3
+
+dYi0lo DN dYj0lo
+dYi0hi DN dYj0hi
+dYi1lo DN dYj4lo
+dYi1hi DN dYj4hi
+dYi2lo DN dYj2lo
+dYi2hi DN dYj2hi
+dYi3lo DN dYj7lo
+dYi3hi DN dYj7hi
+dYi4lo DN dYj5lo
+dYi4hi DN dYj5hi
+dYi5lo DN dYjtlo
+dYi5hi DN dYjthi
+dYi6lo DN dYj1lo
+dYi6hi DN dYj1hi
+dYi7lo DN dYj6lo
+dYi7hi DN dYj6hi
+dYitlo DN dYj3lo
+dYithi DN dYj3hi
+
+qYh0 QN qYit
+qYh1 QN qYi0
+qYh2 QN qYi2
+qYh3 QN qYi3
+qYh4 QN qYi7
+qYh5 QN qYi5
+qYh6 QN qYi4
+qYh7 QN qYi1
+qYht QN qYi6
+
+dYh0lo DN dYitlo
+dYh0hi DN dYithi
+dYh1lo DN dYi0lo
+dYh1hi DN dYi0hi
+dYh2lo DN dYi2lo
+dYh2hi DN dYi2hi
+dYh3lo DN dYi3lo
+dYh3hi DN dYi3hi
+dYh4lo DN dYi7lo
+dYh4hi DN dYi7hi
+dYh5lo DN dYi5lo
+dYh5hi DN dYi5hi
+dYh6lo DN dYi4lo
+dYh6hi DN dYi4hi
+dYh7lo DN dYi1lo
+dYh7hi DN dYi1hi
+dYhtlo DN dYi6lo
+dYhthi DN dYi6hi
+
+qYg0 QN qYh2
+qYg1 QN qYht
+qYg2 QN qYh1
+qYg3 QN qYh0
+qYg4 QN qYh4
+qYg5 QN qYh5
+qYg6 QN qYh6
+qYg7 QN qYh7
+qYgt QN qYh3
+
+qYf0 QN qYg6
+qYf1 QN qYg5
+qYf2 QN qYg4
+qYf3 QN qYgt
+qYf4 QN qYg3
+qYf5 QN qYg2
+qYf6 QN qYg1
+qYf7 QN qYg0
+qYft QN qYg7
+
+ VRSHR qYj7, qYj7, #2
+ VRSHR qYj6, qYj6, #1
+
+ VHADD qYi5, qYj1, qYj7 ;// i5 = (j1+j7)/2
+ VSUB qYi6, qYj1, qYj7 ;// i6 = j1-j7
+ VHADD qYi3, qYj2, qYj6 ;// i3 = (j2+j6)/2
+ VSUB qYi2, qYj2, qYj6 ;// i2 = j2-j6
+ VHADD qYi7, qYj5, qYj3 ;// i7 = (j5+j3)/2
+ VSUB qYi4, qYj5, qYj3 ;// i4 = j5-j3
+
+ VQRDMULH qYi2, qYi2, InvSqrt2 ;// i2/sqrt(2)
+ ;// IStage 4,3 rows 0to1 x 1/2
+
+ MOV pTemp, #0x4 ;// ensure correct round
+ VDUP qScale1, pTemp ;// of DC result
+ VADD qYi0, qYi0, qScale1
+
+ VHADD qYh0, qYi0, qYi1 ;// (i0+i1)/2
+ VHSUB qYh1, qYi0, qYi1 ;// (i0-i1)/2
+
+ VHADD qYh7, qYi5, qYi7 ;// (i5+i7)/4
+ VSUB qYh5, qYi5, qYi7 ;// (i5-i7)/2
+ VSUB qYh2, qYi2, qYi3 ;// h2, h3
+ VQRDMULH qYh5, qYh5, InvSqrt2 ;// h5/sqrt(2)
+
+ VMULL qXt0, dYi4lo, C ;// c*i4
+ VMLAL qXt0, dYi6lo, S ;// c*i4+s*i6
+ VMULL qXt1, dYi4hi, C
+ VMLAL qXt1, dYi6hi, S
+ VSHRN dYh4lo, qXt0, #16 ;// h4
+ VSHRN dYh4hi, qXt1, #16
+
+ VMULL qXt0, dYi6lo, C ;// c*i6
+ VMLSL qXt0, dYi4lo, S ;// -s*i4 + c*h6
+ VMULL qXt1, dYi6hi, C
+ VMLSL qXt1, dYi4hi, S
+ VSHRN dYh6lo, qXt0, #16 ;// h6
+ VSHRN dYh6hi, qXt1, #16
+
+ VSUB qYg6, qYh6, qYh7
+ VSUB qYg5, qYh5, qYg6
+ VSUB qYg4, qYh4, qYg5
+
+ ;// IStage 2 rows 0to3 x 1/2
+ VHADD qYg1, qYh1, qYh2 ;// (h1+h2)/2
+ VHSUB qYg2, qYh1, qYh2 ;// (h1-h2)/2
+ VHADD qYg0, qYh0, qYh3 ;// (h0+h3)/2
+ VHSUB qYg3, qYh0, qYh3 ;// (h0-h3)/2
+
+
+ ;// IStage 1 all rows
+ VHADD qYf3, qYg3, qYg4
+ VHSUB qYf4, qYg3, qYg4
+ VHADD qYf2, qYg2, qYg5
+ VHSUB qYf5, qYg2, qYg5
+ VHADD qYf1, qYg1, qYg6
+ VHSUB qYf6, qYg1, qYg6
+ VHADD qYf0, qYg0, qYg7
+ VHSUB qYf7, qYg0, qYg7
+
+YTR0 EQU Src0
+YTR1 EQU Src4
+YTR2 EQU Src1
+YTR3 EQU Src2
+YTR4 EQU Src7
+YTR5 EQU Src5
+YTR6 EQU Tmp
+YTR7 EQU Src6
+YTRt EQU Src3
+
+qC0 QN YTR0.S32 ;// for YTRpose
+qC1 QN YTR1.S32
+qC2 QN YTR2.S32
+qC3 QN YTR3.S32
+qC4 QN YTR4.S32
+qC5 QN YTR5.S32
+qC6 QN YTR6.S32
+qC7 QN YTR7.S32
+
+dD0 DN YTR0*2+1 ;// for using VSWP
+dD1 DN YTR1*2+1
+dD2 DN YTR2*2+1
+dD3 DN YTR3*2+1
+dD4 DN YTR4*2
+dD5 DN YTR5*2
+dD6 DN YTR6*2
+dD7 DN YTR7*2
+
+ VTRN qYf0, qYf1
+ VTRN qYf2, qYf3
+ VTRN qYf4, qYf5
+ VTRN qYf6, qYf7
+ VTRN qC0, qC2
+ VTRN qC1, qC3
+ VTRN qC4, qC6
+ VTRN qC5, qC7
+ VSWP dD0, dD4
+ VSWP dD1, dD5
+ VSWP dD2, dD6
+ VSWP dD3, dD7
+
+
+dYf0U8 DN YTR0*2.U8
+dYf1U8 DN YTR1*2.U8
+dYf2U8 DN YTR2*2.U8
+dYf3U8 DN YTR3*2.U8
+dYf4U8 DN YTR4*2.U8
+dYf5U8 DN YTR5*2.U8
+dYf6U8 DN YTR6*2.U8
+dYf7U8 DN YTR7*2.U8
+
+ ;//
+ ;// Do saturation if outsize is other than S16
+ ;//
+
+ IF ("$outsize"="u8")
+ ;// Output range [0-255]
+ VQMOVN dYf0U8, qYf0
+ VQMOVN dYf1U8, qYf1
+ VQMOVN dYf2U8, qYf2
+ VQMOVN dYf3U8, qYf3
+ VQMOVN dYf4U8, qYf4
+ VQMOVN dYf5U8, qYf5
+ VQMOVN dYf6U8, qYf6
+ VQMOVN dYf7U8, qYf7
+ ENDIF
+
+ IF ("$outsize"="s9")
+ ;// Output range [-256 to +255]
+ VQSHL qYf0, qYf0, #16-9
+ VQSHL qYf1, qYf1, #16-9
+ VQSHL qYf2, qYf2, #16-9
+ VQSHL qYf3, qYf3, #16-9
+ VQSHL qYf4, qYf4, #16-9
+ VQSHL qYf5, qYf5, #16-9
+ VQSHL qYf6, qYf6, #16-9
+ VQSHL qYf7, qYf7, #16-9
+
+ VSHR qYf0, qYf0, #16-9
+ VSHR qYf1, qYf1, #16-9
+ VSHR qYf2, qYf2, #16-9
+ VSHR qYf3, qYf3, #16-9
+ VSHR qYf4, qYf4, #16-9
+ VSHR qYf5, qYf5, #16-9
+ VSHR qYf6, qYf6, #16-9
+ VSHR qYf7, qYf7, #16-9
+ ENDIF
+
+ ;// Store output depending on the Stride size
+ IF "$stride"="s"
+ VST1 qYf0, [pDest @64], Stride
+ VST1 qYf1, [pDest @64], Stride
+ VST1 qYf2, [pDest @64], Stride
+ VST1 qYf3, [pDest @64], Stride
+ VST1 qYf4, [pDest @64], Stride
+ VST1 qYf5, [pDest @64], Stride
+ VST1 qYf6, [pDest @64], Stride
+ VST1 qYf7, [pDest @64]
+ ELSE
+ IF ("$outsize"="u8")
+ VST1 dYf0U8, [pDest @64], #8
+ VST1 dYf1U8, [pDest @64], #8
+ VST1 dYf2U8, [pDest @64], #8
+ VST1 dYf3U8, [pDest @64], #8
+ VST1 dYf4U8, [pDest @64], #8
+ VST1 dYf5U8, [pDest @64], #8
+ VST1 dYf6U8, [pDest @64], #8
+ VST1 dYf7U8, [pDest @64]
+ ELSE
+ ;// ("$outsize"="s9") or ("$outsize"="s16")
+ VST1 qYf0, [pDest @64], #16
+ VST1 qYf1, [pDest @64], #16
+ VST1 qYf2, [pDest @64], #16
+ VST1 qYf3, [pDest @64], #16
+ VST1 qYf4, [pDest @64], #16
+ VST1 qYf5, [pDest @64], #16
+ VST1 qYf6, [pDest @64], #16
+ VST1 qYf7, [pDest @64]
+ ENDIF
+
+ ENDIF
+
+
+
+ ENDIF ;// CortexA8
+
+
+
+ MEND
+
+ ;// Scale TWO input rows with TWO rows of 16 bit scale values
+ ;//
+ ;// This macro is used by M_IDCT_PRESCALE16 to pre-scale one row
+ ;// input (Eight input values) with one row of scale values. Also
+ ;// Loads next scale values from pScale, if $LastRow flag is not set.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $dAlo - Input D register with first four S16 values of row n
+ ;// $dAhi - Input D register with next four S16 values of row n
+ ;// $dBlo - Input D register with first four S16 values of row n+1
+ ;// $dBhi - Input D register with next four S16 values of row n+1
+ ;// pScale - Pointer to next row of scale values
+ ;// qT0lo - Temporary scratch register
+ ;// qT0hi - Temporary scratch register
+ ;// qT1lo - Temporary scratch register
+ ;// qT1hi - Temporary scratch register
+ ;// dScale1lo - Scale value of row n
+ ;// dScale1hi - Scale value of row n
+ ;// dScale2lo - Scale value of row n+1
+ ;// dScale2hi - Scale value of row n+1
+ ;//
+ ;// Input Flag
+ ;//
+ ;// $LastRow - Flag to indicate whether current row is last row
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $dAlo - Scaled output values (first four S16 of row n)
+ ;// $dAhi - Scaled output values (next four S16 of row n)
+ ;// $dBlo - Scaled output values (first four S16 of row n+1)
+ ;// $dBhi - Scaled output values (next four S16 of row n+1)
+ ;// qScale1 - Scale values for next row
+ ;// qScale2 - Scale values for next row+1
+ ;// pScale - Pointer to next row of scale values
+ ;//
+ MACRO
+ M_IDCT_SCALE16 $dAlo, $dAhi, $dBlo, $dBhi, $LastRow
+ VMULL qT0lo, $dAlo, dScale1lo
+ VMULL qT0hi, $dAhi, dScale1hi
+ VMULL qT1lo, $dBlo, dScale2lo
+ VMULL qT1hi, $dBhi, dScale2hi
+ IF "$LastRow"="0"
+ VLD1 qScale1, [pScale], #16 ;// Load scale for row n+1
+ VLD1 qScale2, [pScale], #16 ;// Load scale for row n+2
+ ENDIF
+ VQRSHRN $dAlo, qT0lo, #12
+ VQRSHRN $dAhi, qT0hi, #12
+ VQRSHRN $dBlo, qT1lo, #12
+ VQRSHRN $dBhi, qT1hi, #12
+ MEND
+
+ ;// Scale 8x8 block input values with 16 bit scale values
+ ;//
+ ;// This macro is used to pre-scale block of 8x8 input.
+ ;// This also do the Ist stage transformations of IDCT.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// dXjnlo - n th input D register with first four S16 values
+ ;// dXjnhi - n th input D register with next four S16 values
+ ;// qXjn - n th input Q register with eight S16 values
+ ;// pScale - Pointer to scale values
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// qXin - n th output Q register with eight S16 output values of 1st stage
+ ;//
+ MACRO
+ M_IDCT_PRESCALE16
+ VLD1 qScale1, [pScale], #16 ;// Load Pre scale for row 0
+ VLD1 qScale2, [pScale], #16 ;// Load Pre scale for row 0
+ M_IDCT_SCALE16 dXj0lo, dXj0hi, dXj1lo, dXj1hi, 0 ;// Pre scale row 0 & 1
+ M_IDCT_SCALE16 dXj2lo, dXj2hi, dXj3lo, dXj3hi, 0
+ M_IDCT_SCALE16 dXj4lo, dXj4hi, dXj5lo, dXj5hi, 0
+ M_IDCT_SCALE16 dXj6lo, dXj6hi, dXj7lo, dXj7hi, 1
+ VHADD qXi5, qXj1, qXj7 ;// (j1+j7)/2
+ VSUB qXi6, qXj1, qXj7 ;// j1-j7
+ LDR pSrc, =armCOMM_IDCTCoef ;// Address of DCT inverse AAN constants
+ VHADD qXi3, qXj2, qXj6 ;// (j2+j6)/2
+ VSUB qXi2, qXj2, qXj6 ;// j2-j6
+ VLDR dCoefs, [pSrc] ;// Load DCT inverse AAN constants
+ VHADD qXi7, qXj5, qXj3 ;// (j5+j3)/2
+ VSUB qXi4, qXj5, qXj3 ;// j5-j3
+ MEND
+
+
+ ;// Scale 8x8 block input values with 32 bit scale values
+ ;//
+ ;// This macro is used to pre-scale block of 8x8 input.
+ ;// This also do the Ist stage transformations of IDCT.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// dXjnlo - n th input D register with first four S16 values
+ ;// dXjnhi - n th input D register with next four S16 values
+ ;// qXjn - n th input Q register with eight S16 values
+ ;// pScale - Pointer to 32bit scale values in Q23 format
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// dXinlo - n th output D register with first four S16 output values of 1st stage
+ ;// dXinhi - n th output D register with next four S16 output values of 1st stage
+ ;//
+ MACRO
+ M_IDCT_PRESCALE32
+qScale0lo QN 0.S32
+qScale0hi QN 1.S32
+qScale1lo QN 2.S32
+qScale1hi QN 3.S32
+qScale2lo QN qScale1lo
+qScale2hi QN qScale1hi
+qScale3lo QN qScale1lo
+qScale3hi QN qScale1hi
+qScale4lo QN qScale1lo
+qScale4hi QN qScale1hi
+qScale5lo QN qScale0lo
+qScale5hi QN qScale0hi
+qScale6lo QN qScale0lo
+qScale6hi QN qScale0hi
+qScale7lo QN qScale0lo
+qScale7hi QN qScale0hi
+
+qSrc0lo QN 4.S32
+qSrc0hi QN 5.S32
+qSrc1lo QN 6.S32
+qSrc1hi QN Src4.S32
+qSrc2lo QN qSrc0lo
+qSrc2hi QN qSrc0hi
+qSrc3lo QN qSrc0lo
+qSrc3hi QN qSrc0hi
+qSrc4lo QN qSrc0lo
+qSrc4hi QN qSrc0hi
+qSrc5lo QN qSrc1lo
+qSrc5hi QN qSrc1hi
+qSrc6lo QN qSrc1lo
+qSrc6hi QN qSrc1hi
+qSrc7lo QN qSrc0lo
+qSrc7hi QN qSrc0hi
+
+qRes17lo QN qScale0lo
+qRes17hi QN qScale0hi
+qRes26lo QN qScale0lo
+qRes26hi QN qScale0hi
+qRes53lo QN qScale0lo
+qRes53hi QN qScale0hi
+
+ ADD pTemp, pScale, #4*8*7 ;// Address of pScale[7]
+
+ ;// Row 0
+ VLD1 {qScale0lo, qScale0hi}, [pScale]!
+ VSHLL qSrc0lo, dXj0lo, #(12-1)
+ VSHLL qSrc0hi, dXj0hi, #(12-1)
+ VLD1 {qScale1lo, qScale1hi}, [pScale]!
+ VQRDMULH qSrc0lo, qScale0lo, qSrc0lo
+ VQRDMULH qSrc0hi, qScale0hi, qSrc0hi
+ VLD1 {qScale7lo, qScale7hi}, [pTemp]!
+ VSHLL qSrc1lo, dXj1lo, #(12-1)
+ VSHLL qSrc1hi, dXj1hi, #(12-1)
+ VMOVN dXi0lo, qSrc0lo ;// Output i0
+ VMOVN dXi0hi, qSrc0hi
+ VSHLL qSrc7lo, dXj7lo, #(12-1)
+ VSHLL qSrc7hi, dXj7hi, #(12-1)
+ SUB pTemp, pTemp, #((16*2)+(4*8*1))
+ VQRDMULH qSrc1lo, qScale1lo, qSrc1lo
+ VQRDMULH qSrc1hi, qScale1hi, qSrc1hi
+ VQRDMULH qSrc7lo, qScale7lo, qSrc7lo
+ VQRDMULH qSrc7hi, qScale7hi, qSrc7hi
+ VLD1 {qScale2lo, qScale2hi}, [pScale]!
+
+ ;// Row 1 & 7
+ VHADD qRes17lo, qSrc1lo, qSrc7lo ;// (j1+j7)/2
+ VHADD qRes17hi, qSrc1hi, qSrc7hi ;// (j1+j7)/2
+ VMOVN dXi5lo, qRes17lo ;// Output i5
+ VMOVN dXi5hi, qRes17hi
+ VSUB qRes17lo, qSrc1lo, qSrc7lo ;// j1-j7
+ VSUB qRes17hi, qSrc1hi, qSrc7hi ;// j1-j7
+ VMOVN dXi6lo, qRes17lo ;// Output i6
+ VMOVN dXi6hi, qRes17hi
+ VSHLL qSrc2lo, dXj2lo, #(12-1)
+ VSHLL qSrc2hi, dXj2hi, #(12-1)
+ VLD1 {qScale6lo, qScale6hi}, [pTemp]!
+ VSHLL qSrc6lo, dXj6lo, #(12-1)
+ VSHLL qSrc6hi, dXj6hi, #(12-1)
+ SUB pTemp, pTemp, #((16*2)+(4*8*1))
+ VQRDMULH qSrc2lo, qScale2lo, qSrc2lo
+ VQRDMULH qSrc2hi, qScale2hi, qSrc2hi
+ VQRDMULH qSrc6lo, qScale6lo, qSrc6lo
+ VQRDMULH qSrc6hi, qScale6hi, qSrc6hi
+ VLD1 {qScale3lo, qScale3hi}, [pScale]!
+
+ ;// Row 2 & 6
+ VHADD qRes26lo, qSrc2lo, qSrc6lo ;// (j2+j6)/2
+ VHADD qRes26hi, qSrc2hi, qSrc6hi ;// (j2+j6)/2
+ VMOVN dXi3lo, qRes26lo ;// Output i3
+ VMOVN dXi3hi, qRes26hi
+ VSUB qRes26lo, qSrc2lo, qSrc6lo ;// j2-j6
+ VSUB qRes26hi, qSrc2hi, qSrc6hi ;// j2-j6
+ VMOVN dXi2lo, qRes26lo ;// Output i2
+ VMOVN dXi2hi, qRes26hi
+ VSHLL qSrc3lo, dXj3lo, #(12-1)
+ VSHLL qSrc3hi, dXj3hi, #(12-1)
+ VLD1 {qScale5lo, qScale5hi}, [pTemp]!
+ VSHLL qSrc5lo, dXj5lo, #(12-1)
+ VSHLL qSrc5hi, dXj5hi, #(12-1)
+ VQRDMULH qSrc3lo, qScale3lo, qSrc3lo
+ VQRDMULH qSrc3hi, qScale3hi, qSrc3hi
+ VQRDMULH qSrc5lo, qScale5lo, qSrc5lo
+ VQRDMULH qSrc5hi, qScale5hi, qSrc5hi
+
+ ;// Row 3 & 5
+ VHADD qRes53lo, qSrc5lo, qSrc3lo ;// (j5+j3)/2
+ VHADD qRes53hi, qSrc5hi, qSrc3hi ;// (j5+j3)/2
+ SUB pSrc, pSrc, #16*2*2
+ VMOVN dXi7lo, qRes53lo ;// Output i7
+ VMOVN dXi7hi, qRes53hi
+ VSUB qRes53lo, qSrc5lo, qSrc3lo ;// j5-j3
+ VSUB qRes53hi, qSrc5hi, qSrc3hi ;// j5-j3
+ VLD1 qXj4, [pSrc @64]
+ VMOVN dXi4lo, qRes53lo ;// Output i4
+ VMOVN dXi4hi, qRes53hi
+ VSHLL qSrc4lo, dXj4lo, #(12-1)
+ VSHLL qSrc4hi, dXj4hi, #(12-1)
+ VLD1 {qScale4lo, qScale4hi}, [pScale]
+ LDR pSrc, =armCOMM_IDCTCoef ;// Address of DCT inverse AAN constants
+ VQRDMULH qSrc4lo, qScale4lo, qSrc4lo
+ VQRDMULH qSrc4hi, qScale4hi, qSrc4hi
+ VLDR dCoefs, [pSrc] ;// Load DCT inverse AAN constants
+ ;// Row 4
+ VMOVN dXi1lo, qSrc4lo ;// Output i1
+ VMOVN dXi1hi, qSrc4hi
+
+ MEND
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_MaskTable.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_MaskTable.h
new file mode 100644
index 0000000..b5da9dc
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_MaskTable.h
@@ -0,0 +1,27 @@
+/**
+ *
+ * File Name: armCOMM_MaskTable.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Mask Table to mask the end of array
+ */
+
+
+
+#ifndef _ARMCOMM_MASKTABLE_H_
+#define _ARMCOMM_MASKTABLE_H_
+
+#define MaskTableSize 72
+
+/* Mask table */
+
+extern const OMX_U16 armCOMM_qMaskTable16[MaskTableSize];
+extern const OMX_U8 armCOMM_qMaskTable8[MaskTableSize];
+
+#endif
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_Version.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_Version.h
new file mode 100644
index 0000000..13e5b2b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_Version.h
@@ -0,0 +1,43 @@
+/* Guard the header against multiple inclusion. */
+#ifndef __ARM_COMM_VERSION_H__
+#define __ARM_COMM_VERSION_H__
+
+
+/* The following line should be in omxtypes.h but hasn't been approved by OpenMAX yet */
+#define OMX_VERSION 102
+
+/* We need to define these macros in order to convert a #define number into a #define string. */
+#define ARM_QUOTE(a) #a
+#define ARM_INDIRECT(A) ARM_QUOTE(A)
+
+/* Convert the OMX_VERSION number into a string that can be used, for example, to print it out. */
+#define ARM_VERSION_STRING ARM_INDIRECT(OMX_VERSION)
+
+
+/* Define this in order to turn on ARM version/release/build strings in each domain */
+#define ARM_INCLUDE_VERSION_DESCRIPTIONS
+
+#ifdef ARM_INCLUDE_VERSION_DESCRIPTIONS
+ extern const char * const omxAC_VersionDescription;
+ extern const char * const omxIC_VersionDescription;
+ extern const char * const omxIP_VersionDescription;
+ extern const char * const omxSP_VersionDescription;
+ extern const char * const omxVC_VersionDescription;
+#endif /* ARM_INCLUDE_VERSION_DESCRIPTIONS */
+
+
+/* The following entries should be automatically updated by the release script */
+/* They are used in the ARM version strings defined for each domain. */
+
+/* The release tag associated with this release of the library. - used for source and object releases */
+#define OMX_ARM_RELEASE_TAG "r0p0-00bet1"
+
+/* The ARM architecture used to build any objects or executables in this release. */
+#define OMX_ARM_BUILD_ARCHITECTURE "ARM Architecture V6"
+
+/* The ARM Toolchain used to build any objects or executables in this release. */
+#define OMX_ARM_BUILD_TOOLCHAIN "ARM RVCT 3.1"
+
+
+#endif /* __ARM_COMM_VERSION_H__ */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_s.h
new file mode 100644
index 0000000..2df1fc8
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armCOMM_s.h
@@ -0,0 +1,1154 @@
+;//
+;//
+;// File Name: armCOMM_s.h
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// ARM optimized OpenMAX common header file
+;//
+
+;// Protect against multiple inclusion
+ IF :LNOT::DEF:ARMCOMM_S_H
+ GBLL ARMCOMM_S_H
+
+ REQUIRE8 ;// Requires 8-byte stack alignment
+ PRESERVE8 ;// Preserves 8-byte stack alignment
+
+ GBLL ARM_ERRORCHECK
+ARM_ERRORCHECK SETL {FALSE}
+
+;// Globals
+
+ GBLS _RRegList ;// R saved register list
+ GBLS _DRegList ;// D saved register list
+ GBLS _Variant ;// Selected processor variant
+ GBLS _CPU ;// CPU name
+ GBLS _Struct ;// Structure name
+
+ GBLL _InFunc ;// Inside function assembly flag
+ GBLL _SwLong ;// Long switch flag
+
+ GBLA _RBytes ;// Number of register bytes on stack
+ GBLA _SBytes ;// Number of scratch bytes on stack
+ GBLA _ABytes ;// Stack offset of next argument
+ GBLA _Workspace ;// Stack offset of scratch workspace
+ GBLA _F ;// Function number
+ GBLA _StOff ;// Struct offset
+ GBLA _SwNum ;// Switch number
+ GBLS _32 ;// Suffix for 32 byte alignmnet
+ GBLS _16 ;// Suffix for 16 byte alignmnet
+
+_InFunc SETL {FALSE}
+_SBytes SETA 0
+_F SETA 0
+_SwNum SETA 0
+_32 SETS "ALIGN32"
+_16 SETS "ALIGN16"
+
+;/////////////////////////////////////////////////////////
+;// Override the tools settings of the CPU if the #define
+;// USECPU is set, otherwise use the CPU defined by the
+;// assembler settings.
+;/////////////////////////////////////////////////////////
+
+ IF :DEF: OVERRIDECPU
+_CPU SETS OVERRIDECPU
+ ELSE
+_CPU SETS {CPU}
+ ENDIF
+
+
+
+;/////////////////////////////////////////////////////////
+;// Work out which code to build
+;/////////////////////////////////////////////////////////
+
+ IF :DEF:ARM1136JS:LOR::DEF:CortexA8:LOR::DEF:ARM_GENERIC
+ INFO 1,"Please switch to using M_VARIANTS"
+ ENDIF
+
+ ;// Define and reset all officially recongnised variants
+ MACRO
+ _M_DEF_VARIANTS
+ _M_DEF_VARIANT ARM926EJS
+ _M_DEF_VARIANT ARM1136JS
+ _M_DEF_VARIANT ARM1136JS_U
+ _M_DEF_VARIANT CortexA8
+ _M_DEF_VARIANT ARM7TDMI
+ MEND
+
+ MACRO
+ _M_DEF_VARIANT $var
+ GBLL $var
+ GBLL _ok$var
+$var SETL {FALSE}
+ MEND
+
+
+ ;// Variant declaration
+ ;//
+ ;// Define a list of code variants supported by this
+ ;// source file. This macro then chooses the most
+ ;// appropriate variant to build for the currently configured
+ ;// core.
+ ;//
+ MACRO
+ M_VARIANTS $v0,$v1,$v2,$v3,$v4,$v5,$v6,$v7
+ ;// Set to TRUE variants that are supported
+ _M_DEF_VARIANTS
+ _M_VARIANT $v0
+ _M_VARIANT $v1
+ _M_VARIANT $v2
+ _M_VARIANT $v3
+ _M_VARIANT $v4
+ _M_VARIANT $v5
+ _M_VARIANT $v6
+ _M_VARIANT $v7
+
+ ;// Look for first available variant to match a CPU
+ ;// _M_TRY cpu, variant fall back list
+_Variant SETS ""
+ _M_TRY ARM926EJ-S, ARM926EJS
+ _M_TRY ARM1176JZ-S, ARM1136JS
+ _M_TRY ARM1176JZF-S, ARM1136JS
+ _M_TRY ARM1156T2-S, ARM1136JS
+ _M_TRY ARM1156T2F-S, ARM1136JS
+ _M_TRY ARM1136J-S, ARM1136JS
+ _M_TRY ARM1136JF-S, ARM1136JS
+ _M_TRY MPCore, ARM1136JS
+ _M_TRY Cortex-A8, CortexA8, ARM1136JS
+ _M_TRY Cortex-R4, ARM1136JS
+ _M_TRY ARM7TDMI
+
+ ;// Select the correct variant
+ _M_DEF_VARIANTS
+ IF _Variant=""
+ INFO 1, "No match found for CPU '$_CPU'"
+ ELSE
+$_Variant SETL {TRUE}
+ ENDIF
+ MEND
+
+ ;// Register a variant as available
+ MACRO
+ _M_VARIANT $var
+ IF "$var"=""
+ MEXIT
+ ENDIF
+ IF :LNOT::DEF:_ok$var
+ INFO 1, "Unrecognized variant '$var'"
+ ENDIF
+$var SETL {TRUE}
+ MEND
+
+ ;// For a given CPU, see if any of the variants supporting
+ ;// this CPU are available. The first available variant is
+ ;// chosen
+ MACRO
+ _M_TRY $cpu, $v0,$v1,$v2,$v3,$v4,$v5,$v6,$v7
+ IF "$cpu"<>_CPU
+ MEXIT
+ ENDIF
+ _M_TRY1 $v0
+ _M_TRY1 $v1
+ _M_TRY1 $v2
+ _M_TRY1 $v3
+ _M_TRY1 $v4
+ _M_TRY1 $v5
+ _M_TRY1 $v6
+ _M_TRY1 $v7
+ ;// Check a match was found
+ IF _Variant=""
+ INFO 1, "No variant match found for CPU '$_CPU'"
+ ENDIF
+ MEND
+
+ MACRO
+ _M_TRY1 $var
+ IF "$var"=""
+ MEXIT
+ ENDIF
+ IF (_Variant=""):LAND:$var
+_Variant SETS "$var"
+ ENDIF
+ MEND
+
+;////////////////////////////////////////////////////////
+;// Structure definition
+;////////////////////////////////////////////////////////
+
+ ;// Declare a structure of given name
+ MACRO
+ M_STRUCT $sname
+_Struct SETS "$sname"
+_StOff SETA 0
+ MEND
+
+ ;// Declare a structure field
+ ;// The field is called $sname_$fname
+ ;// $size = the size of each entry, must be power of 2
+ ;// $number = (if provided) the number of entries for an array
+ MACRO
+ M_FIELD $fname, $size, $number
+ IF (_StOff:AND:($size-1))!=0
+_StOff SETA _StOff + ($size - (_StOff:AND:($size-1)))
+ ENDIF
+$_Struct._$fname EQU _StOff
+ IF "$number"<>""
+_StOff SETA _StOff + $size*$number
+ ELSE
+_StOff SETA _StOff + $size
+ ENDIF
+ MEND
+
+
+ MACRO
+ M_ENDSTRUCT
+sizeof_$_Struct EQU _StOff
+_Struct SETS ""
+ MEND
+
+;//////////////////////////////////////////////////////////
+;// Switch and table macros
+;//////////////////////////////////////////////////////////
+
+ ;// Start a relative switch table with register to switch on
+ ;//
+ ;// $v = the register to switch on
+ ;// $s = if specified must be "L" to indicate long
+ ;// this allows a greater range to the case code
+ MACRO
+ M_SWITCH $v, $s
+ ASSERT "$s"="":LOR:"$s"="L"
+_SwLong SETL {FALSE}
+ IF "$s"="L"
+_SwLong SETL {TRUE}
+ ENDIF
+_SwNum SETA _SwNum+1
+ IF {CONFIG}=16
+ ;// Thumb
+ IF _SwLong
+ TBH [pc, $v, LSL#1]
+ ELSE
+ TBB [pc, $v]
+ ENDIF
+_Switch$_SwNum
+ ELSE
+ ;// ARM
+ ADD pc, pc, $v, LSL #2
+ NOP
+ ENDIF
+ MEND
+
+ ;// Add a case to the switch statement
+ MACRO
+ M_CASE $label
+ IF {CONFIG}=16
+ ;// Thumb
+ IF _SwLong
+ DCW ($label - _Switch$_SwNum)/2
+ ELSE
+ DCB ($label - _Switch$_SwNum)/2
+ ENDIF
+ ELSE
+ ;// ARM
+ B $label
+ ENDIF
+ MEND
+
+ ;// End of switch statement
+ MACRO
+ M_ENDSWITCH
+ ALIGN 2
+ MEND
+
+
+;////////////////////////////////////////////////////////
+;// Data area allocation
+;////////////////////////////////////////////////////////
+
+ ;// Constant table allocator macro
+ ;//
+ ;// Creates a new section for each constant table
+ ;// $name is symbol through which the table can be accessed.
+ ;// $align is the optional alignment of the table, log2 of
+ ;// the byte alignment - $align=4 is 16 byte aligned
+ MACRO
+ M_TABLE $name, $align
+ ASSERT :LNOT:_InFunc
+ IF "$align"=""
+ AREA |.constdata|, READONLY, DATA
+ ELSE
+ ;// AREAs inherit the alignment of the first declaration.
+ ;// Therefore for each alignment size we must have an area
+ ;// of a different name.
+ AREA constdata_a$align, READONLY, DATA, ALIGN=$align
+
+ ;// We also force alignment incase we are tagging onto
+ ;// an already started area.
+ ALIGN (1<<$align)
+ ENDIF
+$name
+ MEND
+
+;/////////////////////////////////////////////////////
+;// Macros to allocate space on the stack
+;//
+;// These all assume that the stack is 8-byte aligned
+;// at entry to the function, which means that the
+;// 32-byte alignment macro needs to work in a
+;// bit more of a special way...
+;/////////////////////////////////////////////////////
+
+
+
+
+ ;// Allocate 1-byte aligned area of name
+ ;// $name size $size bytes.
+ MACRO
+ M_ALLOC1 $name, $size
+ ASSERT :LNOT:_InFunc
+$name$_F EQU _SBytes
+_SBytes SETA _SBytes + ($size)
+ MEND
+
+ ;// Allocate 2-byte aligned area of name
+ ;// $name size $size bytes.
+ MACRO
+ M_ALLOC2 $name, $size
+ ASSERT :LNOT:_InFunc
+ IF (_SBytes:AND:1)!=0
+_SBytes SETA _SBytes + (2 - (_SBytes:AND:1))
+ ENDIF
+$name$_F EQU _SBytes
+_SBytes SETA _SBytes + ($size)
+ MEND
+
+ ;// Allocate 4-byte aligned area of name
+ ;// $name size $size bytes.
+ MACRO
+ M_ALLOC4 $name, $size
+ ASSERT :LNOT:_InFunc
+ IF (_SBytes:AND:3)!=0
+_SBytes SETA _SBytes + (4 - (_SBytes:AND:3))
+ ENDIF
+$name$_F EQU _SBytes
+_SBytes SETA _SBytes + ($size)
+ MEND
+
+ ;// Allocate 8-byte aligned area of name
+ ;// $name size $size bytes.
+ MACRO
+ M_ALLOC8 $name, $size
+ ASSERT :LNOT:_InFunc
+ IF (_SBytes:AND:7)!=0
+_SBytes SETA _SBytes + (8 - (_SBytes:AND:7))
+ ENDIF
+$name$_F EQU _SBytes
+_SBytes SETA _SBytes + ($size)
+ MEND
+
+
+ ;// Allocate 8-byte aligned area of name
+ ;// $name size ($size+16) bytes.
+ ;// The extra 16 bytes are later used to align the pointer to 16 bytes
+
+ MACRO
+ M_ALLOC16 $name, $size
+ ASSERT :LNOT:_InFunc
+ IF (_SBytes:AND:7)!=0
+_SBytes SETA _SBytes + (8 - (_SBytes:AND:7))
+ ENDIF
+$name$_F$_16 EQU (_SBytes + 8)
+_SBytes SETA _SBytes + ($size) + 8
+ MEND
+
+ ;// Allocate 8-byte aligned area of name
+ ;// $name size ($size+32) bytes.
+ ;// The extra 32 bytes are later used to align the pointer to 32 bytes
+
+ MACRO
+ M_ALLOC32 $name, $size
+ ASSERT :LNOT:_InFunc
+ IF (_SBytes:AND:7)!=0
+_SBytes SETA _SBytes + (8 - (_SBytes:AND:7))
+ ENDIF
+$name$_F$_32 EQU (_SBytes + 24)
+_SBytes SETA _SBytes + ($size) + 24
+ MEND
+
+
+
+
+ ;// Argument Declaration Macro
+ ;//
+ ;// Allocate an argument name $name
+ ;// size $size bytes
+ MACRO
+ M_ARG $name, $size
+ ASSERT _InFunc
+$name$_F EQU _ABytes
+_ABytes SETA _ABytes + ($size)
+ MEND
+
+;///////////////////////////////////////////////
+;// Macros to access stacked variables
+;///////////////////////////////////////////////
+
+ ;// Macro to perform a data processing operation
+ ;// with a constant second operand
+ MACRO
+ _M_OPC $op,$rd,$rn,$const
+ LCLA _sh
+ LCLA _cst
+_sh SETA 0
+_cst SETA $const
+ IF _cst=0
+ $op $rd, $rn, #_cst
+ MEXIT
+ ENDIF
+ WHILE (_cst:AND:3)=0
+_cst SETA _cst>>2
+_sh SETA _sh+2
+ WEND
+ $op $rd, $rn, #(_cst:AND:0x000000FF)<<_sh
+ IF _cst>=256
+ $op $rd, $rd, #(_cst:AND:0xFFFFFF00)<<_sh
+ ENDIF
+ MEND
+
+ ;// Macro to perform a data access operation
+ ;// Such as LDR or STR
+ ;// The addressing mode is modified such that
+ ;// 1. If no address is given then the name is taken
+ ;// as a stack offset
+ ;// 2. If the addressing mode is not available for the
+ ;// state being assembled for (eg Thumb) then a suitable
+ ;// addressing mode is substituted.
+ ;//
+ ;// On Entry:
+ ;// $i = Instruction to perform (eg "LDRB")
+ ;// $a = Required byte alignment
+ ;// $r = Register(s) to transfer (eg "r1")
+ ;// $a0,$a1,$a2. Addressing mode and condition. One of:
+ ;// label {,cc}
+ ;// [base] {,,,cc}
+ ;// [base, offset]{!} {,,cc}
+ ;// [base, offset, shift]{!} {,cc}
+ ;// [base], offset {,,cc}
+ ;// [base], offset, shift {,cc}
+ MACRO
+ _M_DATA $i,$a,$r,$a0,$a1,$a2,$a3
+ IF "$a0":LEFT:1="["
+ IF "$a1"=""
+ $i$a3 $r, $a0
+ ELSE
+ IF "$a0":RIGHT:1="]"
+ IF "$a2"=""
+ _M_POSTIND $i$a3, "$r", $a0, $a1
+ ELSE
+ _M_POSTIND $i$a3, "$r", $a0, "$a1,$a2"
+ ENDIF
+ ELSE
+ IF "$a2"=""
+ _M_PREIND $i$a3, "$r", $a0, $a1
+ ELSE
+ _M_PREIND $i$a3, "$r", $a0, "$a1,$a2"
+ ENDIF
+ ENDIF
+ ENDIF
+ ELSE
+ LCLA _Offset
+_Offset SETA _Workspace + $a0$_F
+ ASSERT (_Offset:AND:($a-1))=0
+ $i$a1 $r, [sp, #_Offset]
+ ENDIF
+ MEND
+
+ ;// Handle post indexed load/stores
+ ;// op reg, [base], offset
+ MACRO
+ _M_POSTIND $i,$r,$a0,$a1
+ LCLS _base
+ LCLS _offset
+ IF {CONFIG}=16 ;// Thumb
+_base SETS ("$a0":LEFT:(:LEN:"$a0"-1)):RIGHT:(:LEN:"$a0"-2) ;// remove []
+_offset SETS "$a1"
+ IF _offset:LEFT:1="+"
+_offset SETS _offset:RIGHT:(:LEN:_offset-1)
+ ENDIF
+ $i $r, $a0
+ IF _offset:LEFT:1="-"
+_offset SETS _offset:RIGHT:(:LEN:_offset-1)
+ SUB $_base, $_base, $_offset
+ ELSE
+ ADD $_base, $_base, $_offset
+ ENDIF
+ ELSE ;// ARM
+ $i $r, $a0, $a1
+ ENDIF
+ MEND
+
+ ;// Handle pre indexed load/store
+ ;// op reg, [base, offset]{!}
+ MACRO
+ _M_PREIND $i,$r,$a0,$a1
+ LCLS _base
+ LCLS _offset
+ IF ({CONFIG}=16):LAND:(("$a1":RIGHT:2)="]!")
+_base SETS "$a0":RIGHT:(:LEN:("$a0")-1)
+_offset SETS "$a1":LEFT:(:LEN:("$a1")-2)
+ $i $r, [$_base, $_offset]
+ ADD $_base, $_base, $_offset
+ ELSE
+ $i $r, $a0, $a1
+ ENDIF
+ MEND
+
+ ;// Load unsigned byte from stack
+ MACRO
+ M_LDRB $r,$a0,$a1,$a2,$a3
+ _M_DATA "LDRB",1,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Load signed byte from stack
+ MACRO
+ M_LDRSB $r,$a0,$a1,$a2,$a3
+ _M_DATA "LDRSB",1,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Store byte to stack
+ MACRO
+ M_STRB $r,$a0,$a1,$a2,$a3
+ _M_DATA "STRB",1,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Load unsigned half word from stack
+ MACRO
+ M_LDRH $r,$a0,$a1,$a2,$a3
+ _M_DATA "LDRH",2,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Load signed half word from stack
+ MACRO
+ M_LDRSH $r,$a0,$a1,$a2,$a3
+ _M_DATA "LDRSH",2,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Store half word to stack
+ MACRO
+ M_STRH $r,$a0,$a1,$a2,$a3
+ _M_DATA "STRH",2,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Load word from stack
+ MACRO
+ M_LDR $r,$a0,$a1,$a2,$a3
+ _M_DATA "LDR",4,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Store word to stack
+ MACRO
+ M_STR $r,$a0,$a1,$a2,$a3
+ _M_DATA "STR",4,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Load double word from stack
+ MACRO
+ M_LDRD $r0,$r1,$a0,$a1,$a2,$a3
+ _M_DATA "LDRD",8,"$r0,$r1",$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Store double word to stack
+ MACRO
+ M_STRD $r0,$r1,$a0,$a1,$a2,$a3
+ _M_DATA "STRD",8,"$r0,$r1",$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Get absolute address of stack allocated location
+ MACRO
+ M_ADR $a, $b, $cc
+ _M_OPC ADD$cc, $a, sp, (_Workspace + $b$_F)
+ MEND
+
+ ;// Get absolute address of stack allocated location and align the address to 16 bytes
+ MACRO
+ M_ADR16 $a, $b, $cc
+ _M_OPC ADD$cc, $a, sp, (_Workspace + $b$_F$_16)
+
+ ;// Now align $a to 16 bytes
+ BIC$cc $a,$a,#0x0F
+ MEND
+
+ ;// Get absolute address of stack allocated location and align the address to 32 bytes
+ MACRO
+ M_ADR32 $a, $b, $cc
+ _M_OPC ADD$cc, $a, sp, (_Workspace + $b$_F$_32)
+
+ ;// Now align $a to 32 bytes
+ BIC$cc $a,$a,#0x1F
+ MEND
+
+;//////////////////////////////////////////////////////////
+;// Function header and footer macros
+;//////////////////////////////////////////////////////////
+
+ ;// Function Header Macro
+ ;// Generates the function prologue
+ ;// Note that functions should all be "stack-moves-once"
+ ;// The FNSTART and FNEND macros should be the only places
+ ;// where the stack moves.
+ ;//
+ ;// $name = function name
+ ;// $rreg = "" don't stack any registers
+ ;// "lr" stack "lr" only
+ ;// "rN" stack registers "r4-rN,lr"
+ ;// $dreg = "" don't stack any D registers
+ ;// "dN" stack registers "d8-dN"
+ ;//
+ ;// Note: ARM Archicture procedure call standard AAPCS
+ ;// states that r4-r11, sp, d8-d15 must be preserved by
+ ;// a compliant function.
+ MACRO
+ M_START $name, $rreg, $dreg
+ ASSERT :LNOT:_InFunc
+ ASSERT "$name"!=""
+_InFunc SETL {TRUE}
+_RBytes SETA 0
+_Workspace SETA 0
+
+ ;// Create an area for the function
+ AREA |.text|, CODE
+ EXPORT $name
+$name FUNCTION
+
+ ;// Save R registers
+ _M_GETRREGLIST $rreg
+ IF _RRegList<>""
+ STMFD sp!, {$_RRegList, lr}
+ ENDIF
+
+ ;// Save D registers
+ _M_GETDREGLIST $dreg
+ IF _DRegList<>""
+ VSTMFD sp!, {$_DRegList}
+ ENDIF
+
+
+ ;// Ensure size claimed on stack is 8-byte aligned
+ IF ((_SBytes:AND:7)!=0)
+_SBytes SETA _SBytes + (8 - (_SBytes:AND:7))
+ ENDIF
+
+ IF (_SBytes!=0)
+ _M_OPC SUB, sp, sp, _SBytes
+ ENDIF
+
+
+_ABytes SETA _SBytes + _RBytes - _Workspace
+
+
+ ;// Print function name if debug enabled
+ M_PRINTF "$name\n",
+ MEND
+
+ ;// Work out a list of R saved registers
+ MACRO
+ _M_GETRREGLIST $rreg
+ IF "$rreg"=""
+_RRegList SETS ""
+ MEXIT
+ ENDIF
+ IF "$rreg"="lr":LOR:"$rreg"="r4"
+_RRegList SETS "r4"
+_RBytes SETA _RBytes+8
+ MEXIT
+ ENDIF
+ IF "$rreg"="r5":LOR:"$rreg"="r6"
+_RRegList SETS "r4-r6"
+_RBytes SETA _RBytes+16
+ MEXIT
+ ENDIF
+ IF "$rreg"="r7":LOR:"$rreg"="r8"
+_RRegList SETS "r4-r8"
+_RBytes SETA _RBytes+24
+ MEXIT
+ ENDIF
+ IF "$rreg"="r9":LOR:"$rreg"="r10"
+_RRegList SETS "r4-r10"
+_RBytes SETA _RBytes+32
+ MEXIT
+ ENDIF
+ IF "$rreg"="r11":LOR:"$rreg"="r12"
+_RRegList SETS "r4-r12"
+_RBytes SETA _RBytes+40
+ MEXIT
+ ENDIF
+ INFO 1, "Unrecognized saved r register limit '$rreg'"
+ MEND
+
+ ;// Work out a list of D saved registers
+ MACRO
+ _M_GETDREGLIST $dreg
+ IF "$dreg"=""
+_DRegList SETS ""
+ MEXIT
+ ENDIF
+ IF "$dreg"="d8"
+_DRegList SETS "d8"
+_RBytes SETA _RBytes+8
+ MEXIT
+ ENDIF
+ IF "$dreg"="d9"
+_DRegList SETS "d8-d9"
+_RBytes SETA _RBytes+16
+ MEXIT
+ ENDIF
+ IF "$dreg"="d10"
+_DRegList SETS "d8-d10"
+_RBytes SETA _RBytes+24
+ MEXIT
+ ENDIF
+ IF "$dreg"="d11"
+_DRegList SETS "d8-d11"
+_RBytes SETA _RBytes+32
+ MEXIT
+ ENDIF
+ IF "$dreg"="d12"
+_DRegList SETS "d8-d12"
+_RBytes SETA _RBytes+40
+ MEXIT
+ ENDIF
+ IF "$dreg"="d13"
+_DRegList SETS "d8-d13"
+_RBytes SETA _RBytes+48
+ MEXIT
+ ENDIF
+ IF "$dreg"="d14"
+_DRegList SETS "d8-d14"
+_RBytes SETA _RBytes+56
+ MEXIT
+ ENDIF
+ IF "$dreg"="d15"
+_DRegList SETS "d8-d15"
+_RBytes SETA _RBytes+64
+ MEXIT
+ ENDIF
+ INFO 1, "Unrecognized saved d register limit '$dreg'"
+ MEND
+
+ ;// Produce function return instructions
+ MACRO
+ _M_RET $cc
+ IF _DRegList<>""
+ VPOP$cc {$_DRegList}
+ ENDIF
+ IF _RRegList=""
+ BX$cc lr
+ ELSE
+ LDM$cc.FD sp!, {$_RRegList, pc}
+ ENDIF
+ MEND
+
+ ;// Early Function Exit Macro
+ ;// $cc = condition to exit with
+ ;// (Example: M_EXIT EQ)
+ MACRO
+ M_EXIT $cc
+ ASSERT _InFunc
+ IF _SBytes!=0
+ ;// Restore stack frame and exit
+ B$cc _End$_F
+ ELSE
+ ;// Can return directly
+ _M_RET $cc
+ ENDIF
+ MEND
+
+ ;// Function Footer Macro
+ ;// Generates the function epilogue
+ MACRO
+ M_END
+ ASSERT _InFunc
+_InFunc SETL {FALSE}
+_End$_F
+
+ ;// Restore the stack pointer to its original value on function entry
+ IF _SBytes!=0
+ _M_OPC ADD, sp, sp, _SBytes
+ ENDIF
+ _M_RET
+ ENDFUNC
+
+ ;// Reset the global stack tracking variables back to their
+ ;// initial values, and increment the function count
+_SBytes SETA 0
+_F SETA _F+1
+ MEND
+
+
+;//==========================================================================
+;// Debug Macros
+;//==========================================================================
+
+ GBLL DEBUG_ON
+DEBUG_ON SETL {FALSE}
+ GBLL DEBUG_STALLS_ON
+DEBUG_STALLS_ON SETL {FALSE}
+
+ ;//==========================================================================
+ ;// Debug call to printf
+ ;// M_PRINTF $format, $val0, $val1, $val2
+ ;//
+ ;// Examples:
+ ;// M_PRINTF "x=%08x\n", r0
+ ;//
+ ;// This macro preserves the value of all registers including the
+ ;// flags.
+ ;//==========================================================================
+
+ MACRO
+ M_PRINTF $format, $val0, $val1, $val2
+ IF DEBUG_ON
+
+ IMPORT printf
+ LCLA nArgs
+nArgs SETA 0
+
+ ;// save registers so we don't corrupt them
+ STMFD sp!, {r0-r12, lr}
+
+ ;// Drop stack to give us some workspace
+ SUB sp, sp, #16
+
+ ;// Save registers we need to print to the stack
+ IF "$val2" <> ""
+ ASSERT "$val1" <> ""
+ STR $val2, [sp, #8]
+nArgs SETA nArgs+1
+ ENDIF
+ IF "$val1" <> ""
+ ASSERT "$val0" <> ""
+ STR $val1, [sp, #4]
+nArgs SETA nArgs+1
+ ENDIF
+ IF "$val0"<>""
+ STR $val0, [sp]
+nArgs SETA nArgs+1
+ ENDIF
+
+ ;// Now we are safe to corrupt registers
+ ADR r0, %FT00
+ IF nArgs=1
+ LDR r1, [sp]
+ ENDIF
+ IF nArgs=2
+ LDMIA sp, {r1,r2}
+ ENDIF
+ IF nArgs=3
+ LDMIA sp, {r1,r2,r3}
+ ENDIF
+
+ ;// print the values
+ MRS r4, cpsr ;// preserve flags
+ BL printf
+ MSR cpsr_f, r4 ;// restore flags
+ B %FT01
+00 ;// string to print
+ DCB "$format", 0
+ ALIGN
+01 ;// Finished
+ ADD sp, sp, #16
+ ;// Restore registers
+ LDMFD sp!, {r0-r12,lr}
+
+ ENDIF ;// DEBUG_ON
+ MEND
+
+
+ ;// Stall Simulation Macro
+ ;// Inserts a given number of NOPs for the currently
+ ;// defined platform
+ MACRO
+ M_STALL $plat1stall, $plat2stall, $plat3stall, $plat4stall, $plat5stall, $plat6stall
+ IF DEBUG_STALLS_ON
+ _M_STALL_SUB $plat1stall
+ _M_STALL_SUB $plat2stall
+ _M_STALL_SUB $plat3stall
+ _M_STALL_SUB $plat4stall
+ _M_STALL_SUB $plat5stall
+ _M_STALL_SUB $plat6stall
+ ENDIF
+ MEND
+
+ MACRO
+ _M_STALL_SUB $platstall
+ IF "$platstall"!=""
+ LCLA _pllen
+ LCLS _pl
+ LCLL _pllog
+_pllen SETA :LEN:"$platstall"
+_pl SETS "$platstall":LEFT:(_pllen - 2)
+ IF :DEF:$_pl
+ IF $_pl
+ LCLS _st
+ LCLA _stnum
+_st SETS "$platstall":RIGHT:1
+_stnum SETA $_st
+ WHILE _stnum>0
+ MOV sp, sp
+_stnum SETA _stnum - 1
+ WEND
+ ENDIF
+ ENDIF
+ ENDIF
+ MEND
+
+
+
+;//==========================================================================
+;// Endian Invarience Macros
+;//
+;// The idea behind these macros is that if an array is
+;// loaded as words then the SMUL00 macro will multiply
+;// array elements 0 regardless of the endianess of the
+;// system. For little endian SMUL00=SMULBB, for big
+;// endian SMUL00=SMULTT and similarly for other packed operations.
+;//
+;//==========================================================================
+
+ MACRO
+ LIBI4 $comli, $combi, $a, $b, $c, $d, $cc
+ IF {ENDIAN}="big"
+ $combi.$cc $a, $b, $c, $d
+ ELSE
+ $comli.$cc $a, $b, $c, $d
+ ENDIF
+ MEND
+
+ MACRO
+ LIBI3 $comli, $combi, $a, $b, $c, $cc
+ IF {ENDIAN}="big"
+ $combi.$cc $a, $b, $c
+ ELSE
+ $comli.$cc $a, $b, $c
+ ENDIF
+ MEND
+
+ ;// SMLAxy macros
+
+ MACRO
+ SMLA00 $a, $b, $c, $d, $cc
+ LIBI4 SMLABB, SMLATT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA01 $a, $b, $c, $d, $cc
+ LIBI4 SMLABT, SMLATB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA0B $a, $b, $c, $d, $cc
+ LIBI4 SMLABB, SMLATB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA0T $a, $b, $c, $d, $cc
+ LIBI4 SMLABT, SMLATT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA10 $a, $b, $c, $d, $cc
+ LIBI4 SMLATB, SMLABT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA11 $a, $b, $c, $d, $cc
+ LIBI4 SMLATT, SMLABB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA1B $a, $b, $c, $d, $cc
+ LIBI4 SMLATB, SMLABB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA1T $a, $b, $c, $d, $cc
+ LIBI4 SMLATT, SMLABT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAB0 $a, $b, $c, $d, $cc
+ LIBI4 SMLABB, SMLABT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAB1 $a, $b, $c, $d, $cc
+ LIBI4 SMLABT, SMLABB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAT0 $a, $b, $c, $d, $cc
+ LIBI4 SMLATB, SMLATT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAT1 $a, $b, $c, $d, $cc
+ LIBI4 SMLATT, SMLATB, $a, $b, $c, $d, $cc
+ MEND
+
+ ;// SMULxy macros
+
+ MACRO
+ SMUL00 $a, $b, $c, $cc
+ LIBI3 SMULBB, SMULTT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL01 $a, $b, $c, $cc
+ LIBI3 SMULBT, SMULTB, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL0B $a, $b, $c, $cc
+ LIBI3 SMULBB, SMULTB, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL0T $a, $b, $c, $cc
+ LIBI3 SMULBT, SMULTT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL10 $a, $b, $c, $cc
+ LIBI3 SMULTB, SMULBT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL11 $a, $b, $c, $cc
+ LIBI3 SMULTT, SMULBB, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL1B $a, $b, $c, $cc
+ LIBI3 SMULTB, SMULBB, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL1T $a, $b, $c, $cc
+ LIBI3 SMULTT, SMULBT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMULB0 $a, $b, $c, $cc
+ LIBI3 SMULBB, SMULBT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMULB1 $a, $b, $c, $cc
+ LIBI3 SMULBT, SMULBB, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMULT0 $a, $b, $c, $cc
+ LIBI3 SMULTB, SMULTT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMULT1 $a, $b, $c, $cc
+ LIBI3 SMULTT, SMULTB, $a, $b, $c, $cc
+ MEND
+
+ ;// SMLAWx, SMULWx macros
+
+ MACRO
+ SMLAW0 $a, $b, $c, $d, $cc
+ LIBI4 SMLAWB, SMLAWT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAW1 $a, $b, $c, $d, $cc
+ LIBI4 SMLAWT, SMLAWB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMULW0 $a, $b, $c, $cc
+ LIBI3 SMULWB, SMULWT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMULW1 $a, $b, $c, $cc
+ LIBI3 SMULWT, SMULWB, $a, $b, $c, $cc
+ MEND
+
+ ;// SMLALxy macros
+
+
+ MACRO
+ SMLAL00 $a, $b, $c, $d, $cc
+ LIBI4 SMLALBB, SMLALTT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL01 $a, $b, $c, $d, $cc
+ LIBI4 SMLALBT, SMLALTB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL0B $a, $b, $c, $d, $cc
+ LIBI4 SMLALBB, SMLALTB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL0T $a, $b, $c, $d, $cc
+ LIBI4 SMLALBT, SMLALTT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL10 $a, $b, $c, $d, $cc
+ LIBI4 SMLALTB, SMLALBT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL11 $a, $b, $c, $d, $cc
+ LIBI4 SMLALTT, SMLALBB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL1B $a, $b, $c, $d, $cc
+ LIBI4 SMLALTB, SMLALBB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL1T $a, $b, $c, $d, $cc
+ LIBI4 SMLALTT, SMLALBT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLALB0 $a, $b, $c, $d, $cc
+ LIBI4 SMLALBB, SMLALBT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLALB1 $a, $b, $c, $d, $cc
+ LIBI4 SMLALBT, SMLALBB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLALT0 $a, $b, $c, $d, $cc
+ LIBI4 SMLALTB, SMLALTT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLALT1 $a, $b, $c, $d, $cc
+ LIBI4 SMLALTT, SMLALTB, $a, $b, $c, $d, $cc
+ MEND
+
+ ENDIF ;// ARMCOMM_S_H
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armOMX.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armOMX.h
new file mode 100644
index 0000000..f629f72
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/armOMX.h
@@ -0,0 +1,274 @@
+/*
+ *
+ * File Name: armOMX_ReleaseVersion.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * This file allows a version of the OMX DL libraries to be built where some or
+ * all of the function names can be given a user specified suffix.
+ *
+ * You might want to use it where:
+ *
+ * - you want to rename a function "out of the way" so that you could replace
+ * a function with a different version (the original version would still be
+ * in the library just with a different name - so you could debug the new
+ * version by comparing it to the output of the old)
+ *
+ * - you want to rename all the functions to versions with a suffix so that
+ * you can include two versions of the library and choose between functions
+ * at runtime.
+ *
+ * e.g. omxIPBM_Copy_U8_C1R could be renamed omxIPBM_Copy_U8_C1R_CortexA8
+ *
+ */
+
+
+#ifndef _armOMX_H_
+#define _armOMX_H_
+
+
+/* We need to define these two macros in order to expand and concatenate the names */
+#define OMXCAT2BAR(A, B) omx ## A ## B
+#define OMXCATBAR(A, B) OMXCAT2BAR(A, B)
+
+/* Define the suffix to add to all functions - the default is no suffix */
+#define BARE_SUFFIX
+
+
+
+/* Define what happens to the bare suffix-less functions, down to the sub-domain accuracy */
+#define OMXACAAC_SUFFIX BARE_SUFFIX
+#define OMXACMP3_SUFFIX BARE_SUFFIX
+#define OMXICJP_SUFFIX BARE_SUFFIX
+#define OMXIPBM_SUFFIX BARE_SUFFIX
+#define OMXIPCS_SUFFIX BARE_SUFFIX
+#define OMXIPPP_SUFFIX BARE_SUFFIX
+#define OMXSP_SUFFIX BARE_SUFFIX
+#define OMXVCCOMM_SUFFIX BARE_SUFFIX
+#define OMXVCM4P10_SUFFIX BARE_SUFFIX
+#define OMXVCM4P2_SUFFIX BARE_SUFFIX
+
+
+
+
+/* Define what the each bare, un-suffixed OpenMAX API function names is to be renamed */
+#define omxACAAC_DecodeChanPairElt OMXCATBAR(ACAAC_DecodeChanPairElt, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeDatStrElt OMXCATBAR(ACAAC_DecodeDatStrElt, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeFillElt OMXCATBAR(ACAAC_DecodeFillElt, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeIsStereo_S32 OMXCATBAR(ACAAC_DecodeIsStereo_S32, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeMsPNS_S32_I OMXCATBAR(ACAAC_DecodeMsPNS_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeMsStereo_S32_I OMXCATBAR(ACAAC_DecodeMsStereo_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodePrgCfgElt OMXCATBAR(ACAAC_DecodePrgCfgElt, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeTNS_S32_I OMXCATBAR(ACAAC_DecodeTNS_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_DeinterleaveSpectrum_S32 OMXCATBAR(ACAAC_DeinterleaveSpectrum_S32, OMXACAAC_SUFFIX)
+#define omxACAAC_EncodeTNS_S32_I OMXCATBAR(ACAAC_EncodeTNS_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_LongTermPredict_S32 OMXCATBAR(ACAAC_LongTermPredict_S32, OMXACAAC_SUFFIX)
+#define omxACAAC_LongTermReconstruct_S32_I OMXCATBAR(ACAAC_LongTermReconstruct_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_MDCTFwd_S32 OMXCATBAR(ACAAC_MDCTFwd_S32, OMXACAAC_SUFFIX)
+#define omxACAAC_MDCTInv_S32_S16 OMXCATBAR(ACAAC_MDCTInv_S32_S16, OMXACAAC_SUFFIX)
+#define omxACAAC_NoiselessDecode OMXCATBAR(ACAAC_NoiselessDecode, OMXACAAC_SUFFIX)
+#define omxACAAC_QuantInv_S32_I OMXCATBAR(ACAAC_QuantInv_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_UnpackADIFHeader OMXCATBAR(ACAAC_UnpackADIFHeader, OMXACAAC_SUFFIX)
+#define omxACAAC_UnpackADTSFrameHeader OMXCATBAR(ACAAC_UnpackADTSFrameHeader, OMXACAAC_SUFFIX)
+
+
+#define omxACMP3_HuffmanDecode_S32 OMXCATBAR(ACMP3_HuffmanDecode_S32, OMXACMP3_SUFFIX)
+#define omxACMP3_HuffmanDecodeSfb_S32 OMXCATBAR(ACMP3_HuffmanDecodeSfb_S32, OMXACMP3_SUFFIX)
+#define omxACMP3_HuffmanDecodeSfbMbp_S32 OMXCATBAR(ACMP3_HuffmanDecodeSfbMbp_S32, OMXACMP3_SUFFIX)
+#define omxACMP3_MDCTInv_S32 OMXCATBAR(ACMP3_MDCTInv_S32, OMXACMP3_SUFFIX)
+#define omxACMP3_ReQuantize_S32_I OMXCATBAR(ACMP3_ReQuantize_S32_I, OMXACMP3_SUFFIX)
+#define omxACMP3_ReQuantizeSfb_S32_I OMXCATBAR(ACMP3_ReQuantizeSfb_S32_I, OMXACMP3_SUFFIX)
+#define omxACMP3_SynthPQMF_S32_S16 OMXCATBAR(ACMP3_SynthPQMF_S32_S16, OMXACMP3_SUFFIX)
+#define omxACMP3_UnpackFrameHeader OMXCATBAR(ACMP3_UnpackFrameHeader, OMXACMP3_SUFFIX)
+#define omxACMP3_UnpackScaleFactors_S8 OMXCATBAR(ACMP3_UnpackScaleFactors_S8, OMXACMP3_SUFFIX)
+#define omxACMP3_UnpackSideInfo OMXCATBAR(ACMP3_UnpackSideInfo, OMXACMP3_SUFFIX)
+
+#define omxICJP_CopyExpand_U8_C3 OMXCATBAR(ICJP_CopyExpand_U8_C3, OMXICJP_SUFFIX)
+#define omxICJP_DCTFwd_S16 OMXCATBAR(ICJP_DCTFwd_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTFwd_S16_I OMXCATBAR(ICJP_DCTFwd_S16_I, OMXICJP_SUFFIX)
+#define omxICJP_DCTInv_S16 OMXCATBAR(ICJP_DCTInv_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTInv_S16_I OMXCATBAR(ICJP_DCTInv_S16_I, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantFwd_Multiple_S16 OMXCATBAR(ICJP_DCTQuantFwd_Multiple_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantFwd_S16 OMXCATBAR(ICJP_DCTQuantFwd_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantFwd_S16_I OMXCATBAR(ICJP_DCTQuantFwd_S16_I, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantFwdTableInit OMXCATBAR(ICJP_DCTQuantFwdTableInit, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantInv_Multiple_S16 OMXCATBAR(ICJP_DCTQuantInv_Multiple_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantInv_S16 OMXCATBAR(ICJP_DCTQuantInv_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantInv_S16_I OMXCATBAR(ICJP_DCTQuantInv_S16_I, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantInvTableInit OMXCATBAR(ICJP_DCTQuantInvTableInit, OMXICJP_SUFFIX)
+#define omxICJP_DecodeHuffman8x8_Direct_S16_C1 OMXCATBAR(ICJP_DecodeHuffman8x8_Direct_S16_C1, OMXICJP_SUFFIX)
+#define omxICJP_DecodeHuffmanSpecGetBufSize_U8 OMXCATBAR(ICJP_DecodeHuffmanSpecGetBufSize_U8, OMXICJP_SUFFIX)
+#define omxICJP_DecodeHuffmanSpecInit_U8 OMXCATBAR(ICJP_DecodeHuffmanSpecInit_U8, OMXICJP_SUFFIX)
+#define omxICJP_EncodeHuffman8x8_Direct_S16_U1_C1 OMXCATBAR(ICJP_EncodeHuffman8x8_Direct_S16_U1_C1, OMXICJP_SUFFIX)
+#define omxICJP_EncodeHuffmanSpecGetBufSize_U8 OMXCATBAR(ICJP_EncodeHuffmanSpecGetBufSize_U8, OMXICJP_SUFFIX)
+#define omxICJP_EncodeHuffmanSpecInit_U8 OMXCATBAR(ICJP_EncodeHuffmanSpecInit_U8, OMXICJP_SUFFIX)
+
+#define omxIPBM_AddC_U8_C1R_Sfs OMXCATBAR(IPBM_AddC_U8_C1R_Sfs, OMXIPBM_SUFFIX)
+#define omxIPBM_Copy_U8_C1R OMXCATBAR(IPBM_Copy_U8_C1R, OMXIPBM_SUFFIX)
+#define omxIPBM_Copy_U8_C3R OMXCATBAR(IPBM_Copy_U8_C3R, OMXIPBM_SUFFIX)
+#define omxIPBM_Mirror_U8_C1R OMXCATBAR(IPBM_Mirror_U8_C1R, OMXIPBM_SUFFIX)
+#define omxIPBM_MulC_U8_C1R_Sfs OMXCATBAR(IPBM_MulC_U8_C1R_Sfs, OMXIPBM_SUFFIX)
+
+#define omxIPCS_ColorTwistQ14_U8_C3R OMXCATBAR(IPCS_ColorTwistQ14_U8_C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR565ToYCbCr420LS_MCU_U16_S16_C3P3R OMXCATBAR(IPCS_BGR565ToYCbCr420LS_MCU_U16_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR565ToYCbCr422LS_MCU_U16_S16_C3P3R OMXCATBAR(IPCS_BGR565ToYCbCr422LS_MCU_U16_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR565ToYCbCr444LS_MCU_U16_S16_C3P3R OMXCATBAR(IPCS_BGR565ToYCbCr444LS_MCU_U16_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR888ToYCbCr420LS_MCU_U8_S16_C3P3R OMXCATBAR(IPCS_BGR888ToYCbCr420LS_MCU_U8_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR888ToYCbCr422LS_MCU_U8_S16_C3P3R OMXCATBAR(IPCS_BGR888ToYCbCr422LS_MCU_U8_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR888ToYCbCr444LS_MCU_U8_S16_C3P3R OMXCATBAR(IPCS_BGR888ToYCbCr444LS_MCU_U8_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420RszCscRotBGR_U8_P3C3R OMXCATBAR(IPCS_YCbCr420RszCscRotBGR_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420RszRot_U8_P3R OMXCATBAR(IPCS_YCbCr420RszRot_U8_P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420ToBGR565_U8_U16_P3C3R OMXCATBAR(IPCS_YCbCr420ToBGR565_U8_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420ToBGR565LS_MCU_S16_U16_P3C3R OMXCATBAR(IPCS_YCbCr420ToBGR565LS_MCU_S16_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420ToBGR888LS_MCU_S16_U8_P3C3R OMXCATBAR(IPCS_YCbCr420ToBGR888LS_MCU_S16_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422RszCscRotBGR_U8_P3C3R OMXCATBAR(IPCS_YCbCr422RszCscRotBGR_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_CbYCrY422RszCscRotBGR_U8_U16_C2R OMXCATBAR(IPCS_CbYCrY422RszCscRotBGR_U8_U16_C2R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422RszRot_U8_P3R OMXCATBAR(IPCS_YCbCr422RszRot_U8_P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbYCr422ToBGR565_U8_U16_C2C3R OMXCATBAR(IPCS_YCbYCr422ToBGR565_U8_U16_C2C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422ToBGR565LS_MCU_S16_U16_P3C3R OMXCATBAR(IPCS_YCbCr422ToBGR565LS_MCU_S16_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbYCr422ToBGR888_U8_C2C3R OMXCATBAR(IPCS_YCbYCr422ToBGR888_U8_C2C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422ToBGR888LS_MCU_S16_U8_P3C3R OMXCATBAR(IPCS_YCbCr422ToBGR888LS_MCU_S16_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422ToBGR888LS_MCU_S16_U8_P3C3R OMXCATBAR(IPCS_YCbCr422ToBGR888LS_MCU_S16_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_CbYCrY422ToYCbCr420Rotate_U8_C2P3R OMXCATBAR(IPCS_CbYCrY422ToYCbCr420Rotate_U8_C2P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422ToYCbCr420Rotate_U8_P3R OMXCATBAR(IPCS_YCbCr422ToYCbCr420Rotate_U8_P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr444ToBGR565_U8_U16_C3R OMXCATBAR(IPCS_YCbCr444ToBGR565_U8_U16_C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr444ToBGR565_U8_U16_P3C3R OMXCATBAR(IPCS_YCbCr444ToBGR565_U8_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr444ToBGR565LS_MCU_S16_U16_P3C3R OMXCATBAR(IPCS_YCbCr444ToBGR565LS_MCU_S16_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr444ToBGR888_U8_C3R OMXCATBAR(IPCS_YCbCr444ToBGR888_U8_C3R, OMXIPCS_SUFFIX)
+
+#define omxIPPP_Deblock_HorEdge_U8_I OMXCATBAR(IPPP_Deblock_HorEdge_U8_I, OMXIPPP_SUFFIX)
+#define omxIPPP_Deblock_VerEdge_U8_I OMXCATBAR(IPPP_Deblock_VerEdge_U8_I, OMXIPPP_SUFFIX)
+#define omxIPPP_FilterFIR_U8_C1R OMXCATBAR(IPPP_FilterFIR_U8_C1R, OMXIPPP_SUFFIX)
+#define omxIPPP_FilterMedian_U8_C1R OMXCATBAR(IPPP_FilterMedian_U8_C1R, OMXIPPP_SUFFIX)
+#define omxIPPP_GetCentralMoment_S64 OMXCATBAR(IPPP_GetCentralMoment_S64, OMXIPPP_SUFFIX)
+#define omxIPPP_GetSpatialMoment_S64 OMXCATBAR(IPPP_GetSpatialMoment_S64, OMXIPPP_SUFFIX)
+#define omxIPPP_MomentGetStateSize OMXCATBAR(IPPP_MomentGetStateSize, OMXIPPP_SUFFIX)
+#define omxIPPP_MomentInit OMXCATBAR(IPPP_MomentInit, OMXIPPP_SUFFIX)
+#define omxIPPP_Moments_U8_C1R OMXCATBAR(IPPP_Moments_U8_C1R, OMXIPPP_SUFFIX)
+#define omxIPPP_Moments_U8_C3R OMXCATBAR(IPPP_Moments_U8_C3R, OMXIPPP_SUFFIX)
+
+#define omxSP_BlockExp_S16 OMXCATBAR(SP_BlockExp_S16, OMXSP_SUFFIX)
+#define omxSP_BlockExp_S32 OMXCATBAR(SP_BlockExp_S32, OMXSP_SUFFIX)
+#define omxSP_Copy_S16 OMXCATBAR(SP_Copy_S16, OMXSP_SUFFIX)
+#define omxSP_DotProd_S16 OMXCATBAR(SP_DotProd_S16, OMXSP_SUFFIX)
+#define omxSP_DotProd_S16_Sfs OMXCATBAR(SP_DotProd_S16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTFwd_CToC_SC16_Sfs OMXCATBAR(SP_FFTFwd_CToC_SC16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTFwd_CToC_SC32_Sfs OMXCATBAR(SP_FFTFwd_CToC_SC32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTFwd_RToCCS_S16S32_Sfs OMXCATBAR(SP_FFTFwd_RToCCS_S16S32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTFwd_RToCCS_S32_Sfs OMXCATBAR(SP_FFTFwd_RToCCS_S32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTGetBufSize_C_SC16 OMXCATBAR(SP_FFTGetBufSize_C_SC16, OMXSP_SUFFIX)
+#define omxSP_FFTGetBufSize_C_SC32 OMXCATBAR(SP_FFTGetBufSize_C_SC32, OMXSP_SUFFIX)
+#define omxSP_FFTGetBufSize_R_S16S32 OMXCATBAR(SP_FFTGetBufSize_R_S16S32, OMXSP_SUFFIX)
+#define omxSP_FFTGetBufSize_R_S32 OMXCATBAR(SP_FFTGetBufSize_R_S32, OMXSP_SUFFIX)
+#define omxSP_FFTInit_C_SC16 OMXCATBAR(SP_FFTInit_C_SC16, OMXSP_SUFFIX)
+#define omxSP_FFTInit_C_SC32 OMXCATBAR(SP_FFTInit_C_SC32, OMXSP_SUFFIX)
+#define omxSP_FFTInit_R_S16S32 OMXCATBAR(SP_FFTInit_R_S16S32, OMXSP_SUFFIX)
+#define omxSP_FFTInit_R_S32 OMXCATBAR(SP_FFTInit_R_S32, OMXSP_SUFFIX)
+#define omxSP_FFTInv_CCSToR_S32_Sfs OMXCATBAR(SP_FFTInv_CCSToR_S32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTInv_CCSToR_S32S16_Sfs OMXCATBAR(SP_FFTInv_CCSToR_S32S16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTInv_CToC_SC16_Sfs OMXCATBAR(SP_FFTInv_CToC_SC16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTInv_CToC_SC32_Sfs OMXCATBAR(SP_FFTInv_CToC_SC32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FilterMedian_S32 OMXCATBAR(SP_FilterMedian_S32, OMXSP_SUFFIX)
+#define omxSP_FilterMedian_S32_I OMXCATBAR(SP_FilterMedian_S32_I, OMXSP_SUFFIX)
+#define omxSP_FIR_Direct_S16 OMXCATBAR(SP_FIR_Direct_S16, OMXSP_SUFFIX)
+#define omxSP_FIR_Direct_S16_I OMXCATBAR(SP_FIR_Direct_S16_I, OMXSP_SUFFIX)
+#define omxSP_FIR_Direct_S16_ISfs OMXCATBAR(SP_FIR_Direct_S16_ISfs, OMXSP_SUFFIX)
+#define omxSP_FIR_Direct_S16_Sfs OMXCATBAR(SP_FIR_Direct_S16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FIROne_Direct_S16 OMXCATBAR(SP_FIROne_Direct_S16, OMXSP_SUFFIX)
+#define omxSP_FIROne_Direct_S16_I OMXCATBAR(SP_FIROne_Direct_S16_I, OMXSP_SUFFIX)
+#define omxSP_FIROne_Direct_S16_ISfs OMXCATBAR(SP_FIROne_Direct_S16_ISfs, OMXSP_SUFFIX)
+#define omxSP_FIROne_Direct_S16_Sfs OMXCATBAR(SP_FIROne_Direct_S16_Sfs, OMXSP_SUFFIX)
+#define omxSP_IIR_BiQuadDirect_S16 OMXCATBAR(SP_IIR_BiQuadDirect_S16, OMXSP_SUFFIX)
+#define omxSP_IIR_BiQuadDirect_S16_I OMXCATBAR(SP_IIR_BiQuadDirect_S16_I, OMXSP_SUFFIX)
+#define omxSP_IIR_Direct_S16 OMXCATBAR(SP_IIR_Direct_S16, OMXSP_SUFFIX)
+#define omxSP_IIR_Direct_S16_I OMXCATBAR(SP_IIR_Direct_S16_I, OMXSP_SUFFIX)
+#define omxSP_IIROne_BiQuadDirect_S16 OMXCATBAR(SP_IIROne_BiQuadDirect_S16, OMXSP_SUFFIX)
+#define omxSP_IIROne_BiQuadDirect_S16_I OMXCATBAR(SP_IIROne_BiQuadDirect_S16_I, OMXSP_SUFFIX)
+#define omxSP_IIROne_Direct_S16 OMXCATBAR(SP_IIROne_Direct_S16, OMXSP_SUFFIX)
+#define omxSP_IIROne_Direct_S16_I OMXCATBAR(SP_IIROne_Direct_S16_I, OMXSP_SUFFIX)
+
+#define omxVCCOMM_Average_16x OMXCATBAR(VCCOMM_Average_16x, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_Average_8x OMXCATBAR(VCCOMM_Average_8x, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_ComputeTextureErrorBlock OMXCATBAR(VCCOMM_ComputeTextureErrorBlock, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_ComputeTextureErrorBlock_SAD OMXCATBAR(VCCOMM_ComputeTextureErrorBlock_SAD, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_Copy16x16 OMXCATBAR(VCCOMM_Copy16x16, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_Copy8x8 OMXCATBAR(VCCOMM_Copy8x8, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_ExpandFrame_I OMXCATBAR(VCCOMM_ExpandFrame_I, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_LimitMVToRect OMXCATBAR(VCCOMM_LimitMVToRect, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_SAD_16x OMXCATBAR(VCCOMM_SAD_16x, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_SAD_8x OMXCATBAR(VCCOMM_SAD_8x, OMXVCCOMM_SUFFIX)
+
+#define omxVCM4P10_Average_4x OMXCATBAR(VCM4P10_Average_4x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_BlockMatch_Half OMXCATBAR(VCM4P10_BlockMatch_Half, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_BlockMatch_Integer OMXCATBAR(VCM4P10_BlockMatch_Integer, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_BlockMatch_Quarter OMXCATBAR(VCM4P10_BlockMatch_Quarter, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DeblockChroma_I OMXCATBAR(VCM4P10_DeblockChroma_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DeblockLuma_I OMXCATBAR(VCM4P10_DeblockLuma_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC OMXCATBAR(VCM4P10_DecodeChromaDcCoeffsToPairCAVLC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DecodeCoeffsToPairCAVLC OMXCATBAR(VCM4P10_DecodeCoeffsToPairCAVLC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DequantTransformResidualFromPairAndAdd OMXCATBAR(VCM4P10_DequantTransformResidualFromPairAndAdd, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_FilterDeblockingChroma_HorEdge_I OMXCATBAR(VCM4P10_FilterDeblockingChroma_HorEdge_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_FilterDeblockingChroma_VerEdge_I OMXCATBAR(VCM4P10_FilterDeblockingChroma_VerEdge_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_FilterDeblockingLuma_HorEdge_I OMXCATBAR(VCM4P10_FilterDeblockingLuma_HorEdge_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_FilterDeblockingLuma_VerEdge_I OMXCATBAR(VCM4P10_FilterDeblockingLuma_VerEdge_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_GetVLCInfo OMXCATBAR(VCM4P10_GetVLCInfo, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InterpolateChroma OMXCATBAR(VCM4P10_InterpolateChroma, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InterpolateHalfHor_Luma OMXCATBAR(VCM4P10_InterpolateHalfHor_Luma, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InterpolateHalfVer_Luma OMXCATBAR(VCM4P10_InterpolateHalfVer_Luma, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InterpolateLuma OMXCATBAR(VCM4P10_InterpolateLuma, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InvTransformDequant_ChromaDC OMXCATBAR(VCM4P10_InvTransformDequant_ChromaDC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InvTransformDequant_LumaDC OMXCATBAR(VCM4P10_InvTransformDequant_LumaDC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InvTransformResidualAndAdd OMXCATBAR(VCM4P10_InvTransformResidualAndAdd, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_MEGetBufSize OMXCATBAR(VCM4P10_MEGetBufSize, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_MEInit OMXCATBAR(VCM4P10_MEInit, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_MotionEstimationMB OMXCATBAR(VCM4P10_MotionEstimationMB, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_PredictIntra_16x16 OMXCATBAR(VCM4P10_PredictIntra_16x16, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_PredictIntra_4x4 OMXCATBAR(VCM4P10_PredictIntra_4x4, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_PredictIntraChroma_8x8 OMXCATBAR(VCM4P10_PredictIntraChroma_8x8, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SAD_4x OMXCATBAR(VCM4P10_SAD_4x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SADQuar_16x OMXCATBAR(VCM4P10_SADQuar_16x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SADQuar_4x OMXCATBAR(VCM4P10_SADQuar_4x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SADQuar_8x OMXCATBAR(VCM4P10_SADQuar_8x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SATD_4x4 OMXCATBAR(VCM4P10_SATD_4x4, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SubAndTransformQDQResidual OMXCATBAR(VCM4P10_SubAndTransformQDQResidual, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_TransformDequantChromaDCFromPair OMXCATBAR(VCM4P10_TransformDequantChromaDCFromPair, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_TransformDequantLumaDCFromPair OMXCATBAR(VCM4P10_TransformDequantLumaDCFromPair, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_TransformQuant_ChromaDC OMXCATBAR(VCM4P10_TransformQuant_ChromaDC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_TransformQuant_LumaDC OMXCATBAR(VCM4P10_TransformQuant_LumaDC, OMXVCM4P10_SUFFIX)
+
+#define omxVCM4P2_BlockMatch_Half_16x16 OMXCATBAR(VCM4P2_BlockMatch_Half_16x16, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_BlockMatch_Half_8x8 OMXCATBAR(VCM4P2_BlockMatch_Half_8x8, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_BlockMatch_Integer_16x16 OMXCATBAR(VCM4P2_BlockMatch_Integer_16x16, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_BlockMatch_Integer_8x8 OMXCATBAR(VCM4P2_BlockMatch_Integer_8x8, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DCT8x8blk OMXCATBAR(VCM4P2_DCT8x8blk, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeBlockCoef_Inter OMXCATBAR(VCM4P2_DecodeBlockCoef_Inter, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeBlockCoef_Intra OMXCATBAR(VCM4P2_DecodeBlockCoef_Intra, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodePadMV_PVOP OMXCATBAR(VCM4P2_DecodePadMV_PVOP, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeVLCZigzag_Inter OMXCATBAR(VCM4P2_DecodeVLCZigzag_Inter, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeVLCZigzag_IntraACVLC OMXCATBAR(VCM4P2_DecodeVLCZigzag_IntraACVLC, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeVLCZigzag_IntraDCVLC OMXCATBAR(VCM4P2_DecodeVLCZigzag_IntraDCVLC, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_EncodeMV OMXCATBAR(VCM4P2_EncodeMV, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_EncodeVLCZigzag_Inter OMXCATBAR(VCM4P2_EncodeVLCZigzag_Inter, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_EncodeVLCZigzag_IntraACVLC OMXCATBAR(VCM4P2_EncodeVLCZigzag_IntraACVLC, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_EncodeVLCZigzag_IntraDCVLC OMXCATBAR(VCM4P2_EncodeVLCZigzag_IntraDCVLC, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_FindMVpred OMXCATBAR(VCM4P2_FindMVpred, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_IDCT8x8blk OMXCATBAR(VCM4P2_IDCT8x8blk, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_MCReconBlock OMXCATBAR(VCM4P2_MCReconBlock, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_MEGetBufSize OMXCATBAR(VCM4P2_MEGetBufSize, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_MEInit OMXCATBAR(VCM4P2_MEInit, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_MotionEstimationMB OMXCATBAR(VCM4P2_MotionEstimationMB, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_PredictReconCoefIntra OMXCATBAR(VCM4P2_PredictReconCoefIntra, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_QuantInter_I OMXCATBAR(VCM4P2_QuantInter_I, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_QuantIntra_I OMXCATBAR(VCM4P2_QuantIntra_I, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_QuantInvInter_I OMXCATBAR(VCM4P2_QuantInvInter_I, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_QuantInvIntra_I OMXCATBAR(VCM4P2_QuantInvIntra_I, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_TransRecBlockCoef_inter OMXCATBAR(VCM4P2_TransRecBlockCoef_inter, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_TransRecBlockCoef_intra OMXCATBAR(VCM4P2_TransRecBlockCoef_intra, OMXVCM4P2_SUFFIX)
+
+
+#endif /* _armOMX_h_ */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes.h
new file mode 100644
index 0000000..8b295a6
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes.h
@@ -0,0 +1,252 @@
+/**
+ * File: omxtypes.h
+ * Brief: Defines basic Data types used in OpenMAX v1.0.2 header files.
+ *
+ * Copyright © 2005-2008 The Khronos Group Inc. All Rights Reserved.
+ *
+ * These materials are protected by copyright laws and contain material
+ * proprietary to the Khronos Group, Inc. You may use these materials
+ * for implementing Khronos specifications, without altering or removing
+ * any trademark, copyright or other notice from the specification.
+ *
+ * Khronos Group makes no, and expressly disclaims any, representations
+ * or warranties, express or implied, regarding these materials, including,
+ * without limitation, any implied warranties of merchantability or fitness
+ * for a particular purpose or non-infringement of any intellectual property.
+ * Khronos Group makes no, and expressly disclaims any, warranties, express
+ * or implied, regarding the correctness, accuracy, completeness, timeliness,
+ * and reliability of these materials.
+ *
+ * Under no circumstances will the Khronos Group, or any of its Promoters,
+ * Contributors or Members or their respective partners, officers, directors,
+ * employees, agents or representatives be liable for any damages, whether
+ * direct, indirect, special or consequential damages for lost revenues,
+ * lost profits, or otherwise, arising from or in connection with these
+ * materials.
+ *
+ * Khronos and OpenMAX are trademarks of the Khronos Group Inc.
+ *
+ */
+
+#ifndef _OMXTYPES_H_
+#define _OMXTYPES_H_
+
+#include <limits.h>
+
+#define OMX_IN
+#define OMX_OUT
+#define OMX_INOUT
+
+
+typedef enum {
+
+ /* Mandatory return codes - use cases are explicitly described for each function */
+ OMX_Sts_NoErr = 0, /* No error, the function completed successfully */
+ OMX_Sts_Err = -2, /* Unknown/unspecified error */
+ OMX_Sts_InvalidBitstreamValErr = -182, /* Invalid value detected during bitstream processing */
+ OMX_Sts_MemAllocErr = -9, /* Not enough memory allocated for the operation */
+ OMX_StsACAAC_GainCtrErr = -159, /* AAC: Unsupported gain control data detected */
+ OMX_StsACAAC_PrgNumErr = -167, /* AAC: Invalid number of elements for one program */
+ OMX_StsACAAC_CoefValErr = -163, /* AAC: Invalid quantized coefficient value */
+ OMX_StsACAAC_MaxSfbErr = -162, /* AAC: Invalid maxSfb value in relation to numSwb */
+ OMX_StsACAAC_PlsDataErr = -160, /* AAC: pulse escape sequence data error */
+
+ /* Optional return codes - use cases are explicitly described for each function*/
+ OMX_Sts_BadArgErr = -5, /* Bad Arguments */
+
+ OMX_StsACAAC_TnsNumFiltErr = -157, /* AAC: Invalid number of TNS filters */
+ OMX_StsACAAC_TnsLenErr = -156, /* AAC: Invalid TNS region length */
+ OMX_StsACAAC_TnsOrderErr = -155, /* AAC: Invalid order of TNS filter */
+ OMX_StsACAAC_TnsCoefResErr = -154, /* AAC: Invalid bit-resolution for TNS filter coefficients */
+ OMX_StsACAAC_TnsCoefErr = -153, /* AAC: Invalid TNS filter coefficients */
+ OMX_StsACAAC_TnsDirectErr = -152, /* AAC: Invalid TNS filter direction */
+
+ OMX_StsICJP_JPEGMarkerErr = -183, /* JPEG marker encountered within an entropy-coded block; */
+ /* Huffman decoding operation terminated early. */
+ OMX_StsICJP_JPEGMarker = -181, /* JPEG marker encountered; Huffman decoding */
+ /* operation terminated early. */
+ OMX_StsIPPP_ContextMatchErr = -17, /* Context parameter doesn't match to the operation */
+
+ OMX_StsSP_EvenMedianMaskSizeErr = -180, /* Even size of the Median Filter mask was replaced by the odd one */
+
+ OMX_Sts_MaximumEnumeration = INT_MAX /*Placeholder, forces enum of size OMX_INT*/
+
+ } OMXResult; /** Return value or error value returned from a function. Identical to OMX_INT */
+
+
+/* OMX_U8 */
+#if UCHAR_MAX == 0xff
+typedef unsigned char OMX_U8;
+#elif USHRT_MAX == 0xff
+typedef unsigned short int OMX_U8;
+#else
+#error OMX_U8 undefined
+#endif
+
+
+/* OMX_S8 */
+#if SCHAR_MAX == 0x7f
+typedef signed char OMX_S8;
+#elif SHRT_MAX == 0x7f
+typedef signed short int OMX_S8;
+#else
+#error OMX_S8 undefined
+#endif
+
+
+/* OMX_U16 */
+#if USHRT_MAX == 0xffff
+typedef unsigned short int OMX_U16;
+#elif UINT_MAX == 0xffff
+typedef unsigned int OMX_U16;
+#else
+#error OMX_U16 undefined
+#endif
+
+
+/* OMX_S16 */
+#if SHRT_MAX == 0x7fff
+typedef signed short int OMX_S16;
+#elif INT_MAX == 0x7fff
+typedef signed int OMX_S16;
+#else
+#error OMX_S16 undefined
+#endif
+
+
+/* OMX_U32 */
+#if UINT_MAX == 0xffffffff
+typedef unsigned int OMX_U32;
+#elif LONG_MAX == 0xffffffff
+typedef unsigned long int OMX_U32;
+#else
+#error OMX_U32 undefined
+#endif
+
+
+/* OMX_S32 */
+#if INT_MAX == 0x7fffffff
+typedef signed int OMX_S32;
+#elif LONG_MAX == 0x7fffffff
+typedef long signed int OMX_S32;
+#else
+#error OMX_S32 undefined
+#endif
+
+
+/* OMX_U64 & OMX_S64 */
+#if defined( _WIN32 ) || defined ( _WIN64 )
+ typedef __int64 OMX_S64; /** Signed 64-bit integer */
+ typedef unsigned __int64 OMX_U64; /** Unsigned 64-bit integer */
+ #define OMX_MIN_S64 (0x8000000000000000i64)
+ #define OMX_MIN_U64 (0x0000000000000000i64)
+ #define OMX_MAX_S64 (0x7FFFFFFFFFFFFFFFi64)
+ #define OMX_MAX_U64 (0xFFFFFFFFFFFFFFFFi64)
+#else
+ typedef long long OMX_S64; /** Signed 64-bit integer */
+ typedef unsigned long long OMX_U64; /** Unsigned 64-bit integer */
+ #define OMX_MIN_S64 (0x8000000000000000LL)
+ #define OMX_MIN_U64 (0x0000000000000000LL)
+ #define OMX_MAX_S64 (0x7FFFFFFFFFFFFFFFLL)
+ #define OMX_MAX_U64 (0xFFFFFFFFFFFFFFFFLL)
+#endif
+
+
+/* OMX_SC8 */
+typedef struct
+{
+ OMX_S8 Re; /** Real part */
+ OMX_S8 Im; /** Imaginary part */
+
+} OMX_SC8; /** Signed 8-bit complex number */
+
+
+/* OMX_SC16 */
+typedef struct
+{
+ OMX_S16 Re; /** Real part */
+ OMX_S16 Im; /** Imaginary part */
+
+} OMX_SC16; /** Signed 16-bit complex number */
+
+
+/* OMX_SC32 */
+typedef struct
+{
+ OMX_S32 Re; /** Real part */
+ OMX_S32 Im; /** Imaginary part */
+
+} OMX_SC32; /** Signed 32-bit complex number */
+
+
+/* OMX_SC64 */
+typedef struct
+{
+ OMX_S64 Re; /** Real part */
+ OMX_S64 Im; /** Imaginary part */
+
+} OMX_SC64; /** Signed 64-bit complex number */
+
+
+/* OMX_F32 */
+typedef float OMX_F32; /** Single precision floating point,IEEE 754 */
+
+
+/* OMX_F64 */
+typedef double OMX_F64; /** Double precision floating point,IEEE 754 */
+
+
+/* OMX_INT */
+typedef int OMX_INT; /** signed integer corresponding to machine word length, has maximum signed value INT_MAX*/
+
+
+#define OMX_MIN_S8 (-128)
+#define OMX_MIN_U8 0
+#define OMX_MIN_S16 (-32768)
+#define OMX_MIN_U16 0
+#define OMX_MIN_S32 (-2147483647-1)
+#define OMX_MIN_U32 0
+
+#define OMX_MAX_S8 (127)
+#define OMX_MAX_U8 (255)
+#define OMX_MAX_S16 (32767)
+#define OMX_MAX_U16 (0xFFFF)
+#define OMX_MAX_S32 (2147483647)
+#define OMX_MAX_U32 (0xFFFFFFFF)
+
+typedef void OMXVoid;
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+/** Defines the geometric position and size of a rectangle,
+ * where x,y defines the coordinates of the top left corner
+ * of the rectangle, with dimensions width in the x-direction
+ * and height in the y-direction */
+typedef struct {
+ OMX_INT x; /** x-coordinate of top left corner of rectangle */
+ OMX_INT y; /** y-coordinate of top left corner of rectangle */
+ OMX_INT width; /** Width in the x-direction. */
+ OMX_INT height; /** Height in the y-direction. */
+}OMXRect;
+
+
+/** Defines the geometric position of a point, */
+typedef struct
+{
+ OMX_INT x; /** x-coordinate */
+ OMX_INT y; /** y-coordinate */
+
+} OMXPoint;
+
+
+/** Defines the dimensions of a rectangle, or region of interest in an image */
+typedef struct
+{
+ OMX_INT width; /** Width of the rectangle, in the x-direction */
+ OMX_INT height; /** Height of the rectangle, in the y-direction */
+
+} OMXSize;
+
+#endif /* _OMXTYPES_H_ */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes_s.h
new file mode 100644
index 0000000..8d24b65
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/api/omxtypes_s.h
@@ -0,0 +1,77 @@
+;//
+;//
+;// File Name: omxtypes_s.h
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+;// Mandatory return codes - use cases are explicitly described for each function
+OMX_Sts_NoErr EQU 0 ;// No error the function completed successfully
+OMX_Sts_Err EQU -2 ;// Unknown/unspecified error
+OMX_Sts_InvalidBitstreamValErr EQU -182 ;// Invalid value detected during bitstream processing
+OMX_Sts_MemAllocErr EQU -9 ;// Not enough memory allocated for the operation
+OMX_StsACAAC_GainCtrErr EQU -159 ;// AAC: Unsupported gain control data detected
+OMX_StsACAAC_PrgNumErr EQU -167 ;// AAC: Invalid number of elements for one program
+OMX_StsACAAC_CoefValErr EQU -163 ;// AAC: Invalid quantized coefficient value
+OMX_StsACAAC_MaxSfbErr EQU -162 ;// AAC: Invalid maxSfb value in relation to numSwb
+OMX_StsACAAC_PlsDataErr EQU -160 ;// AAC: pulse escape sequence data error
+
+;// Optional return codes - use cases are explicitly described for each function
+OMX_Sts_BadArgErr EQU -5 ;// Bad Arguments
+
+OMX_StsACAAC_TnsNumFiltErr EQU -157 ;// AAC: Invalid number of TNS filters
+OMX_StsACAAC_TnsLenErr EQU -156 ;// AAC: Invalid TNS region length
+OMX_StsACAAC_TnsOrderErr EQU -155 ;// AAC: Invalid order of TNS filter
+OMX_StsACAAC_TnsCoefResErr EQU -154 ;// AAC: Invalid bit-resolution for TNS filter coefficients
+OMX_StsACAAC_TnsCoefErr EQU -153 ;// AAC: Invalid TNS filter coefficients
+OMX_StsACAAC_TnsDirectErr EQU -152 ;// AAC: Invalid TNS filter direction
+
+OMX_StsICJP_JPEGMarkerErr EQU -183 ;// JPEG marker encountered within an entropy-coded block;
+ ;// Huffman decoding operation terminated early.
+OMX_StsICJP_JPEGMarker EQU -181 ;// JPEG marker encountered; Huffman decoding
+ ;// operation terminated early.
+OMX_StsIPPP_ContextMatchErr EQU -17 ;// Context parameter doesn't match to the operation
+
+OMX_StsSP_EvenMedianMaskSizeErr EQU -180 ;// Even size of the Median Filter mask was replaced by the odd one
+
+OMX_Sts_MaximumEnumeration EQU 0x7FFFFFFF
+
+
+
+OMX_MIN_S8 EQU (-128)
+OMX_MIN_U8 EQU 0
+OMX_MIN_S16 EQU (-32768)
+OMX_MIN_U16 EQU 0
+
+
+OMX_MIN_S32 EQU (-2147483647-1)
+OMX_MIN_U32 EQU 0
+
+OMX_MAX_S8 EQU (127)
+OMX_MAX_U8 EQU (255)
+OMX_MAX_S16 EQU (32767)
+OMX_MAX_U16 EQU (0xFFFF)
+OMX_MAX_S32 EQU (2147483647)
+OMX_MAX_U32 EQU (0xFFFFFFFF)
+
+OMX_VC_UPPER EQU 0x1 ;// Used by the PredictIntra functions
+OMX_VC_LEFT EQU 0x2 ;// Used by the PredictIntra functions
+OMX_VC_UPPER_RIGHT EQU 0x40 ;// Used by the PredictIntra functions
+
+NULL EQU 0
+
+;// Structures
+
+ INCLUDE armCOMM_s.h
+
+ M_STRUCT OMXPoint
+ M_FIELD x, 4
+ M_FIELD y, 4
+ M_ENDSTRUCT
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/build_vc.pl b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/build_vc.pl
new file mode 100755
index 0000000..1ae7005
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/build_vc.pl
@@ -0,0 +1,111 @@
+#!/usr/bin/perl
+#
+#
+# File Name: build_vc.pl
+# OpenMAX DL: v1.0.2
+# Revision: 9641
+# Date: Thursday, February 7, 2008
+#
+# (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+#
+#
+#
+# This file builds the OpenMAX DL vc domain library omxVC.o.
+#
+
+use File::Spec;
+use strict;
+
+my ($CC, $CC_OPTS, $AS, $AS_OPTS, $LIB, $LIB_OPTS, $LIB_TYPE);
+
+$CC = 'armcc';
+$CC_OPTS = '--no_unaligned_access --cpu ARM1136J-S -c';
+$AS = 'armasm';
+$AS_OPTS = '--no_unaligned_access --cpu ARM1136J-S';
+# $LIB = 'armlink';
+# $LIB_OPTS = '--partial -o';
+# $LIB_TYPE = '.o';
+$LIB = 'armar';
+$LIB_OPTS = '--create -r';
+$LIB_TYPE = '.a';
+
+#------------------------
+
+my (@headerlist, @filelist, $hd, $file, $ofile, $command, $objlist, $libfile, $h);
+
+# Define the list of directories containing included header files.
+@headerlist = qw(api vc/api vc/m4p2/api vc/m4p10/api);
+
+# Define the list of source files to compile.
+open(FILES, '<filelist_vc.txt') or die("Can't open source file list\n");
+@filelist = <FILES>;
+close(FILES);
+
+# Fix the file separators in the header paths
+foreach $h (@headerlist)
+{
+ $h = File::Spec->canonpath($h);
+}
+
+# Create the include path to be passed to the compiler
+$hd = '-I' . join(' -I', @headerlist);
+
+# Create the build directories "/lib/" and "/obj/" (if they are not there already)
+mkdir "obj", 0777 if (! -d "obj");
+mkdir "lib", 0777 if (! -d "lib");
+
+$objlist = '';
+
+# Compile each file
+foreach $file (@filelist)
+{
+ my $f;
+ my $base;
+ my $ext;
+ my $objfile;
+
+ chomp($file);
+ $file = File::Spec->canonpath($file);
+
+ (undef, undef, $f) = File::Spec->splitpath($file);
+ if(($base, $ext) = $f =~ /(.+)\.(\w)$/)
+ {
+ $objfile = File::Spec->catfile('obj', $base.'.o');
+
+ if($ext eq 'c')
+ {
+ $objlist .= "$objfile ";
+ $command = $CC.' '.$CC_OPTS.' '.$hd.' -o '.$objfile.' '.$file;
+ print "$command\n";
+ system($command);
+ }
+ elsif($ext eq 's')
+ {
+ $objlist .= "$objfile ";
+ $command = $AS.' '.$AS_OPTS.' '.$hd.' -o '.$objfile.' '.$file;
+ print "$command\n";
+ system($command);
+ }
+ else
+ {
+ print "Ignoring file: $f\n";
+ }
+ }
+ else
+ {
+ die "No file extension found: $f\n";
+ }
+}
+
+# Do the final link stage to create the libraries.
+$libfile = File::Spec->catfile('lib', 'omxVC'.$LIB_TYPE);
+$command = $LIB.' '.$LIB_OPTS.' '.$libfile.' '.$objlist;
+print "$command\n";
+(system($command) == 0) and print "Build successful\n";
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/filelist_vc.txt b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/filelist_vc.txt
new file mode 100644
index 0000000..0f1623f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/filelist_vc.txt
@@ -0,0 +1,74 @@
+./api/armCOMM.h
+./api/armCOMM_BitDec_s.h
+./api/armCOMM_Bitstream.h
+./api/armCOMM_IDCT_s.h
+./api/armCOMM_IDCTTable.h
+./api/armCOMM_MaskTable.h
+./api/armCOMM_s.h
+./api/armCOMM_Version.h
+./api/armOMX_ReleaseVersion.h
+./api/omxtypes.h
+./api/omxtypes_s.h
+./src/armCOMM_IDCTTable.c
+./src/armCOMM_MaskTable.c
+./vc/api/armVC.h
+./vc/api/armVCCOMM_s.h
+./vc/api/omxVC.h
+./vc/api/omxVC_s.h
+./vc/comm/src/omxVCCOMM_Copy16x16_s.s
+./vc/comm/src/omxVCCOMM_Copy8x8_s.s
+./vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
+./vc/m4p10/api/armVCM4P10_CAVLCTables.h
+./vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_CAVLCTables.c
+./vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
+./vc/m4p10/src/armVCM4P10_DequantTables_s.s
+./vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_QuantTables_s.s
+./vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
+./vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
+./vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
+./vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
+./vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
+./vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
+./vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
+./vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
+./vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
+./vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
+./vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
+./vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
+./vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
+./vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
+./vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
+./vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
+./vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
+./vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
+./vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
+./vc/m4p2/src/armVCM4P2_Clip8_s.s
+./vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
+./vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
+./vc/m4p2/src/armVCM4P2_Lookup_Tables.c
+./vc/m4p2/src/armVCM4P2_SetPredDir_s.s
+./vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
+./vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
+./vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
+./vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
+./vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
+./vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
+./vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
+./vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
+./vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
+./vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
+./vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
+./vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
+./vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
+./vc/src/armVC_Version.c \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM.c
new file mode 100644
index 0000000..e572a89
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM.c
@@ -0,0 +1,936 @@
+/**
+ *
+ * File Name: armCOMM.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Defines Common APIs used across OpenMAX API's
+ */
+
+#include "omxtypes.h"
+#include "armCOMM.h"
+
+/***********************************************************************/
+ /* Miscellaneous Arithmetic operations */
+
+/**
+ * Function: armRoundFloatToS16
+ *
+ * Description:
+ * Converts a double precision value into a short int after rounding
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S16 format
+ *
+ */
+
+OMX_S16 armRoundFloatToS16 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ return (OMX_S16)(Value + .5);
+ }
+ else
+ {
+ return (OMX_S16)(Value - .5);
+ }
+}
+
+/**
+ * Function: armRoundFloatToS32
+ *
+ * Description:
+ * Converts a double precision value into a int after rounding
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S32 format
+ *
+ */
+
+OMX_S32 armRoundFloatToS32 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ return (OMX_S32)(Value + .5);
+ }
+ else
+ {
+ return (OMX_S32)(Value - .5);
+ }
+}
+/**
+ * Function: armSatRoundFloatToS16
+ *
+ * Description:
+ * Converts a double precision value into a short int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S16 format
+ *
+ */
+
+OMX_S16 armSatRoundFloatToS16 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ Value += 0.5;
+
+ if(Value > (OMX_S16)OMX_MAX_S16 )
+ {
+ return (OMX_S16)OMX_MAX_S16;
+ }
+ else
+ {
+ return (OMX_S16)Value;
+ }
+ }
+ else
+ {
+ Value -= 0.5;
+
+ if(Value < (OMX_S16)OMX_MIN_S16 )
+ {
+ return (OMX_S16)OMX_MIN_S16;
+ }
+ else
+ {
+ return (OMX_S16)Value;
+ }
+ }
+}
+
+/**
+ * Function: armSatRoundFloatToS32
+ *
+ * Description:
+ * Converts a double precision value into a int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S32 format
+ *
+ */
+
+OMX_S32 armSatRoundFloatToS32 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ Value += 0.5;
+
+ if(Value > (OMX_S32)OMX_MAX_S32 )
+ {
+ return (OMX_S32)OMX_MAX_S32;
+ }
+ else
+ {
+ return (OMX_S32)Value;
+ }
+ }
+ else
+ {
+ Value -= 0.5;
+
+ if(Value < (OMX_S32)OMX_MIN_S32 )
+ {
+ return (OMX_S32)OMX_MIN_S32;
+ }
+ else
+ {
+ return (OMX_S32)Value;
+ }
+ }
+}
+
+/**
+ * Function: armSatRoundFloatToU16
+ *
+ * Description:
+ * Converts a double precision value into a unsigned short int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_U16 format
+ *
+ */
+
+OMX_U16 armSatRoundFloatToU16 (OMX_F64 Value)
+{
+ Value += 0.5;
+
+ if(Value > (OMX_U16)OMX_MAX_U16 )
+ {
+ return (OMX_U16)OMX_MAX_U16;
+ }
+ else
+ {
+ return (OMX_U16)Value;
+ }
+}
+
+/**
+ * Function: armSatRoundFloatToU32
+ *
+ * Description:
+ * Converts a double precision value into a unsigned int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_U32 format
+ *
+ */
+
+OMX_U32 armSatRoundFloatToU32 (OMX_F64 Value)
+{
+ Value += 0.5;
+
+ if(Value > (OMX_U32)OMX_MAX_U32 )
+ {
+ return (OMX_U32)OMX_MAX_U32;
+ }
+ else
+ {
+ return (OMX_U32)Value;
+ }
+}
+
+/**
+ * Function: armRoundFloatToS64
+ *
+ * Description:
+ * Converts a double precision value into a 64 bit int after rounding
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S64 format
+ *
+ */
+
+OMX_S64 armRoundFloatToS64 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ return (OMX_S64)(Value + .5);
+ }
+ else
+ {
+ return (OMX_S64)(Value - .5);
+ }
+}
+
+/**
+ * Function: armSignCheck
+ *
+ * Description:
+ * Checks the sign of a variable:
+ * returns 1 if it is Positive
+ * returns 0 if it is 0
+ * returns -1 if it is Negative
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] var Variable to be checked
+ *
+ * Return Value:
+ * OMX_INT -- returns 1 if it is Positive
+ * returns 0 if it is 0
+ * returns -1 if it is Negative
+ */
+
+OMX_INT armSignCheck (
+ OMX_S16 var
+)
+
+{
+ OMX_INT Sign;
+
+ if (var < 0)
+ {
+ Sign = -1;
+ }
+ else if ( var > 0)
+ {
+ Sign = 1;
+ }
+ else
+ {
+ Sign = 0;
+ }
+
+ return Sign;
+}
+
+/**
+ * Function: armClip
+ *
+ * Description: Clips the input between MAX and MIN value
+ *
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] Min lower bound
+ * [in] Max upper bound
+ * [in] src variable to the clipped
+ *
+ * Return Value:
+ * OMX_S32 -- returns clipped value
+ */
+
+OMX_S32 armClip (
+ OMX_INT min,
+ OMX_INT max,
+ OMX_S32 src
+)
+
+{
+ if (src > max)
+ {
+ src = max;
+ }
+ else if (src < min)
+ {
+ src = min;
+ }
+
+ return src;
+}
+
+/**
+ * Function: armClip_F32
+ *
+ * Description: Clips the input between MAX and MIN value
+ *
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] Min lower bound
+ * [in] Max upper bound
+ * [in] src variable to the clipped
+ *
+ * Return Value:
+ * OMX_F32 -- returns clipped value
+ */
+
+OMX_F32 armClip_F32 (
+ OMX_F32 min,
+ OMX_F32 max,
+ OMX_F32 src
+)
+
+{
+ if (src > max)
+ {
+ src = max;
+ }
+ else if (src < min)
+ {
+ src = min;
+ }
+
+ return src;
+}
+
+/**
+ * Function: armShiftSat_F32
+ *
+ * Description: Divides a float value by 2^shift and
+ * saturates it for unsigned value range for satBits.
+ * Second parameter is like "shifting" the corresponding
+ * integer value. Takes care of rounding while clipping the final
+ * value.
+ *
+ * Parameters:
+ * [in] v Number to be operated upon
+ * [in] shift Divides the input "v" by "2^shift"
+ * [in] satBits Final range is [0, 2^satBits)
+ *
+ * Return Value:
+ * OMX_S32 -- returns "shifted" saturated value
+ */
+
+OMX_U32 armShiftSat_F32(OMX_F32 v, OMX_INT shift, OMX_INT satBits)
+{
+ OMX_U32 allOnes = (OMX_U32)(-1);
+ OMX_U32 maxV = allOnes >> (32-satBits);
+ OMX_F32 vShifted, vRounded, shiftDiv = (OMX_F32)(1 << shift);
+ OMX_U32 vInt;
+ OMX_U32 vIntSat;
+
+ if(v <= 0)
+ return 0;
+
+ vShifted = v / shiftDiv;
+ vRounded = (OMX_F32)(vShifted + 0.5);
+ vInt = (OMX_U32)vRounded;
+ vIntSat = vInt;
+ if(vIntSat > maxV)
+ vIntSat = maxV;
+ return vIntSat;
+}
+
+/**
+ * Functions: armSwapElem
+ *
+ * Description:
+ * These function swaps two elements at the specified pointer locations.
+ * The size of each element could be anything as specified by <elemSize>
+ *
+ * Return Value:
+ * OMXResult -- Error status from the function
+ */
+OMXResult armSwapElem(
+ OMX_U8 *pBuf1,
+ OMX_U8 *pBuf2,
+ OMX_INT elemSize
+ )
+{
+ OMX_INT i;
+ OMX_U8 temp;
+ armRetArgErrIf(!pBuf1 || !pBuf2, OMX_Sts_BadArgErr);
+
+ for(i = 0; i < elemSize; i++)
+ {
+ temp = *(pBuf1 + i);
+ *(pBuf1 + i) = *(pBuf2 + i);
+ *(pBuf2 + i) = temp;
+ }
+ return OMX_Sts_NoErr;
+}
+
+/**
+ * Function: armMedianOf3
+ *
+ * Description: Finds the median of three numbers
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] fEntry First entry
+ * [in] sEntry second entry
+ * [in] tEntry Third entry
+ *
+ * Return Value:
+ * OMX_S32 -- returns the median value
+ */
+
+OMX_S32 armMedianOf3 (
+ OMX_S32 fEntry,
+ OMX_S32 sEntry,
+ OMX_S32 tEntry
+)
+{
+ OMX_S32 a, b, c;
+
+ a = armMin (fEntry, sEntry);
+ b = armMax (fEntry, sEntry);
+ c = armMin (b, tEntry);
+ return (armMax (a, c));
+}
+
+/**
+ * Function: armLogSize
+ *
+ * Description: Finds the size of a positive value and returns the same
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] value Positive value
+ *
+ * Return Value:
+ * OMX_U8 -- Returns the minimum number of bits required to represent the positive value.
+ This is the smallest k>=0 such that that value is less than (1<<k).
+ */
+
+OMX_U8 armLogSize (
+ OMX_U16 value
+)
+{
+ OMX_U8 i;
+ for ( i = 0; value > 0; value = value >> 1)
+ {
+ i++;
+ }
+ return i;
+}
+
+/***********************************************************************/
+ /* Saturating Arithmetic operations */
+
+/**
+ * Function :armSatAdd_S32()
+ *
+ * Description :
+ * Returns the result of saturated addition of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ *
+ **/
+
+OMX_S32 armSatAdd_S32(OMX_S32 Value1,OMX_S32 Value2)
+{
+ OMX_S32 Result;
+
+ Result = Value1 + Value2;
+
+ if( (Value1^Value2) >= 0)
+ {
+ /*Same sign*/
+ if( (Result^Value1) >= 0)
+ {
+ /*Result has not saturated*/
+ return Result;
+ }
+ else
+ {
+ if(Value1 >= 0)
+ {
+ /*Result has saturated in positive side*/
+ return OMX_MAX_S32;
+ }
+ else
+ {
+ /*Result has saturated in negative side*/
+ return OMX_MIN_S32;
+ }
+
+ }
+
+ }
+ else
+ {
+ return Result;
+ }
+
+}
+
+/**
+ * Function :armSatAdd_S64()
+ *
+ * Description :
+ * Returns the result of saturated addition of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ *
+ **/
+
+OMX_S64 armSatAdd_S64(OMX_S64 Value1,OMX_S64 Value2)
+{
+ OMX_S64 Result;
+
+ Result = Value1 + Value2;
+
+ if( (Value1^Value2) >= 0)
+ {
+ /*Same sign*/
+ if( (Result^Value1) >= 0)
+ {
+ /*Result has not saturated*/
+ return Result;
+ }
+ else
+ {
+ if(Value1 >= 0)
+ {
+ /*Result has saturated in positive side*/
+ Result = OMX_MAX_S64;
+ return Result;
+ }
+ else
+ {
+ /*Result has saturated in negative side*/
+ return OMX_MIN_S64;
+ }
+
+ }
+
+ }
+ else
+ {
+ return Result;
+ }
+
+}
+
+/** Function :armSatSub_S32()
+ *
+ * Description :
+ * Returns the result of saturated substraction of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatSub_S32(OMX_S32 Value1,OMX_S32 Value2)
+{
+ OMX_S32 Result;
+
+ Result = Value1 - Value2;
+
+ if( (Value1^Value2) < 0)
+ {
+ /*Opposite sign*/
+ if( (Result^Value1) >= 0)
+ {
+ /*Result has not saturated*/
+ return Result;
+ }
+ else
+ {
+ if(Value1 >= 0)
+ {
+ /*Result has saturated in positive side*/
+ return OMX_MAX_S32;
+ }
+ else
+ {
+ /*Result has saturated in negative side*/
+ return OMX_MIN_S32;
+ }
+
+ }
+
+ }
+ else
+ {
+ return Result;
+ }
+
+}
+
+/**
+ * Function :armSatMac_S32()
+ *
+ * Description :
+ * Returns the result of Multiplication of Value1 and Value2 and subesquent saturated
+ * accumulation with Mac
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ * [in] Mac Accumulator
+ *
+ * Return:
+ * [out] Result of operation
+ **/
+
+OMX_S32 armSatMac_S32(OMX_S32 Mac,OMX_S16 Value1,OMX_S16 Value2)
+{
+ OMX_S32 Result;
+
+ Result = (OMX_S32)(Value1*Value2);
+ Result = armSatAdd_S32( Mac , Result );
+
+ return Result;
+}
+
+/**
+ * Function :armSatMac_S16S32_S32
+ *
+ * Description :
+ * Returns the result of saturated MAC operation of the three inputs delayElem, filTap , mac
+ *
+ * mac = mac + Saturate_in_32Bits(delayElem * filTap)
+ *
+ * Parametrs:
+ * [in] delayElem First 32 bit Operand
+ * [in] filTap Second 16 bit Operand
+ * [in] mac Result of MAC operation
+ *
+ * Return:
+ * [out] mac Result of operation
+ *
+ **/
+
+OMX_S32 armSatMac_S16S32_S32(OMX_S32 mac, OMX_S32 delayElem, OMX_S16 filTap )
+{
+
+ OMX_S32 result;
+
+ result = armSatMulS16S32_S32(filTap,delayElem);
+
+ if ( result > OMX_MAX_S16 )
+ {
+ result = OMX_MAX_S32;
+ }
+ else if( result < OMX_MIN_S16 )
+ {
+ result = OMX_MIN_S32;
+ }
+ else
+ {
+ result = delayElem * filTap;
+ }
+
+ mac = armSatAdd_S32(mac,result);
+
+ return mac;
+}
+
+
+/**
+ * Function :armSatRoundRightShift_S32_S16
+ *
+ * Description :
+ * Returns the result of rounded right shift operation of input by the scalefactor
+ *
+ * output = Saturate_in_16Bits( ( Right/LeftShift( (Round(input) , shift ) )
+ *
+ * Parametrs:
+ * [in] input The input to be operated on
+ * [in] shift The shift number
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+
+OMX_S16 armSatRoundRightShift_S32_S16(OMX_S32 input, OMX_INT shift)
+{
+ input = armSatRoundLeftShift_S32(input,-shift);
+
+ if ( input > OMX_MAX_S16 )
+ {
+ return (OMX_S16)OMX_MAX_S16;
+ }
+ else if (input < OMX_MIN_S16)
+ {
+ return (OMX_S16)OMX_MIN_S16;
+ }
+ else
+ {
+ return (OMX_S16)input;
+ }
+
+}
+
+/**
+ * Function :armSatRoundLeftShift_S32()
+ *
+ * Description :
+ * Returns the result of saturating left-shift operation on input
+ * Or rounded Right shift if the input Shift is negative.
+ *
+ * Parametrs:
+ * [in] Value Operand
+ * [in] Shift Operand for shift operation
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatRoundLeftShift_S32(OMX_S32 Value, OMX_INT Shift)
+{
+ OMX_INT i;
+
+ if (Shift < 0)
+ {
+ Shift = -Shift;
+ Value = armSatAdd_S32(Value, (1 << (Shift - 1)));
+ Value = Value >> Shift;
+ }
+ else
+ {
+ for (i = 0; i < Shift; i++)
+ {
+ Value = armSatAdd_S32(Value, Value);
+ }
+ }
+ return Value;
+}
+
+/**
+ * Function :armSatRoundLeftShift_S64()
+ *
+ * Description :
+ * Returns the result of saturating left-shift operation on input
+ * Or rounded Right shift if the input Shift is negative.
+ *
+ * Parametrs:
+ * [in] Value Operand
+ * [in] shift Operand for shift operation
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S64 armSatRoundLeftShift_S64(OMX_S64 Value, OMX_INT Shift)
+{
+ OMX_INT i;
+
+ if (Shift < 0)
+ {
+ Shift = -Shift;
+ Value = armSatAdd_S64(Value, ((OMX_S64)1 << (Shift - 1)));
+ Value = Value >> Shift;
+ }
+ else
+ {
+ for (i = 0; i < Shift; i++)
+ {
+ Value = armSatAdd_S64(Value, Value);
+ }
+ }
+ return Value;
+}
+
+/**
+ * Function :armSatMulS16S32_S32()
+ *
+ * Description :
+ * Returns the result of a S16 data type multiplied with an S32 data type
+ * in a S32 container
+ *
+ * Parametrs:
+ * [in] input1 Operand 1
+ * [in] input2 Operand 2
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+
+OMX_S32 armSatMulS16S32_S32(OMX_S16 input1,OMX_S32 input2)
+{
+ OMX_S16 hi2,lo1;
+ OMX_U16 lo2;
+
+ OMX_S32 temp1,temp2;
+ OMX_S32 result;
+
+ lo1 = input1;
+
+ hi2 = ( input2 >> 16 );
+ lo2 = ( (OMX_U32)( input2 << 16 ) >> 16 );
+
+ temp1 = hi2 * lo1;
+ temp2 = ( lo2* lo1 ) >> 16;
+
+ result = armSatAdd_S32(temp1,temp2);
+
+ return result;
+}
+
+/**
+ * Function :armSatMulS32S32_S32()
+ *
+ * Description :
+ * Returns the result of a S32 data type multiplied with an S32 data type
+ * in a S32 container
+ *
+ * Parametrs:
+ * [in] input1 Operand 1
+ * [in] input2 Operand 2
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatMulS32S32_S32(OMX_S32 input1,OMX_S32 input2)
+{
+ OMX_S16 hi1,hi2;
+ OMX_U16 lo1,lo2;
+
+ OMX_S32 temp1,temp2,temp3;
+ OMX_S32 result;
+
+ hi1 = ( input1 >> 16 );
+ lo1 = ( (OMX_U32)( input1 << 16 ) >> 16 );
+
+ hi2 = ( input2 >> 16 );
+ lo2 = ( (OMX_U32)( input2 << 16 ) >> 16 );
+
+ temp1 = hi1 * hi2;
+ temp2 = ( hi1* lo2 ) >> 16;
+ temp3 = ( hi2* lo1 ) >> 16;
+
+ result = armSatAdd_S32(temp1,temp2);
+ result = armSatAdd_S32(result,temp3);
+
+ return result;
+}
+
+/**
+ * Function :armIntDivAwayFromZero()
+ *
+ * Description : Integer division with rounding to the nearest integer.
+ * Half-integer values are rounded away from zero
+ * unless otherwise specified. For example 3//2 is rounded
+ * to 2, and -3//2 is rounded to -2.
+ *
+ * Parametrs:
+ * [in] Num Operand 1
+ * [in] Deno Operand 2
+ *
+ * Return:
+ * [out] Result of operation input1//input2
+ *
+ **/
+
+OMX_S32 armIntDivAwayFromZero (OMX_S32 Num, OMX_S32 Deno)
+{
+ OMX_F64 result;
+
+ result = ((OMX_F64)Num)/((OMX_F64)Deno);
+
+ if (result >= 0)
+ {
+ result += 0.5;
+ }
+ else
+ {
+ result -= 0.5;
+ }
+
+ return (OMX_S32)(result);
+}
+
+
+/*End of File*/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_Bitstream.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_Bitstream.c
new file mode 100644
index 0000000..9ef9319
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_Bitstream.c
@@ -0,0 +1,329 @@
+/**
+ *
+ * File Name: armCOMM_Bitstream.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Defines bitstream encode and decode functions common to all codecs
+ */
+
+#include "omxtypes.h"
+#include "armCOMM.h"
+#include "armCOMM_Bitstream.h"
+
+/***************************************
+ * Fixed bit length Decode
+ ***************************************/
+
+/**
+ * Function: armLookAheadBits()
+ *
+ * Description:
+ * Get the next N bits from the bitstream without advancing the bitstream pointer
+ *
+ * Parameters:
+ * [in] **ppBitStream
+ * [in] *pOffset
+ * [in] N=1...32
+ *
+ * Returns Value
+ */
+
+OMX_U32 armLookAheadBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N)
+{
+ const OMX_U8 *pBitStream = *ppBitStream;
+ OMX_INT Offset = *pOffset;
+ OMX_U32 Value;
+
+ armAssert(Offset>=0 && Offset<=7);
+ armAssert(N>=1 && N<=32);
+
+ /* Read next 32 bits from stream */
+ Value = (pBitStream[0] << 24 ) | ( pBitStream[1] << 16) | (pBitStream[2] << 8 ) | (pBitStream[3]) ;
+ Value = (Value << Offset ) | (pBitStream[4] >> (8-Offset));
+
+ /* Return N bits */
+ return Value >> (32-N);
+}
+
+
+/**
+ * Function: armGetBits()
+ *
+ * Description:
+ * Read N bits from the bitstream
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ * [in] N=1..32
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ * Returns Value
+ */
+
+
+OMX_U32 armGetBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N)
+{
+ const OMX_U8 *pBitStream = *ppBitStream;
+ OMX_INT Offset = *pOffset;
+ OMX_U32 Value;
+
+ if(N == 0)
+ {
+ return 0;
+ }
+
+ armAssert(Offset>=0 && Offset<=7);
+ armAssert(N>=1 && N<=32);
+
+ /* Read next 32 bits from stream */
+ Value = (pBitStream[0] << 24 ) | ( pBitStream[1] << 16) | (pBitStream[2] << 8 ) | (pBitStream[3]) ;
+ Value = (Value << Offset ) | (pBitStream[4] >> (8-Offset));
+
+ /* Advance bitstream pointer by N bits */
+ Offset += N;
+ *ppBitStream = pBitStream + (Offset>>3);
+ *pOffset = Offset & 7;
+
+ /* Return N bits */
+ return Value >> (32-N);
+}
+
+/**
+ * Function: armByteAlign()
+ *
+ * Description:
+ * Align the pointer *ppBitStream to the next byte boundary
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ *
+ **/
+
+OMXVoid armByteAlign(const OMX_U8 **ppBitStream,OMX_INT *pOffset)
+{
+ if(*pOffset > 0)
+ {
+ *ppBitStream += 1;
+ *pOffset = 0;
+ }
+}
+
+/**
+ * Function: armSkipBits()
+ *
+ * Description:
+ * Skip N bits from the value at *ppBitStream
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ * [in] N
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ *
+ **/
+
+
+OMXVoid armSkipBits(const OMX_U8 **ppBitStream,OMX_INT *pOffset,OMX_INT N)
+{
+ OMX_INT Offset = *pOffset;
+ const OMX_U8 *pBitStream = *ppBitStream;
+
+ /* Advance bitstream pointer by N bits */
+ Offset += N;
+ *ppBitStream = pBitStream + (Offset>>3);
+ *pOffset = Offset & 7;
+}
+
+/***************************************
+ * Variable bit length Decode
+ ***************************************/
+
+/**
+ * Function: armUnPackVLC32()
+ *
+ * Description:
+ * Variable length decode of variable length symbol (max size 32 bits) read from
+ * the bit stream pointed by *ppBitStream at *pOffset by using the table
+ * pointed by pCodeBook
+ *
+ * Parameters:
+ * [in] *pBitStream
+ * [in] *pOffset
+ * [in] pCodeBook
+ *
+ * [out] *pBitStream
+ * [out] *pOffset
+ *
+ * Returns : Code Book Index if successfull.
+ * : ARM_NO_CODEBOOK_INDEX = -1 if search fails.
+ **/
+#ifndef C_OPTIMIZED_IMPLEMENTATION
+
+OMX_U16 armUnPackVLC32(
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pOffset,
+ const ARM_VLC32 *pCodeBook
+)
+{
+ const OMX_U8 *pBitStream = *ppBitStream;
+ OMX_INT Offset = *pOffset;
+ OMX_U32 Value;
+ OMX_INT Index;
+
+ armAssert(Offset>=0 && Offset<=7);
+
+ /* Read next 32 bits from stream */
+ Value = (pBitStream[0] << 24 ) | ( pBitStream[1] << 16) | (pBitStream[2] << 8 ) | (pBitStream[3]) ;
+ Value = (Value << Offset ) | (pBitStream[4] >> (8-Offset));
+
+ /* Search through the codebook */
+ for (Index=0; pCodeBook->codeLen != 0; Index++)
+ {
+ if (pCodeBook->codeWord == (Value >> (32 - pCodeBook->codeLen)))
+ {
+ Offset = Offset + pCodeBook->codeLen;
+ *ppBitStream = pBitStream + (Offset >> 3) ;
+ *pOffset = Offset & 7;
+
+ return Index;
+ }
+ pCodeBook++;
+ }
+
+ /* No code match found */
+ return ARM_NO_CODEBOOK_INDEX;
+}
+
+#endif
+
+/***************************************
+ * Fixed bit length Encode
+ ***************************************/
+
+/**
+ * Function: armPackBits
+ *
+ * Description:
+ * Pack a VLC code word into the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte
+ * in the bit stream.
+ * [in] pOffset pointer to the bit position in the byte
+ * pointed by *ppBitStream. Valid within 0
+ * to 7.
+ * [in] codeWord Code word that need to be inserted in to the
+ * bitstream
+ * [in] codeLength Length of the code word valid range 1...32
+ *
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMX_RESULT result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armPackBits (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pOffset,
+ OMX_U32 codeWord,
+ OMX_INT codeLength
+)
+{
+ OMX_U8 *pBitStream = *ppBitStream;
+ OMX_INT Offset = *pOffset;
+ OMX_U32 Value;
+
+ /* checking argument validity */
+ armRetArgErrIf(Offset < 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf(Offset > 7, OMX_Sts_BadArgErr);
+ armRetArgErrIf(codeLength < 1, OMX_Sts_BadArgErr);
+ armRetArgErrIf(codeLength > 32, OMX_Sts_BadArgErr);
+
+ /* Prepare the first byte */
+ codeWord = codeWord << (32-codeLength);
+ Value = (pBitStream[0] >> (8-Offset)) << (8-Offset);
+ Value = Value | (codeWord >> (24+Offset));
+
+ /* Write out whole bytes */
+ while (8-Offset <= codeLength)
+ {
+ *pBitStream++ = (OMX_U8)Value;
+ codeWord = codeWord << (8-Offset);
+ codeLength = codeLength - (8-Offset);
+ Offset = 0;
+ Value = codeWord >> 24;
+ }
+
+ /* Write out final partial byte */
+ *pBitStream = (OMX_U8)Value;
+ *ppBitStream = pBitStream;
+ *pOffset = Offset + codeLength;
+
+ return OMX_Sts_NoErr;
+}
+
+/***************************************
+ * Variable bit length Encode
+ ***************************************/
+
+/**
+ * Function: armPackVLC32
+ *
+ * Description:
+ * Pack a VLC code word into the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte
+ * in the bit stream.
+ * [in] pBitOffset pointer to the bit position in the byte
+ * pointed by *ppBitStream. Valid within 0
+ * to 7.
+ * [in] code VLC code word that need to be inserted in to the
+ * bitstream
+ *
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMX_RESULT result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armPackVLC32 (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ ARM_VLC32 code
+)
+{
+ return (armPackBits(ppBitStream, pBitOffset, code.codeWord, code.codeLen));
+}
+
+/*End of File*/
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_IDCTTable.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_IDCTTable.c
new file mode 100644
index 0000000..9e4679c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_IDCTTable.c
@@ -0,0 +1,60 @@
+/**
+ *
+ * File Name: armCOMM_IDCTTable.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armCOMM_IDCTTable.c
+ * Brief: Defines Tables used in IDCT computation
+ *
+ */
+
+#include "armCOMM_IDCTTable.h"
+
+ /* Table of s(u)*A(u)*A(v)/16 at Q15
+ * s(u)=1.0 0 <= u <= 5
+ * s(6)=2.0
+ * s(7)=4.0
+ * A(0) = 2*sqrt(2)
+ * A(u) = 4*cos(u*pi/16) for (u!=0)
+ */
+
+__align(4) const OMX_U16 armCOMM_IDCTPreScale [64] =
+{
+ 0x4000, 0x58c5, 0x539f, 0x4b42, 0x4000, 0x3249, 0x4546, 0x46a1,
+ 0x58c5, 0x7b21, 0x73fc, 0x6862, 0x58c5, 0x45bf, 0x6016, 0x61f8,
+ 0x539f, 0x73fc, 0x6d41, 0x6254, 0x539f, 0x41b3, 0x5a82, 0x5c48,
+ 0x4b42, 0x6862, 0x6254, 0x587e, 0x4b42, 0x3b21, 0x5175, 0x530d,
+ 0x4000, 0x58c5, 0x539f, 0x4b42, 0x4000, 0x3249, 0x4546, 0x46a1,
+ 0x3249, 0x45bf, 0x41b3, 0x3b21, 0x3249, 0x2782, 0x366d, 0x377e,
+ 0x22a3, 0x300b, 0x2d41, 0x28ba, 0x22a3, 0x1b37, 0x257e, 0x263a,
+ 0x11a8, 0x187e, 0x1712, 0x14c3, 0x11a8, 0x0de0, 0x131d, 0x137d
+};
+ /* Above array armCOMM_IDCTPreScale, in Q23 format */
+const OMX_U32 armCOMM_IDCTPreScaleU32 [64] =
+{
+ 0x400000, 0x58c543, 0x539eba, 0x4b418c, 0x400000, 0x3248d4, 0x4545ea, 0x46a157,
+ 0x58c543, 0x7b20d8, 0x73fbfc, 0x686214, 0x58c543, 0x45bf1f, 0x6015a5, 0x61f78b,
+ 0x539eba, 0x73fbfc, 0x6d413d, 0x6253a6, 0x539eba, 0x41b328, 0x5a827a, 0x5c4869,
+ 0x4b418c, 0x686214, 0x6253a6, 0x587de3, 0x4b418c, 0x3b20d8, 0x5174e0, 0x530d69,
+ 0x400000, 0x58c543, 0x539eba, 0x4b418c, 0x400000, 0x3248d4, 0x4545ea, 0x46a157,
+ 0x3248d4, 0x45bf1f, 0x41b328, 0x3b20d8, 0x3248d4, 0x27821d, 0x366d72, 0x377e6b,
+ 0x22a2f5, 0x300ad3, 0x2d413d, 0x28ba70, 0x22a2f5, 0x1b36b9, 0x257d86, 0x26398d,
+ 0x11a856, 0x187de3, 0x17121a, 0x14c35a, 0x11a856, 0x0ddf9b, 0x131cc7, 0x137ca2
+};
+
+const OMX_U16 armCOMM_IDCTCoef [4] =
+{
+ 0x5a82, /* InvSqrt2 */
+ 0x30fc, /* SinPIBy8 */
+ 0x7642, /* CosPIBy8 */
+ 0x0000
+};
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_MaskTable.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_MaskTable.c
new file mode 100644
index 0000000..3241db2
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/src/armCOMM_MaskTable.c
@@ -0,0 +1,45 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armCOMM_MaskTable.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Mask Table to mask the end of array.
+ *
+ */
+
+#include "omxtypes.h"
+
+#define MaskTableSize 72
+
+const OMX_U16 armCOMM_qMaskTable16[MaskTableSize] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF
+};
+
+const OMX_U8 armCOMM_qMaskTable8[MaskTableSize] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVC.h
new file mode 100644
index 0000000..7fa7716
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVC.h
@@ -0,0 +1,1153 @@
+/**
+ *
+ * File Name: armVC.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armVideo.h
+ * Brief: Declares API's/Basic Data types used across the OpenMAX Video domain
+ *
+ */
+
+
+#ifndef _armVideo_H_
+#define _armVideo_H_
+
+#include "omxVC.h"
+#include "armCOMM_Bitstream.h"
+
+/**
+ * ARM specific state structure to hold Motion Estimation information.
+ */
+
+struct m4p2_MESpec
+{
+ OMXVCM4P2MEParams MEParams;
+ OMXVCM4P2MEMode MEMode;
+};
+
+struct m4p10_MESpec
+{
+ OMXVCM4P10MEParams MEParams;
+ OMXVCM4P10MEMode MEMode;
+};
+
+typedef struct m4p2_MESpec ARMVCM4P2_MESpec;
+typedef struct m4p10_MESpec ARMVCM4P10_MESpec;
+
+/**
+ * Function: armVCM4P2_CompareMV
+ *
+ * Description:
+ * Performs comparision of motion vectors and SAD's to decide the
+ * best MV and SAD
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] mvX x coordinate of the candidate motion vector
+ * [in] mvY y coordinate of the candidate motion vector
+ * [in] candSAD Candidate SAD
+ * [in] bestMVX x coordinate of the best motion vector
+ * [in] bestMVY y coordinate of the best motion vector
+ * [in] bestSAD best SAD
+ *
+ * Return Value:
+ * OMX_INT -- 1 to indicate that the current sad is the best
+ * 0 to indicate that it is NOT the best SAD
+ */
+
+OMX_INT armVCM4P2_CompareMV (
+ OMX_S16 mvX,
+ OMX_S16 mvY,
+ OMX_INT candSAD,
+ OMX_S16 bestMVX,
+ OMX_S16 bestMVY,
+ OMX_INT bestSAD);
+
+/**
+ * Function: armVCM4P2_ACDCPredict
+ *
+ * Description:
+ * Performs adaptive DC/AC coefficient prediction for an intra block. Prior
+ * to the function call, prediction direction (predDir) should be selected
+ * as specified in subclause 7.4.3.1 of ISO/IEC 14496-2.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcDst pointer to the coefficient buffer which contains
+ * the quantized coefficient residuals (PQF) of the
+ * current block
+ * [in] pPredBufRow pointer to the coefficient row buffer
+ * [in] pPredBufCol pointer to the coefficient column buffer
+ * [in] curQP quantization parameter of the current block. curQP
+ * may equal to predQP especially when the current
+ * block and the predictor block are in the same
+ * macroblock.
+ * [in] predQP quantization parameter of the predictor block
+ * [in] predDir indicates the prediction direction which takes one
+ * of the following values:
+ * OMX_VIDEO_HORIZONTAL predict horizontally
+ * OMX_VIDEO_VERTICAL predict vertically
+ * [in] ACPredFlag a flag indicating if AC prediction should be
+ * performed. It is equal to ac_pred_flag in the bit
+ * stream syntax of MPEG-4
+ * [in] videoComp video component type (luminance, chrominance or
+ * alpha) of the current block
+ * [in] flag This flag defines the if one wants to use this functions to
+ * calculate PQF (set 1, prediction) or QF (set 0, reconstruction)
+ * [out] pPreACPredict pointer to the predicted coefficients buffer.
+ * Filled ONLY if it is not NULL
+ * [out] pSrcDst pointer to the coefficient buffer which contains
+ * the quantized coefficients (QF) of the current
+ * block
+ * [out] pPredBufRow pointer to the updated coefficient row buffer
+ * [out] pPredBufCol pointer to the updated coefficient column buffer
+ * [out] pSumErr pointer to the updated sum of the difference
+ * between predicted and unpredicted coefficients
+ * If this is NULL, do not update
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_ACDCPredict(
+ OMX_S16 * pSrcDst,
+ OMX_S16 * pPreACPredict,
+ OMX_S16 * pPredBufRow,
+ OMX_S16 * pPredBufCol,
+ OMX_INT curQP,
+ OMX_INT predQP,
+ OMX_INT predDir,
+ OMX_INT ACPredFlag,
+ OMXVCM4P2VideoComponent videoComp,
+ OMX_U8 flag,
+ OMX_INT *pSumErr
+);
+
+/**
+ * Function: armVCM4P2_SetPredDir
+ *
+ * Description:
+ * Performs detecting the prediction direction
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] blockIndex block index indicating the component type and
+ * position as defined in subclause 6.1.3.8, of ISO/IEC
+ * 14496-2. Furthermore, indexes 6 to 9 indicate the
+ * alpha blocks spatially corresponding to luminance
+ * blocks 0 to 3 in the same macroblock.
+ * [in] pCoefBufRow pointer to the coefficient row buffer
+ * [in] pQpBuf pointer to the quantization parameter buffer
+ * [out] predQP quantization parameter of the predictor block
+ * [out] predDir indicates the prediction direction which takes one
+ * of the following values:
+ * OMX_VIDEO_HORIZONTAL predict horizontally
+ * OMX_VIDEO_VERTICAL predict vertically
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_SetPredDir(
+ OMX_INT blockIndex,
+ OMX_S16 *pCoefBufRow,
+ OMX_S16 *pCoefBufCol,
+ OMX_INT *predDir,
+ OMX_INT *predQP,
+ const OMX_U8 *pQpBuf
+);
+
+/**
+ * Function: armVCM4P2_EncodeVLCZigzag_Intra
+ *
+ * Description:
+ * Performs zigzag scanning and VLC encoding for one intra block.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7.
+ * [in] pQDctBlkCoef pointer to the quantized DCT coefficient
+ * [in] predDir AC prediction direction, which is used to decide
+ * the zigzag scan pattern. This takes one of the
+ * following values:
+ * OMX_VIDEO_NONE AC prediction not used.
+ * Performs classical zigzag
+ * scan.
+ * OMX_VIDEO_HORIZONTAL Horizontal prediction.
+ * Performs alternate-vertical
+ * zigzag scan.
+ * OMX_VIDEO_VERTICAL Vertical prediction.
+ * Performs alternate-horizontal
+ * zigzag scan.
+ * [in] pattern block pattern which is used to decide whether
+ * this block is encoded
+ * [in] start start indicates whether the encoding begins with 0th element
+ * or 1st.
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_EncodeVLCZigzag_Intra(
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 predDir,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start
+);
+
+/**
+ * Function: armVCM4P2_DecodeVLCZigzag_Intra
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan for one intra coded block.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bitstream buffer
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * to by *ppBitStream. *pBitOffset is valid within
+ * [0-7].
+ * [in] predDir AC prediction direction which is used to decide
+ * the zigzag scan pattern. It takes one of the
+ * following values:
+ * OMX_VIDEO_NONE AC prediction not used;
+ * perform classical zigzag scan;
+ * OMX_VIDEO_HORIZONTAL Horizontal prediction;
+ * perform alternate-vertical
+ * zigzag scan;
+ * OMX_VIDEO_VERTICAL Vertical prediction;
+ * thus perform
+ * alternate-horizontal
+ * zigzag scan.
+ * [in] videoComp video component type (luminance, chrominance or
+ * alpha) of the current block
+ * [in] shortVideoHeader binary flag indicating presence of short_video_header; escape modes 0-3 are used if shortVideoHeader==0,
+ * and escape mode 4 is used when shortVideoHeader==1.
+ * [in] start start indicates whether the encoding begins with 0th element
+ * or 1st.
+ * [out] ppBitStream *ppBitStream is updated after the block is
+ * decoded, so that it points to the current byte
+ * in the bit stream buffer
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream
+ * [out] pDst pointer to the coefficient buffer of current
+ * block. Should be 32-bit aligned
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_DecodeVLCZigzag_Intra(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_U8 predDir,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start
+);
+
+/**
+ * Function: armVCM4P2_FillVLDBuffer
+ *
+ * Description:
+ * Performs filling of the coefficient buffer according to the run, level
+ * and sign, also updates the index
+ *
+ * Parameters:
+ * [in] storeRun Stored Run value (count of zeros)
+ * [in] storeLevel Stored Level value (non-zero value)
+ * [in] sign Flag indicating the sign of level
+ * [in] last status of the last flag
+ * [in] pIndex pointer to coefficient index in 8x8 matrix
+ * [out] pIndex pointer to updated coefficient index in 8x8
+ * matrix
+ * [in] pZigzagTable pointer to the zigzag tables
+ * [out] pDst pointer to the coefficient buffer of current
+ * block. Should be 32-bit aligned
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_FillVLDBuffer(
+ OMX_U32 storeRun,
+ OMX_S16 * pDst,
+ OMX_S16 storeLevel,
+ OMX_U8 sign,
+ OMX_U8 last,
+ OMX_U8 * index,
+ const OMX_U8 * pZigzagTable
+);
+
+/**
+ * Function: armVCM4P2_GetVLCBits
+ *
+ * Description:
+ * Performs escape mode decision based on the run, run+, level, level+ and
+ * last combinations.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7
+ * [in] shortVideoHeader binary flag indicating presence of short_video_header; escape modes 0-3 are used if shortVideoHeader==0,
+ * and escape mode 4 is used when shortVideoHeader==1.
+ * [in] start start indicates whether the encoding begins with
+ * 0th element or 1st.
+ * [in/out] pLast pointer to last status flag
+ * [in] runBeginSingleLevelEntriesL0 The run value from which level
+ * will be equal to 1: last == 0
+ * [in] IndexBeginSingleLevelEntriesL0 Array index in the VLC table
+ * pointing to the
+ * runBeginSingleLevelEntriesL0
+ * [in] runBeginSingleLevelEntriesL1 The run value from which level
+ * will be equal to 1: last == 1
+ * [in] IndexBeginSingleLevelEntriesL1 Array index in the VLC table
+ * pointing to the
+ * runBeginSingleLevelEntriesL0
+ * [in] pRunIndexTableL0 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pVlcTableL0 VLC table for last == 0
+ * [in] pRunIndexTableL1 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pVlcTableL1 VLC table for last == 1
+ * [in] pLMAXTableL0 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pLMAXTableL1 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pRMAXTableL0 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pRMAXTableL1 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [out]pDst pointer to the coefficient buffer of current
+ * block. Should be 32-bit aligned
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_GetVLCBits (
+ const OMX_U8 **ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start,
+ OMX_U8 * pLast,
+ OMX_U8 runBeginSingleLevelEntriesL0,
+ OMX_U8 maxIndexForMultipleEntriesL0,
+ OMX_U8 maxRunForMultipleEntriesL1,
+ OMX_U8 maxIndexForMultipleEntriesL1,
+ const OMX_U8 * pRunIndexTableL0,
+ const ARM_VLC32 *pVlcTableL0,
+ const OMX_U8 * pRunIndexTableL1,
+ const ARM_VLC32 *pVlcTableL1,
+ const OMX_U8 * pLMAXTableL0,
+ const OMX_U8 * pLMAXTableL1,
+ const OMX_U8 * pRMAXTableL0,
+ const OMX_U8 * pRMAXTableL1,
+ const OMX_U8 * pZigzagTable
+);
+
+/**
+ * Function: armVCM4P2_PutVLCBits
+ *
+ * Description:
+ * Checks the type of Escape Mode and put encoded bits for
+ * quantized DCT coefficients.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7
+ * [in] shortVideoHeader binary flag indicating presence of short_video_header; escape modes 0-3 are used if shortVideoHeader==0,
+ * and escape mode 4 is used when shortVideoHeader==1.
+ * [in] start start indicates whether the encoding begins with
+ * 0th element or 1st.
+ * [in] maxStoreRunL0 Max store possible (considering last and inter/intra)
+ * for last = 0
+ * [in] maxStoreRunL1 Max store possible (considering last and inter/intra)
+ * for last = 1
+ * [in] maxRunForMultipleEntriesL0
+ * The run value after which level
+ * will be equal to 1:
+ * (considering last and inter/intra status) for last = 0
+ * [in] maxRunForMultipleEntriesL1
+ * The run value after which level
+ * will be equal to 1:
+ * (considering last and inter/intra status) for last = 1
+ * [in] pRunIndexTableL0 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pVlcTableL0 VLC table for last == 0
+ * [in] pRunIndexTableL1 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pVlcTableL1 VLC table for last == 1
+ * [in] pLMAXTableL0 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pLMAXTableL1 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pRMAXTableL0 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pRMAXTableL1 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [out] pQDctBlkCoef pointer to the quantized DCT coefficient
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+
+OMXResult armVCM4P2_PutVLCBits (
+ OMX_U8 **ppBitStream,
+ OMX_INT * pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start,
+ OMX_U8 maxStoreRunL0,
+ OMX_U8 maxStoreRunL1,
+ OMX_U8 maxRunForMultipleEntriesL0,
+ OMX_U8 maxRunForMultipleEntriesL1,
+ const OMX_U8 * pRunIndexTableL0,
+ const ARM_VLC32 *pVlcTableL0,
+ const OMX_U8 * pRunIndexTableL1,
+ const ARM_VLC32 *pVlcTableL1,
+ const OMX_U8 * pLMAXTableL0,
+ const OMX_U8 * pLMAXTableL1,
+ const OMX_U8 * pRMAXTableL0,
+ const OMX_U8 * pRMAXTableL1,
+ const OMX_U8 * pZigzagTable
+);
+/**
+ * Function: armVCM4P2_FillVLCBuffer
+ *
+ * Description:
+ * Performs calculating the VLC bits depending on the escape type and insert
+ * the same in the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7
+ * [in] run Run value (count of zeros) to be encoded
+ * [in] level Level value (non-zero value) to be encoded
+ * [in] runPlus Calculated as runPlus = run - (RMAX + 1)
+ * [in] levelPlus Calculated as
+ * levelPlus = sign(level)*[abs(level) - LMAX]
+ * [in] fMode Flag indicating the escape modes
+ * [in] last status of the last flag
+ * [in] maxRunForMultipleEntries
+ * The run value after which level will be equal to 1:
+ * (considering last and inter/intra status)
+ * [in] pRunIndexTable Run Index table defined in
+ * armVCM4P2_Huff_tables_VLC.h
+ * [in] pVlcTable VLC table defined in armVCM4P2_Huff_tables_VLC.h
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_FillVLCBuffer (
+ OMX_U8 **ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_U32 run,
+ OMX_S16 level,
+ OMX_U32 runPlus,
+ OMX_S16 levelPlus,
+ OMX_U8 fMode,
+ OMX_U8 last,
+ OMX_U8 maxRunForMultipleEntries,
+ const OMX_U8 *pRunIndexTable,
+ const ARM_VLC32 *pVlcTable
+);
+
+/**
+ * Function: armVCM4P2_CheckVLCEscapeMode
+ *
+ * Description:
+ * Performs escape mode decision based on the run, run+, level, level+ and
+ * last combinations.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] run Run value (count of zeros) to be encoded
+ * [in] level Level value (non-zero value) to be encoded
+ * [in] runPlus Calculated as runPlus = run - (RMAX + 1)
+ * [in] levelPlus Calculated as
+ * levelPlus = sign(level)*[abs(level) - LMAX]
+ * [in] maxStoreRun Max store possible (considering last and inter/intra)
+ * [in] maxRunForMultipleEntries
+ * The run value after which level
+ * will be equal to 1:
+ * (considering last and inter/intra status)
+ * [in] shortVideoHeader binary flag indicating presence of short_video_header; escape modes 0-3 are used if shortVideoHeader==0,
+ * and escape mode 4 is used when shortVideoHeader==1.
+ * [in] pRunIndexTable Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c
+ * (considering last and inter/intra status)
+ *
+ *
+ * Return Value:
+ * Returns an Escape mode which can take values from 0 to 3
+ * 0 --> no escape mode, 1 --> escape type 1,
+ * 1 --> escape type 2, 3 --> escape type 3, check section 7.4.1.3
+ * in the MPEG ISO standard.
+ *
+ */
+
+OMX_U8 armVCM4P2_CheckVLCEscapeMode(
+ OMX_U32 run,
+ OMX_U32 runPlus,
+ OMX_S16 level,
+ OMX_S16 levelPlus,
+ OMX_U8 maxStoreRun,
+ OMX_U8 maxRunForMultipleEntries,
+ OMX_INT shortVideoHeader,
+ const OMX_U8 *pRunIndexTable
+);
+
+
+/**
+ * Function: armVCM4P2_BlockMatch_Integer
+ *
+ * Description:
+ * Performs a 16x16 block search; estimates motion vector and associated minimum SAD.
+ * Both the input and output motion vectors are represented using half-pixel units, and
+ * therefore a shift left or right by 1 bit may be required, respectively, to match the
+ * input or output MVs with other functions that either generate output MVs or expect
+ * input MVs represented using integer pixel units.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcRefBuf pointer to the reference Y plane; points to the reference MB that
+ * corresponds to the location of the current macroblock in the current
+ * plane.
+ * [in] refWidth width of the reference plane
+ * [in] pRefRect pointer to the valid rectangular in reference plane. Relative to image origin.
+ * It's not limited to the image boundary, but depended on the padding. For example,
+ * if you pad 4 pixels outside the image border, then the value for left border
+ * can be -4
+ * [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane (linear array,
+ * 256 entries); must be aligned on an 8-byte boundary.
+ * [in] pCurrPointPos position of the current macroblock in the current plane
+ * [in] pSrcPreMV pointer to predicted motion vector; NULL indicates no predicted MV
+ * [in] pSrcPreSAD pointer to SAD associated with the predicted MV (referenced by pSrcPreMV)
+ * [in] searchRange search range for 16X16 integer block,the units of it is full pixel,the search range
+ * is the same in all directions.It is in inclusive of the boundary and specified in
+ * terms of integer pixel units.
+ * [in] pMESpec vendor-specific motion estimation specification structure; must have been allocated
+ * and then initialized using omxVCM4P2_MEInit prior to calling the block matching
+ * function.
+ * [in] BlockSize MacroBlock Size i.e either 16x16 or 8x8.
+ * [out] pDstMV pointer to estimated MV
+ * [out] pDstSAD pointer to minimum SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr ¨C no error.
+ * OMX_Sts_BadArgErr ¨C bad arguments
+ *
+ */
+
+OMXResult armVCM4P2_BlockMatch_Integer(
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCMotionVector *pSrcPreMV,
+ const OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector *pDstMV,
+ OMX_INT *pDstSAD,
+ OMX_U8 BlockSize
+);
+
+/**
+ * Function: armVCM4P2_BlockMatch_Half
+ *
+ * Description:
+ * Performs a 16x16 block match with half-pixel resolution. Returns the estimated
+ * motion vector and associated minimum SAD. This function estimates the half-pixel
+ * motion vector by interpolating the integer resolution motion vector referenced
+ * by the input parameter pSrcDstMV, i.e., the initial integer MV is generated
+ * externally. The input parameters pSrcRefBuf and pSearchPointRefPos should be
+ * shifted by the winning MV of 16x16 integer search prior to calling BlockMatch_Half_16x16.
+ * The function BlockMatch_Integer_16x16 may be used for integer motion estimation.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcRefBuf pointer to the reference Y plane; points to the reference MB
+ * that corresponds to the location of the current macroblock in
+ * the current plane.
+ * [in] refWidth width of the reference plane
+ * [in] pRefRect reference plane valid region rectangle
+ * [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane
+ * (linear array, 256 entries); must be aligned on an 8-byte boundary.
+ * [in] pSearchPointRefPos position of the starting point for half pixel search (specified
+ * in terms of integer pixel units) in the reference plane.
+ * [in] rndVal rounding control bit for half pixel motion estimation;
+ * 0=rounding control disabled; 1=rounding control enabled
+ * [in] pSrcDstMV pointer to the initial MV estimate; typically generated during a prior
+ * 16X16 integer search and its unit is half pixel.
+ * [in] BlockSize MacroBlock Size i.e either 16x16 or 8x8.
+ * [out]pSrcDstMV pointer to estimated MV
+ * [out]pDstSAD pointer to minimum SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr ¨C no error
+ * OMX_Sts_BadArgErr ¨C bad arguments
+ *
+ */
+
+OMXResult armVCM4P2_BlockMatch_Half(
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pSearchPointRefPos,
+ OMX_INT rndVal,
+ OMXVCMotionVector *pSrcDstMV,
+ OMX_INT *pDstSAD,
+ OMX_U8 BlockSize
+);
+/**
+ * Function: armVCM4P2_PadMV
+ *
+ * Description:
+ * Performs motion vector padding for a macroblock.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcDstMV pointer to motion vector buffer of the current
+ * macroblock
+ * [in] pTransp pointer to transparent status buffer of the
+ * current macroblock
+ * [out] pSrcDstMV pointer to motion vector buffer in which the
+ * motion vectors have been padded
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_PadMV(
+ OMXVCMotionVector * pSrcDstMV,
+ OMX_U8 * pTransp
+);
+
+/*
+ * H.264 Specific Declarations
+ */
+/* Defines */
+#define ARM_M4P10_Q_OFFSET (15)
+
+
+/* Dequant tables */
+
+extern const OMX_U8 armVCM4P10_PosToVCol4x4[16];
+extern const OMX_U8 armVCM4P10_PosToVCol2x2[4];
+extern const OMX_U8 armVCM4P10_VMatrix[6][3];
+extern const OMX_U32 armVCM4P10_MFMatrix[6][3];
+
+
+/*
+ * Description:
+ * This function perform the work required by the OpenMAX
+ * DecodeCoeffsToPair function and DecodeChromaDCCoeffsToPair.
+ * Since most of the code is common we share it here.
+ *
+ * Parameters:
+ * [in] ppBitStream Double pointer to current byte in bit stream buffer
+ * [in] pOffset Pointer to current bit position in the byte pointed
+ * to by *ppBitStream
+ * [in] sMaxNumCoeff Maximum number of non-zero coefficients in current
+ * block (4,15 or 16)
+ * [in] nTable Table number (0 to 4) according to the five columns
+ * of Table 9-5 in the H.264 spec
+ * [out] ppBitStream *ppBitStream is updated after each block is decoded
+ * [out] pOffset *pOffset is updated after each block is decoded
+ * [out] pNumCoeff Pointer to the number of nonzero coefficients in
+ * this block
+ * [out] ppPosCoefbuf Double pointer to destination residual
+ * coefficient-position pair buffer
+ * Return Value:
+ * Standard omxError result. See enumeration for possible result codes.
+
+ */
+
+OMXResult armVCM4P10_DecodeCoeffsToPair(
+ const OMX_U8** ppBitStream,
+ OMX_S32* pOffset,
+ OMX_U8* pNumCoeff,
+ OMX_U8**ppPosCoefbuf,
+ OMX_INT nTable,
+ OMX_INT sMaxNumCoeff
+ );
+
+/*
+ * Description:
+ * Perform DC style intra prediction, averaging upper and left block
+ *
+ * Parameters:
+ * [in] pSrcLeft Pointer to the buffer of 16 left coefficients:
+ * p[x, y] (x = -1, y = 0..3)
+ * [in] pSrcAbove Pointer to the buffer of 16 above coefficients:
+ * p[x,y] (x = 0..3, y = -1)
+ * [in] leftStep Step of left coefficient buffer
+ * [in] dstStep Step of the destination buffer
+ * [in] availability Neighboring 16x16 MB availability flag
+ * [out] pDst Pointer to the destination buffer
+ *
+ * Return Value:
+ * None
+ */
+
+void armVCM4P10_PredictIntraDC4x4(
+ const OMX_U8* pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ OMX_U8* pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMX_S32 availability
+);
+
+/*
+ * Description
+ * Unpack a 4x4 block of coefficient-residual pair values
+ *
+ * Parameters:
+ * [in] ppSrc Double pointer to residual coefficient-position pair
+ * buffer output by CALVC decoding
+ * [out] ppSrc *ppSrc is updated to the start of next non empty block
+ * [out] pDst Pointer to unpacked 4x4 block
+ */
+
+void armVCM4P10_UnpackBlock4x4(
+ const OMX_U8 **ppSrc,
+ OMX_S16* pDst
+);
+
+/*
+ * Description
+ * Unpack a 2x2 block of coefficient-residual pair values
+ *
+ * Parameters:
+ * [in] ppSrc Double pointer to residual coefficient-position pair
+ * buffer output by CALVC decoding
+ * [out] ppSrc *ppSrc is updated to the start of next non empty block
+ * [out] pDst Pointer to unpacked 4x4 block
+ */
+
+void armVCM4P10_UnpackBlock2x2(
+ const OMX_U8 **ppSrc,
+ OMX_S16* pDst
+);
+
+/*
+ * Description
+ * Deblock one boundary pixel
+ *
+ * Parameters:
+ * [in] pQ0 Pointer to pixel q0
+ * [in] Step Step between pixels q0 and q1
+ * [in] tC0 Edge threshold value
+ * [in] alpha alpha threshold value
+ * [in] beta beta threshold value
+ * [in] bS deblocking strength
+ * [in] ChromaFlag True for chroma blocks
+ * [out] pQ0 Deblocked pixels
+ *
+ */
+
+void armVCM4P10_DeBlockPixel(
+ OMX_U8 *pQ0, /* pointer to the pixel q0 */
+ int Step, /* step between pixels q0 and q1 */
+ int tC0, /* edge threshold value */
+ int alpha, /* alpha */
+ int beta, /* beta */
+ int bS, /* deblocking strength */
+ int ChromaFlag
+);
+
+/**
+ * Function: armVCM4P10_InterpolateHalfHor_Luma
+ *
+ * Description:
+ * This function performs interpolation for horizontal 1/2-pel positions
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to interpolate
+ in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [out] pDst Pointer to the interpolation buffer of the 1/2-pel
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+OMXResult armVCM4P10_InterpolateHalfHor_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+/**
+ * Function: armVCM4P10_InterpolateHalfVer_Luma
+ *
+ * Description:
+ * This function performs interpolation for vertical 1/2-pel positions
+ * around a full-pel position.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to interpolate
+ * in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [out] pDst Pointer to the interpolation buffer of the 1/2-pel
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+OMXResult armVCM4P10_InterpolateHalfVer_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+/**
+ * Function: armVCM4P10_InterpolateHalfDiag_Luma
+ *
+ * Description:
+ * This function performs interpolation for (1/2, 1/2) positions
+ * around a full-pel position.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to interpolate
+ * in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [out] pDst Pointer to the interpolation buffer of the (1/2,1/2)-pel
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+OMXResult armVCM4P10_InterpolateHalfDiag_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+/*
+ * Description:
+ * Transform Residual 4x4 Coefficients
+ *
+ * Parameters:
+ * [in] pSrc Source 4x4 block
+ * [out] pDst Destination 4x4 block
+ *
+ */
+
+void armVCM4P10_TransformResidual4x4(OMX_S16* pDst, OMX_S16 *pSrc);
+
+/*
+ * Description:
+ * Forward Transform Residual 4x4 Coefficients
+ *
+ * Parameters:
+ * [in] pSrc Source 4x4 block
+ * [out] pDst Destination 4x4 block
+ *
+ */
+
+void armVCM4P10_FwdTransformResidual4x4(OMX_S16* pDst, OMX_S16 *pSrc);
+
+OMX_INT armVCM4P10_CompareMotionCostToMV (
+ OMX_S16 mvX,
+ OMX_S16 mvY,
+ OMXVCMotionVector diffMV,
+ OMX_INT candSAD,
+ OMXVCMotionVector *bestMV,
+ OMX_U32 nLamda,
+ OMX_S32 *pBestCost);
+
+/**
+ * Function: armVCCOMM_SAD
+ *
+ * Description:
+ * This function calculate the SAD for NxM blocks.
+ *
+ * Remarks:
+ *
+ * [in] pSrcOrg Pointer to the original block
+ * [in] iStepOrg Step of the original block buffer
+ * [in] pSrcRef Pointer to the reference block
+ * [in] iStepRef Step of the reference block buffer
+ * [in] iHeight Height of the block
+ * [in] iWidth Width of the block
+ * [out] pDstSAD Pointer of result SAD
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+OMXResult armVCCOMM_SAD(
+ const OMX_U8* pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8* pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32* pDstSAD,
+ OMX_U32 iHeight,
+ OMX_U32 iWidth);
+
+/**
+ * Function: armVCCOMM_Average
+ *
+ * Description:
+ * This function calculates the average of two blocks and stores the result.
+ *
+ * Remarks:
+ *
+ * [in] pPred0 Pointer to the top-left corner of reference block 0
+ * [in] pPred1 Pointer to the top-left corner of reference block 1
+ * [in] iPredStep0 Step of reference block 0
+ * [in] iPredStep1 Step of reference block 1
+ * [in] iDstStep Step of the destination buffer
+ * [in] iWidth Width of the blocks
+ * [in] iHeight Height of the blocks
+ * [out] pDstPred Pointer to the destination buffer
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+ OMXResult armVCCOMM_Average (
+ const OMX_U8* pPred0,
+ const OMX_U8* pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8* pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+/**
+ * Function: armVCM4P10_SADQuar
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the
+ * average of the other two (pSrcRef0 and pSrcRef1)
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to the original block
+ * [in] pSrcRef0 Pointer to reference block 0
+ * [in] pSrcRef1 Pointer to reference block 1
+ * [in] iSrcStep Step of the original block buffer
+ * [in] iRefStep0 Step of reference block 0
+ * [in] iRefStep1 Step of reference block 1
+ * [in] iHeight Height of the block
+ * [in] iWidth Width of the block
+ * [out] pDstSAD Pointer of result SAD
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+OMXResult armVCM4P10_SADQuar(
+ const OMX_U8* pSrc,
+ const OMX_U8* pSrcRef0,
+ const OMX_U8* pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32* pDstSAD,
+ OMX_U32 iHeight,
+ OMX_U32 iWidth
+);
+
+/**
+ * Function: armVCM4P10_Interpolate_Chroma
+ *
+ * Description:
+ * This function performs interpolation for chroma components.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to
+ * interpolate in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [in] dx Fractional part of horizontal motion vector
+ * component in 1/8 pixel unit (0~7)
+ * [in] dy Fractional part of vertical motion vector
+ * component in 1/8 pixel unit (0~7)
+ * [out] pDst Pointer to the interpolation buffer
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+ OMXResult armVCM4P10_Interpolate_Chroma(
+ OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight,
+ OMX_U32 dx,
+ OMX_U32 dy
+);
+
+/**
+ * Function: armVCM4P10_Interpolate_Luma
+ *
+ * Description:
+ * This function performs interpolation for luma components.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to
+ * interpolate in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [in] dx Fractional part of horizontal motion vector
+ * component in 1/4 pixel unit (0~3)
+ * [in] dy Fractional part of vertical motion vector
+ * component in 1/4 pixel unit (0~3)
+ * [out] pDst Pointer to the interpolation buffer
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+ OMXResult armVCM4P10_Interpolate_Luma(
+ const OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight,
+ OMX_U32 dx,
+ OMX_U32 dy
+);
+
+/**
+ * Function: omxVCH264_DequantTransformACFromPair_U8_S16_C1_DLx
+ *
+ * Description:
+ * Reconstruct the 4x4 residual block from coefficient-position pair buffer,
+ * perform dequantisation and integer inverse transformation for 4x4 block of
+ * residuals and update the pair buffer pointer to next non-empty block.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppSrc Double pointer to residual coefficient-position
+ * pair buffer output by CALVC decoding
+ * [in] pDC Pointer to the DC coefficient of this block, NULL
+ * if it doesn't exist
+ * [in] QP Quantization parameter
+ * [in] AC Flag indicating if at least one non-zero coefficient exists
+ * [out] pDst pointer to the reconstructed 4x4 block data
+ *
+ * Return Value:
+ * Standard omxError result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P10_DequantTransformACFromPair_U8_S16_C1_DLx(
+ OMX_U8 **ppSrc,
+ OMX_S16 *pDst,
+ OMX_INT QP,
+ OMX_S16* pDC,
+ int AC
+);
+
+#endif /*_armVideo_H_*/
+
+/*End of File*/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVCCOMM_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVCCOMM_s.h
new file mode 100644
index 0000000..7f0a9b8
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/armVCCOMM_s.h
@@ -0,0 +1,72 @@
+;//
+;//
+;// File Name: armVCCOMM_s.h
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// ARM optimized OpenMAX AC header file
+;//
+;// Formula used:
+;// MACRO for calculating median for three values.
+
+
+
+ IF :LNOT::DEF:ARMVCCOMM_S_H
+ INCLUDE armCOMM_s.h
+ M_VARIANTS CortexA8, ARM1136JS
+
+ IF ARM1136JS :LOR: CortexA8
+
+ ;///*
+ ;// * Macro: M_MEDIAN3
+ ;// *
+ ;// * Description: Finds the median of three numbers
+ ;// *
+ ;// * Remarks:
+ ;// *
+ ;// * Parameters:
+ ;// * [in] x First entry for the list of three numbers.
+ ;// * [in] y Second entry for the list of three numbers.
+ ;// * Input value may be corrupted at the end of
+ ;// * the execution of this macro.
+ ;// * [in] z Third entry of the list of three numbers.
+ ;// * Input value corrupted at the end of the
+ ;// * execution of this macro.
+ ;// * [in] t Temporary scratch register.
+ ;// * [out]z Median of the three numbers.
+ ;// */
+
+ MACRO
+
+ M_MEDIAN3 $x, $y, $z, $t
+
+ SUBS $t, $y, $z; // if (y < z)
+ ADDLT $z, $z, $t; // swap y and z
+ SUBLT $y, $y, $t;
+
+ ;// Now z' <= y', so there are three cases for the
+ ;// median value, depending on x.
+
+ ;// 1) x <= z' <= y' : median value is z'
+ ;// 2) z' <= x <= y' : median value is x
+ ;// 3) z' <= y' <= x : median value is y'
+
+ CMP $z, $x; // if ( x > min(y,z) )
+ MOVLT $z, $x; // ans = x
+
+ CMP $x, $y; // if ( x > max(y,z) )
+ MOVGT $z, $y; // ans = max(y,z)
+
+ MEND
+ ENDIF
+
+
+
+ ENDIF ;// ARMACCOMM_S_H
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/omxVC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/omxVC.h
new file mode 100644
index 0000000..7b3cc72
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/omxVC.h
@@ -0,0 +1,4381 @@
+/**
+ * File: omxVC.h
+ * Brief: OpenMAX DL v1.0.2 - Video Coding library
+ *
+ * Copyright © 2005-2008 The Khronos Group Inc. All Rights Reserved.
+ *
+ * These materials are protected by copyright laws and contain material
+ * proprietary to the Khronos Group, Inc. You may use these materials
+ * for implementing Khronos specifications, without altering or removing
+ * any trademark, copyright or other notice from the specification.
+ *
+ * Khronos Group makes no, and expressly disclaims any, representations
+ * or warranties, express or implied, regarding these materials, including,
+ * without limitation, any implied warranties of merchantability or fitness
+ * for a particular purpose or non-infringement of any intellectual property.
+ * Khronos Group makes no, and expressly disclaims any, warranties, express
+ * or implied, regarding the correctness, accuracy, completeness, timeliness,
+ * and reliability of these materials.
+ *
+ * Under no circumstances will the Khronos Group, or any of its Promoters,
+ * Contributors or Members or their respective partners, officers, directors,
+ * employees, agents or representatives be liable for any damages, whether
+ * direct, indirect, special or consequential damages for lost revenues,
+ * lost profits, or otherwise, arising from or in connection with these
+ * materials.
+ *
+ * Khronos and OpenMAX are trademarks of the Khronos Group Inc.
+ *
+ */
+
+/* *****************************************************************************************/
+
+#ifndef _OMXVC_H_
+#define _OMXVC_H_
+
+#include "omxtypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* 6.1.1.1 Motion Vectors */
+/* In omxVC, motion vectors are represented as follows: */
+
+typedef struct {
+ OMX_S16 dx;
+ OMX_S16 dy;
+} OMXVCMotionVector;
+
+
+
+/**
+ * Function: omxVCCOMM_Average_8x (6.1.3.1.1)
+ *
+ * Description:
+ * This function calculates the average of two 8x4, 8x8, or 8x16 blocks. The
+ * result is rounded according to (a+b+1)/2. The block average function can
+ * be used in conjunction with half-pixel interpolation to obtain quarter
+ * pixel motion estimates, as described in [ISO14496-10], subclause 8.4.2.2.1.
+ *
+ * Input Arguments:
+ *
+ * pPred0 - Pointer to the top-left corner of reference block 0
+ * pPred1 - Pointer to the top-left corner of reference block 1
+ * iPredStep0 - Step of reference block 0
+ * iPredStep1 - Step of reference block 1
+ * iDstStep - Step of the destination buffer.
+ * iHeight - Height of the blocks
+ *
+ * Output Arguments:
+ *
+ * pDstPred - Pointer to the destination buffer. 8-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pPred0, pPred1, or
+ * pDstPred.
+ * - pDstPred is not aligned on an 8-byte boundary.
+ * - iPredStep0 <= 0 or iPredStep0 is not a multiple of 8.
+ * - iPredStep1 <= 0 or iPredStep1 is not a multiple of 8.
+ * - iDstStep <= 0 or iDstStep is not a multiple of 8.
+ * - iHeight is not 4, 8, or 16.
+ *
+ */
+OMXResult omxVCCOMM_Average_8x (
+ const OMX_U8 *pPred0,
+ const OMX_U8 *pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8 *pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCCOMM_Average_16x (6.1.3.1.2)
+ *
+ * Description:
+ * This function calculates the average of two 16x16 or 16x8 blocks. The
+ * result is rounded according to (a+b+1)/2. The block average function can
+ * be used in conjunction with half-pixel interpolation to obtain quarter
+ * pixel motion estimates, as described in [ISO14496-10], subclause 8.4.2.2.1.
+ *
+ * Input Arguments:
+ *
+ * pPred0 - Pointer to the top-left corner of reference block 0
+ * pPred1 - Pointer to the top-left corner of reference block 1
+ * iPredStep0 - Step of reference block 0
+ * iPredStep1 - Step of reference block 1
+ * iDstStep - Step of the destination buffer
+ * iHeight - Height of the blocks
+ *
+ * Output Arguments:
+ *
+ * pDstPred - Pointer to the destination buffer. 16-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pPred0, pPred1, or
+ * pDstPred.
+ * - pDstPred is not aligned on a 16-byte boundary.
+ * - iPredStep0 <= 0 or iPredStep0 is not a multiple of 16.
+ * - iPredStep1 <= 0 or iPredStep1 is not a multiple of 16.
+ * - iDstStep <= 0 or iDstStep is not a multiple of 16.
+ * - iHeight is not 8 or 16.
+ *
+ */
+OMXResult omxVCCOMM_Average_16x (
+ const OMX_U8 *pPred0,
+ const OMX_U8 *pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8 *pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCCOMM_ExpandFrame_I (6.1.3.2.1)
+ *
+ * Description:
+ * This function expands a reconstructed frame in-place. The unexpanded
+ * source frame should be stored in a plane buffer with sufficient space
+ * pre-allocated for edge expansion, and the input frame should be located in
+ * the plane buffer center. This function executes the pixel expansion by
+ * replicating source frame edge pixel intensities in the empty pixel
+ * locations (expansion region) between the source frame edge and the plane
+ * buffer edge. The width/height of the expansion regions on the
+ * horizontal/vertical edges is controlled by the parameter iExpandPels.
+ *
+ * Input Arguments:
+ *
+ * pSrcDstPlane - pointer to the top-left corner of the frame to be
+ * expanded; must be aligned on an 8-byte boundary.
+ * iFrameWidth - frame width; must be a multiple of 8.
+ * iFrameHeight -frame height; must be a multiple of 8.
+ * iExpandPels - number of pixels to be expanded in the horizontal and
+ * vertical directions; must be a multiple of 8.
+ * iPlaneStep - distance, in bytes, between the start of consecutive lines
+ * in the plane buffer; must be larger than or equal to
+ * (iFrameWidth + 2 * iExpandPels).
+ *
+ * Output Arguments:
+ *
+ * pSrcDstPlane -Pointer to the top-left corner of the frame (NOT the
+ * top-left corner of the plane); must be aligned on an 8-byte
+ * boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - pSrcDstPlane is NULL.
+ * - pSrcDstPlane is not aligned on an 8-byte boundary.
+ * - one of the following parameters is either equal to zero or is a
+ * non-multiple of 8: iFrameHeight, iFrameWidth, iPlaneStep, or
+ * iExpandPels.
+ * - iPlaneStep < (iFrameWidth + 2 * iExpandPels).
+ *
+ */
+OMXResult omxVCCOMM_ExpandFrame_I (
+ OMX_U8 *pSrcDstPlane,
+ OMX_U32 iFrameWidth,
+ OMX_U32 iFrameHeight,
+ OMX_U32 iExpandPels,
+ OMX_U32 iPlaneStep
+);
+
+
+
+/**
+ * Function: omxVCCOMM_Copy8x8 (6.1.3.3.1)
+ *
+ * Description:
+ * Copies the reference 8x8 block to the current block.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the reference block in the source frame; must be
+ * aligned on an 8-byte boundary.
+ * step - distance between the starts of consecutive lines in the reference
+ * frame, in bytes; must be a multiple of 8 and must be larger than
+ * or equal to 8.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination block; must be aligned on an 8-byte
+ * boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pSrc, pDst
+ * - one or more of the following pointers is not aligned on an 8-byte
+ * boundary: pSrc, pDst
+ * - step <8 or step is not a multiple of 8.
+ *
+ */
+OMXResult omxVCCOMM_Copy8x8 (
+ const OMX_U8 *pSrc,
+ OMX_U8 *pDst,
+ OMX_INT step
+);
+
+
+
+/**
+ * Function: omxVCCOMM_Copy16x16 (6.1.3.3.2)
+ *
+ * Description:
+ * Copies the reference 16x16 macroblock to the current macroblock.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the reference macroblock in the source frame; must be
+ * aligned on a 16-byte boundary.
+ * step - distance between the starts of consecutive lines in the reference
+ * frame, in bytes; must be a multiple of 16 and must be larger
+ * than or equal to 16.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination macroblock; must be aligned on a
+ * 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pSrc, pDst
+ * - one or more of the following pointers is not aligned on a 16-byte
+ * boundary: pSrc, pDst
+ * - step <16 or step is not a multiple of 16.
+ *
+ */
+OMXResult omxVCCOMM_Copy16x16 (
+ const OMX_U8 *pSrc,
+ OMX_U8 *pDst,
+ OMX_INT step
+);
+
+
+
+/**
+ * Function: omxVCCOMM_ComputeTextureErrorBlock_SAD (6.1.4.1.1)
+ *
+ * Description:
+ * Computes texture error of the block; also returns SAD.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the source plane; must be aligned on an 8-byte
+ * boundary.
+ * srcStep - step of the source plane
+ * pSrcRef - pointer to the reference buffer, an 8x8 block; must be aligned
+ * on an 8-byte boundary.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination buffer, an 8x8 block; must be aligned
+ * on an 8-byte boundary.
+ * pDstSAD - pointer to the Sum of Absolute Differences (SAD) value
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - At least one of the following
+ * pointers is NULL: pSrc, pSrcRef, pDst and pDstSAD.
+ * - pSrc is not 8-byte aligned.
+ * - SrcStep <= 0 or srcStep is not a multiple of 8.
+ * - pSrcRef is not 8-byte aligned.
+ * - pDst is not 8-byte aligned.
+ *
+ */
+OMXResult omxVCCOMM_ComputeTextureErrorBlock_SAD (
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ const OMX_U8 *pSrcRef,
+ OMX_S16 *pDst,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCCOMM_ComputeTextureErrorBlock (6.1.4.1.2)
+ *
+ * Description:
+ * Computes the texture error of the block.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the source plane. This should be aligned on an 8-byte
+ * boundary.
+ * srcStep - step of the source plane
+ * pSrcRef - pointer to the reference buffer, an 8x8 block. This should be
+ * aligned on an 8-byte boundary.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination buffer, an 8x8 block. This should be
+ * aligned on an 8-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is NULL:
+ * pSrc, pSrcRef, pDst.
+ * - pSrc is not 8-byte aligned.
+ * - SrcStep <= 0 or srcStep is not a multiple of 8.
+ * - pSrcRef is not 8-byte aligned.
+ * - pDst is not 8-byte aligned
+ *
+ */
+OMXResult omxVCCOMM_ComputeTextureErrorBlock (
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ const OMX_U8 *pSrcRef,
+ OMX_S16 *pDst
+);
+
+
+
+/**
+ * Function: omxVCCOMM_LimitMVToRect (6.1.4.1.3)
+ *
+ * Description:
+ * Limits the motion vector associated with the current block/macroblock to
+ * prevent the motion compensated block/macroblock from moving outside a
+ * bounding rectangle as shown in Figure 6-1.
+ *
+ * Input Arguments:
+ *
+ * pSrcMV - pointer to the motion vector associated with the current block
+ * or macroblock
+ * pRectVOPRef - pointer to the bounding rectangle
+ * Xcoord, Ycoord - coordinates of the current block or macroblock
+ * size - size of the current block or macroblock; must be equal to 8 or
+ * 16.
+ *
+ * Output Arguments:
+ *
+ * pDstMV - pointer to the limited motion vector
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcMV, pDstMV, or pRectVOPRef.
+ * - size is not equal to either 8 or 16.
+ * - the width or height of the bounding rectangle is less than
+ * twice the block size.
+ */
+OMXResult omxVCCOMM_LimitMVToRect (
+ const OMXVCMotionVector *pSrcMV,
+ OMXVCMotionVector *pDstMV,
+ const OMXRect *pRectVOPRef,
+ OMX_INT Xcoord,
+ OMX_INT Ycoord,
+ OMX_INT size
+);
+
+
+
+/**
+ * Function: omxVCCOMM_SAD_16x (6.1.4.1.4)
+ *
+ * Description:
+ * This function calculates the SAD for 16x16 and 16x8 blocks.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to the original block; must be aligned on a 16-byte
+ * boundary.
+ * iStepOrg - Step of the original block buffer
+ * pSrcRef - Pointer to the reference block
+ * iStepRef - Step of the reference block buffer
+ * iHeight - Height of the block
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - Pointer of result SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pDstSAD, or pSrcRef
+ * - pSrcOrg is not 16-byte aligned.
+ * - iStepOrg <= 0 or iStepOrg is not a multiple of 16
+ * - iStepRef <= 0 or iStepRef is not a multiple of 16
+ * - iHeight is not 8 or 16
+ *
+ */
+OMXResult omxVCCOMM_SAD_16x (
+ const OMX_U8 *pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8 *pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCCOMM_SAD_8x (6.1.4.1.5)
+ *
+ * Description:
+ * This function calculates the SAD for 8x16, 8x8, 8x4 blocks.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to the original block; must be aligned on a 8-byte
+ * boundary.
+ * iStepOrg - Step of the original block buffer
+ * pSrcRef - Pointer to the reference block
+ * iStepRef - Step of the reference block buffer
+ * iHeight - Height of the block
+ *
+ * Output Arguments:
+ *
+ * pDstSAD -Pointer of result SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pDstSAD, or pSrcRef
+ * - pSrcOrg is not 8-byte aligned.
+ * - iStepOrg <= 0 or iStepOrg is not a multiple of 8
+ * - iStepRef <= 0 or iStepRef is not a multiple of 8
+ * - iHeight is not 4, 8 or 16
+ *
+ */
+OMXResult omxVCCOMM_SAD_8x (
+ const OMX_U8 *pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8 *pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32*pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/* 6.2.1.1 Direction */
+/* The direction enumerator is used with functions that perform AC/DC prediction and zig-zag scan. */
+
+enum {
+ OMX_VC_NONE = 0,
+ OMX_VC_HORIZONTAL = 1,
+ OMX_VC_VERTICAL = 2
+};
+
+
+
+/* 6.2.1.2 Bilinear Interpolation */
+/* The bilinear interpolation enumerator is used with motion estimation, motion compensation, and reconstruction functions. */
+
+enum {
+ OMX_VC_INTEGER_PIXEL = 0, /* case a */
+ OMX_VC_HALF_PIXEL_X = 1, /* case b */
+ OMX_VC_HALF_PIXEL_Y = 2, /* case c */
+ OMX_VC_HALF_PIXEL_XY = 3 /* case d */
+};
+
+
+
+/* 6.2.1.3 Neighboring Macroblock Availability */
+/* Neighboring macroblock availability is indicated using the following flags: */
+
+enum {
+ OMX_VC_UPPER = 1, /** above macroblock is available */
+ OMX_VC_LEFT = 2, /** left macroblock is available */
+ OMX_VC_CENTER = 4,
+ OMX_VC_RIGHT = 8,
+ OMX_VC_LOWER = 16,
+ OMX_VC_UPPER_LEFT = 32, /** above-left macroblock is available */
+ OMX_VC_UPPER_RIGHT = 64, /** above-right macroblock is available */
+ OMX_VC_LOWER_LEFT = 128,
+ OMX_VC_LOWER_RIGHT = 256
+};
+
+
+
+/* 6.2.1.4 Video Components */
+/* A data type that enumerates video components is defined as follows: */
+
+typedef enum {
+ OMX_VC_LUMINANCE, /** Luminance component */
+ OMX_VC_CHROMINANCE /** chrominance component */
+} OMXVCM4P2VideoComponent;
+
+
+
+/* 6.2.1.5 MacroblockTypes */
+/* A data type that enumerates macroblock types is defined as follows: */
+
+typedef enum {
+ OMX_VC_INTER = 0, /** P picture or P-VOP */
+ OMX_VC_INTER_Q = 1, /** P picture or P-VOP */
+ OMX_VC_INTER4V = 2, /** P picture or P-VOP */
+ OMX_VC_INTRA = 3, /** I and P picture, I- and P-VOP */
+ OMX_VC_INTRA_Q = 4, /** I and P picture, I- and P-VOP */
+ OMX_VC_INTER4V_Q = 5 /** P picture or P-VOP (H.263)*/
+} OMXVCM4P2MacroblockType;
+
+
+
+/* 6.2.1.6 Coordinates */
+/* Coordinates are represented as follows: */
+
+typedef struct {
+ OMX_INT x;
+ OMX_INT y;
+} OMXVCM4P2Coordinate;
+
+
+
+/* 6.2.1.7 Motion Estimation Algorithms */
+/* A data type that enumerates motion estimation search methods is defined as follows: */
+
+typedef enum {
+ OMX_VC_M4P2_FAST_SEARCH = 0, /** Fast motion search */
+ OMX_VC_M4P2_FULL_SEARCH = 1 /** Full motion search */
+} OMXVCM4P2MEMode;
+
+
+
+/* 6.2.1.8 Motion Estimation Parameters */
+/* A data structure containing control parameters for
+ * motion estimation functions is defined as follows:
+ */
+
+typedef struct {
+ OMX_INT searchEnable8x8; /** enables 8x8 search */
+ OMX_INT halfPelSearchEnable; /** enables half-pel resolution */
+ OMX_INT searchRange; /** search range */
+ OMX_INT rndVal; /** rounding control; 0-disabled, 1-enabled*/
+} OMXVCM4P2MEParams;
+
+
+
+/* 6.2.1.9 Macroblock Information */
+/* A data structure containing macroblock parameters for
+ * motion estimation functions is defined as follows:
+ */
+
+typedef struct {
+ OMX_S32 sliceId; /* slice number */
+ OMXVCM4P2MacroblockType mbType; /* MB type: OMX_VC_INTRA, OMX_VC_INTER, or OMX_VC_INTER4 */
+ OMX_S32 qp; /* quantization parameter*/
+ OMX_U32 cbpy; /* CBP Luma */
+ OMX_U32 cbpc; /* CBP Chroma */
+ OMXVCMotionVector pMV0[2][2]; /* motion vector, represented using 1/2-pel units,
+ * pMV0[blocky][blockx] (blocky = 0~1, blockx =0~1)
+ */
+ OMXVCMotionVector pMVPred[2][2]; /* motion vector prediction, represented using 1/2-pel units,
+ * pMVPred[blocky][blockx] (blocky = 0~1, blockx = 0~1)
+ */
+ OMX_U8 pPredDir[2][2]; /* AC prediction direction:
+ * OMX_VC_NONE, OMX_VC_VERTICAL, OMX_VC_HORIZONTAL
+ */
+} OMXVCM4P2MBInfo, *OMXVCM4P2MBInfoPtr;
+
+
+
+/**
+ * Function: omxVCM4P2_FindMVpred (6.2.3.1.1)
+ *
+ * Description:
+ * Predicts a motion vector for the current block using the procedure
+ * specified in [ISO14496-2], subclause 7.6.5. The resulting predicted MV is
+ * returned in pDstMVPred. If the parameter pDstMVPredME if is not NULL then
+ * the set of three MV candidates used for prediction is also returned,
+ * otherwise pDstMVPredMEis NULL upon return.
+ *
+ * Input Arguments:
+ *
+ * pSrcMVCurMB - pointer to the MV buffer associated with the current Y
+ * macroblock; a value of NULL indicates unavailability.
+ * pSrcCandMV1 - pointer to the MV buffer containing the 4 MVs associated
+ * with the MB located to the left of the current MB; set to NULL
+ * if there is no MB to the left.
+ * pSrcCandMV2 - pointer to the MV buffer containing the 4 MVs associated
+ * with the MB located above the current MB; set to NULL if there
+ * is no MB located above the current MB.
+ * pSrcCandMV3 - pointer to the MV buffer containing the 4 MVs associated
+ * with the MB located to the right and above the current MB; set
+ * to NULL if there is no MB located to the above-right.
+ * iBlk - the index of block in the current macroblock
+ * pDstMVPredME - MV candidate return buffer; if set to NULL then
+ * prediction candidate MVs are not returned and pDstMVPredME will
+ * be NULL upon function return; if pDstMVPredME is non-NULL then it
+ * must point to a buffer containing sufficient space for three
+ * return MVs.
+ *
+ * Output Arguments:
+ *
+ * pDstMVPred - pointer to the predicted motion vector
+ * pDstMVPredME - if non-NULL upon input then pDstMVPredME points upon
+ * return to a buffer containing the three motion vector candidates
+ * used for prediction as specified in [ISO14496-2], subclause
+ * 7.6.5, otherwise if NULL upon input then pDstMVPredME is NULL
+ * upon output.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - the pointer pDstMVPred is NULL
+ * - the parameter iBlk does not fall into the range 0 <= iBlk<=3
+ *
+ */
+OMXResult omxVCM4P2_FindMVpred (
+ const OMXVCMotionVector *pSrcMVCurMB,
+ const OMXVCMotionVector *pSrcCandMV1,
+ const OMXVCMotionVector *pSrcCandMV2,
+ const OMXVCMotionVector *pSrcCandMV3,
+ OMXVCMotionVector *pDstMVPred,
+ OMXVCMotionVector *pDstMVPredME,
+ OMX_INT iBlk
+);
+
+
+
+/**
+ * Function: omxVCM4P2_IDCT8x8blk (6.2.3.2.1)
+ *
+ * Description:
+ * Computes a 2D inverse DCT for a single 8x8 block, as defined in
+ * [ISO14496-2].
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the start of the linearly arranged IDCT input buffer;
+ * must be aligned on a 16-byte boundary. According to
+ * [ISO14496-2], the input coefficient values should lie within the
+ * range [-2048, 2047].
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the start of the linearly arranged IDCT output buffer;
+ * must be aligned on a 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - pSrc or pDst is NULL.
+ * - pSrc or pDst is not 16-byte aligned.
+ *
+ */
+OMXResult omxVCM4P2_IDCT8x8blk (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst
+);
+
+
+
+/**
+ * Function: omxVCM4P2_MEGetBufSize (6.2.4.1.1)
+ *
+ * Description:
+ * Computes the size, in bytes, of the vendor-specific specification
+ * structure for the following motion estimation functions:
+ * BlockMatch_Integer_8x8, BlockMatch_Integer_16x16, and MotionEstimationMB.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P2MEMode
+ * pMEParams - motion estimation parameters
+ *
+ * Output Arguments:
+ *
+ * pSize - pointer to the number of bytes required for the specification
+ * structure
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - one or more of the following is true:
+ * - an invalid value was specified for the parameter MEmode
+ * - a negative or zero value was specified for the
+ * parameter pMEParams->searchRange
+ *
+ */
+OMXResult omxVCM4P2_MEGetBufSize (
+ OMXVCM4P2MEMode MEmode,
+ const OMXVCM4P2MEParams *pMEParams,
+ OMX_U32 *pSize
+);
+
+
+
+/**
+ * Function: omxVCM4P2_MEInit (6.2.4.1.2)
+ *
+ * Description:
+ * Initializes the vendor-specific specification structure required for the
+ * following motion estimation functions: BlockMatch_Integer_8x8,
+ * BlockMatch_Integer_16x16, and MotionEstimationMB. Memory for the
+ * specification structure *pMESpec must be allocated prior to calling the
+ * function, and should be aligned on a 4-byte boundary. Following
+ * initialization by this function, the vendor-specific structure *pMESpec
+ * should contain an implementation-specific representation of all motion
+ * estimation parameters received via the structure pMEParams, for example
+ * rndVal, searchRange, etc. The number of bytes required for the
+ * specification structure can be determined using the function
+ * omxVCM4P2_MEGetBufSize.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P2MEMode
+ * pMEParams - motion estimation parameters
+ * pMESpec - pointer to the uninitialized ME specification structure
+ *
+ * Output Arguments:
+ *
+ * pMESpec - pointer to the initialized ME specification structure
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - one or more of the following is true:
+ * - an invalid value was specified for the parameter MEmode
+ * - a negative or zero value was specified for the
+ * parameter pMEParams->searchRange
+ *
+ */
+OMXResult omxVCM4P2_MEInit (
+ OMXVCM4P2MEMode MEmode,
+ const OMXVCM4P2MEParams*pMEParams,
+ void *pMESpec
+);
+
+
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Integer_16x16 (6.2.4.2.1)
+ *
+ * Description:
+ * Performs a 16x16 block search; estimates motion vector and associated
+ * minimum SAD. Both the input and output motion vectors are represented using
+ * half-pixel units, and therefore a shift left or right by 1 bit may be
+ * required, respectively, to match the input or output MVs with other
+ * functions that either generate output MVs or expect input MVs represented
+ * using integer pixel units.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * MB that corresponds to the location of the current macroblock in
+ * the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - pointer to the valid reference plane rectangle; coordinates
+ * are specified relative to the image origin. Rectangle
+ * boundaries may extend beyond image boundaries if the image has
+ * been padded. For example, if padding extends 4 pixels beyond
+ * frame border, then the value for the left border could be set to
+ * -4.
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 256
+ * entries); must be aligned on a 16-byte boundary. The number of
+ * bytes between lines (step) is 16.
+ * pCurrPointPos - position of the current macroblock in the current plane
+ * pSrcPreMV - pointer to predicted motion vector; NULL indicates no
+ * predicted MV
+ * pSrcPreSAD - pointer to SAD associated with the predicted MV (referenced
+ * by pSrcPreMV); may be set to NULL if unavailable.
+ * pMESpec - vendor-specific motion estimation specification structure;
+ * must have been allocated and then initialized using
+ * omxVCM4P2_MEInit prior to calling the block matching function.
+ *
+ * Output Arguments:
+ *
+ * pDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL: pSrcRefBuf,
+ * pRefRect, pSrcCurrBuff, pCurrPointPos, pDstMV, pDstSAD or
+ * pMESpec, or
+ * - pSrcCurrBuf is not 16-byte aligned
+ *
+ */
+OMXResult omxVCM4P2_BlockMatch_Integer_16x16 (
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCMotionVector*pSrcPreMV,
+ const OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector*pDstMV,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Integer_8x8 (6.2.4.2.2)
+ *
+ * Description:
+ * Performs an 8x8 block search; estimates motion vector and associated
+ * minimum SAD. Both the input and output motion vectors are represented
+ * using half-pixel units, and therefore a shift left or right by 1 bit may be
+ * required, respectively, to match the input or output MVs with other
+ * functions that either generate output MVs or expect input MVs represented
+ * using integer pixel units.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * block that corresponds to the location of the current 8x8 block
+ * in the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - pointer to the valid reference plane rectangle; coordinates
+ * are specified relative to the image origin. Rectangle
+ * boundaries may extend beyond image boundaries if the image has
+ * been padded.
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 128
+ * entries); must be aligned on an 8-byte boundary. The number of
+ * bytes between lines (step) is 16 bytes.
+ * pCurrPointPos - position of the current block in the current plane
+ * pSrcPreMV - pointer to predicted motion vector; NULL indicates no
+ * predicted MV
+ * pSrcPreSAD - pointer to SAD associated with the predicted MV (referenced
+ * by pSrcPreMV); may be set to NULL if unavailable.
+ * pMESpec - vendor-specific motion estimation specification structure;
+ * must have been allocated and then initialized using
+ * omxVCM4P2_MEInit prior to calling the block matching function.
+ *
+ * Output Arguments:
+ *
+ * pDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL: pSrcRefBuf,
+ * pRefRect, pSrcCurrBuff, pCurrPointPos, pDstMV, pDstSAD or
+ * pMESpec, or
+ * - pSrcCurrBuf is not 8-byte aligned
+ *
+ */
+OMXResult omxVCM4P2_BlockMatch_Integer_8x8 (
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCMotionVector *pSrcPreMV,
+ const OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector *pDstMV,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Half_16x16 (6.2.4.2.3)
+ *
+ * Description:
+ * Performs a 16x16 block match with half-pixel resolution. Returns the
+ * estimated motion vector and associated minimum SAD. This function
+ * estimates the half-pixel motion vector by interpolating the integer
+ * resolution motion vector referenced by the input parameter pSrcDstMV, i.e.,
+ * the initial integer MV is generated externally. The input parameters
+ * pSrcRefBuf and pSearchPointRefPos should be shifted by the winning MV of
+ * 16x16 integer search prior to calling BlockMatch_Half_16x16. The function
+ * BlockMatch_Integer_16x16 may be used for integer motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * macroblock that corresponds to the location of the current
+ * macroblock in the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - reference plane valid region rectangle
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 256
+ * entries); must be aligned on a 16-byte boundary. The number of
+ * bytes between lines (step) is 16.
+ * pSearchPointRefPos - position of the starting point for half pixel
+ * search (specified in terms of integer pixel units) in the
+ * reference plane, i.e., the reference position pointed to by the
+ * predicted motion vector.
+ * rndVal - rounding control parameter: 0 - disabled; 1 - enabled.
+ * pSrcDstMV - pointer to the initial MV estimate; typically generated
+ * during a prior 16X16 integer search; specified in terms of
+ * half-pixel units.
+ *
+ * Output Arguments:
+ *
+ * pSrcDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL: pSrcRefBuf,
+ * pRefRect, pSrcCurrBuff, pSearchPointRefPos, pSrcDstMV.
+ * - pSrcCurrBuf is not 16-byte aligned, or
+ *
+ */
+OMXResult omxVCM4P2_BlockMatch_Half_16x16 (
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pSearchPointRefPos,
+ OMX_INT rndVal,
+ OMXVCMotionVector *pSrcDstMV,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Half_8x8 (6.2.4.2.4)
+ *
+ * Description:
+ * Performs an 8x8 block match with half-pixel resolution. Returns the
+ * estimated motion vector and associated minimum SAD. This function
+ * estimates the half-pixel motion vector by interpolating the integer
+ * resolution motion vector referenced by the input parameter pSrcDstMV, i.e.,
+ * the initial integer MV is generated externally. The input parameters
+ * pSrcRefBuf and pSearchPointRefPos should be shifted by the winning MV of
+ * 8x8 integer search prior to calling BlockMatch_Half_8x8. The function
+ * BlockMatch_Integer_8x8 may be used for integer motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * block that corresponds to the location of the current 8x8 block
+ * in the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - reference plane valid region rectangle
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 128
+ * entries); must be aligned on a 8-byte boundary. The number of
+ * bytes between lines (step) is 16.
+ * pSearchPointRefPos - position of the starting point for half pixel
+ * search (specified in terms of integer pixel units) in the
+ * reference plane.
+ * rndVal - rounding control parameter: 0 - disabled; 1 - enabled.
+ * pSrcDstMV - pointer to the initial MV estimate; typically generated
+ * during a prior 8x8 integer search, specified in terms of
+ * half-pixel units.
+ *
+ * Output Arguments:
+ *
+ * pSrcDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcRefBuf, pRefRect, pSrcCurrBuff, pSearchPointRefPos, pSrcDstMV
+ * - pSrcCurrBuf is not 8-byte aligned
+ *
+ */
+OMXResult omxVCM4P2_BlockMatch_Half_8x8 (
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pSearchPointRefPos,
+ OMX_INT rndVal,
+ OMXVCMotionVector *pSrcDstMV,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_MotionEstimationMB (6.2.4.3.1)
+ *
+ * Description:
+ * Performs motion search for a 16x16 macroblock. Selects best motion search
+ * strategy from among inter-1MV, inter-4MV, and intra modes. Supports
+ * integer and half pixel resolution.
+ *
+ * Input Arguments:
+ *
+ * pSrcCurrBuf - pointer to the top-left corner of the current MB in the
+ * original picture plane; must be aligned on a 16-byte boundary.
+ * The function does not expect source data outside the region
+ * bounded by the MB to be available; for example it is not
+ * necessary for the caller to guarantee the availability of
+ * pSrcCurrBuf[-SrcCurrStep], i.e., the row of pixels above the MB
+ * to be processed.
+ * srcCurrStep - width of the original picture plane, in terms of full
+ * pixels; must be a multiple of 16.
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * plane location corresponding to the location of the current
+ * macroblock in the current plane; must be aligned on a 16-byte
+ * boundary.
+ * srcRefStep - width of the reference picture plane, in terms of full
+ * pixels; must be a multiple of 16.
+ * pRefRect - reference plane valid region rectangle, specified relative to
+ * the image origin
+ * pCurrPointPos - position of the current macroblock in the current plane
+ * pMESpec - pointer to the vendor-specific motion estimation specification
+ * structure; must be allocated and then initialized using
+ * omxVCM4P2_MEInit prior to calling this function.
+ * pMBInfo - array, of dimension four, containing pointers to information
+ * associated with four nearby MBs:
+ * - pMBInfo[0] - pointer to left MB information
+ * - pMBInfo[1] - pointer to top MB information
+ * - pMBInfo[2] - pointer to top-left MB information
+ * - pMBInfo[3] - pointer to top-right MB information
+ * Any pointer in the array may be set equal to NULL if the
+ * corresponding MB doesn't exist. For each MB, the following structure
+ * members are used:
+ * - mbType - macroblock type, either OMX_VC_INTRA, OMX_VC_INTER, or
+ * OMX_VC_INTER4V
+ * - pMV0[2][2] - estimated motion vectors; represented
+ * in 1/2 pixel units
+ * - sliceID - number of the slice to which the MB belongs
+ * pSrcDstMBCurr - pointer to information structure for the current MB.
+ * The following entries should be set prior to calling the
+ * function: sliceID - the number of the slice the to which the
+ * current MB belongs. The structure elements cbpy and cbpc are
+ * ignored.
+ *
+ * Output Arguments:
+ *
+ * pSrcDstMBCurr - pointer to updated information structure for the current
+ * MB after MB-level motion estimation has been completed. The
+ * following structure members are updated by the ME function:
+ * - mbType - macroblock type: OMX_VC_INTRA, OMX_VC_INTER, or
+ * OMX_VC_INTER4V.
+ * - pMV0[2][2] - estimated motion vectors; represented in
+ * terms of 1/2 pel units.
+ * - pMVPred[2][2] - predicted motion vectors; represented
+ * in terms of 1/2 pel units.
+ * The structure members cbpy and cbpc are not updated by the function.
+ * pDstSAD - pointer to the minimum SAD for INTER1V, or sum of minimum SADs
+ * for INTER4V
+ * pDstBlockSAD - pointer to an array of SAD values for each of the four
+ * 8x8 luma blocks in the MB. The block SADs are in scan order for
+ * each MB.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL: pSrcCurrBuf,
+ * pSrcRefBuf, pRefRect, pCurrPointPos, pMBInter, pMBIntra,
+ * pSrcDstMBCurr, or pDstSAD.
+ *
+ */
+OMXResult omxVCM4P2_MotionEstimationMB (
+ const OMX_U8 *pSrcCurrBuf,
+ OMX_S32 srcCurrStep,
+ const OMX_U8 *pSrcRefBuf,
+ OMX_S32 srcRefStep,
+ const OMXRect*pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ void *pMESpec,
+ const OMXVCM4P2MBInfoPtr *pMBInfo,
+ OMXVCM4P2MBInfo *pSrcDstMBCurr,
+ OMX_U16 *pDstSAD,
+ OMX_U16 *pDstBlockSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DCT8x8blk (6.2.4.4.1)
+ *
+ * Description:
+ * Computes a 2D forward DCT for a single 8x8 block, as defined in
+ * [ISO14496-2].
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the start of the linearly arranged input buffer; must
+ * be aligned on a 16-byte boundary. Input values (pixel
+ * intensities) are valid in the range [-255,255].
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the start of the linearly arranged output buffer; must
+ * be aligned on a 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, returned if:
+ * - pSrc or pDst is NULL.
+ * - pSrc or pDst is not 16-byte aligned.
+ *
+ */
+OMXResult omxVCM4P2_DCT8x8blk (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst
+);
+
+
+
+/**
+ * Function: omxVCM4P2_QuantIntra_I (6.2.4.4.2)
+ *
+ * Description:
+ * Performs quantization on intra block coefficients. This function supports
+ * bits_per_pixel == 8.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input intra block coefficients; must be aligned
+ * on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale).
+ * blockIndex - block index indicating the component type and position,
+ * valid in the range 0 to 5, as defined in [ISO14496-2], subclause
+ * 6.1.3.8.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (quantized) interblock coefficients.
+ * When shortVideoHeader==1, AC coefficients are saturated on the
+ * interval [-127, 127], and DC coefficients are saturated on the
+ * interval [1, 254]. When shortVideoHeader==0, AC coefficients
+ * are saturated on the interval [-2047, 2047].
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - pSrcDst is NULL.
+ * - blockIndex < 0 or blockIndex >= 10
+ * - QP <= 0 or QP >= 32.
+ *
+ */
+OMXResult omxVCM4P2_QuantIntra_I (
+ OMX_S16 *pSrcDst,
+ OMX_U8 QP,
+ OMX_INT blockIndex,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_QuantInter_I (6.2.4.4.3)
+ *
+ * Description:
+ * Performs quantization on an inter coefficient block; supports
+ * bits_per_pixel == 8.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input inter block coefficients; must be aligned
+ * on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale)
+ * shortVideoHeader - binary flag indicating presence of short_video_header;
+ * shortVideoHeader==1 selects linear intra DC mode, and
+ * shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (quantized) interblock coefficients.
+ * When shortVideoHeader==1, AC coefficients are saturated on the
+ * interval [-127, 127], and DC coefficients are saturated on the
+ * interval [1, 254]. When shortVideoHeader==0, AC coefficients
+ * are saturated on the interval [-2047, 2047].
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - pSrcDst is NULL.
+ * - QP <= 0 or QP >= 32.
+ *
+ */
+OMXResult omxVCM4P2_QuantInter_I (
+ OMX_S16 *pSrcDst,
+ OMX_U8 QP,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_TransRecBlockCoef_intra (6.2.4.4.4)
+ *
+ * Description:
+ * Quantizes the DCT coefficients, implements intra block AC/DC coefficient
+ * prediction, and reconstructs the current intra block texture for prediction
+ * on the next frame. Quantized row and column coefficients are returned in
+ * the updated coefficient buffers.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the pixels of current intra block; must be aligned on
+ * an 8-byte boundary.
+ * pPredBufRow - pointer to the coefficient row buffer containing
+ * ((num_mb_per_row * 2 + 1) * 8) elements of type OMX_S16.
+ * Coefficients are organized into blocks of eight as described
+ * below (Internal Prediction Coefficient Update Procedures). The
+ * DC coefficient is first, and the remaining buffer locations
+ * contain the quantized AC coefficients. Each group of eight row
+ * buffer elements combined with one element eight elements ahead
+ * contains the coefficient predictors of the neighboring block
+ * that is spatially above or to the left of the block currently to
+ * be decoded. A negative-valued DC coefficient indicates that this
+ * neighboring block is not INTRA-coded or out of bounds, and
+ * therefore the AC and DC coefficients are invalid. Pointer must
+ * be aligned on an 8-byte boundary.
+ * pPredBufCol - pointer to the prediction coefficient column buffer
+ * containing 16 elements of type OMX_S16. Coefficients are
+ * organized as described in section 6.2.2.5. Pointer must be
+ * aligned on an 8-byte boundary.
+ * pSumErr - pointer to a flag indicating whether or not AC prediction is
+ * required; AC prediction is enabled if *pSumErr >=0, but the
+ * value is not used for coefficient prediction, i.e., the sum of
+ * absolute differences starts from 0 for each call to this
+ * function. Otherwise AC prediction is disabled if *pSumErr < 0 .
+ * blockIndex - block index indicating the component type and position, as
+ * defined in [ISO14496-2], subclause 6.1.3.8.
+ * curQp - quantization parameter of the macroblock to which the current
+ * block belongs
+ * pQpBuf - pointer to a 2-element quantization parameter buffer; pQpBuf[0]
+ * contains the quantization parameter associated with the 8x8
+ * block left of the current block (QPa), and pQpBuf[1] contains
+ * the quantization parameter associated with the 8x8 block above
+ * the current block (QPc). In the event that the corresponding
+ * block is outside of the VOP bound, the Qp value will not affect
+ * the intra prediction process, as described in [ISO14496-2],
+ * sub-clause 7.4.3.3, Adaptive AC Coefficient Prediction.
+ * srcStep - width of the source buffer; must be a multiple of 8.
+ * dstStep - width of the reconstructed destination buffer; must be a
+ * multiple of 16.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the quantized DCT coefficient buffer; pDst[0] contains
+ * the predicted DC coefficient; the remaining entries contain the
+ * quantized AC coefficients (without prediction). The pointer
+ * pDstmust be aligned on a 16-byte boundary.
+ * pRec - pointer to the reconstructed texture; must be aligned on an
+ * 8-byte boundary.
+ * pPredBufRow - pointer to the updated coefficient row buffer
+ * pPredBufCol - pointer to the updated coefficient column buffer
+ * pPreACPredict - if prediction is enabled, the parameter points to the
+ * start of the buffer containing the coefficient differences for
+ * VLC encoding. The entry pPreACPredict[0]indicates prediction
+ * direction for the current block and takes one of the following
+ * values: OMX_VC_NONE (prediction disabled), OMX_VC_HORIZONTAL, or
+ * OMX_VC_VERTICAL. The entries
+ * pPreACPredict[1]-pPreACPredict[7]contain predicted AC
+ * coefficients. If prediction is disabled (*pSumErr<0) then the
+ * contents of this buffer are undefined upon return from the
+ * function
+ * pSumErr - pointer to the value of the accumulated AC coefficient errors,
+ * i.e., sum of the absolute differences between predicted and
+ * unpredicted AC coefficients
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ * - At least one of the following pointers is NULL: pSrc, pDst, pRec,
+ * pCoefBufRow, pCoefBufCol, pQpBuf, pPreACPredict, pSumErr.
+ * - blockIndex < 0 or blockIndex >= 10;
+ * - curQP <= 0 or curQP >= 32.
+ * - srcStep, or dstStep <= 0 or not a multiple of 8.
+ * - pDst is not 16-byte aligned: .
+ * - At least one of the following pointers is not 8-byte aligned:
+ * pSrc, pRec.
+ *
+ * Note: The coefficient buffers must be updated in accordance with the
+ * update procedures defined in section in 6.2.2.
+ *
+ */
+OMXResult omxVCM4P2_TransRecBlockCoef_intra (
+ const OMX_U8 *pSrc,
+ OMX_S16 *pDst,
+ OMX_U8 *pRec,
+ OMX_S16 *pPredBufRow,
+ OMX_S16 *pPredBufCol,
+ OMX_S16 *pPreACPredict,
+ OMX_INT *pSumErr,
+ OMX_INT blockIndex,
+ OMX_U8 curQp,
+ const OMX_U8 *pQpBuf,
+ OMX_INT srcStep,
+ OMX_INT dstStep,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_TransRecBlockCoef_inter (6.2.4.4.5)
+ *
+ * Description:
+ * Implements DCT, and quantizes the DCT coefficients of the inter block
+ * while reconstructing the texture residual. There is no boundary check for
+ * the bit stream buffer.
+ *
+ * Input Arguments:
+ *
+ * pSrc -pointer to the residuals to be encoded; must be aligned on an
+ * 16-byte boundary.
+ * QP - quantization parameter.
+ * shortVideoHeader - binary flag indicating presence of short_video_header;
+ * shortVideoHeader==1 selects linear intra DC mode, and
+ * shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the quantized DCT coefficients buffer; must be aligned
+ * on a 16-byte boundary.
+ * pRec - pointer to the reconstructed texture residuals; must be aligned
+ * on a 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is either NULL or
+ * not 16-byte aligned:
+ * - pSrc
+ * - pDst
+ * - pRec
+ * - QP <= 0 or QP >= 32.
+ *
+ */
+OMXResult omxVCM4P2_TransRecBlockCoef_inter (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst,
+ OMX_S16 *pRec,
+ OMX_U8 QP,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeVLCZigzag_IntraDCVLC (6.2.4.5.2)
+ *
+ * Description:
+ * Performs zigzag scan and VLC encoding of AC and DC coefficients for one
+ * intra block. Two versions of the function (DCVLC and ACVLC) are provided
+ * in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, "Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding".
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the bitstream
+ * pBitOffset - pointer to the bit position in the byte pointed by
+ * *ppBitStream. Valid within 0 to 7.
+ * pQDctBlkCoef - pointer to the quantized DCT coefficient
+ * predDir - AC prediction direction, which is used to decide the zigzag
+ * scan pattern; takes one of the following values:
+ * - OMX_VC_NONE - AC prediction not used.
+ * Performs classical zigzag scan.
+ * - OMX_VC_HORIZONTAL - Horizontal prediction.
+ * Performs alternate-vertical zigzag scan.
+ * - OMX_VC_VERTICAL - Vertical prediction.
+ * Performs alternate-horizontal zigzag scan.
+ * pattern - block pattern which is used to decide whether this block is
+ * encoded
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ * videoComp - video component type (luminance, chrominance) of the current
+ * block
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is encoded, so
+ * that it points to the current byte in the bit stream buffer.
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ * - At least one of the following pointers is NULL: ppBitStream,
+ * *ppBitStream, pBitOffset, pQDctBlkCoef.
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ * - PredDir is not one of: OMX_VC_NONE, OMX_VC_HORIZONTAL, or
+ * OMX_VC_VERTICAL.
+ * - VideoComp is not one component of enum OMXVCM4P2VideoComponent.
+ *
+ */
+OMXResult omxVCM4P2_EncodeVLCZigzag_IntraDCVLC (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 predDir,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader,
+ OMXVCM4P2VideoComponent videoComp
+);
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeVLCZigzag_IntraACVLC (6.2.4.5.2)
+ *
+ * Description:
+ * Performs zigzag scan and VLC encoding of AC and DC coefficients for one
+ * intra block. Two versions of the function (DCVLC and ACVLC) are provided
+ * in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the bitstream
+ * pBitOffset - pointer to the bit position in the byte pointed by
+ * *ppBitStream. Valid within 0 to 7.
+ * pQDctBlkCoef - pointer to the quantized DCT coefficient
+ * predDir - AC prediction direction, which is used to decide the zigzag
+ * scan pattern; takes one of the following values:
+ * - OMX_VC_NONE - AC prediction not used.
+ * Performs classical zigzag scan.
+ * - OMX_VC_HORIZONTAL - Horizontal prediction.
+ * Performs alternate-vertical zigzag scan.
+ * - OMX_VC_VERTICAL - Vertical prediction.
+ * Performs alternate-horizontal zigzag scan.
+ * pattern - block pattern which is used to decide whether this block is
+ * encoded
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is encoded, so
+ * that it points to the current byte in the bit stream buffer.
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ * - At least one of the following pointers is NULL: ppBitStream,
+ * *ppBitStream, pBitOffset, pQDctBlkCoef.
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ * - PredDir is not one of: OMX_VC_NONE, OMX_VC_HORIZONTAL, or
+ * OMX_VC_VERTICAL.
+ * - VideoComp is not one component of enum OMXVCM4P2VideoComponent.
+ *
+ */
+OMXResult omxVCM4P2_EncodeVLCZigzag_IntraACVLC (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 predDir,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeVLCZigzag_Inter (6.2.4.5.3)
+ *
+ * Description:
+ * Performs classical zigzag scanning and VLC encoding for one inter block.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream
+ * pBitOffset - pointer to the bit position in the byte pointed by
+ * *ppBitStream. Valid within 0 to 7
+ * pQDctBlkCoef - pointer to the quantized DCT coefficient
+ * pattern - block pattern which is used to decide whether this block is
+ * encoded
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is encoded so that
+ * it points to the current byte in the bit stream buffer.
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments
+ * - At least one of the pointers: is NULL: ppBitStream, *ppBitStream,
+ * pBitOffset, pQDctBlkCoef
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ *
+ */
+OMXResult omxVCM4P2_EncodeVLCZigzag_Inter (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeMV (6.2.4.5.4)
+ *
+ * Description:
+ * Predicts a motion vector for the current macroblock, encodes the
+ * difference, and writes the output to the stream buffer. The input MVs
+ * pMVCurMB, pSrcMVLeftMB, pSrcMVUpperMB, and pSrcMVUpperRightMB should lie
+ * within the ranges associated with the input parameter fcodeForward, as
+ * described in [ISO14496-2], subclause 7.6.3. This function provides a
+ * superset of the functionality associated with the function
+ * omxVCM4P2_FindMVpred.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the bitstream buffer
+ * pBitOffset - index of the first free (next available) bit in the stream
+ * buffer referenced by *ppBitStream, valid in the range 0 to 7.
+ * pMVCurMB - pointer to the current macroblock motion vector; a value of
+ * NULL indicates unavailability.
+ * pSrcMVLeftMB - pointer to the source left macroblock motion vector; a
+ * value of NULLindicates unavailability.
+ * pSrcMVUpperMB - pointer to source upper macroblock motion vector; a
+ * value of NULL indicates unavailability.
+ * pSrcMVUpperRightMB - pointer to source upper right MB motion vector; a
+ * value of NULL indicates unavailability.
+ * fcodeForward - an integer with values from 1 to 7; used in encoding
+ * motion vectors related to search range, as described in
+ * [ISO14496-2], subclause 7.6.3.
+ * MBType - macro block type, valid in the range 0 to 5
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - updated pointer to the current byte in the bit stream
+ * buffer
+ * pBitOffset - updated index of the next available bit position in stream
+ * buffer referenced by *ppBitStream
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - At least one of the following pointers is NULL: ppBitStream,
+ * *ppBitStream, pBitOffset, pMVCurMB
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ * - fcodeForward <= 0, or fcodeForward > 7, or MBType < 0.
+ *
+ */
+OMXResult omxVCM4P2_EncodeMV (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMXVCMotionVector *pMVCurMB,
+ const OMXVCMotionVector*pSrcMVLeftMB,
+ const OMXVCMotionVector *pSrcMVUpperMB,
+ const OMXVCMotionVector *pSrcMVUpperRightMB,
+ OMX_INT fcodeForward,
+ OMXVCM4P2MacroblockType MBType
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodePadMV_PVOP (6.2.5.1.1)
+ *
+ * Description:
+ * Decodes and pads the four motion vectors associated with a non-intra P-VOP
+ * macroblock. For macroblocks of type OMX_VC_INTER4V, the output MV is
+ * padded as specified in [ISO14496-2], subclause 7.6.1.6. Otherwise, for
+ * macroblocks of types other than OMX_VC_INTER4V, the decoded MV is copied to
+ * all four output MV buffer entries.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream buffer
+ * pBitOffset - pointer to the bit position in the byte pointed to by
+ * *ppBitStream. *pBitOffset is valid within [0-7].
+ * pSrcMVLeftMB, pSrcMVUpperMB, and pSrcMVUpperRightMB - pointers to the
+ * motion vector buffers of the macroblocks specially at the left,
+ * upper, and upper-right side of the current macroblock,
+ * respectively; a value of NULL indicates unavailability. Note:
+ * Any neighborhood macroblock outside the current VOP or video
+ * packet or outside the current GOB (when short_video_header is
+ * 1 ) for which gob_header_empty is 0 is treated as
+ * transparent, according to [ISO14496-2], subclause 7.6.5.
+ * fcodeForward - a code equal to vop_fcode_forward in MPEG-4 bit stream
+ * syntax
+ * MBType - the type of the current macroblock. If MBType is not equal to
+ * OMX_VC_INTER4V, the destination motion vector buffer is still
+ * filled with the same decoded vector.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded, so
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream
+ * pDstMVCurMB - pointer to the motion vector buffer for the current
+ * macroblock; contains four decoded motion vectors
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pDstMVCurMB
+ * - *pBitOffset exceeds [0,7]
+ * - fcodeForward exceeds (0,7]
+ * - MBType less than zero
+ * - motion vector buffer is not 4-byte aligned.
+ * OMX_Sts_Err - status error
+ *
+ */
+OMXResult omxVCM4P2_DecodePadMV_PVOP (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMXVCMotionVector *pSrcMVLeftMB,
+ OMXVCMotionVector*pSrcMVUpperMB,
+ OMXVCMotionVector *pSrcMVUpperRightMB,
+ OMXVCMotionVector*pDstMVCurMB,
+ OMX_INT fcodeForward,
+ OMXVCM4P2MacroblockType MBType
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeVLCZigzag_IntraDCVLC (6.2.5.2.2)
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan of AC and DC coefficients
+ * for one intra block. Two versions of the function (DCVLC and ACVLC) are
+ * provided in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the
+ * bitstream buffer
+ * pBitOffset - pointer to the bit position in the current byte referenced
+ * by *ppBitStream. The parameter *pBitOffset is valid in the
+ * range [0-7].
+ * Bit Position in one byte: |Most Least|
+ * *pBitOffset |0 1 2 3 4 5 6 7|
+ * predDir - AC prediction direction; used to select the zigzag scan
+ * pattern; takes one of the following values:
+ * - OMX_VC_NONE - AC prediction not used;
+ * performs classical zigzag scan.
+ * - OMX_VC_HORIZONTAL - Horizontal prediction;
+ * performs alternate-vertical zigzag scan;
+ * - OMX_VC_VERTICAL - Vertical prediction;
+ * performs alternate-horizontal zigzag scan.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ * videoComp - video component type (luminance or chrominance) of the
+ * current block
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded such
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated such that it points to the current
+ * bit position in the byte pointed by *ppBitStream
+ * pDst - pointer to the coefficient buffer of current block; must be
+ * 4-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pDst
+ * - *pBitOffset exceeds [0,7]
+ * - preDir exceeds [0,2]
+ * - pDst is not 4-byte aligned
+ * OMX_Sts_Err - if:
+ * - In DecodeVLCZigzag_IntraDCVLC, dc_size > 12
+ * - At least one of mark bits equals zero
+ * - Illegal stream encountered; code cannot be located in VLC table
+ * - Forbidden code encountered in the VLC FLC table.
+ * - The number of coefficients is greater than 64
+ *
+ */
+OMXResult omxVCM4P2_DecodeVLCZigzag_IntraDCVLC (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_S16 *pDst,
+ OMX_U8 predDir,
+ OMX_INT shortVideoHeader,
+ OMXVCM4P2VideoComponent videoComp
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeVLCZigzag_IntraACVLC (6.2.5.2.2)
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan of AC and DC coefficients
+ * for one intra block. Two versions of the function (DCVLC and ACVLC) are
+ * provided in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the
+ * bitstream buffer
+ * pBitOffset - pointer to the bit position in the current byte referenced
+ * by *ppBitStream. The parameter *pBitOffset is valid in the
+ * range [0-7]. Bit Position in one byte: |Most Least| *pBitOffset
+ * |0 1 2 3 4 5 6 7|
+ * predDir - AC prediction direction; used to select the zigzag scan
+ * pattern; takes one of the following values: OMX_VC_NONE - AC
+ * prediction not used; performs classical zigzag scan.
+ * OMX_VC_HORIZONTAL - Horizontal prediction; performs
+ * alternate-vertical zigzag scan; OMX_VC_VERTICAL - Vertical
+ * prediction; performs alternate-horizontal zigzag scan.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ * videoComp - video component type (luminance or chrominance) of the
+ * current block
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded such
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated such that it points to the current
+ * bit position in the byte pointed by *ppBitStream
+ * pDst - pointer to the coefficient buffer of current block; must be
+ * 4-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments At least one of the following
+ * pointers is NULL: ppBitStream, *ppBitStream, pBitOffset, pDst,
+ * or At least one of the following conditions is true:
+ * *pBitOffset exceeds [0,7], preDir exceeds [0,2], or pDst is
+ * not 4-byte aligned
+ * OMX_Sts_Err In DecodeVLCZigzag_IntraDCVLC, dc_size > 12 At least one of
+ * mark bits equals zero Illegal stream encountered; code cannot
+ * be located in VLC table Forbidden code encountered in the VLC
+ * FLC table The number of coefficients is greater than 64
+ *
+ */
+OMXResult omxVCM4P2_DecodeVLCZigzag_IntraACVLC (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_S16 *pDst,
+ OMX_U8 predDir,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeVLCZigzag_Inter (6.2.5.2.3)
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan for one inter-coded block.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the stream buffer
+ * pBitOffset - pointer to the next available bit in the current stream
+ * byte referenced by *ppBitStream. The parameter *pBitOffset is
+ * valid within the range [0-7].
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded such
+ * that it points to the current byte in the stream buffer
+ * pBitOffset - *pBitOffset is updated after decoding such that it points
+ * to the next available bit in the stream byte referenced by
+ * *ppBitStream
+ * pDst - pointer to the coefficient buffer of current block; must be
+ * 4-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pDst
+ * - pDst is not 4-byte aligned
+ * - *pBitOffset exceeds [0,7]
+ * OMX_Sts_Err - status error, if:
+ * - At least one mark bit is equal to zero
+ * - Encountered an illegal stream code that cannot be found in the VLC table
+ * - Encountered an illegal code in the VLC FLC table
+ * - The number of coefficients is greater than 64
+ *
+ */
+OMXResult omxVCM4P2_DecodeVLCZigzag_Inter (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_S16 *pDst,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_QuantInvIntra_I (6.2.5.3.2)
+ *
+ * Description:
+ * Performs the second inverse quantization mode on an intra/inter coded
+ * block. Supports bits_per_pixel = 8. The output coefficients are clipped to
+ * the range [-2048, 2047].
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input (quantized) intra/inter block; must be
+ * aligned on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale)
+ * videoComp - video component type of the current block. Takes one of the
+ * following flags: OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE (intra
+ * version only).
+ * shortVideoHeader - binary flag indicating presence of short_video_header
+ * (intra version only).
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (dequantized) intra/inter block
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; one or more of the following is
+ * true:
+ * - pSrcDst is NULL
+ * - QP <= 0 or QP >=31
+ * - videoComp is neither OMX_VC_LUMINANCE nor OMX_VC_CHROMINANCE.
+ *
+ */
+OMXResult omxVCM4P2_QuantInvIntra_I (
+ OMX_S16 *pSrcDst,
+ OMX_INT QP,
+ OMXVCM4P2VideoComponent videoComp,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_QuantInvInter_I (6.2.5.3.2)
+ *
+ * Description:
+ * Performs the second inverse quantization mode on an intra/inter coded
+ * block. Supports bits_per_pixel = 8. The output coefficients are clipped to
+ * the range [-2048, 2047].
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input (quantized) intra/inter block; must be
+ * aligned on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale)
+ * videoComp - video component type of the current block. Takes one of the
+ * following flags: OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE (intra
+ * version only).
+ * shortVideoHeader - binary flag indicating presence of short_video_header
+ * (intra version only).
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (dequantized) intra/inter block
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; one or more of the following is
+ * true:
+ * - pSrcDst is NULL
+ * - QP <= 0 or QP >=31
+ * - videoComp is neither OMX_VC_LUMINANCE nor OMX_VC_CHROMINANCE.
+ *
+ */
+OMXResult omxVCM4P2_QuantInvInter_I (
+ OMX_S16 *pSrcDst,
+ OMX_INT QP
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeBlockCoef_Intra (6.2.5.4.1)
+ *
+ * Description:
+ * Decodes the INTRA block coefficients. Inverse quantization, inversely
+ * zigzag positioning, and IDCT, with appropriate clipping on each step, are
+ * performed on the coefficients. The results are then placed in the output
+ * frame/plane on a pixel basis. Note: This function will be used only when
+ * at least one non-zero AC coefficient of current block exists in the bit
+ * stream. The DC only condition will be handled in another function.
+ *
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream buffer. There is no boundary check for the bit stream
+ * buffer.
+ * pBitOffset - pointer to the bit position in the byte pointed to by
+ * *ppBitStream. *pBitOffset is valid within [0-7].
+ * step - width of the destination plane
+ * pCoefBufRow - pointer to the coefficient row buffer; must be aligned on
+ * an 8-byte boundary.
+ * pCoefBufCol - pointer to the coefficient column buffer; must be aligned
+ * on an 8-byte boundary.
+ * curQP - quantization parameter of the macroblock which the current block
+ * belongs to
+ * pQPBuf - pointer to the quantization parameter buffer
+ * blockIndex - block index indicating the component type and position as
+ * defined in [ISO14496-2], subclause 6.1.3.8, Figure 6-5.
+ * intraDCVLC - a code determined by intra_dc_vlc_thr and QP. This allows a
+ * mechanism to switch between two VLC for coding of Intra DC
+ * coefficients as per [ISO14496-2], Table 6-21.
+ * ACPredFlag - a flag equal to ac_pred_flag (of luminance) indicating if
+ * the ac coefficients of the first row or first column are
+ * differentially coded for intra coded macroblock.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded, so
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream
+ * pDst - pointer to the block in the destination plane; must be aligned on
+ * an 8-byte boundary.
+ * pCoefBufRow - pointer to the updated coefficient row buffer.
+ * pCoefBufCol - pointer to the updated coefficient column buffer Note:
+ * The coefficient buffers must be updated in accordance with the
+ * update procedure defined in section 6.2.2.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pCoefBufRow, pCoefBufCol,
+ * pQPBuf, pDst.
+ * - *pBitOffset exceeds [0,7]
+ * - curQP exceeds (1, 31)
+ * - blockIndex exceeds [0,5]
+ * - step is not the multiple of 8
+ * - a pointer alignment requirement was violated.
+ * OMX_Sts_Err - status error. Refer to OMX_Sts_Err of DecodeVLCZigzag_Intra.
+ *
+ */
+OMXResult omxVCM4P2_DecodeBlockCoef_Intra (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_U8 *pDst,
+ OMX_INT step,
+ OMX_S16 *pCoefBufRow,
+ OMX_S16 *pCoefBufCol,
+ OMX_U8 curQP,
+ const OMX_U8 *pQPBuf,
+ OMX_INT blockIndex,
+ OMX_INT intraDCVLC,
+ OMX_INT ACPredFlag,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeBlockCoef_Inter (6.2.5.4.2)
+ *
+ * Description:
+ * Decodes the INTER block coefficients. This function performs inverse
+ * quantization, inverse zigzag positioning, and IDCT (with appropriate
+ * clipping on each step) on the coefficients. The results (residuals) are
+ * placed in a contiguous array of 64 elements. For INTER block, the output
+ * buffer holds the residuals for further reconstruction.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream buffer. There is no boundary check for the bit stream
+ * buffer.
+ * pBitOffset - pointer to the bit position in the byte pointed to by
+ * *ppBitStream. *pBitOffset is valid within [0-7]
+ * QP - quantization parameter
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded, so
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream
+ * pDst - pointer to the decoded residual buffer (a contiguous array of 64
+ * elements of OMX_S16 data type); must be aligned on a 16-byte
+ * boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the following pointers is Null:
+ * ppBitStream, *ppBitStream, pBitOffset , pDst
+ * - *pBitOffset exceeds [0,7]
+ * - QP <= 0.
+ * - pDst is not 16-byte aligned
+ * OMX_Sts_Err - status error. Refer to OMX_Sts_Err of DecodeVLCZigzag_Inter .
+ *
+ */
+OMXResult omxVCM4P2_DecodeBlockCoef_Inter (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_S16 *pDst,
+ OMX_INT QP,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_PredictReconCoefIntra (6.2.5.4.3)
+ *
+ * Description:
+ * Performs adaptive DC/AC coefficient prediction for an intra block. Prior
+ * to the function call, prediction direction (predDir) should be selected as
+ * specified in [ISO14496-2], subclause 7.4.3.1.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the coefficient buffer which contains the quantized
+ * coefficient residuals (PQF) of the current block; must be
+ * aligned on a 4-byte boundary. The output coefficients are
+ * saturated to the range [-2048, 2047].
+ * pPredBufRow - pointer to the coefficient row buffer; must be aligned on
+ * a 4-byte boundary.
+ * pPredBufCol - pointer to the coefficient column buffer; must be aligned
+ * on a 4-byte boundary.
+ * curQP - quantization parameter of the current block. curQP may equal to
+ * predQP especially when the current block and the predictor block
+ * are in the same macroblock.
+ * predQP - quantization parameter of the predictor block
+ * predDir - indicates the prediction direction which takes one of the
+ * following values: OMX_VC_HORIZONTAL - predict horizontally
+ * OMX_VC_VERTICAL - predict vertically
+ * ACPredFlag - a flag indicating if AC prediction should be performed. It
+ * is equal to ac_pred_flag in the bit stream syntax of MPEG-4
+ * videoComp - video component type (luminance or chrominance) of the
+ * current block
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the coefficient buffer which contains the quantized
+ * coefficients (QF) of the current block
+ * pPredBufRow - pointer to the updated coefficient row buffer
+ * pPredBufCol - pointer to the updated coefficient column buffer Note:
+ * Buffer update: Update the AC prediction buffer (both row and
+ * column buffer).
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the pointers is NULL:
+ * pSrcDst, pPredBufRow, or pPredBufCol.
+ * - curQP <= 0,
+ * - predQP <= 0,
+ * - curQP >31,
+ * - predQP > 31,
+ * - preDir exceeds [1,2]
+ * - pSrcDst, pPredBufRow, or pPredBufCol is not 4-byte aligned.
+ *
+ */
+OMXResult omxVCM4P2_PredictReconCoefIntra (
+ OMX_S16 *pSrcDst,
+ OMX_S16 *pPredBufRow,
+ OMX_S16 *pPredBufCol,
+ OMX_INT curQP,
+ OMX_INT predQP,
+ OMX_INT predDir,
+ OMX_INT ACPredFlag,
+ OMXVCM4P2VideoComponent videoComp
+);
+
+
+
+/**
+ * Function: omxVCM4P2_MCReconBlock (6.2.5.5.1)
+ *
+ * Description:
+ * Performs motion compensation prediction for an 8x8 block using
+ * interpolation described in [ISO14496-2], subclause 7.6.2.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the block in the reference plane.
+ * srcStep - distance between the start of consecutive lines in the
+ * reference plane, in bytes; must be a multiple of 8.
+ * dstStep - distance between the start of consecutive lines in the
+ * destination plane, in bytes; must be a multiple of 8.
+ * pSrcResidue - pointer to a buffer containing the 16-bit prediction
+ * residuals; must be 16-byte aligned. If the pointer is NULL, then
+ * no prediction is done, only motion compensation, i.e., the block
+ * is moved with interpolation.
+ * predictType - bilinear interpolation type, as defined in section
+ * 6.2.1.2.
+ * rndVal - rounding control parameter: 0 - disabled; 1 - enabled.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination buffer; must be 8-byte aligned. If
+ * prediction residuals are added then output intensities are
+ * clipped to the range [0,255].
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - pDst is not 8-byte aligned.
+ * - pSrcResidue is not 16-byte aligned.
+ * - one or more of the following pointers is NULL: pSrc or pDst.
+ * - either srcStep or dstStep is not a multiple of 8.
+ * - invalid type specified for the parameter predictType.
+ * - the parameter rndVal is not equal either to 0 or 1.
+ *
+ */
+OMXResult omxVCM4P2_MCReconBlock (
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ const OMX_S16 *pSrcResidue,
+ OMX_U8 *pDst,
+ OMX_INT dstStep,
+ OMX_INT predictType,
+ OMX_INT rndVal
+);
+
+
+
+/* 6.3.1.1 Intra 16x16 Prediction Modes */
+/* A data type that enumerates intra_16x16 macroblock prediction modes is defined as follows: */
+
+typedef enum {
+ OMX_VC_16X16_VERT = 0, /** Intra_16x16_Vertical */
+ OMX_VC_16X16_HOR = 1, /** Intra_16x16_Horizontal */
+ OMX_VC_16X16_DC = 2, /** Intra_16x16_DC */
+ OMX_VC_16X16_PLANE = 3 /** Intra_16x16_Plane */
+} OMXVCM4P10Intra16x16PredMode;
+
+
+
+/* 6.3.1.2 Intra 4x4 Prediction Modes */
+/* A data type that enumerates intra_4x4 macroblock prediction modes is defined as follows: */
+
+typedef enum {
+ OMX_VC_4X4_VERT = 0, /** Intra_4x4_Vertical */
+ OMX_VC_4X4_HOR = 1, /** Intra_4x4_Horizontal */
+ OMX_VC_4X4_DC = 2, /** Intra_4x4_DC */
+ OMX_VC_4X4_DIAG_DL = 3, /** Intra_4x4_Diagonal_Down_Left */
+ OMX_VC_4X4_DIAG_DR = 4, /** Intra_4x4_Diagonal_Down_Right */
+ OMX_VC_4X4_VR = 5, /** Intra_4x4_Vertical_Right */
+ OMX_VC_4X4_HD = 6, /** Intra_4x4_Horizontal_Down */
+ OMX_VC_4X4_VL = 7, /** Intra_4x4_Vertical_Left */
+ OMX_VC_4X4_HU = 8 /** Intra_4x4_Horizontal_Up */
+} OMXVCM4P10Intra4x4PredMode;
+
+
+
+/* 6.3.1.3 Chroma Prediction Modes */
+/* A data type that enumerates intra chroma prediction modes is defined as follows: */
+
+typedef enum {
+ OMX_VC_CHROMA_DC = 0, /** Intra_Chroma_DC */
+ OMX_VC_CHROMA_HOR = 1, /** Intra_Chroma_Horizontal */
+ OMX_VC_CHROMA_VERT = 2, /** Intra_Chroma_Vertical */
+ OMX_VC_CHROMA_PLANE = 3 /** Intra_Chroma_Plane */
+} OMXVCM4P10IntraChromaPredMode;
+
+
+
+/* 6.3.1.4 Motion Estimation Modes */
+/* A data type that enumerates H.264 motion estimation modes is defined as follows: */
+
+typedef enum {
+ OMX_VC_M4P10_FAST_SEARCH = 0, /** Fast motion search */
+ OMX_VC_M4P10_FULL_SEARCH = 1 /** Full motion search */
+} OMXVCM4P10MEMode;
+
+
+
+/* 6.3.1.5 Macroblock Types */
+/* A data type that enumerates H.264 macroblock types is defined as follows: */
+
+typedef enum {
+ OMX_VC_P_16x16 = 0, /* defined by [ISO14496-10] */
+ OMX_VC_P_16x8 = 1,
+ OMX_VC_P_8x16 = 2,
+ OMX_VC_P_8x8 = 3,
+ OMX_VC_PREF0_8x8 = 4,
+ OMX_VC_INTER_SKIP = 5,
+ OMX_VC_INTRA_4x4 = 8,
+ OMX_VC_INTRA_16x16 = 9,
+ OMX_VC_INTRA_PCM = 10
+} OMXVCM4P10MacroblockType;
+
+
+
+/* 6.3.1.6 Sub-Macroblock Types */
+/* A data type that enumerates H.264 sub-macroblock types is defined as follows: */
+
+typedef enum {
+ OMX_VC_SUB_P_8x8 = 0, /* defined by [ISO14496-10] */
+ OMX_VC_SUB_P_8x4 = 1,
+ OMX_VC_SUB_P_4x8 = 2,
+ OMX_VC_SUB_P_4x4 = 3
+} OMXVCM4P10SubMacroblockType;
+
+
+
+/* 6.3.1.7 Variable Length Coding (VLC) Information */
+
+typedef struct {
+ OMX_U8 uTrailing_Ones; /* Trailing ones; 3 at most */
+ OMX_U8 uTrailing_One_Signs; /* Trailing ones signal */
+ OMX_U8 uNumCoeffs; /* Total number of non-zero coefs, including trailing ones */
+ OMX_U8 uTotalZeros; /* Total number of zero coefs */
+ OMX_S16 iLevels[16]; /* Levels of non-zero coefs, in reverse zig-zag order */
+ OMX_U8 uRuns[16]; /* Runs for levels and trailing ones, in reverse zig-zag order */
+} OMXVCM4P10VLCInfo;
+
+
+
+/* 6.3.1.8 Macroblock Information */
+
+typedef struct {
+ OMX_S32 sliceId; /* slice number */
+ OMXVCM4P10MacroblockType mbType; /* MB type */
+ OMXVCM4P10SubMacroblockType subMBType[4]; /* sub-block type */
+ OMX_S32 qpy; /* qp for luma */
+ OMX_S32 qpc; /* qp for chroma */
+ OMX_U32 cbpy; /* CBP Luma */
+ OMX_U32 cbpc; /* CBP Chroma */
+ OMXVCMotionVector pMV0[4][4]; /* motion vector, represented using 1/4-pel units, pMV0[blocky][blockx] (blocky = 0~3, blockx =0~3) */
+ OMXVCMotionVector pMVPred[4][4]; /* motion vector prediction, Represented using 1/4-pel units, pMVPred[blocky][blockx] (blocky = 0~3, blockx = 0~3) */
+ OMX_U8 pRefL0Idx[4]; /* reference picture indices */
+ OMXVCM4P10Intra16x16PredMode Intra16x16PredMode; /* best intra 16x16 prediction mode */
+ OMXVCM4P10Intra4x4PredMode pIntra4x4PredMode[16]; /* best intra 4x4 prediction mode for each block, pMV0 indexed as above */
+} OMXVCM4P10MBInfo, *OMXVCM4P10MBInfoPtr;
+
+
+
+/* 6.3.1.9 Motion Estimation Parameters */
+
+typedef struct {
+ OMX_S32 blockSplitEnable8x8; /* enables 16x8, 8x16, 8x8 */
+ OMX_S32 blockSplitEnable4x4; /* enable splitting of 8x4, 4x8, 4x4 blocks */
+ OMX_S32 halfSearchEnable;
+ OMX_S32 quarterSearchEnable;
+ OMX_S32 intraEnable4x4; /* 1=enable, 0=disable */
+ OMX_S32 searchRange16x16; /* integer pixel units */
+ OMX_S32 searchRange8x8;
+ OMX_S32 searchRange4x4;
+} OMXVCM4P10MEParams;
+
+
+
+/**
+ * Function: omxVCM4P10_PredictIntra_4x4 (6.3.3.1.1)
+ *
+ * Description:
+ * Perform Intra_4x4 prediction for luma samples. If the upper-right block is
+ * not available, then duplication work should be handled inside the function.
+ * Users need not define them outside.
+ *
+ * Input Arguments:
+ *
+ * pSrcLeft - Pointer to the buffer of 4 left pixels:
+ * p[x, y] (x = -1, y = 0..3)
+ * pSrcAbove - Pointer to the buffer of 8 above pixels:
+ * p[x,y] (x = 0..7, y =-1);
+ * must be aligned on a 4-byte boundary.
+ * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
+ * leftStep - Step of left pixel buffer; must be a multiple of 4.
+ * dstStep - Step of the destination buffer; must be a multiple of 4.
+ * predMode - Intra_4x4 prediction mode.
+ * availability - Neighboring 4x4 block availability flag, refer to
+ * "Neighboring Macroblock Availability" .
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to the destination buffer; must be aligned on a 4-byte
+ * boundary.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pDst is NULL.
+ * dstStep < 4, or dstStep is not a multiple of 4.
+ * leftStep is not a multiple of 4.
+ * predMode is not in the valid range of enumeration
+ * OMXVCM4P10Intra4x4PredMode.
+ * predMode is OMX_VC_4x4_VERT, but availability doesn't set OMX_VC_UPPER
+ * indicating p[x,-1] (x = 0..3) is not available.
+ * predMode is OMX_VC_4x4_HOR, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..3) is not available.
+ * predMode is OMX_VC_4x4_DIAG_DL, but availability doesn't set
+ * OMX_VC_UPPER indicating p[x, -1] (x = 0..3) is not available.
+ * predMode is OMX_VC_4x4_DIAG_DR, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
+ * available.
+ * predMode is OMX_VC_4x4_VR, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
+ * available.
+ * predMode is OMX_VC_4x4_HD, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
+ * available.
+ * predMode is OMX_VC_4x4_VL, but availability doesn't set OMX_VC_UPPER
+ * indicating p[x,-1] (x = 0..3) is not available.
+ * predMode is OMX_VC_4x4_HU, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..3) is not available.
+ * availability sets OMX_VC_UPPER, but pSrcAbove is NULL.
+ * availability sets OMX_VC_LEFT, but pSrcLeft is NULL.
+ * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL.
+ * either pSrcAbove or pDst is not aligned on a 4-byte boundary.
+ *
+ * Note:
+ * pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointers if
+ * they are not used by intra prediction as implied in predMode.
+ *
+ */
+OMXResult omxVCM4P10_PredictIntra_4x4 (
+ const OMX_U8 *pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ const OMX_U8 *pSrcAboveLeft,
+ OMX_U8 *pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMXVCM4P10Intra4x4PredMode predMode,
+ OMX_S32 availability
+);
+
+
+
+/**
+ * Function: omxVCM4P10_PredictIntra_16x16 (6.3.3.1.2)
+ *
+ * Description:
+ * Perform Intra_16x16 prediction for luma samples. If the upper-right block
+ * is not available, then duplication work should be handled inside the
+ * function. Users need not define them outside.
+ *
+ * Input Arguments:
+ *
+ * pSrcLeft - Pointer to the buffer of 16 left pixels: p[x, y] (x = -1, y =
+ * 0..15)
+ * pSrcAbove - Pointer to the buffer of 16 above pixels: p[x,y] (x = 0..15,
+ * y= -1); must be aligned on a 16-byte boundary.
+ * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
+ * leftStep - Step of left pixel buffer; must be a multiple of 16.
+ * dstStep - Step of the destination buffer; must be a multiple of 16.
+ * predMode - Intra_16x16 prediction mode, please refer to section 3.4.1.
+ * availability - Neighboring 16x16 MB availability flag. Refer to
+ * section 3.4.4.
+ *
+ * Output Arguments:
+ *
+ * pDst -Pointer to the destination buffer; must be aligned on a 16-byte
+ * boundary.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pDst is NULL.
+ * dstStep < 16. or dstStep is not a multiple of 16.
+ * leftStep is not a multiple of 16.
+ * predMode is not in the valid range of enumeration
+ * OMXVCM4P10Intra16x16PredMode
+ * predMode is OMX_VC_16X16_VERT, but availability doesn't set
+ * OMX_VC_UPPER indicating p[x,-1] (x = 0..15) is not available.
+ * predMode is OMX_VC_16X16_HOR, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..15) is not available.
+ * predMode is OMX_VC_16X16_PLANE, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1](x = 0..15), or p[-1,y] (y = 0..15), or p[-1,-1] is not
+ * available.
+ * availability sets OMX_VC_UPPER, but pSrcAbove is NULL.
+ * availability sets OMX_VC_LEFT, but pSrcLeft is NULL.
+ * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL.
+ * either pSrcAbove or pDst is not aligned on a 16-byte boundary.
+ *
+ * Note:
+ * pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointers if
+ * they are not used by intra prediction implied in predMode.
+ * Note:
+ * OMX_VC_UPPER_RIGHT is not used in intra_16x16 luma prediction.
+ *
+ */
+OMXResult omxVCM4P10_PredictIntra_16x16 (
+ const OMX_U8 *pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ const OMX_U8 *pSrcAboveLeft,
+ OMX_U8 *pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMXVCM4P10Intra16x16PredMode predMode,
+ OMX_S32 availability
+);
+
+
+
+/**
+ * Function: omxVCM4P10_PredictIntraChroma_8x8 (6.3.3.1.3)
+ *
+ * Description:
+ * Performs intra prediction for chroma samples.
+ *
+ * Input Arguments:
+ *
+ * pSrcLeft - Pointer to the buffer of 8 left pixels: p[x, y] (x = -1, y=
+ * 0..7).
+ * pSrcAbove - Pointer to the buffer of 8 above pixels: p[x,y] (x = 0..7, y
+ * = -1); must be aligned on an 8-byte boundary.
+ * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
+ * leftStep - Step of left pixel buffer; must be a multiple of 8.
+ * dstStep - Step of the destination buffer; must be a multiple of 8.
+ * predMode - Intra chroma prediction mode, please refer to section 3.4.3.
+ * availability - Neighboring chroma block availability flag, please refer
+ * to "Neighboring Macroblock Availability".
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to the destination buffer; must be aligned on an 8-byte
+ * boundary.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If any of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pDst is NULL.
+ * dstStep < 8 or dstStep is not a multiple of 8.
+ * leftStep is not a multiple of 8.
+ * predMode is not in the valid range of enumeration
+ * OMXVCM4P10IntraChromaPredMode.
+ * predMode is OMX_VC_CHROMA_VERT, but availability doesn't set
+ * OMX_VC_UPPER indicating p[x,-1] (x = 0..7) is not available.
+ * predMode is OMX_VC_CHROMA_HOR, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..7) is not available.
+ * predMode is OMX_VC_CHROMA_PLANE, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1](x = 0..7), or p[-1,y] (y = 0..7), or p[-1,-1] is not
+ * available.
+ * availability sets OMX_VC_UPPER, but pSrcAbove is NULL.
+ * availability sets OMX_VC_LEFT, but pSrcLeft is NULL.
+ * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL.
+ * either pSrcAbove or pDst is not aligned on a 8-byte boundary.
+ *
+ * Note: pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointer if
+ * they are not used by intra prediction implied in predMode.
+ *
+ * Note: OMX_VC_UPPER_RIGHT is not used in intra chroma prediction.
+ *
+ */
+OMXResult omxVCM4P10_PredictIntraChroma_8x8 (
+ const OMX_U8 *pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ const OMX_U8 *pSrcAboveLeft,
+ OMX_U8 *pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMXVCM4P10IntraChromaPredMode predMode,
+ OMX_S32 availability
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InterpolateLuma (6.3.3.2.1)
+ *
+ * Description:
+ * Performs quarter-pixel interpolation for inter luma MB. It is assumed that
+ * the frame is already padded when calling this function.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the source reference frame buffer
+ * srcStep - reference frame step, in bytes; must be a multiple of roi.width
+ * dstStep - destination frame step, in bytes; must be a multiple of
+ * roi.width
+ * dx - Fractional part of horizontal motion vector component in 1/4 pixel
+ * unit; valid in the range [0,3]
+ * dy - Fractional part of vertical motion vector y component in 1/4 pixel
+ * unit; valid in the range [0,3]
+ * roi - Dimension of the interpolation region; the parameters roi.width and
+ * roi.height must be equal to either 4, 8, or 16.
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to the destination frame buffer:
+ * if roi.width==4, 4-byte alignment required
+ * if roi.width==8, 8-byte alignment required
+ * if roi.width==16, 16-byte alignment required
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pSrc or pDst is NULL.
+ * srcStep or dstStep < roi.width.
+ * dx or dy is out of range [0,3].
+ * roi.width or roi.height is out of range {4, 8, 16}.
+ * roi.width is equal to 4, but pDst is not 4 byte aligned.
+ * roi.width is equal to 8 or 16, but pDst is not 8 byte aligned.
+ * srcStep or dstStep is not a multiple of 8.
+ *
+ */
+OMXResult omxVCM4P10_InterpolateLuma (
+ const OMX_U8 *pSrc,
+ OMX_S32 srcStep,
+ OMX_U8 *pDst,
+ OMX_S32 dstStep,
+ OMX_S32 dx,
+ OMX_S32 dy,
+ OMXSize roi
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InterpolateChroma (6.3.3.2.2)
+ *
+ * Description:
+ * Performs 1/8-pixel interpolation for inter chroma MB.
+ *
+ * Input Arguments:
+ *
+ * pSrc -Pointer to the source reference frame buffer
+ * srcStep -Reference frame step in bytes
+ * dstStep -Destination frame step in bytes; must be a multiple of
+ * roi.width.
+ * dx -Fractional part of horizontal motion vector component in 1/8 pixel
+ * unit; valid in the range [0,7]
+ * dy -Fractional part of vertical motion vector component in 1/8 pixel
+ * unit; valid in the range [0,7]
+ * roi -Dimension of the interpolation region; the parameters roi.width and
+ * roi.height must be equal to either 2, 4, or 8.
+ *
+ * Output Arguments:
+ *
+ * pDst -Pointer to the destination frame buffer:
+ * if roi.width==2, 2-byte alignment required
+ * if roi.width==4, 4-byte alignment required
+ * if roi.width==8, 8-byte alignment required
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pSrc or pDst is NULL.
+ * srcStep or dstStep < 8.
+ * dx or dy is out of range [0-7].
+ * roi.width or roi.height is out of range {2,4,8}.
+ * roi.width is equal to 2, but pDst is not 2-byte aligned.
+ * roi.width is equal to 4, but pDst is not 4-byte aligned.
+ * roi.width is equal to 8, but pDst is not 8 byte aligned.
+ * srcStep or dstStep is not a multiple of 8.
+ *
+ */
+OMXResult omxVCM4P10_InterpolateChroma (
+ const OMX_U8 *pSrc,
+ OMX_S32 srcStep,
+ OMX_U8 *pDst,
+ OMX_S32 dstStep,
+ OMX_S32 dx,
+ OMX_S32 dy,
+ OMXSize roi
+);
+
+
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingLuma_VerEdge_I (6.3.3.3.1)
+ *
+ * Description:
+ * Performs in-place deblock filtering on four vertical edges of the luma
+ * macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the input macroblock; must be 16-byte aligned.
+ * srcdstStep -Step of the arrays; must be a multiple of 16.
+ * pAlpha -Array of size 2 of alpha thresholds (the first item is the alpha
+ * threshold for the external vertical edge, and the second item is
+ * for the internal vertical edge); per [ISO14496-10] alpha values
+ * must be in the range [0,255].
+ * pBeta -Array of size 2 of beta thresholds (the first item is the beta
+ * threshold for the external vertical edge, and the second item is
+ * for the internal vertical edge); per [ISO14496-10] beta values
+ * must be in the range [0,18].
+ * pThresholds -Array of size 16 of Thresholds (TC0) (values for the left
+ * edge of each 4x4 block, arranged in vertical block order); must
+ * be aligned on a 4-byte boundary.. Per [ISO14496-10] values must
+ * be in the range [0,25].
+ * pBS -Array of size 16 of BS parameters (arranged in vertical block
+ * order); valid in the range [0,4] with the following
+ * restrictions: i) pBS[i]== 4 may occur only for 0<=i<=3, ii)
+ * pBS[i]== 4 if and only if pBS[i^3]== 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * Either of the pointers in pSrcDst, pAlpha, pBeta, pThresholds, or pBS
+ * is NULL.
+ * Either pThresholds or pBS is not aligned on a 4-byte boundary.
+ * pSrcDst is not 16-byte aligned.
+ * srcdstStep is not a multiple of 16.
+ * pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * One or more entries in the table pThresholds[0..15]is outside of the
+ * range [0,25].
+ * pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or (pBS[i]==4 &&
+ * pBS[i^3]!=4) for 0<=i<=3.
+ *
+ */
+OMXResult omxVCM4P10_FilterDeblockingLuma_VerEdge_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingLuma_HorEdge_I (6.3.3.3.2)
+ *
+ * Description:
+ * Performs in-place deblock filtering on four horizontal edges of the luma
+ * macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 16-byte aligned.
+ * srcdstStep - step of the arrays; must be a multiple of 16.
+ * pAlpha - array of size 2 of alpha thresholds (the first item is the alpha
+ * threshold for the external vertical edge, and the second item is
+ * for the internal horizontal edge); per [ISO14496-10] alpha
+ * values must be in the range [0,255].
+ * pBeta - array of size 2 of beta thresholds (the first item is the beta
+ * threshold for the external horizontal edge, and the second item
+ * is for the internal horizontal edge). Per [ISO14496-10] beta
+ * values must be in the range [0,18].
+ * pThresholds - array of size 16 containing thresholds, TC0, for the top
+ * horizontal edge of each 4x4 block, arranged in horizontal block
+ * order; must be aligned on a 4-byte boundary. Per [ISO14496 10]
+ * values must be in the range [0,25].
+ * pBS - array of size 16 of BS parameters (arranged in horizontal block
+ * order); valid in the range [0,4] with the following
+ * restrictions: i) pBS[i]== 4 may occur only for 0<=i<=3, ii)
+ * pBS[i]== 4 if and only if pBS[i^3]== 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr, if one of the following cases occurs:
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds, or pBS.
+ * - either pThresholds or pBS is not aligned on a 4-byte boundary.
+ * - pSrcDst is not 16-byte aligned.
+ * - srcdstStep is not a multiple of 16.
+ * - pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * - pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * - One or more entries in the table pThresholds[0..15] is
+ * outside of the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ *
+ */
+OMXResult omxVCM4P10_FilterDeblockingLuma_HorEdge_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingChroma_VerEdge_I (6.3.3.3.3)
+ *
+ * Description:
+ * Performs in-place deblock filtering on four vertical edges of the chroma
+ * macroblock (8x8).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the input macroblock; must be 8-byte aligned.
+ * srcdstStep - Step of the arrays; must be a multiple of 8.
+ * pAlpha - Array of size 2 of alpha thresholds (the first item is alpha
+ * threshold for external vertical edge, and the second item is for
+ * internal vertical edge); per [ISO14496-10] alpha values must be
+ * in the range [0,255].
+ * pBeta - Array of size 2 of beta thresholds (the first item is the beta
+ * threshold for the external vertical edge, and the second item is
+ * for the internal vertical edge); per [ISO14496-10] beta values
+ * must be in the range [0,18].
+ * pThresholds - Array of size 8 containing thresholds, TC0, for the left
+ * vertical edge of each 4x2 chroma block, arranged in vertical
+ * block order; must be aligned on a 4-byte boundary. Per
+ * [ISO14496-10] values must be in the range [0,25].
+ * pBS - Array of size 16 of BS parameters (values for each 2x2 chroma
+ * block, arranged in vertical block order). This parameter is the
+ * same as the pBS parameter passed into FilterDeblockLuma_VerEdge;
+ * valid in the range [0,4] with the following restrictions: i)
+ * pBS[i]== 4 may occur only for 0<=i<=3, ii) pBS[i]== 4 if and
+ * only if pBS[i^3]== 4. Must be 4 byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds, or pBS.
+ * - pSrcDst is not 8-byte aligned.
+ * - srcdstStep is not a multiple of 8.
+ * - pThresholds is not 4-byte aligned.
+ * - pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * - pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * - One or more entries in the table pThresholds[0..7] is outside
+ * of the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - pBS is not 4-byte aligned.
+ *
+ */
+OMXResult omxVCM4P10_FilterDeblockingChroma_VerEdge_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingChroma_HorEdge_I (6.3.3.3.4)
+ *
+ * Description:
+ * Performs in-place deblock filtering on the horizontal edges of the chroma
+ * macroblock (8x8).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 8-byte aligned.
+ * srcdstStep - array step; must be a multiple of 8.
+ * pAlpha - array of size 2 containing alpha thresholds; the first element
+ * contains the threshold for the external horizontal edge, and the
+ * second element contains the threshold for internal horizontal
+ * edge. Per [ISO14496-10] alpha values must be in the range
+ * [0,255].
+ * pBeta - array of size 2 containing beta thresholds; the first element
+ * contains the threshold for the external horizontal edge, and the
+ * second element contains the threshold for the internal
+ * horizontal edge. Per [ISO14496-10] beta values must be in the
+ * range [0,18].
+ * pThresholds - array of size 8 containing thresholds, TC0, for the top
+ * horizontal edge of each 2x4 chroma block, arranged in horizontal
+ * block order; must be aligned on a 4-byte boundary. Per
+ * [ISO14496-10] values must be in the range [0,25].
+ * pBS - array of size 16 containing BS parameters for each 2x2 chroma
+ * block, arranged in horizontal block order; valid in the range
+ * [0,4] with the following restrictions: i) pBS[i]== 4 may occur
+ * only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^3]== 4.
+ * Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr, if one of the following cases occurs:
+ * - any of the following pointers is NULL:
+ * pSrcDst, pAlpha, pBeta, pThresholds, or pBS.
+ * - pSrcDst is not 8-byte aligned.
+ * - srcdstStep is not a multiple of 8.
+ * - pThresholds is not 4-byte aligned.
+ * - pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * - pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * - One or more entries in the table pThresholds[0..7] is outside
+ * of the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - pBS is not 4-byte aligned.
+ *
+ */
+OMXResult omxVCM4P10_FilterDeblockingChroma_HorEdge_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DeblockLuma_I (6.3.3.3.5)
+ *
+ * Description:
+ * This function performs in-place deblock filtering the horizontal and
+ * vertical edges of a luma macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 16-byte aligned.
+ * srcdstStep - image width; must be a multiple of 16.
+ * pAlpha - pointer to a 2x2 table of alpha thresholds, organized as
+ * follows: {external vertical edge, internal vertical edge,
+ * external horizontal edge, internal horizontal edge }. Per
+ * [ISO14496-10] alpha values must be in the range [0,255].
+ * pBeta - pointer to a 2x2 table of beta thresholds, organized as follows:
+ * {external vertical edge, internal vertical edge, external
+ * horizontal edge, internal horizontal edge }. Per [ISO14496-10]
+ * beta values must be in the range [0,18].
+ * pThresholds - pointer to a 16x2 table of threshold (TC0), organized as
+ * follows: {values for the left or above edge of each 4x4 block,
+ * arranged in vertical block order and then in horizontal block
+ * order}; must be aligned on a 4-byte boundary. Per [ISO14496-10]
+ * values must be in the range [0,25].
+ * pBS - pointer to a 16x2 table of BS parameters arranged in scan block
+ * order for vertical edges and then horizontal edges; valid in the
+ * range [0,4] with the following restrictions: i) pBS[i]== 4 may
+ * occur only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^3]==
+ * 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds or pBS.
+ * - pSrcDst is not 16-byte aligned.
+ * - either pThresholds or pBS is not aligned on a 4-byte boundary.
+ * - one or more entries in the table pAlpha[0..3] is outside the range
+ * [0,255].
+ * - one or more entries in the table pBeta[0..3] is outside the range
+ * [0,18].
+ * - one or more entries in the table pThresholds[0..31]is outside of
+ * the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - srcdstStep is not a multiple of 16.
+ *
+ */
+OMXResult omxVCM4P10_DeblockLuma_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DeblockChroma_I (6.3.3.3.6)
+ *
+ * Description:
+ * Performs in-place deblocking filtering on all edges of the chroma
+ * macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 8-byte aligned.
+ * srcdstStep - step of the arrays; must be a multiple of 8.
+ * pAlpha - pointer to a 2x2 array of alpha thresholds, organized as
+ * follows: {external vertical edge, internal vertical edge,
+ * external horizontal edge, internal horizontal edge }. Per
+ * [ISO14496-10] alpha values must be in the range [0,255].
+ * pBeta - pointer to a 2x2 array of Beta Thresholds, organized as follows:
+ * { external vertical edge, internal vertical edge, external
+ * horizontal edge, internal horizontal edge }. Per [ISO14496-10]
+ * beta values must be in the range [0,18].
+ * pThresholds - array of size 8x2 of Thresholds (TC0) (values for the left
+ * or above edge of each 4x2 or 2x4 block, arranged in vertical
+ * block order and then in horizontal block order); must be aligned
+ * on a 4-byte boundary. Per [ISO14496-10] values must be in the
+ * range [0,25].
+ * pBS - array of size 16x2 of BS parameters (arranged in scan block order
+ * for vertical edges and then horizontal edges); valid in the
+ * range [0,4] with the following restrictions: i) pBS[i]== 4 may
+ * occur only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^3]==
+ * 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds, or pBS.
+ * - pSrcDst is not 8-byte aligned.
+ * - either pThresholds or pBS is not 4-byte aligned.
+ * - one or more entries in the table pAlpha[0..3] is outside the range
+ * [0,255].
+ * - one or more entries in the table pBeta[0..3] is outside the range
+ * [0,18].
+ * - one or more entries in the table pThresholds[0..15]is outside of
+ * the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - srcdstStep is not a multiple of 8.
+ *
+ */
+OMXResult omxVCM4P10_DeblockChroma_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC (6.3.4.1.1)
+ *
+ * Description:
+ * Performs CAVLC decoding and inverse raster scan for a 2x2 block of
+ * ChromaDCLevel. The decoded coefficients in the packed position-coefficient
+ * buffer are stored in reverse zig-zag order, i.e., the first buffer element
+ * contains the last non-zero postion-coefficient pair of the block. Within
+ * each position-coefficient pair, the position entry indicates the
+ * raster-scan position of the coefficient, while the coefficient entry
+ * contains the coefficient value.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - Double pointer to current byte in bit stream buffer
+ * pOffset - Pointer to current bit position in the byte pointed to by
+ * *ppBitStream; valid in the range [0,7].
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after each block is decoded
+ * pOffset - *pOffset is updated after each block is decoded
+ * pNumCoeff - Pointer to the number of nonzero coefficients in this block
+ * ppPosCoefBuf - Double pointer to destination residual
+ * coefficient-position pair buffer. Buffer position
+ * (*ppPosCoefBuf) is updated upon return, unless there are only
+ * zero coefficients in the currently decoded block. In this case
+ * the caller is expected to bypass the transform/dequantization of
+ * the empty blocks.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppBitStream or pOffset is NULL.
+ * - ppPosCoefBuf or pNumCoeff is NULL.
+ * OMX_Sts_Err - if one of the following is true:
+ * - an illegal code is encountered in the bitstream
+ *
+ */
+OMXResult omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC (
+ const OMX_U8 **ppBitStream,
+ OMX_S32*pOffset,
+ OMX_U8 *pNumCoeff,
+ OMX_U8 **ppPosCoefbuf
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DecodeCoeffsToPairCAVLC (6.3.4.1.2)
+ *
+ * Description:
+ * Performs CAVLC decoding and inverse zigzag scan for 4x4 block of
+ * Intra16x16DCLevel, Intra16x16ACLevel, LumaLevel, and ChromaACLevel. Inverse
+ * field scan is not supported. The decoded coefficients in the packed
+ * position-coefficient buffer are stored in reverse zig-zag order, i.e., the
+ * first buffer element contains the last non-zero postion-coefficient pair of
+ * the block. Within each position-coefficient pair, the position entry
+ * indicates the raster-scan position of the coefficient, while the
+ * coefficient entry contains the coefficient value.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream -Double pointer to current byte in bit stream buffer
+ * pOffset - Pointer to current bit position in the byte pointed to by
+ * *ppBitStream; valid in the range [0,7].
+ * sMaxNumCoeff - Maximum the number of non-zero coefficients in current
+ * block
+ * sVLCSelect - VLC table selector, obtained from the number of non-zero
+ * coefficients contained in the above and left 4x4 blocks. It is
+ * equivalent to the variable nC described in H.264 standard table
+ * 9 5, except its value can t be less than zero.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after each block is decoded.
+ * Buffer position (*ppPosCoefBuf) is updated upon return, unless
+ * there are only zero coefficients in the currently decoded block.
+ * In this case the caller is expected to bypass the
+ * transform/dequantization of the empty blocks.
+ * pOffset - *pOffset is updated after each block is decoded
+ * pNumCoeff - Pointer to the number of nonzero coefficients in this block
+ * ppPosCoefBuf - Double pointer to destination residual
+ * coefficient-position pair buffer
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppBitStream or pOffset is NULL.
+ * - ppPosCoefBuf or pNumCoeff is NULL.
+ * - sMaxNumCoeff is not equal to either 15 or 16.
+ * - sVLCSelect is less than 0.
+ *
+ * OMX_Sts_Err - if one of the following is true:
+ * - an illegal code is encountered in the bitstream
+ *
+ */
+OMXResult omxVCM4P10_DecodeCoeffsToPairCAVLC (
+ const OMX_U8 **ppBitStream,
+ OMX_S32 *pOffset,
+ OMX_U8 *pNumCoeff,
+ OMX_U8 **ppPosCoefbuf,
+ OMX_INT sVLCSelect,
+ OMX_INT sMaxNumCoeff
+);
+
+
+
+/**
+ * Function: omxVCM4P10_TransformDequantLumaDCFromPair (6.3.4.2.1)
+ *
+ * Description:
+ * Reconstructs the 4x4 LumaDC block from the coefficient-position pair
+ * buffer, performs integer inverse, and dequantization for 4x4 LumaDC
+ * coefficients, and updates the pair buffer pointer to the next non-empty
+ * block.
+ *
+ * Input Arguments:
+ *
+ * ppSrc - Double pointer to residual coefficient-position pair buffer
+ * output by CALVC decoding
+ * QP - Quantization parameter QpY
+ *
+ * Output Arguments:
+ *
+ * ppSrc - *ppSrc is updated to the start of next non empty block
+ * pDst - Pointer to the reconstructed 4x4 LumaDC coefficients buffer; must
+ * be aligned on a 8-byte boundary.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppSrc or pDst is NULL.
+ * - pDst is not 8 byte aligned.
+ * - QP is not in the range of [0-51].
+ *
+ */
+OMXResult omxVCM4P10_TransformDequantLumaDCFromPair (
+ const OMX_U8 **ppSrc,
+ OMX_S16 *pDst,
+ OMX_INT QP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_TransformDequantChromaDCFromPair (6.3.4.2.2)
+ *
+ * Description:
+ * Reconstruct the 2x2 ChromaDC block from coefficient-position pair buffer,
+ * perform integer inverse transformation, and dequantization for 2x2 chroma
+ * DC coefficients, and update the pair buffer pointer to next non-empty
+ * block.
+ *
+ * Input Arguments:
+ *
+ * ppSrc - Double pointer to residual coefficient-position pair buffer
+ * output by CALVC decoding
+ * QP - Quantization parameter QpC
+ *
+ * Output Arguments:
+ *
+ * ppSrc - *ppSrc is updated to the start of next non empty block
+ * pDst - Pointer to the reconstructed 2x2 ChromaDC coefficients buffer;
+ * must be aligned on a 4-byte boundary.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppSrc or pDst is NULL.
+ * - pDst is not 4-byte aligned.
+ * - QP is not in the range of [0-51].
+ *
+ */
+OMXResult omxVCM4P10_TransformDequantChromaDCFromPair (
+ const OMX_U8 **ppSrc,
+ OMX_S16 *pDst,
+ OMX_INT QP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DequantTransformResidualFromPairAndAdd (6.3.4.2.3)
+ *
+ * Description:
+ * Reconstruct the 4x4 residual block from coefficient-position pair buffer,
+ * perform dequantization and integer inverse transformation for 4x4 block of
+ * residuals with previous intra prediction or motion compensation data, and
+ * update the pair buffer pointer to next non-empty block. If pDC == NULL,
+ * there re 16 non-zero AC coefficients at most in the packed buffer starting
+ * from 4x4 block position 0; If pDC != NULL, there re 15 non-zero AC
+ * coefficients at most in the packet buffer starting from 4x4 block position
+ * 1.
+ *
+ * Input Arguments:
+ *
+ * ppSrc - Double pointer to residual coefficient-position pair buffer
+ * output by CALVC decoding
+ * pPred - Pointer to the predicted 4x4 block; must be aligned on a 4-byte
+ * boundary
+ * predStep - Predicted frame step size in bytes; must be a multiple of 4
+ * dstStep - Destination frame step in bytes; must be a multiple of 4
+ * pDC - Pointer to the DC coefficient of this block, NULL if it doesn't
+ * exist
+ * QP - QP Quantization parameter. It should be QpC in chroma 4x4 block
+ * decoding, otherwise it should be QpY.
+ * AC - Flag indicating if at least one non-zero AC coefficient exists
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the reconstructed 4x4 block data; must be aligned on a
+ * 4-byte boundary
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - pPred or pDst is NULL.
+ * - pPred or pDst is not 4-byte aligned.
+ * - predStep or dstStep is not a multiple of 4.
+ * - AC !=0 and Qp is not in the range of [0-51] or ppSrc == NULL.
+ * - AC ==0 && pDC ==NULL.
+ *
+ */
+OMXResult omxVCM4P10_DequantTransformResidualFromPairAndAdd (
+ const OMX_U8 **ppSrc,
+ const OMX_U8 *pPred,
+ const OMX_S16 *pDC,
+ OMX_U8 *pDst,
+ OMX_INT predStep,
+ OMX_INT dstStep,
+ OMX_INT QP,
+ OMX_INT AC
+);
+
+
+
+/**
+ * Function: omxVCM4P10_MEGetBufSize (6.3.5.1.1)
+ *
+ * Description:
+ * Computes the size, in bytes, of the vendor-specific specification
+ * structure for the omxVCM4P10 motion estimation functions BlockMatch_Integer
+ * and MotionEstimationMB.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P10MEMode
+ * pMEParams -motion estimation parameters
+ *
+ * Output Arguments:
+ *
+ * pSize - pointer to the number of bytes required for the motion
+ * estimation specification structure
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - pMEParams or pSize is NULL.
+ * - an invalid MEMode is specified.
+ *
+ */
+OMXResult omxVCM4P10_MEGetBufSize (
+ OMXVCM4P10MEMode MEmode,
+ const OMXVCM4P10MEParams *pMEParams,
+ OMX_U32 *pSize
+);
+
+
+
+/**
+ * Function: omxVCM4P10_MEInit (6.3.5.1.2)
+ *
+ * Description:
+ * Initializes the vendor-specific specification structure required for the
+ * omxVCM4P10 motion estimation functions: BlockMatch_Integer and
+ * MotionEstimationMB. Memory for the specification structure *pMESpec must be
+ * allocated prior to calling the function, and should be aligned on a 4-byte
+ * boundary. The number of bytes required for the specification structure can
+ * be determined using the function omxVCM4P10_MEGetBufSize. Following
+ * initialization by this function, the vendor-specific structure *pMESpec
+ * should contain an implementation-specific representation of all motion
+ * estimation parameters received via the structure pMEParams, for example
+ * searchRange16x16, searchRange8x8, etc.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P10MEMode
+ * pMEParams - motion estimation parameters
+ * pMESpec - pointer to the uninitialized ME specification structure
+ *
+ * Output Arguments:
+ *
+ * pMESpec - pointer to the initialized ME specification structure
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - pMEParams or pSize is NULL.
+ * - an invalid value was specified for the parameter MEmode
+ * - a negative or zero value was specified for one of the search ranges
+ * (e.g., pMBParams >searchRange8x8, pMEParams->searchRange16x16, etc.)
+ * - either in isolation or in combination, one or more of the enables or
+ * search ranges in the structure *pMEParams were configured such
+ * that the requested behavior fails to comply with [ISO14496-10].
+ *
+ */
+OMXResult omxVCM4P10_MEInit (
+ OMXVCM4P10MEMode MEmode,
+ const OMXVCM4P10MEParams *pMEParams,
+ void *pMESpec
+);
+
+
+
+/**
+ * Function: omxVCM4P10_BlockMatch_Integer (6.3.5.2.1)
+ *
+ * Description:
+ * Performs integer block match. Returns best MV and associated cost.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrgY - Pointer to the top-left corner of the current block:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * pSrcRefY - Pointer to the top-left corner of the co-located block in the
+ * reference picture:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * nSrcOrgStep - Stride of the original picture plane, expressed in terms
+ * of integer pixels; must be a multiple of iBlockWidth.
+ * nSrcRefStep - Stride of the reference picture plane, expressed in terms
+ * of integer pixels
+ * pRefRect - pointer to the valid reference rectangle inside the reference
+ * picture plane
+ * nCurrPointPos - position of the current block in the current plane
+ * iBlockWidth - Width of the current block, expressed in terms of integer
+ * pixels; must be equal to either 4, 8, or 16.
+ * iBlockHeight - Height of the current block, expressed in terms of
+ * integer pixels; must be equal to either 4, 8, or 16.
+ * nLamda - Lamda factor; used to compute motion cost
+ * pMVPred - Predicted MV; used to compute motion cost, expressed in terms
+ * of 1/4-pel units
+ * pMVCandidate - Candidate MV; used to initialize the motion search,
+ * expressed in terms of integer pixels
+ * pMESpec - pointer to the ME specification structure
+ *
+ * Output Arguments:
+ *
+ * pDstBestMV - Best MV resulting from integer search, expressed in terms
+ * of 1/4-pel units
+ * pBestCost - Motion cost associated with the best MV; computed as
+ * SAD+Lamda*BitsUsedByMV
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - any of the following pointers are NULL:
+ * pSrcOrgY, pSrcRefY, pRefRect, pMVPred, pMVCandidate, or pMESpec.
+ * - Either iBlockWidth or iBlockHeight are values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_BlockMatch_Integer (
+ const OMX_U8 *pSrcOrgY,
+ OMX_S32 nSrcOrgStep,
+ const OMX_U8 *pSrcRefY,
+ OMX_S32 nSrcRefStep,
+ const OMXRect *pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ OMX_U8 iBlockWidth,
+ OMX_U8 iBlockHeight,
+ OMX_U32 nLamda,
+ const OMXVCMotionVector *pMVPred,
+ const OMXVCMotionVector *pMVCandidate,
+ OMXVCMotionVector *pBestMV,
+ OMX_S32 *pBestCost,
+ void *pMESpec
+);
+
+
+
+/**
+ * Function: omxVCM4P10_BlockMatch_Half (6.3.5.2.2)
+ *
+ * Description:
+ * Performs a half-pel block match using results from a prior integer search.
+ * Returns the best MV and associated cost. This function estimates the
+ * half-pixel motion vector by interpolating the integer resolution motion
+ * vector referenced by the input parameter pSrcDstBestMV, i.e., the initial
+ * integer MV is generated externally. The function
+ * omxVCM4P10_BlockMatch_Integer may be used for integer motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrgY - Pointer to the current position in original picture plane:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * pSrcRefY - Pointer to the top-left corner of the co-located block in the
+ * reference picture:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * nSrcOrgStep - Stride of the original picture plane in terms of full
+ * pixels; must be a multiple of iBlockWidth.
+ * nSrcRefStep - Stride of the reference picture plane in terms of full
+ * pixels
+ * iBlockWidth - Width of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * iBlockHeight - Height of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * nLamda - Lamda factor, used to compute motion cost
+ * pMVPred - Predicted MV, represented in terms of 1/4-pel units; used to
+ * compute motion cost
+ * pSrcDstBestMV - The best MV resulting from a prior integer search,
+ * represented in terms of 1/4-pel units
+ *
+ * Output Arguments:
+ *
+ * pSrcDstBestMV - Best MV resulting from the half-pel search, expressed in
+ * terms of 1/4-pel units
+ * pBestCost - Motion cost associated with the best MV; computed as
+ * SAD+Lamda*BitsUsedByMV
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - any of the following pointers is NULL: pSrcOrgY, pSrcRefY,
+ * pSrcDstBestMV, pMVPred, pBestCost
+ * - iBlockWidth or iBlockHeight are equal to values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_BlockMatch_Half (
+ const OMX_U8 *pSrcOrgY,
+ OMX_S32 nSrcOrgStep,
+ const OMX_U8 *pSrcRefY,
+ OMX_S32 nSrcRefStep,
+ OMX_U8 iBlockWidth,
+ OMX_U8 iBlockHeight,
+ OMX_U32 nLamda,
+ const OMXVCMotionVector *pMVPred,
+ OMXVCMotionVector *pSrcDstBestMV,
+ OMX_S32 *pBestCost
+);
+
+
+
+/**
+ * Function: omxVCM4P10_BlockMatch_Quarter (6.3.5.2.3)
+ *
+ * Description:
+ * Performs a quarter-pel block match using results from a prior half-pel
+ * search. Returns the best MV and associated cost. This function estimates
+ * the quarter-pixel motion vector by interpolating the half-pel resolution
+ * motion vector referenced by the input parameter pSrcDstBestMV, i.e., the
+ * initial half-pel MV is generated externally. The function
+ * omxVCM4P10_BlockMatch_Half may be used for half-pel motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrgY - Pointer to the current position in original picture plane:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * pSrcRefY - Pointer to the top-left corner of the co-located block in the
+ * reference picture:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * nSrcOrgStep - Stride of the original picture plane in terms of full
+ * pixels; must be a multiple of iBlockWidth.
+ * nSrcRefStep - Stride of the reference picture plane in terms of full
+ * pixels
+ * iBlockWidth - Width of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * iBlockHeight - Height of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * nLamda - Lamda factor, used to compute motion cost
+ * pMVPred - Predicted MV, represented in terms of 1/4-pel units; used to
+ * compute motion cost
+ * pSrcDstBestMV - The best MV resulting from a prior half-pel search,
+ * represented in terms of 1/4 pel units
+ *
+ * Output Arguments:
+ *
+ * pSrcDstBestMV - Best MV resulting from the quarter-pel search, expressed
+ * in terms of 1/4-pel units
+ * pBestCost - Motion cost associated with the best MV; computed as
+ * SAD+Lamda*BitsUsedByMV
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - One or more of the following pointers is NULL:
+ * pSrcOrgY, pSrcRefY, pSrcDstBestMV, pMVPred, pBestCost
+ * - iBlockWidth or iBlockHeight are equal to values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_BlockMatch_Quarter (
+ const OMX_U8 *pSrcOrgY,
+ OMX_S32 nSrcOrgStep,
+ const OMX_U8 *pSrcRefY,
+ OMX_S32 nSrcRefStep,
+ OMX_U8 iBlockWidth,
+ OMX_U8 iBlockHeight,
+ OMX_U32 nLamda,
+ const OMXVCMotionVector *pMVPred,
+ OMXVCMotionVector *pSrcDstBestMV,
+ OMX_S32 *pBestCost
+);
+
+
+
+/**
+ * Function: omxVCM4P10_MotionEstimationMB (6.3.5.3.1)
+ *
+ * Description:
+ * Performs MB-level motion estimation and selects best motion estimation
+ * strategy from the set of modes supported in baseline profile [ISO14496-10].
+ *
+ * Input Arguments:
+ *
+ * pSrcCurrBuf - Pointer to the current position in original picture plane;
+ * 16-byte alignment required
+ * pSrcRefBufList - Pointer to an array with 16 entries. Each entry points
+ * to the top-left corner of the co-located MB in a reference
+ * picture. The array is filled from low-to-high with valid
+ * reference frame pointers; the unused high entries should be set
+ * to NULL. Ordering of the reference frames should follow
+ * [ISO14496-10] subclause 8.2.4 Decoding Process for Reference
+ * Picture Lists. The entries must be 16-byte aligned.
+ * pSrcRecBuf - Pointer to the top-left corner of the co-located MB in the
+ * reconstructed picture; must be 16-byte aligned.
+ * SrcCurrStep - Width of the original picture plane in terms of full
+ * pixels; must be a multiple of 16.
+ * SrcRefStep - Width of the reference picture plane in terms of full
+ * pixels; must be a multiple of 16.
+ * SrcRecStep - Width of the reconstructed picture plane in terms of full
+ * pixels; must be a multiple of 16.
+ * pRefRect - Pointer to the valid reference rectangle; relative to the
+ * image origin.
+ * pCurrPointPos - Position of the current macroblock in the current plane.
+ * Lambda - Lagrange factor for computing the cost function
+ * pMESpec - Pointer to the motion estimation specification structure; must
+ * have been allocated and initialized prior to calling this
+ * function.
+ * pMBInter - Array, of dimension four, containing pointers to information
+ * associated with four adjacent type INTER MBs (Left, Top,
+ * Top-Left, Top-Right). Any pointer in the array may be set equal
+ * to NULL if the corresponding MB doesn t exist or is not of type
+ * INTER.
+ * - pMBInter[0] - Pointer to left MB information
+ * - pMBInter[1] - Pointer to top MB information
+ * - pMBInter[2] - Pointer to top-left MB information
+ * - pMBInter[3] - Pointer to top-right MB information
+ * pMBIntra - Array, of dimension four, containing pointers to information
+ * associated with four adjacent type INTRA MBs (Left, Top,
+ * Top-Left, Top-Right). Any pointer in the array may be set equal
+ * to NULL if the corresponding MB doesn t exist or is not of type
+ * INTRA.
+ * - pMBIntra[0] - Pointer to left MB information
+ * - pMBIntra[1] - Pointer to top MB information
+ * - pMBIntra[2] - Pointer to top-left MB information
+ * - pMBIntra[3] - Pointer to top-right MB information
+ * pSrcDstMBCurr - Pointer to information structure for the current MB.
+ * The following entries should be set prior to calling the
+ * function: sliceID - the number of the slice the to which the
+ * current MB belongs.
+ *
+ * Output Arguments:
+ *
+ * pDstCost - Pointer to the minimum motion cost for the current MB.
+ * pDstBlockSAD - Pointer to the array of SADs for each of the sixteen luma
+ * 4x4 blocks in each MB. The block SADs are in scan order for
+ * each MB. For implementations that cannot compute the SAD values
+ * individually, the maximum possible value (0xffff) is returned
+ * for each of the 16 block SAD entries.
+ * pSrcDstMBCurr - Pointer to updated information structure for the current
+ * MB after MB-level motion estimation has been completed. The
+ * following fields are updated by the ME function. The following
+ * parameter set quantifies the MB-level ME search results:
+ * - MbType
+ * - subMBType[4]
+ * - pMV0[4][4]
+ * - pMVPred[4][4]
+ * - pRefL0Idx[4]
+ * - Intra16x16PredMode
+ * - pIntra4x4PredMode[4][4]
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - One or more of the following pointers is NULL: pSrcCurrBuf,
+ * pSrcRefBufList, pSrcRecBuf, pRefRect, pCurrPointPos, pMESpec,
+ * pMBInter, pMBIntra,pSrcDstMBCurr, pDstCost, pSrcRefBufList[0]
+ * - SrcRefStep, SrcRecStep are not multiples of 16
+ * - iBlockWidth or iBlockHeight are values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_MotionEstimationMB (
+ const OMX_U8 *pSrcCurrBuf,
+ OMX_S32 SrcCurrStep,
+ const OMX_U8 *pSrcRefBufList[15],
+ OMX_S32 SrcRefStep,
+ const OMX_U8 *pSrcRecBuf,
+ OMX_S32 SrcRecStep,
+ const OMXRect *pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ OMX_U32 Lambda,
+ void *pMESpec,
+ const OMXVCM4P10MBInfoPtr *pMBInter,
+ const OMXVCM4P10MBInfoPtr *pMBIntra,
+ OMXVCM4P10MBInfoPtr pSrcDstMBCurr,
+ OMX_INT *pDstCost,
+ OMX_U16 *pDstBlockSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SAD_4x (6.3.5.4.1)
+ *
+ * Description:
+ * This function calculates the SAD for 4x8 and 4x4 blocks.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg -Pointer to the original block; must be aligned on a 4-byte
+ * boundary.
+ * iStepOrg -Step of the original block buffer; must be a multiple of 4.
+ * pSrcRef -Pointer to the reference block
+ * iStepRef -Step of the reference block buffer
+ * iHeight -Height of the block; must be equal to either 4 or 8.
+ *
+ * Output Arguments:
+ *
+ * pDstSAD -Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - One or more of the following pointers is NULL:
+ * pSrcOrg, pSrcRef, or pDstSAD
+ * - iHeight is not equal to either 4 or 8.
+ * - iStepOrg is not a multiple of 4
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SAD_4x (
+ const OMX_U8 *pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8 *pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SADQuar_4x (6.3.5.4.2)
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the average
+ * of the other two (pSrcRef0 and pSrcRef1) for 4x8 or 4x4 blocks. Rounding
+ * is applied according to the convention (a+b+1)>>1.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the original block; must be aligned on a 4-byte
+ * boundary.
+ * pSrcRef0 - Pointer to reference block 0
+ * pSrcRef1 - Pointer to reference block 1
+ * iSrcStep - Step of the original block buffer; must be a multiple of 4.
+ * iRefStep0 - Step of reference block 0
+ * iRefStep1 - Step of reference block 1
+ * iHeight - Height of the block; must be equal to either 4 or 8.
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - iHeight is not equal to either 4 or 8.
+ * - One or more of the following pointers is NULL: pSrc, pSrcRef0,
+ * pSrcRef1, pDstSAD.
+ * - iSrcStep is not a multiple of 4
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SADQuar_4x (
+ const OMX_U8 *pSrc,
+ const OMX_U8 *pSrcRef0,
+ const OMX_U8 *pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SADQuar_8x (6.3.5.4.3)
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the average
+ * of the other two (pSrcRef0 and pSrcRef1) for 8x16, 8x8, or 8x4 blocks.
+ * Rounding is applied according to the convention (a+b+1)>>1.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the original block; must be aligned on an 8-byte
+ * boundary.
+ * pSrcRef0 - Pointer to reference block 0
+ * pSrcRef1 - Pointer to reference block 1
+ * iSrcStep - Step of the original block buffer; must be a multiple of 8.
+ * iRefStep0 - Step of reference block 0
+ * iRefStep1 - Step of reference block 1
+ * iHeight - Height of the block; must be equal either 4, 8, or 16.
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - iHeight is not equal to either 4, 8, or 16.
+ * - One or more of the following pointers is NULL: pSrc, pSrcRef0,
+ * pSrcRef1, pDstSAD.
+ * - iSrcStep is not a multiple of 8
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SADQuar_8x (
+ const OMX_U8 *pSrc,
+ const OMX_U8 *pSrcRef0,
+ const OMX_U8 *pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SADQuar_16x (6.3.5.4.4)
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the average
+ * of the other two (pSrcRef0 and pSrcRef1) for 16x16 or 16x8 blocks.
+ * Rounding is applied according to the convention (a+b+1)>>1.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the original block; must be aligned on a 16-byte
+ * boundary.
+ * pSrcRef0 - Pointer to reference block 0
+ * pSrcRef1 - Pointer to reference block 1
+ * iSrcStep - Step of the original block buffer; must be a multiple of 16
+ * iRefStep0 - Step of reference block 0
+ * iRefStep1 - Step of reference block 1
+ * iHeight - Height of the block; must be equal to either 8 or 16
+ *
+ * Output Arguments:
+ *
+ * pDstSAD -Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - iHeight is not equal to either 8 or 16.
+ * - One or more of the following pointers is NULL: pSrc, pSrcRef0,
+ * pSrcRef1, pDstSAD.
+ * - iSrcStep is not a multiple of 16
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SADQuar_16x (
+ const OMX_U8 *pSrc,
+ const OMX_U8 *pSrcRef0,
+ const OMX_U8 *pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SATD_4x4 (6.3.5.4.5)
+ *
+ * Description:
+ * This function calculates the sum of absolute transform differences (SATD)
+ * for a 4x4 block by applying a Hadamard transform to the difference block
+ * and then calculating the sum of absolute coefficient values.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to the original block; must be aligned on a 4-byte
+ * boundary
+ * iStepOrg - Step of the original block buffer; must be a multiple of 4
+ * pSrcRef - Pointer to the reference block; must be aligned on a 4-byte
+ * boundary
+ * iStepRef - Step of the reference block buffer; must be a multiple of 4
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - pointer to the resulting SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pSrcRef, or pDstSAD either pSrcOrg
+ * - pSrcRef is not aligned on a 4-byte boundary
+ * - iStepOrg <= 0 or iStepOrg is not a multiple of 4
+ * - iStepRef <= 0 or iStepRef is not a multiple of 4
+ *
+ */
+OMXResult omxVCM4P10_SATD_4x4 (
+ const OMX_U8 *pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8 *pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_U32 *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InterpolateHalfHor_Luma (6.3.5.5.1)
+ *
+ * Description:
+ * This function performs interpolation for two horizontal 1/2-pel positions
+ * (-1/2,0) and (1/2, 0) - around a full-pel position.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the top-left corner of the block used to interpolate in
+ * the reconstruction frame plane.
+ * iSrcStep - Step of the source buffer.
+ * iDstStep - Step of the destination(interpolation) buffer; must be a
+ * multiple of iWidth.
+ * iWidth - Width of the current block; must be equal to either 4, 8, or 16
+ * iHeight - Height of the current block; must be equal to 4, 8, or 16
+ *
+ * Output Arguments:
+ *
+ * pDstLeft -Pointer to the interpolation buffer of the left -pel position
+ * (-1/2, 0)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ * pDstRight -Pointer to the interpolation buffer of the right -pel
+ * position (1/2, 0)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrc, pDstLeft, or pDstRight
+ * - iWidth or iHeight have values other than 4, 8, or 16
+ * - iWidth==4 but pDstLeft and/or pDstRight is/are not aligned on a 4-byte boundary
+ * - iWidth==8 but pDstLeft and/or pDstRight is/are not aligned on a 8-byte boundary
+ * - iWidth==16 but pDstLeft and/or pDstRight is/are not aligned on a 16-byte boundary
+ * - any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_InterpolateHalfHor_Luma (
+ const OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDstLeft,
+ OMX_U8 *pDstRight,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InterpolateHalfVer_Luma (6.3.5.5.2)
+ *
+ * Description:
+ * This function performs interpolation for two vertical 1/2-pel positions -
+ * (0, -1/2) and (0, 1/2) - around a full-pel position.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to top-left corner of block used to interpolate in the
+ * reconstructed frame plane
+ * iSrcStep - Step of the source buffer.
+ * iDstStep - Step of the destination (interpolation) buffer; must be a
+ * multiple of iWidth.
+ * iWidth - Width of the current block; must be equal to either 4, 8, or 16
+ * iHeight - Height of the current block; must be equal to either 4, 8, or 16
+ *
+ * Output Arguments:
+ *
+ * pDstUp -Pointer to the interpolation buffer of the -pel position above
+ * the current full-pel position (0, -1/2)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ * pDstDown -Pointer to the interpolation buffer of the -pel position below
+ * the current full-pel position (0, 1/2)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrc, pDstUp, or pDstDown
+ * - iWidth or iHeight have values other than 4, 8, or 16
+ * - iWidth==4 but pDstUp and/or pDstDown is/are not aligned on a 4-byte boundary
+ * - iWidth==8 but pDstUp and/or pDstDown is/are not aligned on a 8-byte boundary
+ * - iWidth==16 but pDstUp and/or pDstDown is/are not aligned on a 16-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InterpolateHalfVer_Luma (
+ const OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDstUp,
+ OMX_U8 *pDstDown,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_Average_4x (6.3.5.5.3)
+ *
+ * Description:
+ * This function calculates the average of two 4x4, 4x8 blocks. The result
+ * is rounded according to (a+b+1)/2.
+ *
+ * Input Arguments:
+ *
+ * pPred0 - Pointer to the top-left corner of reference block 0
+ * pPred1 - Pointer to the top-left corner of reference block 1
+ * iPredStep0 - Step of reference block 0; must be a multiple of 4.
+ * iPredStep1 - Step of reference block 1; must be a multiple of 4.
+ * iDstStep - Step of the destination buffer; must be a multiple of 4.
+ * iHeight - Height of the blocks; must be either 4 or 8.
+ *
+ * Output Arguments:
+ *
+ * pDstPred - Pointer to the destination buffer. 4-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pPred0, pPred1, or pDstPred
+ * - pDstPred is not aligned on a 4-byte boundary
+ * - iPredStep0 <= 0 or iPredStep0 is not a multiple of 4
+ * - iPredStep1 <= 0 or iPredStep1 is not a multiple of 4
+ * - iDstStep <= 0 or iDstStep is not a multiple of 4
+ * - iHeight is not equal to either 4 or 8
+ *
+ */
+OMXResult omxVCM4P10_Average_4x (
+ const OMX_U8 *pPred0,
+ const OMX_U8 *pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8 *pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_TransformQuant_ChromaDC (6.3.5.6.1)
+ *
+ * Description:
+ * This function performs 2x2 Hadamard transform of chroma DC coefficients
+ * and then quantizes the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the 2x2 array of chroma DC coefficients. 8-byte
+ * alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ * bIntra - Indicate whether this is an INTRA block. 1-INTRA, 0-INTER
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - Pointer to transformed and quantized coefficients. 8-byte
+ * alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcDst
+ * - pSrcDst is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_TransformQuant_ChromaDC (
+ OMX_S16 *pSrcDst,
+ OMX_U32 iQP,
+ OMX_U8 bIntra
+);
+
+
+
+/**
+ * Function: omxVCM4P10_TransformQuant_LumaDC (6.3.5.6.2)
+ *
+ * Description:
+ * This function performs a 4x4 Hadamard transform of luma DC coefficients
+ * and then quantizes the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the 4x4 array of luma DC coefficients. 16-byte
+ * alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - Pointer to transformed and quantized coefficients. 16-byte
+ * alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL: pSrcDst
+ * - pSrcDst is not aligned on an 16-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_TransformQuant_LumaDC (
+ OMX_S16 *pSrcDst,
+ OMX_U32 iQP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InvTransformDequant_LumaDC (6.3.5.6.3)
+ *
+ * Description:
+ * This function performs inverse 4x4 Hadamard transform and then dequantizes
+ * the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the 4x4 array of the 4x4 Hadamard-transformed and
+ * quantized coefficients. 16 byte alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to inverse-transformed and dequantized coefficients.
+ * 16-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL: pSrc
+ * - pSrc or pDst is not aligned on a 16-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InvTransformDequant_LumaDC (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst,
+ OMX_U32 iQP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InvTransformDequant_ChromaDC (6.3.5.6.4)
+ *
+ * Description:
+ * This function performs inverse 2x2 Hadamard transform and then dequantizes
+ * the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the 2x2 array of the 2x2 Hadamard-transformed and
+ * quantized coefficients. 8 byte alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to inverse-transformed and dequantized coefficients.
+ * 8-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL: pSrc
+ * - pSrc or pDst is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InvTransformDequant_ChromaDC (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst,
+ OMX_U32 iQP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InvTransformResidualAndAdd (6.3.5.7.1)
+ *
+ * Description:
+ * This function performs inverse an 4x4 integer transformation to produce
+ * the difference signal and then adds the difference to the prediction to get
+ * the reconstructed signal.
+ *
+ * Input Arguments:
+ *
+ * pSrcPred - Pointer to prediction signal. 4-byte alignment required.
+ * pDequantCoeff - Pointer to the transformed coefficients. 8-byte
+ * alignment required.
+ * iSrcPredStep - Step of the prediction buffer; must be a multiple of 4.
+ * iDstReconStep - Step of the destination reconstruction buffer; must be a
+ * multiple of 4.
+ * bAC - Indicate whether there is AC coefficients in the coefficients
+ * matrix.
+ *
+ * Output Arguments:
+ *
+ * pDstRecon -Pointer to the destination reconstruction buffer. 4-byte
+ * alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcPred, pDequantCoeff, pDstRecon
+ * - pSrcPred is not aligned on a 4-byte boundary
+ * - iSrcPredStep or iDstReconStep is not a multiple of 4.
+ * - pDequantCoeff is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InvTransformResidualAndAdd (
+ const OMX_U8 *pSrcPred,
+ const OMX_S16 *pDequantCoeff,
+ OMX_U8 *pDstRecon,
+ OMX_U32 iSrcPredStep,
+ OMX_U32 iDstReconStep,
+ OMX_U8 bAC
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SubAndTransformQDQResidual (6.3.5.8.1)
+ *
+ * Description:
+ * This function subtracts the prediction signal from the original signal to
+ * produce the difference signal and then performs a 4x4 integer transform and
+ * quantization. The quantized transformed coefficients are stored as
+ * pDstQuantCoeff. This function can also output dequantized coefficients or
+ * unquantized DC coefficients optionally by setting the pointers
+ * pDstDeQuantCoeff, pDCCoeff.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to original signal. 4-byte alignment required.
+ * pSrcPred - Pointer to prediction signal. 4-byte alignment required.
+ * iSrcOrgStep - Step of the original signal buffer; must be a multiple of
+ * 4.
+ * iSrcPredStep - Step of the prediction signal buffer; must be a multiple
+ * of 4.
+ * pNumCoeff -Number of non-zero coefficients after quantization. If this
+ * parameter is not required, it is set to NULL.
+ * nThreshSAD - Zero-block early detection threshold. If this parameter is
+ * not required, it is set to 0.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ * bIntra - Indicates whether this is an INTRA block, either 1-INTRA or
+ * 0-INTER
+ *
+ * Output Arguments:
+ *
+ * pDstQuantCoeff - Pointer to the quantized transformed coefficients.
+ * 8-byte alignment required.
+ * pDstDeQuantCoeff - Pointer to the dequantized transformed coefficients
+ * if this parameter is not equal to NULL. 8-byte alignment
+ * required.
+ * pDCCoeff - Pointer to the unquantized DC coefficient if this parameter
+ * is not equal to NULL.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pSrcPred, pNumCoeff, pDstQuantCoeff,
+ * pDstDeQuantCoeff, pDCCoeff
+ * - pSrcOrg is not aligned on a 4-byte boundary
+ * - pSrcPred is not aligned on a 4-byte boundary
+ * - iSrcOrgStep is not a multiple of 4
+ * - iSrcPredStep is not a multiple of 4
+ * - pDstQuantCoeff or pDstDeQuantCoeff is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_SubAndTransformQDQResidual (
+ const OMX_U8 *pSrcOrg,
+ const OMX_U8 *pSrcPred,
+ OMX_U32 iSrcOrgStep,
+ OMX_U32 iSrcPredStep,
+ OMX_S16 *pDstQuantCoeff,
+ OMX_S16 *pDstDeQuantCoeff,
+ OMX_S16 *pDCCoeff,
+ OMX_S8 *pNumCoeff,
+ OMX_U32 nThreshSAD,
+ OMX_U32 iQP,
+ OMX_U8 bIntra
+);
+
+
+
+/**
+ * Function: omxVCM4P10_GetVLCInfo (6.3.5.9.1)
+ *
+ * Description:
+ * This function extracts run-length encoding (RLE) information from the
+ * coefficient matrix. The results are returned in an OMXVCM4P10VLCInfo
+ * structure.
+ *
+ * Input Arguments:
+ *
+ * pSrcCoeff - pointer to the transform coefficient matrix. 8-byte
+ * alignment required.
+ * pScanMatrix - pointer to the scan order definition matrix. For a luma
+ * block the scan matrix should follow [ISO14496-10] section 8.5.4,
+ * and should contain the values 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13,
+ * 10, 7, 11, 14, 15. For a chroma block, the scan matrix should
+ * contain the values 0, 1, 2, 3.
+ * bAC - indicates presence of a DC coefficient; 0 = DC coefficient
+ * present, 1= DC coefficient absent.
+ * MaxNumCoef - specifies the number of coefficients contained in the
+ * transform coefficient matrix, pSrcCoeff. The value should be 16
+ * for blocks of type LUMADC, LUMAAC, LUMALEVEL, and CHROMAAC. The
+ * value should be 4 for blocks of type CHROMADC.
+ *
+ * Output Arguments:
+ *
+ * pDstVLCInfo - pointer to structure that stores information for
+ * run-length coding.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcCoeff, pScanMatrix, pDstVLCInfo
+ * - pSrcCoeff is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_GetVLCInfo (
+ const OMX_S16 *pSrcCoeff,
+ const OMX_U8 *pScanMatrix,
+ OMX_U8 bAC,
+ OMX_U32 MaxNumCoef,
+ OMXVCM4P10VLCInfo*pDstVLCInfo
+);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** end of #define _OMXVC_H_ */
+
+/** EOF */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/omxVC_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/omxVC_s.h
new file mode 100644
index 0000000..be974d5
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/api/omxVC_s.h
@@ -0,0 +1,129 @@
+;/******************************************************************************
+;// Copyright (c) 1999-2005 The Khronos Group Inc. All Rights Reserved
+;//
+;//
+;//
+;//
+;//
+;//
+;//
+;//
+;******************************************************************************/
+
+;/** =============== Structure Definition for Sample Generation ============== */
+;/** transparent status */
+
+;enum {
+OMX_VIDEO_TRANSPARENT EQU 0; /** Wholly transparent */
+OMX_VIDEO_PARTIAL EQU 1; /** Partially transparent */
+OMX_VIDEO_OPAQUE EQU 2; /** Opaque */
+;}
+
+;/** direction */
+;enum {
+OMX_VIDEO_NONE EQU 0;
+OMX_VIDEO_HORIZONTAL EQU 1;
+OMX_VIDEO_VERTICAL EQU 2;
+;}
+
+;/** bilinear interpolation type */
+;enum {
+OMX_VIDEO_INTEGER_PIXEL EQU 0; /** case ¡°a¡± */
+OMX_VIDEO_HALF_PIXEL_X EQU 1; /** case ¡°b¡± */
+OMX_VIDEO_HALF_PIXEL_Y EQU 2; /** case ¡°c¡± */
+OMX_VIDEO_HALF_PIXEL_XY EQU 3; /** case ¡°d¡± */
+;}
+
+;enum {
+OMX_UPPER EQU 1; /** set if the above macroblock is available */
+OMX_LEFT EQU 2; /** set if the left macroblock is available */
+OMX_CENTER EQU 4;
+OMX_RIGHT EQU 8;
+OMX_LOWER EQU 16;
+OMX_UPPER_LEFT EQU 32; /** set if the above-left macroblock is available */
+OMX_UPPER_RIGHT EQU 64; /** set if the above-right macroblock is available */
+OMX_LOWER_LEFT EQU 128;
+OMX_LOWER_RIGHT EQU 256
+;}
+
+;enum {
+OMX_VIDEO_LUMINANCE EQU 0; /** Luminance component */
+OMX_VIDEO_CHROMINANCE EQU 1; /** chrominance component */
+OMX_VIDEO_ALPHA EQU 2; /** Alpha component */
+;}
+
+;enum {
+OMX_VIDEO_INTER EQU 0; /** P picture or P-VOP */
+OMX_VIDEO_INTER_Q EQU 1; /** P picture or P-VOP */
+OMX_VIDEO_INTER4V EQU 2; /** P picture or P-VOP */
+OMX_VIDEO_INTRA EQU 3; /** I and P picture; I- and P-VOP */
+OMX_VIDEO_INTRA_Q EQU 4; /** I and P picture; I- and P-VOP */
+OMX_VIDEO_INTER4V_Q EQU 5; /** P picture or P-VOP (H.263)*/
+OMX_VIDEO_DIRECT EQU 6; /** B picture or B-VOP (MPEG-4 only) */
+OMX_VIDEO_INTERPOLATE EQU 7; /** B picture or B-VOP */
+OMX_VIDEO_BACKWARD EQU 8; /** B picture or B-VOP */
+OMX_VIDEO_FORWARD EQU 9; /** B picture or B-VOP */
+OMX_VIDEO_NOTCODED EQU 10; /** B picture or B-VOP */
+;}
+
+;enum {
+OMX_16X16_VERT EQU 0; /** Intra_16x16_Vertical (prediction mode) */
+OMX_16X16_HOR EQU 1; /** Intra_16x16_Horizontal (prediction mode) */
+OMX_16X16_DC EQU 2; /** Intra_16x16_DC (prediction mode) */
+OMX_16X16_PLANE EQU 3; /** Intra_16x16_Plane (prediction mode) */
+;}
+
+;enum {
+OMX_4x4_VERT EQU 0; /** Intra_4x4_Vertical (prediction mode) */
+OMX_4x4_HOR EQU 1; /** Intra_4x4_Horizontal (prediction mode) */
+OMX_4x4_DC EQU 2; /** Intra_4x4_DC (prediction mode) */
+OMX_4x4_DIAG_DL EQU 3; /** Intra_4x4_Diagonal_Down_Left (prediction mode) */
+OMX_4x4_DIAG_DR EQU 4; /** Intra_4x4_Diagonal_Down_Right (prediction mode) */
+OMX_4x4_VR EQU 5; /** Intra_4x4_Vertical_Right (prediction mode) */
+OMX_4x4_HD EQU 6; /** Intra_4x4_Horizontal_Down (prediction mode) */
+OMX_4x4_VL EQU 7; /** Intra_4x4_Vertical_Left (prediction mode) */
+OMX_4x4_HU EQU 8; /** Intra_4x4_Horizontal_Up (prediction mode) */
+;}
+
+;enum {
+OMX_CHROMA_DC EQU 0; /** Intra_Chroma_DC (prediction mode) */
+OMX_CHROMA_HOR EQU 1; /** Intra_Chroma_Horizontal (prediction mode) */
+OMX_CHROMA_VERT EQU 2; /** Intra_Chroma_Vertical (prediction mode) */
+OMX_CHROMA_PLANE EQU 3; /** Intra_Chroma_Plane (prediction mode) */
+;}
+
+;typedef struct {
+x EQU 0;
+y EQU 4;
+;}OMXCoordinate;
+
+;typedef struct {
+dx EQU 0;
+dy EQU 2;
+;}OMXMotionVector;
+
+;typedef struct {
+xx EQU 0;
+yy EQU 4;
+width EQU 8;
+height EQU 12;
+;}OMXiRect;
+
+;typedef enum {
+OMX_VC_INTER EQU 0; /** P picture or P-VOP */
+OMX_VC_INTER_Q EQU 1; /** P picture or P-VOP */
+OMX_VC_INTER4V EQU 2; /** P picture or P-VOP */
+OMX_VC_INTRA EQU 3; /** I and P picture, I- and P-VOP */
+OMX_VC_INTRA_Q EQU 4; /** I and P picture, I- and P-VOP */
+OMX_VC_INTER4V_Q EQU 5; /** P picture or P-VOP (H.263)*/
+;} OMXVCM4P2MacroblockType;
+
+;enum {
+OMX_VC_NONE EQU 0
+OMX_VC_HORIZONTAL EQU 1
+OMX_VC_VERTICAL EQU 2
+;};
+
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_Copy16x16_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_Copy16x16_s.s
new file mode 100644
index 0000000..2663a70
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_Copy16x16_s.s
@@ -0,0 +1,148 @@
+ ;/**
+ ; * Function: omxVCCOMM_Copy16x16
+ ; *
+ ; * Description:
+ ; * Copies the reference 16x16 block to the current block.
+ ; * Parameters:
+ ; * [in] pSrc - pointer to the reference block in the source frame; must be aligned on an 16-byte boundary.
+ ; * [in] step - distance between the starts of consecutive lines in the reference frame, in bytes;
+ ; * must be a multiple of 16 and must be larger than or equal to 16.
+ ; * [out] pDst - pointer to the destination block; must be aligned on an 8-byte boundary.
+ ; * Return Value:
+ ; * OMX_Sts_NoErr - no error
+ ; * OMX_Sts_BadArgErr - bad arguments; returned under any of the following conditions:
+ ; * - one or more of the following pointers is NULL: pSrc, pDst
+ ; * - one or more of the following pointers is not aligned on an 16-byte boundary: pSrc, pDst
+ ; * - step <16 or step is not a multiple of 16.
+ ; */
+
+ INCLUDE omxtypes_s.h
+
+
+ M_VARIANTS ARM1136JS
+
+
+
+
+ IF ARM1136JS
+
+;//Input Arguments
+pSrc RN 0
+pDst RN 1
+step RN 2
+
+;//Local Variables
+Count RN 14
+X0 RN 2
+X1 RN 4
+
+Return RN 0
+
+ M_START omxVCCOMM_Copy16x16,r5
+
+
+
+ SUB Count,step,#8 ;//Count=step-8
+ LDRD X0,[pSrc],#8 ;//pSrc after loading pSrc=pSrc+8
+ LDRD X1,[pSrc],Count ;//pSrc after loading pSrc=pSrc+step
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ ;// loading 16 bytes and storing
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],#8
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ STRD X0,[pDst],#8
+ MOV Return,#OMX_Sts_NoErr
+ STRD X1,[pDst],#8
+
+
+ M_END
+ ENDIF
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_Copy8x8_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_Copy8x8_s.s
new file mode 100644
index 0000000..993873c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_Copy8x8_s.s
@@ -0,0 +1,72 @@
+ ;/**
+ ; * Function: omxVCCOMM_Copy8x8
+ ; *
+ ; * Description:
+ ; * Copies the reference 8x8 block to the current block.
+ ; * Parameters:
+ ; * [in] pSrc - pointer to the reference block in the source frame; must be aligned on an 8-byte boundary.
+ ; * [in] step - distance between the starts of consecutive lines in the reference frame, in bytes;
+ ; * must be a multiple of 8 and must be larger than or equal to 8.
+ ; * [out] pDst - pointer to the destination block; must be aligned on an 8-byte boundary.
+ ; * Return Value:
+ ; * OMX_Sts_NoErr - no error
+ ; * OMX_Sts_BadArgErr - bad arguments; returned under any of the following conditions:
+ ; * - one or more of the following pointers is NULL: pSrc, pDst
+ ; * - one or more of the following pointers is not aligned on an 8-byte boundary: pSrc, pDst
+ ; * - step <8 or step is not a multiple of 8.
+ ; */
+
+ INCLUDE omxtypes_s.h
+
+
+ M_VARIANTS ARM1136JS
+
+
+
+
+ IF ARM1136JS
+
+;//Input Arguments
+pSrc RN 0
+pDst RN 1
+step RN 2
+
+;//Local Variables
+Count RN 14
+X0 RN 2
+X1 RN 4
+Return RN 0
+ M_START omxVCCOMM_Copy8x8,r5
+
+
+
+ MOV Count,step ;//Count=step
+
+ LDRD X0,[pSrc],Count ;//pSrc after loading : pSrc=pSrc+step
+ LDRD X1,[pSrc],Count
+
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],Count
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],Count
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ STRD X0,[pDst],#8
+ LDRD X0,[pSrc],Count
+ STRD X1,[pDst],#8
+ LDRD X1,[pSrc],Count
+
+ STRD X0,[pDst],#8
+ MOV Return,#OMX_Sts_NoErr
+ STRD X1,[pDst],#8
+
+
+ M_END
+ ENDIF
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
new file mode 100644
index 0000000..02b4b08
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
@@ -0,0 +1,189 @@
+;//
+;//
+;// File Name: omxVCCOMM_ExpandFrame_I_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// Description:
+;// This function will Expand Frame boundary pixels into Plane
+;//
+;//
+
+;// Include standard headers
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+;// Import symbols required from other files
+;// (For example tables)
+
+
+;// Set debugging level
+DEBUG_ON SETL {FALSE}
+
+
+
+
+
+
+
+;// Guarding implementation by the processor name
+
+ IF ARM1136JS
+
+;//Input Registers
+
+pSrcDstPlane RN 0
+iFrameWidth RN 1
+iFrameHeight RN 2
+iExpandPels RN 3
+
+
+;//Output Registers
+
+result RN 0
+
+;//Local Scratch Registers
+
+iPlaneStep RN 4
+pTop RN 5
+pBottom RN 6
+pBottomIndex RN 7
+x RN 8
+y RN 9
+tempTop RN 10
+tempBot RN 11
+ColStep RN 12
+pLeft RN 5
+pRight RN 6
+pRightIndex RN 7
+tempLeft1 RN 10
+tempRight1 RN 11
+tempLeft2 RN 14
+tempRight2 RN 2
+indexY RN 14
+RowStep RN 12
+expandTo4bytes RN 1 ;// copy a byte to 4 bytes of a word
+
+ ;// Allocate stack memory required by the function
+
+
+ ;// Write function header
+ M_START omxVCCOMM_ExpandFrame_I,r11
+
+ ;// Define stack arguments
+ M_ARG iPlaneStepOnStack, 4
+
+ ;// Load argument from the stack
+ M_LDR iPlaneStep, iPlaneStepOnStack
+
+ MUL pTop,iExpandPels,iPlaneStep
+ MLA pBottom,iFrameHeight,iPlaneStep,pSrcDstPlane
+ SUB x,iFrameWidth,#4
+ MOV indexY,pTop
+ ADD ColStep,indexY,#4
+ SUB pBottomIndex,pBottom,iPlaneStep
+ SUB pTop,pSrcDstPlane,pTop
+
+
+ ADD pTop,pTop,x
+ ADD pBottom,pBottom,x
+
+ ;//------------------------------------------------------------------------
+ ;// The following improves upon the C implmentation
+ ;// The x and y loops are interchanged: This ensures that the values of
+ ;// pSrcDstPlane [x] and pSrcDstPlane [(iFrameHeight - 1) * iPlaneStep + x]
+ ;// which depend only on loop variable 'x' are loaded once and used in
+ ;// multiple stores in the 'Y' loop
+ ;//------------------------------------------------------------------------
+
+ ;// xloop
+ExpandFrameTopBotXloop
+
+ LDR tempTop,[pSrcDstPlane,x]
+ ;//------------------------------------------------------------------------
+ ;// pSrcDstPlane [(iFrameHeight - 1) * iPlaneStep + x] is simplified as:
+ ;// pSrcDstPlane + (iFrameHeight * iPlaneStep) - iPlaneStep + x ==
+ ;// pBottom - iPlaneStep + x == pBottomIndex [x]
+ ;// The value of pBottomIndex is calculated above this 'x' loop
+ ;//------------------------------------------------------------------------
+ LDR tempBot,[pBottomIndex,x]
+
+ ;// yloop
+ MOV y,iExpandPels
+
+ExpandFrameTopBotYloop
+ SUBS y,y,#1
+ M_STR tempTop,[pTop],iPlaneStep
+ M_STR tempBot,[pBottom],iPlaneStep
+ BGT ExpandFrameTopBotYloop
+
+ SUBS x,x,#4
+ SUB pTop,pTop,ColStep
+ SUB pBottom,pBottom,ColStep
+ BGE ExpandFrameTopBotXloop
+
+
+ ;// y loop
+ ;// The product is already calculated above : Reuse
+ ;//MUL indexY,iExpandPels,iPlaneStep
+
+ SUB pSrcDstPlane,pSrcDstPlane,indexY
+ SUB pLeft,pSrcDstPlane,iExpandPels ;// pLeft->points to the top left of the expanded block
+ ADD pRight,pSrcDstPlane,iFrameWidth
+ SUB pRightIndex,pRight,#1
+
+ ADD y,iFrameHeight,iExpandPels,LSL #1
+ LDR expandTo4bytes,=0x01010101
+
+ RSB RowStep,iExpandPels,iPlaneStep,LSL #1
+
+ ;// The Y Loop is unrolled twice
+ExpandFrameLeftRightYloop
+ LDRB tempLeft2,[pSrcDstPlane,iPlaneStep] ;// PreLoad the values
+ LDRB tempRight2,[pRightIndex,iPlaneStep]
+ M_LDRB tempLeft1,[pSrcDstPlane],iPlaneStep,LSL #1 ;// PreLoad the values
+ M_LDRB tempRight1,[pRightIndex],iPlaneStep,LSL #1
+
+ SUB x,iExpandPels,#4
+ MUL tempLeft2,tempLeft2,expandTo4bytes ;// Copy the single byte to 4 bytes
+ MUL tempRight2,tempRight2,expandTo4bytes
+ MUL tempLeft1,tempLeft1,expandTo4bytes ;// Copy the single byte to 4 bytes
+ MUL tempRight1,tempRight1,expandTo4bytes
+
+
+ ;// x loop
+ExpandFrameLeftRightXloop
+ SUBS x,x,#4
+ STR tempLeft2,[pLeft,iPlaneStep] ;// Store the 4 bytes at one go
+ STR tempRight2,[pRight,iPlaneStep]
+ STR tempLeft1,[pLeft],#4 ;// Store the 4 bytes at one go
+ STR tempRight1,[pRight],#4
+ BGE ExpandFrameLeftRightXloop
+
+ SUBS y,y,#2
+ ADD pLeft,pLeft,RowStep
+ ADD pRight,pRight,RowStep
+ BGT ExpandFrameLeftRightYloop
+
+
+ ;// Set return value
+
+ MOV result,#OMX_Sts_NoErr
+End
+
+ ;// Write function tail
+
+ M_END
+
+ ENDIF ;//ARM1136JS
+
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/api/armVCM4P10_CAVLCTables.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/api/armVCM4P10_CAVLCTables.h
new file mode 100644
index 0000000..4340f2a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/api/armVCM4P10_CAVLCTables.h
@@ -0,0 +1,30 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_CAVLCTables.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Header file for optimized H.264 CALVC tables
+ *
+ */
+
+#ifndef ARMVCM4P10_CAVLCTABLES_H
+#define ARMVCM4P10_CAVLCTABLES_H
+
+/* CAVLC tables */
+
+extern const OMX_U16 *armVCM4P10_CAVLCCoeffTokenTables[18];
+extern const OMX_U16 *armVCM4P10_CAVLCTotalZeroTables[15];
+extern const OMX_U16 *armVCM4P10_CAVLCTotalZeros2x2Tables[3];
+extern const OMX_U16 *armVCM4P10_CAVLCRunBeforeTables[15];
+extern const OMX_U8 armVCM4P10_ZigZag_4x4[16];
+extern const OMX_U8 armVCM4P10_ZigZag_2x2[4];
+extern const OMX_S8 armVCM4P10_SuffixToLevel[7];
+
+#endif
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
new file mode 100644
index 0000000..b2cd9d1
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
@@ -0,0 +1,222 @@
+;//
+;//
+;// File Name: armVCM4P10_Average_4x_Align_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+;// Functions:
+;// armVCM4P10_Average_4x4_Align<ALIGNMENT>_unsafe
+;//
+;// Implements Average of 4x4 with equation c = (a+b+1)>>1.
+;// First operand will be at offset ALIGNMENT from aligned address
+;// Second operand will be at aligned location and will be used as output.
+;// destination pointed by (pDst) for vertical interpolation.
+;// This function needs to copy 4 bytes in horizontal direction
+;//
+;// Registers used as input for this function
+;// r0,r1,r2,r3 where r2 containings aligned memory pointer and r3 step size
+;//
+;// Registers preserved for top level function
+;// r4,r5,r6,r8,r9,r14
+;//
+;// Registers modified by the function
+;// r7,r10,r11,r12
+;//
+;// Output registers
+;// r2 - pointer to the aligned location
+;// r3 - step size to this aligned location
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ EXPORT armVCM4P10_Average_4x4_Align0_unsafe
+ EXPORT armVCM4P10_Average_4x4_Align2_unsafe
+ EXPORT armVCM4P10_Average_4x4_Align3_unsafe
+
+DEBUG_ON SETL {FALSE}
+
+;// Declare input registers
+pPred0 RN 0
+iPredStep0 RN 1
+pPred1 RN 2
+iPredStep1 RN 3
+pDstPred RN 2
+iDstStep RN 3
+
+;// Declare other intermediate registers
+iPredA0 RN 10
+iPredA1 RN 11
+iPredB0 RN 12
+iPredB1 RN 14
+Temp1 RN 4
+Temp2 RN 5
+ResultA RN 5
+ResultB RN 4
+r0x80808080 RN 7
+
+ IF ARM1136JS
+
+ ;// This function calculates average of 4x4 block
+ ;// pPred0 is at alignment offset 0 and pPred1 is alignment 4
+
+ ;// Function header
+ M_START armVCM4P10_Average_4x4_Align0_unsafe, r6
+
+ ;// Code start
+ LDR r0x80808080, =0x80808080
+
+ ;// 1st load
+ M_LDR iPredB0, [pPred1]
+ M_LDR iPredA0, [pPred0], iPredStep0
+ M_LDR iPredB1, [pPred1, iPredStep1]
+ M_LDR iPredA1, [pPred0], iPredStep0
+
+ ;// (a+b+1)/2 = (a+256-(255-b))/2 = (a-(255-b))/2 + 128
+ MVN iPredB0, iPredB0
+ MVN iPredB1, iPredB1
+ UHSUB8 ResultA, iPredA0, iPredB0
+ UHSUB8 ResultB, iPredA1, iPredB1
+ EOR ResultA, ResultA, r0x80808080
+ M_STR ResultA, [pDstPred], iDstStep
+ EOR ResultB, ResultB, r0x80808080
+ M_STR ResultB, [pDstPred], iDstStep
+
+ ;// 2nd load
+ M_LDR iPredA0, [pPred0], iPredStep0
+ M_LDR iPredB0, [pPred1]
+ M_LDR iPredA1, [pPred0], iPredStep0
+ M_LDR iPredB1, [pPred1, iPredStep1]
+
+ MVN iPredB0, iPredB0
+ UHSUB8 ResultA, iPredA0, iPredB0
+ MVN iPredB1, iPredB1
+ UHSUB8 ResultB, iPredA1, iPredB1
+ EOR ResultA, ResultA, r0x80808080
+ M_STR ResultA, [pDstPred], iDstStep
+ EOR ResultB, ResultB, r0x80808080
+ M_STR ResultB, [pDstPred], iDstStep
+End0
+ M_END
+
+ ;// This function calculates average of 4x4 block
+ ;// pPred0 is at alignment offset 2 and pPred1 is alignment 4
+
+ ;// Function header
+ M_START armVCM4P10_Average_4x4_Align2_unsafe, r6
+
+ ;// Code start
+ LDR r0x80808080, =0x80808080
+
+ ;// 1st load
+ LDR Temp1, [pPred0, #4]
+ M_LDR iPredA0, [pPred0], iPredStep0
+ M_LDR iPredB0, [pPred1]
+ M_LDR iPredB1, [pPred1, iPredStep1]
+ M_LDR Temp2, [pPred0, #4]
+ M_LDR iPredA1, [pPred0], iPredStep0
+ MVN iPredB0, iPredB0
+ MVN iPredB1, iPredB1
+ MOV iPredA0, iPredA0, LSR #16
+ ORR iPredA0, iPredA0, Temp1, LSL #16
+ MOV iPredA1, iPredA1, LSR #16
+ ORR iPredA1, iPredA1, Temp2, LSL #16
+
+ ;// (a+b+1)/2 = (a+256-(255-b))/2 = (a-(255-b))/2 + 128
+ UHSUB8 ResultA, iPredA0, iPredB0
+ UHSUB8 ResultB, iPredA1, iPredB1
+ EOR ResultA, ResultA, r0x80808080
+ M_STR ResultA, [pDstPred], iDstStep
+ EOR ResultB, ResultB, r0x80808080
+ M_STR ResultB, [pDstPred], iDstStep
+
+ ;// 2nd load
+ LDR Temp1, [pPred0, #4]
+ M_LDR iPredA0, [pPred0], iPredStep0
+ LDR iPredB0, [pPred1]
+ LDR iPredB1, [pPred1, iPredStep1]
+ LDR Temp2, [pPred0, #4]
+ M_LDR iPredA1, [pPred0], iPredStep0
+ MVN iPredB0, iPredB0
+ MVN iPredB1, iPredB1
+ MOV iPredA0, iPredA0, LSR #16
+ ORR iPredA0, iPredA0, Temp1, LSL #16
+ MOV iPredA1, iPredA1, LSR #16
+ ORR iPredA1, iPredA1, Temp2, LSL #16
+
+ UHSUB8 ResultA, iPredA0, iPredB0
+ UHSUB8 ResultB, iPredA1, iPredB1
+ EOR ResultA, ResultA, r0x80808080
+ M_STR ResultA, [pDstPred], iDstStep
+ EOR ResultB, ResultB, r0x80808080
+ M_STR ResultB, [pDstPred], iDstStep
+End2
+ M_END
+
+
+ ;// This function calculates average of 4x4 block
+ ;// pPred0 is at alignment offset 3 and pPred1 is alignment 4
+
+ ;// Function header
+ M_START armVCM4P10_Average_4x4_Align3_unsafe, r6
+
+ ;// Code start
+ LDR r0x80808080, =0x80808080
+
+ ;// 1st load
+ LDR Temp1, [pPred0, #4]
+ M_LDR iPredA0, [pPred0], iPredStep0
+ LDR iPredB0, [pPred1]
+ LDR iPredB1, [pPred1, iPredStep1]
+ LDR Temp2, [pPred0, #4]
+ M_LDR iPredA1, [pPred0], iPredStep0
+
+ MVN iPredB0, iPredB0
+ MVN iPredB1, iPredB1
+ MOV iPredA0, iPredA0, LSR #24
+ ORR iPredA0, iPredA0, Temp1, LSL #8
+ MOV iPredA1, iPredA1, LSR #24
+ ORR iPredA1, iPredA1, Temp2, LSL #8
+ UHSUB8 ResultA, iPredA0, iPredB0
+ UHSUB8 ResultB, iPredA1, iPredB1
+ EOR ResultA, ResultA, r0x80808080
+ M_STR ResultA, [pDstPred], iDstStep
+ EOR ResultB, ResultB, r0x80808080
+ M_STR ResultB, [pDstPred], iDstStep
+
+ ;// 2nd load
+ LDR Temp1, [pPred0, #4]
+ M_LDR iPredA0, [pPred0], iPredStep0
+ LDR iPredB0, [pPred1]
+ LDR iPredB1, [pPred1, iPredStep1]
+ LDR Temp2, [pPred0, #4]
+ M_LDR iPredA1, [pPred0], iPredStep0
+
+ MVN iPredB0, iPredB0
+ MVN iPredB1, iPredB1
+ MOV iPredA0, iPredA0, LSR #24
+ ORR iPredA0, iPredA0, Temp1, LSL #8
+ MOV iPredA1, iPredA1, LSR #24
+ ORR iPredA1, iPredA1, Temp2, LSL #8
+
+ UHSUB8 ResultA, iPredA0, iPredB0
+ UHSUB8 ResultB, iPredA1, iPredB1
+ EOR ResultA, ResultA, r0x80808080
+ M_STR ResultA, [pDstPred], iDstStep
+ EOR ResultB, ResultB, r0x80808080
+ M_STR ResultB, [pDstPred], iDstStep
+End3
+ M_END
+
+ ENDIF
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_CAVLCTables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_CAVLCTables.c
new file mode 100644
index 0000000..17fe518
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_CAVLCTables.c
@@ -0,0 +1,327 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_CAVLCTables.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Optimized CAVLC tables for H.264
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armVCM4P10_CAVLCTables.h"
+
+/* 4x4 DeZigZag table */
+
+const OMX_U8 armVCM4P10_ZigZag_4x4[16] =
+{
+ 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
+};
+
+/* 2x2 DeZigZag table */
+
+const OMX_U8 armVCM4P10_ZigZag_2x2[4] =
+{
+ 0, 1, 2, 3
+};
+
+
+/*
+ * Suffix To Level table
+ * We increment the suffix length if
+ * ((LevelCode>>1)+1)>(3<<(SuffixLength-1)) && SuffixLength<6
+ * (LevelCode>>1)>=(3<<(SuffixLength-1)) && SuffixLength<6
+ * LevelCode >= 3<<SuffixLength && SuffixLength<6
+ * (LevelCode+2) >= (3<<SuffixLength)+2 && SuffixLength<6
+ */
+const OMX_S8 armVCM4P10_SuffixToLevel[7] =
+{
+ (3<<1)+2, /* SuffixLength=1 */
+ (3<<1)+2, /* SuffixLength=1 */
+ (3<<2)+2, /* SuffixLength=2 */
+ (3<<3)+2, /* SuffixLength=3 */
+ (3<<4)+2, /* SuffixLength=4 */
+ (3<<5)+2, /* SuffixLength=5 */
+ -1 /* SuffixLength=6 - never increment */
+};
+
+static const OMX_U16 armVCM4P10_CAVLCCoeffTokenTables_0[132] = {
+ 0x0020, 0x0100, 0x2015, 0x2015, 0x400b, 0x400b, 0x400b, 0x400b,
+ 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001,
+ 0x0028, 0x00f0, 0x00f8, 0x0027, 0x0030, 0x00d8, 0x00e0, 0x00e8,
+ 0x0038, 0x00a0, 0x00c8, 0x00d0, 0x0040, 0x0068, 0x0090, 0x0098,
+ 0x0048, 0x0050, 0x0058, 0x0060, 0x27ff, 0x27ff, 0x206b, 0x206b,
+ 0x0081, 0x0085, 0x0083, 0x0079, 0x0087, 0x007d, 0x007b, 0x0071,
+ 0x007f, 0x0075, 0x0073, 0x0069, 0x0070, 0x0078, 0x0080, 0x0088,
+ 0x2077, 0x2077, 0x206d, 0x206d, 0x2063, 0x2063, 0x2061, 0x2061,
+ 0x206f, 0x206f, 0x2065, 0x2065, 0x205b, 0x205b, 0x2059, 0x2059,
+ 0x0067, 0x005d, 0x0053, 0x0051, 0x005f, 0x0055, 0x004b, 0x0049,
+ 0x00a8, 0x00b0, 0x00b8, 0x00c0, 0x2041, 0x2041, 0x204d, 0x204d,
+ 0x2043, 0x2043, 0x2039, 0x2039, 0x2057, 0x2057, 0x2045, 0x2045,
+ 0x203b, 0x203b, 0x2031, 0x2031, 0x204f, 0x204f, 0x203d, 0x203d,
+ 0x2033, 0x2033, 0x2029, 0x2029, 0x0047, 0x0035, 0x002b, 0x0021,
+ 0x203f, 0x203f, 0x202d, 0x202d, 0x2023, 0x2023, 0x2019, 0x2019,
+ 0x0037, 0x0025, 0x001b, 0x0011, 0x202f, 0x202f, 0x201d, 0x201d,
+ 0x0013, 0x0009, 0x201f, 0x201f
+};
+
+static const OMX_U16 armVCM4P10_CAVLCCoeffTokenTables_1[128] = {
+ 0x0020, 0x00e8, 0x00f0, 0x00f8, 0x0027, 0x001f, 0x2015, 0x2015,
+ 0x400b, 0x400b, 0x400b, 0x400b, 0x4001, 0x4001, 0x4001, 0x4001,
+ 0x0028, 0x00d0, 0x00d8, 0x00e0, 0x0030, 0x0098, 0x00c0, 0x00c8,
+ 0x0038, 0x0060, 0x0088, 0x0090, 0x0040, 0x0048, 0x0050, 0x0058,
+ 0x27ff, 0x27ff, 0x207f, 0x207f, 0x0087, 0x0085, 0x0083, 0x0081,
+ 0x007b, 0x0079, 0x007d, 0x0073, 0x2075, 0x2075, 0x2071, 0x2071,
+ 0x0068, 0x0070, 0x0078, 0x0080, 0x2077, 0x2077, 0x206d, 0x206d,
+ 0x206b, 0x206b, 0x2069, 0x2069, 0x206f, 0x206f, 0x2065, 0x2065,
+ 0x2063, 0x2063, 0x2061, 0x2061, 0x0059, 0x005d, 0x005b, 0x0051,
+ 0x0067, 0x0055, 0x0053, 0x0049, 0x00a0, 0x00a8, 0x00b0, 0x00b8,
+ 0x205f, 0x205f, 0x204d, 0x204d, 0x204b, 0x204b, 0x2041, 0x2041,
+ 0x2057, 0x2057, 0x2045, 0x2045, 0x2043, 0x2043, 0x2039, 0x2039,
+ 0x204f, 0x204f, 0x203d, 0x203d, 0x203b, 0x203b, 0x2031, 0x2031,
+ 0x0029, 0x0035, 0x0033, 0x0021, 0x2047, 0x2047, 0x202d, 0x202d,
+ 0x202b, 0x202b, 0x2019, 0x2019, 0x003f, 0x0025, 0x0023, 0x0011,
+ 0x0037, 0x001d, 0x001b, 0x0009, 0x202f, 0x202f, 0x2013, 0x2013
+};
+
+static const OMX_U16 armVCM4P10_CAVLCCoeffTokenTables_2[112] = {
+ 0x0020, 0x0088, 0x00b0, 0x00b8, 0x00c0, 0x00c8, 0x00d0, 0x00d8,
+ 0x003f, 0x0037, 0x002f, 0x0027, 0x001f, 0x0015, 0x000b, 0x0001,
+ 0x0028, 0x0050, 0x0078, 0x0080, 0x0030, 0x0038, 0x0040, 0x0048,
+ 0x07ff, 0x0081, 0x0087, 0x0085, 0x0083, 0x0079, 0x007f, 0x007d,
+ 0x007b, 0x0071, 0x0077, 0x0075, 0x0073, 0x0069, 0x206b, 0x206b,
+ 0x0058, 0x0060, 0x0068, 0x0070, 0x2061, 0x2061, 0x206d, 0x206d,
+ 0x2063, 0x2063, 0x2059, 0x2059, 0x206f, 0x206f, 0x2065, 0x2065,
+ 0x205b, 0x205b, 0x2051, 0x2051, 0x0067, 0x005d, 0x0053, 0x0049,
+ 0x005f, 0x0055, 0x004b, 0x0041, 0x0090, 0x0098, 0x00a0, 0x00a8,
+ 0x2039, 0x2039, 0x2031, 0x2031, 0x204d, 0x204d, 0x2029, 0x2029,
+ 0x2057, 0x2057, 0x2045, 0x2045, 0x2043, 0x2043, 0x2021, 0x2021,
+ 0x0019, 0x003d, 0x003b, 0x0011, 0x004f, 0x0035, 0x0033, 0x0009,
+ 0x202b, 0x202b, 0x202d, 0x202d, 0x2023, 0x2023, 0x2025, 0x2025,
+ 0x201b, 0x201b, 0x2047, 0x2047, 0x201d, 0x201d, 0x2013, 0x2013
+};
+
+static const OMX_U16 armVCM4P10_CAVLCCoeffTokenTables_3[80] = {
+ 0x0020, 0x0028, 0x0030, 0x0038, 0x0040, 0x0048, 0x0050, 0x0058,
+ 0x0060, 0x0068, 0x0070, 0x0078, 0x0080, 0x0088, 0x0090, 0x0098,
+ 0x0009, 0x000b, 0x07ff, 0x0001, 0x0011, 0x0013, 0x0015, 0x07ff,
+ 0x0019, 0x001b, 0x001d, 0x001f, 0x0021, 0x0023, 0x0025, 0x0027,
+ 0x0029, 0x002b, 0x002d, 0x002f, 0x0031, 0x0033, 0x0035, 0x0037,
+ 0x0039, 0x003b, 0x003d, 0x003f, 0x0041, 0x0043, 0x0045, 0x0047,
+ 0x0049, 0x004b, 0x004d, 0x004f, 0x0051, 0x0053, 0x0055, 0x0057,
+ 0x0059, 0x005b, 0x005d, 0x005f, 0x0061, 0x0063, 0x0065, 0x0067,
+ 0x0069, 0x006b, 0x006d, 0x006f, 0x0071, 0x0073, 0x0075, 0x0077,
+ 0x0079, 0x007b, 0x007d, 0x007f, 0x0081, 0x0083, 0x0085, 0x0087
+};
+
+static const OMX_U16 armVCM4P10_CAVLCCoeffTokenTables_4[32] = {
+ 0x0020, 0x0038, 0x2015, 0x2015, 0x4001, 0x4001, 0x4001, 0x4001,
+ 0x600b, 0x600b, 0x600b, 0x600b, 0x600b, 0x600b, 0x600b, 0x600b,
+ 0x0028, 0x0030, 0x0021, 0x0019, 0x2027, 0x2027, 0x0025, 0x0023,
+ 0x201d, 0x201d, 0x201b, 0x201b, 0x0011, 0x001f, 0x0013, 0x0009
+};
+
+const OMX_U16 * armVCM4P10_CAVLCCoeffTokenTables[18] = {
+ armVCM4P10_CAVLCCoeffTokenTables_0, /* nC=0 */
+ armVCM4P10_CAVLCCoeffTokenTables_0, /* nC=1 */
+ armVCM4P10_CAVLCCoeffTokenTables_1, /* nC=2 */
+ armVCM4P10_CAVLCCoeffTokenTables_1, /* nC=3 */
+ armVCM4P10_CAVLCCoeffTokenTables_2, /* nC=4 */
+ armVCM4P10_CAVLCCoeffTokenTables_2, /* nC=5 */
+ armVCM4P10_CAVLCCoeffTokenTables_2, /* nC=6 */
+ armVCM4P10_CAVLCCoeffTokenTables_2, /* nC=7 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=8 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=9 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=10 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=11 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=12 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=13 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=14 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=15 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=16 */
+ armVCM4P10_CAVLCCoeffTokenTables_4 /* nC=-1 */
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_0[40] = {
+ 0x0020, 0x0048, 0x0009, 0x0007, 0x2005, 0x2005, 0x2003, 0x2003,
+ 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001,
+ 0x0028, 0x0040, 0x0011, 0x000f, 0x0030, 0x0038, 0x0019, 0x0017,
+ 0x27ff, 0x27ff, 0x201f, 0x201f, 0x201d, 0x201d, 0x201b, 0x201b,
+ 0x2015, 0x2015, 0x2013, 0x2013, 0x200d, 0x200d, 0x200b, 0x200b
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_1[24] = {
+ 0x0020, 0x0028, 0x0011, 0x000f, 0x000d, 0x000b, 0x2009, 0x2009,
+ 0x2007, 0x2007, 0x2005, 0x2005, 0x2003, 0x2003, 0x2001, 0x2001,
+ 0x001d, 0x001b, 0x0019, 0x0017, 0x2015, 0x2015, 0x2013, 0x2013
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_2[24] = {
+ 0x0020, 0x0028, 0x0011, 0x000b, 0x0009, 0x0001, 0x200f, 0x200f,
+ 0x200d, 0x200d, 0x2007, 0x2007, 0x2005, 0x2005, 0x2003, 0x2003,
+ 0x001b, 0x0017, 0x2019, 0x2019, 0x2015, 0x2015, 0x2013, 0x2013
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_3[24] = {
+ 0x0020, 0x0028, 0x0013, 0x000f, 0x0007, 0x0005, 0x2011, 0x2011,
+ 0x200d, 0x200d, 0x200b, 0x200b, 0x2009, 0x2009, 0x2003, 0x2003,
+ 0x2019, 0x2019, 0x2017, 0x2017, 0x2015, 0x2015, 0x2001, 0x2001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_4[20] = {
+ 0x0020, 0x0015, 0x0011, 0x0005, 0x0003, 0x0001, 0x200f, 0x200f,
+ 0x200d, 0x200d, 0x200b, 0x200b, 0x2009, 0x2009, 0x2007, 0x2007,
+ 0x2017, 0x2017, 0x2013, 0x2013
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_5[20] = {
+ 0x0020, 0x0011, 0x2013, 0x2013, 0x200f, 0x200f, 0x200d, 0x200d,
+ 0x200b, 0x200b, 0x2009, 0x2009, 0x2007, 0x2007, 0x2005, 0x2005,
+ 0x0015, 0x0001, 0x2003, 0x2003
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_6[20] = {
+ 0x0020, 0x000f, 0x2011, 0x2011, 0x200d, 0x200d, 0x2009, 0x2009,
+ 0x2007, 0x2007, 0x2005, 0x2005, 0x400b, 0x400b, 0x400b, 0x400b,
+ 0x0013, 0x0001, 0x2003, 0x2003
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_7[20] = {
+ 0x0020, 0x0003, 0x200f, 0x200f, 0x200d, 0x200d, 0x2007, 0x2007,
+ 0x400b, 0x400b, 0x400b, 0x400b, 0x4009, 0x4009, 0x4009, 0x4009,
+ 0x0011, 0x0001, 0x2005, 0x2005
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_8[20] = {
+ 0x0020, 0x0005, 0x200b, 0x200b, 0x400d, 0x400d, 0x400d, 0x400d,
+ 0x4009, 0x4009, 0x4009, 0x4009, 0x4007, 0x4007, 0x4007, 0x4007,
+ 0x0003, 0x0001, 0x200f, 0x200f
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_9[20] = {
+ 0x0020, 0x000d, 0x2005, 0x2005, 0x400b, 0x400b, 0x400b, 0x400b,
+ 0x4009, 0x4009, 0x4009, 0x4009, 0x4007, 0x4007, 0x4007, 0x4007,
+ 0x2003, 0x2003, 0x2001, 0x2001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_10[16] = {
+ 0x0001, 0x0003, 0x2005, 0x2005, 0x2007, 0x2007, 0x200b, 0x200b,
+ 0x6009, 0x6009, 0x6009, 0x6009, 0x6009, 0x6009, 0x6009, 0x6009
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_11[16] = {
+ 0x0001, 0x0003, 0x2009, 0x2009, 0x4005, 0x4005, 0x4005, 0x4005,
+ 0x6007, 0x6007, 0x6007, 0x6007, 0x6007, 0x6007, 0x6007, 0x6007
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_12[16] = {
+ 0x2001, 0x2001, 0x2003, 0x2003, 0x4007, 0x4007, 0x4007, 0x4007,
+ 0x6005, 0x6005, 0x6005, 0x6005, 0x6005, 0x6005, 0x6005, 0x6005
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_13[16] = {
+ 0x4001, 0x4001, 0x4001, 0x4001, 0x4003, 0x4003, 0x4003, 0x4003,
+ 0x6005, 0x6005, 0x6005, 0x6005, 0x6005, 0x6005, 0x6005, 0x6005
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_14[16] = {
+ 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001,
+ 0x6003, 0x6003, 0x6003, 0x6003, 0x6003, 0x6003, 0x6003, 0x6003
+};
+
+const OMX_U16 * armVCM4P10_CAVLCTotalZeroTables[15] = {
+ armVCM4P10_CAVLCTotalZeroTables_0,
+ armVCM4P10_CAVLCTotalZeroTables_1,
+ armVCM4P10_CAVLCTotalZeroTables_2,
+ armVCM4P10_CAVLCTotalZeroTables_3,
+ armVCM4P10_CAVLCTotalZeroTables_4,
+ armVCM4P10_CAVLCTotalZeroTables_5,
+ armVCM4P10_CAVLCTotalZeroTables_6,
+ armVCM4P10_CAVLCTotalZeroTables_7,
+ armVCM4P10_CAVLCTotalZeroTables_8,
+ armVCM4P10_CAVLCTotalZeroTables_9,
+ armVCM4P10_CAVLCTotalZeroTables_10,
+ armVCM4P10_CAVLCTotalZeroTables_11,
+ armVCM4P10_CAVLCTotalZeroTables_12,
+ armVCM4P10_CAVLCTotalZeroTables_13,
+ armVCM4P10_CAVLCTotalZeroTables_14
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeros2x2Tables_0[16] = {
+ 0x2007, 0x2007, 0x2005, 0x2005, 0x4003, 0x4003, 0x4003, 0x4003,
+ 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeros2x2Tables_1[16] = {
+ 0x4005, 0x4005, 0x4005, 0x4005, 0x4003, 0x4003, 0x4003, 0x4003,
+ 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeros2x2Tables_2[16] = {
+ 0x6003, 0x6003, 0x6003, 0x6003, 0x6003, 0x6003, 0x6003, 0x6003,
+ 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001
+};
+
+const OMX_U16 * armVCM4P10_CAVLCTotalZeros2x2Tables[3] = {
+ armVCM4P10_CAVLCTotalZeros2x2Tables_0,
+ armVCM4P10_CAVLCTotalZeros2x2Tables_1,
+ armVCM4P10_CAVLCTotalZeros2x2Tables_2
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_0[8] = {
+ 0x4003, 0x4003, 0x4003, 0x4003, 0x4001, 0x4001, 0x4001, 0x4001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_1[8] = {
+ 0x2005, 0x2005, 0x2003, 0x2003, 0x4001, 0x4001, 0x4001, 0x4001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_2[8] = {
+ 0x2007, 0x2007, 0x2005, 0x2005, 0x2003, 0x2003, 0x2001, 0x2001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_3[8] = {
+ 0x0009, 0x0007, 0x2005, 0x2005, 0x2003, 0x2003, 0x2001, 0x2001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_4[8] = {
+ 0x000b, 0x0009, 0x0007, 0x0005, 0x2003, 0x2003, 0x2001, 0x2001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_5[8] = {
+ 0x0003, 0x0005, 0x0009, 0x0007, 0x000d, 0x000b, 0x2001, 0x2001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_6[24] = {
+ 0x0010, 0x000d, 0x000b, 0x0009, 0x0007, 0x0005, 0x0003, 0x0001,
+ 0x0018, 0x0011, 0x200f, 0x200f, 0x0020, 0x0015, 0x2013, 0x2013,
+ 0x0028, 0x0019, 0x2017, 0x2017, 0x07ff, 0x001d, 0x201b, 0x201b
+};
+
+/* Tables 7 to 14 are duplicates of table 6 */
+
+const OMX_U16 * armVCM4P10_CAVLCRunBeforeTables[15] = {
+ armVCM4P10_CAVLCRunBeforeTables_0, /* ZerosLeft=1 */
+ armVCM4P10_CAVLCRunBeforeTables_1,
+ armVCM4P10_CAVLCRunBeforeTables_2,
+ armVCM4P10_CAVLCRunBeforeTables_3,
+ armVCM4P10_CAVLCRunBeforeTables_4,
+ armVCM4P10_CAVLCRunBeforeTables_5, /* ZerosLeft=6 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=7 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=8 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=9 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=10 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=11 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=12 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=13 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=14 */
+ armVCM4P10_CAVLCRunBeforeTables_6 /* ZerosLeft=15 */
+};
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
new file mode 100644
index 0000000..dcbcd00
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
@@ -0,0 +1,20 @@
+;//
+;//
+;// File Name: armVCM4P10_DeblockingChroma_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
new file mode 100644
index 0000000..14b37fe
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
@@ -0,0 +1,366 @@
+;//
+;//
+;// File Name: armVCM4P10_DeblockingLuma_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+
+
+ IF ARM1136JS
+
+MASK_1 EQU 0x01010101
+
+;// Declare input registers
+
+pQ0 RN 0
+StepArg RN 1
+tC0Arg RN 2
+alpha RN 6
+
+beta RN 14
+bS RN 14
+tC0 RN 14
+ptC0 RN 1
+
+;// Declare Local/Temporary variables
+
+;// Pixels
+p_0 RN 3
+p_1 RN 5
+p_2 RN 4
+p_3 RN 2
+q_0 RN 8
+q_1 RN 9
+q_2 RN 10
+q_3 RN 12
+
+
+;// Filtering
+
+ap0q0 RN 1
+filt RN 2
+
+m00 RN 7
+m01 RN 11
+
+apflg RN 0
+aqflg RN 6
+
+tC RN 1
+
+
+;//Declarations for bSLT4 kernel
+
+pos RN 7
+neg RN 12
+
+P0a RN 1
+P1a RN 8
+Q0a RN 7
+Q1a RN 4
+
+u1 RN 3
+max RN 12
+min RN 2
+
+
+
+;//Declarations for bSGE4 kernel
+
+q_3b RN 9
+p_3b RN 0
+apqflg RN 12
+
+P0b RN 6
+P1b RN 7
+P2b RN 1
+
+Q0b RN 9
+Q1b RN 0
+Q2b RN 2
+
+;// Miscellanous
+
+a RN 0
+t0 RN 3
+t1 RN 12
+t2 RN 7
+t3 RN 11
+t4 RN 4
+t5 RN 1
+t8 RN 6
+t9 RN 14
+t10 RN 5
+t11 RN 9
+
+;// Register usage for - armVCM4P10_DeblockingLumabSLT4_unsafe()
+;//
+;// Inputs - 3,4,5,8,9,10 - Input Pixels (p0-p2,q0-q2)
+;// - 2 - filt, 0 - apflg, 6 - aqflg
+;// - 11 - m01, 7 - tC0
+;//
+;// Outputs - 1,8,7,11 - Output Pixels(P0a,P1a,Q0a,Q1a)
+;//
+;// Registers Corrupted - 0-3,5-12,14
+
+
+ M_START armVCM4P10_DeblockingLumabSLT4_unsafe, lr
+
+ ;// Since beta <= 18 and alpha <= 255 we know
+ ;// -254 <= p0-q0 <= 254
+ ;// -17 <= q1-q0 <= 17
+ ;// -17 <= p1-p0 <= 17
+
+ ;// delta = Clip3( -tC, tC, ((((q0-p0)<<2) + (p1-q1) + 4)>>3))
+ ;//
+ ;// Calculate A = (((q0-p0)<<2) + (p1-q1) + 4)>>3
+ ;// = (4*q0 - 4*p0 + p1 - q1 + 4)>>3
+ ;// = ((p1-p0) - (q1-q0) - 3*(p0-q0) + 4)>>3
+
+ USUB8 t1, p_1, p_0
+ MUL tC0, t2, m01
+
+ USUB8 t2, q_1, q_0
+ SSUB8 t1, t1, t2
+
+ USUB8 t2, p_0, q_0
+ AND t2, t2, m01
+ SHSUB8 t1, t1, t2
+ UHSUB8 t5, p_0, q_0
+ SSUB8 t1, t1, t2
+ SHSUB8 t1, t1, t5
+ MOV m00, #0
+ SADD8 t1, t1, m01
+ SHSUB8 t1, t1, t5
+
+ ;// tC = tC0
+ ;// if (ap < beta) tC++;
+ ;// if (aq < beta) tC++;
+ USUB8 t5, filt, m01
+ SEL tC0, tC0, m00
+ UQADD8 tC, tC0, apflg
+ SSUB8 t1, t1, m00
+ UQADD8 tC, tC, aqflg
+
+ ;// Split into positive and negative part and clip
+ SEL pos, t1, m00
+ USUB8 neg, pos, t1
+ USUB8 t3, pos, tC
+ SEL pos, tC, pos
+ USUB8 t3, neg, tC
+ SEL neg, tC, neg
+
+ ;//Reload m01
+ LDR m01,=MASK_1
+
+ UQADD8 P0a, p_0, pos
+ UQSUB8 Q0a, q_0, pos
+ UQSUB8 P0a, P0a, neg
+ UQADD8 Q0a, Q0a, neg
+
+ ;// Choose to store the filtered
+ ;// value or the original pixel
+ USUB8 t1, filt, m01
+ SEL P0a, P0a, p_0
+ SEL Q0a, Q0a, q_0
+
+ ;// delta = (p2 + ((p0+q0+1)>>1) - (p1<<1))>>1;
+ ;// u1 = (p0 + q0 + 1)>>1
+ ;// u1 = ( (q_0 - p_0')>>1 ) ^ 0x80
+ MVN p_0, p_0
+ UHSUB8 u1, q_0, p_0
+ UQADD8 max, p_1, tC0
+ EOR u1, u1, m01 ,LSL #7
+
+ ;// Calculate A = (p2+u1)>>1
+ ;// Then delta = Clip3( -tC0, tC0, A - p1)
+
+ ;// Clip P1
+ UHADD8 P1a, p_2, u1
+ UQSUB8 min, p_1, tC0
+ USUB8 t4, P1a, max
+ SEL P1a, max, P1a
+ USUB8 t4, P1a, min
+ SEL P1a, P1a, min
+
+ ;// Clip Q1
+ UHADD8 Q1a, q_2, u1
+ UQADD8 max, q_1, tC0
+ UQSUB8 min, q_1, tC0
+ USUB8 t0, Q1a, max
+ SEL Q1a, max, Q1a
+ USUB8 t0, Q1a, min
+ SEL Q1a, Q1a, min
+
+ ;// Choose to store the filtered
+ ;// value or the original pixel
+ USUB8 t0, apflg, m01
+ SEL P1a, P1a, p_1
+ USUB8 t0, aqflg, m01
+ SEL t3, Q1a, q_1
+
+ M_END
+
+;// Register usage for - armVCM4P10_DeblockingLumabSGE4_unsafe()
+;//
+;// Inputs - 3,4,5,8,9,10 - Input Pixels (p0-p2,q0-q2)
+;// - 2 - filt, 0 - apflg,aqflg
+;// - 1 - ap0q0, 6 - alpha
+;// - 7 - m00, 11 - m01
+;//
+;// Outputs - 6,7,1,9,0,2 - Output Pixels(P0b,P1b,P2b, Q0b,Q1b,Q2b)
+;//
+;// Registers Corrupted - 0-3,5-12,14
+
+ M_START armVCM4P10_DeblockingLumabSGE4_unsafe, lr
+
+ ;// apflg = apflg && |p0-q0|<((alpha>>2)+2)
+ ;// apflg = aqflg && |p0-q0|<((alpha>>2)+2)
+
+ M_ARG pDummy,4
+ M_ARG pQ_3,4
+ M_ARG pP_3,4
+
+ UHADD8 alpha, alpha, m00
+ USUB8 t9, p_2, p_0 ;//t9 = dp2p0
+ UHADD8 alpha, alpha, m00
+ ADD alpha, alpha, m01, LSL #1
+ USUB8 ap0q0, ap0q0, alpha
+ SEL apqflg, m00, apflg
+
+ ;// P0 = (p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4)>>3
+ ;// = ((p2-p0) + 2*(p1-p0) + (q1-q0) + 3*(q0-p0) + 8*p0 + 4)>>3
+ ;// = p0 + (((p2-p0) + 2*(p1-p0) + (q1-q0) - 3*(p0-q0) + 4)>>3)
+
+ ;// P1 = (p2 + p1 + q0 + p0 + 2)>>2
+ ;// = p0 + (((p2-p0) + (p1-p0) - (p0-q0) + 2)>>2)
+
+ ;// P2 = (2*p3 + 3*p2 + p1 + p0 + q0 + 4)>>3
+ ;// = (2*(p3-p0) + 3*(p2-p0) + (p1-p0) - (p0-q0) + 8*p0 + 4)>>3
+ ;// = p0 + (((p3-p0) + (p2-p0) + t2 + 2)>>2)
+
+ ;// Compute P0b
+ USUB8 t2, p_0, q_0
+ SSUB8 t5, t9, t2
+
+ USUB8 t8, q_1, q_0
+ SHADD8 t8, t5, t8
+
+ USUB8 t9, p_1, p_0
+ SADD8 t8, t8, t9
+ SHSUB8 t8, t8, t2
+ SHADD8 t5, t5, t9
+ SHADD8 t8, t8, m01
+ SHADD8 t9, t5, m01
+ SADD8 P0b, p_0, t8
+ ;// P0b ready
+
+ ;// Compute P1b
+ M_LDR p_3b, pP_3
+ SADD8 P1b, p_0, t9
+ ;// P1b ready
+
+ ;// Compute P2b
+ USUB8 t9, p_2, p_0
+ SADD8 t5, t5, t9
+ UHSUB8 t9, p_3b, p_0
+ EOR a, p_3b, p_0
+ AND a, a, m01
+ SHADD8 t5, t5, a
+ UHADD8 a, p_0, q_1
+ SADD8 t5, t5, m01
+ SHADD8 t5, t5, t9
+ MVN t9, p_1
+ SADD8 P2b, p_0, t5
+ ;// P2b ready
+
+ UHSUB8 a, a, t9
+ ORR t9, apqflg, m01
+ USUB8 t9, apqflg, t9
+
+ EOR a, a, m01, LSL #7
+ SEL P0b, P0b, a
+ SEL P1b, P1b, p_1
+ SEL P2b, P2b, p_2
+
+ USUB8 t4, filt, m01
+ SEL P0b, P0b, p_0
+
+
+ ;// Q0 = (q2 + 2*q1 + 2*q0 + 2*p0 + p1 + 4)>>3
+ ;// = ((q2-q0) + 2*(q1-q0) + (p1-p0) + 3*(p0-q0) + 8*q0 + 4)>>3
+ ;// = q0 + (((q2-q0) + 2*(q1-q0) + (p1-p0) + 3*(p0-q0) + 4)>>3)
+
+ ;// Q1 = (q2 + q1 + p0 + q0 + 2)>>2
+ ;// = q0 + (((q2-q0) + (q1-q0) + (p0-q0) + 2)>>2)
+
+ ;// Q2 = (2*q3 + 3*q2 + q1 + q0 + p0 + 4)>>3
+ ;// = (2*(q3-q0) + 3*(q2-q0) + (q1-q0) + (p0-q0) + 8*q0 + 4)>>3
+ ;// = q0 + (((q3-q0) + (q2-q0) + t2 + 2)>>2)
+
+
+ ;// Compute Q0b Q1b
+ USUB8 t4, q_2, q_0
+ USUB8 a, p_0, q_0
+ USUB8 t9, p_1, p_0
+ SADD8 t0, t4, a
+ SHADD8 t9, t0, t9
+ UHADD8 t10, q_0, p_1
+ SADD8 t9, t9, a
+ USUB8 a, q_1, q_0
+ SHADD8 t9, t9, a
+ SHADD8 t0, t0, a
+ SHADD8 t9, t9, m01
+ SHADD8 a, t0, m01
+ SADD8 t9, q_0, t9
+ ;// Q0b ready - t9
+
+ MOV t4, #0
+ UHADD8 apqflg, apqflg, t4
+
+ SADD8 Q1b, q_0, a
+ ;// Q1b ready
+
+ USUB8 t4, apqflg, m01
+ SEL Q1b, Q1b, q_1
+ MVN t11, q_1
+ UHSUB8 t10, t10, t11
+ M_LDR q_3b, pQ_3
+ EOR t10, t10, m01, LSL #7
+ SEL t9, t9, t10
+
+ ;// Compute Q2b
+ USUB8 t4, q_2, q_0
+ SADD8 t4, t0, t4
+ EOR t0, q_3b, q_0
+ AND t0, t0, m01
+ SHADD8 t4, t4, t0
+ UHSUB8 t10, q_3b, q_0
+ SADD8 t4, t4, m01
+ SHADD8 t4, t4, t10
+
+ USUB8 t10, filt, m01
+ SEL Q0b, t9, q_0
+
+ SADD8 t4, q_0, t4
+ ;// Q2b ready - t4
+
+ USUB8 t10, apqflg, m01
+ SEL Q2b, t4, q_2
+
+ M_END
+
+ ENDIF
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
new file mode 100644
index 0000000..ac448a0
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
@@ -0,0 +1,325 @@
+;//
+;//
+;// File Name: armVCM4P10_DecodeCoeffsToPair_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armCOMM_BitDec_s.h
+
+ IMPORT armVCM4P10_CAVLCCoeffTokenTables
+ IMPORT armVCM4P10_CAVLCTotalZeroTables
+ IMPORT armVCM4P10_CAVLCTotalZeros2x2Tables
+ IMPORT armVCM4P10_CAVLCRunBeforeTables
+ IMPORT armVCM4P10_SuffixToLevel
+ IMPORT armVCM4P10_ZigZag_4x4
+ IMPORT armVCM4P10_ZigZag_2x2
+
+ M_VARIANTS ARM1136JS
+
+;//DEBUG_ON SETL {TRUE}
+
+LAST_COEFF EQU 0x20 ;// End of block flag
+TWO_BYTE_COEFF EQU 0x10
+
+;// Declare input registers
+
+ppBitStream RN 0
+pOffset RN 1
+pNumCoeff RN 2
+ppPosCoefbuf RN 3
+nC RN 4 ;// number of coeffs or 17 for chroma
+sMaxNumCoeff RN 5
+
+;// Declare inner loop registers
+
+;// Level loop
+Count RN 0
+TrailingOnes RN 1
+pLevel RN 2
+LevelSuffix RN 3
+SuffixLength RN 4
+TotalCoeff RN 5
+
+pVLDTable RN 6
+Symbol RN 7
+T1 RN 8
+T2 RN 9
+RBitStream RN 10
+RBitBuffer RN 11
+RBitCount RN 12
+lr RN 14
+
+;// Run loop
+Count RN 0
+ZerosLeft RN 1
+pLevel RN 2
+ppRunTable RN 3
+pRun RN 4
+TotalCoeff RN 5
+
+pVLDTable RN 6
+Symbol RN 7
+T1 RN 8
+T2 RN 9
+RBitStream RN 10
+RBitBuffer RN 11
+RBitCount RN 12
+lr RN 14
+
+;// Fill in coefficients loop
+pPosCoefbuf RN 0
+temp RN 1
+pLevel RN 2
+ppPosCoefbuf RN 3
+pRun RN 4
+TotalCoeff RN 5
+pZigZag RN 6
+
+T1 RN 8
+T2 RN 9
+RBitStream RN 10
+RBitBuffer RN 11
+RBitCount RN 12
+CoeffNum RN 14
+
+
+
+ IF ARM1136JS
+
+ ;// Allocate stack memory required by the function
+ M_ALLOC4 pppBitStream, 4
+ M_ALLOC4 ppOffset, 4
+ M_ALLOC4 pppPosCoefbuf, 4
+ M_ALLOC4 ppLevel, 16*2
+ M_ALLOC4 ppRun, 16
+
+ ;// Write function header
+ M_START armVCM4P10_DecodeCoeffsToPair, r11
+
+ ;// Define stack arguments
+ M_ARG pNC, 4
+ M_ARG pSMaxNumCoeff,4
+
+ ;// Code start
+ M_BD_INIT0 ppBitStream, pOffset, RBitStream, RBitBuffer, RBitCount
+ LDR pVLDTable, =armVCM4P10_CAVLCCoeffTokenTables
+ M_LDR nC, pNC
+
+ M_BD_INIT1 T1, T2, lr
+ LDR pVLDTable, [pVLDTable, nC, LSL #2] ;// Find VLD table
+
+ M_BD_INIT2 T1, T2, lr
+
+ ;// Decode Symbol = TotalCoeff*4 + TrailingOnes
+ M_BD_VLD Symbol, T1, T2, pVLDTable, 4, 2
+
+ MOVS TotalCoeff, Symbol, LSR #2
+ STRB TotalCoeff, [pNumCoeff]
+ M_PRINTF "TotalCoeff=%d\n", TotalCoeff
+ BEQ.W EndNoError ;// Finished if no coefficients
+
+ CMP Symbol, #17*4
+ BGE.W EndBadSymbol ;// Error if bad symbol
+
+ ;// Save bitstream pointers
+ M_STR ppBitStream, pppBitStream
+ M_STR pOffset, ppOffset
+ M_STR ppPosCoefbuf, pppPosCoefbuf
+
+ ;// Decode Trailing Ones
+ ANDS TrailingOnes, Symbol, #3
+ M_ADR pLevel, ppLevel
+ M_PRINTF "TrailingOnes=%d\n", TrailingOnes
+ BEQ TrailingOnesDone
+ MOV Count, TrailingOnes
+TrailingOnesLoop
+ M_BD_READ8 Symbol, 1, T1
+ SUBS Count, Count, #1
+ MOV T1, #1
+ SUB T1, T1, Symbol, LSL #1
+ M_PRINTF "Level=%d\n", T1
+ STRH T1, [pLevel], #2
+ BGT TrailingOnesLoop
+TrailingOnesDone
+
+ ;// Decode level values
+ SUBS Count, TotalCoeff, TrailingOnes ;// Number of levels to read
+ BEQ DecodeRuns ;// None left
+
+ MOV SuffixLength, #1
+ CMP TotalCoeff, #10
+ MOVLE SuffixLength, #0
+ CMP TrailingOnes, #3 ;// if (TrailingOnes<3)
+ MOVLT TrailingOnes, #4 ;// then TrailingOnes = +4
+ MOVGE TrailingOnes, #2 ;// else TrailingOnes = +2
+ MOVGE SuffixLength, #0 ;// SuffixLength = 0
+
+LevelLoop
+ M_BD_CLZ16 Symbol, T1, T2 ;// Symbol=LevelPrefix
+ CMP Symbol,#16
+ BGE EndBadSymbol
+
+ MOVS lr, SuffixLength ;// if LevelSuffixSize==0
+ TEQEQ Symbol, #14 ;// and LevelPrefix==14
+ MOVEQ lr, #4 ;// then LevelSuffixSize=4
+ TEQ Symbol, #15 ;// if LevelSuffixSize==15
+ MOVEQ lr, #12 ;// then LevelSuffixSize=12
+
+ TEQEQ SuffixLength,#0
+ ADDEQ Symbol,Symbol,#15
+
+ TEQ lr, #0 ;// if LevelSuffixSize==0
+ BEQ LevelCodeRead ;// LevelCode = LevelPrefix
+
+ M_BD_VREAD16 LevelSuffix, lr, T1, T2 ;// Read Level Suffix
+
+ MOV Symbol, Symbol, LSL SuffixLength
+ ADD Symbol, LevelSuffix, Symbol
+
+LevelCodeRead
+ ;// Symbol = LevelCode
+ ADD Symbol, Symbol, TrailingOnes ;// +4 if level cannot be +/-1, +2 o/w
+ MOV TrailingOnes, #2
+ MOVS T1, Symbol, LSR #1
+ RSBCS T1, T1, #0 ;// If Symbol odd then negate
+ M_PRINTF "Level=%d\n", T1
+ STRH T1, [pLevel], #2 ;// Store level.
+
+ LDR T2, =armVCM4P10_SuffixToLevel
+ LDRSB T1, [T2, SuffixLength] ;// Find increment level
+ TEQ SuffixLength, #0
+ MOVEQ SuffixLength, #1
+ CMP Symbol, T1
+ ADDCS SuffixLength, SuffixLength, #1
+ SUBS Count, Count, #1
+ BGT LevelLoop
+
+DecodeRuns
+ ;// Find number of zeros
+ M_LDR T1, pSMaxNumCoeff ;// sMaxNumCoeff
+ SUB Count, TotalCoeff, #1 ;// Number of runs excluding last
+ SUBS ZerosLeft, T1, TotalCoeff ;// Maximum number of zeros there could be
+ M_ADR pRun, ppRun
+ MOV CoeffNum,TotalCoeff
+ SUB CoeffNum,CoeffNum,#1
+ BEQ NoZerosLeft
+
+ ;// Unpack number of zeros from bitstream
+ TEQ T1, #4
+ LDREQ pVLDTable, =(armVCM4P10_CAVLCTotalZeros2x2Tables-4)
+ LDRNE pVLDTable, =(armVCM4P10_CAVLCTotalZeroTables-4)
+ LDR pVLDTable, [pVLDTable, TotalCoeff, LSL #2]
+
+ M_BD_VLD Symbol, T1, T2, pVLDTable, 4, 2 ;// Symbol = ZerosLeft
+ CMP Symbol,#16
+ BGE EndBadSymbol
+
+ LDR ppRunTable, =(armVCM4P10_CAVLCRunBeforeTables-4)
+ M_ADR pRun, ppRun
+ MOVS ZerosLeft, Symbol
+
+ ADD CoeffNum,CoeffNum,ZerosLeft
+
+ BEQ NoZerosLeft
+
+ ;// Decode runs while zeros are left and more than one coefficient
+RunLoop
+ SUBS Count, Count, #1
+ LDR pVLDTable, [ppRunTable, ZerosLeft, LSL#2]
+ BLT LastRun
+ M_BD_VLD Symbol, T1, T2, pVLDTable, 3, 2 ;// Symbol = Run
+ CMP Symbol,#15
+ BGE EndBadSymbol
+
+ SUBS ZerosLeft, ZerosLeft, Symbol
+ M_PRINTF "Run=%d\n", Symbol
+ STRB Symbol, [pRun], #1
+ BGT RunLoop
+
+ ;// Decode runs while no zeros are left
+NoZerosLeft
+ SUBS Count, Count, #1
+ M_PRINTF "Run=%d\n", ZerosLeft
+ STRGEB ZerosLeft, [pRun], #1
+ BGT NoZerosLeft
+
+LastRun
+ ;// Final run length is remaining zeros
+ M_PRINTF "LastRun=%d\n", ZerosLeft
+ STRB ZerosLeft, [pRun], #1
+
+ ;// Write coefficients to output array
+ M_LDR T1, pSMaxNumCoeff ;// sMaxNumCoeff
+ TEQ T1, #15
+ ADDEQ CoeffNum,CoeffNum,#1
+
+
+ SUB pRun,pRun,TotalCoeff
+ SUB pLevel,pLevel,TotalCoeff
+ SUB pLevel,pLevel,TotalCoeff
+
+ M_LDR ppPosCoefbuf, pppPosCoefbuf
+ LDR pPosCoefbuf, [ppPosCoefbuf]
+ TEQ T1, #4
+ LDREQ pZigZag, =armVCM4P10_ZigZag_2x2
+ LDRNE pZigZag, =armVCM4P10_ZigZag_4x4
+
+
+
+OutputLoop
+
+ LDRB T2, [pRun],#1
+ LDRB T1, [pZigZag, CoeffNum]
+ SUB CoeffNum, CoeffNum, #1 ;// Skip Non zero
+ SUB CoeffNum, CoeffNum, T2 ;// Skip Zero run
+
+ LDRSH T2, [pLevel],#2
+
+ SUBS TotalCoeff, TotalCoeff, #1
+ ORREQ T1, T1, #LAST_COEFF
+
+ ADD temp, T2, #128
+ CMP temp, #256
+ ORRCS T1, T1, #TWO_BYTE_COEFF
+
+
+ TEQ TotalCoeff, #0 ;// Preserves carry
+
+ M_PRINTF "Output=%02x %04x\n", T1, T2
+ STRB T1, [pPosCoefbuf], #1
+ STRB T2, [pPosCoefbuf], #1
+ MOV T2, T2, LSR #8
+ STRCSB T2, [pPosCoefbuf], #1
+ BNE OutputLoop
+
+ ;// Finished
+ STR pPosCoefbuf, [ppPosCoefbuf]
+ M_LDR ppBitStream, pppBitStream
+ M_LDR pOffset, ppOffset
+ B EndNoError
+
+EndBadSymbol
+ MOV r0, #OMX_Sts_Err
+ B End
+
+EndNoError
+ ;// Finished reading from the bitstream
+ M_BD_FINI ppBitStream, pOffset
+
+ ;// Set return value
+ MOV r0, #OMX_Sts_NoErr
+End
+ M_END
+
+ ENDIF
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DequantTables_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DequantTables_s.s
new file mode 100644
index 0000000..b16f188
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_DequantTables_s.s
@@ -0,0 +1,123 @@
+;//
+;//
+;// File Name: armVCM4P10_DequantTables_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ EXPORT armVCM4P10_QPDivTable
+ EXPORT armVCM4P10_VMatrixQPModTable
+ EXPORT armVCM4P10_PosToVCol4x4
+ EXPORT armVCM4P10_PosToVCol2x2
+ EXPORT armVCM4P10_VMatrix
+ EXPORT armVCM4P10_QPModuloTable
+ EXPORT armVCM4P10_VMatrixU16
+
+;// Define the processor variants supported by this file
+
+ M_VARIANTS ARM1136JS
+
+
+;// Guarding implementation by the processor name
+
+
+ IF ARM1136JS :LOR: CortexA8
+
+
+ M_TABLE armVCM4P10_PosToVCol4x4
+ DCB 0, 2, 0, 2
+ DCB 2, 1, 2, 1
+ DCB 0, 2, 0, 2
+ DCB 2, 1, 2, 1
+
+
+ M_TABLE armVCM4P10_PosToVCol2x2
+ DCB 0, 2
+ DCB 2, 1
+
+
+ M_TABLE armVCM4P10_VMatrix
+ DCB 10, 16, 13
+ DCB 11, 18, 14
+ DCB 13, 20, 16
+ DCB 14, 23, 18
+ DCB 16, 25, 20
+ DCB 18, 29, 23
+
+;//-------------------------------------------------------
+;// This table evaluates the expression [(INT)(QP/6)],
+;// for values of QP from 0 to 51 (inclusive).
+;//-------------------------------------------------------
+
+ M_TABLE armVCM4P10_QPDivTable
+ DCB 0, 0, 0, 0, 0, 0
+ DCB 1, 1, 1, 1, 1, 1
+ DCB 2, 2, 2, 2, 2, 2
+ DCB 3, 3, 3, 3, 3, 3
+ DCB 4, 4, 4, 4, 4, 4
+ DCB 5, 5, 5, 5, 5, 5
+ DCB 6, 6, 6, 6, 6, 6
+ DCB 7, 7, 7, 7, 7, 7
+ DCB 8, 8, 8, 8, 8, 8
+
+;//----------------------------------------------------
+;// This table contains armVCM4P10_VMatrix[QP%6][0] entires,
+;// for values of QP from 0 to 51 (inclusive).
+;//----------------------------------------------------
+
+ M_TABLE armVCM4P10_VMatrixQPModTable
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+
+;//-------------------------------------------------------
+;// This table evaluates the modulus expression [QP%6]*6,
+;// for values of QP from 0 to 51 (inclusive).
+;//-------------------------------------------------------
+
+ M_TABLE armVCM4P10_QPModuloTable
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+
+;//-------------------------------------------------------
+;// This table contains the invidual byte values stored as
+;// halfwords. This avoids unpacking inside the function
+;//-------------------------------------------------------
+
+ M_TABLE armVCM4P10_VMatrixU16
+ DCW 10, 16, 13
+ DCW 11, 18, 14
+ DCW 13, 20, 16
+ DCW 14, 23, 18
+ DCW 16, 25, 20
+ DCW 18, 29, 23
+
+ ENDIF ;//ARM1136JS
+
+
+
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
new file mode 100644
index 0000000..82b9542
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
@@ -0,0 +1,236 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_Align_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ EXPORT armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ EXPORT armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+
+DEBUG_ON SETL {FALSE}
+
+ IF ARM1136JS
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 8
+iHeight RN 9
+
+;// Declare inner loop registers
+x RN 7
+x0 RN 7
+x1 RN 10
+x2 RN 11
+Scratch RN 12
+
+;// Function:
+;// armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+;//
+;// Implements copy from an arbitrary aligned source memory location (pSrc) to a 4 byte aligned
+;// destination pointed by (pDst) for horizontal interpolation.
+;// This function needs to copy 9 bytes in horizontal direction.
+;//
+;// Registers used as input for this function
+;// r0,r1,r8,r9 where r8 containings aligned memory pointer and r9 no rows to copy
+;//
+;// Registers preserved for top level function
+;// r2,r3,r4,r5,r6
+;//
+;// Registers modified by the function
+;// r7,r8,r9,r10,r11,r12
+;//
+;// Output registers
+;// r0 - pointer to the new aligned location which will be used as pSrc
+;// r1 - step size to this aligned location
+
+ ;// Function header
+ M_START armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+
+ ;// Copy pDst to scratch
+ MOV Scratch, pDst
+
+StartAlignedStackCopy
+ AND x, pSrc, #3
+ BIC pSrc, pSrc, #3
+
+ M_SWITCH x
+ M_CASE Copy0toAligned
+ M_CASE Copy1toAligned
+ M_CASE Copy2toAligned
+ M_CASE Copy3toAligned
+ M_ENDSWITCH
+
+Copy0toAligned
+ LDM pSrc, {x0, x1, x2}
+ SUBS iHeight, iHeight, #1
+ ADD pSrc, pSrc, srcStep
+
+ ;// One cycle stall
+
+ STM pDst!, {x0, x1, x2} ;// Store aligned output row
+ BGT Copy0toAligned
+ B CopyEnd
+
+Copy1toAligned
+ LDM pSrc, {x0, x1, x2}
+ SUBS iHeight, iHeight, #1
+ ADD pSrc, pSrc, srcStep
+
+ ;// One cycle stall
+
+ MOV x0, x0, LSR #8
+ ORR x0, x0, x1, LSL #24
+ MOV x1, x1, LSR #8
+ ORR x1, x1, x2, LSL #24
+ MOV x2, x2, LSR #8
+ STM pDst!, {x0, x1, x2} ;// Store aligned output row
+ BGT Copy1toAligned
+ B CopyEnd
+
+Copy2toAligned
+ LDM pSrc, {x0, x1, x2}
+ SUBS iHeight, iHeight, #1
+ ADD pSrc, pSrc, srcStep
+
+ ;// One cycle stall
+
+ MOV x0, x0, LSR #16
+ ORR x0, x0, x1, LSL #16
+ MOV x1, x1, LSR #16
+ ORR x1, x1, x2, LSL #16
+ MOV x2, x2, LSR #16
+ STM pDst!, {x0, x1, x2} ;// Store aligned output row
+ BGT Copy2toAligned
+ B CopyEnd
+
+Copy3toAligned
+ LDM pSrc, {x0, x1, x2}
+ SUBS iHeight, iHeight, #1
+ ADD pSrc, pSrc, srcStep
+
+ ;// One cycle stall
+
+ MOV x0, x0, LSR #24
+ ORR x0, x0, x1, LSL #8
+ MOV x1, x1, LSR #24
+ ORR x1, x1, x2, LSL #8
+ MOV x2, x2, LSR #24
+ STM pDst!, {x0, x1, x2} ;// Store aligned output row
+ BGT Copy3toAligned
+
+CopyEnd
+
+ MOV pSrc, Scratch
+ MOV srcStep, #12
+
+ M_END
+
+
+;// Function:
+;// armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+;//
+;// Implements copy from an arbitrary aligned source memory location (pSrc) to an aligned
+;// destination pointed by (pDst) for vertical interpolation.
+;// This function needs to copy 4 bytes in horizontal direction
+;//
+;// Registers used as input for this function
+;// r0,r1,r8,r9 where r8 containings aligned memory pointer and r9 no of rows to copy
+;//
+;// Registers preserved for top level function
+;// r2,r3,r4,r5,r6
+;//
+;// Registers modified by the function
+;// r7,r8,r9,r10,r11,r12
+;//
+;// Output registers
+;// r0 - pointer to the new aligned location which will be used as pSrc
+;// r1 - step size to this aligned location
+
+ ;// Function header
+ M_START armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+
+ ;// Copy pSrc to stack
+StartVAlignedStackCopy
+ AND x, pSrc, #3
+ BIC pSrc, pSrc, #3
+
+
+ M_SWITCH x
+ M_CASE Copy0toVAligned
+ M_CASE Copy1toVAligned
+ M_CASE Copy2toVAligned
+ M_CASE Copy3toVAligned
+ M_ENDSWITCH
+
+Copy0toVAligned
+ M_LDR x0, [pSrc], srcStep
+ SUBS iHeight, iHeight, #1
+
+ ;// One cycle stall
+
+ STR x0, [pDst], #4 ;// Store aligned output row
+ BGT Copy0toVAligned
+ B CopyVEnd
+
+Copy1toVAligned
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ SUBS iHeight, iHeight, #1
+
+ ;// One cycle stall
+
+ MOV x1, x1, LSL #24
+ ORR x0, x1, x0, LSR #8
+ STR x0, [pDst], #4 ;// Store aligned output row
+ BGT Copy1toVAligned
+ B CopyVEnd
+
+Copy2toVAligned
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ SUBS iHeight, iHeight, #1
+
+ ;// One cycle stall
+
+ MOV x1, x1, LSL #16
+ ORR x0, x1, x0, LSR #16
+ STR x0, [pDst], #4 ;// Store aligned output row
+ BGT Copy2toVAligned
+ B CopyVEnd
+
+Copy3toVAligned
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ SUBS iHeight, iHeight, #1
+
+ ;// One cycle stall
+
+ MOV x1, x1, LSL #8
+ ORR x0, x1, x0, LSR #24
+ STR x0, [pDst], #4 ;// Store aligned output row
+ BGT Copy3toVAligned
+
+CopyVEnd
+
+ SUB pSrc, pDst, #28
+ MOV srcStep, #4
+
+ M_END
+
+
+ ENDIF
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
new file mode 100644
index 0000000..bc0b6ec
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
@@ -0,0 +1,149 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+;// Function:
+;// armVCM4P10_InterpolateLuma_Copy4x4_unsafe
+;//
+;// Implements copy from an arbitrary aligned source memory location (pSrc) to an aligned
+;// destination pointed by (pDst)
+;//
+;// Registers preserved for top level function
+;// r1,r3,r4,r5,r6,r7,r10,r11,r14
+;//
+;// Registers modified by the function
+;// r0,r2,r8,r9,r12
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ EXPORT armVCM4P10_InterpolateLuma_Copy4x4_unsafe
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 2
+dstStep RN 3
+
+;// Declare other intermediate registers
+x0 RN 4
+x1 RN 5
+x2 RN 8
+x3 RN 9
+Temp RN 12
+
+ IF ARM1136JS
+
+ M_START armVCM4P10_InterpolateLuma_Copy4x4_unsafe, r6
+
+Copy4x4Start
+ ;// Do Copy and branch to EndOfInterpolation
+ AND Temp, pSrc, #3
+ BIC pSrc, pSrc, #3
+
+ M_SWITCH Temp
+ M_CASE Copy4x4Align0
+ M_CASE Copy4x4Align1
+ M_CASE Copy4x4Align2
+ M_CASE Copy4x4Align3
+ M_ENDSWITCH
+
+Copy4x4Align0
+ M_LDR x0, [pSrc], srcStep
+ M_LDR x1, [pSrc], srcStep
+ M_STR x0, [pDst], dstStep
+ M_LDR x2, [pSrc], srcStep
+ M_STR x1, [pDst], dstStep
+ M_LDR x3, [pSrc], srcStep
+ M_STR x2, [pDst], dstStep
+ M_STR x3, [pDst], dstStep
+ B Copy4x4End
+
+Copy4x4Align1
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ LDR x3, [pSrc, #4]
+ M_LDR x2, [pSrc], srcStep
+ MOV x0, x0, LSR #8
+ ORR x0, x0, x1, LSL #24
+ M_STR x0, [pDst], dstStep
+ MOV x2, x2, LSR #8
+ ORR x2, x2, x3, LSL #24
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ M_STR x2, [pDst], dstStep
+ LDR x3, [pSrc, #4]
+ M_LDR x2, [pSrc], srcStep
+ MOV x0, x0, LSR #8
+ ORR x0, x0, x1, LSL #24
+ M_STR x0, [pDst], dstStep
+ MOV x2, x2, LSR #8
+ ORR x2, x2, x3, LSL #24
+ M_STR x2, [pDst], dstStep
+ B Copy4x4End
+
+Copy4x4Align2
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ LDR x3, [pSrc, #4]
+ M_LDR x2, [pSrc], srcStep
+ MOV x0, x0, LSR #16
+ ORR x0, x0, x1, LSL #16
+ M_STR x0, [pDst], dstStep
+ MOV x2, x2, LSR #16
+ ORR x2, x2, x3, LSL #16
+ M_STR x2, [pDst], dstStep
+
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ LDR x3, [pSrc, #4]
+ M_LDR x2, [pSrc], srcStep
+ MOV x0, x0, LSR #16
+ ORR x0, x0, x1, LSL #16
+ M_STR x0, [pDst], dstStep
+ MOV x2, x2, LSR #16
+ ORR x2, x2, x3, LSL #16
+ M_STR x2, [pDst], dstStep
+ B Copy4x4End
+
+Copy4x4Align3
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ LDR x3, [pSrc, #4]
+ M_LDR x2, [pSrc], srcStep
+ MOV x0, x0, LSR #24
+ ORR x0, x0, x1, LSL #8
+ M_STR x0, [pDst], dstStep
+ MOV x2, x2, LSR #24
+ ORR x2, x2, x3, LSL #8
+ M_STR x2, [pDst], dstStep
+
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ LDR x3, [pSrc, #4]
+ M_LDR x2, [pSrc], srcStep
+ MOV x0, x0, LSR #24
+ ORR x0, x0, x1, LSL #8
+ M_STR x0, [pDst], dstStep
+ MOV x2, x2, LSR #24
+ ORR x2, x2, x3, LSL #8
+ M_STR x2, [pDst], dstStep
+ B Copy4x4End
+
+Copy4x4End
+ M_END
+
+ ENDIF
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
new file mode 100644
index 0000000..66cfe5e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
@@ -0,0 +1,178 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ EXPORT armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe
+ EXPORT armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe
+
+;// Functions:
+;// armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe and
+;// armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe
+;//
+;// Implements re-arrangement of data from temporary buffer to a buffer pointed by pBuf.
+;// This will do the convertion of data from 16 bit to 8 bit and it also
+;// remove offset and check for saturation.
+;//
+;// Registers used as input for this function
+;// r0,r1,r7 where r0 is input pointer and r2 its step size, r7 is output pointer
+;//
+;// Registers preserved for top level function
+;// r4,r5,r6,r8,r9,r14
+;//
+;// Registers modified by the function
+;// r7,r10,r11,r12
+;//
+;// Output registers
+;// r0 - pointer to the destination location
+;// r1 - step size to this destination location
+
+
+DEBUG_ON SETL {FALSE}
+
+MASK EQU 0x80808080 ;// Mask is used to implement (a+b+1)/2
+
+;// Declare input registers
+
+pSrc0 RN 0
+srcStep0 RN 1
+
+;// Declare other intermediate registers
+Temp1 RN 4
+Temp2 RN 5
+Temp3 RN 10
+Temp4 RN 11
+pBuf RN 7
+r0x0fe00fe0 RN 6
+r0x00ff00ff RN 12
+Count RN 14
+ValueA0 RN 10
+ValueA1 RN 11
+
+ IF ARM1136JS
+
+
+ ;// Function header
+ M_START armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe, r6
+
+ ;// Code start
+ MOV Count, #4
+ LDR r0x0fe00fe0, =0x0fe00fe0
+ LDR r0x00ff00ff, =0x00ff00ff
+LoopStart1
+ LDR Temp4, [pSrc0, #12]
+ LDR Temp3, [pSrc0, #8]
+ LDR Temp2, [pSrc0, #4]
+ M_LDR Temp1, [pSrc0], srcStep0
+ UQSUB16 Temp4, Temp4, r0x0fe00fe0
+ UQSUB16 Temp3, Temp3, r0x0fe00fe0
+ UQSUB16 Temp2, Temp2, r0x0fe00fe0
+ UQSUB16 Temp1, Temp1, r0x0fe00fe0
+ USAT16 Temp4, #13, Temp4
+ USAT16 Temp3, #13, Temp3
+ USAT16 Temp2, #13, Temp2
+ USAT16 Temp1, #13, Temp1
+ AND Temp4, r0x00ff00ff, Temp4, LSR #5
+ AND Temp3, r0x00ff00ff, Temp3, LSR #5
+ AND Temp2, r0x00ff00ff, Temp2, LSR #5
+ AND Temp1, r0x00ff00ff, Temp1, LSR #5
+ ORR ValueA1, Temp3, Temp4, LSL #8
+ ORR ValueA0, Temp1, Temp2, LSL #8
+ SUBS Count, Count, #1
+ STRD ValueA0, [pBuf], #8
+ BGT LoopStart1
+End1
+ SUB pSrc0, pBuf, #32
+ MOV srcStep0, #8
+
+ M_END
+
+
+ ;// Function header
+ M_START armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe, r6
+
+ ;// Code start
+ LDR r0x0fe00fe0, =0x0fe00fe0
+ LDR r0x00ff00ff, =0x00ff00ff
+ MOV Count, #2
+
+LoopStart
+ LDR Temp4, [pSrc0, #12]
+ LDR Temp3, [pSrc0, #8]
+ LDR Temp2, [pSrc0, #4]
+ M_LDR Temp1, [pSrc0], srcStep0
+
+ UQSUB16 Temp4, Temp4, r0x0fe00fe0
+ UQSUB16 Temp3, Temp3, r0x0fe00fe0
+ UQSUB16 Temp2, Temp2, r0x0fe00fe0
+ UQSUB16 Temp1, Temp1, r0x0fe00fe0
+
+ USAT16 Temp4, #13, Temp4
+ USAT16 Temp3, #13, Temp3
+ USAT16 Temp2, #13, Temp2
+ USAT16 Temp1, #13, Temp1
+
+ AND Temp4, r0x00ff00ff, Temp4, LSR #5
+ AND Temp3, r0x00ff00ff, Temp3, LSR #5
+ AND Temp2, r0x00ff00ff, Temp2, LSR #5
+ AND Temp1, r0x00ff00ff, Temp1, LSR #5
+ ORR ValueA1, Temp3, Temp4, LSL #8 ;// [d2 c2 d0 c0]
+ ORR ValueA0, Temp1, Temp2, LSL #8 ;// [b2 a2 b0 a0]
+
+ PKHBT Temp1, ValueA0, ValueA1, LSL #16 ;// [d0 c0 b0 a0]
+
+ STR Temp1, [pBuf], #8
+ PKHTB Temp2, ValueA1, ValueA0, ASR #16 ;// [d2 c2 b2 a2]
+ STR Temp2, [pBuf], #-4
+
+ LDR Temp4, [pSrc0, #12]
+ LDR Temp3, [pSrc0, #8]
+ LDR Temp2, [pSrc0, #4]
+ M_LDR Temp1, [pSrc0], srcStep0
+
+ UQSUB16 Temp4, Temp4, r0x0fe00fe0
+ UQSUB16 Temp3, Temp3, r0x0fe00fe0
+ UQSUB16 Temp2, Temp2, r0x0fe00fe0
+ UQSUB16 Temp1, Temp1, r0x0fe00fe0
+
+ USAT16 Temp4, #13, Temp4
+ USAT16 Temp3, #13, Temp3
+ USAT16 Temp2, #13, Temp2
+ USAT16 Temp1, #13, Temp1
+
+ AND Temp4, r0x00ff00ff, Temp4, LSR #5
+ AND Temp3, r0x00ff00ff, Temp3, LSR #5
+ AND Temp2, r0x00ff00ff, Temp2, LSR #5
+ AND Temp1, r0x00ff00ff, Temp1, LSR #5
+ ORR ValueA1, Temp3, Temp4, LSL #8 ;// [d2 c2 d0 c0]
+ ORR ValueA0, Temp1, Temp2, LSL #8 ;// [b2 a2 b0 a0]
+
+ PKHBT Temp1, ValueA0, ValueA1, LSL #16 ;// [d0 c0 b0 a0]
+ SUBS Count, Count, #1
+ STR Temp1, [pBuf], #8
+ PKHTB Temp2, ValueA1, ValueA0, ASR #16 ;// [d2 c2 b2 a2]
+ STR Temp2, [pBuf], #4
+
+ BGT LoopStart
+End2
+ SUB pSrc0, pBuf, #32-8
+ MOV srcStep0, #4
+
+ M_END
+
+ ENDIF
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
new file mode 100644
index 0000000..851ff6a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
@@ -0,0 +1,296 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ EXPORT armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+
+ M_VARIANTS ARM1136JS
+
+
+
+ IF ARM1136JS
+
+
+ M_ALLOC8 ppDstArgs, 8
+ M_ALLOC8 pTempResult1, 8
+ M_ALLOC8 pTempResult2, 8
+ M_ALLOC4 ppSrc, 4
+ M_ALLOC4 ppDst, 4
+ M_ALLOC4 pDstStep, 4
+ M_ALLOC4 pSrcStep, 4
+ M_ALLOC4 pCounter, 4
+
+ ;// Function header
+ ;// Function:
+ ;// armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+ ;//
+ ;// Implements diagonal interpolation for a block of size 4x4. Input and output should
+ ;// be aligned.
+ ;//
+ ;// Registers used as input for this function
+ ;// r0,r1,r2,r3, r8 where r0,r2 input pointer and r1,r3 step size, r8 intermediate-buf pointer
+ ;//
+ ;// Registers preserved for top level function
+ ;// r0,r1,r2,r3,r4,r5,r6,r14
+ ;//
+ ;// Registers modified by the function
+ ;// r7,r8,r9,r10,r11,r12
+ ;//
+ ;// Output registers
+ ;// None. Function will preserve r0-r3
+
+ M_START armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe, r6
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 2
+dstStep RN 3
+
+;// Declare inner loop registers
+Acc0 RN 4
+Acc1 RN 5
+Acc2 RN 6
+Acc3 RN 7
+
+ValA RN 4
+ValB RN 5
+ValC RN 6
+ValD RN 7
+ValE RN 8
+ValF RN 9
+ValG RN 12
+ValH RN 14
+ValI RN 1
+
+Temp1 RN 3
+Temp2 RN 1
+Temp3 RN 12
+Temp4 RN 7
+Temp5 RN 5
+r0x0fe00fe0 RN 3 ;// [0 (16*255 - 16) 0 (16*255 - 16)]
+r0x00ff00ff RN 10 ;// [0 255 0 255] where 255 is offset
+Counter RN 11
+pInterBuf RN 8
+
+ValCA RN 8
+ValDB RN 9
+ValGE RN 10
+ValHF RN 11
+r0x00140001 RN 12
+r0x0014fffb RN 14
+
+r0x0001fc00 RN 11
+
+Accx RN 8
+Accy RN 9
+Temp6 RN 14
+
+ M_STRD pDst, dstStep, ppDstArgs
+
+ MOV pDst, pInterBuf
+ MOV dstStep, #16
+
+ ;// Set up counter of format, [0] [0] [1 (height)] [8 (width)]
+ MOV Counter, #4
+ M_STR dstStep, pDstStep
+ M_STR srcStep, pSrcStep
+ LDR r0x00ff00ff, =0x00ff00ff ;// [0 255 0 255] 255 is offset to avoid negative results
+
+HeightLoop
+NextTwoRowsLoop
+ LDR ValD, [pSrc, srcStep] ;// Load row 1 [d1 c1 b1 a1]
+ LDR ValA, [pSrc], #4 ;// Load row 0 [d0 c0 b0 a0]
+ LDR ValH, [pSrc, srcStep] ;// Load [h1 g1 f1 e1]
+ LDR ValE, [pSrc], #4 ;// Load [h0 g0 f0 e0]
+ LDRB Temp2, [pSrc, srcStep] ;// Load row 1 [l1 k1 j1 i1]
+ LDRB Temp1, [pSrc], #-8 ;// Load row 0 [l0 k0 j0 i0]
+
+ PKHBT ValB, ValA, ValD, LSL #16 ;// [b1 a1 b0 a0]
+ PKHTB ValD, ValD, ValA, ASR #16 ;// [d1 c1 d0 c0]
+ UXTAB16 ValA, r0x00ff00ff, ValB ;// [00 a1 00 a0] + [0 255 0 255]
+ UXTAB16 ValC, r0x00ff00ff, ValD ;// [00 c1 00 c0] + [0 255 0 255]
+ PKHBT ValI, Temp1, Temp2, LSL #16 ;// [00 i1 00 i0]
+ PKHBT ValF, ValE, ValH, LSL #16 ;// [f1 e1 f0 e0]
+ PKHTB ValH, ValH, ValE, ASR #16 ;// [h1 g1 h0 g0]
+ UXTAB16 ValE, r0x00ff00ff, ValF ;// [00 e1 00 e0] + [0 255 0 255]
+
+ ;// Calculate Acc0
+ ;// Acc0 = a - 5*b + 20*c + 20*d - 5*e + f
+ UXTAB16 Temp1, ValC, ValD, ROR #8
+ UXTAB16 Temp3, ValE, ValB, ROR #8
+ RSB Temp1, Temp3, Temp1, LSL #2
+ UXTAB16 Acc0, ValA, ValF, ROR #8
+ ADD Temp1, Temp1, Temp1, LSL #2
+ ADD Acc0, Acc0, Temp1
+
+ ;// Calculate Acc1
+ ;// Acc1 = b - 5*c + 20*d + 20*e - 5*f + g
+ UXTAB16 Temp1, ValE, ValD, ROR #8
+ UXTAB16 Temp3, ValC, ValF, ROR #8
+ RSB Temp1, Temp3, Temp1, LSL #2
+ UXTAB16 ValG, r0x00ff00ff, ValH ;// [00 g1 00 g0] + [0 255 0 255]
+ ADD Temp1, Temp1, Temp1, LSL #2
+ UXTAB16 Acc1, ValG, ValB, ROR #8
+ ADD Acc1, Acc1, Temp1
+
+ UXTAB16 Acc2, ValC, ValH, ROR #8
+ ADD ValI, r0x00ff00ff, ValI ;// [00 i1 00 i0] + [0 255 0 255]
+
+ ;// Calculate Acc2
+ ;// Acc2 = c - 5*d + 20*e + 20*f - 5*g + h
+ UXTAB16 Temp1, ValG, ValD, ROR #8
+ UXTAB16 Acc3, ValI, ValD, ROR #8
+ UXTAB16 Temp2, ValE, ValF, ROR #8
+
+ RSB Temp1, Temp1, Temp2, LSL #2
+ UXTAB16 Temp2, ValG, ValF, ROR #8
+ ADD Temp1, Temp1, Temp1, LSL #2
+ ADD Acc2, Acc2, Temp1
+
+ ;// Calculate Acc3
+ ;// Acc3 = d - 5*e + 20*f + 20*g - 5*h + i
+ UXTAB16 Temp1, ValE, ValH, ROR #8
+ RSB Temp1, Temp1, Temp2, LSL #2
+ ADD Temp1, Temp1, Temp1, LSL #2
+ ADD Acc3, Acc3, Temp1
+
+ M_LDR dstStep, pDstStep
+ M_LDR srcStep, pSrcStep
+
+ ;// If Counter is even store Acc0-Acc3 in a temporary buffer
+ ;// If Counter is off store Acc0-Acc3 and previous Acc0-Acc3 in a intermediate buf
+ ANDS Temp3, Counter, #1
+ BEQ NoProcessing
+
+ ;// Packing previous and current Acc0-Acc3 values
+ M_LDRD Accx, Accy, pTempResult1
+ PKHBT Temp6, Accx, Acc0, LSL #16 ;//[0 a2 0 a0] = [0 a3 0 a2] [0 a1 0 a0]
+ PKHTB Acc0, Acc0, Accx, ASR #16 ;//[0 a3 0 a1] = [0 a1 0 a0] [0 a3 0 a2]
+ STR Acc0, [pDst, dstStep]
+ STR Temp6, [pDst], #4
+ PKHBT Temp6, Accy, Acc1, LSL #16 ;//[0 b2 0 b0] = [0 b3 0 b2] [0 b1 0 b0]
+ PKHTB Acc1, Acc1, Accy, ASR #16 ;//[0 b3 0 b1] = [0 b1 0 b0] [0 b3 0 b2]
+ M_LDRD Accx, Accy, pTempResult2
+ STR Acc1, [pDst, dstStep]
+ STR Temp6, [pDst], #4
+
+ PKHBT Temp6, Accx, Acc2, LSL #16 ;//[0 c2 0 c0] = [0 c3 0 c2] [0 c1 0 c0]
+ PKHTB Acc2, Acc2, Accx, ASR #16 ;//[0 c3 0 c1] = [0 c1 0 c0] [0 c3 0 c2]
+ STR Acc2, [pDst, dstStep]
+ STR Temp6, [pDst], #4
+ PKHBT Temp6, Accy, Acc3, LSL #16 ;//[0 d2 0 d0] = [0 d3 0 d2] [0 d1 0 d0]
+ PKHTB Acc3, Acc3, Accy, ASR #16 ;//[0 d3 0 d1] = [0 d1 0 d0] [0 d3 0 d2]
+ STR Acc3, [pDst, dstStep]
+ STR Temp6, [pDst], #-12
+ ADD pDst, pDst, dstStep, LSL #1
+ B AfterStore
+
+NoProcessing
+ M_STRD Acc0, Acc1, pTempResult1
+ M_STRD Acc2, Acc3, pTempResult2
+AfterStore
+ SUBS Counter, Counter, #1 ;// Loop till height is 10
+ ADD pSrc, pSrc, srcStep, LSL #1
+ BPL HeightLoop
+
+ STR Acc0, [pDst], #4 ;//[0 a1 0 a0]
+ STR Acc1, [pDst], #4
+ STR Acc2, [pDst], #4
+ STR Acc3, [pDst], #-12
+
+ ;//
+ ;// Horizontal interpolation using multiplication
+ ;//
+
+ SUB pSrc, pDst, dstStep, LSL #2
+ MOV srcStep, #16
+ M_LDRD pDst, dstStep, ppDstArgs
+
+ MOV Counter, #4
+ LDR r0x0014fffb, =0x0014fffb
+ LDR r0x00140001, =0x00140001
+
+HeightLoop1
+ M_STR Counter, pCounter
+
+ M_LDR ValCA, [pSrc], srcStep ;// Load [0 c 0 a]
+ M_LDR ValDB, [pSrc], srcStep ;// Load [0 d 0 b]
+ M_LDR ValGE, [pSrc], srcStep ;// Load [0 g 0 e]
+ M_LDR ValHF, [pSrc], srcStep ;// Load [0 h 0 f]
+
+
+ ;// Acc0 = smuad ([0 20 0 1], add([0 c 0 a] + [0 d 0 f])) - (5 * (b + e))
+ ;// Acc1 = smuad ([0 20 0 1], add([0 e 0 g] + [0 d 0 b])) - (5 * (c + f))
+ ;// Acc2 = smuad ([0 1 0 20], add([0 c 0 e] + [0 h 0 f])) - (5 * (d + g))
+ ;// Acc3 = smuad ([0 20 0 1], add([0 d 0 f] + [0 i 0 g])) - (5 * (e + h))
+
+ SMUAD Acc0, ValCA, r0x00140001 ;// Acc0 = [0 c 0 a] * [0 20 0 1]
+ SMUAD Acc1, ValDB, r0x00140001 ;// Acc1 = [0 c 0 a] * [0 20 0 1]
+ SMUADX Acc2, ValGE, r0x0014fffb ;// Acc2 = [0 g 0 e] * [0 20 0 -5]
+ SMUAD Acc3, ValGE, r0x0014fffb ;// Acc3 = [0 g 0 e] * [0 20 0 -5]
+
+ SMLAD Acc0, ValDB, r0x0014fffb, Acc0 ;// Acc0 += [0 d 0 b] * [0 20 0 -5]
+ SMLADX Acc1, ValGE, r0x00140001, Acc1 ;// Acc1 += [0 g 0 e] * [0 20 0 1]
+ SMLADX Acc2, ValHF, r0x00140001, Acc2 ;// Acc2 += [0 h 0 f] * [0 20 0 1]
+ SMLADX Acc3, ValHF, r0x0014fffb, Acc3 ;// Acc3 += [0 h 0 f] * [0 20 0 -5]
+
+ SMLABB Acc0, ValGE, r0x0014fffb, Acc0 ;// Acc0 += [0 g 0 e] * [0 0 0 -5]
+ SMLATB Acc1, ValCA, r0x0014fffb, Acc1 ;// Acc1 += [0 d 0 b] * [0 0 0 -5]
+ SMLATB Acc2, ValCA, r0x00140001, Acc2 ;// Acc2 += [0 c 0 a] * [0 0 0 1]
+ SMLATB Acc3, ValDB, r0x00140001, Acc3 ;// Acc3 += [0 c 0 a] * [0 0 0 1]
+
+ LDRH ValCA, [pSrc], #4 ;// 8 = srcStep - 16
+ SMLABB Acc0, ValHF, r0x00140001, Acc0 ;// Acc0 += [0 h 0 f] * [0 0 0 1]
+ SMLABB Acc1, ValHF, r0x0014fffb, Acc1 ;// Acc1 += [0 h 0 f] * [0 0 0 -5]
+ SMLATB Acc2, ValDB, r0x0014fffb, Acc2 ;// Acc2 += [0 d 0 b] * [0 0 0 -5]
+ SMLABB Acc3, ValCA, r0x00140001, Acc3 ;// Acc3 += [0 d 0 b] * [0 0 0 1]
+
+ LDR r0x0001fc00, =0x0001fc00 ;// (0xff * 16 * 32) - 512
+ SUB Acc0, Acc0, r0x0001fc00
+ SUB Acc1, Acc1, r0x0001fc00
+ SUB Acc2, Acc2, r0x0001fc00
+ SUB Acc3, Acc3, r0x0001fc00
+
+ USAT Acc0, #18, Acc0
+ USAT Acc1, #18, Acc1
+ USAT Acc2, #18, Acc2
+ USAT Acc3, #18, Acc3
+
+ MOV Acc0, Acc0, LSR #10
+ M_STRB Acc0, [pDst], dstStep
+ MOV Acc1, Acc1, LSR #10
+ M_STRB Acc1, [pDst], dstStep
+ MOV Acc2, Acc2, LSR #10
+ M_STRB Acc2, [pDst], dstStep
+ MOV Acc3, Acc3, LSR #10
+ M_STRB Acc3, [pDst], dstStep
+
+
+ M_LDR Counter, pCounter
+ SUB pDst, pDst, dstStep, LSL #2
+ SUB pSrc, pSrc, srcStep, LSL #2
+ ADD pDst, pDst, #1
+ SUBS Counter, Counter, #1
+ BGT HeightLoop1
+End
+ SUB pDst, pDst, #4
+ SUB pSrc, pSrc, #16
+
+ M_END
+
+ ENDIF
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
new file mode 100644
index 0000000..2f48e13
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
@@ -0,0 +1,276 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ EXPORT armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+
+ M_VARIANTS ARM1136JS
+
+
+
+
+
+ IF ARM1136JS
+
+ M_ALLOC8 ppDstArgs, 8
+ M_ALLOC4 ppSrc, 4
+ M_ALLOC4 ppDst, 4
+ M_ALLOC4 pCounter, 4
+
+ ;// Function header
+ ;// Function:
+ ;// armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+ ;//
+ ;// Implements diagonal interpolation for a block of size 4x4. Input and output should
+ ;// be aligned.
+ ;//
+ ;// Registers used as input for this function
+ ;// r0,r1,r2,r3, r8 where r0,r2 input pointer and r1,r3 step size, r8 intermediate-buf pointer
+ ;//
+ ;// Registers preserved for top level function
+ ;// r0,r1,r2,r3,r4,r5,r6,r14
+ ;//
+ ;// Registers modified by the function
+ ;// r7,r8,r9,r10,r11,r12
+ ;//
+ ;// Output registers
+ ;// None. Function will preserve r0-r3
+
+ M_START armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe, r6
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 2
+dstStep RN 3
+
+;// Declare inner loop registers
+ValA RN 5
+ValA0 RN 4
+ValA1 RN 5
+ValAF0 RN 4
+ValAF1 RN 5
+
+ValB RN 11
+
+ValC RN 5
+ValC0 RN 4
+ValC1 RN 5
+ValCD0 RN 12
+ValCD1 RN 14
+ValCF0 RN 4
+ValCF1 RN 5
+
+ValD RN 10
+
+ValE RN 7
+ValE0 RN 6
+ValE1 RN 7
+ValEB0 RN 10
+ValEB1 RN 11
+ValED0 RN 6
+ValED1 RN 7
+
+ValF RN 10
+
+ValG RN 14
+ValG0 RN 12
+ValG1 RN 14
+ValGB0 RN 12
+ValGB1 RN 14
+
+Acc0 RN 4
+Acc1 RN 5
+Acc2 RN 6
+Acc3 RN 7
+
+Temp RN 7
+Step RN 6
+
+pInterBuf RN 8
+Counter RN 8
+r0x00ff00ff RN 9 ;// [0 255 0 255] where 255 is offset
+r0x0001fc00 RN 10 ;// [0 (16*255 - 16) 0 (16*255 - 16)]
+
+
+;// Declare inner loop registers
+ValCA RN 8
+ValDB RN 9
+ValGE RN 10
+ValHF RN 11
+r0x00140001 RN 12
+r0x0014fffb RN 14
+
+r0x00000200 RN 12
+r0x000000ff RN 12
+
+ M_STRD pDst, dstStep, ppDstArgs
+ MOV pDst, pInterBuf
+ MOV dstStep, #24
+
+ ;// Set up counter of format, [0] [0] [1 (height)] [8 (width)]
+ MOV Counter, #1
+ MOV Temp, #8
+ ADD Counter, Temp, Counter, LSL #8 ;// [0 0 H W]
+
+ LDR r0x00ff00ff, =0x00ff00ff ;// [0 255 0 255] 255 is offset to avoid negative results
+WidthLoop
+ M_STR pSrc, ppSrc
+ M_STR pDst, ppDst
+HeightLoop
+TwoRowsLoop
+ M_LDR ValC, [pSrc], srcStep ;// Load [c3 c2 c1 c0]
+ M_LDR ValD, [pSrc], srcStep ;// Load [d3 d2 d1 d0]
+ M_LDR ValE, [pSrc], srcStep ;// Load [e3 e2 e1 e0]
+ SUB pSrc, pSrc, srcStep, LSL #2
+ UXTAB16 ValC0, r0x00ff00ff, ValC ;// [0 c2 0 c0] + [0 255 0 255]
+ UXTAB16 ValC1, r0x00ff00ff, ValC, ROR #8 ;// [0 c3 0 c1] + [0 255 0 255]
+ LDR ValB, [pSrc] ;// Load [b3 b2 b1 b0]
+ UXTAB16 ValE0, r0x00ff00ff, ValE ;// [0 e2 0 e0] + [0 255 0 255]
+ UXTAB16 ValE1, r0x00ff00ff, ValE, ROR #8 ;// [0 e3 0 e1] + [0 255 0 255]
+ UXTAB16 ValCD0, ValC0, ValD ;// [0 c2 0 c0] + [0 255 0 255] + [0 d2 0 d0]
+ UXTAB16 ValCD1, ValC1, ValD, ROR #8 ;// [0 c3 0 c1] + [0 255 0 255] + [0 d3 0 d1]
+ UXTAB16 ValEB0, ValE0, ValB ;// [0 e2 0 e0] + [0 255 0 255] + [0 b2 0 b0]
+ RSB ValCD0, ValEB0, ValCD0, LSL #2 ;// 4*(Off+C+D) - (Off+B+E)
+
+ LDR ValD, [pSrc, srcStep, LSL #1] ;// Load [d3 d2 d1 d0]
+ UXTAB16 ValEB1, ValE1, ValB, ROR #8 ;// [0 e3 0 e1] + [0 255 0 255] + [0 b3 0 b1]
+ RSB ValCD1, ValEB1, ValCD1, LSL #2
+
+ UXTAB16 ValED0, ValE0, ValD ;// [0 e2 0 e0] + [0 255 0 255] + [0 d2 0 d0]
+ UXTAB16 ValED1, ValE1, ValD, ROR #8 ;// [0 e3 0 e1] + [0 255 0 255] + [0 d3 0 d1]
+ LDR ValF, [pSrc, srcStep, LSL #2] ;// Load [f3 f2 f1 f0]
+ M_LDR ValB, [pSrc], srcStep ;// Load [b3 b2 b1 b0]
+ ADD ValCD0, ValCD0, ValCD0, LSL #2 ;// 5 * [4*(Off+C+D) - (Off+B+E)]
+ ADD ValCD1, ValCD1, ValCD1, LSL #2
+ UXTAB16 ValCF1, ValC1, ValF, ROR #8 ;// [0 c3 0 c1] + [0 255 0 255] + [0 f3 0 f1]
+ UXTAB16 ValCF0, ValC0, ValF ;// [0 c2 0 c0] + [0 255 0 255] + [0 f2 0 f0]
+ RSB ValED1, ValCF1, ValED1, LSL #2
+
+ SUB ValA, pSrc, srcStep, LSL #1
+ LDR ValA, [ValA] ;// Load [a3 a2 a1 a0]
+ RSB ValED0, ValCF0, ValED0, LSL #2 ;// 4*(Off+E+D) - (Off+C+F)
+ ADD ValED1, ValED1, ValED1, LSL #2
+ ADD ValED0, ValED0, ValED0, LSL #2 ;// 5 * [4*(Off+E+D) - (Off+C+F)]
+ UXTAB16 ValA0, r0x00ff00ff, ValA ;// [0 a2 0 a0] + [0 255 0 255]
+ UXTAB16 ValA1, r0x00ff00ff, ValA, ROR #8 ;// [0 a3 0 a1] + [0 255 0 255]
+ UXTAB16 ValAF0, ValA0, ValF ;// [0 a2 0 a0] + [0 255 0 255] + [0 f2 0 f0]
+ UXTAB16 ValAF1, ValA1, ValF, ROR #8 ;// [0 a3 0 a1] + [0 255 0 255] + [0 f3 0 f1]
+ ADD Acc1, ValCD1, ValAF1
+
+ LDR ValG, [pSrc, srcStep, LSL #2] ;// Load [g3 g2 g1 g0]
+ ADD Acc0, ValCD0, ValAF0 ;// Acc0 = 16*Off + (A+F) + 20*(C+D) - 5*(B+E)
+ STR Acc1, [pDst, #4] ;// Store result & adjust pointer
+ M_STR Acc0, [pDst], dstStep ;// Store result & adjust pointer
+ UXTAB16 ValG0, r0x00ff00ff, ValG ;// [0 g2 0 g0] + [0 255 0 255]
+ UXTAB16 ValG1, r0x00ff00ff, ValG, ROR #8 ;// [0 g3 0 g1] + [0 255 0 255]
+ UXTAB16 ValGB0, ValG0, ValB ;// [0 g2 0 g0] + [0 255 0 255] + [0 b2 0 b0]
+ UXTAB16 ValGB1, ValG1, ValB, ROR #8 ;// [0 g3 0 g1] + [0 255 0 255] + [0 b3 0 b1]
+ ADD Acc2, ValED0, ValGB0 ;// Acc2 = 16*Off + (B+G) + 20*(D+E) - 5*(C+F)
+ ADD Acc3, ValED1, ValGB1
+
+ STR Acc3, [pDst, #4] ;// Store result & adjust pointer
+ M_STR Acc2, [pDst], dstStep ;// Store result & adjust pointer
+
+ SUBS Counter, Counter, #1 << 8 ;// Loop till height is 10
+ ADD pSrc, pSrc, srcStep, LSL #1
+ BPL HeightLoop
+
+ M_LDR pSrc, ppSrc
+ M_LDR pDst, ppDst
+ ADDS Counter, Counter, #(1 << 8)-4 ;// Loop till width is 12
+ ADD pSrc, pSrc, #4
+ ADD pDst, pDst, #8
+ ADD Counter, Counter, #1<<8
+ BPL WidthLoop
+
+ ;//
+ ;// Horizontal interpolation using multiplication
+ ;//
+
+ SUB pSrc, pDst, #24
+ MOV srcStep, #24
+ M_LDRD pDst, dstStep, ppDstArgs
+
+ MOV Counter, #4
+ LDR r0x0014fffb, =0x0014fffb
+ LDR r0x00140001, =0x00140001
+
+HeightLoop1
+ M_STR Counter, pCounter
+
+
+ LDR ValCA, [pSrc], #4 ;// Load [0 c 0 a]
+ LDR ValDB, [pSrc], #4 ;// Load [0 d 0 b]
+ LDR ValGE, [pSrc], #4 ;// Load [0 g 0 e]
+ LDR ValHF, [pSrc], #4 ;// Load [0 h 0 f]
+
+ ;// Acc0 = smuad ([0 20 0 1], add([0 c 0 a] + [0 d 0 f])) - (5 * (b + e))
+ ;// Acc1 = smuad ([0 20 0 1], add([0 e 0 g] + [0 d 0 b])) - (5 * (c + f))
+ ;// Acc2 = smuad ([0 1 0 20], add([0 c 0 e] + [0 h 0 f])) - (5 * (d + g))
+ ;// Acc3 = smuad ([0 20 0 1], add([0 d 0 f] + [0 i 0 g])) - (5 * (e + h))
+ SMUAD Acc0, ValCA, r0x00140001 ;// Acc0 = [0 c 0 a] * [0 20 0 1]
+ SMUAD Acc1, ValDB, r0x00140001 ;// Acc1 = [0 c 0 a] * [0 20 0 1]
+ SMUADX Acc2, ValGE, r0x0014fffb ;// Acc2 = [0 g 0 e] * [0 20 0 -5]
+ SMUAD Acc3, ValGE, r0x0014fffb ;// Acc3 = [0 g 0 e] * [0 20 0 -5]
+
+ SMLAD Acc0, ValDB, r0x0014fffb, Acc0 ;// Acc0 += [0 d 0 b] * [0 20 0 -5]
+ SMLADX Acc1, ValGE, r0x00140001, Acc1 ;// Acc1 += [0 g 0 e] * [0 20 0 1]
+ SMLADX Acc2, ValHF, r0x00140001, Acc2 ;// Acc2 += [0 h 0 f] * [0 20 0 1]
+ SMLADX Acc3, ValHF, r0x0014fffb, Acc3 ;// Acc3 += [0 h 0 f] * [0 20 0 -5]
+
+ SMLABB Acc0, ValGE, r0x0014fffb, Acc0 ;// Acc0 += [0 g 0 e] * [0 0 0 -5]
+ SMLATB Acc1, ValCA, r0x0014fffb, Acc1 ;// Acc1 += [0 d 0 b] * [0 0 0 -5]
+ SMLATB Acc2, ValCA, r0x00140001, Acc2 ;// Acc2 += [0 c 0 a] * [0 0 0 1]
+ SMLATB Acc3, ValDB, r0x00140001, Acc3 ;// Acc3 += [0 c 0 a] * [0 0 0 1]
+
+ LDRH ValCA, [pSrc], #8 ;// 8 = srcStep - 16
+ SMLABB Acc0, ValHF, r0x00140001, Acc0 ;// Acc0 += [0 h 0 f] * [0 0 0 1]
+ SMLABB Acc1, ValHF, r0x0014fffb, Acc1 ;// Acc1 += [0 h 0 f] * [0 0 0 -5]
+ SMLATB Acc2, ValDB, r0x0014fffb, Acc2 ;// Acc2 += [0 d 0 b] * [0 0 0 -5]
+ SMLABB Acc3, ValCA, r0x00140001, Acc3 ;// Acc3 += [0 d 0 b] * [0 0 0 1]
+
+ LDR r0x0001fc00, =0x0001fc00 ;// (0xff * 16 * 32) - 512
+ SUB Acc0, Acc0, r0x0001fc00
+ SUB Acc1, Acc1, r0x0001fc00
+ SUB Acc2, Acc2, r0x0001fc00
+ SUB Acc3, Acc3, r0x0001fc00
+
+ USAT Acc0, #18, Acc0
+ USAT Acc1, #18, Acc1
+ USAT Acc2, #18, Acc2
+ USAT Acc3, #18, Acc3
+
+ MOV Acc0, Acc0, LSR #10
+ MOV Acc1, Acc1, LSR #10
+ MOV Acc2, Acc2, LSR #10
+ MOV Acc3, Acc3, LSR #10
+
+ M_LDR Counter, pCounter
+ ORR Acc0, Acc0, Acc1, LSL #8
+ ORR Acc2, Acc2, Acc3, LSL #8
+ SUBS Counter, Counter, #1
+ ORR Acc0, Acc0, Acc2, LSL #16
+ M_STR Acc0, [pDst], dstStep
+ BGT HeightLoop1
+End
+ SUB pDst, pDst, dstStep, LSL #2
+ SUB pSrc, pSrc, srcStep, LSL #2
+
+ M_END
+
+ ENDIF
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
new file mode 100644
index 0000000..6690ced
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
@@ -0,0 +1,239 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ EXPORT armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+
+DEBUG_ON SETL {FALSE}
+
+
+ IF ARM1136JS
+
+;// Function:
+;// armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+;//
+;// Implements horizontal interpolation for a block of size 4x4. Input and output should
+;// be aligned.
+;//
+;// Registers used as input for this function
+;// r0,r1,r2,r3 where r0,r2 input pointer and r1,r3 corresponding step size
+;//
+;// Registers preserved for top level function
+;// r0,r1,r2,r3,r4,r5,r6,r14
+;//
+;// Registers modified by the function
+;// r7,r8,r9,r10,r11,r12
+;//
+;// Output registers
+;// None. Function will preserve r0-r3
+
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 2
+dstStep RN 3
+
+;// Declare inner loop registers
+Acc0 RN 4
+Acc1 RN 5
+Acc2 RN 6
+Acc3 RN 7
+
+ValA RN 4
+ValB RN 5
+ValC RN 6
+ValD RN 7
+ValE RN 8
+ValF RN 9
+ValG RN 12
+ValH RN 14
+ValI RN 1
+
+Temp1 RN 3
+Temp2 RN 1
+Temp3 RN 12
+Temp4 RN 7
+Temp5 RN 5
+r0x0fe00fe0 RN 3 ;// [0 (16*255 - 16) 0 (16*255 - 16)]
+r0x00ff00ff RN 10 ;// [0 255 0 255] where 255 is offset
+Counter RN 11
+
+Height RN 3
+
+ M_ALLOC4 pDstStep, 4
+ M_ALLOC4 pSrcStep, 4
+
+ ;// Function header
+ M_START armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe, r6
+
+ MOV Counter, #2
+ M_STR dstStep, pDstStep
+ M_STR srcStep, pSrcStep
+ LDR r0x00ff00ff, =0x00ff00ff ;// [0 255 0 255] 255 is offset to avoid negative results
+
+NextTwoRowsLoop
+ LDR ValD, [pSrc, srcStep] ;// Load row 1 [d1 c1 b1 a1]
+ LDR ValA, [pSrc], #4 ;// Load row 0 [d0 c0 b0 a0]
+ LDR ValH, [pSrc, srcStep] ;// Load [h1 g1 f1 e1]
+ LDR ValE, [pSrc], #4 ;// Load [h0 g0 f0 e0]
+ LDRB Temp2, [pSrc, srcStep] ;// Load row 1 [l1 k1 j1 i1]
+ LDRB Temp1, [pSrc], #-8 ;// Load row 0 [l0 k0 j0 i0]
+
+ PKHBT ValB, ValA, ValD, LSL #16 ;// [b1 a1 b0 a0]
+ PKHTB ValD, ValD, ValA, ASR #16 ;// [d1 c1 d0 c0]
+ UXTAB16 ValA, r0x00ff00ff, ValB ;// [00 a1 00 a0] + [0 255 0 255]
+ UXTAB16 ValC, r0x00ff00ff, ValD ;// [00 c1 00 c0] + [0 255 0 255]
+ PKHBT ValI, Temp1, Temp2, LSL #16 ;// [00 i1 00 i0]
+ PKHBT ValF, ValE, ValH, LSL #16 ;// [f1 e1 f0 e0]
+ PKHTB ValH, ValH, ValE, ASR #16 ;// [h1 g1 h0 g0]
+ UXTAB16 ValE, r0x00ff00ff, ValF ;// [00 e1 00 e0] + [0 255 0 255]
+
+ ;// Calculate Acc0
+ ;// Acc0 = a - 5*b + 20*c + 20*d - 5*e + f
+ UXTAB16 Temp1, ValC, ValD, ROR #8
+ UXTAB16 Temp3, ValE, ValB, ROR #8
+ RSB Temp1, Temp3, Temp1, LSL #2
+ UXTAB16 Acc0, ValA, ValF, ROR #8
+ ADD Temp1, Temp1, Temp1, LSL #2
+ ADD Acc0, Acc0, Temp1
+
+ ;// Calculate Acc1
+ ;// Acc1 = b - 5*c + 20*d + 20*e - 5*f + g
+ UXTAB16 Temp1, ValE, ValD, ROR #8
+ UXTAB16 Temp3, ValC, ValF, ROR #8
+ RSB Temp1, Temp3, Temp1, LSL #2
+ UXTAB16 ValG, r0x00ff00ff, ValH ;// [00 g1 00 g0] + [0 255 0 255]
+ ADD Temp1, Temp1, Temp1, LSL #2
+ UXTAB16 Acc1, ValG, ValB, ROR #8
+ ADD Acc1, Acc1, Temp1
+
+ LDR r0x0fe00fe0, =0x0fe00fe0 ;// 0x0fe00fe0 = (16 * Offset) - 16 where Offset is 255
+ UXTAB16 Acc2, ValC, ValH, ROR #8
+ ADD ValI, r0x00ff00ff, ValI ;// [00 i1 00 i0] + [0 255 0 255]
+ UQSUB16 Acc0, Acc0, r0x0fe00fe0
+ UQSUB16 Acc1, Acc1, r0x0fe00fe0
+ USAT16 Acc0, #13, Acc0
+ USAT16 Acc1, #13, Acc1
+
+ ;// Calculate Acc2
+ ;// Acc2 = c - 5*d + 20*e + 20*f - 5*g + h
+ UXTAB16 Temp1, ValG, ValD, ROR #8
+ UXTAB16 Acc3, ValI, ValD, ROR #8
+ UXTAB16 Temp2, ValE, ValF, ROR #8
+ AND Acc1, r0x00ff00ff, Acc1, LSR #5
+ AND Acc0, r0x00ff00ff, Acc0, LSR #5
+ ORR Acc0, Acc0, Acc1, LSL #8
+ RSB Temp5, Temp1, Temp2, LSL #2
+ UXTAB16 Temp2, ValG, ValF, ROR #8
+ ADD Temp5, Temp5, Temp5, LSL #2
+ ADD Acc2, Acc2, Temp5
+
+ ;// Calculate Acc3
+ ;// Acc3 = d - 5*e + 20*f + 20*g - 5*h + i
+ UXTAB16 Temp5, ValE, ValH, ROR #8
+ RSB Temp5, Temp5, Temp2, LSL #2
+ LDR r0x0fe00fe0, =0x0fe00fe0
+ ADD Temp5, Temp5, Temp5, LSL #2
+ ADD Acc3, Acc3, Temp5
+
+ UQSUB16 Acc3, Acc3, r0x0fe00fe0
+ UQSUB16 Acc2, Acc2, r0x0fe00fe0
+ USAT16 Acc3, #13, Acc3
+ USAT16 Acc2, #13, Acc2
+
+ M_LDR dstStep, pDstStep
+ AND Acc3, r0x00ff00ff, Acc3, LSR #5
+ AND Acc2, r0x00ff00ff, Acc2, LSR #5
+ ORR Acc2, Acc2, Acc3, LSL #8
+
+ SUBS Counter, Counter, #1
+ M_LDR srcStep, pSrcStep
+ PKHBT Acc1, Acc0, Acc2, LSL #16
+ M_STR Acc1, [pDst], dstStep ;// Store result1
+ PKHTB Acc2, Acc2, Acc0, ASR #16
+ M_STR Acc2, [pDst], dstStep ;// Store result2
+ ADD pSrc, pSrc, srcStep, LSL #1
+
+ BGT NextTwoRowsLoop
+End
+ SUB pDst, pDst, dstStep, LSL #2
+ SUB pSrc, pSrc, srcStep, LSL #2
+
+ M_END
+
+ ENDIF
+
+ END
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
new file mode 100644
index 0000000..007cd0d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
@@ -0,0 +1,185 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ EXPORT armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+
+
+
+ IF ARM1136JS
+
+ ;// Function header
+
+ ;// Function:
+ ;// armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ ;//
+ ;// Implements vertical interpolation for a block of size 4x4. Input and output should
+ ;// be aligned.
+ ;//
+ ;// Registers used as input for this function
+ ;// r0,r1,r2,r3 where r0,r2 input pointer and r1,r3 corresponding step size
+ ;//
+ ;// Registers preserved for top level function
+ ;// r0,r1,r2,r3,r4,r5,r6,r14
+ ;//
+ ;// Registers modified by the function
+ ;// r7,r8,r9,r10,r11,r12
+ ;//
+ ;// Output registers
+ ;// None. Function will preserve r0-r3
+ M_START armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe, r6
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 2
+dstStep RN 3
+
+;// Declare inner loop registers
+ValA RN 5
+ValA0 RN 4
+ValA1 RN 5
+ValAF0 RN 4
+ValAF1 RN 5
+
+ValB RN 11
+
+ValC RN 5
+ValC0 RN 4
+ValC1 RN 5
+ValCD0 RN 12
+ValCD1 RN 14
+ValCF0 RN 4
+ValCF1 RN 5
+
+ValD RN 10
+
+ValE RN 7
+ValE0 RN 6
+ValE1 RN 7
+ValEB0 RN 10
+ValEB1 RN 11
+ValED0 RN 6
+ValED1 RN 7
+
+ValF RN 10
+
+ValG RN 14
+ValG0 RN 12
+ValG1 RN 14
+ValGB0 RN 12
+ValGB1 RN 14
+
+Acc0 RN 4
+Acc1 RN 5
+Acc2 RN 6
+Acc3 RN 7
+
+Temp RN 7
+Height RN 3
+Step RN 6
+
+Counter RN 8
+r0x00ff00ff RN 9 ;// [0 255 0 255] where 255 is offset
+r0x0fe00fe0 RN 10 ;// [0 (16*255 - 16) 0 (16*255 - 16)]
+
+
+ LDR r0x00ff00ff, =0x00ff00ff ;// [0 255 0 255] 255 is offset to avoid negative results
+ MOV Counter, #2
+
+TwoRowsLoop
+ M_LDR ValC, [pSrc], srcStep ;// Load [c3 c2 c1 c0]
+ M_LDR ValD, [pSrc], srcStep ;// Load [d3 d2 d1 d0]
+ M_LDR ValE, [pSrc], srcStep ;// Load [e3 e2 e1 e0]
+ SUB pSrc, pSrc, srcStep, LSL #2
+ LDR ValB, [pSrc] ;// Load [b3 b2 b1 b0]
+ UXTAB16 ValC0, r0x00ff00ff, ValC ;// [0 c2 0 c0] + [0 255 0 255]
+ UXTAB16 ValC1, r0x00ff00ff, ValC, ROR #8 ;// [0 c3 0 c1] + [0 255 0 255]
+
+ UXTAB16 ValE0, r0x00ff00ff, ValE ;// [0 e2 0 e0] + [0 255 0 255]
+ UXTAB16 ValE1, r0x00ff00ff, ValE, ROR #8 ;// [0 e3 0 e1] + [0 255 0 255]
+ UXTAB16 ValCD0, ValC0, ValD ;// [0 c2 0 c0] + [0 255 0 255] + [0 d2 0 d0]
+ UXTAB16 ValCD1, ValC1, ValD, ROR #8 ;// [0 c3 0 c1] + [0 255 0 255] + [0 d3 0 d1]
+ UXTAB16 ValEB0, ValE0, ValB ;// [0 e2 0 e0] + [0 255 0 255] + [0 b2 0 b0]
+ RSB ValCD0, ValEB0, ValCD0, LSL #2 ;// 4*(Off+C+D) - (Off+B+E)
+
+ LDR ValD, [pSrc, srcStep, LSL #1] ;// Load [d3 d2 d1 d0]
+ UXTAB16 ValEB1, ValE1, ValB, ROR #8 ;// [0 e3 0 e1] + [0 255 0 255] + [0 b3 0 b1]
+ RSB ValCD1, ValEB1, ValCD1, LSL #2
+ ;// One cycle stall
+ UXTAB16 ValED0, ValE0, ValD ;// [0 e2 0 e0] + [0 255 0 255] + [0 d2 0 d0]
+ UXTAB16 ValED1, ValE1, ValD, ROR #8 ;// [0 e3 0 e1] + [0 255 0 255] + [0 d3 0 d1]
+
+ LDR ValF, [pSrc, srcStep, LSL #2] ;// Load [f3 f2 f1 f0]
+ M_LDR ValB, [pSrc], srcStep ;// Load [b3 b2 b1 b0]
+ ADD ValCD0, ValCD0, ValCD0, LSL #2 ;// 5 * [4*(Off+C+D) - (Off+B+E)]
+ ADD ValCD1, ValCD1, ValCD1, LSL #2
+ UXTAB16 ValCF1, ValC1, ValF, ROR #8 ;// [0 c3 0 c1] + [0 255 0 255] + [0 f3 0 f1]
+ UXTAB16 ValCF0, ValC0, ValF ;// [0 c2 0 c0] + [0 255 0 255] + [0 f2 0 f0]
+ RSB ValED1, ValCF1, ValED1, LSL #2
+
+ SUB ValA, pSrc, srcStep, LSL #1
+ LDR ValA, [ValA] ;// Load [a3 a2 a1 a0]
+ RSB ValED0, ValCF0, ValED0, LSL #2 ;// 4*(Off+E+D) - (Off+C+F)
+ ADD ValED1, ValED1, ValED1, LSL #2
+ ADD ValED0, ValED0, ValED0, LSL #2 ;// 5 * [4*(Off+E+D) - (Off+C+F)]
+ UXTAB16 ValA0, r0x00ff00ff, ValA ;// [0 a2 0 a0] + [0 255 0 255]
+ UXTAB16 ValA1, r0x00ff00ff, ValA, ROR #8 ;// [0 a3 0 a1] + [0 255 0 255]
+ UXTAB16 ValAF0, ValA0, ValF ;// [0 a2 0 a0] + [0 255 0 255] + [0 f2 0 f0]
+ UXTAB16 ValAF1, ValA1, ValF, ROR #8 ;// [0 a3 0 a1] + [0 255 0 255] + [0 f3 0 f1]
+
+ LDR r0x0fe00fe0, =0x0fe00fe0 ;// [0 255 0 255] 255 is offset to avoid negative results
+ ADD Acc1, ValCD1, ValAF1
+
+ LDR ValG, [pSrc, srcStep, LSL #2] ;// Load [g3 g2 g1 g0]
+ ADD Acc0, ValCD0, ValAF0 ;// Acc0 = 16*Off + (A+F) + 20*(C+D) - 5*(B+E)
+ UQSUB16 Acc1, Acc1, r0x0fe00fe0 ;// Acc1 -= (16*Off - 16)
+ UQSUB16 Acc0, Acc0, r0x0fe00fe0
+ UXTAB16 ValG0, r0x00ff00ff, ValG ;// [0 g2 0 g0] + [0 255 0 255]
+ UXTAB16 ValG1, r0x00ff00ff, ValG, ROR #8 ;// [0 g3 0 g1] + [0 255 0 255]
+ UXTAB16 ValGB0, ValG0, ValB ;// [0 g2 0 g0] + [0 255 0 255] + [0 b2 0 b0]
+ UXTAB16 ValGB1, ValG1, ValB, ROR #8 ;// [0 g3 0 g1] + [0 255 0 255] + [0 b3 0 b1]
+ ADD Acc2, ValED0, ValGB0 ;// Acc2 = 16*Off + (B+G) + 20*(D+E) - 5*(C+F)
+ ADD Acc3, ValED1, ValGB1
+ UQSUB16 Acc3, Acc3, r0x0fe00fe0 ;// Acc3 -= (16*Off - 16)
+ UQSUB16 Acc2, Acc2, r0x0fe00fe0
+ USAT16 Acc1, #13, Acc1 ;// Saturate to 8+5 = 13 bits
+ USAT16 Acc0, #13, Acc0
+ USAT16 Acc3, #13, Acc3
+ USAT16 Acc2, #13, Acc2
+ AND Acc1, r0x00ff00ff, Acc1, LSR #5 ;// [0 a3 0 a1]
+ AND Acc0, r0x00ff00ff, Acc0, LSR #5 ;// [0 a2 0 a0]
+ ORR Acc0, Acc0, Acc1, LSL #8 ;// [a3 a2 a1 a0]
+ AND Acc3, r0x00ff00ff, Acc3, LSR #5 ;// [0 b3 0 b1]
+ AND Acc2, r0x00ff00ff, Acc2, LSR #5 ;// [0 b2 0 b0]
+
+ M_STR Acc0, [pDst], dstStep ;// Store result & adjust pointer
+ ORR Acc2, Acc2, Acc3, LSL #8 ;// [b3 b2 b1 b0]
+ M_STR Acc2, [pDst], dstStep ;// Store result & adjust pointer
+ ADD pSrc, pSrc, srcStep, LSL #1
+
+ SUBS Counter, Counter, #1
+ BGT TwoRowsLoop
+End
+ SUB pDst, pDst, dstStep, LSL #2
+ SUB pSrc, pSrc, srcStep, LSL #2
+
+ M_END
+
+ ENDIF
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
new file mode 100644
index 0000000..b1ad17c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
@@ -0,0 +1,273 @@
+;//
+;//
+;// File Name: armVCM4P10_Interpolate_Chroma_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ IF ARM1136JS
+
+;// input registers
+
+pSrc RN 0
+iSrcStep RN 1
+pDst RN 2
+iDstStep RN 3
+iWidth RN 4
+iHeight RN 5
+dx RN 6
+dy RN 7
+
+
+;// local variable registers
+temp RN 11
+r0x20 RN 12
+tmp0x20 RN 14
+return RN 0
+dxPlusdy RN 10
+EightMinusdx RN 8
+EightMinusdy RN 9
+dxEightMinusdx RN 8
+BACoeff RN 6
+DCCoeff RN 7
+
+iDstStepx2MinusWidth RN 8
+iSrcStepx2MinusWidth RN 9
+iSrcStep1 RN 10
+
+pSrc1 RN 1
+pSrc2 RN 8
+pDst1 RN 8
+pDst2 RN 12
+
+pix00 RN 8
+pix01 RN 9
+pix10 RN 10
+pix11 RN 11
+
+Out0100 RN 8
+Out1110 RN 10
+
+x00 RN 8
+x01 RN 10
+x02 RN 12
+x10 RN 9
+x11 RN 11
+x12 RN 14
+x20 RN 10
+x21 RN 12
+x22 RN 14
+
+x01x00 RN 8
+x02x01 RN 10
+x11x10 RN 9
+x12x11 RN 11
+x21x20 RN 10
+x22x21 RN 12
+
+OutRow00 RN 12
+OutRow01 RN 14
+OutRow10 RN 10
+OutRow11 RN 12
+
+OutRow0100 RN 12
+OutRow1110 RN 12
+
+;//-----------------------------------------------------------------------------------------------
+;// armVCM4P10_Interpolate_Chroma_asm starts
+;//-----------------------------------------------------------------------------------------------
+
+ ;// Write function header
+ M_START armVCM4P10_Interpolate_Chroma, r11
+
+ ;// Define stack arguments
+ M_ARG Width, 4
+ M_ARG Height, 4
+ M_ARG Dx, 4
+ M_ARG Dy, 4
+
+ ;// Load argument from the stack
+ ;// M_STALL ARM1136JS=4
+
+ M_LDR iWidth, Width
+ M_LDR iHeight, Height
+ M_LDR dx, Dx
+ M_LDR dy, Dy
+
+ ;// EightMinusdx = 8 - dx
+ ;// EightMinusdy = 8 - dy
+
+ ;// ACoeff = EightMinusdx * EightMinusdy
+ ;// BCoeff = dx * EightMinusdy
+ ;// CCoeff = EightMinusdx * dy
+ ;// DCoeff = dx * dy
+
+ ADD pSrc1, pSrc, iSrcStep
+ SUB temp, iWidth, #1
+ RSB EightMinusdx, dx, #8
+ RSB EightMinusdy, dy, #8
+ CMN dx,dy
+ ADD dxEightMinusdx, EightMinusdx, dx, LSL #16
+ ORR iWidth, iWidth, temp, LSL #16
+
+ ;// Packed Coeffs.
+
+ MUL BACoeff, dxEightMinusdx, EightMinusdy
+ MUL DCCoeff, dxEightMinusdx, dy
+
+
+ ;// Checking either of dx and dy being non-zero
+
+ BEQ MVIsZero
+
+;// Pixel layout:
+;//
+;// x00 x01 x02
+;// x10 x11 x12
+;// x20 x21 x22
+
+;// If fractionl mv is not (0, 0)
+
+OuterLoopMVIsNotZero
+
+InnerLoopMVIsNotZero
+
+ LDRB x00, [pSrc, #+0]
+ LDRB x10, [pSrc1, #+0]
+ LDRB x01, [pSrc, #+1]
+ LDRB x11, [pSrc1, #+1]
+ LDRB x02, [pSrc, #+2]!
+ LDRB x12, [pSrc1, #+2]!
+
+ ORR x01x00, x00, x01, LSL #16
+ ;// M_STALL ARM1136JS=1
+ ORR x02x01, x01, x02, LSL #16
+ MOV r0x20, #32
+ ORR x11x10, x10, x11, LSL #16
+ ORR x12x11, x11, x12, LSL #16
+
+ SMLAD x01x00, x01x00, BACoeff, r0x20
+ SMLAD x02x01, x02x01, BACoeff, r0x20
+
+ ;// iWidth packed with MSB (top 16 bits)
+ ;// as inner loop counter value i.e
+ ;// (iWidth -1) and LSB (lower 16 bits)
+ ;// as original width
+
+ SUBS iWidth, iWidth, #1<<17
+
+ SMLAD OutRow00, x11x10, DCCoeff, x01x00
+ SMLAD OutRow01, x12x11, DCCoeff, x02x01
+
+ RSB pSrc2, pSrc, pSrc1, LSL #1
+
+ MOV OutRow00, OutRow00, LSR #6
+ MOV OutRow01, OutRow01, LSR #6
+
+ LDRB x20,[pSrc2, #-2]
+
+ ORR OutRow0100, OutRow00, OutRow01, LSL #8
+ STRH OutRow0100, [pDst], #2
+
+ LDRB x21,[pSrc2, #-1]
+ LDRB x22,[pSrc2, #+0]
+
+ ADD pDst1, pDst, iDstStep
+
+ ;// M_STALL ARM1136JS=1
+
+ ORR x21x20, x20, x21, LSL #16
+ ORR x22x21, x21, x22, LSL #16
+
+ MOV tmp0x20, #32
+
+ ;// Reusing the packed data x11x10 and x12x11
+
+ SMLAD x11x10, x11x10, BACoeff, tmp0x20
+ SMLAD x12x11, x12x11, BACoeff, tmp0x20
+ SMLAD OutRow10, x21x20, DCCoeff, x11x10
+ SMLAD OutRow11, x22x21, DCCoeff, x12x11
+
+ MOV OutRow10, OutRow10, LSR #6
+ MOV OutRow11, OutRow11, LSR #6
+
+ ;// M_STALL ARM1136JS=1
+
+ ORR OutRow1110, OutRow10, OutRow11, LSL #8
+
+ STRH OutRow1110, [pDst1, #-2]
+
+ BGT InnerLoopMVIsNotZero
+
+ SUBS iHeight, iHeight, #2
+ ADD iWidth, iWidth, #1<<16
+ RSB iDstStepx2MinusWidth, iWidth, iDstStep, LSL #1
+ SUB iSrcStep1, pSrc1, pSrc
+ SUB temp, iWidth, #1
+ RSB iSrcStepx2MinusWidth, iWidth, iSrcStep1, LSL #1
+ ADD pDst, pDst, iDstStepx2MinusWidth
+ ADD pSrc1, pSrc1, iSrcStepx2MinusWidth
+ ADD pSrc, pSrc, iSrcStepx2MinusWidth
+ ORR iWidth, iWidth, temp, LSL #16
+ BGT OuterLoopMVIsNotZero
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+;// If fractionl mv is (0, 0)
+
+MVIsZero
+ ;// M_STALL ARM1136JS=4
+OuterLoopMVIsZero
+
+InnerLoopMVIsZero
+
+ LDRB pix00, [pSrc], #+1
+ LDRB pix01, [pSrc], #+1
+ LDRB pix10, [pSrc1], #+1
+ LDRB pix11, [pSrc1], #+1
+
+ ADD pDst2, pDst, iDstStep
+ SUBS iWidth, iWidth, #1<<17
+
+ ORR Out0100, pix00, pix01, LSL #8
+ ORR Out1110, pix10, pix11, LSL #8
+
+ STRH Out0100, [pDst], #2
+ STRH Out1110, [pDst2], #2
+
+ BGT InnerLoopMVIsZero
+
+ SUBS iHeight, iHeight, #2
+ ADD iWidth, iWidth, #1<<16
+ RSB iDstStepx2MinusWidth, iWidth, iDstStep, LSL #1
+ SUB iSrcStep1, pSrc1, pSrc
+ SUB temp, iWidth, #1
+ RSB iSrcStepx2MinusWidth, iWidth, iSrcStep1, LSL #1
+ ADD pDst, pDst, iDstStepx2MinusWidth
+ ADD pSrc1, pSrc1, iSrcStepx2MinusWidth
+ ADD pSrc, pSrc, iSrcStepx2MinusWidth
+ ORR iWidth, iWidth, temp, LSL #16
+ BGT OuterLoopMVIsZero
+ MOV return, #OMX_Sts_NoErr
+ M_END
+
+ ENDIF ;// ARM1136JS
+
+
+ END
+
+;//-----------------------------------------------------------------------------------------------
+;// armVCM4P10_Interpolate_Chroma_asm ends
+;//-----------------------------------------------------------------------------------------------
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_QuantTables_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_QuantTables_s.s
new file mode 100644
index 0000000..f962f70
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_QuantTables_s.s
@@ -0,0 +1,74 @@
+;//
+;//
+;// File Name: armVCM4P10_QuantTables_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;// Description:
+;// This file contains quantization tables
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+
+ EXPORT armVCM4P10_MFMatrixQPModTable
+ EXPORT armVCM4P10_QPDivIntraTable
+ EXPORT armVCM4P10_QPDivPlusOneTable
+
+;//--------------------------------------------------------------
+;// This table contains armVCM4P10_MFMatrix [iQP % 6][0] entires,
+;// for values of iQP from 0 to 51 (inclusive).
+;//--------------------------------------------------------------
+
+ M_TABLE armVCM4P10_MFMatrixQPModTable
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+
+;//---------------------------------------------------------------
+;// This table contains ARM_M4P10_Q_OFFSET + 1 + (iQP / 6) values,
+;// for values of iQP from 0 to 51 (inclusive).
+;//---------------------------------------------------------------
+
+ M_TABLE armVCM4P10_QPDivPlusOneTable
+ DCB 16, 16, 16, 16, 16, 16
+ DCB 17, 17, 17, 17, 17, 17
+ DCB 18, 18, 18, 18, 18, 18
+ DCB 19, 19, 19, 19, 19, 19
+ DCB 20, 20, 20, 20, 20, 20
+ DCB 21, 21, 21, 21, 21, 21
+ DCB 22, 22, 22, 22, 22, 22
+ DCB 23, 23, 23, 23, 23, 23
+ DCB 24, 24, 24, 24, 24, 24
+
+;//------------------------------------------------------------------
+;// This table contains (1 << QbitsPlusOne) / 3 Values (Intra case) ,
+;// for values of iQP from 0 to 51 (inclusive).
+;//------------------------------------------------------------------
+
+ M_TABLE armVCM4P10_QPDivIntraTable, 2
+ DCD 21845, 21845, 21845, 21845, 21845, 21845
+ DCD 43690, 43690, 43690, 43690, 43690, 43690
+ DCD 87381, 87381, 87381, 87381, 87381, 87381
+ DCD 174762, 174762, 174762, 174762, 174762, 174762
+ DCD 349525, 349525, 349525, 349525, 349525, 349525
+ DCD 699050, 699050, 699050, 699050, 699050, 699050
+ DCD 1398101, 1398101, 1398101, 1398101, 1398101, 1398101
+ DCD 2796202, 2796202, 2796202, 2796202, 2796202, 2796202
+ DCD 5592405, 5592405, 5592405, 5592405, 5592405, 5592405
+
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
new file mode 100644
index 0000000..241d188
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
@@ -0,0 +1,407 @@
+;//
+;//
+;// File Name: armVCM4P10_TransformResidual4x4_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// Description:
+;// Transform Residual 4x4 Coefficients
+;//
+;//
+
+
+;// Include standard headers
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+;// Import symbols required from other files
+;// (For example tables)
+
+
+
+
+;// Set debugging level
+;//DEBUG_ON SETL {TRUE}
+
+
+
+;// Guarding implementation by the processor name
+
+ IF ARM1136JS
+
+;//Input Registers
+pDst RN 0
+pSrc RN 1
+
+;//Output Registers
+
+
+;//Local Scratch Registers
+
+;// Packed Input pixels
+in00 RN 2 ;// Src[0] & Src[1]
+in02 RN 3 ;// Src[2] & Src[3]
+in10 RN 4 ;// Src[4] & Src[5]
+in12 RN 5 ;// Src[6] & Src[7]
+in20 RN 6 ;// Src[8] & Src[9]
+in22 RN 7 ;// Src[10] & Src[11]
+in30 RN 8 ;// Src[12] & Src[13]
+in32 RN 9 ;// Src[14] & Src[15]
+
+;// Transpose for Row operations (Rows to cols)
+trRow00 RN 2
+trRow10 RN 10
+trRow02 RN 3
+trRow12 RN 5
+trRow20 RN 11
+trRow30 RN 12
+trRow32 RN 14
+trRow22 RN 7
+
+;// Intermediate calculations
+e0 RN 4
+e1 RN 6
+e2 RN 8
+e3 RN 9
+constZero RN 1
+
+;// Row operated pixels
+rowOp00 RN 2
+rowOp10 RN 10
+rowOp20 RN 11
+rowOp30 RN 12
+rowOp02 RN 3
+rowOp12 RN 5
+rowOp22 RN 7
+rowOp32 RN 14
+
+;// Transpose for colulmn operations
+trCol00 RN 2
+trCol02 RN 3
+trCol10 RN 4
+trCol12 RN 5
+trCol20 RN 6
+trCol22 RN 7
+trCol30 RN 8
+trCol32 RN 9
+
+;// Intermediate calculations
+g0 RN 10
+g1 RN 11
+g2 RN 12
+g3 RN 14
+
+;// Coloumn operated pixels
+colOp00 RN 2
+colOp02 RN 3
+colOp10 RN 4
+colOp12 RN 5
+colOp20 RN 6
+colOp22 RN 7
+colOp30 RN 8
+colOp32 RN 9
+
+
+temp1 RN 10 ;// Temporary scratch varaibles
+const1 RN 11
+const2 RN 12
+mask RN 14
+
+;// Output pixels
+out00 RN 2
+out02 RN 3
+out10 RN 4
+out12 RN 5
+out20 RN 6
+out22 RN 7
+out30 RN 8
+out32 RN 9
+
+
+
+ ;// Allocate stack memory required by the function
+
+
+ ;// Write function header
+ M_START armVCM4P10_TransformResidual4x4,r11
+
+ ;******************************************************************
+ ;// The strategy used in implementing the transform is as follows:*
+ ;// Load the 4x4 block into 8 registers *
+ ;// Transpose the 4x4 matrix *
+ ;// Perform the row operations (on columns) using SIMD *
+ ;// Transpose the 4x4 result matrix *
+ ;// Perform the coloumn operations *
+ ;// Store the 4x4 block at one go *
+ ;******************************************************************
+
+ ;// Load all the 4x4 pixels
+
+ LDMIA pSrc,{in00,in02,in10,in12,in20,in22,in30,in32}
+
+ MOV constZero,#0 ;// Used to right shift by 1
+ ;LDR constZero,=0x00000000
+
+ ;*****************************************************************
+ ;//
+ ;// Transpose the matrix inorder to perform row ops as coloumn ops
+ ;// Input: in[][] = original matrix
+ ;// Output: trRow[][]= transposed matrix
+ ;// Step1: Obtain the LL part of the transposed matrix
+ ;// Step2: Obtain the HL part
+ ;// step3: Obtain the LH part
+ ;// Step4: Obtain the HH part
+ ;//
+ ;*****************************************************************
+
+ ;// LL 2x2 transposed matrix
+ ;// d0 d1 - -
+ ;// d4 d5 - -
+ ;// - - - -
+ ;// - - - -
+
+ PKHTB trRow10,in10,in00,ASR #16 ;// [5 4] = [f5:f1]
+ PKHBT trRow00,in00,in10,LSL #16 ;// [1 0] = [f4:f0]
+
+ ;// HL 2x2 transposed matrix
+ ;// - - - -
+ ;// - - - -
+ ;// d8 d9 - -
+ ;// d12 d13 - -
+
+
+ PKHTB trRow30,in12,in02,ASR #16 ;// [13 12] = [7 3]
+ PKHBT trRow20,in02,in12,LSL #16 ;// [9 8] = [6 2]
+
+ ;// LH 2x2 transposed matrix
+ ;// - - d2 d3
+ ;// - - d6 d7
+ ;// - - - -
+ ;// - - - -
+
+ PKHBT trRow02,in20,in30,LSL #16 ;// [3 2] = [f12:f8]
+ PKHTB trRow12,in30,in20,ASR #16 ;// [7 6] = [f13:f9]
+
+
+
+
+ ;// HH 2x2 transposed matrix
+ ;// - - - -
+ ;// - - - -
+ ;// - - d10 d11
+ ;// - - d14 d15
+
+ PKHTB trRow32,in32,in22,ASR #16 ;// [15 14] = [15 11]
+ PKHBT trRow22,in22,in32,LSL #16 ;// [11 10] = [14 10]
+
+
+ ;****************************************
+ ;// Row Operations (Performed on columns)
+ ;****************************************
+
+
+ ;// SIMD operations on first two columns(two rows of the original matrix)
+
+
+ SADD16 e0, trRow00,trRow20 ;// e0 = d0 + d2
+ SSUB16 e1, trRow00,trRow20 ;// e1 = d0 - d2
+ SHADD16 e2, trRow10,constZero ;// (f1>>1) constZero is a register holding 0
+ SHADD16 e3, trRow30,constZero ;// avoid pipeline stalls for e2 and e3
+ SSUB16 e2, e2, trRow30 ;// e2 = (d1>>1) - d3
+ SADD16 e3, e3, trRow10 ;// e3 = d1 + (d3>>1)
+ SADD16 rowOp00, e0, e3 ;// f0 = e0 + e3
+ SADD16 rowOp10, e1, e2 ;// f1 = e1 + e2
+ SSUB16 rowOp20, e1, e2 ;// f2 = e1 - e2
+ SSUB16 rowOp30, e0, e3 ;// f3 = e0 - e3
+
+ ;// SIMD operations on next two columns(next two rows of the original matrix)
+
+ SADD16 e0, trRow02,trRow22
+ SSUB16 e1, trRow02,trRow22
+ SHADD16 e2, trRow12,constZero ;//(f1>>1) constZero is a register holding 0
+ SHADD16 e3, trRow32,constZero
+ SSUB16 e2, e2, trRow32
+ SADD16 e3, e3, trRow12
+ SADD16 rowOp02, e0, e3
+ SADD16 rowOp12, e1, e2
+ SSUB16 rowOp22, e1, e2
+ SSUB16 rowOp32, e0, e3
+
+
+ ;*****************************************************************
+ ;// Transpose the resultant matrix
+ ;// Input: rowOp[][]
+ ;// Output: trCol[][]
+ ;*****************************************************************
+
+ ;// LL 2x2 transposed matrix
+ ;// d0 d1 - -
+ ;// d4 d5 - -
+ ;// - - - -
+ ;// - - - -
+
+ PKHTB trCol10,rowOp10,rowOp00,ASR #16 ;// [5 4] = [f5:f1]
+ PKHBT trCol00,rowOp00,rowOp10,LSL #16 ;// [1 0] = [f4:f0]
+
+ ;// HL 2x2 transposed matrix
+ ;// - - - -
+ ;// - - - -
+ ;// d8 d9 - -
+ ;// d12 d13 - -
+
+
+ PKHTB trCol30,rowOp12,rowOp02,ASR #16 ;// [13 12] = [7 3]
+ PKHBT trCol20,rowOp02,rowOp12,LSL #16 ;// [9 8] = [6 2]
+
+ ;// LH 2x2 transposed matrix
+ ;// - - d2 d3
+ ;// - - d6 d7
+ ;// - - - -
+ ;// - - - -
+
+ PKHBT trCol02,rowOp20,rowOp30,LSL #16 ;// [3 2] = [f12:f8]
+ PKHTB trCol12,rowOp30,rowOp20,ASR #16 ;// [7 6] = [f13:f9]
+
+
+
+
+ ;// HH 2x2 transposed matrix
+ ;// - - - -
+ ;// - - - -
+ ;// - - d10 d11
+ ;// - - d14 d15
+
+ PKHTB trCol32,rowOp32,rowOp22,ASR #16 ;// [15 14] = [15 11]
+ PKHBT trCol22,rowOp22,rowOp32,LSL #16 ;// [11 10] = [14 10]
+
+
+ ;*******************************
+ ;// Coloumn Operations
+ ;*******************************
+
+
+ ;// SIMD operations on first two columns
+
+
+ SADD16 g0, trCol00,trCol20
+ SSUB16 g1, trCol00,trCol20
+ SHADD16 g2, trCol10,constZero ;// (f1>>1) constZero is a register holding 0
+ SHADD16 g3, trCol30,constZero
+ SSUB16 g2, g2, trCol30
+ SADD16 g3, g3, trCol10
+ SADD16 colOp00, g0, g3
+ SADD16 colOp10, g1, g2
+ SSUB16 colOp20, g1, g2
+ SSUB16 colOp30, g0, g3
+
+ ;// SIMD operations on next two columns
+
+ SADD16 g0, trCol02,trCol22
+ SSUB16 g1, trCol02,trCol22
+ SHADD16 g2, trCol12,constZero ;// (f1>>1) constZero is a register holding 0
+ SHADD16 g3, trCol32,constZero
+ SSUB16 g2, g2, trCol32
+ SADD16 g3, g3, trCol12
+ SADD16 colOp02, g0, g3
+ SADD16 colOp12, g1, g2
+ SSUB16 colOp22, g1, g2
+ SSUB16 colOp32, g0, g3
+
+
+
+
+
+ ;************************************************
+ ;// Calculate final value (colOp[i][j] + 32)>>6
+ ;************************************************
+
+ ;// const1: Serves dual purpose
+ ;// (1) Add #32 to both the lower and higher 16bits of the SIMD result
+ ;// (2) Convert the lower 16 bit value to an unsigned number (Add 32768)
+
+ LDR const1, =0x00208020
+
+ LDR mask, =0xffff03ff ;// Used to mask the down shifted 6 bits
+
+ ;// const2(#512): used to convert the lower 16bit number back to signed value
+
+ MOV const2,#0x200 ;// const2 = 2^9
+
+ ;// First Row
+
+ SADD16 colOp00, colOp00, const1
+ SADD16 colOp02, colOp02, const1
+ AND colOp00, mask, colOp00, ASR #6
+ AND colOp02, mask, colOp02, ASR #6
+ SSUB16 out00,colOp00,const2
+ SSUB16 out02,colOp02,const2
+
+
+ ;// Second Row
+
+ SADD16 colOp10, colOp10, const1
+ SADD16 colOp12, colOp12, const1
+ AND colOp10, mask, colOp10, ASR #6
+ AND colOp12, mask, colOp12, ASR #6
+ SSUB16 out10,colOp10,const2
+ SSUB16 out12,colOp12,const2
+
+
+ ;// Third Row
+
+ SADD16 colOp20, colOp20, const1
+ SADD16 colOp22, colOp22, const1
+ AND colOp20, mask, colOp20, ASR #6
+ AND colOp22, mask, colOp22, ASR #6
+ SSUB16 out20,colOp20,const2
+ SSUB16 out22,colOp22,const2
+
+
+ ;// Fourth Row
+
+ SADD16 colOp30, colOp30, const1
+ SADD16 colOp32, colOp32, const1
+ AND colOp30, mask, colOp30, ASR #6
+ AND colOp32, mask, colOp32, ASR #6
+ SSUB16 out30,colOp30,const2
+ SSUB16 out32,colOp32,const2
+
+
+
+
+ ;***************************
+ ;// Store all the 4x4 pixels
+ ;***************************
+
+ STMIA pDst,{out00,out02,out10,out12,out20,out22,out30,out32}
+
+
+
+ ;// Set return value
+
+End
+
+
+ ;// Write function tail
+ M_END
+
+ ENDIF ;//ARM1136JS
+
+
+
+
+
+
+
+;// Guarding implementation by the processor name
+
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
new file mode 100644
index 0000000..ad16d9c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
@@ -0,0 +1,92 @@
+;//
+;//
+;// File Name: armVCM4P10_UnpackBlock4x4_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+;// Define the processor variants supported by this file
+
+ M_VARIANTS ARM1136JS
+
+
+ IF ARM1136JS
+
+;//--------------------------------------
+;// Input Arguments and their scope/usage
+;//--------------------------------------
+ppSrc RN 0 ;// Persistent variable
+pDst RN 1 ;// Persistent variable
+
+;//--------------------------------
+;// Variables and their scope/usage
+;//--------------------------------
+pSrc RN 2 ;// Persistent variables
+Flag RN 3
+Value RN 4
+Value2 RN 5
+strOffset RN 6
+cstOffset RN 7
+
+
+ M_START armVCM4P10_UnpackBlock4x4, r7
+
+ LDR pSrc, [ppSrc] ;// Load pSrc
+ MOV cstOffset, #31 ;// To be used in the loop, to compute offset
+
+ ;//-----------------------------------------------------------------------
+ ; Firstly, fill all the coefficient values on the <pDst> buffer by zero
+ ;//-----------------------------------------------------------------------
+
+ MOV Value, #0 ;// Initialize the zero value
+ MOV Value2, #0 ;// Initialize the zero value
+ LDRB Flag, [pSrc], #1 ;// Preload <Flag> before <unpackLoop>
+
+ STRD Value, [pDst, #0] ;// pDst[0] = pDst[1] = pDst[2] = pDst[3] = 0
+ STRD Value, [pDst, #8] ;// pDst[4] = pDst[5] = pDst[6] = pDst[7] = 0
+ STRD Value, [pDst, #16] ;// pDst[8] = pDst[9] = pDst[10] = pDst[11] = 0
+ STRD Value, [pDst, #24] ;// pDst[12] = pDst[13] = pDst[14] = pDst[15] = 0
+
+ ;//----------------------------------------------------------------------------
+ ;// The loop below parses and unpacks the input stream. The C-model has
+ ;// a somewhat complicated logic for sign extension. But in the v6 version,
+ ;// that can be easily taken care by loading the data from <pSrc> stream as
+ ;// SIGNED byte/halfword. So, based on the first TST instruction, 8-bits or
+ ;// 16-bits are read.
+ ;//
+ ;// Next, to compute the offset, where the unpacked value needs to be stored,
+ ;// we modify the computation to perform [(Flag & 15) < 1] as [(Flag < 1) & 31]
+ ;// This results in a saving of one cycle.
+ ;//----------------------------------------------------------------------------
+
+unpackLoop
+ TST Flag, #0x10 ;// Computing (Flag & 0x10)
+ LDRSBNE Value2,[pSrc,#1] ;// Load byte wise to avoid unaligned access
+ LDRBNE Value, [pSrc], #2
+ AND strOffset, cstOffset, Flag, LSL #1 ;// strOffset = (Flag & 15) < 1;
+ LDRSBEQ Value, [pSrc], #1 ;// Value = (OMX_U8) *pSrc++
+ ORRNE Value,Value,Value2, LSL #8 ;// Value = (OMX_U16) *pSrc++
+
+ TST Flag, #0x20 ;// Computing (Flag & 0x20) to check, if we're done
+ LDRBEQ Flag, [pSrc], #1 ;// Flag = (OMX_U8) *pSrc++, for next iteration
+ STRH Value, [pDst, strOffset] ;// Store <Value> at offset <strOffset>
+ BEQ unpackLoop ;// Branch to the loop beginning
+
+ STR pSrc, [ppSrc] ;// Update the bitstream pointer
+ M_END
+
+ ENDIF
+
+
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
new file mode 100644
index 0000000..c2e6b60
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
@@ -0,0 +1,88 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_DeblockChroma_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 intra chroma deblock
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_DeblockChroma_I
+ *
+ * Description:
+ * Performs deblocking filtering on all edges of the chroma macroblock (16x16).
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcDst pointer to the input macroblock. Must be 8-byte aligned.
+ * [in] srcdstStep Step of the arrays
+ * [in] pAlpha pointer to a 2x2 array of alpha thresholds, organized as follows: { external
+ * vertical edge, internal vertical edge, external
+ * horizontal edge, internal horizontal edge }
+ * [in] pBeta pointer to a 2x2 array of beta thresholds, organized as follows: { external
+ * vertical edge, internal vertical edge, external horizontal edge,
+ * internal horizontal edge }
+ * [in] pThresholds AArray of size 8x2 of Thresholds (TC0) (values for the left or
+ * above edge of each 4x2 or 2x4 block, arranged in vertical block order
+ * and then in horizontal block order)
+ * [in] pBS array of size 16x2 of BS parameters (arranged in scan block order for vertical edges and then horizontal edges);
+ * valid in the range [0,4] with the following restrictions: i) pBS[i]== 4 may occur only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^1]== 4. Must be 4-byte aligned.
+ * [out] pSrcDst pointer to filtered output macroblock
+ *
+ * Return Value:
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - Either of the pointers in pSrcDst, pAlpha, pBeta, pTresholds, or pBS is NULL.
+ * - pSrcDst is not 8-byte aligned.
+ * - either pThresholds or pBS is not 4-byte aligned.
+ * - pBS is out of range, i.e., one of the following conditions is true: pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or (pBS[i]==4 && pBS[i^1]!=4) for 0<=i<=3.
+ * - srcdstStep is not a multiple of 8.
+ *
+ */
+OMXResult omxVCM4P10_DeblockChroma_I(
+ OMX_U8* pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8* pAlpha,
+ const OMX_U8* pBeta,
+ const OMX_U8* pThresholds,
+ const OMX_U8 *pBS
+)
+{
+ OMXResult errorCode;
+
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot8ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(srcdstStep & 7, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pAlpha == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pThresholds == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pThresholds), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBS == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pBS), OMX_Sts_BadArgErr);
+
+ errorCode = omxVCM4P10_FilterDeblockingChroma_VerEdge_I(
+ pSrcDst, srcdstStep, pAlpha, pBeta, pThresholds, pBS);
+
+ armRetArgErrIf(errorCode != OMX_Sts_NoErr, errorCode)
+
+ errorCode = omxVCM4P10_FilterDeblockingChroma_HorEdge_I(
+ pSrcDst, srcdstStep, pAlpha+2, pBeta+2, pThresholds+8, pBS+16);
+
+ return errorCode;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
new file mode 100644
index 0000000..6023862
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
@@ -0,0 +1,91 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_DeblockLuma_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 luma deblock
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+
+/**
+ * Function: omxVCM4P10_DeblockLuma_I
+ *
+ * Description:
+ * This function performs deblock filtering the horizontal and vertical edges of a luma macroblock
+ *(16x16).
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcDst pointer to the input macroblock. Must be 8-byte aligned.
+ * [in] srcdstStep image width
+ * [in] pAlpha pointer to a 2x2 table of alpha thresholds, organized as follows: { external
+ * vertical edge, internal vertical edge, external horizontal
+ * edge, internal horizontal edge }
+ * [in] pBeta pointer to a 2x2 table of beta thresholds, organized as follows: { external
+ * vertical edge, internal vertical edge, external horizontal edge,
+ * internal horizontal edge }
+ * [in] pThresholds pointer to a 16x2 table of threshold (TC0), organized as follows: { values for
+ * the left or above edge of each 4x4 block, arranged in vertical block order
+ * and then in horizontal block order)
+ * [in] pBS pointer to a 16x2 table of BS parameters arranged in scan block order for vertical edges and then horizontal edges;
+ * valid in the range [0,4] with the following restrictions: i) pBS[i]== 4 may occur only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^1]== 4. Must be 4-byte aligned.
+ * [out] pSrcDst pointer to filtered output macroblock.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - Either of the pointers in pSrcDst, pAlpha, pBeta, pTresholds or pBS is NULL.
+ * - pSrcDst is not 8-byte aligned.
+ * - srcdstStep is not a multiple of 8
+ * - pBS is out of range, i.e., one of the following conditions is true: pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or (pBS[i]==4 && pBS[i^1]!=4) for 0<=i<=3.
+.
+ *
+ */
+
+OMXResult omxVCM4P10_DeblockLuma_I(
+ OMX_U8* pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8* pAlpha,
+ const OMX_U8* pBeta,
+ const OMX_U8* pThresholds,
+ const OMX_U8 *pBS
+)
+{
+ OMXResult errorCode;
+
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot8ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(srcdstStep & 7, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pAlpha == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pThresholds == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pThresholds), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBS == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pBS), OMX_Sts_BadArgErr);
+
+ errorCode = omxVCM4P10_FilterDeblockingLuma_VerEdge_I(
+ pSrcDst, srcdstStep, pAlpha, pBeta, pThresholds, pBS);
+
+ armRetArgErrIf(errorCode != OMX_Sts_NoErr, errorCode)
+
+ errorCode = omxVCM4P10_FilterDeblockingLuma_HorEdge_I(
+ pSrcDst, srcdstStep, pAlpha+2, pBeta+2, pThresholds+16, pBS+16);
+
+ return errorCode;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
new file mode 100644
index 0000000..a19f277
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
@@ -0,0 +1,62 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 decode coefficients module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC
+ *
+ * Description:
+ * Performs CAVLC decoding and inverse raster scan for 2x2 block of
+ * ChromaDCLevel. The decoded coefficients in packed position-coefficient
+ * buffer are stored in increasing raster scan order, namely position order.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream Double pointer to current byte in bit stream
+ * buffer
+ * [in] pOffset Pointer to current bit position in the byte
+ * pointed to by *ppBitStream
+ * [out] ppBitStream *ppBitStream is updated after each block is decoded
+ * [out] pOffset *pOffset is updated after each block is decoded
+ * [out] pNumCoeff Pointer to the number of nonzero coefficients
+ * in this block
+ * [out] ppPosCoefbuf Double pointer to destination residual
+ * coefficient-position pair buffer
+ *
+ * Return Value:
+ * Standard omxError result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC (
+ const OMX_U8** ppBitStream,
+ OMX_S32* pOffset,
+ OMX_U8* pNumCoeff,
+ OMX_U8** ppPosCoefbuf
+ )
+
+{
+ return armVCM4P10_DecodeCoeffsToPair(ppBitStream, pOffset, pNumCoeff,
+ ppPosCoefbuf, 17, 4);
+
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
new file mode 100644
index 0000000..99bb4ce
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
@@ -0,0 +1,68 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_DecodeCoeffsToPairCAVLC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 decode coefficients module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_DecodeCoeffsToPairCAVLC
+ *
+ * Description:
+ * Performs CAVLC decoding and inverse zigzag scan for 4x4 block of
+ * Intra16x16DCLevel, Intra16x16ACLevel,LumaLevel, and ChromaACLevel.
+ * Inverse field scan is not supported. The decoded coefficients in packed
+ * position-coefficient buffer are stored in increasing zigzag order instead
+ * of position order.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream Double pointer to current byte in bit stream buffer
+ * [in] pOffset Pointer to current bit position in the byte pointed
+ * to by *ppBitStream
+ * [in] sMaxNumCoeff Maximum number of non-zero coefficients in current
+ * block
+ * [in] sVLCSelect VLC table selector, obtained from number of non-zero
+ * AC coefficients of above and left 4x4 blocks. It is
+ * equivalent to the variable nC described in H.264 standard
+ * table 9-5, except its value can¡¯t be less than zero.
+ * [out] ppBitStream *ppBitStream is updated after each block is decoded
+ * [out] pOffset *pOffset is updated after each block is decoded
+ * [out] pNumCoeff Pointer to the number of nonzero coefficients in
+ * this block
+ * [out] ppPosCoefbuf Double pointer to destination residual
+ * coefficient-position pair buffer
+ * Return Value:
+ * Standard omxError result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult omxVCM4P10_DecodeCoeffsToPairCAVLC(
+ const OMX_U8** ppBitStream,
+ OMX_S32* pOffset,
+ OMX_U8* pNumCoeff,
+ OMX_U8**ppPosCoefbuf,
+ OMX_INT sVLCSelect,
+ OMX_INT sMaxNumCoeff
+ )
+{
+ return armVCM4P10_DecodeCoeffsToPair(ppBitStream, pOffset, pNumCoeff,
+ ppPosCoefbuf, sVLCSelect, sMaxNumCoeff);
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s
new file mode 100644
index 0000000..2b71486
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s
@@ -0,0 +1,480 @@
+;//
+;// (c) Copyright 2007 ARM Limited. All Rights Reserved.
+;//
+;// Description:
+;// H.264 inverse quantize and transform module
+;//
+;//
+
+
+
+;// Include standard headers
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+;// Import symbols required from other files
+;// (For example tables)
+
+ IMPORT armVCM4P10_UnpackBlock4x4
+ IMPORT armVCM4P10_TransformResidual4x4
+ IMPORT armVCM4P10_QPDivTable
+ IMPORT armVCM4P10_VMatrixU16
+ IMPORT armVCM4P10_QPModuloTable
+
+ M_VARIANTS ARM1136JS, ARM1136JS_U
+
+;// Set debugging level
+;//DEBUG_ON SETL {TRUE}
+
+
+;// Static Function: armVCM4P10_DequantLumaAC4x4
+
+;// Guarding implementation by the processor name
+
+ IF ARM1136JS
+
+;//Input Registers
+pSrcDst RN 0
+QP RN 1
+
+
+;//Output Registers
+
+
+;//Local Scratch Registers
+pQPdiv RN 4
+pQPmod RN 5
+pVRow RN 2
+QPmod RN 6
+shift RN 3
+rowLuma01 RN 1
+rowLuma23 RN 4
+
+SrcDst00 RN 5
+SrcDst02 RN 6
+SrcDst10 RN 7
+SrcDst12 RN 8
+SrcDst20 RN 9
+SrcDst22 RN 10
+SrcDst30 RN 11
+SrcDst32 RN 12
+
+temp1 RN 2
+temp2 RN 3
+temp3 RN 14
+
+
+ ;// Allocate stack memory required by the function
+
+ ;// Write function header
+ M_START armVCM4P10_DequantLumaAC4x4,r11
+
+ LDR pQPmod,=armVCM4P10_QPModuloTable
+ LDR pQPdiv,=armVCM4P10_QPDivTable
+ LDR pVRow,=armVCM4P10_VMatrixU16
+
+ LDRSB QPmod,[pQPmod,QP] ;// (QP%6) * 6
+ LDRSB shift,[pQPdiv,QP] ;// Shift = QP / 6
+
+ LDRH rowLuma01,[pVRow,QPmod]! ;// rowLuma01 = [00|0a]
+ LDRH temp3,[pVRow,#2] ;// temp3 = [00|0b]
+ LDRH rowLuma23,[pVRow,#4] ;// rowLuma23 = [00|0c]
+ ORR rowLuma01,rowLuma01,temp3,LSL #16 ;// rowLuma01 = [0b|0a]
+
+ ;// Load all the 16 'src' values
+ LDMIA pSrcDst,{SrcDst00,SrcDst02,SrcDst10,SrcDst12,SrcDst20,SrcDst22,SrcDst30,SrcDst32}
+
+
+ ;//*********************************************************************************************
+ ;//
+ ;// 'Shift' ranges between [0,8]
+ ;// So we can shift the packed rowLuma values [0b|0a] with a single LSL operation
+ ;//
+ ;//*********************************************************************************************
+
+ LSL rowLuma01,rowLuma01,shift
+ LSL rowLuma23,rowLuma23,shift
+
+
+ ;//**********************************************************************************************
+ ;//
+ ;// The idea is to unroll the Loop completely
+ ;// All the 16 src values are loaded at once into 8 registers : SrcDst<y><x> (above)
+ ;// 0<= armVCM4P10_PosToVCol4x4[i] <=2 for any 'i<16'
+ ;// So the only values of pVRow[i] that need to be loaded are for i=0,1,2
+ ;// These 3 values are loaded into rowLuma01 and rowLuma23 (above)
+ ;// We first calculate pVRow[armVCM4P10_PosToVCol4x4[i]]) << Shift which fits into 16 bits (above)
+ ;// Then the product pSrcDst[i] * (pVRow[armVCM4P10_PosToVCol4x4[i]] << Shift) is calculated
+ ;// Here we interleave the PKHBT operations for various rows to avoide pipeline stalls
+ ;//
+ ;// We then pack the two 16 bit multiplication result into a word and store at one go
+ ;//
+ ;//**********************************************************************************************
+
+
+ ;// Row 1
+
+
+ SMULTB temp1,SrcDst00,rowLuma23 ;// pSrcDst[1] * (pVRow[2]<<Shift)
+ SMULBB SrcDst00,SrcDst00,rowLuma01 ;// pSrcDst[0] * (pVRow[0]<<Shift)
+
+ SMULTB temp2,SrcDst02,rowLuma23 ;// pSrcDst[3] * (pVRow[2]<<Shift)
+ SMULBB SrcDst02,SrcDst02,rowLuma01 ;// pSrcDst[2] * (pVRow[0]<<Shift)
+
+ PKHBT SrcDst00,SrcDst00,temp1,LSL #16 ;// Pack the first two product values
+
+
+ ;// Row 2
+ SMULTT temp1,SrcDst10,rowLuma01 ;// pSrcDst[5] * (pVRow[1]<<Shift)
+ SMULBB SrcDst10,SrcDst10,rowLuma23 ;// pSrcDst[4] * (pVRow[2]<<Shift)
+
+ PKHBT SrcDst02,SrcDst02,temp2,LSL #16 ;// Pack the next two product values
+ SMULTT temp2,SrcDst12,rowLuma01 ;// pSrcDst[7] * (pVRow[1]<<Shift)
+ SMULBB SrcDst12,SrcDst12,rowLuma23 ;// pSrcDst[6] * (pVRow[2]<<Shift)
+
+ PKHBT SrcDst10,SrcDst10,temp1,LSL #16 ;// Pack the next two product values
+
+
+ ;// Row 3
+
+ SMULTB temp1,SrcDst20,rowLuma23 ;// pSrcDst[9] * (pVRow[2]<<Shift)
+ SMULBB SrcDst20,SrcDst20,rowLuma01 ;// pSrcDst[8] * (pVRow[0]<<Shift)
+
+ PKHBT SrcDst12,SrcDst12,temp2,LSL #16 ;// Pack the next two product values
+ SMULTB temp2,SrcDst22,rowLuma23 ;// pSrcDst[11] * (pVRow[2]<<Shift)
+ SMULBB SrcDst22,SrcDst22,rowLuma01 ;// pSrcDst[10] * (pVRow[0]<<Shift)
+
+ PKHBT SrcDst20,SrcDst20,temp1,LSL #16 ;// Pack the next two product values
+
+
+
+ ;// Row 4
+
+ SMULTT temp1,SrcDst30,rowLuma01 ;// pSrcDst[13] * (pVRow[1]<<Shift)
+ SMULBB SrcDst30,SrcDst30,rowLuma23 ;// pSrcDst[12] * (pVRow[2]<<Shift)
+
+ SMULTT temp3,SrcDst32,rowLuma01 ;// pSrcDst[15] * (pVRow[1]<<Shift)
+ SMULBB SrcDst32,SrcDst32,rowLuma23 ;// pSrcDst[14] * (pVRow[2]<<Shift)
+
+ PKHBT SrcDst22,SrcDst22,temp2,LSL #16 ;// Pack the remaining product values
+ PKHBT SrcDst30,SrcDst30,temp1,LSL #16
+ PKHBT SrcDst32,SrcDst32,temp3,LSL #16
+
+
+ STMIA pSrcDst,{SrcDst00,SrcDst02,SrcDst10,SrcDst12,SrcDst20,SrcDst22,SrcDst30,SrcDst32}
+
+
+ ;// Set return value
+
+
+
+ ;// Write function tail
+ M_END
+
+ ENDIF ;//ARM1136JS
+
+
+;// Guarding implementation by the processor name
+
+ IF ARM1136JS_U
+
+;//Input Registers
+pSrcDst RN 0
+QP RN 1
+
+
+;//Output Registers
+
+
+;//Local Scratch Registers
+pQPdiv RN 4
+pQPmod RN 5
+pVRow RN 2
+QPmod RN 6
+shift RN 3
+rowLuma01 RN 1
+rowLuma23 RN 4
+
+SrcDst00 RN 5
+SrcDst02 RN 6
+SrcDst10 RN 7
+SrcDst12 RN 8
+SrcDst20 RN 9
+SrcDst22 RN 10
+SrcDst30 RN 11
+SrcDst32 RN 12
+
+temp1 RN 2
+temp2 RN 3
+temp3 RN 14
+
+
+ ;// Allocate stack memory required by the function
+
+ ;// Write function header
+ M_START armVCM4P10_DequantLumaAC4x4,r11
+
+ LDR pQPmod,=armVCM4P10_QPModuloTable
+ LDR pQPdiv,=armVCM4P10_QPDivTable
+ LDR pVRow,=armVCM4P10_VMatrixU16
+
+ LDRSB QPmod,[pQPmod,QP] ;// (QP%6) * 6
+ LDRSB shift,[pQPdiv,QP] ;// Shift = QP / 6
+
+ LDR rowLuma01,[pVRow,QPmod]! ;// rowLuma01 = [0b|0a]
+ LDR rowLuma23,[pVRow,#4] ;// rowLuma23 = [0d|0c]
+
+ ;// Load all the 16 'src' values
+ LDMIA pSrcDst,{SrcDst00,SrcDst02,SrcDst10,SrcDst12,SrcDst20,SrcDst22,SrcDst30,SrcDst32}
+
+
+ ;//*********************************************************************************************
+ ;//
+ ;// 'Shift' ranges between [0,8]
+ ;// So we can shift the packed rowLuma values [0b|0a] with a single LSL operation
+ ;//
+ ;//*********************************************************************************************
+
+ LSL rowLuma01,rowLuma01,shift
+ LSL rowLuma23,rowLuma23,shift
+
+
+ ;//**********************************************************************************************
+ ;//
+ ;// The idea is to unroll the Loop completely
+ ;// All the 16 src values are loaded at once into 8 registers : SrcDst<y><x> (above)
+ ;// 0<= armVCM4P10_PosToVCol4x4[i] <=2 for any 'i<16'
+ ;// So the only values of pVRow[i] that need to be loaded are for i=0,1,2
+ ;// These 3 values are loaded into rowLuma01 and rowLuma23 (above)
+ ;// We first calculate pVRow[armVCM4P10_PosToVCol4x4[i]]) << Shift which fits into 16 bits (above)
+ ;// Then the product pSrcDst[i] * (pVRow[armVCM4P10_PosToVCol4x4[i]] << Shift) is calculated
+ ;// Here we interleave the PKHBT operations for various rows to avoide pipeline stalls
+ ;//
+ ;// We then pack the two 16 bit multiplication result into a word and store at one go
+ ;//
+ ;//**********************************************************************************************
+
+
+ ;// Row 1
+
+
+ SMULTB temp1,SrcDst00,rowLuma23 ;// pSrcDst[1] * (pVRow[2]<<Shift)
+ SMULBB SrcDst00,SrcDst00,rowLuma01 ;// pSrcDst[0] * (pVRow[0]<<Shift)
+
+ SMULTB temp2,SrcDst02,rowLuma23 ;// pSrcDst[3] * (pVRow[2]<<Shift)
+ SMULBB SrcDst02,SrcDst02,rowLuma01 ;// pSrcDst[2] * (pVRow[0]<<Shift)
+
+ PKHBT SrcDst00,SrcDst00,temp1,LSL #16 ;// Pack the first two product values
+
+
+ ;// Row 2
+ SMULTT temp1,SrcDst10,rowLuma01 ;// pSrcDst[5] * (pVRow[1]<<Shift)
+ SMULBB SrcDst10,SrcDst10,rowLuma23 ;// pSrcDst[4] * (pVRow[2]<<Shift)
+
+ PKHBT SrcDst02,SrcDst02,temp2,LSL #16 ;// Pack the next two product values
+ SMULTT temp2,SrcDst12,rowLuma01 ;// pSrcDst[7] * (pVRow[1]<<Shift)
+ SMULBB SrcDst12,SrcDst12,rowLuma23 ;// pSrcDst[6] * (pVRow[2]<<Shift)
+
+ PKHBT SrcDst10,SrcDst10,temp1,LSL #16 ;// Pack the next two product values
+
+
+ ;// Row 3
+
+ SMULTB temp1,SrcDst20,rowLuma23 ;// pSrcDst[9] * (pVRow[2]<<Shift)
+ SMULBB SrcDst20,SrcDst20,rowLuma01 ;// pSrcDst[8] * (pVRow[0]<<Shift)
+
+ PKHBT SrcDst12,SrcDst12,temp2,LSL #16 ;// Pack the next two product values
+ SMULTB temp2,SrcDst22,rowLuma23 ;// pSrcDst[11] * (pVRow[2]<<Shift)
+ SMULBB SrcDst22,SrcDst22,rowLuma01 ;// pSrcDst[10] * (pVRow[0]<<Shift)
+
+ PKHBT SrcDst20,SrcDst20,temp1,LSL #16 ;// Pack the next two product values
+
+
+
+ ;// Row 4
+
+ SMULTT temp1,SrcDst30,rowLuma01 ;// pSrcDst[13] * (pVRow[1]<<Shift)
+ SMULBB SrcDst30,SrcDst30,rowLuma23 ;// pSrcDst[12] * (pVRow[2]<<Shift)
+
+ SMULTT temp3,SrcDst32,rowLuma01 ;// pSrcDst[15] * (pVRow[1]<<Shift)
+ SMULBB SrcDst32,SrcDst32,rowLuma23 ;// pSrcDst[14] * (pVRow[2]<<Shift)
+
+ PKHBT SrcDst22,SrcDst22,temp2,LSL #16 ;// Pack the remaining product values
+ PKHBT SrcDst30,SrcDst30,temp1,LSL #16
+ PKHBT SrcDst32,SrcDst32,temp3,LSL #16
+
+
+ STMIA pSrcDst,{SrcDst00,SrcDst02,SrcDst10,SrcDst12,SrcDst20,SrcDst22,SrcDst30,SrcDst32}
+
+
+ ;// Set return value
+
+
+
+ ;// Write function tail
+ M_END
+
+ ENDIF ;//ARM1136JS_U
+
+
+
+
+
+;// Function: omxVCM4P10_DequantTransformResidualFromPairAndAdd
+
+;// Guarding implementation by the processor name
+
+ IF ARM1136JS
+
+;//Input Registers
+ppSrc RN 0
+pPred RN 1
+pDC RN 2
+pDst RN 3
+
+
+;//Output Registers
+result RN 0
+
+;//Local Scratch Registers
+pDelta RN 4
+pDeltaTmp RN 6
+AC RN 5 ;//Load from stack
+pPredTemp RN 7
+pDCTemp RN 8
+pDstTemp RN 9
+pDeltaArg1 RN 1
+pDeltaArg0 RN 0
+QP RN 1 ;//Load from stack
+DCval RN 10
+DCvalCopy RN 11
+predstep RN 1
+dstStep RN 10
+ycounter RN 0
+PredVal1 RN 3
+PredVal2 RN 5
+DeltaVal1 RN 2
+DeltaVal2 RN 11
+PredVal RN 8
+tmpDeltaVal RN 6
+sum1 RN 12
+sum2 RN 14
+
+
+
+ ;// Allocate stack memory required by the function
+ M_ALLOC8 pBuffer, 32
+
+
+ ;// Write function header
+ M_START omxVCM4P10_DequantTransformResidualFromPairAndAdd,r11
+
+ ;// Define stack arguments
+ M_ARG predStepOnStack, 4
+ M_ARG dstStepOnStack,4
+ M_ARG QPOnStack, 4
+ M_ARG ACOnStack,4
+
+
+ M_ADR pDelta,pBuffer
+ M_LDR AC,ACOnStack
+
+
+ ;// Save registers r1,r2,r3 before function call
+ MOV pPredTemp,pPred
+ MOV pDCTemp,pDC
+ MOV pDstTemp,pDst
+
+ CMP AC,#0
+ BEQ DCcase
+ MOV pDeltaArg1,pDelta ;// Set up r1 for armVCM4P10_UnpackBlock4x4
+
+ BL armVCM4P10_UnpackBlock4x4
+
+ M_LDR QP,QPOnStack ;// Set up r1 for DequantLumaAC4x4
+ MOV pDeltaArg0,pDelta ;// Set up r0 for DequantLumaAC4x4
+
+ BL armVCM4P10_DequantLumaAC4x4
+
+
+ CMP pDCTemp,#0
+ LDRSHNE DCval,[pDCTemp]
+ MOV pDeltaArg0,pDelta ;// Set up r0 for armVCM4P10_TransformResidual4x4
+ MOV pDeltaArg1,pDelta ;// Set up r1 for armVCM4P10_TransformResidual4x4
+ STRHNE DCval,[pDelta]
+
+ BL armVCM4P10_TransformResidual4x4
+ B OutDCcase
+
+
+DCcase
+ LDRSH DCval,[pDCTemp]
+ ADD DCval,DCval,#32
+ ASR DCval,DCval,#6
+ PKHBT DCval,DCval,DCval,LSL #16 ;// Duplicating the Lower halfword
+ MOV DCvalCopy, DCval ;// Needed for STRD
+ STRD DCval, [pDelta, #0] ;// pDelta[0] = pDelta[1] = pDelta[2] = pDelta[3] = DCval
+ STRD DCval, [pDelta, #8] ;// pDelta[4] = pDelta[5] = pDelta[6] = pDelta[7] = DCval
+ STRD DCval, [pDelta, #16] ;// pDelta[8] = pDelta[9] = pDelta[10] = pDelta[11] = DCval
+ STRD DCval, [pDelta, #24]
+
+
+OutDCcase
+ M_LDR predstep,predStepOnStack
+ M_LDR dstStep,dstStepOnStack
+
+ LDMIA pDelta!,{tmpDeltaVal,DeltaVal2} ;// Pre load
+ MOV ycounter,#4 ;// Counter for the PredPlusDeltaLoop
+ LDR PredVal,[pPredTemp] ;// Pre load
+
+PredPlusDeltaLoop
+
+
+ SUBS ycounter,ycounter,#1
+ ADD pPredTemp,pPredTemp,predstep ;// Increment pPred ptr
+
+ PKHBT DeltaVal1,tmpDeltaVal,DeltaVal2,LSL #16 ;// Deltaval1 = [C A]
+ PKHTB DeltaVal2,DeltaVal2,tmpDeltaVal,ASR #16 ;// DeltaVal2 = [D B]
+
+ UXTB16 PredVal1,PredVal ;// PredVal1 = [0c0a]
+ UXTB16 PredVal2,PredVal,ROR #8 ;// PredVal2 = [0d0b]
+
+ LDRGT PredVal,[pPredTemp] ;// Pre load
+
+ QADD16 sum2,DeltaVal2,PredVal2 ;// Add and saturate to 16 bits
+ QADD16 sum1,DeltaVal1,PredVal1
+
+ USAT16 sum2,#8,sum2 ;// armClip(0,255,sum2)
+ USAT16 sum1,#8,sum1
+
+ LDMGTIA pDelta!,{tmpDeltaVal,DeltaVal2} ;// Pre load
+
+ ORR sum1,sum1,sum2,LSL #8 ;// sum1 = [dcba]
+ STR sum1,[pDstTemp]
+
+ ADD pDstTemp,pDstTemp,dstStep ;// Increment pDst ptr
+ BGT PredPlusDeltaLoop
+
+
+ ;// Set return value
+ MOV result,#OMX_Sts_NoErr
+
+End
+
+
+ ;// Write function tail
+
+ M_END
+
+ ENDIF ;//ARM1136JS
+
+
+;// Function: omxVCM4P10_DequantTransformResidualFromPairAndAdd
+
+;// Guarding implementation by the processor name
+
+
+
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
new file mode 100644
index 0000000..6d960f0
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
@@ -0,0 +1,336 @@
+;//
+;//
+;// File Name: omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+
+ IF ARM1136JS
+
+MASK_0 EQU 0x00000000
+MASK_1 EQU 0x01010101
+LOOP_COUNT EQU 0x50000000
+
+;// Declare input registers
+
+pSrcDst RN 0
+srcdstStep RN 1
+pAlphaArg RN 2
+pBetaArg RN 3
+
+pThresholds RN 6
+pBS RN 9
+pQ0 RN 0
+bS RN 10
+
+alpha RN 6
+alpha0 RN 6
+alpha1 RN 8
+
+beta RN 7
+beta0 RN 7
+beta1 RN 9
+
+;// Declare Local/Temporary variables
+
+;// Pixels
+p_0 RN 3
+p_1 RN 5
+q_0 RN 8
+q_1 RN 9
+
+;// Filtering
+
+dp0q0 RN 12
+dp1p0 RN 12
+dq1q0 RN 12
+
+ap0q0 RN 4
+filt RN 2
+
+m00 RN 14
+m01 RN 11
+
+pQ0 RN 0
+Step RN 1
+
+;// Output
+
+P_0 RN 6
+Q_0 RN 7
+
+;//Declarations for bSLT4 kernel
+
+tC RN 12
+tC0 RN 5
+tC1 RN 12
+pos RN 5
+neg RN 9
+
+;//Declarations for bSGE4 kernel
+
+
+;// Miscellanous
+XY RN 8
+
+a RN 10
+t1 RN 10
+t2 RN 12
+t3 RN 14
+t4 RN 6
+t5 RN 5
+
+
+ ;// Allocate stack memory
+ M_ALLOC4 ppThresholds,4
+ M_ALLOC8 pAlphaBeta0,8
+ M_ALLOC8 pAlphaBeta1,8
+ M_ALLOC8 pXYBS,4
+ M_ALLOC4 ppBS,4
+
+ ;// Function header
+ M_START omxVCM4P10_FilterDeblockingChroma_HorEdge_I, r11
+
+ ;//Input arguments on the stack
+ M_ARG ppThresholdsArg, 4
+ M_ARG ppBSArg, 4
+
+ LDRB alpha1, [pAlphaArg,#1]
+ LDRB beta1, [pBetaArg,#1]
+ M_LDR pThresholds, ppThresholdsArg
+ LDR a,=MASK_1
+ LDRB beta0, [pBetaArg]
+ M_STR pThresholds, ppThresholds
+ LDRB alpha0, [pAlphaArg]
+
+ MUL alpha1, alpha1, a
+ MUL beta1, beta1, a
+ MUL alpha0, alpha0, a
+ MUL beta0, beta0, a
+
+ M_STRD alpha1, beta1, pAlphaBeta1
+ M_LDR pBS, ppBSArg
+ M_STRD alpha0, beta0, pAlphaBeta0
+
+ LDR XY,=LOOP_COUNT
+ M_STRD XY, pBS, pXYBS
+
+ SUB pQ0, pQ0, srcdstStep, LSL #1
+LoopY
+LoopX
+;//---------------Load Pixels-------------------
+ LDRH bS, [pBS], #2
+
+ M_STR pBS, ppBS
+ M_LDR p_1, [pQ0],srcdstStep
+
+ CMP bS, #0
+
+ M_LDR p_0, [pQ0],srcdstStep
+ M_LDR q_0, [pQ0],srcdstStep
+ M_LDR q_1, [pQ0]
+ LDR m01, =MASK_1 ;// 01010101 mask
+ BEQ NoFilterBS0
+
+
+ ;// p_0 = [r3p0 r2p0 r1p0 r0p0]
+ ;// p_1 = [r3p1 r2p1 r1p1 r0p1]
+ ;// q_0 = [r3q0 r2q0 r1q0 r0q0]
+ ;// q_1 = [r3q1 r2q1 r1q1 r0q1]
+
+;//--------------Filtering Decision -------------------
+ MOV m00, #MASK_0 ;// 00000000 mask
+
+ MOV filt, m01
+ TST bS, #0xff00
+ MOVEQ filt, filt, LSR #16
+ TST bS, #0xff
+ MOVEQ filt, filt, LSL #16
+ TST bS, #4
+
+
+ ;// Check |p0-q0|<Alpha
+ USUB8 dp0q0, p_0, q_0
+ USUB8 a, q_0, p_0
+ SEL ap0q0, a, dp0q0
+ USUB8 a, ap0q0, alpha
+ SEL filt, m00, filt
+
+ ;// Check |p1-p0|<Beta
+ USUB8 dp1p0, p_1, p_0
+ USUB8 a, p_0, p_1
+ SEL a, a, dp1p0
+ USUB8 a, a, beta
+ SEL filt, m00, filt
+
+ ;// Check |q1-q0|<Beta
+ USUB8 dq1q0, q_1, q_0
+ USUB8 a, q_0, q_1
+ SEL a, a, dq1q0
+ USUB8 a, a, beta
+ SEL filt, m00, filt
+
+ BEQ bSLT4
+;//-------------------Filter--------------------
+bSGE4
+ ;//---------bSGE4 Execution---------------
+ CMP filt, #0
+
+ M_LDR pThresholds, ppThresholds
+
+ ;// Compute P0b
+ UHADD8 t1, p_0, q_1
+ BEQ NoFilterFilt0
+ MVN t2, p_1
+ UHSUB8 t1, t1, t2
+ USUB8 t2, filt, m01
+ EOR t1, t1, m01, LSL #7
+
+ ADD pThresholds,pThresholds, #2
+
+ ;// Compute Q0b
+ UHADD8 t2, q_0, p_1
+ MVN t3, q_1
+ UHSUB8 t2, t2, t3
+ M_STR pThresholds, ppThresholds
+ SEL P_0, t1, p_0
+ EOR t2, t2, m01, LSL #7
+ SEL Q_0, t2, q_0
+
+ SUB pQ0, pQ0, srcdstStep, LSL #1
+ B StoreResultAndExit
+
+;//---------- Exit of LoopX --------------
+;//---- for the case of no filtering -----
+
+NoFilterFilt0
+NoFilterBS0
+ M_LDR pThresholds, ppThresholds
+ SUB pQ0, pQ0, srcdstStep, LSL #1
+ SUB pQ0, pQ0, srcdstStep
+ ADD pQ0, pQ0, #4
+ ADD pThresholds, pThresholds, #2
+
+ ;// Load counter for LoopX
+ M_LDRD XY, pBS, pXYBS
+ M_STR pThresholds, ppThresholds
+ M_LDRD alpha, beta, pAlphaBeta0
+
+ ;// Align the pointer
+ ADDS XY, XY, XY
+ M_STR XY, pXYBS
+ BCC LoopY
+ B ExitLoopY
+
+bSLT4
+ ;//---------bSLT4 Execution---------------
+ M_LDR pThresholds, ppThresholds
+ CMP filt, #0
+
+ ;// Since beta <= 18 and alpha <= 255 we know
+ ;// -254 <= p0-q0 <= 254
+ ;// -17 <= q1-q0 <= 17
+ ;// -17 <= p1-p0 <= 17
+
+ ;// delta = Clip3( -tC, tC, ((((q0-p0)<<2) + (p1-q1) + 4)>>3))
+ ;//
+ ;// Calculate A = (((q0-p0)<<2) + (p1-q1) + 4)>>3
+ ;// = (4*q0 - 4*p0 + p1 - q1 + 4)>>3
+ ;// = ((p1-p0) - (q1-q0) - 3*(p0-q0) + 4)>>3
+
+ USUB8 t1, p_1, p_0
+ USUB8 t2, q_1, q_0
+ BEQ NoFilterFilt0
+
+ LDRB tC0, [pThresholds],#1
+ SSUB8 t1, t1, t2
+ LDRB tC1, [pThresholds],#1
+ M_STR pThresholds, ppThresholds
+ UHSUB8 t4, p_0, q_0
+ ORR tC, tC0, tC1, LSL #16
+ USUB8 t5, p_0, q_0
+ AND t5, t5, m01
+ SHSUB8 t1, t1, t5
+ ORR tC, tC, LSL #8
+ SSUB8 t1, t1, t5
+ SHSUB8 t1, t1, t4
+ UQADD8 tC, tC, m01
+ SADD8 t1, t1, m01
+ USUB8 t5, filt, m01
+ SHSUB8 t1, t1, t4
+ SEL tC, tC, m00
+
+ ;// Split into positive and negative part and clip
+
+ SSUB8 t1, t1, m00
+ SEL pos, t1, m00
+ USUB8 neg, pos, t1
+ USUB8 t3, pos, tC
+ SEL pos, tC, pos
+ USUB8 t3, neg, tC
+ SEL neg, tC, neg
+ UQADD8 P_0, p_0, pos
+ UQSUB8 Q_0, q_0, pos
+ UQSUB8 P_0, P_0, neg
+ UQADD8 Q_0, Q_0, neg
+
+ SUB pQ0, pQ0, srcdstStep, LSL #1
+
+ ;// Choose to store the filtered
+ ;// value or the original pixel
+ USUB8 t1, filt, m01
+ SEL P_0, P_0, p_0
+ SEL Q_0, Q_0, q_0
+
+StoreResultAndExit
+
+ ;//---------Store result---------------
+
+ ;// P_0 = [r0p0 r1p0 r2p0 r3p0]
+ ;// Q_0 = [r0q0 r1q0 r2q0 r3q0]
+
+ M_STR P_0, [pQ0], srcdstStep
+ STR Q_0, [pQ0], #4
+
+ M_LDRD XY, pBS, pXYBS
+ M_LDRD alpha, beta, pAlphaBeta0
+
+ SUB pQ0, pQ0, srcdstStep, LSL #1
+
+ ADDS XY, XY, XY
+ M_STR XY, pXYBS
+ BCC LoopX
+
+;//-------- Common Exit of LoopY -----------------
+ ;// Align the pointers
+
+ExitLoopY
+ ADD pBS, pBS, #4
+ M_LDRD alpha, beta, pAlphaBeta1
+ SUB pQ0, pQ0, #8
+ ADD pQ0, pQ0, srcdstStep, LSL #2
+ M_STRD alpha, beta, pAlphaBeta0
+
+ BNE LoopY
+ MOV r0, #OMX_Sts_NoErr
+
+;//-----------------End Filter--------------------
+ M_END
+
+ ENDIF
+
+ END
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
new file mode 100644
index 0000000..00c8354
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
@@ -0,0 +1,437 @@
+;//
+;//
+;// File Name: omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+
+ IF ARM1136JS
+
+
+MASK_0 EQU 0x00000000
+MASK_1 EQU 0x01010101
+MASK_2 EQU 0x0000ff00
+LOOP_COUNT EQU 0x50000000
+
+;// Declare input registers
+
+pSrcDst RN 0
+srcdstStep RN 1
+pAlphaArg RN 2
+pBetaArg RN 3
+
+pThresholds RN 6
+pBS RN 9
+pQ0 RN 0
+bS RN 2
+bSTemp RN 10
+
+alpha RN 6
+alpha0 RN 6
+alpha1 RN 8
+
+beta RN 7
+beta0 RN 7
+beta1 RN 9
+
+;// Declare Local/Temporary variables
+
+;// Pixels
+p_0 RN 3
+p_1 RN 5
+q_0 RN 8
+q_1 RN 9
+
+;// Unpacking
+mask RN 11
+
+row0 RN 2
+row1 RN 4
+row2 RN 5
+row3 RN 3
+
+row4 RN 8
+row5 RN 9
+row6 RN 10
+row7 RN 12
+
+tunpk0 RN 2
+tunpk2 RN 10
+tunpk3 RN 12
+
+tunpk4 RN 4
+tunpk5 RN 5
+tunpk6 RN 14
+tunpk7 RN 2
+
+;// Filtering
+
+dp0q0 RN 12
+dp1p0 RN 12
+dq1q0 RN 12
+
+ap0q0 RN 4
+filt RN 2
+
+m00 RN 14
+m01 RN 11
+
+pQ0 RN 0
+Step RN 1
+
+;// Output
+
+P_0 RN 6
+Q_0 RN 7
+
+;//Declarations for bSLT4 kernel
+
+tC RN 12
+tC0 RN 5
+tC1 RN 12
+pos RN 5
+neg RN 9
+
+;//Declarations for bSGE4 kernel
+
+
+;// Miscellanous
+XY RN 8
+
+a RN 10
+t1 RN 10
+t2 RN 12
+t3 RN 14
+t4 RN 6
+t5 RN 5
+
+
+ ;// Allocate stack memory
+ M_ALLOC4 ppThresholds,4
+ M_ALLOC8 pAlphaBeta0,8
+ M_ALLOC8 pAlphaBeta1,8
+ M_ALLOC8 pXYBS,4
+ M_ALLOC4 ppBS,4
+
+ ;// Function header
+ M_START omxVCM4P10_FilterDeblockingChroma_VerEdge_I, r11
+
+ ;//Input arguments on the stack
+ M_ARG ppThresholdsArg, 4
+ M_ARG ppBSArg, 4
+
+ LDRB alpha1, [pAlphaArg,#1]
+ LDRB beta1, [pBetaArg,#1]
+ M_LDR pThresholds, ppThresholdsArg
+ LDR a,=MASK_1
+ LDRB beta0, [pBetaArg]
+ M_STR pThresholds, ppThresholds
+ LDRB alpha0, [pAlphaArg]
+
+ MUL alpha1, alpha1, a
+ MUL beta1, beta1, a
+ MUL alpha0, alpha0, a
+ MUL beta0, beta0, a
+
+ M_STRD alpha1, beta1, pAlphaBeta1
+ M_LDR pBS, ppBSArg
+ M_STRD alpha0, beta0, pAlphaBeta0
+
+ LDR XY,=LOOP_COUNT
+ M_STRD XY, pBS, pXYBS
+
+
+LoopY
+LoopX
+;//---------------Load Pixels-------------------
+
+;//----------------Pack q0-q1-----------------------
+ LDRH bS, [pBS], #8
+ LDR mask, =MASK_2
+
+ M_LDRH row4, [pQ0], srcdstStep
+ CMP bS, #0
+ M_STR pBS, ppBS
+ M_LDRH row5, [pQ0], srcdstStep
+ BEQ.W NoFilterBS0
+ LDRH row6, [pQ0]
+ LDRH row7, [pQ0, srcdstStep]
+
+ ;// row4 = [0 0 r0q0 r0q1]
+ ;// row5 = [0 0 r1q0 r1q1]
+ ;// row6 = [0 0 r2q0 r2q1]
+ ;// row7 = [0 0 r3q0 r3q1]
+
+ AND tunpk4, mask, row4
+ AND tunpk5, mask, row4, LSL#8
+ UXTAB tunpk4, tunpk4, row5, ROR#8
+ UXTAB tunpk5, tunpk5, row5
+ AND tunpk6, mask, row6
+ AND tunpk7, mask, row6, LSL#8
+ UXTAB tunpk6, tunpk6, row7, ROR#8
+ UXTAB tunpk7, tunpk7, row7
+
+ ;// tunpk4 = [0 0 r0q0 r1q0]
+ ;// tunpk5 = [0 0 r0q1 r1q1]
+ ;// tunpk6 = [0 0 r2q0 r3q0]
+ ;// tunpk7 = [0 0 r2q1 r3q1]
+
+ SUB pQ0, pQ0, srcdstStep, LSL #1
+ SUB pQ0, pQ0, #2
+
+ PKHBT q_1, tunpk6, tunpk4, LSL#16
+ PKHBT q_0, tunpk7, tunpk5, LSL#16
+
+ ;// q_0 = [r0q0 r1q0 r2q0 r3q0]
+ ;// q_1 = [r0q1 r1q1 r2q1 r3q1]
+
+
+;//----------------Pack p0-p1-----------------------
+
+ M_LDRH row0, [pQ0], srcdstStep
+ M_LDRH row1, [pQ0], srcdstStep
+ LDRH row2, [pQ0]
+ LDRH row3, [pQ0, srcdstStep]
+
+ ;// row0 = [0 0 r0p0 r0p1]
+ ;// row1 = [0 0 r1p0 r1p1]
+ ;// row2 = [0 0 r2p0 r2p1]
+ ;// row3 = [0 0 r3p0 r3p1]
+
+ AND tunpk2, mask, row0
+ AND tunpk6, mask, row0, LSL#8
+ UXTAB tunpk2, tunpk2, row1, ROR#8
+ UXTAB tunpk6, tunpk6, row1
+
+ AND tunpk0, mask, row2
+ AND tunpk3, mask, row2, LSL#8
+ UXTAB tunpk0, tunpk0, row3, ROR#8
+ UXTAB tunpk3, tunpk3, row3
+
+ ;// tunpk2 = [0 0 r0p0 r1p0]
+ ;// tunpk6 = [0 0 r0p1 r1p1]
+ ;// tunpk0 = [0 0 r2p0 r3p0]
+ ;// tunpk3 = [0 0 r2p1 r3p1]
+
+ PKHBT p_0, tunpk0, tunpk2, LSL#16
+ M_LDR bSTemp, ppBS
+ PKHBT p_1, tunpk3, tunpk6, LSL#16
+
+ ;// p_0 = [r0p0 r1p0 r2p0 r3p0]
+ ;// p_1 = [r0p1 r1p1 r2p1 r3p1]
+
+;//--------------Filtering Decision -------------------
+ USUB8 dp0q0, p_0, q_0
+ LDR m01, =MASK_1
+ LDRH bSTemp, [bSTemp ,#-8]
+ MOV m00, #MASK_0 ;// 00000000 mask
+
+ MOV filt, m01
+ TST bSTemp, #0xff00
+ MOVEQ filt, filt, LSL #16
+ TST bSTemp, #0xff
+ MOVEQ filt, filt, LSR #16
+ TST bSTemp, #4
+
+ ;// Check |p0-q0|<Alpha
+ USUB8 a, q_0, p_0
+ SEL ap0q0, a, dp0q0
+ USUB8 a, ap0q0, alpha
+ SEL filt, m00, filt
+
+ ;// Check |p1-p0|<Beta
+ USUB8 dp1p0, p_1, p_0
+ USUB8 a, p_0, p_1
+ SEL a, a, dp1p0
+ USUB8 a, a, beta
+ SEL filt, m00, filt
+
+ ;// Check |q1-q0|<Beta
+ USUB8 dq1q0, q_1, q_0
+ USUB8 a, q_0, q_1
+ SEL a, a, dq1q0
+ USUB8 a, a, beta
+ SEL filt, m00, filt
+
+ BEQ bSLT4
+;//-------------------Filter--------------------
+bSGE4
+ ;//---------bSGE4 Execution---------------
+ CMP filt, #0
+
+ M_LDR pThresholds, ppThresholds
+
+ ;// Compute P0b
+ UHADD8 t1, p_0, q_1
+ BEQ NoFilterFilt0
+ MVN t2, p_1
+ UHSUB8 t1, t1, t2
+ USUB8 t2, filt, m01
+ EOR t1, t1, m01, LSL #7
+
+ ADD pThresholds,pThresholds, #4
+
+ ;// Compute Q0b
+ UHADD8 t2, q_0, p_1
+ MVN t3, q_1
+ UHSUB8 t2, t2, t3
+ M_STR pThresholds, ppThresholds
+ SEL P_0, t1, p_0
+ EOR t2, t2, m01, LSL #7
+ SEL Q_0, t2, q_0
+
+ B StoreResultAndExit
+
+;//---------- Exit of LoopX --------------
+;//---- for the case of no filtering -----
+
+NoFilterFilt0
+ ADD pQ0, pQ0, #2
+NoFilterBS0
+ M_LDR pThresholds, ppThresholds
+ SUB pQ0, pQ0, srcdstStep, LSL #1
+ ADD pQ0, pQ0, #4
+ ADD pThresholds, pThresholds, #4
+ ;// Load counter for LoopX
+ M_LDRD XY, pBS, pXYBS
+ M_STR pThresholds, ppThresholds
+ M_LDRD alpha, beta, pAlphaBeta1
+
+ ;// Align the pointer
+ ADDS XY, XY, XY
+ M_STR XY, pXYBS
+ BCC LoopY
+ B ExitLoopY
+
+bSLT4
+ ;//---------bSLT4 Execution---------------
+ M_LDR pThresholds, ppThresholds
+ CMP filt, #0
+
+
+ ;// Since beta <= 18 and alpha <= 255 we know
+ ;// -254 <= p0-q0 <= 254
+ ;// -17 <= q1-q0 <= 17
+ ;// -17 <= p1-p0 <= 17
+
+ ;// delta = Clip3( -tC, tC, ((((q0-p0)<<2) + (p1-q1) + 4)>>3))
+ ;//
+ ;// Calculate A = (((q0-p0)<<2) + (p1-q1) + 4)>>3
+ ;// = (4*q0 - 4*p0 + p1 - q1 + 4)>>3
+ ;// = ((p1-p0) - (q1-q0) - 3*(p0-q0) + 4)>>3
+
+ USUB8 t1, p_1, p_0
+ USUB8 t2, q_1, q_0
+ BEQ NoFilterFilt0
+
+ LDRB tC0, [pThresholds], #1
+ SSUB8 t1, t1, t2
+ LDRB tC1, [pThresholds], #3
+ M_STR pThresholds, ppThresholds
+ UHSUB8 t4, p_0, q_0
+ ORR tC, tC1, tC0, LSL #16
+ USUB8 t5, p_0, q_0
+ AND t5, t5, m01
+ SHSUB8 t1, t1, t5
+ ORR tC, tC, LSL #8
+ SSUB8 t1, t1, t5
+ SHSUB8 t1, t1, t4
+ UQADD8 tC, tC, m01
+ SADD8 t1, t1, m01
+ USUB8 t5, filt, m01
+ SHSUB8 t1, t1, t4
+ SEL tC, tC, m00
+
+ ;// Split into positive and negative part and clip
+
+ SSUB8 t1, t1, m00
+ SEL pos, t1, m00
+ USUB8 neg, pos, t1
+ USUB8 t3, pos, tC
+ SEL pos, tC, pos
+ USUB8 t3, neg, tC
+ SEL neg, tC, neg
+ UQADD8 P_0, p_0, pos
+ UQSUB8 Q_0, q_0, pos
+ UQSUB8 P_0, P_0, neg
+ UQADD8 Q_0, Q_0, neg
+
+ ;// Choose to store the filtered
+ ;// value or the original pixel
+ USUB8 t1, filt, m01
+ SEL P_0, P_0, p_0
+ SEL Q_0, Q_0, q_0
+
+StoreResultAndExit
+
+ ;//---------Store result---------------
+
+ ;// P_0 = [r0p0 r1p0 r2p0 r3p0]
+ ;// Q_0 = [r0q0 r1q0 r2q0 r3q0]
+
+ SUB pQ0, pQ0, srcdstStep, LSL #1
+ ADD pQ0, pQ0, #1
+
+ MOV t1, Q_0, LSR #24
+ STRB t1, [pQ0, #1]
+ MOV t1, P_0, LSR #24
+ M_STRB t1, [pQ0], srcdstStep
+
+ MOV t1, Q_0, LSR #16
+ STRB t1, [pQ0, #1]
+ MOV t1, P_0, LSR #16
+ M_STRB t1, [pQ0], srcdstStep
+
+ MOV t1, P_0, LSR #8
+ STRB t1, [pQ0]
+ STRB P_0, [pQ0, srcdstStep]
+ MOV t1, Q_0, LSR #8
+ STRB t1, [pQ0, #1]!
+ STRB Q_0, [pQ0, srcdstStep]
+
+ M_LDRD XY, pBS, pXYBS
+ M_LDRD alpha, beta, pAlphaBeta1
+
+ SUB pQ0, pQ0, srcdstStep, LSL #1
+ ADD pQ0, pQ0, #4
+
+ ADDS XY, XY, XY
+ M_STR XY, pXYBS
+ BCC LoopX
+
+;//-------- Common Exit of LoopY -----------------
+ ;// Align the pointers
+
+ExitLoopY
+
+ M_LDR pThresholds, ppThresholds
+ SUB pQ0, pQ0, #8
+ ADD pQ0, pQ0, srcdstStep, LSL #2
+ SUB pBS, pBS, #14
+ SUB pThresholds, pThresholds, #6
+ M_STR pThresholds, ppThresholds
+
+ M_LDRD alpha, beta, pAlphaBeta0
+
+ BNE LoopY
+ MOV r0, #OMX_Sts_NoErr
+;//-----------------End Filter--------------------
+
+ M_END
+
+ ENDIF
+
+ END
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
new file mode 100644
index 0000000..1b84080
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
@@ -0,0 +1,331 @@
+;//
+;//
+;// File Name: omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ IMPORT armVCM4P10_DeblockingLumabSLT4_unsafe
+ IMPORT armVCM4P10_DeblockingLumabSGE4_unsafe
+
+
+
+ IF ARM1136JS
+
+
+MASK_0 EQU 0x00000000
+MASK_1 EQU 0x01010101
+MASK_2 EQU 0xff00ff00
+LOOP_COUNT EQU 0x11110000
+
+;// Declare input registers
+
+pSrcDst RN 0
+srcdstStep RN 1
+pAlphaArg RN 2
+pBetaArg RN 3
+
+pThresholds RN 14
+pBS RN 9
+pQ0 RN 0
+bS RN 2
+
+alpha RN 6
+alpha0 RN 6
+alpha1 RN 8
+
+beta RN 7
+beta0 RN 7
+beta1 RN 9
+
+;// Declare Local/Temporary variables
+
+;// Pixels
+p_0 RN 3
+p_1 RN 5
+p_2 RN 4
+p_3 RN 2
+q_0 RN 8
+q_1 RN 9
+q_2 RN 10
+q_3 RN 12
+
+;// Filtering
+
+dp0q0 RN 12
+dp1p0 RN 12
+dq1q0 RN 12
+dp2p0 RN 12
+dq2q0 RN 12
+
+ap0q0 RN 1
+filt RN 2
+
+m00 RN 14
+m01 RN 11
+
+apflg RN 0
+aqflg RN 6
+apqflg RN 0
+
+
+;//Declarations for bSLT4 kernel
+
+tC0 RN 7
+ptC0 RN 1
+
+pQ0a RN 0
+Stepa RN 1
+maska RN 14
+
+P0a RN 1
+P1a RN 8
+Q0a RN 7
+Q1a RN 11
+
+;//Declarations for bSGE4 kernel
+
+pQ0b RN 0
+Stepb RN 1
+maskb RN 14
+
+P0b RN 6
+P1b RN 7
+P2b RN 1
+P3b RN 3
+
+Q0b RN 9
+Q1b RN 0
+Q2b RN 2
+Q3b RN 3
+
+;// Miscellanous
+XY RN 8
+t0 RN 3
+t1 RN 12
+t2 RN 14
+t7 RN 7
+t4 RN 4
+t5 RN 1
+t8 RN 6
+a RN 0
+
+
+
+
+ ;// Allocate stack memory
+ M_ALLOC4 ppThresholds,4
+ M_ALLOC4 pQ_3,4
+ M_ALLOC4 pP_3,4
+ M_ALLOC8 pAlphaBeta0,8
+ M_ALLOC8 pAlphaBeta1,8
+ M_ALLOC8 pXYBS,4
+ M_ALLOC4 ppBS,4
+ M_ALLOC8 ppQ0Step,4
+ M_ALLOC4 pStep,4
+
+ ;// Function header
+ M_START omxVCM4P10_FilterDeblockingLuma_HorEdge_I, r11
+
+ ;//Input arguments on the stack
+ M_ARG ppThresholdsArg, 4
+ M_ARG ppBSArg, 4
+
+ LDR t4,=MASK_1
+
+ LDRB alpha0, [pAlphaArg]
+ LDRB beta0, [pBetaArg]
+ LDRB alpha1, [pAlphaArg,#1]
+ LDRB beta1, [pBetaArg,#1]
+
+ MUL alpha0, alpha0, t4
+ MUL beta0, beta0, t4
+ MUL alpha1, alpha1, t4
+ MUL beta1, beta1, t4
+
+ M_STRD alpha0, beta0, pAlphaBeta0
+ M_STRD alpha1, beta1, pAlphaBeta1
+
+ LDR XY,=LOOP_COUNT
+ M_LDR pBS, ppBSArg
+ M_LDR pThresholds, ppThresholdsArg
+ M_STR srcdstStep, pStep
+ M_STRD XY, pBS, pXYBS
+ SUB pQ0, pQ0, srcdstStep, LSL #2
+ M_STR pThresholds, ppThresholds
+LoopY
+LoopX
+;//---------------Load Pixels-------------------
+ M_STR pQ0, ppQ0Step
+ M_LDR p_3, [pQ0], srcdstStep
+ M_LDR p_2, [pQ0], srcdstStep
+ M_STR p_3, pP_3
+ LDRB bS, [pBS], #1
+ M_STR pBS, ppBS
+ M_LDR p_1, [pQ0], srcdstStep
+ CMP bS, #0
+ M_LDR p_0, [pQ0], srcdstStep
+ M_LDR q_0, [pQ0], srcdstStep
+ M_LDR q_1, [pQ0], srcdstStep
+ M_LDR q_2, [pQ0], srcdstStep
+ M_LDR q_3, [pQ0], srcdstStep
+ BEQ NoFilterBS0
+ CMP bS, #4
+ M_STR q_3, pQ_3
+
+;//--------------Filtering Decision -------------------
+ LDR m01, =MASK_1 ;// 01010101 mask
+ MOV m00, #MASK_0 ;// 00000000 mask
+
+ ;// Check |p0-q0|<Alpha
+ USUB8 dp0q0, p_0, q_0
+ USUB8 a, q_0, p_0
+ SEL ap0q0, a, dp0q0
+ USUB8 a, ap0q0, alpha
+ SEL filt, m00, m01
+
+ ;// Check |p1-p0|<Beta
+ USUB8 dp1p0, p_1, p_0
+ USUB8 a, p_0, p_1
+ SEL a, a, dp1p0
+ USUB8 a, a, beta
+ SEL filt, m00, filt
+
+ ;// Check |q1-q0|<Beta
+ USUB8 dq1q0, q_1, q_0
+ USUB8 a, q_0, q_1
+ SEL a, a, dq1q0
+ USUB8 a, a, beta
+ SEL filt, m00, filt
+
+ ;// Check ap<Beta
+ USUB8 dp2p0, p_2, p_0
+ USUB8 a, p_0, p_2
+ SEL a, a, dp2p0
+ USUB8 a, a, beta
+ SEL apflg, m00, filt ;// apflg = filt && (ap<beta)
+
+ ;// Check aq<Beta
+ USUB8 dq2q0, q_2, q_0
+ USUB8 t2, q_0, q_2
+ SEL t2, t2, dq2q0
+ USUB8 t2, t2, beta
+ MOV t7,#0
+
+ BLT bSLT4
+;//-------------------Filter--------------------
+bSGE4
+ ;//---------bSGE4 Execution---------------
+ SEL t1, t7, filt ;// aqflg = filt && (aq<beta)
+ CMP filt, #0
+ ORR apqflg, apflg, t1, LSL #1
+ M_LDRD pQ0, srcdstStep, ppQ0Step, EQ
+ BEQ NoFilterFilt0
+
+ BL armVCM4P10_DeblockingLumabSGE4_unsafe
+
+ ;//---------Store result---------------
+ M_LDR pThresholds, ppThresholds
+ MOV p_2, Q1b
+ MOV p_1, P2b
+ M_LDRD pQ0b, Stepb, ppQ0Step
+ ADD pThresholds, #1
+ M_STR pThresholds, ppThresholds
+ M_STR p_1, [pQ0b, Stepb]!
+ M_STR P1b, [pQ0b, Stepb]!
+ M_STR P0b, [pQ0b, Stepb]!
+ M_STR Q0b, [pQ0b, Stepb]!
+ STR p_2, [pQ0b, Stepb]
+ STR Q2b, [pQ0b, Stepb, LSL #1]
+
+
+ M_LDRD XY, pBS, pXYBS
+ SUB pQ0, pQ0b, Stepb, LSL #2
+ ADD pQ0, pQ0, #4
+ M_LDRD alpha, beta, pAlphaBeta0
+ ADDS XY, XY, XY
+ M_STR XY, pXYBS
+ BCC LoopX
+ B ExitLoopY
+
+;//---------- Exit of LoopX --------------
+;//---- for the case of no filtering -----
+
+NoFilterBS0
+ SUB pQ0, pQ0, srcdstStep, LSL #3
+NoFilterFilt0
+ ADD pQ0, pQ0, #4
+ ;// Load counter for LoopX
+ M_LDRD XY, pBS, pXYBS
+ M_LDR pThresholds, ppThresholds
+ M_LDRD alpha, beta, pAlphaBeta0
+
+ ;// Align the pointers
+ ADDS XY, XY, XY
+ ADD pThresholds, pThresholds, #1
+ M_STR pThresholds, ppThresholds
+ M_STR XY, pXYBS
+ BCC LoopX
+ B ExitLoopY
+
+bSLT4
+ ;//---------bSLT4 Execution---------------
+ SEL aqflg, t7, filt ;// aqflg = filt && (aq<beta)
+ M_LDR ptC0, ppThresholds
+ CMP filt, #0
+ M_LDRD pQ0, srcdstStep, ppQ0Step, EQ
+ BEQ NoFilterFilt0
+
+ LDRB tC0, [ptC0], #1
+ M_STR ptC0, ppThresholds
+
+ BL armVCM4P10_DeblockingLumabSLT4_unsafe
+
+ ;//---------Store result---------------
+ MOV p_2, P0a
+ M_LDRD pQ0a, Stepa, ppQ0Step
+ M_STR P1a, [pQ0a, Stepa, LSL #1]!
+ M_STR p_2, [pQ0a, Stepa]!
+ M_STR Q0a, [pQ0a, Stepa]!
+ STR Q1a, [pQ0a, Stepa]
+
+ ;// Load counter
+ M_LDRD XY, pBS, pXYBS
+ M_LDRD alpha, beta, pAlphaBeta0
+
+ SUB pQ0, pQ0a, Stepa, LSL #2
+ ADD pQ0, pQ0, #4
+
+ ADDS XY, XY, XY
+ M_STR XY, pXYBS
+ BCC LoopX
+
+;//-------- Common Exit of LoopY -----------------
+ ;// Align the pointers
+ExitLoopY
+ M_LDRD alpha, beta, pAlphaBeta1
+ SUB pQ0, pQ0, #16
+ ADD pQ0, pQ0, srcdstStep, LSL #2
+ M_STRD alpha, beta, pAlphaBeta0
+
+ BNE LoopY
+ MOV r0, #OMX_Sts_NoErr
+;//-----------------End Filter--------------------
+ M_END
+
+ ENDIF
+
+
+ END
+
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
new file mode 100644
index 0000000..417ddc2
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
@@ -0,0 +1,550 @@
+;//
+;//
+;// File Name: omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ IMPORT armVCM4P10_DeblockingLumabSLT4_unsafe
+ IMPORT armVCM4P10_DeblockingLumabSGE4_unsafe
+
+
+ IF ARM1136JS
+
+MASK_0 EQU 0x00000000
+MASK_1 EQU 0x01010101
+MASK_2 EQU 0xff00ff00
+LOOP_COUNT EQU 0x11110000
+
+;// Declare input registers
+
+pSrcDst RN 0
+srcdstStep RN 1
+pAlphaArg RN 2
+pBetaArg RN 3
+
+pThresholds RN 14
+pBS RN 9
+pQ0 RN 0
+bS RN 2
+
+alpha RN 6
+alpha0 RN 6
+alpha1 RN 8
+
+beta RN 7
+beta0 RN 7
+beta1 RN 9
+
+;// Declare Local/Temporary variables
+
+;// Pixels
+p_0 RN 3
+p_1 RN 5
+p_2 RN 4
+p_3 RN 2
+q_0 RN 8
+q_1 RN 9
+q_2 RN 10
+q_3 RN 12
+
+;// Unpacking
+mask RN 11
+
+row0 RN 2
+row1 RN 4
+row2 RN 5
+row3 RN 3
+
+row4 RN 8
+row5 RN 9
+row6 RN 10
+row7 RN 12
+row8 RN 14
+row9 RN 7
+
+tunpk0 RN 8
+tunpk1 RN 9
+tunpk2 RN 10
+tunpk3 RN 12
+tunpk4 RN 0
+
+tunpk5 RN 1
+tunpk6 RN 14
+tunpk7 RN 2
+tunpk8 RN 5
+tunpk9 RN 6
+
+
+;// Filtering
+
+dp0q0 RN 12
+dp1p0 RN 12
+dq1q0 RN 12
+dp2p0 RN 12
+dq2q0 RN 12
+
+ap0q0 RN 1
+filt RN 2
+
+m00 RN 14
+m01 RN 11
+
+apflg RN 0
+aqflg RN 6
+apqflg RN 0
+
+
+;//Declarations for bSLT4 kernel
+
+tC0 RN 7
+ptC0 RN 1
+
+pQ0a RN 0
+Stepa RN 1
+maska RN 14
+
+P0a RN 1
+P1a RN 8
+Q0a RN 7
+Q1a RN 11
+
+;//Declarations for bSGE4 kernel
+
+pQ0b RN 0
+Stepb RN 1
+maskb RN 14
+
+P0b RN 6
+P1b RN 7
+P2b RN 1
+P3b RN 3
+
+Q0b RN 9
+Q1b RN 0
+Q2b RN 2
+Q3b RN 3
+
+;// Miscellanous
+XY RN 8
+t0 RN 3
+t1 RN 12
+t2 RN 14
+t7 RN 7
+t4 RN 4
+t5 RN 1
+t8 RN 6
+a RN 0
+
+
+
+ ;// Allocate stack memory
+ M_ALLOC4 ppThresholds,4
+ M_ALLOC4 pQ_3,4
+ M_ALLOC4 pP_3,4
+ M_ALLOC8 pAlphaBeta0,8
+ M_ALLOC8 pAlphaBeta1,8
+ M_ALLOC8 pXYBS,4
+ M_ALLOC4 ppBS,4
+ M_ALLOC8 ppQ0Step,4
+ M_ALLOC4 pStep,4
+
+ ;// Function header
+ M_START omxVCM4P10_FilterDeblockingLuma_VerEdge_I, r11
+
+ ;//Input arguments on the stack
+ M_ARG ppThresholdsArg, 4
+ M_ARG ppBSArg, 4
+
+ LDR t4,=MASK_1
+
+ LDRB alpha0, [pAlphaArg]
+ LDRB beta0, [pBetaArg]
+ LDRB alpha1, [pAlphaArg,#1]
+ LDRB beta1, [pBetaArg,#1]
+
+ MUL alpha0, alpha0, t4
+ MUL beta0, beta0, t4
+ MUL alpha1, alpha1, t4
+ MUL beta1, beta1, t4
+
+ M_STRD alpha0, beta0, pAlphaBeta0
+ M_STRD alpha1, beta1, pAlphaBeta1
+
+ LDR XY,=LOOP_COUNT
+ M_LDR pBS, ppBSArg
+ M_LDR pThresholds, ppThresholdsArg
+ M_STR srcdstStep, pStep
+ M_STRD XY, pBS, pXYBS
+ M_STR pThresholds, ppThresholds
+
+ SUB pQ0, pQ0, #4
+LoopY
+;//---------------Load Pixels-------------------
+
+;//----------------Pack p0-p3-----------------------
+ LDR mask, =MASK_2
+
+ M_LDR row0, [pQ0], srcdstStep
+ M_LDR row1, [pQ0], srcdstStep
+ LDR row2, [pQ0]
+ LDR row3, [pQ0, srcdstStep]
+ SUB pQ0, pQ0, srcdstStep, LSL #1
+
+ ;// row0 = [r0p0 r0p1 r0p2 r0p3]
+ ;// row1 = [r1p0 r1p1 r1p2 r1p3]
+ ;// row2 = [r2p0 r2p1 r2p2 r2p3]
+ ;// row3 = [r3p0 r3p1 r3p2 r3p3]
+
+ AND tunpk0, mask, row0
+ AND tunpk6, mask, row0, LSL#8
+ UXTAB16 tunpk0, tunpk0, row1, ROR#8
+ UXTAB16 tunpk6, tunpk6, row1
+ AND tunpk2, mask, row2
+ AND tunpk3, mask, row2, LSL#8
+ UXTAB16 tunpk2, tunpk2, row3, ROR#8
+ UXTAB16 tunpk3, tunpk3, row3
+
+ ;// tunpk0 = [r0p0 r1p0 r0p2 r1p2]
+ ;// tunpk6 = [r0p1 r1p1 r0p3 r1p3]
+ ;// tunpk2 = [r2p0 r3p0 r2p2 r3p2]
+ ;// tunpk3 = [r2p1 r3p1 r2p3 r3p3]
+
+ PKHTB p_0, tunpk0, tunpk2, ASR#16
+ PKHTB p_1, tunpk6, tunpk3, ASR#16
+ PKHBT p_2, tunpk2, tunpk0, LSL#16
+ PKHBT p_3, tunpk3, tunpk6, LSL#16
+
+
+ ;// p_0 = [r0p0 r1p0 r2p0 r3p0]
+ ;// p_1 = [r0p1 r1p1 r2p1 r3p1]
+ ;// p_2 = [r0p2 r1p2 r2p1 r3p2]
+ ;// p_3 = [r0p3 r1p3 r2p3 r3p3]
+
+ M_STR p_3, pP_3
+
+;//----------------Pack q0-q3-----------------------
+LoopX
+ LDRB bS, [pBS], #4
+ M_STR pQ0, ppQ0Step
+ LDR mask, =MASK_2
+ CMP bS, #0
+ M_STR pBS, ppBS
+
+ LDR row4, [pQ0, #4]!
+ BEQ.W NoFilterBS0
+ M_LDR row5, [pQ0, srcdstStep]!
+ M_LDR row6, [pQ0, srcdstStep]!
+ M_LDR row7, [pQ0, srcdstStep]
+
+ ;// row4 = [r0q3 r0q2 r0q1 r0q0]
+ ;// row5 = [r1q3 r1q2 r1q1 r1q0]
+ ;// row6 = [r2q3 r2q2 r2q1 r2q0]
+ ;// row7 = [r3q3 r3q2 r3q1 r3q0]
+
+ AND tunpk4, mask, row4
+ CMP bS, #4
+ AND tunpk5, mask, row4, LSL#8
+ UXTAB16 tunpk4, tunpk4, row5, ROR#8
+ UXTAB16 tunpk5, tunpk5, row5
+ AND tunpk6, mask, row6
+ AND tunpk7, mask, row6, LSL#8
+ UXTAB16 tunpk6, tunpk6, row7, ROR#8
+ UXTAB16 tunpk7, tunpk7, row7
+
+ ;// tunpk4 = [r0q0 r1q0 r0q2 r1q2]
+ ;// tunpk5 = [r0q1 r1q1 r0q3 r1q3]
+ ;// tunpk6 = [r2q0 r3q0 r2q2 r3q2]
+ ;// tunpk7 = [r2q1 r3q1 r2q3 r3q3]
+
+ PKHTB q_3, tunpk4, tunpk6, ASR#16
+ PKHTB q_2, tunpk5, tunpk7, ASR#16
+ PKHBT q_1, tunpk6, tunpk4, LSL#16
+ M_STR q_3, pQ_3
+ PKHBT q_0, tunpk7, tunpk5, LSL#16
+
+
+ ;// q_0 = [r0q0 r1q0 r2q0 r3q0]
+ ;// q_1 = [r0q1 r1q1 r2q1 r3q1]
+ ;// q_2 = [r0q2 r1q2 r2q1 r3q2]
+ ;// q_3 = [r0q3 r1q3 r2q3 r3q3]
+
+
+;//--------------Filtering Decision -------------------
+ LDR m01, =MASK_1 ;// 01010101 mask
+ MOV m00, #MASK_0 ;// 00000000 mask
+
+ ;// Check |p0-q0|<Alpha
+ USUB8 dp0q0, p_0, q_0
+ USUB8 a, q_0, p_0
+ SEL ap0q0, a, dp0q0
+ USUB8 a, ap0q0, alpha
+ SEL filt, m00, m01
+
+ ;// Check |p1-p0|<Beta
+ USUB8 dp1p0, p_1, p_0
+ USUB8 a, p_0, p_1
+ SEL a, a, dp1p0
+ USUB8 a, a, beta
+ SEL filt, m00, filt
+
+ ;// Check |q1-q0|<Beta
+ USUB8 dq1q0, q_1, q_0
+ USUB8 a, q_0, q_1
+ SEL a, a, dq1q0
+ USUB8 a, a, beta
+ SEL filt, m00, filt
+
+ ;// Check ap<Beta
+ USUB8 dp2p0, p_2, p_0
+ USUB8 a, p_0, p_2
+ SEL a, a, dp2p0
+ USUB8 a, a, beta
+ SEL apflg, m00, filt ;// apflg = filt && (ap<beta)
+
+ ;// Check aq<Beta
+ USUB8 dq2q0, q_2, q_0
+ USUB8 t2, q_0, q_2
+ SEL t2, t2, dq2q0
+ USUB8 t2, t2, beta
+ MOV t7,#0
+
+
+ BLT bSLT4
+;//-------------------Filter--------------------
+bSGE4
+ ;//---------bSGE4 Execution---------------
+ SEL t1, t7, filt ;// aqflg = filt && (aq<beta)
+ CMP filt, #0
+ ORR apqflg, apflg, t1, LSL #1
+ M_LDRD pQ0, srcdstStep, ppQ0Step, EQ
+ BEQ NoFilterFilt0
+
+ BL armVCM4P10_DeblockingLumabSGE4_unsafe
+
+ ;//---------Store result---------------
+
+ LDR maskb,=MASK_2
+
+ ;// P0b = [r0p0 r1p0 r2p0 r3p0]
+ ;// P1b = [r0p1 r1p1 r2p1 r3p1]
+ ;// P2b = [r0p2 r1p2 r2p2 r3p2]
+ ;// P3b = [r0p3 r1p3 r2p3 r3p3]
+
+ M_LDR P3b, pP_3
+ M_STR Q0b, pP_3
+
+ ;//------Pack p0-p3------
+ AND tunpk0, maskb, P0b
+ AND tunpk2, maskb, P0b, LSL#8
+ UXTAB16 tunpk0, tunpk0, P1b, ROR#8
+ UXTAB16 tunpk2, tunpk2, P1b
+
+ AND tunpk3, maskb, P2b
+ AND tunpk8, maskb, P2b, LSL#8
+ UXTAB16 tunpk3, tunpk3, P3b, ROR#8
+ UXTAB16 tunpk8, tunpk8, P3b
+
+ ;// tunpk0 = [r0p0 r0p1 r2p0 r2p1]
+ ;// tunpk2 = [r1p0 r1p1 r3p0 r3p1]
+ ;// tunpk3 = [r0p2 r0p3 r2p2 r2p3]
+ ;// tunpk8 = [r1p2 r1p3 r3p2 r3p3]
+
+ MOV p_2, Q1b
+ M_LDRD pQ0b, Stepb, ppQ0Step
+
+ PKHTB row9, tunpk0, tunpk3, ASR#16
+ PKHBT row7, tunpk3, tunpk0, LSL#16
+ PKHTB row3, tunpk2, tunpk8, ASR#16
+ PKHBT row6, tunpk8, tunpk2, LSL#16
+
+ ;// row9 = [r0p0 r0p1 r0p2 r0p3]
+ ;// row3 = [r1p0 r1p1 r1p2 r1p3]
+ ;// row7 = [r2p0 r2p1 r2p2 r2p3]
+ ;// row6 = [r3p0 r3p1 r3p2 r3p3]
+
+ M_STR row9, [pQ0b], Stepb
+ STR row7, [pQ0b, Stepb]
+ STR row6, [pQ0b, Stepb, LSL #1]
+ STR row3, [pQ0b], #4
+
+ M_LDR Q3b, pQ_3
+
+ ;// Q0b = [r0q0 r1q0 r2q0 r3q0]
+ ;// Q1b = [r0q1 r1q1 r2q1 r3q1]
+ ;// Q2b = [r0q2 r1q2 r2q2 r3q2]
+ ;// Q3b = [r0q3 r1q3 r2q3 r3q3]
+
+ ;//------Pack q0-q3------
+ AND tunpk0, maskb, p_2
+ AND tunpk2, maskb, p_2, LSL#8
+ UXTAB16 tunpk0, tunpk0, Q0b, ROR#8
+ UXTAB16 tunpk2, tunpk2, Q0b
+
+ AND tunpk3, maskb, Q3b
+ AND tunpk8, maskb, Q3b, LSL#8
+ UXTAB16 tunpk3, tunpk3, Q2b, ROR#8
+ UXTAB16 tunpk8, tunpk8, Q2b
+
+ ;// tunpk0 = [r0q1 r0q0 r2q1 r2q0]
+ ;// tunpk2 = [r1q1 r1q0 r3q1 r3q0]
+ ;// tunpk3 = [r0q3 r0q2 r2q3 r2q2]
+ ;// tunpk8 = [r1q3 r1q2 r3q3 r3q2]
+
+ PKHTB row8, tunpk3, tunpk0, ASR#16
+ PKHBT row7, tunpk0, tunpk3, LSL#16
+ PKHTB row4, tunpk8, tunpk2, ASR#16
+ PKHBT row6, tunpk2, tunpk8, LSL#16
+
+ ;// row8 = [r0q0 r0q1 r0q2 r0q3]
+ ;// row4 = [r1q0 r1q1 r1q2 r1q3]
+ ;// row7 = [r2q0 r2q1 r2q2 r2q3]
+ ;// row6 = [r3q0 r3q1 r3q2 r3q3]
+
+ STR row4, [pQ0b]
+ STR row7, [pQ0b, Stepb]
+ STR row6, [pQ0b, Stepb, LSL #1]
+
+ SUB pQ0, pQ0b, Stepb
+ MOV p_1, Q2b
+
+ STR row8, [pQ0]
+
+ M_LDRD XY, pBS, pXYBS
+ M_LDR pThresholds, ppThresholds
+ M_LDRD alpha, beta, pAlphaBeta1
+
+ ADDS XY, XY, XY
+ ADD pThresholds, #4
+ M_STR pThresholds, ppThresholds
+ M_STR XY, pXYBS
+ BCC LoopX
+ B ExitLoopY
+
+;//---------- Exit of LoopX --------------
+;//---- for the case of no filtering -----
+
+NoFilterFilt0
+ ADD pQ0, pQ0, #4
+NoFilterBS0
+ ;// Load counter for LoopX
+ M_LDRD XY, pBS, pXYBS
+ M_LDR pThresholds, ppThresholds
+ M_LDRD alpha, beta, pAlphaBeta1
+
+ ;// Align the pointer
+ ADDS XY, XY, XY
+ ADD pThresholds, pThresholds, #4
+ M_STR pThresholds, ppThresholds
+ M_STR XY, pXYBS
+ BCC LoopY
+ B ExitLoopY
+
+bSLT4
+ ;//---------bSLT4 Execution---------------
+ SEL aqflg, t7, filt ;// aqflg = filt && (aq<beta)
+ M_LDR ptC0, ppThresholds
+ CMP filt, #0
+ M_LDRD pQ0, srcdstStep, ppQ0Step, EQ
+ BEQ NoFilterFilt0
+
+ LDRB tC0, [ptC0], #4
+ M_STR ptC0, ppThresholds
+
+ BL armVCM4P10_DeblockingLumabSLT4_unsafe
+
+ ;//---------Store result---------------
+ ;//--------Pack p1,p0,q1,q0------------
+
+ ;//Load destination pointer
+ LDR maska,=MASK_2
+ M_STR Q0a, pP_3
+ MOV p_1, q_2
+
+ ;// P1a = [r0p1 r1p1 r2p1 r3p1]
+ ;// P0a = [r0p0 r1p0 r2p0 r3p0]
+ ;// Q0a = [r0q0 r1q0 r2q0 r3q0]
+ ;// Q1a = [r0q1 r1q1 r2q1 r3q1]
+
+ AND tunpk1, maska, P0a
+ AND tunpk2, maska, P0a, LSL#8
+ UXTAB16 tunpk1, tunpk1, P1a, ROR#8
+ UXTAB16 tunpk2, tunpk2, P1a
+
+ M_LDRD pQ0a, Stepa, ppQ0Step
+
+ AND tunpk9, maska, Q1a
+ AND tunpk3, maska, Q1a, LSL#8
+ UXTAB16 tunpk9, tunpk9, Q0a, ROR#8
+ UXTAB16 tunpk3, tunpk3, Q0a
+
+ ;// tunpk1 = [r0p0 r0p1 r2p0 r2p1]
+ ;// tunpk2 = [r1p0 r1p1 r3p0 r3p1]
+ ;// tunpk9 = [r0q1 r0q0 r2q1 r2q0]
+ ;// tunpk3 = [r1q1 r1q0 r3q1 r3q0]
+
+ MOV t4, tunpk1, LSR #16
+ MOV t0, tunpk9, LSR #16
+
+ STRH t4,[pQ0a, #2]! ;//Stores [r0p0 r0p1]
+ STRH t0,[pQ0a, #2] ;//Stores [r0q0 r0q1]
+
+ MOV t4, tunpk2, LSR #16
+ MOV t0, tunpk3, LSR #16
+
+ M_STRH t4,[pQ0a, Stepa]! ;//Stores [r1p0 r1p1]
+ STRH t0,[pQ0a, #2] ;//Stores [r1q0 r1q1]
+
+ M_STRH tunpk1,[pQ0a, Stepa]! ;//Stores [r2p0 r2p1]
+ STRH tunpk2,[pQ0a, Stepa] ;//Stores [r3p0 r3p1]
+ STRH tunpk9,[pQ0a, #2]! ;//Stores [r2q0 r2q1]
+ STRH tunpk3,[pQ0a, Stepa] ;//Stores [r3q0 r3q1]
+
+ SUB pQ0, pQ0a, Stepa, LSL #1
+
+ ;// Load counter
+ M_LDRD XY, pBS, pXYBS
+
+ ;// Reload Pixels
+ M_LDR p_0, pQ_3
+ MOV p_2, Q1a
+
+ M_LDRD alpha, beta, pAlphaBeta1
+
+ ADDS XY, XY, XY
+ M_STR XY, pXYBS
+ BCC LoopX
+
+;//-------- Common Exit of LoopY -----------------
+ ;// Align the pointers
+ M_LDR pThresholds, ppThresholds
+ExitLoopY
+ SUB pQ0, pQ0, #16
+ ADD pQ0, pQ0, srcdstStep, LSL #2
+ SUB pBS, pBS, #15
+ SUB pThresholds, pThresholds, #15
+ M_STR pThresholds, ppThresholds
+
+ M_LDRD alpha, beta, pAlphaBeta0
+
+ BNE LoopY
+ MOV r0, #OMX_Sts_NoErr
+
+ M_END
+;//-----------------End Filter--------------------
+
+ ENDIF
+
+ END
+
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
new file mode 100644
index 0000000..de835bd
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
@@ -0,0 +1,79 @@
+/**
+ *
+ * File Name: omxVCM4P10_InterpolateChroma.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate 1/8 Pixel interpolation for Chroma Block
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+
+/**
+ * Function: omxVCM4P10_InterpolateChroma,
+ *
+ * Description:
+ * Performs 1/8-pixel interpolation for inter chroma MB.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrc Pointer to the source reference frame buffer
+ * [in] srcStep Reference frame step in byte
+ * [in] dstStep Destination frame step in byte. Must be multiple of roi.width.
+ * [in] dx Fractional part of horizontal motion vector component
+ * in 1/8 pixel unit;valid in the range [0,7]
+ * [in] dy Fractional part of vertical motion vector component
+ * in 1/8 pixel unit;valid in the range [0,7]
+ * [in] roi Dimension of the interpolation region;the parameters roi.width and roi.height must
+ * be equal to either 2, 4, or 8.
+ * [out] pDst Pointer to the destination frame buffer.
+ * if roi.width==2, 2-byte alignment required
+ * if roi.width==4, 4-byte alignment required
+ * if roi.width==8, 8-byte alignment required
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns OMX_Sts_BadArgErr:
+ * pSrc or pDst is NULL.
+ * srcStep or dstStep < 8.
+ * dx or dy is out of range [0-7].
+ * roi.width or roi.height is out of range {2,4,8}.
+ * roi.width is equal to 2, but pDst is not 2-byte aligned.
+ * roi.width is equal to 4, but pDst is not 4-byte aligned.
+ * roi.width is equal to 8, but pDst is not 8 byte aligned.
+ * srcStep or dstStep is not a multiple of 8.
+ *
+ */
+
+OMXResult omxVCM4P10_InterpolateChroma (
+ const OMX_U8* pSrc,
+ OMX_S32 srcStep,
+ OMX_U8* pDst,
+ OMX_S32 dstStep,
+ OMX_S32 dx,
+ OMX_S32 dy,
+ OMXSize roi
+ )
+{
+ return armVCM4P10_Interpolate_Chroma
+ ((OMX_U8*)pSrc, srcStep, pDst, dstStep, roi.width, roi.height, dx, dy);
+}
+
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
new file mode 100644
index 0000000..cf611a3
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
@@ -0,0 +1,426 @@
+;//
+;//
+;// File Name: omxVCM4P10_InterpolateLuma_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+;// Function:
+;// omxVCM4P10_InterpolateLuma
+;//
+;// This function implements omxVCM4P10_InterpolateLuma in v6 assembly.
+;// Performs quarter pel interpolation of inter luma MB.
+;// It's assumed that the frame is already padded when calling this function.
+;// Parameters:
+;// [in] pSrc Pointer to the source reference frame buffer
+;// [in] srcStep Reference frame step in byte
+;// [in] dstStep Destination frame step in byte. Must be multiple of roi.width
+;// [in] dx Fractional part of horizontal motion vector
+;// component in 1/4 pixel unit; valid in the range [0,3]
+;// [in] dy Fractional part of vertical motion vector
+;// component in 1/4 pixel unit; valid in the range [0,3]
+;// [in] roi Dimension of the interpolation region;the parameters roi.width and roi.height must
+;// be equal to either 4, 8, or 16.
+;// [out] pDst Pointer to the destination frame buffer.
+;// if roi.width==4, 4-byte alignment required
+;// if roi.width==8, 8-byte alignment required
+;// if roi.width==16, 16-byte alignment required
+;//
+;// Return Value:
+;// If the function runs without error, it returns OMX_Sts_NoErr.
+;// It is assued that following cases are satisfied before calling this function:
+;// pSrc or pDst is not NULL.
+;// srcStep or dstStep >= roi.width.
+;// dx or dy is in the range [0-3].
+;// roi.width or roi.height is not out of range {4, 8, 16}.
+;// If roi.width is equal to 4, Dst is 4 byte aligned.
+;// If roi.width is equal to 8, pDst is 8 byte aligned.
+;// If roi.width is equal to 16, pDst is 16 byte aligned.
+;// srcStep and dstStep is multiple of 8.
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ EXPORT omxVCM4P10_InterpolateLuma
+
+ IF ARM1136JS
+ IMPORT armVCM4P10_InterpolateLuma_Copy4x4_unsafe
+ IMPORT armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ IMPORT armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+ IMPORT armVCM4P10_Average_4x4_Align0_unsafe
+ IMPORT armVCM4P10_Average_4x4_Align2_unsafe
+ IMPORT armVCM4P10_Average_4x4_Align3_unsafe
+ IMPORT armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe
+ IMPORT armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe
+ ENDIF
+
+ IF ARM1136JS
+ IMPORT armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ IMPORT armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ IMPORT armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+ IMPORT armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+ ENDIF
+
+
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 2
+dstStep RN 3
+iHeight RN 4
+iWidth RN 5
+
+;// Declare other intermediate registers
+idx RN 6
+idy RN 7
+index RN 6
+Temp RN 12
+pArgs RN 11
+
+
+ ;// End of CortexA8
+
+;//-------------------------------------------------------------------------------------------------------------------------
+;//-------------------------------------------------------------------------------------------------------------------------
+ IF ARM1136JS
+
+
+ M_ALLOC4 ppDst, 8
+ M_ALLOC4 ppSrc, 8
+ M_ALLOC4 ppArgs, 16
+ M_ALLOC4 pBuffer, 120 ;// 120 = 12x10
+ M_ALLOC8 pInterBuf, 120 ;// 120 = 12*5*2
+ M_ALLOC8 pTempBuf, 32 ;// 32 = 8*4
+
+ ;// Function header
+ ;// Interpolation of luma is implemented by processing block of pixels, size 4x4 at a time.
+ ;// Depending on the values of motion vector fractional parts (dx,dy), one out of 16 cases will be processed.
+ ;// Registers r4, r5, r6 to be preserved by internal unsafe functions
+ ;// r4 - iHeight
+ ;// r5 - iWidth
+ ;// r6 - index
+ M_START omxVCM4P10_InterpolateLuma, r11
+
+;// Declare other intermediate registers
+idx RN 6
+idy RN 7
+index RN 6
+Temp RN 12
+pArgs RN 11
+
+pBuf RN 8
+Height RN 9
+bufStep RN 9
+
+ ;// Define stack arguments
+ M_ARG ptridx, 4
+ M_ARG ptridy, 4
+ M_ARG ptrWidth, 4
+ M_ARG ptrHeight, 4
+
+ ;// Load structure elements of roi
+ M_LDR idx, ptridx
+ M_LDR idy, ptridy
+ M_LDR iWidth, ptrWidth
+ M_LDR iHeight, ptrHeight
+
+ M_PRINTF "roi.width %d\n", iWidth
+ M_PRINTF "roi.height %d\n", iHeight
+
+ ADD index, idx, idy, LSL #2 ;// [index] = [idy][idx]
+ M_ADR pArgs, ppArgs
+
+InterpolateLuma
+Block4x4WidthLoop
+Block4x4HeightLoop
+
+ STM pArgs, {pSrc,srcStep,pDst,dstStep}
+ M_ADR pBuf, pBuffer
+
+ ;// switch table using motion vector as index
+ M_SWITCH index, L
+ M_CASE Case_0
+ M_CASE Case_1
+ M_CASE Case_2
+ M_CASE Case_3
+ M_CASE Case_4
+ M_CASE Case_5
+ M_CASE Case_6
+ M_CASE Case_7
+ M_CASE Case_8
+ M_CASE Case_9
+ M_CASE Case_a
+ M_CASE Case_b
+ M_CASE Case_c
+ M_CASE Case_d
+ M_CASE Case_e
+ M_CASE Case_f
+ M_ENDSWITCH
+
+Case_0
+ ;// Case G
+ M_PRINTF "Case 0 \n"
+
+ BL armVCM4P10_InterpolateLuma_Copy4x4_unsafe
+ B Block4x4LoopEnd
+
+Case_1
+ ;// Case a
+ M_PRINTF "Case 1 \n"
+
+ SUB pSrc, pSrc, #2
+ MOV Height, #4
+ BL armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ BL armVCM4P10_Average_4x4_Align2_unsafe
+ B Block4x4LoopEnd
+Case_2
+ ;// Case b
+ M_PRINTF "Case 2 \n"
+
+ SUB pSrc, pSrc, #2
+ MOV Height, #4
+ BL armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ B Block4x4LoopEnd
+Case_3
+ ;// Case c
+ M_PRINTF "Case 3 \n"
+
+ SUB pSrc, pSrc, #2
+ MOV Height, #4
+ BL armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ BL armVCM4P10_Average_4x4_Align3_unsafe
+ B Block4x4LoopEnd
+Case_4
+ ;// Case d
+ M_PRINTF "Case 4 \n"
+
+ SUB pSrc, pSrc, srcStep, LSL #1
+ MOV Height, #9
+ BL armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ BL armVCM4P10_Average_4x4_Align0_unsafe
+
+ B Block4x4LoopEnd
+Case_5
+ ;// Case e
+ M_PRINTF "Case 5 \n"
+
+ SUB pSrc, pSrc, #2
+ MOV Height, #4
+ M_ADR pDst, pTempBuf
+ MOV dstStep, #4
+ BL armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ M_ADR pArgs, ppArgs
+ LDM pArgs, {pSrc, srcStep, pDst, dstStep}
+ SUB pSrc, pSrc, srcStep, LSL #1
+ M_ADR pBuf, pBuffer
+ MOV Height, #9
+ BL armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ M_ADR pSrc, pTempBuf
+ MOV srcStep, #4
+ BL armVCM4P10_Average_4x4_Align0_unsafe
+
+
+ B Block4x4LoopEnd
+Case_6
+ ;// Case f
+ M_PRINTF "Case 6 \n"
+
+ SUB pSrc, pSrc, #2
+ SUB pSrc, pSrc, srcStep, LSL #1
+ MOV Height, #9
+ BL armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ M_ADR pBuf, pInterBuf
+ BL armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+ M_ADR idy, pTempBuf
+ BL armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe
+ BL armVCM4P10_Average_4x4_Align0_unsafe
+ B Block4x4LoopEnd
+Case_7
+ ;// Case g
+ M_PRINTF "Case 7 \n"
+
+ SUB pSrc, pSrc, #2
+ MOV Height, #4
+ M_ADR pDst, pTempBuf
+ MOV dstStep, #4
+ BL armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ M_ADR pArgs, ppArgs
+ LDM pArgs, {pSrc, srcStep, pDst, dstStep}
+ SUB pSrc, pSrc, srcStep, LSL #1
+ ADD pSrc, pSrc, #1
+ M_ADR pBuf, pBuffer
+ MOV Height, #9
+ BL armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ M_ADR pSrc, pTempBuf
+ MOV srcStep, #4
+ BL armVCM4P10_Average_4x4_Align0_unsafe
+
+ B Block4x4LoopEnd
+Case_8
+ ;// Case h
+ M_PRINTF "Case 8 \n"
+
+ SUB pSrc, pSrc, srcStep, LSL #1
+ MOV Height, #9
+ BL armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ B Block4x4LoopEnd
+Case_9
+ ;// Case i
+ M_PRINTF "Case 9 \n"
+
+ SUB pSrc, pSrc, #2
+ SUB pSrc, pSrc, srcStep, LSL #1
+ MOV Height, #9
+ BL armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ ADD pSrc, pSrc, srcStep, LSL #1
+ M_ADR pBuf, pInterBuf
+ BL armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+ M_ADR idy, pTempBuf
+ BL armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe
+ BL armVCM4P10_Average_4x4_Align2_unsafe
+ B Block4x4LoopEnd
+Case_a
+ ;// Case j
+ M_PRINTF "Case a \n"
+
+ SUB pSrc, pSrc, #2
+ SUB pSrc, pSrc, srcStep, LSL #1
+ MOV Height, #9
+ BL armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ ADD pSrc, pSrc, srcStep, LSL #1
+ M_ADR pBuf, pInterBuf
+ BL armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+ B Block4x4LoopEnd
+Case_b
+ ;// Case k
+ M_PRINTF "Case b \n"
+ SUB pSrc, pSrc, #2
+ SUB pSrc, pSrc, srcStep, LSL #1
+ MOV Height, #9
+ BL armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ ADD pSrc, pSrc, srcStep, LSL #1
+ M_ADR pBuf, pInterBuf
+ BL armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+ M_ADR idy, pTempBuf
+ BL armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe
+ BL armVCM4P10_Average_4x4_Align3_unsafe
+ B Block4x4LoopEnd
+Case_c
+ ;// Case n
+ M_PRINTF "Case c \n"
+
+ SUB pSrc, pSrc, srcStep, LSL #1
+ MOV Height, #9
+ BL armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ ADD pSrc, pSrc, srcStep ;// Update pSrc to one row down
+ BL armVCM4P10_Average_4x4_Align0_unsafe
+ B Block4x4LoopEnd
+Case_d
+ ;// Case p
+ M_PRINTF "Case d \n"
+ SUB pSrc, pSrc, #2
+ ADD pSrc, pSrc, srcStep
+ MOV Height, #4
+ M_ADR pDst, pTempBuf
+ MOV dstStep, #4
+ BL armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ M_ADR pArgs, ppArgs
+ LDM pArgs, {pSrc, srcStep, pDst, dstStep}
+ SUB pSrc, pSrc, srcStep, LSL #1
+ M_ADR pBuf, pBuffer
+ MOV Height, #9
+ BL armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ M_ADR pSrc, pTempBuf
+ MOV srcStep, #4
+ BL armVCM4P10_Average_4x4_Align0_unsafe
+ B Block4x4LoopEnd
+Case_e
+ ;// Case q
+ M_PRINTF "Case e \n"
+
+ SUB pSrc, pSrc, #2
+ SUB pSrc, pSrc, srcStep, LSL #1
+ MOV Height, #9
+ BL armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ M_ADR pBuf, pInterBuf
+ BL armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+ M_ADR idy, pTempBuf
+ BL armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe
+ ADD pSrc, pSrc, #4
+ BL armVCM4P10_Average_4x4_Align0_unsafe
+
+ B Block4x4LoopEnd
+Case_f
+ ;// Case r
+ M_PRINTF "Case f \n"
+ SUB pSrc, pSrc, #2
+ ADD pSrc, pSrc, srcStep
+ MOV Height, #4
+ M_ADR pDst, pTempBuf
+ MOV dstStep, #4
+ BL armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ M_ADR pArgs, ppArgs
+ LDM pArgs, {pSrc, srcStep, pDst, dstStep}
+ SUB pSrc, pSrc, srcStep, LSL #1
+ ADD pSrc, pSrc, #1
+ M_ADR pBuf, pBuffer
+ MOV Height, #9
+ BL armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ M_ADR pSrc, pTempBuf
+ MOV srcStep, #4
+ BL armVCM4P10_Average_4x4_Align0_unsafe
+
+Block4x4LoopEnd
+
+ ;// Width Loop
+ SUBS iWidth, iWidth, #4
+ M_ADR pArgs, ppArgs
+ LDM pArgs, {pSrc,srcStep,pDst,dstStep} ;// Load arguments
+ ADD pSrc, pSrc, #4
+ ADD pDst, pDst, #4
+ BGT Block4x4WidthLoop
+
+ ;// Height Loop
+ SUBS iHeight, iHeight, #4
+ M_LDR iWidth, ptrWidth
+ M_ADR pArgs, ppArgs
+ ADD pSrc, pSrc, srcStep, LSL #2
+ ADD pDst, pDst, dstStep, LSL #2
+ SUB pSrc, pSrc, iWidth
+ SUB pDst, pDst, iWidth
+ BGT Block4x4HeightLoop
+
+EndOfInterpolation
+ MOV r0, #0
+ M_END
+
+ ENDIF
+
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
new file mode 100644
index 0000000..34fedd8
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
@@ -0,0 +1,494 @@
+;//
+;//
+;// File Name: omxVCM4P10_PredictIntraChroma_8x8_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ EXPORT armVCM4P10_pIndexTable8x8
+
+;// Define the processor variants supported by this file
+
+ M_VARIANTS ARM1136JS
+
+ AREA table, DATA
+;//-------------------------------------------------------
+;// This table for implementing switch case of C in asm by
+;// the mehtod of two levels of indexing.
+;//-------------------------------------------------------
+
+ M_TABLE armVCM4P10_pIndexTable8x8
+ DCD OMX_VC_CHROMA_DC, OMX_VC_CHROMA_HOR
+ DCD OMX_VC_CHROMA_VERT, OMX_VC_CHROMA_PLANE
+
+ M_TABLE armVCM4P10_MultiplierTableChroma8x8,1
+ DCW 3, 2, 1,4
+ DCW -3,-2,-1,0
+ DCW 1, 2, 3,4
+
+ IF ARM1136JS
+
+;//--------------------------------------------
+;// Constants
+;//--------------------------------------------
+
+BLK_SIZE EQU 0x8
+MUL_CONST0 EQU 0x01010101
+MASK_CONST EQU 0x00FF00FF
+MUL_CONST1 EQU 0x80808080
+
+;//--------------------------------------------
+;// Scratch variable
+;//--------------------------------------------
+y RN 12
+pc RN 15
+return RN 0
+pSrcLeft2 RN 1
+pDst2 RN 2
+sum1 RN 6
+sum2 RN 7
+pTable RN 9
+dstStepx2 RN 11
+leftStepx2 RN 14
+outerCount RN 14
+r0x01010101 RN 10
+r0x00FF00FF RN 11
+
+tVal0 RN 0
+tVal1 RN 1
+tVal2 RN 2
+tVal3 RN 3
+tVal4 RN 4
+tVal5 RN 5
+tVal6 RN 6
+tVal7 RN 7
+tVal8 RN 8
+tVal9 RN 9
+tVal10 RN 10
+tVal11 RN 11
+tVal12 RN 12
+tVal14 RN 14
+
+b RN 14
+c RN 12
+
+p2p0 RN 0
+p3p1 RN 1
+p6p4 RN 2
+p7p5 RN 4
+
+pp2pp0 RN 6
+pp3pp1 RN 7
+pp6pp4 RN 8
+pp7pp5 RN 9
+
+p3210 RN 10
+p7654 RN 10
+
+;//--------------------------------------------
+;// Input Arguments
+;//--------------------------------------------
+pSrcLeft RN 0 ;// input pointer
+pSrcAbove RN 1 ;// input pointer
+pSrcAboveLeft RN 2 ;// input pointer
+pDst RN 3 ;// output pointer
+leftStep RN 4 ;// input variable
+dstStep RN 5 ;// input variable
+predMode RN 6 ;// input variable
+availability RN 7 ;// input variable
+
+;//-----------------------------------------------------------------------------------------------
+;// omxVCM4P10_PredictIntraChroma_8x8 starts
+;//-----------------------------------------------------------------------------------------------
+
+ ;// Write function header
+ M_START omxVCM4P10_PredictIntraChroma_8x8, r11
+
+ ;// Define stack arguments
+ M_ARG LeftStep, 4
+ M_ARG DstStep, 4
+ M_ARG PredMode, 4
+ M_ARG Availability, 4
+
+ ;// M_STALL ARM1136JS=4
+
+ LDR pTable,=armVCM4P10_pIndexTable8x8 ;// Load index table for switch case
+
+
+ ;// Load argument from the stack
+ M_LDR predMode, PredMode ;// Arg predMode loaded from stack to reg
+ M_LDR leftStep, LeftStep ;// Arg leftStep loaded from stack to reg
+ M_LDR dstStep, DstStep ;// Arg dstStep loaded from stack to reg
+ M_LDR availability, Availability ;// Arg availability loaded from stack to reg
+
+ MOV y, #BLK_SIZE ;// Outer Loop Count
+ LDR pc, [pTable, predMode, LSL #2] ;// Branch to the case based on preMode
+
+OMX_VC_CHROMA_DC
+ AND availability, availability,#(OMX_VC_UPPER + OMX_VC_LEFT)
+ CMP availability, #(OMX_VC_UPPER + OMX_VC_LEFT) ;// if(availability & (#OMX_VC_UPPER | #OMX_VC_LEFT))
+ LDR r0x01010101, =MUL_CONST0
+ BNE TST_UPPER ;// Jump to Upper if not both
+ LDM pSrcAbove,{tVal8,tVal9} ;// tVal 8 to 9 = pSrcAbove[0 to 7]
+
+ ADD leftStepx2, leftStep,leftStep ;// leftStepx2 = 2 * leftStep
+ ADD pSrcLeft2, pSrcLeft, leftStep ;// pSrcLeft2 = pSrcLeft + leftStep
+
+ ;// M_STALL ARM1136JS=1
+
+ UXTB16 tVal7, tVal8 ;// pSrcAbove[0, 2]
+ UXTB16 tVal8, tVal8, ROR #8 ;// pSrcAbove[1, 3]
+ UADD16 sum1, tVal7, tVal8 ;// pSrcAbove[0, 2] + pSrcAbove[1, 3]
+
+ UXTB16 tVal7, tVal9 ;// pSrcAbove[4, 6]
+ UXTB16 tVal9, tVal9, ROR #8 ;// pSrcAbove[5, 7]
+ UADD16 sum2, tVal7, tVal9 ;// pSrcAbove[0, 2] + pSrcAbove[4, 6]
+ ADD sum1, sum1, sum1, LSR #16 ;// sum(pSrcAbove[0] to pSrcAbove[3])
+ ADD sum2, sum2, sum2, LSR #16 ;// sum(pSrcAbove[4] to pSrcAbove[7])
+ UXTH sum1, sum1 ;// upsum1 (Clear the top junk bits)
+ UXTH sum2, sum2 ;// upsum2 (Clear the top junk bits)
+
+ M_LDRB tVal8, [pSrcLeft], +leftStepx2 ;// tVal8 = pSrcLeft[0]
+ M_LDRB tVal9, [pSrcLeft2], +leftStepx2 ;// tVal9 = pSrcLeft[1]
+ M_LDRB tVal4, [pSrcLeft], +leftStepx2 ;// tVal4 = pSrcLeft[2]
+ M_LDRB tVal12,[pSrcLeft2], +leftStepx2 ;// tVal12= pSrcLeft[3]
+ ADD tVal2, tVal8, tVal9 ;// tVal14 = tVal8 + tVal9
+
+ M_LDRB tVal8, [pSrcLeft], +leftStepx2 ;// tVal8 = pSrcLeft[4]
+ M_LDRB tVal9, [pSrcLeft2], +leftStepx2 ;// tVal9 = pSrcLeft[5]
+ ADD tVal14, tVal4, tVal12 ;// tVal14 = tVal4 + tVal12
+
+ LDRB tVal4, [pSrcLeft] ;// tVal4 = pSrcLeft[6]
+ LDRB tVal12,[pSrcLeft2] ;// tVal12= pSrcLeft[7]
+ ADD tVal8, tVal8, tVal9 ;// tVal8 = tVal8 + tVal9
+ ADD tVal2, tVal2, tVal14 ;// leftsum1 = sum(pSrcLeft[0] to pSrcLeft[3])
+ ADD tVal4, tVal4, tVal12 ;// tVal4 = tVal4 + tVal12
+ ADD tVal14, tVal8, tVal4 ;// leftsum2 = sum(pSrcLeft[4] to pSrcLeft[7])
+ ADD tVal8, tVal14, #2 ;// tVal8 = leftsum2 + 2
+ ADD tVal9, sum2, #2 ;// tVal8 = upsum2 + 2
+ ADD sum1, sum1, tVal2 ;// sum1 = upsum1 + leftsum1
+ ADD sum2, sum2, tVal14 ;// sum2 = upsum2 + leftsum2
+ ADD sum1, sum1, #4 ;// (sum1 + 4)
+ ADD sum2, sum2, #4 ;// (sum2 + 4)
+ MOV sum1, sum1, LSR #3 ;// (sum1 + 4)>>3
+ MOV tVal9, tVal9, LSR #2 ;// (tVal9 + 2)>>2
+ MOV tVal8, tVal8, LSR #2 ;// (tVal8 + 2)>>2
+ MOV sum2, sum2, LSR #3 ;// (sum2 + 4)>>3
+
+ MUL tVal0, sum1, r0x01010101 ;// replicate the val in all the bytes
+ MUL tVal1, tVal9,r0x01010101 ;// replicate the val in all the bytes
+ MUL tVal8, tVal8,r0x01010101 ;// replicate the val in all the bytes
+ MUL tVal9, sum2, r0x01010101 ;// replicate the val in all the bytes
+
+ M_STRD tVal0, tVal1, [pDst], dstStep ;// pDst[0 to 7] = tVal 0 to 1
+ M_STRD tVal0, tVal1, [pDst], dstStep ;// pDst[8 to 15] = tVal 0 to 1
+ M_STRD tVal0, tVal1, [pDst], dstStep ;// pDst[16 to 23] = tVal 0 to 1
+ M_STRD tVal0, tVal1, [pDst], dstStep ;// pDst[24 to 31] = tVal 0 to 1
+
+ M_STRD tVal8, tVal9, [pDst], dstStep ;// pDst[32 to 39] = tVal 8 to 9
+ M_STRD tVal8, tVal9, [pDst], dstStep ;// pDst[40 to 47] = tVal 8 to 9
+ M_STRD tVal8, tVal9, [pDst], dstStep ;// pDst[48 to 55] = tVal 8 to 9
+ M_STRD tVal8, tVal9, [pDst], dstStep ;// pDst[56 to 63] = tVal 8 to 9
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+TST_UPPER
+
+ ;// M_STALL ARM1136JS=3
+
+ CMP availability, #OMX_VC_UPPER ;// if(availability & #OMX_VC_UPPER)
+
+ BNE TST_LEFT ;// Jump to Left if not upper
+ LDM pSrcAbove,{tVal8,tVal9} ;// tVal 8 to 9 = pSrcAbove[0 to 7]
+
+ ;// M_STALL ARM1136JS=3
+
+ UXTB16 tVal7, tVal8 ;// pSrcAbove[0, 2]
+ UXTB16 tVal8, tVal8, ROR #8 ;// pSrcAbove[1, 3]
+ UADD16 sum1, tVal7, tVal8 ;// pSrcAbove[0, 2] + pSrcAbove[1, 3]
+
+ UXTB16 tVal7, tVal9 ;// pSrcAbove[4, 6]
+ UXTB16 tVal9, tVal9, ROR #8 ;// pSrcAbove[5, 7]
+ UADD16 sum2, tVal7, tVal9 ;// pSrcAbove[0, 2] + pSrcAbove[4, 6]
+
+ ADD sum1, sum1, sum1, LSR #16 ;// sum(pSrcAbove[0] to pSrcAbove[3])
+ ADD sum2, sum2, sum2, LSR #16 ;// sum(pSrcAbove[4] to pSrcAbove[7])
+
+ UXTH sum1, sum1 ;// upsum1 (Clear the top junk bits)
+ UXTH sum2, sum2 ;// upsum2 (Clear the top junk bits)
+
+ ADD sum1, sum1, #2 ;// sum1 + 2
+ ADD sum2, sum2, #2 ;// sum2 + 2
+
+ MOV sum1, sum1, LSR #2 ;// (sum1 + 2)>>2
+ MOV sum2, sum2, LSR #2 ;// (sum2 + 2)>>2
+
+ MUL sum1, sum1,r0x01010101 ;// replicate the val in all the bytes
+ MUL sum2, sum2,r0x01010101 ;// replicate the val in all the bytes
+
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[0 to 7] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[8 to 15] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[16 to 23] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[24 to 31] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[32 to 39] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[40 to 47] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[48 to 55] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[56 to 63] = tVal 6 to 7
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+TST_LEFT
+ ;// M_STALL ARM1136JS=3
+
+ CMP availability, #OMX_VC_LEFT
+ BNE TST_COUNT0
+ ADD leftStepx2, leftStep,leftStep ;// leftStepx2 = 2 * leftStep
+ ADD pSrcLeft2, pSrcLeft, leftStep ;// pSrcLeft2 = pSrcLeft + leftStep
+
+ M_LDRB tVal8, [pSrcLeft], +leftStepx2 ;// tVal8 = pSrcLeft[0]
+ M_LDRB tVal9, [pSrcLeft2], +leftStepx2 ;// tVal9 = pSrcLeft[1]
+ M_LDRB tVal4, [pSrcLeft], +leftStepx2 ;// tVal4 = pSrcLeft[2]
+ M_LDRB tVal12,[pSrcLeft2], +leftStepx2 ;// tVal12= pSrcLeft[3]
+
+ ADD tVal6, tVal8, tVal9 ;// tVal6 = tVal8 + tVal9
+
+ M_LDRB tVal8, [pSrcLeft], +leftStepx2 ;// tVal8 = pSrcLeft[4]
+ ADD tVal7, tVal4, tVal12 ;// tVal7 = tVal4 + tVal12
+ M_LDRB tVal9, [pSrcLeft2], +leftStepx2 ;// tVal9 = pSrcLeft[5]
+ M_LDRB tVal4, [pSrcLeft], +leftStepx2 ;// tVal4 = pSrcLeft[6]
+ M_LDRB tVal12,[pSrcLeft2], +leftStepx2 ;// tVal12= pSrcLeft[7]
+
+ ADD tVal8, tVal8, tVal9 ;// tVal8 = tVal8 + tVal9
+ ADD sum1, tVal6, tVal7 ;// sum1 = sum(pSrcLeft[0] to pSrcLeft[3])
+ ADD tVal4, tVal4, tVal12 ;// tVal4 = tVal4 + tVal12
+ ADD sum2, tVal8, tVal4 ;// sum2 = sum(pSrcLeft[4] to pSrcLeft[7])
+
+ ADD sum1, sum1, #2 ;// sum1 + 2
+ ADD sum2, sum2, #2 ;// sum2 + 2
+
+ MOV sum1, sum1, LSR #2 ;// (sum1 + 2)>>2
+ MOV sum2, sum2, LSR #2 ;// (sum2 + 2)>>2
+
+ MUL tVal6, sum1,r0x01010101 ;// replicate the val in all the bytes
+ MUL tVal8, sum2,r0x01010101 ;// replicate the val in all the bytes
+
+ ;// M_STALL ARM1136JS=1
+ MOV tVal7,tVal6 ;// tVal7 = sum1
+ MOV tVal9,tVal8 ;// tVal9 = sum2
+
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[0 to 7] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[8 to 15] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[16 to 23] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[24 to 31] = tVal 6 to 7
+
+ M_STRD tVal8, tVal9, [pDst], dstStep ;// pDst[32 to 39] = tVal 8 to 9
+ M_STRD tVal8, tVal9, [pDst], dstStep ;// pDst[40 to 47] = tVal 8 to 9
+ M_STRD tVal8, tVal9, [pDst], dstStep ;// pDst[48 to 55] = tVal 8 to 9
+ M_STRD tVal8, tVal9, [pDst], dstStep ;// pDst[56 to 63] = tVal 8 to 9
+
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT ;// Macro to exit midway-break frm case
+
+TST_COUNT0
+ LDR sum1, =MUL_CONST1 ;// sum1 = 0x80808080 if(count == 0)
+
+ ;// M_STALL ARM1136JS=2
+
+ MOV tVal7, sum1 ;// tVal7 = sum1
+
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[0 to 7] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[8 to 15] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[16 to 23] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[24 to 31] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[32 to 39] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[40 to 47] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[48 to 55] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[56 to 63] = tVal 6 to 7
+
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT ;// Macro to exit midway-break frm case
+
+OMX_VC_CHROMA_HOR
+
+ ;// M_STALL ARM1136JS=2
+
+ ADD pSrcLeft2, pSrcLeft, leftStep ;// pSrcLeft2 = pSrcLeft + leftStep
+ ADD leftStepx2, leftStep, leftStep ;// leftStepx2 = leftStep * 2
+ ADD pDst2, pDst, dstStep ;// pDst2 = pDst + dstStep
+ ADD dstStepx2, dstStep, dstStep ;// double dstStep
+ SUB dstStepx2, dstStepx2, #4 ;// double dstStep minus 4
+ LDR r0x01010101, =MUL_CONST0 ;// Const to repeat the byte in reg 4 times
+ M_LDRB tVal6, [pSrcLeft], +leftStepx2 ;// tVal6 = pSrcLeft[0]
+ M_LDRB tVal7, [pSrcLeft2],+leftStepx2 ;// tVal7 = pSrcLeft[1]
+ M_LDRB tVal8, [pSrcLeft], +leftStepx2 ;// tVal8 = pSrcLeft[2]
+ M_LDRB tVal9, [pSrcLeft2],+leftStepx2 ;// tVal9 = pSrcLeft[3]
+ MUL tVal6, tVal6, r0x01010101 ;// replicate the val in all the bytes
+ MUL tVal7, tVal7, r0x01010101 ;// replicate the val in all the bytes
+ MUL tVal8, tVal8, r0x01010101 ;// replicate the val in all the bytes
+ MUL tVal9, tVal9, r0x01010101 ;// replicate the val in all the bytes
+ STR tVal6, [pDst], #+4 ;// store {tVal6} at pDst [0 to 3]
+ STR tVal7, [pDst2], #+4 ;// store {tVal7} at pDst2[0 to 3]
+ M_STR tVal6, [pDst], dstStepx2 ;// store {tVal6} at pDst [4 to 7]
+ M_STR tVal7, [pDst2], dstStepx2 ;// store {tVal7} at pDst2[4 to 7]
+ STR tVal8, [pDst], #+4 ;// store {tVal6} at pDst [0 to 3]
+ STR tVal9, [pDst2], #+4 ;// store {tVal7} at pDst2[0 to 3]
+ M_STR tVal8, [pDst], dstStepx2 ;// store {tVal6} at pDst [4 to 7]
+ M_STR tVal9, [pDst2], dstStepx2 ;// store {tVal7} at pDst2[4 to 7]
+ M_LDRB tVal6, [pSrcLeft], +leftStepx2 ;// tVal6 = pSrcLeft[4]
+ M_LDRB tVal7, [pSrcLeft2],+leftStepx2 ;// tVal7 = pSrcLeft[5]
+ M_LDRB tVal8, [pSrcLeft], +leftStepx2 ;// tVal8 = pSrcLeft[6]
+ M_LDRB tVal9, [pSrcLeft2],+leftStepx2 ;// tVal9 = pSrcLeft[7]
+ MUL tVal6, tVal6, r0x01010101 ;// replicate the val in all the bytes
+ MUL tVal7, tVal7, r0x01010101 ;// replicate the val in all the bytes
+ MUL tVal8, tVal8, r0x01010101 ;// replicate the val in all the bytes
+ MUL tVal9, tVal9, r0x01010101 ;// replicate the val in all the bytes
+ STR tVal6, [pDst], #+4 ;// store {tVal6} at pDst [0 to 3]
+ STR tVal7, [pDst2], #+4 ;// store {tVal7} at pDst2[0 to 3]
+ M_STR tVal6, [pDst], dstStepx2 ;// store {tVal6} at pDst [4 to 7]
+ M_STR tVal7, [pDst2], dstStepx2 ;// store {tVal7} at pDst2[4 to 7]
+ STR tVal8, [pDst], #+4 ;// store {tVal6} at pDst [0 to 3]
+ STR tVal9, [pDst2], #+4 ;// store {tVal7} at pDst2[0 to 3]
+ M_STR tVal8, [pDst], dstStepx2 ;// store {tVal6} at pDst [4 to 7]
+ M_STR tVal9, [pDst2], dstStepx2 ;// store {tVal7} at pDst2[4 to 7]
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+OMX_VC_CHROMA_VERT
+
+ ;// M_STALL ARM1136JS=4
+
+ LDMIA pSrcAbove, {tVal6,tVal7} ;// tVal 6 to 7 = pSrcAbove[0 to 7]
+ MOV return, #OMX_Sts_NoErr
+
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[0 to 7] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[8 to 15] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[16 to 23] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[24 to 31] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[32 to 39] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[40 to 47] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[48 to 55] = tVal 6 to 7
+ M_STRD tVal6, tVal7, [pDst], dstStep ;// pDst[56 to 63] = tVal 6 to 7
+
+ M_EXIT ;// Macro to exit midway-break frm case
+
+OMX_VC_CHROMA_PLANE
+
+ ;// M_STALL ARM1136JS=3
+
+ RSB tVal14, leftStep, leftStep, LSL #3 ;// 7*leftStep
+ LDRB tVal7, [pSrcAbove, #+7] ;// pSrcAbove[7]
+ LDRB tVal6, [pSrcLeft, +tVal14] ;// pSrcLeft[7*leftStep]
+ LDRB tVal8, [pSrcAboveLeft] ;// pSrcAboveLeft[0]
+ LDRB tVal9, [pSrcAbove, #+6 ] ;// pSrcAbove[6]
+ LDRB tVal10,[pSrcAbove] ;// pSrcAbove[0]
+ ADD tVal2, tVal7, tVal6 ;// pSrcAbove[7] + pSrcLeft[7*leftStep]
+ SUB tVal6, tVal6, tVal8 ;// V0 = pSrcLeft[7*leftStep] - pSrcAboveLeft[0]
+ SUB tVal7, tVal7, tVal8 ;// H0 = pSrcAbove[7] - pSrcAboveLeft[0]
+ LSL tVal2, tVal2, #4 ;// a = 16 * (pSrcAbove[15] + pSrcLeft[15*lS])
+ ADD tVal2, tVal2, #16 ;// a + 16
+ SUB tVal9, tVal9,tVal10 ;// pSrcAbove[6] - pSrcAbove[0]
+ LDRB tVal8, [pSrcAbove,#+5] ;// pSrcAbove[5]
+ LDRB tVal10,[pSrcAbove,#+1] ;// pSrcAbove[1]
+ ADD tVal9, tVal9, tVal9, LSL #1 ;// H1 = 3 * (pSrcAbove[6] - pSrcAbove[0])
+ ADD tVal7, tVal9, tVal7, LSL #2 ;// H = H1 + H0
+ SUB tVal8, tVal8, tVal10 ;// pSrcAbove[5] - pSrcAbove[1]
+ LDRB tVal9, [pSrcAbove,#+4] ;// pSrcAbove[4]
+ LDRB tVal10,[pSrcAbove,#+2] ;// pSrcAbove[2]
+ ADD tVal7, tVal7, tVal8, LSL #1 ;// H = H + H2
+ SUB tVal11, tVal14,leftStep ;// 6*leftStep
+ ADD tVal11, pSrcLeft, tVal11 ;// pSrcLeft + 6*leftStep
+ MOV tVal12, pSrcLeft ;// pSrcLeft
+ SUB tVal9, tVal9, tVal10 ;// pSrcAbove[4] - pSrcAbove[2]
+ ADD tVal7, tVal7, tVal9 ;// H = H + H3
+ M_LDRB tVal8, [tVal11],-leftStep ;// pSrcLeft[6*leftStep]
+ M_LDRB tVal10,[tVal12],+leftStep ;// pSrcLeft[0]
+ ADD tVal7, tVal7, tVal7, LSL #4 ;// 17 * H
+ ADD tVal7, tVal7, #16 ;// 17 * H + 16
+ SUB tVal8, tVal8, tVal10 ;// pSrcLeft[6*leftStep] - pSrcLeft[0]
+ ASR b, tVal7, #5 ;// b = (17 * H + 16) >> 5
+ ADD tVal8, tVal8, tVal8, LSL #1 ;// V1 = 3 * (pSrcLeft[6*leftStep] - pSrcLeft[0])
+ ADD tVal6, tVal8, tVal6, LSL #2 ;// V = V0 +V1
+ M_LDRB tVal8, [tVal11],-leftStep ;// pSrcLeft[5*leftStep]
+ M_LDRB tVal10,[tVal12],+leftStep ;// pSrcLeft[leftStep]
+ ADD tVal7, b, b, LSL #1 ;// 3*b
+ SUB tVal2, tVal2, tVal7 ;// a + 16 - 3*b
+ SUB tVal7, tVal8, tVal10 ;// pSrcLeft[5*leftStep] - pSrcLeft[leftStep]
+ M_LDRB tVal8, [tVal11],-leftStep ;// pSrcLeft[4*leftStep]
+ M_LDRB tVal10,[tVal12],+leftStep ;// pSrcLeft[2*leftStep]
+ ADD tVal6, tVal6, tVal7, LSL #1 ;// V = V + V2
+ LDR r0x00FF00FF, =MASK_CONST ;// r0x00FF00FF = 0x00FF00FF
+ SUB tVal7, tVal8, tVal10 ;// pSrcLeft[4*leftStep] - pSrcLeft[2*leftStep]
+ ADD tVal6, tVal6, tVal7 ;// V = V + V7
+ SUB dstStep, dstStep, #4 ;// dstStep - 4
+ ADD tVal6, tVal6, tVal6, LSL #4 ;// 17*V
+ ADD tVal6, tVal6, #16 ;// 17*V + 16
+
+ ;// M_STALL ARM1136JS=1
+
+ ASR c, tVal6, #5 ;// c = (17*V + 16)>>5
+
+ ;// M_STALL ARM1136JS=1
+
+ ADD tVal6, c, c, LSL #1 ;// 3*c
+ UXTH c, c ;// only in half word
+ SUB tVal6, tVal2, tVal6 ;// a - 3*b - 3*c + 16
+ ORR c, c, c, LSL #16 ;// c c
+ ADD tVal7, b, b ;// 2b
+ ADD tVal2, tVal6, tVal7 ;// pp2 = d + 2*b
+ ADD tVal7, tVal7, b ;// 3b
+ ORR p2p0, tVal6, tVal2, LSL #16 ;// p2p0 = pack {p2, p0}
+ UXTH b, b
+ UXTH tVal7, tVal7
+ ORR b, b, b, LSL #16 ;// {b,b}
+ ORR tVal7, tVal7, tVal7, LSL #16 ;// {3b,3b}
+ SADD16 p3p1, p2p0, b ;// p3p1 = p2p0 + {b,b}
+ SADD16 p6p4, p3p1, tVal7 ;// p6p4 = p3p1 + {3b,3b}
+ SADD16 p7p5, p6p4, b ;// p7p5 = p6p4 + {b,b}
+ MOV outerCount, #BLK_SIZE ;// Outer Loop Count
+
+LOOP_PLANE
+
+ USAT16 p7p5, #13, p7p5 ;// clip13(p7) clip13(p5)
+ USAT16 p6p4, #13, p6p4 ;// clip13(p6) clip13(p4)
+ USAT16 p3p1, #13, p3p1 ;// clip13(p3) clip13(p1)
+ USAT16 p2p0, #13, p2p0 ;// clip13(p2) clip13(p0)
+
+ AND pp7pp5, r0x00FF00FF, p7p5, ASR #5 ;// clip8(p7) clip8(p5)
+ AND pp6pp4, r0x00FF00FF, p6p4, ASR #5 ;// clip8(p6) clip8(p4)
+ AND pp3pp1, r0x00FF00FF, p3p1, ASR #5 ;// clip8(p3) clip8(p1)
+ AND pp2pp0, r0x00FF00FF, p2p0, ASR #5 ;// clip8(p2) clip8(p0)
+
+ SUBS outerCount, outerCount, #1 ;// outerCount--
+
+ ORR p3210, pp2pp0, pp3pp1, LSL #8 ;// pack {p3,p2, p1, p0}
+ STR p3210, [pDst], #4 ;// store {pDst[0] to pDst[3]}
+
+ ORR p7654, pp6pp4, pp7pp5, LSL #8 ;// pack {p7,p6, p5, p4}
+ M_STR p7654, [pDst], dstStep ;// store {pDst[4] to pDst[7]}
+
+ SADD16 p7p5, p7p5, c ;// {p7 + c}, {p5 + c}
+ SADD16 p6p4, p6p4, c ;// {p6 + c}, {p4 + c}
+ SADD16 p3p1, p3p1, c ;// {p3 + c}, {p1 + c}
+ SADD16 p2p0, p2p0, c ;// {p2 + c}, {p0 + c}
+
+ BNE LOOP_PLANE ;// Loop for 8 times
+ MOV return, #OMX_Sts_NoErr
+ M_END
+
+ ENDIF ;// ARM1136JS
+
+
+
+ END
+;//-----------------------------------------------------------------------------------------------
+;// omxVCM4P10_PredictIntraChroma_8x8 ends
+;//-----------------------------------------------------------------------------------------------
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
new file mode 100644
index 0000000..1557208
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
@@ -0,0 +1,501 @@
+;//
+;//
+;// File Name: omxVCM4P10_PredictIntra_16x16_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+;//-------------------------------------------------------
+;// This table for implementing switch case of C in asm by
+;// the mehtod of two levels of indexing.
+;//-------------------------------------------------------
+
+ M_TABLE armVCM4P10_pIndexTable16x16
+ DCD OMX_VC_16X16_VERT, OMX_VC_16X16_HOR
+ DCD OMX_VC_16X16_DC, OMX_VC_16X16_PLANE
+
+ IF ARM1136JS
+
+;//--------------------------------------------
+;// Constants
+;//--------------------------------------------
+BLK_SIZE EQU 0x10
+MUL_CONST0 EQU 0x01010101
+MUL_CONST1 EQU 0x00060004
+MUL_CONST2 EQU 0x00070005
+MUL_CONST3 EQU 0x00030001
+MASK_CONST EQU 0x00FF00FF
+
+;//--------------------------------------------
+;// Scratch variable
+;//--------------------------------------------
+y RN 12
+pc RN 15
+
+return RN 0
+innerCount RN 0
+outerCount RN 1
+pSrcLeft2 RN 1
+pDst2 RN 2
+sum RN 6
+pTable RN 9
+temp1 RN 10
+temp2 RN 12
+cMul1 RN 11
+cMul2 RN 12
+count RN 12
+dstStepx2 RN 11
+leftStepx2 RN 14
+r0x01010101 RN 10
+r0x00FF00FF RN 11
+
+tVal0 RN 0
+tVal1 RN 1
+tVal2 RN 2
+tVal3 RN 3
+tVal4 RN 4
+tVal5 RN 5
+tVal6 RN 6
+tVal7 RN 7
+tVal8 RN 8
+tVal9 RN 9
+tVal10 RN 10
+tVal11 RN 11
+tVal12 RN 12
+tVal14 RN 14
+
+b RN 12
+c RN 14
+
+p2p0 RN 0
+p3p1 RN 1
+p6p4 RN 2
+p7p5 RN 4
+p10p8 RN 6
+p11p9 RN 7
+p14p12 RN 8
+p15p13 RN 9
+
+p3210 RN 10
+p7654 RN 10
+p111098 RN 10
+p15141312 RN 10
+
+;//--------------------------------------------
+;// Declare input registers
+;//--------------------------------------------
+pSrcLeft RN 0 ;// input pointer
+pSrcAbove RN 1 ;// input pointer
+pSrcAboveLeft RN 2 ;// input pointer
+pDst RN 3 ;// output pointer
+leftStep RN 4 ;// input variable
+dstStep RN 5 ;// input variable
+predMode RN 6 ;// input variable
+availability RN 7 ;// input variable
+
+;//-----------------------------------------------------------------------------------------------
+;// omxVCM4P10_PredictIntra_16x16 starts
+;//-----------------------------------------------------------------------------------------------
+
+ ;// Write function header
+ M_START omxVCM4P10_PredictIntra_16x16, r11
+
+ ;// Define stack arguments
+ M_ARG LeftStep, 4
+ M_ARG DstStep, 4
+ M_ARG PredMode, 4
+ M_ARG Availability, 4
+
+ ;// M_STALL ARM1136JS=4
+
+ LDR pTable,=armVCM4P10_pIndexTable16x16 ;// Load index table for switch case
+
+ ;// Load argument from the stack
+ M_LDR predMode, PredMode ;// Arg predMode loaded from stack to reg
+ M_LDR leftStep, LeftStep ;// Arg leftStep loaded from stack to reg
+ M_LDR dstStep, DstStep ;// Arg dstStep loaded from stack to reg
+ M_LDR availability, Availability ;// Arg availability loaded from stack to reg
+
+ MOV y, #BLK_SIZE ;// Outer Loop Count
+ LDR pc, [pTable, predMode, LSL #2] ;// Branch to the case based on preMode
+
+OMX_VC_16X16_VERT
+ LDM pSrcAbove, {tVal6,tVal7,tVal8,tVal9};// tVal 6 to 9 = pSrcAbove[0 to 15]
+ ADD dstStepx2, dstStep, dstStep ;// double dstStep
+ ADD pDst2, pDst, dstStep ;// pDst2- pDst advanced by dstStep
+
+ ;// M_STALL ARM1136JS=2 ;// Stall outside the loop
+
+LOOP_VERT
+ STM pDst, {tVal6,tVal7,tVal8,tVal9} ;// pDst[0 to 15] = tVal 6 to 9
+ SUBS y, y, #2 ;// y--
+ ADD pDst, pDst, dstStepx2 ;// pDst advanced by dstStep
+ STM pDst2, {tVal6,tVal7,tVal8,tVal9} ;// pDst2[16 to 31] = tVal 6 to 9
+ ADD pDst2, pDst2, dstStepx2 ;// pDst advanced by dstStep
+ BNE LOOP_VERT ;// Loop for 8 times
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+
+OMX_VC_16X16_HOR
+
+ ;// M_STALL ARM1136JS=6
+
+ LDR r0x01010101, =MUL_CONST0 ;// Const to repeat the byte in reg 4 times
+ MOV y, #4 ;// Outer Loop Count
+ M_LDRB tVal6, [pSrcLeft], +leftStep ;// tVal6 = pSrcLeft[0 to 3]
+ ADD pDst2, pDst, dstStep ;// pDst2- pDst advanced by dstStep
+ M_LDRB tVal7, [pSrcLeft], +leftStep ;// tVal1 = pSrcLeft[4 to 7]
+ ADD dstStepx2, dstStep, dstStep ;// double dstStep
+ SUB dstStepx2, dstStepx2, #12 ;// double dstStep minus 12
+
+LOOP_HOR
+ M_LDRB tVal8, [pSrcLeft], +leftStep ;// tVal8 = pSrcLeft[0 to 3]
+ MUL tVal6, tVal6, r0x01010101 ;// replicate the val in all the bytes
+ M_LDRB tVal9, [pSrcLeft], +leftStep ;// tVal9 = pSrcLeft[4 to 7]
+ MUL tVal7, tVal7, r0x01010101 ;// replicate the val in all the bytes
+ SUBS y, y, #1 ;// y--
+ STR tVal6, [pDst], #+4 ;// store {tVal6} at pDst[0 to 3]
+ STR tVal7, [pDst2], #+4 ;// store {tVal7} at pDst2[0 to 3]
+ STR tVal6, [pDst], #+4 ;// store {tVal6} at pDst[4 to 7]
+ STR tVal7, [pDst2], #+4 ;// store {tVal7} at pDst2[4 to 7]
+ MUL tVal8, tVal8, r0x01010101 ;// replicate the val in all the bytes
+ STR tVal6, [pDst], #+4 ;// store {tVal6} at pDst[8 to 11]
+ STR tVal7, [pDst2], #+4 ;// store {tVal7} at pDst2[8 to 11]
+ MUL tVal9, tVal9, r0x01010101 ;// replicate the val in all the bytes
+ M_STR tVal6, [pDst], dstStepx2 ;// store {tVal6} at pDst[12 to 15]
+ M_STR tVal7, [pDst2], dstStepx2 ;// store {tVal7} at pDst2[12 to 15]
+ STR tVal8, [pDst], #+4 ;// store {tVal6} at pDst[0 to 3]
+ STR tVal9, [pDst2], #+4 ;// store {tVal7} at pDst2[0 to 3]
+ STR tVal8, [pDst], #+4 ;// store {tVal6} at pDst[4 to 7]
+ STR tVal9, [pDst2], #+4 ;// store {tVal7} at pDst2[4 to 7]
+ STR tVal8, [pDst], #+4 ;// store {tVal6} at pDst[8 to 11]
+ STR tVal9, [pDst2], #+4 ;// store {tVal7} at pDst2[8 to 11]
+ M_STR tVal8, [pDst], dstStepx2 ;// store {tVal6} at pDst[12 to 15]
+ M_LDRB tVal6, [pSrcLeft], +leftStep ;// tVal6 = pSrcLeft[0 to 3]
+ M_STR tVal9, [pDst2], dstStepx2 ;// store {tVal7} at pDst2[12 to 15]
+ M_LDRB tVal7, [pSrcLeft], +leftStep ;// tVal7 = pSrcLeft[4 to 7]
+ BNE LOOP_HOR ;// Loop for 3 times
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+OMX_VC_16X16_DC
+
+ ;// M_STALL ARM1136JS=2
+
+ MOV count, #0 ;// count = 0
+ TST availability, #OMX_VC_UPPER ;// if(availability & #OMX_VC_UPPER)
+ BEQ TST_LEFT ;// Jump to Left if not upper
+ LDM pSrcAbove,{tVal8,tVal9,tVal10,tVal11};// tVal 8 to 11 = pSrcAbove[0 to 15]
+ ADD count, count, #1 ;// if upper inc count by 1
+
+ ;// M_STALL ARM1136JS=2
+
+ UXTB16 tVal2, tVal8 ;// pSrcAbove[0, 2]
+ UXTB16 tVal6, tVal9 ;// pSrcAbove[4, 6]
+ UADD16 tVal2, tVal2, tVal6 ;// pSrcAbove[0, 2] + pSrcAbove[4, 6]
+ UXTB16 tVal8, tVal8, ROR #8 ;// pSrcAbove[1, 3]
+ UXTB16 tVal9, tVal9, ROR #8 ;// pSrcAbove[5, 7]
+ UADD16 tVal8, tVal8, tVal9 ;// pSrcAbove[1, 3] + pSrcAbove[5, 7]
+ UADD16 tVal2, tVal2, tVal8 ;// sum(pSrcAbove[0] to pSrcAbove[7])
+
+ UXTB16 tVal8, tVal10 ;// pSrcAbove[8, 10]
+ UXTB16 tVal9, tVal11 ;// pSrcAbove[12, 14]
+ UADD16 tVal8, tVal8, tVal9 ;// pSrcAbove[8, 10] + pSrcAbove[12, 14]
+ UXTB16 tVal10, tVal10, ROR #8 ;// pSrcAbove[9, 11]
+ UXTB16 tVal11, tVal11, ROR #8 ;// pSrcAbove[13, 15]
+ UADD16 tVal10, tVal10, tVal11 ;// pSrcAbove[9, 11] + pSrcAbove[13, 15]
+ UADD16 tVal8, tVal8, tVal10 ;// sum(pSrcAbove[8] to pSrcAbove[15])
+
+ UADD16 tVal2, tVal2, tVal8 ;// sum(pSrcAbove[0] to pSrcAbove[15])
+
+ ;// M_STALL ARM1136JS=1
+
+ ADD tVal2, tVal2, tVal2, LSR #16 ;// sum(pSrcAbove[0] to pSrcAbove[15])
+
+ ;// M_STALL ARM1136JS=1
+
+ UXTH sum, tVal2 ;// Extract the lower half for result
+
+TST_LEFT
+ TST availability, #OMX_VC_LEFT
+ BEQ TST_COUNT
+ ADD leftStepx2, leftStep,leftStep ;// leftStepx2 = 2 * leftStep
+ ADD pSrcLeft2, pSrcLeft, leftStep ;// pSrcLeft2 = pSrcLeft + leftStep
+
+ M_LDRB tVal8, [pSrcLeft], +leftStepx2 ;// tVal8 = pSrcLeft[0]
+ M_LDRB tVal9, [pSrcLeft2], +leftStepx2 ;// tVal9 = pSrcLeft[1]
+ M_LDRB tVal10, [pSrcLeft], +leftStepx2 ;// tVal10= pSrcLeft[2]
+ M_LDRB tVal11, [pSrcLeft2],+leftStepx2 ;// tVal11= pSrcLeft[3]
+ ADD tVal7, tVal8, tVal9 ;// tVal7 = tVal8 + tVal9
+ ADD count, count, #1 ;// Inc Counter if Left is available
+ ADD tVal6, tVal10, tVal11 ;// tVal6 = tVal10 + tVal11
+
+ M_LDRB tVal8, [pSrcLeft], +leftStepx2 ;// tVal8 = pSrcLeft[0]
+ M_LDRB tVal9, [pSrcLeft2], +leftStepx2 ;// tVal9 = pSrcLeft[1]
+ M_LDRB tVal10, [pSrcLeft], +leftStepx2 ;// tVal10= pSrcLeft[2]
+ M_LDRB tVal11, [pSrcLeft2],+leftStepx2 ;// tVal11= pSrcLeft[3]
+ ADD sum, tVal7, tVal6 ;// sum = tVal8 + tVal10
+ ADD tVal8, tVal8, tVal9 ;// tVal8 = tVal8 + tVal9
+ ADD tVal10, tVal10, tVal11 ;// tVal10= tVal10 + tVal11
+ ADD tVal7, tVal8, tVal10 ;// tVal7 = tVal8 + tVal10
+
+
+ M_LDRB tVal8, [pSrcLeft], +leftStepx2 ;// tVal8 = pSrcLeft[0]
+ M_LDRB tVal9, [pSrcLeft2], +leftStepx2 ;// tVal9 = pSrcLeft[1]
+ M_LDRB tVal10, [pSrcLeft], +leftStepx2 ;// tVal10= pSrcLeft[2]
+ M_LDRB tVal11, [pSrcLeft2],+leftStepx2 ;// tVal11= pSrcLeft[3]
+ ADD sum, sum, tVal7 ;// sum = sum + tVal7
+ ADD tVal8, tVal8, tVal9 ;// tVal8 = tVal8 + tVal9
+ ADD tVal10, tVal10, tVal11 ;// tVal10= tVal10 + tVal11
+ ADD tVal7, tVal8, tVal10 ;// tVal7 = tVal8 + tVal10
+
+
+ M_LDRB tVal8, [pSrcLeft], +leftStepx2 ;// tVal8 = pSrcLeft[0]
+ M_LDRB tVal9, [pSrcLeft2], +leftStepx2 ;// tVal9 = pSrcLeft[1]
+ M_LDRB tVal10, [pSrcLeft], +leftStepx2 ;// tVal10= pSrcLeft[2]
+ M_LDRB tVal11, [pSrcLeft2],+leftStepx2 ;// tVal11= pSrcLeft[3]
+ ADD sum, sum, tVal7 ;// sum = sum + tVal7
+ ADD tVal8, tVal8, tVal9 ;// tVal8 = tVal8 + tVal9
+ ADD tVal10, tVal10, tVal11 ;// tVal10= tVal10 + tVal11
+ ADD tVal7, tVal8, tVal10 ;// tVal7 = tVal8 + tVal10
+ ADD sum, sum, tVal7 ;// sum = sum + tVal7
+
+TST_COUNT
+ CMP count, #0 ;// if(count == 0)
+ MOVEQ sum, #128 ;// sum = 128 if(count == 0)
+ BEQ TST_COUNT0 ;// if(count == 0)
+ CMP count, #1 ;// if(count == 1)
+ ADDEQ sum, sum, #8 ;// sum += 8 if(count == 1)
+ ADDNE sum, sum, tVal2 ;// sum = sumleft + sumupper
+ ADDNE sum, sum, #16 ;// sum += 16 if(count == 2)
+
+ ;// M_STALL ARM1136JS=1
+
+ UXTH sum, sum ;// sum only byte rest cleared
+
+ ;// M_STALL ARM1136JS=1
+
+ LSREQ sum, sum, #4 ;// sum >> 4 if(count == 1)
+
+ ;// M_STALL ARM1136JS=1
+
+ LSRNE sum, sum, #5 ;// sum >> 5 if(count == 2)
+
+TST_COUNT0
+
+ ;// M_STALL ARM1136JS=1
+
+ ORR sum, sum, sum, LSL #8 ;// sum replicated in two halfword
+
+ ;// M_STALL ARM1136JS=1
+
+ ORR tVal6, sum, sum, LSL #16 ;// sum replicated in all bytes
+ CPY tVal7, tVal6 ;// tVal1 = tVal0
+ CPY tVal8, tVal6 ;// tVal2 = tVal0
+ CPY tVal9, tVal6 ;// tVal3 = tVal0
+ ADD dstStepx2, dstStep, dstStep ;// double dstStep
+ ADD pDst2, pDst, dstStep ;// pDst2- pDst advanced by dstStep
+ MOV y, #BLK_SIZE ;// Outer Loop Count
+
+LOOP_DC
+ STM pDst, {tVal6,tVal7,tVal8,tVal9} ;// pDst[0 to 15] = tVal 6 to 9
+ SUBS y, y, #2 ;// y--
+ ADD pDst, pDst, dstStepx2 ;// pDst advanced by dstStep
+ STM pDst2, {tVal6,tVal7,tVal8,tVal9} ;// pDst2[16 to 31] = tVal 6 to 9
+ ADD pDst2, pDst2, dstStepx2 ;// pDst advanced by dstStep
+ BNE LOOP_DC ;// Loop for 8 times
+
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+OMX_VC_16X16_PLANE
+
+ ;// M_STALL ARM1136JS=3
+ RSB tVal14, leftStep, leftStep, LSL #4 ;// tVal14 = 15*leftStep
+
+ ;// M_STALL ARM1136JS=2
+ LDRB tVal10, [pSrcLeft, tVal14] ;// tVal10 = pSrcLeft[15*leftStep]
+ LDRB tVal11, [pSrcAboveLeft] ;// tVal11 = pSrcAboveLeft[0]
+ LDRB tVal12, [pSrcAbove, #15]
+
+ ADD tVal2, tVal12, tVal10 ;// tVal2 = pSrcAbove[15] + pSrcLeft[15*leftStep]
+ SUB tVal10, tVal10, tVal11 ;// tVal10 = V0 = pSrcLeft[15*leftStep] - pSrcAboveLeft[0]
+ SUB tVal11, tVal12, tVal11 ;// tVal11 = H0 = pSrcAbove[15] - pSrcAboveLeft[0]
+ MOV tVal2, tVal2, LSL #4 ;// tVal2 = a = 16 * (pSrcAbove[15] + pSrcLeft[15*leftStep])
+
+ MOV tVal11, tVal11, LSL #3 ;// 8*[15]-[-1]
+ LDRB tVal6, [pSrcAbove, #0]
+ LDRB tVal7, [pSrcAbove, #14]
+ SUB tVal8, tVal7, tVal6
+ RSB tVal8, tVal8, tVal8, LSL #3 ;// 7*[14]-[0]
+ ADD tVal11, tVal11, tVal8
+ LDRB tVal6, [pSrcAbove, #1]
+ LDRB tVal7, [pSrcAbove, #13]
+ SUB tVal8, tVal7, tVal6
+ ADD tVal8, tVal8, tVal8
+ ADD tVal8, tVal8, tVal8, LSL #1 ;// 6*[13]-[1]
+ ADD tVal11, tVal11, tVal8
+ LDRB tVal6, [pSrcAbove, #2]
+ LDRB tVal7, [pSrcAbove, #12]
+ SUB tVal8, tVal7, tVal6
+ ADD tVal8, tVal8, tVal8, LSL #2 ;// 5*[12]-[2]
+ ADD tVal11, tVal11, tVal8
+ LDRB tVal6, [pSrcAbove, #3]
+ LDRB tVal7, [pSrcAbove, #11]
+ SUB tVal8, tVal7, tVal6
+ ADD tVal11, tVal11, tVal8, LSL #2 ;// + 4*[11]-[3]
+ LDRB tVal6, [pSrcAbove, #4]
+ LDRB tVal7, [pSrcAbove, #10]
+ SUB tVal8, tVal7, tVal6
+ ADD tVal8, tVal8, tVal8, LSL #1 ;// 3*[10]-[4]
+ ADD tVal11, tVal11, tVal8
+ LDRB tVal6, [pSrcAbove, #5]
+ LDRB tVal7, [pSrcAbove, #9]
+ SUB tVal8, tVal7, tVal6
+ ADD tVal11, tVal11, tVal8, LSL #1 ;// + 2*[9]-[5]
+ LDRB tVal6, [pSrcAbove, #6]
+ LDRB tVal7, [pSrcAbove, #8]
+ SUB tVal8, tVal7, tVal6 ;// 1*[8]-[6]
+ ADD tVal7, tVal11, tVal8
+
+ ADD tVal2, tVal2, #16 ;// tVal2 = a + 16
+ MOV tVal1, pSrcLeft ;// tVal4 = pSrcLeft
+ SUB tVal9, tVal14, leftStep ;// tVal9 = 14*leftStep
+ ADD tVal9, pSrcLeft, tVal9 ;// tVal9 = pSrcLeft + 14*leftStep
+
+ M_LDRB tVal8, [tVal9], -leftStep ;// tVal8 = pSrcLeft[14*leftStep]
+ M_LDRB tVal11, [tVal1], +leftStep ;// tVal11 = pSrcLeft[0]
+ ADD tVal7, tVal7, tVal7, LSL #2 ;// tVal7 = 5 * H
+ ADD tVal7, tVal7, #32 ;// tVal7 = 5 * H + 32
+ SUB tVal8, tVal8, tVal11 ;// tVal8 = pSrcLeft[14*leftStep] - pSrcLeft[0]
+ ASR tVal12, tVal7, #6 ;// tVal12 = b = (5 * H + 32) >> 6
+
+ RSB tVal8, tVal8, tVal8, LSL #3 ;// tVal8 = V1 = 7* (pSrcLeft[14*leftStep]-pSrcLeft[0])
+ ADD tVal6, tVal8, tVal10, LSL #3 ;// tVal6 = V = V0 +V1
+ M_LDRB tVal8, [tVal9], -leftStep ;// tVal8 = pSrcLeft[13*leftStep]
+ M_LDRB tVal10, [tVal1], +leftStep ;// tVal10 = pSrcLeft[leftStep]
+ RSB tVal7, tVal12, tVal12, LSL #3 ;// tVal7 = 7*b
+ SUB tVal2, tVal2, tVal7 ;// tVal2 = a + 16 - 7*b
+ SUB tVal7, tVal8, tVal10 ;// tVal7 = pSrcLeft[13*leftStep] - pSrcLeft[leftStep]
+ M_LDRB tVal8, [tVal9], -leftStep ;// tVal8 = pSrcLeft[12*lS]
+ ADD tVal7, tVal7, tVal7 ;// tVal7 = 2 * (pSrcLeft[13*leftStep] - pSrcLeft[leftStep])
+ M_LDRB tVal10, [tVal1], +leftStep ;// tVal10 = pSrcLeft[2*leftStep]
+ ADD tVal7, tVal7, tVal7, LSL #1 ;// tVal7 = 6 * (pSrcLeft[13*leftStep] - pSrcLeft[leftStep])
+ ADD tVal6, tVal6, tVal7 ;// tVal6 = V = V + V2
+ SUB tVal7, tVal8, tVal10 ;// tVal7 = pSrcLeft[12*leftStep] - pSrcLeft[2*leftStep]
+ M_LDRB tVal8, [tVal9], -leftStep ;// tVal8 = pSrcLeft[11*leftStep]
+ M_LDRB tVal10, [tVal1], +leftStep ;// tVal10 = pSrcLeft[3*leftStep]
+ ADD tVal7, tVal7, tVal7, LSL #2 ;// tVal7 = 5 * (pSrcLeft[12*leftStep] - pSrcLeft[2*leftStep])
+ ADD tVal6, tVal6, tVal7 ;// tVal6 = V = V + V3
+ SUB tVal7, tVal8, tVal10 ;// tVal7 = pSrcLeft[11*leftStep] - pSrcLeft[3*leftStep]
+ M_LDRB tVal8, [tVal9], -leftStep ;// tVal8 = pSrcLeft[10*leftStep]
+ M_LDRB tVal10, [tVal1], +leftStep ;// tVal10 = pSrcLeft[4*leftStep]
+ ADD tVal6, tVal6, tVal7, LSL #2 ;// tVal6 = V = V + V4
+ SUB dstStep, dstStep, #16 ;// tVal5 = dstStep - 16
+ SUB tVal7, tVal8, tVal10 ;// tVal7 = pSrcLeft[10*leftStep] - pSrcLeft[4*leftStep]
+ M_LDRB tVal8, [tVal9], -leftStep ;// tVal8 = pSrcLeft[9*leftStep]
+ M_LDRB tVal10, [tVal1], +leftStep ;// tVal10 = pSrcLeft[5*leftStep]
+ ADD tVal7, tVal7, tVal7, LSL #1 ;// tVal7 = 3 * (pSrcLeft[10*leftStep] - pSrcLeft[4*leftStep])
+ ADD tVal6, tVal6, tVal7 ;// tVal6 = V = V + V5
+ SUB tVal7, tVal8, tVal10 ;// tVal7 = pSrcLeft[9*leftStep] - pSrcLeft[5*leftStep]
+ M_LDRB tVal8, [tVal9], -leftStep ;// tVal8 = pSrcLeft[8*leftStep]
+ M_LDRB tVal10, [tVal1], +leftStep ;// tVal10 = pSrcLeft[6*leftStep]
+ ADD tVal6, tVal6, tVal7, LSL #1 ;// tVal6 = V = V + V6
+
+ ;// M_STALL ARM1136JS=1
+ SUB tVal7, tVal8, tVal10 ;// tVal7 = pSrcLeft[8*leftStep] - pSrcLeft[6*leftStep]
+ ADD tVal6, tVal6, tVal7 ;// tVal6 = V = V + V7
+
+ ;// M_STALL ARM1136JS=1
+ ADD tVal6, tVal6, tVal6, LSL #2 ;// tVal6 = 5*V
+ ADD tVal6, tVal6, #32 ;// tVal6 = 5*V + 32
+
+ ;// M_STALL ARM1136JS=1
+ ASR tVal14, tVal6, #6 ;// tVal14 = c = (5*V + 32)>>6
+
+ ;// M_STALL ARM1136JS=1
+ RSB tVal6, tVal14, tVal14, LSL #3 ;// tVal6 = 7*c
+ UXTH tVal14, tVal14 ;// tVal14 = Cleared the upper half word
+ ADD tVal10, tVal12, tVal12 ;// tVal10 = 2*b
+ ORR tVal14, tVal14, tVal14, LSL #16 ;// tVal14 = {c , c}
+ SUB tVal6, tVal2, tVal6 ;// tVal6 = d = a - 7*b - 7*c + 16
+ ADD tVal1, tVal6, tVal10 ;// tVal1 = pp2 = d + 2*b
+ ADD tVal10, tVal10, tVal12 ;// tVal10 =3*b
+ ORR tVal0, tVal6, tVal1, LSL #16 ;// tval0 = p2p0 = pack {p2, p0}
+ UXTH tVal12, tVal12 ;// tVal12 = Cleared the upper half word
+ UXTH tVal10, tVal10 ;// tVal12 = Cleared the upper half word
+ ORR tVal12, tVal12, tVal12, LSL #16 ;// tVal12 = {b , b}
+ ORR tVal10, tVal10, tVal10, LSL #16 ;// tVal10 = {3b , 3b}
+ SADD16 tVal1, tVal0, tVal12 ;// tVal1 = p3p1 = p2p0 + {b,b}
+ SADD16 tVal2, tVal1, tVal10 ;// tVal2 = p6p4 = p3p1 + {3b,3b}
+ SADD16 tVal4, tVal2, tVal12 ;// tVal4 = p7p5 = p6p4 + {b,b}
+ SADD16 tVal6, tVal4, tVal10 ;// tVal6 = p10p8 = p7p5 + {3b,3b}
+ SADD16 tVal7, tVal6, tVal12 ;// tVal7 = p11p9 = p10p8 + {b,b}
+ SADD16 tVal8, tVal7, tVal10 ;// tVal8 = p14p12 = p11p9 + {3b,3b}
+ SADD16 tVal9, tVal8, tVal12 ;// tVal9 = p15p13 = p14p12 + {b,b}
+ LDR r0x00FF00FF, =MASK_CONST ;// r0x00FF00FF = 0x00FF00FF
+
+LOOP_PLANE
+
+ USAT16 temp2, #13, p3p1
+ USAT16 temp1, #13, p2p0
+ SADD16 p3p1, p3p1, c
+ SADD16 p2p0, p2p0, c
+ AND temp2, r0x00FF00FF, temp2, ASR #5
+ AND temp1, r0x00FF00FF, temp1, ASR #5
+ ORR temp1, temp1, temp2, LSL #8
+ STR temp1, [pDst], #4
+
+ USAT16 temp2, #13, p7p5
+ USAT16 temp1, #13, p6p4
+ SADD16 p7p5, p7p5, c
+ SADD16 p6p4, p6p4, c
+ AND temp2, r0x00FF00FF, temp2, ASR #5
+ AND temp1, r0x00FF00FF, temp1, ASR #5
+ ORR temp1, temp1, temp2, LSL #8
+ STR temp1, [pDst], #4
+
+ USAT16 temp2, #13, p11p9
+ USAT16 temp1, #13, p10p8
+ SADD16 p11p9, p11p9, c
+ SADD16 p10p8, p10p8, c
+ AND temp2, r0x00FF00FF, temp2, ASR #5
+ AND temp1, r0x00FF00FF, temp1, ASR #5
+ ORR temp1, temp1, temp2, LSL #8
+ STR temp1, [pDst], #4
+
+ USAT16 temp2, #13, p15p13
+ USAT16 temp1, #13, p14p12
+ SADD16 p15p13, p15p13, c
+ SADD16 p14p12, p14p12, c
+ AND temp2, r0x00FF00FF, temp2, ASR #5
+ AND temp1, r0x00FF00FF, temp1, ASR #5
+ ORR temp1, temp1, temp2, LSL #8
+ STR temp1, [pDst], #4
+
+ ADDS r0x00FF00FF, r0x00FF00FF, #1<<28 ;// Loop counter value in top 4 bits
+
+ ADD pDst, pDst, dstStep
+
+ BCC LOOP_PLANE ;// Loop for 16 times
+ MOV return, #OMX_Sts_NoErr
+ M_END
+
+ ENDIF ;// ARM1136JS
+
+
+ END
+;-----------------------------------------------------------------------------------------------
+; omxVCM4P10_PredictIntra_16x16 ends
+;-----------------------------------------------------------------------------------------------
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
new file mode 100644
index 0000000..a90f460
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
@@ -0,0 +1,567 @@
+;//
+;//
+;// File Name: omxVCM4P10_PredictIntra_4x4_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+;// Define the processor variants supported by this file
+
+ M_VARIANTS ARM1136JS
+
+;//-------------------------------------------------------
+;// This table for implementing switch case of C in asm by
+;// the mehtod of two levels of indexing.
+;//-------------------------------------------------------
+
+ M_TABLE armVCM4P10_pSwitchTable4x4
+ DCD OMX_VC_4x4_VERT, OMX_VC_4x4_HOR
+ DCD OMX_VC_4x4_DC, OMX_VC_4x4_DIAG_DL
+ DCD OMX_VC_4x4_DIAG_DR, OMX_VC_4x4_VR
+ DCD OMX_VC_4x4_HD, OMX_VC_4x4_VL
+ DCD OMX_VC_4x4_HU
+
+ IF ARM1136JS
+
+;//--------------------------------------------
+;// Constants
+;//--------------------------------------------
+BLK_SIZE EQU 0x8
+MUL_CONST0 EQU 0x01010101
+ADD_CONST1 EQU 0x80808080
+
+;//--------------------------------------------
+;// Scratch variable
+;//--------------------------------------------
+return RN 0
+pTable RN 9
+pc RN 15
+r0x01010101 RN 1
+r0x80808080 RN 0
+
+tVal0 RN 0
+tVal1 RN 1
+tVal2 RN 2
+tVal4 RN 4
+tVal6 RN 6
+tVal7 RN 7
+tVal8 RN 8
+tVal9 RN 9
+tVal10 RN 10
+tVal11 RN 11
+tVal12 RN 12
+tVal14 RN 14
+
+Out0 RN 6
+Out1 RN 7
+Out2 RN 8
+Out3 RN 9
+
+Left0 RN 6
+Left1 RN 7
+Left2 RN 8
+Left3 RN 9
+
+Above0123 RN 12
+Above4567 RN 14
+
+AboveLeft RN 10
+
+;//--------------------------------------------
+;// Declare input registers
+;//--------------------------------------------
+pSrcLeft RN 0 ;// input pointer
+pSrcAbove RN 1 ;// input pointer
+pSrcAboveLeft RN 2 ;// input pointer
+pDst RN 3 ;// output pointer
+leftStep RN 4 ;// input variable
+dstStep RN 5 ;// input variable
+predMode RN 6 ;// input variable
+availability RN 7 ;// input variable
+
+;//-----------------------------------------------------------------------------------------------
+;// omxVCM4P10_PredictIntra_4x4 starts
+;//-----------------------------------------------------------------------------------------------
+
+ ;// Write function header
+ M_START omxVCM4P10_PredictIntra_4x4, r11
+
+ ;// Define stack arguments
+ M_ARG LeftStep, 4
+ M_ARG DstStep, 4
+ M_ARG PredMode, 4
+ M_ARG Availability, 4
+
+ ;// M_STALL ARM1136JS=4
+
+ LDR pTable,=armVCM4P10_pSwitchTable4x4 ;// Load index table for switch case
+
+ ;// Load argument from the stack
+ M_LDR predMode, PredMode ;// Arg predMode loaded from stack to reg
+ M_LDR leftStep, LeftStep ;// Arg leftStep loaded from stack to reg
+ M_LDR dstStep, DstStep ;// Arg dstStep loaded from stack to reg
+ M_LDR availability, Availability ;// Arg availability loaded from stack to reg
+
+ LDR pc, [pTable, predMode, LSL #2] ;// Branch to the case based on preMode
+
+OMX_VC_4x4_VERT
+
+ LDR Above0123, [pSrcAbove] ;// Above0123 = pSrcAbove[0 to 3]
+ M_STR Above0123, [pDst], dstStep ;// pDst[0 to 3] = Above0123
+ M_STR Above0123, [pDst], dstStep ;// pDst[4 to 7] = Above0123
+ M_STR Above0123, [pDst], dstStep ;// pDst[8 to 11] = Above0123
+ STR Above0123, [pDst] ;// pDst[12 to 15] = Above0123
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT ;// Macro to exit midway-break frm case
+
+OMX_VC_4x4_HOR
+
+ ;// M_STALL ARM1136JS=6
+
+ LDR r0x01010101, =MUL_CONST0 ;// Const to repeat the byte in reg 4 times
+ M_LDRB Left0, [pSrcLeft], leftStep ;// Left0 = pSrcLeft[0]
+ M_LDRB Left1, [pSrcLeft], leftStep ;// Left1 = pSrcLeft[1]
+ M_LDRB Left2, [pSrcLeft], leftStep ;// Left2 = pSrcLeft[2]
+ LDRB Left3, [pSrcLeft] ;// Left3 = pSrcLeft[3]
+ MUL Out0, Left0, r0x01010101 ;// replicate the val in all the bytes
+ MUL Out1, Left1, r0x01010101 ;// replicate the val in all the bytes
+ MUL Out2, Left2, r0x01010101 ;// replicate the val in all the bytes
+ MUL Out3, Left3, r0x01010101 ;// replicate the val in all the bytes
+ M_STR Out0, [pDst], dstStep ;// store {Out0} at pDst [0 to 3 ]
+ M_STR Out1, [pDst], dstStep ;// store {Out1} at pDst [4 to 7 ]
+ M_STR Out2, [pDst], dstStep ;// store {Out2} at pDst [8 to 11]
+ STR Out3, [pDst] ;// store {Out3} at pDst [12 to 15]
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT ;// Macro to exit midway-break frm case
+
+OMX_VC_4x4_DC
+
+ ;// M_STALL ARM1136JS=6
+
+ AND availability, availability, #(OMX_VC_UPPER + OMX_VC_LEFT)
+ CMP availability, #(OMX_VC_UPPER + OMX_VC_LEFT)
+ BNE UpperOrLeftOrNoneAvailable ;// Jump to Upper if not both
+ LDR Above0123, [pSrcAbove] ;// Above0123 = pSrcAbove[0 to 3]
+
+ ;// M_STALL ARM1136JS=1
+
+ UXTB16 tVal7, Above0123 ;// pSrcAbove[0, 2]
+ UXTB16 tVal6, Above0123, ROR #8 ;// pSrcAbove[1, 3]
+ UADD16 tVal11, tVal6, tVal7 ;// pSrcAbove[0, 2] + pSrcAbove[1, 3]
+ M_LDRB Left0, [pSrcLeft], leftStep ;// Left0 = pSrcLeft[0]
+ M_LDRB Left1, [pSrcLeft], leftStep ;// Left1 = pSrcLeft[1]
+ ADD tVal11, tVal11, LSR #16 ;// sum(pSrcAbove[0] to pSrcAbove[3])
+ M_LDRB Left2, [pSrcLeft], leftStep ;// Left2 = pSrcLeft[2]
+ LDRB Left3, [pSrcLeft] ;// Left3 = pSrcLeft[3]
+ UXTH tVal11, tVal11 ;// upsum1 (Clear the top junk bits)
+ ADD tVal6, Left0, Left1 ;// tVal6 = Left0 + Left1
+ ADD tVal7, Left2, Left3 ;// tVal7 = Left2 + Left3
+ ADD tVal6, tVal6, tVal7 ;// tVal6 = tVal6 + tVal7
+ ADD Out0, tVal6, tVal11 ;// Out0 = tVal6 + tVal11
+ ADD Out0, Out0, #4 ;// Out0 = Out0 + 4
+ LDR r0x01010101, =MUL_CONST0 ;// 0x01010101
+ MOV Out0, Out0, LSR #3 ;// Out0 = (Out0 + 4)>>3
+
+ ;// M_STALL ARM1136JS=1
+
+ MUL Out0, Out0, r0x01010101 ;// replicate the val in all the bytes
+
+ ;// M_STALL ARM1136JS=1
+
+ MOV return, #OMX_Sts_NoErr
+ M_STR Out0, [pDst], dstStep ;// store {Out0} at pDst [0 to 3 ]
+ M_STR Out0, [pDst], dstStep ;// store {Out0} at pDst [4 to 7 ]
+ M_STR Out0, [pDst], dstStep ;// store {Out0} at pDst [8 to 11]
+ STR Out0, [pDst] ;// store {Out0} at pDst [12 to 15]
+ M_EXIT ;// Macro to exit midway-break frm case
+
+UpperOrLeftOrNoneAvailable
+ ;// M_STALL ARM1136JS=3
+
+ CMP availability, #OMX_VC_UPPER ;// if(availability & #OMX_VC_UPPER)
+ BNE LeftOrNoneAvailable ;// Jump to Left if not upper
+ LDR Above0123, [pSrcAbove] ;// Above0123 = pSrcAbove[0 to 3]
+
+ ;// M_STALL ARM1136JS=3
+
+ UXTB16 tVal7, Above0123 ;// pSrcAbove[0, 2]
+ UXTB16 tVal6, Above0123, ROR #8 ;// pSrcAbove[1, 3]
+ UADD16 Out0, tVal6, tVal7 ;// pSrcAbove[0, 2] + pSrcAbove[1, 3]
+ LDR r0x01010101, =MUL_CONST0 ;// 0x01010101
+ ADD Out0, Out0, LSR #16 ;// sum(pSrcAbove[0] to pSrcAbove[3])
+
+ ;// M_STALL ARM1136JS=1
+
+ UXTH Out0, Out0 ;// upsum1 (Clear the top junk bits)
+ ADD Out0, Out0, #2 ;// Out0 = Out0 + 2
+
+ ;// M_STALL ARM1136JS=1
+
+ MOV Out0, Out0, LSR #2 ;// Out0 = (Out0 + 2)>>2
+
+ ;// M_STALL ARM1136JS=1
+
+ MUL Out0, Out0, r0x01010101 ;// replicate the val in all the bytes
+
+ ;// M_STALL ARM1136JS=1
+
+ MOV return, #OMX_Sts_NoErr
+ M_STR Out0, [pDst], dstStep ;// store {tVal6} at pDst [0 to 3 ]
+ M_STR Out0, [pDst], dstStep ;// store {tVal6} at pDst [4 to 7 ]
+ M_STR Out0, [pDst], dstStep ;// store {tVal6} at pDst [8 to 11]
+ STR Out0, [pDst] ;// store {tVal6} at pDst [12 to 15]
+
+ M_EXIT ;// Macro to exit midway-break frm case
+
+LeftOrNoneAvailable
+ ;// M_STALL ARM1136JS=3
+
+ LDR r0x01010101, =MUL_CONST0 ;// 0x01010101
+ CMP availability, #OMX_VC_LEFT
+ BNE NoneAvailable
+ M_LDRB Left0, [pSrcLeft], leftStep ;// Left0 = pSrcLeft[0]
+ M_LDRB Left1, [pSrcLeft], leftStep ;// Left1 = pSrcLeft[1]
+ M_LDRB Left2, [pSrcLeft], leftStep ;// Left2 = pSrcLeft[2]
+ LDRB Left3, [pSrcLeft] ;// Left3 = pSrcLeft[3]
+ ADD Out0, Left0, Left1 ;// Out0 = Left0 + Left1
+
+ ;// M_STALL ARM1136JS=1
+
+ ADD Out1, Left2, Left3 ;// Out1 = Left2 + Left3
+ ADD Out0, Out0, Out1 ;// Out0 = Out0 + Out1
+ ADD Out0, Out0, #2 ;// Out0 = Out0 + 2
+
+ ;// M_STALL ARM1136JS=1
+
+ MOV Out0, Out0, LSR #2 ;// Out0 = (Out0 + 2)>>2
+
+ ;// M_STALL ARM1136JS=1
+
+ MUL Out0, Out0, r0x01010101 ;// replicate the val in all the bytes
+
+ ;// M_STALL ARM1136JS=1
+
+ MOV return, #OMX_Sts_NoErr
+ M_STR Out0, [pDst], dstStep ;// store {Out0} at pDst [0 to 3 ]
+ M_STR Out0, [pDst], dstStep ;// store {Out0} at pDst [4 to 7 ]
+ M_STR Out0, [pDst], dstStep ;// store {Out0} at pDst [8 to 11]
+ STR Out0, [pDst] ;// store {Out0} at pDst [12 to 15]
+ M_EXIT ;// Macro to exit midway-break frm case
+
+NoneAvailable
+ MOV Out0, #128 ;// Out0 = 128 if(count == 0)
+
+ ;// M_STALL ARM1136JS=5
+
+ MUL Out0, Out0, r0x01010101 ;// replicate the val in all the bytes
+
+ ;// M_STALL ARM1136JS=1
+
+ MOV return, #OMX_Sts_NoErr
+ M_STR Out0, [pDst], dstStep ;// store {Out0} at pDst [0 to 3 ]
+ M_STR Out0, [pDst], dstStep ;// store {Out0} at pDst [4 to 7 ]
+ M_STR Out0, [pDst], dstStep ;// store {Out0} at pDst [8 to 11]
+ STR Out0, [pDst] ;// store {Out0} at pDst [12 to 15]
+ M_EXIT ;// Macro to exit midway-break frm case
+
+OMX_VC_4x4_DIAG_DL
+
+ ;//------------------------------------------------------------------
+ ;// f = (a+2*b+c+2)>>2
+ ;// Calculate as:
+ ;// d = (a + c )>>1
+ ;// e = (d - b')>>1
+ ;// f = e + 128
+ ;//------------------------------------------------------------------
+
+ ;// M_STALL ARM1136JS=3
+
+ TST availability, #OMX_VC_UPPER_RIGHT
+ LDMIA pSrcAbove, {Above0123, Above4567} ;// Above0123, Above4567 = pSrcAbove[0 to 7]
+ LDR r0x80808080, =ADD_CONST1 ;// 0x80808080
+ BNE DLUpperRightAvailable
+ LDR r0x01010101, =MUL_CONST0 ;// 0x01010101
+ MOV tVal7, Above0123, LSR #24 ;// {00, 00, 00, U3 }
+ MOV tVal11, tVal7, LSL #24 ;// {U3, 00, 00, 00 }
+ MUL Out3, tVal7, r0x01010101 ;// {U3, U3, U3, U3 }
+ MOV tVal8, Above0123, LSR #16 ;// {00, 00, U3, U2 }
+ MOV tVal10, Above0123, LSR #8 ;// {00, U3, U2, U1 }
+ MVN tVal10, tVal10 ;// {00', U3', U2', U1'}
+ UHADD8 tVal8, tVal8, Above0123 ;// {xx, xx, d1, d0 }
+ UHADD8 tVal6, Above0123, tVal9 ;// {xx, d2, xx, xx }
+ UHSUB8 tVal8, tVal8, tVal10 ;// {xx, xx, e1, e0 }
+ UHSUB8 tVal6, tVal6, tVal10 ;// {xx, e2, xx, xx }
+ UADD8 tVal8, tVal8, r0x80808080 ;// {xx, xx, f1, f0 }
+ UADD8 tVal6, tVal6, r0x80808080 ;// {xx, f2, xx, xx }
+
+ ;// M_STALL ARM1136JS=1
+
+ PKHBT tVal6, tVal8, tVal6 ;// {xx, f2, f1, f0 }
+ BIC tVal6, tVal6, #0xFF000000 ;// {00, f2, f1, f0 }
+ ORR Out0, tVal6, tVal11 ;// {U3, f2, f1, f0 }
+
+ ;// M_STALL ARM1136JS=1
+
+ PKHTB Out1, Out3, Out0, ASR #8 ;// {U3, U3, f2, f1 }
+ MOV return, #OMX_Sts_NoErr
+ PKHTB Out2, Out3, Out1, ASR #8 ;// {U3, U3, U3, f2 }
+
+ M_STR Out0, [pDst], dstStep ;// store {f3 to f0} at pDst[3 to 0 ]
+ M_STR Out1, [pDst], dstStep ;// store {f4 to f1} at pDst[7 to 4 ]
+ M_STR Out2, [pDst], dstStep ;// store {f5 to f2} at pDst[11 to 8 ]
+ STR Out3, [pDst] ;// store {f6 to f3} at pDSt[15 to 12]
+ M_EXIT ;// Macro to exit midway-break frm case
+
+DLUpperRightAvailable
+
+ MOV tVal8, Above0123, LSR #24 ;// {00, 00, 00, U3 }
+ MOV tVal9, Above0123, LSR #16 ;// {00, 00, U3, U2 }
+ MOV tVal10, Above0123, LSR #8 ;// {00, U3, U2, U1 }
+ ORR tVal8, tVal8, Above4567, LSL #8 ;// {U6, U5, U4, U3 }
+ ORR tVal10, tVal10, Above4567, LSL #24 ;// {U4, U3, U2, U1 }
+ PKHBT tVal9, tVal9, Above4567, LSL #16 ;// {U5, U4, U3, U2 }
+ MVN tVal1, tVal8 ;// {U6', U5', U4', U3'}
+ MVN tVal10, tVal10 ;// {U4', U3', U2', U1'}
+ MVN tVal2, Above4567 ;// {U7', U6', U5', U4'}
+ UHADD8 tVal6, Above0123, tVal9 ;// {d3, d2, d1, d0 }
+ UHADD8 tVal9, tVal9, Above4567 ;// {d5, d4, d3, d2 }
+ UHADD8 tVal8, Above4567, tVal8 ;// {d6, xx, xx, xx }
+ UHSUB8 tVal6, tVal6, tVal10 ;// {e3, e2, e1, e0 }
+ UHSUB8 tVal12, tVal9, tVal1 ;// {e5, e4, e3, e2 }
+ UHSUB8 tVal8, tVal8, tVal2 ;// {e6, xx, xx, xx }
+ UADD8 Out0, tVal6, r0x80808080 ;// {f3, f2, f1, f0 }
+ UADD8 tVal9, tVal8, r0x80808080 ;// {f6, xx, xx, xx }
+ UADD8 Out2, tVal12, r0x80808080 ;// {f5, f4, f3, f2 }
+ MOV tVal7, Out0, LSR #8 ;// {00, f3, f2, f1 }
+ AND tVal9, tVal9, #0xFF000000 ;// {f6, 00, 00, 00 }
+ PKHBT Out1, tVal7, Out2, LSL #8 ;// {f4, f3, f2, f1 }
+ ORR Out3, tVal9, Out2, LSR #8 ;// {f6, f5, f4, f3 }
+ M_STR Out0, [pDst], dstStep ;// store {f3 to f0} at pDst[3 to 0 ]
+ M_STR Out1, [pDst], dstStep ;// store {f4 to f1} at pDst[7 to 4 ]
+ M_STR Out2, [pDst], dstStep ;// store {f5 to f2} at pDst[11 to 8 ]
+ STR Out3, [pDst] ;// store {f6 to f3} at pDSt[15 to 12]
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT ;// Macro to exit midway-break frm case
+
+
+OMX_VC_4x4_DIAG_DR
+
+ ;// M_STALL ARM1136JS=4
+
+ M_LDRB Left0, [pSrcLeft], leftStep ;// Left0 = pSrcLeft[0]
+ M_LDRB Left1, [pSrcLeft], leftStep ;// Left1 = pSrcLeft[1]
+ M_LDRB Left2, [pSrcLeft], leftStep ;// Left2 = pSrcLeft[2]
+ LDRB Left3, [pSrcLeft] ;// Left3 = pSrcLeft[3]
+ LDRB AboveLeft, [pSrcAboveLeft] ;// AboveLeft = pSrcAboveLeft[0]
+ ORR tVal7, Left1, Left0, LSL #8 ;// tVal7 = 00 00 L0 L1
+ LDR Above0123, [pSrcAbove] ;// Above0123 = U3 U2 U1 U0
+ LDR r0x80808080, =ADD_CONST1 ;// 0x80808080
+ ORR tVal8, Left3, Left2, LSL #8 ;// tVal8 = 00 00 L2 L3
+ PKHBT tVal7, tVal8, tVal7, LSL #16 ;// tVal7 = L0 L1 L2 L3
+ MOV tVal8, Above0123, LSL #8 ;// tVal8 = U2 U1 U0 00
+ MOV tVal9, tVal7, LSR #8 ;// tVal9 = 00 L0 L1 L2
+ ORR tVal8, tVal8, AboveLeft ;// tVal8 = U2 U1 U0 UL
+ ORR tVal9, tVal9, AboveLeft, LSL #24 ;// tVal9 = UL L0 L1 L2
+ MOV tVal10, Above0123, LSL #24 ;// tVal10= U0 00 00 00
+ UXTB tVal11, tVal7, ROR #24 ;// tVal11= 00 00 00 L0
+ ORR tVal10, tVal10, tVal9, LSR #8 ;// tVal10= U0 UL L0 L1
+ ORR tVal11, tVal11, tVal8, LSL #8 ;// tVal11= U1 U0 UL L0
+ UHADD8 tVal11, Above0123, tVal11 ;// tVal11= d1 d0 dL g0
+ UHADD8 tVal10, tVal7, tVal10 ;// tVal10= g0 g1 g2 g3
+ MVN tVal8, tVal8 ;// tVal8 = U2'U1'U0'UL'
+ MVN tVal9, tVal9 ;// tVal9 = UL'L0'L1'L2'
+ UHSUB8 tVal11, tVal11, tVal8 ;// tVal11= e1 e0 eL h0
+ UHSUB8 tVal10, tVal10, tVal9 ;// tVal10= h0 h1 h2 h3
+ UADD8 Out3, tVal10, r0x80808080 ;// Out3 = i0 i1 i2 i3
+ UADD8 Out0, tVal11, r0x80808080 ;// Out0 = f1 f0 fL i0
+ UXTH tVal11, Out3, ROR #8 ;// tVal11= 00 00 i1 i2
+ MOV tVal7, Out0, LSL #8 ;// tVal7 = f0 fL i0 00
+ ORR Out1, tVal7, tVal11, LSR #8 ;// Out1 = f0 fL i0 i1
+ PKHBT Out2, tVal11, Out0, LSL #16 ;// Out2 = fL i0 i1 i2
+ M_STR Out0, [pDst], dstStep ;// store {f1 to i0} at pDst[3 to 0 ]
+ M_STR Out1, [pDst], dstStep ;// store {f0 to i1} at pDst[7 to 4 ]
+ M_STR Out2, [pDst], dstStep ;// store {fL to i2} at pDst[11 to 8 ]
+ STR Out3, [pDst] ;// store {i0 to i3} at pDst[15 to 12]
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT ;// Macro to exit midway-break frm case
+
+OMX_VC_4x4_VR
+
+ ;// M_STALL ARM1136JS=4
+
+ LDR Above0123, [pSrcAbove] ;// Above0123 = U3 U2 U1 U0
+ LDRB AboveLeft, [pSrcAboveLeft] ;// AboveLeft = 00 00 00 UL
+ M_LDRB Left0, [pSrcLeft], leftStep ;// Left0 = 00 00 00 L0
+ M_LDRB Left1, [pSrcLeft], leftStep ;// Left1 = 00 00 00 L1
+ LDRB Left2, [pSrcLeft] ;// Left2 = 00 00 00 L2
+ MOV tVal0, Above0123, LSL #8 ;// tVal0 = U2 U1 U0 00
+ MOV tVal9, Above0123 ;// tVal9 = U3 U2 U1 U0
+ ORR tVal14, tVal0, AboveLeft ;// tVal14 = U2 U1 U0 UL
+ MVN tVal11, tVal14 ;// tVal11 = U2'U1'U0'UL'
+ MOV tVal2, tVal14, LSL #8 ;// tVal2 = U1 U0 UL 00
+ UHSUB8 tVal1, Above0123, tVal11 ;// tVal1 = d2 d1 d0 dL
+ UHADD8 tVal10, AboveLeft, Left1 ;// tVal10 = 00 00 00 j1
+ MVN tVal4, Left0 ;// tVal4 = 00 00 00 L0'
+ UHSUB8 tVal4, tVal10, tVal4 ;// tVal4 = 00 00 00 k1
+ ORR tVal12, tVal0, Left0 ;// tVal12 = U2 U1 U0 L0
+ ORR tVal14, tVal2, Left0 ;// tVal14 = U1 U0 UL L0
+ LDR r0x80808080, =ADD_CONST1 ;// 0x80808080
+ UHADD8 tVal10, tVal9, tVal14 ;// tVal10 = g3 g2 g1 g0
+ UADD8 Out0, tVal1, r0x80808080 ;// Out0 = e2 e1 e0 eL
+ UHSUB8 tVal10, tVal10, tVal11 ;// tVal10 = h3 h2 h1 h0
+ M_STR Out0, [pDst], dstStep ;// store {e2 to eL} at pDst[3 to 0 ]
+ MOV tVal1, tVal14, LSL #8 ;// tVal1 = U0 UL L0 00
+ MOV tVal6, Out0, LSL #8 ;// tVal6 = e1 e0 eL 00
+ ORR tVal2, tVal2, Left1 ;// tVal2 = U1 U0 UL L1
+ UADD8 tVal4, tVal4, r0x80808080 ;// tVal4 = 00 00 00 l1
+ UADD8 Out1, tVal10, r0x80808080 ;// Out1 = i3 i2 i1 i0
+ MVN tVal2, tVal2 ;// tVal14 = U1'U0'UL'L1'
+ ORR tVal1, tVal1, Left2 ;// tVal1 = U0 UL L0 L2
+ ORR Out2, tVal6, tVal4 ;// Out2 = e1 e0 eL l1
+ UHADD8 tVal1, tVal1, tVal12 ;// tVal1 = g2 g1 g0 j2
+ M_STR Out1, [pDst], dstStep ;// store {i3 to i0} at pDst[7 to 4 ]
+ M_STR Out2, [pDst], dstStep ;// store {e1 to l1} at pDst[11 to 8 ]
+ UHSUB8 tVal9, tVal1, tVal2 ;// tVal9 = h2 h1 h0 k2
+ UADD8 Out3, tVal9, r0x80808080 ;// Out3 = i2 i1 i0 l2
+ STR Out3, [pDst] ;// store {i2 to l2} at pDst[15 to 12]
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT ;// Macro to exit midway-break frm case
+
+OMX_VC_4x4_HD
+
+ ;// M_STALL ARM1136JS=4
+
+ LDR Above0123, [pSrcAbove] ;// Above0123 = U3 U2 U1 U0
+ LDRB AboveLeft, [pSrcAboveLeft] ;// AboveLeft = 00 00 00 UL
+ M_LDRB Left0, [pSrcLeft], leftStep ;// Left0 = 00 00 00 L0
+ M_LDRB Left1, [pSrcLeft], leftStep ;// Left1 = 00 00 00 L1
+ M_LDRB Left2, [pSrcLeft], leftStep ;// Left2 = 00 00 00 L2
+ LDRB Left3, [pSrcLeft] ;// Left3 = 00 00 00 L3
+ LDR r0x80808080, =ADD_CONST1 ;// 0x80808080
+ ORR tVal2, AboveLeft, Above0123, LSL #8;// tVal2 = U2 U1 U0 UL
+ MVN tVal1, Left0 ;// tVal1 = 00 00 00 L0'
+ ORR tVal4, Left0, tVal2, LSL #8 ;// tVal4 = U1 U0 UL L0
+ MVN tVal2, tVal2 ;// tVal2 = U2'U1'U0'UL'
+ UHADD8 tVal4, tVal4, Above0123 ;// tVal4 = g3 g2 g1 g0
+ UHSUB8 tVal1, AboveLeft, tVal1 ;// tVal1 = 00 00 00 dL
+ UHSUB8 tVal4, tVal4, tVal2 ;// tVal4 = h3 h2 h1 h0
+ UADD8 tVal1, tVal1, r0x80808080 ;// tVal1 = 00 00 00 eL
+ UADD8 tVal4, tVal4, r0x80808080 ;// tVal4 = i3 i2 i1 i0
+ ORR tVal2, Left0, AboveLeft, LSL #16 ;// tVal2 = 00 UL 00 L0
+ MOV tVal4, tVal4, LSL #8 ;// tVal4 = i2 i1 i0 00
+ ORR tVal11, Left1, Left0, LSL #16 ;// tVal11= 00 L0 00 L1
+ ORR tVal7, Left2, Left1, LSL #16 ;// tVal7 = 00 L1 00 L2
+ ORR tVal10, Left3, Left2, LSL #16 ;// tVal10= 00 L2 00 L3
+ ORR Out0, tVal4, tVal1 ;// Out0 = i2 i1 i0 eL
+ M_STR Out0, [pDst], dstStep ;// store {Out0} at pDst [0 to 3 ]
+ MOV tVal4, Out0, LSL #16 ;// tVal4 = i1 i0 00 00
+ UHADD8 tVal2, tVal2, tVal7 ;// tVal2 = 00 j1 00 j2
+ UHADD8 tVal6, tVal11, tVal10 ;// tVal11= 00 j2 00 j3
+ MVN tVal12, tVal11 ;// tVal12= 00 L0'00 L1'
+ MVN tVal14, tVal7 ;// tVal14= 00 L1'00 L2'
+ UHSUB8 tVal2, tVal2, tVal12 ;// tVal2 = 00 k1 00 k2
+ UHSUB8 tVal8, tVal7, tVal12 ;// tVal8 = 00 d1 00 d2
+ UHSUB8 tVal11, tVal6, tVal14 ;// tVal11= 00 k2 00 k3
+ UHSUB8 tVal9, tVal10, tVal14 ;// tVal9 = 00 d2 00 d3
+ UADD8 tVal2, tVal2, r0x80808080 ;// tVal2 = 00 l1 00 l2
+ UADD8 tVal8, tVal8, r0x80808080 ;// tVal8 = 00 e1 00 e2
+ UADD8 tVal11, tVal11, r0x80808080 ;// tVal11= 00 l2 00 l3
+ UADD8 tVal9, tVal9, r0x80808080 ;// tVal9 = 00 e2 00 e3
+ ORR Out2, tVal8, tVal2, LSL #8 ;// Out2 = l1 e1 l2 e2
+ ORR Out3, tVal9, tVal11, LSL #8 ;// Out3 = l2 e2 l3 e3
+ PKHTB Out1, tVal4, Out2, ASR #16 ;// Out1 = i1 i0 l1 e1
+ M_STR Out1, [pDst], dstStep ;// store {Out1} at pDst [4 to 7 ]
+ M_STR Out2, [pDst], dstStep ;// store {Out2} at pDst [8 to 11]
+ STR Out3, [pDst] ;// store {Out3} at pDst [12 to 15]
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT ;// Macro to exit midway-break frm case
+
+OMX_VC_4x4_VL
+
+ ;// M_STALL ARM1136JS=3
+
+ LDMIA pSrcAbove, {Above0123, Above4567} ;// Above0123, Above4567 = pSrcAbove[0 to 7]
+ TST availability, #OMX_VC_UPPER_RIGHT
+ LDR r0x80808080, =ADD_CONST1 ;// 0x80808080
+ LDR r0x01010101, =MUL_CONST0 ;// 0x01010101
+ MOV tVal11, Above0123, LSR #24 ;// tVal11= 00 00 00 U3
+ MULEQ Above4567, tVal11, r0x01010101 ;// Above4567 = U3 U3 U3 U3
+ MOV tVal9, Above0123, LSR #8 ;// tVal9 = 00 U3 U2 U1
+ MVN tVal10, Above0123 ;// tVal10= U3'U2'U1'U0'
+ ORR tVal2, tVal9, Above4567, LSL #24 ;// tVal2 = U4 U3 U2 U1
+ UHSUB8 tVal8, tVal2, tVal10 ;// tVal8 = d4 d3 d2 d1
+ UADD8 Out0, tVal8, r0x80808080 ;// Out0 = e4 e3 e2 e1
+ M_STR Out0, [pDst], dstStep ;// store {Out0} at pDst [0 to 3 ]
+ MOV tVal9, tVal9, LSR #8 ;// tVal9 = 00 00 U3 U2
+ MOV tVal10, Above4567, LSL #8 ;// tVal10= U6 U5 U4 00
+ PKHBT tVal9, tVal9, Above4567, LSL #16 ;// tVal9 = U5 U4 U3 U2
+ ORR tVal10, tVal10, tVal11 ;// tVal10= U6 U5 U4 U3
+ UHADD8 tVal11, tVal9, Above0123 ;// tVal11= g5 g4 g3 g2
+ UHADD8 tVal14, tVal2, tVal10 ;// tVal14= g6 g5 g4 g3
+ MVN tVal8, tVal2 ;// tVal8 = U4'U3'U2'U1'
+ MVN tVal7, tVal9 ;// tVal7 = U5'U4'U3'U2'
+ UHSUB8 tVal12, tVal9, tVal8 ;// tVal12= d5 d4 d3 d2
+ UHSUB8 tVal11, tVal11, tVal8 ;// tVal11= h5 h4 h3 h2
+ UHSUB8 tVal2, tVal14, tVal7 ;// tVal2 = h6 h5 h4 h3
+ UADD8 Out1, tVal11, r0x80808080 ;// Out1 = i5 i4 i3 i2
+ UADD8 Out2, tVal12, r0x80808080 ;// Out2 = e5 e4 e3 e2
+ UADD8 Out3, tVal2, r0x80808080 ;// Out3 = i6 i5 i4 i3
+ M_STR Out1, [pDst], dstStep ;// store {Out1} at pDst [4 to 7 ]
+ M_STR Out2, [pDst], dstStep ;// store {Out2} at pDst [8 to 11]
+ M_STR Out3, [pDst], dstStep ;// store {Out3} at pDst [12 to 15]
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT ;// Macro to exit midway-break frm case
+
+OMX_VC_4x4_HU
+
+ ;// M_STALL ARM1136JS=2
+
+ LDR r0x01010101, =MUL_CONST0 ;// 0x01010101
+ M_LDRB Left0, [pSrcLeft], leftStep ;// Left0 = pSrcLeft[0]
+ M_LDRB Left1, [pSrcLeft], leftStep ;// Left1 = pSrcLeft[1]
+ M_LDRB Left2, [pSrcLeft], leftStep ;// Left2 = pSrcLeft[2]
+ LDRB Left3, [pSrcLeft] ;// Left3 = pSrcLeft[3]
+ MOV r0x80808080, r0x01010101, LSL #7 ;// 0x80808080
+ ORR tVal6, Left0, Left1, LSL #16 ;// tVal6 = 00 L1 00 L0
+ ORR tVal7, Left1, Left2, LSL #16 ;// tVal7 = 00 L2 00 L1
+ ORR tVal11, Left2, Left3, LSL #16 ;// tVal11= 00 L3 00 L2
+ MUL Out3, Left3, r0x01010101 ;// Out3 = L3 L3 L3 L3
+ MVN tVal8, tVal7 ;// tVal8 = 00 L2'00 L1'
+ MVN tVal10, tVal11 ;// tVal10= 00 L3'00 L2'
+ UHADD8 tVal4, tVal6, tVal11 ;// tVal4 = 00 g3 00 g2
+ UXTB16 tVal12, Out3 ;// tVal12= 00 L3 00 L3
+ UHSUB8 tVal4, tVal4, tVal8 ;// tVal4 = 00 h3 00 h2
+ UHSUB8 tVal6, tVal6, tVal8 ;// tVal6 = 00 d2 00 d1
+ UHSUB8 tVal11, tVal11, tVal8 ;// tVal11= 00 d3 00 d2
+ UHADD8 tVal12, tVal12, tVal7 ;// tVal12= 00 g4 00 g3
+ UADD8 tVal4, tVal4, r0x80808080 ;// tVal4 = 00 i3 00 i2
+ UHSUB8 tVal12, tVal12, tVal10 ;// tVal12= 00 h4 00 h3
+ UADD8 tVal8, tVal6, r0x80808080 ;// tVal8 = 00 e2 00 e1
+ UADD8 tVal11, tVal11, r0x80808080 ;// tVal11= 00 e3 00 e2
+ UADD8 tVal12, tVal12, r0x80808080 ;// tVal12= 00 i4 00 i3
+ ORR Out0, tVal8, tVal4, LSL #8 ;// Out0 = i3 e2 i2 e1
+ ORR Out1, tVal11, tVal12, LSL #8 ;// Out1 = i4 e3 i3 e2
+ M_STR Out0, [pDst], dstStep ;// store {Out0} at pDst [0 to 3 ]
+ PKHTB Out2, Out3, Out1, ASR #16 ;// Out2 = L3 L3 i4 e3
+ M_STR Out1, [pDst], dstStep ;// store {Out1} at pDst [4 to 7 ]
+ M_STR Out2, [pDst], dstStep ;// store {Out2} at pDst [8 to 11]
+ STR Out3, [pDst] ;// store {Out3} at pDst [12 to 15]
+ MOV return, #OMX_Sts_NoErr
+ M_END
+
+ ENDIF ;// ARM1136JS
+
+
+ END
+;//-----------------------------------------------------------------------------------------------
+;// omxVCM4P10_PredictIntra_4x4 ends
+;//-----------------------------------------------------------------------------------------------
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
new file mode 100644
index 0000000..53597a8
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
@@ -0,0 +1,128 @@
+;//
+;//
+;// File Name: omxVCM4P10_TransformDequantChromaDCFromPair_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ IMPORT armVCM4P10_QPDivTable
+ IMPORT armVCM4P10_VMatrixQPModTable
+
+ M_VARIANTS ARM1136JS
+
+
+ IF ARM1136JS
+
+;//--------------------------------------
+;// Declare input registers
+;//--------------------------------------
+ppSrc RN 0
+pDst RN 1
+QP RN 2
+
+;//--------------------------------
+;// Scratch variable for Unpack2x2
+;//--------------------------------
+pSrc RN 9
+Value RN 4
+Value2 RN 5
+Flag RN 6
+strOffset RN 7
+cstOffset RN 8
+
+;//--------------------------------
+;// Scratch variable
+;//--------------------------------
+r0w0 RN 3
+r0w1 RN 4
+
+c0w0 RN 5
+c1w0 RN 6
+
+return RN 0
+pQPDivTable RN 5
+pQPModTable RN 6
+Shift RN 9
+Scale RN 2
+
+Temp1 RN 3
+Temp2 RN 4
+Temp3 RN 7
+Temp4 RN 8
+
+ ;// Write function header
+ M_START omxVCM4P10_TransformDequantChromaDCFromPair, r9
+
+
+ LDR pSrc, [ppSrc] ;// Load pSrc
+ MOV cstOffset, #31 ;// To be used in the loop, to compute offset
+
+ ;//-----------------------------------------------------------------------
+ ;// Firstly, fill all the coefficient values on the <pDst> buffer by zero
+ ;//-----------------------------------------------------------------------
+
+ MOV Value, #0 ;// Initialize the zero value
+ MOV Value2, #0 ;// Initialize the zero value
+ LDRB Flag, [pSrc], #1 ;// Preload <Flag> before <unpackLoop>
+ STRD Value, [pDst, #0] ;// pDst[0] = pDst[1] = pDst[2] = pDst[3] = 0
+
+
+unpackLoop
+ TST Flag, #0x10 ;// Computing (Flag & 0x10)
+ LDRSBNE Value2,[pSrc,#1]
+ LDRBNE Value, [pSrc], #2 ;// Load byte wise to avoid unaligned access
+ AND strOffset, cstOffset, Flag, LSL #1 ;// strOffset = (Flag & 15) < 1;
+ LDRSBEQ Value, [pSrc], #1 ;// Value = (OMX_U8) *pSrc++
+ ORRNE Value,Value,Value2, LSL #8 ;// Value = (OMX_U16) *pSrc++
+
+ TST Flag, #0x20 ;// Computing (Flag & 0x20) to check, if we're done
+ LDRBEQ Flag, [pSrc], #1 ;// Flag = (OMX_U8) *pSrc++, for next iteration
+ STRH Value, [pDst, strOffset] ;// Store <Value> at offset <strOffset>
+ BEQ unpackLoop ;// Branch to the loop beginning
+
+ LDMIA pDst, {r0w0, r0w1} ;// r0w0 = |c1|c0| & r0w1 = |c3|c2|
+
+
+ STR pSrc, [ppSrc] ;// Update the bitstream pointer
+
+ LDR pQPDivTable, =armVCM4P10_QPDivTable ;// QP Division look-up-table base pointer
+ LDR pQPModTable, =armVCM4P10_VMatrixQPModTable ;// QP Modulo look-up-table base pointer
+
+ SADDSUBX r0w0, r0w0, r0w0 ;// [ c00+c01, c00-c01 ]
+ SADDSUBX r0w1, r0w1, r0w1 ;// [ c10+c11, c10-c11 ]
+
+ LDRSB Shift, [pQPDivTable, QP] ;// Shift = pQPDivTable[QP]
+ LDRSB Scale, [pQPModTable, QP] ;// Scale = pQPModTable[QP]
+
+ SADD16 c0w0, r0w0, r0w1 ;// [ d00+d10, d01+d11 ]
+ SSUB16 c1w0, r0w0, r0w1 ;// [ d00-d10, d01-d11 ]
+
+ LSL Scale, Scale, Shift ;// Scale = Scale << Shift
+
+ SMULTB Temp2, c0w0, Scale ;// Temp2 = T(c0w0) * Scale
+ SMULTB Temp4, c1w0, Scale ;// Temp4 = T(c1w0) * Scale
+ SMULBB Temp1, c0w0, Scale ;// Temp1 = B(c0w0) * Scale
+ SMULBB Temp3, c1w0, Scale ;// Temp3 = B(c1w0) * Scale
+ MOV Temp2, Temp2, ASR #1 ;// Temp2 = Temp2 >> 1 & Temp1 = (Temp1 >> 1) << 16
+ MOV Temp4, Temp4, ASR #1 ;// Temp4 = Temp4 >> 1 & Temp3 = (Temp3 >> 1) << 16
+ PKHBT c0w0, Temp2, Temp1, LSL #15 ;// c0w0 = | Temp1 | Temp2 |
+ PKHBT c1w0, Temp4, Temp3, LSL #15 ;// c1w0 = | Temp3 | Temp4 |
+ STMIA pDst, {c0w0, c1w0} ;// Storing all the coefficients at once
+ MOV return, #OMX_Sts_NoErr
+ M_END
+
+ ENDIF ;// ARM1136JS
+
+
+
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
new file mode 100644
index 0000000..73caec2
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
@@ -0,0 +1,469 @@
+;//
+;//
+;// File Name: omxVCM4P10_TransformDequantLumaDCFromPair_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// Description:
+;// H.264 inverse quantize and transform module
+;//
+;//
+
+;// Include standard headers
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+;// Import/Export symbols required from/to other files
+;// (For example tables)
+
+ IMPORT armVCM4P10_UnpackBlock4x4
+ IMPORT armVCM4P10_QPDivTable
+ IMPORT armVCM4P10_VMatrixQPModTable
+
+ M_VARIANTS ARM1136JS
+
+;// Set debugging level
+;//DEBUG_ON SETL {TRUE}
+
+
+;// Static Function: armVCM4P10_InvTransformDequantLumaDC4x4
+
+
+;// Guarding implementation by the processor name
+
+ IF ARM1136JS
+
+
+;//Input Registers
+pData RN 0
+QP RN 1
+
+;//Output Registers
+
+
+;//Local Scratch Registers
+
+;// Packed Input pixels
+in00 RN 2 ;// Src[0] & Src[1]
+in02 RN 3 ;// Src[2] & Src[3]
+in10 RN 4 ;// Src[4] & Src[5]
+in12 RN 5 ;// Src[6] & Src[7]
+in20 RN 6 ;// Src[8] & Src[9]
+in22 RN 7 ;// Src[10] & Src[11]
+in30 RN 8 ;// Src[12] & Src[13]
+in32 RN 9 ;// Src[14] & Src[15]
+
+;// Transpose for Row operations (Rows to cols)
+trRow00 RN 2
+trRow10 RN 10
+trRow02 RN 3
+trRow12 RN 5
+trRow20 RN 11
+trRow30 RN 12
+trRow32 RN 14
+trRow22 RN 7
+
+;// Intermediate calculations
+rowSum1 RN 4
+rowSum2 RN 6
+rowDiff1 RN 8
+rowDiff2 RN 9
+
+
+;// Row operated pixels
+rowOp00 RN 2
+rowOp10 RN 10
+rowOp20 RN 11
+rowOp30 RN 12
+rowOp02 RN 3
+rowOp12 RN 5
+rowOp22 RN 7
+rowOp32 RN 14
+
+;// Transpose for colulmn operations
+trCol00 RN 2
+trCol02 RN 3
+trCol10 RN 4
+trCol12 RN 5
+trCol20 RN 6
+trCol22 RN 7
+trCol30 RN 8
+trCol32 RN 9
+
+;// Intermediate calculations
+colSum1 RN 10
+colSum2 RN 11
+colDiff1 RN 12
+colDiff2 RN 14
+
+
+;// Coloumn operated pixels
+colOp00 RN 2
+colOp02 RN 3
+colOp10 RN 4
+colOp12 RN 5
+colOp20 RN 6
+colOp22 RN 7
+colOp30 RN 8
+colOp32 RN 9
+
+;// Temporary scratch varaibles
+pQPDivTable RN 0
+pQPModTable RN 11
+Shift RN 10
+Scale RN 14
+Round RN 0
+
+temp1 RN 10
+temp2 RN 11
+temp3 RN 12
+temp4 RN 1
+
+
+
+;// InvTransformed and Dequantized pixels
+out00 RN 2
+out02 RN 3
+out10 RN 4
+out12 RN 5
+out20 RN 6
+out22 RN 7
+out30 RN 8
+out32 RN 9
+
+
+
+
+ ;// Allocate stack memory required by the function
+ M_ALLOC4 pDataOnStack, 4
+
+ ;// Write function header
+ M_START armVCM4P10_InvTransformDequantLumaDC4x4,r11
+
+ ;******************************************************************
+ ;// The strategy used in implementing the transform is as follows:*
+ ;// Load the 4x4 block into 8 registers *
+ ;// Transpose the 4x4 matrix *
+ ;// Perform the row operations (on columns) using SIMD *
+ ;// Transpose the 4x4 result matrix *
+ ;// Perform the coloumn operations *
+ ;// Store the 4x4 block at one go *
+ ;******************************************************************
+
+ ;// Load all the 4x4 pixels
+
+ LDMIA pData,{in00,in02,in10,in12,in20,in22,in30,in32}
+
+ ;//*****************************************************************
+ ;//
+ ;// Transpose the matrix inorder to perform row ops as coloumn ops
+ ;// Input: in[][] = original matrix
+ ;// Output: trRow[][]= transposed matrix
+ ;// Step1: Obtain the LL part of the transposed matrix
+ ;// Step2: Obtain the HL part
+ ;// step3: Obtain the LH part
+ ;// Step4: Obtain the HH part
+ ;//
+ ;//*****************************************************************
+
+ ;// LL 2x2 transposed matrix
+ ;// d0 d1 - -
+ ;// d4 d5 - -
+ ;// - - - -
+ ;// - - - -
+
+ PKHTB trRow10,in10,in00,ASR #16 ;// [5 4] = [f5:f1]
+ PKHBT trRow00,in00,in10,LSL #16 ;// [1 0] = [f4:f0]
+
+ ;// HL 2x2 transposed matrix
+ ;// - - - -
+ ;// - - - -
+ ;// d8 d9 - -
+ ;// d12 d13 - -
+
+
+ PKHTB trRow30,in12,in02,ASR #16 ;// [13 12] = [7 3]
+ PKHBT trRow20,in02,in12,LSL #16 ;// [9 8] = [6 2]
+
+ ;// LH 2x2 transposed matrix
+ ;// - - d2 d3
+ ;// - - d6 d7
+ ;// - - - -
+ ;// - - - -
+
+ PKHBT trRow02,in20,in30,LSL #16 ;// [3 2] = [f12:f8]
+ PKHTB trRow12,in30,in20,ASR #16 ;// [7 6] = [f13:f9]
+
+
+
+
+ ;// HH 2x2 transposed matrix
+ ;// - - - -
+ ;// - - - -
+ ;// - - d10 d11
+ ;// - - d14 d15
+
+ PKHTB trRow32,in32,in22,ASR #16 ;// [15 14] = [15 11]
+ PKHBT trRow22,in22,in32,LSL #16 ;// [11 10] = [14 10]
+
+
+ ;****************************************
+ ;// Row Operations (Performed on columns)
+ ;****************************************
+
+
+ ;// SIMD operations on first two columns(two rows of the original matrix)
+
+ SADD16 rowSum1,trRow00,trRow10 ;// (c0+c1)
+ SADD16 rowSum2,trRow20,trRow30 ;// (c2+c3)
+ SSUB16 rowDiff1,trRow00,trRow10 ;// (c0-c1)
+ SSUB16 rowDiff2,trRow20,trRow30 ;// (c2-c3)
+ SADD16 rowOp00,rowSum1,rowSum2 ;// (c0+c1+c2+c3)
+ SSUB16 rowOp10,rowSum1,rowSum2 ;// (c0+c1-c2-c3)
+ SSUB16 rowOp20,rowDiff1,rowDiff2 ;// (c0-c1-c2+c3)
+ SADD16 rowOp30,rowDiff1,rowDiff2 ;// (c0-c1+c2-c3)
+
+
+ ;// SIMD operations on next two columns(next two rows of the original matrix)
+
+ SADD16 rowSum1,trRow02,trRow12 ;// (c0+c1)
+ SADD16 rowSum2,trRow22,trRow32 ;// (c2+c3)
+ SSUB16 rowDiff1,trRow02,trRow12 ;// (c0-c1)
+ SSUB16 rowDiff2,trRow22,trRow32 ;// (c2-c3)
+ SADD16 rowOp02,rowSum1,rowSum2 ;// (c0+c1+c2+c3)
+ SSUB16 rowOp12,rowSum1,rowSum2 ;// (c0+c1-c2-c3)
+ SSUB16 rowOp22,rowDiff1,rowDiff2 ;// (c0-c1-c2+c3)
+ SADD16 rowOp32,rowDiff1,rowDiff2 ;// (c0-c1+c2-c3)
+
+
+
+ ;*****************************************************************
+ ;// Transpose the resultant matrix
+ ;// Input: rowOp[][]
+ ;// Output: trCol[][]
+ ;*****************************************************************
+
+ ;// LL 2x2 transposed matrix
+ ;// d0 d1 - -
+ ;// d4 d5 - -
+ ;// - - - -
+ ;// - - - -
+
+ PKHTB trCol10,rowOp10,rowOp00,ASR #16 ;// [5 4] = [f5:f1]
+ PKHBT trCol00,rowOp00,rowOp10,LSL #16 ;// [1 0] = [f4:f0]
+
+ ;// HL 2x2 transposed matrix
+ ;// - - - -
+ ;// - - - -
+ ;// d8 d9 - -
+ ;// d12 d13 - -
+
+
+ PKHTB trCol30,rowOp12,rowOp02,ASR #16 ;// [13 12] = [7 3]
+ PKHBT trCol20,rowOp02,rowOp12,LSL #16 ;// [9 8] = [6 2]
+
+ ;// LH 2x2 transposed matrix
+ ;// - - d2 d3
+ ;// - - d6 d7
+ ;// - - - -
+ ;// - - - -
+
+ PKHBT trCol02,rowOp20,rowOp30,LSL #16 ;// [3 2] = [f12:f8]
+ PKHTB trCol12,rowOp30,rowOp20,ASR #16 ;// [7 6] = [f13:f9]
+
+
+
+
+ ;// HH 2x2 transposed matrix
+ ;// - - - -
+ ;// - - - -
+ ;// - - d10 d11
+ ;// - - d14 d15
+
+ PKHTB trCol32,rowOp32,rowOp22,ASR #16 ;// [15 14] = [15 11]
+ PKHBT trCol22,rowOp22,rowOp32,LSL #16 ;// [11 10] = [14 10]
+
+
+ ;*******************************
+ ;// Coloumn Operations
+ ;*******************************
+
+ ;//--------------------------------------------------------------------------------------
+ ;// Store pData(RN0) on stack and restore it only at the final store back
+ ;// This frees up a register (RN0) which is used to reduce number of intermediate stalls
+ ;//--------------------------------------------------------------------------------------
+ M_STR pData,pDataOnStack
+
+
+ ;// SIMD operations on first two columns(two rows of the original matrix)
+
+ SADD16 colSum1,trCol00,trCol10 ;// (c0+c1)
+ SADD16 colSum2,trCol20,trCol30 ;// (c2+c3)
+ SSUB16 colDiff1,trCol00,trCol10 ;// (c0-c1)
+ SSUB16 colDiff2,trCol20,trCol30 ;// (c2-c3)
+ SADD16 colOp00,colSum1,colSum2 ;// (c0+c1+c2+c3)
+ SSUB16 colOp10,colSum1,colSum2 ;// (c0+c1-c2-c3)
+ SSUB16 colOp20,colDiff1,colDiff2 ;// (c0-c1-c2+c3)
+ SADD16 colOp30,colDiff1,colDiff2 ;// (c0-c1+c2-c3)
+
+
+ ;// SIMD operations on next two columns(next two rows of the original matrix)
+
+ LDR pQPDivTable, =armVCM4P10_QPDivTable ;// QP Division look-up-table base pointer
+ SADD16 colSum1,trCol02,trCol12 ;// (c0+c1)
+ SADD16 colSum2,trCol22,trCol32 ;// (c2+c3)
+ SSUB16 colDiff1,trCol02,trCol12 ;// (c0-c1)
+ SSUB16 colDiff2,trCol22,trCol32 ;// (c2-c3)
+ SADD16 colOp02,colSum1,colSum2 ;// (c0+c1+c2+c3)
+ SSUB16 colOp12,colSum1,colSum2 ;// (c0+c1-c2-c3)
+ LDR pQPModTable, =armVCM4P10_VMatrixQPModTable ;// QP Modulo look-up-table base pointer
+ LDRSB Shift, [pQPDivTable, QP] ;// Shift = pQPDivTable[QP]
+ SSUB16 colOp22,colDiff1,colDiff2 ;// (c0-c1-c2+c3)
+ SADD16 colOp32,colDiff1,colDiff2 ;// (c0-c1+c2-c3)
+
+
+ LDRSB Scale, [pQPModTable, QP] ;// Scale = pQPModTable[QP]
+
+ ;//----------------------------------------------------------------------
+ ;//
+ ;// <Dequantize> improves on the c-reference code
+ ;// Both the cases i.e., Shift>=0 and Shift<0 cases are covered together
+ ;// We do not subtract 2 from Shift as in C reference, instead perform a
+ ;// Scale << Shift once in the beginning and do a right shift by a
+ ;// constant 2 after the Multiplication. The value of Round would be 2
+ ;//
+ ;// By doing this we aviod the Branches required and also
+ ;// reduce the code size substantially
+ ;//
+ ;//----------------------------------------------------------------------
+
+ MOV Round, #2 ;// Round = 2
+ LSL Scale, Scale, Shift ;// Scale = Scale << Shift
+
+
+ ;// Row 1
+ SMLABB temp1, colOp00, Scale, Round ;// Temp1 = B(c0w0) * Scale + Round
+ SMLABB temp3, colOp02, Scale, Round ;// Temp3 = B(c1w0) * Scale + Round
+ SMLATB temp2, colOp00, Scale, Round ;// Temp2 = T(c0w0) * Scale + Round
+ SMLATB temp4, colOp02, Scale, Round ;// Temp4 = T(c1w0) * Scale + Round
+
+ ASR temp1, temp1, #2 ;// Temp1 = Temp1 >> 2
+ ASR temp3, temp3, #2 ;// Temp3 = Temp3 >> 2
+ PKHBT out00, temp1, temp2, LSL #14 ;// c0w0 = | Temp2 | Temp1 |
+ PKHBT out02, temp3, temp4, LSL #14 ;// c1w0 = | Temp2 | Temp1 |
+
+
+ ;// Row 2
+ SMLABB temp1, colOp10, Scale, Round ;// Temp1 = B(c0w0) * Scale + Round
+ SMLABB temp3, colOp12, Scale, Round ;// Temp3 = B(c1w0) * Scale + Round
+ SMLATB temp2, colOp10, Scale, Round ;// Temp2 = T(c0w0) * Scale + Round
+ SMLATB temp4, colOp12, Scale, Round ;// Temp4 = T(c1w0) * Scale + Round
+
+ ASR temp1, temp1, #2 ;// Temp1 = Temp1 >> 2
+ ASR temp3, temp3, #2 ;// Temp3 = Temp3 >> 2
+ PKHBT out10, temp1, temp2, LSL #14 ;// c0w0 = | Temp2 | Temp1 |
+ PKHBT out12, temp3, temp4, LSL #14 ;// c1w0 = | Temp2 | Temp1 |
+
+ ;// Row 3
+ SMLABB temp1, colOp20, Scale, Round ;// Temp1 = B(c0w0) * Scale + Round
+ SMLABB temp3, colOp22, Scale, Round ;// Temp3 = B(c1w0) * Scale + Round
+ SMLATB temp2, colOp20, Scale, Round ;// Temp2 = T(c0w0) * Scale + Round
+ SMLATB temp4, colOp22, Scale, Round ;// Temp4 = T(c1w0) * Scale + Round
+
+ ASR temp1, temp1, #2 ;// Temp1 = Temp1 >> 2
+ ASR temp3, temp3, #2 ;// Temp3 = Temp3 >> 2
+ PKHBT out20, temp1, temp2, LSL #14 ;// c0w0 = | Temp2 | Temp1 |
+ PKHBT out22, temp3, temp4, LSL #14 ;// c1w0 = | Temp2 | Temp1 |
+
+ ;// Row 4
+ SMLABB temp1, colOp30, Scale, Round ;// Temp1 = B(c0w0) * Scale + Round
+ SMLABB temp3, colOp32, Scale, Round ;// Temp3 = B(c1w0) * Scale + Round
+ SMLATB temp2, colOp30, Scale, Round ;// Temp2 = T(c0w0) * Scale + Round
+ SMLATB temp4, colOp32, Scale, Round ;// Temp4 = T(c1w0) * Scale + Round
+
+ M_LDR pData,pDataOnStack ;// Restore pData pointer from stack
+ ASR temp1, temp1, #2 ;// Temp1 = Temp1 >> 2
+ ASR temp3, temp3, #2 ;// Temp3 = Temp3 >> 2
+ PKHBT out30, temp1, temp2, LSL #14 ;// c0w0 = | Temp2 | Temp1 |
+ PKHBT out32, temp3, temp4, LSL #14 ;// c1w0 = | Temp2 | Temp1 |
+
+
+
+ ;***************************
+ ;// Store all the 4x4 pixels
+ ;***************************
+
+store_coeff
+
+ STMIA pData,{out00,out02,out10,out12,out20,out22,out30,out32}
+
+
+
+ ;// Set return value
+
+
+ ;// Write function tail
+ M_END
+
+ ENDIF ;//ARM1136JS
+
+
+;// Static Function: armVCM4P10_InvTransformDequantLumaDC4x4
+
+;// Guarding implementation by the processor name
+
+
+
+
+;// Function: omxVCM4P10_TransformDequantLumaDCFromPair
+
+;//Input Registers
+ppSrc RN 0
+pDst RN 1
+QPR2 RN 2
+
+;//Output Registers
+result RN 0
+
+;//Local Scratch Registers
+pDstR4 RN 4
+pDstR0 RN 0
+QPR1 RN 1
+QPR5 RN 5
+
+;// Guarding implementation by the processor name
+
+ IF ARM1136JS
+
+ ;// Allocate stack memory required by the function
+
+
+ ;// Write function header
+ M_START omxVCM4P10_TransformDequantLumaDCFromPair,r5
+
+ MOV pDstR4,pDst ;// Saving register r1
+ MOV QPR5,QPR2 ;// Saving register r2
+ BL armVCM4P10_UnpackBlock4x4
+
+ MOV pDstR0,pDstR4 ;// Setting up register r0
+ MOV QPR1,QPR5 ;// Setting up register r1
+ BL armVCM4P10_InvTransformDequantLumaDC4x4
+
+
+ ;// Set return value
+ MOV result,#OMX_Sts_NoErr
+
+ ;// Write function tail
+ M_END
+
+
+ ENDIF ;//ARM1136JS
+
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
new file mode 100644
index 0000000..22115d3
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
@@ -0,0 +1,37 @@
+/**
+ *
+ * File Name: armVCM4P2_Huff_Tables_VLC.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ *
+ * File: armVCM4P2_Huff_Tables.h
+ * Description: Declares Tables used for Hufffman coding and decoding
+ * in MP4P2 codec.
+ *
+ */
+
+#ifndef _OMXHUFFTAB_H_
+#define _OMXHUFFTAB_H_
+
+
+extern const OMX_U16 armVCM4P2_IntraVlcL0L1[200];
+
+
+extern const OMX_U16 armVCM4P2_InterVlcL0L1[200];
+
+extern const OMX_U16 armVCM4P2_aIntraDCLumaChromaIndex[64];
+//extern const OMX_U16 armVCM4P2_aIntraDCChromaIndex[32];
+extern const OMX_U16 armVCM4P2_aVlcMVD[124];
+
+extern const OMX_U8 armVCM4P2_InterL0L1LMAX[73];
+extern const OMX_U8 armVCM4P2_InterL0L1RMAX[35];
+extern const OMX_U8 armVCM4P2_IntraL0L1LMAX[53];
+extern const OMX_U8 armVCM4P2_IntraL0L1RMAX[40]
+
+#endif /* _OMXHUFFTAB_H_ */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
new file mode 100644
index 0000000..d5f865c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
@@ -0,0 +1,25 @@
+/**
+ *
+ * File Name: armVCM4P2_ZigZag_Tables.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ *
+ * File: armVCM4P2_Zigzag_Tables.h
+ * Description: Declares Tables used for Zigzag scan in MP4P2 codec.
+ *
+ */
+
+#ifndef _OMXZIGZAGTAB_H
+#define _OMXZIGZAGTAB_H
+
+extern const OMX_U8 armVCM4P2_aClassicalZigzagScan [192];
+//extern const OMX_U8 armVCM4P2_aHorizontalZigzagScan [64];
+//extern const OMX_U8 armVCM4P2_aVerticalZigzagScan [64];
+
+#endif /* _OMXZIGZAGTAB_H_ */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Clip8_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Clip8_s.s
new file mode 100644
index 0000000..7801e57
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Clip8_s.s
@@ -0,0 +1,75 @@
+; /**
+; *
+; * File Name: armVCM4P2_Clip8_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 9641
+; * Date: Thursday, February 7, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains module for Clipping 16 bit value to [0,255] Range
+; */
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+
+ M_VARIANTS ARM1136JS
+
+
+
+ IF ARM1136JS
+
+;//Input Arguments
+
+pSrc RN 0
+pDst RN 1
+step RN 2
+
+;// Local variables
+
+x0 RN 3
+x1 RN 4
+x2 RN 5
+x3 RN 6
+
+Count RN 14
+
+
+ M_START armVCM4P2_Clip8,r6
+
+
+ MOV Count,#8
+loop
+
+ LDMIA pSrc!,{x0, x1}
+ SUBS Count,Count, #1 ;// count down
+ LDMIA pSrc!,{x2, x3}
+ USAT16 x0, #8, x0 ;// clip two samples to [0,255]
+ USAT16 x1, #8, x1 ;// clip two samples to [0,255]
+ STRB x0, [pDst]
+ MOV x0, x0, LSR #16
+ STRB x0, [pDst,#1]
+ STRB x1, [pDst,#2]
+ MOV x1, x1, LSR #16
+ STRB x1, [pDst,#3]
+
+ USAT16 x2, #8, x2 ;// clip two samples to [0,255]
+ USAT16 x3, #8, x3 ;// clip two samples to [0,255]
+ STRB x2, [pDst,#4]
+ MOV x2, x2, LSR #16
+ STRB x2, [pDst,#5]
+ STRB x3, [pDst,#6]
+ MOV x3, x3, LSR #16
+ STRB x3, [pDst,#7]
+ ADD pDst,pDst,step ;// Increment pDst by step value
+
+ BGT loop ;// Continue loop until Count reaches 64
+
+ M_END
+ ENDIF
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
new file mode 100644
index 0000000..9e30900
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
@@ -0,0 +1,398 @@
+;/**
+; *
+; * File Name: armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 9641
+; * Date: Thursday, February 7, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains modules for zigzag scanning and VLC decoding
+; * for inter, intra block.
+; *
+; *
+; *
+; * Function: omxVCM4P2_DecodeVLCZigzag_AC_unsafe
+; *
+; * Description:
+; * Performs VLC decoding and inverse zigzag scan
+; *
+; *
+; *
+; *
+; */
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armCOMM_BitDec_s.h
+
+
+ M_VARIANTS ARM1136JS
+
+
+
+
+
+ IF ARM1136JS
+
+
+
+
+
+;//Input Arguments
+
+ppBitStream RN 0
+pBitOffset RN 1
+pDst RN 2
+shortVideoHeader RN 3
+
+
+;//Local Variables
+
+Return RN 0
+
+pVlcTableL0L1 RN 4
+pLMAXTableL0L1 RN 4
+pRMAXTableL0L1 RN 4
+pZigzagTable RN 4
+
+ftype RN 0
+temp3 RN 4
+temp RN 5
+Count RN 6
+Escape RN 5
+
+;// armVCM4P2_FillVLDBuffer
+zigzag RN 0
+storeLevel RN 1
+temp2 RN 4
+temp1 RN 5
+sign RN 5
+Last RN 7
+storeRun RN 14
+
+
+packRetIndex RN 5
+
+
+markerbit RN 5
+
+;// Scratch Registers
+
+RBitStream RN 8
+RBitBuffer RN 9
+RBitCount RN 10
+
+T1 RN 11
+T2 RN 12
+LR RN 14
+
+
+
+ M_ALLOC4 pppBitStream,4
+ M_ALLOC4 ppOffset,4
+ M_ALLOC4 pLinkRegister,4
+
+ M_START armVCM4P2_DecodeVLCZigzag_AC_unsafe
+
+ ;// get the table addresses from stack
+ M_ARG ppVlcTableL0L1,4
+ M_ARG ppLMAXTableL0L1,4
+ M_ARG ppRMAXTableL0L1,4
+ M_ARG ppZigzagTable,4
+
+ ;// Store ALL zeros at pDst
+
+ MOV temp1,#0 ;// Initialize Count to zero
+ MOV Last,#0
+ M_STR LR,pLinkRegister ;// Store Link Register on Stack
+ MOV temp2,#0
+ MOV LR,#0
+
+ ;// Initialize the Macro and Store all zeros to pDst
+
+ STM pDst!,{temp2,temp1,Last,LR}
+ M_BD_INIT0 ppBitStream, pBitOffset, RBitStream, RBitBuffer, RBitCount
+ STM pDst!,{temp2,temp1,Last,LR}
+ M_BD_INIT1 T1, T2, T2
+ STM pDst!,{temp2,temp1,Last,LR}
+ M_BD_INIT2 T1, T2, T2
+ STM pDst!,{temp2,temp1,Last,LR}
+ M_STR ppBitStream,pppBitStream ;// Store ppBitstream on stack
+ STM pDst!,{temp2,temp1,Last,LR}
+ M_STR pBitOffset,ppOffset ;// Store pBitOffset on stack
+ STM pDst!,{temp2,temp1,Last,LR}
+
+ STM pDst!,{temp2,temp1,Last,LR}
+ STM pDst!,{temp2,temp1,Last,LR}
+
+
+ SUB pDst,pDst,#128 ;// Restore pDst
+
+ ;// The armVCM4P2_GetVLCBits begins
+
+getVLCbits
+
+ M_BD_LOOK8 Escape,7 ;// Load Escape Value
+ LSR Escape,Escape,#25
+ CMP Escape,#3 ;// check for escape mode
+ MOVNE ftype,#0
+ BNE notEscapemode ;// Branch if not in Escape mode 3
+
+ M_BD_VSKIP8 #7,T1
+ CMP shortVideoHeader,#0 ;// Check shortVideoHeader flag to know the type of Escape mode
+ BEQ endFillVLD
+
+ ;// Escape Mode 4
+
+ M_BD_READ8 Last,1,T1
+ M_BD_READ8 storeRun,6,T1
+ M_BD_READ8 storeLevel,8,T1
+
+
+ ;// Check whether the Reserved values for Level are used and Exit with an Error Message if it is so
+
+ TEQ storeLevel,#0
+ TEQNE storeLevel,#128
+ BEQ ExitError
+
+ ADD temp2,storeRun,Count
+ CMP temp2,#64
+ BGE ExitError ;// error if Count+storeRun >= 64
+
+
+ ;// Load address of zigzagTable
+
+ M_LDR pZigzagTable,ppZigzagTable ;// Loading the Address of Zigzag table
+
+
+ ;// armVCM4P2_FillVLDBuffer
+
+ SXTB storeLevel,storeLevel ;// Sign Extend storeLevel to 32 bits
+
+
+ ;// To Reflect Runlength
+
+ ADD Count,Count,storeRun
+ LDRB zigzag,[pZigzagTable,Count]
+ ADD Count,Count,#1
+ STRH storeLevel,[pDst,zigzag] ;// store Level
+
+ B ExitOk
+
+
+
+endFillVLD
+
+
+ ;// Load Ftype( Escape Mode) value based on the two successive bits in the bitstream
+
+ M_BD_READ8 temp1,1,T1
+ CMP temp1,#0
+ MOVEQ ftype,#1
+ BEQ notEscapemode
+ M_BD_READ8 temp1,1,T1
+ CMP temp1,#1
+ MOVEQ ftype,#3
+ MOVNE ftype,#2
+
+
+notEscapemode
+
+ ;// Load optimized packed VLC table with last=0 and Last=1
+
+ M_LDR pVlcTableL0L1,ppVlcTableL0L1 ;// Load Combined VLC Table
+
+
+ CMP ftype,#3 ;// If ftype >=3 get perform Fixed Length Decoding (Escape Mode 3)
+ BGE EscapeMode3 ;// Else continue normal VLC Decoding
+
+ ;// Variable lengh decoding, "armUnPackVLC32"
+
+
+ M_BD_VLD packRetIndex,T1,T2,pVlcTableL0L1,4,2
+
+
+ LDR temp3,=0xFFF
+
+ CMP packRetIndex,temp3 ;// Check for invalid symbol
+ BEQ ExitError ;// if invalid symbol occurs exit with an error message
+
+ AND Last,packRetIndex,#2 ;// Get Last from packed Index
+
+
+
+
+ LSR storeRun,packRetIndex,#7 ;// Get Run Value from Packed index
+ AND storeLevel,packRetIndex,#0x7c ;// storeLevel=packRetIndex[2-6],storeLevel[0-1]=0
+
+
+ M_LDR pLMAXTableL0L1,ppLMAXTableL0L1 ;// Load LMAX table
+
+
+ LSR storeLevel,storeLevel,#2 ;// Level value
+
+ CMP ftype,#1
+ BNE ftype2
+
+ ;// ftype==1; Escape mode =1
+
+
+ ADD temp1, pLMAXTableL0L1, Last, LSL#4 ;// If the Last=1 add 32 to table address
+ LDRB temp1,[temp1,storeRun]
+
+
+ ADD storeLevel,temp1,storeLevel
+
+ftype2
+
+ ;// ftype =2; Escape mode =2
+
+ M_LDR pRMAXTableL0L1,ppRMAXTableL0L1 ;// Load RMAX Table
+
+ CMP ftype,#2
+ BNE FillVLDL1
+
+ ADD temp1, pRMAXTableL0L1, Last, LSL#4 ;// If Last=1 add 32 to table address
+ SUB temp2,storeLevel,#1
+ LDRB temp1,[temp1,temp2]
+
+
+ ADD storeRun,storeRun,#1
+ ADD storeRun,temp1
+
+FillVLDL1
+
+
+ ;// armVCM4P2_FillVLDBuffer
+
+ M_LDR pZigzagTable,ppZigzagTable ;// Load address of zigzagTable
+
+ M_BD_READ8 sign,1,T1
+
+ CMP sign,#1
+ RSBEQ storeLevel,storeLevel,#0
+
+ ADD temp1,storeRun,Count ;// Exit with an error message if Run + Count exceeds 63
+ CMP temp1,#64
+ BGE ExitError
+
+
+
+
+
+
+ ;// To Reflect Runlenght
+
+ ADD Count,Count,storeRun
+
+storeLevelL1
+
+ LDRB zigzag,[pZigzagTable,Count]
+ CMP Last,#2 ;// Check if the Level val is Last non zero val
+ ADD Count,Count,#1
+ LSR Last,Last,#1
+ STRH storeLevel,[pDst,zigzag]
+
+ BNE end
+
+ B ExitOk
+
+
+
+ ;// Fixed Lengh Decoding Escape Mode 3
+
+EscapeMode3
+
+ M_BD_READ8 Last,1,T1
+ M_BD_READ8 storeRun,6,T1
+
+ ADD temp2,storeRun,Count ;// Exit with an error message if Run + Count exceeds 63
+ CMP temp2,#64
+ BGE ExitError
+
+ M_BD_READ8 markerbit,1,T1
+ TEQ markerbit,#0 ;// Exit with an error message if marker bit is zero
+ BEQ ExitError
+
+ M_BD_READ16 storeLevel,12,T1
+
+ TST storeLevel,#0x800 ;// test if the level is negative
+ SUBNE storeLevel,storeLevel,#4096
+ CMP storeLevel,#0
+ CMPNE storeLevel,#-2048
+ BEQ ExitError ;// Exit with an error message if Level==0 or -2048
+
+ M_LDR pZigzagTable,ppZigzagTable ;// Load address of zigzagTable
+
+ M_BD_READ8 markerbit,1,T1
+
+
+ ;// armVCM4P2_FillVLDBuffer ( Sign not used as storeLevel is preprocessed)
+
+
+
+ ;// To Reflect Run Length
+
+ ADD Count,Count,storeRun
+
+
+
+storeLevelLast
+
+ LDRB zigzag,[pZigzagTable,Count]
+ CMP Last,#1
+ ADD Count,Count,#1
+ STRH storeLevel,[pDst,zigzag]
+
+ BNE end
+
+ B ExitOk
+
+end
+
+ CMP Count,#64 ;//Run the Loop untill Count reaches 64
+
+ BLT getVLCbits
+
+
+ExitOk
+ ;// Exit When VLC Decoding is done Successfully
+
+ ;// Loading ppBitStream and pBitOffset from stack
+
+ CMP Last,#1
+ M_LDR ppBitStream,pppBitStream
+ M_LDR pBitOffset,ppOffset
+
+ ;//Ending the macro
+
+ M_BD_FINI ppBitStream,pBitOffset
+
+ MOVEQ Return,#OMX_Sts_NoErr
+ MOVNE Return,#OMX_Sts_Err
+ M_LDR LR,pLinkRegister ;// Load the Link Register Back
+ B exit2
+
+ExitError
+ ;// Exit When an Error occurs
+
+ M_LDR ppBitStream,pppBitStream
+ M_LDR pBitOffset,ppOffset
+ ;//Ending the macro
+
+ M_BD_FINI ppBitStream,pBitOffset
+ M_LDR LR,pLinkRegister
+ MOV Return,#OMX_Sts_Err
+
+exit2
+
+
+ M_END
+ ENDIF
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
new file mode 100644
index 0000000..ba4d058
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
@@ -0,0 +1,211 @@
+ /**
+ *
+ * File Name: armVCM4P2_Huff_Tables_VLC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armVCM4P2_Huff_Tables_VLC.c
+ * Description: Contains all the Huffman tables used in MPEG4 codec
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armCOMM_Bitstream.h"
+
+
+
+
+// Contains optimized and Packed VLC tables with Last=0 and Last=1
+
+// optimized Packed VLC table Entry Format
+// ---------------------------------------
+//
+// 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+// +------------------------------------------------+
+// | Len | Run | Level |L | 1 |
+// +------------------------------------------------+
+// | Offset | 0 |
+// +------------------------------------------------+
+// If the table entry is a leaf entry then bit 0 set:
+// Len = Number of bits overread (0 to 7) 3 bits
+// Run = RunLength of the Symbol (0 to 63) 6 bits
+// Level = Level of the Symbol (0 to 31) 5 bits
+// L = Last Value of the Symbol (0 or 1) 1 bit
+//
+// If the table entry is an internal node then bit 0 is clear:
+// Offset = Number of (16-bit) half words from the table
+// start to the next table node
+//
+// The table is accessed by successive lookup up on the
+// next Step bits of the input bitstream until a leaf node
+// is obtained. The Step sizes are supplied to the VLD macro.
+
+// The VLC tables used for Intra and non inta coefficients in non Escape mode
+// contains symbols with both Last=0 and Last=1.
+// If a symbol is not found in the table it will be coded as 0xFFF
+
+
+const OMX_U16 armVCM4P2_InterVlcL0L1[200] = {
+ 0x0020, 0x0108, 0x0148, 0x0170, 0x0178, 0x0180, 0x0188, 0x1b09,
+ 0x4009, 0x4009, 0x4009, 0x4009, 0x2109, 0x2109, 0x0209, 0x0011,
+ 0x0028, 0x0060, 0x00b8, 0x00e0, 0x0030, 0x0048, 0x0050, 0x0058,
+ 0x3fff, 0x3fff, 0x0038, 0x0040, 0x2115, 0x2115, 0x201d, 0x201d,
+ 0x2059, 0x2059, 0x2051, 0x2051, 0x1c0d, 0x1b0d, 0x1a0d, 0x190d,
+ 0x0911, 0x0811, 0x0711, 0x0611, 0x0511, 0x0319, 0x0219, 0x0121,
+ 0x0068, 0x0090, 0x3fff, 0x3fff, 0x0070, 0x0078, 0x0080, 0x0088,
+ 0x2061, 0x2061, 0x2129, 0x2129, 0x3709, 0x3709, 0x3809, 0x3809,
+ 0x3d0d, 0x3d0d, 0x3e0d, 0x3e0d, 0x3f0d, 0x3f0d, 0x200d, 0x200d,
+ 0x0098, 0x00a0, 0x00a8, 0x00b0, 0x0131, 0x0221, 0x0419, 0x0519,
+ 0x0619, 0x0a11, 0x1909, 0x1a09, 0x210d, 0x220d, 0x230d, 0x240d,
+ 0x250d, 0x260d, 0x270d, 0x280d, 0x00c0, 0x00c8, 0x00d0, 0x00d8,
+ 0x0049, 0x0041, 0x380d, 0x380d, 0x370d, 0x370d, 0x360d, 0x360d,
+ 0x350d, 0x350d, 0x340d, 0x340d, 0x330d, 0x330d, 0x320d, 0x320d,
+ 0x00e8, 0x00f0, 0x00f8, 0x0100, 0x310d, 0x310d, 0x2015, 0x2015,
+ 0x3609, 0x3609, 0x3509, 0x3509, 0x3409, 0x3409, 0x3309, 0x3309,
+ 0x3209, 0x3209, 0x3109, 0x3109, 0x0110, 0x0130, 0x0138, 0x0140,
+ 0x0118, 0x0120, 0x0128, 0x100d, 0x3009, 0x3009, 0x2f09, 0x2f09,
+ 0x2411, 0x2411, 0x2311, 0x2311, 0x2039, 0x2039, 0x2031, 0x2031,
+ 0x0f0d, 0x0e0d, 0x0d0d, 0x0c0d, 0x0b0d, 0x0a0d, 0x090d, 0x0e09,
+ 0x0d09, 0x0211, 0x0119, 0x0029, 0x0150, 0x0158, 0x0160, 0x0168,
+ 0x280d, 0x280d, 0x270d, 0x270d, 0x260d, 0x260d, 0x250d, 0x250d,
+ 0x2c09, 0x2c09, 0xb759, 0xb759, 0x2a09, 0x2a09, 0x2021, 0x2021,
+ 0x040d, 0x030d, 0x0b35, 0x010d, 0x0909, 0x0809, 0x0709, 0x0609,
+ 0x0111, 0x0019, 0x2509, 0x2509, 0x2409, 0x2409, 0x2309, 0x2309
+};
+
+
+const OMX_U16 armVCM4P2_IntraVlcL0L1[200] = {
+ 0x0020, 0x0108, 0x0148, 0x0170, 0x0178, 0x0180, 0x0188, 0x0f09,
+ 0x4009, 0x4009, 0x4009, 0x4009, 0x2011, 0x2011, 0x0109, 0x0019,
+ 0x0028, 0x0060, 0x00b8, 0x00e0, 0x0030, 0x0048, 0x0050, 0x0058,
+ 0x3fff, 0x3fff, 0x0038, 0x0040, 0x203d, 0x203d, 0x2035, 0x2035,
+ 0x20b1, 0x20b1, 0x20a9, 0x20a9, 0x0215, 0x011d, 0x002d, 0x0d09,
+ 0x0519, 0x0811, 0x0419, 0x0321, 0x0221, 0x0139, 0x00a1, 0x0099,
+ 0x0068, 0x0090, 0x3fff, 0x3fff, 0x0070, 0x0078, 0x0080, 0x0088,
+ 0x20b9, 0x20b9, 0x20c1, 0x20c1, 0x2141, 0x2141, 0x2911, 0x2911,
+ 0x2315, 0x2315, 0x2415, 0x2415, 0x2f0d, 0x2f0d, 0x300d, 0x300d,
+ 0x0098, 0x00a0, 0x00a8, 0x00b0, 0x00c9, 0x00d1, 0x00d9, 0x0149,
+ 0x0619, 0x0151, 0x0229, 0x0719, 0x0e09, 0x0045, 0x0515, 0x0615,
+ 0x110d, 0x120d, 0x130d, 0x140d, 0x00c0, 0x00c8, 0x00d0, 0x00d8,
+ 0x0091, 0x0089, 0x2e0d, 0x2e0d, 0x2d0d, 0x2d0d, 0x2c0d, 0x2c0d,
+ 0x2b0d, 0x2b0d, 0x2a0d, 0x2a0d, 0x2115, 0x2115, 0x2025, 0x2025,
+ 0x00e8, 0x00f0, 0x00f8, 0x0100, 0x2c09, 0x2c09, 0x2b09, 0x2b09,
+ 0x2711, 0x2711, 0x2611, 0x2611, 0x2511, 0x2511, 0x2319, 0x2319,
+ 0x2219, 0x2219, 0x2131, 0x2131, 0x0110, 0x0130, 0x0138, 0x0140,
+ 0x0118, 0x0120, 0x0128, 0x080d, 0x2129, 0x2129, 0x2081, 0x2081,
+ 0x2411, 0x2411, 0x2079, 0x2079, 0x2071, 0x2071, 0x2069, 0x2069,
+ 0x1bb5, 0x060d, 0x001d, 0xd3f9, 0x0909, 0x0809, 0x090d, 0x0311,
+ 0x0121, 0x0061, 0x0059, 0x0051, 0x0150, 0x0158, 0x0160, 0x0168,
+ 0x240d, 0x240d, 0x230d, 0x230d, 0x2609, 0x2609, 0x250d, 0x250d,
+ 0x2709, 0x2709, 0x2211, 0x2211, 0x2119, 0x2119, 0x2049, 0x2049,
+ 0x0015, 0x0509, 0x020d, 0x010d, 0x0409, 0x0309, 0x0041, 0x0039,
+ 0x0111, 0x0031, 0x2209, 0x2209, 0x2029, 0x2029, 0x2021, 0x2021
+};
+
+const OMX_U16 armVCM4P2_aIntraDCLumaChromaIndex[64] = {
+ 0x0020, 0x000b, 0x2009, 0x2009, 0x2007, 0x2007, 0x2001, 0x2001,
+ 0x4005, 0x4005, 0x4005, 0x4005, 0x4003, 0x4003, 0x4003, 0x4003,
+ 0x0028, 0x000f, 0x200d, 0x200d, 0x0030, 0x0013, 0x2011, 0x2011,
+ 0x0038, 0x0017, 0x2015, 0x2015, 0x3fff, 0x3fff, 0x2019, 0x2019,
+
+ 0x0020, 0x0009, 0x2007, 0x2007, 0x4005, 0x4005, 0x4005, 0x4005,
+ 0x4003, 0x4003, 0x4003, 0x4003, 0x4001, 0x4001, 0x4001, 0x4001,
+ 0x0028, 0x000d, 0x200b, 0x200b, 0x0030, 0x0011, 0x200f, 0x200f,
+ 0x0038, 0x0015, 0x2013, 0x2013, 0x1fff, 0x0019, 0x2017, 0x2017
+};
+
+
+const OMX_U16 armVCM4P2_aVlcMVD[124] = {
+ 0x0010, 0x00f0, 0x0043, 0x003f, 0x4041, 0x4041, 0x4041, 0x4041,
+ 0x0018, 0x00d8, 0x0047, 0x003b, 0x0020, 0x0080, 0x00a8, 0x00d0,
+ 0x0028, 0x0048, 0x0070, 0x0078, 0x1fff, 0x0030, 0x0038, 0x0040,
+ 0x0081, 0x0001, 0x007f, 0x0003, 0x207d, 0x207d, 0x2005, 0x2005,
+ 0x207b, 0x207b, 0x2007, 0x2007, 0x0050, 0x0058, 0x0060, 0x0068,
+ 0x2079, 0x2079, 0x2009, 0x2009, 0x2077, 0x2077, 0x200b, 0x200b,
+ 0x2075, 0x2075, 0x200d, 0x200d, 0x2073, 0x2073, 0x200f, 0x200f,
+ 0x0071, 0x0011, 0x006f, 0x0013, 0x006d, 0x0015, 0x006b, 0x0017,
+ 0x0088, 0x0090, 0x0098, 0x00a0, 0x0069, 0x0019, 0x0067, 0x001b,
+ 0x0065, 0x001d, 0x0063, 0x001f, 0x0061, 0x0021, 0x005f, 0x0023,
+ 0x005d, 0x0025, 0x005b, 0x0027, 0x00b0, 0x00b8, 0x00c0, 0x00c8,
+ 0x0059, 0x0029, 0x0057, 0x002b, 0x2055, 0x2055, 0x202d, 0x202d,
+ 0x2053, 0x2053, 0x202f, 0x202f, 0x2051, 0x2051, 0x2031, 0x2031,
+ 0x204f, 0x204f, 0x2033, 0x2033, 0x00e0, 0x00e8, 0x0049, 0x0039,
+ 0x204d, 0x204d, 0x2035, 0x2035, 0x204b, 0x204b, 0x2037, 0x2037,
+ 0x2045, 0x2045, 0x203d, 0x203d
+};
+
+/* LMAX table for non Inter (Last == 0 and Last=1)
+ Level - 1 Indexed
+ padded armVCM4P2_InterL0L1LMAX[27-31] with zeros to acess entries for Last=1 effectively
+
+*/
+const OMX_U8 armVCM4P2_InterL0L1LMAX[73] =
+{
+ 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,
+ 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
+};
+
+/* RMAX table for non Inter (Last == 0 and Last=1)
+ Level - 1 Indexed
+ padded armVCM4P2_InterL0L1RMAX[12-31] with zeros to access entries for Last=1 table effectively */
+
+
+const OMX_U8 armVCM4P2_InterL0L1RMAX[35] =
+{
+ 26, 10, 6, 2, 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, 40, 1, 0
+};
+
+/* LMAX table for non Intra (Last == 0 and Last=1)
+ Level - 1 Indexed
+ padded armVCM4P2_IntraL0L1LMAX[15-31] with zeros to acess entries for Last=1 effectively
+
+*/
+const OMX_U8 armVCM4P2_IntraL0L1LMAX[53] =
+{
+ 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,
+
+ 8, 3, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+};
+
+
+/* RMAX table for non Inter (Last == 0 and Last=1)
+ Level - 1 Indexed
+ padded armVCM4P2_IntraL0L1RMAX[27-31] with zeros to access entries for Last=1 table effectively */
+
+
+const OMX_U8 armVCM4P2_IntraL0L1RMAX[40] =
+{
+ 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, 0,
+ 0, 0, 0, 0,
+
+ 20, 6, 1, 0, 0, 0, 0, 0
+
+};
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Lookup_Tables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Lookup_Tables.c
new file mode 100644
index 0000000..25cf8db
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Lookup_Tables.c
@@ -0,0 +1,75 @@
+ /**
+ *
+ * File Name: armVCM4P2_Lookup_Tables.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armVCM4P2_Lookup_Tables.c
+ * Description: Contains all the Lookup tables used in MPEG4 codec
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+ /* * Table Entries contain Dc Scaler values
+ * armVCM4P2_DCScaler[i]= 8 for i=1 to 4 and i=33 to 36
+ * = 2*i for i=5 to 8
+ * = i+8 for i=9 to 25
+ * = 2*i-16 for i=26 to 31
+ * = (i-32+13)/2 for i=37 to 59
+ * = i-6-32 for i=60 to 63
+ * = 255 for i=0 and i=32
+ */
+
+const OMX_U8 armVCM4P2_DCScaler[64]={
+ 0xff, 0x8, 0x8, 0x8, 0x8, 0xa, 0xc, 0xe,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e,
+ 0xff, 0x8, 0x8, 0x8, 0x8, 0x9, 0x9, 0xa,
+ 0xa, 0xb, 0xb, 0xc, 0xc, 0xd, 0xd, 0xe,
+ 0xe, 0xf, 0xf, 0x10, 0x10, 0x11, 0x11, 0x12,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+
+};
+
+
+ /* Table Entries Contain reciprocal of 1 to 63
+ * armVCM4P2_Reciprocal_QP_S16[i]=round(32767/i)
+ * armVCM4P2_Reciprocal_QP_S16[0]= 0
+ */
+
+const OMX_S16 armVCM4P2_Reciprocal_QP_S16[64]={
+ 0x0000,0x7fff,0x4000,0x2aaa,0x2000,0x1999,0x1555,0x1249,
+ 0x1000,0x0e39,0x0ccd,0x0ba3,0x0aab,0x09d9,0x0925,0x0888,
+ 0x0800,0x0787,0x071c,0x06bd,0x0666,0x0618,0x05d1,0x0591,
+ 0x0555,0x051f,0x04ec,0x04be,0x0492,0x046a,0x0444,0x0421,
+ 0x0400,0x03e1,0x03c4,0x03a8,0x038e,0x0376,0x035e,0x0348,
+ 0x0333,0x031f,0x030c,0x02fa,0x02e9,0x02d8,0x02c8,0x02b9,
+ 0x02ab,0x029d,0x028f,0x0282,0x0276,0x026a,0x025f,0x0254,
+ 0x0249,0x023f,0x0235,0x022b,0x0222,0x0219,0x0211,0x0208
+
+};
+
+ /* Table Entries Contain reciprocal of 1 to 63
+ * armVCM4P2_Reciprocal_QP_S32[i]=round(131071/i)
+ * armVCM4P2_Reciprocal_QP_S32[0]= 0
+ */
+
+const OMX_S32 armVCM4P2_Reciprocal_QP_S32[64]={
+ 0x00000000,0x0001ffff,0x00010000,0x0000aaaa, 0x00008000, 0x00006666, 0x00005555, 0x00004924,
+ 0x00004000,0x000038e3,0x00003333,0x00002e8c, 0x00002aab, 0x00002762, 0x00002492, 0x00002222,
+ 0x00002000,0x00001e1e,0x00001c72,0x00001af2, 0x0000199a, 0x00001861, 0x00001746, 0x00001643,
+ 0x00001555,0x0000147b,0x000013b1,0x000012f6, 0x00001249, 0x000011a8, 0x00001111, 0x00001084,
+ 0x00001000,0x00000f84,0x00000f0f,0x00000ea1, 0x00000e39, 0x00000dd6, 0x00000d79, 0x00000d21,
+ 0x00000ccd,0x00000c7d,0x00000c31,0x00000be8, 0x00000ba3, 0x00000b61, 0x00000b21, 0x00000ae5,
+ 0x00000aab,0x00000a73,0x00000a3d,0x00000a0a, 0x000009d9, 0x000009a9, 0x0000097b, 0x0000094f,
+ 0x00000925,0x000008fb,0x000008d4,0x000008ae, 0x00000889, 0x00000865, 0x00000842, 0x00000820
+
+};
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_SetPredDir_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_SetPredDir_s.s
new file mode 100644
index 0000000..3f92d85
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_SetPredDir_s.s
@@ -0,0 +1,104 @@
+;//
+;//
+;// File Name: armVCM4P2_SetPredDir_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+; **
+; * Function: armVCM4P2_SetPredDir
+; *
+; * Description:
+; * Performs detecting the prediction direction
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] blockIndex block index indicating the component type and
+; * position as defined in subclause 6.1.3.8, of ISO/IEC
+; * 14496-2. Furthermore, indexes 6 to 9 indicate the
+; * alpha blocks spatially corresponding to luminance
+; * blocks 0 to 3 in the same macroblock.
+; * [in] pCoefBufRow pointer to the coefficient row buffer
+; * [in] pQpBuf pointer to the quantization parameter buffer
+; * [out]predQP quantization parameter of the predictor block
+; * [out]predDir indicates the prediction direction which takes one
+; * of the following values:
+; * OMX_VC_HORIZONTAL predict horizontally
+; * OMX_VC_VERTICAL predict vertically
+; *
+; * Return Value:
+; * Standard OMXResult result. See enumeration for possible result codes.
+; *
+; */
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE omxVC_s.h
+
+
+ M_VARIANTS ARM1136JS
+
+
+ IF ARM1136JS
+
+;// Input Arguments
+BlockIndex RN 0
+pCoefBufRow RN 1
+pCoefBufCol RN 2
+predDir RN 3
+predQP RN 4
+pQpBuf RN 5
+
+;// Local Variables
+
+Return RN 0
+blockDCLeft RN 6
+blockDCTop RN 7
+blockDCTopLeft RN 8
+temp1 RN 9
+temp2 RN 14
+
+ M_START armVCM4P2_SetPredDir,r9
+
+ M_ARG ppredQP,4
+ M_ARG ppQpBuf,4
+
+ LDRH blockDCTopLeft,[pCoefBufRow,#-16]
+ LDRH blockDCLeft,[pCoefBufCol]
+
+ TEQ BlockIndex,#3
+ LDREQH blockDCTop,[pCoefBufCol,#-16]
+ LDRNEH blockDCTop,[pCoefBufRow]
+
+ SUBS temp1,blockDCLeft,blockDCTopLeft
+ RSBLT temp1,temp1,#0
+ SUBS temp2,blockDCTopLeft,blockDCTop
+ RSBLT temp2,temp2,#0
+
+ M_LDR pQpBuf,ppQpBuf
+ M_LDR predQP,ppredQP
+ CMP temp1,temp2
+ MOV temp2,#OMX_VC_VERTICAL
+ LDRLTB temp1,[pQpBuf,#1]
+ STRLT temp2,[predDir]
+ STRLT temp1,[predQP]
+ MOV temp2,#OMX_VC_HORIZONTAL
+ LDRGEB temp1,[pQpBuf]
+ STRGE temp2,[predDir]
+ MOV Return,#OMX_Sts_NoErr
+ STRGE temp1,[predQP]
+
+
+
+ M_END
+
+ ENDIF
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
new file mode 100644
index 0000000..ed17f9b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
@@ -0,0 +1,61 @@
+/**
+ *
+ * File Name: armVCM4P2_Zigzag_Tables.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armVCM4P2_ZigZag_Tables.c
+ * Description: Contains the zigzag tables
+ *
+ */
+
+#include "omxtypes.h"
+
+/* Contains Double the values in the reference Zigzag Table
+ * Contains Classical,Vetical and Horizontal Zigzagscan tables in one array
+ */
+
+const OMX_U8 armVCM4P2_aClassicalZigzagScan [192] =
+{
+ 0, 2, 16, 32, 18, 4, 6, 20,
+ 34, 48, 64, 50, 36, 22, 8, 10,
+ 24, 38, 52, 66, 80, 96, 82, 68,
+ 54, 40, 26, 12, 14, 28, 42, 56,
+ 70, 84, 98, 112, 114, 100, 86, 72,
+ 58, 44, 30, 46, 60, 74, 88, 102,
+ 116, 118, 104, 90, 76, 62, 78, 92,
+ 106, 120, 122, 104, 94, 110, 124, 126,
+
+ 0, 16, 32, 48, 2, 18, 4, 20,
+ 34, 50, 64, 80, 96, 112, 114, 98,
+ 82, 66, 52, 36, 6, 22, 8, 24,
+ 38, 54, 68, 84, 100, 116, 70, 86,
+ 102, 118, 40, 56, 10, 26, 12, 28,
+ 42, 58, 72, 88, 104, 120, 74, 90,
+ 106, 122, 44, 60, 14, 30, 46, 62,
+ 76, 92, 108, 124, 78, 94, 110, 126,
+
+ 0, 2, 4, 6, 16, 18, 32, 34,
+ 20, 22, 8, 10, 12, 14, 30, 28,
+ 26, 24, 38, 36, 48, 50, 64, 66,
+ 52, 54, 40, 42, 44, 46, 56, 58,
+ 60, 62, 68, 70, 80, 82, 96, 98,
+ 84, 86, 72, 74, 76, 78, 88, 90,
+ 92, 94, 100, 102, 112, 114, 116, 118,
+ 104, 106, 108, 110, 120, 122, 124, 126
+
+
+};
+
+
+
+
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
new file mode 100644
index 0000000..b63d295
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
@@ -0,0 +1,102 @@
+/**
+ *
+ * File Name: omxVCM4P2_DecodeBlockCoef_Inter.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for inter reconstruction
+ *
+ */
+
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+
+/**
+ * Function: omxVCM4P2_DecodeBlockCoef_Inter
+ *
+ * Description:
+ * Decodes the INTER block coefficients. Inverse quantization, inversely zigzag
+ * positioning and IDCT, with appropriate clipping on each step, are performed
+ * on the coefficients. The results (residuals) are placed in a contiguous array
+ * of 64 elements. For INTER block, the output buffer holds the residuals for
+ * further reconstruction.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream buffer. There is no boundary
+ * check for the bit stream buffer.
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * to by *ppBitStream. *pBitOffset is valid within
+ * [0-7]
+ * [in] QP quantization parameter
+ * [in] shortVideoHeader a flag indicating presence of short_video_header;
+ * shortVideoHeader==1 indicates using quantization method defined in short
+ * video header mode, and shortVideoHeader==0 indicates normail quantization method.
+ * [out] ppBitStream *ppBitStream is updated after the block is decoded, so that it points to the
+ * current byte in the bit stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the current bit position in the
+ * byte pointed by *ppBitStream
+ * [out] pDst pointer to the decoded residual buffer (a contiguous array of 64 elements of
+ * OMX_S16 data type). Must be 16-byte aligned.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - At least one of the following pointers is Null: ppBitStream, *ppBitStream, pBitOffset , pDst
+ * - At least one of the below case:
+ * - *pBitOffset exceeds [0,7], QP <= 0;
+ * - pDst not 16-byte aligned
+ * OMX_Sts_Err - status error
+ *
+ */
+OMXResult omxVCM4P2_DecodeBlockCoef_Inter(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_INT QP,
+ OMX_INT shortVideoHeader
+)
+{
+ /* 64 elements are needed but to align it to 16 bytes need
+ 15 more elements of padding */
+ OMX_S16 tempBuf[79];
+ OMX_S16 *pTempBuf1;
+ OMXResult errorCode;
+ /* Aligning the local buffers */
+ pTempBuf1 = armAlignTo16Bytes(tempBuf);
+
+
+ /* VLD and zigzag */
+ errorCode = omxVCM4P2_DecodeVLCZigzag_Inter(ppBitStream, pBitOffset,
+ pTempBuf1,shortVideoHeader);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Dequantization */
+ errorCode = omxVCM4P2_QuantInvInter_I(
+ pTempBuf1,
+ QP);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Inverse transform */
+ errorCode = omxVCM4P2_IDCT8x8blk(pTempBuf1, pDst);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
new file mode 100644
index 0000000..c609a60
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
@@ -0,0 +1,208 @@
+/**
+ *
+ * File Name: omxVCM4P2_DecodeBlockCoef_Intra.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for intra reconstruction
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P2_DecodeBlockCoef_Intra
+ *
+ * Description:
+ * Decodes the INTRA block coefficients. Inverse quantization, inversely zigzag
+ * positioning, and IDCT, with appropriate clipping on each step, are performed
+ * on the coefficients. The results are then placed in the output frame/plane on
+ * a pixel basis. For INTRA block, the output values are clipped to [0, 255] and
+ * written to corresponding block buffer within the destination plane.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream buffer. There is no boundary
+ * check for the bit stream buffer.
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * to by *ppBitStream. *pBitOffset is valid within
+ * [0-7].
+ * [in] step width of the destination plane
+ * [in/out] pCoefBufRow [in] pointer to the coefficient row buffer
+ * [out] updated coefficient rwo buffer
+ * [in/out] pCoefBufCol [in] pointer to the coefficient column buffer
+ * [out] updated coefficient column buffer
+ * [in] curQP quantization parameter of the macroblock which
+ * the current block belongs to
+ * [in] pQpBuf Pointer to a 2-element QP array. pQpBuf[0] holds the QP of the 8x8 block left to
+ * the current block(QPa). pQpBuf[1] holds the QP of the 8x8 block just above the
+ * current block(QPc).
+ * Note, in case the corresponding block is out of VOP bound, the QP value will have
+ * no effect to the intra-prediction process. Refer to subclause "7.4.3.3 Adaptive
+ * ac coefficient prediction" of ISO/IEC 14496-2(MPEG4 Part2) for accurate description.
+ * [in] blockIndex block index indicating the component type and
+ * position as defined in subclause 6.1.3.8,
+ * Figure 6-5 of ISO/IEC 14496-2.
+ * [in] intraDCVLC a code determined by intra_dc_vlc_thr and QP.
+ * This allows a mechanism to switch between two VLC
+ * for coding of Intra DC coefficients as per Table
+ * 6-21 of ISO/IEC 14496-2.
+ * [in] ACPredFlag a flag equal to ac_pred_flag (of luminance) indicating
+ * if the ac coefficients of the first row or first
+ * column are differentially coded for intra coded
+ * macroblock.
+ * [in] shortVideoHeader a flag indicating presence of short_video_header;
+ * shortVideoHeader==1 selects linear intra DC mode,
+ * and shortVideoHeader==0 selects nonlinear intra DC mode.
+ * [out] ppBitStream *ppBitStream is updated after the block is
+ * decoded, so that it points to the current byte
+ * in the bit stream buffer
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream
+ * [out] pDst pointer to the block in the destination plane.
+ * pDst should be 16-byte aligned.
+ * [out] pCoefBufRow pointer to the updated coefficient row buffer.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - At least one of the following pointers is NULL: ppBitStream, *ppBitStream, pBitOffset,
+ * pCoefBufRow, pCoefBufCol, pQPBuf, pDst.
+ * or
+ * - At least one of the below case: *pBitOffset exceeds [0,7], curQP exceeds (1, 31),
+ * blockIndex exceeds [0,9], step is not the multiple of 8, intraDCVLC is zero while
+ * blockIndex greater than 5.
+ * or
+ * - pDst is not 16-byte aligned
+ * OMX_Sts_Err - status error
+ *
+ */
+
+OMXResult omxVCM4P2_DecodeBlockCoef_Intra(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_U8 *pDst,
+ OMX_INT step,
+ OMX_S16 *pCoefBufRow,
+ OMX_S16 *pCoefBufCol,
+ OMX_U8 curQP,
+ const OMX_U8 *pQPBuf,
+ OMX_INT blockIndex,
+ OMX_INT intraDCVLC,
+ OMX_INT ACPredFlag,
+ OMX_INT shortVideoHeader
+ )
+{
+ OMX_S16 tempBuf1[79], tempBuf2[79];
+ OMX_S16 *pTempBuf1, *pTempBuf2;
+ OMX_INT predDir, predACDir;
+ OMX_INT predQP;
+ OMXVCM4P2VideoComponent videoComp;
+ OMXResult errorCode;
+
+
+ /* Aligning the local buffers */
+ pTempBuf1 = armAlignTo16Bytes(tempBuf1);
+ pTempBuf2 = armAlignTo16Bytes(tempBuf2);
+
+ /* Setting the AC prediction direction and prediction direction */
+ armVCM4P2_SetPredDir(
+ blockIndex,
+ pCoefBufRow,
+ pCoefBufCol,
+ &predDir,
+ &predQP,
+ pQPBuf);
+
+ predACDir = predDir;
+
+
+ if (ACPredFlag == 0)
+ {
+ predACDir = OMX_VC_NONE;
+ }
+
+ /* Setting the videoComp */
+ if (blockIndex <= 3)
+ {
+ videoComp = OMX_VC_LUMINANCE;
+ }
+ else
+ {
+ videoComp = OMX_VC_CHROMINANCE;
+ }
+
+
+ /* VLD and zigzag */
+ if (intraDCVLC == 1)
+ {
+ errorCode = omxVCM4P2_DecodeVLCZigzag_IntraDCVLC(
+ ppBitStream,
+ pBitOffset,
+ pTempBuf1,
+ predACDir,
+ shortVideoHeader,
+ videoComp);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+ }
+ else
+ {
+ errorCode = omxVCM4P2_DecodeVLCZigzag_IntraACVLC(
+ ppBitStream,
+ pBitOffset,
+ pTempBuf1,
+ predACDir,
+ shortVideoHeader);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+ }
+
+ /* AC DC prediction */
+ errorCode = omxVCM4P2_PredictReconCoefIntra(
+ pTempBuf1,
+ pCoefBufRow,
+ pCoefBufCol,
+ curQP,
+ predQP,
+ predDir,
+ ACPredFlag,
+ videoComp);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Dequantization */
+ errorCode = omxVCM4P2_QuantInvIntra_I(
+ pTempBuf1,
+ curQP,
+ videoComp,
+ shortVideoHeader);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Inverse transform */
+ errorCode = omxVCM4P2_IDCT8x8blk (pTempBuf1, pTempBuf2);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Placing the linear array into the destination plane and clipping
+ it to 0 to 255 */
+
+ armVCM4P2_Clip8(pTempBuf2,pDst,step);
+
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
new file mode 100644
index 0000000..a1861da
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
@@ -0,0 +1,364 @@
+; **********
+; *
+; * File Name: omxVCM4P2_DecodePadMV_PVOP_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 9641
+; * Date: Thursday, February 7, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; **
+; * Function: omxVCM4P2_DecodePadMV_PVOP
+; *
+; * Description:
+; * Decodes and pads four motion vectors of the non-intra macroblock in P-VOP.
+; * The motion vector padding process is specified in subclause 7.6.1.6 of
+; * ISO/IEC 14496-2.
+; *
+; * Remarks:
+; *
+; *
+; * Parameters:
+; * [in] ppBitStream pointer to the pointer to the current byte in
+; * the bit stream buffer
+; * [in] pBitOffset pointer to the bit position in the byte pointed
+; * to by *ppBitStream. *pBitOffset is valid within
+; * [0-7].
+; * [in] pSrcMVLeftMB pointers to the motion vector buffers of the
+; * macroblocks specially at the left side of the current macroblock
+; * respectively.
+; * [in] pSrcMVUpperMB pointers to the motion vector buffers of the
+; * macroblocks specially at the upper side of the current macroblock
+; * respectively.
+; * [in] pSrcMVUpperRightMB pointers to the motion vector buffers of the
+; * macroblocks specially at the upper-right side of the current macroblock
+; * respectively.
+; * [in] fcodeForward a code equal to vop_fcode_forward in MPEG-4
+; * bit stream syntax
+; * [in] MBType the type of the current macroblock. If MBType
+; * is not equal to OMX_VC_INTER4V, the destination
+; * motion vector buffer is still filled with the
+; * same decoded vector.
+; * [out] ppBitStream *ppBitStream is updated after the block is decoded,
+; * so that it points to the current byte in the bit
+; * stream buffer
+; * [out] pBitOffset *pBitOffset is updated so that it points to the
+; * current bit position in the byte pointed by
+; * *ppBitStream
+; * [out] pDstMVCurMB pointer to the motion vector buffer of the current
+; * macroblock which contains four decoded motion vectors
+; *
+; * Return Value:
+; * OMX_Sts_NoErr -no error
+; *
+; *
+; * OMX_Sts_Err - status error
+; *
+; *
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armCOMM_BitDec_s.h
+ INCLUDE omxVC_s.h
+
+ M_VARIANTS ARM1136JS
+
+
+
+
+ IF ARM1136JS
+
+;//Input Arguments
+
+ppBitStream RN 0
+pBitOffset RN 1
+pSrcMVLeftMB RN 2
+pSrcMVUpperMB RN 3
+pSrcMVUpperRightMB RN 4
+pDstMVCurMB RN 5
+fcodeForward RN 6
+MBType RN 7
+
+;//Local Variables
+
+zero RN 4
+one RN 4
+scaleFactor RN 1
+
+
+Return RN 0
+
+VlcMVD RN 0
+index RN 4
+Count RN 7
+
+mvHorData RN 4
+mvHorResidual RN 0
+
+mvVerData RN 4
+mvVerResidual RN 0
+
+temp RN 1
+
+temp1 RN 3
+High RN 4
+Low RN 2
+Range RN 1
+
+BlkCount RN 14
+
+diffMVdx RN 0
+diffMVdy RN 1
+
+;// Scratch Registers
+
+RBitStream RN 8
+RBitCount RN 9
+RBitBuffer RN 10
+
+T1 RN 11
+T2 RN 12
+LR RN 14
+
+ IMPORT armVCM4P2_aVlcMVD
+ IMPORT omxVCM4P2_FindMVpred
+
+ ;// Allocate stack memory
+
+ M_ALLOC4 ppDstMVCurMB,4
+ M_ALLOC4 pDstMVPredME,4
+ M_ALLOC4 pBlkCount,4
+
+ M_ALLOC4 pppBitStream,4
+ M_ALLOC4 ppBitOffset,4
+ M_ALLOC4 ppSrcMVLeftMB,4
+ M_ALLOC4 ppSrcMVUpperMB,4
+
+ M_ALLOC4 pdiffMVdx,4
+ M_ALLOC4 pdiffMVdy,4
+ M_ALLOC4 pHigh,4
+
+
+
+
+ M_START omxVCM4P2_DecodePadMV_PVOP,r11
+
+ M_ARG pSrcMVUpperRightMBonStack,4 ;// pointer to pSrcMVUpperRightMB on stack
+ M_ARG pDstMVCurMBonStack,4 ;// pointer to pDstMVCurMB on stack
+ M_ARG fcodeForwardonStack,4 ;// pointer to fcodeForward on stack
+ M_ARG MBTypeonStack,4 ;// pointer to MBType on stack
+
+
+
+
+
+ ;// Initializing the BitStream Macro
+
+ M_BD_INIT0 ppBitStream, pBitOffset, RBitStream, RBitBuffer, RBitCount
+ M_LDR MBType,MBTypeonStack ;// Load MBType from stack
+ M_LDR pDstMVCurMB,pDstMVCurMBonStack ;// Load pDstMVCurMB from stack
+ MOV zero,#0
+
+ TEQ MBType,#OMX_VC_INTRA ;// Check if MBType=OMX_VC_INTRA
+ TEQNE MBType,#OMX_VC_INTRA_Q ;// check if MBType=OMX_VC_INTRA_Q
+ STREQ zero,[pDstMVCurMB]
+ M_BD_INIT1 T1, T2, T2
+ STREQ zero,[pDstMVCurMB,#4]
+ M_BD_INIT2 T1, T2, T2
+ STREQ zero,[pDstMVCurMB,#4]
+ MOVEQ Return,#OMX_Sts_NoErr
+ MOV BlkCount,#0
+ STREQ zero,[pDstMVCurMB,#4]
+
+ BEQ ExitOK
+
+ TEQ MBType,#OMX_VC_INTER4V ;// Check if MBType=OMX_VC_INTER4V
+ TEQNE MBType,#OMX_VC_INTER4V_Q ;// Check if MBType=OMX_VC_INTER4V_Q
+ MOVEQ Count,#4
+
+ TEQ MBType,#OMX_VC_INTER ;// Check if MBType=OMX_VC_INTER
+ TEQNE MBType,#OMX_VC_INTER_Q ;// Check if MBType=OMX_VC_INTER_Q
+ MOVEQ Count,#1
+
+ M_LDR fcodeForward,fcodeForwardonStack ;// Load fcodeForward from stack
+
+ ;// Storing the values temporarily on stack
+
+ M_STR ppBitStream,pppBitStream
+ M_STR pBitOffset,ppBitOffset
+
+
+ SUB temp,fcodeForward,#1 ;// temp=fcodeForward-1
+ MOV one,#1
+ M_STR pSrcMVLeftMB,ppSrcMVLeftMB
+ LSL scaleFactor,one,temp ;// scaleFactor=1<<(fcodeForward-1)
+ M_STR pSrcMVUpperMB,ppSrcMVUpperMB
+ LSL scaleFactor,scaleFactor,#5
+ M_STR scaleFactor,pHigh ;// [pHigh]=32*scaleFactor
+
+ ;// VLD Decoding
+
+
+Loop
+
+ LDR VlcMVD, =armVCM4P2_aVlcMVD ;// Load the optimized MVD VLC table
+
+ ;// Horizontal Data and Residual calculation
+
+ LDR temp,=0xFFF
+ M_BD_VLD index,T1,T2,VlcMVD,3,2 ;// variable lenght decoding using the macro
+
+ TEQ index,temp
+ BEQ ExitError ;// Exit with an Error Message if the decoded symbol is an invalied symbol
+
+ SUB mvHorData,index,#32 ;// mvHorData=index-32
+ MOV mvHorResidual,#1 ;// mvHorResidual=1
+ CMP fcodeForward,#1
+ TEQNE mvHorData,#0
+ MOVEQ diffMVdx,mvHorData ;// if scaleFactor=1(fcodeForward=1) or mvHorData=0 diffMVdx=mvHorData
+ BEQ VerticalData
+
+ SUB temp,fcodeForward,#1
+ M_BD_VREAD8 mvHorResidual,temp,T1,T2 ;// get mvHorResidual from bitstream if fcodeForward>1 and mvHorData!=0
+
+ CMP mvHorData,#0
+ RSBLT mvHorData,mvHorData,#0 ;// mvHorData=abs(mvHorData)
+ SUB mvHorResidual,mvHorResidual,fcodeForward
+ SMLABB diffMVdx,mvHorData,fcodeForward,mvHorResidual ;// diffMVdx=abs(mvHorData)*fcodeForward+mvHorResidual-fcodeForward
+ ADD diffMVdx,diffMVdx,#1
+ RSBLT diffMVdx,diffMVdx,#0
+
+ ;// Vertical Data and Residual calculation
+
+VerticalData
+
+ M_STR diffMVdx,pdiffMVdx ;// Store the diffMVdx on stack
+ LDR VlcMVD, =armVCM4P2_aVlcMVD ;// Loading the address of optimized VLC tables
+
+ LDR temp,=0xFFF
+ M_BD_VLD index,T1,T2,VlcMVD,3,2 ;// VLC decoding using the macro
+
+ TEQ index,temp
+ BEQ ExitError ;// Exit with an Error Message if an Invalied Symbol occurs
+
+ SUB mvVerData,index,#32 ;// mvVerData=index-32
+ MOV mvVerResidual,#1
+ CMP fcodeForward,#1
+ TEQNE mvVerData,#0
+ MOVEQ diffMVdy,mvVerData ;// diffMVdy = mvVerData if scaleFactor=1(fcodeForward=1) or mvVerData=0
+ BEQ FindMVPred
+
+ SUB temp,fcodeForward,#1
+ M_BD_VREAD8 mvVerResidual,temp,T1,T2 ;// Get mvVerResidual from bit stream if fcodeForward>1 and mnVerData!=0
+
+
+ CMP mvVerData,#0
+ RSBLT mvVerData,mvVerData,#0
+ SUB mvVerResidual,mvVerResidual,fcodeForward
+ SMLABB diffMVdy,mvVerData,fcodeForward,mvVerResidual ;// diffMVdy=abs(mvVerData)*fcodeForward+mvVerResidual-fcodeForward
+ ADD diffMVdy,diffMVdy,#1
+ RSBLT diffMVdy,diffMVdy,#0
+
+ ;//Calling the Function omxVCM4P2_FindMVpred
+
+FindMVPred
+
+ M_STR diffMVdy,pdiffMVdy
+ ADD temp,pDstMVCurMB,BlkCount,LSL #2 ;// temp=pDstMVCurMB[BlkCount]
+ M_STR temp,ppDstMVCurMB ;// store temp on stack for passing as an argument to FindMVPred
+
+ MOV temp,#0
+ M_STR temp,pDstMVPredME ;// Pass pDstMVPredME=NULL as an argument
+ M_STR BlkCount,pBlkCount ;// Passs BlkCount as Argument through stack
+
+ MOV temp,pSrcMVLeftMB ;// temp (RN 1)=pSrcMVLeftMB
+ M_LDR pSrcMVUpperRightMB,pSrcMVUpperRightMBonStack
+ MOV pSrcMVLeftMB,pSrcMVUpperMB ;// pSrcMVLeftMB ( RN 2) = pSrcMVUpperMB
+ MOV ppBitStream,pDstMVCurMB ;// ppBitStream ( RN 0) = pDstMVCurMB
+ MOV pSrcMVUpperMB,pSrcMVUpperRightMB ;// pSrcMVUpperMB( RN 3) = pSrcMVUpperRightMB
+ BL omxVCM4P2_FindMVpred ;// Branch to subroutine omxVCM4P2_FindMVpred
+
+ ;// Store Horizontal Motion Vector
+
+ M_LDR BlkCount,pBlkCount ;// Load BlkCount from stack
+ M_LDR High,pHigh ;// High=32*scaleFactor
+ LSL temp1,BlkCount,#2 ;// temp=BlkCount*4
+ M_LDR diffMVdx,pdiffMVdx ;// Laad diffMVdx
+
+ LDRSH temp,[pDstMVCurMB,temp1] ;// temp=pDstMVCurMB[BlkCount]
+
+
+ RSB Low,High,#0 ;// Low = -32*scaleFactor
+ ADD diffMVdx,temp,diffMVdx ;// diffMVdx=pDstMVCurMB[BlkCount]+diffMVdx
+ ADD Range,High,High ;// Range=64*ScaleFactor
+ SUB High,High,#1 ;// High= 32*scaleFactor-1
+
+ CMP diffMVdx,Low ;// If diffMVdx<Low
+ ADDLT diffMVdx,diffMVdx,Range ;// diffMVdx+=Range
+
+ CMP diffMVdx,High
+ SUBGT diffMVdx,diffMVdx,Range ;// If diffMVdx > High diffMVdx-=Range
+ STRH diffMVdx,[pDstMVCurMB,temp1]
+
+ ;// Store Vertical
+
+ ADD temp1,temp1,#2 ;// temp1=4*BlkCount+2
+ M_LDR diffMVdx,pdiffMVdy ;// Laad diffMVdy
+ LDRSH temp,[pDstMVCurMB,temp1] ;// temp=pDstMVCurMB[BlkCount].diffMVdy
+ ADD BlkCount,BlkCount,#1 ;// BlkCount=BlkCount+1
+ ADD diffMVdx,temp,diffMVdx
+ CMP diffMVdx,Low
+ ADDLT diffMVdx,diffMVdx,Range ;// If diffMVdy<Low diffMVdy+=Range
+ CMP diffMVdx,High
+ SUBGT diffMVdx,diffMVdx,Range ;// If diffMVdy > High diffMVdy-=Range
+ STRH diffMVdx,[pDstMVCurMB,temp1]
+
+ CMP BlkCount,Count
+ M_LDR pSrcMVLeftMB,ppSrcMVLeftMB
+ M_LDR pSrcMVUpperMB,ppSrcMVUpperMB
+
+ BLT Loop ;// If BlkCount<Count Continue the Loop
+
+
+ ;// If MBType=OMX_VC_INTER or MBtype=OMX_VC_INTER_Q copy pDstMVCurMB[0] to
+ ;// pDstMVCurMB[1], pDstMVCurMB[2], pDstMVCurMB[3]
+
+ M_LDR MBType,MBTypeonStack
+
+ TEQ MBType,#OMX_VC_INTER
+ TEQNE MBType,#OMX_VC_INTER_Q
+ LDREQ temp,[pDstMVCurMB]
+ M_LDR ppBitStream,pppBitStream
+ STREQ temp,[pDstMVCurMB,#4]
+
+ STREQ temp,[pDstMVCurMB,#8]
+ STREQ temp,[pDstMVCurMB,#12]
+
+
+ M_LDR pBitOffset,ppBitOffset
+ ;//Ending the macro
+ M_BD_FINI ppBitStream,pBitOffset ;// Finishing the Macro
+
+
+ MOV Return,#OMX_Sts_NoErr
+ B ExitOK
+
+ExitError
+
+ M_LDR ppBitStream,pppBitStream
+ M_LDR pBitOffset,ppBitOffset
+ ;//Ending the macro
+ M_BD_FINI ppBitStream,pBitOffset
+
+ MOV Return,#OMX_Sts_Err
+
+ExitOK
+
+ M_END
+ ENDIF
+ END
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
new file mode 100644
index 0000000..c43b253
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
@@ -0,0 +1,132 @@
+;/**
+; *
+; * File Name: omxVCM4P2_DecodeVLCZigzag_Inter_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 9641
+; * Date: Thursday, February 7, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains modules for zigzag scanning and VLC decoding
+; * for inter block.
+; *
+; *
+; *
+; * Function: omxVCM4P2_DecodeVLCZigzag_Inter
+; *
+; * Description:
+; * Performs VLC decoding and inverse zigzag scan for one inter coded block.
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] ppBitStream pointer to the pointer to the current byte in
+; * the bitstream buffer
+; * [in] pBitOffset pointer to the bit position in the byte pointed
+; * to by *ppBitStream. *pBitOffset is valid within [0-7].
+; * [in] shortVideoHeader binary flag indicating presence of short_video_header;
+; * escape modes 0-3 are used if shortVideoHeader==0,
+; * and escape mode 4 is used when shortVideoHeader==1.
+; * [out] ppBitStream *ppBitStream is updated after the block is
+; * decoded, so that it points to the current byte
+; * in the bit stream buffer
+; * [out] pBitOffset *pBitOffset is updated so that it points to the
+; * current bit position in the byte pointed by
+; * *ppBitStream
+; * [out] pDst pointer to the coefficient buffer of current
+; * block. Must be 16-byte aligned
+; *
+; * Return Value:
+; * OMX_Sts_BadArgErr - bad arguments
+; * -At least one of the following pointers is NULL: ppBitStream, *ppBitStream, pBitOffset, pDst, or
+; * -pDst is not 16-byte aligned, or
+; * -*pBitOffset exceeds [0,7].
+; * OMX_Sts_Err - status error
+; * -At least one mark bit is equal to zero
+; * -Encountered an illegal stream code that cannot be found in the VLC table
+; * -Encountered and illegal code in the VLC FLC table
+; * -The number of coefficients is greater than 64
+; *
+; */
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armCOMM_BitDec_s.h
+
+
+ M_VARIANTS ARM1136JS
+
+
+
+
+
+ IF ARM1136JS
+
+ ;// Import various tables needed for the function
+
+
+ IMPORT armVCM4P2_InterVlcL0L1 ;// Contains optimized and packed VLC Tables for both Last =1 and last=0
+ ;// Packed in Run:Level:Last format
+ IMPORT armVCM4P2_InterL0L1LMAX ;// Contains LMAX table entries with both Last=0 and Last=1
+ IMPORT armVCM4P2_InterL0L1RMAX ;// Contains RMAX table entries with both Last=0 and Last=1
+ IMPORT armVCM4P2_aClassicalZigzagScan ;// contains classical Zigzag table entries with double the original values
+ IMPORT armVCM4P2_DecodeVLCZigzag_AC_unsafe
+
+
+
+;//Input Arguments
+
+ppBitStream RN 0
+pBitOffset RN 1
+pDst RN 2
+shortVideoHeader RN 3
+
+;//Local Variables
+
+Return RN 0
+
+pVlcTableL0L1 RN 4
+pLMAXTableL0L1 RN 4
+pRMAXTableL0L1 RN 4
+pZigzagTable RN 4
+Count RN 6
+
+
+
+ ;// Allocate stack memory to store the VLC,Zigzag,LMAX and RMAX tables
+
+
+ M_ALLOC4 ppVlcTableL0L1,4
+ M_ALLOC4 ppLMAXTableL0L1,4
+ M_ALLOC4 ppRMAXTableL0L1,4
+ M_ALLOC4 ppZigzagTable,4
+
+
+ M_START omxVCM4P2_DecodeVLCZigzag_Inter,r12
+
+
+
+
+ LDR pZigzagTable, =armVCM4P2_aClassicalZigzagScan ;// Load zigzag table
+ M_STR pZigzagTable,ppZigzagTable ;// Store zigzag table on stack to pass as argument to unsafe function
+ LDR pVlcTableL0L1, =armVCM4P2_InterVlcL0L1 ;// Load optimized VLC table with both L=0 and L=1 entries
+ M_STR pVlcTableL0L1,ppVlcTableL0L1 ;// Store optimized VLC table address on stack
+ LDR pLMAXTableL0L1, =armVCM4P2_InterL0L1LMAX ;// Load Interleaved L=0 and L=1 LMAX Tables
+ M_STR pLMAXTableL0L1,ppLMAXTableL0L1 ;// Store LMAX table address on stack
+ LDR pRMAXTableL0L1, =armVCM4P2_InterL0L1RMAX ;// Load Interleaved L=0 and L=1 RMAX Tables
+ MOV Count,#0 ;// set start=0
+ M_STR pRMAXTableL0L1,ppRMAXTableL0L1 ;// store RMAX table address on stack
+
+
+ BL armVCM4P2_DecodeVLCZigzag_AC_unsafe ;// call Unsafe Function for VLC Zigzag Decoding
+
+
+
+ M_END
+ ENDIF
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
new file mode 100644
index 0000000..166729e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
@@ -0,0 +1,136 @@
+;/**
+; *
+; * File Name: omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 9641
+; * Date: Thursday, February 7, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains modules for zigzag scanning and VLC decoding
+; * for inter block.
+; *
+; *
+; *
+; * Function: omxVCM4P2_DecodeVLCZigzag_Inter
+; *
+; * Description:
+; * Performs VLC decoding and inverse zigzag scan for one intra coded block.
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] ppBitStream pointer to the pointer to the current byte in
+; * the bitstream buffer
+; * [in] pBitOffset pointer to the bit position in the byte pointed
+; * to by *ppBitStream. *pBitOffset is valid within [0-7].
+; * [in] shortVideoHeader binary flag indicating presence of short_video_header;
+; * escape modes 0-3 are used if shortVideoHeader==0,
+; * and escape mode 4 is used when shortVideoHeader==1.
+; * [out] ppBitStream *ppBitStream is updated after the block is
+; * decoded, so that it points to the current byte
+; * in the bit stream buffer
+; * [out] pBitOffset *pBitOffset is updated so that it points to the
+; * current bit position in the byte pointed by
+; * *ppBitStream
+; * [out] pDst pointer to the coefficient buffer of current
+; * block. Must be 16-byte aligned
+; *
+; * Return Value:
+; * OMX_Sts_BadArgErr - bad arguments
+; * -At least one of the following pointers is NULL: ppBitStream, *ppBitStream, pBitOffset, pDst, or
+; * -pDst is not 16-byte aligned, or
+; * -*pBitOffset exceeds [0,7].
+; * OMX_Sts_Err - status error
+; * -At least one mark bit is equal to zero
+; * -Encountered an illegal stream code that cannot be found in the VLC table
+; * -Encountered and illegal code in the VLC FLC table
+; * -The number of coefficients is greater than 64
+; *
+; */
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armCOMM_BitDec_s.h
+
+
+ M_VARIANTS ARM1136JS
+
+
+
+
+
+ IF ARM1136JS
+
+ ;// Import various tables needed for the function
+
+
+ IMPORT armVCM4P2_IntraVlcL0L1 ;// Contains optimized and packed VLC Tables for both Last =1 and last=0
+ ;// Packed in Run:Level:Last format
+ IMPORT armVCM4P2_IntraL0L1LMAX ;// Contains LMAX table entries with both Last=0 and Last=1
+ IMPORT armVCM4P2_IntraL0L1RMAX ;// Contains RMAX table entries with both Last=0 and Last=1
+ IMPORT armVCM4P2_aClassicalZigzagScan ;// contains classical Zigzag table entries with double the original values
+ IMPORT armVCM4P2_DecodeVLCZigzag_AC_unsafe
+
+;//Input Arguments
+
+ppBitStream RN 0
+pBitOffset RN 1
+pDst RN 2
+PredDir RN 3
+shortVideoHeader RN 3
+
+;//Local Variables
+
+Return RN 0
+
+pVlcTableL0L1 RN 4
+pLMAXTableL0L1 RN 4
+pRMAXTableL0L1 RN 4
+pZigzagTable RN 4
+Count RN 6
+
+
+
+ ;// Allocate stack memory to store optimized VLC,Zigzag, RMAX, LMAX Table Addresses
+
+ M_ALLOC4 ppVlcTableL0L1,4
+ M_ALLOC4 ppLMAXTableL0L1,4
+ M_ALLOC4 ppRMAXTableL0L1,4
+ M_ALLOC4 ppZigzagTable,4
+
+
+ M_START omxVCM4P2_DecodeVLCZigzag_IntraACVLC,r12
+
+ M_ARG shortVideoHeaderonStack,4 ;// pointer to Input Argument on stack
+
+ LDR pZigzagTable, =armVCM4P2_aClassicalZigzagScan ;// Load Address of the Zigzag table
+ ADD pZigzagTable, pZigzagTable, PredDir, LSL #6 ;// Loading Different type of zigzag tables based on PredDir
+
+ M_STR pZigzagTable,ppZigzagTable ;// Store Zigzag table address on stack
+ LDR pVlcTableL0L1, =armVCM4P2_IntraVlcL0L1 ;// Load optimized packed VLC Table with both L=0 and L=1 entries
+ M_STR pVlcTableL0L1,ppVlcTableL0L1 ;// Store VLC Table address on stack
+ LDR pLMAXTableL0L1, =armVCM4P2_IntraL0L1LMAX ;// Load LMAX Table
+ M_STR pLMAXTableL0L1,ppLMAXTableL0L1 ;// Store LMAX Table address on Stack
+ LDR pRMAXTableL0L1, =armVCM4P2_IntraL0L1RMAX ;// Load RMAX Table
+ MOV Count,#0 ;// Set Start=0
+
+ M_STR pRMAXTableL0L1,ppRMAXTableL0L1 ;// Store RMAX Table address on stack
+
+
+
+ M_LDR shortVideoHeader,shortVideoHeaderonStack ;// get the Input Argument from stack
+
+ BL armVCM4P2_DecodeVLCZigzag_AC_unsafe ;// Call Unsafe Function
+
+
+
+
+ M_END
+ ENDIF
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
new file mode 100644
index 0000000..d19cb13
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
@@ -0,0 +1,224 @@
+;/**
+; *
+; * File Name: omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 9641
+; * Date: Thursday, February 7, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains modules for zigzag scanning and VLC decoding
+; * for inter block.
+; *
+; *
+; *
+; * Function: omxVCM4P2_DecodeVLCZigzag_Inter
+; *
+; * Description:
+; * Performs VLC decoding and inverse zigzag scan for one intra coded block.
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] ppBitStream pointer to the pointer to the current byte in
+; * the bitstream buffer
+; * [in] pBitOffset pointer to the bit position in the byte pointed
+; * to by *ppBitStream. *pBitOffset is valid within [0-7].
+; * [in] shortVideoHeader binary flag indicating presence of short_video_header;
+; * escape modes 0-3 are used if shortVideoHeader==0,
+; * and escape mode 4 is used when shortVideoHeader==1.
+; * [out] ppBitStream *ppBitStream is updated after the block is
+; * decoded, so that it points to the current byte
+; * in the bit stream buffer
+; * [out] pBitOffset *pBitOffset is updated so that it points to the
+; * current bit position in the byte pointed by
+; * *ppBitStream
+; * [out] pDst pointer to the coefficient buffer of current
+; * block. Must be 16-byte aligned
+; *
+; * Return Value:
+; * OMX_Sts_BadArgErr - bad arguments
+; * -At least one of the following pointers is NULL: ppBitStream, *ppBitStream, pBitOffset, pDst, or
+; * -pDst is not 16-byte aligned, or
+; * -*pBitOffset exceeds [0,7].
+; * OMX_Sts_Err - status error
+; * -At least one mark bit is equal to zero
+; * -Encountered an illegal stream code that cannot be found in the VLC table
+; * -Encountered and illegal code in the VLC FLC table
+; * -The number of coefficients is greater than 64
+; *
+; */
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armCOMM_BitDec_s.h
+
+
+ M_VARIANTS ARM1136JS
+
+
+
+
+
+ IF ARM1136JS :LOR: CortexA8
+
+
+ ;// Import various tables needed for the function
+
+
+ IMPORT armVCM4P2_IntraVlcL0L1 ;// Contains optimized and packed VLC Tables for both Last =1 and last=0
+ ;// Packed in Run:Level:Last format
+ IMPORT armVCM4P2_IntraL0L1LMAX ;// Contains LMAX table entries with both Last=0 and Last=1
+ IMPORT armVCM4P2_IntraL0L1RMAX ;// Contains RMAX table entries with both Last=0 and Last=1
+ IMPORT armVCM4P2_aClassicalZigzagScan ;// contains CLassical, Horizontal, Vertical Zigzag table entries with double the original values
+ IMPORT armVCM4P2_aIntraDCLumaChromaIndex ;// Contains Optimized DCLuma and DCChroma Index table Entries
+
+
+ IMPORT armVCM4P2_DecodeVLCZigzag_AC_unsafe
+
+;//Input Arguments
+
+ppBitStream RN 0
+pBitOffset RN 1
+pDst RN 2
+PredDir RN 3
+shortVideoHeader RN 3
+videoComp RN 5
+;//Local Variables
+
+Return RN 0
+
+pDCLumaChromaIndex RN 4
+pDCChromaIndex RN 7
+pVlcTableL0L1 RN 4
+pLMAXTableL0L1 RN 4
+pRMAXTableL0L1 RN 4
+pZigzagTable RN 4
+Count RN 6
+DCValueSize RN 6
+powOfSize RN 7
+temp1 RN 5
+
+
+;// Scratch Registers
+
+RBitStream RN 8
+RBitBuffer RN 9
+RBitCount RN 10
+
+T1 RN 11
+T2 RN 12
+DCVal RN 14
+
+
+ ;// Allocate stack memory to store optimized VLC,Zigzag, RMAX, LMAX Table Addresses
+
+ M_ALLOC4 ppVlcTableL0L1,4
+ M_ALLOC4 ppLMAXTableL0L1,4
+ M_ALLOC4 ppRMAXTableL0L1,4
+ M_ALLOC4 ppZigzagTable,4
+ M_ALLOC4 pDCCoeff,4
+
+
+
+ M_START omxVCM4P2_DecodeVLCZigzag_IntraDCVLC,r12
+
+ M_ARG shortVideoHeaderonStack,4 ;// Pointer to argument on stack
+ M_ARG videoComponstack,4 ;// Pointer to argument on stack
+
+
+ ;// Decode DC Coefficient
+
+
+ LDR pDCLumaChromaIndex, =armVCM4P2_aIntraDCLumaChromaIndex ;// Load Optimized VLC Table for Luminance and Chrominance
+
+ ;// Initializing the Bitstream Macro
+
+ M_BD_INIT0 ppBitStream, pBitOffset, RBitStream, RBitBuffer, RBitCount
+ M_LDR videoComp,videoComponstack
+ M_BD_INIT1 T1, T2, T2
+ ADD pDCLumaChromaIndex,pDCLumaChromaIndex,videoComp, LSL #6
+ M_BD_INIT2 T1, T2, T2
+
+
+ M_BD_VLD DCValueSize,T1,T2,pDCLumaChromaIndex,4,2 ;// VLC Decode using optimized Luminance and Chrominance VLC Table
+
+
+
+
+DecodeDC
+
+ CMP DCValueSize,#12
+ BGT ExitError
+
+ CMP DCValueSize,#0
+ MOVEQ DCVal,#0 ;// If DCValueSize is zero then DC coeff =0
+ BEQ ACDecode ;// Branch to perform AC Coeff Decoding
+
+ M_BD_VREAD16 DCVal,DCValueSize,T1,T2 ;// Get DC Value From Bit stream
+
+
+ MOV powOfSize,#1
+ LSL powOfSize,DCValueSize ;// powOfSize=pow(2,DCValueSize)
+ CMP DCVal,powOfSize,LSR #1 ;// Compare DCVal with powOfSize/2
+ ADDLT DCVal,DCVal,#1
+ SUBLT DCVal,DCVal,powOfSize ;// If Lessthan powOfSize/2 DCVal=DCVal-powOfSize+1
+ ;// Else DCVal= fetchbits from bit stream
+
+CheckDCValueSize
+
+ CMP DCValueSize,#8 ;// If DCValueSize greater than 8 check marker bit
+
+ BLE ACDecode
+
+ M_BD_READ8 temp1,1,T1
+ TEQ temp1,#0 ;// If Marker bit is zero Exit with an Error Message
+ BEQ ExitError
+
+
+
+ ;// Decode AC Coefficient
+
+ACDecode
+
+ M_STR DCVal,pDCCoeff ;// Store Decoded DC Coeff on Stack
+ M_BD_FINI ppBitStream,pBitOffset ;// Terminating the Bit stream Macro
+
+ LDR pZigzagTable, =armVCM4P2_aClassicalZigzagScan ;// Load Zigzag talbe address
+ ADD pZigzagTable, pZigzagTable, PredDir, LSL #6 ;// Modify the Zigzag table adress based on PredDir
+
+ M_STR pZigzagTable,ppZigzagTable ;// Store zigzag table on stack
+ LDR pVlcTableL0L1, =armVCM4P2_IntraVlcL0L1 ;// Load Optimized VLC Table With both Last=0 and Last=1 Entries
+ M_STR pVlcTableL0L1,ppVlcTableL0L1 ;// Store Optimized VLC Table on stack
+ LDR pLMAXTableL0L1, =armVCM4P2_IntraL0L1LMAX ;// Load LMAX Table
+ M_STR pLMAXTableL0L1,ppLMAXTableL0L1 ;// Store LMAX table on stack
+ LDR pRMAXTableL0L1, =armVCM4P2_IntraL0L1RMAX ;// Load RMAX Table
+ MOV Count,#1 ;// Set Start =1
+
+ M_STR pRMAXTableL0L1,ppRMAXTableL0L1 ;// Store RMAX Table on Stack
+
+
+ M_LDR shortVideoHeader,shortVideoHeaderonStack ;// Load the Input Argument From Stack
+
+ BL armVCM4P2_DecodeVLCZigzag_AC_unsafe ;// Call the Unsafe Function
+
+ M_LDR DCVal,pDCCoeff ;// Get the Decoded DC Value From Stack
+ STRH DCVal,[pDst] ;// Store the DC Value
+ B ExitOK
+
+
+
+ExitError
+
+ M_BD_FINI ppBitStream,pBitOffset ;// Terminating the Bit Stream Macro in case of an Error
+ MOV Return,#OMX_Sts_Err ;// Exit with an Error Message
+ExitOK
+
+ M_END
+ ENDIF
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
new file mode 100644
index 0000000..a4bfa71
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
@@ -0,0 +1,194 @@
+;//
+;//
+;// File Name: omxVCM4P2_FindMVpred_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+;// Function:
+;// omxVCM4P2_FindMVpred
+;//
+ ;// Include headers
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armVCCOMM_s.h
+
+ ;// Define cpu variants
+ M_VARIANTS ARM1136JS
+
+
+ IF ARM1136JS
+
+ M_TABLE armVCM4P2_pBlkIndexTable
+ DCD OMXVCBlk0, OMXVCBlk1
+ DCD OMXVCBlk2, OMXVCBlk3
+
+;//--------------------------------------------
+;// Declare input registers
+;//--------------------------------------------
+
+pSrcMVCurMB RN 0
+pSrcCandMV1 RN 1
+pSrcCandMV2 RN 2
+pSrcCandMV3 RN 3
+pDstMVPred RN 4
+pDstMVPredME RN 5
+iBlk RN 6
+
+pTable RN 4
+CandMV RN 12
+
+pCandMV1 RN 7
+pCandMV2 RN 8
+pCandMV3 RN 9
+
+CandMV1dx RN 0
+CandMV1dy RN 1
+CandMV2dx RN 2
+CandMV2dy RN 3
+CandMV3dx RN 10
+CandMV3dy RN 11
+
+temp RN 14
+
+zero RN 14
+return RN 0
+
+; ----------------------------------------------
+; Main routine
+; ----------------------------------------------
+
+ M_ALLOC4 MV, 4
+
+ ;// Function header
+ M_START omxVCM4P2_FindMVpred, r11
+
+ ;// Define stack arguments
+ M_ARG ppDstMVPred, 4
+ M_ARG ppDstMVPredME, 4
+ M_ARG Blk, 4
+
+ M_ADR CandMV, MV
+ MOV zero, #0
+ M_LDR iBlk, Blk
+
+ ;// Set the default value for these
+ ;// to be used if pSrcCandMV[1|2|3] == NULL
+ MOV pCandMV1, CandMV
+ MOV pCandMV2, CandMV
+ MOV pCandMV3, CandMV
+
+ STR zero, [CandMV]
+
+ ;// Branch to the case based on blk number
+ M_SWITCH iBlk
+ M_CASE OMXVCBlk0 ;// iBlk=0
+ M_CASE OMXVCBlk1 ;// iBlk=0
+ M_CASE OMXVCBlk2 ;// iBlk=0
+ M_CASE OMXVCBlk3 ;// iBlk=0
+ M_ENDSWITCH
+
+OMXVCBlk0
+ CMP pSrcCandMV1, #0
+ ADDNE pCandMV1, pSrcCandMV1, #4
+
+ CMP pSrcCandMV2, #0
+ ADDNE pCandMV2, pSrcCandMV2, #8
+
+ CMP pSrcCandMV3, #0
+ ADDNE pCandMV3, pSrcCandMV3, #8
+ CMPEQ pSrcCandMV1, #0
+
+ MOVEQ pCandMV3, pCandMV2
+ MOVEQ pCandMV1, pCandMV2
+
+ CMP pSrcCandMV1, #0
+ CMPEQ pSrcCandMV2, #0
+
+ MOVEQ pCandMV1, pCandMV3
+ MOVEQ pCandMV2, pCandMV3
+
+ CMP pSrcCandMV2, #0
+ CMPEQ pSrcCandMV3, #0
+
+ MOVEQ pCandMV2, pCandMV1
+ MOVEQ pCandMV3, pCandMV1
+
+ B BlkEnd
+
+OMXVCBlk1
+ MOV pCandMV1, pSrcMVCurMB
+ CMP pSrcCandMV3, #0
+ ADDNE pCandMV3, pSrcCandMV3, #8
+
+ CMP pSrcCandMV2, #0
+ ADDNE pCandMV2, pSrcCandMV2, #12
+
+ CMPEQ pSrcCandMV3, #0
+
+ MOVEQ pCandMV2, pCandMV1
+ MOVEQ pCandMV3, pCandMV1
+
+ B BlkEnd
+
+OMXVCBlk2
+ CMP pSrcCandMV1, #0
+ MOV pCandMV2, pSrcMVCurMB
+ ADD pCandMV3, pSrcMVCurMB, #4
+ ADDNE pCandMV1, pSrcCandMV1, #12
+ B BlkEnd
+
+OMXVCBlk3
+ ADD pCandMV1, pSrcMVCurMB, #8
+ MOV pCandMV2, pSrcMVCurMB
+ ADD pCandMV3, pSrcMVCurMB, #4
+
+BlkEnd
+
+ ;// Using the transperancy info, zero
+ ;// out the candidate MV if neccesary
+ LDRSH CandMV1dx, [pCandMV1], #2
+ LDRSH CandMV2dx, [pCandMV2], #2
+ LDRSH CandMV3dx, [pCandMV3], #2
+
+ ;// Load argument from the stack
+ M_LDR pDstMVPredME, ppDstMVPredME
+
+ LDRSH CandMV1dy, [pCandMV1]
+ LDRSH CandMV2dy, [pCandMV2]
+ LDRSH CandMV3dy, [pCandMV3]
+
+ CMP pDstMVPredME, #0
+
+ ;// Store the candidate MV's into the pDstMVPredME,
+ ;// these can be used in the fast algorithm if implemented
+
+ STRHNE CandMV1dx, [pDstMVPredME], #2
+ STRHNE CandMV1dy, [pDstMVPredME], #2
+ STRHNE CandMV2dx, [pDstMVPredME], #2
+ STRHNE CandMV2dy, [pDstMVPredME], #2
+ STRHNE CandMV3dx, [pDstMVPredME], #2
+ STRHNE CandMV3dy, [pDstMVPredME]
+
+ ; Find the median of the 3 candidate MV's
+ M_MEDIAN3 CandMV1dx, CandMV2dx, CandMV3dx, temp
+
+ ;// Load argument from the stack
+ M_LDR pDstMVPred, ppDstMVPred
+
+ M_MEDIAN3 CandMV1dy, CandMV2dy, CandMV3dy, temp
+
+ STRH CandMV3dx, [pDstMVPred], #2
+ STRH CandMV3dy, [pDstMVPred]
+
+ MOV return, #OMX_Sts_NoErr
+
+ M_END
+ ENDIF ;// ARM1136JS :LOR: CortexA8
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
new file mode 100644
index 0000000..bfeb540
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
@@ -0,0 +1,73 @@
+;//
+;//
+;// File Name: omxVCM4P2_IDCT8x8blk_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+;// Function:
+;// omxVCM4P2_IDCT8x8blk
+;//
+ ;// Include headers
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ ;// Define cpu variants
+ M_VARIANTS ARM1136JS
+
+ INCLUDE armCOMM_IDCT_s.h
+
+ IMPORT armCOMM_IDCTPreScale
+ ;//
+ ;// Function prototype
+ ;//
+ ;// OMXResult
+ ;// omxVCM4P2_IDCT8x8blk(const OMX_S16* pSrc,
+ ;// OMX_S16* pDst)
+ ;//
+
+ IF ARM1136JS :LOR: CortexA8
+ M_ALLOC4 ppDest, 4
+ M_ALLOC4 pStride, 4
+ M_ALLOC8 pBlk, 2*8*8
+ ENDIF
+
+ IF ARM1136JS
+ M_START omxVCM4P2_IDCT8x8blk, r11
+ ENDIF
+
+
+ IF ARM1136JS :LOR: CortexA8
+
+;// Declare input registers
+pSrc RN 0
+pDst RN 1
+
+;// Declare other intermediate registers
+Result RN 0
+
+;// Prototype for macro M_IDCT
+;// pSrc RN 0 ;// source data buffer
+;// Stride RN 1 ;// destination stride in bytes
+;// pDest RN 2 ;// destination data buffer
+;// pScale RN 3 ;// pointer to scaling table
+
+pSrc RN 0
+Stride RN 1
+pDest RN 2
+pScale RN 3
+
+ MOV pDest, pDst
+ LDR pScale, =armCOMM_IDCTPreScale
+ M_IDCT s9, s16, 16
+ MOV Result, #OMX_Sts_NoErr
+ M_END
+ ENDIF
+ ;// ARM1136JS :LOR: CortexA8
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
new file mode 100644
index 0000000..20965bf
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
@@ -0,0 +1,713 @@
+;//
+;//
+;// File Name: omxVCM4P2_MCReconBlock_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// Description:
+;//
+;//
+
+;// Include standard headers
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+;// Import symbols required from other files
+
+ M_VARIANTS ARM1136JS
+
+;// ***************************************************************************
+;// ARM1136JS implementation
+;// ***************************************************************************
+ IF ARM1136JS
+
+;// ***************************************************************************
+;// MACRO DEFINITIONS
+;// ***************************************************************************
+ ;// Description:
+ ;//
+ ;// dest[j] = (x[j] + y[j] + round) >> 1, j=0..3
+ ;//
+ ;// Similar to UHADD8 instruction, but with a rounding value of 1 added to
+ ;// each sum before dividing by two, if round is 1
+ ;//
+ ;// Syntax:
+ ;// M_UHADD8R $dest, $x, $y, $round, $mask
+ ;//
+ ;// Inputs:
+ ;// $x four packed bytes, x[3] : x[2] : x[1] : x[0]
+ ;// $y four packed bytes, y[3] : y[2] : y[1] : y[0]
+ ;// $round 0 if no rounding to be added, 1 if rounding to be done
+ ;// $mask some register set to 0x80808080
+ ;//
+ ;// Outputs:
+ ;// $dest four packed bytes, z[3] : z[2] : z[1] : z[0]
+
+ MACRO
+ M_UHADD8R $dest, $x, $y, $round, $mask
+ IF $round = 1
+ IF $dest /= $y
+ MVN $dest, $x
+ UHSUB8 $dest, $y, $dest
+ EOR $dest, $dest, $mask
+ ELSE
+ MVN $dest, $y
+ UHSUB8 $dest, $x, $dest
+ EOR $dest, $dest, $mask
+ ENDIF
+ ELSE
+ UHADD8 $dest, $x, $y
+ ENDIF
+ MEND
+;// ***************************************************************************
+ ;// Description:
+ ;// Load 8 bytes from $pSrc (aligned or unaligned locations)
+ ;//
+ ;// Syntax:
+ ;// M_LOAD_X $pSrc, $srcStep, $out0, $out1, $scratch, $offset
+ ;//
+ ;// Inputs:
+ ;// $pSrc 4 byte aligned source pointer to an address just less than
+ ;// or equal to the data location
+ ;// $srcStep The stride on source
+ ;// $scratch A scratch register, used internally for temp calculations
+ ;// $offset Difference of source data location to the source pointer
+ ;// Use when $offset != 0 (unaligned load)
+ ;//
+ ;// Outputs:
+ ;// $pSrc In case the macro accepts stride, it increments the pSrc by
+ ;// that value, else unchanged
+ ;// $out0 four packed bytes, z[3] : z[2] : z[1] : z[0]
+ ;// $out1 four packed bytes, z[7] : z[6] : z[5] : z[4]
+ ;//
+ ;// Note: {$out0, $out1, $scratch} should be registers with ascending
+ ;// register numbering. In case offset is 0, $scratch is not modified.
+
+ MACRO
+ M_LOAD_X $pSrc, $srcStep, $out0, $out1, $scratch, $offset
+ IF $offset = 0
+ LDM $pSrc, {$out0, $out1}
+ ADD $pSrc, $pSrc, $srcStep
+ ELSE
+ LDM $pSrc, {$out0, $out1, $scratch}
+ ADD $pSrc, $pSrc, $srcStep
+
+ MOV $out0, $out0, LSR #8 * $offset
+ ORR $out0, $out0, $out1, LSL #(32 - 8 * ($offset))
+ MOV $out1, $out1, LSR #8 * $offset
+ ORR $out1, $out1, $scratch, LSL #(32 - 8 * ($offset))
+ ENDIF
+ MEND
+
+;// ***************************************************************************
+ ;// Description:
+ ;// Loads three words for X interpolation, update pointer to next row. For
+ ;// X interpolation, given a truncated-4byteAligned source pointer,
+ ;// invariably three continous words are required from there to get the
+ ;// nine bytes from the source pointer for filtering.
+ ;//
+ ;// Syntax:
+ ;// M_LOAD_XINT $pSrc, $srcStep, $offset, $word0, $word1, $word2, $word3
+ ;//
+ ;// Inputs:
+ ;// $pSrc 4 byte aligned source pointer to an address just less than
+ ;// or equal to the data location
+ ;//
+ ;// $srcStep The stride on source
+ ;//
+ ;// $offset Difference of source data location to the source pointer
+ ;// Use when $offset != 0 (unaligned load)
+ ;//
+ ;// Outputs:
+ ;// $pSrc Incremented by $srcStep
+ ;//
+ ;// $word0, $word1, $word2, $word3
+ ;// Three of these are outputs based on the $offset parameter.
+ ;// The outputs are specifically generated to be processed by
+ ;// the M_EXT_XINT macro. Following is the illustration to show
+ ;// how the nine bytes are spanned for different offsets from
+ ;// notTruncatedForAlignmentSourcePointer.
+ ;//
+ ;// ------------------------------------------------------
+ ;// | Offset | Aligned Ptr | word0 | word1 | word2 | word3 |
+ ;// |------------------------------------------------------|
+ ;// | 0 | 0 | 0123 | 4567 | 8xxx | |
+ ;// | 1 | -1 | x012 | 3456 | 78xx | |
+ ;// | 2 | -2 | xx01 | 2345 | 678x | |
+ ;// | 3 | -3 | xxx0 | | 1234 | 5678 |
+ ;// ------------------------------------------------------
+ ;//
+ ;// where the numbering (0-8) is to designate the 9 bytes from
+ ;// start of a particular row. The illustration doesn't take in
+ ;// account the positioning of bytes with in the word and the
+ ;// macro combination with M_EXT_XINT will work only in little
+ ;// endian environs
+ ;//
+ ;// Note: {$word0, $word1, $word2, $word3} should be registers with ascending
+ ;// register numbering
+
+ MACRO
+ M_LOAD_XINT $pSrc, $srcStep, $offset, $word0, $word1, $word2, $word3
+ IF $offset /= 3
+ LDM $pSrc, {$word0, $word1, $word2}
+ ELSE
+ LDM $pSrc, {$word0, $word2, $word3}
+ ENDIF
+ ADD $pSrc, $pSrc, $srcStep
+ MEND
+
+;// ***************************************************************************
+ ;// Description:
+ ;// Extract four registers of four pixels for X interpolation
+ ;//
+ ;// Syntax:
+ ;// M_EXT_XINT $offset, $word0, $word1, $word2, $word3
+ ;//
+ ;// Inputs:
+ ;// $offset Difference of source data location to the source pointer
+ ;// Use when $offset != 0 (unaligned load)
+ ;//
+ ;// $word0, $word1, $word2, $word3
+ ;// Three of these are inputs based on the $offset parameter.
+ ;// The inputs are specifically selected to be processed by
+ ;// the M_EXT_XINT macro.
+ ;//
+ ;// ------------------------------------------------------
+ ;// | Offset | Aligned Ptr | word0 | word1 | word2 | word3 |
+ ;// |------------------------------------------------------|
+ ;// | 0 | 0 | 0123 | 4567 | 8xxx | yyyy |
+ ;// | 1 | -1 | x012 | 3456 | 78xx | yyyy |
+ ;// | 2 | -2 | xx01 | 2345 | 678x | yyyy |
+ ;// | 3 | -3 | xxx0 | yyyy | 1234 | 5678 |
+ ;// ------------------------------------------------------
+ ;//
+ ;// Outputs:
+ ;// $word0, $word1, $word2, $word3
+ ;// Bytes from the original source pointer (not truncated for
+ ;// 4 byte alignment) as shown in the table.
+ ;// -------------------------------
+ ;// | word0 | word1 | word2 | word3 |
+ ;// |-------------------------------|
+ ;// | 0123 | 4567 | 1234 | 5678 |
+ ;// -------------------------------
+ ;//
+ ;// Note: {$word0, $word1, $word2, $word3} should be registers with ascending
+ ;// register numbering
+
+ MACRO
+ M_EXT_XINT $offset, $word0, $word1, $word2, $word3
+ IF $offset = 0
+ ; $word0 and $word1 are ok
+ ; $word2, $word3 are just 8 shifted versions
+ MOV $word3, $word1, LSR #8
+ ORR $word3, $word3, $word2, LSL #24
+ MOV $word2, $word0, LSR #8
+ ORR $word2, $word2, $word1, LSL #24
+ ELIF $offset = 3
+ ; $word2 and $word3 are ok (taken care while loading itself)
+ ; set $word0 & $word1
+ MOV $word0, $word0, LSR #24
+ ORR $word0, $word0, $word2, LSL #8
+ MOV $word1, $word2, LSR #24
+ ORR $word1, $word1, $word3, LSL #8
+ ELSE
+ MOV $word0, $word0, LSR #8 * $offset
+ ORR $word0, $word0, $word1, LSL #(32 - 8 * ($offset))
+ MOV $word1, $word1, LSR #8 * $offset
+ ORR $word1, $word1, $word2, LSL #(32 - 8 * ($offset))
+
+ MOV $word3, $word1, LSR #8
+ ORR $word3, $word3, $word2, LSL #(32 - 8 * (($offset)+1))
+ MOV $word2, $word0, LSR #8
+ ORR $word2, $word2, $word1, LSL #24
+ ENDIF
+ MEND
+
+;// ***************************************************************************
+ ;// Description:
+ ;// Computes half-sum and xor of two inputs and puts them in the input
+ ;// registers in that order
+ ;//
+ ;// Syntax:
+ ;// M_HSUM_XOR $v0, $v1, $tmp
+ ;//
+ ;// Inputs:
+ ;// $v0 a, first input
+ ;// $v1 b, second input
+ ;// $tmp scratch register
+ ;//
+ ;// Outputs:
+ ;// $v0 (a + b)/2
+ ;// $v1 a ^ b
+
+ MACRO
+ M_HSUM_XOR $v0, $v1, $tmp
+ UHADD8 $tmp, $v0, $v1 ;// s0 = a + b
+ EOR $v1, $v0, $v1 ;// l0 = a ^ b
+ MOV $v0, $tmp ;// s0
+ MEND
+;// ***************************************************************************
+ ;// Description:
+ ;// Calculates average of 4 values (a,b,c,d) for HalfPixelXY predict type in
+ ;// mcReconBlock module. Very specific to the implementation of
+ ;// M_MCRECONBLOCK_HalfPixelXY done here. Uses "tmp" as scratch register and
+ ;// "yMask" for mask variable "0x1010101x" set in it. In yMask 4 lsbs are
+ ;// not significant and are used by the callee for row counter (y)
+ ;//
+ ;// Some points to note are:
+ ;// 1. Input is pair of pair-averages and Xors
+ ;// 2. $sum1 and $lsb1 are not modified and hence can be reused in another
+ ;// running average
+ ;// 3. Output is in the first argument
+ ;//
+ ;// Syntax:
+ ;// M_AVG4 $sum0, $lsb0, $sum1, $lsb1, $rndVal
+ ;//
+ ;// Inputs:
+ ;// $sum0 (a + b) >> 1, where a and b are 1st and 2nd inputs to be averaged
+ ;// $lsb0 (a ^ b)
+ ;// $sum1 (c + d) >> 1. Not modified
+ ;// $lsb1 (c ^ d) Not modified
+ ;// $rndVal Assembler Variable. 0 for rounding, 1 for no rounding
+ ;//
+ ;// Outputs:
+ ;// $sum0 (a + b + c + d + 1) / 4 : If no rounding
+ ;// (a + b + c + d + 2) / 4 : If rounding
+
+ MACRO
+ M_AVG4 $sum0, $lsb0, $sum1, $lsb1, $rndVal
+ LCLS OP1
+ LCLS OP2
+ IF $rndVal = 0 ;// rounding case
+OP1 SETS "AND"
+OP2 SETS "ORR"
+ ELSE ;// Not rounding case
+OP1 SETS "ORR"
+OP2 SETS "AND"
+ ENDIF
+
+ LCLS lsb2
+ LCLS sum2
+ LCLS dest
+
+lsb2 SETS "tmp"
+sum2 SETS "$lsb0"
+dest SETS "$sum0"
+
+ $OP1 $lsb0, $lsb0, $lsb1 ;// e0 = e0 & e1
+ EOR $lsb2, $sum0, $sum1 ;// e2 = s0 ^ s1
+ $OP2 $lsb2, $lsb2, $lsb0 ;// e2 = e2 | e0
+ AND $lsb2, $lsb2, yMask, LSR # 4 ;// e2 = e2 & mask
+ UHADD8 $sum2, $sum0, $sum1 ;// s2 = (s0 + s1)/2
+ UADD8 $dest, $sum2, $lsb2 ;// dest = s2 + e2
+ MEND
+;// ***************************************************************************
+;// Motion compensation handler macros
+;// ***************************************************************************
+ ;// Description:
+ ;// Implement motion compensation routines using the named registers in
+ ;// callee function. Each of the following 4 implement the 4 predict type
+ ;// Each handles 8 cases each ie all the combinations of 4 types of source
+ ;// alignment offsets and 2 types of rounding flag
+ ;//
+ ;// Syntax:
+ ;// M_MCRECONBLOCK_IntegerPixel $rndVal, $offset
+ ;// M_MCRECONBLOCK_HalfPixelX $rndVal, $offset
+ ;// M_MCRECONBLOCK_HalfPixelY $rndVal, $offset
+ ;// M_MCRECONBLOCK_HalfPixelXY $rndVal, $offset
+ ;//
+ ;// Inputs:
+ ;// $rndVal Assembler Variable. 0 for rounding, 1 for no rounding
+ ;// $offset $pSrc MOD 4 value. Offset from 4 byte aligned location.
+ ;//
+ ;// Outputs:
+ ;// Outputs come in the named registers of the callee functions
+ ;// The macro loads the data from the source pointer, processes it and
+ ;// stores in the destination pointer. Does the whole prediction cycle
+ ;// of Motion Compensation routine for a particular predictType
+ ;// After this only residue addition to the predicted values remain
+
+ MACRO
+ M_MCRECONBLOCK_IntegerPixel $rndVal, $offset
+ ;// Algorithmic Description:
+ ;// This handles motion compensation for IntegerPixel predictType. Both
+ ;// rounding cases are handled by the same code base. It is just a copy
+ ;// from source to destination. Two lines are done per loop to reduce
+ ;// stalls. Loop has been software pipelined as well for that purpose.
+ ;//
+ ;// M_LOAD_X loads a whole row in two registers and then they are stored
+
+CaseIntegerPixelRnd0Offset$offset
+CaseIntegerPixelRnd1Offset$offset
+ M_LOAD_X pSrc, srcStep, tmp1, tmp2, tmp3, $offset
+ M_LOAD_X pSrc, srcStep, tmp3, tmp4, tmp5, $offset
+YloopIntegerPixelOffset$offset
+ SUBS y, y, #2
+ STRD tmp1, tmp2, [pDst], dstStep
+ STRD tmp3, tmp4, [pDst], dstStep
+ M_LOAD_X pSrc, srcStep, tmp1, tmp2, tmp3, $offset
+ M_LOAD_X pSrc, srcStep, tmp3, tmp4, tmp5, $offset
+ BGT YloopIntegerPixelOffset$offset
+
+ B SwitchPredictTypeEnd
+ MEND
+;// ***************************************************************************
+ MACRO
+ M_MCRECONBLOCK_HalfPixelX $rndVal, $offset
+ ;// Algorithmic Description:
+ ;// This handles motion compensation for HalfPixelX predictType. The two
+ ;// rounding cases are handled by the different code base and spanned by
+ ;// different macro calls. Loop has been software pipelined to reduce
+ ;// stalls.
+ ;//
+ ;// Filtering involves averaging a pixel with the next horizontal pixel.
+ ;// M_LOAD_XINT and M_EXT_XINT combination generate 4 registers, 2 with
+ ;// all pixels in a row with 4 pixel in each register and another 2
+ ;// registers with pixels corresponding to one horizontally shifted pixel
+ ;// corresponding to the initial row pixels. These are set of packed
+ ;// registers appropriate to do 4 lane SIMD.
+ ;// After that M_UHADD8R macro does the averaging taking care of the
+ ;// rounding as required
+
+CaseHalfPixelXRnd$rndVal.Offset$offset
+ IF $rndVal = 0
+ LDR mask, =0x80808080
+ ENDIF
+
+ M_LOAD_XINT pSrc, srcStep, $offset, tmp1, tmp2, tmp3, tmp4
+YloopHalfPixelXRnd$rndVal.Offset$offset
+ SUBS y, y, #1
+ M_EXT_XINT $offset, tmp1, tmp2, tmp3, tmp4
+ M_UHADD8R tmp5, tmp1, tmp3, (1-$rndVal), mask
+ M_UHADD8R tmp6, tmp2, tmp4, (1-$rndVal), mask
+ STRD tmp5, tmp6, [pDst], dstStep
+ M_LOAD_XINT pSrc, srcStep, $offset, tmp1, tmp2, tmp3, tmp4
+ BGT YloopHalfPixelXRnd$rndVal.Offset$offset
+
+ B SwitchPredictTypeEnd
+ MEND
+;// ***************************************************************************
+ MACRO
+ M_MCRECONBLOCK_HalfPixelY $rndVal, $offset
+ ;// Algorithmic Description:
+ ;// This handles motion compensation for HalfPixelY predictType. The two
+ ;// rounding cases are handled by the different code base and spanned by
+ ;// different macro calls. PreLoading is used to avoid reload of same data.
+ ;//
+ ;// Filtering involves averaging a pixel with the next vertical pixel.
+ ;// M_LOAD_X generates 2 registers with all pixels in a row with 4 pixel in
+ ;// each register. These are set of packed registers appropriate to do
+ ;// 4 lane SIMD. After that M_UHADD8R macro does the averaging taking care
+ ;// of the rounding as required
+
+CaseHalfPixelYRnd$rndVal.Offset$offset
+ IF $rndVal = 0
+ LDR mask, =0x80808080
+ ENDIF
+
+ M_LOAD_X pSrc, srcStep, tmp1, tmp2, tmp5, $offset ;// Pre-load
+YloopHalfPixelYRnd$rndVal.Offset$offset
+ SUBS y, y, #2
+ ;// Processing one line
+ M_LOAD_X pSrc, srcStep, tmp3, tmp4, tmp5, $offset
+ M_UHADD8R tmp1, tmp1, tmp3, (1-$rndVal), mask
+ M_UHADD8R tmp2, tmp2, tmp4, (1-$rndVal), mask
+ STRD tmp1, tmp2, [pDst], dstStep
+ ;// Processing another line
+ M_LOAD_X pSrc, srcStep, tmp1, tmp2, tmp5, $offset
+ M_UHADD8R tmp3, tmp3, tmp1, (1-$rndVal), mask
+ M_UHADD8R tmp4, tmp4, tmp2, (1-$rndVal), mask
+ STRD tmp3, tmp4, [pDst], dstStep
+
+ BGT YloopHalfPixelYRnd$rndVal.Offset$offset
+
+ B SwitchPredictTypeEnd
+ MEND
+;// ***************************************************************************
+ MACRO
+ M_MCRECONBLOCK_HalfPixelXY $rndVal, $offset
+ ;// Algorithmic Description:
+ ;// This handles motion compensation for HalfPixelXY predictType. The two
+ ;// rounding cases are handled by the different code base and spanned by
+ ;// different macro calls. PreLoading is used to avoid reload of same data.
+ ;//
+ ;// Filtering involves averaging a pixel with the next vertical, horizontal
+ ;// and right-down diagonal pixels. Just as in HalfPixelX case, M_LOAD_XINT
+ ;// and M_EXT_XINT combination generates 4 registers with a row and its
+ ;// 1 pixel right shifted version, with 4 pixels in one register. Another
+ ;// call of that macro-combination gets another row. Then M_HSUM_XOR is
+ ;// called to get mutual half-sum and xor combinations of a row with its
+ ;// shifted version as they are inputs to the M_AVG4 macro which computes
+ ;// the 4 element average with rounding. Note that it is the half-sum/xor
+ ;// values that are preserved for next row as they can be re-used in the
+ ;// next call to the M_AVG4 and saves recomputation.
+ ;// Due to lack of register, the row counter and a masking value required
+ ;// in M_AVG4 are packed into a single register yMask where the last nibble
+ ;// holds the row counter values and rest holds the masking variable left
+ ;// shifted by 4
+
+CaseHalfPixelXYRnd$rndVal.Offset$offset
+ LDR yMask, =((0x01010101 << 4) + 8)
+
+ M_LOAD_XINT pSrc, srcStep, $offset, t00, t01, t10, t11 ;// Load a, a', b, b'
+ M_EXT_XINT $offset, t00, t01, t10, t11
+ M_HSUM_XOR t00, t10, tmp ;// s0, l0
+ M_HSUM_XOR t01, t11, tmp ;// s0', l0'
+
+YloopHalfPixelXYRnd$rndVal.Offset$offset
+ ;// Processsing one line
+ ;// t00, t01, t10, t11 required from previous loop
+ M_LOAD_XINT pSrc, srcStep, $offset, t20, t21, t30, t31 ;// Load c, c', d, d'
+ SUB yMask, yMask, #2
+ M_EXT_XINT $offset, t20, t21, t30, t31
+ M_HSUM_XOR t20, t30, tmp ;// s1, l1
+ M_HSUM_XOR t21, t31, tmp ;// s1', l1'
+ M_AVG4 t00, t10, t20, t30, $rndVal ;// s0, l0, s1, l1
+ M_AVG4 t01, t11, t21, t31, $rndVal ;// s0', l0', s1', l1'
+ STRD t00, t01, [pDst], dstStep ;// store the average
+
+ ;// Processsing another line
+ ;// t20, t21, t30, t31 required from above
+ M_LOAD_XINT pSrc, srcStep, $offset, t00, t01, t10, t11 ;// Load a, a', b, b'
+ TST yMask, #7
+ M_EXT_XINT $offset, t00, t01, t10, t11
+ M_HSUM_XOR t00, t10, tmp
+ M_HSUM_XOR t01, t11, tmp
+ M_AVG4 t20, t30, t00, t10, $rndVal
+ M_AVG4 t21, t31, t01, t11, $rndVal
+ STRD t20, t21, [pDst], dstStep
+
+ BGT YloopHalfPixelXYRnd$rndVal.Offset$offset
+
+ IF $offset/=3 :LOR: $rndVal/=1
+ B SwitchPredictTypeEnd
+ ENDIF
+ MEND
+;// ***************************************************************************
+;// Motion compensation handler macros end here
+;// ***************************************************************************
+ ;// Description:
+ ;// Populates all 4 kinds of offsets "cases" for each predictType and rndVal
+ ;// combination in the "switch" to prediction processing code segment
+ ;//
+ ;// Syntax:
+ ;// M_CASE_OFFSET $rnd, $predictType
+ ;//
+ ;// Inputs:
+ ;// $rnd 0 for rounding, 1 for no rounding
+ ;// $predictType The prediction mode
+ ;//
+ ;// Outputs:
+ ;// Populated list of "M_CASE"s for the "M_SWITCH" macro
+
+ MACRO
+ M_CASE_OFFSET $rnd, $predictType
+ M_CASE Case$predictType.Rnd$rnd.Offset0
+ M_CASE Case$predictType.Rnd$rnd.Offset1
+ M_CASE Case$predictType.Rnd$rnd.Offset2
+ M_CASE Case$predictType.Rnd$rnd.Offset3
+ MEND
+;// ***************************************************************************
+ ;// Description:
+ ;// Populates all 2 kinds of rounding "cases" for each predictType in the
+ ;// "switch" to prediction processing code segment
+ ;//
+ ;// Syntax:
+ ;// M_CASE_OFFSET $predictType
+ ;//
+ ;// Inputs:
+ ;// $predictType The prediction mode
+ ;//
+ ;// Outputs:
+ ;// Populated list of "M_CASE_OFFSET" macros
+
+ MACRO
+ M_CASE_MCRECONBLOCK $predictType
+ M_CASE_OFFSET 0, $predictType ;// 0 for rounding
+ M_CASE_OFFSET 1, $predictType ;// 1 for no rounding
+ MEND
+;// ***************************************************************************
+ ;// Description:
+ ;// Populates all 8 kinds of rounding and offset combinations handling macros
+ ;// for the specified predictType. In case of "IntegerPixel" predictType,
+ ;// rounding is not required so same code segment handles both cases
+ ;//
+ ;// Syntax:
+ ;// M_MCRECONBLOCK $predictType
+ ;//
+ ;// Inputs:
+ ;// $predictType The prediction mode
+ ;//
+ ;// Outputs:
+ ;// Populated list of "M_MCRECONBLOCK_<predictType>" macros for specified
+ ;// predictType. Each
+ ;// M_MCRECONBLOCK_<predictType> $rnd, $offset
+ ;// is an code segment (starting with a label indicating the predictType,
+ ;// rounding and offset combination)
+ ;// Four calls of this macro with the 4 prediction modes populate all the 32
+ ;// handlers
+
+ MACRO
+ M_MCRECONBLOCK $predictType
+ M_MCRECONBLOCK_$predictType 0, 0
+ M_MCRECONBLOCK_$predictType 0, 1
+ M_MCRECONBLOCK_$predictType 0, 2
+ M_MCRECONBLOCK_$predictType 0, 3
+ IF "$predictType" /= "IntegerPixel" ;// If not IntegerPixel then rounding makes a difference
+ M_MCRECONBLOCK_$predictType 1, 0
+ M_MCRECONBLOCK_$predictType 1, 1
+ M_MCRECONBLOCK_$predictType 1, 2
+ M_MCRECONBLOCK_$predictType 1, 3
+ ENDIF
+ MEND
+;// ***************************************************************************
+;// Input/Output Registers
+pSrc RN 0
+srcStep RN 1
+arg_pSrcResidue RN 2
+pSrcResidue RN 12
+pDst RN 3
+dstStep RN 2
+predictType RN 10
+rndVal RN 11
+mask RN 11
+
+;// Local Scratch Registers
+zero RN 12
+y RN 14
+
+tmp1 RN 4
+tmp2 RN 5
+tmp3 RN 6
+tmp4 RN 7
+tmp5 RN 8
+tmp6 RN 9
+tmp7 RN 10
+tmp8 RN 11
+tmp9 RN 12
+
+t00 RN 4
+t01 RN 5
+t10 RN 6
+t11 RN 7
+t20 RN 8
+t21 RN 9
+t30 RN 10
+t31 RN 11
+tmp RN 12
+
+yMask RN 14
+
+dst RN 1
+return RN 0
+
+ ;// Allocate memory on stack
+ M_ALLOC4 Stk_pDst, 4
+ M_ALLOC4 Stk_pSrcResidue, 4
+ ;// Function header
+ M_START omxVCM4P2_MCReconBlock, r11
+ ;// Define stack arguments
+ M_ARG Arg_dstStep, 4
+ M_ARG Arg_predictType, 4
+ M_ARG Arg_rndVal, 4
+ ;// Save on stack
+ M_STR pDst, Stk_pDst
+ M_STR arg_pSrcResidue, Stk_pSrcResidue
+ ;// Load argument from the stack
+ M_LDR dstStep, Arg_dstStep
+ M_LDR predictType, Arg_predictType
+ M_LDR rndVal, Arg_rndVal
+
+ MOV y, #8
+
+ AND tmp1, pSrc, #3
+ ORR predictType, tmp1, predictType, LSL #3
+ ORR predictType, predictType, rndVal, LSL #2
+ ;// Truncating source pointer to align to 4 byte location
+ BIC pSrc, pSrc, #3
+
+ ;// Implementation takes care of all combinations of different
+ ;// predictTypes, rounding cases and source pointer offsets to alignment
+ ;// of 4 bytes in different code bases unless one of these parameter wasn't
+ ;// making any difference to the implementation. Below M_CASE_MCRECONBLOCK
+ ;// macros branch into 8 M_CASE macros for all combinations of the 2
+ ;// rounding cases and 4 offsets of the pSrc pointer to the 4 byte
+ ;// alignment.
+ M_SWITCH predictType
+ M_CASE_MCRECONBLOCK IntegerPixel
+ M_CASE_MCRECONBLOCK HalfPixelX
+ M_CASE_MCRECONBLOCK HalfPixelY
+ M_CASE_MCRECONBLOCK HalfPixelXY
+ M_ENDSWITCH
+
+ ;// The M_MCRECONBLOCK macros populate the code bases by calling all 8
+ ;// particular macros (4 in case of IntegerPixel as rounding makes no
+ ;// difference there) to generate the code for all cases of rounding and
+ ;// offsets. LTORG is used to segment the code as code size bloated beyond
+ ;// 4KB.
+ M_MCRECONBLOCK IntegerPixel
+ M_MCRECONBLOCK HalfPixelX
+ LTORG
+ M_MCRECONBLOCK HalfPixelY
+ M_MCRECONBLOCK HalfPixelXY
+SwitchPredictTypeEnd
+
+ ;// Residue Addition
+ ;// This is done in 2 lane SIMD though loads are further optimized and
+ ;// 4 bytes are loaded in case of destination buffer. Algorithmic
+ ;// details are in inlined comments
+ M_LDR pSrcResidue, Stk_pSrcResidue
+ CMP pSrcResidue, #0
+ BEQ pSrcResidueConditionEnd
+pSrcResidueNotNull
+ M_LDR pDst, Stk_pDst
+ MOV y, #8
+ SUB dstStep, dstStep, #4
+Yloop_pSrcResidueNotNull
+ SUBS y, y, #1
+ LDR dst, [pDst] ;// dst = [dcba]
+ LDMIA pSrcResidue!, {tmp1, tmp2} ;// tmp1=[DC] tmp2=[BA]
+ PKHBT tmp3, tmp1, tmp2, LSL #16 ;// Deltaval1 = [C A]
+ PKHTB tmp4, tmp2, tmp1, ASR #16 ;// DeltaVal2 = [D B]
+ UXTB16 tmp1, dst ;// tmp1 = [0c0a]
+ UXTB16 tmp2, dst, ROR #8 ;// tmp2 = [0d0b]
+ QADD16 tmp1, tmp1, tmp3 ;// Add and saturate to 16 bits
+ QADD16 tmp2, tmp2, tmp4
+ USAT16 tmp1, #8, tmp1
+ USAT16 tmp2, #8, tmp2 ;// armClip(0, 255, tmp2)
+ ORR tmp1, tmp1, tmp2, LSL #8 ;// tmp1 = [dcba]
+ STR tmp1, [pDst], #4
+
+ LDR dst, [pDst]
+ LDMIA pSrcResidue!, {tmp1, tmp2}
+ PKHBT tmp3, tmp1, tmp2, LSL #16
+ PKHTB tmp4, tmp2, tmp1, ASR #16
+ UXTB16 tmp1, dst
+ UXTB16 tmp2, dst, ROR #8
+ QADD16 tmp1, tmp1, tmp3
+ QADD16 tmp2, tmp2, tmp4
+ USAT16 tmp1, #8, tmp1
+ USAT16 tmp2, #8, tmp2
+ ORR tmp1, tmp1, tmp2, LSL #8
+ STR tmp1, [pDst], dstStep
+
+ BGT Yloop_pSrcResidueNotNull
+pSrcResidueConditionEnd
+
+ MOV return, #OMX_Sts_NoErr
+
+ M_END
+ ENDIF ;// ARM1136JS
+
+;// ***************************************************************************
+;// CortexA8 implementation
+;// ***************************************************************************
+ END
+;// ***************************************************************************
+;// omxVCM4P2_MCReconBlock ends
+;// ***************************************************************************
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
new file mode 100644
index 0000000..213444a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
@@ -0,0 +1,283 @@
+; **********
+; *
+; * File Name: omxVCM4P2_PredictReconCoefIntra_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 9641
+; * Date: Thursday, February 7, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains module for DC/AC coefficient prediction
+; *
+; *
+; * Function: omxVCM4P2_PredictReconCoefIntra
+; *
+; * Description:
+; * Performs adaptive DC/AC coefficient prediction for an intra block. Prior
+; * to the function call, prediction direction (predDir) should be selected
+; * as specified in subclause 7.4.3.1 of ISO/IEC 14496-2.
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] pSrcDst pointer to the coefficient buffer which contains the
+; * quantized coefficient residuals (PQF) of the current
+; * block; must be aligned on a 4-byte boundary. The
+; * output coefficients are saturated to the range
+; * [-2048, 2047].
+; * [in] pPredBufRow pointer to the coefficient row buffer; must be aligned
+; * on a 4-byte boundary.
+; * [in] pPredBufCol pointer to the coefficient column buffer; must be
+; * aligned on a 4-byte boundary.
+; * [in] curQP quantization parameter of the current block. curQP may
+; * equal to predQP especially when the current block and
+; * the predictor block are in the same macroblock.
+; * [in] predQP quantization parameter of the predictor block
+; * [in] predDir indicates the prediction direction which takes one
+; * of the following values:
+; * OMX_VIDEO_HORIZONTAL predict horizontally
+; * OMX_VIDEO_VERTICAL predict vertically
+; * [in] ACPredFlag a flag indicating if AC prediction should be
+; * performed. It is equal to ac_pred_flag in the bit
+; * stream syntax of MPEG-4
+; * [in] videoComp video component type (luminance, chrominance or
+; * alpha) of the current block
+; * [out] pSrcDst pointer to the coefficient buffer which contains
+; * the quantized coefficients (QF) of the current
+; * block
+; * [out] pPredBufRow pointer to the updated coefficient row buffer
+; * [out] pPredBufCol pointer to the updated coefficient column buffer
+; * Return Value:
+; * OMX_Sts_NoErr - no error
+; * OMX_Sts_BadArgErr - Bad arguments
+; * - At least one of the pointers is NULL: pSrcDst, pPredBufRow, or pPredBufCol.
+; * - At least one the following cases: curQP <= 0, predQP <= 0, curQP >31,
+; * predQP > 31, preDir exceeds [1,2].
+; * - At least one of the pointers pSrcDst, pPredBufRow, or pPredBufCol is not
+; * 4-byte aligned.
+; *
+; *********
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+
+
+ IMPORT armVCM4P2_Reciprocal_QP_S32
+ IMPORT armVCM4P2_Reciprocal_QP_S16
+ IMPORT armVCM4P2_DCScaler
+
+
+
+ IF ARM1136JS
+
+
+;// Input Arguments
+
+pSrcDst RN 0
+pPredBufRow RN 1
+pPredBufCol RN 2
+curQP RN 3
+QP RN 3
+predQP RN 4
+predDir RN 5
+ACPredFlag RN 6
+videoComp RN 7
+
+;// Local Variables
+
+temp2 RN 5
+negCurQP RN 7
+negdcScaler RN 7
+tempPred RN 8
+
+dcScaler RN 4
+CoeffTable RN 9
+absCoeffDC RN 9
+temp3 RN 6
+absCoeffAC RN 6
+
+shortVideoHeader RN 9
+predCoeffTable RN 10
+Count RN 10
+temp1 RN 12
+index RN 12
+Rem RN 14
+temp RN 11
+Return RN 0
+
+
+
+ M_START omxVCM4P2_PredictReconCoefIntra,r12
+
+ ;// Assigning pointers to Input arguments on Stack
+
+ M_ARG predQPonStack,4
+ M_ARG predDironStack,4
+ M_ARG ACPredFlagonStack,4
+ M_ARG videoComponStack,4
+
+ ;// DC Prediction
+
+ M_LDR videoComp,videoComponStack ;// Load videoComp From Stack
+
+ M_LDR predDir,predDironStack ;// Load Prediction direction
+
+ ;// dcScaler Calculation
+
+ LDR index, =armVCM4P2_DCScaler
+ ADD index,index,videoComp,LSL #5
+ LDRB dcScaler,[index,QP]
+
+
+calDCVal
+
+
+ LDR predCoeffTable, =armVCM4P2_Reciprocal_QP_S16 ;// Loading the table with entries 32767/(1 to 63)
+
+ CMP predDir,#2 ;// Check if the Prediction direction is vertical
+
+ ;// Caulucate temp pred by performing Division
+
+ LDREQSH absCoeffDC,[pPredBufRow] ;// If vetical load the coeff from Row Prediction Buffer
+ LDRNESH absCoeffDC,[pPredBufCol] ;// If horizontal load the coeff from column Prediction Buffer
+
+ RSB negdcScaler,dcScaler,#0 ;// negdcScaler=-dcScaler
+
+ MOV temp1,absCoeffDC ;// temp1=prediction coeff
+ CMP temp1,#0
+ RSBLT absCoeffDC,temp1,#0 ;//absCoeffDC=abs(temp1)
+
+ ADD temp,dcScaler,dcScaler
+ LDRH temp,[predCoeffTable,temp] ;// Load value from coeff table for performing division using multiplication
+
+ SMULBB tempPred,temp,absCoeffDC ;// tempPred=pPredBufRow(Col)[0]*32767/dcScaler
+ ADD temp3,dcScaler,#1
+ LSR tempPred,tempPred,#15 ;// tempPred=pPredBufRow(Col)[0]/dcScaler
+ LSR temp3,temp3,#1 ;// temp3=round(dcScaler/2)
+
+ MLA Rem,negdcScaler,tempPred,absCoeffDC ;// Rem = pPredBufRow(Col)[0]-tempPred*dcScaler
+
+
+ LDRH temp,[pPredBufCol]
+ CMP Rem,temp3
+ ADDGE tempPred,#1 ;// If Rem>=round(dcScaler/2);tempPred=tempPred+1
+ CMP temp1,#0
+ RSBLT tempPred,tempPred,#0 ;/ if pPredBufRow(Col)[0]<0; tempPred=-tempPred
+
+
+ STRH temp,[pPredBufRow,#-16]
+
+ LDRH temp,[pSrcDst] ;// temp=pSrcDst[0]
+ M_LDR ACPredFlag,ACPredFlagonStack
+ ADD temp,temp,tempPred ;// temp=pSrcDst[0]+tempPred
+ SSAT16 temp,#12,temp ;// clip temp to [-2048,2047]
+
+ SMULBB temp1,temp,dcScaler ;// temp1=clipped(pSrcDst[0])*dcScaler
+ M_LDR predQP,predQPonStack
+ STRH temp,[pSrcDst]
+ CMP ACPredFlag,#1 ;// Check if the AC prediction flag is set or not
+ STRH temp1,[pPredBufCol] ;// store temp1 to pPredBufCol
+
+ ;// AC Prediction
+
+
+ BNE Exit ;// If not set Exit
+
+ LDR predCoeffTable, =armVCM4P2_Reciprocal_QP_S32 ;// Loading the table with entries 0x1ffff/(1 to 63)
+ MOV temp1,#4
+ MUL temp1,curQP,temp1
+ CMP predDir,#2 ;// Check the Prediction direction
+ RSB negCurQP,curQP,#0
+ LDR CoeffTable,[predCoeffTable,temp1] ;// CoeffTable=0x1ffff/curQP
+ ADD curQP,curQP,#1 ;// curQP=curQP+1
+ LSR curQP,curQP,#1 ;// curQP=round(curQP/2)
+ MOV Count,#2 ;// Initializing the Loop Count
+ BNE Horizontal ;// If the Prediction direction is horizontal branch to Horizontal
+
+
+
+loop1
+ ;// Calculate tempPred
+
+ LDRSH absCoeffAC,[pPredBufRow,Count] ;// absCoeffAC=pPredBufRow[i], 1=<i<=7
+ MOV temp1,absCoeffAC
+ CMP temp1,#0 ;// compare pPredBufRow[i] with zero, 1=<i<=7
+ RSBLT absCoeffAC,temp1,#0 ;// absCoeffAC= abs(pPredBufRow[i])
+
+ SMULBB absCoeffAC,absCoeffAC,predQP ;// temp1=pPredBufRow[i]*predQP
+ MUL tempPred,absCoeffAC,CoeffTable ;// tempPred=pPredBufRow[i]*predQP*0x1ffff/curQP
+ LSR tempPred,tempPred,#17
+
+ MLA Rem,negCurQP,tempPred,absCoeffAC ;// Rem=abs(pPredBufRow[i])-tempPred*curQP
+ LDRH temp,[pSrcDst,Count] ;// temp=pSrcDst[i],1<=i<8
+
+ CMP Rem,curQP
+ ADDGE tempPred,#1 ;// if Rem>=round(curQP/2); tempPred=tempPred+1
+ CMP temp1,#0
+ RSBLT tempPred,tempPred,#0 ;// if pPredBufRow[i]<0 ; tempPred=-tempPred
+
+ ;// Update source and Row Prediction buffers
+
+ ADD temp,temp,tempPred ;// temp=tempPred+pSrcDst[i]
+ SSAT16 temp,#12,temp ;// Clip temp to [-2048,2047]
+ STRH temp,[pSrcDst,Count]
+ STRH temp,[pPredBufRow,Count] ;// pPredBufRow[i]=temp
+ ADD Count,Count,#2 ;// i=i+1
+ CMP Count,#16 ;// compare if i=8
+ BLT loop1
+ B Exit ;// Branch to exit
+
+Horizontal
+
+ MOV Count,#16 ;// Initializing i=8
+
+loop2
+
+ LSR temp2,Count,#3 ;// temp2=i>>3
+
+ ;// Calculate tempPred
+
+ LDRH absCoeffAC,[pPredBufCol,temp2] ;// absCoefAC=pPredBufCol[i>>3]
+ MOV temp1,absCoeffAC
+ CMP temp1,#0 ;// compare pPredBufRow[i] with zero, 1=<i<=7
+ RSBLT absCoeffAC,temp1,#0 ;// absCoeffAC=abs(pPredBufCol[i>>3])
+
+ SMULBB absCoeffAC,absCoeffAC,predQP ;// temp1=pPredBufCol[i>>3]*predQP
+ MUL tempPred,absCoeffAC,CoeffTable ;// tempPred=pPredBufCol[i>>3]*predQP*0x1ffff/curQP
+ LSR tempPred,tempPred,#17 ;// tempPred=pPredBufCol[i>>3]*predQP/curQP
+
+ MLA Rem,negCurQP,tempPred,absCoeffAC
+ LDRH temp,[pSrcDst,Count] ;// temp=pSrcDst[i]
+
+ CMP Rem,curQP ;// Compare Rem with round(curQP/2)
+ ADDGE tempPred,#1 ;// tempPred=tempPred+1 if Rem>=round(curQP/2)
+ CMP temp1,#0
+ RSBLT tempPred,tempPred,#0 ;// if pPredBufCol[i>>3 <0 tempPred=-tempPred
+
+ ;// Update source and Row Prediction buffers
+
+ ADD temp,temp,tempPred ;// temp=pSrcDst[i]+tempPred
+ SSAT16 temp,#12,temp ;// Clip temp to [-2048,2047]
+ STRH temp,[pSrcDst,Count] ;// pSrcDst[0]= clipped value
+ STRH temp,[pPredBufCol,temp2] ;// pPredBufCol[i>>3]=temp
+ ADD Count,Count,#16 ;// i=i+8
+ CMP Count,#128 ;// compare i with 64
+ BLT loop2
+
+
+Exit
+
+ MOV Return,#OMX_Sts_NoErr
+
+ M_END
+ ENDIF
+ END
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
new file mode 100644
index 0000000..c9591cb
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
@@ -0,0 +1,141 @@
+;/**
+; *
+; * File Name: omxVCM4P2_QuantInvInter_I_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 9641
+; * Date: Thursday, February 7, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains modules for inter reconstruction
+; *
+; *
+; *
+; *
+; *
+; * Function: omxVCM4P2_QuantInvInter_I
+; *
+; * Description:
+; * Performs inverse quantization on intra/inter coded block.
+; * This function supports bits_per_pixel = 8. Mismatch control
+; * is performed for the first MPEG-4 mode inverse quantization method.
+; * The output coefficients are clipped to the range: [-2048, 2047].
+; * Mismatch control is performed for the first inverse quantization method.
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] pSrcDst pointer to the input (quantized) intra/inter block. Must be 16-byte aligned.
+; * [in] QP quantization parameter (quantiser_scale)
+; * [in] videoComp (Intra version only.) Video component type of the
+; * current block. Takes one of the following flags:
+; * OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE,
+; * OMX_VC_ALPHA.
+; * [in] shortVideoHeader a flag indicating presence of short_video_header;
+; * shortVideoHeader==1 selects linear intra DC mode,
+; * and shortVideoHeader==0 selects nonlinear intra DC mode.
+; * [out] pSrcDst pointer to the output (dequantized) intra/inter block. Must be 16-byte aligned.
+; *
+; * Return Value:
+; * OMX_Sts_NoErr - no error
+; * OMX_Sts_BadArgErr - bad arguments
+; * - If pSrcDst is NULL or is not 16-byte aligned.
+; * or
+; * - If QP <= 0.
+; * or
+; * - videoComp is none of OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE and OMX_VC_ALPHA.
+; *
+; */
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+
+
+ IF ARM1136JS
+
+;//Input Arguments
+pSrcDst RN 0
+QP RN 1
+
+;//Local Variables
+Return RN 0
+Count RN 4
+tempVal21 RN 2
+tempVal43 RN 3
+QP1 RN 5
+X2 RN 6
+X3 RN 14
+Result1 RN 8
+Result2 RN 9
+two RN 7
+
+ M_START omxVCM4P2_QuantInvInter_I,r9
+
+ MOV Count,#64
+ TST QP,#1
+ LDRD tempVal21,[pSrcDst] ;// Loads first two values of pSrcDst to tempVal21,
+ ;// next two values to tempVal43
+ SUBEQ QP1,QP,#1 ;// QP1=QP if QP is odd , QP1=QP-1 if QP is even
+ MOVNE QP1,QP
+ MOV two,#2
+
+
+
+Loop
+
+
+ SMULBB X2,tempVal21,two ;// X2= first val(lower 16 bits of tampVal21)*2
+ CMP X2,#0
+
+ RSBLT X2,X2,#0 ;// X2=absoluteval(first val)
+ SMLABBNE X2,QP,X2,QP1 ;// X2=2*absval(first val)*QP+QP if QP is odd
+ ;// X2=2*absval(first val)*QP+QP-1 if QP is even
+ SMULTB X3,tempVal21,two ;// X3= second val(top 16 bits of tampVal21)*2
+ RSBLT X2,X2,#0
+
+ CMP X3,#0
+
+ RSBLT X3,X3,#0
+ SMLABBNE X3,QP,X3,QP1
+
+ RSBLT X3,X3,#0
+ PKHBT Result1,X2,X3,LSL #16 ;// Result1[0-15]=X2[0-15],Result1[16-31]=X3[16-31]
+ SMULBB X2,tempVal43,two ;// X2= first val(lower 16 bits of tampVal43)*2
+ SSAT16 Result1,#12,Result1 ;// clip to range [-2048,2047]
+ CMP X2,#0
+
+
+
+ RSBLE X2,X2,#0
+ SMLABBNE X2,QP,X2,QP1
+ SMULTB X3,tempVal43,two ;// X2= first val(top 16 bits of tampVal21)*2
+ RSBLT X2,X2,#0
+ CMP X3,#0
+
+ LDRD tempVal21,[pSrcDst,#8] ;// Load next four Values to tempVal21,tempVal43
+
+ RSBLT X3,X3,#0
+ SMLABBNE X3,QP,X3,QP1
+ RSBLT X3,X3,#0
+ PKHBT Result2,X2,X3,LSL #16 ;// Result2[0-15]=X2[0-15],Result2[16-31]=X3[0-15]
+ SSAT16 Result2,#12,Result2 ;// clip to range [-2048,2047]
+
+ SUBS Count,Count,#4 ;// Decrement Count by 4 and continue if it has not reached 0
+ STRD Result1,[pSrcDst],#8 ;// Store Double words and increment the pointer to point the next store address
+
+
+
+ BGT Loop
+
+ MOV Return,#OMX_Sts_NoErr
+
+ M_END
+ ENDIF
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
new file mode 100644
index 0000000..6328e01
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
@@ -0,0 +1,188 @@
+;/**
+; *
+; * File Name: omxVCM4P2_QuantInvIntra_I_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 9641
+; * Date: Thursday, February 7, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains modules for inter reconstruction
+; *
+; *
+; *
+; *
+; *
+; *
+; * Function: omxVCM4P2_QuantInvIntra_I
+; *
+; * Description:
+; * Performs inverse quantization on intra/inter coded block.
+; * This function supports bits_per_pixel = 8. Mismatch control
+; * is performed for the first MPEG-4 mode inverse quantization method.
+; * The output coefficients are clipped to the range: [-2048, 2047].
+; * Mismatch control is performed for the first inverse quantization method.
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] pSrcDst pointer to the input (quantized) intra/inter block. Must be 16-byte aligned.
+; * [in] QP quantization parameter (quantiser_scale)
+; * [in] videoComp (Intra version only.) Video component type of the
+; * current block. Takes one of the following flags:
+; * OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE,
+; * OMX_VC_ALPHA.
+; * [in] shortVideoHeader a flag indicating presence of short_video_header;
+; * shortVideoHeader==1 selects linear intra DC mode,
+; * and shortVideoHeader==0 selects nonlinear intra DC mode.
+; * [out] pSrcDst pointer to the output (dequantized) intra/inter block. Must be 16-byte aligned.
+; *
+; * Return Value:
+; * OMX_Sts_NoErr - no error
+; * OMX_Sts_BadArgErr - bad arguments
+; * - If pSrcDst is NULL or is not 16-byte aligned.
+; * or
+; * - If QP <= 0.
+; * or
+; * - videoComp is none of OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE and OMX_VC_ALPHA.
+; *
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+
+ IMPORT armVCM4P2_DCScaler
+
+
+
+ IF ARM1136JS
+
+;//Input Arguments
+pSrcDst RN 0
+QP RN 1
+videoComp RN 2
+shortVideoHeader RN 3
+
+;//Local Variables
+Return RN 0
+dcScaler RN 4
+temp RN 12
+index RN 6
+
+tempVal21 RN 4
+tempVal43 RN 5
+QP1 RN 6
+X2 RN 7
+X3 RN 14
+Result1 RN 8
+Result2 RN 9
+two RN 10
+Count RN 11
+
+
+
+
+ M_START omxVCM4P2_QuantInvIntra_I,r11
+
+
+
+ ;// Perform Inverse Quantization for DC coefficient
+
+ TEQ shortVideoHeader,#0 ;// Test if short Video Header flag =0
+ MOVNE dcScaler,#8 ;// if shortVideoHeader is non zero dcScaler=8
+ BNE calDCVal
+ LDR index, =armVCM4P2_DCScaler
+ ADD index,index,videoComp,LSL #5
+ LDRB dcScaler,[index,QP]
+
+
+ ;//M_CalDCScalar shortVideoHeader,videoComp, QP
+
+calDCVal
+
+ LDRH temp,[pSrcDst]
+ SMULBB temp,temp,dcScaler ;// dcCoeff = dcScaler * Quantized DC coefficient(from memory)
+ SSAT temp,#12,temp ;// Saturating to 12 bits
+
+
+ MOV Count,#64
+ TST QP,#1
+ LDRD tempVal21,[pSrcDst] ;// Loads first two values of pSrcDst to tempVal21,
+ ;// next two values to tempVal43
+ SUBEQ QP1,QP,#1 ;// QP1=QP if QP is odd , QP1=QP-1 if QP is even
+ MOVNE QP1,QP
+ MOV two,#2
+
+
+
+
+
+Loop
+
+
+ SMULBB X2,tempVal21,two ;// X2= first val(lower 16 bits of tampVal21)*2
+ CMP X2,#0
+
+ RSBLT X2,X2,#0 ;// X2=absoluteval(first val)
+ SMLABBNE X2,QP,X2,QP1 ;// X2=2*absval(first val)*QP+QP if QP is odd
+ ;// X2=2*absval(first val)*QP+QP-1 if QP is even
+ SMULTB X3,tempVal21,two ;// X3= second val(top 16 bits of tampVal21)*2
+ RSBLT X2,X2,#0
+
+ CMP X3,#0
+
+ RSBLT X3,X3,#0
+ SMLABBNE X3,QP,X3,QP1
+
+ RSBLT X3,X3,#0
+ PKHBT Result1,X2,X3,LSL #16 ;// Result1[0-15]=X2[0-15],Result1[16-31]=X3[16-31]
+ SMULBB X2,tempVal43,two ;// X2= first val(lower 16 bits of tampVal43)*2
+ SSAT16 Result1,#12,Result1 ;// clip to range [-2048,2047]
+ CMP X2,#0
+
+
+
+ RSBLE X2,X2,#0
+ SMLABBNE X2,QP,X2,QP1
+ SMULTB X3,tempVal43,two ;// X2= first val(top 16 bits of tampVal21)*2
+ RSBLT X2,X2,#0
+ CMP X3,#0
+
+ LDRD tempVal21,[pSrcDst,#8] ;// Load next four Values to tempVal21,tempVal43
+
+ RSBLT X3,X3,#0
+ SMLABBNE X3,QP,X3,QP1
+ RSBLT X3,X3,#0
+ PKHBT Result2,X2,X3,LSL #16 ;// Result2[0-15]=X2[0-15],Result2[16-31]=X3[16-31]
+ SSAT16 Result2,#12,Result2 ;// clip to range [-2048,2047]
+
+ SUBS Count,Count,#4 ;// Decrement Count by 4 and continue if it has not reached 0
+ STRD Result1,[pSrcDst],#8 ;// Store Double words and increment the pointer to point the next store address
+
+
+
+ BGT Loop
+
+ SUB pSrcDst,pSrcDst,#128
+
+ ;// Storing the Inverse Quantized DC coefficient
+
+ STRH temp,[pSrcDst],#2
+
+
+
+ MOV Return,#OMX_Sts_NoErr
+
+
+
+
+ M_END
+ ENDIF
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/src/armVC_Version.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/src/armVC_Version.c
new file mode 100644
index 0000000..5d93681
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm11/vc/src/armVC_Version.c
@@ -0,0 +1,6 @@
+#include "omxtypes.h"
+#include "armCOMM_Version.h"
+
+#ifdef ARM_INCLUDE_VERSION_DESCRIPTIONS
+const char * const omxVC_VersionDescription = "ARM OpenMAX DL v" ARM_VERSION_STRING " Rel=" OMX_ARM_RELEASE_TAG " Arch=" OMX_ARM_BUILD_ARCHITECTURE " Tools=" OMX_ARM_BUILD_TOOLCHAIN ;
+#endif /* ARM_INCLUDE_VERSION_DESCRIPTIONS */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/ARM_DELIVERY.TXT b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/ARM_DELIVERY.TXT
new file mode 100755
index 0000000..cc2d70a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/ARM_DELIVERY.TXT
@@ -0,0 +1,63 @@
+The contents of this transaction was created by Hedley Francis
+of ARM on 19-Feb-2008.
+
+It contains the ARM data versions listed below.
+
+This data, unless otherwise stated, is ARM Proprietary and access to it
+is subject to the agreements indicated below.
+
+If you experience problems with this data, please contact ARM support
+quoting transaction reference <97414>.
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+- OX002-SW-98010-r0p0-00bet1
+ Video codecs - optimised code
+ V7 code release for Hantro (Ver 1.0.2)
+ internal access
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+This transaction contains deliverables which are designated as being of
+beta release status (BET).
+
+Beta release status has a particular meaning to ARM of which the recipient
+must be aware. Beta is a pre-release status indicating that the deliverable
+so described is believed to robustly demonstrate specified behaviour, to be
+consistent across its included aspects and be ready for general deployment.
+But Beta also indicates that pre-release reliability trials are ongoing and
+that it is possible residual defects or errors in operation, consistency
+and documentation may still be encountered. The recipient should consider
+this position when using this Beta material supplied. ARM will normally
+attempt to provide fixes or a work-around for defects identified by the
+recipient, but the provision or timeliness of this support cannot be
+guaranteed. ARM shall not be responsible for direct or consequential
+damages as a result of encountering one or more of these residual defects.
+By accepting a Beta release, the recipient agrees to these constraints and
+to providing reasonable information to ARM to enable the replication of the
+defects identified by the recipient. The specific Beta version supplied
+will not be supported after release of a later or higher status version.
+It should be noted that Support for the Beta release of the deliverable
+will only be provided by ARM to a recipient who has a current support and
+maintenance contract for the deliverable.
+
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+In addition to the data versions listed above, this transaction contains
+two additional files at the top level.
+
+The first is this file, ARM_DELIVERY_97414.TXT, which is the delivery
+note.
+
+The second is ARM_MANIFEST_97414.TXT which contains a manifest of all the
+files included in this transaction, together with their checksums.
+
+The checksums provided are calculated using the RSA Data Security, Inc.
+MD5 Message-Digest Algorithm.
+
+The checksums can be used to verify the integrity of this data using the
+"md5sum" tool (which is part of the GNU "textutils" package) by running:
+
+ % md5sum --check ARM_MANIFEST_97414.TXT
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/ARM_MANIFEST.TXT b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/ARM_MANIFEST.TXT
new file mode 100755
index 0000000..8310f67
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/ARM_MANIFEST.TXT
@@ -0,0 +1,91 @@
+ OX002-SW-98010-r0p0-00bet1/
+ OX002-SW-98010-r0p0-00bet1/api/
+e049791cfab6060a08cbac7b3ad767d6 OX002-SW-98010-r0p0-00bet1/api/armCOMM_s.h
+ed798face25497b2703ede736d6d52b6 OX002-SW-98010-r0p0-00bet1/api/omxtypes_s.h
+4eebd63af087376811d6749f0646b864 OX002-SW-98010-r0p0-00bet1/api/armCOMM_BitDec_s.h
+43cf46c2cf2fe1f93c615b57bcbe4809 OX002-SW-98010-r0p0-00bet1/api/armCOMM.h
+8f248ceaac8f602e277a521b679dcbbe OX002-SW-98010-r0p0-00bet1/api/armCOMM_IDCTTable.h
+8ac5fa80ea98e391f5730a375280b5bd OX002-SW-98010-r0p0-00bet1/api/armCOMM_Version.h
+3a2f420ddf6a1b950470bd0f5ebd5c62 OX002-SW-98010-r0p0-00bet1/api/armCOMM_IDCT_s.h
+511c0bb534fe223599e2c84eff24c9ed OX002-SW-98010-r0p0-00bet1/api/armCOMM_MaskTable.h
+8971932d56eed6b1ad1ba507f0bff5f0 OX002-SW-98010-r0p0-00bet1/api/armCOMM_Bitstream.h
+f87fedd9ca432fefa757008176864ef8 OX002-SW-98010-r0p0-00bet1/api/armOMX.h
+8e49899a428822c36ef9dd94e0e05f18 OX002-SW-98010-r0p0-00bet1/api/omxtypes.h
+323008b72e9f04099a8cb42e99a1face OX002-SW-98010-r0p0-00bet1/build_vc.pl
+e72d96c0a415459748df9807f3dae72f OX002-SW-98010-r0p0-00bet1/filelist_vc.txt
+ OX002-SW-98010-r0p0-00bet1/src/
+5eeae659a29477f5c52296d24afffd3c OX002-SW-98010-r0p0-00bet1/src/armCOMM_IDCTTable.c
+d64cdcf38f7749dc7f77465e5b7d356d OX002-SW-98010-r0p0-00bet1/src/armCOMM_MaskTable.c
+ OX002-SW-98010-r0p0-00bet1/vc/
+ OX002-SW-98010-r0p0-00bet1/vc/m4p10/
+ OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/
+e7e0c320978564a7c9b2c723749a98d6 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_CAVLCTables.c
+4adcd0df081990bdfc4729041a2a9152 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
+852e0404142965dc1f3aa7f00ee5127b OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
+7054151c5bfea6b5e74feee86b2d7b01 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
+5f7213a4f37627b3c58f6294ba477e30 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_DequantTables_s.s
+32ff4b8be62e2f0f3e764b83c1e5e2fd OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
+d066e3c81d82616f37ec1810ea49e7b7 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
+fe629a3e9d55395a6098bdf2431b5f02 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
+5b13fb954b7679de20076bb6a7f4ee1d OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
+01ba60eff66ea49a4f833ce6279f8e2f OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
+fa1072cf1d17e9666c9f1e215fa302b1 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
+db387b9e66d32787f47ef9cf0347da2a OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
+ea537e4e2ad03a1940981055fa3ace01 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
+29a4283885b9473a3550a81eff2559d2 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
+2ddcaf60a8ea1e6e6b77737f768bfb9d OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_QuantTables_s.s
+c3002aad5600f872b70a5d7fe3915846 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
+a2900f2c47f1c61d20bd6c1eda33d6d4 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
+c921df73397a32c947dc996ba6858553 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
+3769e14f2fc3f514d025fe6ab73ff67a OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
+c029d1cebea0a09e1d235a37e2155002 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
+076a033f8161750a685756f9f51f04c9 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
+c5b5d22842822e6e5e31094882cbeb46 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
+f6bdf6d914a4a1479f524951a3409846 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
+ebeb0713a9b2ea25986360ef262138c4 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
+78ed9ea200faa7be665445a713859af1 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
+c2d995f787b6f44ef10c751c12d1935f OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
+40bed679a9f6e0d3efe216b7d4a9cf45 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
+4a52b3e9e268b8a8f07829bf500d03af OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
+11249f8a98c5d4b84cb5575b0e37ca9c OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
+2513b60559ba71ae495c6053fb779fa9 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
+2fb1ee17c36e3c1469c170f6dac11bf1 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
+cc4a6f32db0b72a91d3f278f6855df69 OX002-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
+ OX002-SW-98010-r0p0-00bet1/vc/m4p10/api/
+6e530ddaa7c2b57ffe88162c020cb662 OX002-SW-98010-r0p0-00bet1/vc/m4p10/api/armVCM4P10_CAVLCTables.h
+ OX002-SW-98010-r0p0-00bet1/vc/m4p2/
+ OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/
+bec6de348b113438498867b869001622 OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_Clip8_s.s
+dba9824e959b21d401cac925e68a11a6 OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
+dfa7e5b58027be3542dda0593b77b2d3 OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
+4fba4c431a783a78a2eb6497a94ac967 OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
+39991961179ca03b6381b6e653b1f14b OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
+1b0b2990c2669dfb87cf6b810611c01b OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
+1c9b87abf3283e957816b3937c680701 OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
+4fe1afca659a9055fc1172e58f78a506 OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
+2ea067f0436f91ba1351edaf411cb4ea OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_Lookup_Tables.c
+6ce363aadc9d65c308b40cca8902e4f6 OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
+bf212f786772aed2bc705d22ff4e74f5 OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
+293a48a648a3085456e6665bb7366fad OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_SetPredDir_s.s
+2bb47ed9c9e25c5709c6d9b4ad39a38a OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
+437dfa204508850d61d4b87091446e9f OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
+bc9778898dd41101dc0fb0139eaf83cc OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
+fc191eeae43f8ce735dbd311cc7bcb8d OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
+a0d85f4f517c945a4c9317ac021f2d08 OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
+386020dee8b725c7fe2526f1fc211d7d OX002-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
+ OX002-SW-98010-r0p0-00bet1/vc/m4p2/api/
+4624e7c838e10a249abcc3d3f4f40748 OX002-SW-98010-r0p0-00bet1/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
+65e1057d04e2cb844559dc9f6e09795a OX002-SW-98010-r0p0-00bet1/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
+ OX002-SW-98010-r0p0-00bet1/vc/src/
+e627b3346b0dc9aff14446005ce0fa43 OX002-SW-98010-r0p0-00bet1/vc/src/armVC_Version.c
+ OX002-SW-98010-r0p0-00bet1/vc/api/
+7ca94b1c33ac0211e17d38baadd7d1dd OX002-SW-98010-r0p0-00bet1/vc/api/armVC.h
+12cf7596edbbf6048b626d15e8d0ed48 OX002-SW-98010-r0p0-00bet1/vc/api/omxVC.h
+11726e286a81257cb45f5547fb4d374c OX002-SW-98010-r0p0-00bet1/vc/api/omxVC_s.h
+a5b2af605c319cd2491319e430741377 OX002-SW-98010-r0p0-00bet1/vc/api/armVCCOMM_s.h
+ OX002-SW-98010-r0p0-00bet1/vc/comm/
+ OX002-SW-98010-r0p0-00bet1/vc/comm/src/
+1f81187b48487a8ea6dbc327648e3e4f OX002-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_Copy16x16_s.s
+936d3f2038a6f8613ec25e50cc601fe8 OX002-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_Copy8x8_s.s
+8f6708a249130962e0bc5c044ac6dd93 OX002-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
+aab7713414428e95de0ba799a2679b36 ARM_DELIVERY_97414.TXT
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h
new file mode 100755
index 0000000..64c1958
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM.h
@@ -0,0 +1,785 @@
+/**
+ *
+ * File Name: armCOMM.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armCOMM.h
+ * Brief: Declares Common APIs/Data Types used across OpenMAX API's
+ *
+ */
+
+
+#ifndef _armCommon_H_
+#define _armCommon_H_
+
+#include "omxtypes.h"
+
+typedef struct
+{
+ OMX_F32 Re; /** Real part */
+ OMX_F32 Im; /** Imaginary part */
+
+} OMX_FC32; /** single precision floating point complex number */
+
+typedef struct
+{
+ OMX_F64 Re; /** Real part */
+ OMX_F64 Im; /** Imaginary part */
+
+} OMX_FC64; /** double precision floating point complex number */
+
+
+/* Used by both IP and IC domains for 8x8 JPEG blocks. */
+typedef OMX_S16 ARM_BLOCK8x8[64];
+
+
+#include "armOMX.h"
+
+#define armPI (OMX_F64)(3.1415926535897932384626433832795)
+
+/***********************************************************************/
+
+/* Compiler extensions */
+#ifdef ARM_DEBUG
+/* debug version */
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#define armError(str) {printf((str)); printf("\n"); exit(-1);}
+#define armWarn(str) {printf((str)); printf("\n");}
+#define armIgnore(a) ((void)a)
+#define armAssert(a) assert(a)
+#else
+/* release version */
+#define armError(str) ((void) (str))
+#define armWarn(str) ((void) (str))
+#define armIgnore(a) ((void) (a))
+#define armAssert(a) ((void) (a))
+#endif /* ARM_DEBUG */
+
+/* Arithmetic operations */
+
+#define armMin(a,b) ( (a) > (b) ? (b):(a) )
+#define armMax(a,b) ( (a) > (b) ? (a):(b) )
+#define armAbs(a) ( (a) < 0 ? -(a):(a) )
+
+/* Alignment operation */
+
+#define armAlignToBytes(Ptr,N) (Ptr + ( ((N-(int)Ptr)&(N-1)) / sizeof(*Ptr) ))
+#define armAlignTo2Bytes(Ptr) armAlignToBytes(Ptr,2)
+#define armAlignTo4Bytes(Ptr) armAlignToBytes(Ptr,4)
+#define armAlignTo8Bytes(Ptr) armAlignToBytes(Ptr,8)
+#define armAlignTo16Bytes(Ptr) armAlignToBytes(Ptr,16)
+
+/* Error and Alignment check */
+
+#define armRetArgErrIf(condition, code) if(condition) { return (code); }
+#define armRetDataErrIf(condition, code) if(condition) { return (code); }
+
+#ifndef ALIGNMENT_DOESNT_MATTER
+#define armIsByteAligned(Ptr,N) ((((int)(Ptr)) % N)==0)
+#define armNotByteAligned(Ptr,N) ((((int)(Ptr)) % N)!=0)
+#else
+#define armIsByteAligned(Ptr,N) (1)
+#define armNotByteAligned(Ptr,N) (0)
+#endif
+
+#define armIs2ByteAligned(Ptr) armIsByteAligned(Ptr,2)
+#define armIs4ByteAligned(Ptr) armIsByteAligned(Ptr,4)
+#define armIs8ByteAligned(Ptr) armIsByteAligned(Ptr,8)
+#define armIs16ByteAligned(Ptr) armIsByteAligned(Ptr,16)
+
+#define armNot2ByteAligned(Ptr) armNotByteAligned(Ptr,2)
+#define armNot4ByteAligned(Ptr) armNotByteAligned(Ptr,4)
+#define armNot8ByteAligned(Ptr) armNotByteAligned(Ptr,8)
+#define armNot16ByteAligned(Ptr) armNotByteAligned(Ptr,16)
+#define armNot32ByteAligned(Ptr) armNotByteAligned(Ptr,32)
+
+/**
+ * Function: armRoundFloatToS16_ref/armRoundFloatToS32_ref/armRoundFloatToS64
+ *
+ * Description:
+ * Converts a double precision value into a short int/int after rounding
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S16/OMX_S32 format
+ *
+ */
+
+OMX_S16 armRoundFloatToS16 (OMX_F64 Value);
+OMX_S32 armRoundFloatToS32 (OMX_F64 Value);
+OMX_S64 armRoundFloatToS64 (OMX_F64 Value);
+
+/**
+ * Function: armSatRoundFloatToS16_ref/armSatRoundFloatToS32
+ *
+ * Description:
+ * Converts a double precision value into a short int/int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S16/OMX_S32 format
+ *
+ */
+
+OMX_S16 armSatRoundFloatToS16 (OMX_F64 Value);
+OMX_S32 armSatRoundFloatToS32 (OMX_F64 Value);
+
+/**
+ * Function: armSatRoundFloatToU16_ref/armSatRoundFloatToU32
+ *
+ * Description:
+ * Converts a double precision value into a unsigned short int/int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_U16/OMX_U32 format
+ *
+ */
+
+OMX_U16 armSatRoundFloatToU16 (OMX_F64 Value);
+OMX_U32 armSatRoundFloatToU32 (OMX_F64 Value);
+
+/**
+ * Function: armSignCheck
+ *
+ * Description:
+ * Checks the sign of a variable:
+ * returns 1 if it is Positive
+ * returns 0 if it is 0
+ * returns -1 if it is Negative
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] var Variable to be checked
+ *
+ * Return Value:
+ * OMX_INT -- returns 1 if it is Positive
+ * returns 0 if it is 0
+ * returns -1 if it is Negative
+ */
+
+OMX_INT armSignCheck (OMX_S16 var);
+
+/**
+ * Function: armClip
+ *
+ * Description: Clips the input between MAX and MIN value
+ *
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] Min lower bound
+ * [in] Max upper bound
+ * [in] src variable to the clipped
+ *
+ * Return Value:
+ * OMX_S32 -- returns clipped value
+ */
+
+OMX_S32 armClip (
+ OMX_INT min,
+ OMX_INT max,
+ OMX_S32 src
+ );
+
+/**
+ * Function: armClip_F32
+ *
+ * Description: Clips the input between MAX and MIN value
+ *
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] Min lower bound
+ * [in] Max upper bound
+ * [in] src variable to the clipped
+ *
+ * Return Value:
+ * OMX_F32 -- returns clipped value
+ */
+
+OMX_F32 armClip_F32 (
+ OMX_F32 min,
+ OMX_F32 max,
+ OMX_F32 src
+ );
+
+/**
+ * Function: armShiftSat_F32
+ *
+ * Description: Divides a float value by 2^shift and
+ * saturates it for unsigned value range for satBits.
+ * Second parameter is like "shifting" the corresponding
+ * integer value. Takes care of rounding while clipping the final
+ * value.
+ *
+ * Parameters:
+ * [in] v Number to be operated upon
+ * [in] shift Divides the input "v" by "2^shift"
+ * [in] satBits Final range is [0, 2^satBits)
+ *
+ * Return Value:
+ * OMX_S32 -- returns "shifted" saturated value
+ */
+
+OMX_U32 armShiftSat_F32(
+ OMX_F32 v,
+ OMX_INT shift,
+ OMX_INT satBits
+ );
+
+/**
+ * Functions: armSwapElem
+ *
+ * Description:
+ * This function swaps two elements at the specified pointer locations.
+ * The size of each element could be anything as specified by <elemSize>
+ *
+ * Return Value:
+ * OMXResult -- Error status from the function
+ */
+OMXResult armSwapElem(OMX_U8 *pBuf1, OMX_U8 *pBuf2, OMX_INT elemSize);
+
+
+/**
+ * Function: armMedianOf3
+ *
+ * Description: Finds the median of three numbers
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] fEntry First entry
+ * [in] sEntry second entry
+ * [in] tEntry Third entry
+ *
+ * Return Value:
+ * OMX_S32 -- returns the median value
+ */
+
+OMX_S32 armMedianOf3 (
+ OMX_S32 fEntry,
+ OMX_S32 sEntry,
+ OMX_S32 tEntry
+ );
+
+/**
+ * Function: armLogSize
+ *
+ * Description: Finds the size of a positive value and returns the same
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] value Positive value
+ *
+ * Return Value:
+ * OMX_U8 -- returns the size of the positive value
+ */
+
+OMX_U8 armLogSize (
+ OMX_U16 value
+ );
+
+/***********************************************************************/
+ /* Saturating Arithmetic operations */
+
+/**
+ * Function :armSatAdd_S32()
+ *
+ * Description :
+ * Returns the result of saturated addition of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ *
+ **/
+
+OMX_S32 armSatAdd_S32(
+ OMX_S32 Value1,
+ OMX_S32 Value2
+ );
+
+/**
+ * Function :armSatAdd_S64()
+ *
+ * Description :
+ * Returns the result of saturated addition of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ *
+ **/
+
+OMX_S64 armSatAdd_S64(
+ OMX_S64 Value1,
+ OMX_S64 Value2
+ );
+
+/** Function :armSatSub_S32()
+ *
+ * Description :
+ * Returns the result of saturated substraction of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatSub_S32(
+ OMX_S32 Value1,
+ OMX_S32 Value2
+ );
+
+/**
+ * Function :armSatMac_S32()
+ *
+ * Description :
+ * Returns the result of Multiplication of Value1 and Value2 and subesquent saturated
+ * accumulation with Mac
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ * [in] Mac Accumulator
+ *
+ * Return:
+ * [out] Result of operation
+ **/
+
+OMX_S32 armSatMac_S32(
+ OMX_S32 Mac,
+ OMX_S16 Value1,
+ OMX_S16 Value2
+ );
+
+/**
+ * Function :armSatMac_S16S32_S32
+ *
+ * Description :
+ * Returns the result of saturated MAC operation of the three inputs delayElem, filTap , mac
+ *
+ * mac = mac + Saturate_in_32Bits(delayElem * filTap)
+ *
+ * Parametrs:
+ * [in] delayElem First 32 bit Operand
+ * [in] filTap Second 16 bit Operand
+ * [in] mac Result of MAC operation
+ *
+ * Return:
+ * [out] mac Result of operation
+ *
+ **/
+
+OMX_S32 armSatMac_S16S32_S32(
+ OMX_S32 mac,
+ OMX_S32 delayElem,
+ OMX_S16 filTap );
+
+/**
+ * Function :armSatRoundRightShift_S32_S16
+ *
+ * Description :
+ * Returns the result of rounded right shift operation of input by the scalefactor
+ *
+ * output = Saturate_in_16Bits( ( RightShift( (Round(input) , scaleFactor ) )
+ *
+ * Parametrs:
+ * [in] input The input to be operated on
+ * [in] scaleFactor The shift number
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+
+OMX_S16 armSatRoundRightShift_S32_S16(
+ OMX_S32 input,
+ OMX_INT scaleFactor);
+
+/**
+ * Function :armSatRoundLeftShift_S32()
+ *
+ * Description :
+ * Returns the result of saturating left-shift operation on input
+ * Or rounded Right shift if the input Shift is negative.
+ *
+ * Parametrs:
+ * [in] Value Operand
+ * [in] shift Operand for shift operation
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatRoundLeftShift_S32(
+ OMX_S32 Value,
+ OMX_INT shift
+ );
+
+/**
+ * Function :armSatRoundLeftShift_S64()
+ *
+ * Description :
+ * Returns the result of saturating left-shift operation on input
+ * Or rounded Right shift if the input Shift is negative.
+ *
+ * Parametrs:
+ * [in] Value Operand
+ * [in] shift Operand for shift operation
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S64 armSatRoundLeftShift_S64(
+ OMX_S64 Value,
+ OMX_INT shift
+ );
+
+/**
+ * Function :armSatMulS16S32_S32()
+ *
+ * Description :
+ * Returns the result of a S16 data type multiplied with an S32 data type
+ * in a S32 container
+ *
+ * Parametrs:
+ * [in] input1 Operand 1
+ * [in] input2 Operand 2
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+
+OMX_S32 armSatMulS16S32_S32(
+ OMX_S16 input1,
+ OMX_S32 input2);
+
+/**
+ * Function :armSatMulS32S32_S32()
+ *
+ * Description :
+ * Returns the result of a S32 data type multiplied with an S32 data type
+ * in a S32 container
+ *
+ * Parametrs:
+ * [in] input1 Operand 1
+ * [in] input2 Operand 2
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatMulS32S32_S32(
+ OMX_S32 input1,
+ OMX_S32 input2);
+
+
+/**
+ * Function :armIntDivAwayFromZero()
+ *
+ * Description : Integer division with rounding to the nearest integer.
+ * Half-integer values are rounded away from zero
+ * unless otherwise specified. For example 3//2 is rounded
+ * to 2, and -3//2 is rounded to -2.
+ *
+ * Parametrs:
+ * [in] Num Operand 1
+ * [in] Deno Operand 2
+ *
+ * Return:
+ * [out] Result of operation input1//input2
+ *
+ **/
+
+OMX_S32 armIntDivAwayFromZero (OMX_S32 Num, OMX_S32 Deno);
+
+
+/***********************************************************************/
+/*
+ * Debugging macros
+ *
+ */
+
+
+/*
+ * Definition of output stream - change to stderr if necessary
+ */
+#define DEBUG_STREAM stdout
+
+/*
+ * Debug printf macros, one for each argument count.
+ * Add more if needed.
+ */
+#ifdef DEBUG_ON
+#include <stdio.h>
+
+#define DEBUG_PRINTF_0(a) fprintf(DEBUG_STREAM, a)
+#define DEBUG_PRINTF_1(a, b) fprintf(DEBUG_STREAM, a, b)
+#define DEBUG_PRINTF_2(a, b, c) fprintf(DEBUG_STREAM, a, b, c)
+#define DEBUG_PRINTF_3(a, b, c, d) fprintf(DEBUG_STREAM, a, b, c, d)
+#define DEBUG_PRINTF_4(a, b, c, d, e) fprintf(DEBUG_STREAM, a, b, c, d, e)
+#define DEBUG_PRINTF_5(a, b, c, d, e, f) fprintf(DEBUG_STREAM, a, b, c, d, e, f)
+#define DEBUG_PRINTF_6(a, b, c, d, e, f, g) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g)
+#define DEBUG_PRINTF_7(a, b, c, d, e, f, g, h) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h)
+#define DEBUG_PRINTF_8(a, b, c, d, e, f, g, h, i) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i)
+#define DEBUG_PRINTF_9(a, b, c, d, e, f, g, h, i, j) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j)
+#define DEBUG_PRINTF_10(a, b, c, d, e, f, g, h, i, j, k) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k)
+#define DEBUG_PRINTF_11(a, b, c, d, e, f, g, h, i, j, k, l) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k, l)
+#define DEBUG_PRINTF_12(a, b, c, d, e, f, g, h, i, j, k, l, m) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k, l, m)
+#define DEBUG_PRINTF_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k, l, m, n)
+#define DEBUG_PRINTF_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
+#else /* DEBUG_ON */
+#define DEBUG_PRINTF_0(a)
+#define DEBUG_PRINTF_1(a, b)
+#define DEBUG_PRINTF_2(a, b, c)
+#define DEBUG_PRINTF_3(a, b, c, d)
+#define DEBUG_PRINTF_4(a, b, c, d, e)
+#define DEBUG_PRINTF_5(a, b, c, d, e, f)
+#define DEBUG_PRINTF_6(a, b, c, d, e, f, g)
+#define DEBUG_PRINTF_7(a, b, c, d, e, f, g, h)
+#define DEBUG_PRINTF_8(a, b, c, d, e, f, g, h, i)
+#define DEBUG_PRINTF_9(a, b, c, d, e, f, g, h, i, j)
+#define DEBUG_PRINTF_10(a, b, c, d, e, f, g, h, i, j, k)
+#define DEBUG_PRINTF_11(a, b, c, d, e, f, g, h, i, j, k, l)
+#define DEBUG_PRINTF_12(a, b, c, d, e, f, g, h, i, j, k, l, m)
+#define DEBUG_PRINTF_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n)
+#define DEBUG_PRINTF_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
+#endif /* DEBUG_ON */
+
+
+/*
+ * Domain and sub domain definitions
+ *
+ * In order to turn on debug for an entire domain or sub-domain
+ * at compile time, one of the DEBUG_DOMAIN_* below may be defined,
+ * which will activate debug in all of the defines it contains.
+ */
+
+#ifdef DEBUG_DOMAIN_AC
+#define DEBUG_OMXACAAC_DECODECHANPAIRELT_MPEG4
+#define DEBUG_OMXACAAC_DECODECHANPAIRELT
+#define DEBUG_OMXACAAC_DECODEDATSTRELT
+#define DEBUG_OMXACAAC_DECODEFILLELT
+#define DEBUG_OMXACAAC_DECODEISSTEREO_S32
+#define DEBUG_OMXACAAC_DECODEMSPNS_S32
+#define DEBUG_OMXACAAC_DECODEMSSTEREO_S32_I
+#define DEBUG_OMXACAAC_DECODEPRGCFGELT
+#define DEBUG_OMXACAAC_DECODETNS_S32_I
+#define DEBUG_OMXACAAC_DEINTERLEAVESPECTRUM_S32
+#define DEBUG_OMXACAAC_ENCODETNS_S32_I
+#define DEBUG_OMXACAAC_LONGTERMPREDICT_S32
+#define DEBUG_OMXACAAC_LONGTERMRECONSTRUCT_S32
+#define DEBUG_OMXACAAC_MDCTFWD_S32
+#define DEBUG_OMXACAAC_MDCTINV_S32_S16
+#define DEBUG_OMXACAAC_NOISELESSDECODE
+#define DEBUG_OMXACAAC_QUANTINV_S32_I
+#define DEBUG_OMXACAAC_UNPACKADIFHEADER
+#define DEBUG_OMXACAAC_UNPACKADTSFRAMEHEADER
+#define DEBUG_OMXACMP3_HUFFMANDECODESFBMBP_S32
+#define DEBUG_OMXACMP3_HUFFMANDECODESFB_S32
+#define DEBUG_OMXACMP3_HUFFMANDECODE_S32
+#define DEBUG_OMXACMP3_MDCTINV_S32
+#define DEBUG_OMXACMP3_REQUANTIZESFB_S32_I
+#define DEBUG_OMXACMP3_REQUANTIZE_S32_I
+#define DEBUG_OMXACMP3_SYNTHPQMF_S32_S16
+#define DEBUG_OMXACMP3_UNPACKFRAMEHEADER
+#define DEBUG_OMXACMP3_UNPACKSCALEFACTORS_S8
+#define DEBUG_OMXACMP3_UNPACKSIDEINFO
+#endif /* DEBUG_DOMAIN_AC */
+
+
+#ifdef DEBUG_DOMAIN_VC
+#define DEBUG_OMXVCM4P10_AVERAGE_16X
+#define DEBUG_OMXVCM4P10_AVERAGE_4X
+#define DEBUG_OMXVCM4P10_AVERAGE_8X
+#define DEBUG_OMXVCM4P10_DEBLOCKCHROMA_U8_C1IR
+#define DEBUG_OMXVCM4P10_DEBLOCKLUMA_U8_C1IR
+#define DEBUG_OMXVCM4P10_DECODECHROMADCCOEFFSTOPAIRCAVLC_U8
+#define DEBUG_OMXVCM4P10_DECODECOEFFSTOPAIRCAVLC_U8
+#define DEBUG_OMXVCM4P10_DEQUANTTRANSFORMACFROMPAIR_U8_S16_C1_DLX
+#define DEBUG_OMXVCM4P10_EXPANDFRAME
+#define DEBUG_OMXVCM4P10_FILTERDEBLOCKINGCHROMA_HOREDGE_U8_C1IR
+#define DEBUG_OMXVCM4P10_FILTERDEBLOCKINGCHROMA_VEREDGE_U8_C1IR
+#define DEBUG_OMXVCM4P10_FILTERDEBLOCKINGLUMA_HOREDGE_U8_C1IR
+#define DEBUG_OMXVCM4P10_FILTERDEBLOCKINGLUMA_VEREDGE_U8_C1IR
+#define DEBUG_OMXVCM4P10_PREDICTINTRACHROMA8X8_U8_C1R
+#define DEBUG_OMXVCM4P10_PREDICTINTRA_16X16_U8_C1R
+#define DEBUG_OMXVCM4P10_PREDICTINTRA_4X4_U8_C1R
+#define DEBUG_OMXVCM4P10_SADQUAR_16X
+#define DEBUG_OMXVCM4P10_SADQUAR_4X
+#define DEBUG_OMXVCM4P10_SADQUAR_8X
+#define DEBUG_OMXVCM4P10_SAD_16X
+#define DEBUG_OMXVCM4P10_SAD_4X
+#define DEBUG_OMXVCM4P10_SAD_8X
+#define DEBUG_OMXVCM4P10_SATD_4X4
+#define DEBUG_OMXVCM4P10_TRANSFORMDEQUANTCHROMADCFROMPAIR_U8_S16_C1
+#define DEBUG_OMXVCM4P10_TRANSFORMDEQUANTLUMADCFROMPAIR_U8_S16_C1
+#define DEBUG_OMXVCM4P10_TRANSFORMQUANT_CHROMADC
+#define DEBUG_OMXVCM4P10_TRANSFORMQUANT_LUMADC
+#define DEBUG_OMXVCM4P2_BLOCKMATCH_HALF_16X16
+#define DEBUG_OMXVCM4P2_BLOCKMATCH_HALF_8X8
+#define DEBUG_OMXVCM4P2_BLOCKMATCH_INTEGER_16X16
+#define DEBUG_OMXVCM4P2_BLOCKMATCH_INTEGER_8X8
+#define DEBUG_OMXVCM4P2_COMPUTETEXTUREERRORBLOCK_SAD_U8_S16
+#define DEBUG_OMXVCM4P2_COMPUTETEXTUREERRORBLOCK_U8_S16
+#define DEBUG_OMXVCM4P2_DCT8X8BLKDLX
+#define DEBUG_OMXVCM4P2_DECODEBLOCKCOEF_INTER_S16
+#define DEBUG_OMXVCM4P2_DECODEPADMV_PVOP
+#define DEBUG_OMXVCM4P2_DECODEVLCZIGZAG_INTER_S16
+#define DEBUG_OMXVCM4P2_DECODEVLCZIGZAG_INTRAACVLC_S16
+#define DEBUG_OMXVCM4P2_DECODEVLCZIGZAG_INTRADCVLC_S16
+#define DEBUG_OMXVCM4P2_ENCODEMV_U8_S16
+#define DEBUG_OMXVCM4P2_ENCODEVLCZIGZAG_INTER_S16
+#define DEBUG_OMXVCM4P2_ENCODEVLCZIGZAG_INTRAACVLC_S16
+#define DEBUG_OMXVCM4P2_ENCODEVLCZIGZAG_INTRADCVLC_S16
+#define DEBUG_OMXVCM4P2_FINDMVPRED
+#define DEBUG_OMXVCM4P2_IDCT8X8BLKDLX
+#define DEBUG_OMXVCM4P2_LIMITMVTORECT
+#define DEBUG_OMXVCM4P2_MOTIONESTIMATIONMB
+#define DEBUG_OMXVCM4P2_PADMBGRAY_U8
+#define DEBUG_OMXVCM4P2_PADMBHORIZONTAL_U8
+#define DEBUG_OMXVCM4P2_PADMBVERTICAL_U8
+#define DEBUG_OMXVCM4P2_PADMV
+#define DEBUG_OMXVCM4P2_QUANTINTER_S16_I
+#define DEBUG_OMXVCM4P2_QUANTINTRA_S16_I
+#define DEBUG_OMXVCM4P2_QUANTINVINTER_S16_I
+#define DEBUG_OMXVCM4P2_QUANTINVINTRA_S16_I
+#define DEBUG_OMXVCM4P2_TRANSRECBLOCKCEOF_INTER
+#define DEBUG_OMXVCM4P2_TRANSRECBLOCKCEOF_INTRA
+#endif /* DEBUG_DOMAIN_VC */
+
+
+#ifdef DEBUG_DOMAIN_IC
+/* To be filled in */
+#endif /* DEBUG_DOMAIN_IC */
+
+
+#ifdef DEBUG_DOMAIN_SP
+#define DEBUG_OMXACSP_DOTPROD_S16
+#define DEBUG_OMXACSP_BLOCKEXP_S16
+#define DEBUG_OMXACSP_BLOCKEXP_S32
+#define DEBUG_OMXACSP_COPY_S16
+#define DEBUG_OMXACSP_DOTPROD_S16
+#define DEBUG_OMXACSP_DOTPROD_S16_SFS
+#define DEBUG_OMXACSP_FFTFWD_CTOC_SC16_SFS
+#define DEBUG_OMXACSP_FFTFWD_CTOC_SC32_SFS
+#define DEBUG_OMXACSP_FFTFWD_RTOCCS_S16S32_SFS
+#define DEBUG_OMXACSP_FFTFWD_RTOCCS_S32_SFS
+#define DEBUG_OMXACSP_FFTGETBUFSIZE_C_SC16
+#define DEBUG_OMXACSP_FFTGETBUFSIZE_C_SC32
+#define DEBUG_OMXACSP_FFTGETBUFSIZE_R_S16_S32
+#define DEBUG_OMXACSP_FFTGETBUFSIZE_R_S32
+#define DEBUG_OMXACSP_FFTINIT_C_SC16
+#define DEBUG_OMXACSP_FFTINIT_C_SC32
+#define DEBUG_OMXACSP_FFTINIT_R_S16_S32
+#define DEBUG_OMXACSP_FFTINIT_R_S32
+#define DEBUG_OMXACSP_FFTINV_CCSTOR_S32S16_SFS
+#define DEBUG_OMXACSP_FFTINV_CCSTOR_S32_SFS
+#define DEBUG_OMXACSP_FFTINV_CTOC_SC16_SFS
+#define DEBUG_OMXACSP_FFTINV_CTOC_SC32_SFS
+#define DEBUG_OMXACSP_FILTERMEDIAN_S32_I
+#define DEBUG_OMXACSP_FILTERMEDIAN_S32
+#define DEBUG_OMXACSP_FIRONE_DIRECT_S16_ISFS
+#define DEBUG_OMXACSP_FIRONE_DIRECT_S16_I
+#define DEBUG_OMXACSP_FIRONE_DIRECT_S16
+#define DEBUG_OMXACSP_FIRONE_DIRECT_S16_SFS
+#define DEBUG_OMXACSP_FIR_DIRECT_S16_ISFS
+#define DEBUG_OMXACSP_FIR_DIRECT_S16_I
+#define DEBUG_OMXACSP_FIR_DIRECT_S16
+#define DEBUG_OMXACSP_FIR_DIRECT_S16_SFS
+#define DEBUG_OMXACSP_IIRONE_BIQUADDIRECT_S16_I
+#define DEBUG_OMXACSP_IIRONE_BIQUADDIRECT_S16
+#define DEBUG_OMXACSP_IIRONE_DIRECT_S16_I
+#define DEBUG_OMXACSP_IIRONE_DIRECT_S16
+#define DEBUG_OMXACSP_IIR_BIQUADDIRECT_S16_I
+#define DEBUG_OMXACSP_IIR_BIQUADDIRECT_S16
+#define DEBUG_OMXACSP_IIR_DIRECT_S16_I
+#define DEBUG_OMXACSP_IIR_DIRECT_S16
+#endif /* DEBUG_DOMAIN_SP */
+
+
+#ifdef DEBUG_DOMAIN_IP
+#define DEBUG_OMXIPBM_ADDC_U8_C1R_SFS
+#define DEBUG_OMXIPBM_COPY_U8_C1R
+#define DEBUG_OMXIPBM_COPY_U8_C3R
+#define DEBUG_OMXIPBM_MIRROR_U8_C1R
+#define DEBUG_OMXIPBM_MULC_U8_C1R_SFS
+#define DEBUG_OMXIPCS_COLORTWISTQ14_U8_C3R
+#define DEBUG_OMXIPCS_RGB565TOYCBCR420LS_MCU_U16_S16_C3P3R
+#define DEBUG_OMXIPCS_RGB565TOYCBCR422LS_MCU_U16_S16_C3P3R
+#define DEBUG_OMXIPCS_RGB565TOYCBCR444LS_MCU_U16_S16_C3P3R
+#define DEBUG_OMXIPCS_RGBTOYCBCR420LS_MCU_U8_S16_C3P3R
+#define DEBUG_OMXIPCS_RGBTOYCBCR422LS_MCU_U8_S16_C3P3R
+#define DEBUG_OMXIPCS_RGBTOYCBCR444LS_MCU_U8_S16_C3P3R
+#define DEBUG_OMXIPCS_YCBCR420RSZROT_U8_P3R
+#define DEBUG_OMXIPCS_YCBCR420TORGB565LS_MCU_S16_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCR420TORGB565_U8_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCR420TORGBLS_MCU_S16_U8_P3C3R
+#define DEBUG_OMXIPCS_YCBCR422RSZCSCROTRGB_U8_C2R
+#define DEBUG_OMXIPCS_YCBCR422RSZROT_U8_P3R
+#define DEBUG_OMXIPCS_YCBCR422TORGB565LS_MCU_S16_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCR422TORGB565_U8_U16_C2C3R
+#define DEBUG_OMXIPCS_YCBCR422TORGBLS_MCU_S16_U8_P3C3R
+#define DEBUG_OMXIPCS_YCBCR422TORGB_U8_C2C3R
+#define DEBUG_OMXIPCS_YCBCR422TOYCBCR420ROTATE_U8_C2P3R
+#define DEBUG_OMXIPCS_YCBCR422TOYCBCR420ROTATE_U8_P3R
+#define DEBUG_OMXIPCS_YCBCR444TORGB565LS_MCU_S16_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCR444TORGBLS_MCU_S16_U8_P3C3R
+#define DEBUG_OMXIPCS_YCBCRTORGB565_U8_U16_C3R
+#define DEBUG_OMXIPCS_YCBCRTORGB565_U8_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCRTORGB_U8_C3R
+#define DEBUG_OMXIPPP_GETCENTRALMOMENT_S64
+#define DEBUG_OMXIPPP_GETSPATIALMOMENT_S64
+#define DEBUG_OMXIPPP_MOMENTGETSTATESIZE_S64
+#define DEBUG_OMXIPPP_MOMENTINIT_S64
+#define DEBUG_OMXIPPP_MOMENTS64S_U8_C1R
+#define DEBUG_OMXIPPP_MOMENTS64S_U8_C3R
+#endif /* DEBUG_DOMAIN_IP */
+
+
+#endif /* _armCommon_H_ */
+
+/*End of File*/
+
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_BitDec_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_BitDec_s.h
new file mode 100755
index 0000000..c738f72
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_BitDec_s.h
@@ -0,0 +1,670 @@
+;//
+;//
+;// File Name: armCOMM_BitDec_s.h
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// OpenMAX optimized bitstream decode module
+;//
+;// You must include armCOMM_s.h before including this file
+;//
+;// This module provides macros to perform assembly optimized fixed and
+;// variable length decoding from a read-only bitstream. The variable
+;// length decode modules take as input a pointer to a table of 16-bit
+;// entries of the following format.
+;//
+;// VLD Table Entry format
+;//
+;// 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+;// +------------------------------------------------+
+;// | Len | Symbol | 1 |
+;// +------------------------------------------------+
+;// | Offset | 0 |
+;// +------------------------------------------------+
+;//
+;// If the table entry is a leaf entry then bit 0 set:
+;// Len = Number of bits overread (0 to 7)
+;// Symbol = Symbol payload (unsigned 12 bits)
+;//
+;// If the table entry is an internal node then bit 0 is clear:
+;// Offset = Number of (16-bit) half words from the table
+;// start to the next table node
+;//
+;// The table is accessed by successive lookup up on the
+;// next Step bits of the input bitstream until a leaf node
+;// is obtained. The Step sizes are supplied to the VLD macro.
+;//
+;// USAGE:
+;//
+;// To use any of the macros in this package, first call:
+;//
+;// M_BD_INIT ppBitStream, pBitOffset, pBitStream, RBitBuffer, RBitCount, Tmp
+;//
+;// This caches the current bitstream position and next available
+;// bits in registers pBitStream, RBitBuffer, RBitCount. These registers
+;// are reserved for use by the bitstream decode package until you
+;// call M_BD_FINI.
+;//
+;// Next call the following macro(s) as many times as you need:
+;//
+;// M_BD_LOOK8 - Look ahead constant 1<=N<=8 bits into the bitstream
+;// M_BD_LOOK16 - Look ahead constant 1<=N<=16 bits into the bitstream
+;// M_BD_READ8 - Read constant 1<=N<=8 bits from the bitstream
+;// M_BD_READ16 - Read constant 1<=N<=16 bits from the bitstream
+;// M_BD_VREAD8 - Read variable 1<=N<=8 bits from the bitstream
+;// M_BD_VREAD16 - Read variable 1<=N<=16 bits from the bitstream
+;// M_BD_VLD - Perform variable length decode using lookup table
+;//
+;// Finally call the macro:
+;//
+;// M_BD_FINI ppBitStream, pBitOffset
+;//
+;// This writes the bitstream state back to memory.
+;//
+;// The three bitstream cache register names are assigned to the following global
+;// variables:
+;//
+
+ GBLS pBitStream ;// Register name for pBitStream
+ GBLS BitBuffer ;// Register name for BitBuffer
+ GBLS BitCount ;// Register name for BitCount
+
+;//
+;// These register variables must have a certain defined state on entry to every bitstream
+;// macro (except M_BD_INIT) and on exit from every bitstream macro (except M_BD_FINI).
+;// The state may depend on implementation.
+;//
+;// For the default (ARM11) implementation the following hold:
+;// pBitStream - points to the first byte not held in the BitBuffer
+;// BitBuffer - is a cache of (4 bytes) 32 bits, bit 31 the first bit
+;// BitCount - is offset (from the top bit) to the next unused bitstream bit
+;// 0<=BitCount<=15 (so BitBuffer holds at least 17 unused bits)
+;//
+;//
+
+ ;// Bitstream Decode initialise
+ ;//
+ ;// Initialises the bitstream decode global registers from
+ ;// bitstream pointers. This macro is split into 3 parts to enable
+ ;// scheduling.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $ppBitStream - pointer to pointer to the next bitstream byte
+ ;// $pBitOffset - pointer to the number of bits used in the current byte (0..7)
+ ;// $RBitStream - register to use for pBitStream (can be $ppBitStream)
+ ;// $RBitBuffer - register to use for BitBuffer
+ ;// $RBitCount - register to use for BitCount (can be $pBitOffset)
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $T1,$T2,$T3 - registers that must be preserved between calls to
+ ;// M_BD_INIT1 and M_BD_INIT2
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_INIT0 $ppBitStream, $pBitOffset, $RBitStream, $RBitBuffer, $RBitCount
+
+pBitStream SETS "$RBitStream"
+BitBuffer SETS "$RBitBuffer"
+BitCount SETS "$RBitCount"
+
+ ;// load inputs
+ LDR $pBitStream, [$ppBitStream]
+ LDR $BitCount, [$pBitOffset]
+ MEND
+
+ MACRO
+ M_BD_INIT1 $T1, $T2, $T3
+ LDRB $T2, [$pBitStream, #2]
+ LDRB $T1, [$pBitStream, #1]
+ LDRB $BitBuffer, [$pBitStream], #3
+ ADD $BitCount, $BitCount, #8
+ MEND
+
+ MACRO
+ M_BD_INIT2 $T1, $T2, $T3
+ ORR $T2, $T2, $T1, LSL #8
+ ORR $BitBuffer, $T2, $BitBuffer, LSL #16
+ MEND
+
+ ;//
+ ;// Look ahead fixed 1<=N<=8 bits without consuming any bits
+ ;// The next bits will be placed at bit 31..24 of destination register
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits to look
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the next N bits of the bitstream
+ ;// $T1 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_LOOK8 $Symbol, $N
+ ASSERT ($N>=1):LAND:($N<=8)
+ MOV $Symbol, $BitBuffer, LSL $BitCount
+ MEND
+
+ ;//
+ ;// Look ahead fixed 1<=N<=16 bits without consuming any bits
+ ;// The next bits will be placed at bit 31..16 of destination register
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits to look
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the next N bits of the bitstream
+ ;// $T1 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_LOOK16 $Symbol, $N, $T1
+ ASSERT ($N >= 1):LAND:($N <= 16)
+ MOV $Symbol, $BitBuffer, LSL $BitCount
+ MEND
+
+ ;//
+ ;// Skips fixed 1<=N<=8 bits from the bitstream, advancing the bitstream pointer
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $T1 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_SKIP8 $N, $T1
+ ASSERT ($N>=1):LAND:($N<=8)
+ SUBS $BitCount, $BitCount, #(8-$N)
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+
+ ;//
+ ;// Read fixed 1<=N<=8 bits from the bitstream, advancing the bitstream pointer
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits to read
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the next N bits of the bitstream
+ ;// $T1 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_READ8 $Symbol, $N, $T1
+ ASSERT ($N>=1):LAND:($N<=8)
+ MOVS $Symbol, $BitBuffer, LSL $BitCount
+ SUBS $BitCount, $BitCount, #(8-$N)
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ MOV $Symbol, $Symbol, LSR #(32-$N)
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+ ;//
+ ;// Read fixed 1<=N<=16 bits from the bitstream, advancing the bitstream pointer
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits to read
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the next N bits of the bitstream
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_READ16 $Symbol, $N, $T1, $T2
+ ASSERT ($N>=1):LAND:($N<=16)
+ ASSERT $Symbol<>$T1
+ IF ($N<=8)
+ M_BD_READ8 $Symbol, $N, $T1
+ ELSE
+ ;// N>8 so we will be able to refill at least one byte
+ LDRB $T1, [$pBitStream], #1
+ MOVS $Symbol, $BitBuffer, LSL $BitCount
+ ORR $BitBuffer, $T1, $BitBuffer, LSL #8
+ SUBS $BitCount, $BitCount, #(16-$N)
+ LDRCSB $T1, [$pBitStream], #1
+ MOV $Symbol, $Symbol, LSR #(32-$N)
+ ADDCC $BitCount, $BitCount, #8
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ ENDIF
+ MEND
+
+ ;//
+ ;// Skip variable 1<=N<=8 bits from the bitstream, advancing the bitstream pointer.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits. 1<=N<=8
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_VSKIP8 $N, $T1
+ ADD $BitCount, $BitCount, $N
+ SUBS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+ ;//
+ ;// Skip variable 1<=N<=16 bits from the bitstream, advancing the bitstream pointer.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits. 1<=N<=16
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_VSKIP16 $N, $T1, $T2
+ ADD $BitCount, $BitCount, $N
+ SUBS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ SUBCSS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+ ;//
+ ;// Read variable 1<=N<=8 bits from the bitstream, advancing the bitstream pointer.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits to read. 1<=N<=8
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the next N bits of the bitstream
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_VREAD8 $Symbol, $N, $T1, $T2
+ MOV $Symbol, $BitBuffer, LSL $BitCount
+ ADD $BitCount, $BitCount, $N
+ SUBS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ RSB $T2, $N, #32
+ ADDCC $BitCount, $BitCount, #8
+ MOV $Symbol, $Symbol, LSR $T2
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+
+ ;//
+ ;// Read variable 1<=N<=16 bits from the bitstream, advancing the bitstream pointer.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $N - number of bits to read. 1<=N<=16
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the next N bits of the bitstream
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_VREAD16 $Symbol, $N, $T1, $T2
+ MOV $Symbol, $BitBuffer, LSL $BitCount
+ ADD $BitCount, $BitCount, $N
+ SUBS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ RSB $T2, $N, #32
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ SUBCSS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ MOV $Symbol, $Symbol, LSR $T2
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+
+ ;//
+ ;// Decode a code of the form 0000...001 where there
+ ;// are N zeros before the 1 and N<=15 (code length<=16)
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the number of zeros before the next 1
+ ;// >=16 is an illegal code
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_CLZ16 $Symbol, $T1, $T2
+ MOVS $Symbol, $BitBuffer, LSL $BitCount
+ CLZ $Symbol, $Symbol
+ ADD $BitCount, $BitCount, $Symbol
+ SUBS $BitCount, $BitCount, #7 ;// length is Symbol+1
+ LDRCSB $T1, [$pBitStream], #1
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ SUBCSS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+ ;//
+ ;// Decode a code of the form 1111...110 where there
+ ;// are N ones before the 0 and N<=15 (code length<=16)
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - the number of zeros before the next 1
+ ;// >=16 is an illegal code
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_CLO16 $Symbol, $T1, $T2
+ MOV $Symbol, $BitBuffer, LSL $BitCount
+ MVN $Symbol, $Symbol
+ CLZ $Symbol, $Symbol
+ ADD $BitCount, $BitCount, $Symbol
+ SUBS $BitCount, $BitCount, #7 ;// length is Symbol+1
+ LDRCSB $T1, [$pBitStream], #1
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ SUBCSS $BitCount, $BitCount, #8
+ LDRCSB $T1, [$pBitStream], #1
+ ADDCC $BitCount, $BitCount, #8
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8
+ MEND
+
+
+ ;//
+ ;// Variable Length Decode module
+ ;//
+ ;// Decodes one VLD Symbol from a bitstream and refill the bitstream
+ ;// buffer.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $pVLDTable - pointer to VLD decode table of 16-bit entries.
+ ;// The format is described above at the start of
+ ;// this file.
+ ;// $S0 - The number of bits to look up for the first step
+ ;// 1<=$S0<=8
+ ;// $S1 - The number of bits to look up for each subsequent
+ ;// step 1<=$S1<=$S0.
+ ;//
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $Symbol - decoded VLD symbol value
+ ;// $T1 - corrupted temp/scratch register
+ ;// $T2 - corrupted temp/scratch register
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_VLD $Symbol, $T1, $T2, $pVLDTable, $S0, $S1
+ ASSERT (1<=$S0):LAND:($S0<=8)
+ ASSERT (1<=$S1):LAND:($S1<=$S0)
+
+ ;// Note 0<=BitCount<=15 on entry and exit
+
+ MOVS $T1, $BitBuffer, LSL $BitCount ;// left align next bits
+ MOVS $Symbol, #(2<<$S0)-2 ;// create mask
+ AND $Symbol, $Symbol, $T1, LSR #(31-$S0) ;// 2*(next $S0 bits)
+ SUBS $BitCount, $BitCount, #8 ;// CS if buffer can be filled
+01
+ LDRCSB $T1, [$pBitStream], #1 ;// load refill byte
+ LDRH $Symbol, [$pVLDTable, $Symbol] ;// load table entry
+ ADDCC $BitCount, $BitCount, #8 ;// refill not possible
+ ADD $BitCount, $BitCount, #$S0 ;// assume $S0 bits used
+ ORRCS $BitBuffer, $T1, $BitBuffer, LSL #8 ;// merge in refill byte
+ MOVS $T1, $Symbol, LSR #1 ;// CS=leaf entry
+ BCS %FT02
+
+ MOVS $T1, $BitBuffer, LSL $BitCount ;// left align next bit
+ IF (2*$S0-$S1<=8)
+ ;// Can combine refill check and -S0+S1 and keep $BitCount<=15
+ SUBS $BitCount, $BitCount, #8+($S0-$S1)
+ ELSE
+ ;// Separate refill check and -S0+S1 offset
+ SUBS $BitCount, $BitCount, #8
+ SUB $BitCount, $BitCount, #($S0-$S1)
+ ENDIF
+ ADD $Symbol, $Symbol, $T1, LSR #(31-$S1) ;// add 2*(next $S1 bits) to
+ BIC $Symbol, $Symbol, #1 ;// table offset
+ B %BT01 ;// load next table entry
+02
+ ;// BitCount range now depend on the route here
+ ;// if (first step) S0 <= BitCount <= 7+S0 <=15
+ ;// else if (2*S0-S1<=8) S0 <= BitCount <= 7+(2*S0-S1) <=15
+ ;// else S1 <= BitCount <= 7+S1 <=15
+
+ SUB $BitCount, $BitCount, $Symbol, LSR#13
+ BIC $Symbol, $T1, #0xF000
+ MEND
+
+
+ ;// Add an offset number of bits
+ ;//
+ ;// Outputs destination byte and bit index values which corresponds to an offset number of bits
+ ;// from the current location. This is used to compare bitstream positions using. M_BD_CMP.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $Offset - Offset to be added in bits.
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $ByteIndex - Destination pBitStream pointer after adding the Offset.
+ ;// This value will be 4 byte ahead and needs to subtract by 4 to get exact
+ ;// pointer (as in M_BD_FINI). But for using with M_BD_CMP subtract is not needed.
+ ;// $BitIndex - Destination BitCount after the addition of Offset number of bits
+ ;//
+ MACRO
+ M_BD_ADD $ByteIndex, $BitIndex, $Offset
+
+ ;// ($ByteIndex,$BitIndex) = Current position + $Offset bits
+ ADD $Offset, $Offset, $BitCount
+ AND $BitIndex, $Offset, #7
+ ADD $ByteIndex, $pBitStream, $Offset, ASR #3
+ MEND
+
+ ;// Move bitstream pointers to the location given
+ ;//
+ ;// Outputs destination byte and bit index values which corresponds to
+ ;// the current location given (calculated using M_BD_ADD).
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;// $ByteIndex - Destination pBitStream pointer after move.
+ ;// This value will be 4 byte ahead and needs to subtract by 4 to get exact
+ ;// pointer (as in M_BD_FINI).
+ ;// $BitIndex - Destination BitCount after the move
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $pBitStream \
+ ;// } See description above.
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_MOV $ByteIndex, $BitIndex
+
+ ;// ($pBitStream, $Offset) = ($ByteIndex,$BitIndex)
+ MOV $BitCount, $BitIndex
+ MOV $pBitStream, $ByteIndex
+ MEND
+
+ ;// Bitstream Compare
+ ;//
+ ;// Compares bitstream position with that of a destination position. Destination position
+ ;// is held in two input registers which are calculated using M_BD_ADD macro
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $ByteIndex - Destination pBitStream pointer, (4 byte ahead as described in M_BD_ADD)
+ ;// $BitIndex - Destination BitCount
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// FLAGS - GE if destination is reached, LT = is destination is ahead
+ ;// $T1 - corrupted temp/scratch register
+ ;//
+ MACRO
+ M_BD_CMP $ByteIndex, $BitIndex, $T1
+
+ ;// Return flags set by (current positon)-($ByteIndex,$BitIndex)
+ ;// so GE means that we have reached the indicated position
+
+ ADD $T1, $pBitStream, $BitCount, LSR #3
+ CMP $T1, $ByteIndex
+ AND $T1, $BitCount, #7
+ CMPEQ $T1, $BitIndex
+ MEND
+
+
+ ;// Bitstream Decode finalise
+ ;//
+ ;// Writes back the bitstream state to the bitstream pointers
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $pBitStream \
+ ;// $BitBuffer } See description above.
+ ;// $BitCount /
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $ppBitStream - pointer to pointer to the next bitstream byte
+ ;// $pBitOffset - pointer to the number of bits used in the current byte (0..7)
+ ;// $pBitStream \
+ ;// $BitBuffer } these register are corrupted
+ ;// $BitCount /
+ ;//
+ MACRO
+ M_BD_FINI $ppBitStream, $pBitOffset
+
+ ;// Advance pointer by the number of free bits in the buffer
+ ADD $pBitStream, $pBitStream, $BitCount, LSR#3
+ AND $BitCount, $BitCount, #7
+
+ ;// Now move back 32 bits to reach the first usued bit
+ SUB $pBitStream, $pBitStream, #4
+
+ ;// Store out bitstream state
+ STR $BitCount, [$pBitOffset]
+ STR $pBitStream, [$ppBitStream]
+ MEND
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Bitstream.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Bitstream.h
new file mode 100755
index 0000000..b699034
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Bitstream.h
@@ -0,0 +1,212 @@
+/**
+ *
+ * File Name: armCOMM_Bitstream.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armCOMM_Bitstream.h
+ * Brief: Declares common API's/Data types used across the OpenMax Encoders/Decoders.
+ *
+ */
+
+#ifndef _armCodec_H_
+#define _armCodec_H_
+
+#include "omxtypes.h"
+
+typedef struct {
+ OMX_U8 codeLen;
+ OMX_U32 codeWord;
+} ARM_VLC32;
+
+/* The above should be renamed as "ARM_VLC32" */
+
+/**
+ * Function: armLookAheadBits()
+ *
+ * Description:
+ * Get the next N bits from the bitstream without advancing the bitstream pointer
+ *
+ * Parameters:
+ * [in] **ppBitStream
+ * [in] *pOffset
+ * [in] N=1...32
+ *
+ * Returns Value
+ */
+
+OMX_U32 armLookAheadBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N);
+
+/**
+ * Function: armGetBits()
+ *
+ * Description:
+ * Read N bits from the bitstream
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ * [in] N=1..32
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ * Returns Value
+ */
+
+OMX_U32 armGetBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N);
+
+/**
+ * Function: armByteAlign()
+ *
+ * Description:
+ * Align the pointer *ppBitStream to the next byte boundary
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ *
+ **/
+
+OMXVoid armByteAlign(const OMX_U8 **ppBitStream,OMX_INT *pOffset);
+
+/**
+ * Function: armSkipBits()
+ *
+ * Description:
+ * Skip N bits from the value at *ppBitStream
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ * [in] N
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ *
+ **/
+
+OMXVoid armSkipBits(const OMX_U8 **ppBitStream,OMX_INT *pOffset,OMX_INT N);
+
+/***************************************
+ * Variable bit length Decode
+ ***************************************/
+
+/**
+ * Function: armUnPackVLC32()
+ *
+ * Description:
+ * Variable length decode of variable length symbol (max size 32 bits) read from
+ * the bit stream pointed by *ppBitStream at *pOffset by using the table
+ * pointed by pCodeBook
+ *
+ * Parameters:
+ * [in] **ppBitStream
+ * [in] *pOffset
+ * [in] pCodeBook
+ *
+ * [out] **ppBitStream
+ * [out] *pOffset
+ *
+ * Returns : Code Book Index if successfull.
+ * : "ARM_NO_CODEBOOK_INDEX = 0xFFFF" if search fails.
+ **/
+
+#define ARM_NO_CODEBOOK_INDEX (OMX_U16)(0xFFFF)
+
+OMX_U16 armUnPackVLC32(
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pOffset,
+ const ARM_VLC32 *pCodeBook
+);
+
+/***************************************
+ * Fixed bit length Encode
+ ***************************************/
+
+/**
+ * Function: armPackBits
+ *
+ * Description:
+ * Pack a VLC code word into the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte
+ * in the bit stream.
+ * [in] pOffset pointer to the bit position in the byte
+ * pointed by *ppBitStream. Valid within 0
+ * to 7.
+ * [in] codeWord Code word that need to be inserted in to the
+ * bitstream
+ * [in] codeLength Length of the code word valid range 1...32
+ *
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMX_RESULT result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armPackBits (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pOffset,
+ OMX_U32 codeWord,
+ OMX_INT codeLength
+);
+
+/***************************************
+ * Variable bit length Encode
+ ***************************************/
+
+/**
+ * Function: armPackVLC32
+ *
+ * Description:
+ * Pack a VLC code word into the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte
+ * in the bit stream.
+ * [in] pBitOffset pointer to the bit position in the byte
+ * pointed by *ppBitStream. Valid within 0
+ * to 7.
+ * [in] code VLC code word that need to be inserted in to the
+ * bitstream
+ *
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMX_RESULT result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armPackVLC32 (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ ARM_VLC32 code
+);
+
+#endif /*_armCodec_H_*/
+
+/*End of File*/
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCTTable.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCTTable.h
new file mode 100755
index 0000000..e0cfdaa
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCTTable.h
@@ -0,0 +1,40 @@
+/**
+ *
+ *
+ * File Name: armCOMM_IDCTTable.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File : armCOMM_IDCTTable.h
+ * Description : Contains declarations of tables for IDCT calculation.
+ *
+ */
+
+#ifndef _armCOMM_IDCTTable_H_
+#define _armCOMM_IDCTTable_H_
+
+#include "omxtypes.h"
+
+ /* Table of s(u)*A(u)*A(v)/16 at Q15
+ * s(u)=1.0 0 <= u <= 5
+ * s(6)=2.0
+ * s(7)=4.0
+ * A(0) = 2*sqrt(2)
+ * A(u) = 4*cos(u*pi/16) for (u!=0)
+ */
+extern const OMX_U16 armCOMM_IDCTPreScale [64];
+extern const OMX_U16 armCOMM_IDCTCoef [4];
+
+#endif /* _armCOMM_IDCTTable_H_ */
+
+
+/* End of File */
+
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCT_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCT_s.h
new file mode 100755
index 0000000..0baa087
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_IDCT_s.h
@@ -0,0 +1,1451 @@
+;//
+;// This confidential and proprietary software may be used only as
+;// authorised by a licensing agreement from ARM Limited
+;// (C) COPYRIGHT 2004 ARM Limited
+;// ALL RIGHTS RESERVED
+;// The entire notice above must be reproduced on all authorised
+;// copies and copies may only be made to the extent permitted
+;// by a licensing agreement from ARM Limited.
+;//
+;// IDCT_s.s
+;//
+;// Inverse DCT module
+;//
+;//
+;// ALGORITHM DESCRIPTION
+;//
+;// The 8x8 2D IDCT is performed by calculating a 1D IDCT for each
+;// column and then a 1D IDCT for each row.
+;//
+;// The 8-point 1D IDCT is defined by
+;// f(x) = (C(0)*T(0)*c(0,x) + ... + C(7)*T(7)*c(7,x))/2
+;//
+;// C(u) = 1/sqrt(2) if u=0 or 1 if u!=0
+;// c(u,x) = cos( (2x+1)*u*pi/16 )
+;//
+;// We compute the 8-point 1D IDCT using the reverse of
+;// the Arai-Agui-Nakajima flow graph which we split into
+;// 5 stages named in reverse order to identify with the
+;// forward DCT. Direct inversion of the forward formulae
+;// in file FDCT_s.s gives:
+;//
+;// IStage 5: j(u) = T(u)*A(u) [ A(u)=4*C(u)*c(u,0) ]
+;// [ A(0) = 2*sqrt(2)
+;// A(u) = 4*cos(u*pi/16) for (u!=0) ]
+;//
+;// IStage 4: i0 = j0 i1 = j4
+;// i3 = (j2+j6)/2 i2 = (j2-j6)/2
+;// i7 = (j5+j3)/2 i4 = (j5-j3)/2
+;// i5 = (j1+j7)/2 i6 = (j1-j7)/2
+;//
+;// IStage 3: h0 = (i0+i1)/2 h1 = (i0-i1)/2
+;// h2 = (i2*sqrt2)-i3 h3 = i3
+;// h4 = cos(pi/8)*i4 + sin(pi/8)*i6
+;// h6 = -sin(pi/8)*i4 + cos(pi/8)*i6
+;// [ The above two lines rotate by -(pi/8) ]
+;// h5 = (i5-i7)/sqrt2 h7 = (i5+i7)/2
+;//
+;// IStage 2: g0 = (h0+h3)/2 g3 = (h0-h3)/2
+;// g1 = (h1+h2)/2 g2 = (h1-h2)/2
+;// g7 = h7 g6 = h6 - h7
+;// g5 = h5 - g6 g4 = h4 - g5
+;//
+;// IStage 1: f0 = (g0+g7)/2 f7 = (g0-g7)/2
+;// f1 = (g1+g6)/2 f6 = (g1-g6)/2
+;// f2 = (g2+g5)/2 f5 = (g2-g5)/2
+;// f3 = (g3+g4)/2 f4 = (g3-g4)/2
+;//
+;// Note that most coefficients are halved 3 times during the
+;// above calculation. We can rescale the algorithm dividing
+;// the input by 8 to remove the halvings.
+;//
+;// IStage 5: j(u) = T(u)*A(u)/8
+;//
+;// IStage 4: i0 = j0 i1 = j4
+;// i3 = j2 + j6 i2 = j2 - j6
+;// i7 = j5 + j3 i4 = j5 - j3
+;// i5 = j1 + j7 i6 = j1 - j7
+;//
+;// IStage 3: h0 = i0 + i1 h1 = i0 - i1
+;// h2 = (i2*sqrt2)-i3 h3 = i3
+;// h4 = 2*( cos(pi/8)*i4 + sin(pi/8)*i6)
+;// h6 = 2*(-sin(pi/8)*i4 + cos(pi/8)*i6)
+;// h5 = (i5-i7)*sqrt2 h7 = i5 + i7
+;//
+;// IStage 2: g0 = h0 + h3 g3 = h0 - h3
+;// g1 = h1 + h2 g2 = h1 - h2
+;// g7 = h7 g6 = h6 - h7
+;// g5 = h5 - g6 g4 = h4 - g5
+;//
+;// IStage 1: f0 = g0 + g7 f7 = g0 - g7
+;// f1 = g1 + g6 f6 = g1 - g6
+;// f2 = g2 + g5 f5 = g2 - g5
+;// f3 = g3 + g4 f4 = g3 - g4
+;//
+;// Note:
+;// 1. The scaling by A(u)/8 can often be combined with inverse
+;// quantization. The column and row scalings can be combined.
+;// 2. The flowgraph in the AAN paper has h4,g6 negated compared
+;// to the above code but is otherwise identical.
+;// 3. The rotation by -pi/8 can be peformed using three multiplies
+;// Eg c*i4+s*i6 = (i6-i4)*s + (c+s)*i4
+;// -s*i4+c*i6 = (i6-i4)*s + (c-s)*i6
+;// 4. If |T(u)|<=1 then from the IDCT definition,
+;// |f(x)| <= ((1/sqrt2) + |c(1,x)| + .. + |c(7,x)|)/2
+;// = ((1/sqrt2) + cos(pi/16) + ... + cos(7*pi/16))/2
+;// = ((1/sqrt2) + (cot(pi/32)-1)/2)/2
+;// = (1 + cos(pi/16) + cos(2pi/16) + cos(3pi/16))/sqrt(2)
+;// = (approx)2.64
+;// So the max gain of the 2D IDCT is ~x7.0 = 3 bits.
+;// The table below shows input patterns generating the maximum
+;// value of |f(u)| for input in the range |T(x)|<=1. M=-1, P=+1
+;// InputPattern Max |f(x)|
+;// PPPPPPPP |f0| = 2.64
+;// PPPMMMMM |f1| = 2.64
+;// PPMMMPPP |f2| = 2.64
+;// PPMMPPMM |f3| = 2.64
+;// PMMPPMMP |f4| = 2.64
+;// PMMPMMPM |f5| = 2.64
+;// PMPPMPMP |f6| = 2.64
+;// PMPMPMPM |f7| = 2.64
+;// Note that this input pattern is the transpose of the
+;// corresponding max input patter for the FDCT.
+
+;// Arguments
+
+pSrc RN 0 ;// source data buffer
+Stride RN 1 ;// destination stride in bytes
+pDest RN 2 ;// destination data buffer
+pScale RN 3 ;// pointer to scaling table
+
+
+ ;// DCT Inverse Macro
+ ;// The DCT code should be parametrized according
+ ;// to the following inputs:
+ ;// $outsize = "u8" : 8-bit unsigned data saturated (0 to +255)
+ ;// "s9" : 16-bit signed data saturated to 9-bit (-256 to +255)
+ ;// "s16" : 16-bit signed data not saturated (max size ~+/-14273)
+ ;// $inscale = "s16" : signed 16-bit aan-scale table, Q15 format, with 4 byte alignment
+ ;// "s32" : signed 32-bit aan-scale table, Q23 format, with 4 byte alignment
+ ;//
+ ;// Inputs:
+ ;// pSrc = r0 = Pointer to input data
+ ;// Range is -256 to +255 (9-bit)
+ ;// Stride = r1 = Stride between input lines
+ ;// pDest = r2 = Pointer to output data
+ ;// pScale = r3 = Pointer to aan-scale table in the format defined by $inscale
+
+
+
+ MACRO
+ M_IDCT $outsize, $inscale, $stride
+ LCLA SHIFT
+
+
+ IF ARM1136JS
+
+;// REGISTER ALLOCATION
+;// This is hard since we have 8 values, 9 free registers and each
+;// butterfly requires a temporary register. We also want to
+;// maintain register order so we can use LDM/STM. The table below
+;// summarises the register allocation that meets all these criteria.
+;// a=1stcol, b=2ndcol, f,g,h,i are dataflow points described above.
+;//
+;// r1 a01 g0 h0
+;// r4 b01 f0 g1 h1 i0
+;// r5 a23 f1 g2 i1
+;// r6 b23 f2 g3 h2 i2
+;// r7 a45 f3 h3 i3
+;// r8 b45 f4 g4 h4 i4
+;// r9 a67 f5 g5 h5 i5
+;// r10 b67 f6 g6 h6 i6
+;// r11 f7 g7 h7 i7
+;//
+ra01 RN 1
+rb01 RN 4
+ra23 RN 5
+rb23 RN 6
+ra45 RN 7
+rb45 RN 8
+ra67 RN 9
+rb67 RN 10
+rtmp RN 11
+csPiBy8 RN 12 ;// [ (Sin(pi/8)@Q15), (Cos(pi/8)@Q15) ]
+LoopRR2 RN 14 ;// [ LoopNumber<<13 , (1/Sqrt(2))@Q15 ]
+;// Transpose allocation
+xft RN ra01
+xf0 RN rb01
+xf1 RN ra23
+xf2 RN rb23
+xf3 RN ra45
+xf4 RN rb45
+xf5 RN ra67
+xf6 RN rb67
+xf7 RN rtmp
+;// IStage 1 allocation
+xg0 RN xft
+xg1 RN xf0
+xg2 RN xf1
+xg3 RN xf2
+xgt RN xf3
+xg4 RN xf4
+xg5 RN xf5
+xg6 RN xf6
+xg7 RN xf7
+;// IStage 2 allocation
+xh0 RN xg0
+xh1 RN xg1
+xht RN xg2
+xh2 RN xg3
+xh3 RN xgt
+xh4 RN xg4
+xh5 RN xg5
+xh6 RN xg6
+xh7 RN xg7
+;// IStage 3,4 allocation
+xit RN xh0
+xi0 RN xh1
+xi1 RN xht
+xi2 RN xh2
+xi3 RN xh3
+xi4 RN xh4
+xi5 RN xh5
+xi6 RN xh6
+xi7 RN xh7
+
+ M_STR pDest, ppDest
+ IF "$stride"="s"
+ M_STR Stride, pStride
+ ENDIF
+ M_ADR pDest, pBlk
+ LDR csPiBy8, =0x30fc7642
+ LDR LoopRR2, =0x00005a82
+
+v6_idct_col$_F
+ ;// Load even values
+ LDR xi4, [pSrc], #4 ;// j0
+ LDR xi5, [pSrc, #4*16-4] ;// j4
+ LDR xi6, [pSrc, #2*16-4] ;// j2
+ LDR xi7, [pSrc, #6*16-4] ;// j6
+
+ ;// Scale Even Values
+ IF "$inscale"="s16" ;// 16x16 mul
+SHIFT SETA 12
+ LDR xi0, [pScale], #4
+ LDR xi1, [pScale, #4*16-4]
+ LDR xi2, [pScale, #2*16-4]
+ MOV xit, #1<<(SHIFT-1)
+ SMLABB xi3, xi0, xi4, xit
+ SMLATT xi4, xi0, xi4, xit
+ SMLABB xi0, xi1, xi5, xit
+ SMLATT xi5, xi1, xi5, xit
+ MOV xi3, xi3, ASR #SHIFT
+ PKHBT xi4, xi3, xi4, LSL #(16-SHIFT)
+ LDR xi3, [pScale, #6*16-4]
+ SMLABB xi1, xi2, xi6, xit
+ SMLATT xi6, xi2, xi6, xit
+ MOV xi0, xi0, ASR #SHIFT
+ PKHBT xi5, xi0, xi5, LSL #(16-SHIFT)
+ SMLABB xi2, xi3, xi7, xit
+ SMLATT xi7, xi3, xi7, xit
+ MOV xi1, xi1, ASR #SHIFT
+ PKHBT xi6, xi1, xi6, LSL #(16-SHIFT)
+ MOV xi2, xi2, ASR #SHIFT
+ PKHBT xi7, xi2, xi7, LSL #(16-SHIFT)
+ ENDIF
+ IF "$inscale"="s32" ;// 32x16 mul
+SHIFT SETA (12+8-16)
+ MOV xit, #1<<(SHIFT-1)
+ LDR xi0, [pScale], #8
+ LDR xi1, [pScale, #0*32+4-8]
+ LDR xi2, [pScale, #4*32-8]
+ LDR xi3, [pScale, #4*32+4-8]
+ SMLAWB xi0, xi0, xi4, xit
+ SMLAWT xi1, xi1, xi4, xit
+ SMLAWB xi2, xi2, xi5, xit
+ SMLAWT xi3, xi3, xi5, xit
+ MOV xi0, xi0, ASR #SHIFT
+ PKHBT xi4, xi0, xi1, LSL #(16-SHIFT)
+ MOV xi2, xi2, ASR #SHIFT
+ PKHBT xi5, xi2, xi3, LSL #(16-SHIFT)
+ LDR xi0, [pScale, #2*32-8]
+ LDR xi1, [pScale, #2*32+4-8]
+ LDR xi2, [pScale, #6*32-8]
+ LDR xi3, [pScale, #6*32+4-8]
+ SMLAWB xi0, xi0, xi6, xit
+ SMLAWT xi1, xi1, xi6, xit
+ SMLAWB xi2, xi2, xi7, xit
+ SMLAWT xi3, xi3, xi7, xit
+ MOV xi0, xi0, ASR #SHIFT
+ PKHBT xi6, xi0, xi1, LSL #(16-SHIFT)
+ MOV xi2, xi2, ASR #SHIFT
+ PKHBT xi7, xi2, xi3, LSL #(16-SHIFT)
+ ENDIF
+
+ ;// Load odd values
+ LDR xi0, [pSrc, #1*16-4] ;// j1
+ LDR xi1, [pSrc, #7*16-4] ;// j7
+ LDR xi2, [pSrc, #5*16-4] ;// j5
+ LDR xi3, [pSrc, #3*16-4] ;// j3
+
+ IF {TRUE}
+ ;// shortcut if odd values 0
+ TEQ xi0, #0
+ TEQEQ xi1, #0
+ TEQEQ xi2, #0
+ TEQEQ xi3, #0
+ BEQ v6OddZero$_F
+ ENDIF
+
+ ;// Store scaled even values
+ STMIA pDest, {xi4, xi5, xi6, xi7}
+
+ ;// Scale odd values
+ IF "$inscale"="s16"
+ ;// Perform AAN Scale
+ LDR xi4, [pScale, #1*16-4]
+ LDR xi5, [pScale, #7*16-4]
+ LDR xi6, [pScale, #5*16-4]
+ SMLABB xi7, xi0, xi4, xit
+ SMLATT xi0, xi0, xi4, xit
+ SMLABB xi4, xi1, xi5, xit
+ SMLATT xi1, xi1, xi5, xit
+ MOV xi7, xi7, ASR #SHIFT
+ PKHBT xi0, xi7, xi0, LSL #(16-SHIFT)
+ LDR xi7, [pScale, #3*16-4]
+ SMLABB xi5, xi2, xi6, xit
+ SMLATT xi2, xi2, xi6, xit
+ MOV xi4, xi4, ASR #SHIFT
+ PKHBT xi1, xi4, xi1, LSL #(16-SHIFT)
+ SMLABB xi6, xi3, xi7, xit
+ SMLATT xi3, xi3, xi7, xit
+ MOV xi5, xi5, ASR #SHIFT
+ PKHBT xi2, xi5, xi2, LSL #(16-SHIFT)
+ MOV xi6, xi6, ASR #SHIFT
+ PKHBT xi3, xi6, xi3, LSL #(16-SHIFT)
+ ENDIF
+ IF "$inscale"="s32" ;// 32x16 mul
+ LDR xi4, [pScale, #1*32-8]
+ LDR xi5, [pScale, #1*32+4-8]
+ LDR xi6, [pScale, #7*32-8]
+ LDR xi7, [pScale, #7*32+4-8]
+ SMLAWB xi4, xi4, xi0, xit
+ SMLAWT xi5, xi5, xi0, xit
+ SMLAWB xi6, xi6, xi1, xit
+ SMLAWT xi7, xi7, xi1, xit
+ MOV xi4, xi4, ASR #SHIFT
+ PKHBT xi0, xi4, xi5, LSL #(16-SHIFT)
+ MOV xi6, xi6, ASR #SHIFT
+ PKHBT xi1, xi6, xi7, LSL #(16-SHIFT)
+ LDR xi4, [pScale, #5*32-8]
+ LDR xi5, [pScale, #5*32+4-8]
+ LDR xi6, [pScale, #3*32-8]
+ LDR xi7, [pScale, #3*32+4-8]
+ SMLAWB xi4, xi4, xi2, xit
+ SMLAWT xi5, xi5, xi2, xit
+ SMLAWB xi6, xi6, xi3, xit
+ SMLAWT xi7, xi7, xi3, xit
+ MOV xi4, xi4, ASR #SHIFT
+ PKHBT xi2, xi4, xi5, LSL #(16-SHIFT)
+ MOV xi6, xi6, ASR #SHIFT
+ PKHBT xi3, xi6, xi7, LSL #(16-SHIFT)
+ ENDIF
+
+ LDR xit, =0x00010001 ;// rounding constant
+ SADD16 xi5, xi0, xi1 ;// (j1+j7)/2
+ SHADD16 xi5, xi5, xit
+
+ SSUB16 xi6, xi0, xi1 ;// j1-j7
+ SADD16 xi7, xi2, xi3 ;// (j5+j3)/2
+ SHADD16 xi7, xi7, xit
+
+ SSUB16 xi4, xi2, xi3 ;// j5-j3
+
+ SSUB16 xi3, xi5, xi7 ;// (i5-i7)/2
+
+ PKHBT xi0, xi6, xi4, LSL#16 ;// [i4,i6] row a
+ PKHTB xi1, xi4, xi6, ASR#16 ;// [i4,i6] row b
+
+ SMUADX xi2, xi0, csPiBy8 ;// rowa by [c,s]
+ SMUADX xi4, xi1, csPiBy8 ;// rowb by [c,s]
+ SMUSD xi0, xi0, csPiBy8 ;// rowa by [-s,c]
+ SMUSD xi6, xi1, csPiBy8 ;// rowb by [-s,c]
+
+ SMULBB xi1, xi3, LoopRR2
+ SMULTB xi3, xi3, LoopRR2
+
+ PKHTB xh4, xi4, xi2, ASR#16 ;// h4/4
+ PKHTB xh6, xi6, xi0, ASR#16 ;// h6/4
+ SHADD16 xh7, xi5, xi7 ;// (i5+i7)/4
+
+ ;// xi0,xi1,xi2,xi3 now free
+ ;// IStage 4,3, rows 2to3 x1/2
+
+ MOV xi3, xi3, LSL #1
+ PKHTB xh5, xi3, xi1, ASR#15 ;// h5/4
+ LDRD xi0, [pDest, #8] ;// j2,j6 scaled
+
+ ;// IStage 2, rows4to7
+ SSUB16 xg6, xh6, xh7
+ SSUB16 xg5, xh5, xg6
+ SSUB16 xg4, xh4, xg5
+
+ SSUB16 xi2, xi0, xi1 ;// (j2-j6)
+
+ SHADD16 xi3, xi0, xi1 ;// (j2+j6)/2
+
+ SMULBB xi0, xi2, LoopRR2
+ SMULTB xi2, xi2, LoopRR2
+
+ MOV xi2, xi2, LSL #1
+ PKHTB xh2, xi2, xi0, ASR#15 ;// i2*sqrt(2)/4
+
+ ;// xi0, xi1 now free
+ ;// IStage 4,3 rows 0to1 x 1/2
+ LDRD xi0, [pDest] ;// j0, j4 scaled
+ SSUB16 xh2, xh2, xi3
+ ADDS LoopRR2, LoopRR2, #2<<29 ;// done two rows
+
+ SHADD16 xh0, xi0, xi1
+ SHSUB16 xh1, xi0, xi1
+
+ ;// IStage 2 rows 0to3 x 1/2
+ SHSUB16 xg2, xh1, xh2
+ SHADD16 xg1, xh1, xh2
+ SHSUB16 xg3, xh0, xh3
+ SHADD16 xg0, xh0, xh3
+
+ ;// IStage 1 all rows
+ SADD16 xf3, xg3, xg4
+ SSUB16 xf4, xg3, xg4
+ SADD16 xf2, xg2, xg5
+ SSUB16 xf5, xg2, xg5
+ SADD16 xf1, xg1, xg6
+ SSUB16 xf6, xg1, xg6
+ SADD16 xf0, xg0, xg7
+ SSUB16 xf7, xg0, xg7
+
+ ;// Transpose, store and loop
+ PKHBT ra01, xf0, xf1, LSL #16
+ PKHTB rb01, xf1, xf0, ASR #16
+
+ PKHBT ra23, xf2, xf3, LSL #16
+ PKHTB rb23, xf3, xf2, ASR #16
+
+ PKHBT ra45, xf4, xf5, LSL #16
+ PKHTB rb45, xf5, xf4, ASR #16
+
+ PKHBT ra67, xf6, xf7, LSL #16
+ STMIA pDest!, {ra01, ra23, ra45, ra67}
+ PKHTB rb67, xf7, xf6, ASR #16
+ STMIA pDest!, {rb01, rb23, rb45, rb67}
+ BCC v6_idct_col$_F
+
+ SUB pSrc, pDest, #(64*2)
+ M_LDR pDest, ppDest
+ IF "$stride"="s"
+ M_LDR pScale, pStride
+ ENDIF
+ B v6_idct_row$_F
+
+v6OddZero$_F
+ SSUB16 xi2, xi6, xi7 ;// (j2-j6)
+ SHADD16 xi3, xi6, xi7 ;// (j2+j6)/2
+
+ SMULBB xi0, xi2, LoopRR2
+ SMULTB xi2, xi2, LoopRR2
+
+ MOV xi2, xi2, LSL #1
+ PKHTB xh2, xi2, xi0, ASR#15 ;// i2*sqrt(2)/4
+ SSUB16 xh2, xh2, xi3
+
+ ;// xi0, xi1 now free
+ ;// IStage 4,3 rows 0to1 x 1/2
+
+ SHADD16 xh0, xi4, xi5
+ SHSUB16 xh1, xi4, xi5
+
+ ;// IStage 2 rows 0to3 x 1/2
+ SHSUB16 xg2, xh1, xh2
+ SHADD16 xg1, xh1, xh2
+ SHSUB16 xg3, xh0, xh3
+ SHADD16 xg0, xh0, xh3
+
+ ;// IStage 1 all rows
+ MOV xf3, xg3
+ MOV xf4, xg3
+ MOV xf2, xg2
+ MOV xf5, xg2
+ MOV xf1, xg1
+ MOV xf6, xg1
+ MOV xf0, xg0
+ MOV xf7, xg0
+
+ ;// Transpose
+ PKHBT ra01, xf0, xf1, LSL #16
+ PKHTB rb01, xf1, xf0, ASR #16
+
+ PKHBT ra23, xf2, xf3, LSL #16
+ PKHTB rb23, xf3, xf2, ASR #16
+
+ PKHBT ra45, xf4, xf5, LSL #16
+ PKHTB rb45, xf5, xf4, ASR #16
+
+ PKHBT ra67, xf6, xf7, LSL #16
+ PKHTB rb67, xf7, xf6, ASR #16
+
+ STMIA pDest!, {ra01, ra23, ra45, ra67}
+ ADDS LoopRR2, LoopRR2, #2<<29 ;// done two rows
+ STMIA pDest!, {rb01, rb23, rb45, rb67}
+
+ BCC v6_idct_col$_F
+ SUB pSrc, pDest, #(64*2)
+ M_LDR pDest, ppDest
+ IF "$stride"="s"
+ M_LDR pScale, pStride
+ ENDIF
+
+
+v6_idct_row$_F
+ ;// IStage 4,3, rows4to7 x1/4
+ LDR xit, =0x00010001 ;// rounding constant
+ LDR xi0, [pSrc, #1*16] ;// j1
+ LDR xi1, [pSrc, #7*16] ;// 4*j7
+ LDR xi2, [pSrc, #5*16] ;// j5
+ LDR xi3, [pSrc, #3*16] ;// j3
+
+ SHADD16 xi1, xi1, xit ;// 2*j7
+ SHADD16 xi1, xi1, xit ;// j7
+
+ SHADD16 xi5, xi0, xi1 ;// (j1+j7)/2
+ SSUB16 xi6, xi0, xi1 ;// j1-j7
+ SHADD16 xi7, xi2, xi3 ;// (j5+j3)/2
+ SSUB16 xi4, xi2, xi3 ;// j5-j3
+
+ SSUB16 xi3, xi5, xi7 ;// (i5-i7)/2
+
+ PKHBT xi0, xi6, xi4, LSL#16 ;// [i4,i6] row a
+ PKHTB xi1, xi4, xi6, ASR#16 ;// [i4,i6] row b
+
+ SMUADX xi2, xi0, csPiBy8 ;// rowa by [c,s]
+ SMUADX xi4, xi1, csPiBy8 ;// rowb by [c,s]
+ SMUSD xi0, xi0, csPiBy8 ;// rowa by [-s,c]
+ SMUSD xi6, xi1, csPiBy8 ;// rowb by [-s,c]
+
+ SMULBB xi1, xi3, LoopRR2
+ SMULTB xi3, xi3, LoopRR2
+
+ PKHTB xh4, xi4, xi2, ASR#16 ;// h4/4
+ PKHTB xh6, xi6, xi0, ASR#16 ;// h6/4
+ SHADD16 xh7, xi5, xi7 ;// (i5+i7)/4
+
+ MOV xi3, xi3, LSL #1
+ PKHTB xh5, xi3, xi1, ASR#15 ;// h5/4
+
+ ;// xi0,xi1,xi2,xi3 now free
+ ;// IStage 4,3, rows 2to3 x1/2
+
+ LDR xi0, [pSrc, #2*16] ;// j2
+ LDR xi1, [pSrc, #6*16] ;// 2*j6
+
+ ;// IStage 2, rows4to7
+ SSUB16 xg6, xh6, xh7
+ SSUB16 xg5, xh5, xg6
+ SSUB16 xg4, xh4, xg5
+
+ SHADD16 xi1, xi1, xit ;// j6
+ SSUB16 xi2, xi0, xi1 ;// (j2-j6)
+ SHADD16 xi3, xi0, xi1 ;// (j2+j6)/2
+
+ SMULBB xi0, xi2, LoopRR2
+ SMULTB xi2, xi2, LoopRR2
+
+ MOV xi2, xi2, LSL #1
+
+ PKHTB xh2, xi2, xi0, ASR#15 ;// i2*sqrt(2)/4
+
+ ;// xi0, xi1 now free
+ ;// IStage 4,3 rows 0to1 x 1/2
+ LDR xi1, [pSrc, #4*16] ;// j4
+ LDR xi0, [pSrc], #4 ;// j0
+
+ SSUB16 xh2, xh2, xi3
+ ADDS LoopRR2, LoopRR2, #2<<29 ;// done two rows
+
+ ADD xi0, xi0, xit, LSL #2 ;// ensure correct round
+ SHADD16 xh0, xi0, xi1 ;// of DC result
+ SHSUB16 xh1, xi0, xi1
+
+ ;// IStage 2 rows 0to3 x 1/2
+ SHSUB16 xg2, xh1, xh2
+ SHADD16 xg1, xh1, xh2
+ SHSUB16 xg3, xh0, xh3
+ SHADD16 xg0, xh0, xh3
+
+ ;// IStage 1 all rows
+ SHADD16 xf3, xg3, xg4
+ SHSUB16 xf4, xg3, xg4
+ SHADD16 xf2, xg2, xg5
+ SHSUB16 xf5, xg2, xg5
+ SHADD16 xf1, xg1, xg6
+ SHSUB16 xf6, xg1, xg6
+ SHADD16 xf0, xg0, xg7
+ SHSUB16 xf7, xg0, xg7
+
+ ;// Saturate
+ IF ("$outsize"="u8")
+ USAT16 xf0, #8, xf0
+ USAT16 xf1, #8, xf1
+ USAT16 xf2, #8, xf2
+ USAT16 xf3, #8, xf3
+ USAT16 xf4, #8, xf4
+ USAT16 xf5, #8, xf5
+ USAT16 xf6, #8, xf6
+ USAT16 xf7, #8, xf7
+ ENDIF
+ IF ("$outsize"="s9")
+ SSAT16 xf0, #9, xf0
+ SSAT16 xf1, #9, xf1
+ SSAT16 xf2, #9, xf2
+ SSAT16 xf3, #9, xf3
+ SSAT16 xf4, #9, xf4
+ SSAT16 xf5, #9, xf5
+ SSAT16 xf6, #9, xf6
+ SSAT16 xf7, #9, xf7
+ ENDIF
+
+ ;// Transpose to Row, Pack and store
+ IF ("$outsize"="u8")
+ ORR xf0, xf0, xf1, LSL #8 ;// [ b1 b0 a1 a0 ]
+ ORR xf2, xf2, xf3, LSL #8 ;// [ b3 b2 a3 a2 ]
+ ORR xf4, xf4, xf5, LSL #8 ;// [ b5 b4 a5 a4 ]
+ ORR xf6, xf6, xf7, LSL #8 ;// [ b7 b6 a7 a6 ]
+ PKHBT ra01, xf0, xf2, LSL #16
+ PKHTB rb01, xf2, xf0, ASR #16
+ PKHBT ra23, xf4, xf6, LSL #16
+ PKHTB rb23, xf6, xf4, ASR #16
+ STMIA pDest, {ra01, ra23}
+ IF "$stride"="s"
+ ADD pDest, pDest, pScale
+ STMIA pDest, {rb01, rb23}
+ ADD pDest, pDest, pScale
+ ELSE
+ ADD pDest, pDest, #($stride)
+ STMIA pDest, {rb01, rb23}
+ ADD pDest, pDest, #($stride)
+ ENDIF
+ ENDIF
+ IF ("$outsize"="s9"):LOR:("$outsize"="s16")
+ PKHBT ra01, xf0, xf1, LSL #16
+ PKHTB rb01, xf1, xf0, ASR #16
+
+ PKHBT ra23, xf2, xf3, LSL #16
+ PKHTB rb23, xf3, xf2, ASR #16
+
+ PKHBT ra45, xf4, xf5, LSL #16
+ PKHTB rb45, xf5, xf4, ASR #16
+
+ PKHBT ra67, xf6, xf7, LSL #16
+ PKHTB rb67, xf7, xf6, ASR #16
+
+ STMIA pDest, {ra01, ra23, ra45, ra67}
+ IF "$stride"="s"
+ ADD pDest, pDest, pScale
+ STMIA pDest, {rb01, rb23, rb45, rb67}
+ ADD pDest, pDest, pScale
+ ELSE
+ ADD pDest, pDest, #($stride)
+ STMIA pDest, {rb01, rb23, rb45, rb67}
+ ADD pDest, pDest, #($stride)
+ ENDIF
+ ENDIF
+
+ BCC v6_idct_row$_F
+ ENDIF ;// ARM1136JS
+
+
+ IF CortexA8
+
+Src0 EQU 7
+Src1 EQU 8
+Src2 EQU 9
+Src3 EQU 10
+Src4 EQU 11
+Src5 EQU 12
+Src6 EQU 13
+Src7 EQU 14
+Tmp EQU 15
+
+qXj0 QN Src0.S16
+qXj1 QN Src1.S16
+qXj2 QN Src2.S16
+qXj3 QN Src3.S16
+qXj4 QN Src4.S16
+qXj5 QN Src5.S16
+qXj6 QN Src6.S16
+qXj7 QN Src7.S16
+qXjt QN Tmp.S16
+
+dXj0lo DN (Src0*2).S16
+dXj0hi DN (Src0*2+1).S16
+dXj1lo DN (Src1*2).S16
+dXj1hi DN (Src1*2+1).S16
+dXj2lo DN (Src2*2).S16
+dXj2hi DN (Src2*2+1).S16
+dXj3lo DN (Src3*2).S16
+dXj3hi DN (Src3*2+1).S16
+dXj4lo DN (Src4*2).S16
+dXj4hi DN (Src4*2+1).S16
+dXj5lo DN (Src5*2).S16
+dXj5hi DN (Src5*2+1).S16
+dXj6lo DN (Src6*2).S16
+dXj6hi DN (Src6*2+1).S16
+dXj7lo DN (Src7*2).S16
+dXj7hi DN (Src7*2+1).S16
+dXjtlo DN (Tmp*2).S16
+dXjthi DN (Tmp*2+1).S16
+
+qXi0 QN qXj0
+qXi1 QN qXj4
+qXi2 QN qXj2
+qXi3 QN qXj7
+qXi4 QN qXj5
+qXi5 QN qXjt
+qXi6 QN qXj1
+qXi7 QN qXj6
+qXit QN qXj3
+
+dXi0lo DN dXj0lo
+dXi0hi DN dXj0hi
+dXi1lo DN dXj4lo
+dXi1hi DN dXj4hi
+dXi2lo DN dXj2lo
+dXi2hi DN dXj2hi
+dXi3lo DN dXj7lo
+dXi3hi DN dXj7hi
+dXi4lo DN dXj5lo
+dXi4hi DN dXj5hi
+dXi5lo DN dXjtlo
+dXi5hi DN dXjthi
+dXi6lo DN dXj1lo
+dXi6hi DN dXj1hi
+dXi7lo DN dXj6lo
+dXi7hi DN dXj6hi
+dXitlo DN dXj3lo
+dXithi DN dXj3hi
+
+qXh0 QN qXit
+qXh1 QN qXi0
+qXh2 QN qXi2
+qXh3 QN qXi3
+qXh4 QN qXi7
+qXh5 QN qXi5
+qXh6 QN qXi4
+qXh7 QN qXi1
+qXht QN qXi6
+
+dXh0lo DN dXitlo
+dXh0hi DN dXithi
+dXh1lo DN dXi0lo
+dXh1hi DN dXi0hi
+dXh2lo DN dXi2lo
+dXh2hi DN dXi2hi
+dXh3lo DN dXi3lo
+dXh3hi DN dXi3hi
+dXh4lo DN dXi7lo
+dXh4hi DN dXi7hi
+dXh5lo DN dXi5lo
+dXh5hi DN dXi5hi
+dXh6lo DN dXi4lo
+dXh6hi DN dXi4hi
+dXh7lo DN dXi1lo
+dXh7hi DN dXi1hi
+dXhtlo DN dXi6lo
+dXhthi DN dXi6hi
+
+qXg0 QN qXh2
+qXg1 QN qXht
+qXg2 QN qXh1
+qXg3 QN qXh0
+qXg4 QN qXh4
+qXg5 QN qXh5
+qXg6 QN qXh6
+qXg7 QN qXh7
+qXgt QN qXh3
+
+qXf0 QN qXg6
+qXf1 QN qXg5
+qXf2 QN qXg4
+qXf3 QN qXgt
+qXf4 QN qXg3
+qXf5 QN qXg2
+qXf6 QN qXg1
+qXf7 QN qXg0
+qXft QN qXg7
+
+
+qXt0 QN 1.S32
+qXt1 QN 2.S32
+qT0lo QN 1.S32
+qT0hi QN 2.S32
+qT1lo QN 3.S32
+qT1hi QN 4.S32
+qScalelo QN 5.S32 ;// used to read post scale values
+qScalehi QN 6.S32
+qTemp0 QN 5.S32
+qTemp1 QN 6.S32
+
+
+Scale1 EQU 6
+Scale2 EQU 15
+qScale1 QN Scale1.S16
+qScale2 QN Scale2.S16
+dScale1lo DN (Scale1*2).S16
+dScale1hi DN (Scale1*2+1).S16
+dScale2lo DN (Scale2*2).S16
+dScale2hi DN (Scale2*2+1).S16
+
+dCoefs DN 0.S16 ;// Scale coefficients in format {[0] [C] [S] [InvSqrt2]}
+InvSqrt2 DN dCoefs[0] ;// 1/sqrt(2) in Q15
+S DN dCoefs[1] ;// Sin(PI/8) in Q15
+C DN dCoefs[2] ;// Cos(PI/8) in Q15
+
+pTemp RN 12
+
+
+ IMPORT armCOMM_IDCTCoef
+
+ VLD1 {qXj0,qXj1}, [pSrc @64]!
+ VLD1 {qXj2,qXj3}, [pSrc @64]!
+ VLD1 {qXj4,qXj5}, [pSrc @64]!
+ VLD1 {qXj6,qXj7}, [pSrc @64]!
+
+ ;// Load PreScale and multiply with Src
+ ;// IStage 4
+
+ IF "$inscale"="s16" ;// 16X16 Mul
+ M_IDCT_PRESCALE16
+ ENDIF
+
+ IF "$inscale"="s32" ;// 32X32 ,ul
+ M_IDCT_PRESCALE32
+ ENDIF
+
+ ;// IStage 3
+ VQDMULH qXi2, qXi2, InvSqrt2 ;// i2/sqrt(2)
+ VHADD qXh0, qXi0, qXi1 ;// (i0+i1)/2
+ VHSUB qXh1, qXi0, qXi1 ;// (i0-i1)/2
+ VHADD qXh7, qXi5, qXi7 ;// (i5+i7)/4
+ VSUB qXh5, qXi5, qXi7 ;// (i5-i7)/2
+ VQDMULH qXh5, qXh5, InvSqrt2 ;// h5/sqrt(2)
+ VSUB qXh2, qXi2, qXi3 ;// h2, h3
+
+ VMULL qXt0, dXi4lo, C ;// c*i4
+ VMLAL qXt0, dXi6lo, S ;// c*i4+s*i6
+ VMULL qXt1, dXi4hi, C
+ VMLAL qXt1, dXi6hi, S
+ VSHRN dXh4lo, qXt0, #16 ;// h4
+ VSHRN dXh4hi, qXt1, #16
+
+ VMULL qXt0, dXi6lo, C ;// c*i6
+ VMLSL qXt0, dXi4lo, S ;// -s*i4 + c*h6
+ VMULL qXt1, dXi6hi, C
+ VMLSL qXt1, dXi4hi, S
+ VSHRN dXh6lo, qXt0, #16 ;// h6
+ VSHRN dXh6hi, qXt1, #16
+
+ ;// IStage 2
+ VSUB qXg6, qXh6, qXh7
+ VSUB qXg5, qXh5, qXg6
+ VSUB qXg4, qXh4, qXg5
+ VHADD qXg1, qXh1, qXh2 ;// (h1+h2)/2
+ VHSUB qXg2, qXh1, qXh2 ;// (h1-h2)/2
+ VHADD qXg0, qXh0, qXh3 ;// (h0+h3)/2
+ VHSUB qXg3, qXh0, qXh3 ;// (h0-h3)/2
+
+ ;// IStage 1 all rows
+ VADD qXf3, qXg3, qXg4
+ VSUB qXf4, qXg3, qXg4
+ VADD qXf2, qXg2, qXg5
+ VSUB qXf5, qXg2, qXg5
+ VADD qXf1, qXg1, qXg6
+ VSUB qXf6, qXg1, qXg6
+ VADD qXf0, qXg0, qXg7
+ VSUB qXf7, qXg0, qXg7
+
+ ;// Transpose, store and loop
+XTR0 EQU Src5
+XTR1 EQU Tmp
+XTR2 EQU Src6
+XTR3 EQU Src7
+XTR4 EQU Src3
+XTR5 EQU Src0
+XTR6 EQU Src1
+XTR7 EQU Src2
+XTRt EQU Src4
+
+qA0 QN XTR0.S32 ;// for XTRpose
+qA1 QN XTR1.S32
+qA2 QN XTR2.S32
+qA3 QN XTR3.S32
+qA4 QN XTR4.S32
+qA5 QN XTR5.S32
+qA6 QN XTR6.S32
+qA7 QN XTR7.S32
+
+dB0 DN XTR0*2+1 ;// for using VSWP
+dB1 DN XTR1*2+1
+dB2 DN XTR2*2+1
+dB3 DN XTR3*2+1
+dB4 DN XTR4*2
+dB5 DN XTR5*2
+dB6 DN XTR6*2
+dB7 DN XTR7*2
+
+
+ VTRN qXf0, qXf1
+ VTRN qXf2, qXf3
+ VTRN qXf4, qXf5
+ VTRN qXf6, qXf7
+ VTRN qA0, qA2
+ VTRN qA1, qA3
+ VTRN qA4, qA6
+ VTRN qA5, qA7
+ VSWP dB0, dB4
+ VSWP dB1, dB5
+ VSWP dB2, dB6
+ VSWP dB3, dB7
+
+
+qYj0 QN qXf0
+qYj1 QN qXf1
+qYj2 QN qXf2
+qYj3 QN qXf3
+qYj4 QN qXf4
+qYj5 QN qXf5
+qYj6 QN qXf6
+qYj7 QN qXf7
+qYjt QN qXft
+
+dYj0lo DN (XTR0*2).S16
+dYj0hi DN (XTR0*2+1).S16
+dYj1lo DN (XTR1*2).S16
+dYj1hi DN (XTR1*2+1).S16
+dYj2lo DN (XTR2*2).S16
+dYj2hi DN (XTR2*2+1).S16
+dYj3lo DN (XTR3*2).S16
+dYj3hi DN (XTR3*2+1).S16
+dYj4lo DN (XTR4*2).S16
+dYj4hi DN (XTR4*2+1).S16
+dYj5lo DN (XTR5*2).S16
+dYj5hi DN (XTR5*2+1).S16
+dYj6lo DN (XTR6*2).S16
+dYj6hi DN (XTR6*2+1).S16
+dYj7lo DN (XTR7*2).S16
+dYj7hi DN (XTR7*2+1).S16
+dYjtlo DN (XTRt*2).S16
+dYjthi DN (XTRt*2+1).S16
+
+qYi0 QN qYj0
+qYi1 QN qYj4
+qYi2 QN qYj2
+qYi3 QN qYj7
+qYi4 QN qYj5
+qYi5 QN qYjt
+qYi6 QN qYj1
+qYi7 QN qYj6
+qYit QN qYj3
+
+dYi0lo DN dYj0lo
+dYi0hi DN dYj0hi
+dYi1lo DN dYj4lo
+dYi1hi DN dYj4hi
+dYi2lo DN dYj2lo
+dYi2hi DN dYj2hi
+dYi3lo DN dYj7lo
+dYi3hi DN dYj7hi
+dYi4lo DN dYj5lo
+dYi4hi DN dYj5hi
+dYi5lo DN dYjtlo
+dYi5hi DN dYjthi
+dYi6lo DN dYj1lo
+dYi6hi DN dYj1hi
+dYi7lo DN dYj6lo
+dYi7hi DN dYj6hi
+dYitlo DN dYj3lo
+dYithi DN dYj3hi
+
+qYh0 QN qYit
+qYh1 QN qYi0
+qYh2 QN qYi2
+qYh3 QN qYi3
+qYh4 QN qYi7
+qYh5 QN qYi5
+qYh6 QN qYi4
+qYh7 QN qYi1
+qYht QN qYi6
+
+dYh0lo DN dYitlo
+dYh0hi DN dYithi
+dYh1lo DN dYi0lo
+dYh1hi DN dYi0hi
+dYh2lo DN dYi2lo
+dYh2hi DN dYi2hi
+dYh3lo DN dYi3lo
+dYh3hi DN dYi3hi
+dYh4lo DN dYi7lo
+dYh4hi DN dYi7hi
+dYh5lo DN dYi5lo
+dYh5hi DN dYi5hi
+dYh6lo DN dYi4lo
+dYh6hi DN dYi4hi
+dYh7lo DN dYi1lo
+dYh7hi DN dYi1hi
+dYhtlo DN dYi6lo
+dYhthi DN dYi6hi
+
+qYg0 QN qYh2
+qYg1 QN qYht
+qYg2 QN qYh1
+qYg3 QN qYh0
+qYg4 QN qYh4
+qYg5 QN qYh5
+qYg6 QN qYh6
+qYg7 QN qYh7
+qYgt QN qYh3
+
+qYf0 QN qYg6
+qYf1 QN qYg5
+qYf2 QN qYg4
+qYf3 QN qYgt
+qYf4 QN qYg3
+qYf5 QN qYg2
+qYf6 QN qYg1
+qYf7 QN qYg0
+qYft QN qYg7
+
+ VRSHR qYj7, qYj7, #2
+ VRSHR qYj6, qYj6, #1
+
+ VHADD qYi5, qYj1, qYj7 ;// i5 = (j1+j7)/2
+ VSUB qYi6, qYj1, qYj7 ;// i6 = j1-j7
+ VHADD qYi3, qYj2, qYj6 ;// i3 = (j2+j6)/2
+ VSUB qYi2, qYj2, qYj6 ;// i2 = j2-j6
+ VHADD qYi7, qYj5, qYj3 ;// i7 = (j5+j3)/2
+ VSUB qYi4, qYj5, qYj3 ;// i4 = j5-j3
+
+ VQDMULH qYi2, qYi2, InvSqrt2 ;// i2/sqrt(2)
+ ;// IStage 4,3 rows 0to1 x 1/2
+
+ MOV pTemp, #0x4 ;// ensure correct round
+ VDUP qScale1, pTemp ;// of DC result
+ VADD qYi0, qYi0, qScale1
+
+ VHADD qYh0, qYi0, qYi1 ;// (i0+i1)/2
+ VHSUB qYh1, qYi0, qYi1 ;// (i0-i1)/2
+
+ VHADD qYh7, qYi5, qYi7 ;// (i5+i7)/4
+ VSUB qYh5, qYi5, qYi7 ;// (i5-i7)/2
+ VSUB qYh2, qYi2, qYi3 ;// h2, h3
+ VQDMULH qYh5, qYh5, InvSqrt2 ;// h5/sqrt(2)
+
+ VMULL qXt0, dYi4lo, C ;// c*i4
+ VMLAL qXt0, dYi6lo, S ;// c*i4+s*i6
+ VMULL qXt1, dYi4hi, C
+ VMLAL qXt1, dYi6hi, S
+ VSHRN dYh4lo, qXt0, #16 ;// h4
+ VSHRN dYh4hi, qXt1, #16
+
+ VMULL qXt0, dYi6lo, C ;// c*i6
+ VMLSL qXt0, dYi4lo, S ;// -s*i4 + c*h6
+ VMULL qXt1, dYi6hi, C
+ VMLSL qXt1, dYi4hi, S
+ VSHRN dYh6lo, qXt0, #16 ;// h6
+ VSHRN dYh6hi, qXt1, #16
+
+ VSUB qYg6, qYh6, qYh7
+ VSUB qYg5, qYh5, qYg6
+ VSUB qYg4, qYh4, qYg5
+
+ ;// IStage 2 rows 0to3 x 1/2
+ VHADD qYg1, qYh1, qYh2 ;// (h1+h2)/2
+ VHSUB qYg2, qYh1, qYh2 ;// (h1-h2)/2
+ VHADD qYg0, qYh0, qYh3 ;// (h0+h3)/2
+ VHSUB qYg3, qYh0, qYh3 ;// (h0-h3)/2
+
+
+ ;// IStage 1 all rows
+ VHADD qYf3, qYg3, qYg4
+ VHSUB qYf4, qYg3, qYg4
+ VHADD qYf2, qYg2, qYg5
+ VHSUB qYf5, qYg2, qYg5
+ VHADD qYf1, qYg1, qYg6
+ VHSUB qYf6, qYg1, qYg6
+ VHADD qYf0, qYg0, qYg7
+ VHSUB qYf7, qYg0, qYg7
+
+YTR0 EQU Src0
+YTR1 EQU Src4
+YTR2 EQU Src1
+YTR3 EQU Src2
+YTR4 EQU Src7
+YTR5 EQU Src5
+YTR6 EQU Tmp
+YTR7 EQU Src6
+YTRt EQU Src3
+
+qC0 QN YTR0.S32 ;// for YTRpose
+qC1 QN YTR1.S32
+qC2 QN YTR2.S32
+qC3 QN YTR3.S32
+qC4 QN YTR4.S32
+qC5 QN YTR5.S32
+qC6 QN YTR6.S32
+qC7 QN YTR7.S32
+
+dD0 DN YTR0*2+1 ;// for using VSWP
+dD1 DN YTR1*2+1
+dD2 DN YTR2*2+1
+dD3 DN YTR3*2+1
+dD4 DN YTR4*2
+dD5 DN YTR5*2
+dD6 DN YTR6*2
+dD7 DN YTR7*2
+
+ VTRN qYf0, qYf1
+ VTRN qYf2, qYf3
+ VTRN qYf4, qYf5
+ VTRN qYf6, qYf7
+ VTRN qC0, qC2
+ VTRN qC1, qC3
+ VTRN qC4, qC6
+ VTRN qC5, qC7
+ VSWP dD0, dD4
+ VSWP dD1, dD5
+ VSWP dD2, dD6
+ VSWP dD3, dD7
+
+
+dYf0U8 DN YTR0*2.U8
+dYf1U8 DN YTR1*2.U8
+dYf2U8 DN YTR2*2.U8
+dYf3U8 DN YTR3*2.U8
+dYf4U8 DN YTR4*2.U8
+dYf5U8 DN YTR5*2.U8
+dYf6U8 DN YTR6*2.U8
+dYf7U8 DN YTR7*2.U8
+
+ ;//
+ ;// Do saturation if outsize is other than S16
+ ;//
+
+ IF ("$outsize"="u8")
+ ;// Output range [0-255]
+ VQMOVN dYf0U8, qYf0
+ VQMOVN dYf1U8, qYf1
+ VQMOVN dYf2U8, qYf2
+ VQMOVN dYf3U8, qYf3
+ VQMOVN dYf4U8, qYf4
+ VQMOVN dYf5U8, qYf5
+ VQMOVN dYf6U8, qYf6
+ VQMOVN dYf7U8, qYf7
+ ENDIF
+
+ IF ("$outsize"="s9")
+ ;// Output range [-256 to +255]
+ VQSHL qYf0, qYf0, #16-9
+ VQSHL qYf1, qYf1, #16-9
+ VQSHL qYf2, qYf2, #16-9
+ VQSHL qYf3, qYf3, #16-9
+ VQSHL qYf4, qYf4, #16-9
+ VQSHL qYf5, qYf5, #16-9
+ VQSHL qYf6, qYf6, #16-9
+ VQSHL qYf7, qYf7, #16-9
+
+ VSHR qYf0, qYf0, #16-9
+ VSHR qYf1, qYf1, #16-9
+ VSHR qYf2, qYf2, #16-9
+ VSHR qYf3, qYf3, #16-9
+ VSHR qYf4, qYf4, #16-9
+ VSHR qYf5, qYf5, #16-9
+ VSHR qYf6, qYf6, #16-9
+ VSHR qYf7, qYf7, #16-9
+ ENDIF
+
+ ;// Store output depending on the Stride size
+ IF "$stride"="s"
+ VST1 qYf0, [pDest @64], Stride
+ VST1 qYf1, [pDest @64], Stride
+ VST1 qYf2, [pDest @64], Stride
+ VST1 qYf3, [pDest @64], Stride
+ VST1 qYf4, [pDest @64], Stride
+ VST1 qYf5, [pDest @64], Stride
+ VST1 qYf6, [pDest @64], Stride
+ VST1 qYf7, [pDest @64]
+ ELSE
+ IF ("$outsize"="u8")
+ VST1 dYf0U8, [pDest @64], #8
+ VST1 dYf1U8, [pDest @64], #8
+ VST1 dYf2U8, [pDest @64], #8
+ VST1 dYf3U8, [pDest @64], #8
+ VST1 dYf4U8, [pDest @64], #8
+ VST1 dYf5U8, [pDest @64], #8
+ VST1 dYf6U8, [pDest @64], #8
+ VST1 dYf7U8, [pDest @64]
+ ELSE
+ ;// ("$outsize"="s9") or ("$outsize"="s16")
+ VST1 qYf0, [pDest @64], #16
+ VST1 qYf1, [pDest @64], #16
+ VST1 qYf2, [pDest @64], #16
+ VST1 qYf3, [pDest @64], #16
+ VST1 qYf4, [pDest @64], #16
+ VST1 qYf5, [pDest @64], #16
+ VST1 qYf6, [pDest @64], #16
+ VST1 qYf7, [pDest @64]
+ ENDIF
+
+ ENDIF
+
+
+
+ ENDIF ;// CortexA8
+
+
+
+ MEND
+
+ ;// Scale TWO input rows with TWO rows of 16 bit scale values
+ ;//
+ ;// This macro is used by M_IDCT_PRESCALE16 to pre-scale one row
+ ;// input (Eight input values) with one row of scale values. Also
+ ;// Loads next scale values from pScale, if $LastRow flag is not set.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// $dAlo - Input D register with first four S16 values of row n
+ ;// $dAhi - Input D register with next four S16 values of row n
+ ;// $dBlo - Input D register with first four S16 values of row n+1
+ ;// $dBhi - Input D register with next four S16 values of row n+1
+ ;// pScale - Pointer to next row of scale values
+ ;// qT0lo - Temporary scratch register
+ ;// qT0hi - Temporary scratch register
+ ;// qT1lo - Temporary scratch register
+ ;// qT1hi - Temporary scratch register
+ ;// dScale1lo - Scale value of row n
+ ;// dScale1hi - Scale value of row n
+ ;// dScale2lo - Scale value of row n+1
+ ;// dScale2hi - Scale value of row n+1
+ ;//
+ ;// Input Flag
+ ;//
+ ;// $LastRow - Flag to indicate whether current row is last row
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// $dAlo - Scaled output values (first four S16 of row n)
+ ;// $dAhi - Scaled output values (next four S16 of row n)
+ ;// $dBlo - Scaled output values (first four S16 of row n+1)
+ ;// $dBhi - Scaled output values (next four S16 of row n+1)
+ ;// qScale1 - Scale values for next row
+ ;// qScale2 - Scale values for next row+1
+ ;// pScale - Pointer to next row of scale values
+ ;//
+ MACRO
+ M_IDCT_SCALE16 $dAlo, $dAhi, $dBlo, $dBhi, $LastRow
+ VMULL qT0lo, $dAlo, dScale1lo
+ VMULL qT0hi, $dAhi, dScale1hi
+ VMULL qT1lo, $dBlo, dScale2lo
+ VMULL qT1hi, $dBhi, dScale2hi
+ IF "$LastRow"="0"
+ VLD1 qScale1, [pScale], #16 ;// Load scale for row n+1
+ VLD1 qScale2, [pScale], #16 ;// Load scale for row n+2
+ ENDIF
+ VQRSHRN $dAlo, qT0lo, #12
+ VQRSHRN $dAhi, qT0hi, #12
+ VQRSHRN $dBlo, qT1lo, #12
+ VQRSHRN $dBhi, qT1hi, #12
+ MEND
+
+ ;// Scale 8x8 block input values with 16 bit scale values
+ ;//
+ ;// This macro is used to pre-scale block of 8x8 input.
+ ;// This also do the Ist stage transformations of IDCT.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// dXjnlo - n th input D register with first four S16 values
+ ;// dXjnhi - n th input D register with next four S16 values
+ ;// qXjn - n th input Q register with eight S16 values
+ ;// pScale - Pointer to scale values
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// qXin - n th output Q register with eight S16 output values of 1st stage
+ ;//
+ MACRO
+ M_IDCT_PRESCALE16
+ VLD1 qScale1, [pScale], #16 ;// Load Pre scale for row 0
+ VLD1 qScale2, [pScale], #16 ;// Load Pre scale for row 0
+ M_IDCT_SCALE16 dXj0lo, dXj0hi, dXj1lo, dXj1hi, 0 ;// Pre scale row 0 & 1
+ M_IDCT_SCALE16 dXj2lo, dXj2hi, dXj3lo, dXj3hi, 0
+ M_IDCT_SCALE16 dXj4lo, dXj4hi, dXj5lo, dXj5hi, 0
+ M_IDCT_SCALE16 dXj6lo, dXj6hi, dXj7lo, dXj7hi, 1
+ VHADD qXi5, qXj1, qXj7 ;// (j1+j7)/2
+ VSUB qXi6, qXj1, qXj7 ;// j1-j7
+ LDR pSrc, =armCOMM_IDCTCoef ;// Address of DCT inverse AAN constants
+ VHADD qXi3, qXj2, qXj6 ;// (j2+j6)/2
+ VSUB qXi2, qXj2, qXj6 ;// j2-j6
+ VLDR dCoefs, [pSrc] ;// Load DCT inverse AAN constants
+ VHADD qXi7, qXj5, qXj3 ;// (j5+j3)/2
+ VSUB qXi4, qXj5, qXj3 ;// j5-j3
+ MEND
+
+
+ ;// Scale 8x8 block input values with 32 bit scale values
+ ;//
+ ;// This macro is used to pre-scale block of 8x8 input.
+ ;// This also do the Ist stage transformations of IDCT.
+ ;//
+ ;// Input Registers:
+ ;//
+ ;// dXjnlo - n th input D register with first four S16 values
+ ;// dXjnhi - n th input D register with next four S16 values
+ ;// qXjn - n th input Q register with eight S16 values
+ ;// pScale - Pointer to 32bit scale values in Q23 format
+ ;//
+ ;// Output Registers:
+ ;//
+ ;// dXinlo - n th output D register with first four S16 output values of 1st stage
+ ;// dXinhi - n th output D register with next four S16 output values of 1st stage
+ ;//
+ MACRO
+ M_IDCT_PRESCALE32
+qScale0lo QN 0.S32
+qScale0hi QN 1.S32
+qScale1lo QN 2.S32
+qScale1hi QN 3.S32
+qScale2lo QN qScale1lo
+qScale2hi QN qScale1hi
+qScale3lo QN qScale1lo
+qScale3hi QN qScale1hi
+qScale4lo QN qScale1lo
+qScale4hi QN qScale1hi
+qScale5lo QN qScale0lo
+qScale5hi QN qScale0hi
+qScale6lo QN qScale0lo
+qScale6hi QN qScale0hi
+qScale7lo QN qScale0lo
+qScale7hi QN qScale0hi
+
+qSrc0lo QN 4.S32
+qSrc0hi QN 5.S32
+qSrc1lo QN 6.S32
+qSrc1hi QN Src4.S32
+qSrc2lo QN qSrc0lo
+qSrc2hi QN qSrc0hi
+qSrc3lo QN qSrc0lo
+qSrc3hi QN qSrc0hi
+qSrc4lo QN qSrc0lo
+qSrc4hi QN qSrc0hi
+qSrc5lo QN qSrc1lo
+qSrc5hi QN qSrc1hi
+qSrc6lo QN qSrc1lo
+qSrc6hi QN qSrc1hi
+qSrc7lo QN qSrc0lo
+qSrc7hi QN qSrc0hi
+
+qRes17lo QN qScale0lo
+qRes17hi QN qScale0hi
+qRes26lo QN qScale0lo
+qRes26hi QN qScale0hi
+qRes53lo QN qScale0lo
+qRes53hi QN qScale0hi
+
+ ADD pTemp, pScale, #4*8*7 ;// Address of pScale[7]
+
+ ;// Row 0
+ VLD1 {qScale0lo, qScale0hi}, [pScale]!
+ VSHLL qSrc0lo, dXj0lo, #(12-1)
+ VSHLL qSrc0hi, dXj0hi, #(12-1)
+ VLD1 {qScale1lo, qScale1hi}, [pScale]!
+ VQRDMULH qSrc0lo, qScale0lo, qSrc0lo
+ VQRDMULH qSrc0hi, qScale0hi, qSrc0hi
+ VLD1 {qScale7lo, qScale7hi}, [pTemp]!
+ VSHLL qSrc1lo, dXj1lo, #(12-1)
+ VSHLL qSrc1hi, dXj1hi, #(12-1)
+ VMOVN dXi0lo, qSrc0lo ;// Output i0
+ VMOVN dXi0hi, qSrc0hi
+ VSHLL qSrc7lo, dXj7lo, #(12-1)
+ VSHLL qSrc7hi, dXj7hi, #(12-1)
+ SUB pTemp, pTemp, #((16*2)+(4*8*1))
+ VQRDMULH qSrc1lo, qScale1lo, qSrc1lo
+ VQRDMULH qSrc1hi, qScale1hi, qSrc1hi
+ VQRDMULH qSrc7lo, qScale7lo, qSrc7lo
+ VQRDMULH qSrc7hi, qScale7hi, qSrc7hi
+ VLD1 {qScale2lo, qScale2hi}, [pScale]!
+
+ ;// Row 1 & 7
+ VHADD qRes17lo, qSrc1lo, qSrc7lo ;// (j1+j7)/2
+ VHADD qRes17hi, qSrc1hi, qSrc7hi ;// (j1+j7)/2
+ VMOVN dXi5lo, qRes17lo ;// Output i5
+ VMOVN dXi5hi, qRes17hi
+ VSUB qRes17lo, qSrc1lo, qSrc7lo ;// j1-j7
+ VSUB qRes17hi, qSrc1hi, qSrc7hi ;// j1-j7
+ VMOVN dXi6lo, qRes17lo ;// Output i6
+ VMOVN dXi6hi, qRes17hi
+ VSHLL qSrc2lo, dXj2lo, #(12-1)
+ VSHLL qSrc2hi, dXj2hi, #(12-1)
+ VLD1 {qScale6lo, qScale6hi}, [pTemp]!
+ VSHLL qSrc6lo, dXj6lo, #(12-1)
+ VSHLL qSrc6hi, dXj6hi, #(12-1)
+ SUB pTemp, pTemp, #((16*2)+(4*8*1))
+ VQRDMULH qSrc2lo, qScale2lo, qSrc2lo
+ VQRDMULH qSrc2hi, qScale2hi, qSrc2hi
+ VQRDMULH qSrc6lo, qScale6lo, qSrc6lo
+ VQRDMULH qSrc6hi, qScale6hi, qSrc6hi
+ VLD1 {qScale3lo, qScale3hi}, [pScale]!
+
+ ;// Row 2 & 6
+ VHADD qRes26lo, qSrc2lo, qSrc6lo ;// (j2+j6)/2
+ VHADD qRes26hi, qSrc2hi, qSrc6hi ;// (j2+j6)/2
+ VMOVN dXi3lo, qRes26lo ;// Output i3
+ VMOVN dXi3hi, qRes26hi
+ VSUB qRes26lo, qSrc2lo, qSrc6lo ;// j2-j6
+ VSUB qRes26hi, qSrc2hi, qSrc6hi ;// j2-j6
+ VMOVN dXi2lo, qRes26lo ;// Output i2
+ VMOVN dXi2hi, qRes26hi
+ VSHLL qSrc3lo, dXj3lo, #(12-1)
+ VSHLL qSrc3hi, dXj3hi, #(12-1)
+ VLD1 {qScale5lo, qScale5hi}, [pTemp]!
+ VSHLL qSrc5lo, dXj5lo, #(12-1)
+ VSHLL qSrc5hi, dXj5hi, #(12-1)
+ VQRDMULH qSrc3lo, qScale3lo, qSrc3lo
+ VQRDMULH qSrc3hi, qScale3hi, qSrc3hi
+ VQRDMULH qSrc5lo, qScale5lo, qSrc5lo
+ VQRDMULH qSrc5hi, qScale5hi, qSrc5hi
+
+ ;// Row 3 & 5
+ VHADD qRes53lo, qSrc5lo, qSrc3lo ;// (j5+j3)/2
+ VHADD qRes53hi, qSrc5hi, qSrc3hi ;// (j5+j3)/2
+ SUB pSrc, pSrc, #16*2*2
+ VMOVN dXi7lo, qRes53lo ;// Output i7
+ VMOVN dXi7hi, qRes53hi
+ VSUB qRes53lo, qSrc5lo, qSrc3lo ;// j5-j3
+ VSUB qRes53hi, qSrc5hi, qSrc3hi ;// j5-j3
+ VLD1 qXj4, [pSrc @64]
+ VMOVN dXi4lo, qRes53lo ;// Output i4
+ VMOVN dXi4hi, qRes53hi
+ VSHLL qSrc4lo, dXj4lo, #(12-1)
+ VSHLL qSrc4hi, dXj4hi, #(12-1)
+ VLD1 {qScale4lo, qScale4hi}, [pScale]
+ LDR pSrc, =armCOMM_IDCTCoef ;// Address of DCT inverse AAN constants
+ VQRDMULH qSrc4lo, qScale4lo, qSrc4lo
+ VQRDMULH qSrc4hi, qScale4hi, qSrc4hi
+ VLDR dCoefs, [pSrc] ;// Load DCT inverse AAN constants
+ ;// Row 4
+ VMOVN dXi1lo, qSrc4lo ;// Output i1
+ VMOVN dXi1hi, qSrc4hi
+
+ MEND
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_MaskTable.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_MaskTable.h
new file mode 100755
index 0000000..51118fd
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_MaskTable.h
@@ -0,0 +1,27 @@
+/**
+ *
+ * File Name: armCOMM_MaskTable.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Mask Table to mask the end of array
+ */
+
+
+
+#ifndef _ARMCOMM_MASKTABLE_H_
+#define _ARMCOMM_MASKTABLE_H_
+
+#define MaskTableSize 72
+
+/* Mask table */
+
+extern const OMX_U16 armCOMM_qMaskTable16[MaskTableSize];
+extern const OMX_U8 armCOMM_qMaskTable8[MaskTableSize];
+
+#endif
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Version.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Version.h
new file mode 100755
index 0000000..41b3e1e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_Version.h
@@ -0,0 +1,43 @@
+/* Guard the header against multiple inclusion. */
+#ifndef __ARM_COMM_VERSION_H__
+#define __ARM_COMM_VERSION_H__
+
+
+/* The following line should be in omxtypes.h but hasn't been approved by OpenMAX yet */
+#define OMX_VERSION 102
+
+/* We need to define these macros in order to convert a #define number into a #define string. */
+#define ARM_QUOTE(a) #a
+#define ARM_INDIRECT(A) ARM_QUOTE(A)
+
+/* Convert the OMX_VERSION number into a string that can be used, for example, to print it out. */
+#define ARM_VERSION_STRING ARM_INDIRECT(OMX_VERSION)
+
+
+/* Define this in order to turn on ARM version/release/build strings in each domain */
+#define ARM_INCLUDE_VERSION_DESCRIPTIONS
+
+#ifdef ARM_INCLUDE_VERSION_DESCRIPTIONS
+ extern const char * const omxAC_VersionDescription;
+ extern const char * const omxIC_VersionDescription;
+ extern const char * const omxIP_VersionDescription;
+ extern const char * const omxSP_VersionDescription;
+ extern const char * const omxVC_VersionDescription;
+#endif /* ARM_INCLUDE_VERSION_DESCRIPTIONS */
+
+
+/* The following entries should be automatically updated by the release script */
+/* They are used in the ARM version strings defined for each domain. */
+
+/* The release tag associated with this release of the library. - used for source and object releases */
+#define OMX_ARM_RELEASE_TAG "r1p0-00bet0"
+
+/* The ARM architecture used to build any objects or executables in this release. */
+#define OMX_ARM_BUILD_ARCHITECTURE "ARM Architecture V7 with NEON"
+
+/* The ARM Toolchain used to build any objects or executables in this release. */
+#define OMX_ARM_BUILD_TOOLCHAIN "ARM RVCT 3.1"
+
+
+#endif /* __ARM_COMM_VERSION_H__ */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_s.h
new file mode 100755
index 0000000..0956bd1
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armCOMM_s.h
@@ -0,0 +1,1157 @@
+;//
+;//
+;// File Name: armCOMM_s.h
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// ARM optimized OpenMAX common header file
+;//
+
+;// Protect against multiple inclusion
+ IF :LNOT::DEF:ARMCOMM_S_H
+ GBLL ARMCOMM_S_H
+
+ REQUIRE8 ;// Requires 8-byte stack alignment
+ PRESERVE8 ;// Preserves 8-byte stack alignment
+
+ GBLL ARM_ERRORCHECK
+ARM_ERRORCHECK SETL {FALSE}
+
+;// Globals
+
+ GBLS _RRegList ;// R saved register list
+ GBLS _DRegList ;// D saved register list
+ GBLS _Variant ;// Selected processor variant
+ GBLS _CPU ;// CPU name
+ GBLS _Struct ;// Structure name
+
+ GBLL _InFunc ;// Inside function assembly flag
+ GBLL _SwLong ;// Long switch flag
+
+ GBLA _RBytes ;// Number of register bytes on stack
+ GBLA _SBytes ;// Number of scratch bytes on stack
+ GBLA _ABytes ;// Stack offset of next argument
+ GBLA _Workspace ;// Stack offset of scratch workspace
+ GBLA _F ;// Function number
+ GBLA _StOff ;// Struct offset
+ GBLA _SwNum ;// Switch number
+ GBLS _32 ;// Suffix for 32 byte alignmnet
+ GBLS _16 ;// Suffix for 16 byte alignmnet
+
+_InFunc SETL {FALSE}
+_SBytes SETA 0
+_F SETA 0
+_SwNum SETA 0
+_32 SETS "ALIGN32"
+_16 SETS "ALIGN16"
+
+;/////////////////////////////////////////////////////////
+;// Override the tools settings of the CPU if the #define
+;// USECPU is set, otherwise use the CPU defined by the
+;// assembler settings.
+;/////////////////////////////////////////////////////////
+
+ IF :DEF: OVERRIDECPU
+_CPU SETS OVERRIDECPU
+ ELSE
+_CPU SETS {CPU}
+ ENDIF
+
+
+
+;/////////////////////////////////////////////////////////
+;// Work out which code to build
+;/////////////////////////////////////////////////////////
+
+ IF :DEF:ARM1136JS:LOR::DEF:CortexA8:LOR::DEF:ARM_GENERIC
+ INFO 1,"Please switch to using M_VARIANTS"
+ ENDIF
+
+ ;// Define and reset all officially recongnised variants
+ MACRO
+ _M_DEF_VARIANTS
+ _M_DEF_VARIANT ARM926EJS
+ _M_DEF_VARIANT ARM1136JS
+ _M_DEF_VARIANT ARM1136JS_U
+ _M_DEF_VARIANT CortexA8
+ _M_DEF_VARIANT ARM7TDMI
+ MEND
+
+ MACRO
+ _M_DEF_VARIANT $var
+ GBLL $var
+ GBLL _ok$var
+$var SETL {FALSE}
+ MEND
+
+
+ ;// Variant declaration
+ ;//
+ ;// Define a list of code variants supported by this
+ ;// source file. This macro then chooses the most
+ ;// appropriate variant to build for the currently configured
+ ;// core.
+ ;//
+ MACRO
+ M_VARIANTS $v0,$v1,$v2,$v3,$v4,$v5,$v6,$v7
+ ;// Set to TRUE variants that are supported
+ _M_DEF_VARIANTS
+ _M_VARIANT $v0
+ _M_VARIANT $v1
+ _M_VARIANT $v2
+ _M_VARIANT $v3
+ _M_VARIANT $v4
+ _M_VARIANT $v5
+ _M_VARIANT $v6
+ _M_VARIANT $v7
+
+ ;// Look for first available variant to match a CPU
+ ;// _M_TRY cpu, variant fall back list
+_Variant SETS ""
+ _M_TRY ARM926EJ-S, ARM926EJS
+ _M_TRY ARM1176JZ-S, ARM1136JS
+ _M_TRY ARM1176JZF-S, ARM1136JS
+ _M_TRY ARM1156T2-S, ARM1136JS
+ _M_TRY ARM1156T2F-S, ARM1136JS
+ _M_TRY ARM1136J-S, ARM1136JS
+ _M_TRY ARM1136JF-S, ARM1136JS
+ _M_TRY MPCore, ARM1136JS
+ _M_TRY falcon-vfp, ARM1136JS
+ _M_TRY falcon-full-neon, CortexA8
+ _M_TRY Cortex-A8NoNeon, ARM1136JS
+ _M_TRY Cortex-A8, CortexA8, ARM1136JS
+ _M_TRY Cortex-R4, ARM1136JS
+ _M_TRY ARM7TDMI
+
+ ;// Select the correct variant
+ _M_DEF_VARIANTS
+ IF _Variant=""
+ INFO 1, "No match found for CPU '$_CPU'"
+ ELSE
+$_Variant SETL {TRUE}
+ ENDIF
+ MEND
+
+ ;// Register a variant as available
+ MACRO
+ _M_VARIANT $var
+ IF "$var"=""
+ MEXIT
+ ENDIF
+ IF :LNOT::DEF:_ok$var
+ INFO 1, "Unrecognized variant '$var'"
+ ENDIF
+$var SETL {TRUE}
+ MEND
+
+ ;// For a given CPU, see if any of the variants supporting
+ ;// this CPU are available. The first available variant is
+ ;// chosen
+ MACRO
+ _M_TRY $cpu, $v0,$v1,$v2,$v3,$v4,$v5,$v6,$v7
+ IF "$cpu"<>_CPU
+ MEXIT
+ ENDIF
+ _M_TRY1 $v0
+ _M_TRY1 $v1
+ _M_TRY1 $v2
+ _M_TRY1 $v3
+ _M_TRY1 $v4
+ _M_TRY1 $v5
+ _M_TRY1 $v6
+ _M_TRY1 $v7
+ ;// Check a match was found
+ IF _Variant=""
+ INFO 1, "No variant match found for CPU '$_CPU'"
+ ENDIF
+ MEND
+
+ MACRO
+ _M_TRY1 $var
+ IF "$var"=""
+ MEXIT
+ ENDIF
+ IF (_Variant=""):LAND:$var
+_Variant SETS "$var"
+ ENDIF
+ MEND
+
+;////////////////////////////////////////////////////////
+;// Structure definition
+;////////////////////////////////////////////////////////
+
+ ;// Declare a structure of given name
+ MACRO
+ M_STRUCT $sname
+_Struct SETS "$sname"
+_StOff SETA 0
+ MEND
+
+ ;// Declare a structure field
+ ;// The field is called $sname_$fname
+ ;// $size = the size of each entry, must be power of 2
+ ;// $number = (if provided) the number of entries for an array
+ MACRO
+ M_FIELD $fname, $size, $number
+ IF (_StOff:AND:($size-1))!=0
+_StOff SETA _StOff + ($size - (_StOff:AND:($size-1)))
+ ENDIF
+$_Struct._$fname EQU _StOff
+ IF "$number"<>""
+_StOff SETA _StOff + $size*$number
+ ELSE
+_StOff SETA _StOff + $size
+ ENDIF
+ MEND
+
+
+ MACRO
+ M_ENDSTRUCT
+sizeof_$_Struct EQU _StOff
+_Struct SETS ""
+ MEND
+
+;//////////////////////////////////////////////////////////
+;// Switch and table macros
+;//////////////////////////////////////////////////////////
+
+ ;// Start a relative switch table with register to switch on
+ ;//
+ ;// $v = the register to switch on
+ ;// $s = if specified must be "L" to indicate long
+ ;// this allows a greater range to the case code
+ MACRO
+ M_SWITCH $v, $s
+ ASSERT "$s"="":LOR:"$s"="L"
+_SwLong SETL {FALSE}
+ IF "$s"="L"
+_SwLong SETL {TRUE}
+ ENDIF
+_SwNum SETA _SwNum+1
+ IF {CONFIG}=16
+ ;// Thumb
+ IF _SwLong
+ TBH [pc, $v, LSL#1]
+ ELSE
+ TBB [pc, $v]
+ ENDIF
+_Switch$_SwNum
+ ELSE
+ ;// ARM
+ ADD pc, pc, $v, LSL #2
+ NOP
+ ENDIF
+ MEND
+
+ ;// Add a case to the switch statement
+ MACRO
+ M_CASE $label
+ IF {CONFIG}=16
+ ;// Thumb
+ IF _SwLong
+ DCW ($label - _Switch$_SwNum)/2
+ ELSE
+ DCB ($label - _Switch$_SwNum)/2
+ ENDIF
+ ELSE
+ ;// ARM
+ B $label
+ ENDIF
+ MEND
+
+ ;// End of switch statement
+ MACRO
+ M_ENDSWITCH
+ ALIGN 2
+ MEND
+
+
+;////////////////////////////////////////////////////////
+;// Data area allocation
+;////////////////////////////////////////////////////////
+
+ ;// Constant table allocator macro
+ ;//
+ ;// Creates a new section for each constant table
+ ;// $name is symbol through which the table can be accessed.
+ ;// $align is the optional alignment of the table, log2 of
+ ;// the byte alignment - $align=4 is 16 byte aligned
+ MACRO
+ M_TABLE $name, $align
+ ASSERT :LNOT:_InFunc
+ IF "$align"=""
+ AREA |.constdata|, READONLY, DATA
+ ELSE
+ ;// AREAs inherit the alignment of the first declaration.
+ ;// Therefore for each alignment size we must have an area
+ ;// of a different name.
+ AREA constdata_a$align, READONLY, DATA, ALIGN=$align
+
+ ;// We also force alignment incase we are tagging onto
+ ;// an already started area.
+ ALIGN (1<<$align)
+ ENDIF
+$name
+ MEND
+
+;/////////////////////////////////////////////////////
+;// Macros to allocate space on the stack
+;//
+;// These all assume that the stack is 8-byte aligned
+;// at entry to the function, which means that the
+;// 32-byte alignment macro needs to work in a
+;// bit more of a special way...
+;/////////////////////////////////////////////////////
+
+
+
+
+ ;// Allocate 1-byte aligned area of name
+ ;// $name size $size bytes.
+ MACRO
+ M_ALLOC1 $name, $size
+ ASSERT :LNOT:_InFunc
+$name$_F EQU _SBytes
+_SBytes SETA _SBytes + ($size)
+ MEND
+
+ ;// Allocate 2-byte aligned area of name
+ ;// $name size $size bytes.
+ MACRO
+ M_ALLOC2 $name, $size
+ ASSERT :LNOT:_InFunc
+ IF (_SBytes:AND:1)!=0
+_SBytes SETA _SBytes + (2 - (_SBytes:AND:1))
+ ENDIF
+$name$_F EQU _SBytes
+_SBytes SETA _SBytes + ($size)
+ MEND
+
+ ;// Allocate 4-byte aligned area of name
+ ;// $name size $size bytes.
+ MACRO
+ M_ALLOC4 $name, $size
+ ASSERT :LNOT:_InFunc
+ IF (_SBytes:AND:3)!=0
+_SBytes SETA _SBytes + (4 - (_SBytes:AND:3))
+ ENDIF
+$name$_F EQU _SBytes
+_SBytes SETA _SBytes + ($size)
+ MEND
+
+ ;// Allocate 8-byte aligned area of name
+ ;// $name size $size bytes.
+ MACRO
+ M_ALLOC8 $name, $size
+ ASSERT :LNOT:_InFunc
+ IF (_SBytes:AND:7)!=0
+_SBytes SETA _SBytes + (8 - (_SBytes:AND:7))
+ ENDIF
+$name$_F EQU _SBytes
+_SBytes SETA _SBytes + ($size)
+ MEND
+
+
+ ;// Allocate 8-byte aligned area of name
+ ;// $name size ($size+16) bytes.
+ ;// The extra 16 bytes are later used to align the pointer to 16 bytes
+
+ MACRO
+ M_ALLOC16 $name, $size
+ ASSERT :LNOT:_InFunc
+ IF (_SBytes:AND:7)!=0
+_SBytes SETA _SBytes + (8 - (_SBytes:AND:7))
+ ENDIF
+$name$_F$_16 EQU (_SBytes + 8)
+_SBytes SETA _SBytes + ($size) + 8
+ MEND
+
+ ;// Allocate 8-byte aligned area of name
+ ;// $name size ($size+32) bytes.
+ ;// The extra 32 bytes are later used to align the pointer to 32 bytes
+
+ MACRO
+ M_ALLOC32 $name, $size
+ ASSERT :LNOT:_InFunc
+ IF (_SBytes:AND:7)!=0
+_SBytes SETA _SBytes + (8 - (_SBytes:AND:7))
+ ENDIF
+$name$_F$_32 EQU (_SBytes + 24)
+_SBytes SETA _SBytes + ($size) + 24
+ MEND
+
+
+
+
+ ;// Argument Declaration Macro
+ ;//
+ ;// Allocate an argument name $name
+ ;// size $size bytes
+ MACRO
+ M_ARG $name, $size
+ ASSERT _InFunc
+$name$_F EQU _ABytes
+_ABytes SETA _ABytes + ($size)
+ MEND
+
+;///////////////////////////////////////////////
+;// Macros to access stacked variables
+;///////////////////////////////////////////////
+
+ ;// Macro to perform a data processing operation
+ ;// with a constant second operand
+ MACRO
+ _M_OPC $op,$rd,$rn,$const
+ LCLA _sh
+ LCLA _cst
+_sh SETA 0
+_cst SETA $const
+ IF _cst=0
+ $op $rd, $rn, #_cst
+ MEXIT
+ ENDIF
+ WHILE (_cst:AND:3)=0
+_cst SETA _cst>>2
+_sh SETA _sh+2
+ WEND
+ $op $rd, $rn, #(_cst:AND:0x000000FF)<<_sh
+ IF _cst>=256
+ $op $rd, $rd, #(_cst:AND:0xFFFFFF00)<<_sh
+ ENDIF
+ MEND
+
+ ;// Macro to perform a data access operation
+ ;// Such as LDR or STR
+ ;// The addressing mode is modified such that
+ ;// 1. If no address is given then the name is taken
+ ;// as a stack offset
+ ;// 2. If the addressing mode is not available for the
+ ;// state being assembled for (eg Thumb) then a suitable
+ ;// addressing mode is substituted.
+ ;//
+ ;// On Entry:
+ ;// $i = Instruction to perform (eg "LDRB")
+ ;// $a = Required byte alignment
+ ;// $r = Register(s) to transfer (eg "r1")
+ ;// $a0,$a1,$a2. Addressing mode and condition. One of:
+ ;// label {,cc}
+ ;// [base] {,,,cc}
+ ;// [base, offset]{!} {,,cc}
+ ;// [base, offset, shift]{!} {,cc}
+ ;// [base], offset {,,cc}
+ ;// [base], offset, shift {,cc}
+ MACRO
+ _M_DATA $i,$a,$r,$a0,$a1,$a2,$a3
+ IF "$a0":LEFT:1="["
+ IF "$a1"=""
+ $i$a3 $r, $a0
+ ELSE
+ IF "$a0":RIGHT:1="]"
+ IF "$a2"=""
+ _M_POSTIND $i$a3, "$r", $a0, $a1
+ ELSE
+ _M_POSTIND $i$a3, "$r", $a0, "$a1,$a2"
+ ENDIF
+ ELSE
+ IF "$a2"=""
+ _M_PREIND $i$a3, "$r", $a0, $a1
+ ELSE
+ _M_PREIND $i$a3, "$r", $a0, "$a1,$a2"
+ ENDIF
+ ENDIF
+ ENDIF
+ ELSE
+ LCLA _Offset
+_Offset SETA _Workspace + $a0$_F
+ ASSERT (_Offset:AND:($a-1))=0
+ $i$a1 $r, [sp, #_Offset]
+ ENDIF
+ MEND
+
+ ;// Handle post indexed load/stores
+ ;// op reg, [base], offset
+ MACRO
+ _M_POSTIND $i,$r,$a0,$a1
+ LCLS _base
+ LCLS _offset
+ IF {CONFIG}=16 ;// Thumb
+_base SETS ("$a0":LEFT:(:LEN:"$a0"-1)):RIGHT:(:LEN:"$a0"-2) ;// remove []
+_offset SETS "$a1"
+ IF _offset:LEFT:1="+"
+_offset SETS _offset:RIGHT:(:LEN:_offset-1)
+ ENDIF
+ $i $r, $a0
+ IF _offset:LEFT:1="-"
+_offset SETS _offset:RIGHT:(:LEN:_offset-1)
+ SUB $_base, $_base, $_offset
+ ELSE
+ ADD $_base, $_base, $_offset
+ ENDIF
+ ELSE ;// ARM
+ $i $r, $a0, $a1
+ ENDIF
+ MEND
+
+ ;// Handle pre indexed load/store
+ ;// op reg, [base, offset]{!}
+ MACRO
+ _M_PREIND $i,$r,$a0,$a1
+ LCLS _base
+ LCLS _offset
+ IF ({CONFIG}=16):LAND:(("$a1":RIGHT:2)="]!")
+_base SETS "$a0":RIGHT:(:LEN:("$a0")-1)
+_offset SETS "$a1":LEFT:(:LEN:("$a1")-2)
+ $i $r, [$_base, $_offset]
+ ADD $_base, $_base, $_offset
+ ELSE
+ $i $r, $a0, $a1
+ ENDIF
+ MEND
+
+ ;// Load unsigned byte from stack
+ MACRO
+ M_LDRB $r,$a0,$a1,$a2,$a3
+ _M_DATA "LDRB",1,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Load signed byte from stack
+ MACRO
+ M_LDRSB $r,$a0,$a1,$a2,$a3
+ _M_DATA "LDRSB",1,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Store byte to stack
+ MACRO
+ M_STRB $r,$a0,$a1,$a2,$a3
+ _M_DATA "STRB",1,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Load unsigned half word from stack
+ MACRO
+ M_LDRH $r,$a0,$a1,$a2,$a3
+ _M_DATA "LDRH",2,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Load signed half word from stack
+ MACRO
+ M_LDRSH $r,$a0,$a1,$a2,$a3
+ _M_DATA "LDRSH",2,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Store half word to stack
+ MACRO
+ M_STRH $r,$a0,$a1,$a2,$a3
+ _M_DATA "STRH",2,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Load word from stack
+ MACRO
+ M_LDR $r,$a0,$a1,$a2,$a3
+ _M_DATA "LDR",4,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Store word to stack
+ MACRO
+ M_STR $r,$a0,$a1,$a2,$a3
+ _M_DATA "STR",4,$r,$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Load double word from stack
+ MACRO
+ M_LDRD $r0,$r1,$a0,$a1,$a2,$a3
+ _M_DATA "LDRD",8,"$r0,$r1",$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Store double word to stack
+ MACRO
+ M_STRD $r0,$r1,$a0,$a1,$a2,$a3
+ _M_DATA "STRD",8,"$r0,$r1",$a0,$a1,$a2,$a3
+ MEND
+
+ ;// Get absolute address of stack allocated location
+ MACRO
+ M_ADR $a, $b, $cc
+ _M_OPC ADD$cc, $a, sp, (_Workspace + $b$_F)
+ MEND
+
+ ;// Get absolute address of stack allocated location and align the address to 16 bytes
+ MACRO
+ M_ADR16 $a, $b, $cc
+ _M_OPC ADD$cc, $a, sp, (_Workspace + $b$_F$_16)
+
+ ;// Now align $a to 16 bytes
+ BIC$cc $a,$a,#0x0F
+ MEND
+
+ ;// Get absolute address of stack allocated location and align the address to 32 bytes
+ MACRO
+ M_ADR32 $a, $b, $cc
+ _M_OPC ADD$cc, $a, sp, (_Workspace + $b$_F$_32)
+
+ ;// Now align $a to 32 bytes
+ BIC$cc $a,$a,#0x1F
+ MEND
+
+;//////////////////////////////////////////////////////////
+;// Function header and footer macros
+;//////////////////////////////////////////////////////////
+
+ ;// Function Header Macro
+ ;// Generates the function prologue
+ ;// Note that functions should all be "stack-moves-once"
+ ;// The FNSTART and FNEND macros should be the only places
+ ;// where the stack moves.
+ ;//
+ ;// $name = function name
+ ;// $rreg = "" don't stack any registers
+ ;// "lr" stack "lr" only
+ ;// "rN" stack registers "r4-rN,lr"
+ ;// $dreg = "" don't stack any D registers
+ ;// "dN" stack registers "d8-dN"
+ ;//
+ ;// Note: ARM Archicture procedure call standard AAPCS
+ ;// states that r4-r11, sp, d8-d15 must be preserved by
+ ;// a compliant function.
+ MACRO
+ M_START $name, $rreg, $dreg
+ ASSERT :LNOT:_InFunc
+ ASSERT "$name"!=""
+_InFunc SETL {TRUE}
+_RBytes SETA 0
+_Workspace SETA 0
+
+ ;// Create an area for the function
+ AREA |.text|, CODE
+ EXPORT $name
+$name FUNCTION
+
+ ;// Save R registers
+ _M_GETRREGLIST $rreg
+ IF _RRegList<>""
+ STMFD sp!, {$_RRegList, lr}
+ ENDIF
+
+ ;// Save D registers
+ _M_GETDREGLIST $dreg
+ IF _DRegList<>""
+ VSTMFD sp!, {$_DRegList}
+ ENDIF
+
+
+ ;// Ensure size claimed on stack is 8-byte aligned
+ IF ((_SBytes:AND:7)!=0)
+_SBytes SETA _SBytes + (8 - (_SBytes:AND:7))
+ ENDIF
+
+ IF (_SBytes!=0)
+ _M_OPC SUB, sp, sp, _SBytes
+ ENDIF
+
+
+_ABytes SETA _SBytes + _RBytes - _Workspace
+
+
+ ;// Print function name if debug enabled
+ M_PRINTF "$name\n",
+ MEND
+
+ ;// Work out a list of R saved registers
+ MACRO
+ _M_GETRREGLIST $rreg
+ IF "$rreg"=""
+_RRegList SETS ""
+ MEXIT
+ ENDIF
+ IF "$rreg"="lr":LOR:"$rreg"="r4"
+_RRegList SETS "r4"
+_RBytes SETA _RBytes+8
+ MEXIT
+ ENDIF
+ IF "$rreg"="r5":LOR:"$rreg"="r6"
+_RRegList SETS "r4-r6"
+_RBytes SETA _RBytes+16
+ MEXIT
+ ENDIF
+ IF "$rreg"="r7":LOR:"$rreg"="r8"
+_RRegList SETS "r4-r8"
+_RBytes SETA _RBytes+24
+ MEXIT
+ ENDIF
+ IF "$rreg"="r9":LOR:"$rreg"="r10"
+_RRegList SETS "r4-r10"
+_RBytes SETA _RBytes+32
+ MEXIT
+ ENDIF
+ IF "$rreg"="r11":LOR:"$rreg"="r12"
+_RRegList SETS "r4-r12"
+_RBytes SETA _RBytes+40
+ MEXIT
+ ENDIF
+ INFO 1, "Unrecognized saved r register limit '$rreg'"
+ MEND
+
+ ;// Work out a list of D saved registers
+ MACRO
+ _M_GETDREGLIST $dreg
+ IF "$dreg"=""
+_DRegList SETS ""
+ MEXIT
+ ENDIF
+ IF "$dreg"="d8"
+_DRegList SETS "d8"
+_RBytes SETA _RBytes+8
+ MEXIT
+ ENDIF
+ IF "$dreg"="d9"
+_DRegList SETS "d8-d9"
+_RBytes SETA _RBytes+16
+ MEXIT
+ ENDIF
+ IF "$dreg"="d10"
+_DRegList SETS "d8-d10"
+_RBytes SETA _RBytes+24
+ MEXIT
+ ENDIF
+ IF "$dreg"="d11"
+_DRegList SETS "d8-d11"
+_RBytes SETA _RBytes+32
+ MEXIT
+ ENDIF
+ IF "$dreg"="d12"
+_DRegList SETS "d8-d12"
+_RBytes SETA _RBytes+40
+ MEXIT
+ ENDIF
+ IF "$dreg"="d13"
+_DRegList SETS "d8-d13"
+_RBytes SETA _RBytes+48
+ MEXIT
+ ENDIF
+ IF "$dreg"="d14"
+_DRegList SETS "d8-d14"
+_RBytes SETA _RBytes+56
+ MEXIT
+ ENDIF
+ IF "$dreg"="d15"
+_DRegList SETS "d8-d15"
+_RBytes SETA _RBytes+64
+ MEXIT
+ ENDIF
+ INFO 1, "Unrecognized saved d register limit '$dreg'"
+ MEND
+
+ ;// Produce function return instructions
+ MACRO
+ _M_RET $cc
+ IF _DRegList<>""
+ VPOP$cc {$_DRegList}
+ ENDIF
+ IF _RRegList=""
+ BX$cc lr
+ ELSE
+ LDM$cc.FD sp!, {$_RRegList, pc}
+ ENDIF
+ MEND
+
+ ;// Early Function Exit Macro
+ ;// $cc = condition to exit with
+ ;// (Example: M_EXIT EQ)
+ MACRO
+ M_EXIT $cc
+ ASSERT _InFunc
+ IF _SBytes!=0
+ ;// Restore stack frame and exit
+ B$cc _End$_F
+ ELSE
+ ;// Can return directly
+ _M_RET $cc
+ ENDIF
+ MEND
+
+ ;// Function Footer Macro
+ ;// Generates the function epilogue
+ MACRO
+ M_END
+ ASSERT _InFunc
+_InFunc SETL {FALSE}
+_End$_F
+
+ ;// Restore the stack pointer to its original value on function entry
+ IF _SBytes!=0
+ _M_OPC ADD, sp, sp, _SBytes
+ ENDIF
+ _M_RET
+ ENDFUNC
+
+ ;// Reset the global stack tracking variables back to their
+ ;// initial values, and increment the function count
+_SBytes SETA 0
+_F SETA _F+1
+ MEND
+
+
+;//==========================================================================
+;// Debug Macros
+;//==========================================================================
+
+ GBLL DEBUG_ON
+DEBUG_ON SETL {FALSE}
+ GBLL DEBUG_STALLS_ON
+DEBUG_STALLS_ON SETL {FALSE}
+
+ ;//==========================================================================
+ ;// Debug call to printf
+ ;// M_PRINTF $format, $val0, $val1, $val2
+ ;//
+ ;// Examples:
+ ;// M_PRINTF "x=%08x\n", r0
+ ;//
+ ;// This macro preserves the value of all registers including the
+ ;// flags.
+ ;//==========================================================================
+
+ MACRO
+ M_PRINTF $format, $val0, $val1, $val2
+ IF DEBUG_ON
+
+ IMPORT printf
+ LCLA nArgs
+nArgs SETA 0
+
+ ;// save registers so we don't corrupt them
+ STMFD sp!, {r0-r12, lr}
+
+ ;// Drop stack to give us some workspace
+ SUB sp, sp, #16
+
+ ;// Save registers we need to print to the stack
+ IF "$val2" <> ""
+ ASSERT "$val1" <> ""
+ STR $val2, [sp, #8]
+nArgs SETA nArgs+1
+ ENDIF
+ IF "$val1" <> ""
+ ASSERT "$val0" <> ""
+ STR $val1, [sp, #4]
+nArgs SETA nArgs+1
+ ENDIF
+ IF "$val0"<>""
+ STR $val0, [sp]
+nArgs SETA nArgs+1
+ ENDIF
+
+ ;// Now we are safe to corrupt registers
+ ADR r0, %FT00
+ IF nArgs=1
+ LDR r1, [sp]
+ ENDIF
+ IF nArgs=2
+ LDMIA sp, {r1,r2}
+ ENDIF
+ IF nArgs=3
+ LDMIA sp, {r1,r2,r3}
+ ENDIF
+
+ ;// print the values
+ MRS r4, cpsr ;// preserve flags
+ BL printf
+ MSR cpsr_f, r4 ;// restore flags
+ B %FT01
+00 ;// string to print
+ DCB "$format", 0
+ ALIGN
+01 ;// Finished
+ ADD sp, sp, #16
+ ;// Restore registers
+ LDMFD sp!, {r0-r12,lr}
+
+ ENDIF ;// DEBUG_ON
+ MEND
+
+
+ ;// Stall Simulation Macro
+ ;// Inserts a given number of NOPs for the currently
+ ;// defined platform
+ MACRO
+ M_STALL $plat1stall, $plat2stall, $plat3stall, $plat4stall, $plat5stall, $plat6stall
+ IF DEBUG_STALLS_ON
+ _M_STALL_SUB $plat1stall
+ _M_STALL_SUB $plat2stall
+ _M_STALL_SUB $plat3stall
+ _M_STALL_SUB $plat4stall
+ _M_STALL_SUB $plat5stall
+ _M_STALL_SUB $plat6stall
+ ENDIF
+ MEND
+
+ MACRO
+ _M_STALL_SUB $platstall
+ IF "$platstall"!=""
+ LCLA _pllen
+ LCLS _pl
+ LCLL _pllog
+_pllen SETA :LEN:"$platstall"
+_pl SETS "$platstall":LEFT:(_pllen - 2)
+ IF :DEF:$_pl
+ IF $_pl
+ LCLS _st
+ LCLA _stnum
+_st SETS "$platstall":RIGHT:1
+_stnum SETA $_st
+ WHILE _stnum>0
+ MOV sp, sp
+_stnum SETA _stnum - 1
+ WEND
+ ENDIF
+ ENDIF
+ ENDIF
+ MEND
+
+
+
+;//==========================================================================
+;// Endian Invarience Macros
+;//
+;// The idea behind these macros is that if an array is
+;// loaded as words then the SMUL00 macro will multiply
+;// array elements 0 regardless of the endianess of the
+;// system. For little endian SMUL00=SMULBB, for big
+;// endian SMUL00=SMULTT and similarly for other packed operations.
+;//
+;//==========================================================================
+
+ MACRO
+ LIBI4 $comli, $combi, $a, $b, $c, $d, $cc
+ IF {ENDIAN}="big"
+ $combi.$cc $a, $b, $c, $d
+ ELSE
+ $comli.$cc $a, $b, $c, $d
+ ENDIF
+ MEND
+
+ MACRO
+ LIBI3 $comli, $combi, $a, $b, $c, $cc
+ IF {ENDIAN}="big"
+ $combi.$cc $a, $b, $c
+ ELSE
+ $comli.$cc $a, $b, $c
+ ENDIF
+ MEND
+
+ ;// SMLAxy macros
+
+ MACRO
+ SMLA00 $a, $b, $c, $d, $cc
+ LIBI4 SMLABB, SMLATT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA01 $a, $b, $c, $d, $cc
+ LIBI4 SMLABT, SMLATB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA0B $a, $b, $c, $d, $cc
+ LIBI4 SMLABB, SMLATB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA0T $a, $b, $c, $d, $cc
+ LIBI4 SMLABT, SMLATT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA10 $a, $b, $c, $d, $cc
+ LIBI4 SMLATB, SMLABT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA11 $a, $b, $c, $d, $cc
+ LIBI4 SMLATT, SMLABB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA1B $a, $b, $c, $d, $cc
+ LIBI4 SMLATB, SMLABB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLA1T $a, $b, $c, $d, $cc
+ LIBI4 SMLATT, SMLABT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAB0 $a, $b, $c, $d, $cc
+ LIBI4 SMLABB, SMLABT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAB1 $a, $b, $c, $d, $cc
+ LIBI4 SMLABT, SMLABB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAT0 $a, $b, $c, $d, $cc
+ LIBI4 SMLATB, SMLATT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAT1 $a, $b, $c, $d, $cc
+ LIBI4 SMLATT, SMLATB, $a, $b, $c, $d, $cc
+ MEND
+
+ ;// SMULxy macros
+
+ MACRO
+ SMUL00 $a, $b, $c, $cc
+ LIBI3 SMULBB, SMULTT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL01 $a, $b, $c, $cc
+ LIBI3 SMULBT, SMULTB, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL0B $a, $b, $c, $cc
+ LIBI3 SMULBB, SMULTB, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL0T $a, $b, $c, $cc
+ LIBI3 SMULBT, SMULTT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL10 $a, $b, $c, $cc
+ LIBI3 SMULTB, SMULBT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL11 $a, $b, $c, $cc
+ LIBI3 SMULTT, SMULBB, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL1B $a, $b, $c, $cc
+ LIBI3 SMULTB, SMULBB, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMUL1T $a, $b, $c, $cc
+ LIBI3 SMULTT, SMULBT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMULB0 $a, $b, $c, $cc
+ LIBI3 SMULBB, SMULBT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMULB1 $a, $b, $c, $cc
+ LIBI3 SMULBT, SMULBB, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMULT0 $a, $b, $c, $cc
+ LIBI3 SMULTB, SMULTT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMULT1 $a, $b, $c, $cc
+ LIBI3 SMULTT, SMULTB, $a, $b, $c, $cc
+ MEND
+
+ ;// SMLAWx, SMULWx macros
+
+ MACRO
+ SMLAW0 $a, $b, $c, $d, $cc
+ LIBI4 SMLAWB, SMLAWT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAW1 $a, $b, $c, $d, $cc
+ LIBI4 SMLAWT, SMLAWB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMULW0 $a, $b, $c, $cc
+ LIBI3 SMULWB, SMULWT, $a, $b, $c, $cc
+ MEND
+
+ MACRO
+ SMULW1 $a, $b, $c, $cc
+ LIBI3 SMULWT, SMULWB, $a, $b, $c, $cc
+ MEND
+
+ ;// SMLALxy macros
+
+
+ MACRO
+ SMLAL00 $a, $b, $c, $d, $cc
+ LIBI4 SMLALBB, SMLALTT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL01 $a, $b, $c, $d, $cc
+ LIBI4 SMLALBT, SMLALTB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL0B $a, $b, $c, $d, $cc
+ LIBI4 SMLALBB, SMLALTB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL0T $a, $b, $c, $d, $cc
+ LIBI4 SMLALBT, SMLALTT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL10 $a, $b, $c, $d, $cc
+ LIBI4 SMLALTB, SMLALBT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL11 $a, $b, $c, $d, $cc
+ LIBI4 SMLALTT, SMLALBB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL1B $a, $b, $c, $d, $cc
+ LIBI4 SMLALTB, SMLALBB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLAL1T $a, $b, $c, $d, $cc
+ LIBI4 SMLALTT, SMLALBT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLALB0 $a, $b, $c, $d, $cc
+ LIBI4 SMLALBB, SMLALBT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLALB1 $a, $b, $c, $d, $cc
+ LIBI4 SMLALBT, SMLALBB, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLALT0 $a, $b, $c, $d, $cc
+ LIBI4 SMLALTB, SMLALTT, $a, $b, $c, $d, $cc
+ MEND
+
+ MACRO
+ SMLALT1 $a, $b, $c, $d, $cc
+ LIBI4 SMLALTT, SMLALTB, $a, $b, $c, $d, $cc
+ MEND
+
+ ENDIF ;// ARMCOMM_S_H
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armOMX.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armOMX.h
new file mode 100755
index 0000000..7a68d14
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/armOMX.h
@@ -0,0 +1,274 @@
+/*
+ *
+ * File Name: armOMX_ReleaseVersion.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * This file allows a version of the OMX DL libraries to be built where some or
+ * all of the function names can be given a user specified suffix.
+ *
+ * You might want to use it where:
+ *
+ * - you want to rename a function "out of the way" so that you could replace
+ * a function with a different version (the original version would still be
+ * in the library just with a different name - so you could debug the new
+ * version by comparing it to the output of the old)
+ *
+ * - you want to rename all the functions to versions with a suffix so that
+ * you can include two versions of the library and choose between functions
+ * at runtime.
+ *
+ * e.g. omxIPBM_Copy_U8_C1R could be renamed omxIPBM_Copy_U8_C1R_CortexA8
+ *
+ */
+
+
+#ifndef _armOMX_H_
+#define _armOMX_H_
+
+
+/* We need to define these two macros in order to expand and concatenate the names */
+#define OMXCAT2BAR(A, B) omx ## A ## B
+#define OMXCATBAR(A, B) OMXCAT2BAR(A, B)
+
+/* Define the suffix to add to all functions - the default is no suffix */
+#define BARE_SUFFIX
+
+
+
+/* Define what happens to the bare suffix-less functions, down to the sub-domain accuracy */
+#define OMXACAAC_SUFFIX BARE_SUFFIX
+#define OMXACMP3_SUFFIX BARE_SUFFIX
+#define OMXICJP_SUFFIX BARE_SUFFIX
+#define OMXIPBM_SUFFIX BARE_SUFFIX
+#define OMXIPCS_SUFFIX BARE_SUFFIX
+#define OMXIPPP_SUFFIX BARE_SUFFIX
+#define OMXSP_SUFFIX BARE_SUFFIX
+#define OMXVCCOMM_SUFFIX BARE_SUFFIX
+#define OMXVCM4P10_SUFFIX BARE_SUFFIX
+#define OMXVCM4P2_SUFFIX BARE_SUFFIX
+
+
+
+
+/* Define what the each bare, un-suffixed OpenMAX API function names is to be renamed */
+#define omxACAAC_DecodeChanPairElt OMXCATBAR(ACAAC_DecodeChanPairElt, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeDatStrElt OMXCATBAR(ACAAC_DecodeDatStrElt, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeFillElt OMXCATBAR(ACAAC_DecodeFillElt, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeIsStereo_S32 OMXCATBAR(ACAAC_DecodeIsStereo_S32, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeMsPNS_S32_I OMXCATBAR(ACAAC_DecodeMsPNS_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeMsStereo_S32_I OMXCATBAR(ACAAC_DecodeMsStereo_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodePrgCfgElt OMXCATBAR(ACAAC_DecodePrgCfgElt, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeTNS_S32_I OMXCATBAR(ACAAC_DecodeTNS_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_DeinterleaveSpectrum_S32 OMXCATBAR(ACAAC_DeinterleaveSpectrum_S32, OMXACAAC_SUFFIX)
+#define omxACAAC_EncodeTNS_S32_I OMXCATBAR(ACAAC_EncodeTNS_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_LongTermPredict_S32 OMXCATBAR(ACAAC_LongTermPredict_S32, OMXACAAC_SUFFIX)
+#define omxACAAC_LongTermReconstruct_S32_I OMXCATBAR(ACAAC_LongTermReconstruct_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_MDCTFwd_S32 OMXCATBAR(ACAAC_MDCTFwd_S32, OMXACAAC_SUFFIX)
+#define omxACAAC_MDCTInv_S32_S16 OMXCATBAR(ACAAC_MDCTInv_S32_S16, OMXACAAC_SUFFIX)
+#define omxACAAC_NoiselessDecode OMXCATBAR(ACAAC_NoiselessDecode, OMXACAAC_SUFFIX)
+#define omxACAAC_QuantInv_S32_I OMXCATBAR(ACAAC_QuantInv_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_UnpackADIFHeader OMXCATBAR(ACAAC_UnpackADIFHeader, OMXACAAC_SUFFIX)
+#define omxACAAC_UnpackADTSFrameHeader OMXCATBAR(ACAAC_UnpackADTSFrameHeader, OMXACAAC_SUFFIX)
+
+
+#define omxACMP3_HuffmanDecode_S32 OMXCATBAR(ACMP3_HuffmanDecode_S32, OMXACMP3_SUFFIX)
+#define omxACMP3_HuffmanDecodeSfb_S32 OMXCATBAR(ACMP3_HuffmanDecodeSfb_S32, OMXACMP3_SUFFIX)
+#define omxACMP3_HuffmanDecodeSfbMbp_S32 OMXCATBAR(ACMP3_HuffmanDecodeSfbMbp_S32, OMXACMP3_SUFFIX)
+#define omxACMP3_MDCTInv_S32 OMXCATBAR(ACMP3_MDCTInv_S32, OMXACMP3_SUFFIX)
+#define omxACMP3_ReQuantize_S32_I OMXCATBAR(ACMP3_ReQuantize_S32_I, OMXACMP3_SUFFIX)
+#define omxACMP3_ReQuantizeSfb_S32_I OMXCATBAR(ACMP3_ReQuantizeSfb_S32_I, OMXACMP3_SUFFIX)
+#define omxACMP3_SynthPQMF_S32_S16 OMXCATBAR(ACMP3_SynthPQMF_S32_S16, OMXACMP3_SUFFIX)
+#define omxACMP3_UnpackFrameHeader OMXCATBAR(ACMP3_UnpackFrameHeader, OMXACMP3_SUFFIX)
+#define omxACMP3_UnpackScaleFactors_S8 OMXCATBAR(ACMP3_UnpackScaleFactors_S8, OMXACMP3_SUFFIX)
+#define omxACMP3_UnpackSideInfo OMXCATBAR(ACMP3_UnpackSideInfo, OMXACMP3_SUFFIX)
+
+#define omxICJP_CopyExpand_U8_C3 OMXCATBAR(ICJP_CopyExpand_U8_C3, OMXICJP_SUFFIX)
+#define omxICJP_DCTFwd_S16 OMXCATBAR(ICJP_DCTFwd_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTFwd_S16_I OMXCATBAR(ICJP_DCTFwd_S16_I, OMXICJP_SUFFIX)
+#define omxICJP_DCTInv_S16 OMXCATBAR(ICJP_DCTInv_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTInv_S16_I OMXCATBAR(ICJP_DCTInv_S16_I, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantFwd_Multiple_S16 OMXCATBAR(ICJP_DCTQuantFwd_Multiple_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantFwd_S16 OMXCATBAR(ICJP_DCTQuantFwd_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantFwd_S16_I OMXCATBAR(ICJP_DCTQuantFwd_S16_I, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantFwdTableInit OMXCATBAR(ICJP_DCTQuantFwdTableInit, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantInv_Multiple_S16 OMXCATBAR(ICJP_DCTQuantInv_Multiple_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantInv_S16 OMXCATBAR(ICJP_DCTQuantInv_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantInv_S16_I OMXCATBAR(ICJP_DCTQuantInv_S16_I, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantInvTableInit OMXCATBAR(ICJP_DCTQuantInvTableInit, OMXICJP_SUFFIX)
+#define omxICJP_DecodeHuffman8x8_Direct_S16_C1 OMXCATBAR(ICJP_DecodeHuffman8x8_Direct_S16_C1, OMXICJP_SUFFIX)
+#define omxICJP_DecodeHuffmanSpecGetBufSize_U8 OMXCATBAR(ICJP_DecodeHuffmanSpecGetBufSize_U8, OMXICJP_SUFFIX)
+#define omxICJP_DecodeHuffmanSpecInit_U8 OMXCATBAR(ICJP_DecodeHuffmanSpecInit_U8, OMXICJP_SUFFIX)
+#define omxICJP_EncodeHuffman8x8_Direct_S16_U1_C1 OMXCATBAR(ICJP_EncodeHuffman8x8_Direct_S16_U1_C1, OMXICJP_SUFFIX)
+#define omxICJP_EncodeHuffmanSpecGetBufSize_U8 OMXCATBAR(ICJP_EncodeHuffmanSpecGetBufSize_U8, OMXICJP_SUFFIX)
+#define omxICJP_EncodeHuffmanSpecInit_U8 OMXCATBAR(ICJP_EncodeHuffmanSpecInit_U8, OMXICJP_SUFFIX)
+
+#define omxIPBM_AddC_U8_C1R_Sfs OMXCATBAR(IPBM_AddC_U8_C1R_Sfs, OMXIPBM_SUFFIX)
+#define omxIPBM_Copy_U8_C1R OMXCATBAR(IPBM_Copy_U8_C1R, OMXIPBM_SUFFIX)
+#define omxIPBM_Copy_U8_C3R OMXCATBAR(IPBM_Copy_U8_C3R, OMXIPBM_SUFFIX)
+#define omxIPBM_Mirror_U8_C1R OMXCATBAR(IPBM_Mirror_U8_C1R, OMXIPBM_SUFFIX)
+#define omxIPBM_MulC_U8_C1R_Sfs OMXCATBAR(IPBM_MulC_U8_C1R_Sfs, OMXIPBM_SUFFIX)
+
+#define omxIPCS_ColorTwistQ14_U8_C3R OMXCATBAR(IPCS_ColorTwistQ14_U8_C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR565ToYCbCr420LS_MCU_U16_S16_C3P3R OMXCATBAR(IPCS_BGR565ToYCbCr420LS_MCU_U16_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR565ToYCbCr422LS_MCU_U16_S16_C3P3R OMXCATBAR(IPCS_BGR565ToYCbCr422LS_MCU_U16_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR565ToYCbCr444LS_MCU_U16_S16_C3P3R OMXCATBAR(IPCS_BGR565ToYCbCr444LS_MCU_U16_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR888ToYCbCr420LS_MCU_U8_S16_C3P3R OMXCATBAR(IPCS_BGR888ToYCbCr420LS_MCU_U8_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR888ToYCbCr422LS_MCU_U8_S16_C3P3R OMXCATBAR(IPCS_BGR888ToYCbCr422LS_MCU_U8_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR888ToYCbCr444LS_MCU_U8_S16_C3P3R OMXCATBAR(IPCS_BGR888ToYCbCr444LS_MCU_U8_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420RszCscRotBGR_U8_P3C3R OMXCATBAR(IPCS_YCbCr420RszCscRotBGR_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420RszRot_U8_P3R OMXCATBAR(IPCS_YCbCr420RszRot_U8_P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420ToBGR565_U8_U16_P3C3R OMXCATBAR(IPCS_YCbCr420ToBGR565_U8_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420ToBGR565LS_MCU_S16_U16_P3C3R OMXCATBAR(IPCS_YCbCr420ToBGR565LS_MCU_S16_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420ToBGR888LS_MCU_S16_U8_P3C3R OMXCATBAR(IPCS_YCbCr420ToBGR888LS_MCU_S16_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422RszCscRotBGR_U8_P3C3R OMXCATBAR(IPCS_YCbCr422RszCscRotBGR_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_CbYCrY422RszCscRotBGR_U8_U16_C2R OMXCATBAR(IPCS_CbYCrY422RszCscRotBGR_U8_U16_C2R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422RszRot_U8_P3R OMXCATBAR(IPCS_YCbCr422RszRot_U8_P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbYCr422ToBGR565_U8_U16_C2C3R OMXCATBAR(IPCS_YCbYCr422ToBGR565_U8_U16_C2C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422ToBGR565LS_MCU_S16_U16_P3C3R OMXCATBAR(IPCS_YCbCr422ToBGR565LS_MCU_S16_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbYCr422ToBGR888_U8_C2C3R OMXCATBAR(IPCS_YCbYCr422ToBGR888_U8_C2C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422ToBGR888LS_MCU_S16_U8_P3C3R OMXCATBAR(IPCS_YCbCr422ToBGR888LS_MCU_S16_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422ToBGR888LS_MCU_S16_U8_P3C3R OMXCATBAR(IPCS_YCbCr422ToBGR888LS_MCU_S16_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_CbYCrY422ToYCbCr420Rotate_U8_C2P3R OMXCATBAR(IPCS_CbYCrY422ToYCbCr420Rotate_U8_C2P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422ToYCbCr420Rotate_U8_P3R OMXCATBAR(IPCS_YCbCr422ToYCbCr420Rotate_U8_P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr444ToBGR565_U8_U16_C3R OMXCATBAR(IPCS_YCbCr444ToBGR565_U8_U16_C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr444ToBGR565_U8_U16_P3C3R OMXCATBAR(IPCS_YCbCr444ToBGR565_U8_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr444ToBGR565LS_MCU_S16_U16_P3C3R OMXCATBAR(IPCS_YCbCr444ToBGR565LS_MCU_S16_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr444ToBGR888_U8_C3R OMXCATBAR(IPCS_YCbCr444ToBGR888_U8_C3R, OMXIPCS_SUFFIX)
+
+#define omxIPPP_Deblock_HorEdge_U8_I OMXCATBAR(IPPP_Deblock_HorEdge_U8_I, OMXIPPP_SUFFIX)
+#define omxIPPP_Deblock_VerEdge_U8_I OMXCATBAR(IPPP_Deblock_VerEdge_U8_I, OMXIPPP_SUFFIX)
+#define omxIPPP_FilterFIR_U8_C1R OMXCATBAR(IPPP_FilterFIR_U8_C1R, OMXIPPP_SUFFIX)
+#define omxIPPP_FilterMedian_U8_C1R OMXCATBAR(IPPP_FilterMedian_U8_C1R, OMXIPPP_SUFFIX)
+#define omxIPPP_GetCentralMoment_S64 OMXCATBAR(IPPP_GetCentralMoment_S64, OMXIPPP_SUFFIX)
+#define omxIPPP_GetSpatialMoment_S64 OMXCATBAR(IPPP_GetSpatialMoment_S64, OMXIPPP_SUFFIX)
+#define omxIPPP_MomentGetStateSize OMXCATBAR(IPPP_MomentGetStateSize, OMXIPPP_SUFFIX)
+#define omxIPPP_MomentInit OMXCATBAR(IPPP_MomentInit, OMXIPPP_SUFFIX)
+#define omxIPPP_Moments_U8_C1R OMXCATBAR(IPPP_Moments_U8_C1R, OMXIPPP_SUFFIX)
+#define omxIPPP_Moments_U8_C3R OMXCATBAR(IPPP_Moments_U8_C3R, OMXIPPP_SUFFIX)
+
+#define omxSP_BlockExp_S16 OMXCATBAR(SP_BlockExp_S16, OMXSP_SUFFIX)
+#define omxSP_BlockExp_S32 OMXCATBAR(SP_BlockExp_S32, OMXSP_SUFFIX)
+#define omxSP_Copy_S16 OMXCATBAR(SP_Copy_S16, OMXSP_SUFFIX)
+#define omxSP_DotProd_S16 OMXCATBAR(SP_DotProd_S16, OMXSP_SUFFIX)
+#define omxSP_DotProd_S16_Sfs OMXCATBAR(SP_DotProd_S16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTFwd_CToC_SC16_Sfs OMXCATBAR(SP_FFTFwd_CToC_SC16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTFwd_CToC_SC32_Sfs OMXCATBAR(SP_FFTFwd_CToC_SC32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTFwd_RToCCS_S16S32_Sfs OMXCATBAR(SP_FFTFwd_RToCCS_S16S32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTFwd_RToCCS_S32_Sfs OMXCATBAR(SP_FFTFwd_RToCCS_S32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTGetBufSize_C_SC16 OMXCATBAR(SP_FFTGetBufSize_C_SC16, OMXSP_SUFFIX)
+#define omxSP_FFTGetBufSize_C_SC32 OMXCATBAR(SP_FFTGetBufSize_C_SC32, OMXSP_SUFFIX)
+#define omxSP_FFTGetBufSize_R_S16S32 OMXCATBAR(SP_FFTGetBufSize_R_S16S32, OMXSP_SUFFIX)
+#define omxSP_FFTGetBufSize_R_S32 OMXCATBAR(SP_FFTGetBufSize_R_S32, OMXSP_SUFFIX)
+#define omxSP_FFTInit_C_SC16 OMXCATBAR(SP_FFTInit_C_SC16, OMXSP_SUFFIX)
+#define omxSP_FFTInit_C_SC32 OMXCATBAR(SP_FFTInit_C_SC32, OMXSP_SUFFIX)
+#define omxSP_FFTInit_R_S16S32 OMXCATBAR(SP_FFTInit_R_S16S32, OMXSP_SUFFIX)
+#define omxSP_FFTInit_R_S32 OMXCATBAR(SP_FFTInit_R_S32, OMXSP_SUFFIX)
+#define omxSP_FFTInv_CCSToR_S32_Sfs OMXCATBAR(SP_FFTInv_CCSToR_S32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTInv_CCSToR_S32S16_Sfs OMXCATBAR(SP_FFTInv_CCSToR_S32S16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTInv_CToC_SC16_Sfs OMXCATBAR(SP_FFTInv_CToC_SC16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTInv_CToC_SC32_Sfs OMXCATBAR(SP_FFTInv_CToC_SC32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FilterMedian_S32 OMXCATBAR(SP_FilterMedian_S32, OMXSP_SUFFIX)
+#define omxSP_FilterMedian_S32_I OMXCATBAR(SP_FilterMedian_S32_I, OMXSP_SUFFIX)
+#define omxSP_FIR_Direct_S16 OMXCATBAR(SP_FIR_Direct_S16, OMXSP_SUFFIX)
+#define omxSP_FIR_Direct_S16_I OMXCATBAR(SP_FIR_Direct_S16_I, OMXSP_SUFFIX)
+#define omxSP_FIR_Direct_S16_ISfs OMXCATBAR(SP_FIR_Direct_S16_ISfs, OMXSP_SUFFIX)
+#define omxSP_FIR_Direct_S16_Sfs OMXCATBAR(SP_FIR_Direct_S16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FIROne_Direct_S16 OMXCATBAR(SP_FIROne_Direct_S16, OMXSP_SUFFIX)
+#define omxSP_FIROne_Direct_S16_I OMXCATBAR(SP_FIROne_Direct_S16_I, OMXSP_SUFFIX)
+#define omxSP_FIROne_Direct_S16_ISfs OMXCATBAR(SP_FIROne_Direct_S16_ISfs, OMXSP_SUFFIX)
+#define omxSP_FIROne_Direct_S16_Sfs OMXCATBAR(SP_FIROne_Direct_S16_Sfs, OMXSP_SUFFIX)
+#define omxSP_IIR_BiQuadDirect_S16 OMXCATBAR(SP_IIR_BiQuadDirect_S16, OMXSP_SUFFIX)
+#define omxSP_IIR_BiQuadDirect_S16_I OMXCATBAR(SP_IIR_BiQuadDirect_S16_I, OMXSP_SUFFIX)
+#define omxSP_IIR_Direct_S16 OMXCATBAR(SP_IIR_Direct_S16, OMXSP_SUFFIX)
+#define omxSP_IIR_Direct_S16_I OMXCATBAR(SP_IIR_Direct_S16_I, OMXSP_SUFFIX)
+#define omxSP_IIROne_BiQuadDirect_S16 OMXCATBAR(SP_IIROne_BiQuadDirect_S16, OMXSP_SUFFIX)
+#define omxSP_IIROne_BiQuadDirect_S16_I OMXCATBAR(SP_IIROne_BiQuadDirect_S16_I, OMXSP_SUFFIX)
+#define omxSP_IIROne_Direct_S16 OMXCATBAR(SP_IIROne_Direct_S16, OMXSP_SUFFIX)
+#define omxSP_IIROne_Direct_S16_I OMXCATBAR(SP_IIROne_Direct_S16_I, OMXSP_SUFFIX)
+
+#define omxVCCOMM_Average_16x OMXCATBAR(VCCOMM_Average_16x, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_Average_8x OMXCATBAR(VCCOMM_Average_8x, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_ComputeTextureErrorBlock OMXCATBAR(VCCOMM_ComputeTextureErrorBlock, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_ComputeTextureErrorBlock_SAD OMXCATBAR(VCCOMM_ComputeTextureErrorBlock_SAD, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_Copy16x16 OMXCATBAR(VCCOMM_Copy16x16, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_Copy8x8 OMXCATBAR(VCCOMM_Copy8x8, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_ExpandFrame_I OMXCATBAR(VCCOMM_ExpandFrame_I, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_LimitMVToRect OMXCATBAR(VCCOMM_LimitMVToRect, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_SAD_16x OMXCATBAR(VCCOMM_SAD_16x, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_SAD_8x OMXCATBAR(VCCOMM_SAD_8x, OMXVCCOMM_SUFFIX)
+
+#define omxVCM4P10_Average_4x OMXCATBAR(VCM4P10_Average_4x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_BlockMatch_Half OMXCATBAR(VCM4P10_BlockMatch_Half, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_BlockMatch_Integer OMXCATBAR(VCM4P10_BlockMatch_Integer, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_BlockMatch_Quarter OMXCATBAR(VCM4P10_BlockMatch_Quarter, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DeblockChroma_I OMXCATBAR(VCM4P10_DeblockChroma_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DeblockLuma_I OMXCATBAR(VCM4P10_DeblockLuma_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC OMXCATBAR(VCM4P10_DecodeChromaDcCoeffsToPairCAVLC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DecodeCoeffsToPairCAVLC OMXCATBAR(VCM4P10_DecodeCoeffsToPairCAVLC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DequantTransformResidualFromPairAndAdd OMXCATBAR(VCM4P10_DequantTransformResidualFromPairAndAdd, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_FilterDeblockingChroma_HorEdge_I OMXCATBAR(VCM4P10_FilterDeblockingChroma_HorEdge_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_FilterDeblockingChroma_VerEdge_I OMXCATBAR(VCM4P10_FilterDeblockingChroma_VerEdge_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_FilterDeblockingLuma_HorEdge_I OMXCATBAR(VCM4P10_FilterDeblockingLuma_HorEdge_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_FilterDeblockingLuma_VerEdge_I OMXCATBAR(VCM4P10_FilterDeblockingLuma_VerEdge_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_GetVLCInfo OMXCATBAR(VCM4P10_GetVLCInfo, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InterpolateChroma OMXCATBAR(VCM4P10_InterpolateChroma, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InterpolateHalfHor_Luma OMXCATBAR(VCM4P10_InterpolateHalfHor_Luma, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InterpolateHalfVer_Luma OMXCATBAR(VCM4P10_InterpolateHalfVer_Luma, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InterpolateLuma OMXCATBAR(VCM4P10_InterpolateLuma, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InvTransformDequant_ChromaDC OMXCATBAR(VCM4P10_InvTransformDequant_ChromaDC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InvTransformDequant_LumaDC OMXCATBAR(VCM4P10_InvTransformDequant_LumaDC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InvTransformResidualAndAdd OMXCATBAR(VCM4P10_InvTransformResidualAndAdd, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_MEGetBufSize OMXCATBAR(VCM4P10_MEGetBufSize, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_MEInit OMXCATBAR(VCM4P10_MEInit, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_MotionEstimationMB OMXCATBAR(VCM4P10_MotionEstimationMB, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_PredictIntra_16x16 OMXCATBAR(VCM4P10_PredictIntra_16x16, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_PredictIntra_4x4 OMXCATBAR(VCM4P10_PredictIntra_4x4, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_PredictIntraChroma_8x8 OMXCATBAR(VCM4P10_PredictIntraChroma_8x8, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SAD_4x OMXCATBAR(VCM4P10_SAD_4x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SADQuar_16x OMXCATBAR(VCM4P10_SADQuar_16x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SADQuar_4x OMXCATBAR(VCM4P10_SADQuar_4x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SADQuar_8x OMXCATBAR(VCM4P10_SADQuar_8x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SATD_4x4 OMXCATBAR(VCM4P10_SATD_4x4, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SubAndTransformQDQResidual OMXCATBAR(VCM4P10_SubAndTransformQDQResidual, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_TransformDequantChromaDCFromPair OMXCATBAR(VCM4P10_TransformDequantChromaDCFromPair, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_TransformDequantLumaDCFromPair OMXCATBAR(VCM4P10_TransformDequantLumaDCFromPair, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_TransformQuant_ChromaDC OMXCATBAR(VCM4P10_TransformQuant_ChromaDC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_TransformQuant_LumaDC OMXCATBAR(VCM4P10_TransformQuant_LumaDC, OMXVCM4P10_SUFFIX)
+
+#define omxVCM4P2_BlockMatch_Half_16x16 OMXCATBAR(VCM4P2_BlockMatch_Half_16x16, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_BlockMatch_Half_8x8 OMXCATBAR(VCM4P2_BlockMatch_Half_8x8, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_BlockMatch_Integer_16x16 OMXCATBAR(VCM4P2_BlockMatch_Integer_16x16, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_BlockMatch_Integer_8x8 OMXCATBAR(VCM4P2_BlockMatch_Integer_8x8, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DCT8x8blk OMXCATBAR(VCM4P2_DCT8x8blk, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeBlockCoef_Inter OMXCATBAR(VCM4P2_DecodeBlockCoef_Inter, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeBlockCoef_Intra OMXCATBAR(VCM4P2_DecodeBlockCoef_Intra, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodePadMV_PVOP OMXCATBAR(VCM4P2_DecodePadMV_PVOP, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeVLCZigzag_Inter OMXCATBAR(VCM4P2_DecodeVLCZigzag_Inter, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeVLCZigzag_IntraACVLC OMXCATBAR(VCM4P2_DecodeVLCZigzag_IntraACVLC, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeVLCZigzag_IntraDCVLC OMXCATBAR(VCM4P2_DecodeVLCZigzag_IntraDCVLC, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_EncodeMV OMXCATBAR(VCM4P2_EncodeMV, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_EncodeVLCZigzag_Inter OMXCATBAR(VCM4P2_EncodeVLCZigzag_Inter, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_EncodeVLCZigzag_IntraACVLC OMXCATBAR(VCM4P2_EncodeVLCZigzag_IntraACVLC, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_EncodeVLCZigzag_IntraDCVLC OMXCATBAR(VCM4P2_EncodeVLCZigzag_IntraDCVLC, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_FindMVpred OMXCATBAR(VCM4P2_FindMVpred, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_IDCT8x8blk OMXCATBAR(VCM4P2_IDCT8x8blk, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_MCReconBlock OMXCATBAR(VCM4P2_MCReconBlock, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_MEGetBufSize OMXCATBAR(VCM4P2_MEGetBufSize, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_MEInit OMXCATBAR(VCM4P2_MEInit, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_MotionEstimationMB OMXCATBAR(VCM4P2_MotionEstimationMB, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_PredictReconCoefIntra OMXCATBAR(VCM4P2_PredictReconCoefIntra, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_QuantInter_I OMXCATBAR(VCM4P2_QuantInter_I, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_QuantIntra_I OMXCATBAR(VCM4P2_QuantIntra_I, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_QuantInvInter_I OMXCATBAR(VCM4P2_QuantInvInter_I, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_QuantInvIntra_I OMXCATBAR(VCM4P2_QuantInvIntra_I, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_TransRecBlockCoef_inter OMXCATBAR(VCM4P2_TransRecBlockCoef_inter, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_TransRecBlockCoef_intra OMXCATBAR(VCM4P2_TransRecBlockCoef_intra, OMXVCM4P2_SUFFIX)
+
+
+#endif /* _armOMX_h_ */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h
new file mode 100755
index 0000000..8b295a6
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes.h
@@ -0,0 +1,252 @@
+/**
+ * File: omxtypes.h
+ * Brief: Defines basic Data types used in OpenMAX v1.0.2 header files.
+ *
+ * Copyright © 2005-2008 The Khronos Group Inc. All Rights Reserved.
+ *
+ * These materials are protected by copyright laws and contain material
+ * proprietary to the Khronos Group, Inc. You may use these materials
+ * for implementing Khronos specifications, without altering or removing
+ * any trademark, copyright or other notice from the specification.
+ *
+ * Khronos Group makes no, and expressly disclaims any, representations
+ * or warranties, express or implied, regarding these materials, including,
+ * without limitation, any implied warranties of merchantability or fitness
+ * for a particular purpose or non-infringement of any intellectual property.
+ * Khronos Group makes no, and expressly disclaims any, warranties, express
+ * or implied, regarding the correctness, accuracy, completeness, timeliness,
+ * and reliability of these materials.
+ *
+ * Under no circumstances will the Khronos Group, or any of its Promoters,
+ * Contributors or Members or their respective partners, officers, directors,
+ * employees, agents or representatives be liable for any damages, whether
+ * direct, indirect, special or consequential damages for lost revenues,
+ * lost profits, or otherwise, arising from or in connection with these
+ * materials.
+ *
+ * Khronos and OpenMAX are trademarks of the Khronos Group Inc.
+ *
+ */
+
+#ifndef _OMXTYPES_H_
+#define _OMXTYPES_H_
+
+#include <limits.h>
+
+#define OMX_IN
+#define OMX_OUT
+#define OMX_INOUT
+
+
+typedef enum {
+
+ /* Mandatory return codes - use cases are explicitly described for each function */
+ OMX_Sts_NoErr = 0, /* No error, the function completed successfully */
+ OMX_Sts_Err = -2, /* Unknown/unspecified error */
+ OMX_Sts_InvalidBitstreamValErr = -182, /* Invalid value detected during bitstream processing */
+ OMX_Sts_MemAllocErr = -9, /* Not enough memory allocated for the operation */
+ OMX_StsACAAC_GainCtrErr = -159, /* AAC: Unsupported gain control data detected */
+ OMX_StsACAAC_PrgNumErr = -167, /* AAC: Invalid number of elements for one program */
+ OMX_StsACAAC_CoefValErr = -163, /* AAC: Invalid quantized coefficient value */
+ OMX_StsACAAC_MaxSfbErr = -162, /* AAC: Invalid maxSfb value in relation to numSwb */
+ OMX_StsACAAC_PlsDataErr = -160, /* AAC: pulse escape sequence data error */
+
+ /* Optional return codes - use cases are explicitly described for each function*/
+ OMX_Sts_BadArgErr = -5, /* Bad Arguments */
+
+ OMX_StsACAAC_TnsNumFiltErr = -157, /* AAC: Invalid number of TNS filters */
+ OMX_StsACAAC_TnsLenErr = -156, /* AAC: Invalid TNS region length */
+ OMX_StsACAAC_TnsOrderErr = -155, /* AAC: Invalid order of TNS filter */
+ OMX_StsACAAC_TnsCoefResErr = -154, /* AAC: Invalid bit-resolution for TNS filter coefficients */
+ OMX_StsACAAC_TnsCoefErr = -153, /* AAC: Invalid TNS filter coefficients */
+ OMX_StsACAAC_TnsDirectErr = -152, /* AAC: Invalid TNS filter direction */
+
+ OMX_StsICJP_JPEGMarkerErr = -183, /* JPEG marker encountered within an entropy-coded block; */
+ /* Huffman decoding operation terminated early. */
+ OMX_StsICJP_JPEGMarker = -181, /* JPEG marker encountered; Huffman decoding */
+ /* operation terminated early. */
+ OMX_StsIPPP_ContextMatchErr = -17, /* Context parameter doesn't match to the operation */
+
+ OMX_StsSP_EvenMedianMaskSizeErr = -180, /* Even size of the Median Filter mask was replaced by the odd one */
+
+ OMX_Sts_MaximumEnumeration = INT_MAX /*Placeholder, forces enum of size OMX_INT*/
+
+ } OMXResult; /** Return value or error value returned from a function. Identical to OMX_INT */
+
+
+/* OMX_U8 */
+#if UCHAR_MAX == 0xff
+typedef unsigned char OMX_U8;
+#elif USHRT_MAX == 0xff
+typedef unsigned short int OMX_U8;
+#else
+#error OMX_U8 undefined
+#endif
+
+
+/* OMX_S8 */
+#if SCHAR_MAX == 0x7f
+typedef signed char OMX_S8;
+#elif SHRT_MAX == 0x7f
+typedef signed short int OMX_S8;
+#else
+#error OMX_S8 undefined
+#endif
+
+
+/* OMX_U16 */
+#if USHRT_MAX == 0xffff
+typedef unsigned short int OMX_U16;
+#elif UINT_MAX == 0xffff
+typedef unsigned int OMX_U16;
+#else
+#error OMX_U16 undefined
+#endif
+
+
+/* OMX_S16 */
+#if SHRT_MAX == 0x7fff
+typedef signed short int OMX_S16;
+#elif INT_MAX == 0x7fff
+typedef signed int OMX_S16;
+#else
+#error OMX_S16 undefined
+#endif
+
+
+/* OMX_U32 */
+#if UINT_MAX == 0xffffffff
+typedef unsigned int OMX_U32;
+#elif LONG_MAX == 0xffffffff
+typedef unsigned long int OMX_U32;
+#else
+#error OMX_U32 undefined
+#endif
+
+
+/* OMX_S32 */
+#if INT_MAX == 0x7fffffff
+typedef signed int OMX_S32;
+#elif LONG_MAX == 0x7fffffff
+typedef long signed int OMX_S32;
+#else
+#error OMX_S32 undefined
+#endif
+
+
+/* OMX_U64 & OMX_S64 */
+#if defined( _WIN32 ) || defined ( _WIN64 )
+ typedef __int64 OMX_S64; /** Signed 64-bit integer */
+ typedef unsigned __int64 OMX_U64; /** Unsigned 64-bit integer */
+ #define OMX_MIN_S64 (0x8000000000000000i64)
+ #define OMX_MIN_U64 (0x0000000000000000i64)
+ #define OMX_MAX_S64 (0x7FFFFFFFFFFFFFFFi64)
+ #define OMX_MAX_U64 (0xFFFFFFFFFFFFFFFFi64)
+#else
+ typedef long long OMX_S64; /** Signed 64-bit integer */
+ typedef unsigned long long OMX_U64; /** Unsigned 64-bit integer */
+ #define OMX_MIN_S64 (0x8000000000000000LL)
+ #define OMX_MIN_U64 (0x0000000000000000LL)
+ #define OMX_MAX_S64 (0x7FFFFFFFFFFFFFFFLL)
+ #define OMX_MAX_U64 (0xFFFFFFFFFFFFFFFFLL)
+#endif
+
+
+/* OMX_SC8 */
+typedef struct
+{
+ OMX_S8 Re; /** Real part */
+ OMX_S8 Im; /** Imaginary part */
+
+} OMX_SC8; /** Signed 8-bit complex number */
+
+
+/* OMX_SC16 */
+typedef struct
+{
+ OMX_S16 Re; /** Real part */
+ OMX_S16 Im; /** Imaginary part */
+
+} OMX_SC16; /** Signed 16-bit complex number */
+
+
+/* OMX_SC32 */
+typedef struct
+{
+ OMX_S32 Re; /** Real part */
+ OMX_S32 Im; /** Imaginary part */
+
+} OMX_SC32; /** Signed 32-bit complex number */
+
+
+/* OMX_SC64 */
+typedef struct
+{
+ OMX_S64 Re; /** Real part */
+ OMX_S64 Im; /** Imaginary part */
+
+} OMX_SC64; /** Signed 64-bit complex number */
+
+
+/* OMX_F32 */
+typedef float OMX_F32; /** Single precision floating point,IEEE 754 */
+
+
+/* OMX_F64 */
+typedef double OMX_F64; /** Double precision floating point,IEEE 754 */
+
+
+/* OMX_INT */
+typedef int OMX_INT; /** signed integer corresponding to machine word length, has maximum signed value INT_MAX*/
+
+
+#define OMX_MIN_S8 (-128)
+#define OMX_MIN_U8 0
+#define OMX_MIN_S16 (-32768)
+#define OMX_MIN_U16 0
+#define OMX_MIN_S32 (-2147483647-1)
+#define OMX_MIN_U32 0
+
+#define OMX_MAX_S8 (127)
+#define OMX_MAX_U8 (255)
+#define OMX_MAX_S16 (32767)
+#define OMX_MAX_U16 (0xFFFF)
+#define OMX_MAX_S32 (2147483647)
+#define OMX_MAX_U32 (0xFFFFFFFF)
+
+typedef void OMXVoid;
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+/** Defines the geometric position and size of a rectangle,
+ * where x,y defines the coordinates of the top left corner
+ * of the rectangle, with dimensions width in the x-direction
+ * and height in the y-direction */
+typedef struct {
+ OMX_INT x; /** x-coordinate of top left corner of rectangle */
+ OMX_INT y; /** y-coordinate of top left corner of rectangle */
+ OMX_INT width; /** Width in the x-direction. */
+ OMX_INT height; /** Height in the y-direction. */
+}OMXRect;
+
+
+/** Defines the geometric position of a point, */
+typedef struct
+{
+ OMX_INT x; /** x-coordinate */
+ OMX_INT y; /** y-coordinate */
+
+} OMXPoint;
+
+
+/** Defines the dimensions of a rectangle, or region of interest in an image */
+typedef struct
+{
+ OMX_INT width; /** Width of the rectangle, in the x-direction */
+ OMX_INT height; /** Height of the rectangle, in the y-direction */
+
+} OMXSize;
+
+#endif /* _OMXTYPES_H_ */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes_s.h
new file mode 100755
index 0000000..48703d1
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/api/omxtypes_s.h
@@ -0,0 +1,77 @@
+;//
+;//
+;// File Name: omxtypes_s.h
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+;// Mandatory return codes - use cases are explicitly described for each function
+OMX_Sts_NoErr EQU 0 ;// No error the function completed successfully
+OMX_Sts_Err EQU -2 ;// Unknown/unspecified error
+OMX_Sts_InvalidBitstreamValErr EQU -182 ;// Invalid value detected during bitstream processing
+OMX_Sts_MemAllocErr EQU -9 ;// Not enough memory allocated for the operation
+OMX_StsACAAC_GainCtrErr EQU -159 ;// AAC: Unsupported gain control data detected
+OMX_StsACAAC_PrgNumErr EQU -167 ;// AAC: Invalid number of elements for one program
+OMX_StsACAAC_CoefValErr EQU -163 ;// AAC: Invalid quantized coefficient value
+OMX_StsACAAC_MaxSfbErr EQU -162 ;// AAC: Invalid maxSfb value in relation to numSwb
+OMX_StsACAAC_PlsDataErr EQU -160 ;// AAC: pulse escape sequence data error
+
+;// Optional return codes - use cases are explicitly described for each function
+OMX_Sts_BadArgErr EQU -5 ;// Bad Arguments
+
+OMX_StsACAAC_TnsNumFiltErr EQU -157 ;// AAC: Invalid number of TNS filters
+OMX_StsACAAC_TnsLenErr EQU -156 ;// AAC: Invalid TNS region length
+OMX_StsACAAC_TnsOrderErr EQU -155 ;// AAC: Invalid order of TNS filter
+OMX_StsACAAC_TnsCoefResErr EQU -154 ;// AAC: Invalid bit-resolution for TNS filter coefficients
+OMX_StsACAAC_TnsCoefErr EQU -153 ;// AAC: Invalid TNS filter coefficients
+OMX_StsACAAC_TnsDirectErr EQU -152 ;// AAC: Invalid TNS filter direction
+
+OMX_StsICJP_JPEGMarkerErr EQU -183 ;// JPEG marker encountered within an entropy-coded block;
+ ;// Huffman decoding operation terminated early.
+OMX_StsICJP_JPEGMarker EQU -181 ;// JPEG marker encountered; Huffman decoding
+ ;// operation terminated early.
+OMX_StsIPPP_ContextMatchErr EQU -17 ;// Context parameter doesn't match to the operation
+
+OMX_StsSP_EvenMedianMaskSizeErr EQU -180 ;// Even size of the Median Filter mask was replaced by the odd one
+
+OMX_Sts_MaximumEnumeration EQU 0x7FFFFFFF
+
+
+
+OMX_MIN_S8 EQU (-128)
+OMX_MIN_U8 EQU 0
+OMX_MIN_S16 EQU (-32768)
+OMX_MIN_U16 EQU 0
+
+
+OMX_MIN_S32 EQU (-2147483647-1)
+OMX_MIN_U32 EQU 0
+
+OMX_MAX_S8 EQU (127)
+OMX_MAX_U8 EQU (255)
+OMX_MAX_S16 EQU (32767)
+OMX_MAX_U16 EQU (0xFFFF)
+OMX_MAX_S32 EQU (2147483647)
+OMX_MAX_U32 EQU (0xFFFFFFFF)
+
+OMX_VC_UPPER EQU 0x1 ;// Used by the PredictIntra functions
+OMX_VC_LEFT EQU 0x2 ;// Used by the PredictIntra functions
+OMX_VC_UPPER_RIGHT EQU 0x40 ;// Used by the PredictIntra functions
+
+NULL EQU 0
+
+;// Structures
+
+ INCLUDE armCOMM_s.h
+
+ M_STRUCT OMXPoint
+ M_FIELD x, 4
+ M_FIELD y, 4
+ M_ENDSTRUCT
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/build_vc.pl b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/build_vc.pl
new file mode 100755
index 0000000..649e74c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/build_vc.pl
@@ -0,0 +1,113 @@
+#!/usr/bin/perl
+#
+#
+# File Name: build_vc.pl
+# OpenMAX DL: v1.0.2
+# Revision: 12290
+# Date: Wednesday, April 9, 2008
+#
+# (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+#
+#
+#
+# This file builds the OpenMAX DL vc domain library omxVC.o.
+#
+
+use File::Spec;
+use strict;
+
+my ($CC, $CC_OPTS, $AS, $AS_OPTS, $LIB, $LIB_OPTS, $LIB_TYPE);
+
+$CC = 'armcc';
+$CC_OPTS = '--no_unaligned_access --cpu Cortex-A8 -c';
+$AS = 'armasm';
+$AS_OPTS = '--no_unaligned_access --cpu Cortex-A8';
+# $LIB = 'armlink';
+# $LIB_OPTS = '--partial -o';
+# $LIB_TYPE = '.o';
+$LIB = 'armar';
+$LIB_OPTS = '--create -r';
+$LIB_TYPE = '.a';
+
+#------------------------
+
+my (@headerlist, @filelist, $hd, $file, $ofile, $command, $objlist, $libfile, $h);
+
+# Define the list of directories containing included header files.
+@headerlist = qw(api vc/api vc/m4p2/api vc/m4p10/api);
+
+# Define the list of source files to compile.
+open(FILES, '<filelist_vc.txt') or die("Can't open source file list\n");
+@filelist = <FILES>;
+close(FILES);
+
+# Fix the file separators in the header paths
+foreach $h (@headerlist)
+{
+ $h = File::Spec->canonpath($h);
+}
+
+# Create the include path to be passed to the compiler
+$hd = '-I' . join(' -I', @headerlist);
+
+# Create the build directories "/lib/" and "/obj/" (if they are not there already)
+mkdir "obj", 0777 if (! -d "obj");
+mkdir "lib", 0777 if (! -d "lib");
+
+$objlist = '';
+
+# Compile each file
+foreach $file (@filelist)
+{
+ my $f;
+ my $base;
+ my $ext;
+ my $objfile;
+
+ chomp($file);
+ $file = File::Spec->canonpath($file);
+
+ (undef, undef, $f) = File::Spec->splitpath($file);
+ $f=~s/[\n\f\r]//g; # Remove any end-of-line characters
+
+ if(($base, $ext) = $f =~ /(.+)\.(\w)$/)
+ {
+ $objfile = File::Spec->catfile('obj', $base.'.o');
+
+ if($ext eq 'c')
+ {
+ $objlist .= "$objfile ";
+ $command = $CC.' '.$CC_OPTS.' '.$hd.' -o '.$objfile.' '.$file;
+ print "$command\n";
+ system($command);
+ }
+ elsif($ext eq 's')
+ {
+ $objlist .= "$objfile ";
+ $command = $AS.' '.$AS_OPTS.' '.$hd.' -o '.$objfile.' '.$file;
+ print "$command\n";
+ system($command);
+ }
+ else
+ {
+ print "Ignoring file: $f\n";
+ }
+ }
+ else
+ {
+ die "No file extension found: $f\n";
+ }
+}
+
+# Do the final link stage to create the libraries.
+$libfile = File::Spec->catfile('lib', 'omxVC'.$LIB_TYPE);
+$command = $LIB.' '.$LIB_OPTS.' '.$libfile.' '.$objlist;
+print "$command\n";
+(system($command) == 0) and print "Build successful\n";
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/filelist_vc.txt b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/filelist_vc.txt
new file mode 100755
index 0000000..8db8eeb
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/filelist_vc.txt
@@ -0,0 +1,75 @@
+./api/armCOMM.h
+./api/armCOMM_BitDec_s.h
+./api/armCOMM_Bitstream.h
+./api/armCOMM_IDCT_s.h
+./api/armCOMM_IDCTTable.h
+./api/armCOMM_MaskTable.h
+./api/armCOMM_s.h
+./api/armCOMM_Version.h
+./api/armOMX_ReleaseVersion.h
+./api/omxtypes.h
+./api/omxtypes_s.h
+./src/armCOMM_IDCTTable.c
+./src/armCOMM_MaskTable.c
+./vc/api/armVC.h
+./vc/api/armVCCOMM_s.h
+./vc/api/omxVC.h
+./vc/api/omxVC_s.h
+./vc/comm/src/omxVCCOMM_Copy16x16_s.s
+./vc/comm/src/omxVCCOMM_Copy8x8_s.s
+./vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
+./vc/m4p10/api/armVCM4P10_CAVLCTables.h
+./vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_CAVLCTables.c
+./vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
+./vc/m4p10/src/armVCM4P10_DequantTables_s.s
+./vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
+./vc/m4p10/src/armVCM4P10_QuantTables_s.s
+./vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
+./vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
+./vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
+./vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
+./vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
+./vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
+./vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s
+./vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
+./vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
+./vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
+./vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
+./vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
+./vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
+./vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
+./vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
+./vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
+./vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
+./vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
+./vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
+./vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
+./vc/m4p2/src/armVCM4P2_Clip8_s.s
+./vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
+./vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
+./vc/m4p2/src/armVCM4P2_Lookup_Tables.c
+./vc/m4p2/src/armVCM4P2_SetPredDir_s.s
+./vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
+./vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
+./vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
+./vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
+./vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
+./vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
+./vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
+./vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
+./vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
+./vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
+./vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
+./vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
+./vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
+./vc/src/armVC_Version.c \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM.c
new file mode 100755
index 0000000..e572a89
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM.c
@@ -0,0 +1,936 @@
+/**
+ *
+ * File Name: armCOMM.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Defines Common APIs used across OpenMAX API's
+ */
+
+#include "omxtypes.h"
+#include "armCOMM.h"
+
+/***********************************************************************/
+ /* Miscellaneous Arithmetic operations */
+
+/**
+ * Function: armRoundFloatToS16
+ *
+ * Description:
+ * Converts a double precision value into a short int after rounding
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S16 format
+ *
+ */
+
+OMX_S16 armRoundFloatToS16 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ return (OMX_S16)(Value + .5);
+ }
+ else
+ {
+ return (OMX_S16)(Value - .5);
+ }
+}
+
+/**
+ * Function: armRoundFloatToS32
+ *
+ * Description:
+ * Converts a double precision value into a int after rounding
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S32 format
+ *
+ */
+
+OMX_S32 armRoundFloatToS32 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ return (OMX_S32)(Value + .5);
+ }
+ else
+ {
+ return (OMX_S32)(Value - .5);
+ }
+}
+/**
+ * Function: armSatRoundFloatToS16
+ *
+ * Description:
+ * Converts a double precision value into a short int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S16 format
+ *
+ */
+
+OMX_S16 armSatRoundFloatToS16 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ Value += 0.5;
+
+ if(Value > (OMX_S16)OMX_MAX_S16 )
+ {
+ return (OMX_S16)OMX_MAX_S16;
+ }
+ else
+ {
+ return (OMX_S16)Value;
+ }
+ }
+ else
+ {
+ Value -= 0.5;
+
+ if(Value < (OMX_S16)OMX_MIN_S16 )
+ {
+ return (OMX_S16)OMX_MIN_S16;
+ }
+ else
+ {
+ return (OMX_S16)Value;
+ }
+ }
+}
+
+/**
+ * Function: armSatRoundFloatToS32
+ *
+ * Description:
+ * Converts a double precision value into a int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S32 format
+ *
+ */
+
+OMX_S32 armSatRoundFloatToS32 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ Value += 0.5;
+
+ if(Value > (OMX_S32)OMX_MAX_S32 )
+ {
+ return (OMX_S32)OMX_MAX_S32;
+ }
+ else
+ {
+ return (OMX_S32)Value;
+ }
+ }
+ else
+ {
+ Value -= 0.5;
+
+ if(Value < (OMX_S32)OMX_MIN_S32 )
+ {
+ return (OMX_S32)OMX_MIN_S32;
+ }
+ else
+ {
+ return (OMX_S32)Value;
+ }
+ }
+}
+
+/**
+ * Function: armSatRoundFloatToU16
+ *
+ * Description:
+ * Converts a double precision value into a unsigned short int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_U16 format
+ *
+ */
+
+OMX_U16 armSatRoundFloatToU16 (OMX_F64 Value)
+{
+ Value += 0.5;
+
+ if(Value > (OMX_U16)OMX_MAX_U16 )
+ {
+ return (OMX_U16)OMX_MAX_U16;
+ }
+ else
+ {
+ return (OMX_U16)Value;
+ }
+}
+
+/**
+ * Function: armSatRoundFloatToU32
+ *
+ * Description:
+ * Converts a double precision value into a unsigned int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_U32 format
+ *
+ */
+
+OMX_U32 armSatRoundFloatToU32 (OMX_F64 Value)
+{
+ Value += 0.5;
+
+ if(Value > (OMX_U32)OMX_MAX_U32 )
+ {
+ return (OMX_U32)OMX_MAX_U32;
+ }
+ else
+ {
+ return (OMX_U32)Value;
+ }
+}
+
+/**
+ * Function: armRoundFloatToS64
+ *
+ * Description:
+ * Converts a double precision value into a 64 bit int after rounding
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S64 format
+ *
+ */
+
+OMX_S64 armRoundFloatToS64 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ return (OMX_S64)(Value + .5);
+ }
+ else
+ {
+ return (OMX_S64)(Value - .5);
+ }
+}
+
+/**
+ * Function: armSignCheck
+ *
+ * Description:
+ * Checks the sign of a variable:
+ * returns 1 if it is Positive
+ * returns 0 if it is 0
+ * returns -1 if it is Negative
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] var Variable to be checked
+ *
+ * Return Value:
+ * OMX_INT -- returns 1 if it is Positive
+ * returns 0 if it is 0
+ * returns -1 if it is Negative
+ */
+
+OMX_INT armSignCheck (
+ OMX_S16 var
+)
+
+{
+ OMX_INT Sign;
+
+ if (var < 0)
+ {
+ Sign = -1;
+ }
+ else if ( var > 0)
+ {
+ Sign = 1;
+ }
+ else
+ {
+ Sign = 0;
+ }
+
+ return Sign;
+}
+
+/**
+ * Function: armClip
+ *
+ * Description: Clips the input between MAX and MIN value
+ *
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] Min lower bound
+ * [in] Max upper bound
+ * [in] src variable to the clipped
+ *
+ * Return Value:
+ * OMX_S32 -- returns clipped value
+ */
+
+OMX_S32 armClip (
+ OMX_INT min,
+ OMX_INT max,
+ OMX_S32 src
+)
+
+{
+ if (src > max)
+ {
+ src = max;
+ }
+ else if (src < min)
+ {
+ src = min;
+ }
+
+ return src;
+}
+
+/**
+ * Function: armClip_F32
+ *
+ * Description: Clips the input between MAX and MIN value
+ *
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] Min lower bound
+ * [in] Max upper bound
+ * [in] src variable to the clipped
+ *
+ * Return Value:
+ * OMX_F32 -- returns clipped value
+ */
+
+OMX_F32 armClip_F32 (
+ OMX_F32 min,
+ OMX_F32 max,
+ OMX_F32 src
+)
+
+{
+ if (src > max)
+ {
+ src = max;
+ }
+ else if (src < min)
+ {
+ src = min;
+ }
+
+ return src;
+}
+
+/**
+ * Function: armShiftSat_F32
+ *
+ * Description: Divides a float value by 2^shift and
+ * saturates it for unsigned value range for satBits.
+ * Second parameter is like "shifting" the corresponding
+ * integer value. Takes care of rounding while clipping the final
+ * value.
+ *
+ * Parameters:
+ * [in] v Number to be operated upon
+ * [in] shift Divides the input "v" by "2^shift"
+ * [in] satBits Final range is [0, 2^satBits)
+ *
+ * Return Value:
+ * OMX_S32 -- returns "shifted" saturated value
+ */
+
+OMX_U32 armShiftSat_F32(OMX_F32 v, OMX_INT shift, OMX_INT satBits)
+{
+ OMX_U32 allOnes = (OMX_U32)(-1);
+ OMX_U32 maxV = allOnes >> (32-satBits);
+ OMX_F32 vShifted, vRounded, shiftDiv = (OMX_F32)(1 << shift);
+ OMX_U32 vInt;
+ OMX_U32 vIntSat;
+
+ if(v <= 0)
+ return 0;
+
+ vShifted = v / shiftDiv;
+ vRounded = (OMX_F32)(vShifted + 0.5);
+ vInt = (OMX_U32)vRounded;
+ vIntSat = vInt;
+ if(vIntSat > maxV)
+ vIntSat = maxV;
+ return vIntSat;
+}
+
+/**
+ * Functions: armSwapElem
+ *
+ * Description:
+ * These function swaps two elements at the specified pointer locations.
+ * The size of each element could be anything as specified by <elemSize>
+ *
+ * Return Value:
+ * OMXResult -- Error status from the function
+ */
+OMXResult armSwapElem(
+ OMX_U8 *pBuf1,
+ OMX_U8 *pBuf2,
+ OMX_INT elemSize
+ )
+{
+ OMX_INT i;
+ OMX_U8 temp;
+ armRetArgErrIf(!pBuf1 || !pBuf2, OMX_Sts_BadArgErr);
+
+ for(i = 0; i < elemSize; i++)
+ {
+ temp = *(pBuf1 + i);
+ *(pBuf1 + i) = *(pBuf2 + i);
+ *(pBuf2 + i) = temp;
+ }
+ return OMX_Sts_NoErr;
+}
+
+/**
+ * Function: armMedianOf3
+ *
+ * Description: Finds the median of three numbers
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] fEntry First entry
+ * [in] sEntry second entry
+ * [in] tEntry Third entry
+ *
+ * Return Value:
+ * OMX_S32 -- returns the median value
+ */
+
+OMX_S32 armMedianOf3 (
+ OMX_S32 fEntry,
+ OMX_S32 sEntry,
+ OMX_S32 tEntry
+)
+{
+ OMX_S32 a, b, c;
+
+ a = armMin (fEntry, sEntry);
+ b = armMax (fEntry, sEntry);
+ c = armMin (b, tEntry);
+ return (armMax (a, c));
+}
+
+/**
+ * Function: armLogSize
+ *
+ * Description: Finds the size of a positive value and returns the same
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] value Positive value
+ *
+ * Return Value:
+ * OMX_U8 -- Returns the minimum number of bits required to represent the positive value.
+ This is the smallest k>=0 such that that value is less than (1<<k).
+ */
+
+OMX_U8 armLogSize (
+ OMX_U16 value
+)
+{
+ OMX_U8 i;
+ for ( i = 0; value > 0; value = value >> 1)
+ {
+ i++;
+ }
+ return i;
+}
+
+/***********************************************************************/
+ /* Saturating Arithmetic operations */
+
+/**
+ * Function :armSatAdd_S32()
+ *
+ * Description :
+ * Returns the result of saturated addition of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ *
+ **/
+
+OMX_S32 armSatAdd_S32(OMX_S32 Value1,OMX_S32 Value2)
+{
+ OMX_S32 Result;
+
+ Result = Value1 + Value2;
+
+ if( (Value1^Value2) >= 0)
+ {
+ /*Same sign*/
+ if( (Result^Value1) >= 0)
+ {
+ /*Result has not saturated*/
+ return Result;
+ }
+ else
+ {
+ if(Value1 >= 0)
+ {
+ /*Result has saturated in positive side*/
+ return OMX_MAX_S32;
+ }
+ else
+ {
+ /*Result has saturated in negative side*/
+ return OMX_MIN_S32;
+ }
+
+ }
+
+ }
+ else
+ {
+ return Result;
+ }
+
+}
+
+/**
+ * Function :armSatAdd_S64()
+ *
+ * Description :
+ * Returns the result of saturated addition of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ *
+ **/
+
+OMX_S64 armSatAdd_S64(OMX_S64 Value1,OMX_S64 Value2)
+{
+ OMX_S64 Result;
+
+ Result = Value1 + Value2;
+
+ if( (Value1^Value2) >= 0)
+ {
+ /*Same sign*/
+ if( (Result^Value1) >= 0)
+ {
+ /*Result has not saturated*/
+ return Result;
+ }
+ else
+ {
+ if(Value1 >= 0)
+ {
+ /*Result has saturated in positive side*/
+ Result = OMX_MAX_S64;
+ return Result;
+ }
+ else
+ {
+ /*Result has saturated in negative side*/
+ return OMX_MIN_S64;
+ }
+
+ }
+
+ }
+ else
+ {
+ return Result;
+ }
+
+}
+
+/** Function :armSatSub_S32()
+ *
+ * Description :
+ * Returns the result of saturated substraction of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatSub_S32(OMX_S32 Value1,OMX_S32 Value2)
+{
+ OMX_S32 Result;
+
+ Result = Value1 - Value2;
+
+ if( (Value1^Value2) < 0)
+ {
+ /*Opposite sign*/
+ if( (Result^Value1) >= 0)
+ {
+ /*Result has not saturated*/
+ return Result;
+ }
+ else
+ {
+ if(Value1 >= 0)
+ {
+ /*Result has saturated in positive side*/
+ return OMX_MAX_S32;
+ }
+ else
+ {
+ /*Result has saturated in negative side*/
+ return OMX_MIN_S32;
+ }
+
+ }
+
+ }
+ else
+ {
+ return Result;
+ }
+
+}
+
+/**
+ * Function :armSatMac_S32()
+ *
+ * Description :
+ * Returns the result of Multiplication of Value1 and Value2 and subesquent saturated
+ * accumulation with Mac
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ * [in] Mac Accumulator
+ *
+ * Return:
+ * [out] Result of operation
+ **/
+
+OMX_S32 armSatMac_S32(OMX_S32 Mac,OMX_S16 Value1,OMX_S16 Value2)
+{
+ OMX_S32 Result;
+
+ Result = (OMX_S32)(Value1*Value2);
+ Result = armSatAdd_S32( Mac , Result );
+
+ return Result;
+}
+
+/**
+ * Function :armSatMac_S16S32_S32
+ *
+ * Description :
+ * Returns the result of saturated MAC operation of the three inputs delayElem, filTap , mac
+ *
+ * mac = mac + Saturate_in_32Bits(delayElem * filTap)
+ *
+ * Parametrs:
+ * [in] delayElem First 32 bit Operand
+ * [in] filTap Second 16 bit Operand
+ * [in] mac Result of MAC operation
+ *
+ * Return:
+ * [out] mac Result of operation
+ *
+ **/
+
+OMX_S32 armSatMac_S16S32_S32(OMX_S32 mac, OMX_S32 delayElem, OMX_S16 filTap )
+{
+
+ OMX_S32 result;
+
+ result = armSatMulS16S32_S32(filTap,delayElem);
+
+ if ( result > OMX_MAX_S16 )
+ {
+ result = OMX_MAX_S32;
+ }
+ else if( result < OMX_MIN_S16 )
+ {
+ result = OMX_MIN_S32;
+ }
+ else
+ {
+ result = delayElem * filTap;
+ }
+
+ mac = armSatAdd_S32(mac,result);
+
+ return mac;
+}
+
+
+/**
+ * Function :armSatRoundRightShift_S32_S16
+ *
+ * Description :
+ * Returns the result of rounded right shift operation of input by the scalefactor
+ *
+ * output = Saturate_in_16Bits( ( Right/LeftShift( (Round(input) , shift ) )
+ *
+ * Parametrs:
+ * [in] input The input to be operated on
+ * [in] shift The shift number
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+
+OMX_S16 armSatRoundRightShift_S32_S16(OMX_S32 input, OMX_INT shift)
+{
+ input = armSatRoundLeftShift_S32(input,-shift);
+
+ if ( input > OMX_MAX_S16 )
+ {
+ return (OMX_S16)OMX_MAX_S16;
+ }
+ else if (input < OMX_MIN_S16)
+ {
+ return (OMX_S16)OMX_MIN_S16;
+ }
+ else
+ {
+ return (OMX_S16)input;
+ }
+
+}
+
+/**
+ * Function :armSatRoundLeftShift_S32()
+ *
+ * Description :
+ * Returns the result of saturating left-shift operation on input
+ * Or rounded Right shift if the input Shift is negative.
+ *
+ * Parametrs:
+ * [in] Value Operand
+ * [in] Shift Operand for shift operation
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatRoundLeftShift_S32(OMX_S32 Value, OMX_INT Shift)
+{
+ OMX_INT i;
+
+ if (Shift < 0)
+ {
+ Shift = -Shift;
+ Value = armSatAdd_S32(Value, (1 << (Shift - 1)));
+ Value = Value >> Shift;
+ }
+ else
+ {
+ for (i = 0; i < Shift; i++)
+ {
+ Value = armSatAdd_S32(Value, Value);
+ }
+ }
+ return Value;
+}
+
+/**
+ * Function :armSatRoundLeftShift_S64()
+ *
+ * Description :
+ * Returns the result of saturating left-shift operation on input
+ * Or rounded Right shift if the input Shift is negative.
+ *
+ * Parametrs:
+ * [in] Value Operand
+ * [in] shift Operand for shift operation
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S64 armSatRoundLeftShift_S64(OMX_S64 Value, OMX_INT Shift)
+{
+ OMX_INT i;
+
+ if (Shift < 0)
+ {
+ Shift = -Shift;
+ Value = armSatAdd_S64(Value, ((OMX_S64)1 << (Shift - 1)));
+ Value = Value >> Shift;
+ }
+ else
+ {
+ for (i = 0; i < Shift; i++)
+ {
+ Value = armSatAdd_S64(Value, Value);
+ }
+ }
+ return Value;
+}
+
+/**
+ * Function :armSatMulS16S32_S32()
+ *
+ * Description :
+ * Returns the result of a S16 data type multiplied with an S32 data type
+ * in a S32 container
+ *
+ * Parametrs:
+ * [in] input1 Operand 1
+ * [in] input2 Operand 2
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+
+OMX_S32 armSatMulS16S32_S32(OMX_S16 input1,OMX_S32 input2)
+{
+ OMX_S16 hi2,lo1;
+ OMX_U16 lo2;
+
+ OMX_S32 temp1,temp2;
+ OMX_S32 result;
+
+ lo1 = input1;
+
+ hi2 = ( input2 >> 16 );
+ lo2 = ( (OMX_U32)( input2 << 16 ) >> 16 );
+
+ temp1 = hi2 * lo1;
+ temp2 = ( lo2* lo1 ) >> 16;
+
+ result = armSatAdd_S32(temp1,temp2);
+
+ return result;
+}
+
+/**
+ * Function :armSatMulS32S32_S32()
+ *
+ * Description :
+ * Returns the result of a S32 data type multiplied with an S32 data type
+ * in a S32 container
+ *
+ * Parametrs:
+ * [in] input1 Operand 1
+ * [in] input2 Operand 2
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatMulS32S32_S32(OMX_S32 input1,OMX_S32 input2)
+{
+ OMX_S16 hi1,hi2;
+ OMX_U16 lo1,lo2;
+
+ OMX_S32 temp1,temp2,temp3;
+ OMX_S32 result;
+
+ hi1 = ( input1 >> 16 );
+ lo1 = ( (OMX_U32)( input1 << 16 ) >> 16 );
+
+ hi2 = ( input2 >> 16 );
+ lo2 = ( (OMX_U32)( input2 << 16 ) >> 16 );
+
+ temp1 = hi1 * hi2;
+ temp2 = ( hi1* lo2 ) >> 16;
+ temp3 = ( hi2* lo1 ) >> 16;
+
+ result = armSatAdd_S32(temp1,temp2);
+ result = armSatAdd_S32(result,temp3);
+
+ return result;
+}
+
+/**
+ * Function :armIntDivAwayFromZero()
+ *
+ * Description : Integer division with rounding to the nearest integer.
+ * Half-integer values are rounded away from zero
+ * unless otherwise specified. For example 3//2 is rounded
+ * to 2, and -3//2 is rounded to -2.
+ *
+ * Parametrs:
+ * [in] Num Operand 1
+ * [in] Deno Operand 2
+ *
+ * Return:
+ * [out] Result of operation input1//input2
+ *
+ **/
+
+OMX_S32 armIntDivAwayFromZero (OMX_S32 Num, OMX_S32 Deno)
+{
+ OMX_F64 result;
+
+ result = ((OMX_F64)Num)/((OMX_F64)Deno);
+
+ if (result >= 0)
+ {
+ result += 0.5;
+ }
+ else
+ {
+ result -= 0.5;
+ }
+
+ return (OMX_S32)(result);
+}
+
+
+/*End of File*/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_Bitstream.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_Bitstream.c
new file mode 100755
index 0000000..9ef9319
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_Bitstream.c
@@ -0,0 +1,329 @@
+/**
+ *
+ * File Name: armCOMM_Bitstream.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Defines bitstream encode and decode functions common to all codecs
+ */
+
+#include "omxtypes.h"
+#include "armCOMM.h"
+#include "armCOMM_Bitstream.h"
+
+/***************************************
+ * Fixed bit length Decode
+ ***************************************/
+
+/**
+ * Function: armLookAheadBits()
+ *
+ * Description:
+ * Get the next N bits from the bitstream without advancing the bitstream pointer
+ *
+ * Parameters:
+ * [in] **ppBitStream
+ * [in] *pOffset
+ * [in] N=1...32
+ *
+ * Returns Value
+ */
+
+OMX_U32 armLookAheadBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N)
+{
+ const OMX_U8 *pBitStream = *ppBitStream;
+ OMX_INT Offset = *pOffset;
+ OMX_U32 Value;
+
+ armAssert(Offset>=0 && Offset<=7);
+ armAssert(N>=1 && N<=32);
+
+ /* Read next 32 bits from stream */
+ Value = (pBitStream[0] << 24 ) | ( pBitStream[1] << 16) | (pBitStream[2] << 8 ) | (pBitStream[3]) ;
+ Value = (Value << Offset ) | (pBitStream[4] >> (8-Offset));
+
+ /* Return N bits */
+ return Value >> (32-N);
+}
+
+
+/**
+ * Function: armGetBits()
+ *
+ * Description:
+ * Read N bits from the bitstream
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ * [in] N=1..32
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ * Returns Value
+ */
+
+
+OMX_U32 armGetBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N)
+{
+ const OMX_U8 *pBitStream = *ppBitStream;
+ OMX_INT Offset = *pOffset;
+ OMX_U32 Value;
+
+ if(N == 0)
+ {
+ return 0;
+ }
+
+ armAssert(Offset>=0 && Offset<=7);
+ armAssert(N>=1 && N<=32);
+
+ /* Read next 32 bits from stream */
+ Value = (pBitStream[0] << 24 ) | ( pBitStream[1] << 16) | (pBitStream[2] << 8 ) | (pBitStream[3]) ;
+ Value = (Value << Offset ) | (pBitStream[4] >> (8-Offset));
+
+ /* Advance bitstream pointer by N bits */
+ Offset += N;
+ *ppBitStream = pBitStream + (Offset>>3);
+ *pOffset = Offset & 7;
+
+ /* Return N bits */
+ return Value >> (32-N);
+}
+
+/**
+ * Function: armByteAlign()
+ *
+ * Description:
+ * Align the pointer *ppBitStream to the next byte boundary
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ *
+ **/
+
+OMXVoid armByteAlign(const OMX_U8 **ppBitStream,OMX_INT *pOffset)
+{
+ if(*pOffset > 0)
+ {
+ *ppBitStream += 1;
+ *pOffset = 0;
+ }
+}
+
+/**
+ * Function: armSkipBits()
+ *
+ * Description:
+ * Skip N bits from the value at *ppBitStream
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ * [in] N
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ *
+ **/
+
+
+OMXVoid armSkipBits(const OMX_U8 **ppBitStream,OMX_INT *pOffset,OMX_INT N)
+{
+ OMX_INT Offset = *pOffset;
+ const OMX_U8 *pBitStream = *ppBitStream;
+
+ /* Advance bitstream pointer by N bits */
+ Offset += N;
+ *ppBitStream = pBitStream + (Offset>>3);
+ *pOffset = Offset & 7;
+}
+
+/***************************************
+ * Variable bit length Decode
+ ***************************************/
+
+/**
+ * Function: armUnPackVLC32()
+ *
+ * Description:
+ * Variable length decode of variable length symbol (max size 32 bits) read from
+ * the bit stream pointed by *ppBitStream at *pOffset by using the table
+ * pointed by pCodeBook
+ *
+ * Parameters:
+ * [in] *pBitStream
+ * [in] *pOffset
+ * [in] pCodeBook
+ *
+ * [out] *pBitStream
+ * [out] *pOffset
+ *
+ * Returns : Code Book Index if successfull.
+ * : ARM_NO_CODEBOOK_INDEX = -1 if search fails.
+ **/
+#ifndef C_OPTIMIZED_IMPLEMENTATION
+
+OMX_U16 armUnPackVLC32(
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pOffset,
+ const ARM_VLC32 *pCodeBook
+)
+{
+ const OMX_U8 *pBitStream = *ppBitStream;
+ OMX_INT Offset = *pOffset;
+ OMX_U32 Value;
+ OMX_INT Index;
+
+ armAssert(Offset>=0 && Offset<=7);
+
+ /* Read next 32 bits from stream */
+ Value = (pBitStream[0] << 24 ) | ( pBitStream[1] << 16) | (pBitStream[2] << 8 ) | (pBitStream[3]) ;
+ Value = (Value << Offset ) | (pBitStream[4] >> (8-Offset));
+
+ /* Search through the codebook */
+ for (Index=0; pCodeBook->codeLen != 0; Index++)
+ {
+ if (pCodeBook->codeWord == (Value >> (32 - pCodeBook->codeLen)))
+ {
+ Offset = Offset + pCodeBook->codeLen;
+ *ppBitStream = pBitStream + (Offset >> 3) ;
+ *pOffset = Offset & 7;
+
+ return Index;
+ }
+ pCodeBook++;
+ }
+
+ /* No code match found */
+ return ARM_NO_CODEBOOK_INDEX;
+}
+
+#endif
+
+/***************************************
+ * Fixed bit length Encode
+ ***************************************/
+
+/**
+ * Function: armPackBits
+ *
+ * Description:
+ * Pack a VLC code word into the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte
+ * in the bit stream.
+ * [in] pOffset pointer to the bit position in the byte
+ * pointed by *ppBitStream. Valid within 0
+ * to 7.
+ * [in] codeWord Code word that need to be inserted in to the
+ * bitstream
+ * [in] codeLength Length of the code word valid range 1...32
+ *
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMX_RESULT result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armPackBits (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pOffset,
+ OMX_U32 codeWord,
+ OMX_INT codeLength
+)
+{
+ OMX_U8 *pBitStream = *ppBitStream;
+ OMX_INT Offset = *pOffset;
+ OMX_U32 Value;
+
+ /* checking argument validity */
+ armRetArgErrIf(Offset < 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf(Offset > 7, OMX_Sts_BadArgErr);
+ armRetArgErrIf(codeLength < 1, OMX_Sts_BadArgErr);
+ armRetArgErrIf(codeLength > 32, OMX_Sts_BadArgErr);
+
+ /* Prepare the first byte */
+ codeWord = codeWord << (32-codeLength);
+ Value = (pBitStream[0] >> (8-Offset)) << (8-Offset);
+ Value = Value | (codeWord >> (24+Offset));
+
+ /* Write out whole bytes */
+ while (8-Offset <= codeLength)
+ {
+ *pBitStream++ = (OMX_U8)Value;
+ codeWord = codeWord << (8-Offset);
+ codeLength = codeLength - (8-Offset);
+ Offset = 0;
+ Value = codeWord >> 24;
+ }
+
+ /* Write out final partial byte */
+ *pBitStream = (OMX_U8)Value;
+ *ppBitStream = pBitStream;
+ *pOffset = Offset + codeLength;
+
+ return OMX_Sts_NoErr;
+}
+
+/***************************************
+ * Variable bit length Encode
+ ***************************************/
+
+/**
+ * Function: armPackVLC32
+ *
+ * Description:
+ * Pack a VLC code word into the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte
+ * in the bit stream.
+ * [in] pBitOffset pointer to the bit position in the byte
+ * pointed by *ppBitStream. Valid within 0
+ * to 7.
+ * [in] code VLC code word that need to be inserted in to the
+ * bitstream
+ *
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMX_RESULT result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armPackVLC32 (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ ARM_VLC32 code
+)
+{
+ return (armPackBits(ppBitStream, pBitOffset, code.codeWord, code.codeLen));
+}
+
+/*End of File*/
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_IDCTTable.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_IDCTTable.c
new file mode 100755
index 0000000..3f5e279
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_IDCTTable.c
@@ -0,0 +1,60 @@
+/**
+ *
+ * File Name: armCOMM_IDCTTable.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armCOMM_IDCTTable.c
+ * Brief: Defines Tables used in IDCT computation
+ *
+ */
+
+#include "armCOMM_IDCTTable.h"
+
+ /* Table of s(u)*A(u)*A(v)/16 at Q15
+ * s(u)=1.0 0 <= u <= 5
+ * s(6)=2.0
+ * s(7)=4.0
+ * A(0) = 2*sqrt(2)
+ * A(u) = 4*cos(u*pi/16) for (u!=0)
+ */
+
+__align(4) const OMX_U16 armCOMM_IDCTPreScale [64] =
+{
+ 0x4000, 0x58c5, 0x539f, 0x4b42, 0x4000, 0x3249, 0x4546, 0x46a1,
+ 0x58c5, 0x7b21, 0x73fc, 0x6862, 0x58c5, 0x45bf, 0x6016, 0x61f8,
+ 0x539f, 0x73fc, 0x6d41, 0x6254, 0x539f, 0x41b3, 0x5a82, 0x5c48,
+ 0x4b42, 0x6862, 0x6254, 0x587e, 0x4b42, 0x3b21, 0x5175, 0x530d,
+ 0x4000, 0x58c5, 0x539f, 0x4b42, 0x4000, 0x3249, 0x4546, 0x46a1,
+ 0x3249, 0x45bf, 0x41b3, 0x3b21, 0x3249, 0x2782, 0x366d, 0x377e,
+ 0x22a3, 0x300b, 0x2d41, 0x28ba, 0x22a3, 0x1b37, 0x257e, 0x263a,
+ 0x11a8, 0x187e, 0x1712, 0x14c3, 0x11a8, 0x0de0, 0x131d, 0x137d
+};
+ /* Above array armCOMM_IDCTPreScale, in Q23 format */
+const OMX_U32 armCOMM_IDCTPreScaleU32 [64] =
+{
+ 0x400000, 0x58c543, 0x539eba, 0x4b418c, 0x400000, 0x3248d4, 0x4545ea, 0x46a157,
+ 0x58c543, 0x7b20d8, 0x73fbfc, 0x686214, 0x58c543, 0x45bf1f, 0x6015a5, 0x61f78b,
+ 0x539eba, 0x73fbfc, 0x6d413d, 0x6253a6, 0x539eba, 0x41b328, 0x5a827a, 0x5c4869,
+ 0x4b418c, 0x686214, 0x6253a6, 0x587de3, 0x4b418c, 0x3b20d8, 0x5174e0, 0x530d69,
+ 0x400000, 0x58c543, 0x539eba, 0x4b418c, 0x400000, 0x3248d4, 0x4545ea, 0x46a157,
+ 0x3248d4, 0x45bf1f, 0x41b328, 0x3b20d8, 0x3248d4, 0x27821d, 0x366d72, 0x377e6b,
+ 0x22a2f5, 0x300ad3, 0x2d413d, 0x28ba70, 0x22a2f5, 0x1b36b9, 0x257d86, 0x26398d,
+ 0x11a856, 0x187de3, 0x17121a, 0x14c35a, 0x11a856, 0x0ddf9b, 0x131cc7, 0x137ca2
+};
+
+const OMX_U16 armCOMM_IDCTCoef [4] =
+{
+ 0x5a82, /* InvSqrt2 */
+ 0x30fc, /* SinPIBy8 */
+ 0x7642, /* CosPIBy8 */
+ 0x0000
+};
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_MaskTable.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_MaskTable.c
new file mode 100755
index 0000000..09f88c3
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/src/armCOMM_MaskTable.c
@@ -0,0 +1,45 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armCOMM_MaskTable.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Mask Table to mask the end of array.
+ *
+ */
+
+#include "omxtypes.h"
+
+#define MaskTableSize 72
+
+const OMX_U16 armCOMM_qMaskTable16[MaskTableSize] =
+{
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF
+};
+
+const OMX_U8 armCOMM_qMaskTable8[MaskTableSize] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVC.h
new file mode 100755
index 0000000..35b510b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVC.h
@@ -0,0 +1,1153 @@
+/**
+ *
+ * File Name: armVC.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armVideo.h
+ * Brief: Declares API's/Basic Data types used across the OpenMAX Video domain
+ *
+ */
+
+
+#ifndef _armVideo_H_
+#define _armVideo_H_
+
+#include "omxVC.h"
+#include "armCOMM_Bitstream.h"
+
+/**
+ * ARM specific state structure to hold Motion Estimation information.
+ */
+
+struct m4p2_MESpec
+{
+ OMXVCM4P2MEParams MEParams;
+ OMXVCM4P2MEMode MEMode;
+};
+
+struct m4p10_MESpec
+{
+ OMXVCM4P10MEParams MEParams;
+ OMXVCM4P10MEMode MEMode;
+};
+
+typedef struct m4p2_MESpec ARMVCM4P2_MESpec;
+typedef struct m4p10_MESpec ARMVCM4P10_MESpec;
+
+/**
+ * Function: armVCM4P2_CompareMV
+ *
+ * Description:
+ * Performs comparision of motion vectors and SAD's to decide the
+ * best MV and SAD
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] mvX x coordinate of the candidate motion vector
+ * [in] mvY y coordinate of the candidate motion vector
+ * [in] candSAD Candidate SAD
+ * [in] bestMVX x coordinate of the best motion vector
+ * [in] bestMVY y coordinate of the best motion vector
+ * [in] bestSAD best SAD
+ *
+ * Return Value:
+ * OMX_INT -- 1 to indicate that the current sad is the best
+ * 0 to indicate that it is NOT the best SAD
+ */
+
+OMX_INT armVCM4P2_CompareMV (
+ OMX_S16 mvX,
+ OMX_S16 mvY,
+ OMX_INT candSAD,
+ OMX_S16 bestMVX,
+ OMX_S16 bestMVY,
+ OMX_INT bestSAD);
+
+/**
+ * Function: armVCM4P2_ACDCPredict
+ *
+ * Description:
+ * Performs adaptive DC/AC coefficient prediction for an intra block. Prior
+ * to the function call, prediction direction (predDir) should be selected
+ * as specified in subclause 7.4.3.1 of ISO/IEC 14496-2.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcDst pointer to the coefficient buffer which contains
+ * the quantized coefficient residuals (PQF) of the
+ * current block
+ * [in] pPredBufRow pointer to the coefficient row buffer
+ * [in] pPredBufCol pointer to the coefficient column buffer
+ * [in] curQP quantization parameter of the current block. curQP
+ * may equal to predQP especially when the current
+ * block and the predictor block are in the same
+ * macroblock.
+ * [in] predQP quantization parameter of the predictor block
+ * [in] predDir indicates the prediction direction which takes one
+ * of the following values:
+ * OMX_VIDEO_HORIZONTAL predict horizontally
+ * OMX_VIDEO_VERTICAL predict vertically
+ * [in] ACPredFlag a flag indicating if AC prediction should be
+ * performed. It is equal to ac_pred_flag in the bit
+ * stream syntax of MPEG-4
+ * [in] videoComp video component type (luminance, chrominance or
+ * alpha) of the current block
+ * [in] flag This flag defines the if one wants to use this functions to
+ * calculate PQF (set 1, prediction) or QF (set 0, reconstruction)
+ * [out] pPreACPredict pointer to the predicted coefficients buffer.
+ * Filled ONLY if it is not NULL
+ * [out] pSrcDst pointer to the coefficient buffer which contains
+ * the quantized coefficients (QF) of the current
+ * block
+ * [out] pPredBufRow pointer to the updated coefficient row buffer
+ * [out] pPredBufCol pointer to the updated coefficient column buffer
+ * [out] pSumErr pointer to the updated sum of the difference
+ * between predicted and unpredicted coefficients
+ * If this is NULL, do not update
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_ACDCPredict(
+ OMX_S16 * pSrcDst,
+ OMX_S16 * pPreACPredict,
+ OMX_S16 * pPredBufRow,
+ OMX_S16 * pPredBufCol,
+ OMX_INT curQP,
+ OMX_INT predQP,
+ OMX_INT predDir,
+ OMX_INT ACPredFlag,
+ OMXVCM4P2VideoComponent videoComp,
+ OMX_U8 flag,
+ OMX_INT *pSumErr
+);
+
+/**
+ * Function: armVCM4P2_SetPredDir
+ *
+ * Description:
+ * Performs detecting the prediction direction
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] blockIndex block index indicating the component type and
+ * position as defined in subclause 6.1.3.8, of ISO/IEC
+ * 14496-2. Furthermore, indexes 6 to 9 indicate the
+ * alpha blocks spatially corresponding to luminance
+ * blocks 0 to 3 in the same macroblock.
+ * [in] pCoefBufRow pointer to the coefficient row buffer
+ * [in] pQpBuf pointer to the quantization parameter buffer
+ * [out] predQP quantization parameter of the predictor block
+ * [out] predDir indicates the prediction direction which takes one
+ * of the following values:
+ * OMX_VIDEO_HORIZONTAL predict horizontally
+ * OMX_VIDEO_VERTICAL predict vertically
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_SetPredDir(
+ OMX_INT blockIndex,
+ OMX_S16 *pCoefBufRow,
+ OMX_S16 *pCoefBufCol,
+ OMX_INT *predDir,
+ OMX_INT *predQP,
+ const OMX_U8 *pQpBuf
+);
+
+/**
+ * Function: armVCM4P2_EncodeVLCZigzag_Intra
+ *
+ * Description:
+ * Performs zigzag scanning and VLC encoding for one intra block.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7.
+ * [in] pQDctBlkCoef pointer to the quantized DCT coefficient
+ * [in] predDir AC prediction direction, which is used to decide
+ * the zigzag scan pattern. This takes one of the
+ * following values:
+ * OMX_VIDEO_NONE AC prediction not used.
+ * Performs classical zigzag
+ * scan.
+ * OMX_VIDEO_HORIZONTAL Horizontal prediction.
+ * Performs alternate-vertical
+ * zigzag scan.
+ * OMX_VIDEO_VERTICAL Vertical prediction.
+ * Performs alternate-horizontal
+ * zigzag scan.
+ * [in] pattern block pattern which is used to decide whether
+ * this block is encoded
+ * [in] start start indicates whether the encoding begins with 0th element
+ * or 1st.
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_EncodeVLCZigzag_Intra(
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 predDir,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start
+);
+
+/**
+ * Function: armVCM4P2_DecodeVLCZigzag_Intra
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan for one intra coded block.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bitstream buffer
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * to by *ppBitStream. *pBitOffset is valid within
+ * [0-7].
+ * [in] predDir AC prediction direction which is used to decide
+ * the zigzag scan pattern. It takes one of the
+ * following values:
+ * OMX_VIDEO_NONE AC prediction not used;
+ * perform classical zigzag scan;
+ * OMX_VIDEO_HORIZONTAL Horizontal prediction;
+ * perform alternate-vertical
+ * zigzag scan;
+ * OMX_VIDEO_VERTICAL Vertical prediction;
+ * thus perform
+ * alternate-horizontal
+ * zigzag scan.
+ * [in] videoComp video component type (luminance, chrominance or
+ * alpha) of the current block
+ * [in] shortVideoHeader binary flag indicating presence of short_video_header; escape modes 0-3 are used if shortVideoHeader==0,
+ * and escape mode 4 is used when shortVideoHeader==1.
+ * [in] start start indicates whether the encoding begins with 0th element
+ * or 1st.
+ * [out] ppBitStream *ppBitStream is updated after the block is
+ * decoded, so that it points to the current byte
+ * in the bit stream buffer
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream
+ * [out] pDst pointer to the coefficient buffer of current
+ * block. Should be 32-bit aligned
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_DecodeVLCZigzag_Intra(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_U8 predDir,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start
+);
+
+/**
+ * Function: armVCM4P2_FillVLDBuffer
+ *
+ * Description:
+ * Performs filling of the coefficient buffer according to the run, level
+ * and sign, also updates the index
+ *
+ * Parameters:
+ * [in] storeRun Stored Run value (count of zeros)
+ * [in] storeLevel Stored Level value (non-zero value)
+ * [in] sign Flag indicating the sign of level
+ * [in] last status of the last flag
+ * [in] pIndex pointer to coefficient index in 8x8 matrix
+ * [out] pIndex pointer to updated coefficient index in 8x8
+ * matrix
+ * [in] pZigzagTable pointer to the zigzag tables
+ * [out] pDst pointer to the coefficient buffer of current
+ * block. Should be 32-bit aligned
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_FillVLDBuffer(
+ OMX_U32 storeRun,
+ OMX_S16 * pDst,
+ OMX_S16 storeLevel,
+ OMX_U8 sign,
+ OMX_U8 last,
+ OMX_U8 * index,
+ const OMX_U8 * pZigzagTable
+);
+
+/**
+ * Function: armVCM4P2_GetVLCBits
+ *
+ * Description:
+ * Performs escape mode decision based on the run, run+, level, level+ and
+ * last combinations.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7
+ * [in] shortVideoHeader binary flag indicating presence of short_video_header; escape modes 0-3 are used if shortVideoHeader==0,
+ * and escape mode 4 is used when shortVideoHeader==1.
+ * [in] start start indicates whether the encoding begins with
+ * 0th element or 1st.
+ * [in/out] pLast pointer to last status flag
+ * [in] runBeginSingleLevelEntriesL0 The run value from which level
+ * will be equal to 1: last == 0
+ * [in] IndexBeginSingleLevelEntriesL0 Array index in the VLC table
+ * pointing to the
+ * runBeginSingleLevelEntriesL0
+ * [in] runBeginSingleLevelEntriesL1 The run value from which level
+ * will be equal to 1: last == 1
+ * [in] IndexBeginSingleLevelEntriesL1 Array index in the VLC table
+ * pointing to the
+ * runBeginSingleLevelEntriesL0
+ * [in] pRunIndexTableL0 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pVlcTableL0 VLC table for last == 0
+ * [in] pRunIndexTableL1 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pVlcTableL1 VLC table for last == 1
+ * [in] pLMAXTableL0 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pLMAXTableL1 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pRMAXTableL0 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pRMAXTableL1 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [out]pDst pointer to the coefficient buffer of current
+ * block. Should be 32-bit aligned
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_GetVLCBits (
+ const OMX_U8 **ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start,
+ OMX_U8 * pLast,
+ OMX_U8 runBeginSingleLevelEntriesL0,
+ OMX_U8 maxIndexForMultipleEntriesL0,
+ OMX_U8 maxRunForMultipleEntriesL1,
+ OMX_U8 maxIndexForMultipleEntriesL1,
+ const OMX_U8 * pRunIndexTableL0,
+ const ARM_VLC32 *pVlcTableL0,
+ const OMX_U8 * pRunIndexTableL1,
+ const ARM_VLC32 *pVlcTableL1,
+ const OMX_U8 * pLMAXTableL0,
+ const OMX_U8 * pLMAXTableL1,
+ const OMX_U8 * pRMAXTableL0,
+ const OMX_U8 * pRMAXTableL1,
+ const OMX_U8 * pZigzagTable
+);
+
+/**
+ * Function: armVCM4P2_PutVLCBits
+ *
+ * Description:
+ * Checks the type of Escape Mode and put encoded bits for
+ * quantized DCT coefficients.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7
+ * [in] shortVideoHeader binary flag indicating presence of short_video_header; escape modes 0-3 are used if shortVideoHeader==0,
+ * and escape mode 4 is used when shortVideoHeader==1.
+ * [in] start start indicates whether the encoding begins with
+ * 0th element or 1st.
+ * [in] maxStoreRunL0 Max store possible (considering last and inter/intra)
+ * for last = 0
+ * [in] maxStoreRunL1 Max store possible (considering last and inter/intra)
+ * for last = 1
+ * [in] maxRunForMultipleEntriesL0
+ * The run value after which level
+ * will be equal to 1:
+ * (considering last and inter/intra status) for last = 0
+ * [in] maxRunForMultipleEntriesL1
+ * The run value after which level
+ * will be equal to 1:
+ * (considering last and inter/intra status) for last = 1
+ * [in] pRunIndexTableL0 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pVlcTableL0 VLC table for last == 0
+ * [in] pRunIndexTableL1 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pVlcTableL1 VLC table for last == 1
+ * [in] pLMAXTableL0 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pLMAXTableL1 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pRMAXTableL0 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pRMAXTableL1 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [out] pQDctBlkCoef pointer to the quantized DCT coefficient
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+
+OMXResult armVCM4P2_PutVLCBits (
+ OMX_U8 **ppBitStream,
+ OMX_INT * pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start,
+ OMX_U8 maxStoreRunL0,
+ OMX_U8 maxStoreRunL1,
+ OMX_U8 maxRunForMultipleEntriesL0,
+ OMX_U8 maxRunForMultipleEntriesL1,
+ const OMX_U8 * pRunIndexTableL0,
+ const ARM_VLC32 *pVlcTableL0,
+ const OMX_U8 * pRunIndexTableL1,
+ const ARM_VLC32 *pVlcTableL1,
+ const OMX_U8 * pLMAXTableL0,
+ const OMX_U8 * pLMAXTableL1,
+ const OMX_U8 * pRMAXTableL0,
+ const OMX_U8 * pRMAXTableL1,
+ const OMX_U8 * pZigzagTable
+);
+/**
+ * Function: armVCM4P2_FillVLCBuffer
+ *
+ * Description:
+ * Performs calculating the VLC bits depending on the escape type and insert
+ * the same in the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7
+ * [in] run Run value (count of zeros) to be encoded
+ * [in] level Level value (non-zero value) to be encoded
+ * [in] runPlus Calculated as runPlus = run - (RMAX + 1)
+ * [in] levelPlus Calculated as
+ * levelPlus = sign(level)*[abs(level) - LMAX]
+ * [in] fMode Flag indicating the escape modes
+ * [in] last status of the last flag
+ * [in] maxRunForMultipleEntries
+ * The run value after which level will be equal to 1:
+ * (considering last and inter/intra status)
+ * [in] pRunIndexTable Run Index table defined in
+ * armVCM4P2_Huff_tables_VLC.h
+ * [in] pVlcTable VLC table defined in armVCM4P2_Huff_tables_VLC.h
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_FillVLCBuffer (
+ OMX_U8 **ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_U32 run,
+ OMX_S16 level,
+ OMX_U32 runPlus,
+ OMX_S16 levelPlus,
+ OMX_U8 fMode,
+ OMX_U8 last,
+ OMX_U8 maxRunForMultipleEntries,
+ const OMX_U8 *pRunIndexTable,
+ const ARM_VLC32 *pVlcTable
+);
+
+/**
+ * Function: armVCM4P2_CheckVLCEscapeMode
+ *
+ * Description:
+ * Performs escape mode decision based on the run, run+, level, level+ and
+ * last combinations.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] run Run value (count of zeros) to be encoded
+ * [in] level Level value (non-zero value) to be encoded
+ * [in] runPlus Calculated as runPlus = run - (RMAX + 1)
+ * [in] levelPlus Calculated as
+ * levelPlus = sign(level)*[abs(level) - LMAX]
+ * [in] maxStoreRun Max store possible (considering last and inter/intra)
+ * [in] maxRunForMultipleEntries
+ * The run value after which level
+ * will be equal to 1:
+ * (considering last and inter/intra status)
+ * [in] shortVideoHeader binary flag indicating presence of short_video_header; escape modes 0-3 are used if shortVideoHeader==0,
+ * and escape mode 4 is used when shortVideoHeader==1.
+ * [in] pRunIndexTable Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c
+ * (considering last and inter/intra status)
+ *
+ *
+ * Return Value:
+ * Returns an Escape mode which can take values from 0 to 3
+ * 0 --> no escape mode, 1 --> escape type 1,
+ * 1 --> escape type 2, 3 --> escape type 3, check section 7.4.1.3
+ * in the MPEG ISO standard.
+ *
+ */
+
+OMX_U8 armVCM4P2_CheckVLCEscapeMode(
+ OMX_U32 run,
+ OMX_U32 runPlus,
+ OMX_S16 level,
+ OMX_S16 levelPlus,
+ OMX_U8 maxStoreRun,
+ OMX_U8 maxRunForMultipleEntries,
+ OMX_INT shortVideoHeader,
+ const OMX_U8 *pRunIndexTable
+);
+
+
+/**
+ * Function: armVCM4P2_BlockMatch_Integer
+ *
+ * Description:
+ * Performs a 16x16 block search; estimates motion vector and associated minimum SAD.
+ * Both the input and output motion vectors are represented using half-pixel units, and
+ * therefore a shift left or right by 1 bit may be required, respectively, to match the
+ * input or output MVs with other functions that either generate output MVs or expect
+ * input MVs represented using integer pixel units.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcRefBuf pointer to the reference Y plane; points to the reference MB that
+ * corresponds to the location of the current macroblock in the current
+ * plane.
+ * [in] refWidth width of the reference plane
+ * [in] pRefRect pointer to the valid rectangular in reference plane. Relative to image origin.
+ * It's not limited to the image boundary, but depended on the padding. For example,
+ * if you pad 4 pixels outside the image border, then the value for left border
+ * can be -4
+ * [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane (linear array,
+ * 256 entries); must be aligned on an 8-byte boundary.
+ * [in] pCurrPointPos position of the current macroblock in the current plane
+ * [in] pSrcPreMV pointer to predicted motion vector; NULL indicates no predicted MV
+ * [in] pSrcPreSAD pointer to SAD associated with the predicted MV (referenced by pSrcPreMV)
+ * [in] searchRange search range for 16X16 integer block,the units of it is full pixel,the search range
+ * is the same in all directions.It is in inclusive of the boundary and specified in
+ * terms of integer pixel units.
+ * [in] pMESpec vendor-specific motion estimation specification structure; must have been allocated
+ * and then initialized using omxVCM4P2_MEInit prior to calling the block matching
+ * function.
+ * [in] BlockSize MacroBlock Size i.e either 16x16 or 8x8.
+ * [out] pDstMV pointer to estimated MV
+ * [out] pDstSAD pointer to minimum SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr ¨C no error.
+ * OMX_Sts_BadArgErr ¨C bad arguments
+ *
+ */
+
+OMXResult armVCM4P2_BlockMatch_Integer(
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCMotionVector *pSrcPreMV,
+ const OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector *pDstMV,
+ OMX_INT *pDstSAD,
+ OMX_U8 BlockSize
+);
+
+/**
+ * Function: armVCM4P2_BlockMatch_Half
+ *
+ * Description:
+ * Performs a 16x16 block match with half-pixel resolution. Returns the estimated
+ * motion vector and associated minimum SAD. This function estimates the half-pixel
+ * motion vector by interpolating the integer resolution motion vector referenced
+ * by the input parameter pSrcDstMV, i.e., the initial integer MV is generated
+ * externally. The input parameters pSrcRefBuf and pSearchPointRefPos should be
+ * shifted by the winning MV of 16x16 integer search prior to calling BlockMatch_Half_16x16.
+ * The function BlockMatch_Integer_16x16 may be used for integer motion estimation.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcRefBuf pointer to the reference Y plane; points to the reference MB
+ * that corresponds to the location of the current macroblock in
+ * the current plane.
+ * [in] refWidth width of the reference plane
+ * [in] pRefRect reference plane valid region rectangle
+ * [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane
+ * (linear array, 256 entries); must be aligned on an 8-byte boundary.
+ * [in] pSearchPointRefPos position of the starting point for half pixel search (specified
+ * in terms of integer pixel units) in the reference plane.
+ * [in] rndVal rounding control bit for half pixel motion estimation;
+ * 0=rounding control disabled; 1=rounding control enabled
+ * [in] pSrcDstMV pointer to the initial MV estimate; typically generated during a prior
+ * 16X16 integer search and its unit is half pixel.
+ * [in] BlockSize MacroBlock Size i.e either 16x16 or 8x8.
+ * [out]pSrcDstMV pointer to estimated MV
+ * [out]pDstSAD pointer to minimum SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr ¨C no error
+ * OMX_Sts_BadArgErr ¨C bad arguments
+ *
+ */
+
+OMXResult armVCM4P2_BlockMatch_Half(
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pSearchPointRefPos,
+ OMX_INT rndVal,
+ OMXVCMotionVector *pSrcDstMV,
+ OMX_INT *pDstSAD,
+ OMX_U8 BlockSize
+);
+/**
+ * Function: armVCM4P2_PadMV
+ *
+ * Description:
+ * Performs motion vector padding for a macroblock.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcDstMV pointer to motion vector buffer of the current
+ * macroblock
+ * [in] pTransp pointer to transparent status buffer of the
+ * current macroblock
+ * [out] pSrcDstMV pointer to motion vector buffer in which the
+ * motion vectors have been padded
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_PadMV(
+ OMXVCMotionVector * pSrcDstMV,
+ OMX_U8 * pTransp
+);
+
+/*
+ * H.264 Specific Declarations
+ */
+/* Defines */
+#define ARM_M4P10_Q_OFFSET (15)
+
+
+/* Dequant tables */
+
+extern const OMX_U8 armVCM4P10_PosToVCol4x4[16];
+extern const OMX_U8 armVCM4P10_PosToVCol2x2[4];
+extern const OMX_U8 armVCM4P10_VMatrix[6][3];
+extern const OMX_U32 armVCM4P10_MFMatrix[6][3];
+
+
+/*
+ * Description:
+ * This function perform the work required by the OpenMAX
+ * DecodeCoeffsToPair function and DecodeChromaDCCoeffsToPair.
+ * Since most of the code is common we share it here.
+ *
+ * Parameters:
+ * [in] ppBitStream Double pointer to current byte in bit stream buffer
+ * [in] pOffset Pointer to current bit position in the byte pointed
+ * to by *ppBitStream
+ * [in] sMaxNumCoeff Maximum number of non-zero coefficients in current
+ * block (4,15 or 16)
+ * [in] nTable Table number (0 to 4) according to the five columns
+ * of Table 9-5 in the H.264 spec
+ * [out] ppBitStream *ppBitStream is updated after each block is decoded
+ * [out] pOffset *pOffset is updated after each block is decoded
+ * [out] pNumCoeff Pointer to the number of nonzero coefficients in
+ * this block
+ * [out] ppPosCoefbuf Double pointer to destination residual
+ * coefficient-position pair buffer
+ * Return Value:
+ * Standard omxError result. See enumeration for possible result codes.
+
+ */
+
+OMXResult armVCM4P10_DecodeCoeffsToPair(
+ const OMX_U8** ppBitStream,
+ OMX_S32* pOffset,
+ OMX_U8* pNumCoeff,
+ OMX_U8**ppPosCoefbuf,
+ OMX_INT nTable,
+ OMX_INT sMaxNumCoeff
+ );
+
+/*
+ * Description:
+ * Perform DC style intra prediction, averaging upper and left block
+ *
+ * Parameters:
+ * [in] pSrcLeft Pointer to the buffer of 16 left coefficients:
+ * p[x, y] (x = -1, y = 0..3)
+ * [in] pSrcAbove Pointer to the buffer of 16 above coefficients:
+ * p[x,y] (x = 0..3, y = -1)
+ * [in] leftStep Step of left coefficient buffer
+ * [in] dstStep Step of the destination buffer
+ * [in] availability Neighboring 16x16 MB availability flag
+ * [out] pDst Pointer to the destination buffer
+ *
+ * Return Value:
+ * None
+ */
+
+void armVCM4P10_PredictIntraDC4x4(
+ const OMX_U8* pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ OMX_U8* pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMX_S32 availability
+);
+
+/*
+ * Description
+ * Unpack a 4x4 block of coefficient-residual pair values
+ *
+ * Parameters:
+ * [in] ppSrc Double pointer to residual coefficient-position pair
+ * buffer output by CALVC decoding
+ * [out] ppSrc *ppSrc is updated to the start of next non empty block
+ * [out] pDst Pointer to unpacked 4x4 block
+ */
+
+void armVCM4P10_UnpackBlock4x4(
+ const OMX_U8 **ppSrc,
+ OMX_S16* pDst
+);
+
+/*
+ * Description
+ * Unpack a 2x2 block of coefficient-residual pair values
+ *
+ * Parameters:
+ * [in] ppSrc Double pointer to residual coefficient-position pair
+ * buffer output by CALVC decoding
+ * [out] ppSrc *ppSrc is updated to the start of next non empty block
+ * [out] pDst Pointer to unpacked 4x4 block
+ */
+
+void armVCM4P10_UnpackBlock2x2(
+ const OMX_U8 **ppSrc,
+ OMX_S16* pDst
+);
+
+/*
+ * Description
+ * Deblock one boundary pixel
+ *
+ * Parameters:
+ * [in] pQ0 Pointer to pixel q0
+ * [in] Step Step between pixels q0 and q1
+ * [in] tC0 Edge threshold value
+ * [in] alpha alpha threshold value
+ * [in] beta beta threshold value
+ * [in] bS deblocking strength
+ * [in] ChromaFlag True for chroma blocks
+ * [out] pQ0 Deblocked pixels
+ *
+ */
+
+void armVCM4P10_DeBlockPixel(
+ OMX_U8 *pQ0, /* pointer to the pixel q0 */
+ int Step, /* step between pixels q0 and q1 */
+ int tC0, /* edge threshold value */
+ int alpha, /* alpha */
+ int beta, /* beta */
+ int bS, /* deblocking strength */
+ int ChromaFlag
+);
+
+/**
+ * Function: armVCM4P10_InterpolateHalfHor_Luma
+ *
+ * Description:
+ * This function performs interpolation for horizontal 1/2-pel positions
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to interpolate
+ in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [out] pDst Pointer to the interpolation buffer of the 1/2-pel
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+OMXResult armVCM4P10_InterpolateHalfHor_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+/**
+ * Function: armVCM4P10_InterpolateHalfVer_Luma
+ *
+ * Description:
+ * This function performs interpolation for vertical 1/2-pel positions
+ * around a full-pel position.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to interpolate
+ * in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [out] pDst Pointer to the interpolation buffer of the 1/2-pel
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+OMXResult armVCM4P10_InterpolateHalfVer_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+/**
+ * Function: armVCM4P10_InterpolateHalfDiag_Luma
+ *
+ * Description:
+ * This function performs interpolation for (1/2, 1/2) positions
+ * around a full-pel position.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to interpolate
+ * in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [out] pDst Pointer to the interpolation buffer of the (1/2,1/2)-pel
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+OMXResult armVCM4P10_InterpolateHalfDiag_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+/*
+ * Description:
+ * Transform Residual 4x4 Coefficients
+ *
+ * Parameters:
+ * [in] pSrc Source 4x4 block
+ * [out] pDst Destination 4x4 block
+ *
+ */
+
+void armVCM4P10_TransformResidual4x4(OMX_S16* pDst, OMX_S16 *pSrc);
+
+/*
+ * Description:
+ * Forward Transform Residual 4x4 Coefficients
+ *
+ * Parameters:
+ * [in] pSrc Source 4x4 block
+ * [out] pDst Destination 4x4 block
+ *
+ */
+
+void armVCM4P10_FwdTransformResidual4x4(OMX_S16* pDst, OMX_S16 *pSrc);
+
+OMX_INT armVCM4P10_CompareMotionCostToMV (
+ OMX_S16 mvX,
+ OMX_S16 mvY,
+ OMXVCMotionVector diffMV,
+ OMX_INT candSAD,
+ OMXVCMotionVector *bestMV,
+ OMX_U32 nLamda,
+ OMX_S32 *pBestCost);
+
+/**
+ * Function: armVCCOMM_SAD
+ *
+ * Description:
+ * This function calculate the SAD for NxM blocks.
+ *
+ * Remarks:
+ *
+ * [in] pSrcOrg Pointer to the original block
+ * [in] iStepOrg Step of the original block buffer
+ * [in] pSrcRef Pointer to the reference block
+ * [in] iStepRef Step of the reference block buffer
+ * [in] iHeight Height of the block
+ * [in] iWidth Width of the block
+ * [out] pDstSAD Pointer of result SAD
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+OMXResult armVCCOMM_SAD(
+ const OMX_U8* pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8* pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32* pDstSAD,
+ OMX_U32 iHeight,
+ OMX_U32 iWidth);
+
+/**
+ * Function: armVCCOMM_Average
+ *
+ * Description:
+ * This function calculates the average of two blocks and stores the result.
+ *
+ * Remarks:
+ *
+ * [in] pPred0 Pointer to the top-left corner of reference block 0
+ * [in] pPred1 Pointer to the top-left corner of reference block 1
+ * [in] iPredStep0 Step of reference block 0
+ * [in] iPredStep1 Step of reference block 1
+ * [in] iDstStep Step of the destination buffer
+ * [in] iWidth Width of the blocks
+ * [in] iHeight Height of the blocks
+ * [out] pDstPred Pointer to the destination buffer
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+ OMXResult armVCCOMM_Average (
+ const OMX_U8* pPred0,
+ const OMX_U8* pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8* pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+/**
+ * Function: armVCM4P10_SADQuar
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the
+ * average of the other two (pSrcRef0 and pSrcRef1)
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to the original block
+ * [in] pSrcRef0 Pointer to reference block 0
+ * [in] pSrcRef1 Pointer to reference block 1
+ * [in] iSrcStep Step of the original block buffer
+ * [in] iRefStep0 Step of reference block 0
+ * [in] iRefStep1 Step of reference block 1
+ * [in] iHeight Height of the block
+ * [in] iWidth Width of the block
+ * [out] pDstSAD Pointer of result SAD
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+OMXResult armVCM4P10_SADQuar(
+ const OMX_U8* pSrc,
+ const OMX_U8* pSrcRef0,
+ const OMX_U8* pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32* pDstSAD,
+ OMX_U32 iHeight,
+ OMX_U32 iWidth
+);
+
+/**
+ * Function: armVCM4P10_Interpolate_Chroma
+ *
+ * Description:
+ * This function performs interpolation for chroma components.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to
+ * interpolate in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [in] dx Fractional part of horizontal motion vector
+ * component in 1/8 pixel unit (0~7)
+ * [in] dy Fractional part of vertical motion vector
+ * component in 1/8 pixel unit (0~7)
+ * [out] pDst Pointer to the interpolation buffer
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+ OMXResult armVCM4P10_Interpolate_Chroma(
+ OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight,
+ OMX_U32 dx,
+ OMX_U32 dy
+);
+
+/**
+ * Function: armVCM4P10_Interpolate_Luma
+ *
+ * Description:
+ * This function performs interpolation for luma components.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to
+ * interpolate in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [in] dx Fractional part of horizontal motion vector
+ * component in 1/4 pixel unit (0~3)
+ * [in] dy Fractional part of vertical motion vector
+ * component in 1/4 pixel unit (0~3)
+ * [out] pDst Pointer to the interpolation buffer
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+ OMXResult armVCM4P10_Interpolate_Luma(
+ const OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight,
+ OMX_U32 dx,
+ OMX_U32 dy
+);
+
+/**
+ * Function: omxVCH264_DequantTransformACFromPair_U8_S16_C1_DLx
+ *
+ * Description:
+ * Reconstruct the 4x4 residual block from coefficient-position pair buffer,
+ * perform dequantisation and integer inverse transformation for 4x4 block of
+ * residuals and update the pair buffer pointer to next non-empty block.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppSrc Double pointer to residual coefficient-position
+ * pair buffer output by CALVC decoding
+ * [in] pDC Pointer to the DC coefficient of this block, NULL
+ * if it doesn't exist
+ * [in] QP Quantization parameter
+ * [in] AC Flag indicating if at least one non-zero coefficient exists
+ * [out] pDst pointer to the reconstructed 4x4 block data
+ *
+ * Return Value:
+ * Standard omxError result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P10_DequantTransformACFromPair_U8_S16_C1_DLx(
+ OMX_U8 **ppSrc,
+ OMX_S16 *pDst,
+ OMX_INT QP,
+ OMX_S16* pDC,
+ int AC
+);
+
+#endif /*_armVideo_H_*/
+
+/*End of File*/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVCCOMM_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVCCOMM_s.h
new file mode 100755
index 0000000..32a0166
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/armVCCOMM_s.h
@@ -0,0 +1,72 @@
+;//
+;//
+;// File Name: armVCCOMM_s.h
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// ARM optimized OpenMAX AC header file
+;//
+;// Formula used:
+;// MACRO for calculating median for three values.
+
+
+
+ IF :LNOT::DEF:ARMVCCOMM_S_H
+ INCLUDE armCOMM_s.h
+ M_VARIANTS CortexA8, ARM1136JS
+
+ IF ARM1136JS :LOR: CortexA8
+
+ ;///*
+ ;// * Macro: M_MEDIAN3
+ ;// *
+ ;// * Description: Finds the median of three numbers
+ ;// *
+ ;// * Remarks:
+ ;// *
+ ;// * Parameters:
+ ;// * [in] x First entry for the list of three numbers.
+ ;// * [in] y Second entry for the list of three numbers.
+ ;// * Input value may be corrupted at the end of
+ ;// * the execution of this macro.
+ ;// * [in] z Third entry of the list of three numbers.
+ ;// * Input value corrupted at the end of the
+ ;// * execution of this macro.
+ ;// * [in] t Temporary scratch register.
+ ;// * [out]z Median of the three numbers.
+ ;// */
+
+ MACRO
+
+ M_MEDIAN3 $x, $y, $z, $t
+
+ SUBS $t, $y, $z; // if (y < z)
+ ADDLT $z, $z, $t; // swap y and z
+ SUBLT $y, $y, $t;
+
+ ;// Now z' <= y', so there are three cases for the
+ ;// median value, depending on x.
+
+ ;// 1) x <= z' <= y' : median value is z'
+ ;// 2) z' <= x <= y' : median value is x
+ ;// 3) z' <= y' <= x : median value is y'
+
+ CMP $z, $x; // if ( x > min(y,z) )
+ MOVLT $z, $x; // ans = x
+
+ CMP $x, $y; // if ( x > max(y,z) )
+ MOVGT $z, $y; // ans = max(y,z)
+
+ MEND
+ ENDIF
+
+
+
+ ENDIF ;// ARMACCOMM_S_H
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/omxVC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/omxVC.h
new file mode 100755
index 0000000..7b3cc72
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/omxVC.h
@@ -0,0 +1,4381 @@
+/**
+ * File: omxVC.h
+ * Brief: OpenMAX DL v1.0.2 - Video Coding library
+ *
+ * Copyright © 2005-2008 The Khronos Group Inc. All Rights Reserved.
+ *
+ * These materials are protected by copyright laws and contain material
+ * proprietary to the Khronos Group, Inc. You may use these materials
+ * for implementing Khronos specifications, without altering or removing
+ * any trademark, copyright or other notice from the specification.
+ *
+ * Khronos Group makes no, and expressly disclaims any, representations
+ * or warranties, express or implied, regarding these materials, including,
+ * without limitation, any implied warranties of merchantability or fitness
+ * for a particular purpose or non-infringement of any intellectual property.
+ * Khronos Group makes no, and expressly disclaims any, warranties, express
+ * or implied, regarding the correctness, accuracy, completeness, timeliness,
+ * and reliability of these materials.
+ *
+ * Under no circumstances will the Khronos Group, or any of its Promoters,
+ * Contributors or Members or their respective partners, officers, directors,
+ * employees, agents or representatives be liable for any damages, whether
+ * direct, indirect, special or consequential damages for lost revenues,
+ * lost profits, or otherwise, arising from or in connection with these
+ * materials.
+ *
+ * Khronos and OpenMAX are trademarks of the Khronos Group Inc.
+ *
+ */
+
+/* *****************************************************************************************/
+
+#ifndef _OMXVC_H_
+#define _OMXVC_H_
+
+#include "omxtypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* 6.1.1.1 Motion Vectors */
+/* In omxVC, motion vectors are represented as follows: */
+
+typedef struct {
+ OMX_S16 dx;
+ OMX_S16 dy;
+} OMXVCMotionVector;
+
+
+
+/**
+ * Function: omxVCCOMM_Average_8x (6.1.3.1.1)
+ *
+ * Description:
+ * This function calculates the average of two 8x4, 8x8, or 8x16 blocks. The
+ * result is rounded according to (a+b+1)/2. The block average function can
+ * be used in conjunction with half-pixel interpolation to obtain quarter
+ * pixel motion estimates, as described in [ISO14496-10], subclause 8.4.2.2.1.
+ *
+ * Input Arguments:
+ *
+ * pPred0 - Pointer to the top-left corner of reference block 0
+ * pPred1 - Pointer to the top-left corner of reference block 1
+ * iPredStep0 - Step of reference block 0
+ * iPredStep1 - Step of reference block 1
+ * iDstStep - Step of the destination buffer.
+ * iHeight - Height of the blocks
+ *
+ * Output Arguments:
+ *
+ * pDstPred - Pointer to the destination buffer. 8-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pPred0, pPred1, or
+ * pDstPred.
+ * - pDstPred is not aligned on an 8-byte boundary.
+ * - iPredStep0 <= 0 or iPredStep0 is not a multiple of 8.
+ * - iPredStep1 <= 0 or iPredStep1 is not a multiple of 8.
+ * - iDstStep <= 0 or iDstStep is not a multiple of 8.
+ * - iHeight is not 4, 8, or 16.
+ *
+ */
+OMXResult omxVCCOMM_Average_8x (
+ const OMX_U8 *pPred0,
+ const OMX_U8 *pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8 *pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCCOMM_Average_16x (6.1.3.1.2)
+ *
+ * Description:
+ * This function calculates the average of two 16x16 or 16x8 blocks. The
+ * result is rounded according to (a+b+1)/2. The block average function can
+ * be used in conjunction with half-pixel interpolation to obtain quarter
+ * pixel motion estimates, as described in [ISO14496-10], subclause 8.4.2.2.1.
+ *
+ * Input Arguments:
+ *
+ * pPred0 - Pointer to the top-left corner of reference block 0
+ * pPred1 - Pointer to the top-left corner of reference block 1
+ * iPredStep0 - Step of reference block 0
+ * iPredStep1 - Step of reference block 1
+ * iDstStep - Step of the destination buffer
+ * iHeight - Height of the blocks
+ *
+ * Output Arguments:
+ *
+ * pDstPred - Pointer to the destination buffer. 16-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pPred0, pPred1, or
+ * pDstPred.
+ * - pDstPred is not aligned on a 16-byte boundary.
+ * - iPredStep0 <= 0 or iPredStep0 is not a multiple of 16.
+ * - iPredStep1 <= 0 or iPredStep1 is not a multiple of 16.
+ * - iDstStep <= 0 or iDstStep is not a multiple of 16.
+ * - iHeight is not 8 or 16.
+ *
+ */
+OMXResult omxVCCOMM_Average_16x (
+ const OMX_U8 *pPred0,
+ const OMX_U8 *pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8 *pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCCOMM_ExpandFrame_I (6.1.3.2.1)
+ *
+ * Description:
+ * This function expands a reconstructed frame in-place. The unexpanded
+ * source frame should be stored in a plane buffer with sufficient space
+ * pre-allocated for edge expansion, and the input frame should be located in
+ * the plane buffer center. This function executes the pixel expansion by
+ * replicating source frame edge pixel intensities in the empty pixel
+ * locations (expansion region) between the source frame edge and the plane
+ * buffer edge. The width/height of the expansion regions on the
+ * horizontal/vertical edges is controlled by the parameter iExpandPels.
+ *
+ * Input Arguments:
+ *
+ * pSrcDstPlane - pointer to the top-left corner of the frame to be
+ * expanded; must be aligned on an 8-byte boundary.
+ * iFrameWidth - frame width; must be a multiple of 8.
+ * iFrameHeight -frame height; must be a multiple of 8.
+ * iExpandPels - number of pixels to be expanded in the horizontal and
+ * vertical directions; must be a multiple of 8.
+ * iPlaneStep - distance, in bytes, between the start of consecutive lines
+ * in the plane buffer; must be larger than or equal to
+ * (iFrameWidth + 2 * iExpandPels).
+ *
+ * Output Arguments:
+ *
+ * pSrcDstPlane -Pointer to the top-left corner of the frame (NOT the
+ * top-left corner of the plane); must be aligned on an 8-byte
+ * boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - pSrcDstPlane is NULL.
+ * - pSrcDstPlane is not aligned on an 8-byte boundary.
+ * - one of the following parameters is either equal to zero or is a
+ * non-multiple of 8: iFrameHeight, iFrameWidth, iPlaneStep, or
+ * iExpandPels.
+ * - iPlaneStep < (iFrameWidth + 2 * iExpandPels).
+ *
+ */
+OMXResult omxVCCOMM_ExpandFrame_I (
+ OMX_U8 *pSrcDstPlane,
+ OMX_U32 iFrameWidth,
+ OMX_U32 iFrameHeight,
+ OMX_U32 iExpandPels,
+ OMX_U32 iPlaneStep
+);
+
+
+
+/**
+ * Function: omxVCCOMM_Copy8x8 (6.1.3.3.1)
+ *
+ * Description:
+ * Copies the reference 8x8 block to the current block.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the reference block in the source frame; must be
+ * aligned on an 8-byte boundary.
+ * step - distance between the starts of consecutive lines in the reference
+ * frame, in bytes; must be a multiple of 8 and must be larger than
+ * or equal to 8.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination block; must be aligned on an 8-byte
+ * boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pSrc, pDst
+ * - one or more of the following pointers is not aligned on an 8-byte
+ * boundary: pSrc, pDst
+ * - step <8 or step is not a multiple of 8.
+ *
+ */
+OMXResult omxVCCOMM_Copy8x8 (
+ const OMX_U8 *pSrc,
+ OMX_U8 *pDst,
+ OMX_INT step
+);
+
+
+
+/**
+ * Function: omxVCCOMM_Copy16x16 (6.1.3.3.2)
+ *
+ * Description:
+ * Copies the reference 16x16 macroblock to the current macroblock.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the reference macroblock in the source frame; must be
+ * aligned on a 16-byte boundary.
+ * step - distance between the starts of consecutive lines in the reference
+ * frame, in bytes; must be a multiple of 16 and must be larger
+ * than or equal to 16.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination macroblock; must be aligned on a
+ * 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pSrc, pDst
+ * - one or more of the following pointers is not aligned on a 16-byte
+ * boundary: pSrc, pDst
+ * - step <16 or step is not a multiple of 16.
+ *
+ */
+OMXResult omxVCCOMM_Copy16x16 (
+ const OMX_U8 *pSrc,
+ OMX_U8 *pDst,
+ OMX_INT step
+);
+
+
+
+/**
+ * Function: omxVCCOMM_ComputeTextureErrorBlock_SAD (6.1.4.1.1)
+ *
+ * Description:
+ * Computes texture error of the block; also returns SAD.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the source plane; must be aligned on an 8-byte
+ * boundary.
+ * srcStep - step of the source plane
+ * pSrcRef - pointer to the reference buffer, an 8x8 block; must be aligned
+ * on an 8-byte boundary.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination buffer, an 8x8 block; must be aligned
+ * on an 8-byte boundary.
+ * pDstSAD - pointer to the Sum of Absolute Differences (SAD) value
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - At least one of the following
+ * pointers is NULL: pSrc, pSrcRef, pDst and pDstSAD.
+ * - pSrc is not 8-byte aligned.
+ * - SrcStep <= 0 or srcStep is not a multiple of 8.
+ * - pSrcRef is not 8-byte aligned.
+ * - pDst is not 8-byte aligned.
+ *
+ */
+OMXResult omxVCCOMM_ComputeTextureErrorBlock_SAD (
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ const OMX_U8 *pSrcRef,
+ OMX_S16 *pDst,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCCOMM_ComputeTextureErrorBlock (6.1.4.1.2)
+ *
+ * Description:
+ * Computes the texture error of the block.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the source plane. This should be aligned on an 8-byte
+ * boundary.
+ * srcStep - step of the source plane
+ * pSrcRef - pointer to the reference buffer, an 8x8 block. This should be
+ * aligned on an 8-byte boundary.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination buffer, an 8x8 block. This should be
+ * aligned on an 8-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is NULL:
+ * pSrc, pSrcRef, pDst.
+ * - pSrc is not 8-byte aligned.
+ * - SrcStep <= 0 or srcStep is not a multiple of 8.
+ * - pSrcRef is not 8-byte aligned.
+ * - pDst is not 8-byte aligned
+ *
+ */
+OMXResult omxVCCOMM_ComputeTextureErrorBlock (
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ const OMX_U8 *pSrcRef,
+ OMX_S16 *pDst
+);
+
+
+
+/**
+ * Function: omxVCCOMM_LimitMVToRect (6.1.4.1.3)
+ *
+ * Description:
+ * Limits the motion vector associated with the current block/macroblock to
+ * prevent the motion compensated block/macroblock from moving outside a
+ * bounding rectangle as shown in Figure 6-1.
+ *
+ * Input Arguments:
+ *
+ * pSrcMV - pointer to the motion vector associated with the current block
+ * or macroblock
+ * pRectVOPRef - pointer to the bounding rectangle
+ * Xcoord, Ycoord - coordinates of the current block or macroblock
+ * size - size of the current block or macroblock; must be equal to 8 or
+ * 16.
+ *
+ * Output Arguments:
+ *
+ * pDstMV - pointer to the limited motion vector
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcMV, pDstMV, or pRectVOPRef.
+ * - size is not equal to either 8 or 16.
+ * - the width or height of the bounding rectangle is less than
+ * twice the block size.
+ */
+OMXResult omxVCCOMM_LimitMVToRect (
+ const OMXVCMotionVector *pSrcMV,
+ OMXVCMotionVector *pDstMV,
+ const OMXRect *pRectVOPRef,
+ OMX_INT Xcoord,
+ OMX_INT Ycoord,
+ OMX_INT size
+);
+
+
+
+/**
+ * Function: omxVCCOMM_SAD_16x (6.1.4.1.4)
+ *
+ * Description:
+ * This function calculates the SAD for 16x16 and 16x8 blocks.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to the original block; must be aligned on a 16-byte
+ * boundary.
+ * iStepOrg - Step of the original block buffer
+ * pSrcRef - Pointer to the reference block
+ * iStepRef - Step of the reference block buffer
+ * iHeight - Height of the block
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - Pointer of result SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pDstSAD, or pSrcRef
+ * - pSrcOrg is not 16-byte aligned.
+ * - iStepOrg <= 0 or iStepOrg is not a multiple of 16
+ * - iStepRef <= 0 or iStepRef is not a multiple of 16
+ * - iHeight is not 8 or 16
+ *
+ */
+OMXResult omxVCCOMM_SAD_16x (
+ const OMX_U8 *pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8 *pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCCOMM_SAD_8x (6.1.4.1.5)
+ *
+ * Description:
+ * This function calculates the SAD for 8x16, 8x8, 8x4 blocks.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to the original block; must be aligned on a 8-byte
+ * boundary.
+ * iStepOrg - Step of the original block buffer
+ * pSrcRef - Pointer to the reference block
+ * iStepRef - Step of the reference block buffer
+ * iHeight - Height of the block
+ *
+ * Output Arguments:
+ *
+ * pDstSAD -Pointer of result SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pDstSAD, or pSrcRef
+ * - pSrcOrg is not 8-byte aligned.
+ * - iStepOrg <= 0 or iStepOrg is not a multiple of 8
+ * - iStepRef <= 0 or iStepRef is not a multiple of 8
+ * - iHeight is not 4, 8 or 16
+ *
+ */
+OMXResult omxVCCOMM_SAD_8x (
+ const OMX_U8 *pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8 *pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32*pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/* 6.2.1.1 Direction */
+/* The direction enumerator is used with functions that perform AC/DC prediction and zig-zag scan. */
+
+enum {
+ OMX_VC_NONE = 0,
+ OMX_VC_HORIZONTAL = 1,
+ OMX_VC_VERTICAL = 2
+};
+
+
+
+/* 6.2.1.2 Bilinear Interpolation */
+/* The bilinear interpolation enumerator is used with motion estimation, motion compensation, and reconstruction functions. */
+
+enum {
+ OMX_VC_INTEGER_PIXEL = 0, /* case a */
+ OMX_VC_HALF_PIXEL_X = 1, /* case b */
+ OMX_VC_HALF_PIXEL_Y = 2, /* case c */
+ OMX_VC_HALF_PIXEL_XY = 3 /* case d */
+};
+
+
+
+/* 6.2.1.3 Neighboring Macroblock Availability */
+/* Neighboring macroblock availability is indicated using the following flags: */
+
+enum {
+ OMX_VC_UPPER = 1, /** above macroblock is available */
+ OMX_VC_LEFT = 2, /** left macroblock is available */
+ OMX_VC_CENTER = 4,
+ OMX_VC_RIGHT = 8,
+ OMX_VC_LOWER = 16,
+ OMX_VC_UPPER_LEFT = 32, /** above-left macroblock is available */
+ OMX_VC_UPPER_RIGHT = 64, /** above-right macroblock is available */
+ OMX_VC_LOWER_LEFT = 128,
+ OMX_VC_LOWER_RIGHT = 256
+};
+
+
+
+/* 6.2.1.4 Video Components */
+/* A data type that enumerates video components is defined as follows: */
+
+typedef enum {
+ OMX_VC_LUMINANCE, /** Luminance component */
+ OMX_VC_CHROMINANCE /** chrominance component */
+} OMXVCM4P2VideoComponent;
+
+
+
+/* 6.2.1.5 MacroblockTypes */
+/* A data type that enumerates macroblock types is defined as follows: */
+
+typedef enum {
+ OMX_VC_INTER = 0, /** P picture or P-VOP */
+ OMX_VC_INTER_Q = 1, /** P picture or P-VOP */
+ OMX_VC_INTER4V = 2, /** P picture or P-VOP */
+ OMX_VC_INTRA = 3, /** I and P picture, I- and P-VOP */
+ OMX_VC_INTRA_Q = 4, /** I and P picture, I- and P-VOP */
+ OMX_VC_INTER4V_Q = 5 /** P picture or P-VOP (H.263)*/
+} OMXVCM4P2MacroblockType;
+
+
+
+/* 6.2.1.6 Coordinates */
+/* Coordinates are represented as follows: */
+
+typedef struct {
+ OMX_INT x;
+ OMX_INT y;
+} OMXVCM4P2Coordinate;
+
+
+
+/* 6.2.1.7 Motion Estimation Algorithms */
+/* A data type that enumerates motion estimation search methods is defined as follows: */
+
+typedef enum {
+ OMX_VC_M4P2_FAST_SEARCH = 0, /** Fast motion search */
+ OMX_VC_M4P2_FULL_SEARCH = 1 /** Full motion search */
+} OMXVCM4P2MEMode;
+
+
+
+/* 6.2.1.8 Motion Estimation Parameters */
+/* A data structure containing control parameters for
+ * motion estimation functions is defined as follows:
+ */
+
+typedef struct {
+ OMX_INT searchEnable8x8; /** enables 8x8 search */
+ OMX_INT halfPelSearchEnable; /** enables half-pel resolution */
+ OMX_INT searchRange; /** search range */
+ OMX_INT rndVal; /** rounding control; 0-disabled, 1-enabled*/
+} OMXVCM4P2MEParams;
+
+
+
+/* 6.2.1.9 Macroblock Information */
+/* A data structure containing macroblock parameters for
+ * motion estimation functions is defined as follows:
+ */
+
+typedef struct {
+ OMX_S32 sliceId; /* slice number */
+ OMXVCM4P2MacroblockType mbType; /* MB type: OMX_VC_INTRA, OMX_VC_INTER, or OMX_VC_INTER4 */
+ OMX_S32 qp; /* quantization parameter*/
+ OMX_U32 cbpy; /* CBP Luma */
+ OMX_U32 cbpc; /* CBP Chroma */
+ OMXVCMotionVector pMV0[2][2]; /* motion vector, represented using 1/2-pel units,
+ * pMV0[blocky][blockx] (blocky = 0~1, blockx =0~1)
+ */
+ OMXVCMotionVector pMVPred[2][2]; /* motion vector prediction, represented using 1/2-pel units,
+ * pMVPred[blocky][blockx] (blocky = 0~1, blockx = 0~1)
+ */
+ OMX_U8 pPredDir[2][2]; /* AC prediction direction:
+ * OMX_VC_NONE, OMX_VC_VERTICAL, OMX_VC_HORIZONTAL
+ */
+} OMXVCM4P2MBInfo, *OMXVCM4P2MBInfoPtr;
+
+
+
+/**
+ * Function: omxVCM4P2_FindMVpred (6.2.3.1.1)
+ *
+ * Description:
+ * Predicts a motion vector for the current block using the procedure
+ * specified in [ISO14496-2], subclause 7.6.5. The resulting predicted MV is
+ * returned in pDstMVPred. If the parameter pDstMVPredME if is not NULL then
+ * the set of three MV candidates used for prediction is also returned,
+ * otherwise pDstMVPredMEis NULL upon return.
+ *
+ * Input Arguments:
+ *
+ * pSrcMVCurMB - pointer to the MV buffer associated with the current Y
+ * macroblock; a value of NULL indicates unavailability.
+ * pSrcCandMV1 - pointer to the MV buffer containing the 4 MVs associated
+ * with the MB located to the left of the current MB; set to NULL
+ * if there is no MB to the left.
+ * pSrcCandMV2 - pointer to the MV buffer containing the 4 MVs associated
+ * with the MB located above the current MB; set to NULL if there
+ * is no MB located above the current MB.
+ * pSrcCandMV3 - pointer to the MV buffer containing the 4 MVs associated
+ * with the MB located to the right and above the current MB; set
+ * to NULL if there is no MB located to the above-right.
+ * iBlk - the index of block in the current macroblock
+ * pDstMVPredME - MV candidate return buffer; if set to NULL then
+ * prediction candidate MVs are not returned and pDstMVPredME will
+ * be NULL upon function return; if pDstMVPredME is non-NULL then it
+ * must point to a buffer containing sufficient space for three
+ * return MVs.
+ *
+ * Output Arguments:
+ *
+ * pDstMVPred - pointer to the predicted motion vector
+ * pDstMVPredME - if non-NULL upon input then pDstMVPredME points upon
+ * return to a buffer containing the three motion vector candidates
+ * used for prediction as specified in [ISO14496-2], subclause
+ * 7.6.5, otherwise if NULL upon input then pDstMVPredME is NULL
+ * upon output.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - the pointer pDstMVPred is NULL
+ * - the parameter iBlk does not fall into the range 0 <= iBlk<=3
+ *
+ */
+OMXResult omxVCM4P2_FindMVpred (
+ const OMXVCMotionVector *pSrcMVCurMB,
+ const OMXVCMotionVector *pSrcCandMV1,
+ const OMXVCMotionVector *pSrcCandMV2,
+ const OMXVCMotionVector *pSrcCandMV3,
+ OMXVCMotionVector *pDstMVPred,
+ OMXVCMotionVector *pDstMVPredME,
+ OMX_INT iBlk
+);
+
+
+
+/**
+ * Function: omxVCM4P2_IDCT8x8blk (6.2.3.2.1)
+ *
+ * Description:
+ * Computes a 2D inverse DCT for a single 8x8 block, as defined in
+ * [ISO14496-2].
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the start of the linearly arranged IDCT input buffer;
+ * must be aligned on a 16-byte boundary. According to
+ * [ISO14496-2], the input coefficient values should lie within the
+ * range [-2048, 2047].
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the start of the linearly arranged IDCT output buffer;
+ * must be aligned on a 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - pSrc or pDst is NULL.
+ * - pSrc or pDst is not 16-byte aligned.
+ *
+ */
+OMXResult omxVCM4P2_IDCT8x8blk (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst
+);
+
+
+
+/**
+ * Function: omxVCM4P2_MEGetBufSize (6.2.4.1.1)
+ *
+ * Description:
+ * Computes the size, in bytes, of the vendor-specific specification
+ * structure for the following motion estimation functions:
+ * BlockMatch_Integer_8x8, BlockMatch_Integer_16x16, and MotionEstimationMB.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P2MEMode
+ * pMEParams - motion estimation parameters
+ *
+ * Output Arguments:
+ *
+ * pSize - pointer to the number of bytes required for the specification
+ * structure
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - one or more of the following is true:
+ * - an invalid value was specified for the parameter MEmode
+ * - a negative or zero value was specified for the
+ * parameter pMEParams->searchRange
+ *
+ */
+OMXResult omxVCM4P2_MEGetBufSize (
+ OMXVCM4P2MEMode MEmode,
+ const OMXVCM4P2MEParams *pMEParams,
+ OMX_U32 *pSize
+);
+
+
+
+/**
+ * Function: omxVCM4P2_MEInit (6.2.4.1.2)
+ *
+ * Description:
+ * Initializes the vendor-specific specification structure required for the
+ * following motion estimation functions: BlockMatch_Integer_8x8,
+ * BlockMatch_Integer_16x16, and MotionEstimationMB. Memory for the
+ * specification structure *pMESpec must be allocated prior to calling the
+ * function, and should be aligned on a 4-byte boundary. Following
+ * initialization by this function, the vendor-specific structure *pMESpec
+ * should contain an implementation-specific representation of all motion
+ * estimation parameters received via the structure pMEParams, for example
+ * rndVal, searchRange, etc. The number of bytes required for the
+ * specification structure can be determined using the function
+ * omxVCM4P2_MEGetBufSize.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P2MEMode
+ * pMEParams - motion estimation parameters
+ * pMESpec - pointer to the uninitialized ME specification structure
+ *
+ * Output Arguments:
+ *
+ * pMESpec - pointer to the initialized ME specification structure
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - one or more of the following is true:
+ * - an invalid value was specified for the parameter MEmode
+ * - a negative or zero value was specified for the
+ * parameter pMEParams->searchRange
+ *
+ */
+OMXResult omxVCM4P2_MEInit (
+ OMXVCM4P2MEMode MEmode,
+ const OMXVCM4P2MEParams*pMEParams,
+ void *pMESpec
+);
+
+
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Integer_16x16 (6.2.4.2.1)
+ *
+ * Description:
+ * Performs a 16x16 block search; estimates motion vector and associated
+ * minimum SAD. Both the input and output motion vectors are represented using
+ * half-pixel units, and therefore a shift left or right by 1 bit may be
+ * required, respectively, to match the input or output MVs with other
+ * functions that either generate output MVs or expect input MVs represented
+ * using integer pixel units.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * MB that corresponds to the location of the current macroblock in
+ * the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - pointer to the valid reference plane rectangle; coordinates
+ * are specified relative to the image origin. Rectangle
+ * boundaries may extend beyond image boundaries if the image has
+ * been padded. For example, if padding extends 4 pixels beyond
+ * frame border, then the value for the left border could be set to
+ * -4.
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 256
+ * entries); must be aligned on a 16-byte boundary. The number of
+ * bytes between lines (step) is 16.
+ * pCurrPointPos - position of the current macroblock in the current plane
+ * pSrcPreMV - pointer to predicted motion vector; NULL indicates no
+ * predicted MV
+ * pSrcPreSAD - pointer to SAD associated with the predicted MV (referenced
+ * by pSrcPreMV); may be set to NULL if unavailable.
+ * pMESpec - vendor-specific motion estimation specification structure;
+ * must have been allocated and then initialized using
+ * omxVCM4P2_MEInit prior to calling the block matching function.
+ *
+ * Output Arguments:
+ *
+ * pDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL: pSrcRefBuf,
+ * pRefRect, pSrcCurrBuff, pCurrPointPos, pDstMV, pDstSAD or
+ * pMESpec, or
+ * - pSrcCurrBuf is not 16-byte aligned
+ *
+ */
+OMXResult omxVCM4P2_BlockMatch_Integer_16x16 (
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCMotionVector*pSrcPreMV,
+ const OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector*pDstMV,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Integer_8x8 (6.2.4.2.2)
+ *
+ * Description:
+ * Performs an 8x8 block search; estimates motion vector and associated
+ * minimum SAD. Both the input and output motion vectors are represented
+ * using half-pixel units, and therefore a shift left or right by 1 bit may be
+ * required, respectively, to match the input or output MVs with other
+ * functions that either generate output MVs or expect input MVs represented
+ * using integer pixel units.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * block that corresponds to the location of the current 8x8 block
+ * in the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - pointer to the valid reference plane rectangle; coordinates
+ * are specified relative to the image origin. Rectangle
+ * boundaries may extend beyond image boundaries if the image has
+ * been padded.
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 128
+ * entries); must be aligned on an 8-byte boundary. The number of
+ * bytes between lines (step) is 16 bytes.
+ * pCurrPointPos - position of the current block in the current plane
+ * pSrcPreMV - pointer to predicted motion vector; NULL indicates no
+ * predicted MV
+ * pSrcPreSAD - pointer to SAD associated with the predicted MV (referenced
+ * by pSrcPreMV); may be set to NULL if unavailable.
+ * pMESpec - vendor-specific motion estimation specification structure;
+ * must have been allocated and then initialized using
+ * omxVCM4P2_MEInit prior to calling the block matching function.
+ *
+ * Output Arguments:
+ *
+ * pDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL: pSrcRefBuf,
+ * pRefRect, pSrcCurrBuff, pCurrPointPos, pDstMV, pDstSAD or
+ * pMESpec, or
+ * - pSrcCurrBuf is not 8-byte aligned
+ *
+ */
+OMXResult omxVCM4P2_BlockMatch_Integer_8x8 (
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCMotionVector *pSrcPreMV,
+ const OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector *pDstMV,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Half_16x16 (6.2.4.2.3)
+ *
+ * Description:
+ * Performs a 16x16 block match with half-pixel resolution. Returns the
+ * estimated motion vector and associated minimum SAD. This function
+ * estimates the half-pixel motion vector by interpolating the integer
+ * resolution motion vector referenced by the input parameter pSrcDstMV, i.e.,
+ * the initial integer MV is generated externally. The input parameters
+ * pSrcRefBuf and pSearchPointRefPos should be shifted by the winning MV of
+ * 16x16 integer search prior to calling BlockMatch_Half_16x16. The function
+ * BlockMatch_Integer_16x16 may be used for integer motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * macroblock that corresponds to the location of the current
+ * macroblock in the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - reference plane valid region rectangle
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 256
+ * entries); must be aligned on a 16-byte boundary. The number of
+ * bytes between lines (step) is 16.
+ * pSearchPointRefPos - position of the starting point for half pixel
+ * search (specified in terms of integer pixel units) in the
+ * reference plane, i.e., the reference position pointed to by the
+ * predicted motion vector.
+ * rndVal - rounding control parameter: 0 - disabled; 1 - enabled.
+ * pSrcDstMV - pointer to the initial MV estimate; typically generated
+ * during a prior 16X16 integer search; specified in terms of
+ * half-pixel units.
+ *
+ * Output Arguments:
+ *
+ * pSrcDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL: pSrcRefBuf,
+ * pRefRect, pSrcCurrBuff, pSearchPointRefPos, pSrcDstMV.
+ * - pSrcCurrBuf is not 16-byte aligned, or
+ *
+ */
+OMXResult omxVCM4P2_BlockMatch_Half_16x16 (
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pSearchPointRefPos,
+ OMX_INT rndVal,
+ OMXVCMotionVector *pSrcDstMV,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Half_8x8 (6.2.4.2.4)
+ *
+ * Description:
+ * Performs an 8x8 block match with half-pixel resolution. Returns the
+ * estimated motion vector and associated minimum SAD. This function
+ * estimates the half-pixel motion vector by interpolating the integer
+ * resolution motion vector referenced by the input parameter pSrcDstMV, i.e.,
+ * the initial integer MV is generated externally. The input parameters
+ * pSrcRefBuf and pSearchPointRefPos should be shifted by the winning MV of
+ * 8x8 integer search prior to calling BlockMatch_Half_8x8. The function
+ * BlockMatch_Integer_8x8 may be used for integer motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * block that corresponds to the location of the current 8x8 block
+ * in the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - reference plane valid region rectangle
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 128
+ * entries); must be aligned on a 8-byte boundary. The number of
+ * bytes between lines (step) is 16.
+ * pSearchPointRefPos - position of the starting point for half pixel
+ * search (specified in terms of integer pixel units) in the
+ * reference plane.
+ * rndVal - rounding control parameter: 0 - disabled; 1 - enabled.
+ * pSrcDstMV - pointer to the initial MV estimate; typically generated
+ * during a prior 8x8 integer search, specified in terms of
+ * half-pixel units.
+ *
+ * Output Arguments:
+ *
+ * pSrcDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcRefBuf, pRefRect, pSrcCurrBuff, pSearchPointRefPos, pSrcDstMV
+ * - pSrcCurrBuf is not 8-byte aligned
+ *
+ */
+OMXResult omxVCM4P2_BlockMatch_Half_8x8 (
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pSearchPointRefPos,
+ OMX_INT rndVal,
+ OMXVCMotionVector *pSrcDstMV,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_MotionEstimationMB (6.2.4.3.1)
+ *
+ * Description:
+ * Performs motion search for a 16x16 macroblock. Selects best motion search
+ * strategy from among inter-1MV, inter-4MV, and intra modes. Supports
+ * integer and half pixel resolution.
+ *
+ * Input Arguments:
+ *
+ * pSrcCurrBuf - pointer to the top-left corner of the current MB in the
+ * original picture plane; must be aligned on a 16-byte boundary.
+ * The function does not expect source data outside the region
+ * bounded by the MB to be available; for example it is not
+ * necessary for the caller to guarantee the availability of
+ * pSrcCurrBuf[-SrcCurrStep], i.e., the row of pixels above the MB
+ * to be processed.
+ * srcCurrStep - width of the original picture plane, in terms of full
+ * pixels; must be a multiple of 16.
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * plane location corresponding to the location of the current
+ * macroblock in the current plane; must be aligned on a 16-byte
+ * boundary.
+ * srcRefStep - width of the reference picture plane, in terms of full
+ * pixels; must be a multiple of 16.
+ * pRefRect - reference plane valid region rectangle, specified relative to
+ * the image origin
+ * pCurrPointPos - position of the current macroblock in the current plane
+ * pMESpec - pointer to the vendor-specific motion estimation specification
+ * structure; must be allocated and then initialized using
+ * omxVCM4P2_MEInit prior to calling this function.
+ * pMBInfo - array, of dimension four, containing pointers to information
+ * associated with four nearby MBs:
+ * - pMBInfo[0] - pointer to left MB information
+ * - pMBInfo[1] - pointer to top MB information
+ * - pMBInfo[2] - pointer to top-left MB information
+ * - pMBInfo[3] - pointer to top-right MB information
+ * Any pointer in the array may be set equal to NULL if the
+ * corresponding MB doesn't exist. For each MB, the following structure
+ * members are used:
+ * - mbType - macroblock type, either OMX_VC_INTRA, OMX_VC_INTER, or
+ * OMX_VC_INTER4V
+ * - pMV0[2][2] - estimated motion vectors; represented
+ * in 1/2 pixel units
+ * - sliceID - number of the slice to which the MB belongs
+ * pSrcDstMBCurr - pointer to information structure for the current MB.
+ * The following entries should be set prior to calling the
+ * function: sliceID - the number of the slice the to which the
+ * current MB belongs. The structure elements cbpy and cbpc are
+ * ignored.
+ *
+ * Output Arguments:
+ *
+ * pSrcDstMBCurr - pointer to updated information structure for the current
+ * MB after MB-level motion estimation has been completed. The
+ * following structure members are updated by the ME function:
+ * - mbType - macroblock type: OMX_VC_INTRA, OMX_VC_INTER, or
+ * OMX_VC_INTER4V.
+ * - pMV0[2][2] - estimated motion vectors; represented in
+ * terms of 1/2 pel units.
+ * - pMVPred[2][2] - predicted motion vectors; represented
+ * in terms of 1/2 pel units.
+ * The structure members cbpy and cbpc are not updated by the function.
+ * pDstSAD - pointer to the minimum SAD for INTER1V, or sum of minimum SADs
+ * for INTER4V
+ * pDstBlockSAD - pointer to an array of SAD values for each of the four
+ * 8x8 luma blocks in the MB. The block SADs are in scan order for
+ * each MB.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL: pSrcCurrBuf,
+ * pSrcRefBuf, pRefRect, pCurrPointPos, pMBInter, pMBIntra,
+ * pSrcDstMBCurr, or pDstSAD.
+ *
+ */
+OMXResult omxVCM4P2_MotionEstimationMB (
+ const OMX_U8 *pSrcCurrBuf,
+ OMX_S32 srcCurrStep,
+ const OMX_U8 *pSrcRefBuf,
+ OMX_S32 srcRefStep,
+ const OMXRect*pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ void *pMESpec,
+ const OMXVCM4P2MBInfoPtr *pMBInfo,
+ OMXVCM4P2MBInfo *pSrcDstMBCurr,
+ OMX_U16 *pDstSAD,
+ OMX_U16 *pDstBlockSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DCT8x8blk (6.2.4.4.1)
+ *
+ * Description:
+ * Computes a 2D forward DCT for a single 8x8 block, as defined in
+ * [ISO14496-2].
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the start of the linearly arranged input buffer; must
+ * be aligned on a 16-byte boundary. Input values (pixel
+ * intensities) are valid in the range [-255,255].
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the start of the linearly arranged output buffer; must
+ * be aligned on a 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, returned if:
+ * - pSrc or pDst is NULL.
+ * - pSrc or pDst is not 16-byte aligned.
+ *
+ */
+OMXResult omxVCM4P2_DCT8x8blk (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst
+);
+
+
+
+/**
+ * Function: omxVCM4P2_QuantIntra_I (6.2.4.4.2)
+ *
+ * Description:
+ * Performs quantization on intra block coefficients. This function supports
+ * bits_per_pixel == 8.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input intra block coefficients; must be aligned
+ * on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale).
+ * blockIndex - block index indicating the component type and position,
+ * valid in the range 0 to 5, as defined in [ISO14496-2], subclause
+ * 6.1.3.8.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (quantized) interblock coefficients.
+ * When shortVideoHeader==1, AC coefficients are saturated on the
+ * interval [-127, 127], and DC coefficients are saturated on the
+ * interval [1, 254]. When shortVideoHeader==0, AC coefficients
+ * are saturated on the interval [-2047, 2047].
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - pSrcDst is NULL.
+ * - blockIndex < 0 or blockIndex >= 10
+ * - QP <= 0 or QP >= 32.
+ *
+ */
+OMXResult omxVCM4P2_QuantIntra_I (
+ OMX_S16 *pSrcDst,
+ OMX_U8 QP,
+ OMX_INT blockIndex,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_QuantInter_I (6.2.4.4.3)
+ *
+ * Description:
+ * Performs quantization on an inter coefficient block; supports
+ * bits_per_pixel == 8.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input inter block coefficients; must be aligned
+ * on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale)
+ * shortVideoHeader - binary flag indicating presence of short_video_header;
+ * shortVideoHeader==1 selects linear intra DC mode, and
+ * shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (quantized) interblock coefficients.
+ * When shortVideoHeader==1, AC coefficients are saturated on the
+ * interval [-127, 127], and DC coefficients are saturated on the
+ * interval [1, 254]. When shortVideoHeader==0, AC coefficients
+ * are saturated on the interval [-2047, 2047].
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - pSrcDst is NULL.
+ * - QP <= 0 or QP >= 32.
+ *
+ */
+OMXResult omxVCM4P2_QuantInter_I (
+ OMX_S16 *pSrcDst,
+ OMX_U8 QP,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_TransRecBlockCoef_intra (6.2.4.4.4)
+ *
+ * Description:
+ * Quantizes the DCT coefficients, implements intra block AC/DC coefficient
+ * prediction, and reconstructs the current intra block texture for prediction
+ * on the next frame. Quantized row and column coefficients are returned in
+ * the updated coefficient buffers.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the pixels of current intra block; must be aligned on
+ * an 8-byte boundary.
+ * pPredBufRow - pointer to the coefficient row buffer containing
+ * ((num_mb_per_row * 2 + 1) * 8) elements of type OMX_S16.
+ * Coefficients are organized into blocks of eight as described
+ * below (Internal Prediction Coefficient Update Procedures). The
+ * DC coefficient is first, and the remaining buffer locations
+ * contain the quantized AC coefficients. Each group of eight row
+ * buffer elements combined with one element eight elements ahead
+ * contains the coefficient predictors of the neighboring block
+ * that is spatially above or to the left of the block currently to
+ * be decoded. A negative-valued DC coefficient indicates that this
+ * neighboring block is not INTRA-coded or out of bounds, and
+ * therefore the AC and DC coefficients are invalid. Pointer must
+ * be aligned on an 8-byte boundary.
+ * pPredBufCol - pointer to the prediction coefficient column buffer
+ * containing 16 elements of type OMX_S16. Coefficients are
+ * organized as described in section 6.2.2.5. Pointer must be
+ * aligned on an 8-byte boundary.
+ * pSumErr - pointer to a flag indicating whether or not AC prediction is
+ * required; AC prediction is enabled if *pSumErr >=0, but the
+ * value is not used for coefficient prediction, i.e., the sum of
+ * absolute differences starts from 0 for each call to this
+ * function. Otherwise AC prediction is disabled if *pSumErr < 0 .
+ * blockIndex - block index indicating the component type and position, as
+ * defined in [ISO14496-2], subclause 6.1.3.8.
+ * curQp - quantization parameter of the macroblock to which the current
+ * block belongs
+ * pQpBuf - pointer to a 2-element quantization parameter buffer; pQpBuf[0]
+ * contains the quantization parameter associated with the 8x8
+ * block left of the current block (QPa), and pQpBuf[1] contains
+ * the quantization parameter associated with the 8x8 block above
+ * the current block (QPc). In the event that the corresponding
+ * block is outside of the VOP bound, the Qp value will not affect
+ * the intra prediction process, as described in [ISO14496-2],
+ * sub-clause 7.4.3.3, Adaptive AC Coefficient Prediction.
+ * srcStep - width of the source buffer; must be a multiple of 8.
+ * dstStep - width of the reconstructed destination buffer; must be a
+ * multiple of 16.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the quantized DCT coefficient buffer; pDst[0] contains
+ * the predicted DC coefficient; the remaining entries contain the
+ * quantized AC coefficients (without prediction). The pointer
+ * pDstmust be aligned on a 16-byte boundary.
+ * pRec - pointer to the reconstructed texture; must be aligned on an
+ * 8-byte boundary.
+ * pPredBufRow - pointer to the updated coefficient row buffer
+ * pPredBufCol - pointer to the updated coefficient column buffer
+ * pPreACPredict - if prediction is enabled, the parameter points to the
+ * start of the buffer containing the coefficient differences for
+ * VLC encoding. The entry pPreACPredict[0]indicates prediction
+ * direction for the current block and takes one of the following
+ * values: OMX_VC_NONE (prediction disabled), OMX_VC_HORIZONTAL, or
+ * OMX_VC_VERTICAL. The entries
+ * pPreACPredict[1]-pPreACPredict[7]contain predicted AC
+ * coefficients. If prediction is disabled (*pSumErr<0) then the
+ * contents of this buffer are undefined upon return from the
+ * function
+ * pSumErr - pointer to the value of the accumulated AC coefficient errors,
+ * i.e., sum of the absolute differences between predicted and
+ * unpredicted AC coefficients
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ * - At least one of the following pointers is NULL: pSrc, pDst, pRec,
+ * pCoefBufRow, pCoefBufCol, pQpBuf, pPreACPredict, pSumErr.
+ * - blockIndex < 0 or blockIndex >= 10;
+ * - curQP <= 0 or curQP >= 32.
+ * - srcStep, or dstStep <= 0 or not a multiple of 8.
+ * - pDst is not 16-byte aligned: .
+ * - At least one of the following pointers is not 8-byte aligned:
+ * pSrc, pRec.
+ *
+ * Note: The coefficient buffers must be updated in accordance with the
+ * update procedures defined in section in 6.2.2.
+ *
+ */
+OMXResult omxVCM4P2_TransRecBlockCoef_intra (
+ const OMX_U8 *pSrc,
+ OMX_S16 *pDst,
+ OMX_U8 *pRec,
+ OMX_S16 *pPredBufRow,
+ OMX_S16 *pPredBufCol,
+ OMX_S16 *pPreACPredict,
+ OMX_INT *pSumErr,
+ OMX_INT blockIndex,
+ OMX_U8 curQp,
+ const OMX_U8 *pQpBuf,
+ OMX_INT srcStep,
+ OMX_INT dstStep,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_TransRecBlockCoef_inter (6.2.4.4.5)
+ *
+ * Description:
+ * Implements DCT, and quantizes the DCT coefficients of the inter block
+ * while reconstructing the texture residual. There is no boundary check for
+ * the bit stream buffer.
+ *
+ * Input Arguments:
+ *
+ * pSrc -pointer to the residuals to be encoded; must be aligned on an
+ * 16-byte boundary.
+ * QP - quantization parameter.
+ * shortVideoHeader - binary flag indicating presence of short_video_header;
+ * shortVideoHeader==1 selects linear intra DC mode, and
+ * shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the quantized DCT coefficients buffer; must be aligned
+ * on a 16-byte boundary.
+ * pRec - pointer to the reconstructed texture residuals; must be aligned
+ * on a 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is either NULL or
+ * not 16-byte aligned:
+ * - pSrc
+ * - pDst
+ * - pRec
+ * - QP <= 0 or QP >= 32.
+ *
+ */
+OMXResult omxVCM4P2_TransRecBlockCoef_inter (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst,
+ OMX_S16 *pRec,
+ OMX_U8 QP,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeVLCZigzag_IntraDCVLC (6.2.4.5.2)
+ *
+ * Description:
+ * Performs zigzag scan and VLC encoding of AC and DC coefficients for one
+ * intra block. Two versions of the function (DCVLC and ACVLC) are provided
+ * in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, "Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding".
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the bitstream
+ * pBitOffset - pointer to the bit position in the byte pointed by
+ * *ppBitStream. Valid within 0 to 7.
+ * pQDctBlkCoef - pointer to the quantized DCT coefficient
+ * predDir - AC prediction direction, which is used to decide the zigzag
+ * scan pattern; takes one of the following values:
+ * - OMX_VC_NONE - AC prediction not used.
+ * Performs classical zigzag scan.
+ * - OMX_VC_HORIZONTAL - Horizontal prediction.
+ * Performs alternate-vertical zigzag scan.
+ * - OMX_VC_VERTICAL - Vertical prediction.
+ * Performs alternate-horizontal zigzag scan.
+ * pattern - block pattern which is used to decide whether this block is
+ * encoded
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ * videoComp - video component type (luminance, chrominance) of the current
+ * block
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is encoded, so
+ * that it points to the current byte in the bit stream buffer.
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ * - At least one of the following pointers is NULL: ppBitStream,
+ * *ppBitStream, pBitOffset, pQDctBlkCoef.
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ * - PredDir is not one of: OMX_VC_NONE, OMX_VC_HORIZONTAL, or
+ * OMX_VC_VERTICAL.
+ * - VideoComp is not one component of enum OMXVCM4P2VideoComponent.
+ *
+ */
+OMXResult omxVCM4P2_EncodeVLCZigzag_IntraDCVLC (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 predDir,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader,
+ OMXVCM4P2VideoComponent videoComp
+);
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeVLCZigzag_IntraACVLC (6.2.4.5.2)
+ *
+ * Description:
+ * Performs zigzag scan and VLC encoding of AC and DC coefficients for one
+ * intra block. Two versions of the function (DCVLC and ACVLC) are provided
+ * in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the bitstream
+ * pBitOffset - pointer to the bit position in the byte pointed by
+ * *ppBitStream. Valid within 0 to 7.
+ * pQDctBlkCoef - pointer to the quantized DCT coefficient
+ * predDir - AC prediction direction, which is used to decide the zigzag
+ * scan pattern; takes one of the following values:
+ * - OMX_VC_NONE - AC prediction not used.
+ * Performs classical zigzag scan.
+ * - OMX_VC_HORIZONTAL - Horizontal prediction.
+ * Performs alternate-vertical zigzag scan.
+ * - OMX_VC_VERTICAL - Vertical prediction.
+ * Performs alternate-horizontal zigzag scan.
+ * pattern - block pattern which is used to decide whether this block is
+ * encoded
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is encoded, so
+ * that it points to the current byte in the bit stream buffer.
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ * - At least one of the following pointers is NULL: ppBitStream,
+ * *ppBitStream, pBitOffset, pQDctBlkCoef.
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ * - PredDir is not one of: OMX_VC_NONE, OMX_VC_HORIZONTAL, or
+ * OMX_VC_VERTICAL.
+ * - VideoComp is not one component of enum OMXVCM4P2VideoComponent.
+ *
+ */
+OMXResult omxVCM4P2_EncodeVLCZigzag_IntraACVLC (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 predDir,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeVLCZigzag_Inter (6.2.4.5.3)
+ *
+ * Description:
+ * Performs classical zigzag scanning and VLC encoding for one inter block.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream
+ * pBitOffset - pointer to the bit position in the byte pointed by
+ * *ppBitStream. Valid within 0 to 7
+ * pQDctBlkCoef - pointer to the quantized DCT coefficient
+ * pattern - block pattern which is used to decide whether this block is
+ * encoded
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is encoded so that
+ * it points to the current byte in the bit stream buffer.
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments
+ * - At least one of the pointers: is NULL: ppBitStream, *ppBitStream,
+ * pBitOffset, pQDctBlkCoef
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ *
+ */
+OMXResult omxVCM4P2_EncodeVLCZigzag_Inter (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeMV (6.2.4.5.4)
+ *
+ * Description:
+ * Predicts a motion vector for the current macroblock, encodes the
+ * difference, and writes the output to the stream buffer. The input MVs
+ * pMVCurMB, pSrcMVLeftMB, pSrcMVUpperMB, and pSrcMVUpperRightMB should lie
+ * within the ranges associated with the input parameter fcodeForward, as
+ * described in [ISO14496-2], subclause 7.6.3. This function provides a
+ * superset of the functionality associated with the function
+ * omxVCM4P2_FindMVpred.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the bitstream buffer
+ * pBitOffset - index of the first free (next available) bit in the stream
+ * buffer referenced by *ppBitStream, valid in the range 0 to 7.
+ * pMVCurMB - pointer to the current macroblock motion vector; a value of
+ * NULL indicates unavailability.
+ * pSrcMVLeftMB - pointer to the source left macroblock motion vector; a
+ * value of NULLindicates unavailability.
+ * pSrcMVUpperMB - pointer to source upper macroblock motion vector; a
+ * value of NULL indicates unavailability.
+ * pSrcMVUpperRightMB - pointer to source upper right MB motion vector; a
+ * value of NULL indicates unavailability.
+ * fcodeForward - an integer with values from 1 to 7; used in encoding
+ * motion vectors related to search range, as described in
+ * [ISO14496-2], subclause 7.6.3.
+ * MBType - macro block type, valid in the range 0 to 5
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - updated pointer to the current byte in the bit stream
+ * buffer
+ * pBitOffset - updated index of the next available bit position in stream
+ * buffer referenced by *ppBitStream
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - At least one of the following pointers is NULL: ppBitStream,
+ * *ppBitStream, pBitOffset, pMVCurMB
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ * - fcodeForward <= 0, or fcodeForward > 7, or MBType < 0.
+ *
+ */
+OMXResult omxVCM4P2_EncodeMV (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMXVCMotionVector *pMVCurMB,
+ const OMXVCMotionVector*pSrcMVLeftMB,
+ const OMXVCMotionVector *pSrcMVUpperMB,
+ const OMXVCMotionVector *pSrcMVUpperRightMB,
+ OMX_INT fcodeForward,
+ OMXVCM4P2MacroblockType MBType
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodePadMV_PVOP (6.2.5.1.1)
+ *
+ * Description:
+ * Decodes and pads the four motion vectors associated with a non-intra P-VOP
+ * macroblock. For macroblocks of type OMX_VC_INTER4V, the output MV is
+ * padded as specified in [ISO14496-2], subclause 7.6.1.6. Otherwise, for
+ * macroblocks of types other than OMX_VC_INTER4V, the decoded MV is copied to
+ * all four output MV buffer entries.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream buffer
+ * pBitOffset - pointer to the bit position in the byte pointed to by
+ * *ppBitStream. *pBitOffset is valid within [0-7].
+ * pSrcMVLeftMB, pSrcMVUpperMB, and pSrcMVUpperRightMB - pointers to the
+ * motion vector buffers of the macroblocks specially at the left,
+ * upper, and upper-right side of the current macroblock,
+ * respectively; a value of NULL indicates unavailability. Note:
+ * Any neighborhood macroblock outside the current VOP or video
+ * packet or outside the current GOB (when short_video_header is
+ * 1 ) for which gob_header_empty is 0 is treated as
+ * transparent, according to [ISO14496-2], subclause 7.6.5.
+ * fcodeForward - a code equal to vop_fcode_forward in MPEG-4 bit stream
+ * syntax
+ * MBType - the type of the current macroblock. If MBType is not equal to
+ * OMX_VC_INTER4V, the destination motion vector buffer is still
+ * filled with the same decoded vector.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded, so
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream
+ * pDstMVCurMB - pointer to the motion vector buffer for the current
+ * macroblock; contains four decoded motion vectors
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pDstMVCurMB
+ * - *pBitOffset exceeds [0,7]
+ * - fcodeForward exceeds (0,7]
+ * - MBType less than zero
+ * - motion vector buffer is not 4-byte aligned.
+ * OMX_Sts_Err - status error
+ *
+ */
+OMXResult omxVCM4P2_DecodePadMV_PVOP (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMXVCMotionVector *pSrcMVLeftMB,
+ OMXVCMotionVector*pSrcMVUpperMB,
+ OMXVCMotionVector *pSrcMVUpperRightMB,
+ OMXVCMotionVector*pDstMVCurMB,
+ OMX_INT fcodeForward,
+ OMXVCM4P2MacroblockType MBType
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeVLCZigzag_IntraDCVLC (6.2.5.2.2)
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan of AC and DC coefficients
+ * for one intra block. Two versions of the function (DCVLC and ACVLC) are
+ * provided in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the
+ * bitstream buffer
+ * pBitOffset - pointer to the bit position in the current byte referenced
+ * by *ppBitStream. The parameter *pBitOffset is valid in the
+ * range [0-7].
+ * Bit Position in one byte: |Most Least|
+ * *pBitOffset |0 1 2 3 4 5 6 7|
+ * predDir - AC prediction direction; used to select the zigzag scan
+ * pattern; takes one of the following values:
+ * - OMX_VC_NONE - AC prediction not used;
+ * performs classical zigzag scan.
+ * - OMX_VC_HORIZONTAL - Horizontal prediction;
+ * performs alternate-vertical zigzag scan;
+ * - OMX_VC_VERTICAL - Vertical prediction;
+ * performs alternate-horizontal zigzag scan.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ * videoComp - video component type (luminance or chrominance) of the
+ * current block
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded such
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated such that it points to the current
+ * bit position in the byte pointed by *ppBitStream
+ * pDst - pointer to the coefficient buffer of current block; must be
+ * 4-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pDst
+ * - *pBitOffset exceeds [0,7]
+ * - preDir exceeds [0,2]
+ * - pDst is not 4-byte aligned
+ * OMX_Sts_Err - if:
+ * - In DecodeVLCZigzag_IntraDCVLC, dc_size > 12
+ * - At least one of mark bits equals zero
+ * - Illegal stream encountered; code cannot be located in VLC table
+ * - Forbidden code encountered in the VLC FLC table.
+ * - The number of coefficients is greater than 64
+ *
+ */
+OMXResult omxVCM4P2_DecodeVLCZigzag_IntraDCVLC (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_S16 *pDst,
+ OMX_U8 predDir,
+ OMX_INT shortVideoHeader,
+ OMXVCM4P2VideoComponent videoComp
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeVLCZigzag_IntraACVLC (6.2.5.2.2)
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan of AC and DC coefficients
+ * for one intra block. Two versions of the function (DCVLC and ACVLC) are
+ * provided in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the
+ * bitstream buffer
+ * pBitOffset - pointer to the bit position in the current byte referenced
+ * by *ppBitStream. The parameter *pBitOffset is valid in the
+ * range [0-7]. Bit Position in one byte: |Most Least| *pBitOffset
+ * |0 1 2 3 4 5 6 7|
+ * predDir - AC prediction direction; used to select the zigzag scan
+ * pattern; takes one of the following values: OMX_VC_NONE - AC
+ * prediction not used; performs classical zigzag scan.
+ * OMX_VC_HORIZONTAL - Horizontal prediction; performs
+ * alternate-vertical zigzag scan; OMX_VC_VERTICAL - Vertical
+ * prediction; performs alternate-horizontal zigzag scan.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ * videoComp - video component type (luminance or chrominance) of the
+ * current block
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded such
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated such that it points to the current
+ * bit position in the byte pointed by *ppBitStream
+ * pDst - pointer to the coefficient buffer of current block; must be
+ * 4-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments At least one of the following
+ * pointers is NULL: ppBitStream, *ppBitStream, pBitOffset, pDst,
+ * or At least one of the following conditions is true:
+ * *pBitOffset exceeds [0,7], preDir exceeds [0,2], or pDst is
+ * not 4-byte aligned
+ * OMX_Sts_Err In DecodeVLCZigzag_IntraDCVLC, dc_size > 12 At least one of
+ * mark bits equals zero Illegal stream encountered; code cannot
+ * be located in VLC table Forbidden code encountered in the VLC
+ * FLC table The number of coefficients is greater than 64
+ *
+ */
+OMXResult omxVCM4P2_DecodeVLCZigzag_IntraACVLC (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_S16 *pDst,
+ OMX_U8 predDir,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeVLCZigzag_Inter (6.2.5.2.3)
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan for one inter-coded block.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the stream buffer
+ * pBitOffset - pointer to the next available bit in the current stream
+ * byte referenced by *ppBitStream. The parameter *pBitOffset is
+ * valid within the range [0-7].
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded such
+ * that it points to the current byte in the stream buffer
+ * pBitOffset - *pBitOffset is updated after decoding such that it points
+ * to the next available bit in the stream byte referenced by
+ * *ppBitStream
+ * pDst - pointer to the coefficient buffer of current block; must be
+ * 4-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pDst
+ * - pDst is not 4-byte aligned
+ * - *pBitOffset exceeds [0,7]
+ * OMX_Sts_Err - status error, if:
+ * - At least one mark bit is equal to zero
+ * - Encountered an illegal stream code that cannot be found in the VLC table
+ * - Encountered an illegal code in the VLC FLC table
+ * - The number of coefficients is greater than 64
+ *
+ */
+OMXResult omxVCM4P2_DecodeVLCZigzag_Inter (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_S16 *pDst,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_QuantInvIntra_I (6.2.5.3.2)
+ *
+ * Description:
+ * Performs the second inverse quantization mode on an intra/inter coded
+ * block. Supports bits_per_pixel = 8. The output coefficients are clipped to
+ * the range [-2048, 2047].
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input (quantized) intra/inter block; must be
+ * aligned on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale)
+ * videoComp - video component type of the current block. Takes one of the
+ * following flags: OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE (intra
+ * version only).
+ * shortVideoHeader - binary flag indicating presence of short_video_header
+ * (intra version only).
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (dequantized) intra/inter block
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; one or more of the following is
+ * true:
+ * - pSrcDst is NULL
+ * - QP <= 0 or QP >=31
+ * - videoComp is neither OMX_VC_LUMINANCE nor OMX_VC_CHROMINANCE.
+ *
+ */
+OMXResult omxVCM4P2_QuantInvIntra_I (
+ OMX_S16 *pSrcDst,
+ OMX_INT QP,
+ OMXVCM4P2VideoComponent videoComp,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_QuantInvInter_I (6.2.5.3.2)
+ *
+ * Description:
+ * Performs the second inverse quantization mode on an intra/inter coded
+ * block. Supports bits_per_pixel = 8. The output coefficients are clipped to
+ * the range [-2048, 2047].
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input (quantized) intra/inter block; must be
+ * aligned on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale)
+ * videoComp - video component type of the current block. Takes one of the
+ * following flags: OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE (intra
+ * version only).
+ * shortVideoHeader - binary flag indicating presence of short_video_header
+ * (intra version only).
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (dequantized) intra/inter block
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; one or more of the following is
+ * true:
+ * - pSrcDst is NULL
+ * - QP <= 0 or QP >=31
+ * - videoComp is neither OMX_VC_LUMINANCE nor OMX_VC_CHROMINANCE.
+ *
+ */
+OMXResult omxVCM4P2_QuantInvInter_I (
+ OMX_S16 *pSrcDst,
+ OMX_INT QP
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeBlockCoef_Intra (6.2.5.4.1)
+ *
+ * Description:
+ * Decodes the INTRA block coefficients. Inverse quantization, inversely
+ * zigzag positioning, and IDCT, with appropriate clipping on each step, are
+ * performed on the coefficients. The results are then placed in the output
+ * frame/plane on a pixel basis. Note: This function will be used only when
+ * at least one non-zero AC coefficient of current block exists in the bit
+ * stream. The DC only condition will be handled in another function.
+ *
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream buffer. There is no boundary check for the bit stream
+ * buffer.
+ * pBitOffset - pointer to the bit position in the byte pointed to by
+ * *ppBitStream. *pBitOffset is valid within [0-7].
+ * step - width of the destination plane
+ * pCoefBufRow - pointer to the coefficient row buffer; must be aligned on
+ * an 8-byte boundary.
+ * pCoefBufCol - pointer to the coefficient column buffer; must be aligned
+ * on an 8-byte boundary.
+ * curQP - quantization parameter of the macroblock which the current block
+ * belongs to
+ * pQPBuf - pointer to the quantization parameter buffer
+ * blockIndex - block index indicating the component type and position as
+ * defined in [ISO14496-2], subclause 6.1.3.8, Figure 6-5.
+ * intraDCVLC - a code determined by intra_dc_vlc_thr and QP. This allows a
+ * mechanism to switch between two VLC for coding of Intra DC
+ * coefficients as per [ISO14496-2], Table 6-21.
+ * ACPredFlag - a flag equal to ac_pred_flag (of luminance) indicating if
+ * the ac coefficients of the first row or first column are
+ * differentially coded for intra coded macroblock.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded, so
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream
+ * pDst - pointer to the block in the destination plane; must be aligned on
+ * an 8-byte boundary.
+ * pCoefBufRow - pointer to the updated coefficient row buffer.
+ * pCoefBufCol - pointer to the updated coefficient column buffer Note:
+ * The coefficient buffers must be updated in accordance with the
+ * update procedure defined in section 6.2.2.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pCoefBufRow, pCoefBufCol,
+ * pQPBuf, pDst.
+ * - *pBitOffset exceeds [0,7]
+ * - curQP exceeds (1, 31)
+ * - blockIndex exceeds [0,5]
+ * - step is not the multiple of 8
+ * - a pointer alignment requirement was violated.
+ * OMX_Sts_Err - status error. Refer to OMX_Sts_Err of DecodeVLCZigzag_Intra.
+ *
+ */
+OMXResult omxVCM4P2_DecodeBlockCoef_Intra (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_U8 *pDst,
+ OMX_INT step,
+ OMX_S16 *pCoefBufRow,
+ OMX_S16 *pCoefBufCol,
+ OMX_U8 curQP,
+ const OMX_U8 *pQPBuf,
+ OMX_INT blockIndex,
+ OMX_INT intraDCVLC,
+ OMX_INT ACPredFlag,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeBlockCoef_Inter (6.2.5.4.2)
+ *
+ * Description:
+ * Decodes the INTER block coefficients. This function performs inverse
+ * quantization, inverse zigzag positioning, and IDCT (with appropriate
+ * clipping on each step) on the coefficients. The results (residuals) are
+ * placed in a contiguous array of 64 elements. For INTER block, the output
+ * buffer holds the residuals for further reconstruction.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream buffer. There is no boundary check for the bit stream
+ * buffer.
+ * pBitOffset - pointer to the bit position in the byte pointed to by
+ * *ppBitStream. *pBitOffset is valid within [0-7]
+ * QP - quantization parameter
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded, so
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream
+ * pDst - pointer to the decoded residual buffer (a contiguous array of 64
+ * elements of OMX_S16 data type); must be aligned on a 16-byte
+ * boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the following pointers is Null:
+ * ppBitStream, *ppBitStream, pBitOffset , pDst
+ * - *pBitOffset exceeds [0,7]
+ * - QP <= 0.
+ * - pDst is not 16-byte aligned
+ * OMX_Sts_Err - status error. Refer to OMX_Sts_Err of DecodeVLCZigzag_Inter .
+ *
+ */
+OMXResult omxVCM4P2_DecodeBlockCoef_Inter (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_S16 *pDst,
+ OMX_INT QP,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_PredictReconCoefIntra (6.2.5.4.3)
+ *
+ * Description:
+ * Performs adaptive DC/AC coefficient prediction for an intra block. Prior
+ * to the function call, prediction direction (predDir) should be selected as
+ * specified in [ISO14496-2], subclause 7.4.3.1.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the coefficient buffer which contains the quantized
+ * coefficient residuals (PQF) of the current block; must be
+ * aligned on a 4-byte boundary. The output coefficients are
+ * saturated to the range [-2048, 2047].
+ * pPredBufRow - pointer to the coefficient row buffer; must be aligned on
+ * a 4-byte boundary.
+ * pPredBufCol - pointer to the coefficient column buffer; must be aligned
+ * on a 4-byte boundary.
+ * curQP - quantization parameter of the current block. curQP may equal to
+ * predQP especially when the current block and the predictor block
+ * are in the same macroblock.
+ * predQP - quantization parameter of the predictor block
+ * predDir - indicates the prediction direction which takes one of the
+ * following values: OMX_VC_HORIZONTAL - predict horizontally
+ * OMX_VC_VERTICAL - predict vertically
+ * ACPredFlag - a flag indicating if AC prediction should be performed. It
+ * is equal to ac_pred_flag in the bit stream syntax of MPEG-4
+ * videoComp - video component type (luminance or chrominance) of the
+ * current block
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the coefficient buffer which contains the quantized
+ * coefficients (QF) of the current block
+ * pPredBufRow - pointer to the updated coefficient row buffer
+ * pPredBufCol - pointer to the updated coefficient column buffer Note:
+ * Buffer update: Update the AC prediction buffer (both row and
+ * column buffer).
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the pointers is NULL:
+ * pSrcDst, pPredBufRow, or pPredBufCol.
+ * - curQP <= 0,
+ * - predQP <= 0,
+ * - curQP >31,
+ * - predQP > 31,
+ * - preDir exceeds [1,2]
+ * - pSrcDst, pPredBufRow, or pPredBufCol is not 4-byte aligned.
+ *
+ */
+OMXResult omxVCM4P2_PredictReconCoefIntra (
+ OMX_S16 *pSrcDst,
+ OMX_S16 *pPredBufRow,
+ OMX_S16 *pPredBufCol,
+ OMX_INT curQP,
+ OMX_INT predQP,
+ OMX_INT predDir,
+ OMX_INT ACPredFlag,
+ OMXVCM4P2VideoComponent videoComp
+);
+
+
+
+/**
+ * Function: omxVCM4P2_MCReconBlock (6.2.5.5.1)
+ *
+ * Description:
+ * Performs motion compensation prediction for an 8x8 block using
+ * interpolation described in [ISO14496-2], subclause 7.6.2.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the block in the reference plane.
+ * srcStep - distance between the start of consecutive lines in the
+ * reference plane, in bytes; must be a multiple of 8.
+ * dstStep - distance between the start of consecutive lines in the
+ * destination plane, in bytes; must be a multiple of 8.
+ * pSrcResidue - pointer to a buffer containing the 16-bit prediction
+ * residuals; must be 16-byte aligned. If the pointer is NULL, then
+ * no prediction is done, only motion compensation, i.e., the block
+ * is moved with interpolation.
+ * predictType - bilinear interpolation type, as defined in section
+ * 6.2.1.2.
+ * rndVal - rounding control parameter: 0 - disabled; 1 - enabled.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination buffer; must be 8-byte aligned. If
+ * prediction residuals are added then output intensities are
+ * clipped to the range [0,255].
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - pDst is not 8-byte aligned.
+ * - pSrcResidue is not 16-byte aligned.
+ * - one or more of the following pointers is NULL: pSrc or pDst.
+ * - either srcStep or dstStep is not a multiple of 8.
+ * - invalid type specified for the parameter predictType.
+ * - the parameter rndVal is not equal either to 0 or 1.
+ *
+ */
+OMXResult omxVCM4P2_MCReconBlock (
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ const OMX_S16 *pSrcResidue,
+ OMX_U8 *pDst,
+ OMX_INT dstStep,
+ OMX_INT predictType,
+ OMX_INT rndVal
+);
+
+
+
+/* 6.3.1.1 Intra 16x16 Prediction Modes */
+/* A data type that enumerates intra_16x16 macroblock prediction modes is defined as follows: */
+
+typedef enum {
+ OMX_VC_16X16_VERT = 0, /** Intra_16x16_Vertical */
+ OMX_VC_16X16_HOR = 1, /** Intra_16x16_Horizontal */
+ OMX_VC_16X16_DC = 2, /** Intra_16x16_DC */
+ OMX_VC_16X16_PLANE = 3 /** Intra_16x16_Plane */
+} OMXVCM4P10Intra16x16PredMode;
+
+
+
+/* 6.3.1.2 Intra 4x4 Prediction Modes */
+/* A data type that enumerates intra_4x4 macroblock prediction modes is defined as follows: */
+
+typedef enum {
+ OMX_VC_4X4_VERT = 0, /** Intra_4x4_Vertical */
+ OMX_VC_4X4_HOR = 1, /** Intra_4x4_Horizontal */
+ OMX_VC_4X4_DC = 2, /** Intra_4x4_DC */
+ OMX_VC_4X4_DIAG_DL = 3, /** Intra_4x4_Diagonal_Down_Left */
+ OMX_VC_4X4_DIAG_DR = 4, /** Intra_4x4_Diagonal_Down_Right */
+ OMX_VC_4X4_VR = 5, /** Intra_4x4_Vertical_Right */
+ OMX_VC_4X4_HD = 6, /** Intra_4x4_Horizontal_Down */
+ OMX_VC_4X4_VL = 7, /** Intra_4x4_Vertical_Left */
+ OMX_VC_4X4_HU = 8 /** Intra_4x4_Horizontal_Up */
+} OMXVCM4P10Intra4x4PredMode;
+
+
+
+/* 6.3.1.3 Chroma Prediction Modes */
+/* A data type that enumerates intra chroma prediction modes is defined as follows: */
+
+typedef enum {
+ OMX_VC_CHROMA_DC = 0, /** Intra_Chroma_DC */
+ OMX_VC_CHROMA_HOR = 1, /** Intra_Chroma_Horizontal */
+ OMX_VC_CHROMA_VERT = 2, /** Intra_Chroma_Vertical */
+ OMX_VC_CHROMA_PLANE = 3 /** Intra_Chroma_Plane */
+} OMXVCM4P10IntraChromaPredMode;
+
+
+
+/* 6.3.1.4 Motion Estimation Modes */
+/* A data type that enumerates H.264 motion estimation modes is defined as follows: */
+
+typedef enum {
+ OMX_VC_M4P10_FAST_SEARCH = 0, /** Fast motion search */
+ OMX_VC_M4P10_FULL_SEARCH = 1 /** Full motion search */
+} OMXVCM4P10MEMode;
+
+
+
+/* 6.3.1.5 Macroblock Types */
+/* A data type that enumerates H.264 macroblock types is defined as follows: */
+
+typedef enum {
+ OMX_VC_P_16x16 = 0, /* defined by [ISO14496-10] */
+ OMX_VC_P_16x8 = 1,
+ OMX_VC_P_8x16 = 2,
+ OMX_VC_P_8x8 = 3,
+ OMX_VC_PREF0_8x8 = 4,
+ OMX_VC_INTER_SKIP = 5,
+ OMX_VC_INTRA_4x4 = 8,
+ OMX_VC_INTRA_16x16 = 9,
+ OMX_VC_INTRA_PCM = 10
+} OMXVCM4P10MacroblockType;
+
+
+
+/* 6.3.1.6 Sub-Macroblock Types */
+/* A data type that enumerates H.264 sub-macroblock types is defined as follows: */
+
+typedef enum {
+ OMX_VC_SUB_P_8x8 = 0, /* defined by [ISO14496-10] */
+ OMX_VC_SUB_P_8x4 = 1,
+ OMX_VC_SUB_P_4x8 = 2,
+ OMX_VC_SUB_P_4x4 = 3
+} OMXVCM4P10SubMacroblockType;
+
+
+
+/* 6.3.1.7 Variable Length Coding (VLC) Information */
+
+typedef struct {
+ OMX_U8 uTrailing_Ones; /* Trailing ones; 3 at most */
+ OMX_U8 uTrailing_One_Signs; /* Trailing ones signal */
+ OMX_U8 uNumCoeffs; /* Total number of non-zero coefs, including trailing ones */
+ OMX_U8 uTotalZeros; /* Total number of zero coefs */
+ OMX_S16 iLevels[16]; /* Levels of non-zero coefs, in reverse zig-zag order */
+ OMX_U8 uRuns[16]; /* Runs for levels and trailing ones, in reverse zig-zag order */
+} OMXVCM4P10VLCInfo;
+
+
+
+/* 6.3.1.8 Macroblock Information */
+
+typedef struct {
+ OMX_S32 sliceId; /* slice number */
+ OMXVCM4P10MacroblockType mbType; /* MB type */
+ OMXVCM4P10SubMacroblockType subMBType[4]; /* sub-block type */
+ OMX_S32 qpy; /* qp for luma */
+ OMX_S32 qpc; /* qp for chroma */
+ OMX_U32 cbpy; /* CBP Luma */
+ OMX_U32 cbpc; /* CBP Chroma */
+ OMXVCMotionVector pMV0[4][4]; /* motion vector, represented using 1/4-pel units, pMV0[blocky][blockx] (blocky = 0~3, blockx =0~3) */
+ OMXVCMotionVector pMVPred[4][4]; /* motion vector prediction, Represented using 1/4-pel units, pMVPred[blocky][blockx] (blocky = 0~3, blockx = 0~3) */
+ OMX_U8 pRefL0Idx[4]; /* reference picture indices */
+ OMXVCM4P10Intra16x16PredMode Intra16x16PredMode; /* best intra 16x16 prediction mode */
+ OMXVCM4P10Intra4x4PredMode pIntra4x4PredMode[16]; /* best intra 4x4 prediction mode for each block, pMV0 indexed as above */
+} OMXVCM4P10MBInfo, *OMXVCM4P10MBInfoPtr;
+
+
+
+/* 6.3.1.9 Motion Estimation Parameters */
+
+typedef struct {
+ OMX_S32 blockSplitEnable8x8; /* enables 16x8, 8x16, 8x8 */
+ OMX_S32 blockSplitEnable4x4; /* enable splitting of 8x4, 4x8, 4x4 blocks */
+ OMX_S32 halfSearchEnable;
+ OMX_S32 quarterSearchEnable;
+ OMX_S32 intraEnable4x4; /* 1=enable, 0=disable */
+ OMX_S32 searchRange16x16; /* integer pixel units */
+ OMX_S32 searchRange8x8;
+ OMX_S32 searchRange4x4;
+} OMXVCM4P10MEParams;
+
+
+
+/**
+ * Function: omxVCM4P10_PredictIntra_4x4 (6.3.3.1.1)
+ *
+ * Description:
+ * Perform Intra_4x4 prediction for luma samples. If the upper-right block is
+ * not available, then duplication work should be handled inside the function.
+ * Users need not define them outside.
+ *
+ * Input Arguments:
+ *
+ * pSrcLeft - Pointer to the buffer of 4 left pixels:
+ * p[x, y] (x = -1, y = 0..3)
+ * pSrcAbove - Pointer to the buffer of 8 above pixels:
+ * p[x,y] (x = 0..7, y =-1);
+ * must be aligned on a 4-byte boundary.
+ * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
+ * leftStep - Step of left pixel buffer; must be a multiple of 4.
+ * dstStep - Step of the destination buffer; must be a multiple of 4.
+ * predMode - Intra_4x4 prediction mode.
+ * availability - Neighboring 4x4 block availability flag, refer to
+ * "Neighboring Macroblock Availability" .
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to the destination buffer; must be aligned on a 4-byte
+ * boundary.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pDst is NULL.
+ * dstStep < 4, or dstStep is not a multiple of 4.
+ * leftStep is not a multiple of 4.
+ * predMode is not in the valid range of enumeration
+ * OMXVCM4P10Intra4x4PredMode.
+ * predMode is OMX_VC_4x4_VERT, but availability doesn't set OMX_VC_UPPER
+ * indicating p[x,-1] (x = 0..3) is not available.
+ * predMode is OMX_VC_4x4_HOR, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..3) is not available.
+ * predMode is OMX_VC_4x4_DIAG_DL, but availability doesn't set
+ * OMX_VC_UPPER indicating p[x, -1] (x = 0..3) is not available.
+ * predMode is OMX_VC_4x4_DIAG_DR, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
+ * available.
+ * predMode is OMX_VC_4x4_VR, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
+ * available.
+ * predMode is OMX_VC_4x4_HD, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
+ * available.
+ * predMode is OMX_VC_4x4_VL, but availability doesn't set OMX_VC_UPPER
+ * indicating p[x,-1] (x = 0..3) is not available.
+ * predMode is OMX_VC_4x4_HU, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..3) is not available.
+ * availability sets OMX_VC_UPPER, but pSrcAbove is NULL.
+ * availability sets OMX_VC_LEFT, but pSrcLeft is NULL.
+ * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL.
+ * either pSrcAbove or pDst is not aligned on a 4-byte boundary.
+ *
+ * Note:
+ * pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointers if
+ * they are not used by intra prediction as implied in predMode.
+ *
+ */
+OMXResult omxVCM4P10_PredictIntra_4x4 (
+ const OMX_U8 *pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ const OMX_U8 *pSrcAboveLeft,
+ OMX_U8 *pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMXVCM4P10Intra4x4PredMode predMode,
+ OMX_S32 availability
+);
+
+
+
+/**
+ * Function: omxVCM4P10_PredictIntra_16x16 (6.3.3.1.2)
+ *
+ * Description:
+ * Perform Intra_16x16 prediction for luma samples. If the upper-right block
+ * is not available, then duplication work should be handled inside the
+ * function. Users need not define them outside.
+ *
+ * Input Arguments:
+ *
+ * pSrcLeft - Pointer to the buffer of 16 left pixels: p[x, y] (x = -1, y =
+ * 0..15)
+ * pSrcAbove - Pointer to the buffer of 16 above pixels: p[x,y] (x = 0..15,
+ * y= -1); must be aligned on a 16-byte boundary.
+ * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
+ * leftStep - Step of left pixel buffer; must be a multiple of 16.
+ * dstStep - Step of the destination buffer; must be a multiple of 16.
+ * predMode - Intra_16x16 prediction mode, please refer to section 3.4.1.
+ * availability - Neighboring 16x16 MB availability flag. Refer to
+ * section 3.4.4.
+ *
+ * Output Arguments:
+ *
+ * pDst -Pointer to the destination buffer; must be aligned on a 16-byte
+ * boundary.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pDst is NULL.
+ * dstStep < 16. or dstStep is not a multiple of 16.
+ * leftStep is not a multiple of 16.
+ * predMode is not in the valid range of enumeration
+ * OMXVCM4P10Intra16x16PredMode
+ * predMode is OMX_VC_16X16_VERT, but availability doesn't set
+ * OMX_VC_UPPER indicating p[x,-1] (x = 0..15) is not available.
+ * predMode is OMX_VC_16X16_HOR, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..15) is not available.
+ * predMode is OMX_VC_16X16_PLANE, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1](x = 0..15), or p[-1,y] (y = 0..15), or p[-1,-1] is not
+ * available.
+ * availability sets OMX_VC_UPPER, but pSrcAbove is NULL.
+ * availability sets OMX_VC_LEFT, but pSrcLeft is NULL.
+ * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL.
+ * either pSrcAbove or pDst is not aligned on a 16-byte boundary.
+ *
+ * Note:
+ * pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointers if
+ * they are not used by intra prediction implied in predMode.
+ * Note:
+ * OMX_VC_UPPER_RIGHT is not used in intra_16x16 luma prediction.
+ *
+ */
+OMXResult omxVCM4P10_PredictIntra_16x16 (
+ const OMX_U8 *pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ const OMX_U8 *pSrcAboveLeft,
+ OMX_U8 *pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMXVCM4P10Intra16x16PredMode predMode,
+ OMX_S32 availability
+);
+
+
+
+/**
+ * Function: omxVCM4P10_PredictIntraChroma_8x8 (6.3.3.1.3)
+ *
+ * Description:
+ * Performs intra prediction for chroma samples.
+ *
+ * Input Arguments:
+ *
+ * pSrcLeft - Pointer to the buffer of 8 left pixels: p[x, y] (x = -1, y=
+ * 0..7).
+ * pSrcAbove - Pointer to the buffer of 8 above pixels: p[x,y] (x = 0..7, y
+ * = -1); must be aligned on an 8-byte boundary.
+ * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
+ * leftStep - Step of left pixel buffer; must be a multiple of 8.
+ * dstStep - Step of the destination buffer; must be a multiple of 8.
+ * predMode - Intra chroma prediction mode, please refer to section 3.4.3.
+ * availability - Neighboring chroma block availability flag, please refer
+ * to "Neighboring Macroblock Availability".
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to the destination buffer; must be aligned on an 8-byte
+ * boundary.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If any of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pDst is NULL.
+ * dstStep < 8 or dstStep is not a multiple of 8.
+ * leftStep is not a multiple of 8.
+ * predMode is not in the valid range of enumeration
+ * OMXVCM4P10IntraChromaPredMode.
+ * predMode is OMX_VC_CHROMA_VERT, but availability doesn't set
+ * OMX_VC_UPPER indicating p[x,-1] (x = 0..7) is not available.
+ * predMode is OMX_VC_CHROMA_HOR, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..7) is not available.
+ * predMode is OMX_VC_CHROMA_PLANE, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1](x = 0..7), or p[-1,y] (y = 0..7), or p[-1,-1] is not
+ * available.
+ * availability sets OMX_VC_UPPER, but pSrcAbove is NULL.
+ * availability sets OMX_VC_LEFT, but pSrcLeft is NULL.
+ * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL.
+ * either pSrcAbove or pDst is not aligned on a 8-byte boundary.
+ *
+ * Note: pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointer if
+ * they are not used by intra prediction implied in predMode.
+ *
+ * Note: OMX_VC_UPPER_RIGHT is not used in intra chroma prediction.
+ *
+ */
+OMXResult omxVCM4P10_PredictIntraChroma_8x8 (
+ const OMX_U8 *pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ const OMX_U8 *pSrcAboveLeft,
+ OMX_U8 *pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMXVCM4P10IntraChromaPredMode predMode,
+ OMX_S32 availability
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InterpolateLuma (6.3.3.2.1)
+ *
+ * Description:
+ * Performs quarter-pixel interpolation for inter luma MB. It is assumed that
+ * the frame is already padded when calling this function.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the source reference frame buffer
+ * srcStep - reference frame step, in bytes; must be a multiple of roi.width
+ * dstStep - destination frame step, in bytes; must be a multiple of
+ * roi.width
+ * dx - Fractional part of horizontal motion vector component in 1/4 pixel
+ * unit; valid in the range [0,3]
+ * dy - Fractional part of vertical motion vector y component in 1/4 pixel
+ * unit; valid in the range [0,3]
+ * roi - Dimension of the interpolation region; the parameters roi.width and
+ * roi.height must be equal to either 4, 8, or 16.
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to the destination frame buffer:
+ * if roi.width==4, 4-byte alignment required
+ * if roi.width==8, 8-byte alignment required
+ * if roi.width==16, 16-byte alignment required
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pSrc or pDst is NULL.
+ * srcStep or dstStep < roi.width.
+ * dx or dy is out of range [0,3].
+ * roi.width or roi.height is out of range {4, 8, 16}.
+ * roi.width is equal to 4, but pDst is not 4 byte aligned.
+ * roi.width is equal to 8 or 16, but pDst is not 8 byte aligned.
+ * srcStep or dstStep is not a multiple of 8.
+ *
+ */
+OMXResult omxVCM4P10_InterpolateLuma (
+ const OMX_U8 *pSrc,
+ OMX_S32 srcStep,
+ OMX_U8 *pDst,
+ OMX_S32 dstStep,
+ OMX_S32 dx,
+ OMX_S32 dy,
+ OMXSize roi
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InterpolateChroma (6.3.3.2.2)
+ *
+ * Description:
+ * Performs 1/8-pixel interpolation for inter chroma MB.
+ *
+ * Input Arguments:
+ *
+ * pSrc -Pointer to the source reference frame buffer
+ * srcStep -Reference frame step in bytes
+ * dstStep -Destination frame step in bytes; must be a multiple of
+ * roi.width.
+ * dx -Fractional part of horizontal motion vector component in 1/8 pixel
+ * unit; valid in the range [0,7]
+ * dy -Fractional part of vertical motion vector component in 1/8 pixel
+ * unit; valid in the range [0,7]
+ * roi -Dimension of the interpolation region; the parameters roi.width and
+ * roi.height must be equal to either 2, 4, or 8.
+ *
+ * Output Arguments:
+ *
+ * pDst -Pointer to the destination frame buffer:
+ * if roi.width==2, 2-byte alignment required
+ * if roi.width==4, 4-byte alignment required
+ * if roi.width==8, 8-byte alignment required
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pSrc or pDst is NULL.
+ * srcStep or dstStep < 8.
+ * dx or dy is out of range [0-7].
+ * roi.width or roi.height is out of range {2,4,8}.
+ * roi.width is equal to 2, but pDst is not 2-byte aligned.
+ * roi.width is equal to 4, but pDst is not 4-byte aligned.
+ * roi.width is equal to 8, but pDst is not 8 byte aligned.
+ * srcStep or dstStep is not a multiple of 8.
+ *
+ */
+OMXResult omxVCM4P10_InterpolateChroma (
+ const OMX_U8 *pSrc,
+ OMX_S32 srcStep,
+ OMX_U8 *pDst,
+ OMX_S32 dstStep,
+ OMX_S32 dx,
+ OMX_S32 dy,
+ OMXSize roi
+);
+
+
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingLuma_VerEdge_I (6.3.3.3.1)
+ *
+ * Description:
+ * Performs in-place deblock filtering on four vertical edges of the luma
+ * macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the input macroblock; must be 16-byte aligned.
+ * srcdstStep -Step of the arrays; must be a multiple of 16.
+ * pAlpha -Array of size 2 of alpha thresholds (the first item is the alpha
+ * threshold for the external vertical edge, and the second item is
+ * for the internal vertical edge); per [ISO14496-10] alpha values
+ * must be in the range [0,255].
+ * pBeta -Array of size 2 of beta thresholds (the first item is the beta
+ * threshold for the external vertical edge, and the second item is
+ * for the internal vertical edge); per [ISO14496-10] beta values
+ * must be in the range [0,18].
+ * pThresholds -Array of size 16 of Thresholds (TC0) (values for the left
+ * edge of each 4x4 block, arranged in vertical block order); must
+ * be aligned on a 4-byte boundary.. Per [ISO14496-10] values must
+ * be in the range [0,25].
+ * pBS -Array of size 16 of BS parameters (arranged in vertical block
+ * order); valid in the range [0,4] with the following
+ * restrictions: i) pBS[i]== 4 may occur only for 0<=i<=3, ii)
+ * pBS[i]== 4 if and only if pBS[i^3]== 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * Either of the pointers in pSrcDst, pAlpha, pBeta, pThresholds, or pBS
+ * is NULL.
+ * Either pThresholds or pBS is not aligned on a 4-byte boundary.
+ * pSrcDst is not 16-byte aligned.
+ * srcdstStep is not a multiple of 16.
+ * pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * One or more entries in the table pThresholds[0..15]is outside of the
+ * range [0,25].
+ * pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or (pBS[i]==4 &&
+ * pBS[i^3]!=4) for 0<=i<=3.
+ *
+ */
+OMXResult omxVCM4P10_FilterDeblockingLuma_VerEdge_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingLuma_HorEdge_I (6.3.3.3.2)
+ *
+ * Description:
+ * Performs in-place deblock filtering on four horizontal edges of the luma
+ * macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 16-byte aligned.
+ * srcdstStep - step of the arrays; must be a multiple of 16.
+ * pAlpha - array of size 2 of alpha thresholds (the first item is the alpha
+ * threshold for the external vertical edge, and the second item is
+ * for the internal horizontal edge); per [ISO14496-10] alpha
+ * values must be in the range [0,255].
+ * pBeta - array of size 2 of beta thresholds (the first item is the beta
+ * threshold for the external horizontal edge, and the second item
+ * is for the internal horizontal edge). Per [ISO14496-10] beta
+ * values must be in the range [0,18].
+ * pThresholds - array of size 16 containing thresholds, TC0, for the top
+ * horizontal edge of each 4x4 block, arranged in horizontal block
+ * order; must be aligned on a 4-byte boundary. Per [ISO14496 10]
+ * values must be in the range [0,25].
+ * pBS - array of size 16 of BS parameters (arranged in horizontal block
+ * order); valid in the range [0,4] with the following
+ * restrictions: i) pBS[i]== 4 may occur only for 0<=i<=3, ii)
+ * pBS[i]== 4 if and only if pBS[i^3]== 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr, if one of the following cases occurs:
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds, or pBS.
+ * - either pThresholds or pBS is not aligned on a 4-byte boundary.
+ * - pSrcDst is not 16-byte aligned.
+ * - srcdstStep is not a multiple of 16.
+ * - pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * - pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * - One or more entries in the table pThresholds[0..15] is
+ * outside of the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ *
+ */
+OMXResult omxVCM4P10_FilterDeblockingLuma_HorEdge_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingChroma_VerEdge_I (6.3.3.3.3)
+ *
+ * Description:
+ * Performs in-place deblock filtering on four vertical edges of the chroma
+ * macroblock (8x8).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the input macroblock; must be 8-byte aligned.
+ * srcdstStep - Step of the arrays; must be a multiple of 8.
+ * pAlpha - Array of size 2 of alpha thresholds (the first item is alpha
+ * threshold for external vertical edge, and the second item is for
+ * internal vertical edge); per [ISO14496-10] alpha values must be
+ * in the range [0,255].
+ * pBeta - Array of size 2 of beta thresholds (the first item is the beta
+ * threshold for the external vertical edge, and the second item is
+ * for the internal vertical edge); per [ISO14496-10] beta values
+ * must be in the range [0,18].
+ * pThresholds - Array of size 8 containing thresholds, TC0, for the left
+ * vertical edge of each 4x2 chroma block, arranged in vertical
+ * block order; must be aligned on a 4-byte boundary. Per
+ * [ISO14496-10] values must be in the range [0,25].
+ * pBS - Array of size 16 of BS parameters (values for each 2x2 chroma
+ * block, arranged in vertical block order). This parameter is the
+ * same as the pBS parameter passed into FilterDeblockLuma_VerEdge;
+ * valid in the range [0,4] with the following restrictions: i)
+ * pBS[i]== 4 may occur only for 0<=i<=3, ii) pBS[i]== 4 if and
+ * only if pBS[i^3]== 4. Must be 4 byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds, or pBS.
+ * - pSrcDst is not 8-byte aligned.
+ * - srcdstStep is not a multiple of 8.
+ * - pThresholds is not 4-byte aligned.
+ * - pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * - pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * - One or more entries in the table pThresholds[0..7] is outside
+ * of the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - pBS is not 4-byte aligned.
+ *
+ */
+OMXResult omxVCM4P10_FilterDeblockingChroma_VerEdge_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingChroma_HorEdge_I (6.3.3.3.4)
+ *
+ * Description:
+ * Performs in-place deblock filtering on the horizontal edges of the chroma
+ * macroblock (8x8).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 8-byte aligned.
+ * srcdstStep - array step; must be a multiple of 8.
+ * pAlpha - array of size 2 containing alpha thresholds; the first element
+ * contains the threshold for the external horizontal edge, and the
+ * second element contains the threshold for internal horizontal
+ * edge. Per [ISO14496-10] alpha values must be in the range
+ * [0,255].
+ * pBeta - array of size 2 containing beta thresholds; the first element
+ * contains the threshold for the external horizontal edge, and the
+ * second element contains the threshold for the internal
+ * horizontal edge. Per [ISO14496-10] beta values must be in the
+ * range [0,18].
+ * pThresholds - array of size 8 containing thresholds, TC0, for the top
+ * horizontal edge of each 2x4 chroma block, arranged in horizontal
+ * block order; must be aligned on a 4-byte boundary. Per
+ * [ISO14496-10] values must be in the range [0,25].
+ * pBS - array of size 16 containing BS parameters for each 2x2 chroma
+ * block, arranged in horizontal block order; valid in the range
+ * [0,4] with the following restrictions: i) pBS[i]== 4 may occur
+ * only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^3]== 4.
+ * Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr, if one of the following cases occurs:
+ * - any of the following pointers is NULL:
+ * pSrcDst, pAlpha, pBeta, pThresholds, or pBS.
+ * - pSrcDst is not 8-byte aligned.
+ * - srcdstStep is not a multiple of 8.
+ * - pThresholds is not 4-byte aligned.
+ * - pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * - pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * - One or more entries in the table pThresholds[0..7] is outside
+ * of the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - pBS is not 4-byte aligned.
+ *
+ */
+OMXResult omxVCM4P10_FilterDeblockingChroma_HorEdge_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DeblockLuma_I (6.3.3.3.5)
+ *
+ * Description:
+ * This function performs in-place deblock filtering the horizontal and
+ * vertical edges of a luma macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 16-byte aligned.
+ * srcdstStep - image width; must be a multiple of 16.
+ * pAlpha - pointer to a 2x2 table of alpha thresholds, organized as
+ * follows: {external vertical edge, internal vertical edge,
+ * external horizontal edge, internal horizontal edge }. Per
+ * [ISO14496-10] alpha values must be in the range [0,255].
+ * pBeta - pointer to a 2x2 table of beta thresholds, organized as follows:
+ * {external vertical edge, internal vertical edge, external
+ * horizontal edge, internal horizontal edge }. Per [ISO14496-10]
+ * beta values must be in the range [0,18].
+ * pThresholds - pointer to a 16x2 table of threshold (TC0), organized as
+ * follows: {values for the left or above edge of each 4x4 block,
+ * arranged in vertical block order and then in horizontal block
+ * order}; must be aligned on a 4-byte boundary. Per [ISO14496-10]
+ * values must be in the range [0,25].
+ * pBS - pointer to a 16x2 table of BS parameters arranged in scan block
+ * order for vertical edges and then horizontal edges; valid in the
+ * range [0,4] with the following restrictions: i) pBS[i]== 4 may
+ * occur only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^3]==
+ * 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds or pBS.
+ * - pSrcDst is not 16-byte aligned.
+ * - either pThresholds or pBS is not aligned on a 4-byte boundary.
+ * - one or more entries in the table pAlpha[0..3] is outside the range
+ * [0,255].
+ * - one or more entries in the table pBeta[0..3] is outside the range
+ * [0,18].
+ * - one or more entries in the table pThresholds[0..31]is outside of
+ * the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - srcdstStep is not a multiple of 16.
+ *
+ */
+OMXResult omxVCM4P10_DeblockLuma_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DeblockChroma_I (6.3.3.3.6)
+ *
+ * Description:
+ * Performs in-place deblocking filtering on all edges of the chroma
+ * macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 8-byte aligned.
+ * srcdstStep - step of the arrays; must be a multiple of 8.
+ * pAlpha - pointer to a 2x2 array of alpha thresholds, organized as
+ * follows: {external vertical edge, internal vertical edge,
+ * external horizontal edge, internal horizontal edge }. Per
+ * [ISO14496-10] alpha values must be in the range [0,255].
+ * pBeta - pointer to a 2x2 array of Beta Thresholds, organized as follows:
+ * { external vertical edge, internal vertical edge, external
+ * horizontal edge, internal horizontal edge }. Per [ISO14496-10]
+ * beta values must be in the range [0,18].
+ * pThresholds - array of size 8x2 of Thresholds (TC0) (values for the left
+ * or above edge of each 4x2 or 2x4 block, arranged in vertical
+ * block order and then in horizontal block order); must be aligned
+ * on a 4-byte boundary. Per [ISO14496-10] values must be in the
+ * range [0,25].
+ * pBS - array of size 16x2 of BS parameters (arranged in scan block order
+ * for vertical edges and then horizontal edges); valid in the
+ * range [0,4] with the following restrictions: i) pBS[i]== 4 may
+ * occur only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^3]==
+ * 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds, or pBS.
+ * - pSrcDst is not 8-byte aligned.
+ * - either pThresholds or pBS is not 4-byte aligned.
+ * - one or more entries in the table pAlpha[0..3] is outside the range
+ * [0,255].
+ * - one or more entries in the table pBeta[0..3] is outside the range
+ * [0,18].
+ * - one or more entries in the table pThresholds[0..15]is outside of
+ * the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - srcdstStep is not a multiple of 8.
+ *
+ */
+OMXResult omxVCM4P10_DeblockChroma_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC (6.3.4.1.1)
+ *
+ * Description:
+ * Performs CAVLC decoding and inverse raster scan for a 2x2 block of
+ * ChromaDCLevel. The decoded coefficients in the packed position-coefficient
+ * buffer are stored in reverse zig-zag order, i.e., the first buffer element
+ * contains the last non-zero postion-coefficient pair of the block. Within
+ * each position-coefficient pair, the position entry indicates the
+ * raster-scan position of the coefficient, while the coefficient entry
+ * contains the coefficient value.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - Double pointer to current byte in bit stream buffer
+ * pOffset - Pointer to current bit position in the byte pointed to by
+ * *ppBitStream; valid in the range [0,7].
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after each block is decoded
+ * pOffset - *pOffset is updated after each block is decoded
+ * pNumCoeff - Pointer to the number of nonzero coefficients in this block
+ * ppPosCoefBuf - Double pointer to destination residual
+ * coefficient-position pair buffer. Buffer position
+ * (*ppPosCoefBuf) is updated upon return, unless there are only
+ * zero coefficients in the currently decoded block. In this case
+ * the caller is expected to bypass the transform/dequantization of
+ * the empty blocks.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppBitStream or pOffset is NULL.
+ * - ppPosCoefBuf or pNumCoeff is NULL.
+ * OMX_Sts_Err - if one of the following is true:
+ * - an illegal code is encountered in the bitstream
+ *
+ */
+OMXResult omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC (
+ const OMX_U8 **ppBitStream,
+ OMX_S32*pOffset,
+ OMX_U8 *pNumCoeff,
+ OMX_U8 **ppPosCoefbuf
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DecodeCoeffsToPairCAVLC (6.3.4.1.2)
+ *
+ * Description:
+ * Performs CAVLC decoding and inverse zigzag scan for 4x4 block of
+ * Intra16x16DCLevel, Intra16x16ACLevel, LumaLevel, and ChromaACLevel. Inverse
+ * field scan is not supported. The decoded coefficients in the packed
+ * position-coefficient buffer are stored in reverse zig-zag order, i.e., the
+ * first buffer element contains the last non-zero postion-coefficient pair of
+ * the block. Within each position-coefficient pair, the position entry
+ * indicates the raster-scan position of the coefficient, while the
+ * coefficient entry contains the coefficient value.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream -Double pointer to current byte in bit stream buffer
+ * pOffset - Pointer to current bit position in the byte pointed to by
+ * *ppBitStream; valid in the range [0,7].
+ * sMaxNumCoeff - Maximum the number of non-zero coefficients in current
+ * block
+ * sVLCSelect - VLC table selector, obtained from the number of non-zero
+ * coefficients contained in the above and left 4x4 blocks. It is
+ * equivalent to the variable nC described in H.264 standard table
+ * 9 5, except its value can t be less than zero.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after each block is decoded.
+ * Buffer position (*ppPosCoefBuf) is updated upon return, unless
+ * there are only zero coefficients in the currently decoded block.
+ * In this case the caller is expected to bypass the
+ * transform/dequantization of the empty blocks.
+ * pOffset - *pOffset is updated after each block is decoded
+ * pNumCoeff - Pointer to the number of nonzero coefficients in this block
+ * ppPosCoefBuf - Double pointer to destination residual
+ * coefficient-position pair buffer
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppBitStream or pOffset is NULL.
+ * - ppPosCoefBuf or pNumCoeff is NULL.
+ * - sMaxNumCoeff is not equal to either 15 or 16.
+ * - sVLCSelect is less than 0.
+ *
+ * OMX_Sts_Err - if one of the following is true:
+ * - an illegal code is encountered in the bitstream
+ *
+ */
+OMXResult omxVCM4P10_DecodeCoeffsToPairCAVLC (
+ const OMX_U8 **ppBitStream,
+ OMX_S32 *pOffset,
+ OMX_U8 *pNumCoeff,
+ OMX_U8 **ppPosCoefbuf,
+ OMX_INT sVLCSelect,
+ OMX_INT sMaxNumCoeff
+);
+
+
+
+/**
+ * Function: omxVCM4P10_TransformDequantLumaDCFromPair (6.3.4.2.1)
+ *
+ * Description:
+ * Reconstructs the 4x4 LumaDC block from the coefficient-position pair
+ * buffer, performs integer inverse, and dequantization for 4x4 LumaDC
+ * coefficients, and updates the pair buffer pointer to the next non-empty
+ * block.
+ *
+ * Input Arguments:
+ *
+ * ppSrc - Double pointer to residual coefficient-position pair buffer
+ * output by CALVC decoding
+ * QP - Quantization parameter QpY
+ *
+ * Output Arguments:
+ *
+ * ppSrc - *ppSrc is updated to the start of next non empty block
+ * pDst - Pointer to the reconstructed 4x4 LumaDC coefficients buffer; must
+ * be aligned on a 8-byte boundary.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppSrc or pDst is NULL.
+ * - pDst is not 8 byte aligned.
+ * - QP is not in the range of [0-51].
+ *
+ */
+OMXResult omxVCM4P10_TransformDequantLumaDCFromPair (
+ const OMX_U8 **ppSrc,
+ OMX_S16 *pDst,
+ OMX_INT QP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_TransformDequantChromaDCFromPair (6.3.4.2.2)
+ *
+ * Description:
+ * Reconstruct the 2x2 ChromaDC block from coefficient-position pair buffer,
+ * perform integer inverse transformation, and dequantization for 2x2 chroma
+ * DC coefficients, and update the pair buffer pointer to next non-empty
+ * block.
+ *
+ * Input Arguments:
+ *
+ * ppSrc - Double pointer to residual coefficient-position pair buffer
+ * output by CALVC decoding
+ * QP - Quantization parameter QpC
+ *
+ * Output Arguments:
+ *
+ * ppSrc - *ppSrc is updated to the start of next non empty block
+ * pDst - Pointer to the reconstructed 2x2 ChromaDC coefficients buffer;
+ * must be aligned on a 4-byte boundary.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppSrc or pDst is NULL.
+ * - pDst is not 4-byte aligned.
+ * - QP is not in the range of [0-51].
+ *
+ */
+OMXResult omxVCM4P10_TransformDequantChromaDCFromPair (
+ const OMX_U8 **ppSrc,
+ OMX_S16 *pDst,
+ OMX_INT QP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DequantTransformResidualFromPairAndAdd (6.3.4.2.3)
+ *
+ * Description:
+ * Reconstruct the 4x4 residual block from coefficient-position pair buffer,
+ * perform dequantization and integer inverse transformation for 4x4 block of
+ * residuals with previous intra prediction or motion compensation data, and
+ * update the pair buffer pointer to next non-empty block. If pDC == NULL,
+ * there re 16 non-zero AC coefficients at most in the packed buffer starting
+ * from 4x4 block position 0; If pDC != NULL, there re 15 non-zero AC
+ * coefficients at most in the packet buffer starting from 4x4 block position
+ * 1.
+ *
+ * Input Arguments:
+ *
+ * ppSrc - Double pointer to residual coefficient-position pair buffer
+ * output by CALVC decoding
+ * pPred - Pointer to the predicted 4x4 block; must be aligned on a 4-byte
+ * boundary
+ * predStep - Predicted frame step size in bytes; must be a multiple of 4
+ * dstStep - Destination frame step in bytes; must be a multiple of 4
+ * pDC - Pointer to the DC coefficient of this block, NULL if it doesn't
+ * exist
+ * QP - QP Quantization parameter. It should be QpC in chroma 4x4 block
+ * decoding, otherwise it should be QpY.
+ * AC - Flag indicating if at least one non-zero AC coefficient exists
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the reconstructed 4x4 block data; must be aligned on a
+ * 4-byte boundary
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - pPred or pDst is NULL.
+ * - pPred or pDst is not 4-byte aligned.
+ * - predStep or dstStep is not a multiple of 4.
+ * - AC !=0 and Qp is not in the range of [0-51] or ppSrc == NULL.
+ * - AC ==0 && pDC ==NULL.
+ *
+ */
+OMXResult omxVCM4P10_DequantTransformResidualFromPairAndAdd (
+ const OMX_U8 **ppSrc,
+ const OMX_U8 *pPred,
+ const OMX_S16 *pDC,
+ OMX_U8 *pDst,
+ OMX_INT predStep,
+ OMX_INT dstStep,
+ OMX_INT QP,
+ OMX_INT AC
+);
+
+
+
+/**
+ * Function: omxVCM4P10_MEGetBufSize (6.3.5.1.1)
+ *
+ * Description:
+ * Computes the size, in bytes, of the vendor-specific specification
+ * structure for the omxVCM4P10 motion estimation functions BlockMatch_Integer
+ * and MotionEstimationMB.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P10MEMode
+ * pMEParams -motion estimation parameters
+ *
+ * Output Arguments:
+ *
+ * pSize - pointer to the number of bytes required for the motion
+ * estimation specification structure
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - pMEParams or pSize is NULL.
+ * - an invalid MEMode is specified.
+ *
+ */
+OMXResult omxVCM4P10_MEGetBufSize (
+ OMXVCM4P10MEMode MEmode,
+ const OMXVCM4P10MEParams *pMEParams,
+ OMX_U32 *pSize
+);
+
+
+
+/**
+ * Function: omxVCM4P10_MEInit (6.3.5.1.2)
+ *
+ * Description:
+ * Initializes the vendor-specific specification structure required for the
+ * omxVCM4P10 motion estimation functions: BlockMatch_Integer and
+ * MotionEstimationMB. Memory for the specification structure *pMESpec must be
+ * allocated prior to calling the function, and should be aligned on a 4-byte
+ * boundary. The number of bytes required for the specification structure can
+ * be determined using the function omxVCM4P10_MEGetBufSize. Following
+ * initialization by this function, the vendor-specific structure *pMESpec
+ * should contain an implementation-specific representation of all motion
+ * estimation parameters received via the structure pMEParams, for example
+ * searchRange16x16, searchRange8x8, etc.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P10MEMode
+ * pMEParams - motion estimation parameters
+ * pMESpec - pointer to the uninitialized ME specification structure
+ *
+ * Output Arguments:
+ *
+ * pMESpec - pointer to the initialized ME specification structure
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - pMEParams or pSize is NULL.
+ * - an invalid value was specified for the parameter MEmode
+ * - a negative or zero value was specified for one of the search ranges
+ * (e.g., pMBParams >searchRange8x8, pMEParams->searchRange16x16, etc.)
+ * - either in isolation or in combination, one or more of the enables or
+ * search ranges in the structure *pMEParams were configured such
+ * that the requested behavior fails to comply with [ISO14496-10].
+ *
+ */
+OMXResult omxVCM4P10_MEInit (
+ OMXVCM4P10MEMode MEmode,
+ const OMXVCM4P10MEParams *pMEParams,
+ void *pMESpec
+);
+
+
+
+/**
+ * Function: omxVCM4P10_BlockMatch_Integer (6.3.5.2.1)
+ *
+ * Description:
+ * Performs integer block match. Returns best MV and associated cost.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrgY - Pointer to the top-left corner of the current block:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * pSrcRefY - Pointer to the top-left corner of the co-located block in the
+ * reference picture:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * nSrcOrgStep - Stride of the original picture plane, expressed in terms
+ * of integer pixels; must be a multiple of iBlockWidth.
+ * nSrcRefStep - Stride of the reference picture plane, expressed in terms
+ * of integer pixels
+ * pRefRect - pointer to the valid reference rectangle inside the reference
+ * picture plane
+ * nCurrPointPos - position of the current block in the current plane
+ * iBlockWidth - Width of the current block, expressed in terms of integer
+ * pixels; must be equal to either 4, 8, or 16.
+ * iBlockHeight - Height of the current block, expressed in terms of
+ * integer pixels; must be equal to either 4, 8, or 16.
+ * nLamda - Lamda factor; used to compute motion cost
+ * pMVPred - Predicted MV; used to compute motion cost, expressed in terms
+ * of 1/4-pel units
+ * pMVCandidate - Candidate MV; used to initialize the motion search,
+ * expressed in terms of integer pixels
+ * pMESpec - pointer to the ME specification structure
+ *
+ * Output Arguments:
+ *
+ * pDstBestMV - Best MV resulting from integer search, expressed in terms
+ * of 1/4-pel units
+ * pBestCost - Motion cost associated with the best MV; computed as
+ * SAD+Lamda*BitsUsedByMV
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - any of the following pointers are NULL:
+ * pSrcOrgY, pSrcRefY, pRefRect, pMVPred, pMVCandidate, or pMESpec.
+ * - Either iBlockWidth or iBlockHeight are values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_BlockMatch_Integer (
+ const OMX_U8 *pSrcOrgY,
+ OMX_S32 nSrcOrgStep,
+ const OMX_U8 *pSrcRefY,
+ OMX_S32 nSrcRefStep,
+ const OMXRect *pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ OMX_U8 iBlockWidth,
+ OMX_U8 iBlockHeight,
+ OMX_U32 nLamda,
+ const OMXVCMotionVector *pMVPred,
+ const OMXVCMotionVector *pMVCandidate,
+ OMXVCMotionVector *pBestMV,
+ OMX_S32 *pBestCost,
+ void *pMESpec
+);
+
+
+
+/**
+ * Function: omxVCM4P10_BlockMatch_Half (6.3.5.2.2)
+ *
+ * Description:
+ * Performs a half-pel block match using results from a prior integer search.
+ * Returns the best MV and associated cost. This function estimates the
+ * half-pixel motion vector by interpolating the integer resolution motion
+ * vector referenced by the input parameter pSrcDstBestMV, i.e., the initial
+ * integer MV is generated externally. The function
+ * omxVCM4P10_BlockMatch_Integer may be used for integer motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrgY - Pointer to the current position in original picture plane:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * pSrcRefY - Pointer to the top-left corner of the co-located block in the
+ * reference picture:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * nSrcOrgStep - Stride of the original picture plane in terms of full
+ * pixels; must be a multiple of iBlockWidth.
+ * nSrcRefStep - Stride of the reference picture plane in terms of full
+ * pixels
+ * iBlockWidth - Width of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * iBlockHeight - Height of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * nLamda - Lamda factor, used to compute motion cost
+ * pMVPred - Predicted MV, represented in terms of 1/4-pel units; used to
+ * compute motion cost
+ * pSrcDstBestMV - The best MV resulting from a prior integer search,
+ * represented in terms of 1/4-pel units
+ *
+ * Output Arguments:
+ *
+ * pSrcDstBestMV - Best MV resulting from the half-pel search, expressed in
+ * terms of 1/4-pel units
+ * pBestCost - Motion cost associated with the best MV; computed as
+ * SAD+Lamda*BitsUsedByMV
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - any of the following pointers is NULL: pSrcOrgY, pSrcRefY,
+ * pSrcDstBestMV, pMVPred, pBestCost
+ * - iBlockWidth or iBlockHeight are equal to values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_BlockMatch_Half (
+ const OMX_U8 *pSrcOrgY,
+ OMX_S32 nSrcOrgStep,
+ const OMX_U8 *pSrcRefY,
+ OMX_S32 nSrcRefStep,
+ OMX_U8 iBlockWidth,
+ OMX_U8 iBlockHeight,
+ OMX_U32 nLamda,
+ const OMXVCMotionVector *pMVPred,
+ OMXVCMotionVector *pSrcDstBestMV,
+ OMX_S32 *pBestCost
+);
+
+
+
+/**
+ * Function: omxVCM4P10_BlockMatch_Quarter (6.3.5.2.3)
+ *
+ * Description:
+ * Performs a quarter-pel block match using results from a prior half-pel
+ * search. Returns the best MV and associated cost. This function estimates
+ * the quarter-pixel motion vector by interpolating the half-pel resolution
+ * motion vector referenced by the input parameter pSrcDstBestMV, i.e., the
+ * initial half-pel MV is generated externally. The function
+ * omxVCM4P10_BlockMatch_Half may be used for half-pel motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrgY - Pointer to the current position in original picture plane:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * pSrcRefY - Pointer to the top-left corner of the co-located block in the
+ * reference picture:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * nSrcOrgStep - Stride of the original picture plane in terms of full
+ * pixels; must be a multiple of iBlockWidth.
+ * nSrcRefStep - Stride of the reference picture plane in terms of full
+ * pixels
+ * iBlockWidth - Width of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * iBlockHeight - Height of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * nLamda - Lamda factor, used to compute motion cost
+ * pMVPred - Predicted MV, represented in terms of 1/4-pel units; used to
+ * compute motion cost
+ * pSrcDstBestMV - The best MV resulting from a prior half-pel search,
+ * represented in terms of 1/4 pel units
+ *
+ * Output Arguments:
+ *
+ * pSrcDstBestMV - Best MV resulting from the quarter-pel search, expressed
+ * in terms of 1/4-pel units
+ * pBestCost - Motion cost associated with the best MV; computed as
+ * SAD+Lamda*BitsUsedByMV
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - One or more of the following pointers is NULL:
+ * pSrcOrgY, pSrcRefY, pSrcDstBestMV, pMVPred, pBestCost
+ * - iBlockWidth or iBlockHeight are equal to values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_BlockMatch_Quarter (
+ const OMX_U8 *pSrcOrgY,
+ OMX_S32 nSrcOrgStep,
+ const OMX_U8 *pSrcRefY,
+ OMX_S32 nSrcRefStep,
+ OMX_U8 iBlockWidth,
+ OMX_U8 iBlockHeight,
+ OMX_U32 nLamda,
+ const OMXVCMotionVector *pMVPred,
+ OMXVCMotionVector *pSrcDstBestMV,
+ OMX_S32 *pBestCost
+);
+
+
+
+/**
+ * Function: omxVCM4P10_MotionEstimationMB (6.3.5.3.1)
+ *
+ * Description:
+ * Performs MB-level motion estimation and selects best motion estimation
+ * strategy from the set of modes supported in baseline profile [ISO14496-10].
+ *
+ * Input Arguments:
+ *
+ * pSrcCurrBuf - Pointer to the current position in original picture plane;
+ * 16-byte alignment required
+ * pSrcRefBufList - Pointer to an array with 16 entries. Each entry points
+ * to the top-left corner of the co-located MB in a reference
+ * picture. The array is filled from low-to-high with valid
+ * reference frame pointers; the unused high entries should be set
+ * to NULL. Ordering of the reference frames should follow
+ * [ISO14496-10] subclause 8.2.4 Decoding Process for Reference
+ * Picture Lists. The entries must be 16-byte aligned.
+ * pSrcRecBuf - Pointer to the top-left corner of the co-located MB in the
+ * reconstructed picture; must be 16-byte aligned.
+ * SrcCurrStep - Width of the original picture plane in terms of full
+ * pixels; must be a multiple of 16.
+ * SrcRefStep - Width of the reference picture plane in terms of full
+ * pixels; must be a multiple of 16.
+ * SrcRecStep - Width of the reconstructed picture plane in terms of full
+ * pixels; must be a multiple of 16.
+ * pRefRect - Pointer to the valid reference rectangle; relative to the
+ * image origin.
+ * pCurrPointPos - Position of the current macroblock in the current plane.
+ * Lambda - Lagrange factor for computing the cost function
+ * pMESpec - Pointer to the motion estimation specification structure; must
+ * have been allocated and initialized prior to calling this
+ * function.
+ * pMBInter - Array, of dimension four, containing pointers to information
+ * associated with four adjacent type INTER MBs (Left, Top,
+ * Top-Left, Top-Right). Any pointer in the array may be set equal
+ * to NULL if the corresponding MB doesn t exist or is not of type
+ * INTER.
+ * - pMBInter[0] - Pointer to left MB information
+ * - pMBInter[1] - Pointer to top MB information
+ * - pMBInter[2] - Pointer to top-left MB information
+ * - pMBInter[3] - Pointer to top-right MB information
+ * pMBIntra - Array, of dimension four, containing pointers to information
+ * associated with four adjacent type INTRA MBs (Left, Top,
+ * Top-Left, Top-Right). Any pointer in the array may be set equal
+ * to NULL if the corresponding MB doesn t exist or is not of type
+ * INTRA.
+ * - pMBIntra[0] - Pointer to left MB information
+ * - pMBIntra[1] - Pointer to top MB information
+ * - pMBIntra[2] - Pointer to top-left MB information
+ * - pMBIntra[3] - Pointer to top-right MB information
+ * pSrcDstMBCurr - Pointer to information structure for the current MB.
+ * The following entries should be set prior to calling the
+ * function: sliceID - the number of the slice the to which the
+ * current MB belongs.
+ *
+ * Output Arguments:
+ *
+ * pDstCost - Pointer to the minimum motion cost for the current MB.
+ * pDstBlockSAD - Pointer to the array of SADs for each of the sixteen luma
+ * 4x4 blocks in each MB. The block SADs are in scan order for
+ * each MB. For implementations that cannot compute the SAD values
+ * individually, the maximum possible value (0xffff) is returned
+ * for each of the 16 block SAD entries.
+ * pSrcDstMBCurr - Pointer to updated information structure for the current
+ * MB after MB-level motion estimation has been completed. The
+ * following fields are updated by the ME function. The following
+ * parameter set quantifies the MB-level ME search results:
+ * - MbType
+ * - subMBType[4]
+ * - pMV0[4][4]
+ * - pMVPred[4][4]
+ * - pRefL0Idx[4]
+ * - Intra16x16PredMode
+ * - pIntra4x4PredMode[4][4]
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - One or more of the following pointers is NULL: pSrcCurrBuf,
+ * pSrcRefBufList, pSrcRecBuf, pRefRect, pCurrPointPos, pMESpec,
+ * pMBInter, pMBIntra,pSrcDstMBCurr, pDstCost, pSrcRefBufList[0]
+ * - SrcRefStep, SrcRecStep are not multiples of 16
+ * - iBlockWidth or iBlockHeight are values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_MotionEstimationMB (
+ const OMX_U8 *pSrcCurrBuf,
+ OMX_S32 SrcCurrStep,
+ const OMX_U8 *pSrcRefBufList[15],
+ OMX_S32 SrcRefStep,
+ const OMX_U8 *pSrcRecBuf,
+ OMX_S32 SrcRecStep,
+ const OMXRect *pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ OMX_U32 Lambda,
+ void *pMESpec,
+ const OMXVCM4P10MBInfoPtr *pMBInter,
+ const OMXVCM4P10MBInfoPtr *pMBIntra,
+ OMXVCM4P10MBInfoPtr pSrcDstMBCurr,
+ OMX_INT *pDstCost,
+ OMX_U16 *pDstBlockSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SAD_4x (6.3.5.4.1)
+ *
+ * Description:
+ * This function calculates the SAD for 4x8 and 4x4 blocks.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg -Pointer to the original block; must be aligned on a 4-byte
+ * boundary.
+ * iStepOrg -Step of the original block buffer; must be a multiple of 4.
+ * pSrcRef -Pointer to the reference block
+ * iStepRef -Step of the reference block buffer
+ * iHeight -Height of the block; must be equal to either 4 or 8.
+ *
+ * Output Arguments:
+ *
+ * pDstSAD -Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - One or more of the following pointers is NULL:
+ * pSrcOrg, pSrcRef, or pDstSAD
+ * - iHeight is not equal to either 4 or 8.
+ * - iStepOrg is not a multiple of 4
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SAD_4x (
+ const OMX_U8 *pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8 *pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SADQuar_4x (6.3.5.4.2)
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the average
+ * of the other two (pSrcRef0 and pSrcRef1) for 4x8 or 4x4 blocks. Rounding
+ * is applied according to the convention (a+b+1)>>1.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the original block; must be aligned on a 4-byte
+ * boundary.
+ * pSrcRef0 - Pointer to reference block 0
+ * pSrcRef1 - Pointer to reference block 1
+ * iSrcStep - Step of the original block buffer; must be a multiple of 4.
+ * iRefStep0 - Step of reference block 0
+ * iRefStep1 - Step of reference block 1
+ * iHeight - Height of the block; must be equal to either 4 or 8.
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - iHeight is not equal to either 4 or 8.
+ * - One or more of the following pointers is NULL: pSrc, pSrcRef0,
+ * pSrcRef1, pDstSAD.
+ * - iSrcStep is not a multiple of 4
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SADQuar_4x (
+ const OMX_U8 *pSrc,
+ const OMX_U8 *pSrcRef0,
+ const OMX_U8 *pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SADQuar_8x (6.3.5.4.3)
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the average
+ * of the other two (pSrcRef0 and pSrcRef1) for 8x16, 8x8, or 8x4 blocks.
+ * Rounding is applied according to the convention (a+b+1)>>1.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the original block; must be aligned on an 8-byte
+ * boundary.
+ * pSrcRef0 - Pointer to reference block 0
+ * pSrcRef1 - Pointer to reference block 1
+ * iSrcStep - Step of the original block buffer; must be a multiple of 8.
+ * iRefStep0 - Step of reference block 0
+ * iRefStep1 - Step of reference block 1
+ * iHeight - Height of the block; must be equal either 4, 8, or 16.
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - iHeight is not equal to either 4, 8, or 16.
+ * - One or more of the following pointers is NULL: pSrc, pSrcRef0,
+ * pSrcRef1, pDstSAD.
+ * - iSrcStep is not a multiple of 8
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SADQuar_8x (
+ const OMX_U8 *pSrc,
+ const OMX_U8 *pSrcRef0,
+ const OMX_U8 *pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SADQuar_16x (6.3.5.4.4)
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the average
+ * of the other two (pSrcRef0 and pSrcRef1) for 16x16 or 16x8 blocks.
+ * Rounding is applied according to the convention (a+b+1)>>1.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the original block; must be aligned on a 16-byte
+ * boundary.
+ * pSrcRef0 - Pointer to reference block 0
+ * pSrcRef1 - Pointer to reference block 1
+ * iSrcStep - Step of the original block buffer; must be a multiple of 16
+ * iRefStep0 - Step of reference block 0
+ * iRefStep1 - Step of reference block 1
+ * iHeight - Height of the block; must be equal to either 8 or 16
+ *
+ * Output Arguments:
+ *
+ * pDstSAD -Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - iHeight is not equal to either 8 or 16.
+ * - One or more of the following pointers is NULL: pSrc, pSrcRef0,
+ * pSrcRef1, pDstSAD.
+ * - iSrcStep is not a multiple of 16
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SADQuar_16x (
+ const OMX_U8 *pSrc,
+ const OMX_U8 *pSrcRef0,
+ const OMX_U8 *pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SATD_4x4 (6.3.5.4.5)
+ *
+ * Description:
+ * This function calculates the sum of absolute transform differences (SATD)
+ * for a 4x4 block by applying a Hadamard transform to the difference block
+ * and then calculating the sum of absolute coefficient values.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to the original block; must be aligned on a 4-byte
+ * boundary
+ * iStepOrg - Step of the original block buffer; must be a multiple of 4
+ * pSrcRef - Pointer to the reference block; must be aligned on a 4-byte
+ * boundary
+ * iStepRef - Step of the reference block buffer; must be a multiple of 4
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - pointer to the resulting SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pSrcRef, or pDstSAD either pSrcOrg
+ * - pSrcRef is not aligned on a 4-byte boundary
+ * - iStepOrg <= 0 or iStepOrg is not a multiple of 4
+ * - iStepRef <= 0 or iStepRef is not a multiple of 4
+ *
+ */
+OMXResult omxVCM4P10_SATD_4x4 (
+ const OMX_U8 *pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8 *pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_U32 *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InterpolateHalfHor_Luma (6.3.5.5.1)
+ *
+ * Description:
+ * This function performs interpolation for two horizontal 1/2-pel positions
+ * (-1/2,0) and (1/2, 0) - around a full-pel position.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the top-left corner of the block used to interpolate in
+ * the reconstruction frame plane.
+ * iSrcStep - Step of the source buffer.
+ * iDstStep - Step of the destination(interpolation) buffer; must be a
+ * multiple of iWidth.
+ * iWidth - Width of the current block; must be equal to either 4, 8, or 16
+ * iHeight - Height of the current block; must be equal to 4, 8, or 16
+ *
+ * Output Arguments:
+ *
+ * pDstLeft -Pointer to the interpolation buffer of the left -pel position
+ * (-1/2, 0)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ * pDstRight -Pointer to the interpolation buffer of the right -pel
+ * position (1/2, 0)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrc, pDstLeft, or pDstRight
+ * - iWidth or iHeight have values other than 4, 8, or 16
+ * - iWidth==4 but pDstLeft and/or pDstRight is/are not aligned on a 4-byte boundary
+ * - iWidth==8 but pDstLeft and/or pDstRight is/are not aligned on a 8-byte boundary
+ * - iWidth==16 but pDstLeft and/or pDstRight is/are not aligned on a 16-byte boundary
+ * - any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_InterpolateHalfHor_Luma (
+ const OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDstLeft,
+ OMX_U8 *pDstRight,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InterpolateHalfVer_Luma (6.3.5.5.2)
+ *
+ * Description:
+ * This function performs interpolation for two vertical 1/2-pel positions -
+ * (0, -1/2) and (0, 1/2) - around a full-pel position.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to top-left corner of block used to interpolate in the
+ * reconstructed frame plane
+ * iSrcStep - Step of the source buffer.
+ * iDstStep - Step of the destination (interpolation) buffer; must be a
+ * multiple of iWidth.
+ * iWidth - Width of the current block; must be equal to either 4, 8, or 16
+ * iHeight - Height of the current block; must be equal to either 4, 8, or 16
+ *
+ * Output Arguments:
+ *
+ * pDstUp -Pointer to the interpolation buffer of the -pel position above
+ * the current full-pel position (0, -1/2)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ * pDstDown -Pointer to the interpolation buffer of the -pel position below
+ * the current full-pel position (0, 1/2)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrc, pDstUp, or pDstDown
+ * - iWidth or iHeight have values other than 4, 8, or 16
+ * - iWidth==4 but pDstUp and/or pDstDown is/are not aligned on a 4-byte boundary
+ * - iWidth==8 but pDstUp and/or pDstDown is/are not aligned on a 8-byte boundary
+ * - iWidth==16 but pDstUp and/or pDstDown is/are not aligned on a 16-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InterpolateHalfVer_Luma (
+ const OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDstUp,
+ OMX_U8 *pDstDown,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_Average_4x (6.3.5.5.3)
+ *
+ * Description:
+ * This function calculates the average of two 4x4, 4x8 blocks. The result
+ * is rounded according to (a+b+1)/2.
+ *
+ * Input Arguments:
+ *
+ * pPred0 - Pointer to the top-left corner of reference block 0
+ * pPred1 - Pointer to the top-left corner of reference block 1
+ * iPredStep0 - Step of reference block 0; must be a multiple of 4.
+ * iPredStep1 - Step of reference block 1; must be a multiple of 4.
+ * iDstStep - Step of the destination buffer; must be a multiple of 4.
+ * iHeight - Height of the blocks; must be either 4 or 8.
+ *
+ * Output Arguments:
+ *
+ * pDstPred - Pointer to the destination buffer. 4-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pPred0, pPred1, or pDstPred
+ * - pDstPred is not aligned on a 4-byte boundary
+ * - iPredStep0 <= 0 or iPredStep0 is not a multiple of 4
+ * - iPredStep1 <= 0 or iPredStep1 is not a multiple of 4
+ * - iDstStep <= 0 or iDstStep is not a multiple of 4
+ * - iHeight is not equal to either 4 or 8
+ *
+ */
+OMXResult omxVCM4P10_Average_4x (
+ const OMX_U8 *pPred0,
+ const OMX_U8 *pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8 *pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_TransformQuant_ChromaDC (6.3.5.6.1)
+ *
+ * Description:
+ * This function performs 2x2 Hadamard transform of chroma DC coefficients
+ * and then quantizes the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the 2x2 array of chroma DC coefficients. 8-byte
+ * alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ * bIntra - Indicate whether this is an INTRA block. 1-INTRA, 0-INTER
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - Pointer to transformed and quantized coefficients. 8-byte
+ * alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcDst
+ * - pSrcDst is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_TransformQuant_ChromaDC (
+ OMX_S16 *pSrcDst,
+ OMX_U32 iQP,
+ OMX_U8 bIntra
+);
+
+
+
+/**
+ * Function: omxVCM4P10_TransformQuant_LumaDC (6.3.5.6.2)
+ *
+ * Description:
+ * This function performs a 4x4 Hadamard transform of luma DC coefficients
+ * and then quantizes the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the 4x4 array of luma DC coefficients. 16-byte
+ * alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - Pointer to transformed and quantized coefficients. 16-byte
+ * alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL: pSrcDst
+ * - pSrcDst is not aligned on an 16-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_TransformQuant_LumaDC (
+ OMX_S16 *pSrcDst,
+ OMX_U32 iQP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InvTransformDequant_LumaDC (6.3.5.6.3)
+ *
+ * Description:
+ * This function performs inverse 4x4 Hadamard transform and then dequantizes
+ * the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the 4x4 array of the 4x4 Hadamard-transformed and
+ * quantized coefficients. 16 byte alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to inverse-transformed and dequantized coefficients.
+ * 16-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL: pSrc
+ * - pSrc or pDst is not aligned on a 16-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InvTransformDequant_LumaDC (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst,
+ OMX_U32 iQP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InvTransformDequant_ChromaDC (6.3.5.6.4)
+ *
+ * Description:
+ * This function performs inverse 2x2 Hadamard transform and then dequantizes
+ * the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the 2x2 array of the 2x2 Hadamard-transformed and
+ * quantized coefficients. 8 byte alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to inverse-transformed and dequantized coefficients.
+ * 8-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL: pSrc
+ * - pSrc or pDst is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InvTransformDequant_ChromaDC (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst,
+ OMX_U32 iQP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InvTransformResidualAndAdd (6.3.5.7.1)
+ *
+ * Description:
+ * This function performs inverse an 4x4 integer transformation to produce
+ * the difference signal and then adds the difference to the prediction to get
+ * the reconstructed signal.
+ *
+ * Input Arguments:
+ *
+ * pSrcPred - Pointer to prediction signal. 4-byte alignment required.
+ * pDequantCoeff - Pointer to the transformed coefficients. 8-byte
+ * alignment required.
+ * iSrcPredStep - Step of the prediction buffer; must be a multiple of 4.
+ * iDstReconStep - Step of the destination reconstruction buffer; must be a
+ * multiple of 4.
+ * bAC - Indicate whether there is AC coefficients in the coefficients
+ * matrix.
+ *
+ * Output Arguments:
+ *
+ * pDstRecon -Pointer to the destination reconstruction buffer. 4-byte
+ * alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcPred, pDequantCoeff, pDstRecon
+ * - pSrcPred is not aligned on a 4-byte boundary
+ * - iSrcPredStep or iDstReconStep is not a multiple of 4.
+ * - pDequantCoeff is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InvTransformResidualAndAdd (
+ const OMX_U8 *pSrcPred,
+ const OMX_S16 *pDequantCoeff,
+ OMX_U8 *pDstRecon,
+ OMX_U32 iSrcPredStep,
+ OMX_U32 iDstReconStep,
+ OMX_U8 bAC
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SubAndTransformQDQResidual (6.3.5.8.1)
+ *
+ * Description:
+ * This function subtracts the prediction signal from the original signal to
+ * produce the difference signal and then performs a 4x4 integer transform and
+ * quantization. The quantized transformed coefficients are stored as
+ * pDstQuantCoeff. This function can also output dequantized coefficients or
+ * unquantized DC coefficients optionally by setting the pointers
+ * pDstDeQuantCoeff, pDCCoeff.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to original signal. 4-byte alignment required.
+ * pSrcPred - Pointer to prediction signal. 4-byte alignment required.
+ * iSrcOrgStep - Step of the original signal buffer; must be a multiple of
+ * 4.
+ * iSrcPredStep - Step of the prediction signal buffer; must be a multiple
+ * of 4.
+ * pNumCoeff -Number of non-zero coefficients after quantization. If this
+ * parameter is not required, it is set to NULL.
+ * nThreshSAD - Zero-block early detection threshold. If this parameter is
+ * not required, it is set to 0.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ * bIntra - Indicates whether this is an INTRA block, either 1-INTRA or
+ * 0-INTER
+ *
+ * Output Arguments:
+ *
+ * pDstQuantCoeff - Pointer to the quantized transformed coefficients.
+ * 8-byte alignment required.
+ * pDstDeQuantCoeff - Pointer to the dequantized transformed coefficients
+ * if this parameter is not equal to NULL. 8-byte alignment
+ * required.
+ * pDCCoeff - Pointer to the unquantized DC coefficient if this parameter
+ * is not equal to NULL.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pSrcPred, pNumCoeff, pDstQuantCoeff,
+ * pDstDeQuantCoeff, pDCCoeff
+ * - pSrcOrg is not aligned on a 4-byte boundary
+ * - pSrcPred is not aligned on a 4-byte boundary
+ * - iSrcOrgStep is not a multiple of 4
+ * - iSrcPredStep is not a multiple of 4
+ * - pDstQuantCoeff or pDstDeQuantCoeff is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_SubAndTransformQDQResidual (
+ const OMX_U8 *pSrcOrg,
+ const OMX_U8 *pSrcPred,
+ OMX_U32 iSrcOrgStep,
+ OMX_U32 iSrcPredStep,
+ OMX_S16 *pDstQuantCoeff,
+ OMX_S16 *pDstDeQuantCoeff,
+ OMX_S16 *pDCCoeff,
+ OMX_S8 *pNumCoeff,
+ OMX_U32 nThreshSAD,
+ OMX_U32 iQP,
+ OMX_U8 bIntra
+);
+
+
+
+/**
+ * Function: omxVCM4P10_GetVLCInfo (6.3.5.9.1)
+ *
+ * Description:
+ * This function extracts run-length encoding (RLE) information from the
+ * coefficient matrix. The results are returned in an OMXVCM4P10VLCInfo
+ * structure.
+ *
+ * Input Arguments:
+ *
+ * pSrcCoeff - pointer to the transform coefficient matrix. 8-byte
+ * alignment required.
+ * pScanMatrix - pointer to the scan order definition matrix. For a luma
+ * block the scan matrix should follow [ISO14496-10] section 8.5.4,
+ * and should contain the values 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13,
+ * 10, 7, 11, 14, 15. For a chroma block, the scan matrix should
+ * contain the values 0, 1, 2, 3.
+ * bAC - indicates presence of a DC coefficient; 0 = DC coefficient
+ * present, 1= DC coefficient absent.
+ * MaxNumCoef - specifies the number of coefficients contained in the
+ * transform coefficient matrix, pSrcCoeff. The value should be 16
+ * for blocks of type LUMADC, LUMAAC, LUMALEVEL, and CHROMAAC. The
+ * value should be 4 for blocks of type CHROMADC.
+ *
+ * Output Arguments:
+ *
+ * pDstVLCInfo - pointer to structure that stores information for
+ * run-length coding.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcCoeff, pScanMatrix, pDstVLCInfo
+ * - pSrcCoeff is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_GetVLCInfo (
+ const OMX_S16 *pSrcCoeff,
+ const OMX_U8 *pScanMatrix,
+ OMX_U8 bAC,
+ OMX_U32 MaxNumCoef,
+ OMXVCM4P10VLCInfo*pDstVLCInfo
+);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** end of #define _OMXVC_H_ */
+
+/** EOF */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/omxVC_s.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/omxVC_s.h
new file mode 100755
index 0000000..89f3040
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/api/omxVC_s.h
@@ -0,0 +1,129 @@
+;/******************************************************************************
+;// Copyright (c) 1999-2005 The Khronos Group Inc. All Rights Reserved
+;//
+;//
+;//
+;//
+;//
+;//
+;//
+;//
+;******************************************************************************/
+
+;/** =============== Structure Definition for Sample Generation ============== */
+;/** transparent status */
+
+;enum {
+OMX_VIDEO_TRANSPARENT EQU 0; /** Wholly transparent */
+OMX_VIDEO_PARTIAL EQU 1; /** Partially transparent */
+OMX_VIDEO_OPAQUE EQU 2; /** Opaque */
+;}
+
+;/** direction */
+;enum {
+OMX_VIDEO_NONE EQU 0;
+OMX_VIDEO_HORIZONTAL EQU 1;
+OMX_VIDEO_VERTICAL EQU 2;
+;}
+
+;/** bilinear interpolation type */
+;enum {
+OMX_VIDEO_INTEGER_PIXEL EQU 0; /** case a */
+OMX_VIDEO_HALF_PIXEL_X EQU 1; /** case b */
+OMX_VIDEO_HALF_PIXEL_Y EQU 2; /** case c */
+OMX_VIDEO_HALF_PIXEL_XY EQU 3; /** case d */
+;}
+
+;enum {
+OMX_UPPER EQU 1; /** set if the above macroblock is available */
+OMX_LEFT EQU 2; /** set if the left macroblock is available */
+OMX_CENTER EQU 4;
+OMX_RIGHT EQU 8;
+OMX_LOWER EQU 16;
+OMX_UPPER_LEFT EQU 32; /** set if the above-left macroblock is available */
+OMX_UPPER_RIGHT EQU 64; /** set if the above-right macroblock is available */
+OMX_LOWER_LEFT EQU 128;
+OMX_LOWER_RIGHT EQU 256
+;}
+
+;enum {
+OMX_VIDEO_LUMINANCE EQU 0; /** Luminance component */
+OMX_VIDEO_CHROMINANCE EQU 1; /** chrominance component */
+OMX_VIDEO_ALPHA EQU 2; /** Alpha component */
+;}
+
+;enum {
+OMX_VIDEO_INTER EQU 0; /** P picture or P-VOP */
+OMX_VIDEO_INTER_Q EQU 1; /** P picture or P-VOP */
+OMX_VIDEO_INTER4V EQU 2; /** P picture or P-VOP */
+OMX_VIDEO_INTRA EQU 3; /** I and P picture; I- and P-VOP */
+OMX_VIDEO_INTRA_Q EQU 4; /** I and P picture; I- and P-VOP */
+OMX_VIDEO_INTER4V_Q EQU 5; /** P picture or P-VOP (H.263)*/
+OMX_VIDEO_DIRECT EQU 6; /** B picture or B-VOP (MPEG-4 only) */
+OMX_VIDEO_INTERPOLATE EQU 7; /** B picture or B-VOP */
+OMX_VIDEO_BACKWARD EQU 8; /** B picture or B-VOP */
+OMX_VIDEO_FORWARD EQU 9; /** B picture or B-VOP */
+OMX_VIDEO_NOTCODED EQU 10; /** B picture or B-VOP */
+;}
+
+;enum {
+OMX_16X16_VERT EQU 0; /** Intra_16x16_Vertical (prediction mode) */
+OMX_16X16_HOR EQU 1; /** Intra_16x16_Horizontal (prediction mode) */
+OMX_16X16_DC EQU 2; /** Intra_16x16_DC (prediction mode) */
+OMX_16X16_PLANE EQU 3; /** Intra_16x16_Plane (prediction mode) */
+;}
+
+;enum {
+OMX_4x4_VERT EQU 0; /** Intra_4x4_Vertical (prediction mode) */
+OMX_4x4_HOR EQU 1; /** Intra_4x4_Horizontal (prediction mode) */
+OMX_4x4_DC EQU 2; /** Intra_4x4_DC (prediction mode) */
+OMX_4x4_DIAG_DL EQU 3; /** Intra_4x4_Diagonal_Down_Left (prediction mode) */
+OMX_4x4_DIAG_DR EQU 4; /** Intra_4x4_Diagonal_Down_Right (prediction mode) */
+OMX_4x4_VR EQU 5; /** Intra_4x4_Vertical_Right (prediction mode) */
+OMX_4x4_HD EQU 6; /** Intra_4x4_Horizontal_Down (prediction mode) */
+OMX_4x4_VL EQU 7; /** Intra_4x4_Vertical_Left (prediction mode) */
+OMX_4x4_HU EQU 8; /** Intra_4x4_Horizontal_Up (prediction mode) */
+;}
+
+;enum {
+OMX_CHROMA_DC EQU 0; /** Intra_Chroma_DC (prediction mode) */
+OMX_CHROMA_HOR EQU 1; /** Intra_Chroma_Horizontal (prediction mode) */
+OMX_CHROMA_VERT EQU 2; /** Intra_Chroma_Vertical (prediction mode) */
+OMX_CHROMA_PLANE EQU 3; /** Intra_Chroma_Plane (prediction mode) */
+;}
+
+;typedef struct {
+x EQU 0;
+y EQU 4;
+;}OMXCoordinate;
+
+;typedef struct {
+dx EQU 0;
+dy EQU 2;
+;}OMXMotionVector;
+
+;typedef struct {
+xx EQU 0;
+yy EQU 4;
+width EQU 8;
+height EQU 12;
+;}OMXiRect;
+
+;typedef enum {
+OMX_VC_INTER EQU 0; /** P picture or P-VOP */
+OMX_VC_INTER_Q EQU 1; /** P picture or P-VOP */
+OMX_VC_INTER4V EQU 2; /** P picture or P-VOP */
+OMX_VC_INTRA EQU 3; /** I and P picture, I- and P-VOP */
+OMX_VC_INTRA_Q EQU 4; /** I and P picture, I- and P-VOP */
+OMX_VC_INTER4V_Q EQU 5; /** P picture or P-VOP (H.263)*/
+;} OMXVCM4P2MacroblockType;
+
+;enum {
+OMX_VC_NONE EQU 0
+OMX_VC_HORIZONTAL EQU 1
+OMX_VC_VERTICAL EQU 2
+;};
+
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_Copy16x16_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_Copy16x16_s.s
new file mode 100755
index 0000000..296d59d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_Copy16x16_s.s
@@ -0,0 +1,95 @@
+ ;/**
+ ; * Function: omxVCCOMM_Copy16x16
+ ; *
+ ; * Description:
+ ; * Copies the reference 16x16 block to the current block.
+ ; * Parameters:
+ ; * [in] pSrc - pointer to the reference block in the source frame; must be aligned on an 16-byte boundary.
+ ; * [in] step - distance between the starts of consecutive lines in the reference frame, in bytes;
+ ; * must be a multiple of 16 and must be larger than or equal to 16.
+ ; * [out] pDst - pointer to the destination block; must be aligned on an 8-byte boundary.
+ ; * Return Value:
+ ; * OMX_Sts_NoErr - no error
+ ; * OMX_Sts_BadArgErr - bad arguments; returned under any of the following conditions:
+ ; * - one or more of the following pointers is NULL: pSrc, pDst
+ ; * - one or more of the following pointers is not aligned on an 16-byte boundary: pSrc, pDst
+ ; * - step <16 or step is not a multiple of 16.
+ ; */
+
+ INCLUDE omxtypes_s.h
+
+
+ M_VARIANTS CortexA8
+
+ IF CortexA8
+
+
+ ;//Input Arguments
+pSrc RN 0
+pDst RN 1
+step RN 2
+
+;//Local Variables
+Return RN 0
+;// Neon Registers
+
+X0 DN D0.S8
+X1 DN D1.S8
+X2 DN D2.S8
+X3 DN D3.S8
+X4 DN D4.S8
+X5 DN D5.S8
+X6 DN D6.S8
+X7 DN D7.S8
+
+ M_START omxVCCOMM_Copy16x16
+
+
+ VLD1 {X0,X1},[pSrc@128],step ;// Load 16 bytes from 16 byte aligned pSrc and pSrc=pSrc + step after loading
+ VLD1 {X2,X3},[pSrc@128],step
+ VLD1 {X4,X5},[pSrc@128],step
+ VLD1 {X6,X7},[pSrc@128],step
+
+ VST1 {X0,X1,X2,X3},[pDst@128]! ;// Store 32 bytes to 16 byte aligned pDst
+ VST1 {X4,X5,X6,X7},[pDst@128]!
+
+
+ VLD1 {X0,X1},[pSrc@128],step
+ VLD1 {X2,X3},[pSrc@128],step
+ VLD1 {X4,X5},[pSrc@128],step
+ VLD1 {X6,X7},[pSrc@128],step
+
+ VST1 {X0,X1,X2,X3},[pDst@128]!
+ VST1 {X4,X5,X6,X7},[pDst@128]!
+
+
+ VLD1 {X0,X1},[pSrc@128],step
+ VLD1 {X2,X3},[pSrc@128],step
+ VLD1 {X4,X5},[pSrc@128],step
+ VLD1 {X6,X7},[pSrc@128],step
+
+ VST1 {X0,X1,X2,X3},[pDst@128]!
+ VST1 {X4,X5,X6,X7},[pDst@128]!
+
+
+ VLD1 {X0,X1},[pSrc@128],step
+ VLD1 {X2,X3},[pSrc@128],step
+ VLD1 {X4,X5},[pSrc@128],step
+ VLD1 {X6,X7},[pSrc@128],step
+
+ VST1 {X0,X1,X2,X3},[pDst@128]!
+ VST1 {X4,X5,X6,X7},[pDst@128]!
+
+
+ MOV Return,#OMX_Sts_NoErr
+
+
+
+ M_END
+ ENDIF
+
+
+
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_Copy8x8_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_Copy8x8_s.s
new file mode 100755
index 0000000..db9e5ef
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_Copy8x8_s.s
@@ -0,0 +1,70 @@
+ ;/**
+ ; * Function: omxVCCOMM_Copy8x8
+ ; *
+ ; * Description:
+ ; * Copies the reference 8x8 block to the current block.
+ ; * Parameters:
+ ; * [in] pSrc - pointer to the reference block in the source frame; must be aligned on an 8-byte boundary.
+ ; * [in] step - distance between the starts of consecutive lines in the reference frame, in bytes;
+ ; * must be a multiple of 8 and must be larger than or equal to 8.
+ ; * [out] pDst - pointer to the destination block; must be aligned on an 8-byte boundary.
+ ; * Return Value:
+ ; * OMX_Sts_NoErr - no error
+ ; * OMX_Sts_BadArgErr - bad arguments; returned under any of the following conditions:
+ ; * - one or more of the following pointers is NULL: pSrc, pDst
+ ; * - one or more of the following pointers is not aligned on an 8-byte boundary: pSrc, pDst
+ ; * - step <8 or step is not a multiple of 8.
+ ; */
+
+ INCLUDE omxtypes_s.h
+
+
+ M_VARIANTS CortexA8
+
+ IF CortexA8
+
+
+ ;//Input Arguments
+pSrc RN 0
+pDst RN 1
+step RN 2
+
+;//Local Variables
+Count RN 3
+Return RN 0
+;// Neon Registers
+
+X0 DN D0.S8
+X1 DN D1.S8
+X2 DN D2.S8
+X3 DN D3.S8
+ M_START omxVCCOMM_Copy8x8
+
+
+
+ VLD1 {X0},[pSrc],step ;// Load 8 bytes from 8 byte aligned pSrc, pSrc=pSrc+step after load
+ VLD1 {X1},[pSrc],step
+ VLD1 {X2},[pSrc],step
+ VLD1 {X3},[pSrc],step
+
+ VST1 {X0,X1},[pDst]! ;// Store 16 bytes to 8 byte aligned pDst
+ VST1 {X2,X3},[pDst]!
+
+ VLD1 {X0},[pSrc],step
+ VLD1 {X1},[pSrc],step
+ VLD1 {X2},[pSrc],step
+ VLD1 {X3},[pSrc],step
+
+ VST1 {X0,X1},[pDst]!
+ VST1 {X2,X3},[pDst]!
+
+ MOV Return,#OMX_Sts_NoErr
+
+ M_END
+ ENDIF
+
+
+
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
new file mode 100755
index 0000000..5c5b7d8
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/comm/src/omxVCCOMM_ExpandFrame_I_s.s
@@ -0,0 +1,236 @@
+;//
+;//
+;// File Name: omxVCCOMM_ExpandFrame_I_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// Description:
+;// This function will Expand Frame boundary pixels into Plane
+;//
+;//
+
+;// Include standard headers
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+;// Import symbols required from other files
+;// (For example tables)
+
+
+;// Set debugging level
+DEBUG_ON SETL {FALSE}
+
+
+
+ IF CortexA8
+
+ M_START omxVCCOMM_ExpandFrame_I,r11
+
+;//Input registers
+
+pSrcDstPlane RN 0
+iFrameWidth RN 1
+iFrameHeight RN 2
+iExpandPels RN 3
+iPlaneStep RN 4
+pTop RN 5
+pBot RN 6
+pDstTop RN 7
+pDstBot RN 8
+pLeft RN 5
+pRight RN 6
+pDstLeft RN 9
+pDstRight RN 10
+Offset RN 11
+Temp RN 14
+Counter RN 12
+Tmp RN 7
+;//Output registers
+
+result RN 0
+;// Neon registers
+qData0 QN 0.U8
+qData1 QN 1.U8
+dData0 DN 0.U8
+dData1 DN 1.U8
+dData2 DN 2.U8
+dData3 DN 3.U8
+
+ ;// Define stack arguments
+ M_ARG pPlaneStep, 4
+
+ ;// Load argument from the stack
+ M_LDR iPlaneStep, pPlaneStep
+
+ SUB pTop, pSrcDstPlane, #0 ;// Top row pointer of the frame
+ MUL Offset, iExpandPels, iPlaneStep ;// E*Step
+ SUB Temp, iFrameHeight, #1 ;// H-1
+ MUL Temp, iPlaneStep, Temp ;// (H-1)*Step
+ ADD pBot, Temp, pSrcDstPlane ;// BPtr = TPtr + (H-1)*Step
+ MOV Temp, iFrameWidth ;// Outer loop counter
+
+ ;// Check if pSrcDstPlane and iPlaneStep are 16 byte aligned
+ TST pSrcDstPlane, #0xf
+ TSTEQ iPlaneStep, #0xf
+ BNE Hor8Loop00
+
+ ;//
+ ;// Copy top and bottom region of the plane as follows
+ ;// top region = top row elements from the frame
+ ;// bottom region = last row elements from the frame
+ ;//
+
+ ;// Case for 16 byte alignment
+Hor16Loop00
+ SUB pDstTop, pTop, Offset
+ VLD1 qData0, [pTop @128]!
+ MOV Counter, iExpandPels ;// Inner loop counter
+ ADD pDstBot, pBot, iPlaneStep
+ VLD1 qData1, [pBot @128]!
+Ver16Loop0
+ VST1 qData0, [pDstTop @128], iPlaneStep
+ VST1 qData0, [pDstTop @128], iPlaneStep
+ VST1 qData0, [pDstTop @128], iPlaneStep
+ VST1 qData0, [pDstTop @128], iPlaneStep
+ VST1 qData0, [pDstTop @128], iPlaneStep
+ VST1 qData0, [pDstTop @128], iPlaneStep
+ VST1 qData0, [pDstTop @128], iPlaneStep
+ VST1 qData0, [pDstTop @128], iPlaneStep
+ SUBS Counter, Counter, #8
+ VST1 qData1, [pDstBot @128], iPlaneStep
+ VST1 qData1, [pDstBot @128], iPlaneStep
+ VST1 qData1, [pDstBot @128], iPlaneStep
+ VST1 qData1, [pDstBot @128], iPlaneStep
+ VST1 qData1, [pDstBot @128], iPlaneStep
+ VST1 qData1, [pDstBot @128], iPlaneStep
+ VST1 qData1, [pDstBot @128], iPlaneStep
+ VST1 qData1, [pDstBot @128], iPlaneStep
+ BGT Ver16Loop0
+
+ SUBS Temp, Temp, #16
+ BGT Hor16Loop00
+ B EndAlignedLoop
+
+ ;// Case for 8 byte alignment
+Hor8Loop00
+ SUB pDstTop, pTop, Offset
+ VLD1 qData0, [pTop @64]!
+ MOV Counter, iExpandPels ;// Inner loop counter
+ ADD pDstBot, pBot, iPlaneStep
+ VLD1 qData1, [pBot @64]!
+Ver8Loop0
+ VST1 qData0, [pDstTop @64], iPlaneStep
+ VST1 qData0, [pDstTop @64], iPlaneStep
+ VST1 qData0, [pDstTop @64], iPlaneStep
+ VST1 qData0, [pDstTop @64], iPlaneStep
+ VST1 qData0, [pDstTop @64], iPlaneStep
+ VST1 qData0, [pDstTop @64], iPlaneStep
+ VST1 qData0, [pDstTop @64], iPlaneStep
+ VST1 qData0, [pDstTop @64], iPlaneStep
+ SUBS Counter, Counter, #8
+ VST1 qData1, [pDstBot @64], iPlaneStep
+ VST1 qData1, [pDstBot @64], iPlaneStep
+ VST1 qData1, [pDstBot @64], iPlaneStep
+ VST1 qData1, [pDstBot @64], iPlaneStep
+ VST1 qData1, [pDstBot @64], iPlaneStep
+ VST1 qData1, [pDstBot @64], iPlaneStep
+ VST1 qData1, [pDstBot @64], iPlaneStep
+ VST1 qData1, [pDstBot @64], iPlaneStep
+ BGT Ver8Loop0
+
+ SUBS Temp, Temp, #16
+ BGT Hor8Loop00
+
+EndAlignedLoop
+ ADD Temp, pSrcDstPlane, iFrameWidth
+ SUB pDstRight, Temp, Offset
+ SUB pRight, Temp, #1
+ SUB pDstLeft, pSrcDstPlane, Offset
+ SUB pDstLeft, pDstLeft, iExpandPels
+ ADD pLeft, pSrcDstPlane, #0
+
+ VLD1 {dData0 []}, [pLeft], iPlaneStep ;// Top-Left corner pixel from frame duplicated in dData0
+ SUB Offset, iPlaneStep, iExpandPels
+ VLD1 {dData1 []}, [pRight], iPlaneStep ;// Top-Right corner pixel from frame duplicated in dData1
+ MOV Temp, iExpandPels
+
+ ;//
+ ;// Copy top-left and top-right region of the plane as follows
+ ;// top-left region = top-left corner pixel from the frame
+ ;// top-right region = top-right corner pixel from the frame
+ ;//
+HorLoop11
+ MOV Counter, iExpandPels
+VerLoop1
+ VST1 dData0, [pDstLeft], #8
+ SUBS Counter, Counter, #8
+ VST1 dData1, [pDstRight], #8
+ BGT VerLoop1
+
+ SUBS Temp, Temp, #1
+ ADD pDstLeft, pDstLeft, Offset
+ ADD pDstRight, pDstRight, Offset
+ BPL HorLoop11
+
+ SUB iFrameHeight, iFrameHeight, #1
+ ;//
+ ;// Copy left and right region of the plane as follows
+ ;// Left region = copy the row with left start pixel from the frame
+ ;// Right region = copy the row with right end pixel from the frame
+ ;//
+HorLoop22
+ VLD1 {dData0 []}, [pLeft], iPlaneStep
+ MOV Counter, iExpandPels
+ VLD1 {dData1 []}, [pRight], iPlaneStep
+VerLoop2
+ VST1 dData0, [pDstLeft], #8
+ SUBS Counter, Counter, #8
+ VST1 dData1, [pDstRight], #8
+ BGT VerLoop2
+
+ SUBS iFrameHeight, iFrameHeight, #1
+ ADD pDstLeft, pDstLeft, Offset
+ ADD pDstRight, pDstRight, Offset
+ BGT HorLoop22
+
+ MOV Temp, iExpandPels
+ ;//
+ ;// Copy bottom-left and bottom-right region of the plane as follows
+ ;// bottom-left region = bottom-left corner pixel from the frame
+ ;// bottom-right region = bottom-right corner pixel from the frame
+ ;//
+HorLoop33
+ MOV Counter, iExpandPels
+VerLoop3
+ VST1 dData0, [pDstLeft], #8
+ SUBS Counter, Counter, #8
+ VST1 dData1, [pDstRight], #8
+ BGT VerLoop3
+
+ SUBS Temp, Temp, #1
+ ADD pDstLeft, pDstLeft, Offset
+ ADD pDstRight, pDstRight, Offset
+ BGT HorLoop33
+End
+ MOV r0, #OMX_Sts_NoErr
+
+ M_END
+
+ ENDIF
+
+
+
+
+;// Guarding implementation by the processor name
+
+
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/api/armVCM4P10_CAVLCTables.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/api/armVCM4P10_CAVLCTables.h
new file mode 100755
index 0000000..547a2d9
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/api/armVCM4P10_CAVLCTables.h
@@ -0,0 +1,30 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_CAVLCTables.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Header file for optimized H.264 CALVC tables
+ *
+ */
+
+#ifndef ARMVCM4P10_CAVLCTABLES_H
+#define ARMVCM4P10_CAVLCTABLES_H
+
+/* CAVLC tables */
+
+extern const OMX_U16 *armVCM4P10_CAVLCCoeffTokenTables[18];
+extern const OMX_U16 *armVCM4P10_CAVLCTotalZeroTables[15];
+extern const OMX_U16 *armVCM4P10_CAVLCTotalZeros2x2Tables[3];
+extern const OMX_U16 *armVCM4P10_CAVLCRunBeforeTables[15];
+extern const OMX_U8 armVCM4P10_ZigZag_4x4[16];
+extern const OMX_U8 armVCM4P10_ZigZag_2x2[4];
+extern const OMX_S8 armVCM4P10_SuffixToLevel[7];
+
+#endif
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
new file mode 100755
index 0000000..4f0892d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Average_4x_Align_unsafe_s.s
@@ -0,0 +1,222 @@
+;//
+;//
+;// File Name: armVCM4P10_Average_4x_Align_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+;// Functions:
+;// armVCM4P10_Average_4x4_Align<ALIGNMENT>_unsafe
+;//
+;// Implements Average of 4x4 with equation c = (a+b+1)>>1.
+;// First operand will be at offset ALIGNMENT from aligned address
+;// Second operand will be at aligned location and will be used as output.
+;// destination pointed by (pDst) for vertical interpolation.
+;// This function needs to copy 4 bytes in horizontal direction
+;//
+;// Registers used as input for this function
+;// r0,r1,r2,r3 where r2 containings aligned memory pointer and r3 step size
+;//
+;// Registers preserved for top level function
+;// r4,r5,r6,r8,r9,r14
+;//
+;// Registers modified by the function
+;// r7,r10,r11,r12
+;//
+;// Output registers
+;// r2 - pointer to the aligned location
+;// r3 - step size to this aligned location
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ EXPORT armVCM4P10_Average_4x4_Align0_unsafe
+ EXPORT armVCM4P10_Average_4x4_Align2_unsafe
+ EXPORT armVCM4P10_Average_4x4_Align3_unsafe
+
+DEBUG_ON SETL {FALSE}
+
+;// Declare input registers
+pPred0 RN 0
+iPredStep0 RN 1
+pPred1 RN 2
+iPredStep1 RN 3
+pDstPred RN 2
+iDstStep RN 3
+
+;// Declare other intermediate registers
+iPredA0 RN 10
+iPredA1 RN 11
+iPredB0 RN 12
+iPredB1 RN 14
+Temp1 RN 4
+Temp2 RN 5
+ResultA RN 5
+ResultB RN 4
+r0x80808080 RN 7
+
+ IF ARM1136JS
+
+ ;// This function calculates average of 4x4 block
+ ;// pPred0 is at alignment offset 0 and pPred1 is alignment 4
+
+ ;// Function header
+ M_START armVCM4P10_Average_4x4_Align0_unsafe, r6
+
+ ;// Code start
+ LDR r0x80808080, =0x80808080
+
+ ;// 1st load
+ M_LDR iPredB0, [pPred1]
+ M_LDR iPredA0, [pPred0], iPredStep0
+ M_LDR iPredB1, [pPred1, iPredStep1]
+ M_LDR iPredA1, [pPred0], iPredStep0
+
+ ;// (a+b+1)/2 = (a+256-(255-b))/2 = (a-(255-b))/2 + 128
+ MVN iPredB0, iPredB0
+ MVN iPredB1, iPredB1
+ UHSUB8 ResultA, iPredA0, iPredB0
+ UHSUB8 ResultB, iPredA1, iPredB1
+ EOR ResultA, ResultA, r0x80808080
+ M_STR ResultA, [pDstPred], iDstStep
+ EOR ResultB, ResultB, r0x80808080
+ M_STR ResultB, [pDstPred], iDstStep
+
+ ;// 2nd load
+ M_LDR iPredA0, [pPred0], iPredStep0
+ M_LDR iPredB0, [pPred1]
+ M_LDR iPredA1, [pPred0], iPredStep0
+ M_LDR iPredB1, [pPred1, iPredStep1]
+
+ MVN iPredB0, iPredB0
+ UHSUB8 ResultA, iPredA0, iPredB0
+ MVN iPredB1, iPredB1
+ UHSUB8 ResultB, iPredA1, iPredB1
+ EOR ResultA, ResultA, r0x80808080
+ M_STR ResultA, [pDstPred], iDstStep
+ EOR ResultB, ResultB, r0x80808080
+ M_STR ResultB, [pDstPred], iDstStep
+End0
+ M_END
+
+ ;// This function calculates average of 4x4 block
+ ;// pPred0 is at alignment offset 2 and pPred1 is alignment 4
+
+ ;// Function header
+ M_START armVCM4P10_Average_4x4_Align2_unsafe, r6
+
+ ;// Code start
+ LDR r0x80808080, =0x80808080
+
+ ;// 1st load
+ LDR Temp1, [pPred0, #4]
+ M_LDR iPredA0, [pPred0], iPredStep0
+ M_LDR iPredB0, [pPred1]
+ M_LDR iPredB1, [pPred1, iPredStep1]
+ M_LDR Temp2, [pPred0, #4]
+ M_LDR iPredA1, [pPred0], iPredStep0
+ MVN iPredB0, iPredB0
+ MVN iPredB1, iPredB1
+ MOV iPredA0, iPredA0, LSR #16
+ ORR iPredA0, iPredA0, Temp1, LSL #16
+ MOV iPredA1, iPredA1, LSR #16
+ ORR iPredA1, iPredA1, Temp2, LSL #16
+
+ ;// (a+b+1)/2 = (a+256-(255-b))/2 = (a-(255-b))/2 + 128
+ UHSUB8 ResultA, iPredA0, iPredB0
+ UHSUB8 ResultB, iPredA1, iPredB1
+ EOR ResultA, ResultA, r0x80808080
+ M_STR ResultA, [pDstPred], iDstStep
+ EOR ResultB, ResultB, r0x80808080
+ M_STR ResultB, [pDstPred], iDstStep
+
+ ;// 2nd load
+ LDR Temp1, [pPred0, #4]
+ M_LDR iPredA0, [pPred0], iPredStep0
+ LDR iPredB0, [pPred1]
+ LDR iPredB1, [pPred1, iPredStep1]
+ LDR Temp2, [pPred0, #4]
+ M_LDR iPredA1, [pPred0], iPredStep0
+ MVN iPredB0, iPredB0
+ MVN iPredB1, iPredB1
+ MOV iPredA0, iPredA0, LSR #16
+ ORR iPredA0, iPredA0, Temp1, LSL #16
+ MOV iPredA1, iPredA1, LSR #16
+ ORR iPredA1, iPredA1, Temp2, LSL #16
+
+ UHSUB8 ResultA, iPredA0, iPredB0
+ UHSUB8 ResultB, iPredA1, iPredB1
+ EOR ResultA, ResultA, r0x80808080
+ M_STR ResultA, [pDstPred], iDstStep
+ EOR ResultB, ResultB, r0x80808080
+ M_STR ResultB, [pDstPred], iDstStep
+End2
+ M_END
+
+
+ ;// This function calculates average of 4x4 block
+ ;// pPred0 is at alignment offset 3 and pPred1 is alignment 4
+
+ ;// Function header
+ M_START armVCM4P10_Average_4x4_Align3_unsafe, r6
+
+ ;// Code start
+ LDR r0x80808080, =0x80808080
+
+ ;// 1st load
+ LDR Temp1, [pPred0, #4]
+ M_LDR iPredA0, [pPred0], iPredStep0
+ LDR iPredB0, [pPred1]
+ LDR iPredB1, [pPred1, iPredStep1]
+ LDR Temp2, [pPred0, #4]
+ M_LDR iPredA1, [pPred0], iPredStep0
+
+ MVN iPredB0, iPredB0
+ MVN iPredB1, iPredB1
+ MOV iPredA0, iPredA0, LSR #24
+ ORR iPredA0, iPredA0, Temp1, LSL #8
+ MOV iPredA1, iPredA1, LSR #24
+ ORR iPredA1, iPredA1, Temp2, LSL #8
+ UHSUB8 ResultA, iPredA0, iPredB0
+ UHSUB8 ResultB, iPredA1, iPredB1
+ EOR ResultA, ResultA, r0x80808080
+ M_STR ResultA, [pDstPred], iDstStep
+ EOR ResultB, ResultB, r0x80808080
+ M_STR ResultB, [pDstPred], iDstStep
+
+ ;// 2nd load
+ LDR Temp1, [pPred0, #4]
+ M_LDR iPredA0, [pPred0], iPredStep0
+ LDR iPredB0, [pPred1]
+ LDR iPredB1, [pPred1, iPredStep1]
+ LDR Temp2, [pPred0, #4]
+ M_LDR iPredA1, [pPred0], iPredStep0
+
+ MVN iPredB0, iPredB0
+ MVN iPredB1, iPredB1
+ MOV iPredA0, iPredA0, LSR #24
+ ORR iPredA0, iPredA0, Temp1, LSL #8
+ MOV iPredA1, iPredA1, LSR #24
+ ORR iPredA1, iPredA1, Temp2, LSL #8
+
+ UHSUB8 ResultA, iPredA0, iPredB0
+ UHSUB8 ResultB, iPredA1, iPredB1
+ EOR ResultA, ResultA, r0x80808080
+ M_STR ResultA, [pDstPred], iDstStep
+ EOR ResultB, ResultB, r0x80808080
+ M_STR ResultB, [pDstPred], iDstStep
+End3
+ M_END
+
+ ENDIF
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_CAVLCTables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_CAVLCTables.c
new file mode 100755
index 0000000..137495d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_CAVLCTables.c
@@ -0,0 +1,327 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_CAVLCTables.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Optimized CAVLC tables for H.264
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armVCM4P10_CAVLCTables.h"
+
+/* 4x4 DeZigZag table */
+
+const OMX_U8 armVCM4P10_ZigZag_4x4[16] =
+{
+ 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
+};
+
+/* 2x2 DeZigZag table */
+
+const OMX_U8 armVCM4P10_ZigZag_2x2[4] =
+{
+ 0, 1, 2, 3
+};
+
+
+/*
+ * Suffix To Level table
+ * We increment the suffix length if
+ * ((LevelCode>>1)+1)>(3<<(SuffixLength-1)) && SuffixLength<6
+ * (LevelCode>>1)>=(3<<(SuffixLength-1)) && SuffixLength<6
+ * LevelCode >= 3<<SuffixLength && SuffixLength<6
+ * (LevelCode+2) >= (3<<SuffixLength)+2 && SuffixLength<6
+ */
+const OMX_S8 armVCM4P10_SuffixToLevel[7] =
+{
+ (3<<1)+2, /* SuffixLength=1 */
+ (3<<1)+2, /* SuffixLength=1 */
+ (3<<2)+2, /* SuffixLength=2 */
+ (3<<3)+2, /* SuffixLength=3 */
+ (3<<4)+2, /* SuffixLength=4 */
+ (3<<5)+2, /* SuffixLength=5 */
+ -1 /* SuffixLength=6 - never increment */
+};
+
+static const OMX_U16 armVCM4P10_CAVLCCoeffTokenTables_0[132] = {
+ 0x0020, 0x0100, 0x2015, 0x2015, 0x400b, 0x400b, 0x400b, 0x400b,
+ 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001,
+ 0x0028, 0x00f0, 0x00f8, 0x0027, 0x0030, 0x00d8, 0x00e0, 0x00e8,
+ 0x0038, 0x00a0, 0x00c8, 0x00d0, 0x0040, 0x0068, 0x0090, 0x0098,
+ 0x0048, 0x0050, 0x0058, 0x0060, 0x27ff, 0x27ff, 0x206b, 0x206b,
+ 0x0081, 0x0085, 0x0083, 0x0079, 0x0087, 0x007d, 0x007b, 0x0071,
+ 0x007f, 0x0075, 0x0073, 0x0069, 0x0070, 0x0078, 0x0080, 0x0088,
+ 0x2077, 0x2077, 0x206d, 0x206d, 0x2063, 0x2063, 0x2061, 0x2061,
+ 0x206f, 0x206f, 0x2065, 0x2065, 0x205b, 0x205b, 0x2059, 0x2059,
+ 0x0067, 0x005d, 0x0053, 0x0051, 0x005f, 0x0055, 0x004b, 0x0049,
+ 0x00a8, 0x00b0, 0x00b8, 0x00c0, 0x2041, 0x2041, 0x204d, 0x204d,
+ 0x2043, 0x2043, 0x2039, 0x2039, 0x2057, 0x2057, 0x2045, 0x2045,
+ 0x203b, 0x203b, 0x2031, 0x2031, 0x204f, 0x204f, 0x203d, 0x203d,
+ 0x2033, 0x2033, 0x2029, 0x2029, 0x0047, 0x0035, 0x002b, 0x0021,
+ 0x203f, 0x203f, 0x202d, 0x202d, 0x2023, 0x2023, 0x2019, 0x2019,
+ 0x0037, 0x0025, 0x001b, 0x0011, 0x202f, 0x202f, 0x201d, 0x201d,
+ 0x0013, 0x0009, 0x201f, 0x201f
+};
+
+static const OMX_U16 armVCM4P10_CAVLCCoeffTokenTables_1[128] = {
+ 0x0020, 0x00e8, 0x00f0, 0x00f8, 0x0027, 0x001f, 0x2015, 0x2015,
+ 0x400b, 0x400b, 0x400b, 0x400b, 0x4001, 0x4001, 0x4001, 0x4001,
+ 0x0028, 0x00d0, 0x00d8, 0x00e0, 0x0030, 0x0098, 0x00c0, 0x00c8,
+ 0x0038, 0x0060, 0x0088, 0x0090, 0x0040, 0x0048, 0x0050, 0x0058,
+ 0x27ff, 0x27ff, 0x207f, 0x207f, 0x0087, 0x0085, 0x0083, 0x0081,
+ 0x007b, 0x0079, 0x007d, 0x0073, 0x2075, 0x2075, 0x2071, 0x2071,
+ 0x0068, 0x0070, 0x0078, 0x0080, 0x2077, 0x2077, 0x206d, 0x206d,
+ 0x206b, 0x206b, 0x2069, 0x2069, 0x206f, 0x206f, 0x2065, 0x2065,
+ 0x2063, 0x2063, 0x2061, 0x2061, 0x0059, 0x005d, 0x005b, 0x0051,
+ 0x0067, 0x0055, 0x0053, 0x0049, 0x00a0, 0x00a8, 0x00b0, 0x00b8,
+ 0x205f, 0x205f, 0x204d, 0x204d, 0x204b, 0x204b, 0x2041, 0x2041,
+ 0x2057, 0x2057, 0x2045, 0x2045, 0x2043, 0x2043, 0x2039, 0x2039,
+ 0x204f, 0x204f, 0x203d, 0x203d, 0x203b, 0x203b, 0x2031, 0x2031,
+ 0x0029, 0x0035, 0x0033, 0x0021, 0x2047, 0x2047, 0x202d, 0x202d,
+ 0x202b, 0x202b, 0x2019, 0x2019, 0x003f, 0x0025, 0x0023, 0x0011,
+ 0x0037, 0x001d, 0x001b, 0x0009, 0x202f, 0x202f, 0x2013, 0x2013
+};
+
+static const OMX_U16 armVCM4P10_CAVLCCoeffTokenTables_2[112] = {
+ 0x0020, 0x0088, 0x00b0, 0x00b8, 0x00c0, 0x00c8, 0x00d0, 0x00d8,
+ 0x003f, 0x0037, 0x002f, 0x0027, 0x001f, 0x0015, 0x000b, 0x0001,
+ 0x0028, 0x0050, 0x0078, 0x0080, 0x0030, 0x0038, 0x0040, 0x0048,
+ 0x07ff, 0x0081, 0x0087, 0x0085, 0x0083, 0x0079, 0x007f, 0x007d,
+ 0x007b, 0x0071, 0x0077, 0x0075, 0x0073, 0x0069, 0x206b, 0x206b,
+ 0x0058, 0x0060, 0x0068, 0x0070, 0x2061, 0x2061, 0x206d, 0x206d,
+ 0x2063, 0x2063, 0x2059, 0x2059, 0x206f, 0x206f, 0x2065, 0x2065,
+ 0x205b, 0x205b, 0x2051, 0x2051, 0x0067, 0x005d, 0x0053, 0x0049,
+ 0x005f, 0x0055, 0x004b, 0x0041, 0x0090, 0x0098, 0x00a0, 0x00a8,
+ 0x2039, 0x2039, 0x2031, 0x2031, 0x204d, 0x204d, 0x2029, 0x2029,
+ 0x2057, 0x2057, 0x2045, 0x2045, 0x2043, 0x2043, 0x2021, 0x2021,
+ 0x0019, 0x003d, 0x003b, 0x0011, 0x004f, 0x0035, 0x0033, 0x0009,
+ 0x202b, 0x202b, 0x202d, 0x202d, 0x2023, 0x2023, 0x2025, 0x2025,
+ 0x201b, 0x201b, 0x2047, 0x2047, 0x201d, 0x201d, 0x2013, 0x2013
+};
+
+static const OMX_U16 armVCM4P10_CAVLCCoeffTokenTables_3[80] = {
+ 0x0020, 0x0028, 0x0030, 0x0038, 0x0040, 0x0048, 0x0050, 0x0058,
+ 0x0060, 0x0068, 0x0070, 0x0078, 0x0080, 0x0088, 0x0090, 0x0098,
+ 0x0009, 0x000b, 0x07ff, 0x0001, 0x0011, 0x0013, 0x0015, 0x07ff,
+ 0x0019, 0x001b, 0x001d, 0x001f, 0x0021, 0x0023, 0x0025, 0x0027,
+ 0x0029, 0x002b, 0x002d, 0x002f, 0x0031, 0x0033, 0x0035, 0x0037,
+ 0x0039, 0x003b, 0x003d, 0x003f, 0x0041, 0x0043, 0x0045, 0x0047,
+ 0x0049, 0x004b, 0x004d, 0x004f, 0x0051, 0x0053, 0x0055, 0x0057,
+ 0x0059, 0x005b, 0x005d, 0x005f, 0x0061, 0x0063, 0x0065, 0x0067,
+ 0x0069, 0x006b, 0x006d, 0x006f, 0x0071, 0x0073, 0x0075, 0x0077,
+ 0x0079, 0x007b, 0x007d, 0x007f, 0x0081, 0x0083, 0x0085, 0x0087
+};
+
+static const OMX_U16 armVCM4P10_CAVLCCoeffTokenTables_4[32] = {
+ 0x0020, 0x0038, 0x2015, 0x2015, 0x4001, 0x4001, 0x4001, 0x4001,
+ 0x600b, 0x600b, 0x600b, 0x600b, 0x600b, 0x600b, 0x600b, 0x600b,
+ 0x0028, 0x0030, 0x0021, 0x0019, 0x2027, 0x2027, 0x0025, 0x0023,
+ 0x201d, 0x201d, 0x201b, 0x201b, 0x0011, 0x001f, 0x0013, 0x0009
+};
+
+const OMX_U16 * armVCM4P10_CAVLCCoeffTokenTables[18] = {
+ armVCM4P10_CAVLCCoeffTokenTables_0, /* nC=0 */
+ armVCM4P10_CAVLCCoeffTokenTables_0, /* nC=1 */
+ armVCM4P10_CAVLCCoeffTokenTables_1, /* nC=2 */
+ armVCM4P10_CAVLCCoeffTokenTables_1, /* nC=3 */
+ armVCM4P10_CAVLCCoeffTokenTables_2, /* nC=4 */
+ armVCM4P10_CAVLCCoeffTokenTables_2, /* nC=5 */
+ armVCM4P10_CAVLCCoeffTokenTables_2, /* nC=6 */
+ armVCM4P10_CAVLCCoeffTokenTables_2, /* nC=7 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=8 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=9 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=10 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=11 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=12 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=13 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=14 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=15 */
+ armVCM4P10_CAVLCCoeffTokenTables_3, /* nC=16 */
+ armVCM4P10_CAVLCCoeffTokenTables_4 /* nC=-1 */
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_0[40] = {
+ 0x0020, 0x0048, 0x0009, 0x0007, 0x2005, 0x2005, 0x2003, 0x2003,
+ 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001,
+ 0x0028, 0x0040, 0x0011, 0x000f, 0x0030, 0x0038, 0x0019, 0x0017,
+ 0x27ff, 0x27ff, 0x201f, 0x201f, 0x201d, 0x201d, 0x201b, 0x201b,
+ 0x2015, 0x2015, 0x2013, 0x2013, 0x200d, 0x200d, 0x200b, 0x200b
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_1[24] = {
+ 0x0020, 0x0028, 0x0011, 0x000f, 0x000d, 0x000b, 0x2009, 0x2009,
+ 0x2007, 0x2007, 0x2005, 0x2005, 0x2003, 0x2003, 0x2001, 0x2001,
+ 0x001d, 0x001b, 0x0019, 0x0017, 0x2015, 0x2015, 0x2013, 0x2013
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_2[24] = {
+ 0x0020, 0x0028, 0x0011, 0x000b, 0x0009, 0x0001, 0x200f, 0x200f,
+ 0x200d, 0x200d, 0x2007, 0x2007, 0x2005, 0x2005, 0x2003, 0x2003,
+ 0x001b, 0x0017, 0x2019, 0x2019, 0x2015, 0x2015, 0x2013, 0x2013
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_3[24] = {
+ 0x0020, 0x0028, 0x0013, 0x000f, 0x0007, 0x0005, 0x2011, 0x2011,
+ 0x200d, 0x200d, 0x200b, 0x200b, 0x2009, 0x2009, 0x2003, 0x2003,
+ 0x2019, 0x2019, 0x2017, 0x2017, 0x2015, 0x2015, 0x2001, 0x2001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_4[20] = {
+ 0x0020, 0x0015, 0x0011, 0x0005, 0x0003, 0x0001, 0x200f, 0x200f,
+ 0x200d, 0x200d, 0x200b, 0x200b, 0x2009, 0x2009, 0x2007, 0x2007,
+ 0x2017, 0x2017, 0x2013, 0x2013
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_5[20] = {
+ 0x0020, 0x0011, 0x2013, 0x2013, 0x200f, 0x200f, 0x200d, 0x200d,
+ 0x200b, 0x200b, 0x2009, 0x2009, 0x2007, 0x2007, 0x2005, 0x2005,
+ 0x0015, 0x0001, 0x2003, 0x2003
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_6[20] = {
+ 0x0020, 0x000f, 0x2011, 0x2011, 0x200d, 0x200d, 0x2009, 0x2009,
+ 0x2007, 0x2007, 0x2005, 0x2005, 0x400b, 0x400b, 0x400b, 0x400b,
+ 0x0013, 0x0001, 0x2003, 0x2003
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_7[20] = {
+ 0x0020, 0x0003, 0x200f, 0x200f, 0x200d, 0x200d, 0x2007, 0x2007,
+ 0x400b, 0x400b, 0x400b, 0x400b, 0x4009, 0x4009, 0x4009, 0x4009,
+ 0x0011, 0x0001, 0x2005, 0x2005
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_8[20] = {
+ 0x0020, 0x0005, 0x200b, 0x200b, 0x400d, 0x400d, 0x400d, 0x400d,
+ 0x4009, 0x4009, 0x4009, 0x4009, 0x4007, 0x4007, 0x4007, 0x4007,
+ 0x0003, 0x0001, 0x200f, 0x200f
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_9[20] = {
+ 0x0020, 0x000d, 0x2005, 0x2005, 0x400b, 0x400b, 0x400b, 0x400b,
+ 0x4009, 0x4009, 0x4009, 0x4009, 0x4007, 0x4007, 0x4007, 0x4007,
+ 0x2003, 0x2003, 0x2001, 0x2001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_10[16] = {
+ 0x0001, 0x0003, 0x2005, 0x2005, 0x2007, 0x2007, 0x200b, 0x200b,
+ 0x6009, 0x6009, 0x6009, 0x6009, 0x6009, 0x6009, 0x6009, 0x6009
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_11[16] = {
+ 0x0001, 0x0003, 0x2009, 0x2009, 0x4005, 0x4005, 0x4005, 0x4005,
+ 0x6007, 0x6007, 0x6007, 0x6007, 0x6007, 0x6007, 0x6007, 0x6007
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_12[16] = {
+ 0x2001, 0x2001, 0x2003, 0x2003, 0x4007, 0x4007, 0x4007, 0x4007,
+ 0x6005, 0x6005, 0x6005, 0x6005, 0x6005, 0x6005, 0x6005, 0x6005
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_13[16] = {
+ 0x4001, 0x4001, 0x4001, 0x4001, 0x4003, 0x4003, 0x4003, 0x4003,
+ 0x6005, 0x6005, 0x6005, 0x6005, 0x6005, 0x6005, 0x6005, 0x6005
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeroTables_14[16] = {
+ 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001,
+ 0x6003, 0x6003, 0x6003, 0x6003, 0x6003, 0x6003, 0x6003, 0x6003
+};
+
+const OMX_U16 * armVCM4P10_CAVLCTotalZeroTables[15] = {
+ armVCM4P10_CAVLCTotalZeroTables_0,
+ armVCM4P10_CAVLCTotalZeroTables_1,
+ armVCM4P10_CAVLCTotalZeroTables_2,
+ armVCM4P10_CAVLCTotalZeroTables_3,
+ armVCM4P10_CAVLCTotalZeroTables_4,
+ armVCM4P10_CAVLCTotalZeroTables_5,
+ armVCM4P10_CAVLCTotalZeroTables_6,
+ armVCM4P10_CAVLCTotalZeroTables_7,
+ armVCM4P10_CAVLCTotalZeroTables_8,
+ armVCM4P10_CAVLCTotalZeroTables_9,
+ armVCM4P10_CAVLCTotalZeroTables_10,
+ armVCM4P10_CAVLCTotalZeroTables_11,
+ armVCM4P10_CAVLCTotalZeroTables_12,
+ armVCM4P10_CAVLCTotalZeroTables_13,
+ armVCM4P10_CAVLCTotalZeroTables_14
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeros2x2Tables_0[16] = {
+ 0x2007, 0x2007, 0x2005, 0x2005, 0x4003, 0x4003, 0x4003, 0x4003,
+ 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeros2x2Tables_1[16] = {
+ 0x4005, 0x4005, 0x4005, 0x4005, 0x4003, 0x4003, 0x4003, 0x4003,
+ 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCTotalZeros2x2Tables_2[16] = {
+ 0x6003, 0x6003, 0x6003, 0x6003, 0x6003, 0x6003, 0x6003, 0x6003,
+ 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001, 0x6001
+};
+
+const OMX_U16 * armVCM4P10_CAVLCTotalZeros2x2Tables[3] = {
+ armVCM4P10_CAVLCTotalZeros2x2Tables_0,
+ armVCM4P10_CAVLCTotalZeros2x2Tables_1,
+ armVCM4P10_CAVLCTotalZeros2x2Tables_2
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_0[8] = {
+ 0x4003, 0x4003, 0x4003, 0x4003, 0x4001, 0x4001, 0x4001, 0x4001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_1[8] = {
+ 0x2005, 0x2005, 0x2003, 0x2003, 0x4001, 0x4001, 0x4001, 0x4001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_2[8] = {
+ 0x2007, 0x2007, 0x2005, 0x2005, 0x2003, 0x2003, 0x2001, 0x2001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_3[8] = {
+ 0x0009, 0x0007, 0x2005, 0x2005, 0x2003, 0x2003, 0x2001, 0x2001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_4[8] = {
+ 0x000b, 0x0009, 0x0007, 0x0005, 0x2003, 0x2003, 0x2001, 0x2001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_5[8] = {
+ 0x0003, 0x0005, 0x0009, 0x0007, 0x000d, 0x000b, 0x2001, 0x2001
+};
+
+static const OMX_U16 armVCM4P10_CAVLCRunBeforeTables_6[24] = {
+ 0x0010, 0x000d, 0x000b, 0x0009, 0x0007, 0x0005, 0x0003, 0x0001,
+ 0x0018, 0x0011, 0x200f, 0x200f, 0x0020, 0x0015, 0x2013, 0x2013,
+ 0x0028, 0x0019, 0x2017, 0x2017, 0x07ff, 0x001d, 0x201b, 0x201b
+};
+
+/* Tables 7 to 14 are duplicates of table 6 */
+
+const OMX_U16 * armVCM4P10_CAVLCRunBeforeTables[15] = {
+ armVCM4P10_CAVLCRunBeforeTables_0, /* ZerosLeft=1 */
+ armVCM4P10_CAVLCRunBeforeTables_1,
+ armVCM4P10_CAVLCRunBeforeTables_2,
+ armVCM4P10_CAVLCRunBeforeTables_3,
+ armVCM4P10_CAVLCRunBeforeTables_4,
+ armVCM4P10_CAVLCRunBeforeTables_5, /* ZerosLeft=6 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=7 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=8 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=9 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=10 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=11 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=12 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=13 */
+ armVCM4P10_CAVLCRunBeforeTables_6, /* ZerosLeft=14 */
+ armVCM4P10_CAVLCRunBeforeTables_6 /* ZerosLeft=15 */
+};
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
new file mode 100755
index 0000000..4c3a77c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingChroma_unsafe_s.s
@@ -0,0 +1,198 @@
+;//
+;//
+;// File Name: armVCM4P10_DeblockingChroma_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+
+ IF CortexA8
+
+pAlpha RN 2
+pBeta RN 3
+
+pThresholds RN 5
+pBS RN 4
+bS3210 RN 6
+
+;// Pixels
+dP_0 DN D4.U8
+dP_1 DN D5.U8
+dP_2 DN D6.U8
+dP_3 DN D7.U8
+dQ_0 DN D8.U8
+dQ_1 DN D9.U8
+dQ_2 DN D10.U8
+dQ_3 DN D11.U8
+
+
+;// Filtering Decision
+dAlpha DN D0.U8
+dBeta DN D2.U8
+
+dFilt DN D16.U8
+dAqflg DN D12.U8
+dApflg DN D17.U8
+
+dAp0q0 DN D13.U8
+
+;// bSLT4
+dTC3210 DN D18.U8
+dTCs DN D31.S8
+dTC DN D31.U8
+
+dMask_0 DN D14.U8
+dMask_1 DN D15.U8
+dMask_4 DN D26.U16
+
+dTemp DN D28.U8
+dDummy DN D17.U8
+
+;// Computing P0,Q0
+qDq0p0 QN Q10.S16
+qDp1q1 QN Q11.S16
+qDelta QN Q10.S16 ; reuse qDq0p0
+dDelta DN D20.S8
+
+
+;// Computing P1,Q1
+qP_0n QN Q14.S16
+qQ_0n QN Q12.S16
+
+dQ_0n DN D24.U8
+dP_0n DN D29.U8
+
+;// bSGE4
+
+dHSp0q1 DN D13.U8
+dHSq0p1 DN D31.U8
+
+dBS3210 DN D28.U16
+
+dP_0t DN D13.U8 ;dHSp0q1
+dQ_0t DN D31.U8 ;Temp1
+
+dP_0n DN D29.U8
+dQ_0n DN D24.U8 ;Temp2
+
+;// Register usage for - armVCM4P10_DeblockingLumabSLT4_unsafe
+;//
+;// Inputs - Pixels - p0-p3: D4-D7, q0-q3: D8-D11
+;// - Filter masks - filt: D16, aqflg: D12, apflg: D17
+;// - Additional Params - pThresholds: r5
+;//
+;// Outputs - Pixels - P0-P1: D29-D30, Q0-Q1: D24-D25
+;// - Additional Params - pThresholds: r5
+
+;// Registers Corrupted - D18-D31
+
+
+ M_START armVCM4P10_DeblockingChromabSLT4_unsafe
+
+
+ ;dTC3210 -18
+ ;dTemp-28
+
+ VLD1 d18.U32[0], [pThresholds]! ;here
+
+ ;// delta = (((q0-p0)<<2) + (p1-q1) + 4) >> 3;
+ ;// dDelta = (qDp1q1 >> 2 + qDq0p0 + 1)>> 1
+
+ ;// qDp1q1-11
+ ;// qDq0p0-10
+ VSUBL qDp1q1, dP_1, dQ_1
+ VMOV dTemp, dTC3210
+ VSUBL qDq0p0, dQ_0, dP_0
+ VSHR qDp1q1, qDp1q1, #2
+ VZIP.8 dTC3210, dTemp
+
+ ;// qDelta-qDq0p0-10
+
+ ;// dTC = dTC01 + (dAplg & 1) + (dAqflg & 1)
+
+ ;// dTC3210-18
+ ;// dTemp-28
+ ;// dTC-31
+ VBIF dTC3210, dMask_0, dFilt
+ VRHADD qDelta, qDp1q1, qDq0p0
+ VADD dTC, dTC3210, dMask_1
+ VQMOVN dDelta, qDelta
+ ;// dDelta-d20
+
+ ;// dDelta = (OMX_U8)armClip(0, 255, q0 - delta);
+ VLD1 {dAlpha[]}, [pAlpha]
+ VMIN dDelta, dDelta, dTCs
+ VNEG dTCs, dTCs
+ VLD1 {dBeta[]}, [pBeta]
+ ;1
+ VMAX dDelta, dDelta, dTCs
+
+ ;// dP_0n - 29
+ ;// dQ_0n - 24
+
+ ;// pQ0[-1*Step] = (OMX_U8)armClip(0, 255, dP_0 - delta);
+ ;// pQ0[0*Step] = (OMX_U8)armClip(0, 255, dQ_0 - delta);
+
+ ;// dP_0n = (OMX_U8)armClip(0, 255, dP_0 - dDelta);
+ ;// dQ_0n = (OMX_U8)armClip(0, 255, dP_0 - dDelta);
+
+ ;// qP_0n - 14
+ ;// qQ_0n - 12
+
+ VMOVL qP_0n, dP_0
+ VMOVL qQ_0n, dQ_0
+
+ ;1
+ VADDW qP_0n, qP_0n, dDelta
+ VSUBW qQ_0n, qQ_0n, dDelta
+
+ VQMOVUN dP_0n, qP_0n
+ VQMOVUN dQ_0n, qQ_0n
+
+ M_END
+
+;// Register usage for - armVCM4P10_DeblockingLumabSGE4_unsafe()
+;//
+;// Inputs - Pixels - p0-p3: D4-D7, q0-q3: D8-D11
+;// - Filter masks - filt: D16, aqflg: D12, apflg: D17
+;// - Additional Params - alpha: D0, dMask_1: D15
+;//
+;// Outputs - Pixels - P0-P2: D29-D31, Q0-Q2: D24,D25,D28
+
+;// Registers Corrupted - D18-D31
+
+ M_START armVCM4P10_DeblockingChromabSGE4_unsafe
+
+ ;dHSq0p1 - 31
+ ;dHSp0q1 - 13
+ VHADD dHSp0q1, dP_0, dQ_1
+ VHADD dHSq0p1, dQ_0, dP_1
+
+ ;// Prepare the bS mask
+
+ ;// dHSp0q1-13
+ ;// dP_0t-dHSp0q1-13
+ ;// dHSq0p1-31
+ ;// dQ_0t-Temp1-31
+ VLD1 {dAlpha[]}, [pAlpha]
+ ADD pThresholds, pThresholds, #4
+ VLD1 {dBeta[]}, [pBeta]
+
+ VRHADD dP_0t, dHSp0q1, dP_1
+ VRHADD dQ_0t, dHSq0p1, dQ_1
+
+ M_END
+
+ ENDIF
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
new file mode 100755
index 0000000..0afe4fd
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DeblockingLuma_unsafe_s.s
@@ -0,0 +1,396 @@
+;//
+;//
+;// File Name: armVCM4P10_DeblockingLuma_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+
+ IF CortexA8
+
+pThresholds RN 5
+
+;// Pixels
+dP_0 DN D4.U8
+dP_1 DN D5.U8
+dP_2 DN D6.U8
+dP_3 DN D7.U8
+dQ_0 DN D8.U8
+dQ_1 DN D9.U8
+dQ_2 DN D10.U8
+dQ_3 DN D11.U8
+
+
+;// Filtering Decision
+dAlpha DN D0.U8
+
+dFilt DN D16.U8
+dAqflg DN D12.U8
+dApflg DN D17.U8
+
+dAp0q0 DN D13.U8
+
+;// bSLT4
+dTC0 DN D18.U8
+dTC1 DN D19.U8
+dTC01 DN D18.U8
+
+dTCs DN D31.S8
+dTC DN D31.U8
+
+dMask_0 DN D14.U8
+dMask_1 DN D15.U8
+
+dTemp DN D19.U8
+
+;// Computing P0,Q0
+qDq0p0 QN Q10.S16
+qDp1q1 QN Q11.S16
+qDelta QN Q10.S16 ; reuse qDq0p0
+dDelta DN D20.S8
+
+
+;// Computing P1,Q1
+dRp0q0 DN D24.U8
+
+dMaxP DN D23.U8
+dMinP DN D22.U8
+
+dMaxQ DN D19.U8
+dMinQ DN D21.U8
+
+dDeltaP DN D26.U8
+dDeltaQ DN D27.U8
+
+qP_0n QN Q14.S16
+qQ_0n QN Q12.S16
+
+dQ_0n DN D24.U8
+dQ_1n DN D25.U8
+dP_0n DN D29.U8
+dP_1n DN D30.U8
+
+;// bSGE4
+
+qSp0q0 QN Q10.U16
+
+qSp2q1 QN Q11.U16
+qSp0q0p1 QN Q12.U16
+qSp3p2 QN Q13.U16
+dHSp0q1 DN D28.U8
+
+qSq2p1 QN Q11.U16
+qSp0q0q1 QN Q12.U16
+qSq3q2 QN Q13.U16 ;!!
+dHSq0p1 DN D28.U8 ;!!
+
+qTemp1 QN Q11.U16 ;!!;qSp2q1
+qTemp2 QN Q12.U16 ;!!;qSp0q0p1
+
+dP_0t DN D28.U8 ;!!;dHSp0q1
+dQ_0t DN D22.U8 ;!!;Temp1
+
+dP_0n DN D29.U8
+dP_1n DN D30.U8
+dP_2n DN D31.U8
+
+dQ_0n DN D24.U8 ;!!;Temp2
+dQ_1n DN D25.U8 ;!!;Temp2
+dQ_2n DN D28.U8 ;!!;dQ_0t
+
+;// Register usage for - armVCM4P10_DeblockingLumabSLT4_unsafe
+;//
+;// Inputs - Pixels - p0-p3: D4-D7, q0-q3: D8-D11
+;// - Filter masks - filt: D16, aqflg: D12, apflg: D17
+;// - Additional Params - pThresholds: r5
+;//
+;// Outputs - Pixels - P0-P1: D29-D30, Q0-Q1: D24-D25
+;// - Additional Params - pThresholds: r5
+
+;// Registers Corrupted - D18-D31
+
+
+ M_START armVCM4P10_DeblockingLumabSLT4_unsafe
+
+
+ ;// qDq0p0-10
+ VSUBL qDp1q1, dP_1, dQ_1
+ VLD1 {dTC0[]}, [pThresholds]!
+ ;// qDp1q1-11
+ VSUBL qDq0p0, dQ_0, dP_0
+ VLD1 {dTC1[]}, [pThresholds]!
+
+ ;// dRp0q0-24
+ VSHR qDp1q1, qDp1q1, #2
+
+ ;// dTC01 = (dTC1 << 4) | dTC0
+ ;// dTC01-18
+ VEXT dTC01, dTC0, dTC1, #4
+ ;// dTemp-19
+ VAND dTemp, dApflg, dMask_1
+
+ VBIF dTC01, dMask_0, dFilt
+
+
+ ;// delta = (((q0-p0)<<2) + (p1-q1) + 4) >> 3;
+ ;// dDelta = (qDp1q1 >> 2 + qDq0p0 + 1)>> 1
+
+ ;// qDelta-qDq0p0-10
+ VRHADD qDelta, qDp1q1, qDq0p0
+ VRHADD dRp0q0, dP_0, dQ_0
+ VADD dTC, dTC01, dTemp
+
+ ;// dTC = dTC01 + (dAplg & 1) + (dAqflg & 1)
+
+ VAND dTemp, dAqflg, dMask_1
+ VQADD dMaxP, dP_1, dTC01
+ VQMOVN dDelta, qDelta
+ VADD dTC, dTC, dTemp
+
+ ;// dMaxP = QADD(dP_1, dTC01)
+ ;// dMinP = QSUB(dP_1, dTC01)
+
+ ;// dMaxP-d23
+ ;// dMinP-d22
+ VQSUB dMinP, dP_1, dTC01
+
+ ;// dDelta-d20
+
+ ;// dMaxQ = QADD(dQ_1, dTC01)
+ ;// dMinQ = QSUB(dQ_1, dTC01)
+
+ ;// dMaxQ-19
+ ;// dMinQ-21
+ VQADD dMaxQ, dQ_1, dTC01
+ VHADD dDeltaP, dRp0q0, dP_2
+ VMIN dDelta, dDelta, dTCs
+
+ ;// dDelta = (OMX_U8)armClip(0, 255, q0 - delta);
+ VNEG dTCs, dTCs
+
+ VQSUB dMinQ, dQ_1, dTC01
+
+ ;// delta = (p2 + ((p0+q0+1)>>1) - (p1<<1))>>1;
+ ;// delta = armClip(-tC0, tC0, delta);
+ ;// pQ0[-2*Step] = (OMX_U8)(p1 + delta);
+
+ ;// dDeltaP = (dP_2 + dRp0q0)>>1;
+ ;// dP_1n = armClip(dP_1 - dTC01, dP_1 + dTC01, dDeltaP);
+ ;// dP_1n = armClip(MinP, MaxP, dDeltaP);
+
+ ;// delta = (q2 + ((p0+q0+1)>>1) - (q1<<1))>>1;
+ ;// delta = armClip(-tC0, tC0, delta);
+ ;// pQ0[1*Step] = (OMX_U8)(q1 + delta);
+
+ ;// dDeltaQ = (dQ_2 + dRp0q0)>>1;
+ ;// dQ_1n = armClip(dQ_1 - dTC01, dQ_1 + dTC01, dDeltaQ);
+ ;// dQ_1n = armClip(MinQ, MaxQ, dDeltaQ);
+
+ ;// dDeltaP-26
+ VHADD dDeltaQ, dRp0q0, dQ_2
+
+ ;// dDeltaQ-27
+
+ ;// dP_0n - 29
+ ;// dP_1n - 30
+ ;// dQ_0n - 24
+ ;// dQ_1n - 25
+
+ ;// delta = (q2 + ((p0+q0+1)>>1) - (q1<<1))>>1;
+ ;// dDeltaQ = (dQ_2 + dRp0q0)>>1;
+
+ VMAX dP_1n, dDeltaP, dMinP
+ VMAX dDelta, dDelta, dTCs
+
+ ;// pQ0[-1*Step] = (OMX_U8)armClip(0, 255, dP_0 - delta);
+ ;// pQ0[0*Step] = (OMX_U8)armClip(0, 255, dQ_0 - delta);
+
+ ;// dP_0n = (OMX_U8)armClip(0, 255, dP_0 - dDelta);
+ ;// dQ_0n = (OMX_U8)armClip(0, 255, dP_0 - dDelta);
+
+ ;// qP_0n - 14
+ ;// qQ_0n - 12
+
+ VMOVL qP_0n, dP_0
+ VMOVL qQ_0n, dQ_0
+
+ VADDW qP_0n, qP_0n, dDelta
+ VSUBW qQ_0n, qQ_0n, dDelta
+
+ VQMOVUN dP_0n, qP_0n
+ VQMOVUN dQ_0n, qQ_0n
+
+ VMAX dQ_1n, dDeltaQ, dMinQ
+
+ VMIN dP_1n, dP_1n, dMaxP
+ VMIN dQ_1n, dQ_1n, dMaxQ
+ VBIF dP_0n, dP_0, dFilt
+
+ VBIF dP_1n, dP_1, dApflg
+ VBIF dQ_0n, dQ_0, dFilt
+ VBIF dQ_1n, dQ_1, dAqflg
+
+ M_END
+
+;// Register usage for - armVCM4P10_DeblockingLumabSGE4_unsafe()
+;//
+;// Inputs - Pixels - p0-p3: D4-D7, q0-q3: D8-D11
+;// - Filter masks - filt: D16, aqflg: D12, apflg: D17
+;// - Additional Params - alpha: D0, dMask_1: D15
+;//
+;// Outputs - Pixels - P0-P2: D29-D31, Q0-Q2: D24,D25,D28
+
+;// Registers Corrupted - D18-D31
+
+ M_START armVCM4P10_DeblockingLumabSGE4_unsafe
+
+
+ ;// ap<beta && armAbs(p0-q0)<((alpha>>2)+2)
+ ;// aq<beta && armAbs(p0-q0)<((alpha>>2)+2)
+
+ ;// ( dApflg & dAp0q0 < (dAlpha >> 2 + 2) )
+ ;// ( dAqflg & dAp0q0 < (dAlpha >> 2 + 2) )
+
+ ;// ( dApflg = dApflg & dAp0q0 < (dTemp + dMask_1 + dMask_1) )
+ ;// ( dAqflg = dAqflg & dAp0q0 < (dTemp + dMask_1 + dMask_1) )
+
+ ;// P Filter
+
+ VSHR dTemp, dAlpha, #2
+ VADD dTemp, dTemp, dMask_1
+
+ ;// qSp0q0-10
+ VADDL qSp0q0, dQ_0, dP_0
+ VADD dTemp, dTemp, dMask_1
+
+ ;// qSp2q1-11
+ ;// qSp0q0p1-12
+ VADDL qSp2q1, dP_2, dQ_1
+ VADDW qSp0q0p1, qSp0q0, dP_1
+
+ VCGT dTemp, dTemp, dAp0q0
+ VSHR qSp2q1, #1
+
+ ;// pQ0[-1*Step] = (OMX_U8)((p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4)>>3);
+ ;// pQ0[-1*Step] = ( ( (p0 + q0 + p1) + (p2 + q1)>>1 ) >> 1 + 1 ) >> 1
+
+ ;// dP_0n = ( ( (qSp0q0 + dP_1) + qSp2q1>>1 ) >> 1 + 1 ) >> 1
+ ;// dP_0n = ( ( qSp0q0p1 + qSp2q1>>1 ) >> 1 + 1 ) >> 1
+ ;// dP_0n = ( qTemp1 + 1 ) >> 1
+
+ ;// pQ0[-2*Step] = (OMX_U8)((p2 + p1 + p0 + q0 + 2)>>2);
+
+ ;// dP_1n = (OMX_U8)((dP_2 + qSp0q0p1 + 2)>>2);
+ ;// dP_1n = (OMX_U8)((qTemp2 + 2)>>2);
+
+ ;// pQ0[-3*Step] = (OMX_U8)((2*p3 + 3*p2 + p1 + p0 + q0 + 4)>>3);
+ ;// pQ0[-3*Step] = (OMX_U8)(( (p3 + p2) + (p1 + p0 + q0 + p2) >> 1 + 2)>>2);
+
+ ;// dP_2n = (OMX_U8)(( qSp3p2 + (dP_2 + qSp0q0p1) >> 1 + 2) >> 2);
+ ;// dP_2n = (OMX_U8)(( qSp3p2 + qTemp2 >> 1 + 2) >> 2);
+
+ ;// qTemp1-qSp2q1-11
+ ;// qTemp2-qSp0q0p1-12
+ VHADD qTemp1, qSp0q0p1, qSp2q1
+ VADDW qTemp2, qSp0q0p1, dP_2
+
+ ;// qSp3p2-13
+ VADDL qSp3p2, dP_3, dP_2
+
+ VAND dApflg, dApflg, dTemp
+ VHADD dHSp0q1, dP_0, dQ_1
+ VSRA qSp3p2, qTemp2, #1
+ ;// dHSp0q1-28
+ VAND dAqflg, dAqflg, dTemp
+
+ ;// dP_0n-29
+ ;// dP_0t-dHSp0q1-28
+ VQRSHRN dP_0n, qTemp1, #1
+ VRHADD dP_0t, dHSp0q1, dP_1
+
+ ;// dP_1n-30
+ VQRSHRN dP_1n, qTemp2, #2
+
+ VADDL qSq2p1, dQ_2, dP_1
+ VADDW qSp0q0q1, qSp0q0, dQ_1
+
+ VBIF dP_0n, dP_0t, dApflg
+
+ ;// Q Filter
+
+ ;// pQ0[0*Step] = (OMX_U8)((q2 + 2*q1 + 2*q0 + 2*p0 + p1 + 4)>>3);
+ ;// pQ0[0*Step] = ( ( (p0 + q0 + q1) + (q2 + p1)>>1 ) >> 1 + 1 ) >> 1
+
+ ;// dQ_0n = ( ( (qSp0q0 + dQ_1) + qSq2p1>>1 ) >> 1 + 1 ) >> 1
+ ;// dQ_0n = ( ( qSp0q0q1 + qSq2p1>>1 ) >> 1 + 1 ) >> 1
+ ;// dQ_0n = ( qTemp1 + 1 ) >> 1
+
+ ;// pQ0[1*Step] = (OMX_U8)((q2 + q1 + q0 + q0 + 2)>>2);
+
+ ;// dQ_1n = (OMX_U8)((dQ_2 + qSp0q0q1 + 2)>>2);
+ ;// dQ_1n = (OMX_U8)((qTemp2 + 2)>>2);
+
+ ;// pQ0[2*Step] = (OMX_U8)((2*q3 + 3*q2 + q1 + q0 + p0 + 4)>>3);
+ ;// pQ0[2*Step] = (OMX_U8)(( (q3 + q2) + (q1 + p0 + q0 + q2) >> 1 + 2)>>2);
+
+ ;// dQ_2n = (OMX_U8)(( qSq3q2 + (dQ_2 + qSp0q0q1) >> 1 + 2) >> 2);
+ ;// dQ_2n = (OMX_U8)(( qSq3q2 + qTemp2 >> 1 + 2) >> 2);
+
+ ;// qTemp1-qSp2q1-11
+ ;// qTemp2-qSp0q0p1-12
+ ;// qSq2p1-11
+ ;// qSp0q0q1-12
+
+
+ ;// qTemp2-qSp0q0p1-12
+ ;// qTemp1-qSq2p1-11
+ ;// qSq3q2-13
+ ;// dP_2n-31
+
+ VQRSHRN dP_2n, qSp3p2, #2
+ VADDL qSq3q2, dQ_3, dQ_2
+
+ VSHR qSq2p1, #1
+
+ VHADD qTemp1, qSp0q0q1, qSq2p1
+ VADDW qTemp2, qSp0q0q1, dQ_2
+
+ ;// dHSq0p1-28
+ VHADD dHSq0p1, dQ_0, dP_1
+
+ VBIF dP_0n, dP_0, dFilt
+ VBIF dP_1n, dP_1, dApflg
+
+ VSRA qSq3q2, qTemp2, #1
+
+ ;// dQ_1-Temp2-25
+ ;// dQ_0-Temp2-24
+ VQRSHRN dQ_1n, qTemp2, #2
+ VQRSHRN dQ_0n, qTemp1, #1
+
+ ;// dQ_0t-Temp1-22
+ VRHADD dQ_0t, dHSq0p1, dQ_1
+ VBIF dQ_1n, dQ_1, dAqflg
+
+ VBIF dP_2n, dP_2, dApflg
+ VBIF dQ_0n, dQ_0t, dAqflg
+ VQRSHRN dQ_2n, qSq3q2, #2
+ VBIF dQ_0n, dQ_0, dFilt
+ VBIF dQ_2n, dQ_2, dAqflg
+
+ M_END
+
+ ENDIF
+
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
new file mode 100755
index 0000000..10a89e9
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair_s.s
@@ -0,0 +1,325 @@
+;//
+;//
+;// File Name: armVCM4P10_DecodeCoeffsToPair_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armCOMM_BitDec_s.h
+
+ IMPORT armVCM4P10_CAVLCCoeffTokenTables
+ IMPORT armVCM4P10_CAVLCTotalZeroTables
+ IMPORT armVCM4P10_CAVLCTotalZeros2x2Tables
+ IMPORT armVCM4P10_CAVLCRunBeforeTables
+ IMPORT armVCM4P10_SuffixToLevel
+ IMPORT armVCM4P10_ZigZag_4x4
+ IMPORT armVCM4P10_ZigZag_2x2
+
+ M_VARIANTS ARM1136JS
+
+;//DEBUG_ON SETL {TRUE}
+
+LAST_COEFF EQU 0x20 ;// End of block flag
+TWO_BYTE_COEFF EQU 0x10
+
+;// Declare input registers
+
+ppBitStream RN 0
+pOffset RN 1
+pNumCoeff RN 2
+ppPosCoefbuf RN 3
+nC RN 4 ;// number of coeffs or 17 for chroma
+sMaxNumCoeff RN 5
+
+;// Declare inner loop registers
+
+;// Level loop
+Count RN 0
+TrailingOnes RN 1
+pLevel RN 2
+LevelSuffix RN 3
+SuffixLength RN 4
+TotalCoeff RN 5
+
+pVLDTable RN 6
+Symbol RN 7
+T1 RN 8
+T2 RN 9
+RBitStream RN 10
+RBitBuffer RN 11
+RBitCount RN 12
+lr RN 14
+
+;// Run loop
+Count RN 0
+ZerosLeft RN 1
+pLevel RN 2
+ppRunTable RN 3
+pRun RN 4
+TotalCoeff RN 5
+
+pVLDTable RN 6
+Symbol RN 7
+T1 RN 8
+T2 RN 9
+RBitStream RN 10
+RBitBuffer RN 11
+RBitCount RN 12
+lr RN 14
+
+;// Fill in coefficients loop
+pPosCoefbuf RN 0
+temp RN 1
+pLevel RN 2
+ppPosCoefbuf RN 3
+pRun RN 4
+TotalCoeff RN 5
+pZigZag RN 6
+
+T1 RN 8
+T2 RN 9
+RBitStream RN 10
+RBitBuffer RN 11
+RBitCount RN 12
+CoeffNum RN 14
+
+
+
+ IF ARM1136JS
+
+ ;// Allocate stack memory required by the function
+ M_ALLOC4 pppBitStream, 4
+ M_ALLOC4 ppOffset, 4
+ M_ALLOC4 pppPosCoefbuf, 4
+ M_ALLOC4 ppLevel, 16*2
+ M_ALLOC4 ppRun, 16
+
+ ;// Write function header
+ M_START armVCM4P10_DecodeCoeffsToPair, r11
+
+ ;// Define stack arguments
+ M_ARG pNC, 4
+ M_ARG pSMaxNumCoeff,4
+
+ ;// Code start
+ M_BD_INIT0 ppBitStream, pOffset, RBitStream, RBitBuffer, RBitCount
+ LDR pVLDTable, =armVCM4P10_CAVLCCoeffTokenTables
+ M_LDR nC, pNC
+
+ M_BD_INIT1 T1, T2, lr
+ LDR pVLDTable, [pVLDTable, nC, LSL #2] ;// Find VLD table
+
+ M_BD_INIT2 T1, T2, lr
+
+ ;// Decode Symbol = TotalCoeff*4 + TrailingOnes
+ M_BD_VLD Symbol, T1, T2, pVLDTable, 4, 2
+
+ MOVS TotalCoeff, Symbol, LSR #2
+ STRB TotalCoeff, [pNumCoeff]
+ M_PRINTF "TotalCoeff=%d\n", TotalCoeff
+ BEQ.W EndNoError ;// Finished if no coefficients
+
+ CMP Symbol, #17*4
+ BGE.W EndBadSymbol ;// Error if bad symbol
+
+ ;// Save bitstream pointers
+ M_STR ppBitStream, pppBitStream
+ M_STR pOffset, ppOffset
+ M_STR ppPosCoefbuf, pppPosCoefbuf
+
+ ;// Decode Trailing Ones
+ ANDS TrailingOnes, Symbol, #3
+ M_ADR pLevel, ppLevel
+ M_PRINTF "TrailingOnes=%d\n", TrailingOnes
+ BEQ TrailingOnesDone
+ MOV Count, TrailingOnes
+TrailingOnesLoop
+ M_BD_READ8 Symbol, 1, T1
+ SUBS Count, Count, #1
+ MOV T1, #1
+ SUB T1, T1, Symbol, LSL #1
+ M_PRINTF "Level=%d\n", T1
+ STRH T1, [pLevel], #2
+ BGT TrailingOnesLoop
+TrailingOnesDone
+
+ ;// Decode level values
+ SUBS Count, TotalCoeff, TrailingOnes ;// Number of levels to read
+ BEQ DecodeRuns ;// None left
+
+ MOV SuffixLength, #1
+ CMP TotalCoeff, #10
+ MOVLE SuffixLength, #0
+ CMP TrailingOnes, #3 ;// if (TrailingOnes<3)
+ MOVLT TrailingOnes, #4 ;// then TrailingOnes = +4
+ MOVGE TrailingOnes, #2 ;// else TrailingOnes = +2
+ MOVGE SuffixLength, #0 ;// SuffixLength = 0
+
+LevelLoop
+ M_BD_CLZ16 Symbol, T1, T2 ;// Symbol=LevelPrefix
+ CMP Symbol,#16
+ BGE EndBadSymbol
+
+ MOVS lr, SuffixLength ;// if LevelSuffixSize==0
+ TEQEQ Symbol, #14 ;// and LevelPrefix==14
+ MOVEQ lr, #4 ;// then LevelSuffixSize=4
+ TEQ Symbol, #15 ;// if LevelSuffixSize==15
+ MOVEQ lr, #12 ;// then LevelSuffixSize=12
+
+ TEQEQ SuffixLength,#0
+ ADDEQ Symbol,Symbol,#15
+
+ TEQ lr, #0 ;// if LevelSuffixSize==0
+ BEQ LevelCodeRead ;// LevelCode = LevelPrefix
+
+ M_BD_VREAD16 LevelSuffix, lr, T1, T2 ;// Read Level Suffix
+
+ MOV Symbol, Symbol, LSL SuffixLength
+ ADD Symbol, LevelSuffix, Symbol
+
+LevelCodeRead
+ ;// Symbol = LevelCode
+ ADD Symbol, Symbol, TrailingOnes ;// +4 if level cannot be +/-1, +2 o/w
+ MOV TrailingOnes, #2
+ MOVS T1, Symbol, LSR #1
+ RSBCS T1, T1, #0 ;// If Symbol odd then negate
+ M_PRINTF "Level=%d\n", T1
+ STRH T1, [pLevel], #2 ;// Store level.
+
+ LDR T2, =armVCM4P10_SuffixToLevel
+ LDRSB T1, [T2, SuffixLength] ;// Find increment level
+ TEQ SuffixLength, #0
+ MOVEQ SuffixLength, #1
+ CMP Symbol, T1
+ ADDCS SuffixLength, SuffixLength, #1
+ SUBS Count, Count, #1
+ BGT LevelLoop
+
+DecodeRuns
+ ;// Find number of zeros
+ M_LDR T1, pSMaxNumCoeff ;// sMaxNumCoeff
+ SUB Count, TotalCoeff, #1 ;// Number of runs excluding last
+ SUBS ZerosLeft, T1, TotalCoeff ;// Maximum number of zeros there could be
+ M_ADR pRun, ppRun
+ MOV CoeffNum,TotalCoeff
+ SUB CoeffNum,CoeffNum,#1
+ BEQ NoZerosLeft
+
+ ;// Unpack number of zeros from bitstream
+ TEQ T1, #4
+ LDREQ pVLDTable, =(armVCM4P10_CAVLCTotalZeros2x2Tables-4)
+ LDRNE pVLDTable, =(armVCM4P10_CAVLCTotalZeroTables-4)
+ LDR pVLDTable, [pVLDTable, TotalCoeff, LSL #2]
+
+ M_BD_VLD Symbol, T1, T2, pVLDTable, 4, 2 ;// Symbol = ZerosLeft
+ CMP Symbol,#16
+ BGE EndBadSymbol
+
+ LDR ppRunTable, =(armVCM4P10_CAVLCRunBeforeTables-4)
+ M_ADR pRun, ppRun
+ MOVS ZerosLeft, Symbol
+
+ ADD CoeffNum,CoeffNum,ZerosLeft
+
+ BEQ NoZerosLeft
+
+ ;// Decode runs while zeros are left and more than one coefficient
+RunLoop
+ SUBS Count, Count, #1
+ LDR pVLDTable, [ppRunTable, ZerosLeft, LSL#2]
+ BLT LastRun
+ M_BD_VLD Symbol, T1, T2, pVLDTable, 3, 2 ;// Symbol = Run
+ CMP Symbol,#15
+ BGE EndBadSymbol
+
+ SUBS ZerosLeft, ZerosLeft, Symbol
+ M_PRINTF "Run=%d\n", Symbol
+ STRB Symbol, [pRun], #1
+ BGT RunLoop
+
+ ;// Decode runs while no zeros are left
+NoZerosLeft
+ SUBS Count, Count, #1
+ M_PRINTF "Run=%d\n", ZerosLeft
+ STRGEB ZerosLeft, [pRun], #1
+ BGT NoZerosLeft
+
+LastRun
+ ;// Final run length is remaining zeros
+ M_PRINTF "LastRun=%d\n", ZerosLeft
+ STRB ZerosLeft, [pRun], #1
+
+ ;// Write coefficients to output array
+ M_LDR T1, pSMaxNumCoeff ;// sMaxNumCoeff
+ TEQ T1, #15
+ ADDEQ CoeffNum,CoeffNum,#1
+
+
+ SUB pRun,pRun,TotalCoeff
+ SUB pLevel,pLevel,TotalCoeff
+ SUB pLevel,pLevel,TotalCoeff
+
+ M_LDR ppPosCoefbuf, pppPosCoefbuf
+ LDR pPosCoefbuf, [ppPosCoefbuf]
+ TEQ T1, #4
+ LDREQ pZigZag, =armVCM4P10_ZigZag_2x2
+ LDRNE pZigZag, =armVCM4P10_ZigZag_4x4
+
+
+
+OutputLoop
+
+ LDRB T2, [pRun],#1
+ LDRB T1, [pZigZag, CoeffNum]
+ SUB CoeffNum, CoeffNum, #1 ;// Skip Non zero
+ SUB CoeffNum, CoeffNum, T2 ;// Skip Zero run
+
+ LDRSH T2, [pLevel],#2
+
+ SUBS TotalCoeff, TotalCoeff, #1
+ ORREQ T1, T1, #LAST_COEFF
+
+ ADD temp, T2, #128
+ CMP temp, #256
+ ORRCS T1, T1, #TWO_BYTE_COEFF
+
+
+ TEQ TotalCoeff, #0 ;// Preserves carry
+
+ M_PRINTF "Output=%02x %04x\n", T1, T2
+ STRB T1, [pPosCoefbuf], #1
+ STRB T2, [pPosCoefbuf], #1
+ MOV T2, T2, LSR #8
+ STRCSB T2, [pPosCoefbuf], #1
+ BNE OutputLoop
+
+ ;// Finished
+ STR pPosCoefbuf, [ppPosCoefbuf]
+ M_LDR ppBitStream, pppBitStream
+ M_LDR pOffset, ppOffset
+ B EndNoError
+
+EndBadSymbol
+ MOV r0, #OMX_Sts_Err
+ B End
+
+EndNoError
+ ;// Finished reading from the bitstream
+ M_BD_FINI ppBitStream, pOffset
+
+ ;// Set return value
+ MOV r0, #OMX_Sts_NoErr
+End
+ M_END
+
+ ENDIF
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DequantTables_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DequantTables_s.s
new file mode 100755
index 0000000..2761600
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_DequantTables_s.s
@@ -0,0 +1,123 @@
+;//
+;//
+;// File Name: armVCM4P10_DequantTables_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ EXPORT armVCM4P10_QPDivTable
+ EXPORT armVCM4P10_VMatrixQPModTable
+ EXPORT armVCM4P10_PosToVCol4x4
+ EXPORT armVCM4P10_PosToVCol2x2
+ EXPORT armVCM4P10_VMatrix
+ EXPORT armVCM4P10_QPModuloTable
+ EXPORT armVCM4P10_VMatrixU16
+
+;// Define the processor variants supported by this file
+
+ M_VARIANTS CortexA8
+
+
+;// Guarding implementation by the processor name
+
+
+ IF CortexA8
+
+
+ M_TABLE armVCM4P10_PosToVCol4x4
+ DCB 0, 2, 0, 2
+ DCB 2, 1, 2, 1
+ DCB 0, 2, 0, 2
+ DCB 2, 1, 2, 1
+
+
+ M_TABLE armVCM4P10_PosToVCol2x2
+ DCB 0, 2
+ DCB 2, 1
+
+
+ M_TABLE armVCM4P10_VMatrix
+ DCB 10, 16, 13
+ DCB 11, 18, 14
+ DCB 13, 20, 16
+ DCB 14, 23, 18
+ DCB 16, 25, 20
+ DCB 18, 29, 23
+
+;//-------------------------------------------------------
+;// This table evaluates the expression [(INT)(QP/6)],
+;// for values of QP from 0 to 51 (inclusive).
+;//-------------------------------------------------------
+
+ M_TABLE armVCM4P10_QPDivTable
+ DCB 0, 0, 0, 0, 0, 0
+ DCB 1, 1, 1, 1, 1, 1
+ DCB 2, 2, 2, 2, 2, 2
+ DCB 3, 3, 3, 3, 3, 3
+ DCB 4, 4, 4, 4, 4, 4
+ DCB 5, 5, 5, 5, 5, 5
+ DCB 6, 6, 6, 6, 6, 6
+ DCB 7, 7, 7, 7, 7, 7
+ DCB 8, 8, 8, 8, 8, 8
+
+;//----------------------------------------------------
+;// This table contains armVCM4P10_VMatrix[QP%6][0] entires,
+;// for values of QP from 0 to 51 (inclusive).
+;//----------------------------------------------------
+
+ M_TABLE armVCM4P10_VMatrixQPModTable
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+ DCB 10, 11, 13, 14, 16, 18
+
+;//-------------------------------------------------------
+;// This table evaluates the modulus expression [QP%6]*6,
+;// for values of QP from 0 to 51 (inclusive).
+;//-------------------------------------------------------
+
+ M_TABLE armVCM4P10_QPModuloTable
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+ DCB 0, 6, 12, 18, 24, 30
+
+;//-------------------------------------------------------
+;// This table contains the invidual byte values stored as
+;// halfwords. This avoids unpacking inside the function
+;//-------------------------------------------------------
+
+ M_TABLE armVCM4P10_VMatrixU16
+ DCW 10, 16, 13
+ DCW 11, 18, 14
+ DCW 13, 20, 16
+ DCW 14, 23, 18
+ DCW 16, 25, 20
+ DCW 18, 29, 23
+
+ ENDIF ;//ARM1136JS
+
+
+
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
new file mode 100755
index 0000000..6e912d7
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Align_unsafe_s.s
@@ -0,0 +1,236 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_Align_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ EXPORT armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ EXPORT armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+
+DEBUG_ON SETL {FALSE}
+
+ IF ARM1136JS
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 8
+iHeight RN 9
+
+;// Declare inner loop registers
+x RN 7
+x0 RN 7
+x1 RN 10
+x2 RN 11
+Scratch RN 12
+
+;// Function:
+;// armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+;//
+;// Implements copy from an arbitrary aligned source memory location (pSrc) to a 4 byte aligned
+;// destination pointed by (pDst) for horizontal interpolation.
+;// This function needs to copy 9 bytes in horizontal direction.
+;//
+;// Registers used as input for this function
+;// r0,r1,r8,r9 where r8 containings aligned memory pointer and r9 no rows to copy
+;//
+;// Registers preserved for top level function
+;// r2,r3,r4,r5,r6
+;//
+;// Registers modified by the function
+;// r7,r8,r9,r10,r11,r12
+;//
+;// Output registers
+;// r0 - pointer to the new aligned location which will be used as pSrc
+;// r1 - step size to this aligned location
+
+ ;// Function header
+ M_START armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+
+ ;// Copy pDst to scratch
+ MOV Scratch, pDst
+
+StartAlignedStackCopy
+ AND x, pSrc, #3
+ BIC pSrc, pSrc, #3
+
+ M_SWITCH x
+ M_CASE Copy0toAligned
+ M_CASE Copy1toAligned
+ M_CASE Copy2toAligned
+ M_CASE Copy3toAligned
+ M_ENDSWITCH
+
+Copy0toAligned
+ LDM pSrc, {x0, x1, x2}
+ SUBS iHeight, iHeight, #1
+ ADD pSrc, pSrc, srcStep
+
+ ;// One cycle stall
+
+ STM pDst!, {x0, x1, x2} ;// Store aligned output row
+ BGT Copy0toAligned
+ B CopyEnd
+
+Copy1toAligned
+ LDM pSrc, {x0, x1, x2}
+ SUBS iHeight, iHeight, #1
+ ADD pSrc, pSrc, srcStep
+
+ ;// One cycle stall
+
+ MOV x0, x0, LSR #8
+ ORR x0, x0, x1, LSL #24
+ MOV x1, x1, LSR #8
+ ORR x1, x1, x2, LSL #24
+ MOV x2, x2, LSR #8
+ STM pDst!, {x0, x1, x2} ;// Store aligned output row
+ BGT Copy1toAligned
+ B CopyEnd
+
+Copy2toAligned
+ LDM pSrc, {x0, x1, x2}
+ SUBS iHeight, iHeight, #1
+ ADD pSrc, pSrc, srcStep
+
+ ;// One cycle stall
+
+ MOV x0, x0, LSR #16
+ ORR x0, x0, x1, LSL #16
+ MOV x1, x1, LSR #16
+ ORR x1, x1, x2, LSL #16
+ MOV x2, x2, LSR #16
+ STM pDst!, {x0, x1, x2} ;// Store aligned output row
+ BGT Copy2toAligned
+ B CopyEnd
+
+Copy3toAligned
+ LDM pSrc, {x0, x1, x2}
+ SUBS iHeight, iHeight, #1
+ ADD pSrc, pSrc, srcStep
+
+ ;// One cycle stall
+
+ MOV x0, x0, LSR #24
+ ORR x0, x0, x1, LSL #8
+ MOV x1, x1, LSR #24
+ ORR x1, x1, x2, LSL #8
+ MOV x2, x2, LSR #24
+ STM pDst!, {x0, x1, x2} ;// Store aligned output row
+ BGT Copy3toAligned
+
+CopyEnd
+
+ MOV pSrc, Scratch
+ MOV srcStep, #12
+
+ M_END
+
+
+;// Function:
+;// armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+;//
+;// Implements copy from an arbitrary aligned source memory location (pSrc) to an aligned
+;// destination pointed by (pDst) for vertical interpolation.
+;// This function needs to copy 4 bytes in horizontal direction
+;//
+;// Registers used as input for this function
+;// r0,r1,r8,r9 where r8 containings aligned memory pointer and r9 no of rows to copy
+;//
+;// Registers preserved for top level function
+;// r2,r3,r4,r5,r6
+;//
+;// Registers modified by the function
+;// r7,r8,r9,r10,r11,r12
+;//
+;// Output registers
+;// r0 - pointer to the new aligned location which will be used as pSrc
+;// r1 - step size to this aligned location
+
+ ;// Function header
+ M_START armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+
+ ;// Copy pSrc to stack
+StartVAlignedStackCopy
+ AND x, pSrc, #3
+ BIC pSrc, pSrc, #3
+
+
+ M_SWITCH x
+ M_CASE Copy0toVAligned
+ M_CASE Copy1toVAligned
+ M_CASE Copy2toVAligned
+ M_CASE Copy3toVAligned
+ M_ENDSWITCH
+
+Copy0toVAligned
+ M_LDR x0, [pSrc], srcStep
+ SUBS iHeight, iHeight, #1
+
+ ;// One cycle stall
+
+ STR x0, [pDst], #4 ;// Store aligned output row
+ BGT Copy0toVAligned
+ B CopyVEnd
+
+Copy1toVAligned
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ SUBS iHeight, iHeight, #1
+
+ ;// One cycle stall
+
+ MOV x1, x1, LSL #24
+ ORR x0, x1, x0, LSR #8
+ STR x0, [pDst], #4 ;// Store aligned output row
+ BGT Copy1toVAligned
+ B CopyVEnd
+
+Copy2toVAligned
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ SUBS iHeight, iHeight, #1
+
+ ;// One cycle stall
+
+ MOV x1, x1, LSL #16
+ ORR x0, x1, x0, LSR #16
+ STR x0, [pDst], #4 ;// Store aligned output row
+ BGT Copy2toVAligned
+ B CopyVEnd
+
+Copy3toVAligned
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ SUBS iHeight, iHeight, #1
+
+ ;// One cycle stall
+
+ MOV x1, x1, LSL #8
+ ORR x0, x1, x0, LSR #24
+ STR x0, [pDst], #4 ;// Store aligned output row
+ BGT Copy3toVAligned
+
+CopyVEnd
+
+ SUB pSrc, pDst, #28
+ MOV srcStep, #4
+
+ M_END
+
+
+ ENDIF
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
new file mode 100755
index 0000000..d275891
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
@@ -0,0 +1,149 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_Copy_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+;// Function:
+;// armVCM4P10_InterpolateLuma_Copy4x4_unsafe
+;//
+;// Implements copy from an arbitrary aligned source memory location (pSrc) to an aligned
+;// destination pointed by (pDst)
+;//
+;// Registers preserved for top level function
+;// r1,r3,r4,r5,r6,r7,r10,r11,r14
+;//
+;// Registers modified by the function
+;// r0,r2,r8,r9,r12
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ EXPORT armVCM4P10_InterpolateLuma_Copy4x4_unsafe
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 2
+dstStep RN 3
+
+;// Declare other intermediate registers
+x0 RN 4
+x1 RN 5
+x2 RN 8
+x3 RN 9
+Temp RN 12
+
+ IF ARM1136JS
+
+ M_START armVCM4P10_InterpolateLuma_Copy4x4_unsafe, r6
+
+Copy4x4Start
+ ;// Do Copy and branch to EndOfInterpolation
+ AND Temp, pSrc, #3
+ BIC pSrc, pSrc, #3
+
+ M_SWITCH Temp
+ M_CASE Copy4x4Align0
+ M_CASE Copy4x4Align1
+ M_CASE Copy4x4Align2
+ M_CASE Copy4x4Align3
+ M_ENDSWITCH
+
+Copy4x4Align0
+ M_LDR x0, [pSrc], srcStep
+ M_LDR x1, [pSrc], srcStep
+ M_STR x0, [pDst], dstStep
+ M_LDR x2, [pSrc], srcStep
+ M_STR x1, [pDst], dstStep
+ M_LDR x3, [pSrc], srcStep
+ M_STR x2, [pDst], dstStep
+ M_STR x3, [pDst], dstStep
+ B Copy4x4End
+
+Copy4x4Align1
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ LDR x3, [pSrc, #4]
+ M_LDR x2, [pSrc], srcStep
+ MOV x0, x0, LSR #8
+ ORR x0, x0, x1, LSL #24
+ M_STR x0, [pDst], dstStep
+ MOV x2, x2, LSR #8
+ ORR x2, x2, x3, LSL #24
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ M_STR x2, [pDst], dstStep
+ LDR x3, [pSrc, #4]
+ M_LDR x2, [pSrc], srcStep
+ MOV x0, x0, LSR #8
+ ORR x0, x0, x1, LSL #24
+ M_STR x0, [pDst], dstStep
+ MOV x2, x2, LSR #8
+ ORR x2, x2, x3, LSL #24
+ M_STR x2, [pDst], dstStep
+ B Copy4x4End
+
+Copy4x4Align2
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ LDR x3, [pSrc, #4]
+ M_LDR x2, [pSrc], srcStep
+ MOV x0, x0, LSR #16
+ ORR x0, x0, x1, LSL #16
+ M_STR x0, [pDst], dstStep
+ MOV x2, x2, LSR #16
+ ORR x2, x2, x3, LSL #16
+ M_STR x2, [pDst], dstStep
+
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ LDR x3, [pSrc, #4]
+ M_LDR x2, [pSrc], srcStep
+ MOV x0, x0, LSR #16
+ ORR x0, x0, x1, LSL #16
+ M_STR x0, [pDst], dstStep
+ MOV x2, x2, LSR #16
+ ORR x2, x2, x3, LSL #16
+ M_STR x2, [pDst], dstStep
+ B Copy4x4End
+
+Copy4x4Align3
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ LDR x3, [pSrc, #4]
+ M_LDR x2, [pSrc], srcStep
+ MOV x0, x0, LSR #24
+ ORR x0, x0, x1, LSL #8
+ M_STR x0, [pDst], dstStep
+ MOV x2, x2, LSR #24
+ ORR x2, x2, x3, LSL #8
+ M_STR x2, [pDst], dstStep
+
+ LDR x1, [pSrc, #4]
+ M_LDR x0, [pSrc], srcStep
+ LDR x3, [pSrc, #4]
+ M_LDR x2, [pSrc], srcStep
+ MOV x0, x0, LSR #24
+ ORR x0, x0, x1, LSL #8
+ M_STR x0, [pDst], dstStep
+ MOV x2, x2, LSR #24
+ ORR x2, x2, x3, LSL #8
+ M_STR x2, [pDst], dstStep
+ B Copy4x4End
+
+Copy4x4End
+ M_END
+
+ ENDIF
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
new file mode 100755
index 0000000..4e5a39d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
@@ -0,0 +1,178 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS ARM1136JS
+
+ EXPORT armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe
+ EXPORT armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe
+
+;// Functions:
+;// armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe and
+;// armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe
+;//
+;// Implements re-arrangement of data from temporary buffer to a buffer pointed by pBuf.
+;// This will do the convertion of data from 16 bit to 8 bit and it also
+;// remove offset and check for saturation.
+;//
+;// Registers used as input for this function
+;// r0,r1,r7 where r0 is input pointer and r2 its step size, r7 is output pointer
+;//
+;// Registers preserved for top level function
+;// r4,r5,r6,r8,r9,r14
+;//
+;// Registers modified by the function
+;// r7,r10,r11,r12
+;//
+;// Output registers
+;// r0 - pointer to the destination location
+;// r1 - step size to this destination location
+
+
+DEBUG_ON SETL {FALSE}
+
+MASK EQU 0x80808080 ;// Mask is used to implement (a+b+1)/2
+
+;// Declare input registers
+
+pSrc0 RN 0
+srcStep0 RN 1
+
+;// Declare other intermediate registers
+Temp1 RN 4
+Temp2 RN 5
+Temp3 RN 10
+Temp4 RN 11
+pBuf RN 7
+r0x0fe00fe0 RN 6
+r0x00ff00ff RN 12
+Count RN 14
+ValueA0 RN 10
+ValueA1 RN 11
+
+ IF ARM1136JS
+
+
+ ;// Function header
+ M_START armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe, r6
+
+ ;// Code start
+ MOV Count, #4
+ LDR r0x0fe00fe0, =0x0fe00fe0
+ LDR r0x00ff00ff, =0x00ff00ff
+LoopStart1
+ LDR Temp4, [pSrc0, #12]
+ LDR Temp3, [pSrc0, #8]
+ LDR Temp2, [pSrc0, #4]
+ M_LDR Temp1, [pSrc0], srcStep0
+ UQSUB16 Temp4, Temp4, r0x0fe00fe0
+ UQSUB16 Temp3, Temp3, r0x0fe00fe0
+ UQSUB16 Temp2, Temp2, r0x0fe00fe0
+ UQSUB16 Temp1, Temp1, r0x0fe00fe0
+ USAT16 Temp4, #13, Temp4
+ USAT16 Temp3, #13, Temp3
+ USAT16 Temp2, #13, Temp2
+ USAT16 Temp1, #13, Temp1
+ AND Temp4, r0x00ff00ff, Temp4, LSR #5
+ AND Temp3, r0x00ff00ff, Temp3, LSR #5
+ AND Temp2, r0x00ff00ff, Temp2, LSR #5
+ AND Temp1, r0x00ff00ff, Temp1, LSR #5
+ ORR ValueA1, Temp3, Temp4, LSL #8
+ ORR ValueA0, Temp1, Temp2, LSL #8
+ SUBS Count, Count, #1
+ STRD ValueA0, [pBuf], #8
+ BGT LoopStart1
+End1
+ SUB pSrc0, pBuf, #32
+ MOV srcStep0, #8
+
+ M_END
+
+
+ ;// Function header
+ M_START armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe, r6
+
+ ;// Code start
+ LDR r0x0fe00fe0, =0x0fe00fe0
+ LDR r0x00ff00ff, =0x00ff00ff
+ MOV Count, #2
+
+LoopStart
+ LDR Temp4, [pSrc0, #12]
+ LDR Temp3, [pSrc0, #8]
+ LDR Temp2, [pSrc0, #4]
+ M_LDR Temp1, [pSrc0], srcStep0
+
+ UQSUB16 Temp4, Temp4, r0x0fe00fe0
+ UQSUB16 Temp3, Temp3, r0x0fe00fe0
+ UQSUB16 Temp2, Temp2, r0x0fe00fe0
+ UQSUB16 Temp1, Temp1, r0x0fe00fe0
+
+ USAT16 Temp4, #13, Temp4
+ USAT16 Temp3, #13, Temp3
+ USAT16 Temp2, #13, Temp2
+ USAT16 Temp1, #13, Temp1
+
+ AND Temp4, r0x00ff00ff, Temp4, LSR #5
+ AND Temp3, r0x00ff00ff, Temp3, LSR #5
+ AND Temp2, r0x00ff00ff, Temp2, LSR #5
+ AND Temp1, r0x00ff00ff, Temp1, LSR #5
+ ORR ValueA1, Temp3, Temp4, LSL #8 ;// [d2 c2 d0 c0]
+ ORR ValueA0, Temp1, Temp2, LSL #8 ;// [b2 a2 b0 a0]
+
+ PKHBT Temp1, ValueA0, ValueA1, LSL #16 ;// [d0 c0 b0 a0]
+
+ STR Temp1, [pBuf], #8
+ PKHTB Temp2, ValueA1, ValueA0, ASR #16 ;// [d2 c2 b2 a2]
+ STR Temp2, [pBuf], #-4
+
+ LDR Temp4, [pSrc0, #12]
+ LDR Temp3, [pSrc0, #8]
+ LDR Temp2, [pSrc0, #4]
+ M_LDR Temp1, [pSrc0], srcStep0
+
+ UQSUB16 Temp4, Temp4, r0x0fe00fe0
+ UQSUB16 Temp3, Temp3, r0x0fe00fe0
+ UQSUB16 Temp2, Temp2, r0x0fe00fe0
+ UQSUB16 Temp1, Temp1, r0x0fe00fe0
+
+ USAT16 Temp4, #13, Temp4
+ USAT16 Temp3, #13, Temp3
+ USAT16 Temp2, #13, Temp2
+ USAT16 Temp1, #13, Temp1
+
+ AND Temp4, r0x00ff00ff, Temp4, LSR #5
+ AND Temp3, r0x00ff00ff, Temp3, LSR #5
+ AND Temp2, r0x00ff00ff, Temp2, LSR #5
+ AND Temp1, r0x00ff00ff, Temp1, LSR #5
+ ORR ValueA1, Temp3, Temp4, LSL #8 ;// [d2 c2 d0 c0]
+ ORR ValueA0, Temp1, Temp2, LSL #8 ;// [b2 a2 b0 a0]
+
+ PKHBT Temp1, ValueA0, ValueA1, LSL #16 ;// [d0 c0 b0 a0]
+ SUBS Count, Count, #1
+ STR Temp1, [pBuf], #8
+ PKHTB Temp2, ValueA1, ValueA0, ASR #16 ;// [d2 c2 b2 a2]
+ STR Temp2, [pBuf], #4
+
+ BGT LoopStart
+End2
+ SUB pSrc0, pBuf, #32-8
+ MOV srcStep0, #4
+
+ M_END
+
+ ENDIF
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
new file mode 100755
index 0000000..d1684cb
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
@@ -0,0 +1,313 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ EXPORT armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+
+ M_VARIANTS CortexA8
+
+ IF CortexA8
+
+ M_START armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe, r11
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 2
+dstStep RN 3
+
+;// Declare Neon registers
+dCoeff5 DN 30.S16
+dCoeff20 DN 31.S16
+qCoeff5 QN 14.S32
+qCoeff20 QN 15.S32
+
+qSrc01 QN 0.U8
+dSrc0 DN 0.U8
+dSrc1 DN 1.U8
+
+dSrcb DN 4.U8
+dSrcc DN 2.U8
+dSrcd DN 3.U8
+dSrce DN 5.U8
+dSrcf DN 1.U8
+
+qSrcb QN 2.S16
+qSrcc QN 1.S16
+dSrcB DN 4.S16
+dSrcC DN 2.S16
+
+qRes0 QN 5.S16
+qRes1 QN 6.S16
+qRes2 QN 7.S16
+qRes3 QN 8.S16
+qRes4 QN 9.S16
+qRes5 QN 10.S16
+qRes6 QN 11.S16
+qRes7 QN 12.S16
+qRes8 QN 13.S16
+
+dRes0 DN 10.S16
+dRes1 DN 12.S16
+dRes2 DN 14.S16
+dRes3 DN 16.S16
+dRes4 DN 18.S16
+dRes5 DN 20.S16
+dRes6 DN 22.S16
+dRes7 DN 24.S16
+dRes8 DN 26.S16
+
+qAcc01 QN 5.S32
+qAcc23 QN 6.S32
+qAcc45 QN 2.S32
+qAcc67 QN 3.S32
+qSumBE QN 0.S32
+qSumCD QN 1.S32
+
+dTempAcc0 DN 0.U16
+dTempAcc1 DN 2.U16
+dTempAcc2 DN 4.U16
+dTempAcc3 DN 6.U16
+
+qTAcc0 QN 0.U16
+qTAcc1 QN 1.U16
+qTAcc2 QN 2.U16
+qTAcc3 QN 3.U16
+
+dAcc0 DN 0.U8
+dAcc1 DN 2.U8
+dAcc2 DN 4.U8
+dAcc3 DN 6.U8
+
+dTmp0 DN 8.S16
+dTmp1 DN 9.S16
+qTmp0 QN 4.S32
+
+ VLD1 qSrc01, [pSrc], srcStep ;// [a0 a1 a2 a3 ..]
+ VMOV dCoeff20, #20
+ VMOV dCoeff5, #5
+
+ ;// Row0
+ VEXT dSrcb, dSrc0, dSrc1, #1 ;// [b0 b1 b2 b3 ..]
+ VEXT dSrcc, dSrc0, dSrc1, #2
+ VEXT dSrcd, dSrc0, dSrc1, #3
+ VEXT dSrce, dSrc0, dSrc1, #4
+ VEXT dSrcf, dSrc0, dSrc1, #5 ;// [f0 f1 f2 f3 ..]
+ VADDL qSrcc, dSrcc, dSrcd ;// c+d
+ VADDL qSrcb, dSrcb, dSrce ;// b+e
+ VADDL qRes0, dSrc0, dSrcf ;// Acc=a+f
+ VLD1 qSrc01, [pSrc], srcStep ;// [a0 a1 a2 a3 ..]
+ VMLA dRes0, dSrcC, dCoeff20 ;// Acc += 20*(c+d)
+; VMLS dRes0, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+ VMUL dTmp0, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+
+ ;// Row1
+ VEXT dSrcb, dSrc0, dSrc1, #1 ;// [b0 b1 b2 b3 ..]
+ VEXT dSrcc, dSrc0, dSrc1, #2
+ VEXT dSrcd, dSrc0, dSrc1, #3
+ VEXT dSrce, dSrc0, dSrc1, #4
+ VEXT dSrcf, dSrc0, dSrc1, #5 ;// [f0 f1 f2 f3 ..]
+ VADDL qSrcc, dSrcc, dSrcd ;// c+d
+ VADDL qSrcb, dSrcb, dSrce ;// b+e
+ VADDL qRes1, dSrc0, dSrcf ;// Acc=a+f
+ VLD1 qSrc01, [pSrc], srcStep ;// [a0 a1 a2 a3 ..]
+
+ VSUB dRes0, dRes0, dTmp0 ;// TeRi
+
+ VMLA dRes1, dSrcC, dCoeff20 ;// Acc += 20*(c+d)
+; VMLS dRes1, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+ VMUL dTmp0, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+
+ ;// Row2
+ VEXT dSrcb, dSrc0, dSrc1, #1 ;// [b0 b1 b2 b3 ..]
+ VEXT dSrcc, dSrc0, dSrc1, #2
+ VEXT dSrcd, dSrc0, dSrc1, #3
+ VEXT dSrce, dSrc0, dSrc1, #4
+ VEXT dSrcf, dSrc0, dSrc1, #5 ;// [f0 f1 f2 f3 ..]
+ VADDL qSrcc, dSrcc, dSrcd ;// c+d
+ VADDL qSrcb, dSrcb, dSrce ;// b+e
+ VADDL qRes2, dSrc0, dSrcf ;// Acc=a+f
+ VLD1 qSrc01, [pSrc], srcStep ;// [a0 a1 a2 a3 ..]
+
+ VSUB dRes1, dRes1, dTmp0
+
+ VMLA dRes2, dSrcC, dCoeff20 ;// Acc += 20*(c+d)
+; VMLS dRes2, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+ VMUL dTmp0, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+
+ ;// Row3
+ VEXT dSrcb, dSrc0, dSrc1, #1 ;// [b0 b1 b2 b3 ..]
+ VEXT dSrcc, dSrc0, dSrc1, #2
+ VEXT dSrcd, dSrc0, dSrc1, #3
+ VEXT dSrce, dSrc0, dSrc1, #4
+ VEXT dSrcf, dSrc0, dSrc1, #5 ;// [f0 f1 f2 f3 ..]
+ VADDL qSrcc, dSrcc, dSrcd ;// c+d
+ VADDL qSrcb, dSrcb, dSrce ;// b+e
+ VADDL qRes3, dSrc0, dSrcf ;// Acc=a+f
+ VLD1 qSrc01, [pSrc], srcStep ;// [a0 a1 a2 a3 ..]
+
+ VSUB dRes2, dRes2, dTmp0
+
+ VMLA dRes3, dSrcC, dCoeff20 ;// Acc += 20*(c+d)
+; VMLS dRes3, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+ VMUL dTmp0, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+
+ ;// Row4
+ VEXT dSrcb, dSrc0, dSrc1, #1 ;// [b0 b1 b2 b3 ..]
+ VEXT dSrcc, dSrc0, dSrc1, #2
+ VEXT dSrcd, dSrc0, dSrc1, #3
+ VEXT dSrce, dSrc0, dSrc1, #4
+ VEXT dSrcf, dSrc0, dSrc1, #5 ;// [f0 f1 f2 f3 ..]
+ VADDL qSrcc, dSrcc, dSrcd ;// c+d
+ VADDL qSrcb, dSrcb, dSrce ;// b+e
+ VADDL qRes4, dSrc0, dSrcf ;// Acc=a+f
+ VLD1 qSrc01, [pSrc], srcStep ;// [a0 a1 a2 a3 ..]
+
+ VSUB dRes3, dRes3, dTmp0
+
+ VMLA dRes4, dSrcC, dCoeff20 ;// Acc += 20*(c+d)
+; VMLS dRes4, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+ VMUL dTmp0, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+
+ ;// Row5
+ VEXT dSrcb, dSrc0, dSrc1, #1 ;// [b0 b1 b2 b3 ..]
+ VEXT dSrcc, dSrc0, dSrc1, #2
+ VEXT dSrcd, dSrc0, dSrc1, #3
+ VEXT dSrce, dSrc0, dSrc1, #4
+ VEXT dSrcf, dSrc0, dSrc1, #5 ;// [f0 f1 f2 f3 ..]
+ VADDL qSrcc, dSrcc, dSrcd ;// c+d
+ VADDL qSrcb, dSrcb, dSrce ;// b+e
+ VADDL qRes5, dSrc0, dSrcf ;// Acc=a+f
+ VLD1 qSrc01, [pSrc], srcStep ;// [a0 a1 a2 a3 ..]
+
+ VSUB dRes4, dRes4, dTmp0
+
+ VMLA dRes5, dSrcC, dCoeff20 ;// Acc += 20*(c+d)
+; VMLS dRes5, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+ VMUL dTmp0, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+
+ ;// Row6
+ VEXT dSrcb, dSrc0, dSrc1, #1 ;// [b0 b1 b2 b3 ..]
+ VEXT dSrcc, dSrc0, dSrc1, #2
+ VEXT dSrcd, dSrc0, dSrc1, #3
+ VEXT dSrce, dSrc0, dSrc1, #4
+ VEXT dSrcf, dSrc0, dSrc1, #5 ;// [f0 f1 f2 f3 ..]
+ VADDL qSrcc, dSrcc, dSrcd ;// c+d
+ VADDL qSrcb, dSrcb, dSrce ;// b+e
+ VADDL qRes6, dSrc0, dSrcf ;// Acc=a+f
+ VLD1 qSrc01, [pSrc], srcStep ;// [a0 a1 a2 a3 ..]
+
+ VSUB dRes5, dRes5, dTmp0
+
+ VMLA dRes6, dSrcC, dCoeff20 ;// Acc += 20*(c+d)
+; VMLS dRes6, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+ VMUL dTmp0, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+
+ ;// Row7
+ VEXT dSrcb, dSrc0, dSrc1, #1 ;// [b0 b1 b2 b3 ..]
+ VEXT dSrcc, dSrc0, dSrc1, #2
+ VEXT dSrcd, dSrc0, dSrc1, #3
+ VEXT dSrce, dSrc0, dSrc1, #4
+ VEXT dSrcf, dSrc0, dSrc1, #5 ;// [f0 f1 f2 f3 ..]
+ VADDL qSrcc, dSrcc, dSrcd ;// c+d
+ VADDL qSrcb, dSrcb, dSrce ;// b+e
+ VADDL qRes7, dSrc0, dSrcf ;// Acc=a+f
+ VLD1 qSrc01, [pSrc], srcStep ;// [a0 a1 a2 a3 ..]
+
+ VSUB dRes6, dRes6, dTmp0
+
+ VMLA dRes7, dSrcC, dCoeff20 ;// Acc += 20*(c+d)
+; VMLS dRes7, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+ VMUL dTmp0, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+
+ ;// Row8
+ VEXT dSrcb, dSrc0, dSrc1, #1 ;// [b0 b1 b2 b3 ..]
+ VEXT dSrcc, dSrc0, dSrc1, #2
+ VEXT dSrcd, dSrc0, dSrc1, #3
+ VEXT dSrce, dSrc0, dSrc1, #4
+ VEXT dSrcf, dSrc0, dSrc1, #5 ;// [f0 f1 f2 f3 ..]
+ VADDL qSrcc, dSrcc, dSrcd ;// c+d
+ VADDL qSrcb, dSrcb, dSrce ;// b+e
+ VADDL qRes8, dSrc0, dSrcf ;// Acc=a+f
+
+ VSUB dRes7, dRes7, dTmp0
+
+ VMLA dRes8, dSrcC, dCoeff20 ;// Acc += 20*(c+d)
+; VMLS dRes8, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+ VMUL dTmp0, dSrcB, dCoeff5 ;// Acc -= 5*(b+e)
+
+ VMOV qCoeff20, #20
+ VMOV qCoeff5, #5
+
+ ;// Col0
+ VADDL qAcc01, dRes0, dRes5 ;// Acc = a+f
+ VADDL qSumCD, dRes2, dRes3 ;// c+d
+ VADDL qSumBE, dRes1, dRes4 ;// b+e
+
+ VSUB dRes8, dRes8, dTmp0
+
+ VMLA qAcc01, qSumCD, qCoeff20 ;// Acc += 20*(c+d)
+; VMLS qAcc01, qSumBE, qCoeff5 ;// Acc -= 20*(b+e)
+ VMUL qTmp0, qSumBE, qCoeff5 ;// Acc -= 20*(b+e)
+
+ ;// Col1
+ VADDL qAcc23, dRes1, dRes6 ;// Acc = a+f
+ VADDL qSumCD, dRes3, dRes4 ;// c+d
+ VADDL qSumBE, dRes2, dRes5 ;// b+e
+ VMLA qAcc23, qSumCD, qCoeff20 ;// Acc += 20*(c+d)
+
+ VSUB qAcc01, qAcc01, qTmp0
+
+; VMLS qAcc23, qSumBE, qCoeff5 ;// Acc -= 20*(b+e)
+ VMUL qTmp0, qSumBE, qCoeff5 ;// Acc -= 20*(b+e)
+
+ ;// Col2
+ VADDL qAcc45, dRes2, dRes7 ;// Acc = a+f
+ VADDL qSumCD, dRes4, dRes5 ;// c+d
+ VADDL qSumBE, dRes3, dRes6 ;// b+e
+ VMLA qAcc45, qSumCD, qCoeff20 ;// Acc += 20*(c+d)
+
+ VSUB qAcc23, qAcc23, qTmp0
+
+; VMLS qAcc45, qSumBE, qCoeff5 ;// Acc -= 20*(b+e)
+ VMUL qTmp0, qSumBE, qCoeff5 ;// Acc -= 20*(b+e)
+
+ ;// Col3
+ VADDL qAcc67, dRes3, dRes8 ;// Acc = a+f
+ VADDL qSumCD, dRes5, dRes6 ;// c+d
+ VADDL qSumBE, dRes4, dRes7 ;// b+e
+ VMLA qAcc67, qSumCD, qCoeff20 ;// Acc += 20*(c+d)
+
+ VSUB qAcc45, qAcc45, qTmp0
+
+ VMLS qAcc67, qSumBE, qCoeff5 ;// Acc -= 20*(b+e)
+
+ VQRSHRUN dTempAcc0, qAcc01, #10
+ VQRSHRUN dTempAcc1, qAcc23, #10
+ VQRSHRUN dTempAcc2, qAcc45, #10
+ VQRSHRUN dTempAcc3, qAcc67, #10
+
+ VQMOVN dAcc0, qTAcc0
+ VQMOVN dAcc1, qTAcc1
+ VQMOVN dAcc2, qTAcc2
+ VQMOVN dAcc3, qTAcc3
+
+ M_END
+
+ ENDIF
+
+
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
new file mode 100755
index 0000000..7bc091f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
@@ -0,0 +1,266 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ EXPORT armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+
+ M_VARIANTS CortexA8
+
+ IF CortexA8
+ M_START armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe, r11
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 2
+dstStep RN 3
+
+;// Declare Neon registers
+dTCoeff5 DN 30.U8
+dTCoeff20 DN 31.U8
+dCoeff5 DN 30.S16
+dCoeff20 DN 31.S16
+
+qSrcA01 QN 0.U8
+qSrcB23 QN 1.U8
+qSrcC45 QN 2.U8
+qSrcD67 QN 3.U8
+qSrcE89 QN 4.U8
+qSrcF1011 QN 5.U8
+qSrcG1213 QN 6.U8
+qSrcH1415 QN 7.U8
+qSrcI1617 QN 8.U8
+
+dSrcA0 DN 0.U8
+dSrcB2 DN 2.U8
+dSrcC4 DN 4.U8
+dSrcD6 DN 6.U8
+dSrcE8 DN 8.U8
+dSrcF10 DN 10.U8
+dSrcG12 DN 12.U8
+dSrcH14 DN 14.U8
+dSrcI16 DN 16.U8
+
+dSrcA1 DN 1.U8
+dSrcB3 DN 3.U8
+dSrcC5 DN 5.U8
+dSrcD7 DN 7.U8
+dSrcE9 DN 9.U8
+dSrcF11 DN 11.U8
+dSrcG13 DN 13.U8
+dSrcH15 DN 15.U8
+dSrcI17 DN 17.U8
+
+qTempP01 QN 9.S16
+qTempQ01 QN 10.S16
+qTempR01 QN 11.S16
+qTempS01 QN 12.S16
+
+qTempP23 QN 0.S16
+qTempQ23 QN 1.S16
+qTempR23 QN 2.S16
+qTempS23 QN 3.S16
+
+dTempP0 DN 18.S16
+dTempP1 DN 19.S16
+dTempP2 DN 0.S16
+
+dTempQ0 DN 20.S16
+dTempQ1 DN 21.S16
+dTempQ2 DN 2.S16
+
+dTempR0 DN 22.S16
+dTempR1 DN 23.S16
+dTempR2 DN 4.S16
+
+dTempS0 DN 24.S16
+dTempS1 DN 25.S16
+dTempS2 DN 6.S16
+
+dTempB0 DN 26.S16
+dTempC0 DN 27.S16
+dTempD0 DN 28.S16
+dTempF0 DN 29.S16
+
+dTempAcc0 DN 0.U16
+dTempAcc1 DN 2.U16
+dTempAcc2 DN 4.U16
+dTempAcc3 DN 6.U16
+
+dAcc0 DN 0.U8
+dAcc1 DN 2.U8
+dAcc2 DN 4.U8
+dAcc3 DN 6.U8
+
+qAcc0 QN 0.S32
+qAcc1 QN 1.S32
+qAcc2 QN 2.S32
+qAcc3 QN 3.S32
+
+qTAcc0 QN 0.U16
+qTAcc1 QN 1.U16
+qTAcc2 QN 2.U16
+qTAcc3 QN 3.U16
+
+qTmp QN 4.S16
+dTmp DN 8.S16
+
+ VLD1 qSrcA01, [pSrc], srcStep ;// [a0 a1 a2 a3 .. a15]
+ ADD r12, pSrc, srcStep, LSL #2
+ VMOV dTCoeff5, #5
+ VMOV dTCoeff20, #20
+ VLD1 qSrcF1011, [r12], srcStep
+ VLD1 qSrcB23, [pSrc], srcStep ;// [b0 b1 b2 b3 .. b15]
+
+ VLD1 qSrcG1213, [r12], srcStep
+ VADDL qTempP01, dSrcA0, dSrcF10
+ VLD1 qSrcC45, [pSrc], srcStep ;// [c0 c1 c2 c3 .. c15]
+ VADDL qTempP23, dSrcA1, dSrcF11
+ VLD1 qSrcD67, [pSrc], srcStep
+ VADDL qTempQ01, dSrcB2, dSrcG12
+ VLD1 qSrcE89, [pSrc], srcStep
+
+ ;//t0
+ VMLAL qTempP01, dSrcC4, dTCoeff20
+
+ VLD1 qSrcH1415, [r12], srcStep
+
+ VMLAL qTempP23, dSrcC5, dTCoeff20
+
+ VLD1 qSrcI1617, [r12], srcStep ;// [i0 i1 i2 i3 .. ]
+
+ VMLAL qTempP01, dSrcD6, dTCoeff20
+ VMLAL qTempQ01, dSrcD6, dTCoeff20
+ VMLSL qTempP23, dSrcB3, dTCoeff5
+
+ VADDL qTempR01, dSrcC4, dSrcH14
+
+ VMLSL qTempP01, dSrcB2, dTCoeff5
+
+ VADDL qTempQ23, dSrcB3, dSrcG13
+
+ VMLAL qTempP23, dSrcD7, dTCoeff20
+ VMLAL qTempQ01, dSrcE8, dTCoeff20
+
+ VMLSL qTempP01, dSrcE8, dTCoeff5
+ VMLAL qTempQ23, dSrcD7, dTCoeff20
+
+ VMLSL qTempP23, dSrcE9, dTCoeff5
+
+ ;//t1
+
+ VMLAL qTempR01, dSrcE8, dTCoeff20
+ VMLSL qTempQ01, dSrcC4, dTCoeff5
+ VMLSL qTempQ23, dSrcC5, dTCoeff5
+ VADDL qTempR23, dSrcC5, dSrcH15
+
+ VMLAL qTempR01, dSrcF10, dTCoeff20
+ VMLSL qTempQ01, dSrcF10, dTCoeff5
+ VMLAL qTempQ23, dSrcE9, dTCoeff20
+ VMLAL qTempR23, dSrcE9, dTCoeff20
+ VADDL qTempS01, dSrcD6, dSrcI16
+
+
+ VMLSL qTempR01, dSrcD6, dTCoeff5
+ VMLSL qTempQ23, dSrcF11, dTCoeff5
+ VMLSL qTempR23, dSrcD7, dTCoeff5
+
+ ;//t2
+ VADDL qTempS23, dSrcD7, dSrcI17
+ VMLAL qTempS01, dSrcF10, dTCoeff20
+ VMLSL qTempR01, dSrcG12, dTCoeff5
+ VMLSL qTempR23, dSrcG13, dTCoeff5
+
+ VMLAL qTempS23, dSrcF11, dTCoeff20
+ VMLAL qTempS01, dSrcG12, dTCoeff20
+ VEXT dTempB0, dTempP0, dTempP1, #1
+ VMLAL qTempR23, dSrcF11, dTCoeff20
+
+
+ ;//t3
+ VMLAL qTempS23, dSrcG13, dTCoeff20
+ VMLSL qTempS01, dSrcE8, dTCoeff5
+ VEXT dTempC0, dTempP0, dTempP1, #2
+ VMOV dCoeff20, #20
+ VMLSL qTempS23, dSrcE9, dTCoeff5
+ VMLSL qTempS01, dSrcH14, dTCoeff5
+ VEXT dTempF0, dTempP1, dTempP2, #1
+ VEXT dTempD0, dTempP0, dTempP1, #3
+ VMLSL qTempS23, dSrcH15, dTCoeff5
+
+ VADDL qAcc0, dTempP0, dTempF0
+ VADD dTempC0, dTempC0, dTempD0
+ ;//h
+ VMOV dCoeff5, #5
+
+ ;// res0
+ VADD dTempB0, dTempB0, dTempP1
+ VMLAL qAcc0, dTempC0, dCoeff20
+ VEXT dTempC0, dTempQ0, dTempQ1, #2
+ VEXT dTempD0, dTempQ0, dTempQ1, #3
+ VEXT dTempF0, dTempQ1, dTempQ2, #1
+ VMLSL qAcc0, dTempB0, dCoeff5
+
+ ;// res1
+ VEXT dTempB0, dTempQ0, dTempQ1, #1
+ VADDL qAcc1, dTempQ0, dTempF0
+ VADD dTempC0, dTempC0, dTempD0
+ VADD dTempB0, dTempB0, dTempQ1
+ VEXT dTempD0, dTempR0, dTempR1, #3
+ VMLAL qAcc1, dTempC0, dCoeff20
+ VEXT dTempF0, dTempR1, dTempR2, #1
+ VEXT dTempC0, dTempR0, dTempR1, #2
+ VEXT dTmp, dTempR0, dTempR1, #1
+ VADDL qAcc2, dTempR0, dTempF0
+ VMLSL qAcc1, dTempB0, dCoeff5
+; VEXT dTempB0, dTempR0, dTempR1, #1
+ VADD dTempC0, dTempC0, dTempD0
+
+ ;// res2
+ VADD dTempB0, dTmp, dTempR1
+ VEXT dTempD0, dTempS0, dTempS1, #3
+ VMLAL qAcc2, dTempC0, dCoeff20
+; VADD dTempB0, dTempB0, dTempR1
+
+ ;// res3
+ VEXT dTempC0, dTempS0, dTempS1, #2
+ VEXT dTempF0, dTempS1, dTempS2, #1
+ VADD dTempC0, dTempC0, dTempD0
+ VEXT dTmp, dTempS0, dTempS1, #1
+ VADDL qAcc3, dTempS0, dTempF0
+ VMLSL qAcc2, dTempB0, dCoeff5
+ VMLAL qAcc3, dTempC0, dCoeff20
+ VADD dTmp, dTmp, dTempS1
+ VMLSL qAcc3, dTmp, dCoeff5
+
+ VQRSHRUN dTempAcc0, qAcc0, #10
+ VQRSHRUN dTempAcc1, qAcc1, #10
+ VQRSHRUN dTempAcc2, qAcc2, #10
+ VQRSHRUN dTempAcc3, qAcc3, #10
+
+ VQMOVN dAcc0, qTAcc0
+ VQMOVN dAcc1, qTAcc1
+ VQMOVN dAcc2, qTAcc2
+ VQMOVN dAcc3, qTAcc3
+
+ M_END
+
+ ENDIF
+
+
+
+
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
new file mode 100755
index 0000000..babe8ad
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
@@ -0,0 +1,228 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+ EXPORT armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+
+DEBUG_ON SETL {FALSE}
+
+ IF CortexA8
+
+ M_START armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe, r11
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 2
+dstStep RN 3
+
+;// Declare Neon registers
+dCoeff5 DN 30.S16
+dCoeff20 DN 31.S16
+
+qSrcA01 QN 11.U8
+qSrcB01 QN 12.U8
+qSrcC01 QN 13.U8
+qSrcD01 QN 14.U8
+
+dSrcA0 DN 22.U8
+dSrcA1 DN 23.U8
+dSrcB0 DN 24.U8
+dSrcB1 DN 25.U8
+dSrcC0 DN 26.U8
+dSrcC1 DN 27.U8
+dSrcD0 DN 28.U8
+dSrcD1 DN 29.U8
+
+dSrcb DN 12.U8
+dSrce DN 13.U8
+dSrcf DN 10.U8
+
+dSrc0c DN 14.U8
+dSrc1c DN 16.U8
+dSrc2c DN 18.U8
+dSrc3c DN 20.U8
+
+dSrc0d DN 15.U8
+dSrc1d DN 17.U8
+dSrc2d DN 19.U8
+dSrc3d DN 21.U8
+
+qTemp01 QN 4.S16
+qTemp23 QN 6.S16
+dTemp0 DN 8.S16
+dTemp2 DN 12.S16
+
+qRes01 QN 11.S16
+qRes23 QN 12.S16
+qRes45 QN 13.S16
+qRes67 QN 14.S16
+
+dRes0 DN 22.S16
+dRes2 DN 24.S16
+dRes4 DN 26.S16
+dRes6 DN 28.S16
+
+dAcc0 DN 22.U8
+dAcc2 DN 24.U8
+dAcc4 DN 26.U8
+dAcc6 DN 28.U8
+
+dResult0 DN 22.U32
+dResult2 DN 24.U32
+dResult4 DN 26.U32
+dResult6 DN 28.U32
+
+ VLD1 qSrcA01, [pSrc], srcStep ;// Load A register [a0 a1 a2 a3 ..]
+ ;// One cycle stall
+ VEXT dSrcf, dSrcA0, dSrcA1, #5 ;// [f0 f1 f2 f3 ..]
+ VEXT dSrcb, dSrcA0, dSrcA1, #1 ;// [b0 b1 b2 b3 ..]
+; VLD1 qSrcB01, [pSrc], srcStep ;// Load B register [a0 a1 a2 a3 ..]
+ VEXT dSrc0c, dSrcA0, dSrcA1, #2
+ VEXT dSrc0d, dSrcA0, dSrcA1, #3
+ VEXT dSrce, dSrcA0, dSrcA1, #4
+ VADDL qRes01, dSrcA0, dSrcf ;// Acc=a+f
+ VADDL qTemp01, dSrc0c, dSrc0d ;// c+d
+ VADDL qTemp23, dSrcb, dSrce ;// b+e
+
+ VLD1 qSrcB01, [pSrc], srcStep ;// Load B register [a0 a1 a2 a3 ..]
+; VLD1 qSrcC01, [pSrc], srcStep ;// Load C register [a0 a1 a2 a3 ..]
+ VMLA dRes0, dTemp0, dCoeff20 ;// Acc += 20*(c+d)
+; VMLS dRes0, dTemp2, dCoeff5 ;// Acc -= 5*(b+e)
+ VMUL dTemp0, dTemp2, dCoeff5 ;// TeRi
+
+ VEXT dSrcf, dSrcB0, dSrcB1, #5 ;// [f0 f1 f2 f3 ..]
+ VEXT dSrcb, dSrcB0, dSrcB1, #1 ;// [b0 b1 b2 b3 ..]
+ VEXT dSrc1c, dSrcB0, dSrcB1, #2
+ VEXT dSrc1d, dSrcB0, dSrcB1, #3
+ VEXT dSrce, dSrcB0, dSrcB1, #4
+ VADDL qRes23, dSrcB0, dSrcf ;// Acc=a+f
+
+ VSUB dRes0, dRes0, dTemp0 ;// TeRi
+
+ VADDL qTemp01, dSrc1c, dSrc1d ;// c+d
+ VADDL qTemp23, dSrcb, dSrce ;// b+e
+
+ VLD1 qSrcC01, [pSrc], srcStep ;// Load C register [a0 a1 a2 a3 ..]
+; VLD1 qSrcD01, [pSrc], srcStep ;// Load D register [a0 a1 a2 a3 ..]
+
+ VMLA dRes2, dTemp0, dCoeff20 ;// Acc += 20*(c+d)
+; VMLS dRes2, dTemp2, dCoeff5 ;// Acc -= 5*(b+e)
+ VMUL dTemp0, dTemp2, dCoeff5 ;// TeRi
+
+ VEXT dSrcf, dSrcC0, dSrcC1, #5 ;// [f0 f1 f2 f3 ..]
+ VEXT dSrcb, dSrcC0, dSrcC1, #1 ;// [b0 b1 b2 b3 ..]
+ VEXT dSrc2c, dSrcC0, dSrcC1, #2
+ VEXT dSrc2d, dSrcC0, dSrcC1, #3
+ VEXT dSrce, dSrcC0, dSrcC1, #4
+ VADDL qRes45, dSrcC0, dSrcf ;// Acc=a+f
+
+ VSUB dRes2, dRes2, dTemp0 ;// TeRi
+
+ VADDL qTemp01, dSrc2c, dSrc2d ;// c+d
+ VADDL qTemp23, dSrcb, dSrce ;// b+e
+
+ VLD1 qSrcD01, [pSrc], srcStep ;// Load D register [a0 a1 a2 a3 ..]
+
+ VMLA dRes4, dTemp0, dCoeff20 ;// Acc += 20*(c+d)
+; VMLS dRes4, dTemp2, dCoeff5 ;// Acc -= 5*(b+e)
+ VMUL dTemp0, dTemp2, dCoeff5 ;// Acc -= 5*(b+e) TeRi
+
+
+ VEXT dSrcf, dSrcD0, dSrcD1, #5 ;// [f0 f1 f2 f3 ..]
+ VEXT dSrcb, dSrcD0, dSrcD1, #1 ;// [b0 b1 b2 b3 ..]
+ VEXT dSrc3c, dSrcD0, dSrcD1, #2
+ VEXT dSrc3d, dSrcD0, dSrcD1, #3
+ VEXT dSrce, dSrcD0, dSrcD1, #4
+ VADDL qRes67, dSrcD0, dSrcf ;// Acc=a+f
+
+ VSUB dRes4, dRes4, dTemp0 ;// TeRi
+
+ VADDL qTemp01, dSrc3c, dSrc3d ;// c+d
+ VADDL qTemp23, dSrcb, dSrce ;// b+e
+ VMLA dRes6, dTemp0, dCoeff20 ;// Acc += 20*(c+d)
+ VMLS dRes6, dTemp2, dCoeff5 ;// Acc -= 5*(b+e)
+
+ VQRSHRUN dAcc0, qRes01, #5 ;// Acc = Sat ((Acc + 16) / 32)
+ VQRSHRUN dAcc2, qRes23, #5 ;// Acc = Sat ((Acc + 16) / 32)
+ VQRSHRUN dAcc4, qRes45, #5 ;// Acc = Sat ((Acc + 16) / 32)
+ VQRSHRUN dAcc6, qRes67, #5 ;// Acc = Sat ((Acc + 16) / 32)
+
+ M_END
+
+ ENDIF
+
+
+ END
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
new file mode 100755
index 0000000..89c90aa
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
@@ -0,0 +1,134 @@
+;//
+;//
+;// File Name: armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+ EXPORT armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+
+ IF CortexA8
+
+ M_START armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe, r11
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 2
+dstStep RN 3
+
+Temp RN 12
+
+;// Declare Neon registers
+dCoeff5 DN 30.S16
+dCoeff20 DN 31.S16
+
+dSrc0 DN 7.U8
+dSrc1 DN 8.U8
+dSrc2 DN 9.U8
+dSrc3 DN 10.U8
+dSrc4 DN 11.U8
+dSrc5 DN 12.U8
+dSrc6 DN 13.U8
+dSrc7 DN 14.U8
+dSrc8 DN 15.U8
+
+qSumBE01 QN 8.S16
+qSumCD01 QN 9.S16
+dSumBE0 DN 16.S16
+dSumCD0 DN 18.S16
+
+qAcc01 QN 0.S16
+qAcc23 QN 1.S16
+qAcc45 QN 2.S16
+qAcc67 QN 3.S16
+
+dRes0 DN 0.S16
+dRes1 DN 2.S16
+dRes2 DN 4.S16
+dRes3 DN 6.S16
+
+dAcc0 DN 0.U8
+dAcc1 DN 2.U8
+dAcc2 DN 4.U8
+dAcc3 DN 6.U8
+
+
+dTmp0 DN 20.S16
+dTmp1 DN 21.S16
+dTmp2 DN 22.S16
+dTmp3 DN 23.S16
+
+
+ VLD1 dSrc0, [pSrc], srcStep ;// [a0 a1 a2 a3 .. ]
+ ADD Temp, pSrc, srcStep, LSL #2
+ VLD1 dSrc1, [pSrc], srcStep ;// [b0 b1 b2 b3 .. ]
+ ;// One cycle stall
+ VLD1 dSrc5, [Temp], srcStep
+ ;// One cycle stall
+ VLD1 dSrc2, [pSrc], srcStep ;// [c0 c1 c2 c3 .. ]
+ VADDL qAcc01, dSrc0, dSrc5 ;// Acc = a+f
+ VLD1 dSrc3, [pSrc], srcStep
+ ;// One cycle stall
+ VLD1 dSrc6, [Temp], srcStep ;// TeRi
+
+ VLD1 dSrc4, [pSrc], srcStep
+ VLD1 dSrc7, [Temp], srcStep ;// TeRi
+ VADDL qSumBE01, dSrc1, dSrc4 ;// b+e
+ VADDL qSumCD01, dSrc2, dSrc3 ;// c+d
+ VLD1 dSrc8, [Temp], srcStep ;// TeRi
+ VMLS dRes0, dSumBE0, dCoeff5 ;// Acc -= 20*(b+e)
+; VMLA dRes0, dSumCD0, dCoeff20 ;// Acc += 20*(c+d)
+ VMUL dTmp0, dSumCD0, dCoeff20 ;// Acc += 20*(c+d)
+
+; VLD1 dSrc6, [Temp], srcStep
+ VADDL qSumBE01, dSrc2, dSrc5 ;// b+e
+ VADDL qSumCD01, dSrc3, dSrc4 ;// c+d
+ VADDL qAcc23, dSrc1, dSrc6 ;// Acc = a+f
+ VMLS dRes1, dSumBE0, dCoeff5 ;// Acc -= 20*(b+e)
+; VMLA dRes1, dSumCD0, dCoeff20 ;// Acc += 20*(c+d)
+ VMUL dTmp1, dSumCD0, dCoeff20 ;// Acc += 20*(c+d)
+
+; VLD1 dSrc7, [Temp], srcStep
+ VADDL qSumBE01, dSrc3, dSrc6 ;// b+e
+ VADDL qSumCD01, dSrc4, dSrc5 ;// c+d
+ VADDL qAcc45, dSrc2, dSrc7 ;// Acc = a+f
+ VMLS dRes2, dSumBE0, dCoeff5 ;// Acc -= 20*(b+e)
+; VMLA dRes2, dSumCD0, dCoeff20 ;// Acc += 20*(c+d)
+ VMUL dTmp2, dSumCD0, dCoeff20 ;// Acc += 20*(c+d)
+
+; VLD1 dSrc8, [Temp], srcStep ;// [i0 i1 i2 i3 .. ]
+ VADDL qSumBE01, dSrc4, dSrc7 ;// b+e
+ VADDL qAcc67, dSrc3, dSrc8 ;// Acc = a+f
+ VADDL qSumCD01, dSrc5, dSrc6 ;// c+d
+ VMLS dRes3, dSumBE0, dCoeff5 ;// Acc -= 20*(b+e)
+ VADD dRes0, dRes0, dTmp0
+ VADD dRes1, dRes1, dTmp1
+ VADD dRes2, dRes2, dTmp2
+ VMLA dRes3, dSumCD0, dCoeff20 ;// Acc += 20*(c+d)
+; VMUL dTmp3, dSumCD0, dCoeff20 ;// Acc += 20*(c+d)
+; VADD dRes3, dRes3, dTmp3
+
+ VQRSHRUN dAcc0, qAcc01, #5
+ VQRSHRUN dAcc1, qAcc23, #5
+ VQRSHRUN dAcc2, qAcc45, #5
+ VQRSHRUN dAcc3, qAcc67, #5
+
+ M_END
+
+ ENDIF
+
+
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
new file mode 100755
index 0000000..0f0ec78
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_Interpolate_Chroma_s.s
@@ -0,0 +1,318 @@
+;//
+;//
+;// File Name: armVCM4P10_Interpolate_Chroma_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 9641
+;// Date: Thursday, February 7, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+
+ IF CortexA8
+
+ M_TABLE armVCM4P10_WidthBranchTableMVIsNotZero
+
+ DCD WidthIs2MVIsNotZero, WidthIs2MVIsNotZero
+ DCD WidthIs4MVIsNotZero, WidthIs4MVIsNotZero
+ DCD WidthIs8MVIsNotZero
+
+ M_TABLE armVCM4P10_WidthBranchTableMVIsZero
+
+ DCD WidthIs2MVIsZero, WidthIs2MVIsZero
+ DCD WidthIs4MVIsZero, WidthIs4MVIsZero
+ DCD WidthIs8MVIsZero
+
+
+;// input registers
+
+pSrc RN 0
+iSrcStep RN 1
+pDst RN 2
+iDstStep RN 3
+iWidth RN 4
+iHeight RN 5
+dx RN 6
+dy RN 7
+
+;// local variable registers
+pc RN 15
+return RN 0
+EightMinusdx RN 8
+EightMinusdy RN 9
+
+ACoeff RN 12
+BCoeff RN 9
+CCoeff RN 8
+DCoeff RN 6
+
+pTable RN 11
+
+Step1 RN 10
+SrcStepMinus1 RN 14
+
+dACoeff DN D12.U8
+dBCoeff DN D13.U8
+dCCoeff DN D14.U8
+dDCoeff DN D15.U8
+
+dRow0a DN D0.U8
+dRow0b DN D1.U8
+dRow1a DN D2.U8
+dRow1b DN D3.U8
+
+qRow0a QN Q2.S16
+qRow0b QN Q3.S16
+
+;//dIndex DN D16.U8
+qRow1a QN Q11.S16
+qRow1b QN Q12.S16
+
+dRow2a DN D16.U8
+dRow2b DN D17.U8
+dRow3a DN D18.U8
+dRow3b DN D19.U8
+
+qOutRow2 QN Q11.U16
+qOutRow3 QN Q12.U16
+dOutRow2 DN D20.U8
+dOutRow3 DN D21.U8
+dOutRow2U64 DN D20.U64
+dOutRow3U64 DN D21.U64
+
+qOutRow0 QN Q2.U16
+qOutRow1 QN Q3.U16
+dOutRow0 DN D8.U8
+dOutRow1 DN D9.U8
+
+dOutRow0U64 DN D8.U64
+dOutRow1U64 DN D9.U64
+
+dOutRow0U32 DN D8.U32
+dOutRow1U32 DN D9.U32
+
+dOutRow0U16 DN D8.U16
+dOutRow1U16 DN D9.U16
+
+
+dOut0U64 DN D0.U64
+dOut1U64 DN D1.U64
+
+dOut00U32 DN D0.U32
+dOut01U32 DN D1.U32
+dOut10U32 DN D2.U32
+dOut11U32 DN D3.U32
+
+dOut0U16 DN D0.U16
+dOut1U16 DN D1.U16
+
+;//-----------------------------------------------------------------------------------------------
+;// armVCM4P10_Interpolate_Chroma_asm starts
+;//-----------------------------------------------------------------------------------------------
+
+ ;// Write function header
+ M_START armVCM4P10_Interpolate_Chroma, r11, d15
+
+ ;// Define stack arguments
+ M_ARG Width, 4
+ M_ARG Height, 4
+ M_ARG Dx, 4
+ M_ARG Dy, 4
+
+ ;// Load argument from the stack
+ ;// M_STALL ARM1136JS=4
+
+ M_LDRD dx, dy, Dx
+ M_LDRD iWidth, iHeight, Width
+
+ ;// EightMinusdx = 8 - dx
+ ;// EightMinusdy = 8 - dy
+
+ ;// ACoeff = EightMinusdx * EightMinusdy
+ ;// BCoeff = dx * EightMinusdy
+ ;// CCoeff = EightMinusdx * dy
+ ;// DCoeff = dx * dy
+
+ RSB EightMinusdx, dx, #8
+ RSB EightMinusdy, dy, #8
+ CMN dx,dy
+ MOV Step1, #1
+ LDREQ pTable, =armVCM4P10_WidthBranchTableMVIsZero
+ SUB SrcStepMinus1, iSrcStep, Step1
+ LDRNE pTable, =armVCM4P10_WidthBranchTableMVIsNotZero
+
+ VLD1 dRow0a, [pSrc], Step1 ;// 0a
+
+ SMULBB ACoeff, EightMinusdx, EightMinusdy
+ SMULBB BCoeff, dx, EightMinusdy
+ VLD1 dRow0b, [pSrc], SrcStepMinus1 ;// 0b
+ SMULBB CCoeff, EightMinusdx, dy
+ SMULBB DCoeff, dx, dy
+
+ VDUP dACoeff, ACoeff
+ VDUP dBCoeff, BCoeff
+ VDUP dCCoeff, CCoeff
+ VDUP dDCoeff, DCoeff
+
+ LDR pc, [pTable, iWidth, LSL #1] ;// Branch to the case based on iWidth
+
+;// Pixel layout:
+;//
+;// x00 x01 x02
+;// x10 x11 x12
+;// x20 x21 x22
+
+;// If fractionl mv is not (0, 0)
+WidthIs8MVIsNotZero
+
+ VLD1 dRow1a, [pSrc], Step1 ;// 1a
+ VMULL qRow0a, dRow0a, dACoeff
+ VLD1 dRow1b, [pSrc], SrcStepMinus1 ;// 1b
+ VMULL qRow0b, dRow1a, dACoeff
+ VLD1 dRow2a, [pSrc], Step1 ;// 2a
+ VMLAL qRow0a, dRow0b, dBCoeff
+ VLD1 dRow2b, [pSrc], SrcStepMinus1 ;// 2b
+ VMULL qRow1a, dRow2a, dACoeff
+ VMLAL qRow0b, dRow1b, dBCoeff
+ VLD1 dRow3a, [pSrc], Step1 ;// 3a
+ VMLAL qRow0a, dRow1a, dCCoeff
+ VMLAL qRow1a, dRow2b, dBCoeff
+ VMULL qRow1b, dRow3a, dACoeff
+ VLD1 dRow3b, [pSrc], SrcStepMinus1 ;// 3b
+ VMLAL qRow0b, dRow2a, dCCoeff
+ VLD1 dRow0a, [pSrc], Step1 ;// 0a
+ VMLAL qRow1b, dRow3b, dBCoeff
+ VMLAL qRow1a, dRow3a, dCCoeff
+ VMLAL qRow0a, dRow1b, dDCoeff
+ VLD1 dRow0b, [pSrc], SrcStepMinus1 ;// 0b
+ VMLAL qRow1b, dRow0a, dCCoeff
+ VMLAL qRow0b, dRow2b, dDCoeff
+ VMLAL qRow1a, dRow3b, dDCoeff
+
+
+ SUBS iHeight, iHeight, #4
+ VMLAL qRow1b, dRow0b, dDCoeff
+
+ VQRSHRN dOutRow0, qOutRow0, #6
+ VQRSHRN dOutRow1, qOutRow1, #6
+ VQRSHRN dOutRow2, qOutRow2, #6
+ VST1 dOutRow0U64, [pDst], iDstStep
+ VQRSHRN dOutRow3, qOutRow3, #6
+
+ VST1 dOutRow1U64, [pDst], iDstStep
+ VST1 dOutRow2U64, [pDst], iDstStep
+ VST1 dOutRow3U64, [pDst], iDstStep
+
+
+ BGT WidthIs8MVIsNotZero
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+WidthIs4MVIsNotZero
+
+ VLD1 dRow1a, [pSrc], Step1
+ VMULL qRow0a, dRow0a, dACoeff
+ VMULL qRow0b, dRow1a, dACoeff
+ VLD1 dRow1b, [pSrc], SrcStepMinus1
+ VMLAL qRow0a, dRow0b, dBCoeff
+ VMLAL qRow0b, dRow1b, dBCoeff
+ VLD1 dRow0a, [pSrc], Step1
+ VMLAL qRow0a, dRow1a, dCCoeff
+ VMLAL qRow0b, dRow0a, dCCoeff
+ VLD1 dRow0b, [pSrc], SrcStepMinus1
+ SUBS iHeight, iHeight, #2
+ VMLAL qRow0b, dRow0b, dDCoeff
+ VMLAL qRow0a, dRow1b, dDCoeff
+
+ VQRSHRN dOutRow1, qOutRow1, #6
+ VQRSHRN dOutRow0, qOutRow0, #6
+
+ VST1 dOutRow0U32[0], [pDst], iDstStep
+ VST1 dOutRow1U32[0], [pDst], iDstStep
+
+ BGT WidthIs4MVIsNotZero
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+WidthIs2MVIsNotZero
+
+ VLD1 dRow1a, [pSrc], Step1
+ VMULL qRow0a, dRow0a, dACoeff
+ VMULL qRow0b, dRow1a, dACoeff
+ VLD1 dRow1b, [pSrc], SrcStepMinus1
+ VMLAL qRow0a, dRow0b, dBCoeff
+ VMLAL qRow0b, dRow1b, dBCoeff
+ VLD1 dRow0a, [pSrc], Step1
+ VMLAL qRow0a, dRow1a, dCCoeff
+ VMLAL qRow0b, dRow0a, dCCoeff
+ VLD1 dRow0b, [pSrc], SrcStepMinus1
+ SUBS iHeight, iHeight, #2
+ VMLAL qRow0b, dRow0b, dDCoeff
+ VMLAL qRow0a, dRow1b, dDCoeff
+
+ VQRSHRN dOutRow1, qOutRow1, #6
+ VQRSHRN dOutRow0, qOutRow0, #6
+
+ VST1 dOutRow0U16[0], [pDst], iDstStep
+ VST1 dOutRow1U16[0], [pDst], iDstStep
+
+ BGT WidthIs2MVIsNotZero
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+;// If fractionl mv is (0, 0)
+WidthIs8MVIsZero
+ SUB pSrc, pSrc, iSrcStep
+
+WidthIs8LoopMVIsZero
+ VLD1 dRow0a, [pSrc], iSrcStep
+ SUBS iHeight, iHeight, #2
+ VLD1 dRow0b, [pSrc], iSrcStep
+ VST1 dOut0U64, [pDst], iDstStep
+ VST1 dOut1U64, [pDst], iDstStep
+ BGT WidthIs8LoopMVIsZero
+
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+WidthIs4MVIsZero
+ VLD1 dRow0b, [pSrc], iSrcStep
+
+ SUBS iHeight, iHeight, #2
+
+ VST1 dOut00U32[0], [pDst], iDstStep
+ VLD1 dRow0a, [pSrc], iSrcStep
+ VST1 dOut01U32[0], [pDst], iDstStep
+
+ BGT WidthIs4MVIsZero
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+WidthIs2MVIsZero
+ VLD1 dRow0b, [pSrc], iSrcStep
+ SUBS iHeight, iHeight, #2
+
+ VST1 dOut0U16[0], [pDst], iDstStep
+ VLD1 dRow0a, [pSrc], iSrcStep
+ VST1 dOut1U16[0], [pDst], iDstStep
+
+ BGT WidthIs2MVIsZero
+ MOV return, #OMX_Sts_NoErr
+ M_END
+
+ ENDIF ;// CortexA8
+
+ END
+
+;//-----------------------------------------------------------------------------------------------
+;// armVCM4P10_Interpolate_Chroma_asm ends
+;//-----------------------------------------------------------------------------------------------
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_QuantTables_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_QuantTables_s.s
new file mode 100755
index 0000000..7e2642b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_QuantTables_s.s
@@ -0,0 +1,74 @@
+;//
+;//
+;// File Name: armVCM4P10_QuantTables_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;// Description:
+;// This file contains quantization tables
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+
+ EXPORT armVCM4P10_MFMatrixQPModTable
+ EXPORT armVCM4P10_QPDivIntraTable
+ EXPORT armVCM4P10_QPDivPlusOneTable
+
+;//--------------------------------------------------------------
+;// This table contains armVCM4P10_MFMatrix [iQP % 6][0] entires,
+;// for values of iQP from 0 to 51 (inclusive).
+;//--------------------------------------------------------------
+
+ M_TABLE armVCM4P10_MFMatrixQPModTable
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+ DCW 13107, 11916, 10082, 9362, 8192, 7282
+
+;//---------------------------------------------------------------
+;// This table contains ARM_M4P10_Q_OFFSET + 1 + (iQP / 6) values,
+;// for values of iQP from 0 to 51 (inclusive).
+;//---------------------------------------------------------------
+
+ M_TABLE armVCM4P10_QPDivPlusOneTable
+ DCB 16, 16, 16, 16, 16, 16
+ DCB 17, 17, 17, 17, 17, 17
+ DCB 18, 18, 18, 18, 18, 18
+ DCB 19, 19, 19, 19, 19, 19
+ DCB 20, 20, 20, 20, 20, 20
+ DCB 21, 21, 21, 21, 21, 21
+ DCB 22, 22, 22, 22, 22, 22
+ DCB 23, 23, 23, 23, 23, 23
+ DCB 24, 24, 24, 24, 24, 24
+
+;//------------------------------------------------------------------
+;// This table contains (1 << QbitsPlusOne) / 3 Values (Intra case) ,
+;// for values of iQP from 0 to 51 (inclusive).
+;//------------------------------------------------------------------
+
+ M_TABLE armVCM4P10_QPDivIntraTable, 2
+ DCD 21845, 21845, 21845, 21845, 21845, 21845
+ DCD 43690, 43690, 43690, 43690, 43690, 43690
+ DCD 87381, 87381, 87381, 87381, 87381, 87381
+ DCD 174762, 174762, 174762, 174762, 174762, 174762
+ DCD 349525, 349525, 349525, 349525, 349525, 349525
+ DCD 699050, 699050, 699050, 699050, 699050, 699050
+ DCD 1398101, 1398101, 1398101, 1398101, 1398101, 1398101
+ DCD 2796202, 2796202, 2796202, 2796202, 2796202, 2796202
+ DCD 5592405, 5592405, 5592405, 5592405, 5592405, 5592405
+
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
new file mode 100755
index 0000000..ee9c339
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_TransformResidual4x4_s.s
@@ -0,0 +1,186 @@
+;//
+;//
+;// File Name: armVCM4P10_TransformResidual4x4_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// Description:
+;// Transform Residual 4x4 Coefficients
+;//
+;//
+
+
+;// Include standard headers
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+;// Import symbols required from other files
+;// (For example tables)
+
+
+
+
+;// Set debugging level
+;//DEBUG_ON SETL {TRUE}
+
+
+
+;// Guarding implementation by the processor name
+
+
+
+
+
+
+
+
+;// Guarding implementation by the processor name
+
+ IF CortexA8
+
+;// ARM Registers
+
+;//Input Registers
+pDst RN 0
+pSrc RN 1
+
+
+;// Neon Registers
+
+;// Packed Input pixels
+dIn0 DN D0.S16
+dIn1 DN D1.S16
+dIn2 DN D2.S16
+dIn3 DN D3.S16
+
+;// Intermediate calculations
+dZero DN D4.S16
+de0 DN D5.S16
+de1 DN D6.S16
+de2 DN D7.S16
+de3 DN D8.S16
+dIn1RS DN D7.S16
+dIn3RS DN D8.S16
+df0 DN D0.S16
+df1 DN D1.S16
+df2 DN D2.S16
+df3 DN D3.S16
+qf01 QN Q0.32
+qf23 QN Q1.32
+dg0 DN D5.S16
+dg1 DN D6.S16
+dg2 DN D7.S16
+dg3 DN D8.S16
+df1RS DN D7.S16
+df3RS DN D8.S16
+
+;// Output pixels
+dh0 DN D0.S16
+dh1 DN D1.S16
+dh2 DN D2.S16
+dh3 DN D3.S16
+
+
+ ;// Allocate stack memory required by the function
+
+
+ ;// Write function header
+ M_START armVCM4P10_TransformResidual4x4, ,d8
+
+ ;******************************************************************
+ ;// The strategy used in implementing the transform is as follows:*
+ ;// Load the 4x4 block into 8 registers *
+ ;// Transpose the 4x4 matrix *
+ ;// Perform the row operations (on columns) using SIMD *
+ ;// Transpose the 4x4 result matrix *
+ ;// Perform the coloumn operations *
+ ;// Store the 4x4 block at one go *
+ ;******************************************************************
+
+ ;// Load all the 4x4 pixels in transposed form
+
+ VLD4 {dIn0,dIn1,dIn2,dIn3},[pSrc]
+
+ VMOV dZero,#0 ;// Used to right shift by 1
+
+
+ ;****************************************
+ ;// Row Operations (Performed on columns)
+ ;****************************************
+
+
+ VADD de0,dIn0,dIn2 ;// e0 = d0 + d2
+ VSUB de1,dIn0,dIn2 ;// e1 = d0 - d2
+ VHADD dIn1RS,dIn1,dZero ;// (f1>>1) constZero is a register holding 0
+ VHADD dIn3RS,dIn3,dZero
+ VSUB de2,dIn1RS,dIn3 ;// e2 = (d1>>1) - d3
+ VADD de3,dIn1,dIn3RS ;// e3 = d1 + (d3>>1)
+ VADD df0,de0,de3 ;// f0 = e0 + e3
+ VADD df1,de1,de2 ;// f1 = e1 + e2
+ VSUB df2,de1,de2 ;// f2 = e1 - e2
+ VSUB df3,de0,de3 ;// f3 = e0 - e3
+
+
+
+ ;*****************************************************************
+ ;// Transpose the resultant matrix
+ ;*****************************************************************
+
+ VTRN df0,df1
+ VTRN df2,df3
+ VTRN qf01,qf23
+
+
+ ;*******************************
+ ;// Coloumn Operations
+ ;*******************************
+
+
+ VADD dg0,df0,df2 ;// e0 = d0 + d2
+ VSUB dg1,df0,df2 ;// e1 = d0 - d2
+ VHADD df1RS,df1,dZero ;// (f1>>1) constZero is a register holding 0
+ VHADD df3RS,df3,dZero
+ VSUB dg2,df1RS,df3 ;// e2 = (d1>>1) - d3
+ VADD dg3,df1,df3RS ;// e3 = d1 + (d3>>1)
+ VADD dh0,dg0,dg3 ;// f0 = e0 + e3
+ VADD dh1,dg1,dg2 ;// f1 = e1 + e2
+ VSUB dh2,dg1,dg2 ;// f2 = e1 - e2
+ VSUB dh3,dg0,dg3 ;// f3 = e0 - e3
+
+
+ ;************************************************
+ ;// Calculate final value (colOp[i][j] + 32)>>6
+ ;************************************************
+
+ VRSHR dh0,#6
+ VRSHR dh1,#6
+ VRSHR dh2,#6
+ VRSHR dh3,#6
+
+
+ ;***************************
+ ;// Store all the 4x4 pixels
+ ;***************************
+
+ VST1 {dh0,dh1,dh2,dh3},[pDst]
+
+
+ ;// Set return value
+
+End
+
+
+ ;// Write function tail
+ M_END
+
+ ENDIF ;//CortexA8
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
new file mode 100755
index 0000000..4c52e22
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/armVCM4P10_UnpackBlock4x4_s.s
@@ -0,0 +1,92 @@
+;//
+;//
+;// File Name: armVCM4P10_UnpackBlock4x4_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+;// Define the processor variants supported by this file
+
+ M_VARIANTS ARM1136JS
+
+
+ IF ARM1136JS
+
+;//--------------------------------------
+;// Input Arguments and their scope/usage
+;//--------------------------------------
+ppSrc RN 0 ;// Persistent variable
+pDst RN 1 ;// Persistent variable
+
+;//--------------------------------
+;// Variables and their scope/usage
+;//--------------------------------
+pSrc RN 2 ;// Persistent variables
+Flag RN 3
+Value RN 4
+Value2 RN 5
+strOffset RN 6
+cstOffset RN 7
+
+
+ M_START armVCM4P10_UnpackBlock4x4, r7
+
+ LDR pSrc, [ppSrc] ;// Load pSrc
+ MOV cstOffset, #31 ;// To be used in the loop, to compute offset
+
+ ;//-----------------------------------------------------------------------
+ ; Firstly, fill all the coefficient values on the <pDst> buffer by zero
+ ;//-----------------------------------------------------------------------
+
+ MOV Value, #0 ;// Initialize the zero value
+ MOV Value2, #0 ;// Initialize the zero value
+ LDRB Flag, [pSrc], #1 ;// Preload <Flag> before <unpackLoop>
+
+ STRD Value, [pDst, #0] ;// pDst[0] = pDst[1] = pDst[2] = pDst[3] = 0
+ STRD Value, [pDst, #8] ;// pDst[4] = pDst[5] = pDst[6] = pDst[7] = 0
+ STRD Value, [pDst, #16] ;// pDst[8] = pDst[9] = pDst[10] = pDst[11] = 0
+ STRD Value, [pDst, #24] ;// pDst[12] = pDst[13] = pDst[14] = pDst[15] = 0
+
+ ;//----------------------------------------------------------------------------
+ ;// The loop below parses and unpacks the input stream. The C-model has
+ ;// a somewhat complicated logic for sign extension. But in the v6 version,
+ ;// that can be easily taken care by loading the data from <pSrc> stream as
+ ;// SIGNED byte/halfword. So, based on the first TST instruction, 8-bits or
+ ;// 16-bits are read.
+ ;//
+ ;// Next, to compute the offset, where the unpacked value needs to be stored,
+ ;// we modify the computation to perform [(Flag & 15) < 1] as [(Flag < 1) & 31]
+ ;// This results in a saving of one cycle.
+ ;//----------------------------------------------------------------------------
+
+unpackLoop
+ TST Flag, #0x10 ;// Computing (Flag & 0x10)
+ LDRSBNE Value2,[pSrc,#1] ;// Load byte wise to avoid unaligned access
+ LDRBNE Value, [pSrc], #2
+ AND strOffset, cstOffset, Flag, LSL #1 ;// strOffset = (Flag & 15) < 1;
+ LDRSBEQ Value, [pSrc], #1 ;// Value = (OMX_U8) *pSrc++
+ ORRNE Value,Value,Value2, LSL #8 ;// Value = (OMX_U16) *pSrc++
+
+ TST Flag, #0x20 ;// Computing (Flag & 0x20) to check, if we're done
+ LDRBEQ Flag, [pSrc], #1 ;// Flag = (OMX_U8) *pSrc++, for next iteration
+ STRH Value, [pDst, strOffset] ;// Store <Value> at offset <strOffset>
+ BEQ unpackLoop ;// Branch to the loop beginning
+
+ STR pSrc, [ppSrc] ;// Update the bitstream pointer
+ M_END
+
+ ENDIF
+
+
+
+ END
+ \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
new file mode 100755
index 0000000..40d4d5e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
@@ -0,0 +1,88 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_DeblockChroma_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 intra chroma deblock
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_DeblockChroma_I
+ *
+ * Description:
+ * Performs deblocking filtering on all edges of the chroma macroblock (16x16).
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcDst pointer to the input macroblock. Must be 8-byte aligned.
+ * [in] srcdstStep Step of the arrays
+ * [in] pAlpha pointer to a 2x2 array of alpha thresholds, organized as follows: { external
+ * vertical edge, internal vertical edge, external
+ * horizontal edge, internal horizontal edge }
+ * [in] pBeta pointer to a 2x2 array of beta thresholds, organized as follows: { external
+ * vertical edge, internal vertical edge, external horizontal edge,
+ * internal horizontal edge }
+ * [in] pThresholds AArray of size 8x2 of Thresholds (TC0) (values for the left or
+ * above edge of each 4x2 or 2x4 block, arranged in vertical block order
+ * and then in horizontal block order)
+ * [in] pBS array of size 16x2 of BS parameters (arranged in scan block order for vertical edges and then horizontal edges);
+ * valid in the range [0,4] with the following restrictions: i) pBS[i]== 4 may occur only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^1]== 4. Must be 4-byte aligned.
+ * [out] pSrcDst pointer to filtered output macroblock
+ *
+ * Return Value:
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - Either of the pointers in pSrcDst, pAlpha, pBeta, pTresholds, or pBS is NULL.
+ * - pSrcDst is not 8-byte aligned.
+ * - either pThresholds or pBS is not 4-byte aligned.
+ * - pBS is out of range, i.e., one of the following conditions is true: pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or (pBS[i]==4 && pBS[i^1]!=4) for 0<=i<=3.
+ * - srcdstStep is not a multiple of 8.
+ *
+ */
+OMXResult omxVCM4P10_DeblockChroma_I(
+ OMX_U8* pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8* pAlpha,
+ const OMX_U8* pBeta,
+ const OMX_U8* pThresholds,
+ const OMX_U8 *pBS
+)
+{
+ OMXResult errorCode;
+
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot8ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(srcdstStep & 7, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pAlpha == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pThresholds == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pThresholds), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBS == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pBS), OMX_Sts_BadArgErr);
+
+ errorCode = omxVCM4P10_FilterDeblockingChroma_VerEdge_I(
+ pSrcDst, srcdstStep, pAlpha, pBeta, pThresholds, pBS);
+
+ armRetArgErrIf(errorCode != OMX_Sts_NoErr, errorCode)
+
+ errorCode = omxVCM4P10_FilterDeblockingChroma_HorEdge_I(
+ pSrcDst, srcdstStep, pAlpha+2, pBeta+2, pThresholds+8, pBS+16);
+
+ return errorCode;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
new file mode 100755
index 0000000..619365f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
@@ -0,0 +1,91 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_DeblockLuma_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 luma deblock
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+
+/**
+ * Function: omxVCM4P10_DeblockLuma_I
+ *
+ * Description:
+ * This function performs deblock filtering the horizontal and vertical edges of a luma macroblock
+ *(16x16).
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcDst pointer to the input macroblock. Must be 8-byte aligned.
+ * [in] srcdstStep image width
+ * [in] pAlpha pointer to a 2x2 table of alpha thresholds, organized as follows: { external
+ * vertical edge, internal vertical edge, external horizontal
+ * edge, internal horizontal edge }
+ * [in] pBeta pointer to a 2x2 table of beta thresholds, organized as follows: { external
+ * vertical edge, internal vertical edge, external horizontal edge,
+ * internal horizontal edge }
+ * [in] pThresholds pointer to a 16x2 table of threshold (TC0), organized as follows: { values for
+ * the left or above edge of each 4x4 block, arranged in vertical block order
+ * and then in horizontal block order)
+ * [in] pBS pointer to a 16x2 table of BS parameters arranged in scan block order for vertical edges and then horizontal edges;
+ * valid in the range [0,4] with the following restrictions: i) pBS[i]== 4 may occur only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^1]== 4. Must be 4-byte aligned.
+ * [out] pSrcDst pointer to filtered output macroblock.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - Either of the pointers in pSrcDst, pAlpha, pBeta, pTresholds or pBS is NULL.
+ * - pSrcDst is not 8-byte aligned.
+ * - srcdstStep is not a multiple of 8
+ * - pBS is out of range, i.e., one of the following conditions is true: pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or (pBS[i]==4 && pBS[i^1]!=4) for 0<=i<=3.
+.
+ *
+ */
+
+OMXResult omxVCM4P10_DeblockLuma_I(
+ OMX_U8* pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8* pAlpha,
+ const OMX_U8* pBeta,
+ const OMX_U8* pThresholds,
+ const OMX_U8 *pBS
+)
+{
+ OMXResult errorCode;
+
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot8ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(srcdstStep & 7, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pAlpha == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pThresholds == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pThresholds), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBS == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pBS), OMX_Sts_BadArgErr);
+
+ errorCode = omxVCM4P10_FilterDeblockingLuma_VerEdge_I(
+ pSrcDst, srcdstStep, pAlpha, pBeta, pThresholds, pBS);
+
+ armRetArgErrIf(errorCode != OMX_Sts_NoErr, errorCode)
+
+ errorCode = omxVCM4P10_FilterDeblockingLuma_HorEdge_I(
+ pSrcDst, srcdstStep, pAlpha+2, pBeta+2, pThresholds+16, pBS+16);
+
+ return errorCode;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
new file mode 100755
index 0000000..4e871bf
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
@@ -0,0 +1,62 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 decode coefficients module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC
+ *
+ * Description:
+ * Performs CAVLC decoding and inverse raster scan for 2x2 block of
+ * ChromaDCLevel. The decoded coefficients in packed position-coefficient
+ * buffer are stored in increasing raster scan order, namely position order.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream Double pointer to current byte in bit stream
+ * buffer
+ * [in] pOffset Pointer to current bit position in the byte
+ * pointed to by *ppBitStream
+ * [out] ppBitStream *ppBitStream is updated after each block is decoded
+ * [out] pOffset *pOffset is updated after each block is decoded
+ * [out] pNumCoeff Pointer to the number of nonzero coefficients
+ * in this block
+ * [out] ppPosCoefbuf Double pointer to destination residual
+ * coefficient-position pair buffer
+ *
+ * Return Value:
+ * Standard omxError result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC (
+ const OMX_U8** ppBitStream,
+ OMX_S32* pOffset,
+ OMX_U8* pNumCoeff,
+ OMX_U8** ppPosCoefbuf
+ )
+
+{
+ return armVCM4P10_DecodeCoeffsToPair(ppBitStream, pOffset, pNumCoeff,
+ ppPosCoefbuf, 17, 4);
+
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
new file mode 100755
index 0000000..b29e576
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
@@ -0,0 +1,68 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_DecodeCoeffsToPairCAVLC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 decode coefficients module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_DecodeCoeffsToPairCAVLC
+ *
+ * Description:
+ * Performs CAVLC decoding and inverse zigzag scan for 4x4 block of
+ * Intra16x16DCLevel, Intra16x16ACLevel,LumaLevel, and ChromaACLevel.
+ * Inverse field scan is not supported. The decoded coefficients in packed
+ * position-coefficient buffer are stored in increasing zigzag order instead
+ * of position order.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream Double pointer to current byte in bit stream buffer
+ * [in] pOffset Pointer to current bit position in the byte pointed
+ * to by *ppBitStream
+ * [in] sMaxNumCoeff Maximum number of non-zero coefficients in current
+ * block
+ * [in] sVLCSelect VLC table selector, obtained from number of non-zero
+ * AC coefficients of above and left 4x4 blocks. It is
+ * equivalent to the variable nC described in H.264 standard
+ * table 9-5, except its value can¡¯t be less than zero.
+ * [out] ppBitStream *ppBitStream is updated after each block is decoded
+ * [out] pOffset *pOffset is updated after each block is decoded
+ * [out] pNumCoeff Pointer to the number of nonzero coefficients in
+ * this block
+ * [out] ppPosCoefbuf Double pointer to destination residual
+ * coefficient-position pair buffer
+ * Return Value:
+ * Standard omxError result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult omxVCM4P10_DecodeCoeffsToPairCAVLC(
+ const OMX_U8** ppBitStream,
+ OMX_S32* pOffset,
+ OMX_U8* pNumCoeff,
+ OMX_U8**ppPosCoefbuf,
+ OMX_INT sVLCSelect,
+ OMX_INT sMaxNumCoeff
+ )
+{
+ return armVCM4P10_DecodeCoeffsToPair(ppBitStream, pOffset, pNumCoeff,
+ ppPosCoefbuf, sVLCSelect, sMaxNumCoeff);
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s
new file mode 100755
index 0000000..485a488
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s
@@ -0,0 +1,396 @@
+;//
+;//
+;// File Name: omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// Description:
+;// H.264 inverse quantize and transform module
+;//
+;//
+
+
+
+;// Include standard headers
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+;// Import symbols required from other files
+;// (For example tables)
+
+ IMPORT armVCM4P10_UnpackBlock4x4
+ IMPORT armVCM4P10_TransformResidual4x4
+ IMPORT armVCM4P10_QPDivTable
+ IMPORT armVCM4P10_VMatrixU16
+ IMPORT armVCM4P10_QPModuloTable
+
+ M_VARIANTS CortexA8
+
+;// Set debugging level
+;//DEBUG_ON SETL {TRUE}
+
+
+;// Static Function: armVCM4P10_DequantLumaAC4x4
+
+;// Guarding implementation by the processor name
+
+
+
+;// Guarding implementation by the processor name
+
+
+
+
+
+
+;// Function: omxVCM4P10_DequantTransformResidualFromPairAndAdd
+
+;// Guarding implementation by the processor name
+
+
+
+;// Function: omxVCM4P10_DequantTransformResidualFromPairAndAdd
+
+;// Guarding implementation by the processor name
+
+ IF CortexA8
+
+
+;// ARM Registers
+
+;//Input Registers
+ppSrc RN 0
+pPred RN 1
+pDC RN 2
+pDst RN 3
+
+
+;//Output Registers
+result RN 0
+
+;//Local Scratch Registers
+
+;//Registers used in armVCM4P10_DequantLumaAC4x4
+pQPdiv RN 10
+pQPmod RN 11
+pVRow RN 2
+QPmod RN 12
+shift RN 14
+index0 RN 1
+index1 RN 10
+
+;//Registers used in DequantTransformResidualFromPairAndAdd
+pDelta RN 4
+pDeltaTmp RN 6
+AC RN 5 ;//Load from stack
+pPredTemp RN 7
+pDCTemp RN 8
+pDstTemp RN 9
+pDeltaArg1 RN 1
+pDeltaArg0 RN 0
+QP RN 1 ;//Load from stack
+DCval RN 10
+predstep RN 1
+dstStep RN 10
+PredVal1 RN 3
+PredVal2 RN 5
+
+
+
+
+;// Neon Registers
+
+;// Registers used in armVCM4P10_DequantLumaAC4x4
+
+dVmatrix DN D6.8
+dindexRow0 DN D7.32
+dindexRow1 DN D9.32
+dByteIndexRow0 DN D7.8
+dByteIndexRow1 DN D9.8
+dVRow0 DN D8.8
+dVRow1 DN D4.8
+dVRow0U16 DN D8.U16
+dVRow1U16 DN D4.U16
+dVRow2U16 DN D8.U16
+dVRow3U16 DN D4.U16
+
+dShift DN D5.U16
+dSrcRow0 DN D0.I16
+dSrcRow1 DN D1.I16
+dSrcRow2 DN D2.I16
+dSrcRow3 DN D3.I16
+dDqntRow0 DN D0.I16
+dDqntRow1 DN D1.I16
+dDqntRow2 DN D2.I16
+dDqntRow3 DN D3.I16
+
+;// Registers used in TransformResidual4x4
+
+;// Packed Input pixels
+dIn0 DN D0.S16
+dIn1 DN D1.S16
+dIn2 DN D2.S16
+dIn3 DN D3.S16
+qIn01 QN Q0.32
+qIn23 QN Q1.32
+
+;// Intermediate calculations
+dZero DN D4.S16
+de0 DN D5.S16
+de1 DN D6.S16
+de2 DN D7.S16
+de3 DN D8.S16
+dIn1RS DN D7.S16
+dIn3RS DN D8.S16
+df0 DN D0.S16
+df1 DN D1.S16
+df2 DN D2.S16
+df3 DN D3.S16
+qf01 QN Q0.32
+qf23 QN Q1.32
+dg0 DN D5.S16
+dg1 DN D6.S16
+dg2 DN D7.S16
+dg3 DN D8.S16
+df1RS DN D7.S16
+df3RS DN D8.S16
+
+;// Output pixels
+dh0 DN D0.S16
+dh1 DN D1.S16
+dh2 DN D2.S16
+dh3 DN D3.S16
+
+;// Registers used in DequantTransformResidualFromPairAndAdd
+
+dDeltaRow0 DN D0.S16
+dDeltaRow1 DN D1.S16
+dDeltaRow2 DN D2.S16
+dDeltaRow3 DN D3.S16
+qDeltaRow01 QN Q0.S16
+qDeltaRow23 QN Q1.S16
+
+dPredValRow01 DN D4.U8
+dPredValRow23 DN D5.U8
+
+qSumRow01 QN Q3.S16
+qSumRow23 QN Q4.S16
+dDstRow01 DN D0.U8
+dDstRow23 DN D1.U8
+dDstRow0 DN D0.32[0]
+dDstRow1 DN D0.32[1]
+dDstRow2 DN D1.32[0]
+dDstRow3 DN D1.32[1]
+
+
+ ;// Allocate stack memory required by the function
+ M_ALLOC8 pBuffer, 32
+
+
+ ;// Write function header
+ M_START omxVCM4P10_DequantTransformResidualFromPairAndAdd,r11,d9
+
+ ;// Define stack arguments
+ M_ARG predStepOnStack, 4
+ M_ARG dstStepOnStack,4
+ M_ARG QPOnStack, 4
+ M_ARG ACOnStack,4
+
+
+ M_ADR pDelta,pBuffer
+ M_LDR AC,ACOnStack
+
+
+ ;// Save registers r1,r2,r3 before function call
+ MOV pPredTemp,pPred
+ MOV pDCTemp,pDC
+ MOV pDstTemp,pDst
+
+ CMP AC,#0
+ BEQ DCcase
+ MOV pDeltaArg1,pDelta ;// Set up r1 for armVCM4P10_UnpackBlock4x4
+
+ BL armVCM4P10_UnpackBlock4x4
+
+ ;//--------------------------------------------------------
+ ;// armVCM4P10_DequantLumaAC4x4 : static function inlined
+ ;//--------------------------------------------------------
+
+ ;//BL armVCM4P10_DequantLumaAC4x4
+ M_LDR QP,QPOnStack ;// Set up r1 for armVCM4P10_DequantLumaAC4x4
+
+ LDR pQPmod,=armVCM4P10_QPModuloTable
+ LDR pQPdiv,=armVCM4P10_QPDivTable
+ LDR pVRow,=armVCM4P10_VMatrixU16
+
+
+ LDRSB QPmod,[pQPmod,QP] ;// (QP%6) * 6
+ LDRSB shift,[pQPdiv,QP] ;// Shift = QP / 6
+
+ LDR index1,=0x03020504
+ LDR index0,=0x05040100 ;// Indexes into dVmatrix
+ ADD pVRow,pVRow,QPmod
+ VDUP dindexRow0,index0
+ VDUP dindexRow1,index1
+ VDUP dShift,shift
+
+ ;// Load all 4x4 pVRow[] values
+ VLD1 dVmatrix,[pVRow] ;// dVmatrix = [0d|0c|0b|0a]
+
+
+ VTBL dVRow0,dVmatrix,dByteIndexRow0 ;// row0 = row2 = [pVRow[2] | pVRow[0] | pVRow[2] | pVRow[0]]
+ VTBL dVRow1,dVmatrix,dByteIndexRow1 ;// row1 = row3 = [pVRow[1] | pVRow[2] | pVRow[1] | pVRow[2]]
+ CMP pDCTemp,#0
+ ;// Load all the 4x4 'src' values
+ VLD1 { dSrcRow0,dSrcRow1,dSrcRow2,dSrcRow3 },[pDelta]
+
+ VSHL dVRow0U16,dVRow0U16,dShift
+ VSHL dVRow1U16,dVRow1U16,dShift
+ LDRSHNE DCval,[pDCTemp]
+
+
+ ;// Multiply src[] with pVRow[]
+ VMUL dDqntRow0,dSrcRow0,dVRow0U16
+ VMUL dDqntRow1,dSrcRow1,dVRow1U16
+ VMUL dDqntRow2,dSrcRow2,dVRow2U16
+ VMUL dDqntRow3,dSrcRow3,dVRow3U16
+
+
+
+ ;//-------------------------------------------------------------
+ ;// TransformResidual4x4 : Inlined to avoid Load/Stores
+ ;//-------------------------------------------------------------
+
+
+ ;//BL armVCM4P10_TransformResidual4x4
+ ;//STRHNE DCval,[pDelta]
+ VMOVNE dIn0[0],DCval
+
+
+
+ ;//*****************************************************************
+ ;// Transpose the input pixels : perform Row ops as Col ops
+ ;//*****************************************************************
+
+ VTRN dIn0,dIn1
+ VTRN dIn2,dIn3
+ VTRN qIn01,qIn23
+
+
+ VMOV dZero,#0 ;// Used to right shift by 1
+
+
+ ;//****************************************
+ ;// Row Operations (Performed on columns)
+ ;//****************************************
+
+
+ VADD de0,dIn0,dIn2 ;// e0 = d0 + d2
+ VSUB de1,dIn0,dIn2 ;// e1 = d0 - d2
+ VHADD dIn1RS,dIn1,dZero ;// (f1>>1) constZero is a register holding 0
+ VHADD dIn3RS,dIn3,dZero
+ VSUB de2,dIn1RS,dIn3 ;// e2 = (d1>>1) - d3
+ VADD de3,dIn1,dIn3RS ;// e3 = d1 + (d3>>1)
+ VADD df0,de0,de3 ;// f0 = e0 + e3
+ VADD df1,de1,de2 ;// f1 = e1 + e2
+ VSUB df2,de1,de2 ;// f2 = e1 - e2
+ VSUB df3,de0,de3 ;// f3 = e0 - e3
+
+
+
+ ;//*****************************************************************
+ ;// Transpose the resultant matrix
+ ;//*****************************************************************
+
+ VTRN df0,df1
+ VTRN df2,df3
+ VTRN qf01,qf23
+
+
+ ;//*******************************
+ ;// Coloumn Operations
+ ;//*******************************
+
+
+ VADD dg0,df0,df2 ;// e0 = d0 + d2
+ VSUB dg1,df0,df2 ;// e1 = d0 - d2
+ VHADD df1RS,df1,dZero ;// (f1>>1) constZero is a register holding 0
+ VHADD df3RS,df3,dZero
+ VSUB dg2,df1RS,df3 ;// e2 = (d1>>1) - d3
+ VADD dg3,df1,df3RS ;// e3 = d1 + (d3>>1)
+ VADD dh0,dg0,dg3 ;// f0 = e0 + e3
+ VADD dh1,dg1,dg2 ;// f1 = e1 + e2
+ VSUB dh2,dg1,dg2 ;// f2 = e1 - e2
+ VSUB dh3,dg0,dg3 ;// f3 = e0 - e3
+
+
+ ;//************************************************
+ ;// Calculate final value (colOp[i][j] + 32)>>6
+ ;//************************************************
+
+ VRSHR dh0,#6
+ VRSHR dh1,#6
+ VRSHR dh2,#6
+ VRSHR dh3,#6
+
+
+ B OutDCcase
+
+
+DCcase
+ ;// Calculate the Transformed DCvalue : (DCval+32)>>6
+ LDRSH DCval,[pDCTemp]
+ ADD DCval,DCval,#32
+ ASR DCval,DCval,#6
+
+ VDUP dDeltaRow0, DCval ;// pDelta[0] = pDelta[1] = pDelta[2] = pDelta[3] = DCval
+ VDUP dDeltaRow1, DCval ;// pDelta[4] = pDelta[5] = pDelta[6] = pDelta[7] = DCval
+ VDUP dDeltaRow2, DCval ;// pDelta[8] = pDelta[9] = pDelta[10] = pDelta[11] = DCval
+ VDUP dDeltaRow3, DCval
+
+
+OutDCcase
+ M_LDR predstep,predStepOnStack
+ M_LDR dstStep,dstStepOnStack
+
+ LDR PredVal1,[pPredTemp],predstep
+ LDR PredVal2,[pPredTemp],predstep
+ VMOV dPredValRow01,PredVal1,PredVal2
+
+ LDR PredVal1,[pPredTemp],predstep
+ LDR PredVal2,[pPredTemp]
+ VMOV dPredValRow23,PredVal1,PredVal2
+
+
+ VADDW qSumRow01,qDeltaRow01,dPredValRow01
+ VADDW qSumRow23,qDeltaRow23,dPredValRow23
+ VQMOVUN dDstRow01,qSumRow01
+ VQMOVUN dDstRow23,qSumRow23
+
+
+ VST1 dDstRow0,[pDstTemp],dstStep
+ VST1 dDstRow1,[pDstTemp],dstStep
+ VST1 dDstRow2,[pDstTemp],dstStep
+ VST1 dDstRow3,[pDstTemp]
+
+ ;// Set return value
+ MOV result,#OMX_Sts_NoErr
+
+End
+
+
+ ;// Write function tail
+
+ M_END
+
+ ENDIF ;//CORTEXA8
+
+
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
new file mode 100644
index 0000000..4606197
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
@@ -0,0 +1,202 @@
+;//
+;//
+;// File Name: omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+ IF CortexA8
+
+ IMPORT armVCM4P10_DeblockingChromabSGE4_unsafe
+ IMPORT armVCM4P10_DeblockingChromabSLT4_unsafe
+
+LOOP_COUNT EQU 0x40000000
+MASK_3 EQU 0x03030303
+MASK_4 EQU 0x04040404
+
+;// Function arguments
+
+pSrcDst RN 0
+srcdstStep RN 1
+pAlpha RN 2
+pBeta RN 3
+
+pThresholds RN 5
+pBS RN 4
+bS3210 RN 6
+
+;// Loop
+
+XY RN 7
+
+;// Pixels
+dP_0 DN D4.U8
+dP_1 DN D5.U8
+dP_2 DN D6.U8
+dQ_0 DN D8.U8
+dQ_1 DN D9.U8
+dQ_2 DN D10.U8
+
+;// Filtering Decision
+dAlpha DN D0.U8
+dBeta DN D2.U8
+
+dFilt DN D16.U8
+dAqflg DN D12.U8
+dApflg DN D17.U8
+
+dAp0q0 DN D13.U8
+dAp1p0 DN D12.U8
+dAq1q0 DN D18.U8
+dAp2p0 DN D19.U8
+dAq2q0 DN D17.U8
+
+qBS3210 QN Q13.U16
+dBS3210 DN D26
+dMask_bs DN D27
+dFilt_bs DN D26.U16
+
+;// bSLT4
+dMask_0 DN D14.U8
+dMask_1 DN D15.U8
+dMask_4 DN D1.U16
+
+Mask_4 RN 8
+Mask_3 RN 9
+
+dTemp DN D19.U8
+
+;// Result
+dP_0t DN D13.U8
+dQ_0t DN D31.U8
+
+dP_0n DN D29.U8
+dQ_0n DN D24.U8
+
+
+ ;// Function header
+ M_START omxVCM4P10_FilterDeblockingChroma_HorEdge_I, r9, d15
+
+ ;//Arguments on the stack
+ M_ARG ppThresholds, 4
+ M_ARG ppBS, 4
+
+ ;// d0-dAlpha_0
+ ;// d2-dBeta_0
+
+ ;load alpha1,beta1 somewhere to avoid more loads
+ VLD1 {dAlpha[]}, [pAlpha]!
+ SUB pSrcDst, pSrcDst, srcdstStep, LSL #1 ;?
+ SUB pSrcDst, pSrcDst, srcdstStep
+ VLD1 {dBeta[]}, [pBeta]!
+
+ M_LDR pBS, ppBS
+ M_LDR pThresholds, ppThresholds
+
+ LDR Mask_3, =MASK_3
+ LDR Mask_4, =MASK_4
+
+ VMOV dMask_0, #0
+ VMOV dMask_1, #1
+ VMOV dMask_4, #4
+
+ LDR XY, =LOOP_COUNT
+
+ ;// p0-p3 - d4-d7
+ ;// q0-q3 - d8-d11
+LoopY
+ LDR bS3210, [pBS], #8
+
+ VLD1 dP_2, [pSrcDst], srcdstStep
+ ;1
+ VLD1 dP_1, [pSrcDst], srcdstStep
+ CMP bS3210, #0
+ VLD1 dP_0, [pSrcDst], srcdstStep
+ ;1
+ VLD1 dQ_0, [pSrcDst], srcdstStep
+ VABD dAp2p0, dP_2, dP_0
+ VLD1 dQ_1, [pSrcDst], srcdstStep
+ VABD dAp0q0, dP_0, dQ_0
+ VLD1 dQ_2, [pSrcDst], srcdstStep
+ BEQ NoFilterBS0
+
+ VABD dAp1p0, dP_1, dP_0
+ VABD dAq1q0, dQ_1, dQ_0
+
+ VCGT dFilt, dAlpha, dAp0q0
+ VMOV.U32 dBS3210[0], bS3210
+ VMAX dAp1p0, dAq1q0, dAp1p0
+ VMOVL qBS3210, dBS3210.U8
+ VABD dAq2q0, dQ_2, dQ_0
+ VCGT dMask_bs.S16, dBS3210.S16, #0
+
+ VCGT dAp1p0, dBeta, dAp1p0
+ VCGT dAp2p0, dBeta, dAp2p0
+
+ VAND dFilt, dMask_bs.U8
+
+ TST bS3210, Mask_3
+
+ VCGT dAq2q0, dBeta, dAq2q0
+ VAND dFilt, dFilt, dAp1p0
+
+ VAND dAqflg, dFilt, dAq2q0
+ VAND dApflg, dFilt, dAp2p0
+
+ ;// bS < 4 Filtering
+ BLNE armVCM4P10_DeblockingChromabSLT4_unsafe
+
+ TST bS3210, Mask_4
+
+ SUB pSrcDst, pSrcDst, srcdstStep, LSL #2
+ VTST dFilt_bs, dFilt_bs, dMask_4
+
+ ;// bS == 4 Filtering
+ BLNE armVCM4P10_DeblockingChromabSGE4_unsafe
+
+ VBIT dP_0n, dP_0t, dFilt_bs
+ VBIT dQ_0n, dQ_0t, dFilt_bs
+
+ VBIF dP_0n, dP_0, dFilt
+ VBIF dQ_0n, dQ_0, dFilt
+
+ ;// Result Storage
+ VST1 dP_0n, [pSrcDst], srcdstStep
+ ADDS XY, XY, XY
+ VST1 dQ_0n, [pSrcDst], srcdstStep
+
+ BNE LoopY
+
+ MOV r0, #OMX_Sts_NoErr
+
+ M_EXIT
+
+NoFilterBS0
+
+ VLD1 {dAlpha[]}, [pAlpha]
+ SUB pSrcDst, pSrcDst, srcdstStep, LSL #1
+ ADDS XY, XY, XY
+ VLD1 {dBeta[]}, [pBeta]
+ ADD pThresholds, pThresholds, #4
+ BNE LoopY
+
+ MOV r0, #OMX_Sts_NoErr
+ M_END
+
+ ENDIF
+
+
+ END
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
new file mode 100644
index 0000000..18e6c1d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
@@ -0,0 +1,282 @@
+;//
+;//
+;// File Name: omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+ IF CortexA8
+
+ IMPORT armVCM4P10_DeblockingChromabSGE4_unsafe
+ IMPORT armVCM4P10_DeblockingChromabSLT4_unsafe
+
+LOOP_COUNT EQU 0x40000000
+MASK_3 EQU 0x03030303
+MASK_4 EQU 0x04040404
+
+;// Function arguments
+
+pSrcDst RN 0
+srcdstStep RN 1
+pAlpha RN 2
+pBeta RN 3
+
+pThresholds RN 5
+pBS RN 4
+bS3210 RN 6
+pSrcDst_P RN 10
+pSrcDst_Q RN 12
+
+pTmp RN 10
+pTmp2 RN 12
+step RN 14
+
+;// Loop
+
+XY RN 7
+
+;// Rows input
+dRow0 DN D7.U8
+dRow1 DN D8.U8
+dRow2 DN D5.U8
+dRow3 DN D10.U8
+dRow4 DN D6.U8
+dRow5 DN D9.U8
+dRow6 DN D4.U8
+dRow7 DN D11.U8
+
+
+;// Pixels
+dP_0 DN D4.U8
+dP_1 DN D5.U8
+dP_2 DN D6.U8
+dQ_0 DN D8.U8
+dQ_1 DN D9.U8
+dQ_2 DN D10.U8
+
+;// Filtering Decision
+dAlpha DN D0.U8
+dBeta DN D2.U8
+
+dFilt DN D16.U8
+dAqflg DN D12.U8
+dApflg DN D17.U8
+
+dAp0q0 DN D13.U8
+dAp1p0 DN D12.U8
+dAq1q0 DN D18.U8
+dAp2p0 DN D19.U8
+dAq2q0 DN D17.U8
+
+qBS3210 QN Q13.U16
+dBS3210 DN D26
+dMask_bs DN D27
+dFilt_bs DN D26.U16
+
+;// bSLT4
+dMask_0 DN D14.U8
+dMask_1 DN D15.U8
+dMask_4 DN D1.U16
+
+Mask_4 RN 8
+Mask_3 RN 9
+
+dTemp DN D19.U8
+
+;// Result
+dP_0t DN D13.U8
+dQ_0t DN D31.U8
+
+dP_0n DN D29.U8
+dQ_0n DN D24.U8
+
+
+ ;// Function header
+ M_START omxVCM4P10_FilterDeblockingChroma_VerEdge_I, r12, d15
+
+ ;//Arguments on the stack
+ M_ARG ppThresholds, 4
+ M_ARG ppBS, 4
+
+ ;// d0-dAlpha_0
+ ;// d2-dBeta_0
+
+ ;load alpha1,beta1 somewhere to avoid more loads
+ VLD1 {dAlpha[]}, [pAlpha]!
+ SUB pSrcDst, pSrcDst, #4
+ VLD1 {dBeta[]}, [pBeta]!
+
+ M_LDR pBS, ppBS
+ M_LDR pThresholds, ppThresholds
+
+ LDR Mask_4, =MASK_4
+ LDR Mask_3, =MASK_3
+
+ ;dMask_0-14
+ ;dMask_1-15
+ ;dMask_4-19
+
+ VMOV dMask_0, #0
+ VMOV dMask_1, #1
+ VMOV dMask_4, #4
+
+ LDR XY, =LOOP_COUNT
+
+ ;// p0-p3 - d4-d7
+ ;// q0-q3 - d8-d11
+
+
+LoopY
+ LDR bS3210, [pBS], #8
+ ADD pTmp, pSrcDst, srcdstStep
+ ADD step, srcdstStep, srcdstStep
+
+ ;1
+ VLD1 dRow0, [pSrcDst], step
+ ;1
+ VLD1 dRow1, [pTmp], step
+ VLD1 dRow2, [pSrcDst], step
+ VLD1 dRow3, [pTmp], step
+ VLD1 dRow4, [pSrcDst], step
+ VLD1 dRow5, [pTmp], step
+ VLD1 dRow6, [pSrcDst], step
+ VLD1 dRow7, [pTmp], step
+
+
+ ;// dRow0 = [q3r0 q2r0 q1r0 q0r0 p0r0 p1r0 p2r0 p3r0]
+ ;// dRow1 = [q3r1 q2r1 q1r1 q0r1 p0r1 p1r1 p2r1 p3r1]
+ ;// dRow2 = [q3r2 q2r2 q1r2 q0r2 p0r2 p1r2 p2r2 p3r2]
+ ;// dRow3 = [q3r3 q2r3 q1r3 q0r3 p0r3 p1r3 p2r3 p3r3]
+ ;// dRow4 = [q3r4 q2r4 q1r4 q0r4 p0r4 p1r4 p2r4 p3r4]
+ ;// dRow5 = [q3r5 q2r5 q1r5 q0r5 p0r5 p1r5 p2r5 p3r5]
+ ;// dRow6 = [q3r6 q2r6 q1r6 q0r6 p0r6 p1r6 p2r6 p3r6]
+ ;// dRow7 = [q3r7 q2r7 q1r7 q0r7 p0r7 p1r7 p2r7 p3r7]
+
+ ;// 8x8 Transpose
+ VZIP.8 dRow0, dRow1
+ VZIP.8 dRow2, dRow3
+ VZIP.8 dRow4, dRow5
+ VZIP.8 dRow6, dRow7
+
+ VZIP.16 dRow0, dRow2
+ VZIP.16 dRow1, dRow3
+ VZIP.16 dRow4, dRow6
+ VZIP.16 dRow5, dRow7
+
+ VZIP.32 dRow0, dRow4
+ VZIP.32 dRow2, dRow6
+ VZIP.32 dRow3, dRow7
+ VZIP.32 dRow1, dRow5
+
+
+ ;Realign the pointers
+
+ CMP bS3210, #0
+ VABD dAp2p0, dP_2, dP_0
+ VABD dAp0q0, dP_0, dQ_0
+ BEQ NoFilterBS0
+
+ VABD dAp1p0, dP_1, dP_0
+ VABD dAq1q0, dQ_1, dQ_0
+
+ VMOV.U32 dBS3210[0], bS3210
+ VCGT dFilt, dAlpha, dAp0q0
+ VMAX dAp1p0, dAq1q0, dAp1p0
+ VMOVL qBS3210, dBS3210.U8
+ VABD dAq2q0, dQ_2, dQ_0
+ VCGT dMask_bs.S16, dBS3210.S16, #0
+
+ VCGT dAp1p0, dBeta, dAp1p0
+ VCGT dAp2p0, dBeta, dAp2p0
+ VAND dFilt, dMask_bs.U8
+
+ TST bS3210, Mask_3
+
+ VCGT dAq2q0, dBeta, dAq2q0
+ VAND dFilt, dFilt, dAp1p0
+
+ VAND dAqflg, dFilt, dAq2q0
+ VAND dApflg, dFilt, dAp2p0
+
+ ;// bS < 4 Filtering
+ BLNE armVCM4P10_DeblockingChromabSLT4_unsafe
+
+ TST bS3210, Mask_4
+
+ SUB pSrcDst, pSrcDst, srcdstStep, LSL #3
+ VTST dFilt_bs, dFilt_bs, dMask_4
+
+ ;// bS == 4 Filtering
+ BLNE armVCM4P10_DeblockingChromabSGE4_unsafe
+
+ VBIT dP_0n, dP_0t, dFilt_bs
+ VBIT dQ_0n, dQ_0t, dFilt_bs
+
+ ;// Result Storage
+ ADD pSrcDst_P, pSrcDst, #3
+ VBIF dP_0n, dP_0, dFilt
+
+ ADD pTmp2, pSrcDst_P, srcdstStep
+ ADD step, srcdstStep, srcdstStep
+ VBIF dQ_0n, dQ_0, dFilt
+
+ ADDS XY, XY, XY
+
+ VST1 {dP_0n[0]}, [pSrcDst_P], step
+ VST1 {dP_0n[1]}, [pTmp2], step
+ VST1 {dP_0n[2]}, [pSrcDst_P], step
+ VST1 {dP_0n[3]}, [pTmp2], step
+ VST1 {dP_0n[4]}, [pSrcDst_P], step
+ VST1 {dP_0n[5]}, [pTmp2], step
+ VST1 {dP_0n[6]}, [pSrcDst_P], step
+ VST1 {dP_0n[7]}, [pTmp2], step
+
+ ADD pSrcDst_Q, pSrcDst, #4
+ ADD pTmp, pSrcDst_Q, srcdstStep
+
+ VST1 {dQ_0n[0]}, [pSrcDst_Q], step
+ VST1 {dQ_0n[1]}, [pTmp], step
+ VST1 {dQ_0n[2]}, [pSrcDst_Q], step
+ VST1 {dQ_0n[3]}, [pTmp], step
+ VST1 {dQ_0n[4]}, [pSrcDst_Q], step
+ VST1 {dQ_0n[5]}, [pTmp], step
+ VST1 {dQ_0n[6]}, [pSrcDst_Q], step
+ VST1 {dQ_0n[7]}, [pTmp], step
+
+ ADD pSrcDst, pSrcDst, #4
+
+ BNE LoopY
+
+ MOV r0, #OMX_Sts_NoErr
+
+ M_EXIT
+
+NoFilterBS0
+ VLD1 {dAlpha[]}, [pAlpha]
+ ADD pSrcDst, pSrcDst, #4
+ SUB pSrcDst, pSrcDst, srcdstStep, LSL #3
+ ADDS XY, XY, XY
+ VLD1 {dBeta[]}, [pBeta]
+ ADD pThresholds, pThresholds, #4
+ BNE LoopY
+
+ MOV r0, #OMX_Sts_NoErr
+
+ M_END
+
+ ENDIF
+
+
+ END
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
new file mode 100755
index 0000000..0c3f4f2
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
@@ -0,0 +1,288 @@
+;//
+;//
+;// File Name: omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+ IMPORT armVCM4P10_DeblockingLumabSLT4_unsafe
+ IMPORT armVCM4P10_DeblockingLumabSGE4_unsafe
+
+ IF CortexA8
+
+LOOP_COUNT EQU 0x55000000
+
+
+;// Function arguments
+
+pSrcDst RN 0
+srcdstStep RN 1
+pAlpha RN 2
+pBeta RN 3
+
+pThresholds RN 5
+pBS RN 4
+bS10 RN 12
+
+pAlpha_0 RN 2
+pBeta_0 RN 3
+
+pAlpha_1 RN 7
+pBeta_1 RN 8
+
+
+
+;// Loop
+
+XY RN 9
+
+pTmp RN 6
+step RN 10
+
+;// Pixels
+dP_0 DN D4.U8
+dP_1 DN D5.U8
+dP_2 DN D6.U8
+dP_3 DN D7.U8
+dQ_0 DN D8.U8
+dQ_1 DN D9.U8
+dQ_2 DN D10.U8
+dQ_3 DN D11.U8
+
+
+;// Filtering Decision
+dAlpha DN D0.U8
+dBeta DN D2.U8
+
+dFilt DN D16.U8
+dAqflg DN D12.U8
+dApflg DN D17.U8
+
+dAp0q0 DN D13.U8
+dAp1p0 DN D12.U8
+dAq1q0 DN D18.U8
+dAp2p0 DN D19.U8
+dAq2q0 DN D17.U8
+
+;// bSLT4
+dTC0 DN D18.U8
+dTC1 DN D19.U8
+dTC01 DN D18.U8
+
+dTCs DN D31.S8
+dTC DN D31.U8
+
+dMask_0 DN D14.U8
+dMask_1 DN D15.U8
+
+Mask_0 RN 11
+
+dTemp DN D19.U8
+
+;// Computing P0,Q0
+qDq0p0 QN Q10.S16
+qDp1q1 QN Q11.S16
+qDelta QN Q10.S16 ; reuse qDq0p0
+dDelta DN D20.S8
+
+
+;// Computing P1,Q1
+dRp0q0 DN D24.U8
+
+dMaxP DN D23.U8
+dMinP DN D22.U8
+
+dMaxQ DN D19.U8
+dMinQ DN D21.U8
+
+dDeltaP DN D26.U8
+dDeltaQ DN D27.U8
+
+qP_0n QN Q14.S16
+qQ_0n QN Q12.S16
+
+dQ_0n DN D24.U8
+dQ_1n DN D25.U8
+dP_0n DN D29.U8
+dP_1n DN D30.U8
+
+;// bSGE4
+
+qSp0q0 QN Q10.U16
+
+qSp2q1 QN Q11.U16
+qSp0q0p1 QN Q12.U16
+qSp3p2 QN Q13.U16
+dHSp0q1 DN D28.U8
+
+qSq2p1 QN Q11.U16
+qSp0q0q1 QN Q12.U16
+qSq3q2 QN Q13.U16 ;!!
+dHSq0p1 DN D28.U8 ;!!
+
+qTemp1 QN Q11.U16 ;!!;qSp2q1
+qTemp2 QN Q12.U16 ;!!;qSp0q0p1
+
+dP_0t DN D28.U8 ;!!;dHSp0q1
+dQ_0t DN D22.U8 ;!!;Temp1
+
+dP_0n DN D29.U8
+dP_1n DN D30.U8
+dP_2n DN D31.U8
+
+dQ_0n DN D24.U8 ;!!;Temp2
+dQ_1n DN D25.U8 ;!!;Temp2
+dQ_2n DN D28.U8 ;!!;dQ_0t
+
+
+ ;// Function header
+ M_START omxVCM4P10_FilterDeblockingLuma_HorEdge_I, r11, d15
+
+ ;//Arguments on the stack
+ M_ARG ppThresholds, 4
+ M_ARG ppBS, 4
+
+ ;// d0-dAlpha_0
+ ;// d2-dBeta_0
+
+ ADD pAlpha_1, pAlpha_0, #1
+ ADD pBeta_1, pBeta_0, #1
+
+ VLD1 {dAlpha[]}, [pAlpha_0]
+ SUB pSrcDst, pSrcDst, srcdstStep, LSL #2
+ VLD1 {dBeta[]}, [pBeta_0]
+
+ M_LDR pBS, ppBS
+ M_LDR pThresholds, ppThresholds
+
+ MOV Mask_0,#0
+
+ ;dMask_0-14
+ ;dMask_1-15
+
+ VMOV dMask_0, #0
+ VMOV dMask_1, #1
+
+ ADD step, srcdstStep, srcdstStep
+
+ LDR XY,=LOOP_COUNT
+
+ ;// p0-p3 - d4-d7
+ ;// q0-q3 - d8-d11
+LoopY
+LoopX
+ LDRH bS10, [pBS], #2
+ ADD pTmp, pSrcDst, srcdstStep
+ CMP bS10, #0
+ BEQ NoFilterBS0
+
+ VLD1 dP_3, [pSrcDst], step
+ VLD1 dP_2, [pTmp], step
+ VLD1 dP_1, [pSrcDst], step
+ VLD1 dP_0, [pTmp], step
+ VLD1 dQ_0, [pSrcDst], step
+ VABD dAp1p0, dP_0, dP_1
+ VLD1 dQ_1, [pTmp]
+ VABD dAp0q0, dQ_0, dP_0
+ VLD1 dQ_2, [pSrcDst], srcdstStep
+
+ VABD dAq1q0, dQ_1, dQ_0
+ VABD dAp2p0, dP_2, dP_0
+ VCGT dFilt, dAlpha, dAp0q0
+
+ TST bS10, #0xff
+ VMAX dAp1p0, dAq1q0, dAp1p0
+ VABD dAq2q0, dQ_2, dQ_0
+
+ VMOVEQ.U32 dFilt[0], Mask_0
+ TST bS10, #0xff00
+
+ VCGT dAp2p0, dBeta, dAp2p0
+ VCGT dAp1p0, dBeta, dAp1p0
+
+ VMOVEQ.U32 dFilt[1], Mask_0
+
+ VCGT dAq2q0, dBeta, dAq2q0
+ VLD1 dQ_3, [pSrcDst]
+ VAND dFilt, dFilt, dAp1p0
+ TST bS10, #4
+
+ VAND dAqflg, dFilt, dAq2q0
+ VAND dApflg, dFilt, dAp2p0
+
+ BNE bSGE4
+bSLT4
+ ;// bS < 4 Filtering
+ SUB pSrcDst, pSrcDst, srcdstStep, LSL #2
+ SUB pSrcDst, pSrcDst, srcdstStep
+
+ BL armVCM4P10_DeblockingLumabSLT4_unsafe
+
+ ;// Result Storage
+ VST1 dP_1n, [pSrcDst], srcdstStep
+ VST1 dP_0n, [pSrcDst], srcdstStep
+ SUB pTmp, pSrcDst, srcdstStep, LSL #2
+ VST1 dQ_0n, [pSrcDst], srcdstStep
+ ADDS XY, XY, XY
+ VST1 dQ_1n, [pSrcDst]
+ ADD pSrcDst, pTmp, #8
+
+ BCC LoopX
+ B ExitLoopY
+
+NoFilterBS0
+ ADD pSrcDst, pSrcDst, #8
+ ADDS XY, XY, XY
+ ADD pThresholds, pThresholds, #2
+ BCC LoopX
+ B ExitLoopY
+bSGE4
+ ;// bS >= 4 Filtering
+ SUB pSrcDst, pSrcDst, srcdstStep, LSL #2
+ SUB pSrcDst, pSrcDst, srcdstStep, LSL #1
+ BL armVCM4P10_DeblockingLumabSGE4_unsafe
+
+ ;// Result Storage
+ VST1 dP_2n, [pSrcDst], srcdstStep
+ VST1 dP_1n, [pSrcDst], srcdstStep
+ VST1 dP_0n, [pSrcDst], srcdstStep
+ SUB pTmp, pSrcDst, srcdstStep, LSL #2
+ VST1 dQ_0n, [pSrcDst], srcdstStep
+ ADDS XY,XY,XY
+ VST1 dQ_1n, [pSrcDst], srcdstStep
+ ADD pThresholds, pThresholds, #2
+ VST1 dQ_2n, [pSrcDst]
+
+ ADD pSrcDst, pTmp, #8
+ BCC LoopX
+
+ExitLoopY
+
+ SUB pSrcDst, pSrcDst, #16
+ VLD1 {dAlpha[]}, [pAlpha_1]
+ ADD pSrcDst, pSrcDst, srcdstStep, LSL #2
+ VLD1 {dBeta[]}, [pBeta_1]
+ BNE LoopY
+
+ MOV r0, #OMX_Sts_NoErr
+
+ M_END
+
+ ENDIF
+
+
+
+
+ END
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
new file mode 100755
index 0000000..e6fbb34
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
@@ -0,0 +1,436 @@
+;//
+;//
+;// File Name: omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+ IMPORT armVCM4P10_DeblockingLumabSLT4_unsafe
+ IMPORT armVCM4P10_DeblockingLumabSGE4_unsafe
+
+ IF CortexA8
+
+LOOP_COUNT EQU 0x11000000
+
+
+;// Function arguments
+
+pSrcDst RN 0
+srcdstStep RN 1
+pAlpha RN 2
+pBeta RN 3
+
+pThresholds RN 5
+pBS RN 4
+bS10 RN 12
+
+pAlpha_0 RN 2
+pBeta_0 RN 3
+
+pAlpha_1 RN 7
+pBeta_1 RN 8
+
+pTmp RN 10
+pTmpStep RN 11
+
+;// Loop
+
+XY RN 9
+
+;// Rows input
+dRow0 DN D7.U8
+dRow1 DN D8.U8
+dRow2 DN D5.U8
+dRow3 DN D10.U8
+dRow4 DN D6.U8
+dRow5 DN D9.U8
+dRow6 DN D4.U8
+dRow7 DN D11.U8
+
+;// dRow0 - dP_3, dRow1 - dQ_0, dRow2 - dP_1, dRow3 - dQ_2
+;// dRow4 - dP_2, dRow5 - dQ_1, dRow6 - dP_0, dRow7 - dQ_3
+
+;// Rows output
+dRown0 DN D7.U8
+dRown1 DN D24.U8
+dRown2 DN D30.U8
+dRown3 DN D10.U8
+dRown4 DN D6.U8
+dRown5 DN D25.U8
+dRown6 DN D29.U8
+dRown7 DN D11.U8
+
+;// dP_0n DN D29.U8
+;// dP_1n DN D30.U8
+;// dP_2n DN D31.U8
+;//
+;// dQ_0n DN D24.U8 ;!!;Temp2
+;// dQ_1n DN D25.U8 ;!!;Temp2
+;// dQ_2n DN D28.U8 ;!!;dQ_0t
+;//
+;// dRown0 - dP_3, dRown1 - dQ_0n
+;// dRown2 - dP_1n, dRown3 - dQ_2
+;// dRown4 - dP_2, dRown5 - dQ_1n
+;// dRown6 - dP_0n, dRown7 - dQ_3
+
+dRow0n DN D7.U8
+dRow1n DN D24.U8
+dRow2n DN D30.U8
+dRow3n DN D28.U8
+dRow4n DN D31.U8
+dRow5n DN D25.U8
+dRow6n DN D29.U8
+dRow7n DN D11.U8
+
+;// dRow0n - dP_3, dRow1n - dQ_0n, dRow2n - dP_1n, dRow3n - dQ_2n
+;// dRow4n - dP_2, dRow5n - dQ_1n, dRow6n - dP_0n, dRow7n - dQ_3
+
+;// Pixels
+dP_0 DN D4.U8
+dP_1 DN D5.U8
+dP_2 DN D6.U8
+dP_3 DN D7.U8
+dQ_0 DN D8.U8
+dQ_1 DN D9.U8
+dQ_2 DN D10.U8
+dQ_3 DN D11.U8
+
+
+;// Filtering Decision
+dAlpha DN D0.U8
+dBeta DN D2.U8
+
+dFilt DN D16.U8
+dAqflg DN D12.U8
+dApflg DN D17.U8
+
+dAp0q0 DN D13.U8
+dAp1p0 DN D12.U8
+dAq1q0 DN D18.U8
+dAp2p0 DN D19.U8
+dAq2q0 DN D17.U8
+
+;// bSLT4
+dTC0 DN D18.U8
+dTC1 DN D19.U8
+dTC01 DN D18.U8
+
+dTCs DN D31.S8
+dTC DN D31.U8
+
+dMask_0 DN D14.U8
+dMask_1 DN D15.U8
+
+Mask_0 RN 6
+
+dTemp DN D19.U8
+
+;// Computing P0,Q0
+qDq0p0 QN Q10.S16
+qDp1q1 QN Q11.S16
+qDelta QN Q10.S16 ; reuse qDq0p0
+dDelta DN D20.S8
+
+
+;// Computing P1,Q1
+dRp0q0 DN D24.U8
+
+dMaxP DN D23.U8
+dMinP DN D22.U8
+
+dMaxQ DN D19.U8
+dMinQ DN D21.U8
+
+dDeltaP DN D26.U8
+dDeltaQ DN D27.U8
+
+qP_0n QN Q14.S16
+qQ_0n QN Q12.S16
+
+dQ_0n DN D24.U8
+dQ_1n DN D25.U8
+dP_0n DN D29.U8
+dP_1n DN D30.U8
+
+;// bSGE4
+
+qSp0q0 QN Q10.U16
+
+qSp2q1 QN Q11.U16
+qSp0q0p1 QN Q12.U16
+qSp3p2 QN Q13.U16
+dHSp0q1 DN D28.U8
+
+qSq2p1 QN Q11.U16
+qSp0q0q1 QN Q12.U16
+qSq3q2 QN Q13.U16 ;!!
+dHSq0p1 DN D28.U8 ;!!
+
+qTemp1 QN Q11.U16 ;!!;qSp2q1
+qTemp2 QN Q12.U16 ;!!;qSp0q0p1
+
+dP_0t DN D28.U8 ;!!;dHSp0q1
+dQ_0t DN D22.U8 ;!!;Temp1
+
+dP_0n DN D29.U8
+dP_1n DN D30.U8
+dP_2n DN D31.U8
+
+dQ_0n DN D24.U8 ;!!;Temp2
+dQ_1n DN D25.U8 ;!!;Temp2
+dQ_2n DN D28.U8 ;!!;dQ_0t
+
+
+ ;// Function header
+ M_START omxVCM4P10_FilterDeblockingLuma_VerEdge_I, r11, d15
+
+ ;//Arguments on the stack
+ M_ARG ppThresholds, 4
+ M_ARG ppBS, 4
+
+ ;// d0-dAlpha_0
+ ;// d2-dBeta_0
+
+ ADD pAlpha_1, pAlpha_0, #1
+ ADD pBeta_1, pBeta_0, #1
+
+ VLD1 {dAlpha[]}, [pAlpha_0]
+ SUB pSrcDst, pSrcDst, #4
+ VLD1 {dBeta[]}, [pBeta_0]
+
+ M_LDR pBS, ppBS
+ M_LDR pThresholds, ppThresholds
+
+ MOV Mask_0,#0
+
+ ;dMask_0-14
+ ;dMask_1-15
+
+ VMOV dMask_0, #0
+ VMOV dMask_1, #1
+
+ LDR XY,=LOOP_COUNT
+
+ ADD pTmpStep, srcdstStep, srcdstStep
+
+ ;// p0-p3 - d4-d7
+ ;// q0-q3 - d8-d11
+LoopY
+LoopX
+ LDRH bS10, [pBS], #4
+
+ CMP bS10, #0
+ BEQ NoFilterBS0
+
+ ;// Load 8 rows of data
+ ADD pTmp, pSrcDst, srcdstStep
+ VLD1 dRow0, [pSrcDst], pTmpStep
+ VLD1 dRow1, [pTmp], pTmpStep
+ VLD1 dRow2, [pSrcDst], pTmpStep
+ VZIP.8 dRow0, dRow1
+ VLD1 dRow3, [pTmp], pTmpStep
+ VLD1 dRow4, [pSrcDst], pTmpStep
+ VZIP.8 dRow2, dRow3
+ VLD1 dRow5, [pTmp], pTmpStep
+ VLD1 dRow6, [pSrcDst], pTmpStep
+ VLD1 dRow7, [pTmp], pTmpStep
+ VZIP.8 dRow4, dRow5
+ VZIP.16 dRow1, dRow3
+
+
+ ;// dRow0 = [q3r0 q2r0 q1r0 q0r0 p0r0 p1r0 p2r0 p3r0]
+ ;// dRow1 = [q3r1 q2r1 q1r1 q0r1 p0r1 p1r1 p2r1 p3r1]
+ ;// dRow2 = [q3r2 q2r2 q1r2 q0r2 p0r2 p1r2 p2r2 p3r2]
+ ;// dRow3 = [q3r3 q2r3 q1r3 q0r3 p0r3 p1r3 p2r3 p3r3]
+ ;// dRow4 = [q3r4 q2r4 q1r4 q0r4 p0r4 p1r4 p2r4 p3r4]
+ ;// dRow5 = [q3r5 q2r5 q1r5 q0r5 p0r5 p1r5 p2r5 p3r5]
+ ;// dRow6 = [q3r6 q2r6 q1r6 q0r6 p0r6 p1r6 p2r6 p3r6]
+ ;// dRow7 = [q3r7 q2r7 q1r7 q0r7 p0r7 p1r7 p2r7 p3r7]
+
+ ;// 8x8 Transpose
+
+ VZIP.8 dRow6, dRow7
+
+ SUB pSrcDst, pSrcDst, srcdstStep, LSL #3
+ VZIP.16 dRow0, dRow2
+ VZIP.16 dRow5, dRow7
+
+
+ VZIP.16 dRow4, dRow6
+ VZIP.32 dRow1, dRow5
+ VZIP.32 dRow2, dRow6
+ VZIP.32 dRow3, dRow7
+ VZIP.32 dRow0, dRow4
+
+
+ ;// dRow0 - dP_3, dRow1 - dQ_0, dRow2 - dP_1, dRow3 - dQ_2
+ ;// dRow4 - dP_2, dRow5 - dQ_1, dRow6 - dP_0, dRow7 - dQ_3
+
+ ;// dQ_0 = [q0r7 q0r6 q0r5 q0r4 q0r3 q0r2 q0r1 q0r0]
+ ;// dQ_1 = [q1r7 q1r6 q1r5 q1r4 q1r3 q1r2 q1r1 q1r0]
+ ;// dQ_2 = [q2r7 q2r6 q2r5 q2r4 q2r3 q2r2 q2r1 q2r0]
+ ;// dQ_3 = [q3r7 q3r6 q3r5 q3r4 q3r3 q3r2 q3r1 q3r0]
+
+ ;// dP_0 = [p0r7 p0r6 p0r5 p0r4 p0r3 p0r2 p0r1 p0r0]
+ ;// dP_1 = [p1r7 p1r6 p1r5 p1r4 p1r3 p1r2 p1r1 p1r0]
+ ;// dP_2 = [p2r7 p2r6 p2r5 p2r4 p2r3 p2r2 p2r1 p2r0]
+ ;// dP_3 = [p3r7 p3r6 p3r5 p3r4 p3r3 p3r2 p3r1 p3r0]
+
+ VABD dAp0q0, dP_0, dQ_0
+ VABD dAp1p0, dP_1, dP_0
+
+ VABD dAq1q0, dQ_1, dQ_0
+ VABD dAp2p0, dP_2, dP_0
+
+ TST bS10, #0xff
+ VCGT dFilt, dAlpha, dAp0q0
+
+ VMAX dAp1p0, dAq1q0, dAp1p0
+ VABD dAq2q0, dQ_2, dQ_0
+
+ VMOVEQ.U32 dFilt[0], Mask_0
+ TST bS10, #0xff00
+
+ VCGT dAp2p0, dBeta, dAp2p0
+ VCGT dAp1p0, dBeta, dAp1p0
+
+ VMOVEQ.U32 dFilt[1], Mask_0
+
+ VCGT dAq2q0, dBeta, dAq2q0
+ VAND dFilt, dFilt, dAp1p0
+ TST bS10, #4
+
+ VAND dAqflg, dFilt, dAq2q0
+ VAND dApflg, dFilt, dAp2p0
+
+ BNE bSGE4
+bSLT4
+ ;// bS < 4 Filtering
+
+ BL armVCM4P10_DeblockingLumabSLT4_unsafe
+
+ ;// Transpose
+
+ VZIP.8 dP_3, dP_2
+ VZIP.8 dP_1n, dP_0n
+ VZIP.8 dQ_0n, dQ_1n
+ VZIP.8 dQ_2, dQ_3
+
+
+ VZIP.16 dP_3, dP_1n
+ ADD pTmp, pSrcDst, srcdstStep
+ VZIP.16 dQ_0n, dQ_2
+ VZIP.16 dQ_1n, dQ_3
+ VZIP.16 dP_2, dP_0n
+
+ VZIP.32 dP_3, dQ_0n
+ VZIP.32 dP_1n, dQ_2
+ VZIP.32 dP_2, dQ_1n
+ VZIP.32 dP_0n, dQ_3
+
+ ;// dRown0 - dP_3, dRown1 - dQ_0n
+ ;// dRown2 - dP_1n, dRown3 - dQ_2
+ ;// dRown4 - dP_2, dRown5 - dQ_1n
+ ;// dRown6 - dP_0n, dRown7 - dQ_3
+
+ VST1 dRown0, [pSrcDst], pTmpStep
+ VST1 dRown1, [pTmp], pTmpStep
+ VST1 dRown2, [pSrcDst], pTmpStep
+ VST1 dRown3, [pTmp], pTmpStep
+ ;1
+ VST1 dRown4, [pSrcDst], pTmpStep
+ VST1 dRown5, [pTmp], pTmpStep
+ ADDS XY, XY, XY
+ VST1 dRown6, [pSrcDst], pTmpStep
+ ADD pThresholds, pThresholds, #2
+ VST1 dRown7, [pTmp], srcdstStep
+
+ SUB pSrcDst, pSrcDst, srcdstStep, LSL #3
+ VLD1 {dAlpha[]}, [pAlpha_1]
+ ADD pSrcDst, pSrcDst, #4
+ VLD1 {dBeta[]}, [pBeta_1]
+
+ BCC LoopX
+ B ExitLoopY
+
+NoFilterBS0
+ ADD pSrcDst, pSrcDst, #4
+ ADDS XY, XY, XY
+ VLD1 {dAlpha[]}, [pAlpha_1]
+ ADD pThresholds, pThresholds, #4
+ VLD1 {dBeta[]}, [pBeta_1]
+ BCC LoopX
+ B ExitLoopY
+bSGE4
+ ;// bS >= 4 Filtering
+
+ BL armVCM4P10_DeblockingLumabSGE4_unsafe
+
+ ;// Transpose
+
+ VZIP.8 dP_3, dP_2n
+ VZIP.8 dP_1n, dP_0n
+ VZIP.8 dQ_0n, dQ_1n
+ VZIP.8 dQ_2n, dQ_3
+
+ VZIP.16 dP_3, dP_1n
+ ADD pTmp, pSrcDst, srcdstStep
+ VZIP.16 dQ_0n, dQ_2n
+ VZIP.16 dQ_1n, dQ_3
+ VZIP.16 dP_2n, dP_0n
+
+ VZIP.32 dP_3, dQ_0n
+ VZIP.32 dP_1n, dQ_2n
+ VZIP.32 dP_2n, dQ_1n
+ VZIP.32 dP_0n, dQ_3
+
+ ;// dRow0n - dP_3, dRow1n - dQ_0n, dRow2n - dP_1n, dRow3n - dQ_2n
+ ;// dRow4n - dP_2, dRow5n - dQ_1n, dRow6n - dP_0n, dRow7n - dQ_3
+
+ VST1 dRow0n, [pSrcDst], pTmpStep
+ VST1 dRow1n, [pTmp], pTmpStep
+ VST1 dRow2n, [pSrcDst], pTmpStep
+ VST1 dRow3n, [pTmp], pTmpStep
+ VST1 dRow4n, [pSrcDst], pTmpStep
+ VST1 dRow5n, [pTmp], pTmpStep
+ ADDS XY,XY,XY
+ VST1 dRow6n, [pSrcDst], pTmpStep
+ ADD pThresholds, pThresholds, #4
+ VST1 dRow7n, [pTmp], pTmpStep
+
+ SUB pSrcDst, pSrcDst, srcdstStep, LSL #3
+ VLD1 {dAlpha[]}, [pAlpha_1]
+ ADD pSrcDst, pSrcDst, #4
+ VLD1 {dBeta[]}, [pBeta_1]
+
+ BCC LoopX
+
+ExitLoopY
+ SUB pBS, pBS, #14
+ SUB pThresholds, pThresholds, #14
+ SUB pSrcDst, pSrcDst, #16
+ VLD1 {dAlpha[]}, [pAlpha_0]
+ ADD pSrcDst, pSrcDst, srcdstStep, LSL #3
+ VLD1 {dBeta[]}, [pBeta_0]
+ BNE LoopY
+
+ MOV r0, #OMX_Sts_NoErr
+
+ M_END
+
+ ENDIF
+
+
+ END
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
new file mode 100755
index 0000000..3ce41be
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
@@ -0,0 +1,79 @@
+/**
+ *
+ * File Name: omxVCM4P10_InterpolateChroma.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate 1/8 Pixel interpolation for Chroma Block
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+
+/**
+ * Function: omxVCM4P10_InterpolateChroma,
+ *
+ * Description:
+ * Performs 1/8-pixel interpolation for inter chroma MB.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrc Pointer to the source reference frame buffer
+ * [in] srcStep Reference frame step in byte
+ * [in] dstStep Destination frame step in byte. Must be multiple of roi.width.
+ * [in] dx Fractional part of horizontal motion vector component
+ * in 1/8 pixel unit;valid in the range [0,7]
+ * [in] dy Fractional part of vertical motion vector component
+ * in 1/8 pixel unit;valid in the range [0,7]
+ * [in] roi Dimension of the interpolation region;the parameters roi.width and roi.height must
+ * be equal to either 2, 4, or 8.
+ * [out] pDst Pointer to the destination frame buffer.
+ * if roi.width==2, 2-byte alignment required
+ * if roi.width==4, 4-byte alignment required
+ * if roi.width==8, 8-byte alignment required
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns OMX_Sts_BadArgErr:
+ * pSrc or pDst is NULL.
+ * srcStep or dstStep < 8.
+ * dx or dy is out of range [0-7].
+ * roi.width or roi.height is out of range {2,4,8}.
+ * roi.width is equal to 2, but pDst is not 2-byte aligned.
+ * roi.width is equal to 4, but pDst is not 4-byte aligned.
+ * roi.width is equal to 8, but pDst is not 8 byte aligned.
+ * srcStep or dstStep is not a multiple of 8.
+ *
+ */
+
+OMXResult omxVCM4P10_InterpolateChroma (
+ const OMX_U8* pSrc,
+ OMX_S32 srcStep,
+ OMX_U8* pDst,
+ OMX_S32 dstStep,
+ OMX_S32 dx,
+ OMX_S32 dy,
+ OMXSize roi
+ )
+{
+ return armVCM4P10_Interpolate_Chroma
+ ((OMX_U8*)pSrc, srcStep, pDst, dstStep, roi.width, roi.height, dx, dy);
+}
+
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
new file mode 100755
index 0000000..942ebc6
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_InterpolateLuma_s.s
@@ -0,0 +1,553 @@
+;//
+;//
+;// File Name: omxVCM4P10_InterpolateLuma_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+;// Function:
+;// omxVCM4P10_InterpolateLuma
+;//
+;// This function implements omxVCM4P10_InterpolateLuma in v6 assembly.
+;// Performs quarter pel interpolation of inter luma MB.
+;// It's assumed that the frame is already padded when calling this function.
+;// Parameters:
+;// [in] pSrc Pointer to the source reference frame buffer
+;// [in] srcStep Reference frame step in byte
+;// [in] dstStep Destination frame step in byte. Must be multiple of roi.width
+;// [in] dx Fractional part of horizontal motion vector
+;// component in 1/4 pixel unit; valid in the range [0,3]
+;// [in] dy Fractional part of vertical motion vector
+;// component in 1/4 pixel unit; valid in the range [0,3]
+;// [in] roi Dimension of the interpolation region;the parameters roi.width and roi.height must
+;// be equal to either 4, 8, or 16.
+;// [out] pDst Pointer to the destination frame buffer.
+;// if roi.width==4, 4-byte alignment required
+;// if roi.width==8, 8-byte alignment required
+;// if roi.width==16, 16-byte alignment required
+;//
+;// Return Value:
+;// If the function runs without error, it returns OMX_Sts_NoErr.
+;// It is assued that following cases are satisfied before calling this function:
+;// pSrc or pDst is not NULL.
+;// srcStep or dstStep >= roi.width.
+;// dx or dy is in the range [0-3].
+;// roi.width or roi.height is not out of range {4, 8, 16}.
+;// If roi.width is equal to 4, Dst is 4 byte aligned.
+;// If roi.width is equal to 8, pDst is 8 byte aligned.
+;// If roi.width is equal to 16, pDst is 16 byte aligned.
+;// srcStep and dstStep is multiple of 8.
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+ EXPORT omxVCM4P10_InterpolateLuma
+
+
+ IF CortexA8
+ IMPORT armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ IMPORT armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ IMPORT armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+ IMPORT armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+ ENDIF
+
+
+
+;// Declare input registers
+pSrc RN 0
+srcStep RN 1
+pDst RN 2
+dstStep RN 3
+iHeight RN 4
+iWidth RN 5
+
+;// Declare other intermediate registers
+idx RN 6
+idy RN 7
+index RN 6
+Temp RN 12
+pArgs RN 11
+
+
+ IF CortexA8
+
+ ;//
+ ;// Interpolation of luma is implemented by processing block of pixels, size 4x4 at a time.
+ ;//
+ M_ALLOC4 ppArgs, 16
+
+ ;// Function header
+ M_START omxVCM4P10_InterpolateLuma, r11, d15
+
+pSrcBK RN 8
+
+;// Declare Neon registers
+dCoeff5 DN 30.S16
+dCoeff20 DN 31.S16
+
+;// Registers used for implementing Horizontal interpolation
+dSrc0c DN 14.U8
+dSrc1c DN 16.U8
+dSrc2c DN 18.U8
+dSrc3c DN 20.U8
+dSrc0d DN 15.U8
+dSrc1d DN 17.U8
+dSrc2d DN 19.U8
+dSrc3d DN 21.U8
+dAccH0 DN 22.U8
+dAccH1 DN 24.U8
+dAccH2 DN 26.U8
+dAccH3 DN 28.U8
+dResultH0 DN 22.U32
+dResultH1 DN 24.U32
+dResultH2 DN 26.U32
+dResultH3 DN 28.U32
+
+;// Registers used for implementing Vertical interpolation
+dSrc0 DN 9.U8
+dSrc1 DN 10.U8
+dSrc2 DN 11.U8
+dSrc3 DN 12.U8
+dSrc4 DN 13.U8
+dAccV0 DN 0.U8
+dAccV1 DN 2.U8
+dAccV2 DN 4.U8
+dAccV3 DN 6.U8
+dResultV0 DN 0.U32
+dResultV1 DN 2.U32
+dResultV2 DN 4.U32
+dResultV3 DN 6.U32
+
+;// Registers used for implementing Diagonal interpolation
+dTAcc0 DN 0.U8
+dTAcc1 DN 2.U8
+dTAcc2 DN 4.U8
+dTAcc3 DN 6.U8
+dTRes0 DN 0.32
+dTRes1 DN 2.32
+dTRes2 DN 4.32
+dTRes3 DN 6.32
+dTResult0 DN 14.U8
+dTResult1 DN 16.U8
+dTResult2 DN 18.U8
+dTResult3 DN 20.U8
+dTempP0 DN 18.S16
+dTempP1 DN 19.S16
+dTempQ0 DN 20.S16
+dTempQ1 DN 21.S16
+dTempR0 DN 22.S16
+dTempR1 DN 23.S16
+dTempS0 DN 24.S16
+dTempS1 DN 25.S16
+qTempP01 QN 9.S16
+qTempQ01 QN 10.S16
+qTempR01 QN 11.S16
+qTempS01 QN 12.S16
+
+;// Intermediate values for averaging
+qRes2 QN 7.S16
+qRes3 QN 8.S16
+qRes4 QN 9.S16
+qRes5 QN 10.S16
+qRes6 QN 11.S16
+
+;// For implementing copy
+dDst0 DN 9.32
+dDst1 DN 10.32
+dDst2 DN 11.32
+dDst3 DN 12.32
+
+ ;// Define stack arguments
+ M_ARG ptridx, 4
+ M_ARG ptridy, 4
+ M_ARG ptrWidth, 4
+ M_ARG ptrHeight, 4
+
+ ;// Load structure elements of roi
+ M_LDR idx, ptridx
+ M_LDR idy, ptridy
+ M_LDR iWidth, ptrWidth
+ M_LDR iHeight, ptrHeight
+
+ ADD index, idx, idy, LSL #2 ;// [index] = [idy][idx]
+ M_ADR pArgs, ppArgs
+
+ ;// Move coefficients Neon registers
+ VMOV dCoeff20, #20
+ VMOV dCoeff5, #5
+
+Block4x4WidthLoop
+Block4x4HeightLoop
+
+ STM pArgs, {pSrc,srcStep,pDst,dstStep}
+
+ ;// switch table using motion vector as index
+ ADD pc, pc, index, LSL #2
+ B Case_f
+ B Case_0
+ B Case_1
+ B Case_2
+ B Case_3
+ B Case_4
+ B Case_5
+ B Case_6
+ B Case_7
+ B Case_8
+ B Case_9
+ B Case_a
+ B Case_b
+ B Case_c
+ B Case_d
+ B Case_e
+ B Case_f
+
+Case_0
+ ;// Case G
+ M_PRINTF "Case 0 \n"
+
+ ;// Loads a 4x4 block of .8 and stores as .32
+ ADD Temp, pSrc, srcStep, LSL #1
+ VLD1 dSrc0, [pSrc], srcStep
+ VLD1 dSrc2, [Temp], srcStep
+ VLD1 dSrc1, [pSrc]
+ VLD1 dSrc3, [Temp]
+
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dDst0[0], [pDst], dstStep
+ VST1 dDst2[0], [Temp], dstStep
+ VST1 dDst1[0], [pDst]
+ VST1 dDst3[0], [Temp]
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_1
+ ;// Case a
+ M_PRINTF "Case 1 \n"
+
+ SUB pSrc, pSrc, #2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ VRHADD dAccH0, dAccH0, dSrc0c
+ VRHADD dAccH2, dAccH2, dSrc2c
+ VRHADD dAccH1, dAccH1, dSrc1c
+ VRHADD dAccH3, dAccH3, dSrc3c
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dResultH0[0], [pDst], dstStep
+ VST1 dResultH2[0], [Temp], dstStep
+ VST1 dResultH1[0], [pDst]
+ VST1 dResultH3[0], [Temp]
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_2
+ ;// Case b
+ M_PRINTF "Case 2 \n"
+
+ SUB pSrc, pSrc, #2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dResultH0[0], [pDst], dstStep
+ VST1 dResultH2[0], [Temp], dstStep
+ VST1 dResultH1[0], [pDst]
+ VST1 dResultH3[0], [Temp]
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_3
+ ;// Case c
+ M_PRINTF "Case 3 \n"
+
+ SUB pSrc, pSrc, #2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ VRHADD dAccH0, dAccH0, dSrc0d
+ VRHADD dAccH2, dAccH2, dSrc2d
+ VRHADD dAccH1, dAccH1, dSrc1d
+ VRHADD dAccH3, dAccH3, dSrc3d
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dResultH0[0], [pDst], dstStep
+ VST1 dResultH2[0], [Temp], dstStep
+ VST1 dResultH1[0], [pDst]
+ VST1 dResultH3[0], [Temp]
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_4
+ ;// Case d
+ M_PRINTF "Case 4 \n"
+
+ SUB pSrc, pSrc, srcStep, LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ VRHADD dAccV0, dAccV0, dSrc0
+ VRHADD dAccV2, dAccV2, dSrc2
+ VRHADD dAccV1, dAccV1, dSrc1
+ VRHADD dAccV3, dAccV3, dSrc3
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dResultV0[0], [pDst], dstStep
+ VST1 dResultV2[0], [Temp], dstStep
+ VST1 dResultV1[0], [pDst]
+ VST1 dResultV3[0], [Temp]
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_5
+ ;// Case e
+ M_PRINTF "Case 5 \n"
+
+ MOV pSrcBK, pSrc
+ SUB pSrc, pSrc, srcStep, LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ SUB pSrc, pSrcBK, #2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ VRHADD dAccH0, dAccH0, dAccV0
+ VRHADD dAccH2, dAccH2, dAccV2
+ VRHADD dAccH1, dAccH1, dAccV1
+ VRHADD dAccH3, dAccH3, dAccV3
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dResultH0[0], [pDst], dstStep
+ VST1 dResultH2[0], [Temp], dstStep
+ VST1 dResultH1[0], [pDst]
+ VST1 dResultH3[0], [Temp]
+
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_6
+ ;// Case f
+ M_PRINTF "Case 6 \n"
+
+ SUB pSrc, pSrc, srcStep, LSL #1
+ SUB pSrc, pSrc, #2
+ BL armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+ VQRSHRUN dTResult0, qRes2, #5
+ VQRSHRUN dTResult1, qRes3, #5
+ VQRSHRUN dTResult2, qRes4, #5
+ VQRSHRUN dTResult3, qRes5, #5
+ VRHADD dTAcc0, dTAcc0, dTResult0
+ VRHADD dTAcc2, dTAcc2, dTResult2
+ VRHADD dTAcc1, dTAcc1, dTResult1
+ VRHADD dTAcc3, dTAcc3, dTResult3
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dTRes0[0], [pDst], dstStep
+ VST1 dTRes2[0], [Temp], dstStep
+ VST1 dTRes1[0], [pDst]
+ VST1 dTRes3[0], [Temp]
+
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_7
+ ;// Case g
+ M_PRINTF "Case 7 \n"
+ MOV pSrcBK, pSrc
+ ADD pSrc, pSrc, #1
+ SUB pSrc, pSrc, srcStep, LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ SUB pSrc, pSrcBK, #2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ VRHADD dAccH0, dAccH0, dAccV0
+ VRHADD dAccH2, dAccH2, dAccV2
+ VRHADD dAccH1, dAccH1, dAccV1
+ VRHADD dAccH3, dAccH3, dAccV3
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dResultH0[0], [pDst], dstStep
+ VST1 dResultH2[0], [Temp], dstStep
+ VST1 dResultH1[0], [pDst]
+ VST1 dResultH3[0], [Temp]
+
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_8
+ ;// Case h
+ M_PRINTF "Case 8 \n"
+
+ SUB pSrc, pSrc, srcStep, LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dResultV0[0], [pDst], dstStep
+ VST1 dResultV2[0], [Temp], dstStep
+ VST1 dResultV1[0], [pDst]
+ VST1 dResultV3[0], [Temp]
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_9
+ ;// Case i
+ M_PRINTF "Case 9 \n"
+ SUB pSrc, pSrc, srcStep, LSL #1
+ SUB pSrc, pSrc, #2
+ BL armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+ VEXT dTempP0, dTempP0, dTempP1, #2
+ VEXT dTempQ0, dTempQ0, dTempQ1, #2
+ VEXT dTempR0, dTempR0, dTempR1, #2
+ VEXT dTempS0, dTempS0, dTempS1, #2
+
+ VQRSHRUN dTResult0, qTempP01, #5
+ VQRSHRUN dTResult1, qTempQ01, #5
+ VQRSHRUN dTResult2, qTempR01, #5
+ VQRSHRUN dTResult3, qTempS01, #5
+
+ VRHADD dTAcc0, dTAcc0, dTResult0
+ VRHADD dTAcc2, dTAcc2, dTResult2
+ VRHADD dTAcc1, dTAcc1, dTResult1
+ VRHADD dTAcc3, dTAcc3, dTResult3
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dTRes0[0], [pDst], dstStep
+ VST1 dTRes2[0], [Temp], dstStep
+ VST1 dTRes1[0], [pDst]
+ VST1 dTRes3[0], [Temp]
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_a
+ ;// Case j
+ M_PRINTF "Case a \n"
+
+ SUB pSrc, pSrc, srcStep, LSL #1
+ SUB pSrc, pSrc, #2
+ BL armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dTRes0[0], [pDst], dstStep
+ VST1 dTRes2[0], [Temp], dstStep
+ VST1 dTRes1[0], [pDst]
+ VST1 dTRes3[0], [Temp]
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_b
+ ;// Case k
+ M_PRINTF "Case b \n"
+ SUB pSrc, pSrc, srcStep, LSL #1
+ SUB pSrc, pSrc, #2
+ BL armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+ VEXT dTempP0, dTempP0, dTempP1, #3
+ VEXT dTempQ0, dTempQ0, dTempQ1, #3
+ VEXT dTempR0, dTempR0, dTempR1, #3
+ VEXT dTempS0, dTempS0, dTempS1, #3
+
+ VQRSHRUN dTResult0, qTempP01, #5
+ VQRSHRUN dTResult1, qTempQ01, #5
+ VQRSHRUN dTResult2, qTempR01, #5
+ VQRSHRUN dTResult3, qTempS01, #5
+
+ VRHADD dTAcc0, dTAcc0, dTResult0
+ VRHADD dTAcc2, dTAcc2, dTResult2
+ VRHADD dTAcc1, dTAcc1, dTResult1
+ VRHADD dTAcc3, dTAcc3, dTResult3
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dTRes0[0], [pDst], dstStep
+ VST1 dTRes2[0], [Temp], dstStep
+ VST1 dTRes1[0], [pDst]
+ VST1 dTRes3[0], [Temp]
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_c
+ ;// Case n
+ M_PRINTF "Case c \n"
+
+ SUB pSrc, pSrc, srcStep, LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ VRHADD dAccV0, dAccV0, dSrc1
+ VRHADD dAccV2, dAccV2, dSrc3
+ VRHADD dAccV1, dAccV1, dSrc2
+ VRHADD dAccV3, dAccV3, dSrc4
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dResultV0[0], [pDst], dstStep
+ VST1 dResultV2[0], [Temp], dstStep
+ VST1 dResultV1[0], [pDst]
+ VST1 dResultV3[0], [Temp]
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_d
+ ;// Case p
+ M_PRINTF "Case d \n"
+
+ MOV pSrcBK, pSrc
+ SUB pSrc, pSrc, srcStep, LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ ADD pSrc, pSrcBK, srcStep
+ SUB pSrc, pSrc, #2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ VRHADD dAccH0, dAccH0, dAccV0
+ VRHADD dAccH2, dAccH2, dAccV2
+ VRHADD dAccH1, dAccH1, dAccV1
+ VRHADD dAccH3, dAccH3, dAccV3
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dResultH0[0], [pDst], dstStep
+ VST1 dResultH2[0], [Temp], dstStep
+ VST1 dResultH1[0], [pDst]
+ VST1 dResultH3[0], [Temp]
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_e
+ ;// Case q
+ M_PRINTF "Case e \n"
+
+ SUB pSrc, pSrc, srcStep, LSL #1
+ SUB pSrc, pSrc, #2
+ BL armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+ VQRSHRUN dTResult0, qRes3, #5
+ VQRSHRUN dTResult1, qRes4, #5
+ VQRSHRUN dTResult2, qRes5, #5
+ VQRSHRUN dTResult3, qRes6, #5
+
+ VRHADD dTAcc0, dTAcc0, dTResult0
+ VRHADD dTAcc2, dTAcc2, dTResult2
+ VRHADD dTAcc1, dTAcc1, dTResult1
+ VRHADD dTAcc3, dTAcc3, dTResult3
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dTRes0[0], [pDst], dstStep
+ VST1 dTRes2[0], [Temp], dstStep
+ VST1 dTRes1[0], [pDst]
+ VST1 dTRes3[0], [Temp]
+ M_ADR pArgs, ppArgs
+ B Block4x4LoopEnd
+Case_f
+ ;// Case r
+ M_PRINTF "Case f \n"
+ MOV pSrcBK, pSrc
+ ADD pSrc, pSrc, #1
+ SUB pSrc, pSrc, srcStep, LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ ADD pSrc, pSrcBK, srcStep
+ SUB pSrc, pSrc, #2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ VRHADD dAccH0, dAccH0, dAccV0
+ VRHADD dAccH2, dAccH2, dAccV2
+ VRHADD dAccH1, dAccH1, dAccV1
+ VRHADD dAccH3, dAccH3, dAccV3
+ ADD Temp, pDst, dstStep, LSL #1
+ VST1 dResultH0[0], [pDst], dstStep
+ VST1 dResultH2[0], [Temp], dstStep
+ VST1 dResultH1[0], [pDst]
+ VST1 dResultH3[0], [Temp]
+ M_ADR pArgs, ppArgs
+
+
+Block4x4LoopEnd
+
+ ;// Width Loop
+ ;//M_ADR pArgs, ppArgs
+ LDM pArgs, {pSrc,srcStep,pDst,dstStep} ;// Load arguments
+ SUBS iWidth, iWidth, #4
+ ADD pSrc, pSrc, #4
+ ADD pDst, pDst, #4
+ BGT Block4x4WidthLoop
+
+ ;// Height Loop
+ SUBS iHeight, iHeight, #4
+ M_LDR iWidth, ptrWidth
+ M_ADR pArgs, ppArgs
+ ADD pSrc, pSrc, srcStep, LSL #2
+ ADD pDst, pDst, dstStep, LSL #2
+ SUB pSrc, pSrc, iWidth
+ SUB pDst, pDst, iWidth
+ BGT Block4x4HeightLoop
+
+EndOfInterpolation
+ MOV r0, #0
+ M_END
+
+ ENDIF
+ ;// End of CortexA8
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
new file mode 100755
index 0000000..3a60705
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8_s.s
@@ -0,0 +1,436 @@
+;//
+;//
+;// File Name: omxVCM4P10_PredictIntraChroma_8x8_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ EXPORT armVCM4P10_pIndexTable8x8
+
+;// Define the processor variants supported by this file
+
+ M_VARIANTS CortexA8
+
+ AREA table, DATA
+;//-------------------------------------------------------
+;// This table for implementing switch case of C in asm by
+;// the mehtod of two levels of indexing.
+;//-------------------------------------------------------
+
+ M_TABLE armVCM4P10_pIndexTable8x8
+ DCD OMX_VC_CHROMA_DC, OMX_VC_CHROMA_HOR
+ DCD OMX_VC_CHROMA_VERT, OMX_VC_CHROMA_PLANE
+
+ M_TABLE armVCM4P10_MultiplierTableChroma8x8,1
+ DCW 3, 2, 1,4
+ DCW -3,-2,-1,0
+ DCW 1, 2, 3,4
+
+
+
+ IF CortexA8
+
+;//--------------------------------------------
+;// Scratch variable
+;//--------------------------------------------
+
+pc RN 15
+return RN 0
+pTable RN 8
+
+;//--------------------------------------------
+;// Input Arguments
+;//--------------------------------------------
+pSrcLeft RN 0 ;// input pointer
+pSrcAbove RN 1 ;// input pointer
+pSrcAboveLeft RN 2 ;// input pointer
+pDst RN 3 ;// output pointer
+leftStep RN 4 ;// input variable
+dstStep RN 5 ;// input variable
+predMode RN 6 ;// input variable
+availability RN 7 ;// input variable
+pMultiplierTable RN 2
+
+pTmp RN 9
+step RN 10
+
+;//---------------------
+;// Neon Registers
+;//---------------------
+
+;// OMX_VC_CHROMA_HOR
+
+dLeftVal0 DN D0.8
+dLeftVal1 DN D1.8
+dLeftVal2 DN D2.8
+dLeftVal3 DN D3.8
+dLeftVal4 DN D4.8
+dLeftVal5 DN D5.8
+dLeftVal6 DN D6.8
+dLeftVal7 DN D7.8
+
+;// OMX_VC_CHROMA_VERT
+
+dAboveVal DN D0.U8
+
+;// OMX_VC_CHROMA_DC
+
+dLeftVal DN D1.U8
+dSumAboveValU16 DN D2.U16
+dSumAboveValU32 DN D3.U32
+dSumAboveValU8 DN D3.U8
+dSumLeftValU16 DN D2.U16
+dSumLeftValU32 DN D1.U32
+dSumLeftValU8 DN D1.U8
+dSumAboveLeft DN D2.U32
+dSumAboveLeftU8 DN D2.U8
+dIndexRow0U8 DN D5.U8
+dIndexRow0 DN D5.U64
+dIndexRow4U8 DN D6.U8
+dIndexRow4 DN D6.U64
+dDstRow0 DN D0.U8
+dDstRow4 DN D4.U8
+dConst128U8 DN D0.U8
+
+;// OMX_VC_CHROMA_PLANE
+
+dRevAboveVal DN D3.U8
+dRevAboveValU64 DN D3.U64
+dAboveLeftVal DN D2.U8
+qAbove7minus0 QN Q3.S16
+qAboveDiff QN Q2.S16
+dIndex DN D8.U8
+dDiffAboveU8 DN D9.U8
+dDiffAboveS16 DN D9.S16
+dAboveDiff0U8 DN D4.U8
+dAboveDiff0U64 DN D4.U64
+dAbove7minus0U8 DN D6.U8
+dMultiplier DN D10.S16
+dHorPred DN D11.S16
+dRevLeftVal DN D3.U8
+dRevLeftValU64 DN D3.U64
+qLeft7minus0 QN Q7.S16
+qLeftDiff QN Q6.S16
+dDiffLeftU8 DN D16.U8
+dDiffLeftS16 DN D16.S16
+dLeftDiff0U8 DN D12.U8
+dLeftDiff0U64 DN D12.U64
+dLeft7minus0U8 DN D14.U8
+dVerPred DN D3.S16
+dHVValS16 DN D3.S16
+dHVValS32 DN D3.S32
+dHVTempS32 DN D2.S32
+qA QN Q0.S16
+qB QN Q2.S16
+qC QN Q3.S16
+qMultiplier QN Q5.S16
+dMultiplier0 DN D10.S16
+dMultiplier1 DN D11.S16
+qC0 QN Q0.S16
+qC1 QN Q1.S16
+qC2 QN Q4.S16
+qC3 QN Q5.S16
+qC4 QN Q6.S16
+qC5 QN Q7.S16
+qC6 QN Q8.S16
+qC7 QN Q9.S16
+qSum0 QN Q0.S16
+qSum1 QN Q1.S16
+qSum2 QN Q4.S16
+qSum3 QN Q5.S16
+qSum4 QN Q6.S16
+qSum5 QN Q7.S16
+qSum6 QN Q8.S16
+qSum7 QN Q9.S16
+dSum0 DN D0.U8
+dSum1 DN D1.U8
+dSum2 DN D2.U8
+dSum3 DN D3.U8
+dSum4 DN D4.U8
+dSum5 DN D5.U8
+dSum6 DN D6.U8
+dSum7 DN D7.U8
+
+;//-----------------------------------------------------------------------------------------------
+;// omxVCM4P10_PredictIntraChroma_8x8 starts
+;//-----------------------------------------------------------------------------------------------
+
+ ;// Write function header
+ M_START omxVCM4P10_PredictIntraChroma_8x8, r10, d15
+
+ ;// Define stack arguments
+ M_ARG LeftStep, 4
+ M_ARG DstStep, 4
+ M_ARG PredMode, 4
+ M_ARG Availability, 4
+
+ LDR pTable,=armVCM4P10_pIndexTable8x8 ;// Load index table for switch case
+
+ ;// Load argument from the stack
+ M_LDR predMode, PredMode ;// Arg predMode loaded from stack to reg
+ M_LDR leftStep, LeftStep ;// Arg leftStep loaded from stack to reg
+ M_LDR dstStep, DstStep ;// Arg dstStep loaded from stack to reg
+ M_LDR availability, Availability ;// Arg availability loaded from stack to reg
+
+
+ LDR pc, [pTable, predMode, LSL #2] ;// Branch to the case based on preMode
+
+OMX_VC_CHROMA_DC
+
+ TST availability, #OMX_VC_LEFT
+ BEQ DCChroma8x8LeftNotAvailable
+
+ ADD pTmp, pSrcLeft, leftStep
+ ADD step, leftStep, leftStep
+
+ ;// Load Left Edge
+ VLD1 {dLeftVal[0]},[pSrcLeft],step ;// pSrcLeft[0*leftStep]
+ VLD1 {dLeftVal[1]},[pTmp],step ;// pSrcLeft[1*leftStep]
+ VLD1 {dLeftVal[2]},[pSrcLeft],step ;// pSrcLeft[2*leftStep]
+ VLD1 {dLeftVal[3]},[pTmp],step ;// pSrcLeft[3*leftStep]
+ VLD1 {dLeftVal[4]},[pSrcLeft],step ;// pSrcLeft[4*leftStep]
+ VLD1 {dLeftVal[5]},[pTmp],step ;// pSrcLeft[5*leftStep]
+ VLD1 {dLeftVal[6]},[pSrcLeft],step ;// pSrcLeft[6*leftStep]
+ VLD1 {dLeftVal[7]},[pTmp] ;// pSrcLeft[7*leftStep]
+
+ TST availability, #OMX_VC_UPPER
+ BEQ DCChroma8x8LeftOnlyAvailable
+
+ ;// Load Upper Edge also
+ VLD1 dAboveVal,[pSrcAbove] ;// pSrcAbove[0 to 7]
+
+ MOV return, #OMX_Sts_NoErr ;// returnNoError
+
+ VPADDL dSumAboveValU16, dAboveVal ;// pSrcAbove[ 6+7 | 4+5 | 2+3 | 0+1 ]
+ VPADDL dSumAboveValU32, dSumAboveValU16 ;// pSrcAbove[ 4+5+6+7 | 0+1+2+3 ]
+
+ VPADDL dSumLeftValU16, dLeftVal ;// pSrcLeft[ 6+7 | 4+5 | 2+3 | 0+1 ]
+ VPADDL dSumLeftValU32, dSumLeftValU16 ;// pSrcLeft[ 4+5+6+7 | 0+1+2+3 ]
+
+ VADD dSumAboveLeft,dSumAboveValU32,dSumLeftValU32
+ VRSHR dSumAboveLeft,dSumAboveLeft,#3 ;// Sum = (Sum + 4) >> 3
+ VRSHR dSumAboveValU32,dSumAboveValU32,#2 ;// Sum = (Sum + 2) >> 2
+ VRSHR dSumLeftValU32,dSumLeftValU32,#2 ;// Sum = (Sum + 2) >> 2
+
+ VMOV dIndexRow0U8,#0x0c
+ VMOV dIndexRow4U8,#0x04
+ VSHL dIndexRow0,dIndexRow0,#32 ;// index0 = 0x0c0c0c0c00000000
+ VSHR dIndexRow4,dIndexRow4,#32 ;// index4 = 0x0000000004040404
+ VADD dIndexRow4U8,dIndexRow4U8,dIndexRow0U8 ;// index4 = 0x0c0c0c0c04040404
+ VTBL dDstRow0,{dSumAboveLeftU8,dSumAboveValU8},dIndexRow0U8
+ VTBL dDstRow4,{dSumLeftValU8,dSumAboveLeftU8},dIndexRow4U8
+
+DCChroma8x8LeftStore
+ ADD pTmp, pDst, dstStep
+ ADD step, dstStep, dstStep
+
+ VST1 dDstRow0,[pDst],step ;// pDst[0*dstStep+x] :0<= x <= 7
+ VST1 dDstRow0,[pTmp],step ;// pDst[1*dstStep+x] :0<= x <= 7
+ VST1 dDstRow0,[pDst],step ;// pDst[2*dstStep+x] :0<= x <= 7
+ VST1 dDstRow0,[pTmp],step ;// pDst[3*dstStep+x] :0<= x <= 7
+ VST1 dDstRow4,[pDst],step ;// pDst[4*dstStep+x] :0<= x <= 7
+ VST1 dDstRow4,[pTmp],step ;// pDst[5*dstStep+x] :0<= x <= 7
+ VST1 dDstRow4,[pDst],step ;// pDst[6*dstStep+x] :0<= x <= 7
+ VST1 dDstRow4,[pTmp] ;// pDst[7*dstStep+x] :0<= x <= 7
+
+ M_EXIT
+
+
+DCChroma8x8LeftOnlyAvailable
+
+ MOV return, #OMX_Sts_NoErr
+
+ VPADDL dSumLeftValU16, dLeftVal ;// pSrcLeft[ 6+7 | 4+5 | 2+3 | 0+1 ]
+ VPADDL dSumLeftValU32, dSumLeftValU16 ;// pSrcLeft[ 4+5+6+7 | 0+1+2+3 ]
+ VRSHR dSumLeftValU32,dSumLeftValU32,#2 ;// Sum = (Sum + 2) >> 2
+
+ VDUP dDstRow0,dSumLeftValU8[0]
+ VDUP dDstRow4,dSumLeftValU8[4]
+
+ B DCChroma8x8LeftStore
+
+
+DCChroma8x8LeftNotAvailable
+
+ TST availability, #OMX_VC_UPPER
+ BEQ DCChroma8x8NoneAvailable
+
+ ;// Load Upper Edge
+ VLD1 dAboveVal,[pSrcAbove] ;// pSrcAbove[0 to 7]
+ MOV return, #OMX_Sts_NoErr ;// returnNoError
+
+ VPADDL dSumAboveValU16, dAboveVal ;// pSrcAbove[ 6+7 | 4+5 | 2+3 | 0+1 ]
+ VPADDL dSumAboveValU32, dSumAboveValU16 ;// pSrcAbove[ 4+5+6+7 | 0+1+2+3 ]
+ VRSHR dSumAboveValU32,dSumAboveValU32,#2 ;// Sum = (Sum + 2) >> 2
+ VMOV dIndexRow0U8,#0x04
+ VSHL dIndexRow0,dIndexRow0,#32 ;// index = 0x0404040400000000
+ VTBL dDstRow0,{dSumAboveValU8},dIndexRow0U8
+
+ B DCChroma8x8UpperStore
+
+
+DCChroma8x8NoneAvailable
+
+ VMOV dConst128U8,#0x80 ;// 0x8080808080808080 if(count == 0)
+ MOV return, #OMX_Sts_NoErr ;// returnNoError
+
+DCChroma8x8UpperStore
+
+ ADD pTmp, pDst, dstStep
+ ADD step, dstStep, dstStep
+
+ VST1 dDstRow0,[pDst],step ;// pDst[0*dstStep+x] :0<= x <= 7
+ VST1 dDstRow0,[pTmp],step ;// pDst[1*dstStep+x] :0<= x <= 7
+ VST1 dDstRow0,[pDst],step ;// pDst[2*dstStep+x] :0<= x <= 7
+ VST1 dDstRow0,[pTmp],step ;// pDst[3*dstStep+x] :0<= x <= 7
+ VST1 dDstRow0,[pDst],step ;// pDst[4*dstStep+x] :0<= x <= 7
+ VST1 dDstRow0,[pTmp],step ;// pDst[5*dstStep+x] :0<= x <= 7
+ VST1 dDstRow0,[pDst],step ;// pDst[6*dstStep+x] :0<= x <= 7
+ VST1 dDstRow0,[pTmp] ;// pDst[7*dstStep+x] :0<= x <= 7
+
+ M_EXIT
+
+
+OMX_VC_CHROMA_VERT
+
+ VLD1 dAboveVal,[pSrcAbove] ;// pSrcAbove[x] :0<= x <= 7
+ MOV return, #OMX_Sts_NoErr
+
+ B DCChroma8x8UpperStore
+
+
+OMX_VC_CHROMA_HOR
+
+ ADD pTmp, pSrcLeft, leftStep
+ ADD step, leftStep, leftStep
+
+ VLD1 {dLeftVal0[]},[pSrcLeft],step ;// pSrcLeft[0*leftStep]
+ VLD1 {dLeftVal1[]},[pTmp],step ;// pSrcLeft[1*leftStep]
+ VLD1 {dLeftVal2[]},[pSrcLeft],step ;// pSrcLeft[2*leftStep]
+ VLD1 {dLeftVal3[]},[pTmp],step ;// pSrcLeft[3*leftStep]
+ VLD1 {dLeftVal4[]},[pSrcLeft],step ;// pSrcLeft[4*leftStep]
+ VLD1 {dLeftVal5[]},[pTmp],step ;// pSrcLeft[5*leftStep]
+ VLD1 {dLeftVal6[]},[pSrcLeft],step ;// pSrcLeft[6*leftStep]
+ VLD1 {dLeftVal7[]},[pTmp] ;// pSrcLeft[7*leftStep]
+
+ B DCChroma8x8PlaneStore
+
+
+OMX_VC_CHROMA_PLANE
+ ADD pTmp, pSrcLeft, leftStep
+ ADD step, leftStep, leftStep
+
+ VLD1 dAboveVal,[pSrcAbove] ;// pSrcAbove[x] :0<= x <= 7
+ VLD1 dAboveLeftVal[0],[pSrcAboveLeft]
+
+ VLD1 {dLeftVal[0]},[pSrcLeft],step ;// pSrcLeft[0*leftStep]
+ VLD1 {dLeftVal[1]},[pTmp],step ;// pSrcLeft[1*leftStep]
+ VLD1 {dLeftVal[2]},[pSrcLeft],step ;// pSrcLeft[2*leftStep]
+ VLD1 {dLeftVal[3]},[pTmp],step ;// pSrcLeft[3*leftStep]
+ VLD1 {dLeftVal[4]},[pSrcLeft],step ;// pSrcLeft[4*leftStep]
+ VLD1 {dLeftVal[5]},[pTmp],step ;// pSrcLeft[5*leftStep]
+ VLD1 {dLeftVal[6]},[pSrcLeft],step ;// pSrcLeft[6*leftStep]
+ VLD1 {dLeftVal[7]},[pTmp] ;// pSrcLeft[7*leftStep]
+
+
+ VREV64 dRevAboveVal,dAboveVal ;// Reverse order of bytes = pSrcAbove[0:1:2:3:4:5:6:7]
+ VSUBL qAbove7minus0,dRevAboveVal,dAboveLeftVal ;// qAbove7minus0[0] = pSrcAbove[7] - pSrcAboveLeft[0]
+ VSHR dRevAboveValU64,dRevAboveValU64,#8 ;// pSrcAbove[X:0:1:2:3:4:5:6]
+ VSUBL qAboveDiff,dRevAboveVal,dAboveVal ;// pSrcAbove[6] - pSrcAbove[0]
+ ;// pSrcAbove[5] - pSrcAbove[1]
+ ;// pSrcAbove[4] - pSrcAbove[2]
+
+ VREV64 dRevLeftVal,dLeftVal ;// Reverse order of bytes = pSrcLeft[0:1:2:3:4:5:6:7]
+ VSUBL qLeft7minus0,dRevLeftVal,dAboveLeftVal ;// qAbove7minus0[0] = pSrcLeft[7] - pSrcAboveLeft[0]
+ VSHR dRevLeftValU64,dRevLeftValU64,#8 ;// pSrcLeft[X:0:1:2:3:4:5:6]
+ VSUBL qLeftDiff,dRevLeftVal,dLeftVal ;// pSrcLeft[6] - pSrcLeft[0]
+ ;// pSrcLeft[5] - pSrcLeft[1]
+ ;// pSrcLeft[4] - pSrcLeft[2]
+
+ LDR pMultiplierTable,=armVCM4P10_MultiplierTableChroma8x8 ;// Used to calculate Hval & Vval
+ VSHL dAboveDiff0U64,dAboveDiff0U64,#16
+ VEXT dDiffAboveU8,dAboveDiff0U8,dAbove7minus0U8,#2 ;// pSrcAbove[ 7-0 | 4-2 | 5-1 | 6-0 ]
+ VLD1 dMultiplier,[pMultiplierTable]!
+ VSHL dLeftDiff0U64,dLeftDiff0U64,#16
+ VEXT dDiffLeftU8,dLeftDiff0U8,dLeft7minus0U8,#2 ;// pSrcLeft[ 7-0 | 4-2 | 5-1 | 6-0 ]
+
+
+ VMUL dHorPred,dDiffAboveS16,dMultiplier ;// pSrcAbove[ 4*(7-0) | 1*(4-2) | 2*(5-1) | 3*(6-0) ]
+ VMUL dVerPred,dDiffLeftS16,dMultiplier
+ VPADD dHVValS16,dHorPred,dVerPred
+
+
+ VPADDL dHVValS32,dHVValS16 ;// [V|H] in 32 bits each
+ VSHL dHVTempS32,dHVValS32,#4 ;// 17*H = 16*H + H = (H<<4)+H
+ VADD dHVValS32,dHVValS32,dHVTempS32 ;// [ 17*V | 17*H ]in 32 bits each
+ VLD1 {dMultiplier0,dMultiplier1},[pMultiplierTable] ;// qMultiplier = [ 4|3|2|1|0|-1|-2|-3 ]
+ VRSHR dHVValS32,dHVValS32,#5 ;// [c|b] in 16bits each
+ VADDL qA,dAboveVal,dLeftVal
+ VDUP qA,qA[7]
+ VSHL qA,qA,#4 ;// [a|a|a|a|a|a|a|a]
+ VDUP qB,dHVValS16[0] ;// [b|b|b|b|b|b|b|b]
+ VDUP qC,dHVValS16[2] ;// [c|c|c|c|c|c|c|c]
+
+
+ VMUL qB,qB,qMultiplier
+ VMUL qC,qC,qMultiplier
+ VADD qB,qB,qA
+
+ VDUP qC0,qC[0]
+ VDUP qC1,qC[1]
+ VDUP qC2,qC[2]
+ VDUP qC3,qC[3]
+ VDUP qC4,qC[4]
+ VDUP qC5,qC[5]
+ VDUP qC6,qC[6]
+ VDUP qC7,qC[7]
+
+ VADD qSum0,qB,qC0
+ VADD qSum1,qB,qC1
+ VADD qSum2,qB,qC2
+ VADD qSum3,qB,qC3
+ VADD qSum4,qB,qC4
+ VADD qSum5,qB,qC5
+ VADD qSum6,qB,qC6
+ VADD qSum7,qB,qC7
+
+ VQRSHRUN dSum0,qSum0,#5 ;// (OMX_U8)armClip(0,255,(Sum+16)>>5)
+ VQRSHRUN dSum1,qSum1,#5
+ VQRSHRUN dSum2,qSum2,#5
+ VQRSHRUN dSum3,qSum3,#5
+ VQRSHRUN dSum4,qSum4,#5
+ VQRSHRUN dSum5,qSum5,#5
+ VQRSHRUN dSum6,qSum6,#5
+ VQRSHRUN dSum7,qSum7,#5
+
+DCChroma8x8PlaneStore
+ ADD pTmp, pDst, dstStep
+ ADD step, dstStep, dstStep
+
+ VST1 dSum0,[pDst],step ;// pDst[0*dstStep+x] :0<= x <= 7
+ VST1 dSum1,[pTmp],step ;// pDst[1*dstStep+x] :0<= x <= 7
+ VST1 dSum2,[pDst],step ;// pDst[2*dstStep+x] :0<= x <= 7
+ VST1 dSum3,[pTmp],step ;// pDst[3*dstStep+x] :0<= x <= 7
+ VST1 dSum4,[pDst],step ;// pDst[4*dstStep+x] :0<= x <= 7
+ VST1 dSum5,[pTmp],step ;// pDst[5*dstStep+x] :0<= x <= 7
+ VST1 dSum6,[pDst],step ;// pDst[6*dstStep+x] :0<= x <= 7
+ VST1 dSum7,[pTmp] ;// pDst[7*dstStep+x] :0<= x <= 7
+
+ MOV return, #OMX_Sts_NoErr
+ M_END
+
+ ENDIF ;// CortexA8
+
+ END
+;//-----------------------------------------------------------------------------------------------
+;// omxVCM4P10_PredictIntraChroma_8x8 ends
+;//-----------------------------------------------------------------------------------------------
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
new file mode 100755
index 0000000..e9c0eee
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16_s.s
@@ -0,0 +1,424 @@
+;//
+;//
+;// File Name: omxVCM4P10_PredictIntra_16x16_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+
+;//-------------------------------------------------------
+;// This table for implementing switch case of C in asm by
+;// the mehtod of two levels of indexing.
+;//-------------------------------------------------------
+
+ M_TABLE armVCM4P10_pIndexTable16x16
+ DCD OMX_VC_16X16_VERT, OMX_VC_16X16_HOR
+ DCD OMX_VC_16X16_DC, OMX_VC_16X16_PLANE
+
+
+ IF CortexA8
+
+ M_TABLE armVCM4P10_MultiplierTable16x16,1
+ DCW 7, 6, 5, 4, 3, 2, 1, 8
+ DCW 0, 1, 2, 3, 4, 5, 6, 7
+ DCW 8, 9, 10, 11, 12, 13, 14, 15
+
+;//--------------------------------------------
+;// Constants
+;//--------------------------------------------
+BLK_SIZE EQU 0x10
+MUL_CONST0 EQU 0x01010101
+MUL_CONST1 EQU 0x00060004
+MUL_CONST2 EQU 0x00070005
+MUL_CONST3 EQU 0x00030001
+MASK_CONST EQU 0x00FF00FF
+
+;//--------------------------------------------
+;// Scratch variable
+;//--------------------------------------------
+y RN 12
+pc RN 15
+
+return RN 0
+pTable RN 9
+count RN 11
+pMultTable RN 9
+; ----------------------------------------------
+; Neon registers
+; ----------------------------------------------
+qAbove QN Q0.U8
+qLeft QN Q1.U8
+qSum8 QN Q0.U16
+dSum80 DN D0.U16
+dSum81 DN D1.U16
+dSum4 DN D0.U16
+dSum2 DN D0.U32
+dSum1 DN D0.U64
+qOut QN Q3.U8
+dSumLeft DN D6.U64
+dSumAbove DN D7.U64
+dSum DN D8.U64
+dSum0 DN D8.U8[0]
+
+qH QN Q11.S32
+qV QN Q12.S32
+qA QN Q11.S16
+qB QN Q6.S16
+qC QN Q7.S16
+
+qB0 QN Q5.S16
+qB1 QN Q6.S16
+dA1 DN D23.S16
+
+dH0 DN D22.S32
+dH1 DN D23.S32
+dV0 DN D24.S32
+dV1 DN D25.S32
+
+qHV QN Q11.S64
+qHV0 QN Q11.S32
+qHV1 QN Q12.S64
+
+dHV00 DN D22.S32
+dHV01 DN D23.S32
+
+dHV0 DN D22.S16[0]
+dHV1 DN D23.S16[0]
+dHV10 DN D24.S64
+dHV11 DN D25.S64
+
+qSum0 QN Q0.S16
+qSum1 QN Q1.S16
+
+dOut0 DN D6.U8
+dOut1 DN D7.U8
+
+dLeft0 DN D2.U8
+dLeft1 DN D3.U8
+qConst QN Q13.S16
+
+dAbove0 DN D0.U8
+dAbove1 DN D1.U8
+
+dRevLeft64 DN D12.U64
+dRevLeft DN D12.U8
+dRevAbove64 DN D5.U64
+dRevAbove DN D5.U8
+qLeftDiff QN Q8.S16
+dLeftDiff1 DN D17.S16
+dLeftDiff64 DN D17.S64
+qDiffLeft QN Q8.S16
+qDiffAbove QN Q4.S16
+dAboveDiff1 DN D9.S16
+dAboveDiff64 DN D9.S64
+qAboveDiff QN Q4.S16
+
+dAboveLeft DN D4.U8
+
+dDiffLeft0 DN D16.S16
+dDiffLeft1 DN D17.S16
+dDiffAbove0 DN D8.S16
+dDiffAbove1 DN D9.S16
+
+qLeft15minus0 QN Q7.S16
+dLeft15minus0 DN D14.S16
+qAbove15minus0 QN Q3.S16
+dAbove15minus0 DN D6.S16
+
+qMultiplier QN Q10.S16
+qMultiplier0 QN Q10.S16
+qMultiplier1 QN Q12.S16
+dMultiplier0 DN D20.S16
+dMultiplier1 DN D21.S16
+
+dBPlusCMult7 DN D1.S64
+dBPlusCMult7S16 DN D1.S16
+
+qTmp QN Q0.U8
+
+;//--------------------------------------------
+;// Declare input registers
+;//--------------------------------------------
+pSrcLeft RN 0 ;// input pointer
+pSrcAbove RN 1 ;// input pointer
+pSrcAboveLeft RN 2 ;// input pointer
+pDst RN 3 ;// output pointer
+leftStep RN 4 ;// input variable
+dstStep RN 5 ;// input variable
+predMode RN 6 ;// input variable
+availability RN 7 ;// input variable
+
+pTmp RN 8
+step RN 10
+pTmp2 RN 11
+
+;//-----------------------------------------------------------------------------------------------
+;// omxVCM4P10_PredictIntra_16x16 starts
+;//-----------------------------------------------------------------------------------------------
+
+ ;// Write function header
+ M_START omxVCM4P10_PredictIntra_16x16, r11, d15
+
+ ;// Define stack arguments
+ M_ARG LeftStep, 4
+ M_ARG DstStep, 4
+ M_ARG PredMode, 4
+ M_ARG Availability, 4
+
+ ;// M_STALL ARM1136JS=4
+
+ LDR pTable,=armVCM4P10_pIndexTable16x16 ;// Load index table for switch case
+
+ ;// Load argument from the stack
+ M_LDR predMode, PredMode ;// Arg predMode loaded from stack to reg
+ M_LDR leftStep, LeftStep ;// Arg leftStep loaded from stack to reg
+ M_LDR dstStep, DstStep ;// Arg dstStep loaded from stack to reg
+ M_LDR availability, Availability ;// Arg availability loaded from stack to reg
+
+ MOV y, #BLK_SIZE ;// Outer Loop Count
+ LDR pc, [pTable, predMode, LSL #2] ;// Branch to the case based on preMode
+
+OMX_VC_16X16_VERT
+ VLD1 qAbove, [pSrcAbove]
+ ADD pTmp, pDst, dstStep
+ ADD step, dstStep, dstStep
+ VST1 qAbove, [pDst], step
+ VST1 qAbove, [pTmp], step
+ VST1 qAbove, [pDst], step
+ VST1 qAbove, [pTmp], step
+ VST1 qAbove, [pDst], step
+ VST1 qAbove, [pTmp], step
+ VST1 qAbove, [pDst], step
+ VST1 qAbove, [pTmp], step
+ VST1 qAbove, [pDst], step
+ VST1 qAbove, [pTmp], step
+ VST1 qAbove, [pDst], step
+ VST1 qAbove, [pTmp], step
+ VST1 qAbove, [pDst], step
+ VST1 qAbove, [pTmp], step
+ VST1 qAbove, [pDst]
+ VST1 qAbove, [pTmp]
+ MOV return, #OMX_Sts_NoErr ;// returnNoError
+ M_EXIT
+
+OMX_VC_16X16_HOR
+ ADD pTmp, pSrcLeft, leftStep
+ ADD leftStep, leftStep, leftStep
+ ADD pTmp2, pDst, dstStep
+ ADD dstStep, dstStep, dstStep
+LoopHor
+ VLD1 {qLeft[]}, [pSrcLeft], leftStep
+ VLD1 {qTmp[]}, [pTmp], leftStep
+ SUBS y, y, #8
+ VST1 qLeft, [pDst], dstStep
+ VST1 qTmp, [pTmp2], dstStep
+ VLD1 {qLeft[]}, [pSrcLeft], leftStep
+ VLD1 {qTmp[]}, [pTmp], leftStep
+ VST1 qLeft, [pDst], dstStep
+ VST1 qTmp, [pTmp2], dstStep
+ VLD1 {qLeft[]}, [pSrcLeft], leftStep
+ VLD1 {qTmp[]}, [pTmp], leftStep
+ VST1 qLeft, [pDst], dstStep
+ VST1 qTmp, [pTmp2], dstStep
+ VLD1 {qLeft[]}, [pSrcLeft], leftStep
+ VLD1 {qTmp[]}, [pTmp], leftStep
+ VST1 qLeft, [pDst], dstStep
+ VST1 qTmp, [pTmp2], dstStep
+
+ BNE LoopHor ;// Loop for 16 times
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+OMX_VC_16X16_DC
+ MOV count, #0 ;// count = 0
+ TST availability, #OMX_VC_LEFT
+ BEQ UpperOrNoneAvailable ;// Jump to Upper if not left
+
+ ADD pTmp, pSrcLeft, leftStep
+ ADD step, leftStep, leftStep
+
+ VLD1 {qLeft[0]}, [pSrcLeft],step
+ VLD1 {qLeft[1]}, [pTmp],step
+ VLD1 {qLeft[2]}, [pSrcLeft],step
+ VLD1 {qLeft[3]}, [pTmp],step
+ VLD1 {qLeft[4]}, [pSrcLeft],step
+ VLD1 {qLeft[5]}, [pTmp],step
+ VLD1 {qLeft[6]}, [pSrcLeft],step
+ VLD1 {qLeft[7]}, [pTmp],step
+ VLD1 {qLeft[8]}, [pSrcLeft],step
+ VLD1 {qLeft[9]}, [pTmp],step
+ VLD1 {qLeft[10]},[pSrcLeft],step
+ VLD1 {qLeft[11]},[pTmp],step
+ VLD1 {qLeft[12]},[pSrcLeft],step
+ VLD1 {qLeft[13]},[pTmp],step
+ VLD1 {qLeft[14]},[pSrcLeft],step
+ VLD1 {qLeft[15]},[pTmp]
+
+ VPADDL qSum8, qLeft
+ ADD count, count, #1
+ VPADD dSum4, dSum80, dSum81
+ VPADDL dSum2, dSum4
+ VPADDL dSumLeft, dSum2
+ VRSHR dSum, dSumLeft, #4
+
+UpperOrNoneAvailable
+ TST availability, #OMX_VC_UPPER ;// if(availability & #OMX_VC_UPPER)
+ BEQ BothOrNoneAvailable ;// Jump to Left if not upper
+ VLD1 qAbove, [pSrcAbove]
+ ADD count, count, #1 ;// if upper inc count by 1
+ VPADDL qSum8, qAbove
+ VPADD dSum4, dSum80, dSum81
+ VPADDL dSum2, dSum4
+ VPADDL dSumAbove, dSum2
+ VRSHR dSum, dSumAbove, #4
+
+BothOrNoneAvailable
+ CMP count, #2 ;// check if both available
+ BNE NoneAvailable
+ VADD dSum, dSumAbove, dSumLeft
+ VRSHR dSum, dSum, #5
+
+
+NoneAvailable
+ VDUP qOut, dSum0
+ CMP count, #0 ;// check if none available
+ ADD pTmp, pDst, dstStep
+ ADD step, dstStep, dstStep
+ BNE LoopDC
+ VMOV qOut, #128
+LoopDC
+ VST1 qOut, [pDst], step
+ VST1 qOut, [pTmp], step
+ VST1 qOut, [pDst], step
+ VST1 qOut, [pTmp], step
+ VST1 qOut, [pDst], step
+ VST1 qOut, [pTmp], step
+ VST1 qOut, [pDst], step
+ VST1 qOut, [pTmp], step
+ VST1 qOut, [pDst], step
+ VST1 qOut, [pTmp], step
+ VST1 qOut, [pDst], step
+ VST1 qOut, [pTmp], step
+ VST1 qOut, [pDst], step
+ VST1 qOut, [pTmp], step
+ VST1 qOut, [pDst], step
+ VST1 qOut, [pTmp], step
+ MOV return, #OMX_Sts_NoErr
+ M_EXIT
+
+OMX_VC_16X16_PLANE
+ LDR pMultTable, =armVCM4P10_MultiplierTable16x16
+ VLD1 qAbove, [pSrcAbove] ;// pSrcAbove[x] :0<= x <= 7
+ VLD1 dAboveLeft[0],[pSrcAboveLeft]
+ ADD pTmp, pSrcLeft, leftStep
+ ADD step, leftStep, leftStep
+ VLD1 {qLeft[0]}, [pSrcLeft],step
+ VLD1 {qLeft[1]}, [pTmp],step
+ VLD1 {qLeft[2]}, [pSrcLeft],step
+ VLD1 {qLeft[3]}, [pTmp],step
+ VLD1 {qLeft[4]}, [pSrcLeft],step
+ VLD1 {qLeft[5]}, [pTmp],step
+ VLD1 {qLeft[6]}, [pSrcLeft],step
+ VLD1 {qLeft[7]}, [pTmp],step
+ VLD1 {qLeft[8]}, [pSrcLeft],step
+ VLD1 {qLeft[9]}, [pTmp],step
+ VLD1 {qLeft[10]}, [pSrcLeft],step
+ VLD1 {qLeft[11]}, [pTmp],step
+ VLD1 {qLeft[12]}, [pSrcLeft],step
+ VLD1 {qLeft[13]}, [pTmp],step
+ VLD1 {qLeft[14]}, [pSrcLeft],step
+ VLD1 {qLeft[15]}, [pTmp]
+
+ VREV64 dRevAbove, dAbove1 ;// pSrcAbove[15:14:13:12:11:10:9:8]
+ VSUBL qAbove15minus0, dRevAbove, dAboveLeft ;// qAbove7minus0[0] = pSrcAbove[15] - pSrcAboveLeft[0]
+ VSHR dRevAbove64, dRevAbove64, #8 ;// pSrcAbove[14:13:12:11:10:9:8:X]
+ VSUBL qAboveDiff, dRevAbove, dAbove0
+
+ VSHL dAboveDiff64, dAboveDiff64, #16
+ VEXT dDiffAbove1, dAboveDiff1, dAbove15minus0, #1
+
+ VREV64 dRevLeft,dLeft1 ;// pSrcLeft[15:14:13:12:11:10:9:8]
+ VSUBL qLeft15minus0,dRevLeft, dAboveLeft ;// qAbove7minus0[0] = pSrcLeft[7] - pSrcAboveLeft[0]
+ VSHR dRevLeft64, dRevLeft64, #8 ;// pSrcLeft[14:13:12:11:10:9:8:X]
+ VSUBL qLeftDiff,dRevLeft, dLeft0
+
+ ;// Multiplier = [8|1|2|...|6|7]
+ VLD1 qMultiplier, [pMultTable]!
+
+ VSHL dLeftDiff64, dLeftDiff64, #16
+ VEXT dDiffLeft1, dLeftDiff1, dLeft15minus0, #1
+
+ VMULL qH,dDiffAbove0, dMultiplier0
+ VMULL qV,dDiffLeft0, dMultiplier0
+ VMLAL qH,dDiffAbove1, dMultiplier1
+ VMLAL qV,dDiffLeft1, dMultiplier1
+
+ VPADD dHV00,dH1,dH0
+ VPADD dHV01,dV1,dV0
+ VPADDL qHV, qHV0
+ VSHL qHV1,qHV,#2
+ VADD qHV,qHV,qHV1
+
+ ;// HV = [c = ((5*V+32)>>6) | b = ((5*H+32)>>6)]
+ VRSHR qHV,qHV,#6
+
+ ;// HV1 = [c*7|b*7]
+ VSHL qHV1,qHV,#3
+ VSUB qHV1,qHV1,qHV
+
+ ;// Multiplier1 = [0|1|2|...|7]
+ VLD1 qMultiplier0, [pMultTable]!
+ VDUP qB, dHV0
+ VDUP qC, dHV1
+
+ VADDL qA,dAbove1,dLeft1
+ VSHL qA,qA, #4
+ VDUP qA,dA1[3]
+ VADD dBPlusCMult7, dHV10, dHV11
+
+ ;// Multiplier1 = [8|9|10|...|15]
+ VLD1 qMultiplier1, [pMultTable]
+ ;// Const = a - 7*(b+c)
+ VDUP qConst, dBPlusCMult7S16[0]
+ VSUB qConst, qA, qConst
+
+ ;// B0 = [0*b|1*b|2*b|3*b|......|7*b]
+ VMUL qB0,qB,qMultiplier0
+
+ ;// B0 = [8*b|9*b|10*b|11*b|....|15*b]
+ VMUL qB1,qB,qMultiplier1
+
+ VADD qSum0, qB0, qConst
+ VADD qSum1, qB1, qConst
+
+ ;// Loops for 16 times
+LoopPlane
+ ;// (b*x + c*y + C)>>5
+ VQRSHRUN dOut0, qSum0,#5
+ VQRSHRUN dOut1, qSum1,#5
+ SUBS y, y, #1
+ VST1 qOut,[pDst],dstStep
+ VADD qSum0,qSum0,qC
+ VADD qSum1,qSum1,qC
+ BNE LoopPlane
+
+ MOV return, #OMX_Sts_NoErr
+
+ M_END
+
+ ENDIF ;// CortexA8
+
+ END
+;-----------------------------------------------------------------------------------------------
+; omxVCM4P10_PredictIntra_16x16 ends
+;-----------------------------------------------------------------------------------------------
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
new file mode 100755
index 0000000..39eb8a4
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4_s.s
@@ -0,0 +1,531 @@
+;//
+;//
+;// File Name: omxVCM4P10_PredictIntra_4x4_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+;// Define the processor variants supported by this file
+
+ M_VARIANTS CortexA8
+
+;//-------------------------------------------------------
+;// This table for implementing switch case of C in asm by
+;// the mehtod of two levels of indexing.
+;//-------------------------------------------------------
+
+ M_TABLE armVCM4P10_pSwitchTable4x4
+ DCD OMX_VC_4x4_VERT, OMX_VC_4x4_HOR
+ DCD OMX_VC_4x4_DC, OMX_VC_4x4_DIAG_DL
+ DCD OMX_VC_4x4_DIAG_DR, OMX_VC_4x4_VR
+ DCD OMX_VC_4x4_HD, OMX_VC_4x4_VL
+ DCD OMX_VC_4x4_HU
+
+
+ IF CortexA8
+
+;//--------------------------------------------
+;// Scratch variable
+;//--------------------------------------------
+return RN 0
+pTable RN 8
+pc RN 15
+
+;//--------------------------------------------
+;// Declare input registers
+;//--------------------------------------------
+pSrcLeft RN 0 ;// input pointer
+pSrcAbove RN 1 ;// input pointer
+pSrcAboveLeft RN 2 ;// input pointer
+pDst RN 3 ;// output pointer
+leftStep RN 4 ;// input variable
+dstStep RN 5 ;// input variable
+predMode RN 6 ;// input variable
+availability RN 7 ;// input variable
+pDst1 RN 1
+pDst2 RN 4
+pDst3 RN 6
+
+pSrcTmp RN 9
+srcStep RN 10
+pDstTmp RN 11
+dstep RN 12
+
+;//-------------------
+;// Neon registers
+;//-------------------
+
+;// OMX_VC_CHROMA_VERT
+dAboveU32 DN D0.U32
+
+;// OMX_VC_CHROMA_HOR
+dLeftVal0 DN D0.8
+dLeftVal1 DN D1.8
+dLeftVal2 DN D2.8
+dLeftVal3 DN D3.8
+dLeftVal0U32 DN D0.U32
+dLeftVal1U32 DN D1.U32
+dLeftVal2U32 DN D2.U32
+dLeftVal3U32 DN D3.U32
+
+;// OMX_VC_4x4_DC
+dLeftVal DN D0.U8
+dLeftValU32 DN D0.U32
+dSumAboveLeftU16 DN D1.U16
+dSumAboveLeftU32 DN D1.U32
+dSumAboveLeftU64 DN D1.U64
+dSumAboveLeftU8 DN D1.U8
+dSum DN D0.U8
+
+dSumLeftValU16 DN D1.U16
+dSumLeftValU32 DN D1.U32
+dSumLeftValU64 DN D1.U64
+dSumLeftValU8 DN D1.U8
+
+dAboveVal DN D0.U8
+dSumAboveValU16 DN D1.U16
+dSumAboveValU32 DN D1.U32
+dSumAboveValU64 DN D1.U64
+dSumAboveValU8 DN D1.U8
+dConst128U8 DN D0.U8
+
+
+;//OMX_VC_4x4_DIAG_DL
+
+dAbove DN D0.U8
+dU7 DN D2.U8
+dU3 DN D2.U8
+dAbove0 DN D3.U8
+dAbove1 DN D4.U8
+dAbove2 DN D5.U8
+dTmp DN D6.U8
+dTmp0 DN D7.U8
+dTmp1 DN D8.U8
+dTmp2 DN D9.U8
+dTmp3 DN D10.U8
+dTmpU32 DN D6.U32
+
+
+;//OMX_VC_4x4_DIAG_DR
+dLeft DN D1.U8
+dUL DN D2.U8
+
+;//OMX_VC_4x4_VR
+dLeft0 DN D1.U8
+dLeft1 DN D2.U8
+dEven0 DN D3.U8
+dEven1 DN D4.U8
+dEven2 DN D5.U8
+dOdd0 DN D6.U8
+dOdd1 DN D11.U8
+dOdd2 DN D12.U8
+dTmp3U32 DN D10.U32
+dTmp2U32 DN D9.U32
+
+
+;//OMX_VC_4x4_HD
+dTmp1U64 DN D8.U64
+dTmp0U64 DN D7.U64
+dTmpU64 DN D6.U64
+dTmpU32 DN D6.U32
+dTmp1U32 DN D8.U32
+
+;//OMX_VC_4x4_HU
+dL3 DN D2.U8
+dLeftHU0 DN D3.U8
+dLeftHU1 DN D4.U8
+dLeftHU2 DN D5.U8
+dTmp0U32 DN D7.U32
+
+
+
+
+;//-----------------------------------------------------------------------------------------------
+;// omxVCM4P10_PredictIntra_4x4 starts
+;//-----------------------------------------------------------------------------------------------
+
+ ;// Write function header
+ M_START omxVCM4P10_PredictIntra_4x4, r12,d12
+
+ ;// Define stack arguments
+ M_ARG LeftStep, 4
+ M_ARG DstStep, 4
+ M_ARG PredMode, 4
+ M_ARG Availability, 4
+
+
+ LDR pTable,=armVCM4P10_pSwitchTable4x4 ;// Load index table for switch case
+
+ ;// Load argument from the stack
+ M_LDRD predMode,availability,PredMode ;// Arg predMode & availability loaded from stack to reg
+ M_LDRD leftStep,dstStep,LeftStep ;// Arg leftStep & dstStep loaded from stack to reg
+
+
+ LDR pc, [pTable, predMode, LSL #2] ;// Branch to the case based on preMode
+
+
+OMX_VC_4x4_HOR
+
+ ADD pSrcTmp, pSrcLeft, leftStep
+ ADD srcStep, leftStep, leftStep
+ ;// Load Left Edge
+ VLD1 {dLeftVal0[]},[pSrcLeft],srcStep ;// pSrcLeft[0*leftStep]
+ VLD1 {dLeftVal1[]},[pSrcTmp],srcStep ;// pSrcLeft[1*leftStep]
+ VLD1 {dLeftVal2[]},[pSrcLeft] ;// pSrcLeft[2*leftStep]
+ VLD1 {dLeftVal3[]},[pSrcTmp] ;// pSrcLeft[3*leftStep]
+
+ ADD pDstTmp, pDst, dstStep
+ ADD dstep, dstStep, dstStep
+
+ VST1 dLeftVal0U32[0],[pDst],dstep ;// pDst[0*dstStep+x] :0<= x <= 7
+ VST1 dLeftVal1U32[0],[pDstTmp],dstep ;// pDst[1*dstStep+x] :0<= x <= 7
+ VST1 dLeftVal2U32[0],[pDst] ;// pDst[2*dstStep+x] :0<= x <= 7
+ VST1 dLeftVal3U32[0],[pDstTmp] ;// pDst[3*dstStep+x] :0<= x <= 7
+
+ B ExitPredict4x4 ;// Branch to exit code
+
+OMX_VC_4x4_VERT
+
+ ;// Load Upper Edge
+ VLD1 dAboveU32[0],[pSrcAbove]
+ ADD pDstTmp, pDst, dstStep
+ ADD dstep, dstStep, dstStep
+
+DCPredict4x4VertStore
+
+ VST1 dAboveU32[0],[pDst],dstep
+ VST1 dAboveU32[0],[pDstTmp],dstep
+ VST1 dAboveU32[0],[pDst]
+ VST1 dAboveU32[0],[pDstTmp]
+
+ B ExitPredict4x4 ;// Branch to exit code
+
+OMX_VC_4x4_DC
+
+
+ TST availability, #OMX_VC_LEFT
+ BEQ DCPredict4x4LeftNotAvailable
+
+ ADD pSrcTmp, pSrcLeft, leftStep
+ ADD srcStep, leftStep, leftStep
+ ;// Load Left Edge
+ VLD1 {dLeftVal[0]},[pSrcLeft],srcStep ;// pSrcLeft[0*leftStep]
+ VLD1 {dLeftVal[1]},[pSrcTmp],srcStep ;// pSrcLeft[1*leftStep]
+ VLD1 {dLeftVal[2]},[pSrcLeft] ;// pSrcLeft[2*leftStep]
+ VLD1 {dLeftVal[3]},[pSrcTmp] ;// pSrcLeft[3*leftStep]
+
+ TST availability, #OMX_VC_UPPER
+ BEQ DCPredict4x4LeftOnlyAvailable
+
+ ;// Load Upper Edge also
+ VLD1 dLeftValU32[1],[pSrcAbove] ;// pSrcAbove[0 to 3]
+ MOV return, #OMX_Sts_NoErr
+
+ VPADDL dSumAboveLeftU16, dLeftVal ;// [pSrcAbove[2+3 | 0+1] | pSrcLeft[2+3 | 0+1]]
+ VPADDL dSumAboveLeftU32, dSumAboveLeftU16 ;// [pSrcAbove[2+3+0+1] | pSrcLeft[2+3+0+1]]
+ VPADDL dSumAboveLeftU64, dSumAboveLeftU32 ;// [pSrcAbove[2+3+0+1] + pSrcLeft[2+3+0+1]]
+ VRSHR dSumAboveLeftU64,dSumAboveLeftU64,#3 ;// Sum = (Sum + 4) >> 3
+ ADD pDstTmp, pDst, dstStep
+ ADD dstep, dstStep, dstStep
+ VDUP dSum,dSumAboveLeftU8[0]
+
+ B DCPredict4x4VertStore
+
+DCPredict4x4LeftOnlyAvailable
+
+ MOV return, #OMX_Sts_NoErr ;// returnNoError
+
+ VPADDL dSumLeftValU16, dLeftVal ;// [ XX | pSrcLeft[2+3 | 0+1]]
+ VPADDL dSumLeftValU32, dSumLeftValU16 ;// [ XXXX | pSrcLeft[2+3+0+1]]
+
+ VRSHR dSumLeftValU32,dSumLeftValU32,#2 ;// Sum = (Sum + 2) >> 2
+ ADD pDstTmp, pDst, dstStep
+ ADD dstep, dstStep, dstStep
+ VDUP dSum,dSumLeftValU8[0]
+
+ B DCPredict4x4VertStore
+
+DCPredict4x4LeftNotAvailable
+
+ TST availability, #OMX_VC_UPPER
+ BEQ DCPredict4x4NoneAvailable
+
+ ;// Load Upper Edge
+ VLD1 dAboveU32[0],[pSrcAbove] ;// pSrcAbove[0 to 3]
+ MOV return, #OMX_Sts_NoErr
+
+ VPADDL dSumAboveValU16, dAboveVal ;// [ XX | pSrcAbove[2+3 | 0+1]]
+ VPADDL dSumAboveValU32, dSumAboveValU16 ;// [ XXXX | pSrcAbove[2+3+0+1]]
+
+ VRSHR dSumAboveValU32,dSumAboveValU32,#2 ;// Sum = (Sum + 2) >> 2
+ ADD pDstTmp, pDst, dstStep
+ ADD dstep, dstStep, dstStep
+ VDUP dSum,dSumAboveValU8[0]
+
+ B DCPredict4x4VertStore
+
+DCPredict4x4NoneAvailable
+
+ VMOV dConst128U8,#0x80 ;// 0x8080808080808080 if(count == 0)
+ MOV return, #OMX_Sts_NoErr
+
+ ADD pDstTmp, pDst, dstStep
+ ADD dstep, dstStep, dstStep
+ B DCPredict4x4VertStore
+
+
+
+OMX_VC_4x4_DIAG_DL
+
+ TST availability, #OMX_VC_UPPER_RIGHT
+ BEQ DiagDLUpperRightNotAvailable
+
+ VLD1 dAbove0,[pSrcAbove] ;// [U7|U6|U5|U4|U3|U2|U1|U0]
+ VDUP dU7, dAbove0[7] ;// [U7|U7|U7|U7|U7|U7|U7|U7]
+ VEXT dAbove1, dAbove0, dU7, #1 ;// [U7|U7|U6|U5|U4|U3|U2|U1]
+ VEXT dAbove2, dAbove0, dU7, #2 ;// [U7|U7|U7|U6|U5|U4|U3|U2]
+ B DiagDLPredict4x4Store
+
+DiagDLUpperRightNotAvailable
+ VLD1 dAboveU32[1],[pSrcAbove] ;// [U3|U2|U1|U0|-|-|-|-]
+ VDUP dU3, dAbove[7] ;// [U3 U3 U3 U3 U3 U3 U3 U3]
+
+ VEXT dAbove0, dAbove, dU3, #4 ;// [U3 U3 U3 U3 U3 U2 U1 U0]
+ VEXT dAbove1, dAbove, dU3, #5 ;// [U3 U3 U3 U3 U3 U3 U2 U1]
+ VEXT dAbove2, dAbove, dU3, #6 ;// [U3 U3 U3 U3 U3 U3 U3 U2]
+
+DiagDLPredict4x4Store
+
+ VHADD dTmp, dAbove0, dAbove2
+ VRHADD dTmp, dTmp, dAbove1 ;// (a+2*b+c+2)>>2
+
+
+ VST1 dTmpU32[0],[pDst],dstStep
+ VEXT dTmp,dTmp,dTmp,#1
+ VST1 dTmpU32[0],[pDst],dstStep
+ VEXT dTmp,dTmp,dTmp,#1
+ VST1 dTmpU32[0],[pDst],dstStep
+ VEXT dTmp,dTmp,dTmp,#1
+ VST1 dTmpU32[0],[pDst]
+
+ B ExitPredict4x4 ;// Branch to exit code
+
+
+OMX_VC_4x4_DIAG_DR
+
+
+ ;// Load U0,U1,U2,U3
+
+ VLD1 dAboveU32[0],[pSrcAbove] ;// [X|X|X|X|U3|U2|U1|U0]
+
+ ;// Load UL,L0,L1,L2,L3 ;// dLeft = [UL|L0|L1|L2|L3|X|X|X]
+ VLD1 {dLeft[7]},[pSrcAboveLeft]
+ ADD pSrcTmp, pSrcLeft, leftStep
+ ADD srcStep, leftStep, leftStep
+ ADD pDst1,pDst,dstStep
+
+ VLD1 {dLeft[6]},[pSrcLeft],srcStep ;// pSrcLeft[0*leftStep]
+ VLD1 {dLeft[5]},[pSrcTmp],srcStep ;// pSrcLeft[1*leftStep]
+ VLD1 {dLeft[4]},[pSrcLeft] ;// pSrcLeft[2*leftStep]
+ VLD1 {dLeft[3]},[pSrcTmp] ;// pSrcLeft[3*leftStep]
+
+
+ VEXT dAbove0,dLeft,dAbove,#3 ;// [U2|U1|U0|UL|L0|L1|L2|L3]
+ ADD pDst2,pDst1,dstStep
+ VEXT dAbove1,dLeft,dAbove,#4 ;// [U3|U2|U1|U0|UL|L0|L1|L2]
+ ADD pDst3,pDst2,dstStep
+ VEXT dAbove2,dLeft,dAbove,#5 ;// [ X|U3|U2|U1|U0|UL|L0|L1]
+
+ VHADD dTmp, dAbove0, dAbove2
+ VRHADD dTmp, dTmp, dAbove1 ;// (a+2*b+c+2)>>2
+
+
+ VST1 dTmpU32[0],[pDst3] ;// Store pTmp[0],[1],[2],[3] @ pDst3
+ VEXT dTmp,dTmp,dTmp,#1
+ VST1 dTmpU32[0],[pDst2] ;// Store pTmp[1],[2],[3],[4] @ pDst2
+ VEXT dTmp,dTmp,dTmp,#1
+ VST1 dTmpU32[0],[pDst1] ;// Store pTmp[2],[3],[4],[5] @ pDst1
+ VEXT dTmp,dTmp,dTmp,#1
+ VST1 dTmpU32[0],[pDst] ;// Store pTmp[3],[4],[5],[6] @ pDst
+
+ B ExitPredict4x4 ;// Branch to exit code
+
+OMX_VC_4x4_VR
+
+
+ ;// Load UL,U0,U1,U2,U3
+ VLD1 dAboveU32[0],[pSrcAbove]
+ VLD1 dAbove[7],[pSrcAboveLeft] ;// [UL|X|X|X|U3|U2|U1|U0]
+
+ ;// Load L0,L1,L2 ;// dLeft0 = [L0|L2|X|X|X|X|X|X]
+ ;// dLeft1 = [L1| X|X|X|X|X|X|X]
+ VLD1 {dLeft0[7]},[pSrcLeft],leftStep ;// pSrcLeft[0*leftStep]
+ VLD1 {dLeft1[7]},[pSrcLeft],leftStep ;// pSrcLeft[1*leftStep]
+ VLD1 {dLeft0[6]},[pSrcLeft] ;// pSrcLeft[2*leftStep]
+
+
+ VEXT dOdd2,dAbove,dAbove,#7 ;// [ x x x U3 U2 U1 U0 UL ]
+ VEXT dEven0,dLeft0,dOdd2,#6 ;// [ x x x U1 U0 UL L0 L2 ]
+ VEXT dEven1,dLeft1,dOdd2,#7 ;// [ x x x U2 U1 U0 UL L1 ]
+ VEXT dEven2,dLeft0,dAbove,#7 ;// [ x x x U3 U2 U1 U0 L0 ]
+ VEXT dOdd0,dLeft1,dAbove,#7 ;// [ x x x U3 U2 U1 U0 L1 ]
+ VEXT dOdd1,dLeft0,dOdd2,#7 ;// [ x x x U2 U1 U0 UL L0 ]
+
+ VHADD dTmp1, dOdd0, dOdd2
+ VRHADD dTmp1, dTmp1, dOdd1 ;// Tmp[ x x x 9 7 5 3 1 ]
+
+ VHADD dTmp0, dEven0, dEven2
+ VRHADD dTmp0, dTmp0, dEven1 ;// Tmp[ x x x 8 6 4 2 0 ]
+
+
+ VEXT dTmp3,dTmp1,dTmp1,#1 ;// Tmp[ x x x x 9 7 5 3 ]
+ ADD pDstTmp, pDst, dstStep
+ ADD dstep, dstStep, dstStep
+ VEXT dTmp2,dTmp0,dTmp0,#1 ;// Tmp[ x x x x 8 6 4 2 ]
+
+
+ VST1 dTmp3U32[0],[pDst],dstep ;// Tmp[9],[7],[5],[3]
+ VST1 dTmp2U32[0],[pDstTmp],dstep ;// Tmp[8],[6],[4],[2]
+ VST1 dTmp1U32[0],[pDst],dstep ;// Tmp[7],[5],[3],[1]
+ VST1 dTmp0U32[0],[pDstTmp] ;// Tmp[6],[4],[2],[0]
+
+ B ExitPredict4x4 ;// Branch to exit code
+
+OMX_VC_4x4_HD
+
+
+ ;// Load U0,U1,U2,U3
+ VLD1 dAbove,[pSrcAbove] ;//dAboveLeftVal = [U7|U6|U5|U4|U3|U2|U1|U0]
+
+ ;// Load UL,L0,L1,L2,L3 ;// dLeft = [UL|L0|L1|L2|L3|X|X|X]
+ VLD1 {dLeft[7]},[pSrcAboveLeft]
+ ADD pSrcTmp, pSrcLeft, leftStep
+ ADD srcStep, leftStep, leftStep
+
+ VLD1 {dLeft[6]},[pSrcLeft],srcStep ;// pSrcLeft[0*leftStep]
+ VLD1 {dLeft[5]},[pSrcTmp],srcStep ;// pSrcLeft[1*leftStep]
+ VLD1 {dLeft[4]},[pSrcLeft] ;// pSrcLeft[2*leftStep]
+ VLD1 {dLeft[3]},[pSrcTmp] ;// pSrcLeft[3*leftStep]
+
+ VEXT dAbove0,dLeft,dAbove,#3 ;// [ U2|U1|U0|UL|L0|L1|L2|L3 ]
+ VEXT dAbove1,dLeft,dAbove,#2 ;// [ U1|U0|UL|L0|L1|L2|L3|X ]
+ VEXT dAbove2,dLeft,dAbove,#1 ;// [ U0|UL|L0|L1|L2|L3|X|X ]
+
+ VHADD dTmp0, dAbove0, dAbove2
+ VRHADD dTmp0, dTmp0, dAbove1 ;// Tmp[ 0 | 1 | 2 | 4 | 6 | 8 | X | X ]
+
+
+ VRHADD dTmp1, dAbove1, dAbove0 ;// (a+b+1)>>1
+ VSHL dTmp1U64,dTmp1U64,#24 ;// Tmp[ 3|5| 7 |9 | X | X | X | X ]
+
+
+ VSHL dTmpU64,dTmp0U64,#16 ;// Tmp[ 2|4|6|8| X | X | X | X ]
+ VZIP dTmp1,dTmp ;// dTmp = [ 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ]
+ VEXT dTmp0,dTmp0,dTmp0,#6 ;// Tmp[ X| X| X| X| X| X| 0 | 1 ]
+ VEXT dTmp1,dTmp,dTmp0,#2 ;// Tmp[ 0 | 1 | 2 | 3 | 4 | 5 | 6 |7 ]
+
+ ADD pDstTmp, pDst, dstStep
+ ADD dstep, dstStep, dstStep
+
+ VST1 dTmp1U32[1],[pDst],dstep ;// Store pTmp[0|1|2|3]
+ VST1 dTmpU32[1],[pDstTmp],dstep ;// Store pTmp[2|3|4|5]
+ VST1 dTmp1U32[0],[pDst] ;// Store pTmp[4|5|6|7]
+ VST1 dTmpU32[0],[pDstTmp] ;// Store pTmp[6|7|8|9]
+
+ B ExitPredict4x4 ;// Branch to exit code
+
+OMX_VC_4x4_VL
+
+
+ TST availability, #OMX_VC_UPPER_RIGHT
+ BEQ DiagVLUpperRightNotAvailable
+
+ VLD1 dAbove0,[pSrcAbove] ;// [U7|U6|U5|U4|U3|U2|U1|U0]
+ VEXT dAbove1,dAbove0,dAbove0,#1 ;// [ X|U7|U6|U5|U4|U3|U2|U1]
+ VEXT dAbove2,dAbove1,dAbove1,#1 ;// [ X| X|U7|U6|U5|U4|U3|U2]
+
+ B DiagVLPredict4x4Store
+
+DiagVLUpperRightNotAvailable
+ VLD1 dAboveU32[1],[pSrcAbove] ;// [U3|U2|U1|U0|-|-|-|-]
+ VDUP dU3, dAbove[7] ;// [U3 U3 U3 U3 U3 U3 U3 U3]
+
+ VEXT dAbove0, dAbove, dU3, #4 ;// [U3 U3 U3 U3 U3 U2 U1 U0]
+ VEXT dAbove1, dAbove, dU3, #5 ;// [U3 U3 U3 U3 U3 U3 U2 U1]
+ VEXT dAbove2, dAbove, dU3, #6 ;// [U3 U3 U3 U3 U3 U3 U3 U2]
+
+DiagVLPredict4x4Store
+
+ VRHADD dTmp0, dAbove1, dAbove0 ;// (a+b+1)>>1
+ ;// Tmp[ X| X| X| 8| 6| 4| 2| 0 ]
+
+ VHADD dTmp3, dAbove0, dAbove2
+ VRHADD dTmp3, dTmp3, dAbove1 ;// (a+2*b+c+2)>>2
+ ;// Tmp[ X| X| X| 9| 7| 5| 3| 1 ]
+
+ VEXT dTmp1,dTmp0,dTmp0,#1 ;// Tmp[ X| X| X| X| 8| 6| 4| 2 ]
+ ADD pDstTmp, pDst, dstStep
+ ADD dstep, dstStep, dstStep
+ VEXT dTmp2,dTmp3,dTmp1,#1 ;// Tmp[ X| X| X| X| 9| 7| 5| 3 ]
+
+ VST1 dTmp0U32[0],[pDst],dstep ;// Tmp[6],[4],[2],[0]
+ VST1 dTmp3U32[0],[pDstTmp],dstep ;// Tmp[7],[5],[3],[1]
+ VST1 dTmp1U32[0],[pDst] ;// Tmp[8],[6],[4],[2]
+ VST1 dTmp2U32[0],[pDstTmp] ;// Tmp[9],[7],[5],[3]
+
+ B ExitPredict4x4 ;// Branch to exit code
+
+OMX_VC_4x4_HU
+ ADD pSrcTmp, pSrcLeft, leftStep
+ ADD srcStep, leftStep, leftStep
+
+ ;// Load Left Edge ;// [L3|L2|L1|L0|X|X|X|X]
+ VLD1 {dLeft[4]},[pSrcLeft],srcStep ;// pSrcLeft[0*leftStep]
+ VLD1 {dLeft[5]},[pSrcTmp],srcStep ;// pSrcLeft[1*leftStep]
+ VLD1 {dLeft[6]},[pSrcLeft] ;// pSrcLeft[2*leftStep]
+ VLD1 {dLeft[7]},[pSrcTmp] ;// pSrcLeft[3*leftStep]
+
+ VDUP dL3,dLeft[7] ;// [L3|L3|L3|L3|L3|L3|L3|L3]
+
+ VEXT dLeftHU0,dLeft,dL3,#4 ;// [L3|L3|L3|L3|L3|L2|L1|L0]
+ VEXT dLeftHU1,dLeft,dL3,#5 ;// [L3|L3|L3|L3|L3|L3|L2|L1]
+ VEXT dLeftHU2,dLeft,dL3,#6 ;// [L3|L3|L3|L3|L3|L3|L3|L2]
+
+ VHADD dTmp0, dLeftHU0, dLeftHU2
+ VRHADD dTmp0, dTmp0, dLeftHU1 ;// Tmp[ L3 | L3 | L3 | L3 | L3 | 5 | 3 | 1 ]
+
+ VRHADD dTmp1, dLeftHU1, dLeftHU0 ;// (a+b+1)>>1
+ ;// Tmp[ L3 | L3 | L3 | L3 | L3 | 4 | 2 | 0 ]
+
+ VZIP dTmp1,dTmp0 ;// dTmp1 = Tmp[7| 6| 5| 4| 3| 2| 1| 0]
+ ;// dTmp0 = [L3|L3|L3|L3|L3|L3|L3|L3]
+
+
+ VST1 dTmp1U32[0],[pDst],dstStep ;// [3|2|1|0]
+ VEXT dTmp1,dTmp1,dTmp1,#2
+ VST1 dTmp1U32[0],[pDst],dstStep ;// [5|4|3|2]
+ VEXT dTmp1,dTmp1,dTmp1,#2
+ VST1 dTmp1U32[0],[pDst],dstStep ;// [7|6|5|4]
+ VST1 dTmp0U32[0],[pDst] ;// [9|8|7|6]
+
+
+ExitPredict4x4
+
+ MOV return, #OMX_Sts_NoErr
+ M_END
+
+ ENDIF ;// CortexA8
+
+ END
+;//-----------------------------------------------------------------------------------------------
+;// omxVCM4P10_PredictIntra_4x4 ends
+;//-----------------------------------------------------------------------------------------------
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
new file mode 100755
index 0000000..e394339
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair_s.s
@@ -0,0 +1,140 @@
+;//
+;//
+;// File Name: omxVCM4P10_TransformDequantChromaDCFromPair_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ IMPORT armVCM4P10_QPDivTable
+ IMPORT armVCM4P10_VMatrixQPModTable
+
+ M_VARIANTS CortexA8
+
+
+
+
+ IF CortexA8
+
+;// ARM Registers
+;//--------------------------------------
+;// Declare input registers
+;//--------------------------------------
+ppSrc RN 0
+pDst RN 1
+QP RN 2
+
+;//--------------------------------
+;// Scratch variable for Unpack2x2
+;//--------------------------------
+pSrc RN 9
+Value RN 4
+Value2 RN 5
+Flag RN 6
+strOffset RN 7
+cstOffset RN 8
+
+;//--------------------------------
+;// Scratch variable
+;//--------------------------------
+r0w0 RN 3
+r0w1 RN 4
+
+c0w0 RN 5
+c1w0 RN 6
+
+return RN 0
+pQPDivTable RN 5
+pQPModTable RN 6
+Shift RN 9
+Scale RN 2
+
+
+
+;// Neon Registers
+
+dZero DN D0.U16
+dInvTrCoeff DN D0.S16
+dScale DN D1.S16
+qDqntCoeff QN Q1.S32
+dDqntCoeff DN D2.S16
+
+
+ ;// Write function header
+ M_START omxVCM4P10_TransformDequantChromaDCFromPair, r9
+
+ LDR pSrc, [ppSrc] ;// Load pSrc
+ VMOV dZero, #0
+ MOV cstOffset, #31 ;// To be used in the loop, to compute offset
+
+ ;//-----------------------------------------------------------------------
+ ;// Firstly, fill all the coefficient values on the <pDst> buffer by zero
+ ;//-----------------------------------------------------------------------
+
+ VST1 dZero,[pDst] ;// pDst[0] = pDst[1] = pDst[2] = pDst[3] = 0
+ LDRB Flag, [pSrc], #1 ;// Preload <Flag> before <unpackLoop>
+
+
+unpackLoop
+ TST Flag, #0x10 ;// Computing (Flag & 0x10)
+ LDRSBNE Value2,[pSrc,#1]
+ LDRBNE Value, [pSrc], #2 ;// Load byte wise to avoid unaligned access
+ AND strOffset, cstOffset, Flag, LSL #1 ;// strOffset = (Flag & 15) < 1;
+ LDRSBEQ Value, [pSrc], #1 ;// Value = (OMX_U8) *pSrc++
+ ORRNE Value,Value,Value2, LSL #8 ;// Value = (OMX_U16) *pSrc++
+
+ TST Flag, #0x20 ;// Computing (Flag & 0x20) to check, if we're done
+ LDRBEQ Flag, [pSrc], #1 ;// Flag = (OMX_U8) *pSrc++, for next iteration
+ STRH Value, [pDst, strOffset] ;// Store <Value> at offset <strOffset>
+ BEQ unpackLoop ;// Branch to the loop beginning
+
+ ;//--------------------------------------------------
+ ;//InvTransformDC2x2: Inlined (Implemented in ARM V6)
+ ;//--------------------------------------------------
+
+ LDMIA pDst, {r0w0, r0w1} ;// r0w0 = |c1|c0| & r0w1 = |c3|c2|
+
+ STR pSrc, [ppSrc] ;// Update the bitstream pointer
+
+ LDR pQPDivTable, =armVCM4P10_QPDivTable ;// QP Division look-up-table base pointer
+ LDR pQPModTable, =armVCM4P10_VMatrixQPModTable ;// QP Modulo look-up-table base pointer
+
+ SADDSUBX r0w0, r0w0, r0w0 ;// [ c00+c01, c00-c01 ]
+ SADDSUBX r0w1, r0w1, r0w1 ;// [ c10+c11, c10-c11 ]
+
+ LDRSB Shift, [pQPDivTable, QP] ;// Shift = pQPDivTable[QP]
+ LDRSB Scale, [pQPModTable, QP] ;// Scale = pQPModTable[QP]
+
+ SADD16 c0w0, r0w0, r0w1 ;// [ d00+d10, d01+d11 ]
+ SSUB16 c1w0, r0w0, r0w1 ;// [ d00-d10, d01-d11 ]
+
+ ;//-------------------------------------------------
+ ;//DequantChromaDC2x2: Inlined (Neon Implementation)
+ ;//-------------------------------------------------
+
+ LSL Scale, Scale, Shift ;// Scale = Scale << Shift
+ VMOV dInvTrCoeff, c0w0, c1w0
+ VREV32 dInvTrCoeff,dInvTrCoeff
+ VDUP dScale,Scale
+
+ VMULL qDqntCoeff,dInvTrCoeff,dScale
+ VSHRN dDqntCoeff,qDqntCoeff,#1
+
+
+ VST1 dDqntCoeff,[pDst] ;// Storing all the coefficients at once
+
+ MOV return, #OMX_Sts_NoErr
+ M_END
+
+ ENDIF ;// CortexA8
+
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
new file mode 100755
index 0000000..2529959
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair_s.s
@@ -0,0 +1,264 @@
+;//
+;//
+;// File Name: omxVCM4P10_TransformDequantLumaDCFromPair_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// Description:
+;// H.264 inverse quantize and transform module
+;//
+;//
+
+;// Include standard headers
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+;// Import/Export symbols required from/to other files
+;// (For example tables)
+
+ IMPORT armVCM4P10_UnpackBlock4x4
+ IMPORT armVCM4P10_QPDivTable
+ IMPORT armVCM4P10_VMatrixQPModTable
+
+ M_VARIANTS CortexA8
+
+;// Set debugging level
+;//DEBUG_ON SETL {TRUE}
+
+
+;// Static Function: armVCM4P10_InvTransformDequantLumaDC4x4
+
+
+;// Guarding implementation by the processor name
+
+
+
+;// Static Function: armVCM4P10_InvTransformDequantLumaDC4x4
+
+;// Guarding implementation by the processor name
+
+ IF CortexA8
+
+;//Input Registers
+pData RN 0
+QP RN 1
+
+
+;//Local Scratch Registers
+
+;// ARM Registers
+
+pQPDivTable RN 2
+pQPModTable RN 3
+Shift RN 4
+Scale RN 5
+
+;// NEON Registers
+
+;// Packed Input pixels
+dIn0 DN D0.S16
+dIn1 DN D1.S16
+dIn2 DN D2.S16
+dIn3 DN D3.S16
+
+;// Intermediate calculations
+dRowSum1 DN D4.S16
+dRowSum2 DN D5.S16
+dRowDiff1 DN D6.S16
+dRowDiff2 DN D7.S16
+
+;// Row operated pixels
+dRowOp0 DN D0.S16
+dRowOp1 DN D1.S16
+dRowOp2 DN D2.S16
+dRowOp3 DN D3.S16
+qRowOp01 QN Q0.32
+qRowOp23 QN Q1.32
+
+;// Intermediate calculations
+dColSum1 DN D4.S16
+dColSum2 DN D5.S16
+dColDiff1 DN D6.S16
+dColDiff2 DN D7.S16
+
+;// Coloumn operated pixels
+dColOp0 DN D0.S16
+dColOp1 DN D1.S16
+dColOp2 DN D2.S16
+dColOp3 DN D3.S16
+
+;// Temporary scratch varaibles
+
+dScale DN D5.S16
+qRound0 QN Q3.S32
+qRound1 QN Q4.S32
+qRound2 QN Q5.S32
+qRound3 QN Q6.S32
+
+;// InvTransformed and Dequantized pixels
+dOut0 DN D0.S16
+dOut1 DN D1.S16
+dOut2 DN D2.S16
+dOut3 DN D3.S16
+
+
+ ;// Allocate stack memory required by the function
+
+
+ ;// Write function header
+ M_START armVCM4P10_InvTransformDequantLumaDC4x4,r5,d13
+
+ ;******************************************************************
+ ;// The strategy used in implementing the transform is as follows:*
+ ;// Load the 4x4 block into 4 D-registers *
+ ;// Transpose the 4x4 matrix *
+ ;// Perform the row operations (on columns) using SIMD *
+ ;// Transpose the 4x4 result matrix *
+ ;// Perform the coloumn operations *
+ ;******************************************************************
+
+ ;// Load all the 4x4 pixels in Transposed form
+
+ VLD4 {dIn0,dIn1,dIn2,dIn3},[pData]
+ LDR pQPDivTable, =armVCM4P10_QPDivTable ;// QP Division look-up-table base pointer
+ LDR pQPModTable, =armVCM4P10_VMatrixQPModTable ;// QP Modulo look-up-table base pointer
+
+ ;****************************************
+ ;// Row Operations (Performed on columns)
+ ;****************************************
+ ;// Scale factor calculation is done using ARM instructions
+ ;// Interleaved with NEON instructions inorder to Dual issue
+
+ VADD dRowSum1,dIn0,dIn1
+ VADD dRowSum2,dIn2,dIn3
+ VSUB dRowDiff1,dIn0,dIn1
+ LDRSB Shift, [pQPDivTable, QP] ;// ARM CODE: Shift = pQPDivTable[QP]
+ VSUB dRowDiff2,dIn2,dIn3
+ LDRSB Scale, [pQPModTable, QP] ;// ARM CODE: Scale = pQPModTable[QP]
+ VADD dRowOp0,dRowSum1,dRowSum2
+ VSUB dRowOp1,dRowSum1,dRowSum2
+ VSUB dRowOp2,dRowDiff1,dRowDiff2
+ LSL Scale, Scale, Shift ;// ARM CODE: Scale = Scale << Shift
+ VADD dRowOp3,dRowDiff1,dRowDiff2
+
+ ;****************************************
+ ;// Transpose the resultant matrix
+ ;****************************************
+
+ VTRN dRowOp0,dRowOp1
+ VTRN dRowOp2,dRowOp3
+ VTRN qRowOp01,qRowOp23
+
+ ;****************************************
+ ;// Coloumn Operations
+ ;****************************************
+
+ VADD dColSum1,dRowOp0,dRowOp1
+ VADD dColSum2,dRowOp2,dRowOp3
+ VSUB dColDiff1,dRowOp0,dRowOp1
+ VSUB dColDiff2,dRowOp2,dRowOp3
+ VADD dColOp0,dColSum1,dColSum2
+ VSUB dColOp1,dColSum1,dColSum2
+ VSUB dColOp2,dColDiff1,dColDiff2
+ VADD dColOp3,dColDiff1,dColDiff2
+
+ ;//----------------------------------------------------------------------
+ ;//
+ ;// <Dequantize> improves on the c-reference code
+ ;// Both the cases i.e., Shift>=0 and Shift<0 cases are covered together
+ ;// We do not subtract 2 from Shift as in C reference, instead perform a
+ ;// Scale << Shift once in the beginning and do a right shift by a
+ ;// constant 2 after the Multiplication. The value of Round would be 2
+ ;//
+ ;// By doing this we aviod the Branches required and also
+ ;// reduce the code size substantially
+ ;//
+ ;//----------------------------------------------------------------------
+
+
+ VDUP dScale, Scale ;// ARM -> NEON copy 'scale' to vector
+
+
+ VMOV qRound0,#2 ;// Set the Round Value
+ VMOV qRound1,#2
+ VMOV qRound2,#2
+ VMOV qRound3,#2
+
+ VMLAL qRound0,dColOp0,dScale ;// pDst[i] * Scale + Round
+ VMLAL qRound1,dColOp1,dScale
+ VMLAL qRound2,dColOp2,dScale
+ VMLAL qRound3,dColOp3,dScale
+
+ VSHRN dOut0,qRound0,#2 ;// Right shift by 2 & (OMX_S16)Value
+ VSHRN dOut1,qRound1,#2
+ VSHRN dOut2,qRound2,#2
+ VSHRN dOut3,qRound3,#2
+
+ ;***************************
+ ;// Store all the 4x4 pixels
+ ;***************************
+
+ VST1 {dOut0,dOut1,dOut2,dOut3}, [pData]
+
+
+ ;// Set return value
+
+ ;// Write function tail
+ M_END
+
+ ENDIF ;//CORTEXA8
+
+
+
+;// Function: omxVCM4P10_TransformDequantLumaDCFromPair
+
+;//Input Registers
+ppSrc RN 0
+pDst RN 1
+QPR2 RN 2
+
+;//Output Registers
+result RN 0
+
+;//Local Scratch Registers
+pDstR4 RN 4
+pDstR0 RN 0
+QPR1 RN 1
+QPR5 RN 5
+
+;// Guarding implementation by the processor name
+
+ IF CortexA8
+
+ ;// Allocate stack memory required by the function
+
+
+ ;// Write function header
+ M_START omxVCM4P10_TransformDequantLumaDCFromPair,r5
+
+ MOV pDstR4,pDst ;// Saving register r1
+ MOV QPR5,QPR2 ;// Saving register r2
+ BL armVCM4P10_UnpackBlock4x4
+
+ MOV pDstR0,pDstR4 ;// Setting up register r0
+ MOV QPR1,QPR5 ;// Setting up register r1
+ BL armVCM4P10_InvTransformDequantLumaDC4x4
+
+
+ ;// Set return value
+ MOV result,#OMX_Sts_NoErr
+
+ ;// Write function tail
+ M_END
+
+
+ ENDIF ;//ARM1136JS
+
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Average_4x_Align_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Average_4x_Align_unsafe_s.S
new file mode 100644
index 0000000..aca2df4
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Average_4x_Align_unsafe_s.S
@@ -0,0 +1,134 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_Average_4x4_Align0_unsafe
+ .func armVCM4P10_Average_4x4_Align0_unsafe
+armVCM4P10_Average_4x4_Align0_unsafe:
+ PUSH {r4-r6,lr}
+ LDR r7, =0x80808080
+ LDR r12,[r2,#0]
+ LDR r10,[r0],r1
+ LDR lr,[r2,r3]
+ LDR r11,[r0],r1
+ MVN r12,r12
+ MVN lr,lr
+ UHSUB8 r5,r10,r12
+ UHSUB8 r4,r11,lr
+ EOR r5,r5,r7
+ STR r5,[r2],r3
+ EOR r4,r4,r7
+ STR r4,[r2],r3
+ LDR r10,[r0],r1
+ LDR r12,[r2,#0]
+ LDR r11,[r0],r1
+ LDR lr,[r2,r3]
+ MVN r12,r12
+ UHSUB8 r5,r10,r12
+ MVN lr,lr
+ UHSUB8 r4,r11,lr
+ EOR r5,r5,r7
+ STR r5,[r2],r3
+ EOR r4,r4,r7
+ STR r4,[r2],r3
+ POP {r4-r6,pc}
+ .endfunc
+
+ .global armVCM4P10_Average_4x4_Align2_unsafe
+ .func armVCM4P10_Average_4x4_Align2_unsafe
+armVCM4P10_Average_4x4_Align2_unsafe:
+ PUSH {r4-r6,lr}
+ LDR r7, =0x80808080
+ LDR r4,[r0,#4]
+ LDR r10,[r0],r1
+ LDR r12,[r2,#0]
+ LDR lr,[r2,r3]
+ LDR r5,[r0,#4]
+ LDR r11,[r0],r1
+ MVN r12,r12
+ MVN lr,lr
+ LSR r10,r10,#16
+ ORR r10,r10,r4,LSL #16
+ LSR r11,r11,#16
+ ORR r11,r11,r5,LSL #16
+ UHSUB8 r5,r10,r12
+ UHSUB8 r4,r11,lr
+ EOR r5,r5,r7
+ STR r5,[r2],r3
+ EOR r4,r4,r7
+ STR r4,[r2],r3
+ LDR r4,[r0,#4]
+ LDR r10,[r0],r1
+ LDR r12,[r2,#0]
+ LDR lr,[r2,r3]
+ LDR r5,[r0,#4]
+ LDR r11,[r0],r1
+ MVN r12,r12
+ MVN lr,lr
+ LSR r10,r10,#16
+ ORR r10,r10,r4,LSL #16
+ LSR r11,r11,#16
+ ORR r11,r11,r5,LSL #16
+ UHSUB8 r5,r10,r12
+ UHSUB8 r4,r11,lr
+ EOR r5,r5,r7
+ STR r5,[r2],r3
+ EOR r4,r4,r7
+ STR r4,[r2],r3
+ POP {r4-r6,pc}
+ .endfunc
+
+ .global armVCM4P10_Average_4x4_Align3_unsafe
+ .func armVCM4P10_Average_4x4_Align3_unsafe
+armVCM4P10_Average_4x4_Align3_unsafe:
+ PUSH {r4-r6,lr}
+ LDR r7, =0x80808080
+ LDR r4,[r0,#4]
+ LDR r10,[r0],r1
+ LDR r12,[r2,#0]
+ LDR lr,[r2,r3]
+ LDR r5,[r0,#4]
+ LDR r11,[r0],r1
+ MVN r12,r12
+ MVN lr,lr
+ LSR r10,r10,#24
+ ORR r10,r10,r4,LSL #8
+ LSR r11,r11,#24
+ ORR r11,r11,r5,LSL #8
+ UHSUB8 r5,r10,r12
+ UHSUB8 r4,r11,lr
+ EOR r5,r5,r7
+ STR r5,[r2],r3
+ EOR r4,r4,r7
+ STR r4,[r2],r3
+ LDR r4,[r0,#4]
+ LDR r10,[r0],r1
+ LDR r12,[r2,#0]
+ LDR lr,[r2,r3]
+ LDR r5,[r0,#4]
+ LDR r11,[r0],r1
+ MVN r12,r12
+ MVN lr,lr
+ LSR r10,r10,#24
+ ORR r10,r10,r4,LSL #8
+ LSR r11,r11,#24
+ ORR r11,r11,r5,LSL #8
+ UHSUB8 r5,r10,r12
+ UHSUB8 r4,r11,lr
+ EOR r5,r5,r7
+ STR r5,[r2],r3
+ EOR r4,r4,r7
+ STR r4,[r2],r3
+ POP {r4-r6,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingChroma_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingChroma_unsafe_s.S
new file mode 100644
index 0000000..b9ee221
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingChroma_unsafe_s.S
@@ -0,0 +1,54 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_DeblockingChromabSLT4_unsafe
+ .func armVCM4P10_DeblockingChromabSLT4_unsafe
+armVCM4P10_DeblockingChromabSLT4_unsafe:
+ VLD1.32 {d18[0]},[r5]!
+ VSUBL.U8 q11,d5,d9
+ VMOV d28,d18
+ VSUBL.U8 q10,d8,d4
+ VSHR.S16 q11,q11,#2
+ VZIP.8 d18,d28
+ VBIF d18,d14,d16
+ VRHADD.S16 q10,q11,q10
+ VADD.I8 d31,d18,d15
+ VQMOVN.S16 d20,q10
+ VLD1.8 {d0[]},[r2]
+ VMIN.S8 d20,d20,d31
+ VNEG.S8 d31,d31
+ VLD1.8 {d2[]},[r3]
+ VMAX.S8 d20,d20,d31
+ VMOVL.U8 q14,d4
+ VMOVL.U8 q12,d8
+ VADDW.S8 q14,q14,d20
+ VSUBW.S8 q12,q12,d20
+ VQMOVUN.S16 d29,q14
+ VQMOVUN.S16 d24,q12
+ BX lr
+ .endfunc
+
+ .global armVCM4P10_DeblockingChromabSGE4_unsafe
+ .func armVCM4P10_DeblockingChromabSGE4_unsafe
+armVCM4P10_DeblockingChromabSGE4_unsafe:
+ VHADD.U8 d13,d4,d9
+ VHADD.U8 d31,d8,d5
+ VLD1.8 {d0[]},[r2]
+ ADD r5,r5,#4
+ VLD1.8 {d2[]},[r3]
+ VRHADD.U8 d13,d13,d5
+ VRHADD.U8 d31,d31,d9
+ BX lr
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingLuma_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingLuma_unsafe_s.S
new file mode 100644
index 0000000..47f3d44
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DeblockingLuma_unsafe_s.S
@@ -0,0 +1,102 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_DeblockingLumabSLT4_unsafe
+ .func armVCM4P10_DeblockingLumabSLT4_unsafe
+armVCM4P10_DeblockingLumabSLT4_unsafe:
+ VSUBL.U8 q11,d5,d9
+ VLD1.8 {d18[]},[r5]!
+ VSUBL.U8 q10,d8,d4
+ VLD1.8 {d19[]},[r5]!
+ VSHR.S16 q11,q11,#2
+ VEXT.8 d18,d18,d19,#4
+ VAND d19,d17,d15
+ VBIF d18,d14,d16
+ VRHADD.S16 q10,q11,q10
+ VRHADD.U8 d24,d4,d8
+ VADD.I8 d31,d18,d19
+ VAND d19,d12,d15
+ VQADD.U8 d23,d5,d18
+ VQMOVN.S16 d20,q10
+ VADD.I8 d31,d31,d19
+ VQSUB.U8 d22,d5,d18
+ VQADD.U8 d19,d9,d18
+ VHADD.U8 d26,d24,d6
+ VMIN.S8 d20,d20,d31
+ VNEG.S8 d31,d31
+ VQSUB.U8 d21,d9,d18
+ VHADD.U8 d27,d24,d10
+ VMAX.U8 d30,d26,d22
+ VMAX.S8 d20,d20,d31
+ VMOVL.U8 q14,d4
+ VMOVL.U8 q12,d8
+ VADDW.S8 q14,q14,d20
+ VSUBW.S8 q12,q12,d20
+ VQMOVUN.S16 d29,q14
+ VQMOVUN.S16 d24,q12
+ VMAX.U8 d25,d27,d21
+ VMIN.U8 d30,d30,d23
+ VMIN.U8 d25,d25,d19
+ VBIF d29,d4,d16
+ VBIF d30,d5,d17
+ VBIF d24,d8,d16
+ VBIF d25,d9,d12
+ BX lr
+ .endfunc
+
+ .global armVCM4P10_DeblockingLumabSGE4_unsafe
+ .func armVCM4P10_DeblockingLumabSGE4_unsafe
+armVCM4P10_DeblockingLumabSGE4_unsafe:
+ VSHR.U8 d19,d0,#2
+ VADD.I8 d19,d19,d15
+ VADDL.U8 q10,d8,d4
+ VADD.I8 d19,d19,d15
+ VADDL.U8 q11,d6,d9
+ VADDW.U8 q12,q10,d5
+ VCGT.U8 d19,d19,d13
+ VSHR.U16 q11,q11,#1
+ VHADD.U16 q11,q12,q11
+ VADDW.U8 q12,q12,d6
+ VADDL.U8 q13,d7,d6
+ VAND d17,d17,d19
+ VHADD.U8 d28,d4,d9
+ VSRA.U16 q13,q12,#1
+ VAND d12,d12,d19
+ VQRSHRN.U16 d29,q11,#1
+ VRHADD.U8 d28,d28,d5
+ VQRSHRN.U16 d30,q12,#2
+ VADDL.U8 q11,d10,d5
+ VADDW.U8 q12,q10,d9
+ VBIF d29,d28,d17
+ VQRSHRN.U16 d31,q13,#2
+ VADDL.U8 q13,d11,d10
+ VSHR.U16 q11,q11,#1
+ VHADD.U16 q11,q12,q11
+ VADDW.U8 q12,q12,d10
+ VHADD.U8 d28,d8,d5
+ VBIF d29,d4,d16
+ VBIF d30,d5,d17
+ VSRA.U16 q13,q12,#1
+ VQRSHRN.U16 d25,q12,#2
+ VQRSHRN.U16 d24,q11,#1
+ VRHADD.U8 d22,d28,d9
+ VBIF d25,d9,d12
+ VBIF d31,d6,d17
+ VBIF d24,d22,d12
+ VQRSHRN.U16 d28,q13,#2
+ VBIF d24,d8,d16
+ VBIF d28,d10,d12
+ BX lr
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S
new file mode 100644
index 0000000..e68bd8e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DecodeCoeffsToPair_s.S
@@ -0,0 +1,272 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_DecodeCoeffsToPair
+ .func armVCM4P10_DecodeCoeffsToPair
+armVCM4P10_DecodeCoeffsToPair:
+ PUSH {r4-r12,lr}
+ SUB sp,sp,#0x40
+ LDR r10,[r0,#0]
+ LDR r12,[r1,#0]
+ LDR r6, =armVCM4P10_CAVLCCoeffTokenTables
+ LDR r4,[sp,#0x68]
+ LDRB r9,[r10,#2]
+ LDRB r8,[r10,#1]
+ LDRB r11,[r10],#3
+ ADD r12,r12,#8
+ LDR r6,[r6,r4,LSL #2]
+ ORR r9,r9,r8,LSL #8
+ ORR r11,r9,r11,LSL #16
+ LSLS r8,r11,r12
+ MOVS r7,#0x1e
+ AND r7,r7,r8,LSR #27
+ SUBS r12,r12,#8
+L0x44:
+ BCC L1
+ LDRB r8,[r10],#1
+L1:
+ LDRH r7,[r6,r7]
+ ADDCC r12,r12,#8
+ ADD r12,r12,#4
+ ORRCS r11,r8,r11,LSL #8
+ LSRS r8,r7,#1
+ BCS L0x74
+ LSLS r8,r11,r12
+ SUBS r12,r12,#0xa
+ ADD r7,r7,r8,LSR #29
+ BIC r7,r7,#1
+ B L0x44
+L0x74:
+ SUB r12,r12,r7,LSR #13
+ BIC r7,r8,#0xf000
+ LSRS r5,r7,#2
+ STRB r5,[r2,#0]
+ BEQ L0x344
+ CMP r7,#0x44
+ BGE L0x33c
+ STR r0,[sp,#0]
+ STR r1,[sp,#4]
+ STR r3,[sp,#8]
+ ANDS r1,r7,#3
+ ADD r2,sp,#0xc
+ BEQ L0xd8
+ MOV r0,r1
+L0xac:
+ LSLS r7,r11,r12
+ SUBS r12,r12,#7
+ BCC L2
+ LDRB r8,[r10],#1
+L2:
+ ADDCC r12,r12,#8
+ LSR r7,r7,#31
+ ORRCS r11,r8,r11,LSL #8
+ SUBS r0,r0,#1
+ MOV r8,#1
+ SUB r8,r8,r7,LSL #1
+ STRH r8,[r2],#2
+ BGT L0xac
+L0xd8:
+ SUBS r0,r5,r1
+ BEQ L0x1b8
+ MOV r4,#1
+ CMP r5,#0xa
+ MOVLE r4,#0
+ CMP r1,#3
+ MOVLT r1,#4
+ MOVGE r1,#2
+ MOVGE r4,#0
+L0xfc:
+ LSLS r7,r11,r12
+ CLZ r7,r7
+ ADD r12,r12,r7
+ SUBS r12,r12,#7
+ BCC L3
+ LDRB r8,[r10],#1
+ ORR r11,r8,r11,LSL #8
+ SUBS r12,r12,#8
+ BCC L3
+ LDRB r8,[r10],#1
+L3:
+ ADDCC r12,r12,#8
+ ORRCS r11,r8,r11,LSL #8
+ CMP r7,#0x10
+ BGE L0x33c
+ MOVS lr,r4
+ TEQEQ r7,#0xe
+ MOVEQ lr,#4
+ TEQ r7,#0xf
+ MOVEQ lr,#0xc
+ TEQEQ r4,#0
+ ADDEQ r7,r7,#0xf
+ TEQ lr,#0
+ BEQ L0x184
+ LSL r3,r11,r12
+ ADD r12,r12,lr
+ SUBS r12,r12,#8
+ RSB r9,lr,#0x20
+ BCC L4
+ LDRB r8,[r10],#1
+ ORR r11,r8,r11,LSL #8
+ SUBS r12,r12,#8
+ BCC L4
+ LDRB r8,[r10],#1
+L4:
+ ADDCC r12,r12,#8
+ LSR r3,r3,r9
+ ORRCS r11,r8,r11,LSL #8
+ LSL r7,r7,r4
+ ADD r7,r3,r7
+L0x184:
+ ADD r7,r7,r1
+ MOV r1,#2
+ LSRS r8,r7,#1
+ RSBCS r8,r8,#0
+ STRH r8,[r2],#2
+ LDR r9, =armVCM4P10_SuffixToLevel
+ LDRSB r8,[r9,r4]
+ TEQ r4,#0
+ MOVEQ r4,#1
+ CMP r7,r8
+ ADDCS r4,r4,#1
+ SUBS r0,r0,#1
+ BGT L0xfc
+L0x1b8:
+ LDR r8,[sp,#0x6c]
+ SUB r0,r5,#1
+ SUBS r1,r8,r5
+ ADD r4,sp,#0x2c
+ MOV lr,r5
+ SUB lr,lr,#1
+ BEQ L0x2b0
+ TEQ r8,#4
+ LDREQ r6, =(armVCM4P10_CAVLCTotalZeros2x2Tables - 4)
+ LDRNE r6, =(armVCM4P10_CAVLCTotalZeroTables - 4)
+ LDR r6,[r6,r5,LSL #2]
+ LSLS r8,r11,r12
+ MOVS r7,#0x1e
+ AND r7,r7,r8,LSR #27
+ SUBS r12,r12,#8
+L0x1f4:
+ BCC L5
+ LDRB r8,[r10],#1
+L5:
+ LDRH r7,[r6,r7]
+ ADDCC r12,r12,#8
+ ADD r12,r12,#4
+ ORRCS r11,r8,r11,LSL #8
+ LSRS r8,r7,#1
+ BCS L0x224
+ LSLS r8,r11,r12
+ SUBS r12,r12,#0xa
+ ADD r7,r7,r8,LSR #29
+ BIC r7,r7,#1
+ B L0x1f4
+L0x224:
+ SUB r12,r12,r7,LSR #13
+ BIC r7,r8,#0xf000
+ CMP r7,#0x10
+ BGE L0x33c
+ LDR r3, =(armVCM4P10_CAVLCRunBeforeTables - 4)
+ ADD r4,sp,#0x2c
+ MOVS r1,r7
+ ADD lr,lr,r1
+ BEQ L0x2b0
+L0x248:
+ SUBS r0,r0,#1
+ LDR r6,[r3,r1,LSL #2]
+ BLT L0x2bc
+ LSLS r8,r11,r12
+ MOVS r7,#0xe
+ AND r7,r7,r8,LSR #28
+ SUBS r12,r12,#8
+L0x264:
+ BCC L6
+ LDRB r8,[r10],#1
+L6:
+ LDRH r7,[r6,r7]
+ ADDCC r12,r12,#8
+ ADD r12,r12,#3
+ ORRCS r11,r8,r11,LSL #8
+ LSRS r8,r7,#1
+ BCS L0x294
+ LSLS r8,r11,r12
+ SUBS r12,r12,#9
+ ADD r7,r7,r8,LSR #29
+ BIC r7,r7,#1
+ B L0x264
+L0x294:
+ SUB r12,r12,r7,LSR #13
+ BIC r7,r8,#0xf000
+ CMP r7,#0xf
+ BGE L0x33c
+ SUBS r1,r1,r7
+ STRB r7,[r4],#1
+ BGT L0x248
+L0x2b0:
+ SUBS r0,r0,#1
+ BLT L7
+ STRB r1,[r4],#1
+L7:
+ BGT L0x2b0
+L0x2bc:
+ STRB r1,[r4],#1
+ LDR r8,[sp,#0x6c]
+ TEQ r8,#0xf
+ ADDEQ lr,lr,#1
+ SUB r4,r4,r5
+ SUB r2,r2,r5
+ SUB r2,r2,r5
+ LDR r3,[sp,#8]
+ LDR r0,[r3,#0]
+ TEQ r8,#4
+ LDREQ r6, =armVCM4P10_ZigZag_2x2
+ LDRNE r6, =armVCM4P10_ZigZag_4x4
+L0x2ec:
+ LDRB r9,[r4],#1
+ LDRB r8,[r6,lr]
+ SUB lr,lr,#1
+ SUB lr,lr,r9
+ LDRSH r9,[r2],#2
+ SUBS r5,r5,#1
+ ORREQ r8,r8,#0x20
+ ADD r1,r9,#0x80
+ CMP r1,#0x100
+ ORRCS r8,r8,#0x10
+ TEQ r5,#0
+ STRB r8,[r0],#1
+ STRB r9,[r0],#1
+ LSR r9,r9,#8
+ BCC L8
+ STRB r9,[r0],#1
+L8:
+ BNE L0x2ec
+ STR r0,[r3,#0]
+ LDR r0,[sp,#0]
+ LDR r1,[sp,#4]
+ B L0x344
+L0x33c:
+ MVN r0,#1
+ B L0x35c
+L0x344:
+ ADD r10,r10,r12,LSR #3
+ AND r12,r12,#7
+ SUB r10,r10,#4
+ STR r12,[r1,#0]
+ STR r10,[r0,#0]
+ MOV r0,#0
+L0x35c:
+ ADD sp,sp,#0x40
+ POP {r4-r12,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S
new file mode 100644
index 0000000..44eb428
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_DequantTables_s.S
@@ -0,0 +1,103 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .section .rodata
+ .align 4
+
+
+ .global armVCM4P10_QPDivTable
+ .global armVCM4P10_VMatrixQPModTable
+ .global armVCM4P10_PosToVCol4x4
+ .global armVCM4P10_PosToVCol2x2
+ .global armVCM4P10_VMatrix
+ .global armVCM4P10_QPModuloTable
+ .global armVCM4P10_VMatrixU16
+
+armVCM4P10_PosToVCol4x4:
+ .byte 0, 2, 0, 2
+ .byte 2, 1, 2, 1
+ .byte 0, 2, 0, 2
+ .byte 2, 1, 2, 1
+
+armVCM4P10_PosToVCol2x2:
+ .byte 0, 2
+ .byte 2, 1
+
+armVCM4P10_VMatrix:
+ .byte 10, 16, 13
+ .byte 11, 18, 14
+ .byte 13, 20, 16
+ .byte 14, 23, 18
+ .byte 16, 25, 20
+ .byte 18, 29, 23
+
+;//-------------------------------------------------------
+;// This table evaluates the expression [(INT)(QP/6)],
+;// for values of QP from 0 to 51 (inclusive).
+;//-------------------------------------------------------
+
+armVCM4P10_QPDivTable:
+ .byte 0, 0, 0, 0, 0, 0
+ .byte 1, 1, 1, 1, 1, 1
+ .byte 2, 2, 2, 2, 2, 2
+ .byte 3, 3, 3, 3, 3, 3
+ .byte 4, 4, 4, 4, 4, 4
+ .byte 5, 5, 5, 5, 5, 5
+ .byte 6, 6, 6, 6, 6, 6
+ .byte 7, 7, 7, 7, 7, 7
+ .byte 8, 8, 8, 8, 8, 8
+
+;//----------------------------------------------------
+;// This table contains armVCM4P10_VMatrix[QP%6][0] entires,
+;// for values of QP from 0 to 51 (inclusive).
+;//----------------------------------------------------
+
+armVCM4P10_VMatrixQPModTable:
+ .byte 10, 11, 13, 14, 16, 18
+ .byte 10, 11, 13, 14, 16, 18
+ .byte 10, 11, 13, 14, 16, 18
+ .byte 10, 11, 13, 14, 16, 18
+ .byte 10, 11, 13, 14, 16, 18
+ .byte 10, 11, 13, 14, 16, 18
+ .byte 10, 11, 13, 14, 16, 18
+ .byte 10, 11, 13, 14, 16, 18
+ .byte 10, 11, 13, 14, 16, 18
+
+;//-------------------------------------------------------
+;// This table evaluates the modulus expression [QP%6]*6,
+;// for values of QP from 0 to 51 (inclusive).
+;//-------------------------------------------------------
+
+armVCM4P10_QPModuloTable:
+ .byte 0, 6, 12, 18, 24, 30
+ .byte 0, 6, 12, 18, 24, 30
+ .byte 0, 6, 12, 18, 24, 30
+ .byte 0, 6, 12, 18, 24, 30
+ .byte 0, 6, 12, 18, 24, 30
+ .byte 0, 6, 12, 18, 24, 30
+ .byte 0, 6, 12, 18, 24, 30
+ .byte 0, 6, 12, 18, 24, 30
+ .byte 0, 6, 12, 18, 24, 30
+
+;//-------------------------------------------------------
+;// This table contains the invidual byte values stored as
+;// halfwords. This avoids unpacking inside the function
+;//-------------------------------------------------------
+
+armVCM4P10_VMatrixU16:
+ .hword 10, 16, 13
+ .hword 11, 18, 14
+ .hword 13, 20, 16
+ .hword 14, 23, 18
+ .hword 16, 25, 20
+ .hword 18, 29, 23
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Align_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Align_unsafe_s.S
new file mode 100644
index 0000000..37bc69b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Align_unsafe_s.S
@@ -0,0 +1,123 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+ .func armVCM4P10_InterpolateLuma_HorAlign9x_unsafe
+armVCM4P10_InterpolateLuma_HorAlign9x_unsafe:
+ MOV r12,r8
+ AND r7,r0,#3
+ BIC r0,r0,#3
+ ADD pc,pc,r7,LSL #2
+ NOP
+ B Copy0toAligned
+ B Copy1toAligned
+ B Copy2toAligned
+ B Copy3toAligned
+Copy0toAligned:
+ LDM r0,{r7,r10,r11}
+ SUBS r9,r9,#1
+ ADD r0,r0,r1
+ STM r8!,{r7,r10,r11}
+ BGT Copy0toAligned
+ B CopyEnd
+Copy1toAligned:
+ LDM r0,{r7,r10,r11}
+ SUBS r9,r9,#1
+ ADD r0,r0,r1
+ LSR r7,r7,#8
+ ORR r7,r7,r10,LSL #24
+ LSR r10,r10,#8
+ ORR r10,r10,r11,LSL #24
+ LSR r11,r11,#8
+ STM r8!,{r7,r10,r11}
+ BGT Copy1toAligned
+ B CopyEnd
+Copy2toAligned:
+ LDM r0,{r7,r10,r11}
+ SUBS r9,r9,#1
+ ADD r0,r0,r1
+ LSR r7,r7,#16
+ ORR r7,r7,r10,LSL #16
+ LSR r10,r10,#16
+ ORR r10,r10,r11,LSL #16
+ LSR r11,r11,#16
+ STM r8!,{r7,r10,r11}
+ BGT Copy2toAligned
+ B CopyEnd
+Copy3toAligned:
+ LDM r0,{r7,r10,r11}
+ SUBS r9,r9,#1
+ ADD r0,r0,r1
+ LSR r7,r7,#24
+ ORR r7,r7,r10,LSL #8
+ LSR r10,r10,#24
+ ORR r10,r10,r11,LSL #8
+ LSR r11,r11,#24
+ STM r8!,{r7,r10,r11}
+ BGT Copy3toAligned
+CopyEnd:
+ MOV r0,r12
+ MOV r1,#0xc
+ BX lr
+ .endfunc
+
+ .global armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+ .func armVCM4P10_InterpolateLuma_VerAlign4x_unsafe
+armVCM4P10_InterpolateLuma_VerAlign4x_unsafe:
+ AND r7,r0,#3
+ BIC r0,r0,#3
+ ADD pc,pc,r7,LSL #2
+ NOP
+ B Copy0toVAligned
+ B Copy1toVAligned
+ B Copy2toVAligned
+ B Copy3toVAligned
+Copy0toVAligned:
+ LDR r7,[r0],r1
+ SUBS r9,r9,#1
+ STR r7,[r8],#4
+ BGT Copy0toVAligned
+ B CopyVEnd
+Copy1toVAligned:
+ LDR r10,[r0,#4]
+ LDR r7,[r0],r1
+ SUBS r9,r9,#1
+ LSL r10,r10,#24
+ ORR r7,r10,r7,LSR #8
+ STR r7,[r8],#4
+ BGT Copy1toVAligned
+ B CopyVEnd
+Copy2toVAligned:
+ LDR r10,[r0,#4]
+ LDR r7,[r0],r1
+ SUBS r9,r9,#1
+ LSL r10,r10,#16
+ ORR r7,r10,r7,LSR #16
+ STR r7,[r8],#4
+ BGT Copy2toVAligned
+ B CopyVEnd
+Copy3toVAligned:
+ LDR r10,[r0,#4]
+ LDR r7,[r0],r1
+ SUBS r9,r9,#1
+ LSL r10,r10,#8
+ ORR r7,r10,r7,LSR #24
+ STR r7,[r8],#4
+ BGT Copy3toVAligned
+CopyVEnd:
+ SUB r0,r8,#0x1c
+ MOV r1,#4
+ BX lr
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Copy_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Copy_unsafe_s.S
new file mode 100644
index 0000000..fe92201
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_Copy_unsafe_s.S
@@ -0,0 +1,105 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_InterpolateLuma_Copy4x4_unsafe
+ .func armVCM4P10_InterpolateLuma_Copy4x4_unsafe
+armVCM4P10_InterpolateLuma_Copy4x4_unsafe:
+ PUSH {r4-r6,lr}
+ AND r12,r0,#3
+ BIC r0,r0,#3
+ ADD pc,pc,r12,LSL #2
+ NOP
+ B Copy4x4Align0
+ B Copy4x4Align1
+ B Copy4x4Align2
+ B Copy4x4Align3
+Copy4x4Align0:
+ LDR r4,[r0],r1
+ LDR r5,[r0],r1
+ STR r4,[r2],r3
+ LDR r8,[r0],r1
+ STR r5,[r2],r3
+ LDR r9,[r0],r1
+ STR r8,[r2],r3
+ STR r9,[r2],r3
+ B Copy4x4End
+Copy4x4Align1:
+ LDR r5,[r0,#4]
+ LDR r4,[r0],r1
+ LDR r9,[r0,#4]
+ LDR r8,[r0],r1
+ LSR r4,r4,#8
+ ORR r4,r4,r5,LSL #24
+ STR r4,[r2],r3
+ LSR r8,r8,#8
+ ORR r8,r8,r9,LSL #24
+ LDR r5,[r0,#4]
+ LDR r4,[r0],r1
+ STR r8,[r2],r3
+ LDR r9,[r0,#4]
+ LDR r8,[r0],r1
+ LSR r4,r4,#8
+ ORR r4,r4,r5,LSL #24
+ STR r4,[r2],r3
+ LSR r8,r8,#8
+ ORR r8,r8,r9,LSL #24
+ STR r8,[r2],r3
+ B Copy4x4End
+Copy4x4Align2:
+ LDR r5,[r0,#4]
+ LDR r4,[r0],r1
+ LDR r9,[r0,#4]
+ LDR r8,[r0],r1
+ LSR r4,r4,#16
+ ORR r4,r4,r5,LSL #16
+ STR r4,[r2],r3
+ LSR r8,r8,#16
+ ORR r8,r8,r9,LSL #16
+ STR r8,[r2],r3
+ LDR r5,[r0,#4]
+ LDR r4,[r0],r1
+ LDR r9,[r0,#4]
+ LDR r8,[r0],r1
+ LSR r4,r4,#16
+ ORR r4,r4,r5,LSL #16
+ STR r4,[r2],r3
+ LSR r8,r8,#16
+ ORR r8,r8,r9,LSL #16
+ STR r8,[r2],r3
+ B Copy4x4End
+Copy4x4Align3:
+ LDR r5,[r0,#4]
+ LDR r4,[r0],r1
+ LDR r9,[r0,#4]
+ LDR r8,[r0],r1
+ LSR r4,r4,#24
+ ORR r4,r4,r5,LSL #8
+ STR r4,[r2],r3
+ LSR r8,r8,#24
+ ORR r8,r8,r9,LSL #8
+ STR r8,[r2],r3
+ LDR r5,[r0,#4]
+ LDR r4,[r0],r1
+ LDR r9,[r0,#4]
+ LDR r8,[r0],r1
+ LSR r4,r4,#24
+ ORR r4,r4,r5,LSL #8
+ STR r4,[r2],r3
+ LSR r8,r8,#24
+ ORR r8,r8,r9,LSL #8
+ STR r8,[r2],r3
+Copy4x4End:
+ POP {r4-r6,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.S
new file mode 100644
index 0000000..544abe8
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_DiagCopy_unsafe_s.S
@@ -0,0 +1,107 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe
+ .func armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe
+armVCM4P10_InterpolateLuma_HorDiagCopy_unsafe:
+ PUSH {r4-r6,lr}
+ MOV lr,#4
+ LDR r6, =0xfe00fe0
+ LDR r12, =0xff00ff
+LoopStart1:
+ LDR r11,[r0,#0xc]
+ LDR r10,[r0,#8]
+ LDR r5,[r0,#4]
+ LDR r4,[r0],r1
+ UQSUB16 r11,r11,r6
+ UQSUB16 r10,r10,r6
+ UQSUB16 r5,r5,r6
+ UQSUB16 r4,r4,r6
+ USAT16 r11,#13,r11
+ USAT16 r10,#13,r10
+ USAT16 r5,#13,r5
+ USAT16 r4,#13,r4
+ AND r11,r12,r11,LSR #5
+ AND r10,r12,r10,LSR #5
+ AND r5,r12,r5,LSR #5
+ AND r4,r12,r4,LSR #5
+ ORR r11,r10,r11,LSL #8
+ ORR r10,r4,r5,LSL #8
+ SUBS lr,lr,#1
+ STRD r10,r11,[r7],#8
+ BGT LoopStart1
+ SUB r0,r7,#0x20
+ MOV r1,#8
+ POP {r4-r6,pc}
+ .endfunc
+
+ .global armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe
+ .func armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe
+armVCM4P10_InterpolateLuma_VerDiagCopy_unsafe:
+ PUSH {r4-r6,lr}
+ LDR r6, =0xfe00fe0
+ LDR r12, =0xff00ff
+ MOV lr,#2
+LoopStart:
+ LDR r11,[r0,#0xc]
+ LDR r10,[r0,#8]
+ LDR r5,[r0,#4]
+ LDR r4,[r0],r1
+ UQSUB16 r11,r11,r6
+ UQSUB16 r10,r10,r6
+ UQSUB16 r5,r5,r6
+ UQSUB16 r4,r4,r6
+ USAT16 r11,#13,r11
+ USAT16 r10,#13,r10
+ USAT16 r5,#13,r5
+ USAT16 r4,#13,r4
+ AND r11,r12,r11,LSR #5
+ AND r10,r12,r10,LSR #5
+ AND r5,r12,r5,LSR #5
+ AND r4,r12,r4,LSR #5
+ ORR r11,r10,r11,LSL #8
+ ORR r10,r4,r5,LSL #8
+ PKHBT r4,r10,r11,LSL #16
+ STR r4,[r7],#8
+ PKHTB r5,r11,r10,ASR #16
+ STR r5,[r7],#-4
+ LDR r11,[r0,#0xc]
+ LDR r10,[r0,#8]
+ LDR r5,[r0,#4]
+ LDR r4,[r0],r1
+ UQSUB16 r11,r11,r6
+ UQSUB16 r10,r10,r6
+ UQSUB16 r5,r5,r6
+ UQSUB16 r4,r4,r6
+ USAT16 r11,#13,r11
+ USAT16 r10,#13,r10
+ USAT16 r5,#13,r5
+ USAT16 r4,#13,r4
+ AND r11,r12,r11,LSR #5
+ AND r10,r12,r10,LSR #5
+ AND r5,r12,r5,LSR #5
+ AND r4,r12,r4,LSR #5
+ ORR r11,r10,r11,LSL #8
+ ORR r10,r4,r5,LSL #8
+ PKHBT r4,r10,r11,LSL #16
+ SUBS lr,lr,#1
+ STR r4,[r7],#8
+ PKHTB r5,r11,r10,ASR #16
+ STR r5,[r7],#4
+ BGT LoopStart
+ SUB r0,r7,#0x18
+ MOV r1,#4
+ POP {r4-r6,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.S
new file mode 100644
index 0000000..a330972
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe_s.S
@@ -0,0 +1,164 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+ .func armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe:
+ PUSH {r4-r12,lr}
+ VLD1.8 {d0,d1},[r0],r1
+ VMOV.I16 d31,#0x14
+ VMOV.I16 d30,#0x5
+ VEXT.8 d4,d0,d1,#1
+ VEXT.8 d2,d0,d1,#2
+ VEXT.8 d3,d0,d1,#3
+ VEXT.8 d5,d0,d1,#4
+ VEXT.8 d1,d0,d1,#5
+ VADDL.U8 q1,d2,d3
+ VADDL.U8 q2,d4,d5
+ VADDL.U8 q5,d0,d1
+ VLD1.8 {d0,d1},[r0],r1
+ VMLA.I16 d10,d2,d31
+ VMUL.I16 d8,d4,d30
+ VEXT.8 d4,d0,d1,#1
+ VEXT.8 d2,d0,d1,#2
+ VEXT.8 d3,d0,d1,#3
+ VEXT.8 d5,d0,d1,#4
+ VEXT.8 d1,d0,d1,#5
+ VADDL.U8 q1,d2,d3
+ VADDL.U8 q2,d4,d5
+ VADDL.U8 q6,d0,d1
+ VLD1.8 {d0,d1},[r0],r1
+ VSUB.I16 d10,d10,d8
+ VMLA.I16 d12,d2,d31
+ VMUL.I16 d8,d4,d30
+ VEXT.8 d4,d0,d1,#1
+ VEXT.8 d2,d0,d1,#2
+ VEXT.8 d3,d0,d1,#3
+ VEXT.8 d5,d0,d1,#4
+ VEXT.8 d1,d0,d1,#5
+ VADDL.U8 q1,d2,d3
+ VADDL.U8 q2,d4,d5
+ VADDL.U8 q7,d0,d1
+ VLD1.8 {d0,d1},[r0],r1
+ VSUB.I16 d12,d12,d8
+ VMLA.I16 d14,d2,d31
+ VMUL.I16 d8,d4,d30
+ VEXT.8 d4,d0,d1,#1
+ VEXT.8 d2,d0,d1,#2
+ VEXT.8 d3,d0,d1,#3
+ VEXT.8 d5,d0,d1,#4
+ VEXT.8 d1,d0,d1,#5
+ VADDL.U8 q1,d2,d3
+ VADDL.U8 q2,d4,d5
+ VADDL.U8 q8,d0,d1
+ VLD1.8 {d0,d1},[r0],r1
+ VSUB.I16 d14,d14,d8
+ VMLA.I16 d16,d2,d31
+ VMUL.I16 d8,d4,d30
+ VEXT.8 d4,d0,d1,#1
+ VEXT.8 d2,d0,d1,#2
+ VEXT.8 d3,d0,d1,#3
+ VEXT.8 d5,d0,d1,#4
+ VEXT.8 d1,d0,d1,#5
+ VADDL.U8 q1,d2,d3
+ VADDL.U8 q2,d4,d5
+ VADDL.U8 q9,d0,d1
+ VLD1.8 {d0,d1},[r0],r1
+ VSUB.I16 d16,d16,d8
+ VMLA.I16 d18,d2,d31
+ VMUL.I16 d8,d4,d30
+ VEXT.8 d4,d0,d1,#1
+ VEXT.8 d2,d0,d1,#2
+ VEXT.8 d3,d0,d1,#3
+ VEXT.8 d5,d0,d1,#4
+ VEXT.8 d1,d0,d1,#5
+ VADDL.U8 q1,d2,d3
+ VADDL.U8 q2,d4,d5
+ VADDL.U8 q10,d0,d1
+ VLD1.8 {d0,d1},[r0],r1
+ VSUB.I16 d18,d18,d8
+ VMLA.I16 d20,d2,d31
+ VMUL.I16 d8,d4,d30
+ VEXT.8 d4,d0,d1,#1
+ VEXT.8 d2,d0,d1,#2
+ VEXT.8 d3,d0,d1,#3
+ VEXT.8 d5,d0,d1,#4
+ VEXT.8 d1,d0,d1,#5
+ VADDL.U8 q1,d2,d3
+ VADDL.U8 q2,d4,d5
+ VADDL.U8 q11,d0,d1
+ VLD1.8 {d0,d1},[r0],r1
+ VSUB.I16 d20,d20,d8
+ VMLA.I16 d22,d2,d31
+ VMUL.I16 d8,d4,d30
+ VEXT.8 d4,d0,d1,#1
+ VEXT.8 d2,d0,d1,#2
+ VEXT.8 d3,d0,d1,#3
+ VEXT.8 d5,d0,d1,#4
+ VEXT.8 d1,d0,d1,#5
+ VADDL.U8 q1,d2,d3
+ VADDL.U8 q2,d4,d5
+ VADDL.U8 q12,d0,d1
+ VLD1.8 {d0,d1},[r0],r1
+ VSUB.I16 d22,d22,d8
+ VMLA.I16 d24,d2,d31
+ VMUL.I16 d8,d4,d30
+ VEXT.8 d4,d0,d1,#1
+ VEXT.8 d2,d0,d1,#2
+ VEXT.8 d3,d0,d1,#3
+ VEXT.8 d5,d0,d1,#4
+ VEXT.8 d1,d0,d1,#5
+ VADDL.U8 q1,d2,d3
+ VADDL.U8 q2,d4,d5
+ VADDL.U8 q13,d0,d1
+ VSUB.I16 d24,d24,d8
+ VMLA.I16 d26,d2,d31
+ VMUL.I16 d8,d4,d30
+ VMOV.I32 q15,#0x14
+ VMOV.I32 q14,#0x5
+ VADDL.S16 q5,d10,d20
+ VADDL.S16 q1,d14,d16
+ VADDL.S16 q0,d12,d18
+ VSUB.I16 d26,d26,d8
+ VMLA.I32 q5,q1,q15
+ VMUL.I32 q4,q0,q14
+ VADDL.S16 q6,d12,d22
+ VADDL.S16 q1,d16,d18
+ VADDL.S16 q0,d14,d20
+ VMLA.I32 q6,q1,q15
+ VSUB.I32 q5,q5,q4
+ VMUL.I32 q4,q0,q14
+ VADDL.S16 q2,d14,d24
+ VADDL.S16 q1,d18,d20
+ VADDL.S16 q0,d16,d22
+ VMLA.I32 q2,q1,q15
+ VSUB.I32 q6,q6,q4
+ VMUL.I32 q4,q0,q14
+ VADDL.S16 q3,d16,d26
+ VADDL.S16 q1,d20,d22
+ VADDL.S16 q0,d18,d24
+ VMLA.I32 q3,q1,q15
+ VSUB.I32 q2,q2,q4
+ VMLS.I32 q3,q0,q14
+ VQRSHRUN.S32 d0,q5,#10
+ VQRSHRUN.S32 d2,q6,#10
+ VQRSHRUN.S32 d4,q2,#10
+ VQRSHRUN.S32 d6,q3,#10
+ VQMOVN.U16 d0,q0
+ VQMOVN.U16 d2,q1
+ VQMOVN.U16 d4,q2
+ VQMOVN.U16 d6,q3
+ POP {r4-r12,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.S
new file mode 100644
index 0000000..991c33f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe_s.S
@@ -0,0 +1,119 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+ .func armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe:
+ PUSH {r4-r12,lr}
+ VLD1.8 {d0,d1},[r0],r1
+ ADD r12,r0,r1,LSL #2
+ VMOV.I8 d30,#0x5
+ VMOV.I8 d31,#0x14
+ VLD1.8 {d10,d11},[r12],r1
+ VLD1.8 {d2,d3},[r0],r1
+ VLD1.8 {d12,d13},[r12],r1
+ VADDL.U8 q9,d0,d10
+ VLD1.8 {d4,d5},[r0],r1
+ VADDL.U8 q0,d1,d11
+ VLD1.8 {d6,d7},[r0],r1
+ VADDL.U8 q10,d2,d12
+ VLD1.8 {d8,d9},[r0],r1
+ VMLAL.U8 q9,d4,d31
+ VLD1.8 {d14,d15},[r12],r1
+ VMLAL.U8 q0,d5,d31
+ VLD1.8 {d16,d17},[r12],r1
+ VMLAL.U8 q9,d6,d31
+ VMLAL.U8 q10,d6,d31
+ VMLSL.U8 q0,d3,d30
+ VADDL.U8 q11,d4,d14
+ VMLSL.U8 q9,d2,d30
+ VADDL.U8 q1,d3,d13
+ VMLAL.U8 q0,d7,d31
+ VMLAL.U8 q10,d8,d31
+ VMLSL.U8 q9,d8,d30
+ VMLAL.U8 q1,d7,d31
+ VMLSL.U8 q0,d9,d30
+ VMLAL.U8 q11,d8,d31
+ VMLSL.U8 q10,d4,d30
+ VMLSL.U8 q1,d5,d30
+ VADDL.U8 q2,d5,d15
+ VMLAL.U8 q11,d10,d31
+ VMLSL.U8 q10,d10,d30
+ VMLAL.U8 q1,d9,d31
+ VMLAL.U8 q2,d9,d31
+ VADDL.U8 q12,d6,d16
+ VMLSL.U8 q11,d6,d30
+ VMLSL.U8 q1,d11,d30
+ VMLSL.U8 q2,d7,d30
+ VADDL.U8 q3,d7,d17
+ VMLAL.U8 q12,d10,d31
+ VMLSL.U8 q11,d12,d30
+ VMLSL.U8 q2,d13,d30
+ VMLAL.U8 q3,d11,d31
+ VMLAL.U8 q12,d12,d31
+ VEXT.8 d26,d18,d19,#2
+ VMLAL.U8 q2,d11,d31
+ VMLAL.U8 q3,d13,d31
+ VMLSL.U8 q12,d8,d30
+ VEXT.8 d27,d18,d19,#4
+ VMOV.I16 d31,#0x14
+ VMLSL.U8 q3,d9,d30
+ VMLSL.U8 q12,d14,d30
+ VEXT.8 d29,d19,d0,#2
+ VEXT.8 d28,d18,d19,#6
+ VMLSL.U8 q3,d15,d30
+ VADDL.S16 q0,d18,d29
+ VADD.I16 d27,d27,d28
+ VMOV.I16 d30,#0x5
+ VADD.I16 d26,d26,d19
+ VMLAL.S16 q0,d27,d31
+ VEXT.8 d27,d20,d21,#4
+ VEXT.8 d28,d20,d21,#6
+ VEXT.8 d29,d21,d2,#2
+ VMLSL.S16 q0,d26,d30
+ VEXT.8 d26,d20,d21,#2
+ VADDL.S16 q1,d20,d29
+ VADD.I16 d27,d27,d28
+ VADD.I16 d26,d26,d21
+ VEXT.8 d28,d22,d23,#6
+ VMLAL.S16 q1,d27,d31
+ VEXT.8 d29,d23,d4,#2
+ VEXT.8 d27,d22,d23,#4
+ VEXT.8 d8,d22,d23,#2
+ VADDL.S16 q2,d22,d29
+ VMLSL.S16 q1,d26,d30
+ VADD.I16 d27,d27,d28
+ VADD.I16 d26,d8,d23
+ VEXT.8 d28,d24,d25,#6
+ VMLAL.S16 q2,d27,d31
+ VEXT.8 d27,d24,d25,#4
+ VEXT.8 d29,d25,d6,#2
+ VADD.I16 d27,d27,d28
+ VEXT.8 d8,d24,d25,#2
+ VADDL.S16 q3,d24,d29
+ VMLSL.S16 q2,d26,d30
+ VMLAL.S16 q3,d27,d31
+ VADD.I16 d8,d8,d25
+ VMLSL.S16 q3,d8,d30
+ VQRSHRUN.S32 d0,q0,#10
+ VQRSHRUN.S32 d2,q1,#10
+ VQRSHRUN.S32 d4,q2,#10
+ VQRSHRUN.S32 d6,q3,#10
+ VQMOVN.U16 d0,q0
+ VQMOVN.U16 d2,q1
+ VQMOVN.U16 d4,q2
+ VQMOVN.U16 d6,q3
+ POP {r4-r12,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.S
new file mode 100644
index 0000000..40e141b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe_s.S
@@ -0,0 +1,72 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ .func armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe:
+ PUSH {r4-r12,lr}
+ VLD1.8 {d22,d23},[r0],r1
+ VEXT.8 d10,d22,d23,#5
+ VEXT.8 d12,d22,d23,#1
+ VEXT.8 d14,d22,d23,#2
+ VEXT.8 d15,d22,d23,#3
+ VEXT.8 d13,d22,d23,#4
+ VADDL.U8 q11,d22,d10
+ VADDL.U8 q4,d14,d15
+ VADDL.U8 q6,d12,d13
+ VLD1.8 {d24,d25},[r0],r1
+ VMLA.I16 d22,d8,d31
+ VMUL.I16 d8,d12,d30
+ VEXT.8 d10,d24,d25,#5
+ VEXT.8 d12,d24,d25,#1
+ VEXT.8 d16,d24,d25,#2
+ VEXT.8 d17,d24,d25,#3
+ VEXT.8 d13,d24,d25,#4
+ VADDL.U8 q12,d24,d10
+ VSUB.I16 d22,d22,d8
+ VADDL.U8 q4,d16,d17
+ VADDL.U8 q6,d12,d13
+ VLD1.8 {d26,d27},[r0],r1
+ VMLA.I16 d24,d8,d31
+ VMUL.I16 d8,d12,d30
+ VEXT.8 d10,d26,d27,#5
+ VEXT.8 d12,d26,d27,#1
+ VEXT.8 d18,d26,d27,#2
+ VEXT.8 d19,d26,d27,#3
+ VEXT.8 d13,d26,d27,#4
+ VADDL.U8 q13,d26,d10
+ VSUB.I16 d24,d24,d8
+ VADDL.U8 q4,d18,d19
+ VADDL.U8 q6,d12,d13
+ VLD1.8 {d28,d29},[r0],r1
+ VMLA.I16 d26,d8,d31
+ VMUL.I16 d8,d12,d30
+ VEXT.8 d10,d28,d29,#5
+ VEXT.8 d12,d28,d29,#1
+ VEXT.8 d20,d28,d29,#2
+ VEXT.8 d21,d28,d29,#3
+ VEXT.8 d13,d28,d29,#4
+ VADDL.U8 q14,d28,d10
+ VSUB.I16 d26,d26,d8
+ VADDL.U8 q4,d20,d21
+ VADDL.U8 q6,d12,d13
+ VMLA.I16 d28,d8,d31
+ VMLS.I16 d28,d12,d30
+ VQRSHRUN.S16 d22,q11,#5
+ VQRSHRUN.S16 d24,q12,#5
+ VQRSHRUN.S16 d26,q13,#5
+ VQRSHRUN.S16 d28,q14,#5
+ POP {r4-r12,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.S
new file mode 100644
index 0000000..955846f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe_s.S
@@ -0,0 +1,58 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ .func armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe:
+ PUSH {r4-r12,lr}
+ VLD1.8 {d7},[r0],r1
+ ADD r12,r0,r1,LSL #2
+ VLD1.8 {d8},[r0],r1
+ VLD1.8 {d12},[r12],r1
+ VLD1.8 {d9},[r0],r1
+ VADDL.U8 q0,d7,d12
+ VLD1.8 {d10},[r0],r1
+ VLD1.8 {d13},[r12],r1
+ VLD1.8 {d11},[r0],r1
+ VLD1.8 {d14},[r12],r1
+ VADDL.U8 q8,d8,d11
+ VADDL.U8 q9,d9,d10
+ VLD1.8 {d15},[r12],r1
+ VMLS.I16 d0,d16,d30
+ VMUL.I16 d20,d18,d31
+ VADDL.U8 q8,d9,d12
+ VADDL.U8 q9,d10,d11
+ VADDL.U8 q1,d8,d13
+ VMLS.I16 d2,d16,d30
+ VMUL.I16 d21,d18,d31
+ VADDL.U8 q8,d10,d13
+ VADDL.U8 q9,d11,d12
+ VADDL.U8 q2,d9,d14
+ VMLS.I16 d4,d16,d30
+ VMUL.I16 d22,d18,d31
+ VADDL.U8 q8,d11,d14
+ VADDL.U8 q3,d10,d15
+ VADDL.U8 q9,d12,d13
+ VMLS.I16 d6,d16,d30
+ VADD.I16 d0,d0,d20
+ VADD.I16 d2,d2,d21
+ VADD.I16 d4,d4,d22
+ VMLA.I16 d6,d18,d31
+ VQRSHRUN.S16 d0,q0,#5
+ VQRSHRUN.S16 d2,q1,#5
+ VQRSHRUN.S16 d4,q2,#5
+ VQRSHRUN.S16 d6,q3,#5
+ POP {r4-r12,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Interpolate_Chroma_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Interpolate_Chroma_s.S
new file mode 100644
index 0000000..66520da
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_Interpolate_Chroma_s.S
@@ -0,0 +1,175 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+
+ .section .rodata
+ .align 4
+
+armVCM4P10_WidthBranchTableMVIsNotZero:
+ .word WidthIs2MVIsNotZero, WidthIs2MVIsNotZero
+ .word WidthIs4MVIsNotZero, WidthIs4MVIsNotZero
+ .word WidthIs8MVIsNotZero
+
+armVCM4P10_WidthBranchTableMVIsZero:
+ .word WidthIs2MVIsZero, WidthIs2MVIsZero
+ .word WidthIs4MVIsZero, WidthIs4MVIsZero
+ .word WidthIs8MVIsZero
+
+ .text
+
+ .global armVCM4P10_Interpolate_Chroma
+ .func armVCM4P10_Interpolate_Chroma
+armVCM4P10_Interpolate_Chroma:
+ PUSH {r4-r12,lr}
+ VPUSH {d8-d15}
+ LDRD r6,r7,[sp,#0x70]
+ LDRD r4,r5,[sp,#0x68]
+ RSB r8,r6,#8
+ RSB r9,r7,#8
+ CMN r6,r7
+ MOV r10,#1
+ LDREQ r11, =armVCM4P10_WidthBranchTableMVIsZero
+ SUB lr,r1,r10
+ LDRNE r11, =armVCM4P10_WidthBranchTableMVIsNotZero
+ VLD1.8 {d0},[r0],r10
+ SMULBB r12,r8,r9
+ SMULBB r9,r6,r9
+ VLD1.8 {d1},[r0],lr
+ SMULBB r8,r8,r7
+ SMULBB r6,r6,r7
+ VDUP.8 d12,r12
+ VDUP.8 d13,r9
+ VDUP.8 d14,r8
+ VDUP.8 d15,r6
+ LDR pc,[r11,r4,LSL #1]
+
+WidthIs8MVIsNotZero:
+ VLD1.8 {d2},[r0],r10
+ VMULL.U8 q2,d0,d12
+ VLD1.8 {d3},[r0],lr
+ VMULL.U8 q3,d2,d12
+ VLD1.8 {d16},[r0],r10
+ VMLAL.U8 q2,d1,d13
+ VLD1.8 {d17},[r0],lr
+ VMULL.U8 q11,d16,d12
+ VMLAL.U8 q3,d3,d13
+ VLD1.8 {d18},[r0],r10
+ VMLAL.U8 q2,d2,d14
+ VMLAL.U8 q11,d17,d13
+ VMULL.U8 q12,d18,d12
+ VLD1.8 {d19},[r0],lr
+ VMLAL.U8 q3,d16,d14
+ VLD1.8 {d0},[r0],r10
+ VMLAL.U8 q12,d19,d13
+ VMLAL.U8 q11,d18,d14
+ VMLAL.U8 q2,d3,d15
+ VLD1.8 {d1},[r0],lr
+ VMLAL.U8 q12,d0,d14
+ VMLAL.U8 q3,d17,d15
+ VMLAL.U8 q11,d19,d15
+ SUBS r5,r5,#4
+ VMLAL.U8 q12,d1,d15
+ VQRSHRN.U16 d8,q2,#6
+ VQRSHRN.U16 d9,q3,#6
+ VQRSHRN.U16 d20,q11,#6
+ VST1.64 {d8},[r2],r3
+ VQRSHRN.U16 d21,q12,#6
+ VST1.64 {d9},[r2],r3
+ VST1.64 {d20},[r2],r3
+ VST1.64 {d21},[r2],r3
+ BGT WidthIs8MVIsNotZero
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+
+WidthIs4MVIsNotZero:
+ VLD1.8 {d2},[r0],r10
+ VMULL.U8 q2,d0,d12
+ VMULL.U8 q3,d2,d12
+ VLD1.8 {d3},[r0],lr
+ VMLAL.U8 q2,d1,d13
+ VMLAL.U8 q3,d3,d13
+ VLD1.8 {d0},[r0],r10
+ VMLAL.U8 q2,d2,d14
+ VMLAL.U8 q3,d0,d14
+ VLD1.8 {d1},[r0],lr
+ SUBS r5,r5,#2
+ VMLAL.U8 q3,d1,d15
+ VMLAL.U8 q2,d3,d15
+ VQRSHRN.U16 d9,q3,#6
+ VQRSHRN.U16 d8,q2,#6
+ VST1.32 {d8[0]},[r2],r3
+ VST1.32 {d9[0]},[r2],r3
+ BGT WidthIs4MVIsNotZero
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+
+WidthIs2MVIsNotZero:
+ VLD1.8 {d2},[r0],r10
+ VMULL.U8 q2,d0,d12
+ VMULL.U8 q3,d2,d12
+ VLD1.8 {d3},[r0],lr
+ VMLAL.U8 q2,d1,d13
+ VMLAL.U8 q3,d3,d13
+ VLD1.8 {d0},[r0],r10
+ VMLAL.U8 q2,d2,d14
+ VMLAL.U8 q3,d0,d14
+ VLD1.8 {d1},[r0],lr
+ SUBS r5,r5,#2
+ VMLAL.U8 q3,d1,d15
+ VMLAL.U8 q2,d3,d15
+ VQRSHRN.U16 d9,q3,#6
+ VQRSHRN.U16 d8,q2,#6
+ VST1.16 {d8[0]},[r2],r3
+ VST1.16 {d9[0]},[r2],r3
+ BGT WidthIs2MVIsNotZero
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+
+WidthIs8MVIsZero:
+ SUB r0,r0,r1
+WidthIs8LoopMVIsZero:
+ VLD1.8 {d0},[r0],r1
+ SUBS r5,r5,#2
+ VLD1.8 {d1},[r0],r1
+ VST1.64 {d0},[r2],r3
+ VST1.64 {d1},[r2],r3
+ BGT WidthIs8LoopMVIsZero
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+
+WidthIs4MVIsZero:
+ VLD1.8 {d1},[r0],r1
+ SUBS r5,r5,#2
+ VST1.32 {d0[0]},[r2],r3
+ VLD1.8 {d0},[r0],r1
+ VST1.32 {d1[0]},[r2],r3
+ BGT WidthIs4MVIsZero
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+
+WidthIs2MVIsZero:
+ VLD1.8 {d1},[r0],r1
+ SUBS r5,r5,#2
+ VST1.16 {d0[0]},[r2],r3
+ VLD1.8 {d0},[r0],r1
+ VST1.16 {d1[0]},[r2],r3
+ BGT WidthIs2MVIsZero
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_QuantTables_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_QuantTables_s.S
new file mode 100644
index 0000000..f5d6d1f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_QuantTables_s.S
@@ -0,0 +1,68 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .section .rodata
+ .align 4
+
+ .global armVCM4P10_MFMatrixQPModTable
+ .global armVCM4P10_QPDivIntraTable
+ .global armVCM4P10_QPDivPlusOneTable
+
+;//------------------------------------------------------------------
+;// This table contains (1 << QbitsPlusOne) / 3 Values (Intra case) ,
+;// for values of iQP from 0 to 51 (inclusive).
+;//------------------------------------------------------------------
+
+
+armVCM4P10_QPDivIntraTable:
+ .word 21845, 21845, 21845, 21845, 21845, 21845
+ .word 43690, 43690, 43690, 43690, 43690, 43690
+ .word 87381, 87381, 87381, 87381, 87381, 87381
+ .word 174762, 174762, 174762, 174762, 174762, 174762
+ .word 349525, 349525, 349525, 349525, 349525, 349525
+ .word 699050, 699050, 699050, 699050, 699050, 699050
+ .word 1398101, 1398101, 1398101, 1398101, 1398101, 1398101
+ .word 2796202, 2796202, 2796202, 2796202, 2796202, 2796202
+
+
+;//--------------------------------------------------------------
+;// This table contains armVCM4P10_MFMatrix [iQP % 6][0] entires,
+;// for values of iQP from 0 to 51 (inclusive).
+;//--------------------------------------------------------------
+
+armVCM4P10_MFMatrixQPModTable:
+ .hword 13107, 11916, 10082, 9362, 8192, 7282
+ .hword 13107, 11916, 10082, 9362, 8192, 7282
+ .hword 13107, 11916, 10082, 9362, 8192, 7282
+ .hword 13107, 11916, 10082, 9362, 8192, 7282
+ .hword 13107, 11916, 10082, 9362, 8192, 7282
+ .hword 13107, 11916, 10082, 9362, 8192, 7282
+ .hword 13107, 11916, 10082, 9362, 8192, 7282
+ .hword 13107, 11916, 10082, 9362, 8192, 7282
+ .hword 13107, 11916, 10082, 9362, 8192, 7282
+
+;//---------------------------------------------------------------
+;// This table contains ARM_M4P10_Q_OFFSET + 1 + (iQP / 6) values,
+;// for values of iQP from 0 to 51 (inclusive).
+;//---------------------------------------------------------------
+
+armVCM4P10_QPDivPlusOneTable:
+ .byte 16, 16, 16, 16, 16, 16
+ .byte 17, 17, 17, 17, 17, 17
+ .byte 18, 18, 18, 18, 18, 18
+ .byte 19, 19, 19, 19, 19, 19
+ .byte 20, 20, 20, 20, 20, 20
+ .byte 21, 21, 21, 21, 21, 21
+ .byte 22, 22, 22, 22, 22, 22
+ .byte 23, 23, 23, 23, 23, 23
+ .byte 24, 24, 24, 24, 24, 24
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_TransformResidual4x4_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_TransformResidual4x4_s.S
new file mode 100644
index 0000000..c24d717
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_TransformResidual4x4_s.S
@@ -0,0 +1,52 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_TransformResidual4x4
+ .func armVCM4P10_TransformResidual4x4
+armVCM4P10_TransformResidual4x4:
+ VPUSH {d8}
+ VLD4.16 {d0,d1,d2,d3},[r1]
+ VMOV.I16 d4,#0
+ VADD.I16 d5,d0,d2
+ VSUB.I16 d6,d0,d2
+ VHADD.S16 d7,d1,d4
+ VHADD.S16 d8,d3,d4
+ VSUB.I16 d7,d7,d3
+ VADD.I16 d8,d1,d8
+ VADD.I16 d0,d5,d8
+ VADD.I16 d1,d6,d7
+ VSUB.I16 d2,d6,d7
+ VSUB.I16 d3,d5,d8
+ VTRN.16 d0,d1
+ VTRN.16 d2,d3
+ VTRN.32 q0,q1
+ VADD.I16 d5,d0,d2
+ VSUB.I16 d6,d0,d2
+ VHADD.S16 d7,d1,d4
+ VHADD.S16 d8,d3,d4
+ VSUB.I16 d7,d7,d3
+ VADD.I16 d8,d1,d8
+ VADD.I16 d0,d5,d8
+ VADD.I16 d1,d6,d7
+ VSUB.I16 d2,d6,d7
+ VSUB.I16 d3,d5,d8
+ VRSHR.S16 d0,d0,#6
+ VRSHR.S16 d1,d1,#6
+ VRSHR.S16 d2,d2,#6
+ VRSHR.S16 d3,d3,#6
+ VST1.16 {d0,d1,d2,d3},[r0]
+ VPOP {d8}
+ BX lr
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_UnpackBlock4x4_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_UnpackBlock4x4_s.S
new file mode 100644
index 0000000..c552f8d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/armVCM4P10_UnpackBlock4x4_s.S
@@ -0,0 +1,40 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_UnpackBlock4x4
+ .func armVCM4P10_UnpackBlock4x4
+armVCM4P10_UnpackBlock4x4:
+ PUSH {r4-r8,lr}
+ LDR r2,[r0,#0]
+ MOV r7,#0x1f
+ MOV r4,#0
+ MOV r5,#0
+ LDRB r3,[r2],#1
+ STRD r4,r5,[r1,#0]
+ STRD r4,r5,[r1,#8]
+ STRD r4,r5,[r1,#0x10]
+ STRD r4,r5,[r1,#0x18]
+unpackLoop:
+ TST r3,#0x10
+ LDRNESB r5,[r2,#1]
+ LDRNEB r4,[r2],#2
+ AND r6,r7,r3,LSL #1
+ LDREQSB r4,[r2],#1
+ ORRNE r4,r4,r5,LSL #8
+ TST r3,#0x20
+ LDREQB r3,[r2],#1
+ STRH r4,[r1,r6]
+ BEQ unpackLoop
+ STR r2,[r0,#0]
+ POP {r4-r8,pc}
+ .endfunc
+ .end
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DeblockLuma_I.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DeblockLuma_I.S
new file mode 100644
index 0000000..ba61059
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DeblockLuma_I.S
@@ -0,0 +1,67 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global omxVCM4P10_DeblockLuma_I
+ .func omxVCM4P10_DeblockLuma_I
+omxVCM4P10_DeblockLuma_I:
+ PUSH {r4-r9,lr}
+ MOVS r6,r0
+ SUB sp,sp,#0xc
+ MOV r9,r1
+ MOV r7,r2
+ MOV r8,r3
+ LDR r4,[sp,#0x28]
+ LDR r5,[sp,#0x2c]
+ BEQ L0x58
+ TST r6,#7
+ TSTEQ r9,#7
+ BNE L0x58
+ CMP r7,#0
+ CMPNE r8,#0
+ CMPNE r4,#0
+ BEQ L0x58
+ TST r4,#3
+ BNE L0x58
+ CMP r5,#0
+ BEQ L0x58
+ TST r5,#3
+ BEQ L0x64
+L0x58:
+ MVN r0,#4
+L0x5c:
+ ADD sp,sp,#0xc
+ POP {r4-r9,pc}
+L0x64:
+ STR r4,[sp,#0]
+ MOV r3,r8
+ STR r5,[sp,#4]
+ MOV r2,r7
+ MOV r1,r9
+ MOV r0,r6
+ BL omxVCM4P10_FilterDeblockingLuma_VerEdge_I
+ CMP r0,#0
+ BNE L0x5c
+ ADD r3,r5,#0x10
+ ADD r2,r4,#0x10
+ STR r3,[sp,#4]
+ STR r2,[sp,#0]
+ ADD r3,r8,#2
+ ADD r2,r7,#2
+ MOV r1,r9
+ MOV r0,r6
+ BL omxVCM4P10_FilterDeblockingLuma_HorEdge_I
+ ADD sp,sp,#0xc
+ POP {r4-r9,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S
new file mode 100644
index 0000000..be21ee7
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_DequantTransformResidualFromPairAndAdd_s.S
@@ -0,0 +1,119 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global omxVCM4P10_DequantTransformResidualFromPairAndAdd
+ .func omxVCM4P10_DequantTransformResidualFromPairAndAdd
+omxVCM4P10_DequantTransformResidualFromPairAndAdd:
+ PUSH {r4-r12,lr}
+ VPUSH {d8-d9}
+ SUB sp,sp,#0x20
+ ADD r4,sp,#0
+ LDR r5,[sp,#0x64]
+ MOV r7,r1
+ MOV r8,r2
+ MOV r9,r3
+ CMP r5,#0
+ BEQ L0x114
+ MOV r1,r4
+ BL armVCM4P10_UnpackBlock4x4 ;//
+ LDR r1,[sp,#0x60]
+ LDR r11, =armVCM4P10_QPModuloTable
+ LDR r10, =armVCM4P10_QPDivTable
+ LDR r2, =armVCM4P10_VMatrixU16
+ LDRSB r12,[r11,r1]
+ LDRSB lr,[r10,r1]
+ LDR r10, =0x3020504
+ LDR r1, =0x5040100
+ ADD r2,r2,r12
+ VDUP.32 d7,r1
+ VDUP.32 d9,r10
+ VDUP.16 d5,lr
+ VLD1.8 {d6},[r2]
+ VTBL.8 d8,{d6},d7
+ VTBL.8 d4,{d6},d9
+ CMP r8,#0
+ VLD1.16 {d0,d1,d2,d3},[r4]
+ VSHL.U16 d8,d8,d5
+ VSHL.U16 d4,d4,d5
+ BEQ L1
+ LDRSH r10,[r8,#0]
+L1:
+ VMUL.I16 d0,d0,d8
+ VMUL.I16 d1,d1,d4
+ VMUL.I16 d2,d2,d8
+ VMUL.I16 d3,d3,d4
+ VMOVNE.16 d0[0],r10
+ VTRN.16 d0,d1
+ VTRN.16 d2,d3
+ VTRN.32 q0,q1
+ VMOV.I16 d4,#0
+ VADD.I16 d5,d0,d2
+ VSUB.I16 d6,d0,d2
+ VHADD.S16 d7,d1,d4
+ VHADD.S16 d8,d3,d4
+ VSUB.I16 d7,d7,d3
+ VADD.I16 d8,d1,d8
+ VADD.I16 d0,d5,d8
+ VADD.I16 d1,d6,d7
+ VSUB.I16 d2,d6,d7
+ VSUB.I16 d3,d5,d8
+ VTRN.16 d0,d1
+ VTRN.16 d2,d3
+ VTRN.32 q0,q1
+ VADD.I16 d5,d0,d2
+ VSUB.I16 d6,d0,d2
+ VHADD.S16 d7,d1,d4
+ VHADD.S16 d8,d3,d4
+ VSUB.I16 d7,d7,d3
+ VADD.I16 d8,d1,d8
+ VADD.I16 d0,d5,d8
+ VADD.I16 d1,d6,d7
+ VSUB.I16 d2,d6,d7
+ VSUB.I16 d3,d5,d8
+ VRSHR.S16 d0,d0,#6
+ VRSHR.S16 d1,d1,#6
+ VRSHR.S16 d2,d2,#6
+ VRSHR.S16 d3,d3,#6
+ B L0x130
+L0x114:
+ LDRSH r10,[r8,#0]
+ ADD r10,r10,#0x20
+ ASR r10,r10,#6
+ VDUP.16 d0,r10
+ VDUP.16 d1,r10
+ VDUP.16 d2,r10
+ VDUP.16 d3,r10
+L0x130:
+ LDR r1,[sp,#0x58]
+ LDR r10,[sp,#0x5c]
+ LDR r3,[r7],r1
+ LDR r5,[r7],r1
+ VMOV d4,r3,r5
+ LDR r3,[r7],r1
+ LDR r5,[r7,#0]
+ VMOV d5,r3,r5
+ VADDW.U8 q3,q0,d4
+ VADDW.U8 q4,q1,d5
+ VQMOVUN.S16 d0,q3
+ VQMOVUN.S16 d1,q4
+ VST1.32 {d0[0]},[r9],r10
+ VST1.32 {d0[1]},[r9],r10
+ VST1.32 {d1[0]},[r9],r10
+ VST1.32 {d1[1]},[r9]
+ MOV r0,#0
+ ADD sp,sp,#0x20
+ VPOP {d8-d9}
+ POP {r4-r12,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.S
new file mode 100644
index 0000000..79ba538
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_HorEdge_I_s.S
@@ -0,0 +1,87 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global omxVCM4P10_FilterDeblockingChroma_HorEdge_I
+ .func omxVCM4P10_FilterDeblockingChroma_HorEdge_I
+omxVCM4P10_FilterDeblockingChroma_HorEdge_I:
+ PUSH {r4-r10,lr}
+ VPUSH {d8-d15}
+ VLD1.8 {d0[]},[r2]!
+ SUB r0,r0,r1,LSL #1
+ SUB r0,r0,r1
+ VLD1.8 {d2[]},[r3]!
+ LDR r4,[sp,#0x64]
+ LDR r5,[sp,#0x60]
+ LDR r9, =0x3030303
+ LDR r8, =0x4040404
+ VMOV.I8 d14,#0
+ VMOV.I8 d15,#0x1
+ VMOV.I16 d1,#0x4
+ MOV r7,#0x40000000
+L0x38:
+ LDR r6,[r4],#8
+ VLD1.8 {d6},[r0],r1
+ VLD1.8 {d5},[r0],r1
+ CMP r6,#0
+ VLD1.8 {d4},[r0],r1
+ VLD1.8 {d8},[r0],r1
+ VABD.U8 d19,d6,d4
+ VLD1.8 {d9},[r0],r1
+ VABD.U8 d13,d4,d8
+ VLD1.8 {d10},[r0],r1
+ BEQ L0xe4
+ VABD.U8 d12,d5,d4
+ VABD.U8 d18,d9,d8
+ VCGT.U8 d16,d0,d13
+ VMOV.32 d26[0],r6
+ VMAX.U8 d12,d18,d12
+ VMOVL.U8 q13,d26
+ VABD.U8 d17,d10,d8
+ VCGT.S16 d27,d26,#0
+ VCGT.U8 d12,d2,d12
+ VCGT.U8 d19,d2,d19
+ VAND d16,d16,d27
+ TST r6,r9
+ VCGT.U8 d17,d2,d17
+ VAND d16,d16,d12
+ VAND d12,d16,d17
+ VAND d17,d16,d19
+ BLNE armVCM4P10_DeblockingChromabSLT4_unsafe
+ TST r6,r8
+ SUB r0,r0,r1,LSL #2
+ VTST.16 d26,d26,d1
+ BLNE armVCM4P10_DeblockingChromabSGE4_unsafe
+ VBIT d29,d13,d26
+ VBIT d24,d31,d26
+ VBIF d29,d4,d16
+ VBIF d24,d8,d16
+ VST1.8 {d29},[r0],r1
+ ADDS r7,r7,r7
+ VST1.8 {d24},[r0],r1
+ BNE L0x38
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r10,pc}
+L0xe4:
+ VLD1.8 {d0[]},[r2]
+ SUB r0,r0,r1,LSL #1
+ ADDS r7,r7,r7
+ VLD1.8 {d2[]},[r3]
+ ADD r5,r5,#4
+ BNE L0x38
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r10,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.S
new file mode 100644
index 0000000..dcdddbe
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingChroma_VerEdge_I_s.S
@@ -0,0 +1,123 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global omxVCM4P10_FilterDeblockingChroma_VerEdge_I
+ .func omxVCM4P10_FilterDeblockingChroma_VerEdge_I
+omxVCM4P10_FilterDeblockingChroma_VerEdge_I:
+ PUSH {r4-r12,lr}
+ VPUSH {d8-d15}
+ VLD1.8 {d0[]},[r2]!
+ SUB r0,r0,#4
+ VLD1.8 {d2[]},[r3]!
+ LDR r4,[sp,#0x6c]
+ LDR r5,[sp,#0x68]
+ LDR r8, =0x4040404
+ LDR r9, =0x3030303
+ VMOV.I8 d14,#0
+ VMOV.I8 d15,#0x1
+ VMOV.I16 d1,#0x4
+ MOV r7,#0x40000000
+L0x34:
+ LDR r6,[r4],#8
+ ADD r10,r0,r1
+ ADD lr,r1,r1
+ VLD1.8 {d7},[r0],lr
+ VLD1.8 {d8},[r10],lr
+ VLD1.8 {d5},[r0],lr
+ VLD1.8 {d10},[r10],lr
+ VLD1.8 {d6},[r0],lr
+ VLD1.8 {d9},[r10],lr
+ VLD1.8 {d4},[r0],lr
+ VLD1.8 {d11},[r10],lr
+ VZIP.8 d7,d8
+ VZIP.8 d5,d10
+ VZIP.8 d6,d9
+ VZIP.8 d4,d11
+ VZIP.16 d7,d5
+ VZIP.16 d8,d10
+ VZIP.16 d6,d4
+ VZIP.16 d9,d11
+ VTRN.32 d7,d6
+ VTRN.32 d5,d4
+ VTRN.32 d10,d11
+ VTRN.32 d8,d9
+ CMP r6,#0
+ VABD.U8 d19,d6,d4
+ VABD.U8 d13,d4,d8
+ BEQ L0x170
+ VABD.U8 d12,d5,d4
+ VABD.U8 d18,d9,d8
+ VMOV.32 d26[0],r6
+ VCGT.U8 d16,d0,d13
+ VMAX.U8 d12,d18,d12
+ VMOVL.U8 q13,d26
+ VABD.U8 d17,d10,d8
+ VCGT.S16 d27,d26,#0
+ VCGT.U8 d12,d2,d12
+ VCGT.U8 d19,d2,d19
+ VAND d16,d16,d27
+ TST r6,r9
+ VCGT.U8 d17,d2,d17
+ VAND d16,d16,d12
+ VAND d12,d16,d17
+ VAND d17,d16,d19
+ BLNE armVCM4P10_DeblockingChromabSLT4_unsafe
+ TST r6,r8
+ SUB r0,r0,r1,LSL #3
+ VTST.16 d26,d26,d1
+ BLNE armVCM4P10_DeblockingChromabSGE4_unsafe
+ VBIT d29,d13,d26
+ VBIT d24,d31,d26
+ ADD r10,r0,#3
+ VBIF d29,d4,d16
+ ADD r12,r10,r1
+ ADD lr,r1,r1
+ VBIF d24,d8,d16
+ ADDS r7,r7,r7
+ VST1.8 {d29[0]},[r10],lr
+ VST1.8 {d29[1]},[r12],lr
+ VST1.8 {d29[2]},[r10],lr
+ VST1.8 {d29[3]},[r12],lr
+ VST1.8 {d29[4]},[r10],lr
+ VST1.8 {d29[5]},[r12],lr
+ VST1.8 {d29[6]},[r10],lr
+ VST1.8 {d29[7]},[r12],lr
+ ADD r12,r0,#4
+ ADD r10,r12,r1
+ VST1.8 {d24[0]},[r12],lr
+ VST1.8 {d24[1]},[r10],lr
+ VST1.8 {d24[2]},[r12],lr
+ VST1.8 {d24[3]},[r10],lr
+ VST1.8 {d24[4]},[r12],lr
+ VST1.8 {d24[5]},[r10],lr
+ VST1.8 {d24[6]},[r12],lr
+ VST1.8 {d24[7]},[r10],lr
+ ADD r0,r0,#4
+ BNE L0x34
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+L0x170:
+ VLD1.8 {d0[]},[r2]
+ ADD r0,r0,#4
+ SUB r0,r0,r1,LSL #3
+ ADDS r7,r7,r7
+ VLD1.8 {d2[]},[r3]
+ ADD r5,r5,#4
+ BNE L0x34
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.S
new file mode 100644
index 0000000..9755899
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_HorEdge_I_s.S
@@ -0,0 +1,107 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global omxVCM4P10_FilterDeblockingLuma_HorEdge_I
+ .func omxVCM4P10_FilterDeblockingLuma_HorEdge_I
+omxVCM4P10_FilterDeblockingLuma_HorEdge_I:
+ PUSH {r4-r12,lr}
+ VPUSH {d8-d15}
+ ADD r7,r2,#1
+ ADD r8,r3,#1
+ VLD1.8 {d0[]},[r2]
+ SUB r0,r0,r1,LSL #2
+ VLD1.8 {d2[]},[r3]
+ LDR r4,[sp,#0x6c]
+ LDR r5,[sp,#0x68]
+ MOV r11,#0
+ VMOV.I8 d14,#0
+ VMOV.I8 d15,#0x1
+ ADD r10,r1,r1
+ MOV r9,#0x55000000
+L0x38:
+ LDRH r12,[r4],#2
+ ADD r6,r0,r1
+ CMP r12,#0
+ BEQ L0xe4
+ VLD1.8 {d7},[r0],r10
+ VLD1.8 {d6},[r6],r10
+ VLD1.8 {d5},[r0],r10
+ VLD1.8 {d4},[r6],r10
+ VLD1.8 {d8},[r0],r10
+ VABD.U8 d12,d4,d5
+ VLD1.8 {d9},[r6]
+ VABD.U8 d13,d8,d4
+ VLD1.8 {d10},[r0],r1
+ VABD.U8 d18,d9,d8
+ VABD.U8 d19,d6,d4
+ VCGT.U8 d16,d0,d13
+ TST r12,#0xff
+ VMAX.U8 d12,d18,d12
+ VABD.U8 d17,d10,d8
+ VMOVEQ.32 d16[0],r11
+ TST r12,#0xff00
+ VCGT.U8 d19,d2,d19
+ VCGT.U8 d12,d2,d12
+ VMOVEQ.32 d16[1],r11
+ VCGT.U8 d17,d2,d17
+ VLD1.8 {d11},[r0]
+ VAND d16,d16,d12
+ TST r12,#4
+ VAND d12,d16,d17
+ VAND d17,d16,d19
+ BNE L0xf8
+ SUB r0,r0,r1,LSL #2
+ SUB r0,r0,r1
+ BL armVCM4P10_DeblockingLumabSLT4_unsafe
+ VST1.8 {d30},[r0],r1
+ VST1.8 {d29},[r0],r1
+ SUB r6,r0,r1,LSL #2
+ VST1.8 {d24},[r0],r1
+ ADDS r9,r9,r9
+ VST1.8 {d25},[r0]
+ ADD r0,r6,#8
+ BCC L0x38
+ B L0x130
+L0xe4:
+ ADD r0,r0,#8
+ ADDS r9,r9,r9
+ ADD r5,r5,#2
+ BCC L0x38
+ B L0x130
+L0xf8:
+ SUB r0,r0,r1,LSL #2
+ SUB r0,r0,r1,LSL #1
+ BL armVCM4P10_DeblockingLumabSGE4_unsafe
+ VST1.8 {d31},[r0],r1
+ VST1.8 {d30},[r0],r1
+ VST1.8 {d29},[r0],r1
+ SUB r6,r0,r1,LSL #2
+ VST1.8 {d24},[r0],r1
+ ADDS r9,r9,r9
+ VST1.8 {d25},[r0],r1
+ ADD r5,r5,#2
+ VST1.8 {d28},[r0]
+ ADD r0,r6,#8
+ BCC L0x38
+L0x130:
+ SUB r0,r0,#0x10
+ VLD1.8 {d0[]},[r7]
+ ADD r0,r0,r1,LSL #2
+ VLD1.8 {d2[]},[r8]
+ BNE L0x38
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.S
new file mode 100644
index 0000000..66cc32e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_FilterDeblockingLuma_VerEdge_I_s.S
@@ -0,0 +1,157 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global omxVCM4P10_FilterDeblockingLuma_VerEdge_I
+ .func omxVCM4P10_FilterDeblockingLuma_VerEdge_I
+omxVCM4P10_FilterDeblockingLuma_VerEdge_I:
+ PUSH {r4-r12,lr}
+ VPUSH {d8-d15}
+ ADD r7,r2,#1
+ ADD r8,r3,#1
+ VLD1.8 {d0[]},[r2]
+ SUB r0,r0,#4
+ VLD1.8 {d2[]},[r3]
+ LDR r4,[sp,#0x6c]
+ LDR r5,[sp,#0x68]
+ MOV r6,#0
+ VMOV.I8 d14,#0
+ VMOV.I8 d15,#0x1
+ MOV r9,#0x11000000
+ ADD r11,r1,r1
+L0x38:
+ LDRH r12,[r4],#4
+ CMP r12,#0
+ BEQ L0x160
+ ADD r10,r0,r1
+ VLD1.8 {d7},[r0],r11
+ VLD1.8 {d8},[r10],r11
+ VLD1.8 {d5},[r0],r11
+ VZIP.8 d7,d8
+ VLD1.8 {d10},[r10],r11
+ VLD1.8 {d6},[r0],r11
+ VZIP.8 d5,d10
+ VLD1.8 {d9},[r10],r11
+ VLD1.8 {d4},[r0],r11
+ VLD1.8 {d11},[r10],r11
+ VZIP.8 d6,d9
+ VZIP.16 d8,d10
+ VZIP.8 d4,d11
+ SUB r0,r0,r1,LSL #3
+ VZIP.16 d7,d5
+ VZIP.16 d9,d11
+ VZIP.16 d6,d4
+ VTRN.32 d8,d9
+ VTRN.32 d5,d4
+ VTRN.32 d10,d11
+ VTRN.32 d7,d6
+ VABD.U8 d13,d4,d8
+ VABD.U8 d12,d5,d4
+ VABD.U8 d18,d9,d8
+ VABD.U8 d19,d6,d4
+ TST r12,#0xff
+ VCGT.U8 d16,d0,d13
+ VMAX.U8 d12,d18,d12
+ VABD.U8 d17,d10,d8
+ VMOVEQ.32 d16[0],r6
+ TST r12,#0xff00
+ VCGT.U8 d19,d2,d19
+ VCGT.U8 d12,d2,d12
+ VMOVEQ.32 d16[1],r6
+ VCGT.U8 d17,d2,d17
+ VAND d16,d16,d12
+ TST r12,#4
+ VAND d12,d16,d17
+ VAND d17,d16,d19
+ BNE L0x17c
+ BL armVCM4P10_DeblockingLumabSLT4_unsafe
+ VZIP.8 d7,d6
+ VZIP.8 d30,d29
+ VZIP.8 d24,d25
+ VZIP.8 d10,d11
+ VZIP.16 d7,d30
+ ADD r10,r0,r1
+ VZIP.16 d24,d10
+ VZIP.16 d25,d11
+ VZIP.16 d6,d29
+ VTRN.32 d7,d24
+ VTRN.32 d30,d10
+ VTRN.32 d6,d25
+ VTRN.32 d29,d11
+ VST1.8 {d7},[r0],r11
+ VST1.8 {d24},[r10],r11
+ VST1.8 {d30},[r0],r11
+ VST1.8 {d10},[r10],r11
+ VST1.8 {d6},[r0],r11
+ VST1.8 {d25},[r10],r11
+ ADDS r9,r9,r9
+ VST1.8 {d29},[r0],r11
+ ADD r5,r5,#2
+ VST1.8 {d11},[r10],r1
+ SUB r0,r0,r1,LSL #3
+ VLD1.8 {d0[]},[r7]
+ ADD r0,r0,#4
+ VLD1.8 {d2[]},[r8]
+ BCC L0x38
+ B L0x1f0
+L0x160:
+ ADD r0,r0,#4
+ ADDS r9,r9,r9
+ VLD1.8 {d0[]},[r7]
+ ADD r5,r5,#4
+ VLD1.8 {d2[]},[r8]
+ BCC L0x38
+ B L0x1f0
+L0x17c:
+ BL armVCM4P10_DeblockingLumabSGE4_unsafe
+ VZIP.8 d7,d31
+ VZIP.8 d30,d29
+ VZIP.8 d24,d25
+ VZIP.8 d28,d11
+ VZIP.16 d7,d30
+ ADD r10,r0,r1
+ VZIP.16 d24,d28
+ VZIP.16 d25,d11
+ VZIP.16 d31,d29
+ VTRN.32 d7,d24
+ VTRN.32 d30,d28
+ VTRN.32 d31,d25
+ VTRN.32 d29,d11
+ VST1.8 {d7},[r0],r11
+ VST1.8 {d24},[r10],r11
+ VST1.8 {d30},[r0],r11
+ VST1.8 {d28},[r10],r11
+ VST1.8 {d31},[r0],r11
+ VST1.8 {d25},[r10],r11
+ ADDS r9,r9,r9
+ VST1.8 {d29},[r0],r11
+ ADD r5,r5,#4
+ VST1.8 {d11},[r10],r11
+ SUB r0,r0,r1,LSL #3
+ VLD1.8 {d0[]},[r7]
+ ADD r0,r0,#4
+ VLD1.8 {d2[]},[r8]
+ BCC L0x38
+L0x1f0:
+ SUB r4,r4,#0xe
+ SUB r5,r5,#0xe
+ SUB r0,r0,#0x10
+ VLD1.8 {d0[]},[r2]
+ ADD r0,r0,r1,LSL #3
+ VLD1.8 {d2[]},[r3]
+ BNE L0x38
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_InterpolateLuma_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_InterpolateLuma_s.S
new file mode 100644
index 0000000..76c3d7d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_InterpolateLuma_s.S
@@ -0,0 +1,323 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global omxVCM4P10_InterpolateLuma
+ .func omxVCM4P10_InterpolateLuma
+omxVCM4P10_InterpolateLuma:
+ PUSH {r4-r12,lr}
+ VPUSH {d8-d15}
+ SUB sp,sp,#0x10
+ LDR r6,[sp,#0x78]
+ LDR r7,[sp,#0x7c]
+ LDR r5,[sp,#0x80]
+ LDR r4,[sp,#0x84]
+ ADD r6,r6,r7,LSL #2
+ ADD r11,sp,#0
+ VMOV.I16 d31,#0x14
+ VMOV.I16 d30,#0x5
+L0x2c:
+ STM r11,{r0-r3}
+ ADD pc,pc,r6,LSL #2
+ B L0x3f0
+ B L0x78
+ B L0xa8
+ B L0xdc
+ B L0x100
+ B L0x134
+ B L0x168
+ B L0x1a8
+ B L0x1f0
+ B L0x234
+ B L0x258
+ B L0x2b0
+ B L0x2d8
+ B L0x330
+ B L0x364
+ B L0x3a8
+ B L0x3f0
+L0x78:
+ ADD r12,r0,r1,LSL #1
+ VLD1.8 {d9},[r0],r1
+ VLD1.8 {d11},[r12],r1
+ VLD1.8 {d10},[r0]
+ VLD1.8 {d12},[r12]
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d9[0]},[r2],r3
+ VST1.32 {d11[0]},[r12],r3
+ VST1.32 {d10[0]},[r2]
+ VST1.32 {d12[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0xa8:
+ SUB r0,r0,#2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ VRHADD.U8 d22,d22,d14
+ VRHADD.U8 d26,d26,d18
+ VRHADD.U8 d24,d24,d16
+ VRHADD.U8 d28,d28,d20
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d22[0]},[r2],r3
+ VST1.32 {d26[0]},[r12],r3
+ VST1.32 {d24[0]},[r2]
+ VST1.32 {d28[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0xdc:
+ SUB r0,r0,#2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d22[0]},[r2],r3
+ VST1.32 {d26[0]},[r12],r3
+ VST1.32 {d24[0]},[r2]
+ VST1.32 {d28[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0x100:
+ SUB r0,r0,#2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ VRHADD.U8 d22,d22,d15
+ VRHADD.U8 d26,d26,d19
+ VRHADD.U8 d24,d24,d17
+ VRHADD.U8 d28,d28,d21
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d22[0]},[r2],r3
+ VST1.32 {d26[0]},[r12],r3
+ VST1.32 {d24[0]},[r2]
+ VST1.32 {d28[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0x134:
+ SUB r0,r0,r1,LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ VRHADD.U8 d0,d0,d9
+ VRHADD.U8 d4,d4,d11
+ VRHADD.U8 d2,d2,d10
+ VRHADD.U8 d6,d6,d12
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d0[0]},[r2],r3
+ VST1.32 {d4[0]},[r12],r3
+ VST1.32 {d2[0]},[r2]
+ VST1.32 {d6[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0x168:
+ MOV r8,r0
+ SUB r0,r0,r1,LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ SUB r0,r8,#2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ VRHADD.U8 d22,d22,d0
+ VRHADD.U8 d26,d26,d4
+ VRHADD.U8 d24,d24,d2
+ VRHADD.U8 d28,d28,d6
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d22[0]},[r2],r3
+ VST1.32 {d26[0]},[r12],r3
+ VST1.32 {d24[0]},[r2]
+ VST1.32 {d28[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0x1a8:
+ SUB r0,r0,r1,LSL #1
+ SUB r0,r0,#2
+ BL armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+ VQRSHRUN.S16 d14,q7,#5
+ VQRSHRUN.S16 d16,q8,#5
+ VQRSHRUN.S16 d18,q9,#5
+ VQRSHRUN.S16 d20,q10,#5
+ VRHADD.U8 d0,d0,d14
+ VRHADD.U8 d4,d4,d18
+ VRHADD.U8 d2,d2,d16
+ VRHADD.U8 d6,d6,d20
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d0[0]},[r2],r3
+ VST1.32 {d4[0]},[r12],r3
+ VST1.32 {d2[0]},[r2]
+ VST1.32 {d6[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0x1f0:
+ MOV r8,r0
+ ADD r0,r0,#1
+ SUB r0,r0,r1,LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ SUB r0,r8,#2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ VRHADD.U8 d22,d22,d0
+ VRHADD.U8 d26,d26,d4
+ VRHADD.U8 d24,d24,d2
+ VRHADD.U8 d28,d28,d6
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d22[0]},[r2],r3
+ VST1.32 {d26[0]},[r12],r3
+ VST1.32 {d24[0]},[r2]
+ VST1.32 {d28[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0x234:
+ SUB r0,r0,r1,LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d0[0]},[r2],r3
+ VST1.32 {d4[0]},[r12],r3
+ VST1.32 {d2[0]},[r2]
+ VST1.32 {d6[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0x258:
+ SUB r0,r0,r1,LSL #1
+ SUB r0,r0,#2
+ BL armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+ VEXT.8 d18,d18,d19,#4
+ VEXT.8 d20,d20,d21,#4
+ VEXT.8 d22,d22,d23,#4
+ VEXT.8 d24,d24,d25,#4
+ VQRSHRUN.S16 d14,q9,#5
+ VQRSHRUN.S16 d16,q10,#5
+ VQRSHRUN.S16 d18,q11,#5
+ VQRSHRUN.S16 d20,q12,#5
+ VRHADD.U8 d0,d0,d14
+ VRHADD.U8 d4,d4,d18
+ VRHADD.U8 d2,d2,d16
+ VRHADD.U8 d6,d6,d20
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d0[0]},[r2],r3
+ VST1.32 {d4[0]},[r12],r3
+ VST1.32 {d2[0]},[r2]
+ VST1.32 {d6[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0x2b0:
+ SUB r0,r0,r1,LSL #1
+ SUB r0,r0,#2
+ BL armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d0[0]},[r2],r3
+ VST1.32 {d4[0]},[r12],r3
+ VST1.32 {d2[0]},[r2]
+ VST1.32 {d6[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0x2d8:
+ SUB r0,r0,r1,LSL #1
+ SUB r0,r0,#2
+ BL armVCM4P10_InterpolateLuma_HalfDiagVerHor4x4_unsafe
+ VEXT.8 d18,d18,d19,#6
+ VEXT.8 d20,d20,d21,#6
+ VEXT.8 d22,d22,d23,#6
+ VEXT.8 d24,d24,d25,#6
+ VQRSHRUN.S16 d14,q9,#5
+ VQRSHRUN.S16 d16,q10,#5
+ VQRSHRUN.S16 d18,q11,#5
+ VQRSHRUN.S16 d20,q12,#5
+ VRHADD.U8 d0,d0,d14
+ VRHADD.U8 d4,d4,d18
+ VRHADD.U8 d2,d2,d16
+ VRHADD.U8 d6,d6,d20
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d0[0]},[r2],r3
+ VST1.32 {d4[0]},[r12],r3
+ VST1.32 {d2[0]},[r2]
+ VST1.32 {d6[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0x330:
+ SUB r0,r0,r1,LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ VRHADD.U8 d0,d0,d10
+ VRHADD.U8 d4,d4,d12
+ VRHADD.U8 d2,d2,d11
+ VRHADD.U8 d6,d6,d13
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d0[0]},[r2],r3
+ VST1.32 {d4[0]},[r12],r3
+ VST1.32 {d2[0]},[r2]
+ VST1.32 {d6[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0x364:
+ MOV r8,r0
+ SUB r0,r0,r1,LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ ADD r0,r8,r1
+ SUB r0,r0,#2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ VRHADD.U8 d22,d22,d0
+ VRHADD.U8 d26,d26,d4
+ VRHADD.U8 d24,d24,d2
+ VRHADD.U8 d28,d28,d6
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d22[0]},[r2],r3
+ VST1.32 {d26[0]},[r12],r3
+ VST1.32 {d24[0]},[r2]
+ VST1.32 {d28[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0x3a8:
+ SUB r0,r0,r1,LSL #1
+ SUB r0,r0,#2
+ BL armVCM4P10_InterpolateLuma_HalfDiagHorVer4x4_unsafe
+ VQRSHRUN.S16 d14,q8,#5
+ VQRSHRUN.S16 d16,q9,#5
+ VQRSHRUN.S16 d18,q10,#5
+ VQRSHRUN.S16 d20,q11,#5
+ VRHADD.U8 d0,d0,d14
+ VRHADD.U8 d4,d4,d18
+ VRHADD.U8 d2,d2,d16
+ VRHADD.U8 d6,d6,d20
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d0[0]},[r2],r3
+ VST1.32 {d4[0]},[r12],r3
+ VST1.32 {d2[0]},[r2]
+ VST1.32 {d6[0]},[r12]
+ ADD r11,sp,#0
+ B L0x434
+L0x3f0:
+ MOV r8,r0
+ ADD r0,r0,#1
+ SUB r0,r0,r1,LSL #1
+ BL armVCM4P10_InterpolateLuma_HalfVer4x4_unsafe
+ ADD r0,r8,r1
+ SUB r0,r0,#2
+ BL armVCM4P10_InterpolateLuma_HalfHor4x4_unsafe
+ VRHADD.U8 d22,d22,d0
+ VRHADD.U8 d26,d26,d4
+ VRHADD.U8 d24,d24,d2
+ VRHADD.U8 d28,d28,d6
+ ADD r12,r2,r3,LSL #1
+ VST1.32 {d22[0]},[r2],r3
+ VST1.32 {d26[0]},[r12],r3
+ VST1.32 {d24[0]},[r2]
+ VST1.32 {d28[0]},[r12]
+ ADD r11,sp,#0
+L0x434:
+ LDM r11,{r0-r3}
+ SUBS r5,r5,#4
+ ADD r0,r0,#4
+ ADD r2,r2,#4
+ BGT L0x2c
+ SUBS r4,r4,#4
+ LDR r5,[sp,#0x80]
+ ADD r11,sp,#0
+ ADD r0,r0,r1,LSL #2
+ ADD r2,r2,r3,LSL #2
+ SUB r0,r0,r5
+ SUB r2,r2,r5
+ BGT L0x2c
+ MOV r0,#0
+ ADD sp,sp,#0x10
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntraChroma_8x8_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntraChroma_8x8_s.S
new file mode 100644
index 0000000..0d49e4b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntraChroma_8x8_s.S
@@ -0,0 +1,217 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .section .rodata
+ .align 4
+
+armVCM4P10_pIndexTable8x8:
+ .word OMX_VC_CHROMA_DC, OMX_VC_CHROMA_HOR
+ .word OMX_VC_CHROMA_VERT, OMX_VC_CHROMA_PLANE
+
+armVCM4P10_MultiplierTableChroma8x8:
+ .hword 3, 2, 1,4
+ .hword -3,-2,-1,0
+ .hword 1, 2, 3,4
+
+
+ .text
+ .global omxVCM4P10_PredictIntraChroma_8x8
+ .func omxVCM4P10_PredictIntraChroma_8x8
+omxVCM4P10_PredictIntraChroma_8x8:
+ PUSH {r4-r10,lr}
+ VPUSH {d8-d15}
+ LDR r8, =armVCM4P10_pIndexTable8x8
+ LDR r6,[sp,#0x68]
+ LDR r4,[sp,#0x60]
+ LDR r5,[sp,#0x64]
+ LDR r7,[sp,#0x6c]
+ LDR pc,[r8,r6,LSL #2]
+OMX_VC_CHROMA_DC:
+ TST r7,#2
+ BEQ L0xe8
+ ADD r9,r0,r4
+ ADD r10,r4,r4
+ VLD1.8 {d1[0]},[r0],r10
+ VLD1.8 {d1[1]},[r9],r10
+ VLD1.8 {d1[2]},[r0],r10
+ VLD1.8 {d1[3]},[r9],r10
+ VLD1.8 {d1[4]},[r0],r10
+ VLD1.8 {d1[5]},[r9],r10
+ VLD1.8 {d1[6]},[r0],r10
+ VLD1.8 {d1[7]},[r9]
+ TST r7,#1
+ BEQ L0xcc
+ VLD1.8 {d0},[r1]
+ MOV r0,#0
+ VPADDL.U8 d2,d0
+ VPADDL.U16 d3,d2
+ VPADDL.U8 d2,d1
+ VPADDL.U16 d1,d2
+ VADD.I32 d2,d3,d1
+ VRSHR.U32 d2,d2,#3
+ VRSHR.U32 d3,d3,#2
+ VRSHR.U32 d1,d1,#2
+ VMOV.I8 d5,#0xc
+ VMOV.I8 d6,#0x4
+ VSHL.I64 d5,d5,#32
+ VSHR.U64 d6,d6,#32
+ VADD.I8 d6,d6,d5
+ VTBL.8 d0,{d2-d3},d5
+ VTBL.8 d4,{d1-d2},d6
+L0x9c:
+ ADD r9,r3,r5
+ ADD r10,r5,r5
+ VST1.8 {d0},[r3],r10
+ VST1.8 {d0},[r9],r10
+ VST1.8 {d0},[r3],r10
+ VST1.8 {d0},[r9],r10
+ VST1.8 {d4},[r3],r10
+ VST1.8 {d4},[r9],r10
+ VST1.8 {d4},[r3],r10
+ VST1.8 {d4},[r9]
+ VPOP {d8-d15}
+ POP {r4-r10,pc}
+L0xcc:
+ MOV r0,#0
+ VPADDL.U8 d2,d1
+ VPADDL.U16 d1,d2
+ VRSHR.U32 d1,d1,#2
+ VDUP.8 d0,d1[0]
+ VDUP.8 d4,d1[4]
+ B L0x9c
+L0xe8:
+ TST r7,#1
+ BEQ L0x114
+ VLD1.8 {d0},[r1]
+ MOV r0,#0
+ VPADDL.U8 d2,d0
+ VPADDL.U16 d3,d2
+ VRSHR.U32 d3,d3,#2
+ VMOV.I8 d5,#0x4
+ VSHL.I64 d5,d5,#32
+ VTBL.8 d0,{d3},d5
+ B L0x11c
+L0x114:
+ VMOV.I8 d0,#0x80
+ MOV r0,#0
+L0x11c:
+ ADD r9,r3,r5
+ ADD r10,r5,r5
+ VST1.8 {d0},[r3],r10
+ VST1.8 {d0},[r9],r10
+ VST1.8 {d0},[r3],r10
+ VST1.8 {d0},[r9],r10
+ VST1.8 {d0},[r3],r10
+ VST1.8 {d0},[r9],r10
+ VST1.8 {d0},[r3],r10
+ VST1.8 {d0},[r9]
+ VPOP {d8-d15}
+ POP {r4-r10,pc}
+OMX_VC_CHROMA_VERT:
+ VLD1.8 {d0},[r1]
+ MOV r0,#0
+ B L0x11c
+OMX_VC_CHROMA_HOR:
+ ADD r9,r0,r4
+ ADD r10,r4,r4
+ VLD1.8 {d0[]},[r0],r10
+ VLD1.8 {d1[]},[r9],r10
+ VLD1.8 {d2[]},[r0],r10
+ VLD1.8 {d3[]},[r9],r10
+ VLD1.8 {d4[]},[r0],r10
+ VLD1.8 {d5[]},[r9],r10
+ VLD1.8 {d6[]},[r0],r10
+ VLD1.8 {d7[]},[r9]
+ B L0x28c
+OMX_VC_CHROMA_PLANE:
+ ADD r9,r0,r4
+ ADD r10,r4,r4
+ VLD1.8 {d0},[r1]
+ VLD1.8 {d2[0]},[r2]
+ VLD1.8 {d1[0]},[r0],r10
+ VLD1.8 {d1[1]},[r9],r10
+ VLD1.8 {d1[2]},[r0],r10
+ VLD1.8 {d1[3]},[r9],r10
+ VLD1.8 {d1[4]},[r0],r10
+ VLD1.8 {d1[5]},[r9],r10
+ VLD1.8 {d1[6]},[r0],r10
+ VLD1.8 {d1[7]},[r9]
+ VREV64.8 d3,d0
+ VSUBL.U8 q3,d3,d2
+ VSHR.U64 d3,d3,#8
+ VSUBL.U8 q2,d3,d0
+ VREV64.8 d3,d1
+ VSUBL.U8 q7,d3,d2
+ VSHR.U64 d3,d3,#8
+ VSUBL.U8 q6,d3,d1
+ LDR r2, =armVCM4P10_MultiplierTableChroma8x8
+ VSHL.I64 d4,d4,#16
+ VEXT.8 d9,d4,d6,#2
+ VLD1.16 {d10},[r2]!
+ VSHL.I64 d12,d12,#16
+ VEXT.8 d16,d12,d14,#2
+ VMUL.I16 d11,d9,d10
+ VMUL.I16 d3,d16,d10
+ VPADD.I16 d3,d11,d3
+ VPADDL.S16 d3,d3
+ VSHL.I32 d2,d3,#4
+ VADD.I32 d3,d3,d2
+ VLD1.16 {d10,d11},[r2]
+ VRSHR.S32 d3,d3,#5
+ VADDL.U8 q0,d0,d1
+ VDUP.16 q0,d1[3]
+ VSHL.I16 q0,q0,#4
+ VDUP.16 q2,d3[0]
+ VDUP.16 q3,d3[2]
+ VMUL.I16 q2,q2,q5
+ VMUL.I16 q3,q3,q5
+ VADD.I16 q2,q2,q0
+ VDUP.16 q0,d6[0]
+ VDUP.16 q1,d6[1]
+ VDUP.16 q4,d6[2]
+ VDUP.16 q5,d6[3]
+ VDUP.16 q6,d7[0]
+ VDUP.16 q7,d7[1]
+ VDUP.16 q8,d7[2]
+ VDUP.16 q9,d7[3]
+ VADD.I16 q0,q2,q0
+ VADD.I16 q1,q2,q1
+ VADD.I16 q4,q2,q4
+ VADD.I16 q5,q2,q5
+ VADD.I16 q6,q2,q6
+ VADD.I16 q7,q2,q7
+ VADD.I16 q8,q2,q8
+ VADD.I16 q9,q2,q9
+ VQRSHRUN.S16 d0,q0,#5
+ VQRSHRUN.S16 d1,q1,#5
+ VQRSHRUN.S16 d2,q4,#5
+ VQRSHRUN.S16 d3,q5,#5
+ VQRSHRUN.S16 d4,q6,#5
+ VQRSHRUN.S16 d5,q7,#5
+ VQRSHRUN.S16 d6,q8,#5
+ VQRSHRUN.S16 d7,q9,#5
+L0x28c:
+ ADD r9,r3,r5
+ ADD r10,r5,r5
+ VST1.8 {d0},[r3],r10
+ VST1.8 {d1},[r9],r10
+ VST1.8 {d2},[r3],r10
+ VST1.8 {d3},[r9],r10
+ VST1.8 {d4},[r3],r10
+ VST1.8 {d5},[r9],r10
+ VST1.8 {d6},[r3],r10
+ VST1.8 {d7},[r9]
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r10,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_16x16_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_16x16_s.S
new file mode 100644
index 0000000..53268f6
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_16x16_s.S
@@ -0,0 +1,239 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+
+ .section .rodata
+ .align 4
+;//-------------------------------------------------------
+;// This table for implementing switch case of C in asm by
+;// the mehtod of two levels of indexing.
+;//-------------------------------------------------------
+
+armVCM4P10_pIndexTable16x16:
+ .word OMX_VC_16X16_VERT, OMX_VC_16X16_HOR
+ .word OMX_VC_16X16_DC, OMX_VC_16X16_PLANE
+
+
+
+armVCM4P10_MultiplierTable16x16:
+ .hword 7, 6, 5, 4, 3, 2, 1, 8
+ .hword 0, 1, 2, 3, 4, 5, 6, 7
+ .hword 8, 9, 10, 11, 12, 13, 14, 15
+
+ .text
+
+ .global omxVCM4P10_PredictIntra_16x16
+ .func omxVCM4P10_PredictIntra_16x16
+omxVCM4P10_PredictIntra_16x16:
+ PUSH {r4-r12,lr}
+ VPUSH {d8-d15}
+ LDR r9, =armVCM4P10_pIndexTable16x16
+ LDR r6,[sp,#0x70]
+ LDR r4,[sp,#0x68]
+ LDR r5,[sp,#0x6c]
+ LDR r7,[sp,#0x74]
+ MOV r12,#0x10
+ LDR pc,[r9,r6,LSL #2]
+OMX_VC_16X16_VERT:
+ VLD1.8 {d0,d1},[r1]
+ ADD r8,r3,r5
+ ADD r10,r5,r5
+ VST1.8 {d0,d1},[r3],r10
+ VST1.8 {d0,d1},[r8],r10
+ VST1.8 {d0,d1},[r3],r10
+ VST1.8 {d0,d1},[r8],r10
+ VST1.8 {d0,d1},[r3],r10
+ VST1.8 {d0,d1},[r8],r10
+ VST1.8 {d0,d1},[r3],r10
+ VST1.8 {d0,d1},[r8],r10
+ VST1.8 {d0,d1},[r3],r10
+ VST1.8 {d0,d1},[r8],r10
+ VST1.8 {d0,d1},[r3],r10
+ VST1.8 {d0,d1},[r8],r10
+ VST1.8 {d0,d1},[r3],r10
+ VST1.8 {d0,d1},[r8],r10
+ VST1.8 {d0,d1},[r3]
+ VST1.8 {d0,d1},[r8]
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+OMX_VC_16X16_HOR:
+ ADD r8,r0,r4
+ ADD r4,r4,r4
+ ADD r11,r3,r5
+ ADD r5,r5,r5
+L0x8c:
+ VLD1.8 {d2[],d3[]},[r0],r4
+ VLD1.8 {d0[],d1[]},[r8],r4
+ SUBS r12,r12,#8
+ VST1.8 {d2,d3},[r3],r5
+ VST1.8 {d0,d1},[r11],r5
+ VLD1.8 {d2[],d3[]},[r0],r4
+ VLD1.8 {d0[],d1[]},[r8],r4
+ VST1.8 {d2,d3},[r3],r5
+ VST1.8 {d0,d1},[r11],r5
+ VLD1.8 {d2[],d3[]},[r0],r4
+ VLD1.8 {d0[],d1[]},[r8],r4
+ VST1.8 {d2,d3},[r3],r5
+ VST1.8 {d0,d1},[r11],r5
+ VLD1.8 {d2[],d3[]},[r0],r4
+ VLD1.8 {d0[],d1[]},[r8],r4
+ VST1.8 {d2,d3},[r3],r5
+ VST1.8 {d0,d1},[r11],r5
+ BNE L0x8c
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+OMX_VC_16X16_DC:
+ MOV r11,#0
+ TST r7,#2
+ BEQ L0x14c
+ ADD r8,r0,r4
+ ADD r10,r4,r4
+ VLD1.8 {d2[0]},[r0],r10
+ VLD1.8 {d2[1]},[r8],r10
+ VLD1.8 {d2[2]},[r0],r10
+ VLD1.8 {d2[3]},[r8],r10
+ VLD1.8 {d2[4]},[r0],r10
+ VLD1.8 {d2[5]},[r8],r10
+ VLD1.8 {d2[6]},[r0],r10
+ VLD1.8 {d2[7]},[r8],r10
+ VLD1.8 {d3[0]},[r0],r10
+ VLD1.8 {d3[1]},[r8],r10
+ VLD1.8 {d3[2]},[r0],r10
+ VLD1.8 {d3[3]},[r8],r10
+ VLD1.8 {d3[4]},[r0],r10
+ VLD1.8 {d3[5]},[r8],r10
+ VLD1.8 {d3[6]},[r0],r10
+ VLD1.8 {d3[7]},[r8]
+ VPADDL.U8 q0,q1
+ ADD r11,r11,#1
+ VPADD.I16 d0,d0,d1
+ VPADDL.U16 d0,d0
+ VPADDL.U32 d6,d0
+ VRSHR.U64 d8,d6,#4
+L0x14c:
+ TST r7,#1
+ BEQ L0x170
+ VLD1.8 {d0,d1},[r1]
+ ADD r11,r11,#1
+ VPADDL.U8 q0,q0
+ VPADD.I16 d0,d0,d1
+ VPADDL.U16 d0,d0
+ VPADDL.U32 d7,d0
+ VRSHR.U64 d8,d7,#4
+L0x170:
+ CMP r11,#2
+ BNE L0x180
+ VADD.I64 d8,d7,d6
+ VRSHR.U64 d8,d8,#5
+L0x180:
+ VDUP.8 q3,d8[0]
+ CMP r11,#0
+ ADD r8,r3,r5
+ ADD r10,r5,r5
+ BNE L0x198
+ VMOV.I8 q3,#0x80
+L0x198:
+ VST1.8 {d6,d7},[r3],r10
+ VST1.8 {d6,d7},[r8],r10
+ VST1.8 {d6,d7},[r3],r10
+ VST1.8 {d6,d7},[r8],r10
+ VST1.8 {d6,d7},[r3],r10
+ VST1.8 {d6,d7},[r8],r10
+ VST1.8 {d6,d7},[r3],r10
+ VST1.8 {d6,d7},[r8],r10
+ VST1.8 {d6,d7},[r3],r10
+ VST1.8 {d6,d7},[r8],r10
+ VST1.8 {d6,d7},[r3],r10
+ VST1.8 {d6,d7},[r8],r10
+ VST1.8 {d6,d7},[r3],r10
+ VST1.8 {d6,d7},[r8],r10
+ VST1.8 {d6,d7},[r3],r10
+ VST1.8 {d6,d7},[r8],r10
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+OMX_VC_16X16_PLANE:
+ LDR r9, =armVCM4P10_MultiplierTable16x16
+ VLD1.8 {d0,d1},[r1]
+ VLD1.8 {d4[0]},[r2]
+ ADD r8,r0,r4
+ ADD r10,r4,r4
+ VLD1.8 {d2[0]},[r0],r10
+ VLD1.8 {d2[1]},[r8],r10
+ VLD1.8 {d2[2]},[r0],r10
+ VLD1.8 {d2[3]},[r8],r10
+ VLD1.8 {d2[4]},[r0],r10
+ VLD1.8 {d2[5]},[r8],r10
+ VLD1.8 {d2[6]},[r0],r10
+ VLD1.8 {d2[7]},[r8],r10
+ VLD1.8 {d3[0]},[r0],r10
+ VLD1.8 {d3[1]},[r8],r10
+ VLD1.8 {d3[2]},[r0],r10
+ VLD1.8 {d3[3]},[r8],r10
+ VLD1.8 {d3[4]},[r0],r10
+ VLD1.8 {d3[5]},[r8],r10
+ VLD1.8 {d3[6]},[r0],r10
+ VLD1.8 {d3[7]},[r8]
+ VREV64.8 d5,d1
+ VSUBL.U8 q3,d5,d4
+ VSHR.U64 d5,d5,#8
+ VSUBL.U8 q4,d5,d0
+ VSHL.I64 d9,d9,#16
+ VEXT.8 d9,d9,d6,#2
+ VREV64.8 d12,d3
+ VSUBL.U8 q7,d12,d4
+ VSHR.U64 d12,d12,#8
+ VSUBL.U8 q8,d12,d2
+ VLD1.16 {d20,d21},[r9]!
+ VSHL.I64 d17,d17,#16
+ VEXT.8 d17,d17,d14,#2
+ VMULL.S16 q11,d8,d20
+ VMULL.S16 q12,d16,d20
+ VMLAL.S16 q11,d9,d21
+ VMLAL.S16 q12,d17,d21
+ VPADD.I32 d22,d23,d22
+ VPADD.I32 d23,d25,d24
+ VPADDL.S32 q11,q11
+ VSHL.I64 q12,q11,#2
+ VADD.I64 q11,q11,q12
+ VRSHR.S64 q11,q11,#6
+ VSHL.I64 q12,q11,#3
+ VSUB.I64 q12,q12,q11
+ VLD1.16 {d20,d21},[r9]!
+ VDUP.16 q6,d22[0]
+ VDUP.16 q7,d23[0]
+ VADDL.U8 q11,d1,d3
+ VSHL.I16 q11,q11,#4
+ VDUP.16 q11,d23[3]
+ VADD.I64 d1,d24,d25
+ VLD1.16 {d24,d25},[r9]
+ VDUP.16 q13,d1[0]
+ VSUB.I16 q13,q11,q13
+ VMUL.I16 q5,q6,q10
+ VMUL.I16 q6,q6,q12
+ VADD.I16 q0,q5,q13
+ VADD.I16 q1,q6,q13
+L0x2d4:
+ VQRSHRUN.S16 d6,q0,#5
+ VQRSHRUN.S16 d7,q1,#5
+ SUBS r12,r12,#1
+ VST1.8 {d6,d7},[r3],r5
+ VADD.I16 q0,q0,q7
+ VADD.I16 q1,q1,q7
+ BNE L0x2d4
+ MOV r0,#0
+ VPOP {d8-d15}
+ POP {r4-r12,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_4x4_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_4x4_s.S
new file mode 100644
index 0000000..aa6d7ef
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_PredictIntra_4x4_s.S
@@ -0,0 +1,261 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+
+ .section .rodata
+ .align 4
+
+armVCM4P10_pSwitchTable4x4:
+ .word OMX_VC_4x4_VERT, OMX_VC_4x4_HOR
+ .word OMX_VC_4x4_DC, OMX_VC_4x4_DIAG_DL
+ .word OMX_VC_4x4_DIAG_DR, OMX_VC_4x4_VR
+ .word OMX_VC_4x4_HD, OMX_VC_4x4_VL
+ .word OMX_VC_4x4_HU
+
+ .text
+
+ .global omxVCM4P10_PredictIntra_4x4
+ .func omxVCM4P10_PredictIntra_4x4
+omxVCM4P10_PredictIntra_4x4:
+ PUSH {r4-r12,lr}
+ VPUSH {d8-d12}
+ LDR r8, =armVCM4P10_pSwitchTable4x4
+ LDRD r6,r7,[sp,#0x58]
+ LDRD r4,r5,[sp,#0x50]
+ LDR pc,[r8,r6,LSL #2]
+OMX_VC_4x4_HOR:
+ ADD r9,r0,r4
+ ADD r10,r4,r4
+ VLD1.8 {d0[]},[r0],r10
+ VLD1.8 {d1[]},[r9],r10
+ VLD1.8 {d2[]},[r0]
+ VLD1.8 {d3[]},[r9]
+ ADD r11,r3,r5
+ ADD r12,r5,r5
+ VST1.32 {d0[0]},[r3],r12
+ VST1.32 {d1[0]},[r11],r12
+ VST1.32 {d2[0]},[r3]
+ VST1.32 {d3[0]},[r11]
+ B L0x348
+OMX_VC_4x4_VERT:
+ VLD1.32 {d0[0]},[r1]
+ ADD r11,r3,r5
+ ADD r12,r5,r5
+L0x58:
+ VST1.32 {d0[0]},[r3],r12
+ VST1.32 {d0[0]},[r11],r12
+ VST1.32 {d0[0]},[r3]
+ VST1.32 {d0[0]},[r11]
+ B L0x348
+OMX_VC_4x4_DC:
+ TST r7,#2
+ BEQ L0xdc
+ ADD r9,r0,r4
+ ADD r10,r4,r4
+ VLD1.8 {d0[0]},[r0],r10
+ VLD1.8 {d0[1]},[r9],r10
+ VLD1.8 {d0[2]},[r0]
+ VLD1.8 {d0[3]},[r9]
+ TST r7,#1
+ BEQ L0xbc
+ VLD1.32 {d0[1]},[r1]
+ MOV r0,#0
+ VPADDL.U8 d1,d0
+ VPADDL.U16 d1,d1
+ VPADDL.U32 d1,d1
+ VRSHR.U64 d1,d1,#3
+ ADD r11,r3,r5
+ ADD r12,r5,r5
+ VDUP.8 d0,d1[0]
+ B L0x58
+L0xbc:
+ MOV r0,#0
+ VPADDL.U8 d1,d0
+ VPADDL.U16 d1,d1
+ VRSHR.U32 d1,d1,#2
+ ADD r11,r3,r5
+ ADD r12,r5,r5
+ VDUP.8 d0,d1[0]
+ B L0x58
+L0xdc:
+ TST r7,#1
+ BEQ L0x108
+ VLD1.32 {d0[0]},[r1]
+ MOV r0,#0
+ VPADDL.U8 d1,d0
+ VPADDL.U16 d1,d1
+ VRSHR.U32 d1,d1,#2
+ ADD r11,r3,r5
+ ADD r12,r5,r5
+ VDUP.8 d0,d1[0]
+ B L0x58
+L0x108:
+ VMOV.I8 d0,#0x80
+ MOV r0,#0
+ ADD r11,r3,r5
+ ADD r12,r5,r5
+ B L0x58
+OMX_VC_4x4_DIAG_DL:
+ TST r7,#0x40
+ BEQ L0x138
+ VLD1.8 {d3},[r1]
+ VDUP.8 d2,d3[7]
+ VEXT.8 d4,d3,d2,#1
+ VEXT.8 d5,d3,d2,#2
+ B L0x14c
+L0x138:
+ VLD1.32 {d0[1]},[r1]
+ VDUP.8 d2,d0[7]
+ VEXT.8 d3,d0,d2,#4
+ VEXT.8 d4,d0,d2,#5
+ VEXT.8 d5,d0,d2,#6
+L0x14c:
+ VHADD.U8 d6,d3,d5
+ VRHADD.U8 d6,d6,d4
+ VST1.32 {d6[0]},[r3],r5
+ VEXT.8 d6,d6,d6,#1
+ VST1.32 {d6[0]},[r3],r5
+ VEXT.8 d6,d6,d6,#1
+ VST1.32 {d6[0]},[r3],r5
+ VEXT.8 d6,d6,d6,#1
+ VST1.32 {d6[0]},[r3]
+ B L0x348
+OMX_VC_4x4_DIAG_DR:
+ VLD1.32 {d0[0]},[r1]
+ VLD1.8 {d1[7]},[r2]
+ ADD r9,r0,r4
+ ADD r10,r4,r4
+ ADD r1,r3,r5
+ VLD1.8 {d1[6]},[r0],r10
+ VLD1.8 {d1[5]},[r9],r10
+ VLD1.8 {d1[4]},[r0]
+ VLD1.8 {d1[3]},[r9]
+ VEXT.8 d3,d1,d0,#3
+ ADD r4,r1,r5
+ VEXT.8 d4,d1,d0,#4
+ ADD r6,r4,r5
+ VEXT.8 d5,d1,d0,#5
+ VHADD.U8 d6,d3,d5
+ VRHADD.U8 d6,d6,d4
+ VST1.32 {d6[0]},[r6]
+ VEXT.8 d6,d6,d6,#1
+ VST1.32 {d6[0]},[r4]
+ VEXT.8 d6,d6,d6,#1
+ VST1.32 {d6[0]},[r1]
+ VEXT.8 d6,d6,d6,#1
+ VST1.32 {d6[0]},[r3]
+ B L0x348
+OMX_VC_4x4_VR:
+ VLD1.32 {d0[0]},[r1]
+ VLD1.8 {d0[7]},[r2]
+ VLD1.8 {d1[7]},[r0],r4
+ VLD1.8 {d2[7]},[r0],r4
+ VLD1.8 {d1[6]},[r0]
+ VEXT.8 d12,d0,d0,#7
+ VEXT.8 d3,d1,d12,#6
+ VEXT.8 d4,d2,d12,#7
+ VEXT.8 d5,d1,d0,#7
+ VEXT.8 d6,d2,d0,#7
+ VEXT.8 d11,d1,d12,#7
+ VHADD.U8 d8,d6,d12
+ VRHADD.U8 d8,d8,d11
+ VHADD.U8 d7,d3,d5
+ VRHADD.U8 d7,d7,d4
+ VEXT.8 d10,d8,d8,#1
+ ADD r11,r3,r5
+ ADD r12,r5,r5
+ VEXT.8 d9,d7,d7,#1
+ VST1.32 {d10[0]},[r3],r12
+ VST1.32 {d9[0]},[r11],r12
+ VST1.32 {d8[0]},[r3],r12
+ VST1.32 {d7[0]},[r11]
+ B L0x348
+OMX_VC_4x4_HD:
+ VLD1.8 {d0},[r1]
+ VLD1.8 {d1[7]},[r2]
+ ADD r9,r0,r4
+ ADD r10,r4,r4
+ VLD1.8 {d1[6]},[r0],r10
+ VLD1.8 {d1[5]},[r9],r10
+ VLD1.8 {d1[4]},[r0]
+ VLD1.8 {d1[3]},[r9]
+ VEXT.8 d3,d1,d0,#3
+ VEXT.8 d4,d1,d0,#2
+ VEXT.8 d5,d1,d0,#1
+ VHADD.U8 d7,d3,d5
+ VRHADD.U8 d7,d7,d4
+ VRHADD.U8 d8,d4,d3
+ VSHL.I64 d8,d8,#24
+ VSHL.I64 d6,d7,#16
+ VZIP.8 d8,d6
+ VEXT.8 d7,d7,d7,#6
+ VEXT.8 d8,d6,d7,#2
+ ADD r11,r3,r5
+ ADD r12,r5,r5
+ VST1.32 {d8[1]},[r3],r12
+ VST1.32 {d6[1]},[r11],r12
+ VST1.32 {d8[0]},[r3]
+ VST1.32 {d6[0]},[r11]
+ B L0x348
+OMX_VC_4x4_VL:
+ TST r7,#0x40
+ BEQ L0x2b4
+ VLD1.8 {d3},[r1]
+ VEXT.8 d4,d3,d3,#1
+ VEXT.8 d5,d4,d4,#1
+ B L0x2c8
+L0x2b4:
+ VLD1.32 {d0[1]},[r1]
+ VDUP.8 d2,d0[7]
+ VEXT.8 d3,d0,d2,#4
+ VEXT.8 d4,d0,d2,#5
+ VEXT.8 d5,d0,d2,#6
+L0x2c8:
+ VRHADD.U8 d7,d4,d3
+ VHADD.U8 d10,d3,d5
+ VRHADD.U8 d10,d10,d4
+ VEXT.8 d8,d7,d7,#1
+ ADD r11,r3,r5
+ ADD r12,r5,r5
+ VEXT.8 d9,d10,d8,#1
+ VST1.32 {d7[0]},[r3],r12
+ VST1.32 {d10[0]},[r11],r12
+ VST1.32 {d8[0]},[r3]
+ VST1.32 {d9[0]},[r11]
+ B L0x348
+OMX_VC_4x4_HU:
+ ADD r9,r0,r4
+ ADD r10,r4,r4
+ VLD1.8 {d1[4]},[r0],r10
+ VLD1.8 {d1[5]},[r9],r10
+ VLD1.8 {d1[6]},[r0]
+ VLD1.8 {d1[7]},[r9]
+ VDUP.8 d2,d1[7]
+ VEXT.8 d3,d1,d2,#4
+ VEXT.8 d4,d1,d2,#5
+ VEXT.8 d5,d1,d2,#6
+ VHADD.U8 d7,d3,d5
+ VRHADD.U8 d7,d7,d4
+ VRHADD.U8 d8,d4,d3
+ VZIP.8 d8,d7
+ VST1.32 {d8[0]},[r3],r5
+ VEXT.8 d8,d8,d8,#2
+ VST1.32 {d8[0]},[r3],r5
+ VEXT.8 d8,d8,d8,#2
+ VST1.32 {d8[0]},[r3],r5
+ VST1.32 {d7[0]},[r3]
+L0x348:
+ MOV r0,#0
+ VPOP {d8-d12}
+ POP {r4-r12,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S
new file mode 100644
index 0000000..28a89cb
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantChromaDCFromPair_s.S
@@ -0,0 +1,54 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global omxVCM4P10_TransformDequantChromaDCFromPair
+ .func omxVCM4P10_TransformDequantChromaDCFromPair
+omxVCM4P10_TransformDequantChromaDCFromPair:
+ push {r4-r10, lr}
+ ldr r9, [r0,#0]
+ vmov.i16 d0, #0
+ mov r8, #0x1f
+ vst1.16 {d0}, [r1]
+ ldrb r6, [r9], #1
+unpackLoop:
+ tst r6, #0x10
+ ldrnesb r5, [r9, #1]
+ ldrneb r4, [r9], #2
+ and r7, r8, r6, lsl #1
+ ldreqsb r4, [r9], #1
+ orrne r4, r4, r5, lsl #8
+ tst r6, #0x20
+ ldreqb r6, [r9], #1
+ strh r4, [r1, r7]
+ beq unpackLoop
+ ldmia r1, {r3, r4}
+ str r9, [r0, #0]
+ ldr r5, =armVCM4P10_QPDivTable
+ ldr r6, =armVCM4P10_VMatrixQPModTable
+ saddsubx r3, r3, r3
+ saddsubx r4, r4, r4
+ ldrsb r9, [r5, r2]
+ ldrsb r2, [r6, r2]
+ sadd16 r5, r3, r4
+ ssub16 r6, r3, r4
+ lsl r2, r2, r9
+ vmov d0, r5, r6
+ vrev32.16 d0, d0
+ vdup.16 d1, r2
+ vmull.s16 q1, d0, d1
+ vshrn.i32 d2, q1, #1
+ vst1.16 {d2}, [r1]
+ mov r0, #0
+ pop {r4-r10, pc}
+ .endfunc
+
+ .end
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantLumaDCFromPair_s.S b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantLumaDCFromPair_s.S
new file mode 100644
index 0000000..a3a0715
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p10/src_gcc/omxVCM4P10_TransformDequantLumaDCFromPair_s.S
@@ -0,0 +1,76 @@
+/*
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ */
+
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+
+ .arm
+ .fpu neon
+ .text
+
+ .global armVCM4P10_InvTransformDequantLumaDC4x4
+ .func armVCM4P10_InvTransformDequantLumaDC4x4
+armVCM4P10_InvTransformDequantLumaDC4x4:
+ PUSH {r4-r6,lr}
+ VPUSH {d8-d13}
+ VLD4.16 {d0,d1,d2,d3},[r0]
+ LDR r2, =armVCM4P10_QPDivTable
+ LDR r3, =armVCM4P10_VMatrixQPModTable
+ VADD.I16 d4,d0,d1
+ VADD.I16 d5,d2,d3
+ VSUB.I16 d6,d0,d1
+ LDRSB r4,[r2,r1]
+ VSUB.I16 d7,d2,d3
+ LDRSB r5,[r3,r1]
+ VADD.I16 d0,d4,d5
+ VSUB.I16 d1,d4,d5
+ VSUB.I16 d2,d6,d7
+ LSL r5,r5,r4
+ VADD.I16 d3,d6,d7
+ VTRN.16 d0,d1
+ VTRN.16 d2,d3
+ VTRN.32 q0,q1
+ VADD.I16 d4,d0,d1
+ VADD.I16 d5,d2,d3
+ VSUB.I16 d6,d0,d1
+ VSUB.I16 d7,d2,d3
+ VADD.I16 d0,d4,d5
+ VSUB.I16 d1,d4,d5
+ VSUB.I16 d2,d6,d7
+ VADD.I16 d3,d6,d7
+ VDUP.16 d5,r5
+ VMOV.I32 q3,#0x2
+ VMOV.I32 q4,#0x2
+ VMOV.I32 q5,#0x2
+ VMOV.I32 q6,#0x2
+ VMLAL.S16 q3,d0,d5
+ VMLAL.S16 q4,d1,d5
+ VMLAL.S16 q5,d2,d5
+ VMLAL.S16 q6,d3,d5
+ VSHRN.I32 d0,q3,#2
+ VSHRN.I32 d1,q4,#2
+ VSHRN.I32 d2,q5,#2
+ VSHRN.I32 d3,q6,#2
+ VST1.16 {d0,d1,d2,d3},[r0]
+ VPOP {d8-d13}
+ POP {r4-r6,pc}
+ .endfunc
+
+.global omxVCM4P10_TransformDequantLumaDCFromPair
+.func omxVCM4P10_TransformDequantLumaDCFromPair
+omxVCM4P10_TransformDequantLumaDCFromPair:
+ PUSH {r4-r6,lr}
+ MOV r4,r1
+ MOV r5,r2
+ BL armVCM4P10_UnpackBlock4x4
+ MOV r0,r4
+ MOV r1,r5
+ BL armVCM4P10_InvTransformDequantLumaDC4x4
+ MOV r0,#0
+ POP {r4-r6,pc}
+ .endfunc
+
+ .end
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
new file mode 100755
index 0000000..74b5505
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
@@ -0,0 +1,37 @@
+/**
+ *
+ * File Name: armVCM4P2_Huff_Tables_VLC.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ *
+ * File: armVCM4P2_Huff_Tables.h
+ * Description: Declares Tables used for Hufffman coding and decoding
+ * in MP4P2 codec.
+ *
+ */
+
+#ifndef _OMXHUFFTAB_H_
+#define _OMXHUFFTAB_H_
+
+
+extern const OMX_U16 armVCM4P2_IntraVlcL0L1[200];
+
+
+extern const OMX_U16 armVCM4P2_InterVlcL0L1[200];
+
+extern const OMX_U16 armVCM4P2_aIntraDCLumaChromaIndex[64];
+//extern const OMX_U16 armVCM4P2_aIntraDCChromaIndex[32];
+extern const OMX_U16 armVCM4P2_aVlcMVD[124];
+
+extern const OMX_U8 armVCM4P2_InterL0L1LMAX[73];
+extern const OMX_U8 armVCM4P2_InterL0L1RMAX[35];
+extern const OMX_U8 armVCM4P2_IntraL0L1LMAX[53];
+extern const OMX_U8 armVCM4P2_IntraL0L1RMAX[40]
+
+#endif /* _OMXHUFFTAB_H_ */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
new file mode 100755
index 0000000..e95203a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
@@ -0,0 +1,25 @@
+/**
+ *
+ * File Name: armVCM4P2_ZigZag_Tables.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ *
+ * File: armVCM4P2_Zigzag_Tables.h
+ * Description: Declares Tables used for Zigzag scan in MP4P2 codec.
+ *
+ */
+
+#ifndef _OMXZIGZAGTAB_H
+#define _OMXZIGZAGTAB_H
+
+extern const OMX_U8 armVCM4P2_aClassicalZigzagScan [192];
+//extern const OMX_U8 armVCM4P2_aHorizontalZigzagScan [64];
+//extern const OMX_U8 armVCM4P2_aVerticalZigzagScan [64];
+
+#endif /* _OMXZIGZAGTAB_H_ */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Clip8_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Clip8_s.s
new file mode 100755
index 0000000..95fe6d2
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Clip8_s.s
@@ -0,0 +1,82 @@
+; /**
+; *
+; * File Name: armVCM4P2_Clip8_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 12290
+; * Date: Wednesday, April 9, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains module for Clipping 16 bit value to [0,255] Range
+; */
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+
+ M_VARIANTS CortexA8
+
+ IF CortexA8
+;//Input Arguments
+
+pSrc RN 0
+pDst RN 1
+step RN 2
+
+;// Neon Registers
+
+qx0 QN Q0.S16
+dx00 DN D0.S16
+dx01 DN D1.S16
+qx1 QN Q1.S16
+dx10 DN D2.S16
+dx11 DN D3.S16
+
+qx2 QN Q2.S16
+dx20 DN D4.S16
+dx21 DN D5.S16
+qx3 QN Q3.S16
+dx30 DN D6.S16
+dx31 DN D7.S16
+
+
+dclip0 DN D0.U8
+dclip1 DN D2.U8
+dclip2 DN D4.U8
+dclip3 DN D6.U8
+
+ M_START armVCM4P2_Clip8
+
+ VLD1 {dx00,dx01,dx10,dx11},[pSrc]! ;// Load 16 entries from pSrc
+ VLD1 {dx20,dx21,dx30,dx31},[pSrc]! ;// Load next 16 entries from pSrc
+ VQSHRUN dclip0,qx0,#0 ;// dclip0[i]=clip qx0[i] to [0,255]
+ VQSHRUN dclip1,qx1,#0 ;// dclip1[i]=clip qx1[i] to [0,255]
+ VST1 {dclip0},[pDst],step ;// store 8 bytes and pDst=pDst+step
+ VST1 {dclip1},[pDst],step ;// store 8 bytes and pDst=pDst+step
+ VQSHRUN dclip2,qx2,#0
+ VQSHRUN dclip3,qx3,#0
+ VST1 {dclip2},[pDst],step
+ VST1 {dclip3},[pDst],step
+
+ VLD1 {dx00,dx01,dx10,dx11},[pSrc]! ;// Load 16 entries from pSrc
+ VLD1 {dx20,dx21,dx30,dx31},[pSrc]! ;// Load next 16 entries from pSrc
+ VQSHRUN dclip0,qx0,#0 ;// dclip0[i]=clip qx0[i] to [0,255]
+ VQSHRUN dclip1,qx1,#0 ;// dclip1[i]=clip qx1[i] to [0,255]
+ VST1 {dclip0},[pDst],step ;// store 8 bytes and pDst=pDst+step
+ VST1 {dclip1},[pDst],step ;// store 8 bytes and pDst=pDst+step
+ VQSHRUN dclip2,qx2,#0
+ VQSHRUN dclip3,qx3,#0
+ VST1 {dclip2},[pDst],step
+ VST1 {dclip3},[pDst],step
+
+
+
+ M_END
+ ENDIF
+
+
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
new file mode 100755
index 0000000..e4a7f33
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
@@ -0,0 +1,398 @@
+;/**
+; *
+; * File Name: armVCM4P2_DecodeVLCZigzag_AC_unsafe_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 12290
+; * Date: Wednesday, April 9, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains modules for zigzag scanning and VLC decoding
+; * for inter, intra block.
+; *
+; *
+; *
+; * Function: omxVCM4P2_DecodeVLCZigzag_AC_unsafe
+; *
+; * Description:
+; * Performs VLC decoding and inverse zigzag scan
+; *
+; *
+; *
+; *
+; */
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armCOMM_BitDec_s.h
+
+
+ M_VARIANTS ARM1136JS
+
+
+
+
+
+ IF ARM1136JS
+
+
+
+
+
+;//Input Arguments
+
+ppBitStream RN 0
+pBitOffset RN 1
+pDst RN 2
+shortVideoHeader RN 3
+
+
+;//Local Variables
+
+Return RN 0
+
+pVlcTableL0L1 RN 4
+pLMAXTableL0L1 RN 4
+pRMAXTableL0L1 RN 4
+pZigzagTable RN 4
+
+ftype RN 0
+temp3 RN 4
+temp RN 5
+Count RN 6
+Escape RN 5
+
+;// armVCM4P2_FillVLDBuffer
+zigzag RN 0
+storeLevel RN 1
+temp2 RN 4
+temp1 RN 5
+sign RN 5
+Last RN 7
+storeRun RN 14
+
+
+packRetIndex RN 5
+
+
+markerbit RN 5
+
+;// Scratch Registers
+
+RBitStream RN 8
+RBitBuffer RN 9
+RBitCount RN 10
+
+T1 RN 11
+T2 RN 12
+LR RN 14
+
+
+
+ M_ALLOC4 pppBitStream,4
+ M_ALLOC4 ppOffset,4
+ M_ALLOC4 pLinkRegister,4
+
+ M_START armVCM4P2_DecodeVLCZigzag_AC_unsafe
+
+ ;// get the table addresses from stack
+ M_ARG ppVlcTableL0L1,4
+ M_ARG ppLMAXTableL0L1,4
+ M_ARG ppRMAXTableL0L1,4
+ M_ARG ppZigzagTable,4
+
+ ;// Store ALL zeros at pDst
+
+ MOV temp1,#0 ;// Initialize Count to zero
+ MOV Last,#0
+ M_STR LR,pLinkRegister ;// Store Link Register on Stack
+ MOV temp2,#0
+ MOV LR,#0
+
+ ;// Initialize the Macro and Store all zeros to pDst
+
+ STM pDst!,{temp2,temp1,Last,LR}
+ M_BD_INIT0 ppBitStream, pBitOffset, RBitStream, RBitBuffer, RBitCount
+ STM pDst!,{temp2,temp1,Last,LR}
+ M_BD_INIT1 T1, T2, T2
+ STM pDst!,{temp2,temp1,Last,LR}
+ M_BD_INIT2 T1, T2, T2
+ STM pDst!,{temp2,temp1,Last,LR}
+ M_STR ppBitStream,pppBitStream ;// Store ppBitstream on stack
+ STM pDst!,{temp2,temp1,Last,LR}
+ M_STR pBitOffset,ppOffset ;// Store pBitOffset on stack
+ STM pDst!,{temp2,temp1,Last,LR}
+
+ STM pDst!,{temp2,temp1,Last,LR}
+ STM pDst!,{temp2,temp1,Last,LR}
+
+
+ SUB pDst,pDst,#128 ;// Restore pDst
+
+ ;// The armVCM4P2_GetVLCBits begins
+
+getVLCbits
+
+ M_BD_LOOK8 Escape,7 ;// Load Escape Value
+ LSR Escape,Escape,#25
+ CMP Escape,#3 ;// check for escape mode
+ MOVNE ftype,#0
+ BNE notEscapemode ;// Branch if not in Escape mode 3
+
+ M_BD_VSKIP8 #7,T1
+ CMP shortVideoHeader,#0 ;// Check shortVideoHeader flag to know the type of Escape mode
+ BEQ endFillVLD
+
+ ;// Escape Mode 4
+
+ M_BD_READ8 Last,1,T1
+ M_BD_READ8 storeRun,6,T1
+ M_BD_READ8 storeLevel,8,T1
+
+
+ ;// Check whether the Reserved values for Level are used and Exit with an Error Message if it is so
+
+ TEQ storeLevel,#0
+ TEQNE storeLevel,#128
+ BEQ ExitError
+
+ ADD temp2,storeRun,Count
+ CMP temp2,#64
+ BGE ExitError ;// error if Count+storeRun >= 64
+
+
+ ;// Load address of zigzagTable
+
+ M_LDR pZigzagTable,ppZigzagTable ;// Loading the Address of Zigzag table
+
+
+ ;// armVCM4P2_FillVLDBuffer
+
+ SXTB storeLevel,storeLevel ;// Sign Extend storeLevel to 32 bits
+
+
+ ;// To Reflect Runlength
+
+ ADD Count,Count,storeRun
+ LDRB zigzag,[pZigzagTable,Count]
+ ADD Count,Count,#1
+ STRH storeLevel,[pDst,zigzag] ;// store Level
+
+ B ExitOk
+
+
+
+endFillVLD
+
+
+ ;// Load Ftype( Escape Mode) value based on the two successive bits in the bitstream
+
+ M_BD_READ8 temp1,1,T1
+ CMP temp1,#0
+ MOVEQ ftype,#1
+ BEQ notEscapemode
+ M_BD_READ8 temp1,1,T1
+ CMP temp1,#1
+ MOVEQ ftype,#3
+ MOVNE ftype,#2
+
+
+notEscapemode
+
+ ;// Load optimized packed VLC table with last=0 and Last=1
+
+ M_LDR pVlcTableL0L1,ppVlcTableL0L1 ;// Load Combined VLC Table
+
+
+ CMP ftype,#3 ;// If ftype >=3 get perform Fixed Length Decoding (Escape Mode 3)
+ BGE EscapeMode3 ;// Else continue normal VLC Decoding
+
+ ;// Variable lengh decoding, "armUnPackVLC32"
+
+
+ M_BD_VLD packRetIndex,T1,T2,pVlcTableL0L1,4,2
+
+
+ LDR temp3,=0xFFF
+
+ CMP packRetIndex,temp3 ;// Check for invalid symbol
+ BEQ ExitError ;// if invalid symbol occurs exit with an error message
+
+ AND Last,packRetIndex,#2 ;// Get Last from packed Index
+
+
+
+
+ LSR storeRun,packRetIndex,#7 ;// Get Run Value from Packed index
+ AND storeLevel,packRetIndex,#0x7c ;// storeLevel=packRetIndex[2-6],storeLevel[0-1]=0
+
+
+ M_LDR pLMAXTableL0L1,ppLMAXTableL0L1 ;// Load LMAX table
+
+
+ LSR storeLevel,storeLevel,#2 ;// Level value
+
+ CMP ftype,#1
+ BNE ftype2
+
+ ;// ftype==1; Escape mode =1
+
+
+ ADD temp1, pLMAXTableL0L1, Last, LSL#4 ;// If the Last=1 add 32 to table address
+ LDRB temp1,[temp1,storeRun]
+
+
+ ADD storeLevel,temp1,storeLevel
+
+ftype2
+
+ ;// ftype =2; Escape mode =2
+
+ M_LDR pRMAXTableL0L1,ppRMAXTableL0L1 ;// Load RMAX Table
+
+ CMP ftype,#2
+ BNE FillVLDL1
+
+ ADD temp1, pRMAXTableL0L1, Last, LSL#4 ;// If Last=1 add 32 to table address
+ SUB temp2,storeLevel,#1
+ LDRB temp1,[temp1,temp2]
+
+
+ ADD storeRun,storeRun,#1
+ ADD storeRun,temp1
+
+FillVLDL1
+
+
+ ;// armVCM4P2_FillVLDBuffer
+
+ M_LDR pZigzagTable,ppZigzagTable ;// Load address of zigzagTable
+
+ M_BD_READ8 sign,1,T1
+
+ CMP sign,#1
+ RSBEQ storeLevel,storeLevel,#0
+
+ ADD temp1,storeRun,Count ;// Exit with an error message if Run + Count exceeds 63
+ CMP temp1,#64
+ BGE ExitError
+
+
+
+
+
+
+ ;// To Reflect Runlenght
+
+ ADD Count,Count,storeRun
+
+storeLevelL1
+
+ LDRB zigzag,[pZigzagTable,Count]
+ CMP Last,#2 ;// Check if the Level val is Last non zero val
+ ADD Count,Count,#1
+ LSR Last,Last,#1
+ STRH storeLevel,[pDst,zigzag]
+
+ BNE end
+
+ B ExitOk
+
+
+
+ ;// Fixed Lengh Decoding Escape Mode 3
+
+EscapeMode3
+
+ M_BD_READ8 Last,1,T1
+ M_BD_READ8 storeRun,6,T1
+
+ ADD temp2,storeRun,Count ;// Exit with an error message if Run + Count exceeds 63
+ CMP temp2,#64
+ BGE ExitError
+
+ M_BD_READ8 markerbit,1,T1
+ TEQ markerbit,#0 ;// Exit with an error message if marker bit is zero
+ BEQ ExitError
+
+ M_BD_READ16 storeLevel,12,T1
+
+ TST storeLevel,#0x800 ;// test if the level is negative
+ SUBNE storeLevel,storeLevel,#4096
+ CMP storeLevel,#0
+ CMPNE storeLevel,#-2048
+ BEQ ExitError ;// Exit with an error message if Level==0 or -2048
+
+ M_LDR pZigzagTable,ppZigzagTable ;// Load address of zigzagTable
+
+ M_BD_READ8 markerbit,1,T1
+
+
+ ;// armVCM4P2_FillVLDBuffer ( Sign not used as storeLevel is preprocessed)
+
+
+
+ ;// To Reflect Run Length
+
+ ADD Count,Count,storeRun
+
+
+
+storeLevelLast
+
+ LDRB zigzag,[pZigzagTable,Count]
+ CMP Last,#1
+ ADD Count,Count,#1
+ STRH storeLevel,[pDst,zigzag]
+
+ BNE end
+
+ B ExitOk
+
+end
+
+ CMP Count,#64 ;//Run the Loop untill Count reaches 64
+
+ BLT getVLCbits
+
+
+ExitOk
+ ;// Exit When VLC Decoding is done Successfully
+
+ ;// Loading ppBitStream and pBitOffset from stack
+
+ CMP Last,#1
+ M_LDR ppBitStream,pppBitStream
+ M_LDR pBitOffset,ppOffset
+
+ ;//Ending the macro
+
+ M_BD_FINI ppBitStream,pBitOffset
+
+ MOVEQ Return,#OMX_Sts_NoErr
+ MOVNE Return,#OMX_Sts_Err
+ M_LDR LR,pLinkRegister ;// Load the Link Register Back
+ B exit2
+
+ExitError
+ ;// Exit When an Error occurs
+
+ M_LDR ppBitStream,pppBitStream
+ M_LDR pBitOffset,ppOffset
+ ;//Ending the macro
+
+ M_BD_FINI ppBitStream,pBitOffset
+ M_LDR LR,pLinkRegister
+ MOV Return,#OMX_Sts_Err
+
+exit2
+
+
+ M_END
+ ENDIF
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
new file mode 100755
index 0000000..38af975
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
@@ -0,0 +1,211 @@
+ /**
+ *
+ * File Name: armVCM4P2_Huff_Tables_VLC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armVCM4P2_Huff_Tables_VLC.c
+ * Description: Contains all the Huffman tables used in MPEG4 codec
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armCOMM_Bitstream.h"
+
+
+
+
+// Contains optimized and Packed VLC tables with Last=0 and Last=1
+
+// optimized Packed VLC table Entry Format
+// ---------------------------------------
+//
+// 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+// +------------------------------------------------+
+// | Len | Run | Level |L | 1 |
+// +------------------------------------------------+
+// | Offset | 0 |
+// +------------------------------------------------+
+// If the table entry is a leaf entry then bit 0 set:
+// Len = Number of bits overread (0 to 7) 3 bits
+// Run = RunLength of the Symbol (0 to 63) 6 bits
+// Level = Level of the Symbol (0 to 31) 5 bits
+// L = Last Value of the Symbol (0 or 1) 1 bit
+//
+// If the table entry is an internal node then bit 0 is clear:
+// Offset = Number of (16-bit) half words from the table
+// start to the next table node
+//
+// The table is accessed by successive lookup up on the
+// next Step bits of the input bitstream until a leaf node
+// is obtained. The Step sizes are supplied to the VLD macro.
+
+// The VLC tables used for Intra and non inta coefficients in non Escape mode
+// contains symbols with both Last=0 and Last=1.
+// If a symbol is not found in the table it will be coded as 0xFFF
+
+
+const OMX_U16 armVCM4P2_InterVlcL0L1[200] = {
+ 0x0020, 0x0108, 0x0148, 0x0170, 0x0178, 0x0180, 0x0188, 0x1b09,
+ 0x4009, 0x4009, 0x4009, 0x4009, 0x2109, 0x2109, 0x0209, 0x0011,
+ 0x0028, 0x0060, 0x00b8, 0x00e0, 0x0030, 0x0048, 0x0050, 0x0058,
+ 0x3fff, 0x3fff, 0x0038, 0x0040, 0x2115, 0x2115, 0x201d, 0x201d,
+ 0x2059, 0x2059, 0x2051, 0x2051, 0x1c0d, 0x1b0d, 0x1a0d, 0x190d,
+ 0x0911, 0x0811, 0x0711, 0x0611, 0x0511, 0x0319, 0x0219, 0x0121,
+ 0x0068, 0x0090, 0x3fff, 0x3fff, 0x0070, 0x0078, 0x0080, 0x0088,
+ 0x2061, 0x2061, 0x2129, 0x2129, 0x3709, 0x3709, 0x3809, 0x3809,
+ 0x3d0d, 0x3d0d, 0x3e0d, 0x3e0d, 0x3f0d, 0x3f0d, 0x200d, 0x200d,
+ 0x0098, 0x00a0, 0x00a8, 0x00b0, 0x0131, 0x0221, 0x0419, 0x0519,
+ 0x0619, 0x0a11, 0x1909, 0x1a09, 0x210d, 0x220d, 0x230d, 0x240d,
+ 0x250d, 0x260d, 0x270d, 0x280d, 0x00c0, 0x00c8, 0x00d0, 0x00d8,
+ 0x0049, 0x0041, 0x380d, 0x380d, 0x370d, 0x370d, 0x360d, 0x360d,
+ 0x350d, 0x350d, 0x340d, 0x340d, 0x330d, 0x330d, 0x320d, 0x320d,
+ 0x00e8, 0x00f0, 0x00f8, 0x0100, 0x310d, 0x310d, 0x2015, 0x2015,
+ 0x3609, 0x3609, 0x3509, 0x3509, 0x3409, 0x3409, 0x3309, 0x3309,
+ 0x3209, 0x3209, 0x3109, 0x3109, 0x0110, 0x0130, 0x0138, 0x0140,
+ 0x0118, 0x0120, 0x0128, 0x100d, 0x3009, 0x3009, 0x2f09, 0x2f09,
+ 0x2411, 0x2411, 0x2311, 0x2311, 0x2039, 0x2039, 0x2031, 0x2031,
+ 0x0f0d, 0x0e0d, 0x0d0d, 0x0c0d, 0x0b0d, 0x0a0d, 0x090d, 0x0e09,
+ 0x0d09, 0x0211, 0x0119, 0x0029, 0x0150, 0x0158, 0x0160, 0x0168,
+ 0x280d, 0x280d, 0x270d, 0x270d, 0x260d, 0x260d, 0x250d, 0x250d,
+ 0x2c09, 0x2c09, 0xb759, 0xb759, 0x2a09, 0x2a09, 0x2021, 0x2021,
+ 0x040d, 0x030d, 0x0b35, 0x010d, 0x0909, 0x0809, 0x0709, 0x0609,
+ 0x0111, 0x0019, 0x2509, 0x2509, 0x2409, 0x2409, 0x2309, 0x2309
+};
+
+
+const OMX_U16 armVCM4P2_IntraVlcL0L1[200] = {
+ 0x0020, 0x0108, 0x0148, 0x0170, 0x0178, 0x0180, 0x0188, 0x0f09,
+ 0x4009, 0x4009, 0x4009, 0x4009, 0x2011, 0x2011, 0x0109, 0x0019,
+ 0x0028, 0x0060, 0x00b8, 0x00e0, 0x0030, 0x0048, 0x0050, 0x0058,
+ 0x3fff, 0x3fff, 0x0038, 0x0040, 0x203d, 0x203d, 0x2035, 0x2035,
+ 0x20b1, 0x20b1, 0x20a9, 0x20a9, 0x0215, 0x011d, 0x002d, 0x0d09,
+ 0x0519, 0x0811, 0x0419, 0x0321, 0x0221, 0x0139, 0x00a1, 0x0099,
+ 0x0068, 0x0090, 0x3fff, 0x3fff, 0x0070, 0x0078, 0x0080, 0x0088,
+ 0x20b9, 0x20b9, 0x20c1, 0x20c1, 0x2141, 0x2141, 0x2911, 0x2911,
+ 0x2315, 0x2315, 0x2415, 0x2415, 0x2f0d, 0x2f0d, 0x300d, 0x300d,
+ 0x0098, 0x00a0, 0x00a8, 0x00b0, 0x00c9, 0x00d1, 0x00d9, 0x0149,
+ 0x0619, 0x0151, 0x0229, 0x0719, 0x0e09, 0x0045, 0x0515, 0x0615,
+ 0x110d, 0x120d, 0x130d, 0x140d, 0x00c0, 0x00c8, 0x00d0, 0x00d8,
+ 0x0091, 0x0089, 0x2e0d, 0x2e0d, 0x2d0d, 0x2d0d, 0x2c0d, 0x2c0d,
+ 0x2b0d, 0x2b0d, 0x2a0d, 0x2a0d, 0x2115, 0x2115, 0x2025, 0x2025,
+ 0x00e8, 0x00f0, 0x00f8, 0x0100, 0x2c09, 0x2c09, 0x2b09, 0x2b09,
+ 0x2711, 0x2711, 0x2611, 0x2611, 0x2511, 0x2511, 0x2319, 0x2319,
+ 0x2219, 0x2219, 0x2131, 0x2131, 0x0110, 0x0130, 0x0138, 0x0140,
+ 0x0118, 0x0120, 0x0128, 0x080d, 0x2129, 0x2129, 0x2081, 0x2081,
+ 0x2411, 0x2411, 0x2079, 0x2079, 0x2071, 0x2071, 0x2069, 0x2069,
+ 0x1bb5, 0x060d, 0x001d, 0xd3f9, 0x0909, 0x0809, 0x090d, 0x0311,
+ 0x0121, 0x0061, 0x0059, 0x0051, 0x0150, 0x0158, 0x0160, 0x0168,
+ 0x240d, 0x240d, 0x230d, 0x230d, 0x2609, 0x2609, 0x250d, 0x250d,
+ 0x2709, 0x2709, 0x2211, 0x2211, 0x2119, 0x2119, 0x2049, 0x2049,
+ 0x0015, 0x0509, 0x020d, 0x010d, 0x0409, 0x0309, 0x0041, 0x0039,
+ 0x0111, 0x0031, 0x2209, 0x2209, 0x2029, 0x2029, 0x2021, 0x2021
+};
+
+const OMX_U16 armVCM4P2_aIntraDCLumaChromaIndex[64] = {
+ 0x0020, 0x000b, 0x2009, 0x2009, 0x2007, 0x2007, 0x2001, 0x2001,
+ 0x4005, 0x4005, 0x4005, 0x4005, 0x4003, 0x4003, 0x4003, 0x4003,
+ 0x0028, 0x000f, 0x200d, 0x200d, 0x0030, 0x0013, 0x2011, 0x2011,
+ 0x0038, 0x0017, 0x2015, 0x2015, 0x3fff, 0x3fff, 0x2019, 0x2019,
+
+ 0x0020, 0x0009, 0x2007, 0x2007, 0x4005, 0x4005, 0x4005, 0x4005,
+ 0x4003, 0x4003, 0x4003, 0x4003, 0x4001, 0x4001, 0x4001, 0x4001,
+ 0x0028, 0x000d, 0x200b, 0x200b, 0x0030, 0x0011, 0x200f, 0x200f,
+ 0x0038, 0x0015, 0x2013, 0x2013, 0x1fff, 0x0019, 0x2017, 0x2017
+};
+
+
+const OMX_U16 armVCM4P2_aVlcMVD[124] = {
+ 0x0010, 0x00f0, 0x0043, 0x003f, 0x4041, 0x4041, 0x4041, 0x4041,
+ 0x0018, 0x00d8, 0x0047, 0x003b, 0x0020, 0x0080, 0x00a8, 0x00d0,
+ 0x0028, 0x0048, 0x0070, 0x0078, 0x1fff, 0x0030, 0x0038, 0x0040,
+ 0x0081, 0x0001, 0x007f, 0x0003, 0x207d, 0x207d, 0x2005, 0x2005,
+ 0x207b, 0x207b, 0x2007, 0x2007, 0x0050, 0x0058, 0x0060, 0x0068,
+ 0x2079, 0x2079, 0x2009, 0x2009, 0x2077, 0x2077, 0x200b, 0x200b,
+ 0x2075, 0x2075, 0x200d, 0x200d, 0x2073, 0x2073, 0x200f, 0x200f,
+ 0x0071, 0x0011, 0x006f, 0x0013, 0x006d, 0x0015, 0x006b, 0x0017,
+ 0x0088, 0x0090, 0x0098, 0x00a0, 0x0069, 0x0019, 0x0067, 0x001b,
+ 0x0065, 0x001d, 0x0063, 0x001f, 0x0061, 0x0021, 0x005f, 0x0023,
+ 0x005d, 0x0025, 0x005b, 0x0027, 0x00b0, 0x00b8, 0x00c0, 0x00c8,
+ 0x0059, 0x0029, 0x0057, 0x002b, 0x2055, 0x2055, 0x202d, 0x202d,
+ 0x2053, 0x2053, 0x202f, 0x202f, 0x2051, 0x2051, 0x2031, 0x2031,
+ 0x204f, 0x204f, 0x2033, 0x2033, 0x00e0, 0x00e8, 0x0049, 0x0039,
+ 0x204d, 0x204d, 0x2035, 0x2035, 0x204b, 0x204b, 0x2037, 0x2037,
+ 0x2045, 0x2045, 0x203d, 0x203d
+};
+
+/* LMAX table for non Inter (Last == 0 and Last=1)
+ Level - 1 Indexed
+ padded armVCM4P2_InterL0L1LMAX[27-31] with zeros to acess entries for Last=1 effectively
+
+*/
+const OMX_U8 armVCM4P2_InterL0L1LMAX[73] =
+{
+ 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,
+ 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
+};
+
+/* RMAX table for non Inter (Last == 0 and Last=1)
+ Level - 1 Indexed
+ padded armVCM4P2_InterL0L1RMAX[12-31] with zeros to access entries for Last=1 table effectively */
+
+
+const OMX_U8 armVCM4P2_InterL0L1RMAX[35] =
+{
+ 26, 10, 6, 2, 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, 40, 1, 0
+};
+
+/* LMAX table for non Intra (Last == 0 and Last=1)
+ Level - 1 Indexed
+ padded armVCM4P2_IntraL0L1LMAX[15-31] with zeros to acess entries for Last=1 effectively
+
+*/
+const OMX_U8 armVCM4P2_IntraL0L1LMAX[53] =
+{
+ 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,
+
+ 8, 3, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+};
+
+
+/* RMAX table for non Inter (Last == 0 and Last=1)
+ Level - 1 Indexed
+ padded armVCM4P2_IntraL0L1RMAX[27-31] with zeros to access entries for Last=1 table effectively */
+
+
+const OMX_U8 armVCM4P2_IntraL0L1RMAX[40] =
+{
+ 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, 0,
+ 0, 0, 0, 0,
+
+ 20, 6, 1, 0, 0, 0, 0, 0
+
+};
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Lookup_Tables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Lookup_Tables.c
new file mode 100755
index 0000000..6948f80
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Lookup_Tables.c
@@ -0,0 +1,75 @@
+ /**
+ *
+ * File Name: armVCM4P2_Lookup_Tables.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armVCM4P2_Lookup_Tables.c
+ * Description: Contains all the Lookup tables used in MPEG4 codec
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+ /* * Table Entries contain Dc Scaler values
+ * armVCM4P2_DCScaler[i]= 8 for i=1 to 4 and i=33 to 36
+ * = 2*i for i=5 to 8
+ * = i+8 for i=9 to 25
+ * = 2*i-16 for i=26 to 31
+ * = (i-32+13)/2 for i=37 to 59
+ * = i-6-32 for i=60 to 63
+ * = 255 for i=0 and i=32
+ */
+
+const OMX_U8 armVCM4P2_DCScaler[64]={
+ 0xff, 0x8, 0x8, 0x8, 0x8, 0xa, 0xc, 0xe,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e,
+ 0xff, 0x8, 0x8, 0x8, 0x8, 0x9, 0x9, 0xa,
+ 0xa, 0xb, 0xb, 0xc, 0xc, 0xd, 0xd, 0xe,
+ 0xe, 0xf, 0xf, 0x10, 0x10, 0x11, 0x11, 0x12,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+
+};
+
+
+ /* Table Entries Contain reciprocal of 1 to 63
+ * armVCM4P2_Reciprocal_QP_S16[i]=round(32767/i)
+ * armVCM4P2_Reciprocal_QP_S16[0]= 0
+ */
+
+const OMX_S16 armVCM4P2_Reciprocal_QP_S16[64]={
+ 0x0000,0x7fff,0x4000,0x2aaa,0x2000,0x1999,0x1555,0x1249,
+ 0x1000,0x0e39,0x0ccd,0x0ba3,0x0aab,0x09d9,0x0925,0x0888,
+ 0x0800,0x0787,0x071c,0x06bd,0x0666,0x0618,0x05d1,0x0591,
+ 0x0555,0x051f,0x04ec,0x04be,0x0492,0x046a,0x0444,0x0421,
+ 0x0400,0x03e1,0x03c4,0x03a8,0x038e,0x0376,0x035e,0x0348,
+ 0x0333,0x031f,0x030c,0x02fa,0x02e9,0x02d8,0x02c8,0x02b9,
+ 0x02ab,0x029d,0x028f,0x0282,0x0276,0x026a,0x025f,0x0254,
+ 0x0249,0x023f,0x0235,0x022b,0x0222,0x0219,0x0211,0x0208
+
+};
+
+ /* Table Entries Contain reciprocal of 1 to 63
+ * armVCM4P2_Reciprocal_QP_S32[i]=round(131071/i)
+ * armVCM4P2_Reciprocal_QP_S32[0]= 0
+ */
+
+const OMX_S32 armVCM4P2_Reciprocal_QP_S32[64]={
+ 0x00000000,0x0001ffff,0x00010000,0x0000aaaa, 0x00008000, 0x00006666, 0x00005555, 0x00004924,
+ 0x00004000,0x000038e3,0x00003333,0x00002e8c, 0x00002aab, 0x00002762, 0x00002492, 0x00002222,
+ 0x00002000,0x00001e1e,0x00001c72,0x00001af2, 0x0000199a, 0x00001861, 0x00001746, 0x00001643,
+ 0x00001555,0x0000147b,0x000013b1,0x000012f6, 0x00001249, 0x000011a8, 0x00001111, 0x00001084,
+ 0x00001000,0x00000f84,0x00000f0f,0x00000ea1, 0x00000e39, 0x00000dd6, 0x00000d79, 0x00000d21,
+ 0x00000ccd,0x00000c7d,0x00000c31,0x00000be8, 0x00000ba3, 0x00000b61, 0x00000b21, 0x00000ae5,
+ 0x00000aab,0x00000a73,0x00000a3d,0x00000a0a, 0x000009d9, 0x000009a9, 0x0000097b, 0x0000094f,
+ 0x00000925,0x000008fb,0x000008d4,0x000008ae, 0x00000889, 0x00000865, 0x00000842, 0x00000820
+
+};
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_SetPredDir_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_SetPredDir_s.s
new file mode 100755
index 0000000..44f2460
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_SetPredDir_s.s
@@ -0,0 +1,104 @@
+;//
+;//
+;// File Name: armVCM4P2_SetPredDir_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+; **
+; * Function: armVCM4P2_SetPredDir
+; *
+; * Description:
+; * Performs detecting the prediction direction
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] blockIndex block index indicating the component type and
+; * position as defined in subclause 6.1.3.8, of ISO/IEC
+; * 14496-2. Furthermore, indexes 6 to 9 indicate the
+; * alpha blocks spatially corresponding to luminance
+; * blocks 0 to 3 in the same macroblock.
+; * [in] pCoefBufRow pointer to the coefficient row buffer
+; * [in] pQpBuf pointer to the quantization parameter buffer
+; * [out]predQP quantization parameter of the predictor block
+; * [out]predDir indicates the prediction direction which takes one
+; * of the following values:
+; * OMX_VC_HORIZONTAL predict horizontally
+; * OMX_VC_VERTICAL predict vertically
+; *
+; * Return Value:
+; * Standard OMXResult result. See enumeration for possible result codes.
+; *
+; */
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE omxVC_s.h
+
+
+ M_VARIANTS ARM1136JS
+
+
+ IF ARM1136JS
+
+;// Input Arguments
+BlockIndex RN 0
+pCoefBufRow RN 1
+pCoefBufCol RN 2
+predDir RN 3
+predQP RN 4
+pQpBuf RN 5
+
+;// Local Variables
+
+Return RN 0
+blockDCLeft RN 6
+blockDCTop RN 7
+blockDCTopLeft RN 8
+temp1 RN 9
+temp2 RN 14
+
+ M_START armVCM4P2_SetPredDir,r9
+
+ M_ARG ppredQP,4
+ M_ARG ppQpBuf,4
+
+ LDRH blockDCTopLeft,[pCoefBufRow,#-16]
+ LDRH blockDCLeft,[pCoefBufCol]
+
+ TEQ BlockIndex,#3
+ LDREQH blockDCTop,[pCoefBufCol,#-16]
+ LDRNEH blockDCTop,[pCoefBufRow]
+
+ SUBS temp1,blockDCLeft,blockDCTopLeft
+ RSBLT temp1,temp1,#0
+ SUBS temp2,blockDCTopLeft,blockDCTop
+ RSBLT temp2,temp2,#0
+
+ M_LDR pQpBuf,ppQpBuf
+ M_LDR predQP,ppredQP
+ CMP temp1,temp2
+ MOV temp2,#OMX_VC_VERTICAL
+ LDRLTB temp1,[pQpBuf,#1]
+ STRLT temp2,[predDir]
+ STRLT temp1,[predQP]
+ MOV temp2,#OMX_VC_HORIZONTAL
+ LDRGEB temp1,[pQpBuf]
+ STRGE temp2,[predDir]
+ MOV Return,#OMX_Sts_NoErr
+ STRGE temp1,[predQP]
+
+
+
+ M_END
+
+ ENDIF
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
new file mode 100755
index 0000000..21fa715
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
@@ -0,0 +1,61 @@
+/**
+ *
+ * File Name: armVCM4P2_Zigzag_Tables.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armVCM4P2_ZigZag_Tables.c
+ * Description: Contains the zigzag tables
+ *
+ */
+
+#include "omxtypes.h"
+
+/* Contains Double the values in the reference Zigzag Table
+ * Contains Classical,Vetical and Horizontal Zigzagscan tables in one array
+ */
+
+const OMX_U8 armVCM4P2_aClassicalZigzagScan [192] =
+{
+ 0, 2, 16, 32, 18, 4, 6, 20,
+ 34, 48, 64, 50, 36, 22, 8, 10,
+ 24, 38, 52, 66, 80, 96, 82, 68,
+ 54, 40, 26, 12, 14, 28, 42, 56,
+ 70, 84, 98, 112, 114, 100, 86, 72,
+ 58, 44, 30, 46, 60, 74, 88, 102,
+ 116, 118, 104, 90, 76, 62, 78, 92,
+ 106, 120, 122, 104, 94, 110, 124, 126,
+
+ 0, 16, 32, 48, 2, 18, 4, 20,
+ 34, 50, 64, 80, 96, 112, 114, 98,
+ 82, 66, 52, 36, 6, 22, 8, 24,
+ 38, 54, 68, 84, 100, 116, 70, 86,
+ 102, 118, 40, 56, 10, 26, 12, 28,
+ 42, 58, 72, 88, 104, 120, 74, 90,
+ 106, 122, 44, 60, 14, 30, 46, 62,
+ 76, 92, 108, 124, 78, 94, 110, 126,
+
+ 0, 2, 4, 6, 16, 18, 32, 34,
+ 20, 22, 8, 10, 12, 14, 30, 28,
+ 26, 24, 38, 36, 48, 50, 64, 66,
+ 52, 54, 40, 42, 44, 46, 56, 58,
+ 60, 62, 68, 70, 80, 82, 96, 98,
+ 84, 86, 72, 74, 76, 78, 88, 90,
+ 92, 94, 100, 102, 112, 114, 116, 118,
+ 104, 106, 108, 110, 120, 122, 124, 126
+
+
+};
+
+
+
+
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
new file mode 100755
index 0000000..796ad6e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
@@ -0,0 +1,102 @@
+/**
+ *
+ * File Name: omxVCM4P2_DecodeBlockCoef_Inter.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for inter reconstruction
+ *
+ */
+
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+
+/**
+ * Function: omxVCM4P2_DecodeBlockCoef_Inter
+ *
+ * Description:
+ * Decodes the INTER block coefficients. Inverse quantization, inversely zigzag
+ * positioning and IDCT, with appropriate clipping on each step, are performed
+ * on the coefficients. The results (residuals) are placed in a contiguous array
+ * of 64 elements. For INTER block, the output buffer holds the residuals for
+ * further reconstruction.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream buffer. There is no boundary
+ * check for the bit stream buffer.
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * to by *ppBitStream. *pBitOffset is valid within
+ * [0-7]
+ * [in] QP quantization parameter
+ * [in] shortVideoHeader a flag indicating presence of short_video_header;
+ * shortVideoHeader==1 indicates using quantization method defined in short
+ * video header mode, and shortVideoHeader==0 indicates normail quantization method.
+ * [out] ppBitStream *ppBitStream is updated after the block is decoded, so that it points to the
+ * current byte in the bit stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the current bit position in the
+ * byte pointed by *ppBitStream
+ * [out] pDst pointer to the decoded residual buffer (a contiguous array of 64 elements of
+ * OMX_S16 data type). Must be 16-byte aligned.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - At least one of the following pointers is Null: ppBitStream, *ppBitStream, pBitOffset , pDst
+ * - At least one of the below case:
+ * - *pBitOffset exceeds [0,7], QP <= 0;
+ * - pDst not 16-byte aligned
+ * OMX_Sts_Err - status error
+ *
+ */
+OMXResult omxVCM4P2_DecodeBlockCoef_Inter(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_INT QP,
+ OMX_INT shortVideoHeader
+)
+{
+ /* 64 elements are needed but to align it to 16 bytes need
+ 15 more elements of padding */
+ OMX_S16 tempBuf[79];
+ OMX_S16 *pTempBuf1;
+ OMXResult errorCode;
+ /* Aligning the local buffers */
+ pTempBuf1 = armAlignTo16Bytes(tempBuf);
+
+
+ /* VLD and zigzag */
+ errorCode = omxVCM4P2_DecodeVLCZigzag_Inter(ppBitStream, pBitOffset,
+ pTempBuf1,shortVideoHeader);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Dequantization */
+ errorCode = omxVCM4P2_QuantInvInter_I(
+ pTempBuf1,
+ QP);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Inverse transform */
+ errorCode = omxVCM4P2_IDCT8x8blk(pTempBuf1, pDst);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
new file mode 100755
index 0000000..b28657c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
@@ -0,0 +1,214 @@
+/**
+ *
+ * File Name: omxVCM4P2_DecodeBlockCoef_Intra.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 12290
+ * Date: Wednesday, April 9, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for intra reconstruction
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/* Function for saturating 16 bit values to the [0,255] range and */
+/* writing out as 8 bit values. Does 64 entries */
+void armVCM4P2_Clip8(OMX_S16 *pSrc, OMX_U8 *pDst, OMX_INT dstStep );
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeBlockCoef_Intra
+ *
+ * Description:
+ * Decodes the INTRA block coefficients. Inverse quantization, inversely zigzag
+ * positioning, and IDCT, with appropriate clipping on each step, are performed
+ * on the coefficients. The results are then placed in the output frame/plane on
+ * a pixel basis. For INTRA block, the output values are clipped to [0, 255] and
+ * written to corresponding block buffer within the destination plane.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream buffer. There is no boundary
+ * check for the bit stream buffer.
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * to by *ppBitStream. *pBitOffset is valid within
+ * [0-7].
+ * [in] step width of the destination plane
+ * [in/out] pCoefBufRow [in] pointer to the coefficient row buffer
+ * [out] updated coefficient rwo buffer
+ * [in/out] pCoefBufCol [in] pointer to the coefficient column buffer
+ * [out] updated coefficient column buffer
+ * [in] curQP quantization parameter of the macroblock which
+ * the current block belongs to
+ * [in] pQpBuf Pointer to a 2-element QP array. pQpBuf[0] holds the QP of the 8x8 block left to
+ * the current block(QPa). pQpBuf[1] holds the QP of the 8x8 block just above the
+ * current block(QPc).
+ * Note, in case the corresponding block is out of VOP bound, the QP value will have
+ * no effect to the intra-prediction process. Refer to subclause "7.4.3.3 Adaptive
+ * ac coefficient prediction" of ISO/IEC 14496-2(MPEG4 Part2) for accurate description.
+ * [in] blockIndex block index indicating the component type and
+ * position as defined in subclause 6.1.3.8,
+ * Figure 6-5 of ISO/IEC 14496-2.
+ * [in] intraDCVLC a code determined by intra_dc_vlc_thr and QP.
+ * This allows a mechanism to switch between two VLC
+ * for coding of Intra DC coefficients as per Table
+ * 6-21 of ISO/IEC 14496-2.
+ * [in] ACPredFlag a flag equal to ac_pred_flag (of luminance) indicating
+ * if the ac coefficients of the first row or first
+ * column are differentially coded for intra coded
+ * macroblock.
+ * [in] shortVideoHeader a flag indicating presence of short_video_header;
+ * shortVideoHeader==1 selects linear intra DC mode,
+ * and shortVideoHeader==0 selects nonlinear intra DC mode.
+ * [out] ppBitStream *ppBitStream is updated after the block is
+ * decoded, so that it points to the current byte
+ * in the bit stream buffer
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream
+ * [out] pDst pointer to the block in the destination plane.
+ * pDst should be 16-byte aligned.
+ * [out] pCoefBufRow pointer to the updated coefficient row buffer.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - At least one of the following pointers is NULL: ppBitStream, *ppBitStream, pBitOffset,
+ * pCoefBufRow, pCoefBufCol, pQPBuf, pDst.
+ * or
+ * - At least one of the below case: *pBitOffset exceeds [0,7], curQP exceeds (1, 31),
+ * blockIndex exceeds [0,9], step is not the multiple of 8, intraDCVLC is zero while
+ * blockIndex greater than 5.
+ * or
+ * - pDst is not 16-byte aligned
+ * OMX_Sts_Err - status error
+ *
+ */
+
+OMXResult omxVCM4P2_DecodeBlockCoef_Intra(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_U8 *pDst,
+ OMX_INT step,
+ OMX_S16 *pCoefBufRow,
+ OMX_S16 *pCoefBufCol,
+ OMX_U8 curQP,
+ const OMX_U8 *pQPBuf,
+ OMX_INT blockIndex,
+ OMX_INT intraDCVLC,
+ OMX_INT ACPredFlag,
+ OMX_INT shortVideoHeader
+ )
+{
+ OMX_S16 tempBuf1[79], tempBuf2[79];
+ OMX_S16 *pTempBuf1, *pTempBuf2;
+ OMX_INT predDir, predACDir;
+ OMX_INT predQP;
+ OMXVCM4P2VideoComponent videoComp;
+ OMXResult errorCode;
+
+
+ /* Aligning the local buffers */
+ pTempBuf1 = armAlignTo16Bytes(tempBuf1);
+ pTempBuf2 = armAlignTo16Bytes(tempBuf2);
+
+ /* Setting the AC prediction direction and prediction direction */
+ armVCM4P2_SetPredDir(
+ blockIndex,
+ pCoefBufRow,
+ pCoefBufCol,
+ &predDir,
+ &predQP,
+ pQPBuf);
+
+ predACDir = predDir;
+
+
+ if (ACPredFlag == 0)
+ {
+ predACDir = OMX_VC_NONE;
+ }
+
+ /* Setting the videoComp */
+ if (blockIndex <= 3)
+ {
+ videoComp = OMX_VC_LUMINANCE;
+ }
+ else
+ {
+ videoComp = OMX_VC_CHROMINANCE;
+ }
+
+
+ /* VLD and zigzag */
+ if (intraDCVLC == 1)
+ {
+ errorCode = omxVCM4P2_DecodeVLCZigzag_IntraDCVLC(
+ ppBitStream,
+ pBitOffset,
+ pTempBuf1,
+ predACDir,
+ shortVideoHeader,
+ videoComp);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+ }
+ else
+ {
+ errorCode = omxVCM4P2_DecodeVLCZigzag_IntraACVLC(
+ ppBitStream,
+ pBitOffset,
+ pTempBuf1,
+ predACDir,
+ shortVideoHeader);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+ }
+
+ /* AC DC prediction */
+ errorCode = omxVCM4P2_PredictReconCoefIntra(
+ pTempBuf1,
+ pCoefBufRow,
+ pCoefBufCol,
+ curQP,
+ predQP,
+ predDir,
+ ACPredFlag,
+ videoComp);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Dequantization */
+ errorCode = omxVCM4P2_QuantInvIntra_I(
+ pTempBuf1,
+ curQP,
+ videoComp,
+ shortVideoHeader);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Inverse transform */
+ errorCode = omxVCM4P2_IDCT8x8blk (pTempBuf1, pTempBuf2);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Placing the linear array into the destination plane and clipping
+ it to 0 to 255 */
+
+ armVCM4P2_Clip8(pTempBuf2,pDst,step);
+
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
new file mode 100755
index 0000000..cc16f5a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP_s.s
@@ -0,0 +1,364 @@
+; **********
+; *
+; * File Name: omxVCM4P2_DecodePadMV_PVOP_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 12290
+; * Date: Wednesday, April 9, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; **
+; * Function: omxVCM4P2_DecodePadMV_PVOP
+; *
+; * Description:
+; * Decodes and pads four motion vectors of the non-intra macroblock in P-VOP.
+; * The motion vector padding process is specified in subclause 7.6.1.6 of
+; * ISO/IEC 14496-2.
+; *
+; * Remarks:
+; *
+; *
+; * Parameters:
+; * [in] ppBitStream pointer to the pointer to the current byte in
+; * the bit stream buffer
+; * [in] pBitOffset pointer to the bit position in the byte pointed
+; * to by *ppBitStream. *pBitOffset is valid within
+; * [0-7].
+; * [in] pSrcMVLeftMB pointers to the motion vector buffers of the
+; * macroblocks specially at the left side of the current macroblock
+; * respectively.
+; * [in] pSrcMVUpperMB pointers to the motion vector buffers of the
+; * macroblocks specially at the upper side of the current macroblock
+; * respectively.
+; * [in] pSrcMVUpperRightMB pointers to the motion vector buffers of the
+; * macroblocks specially at the upper-right side of the current macroblock
+; * respectively.
+; * [in] fcodeForward a code equal to vop_fcode_forward in MPEG-4
+; * bit stream syntax
+; * [in] MBType the type of the current macroblock. If MBType
+; * is not equal to OMX_VC_INTER4V, the destination
+; * motion vector buffer is still filled with the
+; * same decoded vector.
+; * [out] ppBitStream *ppBitStream is updated after the block is decoded,
+; * so that it points to the current byte in the bit
+; * stream buffer
+; * [out] pBitOffset *pBitOffset is updated so that it points to the
+; * current bit position in the byte pointed by
+; * *ppBitStream
+; * [out] pDstMVCurMB pointer to the motion vector buffer of the current
+; * macroblock which contains four decoded motion vectors
+; *
+; * Return Value:
+; * OMX_Sts_NoErr -no error
+; *
+; *
+; * OMX_Sts_Err - status error
+; *
+; *
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armCOMM_BitDec_s.h
+ INCLUDE omxVC_s.h
+
+ M_VARIANTS ARM1136JS
+
+
+
+
+ IF ARM1136JS
+
+;//Input Arguments
+
+ppBitStream RN 0
+pBitOffset RN 1
+pSrcMVLeftMB RN 2
+pSrcMVUpperMB RN 3
+pSrcMVUpperRightMB RN 4
+pDstMVCurMB RN 5
+fcodeForward RN 6
+MBType RN 7
+
+;//Local Variables
+
+zero RN 4
+one RN 4
+scaleFactor RN 1
+
+
+Return RN 0
+
+VlcMVD RN 0
+index RN 4
+Count RN 7
+
+mvHorData RN 4
+mvHorResidual RN 0
+
+mvVerData RN 4
+mvVerResidual RN 0
+
+temp RN 1
+
+temp1 RN 3
+High RN 4
+Low RN 2
+Range RN 1
+
+BlkCount RN 14
+
+diffMVdx RN 0
+diffMVdy RN 1
+
+;// Scratch Registers
+
+RBitStream RN 8
+RBitCount RN 9
+RBitBuffer RN 10
+
+T1 RN 11
+T2 RN 12
+LR RN 14
+
+ IMPORT armVCM4P2_aVlcMVD
+ IMPORT omxVCM4P2_FindMVpred
+
+ ;// Allocate stack memory
+
+ M_ALLOC4 ppDstMVCurMB,4
+ M_ALLOC4 pDstMVPredME,4
+ M_ALLOC4 pBlkCount,4
+
+ M_ALLOC4 pppBitStream,4
+ M_ALLOC4 ppBitOffset,4
+ M_ALLOC4 ppSrcMVLeftMB,4
+ M_ALLOC4 ppSrcMVUpperMB,4
+
+ M_ALLOC4 pdiffMVdx,4
+ M_ALLOC4 pdiffMVdy,4
+ M_ALLOC4 pHigh,4
+
+
+
+
+ M_START omxVCM4P2_DecodePadMV_PVOP,r11
+
+ M_ARG pSrcMVUpperRightMBonStack,4 ;// pointer to pSrcMVUpperRightMB on stack
+ M_ARG pDstMVCurMBonStack,4 ;// pointer to pDstMVCurMB on stack
+ M_ARG fcodeForwardonStack,4 ;// pointer to fcodeForward on stack
+ M_ARG MBTypeonStack,4 ;// pointer to MBType on stack
+
+
+
+
+
+ ;// Initializing the BitStream Macro
+
+ M_BD_INIT0 ppBitStream, pBitOffset, RBitStream, RBitBuffer, RBitCount
+ M_LDR MBType,MBTypeonStack ;// Load MBType from stack
+ M_LDR pDstMVCurMB,pDstMVCurMBonStack ;// Load pDstMVCurMB from stack
+ MOV zero,#0
+
+ TEQ MBType,#OMX_VC_INTRA ;// Check if MBType=OMX_VC_INTRA
+ TEQNE MBType,#OMX_VC_INTRA_Q ;// check if MBType=OMX_VC_INTRA_Q
+ STREQ zero,[pDstMVCurMB]
+ M_BD_INIT1 T1, T2, T2
+ STREQ zero,[pDstMVCurMB,#4]
+ M_BD_INIT2 T1, T2, T2
+ STREQ zero,[pDstMVCurMB,#4]
+ MOVEQ Return,#OMX_Sts_NoErr
+ MOV BlkCount,#0
+ STREQ zero,[pDstMVCurMB,#4]
+
+ BEQ ExitOK
+
+ TEQ MBType,#OMX_VC_INTER4V ;// Check if MBType=OMX_VC_INTER4V
+ TEQNE MBType,#OMX_VC_INTER4V_Q ;// Check if MBType=OMX_VC_INTER4V_Q
+ MOVEQ Count,#4
+
+ TEQ MBType,#OMX_VC_INTER ;// Check if MBType=OMX_VC_INTER
+ TEQNE MBType,#OMX_VC_INTER_Q ;// Check if MBType=OMX_VC_INTER_Q
+ MOVEQ Count,#1
+
+ M_LDR fcodeForward,fcodeForwardonStack ;// Load fcodeForward from stack
+
+ ;// Storing the values temporarily on stack
+
+ M_STR ppBitStream,pppBitStream
+ M_STR pBitOffset,ppBitOffset
+
+
+ SUB temp,fcodeForward,#1 ;// temp=fcodeForward-1
+ MOV one,#1
+ M_STR pSrcMVLeftMB,ppSrcMVLeftMB
+ LSL scaleFactor,one,temp ;// scaleFactor=1<<(fcodeForward-1)
+ M_STR pSrcMVUpperMB,ppSrcMVUpperMB
+ LSL scaleFactor,scaleFactor,#5
+ M_STR scaleFactor,pHigh ;// [pHigh]=32*scaleFactor
+
+ ;// VLD Decoding
+
+
+Loop
+
+ LDR VlcMVD, =armVCM4P2_aVlcMVD ;// Load the optimized MVD VLC table
+
+ ;// Horizontal Data and Residual calculation
+
+ LDR temp,=0xFFF
+ M_BD_VLD index,T1,T2,VlcMVD,3,2 ;// variable lenght decoding using the macro
+
+ TEQ index,temp
+ BEQ ExitError ;// Exit with an Error Message if the decoded symbol is an invalied symbol
+
+ SUB mvHorData,index,#32 ;// mvHorData=index-32
+ MOV mvHorResidual,#1 ;// mvHorResidual=1
+ CMP fcodeForward,#1
+ TEQNE mvHorData,#0
+ MOVEQ diffMVdx,mvHorData ;// if scaleFactor=1(fcodeForward=1) or mvHorData=0 diffMVdx=mvHorData
+ BEQ VerticalData
+
+ SUB temp,fcodeForward,#1
+ M_BD_VREAD8 mvHorResidual,temp,T1,T2 ;// get mvHorResidual from bitstream if fcodeForward>1 and mvHorData!=0
+
+ CMP mvHorData,#0
+ RSBLT mvHorData,mvHorData,#0 ;// mvHorData=abs(mvHorData)
+ SUB mvHorResidual,mvHorResidual,fcodeForward
+ SMLABB diffMVdx,mvHorData,fcodeForward,mvHorResidual ;// diffMVdx=abs(mvHorData)*fcodeForward+mvHorResidual-fcodeForward
+ ADD diffMVdx,diffMVdx,#1
+ RSBLT diffMVdx,diffMVdx,#0
+
+ ;// Vertical Data and Residual calculation
+
+VerticalData
+
+ M_STR diffMVdx,pdiffMVdx ;// Store the diffMVdx on stack
+ LDR VlcMVD, =armVCM4P2_aVlcMVD ;// Loading the address of optimized VLC tables
+
+ LDR temp,=0xFFF
+ M_BD_VLD index,T1,T2,VlcMVD,3,2 ;// VLC decoding using the macro
+
+ TEQ index,temp
+ BEQ ExitError ;// Exit with an Error Message if an Invalied Symbol occurs
+
+ SUB mvVerData,index,#32 ;// mvVerData=index-32
+ MOV mvVerResidual,#1
+ CMP fcodeForward,#1
+ TEQNE mvVerData,#0
+ MOVEQ diffMVdy,mvVerData ;// diffMVdy = mvVerData if scaleFactor=1(fcodeForward=1) or mvVerData=0
+ BEQ FindMVPred
+
+ SUB temp,fcodeForward,#1
+ M_BD_VREAD8 mvVerResidual,temp,T1,T2 ;// Get mvVerResidual from bit stream if fcodeForward>1 and mnVerData!=0
+
+
+ CMP mvVerData,#0
+ RSBLT mvVerData,mvVerData,#0
+ SUB mvVerResidual,mvVerResidual,fcodeForward
+ SMLABB diffMVdy,mvVerData,fcodeForward,mvVerResidual ;// diffMVdy=abs(mvVerData)*fcodeForward+mvVerResidual-fcodeForward
+ ADD diffMVdy,diffMVdy,#1
+ RSBLT diffMVdy,diffMVdy,#0
+
+ ;//Calling the Function omxVCM4P2_FindMVpred
+
+FindMVPred
+
+ M_STR diffMVdy,pdiffMVdy
+ ADD temp,pDstMVCurMB,BlkCount,LSL #2 ;// temp=pDstMVCurMB[BlkCount]
+ M_STR temp,ppDstMVCurMB ;// store temp on stack for passing as an argument to FindMVPred
+
+ MOV temp,#0
+ M_STR temp,pDstMVPredME ;// Pass pDstMVPredME=NULL as an argument
+ M_STR BlkCount,pBlkCount ;// Passs BlkCount as Argument through stack
+
+ MOV temp,pSrcMVLeftMB ;// temp (RN 1)=pSrcMVLeftMB
+ M_LDR pSrcMVUpperRightMB,pSrcMVUpperRightMBonStack
+ MOV pSrcMVLeftMB,pSrcMVUpperMB ;// pSrcMVLeftMB ( RN 2) = pSrcMVUpperMB
+ MOV ppBitStream,pDstMVCurMB ;// ppBitStream ( RN 0) = pDstMVCurMB
+ MOV pSrcMVUpperMB,pSrcMVUpperRightMB ;// pSrcMVUpperMB( RN 3) = pSrcMVUpperRightMB
+ BL omxVCM4P2_FindMVpred ;// Branch to subroutine omxVCM4P2_FindMVpred
+
+ ;// Store Horizontal Motion Vector
+
+ M_LDR BlkCount,pBlkCount ;// Load BlkCount from stack
+ M_LDR High,pHigh ;// High=32*scaleFactor
+ LSL temp1,BlkCount,#2 ;// temp=BlkCount*4
+ M_LDR diffMVdx,pdiffMVdx ;// Laad diffMVdx
+
+ LDRSH temp,[pDstMVCurMB,temp1] ;// temp=pDstMVCurMB[BlkCount]
+
+
+ RSB Low,High,#0 ;// Low = -32*scaleFactor
+ ADD diffMVdx,temp,diffMVdx ;// diffMVdx=pDstMVCurMB[BlkCount]+diffMVdx
+ ADD Range,High,High ;// Range=64*ScaleFactor
+ SUB High,High,#1 ;// High= 32*scaleFactor-1
+
+ CMP diffMVdx,Low ;// If diffMVdx<Low
+ ADDLT diffMVdx,diffMVdx,Range ;// diffMVdx+=Range
+
+ CMP diffMVdx,High
+ SUBGT diffMVdx,diffMVdx,Range ;// If diffMVdx > High diffMVdx-=Range
+ STRH diffMVdx,[pDstMVCurMB,temp1]
+
+ ;// Store Vertical
+
+ ADD temp1,temp1,#2 ;// temp1=4*BlkCount+2
+ M_LDR diffMVdx,pdiffMVdy ;// Laad diffMVdy
+ LDRSH temp,[pDstMVCurMB,temp1] ;// temp=pDstMVCurMB[BlkCount].diffMVdy
+ ADD BlkCount,BlkCount,#1 ;// BlkCount=BlkCount+1
+ ADD diffMVdx,temp,diffMVdx
+ CMP diffMVdx,Low
+ ADDLT diffMVdx,diffMVdx,Range ;// If diffMVdy<Low diffMVdy+=Range
+ CMP diffMVdx,High
+ SUBGT diffMVdx,diffMVdx,Range ;// If diffMVdy > High diffMVdy-=Range
+ STRH diffMVdx,[pDstMVCurMB,temp1]
+
+ CMP BlkCount,Count
+ M_LDR pSrcMVLeftMB,ppSrcMVLeftMB
+ M_LDR pSrcMVUpperMB,ppSrcMVUpperMB
+
+ BLT Loop ;// If BlkCount<Count Continue the Loop
+
+
+ ;// If MBType=OMX_VC_INTER or MBtype=OMX_VC_INTER_Q copy pDstMVCurMB[0] to
+ ;// pDstMVCurMB[1], pDstMVCurMB[2], pDstMVCurMB[3]
+
+ M_LDR MBType,MBTypeonStack
+
+ TEQ MBType,#OMX_VC_INTER
+ TEQNE MBType,#OMX_VC_INTER_Q
+ LDREQ temp,[pDstMVCurMB]
+ M_LDR ppBitStream,pppBitStream
+ STREQ temp,[pDstMVCurMB,#4]
+
+ STREQ temp,[pDstMVCurMB,#8]
+ STREQ temp,[pDstMVCurMB,#12]
+
+
+ M_LDR pBitOffset,ppBitOffset
+ ;//Ending the macro
+ M_BD_FINI ppBitStream,pBitOffset ;// Finishing the Macro
+
+
+ MOV Return,#OMX_Sts_NoErr
+ B ExitOK
+
+ExitError
+
+ M_LDR ppBitStream,pppBitStream
+ M_LDR pBitOffset,ppBitOffset
+ ;//Ending the macro
+ M_BD_FINI ppBitStream,pBitOffset
+
+ MOV Return,#OMX_Sts_Err
+
+ExitOK
+
+ M_END
+ ENDIF
+ END
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
new file mode 100755
index 0000000..7208c21
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter_s.s
@@ -0,0 +1,132 @@
+;/**
+; *
+; * File Name: omxVCM4P2_DecodeVLCZigzag_Inter_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 12290
+; * Date: Wednesday, April 9, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains modules for zigzag scanning and VLC decoding
+; * for inter block.
+; *
+; *
+; *
+; * Function: omxVCM4P2_DecodeVLCZigzag_Inter
+; *
+; * Description:
+; * Performs VLC decoding and inverse zigzag scan for one inter coded block.
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] ppBitStream pointer to the pointer to the current byte in
+; * the bitstream buffer
+; * [in] pBitOffset pointer to the bit position in the byte pointed
+; * to by *ppBitStream. *pBitOffset is valid within [0-7].
+; * [in] shortVideoHeader binary flag indicating presence of short_video_header;
+; * escape modes 0-3 are used if shortVideoHeader==0,
+; * and escape mode 4 is used when shortVideoHeader==1.
+; * [out] ppBitStream *ppBitStream is updated after the block is
+; * decoded, so that it points to the current byte
+; * in the bit stream buffer
+; * [out] pBitOffset *pBitOffset is updated so that it points to the
+; * current bit position in the byte pointed by
+; * *ppBitStream
+; * [out] pDst pointer to the coefficient buffer of current
+; * block. Must be 16-byte aligned
+; *
+; * Return Value:
+; * OMX_Sts_BadArgErr - bad arguments
+; * -At least one of the following pointers is NULL: ppBitStream, *ppBitStream, pBitOffset, pDst, or
+; * -pDst is not 16-byte aligned, or
+; * -*pBitOffset exceeds [0,7].
+; * OMX_Sts_Err - status error
+; * -At least one mark bit is equal to zero
+; * -Encountered an illegal stream code that cannot be found in the VLC table
+; * -Encountered and illegal code in the VLC FLC table
+; * -The number of coefficients is greater than 64
+; *
+; */
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armCOMM_BitDec_s.h
+
+
+ M_VARIANTS ARM1136JS
+
+
+
+
+
+ IF ARM1136JS
+
+ ;// Import various tables needed for the function
+
+
+ IMPORT armVCM4P2_InterVlcL0L1 ;// Contains optimized and packed VLC Tables for both Last =1 and last=0
+ ;// Packed in Run:Level:Last format
+ IMPORT armVCM4P2_InterL0L1LMAX ;// Contains LMAX table entries with both Last=0 and Last=1
+ IMPORT armVCM4P2_InterL0L1RMAX ;// Contains RMAX table entries with both Last=0 and Last=1
+ IMPORT armVCM4P2_aClassicalZigzagScan ;// contains classical Zigzag table entries with double the original values
+ IMPORT armVCM4P2_DecodeVLCZigzag_AC_unsafe
+
+
+
+;//Input Arguments
+
+ppBitStream RN 0
+pBitOffset RN 1
+pDst RN 2
+shortVideoHeader RN 3
+
+;//Local Variables
+
+Return RN 0
+
+pVlcTableL0L1 RN 4
+pLMAXTableL0L1 RN 4
+pRMAXTableL0L1 RN 4
+pZigzagTable RN 4
+Count RN 6
+
+
+
+ ;// Allocate stack memory to store the VLC,Zigzag,LMAX and RMAX tables
+
+
+ M_ALLOC4 ppVlcTableL0L1,4
+ M_ALLOC4 ppLMAXTableL0L1,4
+ M_ALLOC4 ppRMAXTableL0L1,4
+ M_ALLOC4 ppZigzagTable,4
+
+
+ M_START omxVCM4P2_DecodeVLCZigzag_Inter,r12
+
+
+
+
+ LDR pZigzagTable, =armVCM4P2_aClassicalZigzagScan ;// Load zigzag table
+ M_STR pZigzagTable,ppZigzagTable ;// Store zigzag table on stack to pass as argument to unsafe function
+ LDR pVlcTableL0L1, =armVCM4P2_InterVlcL0L1 ;// Load optimized VLC table with both L=0 and L=1 entries
+ M_STR pVlcTableL0L1,ppVlcTableL0L1 ;// Store optimized VLC table address on stack
+ LDR pLMAXTableL0L1, =armVCM4P2_InterL0L1LMAX ;// Load Interleaved L=0 and L=1 LMAX Tables
+ M_STR pLMAXTableL0L1,ppLMAXTableL0L1 ;// Store LMAX table address on stack
+ LDR pRMAXTableL0L1, =armVCM4P2_InterL0L1RMAX ;// Load Interleaved L=0 and L=1 RMAX Tables
+ MOV Count,#0 ;// set start=0
+ M_STR pRMAXTableL0L1,ppRMAXTableL0L1 ;// store RMAX table address on stack
+
+
+ BL armVCM4P2_DecodeVLCZigzag_AC_unsafe ;// call Unsafe Function for VLC Zigzag Decoding
+
+
+
+ M_END
+ ENDIF
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
new file mode 100755
index 0000000..9a37ec9
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
@@ -0,0 +1,136 @@
+;/**
+; *
+; * File Name: omxVCM4P2_DecodeVLCZigzag_IntraACVLC_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 12290
+; * Date: Wednesday, April 9, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains modules for zigzag scanning and VLC decoding
+; * for inter block.
+; *
+; *
+; *
+; * Function: omxVCM4P2_DecodeVLCZigzag_Inter
+; *
+; * Description:
+; * Performs VLC decoding and inverse zigzag scan for one intra coded block.
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] ppBitStream pointer to the pointer to the current byte in
+; * the bitstream buffer
+; * [in] pBitOffset pointer to the bit position in the byte pointed
+; * to by *ppBitStream. *pBitOffset is valid within [0-7].
+; * [in] shortVideoHeader binary flag indicating presence of short_video_header;
+; * escape modes 0-3 are used if shortVideoHeader==0,
+; * and escape mode 4 is used when shortVideoHeader==1.
+; * [out] ppBitStream *ppBitStream is updated after the block is
+; * decoded, so that it points to the current byte
+; * in the bit stream buffer
+; * [out] pBitOffset *pBitOffset is updated so that it points to the
+; * current bit position in the byte pointed by
+; * *ppBitStream
+; * [out] pDst pointer to the coefficient buffer of current
+; * block. Must be 16-byte aligned
+; *
+; * Return Value:
+; * OMX_Sts_BadArgErr - bad arguments
+; * -At least one of the following pointers is NULL: ppBitStream, *ppBitStream, pBitOffset, pDst, or
+; * -pDst is not 16-byte aligned, or
+; * -*pBitOffset exceeds [0,7].
+; * OMX_Sts_Err - status error
+; * -At least one mark bit is equal to zero
+; * -Encountered an illegal stream code that cannot be found in the VLC table
+; * -Encountered and illegal code in the VLC FLC table
+; * -The number of coefficients is greater than 64
+; *
+; */
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armCOMM_BitDec_s.h
+
+
+ M_VARIANTS ARM1136JS
+
+
+
+
+
+ IF ARM1136JS
+
+ ;// Import various tables needed for the function
+
+
+ IMPORT armVCM4P2_IntraVlcL0L1 ;// Contains optimized and packed VLC Tables for both Last =1 and last=0
+ ;// Packed in Run:Level:Last format
+ IMPORT armVCM4P2_IntraL0L1LMAX ;// Contains LMAX table entries with both Last=0 and Last=1
+ IMPORT armVCM4P2_IntraL0L1RMAX ;// Contains RMAX table entries with both Last=0 and Last=1
+ IMPORT armVCM4P2_aClassicalZigzagScan ;// contains classical Zigzag table entries with double the original values
+ IMPORT armVCM4P2_DecodeVLCZigzag_AC_unsafe
+
+;//Input Arguments
+
+ppBitStream RN 0
+pBitOffset RN 1
+pDst RN 2
+PredDir RN 3
+shortVideoHeader RN 3
+
+;//Local Variables
+
+Return RN 0
+
+pVlcTableL0L1 RN 4
+pLMAXTableL0L1 RN 4
+pRMAXTableL0L1 RN 4
+pZigzagTable RN 4
+Count RN 6
+
+
+
+ ;// Allocate stack memory to store optimized VLC,Zigzag, RMAX, LMAX Table Addresses
+
+ M_ALLOC4 ppVlcTableL0L1,4
+ M_ALLOC4 ppLMAXTableL0L1,4
+ M_ALLOC4 ppRMAXTableL0L1,4
+ M_ALLOC4 ppZigzagTable,4
+
+
+ M_START omxVCM4P2_DecodeVLCZigzag_IntraACVLC,r12
+
+ M_ARG shortVideoHeaderonStack,4 ;// pointer to Input Argument on stack
+
+ LDR pZigzagTable, =armVCM4P2_aClassicalZigzagScan ;// Load Address of the Zigzag table
+ ADD pZigzagTable, pZigzagTable, PredDir, LSL #6 ;// Loading Different type of zigzag tables based on PredDir
+
+ M_STR pZigzagTable,ppZigzagTable ;// Store Zigzag table address on stack
+ LDR pVlcTableL0L1, =armVCM4P2_IntraVlcL0L1 ;// Load optimized packed VLC Table with both L=0 and L=1 entries
+ M_STR pVlcTableL0L1,ppVlcTableL0L1 ;// Store VLC Table address on stack
+ LDR pLMAXTableL0L1, =armVCM4P2_IntraL0L1LMAX ;// Load LMAX Table
+ M_STR pLMAXTableL0L1,ppLMAXTableL0L1 ;// Store LMAX Table address on Stack
+ LDR pRMAXTableL0L1, =armVCM4P2_IntraL0L1RMAX ;// Load RMAX Table
+ MOV Count,#0 ;// Set Start=0
+
+ M_STR pRMAXTableL0L1,ppRMAXTableL0L1 ;// Store RMAX Table address on stack
+
+
+
+ M_LDR shortVideoHeader,shortVideoHeaderonStack ;// get the Input Argument from stack
+
+ BL armVCM4P2_DecodeVLCZigzag_AC_unsafe ;// Call Unsafe Function
+
+
+
+
+ M_END
+ ENDIF
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
new file mode 100755
index 0000000..778aaf2
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
@@ -0,0 +1,224 @@
+;/**
+; *
+; * File Name: omxVCM4P2_DecodeVLCZigzag_IntraDCVLC_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 12290
+; * Date: Wednesday, April 9, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains modules for zigzag scanning and VLC decoding
+; * for inter block.
+; *
+; *
+; *
+; * Function: omxVCM4P2_DecodeVLCZigzag_Inter
+; *
+; * Description:
+; * Performs VLC decoding and inverse zigzag scan for one intra coded block.
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] ppBitStream pointer to the pointer to the current byte in
+; * the bitstream buffer
+; * [in] pBitOffset pointer to the bit position in the byte pointed
+; * to by *ppBitStream. *pBitOffset is valid within [0-7].
+; * [in] shortVideoHeader binary flag indicating presence of short_video_header;
+; * escape modes 0-3 are used if shortVideoHeader==0,
+; * and escape mode 4 is used when shortVideoHeader==1.
+; * [out] ppBitStream *ppBitStream is updated after the block is
+; * decoded, so that it points to the current byte
+; * in the bit stream buffer
+; * [out] pBitOffset *pBitOffset is updated so that it points to the
+; * current bit position in the byte pointed by
+; * *ppBitStream
+; * [out] pDst pointer to the coefficient buffer of current
+; * block. Must be 16-byte aligned
+; *
+; * Return Value:
+; * OMX_Sts_BadArgErr - bad arguments
+; * -At least one of the following pointers is NULL: ppBitStream, *ppBitStream, pBitOffset, pDst, or
+; * -pDst is not 16-byte aligned, or
+; * -*pBitOffset exceeds [0,7].
+; * OMX_Sts_Err - status error
+; * -At least one mark bit is equal to zero
+; * -Encountered an illegal stream code that cannot be found in the VLC table
+; * -Encountered and illegal code in the VLC FLC table
+; * -The number of coefficients is greater than 64
+; *
+; */
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armCOMM_BitDec_s.h
+
+
+ M_VARIANTS CortexA8
+
+
+
+
+
+ IF CortexA8
+
+
+ ;// Import various tables needed for the function
+
+
+ IMPORT armVCM4P2_IntraVlcL0L1 ;// Contains optimized and packed VLC Tables for both Last =1 and last=0
+ ;// Packed in Run:Level:Last format
+ IMPORT armVCM4P2_IntraL0L1LMAX ;// Contains LMAX table entries with both Last=0 and Last=1
+ IMPORT armVCM4P2_IntraL0L1RMAX ;// Contains RMAX table entries with both Last=0 and Last=1
+ IMPORT armVCM4P2_aClassicalZigzagScan ;// contains CLassical, Horizontal, Vertical Zigzag table entries with double the original values
+ IMPORT armVCM4P2_aIntraDCLumaChromaIndex ;// Contains Optimized DCLuma and DCChroma Index table Entries
+
+
+ IMPORT armVCM4P2_DecodeVLCZigzag_AC_unsafe
+
+;//Input Arguments
+
+ppBitStream RN 0
+pBitOffset RN 1
+pDst RN 2
+PredDir RN 3
+shortVideoHeader RN 3
+videoComp RN 5
+;//Local Variables
+
+Return RN 0
+
+pDCLumaChromaIndex RN 4
+pDCChromaIndex RN 7
+pVlcTableL0L1 RN 4
+pLMAXTableL0L1 RN 4
+pRMAXTableL0L1 RN 4
+pZigzagTable RN 4
+Count RN 6
+DCValueSize RN 6
+powOfSize RN 7
+temp1 RN 5
+
+
+;// Scratch Registers
+
+RBitStream RN 8
+RBitBuffer RN 9
+RBitCount RN 10
+
+T1 RN 11
+T2 RN 12
+DCVal RN 14
+
+
+ ;// Allocate stack memory to store optimized VLC,Zigzag, RMAX, LMAX Table Addresses
+
+ M_ALLOC4 ppVlcTableL0L1,4
+ M_ALLOC4 ppLMAXTableL0L1,4
+ M_ALLOC4 ppRMAXTableL0L1,4
+ M_ALLOC4 ppZigzagTable,4
+ M_ALLOC4 pDCCoeff,4
+
+
+
+ M_START omxVCM4P2_DecodeVLCZigzag_IntraDCVLC,r12
+
+ M_ARG shortVideoHeaderonStack,4 ;// Pointer to argument on stack
+ M_ARG videoComponstack,4 ;// Pointer to argument on stack
+
+
+ ;// Decode DC Coefficient
+
+
+ LDR pDCLumaChromaIndex, =armVCM4P2_aIntraDCLumaChromaIndex ;// Load Optimized VLC Table for Luminance and Chrominance
+
+ ;// Initializing the Bitstream Macro
+
+ M_BD_INIT0 ppBitStream, pBitOffset, RBitStream, RBitBuffer, RBitCount
+ M_LDR videoComp,videoComponstack
+ M_BD_INIT1 T1, T2, T2
+ ADD pDCLumaChromaIndex,pDCLumaChromaIndex,videoComp, LSL #6
+ M_BD_INIT2 T1, T2, T2
+
+
+ M_BD_VLD DCValueSize,T1,T2,pDCLumaChromaIndex,4,2 ;// VLC Decode using optimized Luminance and Chrominance VLC Table
+
+
+
+
+DecodeDC
+
+ CMP DCValueSize,#12
+ BGT ExitError
+
+ CMP DCValueSize,#0
+ MOVEQ DCVal,#0 ;// If DCValueSize is zero then DC coeff =0
+ BEQ ACDecode ;// Branch to perform AC Coeff Decoding
+
+ M_BD_VREAD16 DCVal,DCValueSize,T1,T2 ;// Get DC Value From Bit stream
+
+
+ MOV powOfSize,#1
+ LSL powOfSize,DCValueSize ;// powOfSize=pow(2,DCValueSize)
+ CMP DCVal,powOfSize,LSR #1 ;// Compare DCVal with powOfSize/2
+ ADDLT DCVal,DCVal,#1
+ SUBLT DCVal,DCVal,powOfSize ;// If Lessthan powOfSize/2 DCVal=DCVal-powOfSize+1
+ ;// Else DCVal= fetchbits from bit stream
+
+CheckDCValueSize
+
+ CMP DCValueSize,#8 ;// If DCValueSize greater than 8 check marker bit
+
+ BLE ACDecode
+
+ M_BD_READ8 temp1,1,T1
+ TEQ temp1,#0 ;// If Marker bit is zero Exit with an Error Message
+ BEQ ExitError
+
+
+
+ ;// Decode AC Coefficient
+
+ACDecode
+
+ M_STR DCVal,pDCCoeff ;// Store Decoded DC Coeff on Stack
+ M_BD_FINI ppBitStream,pBitOffset ;// Terminating the Bit stream Macro
+
+ LDR pZigzagTable, =armVCM4P2_aClassicalZigzagScan ;// Load Zigzag talbe address
+ ADD pZigzagTable, pZigzagTable, PredDir, LSL #6 ;// Modify the Zigzag table adress based on PredDir
+
+ M_STR pZigzagTable,ppZigzagTable ;// Store zigzag table on stack
+ LDR pVlcTableL0L1, =armVCM4P2_IntraVlcL0L1 ;// Load Optimized VLC Table With both Last=0 and Last=1 Entries
+ M_STR pVlcTableL0L1,ppVlcTableL0L1 ;// Store Optimized VLC Table on stack
+ LDR pLMAXTableL0L1, =armVCM4P2_IntraL0L1LMAX ;// Load LMAX Table
+ M_STR pLMAXTableL0L1,ppLMAXTableL0L1 ;// Store LMAX table on stack
+ LDR pRMAXTableL0L1, =armVCM4P2_IntraL0L1RMAX ;// Load RMAX Table
+ MOV Count,#1 ;// Set Start =1
+
+ M_STR pRMAXTableL0L1,ppRMAXTableL0L1 ;// Store RMAX Table on Stack
+
+
+ M_LDR shortVideoHeader,shortVideoHeaderonStack ;// Load the Input Argument From Stack
+
+ BL armVCM4P2_DecodeVLCZigzag_AC_unsafe ;// Call the Unsafe Function
+
+ M_LDR DCVal,pDCCoeff ;// Get the Decoded DC Value From Stack
+ STRH DCVal,[pDst] ;// Store the DC Value
+ B ExitOK
+
+
+
+ExitError
+
+ M_BD_FINI ppBitStream,pBitOffset ;// Terminating the Bit Stream Macro in case of an Error
+ MOV Return,#OMX_Sts_Err ;// Exit with an Error Message
+ExitOK
+
+ M_END
+ ENDIF
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
new file mode 100755
index 0000000..caf7121
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_FindMVpred_s.s
@@ -0,0 +1,194 @@
+;//
+;//
+;// File Name: omxVCM4P2_FindMVpred_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+;// Function:
+;// omxVCM4P2_FindMVpred
+;//
+ ;// Include headers
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+ INCLUDE armVCCOMM_s.h
+
+ ;// Define cpu variants
+ M_VARIANTS CortexA8
+
+
+ IF CortexA8
+
+ M_TABLE armVCM4P2_pBlkIndexTable
+ DCD OMXVCBlk0, OMXVCBlk1
+ DCD OMXVCBlk2, OMXVCBlk3
+
+;//--------------------------------------------
+;// Declare input registers
+;//--------------------------------------------
+
+pSrcMVCurMB RN 0
+pSrcCandMV1 RN 1
+pSrcCandMV2 RN 2
+pSrcCandMV3 RN 3
+pDstMVPred RN 4
+pDstMVPredME RN 5
+iBlk RN 6
+
+pTable RN 4
+CandMV RN 12
+
+pCandMV1 RN 7
+pCandMV2 RN 8
+pCandMV3 RN 9
+
+CandMV1dx RN 0
+CandMV1dy RN 1
+CandMV2dx RN 2
+CandMV2dy RN 3
+CandMV3dx RN 10
+CandMV3dy RN 11
+
+temp RN 14
+
+zero RN 14
+return RN 0
+
+; ----------------------------------------------
+; Main routine
+; ----------------------------------------------
+
+ M_ALLOC4 MV, 4
+
+ ;// Function header
+ M_START omxVCM4P2_FindMVpred, r11
+
+ ;// Define stack arguments
+ M_ARG ppDstMVPred, 4
+ M_ARG ppDstMVPredME, 4
+ M_ARG Blk, 4
+
+ M_ADR CandMV, MV
+ MOV zero, #0
+ M_LDR iBlk, Blk
+
+ ;// Set the default value for these
+ ;// to be used if pSrcCandMV[1|2|3] == NULL
+ MOV pCandMV1, CandMV
+ MOV pCandMV2, CandMV
+ MOV pCandMV3, CandMV
+
+ STR zero, [CandMV]
+
+ ;// Branch to the case based on blk number
+ M_SWITCH iBlk
+ M_CASE OMXVCBlk0 ;// iBlk=0
+ M_CASE OMXVCBlk1 ;// iBlk=0
+ M_CASE OMXVCBlk2 ;// iBlk=0
+ M_CASE OMXVCBlk3 ;// iBlk=0
+ M_ENDSWITCH
+
+OMXVCBlk0
+ CMP pSrcCandMV1, #0
+ ADDNE pCandMV1, pSrcCandMV1, #4
+
+ CMP pSrcCandMV2, #0
+ ADDNE pCandMV2, pSrcCandMV2, #8
+
+ CMP pSrcCandMV3, #0
+ ADDNE pCandMV3, pSrcCandMV3, #8
+ CMPEQ pSrcCandMV1, #0
+
+ MOVEQ pCandMV3, pCandMV2
+ MOVEQ pCandMV1, pCandMV2
+
+ CMP pSrcCandMV1, #0
+ CMPEQ pSrcCandMV2, #0
+
+ MOVEQ pCandMV1, pCandMV3
+ MOVEQ pCandMV2, pCandMV3
+
+ CMP pSrcCandMV2, #0
+ CMPEQ pSrcCandMV3, #0
+
+ MOVEQ pCandMV2, pCandMV1
+ MOVEQ pCandMV3, pCandMV1
+
+ B BlkEnd
+
+OMXVCBlk1
+ MOV pCandMV1, pSrcMVCurMB
+ CMP pSrcCandMV3, #0
+ ADDNE pCandMV3, pSrcCandMV3, #8
+
+ CMP pSrcCandMV2, #0
+ ADDNE pCandMV2, pSrcCandMV2, #12
+
+ CMPEQ pSrcCandMV3, #0
+
+ MOVEQ pCandMV2, pCandMV1
+ MOVEQ pCandMV3, pCandMV1
+
+ B BlkEnd
+
+OMXVCBlk2
+ CMP pSrcCandMV1, #0
+ MOV pCandMV2, pSrcMVCurMB
+ ADD pCandMV3, pSrcMVCurMB, #4
+ ADDNE pCandMV1, pSrcCandMV1, #12
+ B BlkEnd
+
+OMXVCBlk3
+ ADD pCandMV1, pSrcMVCurMB, #8
+ MOV pCandMV2, pSrcMVCurMB
+ ADD pCandMV3, pSrcMVCurMB, #4
+
+BlkEnd
+
+ ;// Using the transperancy info, zero
+ ;// out the candidate MV if neccesary
+ LDRSH CandMV1dx, [pCandMV1], #2
+ LDRSH CandMV2dx, [pCandMV2], #2
+ LDRSH CandMV3dx, [pCandMV3], #2
+
+ ;// Load argument from the stack
+ M_LDR pDstMVPredME, ppDstMVPredME
+
+ LDRSH CandMV1dy, [pCandMV1]
+ LDRSH CandMV2dy, [pCandMV2]
+ LDRSH CandMV3dy, [pCandMV3]
+
+ CMP pDstMVPredME, #0
+
+ ;// Store the candidate MV's into the pDstMVPredME,
+ ;// these can be used in the fast algorithm if implemented
+
+ STRHNE CandMV1dx, [pDstMVPredME], #2
+ STRHNE CandMV1dy, [pDstMVPredME], #2
+ STRHNE CandMV2dx, [pDstMVPredME], #2
+ STRHNE CandMV2dy, [pDstMVPredME], #2
+ STRHNE CandMV3dx, [pDstMVPredME], #2
+ STRHNE CandMV3dy, [pDstMVPredME]
+
+ ; Find the median of the 3 candidate MV's
+ M_MEDIAN3 CandMV1dx, CandMV2dx, CandMV3dx, temp
+
+ ;// Load argument from the stack
+ M_LDR pDstMVPred, ppDstMVPred
+
+ M_MEDIAN3 CandMV1dy, CandMV2dy, CandMV3dy, temp
+
+ STRH CandMV3dx, [pDstMVPred], #2
+ STRH CandMV3dy, [pDstMVPred]
+
+ MOV return, #OMX_Sts_NoErr
+
+ M_END
+ ENDIF ;// ARM1136JS :LOR: CortexA8
+
+ END \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
new file mode 100755
index 0000000..b5e3d0d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_IDCT8x8blk_s.s
@@ -0,0 +1,73 @@
+;//
+;//
+;// File Name: omxVCM4P2_IDCT8x8blk_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+
+;// Function:
+;// omxVCM4P2_IDCT8x8blk
+;//
+ ;// Include headers
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ ;// Define cpu variants
+ M_VARIANTS CortexA8
+
+ INCLUDE armCOMM_IDCT_s.h
+
+ IMPORT armCOMM_IDCTPreScale
+ ;//
+ ;// Function prototype
+ ;//
+ ;// OMXResult
+ ;// omxVCM4P2_IDCT8x8blk(const OMX_S16* pSrc,
+ ;// OMX_S16* pDst)
+ ;//
+
+ IF CortexA8
+ M_ALLOC4 ppDest, 4
+ M_ALLOC4 pStride, 4
+ M_ALLOC8 pBlk, 2*8*8
+ ENDIF
+
+
+ IF CortexA8
+ M_START omxVCM4P2_IDCT8x8blk, r11, d15
+ ENDIF
+
+ IF CortexA8
+
+;// Declare input registers
+pSrc RN 0
+pDst RN 1
+
+;// Declare other intermediate registers
+Result RN 0
+
+;// Prototype for macro M_IDCT
+;// pSrc RN 0 ;// source data buffer
+;// Stride RN 1 ;// destination stride in bytes
+;// pDest RN 2 ;// destination data buffer
+;// pScale RN 3 ;// pointer to scaling table
+
+pSrc RN 0
+Stride RN 1
+pDest RN 2
+pScale RN 3
+
+ MOV pDest, pDst
+ LDR pScale, =armCOMM_IDCTPreScale
+ M_IDCT s9, s16, 16
+ MOV Result, #OMX_Sts_NoErr
+ M_END
+ ENDIF
+ ;// ARM1136JS :LOR: CortexA8
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
new file mode 100755
index 0000000..dd00df5
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_MCReconBlock_s.s
@@ -0,0 +1,444 @@
+;//
+;//
+;// File Name: omxVCM4P2_MCReconBlock_s.s
+;// OpenMAX DL: v1.0.2
+;// Revision: 12290
+;// Date: Wednesday, April 9, 2008
+;//
+;// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+;//
+;//
+;//
+;// Description:
+;//
+;//
+
+;// Include standard headers
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+;// Import symbols required from other files
+
+ M_VARIANTS CortexA8
+
+;// ***************************************************************************
+;// ARM1136JS implementation
+;// ***************************************************************************
+
+;// ***************************************************************************
+;// CortexA8 implementation
+;// ***************************************************************************
+ IF CortexA8
+;// ***************************************************************************
+;// MACRO DEFINITIONS
+;// ***************************************************************************
+ ;// Description:
+ ;// Does interpolation for the case of "IntegerPixel" predictType. Both
+ ;// rounding cases are handled. Just copies a block from pSrc to pDst
+ ;//
+ ;// Syntax:
+ ;// M_MCRECONBLOCK_IntegerPixel
+ ;//
+ ;// Inputs: None
+ ;// Outputs: None
+
+ MACRO
+ M_MCRECONBLOCK_IntegerPixel
+CaseIntegerPixel_Rnd0
+CaseIntegerPixel_Rnd1
+
+ VLD1 dRow0, [pSrc], srcStep
+ VLD1 dRow1, [pSrc], srcStep
+ VLD1 dRow2, [pSrc], srcStep
+ VLD1 dRow3, [pSrc], srcStep
+ VLD1 dRow4, [pSrc], srcStep
+ VLD1 dRow5, [pSrc], srcStep
+ VLD1 dRow6, [pSrc], srcStep
+ VLD1 dRow7, [pSrc], srcStep
+
+ VST1 dRow0, [pDst@64], dstStep
+ VST1 dRow1, [pDst@64], dstStep
+ VST1 dRow2, [pDst@64], dstStep
+ VST1 dRow3, [pDst@64], dstStep
+ VST1 dRow4, [pDst@64], dstStep
+ VST1 dRow5, [pDst@64], dstStep
+ VST1 dRow6, [pDst@64], dstStep
+ VST1 dRow7, [pDst@64], dstStep
+
+ B SwitchPredictTypeEnd
+ MEND
+;// ***************************************************************************
+ ;// Description:
+ ;// Does interpolation for the case of "HalfPixelX" predictType. The two
+ ;// rounding cases are handled by the parameter "$rndVal". Averages between
+ ;// a pixel and pixel right to it, rounding it based on $rndVal. The
+ ;// rounding is implemented by using opCode switching between "VRHADD" and
+ ;// "VHADD" instructions.
+ ;//
+ ;// Syntax:
+ ;// M_MCRECONBLOCK_HalfPixelX $rndVal
+ ;//
+ ;// Inputs:
+ ;// $rndVal: 0 for rounding and 1 for no rounding
+ ;// Outputs: None
+
+ MACRO
+ M_MCRECONBLOCK_HalfPixelX $rndVal
+
+ LCLS M_VHADDR
+ IF $rndVal = 0
+M_VHADDR SETS "VRHADD"
+ ELSE
+M_VHADDR SETS "VHADD"
+ ENDIF
+
+CaseHalfPixelX_Rnd$rndVal
+
+ VLD1 {dRow0, dRow0Shft}, [pSrc], srcStep
+ VEXT dRow0Shft, dRow0, dRow0Shft, #1
+ VLD1 {dRow1, dRow1Shft}, [pSrc], srcStep
+ VEXT dRow1Shft, dRow1, dRow1Shft, #1
+ VLD1 {dRow2, dRow2Shft}, [pSrc], srcStep
+ VEXT dRow2Shft, dRow2, dRow2Shft, #1
+ VLD1 {dRow3, dRow3Shft}, [pSrc], srcStep
+ VEXT dRow3Shft, dRow3, dRow3Shft, #1
+ VLD1 {dRow4, dRow4Shft}, [pSrc], srcStep
+ VEXT dRow4Shft, dRow4, dRow4Shft, #1
+ VLD1 {dRow5, dRow5Shft}, [pSrc], srcStep
+ VEXT dRow5Shft, dRow5, dRow5Shft, #1
+ VLD1 {dRow6, dRow6Shft}, [pSrc], srcStep
+ VEXT dRow6Shft, dRow6, dRow6Shft, #1
+ VLD1 {dRow7, dRow7Shft}, [pSrc], srcStep
+ VEXT dRow7Shft, dRow7, dRow7Shft, #1
+ $M_VHADDR dRow0, dRow0, dRow0Shft
+ $M_VHADDR dRow1, dRow1, dRow1Shft
+ VST1 dRow0, [pDst@64], dstStep
+ $M_VHADDR dRow2, dRow2, dRow2Shft
+ VST1 dRow1, [pDst@64], dstStep
+ $M_VHADDR dRow3, dRow3, dRow3Shft
+ VST1 dRow2, [pDst@64], dstStep
+ $M_VHADDR dRow4, dRow4, dRow4Shft
+ VST1 dRow3, [pDst@64], dstStep
+ $M_VHADDR dRow5, dRow5, dRow5Shft
+ VST1 dRow4, [pDst@64], dstStep
+ $M_VHADDR dRow6, dRow6, dRow6Shft
+ VST1 dRow5, [pDst@64], dstStep
+ $M_VHADDR dRow7, dRow7, dRow7Shft
+ VST1 dRow6, [pDst@64], dstStep
+ VST1 dRow7, [pDst@64], dstStep
+
+ B SwitchPredictTypeEnd
+ MEND
+;// ***************************************************************************
+ ;// Description:
+ ;// Does interpolation for the case of "HalfPixelY" predictType. The two
+ ;// rounding cases are handled by the parameter "$rndVal". Averages between
+ ;// a pixel and pixel below it, rounding it based on $rndVal. The
+ ;// rounding is implemented by using opCode switching between "VRHADD" and
+ ;// "VHADD" instructions.
+ ;//
+ ;// Syntax:
+ ;// M_MCRECONBLOCK_HalfPixelY $rndVal
+ ;//
+ ;// Inputs:
+ ;// $rndVal: 0 for rounding and 1 for no rounding
+ ;// Outputs: None
+
+ MACRO
+ M_MCRECONBLOCK_HalfPixelY $rndVal
+
+ LCLS M_VHADDR
+ IF $rndVal = 0
+M_VHADDR SETS "VRHADD"
+ ELSE
+M_VHADDR SETS "VHADD"
+ ENDIF
+
+CaseHalfPixelY_Rnd$rndVal
+ VLD1 dRow0, [pSrc], srcStep
+ VLD1 dRow1, [pSrc], srcStep
+ VLD1 dRow2, [pSrc], srcStep
+ VLD1 dRow3, [pSrc], srcStep
+ VLD1 dRow4, [pSrc], srcStep
+ VLD1 dRow5, [pSrc], srcStep
+ VLD1 dRow6, [pSrc], srcStep
+ VLD1 dRow7, [pSrc], srcStep
+ $M_VHADDR dRow0, dRow0, dRow1
+ VLD1 dRow8, [pSrc], srcStep
+ $M_VHADDR dRow1, dRow1, dRow2
+ VST1 dRow0, [pDst@64], dstStep
+ $M_VHADDR dRow2, dRow2, dRow3
+ VST1 dRow1, [pDst@64], dstStep
+ $M_VHADDR dRow3, dRow3, dRow4
+ VST1 dRow2, [pDst@64], dstStep
+ $M_VHADDR dRow4, dRow4, dRow5
+ VST1 dRow3, [pDst@64], dstStep
+ $M_VHADDR dRow5, dRow5, dRow6
+ VST1 dRow4, [pDst@64], dstStep
+ $M_VHADDR dRow6, dRow6, dRow7
+ VST1 dRow5, [pDst@64], dstStep
+ $M_VHADDR dRow7, dRow7, dRow8
+ VST1 dRow6, [pDst@64], dstStep
+ VST1 dRow7, [pDst@64], dstStep
+
+ B SwitchPredictTypeEnd
+ MEND
+;// ***************************************************************************
+ ;// Description:
+ ;// Does interpolation for the case of "IntegerPixel" predictType. Both
+ ;// rounding cases are handled.
+ ;// Typical computation for a row goes like this
+ ;// 1. VLD1 {dRow0, dRow0Shft}, [pSrc], srcStep ;// Load the row and next 8 bytes
+ ;// 2. VEXT dRow0Shft, dRow0, dRow0Shft, #1 ;// Generate the shifted row
+ ;// 3. VADDL qSum0, dRow0, dRow0Shft ;// Generate the sum of row and shifted row
+ ;// 5. VADD qSum0, qSum0, qSum1 ;// Add to the sum of next row (odd row sum has rounding value added to it)
+ ;// 6. VSHRN dRow0, qSum0, #2 ;// Divide by 4
+ ;// 7. VST1 dRow0, [pDst@64], dstStep ;// Store
+ ;// Odd rows undergo following computation after step 3
+ ;// 4. VADD qSum1, qSum1, qRound
+ ;// This saves for adding rounding value to each final sum (overall saves 4
+ ;// instructions).
+ ;// There is reuse of registers for qSum6, qSum7 & qSum8. Overall scheduling takes
+ ;// care of this and also minimizes stalls. Rounding value was modified in
+ ;// ARM register rndVal (originally used for rounding flag) before the switch.
+ ;// It is then populated into all lanes in this macro. No branching out to
+ ;// label "SwitchPredictTypeEnd" is required in the end of the macro as these
+ ;// are the last of switch cases.
+ ;//
+ ;// Syntax:
+ ;// M_MCRECONBLOCK_HalfPixelXY
+ ;//
+ ;// Inputs: None
+ ;// Outputs: None
+
+ MACRO
+ M_MCRECONBLOCK_HalfPixelXY
+
+CaseHalfPixelXY_Rnd0
+CaseHalfPixelXY_Rnd1
+ VLD1 {dRow0, dRow0Shft}, [pSrc], srcStep
+ VDUP qRound, rndVal
+ VLD1 {dRow1, dRow1Shft}, [pSrc], srcStep
+ VEXT dRow0Shft, dRow0, dRow0Shft, #1
+ VLD1 {dRow2, dRow2Shft}, [pSrc], srcStep
+ VEXT dRow1Shft, dRow1, dRow1Shft, #1
+ VLD1 {dRow3, dRow3Shft}, [pSrc], srcStep
+ VEXT dRow2Shft, dRow2, dRow2Shft, #1
+ VLD1 {dRow4, dRow4Shft}, [pSrc], srcStep
+ VADDL qSum0, dRow0, dRow0Shft
+ VLD1 {dRow5, dRow5Shft}, [pSrc], srcStep
+ VADDL qSum1, dRow1, dRow1Shft
+ VLD1 {dRow6, dRow6Shft}, [pSrc], srcStep
+ VEXT dRow3Shft, dRow3, dRow3Shft, #1
+ VLD1 {dRow7, dRow7Shft}, [pSrc], srcStep
+ VEXT dRow4Shft, dRow4, dRow4Shft, #1
+ VLD1 {dRow8, dRow8Shft}, [pSrc], srcStep
+ VADD qSum1, qSum1, qRound
+ VADDL qSum2, dRow2, dRow2Shft
+ VEXT dRow5Shft, dRow5, dRow5Shft, #1
+ VADD qSum0, qSum0, qSum1
+ VADDL qSum3, dRow3, dRow3Shft
+ VEXT dRow6Shft, dRow6, dRow6Shft, #1
+ VADD qSum1, qSum1, qSum2
+ VSHRN dRow0, qSum0, #2
+ VADDL qSum4, dRow4, dRow4Shft
+ VSHRN dRow1, qSum1, #2
+ VADD qSum3, qSum3, qRound
+ VADDL qSum5, dRow5, dRow5Shft
+ VST1 dRow0, [pDst@64], dstStep
+ VEXT dRow7Shft, dRow7, dRow7Shft, #1
+ VST1 dRow1, [pDst@64], dstStep
+ VEXT dRow8Shft, dRow8, dRow8Shft, #1
+ VADD qSum5, qSum5, qRound
+ VADD qSum2, qSum2, qSum3
+ VADD qSum3, qSum3, qSum4
+ VADD qSum4, qSum4, qSum5
+ VSHRN dRow2, qSum2, #2
+ VSHRN dRow3, qSum3, #2
+ VSHRN dRow4, qSum4, #2
+ VADDL qSum6, dRow6, dRow6Shft
+ VADDL qSum7, dRow7, dRow7Shft
+ VST1 dRow2, [pDst@64], dstStep
+ VADDL qSum8, dRow8, dRow8Shft
+ VADD qSum7, qSum7, qRound
+ VST1 dRow3, [pDst@64], dstStep
+ VST1 dRow4, [pDst@64], dstStep
+ VADD qSum5, qSum5, qSum6
+ VADD qSum6, qSum6, qSum7
+ VADD qSum7, qSum7, qSum8
+ VSHRN dRow5, qSum5, #2
+ VSHRN dRow6, qSum6, #2
+ VSHRN dRow7, qSum7, #2
+ VST1 dRow5, [pDst@64], dstStep
+ VST1 dRow6, [pDst@64], dstStep
+ VST1 dRow7, [pDst@64], dstStep
+
+ MEND
+;// ***************************************************************************
+
+;// Input/Output Registers
+pSrc RN 0
+srcStep RN 1
+pSrcResidue RN 2
+pDst RN 3
+dstStep RN 4
+predictType RN 5
+rndVal RN 6
+
+;// Local Scratch Registers
+pDstCopy RN 0
+return RN 0
+
+;// Neon Registers
+dRow0 DN D0.U8
+dRow0Shft DN D1.U8
+dRow1 DN D2.U8
+dRow1Shft DN D3.U8
+dRow2 DN D4.U8
+dRow2Shft DN D5.U8
+dRow3 DN D6.U8
+dRow3Shft DN D7.U8
+dRow4 DN D8.U8
+dRow4Shft DN D9.U8
+dRow5 DN D10.U8
+dRow5Shft DN D11.U8
+dRow6 DN D12.U8
+dRow6Shft DN D13.U8
+dRow7 DN D14.U8
+dRow7Shft DN D15.U8
+dRow8 DN D16.U8
+dRow8Shft DN D17.U8
+
+
+qSum0 QN Q9.U16
+qSum1 QN Q10.U16
+qSum2 QN Q11.U16
+qSum3 QN Q12.U16
+qSum4 QN Q13.U16
+qSum5 QN Q14.U16
+qSum6 QN Q0.U16
+qSum7 QN Q1.U16
+qSum8 QN Q2.U16
+
+qRound QN Q15.U16
+
+dDst0 DN D0.U8
+dDst1 DN D1.U8
+dDst2 DN D2.U8
+dDst3 DN D3.U8
+dDst4 DN D4.U8
+dDst5 DN D5.U8
+dDst6 DN D6.U8
+dDst7 DN D7.U8
+
+qRes0 QN Q4.S16
+qRes1 QN Q5.S16
+qRes2 QN Q6.S16
+qRes3 QN Q7.S16
+qRes4 QN Q8.S16
+qRes5 QN Q9.S16
+qRes6 QN Q10.S16
+qRes7 QN Q11.S16
+
+ ;// Function header
+ M_START omxVCM4P2_MCReconBlock, r6, d15
+ ;// Define stack arguments
+ M_ARG Arg_dstStep, 4
+ M_ARG Arg_predictType, 4
+ M_ARG Arg_rndVal, 4
+ ;// Load argument from the stack
+ M_LDR dstStep, Arg_dstStep
+ M_LDR predictType, Arg_predictType
+ M_LDR rndVal, Arg_rndVal
+ ADD predictType, rndVal, predictType, LSL #1
+ RSB rndVal, rndVal, #2 ;// preparing rndVal for HalfPixelXY
+
+ ;// The following is implementation of switching to different code segments
+ ;// based on different predictType and rndVal flags. The corresponding
+ ;// labels (e.g. CaseIntegerPixel_Rnd0) are embedded in the macros following
+ ;// M_ENDSWITCH (e.g. M_MCRECONBLOCK_IntegerPixel). While "M_MCRECONBLOCK_IntegerPixel"
+ ;// and "M_MCRECONBLOCK_HalfPixelXY" handle for both rounding cases;
+ ;// "M_MCRECONBLOCK_HalfPixelX" and "M_MCRECONBLOCK_HalfPixelY" macros handle
+ ;// the two rounding cases in separate code bases.
+ ;// All these together implement the interpolation functionality
+
+ M_SWITCH predictType
+ M_CASE CaseIntegerPixel_Rnd0
+ M_CASE CaseIntegerPixel_Rnd1
+ M_CASE CaseHalfPixelX_Rnd0
+ M_CASE CaseHalfPixelX_Rnd1
+ M_CASE CaseHalfPixelY_Rnd0
+ M_CASE CaseHalfPixelY_Rnd1
+ M_CASE CaseHalfPixelXY_Rnd0
+ M_CASE CaseHalfPixelXY_Rnd1
+ M_ENDSWITCH
+
+ M_MCRECONBLOCK_IntegerPixel
+ M_MCRECONBLOCK_HalfPixelX 0
+ M_MCRECONBLOCK_HalfPixelX 1
+ M_MCRECONBLOCK_HalfPixelY 0
+ M_MCRECONBLOCK_HalfPixelY 1
+ M_MCRECONBLOCK_HalfPixelXY
+SwitchPredictTypeEnd
+
+ ;// After interpolation is done, residue needs to be added. This is done
+ ;// only in case "pSrcResidue" parameter to the function is not NULL.
+ ;// Following is a completely unrolled code to do so. Each row and
+ ;// corresponding residue is loaded and residue is added and value
+ ;// stored
+
+ CMP pSrcResidue, #0
+ SUBNE pDst, pDst, dstStep, LSL #3 ;// Restoring pDst
+ MOVNE pDstCopy, pDst
+ BEQ pSrcResidueConditionEnd
+pSrcResidueNotNull
+ VLD1 dDst0, [pDst@64], dstStep
+ VLD1 qRes0, [pSrcResidue@128]!
+ VLD1 dDst1, [pDst@64], dstStep
+ VLD1 qRes1, [pSrcResidue@128]!
+ VLD1 dDst2, [pDst@64], dstStep
+ VLD1 qRes2, [pSrcResidue@128]!
+ VADDW qRes0, qRes0, dDst0
+ VLD1 dDst3, [pDst@64], dstStep
+ VADDW qRes1, qRes1, dDst1
+ VLD1 qRes3, [pSrcResidue@128]!
+ VADDW qRes2, qRes2, dDst2
+ VLD1 dDst4, [pDst@64], dstStep
+ VQMOVUN dDst0, qRes0
+ VLD1 qRes4, [pSrcResidue@128]!
+ VADDW qRes3, qRes3, dDst3
+ VLD1 dDst5, [pDst@64], dstStep
+ VQMOVUN dDst1, qRes1
+ VLD1 qRes5, [pSrcResidue@128]!
+ VADDW qRes4, qRes4, dDst4
+ VLD1 dDst6, [pDst@64], dstStep
+ VQMOVUN dDst2, qRes2
+ VLD1 qRes6, [pSrcResidue@128]!
+ VADDW qRes5, qRes5, dDst5
+ VLD1 dDst7, [pDst@64], dstStep
+ VQMOVUN dDst3, qRes3
+ VLD1 qRes7, [pSrcResidue@128]!
+ VADDW qRes6, qRes6, dDst6
+ VST1 dDst0, [pDstCopy@64], dstStep
+ VQMOVUN dDst4, qRes4
+ VST1 dDst1, [pDstCopy@64], dstStep
+ VADDW qRes7, qRes7, dDst7
+ VST1 dDst2, [pDstCopy@64], dstStep
+ VQMOVUN dDst5, qRes5
+ VST1 dDst3, [pDstCopy@64], dstStep
+ VQMOVUN dDst6, qRes6
+ VST1 dDst4, [pDstCopy@64], dstStep
+ VQMOVUN dDst7, qRes7
+ VST1 dDst5, [pDstCopy@64], dstStep
+ VST1 dDst6, [pDstCopy@64], dstStep
+ VST1 dDst7, [pDstCopy@64], dstStep
+
+pSrcResidueConditionEnd
+ MOV return, #OMX_Sts_NoErr
+
+ M_END
+ ENDIF ;// CortexA8
+ END
+;// ***************************************************************************
+;// omxVCM4P2_MCReconBlock ends
+;// ***************************************************************************
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
new file mode 100755
index 0000000..a73f64a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra_s.s
@@ -0,0 +1,320 @@
+; **********
+; *
+; * File Name: omxVCM4P2_PredictReconCoefIntra_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 12290
+; * Date: Wednesday, April 9, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains module for DC/AC coefficient prediction
+; *
+; *
+; * Function: omxVCM4P2_PredictReconCoefIntra
+; *
+; * Description:
+; * Performs adaptive DC/AC coefficient prediction for an intra block. Prior
+; * to the function call, prediction direction (predDir) should be selected
+; * as specified in subclause 7.4.3.1 of ISO/IEC 14496-2.
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] pSrcDst pointer to the coefficient buffer which contains the
+; * quantized coefficient residuals (PQF) of the current
+; * block; must be aligned on a 4-byte boundary. The
+; * output coefficients are saturated to the range
+; * [-2048, 2047].
+; * [in] pPredBufRow pointer to the coefficient row buffer; must be aligned
+; * on a 4-byte boundary.
+; * [in] pPredBufCol pointer to the coefficient column buffer; must be
+; * aligned on a 4-byte boundary.
+; * [in] curQP quantization parameter of the current block. curQP may
+; * equal to predQP especially when the current block and
+; * the predictor block are in the same macroblock.
+; * [in] predQP quantization parameter of the predictor block
+; * [in] predDir indicates the prediction direction which takes one
+; * of the following values:
+; * OMX_VIDEO_HORIZONTAL predict horizontally
+; * OMX_VIDEO_VERTICAL predict vertically
+; * [in] ACPredFlag a flag indicating if AC prediction should be
+; * performed. It is equal to ac_pred_flag in the bit
+; * stream syntax of MPEG-4
+; * [in] videoComp video component type (luminance, chrominance or
+; * alpha) of the current block
+; * [out] pSrcDst pointer to the coefficient buffer which contains
+; * the quantized coefficients (QF) of the current
+; * block
+; * [out] pPredBufRow pointer to the updated coefficient row buffer
+; * [out] pPredBufCol pointer to the updated coefficient column buffer
+; * Return Value:
+; * OMX_Sts_NoErr - no error
+; * OMX_Sts_BadArgErr - Bad arguments
+; * - At least one of the pointers is NULL: pSrcDst, pPredBufRow, or pPredBufCol.
+; * - At least one the following cases: curQP <= 0, predQP <= 0, curQP >31,
+; * predQP > 31, preDir exceeds [1,2].
+; * - At least one of the pointers pSrcDst, pPredBufRow, or pPredBufCol is not
+; * 4-byte aligned.
+; *
+; *********
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+
+
+ IMPORT armVCM4P2_Reciprocal_QP_S32
+ IMPORT armVCM4P2_Reciprocal_QP_S16
+ IMPORT armVCM4P2_DCScaler
+
+ IF CortexA8
+;// Input Arguments
+
+pSrcDst RN 0
+pPredBufRow RN 1
+pPredBufCol RN 2
+curQP RN 3
+QP RN 3
+predQP RN 4
+predDir RN 5
+ACPredFlag RN 6
+videoComp RN 7
+
+;// Local Variables
+
+shortVideoHeader RN 4
+dcScaler RN 4
+index RN 6
+predCoeffTable RN 7
+temp1 RN 6
+temp2 RN 9
+temp RN 14
+Const RN 8
+temppPredColBuf RN 8
+tempPred RN 9
+
+absCoeffDC RN 8
+negdcScaler RN 10
+Rem RN 11
+temp3 RN 12
+
+dcRowbufCoeff RN 10
+dcColBuffCoeff RN 11
+Return RN 0
+
+;//NEON Registers
+
+qPredRowBuf QN Q0.S16
+dPredRowBuf0 DN D0.S16
+dPredRowBuf1 DN D1.S16
+
+
+
+
+qCoeffTab QN Q1.S32
+
+qPredQP QN Q2.S16
+dPredQP0 DN D4.S16
+dPredQP1 DN D5.S16
+
+
+qtemp1 QN Q3.S32
+qtemp QN Q3.S16
+
+dtemp0 DN D6.S16
+dtemp1 DN D7.S16
+
+dtemp2 DN D8.S16
+dtemp3 DN D9.S16
+
+dtemp4 DN D2.S16
+dtemp5 DN D3.S16
+dtemp6 DN D4.S16
+dtemp7 DN D5.S16
+
+qtempPred1 QN Q5.S32
+qtempPred QN Q5.S16
+
+dtempPred0 DN D10.S16
+dtempPred1 DN D11.S16
+
+
+
+ M_START omxVCM4P2_PredictReconCoefIntra,r11,d11
+
+ ;// Assigning pointers to Input arguments on Stack
+
+ M_ARG predQPonStack,4
+ M_ARG predDironStack,4
+ M_ARG ACPredFlagonStack,4
+ M_ARG videoComponStack,4
+
+ ;// DC Prediction
+
+ M_LDR videoComp,videoComponStack ;// Load videoComp From Stack
+
+ M_LDR predDir,predDironStack ;// Load Prediction direction
+ ;// DC Scaler calculation
+ LDR index, =armVCM4P2_DCScaler
+ ADD index,index,videoComp,LSL #5
+ LDRB dcScaler,[index,QP]
+
+
+ LDR predCoeffTable, =armVCM4P2_Reciprocal_QP_S16 ;// Loading the table with entries 32767/(1 to 63)
+ CMP predDir,#2 ;// Check if the Prediction direction is vertical
+
+ ;// Caulucate tempPred
+
+ LDREQSH absCoeffDC,[pPredBufRow] ;// If vetical load the coeff from Row Prediction Buffer
+ LDRNESH absCoeffDC,[pPredBufCol] ;// If horizontal load the coeff from column Prediction Buffer
+
+ RSB negdcScaler,dcScaler,#0 ;// negdcScaler=-dcScaler
+ MOV temp1,absCoeffDC ;// Load the Prediction coeff to temp for comparision
+ CMP temp1,#0
+ RSBLT absCoeffDC,temp1,#0 ;// calculate absolute val of prediction coeff
+
+ ADD temp,dcScaler,dcScaler
+ LDRH temp,[predCoeffTable,temp] ;// Load value from coeff table for performing division using multiplication
+ SMULBB tempPred,temp,absCoeffDC ;// tempped=pPredBufRow(Col)[0]*32767/dcScaler
+ ADD temp3,dcScaler,#1
+ LSR tempPred,tempPred,#15 ;// tempped=pPredBufRow(Col)[0]/dcScaler
+ LSR temp3,temp3,#1 ;// temp3=round(dcScaler/2)
+ MLA Rem,negdcScaler,tempPred,absCoeffDC ;// Remainder Rem=abs(pPredBufRow(Col)[0])-tempPred*dcScaler
+
+ LDRH dcRowbufCoeff,[pPredBufCol]
+
+ CMP Rem,temp3 ;// compare Rem with (dcScaler/2)
+ ADDGE tempPred,#1 ;// tempPred=tempPred+1 if Rem>=(dcScaler/2)
+ CMP temp1,#0
+ RSBLT tempPred,tempPred,#0 ;// tempPred=-tempPred if
+
+ STRH dcRowbufCoeff,[pPredBufRow,#-16]
+
+
+ LDRH temp,[pSrcDst] ;// temp=pSrcDst[0]
+ ADD temp,temp,tempPred ;// temp=pSrcDst[0]+tempPred
+ SSAT16 temp,#12,temp ;// clip temp to [-2048,2047]
+ SMULBB dcColBuffCoeff,temp,dcScaler ;// temp1=clipped(pSrcDst[0])*dcScaler
+ M_LDR ACPredFlag,ACPredFlagonStack
+ STRH dcColBuffCoeff,[pPredBufCol]
+
+
+ ;// AC Prediction
+
+ M_LDR predQP,predQPonStack
+
+ CMP ACPredFlag,#1 ;// Check if the AC prediction flag is set or not
+ BNE Exit ;// If not set Exit
+ CMP predDir,#2 ;// Check the Prediction direction
+ LDR predCoeffTable, =armVCM4P2_Reciprocal_QP_S32 ;// Loading the table with entries 0x1ffff/(1 to 63)
+ MOV Const,#4
+ MUL curQP,curQP,Const ;// curQP=4*curQP
+ VDUP dPredQP0,predQP
+ LDR temp2,[predCoeffTable,curQP] ;// temp=0x1ffff/curQP
+ VDUP qCoeffTab,temp2
+ BNE Horizontal ;// If the Prediction direction is horizontal branch to Horizontal
+
+
+
+ ;// Vertical
+ ;//Calculating tempPred
+
+ VLD1 {dPredRowBuf0,dPredRowBuf1},[pPredBufRow] ;// Loading pPredBufRow[i]:i=0 t0 7
+
+ VMULL qtemp1,dPredRowBuf0,dPredQP0 ;//qtemp1[i]=pPredBufRow[i]*dPredQP[i]: i=0 t0 3
+ VMUL qtempPred1,qtemp1,qCoeffTab ;//qtempPred1[i]=pPredBufRow[i]*dPredQP[i]*0x1ffff/curQP : i=0 t0 3
+
+ VMULL qtemp1,dPredRowBuf1,dPredQP0 ;//qtemp1[i]=pPredBufRow[i]*dPredQP[i] : i=4 t0 7
+
+ VRSHR qtempPred1,qtempPred1,#17 ;//qtempPred1[i]=round(pPredBufRow[i]*dPredQP[i]/curQP) : i=0 t0 3
+ VSHRN dPredQP1,qtempPred1,#0 ;// narrow qtempPred1[i] to 16 bits
+
+
+ VMUL qtempPred1,qtemp1,qCoeffTab ;//qtempPred1[i]=pPredBufRow[i]*dPredQP[i]*0x1ffff/curQP : i=4 t0 7
+ VRSHR qtempPred1,qtempPred1,#17 ;//qtempPred1[i]=round(pPredBufRow[i]*dPredQP[i]/curQP) : i=4 t0 7
+ VLD1 {dtemp0,dtemp1},[pSrcDst] ;//Loading pSrcDst[i] : i=0 to 7
+ VSHRN dtempPred1,qtempPred1,#0 ;// narrow qtempPred1[i] to 16 bits
+ VMOV dtempPred0,dPredQP1
+
+ ;//updating source and row prediction buffer contents
+ VADD qtemp,qtemp,qtempPred ;//pSrcDst[i]=pSrcDst[i]+qtempPred[i]: i=0 to 7
+ VQSHL qtemp,qtemp,#4 ;//Clip to [-2048,2047]
+ LDRH dcRowbufCoeff,[pPredBufRow] ;//Loading Dc Value of Row Prediction buffer
+ VSHR qtemp,qtemp,#4
+
+ VST1 {dtemp0,dtemp1},[pSrcDst] ;//storing back the updated values
+ VST1 {dtemp0,dtemp1},[pPredBufRow] ;//storing back the updated row prediction values
+ STRH dcRowbufCoeff,[pPredBufRow] ;// storing the updated DC Row Prediction coeff
+
+ B Exit
+
+Horizontal
+
+ ;// Calculating Temppred
+
+
+
+ VLD1 {dPredRowBuf0,dPredRowBuf1},[pPredBufCol] ;// Loading pPredBufCol[i]:i=0 t0 7
+ VMULL qtemp1,dPredRowBuf0,dPredQP0 ;//qtemp1[i]=pPredBufCol[i]*dPredQP[i]: i=0 t0 3
+ VMUL qtempPred1,qtemp1,qCoeffTab ;//qtempPred1[i]=pPredBufCol[i]*dPredQP[i]*0x1ffff/curQP : i=0 t0 3
+
+ VMULL qtemp1,dPredRowBuf1,dPredQP0 ;//qtemp1[i]=pPredBufCol[i]*dPredQP[i] : i=4 t0 7
+
+ VRSHR qtempPred1,qtempPred1,#17 ;//qtempPred1[i]=round(pPredBufCol[i]*dPredQP[i]/curQP) : i=0 t0 3
+ VSHRN dPredQP1,qtempPred1,#0 ;// narrow qtempPred1[i] to 16 bits
+
+
+ VMUL qtempPred1,qtemp1,qCoeffTab ;//qtempPred1[i]=pPredBufCol[i]*dPredQP[i]*0x1ffff/curQP : i=4 t0 7
+
+ MOV temppPredColBuf,pPredBufCol
+ VRSHR qtempPred1,qtempPred1,#17 ;//qtempPred1[i]=round(pPredBufCol[i]*dPredQP[i]/curQP) : i=4 t0 7
+ VLD4 {dtemp0,dtemp1,dtemp2,dtemp3},[pSrcDst] ;// Loading coefficients Interleaving by 4
+ VSHRN dtempPred1,qtempPred1,#0 ;// narrow qtempPred1[i] to 16 bits
+ VMOV dtempPred0,dPredQP1
+
+ ;// Updating source and column prediction buffer contents
+ ADD temp2,pSrcDst,#32
+ VLD4 {dtemp4,dtemp5,dtemp6,dtemp7},[temp2] ;// Loading next 16 coefficients Interleaving by 4
+ VUZP dtemp0,dtemp4 ;// Interleaving by 8
+ VADD dtemp0,dtemp0,dtempPred0 ;// Adding tempPred to coeffs
+ VQSHL dtemp0,dtemp0,#4 ;// Clip to [-2048,2047]
+ VSHR dtemp0,dtemp0,#4
+ VST1 {dtemp0},[pPredBufCol]! ;// Updating Pridiction column buffer
+ VZIP dtemp0,dtemp4 ;// deinterleaving
+ VST4 {dtemp0,dtemp1,dtemp2,dtemp3},[pSrcDst] ;// Updating source coeffs
+ VST4 {dtemp4,dtemp5,dtemp6,dtemp7},[temp2]!
+
+ MOV temp1,temp2
+ VLD4 {dtemp0,dtemp1,dtemp2,dtemp3},[temp2]! ;// Loading coefficients Interleaving by 4
+
+ VLD4 {dtemp4,dtemp5,dtemp6,dtemp7},[temp2]
+ VUZP dtemp0,dtemp4 ;// Interleaving by 8
+ VADD dtemp0,dtemp0,dtempPred1
+ VQSHL dtemp0,dtemp0,#4 ;// Clip to [-2048,2047]
+ VSHR dtemp0,dtemp0,#4
+ VST1 {dtemp0},[pPredBufCol]!
+ VZIP dtemp0,dtemp4
+ VST4 {dtemp0,dtemp1,dtemp2,dtemp3},[temp1]
+ STRH dcColBuffCoeff,[temppPredColBuf]
+ VST4 {dtemp4,dtemp5,dtemp6,dtemp7},[temp2]
+
+Exit
+
+ STRH temp,[pSrcDst]
+
+
+ MOV Return,#OMX_Sts_NoErr
+
+ M_END
+ ENDIF
+
+
+ END
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
new file mode 100755
index 0000000..bd0ad1f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvInter_I_s.s
@@ -0,0 +1,162 @@
+;/**
+; *
+; * File Name: omxVCM4P2_QuantInvInter_I_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 12290
+; * Date: Wednesday, April 9, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains modules for inter reconstruction
+; *
+; *
+; *
+; *
+; *
+; * Function: omxVCM4P2_QuantInvInter_I
+; *
+; * Description:
+; * Performs inverse quantization on intra/inter coded block.
+; * This function supports bits_per_pixel = 8. Mismatch control
+; * is performed for the first MPEG-4 mode inverse quantization method.
+; * The output coefficients are clipped to the range: [-2048, 2047].
+; * Mismatch control is performed for the first inverse quantization method.
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] pSrcDst pointer to the input (quantized) intra/inter block. Must be 16-byte aligned.
+; * [in] QP quantization parameter (quantiser_scale)
+; * [in] videoComp (Intra version only.) Video component type of the
+; * current block. Takes one of the following flags:
+; * OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE,
+; * OMX_VC_ALPHA.
+; * [in] shortVideoHeader a flag indicating presence of short_video_header;
+; * shortVideoHeader==1 selects linear intra DC mode,
+; * and shortVideoHeader==0 selects nonlinear intra DC mode.
+; * [out] pSrcDst pointer to the output (dequantized) intra/inter block. Must be 16-byte aligned.
+; *
+; * Return Value:
+; * OMX_Sts_NoErr - no error
+; * OMX_Sts_BadArgErr - bad arguments
+; * - If pSrcDst is NULL or is not 16-byte aligned.
+; * or
+; * - If QP <= 0.
+; * or
+; * - videoComp is none of OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE and OMX_VC_ALPHA.
+; *
+; */
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+ IF CortexA8
+
+
+;//Input Arguments
+pSrcDst RN 0
+QP RN 1
+
+
+;//Local Variables
+Count RN 3
+doubleQP RN 4
+Return RN 0
+;// Neon registers
+
+
+dQP10 DN D0.S32[0]
+qQP1 QN Q0.S32
+
+dQP1 DN D0.S16
+dMinusQP1 DN D1.S16
+
+dCoeff0 DN D2.S16
+dCoeff1 DN D3.S16
+
+qResult0 QN Q3.S32
+dResult0 DN D7.S16
+qSign0 QN Q3.S32
+dSign0 DN D6.S16
+
+qResult1 QN Q4.S32
+dResult1 DN D8.S16
+qSign1 QN Q4.S32
+dSign1 DN D8.S16
+
+d2QP0 DN D10.S32[0]
+q2QP0 QN Q5.S32
+d2QP DN D10.S16
+
+dZero0 DN D11.S16
+dZero1 DN D12.S16
+dConst0 DN D13.S16
+
+
+ M_START omxVCM4P2_QuantInvInter_I,r4,d13
+
+
+
+ ADD doubleQP,QP,QP ;// doubleQP= 2*QP
+ VMOV d2QP0,doubleQP
+ VDUP q2QP0,d2QP0 ;// Move doubleQP in to a scalar
+ TST QP,#1
+ VLD1 {dCoeff0,dCoeff1},[pSrcDst] ;// Load first 8 values to Coeff0,Coeff1
+ SUBEQ QP,QP,#1
+ VMOV dQP10,QP ;// If QP is even then QP1=QP-1 else QP1=QP
+ MOV Count,#64
+ VDUP qQP1,dQP10 ;// Duplicate tempResult with QP1
+ VSHRN d2QP,q2QP0,#0
+ VEOR dConst0,dConst0,dConst0
+ VSHRN dQP1,qQP1,#0 ;// QP1 truncated to 16 bits
+ VSUB dMinusQP1,dConst0,dQP1 ;// dMinusQP1=-QP1
+
+Loop
+
+ ;//Performing Inverse Quantization
+
+ VCLT dSign0,dCoeff0, #0 ;// Compare Coefficient 0 against 0
+ VCLT dSign1,dCoeff1, #0 ;// Compare Coefficient 1 against 0
+ VCEQ dZero0,dCoeff0,#0 ;// Compare Coefficient 0 against zero
+ VBSL dSign0,dMinusQP1,dQP1 ;// dSign0 = -QP1 if Coeff0< 0 else QP1
+ VCEQ dZero1,dCoeff1,#0 ;// Compare Coefficient 1 against zero
+ VBSL dSign1,dMinusQP1,dQP1 ;// dSign1 = -QP1 if Coeff1< 0 else QP1
+ VMOVL qSign0,dSign0 ;// Sign extend qSign0 to 32 bits
+ VMOVL qSign1,dSign1
+ VMLAL qResult0,dCoeff0,d2QP ;// qResult0[i]= qCoeff0[i]+qCoeff0[i]*(-2) if Coeff <0
+ ;// qResult0[i]= qCoeff0[i] if Coeff >=0
+ VMLAL qResult1,dCoeff1,d2QP ;// qResult1[i]= qCoeff1[i]+qCoeff1[i]*(-2) if Coeff <0
+ ;// qResult1[i]= qCoeff1[i] if Coeff >=0
+ ;// Clip Result to [-2048,2047]
+
+ VQSHL qResult0,qResult0,#20 ;// clip to [-2048,2047]
+ VQSHL qResult1,qResult1,#20
+
+ VSHR qResult0,qResult0,#4
+ VSHR qResult1,qResult1,#4
+ VSHRN dResult0,qResult0,#16 ;// Narrow the clipped Value to Halfword
+ VSHRN dResult1,qResult1,#16
+ VBIT dResult0,dConst0,dZero0
+ VBIT dResult1,dConst0,dZero1
+
+ VST1 {dResult0,dResult1},[pSrcDst]! ;// Store the result
+ SUBS Count,Count,#8
+ VLD1 {dCoeff0,dCoeff1},[pSrcDst]
+
+
+ BGT Loop
+
+ MOV Return,#OMX_Sts_NoErr
+
+
+ M_END
+ ENDIF
+
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
new file mode 100755
index 0000000..e00591f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I_s.s
@@ -0,0 +1,210 @@
+;/**
+; *
+; * File Name: omxVCM4P2_QuantInvIntra_I_s.s
+; * OpenMAX DL: v1.0.2
+; * Revision: 12290
+; * Date: Wednesday, April 9, 2008
+; *
+; * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+; *
+; *
+; *
+; * Description:
+; * Contains modules for inter reconstruction
+; *
+; *
+; *
+; *
+; *
+; *
+; * Function: omxVCM4P2_QuantInvIntra_I
+; *
+; * Description:
+; * Performs inverse quantization on intra/inter coded block.
+; * This function supports bits_per_pixel = 8. Mismatch control
+; * is performed for the first MPEG-4 mode inverse quantization method.
+; * The output coefficients are clipped to the range: [-2048, 2047].
+; * Mismatch control is performed for the first inverse quantization method.
+; *
+; * Remarks:
+; *
+; * Parameters:
+; * [in] pSrcDst pointer to the input (quantized) intra/inter block. Must be 16-byte aligned.
+; * [in] QP quantization parameter (quantiser_scale)
+; * [in] videoComp (Intra version only.) Video component type of the
+; * current block. Takes one of the following flags:
+; * OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE,
+; * OMX_VC_ALPHA.
+; * [in] shortVideoHeader a flag indicating presence of short_video_header;
+; * shortVideoHeader==1 selects linear intra DC mode,
+; * and shortVideoHeader==0 selects nonlinear intra DC mode.
+; * [out] pSrcDst pointer to the output (dequantized) intra/inter block. Must be 16-byte aligned.
+; *
+; * Return Value:
+; * OMX_Sts_NoErr - no error
+; * OMX_Sts_BadArgErr - bad arguments
+; * - If pSrcDst is NULL or is not 16-byte aligned.
+; * or
+; * - If QP <= 0.
+; * or
+; * - videoComp is none of OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE and OMX_VC_ALPHA.
+; *
+
+
+ INCLUDE omxtypes_s.h
+ INCLUDE armCOMM_s.h
+
+ M_VARIANTS CortexA8
+
+
+ IMPORT armVCM4P2_DCScaler
+
+ IF CortexA8
+
+
+;//Input Arguments
+pSrcDst RN 0
+QP RN 1
+videoComp RN 2
+shortVideoHeader RN 3
+
+
+;//Local Variables
+
+dcScaler RN 4
+temp RN 14
+index RN 5
+
+
+Count RN 5
+doubleQP RN 4
+Return RN 0
+
+
+;// Neon registers
+
+
+dQP10 DN D0.S32[0]
+qQP1 QN Q0.S32
+
+dQP1 DN D0.S16
+dMinusQP1 DN D1.S16
+
+dCoeff0 DN D2.S16
+dCoeff1 DN D3.S16
+
+qResult0 QN Q3.S32
+dResult0 DN D7.S16
+qSign0 QN Q3.S32
+dSign0 DN D6.S16
+
+qResult1 QN Q4.S32
+dResult1 DN D8.S16
+qSign1 QN Q4.S32
+dSign1 DN D8.S16
+
+d2QP0 DN D10.S32[0]
+q2QP0 QN Q5.S32
+d2QP DN D10.S16
+
+dZero0 DN D11.S16
+dZero1 DN D4.S16
+dConst0 DN D5.S16
+
+
+
+
+
+
+ M_START omxVCM4P2_QuantInvIntra_I,r5,d11
+
+
+ ;// Perform Inverse Quantization for DC coefficient
+
+ TEQ shortVideoHeader,#0 ;// Test if short Video Header flag =0
+ MOVNE dcScaler,#8 ;// if shortVideoHeader is non zero dcScaler=8
+ BNE calDCVal
+
+ LDR index, =armVCM4P2_DCScaler
+ ADD index,index,videoComp,LSL #5
+ LDRB dcScaler,[index,QP]
+
+ ;//M_CalDCScalar shortVideoHeader,videoComp, QP
+
+calDCVal
+
+ LDRH temp,[pSrcDst]
+ SMULBB temp,temp,dcScaler ;// dcCoeff = dcScaler * Quantized DC coefficient(from memory)
+ SSAT temp,#12,temp ;// Saturating to 12 bits
+
+
+
+ ;// Perform Inverse Quantization for Ac Coefficients
+
+
+
+ ADD doubleQP,QP,QP ;// doubleQP= 2*QP
+ VMOV d2QP0,doubleQP
+ VDUP q2QP0,d2QP0 ;// Move doubleQP in to a scalar
+ TST QP,#1
+ VLD1 {dCoeff0,dCoeff1},[pSrcDst] ;// Load first 8 values to Coeff0,Coeff1
+ SUBEQ QP,QP,#1
+ VMOV dQP10,QP ;// If QP is even then QP1=QP-1 else QP1=QP
+ MOV Count,#64
+ VDUP qQP1,dQP10 ;// Duplicate tempResult with QP1
+ VSHRN d2QP,q2QP0,#0
+ VEOR dConst0,dConst0,dConst0
+ VSHRN dQP1,qQP1,#0 ;// QP1 truncated to 16 bits
+ VSUB dMinusQP1,dConst0,dQP1 ;// dMinusQP1=-QP1
+
+Loop
+
+ ;//Performing Inverse Quantization
+
+ VCLT dSign0,dCoeff0, #0 ;// Compare Coefficient 0 against 0
+ VCLT dSign1,dCoeff1, #0 ;// Compare Coefficient 1 against 0
+ VCEQ dZero0,dCoeff0,#0 ;// Compare Coefficient 0 against zero
+ VBSL dSign0,dMinusQP1,dQP1 ;// dSign0 = -QP1 if Coeff0< 0 else QP1
+ VCEQ dZero1,dCoeff1,#0 ;// Compare Coefficient 1 against zero
+ VBSL dSign1,dMinusQP1,dQP1 ;// dSign1 = -QP1 if Coeff1< 0 else QP1
+ VMOVL qSign0,dSign0 ;// Sign extend qSign0 to 32 bits
+ VMOVL qSign1,dSign1
+ VMLAL qResult0,dCoeff0,d2QP ;// qResult0[i]= qCoeff0[i]+qCoeff0[i]*(-2) if Coeff <0
+ ;// qResult0[i]= qCoeff0[i] if Coeff >=0
+ VMLAL qResult1,dCoeff1,d2QP ;// qResult1[i]= qCoeff1[i]+qCoeff1[i]*(-2) if Coeff <0
+ ;// qResult1[i]= qCoeff1[i] if Coeff >=0
+ ;// Clip Result to [-2048,2047]
+
+ VQSHL qResult0,qResult0,#20 ;// clip to [-2048,2047]
+ VQSHL qResult1,qResult1,#20
+
+ VSHR qResult0,qResult0,#4
+ VSHR qResult1,qResult1,#4
+ VSHRN dResult0,qResult0,#16 ;// Narrow the clipped Value to Halfword
+ VSHRN dResult1,qResult1,#16
+ VBIT dResult0,dConst0,dZero0
+ VBIT dResult1,dConst0,dZero1
+
+ VST1 {dResult0,dResult1},[pSrcDst]! ;// Store the result
+ SUBS Count,Count,#8
+ VLD1 {dCoeff0,dCoeff1},[pSrcDst]
+
+
+ BGT Loop
+
+ SUB pSrcDst,pSrcDst,#128
+
+ ;// Store the Inverse quantized Dc coefficient
+
+ STRH temp,[pSrcDst],#2
+
+ MOV Return,#OMX_Sts_NoErr
+
+
+
+ M_END
+ ENDIF
+
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/src/armVC_Version.c b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/src/armVC_Version.c
new file mode 100755
index 0000000..5d93681
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/arm_neon/vc/src/armVC_Version.c
@@ -0,0 +1,6 @@
+#include "omxtypes.h"
+#include "armCOMM_Version.h"
+
+#ifdef ARM_INCLUDE_VERSION_DESCRIPTIONS
+const char * const omxVC_VersionDescription = "ARM OpenMAX DL v" ARM_VERSION_STRING " Rel=" OMX_ARM_RELEASE_TAG " Arch=" OMX_ARM_BUILD_ARCHITECTURE " Tools=" OMX_ARM_BUILD_TOOLCHAIN ;
+#endif /* ARM_INCLUDE_VERSION_DESCRIPTIONS */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/ARM_DELIVERY.TXT b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/ARM_DELIVERY.TXT
new file mode 100644
index 0000000..7801f3d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/ARM_DELIVERY.TXT
@@ -0,0 +1,63 @@
+The contents of this transaction was created by Hedley Francis
+of ARM on 19-Feb-2008.
+
+It contains the ARM data versions listed below.
+
+This data, unless otherwise stated, is ARM Proprietary and access to it
+is subject to the agreements indicated below.
+
+If you experience problems with this data, please contact ARM support
+quoting transaction reference <97412>.
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+- OX000-SW-98010-r0p0-00bet1
+ Video codecs - sample code
+ Sample code release for Hantro (Ver 1.0.2)
+ internal access
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+This transaction contains deliverables which are designated as being of
+beta release status (BET).
+
+Beta release status has a particular meaning to ARM of which the recipient
+must be aware. Beta is a pre-release status indicating that the deliverable
+so described is believed to robustly demonstrate specified behaviour, to be
+consistent across its included aspects and be ready for general deployment.
+But Beta also indicates that pre-release reliability trials are ongoing and
+that it is possible residual defects or errors in operation, consistency
+and documentation may still be encountered. The recipient should consider
+this position when using this Beta material supplied. ARM will normally
+attempt to provide fixes or a work-around for defects identified by the
+recipient, but the provision or timeliness of this support cannot be
+guaranteed. ARM shall not be responsible for direct or consequential
+damages as a result of encountering one or more of these residual defects.
+By accepting a Beta release, the recipient agrees to these constraints and
+to providing reasonable information to ARM to enable the replication of the
+defects identified by the recipient. The specific Beta version supplied
+will not be supported after release of a later or higher status version.
+It should be noted that Support for the Beta release of the deliverable
+will only be provided by ARM to a recipient who has a current support and
+maintenance contract for the deliverable.
+
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+In addition to the data versions listed above, this transaction contains
+two additional files at the top level.
+
+The first is this file, ARM_DELIVERY_97412.TXT, which is the delivery
+note.
+
+The second is ARM_MANIFEST_97412.TXT which contains a manifest of all the
+files included in this transaction, together with their checksums.
+
+The checksums provided are calculated using the RSA Data Security, Inc.
+MD5 Message-Digest Algorithm.
+
+The checksums can be used to verify the integrity of this data using the
+"md5sum" tool (which is part of the GNU "textutils" package) by running:
+
+ % md5sum --check ARM_MANIFEST_97412.TXT
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/ARM_MANIFEST.TXT b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/ARM_MANIFEST.TXT
new file mode 100644
index 0000000..8e01b1e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/ARM_MANIFEST.TXT
@@ -0,0 +1,140 @@
+ OX000-SW-98010-r0p0-00bet1/
+ OX000-SW-98010-r0p0-00bet1/api/
+8971932d56eed6b1ad1ba507f0bff5f0 OX000-SW-98010-r0p0-00bet1/api/armCOMM_Bitstream.h
+e88ec84e122534092b90c67841549d6f OX000-SW-98010-r0p0-00bet1/api/armCOMM_Version.h
+43cf46c2cf2fe1f93c615b57bcbe4809 OX000-SW-98010-r0p0-00bet1/api/armCOMM.h
+f87fedd9ca432fefa757008176864ef8 OX000-SW-98010-r0p0-00bet1/api/armOMX.h
+8e49899a428822c36ef9dd94e0e05f18 OX000-SW-98010-r0p0-00bet1/api/omxtypes.h
+a06983abb39c476b081e87ea271361a5 OX000-SW-98010-r0p0-00bet1/build_vc.pl
+c01f8b93ab73d8c00ddf2499f01da5ff OX000-SW-98010-r0p0-00bet1/filelist_vc.txt
+ OX000-SW-98010-r0p0-00bet1/src/
+26e2ff3f633764eb720deb340978dc2d OX000-SW-98010-r0p0-00bet1/src/armCOMM_Bitstream.c
+79aa23d9817efd11d0c4c2be36ec1e5c OX000-SW-98010-r0p0-00bet1/src/armCOMM.c
+ OX000-SW-98010-r0p0-00bet1/vc/
+ OX000-SW-98010-r0p0-00bet1/vc/m4p10/
+ OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/
+e45297704d72302d4a947d0798c666fb OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_CAVLCTables.c
+205dfafe1fe7bb160bf36d2600e1100a OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
+bf92641e8548577b77e04e03ec04c358 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_MEGetBufSize.c
+f5ee6f7be822d87471cef3b1801dbfc2 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I.c
+28110b3a13cecf4f216d10bcc761c401 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_Interpolate_Chroma.c
+9a1a25245c975d641e1c6378834aea4d OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_InterpolateHalfVer_Luma.c
+3a643eaaaeb12e8d274dc59a7357a586 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I.c
+4c4de5973a6b74250ce91ac0b317a617 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_InvTransformDequant_LumaDC.c
+4ecdbe9193aaba1f9bb0e24c938b34f9 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_UnpackBlock2x2.c
+66e912f8c88f6019cba3ede27150a407 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_InterpolateLuma.c
+266da42f4e3015e67b2cbb58169d437f OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateHalfDiag_Luma.c
+d905247eeaa52d4e2cf5f6bc3f61b348 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair.c
+5b29448db0495cd1717a4b925f13377c OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16.c
+f6451df27f6dcc99036b4b1253c23bb6 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I.c
+892787d850eef09dc2148d45b416b062 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_TransformQuant_ChromaDC.c
+33da1c01a31f47c0f3aea9a7a5eaa9be OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_BlockMatch_Quarter.c
+e9fb11b066775283dcfeae8d12a6c97a OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateHalfVer_Luma.c
+add97bec08e5e1a538aa8607168e61ba OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8.c
+b695ecfc917b39470d1f40773b923972 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_PredictIntraDC4x4.c
+51bc596fd2ff61ad5450d7138461f4a1 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_MEInit.c
+dc6baa0a388dc5ea8ff65c24b179e670 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_GetVLCInfo.c
+a5499902996576f6712849db34d5ad65 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I.c
+0c3b76745d53e74a8e64e80def31faba OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4.c
+4f2742ba5a3c2208f53bc0f6a443be14 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_SADQuar_4x.c
+b4ae2dc948e8ca64831fe3bbfbd89523 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
+e15118cbe372db7cadba225c9456f189 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_SADQuar.c
+623cf336cfce7d0174f4e54072456f33 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_InvTransformResidualAndAdd.c
+89e452c80e30357cadfb04c05b6fe00c OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_InterpolateHalfHor_Luma.c
+3a5551cc54e85bbe34fc966c7dc00f1c OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_BlockMatch_Integer.c
+114030fa0d8f00af6d3289f47a5e85bf OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
+9e373ab296fb85bb45565a6c384f6ed8 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_DequantTables.c
+2d200f7cc230f302da48c589da42c02f OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_UnpackBlock4x4.c
+ea3f1d1d1507b55610b1349c7b5946e8 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair.c
+bd2bf1743aef2a9396545ed025362be2 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_Average_4x.c
+ca68e809567bf89044631b67d228c7ce OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
+77caf2b5cbee96d360a919f27e1f14f4 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_QuantTables.c
+26081e384ec627fedad474a0e7dad877 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_SADQuar_8x.c
+1c83ae9207a54944936f4a63c665bd99 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c
+4c36e04db20200f4ec72e5aba57446fd OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_SATD_4x4.c
+f75b7c5a80d8bf33e315380e4ef0ab8a OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_InterpolateHalfHor_Luma.c
+488925bb7aeeae0ccf93ec44af9fce35 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_SADQuar_16x.c
+c91a5345b5f877b3831ed1abcc60d579 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_BlockMatch_Half.c
+35515a115a32fcac8479072a9a5b0db9 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_Interpolate_Luma.c
+fdcf4622bc5f0ae75bdb0a51dcd03397 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_TransformQuant_LumaDC.c
+74c9278177400a1f7cc6d799a8c8ab34 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_SAD_4x.c
+56aa2d506d0cfdb4ebd366c07adb2d85 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_DeBlockPixel.c
+36b2165fd4d2a7f3f3e1f8daff4f94e5 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_SubAndTransformQDQResidual.c
+4b6b1b933fc7bc8f14a184c02c028085 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_TransformResidual4x4.c
+cf0ff093a9b372dd3271e3e5c28984d4 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair.c
+9ccad9f894fbd32194f5b53da217072a OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_InvTransformDequant_ChromaDC.c
+4943a7a2df7e9d700675f8c1debf4d90 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_CompareMotionCostToMV.c
+29e4a7f38f8c2e8246ed756db03c012e OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/armVCM4P10_FwdTransformResidual4x4.c
+27bc64e7c18da0aab9c987a388f61608 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
+859185614bb9d0013861e454d7b918f2 OX000-SW-98010-r0p0-00bet1/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd.c
+ OX000-SW-98010-r0p0-00bet1/vc/m4p10/api/
+63e3b64b96cc42a235c04f3a0f991316 OX000-SW-98010-r0p0-00bet1/vc/m4p10/api/armVCM4P10_CAVLCTables.h
+ OX000-SW-98010-r0p0-00bet1/vc/m4p2/
+ OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/
+0aae4f683d8903cba9956d3301ed9ffe OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_ACDCPredict.c
+8d6c1b44915329165df643081cc11a97 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_MCReconBlock.c
+0435eca930eacda0f2a59e843d405eff OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_MotionEstimationMB.c
+9a82dd0b1f05f798567436a009d02969 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP.c
+e1e24646c4bd03f5df78295452dd4eb2 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_8x8.c
+746e6b334e4a26d4a9bfae6d735826f6 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DCT8x8blk.c
+8b1d87b74d80ff13a16215b61d5e52ba OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_IDCT8x8blk.c
+309358d357baafc38d2b37bf1e9768a9 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_QuantInvInter_I.c
+cc77c7242b53c153f8d09527583f2771 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_FindMVpred.c
+7cd8e7796017e3dd00b494d34f629f3f OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_MEGetBufSize.c
+a4905cb5f8d4b244454ee4f60d18358b OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_PutVLCBits.c
+5596b31e433222c1e4860deebfa98ef2 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_DCT_Table.c
+365d072be6eab201f6e040058a3bacfc OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_BlockMatch_Integer.c
+78ed2212585b0cca75913a473b2ec430 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraACVLC.c
+50b2d8da8f20f6b1d39b8d3df38af55d OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_EncodeMV.c
+4a851a2ad6d357cdc233d9c0bf475e02 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_BlockMatch_Half.c
+0d6d63878f2827e00e5f85b1e8e26017 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
+48b865a983fe5bf3075eddf652950722 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra.c
+5f48fa7941835c46ac767e63fc29403b OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraDCVLC.c
+bbaf454b64b32b2c42a76a7ec393d977 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_CompareMV.c
+eebff772f87a414436c5c5286f2cd213 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_MEInit.c
+65ae242eb8cb6d1027677c8ef8f77ca0 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_FillVLCBuffer.c
+125642b1ea0c1256d79af1e0ddecae93 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_QuantInter_I.c
+ce24ba3d83da4cb791485d3128268bf6 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_intra.c
+09bc09a2e6fd962e719944582e38a8fd OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
+6b0ee7a116471a4dadbe5bc8dbf425b0 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_FillVLDBuffer.c
+21322dca027c28353e3e7eb8f3620062 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_CheckVLCEscapeMode.c
+ef353d83244288d8c37e0f70249177cc OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_GetVLCBits.c
+541de824f8aebe4a5cac6f15da943efa OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_8x8.c
+0b40b154b591c7f8842cffe4042d17c5 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
+2ffcec88d3fcb372543a8f4508ea1ac6 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_QuantIntra_I.c
+e06d85ca000afcbb50580f98f0203ac8 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC.c
+ae82b6fcfcf731a61d70e1aa42e6277a OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_16x16.c
+1d04395e231b597562257e98cda6cfb0 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
+72c0a36327b6b9b436d3bce7c896c520 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC.c
+1b65aa7f311124ea6fb47e384ec06a50 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I.c
+714957104a6ef71341fbe6a9ec65c136 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_SetPredDir.c
+86493f0ee853f653354a7389f1727f73 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_inter.c
+5de8afcfb3052968794782a7c3a0b41a OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_Inter.c
+50bcc228cc660dbda037725309de3f8b OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_EncodeVLCZigzag_intra.c
+4f5cfa1ecc668913dde94e3caf97a2e1 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_intra.c
+c2ec804ddf64ee841146e39c3a783451 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_16x16.c
+4087f6a827912ee5b45ed4217f1a6d77 OX000-SW-98010-r0p0-00bet1/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter.c
+ OX000-SW-98010-r0p0-00bet1/vc/m4p2/api/
+5c711702dddcec85298003860d760cec OX000-SW-98010-r0p0-00bet1/vc/m4p2/api/armVCM4P2_DCT_Table.h
+1b92c94b785c03ec76d4fae2f2bbdb8a OX000-SW-98010-r0p0-00bet1/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
+ad9c6986d2a3200dd5e1f6103a54a99b OX000-SW-98010-r0p0-00bet1/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
+ OX000-SW-98010-r0p0-00bet1/vc/src/
+e627b3346b0dc9aff14446005ce0fa43 OX000-SW-98010-r0p0-00bet1/vc/src/armVC_Version.c
+ OX000-SW-98010-r0p0-00bet1/vc/api/
+7ca94b1c33ac0211e17d38baadd7d1dd OX000-SW-98010-r0p0-00bet1/vc/api/armVC.h
+12cf7596edbbf6048b626d15e8d0ed48 OX000-SW-98010-r0p0-00bet1/vc/api/omxVC.h
+ OX000-SW-98010-r0p0-00bet1/vc/comm/
+ OX000-SW-98010-r0p0-00bet1/vc/comm/src/
+3a6df0085736cbcbe2e3f45d08af4221 OX000-SW-98010-r0p0-00bet1/vc/comm/src/armVCCOMM_Average.c
+0bf3cb52863c829b28c0352835170211 OX000-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_Copy8x8.c
+538b62f510b5a8bdced4a39fa12d9a23 OX000-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock_SAD.c
+66993edd9d441bf3b5b6c912f6400b6e OX000-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_ExpandFrame_I.c
+8e526a9007eb0d43ebf362c498b37415 OX000-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_LimitMVToRect.c
+87f8f26e6e9178df0ab7419334d5a3db OX000-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_SAD_16x.c
+1a8577646132ad9b63a1477fdaec2464 OX000-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_Average_16x.c
+48529c4f70c7e954e832eece1aee57bd OX000-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_SAD_8x.c
+252977764d4f38282b6a56c59ccf4f09 OX000-SW-98010-r0p0-00bet1/vc/comm/src/armVCCOMM_SAD.c
+cc78cfaed9502c2e0282c91fb95eeac4 OX000-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_Average_8x.c
+e468751c15a581ebd22da031e22117d1 OX000-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_Copy16x16.c
+3f448d191eaeb82ecb7e27ef8ba27875 OX000-SW-98010-r0p0-00bet1/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock.c
+b1291c307808631fa833684abb9c34ce ARM_DELIVERY_97412.TXT
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h
new file mode 100644
index 0000000..2ed86a4
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM.h
@@ -0,0 +1,785 @@
+/**
+ *
+ * File Name: armCOMM.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armCOMM.h
+ * Brief: Declares Common APIs/Data Types used across OpenMAX API's
+ *
+ */
+
+
+#ifndef _armCommon_H_
+#define _armCommon_H_
+
+#include "omxtypes.h"
+
+typedef struct
+{
+ OMX_F32 Re; /** Real part */
+ OMX_F32 Im; /** Imaginary part */
+
+} OMX_FC32; /** single precision floating point complex number */
+
+typedef struct
+{
+ OMX_F64 Re; /** Real part */
+ OMX_F64 Im; /** Imaginary part */
+
+} OMX_FC64; /** double precision floating point complex number */
+
+
+/* Used by both IP and IC domains for 8x8 JPEG blocks. */
+typedef OMX_S16 ARM_BLOCK8x8[64];
+
+
+#include "armOMX.h"
+
+#define armPI (OMX_F64)(3.1415926535897932384626433832795)
+
+/***********************************************************************/
+
+/* Compiler extensions */
+#ifdef ARM_DEBUG
+/* debug version */
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#define armError(str) {printf((str)); printf("\n"); exit(-1);}
+#define armWarn(str) {printf((str)); printf("\n");}
+#define armIgnore(a) ((void)a)
+#define armAssert(a) assert(a)
+#else
+/* release version */
+#define armError(str) ((void) (str))
+#define armWarn(str) ((void) (str))
+#define armIgnore(a) ((void) (a))
+#define armAssert(a) ((void) (a))
+#endif /* ARM_DEBUG */
+
+/* Arithmetic operations */
+
+#define armMin(a,b) ( (a) > (b) ? (b):(a) )
+#define armMax(a,b) ( (a) > (b) ? (a):(b) )
+#define armAbs(a) ( (a) < 0 ? -(a):(a) )
+
+/* Alignment operation */
+
+#define armAlignToBytes(Ptr,N) (Ptr + ( ((N-(int)Ptr)&(N-1)) / sizeof(*Ptr) ))
+#define armAlignTo2Bytes(Ptr) armAlignToBytes(Ptr,2)
+#define armAlignTo4Bytes(Ptr) armAlignToBytes(Ptr,4)
+#define armAlignTo8Bytes(Ptr) armAlignToBytes(Ptr,8)
+#define armAlignTo16Bytes(Ptr) armAlignToBytes(Ptr,16)
+
+/* Error and Alignment check */
+
+#define armRetArgErrIf(condition, code) if(condition) { return (code); }
+#define armRetDataErrIf(condition, code) if(condition) { return (code); }
+
+#ifndef ALIGNMENT_DOESNT_MATTER
+#define armIsByteAligned(Ptr,N) ((((int)(Ptr)) % N)==0)
+#define armNotByteAligned(Ptr,N) ((((int)(Ptr)) % N)!=0)
+#else
+#define armIsByteAligned(Ptr,N) (1)
+#define armNotByteAligned(Ptr,N) (0)
+#endif
+
+#define armIs2ByteAligned(Ptr) armIsByteAligned(Ptr,2)
+#define armIs4ByteAligned(Ptr) armIsByteAligned(Ptr,4)
+#define armIs8ByteAligned(Ptr) armIsByteAligned(Ptr,8)
+#define armIs16ByteAligned(Ptr) armIsByteAligned(Ptr,16)
+
+#define armNot2ByteAligned(Ptr) armNotByteAligned(Ptr,2)
+#define armNot4ByteAligned(Ptr) armNotByteAligned(Ptr,4)
+#define armNot8ByteAligned(Ptr) armNotByteAligned(Ptr,8)
+#define armNot16ByteAligned(Ptr) armNotByteAligned(Ptr,16)
+#define armNot32ByteAligned(Ptr) armNotByteAligned(Ptr,32)
+
+/**
+ * Function: armRoundFloatToS16_ref/armRoundFloatToS32_ref/armRoundFloatToS64
+ *
+ * Description:
+ * Converts a double precision value into a short int/int after rounding
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S16/OMX_S32 format
+ *
+ */
+
+OMX_S16 armRoundFloatToS16 (OMX_F64 Value);
+OMX_S32 armRoundFloatToS32 (OMX_F64 Value);
+OMX_S64 armRoundFloatToS64 (OMX_F64 Value);
+
+/**
+ * Function: armSatRoundFloatToS16_ref/armSatRoundFloatToS32
+ *
+ * Description:
+ * Converts a double precision value into a short int/int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S16/OMX_S32 format
+ *
+ */
+
+OMX_S16 armSatRoundFloatToS16 (OMX_F64 Value);
+OMX_S32 armSatRoundFloatToS32 (OMX_F64 Value);
+
+/**
+ * Function: armSatRoundFloatToU16_ref/armSatRoundFloatToU32
+ *
+ * Description:
+ * Converts a double precision value into a unsigned short int/int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_U16/OMX_U32 format
+ *
+ */
+
+OMX_U16 armSatRoundFloatToU16 (OMX_F64 Value);
+OMX_U32 armSatRoundFloatToU32 (OMX_F64 Value);
+
+/**
+ * Function: armSignCheck
+ *
+ * Description:
+ * Checks the sign of a variable:
+ * returns 1 if it is Positive
+ * returns 0 if it is 0
+ * returns -1 if it is Negative
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] var Variable to be checked
+ *
+ * Return Value:
+ * OMX_INT -- returns 1 if it is Positive
+ * returns 0 if it is 0
+ * returns -1 if it is Negative
+ */
+
+OMX_INT armSignCheck (OMX_S16 var);
+
+/**
+ * Function: armClip
+ *
+ * Description: Clips the input between MAX and MIN value
+ *
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] Min lower bound
+ * [in] Max upper bound
+ * [in] src variable to the clipped
+ *
+ * Return Value:
+ * OMX_S32 -- returns clipped value
+ */
+
+OMX_S32 armClip (
+ OMX_INT min,
+ OMX_INT max,
+ OMX_S32 src
+ );
+
+/**
+ * Function: armClip_F32
+ *
+ * Description: Clips the input between MAX and MIN value
+ *
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] Min lower bound
+ * [in] Max upper bound
+ * [in] src variable to the clipped
+ *
+ * Return Value:
+ * OMX_F32 -- returns clipped value
+ */
+
+OMX_F32 armClip_F32 (
+ OMX_F32 min,
+ OMX_F32 max,
+ OMX_F32 src
+ );
+
+/**
+ * Function: armShiftSat_F32
+ *
+ * Description: Divides a float value by 2^shift and
+ * saturates it for unsigned value range for satBits.
+ * Second parameter is like "shifting" the corresponding
+ * integer value. Takes care of rounding while clipping the final
+ * value.
+ *
+ * Parameters:
+ * [in] v Number to be operated upon
+ * [in] shift Divides the input "v" by "2^shift"
+ * [in] satBits Final range is [0, 2^satBits)
+ *
+ * Return Value:
+ * OMX_S32 -- returns "shifted" saturated value
+ */
+
+OMX_U32 armShiftSat_F32(
+ OMX_F32 v,
+ OMX_INT shift,
+ OMX_INT satBits
+ );
+
+/**
+ * Functions: armSwapElem
+ *
+ * Description:
+ * This function swaps two elements at the specified pointer locations.
+ * The size of each element could be anything as specified by <elemSize>
+ *
+ * Return Value:
+ * OMXResult -- Error status from the function
+ */
+OMXResult armSwapElem(OMX_U8 *pBuf1, OMX_U8 *pBuf2, OMX_INT elemSize);
+
+
+/**
+ * Function: armMedianOf3
+ *
+ * Description: Finds the median of three numbers
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] fEntry First entry
+ * [in] sEntry second entry
+ * [in] tEntry Third entry
+ *
+ * Return Value:
+ * OMX_S32 -- returns the median value
+ */
+
+OMX_S32 armMedianOf3 (
+ OMX_S32 fEntry,
+ OMX_S32 sEntry,
+ OMX_S32 tEntry
+ );
+
+/**
+ * Function: armLogSize
+ *
+ * Description: Finds the size of a positive value and returns the same
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] value Positive value
+ *
+ * Return Value:
+ * OMX_U8 -- returns the size of the positive value
+ */
+
+OMX_U8 armLogSize (
+ OMX_U16 value
+ );
+
+/***********************************************************************/
+ /* Saturating Arithmetic operations */
+
+/**
+ * Function :armSatAdd_S32()
+ *
+ * Description :
+ * Returns the result of saturated addition of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ *
+ **/
+
+OMX_S32 armSatAdd_S32(
+ OMX_S32 Value1,
+ OMX_S32 Value2
+ );
+
+/**
+ * Function :armSatAdd_S64()
+ *
+ * Description :
+ * Returns the result of saturated addition of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ *
+ **/
+
+OMX_S64 armSatAdd_S64(
+ OMX_S64 Value1,
+ OMX_S64 Value2
+ );
+
+/** Function :armSatSub_S32()
+ *
+ * Description :
+ * Returns the result of saturated substraction of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatSub_S32(
+ OMX_S32 Value1,
+ OMX_S32 Value2
+ );
+
+/**
+ * Function :armSatMac_S32()
+ *
+ * Description :
+ * Returns the result of Multiplication of Value1 and Value2 and subesquent saturated
+ * accumulation with Mac
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ * [in] Mac Accumulator
+ *
+ * Return:
+ * [out] Result of operation
+ **/
+
+OMX_S32 armSatMac_S32(
+ OMX_S32 Mac,
+ OMX_S16 Value1,
+ OMX_S16 Value2
+ );
+
+/**
+ * Function :armSatMac_S16S32_S32
+ *
+ * Description :
+ * Returns the result of saturated MAC operation of the three inputs delayElem, filTap , mac
+ *
+ * mac = mac + Saturate_in_32Bits(delayElem * filTap)
+ *
+ * Parametrs:
+ * [in] delayElem First 32 bit Operand
+ * [in] filTap Second 16 bit Operand
+ * [in] mac Result of MAC operation
+ *
+ * Return:
+ * [out] mac Result of operation
+ *
+ **/
+
+OMX_S32 armSatMac_S16S32_S32(
+ OMX_S32 mac,
+ OMX_S32 delayElem,
+ OMX_S16 filTap );
+
+/**
+ * Function :armSatRoundRightShift_S32_S16
+ *
+ * Description :
+ * Returns the result of rounded right shift operation of input by the scalefactor
+ *
+ * output = Saturate_in_16Bits( ( RightShift( (Round(input) , scaleFactor ) )
+ *
+ * Parametrs:
+ * [in] input The input to be operated on
+ * [in] scaleFactor The shift number
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+
+OMX_S16 armSatRoundRightShift_S32_S16(
+ OMX_S32 input,
+ OMX_INT scaleFactor);
+
+/**
+ * Function :armSatRoundLeftShift_S32()
+ *
+ * Description :
+ * Returns the result of saturating left-shift operation on input
+ * Or rounded Right shift if the input Shift is negative.
+ *
+ * Parametrs:
+ * [in] Value Operand
+ * [in] shift Operand for shift operation
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatRoundLeftShift_S32(
+ OMX_S32 Value,
+ OMX_INT shift
+ );
+
+/**
+ * Function :armSatRoundLeftShift_S64()
+ *
+ * Description :
+ * Returns the result of saturating left-shift operation on input
+ * Or rounded Right shift if the input Shift is negative.
+ *
+ * Parametrs:
+ * [in] Value Operand
+ * [in] shift Operand for shift operation
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S64 armSatRoundLeftShift_S64(
+ OMX_S64 Value,
+ OMX_INT shift
+ );
+
+/**
+ * Function :armSatMulS16S32_S32()
+ *
+ * Description :
+ * Returns the result of a S16 data type multiplied with an S32 data type
+ * in a S32 container
+ *
+ * Parametrs:
+ * [in] input1 Operand 1
+ * [in] input2 Operand 2
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+
+OMX_S32 armSatMulS16S32_S32(
+ OMX_S16 input1,
+ OMX_S32 input2);
+
+/**
+ * Function :armSatMulS32S32_S32()
+ *
+ * Description :
+ * Returns the result of a S32 data type multiplied with an S32 data type
+ * in a S32 container
+ *
+ * Parametrs:
+ * [in] input1 Operand 1
+ * [in] input2 Operand 2
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatMulS32S32_S32(
+ OMX_S32 input1,
+ OMX_S32 input2);
+
+
+/**
+ * Function :armIntDivAwayFromZero()
+ *
+ * Description : Integer division with rounding to the nearest integer.
+ * Half-integer values are rounded away from zero
+ * unless otherwise specified. For example 3//2 is rounded
+ * to 2, and -3//2 is rounded to -2.
+ *
+ * Parametrs:
+ * [in] Num Operand 1
+ * [in] Deno Operand 2
+ *
+ * Return:
+ * [out] Result of operation input1//input2
+ *
+ **/
+
+OMX_S32 armIntDivAwayFromZero (OMX_S32 Num, OMX_S32 Deno);
+
+
+/***********************************************************************/
+/*
+ * Debugging macros
+ *
+ */
+
+
+/*
+ * Definition of output stream - change to stderr if necessary
+ */
+#define DEBUG_STREAM stdout
+
+/*
+ * Debug printf macros, one for each argument count.
+ * Add more if needed.
+ */
+#ifdef DEBUG_ON
+#include <stdio.h>
+
+#define DEBUG_PRINTF_0(a) fprintf(DEBUG_STREAM, a)
+#define DEBUG_PRINTF_1(a, b) fprintf(DEBUG_STREAM, a, b)
+#define DEBUG_PRINTF_2(a, b, c) fprintf(DEBUG_STREAM, a, b, c)
+#define DEBUG_PRINTF_3(a, b, c, d) fprintf(DEBUG_STREAM, a, b, c, d)
+#define DEBUG_PRINTF_4(a, b, c, d, e) fprintf(DEBUG_STREAM, a, b, c, d, e)
+#define DEBUG_PRINTF_5(a, b, c, d, e, f) fprintf(DEBUG_STREAM, a, b, c, d, e, f)
+#define DEBUG_PRINTF_6(a, b, c, d, e, f, g) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g)
+#define DEBUG_PRINTF_7(a, b, c, d, e, f, g, h) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h)
+#define DEBUG_PRINTF_8(a, b, c, d, e, f, g, h, i) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i)
+#define DEBUG_PRINTF_9(a, b, c, d, e, f, g, h, i, j) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j)
+#define DEBUG_PRINTF_10(a, b, c, d, e, f, g, h, i, j, k) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k)
+#define DEBUG_PRINTF_11(a, b, c, d, e, f, g, h, i, j, k, l) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k, l)
+#define DEBUG_PRINTF_12(a, b, c, d, e, f, g, h, i, j, k, l, m) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k, l, m)
+#define DEBUG_PRINTF_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k, l, m, n)
+#define DEBUG_PRINTF_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) fprintf(DEBUG_STREAM, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
+#else /* DEBUG_ON */
+#define DEBUG_PRINTF_0(a)
+#define DEBUG_PRINTF_1(a, b)
+#define DEBUG_PRINTF_2(a, b, c)
+#define DEBUG_PRINTF_3(a, b, c, d)
+#define DEBUG_PRINTF_4(a, b, c, d, e)
+#define DEBUG_PRINTF_5(a, b, c, d, e, f)
+#define DEBUG_PRINTF_6(a, b, c, d, e, f, g)
+#define DEBUG_PRINTF_7(a, b, c, d, e, f, g, h)
+#define DEBUG_PRINTF_8(a, b, c, d, e, f, g, h, i)
+#define DEBUG_PRINTF_9(a, b, c, d, e, f, g, h, i, j)
+#define DEBUG_PRINTF_10(a, b, c, d, e, f, g, h, i, j, k)
+#define DEBUG_PRINTF_11(a, b, c, d, e, f, g, h, i, j, k, l)
+#define DEBUG_PRINTF_12(a, b, c, d, e, f, g, h, i, j, k, l, m)
+#define DEBUG_PRINTF_13(a, b, c, d, e, f, g, h, i, j, k, l, m, n)
+#define DEBUG_PRINTF_14(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)
+#endif /* DEBUG_ON */
+
+
+/*
+ * Domain and sub domain definitions
+ *
+ * In order to turn on debug for an entire domain or sub-domain
+ * at compile time, one of the DEBUG_DOMAIN_* below may be defined,
+ * which will activate debug in all of the defines it contains.
+ */
+
+#ifdef DEBUG_DOMAIN_AC
+#define DEBUG_OMXACAAC_DECODECHANPAIRELT_MPEG4
+#define DEBUG_OMXACAAC_DECODECHANPAIRELT
+#define DEBUG_OMXACAAC_DECODEDATSTRELT
+#define DEBUG_OMXACAAC_DECODEFILLELT
+#define DEBUG_OMXACAAC_DECODEISSTEREO_S32
+#define DEBUG_OMXACAAC_DECODEMSPNS_S32
+#define DEBUG_OMXACAAC_DECODEMSSTEREO_S32_I
+#define DEBUG_OMXACAAC_DECODEPRGCFGELT
+#define DEBUG_OMXACAAC_DECODETNS_S32_I
+#define DEBUG_OMXACAAC_DEINTERLEAVESPECTRUM_S32
+#define DEBUG_OMXACAAC_ENCODETNS_S32_I
+#define DEBUG_OMXACAAC_LONGTERMPREDICT_S32
+#define DEBUG_OMXACAAC_LONGTERMRECONSTRUCT_S32
+#define DEBUG_OMXACAAC_MDCTFWD_S32
+#define DEBUG_OMXACAAC_MDCTINV_S32_S16
+#define DEBUG_OMXACAAC_NOISELESSDECODE
+#define DEBUG_OMXACAAC_QUANTINV_S32_I
+#define DEBUG_OMXACAAC_UNPACKADIFHEADER
+#define DEBUG_OMXACAAC_UNPACKADTSFRAMEHEADER
+#define DEBUG_OMXACMP3_HUFFMANDECODESFBMBP_S32
+#define DEBUG_OMXACMP3_HUFFMANDECODESFB_S32
+#define DEBUG_OMXACMP3_HUFFMANDECODE_S32
+#define DEBUG_OMXACMP3_MDCTINV_S32
+#define DEBUG_OMXACMP3_REQUANTIZESFB_S32_I
+#define DEBUG_OMXACMP3_REQUANTIZE_S32_I
+#define DEBUG_OMXACMP3_SYNTHPQMF_S32_S16
+#define DEBUG_OMXACMP3_UNPACKFRAMEHEADER
+#define DEBUG_OMXACMP3_UNPACKSCALEFACTORS_S8
+#define DEBUG_OMXACMP3_UNPACKSIDEINFO
+#endif /* DEBUG_DOMAIN_AC */
+
+
+#ifdef DEBUG_DOMAIN_VC
+#define DEBUG_OMXVCM4P10_AVERAGE_16X
+#define DEBUG_OMXVCM4P10_AVERAGE_4X
+#define DEBUG_OMXVCM4P10_AVERAGE_8X
+#define DEBUG_OMXVCM4P10_DEBLOCKCHROMA_U8_C1IR
+#define DEBUG_OMXVCM4P10_DEBLOCKLUMA_U8_C1IR
+#define DEBUG_OMXVCM4P10_DECODECHROMADCCOEFFSTOPAIRCAVLC_U8
+#define DEBUG_OMXVCM4P10_DECODECOEFFSTOPAIRCAVLC_U8
+#define DEBUG_OMXVCM4P10_DEQUANTTRANSFORMACFROMPAIR_U8_S16_C1_DLX
+#define DEBUG_OMXVCM4P10_EXPANDFRAME
+#define DEBUG_OMXVCM4P10_FILTERDEBLOCKINGCHROMA_HOREDGE_U8_C1IR
+#define DEBUG_OMXVCM4P10_FILTERDEBLOCKINGCHROMA_VEREDGE_U8_C1IR
+#define DEBUG_OMXVCM4P10_FILTERDEBLOCKINGLUMA_HOREDGE_U8_C1IR
+#define DEBUG_OMXVCM4P10_FILTERDEBLOCKINGLUMA_VEREDGE_U8_C1IR
+#define DEBUG_OMXVCM4P10_PREDICTINTRACHROMA8X8_U8_C1R
+#define DEBUG_OMXVCM4P10_PREDICTINTRA_16X16_U8_C1R
+#define DEBUG_OMXVCM4P10_PREDICTINTRA_4X4_U8_C1R
+#define DEBUG_OMXVCM4P10_SADQUAR_16X
+#define DEBUG_OMXVCM4P10_SADQUAR_4X
+#define DEBUG_OMXVCM4P10_SADQUAR_8X
+#define DEBUG_OMXVCM4P10_SAD_16X
+#define DEBUG_OMXVCM4P10_SAD_4X
+#define DEBUG_OMXVCM4P10_SAD_8X
+#define DEBUG_OMXVCM4P10_SATD_4X4
+#define DEBUG_OMXVCM4P10_TRANSFORMDEQUANTCHROMADCFROMPAIR_U8_S16_C1
+#define DEBUG_OMXVCM4P10_TRANSFORMDEQUANTLUMADCFROMPAIR_U8_S16_C1
+#define DEBUG_OMXVCM4P10_TRANSFORMQUANT_CHROMADC
+#define DEBUG_OMXVCM4P10_TRANSFORMQUANT_LUMADC
+#define DEBUG_OMXVCM4P2_BLOCKMATCH_HALF_16X16
+#define DEBUG_OMXVCM4P2_BLOCKMATCH_HALF_8X8
+#define DEBUG_OMXVCM4P2_BLOCKMATCH_INTEGER_16X16
+#define DEBUG_OMXVCM4P2_BLOCKMATCH_INTEGER_8X8
+#define DEBUG_OMXVCM4P2_COMPUTETEXTUREERRORBLOCK_SAD_U8_S16
+#define DEBUG_OMXVCM4P2_COMPUTETEXTUREERRORBLOCK_U8_S16
+#define DEBUG_OMXVCM4P2_DCT8X8BLKDLX
+#define DEBUG_OMXVCM4P2_DECODEBLOCKCOEF_INTER_S16
+#define DEBUG_OMXVCM4P2_DECODEPADMV_PVOP
+#define DEBUG_OMXVCM4P2_DECODEVLCZIGZAG_INTER_S16
+#define DEBUG_OMXVCM4P2_DECODEVLCZIGZAG_INTRAACVLC_S16
+#define DEBUG_OMXVCM4P2_DECODEVLCZIGZAG_INTRADCVLC_S16
+#define DEBUG_OMXVCM4P2_ENCODEMV_U8_S16
+#define DEBUG_OMXVCM4P2_ENCODEVLCZIGZAG_INTER_S16
+#define DEBUG_OMXVCM4P2_ENCODEVLCZIGZAG_INTRAACVLC_S16
+#define DEBUG_OMXVCM4P2_ENCODEVLCZIGZAG_INTRADCVLC_S16
+#define DEBUG_OMXVCM4P2_FINDMVPRED
+#define DEBUG_OMXVCM4P2_IDCT8X8BLKDLX
+#define DEBUG_OMXVCM4P2_LIMITMVTORECT
+#define DEBUG_OMXVCM4P2_MOTIONESTIMATIONMB
+#define DEBUG_OMXVCM4P2_PADMBGRAY_U8
+#define DEBUG_OMXVCM4P2_PADMBHORIZONTAL_U8
+#define DEBUG_OMXVCM4P2_PADMBVERTICAL_U8
+#define DEBUG_OMXVCM4P2_PADMV
+#define DEBUG_OMXVCM4P2_QUANTINTER_S16_I
+#define DEBUG_OMXVCM4P2_QUANTINTRA_S16_I
+#define DEBUG_OMXVCM4P2_QUANTINVINTER_S16_I
+#define DEBUG_OMXVCM4P2_QUANTINVINTRA_S16_I
+#define DEBUG_OMXVCM4P2_TRANSRECBLOCKCEOF_INTER
+#define DEBUG_OMXVCM4P2_TRANSRECBLOCKCEOF_INTRA
+#endif /* DEBUG_DOMAIN_VC */
+
+
+#ifdef DEBUG_DOMAIN_IC
+/* To be filled in */
+#endif /* DEBUG_DOMAIN_IC */
+
+
+#ifdef DEBUG_DOMAIN_SP
+#define DEBUG_OMXACSP_DOTPROD_S16
+#define DEBUG_OMXACSP_BLOCKEXP_S16
+#define DEBUG_OMXACSP_BLOCKEXP_S32
+#define DEBUG_OMXACSP_COPY_S16
+#define DEBUG_OMXACSP_DOTPROD_S16
+#define DEBUG_OMXACSP_DOTPROD_S16_SFS
+#define DEBUG_OMXACSP_FFTFWD_CTOC_SC16_SFS
+#define DEBUG_OMXACSP_FFTFWD_CTOC_SC32_SFS
+#define DEBUG_OMXACSP_FFTFWD_RTOCCS_S16S32_SFS
+#define DEBUG_OMXACSP_FFTFWD_RTOCCS_S32_SFS
+#define DEBUG_OMXACSP_FFTGETBUFSIZE_C_SC16
+#define DEBUG_OMXACSP_FFTGETBUFSIZE_C_SC32
+#define DEBUG_OMXACSP_FFTGETBUFSIZE_R_S16_S32
+#define DEBUG_OMXACSP_FFTGETBUFSIZE_R_S32
+#define DEBUG_OMXACSP_FFTINIT_C_SC16
+#define DEBUG_OMXACSP_FFTINIT_C_SC32
+#define DEBUG_OMXACSP_FFTINIT_R_S16_S32
+#define DEBUG_OMXACSP_FFTINIT_R_S32
+#define DEBUG_OMXACSP_FFTINV_CCSTOR_S32S16_SFS
+#define DEBUG_OMXACSP_FFTINV_CCSTOR_S32_SFS
+#define DEBUG_OMXACSP_FFTINV_CTOC_SC16_SFS
+#define DEBUG_OMXACSP_FFTINV_CTOC_SC32_SFS
+#define DEBUG_OMXACSP_FILTERMEDIAN_S32_I
+#define DEBUG_OMXACSP_FILTERMEDIAN_S32
+#define DEBUG_OMXACSP_FIRONE_DIRECT_S16_ISFS
+#define DEBUG_OMXACSP_FIRONE_DIRECT_S16_I
+#define DEBUG_OMXACSP_FIRONE_DIRECT_S16
+#define DEBUG_OMXACSP_FIRONE_DIRECT_S16_SFS
+#define DEBUG_OMXACSP_FIR_DIRECT_S16_ISFS
+#define DEBUG_OMXACSP_FIR_DIRECT_S16_I
+#define DEBUG_OMXACSP_FIR_DIRECT_S16
+#define DEBUG_OMXACSP_FIR_DIRECT_S16_SFS
+#define DEBUG_OMXACSP_IIRONE_BIQUADDIRECT_S16_I
+#define DEBUG_OMXACSP_IIRONE_BIQUADDIRECT_S16
+#define DEBUG_OMXACSP_IIRONE_DIRECT_S16_I
+#define DEBUG_OMXACSP_IIRONE_DIRECT_S16
+#define DEBUG_OMXACSP_IIR_BIQUADDIRECT_S16_I
+#define DEBUG_OMXACSP_IIR_BIQUADDIRECT_S16
+#define DEBUG_OMXACSP_IIR_DIRECT_S16_I
+#define DEBUG_OMXACSP_IIR_DIRECT_S16
+#endif /* DEBUG_DOMAIN_SP */
+
+
+#ifdef DEBUG_DOMAIN_IP
+#define DEBUG_OMXIPBM_ADDC_U8_C1R_SFS
+#define DEBUG_OMXIPBM_COPY_U8_C1R
+#define DEBUG_OMXIPBM_COPY_U8_C3R
+#define DEBUG_OMXIPBM_MIRROR_U8_C1R
+#define DEBUG_OMXIPBM_MULC_U8_C1R_SFS
+#define DEBUG_OMXIPCS_COLORTWISTQ14_U8_C3R
+#define DEBUG_OMXIPCS_RGB565TOYCBCR420LS_MCU_U16_S16_C3P3R
+#define DEBUG_OMXIPCS_RGB565TOYCBCR422LS_MCU_U16_S16_C3P3R
+#define DEBUG_OMXIPCS_RGB565TOYCBCR444LS_MCU_U16_S16_C3P3R
+#define DEBUG_OMXIPCS_RGBTOYCBCR420LS_MCU_U8_S16_C3P3R
+#define DEBUG_OMXIPCS_RGBTOYCBCR422LS_MCU_U8_S16_C3P3R
+#define DEBUG_OMXIPCS_RGBTOYCBCR444LS_MCU_U8_S16_C3P3R
+#define DEBUG_OMXIPCS_YCBCR420RSZROT_U8_P3R
+#define DEBUG_OMXIPCS_YCBCR420TORGB565LS_MCU_S16_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCR420TORGB565_U8_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCR420TORGBLS_MCU_S16_U8_P3C3R
+#define DEBUG_OMXIPCS_YCBCR422RSZCSCROTRGB_U8_C2R
+#define DEBUG_OMXIPCS_YCBCR422RSZROT_U8_P3R
+#define DEBUG_OMXIPCS_YCBCR422TORGB565LS_MCU_S16_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCR422TORGB565_U8_U16_C2C3R
+#define DEBUG_OMXIPCS_YCBCR422TORGBLS_MCU_S16_U8_P3C3R
+#define DEBUG_OMXIPCS_YCBCR422TORGB_U8_C2C3R
+#define DEBUG_OMXIPCS_YCBCR422TOYCBCR420ROTATE_U8_C2P3R
+#define DEBUG_OMXIPCS_YCBCR422TOYCBCR420ROTATE_U8_P3R
+#define DEBUG_OMXIPCS_YCBCR444TORGB565LS_MCU_S16_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCR444TORGBLS_MCU_S16_U8_P3C3R
+#define DEBUG_OMXIPCS_YCBCRTORGB565_U8_U16_C3R
+#define DEBUG_OMXIPCS_YCBCRTORGB565_U8_U16_P3C3R
+#define DEBUG_OMXIPCS_YCBCRTORGB_U8_C3R
+#define DEBUG_OMXIPPP_GETCENTRALMOMENT_S64
+#define DEBUG_OMXIPPP_GETSPATIALMOMENT_S64
+#define DEBUG_OMXIPPP_MOMENTGETSTATESIZE_S64
+#define DEBUG_OMXIPPP_MOMENTINIT_S64
+#define DEBUG_OMXIPPP_MOMENTS64S_U8_C1R
+#define DEBUG_OMXIPPP_MOMENTS64S_U8_C3R
+#endif /* DEBUG_DOMAIN_IP */
+
+
+#endif /* _armCommon_H_ */
+
+/*End of File*/
+
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM_Bitstream.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM_Bitstream.h
new file mode 100644
index 0000000..4f9bc3b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM_Bitstream.h
@@ -0,0 +1,212 @@
+/**
+ *
+ * File Name: armCOMM_Bitstream.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armCOMM_Bitstream.h
+ * Brief: Declares common API's/Data types used across the OpenMax Encoders/Decoders.
+ *
+ */
+
+#ifndef _armCodec_H_
+#define _armCodec_H_
+
+#include "omxtypes.h"
+
+typedef struct {
+ OMX_U8 codeLen;
+ OMX_U32 codeWord;
+} ARM_VLC32;
+
+/* The above should be renamed as "ARM_VLC32" */
+
+/**
+ * Function: armLookAheadBits()
+ *
+ * Description:
+ * Get the next N bits from the bitstream without advancing the bitstream pointer
+ *
+ * Parameters:
+ * [in] **ppBitStream
+ * [in] *pOffset
+ * [in] N=1...32
+ *
+ * Returns Value
+ */
+
+OMX_U32 armLookAheadBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N);
+
+/**
+ * Function: armGetBits()
+ *
+ * Description:
+ * Read N bits from the bitstream
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ * [in] N=1..32
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ * Returns Value
+ */
+
+OMX_U32 armGetBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N);
+
+/**
+ * Function: armByteAlign()
+ *
+ * Description:
+ * Align the pointer *ppBitStream to the next byte boundary
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ *
+ **/
+
+OMXVoid armByteAlign(const OMX_U8 **ppBitStream,OMX_INT *pOffset);
+
+/**
+ * Function: armSkipBits()
+ *
+ * Description:
+ * Skip N bits from the value at *ppBitStream
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ * [in] N
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ *
+ **/
+
+OMXVoid armSkipBits(const OMX_U8 **ppBitStream,OMX_INT *pOffset,OMX_INT N);
+
+/***************************************
+ * Variable bit length Decode
+ ***************************************/
+
+/**
+ * Function: armUnPackVLC32()
+ *
+ * Description:
+ * Variable length decode of variable length symbol (max size 32 bits) read from
+ * the bit stream pointed by *ppBitStream at *pOffset by using the table
+ * pointed by pCodeBook
+ *
+ * Parameters:
+ * [in] **ppBitStream
+ * [in] *pOffset
+ * [in] pCodeBook
+ *
+ * [out] **ppBitStream
+ * [out] *pOffset
+ *
+ * Returns : Code Book Index if successfull.
+ * : "ARM_NO_CODEBOOK_INDEX = 0xFFFF" if search fails.
+ **/
+
+#define ARM_NO_CODEBOOK_INDEX (OMX_U16)(0xFFFF)
+
+OMX_U16 armUnPackVLC32(
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pOffset,
+ const ARM_VLC32 *pCodeBook
+);
+
+/***************************************
+ * Fixed bit length Encode
+ ***************************************/
+
+/**
+ * Function: armPackBits
+ *
+ * Description:
+ * Pack a VLC code word into the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte
+ * in the bit stream.
+ * [in] pOffset pointer to the bit position in the byte
+ * pointed by *ppBitStream. Valid within 0
+ * to 7.
+ * [in] codeWord Code word that need to be inserted in to the
+ * bitstream
+ * [in] codeLength Length of the code word valid range 1...32
+ *
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMX_RESULT result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armPackBits (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pOffset,
+ OMX_U32 codeWord,
+ OMX_INT codeLength
+);
+
+/***************************************
+ * Variable bit length Encode
+ ***************************************/
+
+/**
+ * Function: armPackVLC32
+ *
+ * Description:
+ * Pack a VLC code word into the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte
+ * in the bit stream.
+ * [in] pBitOffset pointer to the bit position in the byte
+ * pointed by *ppBitStream. Valid within 0
+ * to 7.
+ * [in] code VLC code word that need to be inserted in to the
+ * bitstream
+ *
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMX_RESULT result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armPackVLC32 (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ ARM_VLC32 code
+);
+
+#endif /*_armCodec_H_*/
+
+/*End of File*/
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM_Version.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM_Version.h
new file mode 100644
index 0000000..e99a450
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armCOMM_Version.h
@@ -0,0 +1,43 @@
+/* Guard the header against multiple inclusion. */
+#ifndef __ARM_COMM_VERSION_H__
+#define __ARM_COMM_VERSION_H__
+
+
+/* The following line should be in omxtypes.h but hasn't been approved by OpenMAX yet */
+#define OMX_VERSION 102
+
+/* We need to define these macros in order to convert a #define number into a #define string. */
+#define ARM_QUOTE(a) #a
+#define ARM_INDIRECT(A) ARM_QUOTE(A)
+
+/* Convert the OMX_VERSION number into a string that can be used, for example, to print it out. */
+#define ARM_VERSION_STRING ARM_INDIRECT(OMX_VERSION)
+
+
+/* Define this in order to turn on ARM version/release/build strings in each domain */
+#define ARM_INCLUDE_VERSION_DESCRIPTIONS
+
+#ifdef ARM_INCLUDE_VERSION_DESCRIPTIONS
+ extern const char * const omxAC_VersionDescription;
+ extern const char * const omxIC_VersionDescription;
+ extern const char * const omxIP_VersionDescription;
+ extern const char * const omxSP_VersionDescription;
+ extern const char * const omxVC_VersionDescription;
+#endif /* ARM_INCLUDE_VERSION_DESCRIPTIONS */
+
+
+/* The following entries should be automatically updated by the release script */
+/* They are used in the ARM version strings defined for each domain. */
+
+/* The release tag associated with this release of the library. - used for source and object releases */
+#define OMX_ARM_RELEASE_TAG "r0p0-00bet1"
+
+/* The ARM architecture used to build any objects or executables in this release. */
+#define OMX_ARM_BUILD_ARCHITECTURE "ANSI C"
+
+/* The ARM Toolchain used to build any objects or executables in this release. */
+#define OMX_ARM_BUILD_TOOLCHAIN "ARM RVCT 3.1"
+
+
+#endif /* __ARM_COMM_VERSION_H__ */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armOMX.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armOMX.h
new file mode 100644
index 0000000..f629f72
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/armOMX.h
@@ -0,0 +1,274 @@
+/*
+ *
+ * File Name: armOMX_ReleaseVersion.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * This file allows a version of the OMX DL libraries to be built where some or
+ * all of the function names can be given a user specified suffix.
+ *
+ * You might want to use it where:
+ *
+ * - you want to rename a function "out of the way" so that you could replace
+ * a function with a different version (the original version would still be
+ * in the library just with a different name - so you could debug the new
+ * version by comparing it to the output of the old)
+ *
+ * - you want to rename all the functions to versions with a suffix so that
+ * you can include two versions of the library and choose between functions
+ * at runtime.
+ *
+ * e.g. omxIPBM_Copy_U8_C1R could be renamed omxIPBM_Copy_U8_C1R_CortexA8
+ *
+ */
+
+
+#ifndef _armOMX_H_
+#define _armOMX_H_
+
+
+/* We need to define these two macros in order to expand and concatenate the names */
+#define OMXCAT2BAR(A, B) omx ## A ## B
+#define OMXCATBAR(A, B) OMXCAT2BAR(A, B)
+
+/* Define the suffix to add to all functions - the default is no suffix */
+#define BARE_SUFFIX
+
+
+
+/* Define what happens to the bare suffix-less functions, down to the sub-domain accuracy */
+#define OMXACAAC_SUFFIX BARE_SUFFIX
+#define OMXACMP3_SUFFIX BARE_SUFFIX
+#define OMXICJP_SUFFIX BARE_SUFFIX
+#define OMXIPBM_SUFFIX BARE_SUFFIX
+#define OMXIPCS_SUFFIX BARE_SUFFIX
+#define OMXIPPP_SUFFIX BARE_SUFFIX
+#define OMXSP_SUFFIX BARE_SUFFIX
+#define OMXVCCOMM_SUFFIX BARE_SUFFIX
+#define OMXVCM4P10_SUFFIX BARE_SUFFIX
+#define OMXVCM4P2_SUFFIX BARE_SUFFIX
+
+
+
+
+/* Define what the each bare, un-suffixed OpenMAX API function names is to be renamed */
+#define omxACAAC_DecodeChanPairElt OMXCATBAR(ACAAC_DecodeChanPairElt, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeDatStrElt OMXCATBAR(ACAAC_DecodeDatStrElt, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeFillElt OMXCATBAR(ACAAC_DecodeFillElt, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeIsStereo_S32 OMXCATBAR(ACAAC_DecodeIsStereo_S32, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeMsPNS_S32_I OMXCATBAR(ACAAC_DecodeMsPNS_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeMsStereo_S32_I OMXCATBAR(ACAAC_DecodeMsStereo_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodePrgCfgElt OMXCATBAR(ACAAC_DecodePrgCfgElt, OMXACAAC_SUFFIX)
+#define omxACAAC_DecodeTNS_S32_I OMXCATBAR(ACAAC_DecodeTNS_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_DeinterleaveSpectrum_S32 OMXCATBAR(ACAAC_DeinterleaveSpectrum_S32, OMXACAAC_SUFFIX)
+#define omxACAAC_EncodeTNS_S32_I OMXCATBAR(ACAAC_EncodeTNS_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_LongTermPredict_S32 OMXCATBAR(ACAAC_LongTermPredict_S32, OMXACAAC_SUFFIX)
+#define omxACAAC_LongTermReconstruct_S32_I OMXCATBAR(ACAAC_LongTermReconstruct_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_MDCTFwd_S32 OMXCATBAR(ACAAC_MDCTFwd_S32, OMXACAAC_SUFFIX)
+#define omxACAAC_MDCTInv_S32_S16 OMXCATBAR(ACAAC_MDCTInv_S32_S16, OMXACAAC_SUFFIX)
+#define omxACAAC_NoiselessDecode OMXCATBAR(ACAAC_NoiselessDecode, OMXACAAC_SUFFIX)
+#define omxACAAC_QuantInv_S32_I OMXCATBAR(ACAAC_QuantInv_S32_I, OMXACAAC_SUFFIX)
+#define omxACAAC_UnpackADIFHeader OMXCATBAR(ACAAC_UnpackADIFHeader, OMXACAAC_SUFFIX)
+#define omxACAAC_UnpackADTSFrameHeader OMXCATBAR(ACAAC_UnpackADTSFrameHeader, OMXACAAC_SUFFIX)
+
+
+#define omxACMP3_HuffmanDecode_S32 OMXCATBAR(ACMP3_HuffmanDecode_S32, OMXACMP3_SUFFIX)
+#define omxACMP3_HuffmanDecodeSfb_S32 OMXCATBAR(ACMP3_HuffmanDecodeSfb_S32, OMXACMP3_SUFFIX)
+#define omxACMP3_HuffmanDecodeSfbMbp_S32 OMXCATBAR(ACMP3_HuffmanDecodeSfbMbp_S32, OMXACMP3_SUFFIX)
+#define omxACMP3_MDCTInv_S32 OMXCATBAR(ACMP3_MDCTInv_S32, OMXACMP3_SUFFIX)
+#define omxACMP3_ReQuantize_S32_I OMXCATBAR(ACMP3_ReQuantize_S32_I, OMXACMP3_SUFFIX)
+#define omxACMP3_ReQuantizeSfb_S32_I OMXCATBAR(ACMP3_ReQuantizeSfb_S32_I, OMXACMP3_SUFFIX)
+#define omxACMP3_SynthPQMF_S32_S16 OMXCATBAR(ACMP3_SynthPQMF_S32_S16, OMXACMP3_SUFFIX)
+#define omxACMP3_UnpackFrameHeader OMXCATBAR(ACMP3_UnpackFrameHeader, OMXACMP3_SUFFIX)
+#define omxACMP3_UnpackScaleFactors_S8 OMXCATBAR(ACMP3_UnpackScaleFactors_S8, OMXACMP3_SUFFIX)
+#define omxACMP3_UnpackSideInfo OMXCATBAR(ACMP3_UnpackSideInfo, OMXACMP3_SUFFIX)
+
+#define omxICJP_CopyExpand_U8_C3 OMXCATBAR(ICJP_CopyExpand_U8_C3, OMXICJP_SUFFIX)
+#define omxICJP_DCTFwd_S16 OMXCATBAR(ICJP_DCTFwd_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTFwd_S16_I OMXCATBAR(ICJP_DCTFwd_S16_I, OMXICJP_SUFFIX)
+#define omxICJP_DCTInv_S16 OMXCATBAR(ICJP_DCTInv_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTInv_S16_I OMXCATBAR(ICJP_DCTInv_S16_I, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantFwd_Multiple_S16 OMXCATBAR(ICJP_DCTQuantFwd_Multiple_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantFwd_S16 OMXCATBAR(ICJP_DCTQuantFwd_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantFwd_S16_I OMXCATBAR(ICJP_DCTQuantFwd_S16_I, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantFwdTableInit OMXCATBAR(ICJP_DCTQuantFwdTableInit, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantInv_Multiple_S16 OMXCATBAR(ICJP_DCTQuantInv_Multiple_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantInv_S16 OMXCATBAR(ICJP_DCTQuantInv_S16, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantInv_S16_I OMXCATBAR(ICJP_DCTQuantInv_S16_I, OMXICJP_SUFFIX)
+#define omxICJP_DCTQuantInvTableInit OMXCATBAR(ICJP_DCTQuantInvTableInit, OMXICJP_SUFFIX)
+#define omxICJP_DecodeHuffman8x8_Direct_S16_C1 OMXCATBAR(ICJP_DecodeHuffman8x8_Direct_S16_C1, OMXICJP_SUFFIX)
+#define omxICJP_DecodeHuffmanSpecGetBufSize_U8 OMXCATBAR(ICJP_DecodeHuffmanSpecGetBufSize_U8, OMXICJP_SUFFIX)
+#define omxICJP_DecodeHuffmanSpecInit_U8 OMXCATBAR(ICJP_DecodeHuffmanSpecInit_U8, OMXICJP_SUFFIX)
+#define omxICJP_EncodeHuffman8x8_Direct_S16_U1_C1 OMXCATBAR(ICJP_EncodeHuffman8x8_Direct_S16_U1_C1, OMXICJP_SUFFIX)
+#define omxICJP_EncodeHuffmanSpecGetBufSize_U8 OMXCATBAR(ICJP_EncodeHuffmanSpecGetBufSize_U8, OMXICJP_SUFFIX)
+#define omxICJP_EncodeHuffmanSpecInit_U8 OMXCATBAR(ICJP_EncodeHuffmanSpecInit_U8, OMXICJP_SUFFIX)
+
+#define omxIPBM_AddC_U8_C1R_Sfs OMXCATBAR(IPBM_AddC_U8_C1R_Sfs, OMXIPBM_SUFFIX)
+#define omxIPBM_Copy_U8_C1R OMXCATBAR(IPBM_Copy_U8_C1R, OMXIPBM_SUFFIX)
+#define omxIPBM_Copy_U8_C3R OMXCATBAR(IPBM_Copy_U8_C3R, OMXIPBM_SUFFIX)
+#define omxIPBM_Mirror_U8_C1R OMXCATBAR(IPBM_Mirror_U8_C1R, OMXIPBM_SUFFIX)
+#define omxIPBM_MulC_U8_C1R_Sfs OMXCATBAR(IPBM_MulC_U8_C1R_Sfs, OMXIPBM_SUFFIX)
+
+#define omxIPCS_ColorTwistQ14_U8_C3R OMXCATBAR(IPCS_ColorTwistQ14_U8_C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR565ToYCbCr420LS_MCU_U16_S16_C3P3R OMXCATBAR(IPCS_BGR565ToYCbCr420LS_MCU_U16_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR565ToYCbCr422LS_MCU_U16_S16_C3P3R OMXCATBAR(IPCS_BGR565ToYCbCr422LS_MCU_U16_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR565ToYCbCr444LS_MCU_U16_S16_C3P3R OMXCATBAR(IPCS_BGR565ToYCbCr444LS_MCU_U16_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR888ToYCbCr420LS_MCU_U8_S16_C3P3R OMXCATBAR(IPCS_BGR888ToYCbCr420LS_MCU_U8_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR888ToYCbCr422LS_MCU_U8_S16_C3P3R OMXCATBAR(IPCS_BGR888ToYCbCr422LS_MCU_U8_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_BGR888ToYCbCr444LS_MCU_U8_S16_C3P3R OMXCATBAR(IPCS_BGR888ToYCbCr444LS_MCU_U8_S16_C3P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420RszCscRotBGR_U8_P3C3R OMXCATBAR(IPCS_YCbCr420RszCscRotBGR_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420RszRot_U8_P3R OMXCATBAR(IPCS_YCbCr420RszRot_U8_P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420ToBGR565_U8_U16_P3C3R OMXCATBAR(IPCS_YCbCr420ToBGR565_U8_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420ToBGR565LS_MCU_S16_U16_P3C3R OMXCATBAR(IPCS_YCbCr420ToBGR565LS_MCU_S16_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr420ToBGR888LS_MCU_S16_U8_P3C3R OMXCATBAR(IPCS_YCbCr420ToBGR888LS_MCU_S16_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422RszCscRotBGR_U8_P3C3R OMXCATBAR(IPCS_YCbCr422RszCscRotBGR_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_CbYCrY422RszCscRotBGR_U8_U16_C2R OMXCATBAR(IPCS_CbYCrY422RszCscRotBGR_U8_U16_C2R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422RszRot_U8_P3R OMXCATBAR(IPCS_YCbCr422RszRot_U8_P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbYCr422ToBGR565_U8_U16_C2C3R OMXCATBAR(IPCS_YCbYCr422ToBGR565_U8_U16_C2C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422ToBGR565LS_MCU_S16_U16_P3C3R OMXCATBAR(IPCS_YCbCr422ToBGR565LS_MCU_S16_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbYCr422ToBGR888_U8_C2C3R OMXCATBAR(IPCS_YCbYCr422ToBGR888_U8_C2C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422ToBGR888LS_MCU_S16_U8_P3C3R OMXCATBAR(IPCS_YCbCr422ToBGR888LS_MCU_S16_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422ToBGR888LS_MCU_S16_U8_P3C3R OMXCATBAR(IPCS_YCbCr422ToBGR888LS_MCU_S16_U8_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_CbYCrY422ToYCbCr420Rotate_U8_C2P3R OMXCATBAR(IPCS_CbYCrY422ToYCbCr420Rotate_U8_C2P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr422ToYCbCr420Rotate_U8_P3R OMXCATBAR(IPCS_YCbCr422ToYCbCr420Rotate_U8_P3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr444ToBGR565_U8_U16_C3R OMXCATBAR(IPCS_YCbCr444ToBGR565_U8_U16_C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr444ToBGR565_U8_U16_P3C3R OMXCATBAR(IPCS_YCbCr444ToBGR565_U8_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr444ToBGR565LS_MCU_S16_U16_P3C3R OMXCATBAR(IPCS_YCbCr444ToBGR565LS_MCU_S16_U16_P3C3R, OMXIPCS_SUFFIX)
+#define omxIPCS_YCbCr444ToBGR888_U8_C3R OMXCATBAR(IPCS_YCbCr444ToBGR888_U8_C3R, OMXIPCS_SUFFIX)
+
+#define omxIPPP_Deblock_HorEdge_U8_I OMXCATBAR(IPPP_Deblock_HorEdge_U8_I, OMXIPPP_SUFFIX)
+#define omxIPPP_Deblock_VerEdge_U8_I OMXCATBAR(IPPP_Deblock_VerEdge_U8_I, OMXIPPP_SUFFIX)
+#define omxIPPP_FilterFIR_U8_C1R OMXCATBAR(IPPP_FilterFIR_U8_C1R, OMXIPPP_SUFFIX)
+#define omxIPPP_FilterMedian_U8_C1R OMXCATBAR(IPPP_FilterMedian_U8_C1R, OMXIPPP_SUFFIX)
+#define omxIPPP_GetCentralMoment_S64 OMXCATBAR(IPPP_GetCentralMoment_S64, OMXIPPP_SUFFIX)
+#define omxIPPP_GetSpatialMoment_S64 OMXCATBAR(IPPP_GetSpatialMoment_S64, OMXIPPP_SUFFIX)
+#define omxIPPP_MomentGetStateSize OMXCATBAR(IPPP_MomentGetStateSize, OMXIPPP_SUFFIX)
+#define omxIPPP_MomentInit OMXCATBAR(IPPP_MomentInit, OMXIPPP_SUFFIX)
+#define omxIPPP_Moments_U8_C1R OMXCATBAR(IPPP_Moments_U8_C1R, OMXIPPP_SUFFIX)
+#define omxIPPP_Moments_U8_C3R OMXCATBAR(IPPP_Moments_U8_C3R, OMXIPPP_SUFFIX)
+
+#define omxSP_BlockExp_S16 OMXCATBAR(SP_BlockExp_S16, OMXSP_SUFFIX)
+#define omxSP_BlockExp_S32 OMXCATBAR(SP_BlockExp_S32, OMXSP_SUFFIX)
+#define omxSP_Copy_S16 OMXCATBAR(SP_Copy_S16, OMXSP_SUFFIX)
+#define omxSP_DotProd_S16 OMXCATBAR(SP_DotProd_S16, OMXSP_SUFFIX)
+#define omxSP_DotProd_S16_Sfs OMXCATBAR(SP_DotProd_S16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTFwd_CToC_SC16_Sfs OMXCATBAR(SP_FFTFwd_CToC_SC16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTFwd_CToC_SC32_Sfs OMXCATBAR(SP_FFTFwd_CToC_SC32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTFwd_RToCCS_S16S32_Sfs OMXCATBAR(SP_FFTFwd_RToCCS_S16S32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTFwd_RToCCS_S32_Sfs OMXCATBAR(SP_FFTFwd_RToCCS_S32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTGetBufSize_C_SC16 OMXCATBAR(SP_FFTGetBufSize_C_SC16, OMXSP_SUFFIX)
+#define omxSP_FFTGetBufSize_C_SC32 OMXCATBAR(SP_FFTGetBufSize_C_SC32, OMXSP_SUFFIX)
+#define omxSP_FFTGetBufSize_R_S16S32 OMXCATBAR(SP_FFTGetBufSize_R_S16S32, OMXSP_SUFFIX)
+#define omxSP_FFTGetBufSize_R_S32 OMXCATBAR(SP_FFTGetBufSize_R_S32, OMXSP_SUFFIX)
+#define omxSP_FFTInit_C_SC16 OMXCATBAR(SP_FFTInit_C_SC16, OMXSP_SUFFIX)
+#define omxSP_FFTInit_C_SC32 OMXCATBAR(SP_FFTInit_C_SC32, OMXSP_SUFFIX)
+#define omxSP_FFTInit_R_S16S32 OMXCATBAR(SP_FFTInit_R_S16S32, OMXSP_SUFFIX)
+#define omxSP_FFTInit_R_S32 OMXCATBAR(SP_FFTInit_R_S32, OMXSP_SUFFIX)
+#define omxSP_FFTInv_CCSToR_S32_Sfs OMXCATBAR(SP_FFTInv_CCSToR_S32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTInv_CCSToR_S32S16_Sfs OMXCATBAR(SP_FFTInv_CCSToR_S32S16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTInv_CToC_SC16_Sfs OMXCATBAR(SP_FFTInv_CToC_SC16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FFTInv_CToC_SC32_Sfs OMXCATBAR(SP_FFTInv_CToC_SC32_Sfs, OMXSP_SUFFIX)
+#define omxSP_FilterMedian_S32 OMXCATBAR(SP_FilterMedian_S32, OMXSP_SUFFIX)
+#define omxSP_FilterMedian_S32_I OMXCATBAR(SP_FilterMedian_S32_I, OMXSP_SUFFIX)
+#define omxSP_FIR_Direct_S16 OMXCATBAR(SP_FIR_Direct_S16, OMXSP_SUFFIX)
+#define omxSP_FIR_Direct_S16_I OMXCATBAR(SP_FIR_Direct_S16_I, OMXSP_SUFFIX)
+#define omxSP_FIR_Direct_S16_ISfs OMXCATBAR(SP_FIR_Direct_S16_ISfs, OMXSP_SUFFIX)
+#define omxSP_FIR_Direct_S16_Sfs OMXCATBAR(SP_FIR_Direct_S16_Sfs, OMXSP_SUFFIX)
+#define omxSP_FIROne_Direct_S16 OMXCATBAR(SP_FIROne_Direct_S16, OMXSP_SUFFIX)
+#define omxSP_FIROne_Direct_S16_I OMXCATBAR(SP_FIROne_Direct_S16_I, OMXSP_SUFFIX)
+#define omxSP_FIROne_Direct_S16_ISfs OMXCATBAR(SP_FIROne_Direct_S16_ISfs, OMXSP_SUFFIX)
+#define omxSP_FIROne_Direct_S16_Sfs OMXCATBAR(SP_FIROne_Direct_S16_Sfs, OMXSP_SUFFIX)
+#define omxSP_IIR_BiQuadDirect_S16 OMXCATBAR(SP_IIR_BiQuadDirect_S16, OMXSP_SUFFIX)
+#define omxSP_IIR_BiQuadDirect_S16_I OMXCATBAR(SP_IIR_BiQuadDirect_S16_I, OMXSP_SUFFIX)
+#define omxSP_IIR_Direct_S16 OMXCATBAR(SP_IIR_Direct_S16, OMXSP_SUFFIX)
+#define omxSP_IIR_Direct_S16_I OMXCATBAR(SP_IIR_Direct_S16_I, OMXSP_SUFFIX)
+#define omxSP_IIROne_BiQuadDirect_S16 OMXCATBAR(SP_IIROne_BiQuadDirect_S16, OMXSP_SUFFIX)
+#define omxSP_IIROne_BiQuadDirect_S16_I OMXCATBAR(SP_IIROne_BiQuadDirect_S16_I, OMXSP_SUFFIX)
+#define omxSP_IIROne_Direct_S16 OMXCATBAR(SP_IIROne_Direct_S16, OMXSP_SUFFIX)
+#define omxSP_IIROne_Direct_S16_I OMXCATBAR(SP_IIROne_Direct_S16_I, OMXSP_SUFFIX)
+
+#define omxVCCOMM_Average_16x OMXCATBAR(VCCOMM_Average_16x, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_Average_8x OMXCATBAR(VCCOMM_Average_8x, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_ComputeTextureErrorBlock OMXCATBAR(VCCOMM_ComputeTextureErrorBlock, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_ComputeTextureErrorBlock_SAD OMXCATBAR(VCCOMM_ComputeTextureErrorBlock_SAD, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_Copy16x16 OMXCATBAR(VCCOMM_Copy16x16, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_Copy8x8 OMXCATBAR(VCCOMM_Copy8x8, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_ExpandFrame_I OMXCATBAR(VCCOMM_ExpandFrame_I, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_LimitMVToRect OMXCATBAR(VCCOMM_LimitMVToRect, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_SAD_16x OMXCATBAR(VCCOMM_SAD_16x, OMXVCCOMM_SUFFIX)
+#define omxVCCOMM_SAD_8x OMXCATBAR(VCCOMM_SAD_8x, OMXVCCOMM_SUFFIX)
+
+#define omxVCM4P10_Average_4x OMXCATBAR(VCM4P10_Average_4x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_BlockMatch_Half OMXCATBAR(VCM4P10_BlockMatch_Half, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_BlockMatch_Integer OMXCATBAR(VCM4P10_BlockMatch_Integer, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_BlockMatch_Quarter OMXCATBAR(VCM4P10_BlockMatch_Quarter, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DeblockChroma_I OMXCATBAR(VCM4P10_DeblockChroma_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DeblockLuma_I OMXCATBAR(VCM4P10_DeblockLuma_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC OMXCATBAR(VCM4P10_DecodeChromaDcCoeffsToPairCAVLC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DecodeCoeffsToPairCAVLC OMXCATBAR(VCM4P10_DecodeCoeffsToPairCAVLC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_DequantTransformResidualFromPairAndAdd OMXCATBAR(VCM4P10_DequantTransformResidualFromPairAndAdd, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_FilterDeblockingChroma_HorEdge_I OMXCATBAR(VCM4P10_FilterDeblockingChroma_HorEdge_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_FilterDeblockingChroma_VerEdge_I OMXCATBAR(VCM4P10_FilterDeblockingChroma_VerEdge_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_FilterDeblockingLuma_HorEdge_I OMXCATBAR(VCM4P10_FilterDeblockingLuma_HorEdge_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_FilterDeblockingLuma_VerEdge_I OMXCATBAR(VCM4P10_FilterDeblockingLuma_VerEdge_I, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_GetVLCInfo OMXCATBAR(VCM4P10_GetVLCInfo, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InterpolateChroma OMXCATBAR(VCM4P10_InterpolateChroma, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InterpolateHalfHor_Luma OMXCATBAR(VCM4P10_InterpolateHalfHor_Luma, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InterpolateHalfVer_Luma OMXCATBAR(VCM4P10_InterpolateHalfVer_Luma, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InterpolateLuma OMXCATBAR(VCM4P10_InterpolateLuma, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InvTransformDequant_ChromaDC OMXCATBAR(VCM4P10_InvTransformDequant_ChromaDC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InvTransformDequant_LumaDC OMXCATBAR(VCM4P10_InvTransformDequant_LumaDC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_InvTransformResidualAndAdd OMXCATBAR(VCM4P10_InvTransformResidualAndAdd, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_MEGetBufSize OMXCATBAR(VCM4P10_MEGetBufSize, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_MEInit OMXCATBAR(VCM4P10_MEInit, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_MotionEstimationMB OMXCATBAR(VCM4P10_MotionEstimationMB, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_PredictIntra_16x16 OMXCATBAR(VCM4P10_PredictIntra_16x16, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_PredictIntra_4x4 OMXCATBAR(VCM4P10_PredictIntra_4x4, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_PredictIntraChroma_8x8 OMXCATBAR(VCM4P10_PredictIntraChroma_8x8, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SAD_4x OMXCATBAR(VCM4P10_SAD_4x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SADQuar_16x OMXCATBAR(VCM4P10_SADQuar_16x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SADQuar_4x OMXCATBAR(VCM4P10_SADQuar_4x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SADQuar_8x OMXCATBAR(VCM4P10_SADQuar_8x, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SATD_4x4 OMXCATBAR(VCM4P10_SATD_4x4, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_SubAndTransformQDQResidual OMXCATBAR(VCM4P10_SubAndTransformQDQResidual, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_TransformDequantChromaDCFromPair OMXCATBAR(VCM4P10_TransformDequantChromaDCFromPair, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_TransformDequantLumaDCFromPair OMXCATBAR(VCM4P10_TransformDequantLumaDCFromPair, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_TransformQuant_ChromaDC OMXCATBAR(VCM4P10_TransformQuant_ChromaDC, OMXVCM4P10_SUFFIX)
+#define omxVCM4P10_TransformQuant_LumaDC OMXCATBAR(VCM4P10_TransformQuant_LumaDC, OMXVCM4P10_SUFFIX)
+
+#define omxVCM4P2_BlockMatch_Half_16x16 OMXCATBAR(VCM4P2_BlockMatch_Half_16x16, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_BlockMatch_Half_8x8 OMXCATBAR(VCM4P2_BlockMatch_Half_8x8, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_BlockMatch_Integer_16x16 OMXCATBAR(VCM4P2_BlockMatch_Integer_16x16, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_BlockMatch_Integer_8x8 OMXCATBAR(VCM4P2_BlockMatch_Integer_8x8, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DCT8x8blk OMXCATBAR(VCM4P2_DCT8x8blk, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeBlockCoef_Inter OMXCATBAR(VCM4P2_DecodeBlockCoef_Inter, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeBlockCoef_Intra OMXCATBAR(VCM4P2_DecodeBlockCoef_Intra, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodePadMV_PVOP OMXCATBAR(VCM4P2_DecodePadMV_PVOP, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeVLCZigzag_Inter OMXCATBAR(VCM4P2_DecodeVLCZigzag_Inter, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeVLCZigzag_IntraACVLC OMXCATBAR(VCM4P2_DecodeVLCZigzag_IntraACVLC, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_DecodeVLCZigzag_IntraDCVLC OMXCATBAR(VCM4P2_DecodeVLCZigzag_IntraDCVLC, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_EncodeMV OMXCATBAR(VCM4P2_EncodeMV, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_EncodeVLCZigzag_Inter OMXCATBAR(VCM4P2_EncodeVLCZigzag_Inter, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_EncodeVLCZigzag_IntraACVLC OMXCATBAR(VCM4P2_EncodeVLCZigzag_IntraACVLC, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_EncodeVLCZigzag_IntraDCVLC OMXCATBAR(VCM4P2_EncodeVLCZigzag_IntraDCVLC, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_FindMVpred OMXCATBAR(VCM4P2_FindMVpred, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_IDCT8x8blk OMXCATBAR(VCM4P2_IDCT8x8blk, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_MCReconBlock OMXCATBAR(VCM4P2_MCReconBlock, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_MEGetBufSize OMXCATBAR(VCM4P2_MEGetBufSize, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_MEInit OMXCATBAR(VCM4P2_MEInit, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_MotionEstimationMB OMXCATBAR(VCM4P2_MotionEstimationMB, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_PredictReconCoefIntra OMXCATBAR(VCM4P2_PredictReconCoefIntra, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_QuantInter_I OMXCATBAR(VCM4P2_QuantInter_I, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_QuantIntra_I OMXCATBAR(VCM4P2_QuantIntra_I, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_QuantInvInter_I OMXCATBAR(VCM4P2_QuantInvInter_I, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_QuantInvIntra_I OMXCATBAR(VCM4P2_QuantInvIntra_I, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_TransRecBlockCoef_inter OMXCATBAR(VCM4P2_TransRecBlockCoef_inter, OMXVCM4P2_SUFFIX)
+#define omxVCM4P2_TransRecBlockCoef_intra OMXCATBAR(VCM4P2_TransRecBlockCoef_intra, OMXVCM4P2_SUFFIX)
+
+
+#endif /* _armOMX_h_ */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/omxtypes.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/omxtypes.h
new file mode 100644
index 0000000..8b295a6
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/api/omxtypes.h
@@ -0,0 +1,252 @@
+/**
+ * File: omxtypes.h
+ * Brief: Defines basic Data types used in OpenMAX v1.0.2 header files.
+ *
+ * Copyright © 2005-2008 The Khronos Group Inc. All Rights Reserved.
+ *
+ * These materials are protected by copyright laws and contain material
+ * proprietary to the Khronos Group, Inc. You may use these materials
+ * for implementing Khronos specifications, without altering or removing
+ * any trademark, copyright or other notice from the specification.
+ *
+ * Khronos Group makes no, and expressly disclaims any, representations
+ * or warranties, express or implied, regarding these materials, including,
+ * without limitation, any implied warranties of merchantability or fitness
+ * for a particular purpose or non-infringement of any intellectual property.
+ * Khronos Group makes no, and expressly disclaims any, warranties, express
+ * or implied, regarding the correctness, accuracy, completeness, timeliness,
+ * and reliability of these materials.
+ *
+ * Under no circumstances will the Khronos Group, or any of its Promoters,
+ * Contributors or Members or their respective partners, officers, directors,
+ * employees, agents or representatives be liable for any damages, whether
+ * direct, indirect, special or consequential damages for lost revenues,
+ * lost profits, or otherwise, arising from or in connection with these
+ * materials.
+ *
+ * Khronos and OpenMAX are trademarks of the Khronos Group Inc.
+ *
+ */
+
+#ifndef _OMXTYPES_H_
+#define _OMXTYPES_H_
+
+#include <limits.h>
+
+#define OMX_IN
+#define OMX_OUT
+#define OMX_INOUT
+
+
+typedef enum {
+
+ /* Mandatory return codes - use cases are explicitly described for each function */
+ OMX_Sts_NoErr = 0, /* No error, the function completed successfully */
+ OMX_Sts_Err = -2, /* Unknown/unspecified error */
+ OMX_Sts_InvalidBitstreamValErr = -182, /* Invalid value detected during bitstream processing */
+ OMX_Sts_MemAllocErr = -9, /* Not enough memory allocated for the operation */
+ OMX_StsACAAC_GainCtrErr = -159, /* AAC: Unsupported gain control data detected */
+ OMX_StsACAAC_PrgNumErr = -167, /* AAC: Invalid number of elements for one program */
+ OMX_StsACAAC_CoefValErr = -163, /* AAC: Invalid quantized coefficient value */
+ OMX_StsACAAC_MaxSfbErr = -162, /* AAC: Invalid maxSfb value in relation to numSwb */
+ OMX_StsACAAC_PlsDataErr = -160, /* AAC: pulse escape sequence data error */
+
+ /* Optional return codes - use cases are explicitly described for each function*/
+ OMX_Sts_BadArgErr = -5, /* Bad Arguments */
+
+ OMX_StsACAAC_TnsNumFiltErr = -157, /* AAC: Invalid number of TNS filters */
+ OMX_StsACAAC_TnsLenErr = -156, /* AAC: Invalid TNS region length */
+ OMX_StsACAAC_TnsOrderErr = -155, /* AAC: Invalid order of TNS filter */
+ OMX_StsACAAC_TnsCoefResErr = -154, /* AAC: Invalid bit-resolution for TNS filter coefficients */
+ OMX_StsACAAC_TnsCoefErr = -153, /* AAC: Invalid TNS filter coefficients */
+ OMX_StsACAAC_TnsDirectErr = -152, /* AAC: Invalid TNS filter direction */
+
+ OMX_StsICJP_JPEGMarkerErr = -183, /* JPEG marker encountered within an entropy-coded block; */
+ /* Huffman decoding operation terminated early. */
+ OMX_StsICJP_JPEGMarker = -181, /* JPEG marker encountered; Huffman decoding */
+ /* operation terminated early. */
+ OMX_StsIPPP_ContextMatchErr = -17, /* Context parameter doesn't match to the operation */
+
+ OMX_StsSP_EvenMedianMaskSizeErr = -180, /* Even size of the Median Filter mask was replaced by the odd one */
+
+ OMX_Sts_MaximumEnumeration = INT_MAX /*Placeholder, forces enum of size OMX_INT*/
+
+ } OMXResult; /** Return value or error value returned from a function. Identical to OMX_INT */
+
+
+/* OMX_U8 */
+#if UCHAR_MAX == 0xff
+typedef unsigned char OMX_U8;
+#elif USHRT_MAX == 0xff
+typedef unsigned short int OMX_U8;
+#else
+#error OMX_U8 undefined
+#endif
+
+
+/* OMX_S8 */
+#if SCHAR_MAX == 0x7f
+typedef signed char OMX_S8;
+#elif SHRT_MAX == 0x7f
+typedef signed short int OMX_S8;
+#else
+#error OMX_S8 undefined
+#endif
+
+
+/* OMX_U16 */
+#if USHRT_MAX == 0xffff
+typedef unsigned short int OMX_U16;
+#elif UINT_MAX == 0xffff
+typedef unsigned int OMX_U16;
+#else
+#error OMX_U16 undefined
+#endif
+
+
+/* OMX_S16 */
+#if SHRT_MAX == 0x7fff
+typedef signed short int OMX_S16;
+#elif INT_MAX == 0x7fff
+typedef signed int OMX_S16;
+#else
+#error OMX_S16 undefined
+#endif
+
+
+/* OMX_U32 */
+#if UINT_MAX == 0xffffffff
+typedef unsigned int OMX_U32;
+#elif LONG_MAX == 0xffffffff
+typedef unsigned long int OMX_U32;
+#else
+#error OMX_U32 undefined
+#endif
+
+
+/* OMX_S32 */
+#if INT_MAX == 0x7fffffff
+typedef signed int OMX_S32;
+#elif LONG_MAX == 0x7fffffff
+typedef long signed int OMX_S32;
+#else
+#error OMX_S32 undefined
+#endif
+
+
+/* OMX_U64 & OMX_S64 */
+#if defined( _WIN32 ) || defined ( _WIN64 )
+ typedef __int64 OMX_S64; /** Signed 64-bit integer */
+ typedef unsigned __int64 OMX_U64; /** Unsigned 64-bit integer */
+ #define OMX_MIN_S64 (0x8000000000000000i64)
+ #define OMX_MIN_U64 (0x0000000000000000i64)
+ #define OMX_MAX_S64 (0x7FFFFFFFFFFFFFFFi64)
+ #define OMX_MAX_U64 (0xFFFFFFFFFFFFFFFFi64)
+#else
+ typedef long long OMX_S64; /** Signed 64-bit integer */
+ typedef unsigned long long OMX_U64; /** Unsigned 64-bit integer */
+ #define OMX_MIN_S64 (0x8000000000000000LL)
+ #define OMX_MIN_U64 (0x0000000000000000LL)
+ #define OMX_MAX_S64 (0x7FFFFFFFFFFFFFFFLL)
+ #define OMX_MAX_U64 (0xFFFFFFFFFFFFFFFFLL)
+#endif
+
+
+/* OMX_SC8 */
+typedef struct
+{
+ OMX_S8 Re; /** Real part */
+ OMX_S8 Im; /** Imaginary part */
+
+} OMX_SC8; /** Signed 8-bit complex number */
+
+
+/* OMX_SC16 */
+typedef struct
+{
+ OMX_S16 Re; /** Real part */
+ OMX_S16 Im; /** Imaginary part */
+
+} OMX_SC16; /** Signed 16-bit complex number */
+
+
+/* OMX_SC32 */
+typedef struct
+{
+ OMX_S32 Re; /** Real part */
+ OMX_S32 Im; /** Imaginary part */
+
+} OMX_SC32; /** Signed 32-bit complex number */
+
+
+/* OMX_SC64 */
+typedef struct
+{
+ OMX_S64 Re; /** Real part */
+ OMX_S64 Im; /** Imaginary part */
+
+} OMX_SC64; /** Signed 64-bit complex number */
+
+
+/* OMX_F32 */
+typedef float OMX_F32; /** Single precision floating point,IEEE 754 */
+
+
+/* OMX_F64 */
+typedef double OMX_F64; /** Double precision floating point,IEEE 754 */
+
+
+/* OMX_INT */
+typedef int OMX_INT; /** signed integer corresponding to machine word length, has maximum signed value INT_MAX*/
+
+
+#define OMX_MIN_S8 (-128)
+#define OMX_MIN_U8 0
+#define OMX_MIN_S16 (-32768)
+#define OMX_MIN_U16 0
+#define OMX_MIN_S32 (-2147483647-1)
+#define OMX_MIN_U32 0
+
+#define OMX_MAX_S8 (127)
+#define OMX_MAX_U8 (255)
+#define OMX_MAX_S16 (32767)
+#define OMX_MAX_U16 (0xFFFF)
+#define OMX_MAX_S32 (2147483647)
+#define OMX_MAX_U32 (0xFFFFFFFF)
+
+typedef void OMXVoid;
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+/** Defines the geometric position and size of a rectangle,
+ * where x,y defines the coordinates of the top left corner
+ * of the rectangle, with dimensions width in the x-direction
+ * and height in the y-direction */
+typedef struct {
+ OMX_INT x; /** x-coordinate of top left corner of rectangle */
+ OMX_INT y; /** y-coordinate of top left corner of rectangle */
+ OMX_INT width; /** Width in the x-direction. */
+ OMX_INT height; /** Height in the y-direction. */
+}OMXRect;
+
+
+/** Defines the geometric position of a point, */
+typedef struct
+{
+ OMX_INT x; /** x-coordinate */
+ OMX_INT y; /** y-coordinate */
+
+} OMXPoint;
+
+
+/** Defines the dimensions of a rectangle, or region of interest in an image */
+typedef struct
+{
+ OMX_INT width; /** Width of the rectangle, in the x-direction */
+ OMX_INT height; /** Height of the rectangle, in the y-direction */
+
+} OMXSize;
+
+#endif /* _OMXTYPES_H_ */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/build_vc.pl b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/build_vc.pl
new file mode 100755
index 0000000..f0b43e0
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/build_vc.pl
@@ -0,0 +1,111 @@
+#!/usr/bin/perl
+#
+#
+# File Name: build_vc.pl
+# OpenMAX DL: v1.0.2
+# Revision: 9641
+# Date: Thursday, February 7, 2008
+#
+# (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+#
+#
+#
+# This file builds the OpenMAX DL vc domain library omxVC.o.
+#
+
+use File::Spec;
+use strict;
+
+my ($CC, $CC_OPTS, $AS, $AS_OPTS, $LIB, $LIB_OPTS, $LIB_TYPE);
+
+$CC = 'armcc';
+$CC_OPTS = '--no_unaligned_access --cpu ARM7TDMI -c';
+$AS = 'armasm';
+$AS_OPTS = '--no_unaligned_access --cpu ARM7TDMI';
+# $LIB = 'armlink';
+# $LIB_OPTS = '--partial -o';
+# $LIB_TYPE = '.o';
+$LIB = 'armar';
+$LIB_OPTS = '--create -r';
+$LIB_TYPE = '.a';
+
+#------------------------
+
+my (@headerlist, @filelist, $hd, $file, $ofile, $command, $objlist, $libfile, $h);
+
+# Define the list of directories containing included header files.
+@headerlist = qw(api vc/api vc/m4p2/api vc/m4p10/api);
+
+# Define the list of source files to compile.
+open(FILES, '<filelist_vc.txt') or die("Can't open source file list\n");
+@filelist = <FILES>;
+close(FILES);
+
+# Fix the file separators in the header paths
+foreach $h (@headerlist)
+{
+ $h = File::Spec->canonpath($h);
+}
+
+# Create the include path to be passed to the compiler
+$hd = '-I' . join(' -I', @headerlist);
+
+# Create the build directories "/lib/" and "/obj/" (if they are not there already)
+mkdir "obj", 0777 if (! -d "obj");
+mkdir "lib", 0777 if (! -d "lib");
+
+$objlist = '';
+
+# Compile each file
+foreach $file (@filelist)
+{
+ my $f;
+ my $base;
+ my $ext;
+ my $objfile;
+
+ chomp($file);
+ $file = File::Spec->canonpath($file);
+
+ (undef, undef, $f) = File::Spec->splitpath($file);
+ if(($base, $ext) = $f =~ /(.+)\.(\w)$/)
+ {
+ $objfile = File::Spec->catfile('obj', $base.'.o');
+
+ if($ext eq 'c')
+ {
+ $objlist .= "$objfile ";
+ $command = $CC.' '.$CC_OPTS.' '.$hd.' -o '.$objfile.' '.$file;
+ print "$command\n";
+ system($command);
+ }
+ elsif($ext eq 's')
+ {
+ $objlist .= "$objfile ";
+ $command = $AS.' '.$AS_OPTS.' '.$hd.' -o '.$objfile.' '.$file;
+ print "$command\n";
+ system($command);
+ }
+ else
+ {
+ print "Ignoring file: $f\n";
+ }
+ }
+ else
+ {
+ die "No file extension found: $f\n";
+ }
+}
+
+# Do the final link stage to create the libraries.
+$libfile = File::Spec->catfile('lib', 'omxVC'.$LIB_TYPE);
+$command = $LIB.' '.$LIB_OPTS.' '.$libfile.' '.$objlist;
+print "$command\n";
+(system($command) == 0) and print "Build successful\n";
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/filelist_vc.txt b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/filelist_vc.txt
new file mode 100644
index 0000000..66f34ac
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/filelist_vc.txt
@@ -0,0 +1,123 @@
+./api/armCOMM.h
+./api/armCOMM_Bitstream.h
+./api/armCOMM_Version.h
+./api/armOMX_ReleaseVersion.h
+./api/omxtypes.h
+./src/armCOMM.c
+./src/armCOMM_Bitstream.c
+./vc/api/armVC.h
+./vc/api/omxVC.h
+./vc/comm/src/armVCCOMM_Average.c
+./vc/comm/src/armVCCOMM_SAD.c
+./vc/comm/src/omxVCCOMM_Average_16x.c
+./vc/comm/src/omxVCCOMM_Average_8x.c
+./vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock.c
+./vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock_SAD.c
+./vc/comm/src/omxVCCOMM_Copy16x16.c
+./vc/comm/src/omxVCCOMM_Copy8x8.c
+./vc/comm/src/omxVCCOMM_ExpandFrame_I.c
+./vc/comm/src/omxVCCOMM_LimitMVToRect.c
+./vc/comm/src/omxVCCOMM_SAD_16x.c
+./vc/comm/src/omxVCCOMM_SAD_8x.c
+./vc/m4p10/api/armVCM4P10_CAVLCTables.h
+./vc/m4p10/src/armVCM4P10_CAVLCTables.c
+./vc/m4p10/src/armVCM4P10_CompareMotionCostToMV.c
+./vc/m4p10/src/armVCM4P10_DeBlockPixel.c
+./vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair.c
+./vc/m4p10/src/armVCM4P10_DequantTables.c
+./vc/m4p10/src/armVCM4P10_FwdTransformResidual4x4.c
+./vc/m4p10/src/armVCM4P10_Interpolate_Chroma.c
+./vc/m4p10/src/armVCM4P10_Interpolate_Luma.c
+./vc/m4p10/src/armVCM4P10_InterpolateHalfDiag_Luma.c
+./vc/m4p10/src/armVCM4P10_InterpolateHalfHor_Luma.c
+./vc/m4p10/src/armVCM4P10_InterpolateHalfVer_Luma.c
+./vc/m4p10/src/armVCM4P10_PredictIntraDC4x4.c
+./vc/m4p10/src/armVCM4P10_QuantTables.c
+./vc/m4p10/src/armVCM4P10_SADQuar.c
+./vc/m4p10/src/armVCM4P10_TransformResidual4x4.c
+./vc/m4p10/src/armVCM4P10_UnpackBlock2x2.c
+./vc/m4p10/src/armVCM4P10_UnpackBlock4x4.c
+./vc/m4p10/src/omxVCM4P10_Average_4x.c
+./vc/m4p10/src/omxVCM4P10_BlockMatch_Half.c
+./vc/m4p10/src/omxVCM4P10_BlockMatch_Integer.c
+./vc/m4p10/src/omxVCM4P10_BlockMatch_Quarter.c
+./vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
+./vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
+./vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
+./vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
+./vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd.c
+./vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I.c
+./vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I.c
+./vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I.c
+./vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I.c
+./vc/m4p10/src/omxVCM4P10_GetVLCInfo.c
+./vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
+./vc/m4p10/src/omxVCM4P10_InterpolateHalfHor_Luma.c
+./vc/m4p10/src/omxVCM4P10_InterpolateHalfVer_Luma.c
+./vc/m4p10/src/omxVCM4P10_InterpolateLuma.c
+./vc/m4p10/src/omxVCM4P10_InvTransformDequant_ChromaDC.c
+./vc/m4p10/src/omxVCM4P10_InvTransformDequant_LumaDC.c
+./vc/m4p10/src/omxVCM4P10_InvTransformResidualAndAdd.c
+./vc/m4p10/src/omxVCM4P10_MEGetBufSize.c
+./vc/m4p10/src/omxVCM4P10_MEInit.c
+./vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c
+./vc/m4p10/src/omxVCM4P10_PredictIntra_16x16.c
+./vc/m4p10/src/omxVCM4P10_PredictIntra_4x4.c
+./vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8.c
+./vc/m4p10/src/omxVCM4P10_SAD_4x.c
+./vc/m4p10/src/omxVCM4P10_SADQuar_16x.c
+./vc/m4p10/src/omxVCM4P10_SADQuar_4x.c
+./vc/m4p10/src/omxVCM4P10_SADQuar_8x.c
+./vc/m4p10/src/omxVCM4P10_SATD_4x4.c
+./vc/m4p10/src/omxVCM4P10_SubAndTransformQDQResidual.c
+./vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair.c
+./vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair.c
+./vc/m4p10/src/omxVCM4P10_TransformQuant_ChromaDC.c
+./vc/m4p10/src/omxVCM4P10_TransformQuant_LumaDC.c
+./vc/m4p2/api/armVCM4P2_DCT_Table.h
+./vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
+./vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
+./vc/m4p2/src/armVCM4P2_ACDCPredict.c
+./vc/m4p2/src/armVCM4P2_BlockMatch_Half.c
+./vc/m4p2/src/armVCM4P2_BlockMatch_Integer.c
+./vc/m4p2/src/armVCM4P2_CheckVLCEscapeMode.c
+./vc/m4p2/src/armVCM4P2_CompareMV.c
+./vc/m4p2/src/armVCM4P2_DCT_Table.c
+./vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_intra.c
+./vc/m4p2/src/armVCM4P2_EncodeVLCZigzag_intra.c
+./vc/m4p2/src/armVCM4P2_FillVLCBuffer.c
+./vc/m4p2/src/armVCM4P2_FillVLDBuffer.c
+./vc/m4p2/src/armVCM4P2_GetVLCBits.c
+./vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
+./vc/m4p2/src/armVCM4P2_PutVLCBits.c
+./vc/m4p2/src/armVCM4P2_SetPredDir.c
+./vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
+./vc/m4p2/src/omxVCM4P2_BlockMatch_Half_16x16.c
+./vc/m4p2/src/omxVCM4P2_BlockMatch_Half_8x8.c
+./vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_16x16.c
+./vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_8x8.c
+./vc/m4p2/src/omxVCM4P2_DCT8x8blk.c
+./vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
+./vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
+./vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP.c
+./vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter.c
+./vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC.c
+./vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC.c
+./vc/m4p2/src/omxVCM4P2_EncodeMV.c
+./vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_Inter.c
+./vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraACVLC.c
+./vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraDCVLC.c
+./vc/m4p2/src/omxVCM4P2_FindMVpred.c
+./vc/m4p2/src/omxVCM4P2_IDCT8x8blk.c
+./vc/m4p2/src/omxVCM4P2_MCReconBlock.c
+./vc/m4p2/src/omxVCM4P2_MEGetBufSize.c
+./vc/m4p2/src/omxVCM4P2_MEInit.c
+./vc/m4p2/src/omxVCM4P2_MotionEstimationMB.c
+./vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra.c
+./vc/m4p2/src/omxVCM4P2_QuantInter_I.c
+./vc/m4p2/src/omxVCM4P2_QuantIntra_I.c
+./vc/m4p2/src/omxVCM4P2_QuantInvInter_I.c
+./vc/m4p2/src/omxVCM4P2_QuantInvIntra_I.c
+./vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_inter.c
+./vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_intra.c
+./vc/src/armVC_Version.c \ No newline at end of file
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM.c
new file mode 100644
index 0000000..e572a89
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM.c
@@ -0,0 +1,936 @@
+/**
+ *
+ * File Name: armCOMM.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Defines Common APIs used across OpenMAX API's
+ */
+
+#include "omxtypes.h"
+#include "armCOMM.h"
+
+/***********************************************************************/
+ /* Miscellaneous Arithmetic operations */
+
+/**
+ * Function: armRoundFloatToS16
+ *
+ * Description:
+ * Converts a double precision value into a short int after rounding
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S16 format
+ *
+ */
+
+OMX_S16 armRoundFloatToS16 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ return (OMX_S16)(Value + .5);
+ }
+ else
+ {
+ return (OMX_S16)(Value - .5);
+ }
+}
+
+/**
+ * Function: armRoundFloatToS32
+ *
+ * Description:
+ * Converts a double precision value into a int after rounding
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S32 format
+ *
+ */
+
+OMX_S32 armRoundFloatToS32 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ return (OMX_S32)(Value + .5);
+ }
+ else
+ {
+ return (OMX_S32)(Value - .5);
+ }
+}
+/**
+ * Function: armSatRoundFloatToS16
+ *
+ * Description:
+ * Converts a double precision value into a short int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S16 format
+ *
+ */
+
+OMX_S16 armSatRoundFloatToS16 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ Value += 0.5;
+
+ if(Value > (OMX_S16)OMX_MAX_S16 )
+ {
+ return (OMX_S16)OMX_MAX_S16;
+ }
+ else
+ {
+ return (OMX_S16)Value;
+ }
+ }
+ else
+ {
+ Value -= 0.5;
+
+ if(Value < (OMX_S16)OMX_MIN_S16 )
+ {
+ return (OMX_S16)OMX_MIN_S16;
+ }
+ else
+ {
+ return (OMX_S16)Value;
+ }
+ }
+}
+
+/**
+ * Function: armSatRoundFloatToS32
+ *
+ * Description:
+ * Converts a double precision value into a int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S32 format
+ *
+ */
+
+OMX_S32 armSatRoundFloatToS32 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ Value += 0.5;
+
+ if(Value > (OMX_S32)OMX_MAX_S32 )
+ {
+ return (OMX_S32)OMX_MAX_S32;
+ }
+ else
+ {
+ return (OMX_S32)Value;
+ }
+ }
+ else
+ {
+ Value -= 0.5;
+
+ if(Value < (OMX_S32)OMX_MIN_S32 )
+ {
+ return (OMX_S32)OMX_MIN_S32;
+ }
+ else
+ {
+ return (OMX_S32)Value;
+ }
+ }
+}
+
+/**
+ * Function: armSatRoundFloatToU16
+ *
+ * Description:
+ * Converts a double precision value into a unsigned short int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_U16 format
+ *
+ */
+
+OMX_U16 armSatRoundFloatToU16 (OMX_F64 Value)
+{
+ Value += 0.5;
+
+ if(Value > (OMX_U16)OMX_MAX_U16 )
+ {
+ return (OMX_U16)OMX_MAX_U16;
+ }
+ else
+ {
+ return (OMX_U16)Value;
+ }
+}
+
+/**
+ * Function: armSatRoundFloatToU32
+ *
+ * Description:
+ * Converts a double precision value into a unsigned int after rounding and saturation
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_U32 format
+ *
+ */
+
+OMX_U32 armSatRoundFloatToU32 (OMX_F64 Value)
+{
+ Value += 0.5;
+
+ if(Value > (OMX_U32)OMX_MAX_U32 )
+ {
+ return (OMX_U32)OMX_MAX_U32;
+ }
+ else
+ {
+ return (OMX_U32)Value;
+ }
+}
+
+/**
+ * Function: armRoundFloatToS64
+ *
+ * Description:
+ * Converts a double precision value into a 64 bit int after rounding
+ *
+ * Parameters:
+ * [in] Value Float value to be converted
+ *
+ * Return Value:
+ * [out] converted value in OMX_S64 format
+ *
+ */
+
+OMX_S64 armRoundFloatToS64 (OMX_F64 Value)
+{
+ if (Value > 0)
+ {
+ return (OMX_S64)(Value + .5);
+ }
+ else
+ {
+ return (OMX_S64)(Value - .5);
+ }
+}
+
+/**
+ * Function: armSignCheck
+ *
+ * Description:
+ * Checks the sign of a variable:
+ * returns 1 if it is Positive
+ * returns 0 if it is 0
+ * returns -1 if it is Negative
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] var Variable to be checked
+ *
+ * Return Value:
+ * OMX_INT -- returns 1 if it is Positive
+ * returns 0 if it is 0
+ * returns -1 if it is Negative
+ */
+
+OMX_INT armSignCheck (
+ OMX_S16 var
+)
+
+{
+ OMX_INT Sign;
+
+ if (var < 0)
+ {
+ Sign = -1;
+ }
+ else if ( var > 0)
+ {
+ Sign = 1;
+ }
+ else
+ {
+ Sign = 0;
+ }
+
+ return Sign;
+}
+
+/**
+ * Function: armClip
+ *
+ * Description: Clips the input between MAX and MIN value
+ *
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] Min lower bound
+ * [in] Max upper bound
+ * [in] src variable to the clipped
+ *
+ * Return Value:
+ * OMX_S32 -- returns clipped value
+ */
+
+OMX_S32 armClip (
+ OMX_INT min,
+ OMX_INT max,
+ OMX_S32 src
+)
+
+{
+ if (src > max)
+ {
+ src = max;
+ }
+ else if (src < min)
+ {
+ src = min;
+ }
+
+ return src;
+}
+
+/**
+ * Function: armClip_F32
+ *
+ * Description: Clips the input between MAX and MIN value
+ *
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] Min lower bound
+ * [in] Max upper bound
+ * [in] src variable to the clipped
+ *
+ * Return Value:
+ * OMX_F32 -- returns clipped value
+ */
+
+OMX_F32 armClip_F32 (
+ OMX_F32 min,
+ OMX_F32 max,
+ OMX_F32 src
+)
+
+{
+ if (src > max)
+ {
+ src = max;
+ }
+ else if (src < min)
+ {
+ src = min;
+ }
+
+ return src;
+}
+
+/**
+ * Function: armShiftSat_F32
+ *
+ * Description: Divides a float value by 2^shift and
+ * saturates it for unsigned value range for satBits.
+ * Second parameter is like "shifting" the corresponding
+ * integer value. Takes care of rounding while clipping the final
+ * value.
+ *
+ * Parameters:
+ * [in] v Number to be operated upon
+ * [in] shift Divides the input "v" by "2^shift"
+ * [in] satBits Final range is [0, 2^satBits)
+ *
+ * Return Value:
+ * OMX_S32 -- returns "shifted" saturated value
+ */
+
+OMX_U32 armShiftSat_F32(OMX_F32 v, OMX_INT shift, OMX_INT satBits)
+{
+ OMX_U32 allOnes = (OMX_U32)(-1);
+ OMX_U32 maxV = allOnes >> (32-satBits);
+ OMX_F32 vShifted, vRounded, shiftDiv = (OMX_F32)(1 << shift);
+ OMX_U32 vInt;
+ OMX_U32 vIntSat;
+
+ if(v <= 0)
+ return 0;
+
+ vShifted = v / shiftDiv;
+ vRounded = (OMX_F32)(vShifted + 0.5);
+ vInt = (OMX_U32)vRounded;
+ vIntSat = vInt;
+ if(vIntSat > maxV)
+ vIntSat = maxV;
+ return vIntSat;
+}
+
+/**
+ * Functions: armSwapElem
+ *
+ * Description:
+ * These function swaps two elements at the specified pointer locations.
+ * The size of each element could be anything as specified by <elemSize>
+ *
+ * Return Value:
+ * OMXResult -- Error status from the function
+ */
+OMXResult armSwapElem(
+ OMX_U8 *pBuf1,
+ OMX_U8 *pBuf2,
+ OMX_INT elemSize
+ )
+{
+ OMX_INT i;
+ OMX_U8 temp;
+ armRetArgErrIf(!pBuf1 || !pBuf2, OMX_Sts_BadArgErr);
+
+ for(i = 0; i < elemSize; i++)
+ {
+ temp = *(pBuf1 + i);
+ *(pBuf1 + i) = *(pBuf2 + i);
+ *(pBuf2 + i) = temp;
+ }
+ return OMX_Sts_NoErr;
+}
+
+/**
+ * Function: armMedianOf3
+ *
+ * Description: Finds the median of three numbers
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] fEntry First entry
+ * [in] sEntry second entry
+ * [in] tEntry Third entry
+ *
+ * Return Value:
+ * OMX_S32 -- returns the median value
+ */
+
+OMX_S32 armMedianOf3 (
+ OMX_S32 fEntry,
+ OMX_S32 sEntry,
+ OMX_S32 tEntry
+)
+{
+ OMX_S32 a, b, c;
+
+ a = armMin (fEntry, sEntry);
+ b = armMax (fEntry, sEntry);
+ c = armMin (b, tEntry);
+ return (armMax (a, c));
+}
+
+/**
+ * Function: armLogSize
+ *
+ * Description: Finds the size of a positive value and returns the same
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] value Positive value
+ *
+ * Return Value:
+ * OMX_U8 -- Returns the minimum number of bits required to represent the positive value.
+ This is the smallest k>=0 such that that value is less than (1<<k).
+ */
+
+OMX_U8 armLogSize (
+ OMX_U16 value
+)
+{
+ OMX_U8 i;
+ for ( i = 0; value > 0; value = value >> 1)
+ {
+ i++;
+ }
+ return i;
+}
+
+/***********************************************************************/
+ /* Saturating Arithmetic operations */
+
+/**
+ * Function :armSatAdd_S32()
+ *
+ * Description :
+ * Returns the result of saturated addition of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ *
+ **/
+
+OMX_S32 armSatAdd_S32(OMX_S32 Value1,OMX_S32 Value2)
+{
+ OMX_S32 Result;
+
+ Result = Value1 + Value2;
+
+ if( (Value1^Value2) >= 0)
+ {
+ /*Same sign*/
+ if( (Result^Value1) >= 0)
+ {
+ /*Result has not saturated*/
+ return Result;
+ }
+ else
+ {
+ if(Value1 >= 0)
+ {
+ /*Result has saturated in positive side*/
+ return OMX_MAX_S32;
+ }
+ else
+ {
+ /*Result has saturated in negative side*/
+ return OMX_MIN_S32;
+ }
+
+ }
+
+ }
+ else
+ {
+ return Result;
+ }
+
+}
+
+/**
+ * Function :armSatAdd_S64()
+ *
+ * Description :
+ * Returns the result of saturated addition of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ *
+ **/
+
+OMX_S64 armSatAdd_S64(OMX_S64 Value1,OMX_S64 Value2)
+{
+ OMX_S64 Result;
+
+ Result = Value1 + Value2;
+
+ if( (Value1^Value2) >= 0)
+ {
+ /*Same sign*/
+ if( (Result^Value1) >= 0)
+ {
+ /*Result has not saturated*/
+ return Result;
+ }
+ else
+ {
+ if(Value1 >= 0)
+ {
+ /*Result has saturated in positive side*/
+ Result = OMX_MAX_S64;
+ return Result;
+ }
+ else
+ {
+ /*Result has saturated in negative side*/
+ return OMX_MIN_S64;
+ }
+
+ }
+
+ }
+ else
+ {
+ return Result;
+ }
+
+}
+
+/** Function :armSatSub_S32()
+ *
+ * Description :
+ * Returns the result of saturated substraction of the two inputs Value1, Value2
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatSub_S32(OMX_S32 Value1,OMX_S32 Value2)
+{
+ OMX_S32 Result;
+
+ Result = Value1 - Value2;
+
+ if( (Value1^Value2) < 0)
+ {
+ /*Opposite sign*/
+ if( (Result^Value1) >= 0)
+ {
+ /*Result has not saturated*/
+ return Result;
+ }
+ else
+ {
+ if(Value1 >= 0)
+ {
+ /*Result has saturated in positive side*/
+ return OMX_MAX_S32;
+ }
+ else
+ {
+ /*Result has saturated in negative side*/
+ return OMX_MIN_S32;
+ }
+
+ }
+
+ }
+ else
+ {
+ return Result;
+ }
+
+}
+
+/**
+ * Function :armSatMac_S32()
+ *
+ * Description :
+ * Returns the result of Multiplication of Value1 and Value2 and subesquent saturated
+ * accumulation with Mac
+ *
+ * Parametrs:
+ * [in] Value1 First Operand
+ * [in] Value2 Second Operand
+ * [in] Mac Accumulator
+ *
+ * Return:
+ * [out] Result of operation
+ **/
+
+OMX_S32 armSatMac_S32(OMX_S32 Mac,OMX_S16 Value1,OMX_S16 Value2)
+{
+ OMX_S32 Result;
+
+ Result = (OMX_S32)(Value1*Value2);
+ Result = armSatAdd_S32( Mac , Result );
+
+ return Result;
+}
+
+/**
+ * Function :armSatMac_S16S32_S32
+ *
+ * Description :
+ * Returns the result of saturated MAC operation of the three inputs delayElem, filTap , mac
+ *
+ * mac = mac + Saturate_in_32Bits(delayElem * filTap)
+ *
+ * Parametrs:
+ * [in] delayElem First 32 bit Operand
+ * [in] filTap Second 16 bit Operand
+ * [in] mac Result of MAC operation
+ *
+ * Return:
+ * [out] mac Result of operation
+ *
+ **/
+
+OMX_S32 armSatMac_S16S32_S32(OMX_S32 mac, OMX_S32 delayElem, OMX_S16 filTap )
+{
+
+ OMX_S32 result;
+
+ result = armSatMulS16S32_S32(filTap,delayElem);
+
+ if ( result > OMX_MAX_S16 )
+ {
+ result = OMX_MAX_S32;
+ }
+ else if( result < OMX_MIN_S16 )
+ {
+ result = OMX_MIN_S32;
+ }
+ else
+ {
+ result = delayElem * filTap;
+ }
+
+ mac = armSatAdd_S32(mac,result);
+
+ return mac;
+}
+
+
+/**
+ * Function :armSatRoundRightShift_S32_S16
+ *
+ * Description :
+ * Returns the result of rounded right shift operation of input by the scalefactor
+ *
+ * output = Saturate_in_16Bits( ( Right/LeftShift( (Round(input) , shift ) )
+ *
+ * Parametrs:
+ * [in] input The input to be operated on
+ * [in] shift The shift number
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+
+OMX_S16 armSatRoundRightShift_S32_S16(OMX_S32 input, OMX_INT shift)
+{
+ input = armSatRoundLeftShift_S32(input,-shift);
+
+ if ( input > OMX_MAX_S16 )
+ {
+ return (OMX_S16)OMX_MAX_S16;
+ }
+ else if (input < OMX_MIN_S16)
+ {
+ return (OMX_S16)OMX_MIN_S16;
+ }
+ else
+ {
+ return (OMX_S16)input;
+ }
+
+}
+
+/**
+ * Function :armSatRoundLeftShift_S32()
+ *
+ * Description :
+ * Returns the result of saturating left-shift operation on input
+ * Or rounded Right shift if the input Shift is negative.
+ *
+ * Parametrs:
+ * [in] Value Operand
+ * [in] Shift Operand for shift operation
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatRoundLeftShift_S32(OMX_S32 Value, OMX_INT Shift)
+{
+ OMX_INT i;
+
+ if (Shift < 0)
+ {
+ Shift = -Shift;
+ Value = armSatAdd_S32(Value, (1 << (Shift - 1)));
+ Value = Value >> Shift;
+ }
+ else
+ {
+ for (i = 0; i < Shift; i++)
+ {
+ Value = armSatAdd_S32(Value, Value);
+ }
+ }
+ return Value;
+}
+
+/**
+ * Function :armSatRoundLeftShift_S64()
+ *
+ * Description :
+ * Returns the result of saturating left-shift operation on input
+ * Or rounded Right shift if the input Shift is negative.
+ *
+ * Parametrs:
+ * [in] Value Operand
+ * [in] shift Operand for shift operation
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S64 armSatRoundLeftShift_S64(OMX_S64 Value, OMX_INT Shift)
+{
+ OMX_INT i;
+
+ if (Shift < 0)
+ {
+ Shift = -Shift;
+ Value = armSatAdd_S64(Value, ((OMX_S64)1 << (Shift - 1)));
+ Value = Value >> Shift;
+ }
+ else
+ {
+ for (i = 0; i < Shift; i++)
+ {
+ Value = armSatAdd_S64(Value, Value);
+ }
+ }
+ return Value;
+}
+
+/**
+ * Function :armSatMulS16S32_S32()
+ *
+ * Description :
+ * Returns the result of a S16 data type multiplied with an S32 data type
+ * in a S32 container
+ *
+ * Parametrs:
+ * [in] input1 Operand 1
+ * [in] input2 Operand 2
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+
+OMX_S32 armSatMulS16S32_S32(OMX_S16 input1,OMX_S32 input2)
+{
+ OMX_S16 hi2,lo1;
+ OMX_U16 lo2;
+
+ OMX_S32 temp1,temp2;
+ OMX_S32 result;
+
+ lo1 = input1;
+
+ hi2 = ( input2 >> 16 );
+ lo2 = ( (OMX_U32)( input2 << 16 ) >> 16 );
+
+ temp1 = hi2 * lo1;
+ temp2 = ( lo2* lo1 ) >> 16;
+
+ result = armSatAdd_S32(temp1,temp2);
+
+ return result;
+}
+
+/**
+ * Function :armSatMulS32S32_S32()
+ *
+ * Description :
+ * Returns the result of a S32 data type multiplied with an S32 data type
+ * in a S32 container
+ *
+ * Parametrs:
+ * [in] input1 Operand 1
+ * [in] input2 Operand 2
+ *
+ * Return:
+ * [out] Result of operation
+ *
+ **/
+
+OMX_S32 armSatMulS32S32_S32(OMX_S32 input1,OMX_S32 input2)
+{
+ OMX_S16 hi1,hi2;
+ OMX_U16 lo1,lo2;
+
+ OMX_S32 temp1,temp2,temp3;
+ OMX_S32 result;
+
+ hi1 = ( input1 >> 16 );
+ lo1 = ( (OMX_U32)( input1 << 16 ) >> 16 );
+
+ hi2 = ( input2 >> 16 );
+ lo2 = ( (OMX_U32)( input2 << 16 ) >> 16 );
+
+ temp1 = hi1 * hi2;
+ temp2 = ( hi1* lo2 ) >> 16;
+ temp3 = ( hi2* lo1 ) >> 16;
+
+ result = armSatAdd_S32(temp1,temp2);
+ result = armSatAdd_S32(result,temp3);
+
+ return result;
+}
+
+/**
+ * Function :armIntDivAwayFromZero()
+ *
+ * Description : Integer division with rounding to the nearest integer.
+ * Half-integer values are rounded away from zero
+ * unless otherwise specified. For example 3//2 is rounded
+ * to 2, and -3//2 is rounded to -2.
+ *
+ * Parametrs:
+ * [in] Num Operand 1
+ * [in] Deno Operand 2
+ *
+ * Return:
+ * [out] Result of operation input1//input2
+ *
+ **/
+
+OMX_S32 armIntDivAwayFromZero (OMX_S32 Num, OMX_S32 Deno)
+{
+ OMX_F64 result;
+
+ result = ((OMX_F64)Num)/((OMX_F64)Deno);
+
+ if (result >= 0)
+ {
+ result += 0.5;
+ }
+ else
+ {
+ result -= 0.5;
+ }
+
+ return (OMX_S32)(result);
+}
+
+
+/*End of File*/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM_Bitstream.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM_Bitstream.c
new file mode 100644
index 0000000..9ef9319
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/src/armCOMM_Bitstream.c
@@ -0,0 +1,329 @@
+/**
+ *
+ * File Name: armCOMM_Bitstream.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Defines bitstream encode and decode functions common to all codecs
+ */
+
+#include "omxtypes.h"
+#include "armCOMM.h"
+#include "armCOMM_Bitstream.h"
+
+/***************************************
+ * Fixed bit length Decode
+ ***************************************/
+
+/**
+ * Function: armLookAheadBits()
+ *
+ * Description:
+ * Get the next N bits from the bitstream without advancing the bitstream pointer
+ *
+ * Parameters:
+ * [in] **ppBitStream
+ * [in] *pOffset
+ * [in] N=1...32
+ *
+ * Returns Value
+ */
+
+OMX_U32 armLookAheadBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N)
+{
+ const OMX_U8 *pBitStream = *ppBitStream;
+ OMX_INT Offset = *pOffset;
+ OMX_U32 Value;
+
+ armAssert(Offset>=0 && Offset<=7);
+ armAssert(N>=1 && N<=32);
+
+ /* Read next 32 bits from stream */
+ Value = (pBitStream[0] << 24 ) | ( pBitStream[1] << 16) | (pBitStream[2] << 8 ) | (pBitStream[3]) ;
+ Value = (Value << Offset ) | (pBitStream[4] >> (8-Offset));
+
+ /* Return N bits */
+ return Value >> (32-N);
+}
+
+
+/**
+ * Function: armGetBits()
+ *
+ * Description:
+ * Read N bits from the bitstream
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ * [in] N=1..32
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ * Returns Value
+ */
+
+
+OMX_U32 armGetBits(const OMX_U8 **ppBitStream, OMX_INT *pOffset, OMX_INT N)
+{
+ const OMX_U8 *pBitStream = *ppBitStream;
+ OMX_INT Offset = *pOffset;
+ OMX_U32 Value;
+
+ if(N == 0)
+ {
+ return 0;
+ }
+
+ armAssert(Offset>=0 && Offset<=7);
+ armAssert(N>=1 && N<=32);
+
+ /* Read next 32 bits from stream */
+ Value = (pBitStream[0] << 24 ) | ( pBitStream[1] << 16) | (pBitStream[2] << 8 ) | (pBitStream[3]) ;
+ Value = (Value << Offset ) | (pBitStream[4] >> (8-Offset));
+
+ /* Advance bitstream pointer by N bits */
+ Offset += N;
+ *ppBitStream = pBitStream + (Offset>>3);
+ *pOffset = Offset & 7;
+
+ /* Return N bits */
+ return Value >> (32-N);
+}
+
+/**
+ * Function: armByteAlign()
+ *
+ * Description:
+ * Align the pointer *ppBitStream to the next byte boundary
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ *
+ **/
+
+OMXVoid armByteAlign(const OMX_U8 **ppBitStream,OMX_INT *pOffset)
+{
+ if(*pOffset > 0)
+ {
+ *ppBitStream += 1;
+ *pOffset = 0;
+ }
+}
+
+/**
+ * Function: armSkipBits()
+ *
+ * Description:
+ * Skip N bits from the value at *ppBitStream
+ *
+ * Parameters:
+ * [in] *ppBitStream
+ * [in] *pOffset
+ * [in] N
+ *
+ * [out] *ppBitStream
+ * [out] *pOffset
+ *
+ **/
+
+
+OMXVoid armSkipBits(const OMX_U8 **ppBitStream,OMX_INT *pOffset,OMX_INT N)
+{
+ OMX_INT Offset = *pOffset;
+ const OMX_U8 *pBitStream = *ppBitStream;
+
+ /* Advance bitstream pointer by N bits */
+ Offset += N;
+ *ppBitStream = pBitStream + (Offset>>3);
+ *pOffset = Offset & 7;
+}
+
+/***************************************
+ * Variable bit length Decode
+ ***************************************/
+
+/**
+ * Function: armUnPackVLC32()
+ *
+ * Description:
+ * Variable length decode of variable length symbol (max size 32 bits) read from
+ * the bit stream pointed by *ppBitStream at *pOffset by using the table
+ * pointed by pCodeBook
+ *
+ * Parameters:
+ * [in] *pBitStream
+ * [in] *pOffset
+ * [in] pCodeBook
+ *
+ * [out] *pBitStream
+ * [out] *pOffset
+ *
+ * Returns : Code Book Index if successfull.
+ * : ARM_NO_CODEBOOK_INDEX = -1 if search fails.
+ **/
+#ifndef C_OPTIMIZED_IMPLEMENTATION
+
+OMX_U16 armUnPackVLC32(
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pOffset,
+ const ARM_VLC32 *pCodeBook
+)
+{
+ const OMX_U8 *pBitStream = *ppBitStream;
+ OMX_INT Offset = *pOffset;
+ OMX_U32 Value;
+ OMX_INT Index;
+
+ armAssert(Offset>=0 && Offset<=7);
+
+ /* Read next 32 bits from stream */
+ Value = (pBitStream[0] << 24 ) | ( pBitStream[1] << 16) | (pBitStream[2] << 8 ) | (pBitStream[3]) ;
+ Value = (Value << Offset ) | (pBitStream[4] >> (8-Offset));
+
+ /* Search through the codebook */
+ for (Index=0; pCodeBook->codeLen != 0; Index++)
+ {
+ if (pCodeBook->codeWord == (Value >> (32 - pCodeBook->codeLen)))
+ {
+ Offset = Offset + pCodeBook->codeLen;
+ *ppBitStream = pBitStream + (Offset >> 3) ;
+ *pOffset = Offset & 7;
+
+ return Index;
+ }
+ pCodeBook++;
+ }
+
+ /* No code match found */
+ return ARM_NO_CODEBOOK_INDEX;
+}
+
+#endif
+
+/***************************************
+ * Fixed bit length Encode
+ ***************************************/
+
+/**
+ * Function: armPackBits
+ *
+ * Description:
+ * Pack a VLC code word into the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte
+ * in the bit stream.
+ * [in] pOffset pointer to the bit position in the byte
+ * pointed by *ppBitStream. Valid within 0
+ * to 7.
+ * [in] codeWord Code word that need to be inserted in to the
+ * bitstream
+ * [in] codeLength Length of the code word valid range 1...32
+ *
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMX_RESULT result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armPackBits (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pOffset,
+ OMX_U32 codeWord,
+ OMX_INT codeLength
+)
+{
+ OMX_U8 *pBitStream = *ppBitStream;
+ OMX_INT Offset = *pOffset;
+ OMX_U32 Value;
+
+ /* checking argument validity */
+ armRetArgErrIf(Offset < 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf(Offset > 7, OMX_Sts_BadArgErr);
+ armRetArgErrIf(codeLength < 1, OMX_Sts_BadArgErr);
+ armRetArgErrIf(codeLength > 32, OMX_Sts_BadArgErr);
+
+ /* Prepare the first byte */
+ codeWord = codeWord << (32-codeLength);
+ Value = (pBitStream[0] >> (8-Offset)) << (8-Offset);
+ Value = Value | (codeWord >> (24+Offset));
+
+ /* Write out whole bytes */
+ while (8-Offset <= codeLength)
+ {
+ *pBitStream++ = (OMX_U8)Value;
+ codeWord = codeWord << (8-Offset);
+ codeLength = codeLength - (8-Offset);
+ Offset = 0;
+ Value = codeWord >> 24;
+ }
+
+ /* Write out final partial byte */
+ *pBitStream = (OMX_U8)Value;
+ *ppBitStream = pBitStream;
+ *pOffset = Offset + codeLength;
+
+ return OMX_Sts_NoErr;
+}
+
+/***************************************
+ * Variable bit length Encode
+ ***************************************/
+
+/**
+ * Function: armPackVLC32
+ *
+ * Description:
+ * Pack a VLC code word into the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte
+ * in the bit stream.
+ * [in] pBitOffset pointer to the bit position in the byte
+ * pointed by *ppBitStream. Valid within 0
+ * to 7.
+ * [in] code VLC code word that need to be inserted in to the
+ * bitstream
+ *
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMX_RESULT result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armPackVLC32 (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ ARM_VLC32 code
+)
+{
+ return (armPackBits(ppBitStream, pBitOffset, code.codeWord, code.codeLen));
+}
+
+/*End of File*/
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/api/armVC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/api/armVC.h
new file mode 100644
index 0000000..7fa7716
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/api/armVC.h
@@ -0,0 +1,1153 @@
+/**
+ *
+ * File Name: armVC.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armVideo.h
+ * Brief: Declares API's/Basic Data types used across the OpenMAX Video domain
+ *
+ */
+
+
+#ifndef _armVideo_H_
+#define _armVideo_H_
+
+#include "omxVC.h"
+#include "armCOMM_Bitstream.h"
+
+/**
+ * ARM specific state structure to hold Motion Estimation information.
+ */
+
+struct m4p2_MESpec
+{
+ OMXVCM4P2MEParams MEParams;
+ OMXVCM4P2MEMode MEMode;
+};
+
+struct m4p10_MESpec
+{
+ OMXVCM4P10MEParams MEParams;
+ OMXVCM4P10MEMode MEMode;
+};
+
+typedef struct m4p2_MESpec ARMVCM4P2_MESpec;
+typedef struct m4p10_MESpec ARMVCM4P10_MESpec;
+
+/**
+ * Function: armVCM4P2_CompareMV
+ *
+ * Description:
+ * Performs comparision of motion vectors and SAD's to decide the
+ * best MV and SAD
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] mvX x coordinate of the candidate motion vector
+ * [in] mvY y coordinate of the candidate motion vector
+ * [in] candSAD Candidate SAD
+ * [in] bestMVX x coordinate of the best motion vector
+ * [in] bestMVY y coordinate of the best motion vector
+ * [in] bestSAD best SAD
+ *
+ * Return Value:
+ * OMX_INT -- 1 to indicate that the current sad is the best
+ * 0 to indicate that it is NOT the best SAD
+ */
+
+OMX_INT armVCM4P2_CompareMV (
+ OMX_S16 mvX,
+ OMX_S16 mvY,
+ OMX_INT candSAD,
+ OMX_S16 bestMVX,
+ OMX_S16 bestMVY,
+ OMX_INT bestSAD);
+
+/**
+ * Function: armVCM4P2_ACDCPredict
+ *
+ * Description:
+ * Performs adaptive DC/AC coefficient prediction for an intra block. Prior
+ * to the function call, prediction direction (predDir) should be selected
+ * as specified in subclause 7.4.3.1 of ISO/IEC 14496-2.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcDst pointer to the coefficient buffer which contains
+ * the quantized coefficient residuals (PQF) of the
+ * current block
+ * [in] pPredBufRow pointer to the coefficient row buffer
+ * [in] pPredBufCol pointer to the coefficient column buffer
+ * [in] curQP quantization parameter of the current block. curQP
+ * may equal to predQP especially when the current
+ * block and the predictor block are in the same
+ * macroblock.
+ * [in] predQP quantization parameter of the predictor block
+ * [in] predDir indicates the prediction direction which takes one
+ * of the following values:
+ * OMX_VIDEO_HORIZONTAL predict horizontally
+ * OMX_VIDEO_VERTICAL predict vertically
+ * [in] ACPredFlag a flag indicating if AC prediction should be
+ * performed. It is equal to ac_pred_flag in the bit
+ * stream syntax of MPEG-4
+ * [in] videoComp video component type (luminance, chrominance or
+ * alpha) of the current block
+ * [in] flag This flag defines the if one wants to use this functions to
+ * calculate PQF (set 1, prediction) or QF (set 0, reconstruction)
+ * [out] pPreACPredict pointer to the predicted coefficients buffer.
+ * Filled ONLY if it is not NULL
+ * [out] pSrcDst pointer to the coefficient buffer which contains
+ * the quantized coefficients (QF) of the current
+ * block
+ * [out] pPredBufRow pointer to the updated coefficient row buffer
+ * [out] pPredBufCol pointer to the updated coefficient column buffer
+ * [out] pSumErr pointer to the updated sum of the difference
+ * between predicted and unpredicted coefficients
+ * If this is NULL, do not update
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_ACDCPredict(
+ OMX_S16 * pSrcDst,
+ OMX_S16 * pPreACPredict,
+ OMX_S16 * pPredBufRow,
+ OMX_S16 * pPredBufCol,
+ OMX_INT curQP,
+ OMX_INT predQP,
+ OMX_INT predDir,
+ OMX_INT ACPredFlag,
+ OMXVCM4P2VideoComponent videoComp,
+ OMX_U8 flag,
+ OMX_INT *pSumErr
+);
+
+/**
+ * Function: armVCM4P2_SetPredDir
+ *
+ * Description:
+ * Performs detecting the prediction direction
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] blockIndex block index indicating the component type and
+ * position as defined in subclause 6.1.3.8, of ISO/IEC
+ * 14496-2. Furthermore, indexes 6 to 9 indicate the
+ * alpha blocks spatially corresponding to luminance
+ * blocks 0 to 3 in the same macroblock.
+ * [in] pCoefBufRow pointer to the coefficient row buffer
+ * [in] pQpBuf pointer to the quantization parameter buffer
+ * [out] predQP quantization parameter of the predictor block
+ * [out] predDir indicates the prediction direction which takes one
+ * of the following values:
+ * OMX_VIDEO_HORIZONTAL predict horizontally
+ * OMX_VIDEO_VERTICAL predict vertically
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_SetPredDir(
+ OMX_INT blockIndex,
+ OMX_S16 *pCoefBufRow,
+ OMX_S16 *pCoefBufCol,
+ OMX_INT *predDir,
+ OMX_INT *predQP,
+ const OMX_U8 *pQpBuf
+);
+
+/**
+ * Function: armVCM4P2_EncodeVLCZigzag_Intra
+ *
+ * Description:
+ * Performs zigzag scanning and VLC encoding for one intra block.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7.
+ * [in] pQDctBlkCoef pointer to the quantized DCT coefficient
+ * [in] predDir AC prediction direction, which is used to decide
+ * the zigzag scan pattern. This takes one of the
+ * following values:
+ * OMX_VIDEO_NONE AC prediction not used.
+ * Performs classical zigzag
+ * scan.
+ * OMX_VIDEO_HORIZONTAL Horizontal prediction.
+ * Performs alternate-vertical
+ * zigzag scan.
+ * OMX_VIDEO_VERTICAL Vertical prediction.
+ * Performs alternate-horizontal
+ * zigzag scan.
+ * [in] pattern block pattern which is used to decide whether
+ * this block is encoded
+ * [in] start start indicates whether the encoding begins with 0th element
+ * or 1st.
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_EncodeVLCZigzag_Intra(
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 predDir,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start
+);
+
+/**
+ * Function: armVCM4P2_DecodeVLCZigzag_Intra
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan for one intra coded block.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bitstream buffer
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * to by *ppBitStream. *pBitOffset is valid within
+ * [0-7].
+ * [in] predDir AC prediction direction which is used to decide
+ * the zigzag scan pattern. It takes one of the
+ * following values:
+ * OMX_VIDEO_NONE AC prediction not used;
+ * perform classical zigzag scan;
+ * OMX_VIDEO_HORIZONTAL Horizontal prediction;
+ * perform alternate-vertical
+ * zigzag scan;
+ * OMX_VIDEO_VERTICAL Vertical prediction;
+ * thus perform
+ * alternate-horizontal
+ * zigzag scan.
+ * [in] videoComp video component type (luminance, chrominance or
+ * alpha) of the current block
+ * [in] shortVideoHeader binary flag indicating presence of short_video_header; escape modes 0-3 are used if shortVideoHeader==0,
+ * and escape mode 4 is used when shortVideoHeader==1.
+ * [in] start start indicates whether the encoding begins with 0th element
+ * or 1st.
+ * [out] ppBitStream *ppBitStream is updated after the block is
+ * decoded, so that it points to the current byte
+ * in the bit stream buffer
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream
+ * [out] pDst pointer to the coefficient buffer of current
+ * block. Should be 32-bit aligned
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_DecodeVLCZigzag_Intra(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_U8 predDir,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start
+);
+
+/**
+ * Function: armVCM4P2_FillVLDBuffer
+ *
+ * Description:
+ * Performs filling of the coefficient buffer according to the run, level
+ * and sign, also updates the index
+ *
+ * Parameters:
+ * [in] storeRun Stored Run value (count of zeros)
+ * [in] storeLevel Stored Level value (non-zero value)
+ * [in] sign Flag indicating the sign of level
+ * [in] last status of the last flag
+ * [in] pIndex pointer to coefficient index in 8x8 matrix
+ * [out] pIndex pointer to updated coefficient index in 8x8
+ * matrix
+ * [in] pZigzagTable pointer to the zigzag tables
+ * [out] pDst pointer to the coefficient buffer of current
+ * block. Should be 32-bit aligned
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_FillVLDBuffer(
+ OMX_U32 storeRun,
+ OMX_S16 * pDst,
+ OMX_S16 storeLevel,
+ OMX_U8 sign,
+ OMX_U8 last,
+ OMX_U8 * index,
+ const OMX_U8 * pZigzagTable
+);
+
+/**
+ * Function: armVCM4P2_GetVLCBits
+ *
+ * Description:
+ * Performs escape mode decision based on the run, run+, level, level+ and
+ * last combinations.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7
+ * [in] shortVideoHeader binary flag indicating presence of short_video_header; escape modes 0-3 are used if shortVideoHeader==0,
+ * and escape mode 4 is used when shortVideoHeader==1.
+ * [in] start start indicates whether the encoding begins with
+ * 0th element or 1st.
+ * [in/out] pLast pointer to last status flag
+ * [in] runBeginSingleLevelEntriesL0 The run value from which level
+ * will be equal to 1: last == 0
+ * [in] IndexBeginSingleLevelEntriesL0 Array index in the VLC table
+ * pointing to the
+ * runBeginSingleLevelEntriesL0
+ * [in] runBeginSingleLevelEntriesL1 The run value from which level
+ * will be equal to 1: last == 1
+ * [in] IndexBeginSingleLevelEntriesL1 Array index in the VLC table
+ * pointing to the
+ * runBeginSingleLevelEntriesL0
+ * [in] pRunIndexTableL0 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pVlcTableL0 VLC table for last == 0
+ * [in] pRunIndexTableL1 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pVlcTableL1 VLC table for last == 1
+ * [in] pLMAXTableL0 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pLMAXTableL1 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pRMAXTableL0 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pRMAXTableL1 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [out]pDst pointer to the coefficient buffer of current
+ * block. Should be 32-bit aligned
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_GetVLCBits (
+ const OMX_U8 **ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start,
+ OMX_U8 * pLast,
+ OMX_U8 runBeginSingleLevelEntriesL0,
+ OMX_U8 maxIndexForMultipleEntriesL0,
+ OMX_U8 maxRunForMultipleEntriesL1,
+ OMX_U8 maxIndexForMultipleEntriesL1,
+ const OMX_U8 * pRunIndexTableL0,
+ const ARM_VLC32 *pVlcTableL0,
+ const OMX_U8 * pRunIndexTableL1,
+ const ARM_VLC32 *pVlcTableL1,
+ const OMX_U8 * pLMAXTableL0,
+ const OMX_U8 * pLMAXTableL1,
+ const OMX_U8 * pRMAXTableL0,
+ const OMX_U8 * pRMAXTableL1,
+ const OMX_U8 * pZigzagTable
+);
+
+/**
+ * Function: armVCM4P2_PutVLCBits
+ *
+ * Description:
+ * Checks the type of Escape Mode and put encoded bits for
+ * quantized DCT coefficients.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7
+ * [in] shortVideoHeader binary flag indicating presence of short_video_header; escape modes 0-3 are used if shortVideoHeader==0,
+ * and escape mode 4 is used when shortVideoHeader==1.
+ * [in] start start indicates whether the encoding begins with
+ * 0th element or 1st.
+ * [in] maxStoreRunL0 Max store possible (considering last and inter/intra)
+ * for last = 0
+ * [in] maxStoreRunL1 Max store possible (considering last and inter/intra)
+ * for last = 1
+ * [in] maxRunForMultipleEntriesL0
+ * The run value after which level
+ * will be equal to 1:
+ * (considering last and inter/intra status) for last = 0
+ * [in] maxRunForMultipleEntriesL1
+ * The run value after which level
+ * will be equal to 1:
+ * (considering last and inter/intra status) for last = 1
+ * [in] pRunIndexTableL0 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pVlcTableL0 VLC table for last == 0
+ * [in] pRunIndexTableL1 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pVlcTableL1 VLC table for last == 1
+ * [in] pLMAXTableL0 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pLMAXTableL1 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pRMAXTableL0 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pRMAXTableL1 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [out] pQDctBlkCoef pointer to the quantized DCT coefficient
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+
+OMXResult armVCM4P2_PutVLCBits (
+ OMX_U8 **ppBitStream,
+ OMX_INT * pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start,
+ OMX_U8 maxStoreRunL0,
+ OMX_U8 maxStoreRunL1,
+ OMX_U8 maxRunForMultipleEntriesL0,
+ OMX_U8 maxRunForMultipleEntriesL1,
+ const OMX_U8 * pRunIndexTableL0,
+ const ARM_VLC32 *pVlcTableL0,
+ const OMX_U8 * pRunIndexTableL1,
+ const ARM_VLC32 *pVlcTableL1,
+ const OMX_U8 * pLMAXTableL0,
+ const OMX_U8 * pLMAXTableL1,
+ const OMX_U8 * pRMAXTableL0,
+ const OMX_U8 * pRMAXTableL1,
+ const OMX_U8 * pZigzagTable
+);
+/**
+ * Function: armVCM4P2_FillVLCBuffer
+ *
+ * Description:
+ * Performs calculating the VLC bits depending on the escape type and insert
+ * the same in the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7
+ * [in] run Run value (count of zeros) to be encoded
+ * [in] level Level value (non-zero value) to be encoded
+ * [in] runPlus Calculated as runPlus = run - (RMAX + 1)
+ * [in] levelPlus Calculated as
+ * levelPlus = sign(level)*[abs(level) - LMAX]
+ * [in] fMode Flag indicating the escape modes
+ * [in] last status of the last flag
+ * [in] maxRunForMultipleEntries
+ * The run value after which level will be equal to 1:
+ * (considering last and inter/intra status)
+ * [in] pRunIndexTable Run Index table defined in
+ * armVCM4P2_Huff_tables_VLC.h
+ * [in] pVlcTable VLC table defined in armVCM4P2_Huff_tables_VLC.h
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_FillVLCBuffer (
+ OMX_U8 **ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_U32 run,
+ OMX_S16 level,
+ OMX_U32 runPlus,
+ OMX_S16 levelPlus,
+ OMX_U8 fMode,
+ OMX_U8 last,
+ OMX_U8 maxRunForMultipleEntries,
+ const OMX_U8 *pRunIndexTable,
+ const ARM_VLC32 *pVlcTable
+);
+
+/**
+ * Function: armVCM4P2_CheckVLCEscapeMode
+ *
+ * Description:
+ * Performs escape mode decision based on the run, run+, level, level+ and
+ * last combinations.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] run Run value (count of zeros) to be encoded
+ * [in] level Level value (non-zero value) to be encoded
+ * [in] runPlus Calculated as runPlus = run - (RMAX + 1)
+ * [in] levelPlus Calculated as
+ * levelPlus = sign(level)*[abs(level) - LMAX]
+ * [in] maxStoreRun Max store possible (considering last and inter/intra)
+ * [in] maxRunForMultipleEntries
+ * The run value after which level
+ * will be equal to 1:
+ * (considering last and inter/intra status)
+ * [in] shortVideoHeader binary flag indicating presence of short_video_header; escape modes 0-3 are used if shortVideoHeader==0,
+ * and escape mode 4 is used when shortVideoHeader==1.
+ * [in] pRunIndexTable Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c
+ * (considering last and inter/intra status)
+ *
+ *
+ * Return Value:
+ * Returns an Escape mode which can take values from 0 to 3
+ * 0 --> no escape mode, 1 --> escape type 1,
+ * 1 --> escape type 2, 3 --> escape type 3, check section 7.4.1.3
+ * in the MPEG ISO standard.
+ *
+ */
+
+OMX_U8 armVCM4P2_CheckVLCEscapeMode(
+ OMX_U32 run,
+ OMX_U32 runPlus,
+ OMX_S16 level,
+ OMX_S16 levelPlus,
+ OMX_U8 maxStoreRun,
+ OMX_U8 maxRunForMultipleEntries,
+ OMX_INT shortVideoHeader,
+ const OMX_U8 *pRunIndexTable
+);
+
+
+/**
+ * Function: armVCM4P2_BlockMatch_Integer
+ *
+ * Description:
+ * Performs a 16x16 block search; estimates motion vector and associated minimum SAD.
+ * Both the input and output motion vectors are represented using half-pixel units, and
+ * therefore a shift left or right by 1 bit may be required, respectively, to match the
+ * input or output MVs with other functions that either generate output MVs or expect
+ * input MVs represented using integer pixel units.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcRefBuf pointer to the reference Y plane; points to the reference MB that
+ * corresponds to the location of the current macroblock in the current
+ * plane.
+ * [in] refWidth width of the reference plane
+ * [in] pRefRect pointer to the valid rectangular in reference plane. Relative to image origin.
+ * It's not limited to the image boundary, but depended on the padding. For example,
+ * if you pad 4 pixels outside the image border, then the value for left border
+ * can be -4
+ * [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane (linear array,
+ * 256 entries); must be aligned on an 8-byte boundary.
+ * [in] pCurrPointPos position of the current macroblock in the current plane
+ * [in] pSrcPreMV pointer to predicted motion vector; NULL indicates no predicted MV
+ * [in] pSrcPreSAD pointer to SAD associated with the predicted MV (referenced by pSrcPreMV)
+ * [in] searchRange search range for 16X16 integer block,the units of it is full pixel,the search range
+ * is the same in all directions.It is in inclusive of the boundary and specified in
+ * terms of integer pixel units.
+ * [in] pMESpec vendor-specific motion estimation specification structure; must have been allocated
+ * and then initialized using omxVCM4P2_MEInit prior to calling the block matching
+ * function.
+ * [in] BlockSize MacroBlock Size i.e either 16x16 or 8x8.
+ * [out] pDstMV pointer to estimated MV
+ * [out] pDstSAD pointer to minimum SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr ¨C no error.
+ * OMX_Sts_BadArgErr ¨C bad arguments
+ *
+ */
+
+OMXResult armVCM4P2_BlockMatch_Integer(
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCMotionVector *pSrcPreMV,
+ const OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector *pDstMV,
+ OMX_INT *pDstSAD,
+ OMX_U8 BlockSize
+);
+
+/**
+ * Function: armVCM4P2_BlockMatch_Half
+ *
+ * Description:
+ * Performs a 16x16 block match with half-pixel resolution. Returns the estimated
+ * motion vector and associated minimum SAD. This function estimates the half-pixel
+ * motion vector by interpolating the integer resolution motion vector referenced
+ * by the input parameter pSrcDstMV, i.e., the initial integer MV is generated
+ * externally. The input parameters pSrcRefBuf and pSearchPointRefPos should be
+ * shifted by the winning MV of 16x16 integer search prior to calling BlockMatch_Half_16x16.
+ * The function BlockMatch_Integer_16x16 may be used for integer motion estimation.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcRefBuf pointer to the reference Y plane; points to the reference MB
+ * that corresponds to the location of the current macroblock in
+ * the current plane.
+ * [in] refWidth width of the reference plane
+ * [in] pRefRect reference plane valid region rectangle
+ * [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane
+ * (linear array, 256 entries); must be aligned on an 8-byte boundary.
+ * [in] pSearchPointRefPos position of the starting point for half pixel search (specified
+ * in terms of integer pixel units) in the reference plane.
+ * [in] rndVal rounding control bit for half pixel motion estimation;
+ * 0=rounding control disabled; 1=rounding control enabled
+ * [in] pSrcDstMV pointer to the initial MV estimate; typically generated during a prior
+ * 16X16 integer search and its unit is half pixel.
+ * [in] BlockSize MacroBlock Size i.e either 16x16 or 8x8.
+ * [out]pSrcDstMV pointer to estimated MV
+ * [out]pDstSAD pointer to minimum SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr ¨C no error
+ * OMX_Sts_BadArgErr ¨C bad arguments
+ *
+ */
+
+OMXResult armVCM4P2_BlockMatch_Half(
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pSearchPointRefPos,
+ OMX_INT rndVal,
+ OMXVCMotionVector *pSrcDstMV,
+ OMX_INT *pDstSAD,
+ OMX_U8 BlockSize
+);
+/**
+ * Function: armVCM4P2_PadMV
+ *
+ * Description:
+ * Performs motion vector padding for a macroblock.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcDstMV pointer to motion vector buffer of the current
+ * macroblock
+ * [in] pTransp pointer to transparent status buffer of the
+ * current macroblock
+ * [out] pSrcDstMV pointer to motion vector buffer in which the
+ * motion vectors have been padded
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_PadMV(
+ OMXVCMotionVector * pSrcDstMV,
+ OMX_U8 * pTransp
+);
+
+/*
+ * H.264 Specific Declarations
+ */
+/* Defines */
+#define ARM_M4P10_Q_OFFSET (15)
+
+
+/* Dequant tables */
+
+extern const OMX_U8 armVCM4P10_PosToVCol4x4[16];
+extern const OMX_U8 armVCM4P10_PosToVCol2x2[4];
+extern const OMX_U8 armVCM4P10_VMatrix[6][3];
+extern const OMX_U32 armVCM4P10_MFMatrix[6][3];
+
+
+/*
+ * Description:
+ * This function perform the work required by the OpenMAX
+ * DecodeCoeffsToPair function and DecodeChromaDCCoeffsToPair.
+ * Since most of the code is common we share it here.
+ *
+ * Parameters:
+ * [in] ppBitStream Double pointer to current byte in bit stream buffer
+ * [in] pOffset Pointer to current bit position in the byte pointed
+ * to by *ppBitStream
+ * [in] sMaxNumCoeff Maximum number of non-zero coefficients in current
+ * block (4,15 or 16)
+ * [in] nTable Table number (0 to 4) according to the five columns
+ * of Table 9-5 in the H.264 spec
+ * [out] ppBitStream *ppBitStream is updated after each block is decoded
+ * [out] pOffset *pOffset is updated after each block is decoded
+ * [out] pNumCoeff Pointer to the number of nonzero coefficients in
+ * this block
+ * [out] ppPosCoefbuf Double pointer to destination residual
+ * coefficient-position pair buffer
+ * Return Value:
+ * Standard omxError result. See enumeration for possible result codes.
+
+ */
+
+OMXResult armVCM4P10_DecodeCoeffsToPair(
+ const OMX_U8** ppBitStream,
+ OMX_S32* pOffset,
+ OMX_U8* pNumCoeff,
+ OMX_U8**ppPosCoefbuf,
+ OMX_INT nTable,
+ OMX_INT sMaxNumCoeff
+ );
+
+/*
+ * Description:
+ * Perform DC style intra prediction, averaging upper and left block
+ *
+ * Parameters:
+ * [in] pSrcLeft Pointer to the buffer of 16 left coefficients:
+ * p[x, y] (x = -1, y = 0..3)
+ * [in] pSrcAbove Pointer to the buffer of 16 above coefficients:
+ * p[x,y] (x = 0..3, y = -1)
+ * [in] leftStep Step of left coefficient buffer
+ * [in] dstStep Step of the destination buffer
+ * [in] availability Neighboring 16x16 MB availability flag
+ * [out] pDst Pointer to the destination buffer
+ *
+ * Return Value:
+ * None
+ */
+
+void armVCM4P10_PredictIntraDC4x4(
+ const OMX_U8* pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ OMX_U8* pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMX_S32 availability
+);
+
+/*
+ * Description
+ * Unpack a 4x4 block of coefficient-residual pair values
+ *
+ * Parameters:
+ * [in] ppSrc Double pointer to residual coefficient-position pair
+ * buffer output by CALVC decoding
+ * [out] ppSrc *ppSrc is updated to the start of next non empty block
+ * [out] pDst Pointer to unpacked 4x4 block
+ */
+
+void armVCM4P10_UnpackBlock4x4(
+ const OMX_U8 **ppSrc,
+ OMX_S16* pDst
+);
+
+/*
+ * Description
+ * Unpack a 2x2 block of coefficient-residual pair values
+ *
+ * Parameters:
+ * [in] ppSrc Double pointer to residual coefficient-position pair
+ * buffer output by CALVC decoding
+ * [out] ppSrc *ppSrc is updated to the start of next non empty block
+ * [out] pDst Pointer to unpacked 4x4 block
+ */
+
+void armVCM4P10_UnpackBlock2x2(
+ const OMX_U8 **ppSrc,
+ OMX_S16* pDst
+);
+
+/*
+ * Description
+ * Deblock one boundary pixel
+ *
+ * Parameters:
+ * [in] pQ0 Pointer to pixel q0
+ * [in] Step Step between pixels q0 and q1
+ * [in] tC0 Edge threshold value
+ * [in] alpha alpha threshold value
+ * [in] beta beta threshold value
+ * [in] bS deblocking strength
+ * [in] ChromaFlag True for chroma blocks
+ * [out] pQ0 Deblocked pixels
+ *
+ */
+
+void armVCM4P10_DeBlockPixel(
+ OMX_U8 *pQ0, /* pointer to the pixel q0 */
+ int Step, /* step between pixels q0 and q1 */
+ int tC0, /* edge threshold value */
+ int alpha, /* alpha */
+ int beta, /* beta */
+ int bS, /* deblocking strength */
+ int ChromaFlag
+);
+
+/**
+ * Function: armVCM4P10_InterpolateHalfHor_Luma
+ *
+ * Description:
+ * This function performs interpolation for horizontal 1/2-pel positions
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to interpolate
+ in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [out] pDst Pointer to the interpolation buffer of the 1/2-pel
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+OMXResult armVCM4P10_InterpolateHalfHor_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+/**
+ * Function: armVCM4P10_InterpolateHalfVer_Luma
+ *
+ * Description:
+ * This function performs interpolation for vertical 1/2-pel positions
+ * around a full-pel position.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to interpolate
+ * in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [out] pDst Pointer to the interpolation buffer of the 1/2-pel
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+OMXResult armVCM4P10_InterpolateHalfVer_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+/**
+ * Function: armVCM4P10_InterpolateHalfDiag_Luma
+ *
+ * Description:
+ * This function performs interpolation for (1/2, 1/2) positions
+ * around a full-pel position.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to interpolate
+ * in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [out] pDst Pointer to the interpolation buffer of the (1/2,1/2)-pel
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+OMXResult armVCM4P10_InterpolateHalfDiag_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+/*
+ * Description:
+ * Transform Residual 4x4 Coefficients
+ *
+ * Parameters:
+ * [in] pSrc Source 4x4 block
+ * [out] pDst Destination 4x4 block
+ *
+ */
+
+void armVCM4P10_TransformResidual4x4(OMX_S16* pDst, OMX_S16 *pSrc);
+
+/*
+ * Description:
+ * Forward Transform Residual 4x4 Coefficients
+ *
+ * Parameters:
+ * [in] pSrc Source 4x4 block
+ * [out] pDst Destination 4x4 block
+ *
+ */
+
+void armVCM4P10_FwdTransformResidual4x4(OMX_S16* pDst, OMX_S16 *pSrc);
+
+OMX_INT armVCM4P10_CompareMotionCostToMV (
+ OMX_S16 mvX,
+ OMX_S16 mvY,
+ OMXVCMotionVector diffMV,
+ OMX_INT candSAD,
+ OMXVCMotionVector *bestMV,
+ OMX_U32 nLamda,
+ OMX_S32 *pBestCost);
+
+/**
+ * Function: armVCCOMM_SAD
+ *
+ * Description:
+ * This function calculate the SAD for NxM blocks.
+ *
+ * Remarks:
+ *
+ * [in] pSrcOrg Pointer to the original block
+ * [in] iStepOrg Step of the original block buffer
+ * [in] pSrcRef Pointer to the reference block
+ * [in] iStepRef Step of the reference block buffer
+ * [in] iHeight Height of the block
+ * [in] iWidth Width of the block
+ * [out] pDstSAD Pointer of result SAD
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+OMXResult armVCCOMM_SAD(
+ const OMX_U8* pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8* pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32* pDstSAD,
+ OMX_U32 iHeight,
+ OMX_U32 iWidth);
+
+/**
+ * Function: armVCCOMM_Average
+ *
+ * Description:
+ * This function calculates the average of two blocks and stores the result.
+ *
+ * Remarks:
+ *
+ * [in] pPred0 Pointer to the top-left corner of reference block 0
+ * [in] pPred1 Pointer to the top-left corner of reference block 1
+ * [in] iPredStep0 Step of reference block 0
+ * [in] iPredStep1 Step of reference block 1
+ * [in] iDstStep Step of the destination buffer
+ * [in] iWidth Width of the blocks
+ * [in] iHeight Height of the blocks
+ * [out] pDstPred Pointer to the destination buffer
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+ OMXResult armVCCOMM_Average (
+ const OMX_U8* pPred0,
+ const OMX_U8* pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8* pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+/**
+ * Function: armVCM4P10_SADQuar
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the
+ * average of the other two (pSrcRef0 and pSrcRef1)
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to the original block
+ * [in] pSrcRef0 Pointer to reference block 0
+ * [in] pSrcRef1 Pointer to reference block 1
+ * [in] iSrcStep Step of the original block buffer
+ * [in] iRefStep0 Step of reference block 0
+ * [in] iRefStep1 Step of reference block 1
+ * [in] iHeight Height of the block
+ * [in] iWidth Width of the block
+ * [out] pDstSAD Pointer of result SAD
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+OMXResult armVCM4P10_SADQuar(
+ const OMX_U8* pSrc,
+ const OMX_U8* pSrcRef0,
+ const OMX_U8* pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32* pDstSAD,
+ OMX_U32 iHeight,
+ OMX_U32 iWidth
+);
+
+/**
+ * Function: armVCM4P10_Interpolate_Chroma
+ *
+ * Description:
+ * This function performs interpolation for chroma components.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to
+ * interpolate in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [in] dx Fractional part of horizontal motion vector
+ * component in 1/8 pixel unit (0~7)
+ * [in] dy Fractional part of vertical motion vector
+ * component in 1/8 pixel unit (0~7)
+ * [out] pDst Pointer to the interpolation buffer
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+ OMXResult armVCM4P10_Interpolate_Chroma(
+ OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight,
+ OMX_U32 dx,
+ OMX_U32 dy
+);
+
+/**
+ * Function: armVCM4P10_Interpolate_Luma
+ *
+ * Description:
+ * This function performs interpolation for luma components.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to
+ * interpolate in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [in] dx Fractional part of horizontal motion vector
+ * component in 1/4 pixel unit (0~3)
+ * [in] dy Fractional part of vertical motion vector
+ * component in 1/4 pixel unit (0~3)
+ * [out] pDst Pointer to the interpolation buffer
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+ OMXResult armVCM4P10_Interpolate_Luma(
+ const OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight,
+ OMX_U32 dx,
+ OMX_U32 dy
+);
+
+/**
+ * Function: omxVCH264_DequantTransformACFromPair_U8_S16_C1_DLx
+ *
+ * Description:
+ * Reconstruct the 4x4 residual block from coefficient-position pair buffer,
+ * perform dequantisation and integer inverse transformation for 4x4 block of
+ * residuals and update the pair buffer pointer to next non-empty block.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppSrc Double pointer to residual coefficient-position
+ * pair buffer output by CALVC decoding
+ * [in] pDC Pointer to the DC coefficient of this block, NULL
+ * if it doesn't exist
+ * [in] QP Quantization parameter
+ * [in] AC Flag indicating if at least one non-zero coefficient exists
+ * [out] pDst pointer to the reconstructed 4x4 block data
+ *
+ * Return Value:
+ * Standard omxError result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P10_DequantTransformACFromPair_U8_S16_C1_DLx(
+ OMX_U8 **ppSrc,
+ OMX_S16 *pDst,
+ OMX_INT QP,
+ OMX_S16* pDC,
+ int AC
+);
+
+#endif /*_armVideo_H_*/
+
+/*End of File*/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/api/omxVC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/api/omxVC.h
new file mode 100644
index 0000000..7b3cc72
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/api/omxVC.h
@@ -0,0 +1,4381 @@
+/**
+ * File: omxVC.h
+ * Brief: OpenMAX DL v1.0.2 - Video Coding library
+ *
+ * Copyright © 2005-2008 The Khronos Group Inc. All Rights Reserved.
+ *
+ * These materials are protected by copyright laws and contain material
+ * proprietary to the Khronos Group, Inc. You may use these materials
+ * for implementing Khronos specifications, without altering or removing
+ * any trademark, copyright or other notice from the specification.
+ *
+ * Khronos Group makes no, and expressly disclaims any, representations
+ * or warranties, express or implied, regarding these materials, including,
+ * without limitation, any implied warranties of merchantability or fitness
+ * for a particular purpose or non-infringement of any intellectual property.
+ * Khronos Group makes no, and expressly disclaims any, warranties, express
+ * or implied, regarding the correctness, accuracy, completeness, timeliness,
+ * and reliability of these materials.
+ *
+ * Under no circumstances will the Khronos Group, or any of its Promoters,
+ * Contributors or Members or their respective partners, officers, directors,
+ * employees, agents or representatives be liable for any damages, whether
+ * direct, indirect, special or consequential damages for lost revenues,
+ * lost profits, or otherwise, arising from or in connection with these
+ * materials.
+ *
+ * Khronos and OpenMAX are trademarks of the Khronos Group Inc.
+ *
+ */
+
+/* *****************************************************************************************/
+
+#ifndef _OMXVC_H_
+#define _OMXVC_H_
+
+#include "omxtypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* 6.1.1.1 Motion Vectors */
+/* In omxVC, motion vectors are represented as follows: */
+
+typedef struct {
+ OMX_S16 dx;
+ OMX_S16 dy;
+} OMXVCMotionVector;
+
+
+
+/**
+ * Function: omxVCCOMM_Average_8x (6.1.3.1.1)
+ *
+ * Description:
+ * This function calculates the average of two 8x4, 8x8, or 8x16 blocks. The
+ * result is rounded according to (a+b+1)/2. The block average function can
+ * be used in conjunction with half-pixel interpolation to obtain quarter
+ * pixel motion estimates, as described in [ISO14496-10], subclause 8.4.2.2.1.
+ *
+ * Input Arguments:
+ *
+ * pPred0 - Pointer to the top-left corner of reference block 0
+ * pPred1 - Pointer to the top-left corner of reference block 1
+ * iPredStep0 - Step of reference block 0
+ * iPredStep1 - Step of reference block 1
+ * iDstStep - Step of the destination buffer.
+ * iHeight - Height of the blocks
+ *
+ * Output Arguments:
+ *
+ * pDstPred - Pointer to the destination buffer. 8-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pPred0, pPred1, or
+ * pDstPred.
+ * - pDstPred is not aligned on an 8-byte boundary.
+ * - iPredStep0 <= 0 or iPredStep0 is not a multiple of 8.
+ * - iPredStep1 <= 0 or iPredStep1 is not a multiple of 8.
+ * - iDstStep <= 0 or iDstStep is not a multiple of 8.
+ * - iHeight is not 4, 8, or 16.
+ *
+ */
+OMXResult omxVCCOMM_Average_8x (
+ const OMX_U8 *pPred0,
+ const OMX_U8 *pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8 *pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCCOMM_Average_16x (6.1.3.1.2)
+ *
+ * Description:
+ * This function calculates the average of two 16x16 or 16x8 blocks. The
+ * result is rounded according to (a+b+1)/2. The block average function can
+ * be used in conjunction with half-pixel interpolation to obtain quarter
+ * pixel motion estimates, as described in [ISO14496-10], subclause 8.4.2.2.1.
+ *
+ * Input Arguments:
+ *
+ * pPred0 - Pointer to the top-left corner of reference block 0
+ * pPred1 - Pointer to the top-left corner of reference block 1
+ * iPredStep0 - Step of reference block 0
+ * iPredStep1 - Step of reference block 1
+ * iDstStep - Step of the destination buffer
+ * iHeight - Height of the blocks
+ *
+ * Output Arguments:
+ *
+ * pDstPred - Pointer to the destination buffer. 16-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pPred0, pPred1, or
+ * pDstPred.
+ * - pDstPred is not aligned on a 16-byte boundary.
+ * - iPredStep0 <= 0 or iPredStep0 is not a multiple of 16.
+ * - iPredStep1 <= 0 or iPredStep1 is not a multiple of 16.
+ * - iDstStep <= 0 or iDstStep is not a multiple of 16.
+ * - iHeight is not 8 or 16.
+ *
+ */
+OMXResult omxVCCOMM_Average_16x (
+ const OMX_U8 *pPred0,
+ const OMX_U8 *pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8 *pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCCOMM_ExpandFrame_I (6.1.3.2.1)
+ *
+ * Description:
+ * This function expands a reconstructed frame in-place. The unexpanded
+ * source frame should be stored in a plane buffer with sufficient space
+ * pre-allocated for edge expansion, and the input frame should be located in
+ * the plane buffer center. This function executes the pixel expansion by
+ * replicating source frame edge pixel intensities in the empty pixel
+ * locations (expansion region) between the source frame edge and the plane
+ * buffer edge. The width/height of the expansion regions on the
+ * horizontal/vertical edges is controlled by the parameter iExpandPels.
+ *
+ * Input Arguments:
+ *
+ * pSrcDstPlane - pointer to the top-left corner of the frame to be
+ * expanded; must be aligned on an 8-byte boundary.
+ * iFrameWidth - frame width; must be a multiple of 8.
+ * iFrameHeight -frame height; must be a multiple of 8.
+ * iExpandPels - number of pixels to be expanded in the horizontal and
+ * vertical directions; must be a multiple of 8.
+ * iPlaneStep - distance, in bytes, between the start of consecutive lines
+ * in the plane buffer; must be larger than or equal to
+ * (iFrameWidth + 2 * iExpandPels).
+ *
+ * Output Arguments:
+ *
+ * pSrcDstPlane -Pointer to the top-left corner of the frame (NOT the
+ * top-left corner of the plane); must be aligned on an 8-byte
+ * boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - pSrcDstPlane is NULL.
+ * - pSrcDstPlane is not aligned on an 8-byte boundary.
+ * - one of the following parameters is either equal to zero or is a
+ * non-multiple of 8: iFrameHeight, iFrameWidth, iPlaneStep, or
+ * iExpandPels.
+ * - iPlaneStep < (iFrameWidth + 2 * iExpandPels).
+ *
+ */
+OMXResult omxVCCOMM_ExpandFrame_I (
+ OMX_U8 *pSrcDstPlane,
+ OMX_U32 iFrameWidth,
+ OMX_U32 iFrameHeight,
+ OMX_U32 iExpandPels,
+ OMX_U32 iPlaneStep
+);
+
+
+
+/**
+ * Function: omxVCCOMM_Copy8x8 (6.1.3.3.1)
+ *
+ * Description:
+ * Copies the reference 8x8 block to the current block.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the reference block in the source frame; must be
+ * aligned on an 8-byte boundary.
+ * step - distance between the starts of consecutive lines in the reference
+ * frame, in bytes; must be a multiple of 8 and must be larger than
+ * or equal to 8.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination block; must be aligned on an 8-byte
+ * boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pSrc, pDst
+ * - one or more of the following pointers is not aligned on an 8-byte
+ * boundary: pSrc, pDst
+ * - step <8 or step is not a multiple of 8.
+ *
+ */
+OMXResult omxVCCOMM_Copy8x8 (
+ const OMX_U8 *pSrc,
+ OMX_U8 *pDst,
+ OMX_INT step
+);
+
+
+
+/**
+ * Function: omxVCCOMM_Copy16x16 (6.1.3.3.2)
+ *
+ * Description:
+ * Copies the reference 16x16 macroblock to the current macroblock.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the reference macroblock in the source frame; must be
+ * aligned on a 16-byte boundary.
+ * step - distance between the starts of consecutive lines in the reference
+ * frame, in bytes; must be a multiple of 16 and must be larger
+ * than or equal to 16.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination macroblock; must be aligned on a
+ * 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pSrc, pDst
+ * - one or more of the following pointers is not aligned on a 16-byte
+ * boundary: pSrc, pDst
+ * - step <16 or step is not a multiple of 16.
+ *
+ */
+OMXResult omxVCCOMM_Copy16x16 (
+ const OMX_U8 *pSrc,
+ OMX_U8 *pDst,
+ OMX_INT step
+);
+
+
+
+/**
+ * Function: omxVCCOMM_ComputeTextureErrorBlock_SAD (6.1.4.1.1)
+ *
+ * Description:
+ * Computes texture error of the block; also returns SAD.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the source plane; must be aligned on an 8-byte
+ * boundary.
+ * srcStep - step of the source plane
+ * pSrcRef - pointer to the reference buffer, an 8x8 block; must be aligned
+ * on an 8-byte boundary.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination buffer, an 8x8 block; must be aligned
+ * on an 8-byte boundary.
+ * pDstSAD - pointer to the Sum of Absolute Differences (SAD) value
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - At least one of the following
+ * pointers is NULL: pSrc, pSrcRef, pDst and pDstSAD.
+ * - pSrc is not 8-byte aligned.
+ * - SrcStep <= 0 or srcStep is not a multiple of 8.
+ * - pSrcRef is not 8-byte aligned.
+ * - pDst is not 8-byte aligned.
+ *
+ */
+OMXResult omxVCCOMM_ComputeTextureErrorBlock_SAD (
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ const OMX_U8 *pSrcRef,
+ OMX_S16 *pDst,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCCOMM_ComputeTextureErrorBlock (6.1.4.1.2)
+ *
+ * Description:
+ * Computes the texture error of the block.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the source plane. This should be aligned on an 8-byte
+ * boundary.
+ * srcStep - step of the source plane
+ * pSrcRef - pointer to the reference buffer, an 8x8 block. This should be
+ * aligned on an 8-byte boundary.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination buffer, an 8x8 block. This should be
+ * aligned on an 8-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is NULL:
+ * pSrc, pSrcRef, pDst.
+ * - pSrc is not 8-byte aligned.
+ * - SrcStep <= 0 or srcStep is not a multiple of 8.
+ * - pSrcRef is not 8-byte aligned.
+ * - pDst is not 8-byte aligned
+ *
+ */
+OMXResult omxVCCOMM_ComputeTextureErrorBlock (
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ const OMX_U8 *pSrcRef,
+ OMX_S16 *pDst
+);
+
+
+
+/**
+ * Function: omxVCCOMM_LimitMVToRect (6.1.4.1.3)
+ *
+ * Description:
+ * Limits the motion vector associated with the current block/macroblock to
+ * prevent the motion compensated block/macroblock from moving outside a
+ * bounding rectangle as shown in Figure 6-1.
+ *
+ * Input Arguments:
+ *
+ * pSrcMV - pointer to the motion vector associated with the current block
+ * or macroblock
+ * pRectVOPRef - pointer to the bounding rectangle
+ * Xcoord, Ycoord - coordinates of the current block or macroblock
+ * size - size of the current block or macroblock; must be equal to 8 or
+ * 16.
+ *
+ * Output Arguments:
+ *
+ * pDstMV - pointer to the limited motion vector
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcMV, pDstMV, or pRectVOPRef.
+ * - size is not equal to either 8 or 16.
+ * - the width or height of the bounding rectangle is less than
+ * twice the block size.
+ */
+OMXResult omxVCCOMM_LimitMVToRect (
+ const OMXVCMotionVector *pSrcMV,
+ OMXVCMotionVector *pDstMV,
+ const OMXRect *pRectVOPRef,
+ OMX_INT Xcoord,
+ OMX_INT Ycoord,
+ OMX_INT size
+);
+
+
+
+/**
+ * Function: omxVCCOMM_SAD_16x (6.1.4.1.4)
+ *
+ * Description:
+ * This function calculates the SAD for 16x16 and 16x8 blocks.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to the original block; must be aligned on a 16-byte
+ * boundary.
+ * iStepOrg - Step of the original block buffer
+ * pSrcRef - Pointer to the reference block
+ * iStepRef - Step of the reference block buffer
+ * iHeight - Height of the block
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - Pointer of result SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pDstSAD, or pSrcRef
+ * - pSrcOrg is not 16-byte aligned.
+ * - iStepOrg <= 0 or iStepOrg is not a multiple of 16
+ * - iStepRef <= 0 or iStepRef is not a multiple of 16
+ * - iHeight is not 8 or 16
+ *
+ */
+OMXResult omxVCCOMM_SAD_16x (
+ const OMX_U8 *pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8 *pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCCOMM_SAD_8x (6.1.4.1.5)
+ *
+ * Description:
+ * This function calculates the SAD for 8x16, 8x8, 8x4 blocks.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to the original block; must be aligned on a 8-byte
+ * boundary.
+ * iStepOrg - Step of the original block buffer
+ * pSrcRef - Pointer to the reference block
+ * iStepRef - Step of the reference block buffer
+ * iHeight - Height of the block
+ *
+ * Output Arguments:
+ *
+ * pDstSAD -Pointer of result SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pDstSAD, or pSrcRef
+ * - pSrcOrg is not 8-byte aligned.
+ * - iStepOrg <= 0 or iStepOrg is not a multiple of 8
+ * - iStepRef <= 0 or iStepRef is not a multiple of 8
+ * - iHeight is not 4, 8 or 16
+ *
+ */
+OMXResult omxVCCOMM_SAD_8x (
+ const OMX_U8 *pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8 *pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32*pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/* 6.2.1.1 Direction */
+/* The direction enumerator is used with functions that perform AC/DC prediction and zig-zag scan. */
+
+enum {
+ OMX_VC_NONE = 0,
+ OMX_VC_HORIZONTAL = 1,
+ OMX_VC_VERTICAL = 2
+};
+
+
+
+/* 6.2.1.2 Bilinear Interpolation */
+/* The bilinear interpolation enumerator is used with motion estimation, motion compensation, and reconstruction functions. */
+
+enum {
+ OMX_VC_INTEGER_PIXEL = 0, /* case a */
+ OMX_VC_HALF_PIXEL_X = 1, /* case b */
+ OMX_VC_HALF_PIXEL_Y = 2, /* case c */
+ OMX_VC_HALF_PIXEL_XY = 3 /* case d */
+};
+
+
+
+/* 6.2.1.3 Neighboring Macroblock Availability */
+/* Neighboring macroblock availability is indicated using the following flags: */
+
+enum {
+ OMX_VC_UPPER = 1, /** above macroblock is available */
+ OMX_VC_LEFT = 2, /** left macroblock is available */
+ OMX_VC_CENTER = 4,
+ OMX_VC_RIGHT = 8,
+ OMX_VC_LOWER = 16,
+ OMX_VC_UPPER_LEFT = 32, /** above-left macroblock is available */
+ OMX_VC_UPPER_RIGHT = 64, /** above-right macroblock is available */
+ OMX_VC_LOWER_LEFT = 128,
+ OMX_VC_LOWER_RIGHT = 256
+};
+
+
+
+/* 6.2.1.4 Video Components */
+/* A data type that enumerates video components is defined as follows: */
+
+typedef enum {
+ OMX_VC_LUMINANCE, /** Luminance component */
+ OMX_VC_CHROMINANCE /** chrominance component */
+} OMXVCM4P2VideoComponent;
+
+
+
+/* 6.2.1.5 MacroblockTypes */
+/* A data type that enumerates macroblock types is defined as follows: */
+
+typedef enum {
+ OMX_VC_INTER = 0, /** P picture or P-VOP */
+ OMX_VC_INTER_Q = 1, /** P picture or P-VOP */
+ OMX_VC_INTER4V = 2, /** P picture or P-VOP */
+ OMX_VC_INTRA = 3, /** I and P picture, I- and P-VOP */
+ OMX_VC_INTRA_Q = 4, /** I and P picture, I- and P-VOP */
+ OMX_VC_INTER4V_Q = 5 /** P picture or P-VOP (H.263)*/
+} OMXVCM4P2MacroblockType;
+
+
+
+/* 6.2.1.6 Coordinates */
+/* Coordinates are represented as follows: */
+
+typedef struct {
+ OMX_INT x;
+ OMX_INT y;
+} OMXVCM4P2Coordinate;
+
+
+
+/* 6.2.1.7 Motion Estimation Algorithms */
+/* A data type that enumerates motion estimation search methods is defined as follows: */
+
+typedef enum {
+ OMX_VC_M4P2_FAST_SEARCH = 0, /** Fast motion search */
+ OMX_VC_M4P2_FULL_SEARCH = 1 /** Full motion search */
+} OMXVCM4P2MEMode;
+
+
+
+/* 6.2.1.8 Motion Estimation Parameters */
+/* A data structure containing control parameters for
+ * motion estimation functions is defined as follows:
+ */
+
+typedef struct {
+ OMX_INT searchEnable8x8; /** enables 8x8 search */
+ OMX_INT halfPelSearchEnable; /** enables half-pel resolution */
+ OMX_INT searchRange; /** search range */
+ OMX_INT rndVal; /** rounding control; 0-disabled, 1-enabled*/
+} OMXVCM4P2MEParams;
+
+
+
+/* 6.2.1.9 Macroblock Information */
+/* A data structure containing macroblock parameters for
+ * motion estimation functions is defined as follows:
+ */
+
+typedef struct {
+ OMX_S32 sliceId; /* slice number */
+ OMXVCM4P2MacroblockType mbType; /* MB type: OMX_VC_INTRA, OMX_VC_INTER, or OMX_VC_INTER4 */
+ OMX_S32 qp; /* quantization parameter*/
+ OMX_U32 cbpy; /* CBP Luma */
+ OMX_U32 cbpc; /* CBP Chroma */
+ OMXVCMotionVector pMV0[2][2]; /* motion vector, represented using 1/2-pel units,
+ * pMV0[blocky][blockx] (blocky = 0~1, blockx =0~1)
+ */
+ OMXVCMotionVector pMVPred[2][2]; /* motion vector prediction, represented using 1/2-pel units,
+ * pMVPred[blocky][blockx] (blocky = 0~1, blockx = 0~1)
+ */
+ OMX_U8 pPredDir[2][2]; /* AC prediction direction:
+ * OMX_VC_NONE, OMX_VC_VERTICAL, OMX_VC_HORIZONTAL
+ */
+} OMXVCM4P2MBInfo, *OMXVCM4P2MBInfoPtr;
+
+
+
+/**
+ * Function: omxVCM4P2_FindMVpred (6.2.3.1.1)
+ *
+ * Description:
+ * Predicts a motion vector for the current block using the procedure
+ * specified in [ISO14496-2], subclause 7.6.5. The resulting predicted MV is
+ * returned in pDstMVPred. If the parameter pDstMVPredME if is not NULL then
+ * the set of three MV candidates used for prediction is also returned,
+ * otherwise pDstMVPredMEis NULL upon return.
+ *
+ * Input Arguments:
+ *
+ * pSrcMVCurMB - pointer to the MV buffer associated with the current Y
+ * macroblock; a value of NULL indicates unavailability.
+ * pSrcCandMV1 - pointer to the MV buffer containing the 4 MVs associated
+ * with the MB located to the left of the current MB; set to NULL
+ * if there is no MB to the left.
+ * pSrcCandMV2 - pointer to the MV buffer containing the 4 MVs associated
+ * with the MB located above the current MB; set to NULL if there
+ * is no MB located above the current MB.
+ * pSrcCandMV3 - pointer to the MV buffer containing the 4 MVs associated
+ * with the MB located to the right and above the current MB; set
+ * to NULL if there is no MB located to the above-right.
+ * iBlk - the index of block in the current macroblock
+ * pDstMVPredME - MV candidate return buffer; if set to NULL then
+ * prediction candidate MVs are not returned and pDstMVPredME will
+ * be NULL upon function return; if pDstMVPredME is non-NULL then it
+ * must point to a buffer containing sufficient space for three
+ * return MVs.
+ *
+ * Output Arguments:
+ *
+ * pDstMVPred - pointer to the predicted motion vector
+ * pDstMVPredME - if non-NULL upon input then pDstMVPredME points upon
+ * return to a buffer containing the three motion vector candidates
+ * used for prediction as specified in [ISO14496-2], subclause
+ * 7.6.5, otherwise if NULL upon input then pDstMVPredME is NULL
+ * upon output.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - the pointer pDstMVPred is NULL
+ * - the parameter iBlk does not fall into the range 0 <= iBlk<=3
+ *
+ */
+OMXResult omxVCM4P2_FindMVpred (
+ const OMXVCMotionVector *pSrcMVCurMB,
+ const OMXVCMotionVector *pSrcCandMV1,
+ const OMXVCMotionVector *pSrcCandMV2,
+ const OMXVCMotionVector *pSrcCandMV3,
+ OMXVCMotionVector *pDstMVPred,
+ OMXVCMotionVector *pDstMVPredME,
+ OMX_INT iBlk
+);
+
+
+
+/**
+ * Function: omxVCM4P2_IDCT8x8blk (6.2.3.2.1)
+ *
+ * Description:
+ * Computes a 2D inverse DCT for a single 8x8 block, as defined in
+ * [ISO14496-2].
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the start of the linearly arranged IDCT input buffer;
+ * must be aligned on a 16-byte boundary. According to
+ * [ISO14496-2], the input coefficient values should lie within the
+ * range [-2048, 2047].
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the start of the linearly arranged IDCT output buffer;
+ * must be aligned on a 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - pSrc or pDst is NULL.
+ * - pSrc or pDst is not 16-byte aligned.
+ *
+ */
+OMXResult omxVCM4P2_IDCT8x8blk (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst
+);
+
+
+
+/**
+ * Function: omxVCM4P2_MEGetBufSize (6.2.4.1.1)
+ *
+ * Description:
+ * Computes the size, in bytes, of the vendor-specific specification
+ * structure for the following motion estimation functions:
+ * BlockMatch_Integer_8x8, BlockMatch_Integer_16x16, and MotionEstimationMB.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P2MEMode
+ * pMEParams - motion estimation parameters
+ *
+ * Output Arguments:
+ *
+ * pSize - pointer to the number of bytes required for the specification
+ * structure
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - one or more of the following is true:
+ * - an invalid value was specified for the parameter MEmode
+ * - a negative or zero value was specified for the
+ * parameter pMEParams->searchRange
+ *
+ */
+OMXResult omxVCM4P2_MEGetBufSize (
+ OMXVCM4P2MEMode MEmode,
+ const OMXVCM4P2MEParams *pMEParams,
+ OMX_U32 *pSize
+);
+
+
+
+/**
+ * Function: omxVCM4P2_MEInit (6.2.4.1.2)
+ *
+ * Description:
+ * Initializes the vendor-specific specification structure required for the
+ * following motion estimation functions: BlockMatch_Integer_8x8,
+ * BlockMatch_Integer_16x16, and MotionEstimationMB. Memory for the
+ * specification structure *pMESpec must be allocated prior to calling the
+ * function, and should be aligned on a 4-byte boundary. Following
+ * initialization by this function, the vendor-specific structure *pMESpec
+ * should contain an implementation-specific representation of all motion
+ * estimation parameters received via the structure pMEParams, for example
+ * rndVal, searchRange, etc. The number of bytes required for the
+ * specification structure can be determined using the function
+ * omxVCM4P2_MEGetBufSize.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P2MEMode
+ * pMEParams - motion estimation parameters
+ * pMESpec - pointer to the uninitialized ME specification structure
+ *
+ * Output Arguments:
+ *
+ * pMESpec - pointer to the initialized ME specification structure
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - one or more of the following is true:
+ * - an invalid value was specified for the parameter MEmode
+ * - a negative or zero value was specified for the
+ * parameter pMEParams->searchRange
+ *
+ */
+OMXResult omxVCM4P2_MEInit (
+ OMXVCM4P2MEMode MEmode,
+ const OMXVCM4P2MEParams*pMEParams,
+ void *pMESpec
+);
+
+
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Integer_16x16 (6.2.4.2.1)
+ *
+ * Description:
+ * Performs a 16x16 block search; estimates motion vector and associated
+ * minimum SAD. Both the input and output motion vectors are represented using
+ * half-pixel units, and therefore a shift left or right by 1 bit may be
+ * required, respectively, to match the input or output MVs with other
+ * functions that either generate output MVs or expect input MVs represented
+ * using integer pixel units.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * MB that corresponds to the location of the current macroblock in
+ * the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - pointer to the valid reference plane rectangle; coordinates
+ * are specified relative to the image origin. Rectangle
+ * boundaries may extend beyond image boundaries if the image has
+ * been padded. For example, if padding extends 4 pixels beyond
+ * frame border, then the value for the left border could be set to
+ * -4.
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 256
+ * entries); must be aligned on a 16-byte boundary. The number of
+ * bytes between lines (step) is 16.
+ * pCurrPointPos - position of the current macroblock in the current plane
+ * pSrcPreMV - pointer to predicted motion vector; NULL indicates no
+ * predicted MV
+ * pSrcPreSAD - pointer to SAD associated with the predicted MV (referenced
+ * by pSrcPreMV); may be set to NULL if unavailable.
+ * pMESpec - vendor-specific motion estimation specification structure;
+ * must have been allocated and then initialized using
+ * omxVCM4P2_MEInit prior to calling the block matching function.
+ *
+ * Output Arguments:
+ *
+ * pDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL: pSrcRefBuf,
+ * pRefRect, pSrcCurrBuff, pCurrPointPos, pDstMV, pDstSAD or
+ * pMESpec, or
+ * - pSrcCurrBuf is not 16-byte aligned
+ *
+ */
+OMXResult omxVCM4P2_BlockMatch_Integer_16x16 (
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCMotionVector*pSrcPreMV,
+ const OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector*pDstMV,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Integer_8x8 (6.2.4.2.2)
+ *
+ * Description:
+ * Performs an 8x8 block search; estimates motion vector and associated
+ * minimum SAD. Both the input and output motion vectors are represented
+ * using half-pixel units, and therefore a shift left or right by 1 bit may be
+ * required, respectively, to match the input or output MVs with other
+ * functions that either generate output MVs or expect input MVs represented
+ * using integer pixel units.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * block that corresponds to the location of the current 8x8 block
+ * in the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - pointer to the valid reference plane rectangle; coordinates
+ * are specified relative to the image origin. Rectangle
+ * boundaries may extend beyond image boundaries if the image has
+ * been padded.
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 128
+ * entries); must be aligned on an 8-byte boundary. The number of
+ * bytes between lines (step) is 16 bytes.
+ * pCurrPointPos - position of the current block in the current plane
+ * pSrcPreMV - pointer to predicted motion vector; NULL indicates no
+ * predicted MV
+ * pSrcPreSAD - pointer to SAD associated with the predicted MV (referenced
+ * by pSrcPreMV); may be set to NULL if unavailable.
+ * pMESpec - vendor-specific motion estimation specification structure;
+ * must have been allocated and then initialized using
+ * omxVCM4P2_MEInit prior to calling the block matching function.
+ *
+ * Output Arguments:
+ *
+ * pDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL: pSrcRefBuf,
+ * pRefRect, pSrcCurrBuff, pCurrPointPos, pDstMV, pDstSAD or
+ * pMESpec, or
+ * - pSrcCurrBuf is not 8-byte aligned
+ *
+ */
+OMXResult omxVCM4P2_BlockMatch_Integer_8x8 (
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCMotionVector *pSrcPreMV,
+ const OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector *pDstMV,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Half_16x16 (6.2.4.2.3)
+ *
+ * Description:
+ * Performs a 16x16 block match with half-pixel resolution. Returns the
+ * estimated motion vector and associated minimum SAD. This function
+ * estimates the half-pixel motion vector by interpolating the integer
+ * resolution motion vector referenced by the input parameter pSrcDstMV, i.e.,
+ * the initial integer MV is generated externally. The input parameters
+ * pSrcRefBuf and pSearchPointRefPos should be shifted by the winning MV of
+ * 16x16 integer search prior to calling BlockMatch_Half_16x16. The function
+ * BlockMatch_Integer_16x16 may be used for integer motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * macroblock that corresponds to the location of the current
+ * macroblock in the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - reference plane valid region rectangle
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 256
+ * entries); must be aligned on a 16-byte boundary. The number of
+ * bytes between lines (step) is 16.
+ * pSearchPointRefPos - position of the starting point for half pixel
+ * search (specified in terms of integer pixel units) in the
+ * reference plane, i.e., the reference position pointed to by the
+ * predicted motion vector.
+ * rndVal - rounding control parameter: 0 - disabled; 1 - enabled.
+ * pSrcDstMV - pointer to the initial MV estimate; typically generated
+ * during a prior 16X16 integer search; specified in terms of
+ * half-pixel units.
+ *
+ * Output Arguments:
+ *
+ * pSrcDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL: pSrcRefBuf,
+ * pRefRect, pSrcCurrBuff, pSearchPointRefPos, pSrcDstMV.
+ * - pSrcCurrBuf is not 16-byte aligned, or
+ *
+ */
+OMXResult omxVCM4P2_BlockMatch_Half_16x16 (
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pSearchPointRefPos,
+ OMX_INT rndVal,
+ OMXVCMotionVector *pSrcDstMV,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Half_8x8 (6.2.4.2.4)
+ *
+ * Description:
+ * Performs an 8x8 block match with half-pixel resolution. Returns the
+ * estimated motion vector and associated minimum SAD. This function
+ * estimates the half-pixel motion vector by interpolating the integer
+ * resolution motion vector referenced by the input parameter pSrcDstMV, i.e.,
+ * the initial integer MV is generated externally. The input parameters
+ * pSrcRefBuf and pSearchPointRefPos should be shifted by the winning MV of
+ * 8x8 integer search prior to calling BlockMatch_Half_8x8. The function
+ * BlockMatch_Integer_8x8 may be used for integer motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * block that corresponds to the location of the current 8x8 block
+ * in the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - reference plane valid region rectangle
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 128
+ * entries); must be aligned on a 8-byte boundary. The number of
+ * bytes between lines (step) is 16.
+ * pSearchPointRefPos - position of the starting point for half pixel
+ * search (specified in terms of integer pixel units) in the
+ * reference plane.
+ * rndVal - rounding control parameter: 0 - disabled; 1 - enabled.
+ * pSrcDstMV - pointer to the initial MV estimate; typically generated
+ * during a prior 8x8 integer search, specified in terms of
+ * half-pixel units.
+ *
+ * Output Arguments:
+ *
+ * pSrcDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcRefBuf, pRefRect, pSrcCurrBuff, pSearchPointRefPos, pSrcDstMV
+ * - pSrcCurrBuf is not 8-byte aligned
+ *
+ */
+OMXResult omxVCM4P2_BlockMatch_Half_8x8 (
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pSearchPointRefPos,
+ OMX_INT rndVal,
+ OMXVCMotionVector *pSrcDstMV,
+ OMX_INT *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_MotionEstimationMB (6.2.4.3.1)
+ *
+ * Description:
+ * Performs motion search for a 16x16 macroblock. Selects best motion search
+ * strategy from among inter-1MV, inter-4MV, and intra modes. Supports
+ * integer and half pixel resolution.
+ *
+ * Input Arguments:
+ *
+ * pSrcCurrBuf - pointer to the top-left corner of the current MB in the
+ * original picture plane; must be aligned on a 16-byte boundary.
+ * The function does not expect source data outside the region
+ * bounded by the MB to be available; for example it is not
+ * necessary for the caller to guarantee the availability of
+ * pSrcCurrBuf[-SrcCurrStep], i.e., the row of pixels above the MB
+ * to be processed.
+ * srcCurrStep - width of the original picture plane, in terms of full
+ * pixels; must be a multiple of 16.
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * plane location corresponding to the location of the current
+ * macroblock in the current plane; must be aligned on a 16-byte
+ * boundary.
+ * srcRefStep - width of the reference picture plane, in terms of full
+ * pixels; must be a multiple of 16.
+ * pRefRect - reference plane valid region rectangle, specified relative to
+ * the image origin
+ * pCurrPointPos - position of the current macroblock in the current plane
+ * pMESpec - pointer to the vendor-specific motion estimation specification
+ * structure; must be allocated and then initialized using
+ * omxVCM4P2_MEInit prior to calling this function.
+ * pMBInfo - array, of dimension four, containing pointers to information
+ * associated with four nearby MBs:
+ * - pMBInfo[0] - pointer to left MB information
+ * - pMBInfo[1] - pointer to top MB information
+ * - pMBInfo[2] - pointer to top-left MB information
+ * - pMBInfo[3] - pointer to top-right MB information
+ * Any pointer in the array may be set equal to NULL if the
+ * corresponding MB doesn't exist. For each MB, the following structure
+ * members are used:
+ * - mbType - macroblock type, either OMX_VC_INTRA, OMX_VC_INTER, or
+ * OMX_VC_INTER4V
+ * - pMV0[2][2] - estimated motion vectors; represented
+ * in 1/2 pixel units
+ * - sliceID - number of the slice to which the MB belongs
+ * pSrcDstMBCurr - pointer to information structure for the current MB.
+ * The following entries should be set prior to calling the
+ * function: sliceID - the number of the slice the to which the
+ * current MB belongs. The structure elements cbpy and cbpc are
+ * ignored.
+ *
+ * Output Arguments:
+ *
+ * pSrcDstMBCurr - pointer to updated information structure for the current
+ * MB after MB-level motion estimation has been completed. The
+ * following structure members are updated by the ME function:
+ * - mbType - macroblock type: OMX_VC_INTRA, OMX_VC_INTER, or
+ * OMX_VC_INTER4V.
+ * - pMV0[2][2] - estimated motion vectors; represented in
+ * terms of 1/2 pel units.
+ * - pMVPred[2][2] - predicted motion vectors; represented
+ * in terms of 1/2 pel units.
+ * The structure members cbpy and cbpc are not updated by the function.
+ * pDstSAD - pointer to the minimum SAD for INTER1V, or sum of minimum SADs
+ * for INTER4V
+ * pDstBlockSAD - pointer to an array of SAD values for each of the four
+ * 8x8 luma blocks in the MB. The block SADs are in scan order for
+ * each MB.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL: pSrcCurrBuf,
+ * pSrcRefBuf, pRefRect, pCurrPointPos, pMBInter, pMBIntra,
+ * pSrcDstMBCurr, or pDstSAD.
+ *
+ */
+OMXResult omxVCM4P2_MotionEstimationMB (
+ const OMX_U8 *pSrcCurrBuf,
+ OMX_S32 srcCurrStep,
+ const OMX_U8 *pSrcRefBuf,
+ OMX_S32 srcRefStep,
+ const OMXRect*pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ void *pMESpec,
+ const OMXVCM4P2MBInfoPtr *pMBInfo,
+ OMXVCM4P2MBInfo *pSrcDstMBCurr,
+ OMX_U16 *pDstSAD,
+ OMX_U16 *pDstBlockSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DCT8x8blk (6.2.4.4.1)
+ *
+ * Description:
+ * Computes a 2D forward DCT for a single 8x8 block, as defined in
+ * [ISO14496-2].
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the start of the linearly arranged input buffer; must
+ * be aligned on a 16-byte boundary. Input values (pixel
+ * intensities) are valid in the range [-255,255].
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the start of the linearly arranged output buffer; must
+ * be aligned on a 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, returned if:
+ * - pSrc or pDst is NULL.
+ * - pSrc or pDst is not 16-byte aligned.
+ *
+ */
+OMXResult omxVCM4P2_DCT8x8blk (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst
+);
+
+
+
+/**
+ * Function: omxVCM4P2_QuantIntra_I (6.2.4.4.2)
+ *
+ * Description:
+ * Performs quantization on intra block coefficients. This function supports
+ * bits_per_pixel == 8.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input intra block coefficients; must be aligned
+ * on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale).
+ * blockIndex - block index indicating the component type and position,
+ * valid in the range 0 to 5, as defined in [ISO14496-2], subclause
+ * 6.1.3.8.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (quantized) interblock coefficients.
+ * When shortVideoHeader==1, AC coefficients are saturated on the
+ * interval [-127, 127], and DC coefficients are saturated on the
+ * interval [1, 254]. When shortVideoHeader==0, AC coefficients
+ * are saturated on the interval [-2047, 2047].
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - pSrcDst is NULL.
+ * - blockIndex < 0 or blockIndex >= 10
+ * - QP <= 0 or QP >= 32.
+ *
+ */
+OMXResult omxVCM4P2_QuantIntra_I (
+ OMX_S16 *pSrcDst,
+ OMX_U8 QP,
+ OMX_INT blockIndex,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_QuantInter_I (6.2.4.4.3)
+ *
+ * Description:
+ * Performs quantization on an inter coefficient block; supports
+ * bits_per_pixel == 8.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input inter block coefficients; must be aligned
+ * on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale)
+ * shortVideoHeader - binary flag indicating presence of short_video_header;
+ * shortVideoHeader==1 selects linear intra DC mode, and
+ * shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (quantized) interblock coefficients.
+ * When shortVideoHeader==1, AC coefficients are saturated on the
+ * interval [-127, 127], and DC coefficients are saturated on the
+ * interval [1, 254]. When shortVideoHeader==0, AC coefficients
+ * are saturated on the interval [-2047, 2047].
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - pSrcDst is NULL.
+ * - QP <= 0 or QP >= 32.
+ *
+ */
+OMXResult omxVCM4P2_QuantInter_I (
+ OMX_S16 *pSrcDst,
+ OMX_U8 QP,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_TransRecBlockCoef_intra (6.2.4.4.4)
+ *
+ * Description:
+ * Quantizes the DCT coefficients, implements intra block AC/DC coefficient
+ * prediction, and reconstructs the current intra block texture for prediction
+ * on the next frame. Quantized row and column coefficients are returned in
+ * the updated coefficient buffers.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the pixels of current intra block; must be aligned on
+ * an 8-byte boundary.
+ * pPredBufRow - pointer to the coefficient row buffer containing
+ * ((num_mb_per_row * 2 + 1) * 8) elements of type OMX_S16.
+ * Coefficients are organized into blocks of eight as described
+ * below (Internal Prediction Coefficient Update Procedures). The
+ * DC coefficient is first, and the remaining buffer locations
+ * contain the quantized AC coefficients. Each group of eight row
+ * buffer elements combined with one element eight elements ahead
+ * contains the coefficient predictors of the neighboring block
+ * that is spatially above or to the left of the block currently to
+ * be decoded. A negative-valued DC coefficient indicates that this
+ * neighboring block is not INTRA-coded or out of bounds, and
+ * therefore the AC and DC coefficients are invalid. Pointer must
+ * be aligned on an 8-byte boundary.
+ * pPredBufCol - pointer to the prediction coefficient column buffer
+ * containing 16 elements of type OMX_S16. Coefficients are
+ * organized as described in section 6.2.2.5. Pointer must be
+ * aligned on an 8-byte boundary.
+ * pSumErr - pointer to a flag indicating whether or not AC prediction is
+ * required; AC prediction is enabled if *pSumErr >=0, but the
+ * value is not used for coefficient prediction, i.e., the sum of
+ * absolute differences starts from 0 for each call to this
+ * function. Otherwise AC prediction is disabled if *pSumErr < 0 .
+ * blockIndex - block index indicating the component type and position, as
+ * defined in [ISO14496-2], subclause 6.1.3.8.
+ * curQp - quantization parameter of the macroblock to which the current
+ * block belongs
+ * pQpBuf - pointer to a 2-element quantization parameter buffer; pQpBuf[0]
+ * contains the quantization parameter associated with the 8x8
+ * block left of the current block (QPa), and pQpBuf[1] contains
+ * the quantization parameter associated with the 8x8 block above
+ * the current block (QPc). In the event that the corresponding
+ * block is outside of the VOP bound, the Qp value will not affect
+ * the intra prediction process, as described in [ISO14496-2],
+ * sub-clause 7.4.3.3, Adaptive AC Coefficient Prediction.
+ * srcStep - width of the source buffer; must be a multiple of 8.
+ * dstStep - width of the reconstructed destination buffer; must be a
+ * multiple of 16.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the quantized DCT coefficient buffer; pDst[0] contains
+ * the predicted DC coefficient; the remaining entries contain the
+ * quantized AC coefficients (without prediction). The pointer
+ * pDstmust be aligned on a 16-byte boundary.
+ * pRec - pointer to the reconstructed texture; must be aligned on an
+ * 8-byte boundary.
+ * pPredBufRow - pointer to the updated coefficient row buffer
+ * pPredBufCol - pointer to the updated coefficient column buffer
+ * pPreACPredict - if prediction is enabled, the parameter points to the
+ * start of the buffer containing the coefficient differences for
+ * VLC encoding. The entry pPreACPredict[0]indicates prediction
+ * direction for the current block and takes one of the following
+ * values: OMX_VC_NONE (prediction disabled), OMX_VC_HORIZONTAL, or
+ * OMX_VC_VERTICAL. The entries
+ * pPreACPredict[1]-pPreACPredict[7]contain predicted AC
+ * coefficients. If prediction is disabled (*pSumErr<0) then the
+ * contents of this buffer are undefined upon return from the
+ * function
+ * pSumErr - pointer to the value of the accumulated AC coefficient errors,
+ * i.e., sum of the absolute differences between predicted and
+ * unpredicted AC coefficients
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ * - At least one of the following pointers is NULL: pSrc, pDst, pRec,
+ * pCoefBufRow, pCoefBufCol, pQpBuf, pPreACPredict, pSumErr.
+ * - blockIndex < 0 or blockIndex >= 10;
+ * - curQP <= 0 or curQP >= 32.
+ * - srcStep, or dstStep <= 0 or not a multiple of 8.
+ * - pDst is not 16-byte aligned: .
+ * - At least one of the following pointers is not 8-byte aligned:
+ * pSrc, pRec.
+ *
+ * Note: The coefficient buffers must be updated in accordance with the
+ * update procedures defined in section in 6.2.2.
+ *
+ */
+OMXResult omxVCM4P2_TransRecBlockCoef_intra (
+ const OMX_U8 *pSrc,
+ OMX_S16 *pDst,
+ OMX_U8 *pRec,
+ OMX_S16 *pPredBufRow,
+ OMX_S16 *pPredBufCol,
+ OMX_S16 *pPreACPredict,
+ OMX_INT *pSumErr,
+ OMX_INT blockIndex,
+ OMX_U8 curQp,
+ const OMX_U8 *pQpBuf,
+ OMX_INT srcStep,
+ OMX_INT dstStep,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_TransRecBlockCoef_inter (6.2.4.4.5)
+ *
+ * Description:
+ * Implements DCT, and quantizes the DCT coefficients of the inter block
+ * while reconstructing the texture residual. There is no boundary check for
+ * the bit stream buffer.
+ *
+ * Input Arguments:
+ *
+ * pSrc -pointer to the residuals to be encoded; must be aligned on an
+ * 16-byte boundary.
+ * QP - quantization parameter.
+ * shortVideoHeader - binary flag indicating presence of short_video_header;
+ * shortVideoHeader==1 selects linear intra DC mode, and
+ * shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the quantized DCT coefficients buffer; must be aligned
+ * on a 16-byte boundary.
+ * pRec - pointer to the reconstructed texture residuals; must be aligned
+ * on a 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is either NULL or
+ * not 16-byte aligned:
+ * - pSrc
+ * - pDst
+ * - pRec
+ * - QP <= 0 or QP >= 32.
+ *
+ */
+OMXResult omxVCM4P2_TransRecBlockCoef_inter (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst,
+ OMX_S16 *pRec,
+ OMX_U8 QP,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeVLCZigzag_IntraDCVLC (6.2.4.5.2)
+ *
+ * Description:
+ * Performs zigzag scan and VLC encoding of AC and DC coefficients for one
+ * intra block. Two versions of the function (DCVLC and ACVLC) are provided
+ * in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, "Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding".
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the bitstream
+ * pBitOffset - pointer to the bit position in the byte pointed by
+ * *ppBitStream. Valid within 0 to 7.
+ * pQDctBlkCoef - pointer to the quantized DCT coefficient
+ * predDir - AC prediction direction, which is used to decide the zigzag
+ * scan pattern; takes one of the following values:
+ * - OMX_VC_NONE - AC prediction not used.
+ * Performs classical zigzag scan.
+ * - OMX_VC_HORIZONTAL - Horizontal prediction.
+ * Performs alternate-vertical zigzag scan.
+ * - OMX_VC_VERTICAL - Vertical prediction.
+ * Performs alternate-horizontal zigzag scan.
+ * pattern - block pattern which is used to decide whether this block is
+ * encoded
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ * videoComp - video component type (luminance, chrominance) of the current
+ * block
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is encoded, so
+ * that it points to the current byte in the bit stream buffer.
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ * - At least one of the following pointers is NULL: ppBitStream,
+ * *ppBitStream, pBitOffset, pQDctBlkCoef.
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ * - PredDir is not one of: OMX_VC_NONE, OMX_VC_HORIZONTAL, or
+ * OMX_VC_VERTICAL.
+ * - VideoComp is not one component of enum OMXVCM4P2VideoComponent.
+ *
+ */
+OMXResult omxVCM4P2_EncodeVLCZigzag_IntraDCVLC (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 predDir,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader,
+ OMXVCM4P2VideoComponent videoComp
+);
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeVLCZigzag_IntraACVLC (6.2.4.5.2)
+ *
+ * Description:
+ * Performs zigzag scan and VLC encoding of AC and DC coefficients for one
+ * intra block. Two versions of the function (DCVLC and ACVLC) are provided
+ * in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the bitstream
+ * pBitOffset - pointer to the bit position in the byte pointed by
+ * *ppBitStream. Valid within 0 to 7.
+ * pQDctBlkCoef - pointer to the quantized DCT coefficient
+ * predDir - AC prediction direction, which is used to decide the zigzag
+ * scan pattern; takes one of the following values:
+ * - OMX_VC_NONE - AC prediction not used.
+ * Performs classical zigzag scan.
+ * - OMX_VC_HORIZONTAL - Horizontal prediction.
+ * Performs alternate-vertical zigzag scan.
+ * - OMX_VC_VERTICAL - Vertical prediction.
+ * Performs alternate-horizontal zigzag scan.
+ * pattern - block pattern which is used to decide whether this block is
+ * encoded
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is encoded, so
+ * that it points to the current byte in the bit stream buffer.
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ * - At least one of the following pointers is NULL: ppBitStream,
+ * *ppBitStream, pBitOffset, pQDctBlkCoef.
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ * - PredDir is not one of: OMX_VC_NONE, OMX_VC_HORIZONTAL, or
+ * OMX_VC_VERTICAL.
+ * - VideoComp is not one component of enum OMXVCM4P2VideoComponent.
+ *
+ */
+OMXResult omxVCM4P2_EncodeVLCZigzag_IntraACVLC (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 predDir,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeVLCZigzag_Inter (6.2.4.5.3)
+ *
+ * Description:
+ * Performs classical zigzag scanning and VLC encoding for one inter block.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream
+ * pBitOffset - pointer to the bit position in the byte pointed by
+ * *ppBitStream. Valid within 0 to 7
+ * pQDctBlkCoef - pointer to the quantized DCT coefficient
+ * pattern - block pattern which is used to decide whether this block is
+ * encoded
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is encoded so that
+ * it points to the current byte in the bit stream buffer.
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments
+ * - At least one of the pointers: is NULL: ppBitStream, *ppBitStream,
+ * pBitOffset, pQDctBlkCoef
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ *
+ */
+OMXResult omxVCM4P2_EncodeVLCZigzag_Inter (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeMV (6.2.4.5.4)
+ *
+ * Description:
+ * Predicts a motion vector for the current macroblock, encodes the
+ * difference, and writes the output to the stream buffer. The input MVs
+ * pMVCurMB, pSrcMVLeftMB, pSrcMVUpperMB, and pSrcMVUpperRightMB should lie
+ * within the ranges associated with the input parameter fcodeForward, as
+ * described in [ISO14496-2], subclause 7.6.3. This function provides a
+ * superset of the functionality associated with the function
+ * omxVCM4P2_FindMVpred.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the bitstream buffer
+ * pBitOffset - index of the first free (next available) bit in the stream
+ * buffer referenced by *ppBitStream, valid in the range 0 to 7.
+ * pMVCurMB - pointer to the current macroblock motion vector; a value of
+ * NULL indicates unavailability.
+ * pSrcMVLeftMB - pointer to the source left macroblock motion vector; a
+ * value of NULLindicates unavailability.
+ * pSrcMVUpperMB - pointer to source upper macroblock motion vector; a
+ * value of NULL indicates unavailability.
+ * pSrcMVUpperRightMB - pointer to source upper right MB motion vector; a
+ * value of NULL indicates unavailability.
+ * fcodeForward - an integer with values from 1 to 7; used in encoding
+ * motion vectors related to search range, as described in
+ * [ISO14496-2], subclause 7.6.3.
+ * MBType - macro block type, valid in the range 0 to 5
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - updated pointer to the current byte in the bit stream
+ * buffer
+ * pBitOffset - updated index of the next available bit position in stream
+ * buffer referenced by *ppBitStream
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - At least one of the following pointers is NULL: ppBitStream,
+ * *ppBitStream, pBitOffset, pMVCurMB
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ * - fcodeForward <= 0, or fcodeForward > 7, or MBType < 0.
+ *
+ */
+OMXResult omxVCM4P2_EncodeMV (
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMXVCMotionVector *pMVCurMB,
+ const OMXVCMotionVector*pSrcMVLeftMB,
+ const OMXVCMotionVector *pSrcMVUpperMB,
+ const OMXVCMotionVector *pSrcMVUpperRightMB,
+ OMX_INT fcodeForward,
+ OMXVCM4P2MacroblockType MBType
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodePadMV_PVOP (6.2.5.1.1)
+ *
+ * Description:
+ * Decodes and pads the four motion vectors associated with a non-intra P-VOP
+ * macroblock. For macroblocks of type OMX_VC_INTER4V, the output MV is
+ * padded as specified in [ISO14496-2], subclause 7.6.1.6. Otherwise, for
+ * macroblocks of types other than OMX_VC_INTER4V, the decoded MV is copied to
+ * all four output MV buffer entries.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream buffer
+ * pBitOffset - pointer to the bit position in the byte pointed to by
+ * *ppBitStream. *pBitOffset is valid within [0-7].
+ * pSrcMVLeftMB, pSrcMVUpperMB, and pSrcMVUpperRightMB - pointers to the
+ * motion vector buffers of the macroblocks specially at the left,
+ * upper, and upper-right side of the current macroblock,
+ * respectively; a value of NULL indicates unavailability. Note:
+ * Any neighborhood macroblock outside the current VOP or video
+ * packet or outside the current GOB (when short_video_header is
+ * 1 ) for which gob_header_empty is 0 is treated as
+ * transparent, according to [ISO14496-2], subclause 7.6.5.
+ * fcodeForward - a code equal to vop_fcode_forward in MPEG-4 bit stream
+ * syntax
+ * MBType - the type of the current macroblock. If MBType is not equal to
+ * OMX_VC_INTER4V, the destination motion vector buffer is still
+ * filled with the same decoded vector.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded, so
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream
+ * pDstMVCurMB - pointer to the motion vector buffer for the current
+ * macroblock; contains four decoded motion vectors
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pDstMVCurMB
+ * - *pBitOffset exceeds [0,7]
+ * - fcodeForward exceeds (0,7]
+ * - MBType less than zero
+ * - motion vector buffer is not 4-byte aligned.
+ * OMX_Sts_Err - status error
+ *
+ */
+OMXResult omxVCM4P2_DecodePadMV_PVOP (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMXVCMotionVector *pSrcMVLeftMB,
+ OMXVCMotionVector*pSrcMVUpperMB,
+ OMXVCMotionVector *pSrcMVUpperRightMB,
+ OMXVCMotionVector*pDstMVCurMB,
+ OMX_INT fcodeForward,
+ OMXVCM4P2MacroblockType MBType
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeVLCZigzag_IntraDCVLC (6.2.5.2.2)
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan of AC and DC coefficients
+ * for one intra block. Two versions of the function (DCVLC and ACVLC) are
+ * provided in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the
+ * bitstream buffer
+ * pBitOffset - pointer to the bit position in the current byte referenced
+ * by *ppBitStream. The parameter *pBitOffset is valid in the
+ * range [0-7].
+ * Bit Position in one byte: |Most Least|
+ * *pBitOffset |0 1 2 3 4 5 6 7|
+ * predDir - AC prediction direction; used to select the zigzag scan
+ * pattern; takes one of the following values:
+ * - OMX_VC_NONE - AC prediction not used;
+ * performs classical zigzag scan.
+ * - OMX_VC_HORIZONTAL - Horizontal prediction;
+ * performs alternate-vertical zigzag scan;
+ * - OMX_VC_VERTICAL - Vertical prediction;
+ * performs alternate-horizontal zigzag scan.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ * videoComp - video component type (luminance or chrominance) of the
+ * current block
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded such
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated such that it points to the current
+ * bit position in the byte pointed by *ppBitStream
+ * pDst - pointer to the coefficient buffer of current block; must be
+ * 4-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pDst
+ * - *pBitOffset exceeds [0,7]
+ * - preDir exceeds [0,2]
+ * - pDst is not 4-byte aligned
+ * OMX_Sts_Err - if:
+ * - In DecodeVLCZigzag_IntraDCVLC, dc_size > 12
+ * - At least one of mark bits equals zero
+ * - Illegal stream encountered; code cannot be located in VLC table
+ * - Forbidden code encountered in the VLC FLC table.
+ * - The number of coefficients is greater than 64
+ *
+ */
+OMXResult omxVCM4P2_DecodeVLCZigzag_IntraDCVLC (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_S16 *pDst,
+ OMX_U8 predDir,
+ OMX_INT shortVideoHeader,
+ OMXVCM4P2VideoComponent videoComp
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeVLCZigzag_IntraACVLC (6.2.5.2.2)
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan of AC and DC coefficients
+ * for one intra block. Two versions of the function (DCVLC and ACVLC) are
+ * provided in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the
+ * bitstream buffer
+ * pBitOffset - pointer to the bit position in the current byte referenced
+ * by *ppBitStream. The parameter *pBitOffset is valid in the
+ * range [0-7]. Bit Position in one byte: |Most Least| *pBitOffset
+ * |0 1 2 3 4 5 6 7|
+ * predDir - AC prediction direction; used to select the zigzag scan
+ * pattern; takes one of the following values: OMX_VC_NONE - AC
+ * prediction not used; performs classical zigzag scan.
+ * OMX_VC_HORIZONTAL - Horizontal prediction; performs
+ * alternate-vertical zigzag scan; OMX_VC_VERTICAL - Vertical
+ * prediction; performs alternate-horizontal zigzag scan.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ * videoComp - video component type (luminance or chrominance) of the
+ * current block
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded such
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated such that it points to the current
+ * bit position in the byte pointed by *ppBitStream
+ * pDst - pointer to the coefficient buffer of current block; must be
+ * 4-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments At least one of the following
+ * pointers is NULL: ppBitStream, *ppBitStream, pBitOffset, pDst,
+ * or At least one of the following conditions is true:
+ * *pBitOffset exceeds [0,7], preDir exceeds [0,2], or pDst is
+ * not 4-byte aligned
+ * OMX_Sts_Err In DecodeVLCZigzag_IntraDCVLC, dc_size > 12 At least one of
+ * mark bits equals zero Illegal stream encountered; code cannot
+ * be located in VLC table Forbidden code encountered in the VLC
+ * FLC table The number of coefficients is greater than 64
+ *
+ */
+OMXResult omxVCM4P2_DecodeVLCZigzag_IntraACVLC (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_S16 *pDst,
+ OMX_U8 predDir,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeVLCZigzag_Inter (6.2.5.2.3)
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan for one inter-coded block.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the stream buffer
+ * pBitOffset - pointer to the next available bit in the current stream
+ * byte referenced by *ppBitStream. The parameter *pBitOffset is
+ * valid within the range [0-7].
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded such
+ * that it points to the current byte in the stream buffer
+ * pBitOffset - *pBitOffset is updated after decoding such that it points
+ * to the next available bit in the stream byte referenced by
+ * *ppBitStream
+ * pDst - pointer to the coefficient buffer of current block; must be
+ * 4-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pDst
+ * - pDst is not 4-byte aligned
+ * - *pBitOffset exceeds [0,7]
+ * OMX_Sts_Err - status error, if:
+ * - At least one mark bit is equal to zero
+ * - Encountered an illegal stream code that cannot be found in the VLC table
+ * - Encountered an illegal code in the VLC FLC table
+ * - The number of coefficients is greater than 64
+ *
+ */
+OMXResult omxVCM4P2_DecodeVLCZigzag_Inter (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_S16 *pDst,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_QuantInvIntra_I (6.2.5.3.2)
+ *
+ * Description:
+ * Performs the second inverse quantization mode on an intra/inter coded
+ * block. Supports bits_per_pixel = 8. The output coefficients are clipped to
+ * the range [-2048, 2047].
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input (quantized) intra/inter block; must be
+ * aligned on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale)
+ * videoComp - video component type of the current block. Takes one of the
+ * following flags: OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE (intra
+ * version only).
+ * shortVideoHeader - binary flag indicating presence of short_video_header
+ * (intra version only).
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (dequantized) intra/inter block
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; one or more of the following is
+ * true:
+ * - pSrcDst is NULL
+ * - QP <= 0 or QP >=31
+ * - videoComp is neither OMX_VC_LUMINANCE nor OMX_VC_CHROMINANCE.
+ *
+ */
+OMXResult omxVCM4P2_QuantInvIntra_I (
+ OMX_S16 *pSrcDst,
+ OMX_INT QP,
+ OMXVCM4P2VideoComponent videoComp,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_QuantInvInter_I (6.2.5.3.2)
+ *
+ * Description:
+ * Performs the second inverse quantization mode on an intra/inter coded
+ * block. Supports bits_per_pixel = 8. The output coefficients are clipped to
+ * the range [-2048, 2047].
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input (quantized) intra/inter block; must be
+ * aligned on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale)
+ * videoComp - video component type of the current block. Takes one of the
+ * following flags: OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE (intra
+ * version only).
+ * shortVideoHeader - binary flag indicating presence of short_video_header
+ * (intra version only).
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (dequantized) intra/inter block
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; one or more of the following is
+ * true:
+ * - pSrcDst is NULL
+ * - QP <= 0 or QP >=31
+ * - videoComp is neither OMX_VC_LUMINANCE nor OMX_VC_CHROMINANCE.
+ *
+ */
+OMXResult omxVCM4P2_QuantInvInter_I (
+ OMX_S16 *pSrcDst,
+ OMX_INT QP
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeBlockCoef_Intra (6.2.5.4.1)
+ *
+ * Description:
+ * Decodes the INTRA block coefficients. Inverse quantization, inversely
+ * zigzag positioning, and IDCT, with appropriate clipping on each step, are
+ * performed on the coefficients. The results are then placed in the output
+ * frame/plane on a pixel basis. Note: This function will be used only when
+ * at least one non-zero AC coefficient of current block exists in the bit
+ * stream. The DC only condition will be handled in another function.
+ *
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream buffer. There is no boundary check for the bit stream
+ * buffer.
+ * pBitOffset - pointer to the bit position in the byte pointed to by
+ * *ppBitStream. *pBitOffset is valid within [0-7].
+ * step - width of the destination plane
+ * pCoefBufRow - pointer to the coefficient row buffer; must be aligned on
+ * an 8-byte boundary.
+ * pCoefBufCol - pointer to the coefficient column buffer; must be aligned
+ * on an 8-byte boundary.
+ * curQP - quantization parameter of the macroblock which the current block
+ * belongs to
+ * pQPBuf - pointer to the quantization parameter buffer
+ * blockIndex - block index indicating the component type and position as
+ * defined in [ISO14496-2], subclause 6.1.3.8, Figure 6-5.
+ * intraDCVLC - a code determined by intra_dc_vlc_thr and QP. This allows a
+ * mechanism to switch between two VLC for coding of Intra DC
+ * coefficients as per [ISO14496-2], Table 6-21.
+ * ACPredFlag - a flag equal to ac_pred_flag (of luminance) indicating if
+ * the ac coefficients of the first row or first column are
+ * differentially coded for intra coded macroblock.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded, so
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream
+ * pDst - pointer to the block in the destination plane; must be aligned on
+ * an 8-byte boundary.
+ * pCoefBufRow - pointer to the updated coefficient row buffer.
+ * pCoefBufCol - pointer to the updated coefficient column buffer Note:
+ * The coefficient buffers must be updated in accordance with the
+ * update procedure defined in section 6.2.2.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pCoefBufRow, pCoefBufCol,
+ * pQPBuf, pDst.
+ * - *pBitOffset exceeds [0,7]
+ * - curQP exceeds (1, 31)
+ * - blockIndex exceeds [0,5]
+ * - step is not the multiple of 8
+ * - a pointer alignment requirement was violated.
+ * OMX_Sts_Err - status error. Refer to OMX_Sts_Err of DecodeVLCZigzag_Intra.
+ *
+ */
+OMXResult omxVCM4P2_DecodeBlockCoef_Intra (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_U8 *pDst,
+ OMX_INT step,
+ OMX_S16 *pCoefBufRow,
+ OMX_S16 *pCoefBufCol,
+ OMX_U8 curQP,
+ const OMX_U8 *pQPBuf,
+ OMX_INT blockIndex,
+ OMX_INT intraDCVLC,
+ OMX_INT ACPredFlag,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeBlockCoef_Inter (6.2.5.4.2)
+ *
+ * Description:
+ * Decodes the INTER block coefficients. This function performs inverse
+ * quantization, inverse zigzag positioning, and IDCT (with appropriate
+ * clipping on each step) on the coefficients. The results (residuals) are
+ * placed in a contiguous array of 64 elements. For INTER block, the output
+ * buffer holds the residuals for further reconstruction.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream buffer. There is no boundary check for the bit stream
+ * buffer.
+ * pBitOffset - pointer to the bit position in the byte pointed to by
+ * *ppBitStream. *pBitOffset is valid within [0-7]
+ * QP - quantization parameter
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded, so
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream
+ * pDst - pointer to the decoded residual buffer (a contiguous array of 64
+ * elements of OMX_S16 data type); must be aligned on a 16-byte
+ * boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the following pointers is Null:
+ * ppBitStream, *ppBitStream, pBitOffset , pDst
+ * - *pBitOffset exceeds [0,7]
+ * - QP <= 0.
+ * - pDst is not 16-byte aligned
+ * OMX_Sts_Err - status error. Refer to OMX_Sts_Err of DecodeVLCZigzag_Inter .
+ *
+ */
+OMXResult omxVCM4P2_DecodeBlockCoef_Inter (
+ const OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_S16 *pDst,
+ OMX_INT QP,
+ OMX_INT shortVideoHeader
+);
+
+
+
+/**
+ * Function: omxVCM4P2_PredictReconCoefIntra (6.2.5.4.3)
+ *
+ * Description:
+ * Performs adaptive DC/AC coefficient prediction for an intra block. Prior
+ * to the function call, prediction direction (predDir) should be selected as
+ * specified in [ISO14496-2], subclause 7.4.3.1.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the coefficient buffer which contains the quantized
+ * coefficient residuals (PQF) of the current block; must be
+ * aligned on a 4-byte boundary. The output coefficients are
+ * saturated to the range [-2048, 2047].
+ * pPredBufRow - pointer to the coefficient row buffer; must be aligned on
+ * a 4-byte boundary.
+ * pPredBufCol - pointer to the coefficient column buffer; must be aligned
+ * on a 4-byte boundary.
+ * curQP - quantization parameter of the current block. curQP may equal to
+ * predQP especially when the current block and the predictor block
+ * are in the same macroblock.
+ * predQP - quantization parameter of the predictor block
+ * predDir - indicates the prediction direction which takes one of the
+ * following values: OMX_VC_HORIZONTAL - predict horizontally
+ * OMX_VC_VERTICAL - predict vertically
+ * ACPredFlag - a flag indicating if AC prediction should be performed. It
+ * is equal to ac_pred_flag in the bit stream syntax of MPEG-4
+ * videoComp - video component type (luminance or chrominance) of the
+ * current block
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the coefficient buffer which contains the quantized
+ * coefficients (QF) of the current block
+ * pPredBufRow - pointer to the updated coefficient row buffer
+ * pPredBufCol - pointer to the updated coefficient column buffer Note:
+ * Buffer update: Update the AC prediction buffer (both row and
+ * column buffer).
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the pointers is NULL:
+ * pSrcDst, pPredBufRow, or pPredBufCol.
+ * - curQP <= 0,
+ * - predQP <= 0,
+ * - curQP >31,
+ * - predQP > 31,
+ * - preDir exceeds [1,2]
+ * - pSrcDst, pPredBufRow, or pPredBufCol is not 4-byte aligned.
+ *
+ */
+OMXResult omxVCM4P2_PredictReconCoefIntra (
+ OMX_S16 *pSrcDst,
+ OMX_S16 *pPredBufRow,
+ OMX_S16 *pPredBufCol,
+ OMX_INT curQP,
+ OMX_INT predQP,
+ OMX_INT predDir,
+ OMX_INT ACPredFlag,
+ OMXVCM4P2VideoComponent videoComp
+);
+
+
+
+/**
+ * Function: omxVCM4P2_MCReconBlock (6.2.5.5.1)
+ *
+ * Description:
+ * Performs motion compensation prediction for an 8x8 block using
+ * interpolation described in [ISO14496-2], subclause 7.6.2.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the block in the reference plane.
+ * srcStep - distance between the start of consecutive lines in the
+ * reference plane, in bytes; must be a multiple of 8.
+ * dstStep - distance between the start of consecutive lines in the
+ * destination plane, in bytes; must be a multiple of 8.
+ * pSrcResidue - pointer to a buffer containing the 16-bit prediction
+ * residuals; must be 16-byte aligned. If the pointer is NULL, then
+ * no prediction is done, only motion compensation, i.e., the block
+ * is moved with interpolation.
+ * predictType - bilinear interpolation type, as defined in section
+ * 6.2.1.2.
+ * rndVal - rounding control parameter: 0 - disabled; 1 - enabled.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination buffer; must be 8-byte aligned. If
+ * prediction residuals are added then output intensities are
+ * clipped to the range [0,255].
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - pDst is not 8-byte aligned.
+ * - pSrcResidue is not 16-byte aligned.
+ * - one or more of the following pointers is NULL: pSrc or pDst.
+ * - either srcStep or dstStep is not a multiple of 8.
+ * - invalid type specified for the parameter predictType.
+ * - the parameter rndVal is not equal either to 0 or 1.
+ *
+ */
+OMXResult omxVCM4P2_MCReconBlock (
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ const OMX_S16 *pSrcResidue,
+ OMX_U8 *pDst,
+ OMX_INT dstStep,
+ OMX_INT predictType,
+ OMX_INT rndVal
+);
+
+
+
+/* 6.3.1.1 Intra 16x16 Prediction Modes */
+/* A data type that enumerates intra_16x16 macroblock prediction modes is defined as follows: */
+
+typedef enum {
+ OMX_VC_16X16_VERT = 0, /** Intra_16x16_Vertical */
+ OMX_VC_16X16_HOR = 1, /** Intra_16x16_Horizontal */
+ OMX_VC_16X16_DC = 2, /** Intra_16x16_DC */
+ OMX_VC_16X16_PLANE = 3 /** Intra_16x16_Plane */
+} OMXVCM4P10Intra16x16PredMode;
+
+
+
+/* 6.3.1.2 Intra 4x4 Prediction Modes */
+/* A data type that enumerates intra_4x4 macroblock prediction modes is defined as follows: */
+
+typedef enum {
+ OMX_VC_4X4_VERT = 0, /** Intra_4x4_Vertical */
+ OMX_VC_4X4_HOR = 1, /** Intra_4x4_Horizontal */
+ OMX_VC_4X4_DC = 2, /** Intra_4x4_DC */
+ OMX_VC_4X4_DIAG_DL = 3, /** Intra_4x4_Diagonal_Down_Left */
+ OMX_VC_4X4_DIAG_DR = 4, /** Intra_4x4_Diagonal_Down_Right */
+ OMX_VC_4X4_VR = 5, /** Intra_4x4_Vertical_Right */
+ OMX_VC_4X4_HD = 6, /** Intra_4x4_Horizontal_Down */
+ OMX_VC_4X4_VL = 7, /** Intra_4x4_Vertical_Left */
+ OMX_VC_4X4_HU = 8 /** Intra_4x4_Horizontal_Up */
+} OMXVCM4P10Intra4x4PredMode;
+
+
+
+/* 6.3.1.3 Chroma Prediction Modes */
+/* A data type that enumerates intra chroma prediction modes is defined as follows: */
+
+typedef enum {
+ OMX_VC_CHROMA_DC = 0, /** Intra_Chroma_DC */
+ OMX_VC_CHROMA_HOR = 1, /** Intra_Chroma_Horizontal */
+ OMX_VC_CHROMA_VERT = 2, /** Intra_Chroma_Vertical */
+ OMX_VC_CHROMA_PLANE = 3 /** Intra_Chroma_Plane */
+} OMXVCM4P10IntraChromaPredMode;
+
+
+
+/* 6.3.1.4 Motion Estimation Modes */
+/* A data type that enumerates H.264 motion estimation modes is defined as follows: */
+
+typedef enum {
+ OMX_VC_M4P10_FAST_SEARCH = 0, /** Fast motion search */
+ OMX_VC_M4P10_FULL_SEARCH = 1 /** Full motion search */
+} OMXVCM4P10MEMode;
+
+
+
+/* 6.3.1.5 Macroblock Types */
+/* A data type that enumerates H.264 macroblock types is defined as follows: */
+
+typedef enum {
+ OMX_VC_P_16x16 = 0, /* defined by [ISO14496-10] */
+ OMX_VC_P_16x8 = 1,
+ OMX_VC_P_8x16 = 2,
+ OMX_VC_P_8x8 = 3,
+ OMX_VC_PREF0_8x8 = 4,
+ OMX_VC_INTER_SKIP = 5,
+ OMX_VC_INTRA_4x4 = 8,
+ OMX_VC_INTRA_16x16 = 9,
+ OMX_VC_INTRA_PCM = 10
+} OMXVCM4P10MacroblockType;
+
+
+
+/* 6.3.1.6 Sub-Macroblock Types */
+/* A data type that enumerates H.264 sub-macroblock types is defined as follows: */
+
+typedef enum {
+ OMX_VC_SUB_P_8x8 = 0, /* defined by [ISO14496-10] */
+ OMX_VC_SUB_P_8x4 = 1,
+ OMX_VC_SUB_P_4x8 = 2,
+ OMX_VC_SUB_P_4x4 = 3
+} OMXVCM4P10SubMacroblockType;
+
+
+
+/* 6.3.1.7 Variable Length Coding (VLC) Information */
+
+typedef struct {
+ OMX_U8 uTrailing_Ones; /* Trailing ones; 3 at most */
+ OMX_U8 uTrailing_One_Signs; /* Trailing ones signal */
+ OMX_U8 uNumCoeffs; /* Total number of non-zero coefs, including trailing ones */
+ OMX_U8 uTotalZeros; /* Total number of zero coefs */
+ OMX_S16 iLevels[16]; /* Levels of non-zero coefs, in reverse zig-zag order */
+ OMX_U8 uRuns[16]; /* Runs for levels and trailing ones, in reverse zig-zag order */
+} OMXVCM4P10VLCInfo;
+
+
+
+/* 6.3.1.8 Macroblock Information */
+
+typedef struct {
+ OMX_S32 sliceId; /* slice number */
+ OMXVCM4P10MacroblockType mbType; /* MB type */
+ OMXVCM4P10SubMacroblockType subMBType[4]; /* sub-block type */
+ OMX_S32 qpy; /* qp for luma */
+ OMX_S32 qpc; /* qp for chroma */
+ OMX_U32 cbpy; /* CBP Luma */
+ OMX_U32 cbpc; /* CBP Chroma */
+ OMXVCMotionVector pMV0[4][4]; /* motion vector, represented using 1/4-pel units, pMV0[blocky][blockx] (blocky = 0~3, blockx =0~3) */
+ OMXVCMotionVector pMVPred[4][4]; /* motion vector prediction, Represented using 1/4-pel units, pMVPred[blocky][blockx] (blocky = 0~3, blockx = 0~3) */
+ OMX_U8 pRefL0Idx[4]; /* reference picture indices */
+ OMXVCM4P10Intra16x16PredMode Intra16x16PredMode; /* best intra 16x16 prediction mode */
+ OMXVCM4P10Intra4x4PredMode pIntra4x4PredMode[16]; /* best intra 4x4 prediction mode for each block, pMV0 indexed as above */
+} OMXVCM4P10MBInfo, *OMXVCM4P10MBInfoPtr;
+
+
+
+/* 6.3.1.9 Motion Estimation Parameters */
+
+typedef struct {
+ OMX_S32 blockSplitEnable8x8; /* enables 16x8, 8x16, 8x8 */
+ OMX_S32 blockSplitEnable4x4; /* enable splitting of 8x4, 4x8, 4x4 blocks */
+ OMX_S32 halfSearchEnable;
+ OMX_S32 quarterSearchEnable;
+ OMX_S32 intraEnable4x4; /* 1=enable, 0=disable */
+ OMX_S32 searchRange16x16; /* integer pixel units */
+ OMX_S32 searchRange8x8;
+ OMX_S32 searchRange4x4;
+} OMXVCM4P10MEParams;
+
+
+
+/**
+ * Function: omxVCM4P10_PredictIntra_4x4 (6.3.3.1.1)
+ *
+ * Description:
+ * Perform Intra_4x4 prediction for luma samples. If the upper-right block is
+ * not available, then duplication work should be handled inside the function.
+ * Users need not define them outside.
+ *
+ * Input Arguments:
+ *
+ * pSrcLeft - Pointer to the buffer of 4 left pixels:
+ * p[x, y] (x = -1, y = 0..3)
+ * pSrcAbove - Pointer to the buffer of 8 above pixels:
+ * p[x,y] (x = 0..7, y =-1);
+ * must be aligned on a 4-byte boundary.
+ * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
+ * leftStep - Step of left pixel buffer; must be a multiple of 4.
+ * dstStep - Step of the destination buffer; must be a multiple of 4.
+ * predMode - Intra_4x4 prediction mode.
+ * availability - Neighboring 4x4 block availability flag, refer to
+ * "Neighboring Macroblock Availability" .
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to the destination buffer; must be aligned on a 4-byte
+ * boundary.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pDst is NULL.
+ * dstStep < 4, or dstStep is not a multiple of 4.
+ * leftStep is not a multiple of 4.
+ * predMode is not in the valid range of enumeration
+ * OMXVCM4P10Intra4x4PredMode.
+ * predMode is OMX_VC_4x4_VERT, but availability doesn't set OMX_VC_UPPER
+ * indicating p[x,-1] (x = 0..3) is not available.
+ * predMode is OMX_VC_4x4_HOR, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..3) is not available.
+ * predMode is OMX_VC_4x4_DIAG_DL, but availability doesn't set
+ * OMX_VC_UPPER indicating p[x, -1] (x = 0..3) is not available.
+ * predMode is OMX_VC_4x4_DIAG_DR, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
+ * available.
+ * predMode is OMX_VC_4x4_VR, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
+ * available.
+ * predMode is OMX_VC_4x4_HD, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
+ * available.
+ * predMode is OMX_VC_4x4_VL, but availability doesn't set OMX_VC_UPPER
+ * indicating p[x,-1] (x = 0..3) is not available.
+ * predMode is OMX_VC_4x4_HU, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..3) is not available.
+ * availability sets OMX_VC_UPPER, but pSrcAbove is NULL.
+ * availability sets OMX_VC_LEFT, but pSrcLeft is NULL.
+ * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL.
+ * either pSrcAbove or pDst is not aligned on a 4-byte boundary.
+ *
+ * Note:
+ * pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointers if
+ * they are not used by intra prediction as implied in predMode.
+ *
+ */
+OMXResult omxVCM4P10_PredictIntra_4x4 (
+ const OMX_U8 *pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ const OMX_U8 *pSrcAboveLeft,
+ OMX_U8 *pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMXVCM4P10Intra4x4PredMode predMode,
+ OMX_S32 availability
+);
+
+
+
+/**
+ * Function: omxVCM4P10_PredictIntra_16x16 (6.3.3.1.2)
+ *
+ * Description:
+ * Perform Intra_16x16 prediction for luma samples. If the upper-right block
+ * is not available, then duplication work should be handled inside the
+ * function. Users need not define them outside.
+ *
+ * Input Arguments:
+ *
+ * pSrcLeft - Pointer to the buffer of 16 left pixels: p[x, y] (x = -1, y =
+ * 0..15)
+ * pSrcAbove - Pointer to the buffer of 16 above pixels: p[x,y] (x = 0..15,
+ * y= -1); must be aligned on a 16-byte boundary.
+ * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
+ * leftStep - Step of left pixel buffer; must be a multiple of 16.
+ * dstStep - Step of the destination buffer; must be a multiple of 16.
+ * predMode - Intra_16x16 prediction mode, please refer to section 3.4.1.
+ * availability - Neighboring 16x16 MB availability flag. Refer to
+ * section 3.4.4.
+ *
+ * Output Arguments:
+ *
+ * pDst -Pointer to the destination buffer; must be aligned on a 16-byte
+ * boundary.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pDst is NULL.
+ * dstStep < 16. or dstStep is not a multiple of 16.
+ * leftStep is not a multiple of 16.
+ * predMode is not in the valid range of enumeration
+ * OMXVCM4P10Intra16x16PredMode
+ * predMode is OMX_VC_16X16_VERT, but availability doesn't set
+ * OMX_VC_UPPER indicating p[x,-1] (x = 0..15) is not available.
+ * predMode is OMX_VC_16X16_HOR, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..15) is not available.
+ * predMode is OMX_VC_16X16_PLANE, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1](x = 0..15), or p[-1,y] (y = 0..15), or p[-1,-1] is not
+ * available.
+ * availability sets OMX_VC_UPPER, but pSrcAbove is NULL.
+ * availability sets OMX_VC_LEFT, but pSrcLeft is NULL.
+ * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL.
+ * either pSrcAbove or pDst is not aligned on a 16-byte boundary.
+ *
+ * Note:
+ * pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointers if
+ * they are not used by intra prediction implied in predMode.
+ * Note:
+ * OMX_VC_UPPER_RIGHT is not used in intra_16x16 luma prediction.
+ *
+ */
+OMXResult omxVCM4P10_PredictIntra_16x16 (
+ const OMX_U8 *pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ const OMX_U8 *pSrcAboveLeft,
+ OMX_U8 *pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMXVCM4P10Intra16x16PredMode predMode,
+ OMX_S32 availability
+);
+
+
+
+/**
+ * Function: omxVCM4P10_PredictIntraChroma_8x8 (6.3.3.1.3)
+ *
+ * Description:
+ * Performs intra prediction for chroma samples.
+ *
+ * Input Arguments:
+ *
+ * pSrcLeft - Pointer to the buffer of 8 left pixels: p[x, y] (x = -1, y=
+ * 0..7).
+ * pSrcAbove - Pointer to the buffer of 8 above pixels: p[x,y] (x = 0..7, y
+ * = -1); must be aligned on an 8-byte boundary.
+ * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
+ * leftStep - Step of left pixel buffer; must be a multiple of 8.
+ * dstStep - Step of the destination buffer; must be a multiple of 8.
+ * predMode - Intra chroma prediction mode, please refer to section 3.4.3.
+ * availability - Neighboring chroma block availability flag, please refer
+ * to "Neighboring Macroblock Availability".
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to the destination buffer; must be aligned on an 8-byte
+ * boundary.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If any of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pDst is NULL.
+ * dstStep < 8 or dstStep is not a multiple of 8.
+ * leftStep is not a multiple of 8.
+ * predMode is not in the valid range of enumeration
+ * OMXVCM4P10IntraChromaPredMode.
+ * predMode is OMX_VC_CHROMA_VERT, but availability doesn't set
+ * OMX_VC_UPPER indicating p[x,-1] (x = 0..7) is not available.
+ * predMode is OMX_VC_CHROMA_HOR, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..7) is not available.
+ * predMode is OMX_VC_CHROMA_PLANE, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1](x = 0..7), or p[-1,y] (y = 0..7), or p[-1,-1] is not
+ * available.
+ * availability sets OMX_VC_UPPER, but pSrcAbove is NULL.
+ * availability sets OMX_VC_LEFT, but pSrcLeft is NULL.
+ * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL.
+ * either pSrcAbove or pDst is not aligned on a 8-byte boundary.
+ *
+ * Note: pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointer if
+ * they are not used by intra prediction implied in predMode.
+ *
+ * Note: OMX_VC_UPPER_RIGHT is not used in intra chroma prediction.
+ *
+ */
+OMXResult omxVCM4P10_PredictIntraChroma_8x8 (
+ const OMX_U8 *pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ const OMX_U8 *pSrcAboveLeft,
+ OMX_U8 *pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMXVCM4P10IntraChromaPredMode predMode,
+ OMX_S32 availability
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InterpolateLuma (6.3.3.2.1)
+ *
+ * Description:
+ * Performs quarter-pixel interpolation for inter luma MB. It is assumed that
+ * the frame is already padded when calling this function.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the source reference frame buffer
+ * srcStep - reference frame step, in bytes; must be a multiple of roi.width
+ * dstStep - destination frame step, in bytes; must be a multiple of
+ * roi.width
+ * dx - Fractional part of horizontal motion vector component in 1/4 pixel
+ * unit; valid in the range [0,3]
+ * dy - Fractional part of vertical motion vector y component in 1/4 pixel
+ * unit; valid in the range [0,3]
+ * roi - Dimension of the interpolation region; the parameters roi.width and
+ * roi.height must be equal to either 4, 8, or 16.
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to the destination frame buffer:
+ * if roi.width==4, 4-byte alignment required
+ * if roi.width==8, 8-byte alignment required
+ * if roi.width==16, 16-byte alignment required
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pSrc or pDst is NULL.
+ * srcStep or dstStep < roi.width.
+ * dx or dy is out of range [0,3].
+ * roi.width or roi.height is out of range {4, 8, 16}.
+ * roi.width is equal to 4, but pDst is not 4 byte aligned.
+ * roi.width is equal to 8 or 16, but pDst is not 8 byte aligned.
+ * srcStep or dstStep is not a multiple of 8.
+ *
+ */
+OMXResult omxVCM4P10_InterpolateLuma (
+ const OMX_U8 *pSrc,
+ OMX_S32 srcStep,
+ OMX_U8 *pDst,
+ OMX_S32 dstStep,
+ OMX_S32 dx,
+ OMX_S32 dy,
+ OMXSize roi
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InterpolateChroma (6.3.3.2.2)
+ *
+ * Description:
+ * Performs 1/8-pixel interpolation for inter chroma MB.
+ *
+ * Input Arguments:
+ *
+ * pSrc -Pointer to the source reference frame buffer
+ * srcStep -Reference frame step in bytes
+ * dstStep -Destination frame step in bytes; must be a multiple of
+ * roi.width.
+ * dx -Fractional part of horizontal motion vector component in 1/8 pixel
+ * unit; valid in the range [0,7]
+ * dy -Fractional part of vertical motion vector component in 1/8 pixel
+ * unit; valid in the range [0,7]
+ * roi -Dimension of the interpolation region; the parameters roi.width and
+ * roi.height must be equal to either 2, 4, or 8.
+ *
+ * Output Arguments:
+ *
+ * pDst -Pointer to the destination frame buffer:
+ * if roi.width==2, 2-byte alignment required
+ * if roi.width==4, 4-byte alignment required
+ * if roi.width==8, 8-byte alignment required
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pSrc or pDst is NULL.
+ * srcStep or dstStep < 8.
+ * dx or dy is out of range [0-7].
+ * roi.width or roi.height is out of range {2,4,8}.
+ * roi.width is equal to 2, but pDst is not 2-byte aligned.
+ * roi.width is equal to 4, but pDst is not 4-byte aligned.
+ * roi.width is equal to 8, but pDst is not 8 byte aligned.
+ * srcStep or dstStep is not a multiple of 8.
+ *
+ */
+OMXResult omxVCM4P10_InterpolateChroma (
+ const OMX_U8 *pSrc,
+ OMX_S32 srcStep,
+ OMX_U8 *pDst,
+ OMX_S32 dstStep,
+ OMX_S32 dx,
+ OMX_S32 dy,
+ OMXSize roi
+);
+
+
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingLuma_VerEdge_I (6.3.3.3.1)
+ *
+ * Description:
+ * Performs in-place deblock filtering on four vertical edges of the luma
+ * macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the input macroblock; must be 16-byte aligned.
+ * srcdstStep -Step of the arrays; must be a multiple of 16.
+ * pAlpha -Array of size 2 of alpha thresholds (the first item is the alpha
+ * threshold for the external vertical edge, and the second item is
+ * for the internal vertical edge); per [ISO14496-10] alpha values
+ * must be in the range [0,255].
+ * pBeta -Array of size 2 of beta thresholds (the first item is the beta
+ * threshold for the external vertical edge, and the second item is
+ * for the internal vertical edge); per [ISO14496-10] beta values
+ * must be in the range [0,18].
+ * pThresholds -Array of size 16 of Thresholds (TC0) (values for the left
+ * edge of each 4x4 block, arranged in vertical block order); must
+ * be aligned on a 4-byte boundary.. Per [ISO14496-10] values must
+ * be in the range [0,25].
+ * pBS -Array of size 16 of BS parameters (arranged in vertical block
+ * order); valid in the range [0,4] with the following
+ * restrictions: i) pBS[i]== 4 may occur only for 0<=i<=3, ii)
+ * pBS[i]== 4 if and only if pBS[i^3]== 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * Either of the pointers in pSrcDst, pAlpha, pBeta, pThresholds, or pBS
+ * is NULL.
+ * Either pThresholds or pBS is not aligned on a 4-byte boundary.
+ * pSrcDst is not 16-byte aligned.
+ * srcdstStep is not a multiple of 16.
+ * pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * One or more entries in the table pThresholds[0..15]is outside of the
+ * range [0,25].
+ * pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or (pBS[i]==4 &&
+ * pBS[i^3]!=4) for 0<=i<=3.
+ *
+ */
+OMXResult omxVCM4P10_FilterDeblockingLuma_VerEdge_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingLuma_HorEdge_I (6.3.3.3.2)
+ *
+ * Description:
+ * Performs in-place deblock filtering on four horizontal edges of the luma
+ * macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 16-byte aligned.
+ * srcdstStep - step of the arrays; must be a multiple of 16.
+ * pAlpha - array of size 2 of alpha thresholds (the first item is the alpha
+ * threshold for the external vertical edge, and the second item is
+ * for the internal horizontal edge); per [ISO14496-10] alpha
+ * values must be in the range [0,255].
+ * pBeta - array of size 2 of beta thresholds (the first item is the beta
+ * threshold for the external horizontal edge, and the second item
+ * is for the internal horizontal edge). Per [ISO14496-10] beta
+ * values must be in the range [0,18].
+ * pThresholds - array of size 16 containing thresholds, TC0, for the top
+ * horizontal edge of each 4x4 block, arranged in horizontal block
+ * order; must be aligned on a 4-byte boundary. Per [ISO14496 10]
+ * values must be in the range [0,25].
+ * pBS - array of size 16 of BS parameters (arranged in horizontal block
+ * order); valid in the range [0,4] with the following
+ * restrictions: i) pBS[i]== 4 may occur only for 0<=i<=3, ii)
+ * pBS[i]== 4 if and only if pBS[i^3]== 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr, if one of the following cases occurs:
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds, or pBS.
+ * - either pThresholds or pBS is not aligned on a 4-byte boundary.
+ * - pSrcDst is not 16-byte aligned.
+ * - srcdstStep is not a multiple of 16.
+ * - pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * - pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * - One or more entries in the table pThresholds[0..15] is
+ * outside of the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ *
+ */
+OMXResult omxVCM4P10_FilterDeblockingLuma_HorEdge_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingChroma_VerEdge_I (6.3.3.3.3)
+ *
+ * Description:
+ * Performs in-place deblock filtering on four vertical edges of the chroma
+ * macroblock (8x8).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the input macroblock; must be 8-byte aligned.
+ * srcdstStep - Step of the arrays; must be a multiple of 8.
+ * pAlpha - Array of size 2 of alpha thresholds (the first item is alpha
+ * threshold for external vertical edge, and the second item is for
+ * internal vertical edge); per [ISO14496-10] alpha values must be
+ * in the range [0,255].
+ * pBeta - Array of size 2 of beta thresholds (the first item is the beta
+ * threshold for the external vertical edge, and the second item is
+ * for the internal vertical edge); per [ISO14496-10] beta values
+ * must be in the range [0,18].
+ * pThresholds - Array of size 8 containing thresholds, TC0, for the left
+ * vertical edge of each 4x2 chroma block, arranged in vertical
+ * block order; must be aligned on a 4-byte boundary. Per
+ * [ISO14496-10] values must be in the range [0,25].
+ * pBS - Array of size 16 of BS parameters (values for each 2x2 chroma
+ * block, arranged in vertical block order). This parameter is the
+ * same as the pBS parameter passed into FilterDeblockLuma_VerEdge;
+ * valid in the range [0,4] with the following restrictions: i)
+ * pBS[i]== 4 may occur only for 0<=i<=3, ii) pBS[i]== 4 if and
+ * only if pBS[i^3]== 4. Must be 4 byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds, or pBS.
+ * - pSrcDst is not 8-byte aligned.
+ * - srcdstStep is not a multiple of 8.
+ * - pThresholds is not 4-byte aligned.
+ * - pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * - pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * - One or more entries in the table pThresholds[0..7] is outside
+ * of the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - pBS is not 4-byte aligned.
+ *
+ */
+OMXResult omxVCM4P10_FilterDeblockingChroma_VerEdge_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingChroma_HorEdge_I (6.3.3.3.4)
+ *
+ * Description:
+ * Performs in-place deblock filtering on the horizontal edges of the chroma
+ * macroblock (8x8).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 8-byte aligned.
+ * srcdstStep - array step; must be a multiple of 8.
+ * pAlpha - array of size 2 containing alpha thresholds; the first element
+ * contains the threshold for the external horizontal edge, and the
+ * second element contains the threshold for internal horizontal
+ * edge. Per [ISO14496-10] alpha values must be in the range
+ * [0,255].
+ * pBeta - array of size 2 containing beta thresholds; the first element
+ * contains the threshold for the external horizontal edge, and the
+ * second element contains the threshold for the internal
+ * horizontal edge. Per [ISO14496-10] beta values must be in the
+ * range [0,18].
+ * pThresholds - array of size 8 containing thresholds, TC0, for the top
+ * horizontal edge of each 2x4 chroma block, arranged in horizontal
+ * block order; must be aligned on a 4-byte boundary. Per
+ * [ISO14496-10] values must be in the range [0,25].
+ * pBS - array of size 16 containing BS parameters for each 2x2 chroma
+ * block, arranged in horizontal block order; valid in the range
+ * [0,4] with the following restrictions: i) pBS[i]== 4 may occur
+ * only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^3]== 4.
+ * Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr, if one of the following cases occurs:
+ * - any of the following pointers is NULL:
+ * pSrcDst, pAlpha, pBeta, pThresholds, or pBS.
+ * - pSrcDst is not 8-byte aligned.
+ * - srcdstStep is not a multiple of 8.
+ * - pThresholds is not 4-byte aligned.
+ * - pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * - pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * - One or more entries in the table pThresholds[0..7] is outside
+ * of the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - pBS is not 4-byte aligned.
+ *
+ */
+OMXResult omxVCM4P10_FilterDeblockingChroma_HorEdge_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DeblockLuma_I (6.3.3.3.5)
+ *
+ * Description:
+ * This function performs in-place deblock filtering the horizontal and
+ * vertical edges of a luma macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 16-byte aligned.
+ * srcdstStep - image width; must be a multiple of 16.
+ * pAlpha - pointer to a 2x2 table of alpha thresholds, organized as
+ * follows: {external vertical edge, internal vertical edge,
+ * external horizontal edge, internal horizontal edge }. Per
+ * [ISO14496-10] alpha values must be in the range [0,255].
+ * pBeta - pointer to a 2x2 table of beta thresholds, organized as follows:
+ * {external vertical edge, internal vertical edge, external
+ * horizontal edge, internal horizontal edge }. Per [ISO14496-10]
+ * beta values must be in the range [0,18].
+ * pThresholds - pointer to a 16x2 table of threshold (TC0), organized as
+ * follows: {values for the left or above edge of each 4x4 block,
+ * arranged in vertical block order and then in horizontal block
+ * order}; must be aligned on a 4-byte boundary. Per [ISO14496-10]
+ * values must be in the range [0,25].
+ * pBS - pointer to a 16x2 table of BS parameters arranged in scan block
+ * order for vertical edges and then horizontal edges; valid in the
+ * range [0,4] with the following restrictions: i) pBS[i]== 4 may
+ * occur only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^3]==
+ * 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds or pBS.
+ * - pSrcDst is not 16-byte aligned.
+ * - either pThresholds or pBS is not aligned on a 4-byte boundary.
+ * - one or more entries in the table pAlpha[0..3] is outside the range
+ * [0,255].
+ * - one or more entries in the table pBeta[0..3] is outside the range
+ * [0,18].
+ * - one or more entries in the table pThresholds[0..31]is outside of
+ * the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - srcdstStep is not a multiple of 16.
+ *
+ */
+OMXResult omxVCM4P10_DeblockLuma_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DeblockChroma_I (6.3.3.3.6)
+ *
+ * Description:
+ * Performs in-place deblocking filtering on all edges of the chroma
+ * macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 8-byte aligned.
+ * srcdstStep - step of the arrays; must be a multiple of 8.
+ * pAlpha - pointer to a 2x2 array of alpha thresholds, organized as
+ * follows: {external vertical edge, internal vertical edge,
+ * external horizontal edge, internal horizontal edge }. Per
+ * [ISO14496-10] alpha values must be in the range [0,255].
+ * pBeta - pointer to a 2x2 array of Beta Thresholds, organized as follows:
+ * { external vertical edge, internal vertical edge, external
+ * horizontal edge, internal horizontal edge }. Per [ISO14496-10]
+ * beta values must be in the range [0,18].
+ * pThresholds - array of size 8x2 of Thresholds (TC0) (values for the left
+ * or above edge of each 4x2 or 2x4 block, arranged in vertical
+ * block order and then in horizontal block order); must be aligned
+ * on a 4-byte boundary. Per [ISO14496-10] values must be in the
+ * range [0,25].
+ * pBS - array of size 16x2 of BS parameters (arranged in scan block order
+ * for vertical edges and then horizontal edges); valid in the
+ * range [0,4] with the following restrictions: i) pBS[i]== 4 may
+ * occur only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^3]==
+ * 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds, or pBS.
+ * - pSrcDst is not 8-byte aligned.
+ * - either pThresholds or pBS is not 4-byte aligned.
+ * - one or more entries in the table pAlpha[0..3] is outside the range
+ * [0,255].
+ * - one or more entries in the table pBeta[0..3] is outside the range
+ * [0,18].
+ * - one or more entries in the table pThresholds[0..15]is outside of
+ * the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - srcdstStep is not a multiple of 8.
+ *
+ */
+OMXResult omxVCM4P10_DeblockChroma_I (
+ OMX_U8 *pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8 *pAlpha,
+ const OMX_U8 *pBeta,
+ const OMX_U8 *pThresholds,
+ const OMX_U8 *pBS
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC (6.3.4.1.1)
+ *
+ * Description:
+ * Performs CAVLC decoding and inverse raster scan for a 2x2 block of
+ * ChromaDCLevel. The decoded coefficients in the packed position-coefficient
+ * buffer are stored in reverse zig-zag order, i.e., the first buffer element
+ * contains the last non-zero postion-coefficient pair of the block. Within
+ * each position-coefficient pair, the position entry indicates the
+ * raster-scan position of the coefficient, while the coefficient entry
+ * contains the coefficient value.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - Double pointer to current byte in bit stream buffer
+ * pOffset - Pointer to current bit position in the byte pointed to by
+ * *ppBitStream; valid in the range [0,7].
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after each block is decoded
+ * pOffset - *pOffset is updated after each block is decoded
+ * pNumCoeff - Pointer to the number of nonzero coefficients in this block
+ * ppPosCoefBuf - Double pointer to destination residual
+ * coefficient-position pair buffer. Buffer position
+ * (*ppPosCoefBuf) is updated upon return, unless there are only
+ * zero coefficients in the currently decoded block. In this case
+ * the caller is expected to bypass the transform/dequantization of
+ * the empty blocks.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppBitStream or pOffset is NULL.
+ * - ppPosCoefBuf or pNumCoeff is NULL.
+ * OMX_Sts_Err - if one of the following is true:
+ * - an illegal code is encountered in the bitstream
+ *
+ */
+OMXResult omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC (
+ const OMX_U8 **ppBitStream,
+ OMX_S32*pOffset,
+ OMX_U8 *pNumCoeff,
+ OMX_U8 **ppPosCoefbuf
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DecodeCoeffsToPairCAVLC (6.3.4.1.2)
+ *
+ * Description:
+ * Performs CAVLC decoding and inverse zigzag scan for 4x4 block of
+ * Intra16x16DCLevel, Intra16x16ACLevel, LumaLevel, and ChromaACLevel. Inverse
+ * field scan is not supported. The decoded coefficients in the packed
+ * position-coefficient buffer are stored in reverse zig-zag order, i.e., the
+ * first buffer element contains the last non-zero postion-coefficient pair of
+ * the block. Within each position-coefficient pair, the position entry
+ * indicates the raster-scan position of the coefficient, while the
+ * coefficient entry contains the coefficient value.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream -Double pointer to current byte in bit stream buffer
+ * pOffset - Pointer to current bit position in the byte pointed to by
+ * *ppBitStream; valid in the range [0,7].
+ * sMaxNumCoeff - Maximum the number of non-zero coefficients in current
+ * block
+ * sVLCSelect - VLC table selector, obtained from the number of non-zero
+ * coefficients contained in the above and left 4x4 blocks. It is
+ * equivalent to the variable nC described in H.264 standard table
+ * 9 5, except its value can t be less than zero.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after each block is decoded.
+ * Buffer position (*ppPosCoefBuf) is updated upon return, unless
+ * there are only zero coefficients in the currently decoded block.
+ * In this case the caller is expected to bypass the
+ * transform/dequantization of the empty blocks.
+ * pOffset - *pOffset is updated after each block is decoded
+ * pNumCoeff - Pointer to the number of nonzero coefficients in this block
+ * ppPosCoefBuf - Double pointer to destination residual
+ * coefficient-position pair buffer
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppBitStream or pOffset is NULL.
+ * - ppPosCoefBuf or pNumCoeff is NULL.
+ * - sMaxNumCoeff is not equal to either 15 or 16.
+ * - sVLCSelect is less than 0.
+ *
+ * OMX_Sts_Err - if one of the following is true:
+ * - an illegal code is encountered in the bitstream
+ *
+ */
+OMXResult omxVCM4P10_DecodeCoeffsToPairCAVLC (
+ const OMX_U8 **ppBitStream,
+ OMX_S32 *pOffset,
+ OMX_U8 *pNumCoeff,
+ OMX_U8 **ppPosCoefbuf,
+ OMX_INT sVLCSelect,
+ OMX_INT sMaxNumCoeff
+);
+
+
+
+/**
+ * Function: omxVCM4P10_TransformDequantLumaDCFromPair (6.3.4.2.1)
+ *
+ * Description:
+ * Reconstructs the 4x4 LumaDC block from the coefficient-position pair
+ * buffer, performs integer inverse, and dequantization for 4x4 LumaDC
+ * coefficients, and updates the pair buffer pointer to the next non-empty
+ * block.
+ *
+ * Input Arguments:
+ *
+ * ppSrc - Double pointer to residual coefficient-position pair buffer
+ * output by CALVC decoding
+ * QP - Quantization parameter QpY
+ *
+ * Output Arguments:
+ *
+ * ppSrc - *ppSrc is updated to the start of next non empty block
+ * pDst - Pointer to the reconstructed 4x4 LumaDC coefficients buffer; must
+ * be aligned on a 8-byte boundary.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppSrc or pDst is NULL.
+ * - pDst is not 8 byte aligned.
+ * - QP is not in the range of [0-51].
+ *
+ */
+OMXResult omxVCM4P10_TransformDequantLumaDCFromPair (
+ const OMX_U8 **ppSrc,
+ OMX_S16 *pDst,
+ OMX_INT QP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_TransformDequantChromaDCFromPair (6.3.4.2.2)
+ *
+ * Description:
+ * Reconstruct the 2x2 ChromaDC block from coefficient-position pair buffer,
+ * perform integer inverse transformation, and dequantization for 2x2 chroma
+ * DC coefficients, and update the pair buffer pointer to next non-empty
+ * block.
+ *
+ * Input Arguments:
+ *
+ * ppSrc - Double pointer to residual coefficient-position pair buffer
+ * output by CALVC decoding
+ * QP - Quantization parameter QpC
+ *
+ * Output Arguments:
+ *
+ * ppSrc - *ppSrc is updated to the start of next non empty block
+ * pDst - Pointer to the reconstructed 2x2 ChromaDC coefficients buffer;
+ * must be aligned on a 4-byte boundary.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppSrc or pDst is NULL.
+ * - pDst is not 4-byte aligned.
+ * - QP is not in the range of [0-51].
+ *
+ */
+OMXResult omxVCM4P10_TransformDequantChromaDCFromPair (
+ const OMX_U8 **ppSrc,
+ OMX_S16 *pDst,
+ OMX_INT QP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_DequantTransformResidualFromPairAndAdd (6.3.4.2.3)
+ *
+ * Description:
+ * Reconstruct the 4x4 residual block from coefficient-position pair buffer,
+ * perform dequantization and integer inverse transformation for 4x4 block of
+ * residuals with previous intra prediction or motion compensation data, and
+ * update the pair buffer pointer to next non-empty block. If pDC == NULL,
+ * there re 16 non-zero AC coefficients at most in the packed buffer starting
+ * from 4x4 block position 0; If pDC != NULL, there re 15 non-zero AC
+ * coefficients at most in the packet buffer starting from 4x4 block position
+ * 1.
+ *
+ * Input Arguments:
+ *
+ * ppSrc - Double pointer to residual coefficient-position pair buffer
+ * output by CALVC decoding
+ * pPred - Pointer to the predicted 4x4 block; must be aligned on a 4-byte
+ * boundary
+ * predStep - Predicted frame step size in bytes; must be a multiple of 4
+ * dstStep - Destination frame step in bytes; must be a multiple of 4
+ * pDC - Pointer to the DC coefficient of this block, NULL if it doesn't
+ * exist
+ * QP - QP Quantization parameter. It should be QpC in chroma 4x4 block
+ * decoding, otherwise it should be QpY.
+ * AC - Flag indicating if at least one non-zero AC coefficient exists
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the reconstructed 4x4 block data; must be aligned on a
+ * 4-byte boundary
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - pPred or pDst is NULL.
+ * - pPred or pDst is not 4-byte aligned.
+ * - predStep or dstStep is not a multiple of 4.
+ * - AC !=0 and Qp is not in the range of [0-51] or ppSrc == NULL.
+ * - AC ==0 && pDC ==NULL.
+ *
+ */
+OMXResult omxVCM4P10_DequantTransformResidualFromPairAndAdd (
+ const OMX_U8 **ppSrc,
+ const OMX_U8 *pPred,
+ const OMX_S16 *pDC,
+ OMX_U8 *pDst,
+ OMX_INT predStep,
+ OMX_INT dstStep,
+ OMX_INT QP,
+ OMX_INT AC
+);
+
+
+
+/**
+ * Function: omxVCM4P10_MEGetBufSize (6.3.5.1.1)
+ *
+ * Description:
+ * Computes the size, in bytes, of the vendor-specific specification
+ * structure for the omxVCM4P10 motion estimation functions BlockMatch_Integer
+ * and MotionEstimationMB.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P10MEMode
+ * pMEParams -motion estimation parameters
+ *
+ * Output Arguments:
+ *
+ * pSize - pointer to the number of bytes required for the motion
+ * estimation specification structure
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - pMEParams or pSize is NULL.
+ * - an invalid MEMode is specified.
+ *
+ */
+OMXResult omxVCM4P10_MEGetBufSize (
+ OMXVCM4P10MEMode MEmode,
+ const OMXVCM4P10MEParams *pMEParams,
+ OMX_U32 *pSize
+);
+
+
+
+/**
+ * Function: omxVCM4P10_MEInit (6.3.5.1.2)
+ *
+ * Description:
+ * Initializes the vendor-specific specification structure required for the
+ * omxVCM4P10 motion estimation functions: BlockMatch_Integer and
+ * MotionEstimationMB. Memory for the specification structure *pMESpec must be
+ * allocated prior to calling the function, and should be aligned on a 4-byte
+ * boundary. The number of bytes required for the specification structure can
+ * be determined using the function omxVCM4P10_MEGetBufSize. Following
+ * initialization by this function, the vendor-specific structure *pMESpec
+ * should contain an implementation-specific representation of all motion
+ * estimation parameters received via the structure pMEParams, for example
+ * searchRange16x16, searchRange8x8, etc.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P10MEMode
+ * pMEParams - motion estimation parameters
+ * pMESpec - pointer to the uninitialized ME specification structure
+ *
+ * Output Arguments:
+ *
+ * pMESpec - pointer to the initialized ME specification structure
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - pMEParams or pSize is NULL.
+ * - an invalid value was specified for the parameter MEmode
+ * - a negative or zero value was specified for one of the search ranges
+ * (e.g., pMBParams >searchRange8x8, pMEParams->searchRange16x16, etc.)
+ * - either in isolation or in combination, one or more of the enables or
+ * search ranges in the structure *pMEParams were configured such
+ * that the requested behavior fails to comply with [ISO14496-10].
+ *
+ */
+OMXResult omxVCM4P10_MEInit (
+ OMXVCM4P10MEMode MEmode,
+ const OMXVCM4P10MEParams *pMEParams,
+ void *pMESpec
+);
+
+
+
+/**
+ * Function: omxVCM4P10_BlockMatch_Integer (6.3.5.2.1)
+ *
+ * Description:
+ * Performs integer block match. Returns best MV and associated cost.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrgY - Pointer to the top-left corner of the current block:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * pSrcRefY - Pointer to the top-left corner of the co-located block in the
+ * reference picture:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * nSrcOrgStep - Stride of the original picture plane, expressed in terms
+ * of integer pixels; must be a multiple of iBlockWidth.
+ * nSrcRefStep - Stride of the reference picture plane, expressed in terms
+ * of integer pixels
+ * pRefRect - pointer to the valid reference rectangle inside the reference
+ * picture plane
+ * nCurrPointPos - position of the current block in the current plane
+ * iBlockWidth - Width of the current block, expressed in terms of integer
+ * pixels; must be equal to either 4, 8, or 16.
+ * iBlockHeight - Height of the current block, expressed in terms of
+ * integer pixels; must be equal to either 4, 8, or 16.
+ * nLamda - Lamda factor; used to compute motion cost
+ * pMVPred - Predicted MV; used to compute motion cost, expressed in terms
+ * of 1/4-pel units
+ * pMVCandidate - Candidate MV; used to initialize the motion search,
+ * expressed in terms of integer pixels
+ * pMESpec - pointer to the ME specification structure
+ *
+ * Output Arguments:
+ *
+ * pDstBestMV - Best MV resulting from integer search, expressed in terms
+ * of 1/4-pel units
+ * pBestCost - Motion cost associated with the best MV; computed as
+ * SAD+Lamda*BitsUsedByMV
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - any of the following pointers are NULL:
+ * pSrcOrgY, pSrcRefY, pRefRect, pMVPred, pMVCandidate, or pMESpec.
+ * - Either iBlockWidth or iBlockHeight are values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_BlockMatch_Integer (
+ const OMX_U8 *pSrcOrgY,
+ OMX_S32 nSrcOrgStep,
+ const OMX_U8 *pSrcRefY,
+ OMX_S32 nSrcRefStep,
+ const OMXRect *pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ OMX_U8 iBlockWidth,
+ OMX_U8 iBlockHeight,
+ OMX_U32 nLamda,
+ const OMXVCMotionVector *pMVPred,
+ const OMXVCMotionVector *pMVCandidate,
+ OMXVCMotionVector *pBestMV,
+ OMX_S32 *pBestCost,
+ void *pMESpec
+);
+
+
+
+/**
+ * Function: omxVCM4P10_BlockMatch_Half (6.3.5.2.2)
+ *
+ * Description:
+ * Performs a half-pel block match using results from a prior integer search.
+ * Returns the best MV and associated cost. This function estimates the
+ * half-pixel motion vector by interpolating the integer resolution motion
+ * vector referenced by the input parameter pSrcDstBestMV, i.e., the initial
+ * integer MV is generated externally. The function
+ * omxVCM4P10_BlockMatch_Integer may be used for integer motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrgY - Pointer to the current position in original picture plane:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * pSrcRefY - Pointer to the top-left corner of the co-located block in the
+ * reference picture:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * nSrcOrgStep - Stride of the original picture plane in terms of full
+ * pixels; must be a multiple of iBlockWidth.
+ * nSrcRefStep - Stride of the reference picture plane in terms of full
+ * pixels
+ * iBlockWidth - Width of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * iBlockHeight - Height of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * nLamda - Lamda factor, used to compute motion cost
+ * pMVPred - Predicted MV, represented in terms of 1/4-pel units; used to
+ * compute motion cost
+ * pSrcDstBestMV - The best MV resulting from a prior integer search,
+ * represented in terms of 1/4-pel units
+ *
+ * Output Arguments:
+ *
+ * pSrcDstBestMV - Best MV resulting from the half-pel search, expressed in
+ * terms of 1/4-pel units
+ * pBestCost - Motion cost associated with the best MV; computed as
+ * SAD+Lamda*BitsUsedByMV
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - any of the following pointers is NULL: pSrcOrgY, pSrcRefY,
+ * pSrcDstBestMV, pMVPred, pBestCost
+ * - iBlockWidth or iBlockHeight are equal to values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_BlockMatch_Half (
+ const OMX_U8 *pSrcOrgY,
+ OMX_S32 nSrcOrgStep,
+ const OMX_U8 *pSrcRefY,
+ OMX_S32 nSrcRefStep,
+ OMX_U8 iBlockWidth,
+ OMX_U8 iBlockHeight,
+ OMX_U32 nLamda,
+ const OMXVCMotionVector *pMVPred,
+ OMXVCMotionVector *pSrcDstBestMV,
+ OMX_S32 *pBestCost
+);
+
+
+
+/**
+ * Function: omxVCM4P10_BlockMatch_Quarter (6.3.5.2.3)
+ *
+ * Description:
+ * Performs a quarter-pel block match using results from a prior half-pel
+ * search. Returns the best MV and associated cost. This function estimates
+ * the quarter-pixel motion vector by interpolating the half-pel resolution
+ * motion vector referenced by the input parameter pSrcDstBestMV, i.e., the
+ * initial half-pel MV is generated externally. The function
+ * omxVCM4P10_BlockMatch_Half may be used for half-pel motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrgY - Pointer to the current position in original picture plane:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * pSrcRefY - Pointer to the top-left corner of the co-located block in the
+ * reference picture:
+ * If iBlockWidth==4, 4-byte alignment required.
+ * If iBlockWidth==8, 8-byte alignment required.
+ * If iBlockWidth==16, 16-byte alignment required.
+ * nSrcOrgStep - Stride of the original picture plane in terms of full
+ * pixels; must be a multiple of iBlockWidth.
+ * nSrcRefStep - Stride of the reference picture plane in terms of full
+ * pixels
+ * iBlockWidth - Width of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * iBlockHeight - Height of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * nLamda - Lamda factor, used to compute motion cost
+ * pMVPred - Predicted MV, represented in terms of 1/4-pel units; used to
+ * compute motion cost
+ * pSrcDstBestMV - The best MV resulting from a prior half-pel search,
+ * represented in terms of 1/4 pel units
+ *
+ * Output Arguments:
+ *
+ * pSrcDstBestMV - Best MV resulting from the quarter-pel search, expressed
+ * in terms of 1/4-pel units
+ * pBestCost - Motion cost associated with the best MV; computed as
+ * SAD+Lamda*BitsUsedByMV
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - One or more of the following pointers is NULL:
+ * pSrcOrgY, pSrcRefY, pSrcDstBestMV, pMVPred, pBestCost
+ * - iBlockWidth or iBlockHeight are equal to values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_BlockMatch_Quarter (
+ const OMX_U8 *pSrcOrgY,
+ OMX_S32 nSrcOrgStep,
+ const OMX_U8 *pSrcRefY,
+ OMX_S32 nSrcRefStep,
+ OMX_U8 iBlockWidth,
+ OMX_U8 iBlockHeight,
+ OMX_U32 nLamda,
+ const OMXVCMotionVector *pMVPred,
+ OMXVCMotionVector *pSrcDstBestMV,
+ OMX_S32 *pBestCost
+);
+
+
+
+/**
+ * Function: omxVCM4P10_MotionEstimationMB (6.3.5.3.1)
+ *
+ * Description:
+ * Performs MB-level motion estimation and selects best motion estimation
+ * strategy from the set of modes supported in baseline profile [ISO14496-10].
+ *
+ * Input Arguments:
+ *
+ * pSrcCurrBuf - Pointer to the current position in original picture plane;
+ * 16-byte alignment required
+ * pSrcRefBufList - Pointer to an array with 16 entries. Each entry points
+ * to the top-left corner of the co-located MB in a reference
+ * picture. The array is filled from low-to-high with valid
+ * reference frame pointers; the unused high entries should be set
+ * to NULL. Ordering of the reference frames should follow
+ * [ISO14496-10] subclause 8.2.4 Decoding Process for Reference
+ * Picture Lists. The entries must be 16-byte aligned.
+ * pSrcRecBuf - Pointer to the top-left corner of the co-located MB in the
+ * reconstructed picture; must be 16-byte aligned.
+ * SrcCurrStep - Width of the original picture plane in terms of full
+ * pixels; must be a multiple of 16.
+ * SrcRefStep - Width of the reference picture plane in terms of full
+ * pixels; must be a multiple of 16.
+ * SrcRecStep - Width of the reconstructed picture plane in terms of full
+ * pixels; must be a multiple of 16.
+ * pRefRect - Pointer to the valid reference rectangle; relative to the
+ * image origin.
+ * pCurrPointPos - Position of the current macroblock in the current plane.
+ * Lambda - Lagrange factor for computing the cost function
+ * pMESpec - Pointer to the motion estimation specification structure; must
+ * have been allocated and initialized prior to calling this
+ * function.
+ * pMBInter - Array, of dimension four, containing pointers to information
+ * associated with four adjacent type INTER MBs (Left, Top,
+ * Top-Left, Top-Right). Any pointer in the array may be set equal
+ * to NULL if the corresponding MB doesn t exist or is not of type
+ * INTER.
+ * - pMBInter[0] - Pointer to left MB information
+ * - pMBInter[1] - Pointer to top MB information
+ * - pMBInter[2] - Pointer to top-left MB information
+ * - pMBInter[3] - Pointer to top-right MB information
+ * pMBIntra - Array, of dimension four, containing pointers to information
+ * associated with four adjacent type INTRA MBs (Left, Top,
+ * Top-Left, Top-Right). Any pointer in the array may be set equal
+ * to NULL if the corresponding MB doesn t exist or is not of type
+ * INTRA.
+ * - pMBIntra[0] - Pointer to left MB information
+ * - pMBIntra[1] - Pointer to top MB information
+ * - pMBIntra[2] - Pointer to top-left MB information
+ * - pMBIntra[3] - Pointer to top-right MB information
+ * pSrcDstMBCurr - Pointer to information structure for the current MB.
+ * The following entries should be set prior to calling the
+ * function: sliceID - the number of the slice the to which the
+ * current MB belongs.
+ *
+ * Output Arguments:
+ *
+ * pDstCost - Pointer to the minimum motion cost for the current MB.
+ * pDstBlockSAD - Pointer to the array of SADs for each of the sixteen luma
+ * 4x4 blocks in each MB. The block SADs are in scan order for
+ * each MB. For implementations that cannot compute the SAD values
+ * individually, the maximum possible value (0xffff) is returned
+ * for each of the 16 block SAD entries.
+ * pSrcDstMBCurr - Pointer to updated information structure for the current
+ * MB after MB-level motion estimation has been completed. The
+ * following fields are updated by the ME function. The following
+ * parameter set quantifies the MB-level ME search results:
+ * - MbType
+ * - subMBType[4]
+ * - pMV0[4][4]
+ * - pMVPred[4][4]
+ * - pRefL0Idx[4]
+ * - Intra16x16PredMode
+ * - pIntra4x4PredMode[4][4]
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - One or more of the following pointers is NULL: pSrcCurrBuf,
+ * pSrcRefBufList, pSrcRecBuf, pRefRect, pCurrPointPos, pMESpec,
+ * pMBInter, pMBIntra,pSrcDstMBCurr, pDstCost, pSrcRefBufList[0]
+ * - SrcRefStep, SrcRecStep are not multiples of 16
+ * - iBlockWidth or iBlockHeight are values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_MotionEstimationMB (
+ const OMX_U8 *pSrcCurrBuf,
+ OMX_S32 SrcCurrStep,
+ const OMX_U8 *pSrcRefBufList[15],
+ OMX_S32 SrcRefStep,
+ const OMX_U8 *pSrcRecBuf,
+ OMX_S32 SrcRecStep,
+ const OMXRect *pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ OMX_U32 Lambda,
+ void *pMESpec,
+ const OMXVCM4P10MBInfoPtr *pMBInter,
+ const OMXVCM4P10MBInfoPtr *pMBIntra,
+ OMXVCM4P10MBInfoPtr pSrcDstMBCurr,
+ OMX_INT *pDstCost,
+ OMX_U16 *pDstBlockSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SAD_4x (6.3.5.4.1)
+ *
+ * Description:
+ * This function calculates the SAD for 4x8 and 4x4 blocks.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg -Pointer to the original block; must be aligned on a 4-byte
+ * boundary.
+ * iStepOrg -Step of the original block buffer; must be a multiple of 4.
+ * pSrcRef -Pointer to the reference block
+ * iStepRef -Step of the reference block buffer
+ * iHeight -Height of the block; must be equal to either 4 or 8.
+ *
+ * Output Arguments:
+ *
+ * pDstSAD -Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - One or more of the following pointers is NULL:
+ * pSrcOrg, pSrcRef, or pDstSAD
+ * - iHeight is not equal to either 4 or 8.
+ * - iStepOrg is not a multiple of 4
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SAD_4x (
+ const OMX_U8 *pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8 *pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SADQuar_4x (6.3.5.4.2)
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the average
+ * of the other two (pSrcRef0 and pSrcRef1) for 4x8 or 4x4 blocks. Rounding
+ * is applied according to the convention (a+b+1)>>1.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the original block; must be aligned on a 4-byte
+ * boundary.
+ * pSrcRef0 - Pointer to reference block 0
+ * pSrcRef1 - Pointer to reference block 1
+ * iSrcStep - Step of the original block buffer; must be a multiple of 4.
+ * iRefStep0 - Step of reference block 0
+ * iRefStep1 - Step of reference block 1
+ * iHeight - Height of the block; must be equal to either 4 or 8.
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - iHeight is not equal to either 4 or 8.
+ * - One or more of the following pointers is NULL: pSrc, pSrcRef0,
+ * pSrcRef1, pDstSAD.
+ * - iSrcStep is not a multiple of 4
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SADQuar_4x (
+ const OMX_U8 *pSrc,
+ const OMX_U8 *pSrcRef0,
+ const OMX_U8 *pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SADQuar_8x (6.3.5.4.3)
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the average
+ * of the other two (pSrcRef0 and pSrcRef1) for 8x16, 8x8, or 8x4 blocks.
+ * Rounding is applied according to the convention (a+b+1)>>1.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the original block; must be aligned on an 8-byte
+ * boundary.
+ * pSrcRef0 - Pointer to reference block 0
+ * pSrcRef1 - Pointer to reference block 1
+ * iSrcStep - Step of the original block buffer; must be a multiple of 8.
+ * iRefStep0 - Step of reference block 0
+ * iRefStep1 - Step of reference block 1
+ * iHeight - Height of the block; must be equal either 4, 8, or 16.
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - iHeight is not equal to either 4, 8, or 16.
+ * - One or more of the following pointers is NULL: pSrc, pSrcRef0,
+ * pSrcRef1, pDstSAD.
+ * - iSrcStep is not a multiple of 8
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SADQuar_8x (
+ const OMX_U8 *pSrc,
+ const OMX_U8 *pSrcRef0,
+ const OMX_U8 *pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SADQuar_16x (6.3.5.4.4)
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the average
+ * of the other two (pSrcRef0 and pSrcRef1) for 16x16 or 16x8 blocks.
+ * Rounding is applied according to the convention (a+b+1)>>1.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the original block; must be aligned on a 16-byte
+ * boundary.
+ * pSrcRef0 - Pointer to reference block 0
+ * pSrcRef1 - Pointer to reference block 1
+ * iSrcStep - Step of the original block buffer; must be a multiple of 16
+ * iRefStep0 - Step of reference block 0
+ * iRefStep1 - Step of reference block 1
+ * iHeight - Height of the block; must be equal to either 8 or 16
+ *
+ * Output Arguments:
+ *
+ * pDstSAD -Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - iHeight is not equal to either 8 or 16.
+ * - One or more of the following pointers is NULL: pSrc, pSrcRef0,
+ * pSrcRef1, pDstSAD.
+ * - iSrcStep is not a multiple of 16
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SADQuar_16x (
+ const OMX_U8 *pSrc,
+ const OMX_U8 *pSrcRef0,
+ const OMX_U8 *pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32 *pDstSAD,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SATD_4x4 (6.3.5.4.5)
+ *
+ * Description:
+ * This function calculates the sum of absolute transform differences (SATD)
+ * for a 4x4 block by applying a Hadamard transform to the difference block
+ * and then calculating the sum of absolute coefficient values.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to the original block; must be aligned on a 4-byte
+ * boundary
+ * iStepOrg - Step of the original block buffer; must be a multiple of 4
+ * pSrcRef - Pointer to the reference block; must be aligned on a 4-byte
+ * boundary
+ * iStepRef - Step of the reference block buffer; must be a multiple of 4
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - pointer to the resulting SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pSrcRef, or pDstSAD either pSrcOrg
+ * - pSrcRef is not aligned on a 4-byte boundary
+ * - iStepOrg <= 0 or iStepOrg is not a multiple of 4
+ * - iStepRef <= 0 or iStepRef is not a multiple of 4
+ *
+ */
+OMXResult omxVCM4P10_SATD_4x4 (
+ const OMX_U8 *pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8 *pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_U32 *pDstSAD
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InterpolateHalfHor_Luma (6.3.5.5.1)
+ *
+ * Description:
+ * This function performs interpolation for two horizontal 1/2-pel positions
+ * (-1/2,0) and (1/2, 0) - around a full-pel position.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the top-left corner of the block used to interpolate in
+ * the reconstruction frame plane.
+ * iSrcStep - Step of the source buffer.
+ * iDstStep - Step of the destination(interpolation) buffer; must be a
+ * multiple of iWidth.
+ * iWidth - Width of the current block; must be equal to either 4, 8, or 16
+ * iHeight - Height of the current block; must be equal to 4, 8, or 16
+ *
+ * Output Arguments:
+ *
+ * pDstLeft -Pointer to the interpolation buffer of the left -pel position
+ * (-1/2, 0)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ * pDstRight -Pointer to the interpolation buffer of the right -pel
+ * position (1/2, 0)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrc, pDstLeft, or pDstRight
+ * - iWidth or iHeight have values other than 4, 8, or 16
+ * - iWidth==4 but pDstLeft and/or pDstRight is/are not aligned on a 4-byte boundary
+ * - iWidth==8 but pDstLeft and/or pDstRight is/are not aligned on a 8-byte boundary
+ * - iWidth==16 but pDstLeft and/or pDstRight is/are not aligned on a 16-byte boundary
+ * - any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_InterpolateHalfHor_Luma (
+ const OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDstLeft,
+ OMX_U8 *pDstRight,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InterpolateHalfVer_Luma (6.3.5.5.2)
+ *
+ * Description:
+ * This function performs interpolation for two vertical 1/2-pel positions -
+ * (0, -1/2) and (0, 1/2) - around a full-pel position.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to top-left corner of block used to interpolate in the
+ * reconstructed frame plane
+ * iSrcStep - Step of the source buffer.
+ * iDstStep - Step of the destination (interpolation) buffer; must be a
+ * multiple of iWidth.
+ * iWidth - Width of the current block; must be equal to either 4, 8, or 16
+ * iHeight - Height of the current block; must be equal to either 4, 8, or 16
+ *
+ * Output Arguments:
+ *
+ * pDstUp -Pointer to the interpolation buffer of the -pel position above
+ * the current full-pel position (0, -1/2)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ * pDstDown -Pointer to the interpolation buffer of the -pel position below
+ * the current full-pel position (0, 1/2)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrc, pDstUp, or pDstDown
+ * - iWidth or iHeight have values other than 4, 8, or 16
+ * - iWidth==4 but pDstUp and/or pDstDown is/are not aligned on a 4-byte boundary
+ * - iWidth==8 but pDstUp and/or pDstDown is/are not aligned on a 8-byte boundary
+ * - iWidth==16 but pDstUp and/or pDstDown is/are not aligned on a 16-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InterpolateHalfVer_Luma (
+ const OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDstUp,
+ OMX_U8 *pDstDown,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_Average_4x (6.3.5.5.3)
+ *
+ * Description:
+ * This function calculates the average of two 4x4, 4x8 blocks. The result
+ * is rounded according to (a+b+1)/2.
+ *
+ * Input Arguments:
+ *
+ * pPred0 - Pointer to the top-left corner of reference block 0
+ * pPred1 - Pointer to the top-left corner of reference block 1
+ * iPredStep0 - Step of reference block 0; must be a multiple of 4.
+ * iPredStep1 - Step of reference block 1; must be a multiple of 4.
+ * iDstStep - Step of the destination buffer; must be a multiple of 4.
+ * iHeight - Height of the blocks; must be either 4 or 8.
+ *
+ * Output Arguments:
+ *
+ * pDstPred - Pointer to the destination buffer. 4-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pPred0, pPred1, or pDstPred
+ * - pDstPred is not aligned on a 4-byte boundary
+ * - iPredStep0 <= 0 or iPredStep0 is not a multiple of 4
+ * - iPredStep1 <= 0 or iPredStep1 is not a multiple of 4
+ * - iDstStep <= 0 or iDstStep is not a multiple of 4
+ * - iHeight is not equal to either 4 or 8
+ *
+ */
+OMXResult omxVCM4P10_Average_4x (
+ const OMX_U8 *pPred0,
+ const OMX_U8 *pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8 *pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iHeight
+);
+
+
+
+/**
+ * Function: omxVCM4P10_TransformQuant_ChromaDC (6.3.5.6.1)
+ *
+ * Description:
+ * This function performs 2x2 Hadamard transform of chroma DC coefficients
+ * and then quantizes the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the 2x2 array of chroma DC coefficients. 8-byte
+ * alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ * bIntra - Indicate whether this is an INTRA block. 1-INTRA, 0-INTER
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - Pointer to transformed and quantized coefficients. 8-byte
+ * alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcDst
+ * - pSrcDst is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_TransformQuant_ChromaDC (
+ OMX_S16 *pSrcDst,
+ OMX_U32 iQP,
+ OMX_U8 bIntra
+);
+
+
+
+/**
+ * Function: omxVCM4P10_TransformQuant_LumaDC (6.3.5.6.2)
+ *
+ * Description:
+ * This function performs a 4x4 Hadamard transform of luma DC coefficients
+ * and then quantizes the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the 4x4 array of luma DC coefficients. 16-byte
+ * alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - Pointer to transformed and quantized coefficients. 16-byte
+ * alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL: pSrcDst
+ * - pSrcDst is not aligned on an 16-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_TransformQuant_LumaDC (
+ OMX_S16 *pSrcDst,
+ OMX_U32 iQP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InvTransformDequant_LumaDC (6.3.5.6.3)
+ *
+ * Description:
+ * This function performs inverse 4x4 Hadamard transform and then dequantizes
+ * the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the 4x4 array of the 4x4 Hadamard-transformed and
+ * quantized coefficients. 16 byte alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to inverse-transformed and dequantized coefficients.
+ * 16-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL: pSrc
+ * - pSrc or pDst is not aligned on a 16-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InvTransformDequant_LumaDC (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst,
+ OMX_U32 iQP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InvTransformDequant_ChromaDC (6.3.5.6.4)
+ *
+ * Description:
+ * This function performs inverse 2x2 Hadamard transform and then dequantizes
+ * the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the 2x2 array of the 2x2 Hadamard-transformed and
+ * quantized coefficients. 8 byte alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to inverse-transformed and dequantized coefficients.
+ * 8-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL: pSrc
+ * - pSrc or pDst is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InvTransformDequant_ChromaDC (
+ const OMX_S16 *pSrc,
+ OMX_S16 *pDst,
+ OMX_U32 iQP
+);
+
+
+
+/**
+ * Function: omxVCM4P10_InvTransformResidualAndAdd (6.3.5.7.1)
+ *
+ * Description:
+ * This function performs inverse an 4x4 integer transformation to produce
+ * the difference signal and then adds the difference to the prediction to get
+ * the reconstructed signal.
+ *
+ * Input Arguments:
+ *
+ * pSrcPred - Pointer to prediction signal. 4-byte alignment required.
+ * pDequantCoeff - Pointer to the transformed coefficients. 8-byte
+ * alignment required.
+ * iSrcPredStep - Step of the prediction buffer; must be a multiple of 4.
+ * iDstReconStep - Step of the destination reconstruction buffer; must be a
+ * multiple of 4.
+ * bAC - Indicate whether there is AC coefficients in the coefficients
+ * matrix.
+ *
+ * Output Arguments:
+ *
+ * pDstRecon -Pointer to the destination reconstruction buffer. 4-byte
+ * alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcPred, pDequantCoeff, pDstRecon
+ * - pSrcPred is not aligned on a 4-byte boundary
+ * - iSrcPredStep or iDstReconStep is not a multiple of 4.
+ * - pDequantCoeff is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InvTransformResidualAndAdd (
+ const OMX_U8 *pSrcPred,
+ const OMX_S16 *pDequantCoeff,
+ OMX_U8 *pDstRecon,
+ OMX_U32 iSrcPredStep,
+ OMX_U32 iDstReconStep,
+ OMX_U8 bAC
+);
+
+
+
+/**
+ * Function: omxVCM4P10_SubAndTransformQDQResidual (6.3.5.8.1)
+ *
+ * Description:
+ * This function subtracts the prediction signal from the original signal to
+ * produce the difference signal and then performs a 4x4 integer transform and
+ * quantization. The quantized transformed coefficients are stored as
+ * pDstQuantCoeff. This function can also output dequantized coefficients or
+ * unquantized DC coefficients optionally by setting the pointers
+ * pDstDeQuantCoeff, pDCCoeff.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to original signal. 4-byte alignment required.
+ * pSrcPred - Pointer to prediction signal. 4-byte alignment required.
+ * iSrcOrgStep - Step of the original signal buffer; must be a multiple of
+ * 4.
+ * iSrcPredStep - Step of the prediction signal buffer; must be a multiple
+ * of 4.
+ * pNumCoeff -Number of non-zero coefficients after quantization. If this
+ * parameter is not required, it is set to NULL.
+ * nThreshSAD - Zero-block early detection threshold. If this parameter is
+ * not required, it is set to 0.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ * bIntra - Indicates whether this is an INTRA block, either 1-INTRA or
+ * 0-INTER
+ *
+ * Output Arguments:
+ *
+ * pDstQuantCoeff - Pointer to the quantized transformed coefficients.
+ * 8-byte alignment required.
+ * pDstDeQuantCoeff - Pointer to the dequantized transformed coefficients
+ * if this parameter is not equal to NULL. 8-byte alignment
+ * required.
+ * pDCCoeff - Pointer to the unquantized DC coefficient if this parameter
+ * is not equal to NULL.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pSrcPred, pNumCoeff, pDstQuantCoeff,
+ * pDstDeQuantCoeff, pDCCoeff
+ * - pSrcOrg is not aligned on a 4-byte boundary
+ * - pSrcPred is not aligned on a 4-byte boundary
+ * - iSrcOrgStep is not a multiple of 4
+ * - iSrcPredStep is not a multiple of 4
+ * - pDstQuantCoeff or pDstDeQuantCoeff is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_SubAndTransformQDQResidual (
+ const OMX_U8 *pSrcOrg,
+ const OMX_U8 *pSrcPred,
+ OMX_U32 iSrcOrgStep,
+ OMX_U32 iSrcPredStep,
+ OMX_S16 *pDstQuantCoeff,
+ OMX_S16 *pDstDeQuantCoeff,
+ OMX_S16 *pDCCoeff,
+ OMX_S8 *pNumCoeff,
+ OMX_U32 nThreshSAD,
+ OMX_U32 iQP,
+ OMX_U8 bIntra
+);
+
+
+
+/**
+ * Function: omxVCM4P10_GetVLCInfo (6.3.5.9.1)
+ *
+ * Description:
+ * This function extracts run-length encoding (RLE) information from the
+ * coefficient matrix. The results are returned in an OMXVCM4P10VLCInfo
+ * structure.
+ *
+ * Input Arguments:
+ *
+ * pSrcCoeff - pointer to the transform coefficient matrix. 8-byte
+ * alignment required.
+ * pScanMatrix - pointer to the scan order definition matrix. For a luma
+ * block the scan matrix should follow [ISO14496-10] section 8.5.4,
+ * and should contain the values 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13,
+ * 10, 7, 11, 14, 15. For a chroma block, the scan matrix should
+ * contain the values 0, 1, 2, 3.
+ * bAC - indicates presence of a DC coefficient; 0 = DC coefficient
+ * present, 1= DC coefficient absent.
+ * MaxNumCoef - specifies the number of coefficients contained in the
+ * transform coefficient matrix, pSrcCoeff. The value should be 16
+ * for blocks of type LUMADC, LUMAAC, LUMALEVEL, and CHROMAAC. The
+ * value should be 4 for blocks of type CHROMADC.
+ *
+ * Output Arguments:
+ *
+ * pDstVLCInfo - pointer to structure that stores information for
+ * run-length coding.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcCoeff, pScanMatrix, pDstVLCInfo
+ * - pSrcCoeff is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_GetVLCInfo (
+ const OMX_S16 *pSrcCoeff,
+ const OMX_U8 *pScanMatrix,
+ OMX_U8 bAC,
+ OMX_U32 MaxNumCoef,
+ OMXVCM4P10VLCInfo*pDstVLCInfo
+);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** end of #define _OMXVC_H_ */
+
+/** EOF */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_Average.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_Average.c
new file mode 100644
index 0000000..1e51077
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_Average.c
@@ -0,0 +1,78 @@
+/**
+ *
+ * File Name: armVCCOMM_Average.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate Average of two blocks if size iWidth X iHeight
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: armVCCOMM_Average
+ *
+ * Description:
+ * This function calculates the average of two blocks and stores the result.
+ *
+ * Remarks:
+ *
+ * [in] pPred0 Pointer to the top-left corner of reference block 0
+ * [in] pPred1 Pointer to the top-left corner of reference block 1
+ * [in] iPredStep0 Step of reference block 0
+ * [in] iPredStep1 Step of reference block 1
+ * [in] iDstStep Step of the destination buffer
+ * [in] iWidth Width of the blocks
+ * [in] iHeight Height of the blocks
+ * [out] pDstPred Pointer to the destination buffer
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+ OMXResult armVCCOMM_Average (
+ const OMX_U8* pPred0,
+ const OMX_U8* pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8* pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+)
+{
+ OMX_U32 x, y;
+
+ /* check for argument error */
+ armRetArgErrIf(pPred0 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pPred1 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstPred == NULL, OMX_Sts_BadArgErr)
+
+ for (y = 0; y < iHeight; y++)
+ {
+ for (x = 0; x < iWidth; x++)
+ {
+ pDstPred [y * iDstStep + x] =
+ (OMX_U8)(((OMX_U32)pPred0 [y * iPredStep0 + x] +
+ pPred1 [y * iPredStep1 + x] + 1) >> 1);
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_SAD.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_SAD.c
new file mode 100644
index 0000000..d41ac9a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/armVCCOMM_SAD.c
@@ -0,0 +1,75 @@
+/**
+ *
+ * File Name: armVCCOMM_SAD.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate SAD for NxM blocks
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+/**
+ * Function: armVCCOMM_SAD
+ *
+ * Description:
+ * This function calculate the SAD for NxM blocks.
+ *
+ * Remarks:
+ *
+ * [in] pSrcOrg Pointer to the original block
+ * [in] iStepOrg Step of the original block buffer
+ * [in] pSrcRef Pointer to the reference block
+ * [in] iStepRef Step of the reference block buffer
+ * [in] iHeight Height of the block
+ * [in] iWidth Width of the block
+ * [out] pDstSAD Pointer of result SAD
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+OMXResult armVCCOMM_SAD(
+ const OMX_U8* pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8* pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32* pDstSAD,
+ OMX_U32 iHeight,
+ OMX_U32 iWidth
+)
+{
+ OMX_INT x, y;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrcOrg == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcRef == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr)
+
+ *pDstSAD = 0;
+ for (y = 0; y < iHeight; y++)
+ {
+ for (x = 0; x < iWidth; x++)
+ {
+ *pDstSAD += armAbs(pSrcOrg [(y * iStepOrg) + x] -
+ pSrcRef [(y * iStepRef) + x]);
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_16x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_16x.c
new file mode 100644
index 0000000..6d1447e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_16x.c
@@ -0,0 +1,86 @@
+/**
+ *
+ * File Name: omxVCCOMM_Average_16x.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate Average of two 16x16 or 16x8 blocks
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCCOMM_Average_16x (6.1.3.1.2)
+ *
+ * Description:
+ * This function calculates the average of two 16x16 or 16x8 blocks. The
+ * result is rounded according to (a+b+1)/2. The block average function can
+ * be used in conjunction with half-pixel interpolation to obtain quarter
+ * pixel motion estimates, as described in [ISO14496-10], subclause 8.4.2.2.1.
+ *
+ * Input Arguments:
+ *
+ * pPred0 - Pointer to the top-left corner of reference block 0
+ * pPred1 - Pointer to the top-left corner of reference block 1
+ * iPredStep0 - Step of reference block 0
+ * iPredStep1 - Step of reference block 1
+ * iDstStep - Step of the destination buffer
+ * iHeight - Height of the blocks
+ *
+ * Output Arguments:
+ *
+ * pDstPred - Pointer to the destination buffer. 16-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pPred0, pPred1, or
+ * pDstPred.
+ * - pDstPred is not aligned on a 16-byte boundary.
+ * - iPredStep0 <= 0 or iPredStep0 is not a multiple of 16.
+ * - iPredStep1 <= 0 or iPredStep1 is not a multiple of 16.
+ * - iDstStep <= 0 or iDstStep is not a multiple of 16.
+ * - iHeight is not 8 or 16.
+ *
+ */
+ OMXResult omxVCCOMM_Average_16x (
+ const OMX_U8* pPred0,
+ const OMX_U8* pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8* pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iHeight
+)
+{
+ /* check for argument error */
+ armRetArgErrIf(pPred0 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pPred1 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstPred == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf((iHeight != 8) && (iHeight != 16), OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot16ByteAligned(pDstPred), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iPredStep0 == 0) || (iPredStep0 & 15), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iPredStep1 == 0) || (iPredStep1 & 15), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iDstStep == 0) || (iDstStep & 15), OMX_Sts_BadArgErr)
+
+ return armVCCOMM_Average
+ (pPred0, pPred1, iPredStep0, iPredStep1, pDstPred, iDstStep, 16, iHeight);
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_8x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_8x.c
new file mode 100644
index 0000000..17b1326
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Average_8x.c
@@ -0,0 +1,87 @@
+/**
+ *
+ * File Name: omxVCCOMM_Average_8x.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate Average of two 8x4 or 8x8 or 8x16 blocks
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCCOMM_Average_8x (6.1.3.1.1)
+ *
+ * Description:
+ * This function calculates the average of two 8x4, 8x8, or 8x16 blocks. The
+ * result is rounded according to (a+b+1)/2. The block average function can
+ * be used in conjunction with half-pixel interpolation to obtain quarter
+ * pixel motion estimates, as described in [ISO14496-10], subclause 8.4.2.2.1.
+ *
+ * Input Arguments:
+ *
+ * pPred0 - Pointer to the top-left corner of reference block 0
+ * pPred1 - Pointer to the top-left corner of reference block 1
+ * iPredStep0 - Step of reference block 0
+ * iPredStep1 - Step of reference block 1
+ * iDstStep - Step of the destination buffer.
+ * iHeight - Height of the blocks
+ *
+ * Output Arguments:
+ *
+ * pDstPred - Pointer to the destination buffer. 8-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pPred0, pPred1, or
+ * pDstPred.
+ * - pDstPred is not aligned on an 8-byte boundary.
+ * - iPredStep0 <= 0 or iPredStep0 is not a multiple of 8.
+ * - iPredStep1 <= 0 or iPredStep1 is not a multiple of 8.
+ * - iDstStep <= 0 or iDstStep is not a multiple of 8.
+ * - iHeight is not 4, 8, or 16.
+ *
+ */
+ OMXResult omxVCCOMM_Average_8x (
+ const OMX_U8* pPred0,
+ const OMX_U8* pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8* pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iHeight
+)
+{
+ /* check for argument error */
+ armRetArgErrIf(pPred0 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pPred1 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstPred == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf((iPredStep0 == 0) || (iPredStep0 & 7), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iPredStep1 == 0) || (iPredStep1 & 7), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iDstStep == 0) || (iDstStep & 7), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iHeight != 4) && (iHeight != 8) && (iHeight != 16), OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot8ByteAligned(pDstPred), OMX_Sts_BadArgErr)
+
+ return armVCCOMM_Average
+ (pPred0, pPred1, iPredStep0, iPredStep1, pDstPred, iDstStep, 8, iHeight);
+}
+
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock.c
new file mode 100644
index 0000000..e559adf
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock.c
@@ -0,0 +1,88 @@
+/**
+ *
+ * File Name: omxVCCOMM_ComputeTextureErrorBlock.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module computing the error for a MB of size 8x8
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCCOMM_ComputeTextureErrorBlock (6.1.4.1.2)
+ *
+ * Description:
+ * Computes the texture error of the block.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the source plane. This should be aligned on an 8-byte
+ * boundary.
+ * srcStep - step of the source plane
+ * pSrcRef - pointer to the reference buffer, an 8x8 block. This should be
+ * aligned on an 8-byte boundary.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination buffer, an 8x8 block. This should be
+ * aligned on an 8-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is NULL:
+ * pSrc, pSrcRef, pDst.
+ * - pSrc is not 8-byte aligned.
+ * - SrcStep <= 0 or srcStep is not a multiple of 8.
+ * - pSrcRef is not 8-byte aligned.
+ * - pDst is not 8-byte aligned
+ *
+ */
+
+OMXResult omxVCCOMM_ComputeTextureErrorBlock(
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ const OMX_U8 *pSrcRef,
+ OMX_S16 * pDst
+)
+{
+
+ OMX_INT x, y, count;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcRef == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs8ByteAligned(pSrc), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs8ByteAligned(pSrcRef), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs8ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf((srcStep <= 0) || (srcStep & 7), OMX_Sts_BadArgErr);
+
+ /* Calculate the error block */
+ for (y = 0, count = 0;
+ y < 8;
+ y++, pSrc += srcStep)
+ {
+ for (x = 0; x < 8; x++, count++)
+ {
+ pDst[count] = pSrc[x] - pSrcRef[count];
+ }
+ }
+
+ return OMX_Sts_NoErr;
+
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock_SAD.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock_SAD.c
new file mode 100644
index 0000000..c4731aa
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ComputeTextureErrorBlock_SAD.c
@@ -0,0 +1,93 @@
+/**
+ *
+ * File Name: omxVCCOMM_ComputeTextureErrorBlock_SAD.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module computing the error for a MB of size 8x8
+ *
+ */
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+
+/**
+ * Function: omxVCCOMM_ComputeTextureErrorBlock_SAD (6.1.4.1.1)
+ *
+ * Description:
+ * Computes texture error of the block; also returns SAD.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the source plane; must be aligned on an 8-byte
+ * boundary.
+ * srcStep - step of the source plane
+ * pSrcRef - pointer to the reference buffer, an 8x8 block; must be aligned
+ * on an 8-byte boundary.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination buffer, an 8x8 block; must be aligned
+ * on an 8-byte boundary.
+ * pDstSAD - pointer to the Sum of Absolute Differences (SAD) value
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - At least one of the following
+ * pointers is NULL: pSrc, pSrcRef, pDst and pDstSAD.
+ * - pSrc is not 8-byte aligned.
+ * - SrcStep <= 0 or srcStep is not a multiple of 8.
+ * - pSrcRef is not 8-byte aligned.
+ * - pDst is not 8-byte aligned.
+ *
+ */
+
+OMXResult omxVCCOMM_ComputeTextureErrorBlock_SAD(
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ const OMX_U8 *pSrcRef,
+ OMX_S16 * pDst,
+ OMX_INT *pDstSAD
+)
+{
+
+ OMX_INT x, y, count;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcRef == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs8ByteAligned(pSrc), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs8ByteAligned(pSrcRef), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs8ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf((srcStep <= 0) || (srcStep & 7), OMX_Sts_BadArgErr);
+
+ /* Calculate the error block */
+ for (y = 0, count = 0, *pDstSAD = 0;
+ y < 8;
+ y++, pSrc += srcStep)
+ {
+ for (x = 0; x < 8; x++, count++)
+ {
+ pDst[count] = pSrc[x] - pSrcRef[count];
+ *pDstSAD += armAbs(pDst[count]);
+ }
+ }
+
+ return OMX_Sts_NoErr;
+
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy16x16.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy16x16.c
new file mode 100644
index 0000000..4857024
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy16x16.c
@@ -0,0 +1,79 @@
+/**
+ *
+ * File Name: omxVCCOMM_Copy16x16.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * MPEG4 16x16 Copy module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCCOMM_Copy16x16 (6.1.3.3.2)
+ *
+ * Description:
+ * Copies the reference 16x16 macroblock to the current macroblock.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the reference macroblock in the source frame; must be
+ * aligned on a 16-byte boundary.
+ * step - distance between the starts of consecutive lines in the reference
+ * frame, in bytes; must be a multiple of 16 and must be larger
+ * than or equal to 16.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination macroblock; must be aligned on a
+ * 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pSrc, pDst
+ * - one or more of the following pointers is not aligned on a 16-byte
+ * boundary: pSrc, pDst
+ * - step <16 or step is not a multiple of 16.
+ *
+ */
+
+OMXResult omxVCCOMM_Copy16x16(
+ const OMX_U8 *pSrc,
+ OMX_U8 *pDst,
+ OMX_INT step)
+ {
+ /* Definitions and Initializations*/
+
+ OMX_INT count,index, x, y;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pSrc), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(((step < 16) || (step % 16)), OMX_Sts_BadArgErr);
+
+
+ /* Copying the ref 16x16 blk to the curr blk */
+ for (y = 0, count = 0, index = 0; y < 16; y++, count = count + step - 16)
+ {
+ for (x = 0; x < 16; x++, count++, index++)
+ {
+ pDst[index] = pSrc[count];
+ }
+ }
+ return OMX_Sts_NoErr;
+ }
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy8x8.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy8x8.c
new file mode 100644
index 0000000..a4f9dde
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_Copy8x8.c
@@ -0,0 +1,79 @@
+/**
+ *
+ * File Name: omxVCCOMM_Copy8x8.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * MPEG4 8x8 Copy module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCCOMM_Copy8x8 (6.1.3.3.1)
+ *
+ * Description:
+ * Copies the reference 8x8 block to the current block.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the reference block in the source frame; must be
+ * aligned on an 8-byte boundary.
+ * step - distance between the starts of consecutive lines in the reference
+ * frame, in bytes; must be a multiple of 8 and must be larger than
+ * or equal to 8.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination block; must be aligned on an 8-byte
+ * boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - one or more of the following pointers is NULL: pSrc, pDst
+ * - one or more of the following pointers is not aligned on an 8-byte
+ * boundary: pSrc, pDst
+ * - step <8 or step is not a multiple of 8.
+ *
+ */
+
+OMXResult omxVCCOMM_Copy8x8(
+ const OMX_U8 *pSrc,
+ OMX_U8 *pDst,
+ OMX_INT step)
+ {
+ /* Definitions and Initializations*/
+
+ OMX_INT count,index, x, y;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs8ByteAligned(pSrc), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs8ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(((step < 8) || (step % 8)), OMX_Sts_BadArgErr);
+
+
+ /* Copying the ref 8x8 blk to the curr blk */
+ for (y = 0, count = 0, index = 0; y < 8; y++, count = count + step - 8)
+ {
+ for (x = 0; x < 8; x++, count++, index++)
+ {
+ pDst[index] = pSrc[count];
+ }
+ }
+ return OMX_Sts_NoErr;
+ }
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ExpandFrame_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ExpandFrame_I.c
new file mode 100644
index 0000000..9536df7
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_ExpandFrame_I.c
@@ -0,0 +1,126 @@
+/**
+ *
+ * File Name: omxVCCOMM_ExpandFrame_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will Expand Frame boundary pixels into Plane
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCCOMM_ExpandFrame_I (6.1.3.2.1)
+ *
+ * Description:
+ * This function expands a reconstructed frame in-place. The unexpanded
+ * source frame should be stored in a plane buffer with sufficient space
+ * pre-allocated for edge expansion, and the input frame should be located in
+ * the plane buffer center. This function executes the pixel expansion by
+ * replicating source frame edge pixel intensities in the empty pixel
+ * locations (expansion region) between the source frame edge and the plane
+ * buffer edge. The width/height of the expansion regions on the
+ * horizontal/vertical edges is controlled by the parameter iExpandPels.
+ *
+ * Input Arguments:
+ *
+ * pSrcDstPlane - pointer to the top-left corner of the frame to be
+ * expanded; must be aligned on an 8-byte boundary.
+ * iFrameWidth - frame width; must be a multiple of 8.
+ * iFrameHeight -frame height; must be a multiple of 8.
+ * iExpandPels - number of pixels to be expanded in the horizontal and
+ * vertical directions; must be a multiple of 8.
+ * iPlaneStep - distance, in bytes, between the start of consecutive lines
+ * in the plane buffer; must be larger than or equal to
+ * (iFrameWidth + 2 * iExpandPels).
+ *
+ * Output Arguments:
+ *
+ * pSrcDstPlane -Pointer to the top-left corner of the frame (NOT the
+ * top-left corner of the plane); must be aligned on an 8-byte
+ * boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - pSrcDstPlane is NULL.
+ * - pSrcDstPlane is not aligned on an 8-byte boundary.
+ * - one of the following parameters is either equal to zero or is a
+ * non-multiple of 8: iFrameHeight, iFrameWidth, iPlaneStep, or
+ * iExpandPels.
+ * - iPlaneStep < (iFrameWidth + 2 * iExpandPels).
+ *
+ */
+OMXResult omxVCCOMM_ExpandFrame_I(
+ OMX_U8* pSrcDstPlane,
+ OMX_U32 iFrameWidth,
+ OMX_U32 iFrameHeight,
+ OMX_U32 iExpandPels,
+ OMX_U32 iPlaneStep
+)
+{
+ OMX_INT x, y;
+ OMX_U8* pLeft;
+ OMX_U8* pRight;
+ OMX_U8* pTop;
+ OMX_U8* pBottom;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrcDstPlane == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot8ByteAligned(pSrcDstPlane), OMX_Sts_BadArgErr)
+ armRetArgErrIf(iFrameWidth == 0 || iFrameWidth & 7, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iFrameHeight== 0 || iFrameHeight & 7, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iExpandPels == 0 || iExpandPels & 7, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iPlaneStep == 0 || iPlaneStep & 7, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iPlaneStep < (iFrameWidth + 2 * iExpandPels),
+ OMX_Sts_BadArgErr)
+
+ /* Top and Bottom */
+ pTop = pSrcDstPlane - (iExpandPels * iPlaneStep);
+ pBottom = pSrcDstPlane + (iFrameHeight * iPlaneStep);
+
+ for (y = 0; y < (OMX_INT)iExpandPels; y++)
+ {
+ for (x = 0; x < (OMX_INT)iFrameWidth; x++)
+ {
+ pTop [y * iPlaneStep + x] =
+ pSrcDstPlane [x];
+ pBottom [y * iPlaneStep + x] =
+ pSrcDstPlane [(iFrameHeight - 1) * iPlaneStep + x];
+ }
+ }
+
+ /* Left, Right and Corners */
+ pLeft = pSrcDstPlane - iExpandPels;
+ pRight = pSrcDstPlane + iFrameWidth;
+
+ for (y = -(OMX_INT)iExpandPels; y < (OMX_INT)(iFrameHeight + iExpandPels); y++)
+ {
+ for (x = 0; x < (OMX_INT)iExpandPels; x++)
+ {
+ pLeft [y * iPlaneStep + x] =
+ pSrcDstPlane [y * iPlaneStep + 0];
+ pRight [y * iPlaneStep + x] =
+ pSrcDstPlane [y * iPlaneStep + (iFrameWidth - 1)];
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_LimitMVToRect.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_LimitMVToRect.c
new file mode 100644
index 0000000..af04582
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_LimitMVToRect.c
@@ -0,0 +1,81 @@
+/**
+ *
+ * File Name: omxVCCOMM_LimitMVToRect.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for limiting the MV
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCCOMM_LimitMVToRect (6.1.4.1.3)
+ *
+ * Description:
+ * Limits the motion vector associated with the current block/macroblock to
+ * prevent the motion compensated block/macroblock from moving outside a
+ * bounding rectangle as shown in Figure 6-1.
+ *
+ * Input Arguments:
+ *
+ * pSrcMV - pointer to the motion vector associated with the current block
+ * or macroblock
+ * pRectVOPRef - pointer to the bounding rectangle
+ * Xcoord, Ycoord - coordinates of the current block or macroblock
+ * size - size of the current block or macroblock; must be equal to 8 or
+ * 16.
+ *
+ * Output Arguments:
+ *
+ * pDstMV - pointer to the limited motion vector
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcMV, pDstMV, or pRectVOPRef.
+ * - size is not equal to either 8 or 16.
+ * - the width or height of the bounding rectangle is less than
+ * twice the block size.
+ */
+OMXResult omxVCCOMM_LimitMVToRect(
+ const OMXVCMotionVector * pSrcMV,
+ OMXVCMotionVector *pDstMV,
+ const OMXRect * pRectVOPRef,
+ OMX_INT Xcoord,
+ OMX_INT Ycoord,
+ OMX_INT size
+)
+{
+ /* Argument error checks */
+ armRetArgErrIf(pSrcMV == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDstMV == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pRectVOPRef == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((size != 8) && (size != 16), OMX_Sts_BadArgErr);
+ armRetArgErrIf((pRectVOPRef->width < (2* size)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((pRectVOPRef->height < (2* size)), OMX_Sts_BadArgErr);
+
+ pDstMV->dx = armMin (armMax (pSrcMV->dx, 2*pRectVOPRef->x - Xcoord),
+ (2*pRectVOPRef->x + pRectVOPRef->width - Xcoord - size));
+ pDstMV->dy = armMin (armMax (pSrcMV->dy, 2*pRectVOPRef->y - Ycoord),
+ (2*pRectVOPRef->y + pRectVOPRef->height - Ycoord - size));
+
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_16x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_16x.c
new file mode 100644
index 0000000..0f0cedb
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_16x.c
@@ -0,0 +1,80 @@
+/**
+ *
+ * File Name: omxVCCOMM_SAD_16x.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate SAD for 16x16 and 16x8 blocks
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCCOMM_SAD_16x (6.1.4.1.4)
+ *
+ * Description:
+ * This function calculates the SAD for 16x16 and 16x8 blocks.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to the original block; must be aligned on a 16-byte
+ * boundary.
+ * iStepOrg - Step of the original block buffer
+ * pSrcRef - Pointer to the reference block
+ * iStepRef - Step of the reference block buffer
+ * iHeight - Height of the block
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - Pointer of result SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pDstSAD, or pSrcRef
+ * - pSrcOrg is not 16-byte aligned.
+ * - iStepOrg <= 0 or iStepOrg is not a multiple of 16
+ * - iStepRef <= 0 or iStepRef is not a multiple of 16
+ * - iHeight is not 8 or 16
+ *
+ */
+OMXResult omxVCCOMM_SAD_16x(
+ const OMX_U8* pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8* pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32* pDstSAD,
+ OMX_U32 iHeight
+)
+{
+ /* check for argument error */
+ armRetArgErrIf(pSrcOrg == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcRef == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf((iHeight != 16) && (iHeight != 8), OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot16ByteAligned(pSrcOrg), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iStepOrg == 0) || (iStepOrg & 15), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iStepRef == 0) || (iStepRef & 15), OMX_Sts_BadArgErr)
+
+ return armVCCOMM_SAD
+ (pSrcOrg, iStepOrg, pSrcRef, iStepRef, pDstSAD, iHeight, 16);
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_8x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_8x.c
new file mode 100644
index 0000000..1421d99
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/comm/src/omxVCCOMM_SAD_8x.c
@@ -0,0 +1,80 @@
+/**
+ *
+ * File Name: omxVCCOMM_SAD_8x.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate SAD for 8x16, 8x8, 8x4 blocks
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCCOMM_SAD_8x (6.1.4.1.5)
+ *
+ * Description:
+ * This function calculates the SAD for 8x16, 8x8, 8x4 blocks.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to the original block; must be aligned on a 8-byte
+ * boundary.
+ * iStepOrg - Step of the original block buffer
+ * pSrcRef - Pointer to the reference block
+ * iStepRef - Step of the reference block buffer
+ * iHeight - Height of the block
+ *
+ * Output Arguments:
+ *
+ * pDstSAD -Pointer of result SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pDstSAD, or pSrcRef
+ * - pSrcOrg is not 8-byte aligned.
+ * - iStepOrg <= 0 or iStepOrg is not a multiple of 8
+ * - iStepRef <= 0 or iStepRef is not a multiple of 8
+ * - iHeight is not 4, 8 or 16
+ *
+ */
+OMXResult omxVCCOMM_SAD_8x(
+ const OMX_U8* pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8* pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32* pDstSAD,
+ OMX_U32 iHeight
+)
+{
+ /* check for argument error */
+ armRetArgErrIf(pSrcOrg == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcRef == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf((iHeight != 16) && (iHeight != 8) && (iHeight != 4), OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot8ByteAligned(pSrcOrg), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iStepOrg == 0) || (iStepOrg & 7), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iStepRef == 0) || (iStepRef & 7), OMX_Sts_BadArgErr)
+
+ return armVCCOMM_SAD
+ (pSrcOrg, iStepOrg, pSrcRef, iStepRef, pDstSAD, iHeight, 8);
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/api/armVCM4P10_CAVLCTables.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/api/armVCM4P10_CAVLCTables.h
new file mode 100644
index 0000000..8d18a8f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/api/armVCM4P10_CAVLCTables.h
@@ -0,0 +1,34 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_CAVLCTables.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * ----------------------------------------------------------------
+ * File: armVCM4P10_CAVLCTables.h
+ * ----------------------------------------------------------------
+ *
+ * Header file for ARM implementation of OpenMAX VCM4P10
+ *
+ */
+
+#ifndef ARMVCM4P10_CAVLCTABLES_H
+#define ARMVCM4P10_CAVLCTABLES_H
+
+/* CAVLC tables */
+
+extern const OMX_U8 armVCM4P10_CAVLCTrailingOnes[62];
+extern const OMX_U8 armVCM4P10_CAVLCTotalCoeff[62];
+extern const ARM_VLC32 *armVCM4P10_CAVLCCoeffTokenTables[5];
+extern const ARM_VLC32 armVCM4P10_CAVLCLevelPrefix[17];
+extern const ARM_VLC32 *armVCM4P10_CAVLCTotalZeroTables[15];
+extern const ARM_VLC32 *armVCM4P10_CAVLCTotalZeros2x2Tables[3];
+extern const ARM_VLC32 *armVCM4P10_CAVLCRunBeforeTables[7];
+
+#endif
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CAVLCTables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CAVLCTables.c
new file mode 100644
index 0000000..f4e36ad
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CAVLCTables.c
@@ -0,0 +1,703 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_CAVLCTables.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * CAVLC tables for H.264
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM_Bitstream.h"
+#include "armVC.h"
+#include "armVCM4P10_CAVLCTables.h"
+
+/* Tables mapping a code to TrailingOnes and TotalCoeff */
+
+const OMX_U8 armVCM4P10_CAVLCTrailingOnes[62] = {
+ 0,
+ 0, 1,
+ 0, 1, 2,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3,
+ 0, 1, 2, 3
+};
+
+const OMX_U8 armVCM4P10_CAVLCTotalCoeff[62] = {
+ 0,
+ 1, 1,
+ 2, 2, 2,
+ 3, 3, 3, 3,
+ 4, 4, 4, 4,
+ 5, 5, 5, 5,
+ 6, 6, 6, 6,
+ 7, 7, 7, 7,
+ 8, 8, 8, 8,
+ 9, 9, 9, 9,
+ 10, 10, 10, 10,
+ 11, 11, 11, 11,
+ 12, 12, 12, 12,
+ 13, 13, 13, 13,
+ 14, 14, 14, 14,
+ 15, 15, 15, 15,
+ 16, 16, 16, 16
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCCoeffToken0[63] = {
+ { 1, 0x0001 },
+ { 6, 0x0005 },
+ { 2, 0x0001 },
+ { 8, 0x0007 },
+ { 6, 0x0004 },
+ { 3, 0x0001 },
+ { 9, 0x0007 },
+ { 8, 0x0006 },
+ { 7, 0x0005 },
+ { 5, 0x0003 },
+ { 10, 0x0007 },
+ { 9, 0x0006 },
+ { 8, 0x0005 },
+ { 6, 0x0003 },
+ { 11, 0x0007 },
+ { 10, 0x0006 },
+ { 9, 0x0005 },
+ { 7, 0x0004 },
+ { 13, 0x000f },
+ { 11, 0x0006 },
+ { 10, 0x0005 },
+ { 8, 0x0004 },
+ { 13, 0x000b },
+ { 13, 0x000e },
+ { 11, 0x0005 },
+ { 9, 0x0004 },
+ { 13, 0x0008 },
+ { 13, 0x000a },
+ { 13, 0x000d },
+ { 10, 0x0004 },
+ { 14, 0x000f },
+ { 14, 0x000e },
+ { 13, 0x0009 },
+ { 11, 0x0004 },
+ { 14, 0x000b },
+ { 14, 0x000a },
+ { 14, 0x000d },
+ { 13, 0x000c },
+ { 15, 0x000f },
+ { 15, 0x000e },
+ { 14, 0x0009 },
+ { 14, 0x000c },
+ { 15, 0x000b },
+ { 15, 0x000a },
+ { 15, 0x000d },
+ { 14, 0x0008 },
+ { 16, 0x000f },
+ { 15, 0x0001 },
+ { 15, 0x0009 },
+ { 15, 0x000c },
+ { 16, 0x000b },
+ { 16, 0x000e },
+ { 16, 0x000d },
+ { 15, 0x0008 },
+ { 16, 0x0007 },
+ { 16, 0x000a },
+ { 16, 0x0009 },
+ { 16, 0x000c },
+ { 16, 0x0004 },
+ { 16, 0x0006 },
+ { 16, 0x0005 },
+ { 16, 0x0008 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCCoeffToken1[63] = {
+ { 2, 0x0003 },
+ { 6, 0x000b },
+ { 2, 0x0002 },
+ { 6, 0x0007 },
+ { 5, 0x0007 },
+ { 3, 0x0003 },
+ { 7, 0x0007 },
+ { 6, 0x000a },
+ { 6, 0x0009 },
+ { 4, 0x0005 },
+ { 8, 0x0007 },
+ { 6, 0x0006 },
+ { 6, 0x0005 },
+ { 4, 0x0004 },
+ { 8, 0x0004 },
+ { 7, 0x0006 },
+ { 7, 0x0005 },
+ { 5, 0x0006 },
+ { 9, 0x0007 },
+ { 8, 0x0006 },
+ { 8, 0x0005 },
+ { 6, 0x0008 },
+ { 11, 0x000f },
+ { 9, 0x0006 },
+ { 9, 0x0005 },
+ { 6, 0x0004 },
+ { 11, 0x000b },
+ { 11, 0x000e },
+ { 11, 0x000d },
+ { 7, 0x0004 },
+ { 12, 0x000f },
+ { 11, 0x000a },
+ { 11, 0x0009 },
+ { 9, 0x0004 },
+ { 12, 0x000b },
+ { 12, 0x000e },
+ { 12, 0x000d },
+ { 11, 0x000c },
+ { 12, 0x0008 },
+ { 12, 0x000a },
+ { 12, 0x0009 },
+ { 11, 0x0008 },
+ { 13, 0x000f },
+ { 13, 0x000e },
+ { 13, 0x000d },
+ { 12, 0x000c },
+ { 13, 0x000b },
+ { 13, 0x000a },
+ { 13, 0x0009 },
+ { 13, 0x000c },
+ { 13, 0x0007 },
+ { 14, 0x000b },
+ { 13, 0x0006 },
+ { 13, 0x0008 },
+ { 14, 0x0009 },
+ { 14, 0x0008 },
+ { 14, 0x000a },
+ { 13, 0x0001 },
+ { 14, 0x0007 },
+ { 14, 0x0006 },
+ { 14, 0x0005 },
+ { 14, 0x0004 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCCoeffToken2[63] = {
+ { 4, 0x000f },
+ { 6, 0x000f },
+ { 4, 0x000e },
+ { 6, 0x000b },
+ { 5, 0x000f },
+ { 4, 0x000d },
+ { 6, 0x0008 },
+ { 5, 0x000c },
+ { 5, 0x000e },
+ { 4, 0x000c },
+ { 7, 0x000f },
+ { 5, 0x000a },
+ { 5, 0x000b },
+ { 4, 0x000b },
+ { 7, 0x000b },
+ { 5, 0x0008 },
+ { 5, 0x0009 },
+ { 4, 0x000a },
+ { 7, 0x0009 },
+ { 6, 0x000e },
+ { 6, 0x000d },
+ { 4, 0x0009 },
+ { 7, 0x0008 },
+ { 6, 0x000a },
+ { 6, 0x0009 },
+ { 4, 0x0008 },
+ { 8, 0x000f },
+ { 7, 0x000e },
+ { 7, 0x000d },
+ { 5, 0x000d },
+ { 8, 0x000b },
+ { 8, 0x000e },
+ { 7, 0x000a },
+ { 6, 0x000c },
+ { 9, 0x000f },
+ { 8, 0x000a },
+ { 8, 0x000d },
+ { 7, 0x000c },
+ { 9, 0x000b },
+ { 9, 0x000e },
+ { 8, 0x0009 },
+ { 8, 0x000c },
+ { 9, 0x0008 },
+ { 9, 0x000a },
+ { 9, 0x000d },
+ { 8, 0x0008 },
+ { 10, 0x000d },
+ { 9, 0x0007 },
+ { 9, 0x0009 },
+ { 9, 0x000c },
+ { 10, 0x0009 },
+ { 10, 0x000c },
+ { 10, 0x000b },
+ { 10, 0x000a },
+ { 10, 0x0005 },
+ { 10, 0x0008 },
+ { 10, 0x0007 },
+ { 10, 0x0006 },
+ { 10, 0x0001 },
+ { 10, 0x0004 },
+ { 10, 0x0003 },
+ { 10, 0x0002 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCCoeffToken3[63] = {
+ { 6, 0x0003 },
+ { 6, 0x0000 },
+ { 6, 0x0001 },
+ { 6, 0x0004 },
+ { 6, 0x0005 },
+ { 6, 0x0006 },
+ { 6, 0x0008 },
+ { 6, 0x0009 },
+ { 6, 0x000a },
+ { 6, 0x000b },
+ { 6, 0x000c },
+ { 6, 0x000d },
+ { 6, 0x000e },
+ { 6, 0x000f },
+ { 6, 0x0010 },
+ { 6, 0x0011 },
+ { 6, 0x0012 },
+ { 6, 0x0013 },
+ { 6, 0x0014 },
+ { 6, 0x0015 },
+ { 6, 0x0016 },
+ { 6, 0x0017 },
+ { 6, 0x0018 },
+ { 6, 0x0019 },
+ { 6, 0x001a },
+ { 6, 0x001b },
+ { 6, 0x001c },
+ { 6, 0x001d },
+ { 6, 0x001e },
+ { 6, 0x001f },
+ { 6, 0x0020 },
+ { 6, 0x0021 },
+ { 6, 0x0022 },
+ { 6, 0x0023 },
+ { 6, 0x0024 },
+ { 6, 0x0025 },
+ { 6, 0x0026 },
+ { 6, 0x0027 },
+ { 6, 0x0028 },
+ { 6, 0x0029 },
+ { 6, 0x002a },
+ { 6, 0x002b },
+ { 6, 0x002c },
+ { 6, 0x002d },
+ { 6, 0x002e },
+ { 6, 0x002f },
+ { 6, 0x0030 },
+ { 6, 0x0031 },
+ { 6, 0x0032 },
+ { 6, 0x0033 },
+ { 6, 0x0034 },
+ { 6, 0x0035 },
+ { 6, 0x0036 },
+ { 6, 0x0037 },
+ { 6, 0x0038 },
+ { 6, 0x0039 },
+ { 6, 0x003a },
+ { 6, 0x003b },
+ { 6, 0x003c },
+ { 6, 0x003d },
+ { 6, 0x003e },
+ { 6, 0x003f },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCCoeffToken4[15] = {
+ { 2, 0x0001 },
+ { 6, 0x0007 },
+ { 1, 0x0001 },
+ { 6, 0x0004 },
+ { 6, 0x0006 },
+ { 3, 0x0001 },
+ { 6, 0x0003 },
+ { 7, 0x0003 },
+ { 7, 0x0002 },
+ { 6, 0x0005 },
+ { 6, 0x0002 },
+ { 8, 0x0003 },
+ { 8, 0x0002 },
+ { 7, 0x0000 },
+ { 0, 0x0000 }
+};
+
+
+const ARM_VLC32 *armVCM4P10_CAVLCCoeffTokenTables[5] = {
+ armVCM4P10_CAVLCCoeffToken0,
+ armVCM4P10_CAVLCCoeffToken1,
+ armVCM4P10_CAVLCCoeffToken2,
+ armVCM4P10_CAVLCCoeffToken3,
+ armVCM4P10_CAVLCCoeffToken4
+};
+
+/* Table for level_prefix */
+
+const ARM_VLC32 armVCM4P10_CAVLCLevelPrefix[17] = {
+ { 1, 1},
+ { 2, 1},
+ { 3, 1},
+ { 4, 1},
+ { 5, 1},
+ { 6, 1},
+ { 7, 1},
+ { 8, 1},
+ { 9, 1},
+ { 10, 1},
+ { 11, 1},
+ { 12, 1},
+ { 13, 1},
+ { 14, 1},
+ { 15, 1},
+ { 16, 1},
+ { 0, 0}
+};
+
+/* Tables for total_zeros */
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros1[17] = {
+ { 1, 0x0001 },
+ { 3, 0x0003 },
+ { 3, 0x0002 },
+ { 4, 0x0003 },
+ { 4, 0x0002 },
+ { 5, 0x0003 },
+ { 5, 0x0002 },
+ { 6, 0x0003 },
+ { 6, 0x0002 },
+ { 7, 0x0003 },
+ { 7, 0x0002 },
+ { 8, 0x0003 },
+ { 8, 0x0002 },
+ { 9, 0x0003 },
+ { 9, 0x0002 },
+ { 9, 0x0001 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros2[16] = {
+ { 3, 0x0007 },
+ { 3, 0x0006 },
+ { 3, 0x0005 },
+ { 3, 0x0004 },
+ { 3, 0x0003 },
+ { 4, 0x0005 },
+ { 4, 0x0004 },
+ { 4, 0x0003 },
+ { 4, 0x0002 },
+ { 5, 0x0003 },
+ { 5, 0x0002 },
+ { 6, 0x0003 },
+ { 6, 0x0002 },
+ { 6, 0x0001 },
+ { 6, 0x0000 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros3[15] = {
+ { 4, 0x0005 },
+ { 3, 0x0007 },
+ { 3, 0x0006 },
+ { 3, 0x0005 },
+ { 4, 0x0004 },
+ { 4, 0x0003 },
+ { 3, 0x0004 },
+ { 3, 0x0003 },
+ { 4, 0x0002 },
+ { 5, 0x0003 },
+ { 5, 0x0002 },
+ { 6, 0x0001 },
+ { 5, 0x0001 },
+ { 6, 0x0000 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros4[14] = {
+ { 5, 0x0003 },
+ { 3, 0x0007 },
+ { 4, 0x0005 },
+ { 4, 0x0004 },
+ { 3, 0x0006 },
+ { 3, 0x0005 },
+ { 3, 0x0004 },
+ { 4, 0x0003 },
+ { 3, 0x0003 },
+ { 4, 0x0002 },
+ { 5, 0x0002 },
+ { 5, 0x0001 },
+ { 5, 0x0000 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros5[13] = {
+ { 4, 0x0005 },
+ { 4, 0x0004 },
+ { 4, 0x0003 },
+ { 3, 0x0007 },
+ { 3, 0x0006 },
+ { 3, 0x0005 },
+ { 3, 0x0004 },
+ { 3, 0x0003 },
+ { 4, 0x0002 },
+ { 5, 0x0001 },
+ { 4, 0x0001 },
+ { 5, 0x0000 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros6[12] = {
+ { 6, 0x0001 },
+ { 5, 0x0001 },
+ { 3, 0x0007 },
+ { 3, 0x0006 },
+ { 3, 0x0005 },
+ { 3, 0x0004 },
+ { 3, 0x0003 },
+ { 3, 0x0002 },
+ { 4, 0x0001 },
+ { 3, 0x0001 },
+ { 6, 0x0000 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros7[11] = {
+ { 6, 0x0001 },
+ { 5, 0x0001 },
+ { 3, 0x0005 },
+ { 3, 0x0004 },
+ { 3, 0x0003 },
+ { 2, 0x0003 },
+ { 3, 0x0002 },
+ { 4, 0x0001 },
+ { 3, 0x0001 },
+ { 6, 0x0000 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros8[10] = {
+ { 6, 0x0001 },
+ { 4, 0x0001 },
+ { 5, 0x0001 },
+ { 3, 0x0003 },
+ { 2, 0x0003 },
+ { 2, 0x0002 },
+ { 3, 0x0002 },
+ { 3, 0x0001 },
+ { 6, 0x0000 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros9[9] = {
+ { 6, 0x0001 },
+ { 6, 0x0000 },
+ { 4, 0x0001 },
+ { 2, 0x0003 },
+ { 2, 0x0002 },
+ { 3, 0x0001 },
+ { 2, 0x0001 },
+ { 5, 0x0001 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros10[8] = {
+ { 5, 0x0001 },
+ { 5, 0x0000 },
+ { 3, 0x0001 },
+ { 2, 0x0003 },
+ { 2, 0x0002 },
+ { 2, 0x0001 },
+ { 4, 0x0001 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros11[7] = {
+ { 4, 0x0000 },
+ { 4, 0x0001 },
+ { 3, 0x0001 },
+ { 3, 0x0002 },
+ { 1, 0x0001 },
+ { 3, 0x0003 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros12[6] = {
+ { 4, 0x0000 },
+ { 4, 0x0001 },
+ { 2, 0x0001 },
+ { 1, 0x0001 },
+ { 3, 0x0001 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros13[5] = {
+ { 3, 0x0000 },
+ { 3, 0x0001 },
+ { 1, 0x0001 },
+ { 2, 0x0001 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros14[4] = {
+ { 2, 0x0000 },
+ { 2, 0x0001 },
+ { 1, 0x0001 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros15[3] = {
+ { 1, 0x0000 },
+ { 1, 0x0001 },
+ { 0, 0x0000 }
+};
+
+const ARM_VLC32 *armVCM4P10_CAVLCTotalZeroTables[15] = {
+ armVCM4P10_CAVLCTotalZeros1,
+ armVCM4P10_CAVLCTotalZeros2,
+ armVCM4P10_CAVLCTotalZeros3,
+ armVCM4P10_CAVLCTotalZeros4,
+ armVCM4P10_CAVLCTotalZeros5,
+ armVCM4P10_CAVLCTotalZeros6,
+ armVCM4P10_CAVLCTotalZeros7,
+ armVCM4P10_CAVLCTotalZeros8,
+ armVCM4P10_CAVLCTotalZeros9,
+ armVCM4P10_CAVLCTotalZeros10,
+ armVCM4P10_CAVLCTotalZeros11,
+ armVCM4P10_CAVLCTotalZeros12,
+ armVCM4P10_CAVLCTotalZeros13,
+ armVCM4P10_CAVLCTotalZeros14,
+ armVCM4P10_CAVLCTotalZeros15
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros2x2_1[5] = {
+ { 1, 1 },
+ { 2, 1 },
+ { 3, 1 },
+ { 3, 0 },
+ { 0, 0 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros2x2_2[4] = {
+ { 1, 1 },
+ { 2, 1 },
+ { 2, 0 },
+ { 0, 0 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCTotalZeros2x2_3[3] = {
+ { 1, 1 },
+ { 1, 0 },
+ { 0, 0 }
+};
+
+const ARM_VLC32 *armVCM4P10_CAVLCTotalZeros2x2Tables[3] = {
+ armVCM4P10_CAVLCTotalZeros2x2_1,
+ armVCM4P10_CAVLCTotalZeros2x2_2,
+ armVCM4P10_CAVLCTotalZeros2x2_3
+};
+
+
+/* Tables for run_before */
+
+static const ARM_VLC32 armVCM4P10_CAVLCRunBefore1[3] = {
+ { 1, 0x0001 },
+ { 1, 0x0000 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCRunBefore2[4] = {
+ { 1, 0x0001 },
+ { 2, 0x0001 },
+ { 2, 0x0000 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCRunBefore3[5] = {
+ { 2, 0x0003 },
+ { 2, 0x0002 },
+ { 2, 0x0001 },
+ { 2, 0x0000 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCRunBefore4[6] = {
+ { 2, 0x0003 },
+ { 2, 0x0002 },
+ { 2, 0x0001 },
+ { 3, 0x0001 },
+ { 3, 0x0000 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCRunBefore5[7] = {
+ { 2, 0x0003 },
+ { 2, 0x0002 },
+ { 3, 0x0003 },
+ { 3, 0x0002 },
+ { 3, 0x0001 },
+ { 3, 0x0000 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCRunBefore6[8] = {
+ { 2, 0x0003 },
+ { 3, 0x0000 },
+ { 3, 0x0001 },
+ { 3, 0x0003 },
+ { 3, 0x0002 },
+ { 3, 0x0005 },
+ { 3, 0x0004 },
+ { 0, 0x0000 }
+};
+
+static const ARM_VLC32 armVCM4P10_CAVLCRunBefore7[16] = {
+ { 3, 0x0007 },
+ { 3, 0x0006 },
+ { 3, 0x0005 },
+ { 3, 0x0004 },
+ { 3, 0x0003 },
+ { 3, 0x0002 },
+ { 3, 0x0001 },
+ { 4, 0x0001 },
+ { 5, 0x0001 },
+ { 6, 0x0001 },
+ { 7, 0x0001 },
+ { 8, 0x0001 },
+ { 9, 0x0001 },
+ { 10, 0x0001 },
+ { 11, 0x0001 },
+ { 0, 0x0000 }
+};
+
+const ARM_VLC32 *armVCM4P10_CAVLCRunBeforeTables[7] = {
+ armVCM4P10_CAVLCRunBefore1,
+ armVCM4P10_CAVLCRunBefore2,
+ armVCM4P10_CAVLCRunBefore3,
+ armVCM4P10_CAVLCRunBefore4,
+ armVCM4P10_CAVLCRunBefore5,
+ armVCM4P10_CAVLCRunBefore6,
+ armVCM4P10_CAVLCRunBefore7
+};
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CompareMotionCostToMV.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CompareMotionCostToMV.c
new file mode 100644
index 0000000..e4bedc2
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_CompareMotionCostToMV.c
@@ -0,0 +1,133 @@
+/**
+ *
+ * File Name: armVCM4P10_CompareMotionCostToMV.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for comparing motion vectors and SAD's to decide
+ * the best MV and SAD
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: armVCM4P10_ExpGolBitsUsed
+ *
+ * Description:
+ * Performs calculating Exp-Golomb code length for a given values
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] val Signed number for which Exp-Golomb code length has
+ * to be calculated
+ *
+ * Return Value:
+ * Returns the length of the Exp-Golomb code for val
+ */
+
+static OMX_U16 armVCM4P10_ExpGolBitsUsed (OMX_S16 val)
+{
+ OMX_U16 sizeCodeNum, codeNum;
+
+ /* Mapping val to codeNum */
+ codeNum = armAbs (val);
+ if (val > 0)
+ {
+ codeNum = (2 * codeNum) - 1;
+ }
+ else
+ {
+ codeNum = 2 * codeNum;
+ }
+
+ /* Size of the exp-golomb code */
+ sizeCodeNum = (2 * armLogSize (codeNum + 1)) - 1;
+
+ return sizeCodeNum;
+}
+
+
+/**
+ * Function: armVCM4P10_CompareMotionCostToMV
+ *
+ * Description:
+ * Performs comparision of motion vectors and Motion cost to decide the
+ * best MV and best MC
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] mvX x coordinate of the candidate motion vector in 1/4 pel units
+ * [in] mvY y coordinate of the candidate motion vector in 1/4 pel units
+ * [in] diffMV differential MV
+ * [in] candSAD Candidate SAD
+ * [in] bestMV Best MV, contains best MV till the previous interation.
+ * [in] nLamda Lamda factor; used to compute motion cost
+ * [in] *pBestCost Contains the current best motion cost.
+ * [out] *pBestCost pBestCost Motion cost will be associated with the best MV
+ * after judgement;
+ * computed as SAD+Lamda*BitsUsedByMV, if the candCost is less
+ * than the best cost passed then the *pBestCost will be equal to candCost
+ * [out] bestMV Finally will have the best MV after the judgement.
+ *
+ * Return Value:
+ * OMX_INT -- 1 to indicate that the current motion cost is the best
+ * 0 to indicate that it is NOT the best motion cost
+ */
+
+OMX_INT armVCM4P10_CompareMotionCostToMV (
+ OMX_S16 mvX,
+ OMX_S16 mvY,
+ OMXVCMotionVector diffMV,
+ OMX_INT candSAD,
+ OMXVCMotionVector *bestMV,
+ OMX_U32 nLamda,
+ OMX_S32 *pBestCost
+)
+{
+ OMX_S32 candCost;
+ OMX_U16 sizeCodeNum;
+
+ sizeCodeNum = armVCM4P10_ExpGolBitsUsed (diffMV.dx);
+ sizeCodeNum += armVCM4P10_ExpGolBitsUsed (diffMV.dy);
+
+ /* Motion cost = SAD + lamda * ((bitsused(diffMVx) + (bitsused(diffMVy))*/
+ candCost = candSAD + (nLamda * sizeCodeNum);
+
+ /* Calculate candCost */
+ if (candCost < *pBestCost)
+ {
+ *pBestCost = candCost;
+ bestMV->dx = mvX;
+ bestMV->dy = mvY;
+ return 1;
+ }
+ if (candCost > *pBestCost)
+ {
+ return 0;
+ }
+ /* shorter motion vector */
+ if ( (mvX * mvX + mvY * mvY) < ((bestMV->dx * bestMV->dx) + (bestMV->dy * bestMV->dy)) )
+ {
+ *pBestCost = candCost;
+ bestMV->dx = mvX;
+ bestMV->dy = mvY;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*End of File*/
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DeBlockPixel.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DeBlockPixel.c
new file mode 100644
index 0000000..f4fb1d9
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DeBlockPixel.c
@@ -0,0 +1,151 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_DeBlockPixel.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 luma deblock module
+ *
+ */
+
+#ifdef DEBUG_ARMVCM4P10_DEBLOCKPIXEL
+#undef DEBUG_ON
+#define DEBUG_ON
+#endif /* DEBUG_ARMVCM4P10_DEBLOCKPIXEL */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/*
+ * Description
+ * Deblock one boundary pixel
+ *
+ * Parameters:
+ * [in] pQ0 Pointer to pixel q0
+ * [in] Step Step between pixels q0 and q1
+ * [in] tC0 Edge threshold value
+ * [in] alpha alpha threshold value
+ * [in] beta beta threshold value
+ * [in] bS deblocking strength
+ * [in] ChromaFlag True for chroma blocks
+ * [out] pQ0 Deblocked pixels
+ *
+ */
+
+void armVCM4P10_DeBlockPixel(
+ OMX_U8 *pQ0, /* pointer to the pixel q0 */
+ int Step, /* step between pixels q0 and q1 */
+ int tC0, /* edge threshold value */
+ int alpha, /* alpha */
+ int beta, /* beta */
+ int bS, /* deblocking strength */
+ int ChromaFlag
+)
+{
+ int p3, p2, p1, p0, q0, q1, q2, q3;
+ int ap, aq, delta;
+
+ if (bS==0)
+ {
+ return;
+ }
+
+ p3 = pQ0[-4*Step];
+ p2 = pQ0[-3*Step];
+ p1 = pQ0[-2*Step];
+ p0 = pQ0[-1*Step];
+ q0 = pQ0[ 0*Step];
+ q1 = pQ0[ 1*Step];
+ q2 = pQ0[ 2*Step];
+ q3 = pQ0[ 3*Step];
+
+ if (armAbs(p0-q0)>=alpha || armAbs(p1-p0)>=beta || armAbs(q1-q0)>=beta)
+ {
+ DEBUG_PRINTF_10("DeBlockPixel: %02x %02x %02x %02x | %02x %02x %02x %02x alpha=%d beta=%d\n",
+ p3, p2, p1, p0, q0, q1, q2, q3, alpha, beta);
+ return;
+ }
+
+ ap = armAbs(p2 - p0);
+ aq = armAbs(q2 - q0);
+
+ if (bS < 4)
+ {
+ int tC = tC0;
+
+ if (ChromaFlag)
+ {
+ tC++;
+ }
+ else
+ {
+ if (ap < beta)
+ {
+ tC++;
+ }
+ if (aq < beta)
+ {
+ tC++;
+ }
+ }
+
+ delta = (((q0-p0)<<2) + (p1-q1) + 4) >> 3;
+ delta = armClip(-tC, tC, delta);
+
+ pQ0[-1*Step] = (OMX_U8)armClip(0, 255, p0 + delta);
+ pQ0[ 0*Step] = (OMX_U8)armClip(0, 255, q0 - delta);
+
+ if (ChromaFlag==0 && ap<beta)
+ {
+ delta = (p2 + ((p0+q0+1)>>1) - (p1<<1))>>1;
+ delta = armClip(-tC0, tC0, delta);
+ pQ0[-2*Step] = (OMX_U8)(p1 + delta);
+ }
+
+ if (ChromaFlag==0 && aq<beta)
+ {
+ delta = (q2 + ((p0+q0+1)>>1) - (q1<<1))>>1;
+ delta = armClip(-tC0, tC0, delta);
+ pQ0[ 1*Step] = (OMX_U8)(q1 + delta);
+ }
+ }
+ else /* bS==4 */
+ {
+ if (ChromaFlag==0 && ap<beta && armAbs(p0-q0)<((alpha>>2)+2))
+ {
+ pQ0[-1*Step] = (OMX_U8)((p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4)>>3);
+ pQ0[-2*Step] = (OMX_U8)((p2 + p1 + p0 + q0 + 2)>>2);
+ pQ0[-3*Step] = (OMX_U8)((2*p3 + 3*p2 + p1 + p0 + q0 + 4)>>3);
+ }
+ else
+ {
+ pQ0[-1*Step] = (OMX_U8)((2*p1 + p0 + q1 + 2)>>2);
+ }
+
+ if (ChromaFlag==0 && aq<beta && armAbs(p0-q0)<((alpha>>2)+2))
+ {
+ pQ0[ 0*Step] = (OMX_U8)((q2 + 2*q1 + 2*q0 + 2*p0 + p1 + 4)>>3);
+ pQ0[ 1*Step] = (OMX_U8)((q2 + q1 + p0 + q0 + 2)>>2);
+ pQ0[ 2*Step] = (OMX_U8)((2*q3 + 3*q2 + q1 + q0 + p0 + 4)>>3);
+ }
+ else
+ {
+ pQ0[ 0*Step] = (OMX_U8)((2*q1 + q0 + p1 + 2)>>2);
+ }
+ }
+
+ DEBUG_PRINTF_13("DeBlockPixel: %02x %02x %02x %02x | %02x %02x %02x %02x bS=%d -> %02x %02x %02x %02x\n",
+ p3, p2, p1, p0, q0, q1, q2, q3, bS,
+ pQ0[-2*Step], pQ0[-1*Step],pQ0[0*Step],pQ0[1*Step]);
+
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair.c
new file mode 100644
index 0000000..7616add
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DecodeCoeffsToPair.c
@@ -0,0 +1,267 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_DecodeCoeffsToPair.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 decode coefficients module
+ *
+ */
+
+#ifdef DEBUG_ARMVCM4P10_DECODECOEFFSTOPAIR
+#undef DEBUG_ON
+#define DEBUG_ON
+#endif
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armCOMM_Bitstream.h"
+#include "armVCM4P10_CAVLCTables.h"
+
+/* 4x4 DeZigZag table */
+
+static const OMX_U8 armVCM4P10_ZigZag[16] =
+{
+ 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15
+};
+
+/*
+ * Description:
+ * This function perform the work required by the OpenMAX
+ * DecodeCoeffsToPair function and DecodeChromaDCCoeffsToPair.
+ * Since most of the code is common we share it here.
+ *
+ * Parameters:
+ * [in] ppBitStream Double pointer to current byte in bit stream buffer
+ * [in] pOffset Pointer to current bit position in the byte pointed
+ * to by *ppBitStream
+ * [in] sMaxNumCoeff Maximum number of non-zero coefficients in current
+ * block (4,15 or 16)
+ * [in] nTable Table number (0 to 4) according to the five columns
+ * of Table 9-5 in the H.264 spec
+ * [out] ppBitStream *ppBitStream is updated after each block is decoded
+ * [out] pOffset *pOffset is updated after each block is decoded
+ * [out] pNumCoeff Pointer to the number of nonzero coefficients in
+ * this block
+ * [out] ppPosCoefbuf Double pointer to destination residual
+ * coefficient-position pair buffer
+ * Return Value:
+ * Standard omxError result. See enumeration for possible result codes.
+
+ */
+
+OMXResult armVCM4P10_DecodeCoeffsToPair(
+ const OMX_U8** ppBitStream,
+ OMX_S32* pOffset,
+ OMX_U8* pNumCoeff,
+ OMX_U8 **ppPosCoefbuf,
+ OMX_INT nTable,
+ OMX_INT sMaxNumCoeff
+ )
+{
+ int CoeffToken, TotalCoeff, TrailingOnes;
+ int Level, LevelCode, LevelPrefix, LevelSuffix, LevelSuffixSize;
+ int SuffixLength, Run, ZerosLeft,CoeffNum;
+ int i, Flags;
+ OMX_U8 *pPosCoefbuf = *ppPosCoefbuf;
+ OMX_S16 pLevel[16];
+ OMX_U8 pRun[16];
+
+ CoeffToken = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCCoeffTokenTables[nTable]);
+ armRetDataErrIf(CoeffToken == ARM_NO_CODEBOOK_INDEX, OMX_Sts_Err);
+
+ TrailingOnes = armVCM4P10_CAVLCTrailingOnes[CoeffToken];
+ TotalCoeff = armVCM4P10_CAVLCTotalCoeff[CoeffToken];
+ *pNumCoeff = (OMX_U8)TotalCoeff;
+
+ DEBUG_PRINTF_2("TotalCoeff = %d, TrailingOnes = %d\n", TotalCoeff, TrailingOnes);
+
+ if (TotalCoeff == 0)
+ {
+ /* Nothing to do */
+ return OMX_Sts_NoErr;
+ }
+
+ /* Decode trailing ones */
+ for (i=TotalCoeff-1; i>=TotalCoeff-TrailingOnes; i--)
+ {
+ if (armGetBits(ppBitStream, pOffset, 1))
+ {
+ Level = -1;
+ }
+ else
+ {
+ Level = +1;
+ }
+ pLevel[i] = (OMX_S16)Level;
+
+ DEBUG_PRINTF_2("Level[%d] = %d\n", i, pLevel[i]);
+ }
+
+ /* Decode (non zero) level values */
+ SuffixLength = 0;
+ if (TotalCoeff>10 && TrailingOnes<3)
+ {
+ SuffixLength=1;
+ }
+ for ( ; i>=0; i--)
+ {
+ LevelPrefix = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCLevelPrefix);
+ armRetDataErrIf(LevelPrefix == ARM_NO_CODEBOOK_INDEX, OMX_Sts_Err);
+
+ LevelSuffixSize = SuffixLength;
+ if (LevelPrefix==14 && SuffixLength==0)
+ {
+ LevelSuffixSize = 4;
+ }
+ if (LevelPrefix==15)
+ {
+ LevelSuffixSize = 12;
+ }
+
+ LevelSuffix = 0;
+ if (LevelSuffixSize > 0)
+ {
+ LevelSuffix = armGetBits(ppBitStream, pOffset, LevelSuffixSize);
+ }
+
+ LevelCode = (LevelPrefix << SuffixLength) + LevelSuffix;
+
+
+ if (LevelPrefix==15 && SuffixLength==0)
+ {
+ LevelCode += 15;
+ }
+
+ /* LevelCode = 2*(magnitude-1) + sign */
+
+ if (i==TotalCoeff-1-TrailingOnes && TrailingOnes<3)
+ {
+ /* Level magnitude can't be 1 */
+ LevelCode += 2;
+ }
+ if (LevelCode & 1)
+ {
+ /* 2a+1 maps to -a-1 */
+ Level = (-LevelCode-1)>>1;
+ }
+ else
+ {
+ /* 2a+0 maps to +a+1 */
+ Level = (LevelCode+2)>>1;
+ }
+ pLevel[i] = (OMX_S16)Level;
+
+ DEBUG_PRINTF_2("Level[%d] = %d\n", i, pLevel[i]);
+
+ if (SuffixLength==0)
+ {
+ SuffixLength=1;
+ }
+ if ( ((LevelCode>>1)+1)>(3<<(SuffixLength-1)) && SuffixLength<6 )
+ {
+ SuffixLength++;
+ }
+ }
+
+ /* Decode run values */
+ ZerosLeft = 0;
+ if (TotalCoeff < sMaxNumCoeff)
+ {
+ /* Decode TotalZeros VLC */
+ if (sMaxNumCoeff==4)
+ {
+ ZerosLeft = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCTotalZeros2x2Tables[TotalCoeff-1]);
+ armRetDataErrIf(ZerosLeft ==ARM_NO_CODEBOOK_INDEX , OMX_Sts_Err);
+ }
+ else
+ {
+ ZerosLeft = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCTotalZeroTables[TotalCoeff-1]);
+ armRetDataErrIf(ZerosLeft ==ARM_NO_CODEBOOK_INDEX , OMX_Sts_Err);
+ }
+ }
+
+ DEBUG_PRINTF_1("TotalZeros = %d\n", ZerosLeft);
+
+ CoeffNum=ZerosLeft+TotalCoeff-1;
+
+ for (i=TotalCoeff-1; i>0; i--)
+ {
+ Run = 0;
+ if (ZerosLeft > 0)
+ {
+ int Table = ZerosLeft;
+ if (Table > 6)
+ {
+ Table = 7;
+ }
+ Run = armUnPackVLC32(ppBitStream, pOffset, armVCM4P10_CAVLCRunBeforeTables[Table-1]);
+ armRetDataErrIf(Run == ARM_NO_CODEBOOK_INDEX, OMX_Sts_Err);
+ }
+ pRun[i] = (OMX_U8)Run;
+
+ DEBUG_PRINTF_2("Run[%d] = %d\n", i, pRun[i]);
+
+ ZerosLeft -= Run;
+ }
+ pRun[0] = (OMX_U8)ZerosLeft;
+
+ DEBUG_PRINTF_1("Run[0] = %d\n", pRun[i]);
+
+
+ /* Fill in coefficients */
+
+ if (sMaxNumCoeff==15)
+ {
+ CoeffNum++; /* Skip the DC position */
+ }
+
+ /*for (i=0;i<TotalCoeff;i++)
+ CoeffNum += pRun[i]+1;*/
+
+ for (i=(TotalCoeff-1); i>=0; i--)
+ {
+ /*CoeffNum += pRun[i]+1;*/
+ Level = pLevel[i];
+
+ DEBUG_PRINTF_2("Coef[%d] = %d\n", CoeffNum, Level);
+
+ Flags = CoeffNum;
+ CoeffNum -= (pRun[i]+1);
+ if (sMaxNumCoeff>4)
+ {
+ /* Perform 4x4 DeZigZag */
+ Flags = armVCM4P10_ZigZag[Flags];
+ }
+ if (i==0)
+ {
+ /* End of block flag */
+ Flags += 0x20;
+ }
+ if (Level<-128 || Level>127)
+ {
+ /* Overflow flag */
+ Flags += 0x10;
+ }
+
+ *pPosCoefbuf++ = (OMX_U8)(Flags);
+ *pPosCoefbuf++ = (OMX_U8)(Level & 0xFF);
+ if (Flags & 0x10)
+ {
+ *pPosCoefbuf++ = (OMX_U8)(Level>>8);
+ }
+ }
+
+ *ppPosCoefbuf = pPosCoefbuf;
+
+ return OMX_Sts_NoErr;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DequantTables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DequantTables.c
new file mode 100644
index 0000000..d9c2541
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_DequantTables.c
@@ -0,0 +1,45 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_DequantTables.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 inverse quantize tables
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+#include "armVC.h"
+
+
+const OMX_U8 armVCM4P10_PosToVCol4x4[16] =
+{
+ 0, 2, 0, 2,
+ 2, 1, 2, 1,
+ 0, 2, 0, 2,
+ 2, 1, 2, 1
+};
+
+const OMX_U8 armVCM4P10_PosToVCol2x2[4] =
+{
+ 0, 2,
+ 2, 1
+};
+
+const OMX_U8 armVCM4P10_VMatrix[6][3] =
+{
+ { 10, 16, 13 },
+ { 11, 18, 14 },
+ { 13, 20, 16 },
+ { 14, 23, 18 },
+ { 16, 25, 20 },
+ { 18, 29, 23 }
+};
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_FwdTransformResidual4x4.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_FwdTransformResidual4x4.c
new file mode 100644
index 0000000..93d54c3
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_FwdTransformResidual4x4.c
@@ -0,0 +1,78 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_FwdTransformResidual4x4.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 transform module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/*
+ * Description:
+ * Forward Transform Residual 4x4 Coefficients
+ *
+ * Parameters:
+ * [in] pSrc Source 4x4 block
+ * [out] pDst Destination 4x4 block
+ *
+ */
+void armVCM4P10_FwdTransformResidual4x4(OMX_S16* pDst, OMX_S16 *pSrc)
+{
+ int i;
+
+ /* Transform rows */
+ for (i=0; i<16; i+=4)
+ {
+ int d0 = pSrc[i+0];
+ int d1 = pSrc[i+1];
+ int d2 = pSrc[i+2];
+ int d3 = pSrc[i+3];
+ int e0 = d0 + d3;
+ int e1 = d0 - d3;
+ int e2 = d1 + d2;
+ int e3 = d1 - d2;
+ int f0 = e0 + e2;
+ int f1 = (e1 << 1) + e3;
+ int f2 = e0 - e2;
+ int f3 = e1 - (e3 << 1);
+ pDst[i+0] = (OMX_S16)f0;
+ pDst[i+1] = (OMX_S16)f1;
+ pDst[i+2] = (OMX_S16)f2;
+ pDst[i+3] = (OMX_S16)f3;
+ }
+
+ /* Transform columns */
+ for (i=0; i<4; i++)
+ {
+ int f0 = pDst[i+0];
+ int f1 = pDst[i+4];
+ int f2 = pDst[i+8];
+ int f3 = pDst[i+12];
+ int g0 = f0 + f3;
+ int g1 = f0 - f3;
+ int g2 = f1 + f2;
+ int g3 = f1 - f2;
+ int h0 = g0 + g2;
+ int h1 = (g1 << 1) + g3;
+ int h2 = g0 - g2;
+ int h3 = g1 - (g3 << 1);
+ pDst[i+0] = (OMX_S16) h0;
+ pDst[i+4] = (OMX_S16) h1;
+ pDst[i+8] = (OMX_S16) h2;
+ pDst[i+12] = (OMX_S16) h3;
+ }
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfDiag_Luma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfDiag_Luma.c
new file mode 100644
index 0000000..8732f4f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfDiag_Luma.c
@@ -0,0 +1,106 @@
+/**
+ *
+ * File Name: armVCM4P10_InterpolateHalfDiag_Luma.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This functions will help to calculate Half Pel luma interpolation
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+
+/**
+ * Function: armVCM4P10_InterpolateHalfDiag_Luma
+ *
+ * Description:
+ * This function performs interpolation for (1/2, 1/2) positions
+ * around a full-pel position.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to interpolate
+ * in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [out] pDst Pointer to the interpolation buffer of the (1/2,1/2)-pel
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+OMXResult armVCM4P10_InterpolateHalfDiag_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+)
+{
+ OMX_S32 HalfCoeff, pos;
+ OMX_S16 Buf [21 * 16]; /* 21 rows by 16 pixels per row */
+ OMX_U32 y, x;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr)
+
+ /*
+ * Intermediate values will be 1/2 pel at Horizontal direction
+ * Starting at (0.5, -2) at top extending to (0.5, height + 3) at bottom
+ * Buf contains a 2D array of size (iWidth)X(iHeight + 5)
+ */
+ for (y = 0; y < iHeight + 5; y++)
+ {
+ for (x = 0; x < iWidth; x++)
+ {
+ pos = (y-2) * iSrcStep + x;
+ HalfCoeff =
+ pSrc [pos - 2] -
+ 5 * pSrc [pos - 1] +
+ 20 * pSrc [pos] +
+ 20 * pSrc [pos + 1] -
+ 5 * pSrc [pos + 2] +
+ pSrc [pos + 3];
+ Buf [y * iWidth + x] = (OMX_S16)HalfCoeff;
+ } /* x */
+ } /* y */
+
+ /* Vertical interpolate */
+ for (y = 0; y < iHeight; y++)
+ {
+ for (x = 0; x < iWidth; x++)
+ {
+ pos = y * iWidth + x;
+ HalfCoeff =
+ Buf [pos] -
+ 5 * Buf [pos + 1 * iWidth] +
+ 20 * Buf [pos + 2 * iWidth] +
+ 20 * Buf [pos + 3 * iWidth] -
+ 5 * Buf [pos + 4 * iWidth] +
+ Buf [pos + 5 * iWidth];
+
+ HalfCoeff = (HalfCoeff + 512) >> 10;
+ HalfCoeff = armClip(0, 255, HalfCoeff);
+
+ pDst [y * iDstStep + x] = (OMX_U8) HalfCoeff;
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfHor_Luma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfHor_Luma.c
new file mode 100644
index 0000000..89c0079
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfHor_Luma.c
@@ -0,0 +1,82 @@
+/**
+ *
+ * File Name: armVCM4P10_InterpolateHalfHor_Luma.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This functions will help to calculate Half Pel luma interpolation
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: armVCM4P10_InterpolateHalfHor_Luma
+ *
+ * Description:
+ * This function performs interpolation for horizontal 1/2-pel positions
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to interpolate
+ * in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [out] pDst Pointer to the interpolation buffer of the 1/2-pel
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+OMXResult armVCM4P10_InterpolateHalfHor_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+)
+{
+ OMX_INT x, y;
+ OMX_S32 HalfCoeff, pos;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr)
+
+ for (y = 0; y < iHeight; y++)
+ {
+ for (x = 0; x < iWidth; x++)
+ {
+ pos = y * iSrcStep + x;
+ HalfCoeff =
+ pSrc [pos - 2] -
+ 5 * pSrc [pos - 1] +
+ 20 * pSrc [pos] +
+ 20 * pSrc [pos + 1] -
+ 5 * pSrc [pos + 2] +
+ pSrc [pos + 3];
+
+ HalfCoeff = (HalfCoeff + 16) >> 5;
+ HalfCoeff = armClip(0, 255, HalfCoeff);
+
+ pDst [y * iDstStep + x] = HalfCoeff;
+ } /* x */
+ } /* y */
+
+ return OMX_Sts_NoErr;
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfVer_Luma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfVer_Luma.c
new file mode 100644
index 0000000..f7ecfc5
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_InterpolateHalfVer_Luma.c
@@ -0,0 +1,84 @@
+/**
+ *
+ * File Name: armVCM4P10_InterpolateHalfVer_Luma.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This functions will help to calculate Half Pel luma interpolation
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: armVCM4P10_InterpolateHalfVer_Luma
+ *
+ * Description:
+ * This function performs interpolation for vertical 1/2-pel positions
+ * around a full-pel position.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to interpolate
+ * in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [out] pDst Pointer to the interpolation buffer of the 1/2-pel
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+OMXResult armVCM4P10_InterpolateHalfVer_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+)
+{
+ OMX_S32 HalfCoeff, pos;
+ OMX_INT y, x;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr)
+
+
+ for (y = 0; y < iHeight; y++)
+ {
+ for (x = 0; x < iWidth; x++)
+ {
+ pos = y * iSrcStep + x;
+ HalfCoeff =
+ pSrc [pos - 2 * iSrcStep] -
+ 5 * pSrc [pos - 1 * iSrcStep] +
+ 20 * pSrc [pos] +
+ 20 * pSrc [pos + 1 * iSrcStep] -
+ 5 * pSrc [pos + 2 * iSrcStep] +
+ pSrc [pos + 3 * iSrcStep];
+
+ HalfCoeff = (HalfCoeff + 16) >> 5;
+ HalfCoeff = armClip(0, 255, HalfCoeff);
+
+ pDst [y * iDstStep + x] = (OMX_U8) HalfCoeff;
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Chroma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Chroma.c
new file mode 100644
index 0000000..1507d23
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Chroma.c
@@ -0,0 +1,109 @@
+/**
+ *
+ * File Name: armVCM4P10_Interpolate_Chroma.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate interpolation for chroma components
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armCOMM.h"
+
+/**
+ * Function: armVCM4P10_Interpolate_Chroma
+ *
+ * Description:
+ * This function performs interpolation for chroma components.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to
+ * interpolate in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [in] dx Fractional part of horizontal motion vector
+ * component in 1/8 pixel unit (0~7)
+ * [in] dy Fractional part of vertical motion vector
+ * component in 1/8 pixel unit (0~7)
+ * [out] pDst Pointer to the interpolation buffer
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+ OMXResult armVCM4P10_Interpolate_Chroma(
+ OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight,
+ OMX_U32 dx,
+ OMX_U32 dy
+)
+{
+ OMX_U32 EightMinusdx = 8 - dx;
+ OMX_U32 EightMinusdy = 8 - dy;
+ OMX_U32 ACoeff, BCoeff, CCoeff, DCoeff;
+ OMX_U32 x, y;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dx > 7, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dy > 7, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iSrcStep == 0, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iDstStep == 0, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iWidth == 0, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iHeight == 0, OMX_Sts_BadArgErr)
+
+ /* if fractionl mv is not (0, 0) */
+ if (dx != 0 || dy != 0)
+ {
+ ACoeff = EightMinusdx * EightMinusdy;
+ BCoeff = dx * EightMinusdy;
+ CCoeff = EightMinusdx * dy;
+ DCoeff = dx * dy;
+
+ for (y = 0; y < iHeight; y++)
+ {
+ for (x = 0; x < iWidth; x++)
+ {
+ pDst [y * iDstStep + x] = (
+ ACoeff * pSrc [y * iSrcStep + x] +
+ BCoeff * pSrc [y * iSrcStep + x + 1] +
+ CCoeff * pSrc [(y + 1) * iSrcStep + x] +
+ DCoeff * pSrc [(y + 1) * iSrcStep + x + 1] +
+ 32) >> 6;
+ }
+ }
+ }
+ else
+ {
+ for (y = 0; y < iHeight; y++)
+ {
+ for (x = 0; x < iWidth; x++)
+ {
+ pDst [y * iDstStep + x] = pSrc [y * iSrcStep + x];
+ }
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Luma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Luma.c
new file mode 100644
index 0000000..89978dd
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_Interpolate_Luma.c
@@ -0,0 +1,195 @@
+/**
+ *
+ * File Name: armVCM4P10_Interpolate_Luma.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate interpolation for luma components
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: armM4P10_Copy
+ *
+ * Description:
+ * This function performs copy a block of data from source to destination
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [out] pDst Pointer to the interpolation buffer
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+static OMXResult armM4P10_Copy(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+)
+{
+ OMX_U32 x, y;
+
+ for (y = 0; y < iHeight; y++)
+ {
+ for (x = 0; x < iWidth; x++)
+ {
+ pDst [y * iDstStep + x] = pSrc [y * iSrcStep + x];
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/**
+ * Function: armVCM4P10_Interpolate_Luma
+ *
+ * Description:
+ * This function performs interpolation for luma components.
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to top-left corner of block used to
+ * interpolate in the reconstructed frame plane
+ * [in] iSrcStep Step of the source buffer.
+ * [in] iDstStep Step of the destination(interpolation) buffer.
+ * [in] iWidth Width of the current block
+ * [in] iHeight Height of the current block
+ * [in] dx Fractional part of horizontal motion vector
+ * component in 1/4 pixel unit (0~3)
+ * [in] dy Fractional part of vertical motion vector
+ * component in 1/4 pixel unit (0~3)
+ * [out] pDst Pointer to the interpolation buffer
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+
+ OMXResult armVCM4P10_Interpolate_Luma(
+ const OMX_U8 *pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8 *pDst,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight,
+ OMX_U32 dx,
+ OMX_U32 dy
+)
+{
+ OMX_U8 pBuf1 [16*16];
+ const OMX_U8 *pSrcHalfHor = pSrc;
+ const OMX_U8 *pSrcHalfVer = pSrc;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dx > 3, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dy > 3, OMX_Sts_BadArgErr)
+
+ /* Work out positions for half pixel interpolation */
+ if (dx == 3)
+ {
+ pSrcHalfVer += 1;
+ }
+ if (dy == 3)
+ {
+ pSrcHalfHor += iSrcStep;
+ }
+
+ /* Switch on type of pixel
+ * Pixels are named 'a' to 's' as in the H.264 standard
+ */
+ if (dx == 0 && dy == 0)
+ {
+ /* G */
+ armM4P10_Copy(pSrc, iSrcStep, pDst, iDstStep, iWidth, iHeight);
+ }
+ else if (dy == 0)
+ {
+ /* a, b, c */
+ armVCM4P10_InterpolateHalfHor_Luma
+ (pSrcHalfHor, iSrcStep, pDst, iDstStep, iWidth, iHeight);
+
+ if (dx == 1 || dx == 3)
+ {
+ armVCCOMM_Average
+ (pDst, pSrcHalfVer, iDstStep, iSrcStep, pDst, iDstStep, iWidth, iHeight);
+ }
+ }
+ else if (dx == 0)
+ {
+ /* d, h, n */
+ armVCM4P10_InterpolateHalfVer_Luma
+ (pSrcHalfVer, iSrcStep, pDst, iDstStep, iWidth, iHeight);
+
+ if (dy == 1 || dy == 3)
+ {
+ armVCCOMM_Average
+ (pDst, pSrcHalfHor, iDstStep, iSrcStep, pDst, iDstStep, iWidth, iHeight);
+ }
+ }
+ else if (dx == 2 || dy == 2)
+ {
+ /* j */
+ armVCM4P10_InterpolateHalfDiag_Luma
+ (pSrc, iSrcStep, pDst, iDstStep, iWidth, iHeight);
+
+ if (dx == 1 || dx == 3)
+ {
+ /* i, k */
+ armVCM4P10_InterpolateHalfVer_Luma
+ (pSrcHalfVer, iSrcStep, pBuf1, iWidth, iWidth, iHeight);
+
+ armVCCOMM_Average
+ (pDst, pBuf1, iDstStep, iWidth, pDst, iDstStep, iWidth, iHeight);
+ }
+ if (dy == 1 || dy == 3)
+ {
+ /* f,q */
+ armVCM4P10_InterpolateHalfHor_Luma
+ (pSrcHalfHor, iSrcStep, pBuf1, iWidth, iWidth, iHeight);
+
+ armVCCOMM_Average
+ (pDst, pBuf1, iDstStep, iWidth, pDst, iDstStep, iWidth, iHeight);
+ }
+ }
+ else /* dx=1,3 and dy=1,3 */
+ {
+ /* e, g, p, r */
+ armVCM4P10_InterpolateHalfHor_Luma
+ (pSrcHalfHor, iSrcStep, pBuf1, iWidth, iWidth, iHeight);
+
+ armVCM4P10_InterpolateHalfVer_Luma
+ (pSrcHalfVer, iSrcStep, pDst, iDstStep, iWidth, iHeight);
+
+ armVCCOMM_Average
+ (pBuf1, pDst, iWidth, iDstStep, pDst, iDstStep, iWidth, iHeight);
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_PredictIntraDC4x4.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_PredictIntraDC4x4.c
new file mode 100644
index 0000000..b713073
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_PredictIntraDC4x4.c
@@ -0,0 +1,88 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_PredictIntraDC4x4.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 4x4 intra prediction module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/*
+ * Description:
+ * Perform DC style intra prediction, averaging upper and left block
+ *
+ * Parameters:
+ * [in] pSrcLeft Pointer to the buffer of 16 left coefficients:
+ * p[x, y] (x = -1, y = 0..3)
+ * [in] pSrcAbove Pointer to the buffer of 16 above coefficients:
+ * p[x,y] (x = 0..3, y = -1)
+ * [in] leftStep Step of left coefficient buffer
+ * [in] dstStep Step of the destination buffer
+ * [in] availability Neighboring 16x16 MB availability flag
+ * [out] pDst Pointer to the destination buffer
+ *
+ * Return Value:
+ * None
+ */
+
+void armVCM4P10_PredictIntraDC4x4(
+ const OMX_U8* pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ OMX_U8* pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMX_S32 availability
+)
+{
+ int x, y, Sum=0, Count = 0;
+
+ if (availability & OMX_VC_LEFT)
+ {
+ for (y=0; y<4; y++)
+ {
+ Sum += pSrcLeft[y*leftStep];
+ }
+ Count++;
+ }
+ if (availability & OMX_VC_UPPER)
+ {
+ for (x=0; x<4; x++)
+ {
+ Sum += pSrcAbove[x];
+ }
+ Count++;
+ }
+ if (Count==0)
+ {
+ Sum = 128;
+ }
+ else if (Count==1)
+ {
+ Sum = (Sum + 2) >> 2;
+ }
+ else /* Count = 2 */
+ {
+ Sum = (Sum + 4) >> 3;
+ }
+ for (y=0; y<4; y++)
+ {
+ for (x=0; x<4; x++)
+ {
+ pDst[y*dstStep+x] = (OMX_U8)Sum;
+ }
+ }
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_QuantTables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_QuantTables.c
new file mode 100644
index 0000000..f0b5bb0
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_QuantTables.c
@@ -0,0 +1,31 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_QuantTables.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 inverse quantize tables
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+
+const OMX_U32 armVCM4P10_MFMatrix[6][3] =
+{
+ {13107, 5243, 8066},
+ {11916, 4660, 7490},
+ {10082, 4194, 6554},
+ { 9362, 3647, 5825},
+ { 8192, 3355, 5243},
+ { 7282, 2893, 4559}
+};
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_SADQuar.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_SADQuar.c
new file mode 100644
index 0000000..a41e04b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_SADQuar.c
@@ -0,0 +1,84 @@
+/**
+ *
+ * File Name: armVCM4P10_SADQuar.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate SAD of pSrc with average of two Ref blocks
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: armVCM4P10_SADQuar
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the
+ * average of the other two (pSrcRef0 and pSrcRef1)
+ *
+ * Remarks:
+ *
+ * [in] pSrc Pointer to the original block
+ * [in] pSrcRef0 Pointer to reference block 0
+ * [in] pSrcRef1 Pointer to reference block 1
+ * [in] iSrcStep Step of the original block buffer
+ * [in] iRefStep0 Step of reference block 0
+ * [in] iRefStep1 Step of reference block 1
+ * [in] iHeight Height of the block
+ * [in] iWidth Width of the block
+ * [out] pDstSAD Pointer of result SAD
+ *
+ * Return Value:
+ * Standard OMXResult value.
+ *
+ */
+OMXResult armVCM4P10_SADQuar(
+ const OMX_U8* pSrc,
+ const OMX_U8* pSrcRef0,
+ const OMX_U8* pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32* pDstSAD,
+ OMX_U32 iHeight,
+ OMX_U32 iWidth
+)
+{
+ OMX_INT x, y;
+ OMX_S32 SAD = 0;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcRef0 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcRef1 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr)
+
+ for (y = 0; y < iHeight; y++)
+ {
+ for (x = 0; x < iWidth; x++)
+ {
+ SAD += armAbs(pSrc [y * iSrcStep + x] - ((
+ pSrcRef0 [y * iRefStep0 + x] +
+ pSrcRef1 [y * iRefStep1 + x] + 1) >> 1));
+ }
+ }
+
+ *pDstSAD = SAD;
+
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_TransformResidual4x4.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_TransformResidual4x4.c
new file mode 100644
index 0000000..f9f756a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_TransformResidual4x4.c
@@ -0,0 +1,80 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_TransformResidual4x4.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 transform module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/*
+ * Description:
+ * Transform Residual 4x4 Coefficients
+ *
+ * Parameters:
+ * [in] pSrc Source 4x4 block
+ * [out] pDst Destination 4x4 block
+ *
+ */
+
+void armVCM4P10_TransformResidual4x4(OMX_S16* pDst, OMX_S16 *pSrc)
+{
+ int i;
+
+ /* Transform rows */
+ for (i=0; i<16; i+=4)
+ {
+ int d0 = pSrc[i+0];
+ int d1 = pSrc[i+1];
+ int d2 = pSrc[i+2];
+ int d3 = pSrc[i+3];
+ int e0 = d0 + d2;
+ int e1 = d0 - d2;
+ int e2 = (d1>>1) - d3;
+ int e3 = d1 + (d3>>1);
+ int f0 = e0 + e3;
+ int f1 = e1 + e2;
+ int f2 = e1 - e2;
+ int f3 = e0 - e3;
+ pDst[i+0] = (OMX_S16)f0;
+ pDst[i+1] = (OMX_S16)f1;
+ pDst[i+2] = (OMX_S16)f2;
+ pDst[i+3] = (OMX_S16)f3;
+ }
+
+ /* Transform columns */
+ for (i=0; i<4; i++)
+ {
+ int f0 = pDst[i+0];
+ int f1 = pDst[i+4];
+ int f2 = pDst[i+8];
+ int f3 = pDst[i+12];
+ int g0 = f0 + f2;
+ int g1 = f0 - f2;
+ int g2 = (f1>>1) - f3;
+ int g3 = f1 + (f3>>1);
+ int h0 = g0 + g3;
+ int h1 = g1 + g2;
+ int h2 = g1 - g2;
+ int h3 = g0 - g3;
+ pDst[i+0] = (OMX_S16)((h0+32)>>6);
+ pDst[i+4] = (OMX_S16)((h1+32)>>6);
+ pDst[i+8] = (OMX_S16)((h2+32)>>6);
+ pDst[i+12] = (OMX_S16)((h3+32)>>6);
+ }
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock2x2.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock2x2.c
new file mode 100644
index 0000000..dda49f6
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock2x2.c
@@ -0,0 +1,78 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_UnpackBlock2x2.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 inverse quantize and transform helper module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+
+/*
+ * Description
+ * Unpack a 2x2 block of coefficient-residual pair values
+ *
+ * Parameters:
+ * [in] ppSrc Double pointer to residual coefficient-position pair
+ * buffer output by CALVC decoding
+ * [out] ppSrc *ppSrc is updated to the start of next non empty block
+ * [out] pDst Pointer to unpacked 4x4 block
+ */
+
+void armVCM4P10_UnpackBlock2x2(
+ const OMX_U8 **ppSrc,
+ OMX_S16* pDst
+)
+{
+ const OMX_U8 *pSrc = *ppSrc;
+ int i;
+ int Flag, Value;
+
+ for (i=0; i<4; i++)
+ {
+ pDst[i] = 0;
+ }
+
+ do
+ {
+ Flag = *pSrc++;
+ if (Flag & 0x10)
+ {
+ /* 16 bit */
+ Value = *pSrc++;
+ Value = Value | ((*pSrc++)<<8);
+ if (Value & 0x8000)
+ {
+ Value -= 0x10000;
+ }
+ }
+ else
+ {
+ /* 8 bit */
+ Value = *pSrc++;
+ if (Value & 0x80)
+ {
+ Value -= 0x100;
+ }
+ }
+ i = Flag & 15;
+ pDst[i] = (OMX_S16)Value;
+ }
+ while ((Flag & 0x20)==0);
+
+ *ppSrc = pSrc;
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock4x4.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock4x4.c
new file mode 100644
index 0000000..3c0dcbd
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/armVCM4P10_UnpackBlock4x4.c
@@ -0,0 +1,78 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: armVCM4P10_UnpackBlock4x4.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 inverse quantize and transform helper module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+
+/*
+ * Description
+ * Unpack a 4x4 block of coefficient-residual pair values
+ *
+ * Parameters:
+ * [in] ppSrc Double pointer to residual coefficient-position pair
+ * buffer output by CALVC decoding
+ * [out] ppSrc *ppSrc is updated to the start of next non empty block
+ * [out] pDst Pointer to unpacked 4x4 block
+ */
+
+void armVCM4P10_UnpackBlock4x4(
+ const OMX_U8 **ppSrc,
+ OMX_S16* pDst
+)
+{
+ const OMX_U8 *pSrc = *ppSrc;
+ int i;
+ int Flag, Value;
+
+ for (i=0; i<16; i++)
+ {
+ pDst[i] = 0;
+ }
+
+ do
+ {
+ Flag = *pSrc++;
+ if (Flag & 0x10)
+ {
+ /* 16 bit */
+ Value = *pSrc++;
+ Value = Value | ((*pSrc++)<<8);
+ if (Value & 0x8000)
+ {
+ Value -= 0x10000;
+ }
+ }
+ else
+ {
+ /* 8 bit */
+ Value = *pSrc++;
+ if (Value & 0x80)
+ {
+ Value -= 0x100;
+ }
+ }
+ i = Flag & 15;
+ pDst[i] = (OMX_S16)Value;
+ }
+ while ((Flag & 0x20)==0);
+
+ *ppSrc = pSrc;
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_Average_4x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_Average_4x.c
new file mode 100644
index 0000000..ac0d523
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_Average_4x.c
@@ -0,0 +1,84 @@
+/**
+ *
+ * File Name: omxVCM4P10_Average_4x.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate Average of two 4x4 or 4x8 blocks
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_Average_4x (6.3.5.5.3)
+ *
+ * Description:
+ * This function calculates the average of two 4x4, 4x8 blocks. The result
+ * is rounded according to (a+b+1)/2.
+ *
+ * Input Arguments:
+ *
+ * pPred0 - Pointer to the top-left corner of reference block 0
+ * pPred1 - Pointer to the top-left corner of reference block 1
+ * iPredStep0 - Step of reference block 0; must be a multiple of 4.
+ * iPredStep1 - Step of reference block 1; must be a multiple of 4.
+ * iDstStep - Step of the destination buffer; must be a multiple of 4.
+ * iHeight - Height of the blocks; must be either 4 or 8.
+ *
+ * Output Arguments:
+ *
+ * pDstPred - Pointer to the destination buffer. 4-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pPred0, pPred1, or pDstPred
+ * - pDstPred is not aligned on a 4-byte boundary
+ * - iPredStep0 <= 0 or iPredStep0 is not a multiple of 4
+ * - iPredStep1 <= 0 or iPredStep1 is not a multiple of 4
+ * - iDstStep <= 0 or iDstStep is not a multiple of 4
+ * - iHeight is not equal to either 4 or 8
+ *
+ */
+ OMXResult omxVCM4P10_Average_4x (
+ const OMX_U8* pPred0,
+ const OMX_U8* pPred1,
+ OMX_U32 iPredStep0,
+ OMX_U32 iPredStep1,
+ OMX_U8* pDstPred,
+ OMX_U32 iDstStep,
+ OMX_U32 iHeight
+)
+{
+ /* check for argument error */
+ armRetArgErrIf(pPred0 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pPred1 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstPred == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf((iHeight != 4) && (iHeight != 8), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iPredStep0 == 0) || (iPredStep0 & 3), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iPredStep1 == 0) || (iPredStep1 & 3), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iDstStep == 0) || (iDstStep & 3), OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot4ByteAligned(pDstPred), OMX_Sts_BadArgErr)
+
+ return armVCCOMM_Average
+ (pPred0, pPred1, iPredStep0, iPredStep1, pDstPred, iDstStep, 4, iHeight);
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Half.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Half.c
new file mode 100644
index 0000000..c490e10
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Half.c
@@ -0,0 +1,191 @@
+/**
+ *
+ * File Name: omxVCM4P10_BlockMatch_Half.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for half pel Block matching,
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+
+/**
+ * Function: omxVCM4P10_BlockMatch_Half (6.3.5.2.2)
+ *
+ * Description:
+ * Performs a half-pel block match using results from a prior integer search.
+ * Returns the best MV and associated cost. This function estimates the
+ * half-pixel motion vector by interpolating the integer resolution motion
+ * vector referenced by the input parameter pSrcDstBestMV, i.e., the initial
+ * integer MV is generated externally. The function
+ * omxVCM4P10_BlockMatch_Integer may be used for integer motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrgY - Pointer to the current position in original picture plane. If
+ * iBlockWidth==4, 4-byte alignment required. If iBlockWidth==8,
+ * 8-byte alignment required. If iBlockWidth==16, 16-byte alignment
+ * required.
+ * pSrcRefY - Pointer to the top-left corner of the co-located block in the
+ * reference picture If iBlockWidth==4, 4-byte alignment
+ * required. If iBlockWidth==8, 8-byte alignment required. If
+ * iBlockWidth==16, 16-byte alignment required.
+ * nSrcOrgStep - Stride of the original picture plane in terms of full
+ * pixels; must be a multiple of iBlockWidth.
+ * nSrcRefStep - Stride of the reference picture plane in terms of full
+ * pixels
+ * iBlockWidth - Width of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * iBlockHeight - Height of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * nLamda - Lamda factor, used to compute motion cost
+ * pMVPred - Predicted MV, represented in terms of 1/4-pel units; used to
+ * compute motion cost
+ * pSrcDstBestMV - The best MV resulting from a prior integer search,
+ * represented in terms of 1/4-pel units
+ *
+ * Output Arguments:
+ *
+ * pSrcDstBestMV - Best MV resulting from the half-pel search, expressed in
+ * terms of 1/4-pel units
+ * pBestCost - Motion cost associated with the best MV; computed as
+ * SAD+Lamda*BitsUsedByMV
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - any of the following pointers is NULL: pSrcOrgY, pSrcRefY,
+ * pSrcDstBestMV, pMVPred, pBestCost
+ * - iBlockWidth or iBlockHeight are equal to values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+
+OMXResult omxVCM4P10_BlockMatch_Half(
+ const OMX_U8* pSrcOrgY,
+ OMX_S32 nSrcOrgStep,
+ const OMX_U8* pSrcRefY,
+ OMX_S32 nSrcRefStep,
+ OMX_U8 iBlockWidth,
+ OMX_U8 iBlockHeight,
+ OMX_U32 nLamda,
+ const OMXVCMotionVector* pMVPred,
+ OMXVCMotionVector* pSrcDstBestMV,
+ OMX_S32* pBestCost
+)
+{
+ /* Definitions and Initializations*/
+ OMX_INT candSAD;
+ OMX_INT fromX, toX, fromY, toY;
+ /* Offset to the reference at the begining of the bounding box */
+ const OMX_U8 *pTempSrcRefY, *pTempSrcOrgY;
+ OMX_S16 x, y;
+ OMXVCMotionVector diffMV, candMV, integerMV;
+ OMX_U8 interpolY[256];
+
+ /* Argument error checks */
+ armRetArgErrIf((iBlockWidth == 4) && (!armIs4ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 8) && (!armIs8ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 16) && (!armIs16ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 4) && (!armIs4ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 8) && (!armIs8ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 16) && (!armIs16ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((nSrcOrgStep % iBlockWidth), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcOrgY == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcRefY == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pMVPred == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcDstBestMV == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBestCost == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(((iBlockWidth!=4)&&(iBlockWidth!=8)&&(iBlockWidth!=16)) , OMX_Sts_BadArgErr);
+ armRetArgErrIf(((iBlockHeight!=4)&&(iBlockHeight!=8)&&(iBlockHeight!=16)) , OMX_Sts_BadArgErr);
+
+
+ /* Check for valid region */
+ fromX = 1;
+ toX = 1;
+ fromY = 1;
+ toY = 1;
+
+ /* Initialize to max value as a start point */
+ *pBestCost = 0x7fffffff;
+
+ integerMV.dx = pSrcDstBestMV->dx;
+ integerMV.dy = pSrcDstBestMV->dy;
+
+ /* Looping on y- axis */
+ for (y = -fromY; y <= toY; y++)
+ {
+ /* Looping on x- axis */
+ for (x = -fromX; x <= toX; x++)
+ {
+ /* Positioning the pointer */
+ pTempSrcRefY = pSrcRefY + (nSrcRefStep * (integerMV.dy/4)) + (integerMV.dx/4);
+ if (x < 0)
+ {
+ pTempSrcRefY = pTempSrcRefY + x;
+ }
+ if (y < 0)
+ {
+ pTempSrcRefY = pTempSrcRefY + (y * nSrcRefStep);
+ }
+ pTempSrcOrgY = pSrcOrgY;
+
+ /* Prepare cand MV */
+ candMV.dx = integerMV.dx + x * 2;
+ candMV.dy = integerMV.dy + y * 2;
+
+ /* Interpolate half pel for the current position*/
+ armVCM4P10_Interpolate_Luma(
+ pTempSrcRefY,
+ nSrcRefStep,
+ interpolY,
+ iBlockWidth,
+ iBlockWidth,
+ iBlockHeight,
+ armAbs(x) * 2,
+ armAbs(y) * 2);
+
+ /* Calculate the SAD */
+ armVCCOMM_SAD(
+ pTempSrcOrgY,
+ nSrcOrgStep,
+ interpolY,
+ iBlockWidth,
+ &candSAD,
+ iBlockHeight,
+ iBlockWidth);
+
+ diffMV.dx = candMV.dx - pMVPred->dx;
+ diffMV.dy = candMV.dy - pMVPred->dy;
+
+ /* Result calculations */
+ armVCM4P10_CompareMotionCostToMV (
+ candMV.dx,
+ candMV.dy,
+ diffMV,
+ candSAD,
+ pSrcDstBestMV,
+ nLamda,
+ pBestCost);
+
+ } /* End of x- axis */
+ } /* End of y-axis */
+
+ return OMX_Sts_NoErr;
+
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Integer.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Integer.c
new file mode 100644
index 0000000..f7764e1
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Integer.c
@@ -0,0 +1,196 @@
+/**
+ *
+ * File Name: omxVCM4P10_BlockMatch_Integer.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for Block matching, a full search algorithm
+ * is implemented
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P10_BlockMatch_Integer (6.3.5.2.1)
+ *
+ * Description:
+ * Performs integer block match. Returns best MV and associated cost.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrgY - Pointer to the top-left corner of the current block. If
+ * iBlockWidth==4, 4-byte alignment required. If iBlockWidth==8,
+ * 8-byte alignment required. If iBlockWidth==16, 16-byte alignment
+ * required.
+ * pSrcRefY - Pointer to the top-left corner of the co-located block in the
+ * reference picture. If iBlockWidth==4, 4-byte alignment
+ * required. If iBlockWidth==8, 8-byte alignment required. If
+ * iBlockWidth==16, 16-byte alignment required.
+ * nSrcOrgStep - Stride of the original picture plane, expressed in terms
+ * of integer pixels; must be a multiple of iBlockWidth.
+ * nSrcRefStep - Stride of the reference picture plane, expressed in terms
+ * of integer pixels
+ * pRefRect - pointer to the valid reference rectangle inside the reference
+ * picture plane
+ * nCurrPointPos - position of the current block in the current plane
+ * iBlockWidth - Width of the current block, expressed in terms of integer
+ * pixels; must be equal to either 4, 8, or 16.
+ * iBlockHeight - Height of the current block, expressed in terms of
+ * integer pixels; must be equal to either 4, 8, or 16.
+ * nLamda - Lamda factor; used to compute motion cost
+ * pMVPred - Predicted MV; used to compute motion cost, expressed in terms
+ * of 1/4-pel units
+ * pMVCandidate - Candidate MV; used to initialize the motion search,
+ * expressed in terms of integer pixels
+ * pMESpec - pointer to the ME specification structure
+ *
+ * Output Arguments:
+ *
+ * pDstBestMV - Best MV resulting from integer search, expressed in terms
+ * of 1/4-pel units
+ * pBestCost - Motion cost associated with the best MV; computed as
+ * SAD+Lamda*BitsUsedByMV
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - any of the following poitners are NULL:
+ * pSrcOrgY, pSrcRefY, pRefRect, pMVPred, pMVCandidate, or pMESpec.
+ * - Either iBlockWidth or iBlockHeight are values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+
+ OMXResult omxVCM4P10_BlockMatch_Integer (
+ const OMX_U8 *pSrcOrgY,
+ OMX_S32 nSrcOrgStep,
+ const OMX_U8 *pSrcRefY,
+ OMX_S32 nSrcRefStep,
+ const OMXRect *pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ OMX_U8 iBlockWidth,
+ OMX_U8 iBlockHeight,
+ OMX_U32 nLamda,
+ const OMXVCMotionVector *pMVPred,
+ const OMXVCMotionVector *pMVCandidate,
+ OMXVCMotionVector *pBestMV,
+ OMX_S32 *pBestCost,
+ void *pMESpec
+)
+{
+ /* Definitions and Initializations*/
+ OMX_INT candSAD;
+ OMX_INT fromX, toX, fromY, toY;
+ /* Offset to the reference at the begining of the bounding box */
+ const OMX_U8 *pTempSrcRefY, *pTempSrcOrgY;
+ OMX_S16 x, y;
+ OMXVCMotionVector diffMV;
+ OMX_S32 nSearchRange;
+ ARMVCM4P10_MESpec *armMESpec = (ARMVCM4P10_MESpec *) pMESpec;
+
+ /* Argument error checks */
+ armRetArgErrIf((iBlockWidth == 4) && (!armIs4ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 8) && (!armIs8ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 16) && (!armIs16ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 4) && (!armIs4ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 8) && (!armIs8ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 16) && (!armIs16ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcOrgY == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcRefY == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pMVPred == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pMVCandidate == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBestMV == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBestCost == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(((iBlockWidth!=4)&&(iBlockWidth!=8)&&(iBlockWidth!=16)) , OMX_Sts_BadArgErr);
+ armRetArgErrIf(((iBlockHeight!=4)&&(iBlockHeight!=8)&&(iBlockHeight!=16)) , OMX_Sts_BadArgErr);
+ armIgnore (pMESpec);
+
+ if(iBlockWidth == 4)
+ {
+ nSearchRange = armMESpec->MEParams.searchRange4x4;
+ }
+ else if(iBlockWidth == 8)
+ {
+ nSearchRange = armMESpec->MEParams.searchRange8x8;
+ }
+ else
+ {
+ nSearchRange = armMESpec->MEParams.searchRange16x16;
+ }
+ /* Check for valid region */
+ fromX = nSearchRange;
+ toX = nSearchRange;
+ fromY = nSearchRange;
+ toY = nSearchRange;
+
+ if ((pCurrPointPos->x - nSearchRange) < pRefRect->x)
+ {
+ fromX = pCurrPointPos->x - pRefRect->x;
+ }
+
+ if ((pCurrPointPos->x + iBlockWidth + nSearchRange) > (pRefRect->x + pRefRect->width))
+ {
+ toX = pRefRect->width - (pCurrPointPos->x - pRefRect->x) - iBlockWidth;
+ }
+
+ if ((pCurrPointPos->y - nSearchRange) < pRefRect->y)
+ {
+ fromY = pCurrPointPos->y - pRefRect->y;
+ }
+
+ if ((pCurrPointPos->y + iBlockWidth + nSearchRange) > (pRefRect->y + pRefRect->height))
+ {
+ toY = pRefRect->width - (pCurrPointPos->y - pRefRect->y) - iBlockWidth;
+ }
+
+ pBestMV->dx = -fromX * 4;
+ pBestMV->dy = -fromY * 4;
+ /* Initialize to max value as a start point */
+ *pBestCost = 0x7fffffff;
+
+ /* Looping on y- axis */
+ for (y = -fromY; y <= toY; y++)
+ {
+ /* Looping on x- axis */
+ for (x = -fromX; x <= toX; x++)
+ {
+ /* Positioning the pointer */
+ pTempSrcRefY = pSrcRefY + (nSrcRefStep * y) + x;
+ pTempSrcOrgY = pSrcOrgY;
+
+ /* Calculate the SAD */
+ armVCCOMM_SAD(
+ pTempSrcOrgY,
+ nSrcOrgStep,
+ pTempSrcRefY,
+ nSrcRefStep,
+ &candSAD,
+ iBlockHeight,
+ iBlockWidth);
+
+ diffMV.dx = (x * 4) - pMVPred->dx;
+ diffMV.dy = (y * 4) - pMVPred->dy;
+
+ /* Result calculations */
+ armVCM4P10_CompareMotionCostToMV ((x * 4), (y * 4), diffMV, candSAD, pBestMV, nLamda, pBestCost);
+
+ } /* End of x- axis */
+ } /* End of y-axis */
+
+ return OMX_Sts_NoErr;
+
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Quarter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Quarter.c
new file mode 100644
index 0000000..513ee25
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_BlockMatch_Quarter.c
@@ -0,0 +1,199 @@
+/**
+ *
+ * File Name: omxVCM4P10_BlockMatch_Quarter.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for quater pel Block matching,
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+
+/**
+ * Function: omxVCM4P10_BlockMatch_Quarter (6.3.5.2.3)
+ *
+ * Description:
+ * Performs a quarter-pel block match using results from a prior half-pel
+ * search. Returns the best MV and associated cost. This function estimates
+ * the quarter-pixel motion vector by interpolating the half-pel resolution
+ * motion vector referenced by the input parameter pSrcDstBestMV, i.e., the
+ * initial half-pel MV is generated externally. The function
+ * omxVCM4P10_BlockMatch_Half may be used for half-pel motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrgY - Pointer to the current position in original picture plane. If
+ * iBlockWidth==4, 4-byte alignment required. If iBlockWidth==8,
+ * 8-byte alignment required. If iBlockWidth==16, 16-byte alignment
+ * required.
+ * pSrcRefY - Pointer to the top-left corner of the co-located block in the
+ * reference picture If iBlockWidth==4, 4-byte alignment
+ * required. If iBlockWidth==8, 8-byte alignment required. If
+ * iBlockWidth==16, 16-byte alignment required.
+ * nSrcOrgStep - Stride of the original picture plane in terms of full
+ * pixels; must be a multiple of iBlockWidth.
+ * nSrcRefStep - Stride of the reference picture plane in terms of full
+ * pixels
+ * iBlockWidth - Width of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * iBlockHeight - Height of the current block in terms of full pixels; must
+ * be equal to either 4, 8, or 16.
+ * nLamda - Lamda factor, used to compute motion cost
+ * pMVPred - Predicted MV, represented in terms of 1/4-pel units; used to
+ * compute motion cost
+ * pSrcDstBestMV - The best MV resulting from a prior half-pel search,
+ * represented in terms of 1/4 pel units
+ *
+ * Output Arguments:
+ *
+ * pSrcDstBestMV - Best MV resulting from the quarter-pel search, expressed
+ * in terms of 1/4-pel units
+ * pBestCost - Motion cost associated with the best MV; computed as
+ * SAD+Lamda*BitsUsedByMV
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - One of more of the following pointers is NULL:
+ * pSrcOrgY, pSrcRefY, pSrcDstBestMV, pMVPred, pBestCost
+ * - iBlockWidth or iBlockHeight are equal to values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+
+OMXResult omxVCM4P10_BlockMatch_Quarter(
+ const OMX_U8* pSrcOrgY,
+ OMX_S32 nSrcOrgStep,
+ const OMX_U8* pSrcRefY,
+ OMX_S32 nSrcRefStep,
+ OMX_U8 iBlockWidth,
+ OMX_U8 iBlockHeight,
+ OMX_U32 nLamda,
+ const OMXVCMotionVector* pMVPred,
+ OMXVCMotionVector* pSrcDstBestMV,
+ OMX_S32* pBestCost
+)
+{
+ /* Definitions and Initializations*/
+ OMX_INT candSAD;
+ OMX_INT fromX, toX, fromY, toY;
+ /* Offset to the reference at the begining of the bounding box */
+ const OMX_U8 *pTempSrcRefY, *pTempSrcOrgY;
+ OMX_S16 x, y;
+ OMXVCMotionVector diffMV, candMV, initialMV;
+ OMX_U8 interpolY[256];
+ OMX_S32 pelPosX, pelPosY;
+
+ /* Argument error checks */
+ armRetArgErrIf((iBlockWidth == 4) && (!armIs4ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 8) && (!armIs8ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 16) && (!armIs16ByteAligned(pSrcOrgY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 4) && (!armIs4ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 8) && (!armIs8ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlockWidth == 16) && (!armIs16ByteAligned(pSrcRefY)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((nSrcOrgStep % iBlockWidth), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcOrgY == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcRefY == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pMVPred == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcDstBestMV == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBestCost == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(((iBlockWidth!=4)&&(iBlockWidth!=8)&&(iBlockWidth!=16)) , OMX_Sts_BadArgErr);
+ armRetArgErrIf(((iBlockHeight!=4)&&(iBlockHeight!=8)&&(iBlockHeight!=16)) , OMX_Sts_BadArgErr);
+
+
+ /* Check for valid region */
+ fromX = 1;
+ toX = 1;
+ fromY = 1;
+ toY = 1;
+
+ /* Initialize to max value as a start point */
+ *pBestCost = 0x7fffffff;
+
+ initialMV.dx = pSrcDstBestMV->dx;
+ initialMV.dy = pSrcDstBestMV->dy;
+
+ /* Looping on y- axis */
+ for (y = -fromY; y <= toY; y++)
+ {
+ /* Looping on x- axis */
+ for (x = -fromX; x <= toX; x++)
+ {
+ /* Positioning the pointer */
+ pTempSrcRefY = pSrcRefY + (nSrcRefStep * (initialMV.dy/4)) + (initialMV.dx/4);
+
+ /* Calculating the fract pel position */
+ pelPosX = (initialMV.dx % 4) + x;
+ if (pelPosX < 0)
+ {
+ pTempSrcRefY = pTempSrcRefY - 1;
+ pelPosX += 4;
+ }
+ pelPosY = (initialMV.dy % 4) + y;
+ if (pelPosY < 0)
+ {
+ pTempSrcRefY = pTempSrcRefY - (1 * nSrcRefStep);
+ pelPosY += 4;
+ }
+
+ pTempSrcOrgY = pSrcOrgY;
+
+ /* Prepare cand MV */
+ candMV.dx = initialMV.dx + x;
+ candMV.dy = initialMV.dy + y;
+
+ /* Interpolate Quater pel for the current position*/
+ armVCM4P10_Interpolate_Luma(
+ pTempSrcRefY,
+ nSrcRefStep,
+ interpolY,
+ iBlockWidth,
+ iBlockWidth,
+ iBlockHeight,
+ pelPosX,
+ pelPosY);
+
+ /* Calculate the SAD */
+ armVCCOMM_SAD(
+ pTempSrcOrgY,
+ nSrcOrgStep,
+ interpolY,
+ iBlockWidth,
+ &candSAD,
+ iBlockHeight,
+ iBlockWidth);
+
+ diffMV.dx = candMV.dx - pMVPred->dx;
+ diffMV.dy = candMV.dy - pMVPred->dy;
+
+ /* Result calculations */
+ armVCM4P10_CompareMotionCostToMV (
+ candMV.dx,
+ candMV.dy,
+ diffMV,
+ candSAD,
+ pSrcDstBestMV,
+ nLamda,
+ pBestCost);
+
+ } /* End of x- axis */
+ } /* End of y-axis */
+
+ return OMX_Sts_NoErr;
+
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
new file mode 100644
index 0000000..a07b1bb
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockChroma_I.c
@@ -0,0 +1,107 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_DeblockChroma_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 intra chroma deblock
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_DeblockChroma_I (6.3.3.3.6)
+ *
+ * Description:
+ * Performs in-place deblocking filtering on all edges of the chroma
+ * macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 8-byte aligned.
+ * srcdstStep - step of the arrays; must be a multiple of 8.
+ * pAlpha - pointer to a 2x2 array of alpha thresholds, organized as
+ * follows: {external vertical edge, internal vertical edge,
+ * external horizontal edge, internal horizontal edge }. Per
+ * [ISO14496-10] alpha values must be in the range [0,255].
+ * pBeta - pointer to a 2x2 array of Beta Thresholds, organized as follows:
+ * { external vertical edge, internal vertical edge, external
+ * horizontal edge, internal horizontal edge }. Per [ISO14496-10]
+ * beta values must be in the range [0,18].
+ * pThresholds - array of size 8x2 of Thresholds (TC0) (values for the left
+ * or above edge of each 4x2 or 2x4 block, arranged in vertical
+ * block order and then in horizontal block order); must be aligned
+ * on a 4-byte boundary. Per [ISO14496-10] values must be in the
+ * range [0,25].
+ * pBS - array of size 16x2 of BS parameters (arranged in scan block order
+ * for vertical edges and then horizontal edges); valid in the
+ * range [0,4] with the following restrictions: i) pBS[i]== 4 may
+ * occur only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^3]==
+ * 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds, or pBS. pSrcDst is not 8-byte aligned.
+ * either pThresholds or pBS is not 4-byte aligned.
+ * - one or more entries in the table pAlpha[0..3] is outside the range
+ * [0,255].
+ * - one or more entries in the table pBeta[0..3] is outside the range
+ * [0,18].
+ * - one or more entries in the table pThresholds[0..15]is outside of
+ * the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - srcdstStep is not a multiple of 8.
+ *
+ */
+OMXResult omxVCM4P10_DeblockChroma_I(
+ OMX_U8* pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8* pAlpha,
+ const OMX_U8* pBeta,
+ const OMX_U8* pThresholds,
+ const OMX_U8 *pBS
+)
+{
+ OMXResult errorCode;
+
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot8ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(srcdstStep & 7, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pAlpha == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pThresholds == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pThresholds), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBS == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pBS), OMX_Sts_BadArgErr);
+
+ errorCode = omxVCM4P10_FilterDeblockingChroma_VerEdge_I(
+ pSrcDst, srcdstStep, pAlpha, pBeta, pThresholds, pBS);
+
+ armRetArgErrIf(errorCode != OMX_Sts_NoErr, errorCode)
+
+ errorCode = omxVCM4P10_FilterDeblockingChroma_HorEdge_I(
+ pSrcDst, srcdstStep, pAlpha+2, pBeta+2, pThresholds+8, pBS+16);
+
+ return errorCode;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
new file mode 100644
index 0000000..1f3a646
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DeblockLuma_I.c
@@ -0,0 +1,109 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_DeblockLuma_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 luma deblock
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+
+/**
+ * Function: omxVCM4P10_DeblockLuma_I (6.3.3.3.5)
+ *
+ * Description:
+ * This function performs in-place deblock filtering the horizontal and
+ * vertical edges of a luma macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 16-byte aligned.
+ * srcdstStep - image width; must be a multiple of 16.
+ * pAlpha - pointer to a 2x2 table of alpha thresholds, organized as
+ * follows: {external vertical edge, internal vertical edge,
+ * external horizontal edge, internal horizontal edge }. Per
+ * [ISO14496-10] alpha values must be in the range [0,255].
+ * pBeta - pointer to a 2x2 table of beta thresholds, organized as follows:
+ * {external vertical edge, internal vertical edge, external
+ * horizontal edge, internal horizontal edge }. Per [ISO14496-10]
+ * beta values must be in the range [0,18].
+ * pThresholds - pointer to a 16x2 table of threshold (TC0), organized as
+ * follows: {values for the left or above edge of each 4x4 block,
+ * arranged in vertical block order and then in horizontal block
+ * order}; must be aligned on a 4-byte boundary. Per [ISO14496-10]
+ * values must be in the range [0,25].
+ * pBS - pointer to a 16x2 table of BS parameters arranged in scan block
+ * order for vertical edges and then horizontal edges; valid in the
+ * range [0,4] with the following restrictions: i) pBS[i]== 4 may
+ * occur only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^3]==
+ * 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds or pBS. pSrcDst is not 16-byte aligned.
+ * either pThresholds or pBS is not aligned on a 4-byte boundary.
+ * - one or more entries in the table pAlpha[0..3] is outside the range
+ * [0,255].
+ * - one or more entries in the table pBeta[0..3] is outside the range
+ * [0,18].
+ * - one or more entries in the table pThresholds[0..31]is outside of
+ * the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - srcdstStep is not a multiple of 16.
+ *
+ */
+
+OMXResult omxVCM4P10_DeblockLuma_I(
+ OMX_U8* pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8* pAlpha,
+ const OMX_U8* pBeta,
+ const OMX_U8* pThresholds,
+ const OMX_U8 *pBS
+)
+{
+ OMXResult errorCode;
+
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot16ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(srcdstStep & 15, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pAlpha == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pThresholds == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pThresholds), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBS == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pBS), OMX_Sts_BadArgErr);
+
+ errorCode = omxVCM4P10_FilterDeblockingLuma_VerEdge_I(
+ pSrcDst, srcdstStep, pAlpha, pBeta, pThresholds, pBS);
+
+ armRetArgErrIf(errorCode != OMX_Sts_NoErr, errorCode)
+
+ errorCode = omxVCM4P10_FilterDeblockingLuma_HorEdge_I(
+ pSrcDst, srcdstStep, pAlpha+2, pBeta+2, pThresholds+16, pBS+16);
+
+ return errorCode;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
new file mode 100644
index 0000000..830ddc7
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
@@ -0,0 +1,86 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 decode coefficients module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC (6.3.4.1.1)
+ *
+ * Description:
+ * Performs CAVLC decoding and inverse raster scan for a 2x2 block of
+ * ChromaDCLevel. The decoded coefficients in the packed position-coefficient
+ * buffer are stored in reverse zig-zag order, i.e., the first buffer element
+ * contains the last non-zero postion-coefficient pair of the block. Within
+ * each position-coefficient pair, the position entry indicates the
+ * raster-scan position of the coefficient, while the coefficient entry
+ * contains the coefficient value.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - Double pointer to current byte in bit stream buffer
+ * pOffset - Pointer to current bit position in the byte pointed to by
+ * *ppBitStream; valid in the range [0,7].
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after each block is decoded
+ * pOffset - *pOffset is updated after each block is decoded
+ * pNumCoeff - Pointer to the number of nonzero coefficients in this block
+ * ppPosCoefBuf - Double pointer to destination residual
+ * coefficient-position pair buffer. Buffer position
+ * (*ppPosCoefBuf) is updated upon return, unless there are only
+ * zero coefficients in the currently decoded block. In this case
+ * the caller is expected to bypass the transform/dequantization of
+ * the empty blocks.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppBitStream or pOffset is NULL.
+ * - ppPosCoefBuf or pNumCoeff is NULL.
+ * OMX_Sts_Err - if one of the following is true:
+ * - an illegal code is encountered in the bitstream
+ *
+ */
+
+OMXResult omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC (
+ const OMX_U8** ppBitStream,
+ OMX_S32* pOffset,
+ OMX_U8* pNumCoeff,
+ OMX_U8** ppPosCoefbuf
+ )
+
+{
+ armRetArgErrIf(ppBitStream==NULL , OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppBitStream==NULL , OMX_Sts_BadArgErr);
+ armRetArgErrIf(pOffset==NULL , OMX_Sts_BadArgErr);
+ armRetArgErrIf(*pOffset<0 , OMX_Sts_BadArgErr);
+ armRetArgErrIf(*pOffset>7 , OMX_Sts_BadArgErr);
+ armRetArgErrIf(pNumCoeff==NULL , OMX_Sts_BadArgErr);
+ armRetArgErrIf(ppPosCoefbuf==NULL , OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppPosCoefbuf==NULL , OMX_Sts_BadArgErr);
+
+ return armVCM4P10_DecodeCoeffsToPair(ppBitStream, pOffset, pNumCoeff,
+ ppPosCoefbuf, 4, 4);
+
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
new file mode 100644
index 0000000..7e83d1e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DecodeCoeffsToPairCAVLC.c
@@ -0,0 +1,117 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_DecodeCoeffsToPairCAVLC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 decode coefficients module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_DecodeCoeffsToPairCAVLC (6.3.4.1.2)
+ *
+ * Description:
+ * Performs CAVLC decoding and inverse zigzag scan for 4x4 block of
+ * Intra16x16DCLevel, Intra16x16ACLevel, LumaLevel, and ChromaACLevel. Inverse
+ * field scan is not supported. The decoded coefficients in the packed
+ * position-coefficient buffer are stored in reverse zig-zag order, i.e., the
+ * first buffer element contains the last non-zero postion-coefficient pair of
+ * the block. Within each position-coefficient pair, the position entry
+ * indicates the raster-scan position of the coefficient, while the
+ * coefficient entry contains the coefficient value.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream -Double pointer to current byte in bit stream buffer
+ * pOffset - Pointer to current bit position in the byte pointed to by
+ * *ppBitStream; valid in the range [0,7].
+ * sMaxNumCoeff - Maximum the number of non-zero coefficients in current
+ * block
+ * sVLCSelect - VLC table selector, obtained from the number of non-zero
+ * coefficients contained in the above and left 4x4 blocks. It is
+ * equivalent to the variable nC described in H.264 standard table
+ * 9 5, except its value can t be less than zero.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after each block is decoded.
+ * Buffer position (*ppPosCoefBuf) is updated upon return, unless
+ * there are only zero coefficients in the currently decoded block.
+ * In this case the caller is expected to bypass the
+ * transform/dequantization of the empty blocks.
+ * pOffset - *pOffset is updated after each block is decoded
+ * pNumCoeff - Pointer to the number of nonzero coefficients in this block
+ * ppPosCoefBuf - Double pointer to destination residual
+ * coefficient-position pair buffer
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppBitStream or pOffset is NULL.
+ * - ppPosCoefBuf or pNumCoeff is NULL.
+ * - sMaxNumCoeff is not equal to either 15 or 16.
+ * - sVLCSelect is less than 0.
+ *
+ * OMX_Sts_Err - if one of the following is true:
+ * - an illegal code is encountered in the bitstream
+ *
+ */
+
+OMXResult omxVCM4P10_DecodeCoeffsToPairCAVLC(
+ const OMX_U8** ppBitStream,
+ OMX_S32* pOffset,
+ OMX_U8* pNumCoeff,
+ OMX_U8**ppPosCoefbuf,
+ OMX_INT sVLCSelect,
+ OMX_INT sMaxNumCoeff
+ )
+{
+ int nTable;
+
+ armRetArgErrIf(ppBitStream==NULL , OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppBitStream==NULL , OMX_Sts_BadArgErr);
+ armRetArgErrIf(pOffset==NULL , OMX_Sts_BadArgErr);
+ armRetArgErrIf(*pOffset<0 , OMX_Sts_BadArgErr);
+ armRetArgErrIf(*pOffset>7 , OMX_Sts_BadArgErr);
+ armRetArgErrIf(pNumCoeff==NULL , OMX_Sts_BadArgErr);
+ armRetArgErrIf(ppPosCoefbuf==NULL , OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppPosCoefbuf==NULL , OMX_Sts_BadArgErr);
+ armRetArgErrIf(sVLCSelect<0 , OMX_Sts_BadArgErr);
+ armRetArgErrIf(sMaxNumCoeff<15 , OMX_Sts_BadArgErr);
+ armRetArgErrIf(sMaxNumCoeff>16 , OMX_Sts_BadArgErr);
+
+ /* Find VLC table number */
+ if (sVLCSelect<2)
+ {
+ nTable = 0;
+ }
+ else if (sVLCSelect<4)
+ {
+ nTable = 1;
+ }
+ else if (sVLCSelect<8)
+ {
+ nTable = 2;
+ }
+ else /* sVLCSelect >= 8 */
+ {
+ nTable = 3;
+ }
+
+ return armVCM4P10_DecodeCoeffsToPair(ppBitStream, pOffset, pNumCoeff,
+ ppPosCoefbuf, nTable, sMaxNumCoeff);
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd.c
new file mode 100644
index 0000000..ed5a158
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_DequantTransformResidualFromPairAndAdd.c
@@ -0,0 +1,145 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_DequantTransformResidualFromPairAndAdd.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 inverse quantize and transform module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/*
+ * Description:
+ * Dequantize Luma AC block
+ */
+
+static void DequantLumaAC4x4(
+ OMX_S16* pSrcDst,
+ OMX_INT QP
+)
+{
+ const OMX_U8 *pVRow = &armVCM4P10_VMatrix[QP%6][0];
+ int Shift = QP / 6;
+ int i;
+ OMX_S32 Value;
+
+ for (i=0; i<16; i++)
+ {
+
+ Value = (pSrcDst[i] * pVRow[armVCM4P10_PosToVCol4x4[i]]) << Shift;
+ pSrcDst[i] = (OMX_S16)Value;
+ }
+}
+
+/**
+ * Function: omxVCM4P10_DequantTransformResidualFromPairAndAdd (6.3.4.2.3)
+ *
+ * Description:
+ * Reconstruct the 4x4 residual block from coefficient-position pair buffer,
+ * perform dequantization and integer inverse transformation for 4x4 block of
+ * residuals with previous intra prediction or motion compensation data, and
+ * update the pair buffer pointer to next non-empty block. If pDC == NULL,
+ * there re 16 non-zero AC coefficients at most in the packed buffer starting
+ * from 4x4 block position 0; If pDC != NULL, there re 15 non-zero AC
+ * coefficients at most in the packet buffer starting from 4x4 block position
+ * 1.
+ *
+ * Input Arguments:
+ *
+ * ppSrc - Double pointer to residual coefficient-position pair buffer
+ * output by CALVC decoding
+ * pPred - Pointer to the predicted 4x4 block; must be aligned on a 4-byte
+ * boundary
+ * predStep - Predicted frame step size in bytes; must be a multiple of 4
+ * dstStep - Destination frame step in bytes; must be a multiple of 4
+ * pDC - Pointer to the DC coefficient of this block, NULL if it doesn't
+ * exist
+ * QP - QP Quantization parameter. It should be QpC in chroma 4x4 block
+ * decoding, otherwise it should be QpY.
+ * AC - Flag indicating if at least one non-zero AC coefficient exists
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the reconstructed 4x4 block data; must be aligned on a
+ * 4-byte boundary
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - pPred or pDst is NULL.
+ * - pPred or pDst is not 4-byte aligned.
+ * - predStep or dstStep is not a multiple of 4.
+ * - AC !=0 and Qp is not in the range of [0-51] or ppSrc == NULL.
+ * - AC ==0 && pDC ==NULL.
+ *
+ */
+
+OMXResult omxVCM4P10_DequantTransformResidualFromPairAndAdd(
+ const OMX_U8 **ppSrc,
+ const OMX_U8 *pPred,
+ const OMX_S16 *pDC,
+ OMX_U8 *pDst,
+ OMX_INT predStep,
+ OMX_INT dstStep,
+ OMX_INT QP,
+ OMX_INT AC
+)
+{
+ OMX_S16 pBuffer[16+4];
+ OMX_S16 *pDelta;
+ int i,x,y;
+
+ armRetArgErrIf(pPred == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pPred),OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predStep & 3, OMX_Sts_BadArgErr);
+ armRetArgErrIf(dstStep & 3, OMX_Sts_BadArgErr);
+ armRetArgErrIf(AC!=0 && (QP<0), OMX_Sts_BadArgErr);
+ armRetArgErrIf(AC!=0 && (QP>51), OMX_Sts_BadArgErr);
+ armRetArgErrIf(AC!=0 && ppSrc==NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(AC!=0 && *ppSrc==NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(AC==0 && pDC==NULL, OMX_Sts_BadArgErr);
+
+ pDelta = armAlignTo8Bytes(pBuffer);
+
+ for (i=0; i<16; i++)
+ {
+ pDelta[i] = 0;
+ }
+ if (AC)
+ {
+ armVCM4P10_UnpackBlock4x4(ppSrc, pDelta);
+ DequantLumaAC4x4(pDelta, QP);
+ }
+ if (pDC)
+ {
+ pDelta[0] = pDC[0];
+ }
+ armVCM4P10_TransformResidual4x4(pDelta,pDelta);
+
+ for (y=0; y<4; y++)
+ {
+ for (x=0; x<4; x++)
+ {
+ pDst[y*dstStep+x] = (OMX_U8)armClip(0,255,pPred[y*predStep+x] + pDelta[4*y+x]);
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I.c
new file mode 100644
index 0000000..75edee2
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_HorEdge_I.c
@@ -0,0 +1,130 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_FilterDeblockingChroma_HorEdge_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 chroma deblock module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingChroma_HorEdge_I (6.3.3.3.4)
+ *
+ * Description:
+ * Performs in-place deblock filtering on the horizontal edges of the chroma
+ * macroblock (8x8).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 8-byte aligned.
+ * srcdstStep - array step; must be a multiple of 8.
+ * pAlpha - array of size 2 containing alpha thresholds; the first element
+ * contains the threshold for the external horizontal edge, and the
+ * second element contains the threshold for internal horizontal
+ * edge. Per [ISO14496-10] alpha values must be in the range
+ * [0,255].
+ * pBeta - array of size 2 containing beta thresholds; the first element
+ * contains the threshold for the external horizontal edge, and the
+ * second element contains the threshold for the internal
+ * horizontal edge. Per [ISO14496-10] beta values must be in the
+ * range [0,18].
+ * pThresholds - array of size 8 containing thresholds, TC0, for the top
+ * horizontal edge of each 2x4 chroma block, arranged in horizontal
+ * block order; must be aligned on a 4-byte boundary. Per
+ * [ISO14496-10] values must be in the range [0,25].
+ * pBS - array of size 16 containing BS parameters for each 2x2 chroma
+ * block, arranged in horizontal block order; valid in the range
+ * [0,4] with the following restrictions: i) pBS[i]== 4 may occur
+ * only for 0<=i<=3, ii) pBS[i]== 4 if and only if pBS[i^3]== 4.
+ * Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr, if one of the following cases occurs:
+ * - any of the following pointers is NULL:
+ * pSrcDst, pAlpha, pBeta, pThresholds, or pBS.
+ * - pSrcDst is not 8-byte aligned.
+ * - srcdstStep is not a multiple of 8.
+ * - pThresholds is not 4-byte aligned.
+ * - pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * - pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * - One or more entries in the table pThresholds[0..7] is outside
+ * of the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - pBS is not 4-byte aligned.
+ *
+ */
+
+OMXResult omxVCM4P10_FilterDeblockingChroma_HorEdge_I(
+ OMX_U8* pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8* pAlpha,
+ const OMX_U8* pBeta,
+ const OMX_U8* pThresholds,
+ const OMX_U8 *pBS
+ )
+{
+ int I, X, Y, Internal=0;
+
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot8ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(srcdstStep & 7, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pAlpha == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pThresholds == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pThresholds), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBS == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pBS), OMX_Sts_BadArgErr);
+
+ for (Y=0; Y<8; Y+=4, Internal=1)
+ {
+ for (X=0; X<8; X++)
+ {
+ I = (X>>1)+4*(Y>>1);
+
+ armRetArgErrIf(pBS[I] > 4, OMX_Sts_BadArgErr)
+
+ armRetArgErrIf( (I > 3) && (pBS[I] == 4),
+ OMX_Sts_BadArgErr)
+
+ armRetArgErrIf( (I < 4) &&
+ ( (pBS[I] == 4) && (pBS[I^1] != 4) ),
+ OMX_Sts_BadArgErr)
+
+
+ /* Filter horizontal edge with q0 at (X,Y) */
+ armVCM4P10_DeBlockPixel(
+ pSrcDst + Y*srcdstStep + X,
+ srcdstStep,
+ pThresholds[(X>>1)+4*(Y>>2)],
+ pAlpha[Internal],
+ pBeta[Internal],
+ pBS[I],
+ 1);
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I.c
new file mode 100644
index 0000000..10b2592
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingChroma_VerEdge_I.c
@@ -0,0 +1,131 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_FilterDeblockingChroma_VerEdge_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 deblocking module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingChroma_VerEdge_I (6.3.3.3.3)
+ *
+ * Description:
+ * Performs in-place deblock filtering on four vertical edges of the chroma
+ * macroblock (8x8).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the input macroblock; must be 8-byte aligned.
+ * srcdstStep - Step of the arrays; must be a multiple of 8.
+ * pAlpha - Array of size 2 of alpha thresholds (the first item is alpha
+ * threshold for external vertical edge, and the second item is for
+ * internal vertical edge); per [ISO14496-10] alpha values must be
+ * in the range [0,255].
+ * pBeta - Array of size 2 of beta thresholds (the first item is the beta
+ * threshold for the external vertical edge, and the second item is
+ * for the internal vertical edge); per [ISO14496-10] beta values
+ * must be in the range [0,18].
+ * pThresholds - Array of size 8 containing thresholds, TC0, for the left
+ * vertical edge of each 4x2 chroma block, arranged in vertical
+ * block order; must be aligned on a 4-byte boundary. Per
+ * [ISO14496-10] values must be in the range [0,25].
+ * pBS - Array of size 16 of BS parameters (values for each 2x2 chroma
+ * block, arranged in vertical block order). This parameter is the
+ * same as the pBSparameter passed into FilterDeblockLuma_VerEdge;
+ * valid in the range [0,4] with the following restrictions: i)
+ * pBS[i]== 4 may occur only for 0<=i<=3, ii) pBS[i]== 4 if and
+ * only if pBS[i^3]== 4. Must be 4 byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds, or pBS.
+ * - pSrcDst is not 8-byte aligned.
+ * - srcdstStep is not a multiple of 8.
+ * - pThresholds is not 4-byte aligned.
+ * - pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * - pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * - One or more entries in the table pThresholds[0..7] is outside
+ * of the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ * - pBS is not 4-byte aligned.
+ *
+ */
+
+OMXResult omxVCM4P10_FilterDeblockingChroma_VerEdge_I(
+ OMX_U8* pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8* pAlpha,
+ const OMX_U8* pBeta,
+ const OMX_U8* pThresholds,
+ const OMX_U8 *pBS
+ )
+{
+ int I, X, Y, Internal=0;
+
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot8ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(srcdstStep & 7, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pAlpha == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pThresholds == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pThresholds), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBS == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pBS), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta[0] > 18, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta[1] > 18, OMX_Sts_BadArgErr);
+
+ for (X=0; X<8; X+=4, Internal=1)
+ {
+ for (Y=0; Y<8; Y++)
+ {
+ I = (Y>>1)+4*(X>>1);
+
+ armRetArgErrIf(pBS[I] > 4, OMX_Sts_BadArgErr);
+
+ armRetArgErrIf( (I > 3) && (pBS[I] == 4),
+ OMX_Sts_BadArgErr);
+
+ armRetArgErrIf( ( (pBS[I] == 4) && (pBS[I^3] != 4) ),
+ OMX_Sts_BadArgErr);
+ armRetArgErrIf(pThresholds[Y] > 25, OMX_Sts_BadArgErr);
+
+
+ /* Filter vertical edge with q0 at (X,Y) */
+ armVCM4P10_DeBlockPixel(
+ pSrcDst + Y*srcdstStep + X,
+ 1,
+ pThresholds[(Y>>1)+4*(X>>2)],
+ pAlpha[Internal],
+ pBeta[Internal],
+ pBS[I],
+ 1);
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I.c
new file mode 100644
index 0000000..30a37da
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_HorEdge_I.c
@@ -0,0 +1,125 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_FilterDeblockingLuma_HorEdge_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 luma deblock module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingLuma_HorEdge_I (6.3.3.3.2)
+ *
+ * Description:
+ * Performs in-place deblock filtering on four horizontal edges of the luma
+ * macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input macroblock; must be 16-byte aligned.
+ * srcdstStep -s tep of the arrays; must be a multiple of 16.
+ * pAlpha - array of size 2 of alpha thresholds (the first item is the alpha
+ * threshold for the external vertical edge, and the second item is
+ * for the internal horizontal edge); per [ISO14496-10] alpha
+ * values must be in the range [0,255].
+ * pBeta - array of size 2 of beta thresholds (the first item is the beta
+ * threshold for the external horizontal edge, and the second item
+ * is for the internal horizontal edge). Per [ISO14496-10] beta
+ * values must be in the range [0,18].
+ * pThresholds - array of size 16 containing thresholds, TC0, for the top
+ * horizontal edge of each 4x4 block, arranged in horizontal block
+ * order; must be aligned on a 4-byte boundary. Per [ISO14496 10]
+ * values must be in the range [0,25].
+ * pBS - array of size 16 of BS parameters (arranged in horizontal block
+ * order); valid in the range [0,4] with the following
+ * restrictions: i) pBS[i]== 4 may occur only for 0<=i<=3, ii)
+ * pBS[i]== 4 if and only if pBS[i^3]== 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr, if the function runs without error.
+ *
+ * OMX_Sts_BadArgErr, if one of the following cases occurs:
+ * - one or more of the following pointers is NULL: pSrcDst, pAlpha,
+ * pBeta, pThresholds, or pBS.
+ * - either pThresholds or pBS is not aligned on a 4-byte boundary.
+ * - pSrcDst is not 16-byte aligned.
+ * - srcdstStep is not a multiple of 16.
+ * - pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * - pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * - One or more entries in the table pThresholds[0..15] is
+ * outside of the range [0,25].
+ * - pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or
+ * (pBS[i]==4 && pBS[i^3]!=4) for 0<=i<=3.
+ *
+ */
+
+OMXResult omxVCM4P10_FilterDeblockingLuma_HorEdge_I(
+ OMX_U8* pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8* pAlpha,
+ const OMX_U8* pBeta,
+ const OMX_U8* pThresholds,
+ const OMX_U8 *pBS
+ )
+{
+ int I, X, Y, Internal=0;
+
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot8ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(srcdstStep & 7, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pAlpha == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pThresholds == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pThresholds), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBS == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pBS), OMX_Sts_BadArgErr);
+
+ for (Y=0; Y<16; Y+=4, Internal=1)
+ {
+ for (X=0; X<16; X++)
+ {
+ I = (X>>2)+4*(Y>>2);
+
+ armRetArgErrIf(pBS[I] > 4, OMX_Sts_BadArgErr)
+
+ armRetArgErrIf( (I > 3) && (pBS[I] == 4),
+ OMX_Sts_BadArgErr)
+
+ armRetArgErrIf( (I < 4) &&
+ ( (pBS[I] == 4) && (pBS[I^1] != 4) ),
+ OMX_Sts_BadArgErr)
+
+ /* Filter horizontal edge with q0 at (X,Y) */
+ armVCM4P10_DeBlockPixel(
+ pSrcDst + Y*srcdstStep + X,
+ srcdstStep,
+ pThresholds[I],
+ pAlpha[Internal],
+ pBeta[Internal],
+ pBS[I],
+ 0);
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I.c
new file mode 100644
index 0000000..8733427
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_FilterDeblockingLuma_VerEdge_I.c
@@ -0,0 +1,128 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_FilterDeblockingLuma_VerEdge_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 luma deblock module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_FilterDeblockingLuma_VerEdge_I (6.3.3.3.1)
+ *
+ * Description:
+ * Performs in-place deblock filtering on four vertical edges of the luma
+ * macroblock (16x16).
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the input macroblock; must be 16-byte aligned.
+ * srcdstStep -Step of the arrays; must be a multiple of 16.
+ * pAlpha -Array of size 2 of alpha thresholds (the first item is the alpha
+ * threshold for the external vertical edge, and the second item is
+ * for the internal vertical edge); per [ISO14496-10] alpha values
+ * must be in the range [0,255].
+ * pBeta -Array of size 2 of beta thresholds (the first item is the beta
+ * threshold for the external vertical edge, and the second item is
+ * for the internal vertical edge); per [ISO14496-10] beta values
+ * must be in the range [0,18].
+ * pThresholds -Array of size 16 of Thresholds (TC0) (values for the left
+ * edge of each 4x4 block, arranged in vertical block order); must
+ * be aligned on a 4-byte boundary.. Per [ISO14496-10] values must
+ * be in the range [0,25].
+ * pBS -Array of size 16 of BS parameters (arranged in vertical block
+ * order); valid in the range [0,4] with the following
+ * restrictions: i) pBS[i]== 4 may occur only for 0<=i<=3, ii)
+ * pBS[i]== 4 if and only if pBS[i^3]== 4. Must be 4-byte aligned.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst -Pointer to filtered output macroblock.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * Either of the pointers in pSrcDst, pAlpha, pBeta, pThresholds, or pBS
+ * is NULL.
+ * Either pThresholds or pBS is not aligned on a 4-byte boundary.
+ * pSrcDst is not 16-byte aligned.
+ * srcdstStep is not a multiple of 16.
+ * pAlpha[0] and/or pAlpha[1] is outside the range [0,255].
+ * pBeta[0] and/or pBeta[1] is outside the range [0,18].
+ * One or more entries in the table pThresholds[0..15]is outside of the
+ * range [0,25].
+ * pBS is out of range, i.e., one of the following conditions is true:
+ * pBS[i]<0, pBS[i]>4, pBS[i]==4 for i>=4, or (pBS[i]==4 &&
+ * pBS[i^3]!=4) for 0<=i<=3.
+ *
+ */
+
+OMXResult omxVCM4P10_FilterDeblockingLuma_VerEdge_I(
+ OMX_U8* pSrcDst,
+ OMX_S32 srcdstStep,
+ const OMX_U8* pAlpha,
+ const OMX_U8* pBeta,
+ const OMX_U8* pThresholds,
+ const OMX_U8 *pBS
+ )
+{
+ int X, Y, I, Internal=0;
+
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot16ByteAligned(pSrcDst),OMX_Sts_BadArgErr);
+ armRetArgErrIf(srcdstStep & 15, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pAlpha == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pThresholds == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pThresholds), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBS == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pBS), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta[0] > 18, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBeta[1] > 18, OMX_Sts_BadArgErr);
+
+
+ for (X=0; X<16; X+=4, Internal=1)
+ {
+ for (Y=0; Y<16; Y++)
+ {
+ I = (Y>>2)+4*(X>>2);
+
+ armRetArgErrIf(pBS[Y] > 4, OMX_Sts_BadArgErr);
+
+ armRetArgErrIf((pBS[Y] == 4) && (Y > 3),
+ OMX_Sts_BadArgErr);
+
+ armRetArgErrIf(( (pBS[Y] == 4) && (pBS[Y^3] != 4) ),
+ OMX_Sts_BadArgErr);
+
+ armRetArgErrIf(pThresholds[Y] > 25, OMX_Sts_BadArgErr);
+
+ /* Filter vertical edge with q0 at (X,Y) */
+ armVCM4P10_DeBlockPixel(
+ pSrcDst + Y*srcdstStep + X,
+ 1,
+ pThresholds[I],
+ pAlpha[Internal],
+ pBeta[Internal],
+ pBS[I],
+ 0);
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_GetVLCInfo.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_GetVLCInfo.c
new file mode 100644
index 0000000..81c59d6
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_GetVLCInfo.c
@@ -0,0 +1,192 @@
+/**
+ *
+ * File Name: omxVCM4P10_GetVLCInfo.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ *
+ * This function extracts run-length encoding (RLE) information
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_GetVLCInfo (6.3.5.9.1)
+ *
+ * Description:
+ * This function extracts run-length encoding (RLE) information from the
+ * coefficient matrix. The results are returned in an OMXVCM4P10VLCInfo
+ * structure.
+ *
+ * Input Arguments:
+ *
+ * pSrcCoeff - pointer to the transform coefficient matrix. 8-byte
+ * alignment required.
+ * pScanMatrix - pointer to the scan order definition matrix. For a luma
+ * block the scan matrix should follow [ISO14496-10] section 8.5.4,
+ * and should contain the values 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13,
+ * 10, 7, 11, 14, 15. For a chroma block, the scan matrix should
+ * contain the values 0, 1, 2, 3.
+ * bAC - indicates presence of a DC coefficient; 0 = DC coefficient
+ * present, 1= DC coefficient absent.
+ * MaxNumCoef - specifies the number of coefficients contained in the
+ * transform coefficient matrix, pSrcCoeff. The value should be 16
+ * for blocks of type LUMADC, LUMAAC, LUMALEVEL, and CHROMAAC. The
+ * value should be 4 for blocks of type CHROMADC.
+ *
+ * Output Arguments:
+ *
+ * pDstVLCInfo - pointer to structure that stores information for
+ * run-length coding.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcCoeff, pScanMatrix, pDstVLCInfo
+ * - pSrcCoeff is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_GetVLCInfo (
+ const OMX_S16* pSrcCoeff,
+ const OMX_U8* pScanMatrix,
+ OMX_U8 bAC,
+ OMX_U32 MaxNumCoef,
+ OMXVCM4P10VLCInfo* pDstVLCInfo
+)
+{
+ OMX_INT i, MinIndex;
+ OMX_S32 Value;
+ OMX_U32 Mask = 4, RunBefore;
+ OMX_S16 *pLevel;
+ OMX_U8 *pRun;
+ OMX_S16 Buf [16];
+
+ /* check for argument error */
+ armRetArgErrIf(pSrcCoeff == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot8ByteAligned(pSrcCoeff), OMX_Sts_BadArgErr)
+ armRetArgErrIf(pScanMatrix == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstVLCInfo == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(bAC > 1, OMX_Sts_BadArgErr)
+ armRetArgErrIf(MaxNumCoef > 16, OMX_Sts_BadArgErr)
+
+ /* Initialize RLE Info structure */
+ pDstVLCInfo->uTrailing_Ones = 0;
+ pDstVLCInfo->uTrailing_One_Signs = 0;
+ pDstVLCInfo->uNumCoeffs = 0;
+ pDstVLCInfo->uTotalZeros = 0;
+
+ for (i = 0; i < 16; i++)
+ {
+ pDstVLCInfo->iLevels [i] = 0;
+ pDstVLCInfo->uRuns [i] = 0;
+ }
+
+ MinIndex = (bAC == 0 && MaxNumCoef == 15) ? 1 : 0;
+ for (i = MinIndex; i < (MaxNumCoef + MinIndex); i++)
+ {
+ /* Scan */
+ Buf [i - MinIndex] = pSrcCoeff [pScanMatrix [i]];
+ }
+
+ /* skip zeros at the end */
+ i = MaxNumCoef - 1;
+ while (!Buf [i] && i >= 0)
+ {
+ i--;
+ }
+
+ if (i < 0)
+ {
+ return OMX_Sts_NoErr;
+ }
+
+ /* Fill RLE Info structure */
+ pLevel = pDstVLCInfo->iLevels;
+ pRun = pDstVLCInfo->uRuns;
+ RunBefore = 0;
+
+ /* Handle first non zero separate */
+ pDstVLCInfo->uNumCoeffs++;
+ Value = Buf [i];
+ if (Value == 1 || Value == -1)
+ {
+ pDstVLCInfo->uTrailing_Ones++;
+
+ pDstVLCInfo->uTrailing_One_Signs |=
+ Value == -1 ? Mask : 0;
+ Mask >>= 1;
+ }
+ else
+ {
+ Value -= (Value > 0 ? 1 : -1);
+ *pLevel++ = Value;
+ Mask = 0;
+ }
+
+ /* Remaining non zero */
+ while (--i >= 0)
+ {
+ Value = Buf [i];
+ if (Value)
+ {
+ pDstVLCInfo->uNumCoeffs++;
+
+ /* Mask becomes zero after entering */
+ if (Mask &&
+ (Value == 1 ||
+ Value == -1))
+ {
+ pDstVLCInfo->uTrailing_Ones++;
+
+ pDstVLCInfo->uTrailing_One_Signs |=
+ Value == -1 ? Mask : 0;
+ Mask >>= 1;
+ *pRun++ = RunBefore;
+ RunBefore = 0;
+ }
+ else
+ {
+ /* If 3 trailing ones are not completed */
+ if (Mask)
+ {
+ Mask = 0;
+ Value -= (Value > 0 ? 1 : -1);
+ }
+ *pLevel++ = Value;
+ *pRun++ = RunBefore;
+ RunBefore = 0;
+ }
+ }
+ else
+ {
+ pDstVLCInfo->uTotalZeros++;
+ RunBefore++;
+ }
+ }
+
+ /* Update last run */
+ if (RunBefore)
+ {
+ *pRun++ = RunBefore;
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
new file mode 100644
index 0000000..8824de2
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateChroma.c
@@ -0,0 +1,99 @@
+/**
+ *
+ * File Name: omxVCM4P10_InterpolateChroma.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate 1/8 Pixel interpolation for Chroma Block
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+
+/**
+ * Function: omxVCM4P10_InterpolateChroma (6.3.3.2.2)
+ *
+ * Description:
+ * Performs 1/8-pixel interpolation for inter chroma MB.
+ *
+ * Input Arguments:
+ *
+ * pSrc -Pointer to the source reference frame buffer
+ * srcStep -Reference frame step in bytes
+ * dstStep -Destination frame step in bytes; must be a multiple of
+ * roi.width.
+ * dx -Fractional part of horizontal motion vector component in 1/8 pixel
+ * unit; valid in the range [0,7]
+ * dy -Fractional part of vertical motion vector component in 1/8 pixel
+ * unit; valid in the range [0,7]
+ * roi -Dimension of the interpolation region; the parameters roi.width and
+ * roi.height must be equal to either 2, 4, or 8.
+ *
+ * Output Arguments:
+ *
+ * pDst -Pointer to the destination frame buffer if roi.width==2, 2-byte
+ * alignment required if roi.width==4, 4-byte alignment required
+ * if roi.width==8, 8-byte alignment required
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pSrc or pDst is NULL.
+ * srcStep or dstStep < 8.
+ * dx or dy is out of range [0-7].
+ * roi.width or roi.height is out of range {2,4,8}.
+ * roi.width is equal to 2, but pDst is not 2-byte aligned.
+ * roi.width is equal to 4, but pDst is not 4-byte aligned.
+ * roi.width is equal to 8, but pDst is not 8 byte aligned.
+ * srcStep or dstStep is not a multiple of 8.
+ *
+ */
+
+OMXResult omxVCM4P10_InterpolateChroma (
+ const OMX_U8* pSrc,
+ OMX_S32 srcStep,
+ OMX_U8* pDst,
+ OMX_S32 dstStep,
+ OMX_S32 dx,
+ OMX_S32 dy,
+ OMXSize roi
+ )
+{
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(srcStep < 8, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dstStep < 8, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dx < 0, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dx > 7, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dy < 0, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dy > 7, OMX_Sts_BadArgErr)
+ armRetArgErrIf((roi.width != 2) && (roi.width != 4) && (roi.width != 8), OMX_Sts_BadArgErr)
+ armRetArgErrIf((roi.height != 2) && (roi.height != 4) && (roi.height != 8), OMX_Sts_BadArgErr)
+ armRetArgErrIf((roi.width == 2) && armNot2ByteAligned(pDst), OMX_Sts_BadArgErr)
+ armRetArgErrIf((roi.width == 4) && armNot4ByteAligned(pDst), OMX_Sts_BadArgErr)
+ armRetArgErrIf((roi.width == 8) && armNot8ByteAligned(pDst), OMX_Sts_BadArgErr)
+ armRetArgErrIf(srcStep & 7, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dstStep & 7, OMX_Sts_BadArgErr)
+
+ return armVCM4P10_Interpolate_Chroma
+ ((OMX_U8*)pSrc, srcStep, pDst, dstStep, roi.width, roi.height, dx, dy);
+}
+
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfHor_Luma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfHor_Luma.c
new file mode 100644
index 0000000..ef0befa
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfHor_Luma.c
@@ -0,0 +1,124 @@
+/**
+ *
+ * File Name: omxVCM4P10_InterpolateHalfHor_Luma.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate Half horizontal luma interpolation
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_InterpolateHalfHor_Luma (6.3.5.5.1)
+ *
+ * Description:
+ * This function performs interpolation for two horizontal 1/2-pel positions
+ * (-1/2,0) and (1/2, 0) - around a full-pel position.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the top-left corner of the block used to interpolate in
+ * the reconstruction frame plane.
+ * iSrcStep - Step of the source buffer.
+ * iDstStep - Step of the destination(interpolation) buffer; must be a
+ * multiple of iWidth.
+ * iWidth - Width of the current block; must be equal to either 4, 8, or 16
+ * iHeight - Height of the current block; must be equal to 4, 8, or 16
+ *
+ * Output Arguments:
+ *
+ * pDstLeft -Pointer to the interpolation buffer of the left -pel position
+ * (-1/2, 0)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ * pDstRight -Pointer to the interpolation buffer of the right -pel
+ * position (1/2, 0)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrc, pDstLeft, or pDstRight
+ * - iWidth or iHeight have values other than 4, 8, or 16
+ * - iWidth==4 but pDstLeft and/or pDstRight is/are not aligned on a 4-byte boundary
+ * - iWidth==8 but pDstLeft and/or pDstRight is/are not aligned on a 8-byte boundary
+ * - iWidth==16 but pDstLeft and/or pDstRight is/are not aligned on a 16-byte boundary
+ * - any alignment restrictions are violated
+ *
+ */
+
+OMXResult omxVCM4P10_InterpolateHalfHor_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDstLeft,
+ OMX_U8* pDstRight,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+)
+{
+ OMXResult RetValue;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstLeft == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstRight == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf((iWidth == 4) &&
+ armNot4ByteAligned(pDstLeft) &&
+ armNot4ByteAligned(pDstRight), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iWidth == 8) &&
+ armNot8ByteAligned(pDstLeft) &&
+ armNot8ByteAligned(pDstRight), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iWidth == 16) &&
+ armNot16ByteAligned(pDstLeft) &&
+ armNot16ByteAligned(pDstRight), OMX_Sts_BadArgErr)
+
+ armRetArgErrIf((iHeight != 16) && (iHeight != 8)&& (iHeight != 4), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iWidth != 16) && (iWidth != 8)&& (iWidth != 4), OMX_Sts_BadArgErr)
+
+ RetValue = armVCM4P10_InterpolateHalfHor_Luma (
+ pSrc - 1,
+ iSrcStep,
+ pDstLeft,
+ iDstStep,
+ iWidth,
+ iHeight);
+
+ if (RetValue != OMX_Sts_NoErr)
+ {
+ return RetValue;
+ }
+
+ RetValue = armVCM4P10_InterpolateHalfHor_Luma (
+ pSrc,
+ iSrcStep,
+ pDstRight,
+ iDstStep,
+ iWidth,
+ iHeight);
+
+ return RetValue;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfVer_Luma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfVer_Luma.c
new file mode 100644
index 0000000..3560ff8
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateHalfVer_Luma.c
@@ -0,0 +1,123 @@
+/**
+ *
+ * File Name: omxVCM4P10_InterpolateHalfVer_Luma.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate SAD for 4x4 blocks
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+
+/**
+ * Function: omxVCM4P10_InterpolateHalfVer_Luma (6.3.5.5.2)
+ *
+ * Description:
+ * This function performs interpolation for two vertical 1/2-pel positions -
+ * (0, -1/2) and (0, 1/2) - around a full-pel position.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to top-left corner of block used to interpolate in the
+ * reconstructed frame plane
+ * iSrcStep - Step of the source buffer.
+ * iDstStep - Step of the destination (interpolation) buffer; must be a
+ * multiple of iWidth.
+ * iWidth - Width of the current block; must be equal to either 4, 8, or 16
+ * iHeight - Height of the current block; must be equal to either 4, 8, or 16
+ *
+ * Output Arguments:
+ *
+ * pDstUp -Pointer to the interpolation buffer of the -pel position above
+ * the current full-pel position (0, -1/2)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ * pDstDown -Pointer to the interpolation buffer of the -pel position below
+ * the current full-pel position (0, 1/2)
+ * If iWidth==4, 4-byte alignment required.
+ * If iWidth==8, 8-byte alignment required.
+ * If iWidth==16, 16-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrc, pDstUp, or pDstDown
+ * - iWidth or iHeight have values other than 4, 8, or 16
+ * - iWidth==4 but pDstUp and/or pDstDown is/are not aligned on a 4-byte boundary
+ * - iWidth==8 but pDstUp and/or pDstDown is/are not aligned on a 8-byte boundary
+ * - iWidth==16 but pDstUp and/or pDstDown is/are not aligned on a 16-byte boundary
+ *
+ */
+ OMXResult omxVCM4P10_InterpolateHalfVer_Luma(
+ const OMX_U8* pSrc,
+ OMX_U32 iSrcStep,
+ OMX_U8* pDstUp,
+ OMX_U8* pDstDown,
+ OMX_U32 iDstStep,
+ OMX_U32 iWidth,
+ OMX_U32 iHeight
+)
+{
+ OMXResult RetValue;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstUp == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstDown == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf((iWidth == 4) &&
+ armNot4ByteAligned(pDstUp) &&
+ armNot4ByteAligned(pDstDown), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iWidth == 8) &&
+ armNot8ByteAligned(pDstUp) &&
+ armNot8ByteAligned(pDstDown), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iWidth == 16) &&
+ armNot16ByteAligned(pDstUp) &&
+ armNot16ByteAligned(pDstDown), OMX_Sts_BadArgErr)
+
+ armRetArgErrIf((iHeight != 16) && (iHeight != 8)&& (iHeight != 4), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iWidth != 16) && (iWidth != 8)&& (iWidth != 4), OMX_Sts_BadArgErr)
+
+ RetValue = armVCM4P10_InterpolateHalfVer_Luma(
+ pSrc - iSrcStep,
+ iSrcStep,
+ pDstUp,
+ iDstStep,
+ iWidth,
+ iHeight);
+
+ if (RetValue != OMX_Sts_NoErr)
+ {
+ return RetValue;
+ }
+
+ RetValue = armVCM4P10_InterpolateHalfVer_Luma(
+ pSrc,
+ iSrcStep,
+ pDstDown,
+ iDstStep,
+ iWidth,
+ iHeight);
+
+ return RetValue;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateLuma.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateLuma.c
new file mode 100644
index 0000000..d233735
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InterpolateLuma.c
@@ -0,0 +1,99 @@
+/**
+ *
+ * File Name: omxVCM4P10_InterpolateLuma.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate Performs quarter-pixel interpolation
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P10_InterpolateLuma (6.3.3.2.1)
+ *
+ * Description:
+ * Performs quarter-pixel interpolation for inter luma MB. It is assumed that
+ * the frame is already padded when calling this function.
+ *
+ * Input Arguments:
+ *
+ * pSrc -Pointer to the source reference frame buffer
+ * srcStep -reference frame step, in bytes; must be a multiple of roi.width
+ * dstStep -destination frame step, in bytes; must be a multiple of
+ * roi.width
+ * dx -Fractional part of horizontal motion vector component in 1/4 pixel
+ * unit; valid in the range [0,3]
+ * dy -Fractional part of vertical motion vector y component in 1/4 pixel
+ * unit; valid in the range [0,3]
+ * roi -Dimension of the interpolation region; the parameters roi.width and
+ * roi.height must be equal to either 4, 8, or 16.
+ *
+ * Output Arguments:
+ *
+ * pDst -Pointer to the destination frame buffer if roi.width==4, 4-byte
+ * alignment required if roi.width==8, 8-byte alignment required
+ * if roi.width==16, 16-byte alignment required
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pSrc or pDst is NULL.
+ * srcStep or dstStep < roi.width.
+ * dx or dy is out of range [0,3].
+ * roi.width or roi.height is out of range {4, 8, 16}.
+ * roi.width is equal to 4, but pDst is not 4 byte aligned.
+ * roi.width is equal to 8 or 16, but pDst is not 8 byte aligned.
+ * srcStep or dstStep is not a multiple of 8.
+ *
+ */
+
+OMXResult omxVCM4P10_InterpolateLuma (
+ const OMX_U8* pSrc,
+ OMX_S32 srcStep,
+ OMX_U8* pDst,
+ OMX_S32 dstStep,
+ OMX_S32 dx,
+ OMX_S32 dy,
+ OMXSize roi
+ )
+{
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(srcStep < roi.width, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dstStep < roi.width, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dx < 0, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dx > 3, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dy < 0, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dy > 3, OMX_Sts_BadArgErr)
+ armRetArgErrIf((roi.width != 4) && (roi.width != 8) && (roi.width != 16), OMX_Sts_BadArgErr)
+ armRetArgErrIf((roi.height != 4) && (roi.height != 8) && (roi.height != 16), OMX_Sts_BadArgErr)
+ armRetArgErrIf((roi.width == 4) && armNot4ByteAligned(pDst), OMX_Sts_BadArgErr)
+ armRetArgErrIf((roi.width == 8) && armNot8ByteAligned(pDst), OMX_Sts_BadArgErr)
+ armRetArgErrIf((roi.width == 16) && armNot16ByteAligned(pDst), OMX_Sts_BadArgErr)
+ armRetArgErrIf(srcStep & 7, OMX_Sts_BadArgErr)
+ armRetArgErrIf(dstStep & 7, OMX_Sts_BadArgErr)
+
+ return armVCM4P10_Interpolate_Luma
+ (pSrc, srcStep, pDst, dstStep, roi.width, roi.height, dx, dy);
+
+}
+
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_ChromaDC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_ChromaDC.c
new file mode 100644
index 0000000..92ba031
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_ChromaDC.c
@@ -0,0 +1,102 @@
+/**
+ *
+ * File Name: omxVCM4P10_InvTransformDequant_ChromaDC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate 4x4 hadamard transform of chroma DC
+ * coefficients and quantization
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P10_InvTransformDequant_ChromaDC (6.3.5.6.4)
+ *
+ * Description:
+ * This function performs inverse 2x2 Hadamard transform and then dequantizes
+ * the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the 2x2 array of the 2x2 Hadamard-transformed and
+ * quantized coefficients. 8 byte alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to inverse-transformed and dequantized coefficients.
+ * 8-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL: pSrc
+ * - pSrc or pDst is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InvTransformDequant_ChromaDC(
+ const OMX_S16* pSrc,
+ OMX_S16* pDst,
+ OMX_U32 iQP
+)
+{
+ OMX_INT i, j;
+ OMX_S32 m[2][2];
+ OMX_S32 QPer, V00, Value;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot8ByteAligned(pSrc), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot8ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(iQP > 51, OMX_Sts_BadArgErr)
+
+ /* Inv Hadamard Transform for 2x2 block */
+ m[0][0] = pSrc[0] + pSrc[1] + pSrc[2] + pSrc[3];
+ m[0][1] = pSrc[0] - pSrc[1] + pSrc[2] - pSrc[3];
+ m[1][0] = pSrc[0] + pSrc[1] - pSrc[2] - pSrc[3];
+ m[1][1] = pSrc[0] - pSrc[1] - pSrc[2] + pSrc[3];
+
+ /* Quantization */
+ /* Scaling */
+ QPer = iQP / 6;
+ V00 = armVCM4P10_VMatrix [iQP % 6][0];
+
+ for (j = 0; j < 2; j++)
+ {
+ for (i = 0; i < 2; i++)
+ {
+ if (QPer < 1)
+ {
+ Value = (m[j][i] * V00) >> 1;
+ }
+ else
+ {
+ Value = (m[j][i] * V00) << (QPer - 1);
+ }
+
+ pDst[j * 2 + i] = (OMX_S16) Value;
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_LumaDC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_LumaDC.c
new file mode 100644
index 0000000..a3b1200
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformDequant_LumaDC.c
@@ -0,0 +1,128 @@
+/**
+ *
+ * File Name: omxVCM4P10_InvTransformDequant_LumaDC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate 4x4 hadamard transform of luma DC coefficients
+ * and quantization
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_InvTransformDequant_LumaDC (6.3.5.6.3)
+ *
+ * Description:
+ * This function performs inverse 4x4 Hadamard transform and then dequantizes
+ * the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the 4x4 array of the 4x4 Hadamard-transformed and
+ * quantized coefficients. 16 byte alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to inverse-transformed and dequantized coefficients.
+ * 16-byte alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL: pSrc
+ * - pSrc or pDst is not aligned on a 16-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InvTransformDequant_LumaDC(
+ const OMX_S16* pSrc,
+ OMX_S16* pDst,
+ OMX_U32 iQP
+)
+{
+ OMX_INT i, j;
+ OMX_S32 m1[4][4], m2[4][4], Value;
+ OMX_S32 QPer, V;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iQP > 51, OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot16ByteAligned(pSrc), OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot16ByteAligned(pDst), OMX_Sts_BadArgErr)
+
+ /* Inv Hadamard Transform for DC Luma 4x4 block */
+ /* Horizontal */
+ for (i = 0; i < 4; i++)
+ {
+ j = i * 4;
+
+ m1[i][0] = pSrc[j + 0] + pSrc[j + 2]; /* a+c */
+ m1[i][1] = pSrc[j + 1] + pSrc[j + 3]; /* b+d */
+ m1[i][2] = pSrc[j + 0] - pSrc[j + 2]; /* a-c */
+ m1[i][3] = pSrc[j + 1] - pSrc[j + 3]; /* b-d */
+
+ m2[i][0] = m1[i][0] + m1[i][1]; /* a+b+c+d */
+ m2[i][1] = m1[i][2] + m1[i][3]; /* a+b-c-d */
+ m2[i][2] = m1[i][2] - m1[i][3]; /* a-b-c+d */
+ m2[i][3] = m1[i][0] - m1[i][1]; /* a-b+c-d */
+
+ }
+
+ /* Vertical */
+ for (i = 0; i < 4; i++)
+ {
+ m1[0][i] = m2[0][i] + m2[2][i];
+ m1[1][i] = m2[1][i] + m2[3][i];
+ m1[2][i] = m2[0][i] - m2[2][i];
+ m1[3][i] = m2[1][i] - m2[3][i];
+
+ m2[0][i] = m1[0][i] + m1[1][i];
+ m2[1][i] = m1[2][i] + m1[3][i];
+ m2[2][i] = m1[2][i] - m1[3][i];
+ m2[3][i] = m1[0][i] - m1[1][i];
+ }
+
+
+ /* Scaling */
+ QPer = iQP / 6;
+ V = armVCM4P10_VMatrix [iQP % 6][0];
+
+ for (j = 0; j < 4; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ if (QPer < 2)
+ {
+ Value = (m2[j][i] * V + (1 << (1 - QPer))) >> (2 - QPer);
+ }
+ else
+ {
+ Value = m2[j][i] * V * (1 << (QPer - 2));
+ }
+
+ pDst[j * 4 + i] = (OMX_S16) Value;
+
+ }
+ }
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformResidualAndAdd.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformResidualAndAdd.c
new file mode 100644
index 0000000..3303997
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_InvTransformResidualAndAdd.c
@@ -0,0 +1,124 @@
+/**
+ *
+ * File Name: omxVCM4P10_InvTransformResidualAndAdd.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will inverse integer 4x4 transform
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_InvTransformResidualAndAdd (6.3.5.7.1)
+ *
+ * Description:
+ * This function performs inverse an 4x4 integer transformation to produce
+ * the difference signal and then adds the difference to the prediction to get
+ * the reconstructed signal.
+ *
+ * Input Arguments:
+ *
+ * pSrcPred - Pointer to prediction signal. 4-byte alignment required.
+ * pDequantCoeff - Pointer to the transformed coefficients. 8-byte
+ * alignment required.
+ * iSrcPredStep - Step of the prediction buffer; must be a multiple of 4.
+ * iDstReconStep - Step of the destination reconstruction buffer; must be a
+ * multiple of 4.
+ * bAC - Indicate whether there is AC coefficients in the coefficients
+ * matrix.
+ *
+ * Output Arguments:
+ *
+ * pDstRecon -Pointer to the destination reconstruction buffer. 4-byte
+ * alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcPred, pDequantCoeff, pDstRecon
+ * - pSrcPred is not aligned on a 4-byte boundary
+ * - iSrcPredStep or iDstReconStep is not a multiple of 4.
+ * - pDequantCoeff is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_InvTransformResidualAndAdd(
+ const OMX_U8* pSrcPred,
+ const OMX_S16* pDequantCoeff,
+ OMX_U8* pDstRecon,
+ OMX_U32 iSrcPredStep,
+ OMX_U32 iDstReconStep,
+ OMX_U8 bAC
+)
+{
+ OMX_INT i, j;
+ OMX_S16 In[16], Out[16];
+ OMX_S32 Value;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrcPred == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot4ByteAligned(pSrcPred), OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDequantCoeff == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot8ByteAligned(pDequantCoeff), OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstRecon == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot4ByteAligned(pDstRecon), OMX_Sts_BadArgErr)
+ armRetArgErrIf(bAC > 1, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iSrcPredStep == 0 || iSrcPredStep & 3, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iDstReconStep == 0 || iDstReconStep & 3, OMX_Sts_BadArgErr)
+
+ if (bAC)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ In[i] = pDequantCoeff [i];
+ }
+ }
+ else
+ {
+ /* Copy DC */
+ In[0] = pDequantCoeff [0];
+
+ for (i = 1; i < 16; i++)
+ {
+ In[i] = 0;
+ }
+ }
+
+ /* Residual Transform */
+ armVCM4P10_TransformResidual4x4 (Out, In);
+
+ for (j = 0; j < 4; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ /* Add predition */
+ Value = (OMX_S32) Out [j * 4 + i] + pSrcPred [j * iSrcPredStep + i];
+
+ /* Saturate Value to OMX_U8 */
+ Value = armClip (0, 255, Value);
+
+ pDstRecon[j * iDstReconStep + i] = (OMX_U8) Value;
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEGetBufSize.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEGetBufSize.c
new file mode 100644
index 0000000..8c3a5c3
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEGetBufSize.c
@@ -0,0 +1,70 @@
+/**
+ *
+ * File Name: omxVCM4P10_MEGetBufSize.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Initialization modules for the vendor specific Motion Estimation structure.
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P10_MEGetBufSize (6.3.5.1.1)
+ *
+ * Description:
+ * Computes the size, in bytes, of the vendor-specific specification
+ * structure for the omxVCM4P10 motion estimation functions BlockMatch_Integer
+ * and MotionEstimationMB.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P10MEMode
+ * pMEParams -motion estimation parameters
+ *
+ * Output Arguments:
+ *
+ * pSize - pointer to the number of bytes required for the motion
+ * estimation specification structure
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - pMEParams or pSize is NULL.
+ * - an invalid MEMode is specified.
+ *
+ */
+
+OMXResult omxVCM4P10_MEGetBufSize(
+ OMXVCM4P10MEMode MEMode,
+ const OMXVCM4P10MEParams *pMEParams,
+ OMX_U32 *pSize
+ )
+{
+ armRetArgErrIf(!pMEParams, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!pSize, OMX_Sts_BadArgErr);
+ armRetArgErrIf((MEMode != OMX_VC_M4P10_FAST_SEARCH) &&
+ (MEMode != OMX_VC_M4P10_FULL_SEARCH), OMX_Sts_BadArgErr);
+ armRetArgErrIf((pMEParams->searchRange16x16 <= 0) ||
+ (pMEParams->searchRange8x8 <= 0) ||
+ (pMEParams->searchRange4x4 <= 0), OMX_Sts_BadArgErr);
+
+ *pSize = (OMX_INT) sizeof(ARMVCM4P10_MESpec);
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEInit.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEInit.c
new file mode 100644
index 0000000..58ecc88
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MEInit.c
@@ -0,0 +1,92 @@
+/**
+ *
+ * File Name: omxVCM4P10_MEInit.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Initialization modules for the vendor specific Motion Estimation structure.
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P10_MEInit (6.3.5.1.2)
+ *
+ * Description:
+ * Initializes the vendor-specific specification structure required for the
+ * omxVCM4P10 motion estimation functions: BlockMatch_Integer and
+ * MotionEstimationMB. Memory for the specification structure *pMESpec must be
+ * allocated prior to calling the function, and should be aligned on a 4-byte
+ * boundary. The number of bytes required for the specification structure can
+ * be determined using the function omxVCM4P10_MEGetBufSize. Following
+ * initialization by this function, the vendor-specific structure *pMESpec
+ * should contain an implementation-specific representation of all motion
+ * estimation parameters received via the structure pMEParams, for example
+ * searchRange16x16, searchRange8x8, etc.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P10MEMode
+ * pMEParams - motion estimation parameters
+ * pMESpec - pointer to the uninitialized ME specification structure
+ *
+ * Output Arguments:
+ *
+ * pMESpec - pointer to the initialized ME specification structure
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - pMEParams or pSize is NULL.
+ * - an invalid value was specified for the parameter MEmode
+ * - a negative or zero value was specified for one of the search ranges
+ * (e.g., pMBParams >searchRange8x8, pMEParams->searchRange16x16, etc.)
+ * - either in isolation or in combination, one or more of the enables or
+ * search ranges in the structure *pMEParams were configured such
+ * that the requested behavior fails to comply with [ISO14496-10].
+ *
+ */
+
+OMXResult omxVCM4P10_MEInit(
+ OMXVCM4P10MEMode MEMode,
+ const OMXVCM4P10MEParams *pMEParams,
+ void *pMESpec
+ )
+{
+ ARMVCM4P10_MESpec *armMESpec = (ARMVCM4P10_MESpec *) pMESpec;
+
+ armRetArgErrIf(!pMEParams, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!pMESpec, OMX_Sts_BadArgErr);
+ armRetArgErrIf((MEMode != OMX_VC_M4P10_FAST_SEARCH) &&
+ (MEMode != OMX_VC_M4P10_FULL_SEARCH), OMX_Sts_BadArgErr);
+ armRetArgErrIf((pMEParams->searchRange16x16 <= 0) ||
+ (pMEParams->searchRange8x8 <= 0) ||
+ (pMEParams->searchRange4x4 <= 0), OMX_Sts_BadArgErr);
+
+ armMESpec->MEParams.blockSplitEnable8x8 = pMEParams->blockSplitEnable8x8;
+ armMESpec->MEParams.blockSplitEnable4x4 = pMEParams->blockSplitEnable4x4;
+ armMESpec->MEParams.halfSearchEnable = pMEParams->halfSearchEnable;
+ armMESpec->MEParams.quarterSearchEnable = pMEParams->quarterSearchEnable;
+ armMESpec->MEParams.intraEnable4x4 = pMEParams->intraEnable4x4;
+ armMESpec->MEParams.searchRange16x16 = pMEParams->searchRange16x16;
+ armMESpec->MEParams.searchRange8x8 = pMEParams->searchRange8x8;
+ armMESpec->MEParams.searchRange4x4 = pMEParams->searchRange4x4;
+ armMESpec->MEMode = MEMode;
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c
new file mode 100644
index 0000000..33dbf3f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_MotionEstimationMB.c
@@ -0,0 +1,1892 @@
+/** x
+ *
+ * File Name: omxVCM4P10_MotionEstimationMB.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function perform MB level motion estimation
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+#define ARM_VCM4P10_MAX_FRAMES (15)
+#define ARM_VCM4P10_MAX_4x4_SAD (0xffff)
+#define ARM_VCM4P10_MAX_MODE_VALUE (0xffffffff)
+#define ARM_VCM4P10_MAX_MODES (16)
+#define ARM_VCM4P10_MB_BLOCK_SIZE (16)
+#define ARM_VCM4P10_MEDIAN(a,b,c) (a>b?a>c?b>c?b:c:a:b>c?a>c?a:c:b)
+#define ARM_VCM4P10_SHIFT_QP (12)
+
+#define ARM_VCM4P10_MVPRED_MEDIAN (0)
+#define ARM_VCM4P10_MVPRED_L (1)
+#define ARM_VCM4P10_MVPRED_U (2)
+#define ARM_VCM4P10_MVPRED_UR (3)
+
+#define ARM_VCM4P10_MB_BLOCK_SIZE (16)
+#define ARM_VCM4P10_BLOCK_SIZE (4)
+#define ARM_VCM4P10_MAX_COST (1 << 30)
+#define ARM_VCM4P10_INVALID_BLOCK (-2)
+
+
+/**
+ * Function: armVCM4P10_CalculateBlockSAD
+ *
+ * Description:
+ * Calculate SAD value for the selected MB encoding mode and update
+ * pDstBlockSAD parameter. These SAD values are calculated 4x4 blocks at
+ * a time and in the scan order.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcMBInfo -
+ * [in] pSrcCurrBuf -
+ * [in] SrcCurrStep -
+ * [in] pSrcRefBufList-
+ * [in] SrcRefStep -
+ * [in] pSrcRecBuf -
+ * [in] SrcRecStep -
+ * [in] pRefRect -
+ * [in] pCurrPointPos -
+ * [in] Lambda -
+ * [in] pMESpec -
+ * [in] pMBInter -
+ * [in] pMBIntra -
+ * [out] pDstBlockSAD - pointer to 16 element array for SAD corresponding to 4x4 blocks
+ * Return Value:
+ * None
+ *
+ */
+
+static OMXResult armVCM4P10_CalculateBlockSAD(
+ OMXVCM4P10MBInfo *pSrcMBInfo,
+ const OMX_U8 *pSrcCurrBuf,
+ OMX_S32 SrcCurrStep,
+ const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES],
+ OMX_S32 SrcRefStep,
+ const OMX_U8 *pSrcRecBuf,
+ OMX_S32 SrcRecStep,
+ const OMXRect *pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCM4P10MBInfoPtr *pMBInter,
+ const OMXVCM4P10MBInfoPtr *pMBIntra,
+ OMX_U16 *pDstBlockSAD)
+{
+ OMX_INT InvalidSAD = 0;
+ OMX_INT i;
+
+ OMX_U8 Buffer [16*16 + 15];
+ OMX_U8 *pTempDstBuf;
+ OMX_S32 TempDstStep;
+ OMX_U8 *pTempRefBuf;
+ OMX_S32 TempRefStep;
+
+ /* Temporary buffer to store the predicted mb coefficients */
+ pTempDstBuf = armAlignTo16Bytes(Buffer);
+ TempDstStep = 16;
+
+ /* Update pDstBlockSAD if MB is a valid type */
+ if (pSrcMBInfo)
+ {
+ OMX_U32 Width=0, Height=0, MaxXPart, MaxYPart,MaxSubXPart,MaxSubYPart;
+
+ /* Depending on type of MB, do prediction and fill temp buffer */
+ switch (pSrcMBInfo->mbType)
+ {
+ case OMX_VC_P_16x16:
+ Width = 16;
+ Height = 16;
+ break;
+ case OMX_VC_P_16x8:
+ Width = 16;
+ Height = 8;
+ break;
+ case OMX_VC_P_8x16:
+ Width = 8;
+ Height = 16;
+ break;
+ case OMX_VC_P_8x8:
+ Width = 8;
+ Height = 8;
+ break;
+ case OMX_VC_INTRA_4x4:
+ {
+ /* Create predicted MB Intra4x4 mode */
+ OMX_S32 PredIntra4x4Mode [5][9];
+ OMX_S32 x, y, Block8x8, Block4x4, BlockX, BlockY;
+ OMX_U8 pSrcYBuff [(16*3)*(16*2)];
+ OMX_U8 *pSrcY;
+ OMX_S32 StepSrcY;
+ OMX_S32 availability;
+
+ for (y = 0; y < 5; y++)
+ {
+ for (x = 0; x < 9; x++)
+ {
+ /*
+ * Initialize with value of ARM_VCM4P10_INVALID_BLOCK, to mean this
+ * 4x4 block is not available
+ */
+ PredIntra4x4Mode [y][x] = ARM_VCM4P10_INVALID_BLOCK;
+ }
+ }
+
+ /* Replace ARM_VCM4P10_INVALID_BLOCK value with available MBs values*/
+ for (x = 0; x < 4; x++)
+ {
+ /* Store values of b0, b1, b2, b3 */
+ if (pMBIntra[1] != NULL)
+ {
+ PredIntra4x4Mode [0][x + 1] =
+ pMBIntra[1]->pIntra4x4PredMode[3*4 + x];
+ }
+
+ /* Store values of d0, d1, d2, d3 */
+ if (pMBIntra[3] != NULL)
+ {
+ PredIntra4x4Mode [0][x + 5] =
+ pMBIntra[3]->pIntra4x4PredMode[3*4 + x];
+ }
+ }
+
+ /* Store values of c3 */
+ if (pMBIntra[2] != NULL)
+ {
+ PredIntra4x4Mode [0][0] = pMBIntra[2]->pIntra4x4PredMode[15];
+ }
+
+ for (y = 0; y < 4; y++)
+ {
+ /* Store values of a0, a1, a2, a3 */
+ if (pMBIntra[0] != NULL)
+ {
+ PredIntra4x4Mode [y + 1][0] =
+ pMBIntra[0]->pIntra4x4PredMode[y*4 + 3];
+ }
+ }
+
+ /*
+ * Update neighbouring Pred mode array which will be used for
+ * prediction of Intra4x4 modes.
+ */
+
+ pSrcY = pSrcYBuff;
+ StepSrcY = 16 * 3;
+ for (y = 0; y < (16 * 2); y++)
+ {
+ for (x = 0; x < (16 * 3); x++)
+ {
+ pSrcY [StepSrcY * y + x] =
+ pSrcRecBuf [SrcRecStep * (y - 16) + x - 16];
+ }
+ }
+
+
+ /* for each 8x8 block */
+ for (Block8x8 = 0; Block8x8 < 4; Block8x8++)
+ {
+ /* for each 4x4 block inside 8x8 block */
+ for (Block4x4 = 0; Block4x4 < 4; Block4x4++)
+ {
+ /* Get block cordinates from 8x8 block index and 4x4 block index */
+ BlockX = ((Block8x8 & 1) << 1) + (Block4x4 & 1);
+ BlockY = ((Block8x8 >> 1) << 1) + (Block4x4 >> 1);
+
+ /* Add offset to point to start of current MB in the array pIntra4x4PredMode */
+ x = BlockX + 1;
+ y = BlockY + 1;
+
+ availability = 0;
+
+ /* Check for availability of LEFT Block */
+ if (PredIntra4x4Mode [y][x - 1] != ARM_VCM4P10_INVALID_BLOCK)
+ {
+ availability |= OMX_VC_LEFT;
+ }
+
+ /* Check for availability of UPPER Block */
+ if (PredIntra4x4Mode [y - 1][x] != ARM_VCM4P10_INVALID_BLOCK)
+ {
+ availability |= OMX_VC_UPPER;
+ }
+
+ /* Check for availability of UPPER LEFT Block */
+ if (PredIntra4x4Mode [y - 1][x - 1] != ARM_VCM4P10_INVALID_BLOCK)
+ {
+ availability |= OMX_VC_UPPER_LEFT;
+ }
+
+ PredIntra4x4Mode [y][x] = pSrcMBInfo->pIntra4x4PredMode[BlockY*4+BlockX];
+ x = BlockX * 4;
+ y = BlockY * 4;
+
+ pSrcY = pSrcYBuff + 16 * StepSrcY + 16 + y * StepSrcY + x;
+
+ omxVCM4P10_PredictIntra_4x4(
+ pSrcY - 1,
+ pSrcY - StepSrcY,
+ pSrcY - StepSrcY - 1,
+ pTempDstBuf + x + y * TempDstStep,
+ StepSrcY,
+ TempDstStep,
+ pSrcMBInfo->pIntra4x4PredMode[BlockY*4+BlockX],
+ availability);
+
+ for (BlockY=0;BlockY<4;BlockY++)
+ {
+ for(BlockX=0;BlockX<4;BlockX++)
+ {
+ pSrcY [BlockY * StepSrcY + BlockX] =
+ (OMX_U8)(*(pTempDstBuf + x + y * TempDstStep + BlockY * TempDstStep + BlockX));
+ }
+ }
+
+ }
+ }
+ break;
+ }
+ case OMX_VC_INTRA_16x16:
+ {
+ OMX_U32 MBPosX = pCurrPointPos->x >> 4;
+ OMX_U32 MBPosY = pCurrPointPos->y >> 4;
+ OMX_U32 availability = 0;
+
+ /* Check for availability of LEFT MB */
+ if ((MBPosX != 0) && (pMBIntra [0] != 0 || pMBInter [0] != 0))
+ {
+ availability |= OMX_VC_LEFT;
+ }
+
+ /* Check for availability of UP MB */
+ if ((MBPosY != 0) && (pMBIntra [1] != 0 || pMBInter [1] != 0))
+ {
+ availability |= OMX_VC_UPPER;
+ }
+
+ /* Check for availability of UP-LEFT MB */
+ if ((MBPosX > 0) && (MBPosY > 0) &&
+ (pMBIntra [2] != 0 || pMBInter [2] != 0))
+ {
+ availability |= OMX_VC_UPPER_LEFT;
+ }
+
+ omxVCM4P10_PredictIntra_16x16(
+ pSrcRecBuf - 1,
+ pSrcRecBuf - SrcRecStep,
+ pSrcRecBuf - SrcRecStep - 1,
+ pTempDstBuf,
+ SrcRecStep,
+ TempDstStep,
+ pSrcMBInfo->Intra16x16PredMode,
+ availability);
+
+ break;
+ }
+
+ case OMX_VC_INTER_SKIP:
+ case OMX_VC_PREF0_8x8:
+ case OMX_VC_INTRA_PCM:
+ default:
+ /* These cases will update pDstBlockSAD with MAX value */
+ InvalidSAD = 1;
+ break;
+ }
+
+ /* INTER MB */
+ if ((pSrcMBInfo->mbType == OMX_VC_P_16x16) ||
+ (pSrcMBInfo->mbType == OMX_VC_P_8x16) ||
+ (pSrcMBInfo->mbType == OMX_VC_P_16x8) ||
+ (pSrcMBInfo->mbType == OMX_VC_P_8x8))
+ {
+ const OMX_U8 *pTempSrcBuf;
+ OMX_S32 TempSrcStep;
+ OMX_S32 mvx,mvy;
+ OMX_U32 PartX, PartY, SubPartX, SubPartY;
+
+ TempSrcStep = SrcRefStep;
+
+ MaxXPart = 16/Width;
+ MaxYPart = 16/Height;
+
+
+ for (PartY = 0; PartY < MaxYPart; PartY++)
+ {
+ for (PartX = 0; PartX < MaxXPart; PartX++)
+ {
+
+ pTempSrcBuf = pSrcRefBufList[pSrcMBInfo->pRefL0Idx[PartY * 2 + PartX]];
+
+ if (MaxXPart == 2 && MaxYPart == 2)
+ {
+ switch (pSrcMBInfo->subMBType[PartY*2+PartX])
+ {
+ case OMX_VC_SUB_P_8x8:
+ Width = 8;
+ Height = 8;
+ break;
+ case OMX_VC_SUB_P_8x4:
+ Width = 8;
+ Height = 4;
+ break;
+ case OMX_VC_SUB_P_4x8:
+ Width = 4;
+ Height = 8;
+ break;
+ case OMX_VC_SUB_P_4x4:
+ Width = 4;
+ Height = 4;
+ break;
+ default:
+ /* Default */
+ Width = 4;
+ Height = 4;
+ break;
+ }
+
+ MaxSubXPart = 8/Width;
+ MaxSubYPart = 8/Height;
+
+ for (SubPartY = 0; SubPartY < MaxSubYPart; SubPartY++)
+ {
+ for (SubPartX = 0; SubPartX < MaxSubXPart; SubPartX++)
+ {
+ mvx = pSrcMBInfo->pMV0 [2*PartY + SubPartY][2*PartX + SubPartX].dx;
+ mvy = pSrcMBInfo->pMV0 [2*PartY + SubPartY][2*PartX + SubPartX].dy;
+ armVCM4P10_Interpolate_Luma(
+ pTempSrcBuf + (8*PartX + 4*SubPartX + (mvx/4)) + (8*PartY + 4*SubPartY + (mvy/4)) * TempSrcStep,
+ TempSrcStep,
+ pTempDstBuf + (8*PartX + 4*SubPartX) + (8*PartY + 4*SubPartY) * TempDstStep,
+ TempDstStep,
+ Width,
+ Height,
+ mvx & 3,
+ mvy & 3
+ );
+ }
+ }
+ }
+ else
+ {
+
+ mvx = pSrcMBInfo->pMV0 [2*PartY][2*PartX].dx;
+ mvy = pSrcMBInfo->pMV0 [2*PartY][2*PartX].dy;
+ armVCM4P10_Interpolate_Luma(
+ pTempSrcBuf + (8*PartX + (mvx/4)) + (8*PartY + (mvy/4)) * TempSrcStep,
+ TempSrcStep,
+ pTempDstBuf + (8*PartX) + (8*PartY) * TempDstStep,
+ TempDstStep,
+ Width,
+ Height,
+ mvx & 3,
+ mvy & 3
+ );
+
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ InvalidSAD = 1;
+ }
+
+ /* Calculate SAD from predicted buffer */
+ if (!InvalidSAD)
+ {
+ OMX_U32 x8x8, y8x8, x4x4, y4x4, Block8x8, Block4x4;
+ OMX_S32 SAD;
+
+ pTempRefBuf = pTempDstBuf;
+ TempRefStep = 16;
+
+ /* SAD for each 4x4 block in scan order */
+ for (Block8x8 = 0; Block8x8 < 4; Block8x8++)
+ {
+ x8x8 = 8*(Block8x8 & 1);
+ y8x8 = 8*(Block8x8 >> 1);
+ for (Block4x4 = 0; Block4x4 < 4; Block4x4++)
+ {
+ x4x4 = 4*(Block4x4 & 1);
+ y4x4 = 4*(Block4x4 >> 1);
+
+ armVCCOMM_SAD(
+ pSrcCurrBuf + (x8x8 + x4x4) + (y8x8 + y4x4) * SrcCurrStep,
+ SrcCurrStep,
+ pTempRefBuf + (x8x8 + x4x4) + (y8x8 + y4x4) * TempRefStep,
+ TempRefStep,
+ &SAD,
+ 4, /* Height */
+ 4); /* Width */
+ *(pDstBlockSAD + 4 * Block8x8 + Block4x4) = (SAD < 0x7fff) ? (OMX_U16) SAD : ARM_VCM4P10_MAX_MODE_VALUE;
+ }
+ }
+ }
+ else
+ {
+ /* Fill SADs with max values and return*/
+ for (i = 0; i < 16; i++)
+ {
+ pDstBlockSAD [i] = ARM_VCM4P10_MAX_4x4_SAD;
+ }
+ }
+ return OMX_Sts_NoErr;
+}
+
+
+
+/**
+ * Function: armVCM4P10_Mode4x4Decision
+ *
+ * Description:
+ * Intra 4x4 Mode decision by calculating cost for all possible modes and
+ * choosing the best mode
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcCurrBuf - Pointer to the start of current Macroblock
+ * [in] SrcCurrStep - Step size of the pointer pSrcCurrBuf
+ * [in/out] pSrcDstMBCurr - Pointer to the OMXVCM4P10MBInfo which will be updated for
+ * field pIntra4x4PredMode of the current block.
+ * [in] Block8x8 - Index 8x8 block in which current 4x4 block belongs
+ * [in] Block4x4 - Index of current 4x4 block
+ * [in/out] pPredIntra4x4SrcY - Pointer to current block location in buffer
+ * with reconstructed values. This will be modified by this
+ * function with best mode predicted values
+ * [in] StepPredIntra4x4SrcY - Step size of the pointer pPredIntra4x4SrcY
+ * [in] pIntra4x4PredMode - Array of Intra 4x4 prediction mode for the MB.
+ * Current MB modes starts at [1,1].
+ * [in] pBestCost - Cost for the Best Intra 4x4 mode
+ * Return Value:
+ * None
+ *
+ */
+static OMXVoid armVCM4P10_Mode4x4Decision (
+ const OMX_U8* pSrcCurrBuf,
+ OMX_S32 SrcCurrStep,
+ OMXVCM4P10MBInfo *pSrcDstMBCurr,
+ OMX_S32 Block8x8,
+ OMX_S32 Block4x4,
+ OMX_U8 *pPredIntra4x4SrcY,
+ OMX_S32 StepPredIntra4x4SrcY,
+ OMX_S32 pIntra4x4PredMode [][9],
+ OMX_S32 *pBestCost
+)
+{
+ OMX_S32 i, j, x, y, BlockX, BlockY, mode;
+ OMX_S32 Cost, BestCost;
+ OMX_U8 *pSrcY;
+ OMX_S32 StepSrcY;
+ OMX_S32 availability = 0;
+ OMX_U8 pPredBlock [4*4];
+ OMXResult Ret = OMX_Sts_Err;
+
+ /* Get block cordinates from 8x8 block index and 4x4 block index */
+ BlockX = ((Block8x8 & 1) << 1) + (Block4x4 & 1);
+ BlockY = ((Block8x8 >> 1) << 1) + (Block4x4 >> 1);
+
+ /* Add offset to point to start of current MB in the array pIntra4x4PredMode */
+ x = BlockX + 1;
+ y = BlockY + 1;
+
+ /* Check for availability of LEFT Block */
+ if (pIntra4x4PredMode [y][x - 1] != ARM_VCM4P10_INVALID_BLOCK)
+ {
+ availability |= OMX_VC_LEFT;
+ }
+
+ /* Check for availability of UPPER Block */
+ if (pIntra4x4PredMode [y - 1][x] != ARM_VCM4P10_INVALID_BLOCK)
+ {
+ availability |= OMX_VC_UPPER;
+ }
+
+ /* Check for availability of UPPER LEFT Block */
+ if (pIntra4x4PredMode [y - 1][x - 1] != ARM_VCM4P10_INVALID_BLOCK)
+ {
+ availability |= OMX_VC_UPPER_LEFT;
+ }
+
+ pSrcY = pPredIntra4x4SrcY +
+ StepPredIntra4x4SrcY * (BlockY << 2) +
+ (BlockX << 2);
+
+ StepSrcY = StepPredIntra4x4SrcY;
+
+ x = BlockX * 4;
+ y = BlockY * 4;
+
+ Cost = BestCost = ARM_VCM4P10_MAX_COST;
+
+ /* Go through each mode for minim cost */
+ for (mode = 0; mode < 9; mode++)
+ {
+ Ret = omxVCM4P10_PredictIntra_4x4(
+ pSrcY - 1,
+ pSrcY - StepSrcY,
+ pSrcY - StepSrcY - 1,
+ pPredBlock,
+ StepSrcY,
+ 4,
+ (OMXVCM4P10Intra4x4PredMode) mode,
+ availability);
+
+ if (Ret == OMX_Sts_NoErr)
+ {
+ armVCCOMM_SAD(
+ pSrcCurrBuf + (y * SrcCurrStep) + x,
+ SrcCurrStep,
+ pPredBlock,
+ 4,
+ &Cost,
+ 4,
+ 4);
+
+ if (Cost < BestCost)
+ {
+ BestCost = Cost;
+
+ pIntra4x4PredMode [BlockY + 1][BlockX + 1] =
+ (OMXVCM4P10Intra4x4PredMode) mode;
+ pSrcDstMBCurr->pIntra4x4PredMode [BlockY * 4 + BlockX] =
+ (OMXVCM4P10Intra4x4PredMode) mode;
+
+ for (j = 0; j < 4; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ pSrcY [StepSrcY * j + i] = pPredBlock [4 * j + i];
+ }
+ }
+ }
+ }
+ }
+
+ *pBestCost = BestCost;
+ return;
+}
+
+/**
+ * Function: armVCM4P10_SetMotionVectorPredictor
+ *
+ * Description:
+ * This function will do the MV Prediction for Inter MBs
+ *
+ * Parameters:
+ * [in] BlockStartX - Start X index in integer pels in current Block
+ * [in] BlockStartY - Start Y index in integer pels in current Block
+ * [in] BlockSizeX - Width of current block
+ * [in] BlockSizeY - Height of current block
+ * [in] RefFrame - Index of the reference frame for prediction
+ * [in] pRefFrArr - Pointer to Ref array storing neighbouring MVs for MV prediction
+ * [in] pMVArr - Pointer to MV array storing neighbouring MVs for MV prediction
+ * [out] pMVPred - Pointer to predicted MVs
+ * Remarks:
+ *
+ * Return Value:
+ * None
+ *
+ */
+static OMXVoid armVCM4P10_SetMotionVectorPredictor(
+ OMX_U32 BlockStartX,
+ OMX_U32 BlockStartY,
+ OMX_U32 BlockSizex,
+ OMX_U32 BlockSizey,
+ OMX_S32 RefFrame,
+ OMX_S32 pRefFrArr[][6],
+ OMXVCMotionVector pMVArr[][12],
+ OMXVCMotionVector *pMVPred
+)
+{
+ OMX_S32 RFrameL; /* Left */
+ OMX_S32 RFrameU; /* Up */
+ OMX_S32 RFrameUR; /* Up-Right */
+
+ OMX_S32 BlockX, BlockY, BlockXFr, BlockYFr, MVPredType;
+ OMX_S32 BlockXPlusOff, BlockXPlusOffFr, BlockXMin1Fr, BlockYMin1Fr;
+
+ BlockX = 4 + (BlockStartX >> 2);
+ BlockY = 4 + (BlockStartY >> 2);
+ BlockXPlusOff = BlockX + (BlockSizex >> 2);
+
+ BlockXFr = BlockX >> 1;
+ BlockYFr = BlockY >> 1;
+ BlockXMin1Fr = (BlockX - 1) >> 1;
+ BlockYMin1Fr = (BlockY - 1) >> 1;
+ BlockXPlusOffFr = BlockXPlusOff >> 1;
+
+ MVPredType = ARM_VCM4P10_MVPRED_MEDIAN;
+
+ RFrameL = pRefFrArr [BlockYFr][BlockXMin1Fr];
+ RFrameU = pRefFrArr [BlockYMin1Fr][BlockXFr];
+ RFrameUR = pRefFrArr [BlockYMin1Fr][BlockXPlusOffFr];
+
+ if (RFrameUR == ARM_VCM4P10_INVALID_BLOCK)
+ {
+ RFrameUR = pRefFrArr [BlockYMin1Fr][BlockXMin1Fr];
+ }
+
+ /*
+ * Prediction if only one of the neighbors uses the reference frame
+ * we are checking
+ */
+
+ if (RFrameL == RefFrame && RFrameU != RefFrame && RFrameUR != RefFrame)
+ {
+ MVPredType = ARM_VCM4P10_MVPRED_L;
+ }
+ else if(RFrameL != RefFrame && RFrameU == RefFrame && RFrameUR != RefFrame)
+ {
+ MVPredType = ARM_VCM4P10_MVPRED_U;
+ }
+ else if(RFrameL != RefFrame && RFrameU != RefFrame && RFrameUR == RefFrame)
+ {
+ MVPredType = ARM_VCM4P10_MVPRED_UR;
+ }
+
+ /* Directional predictions */
+ else if(BlockSizex == 8 && BlockSizey == 16)
+ {
+ if(BlockStartX == 0)
+ {
+ if(RFrameL == RefFrame)
+ {
+ MVPredType = ARM_VCM4P10_MVPRED_L;
+ }
+ }
+ else
+ {
+ if (RFrameUR == RefFrame)
+ {
+ MVPredType = ARM_VCM4P10_MVPRED_UR;
+ }
+ }
+ }
+ else if(BlockSizex == 16 && BlockSizey == 8)
+ {
+ if(BlockStartY == 0)
+ {
+ if(RFrameU == RefFrame)
+ {
+ MVPredType = ARM_VCM4P10_MVPRED_U;
+ }
+ }
+ else
+ {
+ if(RFrameL == RefFrame)
+ {
+ MVPredType = ARM_VCM4P10_MVPRED_L;
+ }
+ }
+ }
+
+ switch (MVPredType)
+ {
+ case ARM_VCM4P10_MVPRED_MEDIAN:
+ if (!(pRefFrArr [BlockYMin1Fr][BlockXMin1Fr] == ARM_VCM4P10_INVALID_BLOCK ||
+ pRefFrArr [BlockYMin1Fr][BlockXFr] == ARM_VCM4P10_INVALID_BLOCK ||
+ pRefFrArr [BlockYMin1Fr][BlockXPlusOffFr] == ARM_VCM4P10_INVALID_BLOCK))
+ {
+ pMVPred->dx = pMVArr [BlockY][BlockX - 1].dx;
+ pMVPred->dy = pMVArr [BlockY][BlockX - 1].dy;
+ }
+ else
+ {
+ pMVPred->dx =
+ ARM_VCM4P10_MEDIAN(pMVArr [BlockY][BlockX - 1].dx,
+ pMVArr [BlockY - 1][BlockX].dx,
+ pMVArr [BlockY - 1][BlockXPlusOff].dx);
+ pMVPred->dy =
+ ARM_VCM4P10_MEDIAN(pMVArr [BlockY][BlockX - 1].dy,
+ pMVArr [BlockY - 1][BlockX].dy,
+ pMVArr [BlockY - 1][BlockXPlusOff].dy);
+ }
+ break;
+
+ case ARM_VCM4P10_MVPRED_L:
+ pMVPred->dx = pMVArr [BlockY][BlockX - 1].dx;
+ pMVPred->dy = pMVArr [BlockY][BlockX - 1].dy;
+ break;
+ case ARM_VCM4P10_MVPRED_U:
+ pMVPred->dx = pMVArr [BlockY - 1][BlockX].dx;
+ pMVPred->dy = pMVArr [BlockY - 1][BlockX].dy;
+ break;
+ case ARM_VCM4P10_MVPRED_UR:
+ if (pRefFrArr [BlockYMin1Fr][BlockXPlusOffFr] != ARM_VCM4P10_INVALID_BLOCK)
+ {
+ pMVPred->dx = pMVArr [BlockY - 1][BlockXPlusOff].dx;
+ pMVPred->dy = pMVArr [BlockY - 1][BlockXPlusOff].dy;
+ }
+ else
+ {
+ pMVPred->dx = pMVArr [BlockY - 1][BlockX - 1].dx;
+ pMVPred->dy = pMVArr [BlockY - 1][BlockX - 1].dy;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+/**
+ * Function: armVCM4P10_BlockMotionSearch
+ *
+ * Description:
+ * Gets best MV for the current block
+ *
+ * Parameters:
+ * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock
+ * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf
+ * [in] pSrcRefY - Pointer to the start of luma component of co-located reference MB
+ * [in] nSrcRefStep - Step size for the pointer pSrcRefY
+ * [in] pRefRect Pointer to the valid reference rectangle; relative to the image origin.
+ * [in] pCurrPointPos Position of the current macroblock in the current plane.
+ * [in] pMESpec - Motion estimation structure
+ * [in] pMBInter - Array, of dimension four, containing pointers to information associated with four
+ * adjacent type INTER MBs (Left, Top, Top-Left, Top-Right).
+ * [in] nLamda - For calculating the cost
+ * [out] pBestCost - Minimum cost for encoding current block
+ * [out] pBestMV - MV corresponding to best cost
+ * [in] BlockStartX - Block start X index in integer pels
+ * [in] BlockStartY - Block start Y index in integer pels
+ * [in] BlockSizeX - Width of current block
+ * [in] BlockSizeY - Height of current block
+ * [in] RefFrame - Index of the reference frame for prediction
+ * [in] pRefFrArr - Pointer to reference frame array storing neighbouring MVs for prediction
+ * [in] pMVArr - Pointer to MV array storing neighbouring MVs for MV prediction
+ * [in] pMVPred - Pointer to MV predicted from neighbour MVs
+ * Remarks:
+ *
+ * Return Value:
+ * OMXResult
+ *
+ */
+static OMXResult armVCM4P10_BlockMotionSearch(
+ const OMX_U8* pSrcCurrBuf,
+ OMX_S32 SrcCurrStep,
+ const OMX_U8* pSrcRefY,
+ OMX_S32 nSrcRefStep,
+ const OMXRect *pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ void* pMESpec,
+
+ OMX_S32 nLamda,
+ OMX_S32* pBestCost,
+ OMXVCMotionVector *pBestMV,
+
+ OMX_U32 BlockStartX,
+ OMX_U32 BlockStartY,
+ OMX_U32 BlockSizeX,
+ OMX_U32 BlockSizeY,
+ OMX_S32 RefFrame,
+ OMX_S32 pRefFrArr [][6],
+ OMXVCMotionVector pMVArr [][12],
+ OMXVCMotionVector *pMVPred
+ )
+{
+
+ OMXVCMotionVector MVCalculated, MVCandidate;
+ OMX_S32 Cost;
+ OMXResult RetValue;
+ OMXVCM4P10MEParams *pMEParams;
+ OMXVCM4P2Coordinate CurrBlockPos;
+
+ /* Get Predicted Motion Vectors */
+ armVCM4P10_SetMotionVectorPredictor (
+ BlockStartX,
+ BlockStartY,
+ BlockSizeX,
+ BlockSizeY,
+ RefFrame,
+ pRefFrArr,
+ pMVArr,
+ pMVPred);
+
+ /* Initialize candidate MV */
+ MVCandidate.dx = 0;
+ MVCandidate.dy = 0;
+
+ CurrBlockPos.x = pCurrPointPos->x + BlockStartX;
+ CurrBlockPos.y = pCurrPointPos->y + BlockStartY;
+
+ /* Block Match Integer */
+ RetValue = omxVCM4P10_BlockMatch_Integer (
+ pSrcCurrBuf,
+ SrcCurrStep,
+ pSrcRefY,
+ nSrcRefStep,
+ pRefRect,
+ &CurrBlockPos,
+ BlockSizeX,
+ BlockSizeY,
+ nLamda,
+ pMVPred,
+ &MVCandidate,
+ &MVCalculated,
+ &Cost,
+ pMESpec);
+
+ /* updated BestMV*/
+ /**pBestCost = Cost;
+ pBestMV->dx = MVCalculated.dx;
+ pBestMV->dy = MVCalculated.dy;*/
+
+ pMEParams = (OMXVCM4P10MEParams *) pMESpec;
+
+ /* Block Match Half pel */
+ if (pMEParams->halfSearchEnable)
+ {
+ RetValue = omxVCM4P10_BlockMatch_Half(
+ pSrcCurrBuf,
+ SrcCurrStep,
+ pSrcRefY,
+ nSrcRefStep,
+ BlockSizeX,
+ BlockSizeY,
+ nLamda,
+ pMVPred,
+ &MVCalculated, /* input/output*/
+ &Cost);
+ }
+
+ /* Block Match Quarter pel */
+ if (pMEParams->quarterSearchEnable)
+ {
+ RetValue = omxVCM4P10_BlockMatch_Quarter(
+ pSrcCurrBuf,
+ SrcCurrStep,
+ pSrcRefY,
+ nSrcRefStep,
+ BlockSizeX,
+ BlockSizeY,
+ nLamda,
+ pMVPred,
+ &MVCalculated,
+ &Cost);
+ }
+
+ /* updated Best Cost and Best MV */
+ *pBestCost = Cost;
+ pBestMV->dx = MVCalculated.dx;
+ pBestMV->dy = MVCalculated.dy;
+
+ /*
+ * Skip MB cost calculations of 16x16 inter mode
+ */
+ return RetValue;
+}
+
+/**
+ * Function: armVCM4P10_PartitionME
+ *
+ * Description:
+ * Gets best cost for the current partition
+ *
+ * Parameters:
+ * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock
+ * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf
+ * [in] pSrcRefBufList - Pointer to List of ref buffer of co-located reference MB
+ * [in] nSrcRefStep - Step size for the pointer pSrcRefY
+ * [in] pRefRect Pointer to the valid reference rectangle; relative to the image origin.
+ * [in] pCurrPointPos Position of the current macroblock in the current plane.
+ * [in] pMESpec - Motion estimation structure
+ * [in] PartWidth - Width of current partition
+ * [in] PartHeight - Height of current partition
+ * [in] BlockWidth - Width of current block
+ * [in] BlockHeight - Height of current block
+ * [in] PartStartX - Partition start X index in integer pels
+ * [in] PartStartY - Partition start Y index in integer pels
+ * [in] pMVArr - Pointer to MV array storing neighbouring MVs for MV prediction
+ * [in] pRefFrArr - Pointer to reference frame array storing neighbouring MVs for prediction
+ * [in] Lambda - For calculating the cost
+ * [out] pCost - Pointer to cost for Inter MB
+ *
+ * Return Value:
+ * OMXResult
+ *
+ */
+static OMXResult armVCM4P10_PartitionME (
+ const OMX_U8* pSrcCurrBuf,
+ OMX_S32 SrcCurrStep,
+ const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES],
+ OMX_S32 SrcRefStep,
+ const OMXRect *pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ void* pMESpec,
+
+ OMX_S32 PartWidth,
+ OMX_S32 PartHeight,
+ OMX_S32 BlockWidth,
+ OMX_S32 BlockHeight,
+ OMX_S32 PartStartX,
+ OMX_S32 PartStartY,
+
+ OMXVCMotionVector pMVArr [][12],
+ OMX_S32 pRefFrArr [][6],
+ OMXVCMotionVector pMVPredArr [][4],
+
+ OMX_S32 Lambda,
+ OMX_S32 *pCost
+)
+{
+ OMX_U32 x, y, i, j, ref, OffX, OffY, OffSrc, OffRef;
+ OMX_S32 BlockCost, PartitionCost, BestCost;
+ OMX_S32 BestRefFrame=0;
+ OMXVCMotionVector BestMV [4][4];
+ OMXVCMotionVector BestMVPred [4][4];
+ OMXVCMotionVector MVPred;
+ OMXVCMotionVector DstMV;
+
+ BestCost = ARM_VCM4P10_MAX_COST;
+
+ for (ref = 0; ref < ARM_VCM4P10_MAX_FRAMES; ref++)
+ {
+ if (pSrcRefBufList [ref] == NULL)
+ {
+ /* No reference frame, continue */
+ continue;
+ }
+
+ PartitionCost = 0;
+
+ for (y = 0; y < PartHeight; y += BlockHeight)
+ {
+ for (x = 0; x < PartWidth; x += BlockWidth)
+ {
+ OffSrc = SrcCurrStep * (PartStartY + y) + PartStartX + x;
+ OffRef = SrcRefStep * (PartStartY + y) + PartStartX + x;
+ armVCM4P10_BlockMotionSearch (
+ pSrcCurrBuf + OffSrc,
+ SrcCurrStep,
+ pSrcRefBufList [ref] + OffRef,
+ SrcRefStep,
+ pRefRect,
+ pCurrPointPos,
+ pMESpec,
+
+ Lambda,
+ &BlockCost,
+ &DstMV,
+
+ x + PartStartX,
+ y + PartStartY,
+ BlockWidth,
+ BlockHeight,
+ ref,
+ pRefFrArr,
+ pMVArr,
+ &MVPred);
+
+ PartitionCost += BlockCost;
+
+ OffX = (PartStartX + x) >> 2;
+ OffY = (PartStartY + y) >> 2;
+
+ for (j = 0; j < (BlockHeight >> 2); j++)
+ {
+ for (i = 0; i < (BlockWidth >> 2); i++)
+ {
+ pMVArr [4 + OffY + j][4 + OffX + i].dx = DstMV.dx;
+ pMVArr [4 + OffY + j][4 + OffX + i].dy = DstMV.dy;
+ pMVPredArr [OffY + j][OffX + i].dx = MVPred.dx;
+ pMVPredArr [OffY + j][OffX + i].dy = MVPred.dy;
+ }
+ }
+
+ pRefFrArr [2 + (OffY >> 1)][2 + (OffX >> 1)] = ref;
+ for (j = 0; j < (BlockHeight >> 3); j++)
+ {
+ for (i = 0; i < (BlockWidth >> 3); i++)
+ {
+ pRefFrArr [2 + (OffY >> 1) + j][2 + (OffX >> 1) + i] = ref;
+ }
+ }
+
+ }
+ }
+
+ /*
+ * If PartitionCost is less for this reference frame, motion vectors needs to be backedup
+ */
+ if (PartitionCost <= BestCost)
+ {
+ BestCost = PartitionCost;
+ BestRefFrame = ref;
+
+ for (y = 0; y < (PartHeight/BlockHeight); y++)
+ {
+ for (x = 0; x < (PartWidth/BlockWidth); x++)
+ {
+ OffX = (PartStartX + x * BlockWidth) >> 2;
+ OffY = (PartStartY + y * BlockHeight) >> 2;
+
+ BestMV[y][x].dx = pMVArr [4 + OffY][4 + OffX].dx;
+ BestMV[y][x].dy = pMVArr [4 + OffY][4 + OffX].dy;
+ BestMVPred[y][x].dx = pMVPredArr [OffY][OffX].dx;
+ BestMVPred[y][x].dy = pMVPredArr [OffY][OffX].dy;
+ }
+ }
+ }
+
+ }
+
+ /*
+ * Copy back best reference frame, motion vectors and cost.
+ */
+ for (y = 0; y < (PartHeight/BlockHeight); y++)
+ {
+ for (x = 0; x < (PartWidth/BlockWidth); x++)
+ {
+ OffX = (PartStartX + x * BlockWidth) >> 2;
+ OffY = (PartStartY + y * BlockHeight) >> 2;
+
+ for (j = 0; j < (BlockHeight >> 2); j++)
+ {
+ for (i = 0; i < (BlockWidth >> 2); i++)
+ {
+ pMVArr [4 + OffY + j][4 + OffX + i].dx = BestMV[y][x].dx;
+ pMVArr [4 + OffY + j][4 + OffX + i].dy = BestMV[y][x].dy;
+ pMVPredArr [OffY + j][OffX + i].dx = BestMVPred[y][x].dx;
+ pMVPredArr [OffY + j][OffX + i].dy = BestMVPred[y][x].dy;
+ }
+ }
+
+ for (j = 0; j < (BlockHeight >> 3); j++)
+ {
+ for (i = 0; i < (BlockWidth >> 3); i++)
+ {
+ pRefFrArr [2 + (OffY >> 1) + j][2 + (OffX >> 1) + i] = BestRefFrame;
+ }
+ }
+ }
+ }
+
+ *pCost = BestCost;
+ return OMX_Sts_NoErr;
+
+}
+
+/**
+ * Function: armVCM4P10_Intra16x16Estimation
+ *
+ * Description:
+ * Performs MB-level motion estimation for INTER MB type and selects best motion estimation strategy from
+ * the set of modes supported in baseline profile ISO/IEC 14496-10.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock
+ * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf
+ * [in] pSrcRecBuf - Pointer to the start of luma component of co-located reconstructed MB
+ * [in] SrcRecStep - Step size for the pointer pSrcRecBuf
+ * [in] nMBPosX - Position of MB in the frame w.r.t X axis
+ * [in] nMBPosY - Position of MB in the frame w.r.t Y axis
+ * [in] pMBInter - Array, of dimension four, containing pointers to information associated with four
+ * adjacent type INTER MBs (Left, Top, Top-Left, Top-Right).
+ * [in] pMBIntra - Array, of dimension four, containing pointers to information associated with four
+ * adjacent type INTRA MBs (Left, Top, Top-Left, Top-Right).
+ * [in/out] pSrcDstMBCurr - Pointer to information structure for the current MB. Following member should be set
+ * before calling this function
+ * [in] Lambda - For calculating the cost
+ * [out] pCost - Pointer to cost for Intra16x16
+ * Return Value:
+ * OMX_Sts_NoErr - No Error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ *
+ */
+
+static OMXResult armVCM4P10_Intra16x16Estimation(
+ const OMX_U8* pSrcCurrBuf,
+ OMX_S32 SrcCurrStep,
+ const OMX_U8* pSrcRecBuf,
+ OMX_S32 SrcRecStep,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCM4P10MBInfoPtr *pMBInter,
+ const OMXVCM4P10MBInfoPtr *pMBIntra,
+ OMXVCM4P10MBInfo *pSrcDstMBCurr,
+ OMX_U32 *pCost)
+{
+ OMX_U8 PredBuf [16*16 + 16];
+ OMX_U8 *pPred;
+ OMX_S32 mode;
+ OMX_S32 Cost;
+ OMX_S32 availability = 0;
+ OMXResult Ret;
+ OMXVCM4P10Intra16x16PredMode IntraMode16x16 [4] =
+ {OMX_VC_16X16_VERT, OMX_VC_16X16_HOR,
+ OMX_VC_16X16_DC, OMX_VC_16X16_PLANE};
+ OMX_U32 MBPosX = pCurrPointPos->x >> 4;
+ OMX_U32 MBPosY = pCurrPointPos->y >> 4;
+
+ pPred = armAlignTo16Bytes(PredBuf);
+
+ /* Check for availability of LEFT MB */
+ if ((MBPosX != 0) && (pMBIntra [0] != 0 || pMBInter [0] != 0))
+ {
+ availability |= OMX_VC_LEFT;
+ }
+
+ /* Check for availability of UP MB */
+ if ((MBPosY != 0) && (pMBIntra [1] != 0 || pMBInter [1] != 0))
+ {
+ availability |= OMX_VC_UPPER;
+ }
+
+ /* Check for availability of UP-LEFT MB */
+ if ((MBPosX > 0) && (MBPosY > 0) &&
+ (pMBIntra [2] != 0 || pMBInter [2] != 0))
+ {
+ availability |= OMX_VC_UPPER_LEFT;
+ }
+
+ *pCost = ARM_VCM4P10_MAX_COST;
+ for (mode = 0; mode < 4; mode++)
+ {
+ Ret = omxVCM4P10_PredictIntra_16x16(
+ pSrcRecBuf - 1,
+ pSrcRecBuf - SrcRecStep,
+ pSrcRecBuf - SrcRecStep - 1,
+ pPred,
+ SrcRecStep,
+ 16,
+ IntraMode16x16 [mode],
+ availability);
+ if (Ret == OMX_Sts_NoErr)
+ {
+ armVCCOMM_SAD(
+ pSrcCurrBuf,
+ SrcCurrStep,
+ pPred,
+ 16,
+ &Cost,
+ 16,
+ 16);
+ if (Cost < *pCost)
+ {
+ *pCost = Cost;
+ pSrcDstMBCurr->Intra16x16PredMode = IntraMode16x16 [mode];
+ }
+
+ }
+
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/**
+ * Function: armVCM4P10_Intra4x4Estimation
+ *
+ * Description:
+ * Performs MB-level motion estimation for Intra 4x4 MB type and selects
+ * the best set of modes supported in baseline profile.
+ *
+ * Parameters:
+ * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock
+ * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf
+ * [in] pSrcRecBuf - Pointer to the start of luma component of co-located reconstructed MB
+ * [in] SrcRecStep - Step size for the pointer pSrcRecBuf
+ * [in] nMBPosX - Position of MB in the frame w.r.t X axis
+ * [in] nMBPosY - Position of MB in the frame w.r.t Y axis
+ * [in] pMBIntra - Array, of dimension four, containing pointers to information associated with four
+ * adjacent type INTRA MBs (Left, Top, Top-Left, Top-Right).
+ * [in/out] pSrcDstMBCurr - Pointer to information structure for the current MB. Following member should be set
+ * before calling this function
+ * [in] Lambda - For calculating the cost
+ * [out] pCost - Pointer to cost for Intra4x4
+ * Return Value:
+ * OMX_Sts_NoErr - No Error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ *
+ */
+
+static OMXResult armVCM4P10_Intra4x4Estimation(
+ const OMX_U8* pSrcCurrBuf,
+ OMX_S32 SrcCurrStep,
+ const OMX_U8* pSrcRecBuf,
+ OMX_S32 SrcRecStep,
+ const OMXVCM4P10MBInfoPtr *pMBIntra,
+ OMXVCM4P10MBInfo *pSrcDstMBCurr,
+ OMX_U32 *pCost)
+{
+ OMX_S32 x, y, Block4x4, Block8x8;
+ OMX_S32 Cost;
+
+ /*
+ * PredIntra4x4Mode will store prediction modes of 4x4 blocks.
+ * Modes for current MB starts at index [1][1].
+ * Modes of nighbouring MB's will be as shown below
+ * A value of ARM_VCM4P10_INVALID_BLOCK for any block in this array means
+ * that block is not available for prediction.
+ *
+ * c3 b0 b1 b2 b3 d0 d1 d2 d3
+ * a0 xx xx xx xx - - - -
+ * a1 xx xx xx xx - - - -
+ * a2 xx xx xx xx - - - -
+ * a3 xx xx xx xx - - - -
+ *
+ */
+ OMX_S32 PredIntra4x4Mode [5][9];
+
+ /*
+ * pSrcY stores re-construsted source array of size 3MB X 2MB as below
+ *
+ * MB11 MB12 MB13
+ * MB21 MB22 MB23
+ *
+ * This array will be used for local reconstruction of 4x4 blocks
+ * with best prediction mode within an MB
+ */
+ OMX_U8 pSrcY [(16*3)*(16*2)];
+ OMX_S32 StepSrcY;
+
+ /* init */
+ *pCost = 0;
+
+ for (y = 0; y < 5; y++)
+ {
+ for (x = 0; x < 9; x++)
+ {
+ /*
+ * Initialize with value of ARM_VCM4P10_INVALID_BLOCK, to mean this
+ * 4x4 block is not available
+ */
+ PredIntra4x4Mode [y][x] = ARM_VCM4P10_INVALID_BLOCK;
+ }
+ }
+
+ /* Replace ARM_VCM4P10_INVALID_BLOCK value with available MBs values*/
+ for (x = 0; x < 4; x++)
+ {
+ /* Store values of b0, b1, b2, b3 */
+ if (pMBIntra[1] != NULL)
+ {
+ PredIntra4x4Mode [0][x + 1] =
+ pMBIntra[1]->pIntra4x4PredMode[3*4 + x];
+ }
+
+ /* Store values of d0, d1, d2, d3 */
+ if (pMBIntra[3] != NULL)
+ {
+ PredIntra4x4Mode [0][x + 5] =
+ pMBIntra[3]->pIntra4x4PredMode[3*4 + x];
+ }
+ }
+
+ /* Store values of c3 */
+ if (pMBIntra[2] != NULL)
+ {
+ PredIntra4x4Mode [0][0] = pMBIntra[2]->pIntra4x4PredMode[15];
+ }
+
+ for (y = 0; y < 4; y++)
+ {
+ /* Store values of a0, a1, a2, a3 */
+ if (pMBIntra[0] != NULL)
+ {
+ PredIntra4x4Mode [y + 1][0] =
+ pMBIntra[0]->pIntra4x4PredMode[y*4 + 3];
+ }
+ }
+
+ /*
+ * Update neighbouring Pred mode array which will be used for
+ * prediction of Intra4x4 modes.
+ */
+
+ StepSrcY = 16 * 3;
+ for (y = 0; y < (16 * 2); y++)
+ {
+ for (x = 0; x < (16 * 3); x++)
+ {
+ pSrcY [StepSrcY * y + x] =
+ pSrcRecBuf [SrcRecStep * (y - 16) + x - 16];
+ }
+ }
+
+ /* for each 8x8 block */
+ for (Block8x8 = 0; Block8x8 < 4; Block8x8++)
+ {
+ /* for each 4x4 block inside 8x8 block */
+ for (Block4x4 = 0; Block4x4 < 4; Block4x4++)
+ {
+ armVCM4P10_Mode4x4Decision (
+ pSrcCurrBuf,
+ SrcCurrStep,
+ pSrcDstMBCurr,
+ Block8x8,
+ Block4x4,
+ pSrcY + 16 * StepSrcY + 16,
+ StepSrcY,
+ PredIntra4x4Mode,
+ &Cost);
+
+ *pCost += Cost;
+ }
+ }
+ return OMX_Sts_NoErr;
+}
+
+/**
+ * Function: armVCM4P10_InterMEMB
+ *
+ * Description:
+ * Performs MB-level motion estimation for INTER MB type and selects best motion estimation strategy from
+ * the set of modes supported in baseline profile ISO/IEC 14496-10.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcCurrBuf - Pointer to the start of luma component of current Macroblock
+ * [in] SrcCurrStep - Step size for the pointer pSrcCurrBuf
+ * [in] pSrcRefBufList - Pointer to the start of luma component of co-located reference MB
+ * [in] SrcRefStep - Step size for the pointer pSrcRefY
+ * [in] pRefRect Pointer to the valid reference rectangle; relative to the image origin.
+ * [in] pCurrPointPos Position of the current macroblock in the current plane.
+ * [in] pMESpec - Motion estimation structure
+ * [in] pMBInter - Array, of dimension four, containing pointers to information associated with four
+ * adjacent type INTER MBs (Left, Top, Top-Left, Top-Right).
+ * [in/out] pSrcDstMBCurr - Pointer to information structure for the current MB. Following member should be set
+ * before calling this function
+ * [in] Lambda - For calculating the cost
+ * [out] pDstCost - Pointer to cost for Inter MB
+ * Return Value:
+ * OMX_Sts_NoErr - No Error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ *
+ */
+
+static OMXResult armVCM4P10_InterMEMB(
+ const OMX_U8 *pSrcCurrBuf,
+ OMX_S32 SrcCurrStep,
+ const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES],
+ OMX_S32 SrcRefStep,
+ const OMXRect *pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ OMX_U32 Lambda,
+ void *pMESpec,
+ const OMXVCM4P10MBInfoPtr *pMBInter,
+ OMXVCM4P10MBInfoPtr pSrcDstMBCurr,
+ OMX_U32 *pDstCost)
+{
+ OMX_S32 i, j, x, y, mode;
+ OMX_U32 Block8x8, XPerMB, YPerMB, Block2x, Block2y;
+ OMX_S32 PartStartX = 0, PartStartY = 0;
+ OMX_S32 PartWidth = 8, PartHeight = 8, BlockWidth = 4, BlockHeight = 4;
+ const OMX_U32 BlkSz [4][2] = {{4,4}, {4,8}, {8,4}};
+ const OMX_U32 PartSz [4][2] = {{8,8}, {8,16}, {16,8}, {16,16}};
+ const OMXVCM4P10SubMacroblockType
+ ModeSubMBType4x4 [] = {OMX_VC_SUB_P_4x4, OMX_VC_SUB_P_4x8,
+ OMX_VC_SUB_P_8x4, OMX_VC_SUB_P_8x8};
+ const OMXVCM4P10MacroblockType
+ ModeMBType [] = {OMX_VC_P_8x8, OMX_VC_P_8x16, OMX_VC_P_16x8, OMX_VC_P_16x16};
+
+ OMXVCM4P10MEParams *pMBOptions;
+ /*
+ * RefFrArr and MVArr will be used for temporary storage of Reference frame index and MVs
+ * It will store RefIndex and MVs of 6 MBs as shown below
+ *
+ * |------|------|------|
+ * |Tp-Lt |Top |Tp-R |
+ * | MB | MB | MB |
+ * |------|------|------|
+ * |Left | Curr | |
+ * | MB | MB | |
+ * |------|------|------|
+ */
+ OMX_S32 RefFrArr [4][6];
+ OMXVCMotionVector MVArr [8][12];
+ OMXVCMotionVector MVPredArr [4][4];
+
+ /*
+ * IndexToLoc will translate pMBInter index into spacial arrangement of MBs
+ */
+ OMX_S32 IndexToLoc [] = {2,1,3,0};
+ OMX_U32 part, MaxPart;
+ OMX_S32 Cost, MotionCost8x8 [4], MBCost, BestCost;
+
+ /*
+ * Update neighbouring MV array and Ref frame array which will be used for
+ * prediction of MVs and Ref frames.
+ */
+
+ /* Set cost to a high value */
+ Cost = BestCost = ARM_VCM4P10_MAX_COST;
+
+ for (y = 0; y < 8; y++)
+ {
+ for (x = 0; x < 12; x++)
+ {
+ i = 3 * (y >> 2) + (x >> 2);
+ if ((y < 4 || x < 4) && (pMBInter[IndexToLoc[i]] != NULL))
+ {
+ MVArr [y][x].dx =
+ pMBInter[IndexToLoc[i]]->pMV0[y % 4][x % 4].dx;
+ MVArr [y][x].dy =
+ pMBInter[IndexToLoc[i]]->pMV0[y % 4][x % 4].dy;
+ }
+ else
+ {
+ MVArr [y][x].dx = 0;
+ MVArr [y][x].dy = 0;
+ }
+ }
+ }
+
+ for (y = 0; y < 4; y++)
+ {
+ for (x = 0; x < 6; x++)
+ {
+ i = 3 * (y >> 1) + (x >> 1);
+ if ((y < 2 || x < 2) && (pMBInter[IndexToLoc[i]] != NULL))
+ {
+ RefFrArr [y][x] =
+ pMBInter[IndexToLoc[i]]->pRefL0Idx [(y % 2) * 2 + (x % 2)];
+ }
+ else
+ {
+ RefFrArr [y][x] = ARM_VCM4P10_INVALID_BLOCK;
+ }
+ }
+ }
+
+ for (y = 0; y < 4; y++)
+ {
+ for (x = 0; x < 4; x++)
+ {
+ MVPredArr [y][x].dx = 0;
+ MVPredArr [y][x].dy = 0;
+ }
+ }
+ /*
+ * Motion Estimation for 8x8 MB Partition
+ */
+
+ for (i = 0; i < 4; i++)
+ {
+ MotionCost8x8 [i] = 0;
+ }
+
+ pMBOptions = (OMXVCM4P10MEParams *) pMESpec;
+
+ if (pMBOptions->blockSplitEnable8x8 == 1 &&
+ pMBOptions->blockSplitEnable4x4 == 1)
+ {
+ pSrcDstMBCurr->mbType = OMX_VC_P_8x8;
+
+ PartWidth = PartSz [0][0];
+ PartHeight = PartSz [0][1];
+
+ /* For each 8x8 partitions */
+ for (Block8x8 = 0; Block8x8 < 4; Block8x8++)
+ {
+ PartStartX = (Block8x8 % 2) << 3;
+ PartStartY = (Block8x8 / 2) << 3;
+
+ Block2x = (Block8x8 & 1) << 1;
+ Block2y = (Block8x8 >> 1) << 1;
+
+ BestCost = ARM_VCM4P10_MAX_COST;
+ for (mode = 0; mode < 3; mode++)
+ {
+ BlockWidth = BlkSz [mode][0];
+ BlockHeight = BlkSz [mode][1];
+
+ armVCM4P10_PartitionME (
+ pSrcCurrBuf,
+ SrcCurrStep,
+ pSrcRefBufList,
+ SrcRefStep,
+ pRefRect,
+ pCurrPointPos,
+ pMESpec,
+
+ PartWidth,
+ PartHeight,
+ BlockWidth,
+ BlockHeight,
+ PartStartX,
+ PartStartY,
+
+ MVArr,
+ RefFrArr,
+ MVPredArr,
+
+ Lambda,
+ &Cost);
+
+ if (Cost <= BestCost)
+ {
+ /* Update cost */
+ BestCost = Cost;
+
+ /* Update MBCurr struct */
+ pSrcDstMBCurr->subMBType [Block8x8] = ModeSubMBType4x4 [mode];
+
+ pSrcDstMBCurr->pRefL0Idx [Block8x8] = RefFrArr [2 + (PartStartY >> 3)][2 + (PartStartX >> 3)];
+
+ /* Update pMV0 and pMVPred of MBCurr struct */
+ for (j = 0; j < 2; j++)
+ {
+ for (i = 0; i < 2; i++)
+ {
+ pSrcDstMBCurr->pMV0 [Block2y + j][Block2x + i].dx =
+ MVArr [4 + Block2y + j][4 + Block2x + i].dx;
+ pSrcDstMBCurr->pMV0 [Block2y + j][Block2x + i].dy =
+ MVArr [4 + Block2y + j][4 + Block2x + i].dy;
+
+ pSrcDstMBCurr->pMVPred [Block2y + j][Block2x + i].dx =
+ MVPredArr [Block2y + j][Block2x + i].dx;
+ pSrcDstMBCurr->pMVPred [Block2y + j][Block2x + i].dy =
+ MVPredArr [Block2y + j][Block2x + i].dy;
+ }
+ }
+ }
+ }
+
+ /* Update cost */
+ MotionCost8x8 [Block8x8] = BestCost;
+ }
+
+ /* Cost for mbType OMX_VC_P_8x8 */
+ BestCost = 0;
+ for (i = 0; i < 4; i++)
+ {
+ BestCost += MotionCost8x8 [i];
+ }
+ }
+ else
+ {
+ /* Set sub MB type to 8x8 */
+ for (i = 0; i < 4; i++)
+ {
+ pSrcDstMBCurr->subMBType [i] = OMX_VC_SUB_P_8x8;
+ }
+ }
+
+ /*
+ * Motion Estimation for 8x8, 8x16, 16x8 and 16x16 MB Partition
+ * If pMBOptions->b8x8BlockSplitEnable is 0, do only 16x16 ME (mode 3)
+ */
+ for (mode = (pMBOptions->blockSplitEnable8x8 == 1 ? 0 : 3); mode < 4; mode++)
+ {
+ BlockWidth = PartWidth = PartSz [mode][0];
+ BlockHeight = PartHeight = PartSz [mode][1];
+
+ XPerMB = 16 / PartWidth;
+ YPerMB = 16 / PartHeight;
+ MaxPart = XPerMB * YPerMB;
+
+ MBCost = 0;
+
+ /* part size 4, 2, 2 and 1 corresponding to 8x8, 8x16, 16x8 and 16x16 MB */
+ for (part = 0; part < MaxPart; part++)
+ {
+ PartStartX = (part % XPerMB) * PartWidth;
+ PartStartY = (part / XPerMB) * PartHeight;
+
+ armVCM4P10_PartitionME (
+ pSrcCurrBuf,
+ SrcCurrStep,
+ pSrcRefBufList,
+ SrcRefStep,
+ pRefRect,
+ pCurrPointPos,
+ pMESpec,
+
+ PartWidth,
+ PartHeight,
+ BlockWidth,
+ BlockHeight,
+ PartStartX,
+ PartStartY,
+
+ MVArr,
+ RefFrArr,
+ MVPredArr,
+
+ Lambda,
+ &Cost);
+
+ MBCost += Cost;
+ }
+
+ if (MBCost <= BestCost)
+ {
+ /* Update cost */
+ BestCost = MBCost;
+
+ /* Update mbType of MBCurr struct */
+ pSrcDstMBCurr->mbType = ModeMBType [mode];
+
+ /* Update pMV0 and pMVPred of MBCurr struct */
+ for (j = 0; j < 4; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ pSrcDstMBCurr->pMV0 [j][i].dx = MVArr [4+j][4+i].dx;
+ pSrcDstMBCurr->pMV0 [j][i].dy = MVArr [4+j][4+i].dy;
+ pSrcDstMBCurr->pMVPred [j][i].dx = MVPredArr [j][i].dx;
+ pSrcDstMBCurr->pMVPred [j][i].dy = MVPredArr [j][i].dy;
+ }
+ }
+ for (j = 0; j < 2; j++)
+ {
+ for (i = 0; i < 2; i++)
+ {
+ pSrcDstMBCurr->pRefL0Idx [j*2+i] = RefFrArr [2+j][2+i];
+ }
+ }
+ }
+
+ }
+
+ /* Update Best Cost */
+ *pDstCost = BestCost;
+
+ return OMX_Sts_NoErr;
+}
+
+/**
+ * Function: omxVCM4P10_MotionEstimationMB (6.3.5.3.1)
+ *
+ * Description:
+ * Performs MB-level motion estimation and selects best motion estimation
+ * strategy from the set of modes supported in baseline profile [ISO14496-10].
+ *
+ * Input Arguments:
+ *
+ * pSrcCurrBuf - Pointer to the current position in original picture plane;
+ * 16-byte alignment required
+ * pSrcRefBufList - Pointer to an array with 16 entries. Each entry points
+ * to the top-left corner of the co-located MB in a reference
+ * picture. The array is filled from low-to-high with valid
+ * reference frame pointers; the unused high entries should be set
+ * to NULL. Ordering of the reference frames should follow
+ * [ISO14496-10] subclause 8.2.4 Decoding Process for Reference
+ * Picture Lists. The entries must be 16-byte aligned.
+ * pSrcRecBuf - Pointer to the top-left corner of the co-located MB in the
+ * reconstructed picture; must be 16-byte aligned.
+ * SrcCurrStep - Width of the original picture plane in terms of full
+ * pixels; must be a multiple of 16.
+ * SrcRefStep - Width of the reference picture plane in terms of full
+ * pixels; must be a multiple of 16.
+ * SrcRecStep - Width of the reconstructed picture plane in terms of full
+ * pixels; must be a multiple of 16.
+ * pRefRect - Pointer to the valid reference rectangle; relative to the
+ * image origin.
+ * pCurrPointPos - Position of the current macroblock in the current plane.
+ * Lambda - Lagrange factor for computing the cost function
+ * pMESpec - Pointer to the motion estimation specification structure; must
+ * have been allocated and initialized prior to calling this
+ * function.
+ * pMBInter - Array, of dimension four, containing pointers to information
+ * associated with four adjacent type INTER MBs (Left, Top,
+ * Top-Left, Top-Right). Any pointer in the array may be set equal
+ * to NULL if the corresponding MB doesn t exist or is not of type
+ * INTER. pMBInter[0] - Pointer to left MB information pMBInter[1]
+ * - Pointer to top MB information pMBInter[2] - Pointer to
+ * top-left MB information pMBInter[3] - Pointer to top-right MB
+ * information
+ * pMBIntra - Array, of dimension four, containing pointers to information
+ * associated with four adjacent type INTRA MBs (Left, Top,
+ * Top-Left, Top-Right). Any pointer in the array may be set equal
+ * to NULL if the corresponding MB doesn t exist or is not of type
+ * INTRA. pMBIntra[0] - Pointer to left MB information pMBIntra[1]
+ * - Pointer to top MB information pMBIntra[2] - Pointer to
+ * top-left MB information pMBIntra[3] - Pointer to top-right MB
+ * information
+ * pSrcDstMBCurr - Pointer to information structure for the current MB.
+ * The following entries should be set prior to calling the
+ * function: sliceID - the number of the slice the to which the
+ * current MB belongs.
+ *
+ * Output Arguments:
+ *
+ * pDstCost - Pointer to the minimum motion cost for the current MB.
+ * pDstBlockSAD - Pointer to the array of SADs for each of the sixteen luma
+ * 4x4 blocks in each MB. The block SADs are in scan order for
+ * each MB. For implementations that cannot compute the SAD values
+ * individually, the maximum possible value (0xffff) is returned
+ * for each of the 16 block SAD entries.
+ * pSrcDstMBCurr - Pointer to updated information structure for the current
+ * MB after MB-level motion estimation has been completed. The
+ * following fields are updated by the ME function. The following
+ * parameter set quantifies the MB-level ME search results: MbType
+ * subMBType[4] pMV0[4][4] pMVPred[4][4] pRefL0Idx[4]
+ * Intra16x16PredMode pIntra4x4PredMode[4][4]
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - One of more of the following pointers is NULL: pSrcCurrBuf,
+ * pSrcRefBufList, pSrcRecBuf, pRefRect, pCurrPointPos, pMESpec,
+ * pMBInter, pMBIntra,pSrcDstMBCurr, pDstCost, pSrcRefBufList[0]
+ * - SrcRefStep, SrcRecStep are not multiples of 16
+ * - iBlockWidth or iBlockHeight are values other than 4, 8, or 16.
+ * - Any alignment restrictions are violated
+ *
+ */
+
+OMXResult omxVCM4P10_MotionEstimationMB(
+ const OMX_U8 *pSrcCurrBuf,
+ OMX_S32 SrcCurrStep,
+ const OMX_U8 *pSrcRefBufList[ARM_VCM4P10_MAX_FRAMES],
+ OMX_S32 SrcRefStep,
+ const OMX_U8 *pSrcRecBuf,
+ OMX_S32 SrcRecStep,
+ const OMXRect *pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ OMX_U32 Lambda,
+ void *pMESpec,
+ const OMXVCM4P10MBInfoPtr *pMBInter,
+ const OMXVCM4P10MBInfoPtr *pMBIntra,
+ OMXVCM4P10MBInfo *pSrcDstMBCurr,
+ OMX_INT *pDstCost,
+ OMX_U16 *pDstBlockSAD)
+{
+ OMX_U32 Cost, i, IntraFlag = 1;
+ OMXVCM4P10MEParams *pMEParams;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcRefBufList == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcRecBuf == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pCurrPointPos == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pMESpec == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pMBInter == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pMBIntra == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcDstMBCurr == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstCost == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(SrcRefStep <= 0 || SrcRefStep & 15, OMX_Sts_BadArgErr)
+ armRetArgErrIf(SrcRecStep <= 0 || SrcRecStep & 15, OMX_Sts_BadArgErr)
+ armRetArgErrIf(SrcCurrStep <= 0 || SrcCurrStep & 15, OMX_Sts_BadArgErr)
+
+ armRetArgErrIf(armNot16ByteAligned(pSrcCurrBuf), OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot16ByteAligned(pSrcRecBuf), OMX_Sts_BadArgErr)
+
+ for (i = 0; i < ARM_VCM4P10_MAX_FRAMES; i++)
+ {
+ armRetArgErrIf(pSrcRefBufList [i] != NULL &&
+ armNot16ByteAligned(pSrcRefBufList [i]), OMX_Sts_BadArgErr)
+
+ /* Check if current MB needs INTER cost calculations */
+ if (pSrcRefBufList [i] != NULL && IntraFlag == 1)
+ {
+ IntraFlag = 0;
+ }
+ }
+
+ *pDstCost = ARM_VCM4P10_MAX_COST;
+ /*
+ * Inter cost calculations
+ */
+
+ /* check this MB can be Inter */
+ if (IntraFlag != 1)
+ {
+ armVCM4P10_InterMEMB(
+ pSrcCurrBuf,
+ SrcCurrStep,
+ pSrcRefBufList,
+ SrcRefStep,
+ pRefRect,
+ pCurrPointPos,
+ Lambda,
+ pMESpec,
+ pMBInter,
+ pSrcDstMBCurr,
+ &Cost
+ );
+
+ *pDstCost = Cost;
+ }
+
+ pMEParams = (OMXVCM4P10MEParams *)pMESpec;
+
+ if (pMEParams->intraEnable4x4 == 1)
+ {
+ /*
+ * Intra 4x4 cost calculations
+ */
+ armVCM4P10_Intra4x4Estimation(
+ pSrcCurrBuf,
+ SrcCurrStep,
+ pSrcRecBuf,
+ SrcRecStep,
+ pMBIntra,
+ pSrcDstMBCurr,
+ &Cost
+ );
+
+ if (Cost <= *pDstCost)
+ {
+ *pDstCost = Cost;
+ pSrcDstMBCurr->mbType = OMX_VC_INTRA_4x4;
+
+ }
+
+ }
+
+ /*
+ * Cost for Intra 16x16 mode
+ */
+
+ armVCM4P10_Intra16x16Estimation(
+ pSrcCurrBuf,
+ SrcCurrStep,
+ pSrcRecBuf,
+ SrcRecStep,
+ pCurrPointPos,
+ pMBInter,
+ pMBIntra,
+ pSrcDstMBCurr,
+ &Cost
+ );
+
+ if (Cost <= *pDstCost)
+ {
+ *pDstCost = Cost;
+ pSrcDstMBCurr->mbType = OMX_VC_INTRA_16x16;
+ }
+
+ /*
+ * Update pDstBlockSAD to max value
+ */
+ armVCM4P10_CalculateBlockSAD( pSrcDstMBCurr,
+ pSrcCurrBuf,
+ SrcCurrStep,
+ pSrcRefBufList,
+ SrcRefStep,
+ pSrcRecBuf,
+ SrcRecStep,
+ pRefRect,
+ pCurrPointPos,
+ pMBInter,
+ pMBIntra,
+ pDstBlockSAD);
+
+
+ return OMX_Sts_NoErr;
+}
+
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8.c
new file mode 100644
index 0000000..d6ca783
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntraChroma_8x8.c
@@ -0,0 +1,284 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_PredictIntraChroma_8x8.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 Chroma 8x8 intra prediction module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/*
+ * Description:
+ * Perform DC style intra prediction, upper block has priority
+ *
+ * Parameters:
+ * [in] pSrcLeft Pointer to the buffer of 16 left coefficients:
+ * p[x, y] (x = -1, y = 0..3)
+ * [in] pSrcAbove Pointer to the buffer of 16 above coefficients:
+ * p[x,y] (x = 0..3, y = -1)
+ * [in] leftStep Step of left coefficient buffer
+ * [in] dstStep Step of the destination buffer
+ * [in] availability Neighboring 16x16 MB availability flag
+ * [out] pDst Pointer to the destination buffer
+ *
+ * Return Value:
+ * None
+ */
+
+static void armVCM4P10_PredictIntraDCUp4x4(
+ const OMX_U8* pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ OMX_U8* pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMX_S32 availability
+)
+{
+ int x, y, Sum=0, Count = 0;
+
+ if (availability & OMX_VC_UPPER)
+ {
+ for (x=0; x<4; x++)
+ {
+ Sum += pSrcAbove[x];
+ }
+ Count++;
+ }
+ else if (availability & OMX_VC_LEFT)
+ {
+ for (y=0; y<4; y++)
+ {
+ Sum += pSrcLeft[y*leftStep];
+ }
+ Count++;
+ }
+ if (Count==0)
+ {
+ Sum = 128;
+ }
+ else
+ {
+ Sum = (Sum + 2) >> 2;
+ }
+ for (y=0; y<4; y++)
+ {
+ for (x=0; x<4; x++)
+ {
+ pDst[y*dstStep+x] = (OMX_U8)Sum;
+ }
+ }
+}
+
+/*
+ * Description:
+ * Perform DC style intra prediction, left block has priority
+ *
+ * Parameters:
+ * [in] pSrcLeft Pointer to the buffer of 16 left coefficients:
+ * p[x, y] (x = -1, y = 0..3)
+ * [in] pSrcAbove Pointer to the buffer of 16 above coefficients:
+ * p[x,y] (x = 0..3, y = -1)
+ * [in] leftStep Step of left coefficient buffer
+ * [in] dstStep Step of the destination buffer
+ * [in] availability Neighboring 16x16 MB availability flag
+ * [out] pDst Pointer to the destination buffer
+ *
+ * Return Value:
+ * None
+ */
+
+static void armVCM4P10_PredictIntraDCLeft4x4(
+ const OMX_U8* pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ OMX_U8* pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMX_S32 availability
+)
+{
+ int x, y, Sum=0, Count = 0;
+
+ if (availability & OMX_VC_LEFT)
+ {
+ for (y=0; y<4; y++)
+ {
+ Sum += pSrcLeft[y*leftStep];
+ }
+ Count++;
+ }
+ else if (availability & OMX_VC_UPPER)
+ {
+ for (x=0; x<4; x++)
+ {
+ Sum += pSrcAbove[x];
+ }
+ Count++;
+ }
+ if (Count==0)
+ {
+ Sum = 128;
+ }
+ else
+ {
+ Sum = (Sum + 2) >> 2;
+ }
+ for (y=0; y<4; y++)
+ {
+ for (x=0; x<4; x++)
+ {
+ pDst[y*dstStep+x] = (OMX_U8)Sum;
+ }
+ }
+}
+
+/**
+ * Function: omxVCM4P10_PredictIntraChroma_8x8 (6.3.3.1.3)
+ *
+ * Description:
+ * Performs intra prediction for chroma samples.
+ *
+ * Input Arguments:
+ *
+ * pSrcLeft - Pointer to the buffer of 8 left pixels: p[x, y] (x = -1, y=
+ * 0..7).
+ * pSrcAbove - Pointer to the buffer of 8 above pixels: p[x,y] (x = 0..7, y
+ * = -1); must be aligned on an 8-byte boundary.
+ * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
+ * leftStep - Step of left pixel buffer; must be a multiple of 8.
+ * dstStep - Step of the destination buffer; must be a multiple of 8.
+ * predMode - Intra chroma prediction mode, please refer to section 3.4.3.
+ * availability - Neighboring chroma block availability flag, please refer
+ * to "Neighboring Macroblock Availability".
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to the destination buffer; must be aligned on an 8-byte
+ * boundary.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If any of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pDst is NULL.
+ * dstStep < 8 or dstStep is not a multiple of 8.
+ * leftStep is not a multiple of 8.
+ * predMode is not in the valid range of enumeration
+ * OMXVCM4P10IntraChromaPredMode.
+ * predMode is OMX_VC_CHROMA_VERT, but availability doesn't set
+ * OMX_VC_UPPER indicating p[x,-1] (x = 0..7) is not available.
+ * predMode is OMX_VC_CHROMA_HOR, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..7) is not available.
+ * predMode is OMX_VC_CHROMA_PLANE, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1](x = 0..7), or p[-1,y] (y = 0..7), or p[-1,-1] is not
+ * available.
+ * availability sets OMX_VC_UPPER, but pSrcAbove is NULL.
+ * availability sets OMX_VC_LEFT, but pSrcLeft is NULL.
+ * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL.
+ * either pSrcAbove or pDst is not aligned on a 8-byte boundary. Note:
+ * pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointer if
+ * they are not used by intra prediction implied in predMode.
+ * Note: OMX_VC_UPPER_RIGHT is not used in intra chroma
+ * prediction.
+ *
+ */
+OMXResult omxVCM4P10_PredictIntraChroma_8x8(
+ const OMX_U8* pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ const OMX_U8 *pSrcAboveLeft,
+ OMX_U8* pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMXVCM4P10IntraChromaPredMode predMode,
+ OMX_S32 availability
+ )
+{
+ int x, y, Sum;
+ int H, V, a, b, c;
+
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(dstStep < 8, OMX_Sts_BadArgErr);
+ armRetArgErrIf((dstStep % 8) != 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf((leftStep % 8) != 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot8ByteAligned(pSrcAbove), OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot8ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf((availability & OMX_VC_UPPER) && pSrcAbove == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((availability & OMX_VC_LEFT ) && pSrcLeft == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((availability & OMX_VC_UPPER_LEFT) && pSrcAboveLeft == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_CHROMA_VERT && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_CHROMA_HOR && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_CHROMA_PLANE && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_CHROMA_PLANE && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_CHROMA_PLANE && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf((unsigned)predMode > OMX_VC_CHROMA_PLANE, OMX_Sts_BadArgErr);
+
+ switch (predMode)
+ {
+ case OMX_VC_CHROMA_DC:
+ armVCM4P10_PredictIntraDC4x4( pSrcLeft, pSrcAbove, pDst, leftStep, dstStep, availability);
+ armVCM4P10_PredictIntraDCUp4x4( pSrcLeft, pSrcAbove+4, pDst+4, leftStep, dstStep, availability);
+ armVCM4P10_PredictIntraDCLeft4x4( pSrcLeft+4*leftStep, pSrcAbove, pDst+4*dstStep, leftStep, dstStep, availability);
+ armVCM4P10_PredictIntraDC4x4( pSrcLeft+4*leftStep, pSrcAbove+4, pDst+4+4*dstStep, leftStep, dstStep, availability);
+ break;
+
+ case OMX_VC_CHROMA_HOR:
+ for (y=0; y<8; y++)
+ {
+ for (x=0; x<8; x++)
+ {
+ pDst[y*dstStep+x] = pSrcLeft[y*leftStep];
+ }
+ }
+ break;
+
+ case OMX_VC_CHROMA_VERT:
+ for (y=0; y<8; y++)
+ {
+ for (x=0; x<8; x++)
+ {
+ pDst[y*dstStep+x] = pSrcAbove[x];
+ }
+ }
+ break;
+
+ case OMX_VC_CHROMA_PLANE:
+ H = 4*(pSrcAbove[7] - pSrcAboveLeft[0]);
+ for (x=2; x>=0; x--)
+ {
+ H += (x+1)*(pSrcAbove[4+x] - pSrcAbove[2-x]);
+ }
+ V = 4*(pSrcLeft[7*leftStep] - pSrcAboveLeft[0]);
+ for (y=2; y>=0; y--)
+ {
+ V += (y+1)*(pSrcLeft[(4+y)*leftStep] - pSrcLeft[(2-y)*leftStep]);
+ }
+ a = 16*(pSrcAbove[7] + pSrcLeft[7*leftStep]);
+ b = (17*H+16)>>5;
+ c = (17*V+16)>>5;
+ for (y=0; y<8; y++)
+ {
+ for (x=0; x<8; x++)
+ {
+ Sum = (a + b*(x-3) + c*(y-3) + 16)>>5;
+ pDst[y*dstStep+x] = (OMX_U8)armClip(0,255,Sum);
+ }
+ }
+ break;
+ }
+
+ return OMX_Sts_NoErr;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16.c
new file mode 100644
index 0000000..c90cb4c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_16x16.c
@@ -0,0 +1,198 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_PredictIntra_16x16.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 16x16 intra prediction module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_PredictIntra_16x16 (6.3.3.1.2)
+ *
+ * Description:
+ * Perform Intra_16x16 prediction for luma samples. If the upper-right block
+ * is not available, then duplication work should be handled inside the
+ * function. Users need not define them outside.
+ *
+ * Input Arguments:
+ *
+ * pSrcLeft - Pointer to the buffer of 16 left pixels: p[x, y] (x = -1, y =
+ * 0..15)
+ * pSrcAbove - Pointer to the buffer of 16 above pixels: p[x,y] (x = 0..15,
+ * y= -1); must be aligned on a 16-byte boundary.
+ * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
+ * leftStep - Step of left pixel buffer; must be a multiple of 16.
+ * dstStep - Step of the destination buffer; must be a multiple of 16.
+ * predMode - Intra_16x16 prediction mode, please refer to section 3.4.1.
+ * availability - Neighboring 16x16 MB availability flag. Refer to
+ * section 3.4.4.
+ *
+ * Output Arguments:
+ *
+ * pDst -Pointer to the destination buffer; must be aligned on a 16-byte
+ * boundary.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pDst is NULL.
+ * dstStep < 16. or dstStep is not a multiple of 16.
+ * leftStep is not a multiple of 16.
+ * predMode is not in the valid range of enumeration
+ * OMXVCM4P10Intra16x16PredMode
+ * predMode is OMX_VC_16X16_VERT, but availability doesn't set
+ * OMX_VC_UPPER indicating p[x,-1] (x = 0..15) is not available.
+ * predMode is OMX_VC_16X16_HOR, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..15) is not available.
+ * predMode is OMX_VC_16X16_PLANE, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1](x = 0..15), or p[-1,y] (y = 0..15), or p[-1,-1] is not
+ * available.
+ * availability sets OMX_VC_UPPER, but pSrcAbove is NULL.
+ * availability sets OMX_VC_LEFT, but pSrcLeft is NULL.
+ * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL.
+ * either pSrcAbove or pDst is not aligned on a 16-byte boundary.
+ *
+ * Note:
+ * pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointers if
+ * they are not used by intra prediction implied in predMode.
+ * Note:
+ * OMX_VC_UPPER_RIGHT is not used in intra_16x16 luma prediction.
+ *
+ */
+OMXResult omxVCM4P10_PredictIntra_16x16(
+ const OMX_U8* pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ const OMX_U8 *pSrcAboveLeft,
+ OMX_U8* pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMXVCM4P10Intra16x16PredMode predMode,
+ OMX_S32 availability)
+{
+ int x,y,Sum,Count;
+ int H,V,a,b,c;
+
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(dstStep < 16, OMX_Sts_BadArgErr);
+ armRetArgErrIf((dstStep % 16) != 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf((leftStep % 16) != 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot16ByteAligned(pSrcAbove), OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot16ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf((availability & OMX_VC_UPPER) && pSrcAbove == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((availability & OMX_VC_LEFT ) && pSrcLeft == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((availability & OMX_VC_UPPER_LEFT) && pSrcAboveLeft == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_16X16_VERT && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_16X16_HOR && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_16X16_PLANE && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_16X16_PLANE && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_16X16_PLANE && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf((unsigned)predMode > OMX_VC_16X16_PLANE, OMX_Sts_BadArgErr);
+
+ switch (predMode)
+ {
+ case OMX_VC_16X16_VERT:
+ for (y=0; y<16; y++)
+ {
+ for (x=0; x<16; x++)
+ {
+ pDst[y*dstStep+x] = pSrcAbove[x];
+ }
+ }
+ break;
+
+ case OMX_VC_16X16_HOR:
+ for (y=0; y<16; y++)
+ {
+ for (x=0; x<16; x++)
+ {
+ pDst[y*dstStep+x] = pSrcLeft[y*leftStep];
+ }
+ }
+ break;
+
+ case OMX_VC_16X16_DC:
+ /* This can always be used even if no blocks available */
+ Sum = 0;
+ Count = 0;
+ if (availability & OMX_VC_LEFT)
+ {
+ for (y=0; y<16; y++)
+ {
+ Sum += pSrcLeft[y*leftStep];
+ }
+ Count++;
+ }
+ if (availability & OMX_VC_UPPER)
+ {
+ for (x=0; x<16; x++)
+ {
+ Sum += pSrcAbove[x];
+ }
+ Count++;
+ }
+ if (Count==0)
+ {
+ Sum = 128;
+ }
+ else if (Count==1)
+ {
+ Sum = (Sum + 8) >> 4;
+ }
+ else /* Count = 2 */
+ {
+ Sum = (Sum + 16) >> 5;
+ }
+ for (y=0; y<16; y++)
+ {
+ for (x=0; x<16; x++)
+ {
+ pDst[y*dstStep+x] = (OMX_U8)Sum;
+ }
+ }
+ break;
+
+ case OMX_VC_16X16_PLANE:
+ H = 8*(pSrcAbove[15] - pSrcAboveLeft[0]);
+ for (x=6; x>=0; x--)
+ {
+ H += (x+1)*(pSrcAbove[8+x] - pSrcAbove[6-x]);
+ }
+ V = 8*(pSrcLeft[15*leftStep] - pSrcAboveLeft[0]);
+ for (y=6; y>=0; y--)
+ {
+ V += (y+1)*(pSrcLeft[(8+y)*leftStep] - pSrcLeft[(6-y)*leftStep]);
+ }
+ a = 16*(pSrcAbove[15] + pSrcLeft[15*leftStep]);
+ b = (5*H+32)>>6;
+ c = (5*V+32)>>6;
+ for (y=0; y<16; y++)
+ {
+ for (x=0; x<16; x++)
+ {
+ Sum = (a + b*(x-7) + c*(y-7) + 16)>>5;
+ pDst[y*dstStep+x] = (OMX_U8)armClip(0,255,Sum);
+ }
+ }
+ break;
+ }
+
+ return OMX_Sts_NoErr;
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4.c
new file mode 100644
index 0000000..3fa8212
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_PredictIntra_4x4.c
@@ -0,0 +1,338 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_PredictIntra_4x4.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 4x4 intra prediction module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_PredictIntra_4x4 (6.3.3.1.1)
+ *
+ * Description:
+ * Perform Intra_4x4 prediction for luma samples. If the upper-right block is
+ * not available, then duplication work should be handled inside the function.
+ * Users need not define them outside.
+ *
+ * Input Arguments:
+ *
+ * pSrcLeft - Pointer to the buffer of 4 left pixels:
+ * p[x, y] (x = -1, y = 0..3)
+ * pSrcAbove - Pointer to the buffer of 8 above pixels:
+ * p[x,y] (x = 0..7, y =-1);
+ * must be aligned on a 4-byte boundary.
+ * pSrcAboveLeft - Pointer to the above left pixels: p[x,y] (x = -1, y = -1)
+ * leftStep - Step of left pixel buffer; must be a multiple of 4.
+ * dstStep - Step of the destination buffer; must be a multiple of 4.
+ * predMode - Intra_4x4 prediction mode.
+ * availability - Neighboring 4x4 block availability flag, refer to
+ * "Neighboring Macroblock Availability" .
+ *
+ * Output Arguments:
+ *
+ * pDst - Pointer to the destination buffer; must be aligned on a 4-byte
+ * boundary.
+ *
+ * Return Value:
+ * If the function runs without error, it returns OMX_Sts_NoErr.
+ * If one of the following cases occurs, the function returns
+ * OMX_Sts_BadArgErr:
+ * pDst is NULL.
+ * dstStep < 4, or dstStep is not a multiple of 4.
+ * leftStep is not a multiple of 4.
+ * predMode is not in the valid range of enumeration
+ * OMXVCM4P10Intra4x4PredMode.
+ * predMode is OMX_VC_4x4_VERT, but availability doesn't set OMX_VC_UPPER
+ * indicating p[x,-1] (x = 0..3) is not available.
+ * predMode is OMX_VC_4x4_HOR, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..3) is not available.
+ * predMode is OMX_VC_4x4_DIAG_DL, but availability doesn't set
+ * OMX_VC_UPPER indicating p[x, 1] (x = 0..3) is not available.
+ * predMode is OMX_VC_4x4_DIAG_DR, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
+ * available.
+ * predMode is OMX_VC_4x4_VR, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
+ * available.
+ * predMode is OMX_VC_4x4_HD, but availability doesn't set
+ * OMX_VC_UPPER_LEFT or OMX_VC_UPPER or OMX_VC_LEFT indicating
+ * p[x,-1] (x = 0..3), or p[-1,y] (y = 0..3) or p[-1,-1] is not
+ * available.
+ * predMode is OMX_VC_4x4_VL, but availability doesn't set OMX_VC_UPPER
+ * indicating p[x,-1] (x = 0..3) is not available.
+ * predMode is OMX_VC_4x4_HU, but availability doesn't set OMX_VC_LEFT
+ * indicating p[-1,y] (y = 0..3) is not available.
+ * availability sets OMX_VC_UPPER, but pSrcAbove is NULL.
+ * availability sets OMX_VC_LEFT, but pSrcLeft is NULL.
+ * availability sets OMX_VC_UPPER_LEFT, but pSrcAboveLeft is NULL.
+ * either pSrcAbove or pDst is not aligned on a 4-byte boundary.
+ *
+ * Note:
+ * pSrcAbove, pSrcAbove, pSrcAboveLeft may be invalid pointers if
+ * they are not used by intra prediction as implied in predMode.
+ *
+ */
+
+OMXResult omxVCM4P10_PredictIntra_4x4(
+ const OMX_U8* pSrcLeft,
+ const OMX_U8 *pSrcAbove,
+ const OMX_U8 *pSrcAboveLeft,
+ OMX_U8* pDst,
+ OMX_INT leftStep,
+ OMX_INT dstStep,
+ OMXVCM4P10Intra4x4PredMode predMode,
+ OMX_S32 availability
+ )
+{
+ int x, y;
+ OMX_U8 pTmp[10];
+
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((leftStep % 4) != 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf((dstStep % 4) != 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf((dstStep < 4), OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pSrcAbove), OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf((availability & OMX_VC_UPPER) && pSrcAbove == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((availability & OMX_VC_LEFT ) && pSrcLeft == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((availability & OMX_VC_UPPER_LEFT) && pSrcAboveLeft == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_VERT && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_HOR && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DL && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DR && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DR && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_DIAG_DR && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_VR && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_VR && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_VR && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_HD && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_HD && !(availability & OMX_VC_UPPER_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_HD && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_VL && !(availability & OMX_VC_UPPER), OMX_Sts_BadArgErr);
+ armRetArgErrIf(predMode==OMX_VC_4X4_HU && !(availability & OMX_VC_LEFT), OMX_Sts_BadArgErr);
+ armRetArgErrIf((unsigned)predMode > OMX_VC_4X4_HU, OMX_Sts_BadArgErr);
+
+ /* Note: This code must not read the pSrc arrays unless the corresponding
+ * block is marked as available. If the block is not avaibable then pSrc
+ * may not be a valid pointer.
+ *
+ * Note: To make the code more readable we refer to the neighbouring pixels
+ * in variables named as below:
+ *
+ * UL U0 U1 U2 U3 U4 U5 U6 U7
+ * L0 xx xx xx xx
+ * L1 xx xx xx xx
+ * L2 xx xx xx xx
+ * L3 xx xx xx xx
+ */
+
+#define UL pSrcAboveLeft[0]
+#define U0 pSrcAbove[0]
+#define U1 pSrcAbove[1]
+#define U2 pSrcAbove[2]
+#define U3 pSrcAbove[3]
+#define U4 pSrcAbove[4]
+#define U5 pSrcAbove[5]
+#define U6 pSrcAbove[6]
+#define U7 pSrcAbove[7]
+#define L0 pSrcLeft[0*leftStep]
+#define L1 pSrcLeft[1*leftStep]
+#define L2 pSrcLeft[2*leftStep]
+#define L3 pSrcLeft[3*leftStep]
+
+ switch (predMode)
+ {
+ case OMX_VC_4X4_VERT:
+ for (y=0; y<4; y++)
+ {
+ pDst[y*dstStep+0] = U0;
+ pDst[y*dstStep+1] = U1;
+ pDst[y*dstStep+2] = U2;
+ pDst[y*dstStep+3] = U3;
+ }
+ break;
+
+ case OMX_VC_4X4_HOR:
+ for (x=0; x<4; x++)
+ {
+ pDst[0*dstStep+x] = L0;
+ pDst[1*dstStep+x] = L1;
+ pDst[2*dstStep+x] = L2;
+ pDst[3*dstStep+x] = L3;
+ }
+ break;
+
+ case OMX_VC_4X4_DC:
+ /* This can always be used even if no blocks available */
+ armVCM4P10_PredictIntraDC4x4(pSrcLeft, pSrcAbove, pDst, leftStep, dstStep, availability);
+ break;
+
+ case OMX_VC_4X4_DIAG_DL:
+ pTmp[0] = (OMX_U8)((U0 + 2*U1 + U2 + 2)>>2);
+ pTmp[1] = (OMX_U8)((U1 + 2*U2 + U3 + 2)>>2);
+ if (availability & OMX_VC_UPPER_RIGHT)
+ {
+ pTmp[2] = (OMX_U8)((U2 + 2*U3 + U4 + 2)>>2);
+ pTmp[3] = (OMX_U8)((U3 + 2*U4 + U5 + 2)>>2);
+ pTmp[4] = (OMX_U8)((U4 + 2*U5 + U6 + 2)>>2);
+ pTmp[5] = (OMX_U8)((U5 + 2*U6 + U7 + 2)>>2);
+ pTmp[6] = (OMX_U8)((U6 + 3*U7 + 2)>>2);
+ }
+ else
+ {
+ pTmp[2] = (OMX_U8)((U2 + 3*U3 + 2)>>2);
+ pTmp[3] = U3;
+ pTmp[4] = U3;
+ pTmp[5] = U3;
+ pTmp[6] = U3;
+ }
+ for (y=0; y<4; y++)
+ {
+ for (x=0; x<4; x++)
+ {
+ pDst[y*dstStep+x] = pTmp[x+y];
+ }
+ }
+ break;
+
+ case OMX_VC_4X4_DIAG_DR:
+ /* x-y = -3, -2, -1, 0, 1, 2, 3 */
+ pTmp[0] = (OMX_U8)((L1 + 2*L2 + L3 + 2)>>2);
+ pTmp[1] = (OMX_U8)((L0 + 2*L1 + L2 + 2)>>2);
+ pTmp[2] = (OMX_U8)((UL + 2*L0 + L1 + 2)>>2);
+ pTmp[3] = (OMX_U8)((U0 + 2*UL + L0 + 2)>>2);
+ pTmp[4] = (OMX_U8)((U1 + 2*U0 + UL + 2)>>2);
+ pTmp[5] = (OMX_U8)((U2 + 2*U1 + U0 + 2)>>2);
+ pTmp[6] = (OMX_U8)((U3 + 2*U2 + U1 + 2)>>2);
+ for (y=0; y<4; y++)
+ {
+ for (x=0; x<4; x++)
+ {
+ pDst[y*dstStep+x] = pTmp[3+x-y];
+ }
+ }
+ break;
+
+ case OMX_VC_4X4_VR:
+ /* zVR=2x-y = -3, -2, -1, 0, 1, 2, 3, 4, 5, 6
+ * x-(y>>1) = -1, -1, 0, 0, 1, 1, 2, 2, 3, 3
+ * y = 3, 2, ?, ?, ?, ?, ?, ?, 1, 0
+ */
+ pTmp[0] = (OMX_U8)((L2 + 2*L1 + L0 + 2)>>2);
+ pTmp[1] = (OMX_U8)((L1 + 2*L0 + UL + 2)>>2);
+ pTmp[2] = (OMX_U8)((L0 + 2*UL + U0 + 2)>>2);
+ pTmp[3] = (OMX_U8)((UL + U0 + 1)>>1);
+ pTmp[4] = (OMX_U8)((UL + 2*U0 + U1 + 2)>>2);
+ pTmp[5] = (OMX_U8)((U0 + U1 + 1)>>1);
+ pTmp[6] = (OMX_U8)((U0 + 2*U1 + U2 + 2)>>2);
+ pTmp[7] = (OMX_U8)((U1 + U2 + 1)>>1);
+ pTmp[8] = (OMX_U8)((U1 + 2*U2 + U3 + 2)>>2);
+ pTmp[9] = (OMX_U8)((U2 + U3 + 1)>>1);
+ for (y=0; y<4; y++)
+ {
+ for (x=0; x<4; x++)
+ {
+ pDst[y*dstStep+x] = pTmp[3+2*x-y];
+ }
+ }
+ break;
+
+ case OMX_VC_4X4_HD:
+ /* zHD=2y-x = -3 -2 -1 0 1 2 3 4 5 6
+ * y-(x>>1) = -1 -1 0 0 1 1 2 2 3 3
+ * x = 3 2 1 0
+ */
+ pTmp[0] = (OMX_U8)((U2 + 2*U1 + U0 + 2)>>2);
+ pTmp[1] = (OMX_U8)((U1 + 2*U0 + UL + 2)>>2);
+ pTmp[2] = (OMX_U8)((U0 + 2*UL + L0 + 2)>>2);
+ pTmp[3] = (OMX_U8)((UL + L0 + 1)>>1);
+ pTmp[4] = (OMX_U8)((UL + 2*L0 + L1 + 2)>>2);
+ pTmp[5] = (OMX_U8)((L0 + L1 + 1)>>1);
+ pTmp[6] = (OMX_U8)((L0 + 2*L1 + L2 + 2)>>2);
+ pTmp[7] = (OMX_U8)((L1 + L2 + 1)>>1);
+ pTmp[8] = (OMX_U8)((L1 + 2*L2 + L3 + 2)>>2);
+ pTmp[9] = (OMX_U8)((L2 + L3 + 1)>>1);
+ for (y=0; y<4; y++)
+ {
+ for (x=0; x<4; x++)
+ {
+ pDst[y*dstStep+x] = pTmp[3+2*y-x];
+ }
+ }
+ break;
+
+ case OMX_VC_4X4_VL:
+ /* Note: x+(y>>1) = (2*x+y)>>1
+ * 2x+y = 0 1 2 3 4 5 6 7 8 9
+ */
+ pTmp[0] = (OMX_U8)((U0 + U1 + 1)>>1);
+ pTmp[1] = (OMX_U8)((U0 + 2*U1 + U2 + 2)>>2);
+ pTmp[2] = (OMX_U8)((U1 + U2 + 1)>>1);
+ pTmp[3] = (OMX_U8)((U1 + 2*U2 + U3 + 2)>>2);
+ pTmp[4] = (OMX_U8)((U2 + U3 + 1)>>1);
+ if (availability & OMX_VC_UPPER_RIGHT)
+ {
+ pTmp[5] = (OMX_U8)((U2 + 2*U3 + U4 + 2)>>2);
+ pTmp[6] = (OMX_U8)((U3 + U4 + 1)>>1);
+ pTmp[7] = (OMX_U8)((U3 + 2*U4 + U5 + 2)>>2);
+ pTmp[8] = (OMX_U8)((U4 + U5 + 1)>>1);
+ pTmp[9] = (OMX_U8)((U4 + 2*U5 + U6 + 2)>>2);
+ }
+ else
+ {
+ pTmp[5] = (OMX_U8)((U2 + 3*U3 + 2)>>2);
+ pTmp[6] = U3;
+ pTmp[7] = U3;
+ pTmp[8] = U3;
+ pTmp[9] = U3;
+ }
+ for (y=0; y<4; y++)
+ {
+ for (x=0; x<4; x++)
+ {
+ pDst[y*dstStep+x] = pTmp[2*x+y];
+ }
+ }
+ break;
+
+ case OMX_VC_4X4_HU:
+ /* zHU = x+2*y */
+ pTmp[0] = (OMX_U8)((L0 + L1 + 1)>>1);
+ pTmp[1] = (OMX_U8)((L0 + 2*L1 + L2 + 2)>>2);
+ pTmp[2] = (OMX_U8)((L1 + L2 + 1)>>1);
+ pTmp[3] = (OMX_U8)((L1 + 2*L2 + L3 + 2)>>2);
+ pTmp[4] = (OMX_U8)((L2 + L3 + 1)>>1);
+ pTmp[5] = (OMX_U8)((L2 + 3*L3 + 2)>>2);
+ pTmp[6] = L3;
+ pTmp[7] = L3;
+ pTmp[8] = L3;
+ pTmp[9] = L3;
+ for (y=0; y<4; y++)
+ {
+ for (x=0; x<4; x++)
+ {
+ pDst[y*dstStep+x] = pTmp[x+2*y];
+ }
+ }
+ break;
+ }
+
+ return OMX_Sts_NoErr;
+}
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_16x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_16x.c
new file mode 100644
index 0000000..c8114ee
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_16x.c
@@ -0,0 +1,86 @@
+/**
+ *
+ * File Name: omxVCM4P10_SADQuar_16x.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate SAD of pSrc with average of two Ref blocks
+ * of 16x16 or 16x8
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P10_SADQuar_16x (6.3.5.4.4)
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the average
+ * of the other two (pSrcRef0 and pSrcRef1) for 16x16 or 16x8 blocks.
+ * Rounding is applied according to the convention (a+b+1)>>1.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the original block; must be aligned on a 16-byte
+ * boundary.
+ * pSrcRef0 - Pointer to reference block 0
+ * pSrcRef1 - Pointer to reference block 1
+ * iSrcStep - Step of the original block buffer; must be a multiple of 16
+ * iRefStep0 - Step of reference block 0
+ * iRefStep1 - Step of reference block 1
+ * iHeight - Height of the block; must be equal to either 8 or 16
+ *
+ * Output Arguments:
+ *
+ * pDstSAD -Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - iHeight is not equal to either 8 or 16.
+ * - One of more of the following pointers is NULL: pSrc, pSrcRef0,
+ * pSrcRef1, pDstSAD.
+ * - iSrcStep is not a multiple of 16
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SADQuar_16x(
+ const OMX_U8* pSrc,
+ const OMX_U8* pSrcRef0,
+ const OMX_U8* pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32* pDstSAD,
+ OMX_U32 iHeight
+)
+{
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcRef0 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcRef1 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf((iHeight != 16) && (iHeight != 8), OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot16ByteAligned(pSrc), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iSrcStep == 0) || (iSrcStep & 15), OMX_Sts_BadArgErr)
+
+
+ return armVCM4P10_SADQuar
+ (pSrc, pSrcRef0, pSrcRef1, iSrcStep,
+ iRefStep0, iRefStep1, pDstSAD, iHeight, 16);
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_4x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_4x.c
new file mode 100644
index 0000000..4b330ba
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_4x.c
@@ -0,0 +1,85 @@
+/**
+ *
+ * File Name: omxVCM4P10_SADQuar_4x.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate SAD of pSrc with average of two Ref blocks
+ * of 4x8 or 4x4 blocks
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P10_SADQuar_4x (6.3.5.4.2)
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the average
+ * of the other two (pSrcRef0 and pSrcRef1) for 4x8 or 4x4 blocks. Rounding
+ * is applied according to the convention (a+b+1)>>1.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the original block; must be aligned on a 4-byte
+ * boundary.
+ * pSrcRef0 - Pointer to reference block 0
+ * pSrcRef1 - Pointer to reference block 1
+ * iSrcStep - Step of the original block buffer; must be a multiple of 4.
+ * iRefStep0 - Step of reference block 0
+ * iRefStep1 - Step of reference block 1
+ * iHeight - Height of the block; must be equal to either 4 or 8.
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - iHeight is not equal to either 4 or 8.
+ * - One of more of the following pointers is NULL: pSrc, pSrcRef0,
+ * pSrcRef1, pDstSAD.
+ * - iSrcStep is not a multiple of 4
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SADQuar_4x(
+ const OMX_U8* pSrc,
+ const OMX_U8* pSrcRef0,
+ const OMX_U8* pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32* pDstSAD,
+ OMX_U32 iHeight
+)
+{
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcRef0 == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcRef1 == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((iHeight != 8) && (iHeight != 4), OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pSrc), OMX_Sts_BadArgErr);
+ armRetArgErrIf((iSrcStep == 0) || (iSrcStep & 3), OMX_Sts_BadArgErr);
+
+ return armVCM4P10_SADQuar
+ (pSrc, pSrcRef0, pSrcRef1, iSrcStep,
+ iRefStep0, iRefStep1, pDstSAD, iHeight, 4);
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_8x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_8x.c
new file mode 100644
index 0000000..c9e9c24
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SADQuar_8x.c
@@ -0,0 +1,87 @@
+/**
+ *
+ * File Name: omxVCM4P10_SADQuar_8x.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate SAD of pSrc with average of two Ref blocks
+ * of 8x16 or 8x8 or 8x4
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P10_SADQuar_8x (6.3.5.4.3)
+ *
+ * Description:
+ * This function calculates the SAD between one block (pSrc) and the average
+ * of the other two (pSrcRef0 and pSrcRef1) for 8x16, 8x8, or 8x4 blocks.
+ * Rounding is applied according to the convention (a+b+1)>>1.
+ *
+ * Input Arguments:
+ *
+ * pSrc - Pointer to the original block; must be aligned on an 8-byte
+ * boundary.
+ * pSrcRef0 - Pointer to reference block 0
+ * pSrcRef1 - Pointer to reference block 1
+ * iSrcStep - Step of the original block buffer; must be a multiple of 8.
+ * iRefStep0 - Step of reference block 0
+ * iRefStep1 - Step of reference block 1
+ * iHeight - Height of the block; must be equal either 4, 8, or 16.
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - iHeight is not equal to either 4, 8, or 16.
+ * - One of more of the following pointers is NULL: pSrc, pSrcRef0,
+ * pSrcRef1, pDstSAD.
+ * - iSrcStep is not a multiple of 8
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SADQuar_8x(
+ const OMX_U8* pSrc,
+ const OMX_U8* pSrcRef0,
+ const OMX_U8* pSrcRef1,
+ OMX_U32 iSrcStep,
+ OMX_U32 iRefStep0,
+ OMX_U32 iRefStep1,
+ OMX_U32* pDstSAD,
+ OMX_U32 iHeight
+)
+{
+ /* check for argument error */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcRef0 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcRef1 == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf((iHeight != 16) && (iHeight != 8) &&
+ (iHeight != 4), OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot8ByteAligned(pSrc), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iSrcStep == 0) || (iSrcStep & 7), OMX_Sts_BadArgErr)
+
+
+ return armVCM4P10_SADQuar
+ (pSrc, pSrcRef0, pSrcRef1, iSrcStep,
+ iRefStep0, iRefStep1, pDstSAD, iHeight, 8);
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SAD_4x.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SAD_4x.c
new file mode 100644
index 0000000..927c454
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SAD_4x.c
@@ -0,0 +1,77 @@
+/**
+ *
+ * File Name: omxVCM4P10_SAD_4x.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate SAD for 4x8 and 4x4 blocks
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P10_SAD_4x (6.3.5.4.1)
+ *
+ * Description:
+ * This function calculates the SAD for 4x8 and 4x4 blocks.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg -Pointer to the original block; must be aligned on a 4-byte
+ * boundary.
+ * iStepOrg -Step of the original block buffer; must be a multiple of 4.
+ * pSrcRef -Pointer to the reference block
+ * iStepRef -Step of the reference block buffer
+ * iHeight -Height of the block; must be equal to either 4 or 8.
+ *
+ * Output Arguments:
+ *
+ * pDstSAD -Pointer of result SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - One of more of the following pointers is NULL:
+ * pSrcOrg, pSrcRef, or pDstSAD
+ * - iHeight is not equal to either 4 or 8.
+ * - iStepOrg is not a multiple of 4
+ * - Any alignment restrictions are violated
+ *
+ */
+OMXResult omxVCM4P10_SAD_4x(
+ const OMX_U8* pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8* pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_S32* pDstSAD,
+ OMX_U32 iHeight
+)
+{
+ /* check for argument error */
+ armRetArgErrIf(pSrcOrg == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcRef == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf((iHeight != 8) && (iHeight != 4), OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot4ByteAligned(pSrcOrg), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iStepOrg == 0) || (iStepOrg & 3), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iStepRef == 0) || (iStepRef & 3), OMX_Sts_BadArgErr)
+
+ return armVCCOMM_SAD
+ (pSrcOrg, iStepOrg, pSrcRef, iStepRef, pDstSAD, iHeight, 4);
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SATD_4x4.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SATD_4x4.c
new file mode 100644
index 0000000..a91ae66
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SATD_4x4.c
@@ -0,0 +1,132 @@
+/**
+ *
+ * File Name: omxVCM4P10_SATD_4x4.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate SAD for 4x4 blocks
+ *
+ */
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P10_SATD_4x4 (6.3.5.4.5)
+ *
+ * Description:
+ * This function calculates the sum of absolute transform differences (SATD)
+ * for a 4x4 block by applying a Hadamard transform to the difference block
+ * and then calculating the sum of absolute coefficient values.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to the original block; must be aligned on a 4-byte
+ * boundary
+ * iStepOrg - Step of the original block buffer; must be a multiple of 4
+ * pSrcRef - Pointer to the reference block; must be aligned on a 4-byte
+ * boundary
+ * iStepRef - Step of the reference block buffer; must be a multiple of 4
+ *
+ * Output Arguments:
+ *
+ * pDstSAD - pointer to the resulting SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pSrcRef, or pDstSAD either pSrcOrg
+ * - pSrcRef is not aligned on a 4-byte boundary
+ * - iStepOrg <= 0 or iStepOrg is not a multiple of 4
+ * - iStepRef <= 0 or iStepRef is not a multiple of 4
+ *
+ */
+OMXResult omxVCM4P10_SATD_4x4(
+ const OMX_U8* pSrcOrg,
+ OMX_U32 iStepOrg,
+ const OMX_U8* pSrcRef,
+ OMX_U32 iStepRef,
+ OMX_U32* pDstSAD
+)
+{
+ OMX_INT i, j;
+ OMX_S32 SATD = 0;
+ OMX_S32 d [4][4], m1[4][4], m2[4][4];
+
+ /* check for argument error */
+ armRetArgErrIf(pSrcOrg == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcRef == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf((iStepOrg == 0) || (iStepOrg & 3), OMX_Sts_BadArgErr)
+ armRetArgErrIf((iStepRef == 0) || (iStepRef & 3), OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot4ByteAligned(pSrcOrg), OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot4ByteAligned(pSrcRef), OMX_Sts_BadArgErr)
+
+ /* Calculate the difference */
+ for (j = 0; j < 4; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ d [j][i] = pSrcOrg [j * iStepOrg + i] - pSrcRef [j * iStepRef + i];
+ }
+ }
+
+ /* Hadamard Transfor for 4x4 block */
+
+ /* Horizontal */
+ for (i = 0; i < 4; i++)
+ {
+ m1[i][0] = d[i][0] + d[i][2]; /* a+c */
+ m1[i][1] = d[i][1] + d[i][3]; /* b+d */
+ m1[i][2] = d[i][0] - d[i][2]; /* a-c */
+ m1[i][3] = d[i][1] - d[i][3]; /* b-d */
+
+ m2[i][0] = m1[i][0] + m1[i][1]; /* a+b+c+d */
+ m2[i][1] = m1[i][2] + m1[i][3]; /* a+b-c-d */
+ m2[i][2] = m1[i][2] - m1[i][3]; /* a-b-c+d */
+ m2[i][3] = m1[i][0] - m1[i][1]; /* a-b+c-d */
+
+ }
+
+ /* Vertical */
+ for (i = 0; i < 4; i++)
+ {
+ m1[0][i] = m2[0][i] + m2[2][i];
+ m1[1][i] = m2[1][i] + m2[3][i];
+ m1[2][i] = m2[0][i] - m2[2][i];
+ m1[3][i] = m2[1][i] - m2[3][i];
+
+ m2[0][i] = m1[0][i] + m1[1][i];
+ m2[1][i] = m1[2][i] + m1[3][i];
+ m2[2][i] = m1[2][i] - m1[3][i];
+ m2[3][i] = m1[0][i] - m1[1][i];
+ }
+
+ /* calculate SAD for Transformed coefficients */
+ for (j = 0; j < 4; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ SATD += armAbs(m2 [j][i]);
+ }
+ }
+
+ *pDstSAD = (SATD + 1) / 2;
+
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SubAndTransformQDQResidual.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SubAndTransformQDQResidual.c
new file mode 100644
index 0000000..23a5662
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_SubAndTransformQDQResidual.c
@@ -0,0 +1,220 @@
+/**
+ *
+ * File Name: omxVCM4P10_SubAndTransformQDQResidual.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate SAD for 4x4 blocks
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_SubAndTransformQDQResidual (6.3.5.8.1)
+ *
+ * Description:
+ * This function subtracts the prediction signal from the original signal to
+ * produce the difference signal and then performs a 4x4 integer transform and
+ * quantization. The quantized transformed coefficients are stored as
+ * pDstQuantCoeff. This function can also output dequantized coefficients or
+ * unquantized DC coefficients optionally by setting the pointers
+ * pDstDeQuantCoeff, pDCCoeff.
+ *
+ * Input Arguments:
+ *
+ * pSrcOrg - Pointer to original signal. 4-byte alignment required.
+ * pSrcPred - Pointer to prediction signal. 4-byte alignment required.
+ * iSrcOrgStep - Step of the original signal buffer; must be a multiple of
+ * 4.
+ * iSrcPredStep - Step of the prediction signal buffer; must be a multiple
+ * of 4.
+ * pNumCoeff -Number of non-zero coefficients after quantization. If this
+ * parameter is not required, it is set to NULL.
+ * nThreshSAD - Zero-block early detection threshold. If this parameter is
+ * not required, it is set to 0.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ * bIntra - Indicates whether this is an INTRA block, either 1-INTRA or
+ * 0-INTER
+ *
+ * Output Arguments:
+ *
+ * pDstQuantCoeff - Pointer to the quantized transformed coefficients.
+ * 8-byte alignment required.
+ * pDstDeQuantCoeff - Pointer to the dequantized transformed coefficients
+ * if this parameter is not equal to NULL. 8-byte alignment
+ * required.
+ * pDCCoeff - Pointer to the unquantized DC coefficient if this parameter
+ * is not equal to NULL.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcOrg, pSrcPred, pNumCoeff, pDstQuantCoeff,
+ * pDstDeQuantCoeff, pDCCoeff
+ * - pSrcOrg is not aligned on a 4-byte boundary
+ * - pSrcPred is not aligned on a 4-byte boundary
+ * - iSrcOrgStep is not a multiple of 4
+ * - iSrcPredStep is not a multiple of 4
+ * - pDstQuantCoeff or pDstDeQuantCoeff is not aligned on an 8-byte boundary
+ *
+ */
+ OMXResult omxVCM4P10_SubAndTransformQDQResidual (
+ const OMX_U8* pSrcOrg,
+ const OMX_U8* pSrcPred,
+ OMX_U32 iSrcOrgStep,
+ OMX_U32 iSrcPredStep,
+ OMX_S16* pDstQuantCoeff,
+ OMX_S16* pDstDeQuantCoeff,
+ OMX_S16* pDCCoeff,
+ OMX_S8* pNumCoeff,
+ OMX_U32 nThreshSAD,
+ OMX_U32 iQP,
+ OMX_U8 bIntra
+)
+{
+ OMX_INT i, j;
+ OMX_S8 NumCoeff = 0;
+ OMX_S16 Buf[16], m[16];
+ OMX_U32 QBits, QPper, QPmod, f;
+ OMX_S32 Value, MF, ThreshDC;
+
+ /* check for argument error */
+ armRetArgErrIf(pSrcOrg == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstDeQuantCoeff == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pNumCoeff == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDCCoeff == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot4ByteAligned(pSrcOrg), OMX_Sts_BadArgErr)
+ armRetArgErrIf(pSrcPred == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot4ByteAligned(pSrcPred), OMX_Sts_BadArgErr)
+ armRetArgErrIf(pDstQuantCoeff == NULL, OMX_Sts_BadArgErr)
+ armRetArgErrIf(armNot8ByteAligned(pDstQuantCoeff), OMX_Sts_BadArgErr)
+ armRetArgErrIf((pDstDeQuantCoeff != NULL) &&
+ armNot8ByteAligned(pDstDeQuantCoeff), OMX_Sts_BadArgErr)
+ armRetArgErrIf((bIntra != 0) && (bIntra != 1), OMX_Sts_BadArgErr)
+ armRetArgErrIf(iQP > 51, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iSrcOrgStep == 0, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iSrcPredStep == 0, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iSrcOrgStep & 3, OMX_Sts_BadArgErr)
+ armRetArgErrIf(iSrcPredStep & 3, OMX_Sts_BadArgErr)
+
+ /*
+ * Zero-Block Early detection using nThreshSAD param
+ */
+
+ QPper = iQP / 6;
+ QPmod = iQP % 6;
+ QBits = 15 + QPper;
+
+ f = (1 << QBits) / (bIntra ? 3 : 6);
+
+ /* Do Zero-Block Early detection if enabled */
+ if (nThreshSAD)
+ {
+ ThreshDC = ((1 << QBits) - f) / armVCM4P10_MFMatrix[QPmod][0];
+ if (nThreshSAD < ThreshDC)
+ {
+ /* Set block to zero */
+ if (pDCCoeff != NULL)
+ {
+ *pDCCoeff = 0;
+ }
+
+ for (j = 0; j < 4; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ pDstQuantCoeff [4 * j + i] = 0;
+ if (pDstDeQuantCoeff != NULL)
+ {
+ pDstDeQuantCoeff [4 * j + i] = 0;
+ }
+ }
+ }
+
+ if (pNumCoeff != NULL)
+ {
+ *pNumCoeff = 0;
+ }
+ return OMX_Sts_NoErr;
+ }
+ }
+
+
+ /* Calculate difference */
+ for (j = 0; j < 4; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ Buf [j * 4 + i] =
+ pSrcOrg [j * iSrcOrgStep + i] - pSrcPred [j * iSrcPredStep + i];
+ }
+ }
+
+ /* Residual Transform */
+ armVCM4P10_FwdTransformResidual4x4 (m, Buf);
+
+ if (pDCCoeff != NULL)
+ {
+ /* Copy unquantized DC value into pointer */
+ *pDCCoeff = m[0];
+ }
+
+ /* Quantization */
+ for (j = 0; j < 4; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ MF = armVCM4P10_MFMatrix[QPmod][armVCM4P10_PosToVCol4x4[j * 4 + i]];
+ Value = armAbs(m[j * 4 + i]) * MF + f;
+ Value >>= QBits;
+ Value = m[j * 4 + i] < 0 ? -Value : Value;
+ Buf[4 * j + i] = pDstQuantCoeff [4 * j + i] = (OMX_S16)Value;
+ if ((pNumCoeff != NULL) && Value)
+ {
+ NumCoeff++;
+ }
+ }
+ }
+
+ /* Output number of non-zero Coeffs */
+ if (pNumCoeff != NULL)
+ {
+ *pNumCoeff = NumCoeff;
+ }
+
+ /* Residual Inv Transform */
+ if (pDstDeQuantCoeff != NULL)
+ {
+ /* Re Scale */
+ for (j = 0; j < 4; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ m [j * 4 + i] = Buf [j * 4 + i] * (1 << QPper) *
+ armVCM4P10_VMatrix[QPmod][armVCM4P10_PosToVCol4x4[j * 4 + i]];
+ }
+ }
+ armVCM4P10_TransformResidual4x4 (pDstDeQuantCoeff, m);
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair.c
new file mode 100644
index 0000000..9ad0e81
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantChromaDCFromPair.c
@@ -0,0 +1,131 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_TransformDequantChromaDCFromPair.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 inverse quantize and transform module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/*
+ * Description:
+ * Dequantize Chroma 2x2 DC block
+ */
+
+static void DequantChromaDC2x2(
+ OMX_S16* pDst,
+ OMX_INT QP
+)
+{
+ int Shift = (QP/6)-1 ;
+ int Scale = armVCM4P10_VMatrix[QP%6][0];
+ int i, Value;
+
+ if (Shift >= 0)
+ {
+ for (i=0; i<4; i++)
+ {
+ Value = (pDst[i] * Scale) << Shift;
+ pDst[i] = (OMX_S16)Value;
+ }
+ }
+ else
+ {
+ for (i=0; i<4; i++)
+ {
+ Value = (pDst[i] * Scale) >> 1;
+ pDst[i] = (OMX_S16)Value;
+ }
+ }
+}
+
+
+/*
+ * Description:
+ * Inverse Transform DC 2x2 Coefficients
+ */
+
+static void InvTransformDC2x2(OMX_S16* pData)
+{
+ int c00 = pData[0];
+ int c01 = pData[1];
+ int c10 = pData[2];
+ int c11 = pData[3];
+
+ int d00 = c00 + c01;
+ int d01 = c00 - c01;
+ int d10 = c10 + c11;
+ int d11 = c10 - c11;
+
+ pData[0] = (OMX_S16)(d00 + d10);
+ pData[1] = (OMX_S16)(d01 + d11);
+ pData[2] = (OMX_S16)(d00 - d10);
+ pData[3] = (OMX_S16)(d01 - d11);
+}
+
+
+/**
+ * Function: omxVCM4P10_TransformDequantChromaDCFromPair (6.3.4.2.2)
+ *
+ * Description:
+ * Reconstruct the 2x2 ChromaDC block from coefficient-position pair buffer,
+ * perform integer inverse transformation, and dequantization for 2x2 chroma
+ * DC coefficients, and update the pair buffer pointer to next non-empty
+ * block.
+ *
+ * Input Arguments:
+ *
+ * ppSrc - Double pointer to residual coefficient-position pair buffer
+ * output by CALVC decoding
+ * QP - Quantization parameter QpC
+ *
+ * Output Arguments:
+ *
+ * ppSrc - *ppSrc is updated to the start of next non empty block
+ * pDst - Pointer to the reconstructed 2x2 ChromaDC coefficients buffer;
+ * must be aligned on a 4-byte boundary.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppSrc or pDst is NULL.
+ * - pDst is not 4-byte aligned.
+ * - QP is not in the range of [0-51].
+ *
+ */
+
+OMXResult omxVCM4P10_TransformDequantChromaDCFromPair(
+ const OMX_U8 **ppSrc,
+ OMX_S16* pDst,
+ OMX_INT QP
+ )
+{
+ armRetArgErrIf(ppSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot4ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(QP<0, OMX_Sts_BadArgErr);
+ armRetArgErrIf(QP>51, OMX_Sts_BadArgErr);
+
+ armVCM4P10_UnpackBlock2x2(ppSrc, pDst);
+ InvTransformDC2x2(pDst);
+ DequantChromaDC2x2(pDst, QP);
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair.c
new file mode 100644
index 0000000..16c8be1
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformDequantLumaDCFromPair.c
@@ -0,0 +1,148 @@
+/* ----------------------------------------------------------------
+ *
+ *
+ * File Name: omxVCM4P10_TransformDequantLumaDCFromPair.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * H.264 inverse quantize and transform module
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/*
+ * Description:
+ * Dequantize Luma DC block
+ */
+
+static void DequantLumaDC4x4(
+ OMX_S16* pDst,
+ OMX_INT QP
+)
+{
+ int Shift = (QP/6)-2 ;
+ int Scale = armVCM4P10_VMatrix[QP%6][0];
+ int i, Round, Value;
+
+ if (Shift >= 0)
+ {
+ for (i=0; i<16; i++)
+ {
+ Value = (pDst[i] * Scale) << Shift;
+ pDst[i] = (OMX_S16)Value;
+ }
+ }
+ else
+ {
+ Shift = -Shift;;
+ Round = 1<<(Shift-1);
+
+ for (i=0; i<16; i++)
+ {
+ Value = (pDst[i] * Scale + Round) >> Shift;
+ pDst[i] = (OMX_S16)Value;
+ }
+ }
+}
+
+
+
+/*
+ * Description:
+ * Inverse Transform DC 4x4 Coefficients
+ */
+static void InvTransformDC4x4(OMX_S16* pData)
+{
+ int i;
+
+ /* Transform rows */
+ for (i=0; i<16; i+=4)
+ {
+ int c0 = pData[i+0];
+ int c1 = pData[i+1];
+ int c2 = pData[i+2];
+ int c3 = pData[i+3];
+ pData[i+0] = (OMX_S16)(c0+c1+c2+c3);
+ pData[i+1] = (OMX_S16)(c0+c1-c2-c3);
+ pData[i+2] = (OMX_S16)(c0-c1-c2+c3);
+ pData[i+3] = (OMX_S16)(c0-c1+c2-c3);
+ }
+
+ /* Transform columns */
+ for (i=0; i<4; i++)
+ {
+ int c0 = pData[i+0];
+ int c1 = pData[i+4];
+ int c2 = pData[i+8];
+ int c3 = pData[i+12];
+ pData[i+0] = (OMX_S16)(c0+c1+c2+c3);
+ pData[i+4] = (OMX_S16)(c0+c1-c2-c3);
+ pData[i+8] = (OMX_S16)(c0-c1-c2+c3);
+ pData[i+12] = (OMX_S16)(c0-c1+c2-c3);
+ }
+}
+
+
+/**
+ * Function: omxVCM4P10_TransformDequantLumaDCFromPair (6.3.4.2.1)
+ *
+ * Description:
+ * Reconstructs the 4x4 LumaDC block from the coefficient-position pair
+ * buffer, performs integer inverse, and dequantization for 4x4 LumaDC
+ * coefficients, and updates the pair buffer pointer to the next non-empty
+ * block.
+ *
+ * Input Arguments:
+ *
+ * ppSrc - Double pointer to residual coefficient-position pair buffer
+ * output by CALVC decoding
+ * QP - Quantization parameter QpY
+ *
+ * Output Arguments:
+ *
+ * ppSrc - *ppSrc is updated to the start of next non empty block
+ * pDst - Pointer to the reconstructed 4x4 LumaDC coefficients buffer; must
+ * be aligned on a 8-byte boundary.
+ *
+ * Return Value:
+ * OMX_Sts_NoErr, if the function runs without error.
+ * OMX_Sts_BadArgErr - bad arguments: if one of the following cases occurs:
+ * - ppSrc or pDst is NULL.
+ * - pDst is not 8 byte aligned.
+ * - QP is not in the range of [0-51].
+ *
+ */
+
+OMXResult omxVCM4P10_TransformDequantLumaDCFromPair(
+ const OMX_U8 **ppSrc,
+ OMX_S16* pDst,
+ OMX_INT QP
+ )
+{
+ armRetArgErrIf(ppSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot8ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(QP<0, OMX_Sts_BadArgErr);
+ armRetArgErrIf(QP>51, OMX_Sts_BadArgErr);
+
+ armVCM4P10_UnpackBlock4x4(ppSrc, pDst);
+ /*InvTransformDequantLumaDC4x4(pDst, QP);*/
+ InvTransformDC4x4(pDst);
+ DequantLumaDC4x4(pDst, QP);
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_ChromaDC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_ChromaDC.c
new file mode 100644
index 0000000..b5544dd
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_ChromaDC.c
@@ -0,0 +1,97 @@
+/**
+ *
+ * File Name: omxVCM4P10_TransformQuant_ChromaDC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate 4x4 hadamard transform of chroma DC
+ * coefficients and quantization
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P10_TransformQuant_ChromaDC (6.3.5.6.1)
+ *
+ * Description:
+ * This function performs 2x2 Hadamard transform of chroma DC coefficients
+ * and then quantizes the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the 2x2 array of chroma DC coefficients. 8-byte
+ * alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ * bIntra - Indicate whether this is an INTRA block. 1-INTRA, 0-INTER
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - Pointer to transformed and quantized coefficients. 8-byte
+ * alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL:
+ * pSrcDst
+ * - pSrcDst is not aligned on an 8-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_TransformQuant_ChromaDC(
+ OMX_S16* pSrcDst,
+ OMX_U32 iQP,
+ OMX_U8 bIntra
+)
+{
+ OMX_INT i, j;
+ OMX_S32 m[2][2];
+ OMX_S32 Value;
+ OMX_S32 QbitsPlusOne, Two_f, MF00;
+
+ /* Check for argument error */
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot8ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(iQP > 51, OMX_Sts_BadArgErr);
+
+ /* Hadamard Transform for 2x2 block */
+ m[0][0] = pSrcDst[0] + pSrcDst[1] + pSrcDst[2] + pSrcDst[3];
+ m[0][1] = pSrcDst[0] - pSrcDst[1] + pSrcDst[2] - pSrcDst[3];
+ m[1][0] = pSrcDst[0] + pSrcDst[1] - pSrcDst[2] - pSrcDst[3];
+ m[1][1] = pSrcDst[0] - pSrcDst[1] - pSrcDst[2] + pSrcDst[3];
+
+ /* Quantization */
+ QbitsPlusOne = ARM_M4P10_Q_OFFSET + 1 + (iQP / 6); /*floor (QP/6)*/
+ MF00 = armVCM4P10_MFMatrix [iQP % 6][0];
+
+ Two_f = (1 << QbitsPlusOne) / (bIntra ? 3 : 6); /* 3->INTRA, 6->INTER */
+
+ /* Scaling */
+ for (j = 0; j < 2; j++)
+ {
+ for (i = 0; i < 2; i++)
+ {
+ Value = (armAbs(m[j][i]) * MF00 + Two_f) >> QbitsPlusOne;
+ pSrcDst[j * 2 + i] = (OMX_S16)((m[j][i] < 0) ? -Value : Value);
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_LumaDC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_LumaDC.c
new file mode 100644
index 0000000..2ccf7f0
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p10/src/omxVCM4P10_TransformQuant_LumaDC.c
@@ -0,0 +1,119 @@
+/**
+ *
+ * File Name: omxVCM4P10_TransformQuant_LumaDC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * This function will calculate 4x4 hadamard transform of luma DC coefficients
+ * and quantization
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P10_TransformQuant_LumaDC (6.3.5.6.2)
+ *
+ * Description:
+ * This function performs a 4x4 Hadamard transform of luma DC coefficients
+ * and then quantizes the coefficients.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - Pointer to the 4x4 array of luma DC coefficients. 16-byte
+ * alignment required.
+ * iQP - Quantization parameter; must be in the range [0,51].
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - Pointer to transformed and quantized coefficients. 16-byte
+ * alignment required.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned if any of the following
+ * conditions are true:
+ * - at least one of the following pointers is NULL: pSrcDst
+ * - pSrcDst is not aligned on an 16-byte boundary
+ *
+ */
+OMXResult omxVCM4P10_TransformQuant_LumaDC(
+ OMX_S16* pSrcDst,
+ OMX_U32 iQP
+)
+{
+ OMX_INT i, j;
+ OMX_S32 m1[4][4], m2[4][4];
+ OMX_S32 Value;
+ OMX_U32 QbitsPlusOne, Two_f, MF;
+
+ /* Check for argument error */
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(armNot16ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(iQP > 51, OMX_Sts_BadArgErr);
+
+ /* Hadamard Transform for 4x4 block */
+ /* Horizontal Hadamard */
+ for (i = 0; i < 4; i++)
+ {
+ j = i * 4;
+
+ m1[i][0] = pSrcDst[j + 0] + pSrcDst[j + 2]; /* a+c */
+ m1[i][1] = pSrcDst[j + 1] + pSrcDst[j + 3]; /* b+d */
+ m1[i][2] = pSrcDst[j + 0] - pSrcDst[j + 2]; /* a-c */
+ m1[i][3] = pSrcDst[j + 1] - pSrcDst[j + 3]; /* b-d */
+
+ m2[i][0] = m1[i][0] + m1[i][1]; /* a+b+c+d */
+ m2[i][1] = m1[i][2] + m1[i][3]; /* a+b-c-d */
+ m2[i][2] = m1[i][2] - m1[i][3]; /* a-b-c+d */
+ m2[i][3] = m1[i][0] - m1[i][1]; /* a-b+c-d */
+
+ }
+
+ /* Vertical */
+ for (i = 0; i < 4; i++)
+ {
+ m1[0][i] = m2[0][i] + m2[2][i];
+ m1[1][i] = m2[1][i] + m2[3][i];
+ m1[2][i] = m2[0][i] - m2[2][i];
+ m1[3][i] = m2[1][i] - m2[3][i];
+
+ m2[0][i] = m1[0][i] + m1[1][i];
+ m2[1][i] = m1[2][i] + m1[3][i];
+ m2[2][i] = m1[2][i] - m1[3][i];
+ m2[3][i] = m1[0][i] - m1[1][i];
+ }
+
+
+ /* Quantization */
+ QbitsPlusOne = ARM_M4P10_Q_OFFSET + 1 + (iQP / 6); /*floor (QP/6)*/
+ Two_f = (1 << QbitsPlusOne) / 3; /* 3->INTRA, 6->INTER */
+ MF = armVCM4P10_MFMatrix [iQP % 6][0];
+
+ /* Scaling */
+ for (j = 0; j < 4; j++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ Value = (armAbs((m2[j][i]/* + 1*/) / 2) * MF + Two_f) >> QbitsPlusOne;
+ pSrcDst[j * 4 + i] = (OMX_S16)((m2[j][i] < 0) ? -Value : Value);
+ }
+ }
+ return OMX_Sts_NoErr;
+}
+
+/*****************************************************************************
+ * END OF FILE
+ *****************************************************************************/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_DCT_Table.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_DCT_Table.h
new file mode 100644
index 0000000..3255b61
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_DCT_Table.h
@@ -0,0 +1,30 @@
+/**
+ *
+ * File Name: armVCM4P2_DCT_Table.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ *
+ * File: armVCM4P2_DCT_Table.h
+ * Description: Declares Tables used for DCT/IDCT module
+ * in MP4P2 codec.
+ *
+ */
+
+#ifndef _OMXDCTTAB_H_
+#define _OMXDCTTAB_H_
+
+extern const OMX_F64 armVCM4P2_preCalcDCTCos[8][8];
+
+#endif /* _OMXDCTTAB_H_ */
+
+
+/* End of file */
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
new file mode 100644
index 0000000..92ecc05
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_Huff_Tables_VLC.h
@@ -0,0 +1,42 @@
+/**
+ *
+ * File Name: armVCM4P2_Huff_Tables_VLC.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ *
+ * File: armVCM4P2_Huff_Tables.h
+ * Description: Declares Tables used for Hufffman coding and decoding
+ * in MP4P2 codec.
+ *
+ */
+
+#ifndef _OMXHUFFTAB_H_
+#define _OMXHUFFTAB_H_
+
+extern const OMX_U8 armVCM4P2_IntraL0RunIdx[11];
+extern const ARM_VLC32 armVCM4P2_IntraVlcL0[68];
+extern const OMX_U8 armVCM4P2_IntraL1RunIdx[7];
+extern const ARM_VLC32 armVCM4P2_IntraVlcL1[36];
+extern const OMX_U8 armVCM4P2_IntraL0LMAX[15];
+extern const OMX_U8 armVCM4P2_IntraL1LMAX[21];
+extern const OMX_U8 armVCM4P2_IntraL0RMAX[27];
+extern const OMX_U8 armVCM4P2_IntraL1RMAX[8];
+extern const OMX_U8 armVCM4P2_InterL0RunIdx[12];
+extern const ARM_VLC32 armVCM4P2_InterVlcL0[59];
+extern const OMX_U8 armVCM4P2_InterL1RunIdx[3];
+extern const ARM_VLC32 armVCM4P2_InterVlcL1[45];
+extern const OMX_U8 armVCM4P2_InterL0LMAX[27];
+extern const OMX_U8 armVCM4P2_InterL1LMAX[41];
+extern const OMX_U8 armVCM4P2_InterL0RMAX[12];
+extern const OMX_U8 armVCM4P2_InterL1RMAX[3];
+extern const ARM_VLC32 armVCM4P2_aIntraDCLumaIndex[14];
+extern const ARM_VLC32 armVCM4P2_aIntraDCChromaIndex[14];
+extern const ARM_VLC32 armVCM4P2_aVlcMVD[66];
+
+#endif /* _OMXHUFFTAB_H_ */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
new file mode 100644
index 0000000..c75ed89
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/api/armVCM4P2_ZigZag_Tables.h
@@ -0,0 +1,25 @@
+/**
+ *
+ * File Name: armVCM4P2_ZigZag_Tables.h
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ *
+ * File: armVCM4P2_Zigzag_Tables.h
+ * Description: Declares Tables used for Zigzag scan in MP4P2 codec.
+ *
+ */
+
+#ifndef _OMXZIGZAGTAB_H_
+#define _OMXZIGZAGTAB_H_
+
+extern const OMX_U8 armVCM4P2_aClassicalZigzagScan [64];
+extern const OMX_U8 armVCM4P2_aHorizontalZigzagScan [64];
+extern const OMX_U8 armVCM4P2_aVerticalZigzagScan [64];
+
+#endif /* _OMXZIGZAGTAB_H_ */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_ACDCPredict.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_ACDCPredict.c
new file mode 100644
index 0000000..b6a396a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_ACDCPredict.c
@@ -0,0 +1,253 @@
+/**
+ *
+ * File Name: armVCM4P2_ACDCPredict.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for DC/AC coefficient prediction
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: armVCM4P2_ACDCPredict
+ *
+ * Description:
+ * Performs adaptive DC/AC coefficient prediction for an intra block. Prior
+ * to the function call, prediction direction (predDir) should be selected
+ * as specified in subclause 7.4.3.1 of ISO/IEC 14496-2.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcDst pointer to the coefficient buffer which contains
+ * the quantized coefficient residuals (PQF) of the
+ * current block
+ * [in] pPredBufRow pointer to the coefficient row buffer
+ * [in] pPredBufCol pointer to the coefficient column buffer
+ * [in] curQP quantization parameter of the current block. curQP
+ * may equal to predQP especially when the current
+ * block and the predictor block are in the same
+ * macroblock.
+ * [in] predQP quantization parameter of the predictor block
+ * [in] predDir indicates the prediction direction which takes one
+ * of the following values:
+ * OMX_VC_HORIZONTAL predict horizontally
+ * OMX_VC_VERTICAL predict vertically
+ * [in] ACPredFlag a flag indicating if AC prediction should be
+ * performed. It is equal to ac_pred_flag in the bit
+ * stream syntax of MPEG-4
+ * [in] videoComp video component type (luminance, chrominance or
+ * alpha) of the current block
+ * [in] flag This flag defines the if one wants to use this functions to
+ * calculate PQF (set 1, prediction) or QF (set 0, reconstruction)
+ * [out] pPreACPredict pointer to the predicted coefficients buffer.
+ * Filled ONLY if it is not NULL
+ * [out] pSrcDst pointer to the coefficient buffer which contains
+ * the quantized coefficients (QF) of the current
+ * block
+ * [out] pPredBufRow pointer to the updated coefficient row buffer
+ * [out] pPredBufCol pointer to the updated coefficient column buffer
+ * [out] pSumErr pointer to the updated sum of the difference
+ * between predicted and unpredicted coefficients
+ * If this is NULL, do not update
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_ACDCPredict(
+ OMX_S16 * pSrcDst,
+ OMX_S16 * pPreACPredict,
+ OMX_S16 * pPredBufRow,
+ OMX_S16 * pPredBufCol,
+ OMX_INT curQP,
+ OMX_INT predQP,
+ OMX_INT predDir,
+ OMX_INT ACPredFlag,
+ OMXVCM4P2VideoComponent videoComp,
+ OMX_U8 flag,
+ OMX_INT *pSumErr
+)
+{
+ OMX_INT dcScaler, i;
+ OMX_S16 tempPred;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pPredBufRow == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pPredBufCol == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(curQP <= 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf(predQP <= 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf((predDir != 1) && (predDir != 2), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs4ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs4ByteAligned(pPredBufRow), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs4ByteAligned(pPredBufCol), OMX_Sts_BadArgErr);
+
+
+ /* Set DC scaler value to avoid some compilers giving a warning. */
+ dcScaler=0;
+
+ /* Calculate the DC scaler value */
+ if (videoComp == OMX_VC_LUMINANCE)
+ {
+ if (curQP >= 1 && curQP <= 4)
+ {
+ dcScaler = 8;
+ }
+ else if (curQP >= 5 && curQP <= 8)
+ {
+ dcScaler = 2 * curQP;
+ }
+ else if (curQP >= 9 && curQP <= 24)
+ {
+ dcScaler = curQP + 8;
+ }
+ else
+ {
+ dcScaler = (2 * curQP) - 16;
+ }
+ }
+ else if (videoComp == OMX_VC_CHROMINANCE)
+ {
+ if (curQP >= 1 && curQP <= 4)
+ {
+ dcScaler = 8;
+ }
+ else if (curQP >= 5 && curQP <= 24)
+ {
+ dcScaler = (curQP + 13)/2;
+ }
+ else
+ {
+ dcScaler = curQP - 6;
+ }
+ }
+
+ if (pPreACPredict != NULL)
+ {
+ pPreACPredict[0] = predDir;
+ }
+
+ if (predDir == OMX_VC_VERTICAL)
+ {
+ /* F[0][0]//dc_scaler */
+ tempPred = armIntDivAwayFromZero(pPredBufRow[0], dcScaler);
+ }
+ else
+ {
+ /* F[0][0]//dc_scaler */
+ tempPred = armIntDivAwayFromZero(pPredBufCol[0], dcScaler);
+ }
+
+ /* Updating the DC value to the row and col buffer */
+ *(pPredBufRow - 8) = *pPredBufCol;
+
+ if (flag)
+ {
+ /* Cal and store F[0][0] into the col buffer */
+ *pPredBufCol = pSrcDst[0] * dcScaler;
+
+ /* PQF = QF - F[0][0]//dc_scaler */
+ pSrcDst[0] -= tempPred;
+ }
+ else
+ {
+ /* QF = PQF + F[0][0]//dc_scaler */
+ pSrcDst[0] += tempPred;
+
+ /* Saturate */
+ pSrcDst[0] = armClip (-2048, 2047, pSrcDst[0]);
+
+ /* Cal and store F[0][0] into the col buffer */
+ *pPredBufCol = pSrcDst[0] * dcScaler;
+ }
+
+
+ if (ACPredFlag == 1)
+ {
+ if (predDir == OMX_VC_VERTICAL)
+ {
+ for (i = 1; i < 8; i++)
+ {
+ tempPred = armIntDivAwayFromZero \
+ (pPredBufRow[i] * predQP, curQP);
+ if (flag)
+ {
+ /* Updating QF to the row buff */
+ pPredBufRow[i] = pSrcDst[i];
+ /*PQFX[v][0] = QFX[v][0] - (QFA[v][0] * QPA) // QPX */
+ pSrcDst[i] -= tempPred;
+ /* Sum of absolute values of AC prediction error, this can
+ be used as a reference to choose whether to use
+ AC prediction */
+ *pSumErr += armAbs(pSrcDst[i]);
+ /* pPreACPredict[1~7] store the error signal
+ after AC prediction */
+ pPreACPredict[i] = pSrcDst[i];
+ }
+ else
+ {
+ /*QFX[v][0] = PQFX[v][0] + (QFA[v][0] * QPA) // QPX */
+ pSrcDst[i] += tempPred;
+
+ /* Saturate */
+ pSrcDst[i] = armClip (-2048, 2047, pSrcDst[i]);
+
+ /* Updating QF to the row buff */
+ pPredBufRow[i] = pSrcDst[i];
+ }
+ }
+ }
+ else
+ {
+ for (i = 8; i < 64; i += 8)
+ {
+ tempPred = armIntDivAwayFromZero \
+ (pPredBufCol[i>>3] * predQP, curQP);
+ if (flag)
+ {
+ /* Updating QF to col buff */
+ pPredBufCol[i>>3] = pSrcDst[i];
+ /*PQFX[0][u] = QFX[0][u] - (QFA[0][u] * QPA) // QPX */
+ pSrcDst[i] -= tempPred;
+ /* Sum of absolute values of AC prediction error, this can
+ be used as a reference to choose whether to use AC
+ prediction */
+ *pSumErr += armAbs(pSrcDst[i]);
+ /* pPreACPredict[1~7] store the error signal
+ after AC prediction */
+ pPreACPredict[i>>3] = pSrcDst[i];
+ }
+ else
+ {
+ /*QFX[0][u] = PQFX[0][u] + (QFA[0][u] * QPA) // QPX */
+ pSrcDst[i] += tempPred;
+
+ /* Saturate */
+ pSrcDst[i] = armClip (-2048, 2047, pSrcDst[i]);
+
+ /* Updating QF to col buff */
+ pPredBufCol[i>>3] = pSrcDst[i];
+ }
+ }
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/*End of File*/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Half.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Half.c
new file mode 100644
index 0000000..1b69a33
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Half.c
@@ -0,0 +1,187 @@
+/**
+ *
+ * File Name: armVCM4P2_BlockMatch_Half.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for Block matching, a full search algorithm
+ * is implemented
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: armVCM4P2_BlockMatch_Half
+ *
+ * Description:
+ * Performs a 16x16 block match with half-pixel resolution. Returns the estimated
+ * motion vector and associated minimum SAD. This function estimates the half-pixel
+ * motion vector by interpolating the integer resolution motion vector referenced
+ * by the input parameter pSrcDstMV, i.e., the initial integer MV is generated
+ * externally. The input parameters pSrcRefBuf and pSearchPointRefPos should be
+ * shifted by the winning MV of 16x16 integer search prior to calling BlockMatch_Half_16x16.
+ * The function BlockMatch_Integer_16x16 may be used for integer motion estimation.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcRefBuf pointer to the reference Y plane; points to the reference MB
+ * that corresponds to the location of the current macroblock in
+ * the current plane.
+ * [in] refWidth width of the reference plane
+ * [in] pRefRect reference plane valid region rectangle
+ * [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane
+ * (linear array, 256 entries); must be aligned on an 8-byte boundary.
+ * [in] pSearchPointRefPos position of the starting point for half pixel search (specified
+ * in terms of integer pixel units) in the reference plane.
+ * [in] rndVal rounding control bit for half pixel motion estimation;
+ * 0=rounding control disabled; 1=rounding control enabled
+ * [in] pSrcDstMV pointer to the initial MV estimate; typically generated during a prior
+ * 16X16 integer search and its unit is half pixel.
+ * [in] BlockSize MacroBlock Size i.e either 16x16 or 8x8.
+ * [out]pSrcDstMV pointer to estimated MV
+ * [out]pDstSAD pointer to minimum SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr ¨C no error
+ * OMX_Sts_BadArgErr ¨C bad arguments
+ *
+ */
+
+OMXResult armVCM4P2_BlockMatch_Half(
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pSearchPointRefPos,
+ OMX_INT rndVal,
+ OMXVCMotionVector *pSrcDstMV,
+ OMX_INT *pDstSAD,
+ OMX_U8 BlockSize
+)
+{
+ OMX_INT outer, inner, count, index;
+ OMX_S16 halfPelX = 0, halfPelY = 0, x, y;
+ OMX_INT candSAD, refSAD = 0;
+ OMX_INT minSAD, fromX, toX, fromY, toY;
+ /* Offset to the reference at the begining of the bounding box */
+ const OMX_U8 *pTempSrcRefBuf;
+ OMX_U8 tempPel;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrcRefBuf == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSearchPointRefPos == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcDstMV == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr);
+
+ /* Positioning the pointer */
+ pTempSrcRefBuf = pSrcRefBuf + (refWidth * (pSrcDstMV->dy/2)) + (pSrcDstMV->dx/2);
+
+ /* Copy the candidate to the temporary linear array */
+ for (outer = 0, count = 0,index = 0;
+ outer < BlockSize;
+ outer++, index += refWidth - BlockSize)
+ {
+ for (inner = 0; inner < BlockSize; inner++, count++, index++)
+ {
+ refSAD += armAbs (pTempSrcRefBuf[index] - pSrcCurrBuf[count]);
+ }
+ }
+
+ /* Set the minSad as reference SAD */
+ minSAD = refSAD;
+ *pDstSAD = refSAD;
+
+ /* Check for valid region */
+ fromX = 1;
+ toX = 1;
+ fromY = 1;
+ toY = 1;
+ if ((pSearchPointRefPos->x - 1) < pRefRect->x)
+ {
+ fromX = 0;
+ }
+
+ if ((pSearchPointRefPos->x + BlockSize + 1) > (pRefRect->x + pRefRect->width))
+ {
+ toX = 0;
+ }
+
+ if ((pSearchPointRefPos->y - 1) < pRefRect->y)
+ {
+ fromY = 0;
+ }
+
+ if ((pSearchPointRefPos->y + BlockSize + 1) > (pRefRect->y + pRefRect->height))
+ {
+ toY = 0;
+ }
+
+ /* Looping on y- axis */
+ for (y = -fromY; y <= toY; y++)
+ {
+ /* Looping on x- axis */
+ for (x = -fromX; x <= toX; x++)
+ {
+ /* check for integer position */
+ if ( x == 0 && y == 0)
+ {
+ continue;
+ }
+ /* Positioning the pointer */
+ pTempSrcRefBuf = pSrcRefBuf + (refWidth * (pSrcDstMV->dy/2))
+ + (pSrcDstMV->dx/2);
+
+ /* Interpolate the pixel and calculate the SAD*/
+ for (outer = 0, count = 0, candSAD = 0,index = 0;
+ outer < BlockSize;
+ outer++, index += refWidth - BlockSize)
+ {
+ for (inner = 0; inner < BlockSize; inner++, count++,index++)
+ {
+ tempPel = (
+ pTempSrcRefBuf[index]
+ + pTempSrcRefBuf[index + x] * armAbs(x)
+ + pTempSrcRefBuf[index + refWidth * y] * armAbs(y)
+ + pTempSrcRefBuf[index + refWidth * y + x]
+ * armAbs(x*y)
+ + armAbs (x) + armAbs (y) - rndVal
+ ) / (2 * (armAbs (x) + armAbs (y)));
+ candSAD += armAbs (tempPel - pSrcCurrBuf[count]);
+ }
+ }
+
+ /* Result calculations */
+ if (armVCM4P2_CompareMV (x, y, candSAD, halfPelX, halfPelY, minSAD))
+ {
+ *pDstSAD = candSAD;
+ minSAD = candSAD;
+ halfPelX = x;
+ halfPelY = y;
+ }
+
+ } /* End of x- axis */
+ } /* End of y-axis */
+
+ pSrcDstMV->dx += halfPelX;
+ pSrcDstMV->dy += halfPelY;
+
+ return OMX_Sts_NoErr;
+
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Integer.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Integer.c
new file mode 100644
index 0000000..77fe358
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_BlockMatch_Integer.c
@@ -0,0 +1,167 @@
+/**
+ *
+ * File Name: armVCM4P2_BlockMatch_Integer.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for Block matching, a full search algorithm
+ * is implemented
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: armVCM4P2_BlockMatch_Integer
+ *
+ * Description:
+ * Performs a 16x16 block search; estimates motion vector and associated minimum SAD.
+ * Both the input and output motion vectors are represented using half-pixel units, and
+ * therefore a shift left or right by 1 bit may be required, respectively, to match the
+ * input or output MVs with other functions that either generate output MVs or expect
+ * input MVs represented using integer pixel units.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcRefBuf pointer to the reference Y plane; points to the reference MB that
+ * corresponds to the location of the current macroblock in the current
+ * plane.
+ * [in] refWidth width of the reference plane
+ * [in] pRefRect pointer to the valid rectangular in reference plane. Relative to image origin.
+ * It's not limited to the image boundary, but depended on the padding. For example,
+ * if you pad 4 pixels outside the image border, then the value for left border
+ * can be -4
+ * [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane (linear array,
+ * 256 entries); must be aligned on an 8-byte boundary.
+ * [in] pCurrPointPos position of the current macroblock in the current plane
+ * [in] pSrcPreMV pointer to predicted motion vector; NULL indicates no predicted MV
+ * [in] pSrcPreSAD pointer to SAD associated with the predicted MV (referenced by pSrcPreMV)
+ * [in] searchRange search range for 16X16 integer block,the units of it is full pixel,the search range
+ * is the same in all directions.It is in inclusive of the boundary and specified in
+ * terms of integer pixel units.
+ * [in] pMESpec vendor-specific motion estimation specification structure; must have been allocated
+ * and then initialized using omxVCM4P2_MEInit prior to calling the block matching
+ * function.
+ * [out] pDstMV pointer to estimated MV
+ * [out] pDstSAD pointer to minimum SAD
+ *
+ * Return Value:
+ * OMX_Sts_NoErr ¨C no error.
+ * OMX_Sts_BadArgErr ¨C bad arguments
+ *
+ */
+
+OMXResult armVCM4P2_BlockMatch_Integer(
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCMotionVector *pSrcPreMV,
+ const OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector *pDstMV,
+ OMX_INT *pDstSAD,
+ OMX_U8 BlockSize
+)
+{
+
+ /* Definitions and Initializations*/
+
+ OMX_INT outer, inner, count,index;
+ OMX_INT candSAD;
+ /*(256*256 +1) this is to make the SAD max initially*/
+ OMX_INT minSAD = 0x10001, fromX, toX, fromY, toY;
+ /* Offset to the reference at the begining of the bounding box */
+ const OMX_U8 *pTempSrcRefBuf;
+ OMX_S16 x, y;
+ OMX_INT searchRange;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrcRefBuf == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pCurrPointPos == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pMESpec == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDstMV == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr);
+
+ searchRange = ((OMXVCM4P2MEParams *)pMESpec)->searchRange;
+ /* Check for valid region */
+ fromX = searchRange;
+ toX = searchRange;
+ fromY = searchRange;
+ toY = searchRange;
+
+ if ((pCurrPointPos->x - searchRange) < pRefRect->x)
+ {
+ fromX = pCurrPointPos->x - pRefRect->x;
+ }
+
+ if ((pCurrPointPos->x + BlockSize + searchRange) > (pRefRect->x + pRefRect->width))
+ {
+ toX = pRefRect->width - (pCurrPointPos->x - pRefRect->x) - BlockSize;
+ }
+
+ if ((pCurrPointPos->y - searchRange) < pRefRect->y)
+ {
+ fromY = pCurrPointPos->y - pRefRect->y;
+ }
+
+ if ((pCurrPointPos->y + BlockSize + searchRange) > (pRefRect->y + pRefRect->height))
+ {
+ toY = pRefRect->width - (pCurrPointPos->y - pRefRect->y) - BlockSize;
+ }
+
+ pDstMV->dx = -fromX;
+ pDstMV->dy = -fromY;
+ /* Looping on y- axis */
+ for (y = -fromY; y <= toY; y++)
+ {
+
+ /* Looping on x- axis */
+ for (x = -fromX; x <= toX; x++)
+ {
+ /* Positioning the pointer */
+ pTempSrcRefBuf = pSrcRefBuf + (refWidth * y) + x;
+
+ /* Calculate the SAD */
+ for (outer = 0, count = 0, index = 0, candSAD = 0;
+ outer < BlockSize;
+ outer++, index += refWidth - BlockSize)
+ {
+ for (inner = 0; inner < BlockSize; inner++, count++, index++)
+ {
+ candSAD += armAbs (pTempSrcRefBuf[index] - pSrcCurrBuf[count]);
+ }
+ }
+
+ /* Result calculations */
+ if (armVCM4P2_CompareMV (x, y, candSAD, pDstMV->dx/2, pDstMV->dy/2, minSAD))
+ {
+ *pDstSAD = candSAD;
+ minSAD = candSAD;
+ pDstMV->dx = x*2;
+ pDstMV->dy = y*2;
+ }
+
+ } /* End of x- axis */
+ } /* End of y-axis */
+
+ return OMX_Sts_NoErr;
+
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CheckVLCEscapeMode.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CheckVLCEscapeMode.c
new file mode 100644
index 0000000..94e8639
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CheckVLCEscapeMode.c
@@ -0,0 +1,156 @@
+/**
+ *
+ * File Name: armVCM4P2_CheckVLCEscapeMode.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for VLC escape mode check
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: armVCM4P2_CheckVLCEscapeMode
+ *
+ * Description:
+ * Performs escape mode decision based on the run, run+, level, level+ and
+ * last combinations.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] run Run value (count of zeros) to be encoded
+ * [in] level Level value (non-zero value) to be encoded
+ * [in] runPlus Calculated as runPlus = run - (RMAX + 1)
+ * [in] levelPlus Calculated as
+ * levelPlus = sign(level)*[abs(level) - LMAX]
+ * [in] maxStoreRun Max store possible (considering last and inter/intra)
+ * [in] maxRunForMultipleEntries
+ * The run value after which level
+ * will be equal to 1:
+ * (considering last and inter/intra status)
+ * [in] pRunIndexTable Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c
+ * (considering last and inter/intra status)
+ *
+ *
+ * Return Value:
+ * Returns an Escape mode which can take values from 0 to 3
+ * 0 --> no escape mode, 1 --> escape type 1,
+ * 1 --> escape type 2, 3 --> escape type 3, check section 7.4.1.3
+ * in the MPEG ISO standard.
+ *
+ */
+
+OMX_U8 armVCM4P2_CheckVLCEscapeMode(
+ OMX_U32 run,
+ OMX_U32 runPlus,
+ OMX_S16 level,
+ OMX_S16 levelPlus,
+ OMX_U8 maxStoreRun,
+ OMX_U8 maxRunForMultipleEntries,
+ OMX_INT shortVideoHeader,
+ const OMX_U8 *pRunIndexTable
+)
+{
+ OMX_U8 escape = 0, fMode = 0, entries;
+
+ level = armAbs (level);
+ levelPlus = armAbs (levelPlus);
+
+ /* Check for a valid entry with run, level and Last combination
+ Mode 0 check */
+ if (run <= maxStoreRun)
+ {
+ entries = pRunIndexTable[run + 1]
+ - pRunIndexTable[run];
+ if (run > maxRunForMultipleEntries)
+ {
+ entries = 1;
+ }
+ if (level > entries)
+ {
+ escape = 1;
+ }
+ }
+ else
+ {
+ escape = 1;
+ }
+ if(escape && shortVideoHeader)
+ {
+ escape = 0;
+ fMode = 4;
+ }
+ /* Check for a valid entry with run, levelPlus and Last combination
+ Mode 1 check */
+ if (escape)
+ {
+ escape = 0;
+ fMode = 1;
+ if (run <= maxStoreRun)
+ {
+ entries = pRunIndexTable[run + 1]
+ - pRunIndexTable[run];
+ if (run > maxRunForMultipleEntries)
+ {
+ entries = 1;
+ }
+ if (levelPlus > entries)
+ {
+ escape = 1;
+ }
+ }
+ else
+ {
+ escape = 1;
+ }
+ }
+
+ /* Check for a valid entry with runPlus, level and Last combination
+ Mode 2 check */
+ if (escape)
+ {
+ escape = 0;
+ fMode = 2;
+ if (runPlus <= maxStoreRun)
+ {
+ entries = pRunIndexTable[runPlus + 1]
+ - pRunIndexTable[runPlus];
+ if (runPlus > maxRunForMultipleEntries)
+ {
+ entries = 1;
+ }
+ if (level > entries)
+ {
+ escape = 1;
+ }
+ }
+ else
+ {
+ escape = 1;
+ }
+ }
+
+ /* select mode 3 --> FLC */
+ if (escape)
+ {
+ fMode = 3;
+ }
+
+ return fMode;
+}
+
+/*End of File*/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CompareMV.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CompareMV.c
new file mode 100644
index 0000000..3b8845e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_CompareMV.c
@@ -0,0 +1,71 @@
+/**
+ *
+ * File Name: armVCM4P2_CompareMV.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for comparing motion vectors and SAD's to decide
+ * the best MV and SAD
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: armVCM4P2_CompareMV
+ *
+ * Description:
+ * Performs comparision of motion vectors and SAD's to decide the
+ * best MV and SAD
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] mvX x coordinate of the candidate motion vector
+ * [in] mvY y coordinate of the candidate motion vector
+ * [in] candSAD Candidate SAD
+ * [in] bestMVX x coordinate of the best motion vector
+ * [in] bestMVY y coordinate of the best motion vector
+ * [in] bestSAD best SAD
+ *
+ * Return Value:
+ * OMX_INT -- 1 to indicate that the current sad is the best
+ * 0 to indicate that it is NOT the best SAD
+ */
+
+OMX_INT armVCM4P2_CompareMV (
+ OMX_S16 mvX,
+ OMX_S16 mvY,
+ OMX_INT candSAD,
+ OMX_S16 bestMVX,
+ OMX_S16 bestMVY,
+ OMX_INT bestSAD
+)
+{
+ if (candSAD < bestSAD)
+ {
+ return 1;
+ }
+ if (candSAD > bestSAD)
+ {
+ return 0;
+ }
+ /* shorter motion vector */
+ if ( (mvX * mvX + mvY * mvY) < (bestMVX*bestMVX+bestMVY*bestMVY) )
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*End of File*/
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DCT_Table.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DCT_Table.c
new file mode 100644
index 0000000..a6f713e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DCT_Table.c
@@ -0,0 +1,112 @@
+ /**
+ *
+ * File Name: armVCM4P2_DCT_Table.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armVCM4P2_DCT_Table.c
+ * Description: Contains the DCT/IDCT coefficent matrix
+ *
+ */
+
+#ifndef _OMXDCTCOSTAB_C_
+#define _OMXDCTCOSTAB_C_
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+const OMX_F64 armVCM4P2_preCalcDCTCos[8][8] =
+{
+ {
+ 0.353553390593273730,
+ 0.490392640201615220,
+ 0.461939766255643370,
+ 0.415734806151272620,
+ 0.353553390593273790,
+ 0.277785116509801140,
+ 0.191341716182544920,
+ 0.097545161008064152
+ },
+ {
+ 0.353553390593273730,
+ 0.415734806151272620,
+ 0.191341716182544920,
+ -0.097545161008064096,
+ -0.353553390593273730,
+ -0.490392640201615220,
+ -0.461939766255643420,
+ -0.277785116509801090
+ },
+ {
+ 0.353553390593273730,
+ 0.277785116509801140,
+ -0.191341716182544860,
+ -0.490392640201615220,
+ -0.353553390593273840,
+ 0.097545161008064138,
+ 0.461939766255643260,
+ 0.415734806151272730
+ },
+ {
+ 0.353553390593273730,
+ 0.097545161008064152,
+ -0.461939766255643370,
+ -0.277785116509801090,
+ 0.353553390593273680,
+ 0.415734806151272730,
+ -0.191341716182544920,
+ -0.490392640201615330
+ },
+ {
+ 0.353553390593273730,
+ -0.097545161008064096,
+ -0.461939766255643420,
+ 0.277785116509800920,
+ 0.353553390593273840,
+ -0.415734806151272620,
+ -0.191341716182545280,
+ 0.490392640201615220
+ },
+ {
+ 0.353553390593273730,
+ -0.277785116509800980,
+ -0.191341716182545170,
+ 0.490392640201615220,
+ -0.353553390593273340,
+ -0.097545161008064013,
+ 0.461939766255643370,
+ -0.415734806151272510
+ },
+ {
+ 0.353553390593273730,
+ -0.415734806151272670,
+ 0.191341716182545000,
+ 0.097545161008064388,
+ -0.353553390593273620,
+ 0.490392640201615330,
+ -0.461939766255643200,
+ 0.277785116509800760
+ },
+ {
+ 0.353553390593273730,
+ -0.490392640201615220,
+ 0.461939766255643260,
+ -0.415734806151272620,
+ 0.353553390593273290,
+ -0.277785116509800760,
+ 0.191341716182544780,
+ -0.097545161008064277
+ }
+};
+
+#endif /*_OMXDCTCOSTAB_C_*/
+
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_intra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_intra.c
new file mode 100644
index 0000000..a2572e0
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_DecodeVLCZigzag_intra.c
@@ -0,0 +1,144 @@
+/**
+ *
+ * File Name: armVCM4P2_DecodeVLCZigzag_intra.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for filling of the coefficient buffer
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM_Bitstream.h"
+#include "armCOMM.h"
+#include "armVCM4P2_Huff_Tables_VLC.h"
+#include "armVCM4P2_ZigZag_Tables.h"
+
+
+
+/**
+ * Function: armVCM4P2_DecodeVLCZigzag_Intra
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan for one intra coded block.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bitstream buffer
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * to by *ppBitStream. *pBitOffset is valid within
+ * [0-7].
+ * [in] predDir AC prediction direction which is used to decide
+ * the zigzag scan pattern. It takes one of the
+ * following values:
+ * OMX_VC_NONE AC prediction not used;
+ * perform classical zigzag scan;
+ * OMX_VC_HORIZONTAL Horizontal prediction;
+ * perform alternate-vertical
+ * zigzag scan;
+ * OMX_VC_VERTICAL Vertical prediction;
+ * thus perform
+ * alternate-horizontal
+ * zigzag scan.
+ * [in] start start indicates whether the encoding begins with 0th element
+ * or 1st.
+ * [out] ppBitStream *ppBitStream is updated after the block is
+ * decoded, so that it points to the current byte
+ * in the bit stream buffer
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream
+ * [out] pDst pointer to the coefficient buffer of current
+ * block. Should be 32-bit aligned
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_DecodeVLCZigzag_Intra(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_U8 predDir,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start
+)
+{
+ OMX_U8 last = 0;
+ const OMX_U8 *pZigzagTable = armVCM4P2_aClassicalZigzagScan;
+ OMXResult errorCode;
+
+ /* Argument error checks */
+ armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs4ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf((*pBitOffset < 0) || (*pBitOffset >7), OMX_Sts_BadArgErr);
+ armRetArgErrIf((predDir > 2), OMX_Sts_BadArgErr);
+
+ switch (predDir)
+ {
+ case OMX_VC_NONE:
+ {
+ pZigzagTable = armVCM4P2_aClassicalZigzagScan;
+ break;
+ }
+
+ case OMX_VC_HORIZONTAL:
+ {
+ pZigzagTable = armVCM4P2_aVerticalZigzagScan;
+ break;
+ }
+
+ case OMX_VC_VERTICAL:
+ {
+ pZigzagTable = armVCM4P2_aHorizontalZigzagScan;
+ break;
+ }
+ }
+
+ errorCode = armVCM4P2_GetVLCBits (
+ ppBitStream,
+ pBitOffset,
+ pDst,
+ shortVideoHeader,
+ start,
+ &last,
+ 10,
+ 62,
+ 7,
+ 21,
+ armVCM4P2_IntraL0RunIdx,
+ armVCM4P2_IntraVlcL0,
+ armVCM4P2_IntraL1RunIdx,
+ armVCM4P2_IntraVlcL1,
+ armVCM4P2_IntraL0LMAX,
+ armVCM4P2_IntraL1LMAX,
+ armVCM4P2_IntraL0RMAX,
+ armVCM4P2_IntraL1RMAX,
+ pZigzagTable );
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ if (last == 0)
+ {
+ return OMX_Sts_Err;
+ }
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_EncodeVLCZigzag_intra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_EncodeVLCZigzag_intra.c
new file mode 100644
index 0000000..cd6b56d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_EncodeVLCZigzag_intra.c
@@ -0,0 +1,145 @@
+/**
+ *
+ * File Name: armVCM4P2_EncodeVLCZigzag_intra.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for zigzag scanning and VLC encoding
+ * for intra block.
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM_Bitstream.h"
+#include "armCOMM.h"
+#include "armVCM4P2_Huff_Tables_VLC.h"
+#include "armVCM4P2_ZigZag_Tables.h"
+
+
+
+/**
+ * Function: armVCM4P2_EncodeVLCZigzag_Intra
+ *
+ * Description:
+ * Performs zigzag scanning and VLC encoding for one intra block.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7.
+ * [in] pQDctBlkCoef pointer to the quantized DCT coefficient
+ * [in] predDir AC prediction direction, which is used to decide
+ * the zigzag scan pattern. This takes one of the
+ * following values:
+ * OMX_VC_NONE AC prediction not used.
+ * Performs classical zigzag
+ * scan.
+ * OMX_VC_HORIZONTAL Horizontal prediction.
+ * Performs alternate-vertical
+ * zigzag scan.
+ * OMX_VC_VERTICAL Vertical prediction.
+ * Performs alternate-horizontal
+ * zigzag scan.
+ * [in] pattern block pattern which is used to decide whether
+ * this block is encoded
+ * [in] start start indicates whether the encoding begins with 0th element
+ * or 1st.
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded,
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_EncodeVLCZigzag_Intra(
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 predDir,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start
+)
+{
+ const OMX_U8 *pZigzagTable = armVCM4P2_aClassicalZigzagScan;
+ OMXResult errorCode;
+
+ /* Argument error checks */
+ armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pQDctBlkCoef == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((*pBitOffset < 0) || (*pBitOffset >7), OMX_Sts_BadArgErr);
+ armRetArgErrIf(start > 1, OMX_Sts_BadArgErr);
+ armRetArgErrIf(predDir > 2, OMX_Sts_BadArgErr);
+
+ if (pattern)
+ {
+ switch (predDir)
+ {
+ case OMX_VC_NONE:
+ {
+ pZigzagTable = armVCM4P2_aClassicalZigzagScan;
+ break;
+ }
+
+ case OMX_VC_HORIZONTAL:
+ {
+ pZigzagTable = armVCM4P2_aVerticalZigzagScan;
+ break;
+ }
+
+ case OMX_VC_VERTICAL:
+ {
+ pZigzagTable = armVCM4P2_aHorizontalZigzagScan;
+ break;
+ }
+ }
+
+ errorCode = armVCM4P2_PutVLCBits (
+ ppBitStream,
+ pBitOffset,
+ pQDctBlkCoef,
+ shortVideoHeader,
+ start,
+ 14,
+ 20,
+ 9,
+ 6,
+ armVCM4P2_IntraL0RunIdx,
+ armVCM4P2_IntraVlcL0,
+ armVCM4P2_IntraL1RunIdx,
+ armVCM4P2_IntraVlcL1,
+ armVCM4P2_IntraL0LMAX,
+ armVCM4P2_IntraL1LMAX,
+ armVCM4P2_IntraL0RMAX,
+ armVCM4P2_IntraL1RMAX,
+ pZigzagTable
+ );
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ } /* Pattern check ends*/
+
+ return (OMX_Sts_NoErr);
+
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLCBuffer.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLCBuffer.c
new file mode 100644
index 0000000..93c9504
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLCBuffer.c
@@ -0,0 +1,153 @@
+/**
+ *
+ * File Name: armVCM4P2_FillVLCBuffer.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for putting VLC bits
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+#include "armCOMM_Bitstream.h"
+
+/**
+ * Function: armVCM4P2_FillVLCBuffer
+ *
+ * Description:
+ * Performs calculating the VLC bits depending on the escape type and insert
+ * the same in the bitstream
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7
+ * [in] run Run value (count of zeros) to be encoded
+ * [in] level Level value (non-zero value) to be encoded
+ * [in] runPlus Calculated as runPlus = run - (RMAX + 1)
+ * [in] levelPlus Calculated as
+ * levelPlus = sign(level)*[abs(level) - LMAX]
+ * [in] fMode Flag indicating the escape modes
+ * [in] last status of the last flag
+ * [in] maxRunForMultipleEntries
+ * The run value after which level will be equal to 1:
+ * (considering last and inter/intra status)
+ * [in] pRunIndexTable Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.h
+ * [in] pVlcTable VLC table defined in armVCM4P2_Huff_Tables_VLC.h
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_FillVLCBuffer (
+ OMX_U8 **ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_U32 run,
+ OMX_S16 level,
+ OMX_U32 runPlus,
+ OMX_S16 levelPlus,
+ OMX_U8 fMode,
+ OMX_U8 last,
+ OMX_U8 maxRunForMultipleEntries,
+ const OMX_U8 *pRunIndexTable,
+ const ARM_VLC32 *pVlcTable
+)
+{
+ OMX_INT tempIndex;
+ OMX_U32 tempRun = run, sign = 0;
+ OMX_S16 tempLevel = level;
+
+ /* Escape sequence addition */
+ if (fMode == 1)
+ {
+ armPackBits(ppBitStream, pBitOffset, 3, 7);
+ armPackBits(ppBitStream, pBitOffset, 0, 1);
+ tempLevel = levelPlus;
+
+ }
+ else if(fMode == 2)
+ {
+ armPackBits(ppBitStream, pBitOffset, 3, 7);
+ armPackBits(ppBitStream, pBitOffset, 2, 2);
+ tempRun = runPlus;
+ }
+ else if (fMode == 3)
+ {
+ armPackBits(ppBitStream, pBitOffset, 3, 7);
+ armPackBits(ppBitStream, pBitOffset, 3, 2);
+ }
+ else if (fMode == 4)
+ {
+ armPackBits(ppBitStream, pBitOffset, 3, 7);
+ armPackBits(ppBitStream, pBitOffset, (OMX_U32)last, 1);
+ armPackBits(ppBitStream, pBitOffset, tempRun, 6);
+ if((tempLevel != 0) && (tempLevel != -128))
+ {
+ armPackBits(ppBitStream, pBitOffset,
+ (OMX_U32) tempLevel, 8);
+ }
+ return OMX_Sts_NoErr;
+ }
+
+ if (tempLevel < 0)
+ {
+ sign = 1;
+ tempLevel = armAbs(tempLevel);
+ }
+ /* Putting VLC bits in the stream */
+ if (fMode < 3)
+ {
+ if (tempRun > maxRunForMultipleEntries)
+ {
+ tempIndex = pRunIndexTable [maxRunForMultipleEntries + 1] +
+ (tempRun - maxRunForMultipleEntries - 1);
+ }
+ else
+ {
+ tempIndex = pRunIndexTable [tempRun] + (tempLevel -1);
+ }
+
+ armPackVLC32 (ppBitStream, pBitOffset,
+ pVlcTable [tempIndex]);
+ armPackBits(ppBitStream, pBitOffset, (OMX_U32)sign, 1);
+ }
+ else
+ {
+ if (sign)
+ {
+ tempLevel = -tempLevel;
+ }
+ tempRun = run;
+ armPackBits(ppBitStream, pBitOffset, (OMX_U32)last, 1);
+ armPackBits(ppBitStream, pBitOffset, tempRun, 6);
+ armPackBits(ppBitStream, pBitOffset, 1, 1);
+ armPackBits(ppBitStream, pBitOffset,
+ (OMX_U32) tempLevel, 12);
+ armPackBits(ppBitStream, pBitOffset, 1, 1);
+ }
+ return OMX_Sts_NoErr;
+}
+
+/*End of File*/
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLDBuffer.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLDBuffer.c
new file mode 100644
index 0000000..1712c3a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_FillVLDBuffer.c
@@ -0,0 +1,84 @@
+/**
+ *
+ * File Name: armVCM4P2_FillVLDBuffer.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for VLC get bits from the stream
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armVCM4P2_ZigZag_Tables.h"
+
+
+/**
+ * Function: armVCM4P2_FillVLDBuffer
+ *
+ * Description:
+ * Performs filling of the coefficient buffer according to the run, level
+ * and sign, also updates the index
+ *
+ * Parameters:
+ * [in] storeRun Stored Run value (count of zeros)
+ * [in] storeLevel Stored Level value (non-zero value)
+ * [in] sign Flag indicating the sign of level
+ * [in] last status of the last flag
+ * [in] pIndex pointer to coefficient index in 8x8 matrix
+ * [out] pIndex pointer to updated coefficient index in 8x8
+ * matrix
+ * [in] pZigzagTable pointer to the zigzag tables
+ * [out] pDst pointer to the coefficient buffer of current
+ * block. Should be 32-bit aligned
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_FillVLDBuffer(
+ OMX_U32 storeRun,
+ OMX_S16 * pDst,
+ OMX_S16 storeLevel,
+ OMX_U8 sign,
+ OMX_U8 last,
+ OMX_U8 * pIndex,
+ const OMX_U8 * pZigzagTable
+)
+{
+ /* Store the zero's as per the run length count */
+ for (;storeRun > 0; storeRun--, (*pIndex)++)
+ {
+ pDst[pZigzagTable[*pIndex]] = 0;
+ }
+ /* Store the level depending on the sign*/
+ if (sign == 1)
+ {
+ pDst[pZigzagTable[*pIndex]] = -storeLevel;
+ }
+ else
+ {
+ pDst[pZigzagTable[*pIndex]] = storeLevel;
+ }
+ (*pIndex)++;
+
+ /* If last is 1, fill the remaining elments of the buffer with zeros */
+ if (last == 1)
+ {
+ while (*pIndex < 64)
+ {
+ pDst[pZigzagTable[*pIndex]] = 0;
+ (*pIndex)++;
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_GetVLCBits.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_GetVLCBits.c
new file mode 100644
index 0000000..953f597
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_GetVLCBits.c
@@ -0,0 +1,278 @@
+/**
+ *
+ * File Name: armVCM4P2_GetVLCBits.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for VLC get bits from the stream
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+#include "armCOMM_Bitstream.h"
+#include "armVCM4P2_ZigZag_Tables.h"
+#include "armVCM4P2_Huff_Tables_VLC.h"
+
+
+/**
+ * Function: armVCM4P2_GetVLCBits
+ *
+ * Description:
+ * Performs escape mode decision based on the run, run+, level, level+ and
+ * last combinations.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7
+ * [in] start start indicates whether the encoding begins with
+ * 0th element or 1st.
+ * [in/out] pLast pointer to last status flag
+ * [in] runBeginSingleLevelEntriesL0 The run value from which level
+ * will be equal to 1: last == 0
+ * [in] IndexBeginSingleLevelEntriesL0 Array index in the VLC table
+ * pointing to the
+ * runBeginSingleLevelEntriesL0
+ * [in] runBeginSingleLevelEntriesL1 The run value from which level
+ * will be equal to 1: last == 1
+ * [in] IndexBeginSingleLevelEntriesL1 Array index in the VLC table
+ * pointing to the
+ * runBeginSingleLevelEntriesL0
+ * [in] pRunIndexTableL0 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pVlcTableL0 VLC table for last == 0
+ * [in] pRunIndexTableL1 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pVlcTableL1 VLC table for last == 1
+ * [in] pLMAXTableL0 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pLMAXTableL1 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pRMAXTableL0 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pRMAXTableL1 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [out]pDst pointer to the coefficient buffer of current
+ * block. Should be 32-bit aligned
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_GetVLCBits (
+ const OMX_U8 **ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start,
+ OMX_U8 * pLast,
+ OMX_U8 runBeginSingleLevelEntriesL0,
+ OMX_U8 maxIndexForMultipleEntriesL0,
+ OMX_U8 maxRunForMultipleEntriesL1,
+ OMX_U8 maxIndexForMultipleEntriesL1,
+ const OMX_U8 * pRunIndexTableL0,
+ const ARM_VLC32 *pVlcTableL0,
+ const OMX_U8 * pRunIndexTableL1,
+ const ARM_VLC32 *pVlcTableL1,
+ const OMX_U8 * pLMAXTableL0,
+ const OMX_U8 * pLMAXTableL1,
+ const OMX_U8 * pRMAXTableL0,
+ const OMX_U8 * pRMAXTableL1,
+ const OMX_U8 * pZigzagTable
+)
+{
+ OMX_U32 storeRun;
+ OMX_U8 tabIndex, markerBit;
+ OMX_S16 storeLevel;
+ OMX_U16 unpackRetIndex;
+ OMX_U8 i, fType, escape;
+ OMX_U8 sign = 0;
+
+ /* Unpacking the bitstream and RLD */
+ for (i = start; i < 64;)
+ {
+ escape = armLookAheadBits(ppBitStream, pBitOffset, 7);
+ if (escape != 3)
+ {
+ fType = 0; /* Not in escape mode */
+ }
+ else
+ {
+ armSkipBits (ppBitStream, pBitOffset, 7);
+ if(shortVideoHeader)
+ {
+ *pLast = armGetBits(ppBitStream, pBitOffset, 1);
+ storeRun = armGetBits(ppBitStream, pBitOffset, 6);
+ storeLevel = armGetBits(ppBitStream, pBitOffset, 8);
+
+ /* Ref to Table B-18 (c) in MPEG4 Standard- FLC code for */
+ /* LEVEL when short_video_header is 1, the storeLevel is */
+ /* a signed value and the sign and the unsigned value for */
+ /* storeLevel need to be extracted and passed to arm */
+ /* FillVLDBuffer function */
+
+ sign = (storeLevel & 0x80);
+ if(sign==0x80)
+ {
+ storeLevel=(storeLevel^0xff)+1;
+ sign=1;
+
+ }
+
+ armRetDataErrIf( storeLevel == 0 || sign*storeLevel == 128 , OMX_Sts_Err); /* Invalid FLC */
+ armRetDataErrIf((i + storeRun) >= 64, OMX_Sts_Err);
+ armVCM4P2_FillVLDBuffer(
+ storeRun,
+ pDst,
+ storeLevel,
+ sign,
+ *pLast,
+ &i,
+ pZigzagTable);
+ return OMX_Sts_NoErr;
+
+ }
+ if (armGetBits(ppBitStream, pBitOffset, 1))
+ {
+ if (armGetBits(ppBitStream, pBitOffset, 1))
+ {
+ fType = 3;
+ }
+ else
+ {
+ fType = 2;
+ }
+ }
+ else
+ {
+ fType = 1;
+ }
+ }
+
+ if (fType < 3)
+ {
+ unpackRetIndex = armUnPackVLC32(ppBitStream, pBitOffset,
+ pVlcTableL0);
+ if (unpackRetIndex != ARM_NO_CODEBOOK_INDEX)
+ {
+ /* Decode run and level from the index */
+ /* last = 0 */
+ *pLast = 0;
+ if (unpackRetIndex > maxIndexForMultipleEntriesL0)
+ {
+ storeLevel = 1;
+ storeRun = (unpackRetIndex - maxIndexForMultipleEntriesL0)
+ + runBeginSingleLevelEntriesL0;
+ }
+ else
+ {
+ tabIndex = 1;
+ while (pRunIndexTableL0[tabIndex] <= unpackRetIndex)
+ {
+ tabIndex++;
+ }
+ storeRun = tabIndex - 1;
+ storeLevel = unpackRetIndex - pRunIndexTableL0[tabIndex - 1] + 1;
+ }
+ sign = (OMX_U8) armGetBits(ppBitStream, pBitOffset, 1);
+
+ if (fType == 1)
+ {
+ storeLevel = (armAbs(storeLevel) + pLMAXTableL0[storeRun]);
+ }
+ else if (fType == 2)
+ {
+ storeRun = storeRun + pRMAXTableL0[storeLevel-1] + 1;
+ }
+ }
+ else
+ {
+ unpackRetIndex = armUnPackVLC32(ppBitStream, pBitOffset,
+ pVlcTableL1);
+
+ armRetDataErrIf(unpackRetIndex == ARM_NO_CODEBOOK_INDEX, OMX_Sts_Err);
+
+ /* Decode run and level from the index */
+ /* last = 1 */
+ *pLast = 1;
+ if (unpackRetIndex > maxIndexForMultipleEntriesL1)
+ {
+ storeLevel = 1;
+ storeRun = (unpackRetIndex - maxIndexForMultipleEntriesL1)
+ + maxRunForMultipleEntriesL1;
+ }
+ else
+ {
+ tabIndex = 1;
+ while (pRunIndexTableL1[tabIndex] <= unpackRetIndex)
+ {
+ tabIndex++;
+ }
+ storeRun = tabIndex - 1;
+ storeLevel = unpackRetIndex - pRunIndexTableL1[tabIndex - 1] + 1;
+ }
+ sign = (OMX_U8) armGetBits(ppBitStream, pBitOffset, 1);
+
+ if (fType == 1)
+ {
+ storeLevel = (armAbs(storeLevel) + pLMAXTableL1[storeRun]);
+ }
+ else if (fType == 2)
+ {
+ storeRun = storeRun + pRMAXTableL1[storeLevel-1] + 1;
+ }
+ }
+ armRetDataErrIf((i + storeRun) >= 64, OMX_Sts_Err);
+ armVCM4P2_FillVLDBuffer(
+ storeRun,
+ pDst,
+ storeLevel,
+ sign,
+ *pLast,
+ &i,
+ pZigzagTable);
+ }
+ else
+ {
+ *pLast = armGetBits(ppBitStream, pBitOffset, 1);
+ storeRun = armGetBits(ppBitStream, pBitOffset, 6);
+ armRetDataErrIf((i + storeRun) >= 64, OMX_Sts_Err);
+ markerBit = armGetBits(ppBitStream, pBitOffset, 1);
+ armRetDataErrIf( markerBit == 0, OMX_Sts_Err);
+ storeLevel = armGetBits(ppBitStream, pBitOffset, 12);
+ if (storeLevel & 0x800)
+ {
+ storeLevel -= 4096;
+ }
+ armRetDataErrIf( storeLevel == 0 || storeLevel == -2048 , OMX_Sts_Err); /* Invalid FLC */
+ armGetBits(ppBitStream, pBitOffset, 1);
+ armVCM4P2_FillVLDBuffer(
+ storeRun,
+ pDst,
+ storeLevel,
+ 0, /* Sign is not used, preprocessing done */
+ *pLast,
+ &i,
+ pZigzagTable);
+
+ }
+ } /* End of forloop for i */
+ return OMX_Sts_NoErr;
+}
+
+/* End of File */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
new file mode 100644
index 0000000..cd7e9e4
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Huff_Tables_VLC.c
@@ -0,0 +1,495 @@
+ /**
+ *
+ * File Name: armVCM4P2_Huff_Tables_VLC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armVCM4P2_Huff_Tables_VLC.c
+ * Description: Contains all the Huffman tables used in MPEG4 codec
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armCOMM_Bitstream.h"
+
+/*
+* For Intra
+* last = 0
+*/
+const OMX_U8 armVCM4P2_IntraL0RunIdx[11] =
+{
+ 0, 27, 37, 42, 46, 49, 52,
+ 55, 58, 60, 62
+};
+
+/* Entry defined for all values
+* for run = 0 to 14
+* Note: the last entry is to terminate while decoding
+*/
+const ARM_VLC32 armVCM4P2_IntraVlcL0[68] =
+{
+ {2, 2},
+ {3, 6},
+ {4, 15},
+ {5, 13},
+ {5, 12},
+ {6, 21},
+ {6, 19},
+ {6, 18},
+ {7, 23},
+ {8, 31},
+ {8, 30},
+ {8, 29},
+ {9, 37},
+ {9, 36},
+ {9, 35},
+ {9, 33},
+ {10, 33},
+ {10, 32},
+ {10, 15},
+ {10, 14},
+ {11, 7},
+ {11, 6},
+ {11, 32},
+ {11, 33},
+ {12, 80},
+ {12, 81},
+ {12, 82},
+ {4, 14},
+ {6, 20},
+ {7, 22},
+ {8, 28},
+ {9, 32},
+ {9, 31},
+ {10, 13},
+ {11, 34},
+ {12, 83},
+ {12, 85},
+ {5, 11},
+ {7, 21},
+ {9, 30},
+ {10, 12},
+ {12, 86},
+ {6, 17},
+ {8, 27},
+ {9, 29},
+ {10, 11},
+ {6, 16},
+ {9, 34},
+ {10, 10},
+ {6, 13},
+ {9, 28},
+ {10, 8},
+ {7, 18},
+ {9, 27},
+ {12, 84},
+ {7, 20},
+ {9, 26},
+ {12, 87},
+ {8, 25},
+ {10, 9},
+ {8, 24},
+ {11, 35},
+ {8, 23},
+ {9, 25},
+ {9, 24},
+ {10, 7},
+ {12, 88},
+ {0, 0}
+};
+
+/*
+* For Intra
+* last = 1
+*/
+
+const OMX_U8 armVCM4P2_IntraL1RunIdx[8] =
+{
+ 0, 8, 11, 13, 15, 17, 19, 21
+};
+
+/* Entry defined for all values
+* for run = 0 to 20
+* * Note: the last entry is to terminate while decoding
+*/
+const ARM_VLC32 armVCM4P2_IntraVlcL1[36] =
+{
+ {4, 7},
+ {6, 12},
+ {8, 22},
+ {9, 23},
+ {10, 6},
+ {11, 5},
+ {11, 4},
+ {12, 89},
+ {6, 15},
+ {9, 22},
+ {10, 5},
+ {6, 14},
+ {10, 4},
+ {7, 17},
+ {11, 36},
+ {7, 16},
+ {11, 37},
+ {7, 19},
+ {12, 90},
+ {8, 21},
+ {12, 91},
+ {8, 20},
+ {8, 19},
+ {8, 26},
+ {9, 21},
+ {9, 20},
+ {9, 19},
+ {9, 18},
+ {9, 17},
+ {11, 38},
+ {11, 39},
+ {12, 92},
+ {12, 93},
+ {12, 94},
+ {12, 95},
+ {0, 0}
+};
+
+/* LMAX table for Intra (Last == 0)*/
+const OMX_U8 armVCM4P2_IntraL0LMAX[15] =
+{
+ 27, 10, 5, 4, 3, 3, 3,
+ 3, 2, 2, 1, 1, 1, 1, 1
+};
+
+/* LMAX table for Intra (Last == 1)*/
+const OMX_U8 armVCM4P2_IntraL1LMAX[21] =
+{
+ 8, 3, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+};
+
+/* RMAX table for Intra (Last == 0)
+ Level - 1 Indexed
+*/
+const OMX_U8 armVCM4P2_IntraL0RMAX[27] =
+{
+ 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
+};
+
+/* RMAX table for Intra (Last == 1)
+ Level - 1 Indexed
+*/
+const OMX_U8 armVCM4P2_IntraL1RMAX[8] =
+{
+ 20, 6, 1, 0, 0, 0, 0, 0
+};
+
+/*
+* For Inter
+* last = 0
+*/
+const OMX_U8 armVCM4P2_InterL0RunIdx[12] =
+{
+ 0, 12, 18, 22, 25, 28,
+ 31, 34, 36, 38, 40, 42
+};
+
+/* Entry defined for all values
+* for run = 0 to 26
+* Note: the last entry is to terminate while decoding
+*/
+const ARM_VLC32 armVCM4P2_InterVlcL0[59] =
+{
+ {2, 2},
+ {4, 15},
+ {6, 21},
+ {7, 23},
+ {8, 31},
+ {9, 37},
+ {9, 36},
+ {10, 33},
+ {10, 32},
+ {11, 7},
+ {11, 6},
+ {11, 32},
+ {3, 6},
+ {6, 20},
+ {8, 30},
+ {10, 15},
+ {11, 33},
+ {12, 80},
+ {4, 14},
+ {8, 29},
+ {10, 14},
+ {12, 81},
+ {5, 13},
+ {9, 35},
+ {10, 13},
+ {5, 12},
+ {9, 34},
+ {12, 82},
+ {5, 11},
+ {10, 12},
+ {12, 83},
+ {6, 19},
+ {10, 11},
+ {12, 84},
+ {6, 18},
+ {10, 10},
+ {6, 17},
+ {10, 9},
+ {6, 16},
+ {10, 8},
+ {7, 22},
+ {12, 85},
+ {7, 21},
+ {7, 20},
+ {8, 28},
+ {8, 27},
+ {9, 33},
+ {9, 32},
+ {9, 31},
+ {9, 30},
+ {9, 29},
+ {9, 28},
+ {9, 27},
+ {9, 26},
+ {11, 34},
+ {11, 35},
+ {12, 86},
+ {12, 87},
+ {0, 0}
+};
+
+
+/*
+* For Intra
+* last = 1
+*/
+
+const OMX_U8 armVCM4P2_InterL1RunIdx[3] =
+{
+ 0, 3, 5
+};
+
+/* Entry defined for all values
+* for run = 0 to 40
+* Note: the last entry is to terminate while decoding
+*/
+const ARM_VLC32 armVCM4P2_InterVlcL1[45] =
+{
+ {4, 7},
+ {9, 25},
+ {11, 5},
+ {6, 15},
+ {11, 4},
+ {6, 14},
+ {6, 13},
+ {6, 12},
+ {7, 19},
+ {7, 18},
+ {7, 17},
+ {7, 16},
+ {8, 26},
+ {8, 25},
+ {8, 24},
+ {8, 23},
+ {8, 22},
+ {8, 21},
+ {8, 20},
+ {8, 19},
+ {9, 24},
+ {9, 23},
+ {9, 22},
+ {9, 21},
+ {9, 20},
+ {9, 19},
+ {9, 18},
+ {9, 17},
+ {10, 7},
+ {10, 6},
+ {10, 5},
+ {10, 4},
+ {11, 36},
+ {11, 37},
+ {11, 38},
+ {11, 39},
+ {12, 88},
+ {12, 89},
+ {12, 90},
+ {12, 91},
+ {12, 92},
+ {12, 93},
+ {12, 94},
+ {12, 95},
+ { 0, 0}
+};
+
+/* LMAX table for Intra (Last == 0)*/
+const OMX_U8 armVCM4P2_InterL0LMAX[27] =
+{
+ 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,
+};
+
+/* LMAX table for Intra (Last == 1)*/
+const OMX_U8 armVCM4P2_InterL1LMAX[41] =
+{
+ 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,
+};
+
+/* RMAX table for Intra (Last == 0)
+ Level - 1 Indexed
+*/
+const OMX_U8 armVCM4P2_InterL0RMAX[12] =
+{
+ 26, 10, 6, 2, 1, 1,
+ 0, 0, 0, 0, 0, 0
+};
+
+/* RMAX table for Intra (Last == 1)
+ Level - 1 Indexed
+*/
+const OMX_U8 armVCM4P2_InterL1RMAX[3] =
+{
+ 40, 1, 0
+};
+
+/*
+* For Intra - Luminance
+*/
+
+const ARM_VLC32 armVCM4P2_aIntraDCLumaIndex[14] =
+{
+ {3, 3},
+ {2, 3},
+ {2, 2},
+ {3, 2},
+ {3, 1},
+ {4, 1},
+ {5, 1},
+ {6, 1},
+ {7, 1},
+ {8, 1},
+ {9, 1},
+ {10, 1},
+ {11, 1},
+ {0, 0}
+};
+
+/*
+* For Intra - Chrominance
+*/
+
+const ARM_VLC32 armVCM4P2_aIntraDCChromaIndex[14] =
+{
+ {2, 3},
+ {2, 2},
+ {2, 1},
+ {3, 1},
+ {4, 1},
+ {5, 1},
+ {6, 1},
+ {7, 1},
+ {8, 1},
+ {9, 1},
+ {10, 1},
+ {11, 1},
+ {12, 1},
+ {0, 0}
+};
+
+/*
+ * Motion vector decoding table
+ */
+
+const ARM_VLC32 armVCM4P2_aVlcMVD[66] =
+{
+ {13, 5},
+ {13, 7},
+ {12, 5},
+ {12, 7},
+ {12, 9},
+ {12, 11},
+ {12, 13},
+ {12, 15},
+ {11, 9},
+ {11, 11},
+ {11, 13},
+ {11, 15},
+ {11, 17},
+ {11, 19},
+ {11, 21},
+ {11, 23},
+ {11, 25},
+ {11, 27},
+ {11, 29},
+ {11, 31},
+ {11, 33},
+ {11, 35},
+ {10, 19},
+ {10, 21},
+ {10, 23},
+ {8, 7},
+ {8, 9},
+ {8, 11},
+ {7, 7},
+ {5, 3},
+ {4, 3},
+ {3, 3},
+ {1, 1},
+ {3, 2},
+ {4, 2},
+ {5, 2},
+ {7, 6},
+ {8, 10},
+ {8, 8},
+ {8, 6},
+ {10, 22},
+ {10, 20},
+ {10, 18},
+ {11, 34},
+ {11, 32},
+ {11, 30},
+ {11, 28},
+ {11, 26},
+ {11, 24},
+ {11, 22},
+ {11, 20},
+ {11, 18},
+ {11, 16},
+ {11, 14},
+ {11, 12},
+ {11, 10},
+ {11, 8},
+ {12, 14},
+ {12, 12},
+ {12, 10},
+ {12, 8},
+ {12, 6},
+ {12, 4},
+ {13, 6},
+ {13, 4},
+ { 0, 0}
+};
+
+/* End of file */
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_PutVLCBits.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_PutVLCBits.c
new file mode 100644
index 0000000..ca9efec
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_PutVLCBits.c
@@ -0,0 +1,200 @@
+/**
+ *
+ * File Name: armVCM4P2_PutVLCBits.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for VLC put bits to bitstream
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+#include "armCOMM_Bitstream.h"
+#include "armVCM4P2_ZigZag_Tables.h"
+#include "armVCM4P2_Huff_Tables_VLC.h"
+
+
+/**
+ * Function: armVCM4P2_PutVLCBits
+ *
+ * Description:
+ * Checks the type of Escape Mode and put encoded bits for
+ * quantized DCT coefficients.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] ppBitStream pointer to the pointer to the current byte in
+ * the bit stream
+ * [in] pBitOffset pointer to the bit position in the byte pointed
+ * by *ppBitStream. Valid within 0 to 7
+ * [in] shortVideoHeader binary flag indicating presence of short_video_header; escape modes 0-3 are used if shortVideoHeader==0,
+ * and escape mode 4 is used when shortVideoHeader==1.
+ * [in] start start indicates whether the encoding begins with
+ * 0th element or 1st.
+ * [in] maxStoreRunL0 Max store possible (considering last and inter/intra)
+ * for last = 0
+ * [in] maxStoreRunL1 Max store possible (considering last and inter/intra)
+ * for last = 1
+ * [in] maxRunForMultipleEntriesL0
+ * The run value after which level
+ * will be equal to 1:
+ * (considering last and inter/intra status) for last = 0
+ * [in] maxRunForMultipleEntriesL1
+ * The run value after which level
+ * will be equal to 1:
+ * (considering last and inter/intra status) for last = 1
+ * [in] pRunIndexTableL0 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pVlcTableL0 VLC table for last == 0
+ * [in] pRunIndexTableL1 Run Index table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pVlcTableL1 VLC table for last == 1
+ * [in] pLMAXTableL0 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pLMAXTableL1 Level MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [in] pRMAXTableL0 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 0
+ * [in] pRMAXTableL1 Run MAX table defined in
+ * armVCM4P2_Huff_Tables_VLC.c for last == 1
+ * [out] pQDctBlkCoef pointer to the quantized DCT coefficient
+ * [out] ppBitStream *ppBitStream is updated after the block is encoded
+ * so that it points to the current byte in the bit
+ * stream buffer.
+ * [out] pBitOffset *pBitOffset is updated so that it points to the
+ * current bit position in the byte pointed by
+ * *ppBitStream.
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+
+OMXResult armVCM4P2_PutVLCBits (
+ OMX_U8 **ppBitStream,
+ OMX_INT * pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_INT shortVideoHeader,
+ OMX_U8 start,
+ OMX_U8 maxStoreRunL0,
+ OMX_U8 maxStoreRunL1,
+ OMX_U8 maxRunForMultipleEntriesL0,
+ OMX_U8 maxRunForMultipleEntriesL1,
+ const OMX_U8 * pRunIndexTableL0,
+ const ARM_VLC32 *pVlcTableL0,
+ const OMX_U8 * pRunIndexTableL1,
+ const ARM_VLC32 *pVlcTableL1,
+ const OMX_U8 * pLMAXTableL0,
+ const OMX_U8 * pLMAXTableL1,
+ const OMX_U8 * pRMAXTableL0,
+ const OMX_U8 * pRMAXTableL1,
+ const OMX_U8 * pZigzagTable
+)
+{
+
+ OMX_U32 storeRun = 0, run, storeRunPlus;
+ OMX_U8 last = 0, first = 1, fMode;
+ OMX_S16 level, storeLevel = 0, storeLevelPlus;
+ OMX_INT i;
+
+ /* RLE encoding and packing the bits into the streams */
+ for (i = start, run=0; i < 64; i++)
+ {
+ level = pQDctBlkCoef[pZigzagTable[i]];
+
+ /* Counting the run */
+ if (level == 0)
+ {
+ run++;
+ }
+
+ /* Found a non-zero coeff */
+ else
+ {
+ if (first == 0)
+ {
+ last = 0;
+
+ /* Check for a valid entry in the VLC table */
+ storeLevelPlus = armSignCheck(storeLevel) *
+ (armAbs(storeLevel) - pLMAXTableL0[storeRun]);
+ storeRunPlus = storeRun -
+ (pRMAXTableL0[armAbs(storeLevel) - 1] + 1);
+
+ fMode = armVCM4P2_CheckVLCEscapeMode(
+ storeRun,
+ storeRunPlus,
+ storeLevel,
+ storeLevelPlus,
+ maxStoreRunL0,
+ maxRunForMultipleEntriesL0,
+ shortVideoHeader,
+ pRunIndexTableL0);
+
+ armVCM4P2_FillVLCBuffer (
+ ppBitStream,
+ pBitOffset,
+ storeRun,
+ storeLevel,
+ storeRunPlus,
+ storeLevelPlus,
+ fMode,
+ last,
+ maxRunForMultipleEntriesL0,
+ pRunIndexTableL0,
+ pVlcTableL0);
+ }
+ storeLevel = level;
+ storeRun = run;
+ first = 0;
+ run = 0;
+ }
+
+ } /* end of for loop for 64 elements */
+
+ /* writing the last element */
+ last = 1;
+
+ /* Check for a valid entry in the VLC table */
+ storeLevelPlus = armSignCheck(storeLevel) *
+ (armAbs(storeLevel) - pLMAXTableL1[run]);
+ storeRunPlus = storeRun -
+ (pRMAXTableL1[armAbs(storeLevel) - 1] + 1);
+ fMode = armVCM4P2_CheckVLCEscapeMode(
+ storeRun,
+ storeRunPlus,
+ storeLevel,
+ storeLevelPlus,
+ maxStoreRunL1,
+ maxRunForMultipleEntriesL1,
+ shortVideoHeader,
+ pRunIndexTableL1);
+
+ armVCM4P2_FillVLCBuffer (
+ ppBitStream,
+ pBitOffset,
+ storeRun,
+ storeLevel,
+ storeRunPlus,
+ storeLevelPlus,
+ fMode,
+ last,
+ maxRunForMultipleEntriesL1,
+ pRunIndexTableL1,
+ pVlcTableL1);
+ return OMX_Sts_NoErr;
+}
+
+/* End of File */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_SetPredDir.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_SetPredDir.c
new file mode 100644
index 0000000..a9cd008
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_SetPredDir.c
@@ -0,0 +1,89 @@
+/**
+ *
+ * File Name: armVCM4P2_SetPredDir.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for detecting the prediction direction
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: armVCM4P2_SetPredDir
+ *
+ * Description:
+ * Performs detecting the prediction direction
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] blockIndex block index indicating the component type and
+ * position as defined in subclause 6.1.3.8, of ISO/IEC
+ * 14496-2. Furthermore, indexes 6 to 9 indicate the
+ * alpha blocks spatially corresponding to luminance
+ * blocks 0 to 3 in the same macroblock.
+ * [in] pCoefBufRow pointer to the coefficient row buffer
+ * [in] pQpBuf pointer to the quantization parameter buffer
+ * [out] predQP quantization parameter of the predictor block
+ * [out] predDir indicates the prediction direction which takes one
+ * of the following values:
+ * OMX_VC_HORIZONTAL predict horizontally
+ * OMX_VC_VERTICAL predict vertically
+ *
+ * Return Value:
+ * Standard OMXResult result. See enumeration for possible result codes.
+ *
+ */
+
+OMXResult armVCM4P2_SetPredDir(
+ OMX_INT blockIndex,
+ OMX_S16 *pCoefBufRow,
+ OMX_S16 *pCoefBufCol,
+ OMX_INT *predDir,
+ OMX_INT *predQP,
+ const OMX_U8 *pQpBuf
+)
+{
+ OMX_U8 blockDCLeft;
+ OMX_U8 blockDCTop;
+ OMX_U8 blockDCTopLeft;
+
+ if (blockIndex == 3)
+ {
+ blockDCTop = *(pCoefBufCol - 8);
+ }
+ else
+ {
+ blockDCTop = *pCoefBufRow;
+ }
+ blockDCLeft = *pCoefBufCol;
+ blockDCTopLeft = *(pCoefBufRow - 8);
+
+ if (armAbs(blockDCLeft - blockDCTopLeft) < armAbs(blockDCTopLeft \
+ - blockDCTop))
+ {
+ *predDir = OMX_VC_VERTICAL;
+ *predQP = pQpBuf[1];
+ }
+ else
+ {
+ *predDir = OMX_VC_HORIZONTAL;
+ *predQP = pQpBuf[0];
+ }
+ return OMX_Sts_NoErr;
+}
+
+
+/*End of File*/
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
new file mode 100644
index 0000000..a247c69
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/armVCM4P2_Zigzag_Tables.c
@@ -0,0 +1,58 @@
+ /**
+ *
+ * File Name: armVCM4P2_Zigzag_Tables.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: armVCM4P2_ZigZag_Tables.c
+ * Description: Contains the zigzag tables
+ *
+ */
+
+#include "omxtypes.h"
+
+const OMX_U8 armVCM4P2_aClassicalZigzagScan [64] =
+{
+ 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
+};
+
+const OMX_U8 armVCM4P2_aHorizontalZigzagScan [64] =
+{
+ 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
+};
+
+const OMX_U8 armVCM4P2_aVerticalZigzagScan [64] =
+{
+ 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
+};
+
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_16x16.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_16x16.c
new file mode 100644
index 0000000..dcd3ce1
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_16x16.c
@@ -0,0 +1,111 @@
+/**
+ *
+ * File Name: omxVCM4P2_BlockMatch_Half_16x16.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for Block matching, a full search algorithm
+ * is implemented
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Half_16x16 (6.2.4.2.3)
+ *
+ * Description:
+ * Performs a 16x16 block match with half-pixel resolution. Returns the
+ * estimated motion vector and associated minimum SAD. This function
+ * estimates the half-pixel motion vector by interpolating the integer
+ * resolution motion vector referenced by the input parameter pSrcDstMV, i.e.,
+ * the initial integer MV is generated externally. The input parameters
+ * pSrcRefBuf and pSearchPointRefPos should be shifted by the winning MV of
+ * 16x16 integer search prior to calling BlockMatch_Half_16x16. The function
+ * BlockMatch_Integer_16x16 may be used for integer motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * macroblock that corresponds to the location of the current
+ * macroblock in the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - reference plane valid region rectangle
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 256
+ * entries); must be aligned on a 16-byte boundary. The number of
+ * bytes between lines (step) is 16.
+ * pSearchPointRefPos - position of the starting point for half pixel
+ * search (specified in terms of integer pixel units) in the
+ * reference plane, i.e., the reference position pointed to by the
+ * predicted motion vector.
+ * rndVal - rounding control parameter: 0 - disabled; 1 - enabled.
+ * pSrcDstMV - pointer to the initial MV estimate; typically generated
+ * during a prior 16X16 integer search; specified in terms of
+ * half-pixel units.
+ *
+ * Output Arguments:
+ *
+ * pSrcDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL: pSrcRefBuf,
+ * pRefRect, pSrcCurrBuff, pSearchPointRefPos, pSrcDstMV.
+ * - pSrcCurrBuf is not 16-byte aligned, or
+ *
+ */
+
+OMXResult omxVCM4P2_BlockMatch_Half_16x16(
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pSearchPointRefPos,
+ OMX_INT rndVal,
+ OMXVCMotionVector *pSrcDstMV,
+ OMX_INT *pDstSAD
+)
+{
+
+ /* For a blocksize of 16x16 */
+ OMX_U8 BlockSize = 16;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrcRefBuf == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSearchPointRefPos == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcDstMV == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pSrcCurrBuf), OMX_Sts_BadArgErr);
+
+ return (armVCM4P2_BlockMatch_Half(
+ pSrcRefBuf,
+ refWidth,
+ pRefRect,
+ pSrcCurrBuf,
+ pSearchPointRefPos,
+ rndVal,
+ pSrcDstMV,
+ pDstSAD,
+ BlockSize));
+
+
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_8x8.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_8x8.c
new file mode 100644
index 0000000..6996e6d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Half_8x8.c
@@ -0,0 +1,109 @@
+/**
+ *
+ * File Name: omxVCM4P2_BlockMatch_Half_8x8.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for Block matching, a full search algorithm
+ * is implemented
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Half_8x8 (6.2.4.2.4)
+ *
+ * Description:
+ * Performs an 8x8 block match with half-pixel resolution. Returns the
+ * estimated motion vector and associated minimum SAD. This function
+ * estimates the half-pixel motion vector by interpolating the integer
+ * resolution motion vector referenced by the input parameter pSrcDstMV, i.e.,
+ * the initial integer MV is generated externally. The input parameters
+ * pSrcRefBuf and pSearchPointRefPos should be shifted by the winning MV of
+ * 8x8 integer search prior to calling BlockMatch_Half_8x8. The function
+ * BlockMatch_Integer_8x8 may be used for integer motion estimation.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * block that corresponds to the location of the current 8x8 block
+ * in the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - reference plane valid region rectangle
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 128
+ * entries); must be aligned on a 8-byte boundary. The number of
+ * bytes between lines (step) is 16.
+ * pSearchPointRefPos - position of the starting point for half pixel
+ * search (specified in terms of integer pixel units) in the
+ * reference plane.
+ * rndVal - rounding control parameter: 0 - disabled; 1 - enabled.
+ * pSrcDstMV - pointer to the initial MV estimate; typically generated
+ * during a prior 8x8 integer search, specified in terms of
+ * half-pixel units.
+ *
+ * Output Arguments:
+ *
+ * pSrcDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL:
+ * pSrcRefBuf, pRefRect, pSrcCurrBuff, pSearchPointRefPos, pSrcDstMV
+ * - pSrcCurrBuf is not 8-byte aligned
+ *
+ */
+
+OMXResult omxVCM4P2_BlockMatch_Half_8x8(
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pSearchPointRefPos,
+ OMX_INT rndVal,
+ OMXVCMotionVector *pSrcDstMV,
+ OMX_INT *pDstSAD
+)
+{
+ /* For a blocksize of 8x8 */
+ OMX_U8 BlockSize = 8;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrcRefBuf == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSearchPointRefPos == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcDstMV == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs8ByteAligned(pSrcCurrBuf), OMX_Sts_BadArgErr);
+
+ return (armVCM4P2_BlockMatch_Half(
+ pSrcRefBuf,
+ refWidth,
+ pRefRect,
+ pSrcCurrBuf,
+ pSearchPointRefPos,
+ rndVal,
+ pSrcDstMV,
+ pDstSAD,
+ BlockSize));
+
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_16x16.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_16x16.c
new file mode 100644
index 0000000..e714ef1
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_16x16.c
@@ -0,0 +1,114 @@
+/**
+ *
+ * File Name: omxVCM4P2_BlockMatch_Integer_16x16.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for Block matching, a full search algorithm
+ * is implemented
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Integer_16x16 (6.2.4.2.1)
+ *
+ * Description:
+ * Performs a 16x16 block search; estimates motion vector and associated
+ * minimum SAD. Both the input and output motion vectors are represented using
+ * half-pixel units, and therefore a shift left or right by 1 bit may be
+ * required, respectively, to match the input or output MVs with other
+ * functions that either generate output MVs or expect input MVs represented
+ * using integer pixel units.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * MB that corresponds to the location of the current macroblock in
+ * the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - pointer to the valid reference plane rectangle; coordinates
+ * are specified relative to the image origin. Rectangle
+ * boundaries may extend beyond image boundaries if the image has
+ * been padded. For example, if padding extends 4 pixels beyond
+ * frame border, then the value for the left border could be set to
+ * -4.
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 256
+ * entries); must be aligned on a 16-byte boundary. The number of
+ * bytes between lines (step) is 16.
+ * pCurrPointPos - position of the current macroblock in the current plane
+ * pSrcPreMV - pointer to predicted motion vector; NULL indicates no
+ * predicted MV
+ * pSrcPreSAD - pointer to SAD associated with the predicted MV (referenced
+ * by pSrcPreMV); may be set to NULL if unavailable.
+ * pMESpec - vendor-specific motion estimation specification structure;
+ * must have been allocated and then initialized using
+ * omxVCM4P2_MEInit prior to calling the block matching function.
+ *
+ * Output Arguments:
+ *
+ * pDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL: pSrcRefBuf,
+ * pRefRect, pSrcCurrBuff, pCurrPointPos, pDstMV, pDstSAD or
+ * pMESpec, or
+ * - pSrcCurrBuf is not 16-byte aligned
+ *
+ */
+
+OMXResult omxVCM4P2_BlockMatch_Integer_16x16(
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCMotionVector *pSrcPreMV,
+ const OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector *pDstMV,
+ OMX_INT *pDstSAD
+)
+{
+
+ OMX_U8 BlockSize = 16;
+
+ /* Argument error checks */
+ armRetArgErrIf(!armIs16ByteAligned(pSrcCurrBuf), OMX_Sts_BadArgErr);
+
+ return ( armVCM4P2_BlockMatch_Integer(
+ pSrcRefBuf,
+ refWidth,
+ pRefRect,
+ pSrcCurrBuf,
+ pCurrPointPos,
+ pSrcPreMV,
+ pSrcPreSAD,
+ pMESpec,
+ pDstMV,
+ pDstSAD,
+ BlockSize)
+ );
+
+
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_8x8.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_8x8.c
new file mode 100644
index 0000000..607e64c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_BlockMatch_Integer_8x8.c
@@ -0,0 +1,110 @@
+/**
+ *
+ * File Name: omxVCM4P2_BlockMatch_Integer_8x8.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for Block matching, a full search algorithm
+ * is implemented
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P2_BlockMatch_Integer_8x8 (6.2.4.2.2)
+ *
+ * Description:
+ * Performs an 8x8 block search; estimates motion vector and associated
+ * minimum SAD. Both the input and output motion vectors are represented
+ * using half-pixel units, and therefore a shift left or right by 1 bit may be
+ * required, respectively, to match the input or output MVs with other
+ * functions that either generate output MVs or expect input MVs represented
+ * using integer pixel units.
+ *
+ * Input Arguments:
+ *
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * block that corresponds to the location of the current 8x8 block
+ * in the current plane.
+ * refWidth - width of the reference plane
+ * pRefRect - pointer to the valid reference plane rectangle; coordinates
+ * are specified relative to the image origin. Rectangle
+ * boundaries may extend beyond image boundaries if the image has
+ * been padded.
+ * pSrcCurrBuf - pointer to the current block in the current macroblock
+ * buffer extracted from the original plane (linear array, 128
+ * entries); must be aligned on an 8-byte boundary. The number of
+ * bytes between lines (step) is 16 bytes.
+ * pCurrPointPos - position of the current block in the current plane
+ * pSrcPreMV - pointer to predicted motion vector; NULL indicates no
+ * predicted MV
+ * pSrcPreSAD - pointer to SAD associated with the predicted MV (referenced
+ * by pSrcPreMV); may be set to NULL if unavailable.
+ * pMESpec - vendor-specific motion estimation specification structure;
+ * must have been allocated and then initialized using
+ * omxVCM4P2_MEInit prior to calling the block matching function.
+ *
+ * Output Arguments:
+ *
+ * pDstMV - pointer to estimated MV
+ * pDstSAD - pointer to minimum SAD
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one of the following
+ * conditions is true:
+ * - at least one of the following pointers is NULL: pSrcRefBuf,
+ * pRefRect, pSrcCurrBuff, pCurrPointPos, pDstMV, pDstSAD or
+ * pMESpec, or
+ * - pSrcCurrBuf is not 8-byte aligned
+ *
+ */
+
+OMXResult omxVCM4P2_BlockMatch_Integer_8x8(
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT refWidth,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ const OMXVCMotionVector *pSrcPreMV,
+ const OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector *pDstMV,
+ OMX_INT *pDstSAD
+)
+{
+ OMX_U8 BlockSize = 8;
+
+ /* Argument error checks */
+ armRetArgErrIf(!armIs8ByteAligned(pSrcCurrBuf), OMX_Sts_BadArgErr);
+
+ return ( armVCM4P2_BlockMatch_Integer(
+ pSrcRefBuf,
+ refWidth,
+ pRefRect,
+ pSrcCurrBuf,
+ pCurrPointPos,
+ pSrcPreMV,
+ pSrcPreSAD,
+ pMESpec,
+ pDstMV,
+ pDstSAD,
+ BlockSize)
+ );
+
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DCT8x8blk.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DCT8x8blk.c
new file mode 100644
index 0000000..a077ac8
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DCT8x8blk.c
@@ -0,0 +1,87 @@
+/**
+ *
+ * File Name: omxVCM4P2_DCT8x8blk.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for 8x8 block DCT
+ *
+ */
+
+#include <math.h>
+#include "omxtypes.h"
+#include "armOMX.h"
+
+#include "armCOMM.h"
+#include "armVCM4P2_DCT_Table.h"
+
+/**
+ * Function: omxVCM4P2_DCT8x8blk (6.2.4.4.1)
+ *
+ * Description:
+ * Computes a 2D forward DCT for a single 8x8 block, as defined in
+ * [ISO14496-2].
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the start of the linearly arranged input buffer; must
+ * be aligned on a 16-byte boundary. Input values (pixel
+ * intensities) are valid in the range [-255,255].
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the start of the linearly arranged output buffer; must
+ * be aligned on a 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, returned if:
+ * - pSrc or pDst is NULL.
+ * - pSrc or pDst is not 16-byte aligned.
+ *
+ */
+
+OMXResult omxVCM4P2_DCT8x8blk (const OMX_S16 *pSrc, OMX_S16 *pDst)
+{
+ OMX_INT x, y, u, v;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pSrc), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pDst), OMX_Sts_BadArgErr);
+
+
+ for (u = 0; u < 8; u++)
+ {
+ for (v = 0; v < 8; v++)
+ {
+ OMX_F64 sum = 0.0;
+ for (x = 0; x < 8; x++)
+ {
+ for (y = 0; y < 8; y++)
+ {
+ sum += pSrc[(x * 8) + y] *
+ armVCM4P2_preCalcDCTCos[x][u] *
+ armVCM4P2_preCalcDCTCos[y][v];
+ }
+ }
+ pDst[(u * 8) + v]= armRoundFloatToS16 (sum);
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
new file mode 100644
index 0000000..51f7bab
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Inter.c
@@ -0,0 +1,115 @@
+/**
+ *
+ * File Name: omxVCM4P2_DecodeBlockCoef_Inter.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for inter reconstruction
+ *
+ */
+
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+
+/**
+ * Function: omxVCM4P2_DecodeBlockCoef_Inter (6.2.5.4.2)
+ *
+ * Description:
+ * Decodes the INTER block coefficients. This function performs inverse
+ * quantization, inverse zigzag positioning, and IDCT (with appropriate
+ * clipping on each step) on the coefficients. The results (residuals) are
+ * placed in a contiguous array of 64 elements. For INTER block, the output
+ * buffer holds the residuals for further reconstruction.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream buffer. There is no boundary check for the bit stream
+ * buffer.
+ * pBitOffset - pointer to the bit position in the byte pointed to by
+ * *ppBitStream. *pBitOffset is valid within [0-7]
+ * QP - quantization parameter
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded, so
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream
+ * pDst - pointer to the decoded residual buffer (a contiguous array of 64
+ * elements of OMX_S16 data type); must be aligned on a 16-byte
+ * boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the following pointers is Null:
+ * ppBitStream, *ppBitStream, pBitOffset , pDst
+ * - *pBitOffset exceeds [0,7]
+ * - QP <= 0.
+ * - pDst is not 16-byte aligned
+ * OMX_Sts_Err - status error. Refer to OMX_Sts_Err of DecodeVLCZigzag_Inter .
+ *
+ */
+OMXResult omxVCM4P2_DecodeBlockCoef_Inter(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_INT QP,
+ OMX_INT shortVideoHeader
+)
+{
+ /* 64 elements are needed but to align it to 16 bytes need
+ 15 more elements of padding */
+ OMX_S16 tempBuf[79];
+ OMX_S16 *pTempBuf1;
+ OMXResult errorCode;
+ /* Aligning the local buffers */
+ pTempBuf1 = armAlignTo16Bytes(tempBuf);
+
+ /* Argument error checks */
+ armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(((QP <= 0) || (QP >= 32)), OMX_Sts_BadArgErr);
+ armRetArgErrIf(((*pBitOffset < 0) || (*pBitOffset > 7)), OMX_Sts_BadArgErr);
+
+
+ /* VLD and zigzag */
+ errorCode = omxVCM4P2_DecodeVLCZigzag_Inter(ppBitStream, pBitOffset,
+ pTempBuf1,shortVideoHeader);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Dequantization */
+ errorCode = omxVCM4P2_QuantInvInter_I(
+ pTempBuf1,
+ QP);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Inverse transform */
+ errorCode = omxVCM4P2_IDCT8x8blk(pTempBuf1, pDst);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
new file mode 100644
index 0000000..a0b2376
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeBlockCoef_Intra.c
@@ -0,0 +1,225 @@
+/**
+ *
+ * File Name: omxVCM4P2_DecodeBlockCoef_Intra.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for intra reconstruction
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P2_DecodeBlockCoef_Intra (6.2.5.4.1)
+ *
+ * Description:
+ * Decodes the INTRA block coefficients. Inverse quantization, inversely
+ * zigzag positioning, and IDCT, with appropriate clipping on each step, are
+ * performed on the coefficients. The results are then placed in the output
+ * frame/plane on a pixel basis. Note: This function will be used only when
+ * at least one non-zero AC coefficient of current block exists in the bit
+ * stream. The DC only condition will be handled in another function.
+ *
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream buffer. There is no boundary check for the bit stream
+ * buffer.
+ * pBitOffset - pointer to the bit position in the byte pointed to by
+ * *ppBitStream. *pBitOffset is valid within [0-7].
+ * step - width of the destination plane
+ * pCoefBufRow - pointer to the coefficient row buffer; must be aligned on
+ * an 8-byte boundary.
+ * pCoefBufCol - pointer to the coefficient column buffer; must be aligned
+ * on an 8-byte boundary.
+ * curQP - quantization parameter of the macroblock which the current block
+ * belongs to
+ * pQPBuf - pointer to the quantization parameter buffer
+ * blockIndex - block index indicating the component type and position as
+ * defined in [ISO14496-2], subclause 6.1.3.8, Figure 6-5.
+ * intraDCVLC - a code determined by intra_dc_vlc_thr and QP. This allows a
+ * mechanism to switch between two VLC for coding of Intra DC
+ * coefficients as per [ISO14496-2], Table 6-21.
+ * ACPredFlag - a flag equal to ac_pred_flag (of luminance) indicating if
+ * the ac coefficients of the first row or first column are
+ * differentially coded for intra coded macroblock.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded, so
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream
+ * pDst - pointer to the block in the destination plane; must be aligned on
+ * an 8-byte boundary.
+ * pCoefBufRow - pointer to the updated coefficient row buffer.
+ * pCoefBufCol - pointer to the updated coefficient column buffer Note:
+ * The coefficient buffers must be updated in accordance with the
+ * update procedure defined in section 6.2.2.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pCoefBufRow, pCoefBufCol,
+ * pQPBuf, pDst.
+ * - *pBitOffset exceeds [0,7]
+ * - curQP exceeds (1, 31)
+ * - blockIndex exceeds [0,5]
+ * - step is not the multiple of 8
+ * - a pointer alignment requirement was violated.
+ * OMX_Sts_Err - status error. Refer to OMX_Sts_Err of DecodeVLCZigzag_Intra.
+ *
+ */
+
+OMXResult omxVCM4P2_DecodeBlockCoef_Intra(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT *pBitOffset,
+ OMX_U8 *pDst,
+ OMX_INT step,
+ OMX_S16 *pCoefBufRow,
+ OMX_S16 *pCoefBufCol,
+ OMX_U8 curQP,
+ const OMX_U8 *pQPBuf,
+ OMX_INT blockIndex,
+ OMX_INT intraDCVLC,
+ OMX_INT ACPredFlag,
+ OMX_INT shortVideoHeader
+ )
+{
+ OMX_S16 tempBuf1[79], tempBuf2[79];
+ OMX_S16 *pTempBuf1, *pTempBuf2;
+ OMX_INT predDir, predACDir, i, j, count;
+ OMX_INT predQP;
+ OMXVCM4P2VideoComponent videoComp;
+ OMXResult errorCode;
+
+ /* Argument error checks */
+ armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pCoefBufRow == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pCoefBufCol == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pQPBuf == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs8ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(((curQP <= 0) || (curQP >= 32)), OMX_Sts_BadArgErr);
+ armRetArgErrIf((*pBitOffset < 0) || (*pBitOffset >7), OMX_Sts_BadArgErr);
+ armRetArgErrIf((blockIndex < 0) || (blockIndex > 5), OMX_Sts_BadArgErr);
+ armRetArgErrIf((step % 8) != 0, OMX_Sts_BadArgErr);
+
+
+ /* Aligning the local buffers */
+ pTempBuf1 = armAlignTo16Bytes(tempBuf1);
+ pTempBuf2 = armAlignTo16Bytes(tempBuf2);
+
+ /* Setting the AC prediction direction and prediction direction */
+ armVCM4P2_SetPredDir(
+ blockIndex,
+ pCoefBufRow,
+ pCoefBufCol,
+ &predDir,
+ &predQP,
+ pQPBuf);
+
+ predACDir = predDir;
+
+ armRetArgErrIf(((predQP <= 0) || (predQP >= 32)), OMX_Sts_BadArgErr);
+
+ if (ACPredFlag == 0)
+ {
+ predACDir = OMX_VC_NONE;
+ }
+
+ /* Setting the videoComp */
+ if (blockIndex <= 3)
+ {
+ videoComp = OMX_VC_LUMINANCE;
+ }
+ else
+ {
+ videoComp = OMX_VC_CHROMINANCE;
+ }
+
+
+ /* VLD and zigzag */
+ if (intraDCVLC == 1)
+ {
+ errorCode = omxVCM4P2_DecodeVLCZigzag_IntraDCVLC(
+ ppBitStream,
+ pBitOffset,
+ pTempBuf1,
+ predACDir,
+ shortVideoHeader,
+ videoComp);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+ }
+ else
+ {
+ errorCode = omxVCM4P2_DecodeVLCZigzag_IntraACVLC(
+ ppBitStream,
+ pBitOffset,
+ pTempBuf1,
+ predACDir,
+ shortVideoHeader);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+ }
+
+ /* AC DC prediction */
+ errorCode = omxVCM4P2_PredictReconCoefIntra(
+ pTempBuf1,
+ pCoefBufRow,
+ pCoefBufCol,
+ curQP,
+ predQP,
+ predDir,
+ ACPredFlag,
+ videoComp);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Dequantization */
+ errorCode = omxVCM4P2_QuantInvIntra_I(
+ pTempBuf1,
+ curQP,
+ videoComp,
+ shortVideoHeader);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Inverse transform */
+ errorCode = omxVCM4P2_IDCT8x8blk (pTempBuf1, pTempBuf2);
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ /* Placing the linear array into the destination plane and clipping
+ it to 0 to 255 */
+ for (j = 0, count = 0; j < 8; j++)
+ {
+ for(i = 0; i < 8; i++, count++)
+ {
+ pDst[i] = armClip (0, 255, pTempBuf2[count]);
+ }
+ pDst += step;
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP.c
new file mode 100644
index 0000000..7e159b7
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodePadMV_PVOP.c
@@ -0,0 +1,243 @@
+/**
+ *
+ * File Name: omxVCM4P2_DecodePadMV_PVOP.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for decoding MV and padding the same
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM_Bitstream.h"
+#include "armCOMM.h"
+#include "armVCM4P2_Huff_Tables_VLC.h"
+
+
+
+/**
+ * Function: omxVCM4P2_DecodePadMV_PVOP (6.2.5.1.1)
+ *
+ * Description:
+ * Decodes and pads the four motion vectors associated with a non-intra P-VOP
+ * macroblock. For macroblocks of type OMX_VC_INTER4V, the output MV is
+ * padded as specified in [ISO14496-2], subclause 7.6.1.6. Otherwise, for
+ * macroblocks of types other than OMX_VC_INTER4V, the decoded MV is copied to
+ * all four output MV buffer entries.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream buffer
+ * pBitOffset - pointer to the bit position in the byte pointed to by
+ * *ppBitStream. *pBitOffset is valid within [0-7].
+ * pSrcMVLeftMB, pSrcMVUpperMB, and pSrcMVUpperRightMB - pointers to the
+ * motion vector buffers of the macroblocks specially at the left,
+ * upper, and upper-right side of the current macroblock,
+ * respectively; a value of NULL indicates unavailability. Note:
+ * Any neighborhood macroblock outside the current VOP or video
+ * packet or outside the current GOB (when short_video_header is
+ * 1 ) for which gob_header_empty is 0 is treated as
+ * transparent, according to [ISO14496-2], subclause 7.6.5.
+ * fcodeForward - a code equal to vop_fcode_forward in MPEG-4 bit stream
+ * syntax
+ * MBType - the type of the current macroblock. If MBType is not equal to
+ * OMX_VC_INTER4V, the destination motion vector buffer is still
+ * filled with the same decoded vector.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded, so
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream
+ * pDstMVCurMB - pointer to the motion vector buffer for the current
+ * macroblock; contains four decoded motion vectors
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pDstMVCurMB
+ * - *pBitOffset exceeds [0,7]
+ * - fcodeForward exceeds (0,7]
+ * - MBType less than zero
+ * - motion vector buffer is not 4-byte aligned.
+ * OMX_Sts_Err - status error
+ *
+ */
+
+OMXResult omxVCM4P2_DecodePadMV_PVOP(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT * pBitOffset,
+ OMXVCMotionVector * pSrcMVLeftMB,
+ OMXVCMotionVector *pSrcMVUpperMB,
+ OMXVCMotionVector * pSrcMVUpperRightMB,
+ OMXVCMotionVector * pDstMVCurMB,
+ OMX_INT fcodeForward,
+ OMXVCM4P2MacroblockType MBType
+ )
+{
+ OMXVCMotionVector diffMV;
+ OMXVCMotionVector dstMVPredME[12];
+ OMX_INT iBlk, i, count = 1;
+ OMX_S32 mvHorResidual = 1, mvVerResidual = 1, mvHorData, mvVerData;
+ OMX_S8 scaleFactor, index;
+ OMX_S16 high, low, range;
+
+
+ /* Argument error checks */
+ armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDstMVCurMB == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(((*pBitOffset < 0) || (*pBitOffset > 7)), OMX_Sts_BadArgErr);
+ armRetArgErrIf(((fcodeForward < 1) || (fcodeForward > 7)), \
+ OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs4ByteAligned(pDstMVCurMB), OMX_Sts_BadArgErr);
+
+ if ((MBType == OMX_VC_INTRA) ||
+ (MBType == OMX_VC_INTRA_Q)
+ )
+ {
+ /* All MV's are zero */
+ for (i = 0; i < 4; i++)
+ {
+ pDstMVCurMB[i].dx = 0;
+ pDstMVCurMB[i].dy = 0;
+ }
+
+ return OMX_Sts_NoErr;
+ }
+
+ if ((MBType == OMX_VC_INTER4V) || (MBType == OMX_VC_INTER4V_Q))
+ {
+ count = 4;
+ }
+ else if ((MBType == OMX_VC_INTER) || (MBType == OMX_VC_INTER_Q))
+ {
+ count = 1;
+ }
+
+ /* Calculating the scale factor */
+ scaleFactor = 1 << (fcodeForward -1);
+ high = ( 32 * scaleFactor) - 1;
+ low = ( (-32) * scaleFactor);
+ range = ( 64 * scaleFactor);
+
+ /* Huffman decoding and MV reconstruction */
+ for (iBlk = 0; iBlk < count; iBlk++)
+ {
+
+ /* Huffman decoding to get Horizontal data and residual */
+ index = armUnPackVLC32(ppBitStream, pBitOffset,
+ armVCM4P2_aVlcMVD);
+ armRetDataErrIf(index == -1, OMX_Sts_Err);
+
+ mvHorData = index - 32;
+
+ if ((fcodeForward > 1) && (mvHorData != 0))
+ {
+ mvHorResidual = (OMX_S32) armGetBits(ppBitStream,
+ pBitOffset, (fcodeForward -1));
+ }
+
+ /* Huffman decoding to get Vertical data and residual */
+ index = armUnPackVLC32(ppBitStream, pBitOffset, armVCM4P2_aVlcMVD);
+ armRetDataErrIf(index == -1, OMX_Sts_Err);
+
+ mvVerData = index - 32;
+
+ if ((fcodeForward > 1) && (mvVerData != 0))
+ {
+ mvVerResidual = (OMX_S32) armGetBits(ppBitStream,
+ pBitOffset, (fcodeForward -1));
+ }
+
+ /* Calculating the differtial MV */
+ if ( (scaleFactor == 1) || (mvHorData == 0) )
+ {
+ diffMV.dx = mvHorData;
+ }
+ else
+ {
+ diffMV.dx = ((armAbs(mvHorData) - 1) * fcodeForward)
+ + mvHorResidual + 1;
+ if (mvHorData < 0)
+ {
+ diffMV.dx = -diffMV.dx;
+ }
+ }
+
+ if ( (scaleFactor == 1) || (mvVerData == 0) )
+ {
+ diffMV.dy = mvVerData;
+ }
+ else
+ {
+ diffMV.dy = ((armAbs(mvVerData) - 1) * fcodeForward)
+ + mvVerResidual + 1;
+ if (mvVerData < 0)
+ {
+ diffMV.dy = -diffMV.dy;
+ }
+ }
+
+ /* Find the predicted vector */
+ omxVCM4P2_FindMVpred (
+ pDstMVCurMB,
+ pSrcMVLeftMB,
+ pSrcMVUpperMB,
+ pSrcMVUpperRightMB,
+ &pDstMVCurMB[iBlk],
+ dstMVPredME,
+ iBlk);
+
+ /* Adding the difference to the predicted MV to reconstruct MV */
+ pDstMVCurMB[iBlk].dx += diffMV.dx;
+ pDstMVCurMB[iBlk].dy += diffMV.dy;
+
+ /* Checking the range and keeping it within the limits */
+ if ( pDstMVCurMB[iBlk].dx < low )
+ {
+ pDstMVCurMB[iBlk].dx += range;
+ }
+ if (pDstMVCurMB[iBlk].dx > high)
+ {
+ pDstMVCurMB[iBlk].dx -= range;
+ }
+
+ if ( pDstMVCurMB[iBlk].dy < low )
+ {
+ pDstMVCurMB[iBlk].dy += range;
+ }
+ if (pDstMVCurMB[iBlk].dy > high)
+ {
+ pDstMVCurMB[iBlk].dy -= range;
+ }
+ }
+
+ if ((MBType == OMX_VC_INTER) || (MBType == OMX_VC_INTER_Q))
+ {
+ pDstMVCurMB[1] = pDstMVCurMB[0];
+ pDstMVCurMB[2] = pDstMVCurMB[0];
+ pDstMVCurMB[3] = pDstMVCurMB[0];
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter.c
new file mode 100644
index 0000000..88a8d04
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_Inter.c
@@ -0,0 +1,120 @@
+/**
+ *
+ * File Name: omxVCM4P2_DecodeVLCZigzag_Inter.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for zigzag scanning and VLC decoding
+ * for inter block.
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM_Bitstream.h"
+#include "armCOMM.h"
+#include "armVCM4P2_Huff_Tables_VLC.h"
+#include "armVCM4P2_ZigZag_Tables.h"
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeVLCZigzag_Inter (6.2.5.2.3)
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan for one inter-coded block.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the stream buffer
+ * pBitOffset - pointer to the next available bit in the current stream
+ * byte referenced by *ppBitStream. The parameter *pBitOffset is
+ * valid within the range [0-7].
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded such
+ * that it points to the current byte in the stream buffer
+ * pBitOffset - *pBitOffset is updated after decoding such that it points
+ * to the next available bit in the stream byte referenced by
+ * *ppBitStream
+ * pDst - pointer to the coefficient buffer of current block; must be
+ * 4-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pDst
+ * - pDst is not 4-byte aligned
+ * - *pBitOffset exceeds [0,7]
+ * OMX_Sts_Err - status error, if:
+ * - At least one mark bit is equal to zero
+ * - Encountered an illegal stream code that cannot be found in the VLC table
+ * - Encountered an illegal code in the VLC FLC table
+ * - The number of coefficients is greater than 64
+ *
+ */
+
+OMXResult omxVCM4P2_DecodeVLCZigzag_Inter(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_INT shortVideoHeader
+)
+{
+ OMX_U8 last,start = 0;
+ const OMX_U8 *pZigzagTable = armVCM4P2_aClassicalZigzagScan;
+ OMXResult errorCode;
+
+ /* Argument error checks */
+ armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs4ByteAligned(pDst), OMX_Sts_BadArgErr);
+
+ errorCode = armVCM4P2_GetVLCBits (
+ ppBitStream,
+ pBitOffset,
+ pDst,
+ shortVideoHeader,
+ start,
+ &last,
+ 11,
+ 42,
+ 2,
+ 5,
+ armVCM4P2_InterL0RunIdx,
+ armVCM4P2_InterVlcL0,
+ armVCM4P2_InterL1RunIdx,
+ armVCM4P2_InterVlcL1,
+ armVCM4P2_InterL0LMAX,
+ armVCM4P2_InterL1LMAX,
+ armVCM4P2_InterL0RMAX,
+ armVCM4P2_InterL1RMAX,
+ pZigzagTable );
+ armRetDataErrIf((errorCode != OMX_Sts_NoErr), errorCode);
+
+ if (last == 0)
+ {
+ return OMX_Sts_Err;
+ }
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC.c
new file mode 100644
index 0000000..96593d1
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraACVLC.c
@@ -0,0 +1,103 @@
+/**
+ *
+ * File Name: omxVCM4P2_DecodeVLCZigzag_IntraACVLC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for zigzag scanning and VLC decoding
+ * for intra block.
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeVLCZigzag_IntraACVLC (6.2.5.2.2)
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan of AC and DC coefficients
+ * for one intra block. Two versions of the function (DCVLC and ACVLC) are
+ * provided in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the
+ * bitstream buffer
+ * pBitOffset - pointer to the bit position in the current byte referenced
+ * by *ppBitStream. The parameter *pBitOffset is valid in the
+ * range [0-7]. Bit Position in one byte: |Most Least| *pBitOffset
+ * |0 1 2 3 4 5 6 7|
+ * predDir - AC prediction direction; used to select the zigzag scan
+ * pattern; takes one of the following values: OMX_VC_NONE - AC
+ * prediction not used; performs classical zigzag scan.
+ * OMX_VC_HORIZONTAL - Horizontal prediction; performs
+ * alternate-vertical zigzag scan; OMX_VC_VERTICAL - Vertical
+ * prediction; performs alternate-horizontal zigzag scan.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ * videoComp - video component type (luminance or chrominance) of the
+ * current block
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded such
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated such that it points to the current
+ * bit position in the byte pointed by *ppBitStream
+ * pDst - pointer to the coefficient buffer of current block; must be
+ * 4-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments At least one of the following
+ * pointers is NULL: ppBitStream, *ppBitStream, pBitOffset, pDst,
+ * or At least one of the following conditions is true:
+ * *pBitOffset exceeds [0,7], preDir exceeds [0,2], or pDst is
+ * not 4-byte aligned
+ * OMX_Sts_Err In DecodeVLCZigzag_IntraDCVLC, dc_size > 12 At least one of
+ * mark bits equals zero Illegal stream encountered; code cannot
+ * be located in VLC table Forbidden code encountered in the VLC
+ * FLC table The number of coefficients is greater than 64
+ *
+ */
+
+
+OMXResult omxVCM4P2_DecodeVLCZigzag_IntraACVLC(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_U8 predDir,
+ OMX_INT shortVideoHeader
+)
+{
+ OMX_U8 start = 0;
+
+ return armVCM4P2_DecodeVLCZigzag_Intra(
+ ppBitStream,
+ pBitOffset,
+ pDst,
+ predDir,
+ shortVideoHeader,
+ start);
+}
+
+/* End of file */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC.c
new file mode 100644
index 0000000..95e00d7
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_DecodeVLCZigzag_IntraDCVLC.c
@@ -0,0 +1,170 @@
+/**
+ *
+ * File Name: omxVCM4P2_DecodeVLCZigzag_IntraDCVLC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for zigzag scanning and VLC decoding
+ * for intra block.
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM_Bitstream.h"
+#include "armCOMM.h"
+#include "armVCM4P2_Huff_Tables_VLC.h"
+#include "armVCM4P2_ZigZag_Tables.h"
+
+
+
+
+/**
+ * Function: omxVCM4P2_DecodeVLCZigzag_IntraDCVLC (6.2.5.2.2)
+ *
+ * Description:
+ * Performs VLC decoding and inverse zigzag scan of AC and DC coefficients
+ * for one intra block. Two versions of the function (DCVLC and ACVLC) are
+ * provided in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the
+ * bitstream buffer
+ * pBitOffset - pointer to the bit position in the current byte referenced
+ * by *ppBitStream. The parameter *pBitOffset is valid in the
+ * range [0-7].
+ * Bit Position in one byte: |Most Least|
+ * *pBitOffset |0 1 2 3 4 5 6 7|
+ * predDir - AC prediction direction; used to select the zigzag scan
+ * pattern; takes one of the following values:
+ * - OMX_VC_NONE - AC prediction not used;
+ * performs classical zigzag scan.
+ * - OMX_VC_HORIZONTAL - Horizontal prediction;
+ * performs alternate-vertical zigzag scan;
+ * - OMX_VC_VERTICAL - Vertical prediction;
+ * performs alternate-horizontal zigzag scan.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ * videoComp - video component type (luminance or chrominance) of the
+ * current block
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is decoded such
+ * that it points to the current byte in the bit stream buffer
+ * pBitOffset - *pBitOffset is updated such that it points to the current
+ * bit position in the byte pointed by *ppBitStream
+ * pDst - pointer to the coefficient buffer of current block; must be
+ * 4-byte aligned.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the following pointers is NULL:
+ * ppBitStream, *ppBitStream, pBitOffset, pDst
+ * - *pBitOffset exceeds [0,7]
+ * - preDir exceeds [0,2]
+ * - pDst is not 4-byte aligned
+ * OMX_Sts_Err - if:
+ * - In DecodeVLCZigzag_IntraDCVLC, dc_size > 12
+ * - At least one of mark bits equals zero
+ * - Illegal stream encountered; code cannot be located in VLC table
+ * - Forbidden code encountered in the VLC FLC table.
+ * - The number of coefficients is greater than 64
+ *
+ */
+
+OMXResult omxVCM4P2_DecodeVLCZigzag_IntraDCVLC(
+ const OMX_U8 ** ppBitStream,
+ OMX_INT * pBitOffset,
+ OMX_S16 * pDst,
+ OMX_U8 predDir,
+ OMX_INT shortVideoHeader,
+ OMXVCM4P2VideoComponent videoComp
+)
+{
+ /* Dummy initilaization to remove compilation error */
+ OMX_S8 DCValueSize = 0;
+ OMX_U16 powOfSize, fetchDCbits;
+ OMX_U8 start = 1;
+
+ /* Argument error checks */
+ armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs4ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf((*pBitOffset < 0) || (*pBitOffset > 7), OMX_Sts_BadArgErr);
+ armRetArgErrIf((predDir > 2), OMX_Sts_BadArgErr);
+
+ /* Insert the code into the bitstream */
+ if (videoComp == OMX_VC_LUMINANCE)
+ {
+ DCValueSize = armUnPackVLC32(ppBitStream,
+ pBitOffset, armVCM4P2_aIntraDCLumaIndex);
+ }
+ else if (videoComp == OMX_VC_CHROMINANCE)
+ {
+ DCValueSize = armUnPackVLC32(ppBitStream,
+ pBitOffset, armVCM4P2_aIntraDCChromaIndex);
+ }
+ armRetDataErrIf(DCValueSize == -1, OMX_Sts_Err);
+ armRetDataErrIf(DCValueSize > 12, OMX_Sts_Err);
+
+
+ if (DCValueSize == 0)
+ {
+ pDst[0] = 0;
+ }
+ else
+ {
+ fetchDCbits = (OMX_U16) armGetBits(ppBitStream, pBitOffset, \
+ DCValueSize);
+
+ if ( (fetchDCbits >> (DCValueSize - 1)) == 0)
+ {
+ /* calulate pow */
+ powOfSize = (1 << DCValueSize);
+
+ pDst[0] = (OMX_S16) (fetchDCbits ^ (powOfSize - 1));
+ pDst[0] = -pDst[0];
+ }
+ else
+ {
+ pDst[0] = fetchDCbits;
+ }
+
+ if (DCValueSize > 8)
+ {
+ /* reading and checking the marker bit*/
+ armRetDataErrIf (armGetBits(ppBitStream, pBitOffset, 1) == 0, \
+ OMX_Sts_Err);
+ }
+ }
+
+ return armVCM4P2_DecodeVLCZigzag_Intra(
+ ppBitStream,
+ pBitOffset,
+ pDst,
+ predDir,
+ shortVideoHeader,
+ start);
+}
+
+/* End of file */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeMV.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeMV.c
new file mode 100644
index 0000000..def2b6d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeMV.c
@@ -0,0 +1,212 @@
+/**
+ *
+ * File Name: omxVCM4P2_EncodeMV.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for predicting MV of MB
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armCOMM_Bitstream.h"
+#include "armVCM4P2_Huff_Tables_VLC.h"
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeMV (6.2.4.5.4)
+ *
+ * Description:
+ * Predicts a motion vector for the current macroblock, encodes the
+ * difference, and writes the output to the stream buffer. The input MVs
+ * pMVCurMB, pSrcMVLeftMB, pSrcMVUpperMB, and pSrcMVUpperRightMB should lie
+ * within the ranges associated with the input parameter fcodeForward, as
+ * described in [ISO14496-2], subclause 7.6.3. This function provides a
+ * superset of the functionality associated with the function
+ * omxVCM4P2_FindMVpred.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the bitstream buffer
+ * pBitOffset - index of the first free (next available) bit in the stream
+ * buffer referenced by *ppBitStream, valid in the range 0 to 7.
+ * pMVCurMB - pointer to the current macroblock motion vector; a value of
+ * NULL indicates unavailability.
+ * pSrcMVLeftMB - pointer to the source left macroblock motion vector; a
+ * value of NULLindicates unavailability.
+ * pSrcMVUpperMB - pointer to source upper macroblock motion vector; a
+ * value of NULL indicates unavailability.
+ * pSrcMVUpperRightMB - pointer to source upper right MB motion vector; a
+ * value of NULL indicates unavailability.
+ * fcodeForward - an integer with values from 1 to 7; used in encoding
+ * motion vectors related to search range, as described in
+ * [ISO14496-2], subclause 7.6.3.
+ * MBType - macro block type, valid in the range 0 to 5
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - updated pointer to the current byte in the bit stream
+ * buffer
+ * pBitOffset - updated index of the next available bit position in stream
+ * buffer referenced by *ppBitStream
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ * - At least one of the following pointers is NULL: ppBitStream,
+ * *ppBitStream, pBitOffset, pMVCurMB
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ * - fcodeForward <= 0, or fcodeForward > 7, or MBType < 0.
+ *
+ */
+
+OMXResult omxVCM4P2_EncodeMV(
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMXVCMotionVector * pMVCurMB,
+ const OMXVCMotionVector * pSrcMVLeftMB,
+ const OMXVCMotionVector * pSrcMVUpperMB,
+ const OMXVCMotionVector * pSrcMVUpperRightMB,
+ OMX_INT fcodeForward,
+ OMXVCM4P2MacroblockType MBType
+)
+{
+ OMXVCMotionVector dstMVPred, diffMV;
+ OMXVCMotionVector dstMVPredME[12];
+ /* Initialized to remove compilation warning */
+ OMX_INT iBlk, i, count = 1;
+ OMX_S32 mvHorResidual, mvVerResidual, mvHorData, mvVerData;
+ OMX_U8 scaleFactor, index;
+
+ /* Argument error checks */
+ armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pMVCurMB == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(((*pBitOffset < 0) || (*pBitOffset > 7)), OMX_Sts_BadArgErr);
+ armRetArgErrIf(((fcodeForward < 1) || (fcodeForward > 7)), \
+ OMX_Sts_BadArgErr);
+
+ if ((MBType == OMX_VC_INTRA) ||
+ (MBType == OMX_VC_INTRA_Q)
+ )
+ {
+ /* No candidate vectors hence make them zero */
+ for (i = 0; i < 12; i++)
+ {
+ dstMVPredME[i].dx = 0;
+ dstMVPredME[i].dy = 0;
+ }
+
+ return OMX_Sts_NoErr;
+ }
+
+ if ((MBType == OMX_VC_INTER4V) || (MBType == OMX_VC_INTER4V_Q))
+ {
+ count = 4;
+ }
+ else if ((MBType == OMX_VC_INTER) || (MBType == OMX_VC_INTER_Q))
+ {
+ count = 1;
+ }
+
+ /* Calculating the scale factor */
+ scaleFactor = 1 << (fcodeForward -1);
+
+ for (iBlk = 0; iBlk < count; iBlk++)
+ {
+
+ /* Find the predicted vector */
+ omxVCM4P2_FindMVpred (
+ pMVCurMB,
+ pSrcMVLeftMB,
+ pSrcMVUpperMB,
+ pSrcMVUpperRightMB,
+ &dstMVPred,
+ dstMVPredME,
+ iBlk );
+
+ /* Calculating the differential motion vector (diffMV) */
+ diffMV.dx = pMVCurMB[iBlk].dx - dstMVPred.dx;
+ diffMV.dy = pMVCurMB[iBlk].dy - dstMVPred.dy;
+
+ /* Calculating the mv_data and mv_residual for Horizantal MV */
+ if (diffMV.dx == 0)
+ {
+ mvHorResidual = 0;
+ mvHorData = 0;
+ }
+ else
+ {
+ mvHorResidual = ( armAbs(diffMV.dx) - 1) % scaleFactor;
+ mvHorData = (armAbs(diffMV.dx) - mvHorResidual + (scaleFactor - 1))
+ / scaleFactor;
+ if (diffMV.dx < 0)
+ {
+ mvHorData = -mvHorData;
+ }
+ }
+
+ /* Calculating the mv_data and mv_residual for Vertical MV */
+ if (diffMV.dy == 0)
+ {
+ mvVerResidual = 0;
+ mvVerData = 0;
+ }
+ else
+ {
+ mvVerResidual = ( armAbs(diffMV.dy) - 1) % scaleFactor;
+ mvVerData = (armAbs(diffMV.dy) - mvVerResidual + (scaleFactor - 1))
+ / scaleFactor;
+ if (diffMV.dy < 0)
+ {
+ mvVerData = -mvVerData;
+ }
+ }
+
+ /* Huffman encoding */
+
+ /* The index is actually calculate as
+ index = ((float) (mvHorData/2) + 16) * 2,
+ meaning the MV data is halfed and then normalized
+ to begin with zero and then doubled to take care of indexing
+ the fractional part included */
+ index = mvHorData + 32;
+ armPackVLC32 (ppBitStream, pBitOffset, armVCM4P2_aVlcMVD[index]);
+ if ((fcodeForward > 1) && (diffMV.dx != 0))
+ {
+ armPackBits (ppBitStream, pBitOffset, mvHorResidual, (fcodeForward -1));
+ }
+
+ /* The index is actually calculate as
+ index = ((float) (mvVerData/2) + 16) * 2,
+ meaning the MV data is halfed and then normalized
+ to begin with zero and then doubled to take care of indexing
+ the fractional part included */
+ index = mvVerData + 32;
+ armPackVLC32 (ppBitStream, pBitOffset, armVCM4P2_aVlcMVD[index]);
+ if ((fcodeForward > 1) && (diffMV.dy != 0))
+ {
+ armPackBits (ppBitStream, pBitOffset, mvVerResidual, (fcodeForward -1));
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_Inter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_Inter.c
new file mode 100644
index 0000000..b6c73ea
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_Inter.c
@@ -0,0 +1,112 @@
+/**
+ *
+ * File Name: omxVCM4P2_EncodeVLCZigzag_Inter.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for zigzag scanning and VLC encoding
+ * for inter block.
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM_Bitstream.h"
+#include "armCOMM.h"
+#include "armVCM4P2_Huff_Tables_VLC.h"
+#include "armVCM4P2_ZigZag_Tables.h"
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeVLCZigzag_Inter (6.2.4.5.3)
+ *
+ * Description:
+ * Performs classical zigzag scanning and VLC encoding for one inter block.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - pointer to the pointer to the current byte in the bit
+ * stream
+ * pBitOffset - pointer to the bit position in the byte pointed by
+ * *ppBitStream. Valid within 0 to 7
+ * pQDctBlkCoef - pointer to the quantized DCT coefficient
+ * pattern - block pattern which is used to decide whether this block is
+ * encoded
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is encoded so that
+ * it points to the current byte in the bit stream buffer.
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments
+ * - At least one of the pointers: is NULL: ppBitStream, *ppBitStream,
+ * pBitOffset, pQDctBlkCoef
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ *
+ */
+OMXResult omxVCM4P2_EncodeVLCZigzag_Inter(
+ OMX_U8 **ppBitStream,
+ OMX_INT * pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader
+)
+{
+ OMX_U8 start = 0;
+ const OMX_U8 *pZigzagTable = armVCM4P2_aClassicalZigzagScan;
+
+ /* Argument error checks */
+ armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pQDctBlkCoef == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((*pBitOffset < 0) || (*pBitOffset >7), OMX_Sts_BadArgErr);
+
+ if (pattern)
+ {
+ armVCM4P2_PutVLCBits (
+ ppBitStream,
+ pBitOffset,
+ pQDctBlkCoef,
+ shortVideoHeader,
+ start,
+ 26,
+ 40,
+ 10,
+ 1,
+ armVCM4P2_InterL0RunIdx,
+ armVCM4P2_InterVlcL0,
+ armVCM4P2_InterL1RunIdx,
+ armVCM4P2_InterVlcL1,
+ armVCM4P2_InterL0LMAX,
+ armVCM4P2_InterL1LMAX,
+ armVCM4P2_InterL0RMAX,
+ armVCM4P2_InterL1RMAX,
+ pZigzagTable
+ );
+ } /* Pattern check ends*/
+
+ return OMX_Sts_NoErr;
+
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraACVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraACVLC.c
new file mode 100644
index 0000000..d047942
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraACVLC.c
@@ -0,0 +1,97 @@
+/**
+ *
+ * File Name: omxVCM4P2_EncodeVLCZigzag_IntraACVLC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for zigzag scanning and VLC encoding
+ * for intra block.
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+
+
+/**
+ * Function: omxVCM4P2_EncodeVLCZigzag_IntraACVLC (6.2.4.5.2)
+ *
+ * Description:
+ * Performs zigzag scan and VLC encoding of AC and DC coefficients for one
+ * intra block. Two versions of the function (DCVLC and ACVLC) are provided
+ * in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding.
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the bitstream
+ * pBitOffset - pointer to the bit position in the byte pointed by
+ * *ppBitStream. Valid within 0 to 7.
+ * pQDctBlkCoef - pointer to the quantized DCT coefficient
+ * predDir - AC prediction direction, which is used to decide the zigzag
+ * scan pattern; takes one of the following values:
+ * - OMX_VC_NONE - AC prediction not used.
+ * Performs classical zigzag scan.
+ * - OMX_VC_HORIZONTAL - Horizontal prediction.
+ * Performs alternate-vertical zigzag scan.
+ * - OMX_VC_VERTICAL - Vertical prediction.
+ * Performs alternate-horizontal zigzag scan.
+ * pattern - block pattern which is used to decide whether this block is
+ * encoded
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is encoded, so
+ * that it points to the current byte in the bit stream buffer.
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ * - At least one of the following pointers is NULL: ppBitStream,
+ * *ppBitStream, pBitOffset, pQDctBlkCoef.
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ * - PredDir is not one of: OMX_VC_NONE, OMX_VC_HORIZONTAL, or
+ * OMX_VC_VERTICAL.
+ * - VideoComp is not one component of enum OMXVCM4P2VideoComponent.
+ *
+ */
+
+OMXResult omxVCM4P2_EncodeVLCZigzag_IntraACVLC(
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 predDir,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader
+)
+{
+ OMX_U8 start = 0;
+
+ return armVCM4P2_EncodeVLCZigzag_Intra(
+ ppBitStream,
+ pBitOffset,
+ pQDctBlkCoef,
+ predDir,
+ pattern,
+ shortVideoHeader,
+ start);
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraDCVLC.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraDCVLC.c
new file mode 100644
index 0000000..c57acd2
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_EncodeVLCZigzag_IntraDCVLC.c
@@ -0,0 +1,160 @@
+/**
+ *
+ * File Name: omxVCM4P2_EncodeVLCZigzag_IntraDCVLC.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for zigzag scanning and VLC encoding
+ * for intra block.
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM_Bitstream.h"
+#include "armCOMM.h"
+#include "armVCM4P2_Huff_Tables_VLC.h"
+#include "armVCM4P2_ZigZag_Tables.h"
+
+
+
+/**
+ * Function: omxVCM4P2_EncodeVLCZigzag_IntraDCVLC (6.2.4.5.2)
+ *
+ * Description:
+ * Performs zigzag scan and VLC encoding of AC and DC coefficients for one
+ * intra block. Two versions of the function (DCVLC and ACVLC) are provided
+ * in order to support the two different methods of processing DC
+ * coefficients, as described in [ISO14496-2], subclause 7.4.1.4, "Intra DC
+ * Coefficient Decoding for the Case of Switched VLC Encoding".
+ *
+ * Input Arguments:
+ *
+ * ppBitStream - double pointer to the current byte in the bitstream
+ * pBitOffset - pointer to the bit position in the byte pointed by
+ * *ppBitStream. Valid within 0 to 7.
+ * pQDctBlkCoef - pointer to the quantized DCT coefficient
+ * predDir - AC prediction direction, which is used to decide the zigzag
+ * scan pattern; takes one of the following values:
+ * - OMX_VC_NONE - AC prediction not used.
+ * Performs classical zigzag scan.
+ * - OMX_VC_HORIZONTAL - Horizontal prediction.
+ * Performs alternate-vertical zigzag scan.
+ * - OMX_VC_VERTICAL - Vertical prediction.
+ * Performs alternate-horizontal zigzag scan.
+ * pattern - block pattern which is used to decide whether this block is
+ * encoded
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; escape modes 0-3 are used if
+ * shortVideoHeader==0, and escape mode 4 is used when
+ * shortVideoHeader==1.
+ * videoComp - video component type (luminance, chrominance) of the current
+ * block
+ *
+ * Output Arguments:
+ *
+ * ppBitStream - *ppBitStream is updated after the block is encoded, so
+ * that it points to the current byte in the bit stream buffer.
+ * pBitOffset - *pBitOffset is updated so that it points to the current bit
+ * position in the byte pointed by *ppBitStream.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ * - At least one of the following pointers is NULL: ppBitStream,
+ * *ppBitStream, pBitOffset, pQDctBlkCoef.
+ * - *pBitOffset < 0, or *pBitOffset >7.
+ * - PredDir is not one of: OMX_VC_NONE, OMX_VC_HORIZONTAL, or
+ * OMX_VC_VERTICAL.
+ * - VideoComp is not one component of enum OMXVCM4P2VideoComponent.
+ *
+ */
+
+OMXResult omxVCM4P2_EncodeVLCZigzag_IntraDCVLC(
+ OMX_U8 **ppBitStream,
+ OMX_INT *pBitOffset,
+ const OMX_S16 *pQDctBlkCoef,
+ OMX_U8 predDir,
+ OMX_U8 pattern,
+ OMX_INT shortVideoHeader,
+ OMXVCM4P2VideoComponent videoComp
+)
+{
+ OMX_S16 dcValue, powOfSize;
+ OMX_U8 DCValueSize, start = 1;
+ OMX_U16 absDCValue;
+
+ /* Argument error checks */
+ armRetArgErrIf(ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(*ppBitStream == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pBitOffset == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pQDctBlkCoef == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((*pBitOffset < 0) || (*pBitOffset >7), OMX_Sts_BadArgErr);
+ armRetArgErrIf((videoComp != OMX_VC_LUMINANCE) && (videoComp != OMX_VC_CHROMINANCE), OMX_Sts_BadArgErr);
+ armRetArgErrIf((predDir != OMX_VC_NONE) && (predDir != OMX_VC_HORIZONTAL) && (predDir != OMX_VC_VERTICAL) , OMX_Sts_BadArgErr);
+
+ if (pattern)
+ {
+ dcValue = pQDctBlkCoef[0];
+ absDCValue = armAbs(dcValue);
+
+ /* Find the size */
+ DCValueSize = armLogSize (absDCValue);
+ absDCValue = armAbs(dcValue);
+
+ /* Insert the code into the bitstream */
+ if (videoComp == OMX_VC_LUMINANCE)
+ {
+
+ armPackVLC32 (ppBitStream, pBitOffset,
+ armVCM4P2_aIntraDCLumaIndex[DCValueSize]);
+ }
+ else if (videoComp == OMX_VC_CHROMINANCE)
+ {
+
+ armPackVLC32 (ppBitStream, pBitOffset,
+ armVCM4P2_aIntraDCChromaIndex[DCValueSize]);
+ }
+
+ /* Additional code generation in case of negative
+ dc value the additional */
+ if (DCValueSize > 0)
+ {
+ if (dcValue < 0)
+ {
+ /* calulate 2 pow */
+ powOfSize = (1 << DCValueSize);
+
+ absDCValue = absDCValue ^ (powOfSize - 1);
+ }
+ armPackBits(ppBitStream, pBitOffset, (OMX_U32)absDCValue, \
+ DCValueSize);
+
+ if (DCValueSize > 8)
+ {
+ armPackBits(ppBitStream, pBitOffset, 1, 1);
+ }
+ }
+ }
+
+ return armVCM4P2_EncodeVLCZigzag_Intra(
+ ppBitStream,
+ pBitOffset,
+ pQDctBlkCoef,
+ predDir,
+ pattern,
+ shortVideoHeader,
+ start);
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_FindMVpred.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_FindMVpred.c
new file mode 100644
index 0000000..a0cff48
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_FindMVpred.c
@@ -0,0 +1,188 @@
+/**
+ *
+ * File Name: omxVCM4P2_FindMVpred.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for predicting MV of MB
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P2_FindMVpred (6.2.3.1.1)
+ *
+ * Description:
+ * Predicts a motion vector for the current block using the procedure
+ * specified in [ISO14496-2], subclause 7.6.5. The resulting predicted MV is
+ * returned in pDstMVPred. If the parameter pDstMVPredME if is not NULL then
+ * the set of three MV candidates used for prediction is also returned,
+ * otherwise pDstMVPredMEis NULL upon return.
+ *
+ * Input Arguments:
+ *
+ * pSrcMVCurMB - pointer to the MV buffer associated with the current Y
+ * macroblock; a value of NULL indicates unavailability.
+ * pSrcCandMV1 - pointer to the MV buffer containing the 4 MVs associated
+ * with the MB located to the left of the current MB; set to NULL
+ * if there is no MB to the left.
+ * pSrcCandMV2 - pointer to the MV buffer containing the 4 MVs associated
+ * with the MB located above the current MB; set to NULL if there
+ * is no MB located above the current MB.
+ * pSrcCandMV3 - pointer to the MV buffer containing the 4 MVs associated
+ * with the MB located to the right and above the current MB; set
+ * to NULL if there is no MB located to the above-right.
+ * iBlk - the index of block in the current macroblock
+ * pDstMVPredME - MV candidate return buffer; if set to NULL then
+ * prediction candidate MVs are not returned and pDstMVPredME will
+ * be NULL upon function return; if pDstMVPredME is non-NULL then it
+ * must point to a buffer containing sufficient space for three
+ * return MVs.
+ *
+ * Output Arguments:
+ *
+ * pDstMVPred - pointer to the predicted motion vector
+ * pDstMVPredME - if non-NULL upon input then pDstMVPredME points upon
+ * return to a buffer containing the three motion vector candidates
+ * used for prediction as specified in [ISO14496-2], subclause
+ * 7.6.5, otherwise if NULL upon input then pDstMVPredME is NULL
+ * upon output.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - the pointer pDstMVPred is NULL
+ * - the parameter iBlk does not fall into the range 0 <= iBlk<=3
+ *
+ */
+
+OMXResult omxVCM4P2_FindMVpred(
+ const OMXVCMotionVector* pSrcMVCurMB,
+ const OMXVCMotionVector* pSrcCandMV1,
+ const OMXVCMotionVector* pSrcCandMV2,
+ const OMXVCMotionVector* pSrcCandMV3,
+ OMXVCMotionVector* pDstMVPred,
+ OMXVCMotionVector* pDstMVPredME,
+ OMX_INT iBlk
+ )
+{
+ OMXVCMotionVector CandMV;
+ const OMXVCMotionVector *pCandMV1;
+ const OMXVCMotionVector *pCandMV2;
+ const OMXVCMotionVector *pCandMV3;
+
+ /* Argument error checks */
+ armRetArgErrIf(iBlk!=0 && pSrcMVCurMB == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDstMVPred == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((iBlk < 0) || (iBlk > 3), OMX_Sts_BadArgErr);
+
+ CandMV.dx = CandMV.dy = 0;
+ /* Based on the position of the block extract the motion vectors and
+ the tranperancy status */
+
+
+ /* Set the default value for these to be used if pSrcCandMV[1|2|3] == NULL */
+ pCandMV1 = pCandMV2 = pCandMV3 = &CandMV;
+
+
+ switch (iBlk)
+ {
+ case 0:
+ {
+ if(pSrcCandMV1 != NULL)
+ {
+ pCandMV1 = &pSrcCandMV1[1];
+ }
+ if(pSrcCandMV2 != NULL)
+ {
+ pCandMV2 = &pSrcCandMV2[2];
+ }
+ if(pSrcCandMV3 != NULL)
+ {
+ pCandMV3 = &pSrcCandMV3[2];
+ }
+ if ((pSrcCandMV1 == NULL) && (pSrcCandMV2 == NULL))
+ {
+ pCandMV1 = pCandMV2 = pCandMV3;
+ }
+ else if((pSrcCandMV1 == NULL) && (pSrcCandMV3 == NULL))
+ {
+ pCandMV1 = pCandMV3 = pCandMV2;
+ }
+ else if((pSrcCandMV2 == NULL) && (pSrcCandMV3 == NULL))
+ {
+ pCandMV2 = pCandMV3 = pCandMV1;
+ }
+ break;
+ }
+ case 1:
+ {
+ pCandMV1 = &pSrcMVCurMB[0];
+ if(pSrcCandMV2 != NULL)
+ {
+ pCandMV2 = &pSrcCandMV2[3];
+ }
+ if(pSrcCandMV3 != NULL)
+ {
+ pCandMV3 = &pSrcCandMV3[2];
+ }
+ if((pSrcCandMV2 == NULL) && (pSrcCandMV3 == NULL))
+ {
+ pCandMV2 = pCandMV3 = pCandMV1;
+ }
+ break;
+ }
+ case 2:
+ {
+ if(pSrcCandMV1 != NULL)
+ {
+ pCandMV1 = &pSrcCandMV1[3];
+ }
+ pCandMV2 = &pSrcMVCurMB[0];
+ pCandMV3 = &pSrcMVCurMB[1];
+ break;
+ }
+ case 3:
+ {
+ pCandMV1 = &pSrcMVCurMB[2];
+ pCandMV2 = &pSrcMVCurMB[0];
+ pCandMV3 = &pSrcMVCurMB[1];
+ break;
+ }
+ }
+
+ /* Find the median of the 3 candidate MV's */
+ pDstMVPred->dx = armMedianOf3 (pCandMV1->dx, pCandMV2->dx, pCandMV3->dx);
+ pDstMVPred->dy = armMedianOf3 (pCandMV1->dy, pCandMV2->dy, pCandMV3->dy);
+
+ if (pDstMVPredME != NULL)
+ {
+ /* Store the candidate MV's into the pDstMVPredME, these can be used
+ in the fast algorithm if implemented */
+ pDstMVPredME[0].dx = pCandMV1->dx;
+ pDstMVPredME[0].dy = pCandMV1->dy;
+ pDstMVPredME[1].dx = pCandMV2->dx;
+ pDstMVPredME[1].dy = pCandMV2->dy;
+ pDstMVPredME[2].dx = pCandMV3->dx;
+ pDstMVPredME[2].dy = pCandMV3->dy;
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+
+/* End of file */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_IDCT8x8blk.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_IDCT8x8blk.c
new file mode 100644
index 0000000..1886d92
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_IDCT8x8blk.c
@@ -0,0 +1,92 @@
+/**
+ *
+ * File Name: omxVCM4P2_IDCT8x8blk.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for 8x8 block IDCT
+ *
+ */
+
+
+#include <math.h>
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVCM4P2_DCT_Table.h"
+
+/**
+ * Function: omxVCM4P2_IDCT8x8blk (6.2.3.2.1)
+ *
+ * Description:
+ * Computes a 2D inverse DCT for a single 8x8 block, as defined in
+ * [ISO14496-2].
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the start of the linearly arranged IDCT input buffer;
+ * must be aligned on a 16-byte boundary. According to
+ * [ISO14496-2], the input coefficient values should lie within the
+ * range [-2048, 2047].
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the start of the linearly arranged IDCT output buffer;
+ * must be aligned on a 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - pSrc or pDst is NULL.
+ * - pSrc or pDst is not 16-byte aligned.
+ *
+ */
+OMXResult omxVCM4P2_IDCT8x8blk (const OMX_S16 *pSrc, OMX_S16 *pDst)
+{
+ OMX_INT x, y, u, v;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pSrc), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pDst), OMX_Sts_BadArgErr);
+
+ for (x = 0; x < 8; x++)
+ {
+ for (y = 0; y < 8; y++)
+ {
+ OMX_F64 sum = 0.0;
+ for (u = 0; u < 8; u++)
+ {
+ for (v = 0; v < 8; v++)
+ {
+ sum += pSrc[(u * 8) + v] *
+ armVCM4P2_preCalcDCTCos[x][u] *
+ armVCM4P2_preCalcDCTCos[y][v];
+ }
+ }
+ pDst[(x * 8) + y] = (OMX_S16) floor(sum + 0.5);
+
+ /* Saturate to [-256, 255] */
+ pDst[(x * 8) + y] = armClip (
+ -256,
+ 255,
+ pDst[(x * 8) + y]);
+ }
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MCReconBlock.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MCReconBlock.c
new file mode 100644
index 0000000..7b3faee
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MCReconBlock.c
@@ -0,0 +1,357 @@
+/**
+ *
+ * File Name: omxVCM4P2_MCReconBlock.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ * Description:
+ * MPEG4 motion compensation prediction for an 8x8 block using
+ * interpolation
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+/**
+ * Function: armVCM4P2_HalfPelVer
+ *
+ * Description:
+ * Performs half pel motion compensation for an 8x8 block using vertical
+ * interpolation described in ISO/IEC 14496-2, subclause 7.6.2.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrc pointer to the block in the reference plane.
+ * [in] srcStep distance between the start of consecutive lines
+ * in the reference plane, in bytes; must be a multiple
+ * of 8.
+ * [in] rndVal rounding control parameter: 0 - disabled; 1 - enabled.
+ * [out] pDst pointer to the linaer 8x8 destination buffer;
+ *
+ */
+static OMXVoid armVCM4P2_HalfPelVer(
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ OMX_U8 *pDst,
+ OMX_INT rndVal)
+{
+ const OMX_U8 *pTempSrc1;
+ const OMX_U8 *pTempSrc2;
+ OMX_INT y, x;
+
+ pTempSrc1 = pSrc;
+ pTempSrc2 = pSrc + srcStep;
+ srcStep -= 8;
+ for (y = 0; y < 8; y++)
+ {
+ for (x = 0; x < 8; x++)
+ {
+ *pDst++ = ((*pTempSrc1++ + *pTempSrc2++) + 1 - rndVal) >> 1;
+ }
+ pTempSrc1 += srcStep;
+ pTempSrc2 += srcStep;
+ }
+}
+
+/**
+ * Function: armVCM4P2_HalfPelHor
+ *
+ * Description:
+ * Performs half pel motion compensation for an 8x8 block using horizontal
+ * interpolation described in ISO/IEC 14496-2, subclause 7.6.2.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrc pointer to the block in the reference plane.
+ * [in] srcStep distance between the start of consecutive lines
+ * in the reference plane, in bytes; must be a multiple
+ * of 8.
+ * [in] rndVal rounding control parameter: 0 - disabled; 1 - enabled.
+ * [out] pDst pointer to the linaer 8x8 destination buffer;
+ *
+ */
+static OMXVoid armVCM4P2_HalfPelHor(
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ OMX_U8 *pDst,
+ OMX_INT rndVal)
+{
+ const OMX_U8 *pTempSrc1;
+ const OMX_U8 *pTempSrc2;
+ OMX_INT y, x;
+
+ pTempSrc1 = pSrc;
+ pTempSrc2 = pTempSrc1 + 1;
+
+ srcStep -= 8;
+ for (y=0; y<8; y++)
+ {
+ for (x=0; x<8; x++)
+ {
+ *pDst++ = ((*pTempSrc1++ + *pTempSrc2++) + 1 - rndVal) >> 1;
+ }
+ pTempSrc1 += srcStep;
+ pTempSrc2 += srcStep;
+ }
+}
+
+
+/**
+ * Function: armVCM4P2_HalfPelVerHor
+ *
+ * Description:
+ * Performs half pel motion compensation for an 8x8 block using both
+ * horizontal and vertical interpolation described in ISO/IEC 14496-2,
+ * subclause 7.6.2.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrc pointer to the block in the reference plane.
+ * [in] srcStep distance between the start of consecutive lines
+ * in the reference plane, in bytes; must be a multiple
+ * of 8.
+ * [in] rndVal rounding control parameter: 0 - disabled; 1 - enabled.
+ * [out] pDst pointer to the linaer 8x8 destination buffer;
+ *
+ */
+static OMXVoid armVCM4P2_HalfPelVerHor(
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ OMX_U8 *pDst,
+ OMX_INT rndVal)
+{
+ const OMX_U8 *pTempSrc1;
+ const OMX_U8 *pTempSrc2;
+ const OMX_U8 *pTempSrc3;
+ const OMX_U8 *pTempSrc4;
+ OMX_INT y, x;
+
+ pTempSrc1 = pSrc;
+ pTempSrc2 = pSrc + srcStep;
+ pTempSrc3 = pSrc + 1;
+ pTempSrc4 = pSrc + srcStep + 1;
+
+ srcStep -= 8;
+ for (y=0; y<8; y++)
+ {
+ for (x=0; x<8; x++)
+ {
+ *pDst++ = ((*pTempSrc1++ + *pTempSrc2++ + *pTempSrc3++ + *pTempSrc4++) +
+ 2 - rndVal) >> 2;
+ }
+ pTempSrc1 += srcStep;
+ pTempSrc2 += srcStep;
+ pTempSrc3 += srcStep;
+ pTempSrc4 += srcStep;
+ }
+}
+
+/**
+ * Function: armVCM4P2_MCReconBlock_NoRes
+ *
+ * Description:
+ * Do motion compensation and copy the result to the current block.
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrc pointer to the block in the reference plane.
+ * [in] srcStep distance between the start of consecutive lines
+ * in the reference plane, in bytes; must be a multiple
+ * of 8.
+ * [in] dstStep distance between the start of consecutive lines in the
+ * destination plane, in bytes; must be a multiple of 8.
+ * [in] predictType bilinear interpolation type, as defined in section 6.2.1.2.
+ * [in] rndVal rounding control parameter: 0 - disabled; 1 - enabled.
+ * [out] pDst pointer to the destination buffer; must be 8-byte aligned.
+ * If prediction residuals are added then output intensities
+ * are clipped to the range [0,255].
+ *
+ */
+static OMXVoid armVCM4P2_MCReconBlock_NoRes(
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ OMX_U8 *pDst,
+ OMX_INT dstStep)
+{
+ OMX_U8 x,y,count,index;
+
+ /* Copying the ref 8x8 blk to the curr blk */
+ for (y = 0, count = 0, index = 0; y < 8; y++,index += (srcStep -8), count += (dstStep - 8))
+ {
+ for (x = 0; x < 8; x++, count++,index++)
+ {
+ pDst[count] = pSrc[index];
+ }
+ }
+}
+
+/**
+ * Function: armVCM4P2_MCReconBlock_Res
+ *
+ * Description:
+ * Reconstructs INTER block by summing the motion compensation results
+ * and the results of the inverse transformation (prediction residuals).
+ * Output intensities are clipped to the range [0,255].
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrc pointer to the block in the reference plane.
+ * [in] pSrcResidue pointer to a buffer containing the 16-bit prediction
+ * residuals. If the pointer is NULL,then no prediction
+ * is done, only motion compensation, i.e., the block is
+ * moved with interpolation.
+ * [in] dstStep distance between the start of consecutive lines in the
+ * destination plane, in bytes; must be a multiple of 8.
+ * [out] pDst pointer to the destination buffer; must be 8-byte aligned.
+ * If prediction residuals are added then output intensities
+ * are clipped to the range [0,255].
+ *
+ */
+static OMXVoid armVCM4P2_MCReconBlock_Res(
+ const OMX_U8 *pSrc,
+ const OMX_S16 *pSrcResidue,
+ OMX_U8 *pDst,
+ OMX_INT dstStep)
+{
+
+ OMX_U8 x,y;
+ OMX_INT temp;
+
+ for(y = 0; y < 8; y++)
+ {
+ for(x = 0; x < 8; x++)
+ {
+ temp = pSrc[x] + pSrcResidue[x];
+ pDst[x] = armClip(0,255,temp);
+ }
+ pDst += dstStep;
+ pSrc += 8;
+ pSrcResidue += 8;
+ }
+}
+
+/**
+ * Function: omxVCM4P2_MCReconBlock (6.2.5.5.1)
+ *
+ * Description:
+ * Performs motion compensation prediction for an 8x8 block using
+ * interpolation described in [ISO14496-2], subclause 7.6.2.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the block in the reference plane.
+ * srcStep - distance between the start of consecutive lines in the
+ * reference plane, in bytes; must be a multiple of 8.
+ * dstStep - distance between the start of consecutive lines in the
+ * destination plane, in bytes; must be a multiple of 8.
+ * pSrcResidue - pointer to a buffer containing the 16-bit prediction
+ * residuals; must be 16-byte aligned. If the pointer is NULL, then
+ * no prediction is done, only motion compensation, i.e., the block
+ * is moved with interpolation.
+ * predictType - bilinear interpolation type, as defined in section
+ * 6.2.1.2.
+ * rndVal - rounding control parameter: 0 - disabled; 1 - enabled.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the destination buffer; must be 8-byte aligned. If
+ * prediction residuals are added then output intensities are
+ * clipped to the range [0,255].
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; returned under any of the following
+ * conditions:
+ * - pDst is not 8-byte aligned.
+ * - pSrcResidue is not 16-byte aligned.
+ * - one or more of the following pointers is NULL: pSrc or pDst.
+ * - either srcStep or dstStep is not a multiple of 8.
+ * - invalid type specified for the parameter predictType.
+ * - the parameter rndVal is not equal either to 0 or 1.
+ *
+ */
+OMXResult omxVCM4P2_MCReconBlock(
+ const OMX_U8 *pSrc,
+ OMX_INT srcStep,
+ const OMX_S16 *pSrcResidue,
+ OMX_U8 *pDst,
+ OMX_INT dstStep,
+ OMX_INT predictType,
+ OMX_INT rndVal)
+{
+ /* Definitions and Initializations*/
+ OMX_U8 pTempDst[64];
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs8ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pSrcResidue), OMX_Sts_BadArgErr);
+ armRetArgErrIf(((dstStep % 8) || (srcStep % 8)), OMX_Sts_BadArgErr);
+ armRetArgErrIf(((predictType != OMX_VC_INTEGER_PIXEL) &&
+ (predictType != OMX_VC_HALF_PIXEL_X) &&
+ (predictType != OMX_VC_HALF_PIXEL_Y) &&
+ (predictType != OMX_VC_HALF_PIXEL_XY)
+ ),OMX_Sts_BadArgErr);
+ armRetArgErrIf(((rndVal != 0) && (rndVal != 1)),OMX_Sts_BadArgErr);
+
+ switch(predictType)
+ {
+ case OMX_VC_INTEGER_PIXEL:
+ armVCM4P2_MCReconBlock_NoRes(pSrc,
+ srcStep,
+ &(pTempDst[0]),
+ 8);
+ break;
+ case OMX_VC_HALF_PIXEL_X:
+ armVCM4P2_HalfPelHor(pSrc,
+ srcStep,
+ &(pTempDst[0]),
+ rndVal);
+ break;
+ case OMX_VC_HALF_PIXEL_Y:
+ armVCM4P2_HalfPelVer(pSrc,
+ srcStep,
+ &(pTempDst[0]),
+ rndVal);
+ break;
+ case OMX_VC_HALF_PIXEL_XY:
+ armVCM4P2_HalfPelVerHor(pSrc,
+ srcStep,
+ &(pTempDst[0]),
+ rndVal);
+ break;
+ }
+
+ if(pSrcResidue == NULL)
+ {
+ armVCM4P2_MCReconBlock_NoRes(&(pTempDst[0]),
+ 8,
+ pDst,
+ dstStep);
+ }
+ else
+ {
+ armVCM4P2_MCReconBlock_Res(&(pTempDst[0]),
+ pSrcResidue,
+ pDst,
+ dstStep);
+ }
+
+ return OMX_Sts_NoErr;
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEGetBufSize.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEGetBufSize.c
new file mode 100644
index 0000000..a8e51da
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEGetBufSize.c
@@ -0,0 +1,70 @@
+/**
+ *
+ * File Name: omxVCM4P2_MEGetBufSize.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Initialization modules for the vendor specific Motion Estimation structure.
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P2_MEGetBufSize (6.2.4.1.1)
+ *
+ * Description:
+ * Computes the size, in bytes, of the vendor-specific specification
+ * structure for the following motion estimation functions:
+ * BlockMatch_Integer_8x8, BlockMatch_Integer_16x16, and MotionEstimationMB.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P2MEMode
+ * pMEParams - motion estimation parameters
+ *
+ * Output Arguments:
+ *
+ * pSize - pointer to the number of bytes required for the specification
+ * structure
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - one or more of the following is true:
+ * - an invalid value was specified for the parameter MEmode
+ * - a negative or zero value was specified for the
+ * parameter pMEParams->searchRange
+ *
+ */
+
+OMXResult omxVCM4P2_MEGetBufSize(
+ OMXVCM4P2MEMode MEMode,
+ const OMXVCM4P2MEParams *pMEParams,
+ OMX_U32 *pSize
+ )
+{
+ armRetArgErrIf(!pMEParams, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!pSize, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pMEParams->searchRange <= 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf((MEMode != OMX_VC_M4P10_FAST_SEARCH) &&
+ (MEMode != OMX_VC_M4P10_FULL_SEARCH), OMX_Sts_BadArgErr);
+
+ *pSize = (OMX_INT) sizeof(ARMVCM4P2_MESpec);
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEInit.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEInit.c
new file mode 100644
index 0000000..419e71a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MEInit.c
@@ -0,0 +1,84 @@
+/**
+ *
+ * File Name: omxVCM4P2_MEInit.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Initialization modules for the vendor specific Motion Estimation structure.
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P2_MEInit (6.2.4.1.2)
+ *
+ * Description:
+ * Initializes the vendor-specific specification structure required for the
+ * following motion estimation functions: BlockMatch_Integer_8x8,
+ * BlockMatch_Integer_16x16, and MotionEstimationMB. Memory for the
+ * specification structure *pMESpec must be allocated prior to calling the
+ * function, and should be aligned on a 4-byte boundary. Following
+ * initialization by this function, the vendor-specific structure *pMESpec
+ * should contain an implementation-specific representation of all motion
+ * estimation parameters received via the structure pMEParams, for example
+ * rndVal, searchRange, etc. The number of bytes required for the
+ * specification structure can be determined using the function
+ * omxVCM4P2_MEGetBufSize.
+ *
+ * Input Arguments:
+ *
+ * MEmode - motion estimation mode; available modes are defined by the
+ * enumerated type OMXVCM4P2MEMode
+ * pMEParams - motion estimation parameters
+ * pMESpec - pointer to the uninitialized ME specification structure
+ *
+ * Output Arguments:
+ *
+ * pMESpec - pointer to the initialized ME specification structure
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - one or more of the following is true:
+ * - an invalid value was specified for the parameter MEmode
+ * - a negative or zero value was specified for the
+ * parameter pMEParams->searchRange
+ *
+ */
+
+OMXResult omxVCM4P2_MEInit(
+ OMXVCM4P2MEMode MEMode,
+ const OMXVCM4P2MEParams *pMEParams,
+ void *pMESpec
+ )
+{
+ ARMVCM4P2_MESpec *armMESpec = (ARMVCM4P2_MESpec *) pMESpec;
+
+ armRetArgErrIf(!pMEParams, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!pMESpec, OMX_Sts_BadArgErr);
+ armRetArgErrIf((MEMode != OMX_VC_M4P2_FAST_SEARCH) &&
+ (MEMode != OMX_VC_M4P2_FULL_SEARCH), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pMEParams->searchRange <= 0, OMX_Sts_BadArgErr);
+
+ armMESpec->MEParams.searchEnable8x8 = pMEParams->searchEnable8x8;
+ armMESpec->MEParams.halfPelSearchEnable = pMEParams->halfPelSearchEnable;
+ armMESpec->MEParams.searchRange = pMEParams->searchRange;
+ armMESpec->MEParams.rndVal = pMEParams->rndVal;
+ armMESpec->MEMode = MEMode;
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MotionEstimationMB.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MotionEstimationMB.c
new file mode 100644
index 0000000..9549050
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_MotionEstimationMB.c
@@ -0,0 +1,630 @@
+/**
+ *
+ * File Name: omxVCM4P2_MotionEstimationMB.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains module for motion search 16x16 macroblock
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armVC.h"
+#include "armCOMM.h"
+
+/**
+ * Function: armVCM4P2_BlockMatch_16x16
+ *
+ * Description:
+ * 16x16 block match wrapper function, calls omxVCM4P2_BlockMatch_Integer_16x16.
+ * If half pel search is enabled it also calls omxVCM4P2_BlockMatch_Half_16x16
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcRefBuf pointer to the reference Y plane; points to the reference MB that
+ * corresponds to the location of the current macroblock in the current
+ * plane.
+ * [in] srcRefStep width of the reference plane
+ * [in] pRefRect pointer to the valid rectangular in reference plane. Relative to image origin.
+ * It's not limited to the image boundary, but depended on the padding. For example,
+ * if you pad 4 pixels outside the image border, then the value for left border
+ * can be -4
+ * [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane (linear array,
+ * 256 entries); must be aligned on an 16-byte boundary.
+ * [in] pCurrPointPos position of the current macroblock in the current plane
+ * [in] pSrcPreMV pointer to predicted motion vector; NULL indicates no predicted MV
+ * [in] pSrcPreSAD pointer to SAD associated with the predicted MV (referenced by pSrcPreMV); may be set to NULL if unavailable.
+ * [in] pMESpec vendor-specific motion estimation specification structure; must have been allocated
+ * and then initialized using omxVCM4P2_MEInit prior to calling the block matching
+ * function.
+ * [out] pDstMV pointer to estimated MV
+ * [out] pDstSAD pointer to minimum SAD
+ * *
+ * Return Value:
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ *
+ */
+static OMXResult armVCM4P2_BlockMatch_16x16(
+ const OMX_U8 *pSrcRefBuf,
+ const OMX_INT srcRefStep,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ OMXVCMotionVector *pSrcPreMV,
+ OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector *pDstMV,
+ OMX_INT *pDstSAD
+)
+{
+ OMXVCM4P2MEParams *pMEParams = (OMXVCM4P2MEParams *)pMESpec;
+ OMX_INT rndVal;
+
+ rndVal = pMEParams->rndVal;
+
+ omxVCM4P2_BlockMatch_Integer_16x16(
+ pSrcRefBuf,
+ srcRefStep,
+ pRefRect,
+ pSrcCurrBuf,
+ pCurrPointPos,
+ pSrcPreMV,
+ pSrcPreSAD,
+ pMEParams,
+ pDstMV,
+ pDstSAD);
+
+ if (pMEParams->halfPelSearchEnable)
+ {
+ omxVCM4P2_BlockMatch_Half_16x16(
+ pSrcRefBuf,
+ srcRefStep,
+ pRefRect,
+ pSrcCurrBuf,
+ pCurrPointPos,
+ rndVal,
+ pDstMV,
+ pDstSAD);
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/**
+ * Function: armVCM4P2_BlockMatch_8x8
+ *
+ * Description:
+ * 8x8 block match wrapper function, calls omxVCM4P2_BlockMatch_Integer_8x8.
+ * If half pel search is enabled it also calls omxVCM4P2_BlockMatch_Half_8x8
+ *
+ * Remarks:
+ *
+ * Parameters:
+ * [in] pSrcRefBuf pointer to the reference Y plane; points to the reference MB that
+ * corresponds to the location of the current macroblock in the current
+ * plane.
+ * [in] srcRefStep width of the reference plane
+ * [in] pRefRect pointer to the valid rectangular in reference plane. Relative to image origin.
+ * It's not limited to the image boundary, but depended on the padding. For example,
+ * if you pad 4 pixels outside the image border, then the value for left border
+ * can be -4
+ * [in] pSrcCurrBuf pointer to the current macroblock extracted from original plane (linear array,
+ * 256 entries); must be aligned on an 16-byte boundary.
+ * [in] pCurrPointPos position of the current macroblock in the current plane
+ * [in] pSrcPreMV pointer to predicted motion vector; NULL indicates no predicted MV
+ * [in] pSrcPreSAD pointer to SAD associated with the predicted MV (referenced by pSrcPreMV); may be set to NULL if unavailable.
+ * [in] pMESpec vendor-specific motion estimation specification structure; must have been allocated
+ * and then initialized using omxVCM4P2_MEInit prior to calling the block matching
+ * function.
+ * [out] pDstMV pointer to estimated MV
+ * [out] pDstSAD pointer to minimum SAD
+ * *
+ * Return Value:
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments
+ *
+ */
+static OMXResult armVCM4P2_BlockMatch_8x8(
+ const OMX_U8 *pSrcRefBuf,
+ OMX_INT srcRefStep,
+ const OMXRect *pRefRect,
+ const OMX_U8 *pSrcCurrBuf,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ OMXVCMotionVector *pSrcPreMV,
+ OMX_INT *pSrcPreSAD,
+ void *pMESpec,
+ OMXVCMotionVector *pSrcDstMV,
+ OMX_INT *pDstSAD
+)
+{
+ OMXVCM4P2MEParams *pMEParams = (OMXVCM4P2MEParams *)pMESpec;
+ OMX_INT rndVal;
+
+ rndVal = pMEParams->rndVal;
+
+ omxVCM4P2_BlockMatch_Integer_8x8(
+ pSrcRefBuf,
+ srcRefStep,
+ pRefRect,
+ pSrcCurrBuf,
+ pCurrPointPos,
+ pSrcPreMV,
+ pSrcPreSAD,
+ pMEParams,
+ pSrcDstMV,
+ pDstSAD);
+
+ if (pMEParams->halfPelSearchEnable)
+ {
+ omxVCM4P2_BlockMatch_Half_8x8(
+ pSrcRefBuf,
+ srcRefStep,
+ pRefRect,
+ pSrcCurrBuf,
+ pCurrPointPos,
+ rndVal,
+ pSrcDstMV,
+ pDstSAD);
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+
+/**
+ * Function: omxVCM4P2_MotionEstimationMB (6.2.4.3.1)
+ *
+ * Description:
+ * Performs motion search for a 16x16 macroblock. Selects best motion search
+ * strategy from among inter-1MV, inter-4MV, and intra modes. Supports
+ * integer and half pixel resolution.
+ *
+ * Input Arguments:
+ *
+ * pSrcCurrBuf - pointer to the top-left corner of the current MB in the
+ * original picture plane; must be aligned on a 16-byte boundary.
+ * The function does not expect source data outside the region
+ * bounded by the MB to be available; for example it is not
+ * necessary for the caller to guarantee the availability of
+ * pSrcCurrBuf[-SrcCurrStep], i.e., the row of pixels above the MB
+ * to be processed.
+ * srcCurrStep - width of the original picture plane, in terms of full
+ * pixels; must be a multiple of 16.
+ * pSrcRefBuf - pointer to the reference Y plane; points to the reference
+ * plane location corresponding to the location of the current
+ * macroblock in the current plane; must be aligned on a 16-byte
+ * boundary.
+ * srcRefStep - width of the reference picture plane, in terms of full
+ * pixels; must be a multiple of 16.
+ * pRefRect - reference plane valid region rectangle, specified relative to
+ * the image origin
+ * pCurrPointPos - position of the current macroblock in the current plane
+ * pMESpec - pointer to the vendor-specific motion estimation specification
+ * structure; must be allocated and then initialized using
+ * omxVCM4P2_MEInit prior to calling this function.
+ * pMBInfo - array, of dimension four, containing pointers to information
+ * associated with four nearby MBs:
+ * - pMBInfo[0] - pointer to left MB information
+ * - pMBInfo[1] - pointer to top MB information
+ * - pMBInfo[2] - pointer to top-left MB information
+ * - pMBInfo[3] - pointer to top-right MB information
+ * Any pointer in the array may be set equal to NULL if the
+ * corresponding MB doesn't exist. For each MB, the following structure
+ * members are used:
+ * - mbType - macroblock type, either OMX_VC_INTRA, OMX_VC_INTER, or
+ * OMX_VC_INTER4V
+ * - pMV0[2][2] - estimated motion vectors; represented
+ * in 1/2 pixel units
+ * - sliceID - number of the slice to which the MB belongs
+ * pSrcDstMBCurr - pointer to information structure for the current MB.
+ * The following entries should be set prior to calling the
+ * function: sliceID - the number of the slice the to which the
+ * current MB belongs. The structure elements cbpy and cbpc are
+ * ignored.
+ *
+ * Output Arguments:
+ *
+ * pSrcDstMBCurr - pointer to updated information structure for the current
+ * MB after MB-level motion estimation has been completed. The
+ * following structure members are updated by the ME function:
+ * - mbType - macroblock type: OMX_VC_INTRA, OMX_VC_INTER, or
+ * OMX_VC_INTER4V.
+ * - pMV0[2][2] - estimated motion vectors; represented in
+ * terms of 1/2 pel units.
+ * - pMVPred[2][2] - predicted motion vectors; represented
+ * in terms of 1/2 pel units.
+ * The structure members cbpy and cbpc are not updated by the function.
+ * pDstSAD - pointer to the minimum SAD for INTER1V, or sum of minimum SADs
+ * for INTER4V
+ * pDstBlockSAD - pointer to an array of SAD values for each of the four
+ * 8x8 luma blocks in the MB. The block SADs are in scan order for
+ * each MB.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments. Returned if one or more of the
+ * following conditions is true:
+ * - at least one of the following pointers is NULL: pSrcCurrBuf,
+ * pSrcRefBuf, pRefRect, pCurrPointPos, pMBInter, pMBIntra,
+ * pSrcDstMBCurr, or pDstSAD.
+ *
+ */
+
+OMXResult omxVCM4P2_MotionEstimationMB (
+ const OMX_U8 *pSrcCurrBuf,
+ OMX_S32 srcCurrStep,
+ const OMX_U8 *pSrcRefBuf,
+ OMX_S32 srcRefStep,
+ const OMXRect*pRefRect,
+ const OMXVCM4P2Coordinate *pCurrPointPos,
+ void *pMESpec,
+ const OMXVCM4P2MBInfoPtr *pMBInfo,
+ OMXVCM4P2MBInfo *pSrcDstMBCurr,
+ OMX_U16 *pDstSAD,
+ OMX_U16 *pDstBlockSAD
+)
+{
+
+ OMX_INT intraSAD, average, count, index, x, y;
+ OMXVCMotionVector dstMV16x16;
+ OMX_INT dstSAD16x16;
+ OMX_INT dstSAD8x8;
+ OMXVCM4P2MEParams *pMEParams;
+ OMXVCM4P2Coordinate TempCurrPointPos;
+ OMXVCM4P2Coordinate *pTempCurrPointPos;
+ OMX_U8 aTempSrcCurrBuf[271];
+ OMX_U8 *pTempSrcCurrBuf;
+ OMX_U8 *pDst;
+ OMX_U8 aDst[71];
+ OMX_S32 dstStep = 8;
+ OMX_INT predictType;
+ OMX_S32 Sad;
+ const OMX_U8 *pTempSrcRefBuf;
+ OMXVCMotionVector* pSrcCandMV1[4];
+ OMXVCMotionVector* pSrcCandMV2[4];
+ OMXVCMotionVector* pSrcCandMV3[4];
+
+ /* Argument error checks */
+ armRetArgErrIf(!armIs16ByteAligned(pSrcCurrBuf), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pSrcRefBuf), OMX_Sts_BadArgErr);
+ armRetArgErrIf(((srcCurrStep % 16) || (srcRefStep % 16)), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcCurrBuf == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcRefBuf == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pRefRect == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pCurrPointPos == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSrcDstMBCurr == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDstSAD == NULL, OMX_Sts_BadArgErr);
+
+
+ pTempCurrPointPos = &(TempCurrPointPos);
+ pTempSrcCurrBuf = armAlignTo16Bytes(aTempSrcCurrBuf);
+ pMEParams = (OMXVCM4P2MEParams *)pMESpec;
+ pTempCurrPointPos->x = pCurrPointPos->x;
+ pTempCurrPointPos->y = pCurrPointPos->y;
+ pSrcDstMBCurr->mbType = OMX_VC_INTER;
+
+ /* Preparing a linear buffer for block match */
+ for (y = 0, index = count = 0; y < 16; y++, index += srcCurrStep - 16)
+ {
+ for(x = 0; x < 16; x++, count++, index++)
+ {
+ pTempSrcCurrBuf[count] = pSrcCurrBuf[index];
+ }
+ }
+ for(y = 0, index = 0; y < 2; y++)
+ {
+ for(x = 0; x < 2; x++,index++)
+ {
+ if((pMBInfo[0] != NULL) && (pMBInfo[0]->mbType != OMX_VC_INTRA))
+ {
+ pSrcCandMV1[index] = &(pMBInfo[0]->pMV0[y][x]);
+ }
+ else
+ {
+ pSrcCandMV1[index] = NULL;
+ }
+ if((pMBInfo[1] != NULL) && (pMBInfo[1]->mbType != OMX_VC_INTRA))
+ {
+ pSrcCandMV2[index] = &(pMBInfo[1]->pMV0[y][x]);
+ }
+ else
+ {
+ pSrcCandMV2[index] = NULL;
+ }
+ if((pMBInfo[3] != NULL) && (pMBInfo[3]->mbType != OMX_VC_INTRA))
+ {
+ pSrcCandMV3[index] = &(pMBInfo[3]->pMV0[y][x]);
+ }
+ else
+ {
+ pSrcCandMV3[index] = NULL;
+ }
+ }
+ }
+ /* Calculating SAD at MV(0,0) */
+ armVCCOMM_SAD(pTempSrcCurrBuf,
+ 16,
+ pSrcRefBuf,
+ srcRefStep,
+ &Sad,
+ 16,
+ 16);
+ *pDstSAD = Sad;
+
+ /* Mode decision for NOT_CODED MB */
+ if(*pDstSAD == 0)
+ {
+ pSrcDstMBCurr->pMV0[0][0].dx = 0;
+ pSrcDstMBCurr->pMV0[0][0].dy = 0;
+ *pDstSAD = 0;
+ return OMX_Sts_NoErr;
+ }
+
+ omxVCM4P2_FindMVpred(
+ &(pSrcDstMBCurr->pMV0[0][0]),
+ pSrcCandMV1[0],
+ pSrcCandMV2[0],
+ pSrcCandMV3[0],
+ &(pSrcDstMBCurr->pMVPred[0][0]),
+ NULL,
+ 0);
+
+ /* Inter 1 MV */
+ armVCM4P2_BlockMatch_16x16(
+ pSrcRefBuf,
+ srcRefStep,
+ pRefRect,
+ pTempSrcCurrBuf,
+ pCurrPointPos,
+ &(pSrcDstMBCurr->pMVPred[0][0]),
+ NULL,
+ pMEParams,
+ &dstMV16x16,
+ &dstSAD16x16);
+
+ /* Initialize all with 1 MV values */
+ pSrcDstMBCurr->pMV0[0][0].dx = dstMV16x16.dx;
+ pSrcDstMBCurr->pMV0[0][0].dy = dstMV16x16.dy;
+ pSrcDstMBCurr->pMV0[0][1].dx = dstMV16x16.dx;
+ pSrcDstMBCurr->pMV0[0][1].dy = dstMV16x16.dy;
+ pSrcDstMBCurr->pMV0[1][0].dx = dstMV16x16.dx;
+ pSrcDstMBCurr->pMV0[1][0].dy = dstMV16x16.dy;
+ pSrcDstMBCurr->pMV0[1][1].dx = dstMV16x16.dx;
+ pSrcDstMBCurr->pMV0[1][1].dy = dstMV16x16.dy;
+
+ *pDstSAD = dstSAD16x16;
+
+ if (pMEParams->searchEnable8x8)
+ {
+ /* Inter 4MV */
+ armVCM4P2_BlockMatch_8x8 (pSrcRefBuf,
+ srcRefStep, pRefRect,
+ pTempSrcCurrBuf, pTempCurrPointPos,
+ &(pSrcDstMBCurr->pMVPred[0][0]), NULL,
+ pMEParams, &(pSrcDstMBCurr->pMV0[0][0]),
+ &dstSAD8x8
+ );
+ pDstBlockSAD[0] = dstSAD8x8;
+ *pDstSAD = dstSAD8x8;
+ pTempCurrPointPos->x += 8;
+ pSrcRefBuf += 8;
+ omxVCM4P2_FindMVpred(
+ &(pSrcDstMBCurr->pMV0[0][1]),
+ pSrcCandMV1[1],
+ pSrcCandMV2[1],
+ pSrcCandMV3[1],
+ &(pSrcDstMBCurr->pMVPred[0][1]),
+ NULL,
+ 1);
+
+ armVCM4P2_BlockMatch_8x8 (pSrcRefBuf,
+ srcRefStep, pRefRect,
+ pTempSrcCurrBuf, pTempCurrPointPos,
+ &(pSrcDstMBCurr->pMVPred[0][1]), NULL,
+ pMEParams, &(pSrcDstMBCurr->pMV0[0][1]),
+ &dstSAD8x8
+ );
+ pDstBlockSAD[1] = dstSAD8x8;
+ *pDstSAD += dstSAD8x8;
+ pTempCurrPointPos->x -= 8;
+ pTempCurrPointPos->y += 8;
+ pSrcRefBuf += (srcRefStep * 8) - 8;
+
+ omxVCM4P2_FindMVpred(
+ &(pSrcDstMBCurr->pMV0[1][0]),
+ pSrcCandMV1[2],
+ pSrcCandMV2[2],
+ pSrcCandMV3[2],
+ &(pSrcDstMBCurr->pMVPred[1][0]),
+ NULL,
+ 2);
+ armVCM4P2_BlockMatch_8x8 (pSrcRefBuf,
+ srcRefStep, pRefRect,
+ pTempSrcCurrBuf, pTempCurrPointPos,
+ &(pSrcDstMBCurr->pMVPred[1][0]), NULL,
+ pMEParams, &(pSrcDstMBCurr->pMV0[1][0]),
+ &dstSAD8x8
+ );
+ pDstBlockSAD[2] = dstSAD8x8;
+ *pDstSAD += dstSAD8x8;
+ pTempCurrPointPos->x += 8;
+ pSrcRefBuf += 8;
+ omxVCM4P2_FindMVpred(
+ &(pSrcDstMBCurr->pMV0[1][1]),
+ pSrcCandMV1[3],
+ pSrcCandMV2[3],
+ pSrcCandMV3[3],
+ &(pSrcDstMBCurr->pMVPred[1][1]),
+ NULL,
+ 3);
+ armVCM4P2_BlockMatch_8x8 (pSrcRefBuf,
+ srcRefStep, pRefRect,
+ pTempSrcCurrBuf, pTempCurrPointPos,
+ &(pSrcDstMBCurr->pMVPred[1][1]), NULL,
+ pMEParams, &(pSrcDstMBCurr->pMV0[1][1]),
+ &dstSAD8x8
+ );
+ pDstBlockSAD[3] = dstSAD8x8;
+ *pDstSAD += dstSAD8x8;
+
+
+ /* Checking if 4MV is equal to 1MV */
+ if (
+ (pSrcDstMBCurr->pMV0[0][0].dx != dstMV16x16.dx) ||
+ (pSrcDstMBCurr->pMV0[0][0].dy != dstMV16x16.dy) ||
+ (pSrcDstMBCurr->pMV0[0][1].dx != dstMV16x16.dx) ||
+ (pSrcDstMBCurr->pMV0[0][1].dy != dstMV16x16.dy) ||
+ (pSrcDstMBCurr->pMV0[1][0].dx != dstMV16x16.dx) ||
+ (pSrcDstMBCurr->pMV0[1][0].dy != dstMV16x16.dy) ||
+ (pSrcDstMBCurr->pMV0[1][1].dx != dstMV16x16.dx) ||
+ (pSrcDstMBCurr->pMV0[1][1].dy != dstMV16x16.dy)
+ )
+ {
+ /* select the 4 MV */
+ pSrcDstMBCurr->mbType = OMX_VC_INTER4V;
+ }
+ }
+
+ /* finding the error in intra mode */
+ for (count = 0, average = 0; count < 256 ; count++)
+ {
+ average = average + pTempSrcCurrBuf[count];
+ }
+ average = average/256;
+
+ intraSAD = 0;
+
+ /* Intra SAD calculation */
+ for (count = 0; count < 256 ; count++)
+ {
+ intraSAD += armAbs ((pTempSrcCurrBuf[count]) - (average));
+ }
+
+ /* Using the MPEG4 VM formula for intra/inter mode decision
+ Var < (SAD - 2*NB) where NB = N^2 is the number of pixels
+ of the macroblock.*/
+
+ if (intraSAD <= (*pDstSAD - 512))
+ {
+ pSrcDstMBCurr->mbType = OMX_VC_INTRA;
+ pSrcDstMBCurr->pMV0[0][0].dx = 0;
+ pSrcDstMBCurr->pMV0[0][0].dy = 0;
+ *pDstSAD = intraSAD;
+ pDstBlockSAD[0] = 0xFFFF;
+ pDstBlockSAD[1] = 0xFFFF;
+ pDstBlockSAD[2] = 0xFFFF;
+ pDstBlockSAD[3] = 0xFFFF;
+ }
+
+ if(pSrcDstMBCurr->mbType == OMX_VC_INTER)
+ {
+ pTempSrcRefBuf = pSrcRefBuf + (srcRefStep * dstMV16x16.dy) + dstMV16x16.dx;
+
+ if((dstMV16x16.dx & 0x1) && (dstMV16x16.dy & 0x1))
+ {
+ predictType = OMX_VC_HALF_PIXEL_XY;
+ }
+ else if(dstMV16x16.dx & 0x1)
+ {
+ predictType = OMX_VC_HALF_PIXEL_X;
+ }
+ else if(dstMV16x16.dy & 0x1)
+ {
+ predictType = OMX_VC_HALF_PIXEL_Y;
+ }
+ else
+ {
+ predictType = OMX_VC_INTEGER_PIXEL;
+ }
+
+ pDst = armAlignTo8Bytes(&(aDst[0]));
+ /* Calculating Block SAD at MV(dstMV16x16.dx,dstMV16x16.dy) */
+ /* Block 0 */
+ omxVCM4P2_MCReconBlock(pTempSrcRefBuf,
+ srcRefStep,
+ NULL,
+ pDst,
+ dstStep,
+ predictType,
+ pMEParams->rndVal);
+
+ armVCCOMM_SAD(pTempSrcCurrBuf,
+ 16,
+ pDst,
+ dstStep,
+ &Sad,
+ 8,
+ 8);
+ pDstBlockSAD[0] = Sad;
+
+ /* Block 1 */
+ omxVCM4P2_MCReconBlock(pTempSrcRefBuf + 8,
+ srcRefStep,
+ NULL,
+ pDst,
+ dstStep,
+ predictType,
+ pMEParams->rndVal);
+
+ armVCCOMM_SAD(pTempSrcCurrBuf + 8,
+ 16,
+ pDst,
+ dstStep,
+ &Sad,
+ 8,
+ 8);
+ pDstBlockSAD[1] = Sad;
+
+ /* Block 2 */
+ omxVCM4P2_MCReconBlock(pTempSrcRefBuf + (srcRefStep*8),
+ srcRefStep,
+ NULL,
+ pDst,
+ dstStep,
+ predictType,
+ pMEParams->rndVal);
+
+ armVCCOMM_SAD(pTempSrcCurrBuf + (16*8),
+ 16,
+ pDst,
+ dstStep,
+ &Sad,
+ 8,
+ 8);
+ pDstBlockSAD[2] = Sad;
+
+ /* Block 3 */
+ omxVCM4P2_MCReconBlock(pTempSrcRefBuf + (srcRefStep*8) + 8,
+ srcRefStep,
+ NULL,
+ pDst,
+ dstStep,
+ predictType,
+ pMEParams->rndVal);
+
+ armVCCOMM_SAD(pTempSrcCurrBuf + (16*8) + 8,
+ 16,
+ pDst,
+ dstStep,
+ &Sad,
+ 8,
+ 8);
+ pDstBlockSAD[3] = Sad;
+ }
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra.c
new file mode 100644
index 0000000..1613f47
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_PredictReconCoefIntra.c
@@ -0,0 +1,121 @@
+ /**
+ *
+ * File Name: omxVCM4P2_PredictReconCoefIntra.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * File: omxVCM4P2_PredictReconCoefIntra_S16.c
+ * Description: Contains modules for AC DC prediction
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+/**
+ * Function: omxVCM4P2_PredictReconCoefIntra (6.2.5.4.3)
+ *
+ * Description:
+ * Performs adaptive DC/AC coefficient prediction for an intra block. Prior
+ * to the function call, prediction direction (predDir) should be selected as
+ * specified in [ISO14496-2], subclause 7.4.3.1.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the coefficient buffer which contains the quantized
+ * coefficient residuals (PQF) of the current block; must be
+ * aligned on a 4-byte boundary. The output coefficients are
+ * saturated to the range [-2048, 2047].
+ * pPredBufRow - pointer to the coefficient row buffer; must be aligned on
+ * a 4-byte boundary.
+ * pPredBufCol - pointer to the coefficient column buffer; must be aligned
+ * on a 4-byte boundary.
+ * curQP - quantization parameter of the current block. curQP may equal to
+ * predQP especially when the current block and the predictor block
+ * are in the same macroblock.
+ * predQP - quantization parameter of the predictor block
+ * predDir - indicates the prediction direction which takes one of the
+ * following values: OMX_VC_HORIZONTAL - predict horizontally
+ * OMX_VC_VERTICAL - predict vertically
+ * ACPredFlag - a flag indicating if AC prediction should be performed. It
+ * is equal to ac_pred_flag in the bit stream syntax of MPEG-4
+ * videoComp - video component type (luminance or chrominance) of the
+ * current block
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the coefficient buffer which contains the quantized
+ * coefficients (QF) of the current block
+ * pPredBufRow - pointer to the updated coefficient row buffer
+ * pPredBufCol - pointer to the updated coefficient column buffer Note:
+ * Buffer update: Update the AC prediction buffer (both row and
+ * column buffer).
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments, if:
+ * - At least one of the pointers is NULL:
+ * pSrcDst, pPredBufRow, or pPredBufCol.
+ * - curQP <= 0,
+ * - predQP <= 0,
+ * - curQP >31,
+ * - predQP > 31,
+ * - preDir exceeds [1,2]
+ * - pSrcDst, pPredBufRow, or pPredBufCol is not 4-byte aligned.
+ *
+ */
+
+OMXResult omxVCM4P2_PredictReconCoefIntra(
+ OMX_S16 * pSrcDst,
+ OMX_S16 * pPredBufRow,
+ OMX_S16 * pPredBufCol,
+ OMX_INT curQP,
+ OMX_INT predQP,
+ OMX_INT predDir,
+ OMX_INT ACPredFlag,
+ OMXVCM4P2VideoComponent videoComp
+ )
+{
+ OMX_U8 flag;
+ /* Argument error checks */
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pPredBufRow == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pPredBufCol == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(curQP <= 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf(predQP <= 0, OMX_Sts_BadArgErr);
+ armRetArgErrIf(curQP > 31, OMX_Sts_BadArgErr);
+ armRetArgErrIf(predQP > 31, OMX_Sts_BadArgErr);
+ armRetArgErrIf((predDir != 1) && (predDir != 2), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs4ByteAligned(pSrcDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs4ByteAligned(pPredBufRow), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs4ByteAligned(pPredBufCol), OMX_Sts_BadArgErr);
+
+ flag = 0;
+ return armVCM4P2_ACDCPredict(
+ pSrcDst,
+ NULL,
+ pPredBufRow,
+ pPredBufCol,
+ curQP,
+ predQP,
+ predDir,
+ ACPredFlag,
+ videoComp,
+ flag,
+ NULL);
+
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInter_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInter_I.c
new file mode 100644
index 0000000..5964f73
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInter_I.c
@@ -0,0 +1,117 @@
+/**
+ *
+ * File Name: omxVCM4P2_QuantInter_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for inter Quantization
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P2_QuantInter_I (6.2.4.4.3)
+ *
+ * Description:
+ * Performs quantization on an inter coefficient block; supports
+ * bits_per_pixel == 8.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input inter block coefficients; must be aligned
+ * on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale)
+ * shortVideoHeader - binary flag indicating presence of short_video_header;
+ * shortVideoHeader==1 selects linear intra DC mode, and
+ * shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (quantized) interblock coefficients.
+ * When shortVideoHeader==1, AC coefficients are saturated on the
+ * interval [-127, 127], and DC coefficients are saturated on the
+ * interval [1, 254]. When shortVideoHeader==0, AC coefficients
+ * are saturated on the interval [-2047, 2047].
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - pSrcDst is NULL.
+ * - QP <= 0 or QP >= 32.
+ *
+ */
+
+OMXResult omxVCM4P2_QuantInter_I(
+ OMX_S16 * pSrcDst,
+ OMX_U8 QP,
+ OMX_INT shortVideoHeader
+)
+{
+
+ /* Definitions and Initializations*/
+ OMX_INT coeffCount;
+ OMX_INT fSign;
+ OMX_INT maxClpAC = 0, minClpAC = 0;
+ OMX_INT maxClpDC = 0, minClpDC = 0;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(((QP <= 0) || (QP >= 32)), OMX_Sts_BadArgErr);
+ /* One argument check is delayed until we have ascertained that */
+ /* pQMatrix is not NULL. */
+
+ /* Set the Clip Range based on SVH on/off */
+ if(shortVideoHeader == 1)
+ {
+ maxClpDC = 254;
+ minClpDC = 1;
+ maxClpAC = 127;
+ minClpAC = -127;
+ }
+ else
+ {
+ maxClpDC = 2047;
+ minClpDC = -2047;
+ maxClpAC = 2047;
+ minClpAC = -2047;
+ }
+
+ /* Second Inverse quantisation method */
+ for (coeffCount = 0; coeffCount < 64; coeffCount++)
+ {
+ fSign = armSignCheck (pSrcDst[coeffCount]);
+ pSrcDst[coeffCount] = (armAbs(pSrcDst[coeffCount])
+ - (QP/2))/(2 * QP);
+ pSrcDst[coeffCount] *= fSign;
+
+ /* Clip */
+ if (coeffCount == 0)
+ {
+ pSrcDst[coeffCount] =
+ (OMX_S16) armClip (minClpDC, maxClpDC, pSrcDst[coeffCount]);
+ }
+ else
+ {
+ pSrcDst[coeffCount] =
+ (OMX_S16) armClip (minClpAC, maxClpAC, pSrcDst[coeffCount]);
+ }
+ }
+ return OMX_Sts_NoErr;
+
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantIntra_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantIntra_I.c
new file mode 100644
index 0000000..a10da68
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantIntra_I.c
@@ -0,0 +1,153 @@
+/**
+ *
+ * File Name: omxVCM4P2_QuantIntra_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for intra Quantization
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+/**
+ * Function: omxVCM4P2_QuantIntra_I (6.2.4.4.2)
+ *
+ * Description:
+ * Performs quantization on intra block coefficients. This function supports
+ * bits_per_pixel == 8.
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input intra block coefficients; must be aligned
+ * on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale).
+ * blockIndex - block index indicating the component type and position,
+ * valid in the range 0 to 5, as defined in [ISO14496-2], subclause
+ * 6.1.3.8.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (quantized) interblock coefficients.
+ * When shortVideoHeader==1, AC coefficients are saturated on the
+ * interval [-127, 127], and DC coefficients are saturated on the
+ * interval [1, 254]. When shortVideoHeader==0, AC coefficients
+ * are saturated on the interval [-2047, 2047].
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - pSrcDst is NULL.
+ * - blockIndex < 0 or blockIndex >= 10
+ * - QP <= 0 or QP >= 32.
+ *
+ */
+
+OMXResult omxVCM4P2_QuantIntra_I(
+ OMX_S16 * pSrcDst,
+ OMX_U8 QP,
+ OMX_INT blockIndex,
+ OMX_INT shortVideoHeader
+ )
+{
+
+ /* Definitions and Initializations*/
+ /* Initialized to remove compilation error */
+ OMX_INT dcScaler = 0, coeffCount,fSign;
+ OMX_INT maxClpAC, minClpAC;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(((blockIndex < 0) || (blockIndex >= 10)), OMX_Sts_BadArgErr);
+ armRetArgErrIf(((QP <= 0) || (QP >= 32)), OMX_Sts_BadArgErr);
+ /* One argument check is delayed until we have ascertained that */
+ /* pQMatrix is not NULL. */
+
+
+ /* Set the Clip Range based on SVH on/off */
+ if(shortVideoHeader == 1)
+ {
+ maxClpAC = 127;
+ minClpAC = -127;
+ dcScaler = 8;
+ /* Dequant the DC value, this applies to both the methods */
+ pSrcDst[0] = armIntDivAwayFromZero (pSrcDst[0], dcScaler);
+
+ /* Clip between 1 and 254 */
+ pSrcDst[0] = (OMX_S16) armClip (1, 254, pSrcDst[0]);
+ }
+ else
+ {
+ maxClpAC = 2047;
+ minClpAC = -2047;
+ /* Calculate the DC scaler value */
+ if ((blockIndex < 4) || (blockIndex > 5))
+ {
+ if (QP >= 1 && QP <= 4)
+ {
+ dcScaler = 8;
+ }
+ else if (QP >= 5 && QP <= 8)
+ {
+ dcScaler = 2 * QP;
+ }
+ else if (QP >= 9 && QP <= 24)
+ {
+ dcScaler = QP + 8;
+ }
+ else
+ {
+ dcScaler = (2 * QP) - 16;
+ }
+ }
+ else if (blockIndex < 6)
+ {
+ if (QP >= 1 && QP <= 4)
+ {
+ dcScaler = 8;
+ }
+ else if (QP >= 5 && QP <= 24)
+ {
+ dcScaler = (QP + 13)/2;
+ }
+ else
+ {
+ dcScaler = QP - 6;
+ }
+ }
+
+ /* Dequant the DC value, this applies to both the methods */
+ pSrcDst[0] = armIntDivAwayFromZero (pSrcDst[0], dcScaler);
+ }
+
+ /* Second Inverse quantisation method */
+ for (coeffCount = 1; coeffCount < 64; coeffCount++)
+ {
+ fSign = armSignCheck (pSrcDst[coeffCount]);
+ pSrcDst[coeffCount] = armAbs(pSrcDst[coeffCount])/(2 * QP);
+ pSrcDst[coeffCount] *= fSign;
+
+ /* Clip */
+ pSrcDst[coeffCount] =
+ (OMX_S16) armClip (minClpAC, maxClpAC, pSrcDst[coeffCount]);
+ }
+ return OMX_Sts_NoErr;
+
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvInter_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvInter_I.c
new file mode 100644
index 0000000..6e0de5c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvInter_I.c
@@ -0,0 +1,96 @@
+/**
+ *
+ * File Name: omxVCM4P2_QuantInvInter_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for inter inverse Quantization
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+
+/**
+ * Function: omxVCM4P2_QuantInvInter_I (6.2.5.3.2)
+ *
+ * Description:
+ * Performs the second inverse quantization mode on an intra/inter coded
+ * block. Supports bits_per_pixel = 8. The output coefficients are clipped to
+ * the range [-2048, 2047].
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input (quantized) intra/inter block; must be
+ * aligned on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale)
+ * videoComp - video component type of the current block. Takes one of the
+ * following flags: OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE (intra
+ * version only).
+ * shortVideoHeader - binary flag indicating presence of short_video_header
+ * (intra version only).
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (dequantized) intra/inter block
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; one or more of the following is
+ * true:
+ * - pSrcDst is NULL
+ * - QP <= 0 or QP >=31
+ * - videoComp is neither OMX_VC_LUMINANCE nor OMX_VC_CHROMINANCE.
+ *
+ */
+
+OMXResult omxVCM4P2_QuantInvInter_I(
+ OMX_S16 * pSrcDst,
+ OMX_INT QP
+ )
+{
+
+ OMX_INT coeffCount, Sign;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(((QP <= 0) || (QP >= 32)), OMX_Sts_BadArgErr);
+
+ /* Second Inverse quantisation method */
+ for (coeffCount = 0; coeffCount < 64; coeffCount++)
+ {
+ /* check sign */
+ Sign = armSignCheck (pSrcDst[coeffCount]);
+
+ /* Quantize the coeff */
+ if (QP & 0x1)
+ {
+ pSrcDst[coeffCount] = (2* armAbs(pSrcDst[coeffCount]) + 1) * QP;
+ pSrcDst[coeffCount] *= Sign;
+ }
+ else
+ {
+ pSrcDst[coeffCount] = (2* armAbs(pSrcDst[coeffCount]) + 1)
+ * QP - 1;
+ pSrcDst[coeffCount] *= Sign;
+ }
+ /* Saturate */
+ pSrcDst[coeffCount] = armClip (-2048, 2047, pSrcDst[coeffCount]);
+ }
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I.c
new file mode 100644
index 0000000..a946d7b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_QuantInvIntra_I.c
@@ -0,0 +1,153 @@
+/**
+ *
+ * File Name: omxVCM4P2_QuantInvIntra_I.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules for intra inverse Quantization
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+/**
+ * Function: omxVCM4P2_QuantInvIntra_I (6.2.5.3.2)
+ *
+ * Description:
+ * Performs the second inverse quantization mode on an intra/inter coded
+ * block. Supports bits_per_pixel = 8. The output coefficients are clipped to
+ * the range [-2048, 2047].
+ *
+ * Input Arguments:
+ *
+ * pSrcDst - pointer to the input (quantized) intra/inter block; must be
+ * aligned on a 16-byte boundary.
+ * QP - quantization parameter (quantizer_scale)
+ * videoComp - video component type of the current block. Takes one of the
+ * following flags: OMX_VC_LUMINANCE, OMX_VC_CHROMINANCE (intra
+ * version only).
+ * shortVideoHeader - binary flag indicating presence of short_video_header
+ * (intra version only).
+ *
+ * Output Arguments:
+ *
+ * pSrcDst - pointer to the output (dequantized) intra/inter block
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments; one or more of the following is
+ * true:
+ * - pSrcDst is NULL
+ * - QP <= 0 or QP >=31
+ * - videoComp is neither OMX_VC_LUMINANCE nor OMX_VC_CHROMINANCE.
+ *
+ */
+
+OMXResult omxVCM4P2_QuantInvIntra_I(
+ OMX_S16 * pSrcDst,
+ OMX_INT QP,
+ OMXVCM4P2VideoComponent videoComp,
+ OMX_INT shortVideoHeader
+)
+{
+
+ /* Initialized to remove compilation error */
+ OMX_INT dcScaler = 0, coeffCount, Sign;
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrcDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(((QP <= 0) || (QP >= 32)), OMX_Sts_BadArgErr);
+ armRetArgErrIf(((videoComp != OMX_VC_LUMINANCE) && (videoComp != OMX_VC_CHROMINANCE)), OMX_Sts_BadArgErr);
+
+ /* Calculate the DC scaler value */
+
+ /* linear intra DC mode */
+ if(shortVideoHeader)
+ {
+ dcScaler = 8;
+ }
+ /* nonlinear intra DC mode */
+ else
+ {
+
+ if (videoComp == OMX_VC_LUMINANCE)
+ {
+ if (QP >= 1 && QP <= 4)
+ {
+ dcScaler = 8;
+ }
+ else if (QP >= 5 && QP <= 8)
+ {
+ dcScaler = 2 * QP;
+ }
+ else if (QP >= 9 && QP <= 24)
+ {
+ dcScaler = QP + 8;
+ }
+ else
+ {
+ dcScaler = (2 * QP) - 16;
+ }
+ }
+
+ else if (videoComp == OMX_VC_CHROMINANCE)
+ {
+ if (QP >= 1 && QP <= 4)
+ {
+ dcScaler = 8;
+ }
+ else if (QP >= 5 && QP <= 24)
+ {
+ dcScaler = (QP + 13)/2;
+ }
+ else
+ {
+ dcScaler = QP - 6;
+ }
+ }
+ }
+ /* Dequant the DC value, this applies to both the methods */
+ pSrcDst[0] = pSrcDst[0] * dcScaler;
+
+ /* Saturate */
+ pSrcDst[0] = armClip (-2048, 2047, pSrcDst[0]);
+
+ /* Second Inverse quantisation method */
+ for (coeffCount = 1; coeffCount < 64; coeffCount++)
+ {
+ /* check sign */
+ Sign = armSignCheck (pSrcDst[coeffCount]);
+
+ if (QP & 0x1)
+ {
+ pSrcDst[coeffCount] = (2* armAbs(pSrcDst[coeffCount]) + 1) * QP;
+ pSrcDst[coeffCount] *= Sign;
+ }
+ else
+ {
+ pSrcDst[coeffCount] =
+ (2* armAbs(pSrcDst[coeffCount]) + 1) * QP - 1;
+ pSrcDst[coeffCount] *= Sign;
+ }
+
+ /* Saturate */
+ pSrcDst[coeffCount] = armClip (-2048, 2047, pSrcDst[coeffCount]);
+ }
+ return OMX_Sts_NoErr;
+
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_inter.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_inter.c
new file mode 100644
index 0000000..6e0c59b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_inter.c
@@ -0,0 +1,108 @@
+/**
+ *
+ * File Name: omxVCM4P2_TransRecBlockCoef_inter.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules DCT->quant and reconstructing the inter texture data
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+
+
+/**
+ * Function: omxVCM4P2_TransRecBlockCoef_inter (6.2.4.4.5)
+ *
+ * Description:
+ * Implements DCT, and quantizes the DCT coefficients of the inter block
+ * while reconstructing the texture residual. There is no boundary check for
+ * the bit stream buffer.
+ *
+ * Input Arguments:
+ *
+ * pSrc -pointer to the residuals to be encoded; must be aligned on an
+ * 16-byte boundary.
+ * QP - quantization parameter.
+ * shortVideoHeader - binary flag indicating presence of short_video_header;
+ * shortVideoHeader==1 selects linear intra DC mode, and
+ * shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the quantized DCT coefficients buffer; must be aligned
+ * on a 16-byte boundary.
+ * pRec - pointer to the reconstructed texture residuals; must be aligned
+ * on a 16-byte boundary.
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - bad arguments:
+ * - At least one of the following pointers is either NULL or
+ * not 16-byte aligned:
+ * - pSrc
+ * - pDst
+ * - pRec
+ * - QP <= 0 or QP >= 32.
+ *
+ */
+
+OMXResult omxVCM4P2_TransRecBlockCoef_inter(
+ const OMX_S16 *pSrc,
+ OMX_S16 * pDst,
+ OMX_S16 * pRec,
+ OMX_U8 QP,
+ OMX_INT shortVideoHeader
+)
+{
+ /* 64 elements are needed but to align it to 16 bytes need
+ 8 more elements of padding */
+ OMX_S16 tempBuffer[72];
+ OMX_S16 *pTempBuffer;
+ OMX_INT i;
+
+ /* Aligning the local buffers */
+ pTempBuffer = armAlignTo16Bytes(tempBuffer);
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pRec == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pSrc), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pRec), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(((QP <= 0) || (QP >= 32)), OMX_Sts_BadArgErr);
+
+ omxVCM4P2_DCT8x8blk (pSrc, pDst);
+ omxVCM4P2_QuantInter_I(
+ pDst,
+ QP,
+ shortVideoHeader);
+
+ for (i = 0; i < 64; i++)
+ {
+ pTempBuffer[i] = pDst[i];
+ }
+
+ omxVCM4P2_QuantInvInter_I(
+ pTempBuffer,
+ QP);
+ omxVCM4P2_IDCT8x8blk (pTempBuffer, pRec);
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_intra.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_intra.c
new file mode 100644
index 0000000..dd444f9
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/m4p2/src/omxVCM4P2_TransRecBlockCoef_intra.c
@@ -0,0 +1,260 @@
+/**
+ *
+ * File Name: omxVCM4P2_TransRecBlockCoef_intra.c
+ * OpenMAX DL: v1.0.2
+ * Revision: 9641
+ * Date: Thursday, February 7, 2008
+ *
+ * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved.
+ *
+ *
+ *
+ * Description:
+ * Contains modules DCT->quant and reconstructing the intra texture data
+ *
+ */
+
+#include "omxtypes.h"
+#include "armOMX.h"
+#include "omxVC.h"
+
+#include "armCOMM.h"
+#include "armVC.h"
+
+
+/**
+ * Function: omxVCM4P2_TransRecBlockCoef_intra (6.2.4.4.4)
+ *
+ * Description:
+ * Quantizes the DCT coefficients, implements intra block AC/DC coefficient
+ * prediction, and reconstructs the current intra block texture for prediction
+ * on the next frame. Quantized row and column coefficients are returned in
+ * the updated coefficient buffers.
+ *
+ * Input Arguments:
+ *
+ * pSrc - pointer to the pixels of current intra block; must be aligned on
+ * an 8-byte boundary.
+ * pPredBufRow - pointer to the coefficient row buffer containing
+ * ((num_mb_per_row * 2 + 1) * 8) elements of type OMX_S16.
+ * Coefficients are organized into blocks of eight as described
+ * below (Internal Prediction Coefficient Update Procedures). The
+ * DC coefficient is first, and the remaining buffer locations
+ * contain the quantized AC coefficients. Each group of eight row
+ * buffer elements combined with one element eight elements ahead
+ * contains the coefficient predictors of the neighboring block
+ * that is spatially above or to the left of the block currently to
+ * be decoded. A negative-valued DC coefficient indicates that this
+ * neighboring block is not INTRA-coded or out of bounds, and
+ * therefore the AC and DC coefficients are invalid. Pointer must
+ * be aligned on an 8-byte boundary.
+ * pPredBufCol - pointer to the prediction coefficient column buffer
+ * containing 16 elements of type OMX_S16. Coefficients are
+ * organized as described in section 6.2.2.5. Pointer must be
+ * aligned on an 8-byte boundary.
+ * pSumErr - pointer to a flag indicating whether or not AC prediction is
+ * required; AC prediction is enabled if *pSumErr >=0, but the
+ * value is not used for coefficient prediction, i.e., the sum of
+ * absolute differences starts from 0 for each call to this
+ * function. Otherwise AC prediction is disabled if *pSumErr < 0 .
+ * blockIndex - block index indicating the component type and position, as
+ * defined in [ISO14496-2], subclause 6.1.3.8.
+ * curQp - quantization parameter of the macroblock to which the current
+ * block belongs
+ * pQpBuf - pointer to a 2-element quantization parameter buffer; pQpBuf[0]
+ * contains the quantization parameter associated with the 8x8
+ * block left of the current block (QPa), and pQpBuf[1] contains
+ * the quantization parameter associated with the 8x8 block above
+ * the current block (QPc). In the event that the corresponding
+ * block is outside of the VOP bound, the Qp value will not affect
+ * the intra prediction process, as described in [ISO14496-2],
+ * sub-clause 7.4.3.3, Adaptive AC Coefficient Prediction.
+ * srcStep - width of the source buffer; must be a multiple of 8.
+ * dstStep - width of the reconstructed destination buffer; must be a
+ * multiple of 16.
+ * shortVideoHeader - binary flag indicating presence of
+ * short_video_header; shortVideoHeader==1 selects linear intra DC
+ * mode, and shortVideoHeader==0 selects non linear intra DC mode.
+ *
+ * Output Arguments:
+ *
+ * pDst - pointer to the quantized DCT coefficient buffer; pDst[0] contains
+ * the predicted DC coefficient; the remaining entries contain the
+ * quantized AC coefficients (without prediction). The pointer
+ * pDstmust be aligned on a 16-byte boundary.
+ * pRec - pointer to the reconstructed texture; must be aligned on an
+ * 8-byte boundary.
+ * pPredBufRow - pointer to the updated coefficient row buffer
+ * pPredBufCol - pointer to the updated coefficient column buffer
+ * pPreACPredict - if prediction is enabled, the parameter points to the
+ * start of the buffer containing the coefficient differences for
+ * VLC encoding. The entry pPreACPredict[0]indicates prediction
+ * direction for the current block and takes one of the following
+ * values: OMX_VC_NONE (prediction disabled), OMX_VC_HORIZONTAL, or
+ * OMX_VC_VERTICAL. The entries
+ * pPreACPredict[1]-pPreACPredict[7]contain predicted AC
+ * coefficients. If prediction is disabled (*pSumErr<0) then the
+ * contents of this buffer are undefined upon return from the
+ * function
+ * pSumErr - pointer to the value of the accumulated AC coefficient errors,
+ * i.e., sum of the absolute differences between predicted and
+ * unpredicted AC coefficients
+ *
+ * Return Value:
+ *
+ * OMX_Sts_NoErr - no error
+ * OMX_Sts_BadArgErr - Bad arguments:
+ * - At least one of the following pointers is NULL: pSrc, pDst, pRec,
+ * pCoefBufRow, pCoefBufCol, pQpBuf, pPreACPredict, pSumErr.
+ * - blockIndex < 0 or blockIndex >= 10;
+ * - curQP <= 0 or curQP >= 32.
+ * - srcStep, or dstStep <= 0 or not a multiple of 8.
+ * - pDst is not 16-byte aligned: .
+ * - At least one of the following pointers is not 8-byte aligned:
+ * pSrc, pRec.
+ *
+ * Note: The coefficient buffers must be updated in accordance with the
+ * update procedures defined in section in 6.2.2.
+ *
+ */
+
+OMXResult omxVCM4P2_TransRecBlockCoef_intra(
+ const OMX_U8 *pSrc,
+ OMX_S16 * pDst,
+ OMX_U8 * pRec,
+ OMX_S16 *pPredBufRow,
+ OMX_S16 *pPredBufCol,
+ OMX_S16 * pPreACPredict,
+ OMX_INT *pSumErr,
+ OMX_INT blockIndex,
+ OMX_U8 curQp,
+ const OMX_U8 *pQpBuf,
+ OMX_INT srcStep,
+ OMX_INT dstStep,
+ OMX_INT shortVideoHeader
+)
+{
+ /* 64 elements are needed but to align it to 16 bytes need
+ 8 more elements of padding */
+ OMX_S16 tempBuf1[79], tempBuf2[79];
+ OMX_S16 tempBuf3[79];
+ OMX_S16 *pTempBuf1, *pTempBuf2,*pTempBuf3;
+ OMXVCM4P2VideoComponent videoComp;
+ OMX_U8 flag;
+ OMX_INT x, y, count, predDir;
+ OMX_INT predQP, ACPredFlag;
+
+
+ /* Aligning the local buffers */
+ pTempBuf1 = armAlignTo16Bytes(tempBuf1);
+ pTempBuf2 = armAlignTo16Bytes(tempBuf2);
+ pTempBuf3 = armAlignTo16Bytes(tempBuf3);
+
+ /* Argument error checks */
+ armRetArgErrIf(pSrc == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pRec == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pDst == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs8ByteAligned(pSrc), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs8ByteAligned(pRec), OMX_Sts_BadArgErr);
+ armRetArgErrIf(!armIs16ByteAligned(pDst), OMX_Sts_BadArgErr);
+ armRetArgErrIf(pPredBufRow == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pPredBufCol == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pPreACPredict == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pSumErr == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf(pQpBuf == NULL, OMX_Sts_BadArgErr);
+ armRetArgErrIf((srcStep <= 0) || (dstStep <= 0) ||
+ (dstStep & 7) || (srcStep & 7)
+ , OMX_Sts_BadArgErr);
+ armRetArgErrIf((blockIndex < 0) || (blockIndex > 9), OMX_Sts_BadArgErr);
+
+ armRetArgErrIf((curQp <= 0) || (curQp >=32), OMX_Sts_BadArgErr);
+
+
+ /* Setting the videoComp */
+ if (blockIndex <= 3)
+ {
+ videoComp = OMX_VC_LUMINANCE;
+ }
+ else
+ {
+ videoComp = OMX_VC_CHROMINANCE;
+ }
+ /* Converting from 2-d to 1-d buffer */
+ for (y = 0, count = 0; y < 8; y++)
+ {
+ for(x= 0; x < 8; x++, count++)
+ {
+ pTempBuf1[count] = pSrc[(y*srcStep) + x];
+ }
+ }
+
+ omxVCM4P2_DCT8x8blk (pTempBuf1, pTempBuf2);
+ omxVCM4P2_QuantIntra_I(
+ pTempBuf2,
+ curQp,
+ blockIndex,
+ shortVideoHeader);
+
+ /* Converting from 1-D to 2-D buffer */
+ for (y = 0, count = 0; y < 8; y++)
+ {
+ for(x = 0; x < 8; x++, count++)
+ {
+ /* storing tempbuf2 to tempbuf1 */
+ pTempBuf1[count] = pTempBuf2[count];
+ pDst[(y*dstStep) + x] = pTempBuf2[count];
+ }
+ }
+
+ /* AC and DC prediction */
+ armVCM4P2_SetPredDir(
+ blockIndex,
+ pPredBufRow,
+ pPredBufCol,
+ &predDir,
+ &predQP,
+ pQpBuf);
+
+ armRetDataErrIf(((predQP <= 0) || (predQP >= 32)), OMX_Sts_BadArgErr);
+
+ flag = 1;
+ if (*pSumErr < 0)
+ {
+ ACPredFlag = 0;
+ }
+ else
+ {
+ ACPredFlag = 1;
+ }
+
+ armVCM4P2_ACDCPredict(
+ pTempBuf2,
+ pPreACPredict,
+ pPredBufRow,
+ pPredBufCol,
+ curQp,
+ predQP,
+ predDir,
+ ACPredFlag,
+ videoComp,
+ flag,
+ pSumErr);
+
+ /* Reconstructing the texture data */
+ omxVCM4P2_QuantInvIntra_I(
+ pTempBuf1,
+ curQp,
+ videoComp,
+ shortVideoHeader);
+ omxVCM4P2_IDCT8x8blk (pTempBuf1, pTempBuf3);
+ for(count = 0; count < 64; count++)
+ {
+ pRec[count] = armMax(0,pTempBuf3[count]);
+ }
+
+ return OMX_Sts_NoErr;
+}
+
+/* End of file */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/src/armVC_Version.c b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/src/armVC_Version.c
new file mode 100644
index 0000000..5d93681
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/omxdl/reference/vc/src/armVC_Version.c
@@ -0,0 +1,6 @@
+#include "omxtypes.h"
+#include "armCOMM_Version.h"
+
+#ifdef ARM_INCLUDE_VERSION_DESCRIPTIONS
+const char * const omxVC_VersionDescription = "ARM OpenMAX DL v" ARM_VERSION_STRING " Rel=" OMX_ARM_RELEASE_TAG " Arch=" OMX_ARM_BUILD_ARCHITECTURE " Tools=" OMX_ARM_BUILD_TOOLCHAIN ;
+#endif /* ARM_INCLUDE_VERSION_DESCRIPTIONS */
diff --git a/media/libstagefright/codecs/on2/h264dec/source/DecTestBench.c b/media/libstagefright/codecs/on2/h264dec/source/DecTestBench.c
new file mode 100755
index 0000000..dcf2ef6
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/DecTestBench.c
@@ -0,0 +1,761 @@
+/*
+ * 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 "H264SwDecApi.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*------------------------------------------------------------------------------
+ Module defines
+------------------------------------------------------------------------------*/
+
+/* CHECK_MEMORY_USAGE prints and sums the memory allocated in calls to
+ * H264SwDecMalloc() */
+/* #define CHECK_MEMORY_USAGE */
+
+/* _NO_OUT disables output file writing */
+/* #define _NO_OUT */
+
+/* Debug prints */
+#define DEBUG(argv) printf argv
+
+/* CVS tag name for identification */
+const char tagName[256] = "$Name: FIRST_ANDROID_COPYRIGHT $";
+
+void WriteOutput(char *filename, u8 *data, u32 picSize);
+u32 NextPacket(u8 **pStrm);
+u32 CropPicture(u8 *pOutImage, u8 *pInImage,
+ u32 picWidth, u32 picHeight, CropParams *pCropParams);
+
+/* Global variables for stream handling */
+u8 *streamStop = NULL;
+u32 packetize = 0;
+u32 nalUnitStream = 0;
+FILE *foutput = NULL;
+
+#ifdef SOC_DESIGNER
+
+// Initialisation function defined in InitCache.s
+extern void cache_init(void);
+
+/*------------------------------------------------------------------------------
+
+ Function name: $Sub$$main
+
+ Purpose:
+ This function is called at the end of the C library initialisation and
+ before main. Its purpose is to do any further initialisation before the
+ application start.
+
+------------------------------------------------------------------------------*/
+int $Sub$$main(char argc, char * argv[])
+{
+ cache_init(); // does some extra setup work setting up caches
+ return $Super$$main(argc, argv); // calls the original function
+}
+#endif
+
+/*------------------------------------------------------------------------------
+
+ Function name: main
+
+ Purpose:
+ main function of decoder testbench. Provides command line interface
+ with file I/O for H.264 decoder. Prints out the usage information
+ when executed without arguments.
+
+------------------------------------------------------------------------------*/
+
+int main(int argc, char **argv)
+{
+
+ u32 i, tmp;
+ u32 maxNumPics = 0;
+ u8 *byteStrmStart;
+ u8 *imageData;
+ u8 *tmpImage = NULL;
+ u32 strmLen;
+ u32 picSize;
+ H264SwDecInst decInst;
+ H264SwDecRet ret;
+ H264SwDecInput decInput;
+ H264SwDecOutput decOutput;
+ H264SwDecPicture decPicture;
+ H264SwDecInfo decInfo;
+ H264SwDecApiVersion decVer;
+ u32 picDecodeNumber;
+ u32 picDisplayNumber;
+ u32 numErrors = 0;
+ u32 cropDisplay = 0;
+ u32 disableOutputReordering = 0;
+
+ FILE *finput;
+
+ char outFileName[256] = "";
+
+ /* Print API version number */
+ decVer = H264SwDecGetAPIVersion();
+ DEBUG(("H.264 Decoder API v%d.%d\n", decVer.major, decVer.minor));
+
+ /* Print tag name if '-T' argument present */
+ if ( argc > 1 && strcmp(argv[1], "-T") == 0 )
+ {
+ DEBUG(("%s\n", tagName));
+ return 0;
+ }
+
+ /* Check that enough command line arguments given, if not -> print usage
+ * information out */
+ if (argc < 2)
+ {
+ DEBUG((
+ "Usage: %s [-Nn] [-Ooutfile] [-P] [-U] [-C] [-R] [-T] file.h264\n",
+ argv[0]));
+ DEBUG(("\t-Nn forces decoding to stop after n pictures\n"));
+#if defined(_NO_OUT)
+ DEBUG(("\t-Ooutfile output writing disabled at compile time\n"));
+#else
+ DEBUG(("\t-Ooutfile write output to \"outfile\" (default out_wxxxhyyy.yuv)\n"));
+ DEBUG(("\t-Onone does not write output\n"));
+#endif
+ DEBUG(("\t-P packet-by-packet mode\n"));
+ DEBUG(("\t-U NAL unit stream mode\n"));
+ DEBUG(("\t-C display cropped image (default decoded image)\n"));
+ DEBUG(("\t-R disable DPB output reordering\n"));
+ DEBUG(("\t-T to print tag name and exit\n"));
+ return 0;
+ }
+
+ /* read command line arguments */
+ for (i = 1; i < (u32)(argc-1); i++)
+ {
+ if ( strncmp(argv[i], "-N", 2) == 0 )
+ {
+ maxNumPics = (u32)atoi(argv[i]+2);
+ }
+ else if ( strncmp(argv[i], "-O", 2) == 0 )
+ {
+ strcpy(outFileName, argv[i]+2);
+ }
+ else if ( strcmp(argv[i], "-P") == 0 )
+ {
+ packetize = 1;
+ }
+ else if ( strcmp(argv[i], "-U") == 0 )
+ {
+ nalUnitStream = 1;
+ }
+ else if ( strcmp(argv[i], "-C") == 0 )
+ {
+ cropDisplay = 1;
+ }
+ else if ( strcmp(argv[i], "-R") == 0 )
+ {
+ disableOutputReordering = 1;
+ }
+ }
+
+ /* open input file for reading, file name given by user. If file open
+ * fails -> exit */
+ finput = fopen(argv[argc-1],"rb");
+ if (finput == NULL)
+ {
+ DEBUG(("UNABLE TO OPEN INPUT FILE\n"));
+ return -1;
+ }
+
+ /* check size of the input file -> length of the stream in bytes */
+ fseek(finput,0L,SEEK_END);
+ strmLen = (u32)ftell(finput);
+ rewind(finput);
+
+ /* allocate memory for stream buffer. if unsuccessful -> exit */
+ byteStrmStart = (u8 *)malloc(sizeof(u8)*strmLen);
+ if (byteStrmStart == NULL)
+ {
+ DEBUG(("UNABLE TO ALLOCATE MEMORY\n"));
+ return -1;
+ }
+
+ /* read input stream from file to buffer and close input file */
+ fread(byteStrmStart, sizeof(u8), strmLen, finput);
+ fclose(finput);
+
+ /* initialize decoder. If unsuccessful -> exit */
+ ret = H264SwDecInit(&decInst, disableOutputReordering);
+ if (ret != H264SWDEC_OK)
+ {
+ DEBUG(("DECODER INITIALIZATION FAILED\n"));
+ free(byteStrmStart);
+ return -1;
+ }
+
+ /* initialize H264SwDecDecode() input structure */
+ streamStop = byteStrmStart + strmLen;
+ decInput.pStream = byteStrmStart;
+ decInput.dataLen = strmLen;
+ decInput.intraConcealmentMethod = 0;
+
+ /* get pointer to next packet and the size of packet
+ * (for packetize or nalUnitStream modes) */
+ if ( (tmp = NextPacket(&decInput.pStream)) != 0 )
+ decInput.dataLen = tmp;
+
+ picDecodeNumber = picDisplayNumber = 1;
+ /* main decoding loop */
+ do
+ {
+ /* Picture ID is the picture number in decoding order */
+ decInput.picId = picDecodeNumber;
+
+ /* call API function to perform decoding */
+ ret = H264SwDecDecode(decInst, &decInput, &decOutput);
+
+ switch(ret)
+ {
+
+ case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY:
+ /* Stream headers were successfully decoded
+ * -> stream information is available for query now */
+
+ ret = H264SwDecGetInfo(decInst, &decInfo);
+ if (ret != H264SWDEC_OK)
+ return -1;
+
+ DEBUG(("Profile %d\n", decInfo.profile));
+
+ DEBUG(("Width %d Height %d\n",
+ decInfo.picWidth, decInfo.picHeight));
+
+ if (cropDisplay && decInfo.croppingFlag)
+ {
+ DEBUG(("Cropping params: (%d, %d) %dx%d\n",
+ decInfo.cropParams.cropLeftOffset,
+ decInfo.cropParams.cropTopOffset,
+ decInfo.cropParams.cropOutWidth,
+ decInfo.cropParams.cropOutHeight));
+
+ /* Cropped frame size in planar YUV 4:2:0 */
+ picSize = decInfo.cropParams.cropOutWidth *
+ decInfo.cropParams.cropOutHeight;
+ picSize = (3 * picSize)/2;
+ tmpImage = malloc(picSize);
+ if (tmpImage == NULL)
+ return -1;
+ }
+ else
+ {
+ /* Decoder output frame size in planar YUV 4:2:0 */
+ picSize = decInfo.picWidth * decInfo.picHeight;
+ picSize = (3 * picSize)/2;
+ }
+
+ DEBUG(("videoRange %d, matrixCoefficients %d\n",
+ decInfo.videoRange, decInfo.matrixCoefficients));
+
+ /* update H264SwDecDecode() input structure, number of bytes
+ * "consumed" is computed as difference between the new stream
+ * pointer and old stream pointer */
+ decInput.dataLen -=
+ (u32)(decOutput.pStrmCurrPos - decInput.pStream);
+ decInput.pStream = decOutput.pStrmCurrPos;
+
+ /* If -O option not used, generate default file name */
+ if (outFileName[0] == 0)
+ sprintf(outFileName, "out_w%dh%d.yuv",
+ decInfo.picWidth, decInfo.picHeight);
+ break;
+
+ case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY:
+ /* Picture is ready and more data remains in input buffer
+ * -> update H264SwDecDecode() input structure, number of bytes
+ * "consumed" is computed as difference between the new stream
+ * pointer and old stream pointer */
+ decInput.dataLen -=
+ (u32)(decOutput.pStrmCurrPos - decInput.pStream);
+ decInput.pStream = decOutput.pStrmCurrPos;
+ /* fall through */
+
+ case H264SWDEC_PIC_RDY:
+
+ /*lint -esym(644,tmpImage,picSize) variable initialized at
+ * H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY case */
+
+ if (ret == H264SWDEC_PIC_RDY)
+ decInput.dataLen = NextPacket(&decInput.pStream);
+
+ /* If enough pictures decoded -> force decoding to end
+ * by setting that no more stream is available */
+ if (maxNumPics && picDecodeNumber == maxNumPics)
+ decInput.dataLen = 0;
+
+ /* Increment decoding number for every decoded picture */
+ picDecodeNumber++;
+
+ /* use function H264SwDecNextPicture() to obtain next picture
+ * in display order. Function is called until no more images
+ * are ready for display */
+ while ( H264SwDecNextPicture(decInst, &decPicture, 0) ==
+ H264SWDEC_PIC_RDY )
+ {
+ DEBUG(("PIC %d, type %s", picDisplayNumber,
+ decPicture.isIdrPicture ? "IDR" : "NON-IDR"));
+ if (picDisplayNumber != decPicture.picId)
+ DEBUG((", decoded pic %d", decPicture.picId));
+ if (decPicture.nbrOfErrMBs)
+ {
+ DEBUG((", concealed %d\n", decPicture.nbrOfErrMBs));
+ }
+ else
+ DEBUG(("\n"));
+ fflush(stdout);
+
+ numErrors += decPicture.nbrOfErrMBs;
+
+ /* Increment display number for every displayed picture */
+ picDisplayNumber++;
+
+ /*lint -esym(644,decInfo) always initialized if pictures
+ * available for display */
+
+ /* Write output picture to file */
+ imageData = (u8*)decPicture.pOutputPicture;
+ if (cropDisplay && decInfo.croppingFlag)
+ {
+ tmp = CropPicture(tmpImage, imageData,
+ decInfo.picWidth, decInfo.picHeight,
+ &decInfo.cropParams);
+ if (tmp)
+ return -1;
+ WriteOutput(outFileName, tmpImage, picSize);
+ }
+ else
+ {
+ WriteOutput(outFileName, imageData, picSize);
+ }
+ }
+
+ break;
+
+ case H264SWDEC_STRM_PROCESSED:
+ case H264SWDEC_STRM_ERR:
+ /* Input stream was decoded but no picture is ready
+ * -> Get more data */
+ decInput.dataLen = NextPacket(&decInput.pStream);
+ break;
+
+ default:
+ DEBUG(("FATAL ERROR\n"));
+ return -1;
+
+ }
+ /* keep decoding until all data from input stream buffer consumed */
+ } while (decInput.dataLen > 0);
+
+ /* if output in display order is preferred, the decoder shall be forced
+ * to output pictures remaining in decoded picture buffer. Use function
+ * H264SwDecNextPicture() to obtain next picture in display order. Function
+ * is called until no more images are ready for display. Second parameter
+ * for the function is set to '1' to indicate that this is end of the
+ * stream and all pictures shall be output */
+ while (H264SwDecNextPicture(decInst, &decPicture, 1) == H264SWDEC_PIC_RDY)
+ {
+ DEBUG(("PIC %d, type %s", picDisplayNumber,
+ decPicture.isIdrPicture ? "IDR" : "NON-IDR"));
+ if (picDisplayNumber != decPicture.picId)
+ DEBUG((", decoded pic %d", decPicture.picId));
+ if (decPicture.nbrOfErrMBs)
+ {
+ DEBUG((", concealed %d\n", decPicture.nbrOfErrMBs));
+ }
+ else
+ DEBUG(("\n"));
+ fflush(stdout);
+
+ numErrors += decPicture.nbrOfErrMBs;
+
+ /* Increment display number for every displayed picture */
+ picDisplayNumber++;
+
+ /* Write output picture to file */
+ imageData = (u8*)decPicture.pOutputPicture;
+ if (cropDisplay && decInfo.croppingFlag)
+ {
+ tmp = CropPicture(tmpImage, imageData,
+ decInfo.picWidth, decInfo.picHeight,
+ &decInfo.cropParams);
+ if (tmp)
+ return -1;
+ WriteOutput(outFileName, tmpImage, picSize);
+ }
+ else
+ {
+ WriteOutput(outFileName, imageData, picSize);
+ }
+ }
+
+ /* release decoder instance */
+ H264SwDecRelease(decInst);
+
+ if (foutput)
+ fclose(foutput);
+
+ /* free allocated buffers */
+ free(byteStrmStart);
+ free(tmpImage);
+
+ DEBUG(("Output file: %s\n", outFileName));
+
+ DEBUG(("DECODING DONE\n"));
+ if (numErrors || picDecodeNumber == 1)
+ {
+ DEBUG(("ERRORS FOUND\n"));
+ return 1;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: WriteOutput
+
+ Purpose:
+ Write picture pointed by data to file. Size of the
+ picture in pixels is indicated by picSize.
+
+------------------------------------------------------------------------------*/
+void WriteOutput(char *filename, u8 *data, u32 picSize)
+{
+
+ /* foutput is global file pointer */
+ if (foutput == NULL)
+ {
+ /* open output file for writing, can be disabled with define.
+ * If file open fails -> exit */
+ if (strcmp(filename, "none") != 0)
+ {
+#if !defined(_NO_OUT)
+ foutput = fopen(filename, "wb");
+ if (foutput == NULL)
+ {
+ DEBUG(("UNABLE TO OPEN OUTPUT FILE\n"));
+ exit(100);
+ }
+#endif
+ }
+ }
+
+ if (foutput && data)
+ fwrite(data, 1, picSize, foutput);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: NextPacket
+
+ Purpose:
+ Get the pointer to start of next packet in input stream. Uses
+ global variables 'packetize' and 'nalUnitStream' to determine the
+ decoder input stream mode and 'streamStop' to determine the end
+ of stream. There are three possible stream modes:
+ default - the whole stream at once
+ packetize - a single NAL-unit with start code prefix
+ nalUnitStream - a single NAL-unit without start code prefix
+
+ pStrm stores pointer to the start of previous decoder input and is
+ replaced with pointer to the start of the next decoder input.
+
+ Returns the packet size in bytes
+
+------------------------------------------------------------------------------*/
+u32 NextPacket(u8 **pStrm)
+{
+
+ u32 index;
+ u32 maxIndex;
+ u32 zeroCount;
+ u8 *stream;
+ u8 byte;
+ static u32 prevIndex=0;
+
+ /* For default stream mode all the stream is in first packet */
+ if (!packetize && !nalUnitStream)
+ return 0;
+
+ index = 0;
+ stream = *pStrm + prevIndex;
+ maxIndex = (u32)(streamStop - stream);
+
+ if (maxIndex == 0)
+ return(0);
+
+ /* leading zeros of first NAL unit */
+ do
+ {
+ byte = stream[index++];
+ } while (byte != 1 && index < maxIndex);
+
+ /* invalid start code prefix */
+ if (index == maxIndex || index < 3)
+ {
+ DEBUG(("INVALID BYTE STREAM\n"));
+ exit(100);
+ }
+
+ /* nalUnitStream is without start code prefix */
+ if (nalUnitStream)
+ {
+ stream += index;
+ maxIndex -= index;
+ index = 0;
+ }
+
+ zeroCount = 0;
+
+ /* Search stream for next start code prefix */
+ /*lint -e(716) while(1) used consciously */
+ while (1)
+ {
+ byte = stream[index++];
+ if (!byte)
+ zeroCount++;
+
+ if ( (byte == 0x01) && (zeroCount >= 2) )
+ {
+ /* Start code prefix has two zeros
+ * Third zero is assumed to be leading zero of next packet
+ * Fourth and more zeros are assumed to be trailing zeros of this
+ * packet */
+ if (zeroCount > 3)
+ {
+ index -= 4;
+ zeroCount -= 3;
+ }
+ else
+ {
+ index -= zeroCount+1;
+ zeroCount = 0;
+ }
+ break;
+ }
+ else if (byte)
+ zeroCount = 0;
+
+ if (index == maxIndex)
+ {
+ break;
+ }
+
+ }
+
+ /* Store pointer to the beginning of the packet */
+ *pStrm = stream;
+ prevIndex = index;
+
+ /* nalUnitStream is without trailing zeros */
+ if (nalUnitStream)
+ index -= zeroCount;
+
+ return(index);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: CropPicture
+
+ Purpose:
+ Perform cropping for picture. Input picture pInImage with dimensions
+ picWidth x picHeight is cropped with pCropParams and the resulting
+ picture is stored in pOutImage.
+
+------------------------------------------------------------------------------*/
+u32 CropPicture(u8 *pOutImage, u8 *pInImage,
+ u32 picWidth, u32 picHeight, CropParams *pCropParams)
+{
+
+ u32 i, j;
+ u32 outWidth, outHeight;
+ u8 *pOut, *pIn;
+
+ if (pOutImage == NULL || pInImage == NULL || pCropParams == NULL ||
+ !picWidth || !picHeight)
+ {
+ /* just to prevent lint warning, returning non-zero will result in
+ * return without freeing the memory */
+ free(pOutImage);
+ return(1);
+ }
+
+ if ( ((pCropParams->cropLeftOffset + pCropParams->cropOutWidth) >
+ picWidth ) ||
+ ((pCropParams->cropTopOffset + pCropParams->cropOutHeight) >
+ picHeight ) )
+ {
+ /* just to prevent lint warning, returning non-zero will result in
+ * return without freeing the memory */
+ free(pOutImage);
+ return(1);
+ }
+
+ outWidth = pCropParams->cropOutWidth;
+ outHeight = pCropParams->cropOutHeight;
+
+ /* Calculate starting pointer for luma */
+ pIn = pInImage + pCropParams->cropTopOffset*picWidth +
+ pCropParams->cropLeftOffset;
+ pOut = pOutImage;
+
+ /* Copy luma pixel values */
+ for (i = outHeight; i; i--)
+ {
+ for (j = outWidth; j; j--)
+ {
+ *pOut++ = *pIn++;
+ }
+ pIn += picWidth - outWidth;
+ }
+
+ outWidth >>= 1;
+ outHeight >>= 1;
+
+ /* Calculate starting pointer for cb */
+ pIn = pInImage + picWidth*picHeight +
+ pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2;
+
+ /* Copy cb pixel values */
+ for (i = outHeight; i; i--)
+ {
+ for (j = outWidth; j; j--)
+ {
+ *pOut++ = *pIn++;
+ }
+ pIn += picWidth/2 - outWidth;
+ }
+
+ /* Calculate starting pointer for cr */
+ pIn = pInImage + 5*picWidth*picHeight/4 +
+ pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2;
+
+ /* Copy cr pixel values */
+ for (i = outHeight; i; i--)
+ {
+ for (j = outWidth; j; j--)
+ {
+ *pOut++ = *pIn++;
+ }
+ pIn += picWidth/2 - outWidth;
+ }
+
+ return (0);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecTrace
+
+ Purpose:
+ Example implementation of H264SwDecTrace function. Prototype of this
+ function is given in H264SwDecApi.h. This implementation appends
+ trace messages to file named 'dec_api.trc'.
+
+------------------------------------------------------------------------------*/
+void H264SwDecTrace(char *string)
+{
+ FILE *fp;
+
+ fp = fopen("dec_api.trc", "at");
+
+ if (!fp)
+ return;
+
+ fwrite(string, 1, strlen(string), fp);
+ fwrite("\n", 1,1, fp);
+
+ fclose(fp);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecMalloc
+
+ Purpose:
+ Example implementation of H264SwDecMalloc function. Prototype of this
+ function is given in H264SwDecApi.h. This implementation uses
+ library function malloc for allocation of memory.
+
+------------------------------------------------------------------------------*/
+void* H264SwDecMalloc(u32 size)
+{
+
+#if defined(CHECK_MEMORY_USAGE)
+ /* Note that if the decoder has to free and reallocate some of the buffers
+ * the total value will be invalid */
+ static u32 numBytes = 0;
+ numBytes += size;
+ DEBUG(("Allocated %d bytes, total %d\n", size, numBytes));
+#endif
+
+ return malloc(size);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecFree
+
+ Purpose:
+ Example implementation of H264SwDecFree function. Prototype of this
+ function is given in H264SwDecApi.h. This implementation uses
+ library function free for freeing of memory.
+
+------------------------------------------------------------------------------*/
+void H264SwDecFree(void *ptr)
+{
+ free(ptr);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecMemcpy
+
+ Purpose:
+ Example implementation of H264SwDecMemcpy function. Prototype of this
+ function is given in H264SwDecApi.h. This implementation uses
+ library function memcpy to copy src to dest.
+
+------------------------------------------------------------------------------*/
+void H264SwDecMemcpy(void *dest, void *src, u32 count)
+{
+ memcpy(dest, src, count);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecMemset
+
+ Purpose:
+ Example implementation of H264SwDecMemset function. Prototype of this
+ function is given in H264SwDecApi.h. This implementation uses
+ library function memset to set content of memory area pointed by ptr.
+
+------------------------------------------------------------------------------*/
+void H264SwDecMemset(void *ptr, i32 value, u32 count)
+{
+ memset(ptr, value, count);
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c b/media/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c
new file mode 100755
index 0000000..aadc75f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/EvaluationTestBench.c
@@ -0,0 +1,350 @@
+/*
+ * 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 "H264SwDecApi.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void WriteOutput(FILE *fid, u8 *data, u32 picSize);
+
+/*------------------------------------------------------------------------------
+
+ Function name: main
+
+ Purpose:
+ main function. Assuming that executable is named 'decoder' the usage
+ is as follows
+
+ decoder inputFileName
+
+ , where inputFileName shall be name of file containing h264 stream
+ data.
+
+------------------------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+
+ u8 *byteStrmStart;
+ u8 *byteStrm;
+ u32 strmLen;
+ u32 picSize;
+ H264SwDecInst decInst;
+ H264SwDecRet ret;
+ H264SwDecInput decInput;
+ H264SwDecOutput decOutput;
+ H264SwDecPicture decPicture;
+ H264SwDecInfo decInfo;
+ u32 picNumber;
+
+ FILE *finput;
+ FILE *foutput;
+
+ /* Check that enough command line arguments given, if not -> print usage
+ * information out */
+ if (argc < 2)
+ {
+ printf( "Usage: %s file.h264\n", argv[0]);
+ return -1;
+ }
+
+ /* open output file for writing, output file named out.yuv. If file open
+ * fails -> exit */
+ foutput = fopen("out.yuv", "wb");
+ if (foutput == NULL)
+ {
+ printf("UNABLE TO OPEN OUTPUT FILE\n");
+ return -1;
+ }
+
+ /* open input file for reading, file name given by user. If file open
+ * fails -> exit */
+ finput = fopen(argv[argc-1], "rb");
+ if (finput == NULL)
+ {
+ printf("UNABLE TO OPEN INPUT FILE\n");
+ return -1;
+ }
+
+ /* check size of the input file -> length of the stream in bytes */
+ fseek(finput, 0L, SEEK_END);
+ strmLen = (u32)ftell(finput);
+ rewind(finput);
+
+ /* allocate memory for stream buffer, exit if unsuccessful */
+ byteStrm = byteStrmStart = (u8 *)H264SwDecMalloc(sizeof(u8)*strmLen);
+ if (byteStrm == NULL)
+ {
+ printf("UNABLE TO ALLOCATE MEMORY\n");
+ return -1;
+ }
+
+ /* read input stream from file to buffer and close input file */
+ fread(byteStrm, sizeof(u8), strmLen, finput);
+ fclose(finput);
+
+ /* initialize decoder. If unsuccessful -> exit */
+ ret = H264SwDecInit(&decInst, 0);
+ if (ret != H264SWDEC_OK)
+ {
+ printf("DECODER INITIALIZATION FAILED\n");
+ return -1;
+ }
+
+ /* initialize H264SwDecDecode() input structure */
+ decInput.pStream = byteStrmStart;
+ decInput.dataLen = strmLen;
+ decInput.intraConcealmentMethod = 0;
+
+ picNumber = 0;
+
+ /* For performance measurements, read the start time (in seconds) here.
+ * The decoding time should be measured over several frames and after
+ * that average fps (frames/second) can be calculated.
+ *
+ * startTime = GetTime();
+ *
+ * To prevent calculating file I/O latensies as a decoding time,
+ * comment out WriteOutput function call. Also prints to stdout might
+ * consume considerable amount of cycles during measurement */
+
+ /* main decoding loop */
+ do
+ {
+ /* call API function to perform decoding */
+ ret = H264SwDecDecode(decInst, &decInput, &decOutput);
+
+ switch(ret)
+ {
+
+ case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY:
+
+ /* picture dimensions are available for query now */
+ ret = H264SwDecGetInfo(decInst, &decInfo);
+ if (ret != H264SWDEC_OK)
+ return -1;
+
+ /* picture size in pixels */
+ picSize = decInfo.picWidth * decInfo.picHeight;
+ /* memory needed for YCbCr 4:2:0 picture in bytes */
+ picSize = (3 * picSize)/2;
+ /* memory needed for 16-bit RGB picture in bytes
+ * picSize = (decInfo.picWidth * decInfo.picHeight) * 2; */
+
+ printf("Width %d Height %d\n",
+ decInfo.picWidth, decInfo.picHeight);
+
+ /* update H264SwDecDecode() input structure, number of bytes
+ * "consumed" is computed as difference between the new stream
+ * pointer and old stream pointer */
+ decInput.dataLen -=
+ (u32)(decOutput.pStrmCurrPos - decInput.pStream);
+ decInput.pStream = decOutput.pStrmCurrPos;
+ break;
+
+ case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY:
+ case H264SWDEC_PIC_RDY:
+
+ /* update H264SwDecDecode() input structure, number of bytes
+ * "consumed" is computed as difference between the new stream
+ * pointer and old stream pointer */
+ decInput.dataLen -=
+ (u32)(decOutput.pStrmCurrPos - decInput.pStream);
+ decInput.pStream = decOutput.pStrmCurrPos;
+
+ /* use function H264SwDecNextPicture() to obtain next picture
+ * in display order. Function is called until no more images
+ * are ready for display */
+ while (H264SwDecNextPicture(decInst, &decPicture, 0) ==
+ H264SWDEC_PIC_RDY) { picNumber++;
+
+ printf("PIC %d, type %s, concealed %d\n", picNumber,
+ decPicture.isIdrPicture ? "IDR" : "NON-IDR",
+ decPicture.nbrOfErrMBs);
+ fflush(stdout);
+
+ /* Do color conversion if needed to get display image
+ * in RGB-format
+ *
+ * YuvToRgb( decPicture.pOutputPicture, pRgbPicture ); */
+
+ /* write next display image to output file */
+ WriteOutput(foutput, (u8*)decPicture.pOutputPicture,
+ picSize);
+ }
+
+ break;
+
+ case H264SWDEC_EVALUATION_LIMIT_EXCEEDED:
+ /* evaluation version of the decoder has limited decoding
+ * capabilities */
+ printf("EVALUATION LIMIT REACHED\n");
+ goto end;
+
+ default:
+ printf("UNRECOVERABLE ERROR\n");
+ return -1;
+ }
+ /* keep decoding until all data from input stream buffer consumed */
+ } while (decInput.dataLen > 0);
+
+end:
+
+ /* if output in display order is preferred, the decoder shall be forced
+ * to output pictures remaining in decoded picture buffer. Use function
+ * H264SwDecNextPicture() to obtain next picture in display order. Function
+ * is called until no more images are ready for display. Second parameter
+ * for the function is set to '1' to indicate that this is end of the
+ * stream and all pictures shall be output */
+ while (H264SwDecNextPicture(decInst, &decPicture, 1) ==
+ H264SWDEC_PIC_RDY) {
+
+ picNumber++;
+
+ printf("PIC %d, type %s, concealed %d\n", picNumber,
+ decPicture.isIdrPicture ? "IDR" : "NON-IDR",
+ decPicture.nbrOfErrMBs);
+ fflush(stdout);
+
+ /* Do color conversion if needed to get display image
+ * in RGB-format
+ *
+ * YuvToRgb( decPicture.pOutputPicture, pRgbPicture ); */
+
+ /* write next display image to output file */
+ WriteOutput(foutput, (u8*)decPicture.pOutputPicture, picSize);
+ }
+
+ /* For performance measurements, read the end time (in seconds) here.
+ *
+ * endTime = GetTime();
+ *
+ * Now the performance can be calculated as frames per second:
+ * fps = picNumber / (endTime - startTime); */
+
+
+ /* release decoder instance */
+ H264SwDecRelease(decInst);
+
+ /* close output file */
+ fclose(foutput);
+
+ /* free byte stream buffer */
+ free(byteStrmStart);
+
+ return 0;
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: WriteOutput
+
+ Purpose:
+ Write picture pointed by data to file pointed by fid. Size of the
+ picture in pixels is indicated by picSize.
+
+------------------------------------------------------------------------------*/
+void WriteOutput(FILE *fid, u8 *data, u32 picSize)
+{
+ fwrite(data, 1, picSize, fid);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecTrace
+
+ Purpose:
+ Example implementation of H264SwDecTrace function. Prototype of this
+ function is given in H264SwDecApi.h. This implementation appends
+ trace messages to file named 'dec_api.trc'.
+
+------------------------------------------------------------------------------*/
+void H264SwDecTrace(char *string)
+{
+ FILE *fp;
+
+ fp = fopen("dec_api.trc", "at");
+
+ if (!fp)
+ return;
+
+ fwrite(string, 1, strlen(string), fp);
+ fwrite("\n", 1,1, fp);
+
+ fclose(fp);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecmalloc
+
+ Purpose:
+ Example implementation of H264SwDecMalloc function. Prototype of this
+ function is given in H264SwDecApi.h. This implementation uses
+ library function malloc for allocation of memory.
+
+------------------------------------------------------------------------------*/
+void* H264SwDecMalloc(u32 size)
+{
+ return malloc(size);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecFree
+
+ Purpose:
+ Example implementation of H264SwDecFree function. Prototype of this
+ function is given in H264SwDecApi.h. This implementation uses
+ library function free for freeing of memory.
+
+------------------------------------------------------------------------------*/
+void H264SwDecFree(void *ptr)
+{
+ free(ptr);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecMemcpy
+
+ Purpose:
+ Example implementation of H264SwDecMemcpy function. Prototype of this
+ function is given in H264SwDecApi.h. This implementation uses
+ library function memcpy to copy src to dest.
+
+------------------------------------------------------------------------------*/
+void H264SwDecMemcpy(void *dest, void *src, u32 count)
+{
+ memcpy(dest, src, count);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecMemset
+
+ Purpose:
+ Example implementation of H264SwDecMemset function. Prototype of this
+ function is given in H264SwDecApi.h. This implementation uses
+ library function memset to set content of memory area pointed by ptr.
+
+------------------------------------------------------------------------------*/
+void H264SwDecMemset(void *ptr, i32 value, u32 count)
+{
+ memset(ptr, value, count);
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
new file mode 100644
index 0000000..2bb4c4d
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/H264SwDecApi.c
@@ -0,0 +1,567 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ H264SwDecInit
+ H264SwDecGetInfo
+ H264SwDecRelease
+ H264SwDecDecode
+ H264SwDecGetAPIVersion
+ H264SwDecNextPicture
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+#include <stdlib.h>
+#include "basetype.h"
+#include "h264bsd_container.h"
+#include "H264SwDecApi.h"
+#include "h264bsd_decoder.h"
+#include "h264bsd_util.h"
+
+/*------------------------------------------------------------------------------
+ Version Information
+------------------------------------------------------------------------------*/
+
+#define H264SWDEC_MAJOR_VERSION 2
+#define H264SWDEC_MINOR_VERSION 3
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+H264DEC_TRACE Trace H264 Decoder API function calls.
+H264DEC_EVALUATION Compile evaluation version, restricts number of frames
+ that can be decoded
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+#ifdef H264DEC_TRACE
+#include <stdio.h>
+#define DEC_API_TRC(str) H264SwDecTrace(str)
+#else
+#define DEC_API_TRC(str)
+#endif
+
+#ifdef H264DEC_EVALUATION
+#define H264DEC_EVALUATION_LIMIT 500
+#endif
+
+void H264SwDecTrace(char *string) {
+}
+
+void* H264SwDecMalloc(u32 size) {
+ return malloc(size);
+}
+
+void H264SwDecFree(void *ptr) {
+ free(ptr);
+}
+
+void H264SwDecMemcpy(void *dest, void *src, u32 count) {
+ memcpy(dest, src, count);
+}
+
+void H264SwDecMemset(void *ptr, i32 value, u32 count) {
+ memset(ptr, value, count);
+}
+
+
+/*------------------------------------------------------------------------------
+
+ Function: H264SwDecInit()
+
+ Functional description:
+ Initialize decoder software. Function reserves memory for the
+ decoder instance and calls h264bsdInit to initialize the
+ instance data.
+
+ Inputs:
+ noOutputReordering flag to indicate decoder that it doesn't have
+ to try to provide output pictures in display
+ order, saves memory
+
+ Outputs:
+ decInst pointer to initialized instance is stored here
+
+ Returns:
+ H264SWDEC_OK successfully initialized the instance
+ H264SWDEC_INITFAIL initialization failed
+ H264SWDEC_PARAM_ERR invalid parameters
+ H264SWDEC_MEM_FAIL memory allocation failed
+
+------------------------------------------------------------------------------*/
+
+H264SwDecRet H264SwDecInit(H264SwDecInst *decInst, u32 noOutputReordering)
+{
+ u32 rv = 0;
+
+ decContainer_t *pDecCont;
+
+ DEC_API_TRC("H264SwDecInit#");
+
+ /* check that right shift on negative numbers is performed signed */
+ /*lint -save -e* following check causes multiple lint messages */
+ if ( ((-1)>>1) != (-1) )
+ {
+ DEC_API_TRC("H264SwDecInit# ERROR: Right shift is not signed");
+ return(H264SWDEC_INITFAIL);
+ }
+ /*lint -restore */
+
+ if (decInst == NULL)
+ {
+ DEC_API_TRC("H264SwDecInit# ERROR: decInst == NULL");
+ return(H264SWDEC_PARAM_ERR);
+ }
+
+ pDecCont = (decContainer_t *)H264SwDecMalloc(sizeof(decContainer_t));
+
+ if (pDecCont == NULL)
+ {
+ DEC_API_TRC("H264SwDecInit# ERROR: Memory allocation failed");
+ return(H264SWDEC_MEMFAIL);
+ }
+
+#ifdef H264DEC_TRACE
+ sprintf(pDecCont->str, "H264SwDecInit# decInst %p noOutputReordering %d",
+ (void*)decInst, noOutputReordering);
+ DEC_API_TRC(pDecCont->str);
+#endif
+
+ rv = h264bsdInit(&pDecCont->storage, noOutputReordering);
+ if (rv != HANTRO_OK)
+ {
+ H264SwDecRelease(pDecCont);
+ return(H264SWDEC_MEMFAIL);
+ }
+
+ pDecCont->decStat = INITIALIZED;
+ pDecCont->picNumber = 0;
+
+#ifdef H264DEC_TRACE
+ sprintf(pDecCont->str, "H264SwDecInit# OK: return %p", (void*)pDecCont);
+ DEC_API_TRC(pDecCont->str);
+#endif
+
+ *decInst = (decContainer_t *)pDecCont;
+
+ return(H264SWDEC_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: H264SwDecGetInfo()
+
+ Functional description:
+ This function provides read access to decoder information. This
+ function should not be called before H264SwDecDecode function has
+ indicated that headers are ready.
+
+ Inputs:
+ decInst decoder instance
+
+ Outputs:
+ pDecInfo pointer to info struct where data is written
+
+ Returns:
+ H264SWDEC_OK success
+ H264SWDEC_PARAM_ERR invalid parameters
+ H264SWDEC_HDRS_NOT_RDY information not available yet
+
+------------------------------------------------------------------------------*/
+
+H264SwDecRet H264SwDecGetInfo(H264SwDecInst decInst, H264SwDecInfo *pDecInfo)
+{
+
+ storage_t *pStorage;
+
+ DEC_API_TRC("H264SwDecGetInfo#");
+
+ if (decInst == NULL || pDecInfo == NULL)
+ {
+ DEC_API_TRC("H264SwDecGetInfo# ERROR: decInst or pDecInfo is NULL");
+ return(H264SWDEC_PARAM_ERR);
+ }
+
+ pStorage = &(((decContainer_t *)decInst)->storage);
+
+ if (pStorage->activeSps == NULL || pStorage->activePps == NULL)
+ {
+ DEC_API_TRC("H264SwDecGetInfo# ERROR: Headers not decoded yet");
+ return(H264SWDEC_HDRS_NOT_RDY);
+ }
+
+#ifdef H264DEC_TRACE
+ sprintf(((decContainer_t*)decInst)->str,
+ "H264SwDecGetInfo# decInst %p pDecInfo %p", decInst, (void*)pDecInfo);
+ DEC_API_TRC(((decContainer_t*)decInst)->str);
+#endif
+
+ /* h264bsdPicWidth and -Height return dimensions in macroblock units,
+ * picWidth and -Height in pixels */
+ pDecInfo->picWidth = h264bsdPicWidth(pStorage) << 4;
+ pDecInfo->picHeight = h264bsdPicHeight(pStorage) << 4;
+ pDecInfo->videoRange = h264bsdVideoRange(pStorage);
+ pDecInfo->matrixCoefficients = h264bsdMatrixCoefficients(pStorage);
+
+ h264bsdCroppingParams(pStorage,
+ &pDecInfo->croppingFlag,
+ &pDecInfo->cropParams.cropLeftOffset,
+ &pDecInfo->cropParams.cropOutWidth,
+ &pDecInfo->cropParams.cropTopOffset,
+ &pDecInfo->cropParams.cropOutHeight);
+
+ /* sample aspect ratio */
+ h264bsdSampleAspectRatio(pStorage,
+ &pDecInfo->parWidth,
+ &pDecInfo->parHeight);
+
+ /* profile */
+ pDecInfo->profile = h264bsdProfile(pStorage);
+
+ DEC_API_TRC("H264SwDecGetInfo# OK");
+
+ return(H264SWDEC_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: H264SwDecRelease()
+
+ Functional description:
+ Release the decoder instance. Function calls h264bsdShutDown to
+ release instance data and frees the memory allocated for the
+ instance.
+
+ Inputs:
+ decInst Decoder instance
+
+ Outputs:
+ none
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void H264SwDecRelease(H264SwDecInst decInst)
+{
+
+ decContainer_t *pDecCont;
+
+ DEC_API_TRC("H264SwDecRelease#");
+
+ if (decInst == NULL)
+ {
+ DEC_API_TRC("H264SwDecRelease# ERROR: decInst == NULL");
+ return;
+ }
+
+ pDecCont = (decContainer_t*)decInst;
+
+#ifdef H264DEC_TRACE
+ sprintf(pDecCont->str, "H264SwDecRelease# decInst %p",decInst);
+ DEC_API_TRC(pDecCont->str);
+#endif
+
+ h264bsdShutdown(&pDecCont->storage);
+
+ H264SwDecFree(pDecCont);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: H264SwDecDecode
+
+ Functional description:
+ Decode stream data. Calls h264bsdDecode to do the actual decoding.
+
+ Input:
+ decInst decoder instance
+ pInput pointer to input struct
+
+ Outputs:
+ pOutput pointer to output struct
+
+ Returns:
+ H264SWDEC_NOT_INITIALIZED decoder instance not initialized yet
+ H264SWDEC_PARAM_ERR invalid parameters
+
+ H264SWDEC_STRM_PROCESSED stream buffer decoded
+ H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY headers decoded,
+ stream buffer not finished
+ H264SWDEC_PIC_RDY decoding of a picture finished
+ H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY decoding of a picture finished,
+ stream buffer not finished
+ H264SWDEC_STRM_ERR serious error in decoding, no
+ valid parameter sets available
+ to decode picture data
+ H264SWDEC_EVALUATION_LIMIT_EXCEEDED this can only occur when
+ evaluation version is used,
+ max number of frames reached
+
+------------------------------------------------------------------------------*/
+
+H264SwDecRet H264SwDecDecode(H264SwDecInst decInst, H264SwDecInput *pInput,
+ H264SwDecOutput *pOutput)
+{
+
+ decContainer_t *pDecCont;
+ u32 strmLen;
+ u32 numReadBytes;
+ u8 *tmpStream;
+ u32 decResult = 0;
+ H264SwDecRet returnValue = H264SWDEC_STRM_PROCESSED;
+
+ DEC_API_TRC("H264SwDecDecode#");
+
+ /* Check that function input parameters are valid */
+ if (pInput == NULL || pOutput == NULL)
+ {
+ DEC_API_TRC("H264SwDecDecode# ERROR: pInput or pOutput is NULL");
+ return(H264SWDEC_PARAM_ERR);
+ }
+
+ if ((pInput->pStream == NULL) || (pInput->dataLen == 0))
+ {
+ DEC_API_TRC("H264SwDecDecode# ERROR: Invalid input parameters");
+ return(H264SWDEC_PARAM_ERR);
+ }
+
+ pDecCont = (decContainer_t *)decInst;
+
+ /* Check if decoder is in an incorrect mode */
+ if (decInst == NULL || pDecCont->decStat == UNINITIALIZED)
+ {
+ DEC_API_TRC("H264SwDecDecode# ERROR: Decoder not initialized");
+ return(H264SWDEC_NOT_INITIALIZED);
+ }
+
+#ifdef H264DEC_EVALUATION
+ if (pDecCont->picNumber >= H264DEC_EVALUATION_LIMIT)
+ return(H264SWDEC_EVALUATION_LIMIT_EXCEEDED);
+#endif
+
+#ifdef H264DEC_TRACE
+ sprintf(pDecCont->str, "H264SwDecDecode# decInst %p pInput %p pOutput %p",
+ decInst, (void*)pInput, (void*)pOutput);
+ DEC_API_TRC(pDecCont->str);
+#endif
+
+ pOutput->pStrmCurrPos = NULL;
+
+ numReadBytes = 0;
+ strmLen = pInput->dataLen;
+ tmpStream = pInput->pStream;
+ pDecCont->storage.intraConcealmentFlag = pInput->intraConcealmentMethod;
+
+ do
+ {
+ /* Return HDRS_RDY after DPB flush caused by new SPS */
+ if (pDecCont->decStat == NEW_HEADERS)
+ {
+ decResult = H264BSD_HDRS_RDY;
+ pDecCont->decStat = INITIALIZED;
+ }
+ else /* Continue decoding normally */
+ {
+ decResult = h264bsdDecode(&pDecCont->storage, tmpStream, strmLen,
+ pInput->picId, &numReadBytes);
+ }
+ tmpStream += numReadBytes;
+ /* check if too many bytes are read from stream */
+ if ( (i32)(strmLen - numReadBytes) >= 0 )
+ strmLen -= numReadBytes;
+ else
+ strmLen = 0;
+
+ pOutput->pStrmCurrPos = tmpStream;
+
+ switch (decResult)
+ {
+ case H264BSD_HDRS_RDY:
+
+ if(pDecCont->storage.dpb->flushed &&
+ pDecCont->storage.dpb->numOut !=
+ pDecCont->storage.dpb->outIndex)
+ {
+ /* output first all DPB stored pictures
+ * DPB flush caused by new SPS */
+ pDecCont->storage.dpb->flushed = 0;
+ pDecCont->decStat = NEW_HEADERS;
+ returnValue = H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY;
+ strmLen = 0;
+ }
+ else
+ {
+ returnValue = H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY;
+ strmLen = 0;
+ }
+ break;
+
+ case H264BSD_PIC_RDY:
+ pDecCont->picNumber++;
+
+ if (strmLen == 0)
+ returnValue = H264SWDEC_PIC_RDY;
+ else
+ returnValue = H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY;
+
+ strmLen = 0;
+ break;
+
+ case H264BSD_PARAM_SET_ERROR:
+ if ( !h264bsdCheckValidParamSets(&pDecCont->storage) &&
+ strmLen == 0 )
+ {
+ returnValue = H264SWDEC_STRM_ERR;
+ }
+ break;
+ case H264BSD_MEMALLOC_ERROR:
+ {
+ returnValue = H264SWDEC_MEMFAIL;
+ strmLen = 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ } while (strmLen);
+
+#ifdef H264DEC_TRACE
+ sprintf(pDecCont->str, "H264SwDecDecode# OK: DecResult %d",
+ returnValue);
+ DEC_API_TRC(pDecCont->str);
+#endif
+
+ return(returnValue);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: H264SwDecGetAPIVersion
+
+ Functional description:
+ Return version information of the API
+
+ Inputs:
+ none
+
+ Outputs:
+ none
+
+ Returns:
+ API version
+
+------------------------------------------------------------------------------*/
+
+H264SwDecApiVersion H264SwDecGetAPIVersion()
+{
+ H264SwDecApiVersion ver;
+
+ ver.major = H264SWDEC_MAJOR_VERSION;
+ ver.minor = H264SWDEC_MINOR_VERSION;
+
+ return(ver);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: H264SwDecNextPicture
+
+ Functional description:
+ Get next picture in display order if any available.
+
+ Input:
+ decInst decoder instance.
+ flushBuffer force output of all buffered pictures
+
+ Output:
+ pOutput pointer to output structure
+
+ Returns:
+ H264SWDEC_OK no pictures available for display
+ H264SWDEC_PIC_RDY picture available for display
+ H264SWDEC_PARAM_ERR invalid parameters
+
+------------------------------------------------------------------------------*/
+
+H264SwDecRet H264SwDecNextPicture(H264SwDecInst decInst,
+ H264SwDecPicture *pOutput, u32 flushBuffer)
+{
+
+ decContainer_t *pDecCont;
+ u32 numErrMbs, isIdrPic, picId;
+ u32 *pOutPic;
+
+ DEC_API_TRC("H264SwDecNextPicture#");
+
+ if (decInst == NULL || pOutput == NULL)
+ {
+ DEC_API_TRC("H264SwDecNextPicture# ERROR: decInst or pOutput is NULL");
+ return(H264SWDEC_PARAM_ERR);
+ }
+
+ pDecCont = (decContainer_t*)decInst;
+
+#ifdef H264DEC_TRACE
+ sprintf(pDecCont->str, "H264SwDecNextPicture# decInst %p pOutput %p %s %d",
+ decInst, (void*)pOutput, "flushBuffer", flushBuffer);
+ DEC_API_TRC(pDecCont->str);
+#endif
+
+ if (flushBuffer)
+ h264bsdFlushBuffer(&pDecCont->storage);
+
+ pOutPic = (u32*)h264bsdNextOutputPicture(&pDecCont->storage, &picId,
+ &isIdrPic, &numErrMbs);
+
+ if (pOutPic == NULL)
+ {
+ DEC_API_TRC("H264SwDecNextPicture# OK: return H264SWDEC_OK");
+ return(H264SWDEC_OK);
+ }
+ else
+ {
+ pOutput->pOutputPicture = pOutPic;
+ pOutput->picId = picId;
+ pOutput->isIdrPicture = isIdrPic;
+ pOutput->nbrOfErrMBs = numErrMbs;
+ DEC_API_TRC("H264SwDecNextPicture# OK: return H264SWDEC_PIC_RDY");
+ return(H264SWDEC_PIC_RDY);
+ }
+
+}
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c b/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c
new file mode 100755
index 0000000..42170d3
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c
@@ -0,0 +1,531 @@
+/*
+ * 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.
+ */
+
+/* CVS tag name for identification */
+const char tagName[256] = "$Name: FIRST_ANDROID_COPYRIGHT $";
+
+#include "H264SwDecApi.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DEBUG(argv) printf argv
+
+/* _NO_OUT disables output file writing */
+#ifdef __arm
+#define _NO_OUT
+#endif
+
+/*------------------------------------------------------------------------------
+
+------------------------------------------------------------------------------*/
+void WriteOutput(FILE *fid, u8 *data, u32 picSize);
+
+u32 CropPicture(u8 *pOutImage, u8 *pInImage,
+ u32 picWidth, u32 picHeight, CropParams *pCropParams);
+
+void CropWriteOutput(FILE *fid, u8 *imageData, u32 cropDisplay,
+ H264SwDecInfo *decInfo);
+
+typedef struct
+{
+ H264SwDecInst decInst;
+ H264SwDecInput decInput;
+ H264SwDecOutput decOutput;
+ H264SwDecPicture decPicture;
+ H264SwDecInfo decInfo;
+ FILE *foutput;
+ char outFileName[256];
+ u8 *byteStrmStart;
+ u32 picNumber;
+} Decoder;
+
+
+/*------------------------------------------------------------------------------
+
+------------------------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+
+ i32 instCount, instRunning;
+ i32 i;
+ u32 maxNumPics;
+ u32 strmLen;
+ H264SwDecRet ret;
+ u32 numErrors = 0;
+ u32 cropDisplay = 0;
+ u32 disableOutputReordering = 0;
+ FILE *finput;
+ Decoder **decoder;
+ char outFileName[256] = "out.yuv";
+
+
+ if ( argc > 1 && strcmp(argv[1], "-T") == 0 )
+ {
+ fprintf(stderr, "%s\n", tagName);
+ return 0;
+ }
+
+ if (argc < 2)
+ {
+ DEBUG((
+ "Usage: %s [-Nn] [-Ooutfile] [-P] [-U] [-C] [-R] [-T] file1.264 [file2.264] .. [fileN.264]\n",
+ argv[0]));
+ DEBUG(("\t-Nn forces decoding to stop after n pictures\n"));
+#if defined(_NO_OUT)
+ DEBUG(("\t-Ooutfile output writing disabled at compile time\n"));
+#else
+ DEBUG(("\t-Ooutfile write output to \"outfile\" (default out.yuv)\n"));
+ DEBUG(("\t-Onone does not write output\n"));
+#endif
+ DEBUG(("\t-C display cropped image (default decoded image)\n"));
+ DEBUG(("\t-R disable DPB output reordering\n"));
+ DEBUG(("\t-T to print tag name and exit\n"));
+ exit(100);
+ }
+
+ instCount = argc - 1;
+
+ /* read command line arguments */
+ maxNumPics = 0;
+ for (i = 1; i < (argc-1); i++)
+ {
+ if ( strncmp(argv[i], "-N", 2) == 0 )
+ {
+ maxNumPics = (u32)atoi(argv[i]+2);
+ instCount--;
+ }
+ else if ( strncmp(argv[i], "-O", 2) == 0 )
+ {
+ strcpy(outFileName, argv[i]+2);
+ instCount--;
+ }
+ else if ( strcmp(argv[i], "-C") == 0 )
+ {
+ cropDisplay = 1;
+ instCount--;
+ }
+ else if ( strcmp(argv[i], "-R") == 0 )
+ {
+ disableOutputReordering = 1;
+ instCount--;
+ }
+ }
+
+ if (instCount < 1)
+ {
+ DEBUG(("No input files\n"));
+ exit(100);
+ }
+
+ /* allocate memory for multiple decoder instances
+ * one instance for every stream file */
+ decoder = (Decoder **)malloc(sizeof(Decoder*)*(u32)instCount);
+ if (decoder == NULL)
+ {
+ DEBUG(("Unable to allocate memory\n"));
+ exit(100);
+ }
+
+ /* prepare each decoder instance */
+ for (i = 0; i < instCount; i++)
+ {
+ decoder[i] = (Decoder *)calloc(1, sizeof(Decoder));
+
+ /* open input file */
+ finput = fopen(argv[argc-instCount+i],"rb");
+ if (finput == NULL)
+ {
+ DEBUG(("Unable to open input file <%s>\n", argv[argc-instCount+i]));
+ exit(100);
+ }
+
+ DEBUG(("Reading input file[%d] %s\n", i, argv[argc-instCount+i]));
+
+ /* read input stream to buffer */
+ fseek(finput,0L,SEEK_END);
+ strmLen = (u32)ftell(finput);
+ rewind(finput);
+ decoder[i]->byteStrmStart = (u8 *)malloc(sizeof(u8)*strmLen);
+ if (decoder[i]->byteStrmStart == NULL)
+ {
+ DEBUG(("Unable to allocate memory\n"));
+ exit(100);
+ }
+ fread(decoder[i]->byteStrmStart, sizeof(u8), strmLen, finput);
+ fclose(finput);
+
+ /* open output file */
+ if (strcmp(outFileName, "none") != 0)
+ {
+#if defined(_NO_OUT)
+ decoder[i]->foutput = NULL;
+#else
+ sprintf(decoder[i]->outFileName, "%s%i", outFileName, i);
+ decoder[i]->foutput = fopen(decoder[i]->outFileName, "wb");
+ if (decoder[i]->foutput == NULL)
+ {
+ DEBUG(("Unable to open output file\n"));
+ exit(100);
+ }
+#endif
+ }
+
+ ret = H264SwDecInit(&(decoder[i]->decInst), disableOutputReordering);
+
+ if (ret != H264SWDEC_OK)
+ {
+ DEBUG(("Init failed %d\n", ret));
+ exit(100);
+ }
+
+ decoder[i]->decInput.pStream = decoder[i]->byteStrmStart;
+ decoder[i]->decInput.dataLen = strmLen;
+ decoder[i]->decInput.intraConcealmentMethod = 0;
+
+ }
+
+ /* main decoding loop */
+ do
+ {
+ /* decode once using each instance */
+ for (i = 0; i < instCount; i++)
+ {
+ ret = H264SwDecDecode(decoder[i]->decInst,
+ &(decoder[i]->decInput),
+ &(decoder[i]->decOutput));
+
+ switch(ret)
+ {
+
+ case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY:
+
+ ret = H264SwDecGetInfo(decoder[i]->decInst,
+ &(decoder[i]->decInfo));
+ if (ret != H264SWDEC_OK)
+ exit(1);
+
+ if (cropDisplay && decoder[i]->decInfo.croppingFlag)
+ {
+ DEBUG(("Decoder[%d] Cropping params: (%d, %d) %dx%d\n",
+ i,
+ decoder[i]->decInfo.cropParams.cropLeftOffset,
+ decoder[i]->decInfo.cropParams.cropTopOffset,
+ decoder[i]->decInfo.cropParams.cropOutWidth,
+ decoder[i]->decInfo.cropParams.cropOutHeight));
+ }
+
+ DEBUG(("Decoder[%d] Width %d Height %d\n", i,
+ decoder[i]->decInfo.picWidth,
+ decoder[i]->decInfo.picHeight));
+
+ DEBUG(("Decoder[%d] videoRange %d, matricCoefficients %d\n",
+ i, decoder[i]->decInfo.videoRange,
+ decoder[i]->decInfo.matrixCoefficients));
+ decoder[i]->decInput.dataLen -=
+ (u32)(decoder[i]->decOutput.pStrmCurrPos -
+ decoder[i]->decInput.pStream);
+ decoder[i]->decInput.pStream =
+ decoder[i]->decOutput.pStrmCurrPos;
+ break;
+
+ case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY:
+ decoder[i]->decInput.dataLen -=
+ (u32)(decoder[i]->decOutput.pStrmCurrPos -
+ decoder[i]->decInput.pStream);
+ decoder[i]->decInput.pStream =
+ decoder[i]->decOutput.pStrmCurrPos;
+ /* fall through */
+ case H264SWDEC_PIC_RDY:
+ if (ret == H264SWDEC_PIC_RDY)
+ decoder[i]->decInput.dataLen = 0;
+
+ ret = H264SwDecGetInfo(decoder[i]->decInst,
+ &(decoder[i]->decInfo));
+ if (ret != H264SWDEC_OK)
+ exit(1);
+
+ while (H264SwDecNextPicture(decoder[i]->decInst,
+ &(decoder[i]->decPicture), 0) == H264SWDEC_PIC_RDY)
+ {
+ decoder[i]->picNumber++;
+
+ numErrors += decoder[i]->decPicture.nbrOfErrMBs;
+
+ DEBUG(("Decoder[%d] PIC %d, type %s, concealed %d\n",
+ i, decoder[i]->picNumber,
+ decoder[i]->decPicture.isIdrPicture
+ ? "IDR" : "NON-IDR",
+ decoder[i]->decPicture.nbrOfErrMBs));
+ fflush(stdout);
+
+ CropWriteOutput(decoder[i]->foutput,
+ (u8*)decoder[i]->decPicture.pOutputPicture,
+ cropDisplay, &(decoder[i]->decInfo));
+ }
+
+ if (maxNumPics && decoder[i]->picNumber == maxNumPics)
+ decoder[i]->decInput.dataLen = 0;
+ break;
+
+ case H264SWDEC_STRM_PROCESSED:
+ case H264SWDEC_STRM_ERR:
+ case H264SWDEC_PARAM_ERR:
+ decoder[i]->decInput.dataLen = 0;
+ break;
+
+ default:
+ DEBUG(("Decoder[%d] FATAL ERROR\n", i));
+ exit(10);
+ break;
+
+ }
+ }
+
+ /* check if any of the instances is still running (=has more data) */
+ instRunning = instCount;
+ for (i = 0; i < instCount; i++)
+ {
+ if (decoder[i]->decInput.dataLen == 0)
+ instRunning--;
+ }
+
+ } while (instRunning);
+
+
+ /* get last frames and close each instance */
+ for (i = 0; i < instCount; i++)
+ {
+ while (H264SwDecNextPicture(decoder[i]->decInst,
+ &(decoder[i]->decPicture), 1) == H264SWDEC_PIC_RDY)
+ {
+ decoder[i]->picNumber++;
+
+ DEBUG(("Decoder[%d] PIC %d, type %s, concealed %d\n",
+ i, decoder[i]->picNumber,
+ decoder[i]->decPicture.isIdrPicture
+ ? "IDR" : "NON-IDR",
+ decoder[i]->decPicture.nbrOfErrMBs));
+ fflush(stdout);
+
+ CropWriteOutput(decoder[i]->foutput,
+ (u8*)decoder[i]->decPicture.pOutputPicture,
+ cropDisplay, &(decoder[i]->decInfo));
+ }
+
+ H264SwDecRelease(decoder[i]->decInst);
+
+ if (decoder[i]->foutput)
+ fclose(decoder[i]->foutput);
+
+ free(decoder[i]->byteStrmStart);
+
+ free(decoder[i]);
+ }
+
+ free(decoder);
+
+ if (numErrors)
+ return 1;
+ else
+ return 0;
+
+}
+
+/*------------------------------------------------------------------------------
+
+------------------------------------------------------------------------------*/
+void CropWriteOutput(FILE *foutput, u8 *imageData, u32 cropDisplay,
+ H264SwDecInfo *decInfo)
+{
+ u8 *tmpImage = NULL;
+ u32 tmp, picSize;
+
+ if (cropDisplay && decInfo->croppingFlag)
+ {
+ picSize = decInfo->cropParams.cropOutWidth *
+ decInfo->cropParams.cropOutHeight;
+ picSize = (3 * picSize)/2;
+ tmpImage = malloc(picSize);
+ if (tmpImage == NULL)
+ exit(1);
+ tmp = CropPicture(tmpImage, imageData,
+ decInfo->picWidth, decInfo->picHeight,
+ &(decInfo->cropParams));
+ if (tmp)
+ exit(1);
+ WriteOutput(foutput, tmpImage, picSize);
+ free(tmpImage);
+ }
+ else
+ {
+ picSize = decInfo->picWidth * decInfo->picHeight;
+ picSize = (3 * picSize)/2;
+ WriteOutput(foutput, imageData, picSize);
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+------------------------------------------------------------------------------*/
+void WriteOutput(FILE *fid, u8 *data, u32 picSize)
+{
+ if (fid)
+ fwrite(data, 1, picSize, fid);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecTrace
+
+------------------------------------------------------------------------------*/
+void H264SwDecTrace(char *string)
+{
+ FILE *fp;
+
+ fp = fopen("dec_api.trc", "at");
+
+ if (!fp)
+ return;
+
+ fwrite(string, 1, strlen(string), fp);
+ fwrite("\n", 1,1, fp);
+
+ fclose(fp);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecmalloc
+
+------------------------------------------------------------------------------*/
+void* H264SwDecMalloc(u32 size)
+{
+ return malloc(size);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecFree
+
+------------------------------------------------------------------------------*/
+void H264SwDecFree(void *ptr)
+{
+ free(ptr);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecMemcpy
+
+------------------------------------------------------------------------------*/
+void H264SwDecMemcpy(void *dest, void *src, u32 count)
+{
+ memcpy(dest, src, count);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecMemset
+
+------------------------------------------------------------------------------*/
+void H264SwDecMemset(void *ptr, i32 value, u32 count)
+{
+ memset(ptr, value, count);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: CropPicture
+
+------------------------------------------------------------------------------*/
+u32 CropPicture(u8 *pOutImage, u8 *pInImage,
+ u32 picWidth, u32 picHeight, CropParams *pCropParams)
+{
+
+ u32 i, j;
+ u32 outWidth, outHeight;
+ u8 *pOut, *pIn;
+
+ if (pOutImage == NULL || pInImage == NULL || pCropParams == NULL ||
+ !picWidth || !picHeight)
+ {
+ /* due to lint warning */
+ free(pOutImage);
+ return(1);
+ }
+
+ if ( ((pCropParams->cropLeftOffset + pCropParams->cropOutWidth) >
+ picWidth ) ||
+ ((pCropParams->cropTopOffset + pCropParams->cropOutHeight) >
+ picHeight ) )
+ {
+ /* due to lint warning */
+ free(pOutImage);
+ return(1);
+ }
+
+ outWidth = pCropParams->cropOutWidth;
+ outHeight = pCropParams->cropOutHeight;
+
+ pIn = pInImage + pCropParams->cropTopOffset*picWidth +
+ pCropParams->cropLeftOffset;
+ pOut = pOutImage;
+
+ /* luma */
+ for (i = outHeight; i; i--)
+ {
+ for (j = outWidth; j; j--)
+ {
+ *pOut++ = *pIn++;
+ }
+ pIn += picWidth - outWidth;
+ }
+
+ outWidth >>= 1;
+ outHeight >>= 1;
+
+ pIn = pInImage + picWidth*picHeight +
+ pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2;
+
+ /* cb */
+ for (i = outHeight; i; i--)
+ {
+ for (j = outWidth; j; j--)
+ {
+ *pOut++ = *pIn++;
+ }
+ pIn += picWidth/2 - outWidth;
+ }
+
+ pIn = pInImage + 5*picWidth*picHeight/4 +
+ pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2;
+
+ /* cr */
+ for (i = outHeight; i; i--)
+ {
+ for (j = outWidth; j; j--)
+ {
+ *pOut++ = *pIn++;
+ }
+ pIn += picWidth/2 - outWidth;
+ }
+
+ return (0);
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor.s
new file mode 100755
index 0000000..634a484
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor.s
@@ -0,0 +1,298 @@
+; 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.
+
+;-------------------------------------------------------------------------------
+;--
+;-- Abstract : ARMv6 optimized version of h264bsdInterpolateChromaHor function
+;--
+;-------------------------------------------------------------------------------
+
+
+ IF :DEF: H264DEC_WINASM
+ ;// We dont use REQUIRE8 and PRESERVE8 for winasm
+ ELSE
+ REQUIRE8
+ PRESERVE8
+ ENDIF
+
+ AREA |.text|, CODE
+
+
+;// h264bsdInterpolateChromaHor register allocation
+
+ref RN 0
+ptrA RN 0
+
+mb RN 1
+block RN 1
+
+x0 RN 2
+count RN 2
+
+y0 RN 3
+valX RN 3
+
+width RN 4
+
+height RN 5
+tmp7 RN 5
+
+chrPW RN 6
+tmp8 RN 6
+
+tmp1 RN 7
+chrPH RN 7
+
+tmp2 RN 8
+
+tmp3 RN 9
+
+tmp4 RN 10
+
+tmp5 RN 11
+
+tmp6 RN 12
+
+c32 RN 14
+xFrac RN 14
+
+;// Function exports and imports
+
+ IMPORT h264bsdFillBlock
+
+ EXPORT h264bsdInterpolateChromaHor
+
+;// Function arguments
+;//
+;// u8 *ref, : 0xc4
+;// u8 *predPartChroma, : 0xc8
+;// i32 x0, : 0xcc
+;// i32 y0, : 0xd0
+;// u32 width, : 0xf8
+;// u32 height, : 0xfc
+;// u32 xFrac, : 0x100
+;// u32 chromaPartWidth, : 0x104
+;// u32 chromaPartHeight : 0x108
+
+h264bsdInterpolateChromaHor
+ STMFD sp!, {r0-r11,lr}
+ SUB sp, sp, #0xc4
+
+ LDR chrPW, [sp, #0x104] ;// chromaPartWidth
+ LDR width, [sp, #0xf8] ;// width
+ CMP x0, #0
+ BLT do_fill
+
+ ADD tmp6, x0, chrPW ;// tmp6 = x0+ chromaPartWidth
+ ADD tmp6, tmp6, #1 ;// tmp6 = x0 + chromaPartWidth + 1
+ CMP tmp6, width ;// x0+chromaPartWidth+1 > width
+ BHI do_fill
+
+ CMP y0, #0
+ BLT do_fill
+ LDR chrPH, [sp, #0x108] ;// chromaPartHeight
+ LDR height, [sp, #0xfc] ;// height
+ ADD tmp6, y0, chrPH ;// tmp6 = y0 + chromaPartHeight
+ CMP tmp6, height
+ BLS skip_fill
+
+do_fill
+ LDR chrPH, [sp, #0x108] ;// chromaPartHeight
+ LDR height, [sp, #0xfc] ;// height
+ ADD tmp8, chrPW, #1 ;// tmp8 = chromaPartWidth+1
+ MOV tmp2, tmp8 ;// tmp2 = chromaPartWidth+1
+ STMIA sp,{width,height,tmp8,chrPH,tmp2}
+ ADD block, sp, #0x1c ;// block
+ BL h264bsdFillBlock
+
+ LDR x0, [sp, #0xcc]
+ LDR y0, [sp, #0xd0]
+ LDR ref, [sp, #0xc4] ;// ref
+ STMIA sp,{width,height,tmp8,chrPH,tmp2}
+ ADD block, sp, #0x1c ;// block
+ MLA ref, height, width, ref ;// ref += width * height;
+ MLA block, chrPH, tmp8, block;// block + (chromaPH)*(chromaPW+1)
+ BL h264bsdFillBlock
+
+ MOV x0, #0 ;// x0 = 0
+ MOV y0, #0 ;// y0 = 0
+ STR x0, [sp, #0xcc]
+ STR y0, [sp, #0xd0]
+ ADD ref, sp, #0x1c ;// ref = block
+ STR ref, [sp, #0xc4] ;// ref
+
+ STR chrPH, [sp, #0xfc] ;// height
+ STR tmp8, [sp, #0xf8] ;// width
+ MOV width, tmp8
+ SUB chrPW, chrPW, #1
+
+skip_fill
+ MLA tmp3, y0, width, x0 ;// tmp3 = y0*width+x0
+ LDR xFrac, [sp, #0x100] ;// xFrac
+ ADD ptrA, ref, tmp3 ;// ptrA = ref + y0*width+x0
+ RSB valX, xFrac, #8 ;// valX = 8-xFrac
+
+ LDR mb, [sp, #0xc8] ;// predPartChroma
+
+
+ ;// pack values to count register
+ ;// [31:28] loop_x (chromaPartWidth-1)
+ ;// [27:24] loop_y (chromaPartHeight-1)
+ ;// [23:20] chromaPartWidth-1
+ ;// [19:16] chromaPartHeight-1
+ ;// [15:00] nothing
+
+ SUB tmp2, chrPH, #1 ;// chromaPartHeight-1
+ SUB tmp1, chrPW, #1 ;// chromaPartWidth-1
+ ADD count, count, tmp2, LSL #16 ;// chromaPartHeight-1
+ ADD count, count, tmp2, LSL #24 ;// loop_y
+ ADD count, count, tmp1, LSL #20 ;// chromaPartWidth-1
+ AND tmp2, count, #0x00F00000 ;// loop_x
+ PKHBT valX, valX, xFrac, LSL #16 ;// |xFrac|valX |
+ MOV valX, valX, LSL #3 ;// multiply by 8 in advance
+ MOV c32, #32
+
+
+ ;///////////////////////////////////////////////////////////////////////////
+ ;// Cb
+ ;///////////////////////////////////////////////////////////////////////////
+
+ ;// 2x2 pels per iteration
+ ;// bilinear vertical interpolation
+
+loop1_y
+ ADD count, count, tmp2, LSL #8
+ LDRB tmp1, [ptrA, width]
+ LDRB tmp2, [ptrA], #1
+
+loop1_x
+ LDRB tmp3, [ptrA, width]
+ LDRB tmp4, [ptrA], #1
+
+ PKHBT tmp5, tmp1, tmp3, LSL #16
+ PKHBT tmp6, tmp2, tmp4, LSL #16
+
+ LDRB tmp1, [ptrA, width]
+ LDRB tmp2, [ptrA], #1
+
+ SMLAD tmp5, tmp5, valX, c32 ;// multiply
+ SMLAD tmp6, tmp6, valX, c32 ;// multiply
+
+ PKHBT tmp7, tmp3, tmp1, LSL #16
+ PKHBT tmp8, tmp4, tmp2, LSL #16
+
+ SMLAD tmp7, tmp7, valX, c32 ;// multiply
+ SMLAD tmp8, tmp8, valX, c32 ;// multiply
+
+ MOV tmp5, tmp5, LSR #6 ;// scale down
+ STRB tmp5, [mb,#8] ;// store row 2 col 1
+
+ MOV tmp6, tmp6, LSR #6 ;// scale down
+ STRB tmp6, [mb],#1 ;// store row 1 col 1
+
+ MOV tmp7, tmp7, LSR #6 ;// scale down
+ STRB tmp7, [mb,#8] ;// store row 2 col 2
+
+ MOV tmp8, tmp8, LSR #6 ;// scale down
+ STRB tmp8, [mb],#1 ;// store row 1 col 2
+
+ SUBS count, count, #2<<28
+ BCS loop1_x
+
+ AND tmp2, count, #0x00F00000
+
+ ADDS mb, mb, #16
+ SBC mb, mb, tmp2, LSR #20
+ ADD ptrA, ptrA, width, LSL #1
+ SBC ptrA, ptrA, tmp2, LSR #20
+ SUB ptrA, ptrA, #1
+
+ ADDS count, count, #0xE << 24
+ BGE loop1_y
+
+ ;///////////////////////////////////////////////////////////////////////////
+ ;// Cr
+ ;///////////////////////////////////////////////////////////////////////////
+ LDR height, [sp,#0xfc] ;// height
+ LDR ref, [sp, #0xc4] ;// ref
+ LDR tmp1, [sp, #0xd0] ;// y0
+ LDR tmp2, [sp, #0xcc] ;// x0
+ LDR mb, [sp, #0xc8] ;// predPartChroma
+
+ ADD tmp1, height, tmp1
+ MLA tmp3, tmp1, width, tmp2
+ ADD ptrA, ref, tmp3
+ ADD mb, mb, #64
+
+ AND count, count, #0x00FFFFFF
+ AND tmp1, count, #0x000F0000
+ ADD count, count, tmp1, LSL #8
+ AND tmp2, count, #0x00F00000
+
+ ;// 2x2 pels per iteration
+ ;// bilinear vertical interpolation
+loop2_y
+ ADD count, count, tmp2, LSL #8
+ LDRB tmp1, [ptrA, width]
+ LDRB tmp2, [ptrA], #1
+
+loop2_x
+ LDRB tmp3, [ptrA, width]
+ LDRB tmp4, [ptrA], #1
+
+ PKHBT tmp5, tmp1, tmp3, LSL #16
+ PKHBT tmp6, tmp2, tmp4, LSL #16
+
+ LDRB tmp1, [ptrA, width]
+ LDRB tmp2, [ptrA], #1
+
+ SMLAD tmp5, tmp5, valX, c32 ;// multiply
+ SMLAD tmp6, tmp6, valX, c32 ;// multiply
+
+ PKHBT tmp7, tmp3, tmp1, LSL #16
+ PKHBT tmp8, tmp4, tmp2, LSL #16
+
+ SMLAD tmp7, tmp7, valX, c32 ;// multiply
+ SMLAD tmp8, tmp8, valX, c32 ;// multiply
+
+ MOV tmp5, tmp5, LSR #6 ;// scale down
+ STRB tmp5, [mb,#8] ;// store row 2 col 1
+
+ MOV tmp6, tmp6, LSR #6 ;// scale down
+ STRB tmp6, [mb],#1 ;// store row 1 col 1
+
+ MOV tmp7, tmp7, LSR #6 ;// scale down
+ STRB tmp7, [mb,#8] ;// store row 2 col 2
+
+ MOV tmp8, tmp8, LSR #6 ;// scale down
+ STRB tmp8, [mb],#1 ;// store row 1 col 2
+
+ SUBS count, count, #2<<28
+ BCS loop2_x
+
+ AND tmp2, count, #0x00F00000
+
+ ADDS mb, mb, #16
+ SBC mb, mb, tmp2, LSR #20
+ ADD ptrA, ptrA, width, LSL #1
+ SBC ptrA, ptrA, tmp2, LSR #20
+ SUB ptrA, ptrA, #1
+
+ ADDS count, count, #0xE << 24
+ BGE loop2_y
+
+ ADD sp,sp,#0xd4
+ LDMFD sp!, {r4-r11,pc}
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor_ver.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor_ver.s
new file mode 100755
index 0000000..7420ad3
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_hor_ver.s
@@ -0,0 +1,339 @@
+; 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.
+
+;-------------------------------------------------------------------------------
+;--
+;-- Abstract : ARMv6 optimized version of h264bsdInterpolateChromaHorVer
+;-- function
+;--
+;-------------------------------------------------------------------------------
+
+
+ IF :DEF: H264DEC_WINASM
+ ;// We dont use REQUIRE8 and PRESERVE8 for winasm
+ ELSE
+ REQUIRE8
+ PRESERVE8
+ ENDIF
+
+ AREA |.text|, CODE
+
+
+;// h264bsdInterpolateChromaHorVer register allocation
+
+ref RN 0
+ptrA RN 0
+
+mb RN 1
+block RN 1
+
+x0 RN 2
+count RN 2
+
+y0 RN 3
+valY RN 3
+
+width RN 4
+
+tmp4 RN 5
+height RN 5
+
+tmp1 RN 6
+
+tmp2 RN 7
+
+tmp3 RN 8
+
+valX RN 9
+
+tmp5 RN 10
+chrPW RN 10
+
+tmp6 RN 11
+chrPH RN 11
+
+xFrac RN 12
+
+c32 RN 14
+yFrac RN 14
+
+;// function exports and imports
+
+ IMPORT h264bsdFillBlock
+
+ EXPORT h264bsdInterpolateChromaHorVer
+
+;// Function arguments
+;//
+;// u8 *ref, : 0xc4
+;// u8 *predPartChroma, : 0xc8
+;// i32 x0, : 0xcc
+;// i32 y0, : 0xd0
+;// u32 width, : 0xf8
+;// u32 height, : 0xfc
+;// u32 xFrac, : 0x100
+;// u32 yFrac, : 0x104
+;// u32 chromaPartWidth, : 0x108
+;// u32 chromaPartHeight : 0x10c
+
+h264bsdInterpolateChromaHorVer
+ STMFD sp!, {r0-r11,lr}
+ SUB sp, sp, #0xc4
+
+ LDR chrPW, [sp, #0x108] ;// chromaPartWidth
+ LDR xFrac, [sp, #0x100] ;// xFrac
+ LDR width, [sp, #0xf8] ;// width
+ CMP x0, #0
+ BLT do_fill
+
+ ADD tmp1, x0, chrPW ;// tmp1 = x0+ chromaPartWidth
+ ADD tmp1, tmp1, #1 ;// tmp1 = x0+ chromaPartWidth+1
+ CMP tmp1, width ;// x0+chromaPartWidth+1 > width
+ BHI do_fill
+
+ CMP y0, #0
+ BLT do_fill
+ LDR chrPH, [sp, #0x10c] ;// chromaPartHeight
+ LDR height, [sp, #0xfc] ;// height
+ ADD tmp1, y0, chrPH ;// tmp1 = y0 + chromaPartHeight
+ ADD tmp1, tmp1, #1 ;// tmp1 = y0 + chromaPartHeight + 1
+ CMP tmp1, height
+ BLS skip_fill
+
+do_fill
+ LDR chrPH, [sp, #0x10c] ;// chromaPartHeight
+ LDR height, [sp, #0xfc] ;// height
+ ADD tmp3, chrPW, #1 ;// tmp3 = chromaPartWidth+1
+ ADD tmp1, chrPW, #1 ;// tmp1 = chromaPartWidth+1
+ ADD tmp2, chrPH, #1 ;// tmp2 = chromaPartHeight+1
+ STMIA sp,{width,height,tmp1,tmp2,tmp3}
+ ADD block, sp, #0x1c ;// block
+ BL h264bsdFillBlock
+
+ LDR x0, [sp, #0xcc]
+ LDR y0, [sp, #0xd0]
+ LDR ref, [sp, #0xc4] ;// ref
+ STMIA sp,{width,height,tmp1,tmp2,tmp3}
+ ADD block, sp, #0x1c ;// block
+ MLA ref, height, width, ref ;// ref += width * height;
+ MLA block, tmp2, tmp1, block;// block + (chromaPW+1)*(chromaPH+1)
+ BL h264bsdFillBlock
+
+ MOV x0, #0 ;// x0 = 0
+ MOV y0, #0 ;// y0 = 0
+ STR x0, [sp, #0xcc]
+ STR y0, [sp, #0xd0]
+ ADD ref, sp, #0x1c ;// ref = block
+ STR ref, [sp, #0xc4] ;// ref
+
+ STR tmp2, [sp, #0xfc] ;// height
+ STR tmp1, [sp, #0xf8] ;// width
+ MOV width, tmp1
+
+skip_fill
+ MLA tmp3, y0, width, x0 ;// tmp3 = y0*width+x0
+ LDR yFrac, [sp, #0x104] ;// yFrac
+ LDR xFrac, [sp, #0x100]
+ ADD ptrA, ref, tmp3 ;// ptrA = ref + y0*width+x0
+ RSB valX, xFrac, #8 ;// valX = 8-xFrac
+ RSB valY, yFrac, #8 ;// valY = 8-yFrac
+
+ LDR mb, [sp, #0xc8] ;// predPartChroma
+
+
+ ;// pack values to count register
+ ;// [31:28] loop_x (chromaPartWidth-1)
+ ;// [27:24] loop_y (chromaPartHeight-1)
+ ;// [23:20] chromaPartWidth-1
+ ;// [19:16] chromaPartHeight-1
+ ;// [15:00] nothing
+
+ SUB tmp2, chrPH, #1 ;// chromaPartHeight-1
+ SUB tmp1, chrPW, #1 ;// chromaPartWidth-1
+ ADD count, count, tmp2, LSL #16 ;// chromaPartHeight-1
+ ADD count, count, tmp2, LSL #24 ;// loop_y
+ ADD count, count, tmp1, LSL #20 ;// chromaPartWidth-1
+ AND tmp2, count, #0x00F00000 ;// loop_x
+ PKHBT valY, valY, yFrac, LSL #16 ;// |yFrac|valY |
+ MOV c32, #32
+
+
+ ;///////////////////////////////////////////////////////////////////////////
+ ;// Cb
+ ;///////////////////////////////////////////////////////////////////////////
+
+ ;// 2x2 pels per iteration
+ ;// bilinear vertical and horizontal interpolation
+
+loop1_y
+ LDRB tmp1, [ptrA]
+ LDRB tmp3, [ptrA, width]
+ LDRB tmp5, [ptrA, width, LSL #1]
+
+ PKHBT tmp1, tmp1, tmp3, LSL #16 ;// |t3|t1|
+ PKHBT tmp3, tmp3, tmp5, LSL #16 ;// |t5|t3|
+
+ SMUAD tmp1, tmp1, valY ;// t1=(t1*valY + t3*yFrac)
+ SMUAD tmp3, tmp3, valY ;// t3=(t3*valY + t5*yFrac)
+
+ ADD count, count, tmp2, LSL #8
+loop1_x
+ ;// first
+ LDRB tmp2, [ptrA, #1]!
+ LDRB tmp4, [ptrA, width]
+ LDRB tmp6, [ptrA, width, LSL #1]
+
+ PKHBT tmp2, tmp2, tmp4, LSL #16 ;// |t4|t2|
+ PKHBT tmp4, tmp4, tmp6, LSL #16 ;// |t6|t4|
+
+ SMUAD tmp2, tmp2, valY ;// t2=(t2*valY + t4*yFrac)
+ MLA tmp5, tmp1, valX, c32 ;// t5=t1*valX+32
+ MLA tmp5, tmp2, xFrac, tmp5 ;// t5=t2*xFrac+t5
+
+ SMUAD tmp4, tmp4, valY ;// t4=(t4*valY + t6*yFrac)
+ MLA tmp6, tmp3, valX, c32 ;// t3=t3*valX+32
+ MLA tmp6, tmp4, xFrac, tmp6 ;// t6=t4*xFrac+t6
+
+ MOV tmp6, tmp6, LSR #6 ;// scale down
+ STRB tmp6, [mb, #8] ;// store pixel
+ MOV tmp5, tmp5, LSR #6 ;// scale down
+ STRB tmp5, [mb], #1 ;// store pixel
+
+ ;// second
+ LDRB tmp1, [ptrA, #1]!
+ LDRB tmp3, [ptrA, width]
+ LDRB tmp5, [ptrA, width, LSL #1]
+
+ PKHBT tmp1, tmp1, tmp3, LSL #16 ;// |t3|t1|
+ PKHBT tmp3, tmp3, tmp5, LSL #16 ;// |t5|t3|
+
+ SMUAD tmp1, tmp1, valY ;// t1=(t1*valY + t3*yFrac)
+ MLA tmp5, tmp1, xFrac, c32 ;// t1=t1*xFrac+32
+ MLA tmp5, tmp2, valX, tmp5 ;// t5=t2*valX+t5
+
+ SMUAD tmp3, tmp3, valY ;// t3=(t3*valY + t5*yFrac)
+ MLA tmp6, tmp3, xFrac, c32 ;// t3=t3*xFrac+32
+ MLA tmp6, tmp4, valX, tmp6 ;// t6=t4*valX+t6
+
+ MOV tmp6, tmp6, LSR #6 ;// scale down
+ STRB tmp6, [mb, #8] ;// store pixel
+ MOV tmp5, tmp5, LSR #6 ;// scale down
+ STRB tmp5, [mb], #1 ;// store pixel
+
+ SUBS count, count, #2<<28
+ BCS loop1_x
+
+ AND tmp2, count, #0x00F00000
+
+ ADDS mb, mb, #16
+ SBC mb, mb, tmp2, LSR #20
+ ADD ptrA, ptrA, width, LSL #1
+ SBC ptrA, ptrA, tmp2, LSR #20
+
+ ADDS count, count, #0xE << 24
+ BGE loop1_y
+
+ ;///////////////////////////////////////////////////////////////////////////
+ ;// Cr
+ ;///////////////////////////////////////////////////////////////////////////
+ LDR height, [sp,#0xfc] ;// height
+ LDR ref, [sp, #0xc4] ;// ref
+ LDR tmp1, [sp, #0xd0] ;// y0
+ LDR tmp2, [sp, #0xcc] ;// x0
+ LDR mb, [sp, #0xc8] ;// predPartChroma
+
+ ADD tmp1, height, tmp1
+ MLA tmp3, tmp1, width, tmp2
+ ADD ptrA, ref, tmp3
+ ADD mb, mb, #64
+
+ AND count, count, #0x00FFFFFF
+ AND tmp1, count, #0x000F0000
+ ADD count, count, tmp1, LSL #8
+ AND tmp2, count, #0x00F00000
+
+ ;// 2x2 pels per iteration
+ ;// bilinear vertical and horizontal interpolation
+loop2_y
+ LDRB tmp1, [ptrA]
+ LDRB tmp3, [ptrA, width]
+ LDRB tmp5, [ptrA, width, LSL #1]
+
+ PKHBT tmp1, tmp1, tmp3, LSL #16 ;// |t3|t1|
+ PKHBT tmp3, tmp3, tmp5, LSL #16 ;// |t5|t3|
+
+ SMUAD tmp1, tmp1, valY ;// t1=(t1*valY + t3*yFrac)
+ SMUAD tmp3, tmp3, valY ;// t3=(t3*valY + t5*yFrac)
+
+ ADD count, count, tmp2, LSL #8
+loop2_x
+ ;// first
+ LDRB tmp2, [ptrA, #1]!
+ LDRB tmp4, [ptrA, width]
+ LDRB tmp6, [ptrA, width, LSL #1]
+
+ PKHBT tmp2, tmp2, tmp4, LSL #16 ;// |t4|t2|
+ PKHBT tmp4, tmp4, tmp6, LSL #16 ;// |t6|t4|
+
+ SMUAD tmp2, tmp2, valY ;// t2=(t2*valY + t4*yFrac)
+ MLA tmp5, tmp1, valX, c32 ;// t5=t1*valX+32
+ MLA tmp5, tmp2, xFrac, tmp5 ;// t5=t2*xFrac+t5
+
+ SMUAD tmp4, tmp4, valY ;// t4=(t4*valY + t6*yFrac)
+ MLA tmp6, tmp3, valX, c32 ;// t3=t3*valX+32
+ MLA tmp6, tmp4, xFrac, tmp6 ;// t6=t4*xFrac+t6
+
+ MOV tmp6, tmp6, LSR #6 ;// scale down
+ STRB tmp6, [mb, #8] ;// store pixel
+ MOV tmp5, tmp5, LSR #6 ;// scale down
+ STRB tmp5, [mb], #1 ;// store pixel
+
+ ;// second
+ LDRB tmp1, [ptrA, #1]!
+ LDRB tmp3, [ptrA, width]
+ LDRB tmp5, [ptrA, width, LSL #1]
+
+ PKHBT tmp1, tmp1, tmp3, LSL #16 ;// |t3|t1|
+ PKHBT tmp3, tmp3, tmp5, LSL #16 ;// |t5|t3|
+
+ SMUAD tmp1, tmp1, valY ;// t1=(t1*valY + t3*yFrac)
+ MLA tmp5, tmp1, xFrac, c32 ;// t1=t1*xFrac+32
+ MLA tmp5, tmp2, valX, tmp5 ;// t5=t2*valX+t5
+
+ SMUAD tmp3, tmp3, valY ;// t3=(t3*valY + t5*yFrac)
+ MLA tmp6, tmp3, xFrac, c32 ;// t3=t3*xFrac+32
+ MLA tmp6, tmp4, valX, tmp6 ;// t6=t4*valX+t6
+
+ MOV tmp6, tmp6, LSR #6 ;// scale down
+ STRB tmp6, [mb, #8] ;// store pixel
+ MOV tmp5, tmp5, LSR #6 ;// scale down
+ STRB tmp5, [mb], #1 ;// store pixel
+
+ SUBS count, count, #2<<28
+ BCS loop2_x
+
+ AND tmp2, count, #0x00F00000
+
+ ADDS mb, mb, #16
+ SBC mb, mb, tmp2, LSR #20
+ ADD ptrA, ptrA, width, LSL #1
+ SBC ptrA, ptrA, tmp2, LSR #20
+
+ ADDS count, count, #0xE << 24
+ BGE loop2_y
+
+ ADD sp,sp,#0xd4
+ LDMFD sp!,{r4-r11,pc}
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_ver.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_ver.s
new file mode 100755
index 0000000..af9df1b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_chroma_ver.s
@@ -0,0 +1,288 @@
+; 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.
+
+;-------------------------------------------------------------------------------
+;--
+;-- Abstract : ARMv6 optimized version of h264bsdInterpolateChromaVer function
+;--
+;-------------------------------------------------------------------------------
+
+
+ IF :DEF: H264DEC_WINASM
+ ;// We dont use REQUIRE8 and PRESERVE8 for winasm
+ ELSE
+ REQUIRE8
+ PRESERVE8
+ ENDIF
+
+ AREA |.text|, CODE
+
+;// h264bsdInterpolateChromaVer register allocation
+
+ref RN 0
+ptrA RN 0
+
+mb RN 1
+block RN 1
+
+x0 RN 2
+count RN 2
+
+y0 RN 3
+valY RN 3
+
+width RN 4
+
+height RN 5
+tmp7 RN 5
+
+chrPW RN 6
+tmp8 RN 6
+
+tmp1 RN 7
+
+tmp2 RN 8
+
+tmp3 RN 9
+
+tmp4 RN 10
+
+tmp5 RN 11
+chrPH RN 11
+
+tmp6 RN 12
+
+c32 RN 14
+yFrac RN 14
+
+;// Function exports and imports
+
+ IMPORT h264bsdFillBlock
+
+ EXPORT h264bsdInterpolateChromaVer
+
+;// Function arguments
+;//
+;// u8 *ref, : 0xc4
+;// u8 *predPartChroma, : 0xc8
+;// i32 x0, : 0xcc
+;// i32 y0, : 0xd0
+;// u32 width, : 0xf8
+;// u32 height, : 0xfc
+;// u32 yFrac, : 0x100
+;// u32 chromaPartWidth, : 0x104
+;// u32 chromaPartHeight : 0x108
+
+h264bsdInterpolateChromaVer
+ STMFD sp!, {r0-r11,lr}
+ SUB sp, sp, #0xc4
+
+ LDR chrPW, [sp, #0x104] ;// chromaPartWidth
+ LDR width, [sp, #0xf8] ;// width
+ CMP x0, #0
+ BLT do_fill
+
+ ADD tmp1, x0, chrPW ;// tmp1 = x0+ chromaPartWidth
+ CMP tmp1, width ;// x0+chromaPartWidth > width
+ BHI do_fill
+
+ CMP y0, #0
+ BLT do_fill
+ LDR chrPH, [sp, #0x108] ;// chromaPartHeight
+ LDR height, [sp, #0xfc] ;// height
+ ADD tmp1, y0, chrPH ;// tmp1 = y0 + chromaPartHeight
+ ADD tmp1, tmp1, #1 ;// tmp1 = y0 + chromaPartHeight + 1
+ CMP tmp1, height
+ BLS skip_fill
+
+do_fill
+ LDR chrPH, [sp, #0x108] ;// chromaPartHeight
+ LDR height, [sp, #0xfc] ;// height
+ ADD tmp1, chrPH, #1 ;// tmp1 = chromaPartHeight+1
+ MOV tmp2, chrPW ;// tmp2 = chromaPartWidth
+ STMIA sp,{width,height,chrPW,tmp1,tmp2}
+ ADD block, sp, #0x1c ;// block
+ BL h264bsdFillBlock
+
+ LDR x0, [sp, #0xcc]
+ LDR y0, [sp, #0xd0]
+ LDR ref, [sp, #0xc4] ;// ref
+ STMIA sp,{width,height,chrPW,tmp1,tmp2}
+ ADD block, sp, #0x1c ;// block
+ MLA ref, height, width, ref ;// ref += width * height;
+ MLA block, chrPW, tmp1, block;// block + (chromaPW)*(chromaPH+1)
+ BL h264bsdFillBlock
+
+ MOV x0, #0 ;// x0 = 0
+ MOV y0, #0 ;// y0 = 0
+ STR x0, [sp, #0xcc]
+ STR y0, [sp, #0xd0]
+ ADD ref, sp, #0x1c ;// ref = block
+ STR ref, [sp, #0xc4] ;// ref
+
+ STR tmp1, [sp, #0xfc] ;// height
+ STR chrPW, [sp, #0xf8] ;// width
+ MOV width, chrPW
+
+skip_fill
+ MLA tmp3, y0, width, x0 ;// tmp3 = y0*width+x0
+ LDR yFrac, [sp, #0x100] ;// yFrac
+ ADD ptrA, ref, tmp3 ;// ptrA = ref + y0*width+x0
+ RSB valY, yFrac, #8 ;// valY = 8-yFrac
+
+ LDR mb, [sp, #0xc8] ;// predPartChroma
+
+
+ ;// pack values to count register
+ ;// [31:28] loop_x (chromaPartWidth-1)
+ ;// [27:24] loop_y (chromaPartHeight-1)
+ ;// [23:20] chromaPartWidth-1
+ ;// [19:16] chromaPartHeight-1
+ ;// [15:00] nothing
+
+ SUB tmp2, chrPH, #1 ;// chromaPartHeight-1
+ SUB tmp1, chrPW, #1 ;// chromaPartWidth-1
+ ADD count, count, tmp2, LSL #16 ;// chromaPartHeight-1
+ ADD count, count, tmp2, LSL #24 ;// loop_y
+ ADD count, count, tmp1, LSL #20 ;// chromaPartWidth-1
+ AND tmp2, count, #0x00F00000 ;// loop_x
+ PKHBT valY, valY, yFrac, LSL #16 ;// |yFrac|valY |
+ MOV valY, valY, LSL #3 ;// multiply by 8 in advance
+ MOV c32, #32
+
+
+ ;///////////////////////////////////////////////////////////////////////////
+ ;// Cb
+ ;///////////////////////////////////////////////////////////////////////////
+
+ ;// 2x2 pels per iteration
+ ;// bilinear vertical interpolation
+
+loop1_y
+ ADD count, count, tmp2, LSL #8
+loop1_x
+ ;// Process 2x2 block
+ LDRB tmp2, [ptrA,width] ;// 2 row, 1 col
+ LDRB tmp3, [ptrA,width, LSL #1] ;// 3 row, 1 col
+ LDRB tmp1, [ptrA],#1 ;// 1 row, 1 col
+
+ LDRB tmp5, [ptrA,width] ;// 2 row, 2 col
+ LDRB tmp6, [ptrA,width, LSL #1] ;// 3 row, 2 col
+ LDRB tmp4, [ptrA],#1 ;// 1 row, 2 col
+
+ PKHBT tmp1, tmp1, tmp2, LSL #16 ;// |B|A|
+ PKHBT tmp2, tmp2, tmp3, LSL #16 ;// |C|B|
+ PKHBT tmp4, tmp4, tmp5, LSL #16 ;// |B|A|
+
+ SMLAD tmp7, tmp2, valY, c32 ;// multiply
+ PKHBT tmp5, tmp5, tmp6, LSL #16 ;// |C|B|
+ SMLAD tmp2, tmp1, valY, c32 ;// multiply
+ SMLAD tmp8, tmp5, valY, c32 ;// multiply
+ SMLAD tmp5, tmp4, valY, c32 ;// multiply
+
+ MOV tmp7, tmp7, LSR #6 ;// scale down
+ STRB tmp7, [mb,#8] ;// store row 2 col 1
+ MOV tmp2, tmp2, LSR #6 ;// scale down
+ STRB tmp2, [mb],#1 ;// store row 1 col 1
+
+ MOV tmp8, tmp8, LSR #6 ;// scale down
+ STRB tmp8, [mb,#8] ;// store row 2 col 2
+ MOV tmp5, tmp5, LSR #6 ;// scale down
+ STRB tmp5, [mb],#1 ;// store row 1 col 2
+
+
+ SUBS count, count, #2<<28
+ BCS loop1_x
+
+ AND tmp2, count, #0x00F00000
+
+ ADDS mb, mb, #16
+ SBC mb, mb, tmp2, LSR #20
+ ADD ptrA, ptrA, width, LSL #1
+ SBC ptrA, ptrA, tmp2, LSR #20
+
+ ADDS count, count, #0xE << 24
+ BGE loop1_y
+
+ ;///////////////////////////////////////////////////////////////////////////
+ ;// Cr
+ ;///////////////////////////////////////////////////////////////////////////
+ LDR height, [sp,#0xfc] ;// height
+ LDR ref, [sp, #0xc4] ;// ref
+ LDR tmp1, [sp, #0xd0] ;// y0
+ LDR tmp2, [sp, #0xcc] ;// x0
+ LDR mb, [sp, #0xc8] ;// predPartChroma
+
+ ADD tmp1, height, tmp1
+ MLA tmp3, tmp1, width, tmp2
+ ADD ptrA, ref, tmp3
+ ADD mb, mb, #64
+
+ AND count, count, #0x00FFFFFF
+ AND tmp1, count, #0x000F0000
+ ADD count, count, tmp1, LSL #8
+ AND tmp2, count, #0x00F00000
+
+ ;// 2x2 pels per iteration
+ ;// bilinear vertical interpolation
+loop2_y
+ ADD count, count, tmp2, LSL #8
+loop2_x
+ ;// Process 2x2 block
+ LDRB tmp2, [ptrA,width] ;// 2 row, 1 col
+ LDRB tmp3, [ptrA,width, LSL #1] ;// 3 row, 1 col
+ LDRB tmp1, [ptrA],#1 ;// 1 row, 1 col
+
+ LDRB tmp5, [ptrA,width] ;// 2 row, 2 col
+ LDRB tmp6, [ptrA,width, LSL #1] ;// 3 row, 2 col
+ LDRB tmp4, [ptrA],#1 ;// 1 row, 2 col
+
+ PKHBT tmp1, tmp1, tmp2, LSL #16 ;// |B|A|
+ PKHBT tmp2, tmp2, tmp3, LSL #16 ;// |C|B|
+ PKHBT tmp4, tmp4, tmp5, LSL #16 ;// |B|A|
+
+ SMLAD tmp7, tmp2, valY, c32 ;// multiply
+ PKHBT tmp5, tmp5, tmp6, LSL #16 ;// |C|B|
+ SMLAD tmp2, tmp1, valY, c32 ;// multiply
+ SMLAD tmp8, tmp5, valY, c32 ;// multiply
+ SMLAD tmp5, tmp4, valY, c32 ;// multiply
+
+ MOV tmp7, tmp7, LSR #6 ;// scale down
+ STRB tmp7, [mb,#8] ;// store row 2 col 1
+ MOV tmp2, tmp2, LSR #6 ;// scale down
+ STRB tmp2, [mb],#1 ;// store row 1 col 1
+
+ MOV tmp8, tmp8, LSR #6 ;// scale down
+ STRB tmp8, [mb,#8] ;// store row 2 col 2
+ MOV tmp5, tmp5, LSR #6 ;// scale down
+ STRB tmp5, [mb],#1 ;// store row 1 col 2
+
+
+ SUBS count, count, #2<<28
+ BCS loop2_x
+
+ AND tmp2, count, #0x00F00000
+
+ ADDS mb, mb, #16
+ SBC mb, mb, tmp2, LSR #20
+ ADD ptrA, ptrA, width, LSL #1
+ SBC ptrA, ptrA, tmp2, LSR #20
+
+ ADDS count, count, #0xE << 24
+ BGE loop2_y
+
+ ADD sp,sp,#0xd4
+ LDMFD sp!, {r4-r11,pc}
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_half.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_half.s
new file mode 100755
index 0000000..93968b6
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_half.s
@@ -0,0 +1,251 @@
+; 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.
+
+;-------------------------------------------------------------------------------
+;--
+;-- Abstract : ARMv6 optimized version of h264bsdInterpolateHorHalf function
+;--
+;-------------------------------------------------------------------------------
+
+
+ IF :DEF: H264DEC_WINASM
+ ;// We dont use REQUIRE8 and PRESERVE8 for winasm
+ ELSE
+ REQUIRE8
+ PRESERVE8
+ ENDIF
+
+ AREA |.text|, CODE
+
+;// h264bsdInterpolateHorHalf register allocation
+
+ref RN 0
+
+mb RN 1
+buff RN 1
+
+count RN 2
+x0 RN 2
+
+y0 RN 3
+x_2_0 RN 3
+
+width RN 4
+x_3_1 RN 4
+
+height RN 5
+x_6_4 RN 5
+
+partW RN 6
+x_7_5 RN 6
+
+partH RN 7
+tmp1 RN 7
+
+tmp2 RN 8
+
+tmp3 RN 9
+
+tmp4 RN 10
+
+mult_20_01 RN 11
+mult_20_m5 RN 12
+
+plus16 RN 14
+
+
+;// function exports and imports
+
+ IMPORT h264bsdFillBlock
+
+ EXPORT h264bsdInterpolateHorHalf
+
+;// Horizontal filter approach
+;//
+;// Basic idea in horizontal filtering is to adjust coefficients
+;// like below. Calculation is done with 16-bit maths.
+;//
+;// Reg x_2_0 x_3_1 x_6_4 x_7_5 x_2_0
+;// [ 2 0 ] [ 3 1 ] [ 6 4 ] [ 7 5 ] [ 10 8 ] ...
+;// y_0 = 20 1 20 -5 -5 1
+;// y_1 = -5 20 1 1 20 -5
+;// y_2 = 1 -5 -5 20 1 20
+;// y_3 = 1 20 -5 -5 20 1
+
+
+h264bsdInterpolateHorHalf
+ STMFD sp!, {r0-r11, lr}
+ SUB sp, sp, #0x1e4
+
+ CMP x0, #0
+ BLT do_fill ;// (x0 < 0)
+ LDR partW, [sp,#0x220] ;// partWidth
+ ADD tmp4, x0, partW ;// (x0+partWidth)
+ ADD tmp4, tmp4, #5 ;// (y0+partW+5)
+ LDR width, [sp,#0x218] ;// width
+ CMP tmp4, width
+ BHI do_fill ;// (x0+partW)>width
+
+ CMP y0, #0
+ BLT do_fill ;// (y0 < 0)
+ LDR partH, [sp,#0x224] ;// partHeight
+ ADD tmp2, y0, partH ;// (y0+partHeight)
+ LDR height, [sp,#0x21c] ;// height
+ CMP tmp2, height
+ BLS skip_fill ;// no overfill needed
+
+
+do_fill
+ LDR partH, [sp,#0x224] ;// partHeight
+ LDR height, [sp,#0x21c] ;// height
+ LDR partW, [sp,#0x220] ;// partWidth
+ ADD tmp4, partW, #5 ;// tmp4 = partW + 5;
+ STMIB sp, {height, tmp4} ;// sp+4 = height, sp+8 = partWidth+5
+ STR partH, [sp,#0xc] ;// sp+c = partHeight
+ STR tmp4, [sp,#0x10] ;// sp+10 = partWidth+5
+ LDR width, [sp,#0x218] ;// width
+ STR width, [sp,#0] ;// sp+0 = width
+ ADD buff, sp, #0x28 ;// buff = p1[21*21/4+1]
+ BL h264bsdFillBlock
+
+ MOV x0, #0
+ STR x0,[sp,#0x1ec] ;// x0 = 0
+ STR x0,[sp,#0x1f0] ;// y0 = 0
+ ADD ref,sp,#0x28 ;// ref = p1
+ STR tmp4, [sp,#0x218] ;// width = partWidth+5
+
+
+skip_fill
+ LDR x0 ,[sp,#0x1ec] ;// x0
+ LDR y0 ,[sp,#0x1f0] ;// y0
+ LDR width, [sp,#0x218] ;// width
+ MLA tmp2, width, y0, x0 ;// y0*width+x0
+ ADD ref, ref, tmp2 ;// ref += y0*width+x0
+ ADD ref, ref, #8 ;// ref = ref+8
+ LDR mb, [sp, #0x1e8] ;// mb
+
+ ;// pack values to count register
+ ;// [31:28] loop_x (partWidth-1)
+ ;// [27:24] loop_y (partHeight-1)
+ ;// [23:20] partWidth-1
+ ;// [19:16] partHeight-1
+ ;// [15:00] width
+ MOV count, width
+ SUB partW, partW, #1;
+ SUB partH, partH, #1;
+ ADD tmp2, partH, partW, LSL #4
+ ADD count, count, tmp2, LSL #16
+
+
+ LDR mult_20_01, = 0x00140001
+ LDR mult_20_m5, = 0x0014FFFB
+ MOV plus16, #16
+ AND tmp1, count, #0x000F0000 ;// partHeight-1
+ AND tmp3, count, #0x00F00000 ;// partWidth-1
+ ADD count, count, tmp1, LSL #8
+loop_y
+ LDR x_3_1, [ref, #-8]
+ ADD count, count, tmp3, LSL #8
+ LDR x_7_5, [ref, #-4]
+ UXTB16 x_2_0, x_3_1
+ UXTB16 x_3_1, x_3_1, ROR #8
+ UXTB16 x_6_4, x_7_5
+
+loop_x
+ UXTB16 x_7_5, x_7_5, ROR #8
+
+ SMLAD tmp1, x_2_0, mult_20_01, plus16
+ SMLATB tmp3, x_2_0, mult_20_01, plus16
+ SMLATB tmp2, x_2_0, mult_20_m5, plus16
+ SMLATB tmp4, x_3_1, mult_20_01, plus16
+
+ SMLAD tmp1, x_3_1, mult_20_m5, tmp1
+ SMLATB tmp3, x_3_1, mult_20_m5, tmp3
+ SMLAD tmp2, x_3_1, mult_20_01, tmp2
+ LDR x_3_1, [ref], #4
+ SMLAD tmp4, x_6_4, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_6_4, mult_20_m5, tmp1
+ SMLADX tmp3, x_6_4, mult_20_m5, tmp3
+ SMLADX tmp2, x_6_4, mult_20_01, tmp2
+ SMLADX tmp4, x_7_5, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_7_5, mult_20_01, tmp1
+ UXTB16 x_2_0, x_3_1
+ SMLABB tmp2, x_7_5, mult_20_m5, tmp2
+ SMLADX tmp3, x_7_5, mult_20_01, tmp3
+ SMLABB tmp4, x_2_0, mult_20_01, tmp4
+
+ MOV tmp2, tmp2, ASR #5
+ MOV tmp1, tmp1, ASR #5
+ PKHBT tmp2, tmp2, tmp4, LSL #(16-5)
+ PKHBT tmp1, tmp1, tmp3, LSL #(16-5)
+ USAT16 tmp2, #8, tmp2
+ USAT16 tmp1, #8, tmp1
+
+ SUBS count, count, #4<<28
+ ORR tmp1, tmp1, tmp2, LSL #8
+ STR tmp1, [mb], #4
+ BCC next_y
+
+ UXTB16 x_3_1, x_3_1, ROR #8
+
+ SMLAD tmp1, x_6_4, mult_20_01, plus16
+ SMLATB tmp3, x_6_4, mult_20_01, plus16
+ SMLATB tmp2, x_6_4, mult_20_m5, plus16
+ SMLATB tmp4, x_7_5, mult_20_01, plus16
+
+ SMLAD tmp1, x_7_5, mult_20_m5, tmp1
+ SMLATB tmp3, x_7_5, mult_20_m5, tmp3
+ SMLAD tmp2, x_7_5, mult_20_01, tmp2
+ LDR x_7_5, [ref], #4
+ SMLAD tmp4, x_2_0, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_2_0, mult_20_m5, tmp1
+ SMLADX tmp3, x_2_0, mult_20_m5, tmp3
+ SMLADX tmp2, x_2_0, mult_20_01, tmp2
+ SMLADX tmp4, x_3_1, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_3_1, mult_20_01, tmp1
+ UXTB16 x_6_4, x_7_5
+ SMLABB tmp2, x_3_1, mult_20_m5, tmp2
+ SMLADX tmp3, x_3_1, mult_20_01, tmp3
+ SMLABB tmp4, x_6_4, mult_20_01, tmp4
+
+ MOV tmp2, tmp2, ASR #5
+ MOV tmp1, tmp1, ASR #5
+ PKHBT tmp2, tmp2, tmp4, LSL #(16-5)
+ PKHBT tmp1, tmp1, tmp3, LSL #(16-5)
+ USAT16 tmp2, #8, tmp2
+ USAT16 tmp1, #8, tmp1
+
+ SUBS count, count, #4<<28
+ ORR tmp1, tmp1, tmp2, LSL #8
+ STR tmp1, [mb], #4
+ BCS loop_x
+
+next_y
+ AND tmp3, count, #0x00F00000 ;// partWidth-1
+ SMLABB ref, count, mult_20_01, ref ;// +width
+ ADDS mb, mb, #16 ;// +16, Carry=0
+ SBC mb, mb, tmp3, LSR #20 ;// -(partWidth-1)-1
+ SBC ref, ref, tmp3, LSR #20 ;// -(partWidth-1)-1
+ ADDS count, count, #(1<<28)-(1<<24)
+ BGE loop_y
+
+ ADD sp,sp,#0x1f4
+ LDMFD sp!, {r4-r11, pc}
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_quarter.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_quarter.s
new file mode 100755
index 0000000..de243d4
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_quarter.s
@@ -0,0 +1,273 @@
+; 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.
+
+;-------------------------------------------------------------------------------
+;--
+;-- Abstract : ARMv6 optimized version of h264bsdInterpolateHorQuarter function
+;--
+;-------------------------------------------------------------------------------
+
+
+ IF :DEF: H264DEC_WINASM
+ ;// We dont use REQUIRE8 and PRESERVE8 for winasm
+ ELSE
+ REQUIRE8
+ PRESERVE8
+ ENDIF
+
+ AREA |.text|, CODE
+
+;// h264bsdInterpolateHorQuarter register allocation
+
+ref RN 0
+
+mb RN 1
+buff RN 1
+
+count RN 2
+x0 RN 2
+
+y0 RN 3
+x_2_0 RN 3
+
+width RN 4
+x_3_1 RN 4
+
+height RN 5
+x_6_4 RN 5
+
+partW RN 6
+x_7_5 RN 6
+
+partH RN 7
+tmp1 RN 7
+
+tmp2 RN 8
+
+tmp3 RN 9
+
+tmp4 RN 10
+
+mult_20_01 RN 11
+
+mult_20_m5 RN 12
+
+plus16 RN 14
+
+
+;// function exports and imports
+
+ IMPORT h264bsdFillBlock
+
+ EXPORT h264bsdInterpolateHorQuarter
+
+
+;// Horizontal filter approach
+;//
+;// Basic idea in horizontal filtering is to adjust coefficients
+;// like below. Calculation is done with 16-bit maths.
+;//
+;// Reg x_2_0 x_3_1 x_6_4 x_7_5 x_2_0
+;// [ 2 0 ] [ 3 1 ] [ 6 4 ] [ 7 5 ] [ 10 8 ] ...
+;// y_0 = 20 1 20 -5 -5 1
+;// y_1 = -5 20 1 1 20 -5
+;// y_2 = 1 -5 -5 20 1 20
+;// y_3 = 1 20 -5 -5 20 1
+
+
+h264bsdInterpolateHorQuarter
+ STMFD sp!, {r0-r11, lr}
+ SUB sp, sp, #0x1e4
+
+ CMP x0, #0
+ BLT do_fill ;// (x0 < 0)
+ LDR partW, [sp,#0x220] ;// partWidth
+ ADD tmp4, x0, partW ;// (x0+partWidth)
+ ADD tmp4, tmp4, #5 ;// (y0+partW+5)
+ LDR width, [sp,#0x218] ;// width
+ CMP tmp4, width
+ BHI do_fill ;// (x0+partW)>width
+
+ CMP y0, #0
+ BLT do_fill ;// (y0 < 0)
+ LDR partH, [sp,#0x224] ;// partHeight
+ ADD tmp2, y0, partH ;// (y0+partHeight)
+ LDR height, [sp,#0x21c] ;// height
+ CMP tmp2, height
+ BLS skip_fill ;// no overfill needed
+
+
+do_fill
+ LDR partH, [sp,#0x224] ;// partHeight
+ LDR height, [sp,#0x21c] ;// height
+ LDR partW, [sp,#0x220] ;// partWidth
+ ADD tmp4, partW, #5 ;// tmp4 = partW + 5;
+ STMIB sp, {height, tmp4} ;// sp+4 = height, sp+8 = partWidth+5
+ STR partH, [sp,#0xc] ;// sp+c = partHeight
+ STR tmp4, [sp,#0x10] ;// sp+10 = partWidth+5
+ LDR width, [sp,#0x218] ;// width
+ STR width, [sp,#0] ;// sp+0 = width
+ ADD buff, sp, #0x28 ;// buff = p1[21*21/4+1]
+ BL h264bsdFillBlock
+
+ MOV x0, #0
+ STR x0,[sp,#0x1ec] ;// x0 = 0
+ STR x0,[sp,#0x1f0] ;// y0 = 0
+ ADD ref,sp,#0x28 ;// ref = p1
+ STR tmp4, [sp,#0x218] ;// width = partWidth+5
+
+
+skip_fill
+ LDR x0 ,[sp,#0x1ec] ;// x0
+ LDR y0 ,[sp,#0x1f0] ;// y0
+ LDR width, [sp,#0x218] ;// width
+ MLA tmp2, width, y0, x0 ;// y0*width+x0
+ ADD ref, ref, tmp2 ;// ref += y0*width+x0
+ ADD ref, ref, #8 ;// ref = ref+8
+ LDR mb, [sp, #0x1e8] ;// mb
+
+ ;// pack values to count register
+ ;// [31:28] loop_x (partWidth-1)
+ ;// [27:24] loop_y (partHeight-1)
+ ;// [23:20] partWidth-1
+ ;// [19:16] partHeight-1
+ ;// [15:00] width
+ MOV count, width
+ SUB partW, partW, #1;
+ SUB partH, partH, #1;
+ ADD tmp2, partH, partW, LSL #4
+ ADD count, count, tmp2, LSL #16
+
+
+ LDR mult_20_01, = 0x00140001
+ LDR mult_20_m5, = 0x0014FFFB
+ MOV plus16, #16
+ AND tmp1, count, #0x000F0000 ;// partHeight-1
+ AND tmp3, count, #0x00F00000 ;// partWidth-1
+ ADD count, count, tmp1, LSL #8
+loop_y
+ LDR x_3_1, [ref, #-8]
+ ADD count, count, tmp3, LSL #8
+ LDR x_7_5, [ref, #-4]
+ UXTB16 x_2_0, x_3_1
+ UXTB16 x_3_1, x_3_1, ROR #8
+ UXTB16 x_6_4, x_7_5
+
+loop_x
+ UXTB16 x_7_5, x_7_5, ROR #8
+
+ SMLAD tmp1, x_2_0, mult_20_01, plus16
+ SMLATB tmp3, x_2_0, mult_20_01, plus16
+ SMLATB tmp2, x_2_0, mult_20_m5, plus16
+ SMLATB tmp4, x_3_1, mult_20_01, plus16
+
+ SMLAD tmp1, x_3_1, mult_20_m5, tmp1
+ SMLATB tmp3, x_3_1, mult_20_m5, tmp3
+ SMLAD tmp2, x_3_1, mult_20_01, tmp2
+ LDR x_3_1, [ref], #4
+ SMLAD tmp4, x_6_4, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_6_4, mult_20_m5, tmp1
+ SMLADX tmp3, x_6_4, mult_20_m5, tmp3
+ SMLADX tmp2, x_6_4, mult_20_01, tmp2
+ SMLADX tmp4, x_7_5, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_7_5, mult_20_01, tmp1
+ UXTB16 x_2_0, x_3_1
+ SMLABB tmp2, x_7_5, mult_20_m5, tmp2
+ SMLADX tmp3, x_7_5, mult_20_01, tmp3
+ SMLABB tmp4, x_2_0, mult_20_01, tmp4
+
+ MOV tmp2, tmp2, ASR #5
+ MOV tmp1, tmp1, ASR #5
+ PKHBT tmp2, tmp2, tmp4, LSL #(16-5)
+ PKHBT tmp1, tmp1, tmp3, LSL #(16-5)
+ LDR tmp4, [sp, #0x228]
+ USAT16 tmp2, #8, tmp2
+ USAT16 tmp1, #8, tmp1
+ SUB tmp4, tmp4, #10
+
+ SUBS count, count, #4<<28
+ LDR tmp3, [ref, tmp4]
+ ORR tmp1, tmp1, tmp2, LSL #8
+
+;// quarter pel position
+ LDR tmp2, = 0x80808080
+ MVN tmp3, tmp3
+ UHSUB8 tmp1, tmp1, tmp3
+ EOR tmp1, tmp1, tmp2
+ STR tmp1, [mb], #4
+
+ BCC next_y
+
+ UXTB16 x_3_1, x_3_1, ROR #8
+
+ SMLAD tmp1, x_6_4, mult_20_01, plus16
+ SMLATB tmp3, x_6_4, mult_20_01, plus16
+ SMLATB tmp2, x_6_4, mult_20_m5, plus16
+ SMLATB tmp4, x_7_5, mult_20_01, plus16
+
+ SMLAD tmp1, x_7_5, mult_20_m5, tmp1
+ SMLATB tmp3, x_7_5, mult_20_m5, tmp3
+ SMLAD tmp2, x_7_5, mult_20_01, tmp2
+ LDR x_7_5, [ref], #4
+ SMLAD tmp4, x_2_0, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_2_0, mult_20_m5, tmp1
+ SMLADX tmp3, x_2_0, mult_20_m5, tmp3
+ SMLADX tmp2, x_2_0, mult_20_01, tmp2
+ SMLADX tmp4, x_3_1, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_3_1, mult_20_01, tmp1
+ UXTB16 x_6_4, x_7_5
+ SMLABB tmp2, x_3_1, mult_20_m5, tmp2
+ SMLADX tmp3, x_3_1, mult_20_01, tmp3
+ SMLABB tmp4, x_6_4, mult_20_01, tmp4
+
+ MOV tmp2, tmp2, ASR #5
+ MOV tmp1, tmp1, ASR #5
+ PKHBT tmp2, tmp2, tmp4, LSL #(16-5)
+ PKHBT tmp1, tmp1, tmp3, LSL #(16-5)
+ LDR tmp4, [sp, #0x228]
+ USAT16 tmp2, #8, tmp2
+ USAT16 tmp1, #8, tmp1
+ SUB tmp4, tmp4, #10
+
+ SUBS count, count, #4<<28
+ LDR tmp3, [ref, tmp4]
+ ORR tmp1, tmp1, tmp2, LSL #8
+
+;// quarter pel
+ LDR tmp2, = 0x80808080
+ MVN tmp3, tmp3
+ UHSUB8 tmp1, tmp1, tmp3
+ EOR tmp1, tmp1, tmp2
+
+ STR tmp1, [mb], #4
+ BCS loop_x
+
+next_y
+ AND tmp3, count, #0x00F00000 ;// partWidth-1
+ SMLABB ref, count, mult_20_01, ref ;// +width
+ ADDS mb, mb, #16 ;// +16, Carry=0
+ SBC mb, mb, tmp3, LSR #20 ;// -(partWidth-1)-1
+ SBC ref, ref, tmp3, LSR #20 ;// -(partWidth-1)-1
+ ADDS count, count, #(1<<28)-(1<<24)
+ BGE loop_y
+
+ ADD sp,sp,#0x1f4
+ LDMFD sp!, {r4-r11, pc}
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_ver_quarter.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_ver_quarter.s
new file mode 100755
index 0000000..1c79b39
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_hor_ver_quarter.s
@@ -0,0 +1,536 @@
+; 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.
+
+;-------------------------------------------------------------------------------
+;--
+;-- Abstract : ARMv6 optimized version of h264bsdInterpolateHorVerQuarter
+;-- function
+;--
+;-------------------------------------------------------------------------------
+
+
+ IF :DEF: H264DEC_WINASM
+ ;// We dont use REQUIRE8 and PRESERVE8 for winasm
+ ELSE
+ REQUIRE8
+ PRESERVE8
+ ENDIF
+
+ AREA |.text|, CODE
+
+;// h264bsdInterpolateHorVerQuarter register allocation
+
+ref RN 0
+
+mb RN 1
+buff RN 1
+
+count RN 2
+x0 RN 2
+
+y0 RN 3
+x_2_0 RN 3
+res RN 3
+
+x_3_1 RN 4
+tmp1 RN 4
+
+height RN 5
+x_6_4 RN 5
+tmp2 RN 5
+
+partW RN 6
+x_7_5 RN 6
+tmp3 RN 6
+
+partH RN 7
+tmp4 RN 7
+
+tmp5 RN 8
+
+tmp6 RN 9
+
+tmpa RN 10
+
+mult_20_01 RN 11
+tmpb RN 11
+
+mult_20_m5 RN 12
+width RN 12
+
+plus16 RN 14
+
+
+;// function exports and imports
+
+ IMPORT h264bsdFillBlock
+
+ EXPORT h264bsdInterpolateHorVerQuarter
+
+;// Horizontal filter approach
+;//
+;// Basic idea in horizontal filtering is to adjust coefficients
+;// like below. Calculation is done with 16-bit maths.
+;//
+;// Reg x_2_0 x_3_1 x_6_4 x_7_5 x_2_0
+;// [ 2 0 ] [ 3 1 ] [ 6 4 ] [ 7 5 ] [ 10 8 ] ...
+;// y_0 = 20 1 20 -5 -5 1
+;// y_1 = -5 20 1 1 20 -5
+;// y_2 = 1 -5 -5 20 1 20
+;// y_3 = 1 20 -5 -5 20 1
+
+
+h264bsdInterpolateHorVerQuarter
+ STMFD sp!, {r0-r11, lr}
+ SUB sp, sp, #0x1e4
+
+ CMP x0, #0
+ BLT do_fill ;// (x0 < 0)
+ LDR partW, [sp,#0x220] ;// partWidth
+ LDR width, [sp,#0x218] ;// width
+ ADD tmpa, x0, partW ;// (x0+partWidth)
+ ADD tmpa, tmpa, #5 ;// (x0+partW+5)
+ CMP tmpa, width
+ BHI do_fill ;// (x0+partW)>width
+
+ CMP y0, #0
+ BLT do_fill ;// (y0 < 0)
+ LDR partH, [sp,#0x224] ;// partHeight
+ LDR height, [sp,#0x21c] ;// height
+ ADD tmp5, y0, partH ;// (y0+partHeight)
+ ADD tmp5, tmp5, #5 ;// (y0+partH+5)
+ CMP tmp5, height
+ BLS skip_fill ;// no overfill needed
+
+
+do_fill
+ LDR partH, [sp,#0x224] ;// partHeight
+ LDR partW, [sp,#0x220] ;// partWidth
+ LDR height, [sp,#0x21c] ;// height
+ ADD tmp5, partH, #5 ;// tmp5 = partH + 5
+ ADD tmpa, partW, #5 ;// tmpa = partW + 5
+ STMIB sp, {height, tmpa} ;// sp+4 = height, sp+8 = partWidth+5
+ LDR width, [sp,#0x218] ;// width
+ STR tmp5, [sp,#0xc] ;// sp+c = partHeight+5
+ STR tmpa, [sp,#0x10] ;// sp+10 = partWidth+5
+ STR width, [sp,#0] ;// sp+0 = width
+ ADD buff, sp, #0x28 ;// buff = p1[21*21/4+1]
+ BL h264bsdFillBlock
+
+ MOV x0, #0
+ STR x0,[sp,#0x1ec] ;// x0 = 0
+ STR x0,[sp,#0x1f0] ;// y0 = 0
+ ADD ref,sp,#0x28 ;// ref = p1
+ STR tmpa, [sp,#0x218] ;// width = partWidth+5
+
+
+skip_fill
+ LDR x0 ,[sp,#0x1ec] ;// x0
+ LDR y0 ,[sp,#0x1f0] ;// y0
+ LDR width, [sp,#0x218] ;// width
+ LDR tmp6, [sp,#0x228] ;// horVerOffset
+ LDR mb, [sp, #0x1e8] ;// mb
+ MLA tmp5, width, y0, x0 ;// y0*width+x0
+ ADD ref, ref, tmp5 ;// ref += y0*width+x0
+ STR ref, [sp, #0x1e4] ;// store "ref" for vertical filtering
+ AND tmp6, tmp6, #2 ;// calculate ref for horizontal filter
+ MOV tmpa, #2
+ ADD tmp6, tmpa, tmp6, LSR #1
+ MLA ref, tmp6, width, ref
+ ADD ref, ref, #8 ;// ref = ref+8
+
+ ;// pack values to count register
+ ;// [31:28] loop_x (partWidth-1)
+ ;// [27:24] loop_y (partHeight-1)
+ ;// [23:20] partWidth-1
+ ;// [19:16] partHeight-1
+ ;// [15:00] width
+ MOV count, width
+ SUB partW, partW, #1;
+ SUB partH, partH, #1;
+ ADD tmp5, partH, partW, LSL #4
+ ADD count, count, tmp5, LSL #16
+
+
+ LDR mult_20_01, = 0x00140001 ;// constant multipliers
+ LDR mult_20_m5, = 0x0014FFFB ;// constant multipliers
+ MOV plus16, #16 ;// constant for add
+ AND tmp4, count, #0x000F0000 ;// partHeight-1
+ AND tmp6, count, #0x00F00000 ;// partWidth-1
+ ADD count, count, tmp4, LSL #8 ;// partH-1 to lower part of top byte
+
+;// HORIZONTAL PART
+
+loop_y_hor
+ LDR x_3_1, [ref, #-8]
+ ADD count, count, tmp6, LSL #8 ;// partW-1 to upper part of top byte
+ LDR x_7_5, [ref, #-4]
+ UXTB16 x_2_0, x_3_1
+ UXTB16 x_3_1, x_3_1, ROR #8
+ UXTB16 x_6_4, x_7_5
+
+loop_x_hor
+ UXTB16 x_7_5, x_7_5, ROR #8
+
+ SMLAD tmp4, x_2_0, mult_20_01, plus16
+ SMLATB tmp6, x_2_0, mult_20_01, plus16
+ SMLATB tmp5, x_2_0, mult_20_m5, plus16
+ SMLATB tmpa, x_3_1, mult_20_01, plus16
+
+ SMLAD tmp4, x_3_1, mult_20_m5, tmp4
+ SMLATB tmp6, x_3_1, mult_20_m5, tmp6
+ SMLAD tmp5, x_3_1, mult_20_01, tmp5
+ LDR x_3_1, [ref], #4
+ SMLAD tmpa, x_6_4, mult_20_m5, tmpa
+
+ SMLABB tmp4, x_6_4, mult_20_m5, tmp4
+ SMLADX tmp6, x_6_4, mult_20_m5, tmp6
+ SMLADX tmp5, x_6_4, mult_20_01, tmp5
+ SMLADX tmpa, x_7_5, mult_20_m5, tmpa
+
+ SMLABB tmp4, x_7_5, mult_20_01, tmp4
+ UXTB16 x_2_0, x_3_1
+ SMLABB tmp5, x_7_5, mult_20_m5, tmp5
+ SMLADX tmp6, x_7_5, mult_20_01, tmp6
+ SMLABB tmpa, x_2_0, mult_20_01, tmpa
+
+ MOV tmp5, tmp5, ASR #5
+ MOV tmp4, tmp4, ASR #5
+ PKHBT tmp5, tmp5, tmpa, LSL #(16-5)
+ PKHBT tmp4, tmp4, tmp6, LSL #(16-5)
+ USAT16 tmp5, #8, tmp5
+ USAT16 tmp4, #8, tmp4
+
+ SUBS count, count, #4<<28
+ ORR tmp4, tmp4, tmp5, LSL #8
+ STR tmp4, [mb], #4
+ BCC next_y_hor
+
+ UXTB16 x_3_1, x_3_1, ROR #8
+
+ SMLAD tmp4, x_6_4, mult_20_01, plus16
+ SMLATB tmp6, x_6_4, mult_20_01, plus16
+ SMLATB tmp5, x_6_4, mult_20_m5, plus16
+ SMLATB tmpa, x_7_5, mult_20_01, plus16
+
+ SMLAD tmp4, x_7_5, mult_20_m5, tmp4
+ SMLATB tmp6, x_7_5, mult_20_m5, tmp6
+ SMLAD tmp5, x_7_5, mult_20_01, tmp5
+ LDR x_7_5, [ref], #4
+ SMLAD tmpa, x_2_0, mult_20_m5, tmpa
+
+ SMLABB tmp4, x_2_0, mult_20_m5, tmp4
+ SMLADX tmp6, x_2_0, mult_20_m5, tmp6
+ SMLADX tmp5, x_2_0, mult_20_01, tmp5
+ SMLADX tmpa, x_3_1, mult_20_m5, tmpa
+
+ SMLABB tmp4, x_3_1, mult_20_01, tmp4
+ UXTB16 x_6_4, x_7_5
+ SMLABB tmp5, x_3_1, mult_20_m5, tmp5
+ SMLADX tmp6, x_3_1, mult_20_01, tmp6
+ SMLABB tmpa, x_6_4, mult_20_01, tmpa
+
+ MOV tmp5, tmp5, ASR #5
+ MOV tmp4, tmp4, ASR #5
+ PKHBT tmp5, tmp5, tmpa, LSL #(16-5)
+ PKHBT tmp4, tmp4, tmp6, LSL #(16-5)
+ USAT16 tmp5, #8, tmp5
+ USAT16 tmp4, #8, tmp4
+
+ SUBS count, count, #4<<28
+ ORR tmp4, tmp4, tmp5, LSL #8
+ STR tmp4, [mb], #4
+ BCS loop_x_hor
+
+next_y_hor
+ AND tmp6, count, #0x00F00000 ;// partWidth-1
+ SMLABB ref, count, mult_20_01, ref ;// +width
+ ADDS mb, mb, #16 ;// +16, Carry=0
+ SBC mb, mb, tmp6, LSR #20 ;// -(partWidth-1)-1
+ SBC ref, ref, tmp6, LSR #20 ;// -(partWidth-1)-1
+ ADDS count, count, #(1<<28)-(1<<24) ;// decrement counter (partW)
+ BGE loop_y_hor
+
+
+
+;// VERTICAL PART
+;//
+;// Approach to vertical interpolation
+;//
+;// Interpolation is done by using 32-bit loads and stores
+;// and by using 16 bit arithmetic. 4x4 block is processed
+;// in each round.
+;//
+;// |a_11|a_11|a_11|a_11|...|a_1n|a_1n|a_1n|a_1n|
+;// |b_11|b_11|b_11|b_11|...|b_1n|b_1n|b_1n|b_1n|
+;// |c_11|c_11|c_11|c_11|...|c_1n|c_1n|c_1n|c_1n|
+;// |d_11|d_11|d_11|d_11|...|d_1n|d_1n|d_1n|d_1n|
+;// ..
+;// ..
+;// |a_m1|a_m1|a_m1|a_m1|...
+;// |b_m1|b_m1|b_m1|b_m1|...
+;// |c_m1|c_m1|c_m1|c_m1|...
+;// |d_m1|d_m1|d_m1|d_m1|...
+
+;// Approach to bilinear interpolation to quarter pel position.
+;// 4 bytes are processed parallel
+;//
+;// algorithm (a+b+1)/2. Rouding upwards +1 can be achieved by
+;// negating second operand to get one's complement (instead of 2's)
+;// and using subtraction, EOR is used to correct sign.
+;//
+;// MVN b, b
+;// UHSUB8 a, a, b
+;// EOR a, a, 0x80808080
+
+
+ LDR ref, [sp, #0x1e4] ;// ref
+ LDR tmpa, [sp, #0x228] ;// horVerOffset
+ LDR mb, [sp, #0x1e8] ;// mb
+ LDR width, [sp, #0x218] ;// width
+ ADD ref, ref, #2 ;// calculate correct position
+ AND tmpa, tmpa, #1
+ ADD ref, ref, tmpa
+ LDR plus16, = 0x00100010 ;// +16 to lower and upperf halfwords
+ AND count, count, #0x00FFFFFF ;// partWidth-1
+
+ AND tmpa, count, #0x000F0000 ;// partHeight-1
+ ADD count, count, tmpa, LSL #8
+
+loop_y
+ ADD count, count, tmp6, LSL #8 ;// partWidth-1
+
+loop_x
+ LDR tmp1, [ref], width ;// |a4|a3|a2|a1|
+ LDR tmp2, [ref], width ;// |c4|c3|c2|c1|
+ LDR tmp3, [ref], width ;// |g4|g3|g2|g1|
+ LDR tmp4, [ref], width ;// |m4|m3|m2|m1|
+ LDR tmp5, [ref], width ;// |r4|r3|r2|r1|
+ LDR tmp6, [ref], width ;// |t4|t3|t2|t1|
+
+ ;// first four pixels
+ UXTB16 tmpa, tmp3 ;// |g3|g1|
+ UXTAB16 tmpa, tmpa, tmp4 ;// |g3+m3|g1+m1|
+ UXTB16 tmpb, tmp2 ;// |c3|c1|
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+
+ UXTAB16 tmpb, tmpb, tmp5 ;// |c3+r3|c1+r1|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpa, tmpa, tmp1 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp6 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR res, = 0x00FF00FF
+ UXTB16 tmpa, tmp3, ROR #8 ;// |g4|g2|
+ UXTAB16 tmpa, tmpa, tmp4, ROR #8 ;// |g4+m4|g2+m2|
+ AND res, res, tmpb, LSR #5 ;// mask and divide by 32
+
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTB16 tmpb, tmp2, ROR #8 ;// |c4|c2|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpb, tmpb, tmp5, ROR #8 ;// |c4+r4|c2+r2|
+ UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp6, ROR #8 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR tmp1, [mb]
+ LDR tmpa, = 0xFF00FF00
+ MVN tmp1, tmp1
+ AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divede by 32
+ ORR res, res, tmpa
+
+ LDR tmpa, = 0x80808080
+ UHSUB8 res, res, tmp1 ;// bilinear interpolation
+ LDR tmp1, [ref], width ;// load next row
+ EOR res, res, tmpa ;// correct sign
+
+ STR res, [mb], #16 ;// next row (mb)
+
+
+ ;// tmp2 = |a4|a3|a2|a1|
+ ;// tmp3 = |c4|c3|c2|c1|
+ ;// tmp4 = |g4|g3|g2|g1|
+ ;// tmp5 = |m4|m3|m2|m1|
+ ;// tmp6 = |r4|r3|r2|r1|
+ ;// tmp1 = |t4|t3|t2|t1|
+
+ ;// second four pixels
+ UXTB16 tmpa, tmp4 ;// |g3|g1|
+ UXTAB16 tmpa, tmpa, tmp5 ;// |g3+m3|g1+m1|
+ UXTB16 tmpb, tmp3 ;// |c3|c1|
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTAB16 tmpb, tmpb, tmp6 ;// |c3+r3|c1+r1|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpa, tmpa, tmp2 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp1 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR res, = 0x00FF00FF
+ UXTB16 tmpa, tmp4, ROR #8 ;// |g4|g2|
+ UXTAB16 tmpa, tmpa, tmp5, ROR #8 ;// |g4+m4|g2+m2|
+ AND res, res, tmpb, LSR #5 ;// mask and divide by 32
+
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTB16 tmpb, tmp3, ROR #8 ;// |c4|c2|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpb, tmpb, tmp6, ROR #8 ;// |c4+r4|c2+r2|
+ UXTAB16 tmpa, tmpa, tmp2, ROR #8 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR tmp2, [mb]
+ LDR tmpa, = 0xFF00FF00
+ MVN tmp2, tmp2
+
+ AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divide by 32
+ ORR res, res, tmpa
+ LDR tmpa, = 0x80808080
+ UHSUB8 res, res, tmp2 ;// bilinear interpolation
+ LDR tmp2, [ref], width ;// load next row
+ EOR res, res, tmpa ;// correct sign
+ STR res, [mb], #16 ;// next row
+
+ ;// tmp3 = |a4|a3|a2|a1|
+ ;// tmp4 = |c4|c3|c2|c1|
+ ;// tmp5 = |g4|g3|g2|g1|
+ ;// tmp6 = |m4|m3|m2|m1|
+ ;// tmp1 = |r4|r3|r2|r1|
+ ;// tmp2 = |t4|t3|t2|t1|
+
+ ;// third four pixels
+ UXTB16 tmpa, tmp5 ;// |g3|g1|
+ UXTAB16 tmpa, tmpa, tmp6 ;// |g3+m3|g1+m1|
+ UXTB16 tmpb, tmp4 ;// |c3|c1|
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTAB16 tmpb, tmpb, tmp1 ;// |c3+r3|c1+r1|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpa, tmpa, tmp3 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp2 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR res, = 0x00FF00FF
+ UXTB16 tmpa, tmp5, ROR #8 ;// |g4|g2|
+ UXTAB16 tmpa, tmpa, tmp6, ROR #8 ;// |g4+m4|g2+m2|
+ AND res, res, tmpb, LSR #5 ;// mask and divide by 32
+
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTB16 tmpb, tmp4, ROR #8 ;// |c4|c2|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpb, tmpb, tmp1, ROR #8 ;// |c4+r4|c2+r2|
+ UXTAB16 tmpa, tmpa, tmp3, ROR #8 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp2, ROR #8 ;// 16+20(G+M)+A+T
+
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR tmp3, [mb]
+ LDR tmpa, = 0xFF00FF00
+ MVN tmp3, tmp3
+
+ AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divide by 32
+ ORR res, res, tmpa
+ LDR tmpa, = 0x80808080
+ UHSUB8 res, res, tmp3 ;// bilinear interpolation
+ LDR tmp3, [ref] ;// load next row
+ EOR res, res, tmpa ;// correct sign
+ STR res, [mb], #16 ;// next row
+
+ ;// tmp4 = |a4|a3|a2|a1|
+ ;// tmp5 = |c4|c3|c2|c1|
+ ;// tmp6 = |g4|g3|g2|g1|
+ ;// tmp1 = |m4|m3|m2|m1|
+ ;// tmp2 = |r4|r3|r2|r1|
+ ;// tmp3 = |t4|t3|t2|t1|
+
+ ;// fourth four pixels
+ UXTB16 tmpa, tmp6 ;// |g3|g1|
+ UXTAB16 tmpa, tmpa, tmp1 ;// |g3+m3|g1+m1|
+ UXTB16 tmpb, tmp5 ;// |c3|c1|
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTAB16 tmpb, tmpb, tmp2 ;// |c3+r3|c1+r1|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpa, tmpa, tmp4 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp3 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR res, = 0x00FF00FF
+ UXTB16 tmpa, tmp6, ROR #8 ;// |g4|g2|
+ UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// |g4+m4|g2+m2|
+ AND res, res, tmpb, LSR #5 ;// mask and divide by 32
+
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTB16 tmpb, tmp5, ROR #8 ;// |c4|c2|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpb, tmpb, tmp2, ROR #8 ;// |c4+r4|c2+r2|
+ UXTAB16 tmpa, tmpa, tmp4, ROR #8 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp3, ROR #8 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR tmp5, [mb]
+ LDR tmp4, = 0xFF00FF00
+ MVN tmp5, tmp5
+
+ AND tmpa, tmp4, tmpb, LSL #3 ;// mask and divide by 32
+ ORR res, res, tmpa
+ LDR tmpa, = 0x80808080
+ UHSUB8 res, res, tmp5 ;// bilinear interpolation
+
+ ;// decrement loop_x counter
+ SUBS count, count, #4<<28 ;// decrement x loop counter
+
+ ;// calculate "ref" address for next round
+ SUB ref, ref, width, LSL #3 ;// ref -= 8*width;
+ ADD ref, ref, #4 ;// next column (4 pixels)
+
+ EOR res, res, tmpa ;// correct sign
+ STR res, [mb], #-44
+
+ BCS loop_x
+
+ ADDS mb, mb, #64 ;// set Carry=0
+ ADD ref, ref, width, LSL #2 ;// ref += 4*width
+ AND tmp6, count, #0x00F00000 ;// partWidth-1
+ SBC ref, ref, tmp6, LSR #20 ;// -(partWidth-1)-1
+ SBC mb, mb, tmp6, LSR #20 ;// -(partWidth-1)-1
+
+ ADDS count, count, #0xC << 24 ;// decrement y loop counter
+ BGE loop_y
+
+ ADD sp, sp, #0x1f4
+ LDMFD sp!, {r4-r11, pc}
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_mid_hor.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_mid_hor.s
new file mode 100755
index 0000000..a81aed7
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_mid_hor.s
@@ -0,0 +1,163 @@
+; 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.
+
+;-------------------------------------------------------------------------------
+;--
+;-- Abstract : ARMv6 optimized version horizontal part of
+;-- h264bsdInterpolateMid functions
+;--
+;-------------------------------------------------------------------------------
+
+
+ IF :DEF: H264DEC_WINASM
+ ;// We dont use REQUIRE8 and PRESERVE8 for winasm
+ ELSE
+ REQUIRE8
+ PRESERVE8
+ ENDIF
+
+ AREA |.text|, CODE
+
+
+;// Register allocation
+
+ref RN 0 ;// pointer to current position in reference image
+mb RN 1 ;// pointer to current position in interpolated mb
+count RN 2 ;// bit-packed width and count values
+
+x_2_0 RN 4
+x_3_1 RN 5
+x_6_4 RN 6
+x_7_5 RN 7
+
+tmp1 RN 8
+tmp2 RN 9
+tmp3 RN 10
+tmp4 RN 11
+
+mult_20_01 RN 12 ;// [20, 1]
+mult_20_m5 RN 14 ;// [20, -5]
+
+
+ EXPORT h264bsdInterpolateMidHorPart
+
+;// Horizontal filter approach
+;//
+;// Basic idea in horizontal filtering is to adjust coefficients
+;// like below. Calculation is done with 16-bit maths.
+;//
+;// Reg x_2_0 x_3_1 x_6_4 x_7_5 x_2_0
+;// [ 2 0 ] [ 3 1 ] [ 6 4 ] [ 7 5 ] [ 10 8 ] ...
+;// y_0 = 20 1 20 -5 -5 1
+;// y_1 = -5 20 1 1 20 -5
+;// y_2 = 1 -5 -5 20 1 20
+;// y_3 = 1 20 -5 -5 20 1
+
+
+h264bsdInterpolateMidHorPart
+ STMFD sp!, {r4-r11, lr}
+
+ ;// pack values to count register
+ ;// [31:28] loop_x (partWidth-1)
+ ;// [27:24] loop_y (partHeight-1)
+ ;// [23:20] partWidth-1
+ ;// [19:16] partHeight-1
+ ;// [15:00] width
+
+
+ LDR mult_20_01, = 0x00140001
+ LDR mult_20_m5, = 0x0014FFFB
+ AND tmp3, count, #0x000F0000 ;// partWidth-1
+loop_y
+ LDR x_3_1, [ref, #-8]
+ ADD count, count, tmp3, LSL #12
+ LDR x_7_5, [ref, #-4]
+ UXTB16 x_2_0, x_3_1
+ UXTB16 x_3_1, x_3_1, ROR #8
+ UXTB16 x_6_4, x_7_5
+
+loop_x
+ UXTB16 x_7_5, x_7_5, ROR #8
+
+ SMUAD tmp1, x_2_0, mult_20_01
+ SMULTB tmp2, x_2_0, mult_20_m5
+ SMULTB tmp3, x_2_0, mult_20_01
+ SMULTB tmp4, x_3_1, mult_20_01
+
+ SMLAD tmp1, x_3_1, mult_20_m5, tmp1
+ SMLAD tmp2, x_3_1, mult_20_01, tmp2
+ SMLATB tmp3, x_3_1, mult_20_m5, tmp3
+ LDR x_3_1, [ref], #4
+ SMLAD tmp4, x_6_4, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_6_4, mult_20_m5, tmp1
+ SMLADX tmp2, x_6_4, mult_20_01, tmp2
+ SMLADX tmp3, x_6_4, mult_20_m5, tmp3
+ SMLADX tmp4, x_7_5, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_7_5, mult_20_01, tmp1
+ SMLABB tmp2, x_7_5, mult_20_m5, tmp2
+ UXTB16 x_2_0, x_3_1
+ SMLADX tmp3, x_7_5, mult_20_01, tmp3
+ SMLABB tmp4, x_2_0, mult_20_01, tmp4
+
+ SUBS count, count, #4<<28
+ STR tmp1, [mb], #4
+ STR tmp2, [mb], #4
+ STR tmp3, [mb], #4
+ STR tmp4, [mb], #4
+ BCC next_y
+
+ UXTB16 x_3_1, x_3_1, ROR #8
+
+ SMUAD tmp1, x_6_4, mult_20_01
+ SMULTB tmp2, x_6_4, mult_20_m5
+ SMULTB tmp3, x_6_4, mult_20_01
+ SMULTB tmp4, x_7_5, mult_20_01
+
+ SMLAD tmp1, x_7_5, mult_20_m5, tmp1
+ SMLAD tmp2, x_7_5, mult_20_01, tmp2
+ SMLATB tmp3, x_7_5, mult_20_m5, tmp3
+ LDR x_7_5, [ref], #4
+ SMLAD tmp4, x_2_0, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_2_0, mult_20_m5, tmp1
+ SMLADX tmp2, x_2_0, mult_20_01, tmp2
+ SMLADX tmp3, x_2_0, mult_20_m5, tmp3
+ SMLADX tmp4, x_3_1, mult_20_m5, tmp4
+
+ SMLABB tmp1, x_3_1, mult_20_01, tmp1
+ SMLABB tmp2, x_3_1, mult_20_m5, tmp2
+ UXTB16 x_6_4, x_7_5
+ SMLADX tmp3, x_3_1, mult_20_01, tmp3
+ SMLABB tmp4, x_6_4, mult_20_01, tmp4
+
+ SUBS count, count, #4<<28
+ STR tmp1, [mb], #4
+ STR tmp2, [mb], #4
+ STR tmp3, [mb], #4
+ STR tmp4, [mb], #4
+ BCS loop_x
+
+next_y
+ AND tmp3, count, #0x000F0000 ;// partWidth-1
+ SMLABB ref, count, mult_20_01, ref ;// +width
+ SBC ref, ref, tmp3, LSR #16 ;// -(partWidth-1)-1
+ ADDS count, count, #(1<<28)-(1<<20)
+ BGE loop_y
+
+ LDMFD sp!, {r4-r11, pc}
+
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_half.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_half.s
new file mode 100755
index 0000000..244fc6f
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_half.s
@@ -0,0 +1,347 @@
+; 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.
+
+;-------------------------------------------------------------------------------
+;--
+;-- Abstract : ARMv6 optimized version of h264bsdInterpolateVerHalf function
+;--
+;-------------------------------------------------------------------------------
+
+
+ IF :DEF: H264DEC_WINASM
+ ;// We dont use REQUIRE8 and PRESERVE8 for winasm
+ ELSE
+ REQUIRE8
+ PRESERVE8
+ ENDIF
+
+ AREA |.text|, CODE
+
+;// h264bsdInterpolateVerHalf register allocation
+
+ref RN 0
+
+mb RN 1
+buff RN 1
+
+count RN 2
+x0 RN 2
+
+res RN 3
+y0 RN 3
+
+tmp1 RN 4
+
+tmp2 RN 5
+height RN 5
+
+tmp3 RN 6
+partW RN 6
+
+tmp4 RN 7
+partH RN 7
+
+tmp5 RN 8
+tmp6 RN 9
+
+tmpa RN 10
+tmpb RN 11
+width RN 12
+
+plus16 RN 14
+
+
+;// function exports and imports
+
+ IMPORT h264bsdFillBlock
+
+ EXPORT h264bsdInterpolateVerHalf
+
+;// Approach to vertical interpolation
+;//
+;// Interpolation is done by using 32-bit loads and stores
+;// and by using 16 bit arithmetic. 4x4 block is processed
+;// in each round.
+;//
+;// |a_11|a_11|a_11|a_11|...|a_1n|a_1n|a_1n|a_1n|
+;// |b_11|b_11|b_11|b_11|...|b_1n|b_1n|b_1n|b_1n|
+;// |c_11|c_11|c_11|c_11|...|c_1n|c_1n|c_1n|c_1n|
+;// |d_11|d_11|d_11|d_11|...|d_1n|d_1n|d_1n|d_1n|
+;// ..
+;// ..
+;// |a_m1|a_m1|a_m1|a_m1|...
+;// |b_m1|b_m1|b_m1|b_m1|...
+;// |c_m1|c_m1|c_m1|c_m1|...
+;// |d_m1|d_m1|d_m1|d_m1|...
+
+h264bsdInterpolateVerHalf
+ STMFD sp!, {r0-r11, lr}
+ SUB sp, sp, #0x1e4
+
+ CMP x0, #0
+ BLT do_fill ;// (x0 < 0)
+ LDR partW, [sp,#0x220] ;// partWidth
+ ADD tmp5, x0, partW ;// (x0+partWidth)
+ LDR width, [sp,#0x218] ;// width
+ CMP tmp5, width
+ BHI do_fill ;// (x0+partW)>width
+
+ CMP y0, #0
+ BLT do_fill ;// (y0 < 0)
+ LDR partH, [sp,#0x224] ;// partHeight
+ ADD tmp6, y0, partH ;// (y0+partHeight)
+ ADD tmp6, tmp6, #5 ;// (y0+partH+5)
+ LDR height, [sp,#0x21c] ;// height
+ CMP tmp6, height
+ BLS skip_fill ;// no overfill needed
+
+
+do_fill
+ LDR partH, [sp,#0x224] ;// partHeight
+ ADD tmp5, partH, #5 ;// r2 = partH + 5;
+ LDR height, [sp,#0x21c] ;// height
+ LDR partW, [sp,#0x220] ;// partWidth
+ STMIB sp, {height, partW} ;// sp+4 = height, sp+8 = partWidth
+ STR tmp5, [sp,#0xc] ;// sp+c partHeight+5
+ STR partW, [sp,#0x10] ;// sp+10 = partWidth
+ LDR width, [sp,#0x218] ;// width
+ STR width, [sp,#0] ;// sp+0 = width
+ ADD buff, sp, #0x28 ;// buff = p1[21*21/4+1]
+ BL h264bsdFillBlock
+
+ MOV x0, #0
+ STR x0,[sp,#0x1ec] ;// x0 = 0
+ STR x0,[sp,#0x1f0] ;// y0 = 0
+ ADD ref,sp,#0x28 ;// ref = p1
+ STR partW, [sp,#0x218]
+
+
+skip_fill
+ LDR x0 ,[sp,#0x1ec] ;// x0
+ LDR y0 ,[sp,#0x1f0] ;// y0
+ LDR width, [sp,#0x218] ;// width
+ MLA tmp6, width, y0, x0 ;// y0*width+x0
+ ADD ref, ref, tmp6 ;// ref += y0*width+x0
+ LDR mb, [sp, #0x1e8] ;// mb
+
+ ADD count, partW, partH, LSL #16 ;// |partH|partW|
+ LDR tmp5, = 0x00010001
+ SSUB16 count, count, tmp5; ;// |partH-1|partW-1|
+ LDR plus16, = 0x00100010
+
+ AND tmp1, count, #0x000000FF ;// partWidth
+
+
+loop_y
+ ADD count, count, tmp1, LSL #24 ;// partWidth-1 to top byte
+
+loop_x
+ LDR tmp1, [ref], width ;// |a4|a3|a2|a1|
+ LDR tmp2, [ref], width ;// |c4|c3|c2|c1|
+ LDR tmp3, [ref], width ;// |g4|g3|g2|g1|
+ LDR tmp4, [ref], width ;// |m4|m3|m2|m1|
+ LDR tmp5, [ref], width ;// |r4|r3|r2|r1|
+ LDR tmp6, [ref], width ;// |t4|t3|t2|t1|
+
+ ;// first four pixels
+ UXTB16 tmpa, tmp3 ;// |g3|g1|
+ UXTAB16 tmpa, tmpa, tmp4 ;// |g3+m3|g1+m1|
+ UXTB16 tmpb, tmp2 ;// |c3|c1|
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+
+ UXTAB16 tmpb, tmpb, tmp5 ;// |c3+r3|c1+r1|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpa, tmpa, tmp1 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp6 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR res, = 0x00FF00FF
+ UXTB16 tmpa, tmp3, ROR #8 ;// |g4|g2|
+ UXTAB16 tmpa, tmpa, tmp4, ROR #8 ;// |g4+m4|g2+m2|
+ AND res, res, tmpb, LSR #5 ;// mask and divide by 32
+
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTB16 tmpb, tmp2, ROR #8 ;// |c4|c2|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpb, tmpb, tmp5, ROR #8 ;// |c4+r4|c2+r2|
+ UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp6, ROR #8 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR tmp1, [ref], width
+ LDR tmpa, = 0xFF00FF00
+
+ AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divede by 32
+ ORR res, res, tmpa
+ STR res, [mb], #16 ;// next row (mb)
+
+ ;// tmp2 = |a4|a3|a2|a1|
+ ;// tmp3 = |c4|c3|c2|c1|
+ ;// tmp4 = |g4|g3|g2|g1|
+ ;// tmp5 = |m4|m3|m2|m1|
+ ;// tmp6 = |r4|r3|r2|r1|
+ ;// tmp1 = |t4|t3|t2|t1|
+
+ ;// second four pixels
+ UXTB16 tmpa, tmp4 ;// |g3|g1|
+ UXTAB16 tmpa, tmpa, tmp5 ;// |g3+m3|g1+m1|
+ UXTB16 tmpb, tmp3 ;// |c3|c1|
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTAB16 tmpb, tmpb, tmp6 ;// |c3+r3|c1+r1|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpa, tmpa, tmp2 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp1 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR res, = 0x00FF00FF
+ UXTB16 tmpa, tmp4, ROR #8 ;// |g4|g2|
+ UXTAB16 tmpa, tmpa, tmp5, ROR #8 ;// |g4+m4|g2+m2|
+ AND res, res, tmpb, LSR #5 ;// mask and divide by 32
+
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTB16 tmpb, tmp3, ROR #8 ;// |c4|c2|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpb, tmpb, tmp6, ROR #8 ;// |c4+r4|c2+r2|
+ UXTAB16 tmpa, tmpa, tmp2, ROR #8 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR tmp2, [ref], width
+ LDR tmpa, = 0xFF00FF00
+
+ AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divide by 32
+ ORR res, res, tmpa
+ STR res, [mb], #16 ;// next row
+
+ ;// tmp3 = |a4|a3|a2|a1|
+ ;// tmp4 = |c4|c3|c2|c1|
+ ;// tmp5 = |g4|g3|g2|g1|
+ ;// tmp6 = |m4|m3|m2|m1|
+ ;// tmp1 = |r4|r3|r2|r1|
+ ;// tmp2 = |t4|t3|t2|t1|
+
+ ;// third four pixels
+ UXTB16 tmpa, tmp5 ;// |g3|g1|
+ UXTAB16 tmpa, tmpa, tmp6 ;// |g3+m3|g1+m1|
+ UXTB16 tmpb, tmp4 ;// |c3|c1|
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTAB16 tmpb, tmpb, tmp1 ;// |c3+r3|c1+r1|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpa, tmpa, tmp3 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp2 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR res, = 0x00FF00FF
+ UXTB16 tmpa, tmp5, ROR #8 ;// |g4|g2|
+ UXTAB16 tmpa, tmpa, tmp6, ROR #8 ;// |g4+m4|g2+m2|
+ AND res, res, tmpb, LSR #5 ;// mask and divide by 32
+
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTB16 tmpb, tmp4, ROR #8 ;// |c4|c2|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpb, tmpb, tmp1, ROR #8 ;// |c4+r4|c2+r2|
+ UXTAB16 tmpa, tmpa, tmp3, ROR #8 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp2, ROR #8 ;// 16+20(G+M)+A+T
+
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR tmp3, [ref]
+ LDR tmpa, = 0xFF00FF00
+
+ ;// decrement loop_x counter
+ SUBS count, count, #4<<24 ;// (partWidth-1) -= 4;
+
+ AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divide by 32
+ ORR res, res, tmpa
+ STR res, [mb], #16 ;// next row
+
+ ;// tmp4 = |a4|a3|a2|a1|
+ ;// tmp5 = |c4|c3|c2|c1|
+ ;// tmp6 = |g4|g3|g2|g1|
+ ;// tmp1 = |m4|m3|m2|m1|
+ ;// tmp2 = |r4|r3|r2|r1|
+ ;// tmp3 = |t4|t3|t2|t1|
+
+ ;// fourth four pixels
+ UXTB16 tmpa, tmp6 ;// |g3|g1|
+ UXTAB16 tmpa, tmpa, tmp1 ;// |g3+m3|g1+m1|
+ UXTB16 tmpb, tmp5 ;// |c3|c1|
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTAB16 tmpb, tmpb, tmp2 ;// |c3+r3|c1+r1|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpa, tmpa, tmp4 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp3 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR res, = 0x00FF00FF
+ UXTB16 tmpa, tmp6, ROR #8 ;// |g4|g2|
+ UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// |g4+m4|g2+m2|
+ AND res, res, tmpb, LSR #5 ;// mask and divide by 32
+
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTB16 tmpb, tmp5, ROR #8 ;// |c4|c2|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpb, tmpb, tmp2, ROR #8 ;// |c4+r4|c2+r2|
+ UXTAB16 tmpa, tmpa, tmp4, ROR #8 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp3, ROR #8 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR tmp4, = 0xFF00FF00
+
+ ;// calculate "ref" address for next round
+ SUB ref, ref, width, LSL #3 ;// ref -= 8*width;
+ ADD ref, ref, #4; ;// next column (4 pixels)
+ AND tmpa, tmp4, tmpb, LSL #3 ;// mask and divide by 32
+ ORR res, res, tmpa
+ STR res, [mb], #-44
+
+ BCS loop_x
+
+ ADDS count, count, #252<<16 ;// (partHeight-1) -= 4;
+ ADD ref, ref, width, LSL #2 ;// ref += 4*width
+ AND tmp1, count, #0x000000FF ;// partWidth-1
+ ADD tmp2, tmp1, #1 ;// partWidth
+ SUB ref, ref, tmp2 ;// ref -= partWidth
+ ADD mb, mb, #64;
+ SUB mb, mb, tmp2; ;// mb -= partWidth
+ BGE loop_y
+
+ ADD sp,sp,#0x1f4
+ LDMFD sp!, {r4-r11, pc}
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_quarter.s b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_quarter.s
new file mode 100755
index 0000000..5266c85
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/h264bsd_interpolate_ver_quarter.s
@@ -0,0 +1,374 @@
+; 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.
+
+;-------------------------------------------------------------------------------
+;--
+;-- Abstract : ARMv6 optimized version of h264bsdInterpolateVerQuarter function
+;--
+;-------------------------------------------------------------------------------
+
+ IF :DEF: H264DEC_WINASM
+ ;// We dont use REQUIRE8 and PRESERVE8 for winasm
+ ELSE
+ REQUIRE8
+ PRESERVE8
+ ENDIF
+
+ AREA |.text|, CODE
+
+;// h264bsdInterpolateVerQuarter register allocation
+
+ref RN 0
+
+mb RN 1
+buff RN 1
+
+count RN 2
+x0 RN 2
+
+res RN 3
+y0 RN 3
+
+tmp1 RN 4
+
+tmp2 RN 5
+height RN 5
+
+tmp3 RN 6
+partW RN 6
+
+tmp4 RN 7
+partH RN 7
+
+tmp5 RN 8
+tmp6 RN 9
+
+tmpa RN 10
+tmpb RN 11
+width RN 12
+
+plus16 RN 14
+
+
+;// function exports and imports
+
+ IMPORT h264bsdFillBlock
+
+ EXPORT h264bsdInterpolateVerQuarter
+
+;// Approach to vertical interpolation
+;//
+;// Interpolation is done by using 32-bit loads and stores
+;// and by using 16 bit arithmetic. 4x4 block is processed
+;// in each round.
+;//
+;// |a_11|a_11|a_11|a_11|...|a_1n|a_1n|a_1n|a_1n|
+;// |b_11|b_11|b_11|b_11|...|b_1n|b_1n|b_1n|b_1n|
+;// |c_11|c_11|c_11|c_11|...|c_1n|c_1n|c_1n|c_1n|
+;// |d_11|d_11|d_11|d_11|...|d_1n|d_1n|d_1n|d_1n|
+;// ..
+;// ..
+;// |a_m1|a_m1|a_m1|a_m1|...
+;// |b_m1|b_m1|b_m1|b_m1|...
+;// |c_m1|c_m1|c_m1|c_m1|...
+;// |d_m1|d_m1|d_m1|d_m1|...
+
+h264bsdInterpolateVerQuarter
+ STMFD sp!, {r0-r11, lr}
+ SUB sp, sp, #0x1e4
+
+ CMP x0, #0
+ BLT do_fill ;// (x0 < 0)
+ LDR partW, [sp,#0x220] ;// partWidth
+ ADD tmp5, x0, partW ;// (x0+partWidth)
+ LDR width, [sp,#0x218] ;// width
+ CMP tmp5, width
+ BHI do_fill ;// (x0+partW)>width
+
+ CMP y0, #0
+ BLT do_fill ;// (y0 < 0)
+ LDR partH, [sp,#0x224] ;// partHeight
+ ADD tmp6, y0, partH ;// (y0+partHeight)
+ ADD tmp6, tmp6, #5 ;// (y0+partH+5)
+ LDR height, [sp,#0x21c] ;// height
+ CMP tmp6, height
+ BLS skip_fill ;// no overfill needed
+
+
+do_fill
+ LDR partH, [sp,#0x224] ;// partHeight
+ ADD tmp5, partH, #5 ;// r2 = partH + 5;
+ LDR height, [sp,#0x21c] ;// height
+ LDR partW, [sp,#0x220] ;// partWidth
+ STMIB sp, {height, partW} ;// sp+4 = height, sp+8 = partWidth
+ STR tmp5, [sp,#0xc] ;// sp+c partHeight+5
+ STR partW, [sp,#0x10] ;// sp+10 = partWidth
+ LDR width, [sp,#0x218] ;// width
+ STR width, [sp,#0] ;// sp+0 = width
+ ADD buff, sp, #0x28 ;// buff = p1[21*21/4+1]
+ BL h264bsdFillBlock
+
+ MOV x0, #0
+ STR x0,[sp,#0x1ec] ;// x0 = 0
+ STR x0,[sp,#0x1f0] ;// y0 = 0
+ ADD ref,sp,#0x28 ;// ref = p1
+ STR partW, [sp,#0x218]
+
+
+skip_fill
+ LDR x0 ,[sp,#0x1ec] ;// x0
+ LDR y0 ,[sp,#0x1f0] ;// y0
+ LDR width, [sp,#0x218] ;// width
+ MLA tmp6, width, y0, x0 ;// y0*width+x0
+ ADD ref, ref, tmp6 ;// ref += y0*width+x0
+ LDR mb, [sp, #0x1e8] ;// mb
+
+ ADD count, partW, partH, LSL #8 ;// |xx|xx|partH|partW|
+ LDR tmp5, = 0x00010100
+ RSB count, tmp5, count, LSL #8 ;// |xx|partH-1|partW-1|xx|
+ LDR tmp2, [sp, #0x228] ;// verOffset
+ ADD count, count, tmp2 ;// |xx|partH-1|partW-1|verOffset|
+ LDR plus16, = 0x00100010
+
+ AND tmp1, count, #0x0000FF00 ;// partWidth
+
+
+loop_y
+ ADD count, count, tmp1, LSL #16 ;// partWidth-1 to top byte
+
+loop_x
+ LDR tmp1, [ref], width ;// |a4|a3|a2|a1|
+ LDR tmp2, [ref], width ;// |c4|c3|c2|c1|
+ LDR tmp3, [ref], width ;// |g4|g3|g2|g1|
+ LDR tmp4, [ref], width ;// |m4|m3|m2|m1|
+ LDR tmp5, [ref], width ;// |r4|r3|r2|r1|
+ LDR tmp6, [ref], width ;// |t4|t3|t2|t1|
+
+ ;// first four pixels
+ UXTB16 tmpa, tmp3 ;// |g3|g1|
+ UXTAB16 tmpa, tmpa, tmp4 ;// |g3+m3|g1+m1|
+ UXTB16 tmpb, tmp2 ;// |c3|c1|
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+
+ UXTAB16 tmpb, tmpb, tmp5 ;// |c3+r3|c1+r1|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpa, tmpa, tmp1 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp6 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR res, = 0x00FF00FF
+ UXTB16 tmpa, tmp3, ROR #8 ;// |g4|g2|
+ UXTAB16 tmpa, tmpa, tmp4, ROR #8 ;// |g4+m4|g2+m2|
+ AND res, res, tmpb, LSR #5 ;// mask and divide by 32
+
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTB16 tmpb, tmp2, ROR #8 ;// |c4|c2|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpb, tmpb, tmp5, ROR #8 ;// |c4+r4|c2+r2|
+ UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp6, ROR #8 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ MOVS tmp1, count, LSL #31 ;// update flags (verOffset)
+ LDR tmpa, = 0xFF00FF00
+ MVNEQ tmp1, tmp3 ;// select verOffset=0
+ MVNNE tmp1, tmp4 ;// select verOffset=1
+ AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divede by 32
+ ORR res, res, tmpa
+
+ LDR tmpa, = 0x80808080
+ UHSUB8 res, res, tmp1 ;// bilinear interpolation
+ LDR tmp1, [ref], width ;// load next row
+ EOR res, res, tmpa ;// correct sign
+
+ STR res, [mb], #16 ;// next row (mb)
+
+
+ ;// tmp2 = |a4|a3|a2|a1|
+ ;// tmp3 = |c4|c3|c2|c1|
+ ;// tmp4 = |g4|g3|g2|g1|
+ ;// tmp5 = |m4|m3|m2|m1|
+ ;// tmp6 = |r4|r3|r2|r1|
+ ;// tmp1 = |t4|t3|t2|t1|
+
+ ;// second four pixels
+ UXTB16 tmpa, tmp4 ;// |g3|g1|
+ UXTAB16 tmpa, tmpa, tmp5 ;// |g3+m3|g1+m1|
+ UXTB16 tmpb, tmp3 ;// |c3|c1|
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTAB16 tmpb, tmpb, tmp6 ;// |c3+r3|c1+r1|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpa, tmpa, tmp2 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp1 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR res, = 0x00FF00FF
+ UXTB16 tmpa, tmp4, ROR #8 ;// |g4|g2|
+ UXTAB16 tmpa, tmpa, tmp5, ROR #8 ;// |g4+m4|g2+m2|
+ AND res, res, tmpb, LSR #5 ;// mask and divide by 32
+
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTB16 tmpb, tmp3, ROR #8 ;// |c4|c2|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpb, tmpb, tmp6, ROR #8 ;// |c4+r4|c2+r2|
+ UXTAB16 tmpa, tmpa, tmp2, ROR #8 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR tmpa, = 0xFF00FF00
+ MVNEQ tmp2, tmp4 ;// select verOffset=0
+ MVNNE tmp2, tmp5 ;// select verOffset=1
+
+ AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divide by 32
+ ORR res, res, tmpa
+ LDR tmpa, = 0x80808080
+ UHSUB8 res, res, tmp2 ;// bilinear interpolation
+ LDR tmp2, [ref], width ;// load next row
+ EOR res, res, tmpa ;// correct sign
+ STR res, [mb], #16 ;// next row
+
+ ;// tmp3 = |a4|a3|a2|a1|
+ ;// tmp4 = |c4|c3|c2|c1|
+ ;// tmp5 = |g4|g3|g2|g1|
+ ;// tmp6 = |m4|m3|m2|m1|
+ ;// tmp1 = |r4|r3|r2|r1|
+ ;// tmp2 = |t4|t3|t2|t1|
+
+ ;// third four pixels
+ UXTB16 tmpa, tmp5 ;// |g3|g1|
+ UXTAB16 tmpa, tmpa, tmp6 ;// |g3+m3|g1+m1|
+ UXTB16 tmpb, tmp4 ;// |c3|c1|
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTAB16 tmpb, tmpb, tmp1 ;// |c3+r3|c1+r1|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpa, tmpa, tmp3 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp2 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR res, = 0x00FF00FF
+ UXTB16 tmpa, tmp5, ROR #8 ;// |g4|g2|
+ UXTAB16 tmpa, tmpa, tmp6, ROR #8 ;// |g4+m4|g2+m2|
+ AND res, res, tmpb, LSR #5 ;// mask and divide by 32
+
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTB16 tmpb, tmp4, ROR #8 ;// |c4|c2|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpb, tmpb, tmp1, ROR #8 ;// |c4+r4|c2+r2|
+ UXTAB16 tmpa, tmpa, tmp3, ROR #8 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp2, ROR #8 ;// 16+20(G+M)+A+T
+
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR tmpa, = 0xFF00FF00
+ MVNEQ tmp3, tmp5 ;// select verOffset=0
+ MVNNE tmp3, tmp6 ;// select verOffset=1
+
+ AND tmpa, tmpa, tmpb, LSL #3 ;// mask and divide by 32
+ ORR res, res, tmpa
+ LDR tmpa, = 0x80808080
+ UHSUB8 res, res, tmp3 ;// bilinear interpolation
+ LDR tmp3, [ref] ;// load next row
+ EOR res, res, tmpa ;// correct sign
+ STR res, [mb], #16 ;// next row
+
+ ;// tmp4 = |a4|a3|a2|a1|
+ ;// tmp5 = |c4|c3|c2|c1|
+ ;// tmp6 = |g4|g3|g2|g1|
+ ;// tmp1 = |m4|m3|m2|m1|
+ ;// tmp2 = |r4|r3|r2|r1|
+ ;// tmp3 = |t4|t3|t2|t1|
+
+ ;// fourth four pixels
+ UXTB16 tmpa, tmp6 ;// |g3|g1|
+ UXTAB16 tmpa, tmpa, tmp1 ;// |g3+m3|g1+m1|
+ UXTB16 tmpb, tmp5 ;// |c3|c1|
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTAB16 tmpb, tmpb, tmp2 ;// |c3+r3|c1+r1|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpa, tmpa, tmp4 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp3 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR res, = 0x00FF00FF
+ UXTB16 tmpa, tmp6, ROR #8 ;// |g4|g2|
+ UXTAB16 tmpa, tmpa, tmp1, ROR #8 ;// |g4+m4|g2+m2|
+ AND res, res, tmpb, LSR #5 ;// mask and divide by 32
+
+ ADD tmpa, tmpa, tmpa, LSL #2 ;// 5(G+M)
+ UXTB16 tmpb, tmp5, ROR #8 ;// |c4|c2|
+ ADD tmpa, plus16, tmpa, LSL #2 ;// 16+20(G+M)
+ UXTAB16 tmpb, tmpb, tmp2, ROR #8 ;// |c4+r4|c2+r2|
+ UXTAB16 tmpa, tmpa, tmp4, ROR #8 ;// 16+20(G+M)+A
+ UXTAB16 tmpa, tmpa, tmp3, ROR #8 ;// 16+20(G+M)+A+T
+
+ ADD tmpb, tmpb, tmpb, LSL #2 ;// 5(C+R)
+ SSUB16 tmpa, tmpa, tmpb ;// 16+20(G+M)+(A+T)-5(C+R)
+
+ USAT16 tmpb, #13, tmpa ;// saturate
+ LDR tmp4, = 0xFF00FF00
+ MVNEQ tmp5, tmp6 ;// select verOffset=0
+ MVNNE tmp5, tmp1 ;// select verOffset=1
+
+ AND tmpa, tmp4, tmpb, LSL #3 ;// mask and divide by 32
+ ORR res, res, tmpa
+ LDR tmpa, = 0x80808080
+ UHSUB8 res, res, tmp5 ;// bilinear interpolation
+
+ ;// decrement loop_x counter
+ SUBS count, count, #4<<24 ;// (partWidth-1) -= 4;
+
+ ;// calculate "ref" address for next round
+ SUB ref, ref, width, LSL #3 ;// ref -= 8*width;
+ ADD ref, ref, #4; ;// next column (4 pixels)
+
+ EOR res, res, tmpa ;// correct sign
+ STR res, [mb], #-44
+
+ BCS loop_x
+
+ ADDS count, count, #252<<16 ;// (partHeight-1) -= 4;
+ ADD ref, ref, width, LSL #2 ;// ref += 4*width
+ AND tmp1, count, #0x0000FF00 ;// partWidth-1
+ MOV tmp2, #1
+ ADD tmp2, tmp2, tmp1, LSR #8 ;// partWidth
+ SUB ref, ref, tmp2 ;// ref -= partWidth
+ ADD mb, mb, #64;
+ SUB mb, mb, tmp2; ;// mb -= partWidth
+ BGE loop_y
+
+ ADD sp,sp,#0x1f4
+ LDMFD sp!, {r4-r11, pc}
+
+ END
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/win_asm.bat b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/win_asm.bat
new file mode 100644
index 0000000..1b8d88c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm11_asm/win_asm.bat
@@ -0,0 +1,15 @@
+echo off
+set ASMFLAGS= -checkreglist -CPU ARM1136 -PreDefine "H264DEC_WINASM SETL {TRUE}"
+set ASM="D:\Program Files\Microsoft Visual Studio 8\VC\ce\bin\x86_arm\armasm"
+echo on
+
+%ASM% %ASMFLAGS% h264bsd_interpolate_chroma_ver.s
+%ASM% %ASMFLAGS% h264bsd_interpolate_chroma_hor.s
+%ASM% %ASMFLAGS% h264bsd_interpolate_hor_half.s
+%ASM% %ASMFLAGS% h264bsd_interpolate_hor_quarter.s
+%ASM% %ASMFLAGS% h264bsd_interpolate_hor_ver_quarter.s
+%ASM% %ASMFLAGS% h264bsd_interpolate_ver_half.s
+%ASM% %ASMFLAGS% h264bsd_interpolate_ver_quarter.s
+
+rem %ASM% %ASMFLAGS% h264bsd_interpolate_chroma_hor_ver.s
+rem %ASM% %ASMFLAGS% h264bsd_interpolate_mid_hor.s
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdClearMbLayer.s b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdClearMbLayer.s
new file mode 100644
index 0000000..db11654
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdClearMbLayer.s
@@ -0,0 +1,66 @@
+;
+; 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.
+;
+
+ REQUIRE8
+ PRESERVE8
+
+ AREA |.text|, CODE
+
+ EXPORT h264bsdClearMbLayer
+
+; Input / output registers
+pMbLayer RN 0
+size RN 1
+pTmp RN 2
+step RN 3
+
+; -- NEON registers --
+
+qZero QN Q0.U8
+
+;/*------------------------------------------------------------------------------
+;
+; Function: h264bsdClearMbLayer
+;
+; Functional description:
+;
+; Inputs:
+;
+; Outputs:
+;
+; Returns:
+;
+;------------------------------------------------------------------------------*/
+
+h264bsdClearMbLayer
+
+ VMOV qZero, #0
+ ADD pTmp, pMbLayer, #16
+ MOV step, #32
+ SUBS size, size, #64
+
+loop
+ VST1 qZero, [pMbLayer], step
+ SUBS size, size, #64
+ VST1 qZero, [pTmp], step
+ VST1 qZero, [pMbLayer], step
+ VST1 qZero, [pTmp], step
+ BCS loop
+
+ BX lr
+ END
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdCountLeadingZeros.s b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdCountLeadingZeros.s
new file mode 100644
index 0000000..c7bd73e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdCountLeadingZeros.s
@@ -0,0 +1,49 @@
+;
+; 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.
+;
+
+ REQUIRE8
+ PRESERVE8
+
+ AREA |.text|, CODE
+
+ EXPORT h264bsdCountLeadingZeros
+
+; Input / output registers
+value RN 0
+
+; -- NEON registers --
+
+;/*------------------------------------------------------------------------------
+;
+; Function: h264bsdCountLeadingZeros
+;
+; Functional description:
+;
+; Inputs:
+;
+; Outputs:
+;
+; Returns:
+;
+;------------------------------------------------------------------------------*/
+
+h264bsdCountLeadingZeros
+
+ CLZ value, value
+ BX lr
+ END
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFillRow7.s b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFillRow7.s
new file mode 100644
index 0000000..5bfac92
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFillRow7.s
@@ -0,0 +1,180 @@
+;
+; 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.
+;
+
+ REQUIRE8
+ PRESERVE8
+
+ AREA |.text|, CODE
+
+ EXPORT h264bsdFillRow7
+
+; Input / output registers
+
+ref RN 0
+fill RN 1
+left RN 2
+tmp2 RN 2
+center RN 3
+right RN 4
+tmp1 RN 5
+
+; -- NEON registers --
+
+qTmp0 QN Q0.U8
+qTmp1 QN Q1.U8
+dTmp0 DN D0.U8
+dTmp1 DN D1.U8
+dTmp2 DN D2.U8
+dTmp3 DN D3.U8
+
+
+;/*------------------------------------------------------------------------------
+;
+; Function: h264bsdFillRow7
+;
+; Functional description:
+;
+; Inputs:
+;
+; Outputs:
+;
+; Returns:
+;
+;------------------------------------------------------------------------------*/
+
+h264bsdFillRow7
+ PUSH {r4-r6,lr}
+ CMP left, #0
+ LDR right, [sp,#0x10]
+ BEQ switch_center
+ LDRB tmp1, [ref,#0]
+
+loop_left
+ SUBS left, left, #1
+ STRB tmp1, [fill], #1
+ BNE loop_left
+
+switch_center
+ ASR tmp2,center,#2
+ CMP tmp2,#9
+ ADDCC pc,pc,tmp2,LSL #2
+ B loop_center
+ B loop_center
+ B case_1
+ B case_2
+ B case_3
+ B case_4
+ B case_5
+ B case_6
+ B case_7
+ B case_8
+;case_8
+; LDR tmp2, [ref], #4
+; SUB center, center, #4
+; STR tmp2, [fill], #4
+;case_7
+; LDR tmp2, [ref], #4
+; SUB center, center, #4
+; STR tmp2, [fill], #4
+;case_6
+; LDR tmp2, [ref], #4
+; SUB center, center, #4
+; STR tmp2, [fill],#4
+;case_5
+; LDR tmp2, [ref], #4
+; SUB center, center, #4
+; STR tmp2, [fill],#4
+;case_4
+; LDR tmp2, [ref],#4
+; SUB center, center, #4
+; STR tmp2, [fill], #4
+;case_3
+; LDR tmp2, [ref],#4
+; SUB center, center, #4
+; STR tmp2, [fill], #4
+;case_2
+; LDR tmp2, [ref],#4
+; SUB center, center, #4
+; STR tmp2, [fill], #4
+;case_1
+; LDR tmp2, [ref],#4
+; SUB center, center, #4
+; STR tmp2, [fill], #4
+
+case_8
+ VLD1 {qTmp0, qTmp1}, [ref]!
+ SUB center, center, #32
+ VST1 qTmp0, [fill]!
+ VST1 qTmp1, [fill]!
+ B loop_center
+case_7
+ VLD1 {dTmp0,dTmp1,dTmp2}, [ref]!
+ SUB center, center, #28
+ LDR tmp2, [ref], #4
+ VST1 {dTmp0,dTmp1,dTmp2}, [fill]!
+ STR tmp2, [fill],#4
+ B loop_center
+case_6
+ VLD1 {dTmp0,dTmp1,dTmp2}, [ref]!
+ SUB center, center, #24
+ VST1 {dTmp0,dTmp1,dTmp2}, [fill]!
+ B loop_center
+case_5
+ VLD1 qTmp0, [ref]!
+ SUB center, center, #20
+ LDR tmp2, [ref], #4
+ VST1 qTmp0, [fill]!
+ STR tmp2, [fill],#4
+ B loop_center
+case_4
+ VLD1 qTmp0, [ref]!
+ SUB center, center, #16
+ VST1 qTmp0, [fill]!
+ B loop_center
+case_3
+ VLD1 dTmp0, [ref]!
+ SUB center, center, #12
+ LDR tmp2, [ref], #4
+ VST1 dTmp0, [fill]!
+ STR tmp2, [fill],#4
+ B loop_center
+case_2
+ LDR tmp2, [ref],#4
+ SUB center, center, #4
+ STR tmp2, [fill], #4
+case_1
+ LDR tmp2, [ref],#4
+ SUB center, center, #4
+ STR tmp2, [fill], #4
+
+loop_center
+ CMP center, #0
+ LDRBNE tmp2, [ref], #1
+ SUBNE center, center, #1
+ STRBNE tmp2, [fill], #1
+ BNE loop_center
+ CMP right,#0
+ POPEQ {r4-r6,pc}
+ LDRB tmp2, [ref,#-1]
+
+loop_right
+ STRB tmp2, [fill], #1
+ SUBS right, right, #1
+ BNE loop_right
+
+ POP {r4-r6,pc}
+ END
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFlushBits.s b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFlushBits.s
new file mode 100644
index 0000000..21335b8
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdFlushBits.s
@@ -0,0 +1,82 @@
+;
+; 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.
+;
+
+ REQUIRE8
+ PRESERVE8
+
+ AREA |.text|, CODE
+
+ EXPORT h264bsdFlushBits
+
+; Input / output registers
+pStrmData RN 0
+numBits RN 1
+readBits RN 2
+strmBuffSize RN 3
+pStrmBuffStart RN 1
+pStrmCurrPos RN 2
+bitPosInWord RN 1
+
+; -- NEON registers --
+
+
+
+;/*------------------------------------------------------------------------------
+;
+; Function: h264bsdFlushBits
+;
+; Functional description:
+;
+; Inputs:
+;
+; Outputs:
+;
+; Returns:
+;
+;------------------------------------------------------------------------------*/
+
+h264bsdFlushBits
+;// PUSH {r4-r6,lr}
+
+ LDR readBits, [pStrmData, #0x10]
+ LDR strmBuffSize, [pStrmData, #0xC]
+
+ ADD readBits, readBits, numBits
+ AND bitPosInWord, readBits, #7
+
+ STR readBits, [pStrmData, #0x10]
+ STR bitPosInWord, [pStrmData, #0x8]
+
+ LDR pStrmBuffStart, [pStrmData, #0x0]
+
+ CMP readBits, strmBuffSize, LSL #3
+
+ BHI end_of_stream
+
+ ADD pStrmCurrPos, pStrmBuffStart, readBits, LSR #3
+ STR pStrmCurrPos, [pStrmData, #0x4]
+ MOV r0, #0
+ BX lr
+;// POP {r4-r6,pc}
+
+end_of_stream
+ MVN r0, #0
+ BX lr
+;// POP {r4-r6,pc}
+
+ END
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdWriteMacroblock.s b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdWriteMacroblock.s
new file mode 100644
index 0000000..38a0781
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm/h264bsdWriteMacroblock.s
@@ -0,0 +1,152 @@
+;
+; 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.
+;
+
+ REQUIRE8
+ PRESERVE8
+
+ AREA |.text|, CODE
+
+ EXPORT h264bsdWriteMacroblock
+
+; Input / output registers
+image RN 0
+data RN 1
+width RN 2
+luma RN 3
+cb RN 4
+cr RN 5
+cwidth RN 6
+
+; -- NEON registers --
+
+qRow0 QN Q0.U8
+qRow1 QN Q1.U8
+qRow2 QN Q2.U8
+qRow3 QN Q3.U8
+qRow4 QN Q4.U8
+qRow5 QN Q5.U8
+qRow6 QN Q6.U8
+qRow7 QN Q7.U8
+qRow8 QN Q8.U8
+qRow9 QN Q9.U8
+qRow10 QN Q10.U8
+qRow11 QN Q11.U8
+qRow12 QN Q12.U8
+qRow13 QN Q13.U8
+qRow14 QN Q14.U8
+qRow15 QN Q15.U8
+
+dRow0 DN D0.U8
+dRow1 DN D1.U8
+dRow2 DN D2.U8
+dRow3 DN D3.U8
+dRow4 DN D4.U8
+dRow5 DN D5.U8
+dRow6 DN D6.U8
+dRow7 DN D7.U8
+dRow8 DN D8.U8
+dRow9 DN D9.U8
+dRow10 DN D10.U8
+dRow11 DN D11.U8
+dRow12 DN D12.U8
+dRow13 DN D13.U8
+dRow14 DN D14.U8
+dRow15 DN D15.U8
+
+;/*------------------------------------------------------------------------------
+;
+; Function: h264bsdWriteMacroblock
+;
+; Functional description:
+; Write one macroblock into the image. Both luma and chroma
+; components will be written at the same time.
+;
+; Inputs:
+; data pointer to macroblock data to be written, 256 values for
+; luma followed by 64 values for both chroma components
+;
+; Outputs:
+; image pointer to the image where the macroblock will be written
+;
+; Returns:
+; none
+;
+;------------------------------------------------------------------------------*/
+
+h264bsdWriteMacroblock
+ PUSH {r4-r6,lr}
+ VPUSH {q4-q7}
+
+ LDR width, [image, #4]
+ LDR luma, [image, #0xC]
+ LDR cb, [image, #0x10]
+ LDR cr, [image, #0x14]
+
+
+; Write luma
+ VLD1 {qRow0, qRow1}, [data]!
+ LSL width, width, #4
+ VLD1 {qRow2, qRow3}, [data]!
+ LSR cwidth, width, #1
+ VST1 {qRow0}, [luma@128], width
+ VLD1 {qRow4, qRow5}, [data]!
+ VST1 {qRow1}, [luma@128], width
+ VLD1 {qRow6, qRow7}, [data]!
+ VST1 {qRow2}, [luma@128], width
+ VLD1 {qRow8, qRow9}, [data]!
+ VST1 {qRow3}, [luma@128], width
+ VLD1 {qRow10, qRow11}, [data]!
+ VST1 {qRow4}, [luma@128], width
+ VLD1 {qRow12, qRow13}, [data]!
+ VST1 {qRow5}, [luma@128], width
+ VLD1 {qRow14, qRow15}, [data]!
+ VST1 {qRow6}, [luma@128], width
+
+ VLD1 {qRow0, qRow1}, [data]! ;cb rows 0,1,2,3
+ VST1 {qRow7}, [luma@128], width
+ VLD1 {qRow2, qRow3}, [data]! ;cb rows 4,5,6,7
+ VST1 {qRow8}, [luma@128], width
+ VLD1 {qRow4, qRow5}, [data]! ;cr rows 0,1,2,3
+ VST1 {qRow9}, [luma@128], width
+ VLD1 {qRow6, qRow7}, [data]! ;cr rows 4,5,6,7
+ VST1 {qRow10}, [luma@128], width
+ VST1 {dRow0}, [cb@64], cwidth
+ VST1 {dRow8}, [cr@64], cwidth
+ VST1 {qRow11}, [luma@128], width
+ VST1 {dRow1}, [cb@64], cwidth
+ VST1 {dRow9}, [cr@64], cwidth
+ VST1 {qRow12}, [luma@128], width
+ VST1 {dRow2}, [cb@64], cwidth
+ VST1 {dRow10}, [cr@64], cwidth
+ VST1 {qRow13}, [luma@128], width
+ VST1 {dRow3}, [cb@64], cwidth
+ VST1 {dRow11}, [cr@64], cwidth
+ VST1 {qRow14}, [luma@128], width
+ VST1 {dRow4}, [cb@64], cwidth
+ VST1 {dRow12}, [cr@64], cwidth
+ VST1 {qRow15}, [luma]
+ VST1 {dRow5}, [cb@64], cwidth
+ VST1 {dRow13}, [cr@64], cwidth
+ VST1 {dRow6}, [cb@64], cwidth
+ VST1 {dRow14}, [cr@64], cwidth
+ VST1 {dRow7}, [cb@64]
+ VST1 {dRow15}, [cr@64]
+
+ VPOP {q4-q7}
+ POP {r4-r6,pc}
+ END
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/asm_common.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/asm_common.S
new file mode 100644
index 0000000..f39f5c4
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/asm_common.S
@@ -0,0 +1,41 @@
+@
+@ 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.
+@
+
+
+
+
+ .macro REQUIRE8
+ .eabi_attribute 24, 1
+ .endm
+
+ .macro PRESERVE8
+ .eabi_attribute 25, 1
+ .endm
+
+
+ .macro function name, export=0
+.if \export
+ .global \name
+.endif
+ .type \name, %function
+ .func \name
+\name:
+ .endm
+
+ .macro endfunction
+ .endfunc
+ .endm
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdClearMbLayer.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdClearMbLayer.S
new file mode 100644
index 0000000..c8a940e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdClearMbLayer.S
@@ -0,0 +1,68 @@
+@
+@ 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 "asm_common.S"
+
+ preserve8
+
+ .fpu neon
+ .text
+
+/* Input / output registers */
+#define pMbLayer r0
+#define size r1
+#define pTmp r2
+#define step r3
+
+/* -- NEON registers -- */
+
+#define qZero Q0.U8
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdClearMbLayer
+
+ Functional description:
+
+ Inputs:
+
+ Outputs:
+
+ Returns:
+
+------------------------------------------------------------------------------*/
+
+function h264bsdClearMbLayer, export=1
+
+ VMOV qZero, #0
+ ADD pTmp, pMbLayer, #16
+ MOV step, #32
+ SUBS size, size, #64
+
+loop:
+ VST1 {qZero}, [pMbLayer], step
+ SUBS size, size, #64
+ VST1 {qZero}, [pTmp], step
+ VST1 {qZero}, [pMbLayer], step
+ VST1 {qZero}, [pTmp], step
+ BCS loop
+
+ BX lr
+
+endfunction
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdCountLeadingZeros.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdCountLeadingZeros.S
new file mode 100644
index 0000000..05253d0
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdCountLeadingZeros.S
@@ -0,0 +1,48 @@
+@
+@ 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 "asm_common.S"
+
+ preserve8
+ .arm
+ .text
+
+
+/* Input / output registers */
+#define value r0
+
+/* -- NEON registers -- */
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdCountLeadingZeros
+
+ Functional description:
+
+ Inputs:
+
+ Outputs:
+
+ Returns:
+
+------------------------------------------------------------------------------*/
+
+function h264bsdCountLeadingZeros, export=1
+
+ CLZ value, value
+ BX lr
+
+endfunction
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFillRow7.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFillRow7.S
new file mode 100644
index 0000000..6955b9a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFillRow7.S
@@ -0,0 +1,143 @@
+@
+@ 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 "asm_common.S"
+
+ preserve8
+
+ .fpu neon
+ .text
+
+/* Input / output registers */
+
+#define ref r0
+#define fill r1
+#define left r2
+#define tmp2 r2
+#define center r3
+#define right r4
+#define tmp1 r5
+
+/* -- NEON registers -- */
+
+#define qTmp0 Q0.U8
+#define qTmp1 Q1.U8
+#define dTmp0 D0.U8
+#define dTmp1 D1.U8
+#define dTmp2 D2.U8
+#define dTmp3 D3.U8
+
+/*
+void h264bsdFillRow7(const u8 * ref, u8 * fill, i32 left, i32 center,
+ i32 right);
+*/
+
+function h264bsdFillRow7, export=1
+
+ PUSH {r4-r6,lr}
+ CMP left, #0
+ LDR right, [sp,#0x10]
+ BEQ switch_center
+ LDRB tmp1, [ref,#0]
+
+loop_left:
+ SUBS left, left, #1
+ STRB tmp1, [fill], #1
+ BNE loop_left
+
+switch_center:
+ ASR tmp2,center,#2
+ CMP tmp2,#9
+ ADDCC pc,pc,tmp2,LSL #2
+ B loop_center
+ B loop_center
+ B case_1
+ B case_2
+ B case_3
+ B case_4
+ B case_5
+ B case_6
+ B case_7
+ B case_8
+
+case_8:
+ VLD1 {qTmp0, qTmp1}, [ref]!
+ SUB center, center, #32
+ VST1 {qTmp0}, [fill]!
+ VST1 {qTmp1}, [fill]!
+ B loop_center
+case_7:
+ VLD1 {dTmp0,dTmp1,dTmp2}, [ref]!
+ SUB center, center, #28
+ LDR tmp2, [ref], #4
+ VST1 {dTmp0,dTmp1,dTmp2}, [fill]!
+ STR tmp2, [fill],#4
+ B loop_center
+case_6:
+ VLD1 {dTmp0,dTmp1,dTmp2}, [ref]!
+ SUB center, center, #24
+ VST1 {dTmp0,dTmp1,dTmp2}, [fill]!
+ B loop_center
+case_5:
+ VLD1 {qTmp0}, [ref]!
+ SUB center, center, #20
+ LDR tmp2, [ref], #4
+ VST1 {qTmp0}, [fill]!
+ STR tmp2, [fill],#4
+ B loop_center
+case_4:
+ VLD1 {qTmp0}, [ref]!
+ SUB center, center, #16
+ VST1 {qTmp0}, [fill]!
+ B loop_center
+case_3:
+ VLD1 {dTmp0}, [ref]!
+ SUB center, center, #12
+ LDR tmp2, [ref], #4
+ VST1 dTmp0, [fill]!
+ STR tmp2, [fill],#4
+ B loop_center
+case_2:
+ LDR tmp2, [ref],#4
+ SUB center, center, #4
+ STR tmp2, [fill], #4
+case_1:
+ LDR tmp2, [ref],#4
+ SUB center, center, #4
+ STR tmp2, [fill], #4
+
+loop_center:
+ CMP center, #0
+ BEQ jump
+ LDRB tmp2, [ref], #1
+ SUB center, center, #1
+ STRB tmp2, [fill], #1
+ BNE loop_center
+jump:
+ CMP right,#0
+ POPEQ {r4-r6,pc}
+ LDRB tmp2, [ref,#-1]
+
+loop_right:
+ STRB tmp2, [fill], #1
+ SUBS right, right, #1
+ BNE loop_right
+
+ POP {r4-r6,pc}
+
+endfunction
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFlushBits.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFlushBits.S
new file mode 100644
index 0000000..b3f3191
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdFlushBits.S
@@ -0,0 +1,78 @@
+@
+@ 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 "asm_common.S"
+
+ preserve8
+
+ .arm
+ .text
+
+/* Input / output registers */
+#define pStrmData r0
+#define numBits r1
+#define readBits r2
+#define strmBuffSize r3
+#define pStrmBuffStart r1
+#define pStrmCurrPos r2
+#define bitPosInWord r1
+
+/* Input / output registers */
+
+
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdFlushBits
+
+ Functional description:
+
+ Inputs:
+
+ Outputs:
+
+ Returns:
+
+------------------------------------------------------------------------------*/
+function h264bsdFlushBits, export=1
+
+ LDR readBits, [pStrmData, #0x10]
+ LDR strmBuffSize, [pStrmData, #0xC]
+
+ ADD readBits, readBits, numBits
+ AND bitPosInWord, readBits, #7
+
+ STR readBits, [pStrmData, #0x10]
+ STR bitPosInWord, [pStrmData, #0x8]
+
+ LDR pStrmBuffStart, [pStrmData, #0x0]
+
+ CMP readBits, strmBuffSize, LSL #3
+
+ BHI end_of_stream
+
+ ADD pStrmCurrPos, pStrmBuffStart, readBits, LSR #3
+ STR pStrmCurrPos, [pStrmData, #0x4]
+ MOV r0, #0
+ BX lr
+
+end_of_stream:
+ MVN r0, #0
+ BX lr
+
+endfunction
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdWriteMacroblock.S b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdWriteMacroblock.S
new file mode 100644
index 0000000..495d560
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/arm_neon_asm_gcc/h264bsdWriteMacroblock.S
@@ -0,0 +1,157 @@
+@
+@ 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 "asm_common.S"
+
+ require8
+ preserve8
+
+ .arm
+ .fpu neon
+ .text
+
+/* Input / output registers */
+#define image r0
+#define data r1
+#define width r2
+#define luma r3
+#define cb r4
+#define cr r5
+#define cwidth r6
+
+/* -- NEON registers -- */
+
+#define qRow0 Q0.U8
+#define qRow1 Q1.U8
+#define qRow2 Q2.U8
+#define qRow3 Q3.U8
+#define qRow4 Q4.U8
+#define qRow5 Q5.U8
+#define qRow6 Q6.U8
+#define qRow7 Q7.U8
+#define qRow8 Q8.U8
+#define qRow9 Q9.U8
+#define qRow10 Q10.U8
+#define qRow11 Q11.U8
+#define qRow12 Q12.U8
+#define qRow13 Q13.U8
+#define qRow14 Q14.U8
+#define qRow15 Q15.U8
+
+#define dRow0 D0.U8
+#define dRow1 D1.U8
+#define dRow2 D2.U8
+#define dRow3 D3.U8
+#define dRow4 D4.U8
+#define dRow5 D5.U8
+#define dRow6 D6.U8
+#define dRow7 D7.U8
+#define dRow8 D8.U8
+#define dRow9 D9.U8
+#define dRow10 D10.U8
+#define dRow11 D11.U8
+#define dRow12 D12.U8
+#define dRow13 D13.U8
+#define dRow14 D14.U8
+#define dRow15 D15.U8
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdWriteMacroblock
+
+ Functional description:
+ Write one macroblock into the image. Both luma and chroma
+ components will be written at the same time.
+
+ Inputs:
+ data pointer to macroblock data to be written, 256 values for
+ luma followed by 64 values for both chroma components
+
+ Outputs:
+ image pointer to the image where the macroblock will be written
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+function h264bsdWriteMacroblock, export=1
+ PUSH {r4-r6,lr}
+ VPUSH {q4-q7}
+
+ LDR width, [image, #4]
+ LDR luma, [image, #0xC]
+ LDR cb, [image, #0x10]
+ LDR cr, [image, #0x14]
+
+
+@ Write luma
+ VLD1 {qRow0, qRow1}, [data]!
+ LSL width, width, #4
+ VLD1 {qRow2, qRow3}, [data]!
+ LSR cwidth, width, #1
+ VST1 {qRow0}, [luma,:128], width
+ VLD1 {qRow4, qRow5}, [data]!
+ VST1 {qRow1}, [luma,:128], width
+ VLD1 {qRow6, qRow7}, [data]!
+ VST1 {qRow2}, [luma,:128], width
+ VLD1 {qRow8, qRow9}, [data]!
+ VST1 {qRow3}, [luma,:128], width
+ VLD1 {qRow10, qRow11}, [data]!
+ VST1 {qRow4}, [luma,:128], width
+ VLD1 {qRow12, qRow13}, [data]!
+ VST1 {qRow5}, [luma,:128], width
+ VLD1 {qRow14, qRow15}, [data]!
+ VST1 {qRow6}, [luma,:128], width
+
+ VLD1 {qRow0, qRow1}, [data]! ;//cb rows 0,1,2,3
+ VST1 {qRow7}, [luma,:128], width
+ VLD1 {qRow2, qRow3}, [data]! ;//cb rows 4,5,6,7
+ VST1 {qRow8}, [luma,:128], width
+ VLD1 {qRow4, qRow5}, [data]! ;//cr rows 0,1,2,3
+ VST1 {qRow9}, [luma,:128], width
+ VLD1 {qRow6, qRow7}, [data]! ;//cr rows 4,5,6,7
+ VST1 {qRow10}, [luma,:128], width
+ VST1 {dRow0}, [cb,:64], cwidth
+ VST1 {dRow8}, [cr,:64], cwidth
+ VST1 {qRow11}, [luma,:128], width
+ VST1 {dRow1}, [cb,:64], cwidth
+ VST1 {dRow9}, [cr,:64], cwidth
+ VST1 {qRow12}, [luma,:128], width
+ VST1 {dRow2}, [cb,:64], cwidth
+ VST1 {dRow10}, [cr,:64], cwidth
+ VST1 {qRow13}, [luma,:128], width
+ VST1 {dRow3}, [cb,:64], cwidth
+ VST1 {dRow11}, [cr,:64], cwidth
+ VST1 {qRow14}, [luma,:128], width
+ VST1 {dRow4}, [cb,:64], cwidth
+ VST1 {dRow12}, [cr,:64], cwidth
+ VST1 {qRow15}, [luma]
+ VST1 {dRow5}, [cb,:64], cwidth
+ VST1 {dRow13}, [cr,:64], cwidth
+ VST1 {dRow6}, [cb,:64], cwidth
+ VST1 {dRow14}, [cr,:64], cwidth
+ VST1 {dRow7}, [cb,:64]
+ VST1 {dRow15}, [cr,:64]
+
+ VPOP {q4-q7}
+ POP {r4-r6,pc}
+@ BX lr
+
+ .endfunc
+
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.c
new file mode 100755
index 0000000..db77f8c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.c
@@ -0,0 +1,237 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ ExtractNalUnit
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_byte_stream.h"
+#include "h264bsd_util.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+#define BYTE_STREAM_ERROR 0xFFFFFFFF
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+
+ Function name: ExtractNalUnit
+
+ Functional description:
+ Extracts one NAL unit from the byte stream buffer. Removes
+ emulation prevention bytes if present. The original stream buffer
+ is used directly and is therefore modified if emulation prevention
+ bytes are present in the stream.
+
+ Stream buffer is assumed to contain either exactly one NAL unit
+ and nothing else, or one or more NAL units embedded in byte
+ stream format described in the Annex B of the standard. Function
+ detects which one is used based on the first bytes in the buffer.
+
+ Inputs:
+ pByteStream pointer to byte stream buffer
+ len length of the stream buffer (in bytes)
+
+ Outputs:
+ pStrmData stream information is stored here
+ readBytes number of bytes "consumed" from the stream buffer
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK error in byte stream
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdExtractNalUnit(u8 *pByteStream, u32 len, strmData_t *pStrmData,
+ u32 *readBytes)
+{
+
+/* Variables */
+
+ u32 i, tmp;
+ u32 byteCount,initByteCount;
+ u32 zeroCount;
+ u8 byte;
+ u32 hasEmulation = HANTRO_FALSE;
+ u32 invalidStream = HANTRO_FALSE;
+ u8 *readPtr, *writePtr;
+
+/* Code */
+
+ ASSERT(pByteStream);
+ ASSERT(len);
+ ASSERT(len < BYTE_STREAM_ERROR);
+ ASSERT(pStrmData);
+
+ /* byte stream format if starts with 0x000001 or 0x000000 */
+ if (len > 3 && pByteStream[0] == 0x00 && pByteStream[1] == 0x00 &&
+ (pByteStream[2]&0xFE) == 0x00)
+ {
+ /* search for NAL unit start point, i.e. point after first start code
+ * prefix in the stream */
+ zeroCount = byteCount = 2;
+ readPtr = pByteStream + 2;
+ /*lint -e(716) while(1) used consciously */
+ while (1)
+ {
+ byte = *readPtr++;
+ byteCount++;
+
+ if (byteCount == len)
+ {
+ /* no start code prefix found -> error */
+ *readBytes = len;
+ return(HANTRO_NOK);
+ }
+
+ if (!byte)
+ zeroCount++;
+ else if ((byte == 0x01) && (zeroCount >= 2))
+ break;
+ else
+ zeroCount = 0;
+ }
+
+ initByteCount = byteCount;
+
+ /* determine size of the NAL unit. Search for next start code prefix
+ * or end of stream and ignore possible trailing zero bytes */
+ zeroCount = 0;
+ /*lint -e(716) while(1) used consciously */
+ while (1)
+ {
+ byte = *readPtr++;
+ byteCount++;
+ if (!byte)
+ zeroCount++;
+
+ if ( (byte == 0x03) && (zeroCount == 2) )
+ {
+ hasEmulation = HANTRO_TRUE;
+ }
+
+ if ( (byte == 0x01) && (zeroCount >= 2 ) )
+ {
+ pStrmData->strmBuffSize =
+ byteCount - initByteCount - zeroCount - 1;
+ zeroCount -= MIN(zeroCount, 3);
+ break;
+ }
+ else if (byte)
+ {
+ if (zeroCount >= 3)
+ invalidStream = HANTRO_TRUE;
+ zeroCount = 0;
+ }
+
+ if (byteCount == len)
+ {
+ pStrmData->strmBuffSize = byteCount - initByteCount - zeroCount;
+ break;
+ }
+
+ }
+ }
+ /* separate NAL units as input -> just set stream params */
+ else
+ {
+ initByteCount = 0;
+ zeroCount = 0;
+ pStrmData->strmBuffSize = len;
+ hasEmulation = HANTRO_TRUE;
+ }
+
+ pStrmData->pStrmBuffStart = pByteStream + initByteCount;
+ pStrmData->pStrmCurrPos = pStrmData->pStrmBuffStart;
+ pStrmData->bitPosInWord = 0;
+ pStrmData->strmBuffReadBits = 0;
+
+ /* return number of bytes "consumed" */
+ *readBytes = pStrmData->strmBuffSize + initByteCount + zeroCount;
+
+ if (invalidStream)
+ {
+ return(HANTRO_NOK);
+ }
+
+ /* remove emulation prevention bytes before rbsp processing */
+ if (hasEmulation)
+ {
+ tmp = pStrmData->strmBuffSize;
+ readPtr = writePtr = pStrmData->pStrmBuffStart;
+ zeroCount = 0;
+ for (i = tmp; i--;)
+ {
+ if ((zeroCount == 2) && (*readPtr == 0x03))
+ {
+ /* emulation prevention byte shall be followed by one of the
+ * following bytes: 0x00, 0x01, 0x02, 0x03. This implies that
+ * emulation prevention 0x03 byte shall not be the last byte
+ * of the stream. */
+ if ( (i == 0) || (*(readPtr+1) > 0x03) )
+ return(HANTRO_NOK);
+
+ /* do not write emulation prevention byte */
+ readPtr++;
+ zeroCount = 0;
+ }
+ else
+ {
+ /* NAL unit shall not contain byte sequences 0x000000,
+ * 0x000001 or 0x000002 */
+ if ( (zeroCount == 2) && (*readPtr <= 0x02) )
+ return(HANTRO_NOK);
+
+ if (*readPtr == 0)
+ zeroCount++;
+ else
+ zeroCount = 0;
+
+ *writePtr++ = *readPtr++;
+ }
+ }
+
+ /* (readPtr - writePtr) indicates number of "removed" emulation
+ * prevention bytes -> subtract from stream buffer size */
+ pStrmData->strmBuffSize -= (u32)(readPtr - writePtr);
+ }
+
+ return(HANTRO_OK);
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.h
new file mode 100755
index 0000000..36aec76
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_byte_stream.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_BYTE_STREAM_H
+#define H264SWDEC_BYTE_STREAM_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_stream.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdExtractNalUnit(u8 *pByteStream, u32 len, strmData_t *pStrmData,
+ u32 *readBytes);
+
+#endif /* #ifdef H264SWDEC_BYTE_STREAM_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.c
new file mode 100755
index 0000000..91d78bd
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.c
@@ -0,0 +1,916 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ DecodeCoeffToken
+ DecodeLevelPrefix
+ DecodeTotalZeros
+ DecodeRunBefore
+ DecodeResidualBlockCavlc
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_cavlc.h"
+#include "h264bsd_util.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/* Following descriptions use term "information field" to represent combination
+ * of certain decoded symbol value and the length of the corresponding variable
+ * length code word. For example, total_zeros information field consists of
+ * 4 bits symbol value (bits [4,7]) along with four bits to represent length
+ * of the VLC code word (bits [0,3]) */
+
+/* macro to obtain length of the coeff token information field, bits [0,4] */
+#define LENGTH_TC(vlc) ((vlc) & 0x1F)
+/* macro to obtain length of the other information fields, bits [0,3] */
+#define LENGTH(vlc) ((vlc) & 0xF)
+/* macro to obtain code word from the information fields, bits [4,7] */
+#define INFO(vlc) (((vlc) >> 4) & 0xF) /* 4 MSB bits contain information */
+/* macro to obtain trailing ones from the coeff token information word,
+ * bits [5,10] */
+#define TRAILING_ONES(coeffToken) ((coeffToken>>5) & 0x3F)
+/* macro to obtain total coeff from the coeff token information word,
+ * bits [11,15] */
+#define TOTAL_COEFF(coeffToken) (((coeffToken) >> 11) & 0x1F)
+
+#define VLC_NOT_FOUND 0xFFFFFFFEU
+
+/* VLC tables for coeff_token. Because of long codes (max. 16 bits) some of the
+ * tables have been splitted into multiple separate tables. Each array/table
+ * element has the following structure:
+ * [5 bits for tot.coeff.] [6 bits for tr.ones] [5 bits for VLC length]
+ * If there is a 0x0000 value, it means that there is not corresponding VLC
+ * codeword for that index. */
+
+/* VLC lengths up to 6 bits, 0 <= nC < 2 */
+static const u16 coeffToken0_0[32] = {
+ 0x0000,0x0000,0x0000,0x2066,0x1026,0x0806,0x1865,0x1865,
+ 0x1043,0x1043,0x1043,0x1043,0x1043,0x1043,0x1043,0x1043,
+ 0x0822,0x0822,0x0822,0x0822,0x0822,0x0822,0x0822,0x0822,
+ 0x0822,0x0822,0x0822,0x0822,0x0822,0x0822,0x0822,0x0822};
+
+/* VLC lengths up to 10 bits, 0 <= nC < 2 */
+static const u16 coeffToken0_1[48] = {
+ 0x0000,0x0000,0x0000,0x0000,0x406a,0x304a,0x282a,0x200a,
+ 0x3869,0x3869,0x2849,0x2849,0x2029,0x2029,0x1809,0x1809,
+ 0x3068,0x3068,0x3068,0x3068,0x2048,0x2048,0x2048,0x2048,
+ 0x1828,0x1828,0x1828,0x1828,0x1008,0x1008,0x1008,0x1008,
+ 0x2867,0x2867,0x2867,0x2867,0x2867,0x2867,0x2867,0x2867,
+ 0x1847,0x1847,0x1847,0x1847,0x1847,0x1847,0x1847,0x1847};
+
+/* VLC lengths up to 14 bits, 0 <= nC < 2 */
+static const u16 coeffToken0_2[56] = {
+ 0x606e,0x584e,0x502e,0x500e,0x586e,0x504e,0x482e,0x480e,
+ 0x400d,0x400d,0x484d,0x484d,0x402d,0x402d,0x380d,0x380d,
+ 0x506d,0x506d,0x404d,0x404d,0x382d,0x382d,0x300d,0x300d,
+ 0x486b,0x486b,0x486b,0x486b,0x486b,0x486b,0x486b,0x486b,
+ 0x384b,0x384b,0x384b,0x384b,0x384b,0x384b,0x384b,0x384b,
+ 0x302b,0x302b,0x302b,0x302b,0x302b,0x302b,0x302b,0x302b,
+ 0x280b,0x280b,0x280b,0x280b,0x280b,0x280b,0x280b,0x280b};
+
+/* VLC lengths up to 16 bits, 0 <= nC < 2 */
+static const u16 coeffToken0_3[32] = {
+ 0x0000,0x0000,0x682f,0x682f,0x8010,0x8050,0x8030,0x7810,
+ 0x8070,0x7850,0x7830,0x7010,0x7870,0x7050,0x7030,0x6810,
+ 0x706f,0x706f,0x684f,0x684f,0x602f,0x602f,0x600f,0x600f,
+ 0x686f,0x686f,0x604f,0x604f,0x582f,0x582f,0x580f,0x580f};
+
+/* VLC lengths up to 6 bits, 2 <= nC < 4 */
+static const u16 coeffToken2_0[32] = {
+ 0x0000,0x0000,0x0000,0x0000,0x3866,0x2046,0x2026,0x1006,
+ 0x3066,0x1846,0x1826,0x0806,0x2865,0x2865,0x1025,0x1025,
+ 0x2064,0x2064,0x2064,0x2064,0x1864,0x1864,0x1864,0x1864,
+ 0x1043,0x1043,0x1043,0x1043,0x1043,0x1043,0x1043,0x1043};
+
+/* VLC lengths up to 9 bits, 2 <= nC < 4 */
+static const u16 coeffToken2_1[32] = {
+ 0x0000,0x0000,0x0000,0x0000,0x4869,0x3849,0x3829,0x3009,
+ 0x2808,0x2808,0x3048,0x3048,0x3028,0x3028,0x2008,0x2008,
+ 0x4067,0x4067,0x4067,0x4067,0x2847,0x2847,0x2847,0x2847,
+ 0x2827,0x2827,0x2827,0x2827,0x1807,0x1807,0x1807,0x1807};
+
+/* VLC lengths up to 14 bits, 2 <= nC < 4 */
+static const u16 coeffToken2_2[128] = {
+ 0x0000,0x0000,0x786d,0x786d,0x806e,0x804e,0x802e,0x800e,
+ 0x782e,0x780e,0x784e,0x702e,0x704d,0x704d,0x700d,0x700d,
+ 0x706d,0x706d,0x684d,0x684d,0x682d,0x682d,0x680d,0x680d,
+ 0x686d,0x686d,0x604d,0x604d,0x602d,0x602d,0x600d,0x600d,
+ 0x580c,0x580c,0x580c,0x580c,0x584c,0x584c,0x584c,0x584c,
+ 0x582c,0x582c,0x582c,0x582c,0x500c,0x500c,0x500c,0x500c,
+ 0x606c,0x606c,0x606c,0x606c,0x504c,0x504c,0x504c,0x504c,
+ 0x502c,0x502c,0x502c,0x502c,0x480c,0x480c,0x480c,0x480c,
+ 0x586b,0x586b,0x586b,0x586b,0x586b,0x586b,0x586b,0x586b,
+ 0x484b,0x484b,0x484b,0x484b,0x484b,0x484b,0x484b,0x484b,
+ 0x482b,0x482b,0x482b,0x482b,0x482b,0x482b,0x482b,0x482b,
+ 0x400b,0x400b,0x400b,0x400b,0x400b,0x400b,0x400b,0x400b,
+ 0x506b,0x506b,0x506b,0x506b,0x506b,0x506b,0x506b,0x506b,
+ 0x404b,0x404b,0x404b,0x404b,0x404b,0x404b,0x404b,0x404b,
+ 0x402b,0x402b,0x402b,0x402b,0x402b,0x402b,0x402b,0x402b,
+ 0x380b,0x380b,0x380b,0x380b,0x380b,0x380b,0x380b,0x380b};
+
+/* VLC lengths up to 6 bits, 4 <= nC < 8 */
+static const u16 coeffToken4_0[64] = {
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x1806,0x3846,0x3826,0x1006,0x4866,0x3046,0x3026,0x0806,
+ 0x2825,0x2825,0x2845,0x2845,0x2025,0x2025,0x2045,0x2045,
+ 0x1825,0x1825,0x4065,0x4065,0x1845,0x1845,0x1025,0x1025,
+ 0x3864,0x3864,0x3864,0x3864,0x3064,0x3064,0x3064,0x3064,
+ 0x2864,0x2864,0x2864,0x2864,0x2064,0x2064,0x2064,0x2064,
+ 0x1864,0x1864,0x1864,0x1864,0x1044,0x1044,0x1044,0x1044,
+ 0x0824,0x0824,0x0824,0x0824,0x0004,0x0004,0x0004,0x0004};
+
+/* VLC lengths up to 10 bits, 4 <= nC < 8 */
+static const u16 coeffToken4_1[128] = {
+ 0x0000,0x800a,0x806a,0x804a,0x802a,0x780a,0x786a,0x784a,
+ 0x782a,0x700a,0x706a,0x704a,0x702a,0x680a,0x6829,0x6829,
+ 0x6009,0x6009,0x6849,0x6849,0x6029,0x6029,0x5809,0x5809,
+ 0x6869,0x6869,0x6049,0x6049,0x5829,0x5829,0x5009,0x5009,
+ 0x6068,0x6068,0x6068,0x6068,0x5848,0x5848,0x5848,0x5848,
+ 0x5028,0x5028,0x5028,0x5028,0x4808,0x4808,0x4808,0x4808,
+ 0x5868,0x5868,0x5868,0x5868,0x5048,0x5048,0x5048,0x5048,
+ 0x4828,0x4828,0x4828,0x4828,0x4008,0x4008,0x4008,0x4008,
+ 0x3807,0x3807,0x3807,0x3807,0x3807,0x3807,0x3807,0x3807,
+ 0x3007,0x3007,0x3007,0x3007,0x3007,0x3007,0x3007,0x3007,
+ 0x4847,0x4847,0x4847,0x4847,0x4847,0x4847,0x4847,0x4847,
+ 0x2807,0x2807,0x2807,0x2807,0x2807,0x2807,0x2807,0x2807,
+ 0x5067,0x5067,0x5067,0x5067,0x5067,0x5067,0x5067,0x5067,
+ 0x4047,0x4047,0x4047,0x4047,0x4047,0x4047,0x4047,0x4047,
+ 0x4027,0x4027,0x4027,0x4027,0x4027,0x4027,0x4027,0x4027,
+ 0x2007,0x2007,0x2007,0x2007,0x2007,0x2007,0x2007,0x2007};
+
+/* fixed 6 bit length VLC, nC <= 8 */
+static const u16 coeffToken8[64] = {
+ 0x0806,0x0826,0x0000,0x0006,0x1006,0x1026,0x1046,0x0000,
+ 0x1806,0x1826,0x1846,0x1866,0x2006,0x2026,0x2046,0x2066,
+ 0x2806,0x2826,0x2846,0x2866,0x3006,0x3026,0x3046,0x3066,
+ 0x3806,0x3826,0x3846,0x3866,0x4006,0x4026,0x4046,0x4066,
+ 0x4806,0x4826,0x4846,0x4866,0x5006,0x5026,0x5046,0x5066,
+ 0x5806,0x5826,0x5846,0x5866,0x6006,0x6026,0x6046,0x6066,
+ 0x6806,0x6826,0x6846,0x6866,0x7006,0x7026,0x7046,0x7066,
+ 0x7806,0x7826,0x7846,0x7866,0x8006,0x8026,0x8046,0x8066};
+
+/* VLC lengths up to 3 bits, nC == -1 */
+static const u16 coeffTokenMinus1_0[8] = {
+ 0x0000,0x1043,0x0002,0x0002,0x0821,0x0821,0x0821,0x0821};
+
+/* VLC lengths up to 8 bits, nC == -1 */
+static const u16 coeffTokenMinus1_1[32] = {
+ 0x2067,0x2067,0x2048,0x2028,0x1847,0x1847,0x1827,0x1827,
+ 0x2006,0x2006,0x2006,0x2006,0x1806,0x1806,0x1806,0x1806,
+ 0x1006,0x1006,0x1006,0x1006,0x1866,0x1866,0x1866,0x1866,
+ 0x1026,0x1026,0x1026,0x1026,0x0806,0x0806,0x0806,0x0806};
+
+/* VLC tables for total_zeros. One table containing longer code, totalZeros_1,
+ * has been broken into two separate tables. Table elements have the
+ * following structure:
+ * [4 bits for info] [4 bits for VLC length] */
+
+/* VLC lengths up to 5 bits */
+static const u8 totalZeros_1_0[32] = {
+ 0x00,0x00,0x65,0x55,0x44,0x44,0x34,0x34,
+ 0x23,0x23,0x23,0x23,0x13,0x13,0x13,0x13,
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01};
+
+/* VLC lengths up to 9 bits */
+static const u8 totalZeros_1_1[32] = {
+ 0x00,0xf9,0xe9,0xd9,0xc8,0xc8,0xb8,0xb8,
+ 0xa7,0xa7,0xa7,0xa7,0x97,0x97,0x97,0x97,
+ 0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,
+ 0x76,0x76,0x76,0x76,0x76,0x76,0x76,0x76};
+
+static const u8 totalZeros_2[64] = {
+ 0xe6,0xd6,0xc6,0xb6,0xa5,0xa5,0x95,0x95,
+ 0x84,0x84,0x84,0x84,0x74,0x74,0x74,0x74,
+ 0x64,0x64,0x64,0x64,0x54,0x54,0x54,0x54,
+ 0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,
+ 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03};
+
+static const u8 totalZeros_3[64] = {
+ 0xd6,0xb6,0xc5,0xc5,0xa5,0xa5,0x95,0x95,
+ 0x84,0x84,0x84,0x84,0x54,0x54,0x54,0x54,
+ 0x44,0x44,0x44,0x44,0x04,0x04,0x04,0x04,
+ 0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,
+ 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,
+ 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13};
+
+static const u8 totalZeros_4[32] = {
+ 0xc5,0xb5,0xa5,0x05,0x94,0x94,0x74,0x74,
+ 0x34,0x34,0x24,0x24,0x83,0x83,0x83,0x83,
+ 0x63,0x63,0x63,0x63,0x53,0x53,0x53,0x53,
+ 0x43,0x43,0x43,0x43,0x13,0x13,0x13,0x13};
+
+static const u8 totalZeros_5[32] = {
+ 0xb5,0x95,0xa4,0xa4,0x84,0x84,0x24,0x24,
+ 0x14,0x14,0x04,0x04,0x73,0x73,0x73,0x73,
+ 0x63,0x63,0x63,0x63,0x53,0x53,0x53,0x53,
+ 0x43,0x43,0x43,0x43,0x33,0x33,0x33,0x33};
+
+static const u8 totalZeros_6[64] = {
+ 0xa6,0x06,0x15,0x15,0x84,0x84,0x84,0x84,
+ 0x93,0x93,0x93,0x93,0x93,0x93,0x93,0x93,
+ 0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,
+ 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,
+ 0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,
+ 0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,
+ 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23};
+
+static const u8 totalZeros_7[64] = {
+ 0x96,0x06,0x15,0x15,0x74,0x74,0x74,0x74,
+ 0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,
+ 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,
+ 0x43,0x43,0x43,0x43,0x43,0x43,0x43,0x43,
+ 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,
+ 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52};
+
+static const u8 totalZeros_8[64] = {
+ 0x86,0x06,0x25,0x25,0x14,0x14,0x14,0x14,
+ 0x73,0x73,0x73,0x73,0x73,0x73,0x73,0x73,
+ 0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,
+ 0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,
+ 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,
+ 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,
+ 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,
+ 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42};
+
+static const u8 totalZeros_9[64] = {
+ 0x16,0x06,0x75,0x75,0x24,0x24,0x24,0x24,
+ 0x53,0x53,0x53,0x53,0x53,0x53,0x53,0x53,
+ 0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,
+ 0x62,0x62,0x62,0x62,0x62,0x62,0x62,0x62,
+ 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,
+ 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,
+ 0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32,
+ 0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32};
+
+static const u8 totalZeros_10[32] = {
+ 0x15,0x05,0x64,0x64,0x23,0x23,0x23,0x23,
+ 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,
+ 0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,
+ 0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x32};
+
+static const u8 totalZeros_11[16] = {
+ 0x04,0x14,0x23,0x23,0x33,0x33,0x53,0x53,
+ 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41};
+
+static const u8 totalZeros_12[16] = {
+ 0x04,0x14,0x43,0x43,0x22,0x22,0x22,0x22,
+ 0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31};
+
+static const u8 totalZeros_13[8] = {0x03,0x13,0x32,0x32,0x21,0x21,0x21,0x21};
+
+static const u8 totalZeros_14[4] = {0x02,0x12,0x21,0x21};
+
+/* VLC tables for run_before. Table elements have the following structure:
+ * [4 bits for info] [4bits for VLC length]
+ */
+
+static const u8 runBefore_6[8] = {0x13,0x23,0x43,0x33,0x63,0x53,0x02,0x02};
+
+static const u8 runBefore_5[8] = {0x53,0x43,0x33,0x23,0x12,0x12,0x02,0x02};
+
+static const u8 runBefore_4[8] = {0x43,0x33,0x22,0x22,0x12,0x12,0x02,0x02};
+
+static const u8 runBefore_3[4] = {0x32,0x22,0x12,0x02};
+
+static const u8 runBefore_2[4] = {0x22,0x12,0x01,0x01};
+
+static const u8 runBefore_1[2] = {0x11,0x01};
+
+/* following four macros are used to handle stream buffer "cache" in the CAVLC
+ * decoding function */
+
+/* macro to initialize stream buffer cache, fills the buffer (32 bits) */
+#define BUFFER_INIT(value, bits) \
+{ \
+ bits = 32; \
+ value = h264bsdShowBits32(pStrmData); \
+}
+
+/* macro to read numBits bits from the buffer, bits will be written to
+ * outVal. Refills the buffer if not enough bits left */
+#define BUFFER_SHOW(value, bits, outVal, numBits) \
+{ \
+ if (bits < (numBits)) \
+ { \
+ if(h264bsdFlushBits(pStrmData,32-bits) == END_OF_STREAM) \
+ return(HANTRO_NOK); \
+ value = h264bsdShowBits32(pStrmData); \
+ bits = 32; \
+ } \
+ (outVal) = value >> (32 - (numBits)); \
+}
+
+/* macro to flush numBits bits from the buffer */
+#define BUFFER_FLUSH(value, bits, numBits) \
+{ \
+ value <<= (numBits); \
+ bits -= (numBits); \
+}
+
+/* macro to read and flush numBits bits from the buffer, bits will be written
+ * to outVal. Refills the buffer if not enough bits left */
+#define BUFFER_GET(value, bits, outVal, numBits) \
+{ \
+ if (bits < (numBits)) \
+ { \
+ if(h264bsdFlushBits(pStrmData,32-bits) == END_OF_STREAM) \
+ return(HANTRO_NOK); \
+ value = h264bsdShowBits32(pStrmData); \
+ bits = 32; \
+ } \
+ (outVal) = value >> (32 - (numBits)); \
+ value <<= (numBits); \
+ bits -= (numBits); \
+}
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static u32 DecodeCoeffToken(u32 bits, u32 nc);
+
+static u32 DecodeLevelPrefix(u32 bits);
+
+static u32 DecodeTotalZeros(u32 bits, u32 totalCoeff, u32 isChromaDC);
+
+static u32 DecodeRunBefore(u32 bits,u32 zerosLeft);
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeCoeffToken
+
+ Functional description:
+ Function to decode coeff_token information field from the stream.
+
+ Inputs:
+ u32 bits next 16 stream bits
+ u32 nc nC, see standard for details
+
+ Outputs:
+ u32 information field (11 bits for value, 5 bits for length)
+
+------------------------------------------------------------------------------*/
+
+u32 DecodeCoeffToken(u32 bits, u32 nc)
+{
+
+/* Variables */
+
+ u32 value;
+
+/* Code */
+
+ /* standard defines that nc for decoding of chroma dc coefficients is -1,
+ * represented by u32 here -> -1 maps to 2^32 - 1 */
+ ASSERT(nc <= 16 || nc == (u32)(-1));
+
+ if (nc < 2)
+ {
+ if (bits >= 0x8000)
+ {
+ value = 0x0001;
+ }
+ else if (bits >= 0x0C00)
+ value = coeffToken0_0[bits >> 10];
+ else if (bits >= 0x0100)
+ value = coeffToken0_1[bits >> 6];
+ else if (bits >= 0x0020)
+ value = coeffToken0_2[(bits>>2)-8];
+ else
+ value = coeffToken0_3[bits];
+ }
+ else if (nc < 4)
+ {
+ if (bits >= 0x8000)
+ {
+ value = bits & 0x4000 ? 0x0002 : 0x0822;
+ }
+ else if (bits >= 0x1000)
+ value = coeffToken2_0[bits >> 10];
+ else if (bits >= 0x0200)
+ value = coeffToken2_1[bits >> 7];
+ else
+ value = coeffToken2_2[bits>>2];
+ }
+ else if (nc < 8)
+ {
+ value = coeffToken4_0[bits >> 10];
+ if (!value)
+ value = coeffToken4_1[bits>>6];
+ }
+ else if (nc <= 16)
+ {
+ value = coeffToken8[bits>>10];
+ }
+ else
+ {
+ value = coeffTokenMinus1_0[bits >> 13];
+ if (!value)
+ value = coeffTokenMinus1_1[bits>>8];
+ }
+
+ return(value);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeLevelPrefix
+
+ Functional description:
+ Function to decode level_prefix information field from the stream
+
+ Inputs:
+ u32 bits next 16 stream bits
+
+ Outputs:
+ u32 level_prefix information field or VLC_NOT_FOUND
+
+------------------------------------------------------------------------------*/
+
+u32 DecodeLevelPrefix(u32 bits)
+{
+
+/* Variables */
+
+ u32 numZeros;
+
+/* Code */
+
+ if (bits >= 0x8000)
+ numZeros = 0;
+ else if (bits >= 0x4000)
+ numZeros = 1;
+ else if (bits >= 0x2000)
+ numZeros = 2;
+ else if (bits >= 0x1000)
+ numZeros = 3;
+ else if (bits >= 0x0800)
+ numZeros = 4;
+ else if (bits >= 0x0400)
+ numZeros = 5;
+ else if (bits >= 0x0200)
+ numZeros = 6;
+ else if (bits >= 0x0100)
+ numZeros = 7;
+ else if (bits >= 0x0080)
+ numZeros = 8;
+ else if (bits >= 0x0040)
+ numZeros = 9;
+ else if (bits >= 0x0020)
+ numZeros = 10;
+ else if (bits >= 0x0010)
+ numZeros = 11;
+ else if (bits >= 0x0008)
+ numZeros = 12;
+ else if (bits >= 0x0004)
+ numZeros = 13;
+ else if (bits >= 0x0002)
+ numZeros = 14;
+ else if (bits >= 0x0001)
+ numZeros = 15;
+ else /* more than 15 zeros encountered which is an error */
+ return(VLC_NOT_FOUND);
+
+ return(numZeros);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeTotalZeros
+
+ Functional description:
+ Function to decode total_zeros information field from the stream
+
+ Inputs:
+ u32 bits next 9 stream bits
+ u32 totalCoeff total number of coefficients for the block
+ being decoded
+ u32 isChromaDC flag to indicate chroma DC block
+
+ Outputs:
+ u32 information field (4 bits value, 4 bits length)
+
+------------------------------------------------------------------------------*/
+
+u32 DecodeTotalZeros(u32 bits, u32 totalCoeff, u32 isChromaDC)
+{
+
+/* Variables */
+
+ u32 value = 0x0;
+
+/* Code */
+
+ ASSERT(totalCoeff);
+
+ if (!isChromaDC)
+ {
+ ASSERT(totalCoeff < 16);
+ switch (totalCoeff)
+ {
+ case 1:
+ value = totalZeros_1_0[bits >> 4];
+ if (!value)
+ value = totalZeros_1_1[bits];
+ break;
+
+ case 2:
+ value = totalZeros_2[bits >> 3];
+ break;
+
+ case 3:
+ value = totalZeros_3[bits >> 3];
+ break;
+
+ case 4:
+ value = totalZeros_4[bits >> 4];
+ break;
+
+ case 5:
+ value = totalZeros_5[bits >> 4];
+ break;
+
+ case 6:
+ value = totalZeros_6[bits >> 3];
+ break;
+
+ case 7:
+ value = totalZeros_7[bits >> 3];
+ break;
+
+ case 8:
+ value = totalZeros_8[bits >> 3];
+ break;
+
+ case 9:
+ value = totalZeros_9[bits >> 3];
+ break;
+
+ case 10:
+ value = totalZeros_10[bits >> 4];
+ break;
+
+ case 11:
+ value = totalZeros_11[bits >> 5];
+ break;
+
+ case 12:
+ value = totalZeros_12[bits >> 5];
+ break;
+
+ case 13:
+ value = totalZeros_13[bits >> 6];
+ break;
+
+ case 14:
+ value = totalZeros_14[bits >> 7];
+ break;
+
+ default: /* case 15 */
+ value = (bits >> 8) ? 0x11 : 0x01;
+ break;
+ }
+ }
+ else
+ {
+ ASSERT(totalCoeff < 4);
+ bits >>= 6;
+ if (bits > 3)
+ value = 0x01;
+ else
+ {
+ if (totalCoeff == 3)
+ value = 0x11;
+ else if (bits > 1)
+ {
+ value = 0x12;
+ }
+ else if (totalCoeff == 2)
+ value = 0x22;
+ else if (bits)
+ value = 0x23;
+ else
+ value = 0x33;
+ }
+ }
+
+ return(value);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeRunBefore
+
+ Functional description:
+ Function to decode run_before information field from the stream
+
+ Inputs:
+ u32 bits next 11 stream bits
+ u32 zerosLeft number of zeros left for the current block
+
+ Outputs:
+ u32 information field (4 bits value, 4 bits length)
+
+------------------------------------------------------------------------------*/
+
+u32 DecodeRunBefore(u32 bits, u32 zerosLeft)
+{
+
+/* Variables */
+
+ u32 value = 0x0;
+
+/* Code */
+
+ switch (zerosLeft)
+ {
+ case 1:
+ value = runBefore_1[bits>>10];
+ break;
+
+ case 2:
+ value = runBefore_2[bits>>9];
+ break;
+
+ case 3:
+ value = runBefore_3[bits>>9];
+ break;
+
+ case 4:
+ value = runBefore_4[bits>>8];
+ break;
+
+ case 5:
+ value = runBefore_5[bits>>8];
+ break;
+
+ case 6:
+ value = runBefore_6[bits>>8];
+ break;
+
+ default:
+ if (bits >= 0x100)
+ value = ((7-(bits>>8))<<4)+0x3;
+ else if (bits >= 0x80)
+ value = 0x74;
+ else if (bits >= 0x40)
+ value = 0x85;
+ else if (bits >= 0x20)
+ value = 0x96;
+ else if (bits >= 0x10)
+ value = 0xa7;
+ else if (bits >= 0x8)
+ value = 0xb8;
+ else if (bits >= 0x4)
+ value = 0xc9;
+ else if (bits >= 0x2)
+ value = 0xdA;
+ else if (bits)
+ value = 0xeB;
+ if (INFO(value) > zerosLeft)
+ value = 0;
+ break;
+ }
+
+ return(value);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeResidualBlockCavlc
+
+ Functional description:
+ Function to decode one CAVLC coded block. This corresponds to
+ syntax elements residual_block_cavlc() in the standard.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ nc nC value
+ maxNumCoeff maximum number of residual coefficients
+
+ Outputs:
+ coeffLevel stores decoded coefficient levels
+
+ Returns:
+ numCoeffs on bits [4,11] if successful
+ coeffMap on bits [16,31] if successful, this is bit map
+ where each bit indicates if the corresponding
+ coefficient was zero (0) or non-zero (1)
+ HANTRO_NOK end of stream or error in stream
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeResidualBlockCavlc(
+ strmData_t *pStrmData,
+ i32 *coeffLevel,
+ i32 nc,
+ u32 maxNumCoeff)
+{
+
+/* Variables */
+
+ u32 i, tmp, totalCoeff, trailingOnes, suffixLength, levelPrefix;
+ u32 levelSuffix, zerosLeft, bit;
+ i32 level[16];
+ u32 run[16];
+ /* stream "cache" */
+ u32 bufferValue;
+ u32 bufferBits;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(coeffLevel);
+ ASSERT(nc > -2);
+ ASSERT(maxNumCoeff == 4 || maxNumCoeff == 15 || maxNumCoeff == 16);
+ ASSERT(VLC_NOT_FOUND != END_OF_STREAM);
+
+ /* assume that coeffLevel array has been "cleaned" by caller */
+
+ BUFFER_INIT(bufferValue, bufferBits);
+
+ /*lint -e774 disable lint warning on always false comparison */
+ BUFFER_SHOW(bufferValue, bufferBits, bit, 16);
+ /*lint +e774 */
+ tmp = DecodeCoeffToken(bit, (u32)nc);
+ if (!tmp)
+ return(HANTRO_NOK);
+ BUFFER_FLUSH(bufferValue, bufferBits, LENGTH_TC(tmp));
+
+ totalCoeff = TOTAL_COEFF(tmp);
+ if (totalCoeff > maxNumCoeff)
+ return(HANTRO_NOK);
+ trailingOnes = TRAILING_ONES(tmp);
+
+ if (totalCoeff != 0)
+ {
+ i = 0;
+ /* nonzero coefficients: +/- 1 */
+ if (trailingOnes)
+ {
+ BUFFER_GET(bufferValue, bufferBits, bit, trailingOnes);
+ tmp = 1 << (trailingOnes - 1);
+ for (; tmp; i++)
+ {
+ level[i] = bit & tmp ? -1 : 1;
+ tmp >>= 1;
+ }
+ }
+
+ /* other levels */
+ if (totalCoeff > 10 && trailingOnes < 3)
+ suffixLength = 1;
+ else
+ suffixLength = 0;
+
+ for (; i < totalCoeff; i++)
+ {
+ BUFFER_SHOW(bufferValue, bufferBits, bit, 16);
+ levelPrefix = DecodeLevelPrefix(bit);
+ if (levelPrefix == VLC_NOT_FOUND)
+ return(HANTRO_NOK);
+ BUFFER_FLUSH(bufferValue, bufferBits, levelPrefix+1);
+
+ if (levelPrefix < 14)
+ tmp = suffixLength;
+ else if (levelPrefix == 14)
+ {
+ tmp = suffixLength ? suffixLength : 4;
+ }
+ else
+ {
+ /* setting suffixLength to 1 here corresponds to adding 15
+ * to levelCode value if levelPrefix == 15 and
+ * suffixLength == 0 */
+ if (!suffixLength)
+ suffixLength = 1;
+ tmp = 12;
+ }
+
+ if (suffixLength)
+ levelPrefix <<= suffixLength;
+
+ if (tmp)
+ {
+ BUFFER_GET(bufferValue, bufferBits, levelSuffix, tmp);
+ levelPrefix += levelSuffix;
+ }
+
+ tmp = levelPrefix;
+
+ if (i == trailingOnes && trailingOnes < 3)
+ tmp += 2;
+
+ level[i] = (tmp+2)>>1;
+
+ if (suffixLength == 0)
+ suffixLength = 1;
+
+ if ((level[i] > (3 << (suffixLength - 1))) && suffixLength < 6)
+ suffixLength++;
+
+ if (tmp & 0x1)
+ level[i] = -level[i];
+ }
+
+ /* zero runs */
+ if (totalCoeff < maxNumCoeff)
+ {
+ BUFFER_SHOW(bufferValue, bufferBits, bit,9);
+ zerosLeft = DecodeTotalZeros(bit, totalCoeff,
+ (u32)(maxNumCoeff == 4));
+ if (!zerosLeft)
+ return(HANTRO_NOK);
+ BUFFER_FLUSH(bufferValue, bufferBits, LENGTH(zerosLeft));
+ zerosLeft = INFO(zerosLeft);
+ }
+ else
+ zerosLeft = 0;
+
+ for (i = 0; i < totalCoeff - 1; i++)
+ {
+ if (zerosLeft > 0)
+ {
+ BUFFER_SHOW(bufferValue, bufferBits, bit,11);
+ tmp = DecodeRunBefore(bit, zerosLeft);
+ if (!tmp)
+ return(HANTRO_NOK);
+ BUFFER_FLUSH(bufferValue, bufferBits, LENGTH(tmp));
+ run[i] = INFO(tmp);
+ zerosLeft -= run[i]++;
+ }
+ else
+ {
+ run[i] = 1;
+ }
+ }
+
+ /* combining level and run, levelSuffix variable used to hold coeffMap,
+ * i.e. bit map indicating which coefficients had non-zero value. */
+
+ /*lint -esym(771,level,run) level and run are always initialized */
+ tmp = zerosLeft;
+ coeffLevel[tmp] = level[totalCoeff-1];
+ levelSuffix = 1 << tmp;
+ for (i = totalCoeff-1; i--;)
+ {
+ tmp += run[i];
+ levelSuffix |= 1 << tmp;
+ coeffLevel[tmp] = level[i];
+ }
+
+ }
+ else
+ levelSuffix = 0;
+
+ if (h264bsdFlushBits(pStrmData, 32-bufferBits) != HANTRO_OK)
+ return(HANTRO_NOK);
+
+ return((totalCoeff << 4) | (levelSuffix << 16));
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.h
new file mode 100755
index 0000000..80353d3
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cavlc.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_CAVLC_H
+#define H264SWDEC_CAVLC_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_stream.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeResidualBlockCavlc(
+ strmData_t *pStrmData,
+ i32 *coeffLevel,
+ i32 nc,
+ u32 maxNumCoeff);
+
+#endif /* #ifdef H264SWDEC_CAVLC_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cfg.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cfg.h
new file mode 100755
index 0000000..2baba5a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_cfg.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_CFG_H
+#define H264SWDEC_CFG_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+#define MAX_NUM_REF_PICS 16
+#define MAX_NUM_SLICE_GROUPS 8
+#define MAX_NUM_SEQ_PARAM_SETS 32
+#define MAX_NUM_PIC_PARAM_SETS 256
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+#endif /* #ifdef H264SWDEC_CFG_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c
new file mode 100755
index 0000000..493fb9e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.c
@@ -0,0 +1,626 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdConceal
+ ConcealMb
+ Transform
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_conceal.h"
+#include "h264bsd_util.h"
+#include "h264bsd_reconstruct.h"
+#include "h264bsd_dpb.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/*lint -e702 disable lint warning on right shift of signed quantity */
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static u32 ConcealMb(mbStorage_t *pMb, image_t *currImage, u32 row, u32 col,
+ u32 sliceType, u8 *data);
+
+static void Transform(i32 *data);
+
+/*------------------------------------------------------------------------------
+
+ Function name: h264bsdConceal
+
+ Functional description:
+ Perform error concealment for a picture. Two types of concealment
+ is performed based on sliceType:
+ 1) copy from previous picture for P-slices.
+ 2) concealment from neighbour pixels for I-slices
+
+ I-type concealment is based on ideas presented by Jarno Tulkki.
+ The concealment algorithm determines frequency domain coefficients
+ from the neighbour pixels, applies integer transform (the same
+ transform used in the residual processing) and uses the results as
+ pixel values for concealed macroblocks. Transform produces 4x4
+ array and one pixel value has to be used for 4x4 luma blocks and
+ 2x2 chroma blocks.
+
+ Similar concealment is performed for whole picture (the choise
+ of the type is based on last successfully decoded slice header of
+ the picture but it is handled by the calling function). It is
+ acknowledged that this may result in wrong type of concealment
+ when a picture contains both types of slices. However,
+ determination of slice type macroblock-by-macroblock cannot
+ be done due to the fact that it is impossible to know to which
+ slice each corrupted (not successfully decoded) macroblock
+ belongs.
+
+ The error concealment is started by searching the first propoerly
+ decoded macroblock and concealing the row containing the macroblock
+ in question. After that all macroblocks above the row in question
+ are concealed. Finally concealment of rows below is performed.
+ The order of concealment for 4x4 picture where macroblock 9 is the
+ first properly decoded one is as follows (properly decoded
+ macroblocks marked with 'x', numbers indicating the order of
+ concealment):
+
+ 4 6 8 10
+ 3 5 7 9
+ 1 x x 2
+ 11 12 13 14
+
+ If all macroblocks of the picture are lost, the concealment is
+ copy of previous picture for P-type and setting the image to
+ constant gray (pixel value 128) for I-type.
+
+ Concealment sets quantization parameter of the concealed
+ macroblocks to value 40 and macroblock type to intra to enable
+ deblocking filter to smooth the edges of the concealed areas.
+
+ Inputs:
+ pStorage pointer to storage structure
+ currImage pointer to current image structure
+ sliceType type of the slice
+
+ Outputs:
+ currImage concealed macroblocks will be written here
+
+ Returns:
+ HANTRO_OK
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdConceal(storage_t *pStorage, image_t *currImage, u32 sliceType)
+{
+
+/* Variables */
+
+ u32 i, j;
+ u32 row, col;
+ u32 width, height;
+ u8 *refData;
+ mbStorage_t *mb;
+
+/* Code */
+
+ ASSERT(pStorage);
+ ASSERT(currImage);
+
+ DEBUG(("Concealing %s slice\n", IS_I_SLICE(sliceType) ?
+ "intra" : "inter"));
+
+ width = currImage->width;
+ height = currImage->height;
+ refData = NULL;
+ /* use reference picture with smallest available index */
+ if (IS_P_SLICE(sliceType) || (pStorage->intraConcealmentFlag != 0))
+ {
+ i = 0;
+ do
+ {
+ refData = h264bsdGetRefPicData(pStorage->dpb, i);
+ i++;
+ if (i >= 16)
+ break;
+ } while (refData == NULL);
+ }
+
+ i = row = col = 0;
+ /* find first properly decoded macroblock -> start point for concealment */
+ while (i < pStorage->picSizeInMbs && !pStorage->mb[i].decoded)
+ {
+ i++;
+ col++;
+ if (col == width)
+ {
+ row++;
+ col = 0;
+ }
+ }
+
+ /* whole picture lost -> copy previous or set grey */
+ if (i == pStorage->picSizeInMbs)
+ {
+ if ( (IS_I_SLICE(sliceType) && (pStorage->intraConcealmentFlag == 0)) ||
+ refData == NULL)
+ H264SwDecMemset(currImage->data, 128, width*height*384);
+ else
+ H264SwDecMemcpy(currImage->data, refData, width*height*384);
+
+ pStorage->numConcealedMbs = pStorage->picSizeInMbs;
+
+ /* no filtering if whole picture concealed */
+ for (i = 0; i < pStorage->picSizeInMbs; i++)
+ pStorage->mb[i].disableDeblockingFilterIdc = 1;
+
+ return(HANTRO_OK);
+ }
+
+ /* start from the row containing the first correct macroblock, conceal the
+ * row in question, all rows above that row and then continue downwards */
+ mb = pStorage->mb + row * width;
+ for (j = col; j--;)
+ {
+ ConcealMb(mb+j, currImage, row, j, sliceType, refData);
+ mb[j].decoded = 1;
+ pStorage->numConcealedMbs++;
+ }
+ for (j = col + 1; j < width; j++)
+ {
+ if (!mb[j].decoded)
+ {
+ ConcealMb(mb+j, currImage, row, j, sliceType, refData);
+ mb[j].decoded = 1;
+ pStorage->numConcealedMbs++;
+ }
+ }
+ /* if previous row(s) could not be concealed -> conceal them now */
+ if (row)
+ {
+ for (j = 0; j < width; j++)
+ {
+ i = row - 1;
+ mb = pStorage->mb + i*width + j;
+ do
+ {
+ ConcealMb(mb, currImage, i, j, sliceType, refData);
+ mb->decoded = 1;
+ pStorage->numConcealedMbs++;
+ mb -= width;
+ } while(i--);
+ }
+ }
+
+ /* process rows below the one containing the first correct macroblock */
+ for (i = row + 1; i < height; i++)
+ {
+ mb = pStorage->mb + i * width;
+
+ for (j = 0; j < width; j++)
+ {
+ if (!mb[j].decoded)
+ {
+ ConcealMb(mb+j, currImage, i, j, sliceType, refData);
+ mb[j].decoded = 1;
+ pStorage->numConcealedMbs++;
+ }
+ }
+ }
+
+ return(HANTRO_OK);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: ConcealMb
+
+ Functional description:
+ Perform error concealment for one macroblock, location of the
+ macroblock in the picture indicated by row and col
+
+------------------------------------------------------------------------------*/
+
+u32 ConcealMb(mbStorage_t *pMb, image_t *currImage, u32 row, u32 col,
+ u32 sliceType, u8 *refData)
+{
+
+/* Variables */
+
+ u32 i, j, comp;
+ u32 hor, ver;
+ u32 mbNum;
+ u32 width, height;
+ u8 *mbPos;
+ u8 data[384];
+ u8 *pData;
+ i32 tmp;
+ i32 firstPhase[16];
+ i32 *pTmp;
+ /* neighbours above, below, left and right */
+ i32 a[4], b[4], l[4], r[4];
+ u32 A, B, L, R;
+#ifdef H264DEC_OMXDL
+ u8 fillBuff[32*21 + 15 + 32];
+ u8 *pFill;
+#endif
+/* Code */
+
+ ASSERT(pMb);
+ ASSERT(!pMb->decoded);
+ ASSERT(currImage);
+ ASSERT(col < currImage->width);
+ ASSERT(row < currImage->height);
+
+#ifdef H264DEC_OMXDL
+ pFill = ALIGN(fillBuff, 16);
+#endif
+ width = currImage->width;
+ height = currImage->height;
+ mbNum = row * width + col;
+
+ h264bsdSetCurrImageMbPointers(currImage, mbNum);
+
+ mbPos = currImage->data + row * 16 * width * 16 + col * 16;
+ A = B = L = R = HANTRO_FALSE;
+
+ /* set qpY to 40 to enable some filtering in deblocking (stetson value) */
+ pMb->qpY = 40;
+ pMb->disableDeblockingFilterIdc = 0;
+ /* mbType set to intra to perform filtering despite the values of other
+ * boundary strength determination fields */
+ pMb->mbType = I_4x4;
+ pMb->filterOffsetA = 0;
+ pMb->filterOffsetB = 0;
+ pMb->chromaQpIndexOffset = 0;
+
+ if (IS_I_SLICE(sliceType))
+ H264SwDecMemset(data, 0, sizeof(data));
+ else
+ {
+ mv_t mv = {0,0};
+ image_t refImage;
+ refImage.width = width;
+ refImage.height = height;
+ refImage.data = refData;
+ if (refImage.data)
+ {
+#ifndef H264DEC_OMXDL
+ h264bsdPredictSamples(data, &mv, &refImage, col*16, row*16,
+ 0, 0, 16, 16);
+#else
+ h264bsdPredictSamples(data, &mv, &refImage,
+ ((row*16) + ((col*16)<<16)),
+ 0x00001010, pFill);
+#endif
+ h264bsdWriteMacroblock(currImage, data);
+
+ return(HANTRO_OK);
+ }
+ else
+ H264SwDecMemset(data, 0, sizeof(data));
+ }
+
+ H264SwDecMemset(firstPhase, 0, sizeof(firstPhase));
+
+ /* counter for number of neighbours used */
+ j = 0;
+ hor = ver = 0;
+ if (row && (pMb-width)->decoded)
+ {
+ A = HANTRO_TRUE;
+ pData = mbPos - width*16;
+ a[0] = *pData++; a[0] += *pData++; a[0] += *pData++; a[0] += *pData++;
+ a[1] = *pData++; a[1] += *pData++; a[1] += *pData++; a[1] += *pData++;
+ a[2] = *pData++; a[2] += *pData++; a[2] += *pData++; a[2] += *pData++;
+ a[3] = *pData++; a[3] += *pData++; a[3] += *pData++; a[3] += *pData++;
+ j++;
+ hor++;
+ firstPhase[0] += a[0] + a[1] + a[2] + a[3];
+ firstPhase[1] += a[0] + a[1] - a[2] - a[3];
+ }
+ if ((row != height - 1) && (pMb+width)->decoded)
+ {
+ B = HANTRO_TRUE;
+ pData = mbPos + 16*width*16;
+ b[0] = *pData++; b[0] += *pData++; b[0] += *pData++; b[0] += *pData++;
+ b[1] = *pData++; b[1] += *pData++; b[1] += *pData++; b[1] += *pData++;
+ b[2] = *pData++; b[2] += *pData++; b[2] += *pData++; b[2] += *pData++;
+ b[3] = *pData++; b[3] += *pData++; b[3] += *pData++; b[3] += *pData++;
+ j++;
+ hor++;
+ firstPhase[0] += b[0] + b[1] + b[2] + b[3];
+ firstPhase[1] += b[0] + b[1] - b[2] - b[3];
+ }
+ if (col && (pMb-1)->decoded)
+ {
+ L = HANTRO_TRUE;
+ pData = mbPos - 1;
+ l[0] = pData[0]; l[0] += pData[16*width];
+ l[0] += pData[32*width]; l[0] += pData[48*width];
+ pData += 64*width;
+ l[1] = pData[0]; l[1] += pData[16*width];
+ l[1] += pData[32*width]; l[1] += pData[48*width];
+ pData += 64*width;
+ l[2] = pData[0]; l[2] += pData[16*width];
+ l[2] += pData[32*width]; l[2] += pData[48*width];
+ pData += 64*width;
+ l[3] = pData[0]; l[3] += pData[16*width];
+ l[3] += pData[32*width]; l[3] += pData[48*width];
+ j++;
+ ver++;
+ firstPhase[0] += l[0] + l[1] + l[2] + l[3];
+ firstPhase[4] += l[0] + l[1] - l[2] - l[3];
+ }
+ if ((col != width - 1) && (pMb+1)->decoded)
+ {
+ R = HANTRO_TRUE;
+ pData = mbPos + 16;
+ r[0] = pData[0]; r[0] += pData[16*width];
+ r[0] += pData[32*width]; r[0] += pData[48*width];
+ pData += 64*width;
+ r[1] = pData[0]; r[1] += pData[16*width];
+ r[1] += pData[32*width]; r[1] += pData[48*width];
+ pData += 64*width;
+ r[2] = pData[0]; r[2] += pData[16*width];
+ r[2] += pData[32*width]; r[2] += pData[48*width];
+ pData += 64*width;
+ r[3] = pData[0]; r[3] += pData[16*width];
+ r[3] += pData[32*width]; r[3] += pData[48*width];
+ j++;
+ ver++;
+ firstPhase[0] += r[0] + r[1] + r[2] + r[3];
+ firstPhase[4] += r[0] + r[1] - r[2] - r[3];
+ }
+
+ /* at least one properly decoded neighbour available */
+ ASSERT(j);
+
+ /*lint -esym(644,l,r,a,b) variable initialized above */
+ if (!hor && L && R)
+ firstPhase[1] = (l[0]+l[1]+l[2]+l[3]-r[0]-r[1]-r[2]-r[3]) >> 5;
+ else if (hor)
+ firstPhase[1] >>= (3+hor);
+
+ if (!ver && A && B)
+ firstPhase[4] = (a[0]+a[1]+a[2]+a[3]-b[0]-b[1]-b[2]-b[3]) >> 5;
+ else if (ver)
+ firstPhase[4] >>= (3+ver);
+
+ switch (j)
+ {
+ case 1:
+ firstPhase[0] >>= 4;
+ break;
+
+ case 2:
+ firstPhase[0] >>= 5;
+ break;
+
+ case 3:
+ /* approximate (firstPhase[0]*4/3)>>6 */
+ firstPhase[0] = (21 * firstPhase[0]) >> 10;
+ break;
+
+ default: /* 4 */
+ firstPhase[0] >>= 6;
+ break;
+
+ }
+
+
+ Transform(firstPhase);
+
+ for (i = 0, pData = data, pTmp = firstPhase; i < 256;)
+ {
+ tmp = pTmp[(i & 0xF)>>2];
+ /*lint -e734 CLIP1 macro results in value that fits into 8 bits */
+ *pData++ = CLIP1(tmp);
+ /*lint +e734 */
+
+ i++;
+ if (!(i & 0x3F))
+ pTmp += 4;
+ }
+
+ /* chroma components */
+ mbPos = currImage->data + width * height * 256 +
+ row * 8 * width * 8 + col * 8;
+ for (comp = 0; comp < 2; comp++)
+ {
+
+ H264SwDecMemset(firstPhase, 0, sizeof(firstPhase));
+
+ /* counter for number of neighbours used */
+ j = 0;
+ hor = ver = 0;
+ if (A)
+ {
+ pData = mbPos - width*8;
+ a[0] = *pData++; a[0] += *pData++;
+ a[1] = *pData++; a[1] += *pData++;
+ a[2] = *pData++; a[2] += *pData++;
+ a[3] = *pData++; a[3] += *pData++;
+ j++;
+ hor++;
+ firstPhase[0] += a[0] + a[1] + a[2] + a[3];
+ firstPhase[1] += a[0] + a[1] - a[2] - a[3];
+ }
+ if (B)
+ {
+ pData = mbPos + 8*width*8;
+ b[0] = *pData++; b[0] += *pData++;
+ b[1] = *pData++; b[1] += *pData++;
+ b[2] = *pData++; b[2] += *pData++;
+ b[3] = *pData++; b[3] += *pData++;
+ j++;
+ hor++;
+ firstPhase[0] += b[0] + b[1] + b[2] + b[3];
+ firstPhase[1] += b[0] + b[1] - b[2] - b[3];
+ }
+ if (L)
+ {
+ pData = mbPos - 1;
+ l[0] = pData[0]; l[0] += pData[8*width];
+ pData += 16*width;
+ l[1] = pData[0]; l[1] += pData[8*width];
+ pData += 16*width;
+ l[2] = pData[0]; l[2] += pData[8*width];
+ pData += 16*width;
+ l[3] = pData[0]; l[3] += pData[8*width];
+ j++;
+ ver++;
+ firstPhase[0] += l[0] + l[1] + l[2] + l[3];
+ firstPhase[4] += l[0] + l[1] - l[2] - l[3];
+ }
+ if (R)
+ {
+ pData = mbPos + 8;
+ r[0] = pData[0]; r[0] += pData[8*width];
+ pData += 16*width;
+ r[1] = pData[0]; r[1] += pData[8*width];
+ pData += 16*width;
+ r[2] = pData[0]; r[2] += pData[8*width];
+ pData += 16*width;
+ r[3] = pData[0]; r[3] += pData[8*width];
+ j++;
+ ver++;
+ firstPhase[0] += r[0] + r[1] + r[2] + r[3];
+ firstPhase[4] += r[0] + r[1] - r[2] - r[3];
+ }
+ if (!hor && L && R)
+ firstPhase[1] = (l[0]+l[1]+l[2]+l[3]-r[0]-r[1]-r[2]-r[3]) >> 4;
+ else if (hor)
+ firstPhase[1] >>= (2+hor);
+
+ if (!ver && A && B)
+ firstPhase[4] = (a[0]+a[1]+a[2]+a[3]-b[0]-b[1]-b[2]-b[3]) >> 4;
+ else if (ver)
+ firstPhase[4] >>= (2+ver);
+
+ switch (j)
+ {
+ case 1:
+ firstPhase[0] >>= 3;
+ break;
+
+ case 2:
+ firstPhase[0] >>= 4;
+ break;
+
+ case 3:
+ /* approximate (firstPhase[0]*4/3)>>5 */
+ firstPhase[0] = (21 * firstPhase[0]) >> 9;
+ break;
+
+ default: /* 4 */
+ firstPhase[0] >>= 5;
+ break;
+
+ }
+
+ Transform(firstPhase);
+
+ pData = data + 256 + comp*64;
+ for (i = 0, pTmp = firstPhase; i < 64;)
+ {
+ tmp = pTmp[(i & 0x7)>>1];
+ /*lint -e734 CLIP1 macro results in value that fits into 8 bits */
+ *pData++ = CLIP1(tmp);
+ /*lint +e734 */
+
+ i++;
+ if (!(i & 0xF))
+ pTmp += 4;
+ }
+
+ /* increment pointers for cr */
+ mbPos += width * height * 64;
+ }
+
+ h264bsdWriteMacroblock(currImage, data);
+
+ return(HANTRO_OK);
+
+}
+
+
+/*------------------------------------------------------------------------------
+
+ Function name: Transform
+
+ Functional description:
+ Simplified transform, assuming that only dc component and lowest
+ horizontal and lowest vertical component may be non-zero
+
+------------------------------------------------------------------------------*/
+
+void Transform(i32 *data)
+{
+
+ u32 col;
+ i32 tmp0, tmp1;
+
+ if (!data[1] && !data[4])
+ {
+ data[1] = data[2] = data[3] = data[4] = data[5] =
+ data[6] = data[7] = data[8] = data[9] = data[10] =
+ data[11] = data[12] = data[13] = data[14] = data[15] = data[0];
+ return;
+ }
+ /* first horizontal transform for rows 0 and 1 */
+ tmp0 = data[0];
+ tmp1 = data[1];
+ data[0] = tmp0 + tmp1;
+ data[1] = tmp0 + (tmp1>>1);
+ data[2] = tmp0 - (tmp1>>1);
+ data[3] = tmp0 - tmp1;
+
+ tmp0 = data[4];
+ data[5] = tmp0;
+ data[6] = tmp0;
+ data[7] = tmp0;
+
+ /* then vertical transform */
+ for (col = 4; col--; data++)
+ {
+ tmp0 = data[0];
+ tmp1 = data[4];
+ data[0] = tmp0 + tmp1;
+ data[4] = tmp0 + (tmp1>>1);
+ data[8] = tmp0 - (tmp1>>1);
+ data[12] = tmp0 - tmp1;
+ }
+
+}
+/*lint +e702 */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.h
new file mode 100755
index 0000000..3134670
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_conceal.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_CONCEAL_H
+#define H264SWDEC_CONCEAL_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_slice_header.h"
+#include "h264bsd_storage.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdConceal(storage_t *pStorage, image_t *currImage, u32 sliceType);
+
+#endif /* #ifdef H264SWDEC_CONCEAL_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_container.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_container.h
new file mode 100755
index 0000000..99b74a0
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_container.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_CONTAINER_H
+#define H264SWDEC_CONTAINER_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_storage.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/* String length for tracing */
+#define H264DEC_TRACE_STR_LEN 100
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+typedef struct
+{
+ enum {
+ UNINITIALIZED,
+ INITIALIZED,
+ NEW_HEADERS
+ } decStat;
+
+ u32 picNumber;
+ storage_t storage;
+#ifdef H264DEC_TRACE
+ char str[H264DEC_TRACE_STR_LEN];
+#endif
+} decContainer_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+#endif /* #ifdef H264SWDEC_DECCONTAINER_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.c
new file mode 100755
index 0000000..f8c1f76
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.c
@@ -0,0 +1,2417 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdFilterPicture
+ FilterVerLumaEdge
+ FilterHorLumaEdge
+ FilterHorLuma
+ FilterVerChromaEdge
+ FilterHorChromaEdge
+ FilterHorChroma
+ InnerBoundaryStrength
+ EdgeBoundaryStrength
+ GetBoundaryStrengths
+ IsSliceBoundaryOnLeft
+ IsSliceBoundaryOnTop
+ GetMbFilteringFlags
+ GetLumaEdgeThresholds
+ GetChromaEdgeThresholds
+ FilterLuma
+ FilterChroma
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_util.h"
+#include "h264bsd_macroblock_layer.h"
+#include "h264bsd_deblocking.h"
+#include "h264bsd_dpb.h"
+
+#ifdef H264DEC_OMXDL
+#include "omxtypes.h"
+#include "omxVC.h"
+#include "armVC.h"
+#endif /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/* Switch off the following Lint messages for this file:
+ * Info 701: Shift left of signed quantity (int)
+ * Info 702: Shift right of signed quantity (int)
+ */
+/*lint -e701 -e702 */
+
+/* array of alpha values, from the standard */
+static const u8 alphas[52] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,5,6,7,8,9,10,
+ 12,13,15,17,20,22,25,28,32,36,40,45,50,56,63,71,80,90,101,113,127,144,162,
+ 182,203,226,255,255};
+
+/* array of beta values, from the standard */
+static const u8 betas[52] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,3,3,3,3,4,4,
+ 4,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18};
+
+
+
+#ifndef H264DEC_OMXDL
+/* array of tc0 values, from the standard, each triplet corresponds to a
+ * column in the table. Indexing goes as tc0[indexA][bS-1] */
+static const u8 tc0[52][3] = {
+ {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,0,0},{0,0,1},{0,0,1},{0,0,1},{0,0,1},{0,1,1},{0,1,1},{1,1,1},
+ {1,1,1},{1,1,1},{1,1,1},{1,1,2},{1,1,2},{1,1,2},{1,1,2},{1,2,3},
+ {1,2,3},{2,2,3},{2,2,4},{2,3,4},{2,3,4},{3,3,5},{3,4,6},{3,4,6},
+ {4,5,7},{4,5,8},{4,6,9},{5,7,10},{6,8,11},{6,8,13},{7,10,14},{8,11,16},
+ {9,12,18},{10,13,20},{11,15,23},{13,17,25}
+};
+#else
+/* array of tc0 values, from the standard, each triplet corresponds to a
+ * column in the table. Indexing goes as tc0[indexA][bS] */
+static const u8 tc0[52][5] = {
+ {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, 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, 1, 0}, {0, 0, 0, 1, 0}, {0, 0, 0, 1, 0},
+ {0, 0, 0, 1, 0}, {0, 0, 1, 1, 0}, {0, 0, 1, 1, 0}, {0, 1, 1, 1, 0},
+ {0, 1, 1, 1, 0}, {0, 1, 1, 1, 0}, {0, 1, 1, 1, 0}, {0, 1, 1, 2, 0},
+ {0, 1, 1, 2, 0}, {0, 1, 1, 2, 0}, {0, 1, 1, 2, 0}, {0, 1, 2, 3, 0},
+ {0, 1, 2, 3, 0}, {0, 2, 2, 3, 0}, {0, 2, 2, 4, 0}, {0, 2, 3, 4, 0},
+ {0, 2, 3, 4, 0}, {0, 3, 3, 5, 0}, {0, 3, 4, 6, 0}, {0, 3, 4, 6, 0},
+ {0, 4, 5, 7, 0}, {0, 4, 5, 8, 0}, {0, 4, 6, 9, 0}, {0, 5, 7, 10, 0},
+ {0, 6, 8, 11, 0}, {0, 6, 8, 13, 0}, {0, 7, 10, 14, 0},
+ {0, 8, 11, 16, 0}, {0, 9, 12, 18, 0}, {0, 10, 13, 20, 0},
+ {0, 11, 15, 23, 0}, {0, 13, 17, 25, 0}
+};
+#endif
+
+
+#ifndef H264DEC_OMXDL
+/* mapping of raster scan block index to 4x4 block index */
+static const u32 mb4x4Index[16] =
+ {0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15};
+
+typedef struct {
+ const u8 *tc0;
+ u32 alpha;
+ u32 beta;
+} edgeThreshold_t;
+
+typedef struct {
+ u32 top;
+ u32 left;
+} bS_t;
+
+enum { TOP = 0, LEFT = 1, INNER = 2 };
+#endif /* H264DEC_OMXDL */
+
+#define FILTER_LEFT_EDGE 0x04
+#define FILTER_TOP_EDGE 0x02
+#define FILTER_INNER_EDGE 0x01
+
+
+/* clipping table defined in intra_prediction.c */
+extern const u8 h264bsdClip[];
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static u32 InnerBoundaryStrength(mbStorage_t *mb1, u32 i1, u32 i2);
+
+#ifndef H264DEC_OMXDL
+static u32 EdgeBoundaryStrength(mbStorage_t *mb1, mbStorage_t *mb2,
+ u32 i1, u32 i2);
+#else
+static u32 InnerBoundaryStrength2(mbStorage_t *mb1, u32 i1, u32 i2);
+static u32 EdgeBoundaryStrengthLeft(mbStorage_t *mb1, mbStorage_t *mb2);
+static u32 EdgeBoundaryStrengthTop(mbStorage_t *mb1, mbStorage_t *mb2);
+#endif
+
+static u32 IsSliceBoundaryOnLeft(mbStorage_t *mb);
+
+static u32 IsSliceBoundaryOnTop(mbStorage_t *mb);
+
+static u32 GetMbFilteringFlags(mbStorage_t *mb);
+
+#ifndef H264DEC_OMXDL
+
+static u32 GetBoundaryStrengths(mbStorage_t *mb, bS_t *bs, u32 flags);
+
+static void FilterLuma(u8 *data, bS_t *bS, edgeThreshold_t *thresholds,
+ u32 imageWidth);
+
+static void FilterChroma(u8 *cb, u8 *cr, bS_t *bS, edgeThreshold_t *thresholds,
+ u32 imageWidth);
+
+static void FilterVerLumaEdge( u8 *data, u32 bS, edgeThreshold_t *thresholds,
+ u32 imageWidth);
+static void FilterHorLumaEdge( u8 *data, u32 bS, edgeThreshold_t *thresholds,
+ i32 imageWidth);
+static void FilterHorLuma( u8 *data, u32 bS, edgeThreshold_t *thresholds,
+ i32 imageWidth);
+
+static void FilterVerChromaEdge( u8 *data, u32 bS, edgeThreshold_t *thresholds,
+ u32 imageWidth);
+static void FilterHorChromaEdge( u8 *data, u32 bS, edgeThreshold_t *thresholds,
+ i32 imageWidth);
+static void FilterHorChroma( u8 *data, u32 bS, edgeThreshold_t *thresholds,
+ i32 imageWidth);
+
+static void GetLumaEdgeThresholds(
+ edgeThreshold_t *thresholds,
+ mbStorage_t *mb,
+ u32 filteringFlags);
+
+static void GetChromaEdgeThresholds(
+ edgeThreshold_t *thresholds,
+ mbStorage_t *mb,
+ u32 filteringFlags,
+ i32 chromaQpIndexOffset);
+
+#else /* H264DEC_OMXDL */
+
+static u32 GetBoundaryStrengths(mbStorage_t *mb, u8 (*bs)[16], u32 flags);
+
+static void GetLumaEdgeThresholds(
+ mbStorage_t *mb,
+ u8 (*alpha)[2],
+ u8 (*beta)[2],
+ u8 (*threshold)[16],
+ u8 (*bs)[16],
+ u32 filteringFlags );
+
+static void GetChromaEdgeThresholds(
+ mbStorage_t *mb,
+ u8 (*alpha)[2],
+ u8 (*beta)[2],
+ u8 (*threshold)[8],
+ u8 (*bs)[16],
+ u32 filteringFlags,
+ i32 chromaQpIndexOffset);
+
+#endif /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+
+ Function: IsSliceBoundaryOnLeft
+
+ Functional description:
+ Function to determine if there is a slice boundary on the left side
+ of a macroblock.
+
+------------------------------------------------------------------------------*/
+u32 IsSliceBoundaryOnLeft(mbStorage_t *mb)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(mb && mb->mbA);
+
+ if (mb->sliceId != mb->mbA->sliceId)
+ return(HANTRO_TRUE);
+ else
+ return(HANTRO_FALSE);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: IsSliceBoundaryOnTop
+
+ Functional description:
+ Function to determine if there is a slice boundary above the
+ current macroblock.
+
+------------------------------------------------------------------------------*/
+u32 IsSliceBoundaryOnTop(mbStorage_t *mb)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(mb && mb->mbB);
+
+ if (mb->sliceId != mb->mbB->sliceId)
+ return(HANTRO_TRUE);
+ else
+ return(HANTRO_FALSE);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: GetMbFilteringFlags
+
+ Functional description:
+ Function to determine which edges of a macroblock has to be
+ filtered. Output is a bit-wise OR of FILTER_LEFT_EDGE,
+ FILTER_TOP_EDGE and FILTER_INNER_EDGE, depending on which edges
+ shall be filtered.
+
+------------------------------------------------------------------------------*/
+u32 GetMbFilteringFlags(mbStorage_t *mb)
+{
+
+/* Variables */
+
+ u32 flags = 0;
+
+/* Code */
+
+ ASSERT(mb);
+
+ /* nothing will be filtered if disableDeblockingFilterIdc == 1 */
+ if (mb->disableDeblockingFilterIdc != 1)
+ {
+ flags |= FILTER_INNER_EDGE;
+
+ /* filterLeftMbEdgeFlag, left mb is MB_A */
+ if (mb->mbA &&
+ ((mb->disableDeblockingFilterIdc != 2) ||
+ !IsSliceBoundaryOnLeft(mb)))
+ flags |= FILTER_LEFT_EDGE;
+
+ /* filterTopMbEdgeFlag */
+ if (mb->mbB &&
+ ((mb->disableDeblockingFilterIdc != 2) ||
+ !IsSliceBoundaryOnTop(mb)))
+ flags |= FILTER_TOP_EDGE;
+ }
+
+ return(flags);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: InnerBoundaryStrength
+
+ Functional description:
+ Function to calculate boundary strength value bs for an inner
+ edge of a macroblock. Macroblock type is checked before this is
+ called -> no intra mb condition here.
+
+------------------------------------------------------------------------------*/
+u32 InnerBoundaryStrength(mbStorage_t *mb1, u32 ind1, u32 ind2)
+{
+ i32 tmp1, tmp2;
+ i32 mv1, mv2, mv3, mv4;
+
+ tmp1 = mb1->totalCoeff[ind1];
+ tmp2 = mb1->totalCoeff[ind2];
+ mv1 = mb1->mv[ind1].hor;
+ mv2 = mb1->mv[ind2].hor;
+ mv3 = mb1->mv[ind1].ver;
+ mv4 = mb1->mv[ind2].ver;
+
+ if (tmp1 || tmp2)
+ {
+ return 2;
+ }
+ else if ( (ABS(mv1 - mv2) >= 4) || (ABS(mv3 - mv4) >= 4) ||
+ (mb1->refAddr[ind1 >> 2] != mb1->refAddr[ind2 >> 2]) )
+ {
+ return 1;
+ }
+ else
+ return 0;
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: InnerBoundaryStrength2
+
+ Functional description:
+ Function to calculate boundary strength value bs for an inner
+ edge of a macroblock. The function is the same as
+ InnerBoundaryStrength but without checking totalCoeff.
+
+------------------------------------------------------------------------------*/
+u32 InnerBoundaryStrength2(mbStorage_t *mb1, u32 ind1, u32 ind2)
+{
+ i32 tmp1, tmp2, tmp3, tmp4;
+
+ tmp1 = mb1->mv[ind1].hor;
+ tmp2 = mb1->mv[ind2].hor;
+ tmp3 = mb1->mv[ind1].ver;
+ tmp4 = mb1->mv[ind2].ver;
+
+ if ( (ABS(tmp1 - tmp2) >= 4) || (ABS(tmp3 - tmp4) >= 4) ||
+ (mb1->refAddr[ind1 >> 2] != mb1->refAddr[ind2 >> 2]))
+ {
+ return 1;
+ }
+ else
+ return 0;
+}
+#ifndef H264DEC_OMXDL
+/*------------------------------------------------------------------------------
+
+ Function: EdgeBoundaryStrength
+
+ Functional description:
+ Function to calculate boundary strength value bs for left- or
+ top-most edge of a macroblock. Macroblock types are checked
+ before this is called -> no intra mb conditions here.
+
+------------------------------------------------------------------------------*/
+u32 EdgeBoundaryStrength(mbStorage_t *mb1, mbStorage_t *mb2,
+ u32 ind1, u32 ind2)
+{
+
+ if (mb1->totalCoeff[ind1] || mb2->totalCoeff[ind2])
+ {
+ return 2;
+ }
+ else if ((mb1->refAddr[ind1 >> 2] != mb2->refAddr[ind2 >> 2]) ||
+ (ABS(mb1->mv[ind1].hor - mb2->mv[ind2].hor) >= 4) ||
+ (ABS(mb1->mv[ind1].ver - mb2->mv[ind2].ver) >= 4))
+ {
+ return 1;
+ }
+ else
+ return 0;
+}
+
+#else /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+
+ Function: EdgeBoundaryStrengthTop
+
+ Functional description:
+ Function to calculate boundary strength value bs for
+ top-most edge of a macroblock. Macroblock types are checked
+ before this is called -> no intra mb conditions here.
+
+------------------------------------------------------------------------------*/
+u32 EdgeBoundaryStrengthTop(mbStorage_t *mb1, mbStorage_t *mb2)
+{
+ u32 topBs = 0;
+ u32 tmp1, tmp2, tmp3, tmp4;
+
+ tmp1 = mb1->totalCoeff[0];
+ tmp2 = mb2->totalCoeff[10];
+ tmp3 = mb1->totalCoeff[1];
+ tmp4 = mb2->totalCoeff[11];
+ if (tmp1 || tmp2)
+ {
+ topBs = 2<<0;
+ }
+ else if ((ABS(mb1->mv[0].hor - mb2->mv[10].hor) >= 4) ||
+ (ABS(mb1->mv[0].ver - mb2->mv[10].ver) >= 4) ||
+ (mb1->refAddr[0] != mb2->refAddr[10 >> 2]))
+ {
+ topBs = 1<<0;
+ }
+ tmp1 = mb1->totalCoeff[4];
+ tmp2 = mb2->totalCoeff[14];
+ if (tmp3 || tmp4)
+ {
+ topBs += 2<<8;
+ }
+ else if ((ABS(mb1->mv[1].hor - mb2->mv[11].hor) >= 4) ||
+ (ABS(mb1->mv[1].ver - mb2->mv[11].ver) >= 4) ||
+ (mb1->refAddr[0] != mb2->refAddr[11 >> 2]))
+ {
+ topBs += 1<<8;
+ }
+ tmp3 = mb1->totalCoeff[5];
+ tmp4 = mb2->totalCoeff[15];
+ if (tmp1 || tmp2)
+ {
+ topBs += 2<<16;
+ }
+ else if ((ABS(mb1->mv[4].hor - mb2->mv[14].hor) >= 4) ||
+ (ABS(mb1->mv[4].ver - mb2->mv[14].ver) >= 4) ||
+ (mb1->refAddr[4 >> 2] != mb2->refAddr[14 >> 2]))
+ {
+ topBs += 1<<16;
+ }
+ if (tmp3 || tmp4)
+ {
+ topBs += 2<<24;
+ }
+ else if ((ABS(mb1->mv[5].hor - mb2->mv[15].hor) >= 4) ||
+ (ABS(mb1->mv[5].ver - mb2->mv[15].ver) >= 4) ||
+ (mb1->refAddr[5 >> 2] != mb2->refAddr[15 >> 2]))
+ {
+ topBs += 1<<24;
+ }
+
+ return topBs;
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: EdgeBoundaryStrengthLeft
+
+ Functional description:
+ Function to calculate boundary strength value bs for left-
+ edge of a macroblock. Macroblock types are checked
+ before this is called -> no intra mb conditions here.
+
+------------------------------------------------------------------------------*/
+u32 EdgeBoundaryStrengthLeft(mbStorage_t *mb1, mbStorage_t *mb2)
+{
+ u32 leftBs = 0;
+ u32 tmp1, tmp2, tmp3, tmp4;
+
+ tmp1 = mb1->totalCoeff[0];
+ tmp2 = mb2->totalCoeff[5];
+ tmp3 = mb1->totalCoeff[2];
+ tmp4 = mb2->totalCoeff[7];
+
+ if (tmp1 || tmp2)
+ {
+ leftBs = 2<<0;
+ }
+ else if ((ABS(mb1->mv[0].hor - mb2->mv[5].hor) >= 4) ||
+ (ABS(mb1->mv[0].ver - mb2->mv[5].ver) >= 4) ||
+ (mb1->refAddr[0] != mb2->refAddr[5 >> 2]))
+ {
+ leftBs = 1<<0;
+ }
+ tmp1 = mb1->totalCoeff[8];
+ tmp2 = mb2->totalCoeff[13];
+ if (tmp3 || tmp4)
+ {
+ leftBs += 2<<8;
+ }
+ else if ((ABS(mb1->mv[2].hor - mb2->mv[7].hor) >= 4) ||
+ (ABS(mb1->mv[2].ver - mb2->mv[7].ver) >= 4) ||
+ (mb1->refAddr[0] != mb2->refAddr[7 >> 2]))
+ {
+ leftBs += 1<<8;
+ }
+ tmp3 = mb1->totalCoeff[10];
+ tmp4 = mb2->totalCoeff[15];
+ if (tmp1 || tmp2)
+ {
+ leftBs += 2<<16;
+ }
+ else if ((ABS(mb1->mv[8].hor - mb2->mv[13].hor) >= 4) ||
+ (ABS(mb1->mv[8].ver - mb2->mv[13].ver) >= 4) ||
+ (mb1->refAddr[8 >> 2] != mb2->refAddr[13 >> 2]))
+ {
+ leftBs += 1<<16;
+ }
+ if (tmp3 || tmp4)
+ {
+ leftBs += 2<<24;
+ }
+ else if ((ABS(mb1->mv[10].hor - mb2->mv[15].hor) >= 4) ||
+ (ABS(mb1->mv[10].ver - mb2->mv[15].ver) >= 4) ||
+ (mb1->refAddr[10 >> 2] != mb2->refAddr[15 >> 2]))
+ {
+ leftBs += 1<<24;
+ }
+
+ return leftBs;
+}
+#endif /* H264DEC_OMXDL */
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdFilterPicture
+
+ Functional description:
+ Perform deblocking filtering for a picture. Filter does not copy
+ the original picture anywhere but filtering is performed directly
+ on the original image. Parameters controlling the filtering process
+ are computed based on information in macroblock structures of the
+ filtered macroblock, macroblock above and macroblock on the left of
+ the filtered one.
+
+ Inputs:
+ image pointer to image to be filtered
+ mb pointer to macroblock data structure of the top-left
+ macroblock of the picture
+
+ Outputs:
+ image filtered image stored here
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+#ifndef H264DEC_OMXDL
+void h264bsdFilterPicture(
+ image_t *image,
+ mbStorage_t *mb)
+{
+
+/* Variables */
+
+ u32 flags;
+ u32 picSizeInMbs, mbRow, mbCol;
+ u32 picWidthInMbs;
+ u8 *data;
+ mbStorage_t *pMb;
+ bS_t bS[16];
+ edgeThreshold_t thresholds[3];
+
+/* Code */
+
+ ASSERT(image);
+ ASSERT(mb);
+ ASSERT(image->data);
+ ASSERT(image->width);
+ ASSERT(image->height);
+
+ picWidthInMbs = image->width;
+ data = image->data;
+ picSizeInMbs = picWidthInMbs * image->height;
+
+ pMb = mb;
+
+ for (mbRow = 0, mbCol = 0; mbRow < image->height; pMb++)
+ {
+ flags = GetMbFilteringFlags(pMb);
+
+ if (flags)
+ {
+ /* GetBoundaryStrengths function returns non-zero value if any of
+ * the bS values for the macroblock being processed was non-zero */
+ if (GetBoundaryStrengths(pMb, bS, flags))
+ {
+ /* luma */
+ GetLumaEdgeThresholds(thresholds, pMb, flags);
+ data = image->data + mbRow * picWidthInMbs * 256 + mbCol * 16;
+
+ FilterLuma((u8*)data, bS, thresholds, picWidthInMbs*16);
+
+ /* chroma */
+ GetChromaEdgeThresholds(thresholds, pMb, flags,
+ pMb->chromaQpIndexOffset);
+ data = image->data + picSizeInMbs * 256 +
+ mbRow * picWidthInMbs * 64 + mbCol * 8;
+
+ FilterChroma((u8*)data, data + 64*picSizeInMbs, bS,
+ thresholds, picWidthInMbs*8);
+
+ }
+ }
+
+ mbCol++;
+ if (mbCol == picWidthInMbs)
+ {
+ mbCol = 0;
+ mbRow++;
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: FilterVerLumaEdge
+
+ Functional description:
+ Filter one vertical 4-pixel luma edge.
+
+------------------------------------------------------------------------------*/
+void FilterVerLumaEdge(
+ u8 *data,
+ u32 bS,
+ edgeThreshold_t *thresholds,
+ u32 imageWidth)
+{
+
+/* Variables */
+
+ i32 delta, tc, tmp;
+ u32 i;
+ u8 p0, q0, p1, q1, p2, q2;
+ u32 tmpFlag;
+ const u8 *clp = h264bsdClip + 512;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(bS && bS <= 4);
+ ASSERT(thresholds);
+
+ if (bS < 4)
+ {
+ tc = thresholds->tc0[bS-1];
+ tmp = tc;
+ for (i = 4; i; i--, data += imageWidth)
+ {
+ p1 = data[-2]; p0 = data[-1];
+ q0 = data[0]; q1 = data[1];
+ if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) &&
+ ((unsigned)ABS(p1-p0) < thresholds->beta) &&
+ ((unsigned)ABS(q1-q0) < thresholds->beta) )
+ {
+ p2 = data[-3];
+ q2 = data[2];
+
+ if ((unsigned)ABS(p2-p0) < thresholds->beta)
+ {
+ data[-2] = (u8)(p1 + CLIP3(-tc,tc,
+ (p2 + ((p0 + q0 + 1) >> 1) - (p1 << 1)) >> 1));
+ tmp++;
+ }
+
+ if ((unsigned)ABS(q2-q0) < thresholds->beta)
+ {
+ data[1] = (u8)(q1 + CLIP3(-tc,tc,
+ (q2 + ((p0 + q0 + 1) >> 1) - (q1 << 1)) >> 1));
+ tmp++;
+ }
+
+ delta = CLIP3(-tmp, tmp, ((((q0 - p0) << 2) +
+ (p1 - q1) + 4) >> 3));
+
+ p0 = clp[p0 + delta];
+ q0 = clp[q0 - delta];
+ tmp = tc;
+ data[-1] = p0;
+ data[ 0] = q0;
+ }
+ }
+ }
+ else
+ {
+ for (i = 4; i; i--, data += imageWidth)
+ {
+ p1 = data[-2]; p0 = data[-1];
+ q0 = data[0]; q1 = data[1];
+ if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) &&
+ ((unsigned)ABS(p1-p0) < thresholds->beta) &&
+ ((unsigned)ABS(q1-q0) < thresholds->beta) )
+ {
+ tmpFlag =
+ ((unsigned)ABS(p0-q0) < ((thresholds->alpha >> 2) +2)) ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ p2 = data[-3];
+ q2 = data[2];
+
+ if (tmpFlag && (unsigned)ABS(p2-p0) < thresholds->beta)
+ {
+ tmp = p1 + p0 + q0;
+ data[-1] = (u8)((p2 + 2 * tmp + q1 + 4) >> 3);
+ data[-2] = (u8)((p2 + tmp + 2) >> 2);
+ data[-3] = (u8)((2 * data[-4] + 3 * p2 + tmp + 4) >> 3);
+ }
+ else
+ data[-1] = (2 * p1 + p0 + q1 + 2) >> 2;
+
+ if (tmpFlag && (unsigned)ABS(q2-q0) < thresholds->beta)
+ {
+ tmp = p0 + q0 + q1;
+ data[0] = (u8)((p1 + 2 * tmp + q2 + 4) >> 3);
+ data[1] = (u8)((tmp + q2 + 2) >> 2);
+ data[2] = (u8)((2 * data[3] + 3 * q2 + tmp + 4) >> 3);
+ }
+ else
+ data[0] = (u8)((2 * q1 + q0 + p1 + 2) >> 2);
+ }
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: FilterHorLumaEdge
+
+ Functional description:
+ Filter one horizontal 4-pixel luma edge
+
+------------------------------------------------------------------------------*/
+void FilterHorLumaEdge(
+ u8 *data,
+ u32 bS,
+ edgeThreshold_t *thresholds,
+ i32 imageWidth)
+{
+
+/* Variables */
+
+ i32 delta, tc, tmp;
+ u32 i;
+ u8 p0, q0, p1, q1, p2, q2;
+ const u8 *clp = h264bsdClip + 512;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(bS < 4);
+ ASSERT(thresholds);
+
+ tc = thresholds->tc0[bS-1];
+ tmp = tc;
+ for (i = 4; i; i--, data++)
+ {
+ p1 = data[-imageWidth*2]; p0 = data[-imageWidth];
+ q0 = data[0]; q1 = data[imageWidth];
+ if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) &&
+ ((unsigned)ABS(p1-p0) < thresholds->beta) &&
+ ((unsigned)ABS(q1-q0) < thresholds->beta) )
+ {
+ p2 = data[-imageWidth*3];
+
+ if ((unsigned)ABS(p2-p0) < thresholds->beta)
+ {
+ data[-imageWidth*2] = (u8)(p1 + CLIP3(-tc,tc,
+ (p2 + ((p0 + q0 + 1) >> 1) - (p1 << 1)) >> 1));
+ tmp++;
+ }
+
+ q2 = data[imageWidth*2];
+
+ if ((unsigned)ABS(q2-q0) < thresholds->beta)
+ {
+ data[imageWidth] = (u8)(q1 + CLIP3(-tc,tc,
+ (q2 + ((p0 + q0 + 1) >> 1) - (q1 << 1)) >> 1));
+ tmp++;
+ }
+
+ delta = CLIP3(-tmp, tmp, ((((q0 - p0) << 2) +
+ (p1 - q1) + 4) >> 3));
+
+ p0 = clp[p0 + delta];
+ q0 = clp[q0 - delta];
+ tmp = tc;
+ data[-imageWidth] = p0;
+ data[ 0] = q0;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: FilterHorLuma
+
+ Functional description:
+ Filter all four successive horizontal 4-pixel luma edges. This can
+ be done when bS is equal to all four edges.
+
+------------------------------------------------------------------------------*/
+void FilterHorLuma(
+ u8 *data,
+ u32 bS,
+ edgeThreshold_t *thresholds,
+ i32 imageWidth)
+{
+
+/* Variables */
+
+ i32 delta, tc, tmp;
+ u32 i;
+ u8 p0, q0, p1, q1, p2, q2;
+ u32 tmpFlag;
+ const u8 *clp = h264bsdClip + 512;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(bS <= 4);
+ ASSERT(thresholds);
+
+ if (bS < 4)
+ {
+ tc = thresholds->tc0[bS-1];
+ tmp = tc;
+ for (i = 16; i; i--, data++)
+ {
+ p1 = data[-imageWidth*2]; p0 = data[-imageWidth];
+ q0 = data[0]; q1 = data[imageWidth];
+ if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) &&
+ ((unsigned)ABS(p1-p0) < thresholds->beta) &&
+ ((unsigned)ABS(q1-q0) < thresholds->beta) )
+ {
+ p2 = data[-imageWidth*3];
+
+ if ((unsigned)ABS(p2-p0) < thresholds->beta)
+ {
+ data[-imageWidth*2] = (u8)(p1 + CLIP3(-tc,tc,
+ (p2 + ((p0 + q0 + 1) >> 1) - (p1 << 1)) >> 1));
+ tmp++;
+ }
+
+ q2 = data[imageWidth*2];
+
+ if ((unsigned)ABS(q2-q0) < thresholds->beta)
+ {
+ data[imageWidth] = (u8)(q1 + CLIP3(-tc,tc,
+ (q2 + ((p0 + q0 + 1) >> 1) - (q1 << 1)) >> 1));
+ tmp++;
+ }
+
+ delta = CLIP3(-tmp, tmp, ((((q0 - p0) << 2) +
+ (p1 - q1) + 4) >> 3));
+
+ p0 = clp[p0 + delta];
+ q0 = clp[q0 - delta];
+ tmp = tc;
+ data[-imageWidth] = p0;
+ data[ 0] = q0;
+ }
+ }
+ }
+ else
+ {
+ for (i = 16; i; i--, data++)
+ {
+ p1 = data[-imageWidth*2]; p0 = data[-imageWidth];
+ q0 = data[0]; q1 = data[imageWidth];
+ if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) &&
+ ((unsigned)ABS(p1-p0) < thresholds->beta) &&
+ ((unsigned)ABS(q1-q0) < thresholds->beta) )
+ {
+ tmpFlag = ((unsigned)ABS(p0-q0) < ((thresholds->alpha >> 2) +2))
+ ? HANTRO_TRUE : HANTRO_FALSE;
+
+ p2 = data[-imageWidth*3];
+ q2 = data[imageWidth*2];
+
+ if (tmpFlag && (unsigned)ABS(p2-p0) < thresholds->beta)
+ {
+ tmp = p1 + p0 + q0;
+ data[-imageWidth] = (u8)((p2 + 2 * tmp + q1 + 4) >> 3);
+ data[-imageWidth*2] = (u8)((p2 + tmp + 2) >> 2);
+ data[-imageWidth*3] = (u8)((2 * data[-imageWidth*4] +
+ 3 * p2 + tmp + 4) >> 3);
+ }
+ else
+ data[-imageWidth] = (u8)((2 * p1 + p0 + q1 + 2) >> 2);
+
+ if (tmpFlag && (unsigned)ABS(q2-q0) < thresholds->beta)
+ {
+ tmp = p0 + q0 + q1;
+ data[ 0] = (u8)((p1 + 2 * tmp + q2 + 4) >> 3);
+ data[imageWidth] = (u8)((tmp + q2 + 2) >> 2);
+ data[imageWidth*2] = (u8)((2 * data[imageWidth*3] +
+ 3 * q2 + tmp + 4) >> 3);
+ }
+ else
+ data[0] = (2 * q1 + q0 + p1 + 2) >> 2;
+ }
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: FilterVerChromaEdge
+
+ Functional description:
+ Filter one vertical 2-pixel chroma edge
+
+------------------------------------------------------------------------------*/
+void FilterVerChromaEdge(
+ u8 *data,
+ u32 bS,
+ edgeThreshold_t *thresholds,
+ u32 width)
+{
+
+/* Variables */
+
+ i32 delta, tc;
+ u8 p0, q0, p1, q1;
+ const u8 *clp = h264bsdClip + 512;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(bS <= 4);
+ ASSERT(thresholds);
+
+ p1 = data[-2]; p0 = data[-1];
+ q0 = data[0]; q1 = data[1];
+ if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) &&
+ ((unsigned)ABS(p1-p0) < thresholds->beta) &&
+ ((unsigned)ABS(q1-q0) < thresholds->beta) )
+ {
+ if (bS < 4)
+ {
+ tc = thresholds->tc0[bS-1] + 1;
+ delta = CLIP3(-tc, tc, ((((q0 - p0) << 2) +
+ (p1 - q1) + 4) >> 3));
+ p0 = clp[p0 + delta];
+ q0 = clp[q0 - delta];
+ data[-1] = p0;
+ data[ 0] = q0;
+ }
+ else
+ {
+ data[-1] = (2 * p1 + p0 + q1 + 2) >> 2;
+ data[ 0] = (2 * q1 + q0 + p1 + 2) >> 2;
+ }
+ }
+ data += width;
+ p1 = data[-2]; p0 = data[-1];
+ q0 = data[0]; q1 = data[1];
+ if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) &&
+ ((unsigned)ABS(p1-p0) < thresholds->beta) &&
+ ((unsigned)ABS(q1-q0) < thresholds->beta) )
+ {
+ if (bS < 4)
+ {
+ tc = thresholds->tc0[bS-1] + 1;
+ delta = CLIP3(-tc, tc, ((((q0 - p0) << 2) +
+ (p1 - q1) + 4) >> 3));
+ p0 = clp[p0 + delta];
+ q0 = clp[q0 - delta];
+ data[-1] = p0;
+ data[ 0] = q0;
+ }
+ else
+ {
+ data[-1] = (2 * p1 + p0 + q1 + 2) >> 2;
+ data[ 0] = (2 * q1 + q0 + p1 + 2) >> 2;
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: FilterHorChromaEdge
+
+ Functional description:
+ Filter one horizontal 2-pixel chroma edge
+
+------------------------------------------------------------------------------*/
+void FilterHorChromaEdge(
+ u8 *data,
+ u32 bS,
+ edgeThreshold_t *thresholds,
+ i32 width)
+{
+
+/* Variables */
+
+ i32 delta, tc;
+ u32 i;
+ u8 p0, q0, p1, q1;
+ const u8 *clp = h264bsdClip + 512;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(bS < 4);
+ ASSERT(thresholds);
+
+ tc = thresholds->tc0[bS-1] + 1;
+ for (i = 2; i; i--, data++)
+ {
+ p1 = data[-width*2]; p0 = data[-width];
+ q0 = data[0]; q1 = data[width];
+ if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) &&
+ ((unsigned)ABS(p1-p0) < thresholds->beta) &&
+ ((unsigned)ABS(q1-q0) < thresholds->beta) )
+ {
+ delta = CLIP3(-tc, tc, ((((q0 - p0) << 2) +
+ (p1 - q1) + 4) >> 3));
+ p0 = clp[p0 + delta];
+ q0 = clp[q0 - delta];
+ data[-width] = p0;
+ data[ 0] = q0;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: FilterHorChroma
+
+ Functional description:
+ Filter all four successive horizontal 2-pixel chroma edges. This
+ can be done if bS is equal for all four edges.
+
+------------------------------------------------------------------------------*/
+void FilterHorChroma(
+ u8 *data,
+ u32 bS,
+ edgeThreshold_t *thresholds,
+ i32 width)
+{
+
+/* Variables */
+
+ i32 delta, tc;
+ u32 i;
+ u8 p0, q0, p1, q1;
+ const u8 *clp = h264bsdClip + 512;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(bS <= 4);
+ ASSERT(thresholds);
+
+ if (bS < 4)
+ {
+ tc = thresholds->tc0[bS-1] + 1;
+ for (i = 8; i; i--, data++)
+ {
+ p1 = data[-width*2]; p0 = data[-width];
+ q0 = data[0]; q1 = data[width];
+ if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) &&
+ ((unsigned)ABS(p1-p0) < thresholds->beta) &&
+ ((unsigned)ABS(q1-q0) < thresholds->beta) )
+ {
+ delta = CLIP3(-tc, tc, ((((q0 - p0) << 2) +
+ (p1 - q1) + 4) >> 3));
+ p0 = clp[p0 + delta];
+ q0 = clp[q0 - delta];
+ data[-width] = p0;
+ data[ 0] = q0;
+ }
+ }
+ }
+ else
+ {
+ for (i = 8; i; i--, data++)
+ {
+ p1 = data[-width*2]; p0 = data[-width];
+ q0 = data[0]; q1 = data[width];
+ if ( ((unsigned)ABS(p0-q0) < thresholds->alpha) &&
+ ((unsigned)ABS(p1-p0) < thresholds->beta) &&
+ ((unsigned)ABS(q1-q0) < thresholds->beta) )
+ {
+ data[-width] = (2 * p1 + p0 + q1 + 2) >> 2;
+ data[ 0] = (2 * q1 + q0 + p1 + 2) >> 2;
+ }
+ }
+ }
+
+}
+
+
+/*------------------------------------------------------------------------------
+
+ Function: GetBoundaryStrengths
+
+ Functional description:
+ Function to calculate boundary strengths for all edges of a
+ macroblock. Function returns HANTRO_TRUE if any of the bS values for
+ the macroblock had non-zero value, HANTRO_FALSE otherwise.
+
+------------------------------------------------------------------------------*/
+u32 GetBoundaryStrengths(mbStorage_t *mb, bS_t *bS, u32 flags)
+{
+
+/* Variables */
+
+ /* this flag is set HANTRO_TRUE as soon as any boundary strength value is
+ * non-zero */
+ u32 nonZeroBs = HANTRO_FALSE;
+
+/* Code */
+
+ ASSERT(mb);
+ ASSERT(bS);
+ ASSERT(flags);
+
+ /* top edges */
+ if (flags & FILTER_TOP_EDGE)
+ {
+ if (IS_INTRA_MB(*mb) || IS_INTRA_MB(*mb->mbB))
+ {
+ bS[0].top = bS[1].top = bS[2].top = bS[3].top = 4;
+ nonZeroBs = HANTRO_TRUE;
+ }
+ else
+ {
+ bS[0].top = EdgeBoundaryStrength(mb, mb->mbB, 0, 10);
+ bS[1].top = EdgeBoundaryStrength(mb, mb->mbB, 1, 11);
+ bS[2].top = EdgeBoundaryStrength(mb, mb->mbB, 4, 14);
+ bS[3].top = EdgeBoundaryStrength(mb, mb->mbB, 5, 15);
+ if (bS[0].top || bS[1].top || bS[2].top || bS[3].top)
+ nonZeroBs = HANTRO_TRUE;
+ }
+ }
+ else
+ {
+ bS[0].top = bS[1].top = bS[2].top = bS[3].top = 0;
+ }
+
+ /* left edges */
+ if (flags & FILTER_LEFT_EDGE)
+ {
+ if (IS_INTRA_MB(*mb) || IS_INTRA_MB(*mb->mbA))
+ {
+ bS[0].left = bS[4].left = bS[8].left = bS[12].left = 4;
+ nonZeroBs = HANTRO_TRUE;
+ }
+ else
+ {
+ bS[0].left = EdgeBoundaryStrength(mb, mb->mbA, 0, 5);
+ bS[4].left = EdgeBoundaryStrength(mb, mb->mbA, 2, 7);
+ bS[8].left = EdgeBoundaryStrength(mb, mb->mbA, 8, 13);
+ bS[12].left = EdgeBoundaryStrength(mb, mb->mbA, 10, 15);
+ if (!nonZeroBs &&
+ (bS[0].left || bS[4].left || bS[8].left || bS[12].left))
+ nonZeroBs = HANTRO_TRUE;
+ }
+ }
+ else
+ {
+ bS[0].left = bS[4].left = bS[8].left = bS[12].left = 0;
+ }
+
+ /* inner edges */
+ if (IS_INTRA_MB(*mb))
+ {
+ bS[4].top = bS[5].top = bS[6].top = bS[7].top =
+ bS[8].top = bS[9].top = bS[10].top = bS[11].top =
+ bS[12].top = bS[13].top = bS[14].top = bS[15].top = 3;
+
+ bS[1].left = bS[2].left = bS[3].left =
+ bS[5].left = bS[6].left = bS[7].left =
+ bS[9].left = bS[10].left = bS[11].left =
+ bS[13].left = bS[14].left = bS[15].left = 3;
+ nonZeroBs = HANTRO_TRUE;
+ }
+ else
+ {
+ /* 16x16 inter mb -> ref addresses or motion vectors cannot differ,
+ * only check if either of the blocks contain coefficients */
+ if (h264bsdNumMbPart(mb->mbType) == 1)
+ {
+ bS[4].top = mb->totalCoeff[2] || mb->totalCoeff[0] ? 2 : 0;
+ bS[5].top = mb->totalCoeff[3] || mb->totalCoeff[1] ? 2 : 0;
+ bS[6].top = mb->totalCoeff[6] || mb->totalCoeff[4] ? 2 : 0;
+ bS[7].top = mb->totalCoeff[7] || mb->totalCoeff[5] ? 2 : 0;
+ bS[8].top = mb->totalCoeff[8] || mb->totalCoeff[2] ? 2 : 0;
+ bS[9].top = mb->totalCoeff[9] || mb->totalCoeff[3] ? 2 : 0;
+ bS[10].top = mb->totalCoeff[12] || mb->totalCoeff[6] ? 2 : 0;
+ bS[11].top = mb->totalCoeff[13] || mb->totalCoeff[7] ? 2 : 0;
+ bS[12].top = mb->totalCoeff[10] || mb->totalCoeff[8] ? 2 : 0;
+ bS[13].top = mb->totalCoeff[11] || mb->totalCoeff[9] ? 2 : 0;
+ bS[14].top = mb->totalCoeff[14] || mb->totalCoeff[12] ? 2 : 0;
+ bS[15].top = mb->totalCoeff[15] || mb->totalCoeff[13] ? 2 : 0;
+
+ bS[1].left = mb->totalCoeff[1] || mb->totalCoeff[0] ? 2 : 0;
+ bS[2].left = mb->totalCoeff[4] || mb->totalCoeff[1] ? 2 : 0;
+ bS[3].left = mb->totalCoeff[5] || mb->totalCoeff[4] ? 2 : 0;
+ bS[5].left = mb->totalCoeff[3] || mb->totalCoeff[2] ? 2 : 0;
+ bS[6].left = mb->totalCoeff[6] || mb->totalCoeff[3] ? 2 : 0;
+ bS[7].left = mb->totalCoeff[7] || mb->totalCoeff[6] ? 2 : 0;
+ bS[9].left = mb->totalCoeff[9] || mb->totalCoeff[8] ? 2 : 0;
+ bS[10].left = mb->totalCoeff[12] || mb->totalCoeff[9] ? 2 : 0;
+ bS[11].left = mb->totalCoeff[13] || mb->totalCoeff[12] ? 2 : 0;
+ bS[13].left = mb->totalCoeff[11] || mb->totalCoeff[10] ? 2 : 0;
+ bS[14].left = mb->totalCoeff[14] || mb->totalCoeff[11] ? 2 : 0;
+ bS[15].left = mb->totalCoeff[15] || mb->totalCoeff[14] ? 2 : 0;
+ }
+ /* 16x8 inter mb -> ref addresses and motion vectors can be different
+ * only for the middle horizontal edge, for the other top edges it is
+ * enough to check whether the blocks contain coefficients or not. The
+ * same applies to all internal left edges. */
+ else if (mb->mbType == P_L0_L0_16x8)
+ {
+ bS[4].top = mb->totalCoeff[2] || mb->totalCoeff[0] ? 2 : 0;
+ bS[5].top = mb->totalCoeff[3] || mb->totalCoeff[1] ? 2 : 0;
+ bS[6].top = mb->totalCoeff[6] || mb->totalCoeff[4] ? 2 : 0;
+ bS[7].top = mb->totalCoeff[7] || mb->totalCoeff[5] ? 2 : 0;
+ bS[12].top = mb->totalCoeff[10] || mb->totalCoeff[8] ? 2 : 0;
+ bS[13].top = mb->totalCoeff[11] || mb->totalCoeff[9] ? 2 : 0;
+ bS[14].top = mb->totalCoeff[14] || mb->totalCoeff[12] ? 2 : 0;
+ bS[15].top = mb->totalCoeff[15] || mb->totalCoeff[13] ? 2 : 0;
+ bS[8].top = InnerBoundaryStrength(mb, 8, 2);
+ bS[9].top = InnerBoundaryStrength(mb, 9, 3);
+ bS[10].top = InnerBoundaryStrength(mb, 12, 6);
+ bS[11].top = InnerBoundaryStrength(mb, 13, 7);
+
+ bS[1].left = mb->totalCoeff[1] || mb->totalCoeff[0] ? 2 : 0;
+ bS[2].left = mb->totalCoeff[4] || mb->totalCoeff[1] ? 2 : 0;
+ bS[3].left = mb->totalCoeff[5] || mb->totalCoeff[4] ? 2 : 0;
+ bS[5].left = mb->totalCoeff[3] || mb->totalCoeff[2] ? 2 : 0;
+ bS[6].left = mb->totalCoeff[6] || mb->totalCoeff[3] ? 2 : 0;
+ bS[7].left = mb->totalCoeff[7] || mb->totalCoeff[6] ? 2 : 0;
+ bS[9].left = mb->totalCoeff[9] || mb->totalCoeff[8] ? 2 : 0;
+ bS[10].left = mb->totalCoeff[12] || mb->totalCoeff[9] ? 2 : 0;
+ bS[11].left = mb->totalCoeff[13] || mb->totalCoeff[12] ? 2 : 0;
+ bS[13].left = mb->totalCoeff[11] || mb->totalCoeff[10] ? 2 : 0;
+ bS[14].left = mb->totalCoeff[14] || mb->totalCoeff[11] ? 2 : 0;
+ bS[15].left = mb->totalCoeff[15] || mb->totalCoeff[14] ? 2 : 0;
+ }
+ /* 8x16 inter mb -> ref addresses and motion vectors can be different
+ * only for the middle vertical edge, for the other left edges it is
+ * enough to check whether the blocks contain coefficients or not. The
+ * same applies to all internal top edges. */
+ else if (mb->mbType == P_L0_L0_8x16)
+ {
+ bS[4].top = mb->totalCoeff[2] || mb->totalCoeff[0] ? 2 : 0;
+ bS[5].top = mb->totalCoeff[3] || mb->totalCoeff[1] ? 2 : 0;
+ bS[6].top = mb->totalCoeff[6] || mb->totalCoeff[4] ? 2 : 0;
+ bS[7].top = mb->totalCoeff[7] || mb->totalCoeff[5] ? 2 : 0;
+ bS[8].top = mb->totalCoeff[8] || mb->totalCoeff[2] ? 2 : 0;
+ bS[9].top = mb->totalCoeff[9] || mb->totalCoeff[3] ? 2 : 0;
+ bS[10].top = mb->totalCoeff[12] || mb->totalCoeff[6] ? 2 : 0;
+ bS[11].top = mb->totalCoeff[13] || mb->totalCoeff[7] ? 2 : 0;
+ bS[12].top = mb->totalCoeff[10] || mb->totalCoeff[8] ? 2 : 0;
+ bS[13].top = mb->totalCoeff[11] || mb->totalCoeff[9] ? 2 : 0;
+ bS[14].top = mb->totalCoeff[14] || mb->totalCoeff[12] ? 2 : 0;
+ bS[15].top = mb->totalCoeff[15] || mb->totalCoeff[13] ? 2 : 0;
+
+ bS[1].left = mb->totalCoeff[1] || mb->totalCoeff[0] ? 2 : 0;
+ bS[3].left = mb->totalCoeff[5] || mb->totalCoeff[4] ? 2 : 0;
+ bS[5].left = mb->totalCoeff[3] || mb->totalCoeff[2] ? 2 : 0;
+ bS[7].left = mb->totalCoeff[7] || mb->totalCoeff[6] ? 2 : 0;
+ bS[9].left = mb->totalCoeff[9] || mb->totalCoeff[8] ? 2 : 0;
+ bS[11].left = mb->totalCoeff[13] || mb->totalCoeff[12] ? 2 : 0;
+ bS[13].left = mb->totalCoeff[11] || mb->totalCoeff[10] ? 2 : 0;
+ bS[15].left = mb->totalCoeff[15] || mb->totalCoeff[14] ? 2 : 0;
+ bS[2].left = InnerBoundaryStrength(mb, 4, 1);
+ bS[6].left = InnerBoundaryStrength(mb, 6, 3);
+ bS[10].left = InnerBoundaryStrength(mb, 12, 9);
+ bS[14].left = InnerBoundaryStrength(mb, 14, 11);
+ }
+ else
+ {
+ bS[4].top =
+ InnerBoundaryStrength(mb, mb4x4Index[4], mb4x4Index[0]);
+ bS[5].top =
+ InnerBoundaryStrength(mb, mb4x4Index[5], mb4x4Index[1]);
+ bS[6].top =
+ InnerBoundaryStrength(mb, mb4x4Index[6], mb4x4Index[2]);
+ bS[7].top =
+ InnerBoundaryStrength(mb, mb4x4Index[7], mb4x4Index[3]);
+ bS[8].top =
+ InnerBoundaryStrength(mb, mb4x4Index[8], mb4x4Index[4]);
+ bS[9].top =
+ InnerBoundaryStrength(mb, mb4x4Index[9], mb4x4Index[5]);
+ bS[10].top =
+ InnerBoundaryStrength(mb, mb4x4Index[10], mb4x4Index[6]);
+ bS[11].top =
+ InnerBoundaryStrength(mb, mb4x4Index[11], mb4x4Index[7]);
+ bS[12].top =
+ InnerBoundaryStrength(mb, mb4x4Index[12], mb4x4Index[8]);
+ bS[13].top =
+ InnerBoundaryStrength(mb, mb4x4Index[13], mb4x4Index[9]);
+ bS[14].top =
+ InnerBoundaryStrength(mb, mb4x4Index[14], mb4x4Index[10]);
+ bS[15].top =
+ InnerBoundaryStrength(mb, mb4x4Index[15], mb4x4Index[11]);
+
+ bS[1].left =
+ InnerBoundaryStrength(mb, mb4x4Index[1], mb4x4Index[0]);
+ bS[2].left =
+ InnerBoundaryStrength(mb, mb4x4Index[2], mb4x4Index[1]);
+ bS[3].left =
+ InnerBoundaryStrength(mb, mb4x4Index[3], mb4x4Index[2]);
+ bS[5].left =
+ InnerBoundaryStrength(mb, mb4x4Index[5], mb4x4Index[4]);
+ bS[6].left =
+ InnerBoundaryStrength(mb, mb4x4Index[6], mb4x4Index[5]);
+ bS[7].left =
+ InnerBoundaryStrength(mb, mb4x4Index[7], mb4x4Index[6]);
+ bS[9].left =
+ InnerBoundaryStrength(mb, mb4x4Index[9], mb4x4Index[8]);
+ bS[10].left =
+ InnerBoundaryStrength(mb, mb4x4Index[10], mb4x4Index[9]);
+ bS[11].left =
+ InnerBoundaryStrength(mb, mb4x4Index[11], mb4x4Index[10]);
+ bS[13].left =
+ InnerBoundaryStrength(mb, mb4x4Index[13], mb4x4Index[12]);
+ bS[14].left =
+ InnerBoundaryStrength(mb, mb4x4Index[14], mb4x4Index[13]);
+ bS[15].left =
+ InnerBoundaryStrength(mb, mb4x4Index[15], mb4x4Index[14]);
+ }
+ if (!nonZeroBs &&
+ (bS[4].top || bS[5].top || bS[6].top || bS[7].top ||
+ bS[8].top || bS[9].top || bS[10].top || bS[11].top ||
+ bS[12].top || bS[13].top || bS[14].top || bS[15].top ||
+ bS[1].left || bS[2].left || bS[3].left ||
+ bS[5].left || bS[6].left || bS[7].left ||
+ bS[9].left || bS[10].left || bS[11].left ||
+ bS[13].left || bS[14].left || bS[15].left))
+ nonZeroBs = HANTRO_TRUE;
+ }
+
+ return(nonZeroBs);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: GetLumaEdgeThresholds
+
+ Functional description:
+ Compute alpha, beta and tc0 thresholds for inner, left and top
+ luma edges of a macroblock.
+
+------------------------------------------------------------------------------*/
+void GetLumaEdgeThresholds(
+ edgeThreshold_t *thresholds,
+ mbStorage_t *mb,
+ u32 filteringFlags)
+{
+
+/* Variables */
+
+ u32 indexA, indexB;
+ u32 qpAv, qp, qpTmp;
+
+/* Code */
+
+ ASSERT(thresholds);
+ ASSERT(mb);
+
+ qp = mb->qpY;
+
+ indexA = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetA);
+ indexB = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetB);
+
+ thresholds[INNER].alpha = alphas[indexA];
+ thresholds[INNER].beta = betas[indexB];
+ thresholds[INNER].tc0 = tc0[indexA];
+
+ if (filteringFlags & FILTER_TOP_EDGE)
+ {
+ qpTmp = mb->mbB->qpY;
+ if (qpTmp != qp)
+ {
+ qpAv = (qp + qpTmp + 1) >> 1;
+
+ indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA);
+ indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB);
+
+ thresholds[TOP].alpha = alphas[indexA];
+ thresholds[TOP].beta = betas[indexB];
+ thresholds[TOP].tc0 = tc0[indexA];
+ }
+ else
+ {
+ thresholds[TOP].alpha = thresholds[INNER].alpha;
+ thresholds[TOP].beta = thresholds[INNER].beta;
+ thresholds[TOP].tc0 = thresholds[INNER].tc0;
+ }
+ }
+ if (filteringFlags & FILTER_LEFT_EDGE)
+ {
+ qpTmp = mb->mbA->qpY;
+ if (qpTmp != qp)
+ {
+ qpAv = (qp + qpTmp + 1) >> 1;
+
+ indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA);
+ indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB);
+
+ thresholds[LEFT].alpha = alphas[indexA];
+ thresholds[LEFT].beta = betas[indexB];
+ thresholds[LEFT].tc0 = tc0[indexA];
+ }
+ else
+ {
+ thresholds[LEFT].alpha = thresholds[INNER].alpha;
+ thresholds[LEFT].beta = thresholds[INNER].beta;
+ thresholds[LEFT].tc0 = thresholds[INNER].tc0;
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: GetChromaEdgeThresholds
+
+ Functional description:
+ Compute alpha, beta and tc0 thresholds for inner, left and top
+ chroma edges of a macroblock.
+
+------------------------------------------------------------------------------*/
+void GetChromaEdgeThresholds(
+ edgeThreshold_t *thresholds,
+ mbStorage_t *mb,
+ u32 filteringFlags,
+ i32 chromaQpIndexOffset)
+{
+
+/* Variables */
+
+ u32 indexA, indexB;
+ u32 qpAv, qp, qpTmp;
+
+/* Code */
+
+ ASSERT(thresholds);
+ ASSERT(mb);
+
+ qp = mb->qpY;
+ qp = h264bsdQpC[CLIP3(0, 51, (i32)qp + chromaQpIndexOffset)];
+
+ indexA = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetA);
+ indexB = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetB);
+
+ thresholds[INNER].alpha = alphas[indexA];
+ thresholds[INNER].beta = betas[indexB];
+ thresholds[INNER].tc0 = tc0[indexA];
+
+ if (filteringFlags & FILTER_TOP_EDGE)
+ {
+ qpTmp = mb->mbB->qpY;
+ if (qpTmp != mb->qpY)
+ {
+ qpTmp = h264bsdQpC[CLIP3(0, 51, (i32)qpTmp + chromaQpIndexOffset)];
+ qpAv = (qp + qpTmp + 1) >> 1;
+
+ indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA);
+ indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB);
+
+ thresholds[TOP].alpha = alphas[indexA];
+ thresholds[TOP].beta = betas[indexB];
+ thresholds[TOP].tc0 = tc0[indexA];
+ }
+ else
+ {
+ thresholds[TOP].alpha = thresholds[INNER].alpha;
+ thresholds[TOP].beta = thresholds[INNER].beta;
+ thresholds[TOP].tc0 = thresholds[INNER].tc0;
+ }
+ }
+ if (filteringFlags & FILTER_LEFT_EDGE)
+ {
+ qpTmp = mb->mbA->qpY;
+ if (qpTmp != mb->qpY)
+ {
+ qpTmp = h264bsdQpC[CLIP3(0, 51, (i32)qpTmp + chromaQpIndexOffset)];
+ qpAv = (qp + qpTmp + 1) >> 1;
+
+ indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA);
+ indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB);
+
+ thresholds[LEFT].alpha = alphas[indexA];
+ thresholds[LEFT].beta = betas[indexB];
+ thresholds[LEFT].tc0 = tc0[indexA];
+ }
+ else
+ {
+ thresholds[LEFT].alpha = thresholds[INNER].alpha;
+ thresholds[LEFT].beta = thresholds[INNER].beta;
+ thresholds[LEFT].tc0 = thresholds[INNER].tc0;
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: FilterLuma
+
+ Functional description:
+ Function to filter all luma edges of a macroblock
+
+------------------------------------------------------------------------------*/
+void FilterLuma(
+ u8 *data,
+ bS_t *bS,
+ edgeThreshold_t *thresholds,
+ u32 width)
+{
+
+/* Variables */
+
+ u32 vblock;
+ bS_t *tmp;
+ u8 *ptr;
+ u32 offset;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(bS);
+ ASSERT(thresholds);
+
+ ptr = data;
+ tmp = bS;
+
+ offset = TOP;
+
+ /* loop block rows, perform filtering for all vertical edges of the block
+ * row first, then filter each horizontal edge of the row */
+ for (vblock = 4; vblock--;)
+ {
+ /* only perform filtering if bS is non-zero, first of the four
+ * FilterVerLumaEdge handles the left edge of the macroblock, others
+ * filter inner edges */
+ if (tmp[0].left)
+ FilterVerLumaEdge(ptr, tmp[0].left, thresholds + LEFT, width);
+ if (tmp[1].left)
+ FilterVerLumaEdge(ptr+4, tmp[1].left, thresholds + INNER, width);
+ if (tmp[2].left)
+ FilterVerLumaEdge(ptr+8, tmp[2].left, thresholds + INNER, width);
+ if (tmp[3].left)
+ FilterVerLumaEdge(ptr+12, tmp[3].left, thresholds + INNER, width);
+
+ /* if bS is equal for all horizontal edges of the row -> perform
+ * filtering with FilterHorLuma, otherwise use FilterHorLumaEdge for
+ * each edge separately. offset variable indicates top macroblock edge
+ * on the first loop round, inner edge for the other rounds */
+ if (tmp[0].top == tmp[1].top && tmp[1].top == tmp[2].top &&
+ tmp[2].top == tmp[3].top)
+ {
+ if(tmp[0].top)
+ FilterHorLuma(ptr, tmp[0].top, thresholds + offset, (i32)width);
+ }
+ else
+ {
+ if(tmp[0].top)
+ FilterHorLumaEdge(ptr, tmp[0].top, thresholds+offset,
+ (i32)width);
+ if(tmp[1].top)
+ FilterHorLumaEdge(ptr+4, tmp[1].top, thresholds+offset,
+ (i32)width);
+ if(tmp[2].top)
+ FilterHorLumaEdge(ptr+8, tmp[2].top, thresholds+offset,
+ (i32)width);
+ if(tmp[3].top)
+ FilterHorLumaEdge(ptr+12, tmp[3].top, thresholds+offset,
+ (i32)width);
+ }
+
+ /* four pixel rows ahead, i.e. next row of 4x4-blocks */
+ ptr += width*4;
+ tmp += 4;
+ offset = INNER;
+ }
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: FilterChroma
+
+ Functional description:
+ Function to filter all chroma edges of a macroblock
+
+------------------------------------------------------------------------------*/
+void FilterChroma(
+ u8 *dataCb,
+ u8 *dataCr,
+ bS_t *bS,
+ edgeThreshold_t *thresholds,
+ u32 width)
+{
+
+/* Variables */
+
+ u32 vblock;
+ bS_t *tmp;
+ u32 offset;
+
+/* Code */
+
+ ASSERT(dataCb);
+ ASSERT(dataCr);
+ ASSERT(bS);
+ ASSERT(thresholds);
+
+ tmp = bS;
+ offset = TOP;
+
+ /* loop block rows, perform filtering for all vertical edges of the block
+ * row first, then filter each horizontal edge of the row */
+ for (vblock = 0; vblock < 2; vblock++)
+ {
+ /* only perform filtering if bS is non-zero, first two of the four
+ * FilterVerChromaEdge calls handle the left edge of the macroblock,
+ * others filter the inner edge. Note that as chroma uses bS values
+ * determined for luma edges, each bS is used only for 2 pixels of
+ * a 4-pixel edge */
+ if (tmp[0].left)
+ {
+ FilterVerChromaEdge(dataCb, tmp[0].left, thresholds + LEFT, width);
+ FilterVerChromaEdge(dataCr, tmp[0].left, thresholds + LEFT, width);
+ }
+ if (tmp[4].left)
+ {
+ FilterVerChromaEdge(dataCb+2*width, tmp[4].left, thresholds + LEFT,
+ width);
+ FilterVerChromaEdge(dataCr+2*width, tmp[4].left, thresholds + LEFT,
+ width);
+ }
+ if (tmp[2].left)
+ {
+ FilterVerChromaEdge(dataCb+4, tmp[2].left, thresholds + INNER,
+ width);
+ FilterVerChromaEdge(dataCr+4, tmp[2].left, thresholds + INNER,
+ width);
+ }
+ if (tmp[6].left)
+ {
+ FilterVerChromaEdge(dataCb+2*width+4, tmp[6].left,
+ thresholds + INNER, width);
+ FilterVerChromaEdge(dataCr+2*width+4, tmp[6].left,
+ thresholds + INNER, width);
+ }
+
+ /* if bS is equal for all horizontal edges of the row -> perform
+ * filtering with FilterHorChroma, otherwise use FilterHorChromaEdge
+ * for each edge separately. offset variable indicates top macroblock
+ * edge on the first loop round, inner edge for the second */
+ if (tmp[0].top == tmp[1].top && tmp[1].top == tmp[2].top &&
+ tmp[2].top == tmp[3].top)
+ {
+ if(tmp[0].top)
+ {
+ FilterHorChroma(dataCb, tmp[0].top, thresholds+offset,
+ (i32)width);
+ FilterHorChroma(dataCr, tmp[0].top, thresholds+offset,
+ (i32)width);
+ }
+ }
+ else
+ {
+ if (tmp[0].top)
+ {
+ FilterHorChromaEdge(dataCb, tmp[0].top, thresholds+offset,
+ (i32)width);
+ FilterHorChromaEdge(dataCr, tmp[0].top, thresholds+offset,
+ (i32)width);
+ }
+ if (tmp[1].top)
+ {
+ FilterHorChromaEdge(dataCb+2, tmp[1].top, thresholds+offset,
+ (i32)width);
+ FilterHorChromaEdge(dataCr+2, tmp[1].top, thresholds+offset,
+ (i32)width);
+ }
+ if (tmp[2].top)
+ {
+ FilterHorChromaEdge(dataCb+4, tmp[2].top, thresholds+offset,
+ (i32)width);
+ FilterHorChromaEdge(dataCr+4, tmp[2].top, thresholds+offset,
+ (i32)width);
+ }
+ if (tmp[3].top)
+ {
+ FilterHorChromaEdge(dataCb+6, tmp[3].top, thresholds+offset,
+ (i32)width);
+ FilterHorChromaEdge(dataCr+6, tmp[3].top, thresholds+offset,
+ (i32)width);
+ }
+ }
+
+ tmp += 8;
+ dataCb += width*4;
+ dataCr += width*4;
+ offset = INNER;
+ }
+}
+
+#else /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdFilterPicture
+
+ Functional description:
+ Perform deblocking filtering for a picture. Filter does not copy
+ the original picture anywhere but filtering is performed directly
+ on the original image. Parameters controlling the filtering process
+ are computed based on information in macroblock structures of the
+ filtered macroblock, macroblock above and macroblock on the left of
+ the filtered one.
+
+ Inputs:
+ image pointer to image to be filtered
+ mb pointer to macroblock data structure of the top-left
+ macroblock of the picture
+
+ Outputs:
+ image filtered image stored here
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+/*lint --e{550} Symbol not accessed */
+void h264bsdFilterPicture(
+ image_t *image,
+ mbStorage_t *mb)
+{
+
+/* Variables */
+
+ u32 flags;
+ u32 picSizeInMbs, mbRow, mbCol;
+ u32 picWidthInMbs;
+ u8 *data;
+ mbStorage_t *pMb;
+ u8 bS[2][16];
+ u8 thresholdLuma[2][16];
+ u8 thresholdChroma[2][8];
+ u8 alpha[2][2];
+ u8 beta[2][2];
+ OMXResult res;
+
+/* Code */
+
+ ASSERT(image);
+ ASSERT(mb);
+ ASSERT(image->data);
+ ASSERT(image->width);
+ ASSERT(image->height);
+
+ picWidthInMbs = image->width;
+ data = image->data;
+ picSizeInMbs = picWidthInMbs * image->height;
+
+ pMb = mb;
+
+ for (mbRow = 0, mbCol = 0; mbRow < image->height; pMb++)
+ {
+ flags = GetMbFilteringFlags(pMb);
+
+ if (flags)
+ {
+ /* GetBoundaryStrengths function returns non-zero value if any of
+ * the bS values for the macroblock being processed was non-zero */
+ if (GetBoundaryStrengths(pMb, bS, flags))
+ {
+
+ /* Luma */
+ GetLumaEdgeThresholds(pMb,alpha,beta,thresholdLuma,bS,flags);
+ data = image->data + mbRow * picWidthInMbs * 256 + mbCol * 16;
+
+ res = omxVCM4P10_FilterDeblockingLuma_VerEdge_I( data,
+ (OMX_S32)(picWidthInMbs*16),
+ (const OMX_U8*)alpha,
+ (const OMX_U8*)beta,
+ (const OMX_U8*)thresholdLuma,
+ (const OMX_U8*)bS );
+
+ res = omxVCM4P10_FilterDeblockingLuma_HorEdge_I( data,
+ (OMX_S32)(picWidthInMbs*16),
+ (const OMX_U8*)alpha+2,
+ (const OMX_U8*)beta+2,
+ (const OMX_U8*)thresholdLuma+16,
+ (const OMX_U8*)bS+16 );
+ /* Cb */
+ GetChromaEdgeThresholds(pMb, alpha, beta, thresholdChroma,
+ bS, flags, pMb->chromaQpIndexOffset);
+ data = image->data + picSizeInMbs * 256 +
+ mbRow * picWidthInMbs * 64 + mbCol * 8;
+
+ res = omxVCM4P10_FilterDeblockingChroma_VerEdge_I( data,
+ (OMX_S32)(picWidthInMbs*8),
+ (const OMX_U8*)alpha,
+ (const OMX_U8*)beta,
+ (const OMX_U8*)thresholdChroma,
+ (const OMX_U8*)bS );
+ res = omxVCM4P10_FilterDeblockingChroma_HorEdge_I( data,
+ (OMX_S32)(picWidthInMbs*8),
+ (const OMX_U8*)alpha+2,
+ (const OMX_U8*)beta+2,
+ (const OMX_U8*)thresholdChroma+8,
+ (const OMX_U8*)bS+16 );
+ /* Cr */
+ data += (picSizeInMbs * 64);
+ res = omxVCM4P10_FilterDeblockingChroma_VerEdge_I( data,
+ (OMX_S32)(picWidthInMbs*8),
+ (const OMX_U8*)alpha,
+ (const OMX_U8*)beta,
+ (const OMX_U8*)thresholdChroma,
+ (const OMX_U8*)bS );
+ res = omxVCM4P10_FilterDeblockingChroma_HorEdge_I( data,
+ (OMX_S32)(picWidthInMbs*8),
+ (const OMX_U8*)alpha+2,
+ (const OMX_U8*)beta+2,
+ (const OMX_U8*)thresholdChroma+8,
+ (const OMX_U8*)bS+16 );
+ }
+ }
+
+ mbCol++;
+ if (mbCol == picWidthInMbs)
+ {
+ mbCol = 0;
+ mbRow++;
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: GetBoundaryStrengths
+
+ Functional description:
+ Function to calculate boundary strengths for all edges of a
+ macroblock. Function returns HANTRO_TRUE if any of the bS values for
+ the macroblock had non-zero value, HANTRO_FALSE otherwise.
+
+------------------------------------------------------------------------------*/
+u32 GetBoundaryStrengths(mbStorage_t *mb, u8 (*bS)[16], u32 flags)
+{
+
+/* Variables */
+
+ /* this flag is set HANTRO_TRUE as soon as any boundary strength value is
+ * non-zero */
+ u32 nonZeroBs = HANTRO_FALSE;
+ u32 *pTmp;
+ u32 tmp1, tmp2, isIntraMb;
+
+/* Code */
+
+ ASSERT(mb);
+ ASSERT(bS);
+ ASSERT(flags);
+
+ isIntraMb = IS_INTRA_MB(*mb);
+
+ /* top edges */
+ pTmp = (u32*)&bS[1][0];
+ if (flags & FILTER_TOP_EDGE)
+ {
+ if (isIntraMb || IS_INTRA_MB(*mb->mbB))
+ {
+ *pTmp = 0x04040404;
+ nonZeroBs = HANTRO_TRUE;
+ }
+ else
+ {
+ *pTmp = EdgeBoundaryStrengthTop(mb, mb->mbB);
+ if (*pTmp)
+ nonZeroBs = HANTRO_TRUE;
+ }
+ }
+ else
+ {
+ *pTmp = 0;
+ }
+
+ /* left edges */
+ pTmp = (u32*)&bS[0][0];
+ if (flags & FILTER_LEFT_EDGE)
+ {
+ if (isIntraMb || IS_INTRA_MB(*mb->mbA))
+ {
+ /*bS[0][0] = bS[0][1] = bS[0][2] = bS[0][3] = 4;*/
+ *pTmp = 0x04040404;
+ nonZeroBs = HANTRO_TRUE;
+ }
+ else
+ {
+ *pTmp = EdgeBoundaryStrengthLeft(mb, mb->mbA);
+ if (!nonZeroBs && *pTmp)
+ nonZeroBs = HANTRO_TRUE;
+ }
+ }
+ else
+ {
+ *pTmp = 0;
+ }
+
+ /* inner edges */
+ if (isIntraMb)
+ {
+ pTmp++;
+ *pTmp++ = 0x03030303;
+ *pTmp++ = 0x03030303;
+ *pTmp++ = 0x03030303;
+ pTmp++;
+ *pTmp++ = 0x03030303;
+ *pTmp++ = 0x03030303;
+ *pTmp = 0x03030303;
+
+ nonZeroBs = HANTRO_TRUE;
+ }
+ else
+ {
+ pTmp = (u32*)mb->totalCoeff;
+
+ /* 16x16 inter mb -> ref addresses or motion vectors cannot differ,
+ * only check if either of the blocks contain coefficients */
+ if (h264bsdNumMbPart(mb->mbType) == 1)
+ {
+ tmp1 = *pTmp++;
+ tmp2 = *pTmp++;
+ bS[1][4] = (tmp1 & 0x00FF00FF) ? 2 : 0; /* [2] || [0] */
+ bS[1][5] = (tmp1 & 0xFF00FF00) ? 2 : 0; /* [3] || [1] */
+ bS[0][4] = (tmp1 & 0x0000FFFF) ? 2 : 0; /* [1] || [0] */
+ bS[0][5] = (tmp1 & 0xFFFF0000) ? 2 : 0; /* [3] || [2] */
+
+ tmp1 = *pTmp++;
+ bS[1][6] = (tmp2 & 0x00FF00FF) ? 2 : 0; /* [6] || [4] */
+ bS[1][7] = (tmp2 & 0xFF00FF00) ? 2 : 0; /* [7] || [5] */
+ bS[0][12] = (tmp2 & 0x0000FFFF) ? 2 : 0; /* [5] || [4] */
+ bS[0][13] = (tmp2 & 0xFFFF0000) ? 2 : 0; /* [7] || [6] */
+ tmp2 = *pTmp;
+ bS[1][12] = (tmp1 & 0x00FF00FF) ? 2 : 0; /* [10] || [8] */
+ bS[1][13] = (tmp1 & 0xFF00FF00) ? 2 : 0; /* [11] || [9] */
+ bS[0][6] = (tmp1 & 0x0000FFFF) ? 2 : 0; /* [9] || [8] */
+ bS[0][7] = (tmp1 & 0xFFFF0000) ? 2 : 0; /* [11] || [10] */
+
+ bS[1][14] = (tmp2 & 0x00FF00FF) ? 2 : 0; /* [14] || [12] */
+ bS[1][15] = (tmp2 & 0xFF00FF00) ? 2 : 0; /* [15] || [13] */
+ bS[0][14] = (tmp2 & 0x0000FFFF) ? 2 : 0; /* [13] || [12] */
+ bS[0][15] = (tmp2 & 0xFFFF0000) ? 2 : 0; /* [15] || [14] */
+
+ {
+ u32 tmp3, tmp4;
+
+ tmp1 = mb->totalCoeff[8];
+ tmp2 = mb->totalCoeff[2];
+ tmp3 = mb->totalCoeff[9];
+ tmp4 = mb->totalCoeff[3];
+
+ bS[1][8] = tmp1 || tmp2 ? 2 : 0;
+ tmp1 = mb->totalCoeff[12];
+ tmp2 = mb->totalCoeff[6];
+ bS[1][9] = tmp3 || tmp4 ? 2 : 0;
+ tmp3 = mb->totalCoeff[13];
+ tmp4 = mb->totalCoeff[7];
+ bS[1][10] = tmp1 || tmp2 ? 2 : 0;
+ tmp1 = mb->totalCoeff[4];
+ tmp2 = mb->totalCoeff[1];
+ bS[1][11] = tmp3 || tmp4 ? 2 : 0;
+ tmp3 = mb->totalCoeff[6];
+ tmp4 = mb->totalCoeff[3];
+ bS[0][8] = tmp1 || tmp2 ? 2 : 0;
+ tmp1 = mb->totalCoeff[12];
+ tmp2 = mb->totalCoeff[9];
+ bS[0][9] = tmp3 || tmp4 ? 2 : 0;
+ tmp3 = mb->totalCoeff[14];
+ tmp4 = mb->totalCoeff[11];
+ bS[0][10] = tmp1 || tmp2 ? 2 : 0;
+ bS[0][11] = tmp3 || tmp4 ? 2 : 0;
+ }
+ }
+
+ /* 16x8 inter mb -> ref addresses and motion vectors can be different
+ * only for the middle horizontal edge, for the other top edges it is
+ * enough to check whether the blocks contain coefficients or not. The
+ * same applies to all internal left edges. */
+ else if (mb->mbType == P_L0_L0_16x8)
+ {
+ tmp1 = *pTmp++;
+ tmp2 = *pTmp++;
+ bS[1][4] = (tmp1 & 0x00FF00FF) ? 2 : 0; /* [2] || [0] */
+ bS[1][5] = (tmp1 & 0xFF00FF00) ? 2 : 0; /* [3] || [1] */
+ bS[0][4] = (tmp1 & 0x0000FFFF) ? 2 : 0; /* [1] || [0] */
+ bS[0][5] = (tmp1 & 0xFFFF0000) ? 2 : 0; /* [3] || [2] */
+ tmp1 = *pTmp++;
+ bS[1][6] = (tmp2 & 0x00FF00FF) ? 2 : 0; /* [6] || [4] */
+ bS[1][7] = (tmp2 & 0xFF00FF00) ? 2 : 0; /* [7] || [5] */
+ bS[0][12] = (tmp2 & 0x0000FFFF) ? 2 : 0; /* [5] || [4] */
+ bS[0][13] = (tmp2 & 0xFFFF0000) ? 2 : 0; /* [7] || [6] */
+ tmp2 = *pTmp;
+ bS[1][12] = (tmp1 & 0x00FF00FF) ? 2 : 0; /* [10] || [8] */
+ bS[1][13] = (tmp1 & 0xFF00FF00) ? 2 : 0; /* [11] || [9] */
+ bS[0][6] = (tmp1 & 0x0000FFFF) ? 2 : 0; /* [9] || [8] */
+ bS[0][7] = (tmp1 & 0xFFFF0000) ? 2 : 0; /* [11] || [10] */
+
+ bS[1][14] = (tmp2 & 0x00FF00FF) ? 2 : 0; /* [14] || [12] */
+ bS[1][15] = (tmp2 & 0xFF00FF00) ? 2 : 0; /* [15] || [13] */
+ bS[0][14] = (tmp2 & 0x0000FFFF) ? 2 : 0; /* [13] || [12] */
+ bS[0][15] = (tmp2 & 0xFFFF0000) ? 2 : 0; /* [15] || [14] */
+
+ bS[1][8] = (u8)InnerBoundaryStrength(mb, 8, 2);
+ bS[1][9] = (u8)InnerBoundaryStrength(mb, 9, 3);
+ bS[1][10] = (u8)InnerBoundaryStrength(mb, 12, 6);
+ bS[1][11] = (u8)InnerBoundaryStrength(mb, 13, 7);
+
+ {
+ u32 tmp3, tmp4;
+
+ tmp1 = mb->totalCoeff[4];
+ tmp2 = mb->totalCoeff[1];
+ tmp3 = mb->totalCoeff[6];
+ tmp4 = mb->totalCoeff[3];
+ bS[0][8] = tmp1 || tmp2 ? 2 : 0;
+ tmp1 = mb->totalCoeff[12];
+ tmp2 = mb->totalCoeff[9];
+ bS[0][9] = tmp3 || tmp4 ? 2 : 0;
+ tmp3 = mb->totalCoeff[14];
+ tmp4 = mb->totalCoeff[11];
+ bS[0][10] = tmp1 || tmp2 ? 2 : 0;
+ bS[0][11] = tmp3 || tmp4 ? 2 : 0;
+ }
+ }
+ /* 8x16 inter mb -> ref addresses and motion vectors can be different
+ * only for the middle vertical edge, for the other left edges it is
+ * enough to check whether the blocks contain coefficients or not. The
+ * same applies to all internal top edges. */
+ else if (mb->mbType == P_L0_L0_8x16)
+ {
+ tmp1 = *pTmp++;
+ tmp2 = *pTmp++;
+ bS[1][4] = (tmp1 & 0x00FF00FF) ? 2 : 0; /* [2] || [0] */
+ bS[1][5] = (tmp1 & 0xFF00FF00) ? 2 : 0; /* [3] || [1] */
+ bS[0][4] = (tmp1 & 0x0000FFFF) ? 2 : 0; /* [1] || [0] */
+ bS[0][5] = (tmp1 & 0xFFFF0000) ? 2 : 0; /* [3] || [2] */
+ tmp1 = *pTmp++;
+ bS[1][6] = (tmp2 & 0x00FF00FF) ? 2 : 0; /* [6] || [4] */
+ bS[1][7] = (tmp2 & 0xFF00FF00) ? 2 : 0; /* [7] || [5] */
+ bS[0][12] = (tmp2 & 0x0000FFFF) ? 2 : 0; /* [5] || [4] */
+ bS[0][13] = (tmp2 & 0xFFFF0000) ? 2 : 0; /* [7] || [6] */
+ tmp2 = *pTmp;
+ bS[1][12] = (tmp1 & 0x00FF00FF) ? 2 : 0; /* [10] || [8] */
+ bS[1][13] = (tmp1 & 0xFF00FF00) ? 2 : 0; /* [11] || [9] */
+ bS[0][6] = (tmp1 & 0x0000FFFF) ? 2 : 0; /* [9] || [8] */
+ bS[0][7] = (tmp1 & 0xFFFF0000) ? 2 : 0; /* [11] || [10] */
+
+ bS[1][14] = (tmp2 & 0x00FF00FF) ? 2 : 0; /* [14] || [12] */
+ bS[1][15] = (tmp2 & 0xFF00FF00) ? 2 : 0; /* [15] || [13] */
+ bS[0][14] = (tmp2 & 0x0000FFFF) ? 2 : 0; /* [13] || [12] */
+ bS[0][15] = (tmp2 & 0xFFFF0000) ? 2 : 0; /* [15] || [14] */
+
+ bS[0][8] = (u8)InnerBoundaryStrength(mb, 4, 1);
+ bS[0][9] = (u8)InnerBoundaryStrength(mb, 6, 3);
+ bS[0][10] = (u8)InnerBoundaryStrength(mb, 12, 9);
+ bS[0][11] = (u8)InnerBoundaryStrength(mb, 14, 11);
+
+ {
+ u32 tmp3, tmp4;
+
+ tmp1 = mb->totalCoeff[8];
+ tmp2 = mb->totalCoeff[2];
+ tmp3 = mb->totalCoeff[9];
+ tmp4 = mb->totalCoeff[3];
+ bS[1][8] = tmp1 || tmp2 ? 2 : 0;
+ tmp1 = mb->totalCoeff[12];
+ tmp2 = mb->totalCoeff[6];
+ bS[1][9] = tmp3 || tmp4 ? 2 : 0;
+ tmp3 = mb->totalCoeff[13];
+ tmp4 = mb->totalCoeff[7];
+ bS[1][10] = tmp1 || tmp2 ? 2 : 0;
+ bS[1][11] = tmp3 || tmp4 ? 2 : 0;
+ }
+ }
+ else
+ {
+ tmp1 = *pTmp++;
+ bS[1][4] = (tmp1 & 0x00FF00FF) ? 2 : (u8)InnerBoundaryStrength2(mb, 2, 0);
+ bS[1][5] = (tmp1 & 0xFF00FF00) ? 2 : (u8)InnerBoundaryStrength2(mb, 3, 1);
+ bS[0][4] = (tmp1 & 0x0000FFFF) ? 2 : (u8)InnerBoundaryStrength2(mb, 1, 0);
+ bS[0][5] = (tmp1 & 0xFFFF0000) ? 2 : (u8)InnerBoundaryStrength2(mb, 3, 2);
+ tmp1 = *pTmp++;
+ bS[1][6] = (tmp1 & 0x00FF00FF) ? 2 : (u8)InnerBoundaryStrength2(mb, 6, 4);
+ bS[1][7] = (tmp1 & 0xFF00FF00) ? 2 : (u8)InnerBoundaryStrength2(mb, 7, 5);
+ bS[0][12] = (tmp1 & 0x0000FFFF) ? 2 : (u8)InnerBoundaryStrength2(mb, 5, 4);
+ bS[0][13] = (tmp1 & 0xFFFF0000) ? 2 : (u8)InnerBoundaryStrength2(mb, 7, 6);
+ tmp1 = *pTmp++;
+ bS[1][12] = (tmp1 & 0x00FF00FF) ? 2 : (u8)InnerBoundaryStrength2(mb, 10, 8);
+ bS[1][13] = (tmp1 & 0xFF00FF00) ? 2 : (u8)InnerBoundaryStrength2(mb, 11, 9);
+ bS[0][6] = (tmp1 & 0x0000FFFF) ? 2 : (u8)InnerBoundaryStrength2(mb, 9, 8);
+ bS[0][7] = (tmp1 & 0xFFFF0000) ? 2 : (u8)InnerBoundaryStrength2(mb, 11, 10);
+ tmp1 = *pTmp;
+ bS[1][14] = (tmp1 & 0x00FF00FF) ? 2 : (u8)InnerBoundaryStrength2(mb, 14, 12);
+ bS[1][15] = (tmp1 & 0xFF00FF00) ? 2 : (u8)InnerBoundaryStrength2(mb, 15, 13);
+ bS[0][14] = (tmp1 & 0x0000FFFF) ? 2 : (u8)InnerBoundaryStrength2(mb, 13, 12);
+ bS[0][15] = (tmp1 & 0xFFFF0000) ? 2 : (u8)InnerBoundaryStrength2(mb, 15, 14);
+
+ bS[1][8] = (u8)InnerBoundaryStrength(mb, 8, 2);
+ bS[1][9] = (u8)InnerBoundaryStrength(mb, 9, 3);
+ bS[1][10] = (u8)InnerBoundaryStrength(mb, 12, 6);
+ bS[1][11] = (u8)InnerBoundaryStrength(mb, 13, 7);
+
+ bS[0][8] = (u8)InnerBoundaryStrength(mb, 4, 1);
+ bS[0][9] = (u8)InnerBoundaryStrength(mb, 6, 3);
+ bS[0][10] = (u8)InnerBoundaryStrength(mb, 12, 9);
+ bS[0][11] = (u8)InnerBoundaryStrength(mb, 14, 11);
+ }
+ pTmp = (u32*)&bS[0][0];
+ if (!nonZeroBs && (pTmp[1] || pTmp[2] || pTmp[3] ||
+ pTmp[5] || pTmp[6] || pTmp[7]) )
+ {
+ nonZeroBs = HANTRO_TRUE;
+ }
+ }
+
+ return(nonZeroBs);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: GetLumaEdgeThresholds
+
+ Functional description:
+ Compute alpha, beta and tc0 thresholds for inner, left and top
+ luma edges of a macroblock.
+
+------------------------------------------------------------------------------*/
+void GetLumaEdgeThresholds(
+ mbStorage_t *mb,
+ u8 (*alpha)[2],
+ u8 (*beta)[2],
+ u8 (*threshold)[16],
+ u8 (*bs)[16],
+ u32 filteringFlags )
+{
+
+/* Variables */
+
+ u32 indexA, indexB;
+ u32 qpAv, qp, qpTmp;
+ u32 i;
+
+/* Code */
+
+ ASSERT(threshold);
+ ASSERT(bs);
+ ASSERT(beta);
+ ASSERT(alpha);
+ ASSERT(mb);
+
+ qp = mb->qpY;
+
+ indexA = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetA);
+ indexB = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetB);
+
+ /* Internal edge values */
+ alpha[0][1] = alphas[indexA];
+ alpha[1][1] = alphas[indexA];
+ alpha[1][0] = alphas[indexA];
+ alpha[0][0] = alphas[indexA];
+ beta[0][1] = betas[indexB];
+ beta[1][1] = betas[indexB];
+ beta[1][0] = betas[indexB];
+ beta[0][0] = betas[indexB];
+
+ /* vertical scan order */
+ for (i = 0; i < 2; i++)
+ {
+ u32 t1, t2;
+
+ t1 = bs[i][0];
+ t2 = bs[i][1];
+ threshold[i][0] = (t1) ? tc0[indexA][t1] : 0;
+ t1 = bs[i][2];
+ threshold[i][1] = (t2) ? tc0[indexA][t2] : 0;
+ t2 = bs[i][3];
+ threshold[i][2] = (t1) ? tc0[indexA][t1] : 0;
+ t1 = bs[i][4];
+ threshold[i][3] = (t2) ? tc0[indexA][t2] : 0;
+ t2 = bs[i][5];
+ threshold[i][4] = (t1) ? tc0[indexA][t1] : 0;
+ t1 = bs[i][6];
+ threshold[i][5] = (t2) ? tc0[indexA][t2] : 0;
+ t2 = bs[i][7];
+ threshold[i][6] = (t1) ? tc0[indexA][t1] : 0;
+ t1 = bs[i][8];
+ threshold[i][7] = (t2) ? tc0[indexA][t2] : 0;
+ t2 = bs[i][9];
+ threshold[i][8] = (t1) ? tc0[indexA][t1] : 0;
+ t1 = bs[i][10];
+ threshold[i][9] = (t2) ? tc0[indexA][t2] : 0;
+ t2 = bs[i][11];
+ threshold[i][10] = (t1) ? tc0[indexA][t1] : 0;
+ t1 = bs[i][12];
+ threshold[i][11] = (t2) ? tc0[indexA][t2] : 0;
+ t2 = bs[i][13];
+ threshold[i][12] = (t1) ? tc0[indexA][t1] : 0;
+ t1 = bs[i][14];
+ threshold[i][13] = (t2) ? tc0[indexA][t2] : 0;
+ t2 = bs[i][15];
+ threshold[i][14] = (t1) ? tc0[indexA][t1] : 0;
+ threshold[i][15] = (t2) ? tc0[indexA][t2] : 0;
+ }
+
+ if (filteringFlags & FILTER_TOP_EDGE)
+ {
+ qpTmp = mb->mbB->qpY;
+ if (qpTmp != qp)
+ {
+ u32 t1, t2, t3, t4;
+ qpAv = (qp + qpTmp + 1) >> 1;
+
+ indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA);
+ indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB);
+
+ alpha[1][0] = alphas[indexA];
+ beta[1][0] = betas[indexB];
+ t1 = bs[1][0];
+ t2 = bs[1][1];
+ t3 = bs[1][2];
+ t4 = bs[1][3];
+ threshold[1][0] = (t1 && (t1 < 4)) ? tc0[indexA][t1] : 0;
+ threshold[1][1] = (t2 && (t2 < 4)) ? tc0[indexA][t2] : 0;
+ threshold[1][2] = (t3 && (t3 < 4)) ? tc0[indexA][t3] : 0;
+ threshold[1][3] = (t4 && (t4 < 4)) ? tc0[indexA][t4] : 0;
+ }
+ }
+ if (filteringFlags & FILTER_LEFT_EDGE)
+ {
+ qpTmp = mb->mbA->qpY;
+ if (qpTmp != qp)
+ {
+ qpAv = (qp + qpTmp + 1) >> 1;
+
+ indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA);
+ indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB);
+
+ alpha[0][0] = alphas[indexA];
+ beta[0][0] = betas[indexB];
+ threshold[0][0] = (bs[0][0] && (bs[0][0] < 4)) ? tc0[indexA][bs[0][0]] : 0;
+ threshold[0][1] = (bs[0][1] && (bs[0][1] < 4)) ? tc0[indexA][bs[0][1]] : 0;
+ threshold[0][2] = (bs[0][2] && (bs[0][2] < 4)) ? tc0[indexA][bs[0][2]] : 0;
+ threshold[0][3] = (bs[0][3] && (bs[0][3] < 4)) ? tc0[indexA][bs[0][3]] : 0;
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: GetChromaEdgeThresholds
+
+ Functional description:
+ Compute alpha, beta and tc0 thresholds for inner, left and top
+ chroma edges of a macroblock.
+
+------------------------------------------------------------------------------*/
+void GetChromaEdgeThresholds(
+ mbStorage_t *mb,
+ u8 (*alpha)[2],
+ u8 (*beta)[2],
+ u8 (*threshold)[8],
+ u8 (*bs)[16],
+ u32 filteringFlags,
+ i32 chromaQpIndexOffset)
+{
+
+/* Variables */
+
+ u32 indexA, indexB;
+ u32 qpAv, qp, qpTmp;
+ u32 i;
+
+/* Code */
+
+ ASSERT(threshold);
+ ASSERT(bs);
+ ASSERT(beta);
+ ASSERT(alpha);
+ ASSERT(mb);
+ ASSERT(mb);
+
+ qp = mb->qpY;
+ qp = h264bsdQpC[CLIP3(0, 51, (i32)qp + chromaQpIndexOffset)];
+
+ indexA = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetA);
+ indexB = (u32)CLIP3(0, 51, (i32)qp + mb->filterOffsetB);
+
+ alpha[0][1] = alphas[indexA];
+ alpha[1][1] = alphas[indexA];
+ alpha[1][0] = alphas[indexA];
+ alpha[0][0] = alphas[indexA];
+ beta[0][1] = betas[indexB];
+ beta[1][1] = betas[indexB];
+ beta[1][0] = betas[indexB];
+ beta[0][0] = betas[indexB];
+
+ for (i = 0; i < 2; i++)
+ {
+ u32 t1, t2;
+
+ t1 = bs[i][0];
+ t2 = bs[i][1];
+ threshold[i][0] = (t1) ? tc0[indexA][t1] : 0;
+ t1 = bs[i][2];
+ threshold[i][1] = (t2) ? tc0[indexA][t2] : 0;
+ t2 = bs[i][3];
+ threshold[i][2] = (t1) ? tc0[indexA][t1] : 0;
+ t1 = bs[i][8];
+ threshold[i][3] = (t2) ? tc0[indexA][t2] : 0;
+ t2 = bs[i][9];
+ threshold[i][4] = (t1) ? tc0[indexA][t1] : 0;
+ t1 = bs[i][10];
+ threshold[i][5] = (t2) ? tc0[indexA][t2] : 0;
+ t2 = bs[i][11];
+ threshold[i][6] = (t1) ? tc0[indexA][t1] : 0;
+ threshold[i][7] = (t2) ? tc0[indexA][t2] : 0;
+ }
+
+ if (filteringFlags & FILTER_TOP_EDGE)
+ {
+ qpTmp = mb->mbB->qpY;
+ if (qpTmp != mb->qpY)
+ {
+ u32 t1, t2, t3, t4;
+ qpTmp = h264bsdQpC[CLIP3(0, 51, (i32)qpTmp + chromaQpIndexOffset)];
+ qpAv = (qp + qpTmp + 1) >> 1;
+
+ indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA);
+ indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB);
+
+ alpha[1][0] = alphas[indexA];
+ beta[1][0] = betas[indexB];
+
+ t1 = bs[1][0];
+ t2 = bs[1][1];
+ t3 = bs[1][2];
+ t4 = bs[1][3];
+ threshold[1][0] = (t1) ? tc0[indexA][t1] : 0;
+ threshold[1][1] = (t2) ? tc0[indexA][t2] : 0;
+ threshold[1][2] = (t3) ? tc0[indexA][t3] : 0;
+ threshold[1][3] = (t4) ? tc0[indexA][t4] : 0;
+ }
+ }
+ if (filteringFlags & FILTER_LEFT_EDGE)
+ {
+ qpTmp = mb->mbA->qpY;
+ if (qpTmp != mb->qpY)
+ {
+
+ qpTmp = h264bsdQpC[CLIP3(0, 51, (i32)qpTmp + chromaQpIndexOffset)];
+ qpAv = (qp + qpTmp + 1) >> 1;
+
+ indexA = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetA);
+ indexB = (u32)CLIP3(0, 51, (i32)qpAv + mb->filterOffsetB);
+
+ alpha[0][0] = alphas[indexA];
+ beta[0][0] = betas[indexB];
+ threshold[0][0] = (bs[0][0]) ? tc0[indexA][bs[0][0]] : 0;
+ threshold[0][1] = (bs[0][1]) ? tc0[indexA][bs[0][1]] : 0;
+ threshold[0][2] = (bs[0][2]) ? tc0[indexA][bs[0][2]] : 0;
+ threshold[0][3] = (bs[0][3]) ? tc0[indexA][bs[0][3]] : 0;
+ }
+ }
+
+}
+
+#endif /* H264DEC_OMXDL */
+
+/*lint +e701 +e702 */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.h
new file mode 100755
index 0000000..2571dda
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_deblocking.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_DEBLOCKING_H
+#define H264SWDEC_DEBLOCKING_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_image.h"
+#include "h264bsd_macroblock_layer.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+void h264bsdFilterPicture(
+ image_t *image,
+ mbStorage_t *mb);
+
+#endif /* #ifdef H264SWDEC_DEBLOCKING_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.c
new file mode 100644
index 0000000..a816871
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.c
@@ -0,0 +1,961 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdInit
+ h264bsdDecode
+ h264bsdShutdown
+ h264bsdCurrentImage
+ h264bsdNextOutputPicture
+ h264bsdPicWidth
+ h264bsdPicHeight
+ h264bsdFlushBuffer
+ h264bsdCheckValidParamSets
+ h264bsdVideoRange
+ h264bsdMatrixCoefficients
+ h264bsdCroppingParams
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_decoder.h"
+#include "h264bsd_nal_unit.h"
+#include "h264bsd_byte_stream.h"
+#include "h264bsd_seq_param_set.h"
+#include "h264bsd_pic_param_set.h"
+#include "h264bsd_slice_header.h"
+#include "h264bsd_slice_data.h"
+#include "h264bsd_neighbour.h"
+#include "h264bsd_util.h"
+#include "h264bsd_dpb.h"
+#include "h264bsd_deblocking.h"
+#include "h264bsd_conceal.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+
+ Function name: h264bsdInit
+
+ Functional description:
+ Initialize the decoder.
+
+ Inputs:
+ noOutputReordering flag to indicate the decoder that it does not
+ have to perform reordering of display images.
+
+ Outputs:
+ pStorage pointer to initialized storage structure
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdInit(storage_t *pStorage, u32 noOutputReordering)
+{
+
+/* Variables */
+ u32 size;
+/* Code */
+
+ ASSERT(pStorage);
+
+ h264bsdInitStorage(pStorage);
+
+ /* allocate mbLayer to be next multiple of 64 to enable use of
+ * specific NEON optimized "memset" for clearing the structure */
+ size = (sizeof(macroblockLayer_t) + 63) & ~0x3F;
+
+ pStorage->mbLayer = (macroblockLayer_t*)H264SwDecMalloc(size);
+ if (!pStorage->mbLayer)
+ return HANTRO_NOK;
+
+ if (noOutputReordering)
+ pStorage->noReordering = HANTRO_TRUE;
+
+ return HANTRO_OK;
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdDecode
+
+ Functional description:
+ Decode a NAL unit. This function calls other modules to perform
+ tasks like
+ * extract and decode NAL unit from the byte stream
+ * decode parameter sets
+ * decode slice header and slice data
+ * conceal errors in the picture
+ * perform deblocking filtering
+
+ This function contains top level control logic of the decoder.
+
+ Inputs:
+ pStorage pointer to storage data structure
+ byteStrm pointer to stream buffer given by application
+ len length of the buffer in bytes
+ picId identifier for a picture, assigned by the
+ application
+
+ Outputs:
+ readBytes number of bytes read from the stream is stored
+ here
+
+ Returns:
+ H264BSD_RDY decoding finished, nothing special
+ H264BSD_PIC_RDY decoding of a picture finished
+ H264BSD_HDRS_RDY param sets activated, information like
+ picture dimensions etc can be read
+ H264BSD_ERROR error in decoding
+ H264BSD_PARAM_SET_ERROR serius error in decoding, failed to
+ activate param sets
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecode(storage_t *pStorage, u8 *byteStrm, u32 len, u32 picId,
+ u32 *readBytes)
+{
+
+/* Variables */
+
+ u32 tmp, ppsId, spsId;
+ i32 picOrderCnt;
+ nalUnit_t nalUnit;
+ seqParamSet_t seqParamSet;
+ picParamSet_t picParamSet;
+ strmData_t strm;
+ u32 accessUnitBoundaryFlag = HANTRO_FALSE;
+ u32 picReady = HANTRO_FALSE;
+
+/* Code */
+
+ ASSERT(pStorage);
+ ASSERT(byteStrm);
+ ASSERT(len);
+ ASSERT(readBytes);
+
+ /* if previous buffer was not finished and same pointer given -> skip NAL
+ * unit extraction */
+ if (pStorage->prevBufNotFinished && byteStrm == pStorage->prevBufPointer)
+ {
+ strm = pStorage->strm[0];
+ strm.pStrmCurrPos = strm.pStrmBuffStart;
+ strm.strmBuffReadBits = strm.bitPosInWord = 0;
+ *readBytes = pStorage->prevBytesConsumed;
+ }
+ else
+ {
+ tmp = h264bsdExtractNalUnit(byteStrm, len, &strm, readBytes);
+ if (tmp != HANTRO_OK)
+ {
+ EPRINT("BYTE_STREAM");
+ return(H264BSD_ERROR);
+ }
+ /* store stream */
+ pStorage->strm[0] = strm;
+ pStorage->prevBytesConsumed = *readBytes;
+ pStorage->prevBufPointer = byteStrm;
+ }
+ pStorage->prevBufNotFinished = HANTRO_FALSE;
+
+ tmp = h264bsdDecodeNalUnit(&strm, &nalUnit);
+ if (tmp != HANTRO_OK)
+ {
+ EPRINT("NAL_UNIT");
+ return(H264BSD_ERROR);
+ }
+
+ /* Discard unspecified, reserved, SPS extension and auxiliary picture slices */
+ if(nalUnit.nalUnitType == 0 || nalUnit.nalUnitType >= 13)
+ {
+ DEBUG(("DISCARDED NAL (UNSPECIFIED, REGISTERED, SPS ext or AUX slice)\n"));
+ return(H264BSD_RDY);
+ }
+
+ tmp = h264bsdCheckAccessUnitBoundary(
+ &strm,
+ &nalUnit,
+ pStorage,
+ &accessUnitBoundaryFlag);
+ if (tmp != HANTRO_OK)
+ {
+ EPRINT("ACCESS UNIT BOUNDARY CHECK");
+ if (tmp == PARAM_SET_ERROR)
+ return(H264BSD_PARAM_SET_ERROR);
+ else
+ return(H264BSD_ERROR);
+ }
+
+ if ( accessUnitBoundaryFlag )
+ {
+ DEBUG(("Access unit boundary\n"));
+ /* conceal if picture started and param sets activated */
+ if (pStorage->picStarted && pStorage->activeSps != NULL)
+ {
+ DEBUG(("CONCEALING..."));
+
+ /* return error if second phase of
+ * initialization is not completed */
+ if (pStorage->pendingActivation)
+ {
+ EPRINT("Pending activation not completed");
+ return (H264BSD_ERROR);
+ }
+
+ if (!pStorage->validSliceInAccessUnit)
+ {
+ pStorage->currImage->data =
+ h264bsdAllocateDpbImage(pStorage->dpb);
+ h264bsdInitRefPicList(pStorage->dpb);
+ tmp = h264bsdConceal(pStorage, pStorage->currImage, P_SLICE);
+ }
+ else
+ tmp = h264bsdConceal(pStorage, pStorage->currImage,
+ pStorage->sliceHeader->sliceType);
+
+ picReady = HANTRO_TRUE;
+
+ /* current NAL unit should be decoded on next activation -> set
+ * readBytes to 0 */
+ *readBytes = 0;
+ pStorage->prevBufNotFinished = HANTRO_TRUE;
+ DEBUG(("...DONE\n"));
+ }
+ else
+ {
+ pStorage->validSliceInAccessUnit = HANTRO_FALSE;
+ }
+ pStorage->skipRedundantSlices = HANTRO_FALSE;
+ }
+
+ if (!picReady)
+ {
+ switch (nalUnit.nalUnitType)
+ {
+ case NAL_SEQ_PARAM_SET:
+ DEBUG(("SEQ PARAM SET\n"));
+ tmp = h264bsdDecodeSeqParamSet(&strm, &seqParamSet);
+ if (tmp != HANTRO_OK)
+ {
+ EPRINT("SEQ_PARAM_SET");
+ FREE(seqParamSet.offsetForRefFrame);
+ FREE(seqParamSet.vuiParameters);
+ return(H264BSD_ERROR);
+ }
+ tmp = h264bsdStoreSeqParamSet(pStorage, &seqParamSet);
+ break;
+
+ case NAL_PIC_PARAM_SET:
+ DEBUG(("PIC PARAM SET\n"));
+ tmp = h264bsdDecodePicParamSet(&strm, &picParamSet);
+ if (tmp != HANTRO_OK)
+ {
+ EPRINT("PIC_PARAM_SET");
+ FREE(picParamSet.runLength);
+ FREE(picParamSet.topLeft);
+ FREE(picParamSet.bottomRight);
+ FREE(picParamSet.sliceGroupId);
+ return(H264BSD_ERROR);
+ }
+ tmp = h264bsdStorePicParamSet(pStorage, &picParamSet);
+ break;
+
+ case NAL_CODED_SLICE_IDR:
+ DEBUG(("IDR "));
+ /* fall through */
+ case NAL_CODED_SLICE:
+ DEBUG(("SLICE HEADER\n"));
+
+ /* picture successfully finished and still decoding same old
+ * access unit -> no need to decode redundant slices */
+ if (pStorage->skipRedundantSlices)
+ return(H264BSD_RDY);
+
+ pStorage->picStarted = HANTRO_TRUE;
+
+ if (h264bsdIsStartOfPicture(pStorage))
+ {
+ pStorage->numConcealedMbs = 0;
+ pStorage->currentPicId = picId;
+
+ tmp = h264bsdCheckPpsId(&strm, &ppsId);
+ ASSERT(tmp == HANTRO_OK);
+ /* store old activeSpsId and return headers ready
+ * indication if activeSps changes */
+ spsId = pStorage->activeSpsId;
+ tmp = h264bsdActivateParamSets(pStorage, ppsId,
+ IS_IDR_NAL_UNIT(&nalUnit) ?
+ HANTRO_TRUE : HANTRO_FALSE);
+ if (tmp != HANTRO_OK)
+ {
+ EPRINT("Param set activation");
+ pStorage->activePpsId = MAX_NUM_PIC_PARAM_SETS;
+ pStorage->activePps = NULL;
+ pStorage->activeSpsId = MAX_NUM_SEQ_PARAM_SETS;
+ pStorage->activeSps = NULL;
+ pStorage->pendingActivation = HANTRO_FALSE;
+
+ if(tmp == MEMORY_ALLOCATION_ERROR)
+ {
+ return H264BSD_MEMALLOC_ERROR;
+ }
+ else
+ return(H264BSD_PARAM_SET_ERROR);
+ }
+
+ if (spsId != pStorage->activeSpsId)
+ {
+ seqParamSet_t *oldSPS = NULL;
+ seqParamSet_t *newSPS = pStorage->activeSps;
+ u32 noOutputOfPriorPicsFlag = 1;
+
+ if(pStorage->oldSpsId < MAX_NUM_SEQ_PARAM_SETS)
+ {
+ oldSPS = pStorage->sps[pStorage->oldSpsId];
+ }
+
+ *readBytes = 0;
+ pStorage->prevBufNotFinished = HANTRO_TRUE;
+
+
+ if(nalUnit.nalUnitType == NAL_CODED_SLICE_IDR)
+ {
+ tmp =
+ h264bsdCheckPriorPicsFlag(&noOutputOfPriorPicsFlag,
+ &strm, newSPS,
+ pStorage->activePps,
+ nalUnit.nalUnitType);
+ }
+ else
+ {
+ tmp = HANTRO_NOK;
+ }
+
+ if((tmp != HANTRO_OK) ||
+ (noOutputOfPriorPicsFlag != 0) ||
+ (pStorage->dpb->noReordering) ||
+ (oldSPS == NULL) ||
+ (oldSPS->picWidthInMbs != newSPS->picWidthInMbs) ||
+ (oldSPS->picHeightInMbs != newSPS->picHeightInMbs) ||
+ (oldSPS->maxDpbSize != newSPS->maxDpbSize))
+ {
+ pStorage->dpb->flushed = 0;
+ }
+ else
+ {
+ h264bsdFlushDpb(pStorage->dpb);
+ }
+
+ pStorage->oldSpsId = pStorage->activeSpsId;
+
+ return(H264BSD_HDRS_RDY);
+ }
+ }
+
+ /* return error if second phase of
+ * initialization is not completed */
+ if (pStorage->pendingActivation)
+ {
+ EPRINT("Pending activation not completed");
+ return (H264BSD_ERROR);
+ }
+ tmp = h264bsdDecodeSliceHeader(&strm, pStorage->sliceHeader + 1,
+ pStorage->activeSps, pStorage->activePps, &nalUnit);
+ if (tmp != HANTRO_OK)
+ {
+ EPRINT("SLICE_HEADER");
+ return(H264BSD_ERROR);
+ }
+ if (h264bsdIsStartOfPicture(pStorage))
+ {
+ if (!IS_IDR_NAL_UNIT(&nalUnit))
+ {
+ tmp = h264bsdCheckGapsInFrameNum(pStorage->dpb,
+ pStorage->sliceHeader[1].frameNum,
+ nalUnit.nalRefIdc != 0 ?
+ HANTRO_TRUE : HANTRO_FALSE,
+ pStorage->activeSps->
+ gapsInFrameNumValueAllowedFlag);
+ if (tmp != HANTRO_OK)
+ {
+ EPRINT("Gaps in frame num");
+ return(H264BSD_ERROR);
+ }
+ }
+ pStorage->currImage->data =
+ h264bsdAllocateDpbImage(pStorage->dpb);
+ }
+
+ /* store slice header to storage if successfully decoded */
+ pStorage->sliceHeader[0] = pStorage->sliceHeader[1];
+ pStorage->validSliceInAccessUnit = HANTRO_TRUE;
+ pStorage->prevNalUnit[0] = nalUnit;
+
+ h264bsdComputeSliceGroupMap(pStorage,
+ pStorage->sliceHeader->sliceGroupChangeCycle);
+
+ h264bsdInitRefPicList(pStorage->dpb);
+ tmp = h264bsdReorderRefPicList(pStorage->dpb,
+ &pStorage->sliceHeader->refPicListReordering,
+ pStorage->sliceHeader->frameNum,
+ pStorage->sliceHeader->numRefIdxL0Active);
+ if (tmp != HANTRO_OK)
+ {
+ EPRINT("Reordering");
+ return(H264BSD_ERROR);
+ }
+
+ DEBUG(("SLICE DATA, FIRST %d\n",
+ pStorage->sliceHeader->firstMbInSlice));
+ tmp = h264bsdDecodeSliceData(&strm, pStorage,
+ pStorage->currImage, pStorage->sliceHeader);
+ if (tmp != HANTRO_OK)
+ {
+ EPRINT("SLICE_DATA");
+ h264bsdMarkSliceCorrupted(pStorage,
+ pStorage->sliceHeader->firstMbInSlice);
+ return(H264BSD_ERROR);
+ }
+
+ if (h264bsdIsEndOfPicture(pStorage))
+ {
+ picReady = HANTRO_TRUE;
+ pStorage->skipRedundantSlices = HANTRO_TRUE;
+ }
+ break;
+
+ case NAL_SEI:
+ DEBUG(("SEI MESSAGE, NOT DECODED"));
+ break;
+
+ default:
+ DEBUG(("NOT IMPLEMENTED YET %d\n",nalUnit.nalUnitType));
+ }
+ }
+
+ if (picReady)
+ {
+ h264bsdFilterPicture(pStorage->currImage, pStorage->mb);
+
+ h264bsdResetStorage(pStorage);
+
+ picOrderCnt = h264bsdDecodePicOrderCnt(pStorage->poc,
+ pStorage->activeSps, pStorage->sliceHeader, pStorage->prevNalUnit);
+
+ if (pStorage->validSliceInAccessUnit)
+ {
+ if (pStorage->prevNalUnit->nalRefIdc)
+ {
+ tmp = h264bsdMarkDecRefPic(pStorage->dpb,
+ &pStorage->sliceHeader->decRefPicMarking,
+ pStorage->currImage, pStorage->sliceHeader->frameNum,
+ picOrderCnt,
+ IS_IDR_NAL_UNIT(pStorage->prevNalUnit) ?
+ HANTRO_TRUE : HANTRO_FALSE,
+ pStorage->currentPicId, pStorage->numConcealedMbs);
+ }
+ /* non-reference picture, just store for possible display
+ * reordering */
+ else
+ {
+ tmp = h264bsdMarkDecRefPic(pStorage->dpb, NULL,
+ pStorage->currImage, pStorage->sliceHeader->frameNum,
+ picOrderCnt,
+ IS_IDR_NAL_UNIT(pStorage->prevNalUnit) ?
+ HANTRO_TRUE : HANTRO_FALSE,
+ pStorage->currentPicId, pStorage->numConcealedMbs);
+ }
+ }
+
+ pStorage->picStarted = HANTRO_FALSE;
+ pStorage->validSliceInAccessUnit = HANTRO_FALSE;
+
+ return(H264BSD_PIC_RDY);
+ }
+ else
+ return(H264BSD_RDY);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdShutdown
+
+ Functional description:
+ Shutdown a decoder instance. Function frees all the memories
+ allocated for the decoder instance.
+
+ Inputs:
+ pStorage pointer to storage data structure
+
+ Returns:
+ none
+
+
+------------------------------------------------------------------------------*/
+
+void h264bsdShutdown(storage_t *pStorage)
+{
+
+/* Variables */
+
+ u32 i;
+
+/* Code */
+
+ ASSERT(pStorage);
+
+ for (i = 0; i < MAX_NUM_SEQ_PARAM_SETS; i++)
+ {
+ if (pStorage->sps[i])
+ {
+ FREE(pStorage->sps[i]->offsetForRefFrame);
+ FREE(pStorage->sps[i]->vuiParameters);
+ FREE(pStorage->sps[i]);
+ }
+ }
+
+ for (i = 0; i < MAX_NUM_PIC_PARAM_SETS; i++)
+ {
+ if (pStorage->pps[i])
+ {
+ FREE(pStorage->pps[i]->runLength);
+ FREE(pStorage->pps[i]->topLeft);
+ FREE(pStorage->pps[i]->bottomRight);
+ FREE(pStorage->pps[i]->sliceGroupId);
+ FREE(pStorage->pps[i]);
+ }
+ }
+
+ FREE(pStorage->mbLayer);
+ FREE(pStorage->mb);
+ FREE(pStorage->sliceGroupMap);
+
+ h264bsdFreeDpb(pStorage->dpb);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdNextOutputPicture
+
+ Functional description:
+ Get next output picture in display order.
+
+ Inputs:
+ pStorage pointer to storage data structure
+
+ Outputs:
+ picId identifier of the picture will be stored here
+ isIdrPic IDR flag of the picture will be stored here
+ numErrMbs number of concealed macroblocks in the picture
+ will be stored here
+
+ Returns:
+ pointer to the picture data
+ NULL if no pictures available for display
+
+------------------------------------------------------------------------------*/
+
+u8* h264bsdNextOutputPicture(storage_t *pStorage, u32 *picId, u32 *isIdrPic,
+ u32 *numErrMbs)
+{
+
+/* Variables */
+
+ dpbOutPicture_t *pOut;
+
+/* Code */
+
+ ASSERT(pStorage);
+
+ pOut = h264bsdDpbOutputPicture(pStorage->dpb);
+
+ if (pOut != NULL)
+ {
+ *picId = pOut->picId;
+ *isIdrPic = pOut->isIdr;
+ *numErrMbs = pOut->numErrMbs;
+ return (pOut->data);
+ }
+ else
+ return(NULL);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdPicWidth
+
+ Functional description:
+ Get width of the picture in macroblocks
+
+ Inputs:
+ pStorage pointer to storage data structure
+
+ Outputs:
+ none
+
+ Returns:
+ picture width
+ 0 if parameters sets not yet activated
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdPicWidth(storage_t *pStorage)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(pStorage);
+
+ if (pStorage->activeSps)
+ return(pStorage->activeSps->picWidthInMbs);
+ else
+ return(0);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdPicHeight
+
+ Functional description:
+ Get height of the picture in macroblocks
+
+ Inputs:
+ pStorage pointer to storage data structure
+
+ Outputs:
+ none
+
+ Returns:
+ picture width
+ 0 if parameters sets not yet activated
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdPicHeight(storage_t *pStorage)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(pStorage);
+
+ if (pStorage->activeSps)
+ return(pStorage->activeSps->picHeightInMbs);
+ else
+ return(0);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdFlushBuffer
+
+ Functional description:
+ Flush the decoded picture buffer, see dpb.c for details
+
+ Inputs:
+ pStorage pointer to storage data structure
+
+------------------------------------------------------------------------------*/
+
+void h264bsdFlushBuffer(storage_t *pStorage)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(pStorage);
+
+ h264bsdFlushDpb(pStorage->dpb);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdCheckValidParamSets
+
+ Functional description:
+ Check if any valid parameter set combinations (SPS/PPS) exists.
+
+ Inputs:
+ pStorage pointer to storage structure
+
+ Returns:
+ 1 at least one valid SPS/PPS combination found
+ 0 no valid param set combinations found
+
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdCheckValidParamSets(storage_t *pStorage)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(pStorage);
+
+ return(h264bsdValidParamSets(pStorage) == HANTRO_OK ? 1 : 0);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdVideoRange
+
+ Functional description:
+ Get value of video_full_range_flag received in the VUI data.
+
+ Inputs:
+ pStorage pointer to storage structure
+
+ Returns:
+ 1 video_full_range_flag received and value is 1
+ 0 otherwise
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdVideoRange(storage_t *pStorage)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(pStorage);
+
+ if (pStorage->activeSps && pStorage->activeSps->vuiParametersPresentFlag &&
+ pStorage->activeSps->vuiParameters &&
+ pStorage->activeSps->vuiParameters->videoSignalTypePresentFlag &&
+ pStorage->activeSps->vuiParameters->videoFullRangeFlag)
+ return(1);
+ else /* default value of video_full_range_flag is 0 */
+ return(0);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdMatrixCoefficients
+
+ Functional description:
+ Get value of matrix_coefficients received in the VUI data
+
+ Inputs:
+ pStorage pointer to storage structure
+
+ Outputs:
+ value of matrix_coefficients if received
+ 2 otherwise (this is the default value)
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdMatrixCoefficients(storage_t *pStorage)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(pStorage);
+
+ if (pStorage->activeSps && pStorage->activeSps->vuiParametersPresentFlag &&
+ pStorage->activeSps->vuiParameters &&
+ pStorage->activeSps->vuiParameters->videoSignalTypePresentFlag &&
+ pStorage->activeSps->vuiParameters->colourDescriptionPresentFlag)
+ return(pStorage->activeSps->vuiParameters->matrixCoefficients);
+ else /* default unspecified */
+ return(2);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: hh264bsdCroppingParams
+
+ Functional description:
+ Get cropping parameters of the active SPS
+
+ Inputs:
+ pStorage pointer to storage structure
+
+ Outputs:
+ croppingFlag flag indicating if cropping params present is
+ stored here
+ leftOffset cropping left offset in pixels is stored here
+ width width of the image after cropping is stored here
+ topOffset cropping top offset in pixels is stored here
+ height height of the image after cropping is stored here
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void h264bsdCroppingParams(storage_t *pStorage, u32 *croppingFlag,
+ u32 *leftOffset, u32 *width, u32 *topOffset, u32 *height)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(pStorage);
+
+ if (pStorage->activeSps && pStorage->activeSps->frameCroppingFlag)
+ {
+ *croppingFlag = 1;
+ *leftOffset = 2 * pStorage->activeSps->frameCropLeftOffset;
+ *width = 16 * pStorage->activeSps->picWidthInMbs -
+ 2 * (pStorage->activeSps->frameCropLeftOffset +
+ pStorage->activeSps->frameCropRightOffset);
+ *topOffset = 2 * pStorage->activeSps->frameCropTopOffset;
+ *height = 16 * pStorage->activeSps->picHeightInMbs -
+ 2 * (pStorage->activeSps->frameCropTopOffset +
+ pStorage->activeSps->frameCropBottomOffset);
+ }
+ else
+ {
+ *croppingFlag = 0;
+ *leftOffset = 0;
+ *width = 0;
+ *topOffset = 0;
+ *height = 0;
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdSampleAspectRatio
+
+ Functional description:
+ Get aspect ratio received in the VUI data
+
+ Inputs:
+ pStorage pointer to storage structure
+
+ Outputs:
+ sarWidth sample aspect ratio height
+ sarHeight sample aspect ratio width
+
+------------------------------------------------------------------------------*/
+
+void h264bsdSampleAspectRatio(storage_t *pStorage, u32 *sarWidth, u32 *sarHeight)
+{
+
+/* Variables */
+ u32 w = 1;
+ u32 h = 1;
+/* Code */
+
+ ASSERT(pStorage);
+
+
+ if (pStorage->activeSps &&
+ pStorage->activeSps->vuiParametersPresentFlag &&
+ pStorage->activeSps->vuiParameters &&
+ pStorage->activeSps->vuiParameters->aspectRatioPresentFlag )
+ {
+ switch (pStorage->activeSps->vuiParameters->aspectRatioIdc)
+ {
+ case ASPECT_RATIO_UNSPECIFIED: w = 0; h = 0; break;
+ case ASPECT_RATIO_1_1: w = 1; h = 1; break;
+ case ASPECT_RATIO_12_11: w = 12; h = 11; break;
+ case ASPECT_RATIO_10_11: w = 10; h = 11; break;
+ case ASPECT_RATIO_16_11: w = 16; h = 11; break;
+ case ASPECT_RATIO_40_33: w = 40; h = 33; break;
+ case ASPECT_RATIO_24_11: w = 24; h = 11; break;
+ case ASPECT_RATIO_20_11: w = 20; h = 11; break;
+ case ASPECT_RATIO_32_11: w = 32; h = 11; break;
+ case ASPECT_RATIO_80_33: w = 80; h = 33; break;
+ case ASPECT_RATIO_18_11: w = 18; h = 11; break;
+ case ASPECT_RATIO_15_11: w = 15; h = 11; break;
+ case ASPECT_RATIO_64_33: w = 64; h = 33; break;
+ case ASPECT_RATIO_160_99: w = 160; h = 99; break;
+ case ASPECT_RATIO_EXTENDED_SAR:
+ w = pStorage->activeSps->vuiParameters->sarWidth;
+ h = pStorage->activeSps->vuiParameters->sarHeight;
+ if ((w == 0) || (h == 0))
+ w = h = 0;
+ break;
+ default:
+ w = 0;
+ h = 0;
+ break;
+ }
+ }
+
+ /* set aspect ratio*/
+ *sarWidth = w;
+ *sarHeight = h;
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdProfile
+
+ Functional description:
+ Get profile information from active SPS
+
+ Inputs:
+ pStorage pointer to storage structure
+
+ Outputs:
+ profile current profile
+
+------------------------------------------------------------------------------*/
+u32 h264bsdProfile(storage_t *pStorage)
+{
+ if (pStorage->activeSps)
+ return pStorage->activeSps->profileIdc;
+ else
+ return 0;
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.h
new file mode 100644
index 0000000..8336523
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_decoder.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_DECODER_H
+#define H264SWDEC_DECODER_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_storage.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/* enumerated return values of the functions */
+enum {
+ H264BSD_RDY,
+ H264BSD_PIC_RDY,
+ H264BSD_HDRS_RDY,
+ H264BSD_ERROR,
+ H264BSD_PARAM_SET_ERROR,
+ H264BSD_MEMALLOC_ERROR
+};
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdInit(storage_t *pStorage, u32 noOutputReordering);
+u32 h264bsdDecode(storage_t *pStorage, u8 *byteStrm, u32 len, u32 picId,
+ u32 *readBytes);
+void h264bsdShutdown(storage_t *pStorage);
+
+u8* h264bsdNextOutputPicture(storage_t *pStorage, u32 *picId, u32 *isIdrPic,
+ u32 *numErrMbs);
+
+u32 h264bsdPicWidth(storage_t *pStorage);
+u32 h264bsdPicHeight(storage_t *pStorage);
+u32 h264bsdVideoRange(storage_t *pStorage);
+u32 h264bsdMatrixCoefficients(storage_t *pStorage);
+void h264bsdCroppingParams(storage_t *pStorage, u32 *croppingFlag,
+ u32 *left, u32 *width, u32 *top, u32 *height);
+void h264bsdSampleAspectRatio(storage_t *pStorage,
+ u32 *sarWidth, u32 *sarHeight);
+u32 h264bsdCheckValidParamSets(storage_t *pStorage);
+
+void h264bsdFlushBuffer(storage_t *pStorage);
+
+u32 h264bsdProfile(storage_t *pStorage);
+
+#endif /* #ifdef H264SWDEC_DECODER_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c
new file mode 100755
index 0000000..9517d0a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.c
@@ -0,0 +1,1584 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ ComparePictures
+ h264bsdReorderRefPicList
+ Mmcop1
+ Mmcop2
+ Mmcop3
+ Mmcop4
+ Mmcop5
+ Mmcop6
+ h264bsdMarkDecRefPic
+ h264bsdGetRefPicData
+ h264bsdAllocateDpbImage
+ SlidingWindowRefPicMarking
+ h264bsdInitDpb
+ h264bsdResetDpb
+ h264bsdInitRefPicList
+ FindDpbPic
+ SetPicNums
+ h264bsdCheckGapsInFrameNum
+ FindSmallestPicOrderCnt
+ OutputPicture
+ h264bsdDpbOutputPicture
+ h264bsdFlushDpb
+ h264bsdFreeDpb
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_cfg.h"
+#include "h264bsd_dpb.h"
+#include "h264bsd_slice_header.h"
+#include "h264bsd_image.h"
+#include "h264bsd_util.h"
+#include "basetype.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/* macros to determine picture status. Note that IS_SHORT_TERM macro returns
+ * true also for non-existing pictures because non-existing pictures are
+ * regarded short term pictures according to H.264 standard */
+#define IS_REFERENCE(a) ((a).status)
+#define IS_EXISTING(a) ((a).status > NON_EXISTING)
+#define IS_SHORT_TERM(a) \
+ ((a).status == NON_EXISTING || (a).status == SHORT_TERM)
+#define IS_LONG_TERM(a) ((a).status == LONG_TERM)
+
+/* macro to set a picture unused for reference */
+#define SET_UNUSED(a) (a).status = UNUSED;
+
+#define MAX_NUM_REF_IDX_L0_ACTIVE 16
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static i32 ComparePictures(const void *ptr1, const void *ptr2);
+
+static u32 Mmcop1(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums);
+
+static u32 Mmcop2(dpbStorage_t *dpb, u32 longTermPicNum);
+
+static u32 Mmcop3(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums,
+ u32 longTermFrameIdx);
+
+static u32 Mmcop4(dpbStorage_t *dpb, u32 maxLongTermFrameIdx);
+
+static u32 Mmcop5(dpbStorage_t *dpb);
+
+static u32 Mmcop6(dpbStorage_t *dpb, u32 frameNum, i32 picOrderCnt,
+ u32 longTermFrameIdx);
+
+static u32 SlidingWindowRefPicMarking(dpbStorage_t *dpb);
+
+static i32 FindDpbPic(dpbStorage_t *dpb, i32 picNum, u32 isShortTerm);
+
+static void SetPicNums(dpbStorage_t *dpb, u32 currFrameNum);
+
+static dpbPicture_t* FindSmallestPicOrderCnt(dpbStorage_t *dpb);
+
+static u32 OutputPicture(dpbStorage_t *dpb);
+
+static void ShellSort(dpbPicture_t *pPic, u32 num);
+
+/*------------------------------------------------------------------------------
+
+ Function: ComparePictures
+
+ Functional description:
+ Function to compare dpb pictures, used by the ShellSort() function.
+ Order of the pictures after sorting shall be as follows:
+ 1) short term reference pictures starting with the largest
+ picNum
+ 2) long term reference pictures starting with the smallest
+ longTermPicNum
+ 3) pictures unused for reference but needed for display
+ 4) other pictures
+
+ Returns:
+ -1 pic 1 is greater than pic 2
+ 0 equal from comparison point of view
+ 1 pic 2 is greater then pic 1
+
+------------------------------------------------------------------------------*/
+
+static i32 ComparePictures(const void *ptr1, const void *ptr2)
+{
+
+/* Variables */
+
+ dpbPicture_t *pic1, *pic2;
+
+/* Code */
+
+ ASSERT(ptr1);
+ ASSERT(ptr2);
+
+ pic1 = (dpbPicture_t*)ptr1;
+ pic2 = (dpbPicture_t*)ptr2;
+
+ /* both are non-reference pictures, check if needed for display */
+ if (!IS_REFERENCE(*pic1) && !IS_REFERENCE(*pic2))
+ {
+ if (pic1->toBeDisplayed && !pic2->toBeDisplayed)
+ return(-1);
+ else if (!pic1->toBeDisplayed && pic2->toBeDisplayed)
+ return(1);
+ else
+ return(0);
+ }
+ /* only pic 1 needed for reference -> greater */
+ else if (!IS_REFERENCE(*pic2))
+ return(-1);
+ /* only pic 2 needed for reference -> greater */
+ else if (!IS_REFERENCE(*pic1))
+ return(1);
+ /* both are short term reference pictures -> check picNum */
+ else if (IS_SHORT_TERM(*pic1) && IS_SHORT_TERM(*pic2))
+ {
+ if (pic1->picNum > pic2->picNum)
+ return(-1);
+ else if (pic1->picNum < pic2->picNum)
+ return(1);
+ else
+ return(0);
+ }
+ /* only pic 1 is short term -> greater */
+ else if (IS_SHORT_TERM(*pic1))
+ return(-1);
+ /* only pic 2 is short term -> greater */
+ else if (IS_SHORT_TERM(*pic2))
+ return(1);
+ /* both are long term reference pictures -> check picNum (contains the
+ * longTermPicNum */
+ else
+ {
+ if (pic1->picNum > pic2->picNum)
+ return(1);
+ else if (pic1->picNum < pic2->picNum)
+ return(-1);
+ else
+ return(0);
+ }
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdReorderRefPicList
+
+ Functional description:
+ Function to perform reference picture list reordering based on
+ reordering commands received in the slice header. See details
+ of the process in the H.264 standard.
+
+ Inputs:
+ dpb pointer to dpb storage structure
+ order pointer to reordering commands
+ currFrameNum current frame number
+ numRefIdxActive number of active reference indices for current
+ picture
+
+ Outputs:
+ dpb 'list' field of the structure reordered
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK if non-existing pictures referred to in the
+ reordering commands
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdReorderRefPicList(
+ dpbStorage_t *dpb,
+ refPicListReordering_t *order,
+ u32 currFrameNum,
+ u32 numRefIdxActive)
+{
+
+/* Variables */
+
+ u32 i, j, k, picNumPred, refIdx;
+ i32 picNum, picNumNoWrap, index;
+ u32 isShortTerm;
+
+/* Code */
+
+ ASSERT(order);
+ ASSERT(currFrameNum <= dpb->maxFrameNum);
+ ASSERT(numRefIdxActive <= MAX_NUM_REF_IDX_L0_ACTIVE);
+
+ /* set dpb picture numbers for sorting */
+ SetPicNums(dpb, currFrameNum);
+
+ if (!order->refPicListReorderingFlagL0)
+ return(HANTRO_OK);
+
+ refIdx = 0;
+ picNumPred = currFrameNum;
+
+ i = 0;
+ while (order->command[i].reorderingOfPicNumsIdc < 3)
+ {
+ /* short term */
+ if (order->command[i].reorderingOfPicNumsIdc < 2)
+ {
+ if (order->command[i].reorderingOfPicNumsIdc == 0)
+ {
+ picNumNoWrap =
+ (i32)picNumPred - (i32)order->command[i].absDiffPicNum;
+ if (picNumNoWrap < 0)
+ picNumNoWrap += (i32)dpb->maxFrameNum;
+ }
+ else
+ {
+ picNumNoWrap =
+ (i32)(picNumPred + order->command[i].absDiffPicNum);
+ if (picNumNoWrap >= (i32)dpb->maxFrameNum)
+ picNumNoWrap -= (i32)dpb->maxFrameNum;
+ }
+ picNumPred = (u32)picNumNoWrap;
+ picNum = picNumNoWrap;
+ if ((u32)picNumNoWrap > currFrameNum)
+ picNum -= (i32)dpb->maxFrameNum;
+ isShortTerm = HANTRO_TRUE;
+ }
+ /* long term */
+ else
+ {
+ picNum = (i32)order->command[i].longTermPicNum;
+ isShortTerm = HANTRO_FALSE;
+
+ }
+ /* find corresponding picture from dpb */
+ index = FindDpbPic(dpb, picNum, isShortTerm);
+ if (index < 0 || !IS_EXISTING(dpb->buffer[index]))
+ return(HANTRO_NOK);
+
+ /* shift pictures */
+ for (j = numRefIdxActive; j > refIdx; j--)
+ dpb->list[j] = dpb->list[j-1];
+ /* put picture into the list */
+ dpb->list[refIdx++] = &dpb->buffer[index];
+ /* remove later references to the same picture */
+ for (j = k = refIdx; j <= numRefIdxActive; j++)
+ if(dpb->list[j] != &dpb->buffer[index])
+ dpb->list[k++] = dpb->list[j];
+
+ i++;
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Mmcop1
+
+ Functional description:
+ Function to mark a short-term reference picture unused for
+ reference, memory_management_control_operation equal to 1
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK failure, picture does not exist in the buffer
+
+------------------------------------------------------------------------------*/
+
+static u32 Mmcop1(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums)
+{
+
+/* Variables */
+
+ i32 index, picNum;
+
+/* Code */
+
+ ASSERT(currPicNum < dpb->maxFrameNum);
+
+ picNum = (i32)currPicNum - (i32)differenceOfPicNums;
+
+ index = FindDpbPic(dpb, picNum, HANTRO_TRUE);
+ if (index < 0)
+ return(HANTRO_NOK);
+
+ SET_UNUSED(dpb->buffer[index]);
+ dpb->numRefFrames--;
+ if (!dpb->buffer[index].toBeDisplayed)
+ dpb->fullness--;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Mmcop2
+
+ Functional description:
+ Function to mark a long-term reference picture unused for
+ reference, memory_management_control_operation equal to 2
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK failure, picture does not exist in the buffer
+
+------------------------------------------------------------------------------*/
+
+static u32 Mmcop2(dpbStorage_t *dpb, u32 longTermPicNum)
+{
+
+/* Variables */
+
+ i32 index;
+
+/* Code */
+
+ index = FindDpbPic(dpb, (i32)longTermPicNum, HANTRO_FALSE);
+ if (index < 0)
+ return(HANTRO_NOK);
+
+ SET_UNUSED(dpb->buffer[index]);
+ dpb->numRefFrames--;
+ if (!dpb->buffer[index].toBeDisplayed)
+ dpb->fullness--;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Mmcop3
+
+ Functional description:
+ Function to assing a longTermFrameIdx to a short-term reference
+ frame (i.e. to change it to a long-term reference picture),
+ memory_management_control_operation equal to 3
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK failure, short-term picture does not exist in the
+ buffer or is a non-existing picture, or invalid
+ longTermFrameIdx given
+
+------------------------------------------------------------------------------*/
+
+static u32 Mmcop3(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums,
+ u32 longTermFrameIdx)
+{
+
+/* Variables */
+
+ i32 index, picNum;
+ u32 i;
+
+/* Code */
+
+ ASSERT(dpb);
+ ASSERT(currPicNum < dpb->maxFrameNum);
+
+ if ( (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) ||
+ (longTermFrameIdx > dpb->maxLongTermFrameIdx) )
+ return(HANTRO_NOK);
+
+ /* check if a long term picture with the same longTermFrameIdx already
+ * exist and remove it if necessary */
+ for (i = 0; i < dpb->maxRefFrames; i++)
+ if (IS_LONG_TERM(dpb->buffer[i]) &&
+ (u32)dpb->buffer[i].picNum == longTermFrameIdx)
+ {
+ SET_UNUSED(dpb->buffer[i]);
+ dpb->numRefFrames--;
+ if (!dpb->buffer[i].toBeDisplayed)
+ dpb->fullness--;
+ break;
+ }
+
+ picNum = (i32)currPicNum - (i32)differenceOfPicNums;
+
+ index = FindDpbPic(dpb, picNum, HANTRO_TRUE);
+ if (index < 0)
+ return(HANTRO_NOK);
+ if (!IS_EXISTING(dpb->buffer[index]))
+ return(HANTRO_NOK);
+
+ dpb->buffer[index].status = LONG_TERM;
+ dpb->buffer[index].picNum = (i32)longTermFrameIdx;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Mmcop4
+
+ Functional description:
+ Function to set maxLongTermFrameIdx,
+ memory_management_control_operation equal to 4
+
+ Returns:
+ HANTRO_OK success
+
+------------------------------------------------------------------------------*/
+
+static u32 Mmcop4(dpbStorage_t *dpb, u32 maxLongTermFrameIdx)
+{
+
+/* Variables */
+
+ u32 i;
+
+/* Code */
+
+ dpb->maxLongTermFrameIdx = maxLongTermFrameIdx;
+
+ for (i = 0; i < dpb->maxRefFrames; i++)
+ if (IS_LONG_TERM(dpb->buffer[i]) &&
+ ( ((u32)dpb->buffer[i].picNum > maxLongTermFrameIdx) ||
+ (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) ) )
+ {
+ SET_UNUSED(dpb->buffer[i]);
+ dpb->numRefFrames--;
+ if (!dpb->buffer[i].toBeDisplayed)
+ dpb->fullness--;
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Mmcop5
+
+ Functional description:
+ Function to mark all reference pictures unused for reference and
+ set maxLongTermFrameIdx to NO_LONG_TERM_FRAME_INDICES,
+ memory_management_control_operation equal to 5. Function flushes
+ the buffer and places all pictures that are needed for display into
+ the output buffer.
+
+ Returns:
+ HANTRO_OK success
+
+------------------------------------------------------------------------------*/
+
+static u32 Mmcop5(dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ u32 i;
+
+/* Code */
+
+ for (i = 0; i < 16; i++)
+ {
+ if (IS_REFERENCE(dpb->buffer[i]))
+ {
+ SET_UNUSED(dpb->buffer[i]);
+ if (!dpb->buffer[i].toBeDisplayed)
+ dpb->fullness--;
+ }
+ }
+
+ /* output all pictures */
+ while (OutputPicture(dpb) == HANTRO_OK)
+ ;
+ dpb->numRefFrames = 0;
+ dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES;
+ dpb->prevRefFrameNum = 0;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Mmcop6
+
+ Functional description:
+ Function to assign longTermFrameIdx to the current picture,
+ memory_management_control_operation equal to 6
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid longTermFrameIdx or no room for current
+ picture in the buffer
+
+------------------------------------------------------------------------------*/
+
+static u32 Mmcop6(dpbStorage_t *dpb, u32 frameNum, i32 picOrderCnt,
+ u32 longTermFrameIdx)
+{
+
+/* Variables */
+
+ u32 i;
+
+/* Code */
+
+ ASSERT(frameNum < dpb->maxFrameNum);
+
+ if ( (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) ||
+ (longTermFrameIdx > dpb->maxLongTermFrameIdx) )
+ return(HANTRO_NOK);
+
+ /* check if a long term picture with the same longTermFrameIdx already
+ * exist and remove it if necessary */
+ for (i = 0; i < dpb->maxRefFrames; i++)
+ if (IS_LONG_TERM(dpb->buffer[i]) &&
+ (u32)dpb->buffer[i].picNum == longTermFrameIdx)
+ {
+ SET_UNUSED(dpb->buffer[i]);
+ dpb->numRefFrames--;
+ if (!dpb->buffer[i].toBeDisplayed)
+ dpb->fullness--;
+ break;
+ }
+
+ if (dpb->numRefFrames < dpb->maxRefFrames)
+ {
+ dpb->currentOut->frameNum = frameNum;
+ dpb->currentOut->picNum = (i32)longTermFrameIdx;
+ dpb->currentOut->picOrderCnt = picOrderCnt;
+ dpb->currentOut->status = LONG_TERM;
+ if (dpb->noReordering)
+ dpb->currentOut->toBeDisplayed = HANTRO_FALSE;
+ else
+ dpb->currentOut->toBeDisplayed = HANTRO_TRUE;
+ dpb->numRefFrames++;
+ dpb->fullness++;
+ return(HANTRO_OK);
+ }
+ /* if there is no room, return an error */
+ else
+ return(HANTRO_NOK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdMarkDecRefPic
+
+ Functional description:
+ Function to perform reference picture marking process. This
+ function should be called both for reference and non-reference
+ pictures. Non-reference pictures shall have mark pointer set to
+ NULL.
+
+ Inputs:
+ dpb pointer to the DPB data structure
+ mark pointer to reference picture marking commands
+ image pointer to current picture to be placed in the buffer
+ frameNum frame number of the current picture
+ picOrderCnt picture order count for the current picture
+ isIdr flag to indicate if the current picture is an
+ IDR picture
+ currentPicId identifier for the current picture, from the
+ application, stored along with the picture
+ numErrMbs number of concealed macroblocks in the current
+ picture, stored along with the picture
+
+ Outputs:
+ dpb 'buffer' modified, possible output frames placed into
+ 'outBuf'
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK failure
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdMarkDecRefPic(
+ dpbStorage_t *dpb,
+ decRefPicMarking_t *mark,
+ image_t *image,
+ u32 frameNum,
+ i32 picOrderCnt,
+ u32 isIdr,
+ u32 currentPicId,
+ u32 numErrMbs)
+{
+
+/* Variables */
+
+ u32 i, status;
+ u32 markedAsLongTerm;
+ u32 toBeDisplayed;
+
+/* Code */
+
+ ASSERT(dpb);
+ ASSERT(mark || !isIdr);
+ ASSERT(!isIdr || (frameNum == 0 && picOrderCnt == 0));
+ ASSERT(frameNum < dpb->maxFrameNum);
+
+ if (image->data != dpb->currentOut->data)
+ {
+ EPRINT("TRYING TO MARK NON-ALLOCATED IMAGE");
+ return(HANTRO_NOK);
+ }
+
+ dpb->lastContainsMmco5 = HANTRO_FALSE;
+ status = HANTRO_OK;
+
+ toBeDisplayed = dpb->noReordering ? HANTRO_FALSE : HANTRO_TRUE;
+
+ /* non-reference picture, stored for display reordering purposes */
+ if (mark == NULL)
+ {
+ dpb->currentOut->status = UNUSED;
+ dpb->currentOut->frameNum = frameNum;
+ dpb->currentOut->picNum = (i32)frameNum;
+ dpb->currentOut->picOrderCnt = picOrderCnt;
+ dpb->currentOut->toBeDisplayed = toBeDisplayed;
+ if (!dpb->noReordering)
+ dpb->fullness++;
+ }
+ /* IDR picture */
+ else if (isIdr)
+ {
+
+ /* h264bsdCheckGapsInFrameNum not called for IDR pictures -> have to
+ * reset numOut and outIndex here */
+ dpb->numOut = dpb->outIndex = 0;
+
+ /* flush the buffer */
+ Mmcop5(dpb);
+ /* if noOutputOfPriorPicsFlag was set -> the pictures preceding the
+ * IDR picture shall not be output -> set output buffer empty */
+ if (mark->noOutputOfPriorPicsFlag || dpb->noReordering)
+ {
+ dpb->numOut = 0;
+ dpb->outIndex = 0;
+ }
+
+ if (mark->longTermReferenceFlag)
+ {
+ dpb->currentOut->status = LONG_TERM;
+ dpb->maxLongTermFrameIdx = 0;
+ }
+ else
+ {
+ dpb->currentOut->status = SHORT_TERM;
+ dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES;
+ }
+ dpb->currentOut->frameNum = 0;
+ dpb->currentOut->picNum = 0;
+ dpb->currentOut->picOrderCnt = 0;
+ dpb->currentOut->toBeDisplayed = toBeDisplayed;
+ dpb->fullness = 1;
+ dpb->numRefFrames = 1;
+ }
+ /* reference picture */
+ else
+ {
+ markedAsLongTerm = HANTRO_FALSE;
+ if (mark->adaptiveRefPicMarkingModeFlag)
+ {
+ i = 0;
+ while (mark->operation[i].memoryManagementControlOperation)
+ {
+ switch (mark->operation[i].memoryManagementControlOperation)
+ {
+ case 1:
+ status = Mmcop1(
+ dpb,
+ frameNum,
+ mark->operation[i].differenceOfPicNums);
+ break;
+
+ case 2:
+ status = Mmcop2(dpb, mark->operation[i].longTermPicNum);
+ break;
+
+ case 3:
+ status = Mmcop3(
+ dpb,
+ frameNum,
+ mark->operation[i].differenceOfPicNums,
+ mark->operation[i].longTermFrameIdx);
+ break;
+
+ case 4:
+ status = Mmcop4(
+ dpb,
+ mark->operation[i].maxLongTermFrameIdx);
+ break;
+
+ case 5:
+ status = Mmcop5(dpb);
+ dpb->lastContainsMmco5 = HANTRO_TRUE;
+ frameNum = 0;
+ break;
+
+ case 6:
+ status = Mmcop6(
+ dpb,
+ frameNum,
+ picOrderCnt,
+ mark->operation[i].longTermFrameIdx);
+ if (status == HANTRO_OK)
+ markedAsLongTerm = HANTRO_TRUE;
+ break;
+
+ default: /* invalid memory management control operation */
+ status = HANTRO_NOK;
+ break;
+ }
+ if (status != HANTRO_OK)
+ {
+ break;
+ }
+ i++;
+ }
+ }
+ else
+ {
+ status = SlidingWindowRefPicMarking(dpb);
+ }
+ /* if current picture was not marked as long-term reference by
+ * memory management control operation 6 -> mark current as short
+ * term and insert it into dpb (if there is room) */
+ if (!markedAsLongTerm)
+ {
+ if (dpb->numRefFrames < dpb->maxRefFrames)
+ {
+ dpb->currentOut->frameNum = frameNum;
+ dpb->currentOut->picNum = (i32)frameNum;
+ dpb->currentOut->picOrderCnt = picOrderCnt;
+ dpb->currentOut->status = SHORT_TERM;
+ dpb->currentOut->toBeDisplayed = toBeDisplayed;
+ dpb->fullness++;
+ dpb->numRefFrames++;
+ }
+ /* no room */
+ else
+ {
+ status = HANTRO_NOK;
+ }
+ }
+ }
+
+ dpb->currentOut->isIdr = isIdr;
+ dpb->currentOut->picId = currentPicId;
+ dpb->currentOut->numErrMbs = numErrMbs;
+
+ /* dpb was initialized to not to reorder the pictures -> output current
+ * picture immediately */
+ if (dpb->noReordering)
+ {
+ ASSERT(dpb->numOut == 0);
+ ASSERT(dpb->outIndex == 0);
+ dpb->outBuf[dpb->numOut].data = dpb->currentOut->data;
+ dpb->outBuf[dpb->numOut].isIdr = dpb->currentOut->isIdr;
+ dpb->outBuf[dpb->numOut].picId = dpb->currentOut->picId;
+ dpb->outBuf[dpb->numOut].numErrMbs = dpb->currentOut->numErrMbs;
+ dpb->numOut++;
+ }
+ else
+ {
+ /* output pictures if buffer full */
+ while (dpb->fullness > dpb->dpbSize)
+ {
+ i = OutputPicture(dpb);
+ ASSERT(i == HANTRO_OK);
+ }
+ }
+
+ /* sort dpb */
+ ShellSort(dpb->buffer, dpb->dpbSize+1);
+
+ return(status);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdGetRefPicData
+
+ Functional description:
+ Function to get reference picture data from the reference picture
+ list
+
+ Returns:
+ pointer to desired reference picture data
+ NULL if invalid index or non-existing picture referred
+
+------------------------------------------------------------------------------*/
+
+u8* h264bsdGetRefPicData(dpbStorage_t *dpb, u32 index)
+{
+
+/* Variables */
+
+/* Code */
+
+ if(index > 16 || dpb->list[index] == NULL)
+ return(NULL);
+ else if(!IS_EXISTING(*dpb->list[index]))
+ return(NULL);
+ else
+ return(dpb->list[index]->data);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdAllocateDpbImage
+
+ Functional description:
+ function to allocate memory for a image. This function does not
+ really allocate any memory but reserves one of the buffer
+ positions for decoding of current picture
+
+ Returns:
+ pointer to memory area for the image
+
+
+------------------------------------------------------------------------------*/
+
+u8* h264bsdAllocateDpbImage(dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT( !dpb->buffer[dpb->dpbSize].toBeDisplayed &&
+ !IS_REFERENCE(dpb->buffer[dpb->dpbSize]) );
+ ASSERT(dpb->fullness <= dpb->dpbSize);
+
+ dpb->currentOut = dpb->buffer + dpb->dpbSize;
+
+ return(dpb->currentOut->data);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: SlidingWindowRefPicMarking
+
+ Functional description:
+ Function to perform sliding window refence picture marking process.
+
+ Outputs:
+ HANTRO_OK success
+ HANTRO_NOK failure, no short-term reference frame found that
+ could be marked unused
+
+
+------------------------------------------------------------------------------*/
+
+static u32 SlidingWindowRefPicMarking(dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ i32 index, picNum;
+ u32 i;
+
+/* Code */
+
+ if (dpb->numRefFrames < dpb->maxRefFrames)
+ {
+ return(HANTRO_OK);
+ }
+ else
+ {
+ index = -1;
+ picNum = 0;
+ /* find the oldest short term picture */
+ for (i = 0; i < dpb->numRefFrames; i++)
+ if (IS_SHORT_TERM(dpb->buffer[i]))
+ if (dpb->buffer[i].picNum < picNum || index == -1)
+ {
+ index = (i32)i;
+ picNum = dpb->buffer[i].picNum;
+ }
+ if (index >= 0)
+ {
+ SET_UNUSED(dpb->buffer[index]);
+ dpb->numRefFrames--;
+ if (!dpb->buffer[index].toBeDisplayed)
+ dpb->fullness--;
+
+ return(HANTRO_OK);
+ }
+ }
+
+ return(HANTRO_NOK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInitDpb
+
+ Functional description:
+ Function to initialize DPB. Reserves memories for the buffer,
+ reference picture list and output buffer. dpbSize indicates
+ the maximum DPB size indicated by the levelIdc in the stream.
+ If noReordering flag is FALSE the DPB stores dpbSize pictures
+ for display reordering purposes. On the other hand, if the
+ flag is TRUE the DPB only stores maxRefFrames reference pictures
+ and outputs all the pictures immediately.
+
+ Inputs:
+ picSizeInMbs picture size in macroblocks
+ dpbSize size of the DPB (number of pictures)
+ maxRefFrames max number of reference frames
+ maxFrameNum max frame number
+ noReordering flag to indicate that DPB does not have to
+ prepare to reorder frames for display
+
+ Outputs:
+ dpb pointer to dpb data storage
+
+ Returns:
+ HANTRO_OK success
+ MEMORY_ALLOCATION_ERROR if memory allocation failed
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdInitDpb(
+ dpbStorage_t *dpb,
+ u32 picSizeInMbs,
+ u32 dpbSize,
+ u32 maxRefFrames,
+ u32 maxFrameNum,
+ u32 noReordering)
+{
+
+/* Variables */
+
+ u32 i;
+
+/* Code */
+
+ ASSERT(picSizeInMbs);
+ ASSERT(maxRefFrames <= MAX_NUM_REF_PICS);
+ ASSERT(maxRefFrames <= dpbSize);
+ ASSERT(maxFrameNum);
+ ASSERT(dpbSize);
+
+ dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES;
+ dpb->maxRefFrames = MAX(maxRefFrames, 1);
+ if (noReordering)
+ dpb->dpbSize = dpb->maxRefFrames;
+ else
+ dpb->dpbSize = dpbSize;
+ dpb->maxFrameNum = maxFrameNum;
+ dpb->noReordering = noReordering;
+ dpb->fullness = 0;
+ dpb->numRefFrames = 0;
+ dpb->prevRefFrameNum = 0;
+
+ ALLOCATE(dpb->buffer, MAX_NUM_REF_IDX_L0_ACTIVE + 1, dpbPicture_t);
+ if (dpb->buffer == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+ H264SwDecMemset(dpb->buffer, 0,
+ (MAX_NUM_REF_IDX_L0_ACTIVE + 1)*sizeof(dpbPicture_t));
+ for (i = 0; i < dpb->dpbSize + 1; i++)
+ {
+ /* Allocate needed amount of memory, which is:
+ * image size + 32 + 15, where 32 cames from the fact that in ARM OpenMax
+ * DL implementation Functions may read beyond the end of an array,
+ * by a maximum of 32 bytes. And +15 cames for the need to align memory
+ * to 16-byte boundary */
+ ALLOCATE(dpb->buffer[i].pAllocatedData, (picSizeInMbs*384 + 32+15), u8);
+ if (dpb->buffer[i].pAllocatedData == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+
+ dpb->buffer[i].data = ALIGN(dpb->buffer[i].pAllocatedData, 16);
+ }
+
+ ALLOCATE(dpb->list, MAX_NUM_REF_IDX_L0_ACTIVE + 1, dpbPicture_t*);
+ ALLOCATE(dpb->outBuf, dpb->dpbSize+1, dpbOutPicture_t);
+
+ if (dpb->list == NULL || dpb->outBuf == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+
+ H264SwDecMemset(dpb->list, 0,
+ ((MAX_NUM_REF_IDX_L0_ACTIVE + 1) * sizeof(dpbPicture_t*)) );
+
+ dpb->numOut = dpb->outIndex = 0;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdResetDpb
+
+ Functional description:
+ Function to reset DPB. This function should be called when an IDR
+ slice (other than the first) activates new sequence parameter set.
+ Function calls h264bsdFreeDpb to free old allocated memories and
+ h264bsdInitDpb to re-initialize the DPB. Same inputs, outputs and
+ returns as for h264bsdInitDpb.
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdResetDpb(
+ dpbStorage_t *dpb,
+ u32 picSizeInMbs,
+ u32 dpbSize,
+ u32 maxRefFrames,
+ u32 maxFrameNum,
+ u32 noReordering)
+{
+
+/* Code */
+
+ ASSERT(picSizeInMbs);
+ ASSERT(maxRefFrames <= MAX_NUM_REF_PICS);
+ ASSERT(maxRefFrames <= dpbSize);
+ ASSERT(maxFrameNum);
+ ASSERT(dpbSize);
+
+ h264bsdFreeDpb(dpb);
+
+ return h264bsdInitDpb(dpb, picSizeInMbs, dpbSize, maxRefFrames,
+ maxFrameNum, noReordering);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInitRefPicList
+
+ Functional description:
+ Function to initialize reference picture list. Function just
+ sets pointers in the list according to pictures in the buffer.
+ The buffer is assumed to contain pictures sorted according to
+ what the H.264 standard says about initial reference picture list.
+
+ Inputs:
+ dpb pointer to dpb data structure
+
+ Outputs:
+ dpb 'list' field initialized
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void h264bsdInitRefPicList(dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ u32 i;
+
+/* Code */
+
+ for (i = 0; i < dpb->numRefFrames; i++)
+ dpb->list[i] = &dpb->buffer[i];
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: FindDpbPic
+
+ Functional description:
+ Function to find a reference picture from the buffer. The picture
+ to be found is identified by picNum and isShortTerm flag.
+
+ Returns:
+ index of the picture in the buffer
+ -1 if the specified picture was not found in the buffer
+
+------------------------------------------------------------------------------*/
+
+static i32 FindDpbPic(dpbStorage_t *dpb, i32 picNum, u32 isShortTerm)
+{
+
+/* Variables */
+
+ u32 i = 0;
+ u32 found = HANTRO_FALSE;
+
+/* Code */
+
+ if (isShortTerm)
+ {
+ while (i < dpb->maxRefFrames && !found)
+ {
+ if (IS_SHORT_TERM(dpb->buffer[i]) &&
+ dpb->buffer[i].picNum == picNum)
+ found = HANTRO_TRUE;
+ else
+ i++;
+ }
+ }
+ else
+ {
+ ASSERT(picNum >= 0);
+ while (i < dpb->maxRefFrames && !found)
+ {
+ if (IS_LONG_TERM(dpb->buffer[i]) &&
+ dpb->buffer[i].picNum == picNum)
+ found = HANTRO_TRUE;
+ else
+ i++;
+ }
+ }
+
+ if (found)
+ return((i32)i);
+ else
+ return(-1);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: SetPicNums
+
+ Functional description:
+ Function to set picNum values for short-term pictures in the
+ buffer. Numbering of pictures is based on frame numbers and as
+ frame numbers are modulo maxFrameNum -> frame numbers of older
+ pictures in the buffer may be bigger than the currFrameNum.
+ picNums will be set so that current frame has the largest picNum
+ and all the short-term frames in the buffer will get smaller picNum
+ representing their "distance" from the current frame. This
+ function kind of maps the modulo arithmetic back to normal.
+
+------------------------------------------------------------------------------*/
+
+static void SetPicNums(dpbStorage_t *dpb, u32 currFrameNum)
+{
+
+/* Variables */
+
+ u32 i;
+ i32 frameNumWrap;
+
+/* Code */
+
+ ASSERT(dpb);
+ ASSERT(currFrameNum < dpb->maxFrameNum);
+
+ for (i = 0; i < dpb->numRefFrames; i++)
+ if (IS_SHORT_TERM(dpb->buffer[i]))
+ {
+ if (dpb->buffer[i].frameNum > currFrameNum)
+ frameNumWrap =
+ (i32)dpb->buffer[i].frameNum - (i32)dpb->maxFrameNum;
+ else
+ frameNumWrap = (i32)dpb->buffer[i].frameNum;
+ dpb->buffer[i].picNum = frameNumWrap;
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdCheckGapsInFrameNum
+
+ Functional description:
+ Function to check gaps in frame_num and generate non-existing
+ (short term) reference pictures if necessary. This function should
+ be called only for non-IDR pictures.
+
+ Inputs:
+ dpb pointer to dpb data structure
+ frameNum frame number of the current picture
+ isRefPic flag to indicate if current picture is a reference or
+ non-reference picture
+ gapsAllowed Flag which indicates active SPS stance on whether
+ to allow gaps
+
+ Outputs:
+ dpb 'buffer' possibly modified by inserting non-existing
+ pictures with sliding window marking process
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK error in sliding window reference picture marking or
+ frameNum equal to previous reference frame used for
+ a reference picture
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdCheckGapsInFrameNum(dpbStorage_t *dpb, u32 frameNum, u32 isRefPic,
+ u32 gapsAllowed)
+{
+
+/* Variables */
+
+ u32 unUsedShortTermFrameNum;
+ u8 *tmp;
+
+/* Code */
+
+ ASSERT(dpb);
+ ASSERT(dpb->fullness <= dpb->dpbSize);
+ ASSERT(frameNum < dpb->maxFrameNum);
+
+ dpb->numOut = 0;
+ dpb->outIndex = 0;
+
+ if(!gapsAllowed)
+ return(HANTRO_OK);
+
+ if ( (frameNum != dpb->prevRefFrameNum) &&
+ (frameNum != ((dpb->prevRefFrameNum + 1) % dpb->maxFrameNum)))
+ {
+
+ unUsedShortTermFrameNum = (dpb->prevRefFrameNum + 1) % dpb->maxFrameNum;
+
+ /* store data pointer of last buffer position to be used as next
+ * "allocated" data pointer if last buffer position after this process
+ * contains data pointer located in outBuf (buffer placed in the output
+ * shall not be overwritten by the current picture) */
+ tmp = dpb->buffer[dpb->dpbSize].data;
+ do
+ {
+ SetPicNums(dpb, unUsedShortTermFrameNum);
+
+ if (SlidingWindowRefPicMarking(dpb) != HANTRO_OK)
+ {
+ return(HANTRO_NOK);
+ }
+
+ /* output pictures if buffer full */
+ while (dpb->fullness >= dpb->dpbSize)
+ {
+#ifdef _ASSERT_USED
+ ASSERT(!dpb->noReordering);
+ ASSERT(OutputPicture(dpb) == HANTRO_OK);
+#else
+ OutputPicture(dpb);
+#endif
+ }
+
+ /* add to end of list */
+ ASSERT( !dpb->buffer[dpb->dpbSize].toBeDisplayed &&
+ !IS_REFERENCE(dpb->buffer[dpb->dpbSize]) );
+ dpb->buffer[dpb->dpbSize].status = NON_EXISTING;
+ dpb->buffer[dpb->dpbSize].frameNum = unUsedShortTermFrameNum;
+ dpb->buffer[dpb->dpbSize].picNum = (i32)unUsedShortTermFrameNum;
+ dpb->buffer[dpb->dpbSize].picOrderCnt = 0;
+ dpb->buffer[dpb->dpbSize].toBeDisplayed = HANTRO_FALSE;
+ dpb->fullness++;
+ dpb->numRefFrames++;
+
+ /* sort the buffer */
+ ShellSort(dpb->buffer, dpb->dpbSize+1);
+
+ unUsedShortTermFrameNum = (unUsedShortTermFrameNum + 1) %
+ dpb->maxFrameNum;
+
+ } while (unUsedShortTermFrameNum != frameNum);
+
+ /* pictures placed in output buffer -> check that 'data' in
+ * buffer position dpbSize is not in the output buffer (this will be
+ * "allocated" by h264bsdAllocateDpbImage). If it is -> exchange data
+ * pointer with the one stored in the beginning */
+ if (dpb->numOut)
+ {
+ u32 i;
+
+ for (i = 0; i < dpb->numOut; i++)
+ {
+ if (dpb->outBuf[i].data == dpb->buffer[dpb->dpbSize].data)
+ {
+ /* find buffer position containing data pointer stored in
+ * tmp */
+ for (i = 0; i < dpb->dpbSize; i++)
+ {
+ if (dpb->buffer[i].data == tmp)
+ {
+ dpb->buffer[i].data =
+ dpb->buffer[dpb->dpbSize].data;
+ dpb->buffer[dpb->dpbSize].data = tmp;
+ break;
+ }
+ }
+ ASSERT(i < dpb->dpbSize);
+ break;
+ }
+ }
+ }
+ }
+ /* frameNum for reference pictures shall not be the same as for previous
+ * reference picture, otherwise accesses to pictures in the buffer cannot
+ * be solved unambiguously */
+ else if (isRefPic && frameNum == dpb->prevRefFrameNum)
+ {
+ return(HANTRO_NOK);
+ }
+
+ /* save current frame_num in prevRefFrameNum. For non-reference frame
+ * prevFrameNum is set to frame number of last non-existing frame above */
+ if (isRefPic)
+ dpb->prevRefFrameNum = frameNum;
+ else if (frameNum != dpb->prevRefFrameNum)
+ {
+ dpb->prevRefFrameNum =
+ (frameNum + dpb->maxFrameNum - 1) % dpb->maxFrameNum;
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: FindSmallestPicOrderCnt
+
+ Functional description:
+ Function to find picture with smallest picture order count. This
+ will be the next picture in display order.
+
+ Returns:
+ pointer to the picture, NULL if no pictures to be displayed
+
+------------------------------------------------------------------------------*/
+
+dpbPicture_t* FindSmallestPicOrderCnt(dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ u32 i;
+ i32 picOrderCnt;
+ dpbPicture_t *tmp;
+
+/* Code */
+
+ ASSERT(dpb);
+
+ picOrderCnt = 0x7FFFFFFF;
+ tmp = NULL;
+
+ for (i = 0; i <= dpb->dpbSize; i++)
+ {
+ if (dpb->buffer[i].toBeDisplayed &&
+ (dpb->buffer[i].picOrderCnt < picOrderCnt))
+ {
+ tmp = dpb->buffer + i;
+ picOrderCnt = dpb->buffer[i].picOrderCnt;
+ }
+ }
+
+ return(tmp);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: OutputPicture
+
+ Functional description:
+ Function to put next display order picture into the output buffer.
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK no pictures to display
+
+------------------------------------------------------------------------------*/
+
+u32 OutputPicture(dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ dpbPicture_t *tmp;
+
+/* Code */
+
+ ASSERT(dpb);
+
+ if (dpb->noReordering)
+ return(HANTRO_NOK);
+
+ tmp = FindSmallestPicOrderCnt(dpb);
+
+ /* no pictures to be displayed */
+ if (tmp == NULL)
+ return(HANTRO_NOK);
+
+ dpb->outBuf[dpb->numOut].data = tmp->data;
+ dpb->outBuf[dpb->numOut].isIdr = tmp->isIdr;
+ dpb->outBuf[dpb->numOut].picId = tmp->picId;
+ dpb->outBuf[dpb->numOut].numErrMbs = tmp->numErrMbs;
+ dpb->numOut++;
+
+ tmp->toBeDisplayed = HANTRO_FALSE;
+ if (!IS_REFERENCE(*tmp))
+ {
+ dpb->fullness--;
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdDpbOutputPicture
+
+ Functional description:
+ Function to get next display order picture from the output buffer.
+
+ Return:
+ pointer to output picture structure, NULL if no pictures to
+ display
+
+------------------------------------------------------------------------------*/
+
+dpbOutPicture_t* h264bsdDpbOutputPicture(dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(dpb);
+
+ if (dpb->outIndex < dpb->numOut)
+ return(dpb->outBuf + dpb->outIndex++);
+ else
+ return(NULL);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdFlushDpb
+
+ Functional description:
+ Function to flush the DPB. Function puts all pictures needed for
+ display into the output buffer. This function shall be called in
+ the end of the stream to obtain pictures buffered for display
+ re-ordering purposes.
+
+------------------------------------------------------------------------------*/
+
+void h264bsdFlushDpb(dpbStorage_t *dpb)
+{
+
+ /* don't do anything if buffer not reserved */
+ if (dpb->buffer)
+ {
+ dpb->flushed = 1;
+ /* output all pictures */
+ while (OutputPicture(dpb) == HANTRO_OK)
+ ;
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdFreeDpb
+
+ Functional description:
+ Function to free memories reserved for the DPB.
+
+------------------------------------------------------------------------------*/
+
+void h264bsdFreeDpb(dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ u32 i;
+
+/* Code */
+
+ ASSERT(dpb);
+
+ if (dpb->buffer)
+ {
+ for (i = 0; i < dpb->dpbSize+1; i++)
+ {
+ FREE(dpb->buffer[i].pAllocatedData);
+ }
+ }
+ FREE(dpb->buffer);
+ FREE(dpb->list);
+ FREE(dpb->outBuf);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: ShellSort
+
+ Functional description:
+ Sort pictures in the buffer. Function implements Shell's method,
+ i.e. diminishing increment sort. See e.g. "Numerical Recipes in C"
+ for more information.
+
+------------------------------------------------------------------------------*/
+
+static void ShellSort(dpbPicture_t *pPic, u32 num)
+{
+
+ u32 i, j;
+ u32 step;
+ dpbPicture_t tmpPic;
+
+ step = 7;
+
+ while (step)
+ {
+ for (i = step; i < num; i++)
+ {
+ tmpPic = pPic[i];
+ j = i;
+ while (j >= step && ComparePictures(pPic + j - step, &tmpPic) > 0)
+ {
+ pPic[j] = pPic[j-step];
+ j -= step;
+ }
+ pPic[j] = tmpPic;
+ }
+ step >>= 1;
+ }
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.h
new file mode 100755
index 0000000..0e25084
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_dpb.h
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_DPB_H
+#define H264SWDEC_DPB_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_slice_header.h"
+#include "h264bsd_image.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/* enumeration to represent status of buffered image */
+typedef enum {
+ UNUSED = 0,
+ NON_EXISTING,
+ SHORT_TERM,
+ LONG_TERM
+} dpbPictureStatus_e;
+
+/* structure to represent a buffered picture */
+typedef struct {
+ u8 *data; /* 16-byte aligned pointer of pAllocatedData */
+ u8 *pAllocatedData; /* allocated picture pointer; (size + 15) bytes */
+ i32 picNum;
+ u32 frameNum;
+ i32 picOrderCnt;
+ dpbPictureStatus_e status;
+ u32 toBeDisplayed;
+ u32 picId;
+ u32 numErrMbs;
+ u32 isIdr;
+} dpbPicture_t;
+
+/* structure to represent display image output from the buffer */
+typedef struct {
+ u8 *data;
+ u32 picId;
+ u32 numErrMbs;
+ u32 isIdr;
+} dpbOutPicture_t;
+
+/* structure to represent DPB */
+typedef struct {
+ dpbPicture_t *buffer;
+ dpbPicture_t **list;
+ dpbPicture_t *currentOut;
+ dpbOutPicture_t *outBuf;
+ u32 numOut;
+ u32 outIndex;
+ u32 maxRefFrames;
+ u32 dpbSize;
+ u32 maxFrameNum;
+ u32 maxLongTermFrameIdx;
+ u32 numRefFrames;
+ u32 fullness;
+ u32 prevRefFrameNum;
+ u32 lastContainsMmco5;
+ u32 noReordering;
+ u32 flushed;
+} dpbStorage_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdInitDpb(
+ dpbStorage_t *dpb,
+ u32 picSizeInMbs,
+ u32 dpbSize,
+ u32 numRefFrames,
+ u32 maxFrameNum,
+ u32 noReordering);
+
+u32 h264bsdResetDpb(
+ dpbStorage_t *dpb,
+ u32 picSizeInMbs,
+ u32 dpbSize,
+ u32 numRefFrames,
+ u32 maxFrameNum,
+ u32 noReordering);
+
+void h264bsdInitRefPicList(dpbStorage_t *dpb);
+
+u8* h264bsdAllocateDpbImage(dpbStorage_t *dpb);
+
+u8* h264bsdGetRefPicData(dpbStorage_t *dpb, u32 index);
+
+u32 h264bsdReorderRefPicList(
+ dpbStorage_t *dpb,
+ refPicListReordering_t *order,
+ u32 currFrameNum,
+ u32 numRefIdxActive);
+
+u32 h264bsdMarkDecRefPic(
+ dpbStorage_t *dpb,
+ decRefPicMarking_t *mark,
+ image_t *image,
+ u32 frameNum,
+ i32 picOrderCnt,
+ u32 isIdr,
+ u32 picId,
+ u32 numErrMbs);
+
+u32 h264bsdCheckGapsInFrameNum(dpbStorage_t *dpb, u32 frameNum, u32 isRefPic,
+ u32 gapsAllowed);
+
+dpbOutPicture_t* h264bsdDpbOutputPicture(dpbStorage_t *dpb);
+
+void h264bsdFlushDpb(dpbStorage_t *dpb);
+
+void h264bsdFreeDpb(dpbStorage_t *dpb);
+
+#endif /* #ifdef H264SWDEC_DPB_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.c
new file mode 100755
index 0000000..7b92870
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.c
@@ -0,0 +1,345 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdWriteMacroblock
+ h264bsdWriteOutputBlocks
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_image.h"
+#include "h264bsd_util.h"
+#include "h264bsd_neighbour.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/* x- and y-coordinates for each block, defined in h264bsd_intra_prediction.c */
+extern const u32 h264bsdBlockX[];
+extern const u32 h264bsdBlockY[];
+
+/* clipping table, defined in h264bsd_intra_prediction.c */
+extern const u8 h264bsdClip[];
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdWriteMacroblock
+
+ Functional description:
+ Write one macroblock into the image. Both luma and chroma
+ components will be written at the same time.
+
+ Inputs:
+ data pointer to macroblock data to be written, 256 values for
+ luma followed by 64 values for both chroma components
+
+ Outputs:
+ image pointer to the image where the macroblock will be written
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+#ifndef H264DEC_NEON
+void h264bsdWriteMacroblock(image_t *image, u8 *data)
+{
+
+/* Variables */
+
+ u32 i;
+ u32 width;
+ u32 *lum, *cb, *cr;
+ u32 *ptr;
+ u32 tmp1, tmp2;
+
+/* Code */
+
+ ASSERT(image);
+ ASSERT(data);
+ ASSERT(!((u32)data&0x3));
+
+ width = image->width;
+
+ /*lint -save -e826 lum, cb and cr used to copy 4 bytes at the time, disable
+ * "area too small" info message */
+ lum = (u32*)image->luma;
+ cb = (u32*)image->cb;
+ cr = (u32*)image->cr;
+ ASSERT(!((u32)lum&0x3));
+ ASSERT(!((u32)cb&0x3));
+ ASSERT(!((u32)cr&0x3));
+
+ ptr = (u32*)data;
+
+ width *= 4;
+ for (i = 16; i ; i--)
+ {
+ tmp1 = *ptr++;
+ tmp2 = *ptr++;
+ *lum++ = tmp1;
+ *lum++ = tmp2;
+ tmp1 = *ptr++;
+ tmp2 = *ptr++;
+ *lum++ = tmp1;
+ *lum++ = tmp2;
+ lum += width-4;
+ }
+
+ width >>= 1;
+ for (i = 8; i ; i--)
+ {
+ tmp1 = *ptr++;
+ tmp2 = *ptr++;
+ *cb++ = tmp1;
+ *cb++ = tmp2;
+ cb += width-2;
+ }
+
+ for (i = 8; i ; i--)
+ {
+ tmp1 = *ptr++;
+ tmp2 = *ptr++;
+ *cr++ = tmp1;
+ *cr++ = tmp2;
+ cr += width-2;
+ }
+
+}
+#endif
+#ifndef H264DEC_OMXDL
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdWriteOutputBlocks
+
+ Functional description:
+ Write one macroblock into the image. Prediction for the macroblock
+ and the residual are given separately and will be combined while
+ writing the data to the image
+
+ Inputs:
+ data pointer to macroblock prediction data, 256 values for
+ luma followed by 64 values for both chroma components
+ mbNum number of the macroblock
+ residual pointer to residual data, 16 16-element arrays for luma
+ followed by 4 16-element arrays for both chroma
+ components
+
+ Outputs:
+ image pointer to the image where the data will be written
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void h264bsdWriteOutputBlocks(image_t *image, u32 mbNum, u8 *data,
+ i32 residual[][16])
+{
+
+/* Variables */
+
+ u32 i;
+ u32 picWidth, picSize;
+ u8 *lum, *cb, *cr;
+ u8 *imageBlock;
+ u8 *tmp;
+ u32 row, col;
+ u32 block;
+ u32 x, y;
+ i32 *pRes;
+ i32 tmp1, tmp2, tmp3, tmp4;
+ const u8 *clp = h264bsdClip + 512;
+
+/* Code */
+
+ ASSERT(image);
+ ASSERT(data);
+ ASSERT(mbNum < image->width * image->height);
+ ASSERT(!((u32)data&0x3));
+
+ /* Image size in macroblocks */
+ picWidth = image->width;
+ picSize = picWidth * image->height;
+ row = mbNum / picWidth;
+ col = mbNum % picWidth;
+
+ /* Output macroblock position in output picture */
+ lum = (image->data + row * picWidth * 256 + col * 16);
+ cb = (image->data + picSize * 256 + row * picWidth * 64 + col * 8);
+ cr = (cb + picSize * 64);
+
+ picWidth *= 16;
+
+ for (block = 0; block < 16; block++)
+ {
+ x = h264bsdBlockX[block];
+ y = h264bsdBlockY[block];
+
+ pRes = residual[block];
+
+ ASSERT(pRes);
+
+ tmp = data + y*16 + x;
+ imageBlock = lum + y*picWidth + x;
+
+ ASSERT(!((u32)tmp&0x3));
+ ASSERT(!((u32)imageBlock&0x3));
+
+ if (IS_RESIDUAL_EMPTY(pRes))
+ {
+ /*lint -e826 */
+ i32 *in32 = (i32*)tmp;
+ i32 *out32 = (i32*)imageBlock;
+
+ /* Residual is zero => copy prediction block to output */
+ tmp1 = *in32; in32 += 4;
+ tmp2 = *in32; in32 += 4;
+ *out32 = tmp1; out32 += picWidth/4;
+ *out32 = tmp2; out32 += picWidth/4;
+ tmp1 = *in32; in32 += 4;
+ tmp2 = *in32;
+ *out32 = tmp1; out32 += picWidth/4;
+ *out32 = tmp2;
+ }
+ else
+ {
+
+ RANGE_CHECK_ARRAY(pRes, -512, 511, 16);
+
+ /* Calculate image = prediction + residual
+ * Process four pixels in a loop */
+ for (i = 4; i; i--)
+ {
+ tmp1 = tmp[0];
+ tmp2 = *pRes++;
+ tmp3 = tmp[1];
+ tmp1 = clp[tmp1 + tmp2];
+ tmp4 = *pRes++;
+ imageBlock[0] = (u8)tmp1;
+ tmp3 = clp[tmp3 + tmp4];
+ tmp1 = tmp[2];
+ tmp2 = *pRes++;
+ imageBlock[1] = (u8)tmp3;
+ tmp1 = clp[tmp1 + tmp2];
+ tmp3 = tmp[3];
+ tmp4 = *pRes++;
+ imageBlock[2] = (u8)tmp1;
+ tmp3 = clp[tmp3 + tmp4];
+ tmp += 16;
+ imageBlock[3] = (u8)tmp3;
+ imageBlock += picWidth;
+ }
+ }
+
+ }
+
+ picWidth /= 2;
+
+ for (block = 16; block <= 23; block++)
+ {
+ x = h264bsdBlockX[block & 0x3];
+ y = h264bsdBlockY[block & 0x3];
+
+ pRes = residual[block];
+
+ ASSERT(pRes);
+
+ tmp = data + 256;
+ imageBlock = cb;
+
+ if (block >= 20)
+ {
+ imageBlock = cr;
+ tmp += 64;
+ }
+
+ tmp += y*8 + x;
+ imageBlock += y*picWidth + x;
+
+ ASSERT(!((u32)tmp&0x3));
+ ASSERT(!((u32)imageBlock&0x3));
+
+ if (IS_RESIDUAL_EMPTY(pRes))
+ {
+ /*lint -e826 */
+ i32 *in32 = (i32*)tmp;
+ i32 *out32 = (i32*)imageBlock;
+
+ /* Residual is zero => copy prediction block to output */
+ tmp1 = *in32; in32 += 2;
+ tmp2 = *in32; in32 += 2;
+ *out32 = tmp1; out32 += picWidth/4;
+ *out32 = tmp2; out32 += picWidth/4;
+ tmp1 = *in32; in32 += 2;
+ tmp2 = *in32;
+ *out32 = tmp1; out32 += picWidth/4;
+ *out32 = tmp2;
+ }
+ else
+ {
+
+ RANGE_CHECK_ARRAY(pRes, -512, 511, 16);
+
+ for (i = 4; i; i--)
+ {
+ tmp1 = tmp[0];
+ tmp2 = *pRes++;
+ tmp3 = tmp[1];
+ tmp1 = clp[tmp1 + tmp2];
+ tmp4 = *pRes++;
+ imageBlock[0] = (u8)tmp1;
+ tmp3 = clp[tmp3 + tmp4];
+ tmp1 = tmp[2];
+ tmp2 = *pRes++;
+ imageBlock[1] = (u8)tmp3;
+ tmp1 = clp[tmp1 + tmp2];
+ tmp3 = tmp[3];
+ tmp4 = *pRes++;
+ imageBlock[2] = (u8)tmp1;
+ tmp3 = clp[tmp3 + tmp4];
+ tmp += 8;
+ imageBlock[3] = (u8)tmp3;
+ imageBlock += picWidth;
+ }
+ }
+ }
+
+}
+#endif /* H264DEC_OMXDL */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.h
new file mode 100755
index 0000000..ed7c18c
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_image.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_IMAGE_H
+#define H264SWDEC_IMAGE_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+typedef struct
+{
+ u8 *data;
+ u32 width;
+ u32 height;
+ /* current MB's components */
+ u8 *luma;
+ u8 *cb;
+ u8 *cr;
+} image_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+void h264bsdWriteMacroblock(image_t *image, u8 *data);
+
+#ifndef H264DEC_OMXDL
+void h264bsdWriteOutputBlocks(image_t *image, u32 mbNum, u8 *data,
+ i32 residual[][16]);
+#endif
+
+#endif /* #ifdef H264SWDEC_IMAGE_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c
new file mode 100755
index 0000000..2a81c4a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.c
@@ -0,0 +1,1027 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdInterPrediction
+ MvPrediction16x16
+ MvPrediction16x8
+ MvPrediction8x16
+ MvPrediction8x8
+ MvPrediction
+ MedianFilter
+ GetInterNeighbour
+ GetPredictionMv
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_inter_prediction.h"
+#include "h264bsd_neighbour.h"
+#include "h264bsd_util.h"
+#include "h264bsd_reconstruct.h"
+#include "h264bsd_dpb.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+typedef struct
+{
+ u32 available;
+ u32 refIndex;
+ mv_t mv;
+} interNeighbour_t;
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static u32 MvPrediction16x16(mbStorage_t *pMb, mbPred_t *mbPred,
+ dpbStorage_t *dpb);
+static u32 MvPrediction16x8(mbStorage_t *pMb, mbPred_t *mbPred,
+ dpbStorage_t *dpb);
+static u32 MvPrediction8x16(mbStorage_t *pMb, mbPred_t *mbPred,
+ dpbStorage_t *dpb);
+static u32 MvPrediction8x8(mbStorage_t *pMb, subMbPred_t *subMbPred,
+ dpbStorage_t *dpb);
+static u32 MvPrediction(mbStorage_t *pMb, subMbPred_t *subMbPred,
+ u32 mbPartIdx, u32 subMbPartIdx);
+static i32 MedianFilter(i32 a, i32 b, i32 c);
+
+static void GetInterNeighbour(u32 sliceId, mbStorage_t *nMb,
+ interNeighbour_t *n, u32 index);
+static void GetPredictionMv(mv_t *mv, interNeighbour_t *a, u32 refIndex);
+
+static const neighbour_t N_A_SUB_PART[4][4][4] = {
+ { { {MB_A,5}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,5}, {MB_A,7}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,5}, {MB_CURR,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,5}, {MB_CURR,0}, {MB_A,7}, {MB_CURR,2} } },
+
+ { { {MB_CURR,1}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,1}, {MB_CURR,3}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,1}, {MB_CURR,4}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,1}, {MB_CURR,4}, {MB_CURR,3}, {MB_CURR,6} } },
+
+ { { {MB_A,13}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,13}, {MB_A,15}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,13}, {MB_CURR,8}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,13}, {MB_CURR,8}, {MB_A,15}, {MB_CURR,10} } },
+
+ { { {MB_CURR,9}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,9}, {MB_CURR,11}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,9}, {MB_CURR,12}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,9}, {MB_CURR,12}, {MB_CURR,11}, {MB_CURR,14} } } };
+
+static const neighbour_t N_B_SUB_PART[4][4][4] = {
+ { { {MB_B,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,10}, {MB_CURR,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,10}, {MB_B,11}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,10}, {MB_B,11}, {MB_CURR,0}, {MB_CURR,1} } },
+
+ { { {MB_B,14}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,14}, {MB_CURR,4}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,14}, {MB_B,15}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,14}, {MB_B,15}, {MB_CURR,4}, {MB_CURR,5} } },
+
+ { { {MB_CURR,2}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,2}, {MB_CURR,8}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,2}, {MB_CURR,3}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,2}, {MB_CURR,3}, {MB_CURR,8}, {MB_CURR,9} } },
+
+ { { {MB_CURR,6}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,6}, {MB_CURR,12}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,6}, {MB_CURR,7}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,6}, {MB_CURR,7}, {MB_CURR,12}, {MB_CURR,13} } } };
+
+static const neighbour_t N_C_SUB_PART[4][4][4] = {
+ { { {MB_B,14}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,14}, {MB_NA,4}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,11}, {MB_B,14}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_NA,4} } },
+
+ { { {MB_C,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_C,10}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,15}, {MB_C,10}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,15}, {MB_C,10}, {MB_CURR,5}, {MB_NA,0} } },
+
+ { { {MB_CURR,6}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,6}, {MB_NA,12}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,3}, {MB_CURR,6}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_NA,12} } },
+
+ { { {MB_NA,2}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_NA,2}, {MB_NA,8}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,7}, {MB_NA,2}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,7}, {MB_NA,2}, {MB_CURR,13}, {MB_NA,8} } } };
+
+static const neighbour_t N_D_SUB_PART[4][4][4] = {
+ { { {MB_D,15}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_D,15}, {MB_A,5}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_D,15}, {MB_B,10}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_D,15}, {MB_B,10}, {MB_A,5}, {MB_CURR,0} } },
+
+ { { {MB_B,11}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,11}, {MB_CURR,1}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,11}, {MB_B,14}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_CURR,4} } },
+
+ { { {MB_A,7}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,7}, {MB_A,13}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,7}, {MB_CURR,2}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_A,7}, {MB_CURR,2}, {MB_A,13}, {MB_CURR,8} } },
+
+ { { {MB_CURR,3}, {MB_NA,0}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,3}, {MB_CURR,9}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,3}, {MB_CURR,6}, {MB_NA,0}, {MB_NA,0} },
+ { {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_CURR,12} } } };
+
+
+#ifdef H264DEC_OMXDL
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterPrediction
+
+ Functional description:
+ Processes one inter macroblock. Performs motion vector prediction
+ and reconstructs prediction macroblock. Writes the final macroblock
+ (prediction + residual) into the output image (currImage)
+
+ Inputs:
+ pMb pointer to macroblock specific information
+ pMbLayer pointer to current macroblock data from stream
+ dpb pointer to decoded picture buffer
+ mbNum current macroblock number
+ currImage pointer to output image
+ data pointer where predicted macroblock will be stored
+
+ Outputs:
+ pMb structure is updated with current macroblock
+ currImage current macroblock is written into image
+ data prediction is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK error in motion vector prediction
+
+------------------------------------------------------------------------------*/
+u32 h264bsdInterPrediction(mbStorage_t *pMb, macroblockLayer_t *pMbLayer,
+ dpbStorage_t *dpb, u32 mbNum, image_t *currImage, u8 *data)
+{
+
+/* Variables */
+
+ u32 i;
+ u32 x, y;
+ u32 colAndRow;
+ subMbPartMode_e subPartMode;
+ image_t refImage;
+ u8 fillBuff[32*21 + 15 + 32];
+ u8 *pFill;
+ u32 tmp;
+/* Code */
+
+ ASSERT(pMb);
+ ASSERT(h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTER);
+ ASSERT(pMbLayer);
+
+ /* 16-byte alignment */
+ pFill = ALIGN(fillBuff, 16);
+
+ /* set row bits 15:0 */
+ colAndRow = mbNum / currImage->width;
+ /*set col to bits 31:16 */
+ colAndRow += (mbNum - colAndRow * currImage->width) << 16;
+ colAndRow <<= 4;
+
+ refImage.width = currImage->width;
+ refImage.height = currImage->height;
+
+ switch (pMb->mbType)
+ {
+ case P_Skip:
+ case P_L0_16x16:
+ if (MvPrediction16x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ refImage.data = pMb->refAddr[0];
+ tmp = (0<<24) + (0<<16) + (16<<8) + 16;
+ h264bsdPredictSamples(data, pMb->mv, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+
+ case P_L0_L0_16x8:
+ if ( MvPrediction16x8(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ refImage.data = pMb->refAddr[0];
+ tmp = (0<<24) + (0<<16) + (16<<8) + 8;
+ h264bsdPredictSamples(data, pMb->mv, &refImage,
+ colAndRow, tmp, pFill);
+
+ refImage.data = pMb->refAddr[2];
+ tmp = (0<<24) + (8<<16) + (16<<8) + 8;
+ h264bsdPredictSamples(data, pMb->mv+8, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+
+ case P_L0_L0_8x16:
+ if ( MvPrediction8x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ refImage.data = pMb->refAddr[0];
+ tmp = (0<<24) + (0<<16) + (8<<8) + 16;
+ h264bsdPredictSamples(data, pMb->mv, &refImage,
+ colAndRow, tmp, pFill);
+ refImage.data = pMb->refAddr[1];
+ tmp = (8<<24) + (0<<16) + (8<<8) + 16;
+ h264bsdPredictSamples(data, pMb->mv+4, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+
+ default: /* P_8x8 and P_8x8ref0 */
+ if ( MvPrediction8x8(pMb, &pMbLayer->subMbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ for (i = 0; i < 4; i++)
+ {
+ refImage.data = pMb->refAddr[i];
+ subPartMode =
+ h264bsdSubMbPartMode(pMbLayer->subMbPred.subMbType[i]);
+ x = i & 0x1 ? 8 : 0;
+ y = i < 2 ? 0 : 8;
+ switch (subPartMode)
+ {
+ case MB_SP_8x8:
+ tmp = (x<<24) + (y<<16) + (8<<8) + 8;
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+
+ case MB_SP_8x4:
+ tmp = (x<<24) + (y<<16) + (8<<8) + 4;
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ colAndRow, tmp, pFill);
+ tmp = (x<<24) + ((y+4)<<16) + (8<<8) + 4;
+ h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+
+ case MB_SP_4x8:
+ tmp = (x<<24) + (y<<16) + (4<<8) + 8;
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ colAndRow, tmp, pFill);
+ tmp = ((x+4)<<24) + (y<<16) + (4<<8) + 8;
+ h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+
+ default:
+ tmp = (x<<24) + (y<<16) + (4<<8) + 4;
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ colAndRow, tmp, pFill);
+ tmp = ((x+4)<<24) + (y<<16) + (4<<8) + 4;
+ h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
+ colAndRow, tmp, pFill);
+ tmp = (x<<24) + ((y+4)<<16) + (4<<8) + 4;
+ h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
+ colAndRow, tmp, pFill);
+ tmp = ((x+4)<<24) + ((y+4)<<16) + (4<<8) + 4;
+ h264bsdPredictSamples(data, pMb->mv+4*i+3, &refImage,
+ colAndRow, tmp, pFill);
+ break;
+ }
+ }
+ break;
+ }
+
+ /* if decoded flag > 1 -> mb has already been successfully decoded and
+ * written to output -> do not write again */
+ if (pMb->decoded > 1)
+ return HANTRO_OK;
+
+ return(HANTRO_OK);
+}
+
+#else /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterPrediction
+
+ Functional description:
+ Processes one inter macroblock. Performs motion vector prediction
+ and reconstructs prediction macroblock. Writes the final macroblock
+ (prediction + residual) into the output image (currImage)
+
+ Inputs:
+ pMb pointer to macroblock specific information
+ pMbLayer pointer to current macroblock data from stream
+ dpb pointer to decoded picture buffer
+ mbNum current macroblock number
+ currImage pointer to output image
+ data pointer where predicted macroblock will be stored
+
+ Outputs:
+ pMb structure is updated with current macroblock
+ currImage current macroblock is written into image
+ data prediction is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK error in motion vector prediction
+
+------------------------------------------------------------------------------*/
+u32 h264bsdInterPrediction(mbStorage_t *pMb, macroblockLayer_t *pMbLayer,
+ dpbStorage_t *dpb, u32 mbNum, image_t *currImage, u8 *data)
+{
+
+/* Variables */
+
+ u32 i;
+ u32 x, y;
+ u32 row, col;
+ subMbPartMode_e subPartMode;
+ image_t refImage;
+
+/* Code */
+
+ ASSERT(pMb);
+ ASSERT(h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTER);
+ ASSERT(pMbLayer);
+
+ row = mbNum / currImage->width;
+ col = mbNum - row * currImage->width;
+ row *= 16;
+ col *= 16;
+
+ refImage.width = currImage->width;
+ refImage.height = currImage->height;
+
+ switch (pMb->mbType)
+ {
+ case P_Skip:
+ case P_L0_16x16:
+ if (MvPrediction16x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ refImage.data = pMb->refAddr[0];
+ h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0,
+ 16, 16);
+ break;
+
+ case P_L0_L0_16x8:
+ if ( MvPrediction16x8(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ refImage.data = pMb->refAddr[0];
+ h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0,
+ 16, 8);
+ refImage.data = pMb->refAddr[2];
+ h264bsdPredictSamples(data, pMb->mv+8, &refImage, col, row, 0, 8,
+ 16, 8);
+ break;
+
+ case P_L0_L0_8x16:
+ if ( MvPrediction8x16(pMb, &pMbLayer->mbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ refImage.data = pMb->refAddr[0];
+ h264bsdPredictSamples(data, pMb->mv, &refImage, col, row, 0, 0,
+ 8, 16);
+ refImage.data = pMb->refAddr[1];
+ h264bsdPredictSamples(data, pMb->mv+4, &refImage, col, row, 8, 0,
+ 8, 16);
+ break;
+
+ default: /* P_8x8 and P_8x8ref0 */
+ if ( MvPrediction8x8(pMb, &pMbLayer->subMbPred, dpb) != HANTRO_OK)
+ return(HANTRO_NOK);
+ for (i = 0; i < 4; i++)
+ {
+ refImage.data = pMb->refAddr[i];
+ subPartMode =
+ h264bsdSubMbPartMode(pMbLayer->subMbPred.subMbType[i]);
+ x = i & 0x1 ? 8 : 0;
+ y = i < 2 ? 0 : 8;
+ switch (subPartMode)
+ {
+ case MB_SP_8x8:
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ col, row, x, y, 8, 8);
+ break;
+
+ case MB_SP_8x4:
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ col, row, x, y, 8, 4);
+ h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
+ col, row, x, y+4, 8, 4);
+ break;
+
+ case MB_SP_4x8:
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ col, row, x, y, 4, 8);
+ h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
+ col, row, x+4, y, 4, 8);
+ break;
+
+ default:
+ h264bsdPredictSamples(data, pMb->mv+4*i, &refImage,
+ col, row, x, y, 4, 4);
+ h264bsdPredictSamples(data, pMb->mv+4*i+1, &refImage,
+ col, row, x+4, y, 4, 4);
+ h264bsdPredictSamples(data, pMb->mv+4*i+2, &refImage,
+ col, row, x, y+4, 4, 4);
+ h264bsdPredictSamples(data, pMb->mv+4*i+3, &refImage,
+ col, row, x+4, y+4, 4, 4);
+ break;
+ }
+ }
+ break;
+ }
+
+ /* if decoded flag > 1 -> mb has already been successfully decoded and
+ * written to output -> do not write again */
+ if (pMb->decoded > 1)
+ return HANTRO_OK;
+
+ if (pMb->mbType != P_Skip)
+ {
+ h264bsdWriteOutputBlocks(currImage, mbNum, data,
+ pMbLayer->residual.level);
+ }
+ else
+ {
+ h264bsdWriteMacroblock(currImage, data);
+ }
+
+ return(HANTRO_OK);
+}
+#endif /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+
+ Function: MvPrediction16x16
+
+ Functional description:
+ Motion vector prediction for 16x16 partition mode
+
+------------------------------------------------------------------------------*/
+
+u32 MvPrediction16x16(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ mv_t mv;
+ mv_t mvPred;
+ interNeighbour_t a[3]; /* A, B, C */
+ u32 refIndex;
+ u8 *tmp;
+ u32 *tmpMv1, *tmpMv2;
+
+/* Code */
+
+ refIndex = mbPred->refIdxL0[0];
+
+ GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5);
+ GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10);
+ /*lint --e(740) Unusual pointer cast (incompatible indirect types) */
+ tmpMv1 = (u32*)(&a[0].mv); /* we test just that both MVs are zero */
+ /*lint --e(740) */
+ tmpMv2 = (u32*)(&a[1].mv); /* i.e. a[0].mv.hor == 0 && a[0].mv.ver == 0 */
+ if (pMb->mbType == P_Skip &&
+ (!a[0].available || !a[1].available ||
+ ( a[0].refIndex == 0 && ((u32)(*tmpMv1) == 0) ) ||
+ ( a[1].refIndex == 0 && ((u32)(*tmpMv2) == 0) )))
+ {
+ mv.hor = mv.ver = 0;
+ }
+ else
+ {
+ mv = mbPred->mvdL0[0];
+ GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10);
+ if (!a[2].available)
+ {
+ GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15);
+ }
+
+ GetPredictionMv(&mvPred, a, refIndex);
+
+ mv.hor += mvPred.hor;
+ mv.ver += mvPred.ver;
+
+ /* horizontal motion vector range [-2048, 2047.75] */
+ if ((u32)(i32)(mv.hor+8192) >= (16384))
+ return(HANTRO_NOK);
+
+ /* vertical motion vector range [-512, 511.75]
+ * (smaller for low levels) */
+ if ((u32)(i32)(mv.ver+2048) >= (4096))
+ return(HANTRO_NOK);
+ }
+
+ tmp = h264bsdGetRefPicData(dpb, refIndex);
+ if (tmp == NULL)
+ return(HANTRO_NOK);
+
+ pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] =
+ pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] =
+ pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] =
+ pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv;
+
+ pMb->refPic[0] = refIndex;
+ pMb->refPic[1] = refIndex;
+ pMb->refPic[2] = refIndex;
+ pMb->refPic[3] = refIndex;
+ pMb->refAddr[0] = tmp;
+ pMb->refAddr[1] = tmp;
+ pMb->refAddr[2] = tmp;
+ pMb->refAddr[3] = tmp;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: MvPrediction16x8
+
+ Functional description:
+ Motion vector prediction for 16x8 partition mode
+
+------------------------------------------------------------------------------*/
+
+u32 MvPrediction16x8(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ mv_t mv;
+ mv_t mvPred;
+ interNeighbour_t a[3]; /* A, B, C */
+ u32 refIndex;
+ u8 *tmp;
+
+/* Code */
+
+ mv = mbPred->mvdL0[0];
+ refIndex = mbPred->refIdxL0[0];
+
+ GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10);
+
+ if (a[1].refIndex == refIndex)
+ mvPred = a[1].mv;
+ else
+ {
+ GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5);
+ GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10);
+ if (!a[2].available)
+ {
+ GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15);
+ }
+
+ GetPredictionMv(&mvPred, a, refIndex);
+
+ }
+ mv.hor += mvPred.hor;
+ mv.ver += mvPred.ver;
+
+ /* horizontal motion vector range [-2048, 2047.75] */
+ if ((u32)(i32)(mv.hor+8192) >= (16384))
+ return(HANTRO_NOK);
+
+ /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
+ if ((u32)(i32)(mv.ver+2048) >= (4096))
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetRefPicData(dpb, refIndex);
+ if (tmp == NULL)
+ return(HANTRO_NOK);
+
+ pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] =
+ pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] = mv;
+ pMb->refPic[0] = refIndex;
+ pMb->refPic[1] = refIndex;
+ pMb->refAddr[0] = tmp;
+ pMb->refAddr[1] = tmp;
+
+ mv = mbPred->mvdL0[1];
+ refIndex = mbPred->refIdxL0[1];
+
+ GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 13);
+ if (a[0].refIndex == refIndex)
+ mvPred = a[0].mv;
+ else
+ {
+ a[1].available = HANTRO_TRUE;
+ a[1].refIndex = pMb->refPic[0];
+ a[1].mv = pMb->mv[0];
+
+ /* c is not available */
+ GetInterNeighbour(pMb->sliceId, pMb->mbA, a+2, 7);
+
+ GetPredictionMv(&mvPred, a, refIndex);
+
+ }
+ mv.hor += mvPred.hor;
+ mv.ver += mvPred.ver;
+
+ /* horizontal motion vector range [-2048, 2047.75] */
+ if ((u32)(i32)(mv.hor+8192) >= (16384))
+ return(HANTRO_NOK);
+
+ /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
+ if ((u32)(i32)(mv.ver+2048) >= (4096))
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetRefPicData(dpb, refIndex);
+ if (tmp == NULL)
+ return(HANTRO_NOK);
+
+ pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] =
+ pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv;
+ pMb->refPic[2] = refIndex;
+ pMb->refPic[3] = refIndex;
+ pMb->refAddr[2] = tmp;
+ pMb->refAddr[3] = tmp;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: MvPrediction8x16
+
+ Functional description:
+ Motion vector prediction for 8x16 partition mode
+
+------------------------------------------------------------------------------*/
+
+u32 MvPrediction8x16(mbStorage_t *pMb, mbPred_t *mbPred, dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ mv_t mv;
+ mv_t mvPred;
+ interNeighbour_t a[3]; /* A, B, C */
+ u32 refIndex;
+ u8 *tmp;
+
+/* Code */
+
+ mv = mbPred->mvdL0[0];
+ refIndex = mbPred->refIdxL0[0];
+
+ GetInterNeighbour(pMb->sliceId, pMb->mbA, a, 5);
+
+ if (a[0].refIndex == refIndex)
+ mvPred = a[0].mv;
+ else
+ {
+ GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 10);
+ GetInterNeighbour(pMb->sliceId, pMb->mbB, a+2, 14);
+ if (!a[2].available)
+ {
+ GetInterNeighbour(pMb->sliceId, pMb->mbD, a+2, 15);
+ }
+
+ GetPredictionMv(&mvPred, a, refIndex);
+
+ }
+ mv.hor += mvPred.hor;
+ mv.ver += mvPred.ver;
+
+ /* horizontal motion vector range [-2048, 2047.75] */
+ if ((u32)(i32)(mv.hor+8192) >= (16384))
+ return(HANTRO_NOK);
+
+ /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
+ if ((u32)(i32)(mv.ver+2048) >= (4096))
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetRefPicData(dpb, refIndex);
+ if (tmp == NULL)
+ return(HANTRO_NOK);
+
+ pMb->mv[0] = pMb->mv[1] = pMb->mv[2] = pMb->mv[3] =
+ pMb->mv[8] = pMb->mv[9] = pMb->mv[10] = pMb->mv[11] = mv;
+ pMb->refPic[0] = refIndex;
+ pMb->refPic[2] = refIndex;
+ pMb->refAddr[0] = tmp;
+ pMb->refAddr[2] = tmp;
+
+ mv = mbPred->mvdL0[1];
+ refIndex = mbPred->refIdxL0[1];
+
+ GetInterNeighbour(pMb->sliceId, pMb->mbC, a+2, 10);
+ if (!a[2].available)
+ {
+ GetInterNeighbour(pMb->sliceId, pMb->mbB, a+2, 11);
+ }
+ if (a[2].refIndex == refIndex)
+ mvPred = a[2].mv;
+ else
+ {
+ a[0].available = HANTRO_TRUE;
+ a[0].refIndex = pMb->refPic[0];
+ a[0].mv = pMb->mv[0];
+
+ GetInterNeighbour(pMb->sliceId, pMb->mbB, a+1, 14);
+
+ GetPredictionMv(&mvPred, a, refIndex);
+
+ }
+ mv.hor += mvPred.hor;
+ mv.ver += mvPred.ver;
+
+ /* horizontal motion vector range [-2048, 2047.75] */
+ if ((u32)(i32)(mv.hor+8192) >= (16384))
+ return(HANTRO_NOK);
+
+ /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
+ if ((u32)(i32)(mv.ver+2048) >= (4096))
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetRefPicData(dpb, refIndex);
+ if (tmp == NULL)
+ return(HANTRO_NOK);
+
+ pMb->mv[4] = pMb->mv[5] = pMb->mv[6] = pMb->mv[7] =
+ pMb->mv[12] = pMb->mv[13] = pMb->mv[14] = pMb->mv[15] = mv;
+ pMb->refPic[1] = refIndex;
+ pMb->refPic[3] = refIndex;
+ pMb->refAddr[1] = tmp;
+ pMb->refAddr[3] = tmp;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: MvPrediction8x8
+
+ Functional description:
+ Motion vector prediction for 8x8 partition mode
+
+------------------------------------------------------------------------------*/
+
+u32 MvPrediction8x8(mbStorage_t *pMb, subMbPred_t *subMbPred, dpbStorage_t *dpb)
+{
+
+/* Variables */
+
+ u32 i, j;
+ u32 numSubMbPart;
+
+/* Code */
+
+ for (i = 0; i < 4; i++)
+ {
+ numSubMbPart = h264bsdNumSubMbPart(subMbPred->subMbType[i]);
+ pMb->refPic[i] = subMbPred->refIdxL0[i];
+ pMb->refAddr[i] = h264bsdGetRefPicData(dpb, subMbPred->refIdxL0[i]);
+ if (pMb->refAddr[i] == NULL)
+ return(HANTRO_NOK);
+ for (j = 0; j < numSubMbPart; j++)
+ {
+ if (MvPrediction(pMb, subMbPred, i, j) != HANTRO_OK)
+ return(HANTRO_NOK);
+ }
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: MvPrediction
+
+ Functional description:
+ Perform motion vector prediction for sub-partition
+
+------------------------------------------------------------------------------*/
+
+u32 MvPrediction(mbStorage_t *pMb, subMbPred_t *subMbPred, u32 mbPartIdx,
+ u32 subMbPartIdx)
+{
+
+/* Variables */
+
+ mv_t mv, mvPred;
+ u32 refIndex;
+ subMbPartMode_e subMbPartMode;
+ const neighbour_t *n;
+ mbStorage_t *nMb;
+ interNeighbour_t a[3]; /* A, B, C */
+
+/* Code */
+
+ mv = subMbPred->mvdL0[mbPartIdx][subMbPartIdx];
+ subMbPartMode = h264bsdSubMbPartMode(subMbPred->subMbType[mbPartIdx]);
+ refIndex = subMbPred->refIdxL0[mbPartIdx];
+
+ n = N_A_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
+ nMb = h264bsdGetNeighbourMb(pMb, n->mb);
+ GetInterNeighbour(pMb->sliceId, nMb, a, n->index);
+
+ n = N_B_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
+ nMb = h264bsdGetNeighbourMb(pMb, n->mb);
+ GetInterNeighbour(pMb->sliceId, nMb, a+1, n->index);
+
+ n = N_C_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
+ nMb = h264bsdGetNeighbourMb(pMb, n->mb);
+ GetInterNeighbour(pMb->sliceId, nMb, a+2, n->index);
+
+ if (!a[2].available)
+ {
+ n = N_D_SUB_PART[mbPartIdx][subMbPartMode]+subMbPartIdx;
+ nMb = h264bsdGetNeighbourMb(pMb, n->mb);
+ GetInterNeighbour(pMb->sliceId, nMb, a+2, n->index);
+ }
+
+ GetPredictionMv(&mvPred, a, refIndex);
+
+ mv.hor += mvPred.hor;
+ mv.ver += mvPred.ver;
+
+ /* horizontal motion vector range [-2048, 2047.75] */
+ if (((u32)(i32)(mv.hor+8192) >= (16384)))
+ return(HANTRO_NOK);
+
+ /* vertical motion vector range [-512, 511.75] (smaller for low levels) */
+ if (((u32)(i32)(mv.ver+2048) >= (4096)))
+ return(HANTRO_NOK);
+
+ switch (subMbPartMode)
+ {
+ case MB_SP_8x8:
+ pMb->mv[4*mbPartIdx] = mv;
+ pMb->mv[4*mbPartIdx + 1] = mv;
+ pMb->mv[4*mbPartIdx + 2] = mv;
+ pMb->mv[4*mbPartIdx + 3] = mv;
+ break;
+
+ case MB_SP_8x4:
+ pMb->mv[4*mbPartIdx + 2*subMbPartIdx] = mv;
+ pMb->mv[4*mbPartIdx + 2*subMbPartIdx + 1] = mv;
+ break;
+
+ case MB_SP_4x8:
+ pMb->mv[4*mbPartIdx + subMbPartIdx] = mv;
+ pMb->mv[4*mbPartIdx + subMbPartIdx + 2] = mv;
+ break;
+
+ case MB_SP_4x4:
+ pMb->mv[4*mbPartIdx + subMbPartIdx] = mv;
+ break;
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: MedianFilter
+
+ Functional description:
+ Median filtering for motion vector prediction
+
+------------------------------------------------------------------------------*/
+
+i32 MedianFilter(i32 a, i32 b, i32 c)
+{
+
+/* Variables */
+
+ i32 max,min,med;
+
+/* Code */
+
+ max = min = med = a;
+ if (b > max)
+ {
+ max = b;
+ }
+ else if (b < min)
+ {
+ min = b;
+ }
+ if (c > max)
+ {
+ med = max;
+ }
+ else if (c < min)
+ {
+ med = min;
+ }
+ else
+ {
+ med = c;
+ }
+
+ return(med);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: GetInterNeighbour
+
+ Functional description:
+ Get availability, reference index and motion vector of a neighbour
+
+------------------------------------------------------------------------------*/
+
+void GetInterNeighbour(u32 sliceId, mbStorage_t *nMb,
+ interNeighbour_t *n, u32 index)
+{
+
+ n->available = HANTRO_FALSE;
+ n->refIndex = 0xFFFFFFFF;
+ n->mv.hor = n->mv.ver = 0;
+
+ if (nMb && (sliceId == nMb->sliceId))
+ {
+ u32 tmp;
+ mv_t tmpMv;
+
+ tmp = nMb->mbType;
+ n->available = HANTRO_TRUE;
+ /* MbPartPredMode "inlined" */
+ if (tmp <= P_8x8ref0)
+ {
+ tmpMv = nMb->mv[index];
+ tmp = nMb->refPic[index>>2];
+ n->refIndex = tmp;
+ n->mv = tmpMv;
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: GetPredictionMv
+
+ Functional description:
+ Compute motion vector predictor based on neighbours A, B and C
+
+------------------------------------------------------------------------------*/
+
+void GetPredictionMv(mv_t *mv, interNeighbour_t *a, u32 refIndex)
+{
+
+ if ( a[1].available || a[2].available || !a[0].available)
+ {
+ u32 isA, isB, isC;
+ isA = (a[0].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE;
+ isB = (a[1].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE;
+ isC = (a[2].refIndex == refIndex) ? HANTRO_TRUE : HANTRO_FALSE;
+
+ if (((u32)isA+(u32)isB+(u32)isC) != 1)
+ {
+ mv->hor = (i16)MedianFilter(a[0].mv.hor, a[1].mv.hor, a[2].mv.hor);
+ mv->ver = (i16)MedianFilter(a[0].mv.ver, a[1].mv.ver, a[2].mv.ver);
+ }
+ else if (isA)
+ *mv = a[0].mv;
+ else if (isB)
+ *mv = a[1].mv;
+ else
+ *mv = a[2].mv;
+ }
+ else
+ {
+ *mv = a[0].mv;
+ }
+
+}
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.h
new file mode 100755
index 0000000..94dee25
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_inter_prediction.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_INTER_PREDICTION_H
+#define H264SWDEC_INTER_PREDICTION_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_image.h"
+#include "h264bsd_macroblock_layer.h"
+#include "h264bsd_dpb.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdInterPrediction(mbStorage_t *pMb, macroblockLayer_t *pMbLayer,
+ dpbStorage_t *dpb, u32 mbNum, image_t *image, u8 *data);
+
+#endif /* #ifdef H264SWDEC_INTER_PREDICTION_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.c
new file mode 100755
index 0000000..15eabfb
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.c
@@ -0,0 +1,1937 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdIntraPrediction
+ h264bsdGetNeighbourPels
+ h264bsdIntra16x16Prediction
+ h264bsdIntra4x4Prediction
+ h264bsdIntraChromaPrediction
+ h264bsdAddResidual
+ Intra16x16VerticalPrediction
+ Intra16x16HorizontalPrediction
+ Intra16x16DcPrediction
+ Intra16x16PlanePrediction
+ IntraChromaDcPrediction
+ IntraChromaHorizontalPrediction
+ IntraChromaVerticalPrediction
+ IntraChromaPlanePrediction
+ Get4x4NeighbourPels
+ Write4x4To16x16
+ Intra4x4VerticalPrediction
+ Intra4x4HorizontalPrediction
+ Intra4x4DcPrediction
+ Intra4x4DiagonalDownLeftPrediction
+ Intra4x4DiagonalDownRightPrediction
+ Intra4x4VerticalRightPrediction
+ Intra4x4HorizontalDownPrediction
+ Intra4x4VerticalLeftPrediction
+ Intra4x4HorizontalUpPrediction
+ DetermineIntra4x4PredMode
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_intra_prediction.h"
+#include "h264bsd_util.h"
+#include "h264bsd_macroblock_layer.h"
+#include "h264bsd_neighbour.h"
+#include "h264bsd_image.h"
+
+#ifdef H264DEC_OMXDL
+#include "omxtypes.h"
+#include "omxVC.h"
+#endif /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/* Switch off the following Lint messages for this file:
+ * Info 702: Shift right of signed quantity (int)
+ */
+/*lint -e702 */
+
+
+/* x- and y-coordinates for each block */
+const u32 h264bsdBlockX[16] =
+ { 0, 4, 0, 4, 8, 12, 8, 12, 0, 4, 0, 4, 8, 12, 8, 12 };
+const u32 h264bsdBlockY[16] =
+ { 0, 0, 4, 4, 0, 0, 4, 4, 8, 8, 12, 12, 8, 8, 12, 12 };
+
+const u8 h264bsdClip[1280] =
+{
+ 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,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,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,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,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,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,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,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,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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 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,35,36,37,38,39,40,41,42,43,44,45,46,47,
+ 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
+ 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
+ 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
+ 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
+};
+
+#ifndef H264DEC_OMXDL
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+static void Get4x4NeighbourPels(u8 *a, u8 *l, u8 *data, u8 *above, u8 *left,
+ u32 blockNum);
+static void Intra16x16VerticalPrediction(u8 *data, u8 *above);
+static void Intra16x16HorizontalPrediction(u8 *data, u8 *left);
+static void Intra16x16DcPrediction(u8 *data, u8 *above, u8 *left,
+ u32 A, u32 B);
+static void Intra16x16PlanePrediction(u8 *data, u8 *above, u8 *left);
+static void IntraChromaDcPrediction(u8 *data, u8 *above, u8 *left,
+ u32 A, u32 B);
+static void IntraChromaHorizontalPrediction(u8 *data, u8 *left);
+static void IntraChromaVerticalPrediction(u8 *data, u8 *above);
+static void IntraChromaPlanePrediction(u8 *data, u8 *above, u8 *left);
+
+static void Intra4x4VerticalPrediction(u8 *data, u8 *above);
+static void Intra4x4HorizontalPrediction(u8 *data, u8 *left);
+static void Intra4x4DcPrediction(u8 *data, u8 *above, u8 *left, u32 A, u32 B);
+static void Intra4x4DiagonalDownLeftPrediction(u8 *data, u8 *above);
+static void Intra4x4DiagonalDownRightPrediction(u8 *data, u8 *above, u8 *left);
+static void Intra4x4VerticalRightPrediction(u8 *data, u8 *above, u8 *left);
+static void Intra4x4HorizontalDownPrediction(u8 *data, u8 *above, u8 *left);
+static void Intra4x4VerticalLeftPrediction(u8 *data, u8 *above);
+static void Intra4x4HorizontalUpPrediction(u8 *data, u8 *left);
+void h264bsdAddResidual(u8 *data, i32 *residual, u32 blockNum);
+
+static void Write4x4To16x16(u8 *data, u8 *data4x4, u32 blockNum);
+#endif /* H264DEC_OMXDL */
+
+static u32 DetermineIntra4x4PredMode(macroblockLayer_t *pMbLayer,
+ u32 available, neighbour_t *nA, neighbour_t *nB, u32 index,
+ mbStorage_t *nMbA, mbStorage_t *nMbB);
+
+
+#ifdef H264DEC_OMXDL
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdIntra16x16Prediction
+
+ Functional description:
+ Perform intra 16x16 prediction mode for luma pixels and add
+ residual into prediction. The resulting luma pixels are
+ stored in macroblock array 'data'.
+
+------------------------------------------------------------------------------*/
+u32 h264bsdIntra16x16Prediction(mbStorage_t *pMb, u8 *data, u8 *ptr,
+ u32 width, u32 constrainedIntraPred)
+{
+
+/* Variables */
+
+ u32 availableA, availableB, availableD;
+ OMXResult omxRes;
+
+/* Code */
+ ASSERT(pMb);
+ ASSERT(data);
+ ASSERT(ptr);
+ ASSERT(h264bsdPredModeIntra16x16(pMb->mbType) < 4);
+
+ availableA = h264bsdIsNeighbourAvailable(pMb, pMb->mbA);
+ if (availableA && constrainedIntraPred &&
+ (h264bsdMbPartPredMode(pMb->mbA->mbType) == PRED_MODE_INTER))
+ availableA = HANTRO_FALSE;
+ availableB = h264bsdIsNeighbourAvailable(pMb, pMb->mbB);
+ if (availableB && constrainedIntraPred &&
+ (h264bsdMbPartPredMode(pMb->mbB->mbType) == PRED_MODE_INTER))
+ availableB = HANTRO_FALSE;
+ availableD = h264bsdIsNeighbourAvailable(pMb, pMb->mbD);
+ if (availableD && constrainedIntraPred &&
+ (h264bsdMbPartPredMode(pMb->mbD->mbType) == PRED_MODE_INTER))
+ availableD = HANTRO_FALSE;
+
+ omxRes = omxVCM4P10_PredictIntra_16x16( (ptr-1),
+ (ptr - width),
+ (ptr - width-1),
+ data,
+ (i32)width,
+ 16,
+ (OMXVCM4P10Intra16x16PredMode)
+ h264bsdPredModeIntra16x16(pMb->mbType),
+ (i32)(availableB + (availableA<<1) +
+ (availableD<<5)) );
+ if (omxRes != OMX_Sts_NoErr)
+ return HANTRO_NOK;
+ else
+ return(HANTRO_OK);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdIntra4x4Prediction
+
+ Functional description:
+ Perform intra 4x4 prediction for luma pixels and add residual
+ into prediction. The resulting luma pixels are stored in
+ macroblock array 'data'. The intra 4x4 prediction mode for each
+ block is stored in 'pMb' structure.
+
+------------------------------------------------------------------------------*/
+u32 h264bsdIntra4x4Prediction(mbStorage_t *pMb, u8 *data,
+ macroblockLayer_t *mbLayer,
+ u8 *ptr, u32 width,
+ u32 constrainedIntraPred, u32 block)
+{
+
+/* Variables */
+ u32 mode;
+ neighbour_t neighbour, neighbourB;
+ mbStorage_t *nMb, *nMb2;
+ u32 availableA, availableB, availableC, availableD;
+
+ OMXResult omxRes;
+ u32 x, y;
+ u8 *l, *a, *al;
+/* Code */
+ ASSERT(pMb);
+ ASSERT(data);
+ ASSERT(mbLayer);
+ ASSERT(ptr);
+ ASSERT(pMb->intra4x4PredMode[block] < 9);
+
+ neighbour = *h264bsdNeighbour4x4BlockA(block);
+ nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb);
+ availableA = h264bsdIsNeighbourAvailable(pMb, nMb);
+ if (availableA && constrainedIntraPred &&
+ ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) )
+ {
+ availableA = HANTRO_FALSE;
+ }
+
+ neighbourB = *h264bsdNeighbour4x4BlockB(block);
+ nMb2 = h264bsdGetNeighbourMb(pMb, neighbourB.mb);
+ availableB = h264bsdIsNeighbourAvailable(pMb, nMb2);
+ if (availableB && constrainedIntraPred &&
+ ( h264bsdMbPartPredMode(nMb2->mbType) == PRED_MODE_INTER) )
+ {
+ availableB = HANTRO_FALSE;
+ }
+
+ mode = DetermineIntra4x4PredMode(mbLayer,
+ (u32)(availableA && availableB),
+ &neighbour, &neighbourB, block, nMb, nMb2);
+ pMb->intra4x4PredMode[block] = (u8)mode;
+
+ neighbour = *h264bsdNeighbour4x4BlockC(block);
+ nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb);
+ availableC = h264bsdIsNeighbourAvailable(pMb, nMb);
+ if (availableC && constrainedIntraPred &&
+ ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) )
+ {
+ availableC = HANTRO_FALSE;
+ }
+
+ neighbour = *h264bsdNeighbour4x4BlockD(block);
+ nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb);
+ availableD = h264bsdIsNeighbourAvailable(pMb, nMb);
+ if (availableD && constrainedIntraPred &&
+ ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) )
+ {
+ availableD = HANTRO_FALSE;
+ }
+
+ x = h264bsdBlockX[block];
+ y = h264bsdBlockY[block];
+
+ if (y == 0)
+ a = ptr - width + x;
+ else
+ a = data-16;
+
+ if (x == 0)
+ l = ptr + y * width -1;
+ else
+ {
+ l = data-1;
+ width = 16;
+ }
+
+ if (x == 0)
+ al = l-width;
+ else
+ al = a-1;
+
+ omxRes = omxVCM4P10_PredictIntra_4x4( l,
+ a,
+ al,
+ data,
+ (i32)width,
+ 16,
+ (OMXVCM4P10Intra4x4PredMode)mode,
+ (i32)(availableB +
+ (availableA<<1) +
+ (availableD<<5) +
+ (availableC<<6)) );
+ if (omxRes != OMX_Sts_NoErr)
+ return HANTRO_NOK;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdIntraChromaPrediction
+
+ Functional description:
+ Perform intra prediction for chroma pixels and add residual
+ into prediction. The resulting chroma pixels are stored in 'data'.
+
+------------------------------------------------------------------------------*/
+u32 h264bsdIntraChromaPrediction(mbStorage_t *pMb, u8 *data, image_t *image,
+ u32 predMode, u32 constrainedIntraPred)
+{
+
+/* Variables */
+
+ u32 availableA, availableB, availableD;
+ OMXResult omxRes;
+ u8 *ptr;
+ u32 width;
+
+/* Code */
+ ASSERT(pMb);
+ ASSERT(data);
+ ASSERT(image);
+ ASSERT(predMode < 4);
+
+ availableA = h264bsdIsNeighbourAvailable(pMb, pMb->mbA);
+ if (availableA && constrainedIntraPred &&
+ (h264bsdMbPartPredMode(pMb->mbA->mbType) == PRED_MODE_INTER))
+ availableA = HANTRO_FALSE;
+ availableB = h264bsdIsNeighbourAvailable(pMb, pMb->mbB);
+ if (availableB && constrainedIntraPred &&
+ (h264bsdMbPartPredMode(pMb->mbB->mbType) == PRED_MODE_INTER))
+ availableB = HANTRO_FALSE;
+ availableD = h264bsdIsNeighbourAvailable(pMb, pMb->mbD);
+ if (availableD && constrainedIntraPred &&
+ (h264bsdMbPartPredMode(pMb->mbD->mbType) == PRED_MODE_INTER))
+ availableD = HANTRO_FALSE;
+
+ ptr = image->cb;
+ width = image->width*8;
+
+ omxRes = omxVCM4P10_PredictIntraChroma_8x8( (ptr-1),
+ (ptr - width),
+ (ptr - width -1),
+ data,
+ (i32)width,
+ 8,
+ (OMXVCM4P10IntraChromaPredMode)
+ predMode,
+ (i32)(availableB +
+ (availableA<<1) +
+ (availableD<<5)) );
+ if (omxRes != OMX_Sts_NoErr)
+ return HANTRO_NOK;
+
+ /* advance pointers */
+ data += 64;
+ ptr = image->cr;
+
+ omxRes = omxVCM4P10_PredictIntraChroma_8x8( (ptr-1),
+ (ptr - width),
+ (ptr - width -1),
+ data,
+ (i32)width,
+ 8,
+ (OMXVCM4P10IntraChromaPredMode)
+ predMode,
+ (i32)(availableB +
+ (availableA<<1) +
+ (availableD<<5)) );
+ if (omxRes != OMX_Sts_NoErr)
+ return HANTRO_NOK;
+
+ return(HANTRO_OK);
+
+}
+
+
+#else /* H264DEC_OMXDL */
+
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdIntraPrediction
+
+ Functional description:
+ Processes one intra macroblock. Performs intra prediction using
+ specified prediction mode. Writes the final macroblock
+ (prediction + residual) into the output image (image)
+
+ Inputs:
+ pMb pointer to macroblock specific information
+ mbLayer pointer to current macroblock data from stream
+ image pointer to output image
+ mbNum current macroblock number
+ constrainedIntraPred flag specifying if neighbouring inter
+ macroblocks are used in intra prediction
+ data pointer where output macroblock will be stored
+
+ Outputs:
+ pMb structure is updated with current macroblock
+ image current macroblock is written into image
+ data current macroblock is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK error in intra prediction
+
+------------------------------------------------------------------------------*/
+u32 h264bsdIntraPrediction(mbStorage_t *pMb, macroblockLayer_t *mbLayer,
+ image_t *image, u32 mbNum, u32 constrainedIntraPred, u8 *data)
+{
+
+/* Variables */
+
+ /* pelAbove and pelLeft contain samples above and left to the current
+ * macroblock. Above array contains also sample above-left to the current
+ * mb as well as 4 samples above-right to the current mb (latter only for
+ * luma) */
+ /* lumD + lumB + lumC + cbD + cbB + crD + crB */
+ u8 pelAbove[1 + 16 + 4 + 1 + 8 + 1 + 8];
+ /* lumA + cbA + crA */
+ u8 pelLeft[16 + 8 + 8];
+ u32 tmp;
+
+/* Code */
+
+ ASSERT(pMb);
+ ASSERT(image);
+ ASSERT(mbNum < image->width * image->height);
+ ASSERT(h264bsdMbPartPredMode(pMb->mbType) != PRED_MODE_INTER);
+
+ h264bsdGetNeighbourPels(image, pelAbove, pelLeft, mbNum);
+
+ if (h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTRA16x16)
+ {
+ tmp = h264bsdIntra16x16Prediction(pMb, data, mbLayer->residual.level,
+ pelAbove, pelLeft, constrainedIntraPred);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+ else
+ {
+ tmp = h264bsdIntra4x4Prediction(pMb, data, mbLayer,
+ pelAbove, pelLeft, constrainedIntraPred);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+
+ tmp = h264bsdIntraChromaPrediction(pMb, data + 256,
+ mbLayer->residual.level+16, pelAbove + 21, pelLeft + 16,
+ mbLayer->mbPred.intraChromaPredMode, constrainedIntraPred);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* if decoded flag > 1 -> mb has already been successfully decoded and
+ * written to output -> do not write again */
+ if (pMb->decoded > 1)
+ return HANTRO_OK;
+
+ h264bsdWriteMacroblock(image, data);
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdGetNeighbourPels
+
+ Functional description:
+ Get pixel values from neighbouring macroblocks into 'above'
+ and 'left' arrays.
+
+------------------------------------------------------------------------------*/
+
+void h264bsdGetNeighbourPels(image_t *image, u8 *above, u8 *left, u32 mbNum)
+{
+
+/* Variables */
+
+ u32 i;
+ u32 width, picSize;
+ u8 *ptr, *tmp;
+ u32 row, col;
+
+/* Code */
+
+ ASSERT(image);
+ ASSERT(above);
+ ASSERT(left);
+ ASSERT(mbNum < image->width * image->height);
+
+ if (!mbNum)
+ return;
+
+ width = image->width;
+ picSize = width * image->height;
+ row = mbNum / width;
+ col = mbNum - row * width;
+
+ width *= 16;
+ ptr = image->data + row * 16 * width + col * 16;
+
+ /* note that luma samples above-right to current macroblock do not make
+ * sense when current mb is the right-most mb in a row. Same applies to
+ * sample above-left if col is zero. However, usage of pels in prediction
+ * is controlled by neighbour availability information in actual prediction
+ * process */
+ if (row)
+ {
+ tmp = ptr - (width + 1);
+ for (i = 21; i--;)
+ *above++ = *tmp++;
+ }
+
+ if (col)
+ {
+ ptr--;
+ for (i = 16; i--; ptr+=width)
+ *left++ = *ptr;
+ }
+
+ width >>= 1;
+ ptr = image->data + picSize * 256 + row * 8 * width + col * 8;
+
+ if (row)
+ {
+ tmp = ptr - (width + 1);
+ for (i = 9; i--;)
+ *above++ = *tmp++;
+ tmp += (picSize * 64) - 9;
+ for (i = 9; i--;)
+ *above++ = *tmp++;
+ }
+
+ if (col)
+ {
+ ptr--;
+ for (i = 8; i--; ptr+=width)
+ *left++ = *ptr;
+ ptr += (picSize * 64) - 8 * width;
+ for (i = 8; i--; ptr+=width)
+ *left++ = *ptr;
+ }
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra16x16Prediction
+
+ Functional description:
+ Perform intra 16x16 prediction mode for luma pixels and add
+ residual into prediction. The resulting luma pixels are
+ stored in macroblock array 'data'.
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdIntra16x16Prediction(mbStorage_t *pMb, u8 *data, i32 residual[][16],
+ u8 *above, u8 *left, u32 constrainedIntraPred)
+{
+
+/* Variables */
+
+ u32 i;
+ u32 availableA, availableB, availableD;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(residual);
+ ASSERT(above);
+ ASSERT(left);
+ ASSERT(h264bsdPredModeIntra16x16(pMb->mbType) < 4);
+
+ availableA = h264bsdIsNeighbourAvailable(pMb, pMb->mbA);
+ if (availableA && constrainedIntraPred &&
+ (h264bsdMbPartPredMode(pMb->mbA->mbType) == PRED_MODE_INTER))
+ availableA = HANTRO_FALSE;
+ availableB = h264bsdIsNeighbourAvailable(pMb, pMb->mbB);
+ if (availableB && constrainedIntraPred &&
+ (h264bsdMbPartPredMode(pMb->mbB->mbType) == PRED_MODE_INTER))
+ availableB = HANTRO_FALSE;
+ availableD = h264bsdIsNeighbourAvailable(pMb, pMb->mbD);
+ if (availableD && constrainedIntraPred &&
+ (h264bsdMbPartPredMode(pMb->mbD->mbType) == PRED_MODE_INTER))
+ availableD = HANTRO_FALSE;
+
+ switch(h264bsdPredModeIntra16x16(pMb->mbType))
+ {
+ case 0: /* Intra_16x16_Vertical */
+ if (!availableB)
+ return(HANTRO_NOK);
+ Intra16x16VerticalPrediction(data, above+1);
+ break;
+
+ case 1: /* Intra_16x16_Horizontal */
+ if (!availableA)
+ return(HANTRO_NOK);
+ Intra16x16HorizontalPrediction(data, left);
+ break;
+
+ case 2: /* Intra_16x16_DC */
+ Intra16x16DcPrediction(data, above+1, left, availableA, availableB);
+ break;
+
+ default: /* case 3: Intra_16x16_Plane */
+ if (!availableA || !availableB || !availableD)
+ return(HANTRO_NOK);
+ Intra16x16PlanePrediction(data, above+1, left);
+ break;
+ }
+ /* add residual */
+ for (i = 0; i < 16; i++)
+ h264bsdAddResidual(data, residual[i], i);
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra4x4Prediction
+
+ Functional description:
+ Perform intra 4x4 prediction for luma pixels and add residual
+ into prediction. The resulting luma pixels are stored in
+ macroblock array 'data'. The intra 4x4 prediction mode for each
+ block is stored in 'pMb' structure.
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdIntra4x4Prediction(mbStorage_t *pMb, u8 *data,
+ macroblockLayer_t *mbLayer, u8 *above,
+ u8 *left, u32 constrainedIntraPred)
+{
+
+/* Variables */
+
+ u32 block;
+ u32 mode;
+ neighbour_t neighbour, neighbourB;
+ mbStorage_t *nMb, *nMb2;
+ u8 a[1 + 4 + 4], l[1 + 4];
+ u32 data4x4[4];
+ u32 availableA, availableB, availableC, availableD;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(mbLayer);
+ ASSERT(above);
+ ASSERT(left);
+
+ for (block = 0; block < 16; block++)
+ {
+
+ ASSERT(pMb->intra4x4PredMode[block] < 9);
+
+ neighbour = *h264bsdNeighbour4x4BlockA(block);
+ nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb);
+ availableA = h264bsdIsNeighbourAvailable(pMb, nMb);
+ if (availableA && constrainedIntraPred &&
+ ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) )
+ {
+ availableA = HANTRO_FALSE;
+ }
+
+ neighbourB = *h264bsdNeighbour4x4BlockB(block);
+ nMb2 = h264bsdGetNeighbourMb(pMb, neighbourB.mb);
+ availableB = h264bsdIsNeighbourAvailable(pMb, nMb2);
+ if (availableB && constrainedIntraPred &&
+ ( h264bsdMbPartPredMode(nMb2->mbType) == PRED_MODE_INTER) )
+ {
+ availableB = HANTRO_FALSE;
+ }
+
+ mode = DetermineIntra4x4PredMode(mbLayer,
+ (u32)(availableA && availableB),
+ &neighbour, &neighbourB, block, nMb, nMb2);
+ pMb->intra4x4PredMode[block] = (u8)mode;
+
+ neighbour = *h264bsdNeighbour4x4BlockC(block);
+ nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb);
+ availableC = h264bsdIsNeighbourAvailable(pMb, nMb);
+ if (availableC && constrainedIntraPred &&
+ ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) )
+ {
+ availableC = HANTRO_FALSE;
+ }
+
+ neighbour = *h264bsdNeighbour4x4BlockD(block);
+ nMb = h264bsdGetNeighbourMb(pMb, neighbour.mb);
+ availableD = h264bsdIsNeighbourAvailable(pMb, nMb);
+ if (availableD && constrainedIntraPred &&
+ ( h264bsdMbPartPredMode(nMb->mbType) == PRED_MODE_INTER) )
+ {
+ availableD = HANTRO_FALSE;
+ }
+
+ Get4x4NeighbourPels(a, l, data, above, left, block);
+
+ switch(mode)
+ {
+ case 0: /* Intra_4x4_Vertical */
+ if (!availableB)
+ return(HANTRO_NOK);
+ Intra4x4VerticalPrediction((u8*)data4x4, a + 1);
+ break;
+ case 1: /* Intra_4x4_Horizontal */
+ if (!availableA)
+ return(HANTRO_NOK);
+ Intra4x4HorizontalPrediction((u8*)data4x4, l + 1);
+ break;
+ case 2: /* Intra_4x4_DC */
+ Intra4x4DcPrediction((u8*)data4x4, a + 1, l + 1,
+ availableA, availableB);
+ break;
+ case 3: /* Intra_4x4_Diagonal_Down_Left */
+ if (!availableB)
+ return(HANTRO_NOK);
+ if (!availableC)
+ {
+ a[5] = a[6] = a[7] = a[8] = a[4];
+ }
+ Intra4x4DiagonalDownLeftPrediction((u8*)data4x4, a + 1);
+ break;
+ case 4: /* Intra_4x4_Diagonal_Down_Right */
+ if (!availableA || !availableB || !availableD)
+ return(HANTRO_NOK);
+ Intra4x4DiagonalDownRightPrediction((u8*)data4x4, a + 1, l + 1);
+ break;
+ case 5: /* Intra_4x4_Vertical_Right */
+ if (!availableA || !availableB || !availableD)
+ return(HANTRO_NOK);
+ Intra4x4VerticalRightPrediction((u8*)data4x4, a + 1, l + 1);
+ break;
+ case 6: /* Intra_4x4_Horizontal_Down */
+ if (!availableA || !availableB || !availableD)
+ return(HANTRO_NOK);
+ Intra4x4HorizontalDownPrediction((u8*)data4x4, a + 1, l + 1);
+ break;
+ case 7: /* Intra_4x4_Vertical_Left */
+ if (!availableB)
+ return(HANTRO_NOK);
+ if (!availableC)
+ {
+ a[5] = a[6] = a[7] = a[8] = a[4];
+ }
+ Intra4x4VerticalLeftPrediction((u8*)data4x4, a + 1);
+ break;
+ default: /* case 8 Intra_4x4_Horizontal_Up */
+ if (!availableA)
+ return(HANTRO_NOK);
+ Intra4x4HorizontalUpPrediction((u8*)data4x4, l + 1);
+ break;
+ }
+
+ Write4x4To16x16(data, (u8*)data4x4, block);
+ h264bsdAddResidual(data, mbLayer->residual.level[block], block);
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: IntraChromaPrediction
+
+ Functional description:
+ Perform intra prediction for chroma pixels and add residual
+ into prediction. The resulting chroma pixels are stored in 'data'.
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdIntraChromaPrediction(mbStorage_t *pMb, u8 *data, i32 residual[][16],
+ u8 *above, u8 *left, u32 predMode, u32 constrainedIntraPred)
+{
+
+/* Variables */
+
+ u32 i, comp, block;
+ u32 availableA, availableB, availableD;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(residual);
+ ASSERT(above);
+ ASSERT(left);
+ ASSERT(predMode < 4);
+
+ availableA = h264bsdIsNeighbourAvailable(pMb, pMb->mbA);
+ if (availableA && constrainedIntraPred &&
+ (h264bsdMbPartPredMode(pMb->mbA->mbType) == PRED_MODE_INTER))
+ availableA = HANTRO_FALSE;
+ availableB = h264bsdIsNeighbourAvailable(pMb, pMb->mbB);
+ if (availableB && constrainedIntraPred &&
+ (h264bsdMbPartPredMode(pMb->mbB->mbType) == PRED_MODE_INTER))
+ availableB = HANTRO_FALSE;
+ availableD = h264bsdIsNeighbourAvailable(pMb, pMb->mbD);
+ if (availableD && constrainedIntraPred &&
+ (h264bsdMbPartPredMode(pMb->mbD->mbType) == PRED_MODE_INTER))
+ availableD = HANTRO_FALSE;
+
+ for (comp = 0, block = 16; comp < 2; comp++)
+ {
+ switch(predMode)
+ {
+ case 0: /* Intra_Chroma_DC */
+ IntraChromaDcPrediction(data, above+1, left, availableA,
+ availableB);
+ break;
+
+ case 1: /* Intra_Chroma_Horizontal */
+ if (!availableA)
+ return(HANTRO_NOK);
+ IntraChromaHorizontalPrediction(data, left);
+ break;
+
+ case 2: /* Intra_Chroma_Vertical */
+ if (!availableB)
+ return(HANTRO_NOK);
+ IntraChromaVerticalPrediction(data, above+1);
+
+ break;
+
+ default: /* case 3: Intra_Chroma_Plane */
+ if (!availableA || !availableB || !availableD)
+ return(HANTRO_NOK);
+ IntraChromaPlanePrediction(data, above+1, left);
+ break;
+ }
+ for (i = 0; i < 4; i++, block++)
+ h264bsdAddResidual(data, residual[i], block);
+
+ /* advance pointers */
+ data += 64;
+ above += 9;
+ left += 8;
+ residual += 4;
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdAddResidual
+
+ Functional description:
+ Add residual of a block into prediction in macroblock array 'data'.
+ The result (residual + prediction) is stored in 'data'.
+
+------------------------------------------------------------------------------*/
+#ifndef H264DEC_OMXDL
+void h264bsdAddResidual(u8 *data, i32 *residual, u32 blockNum)
+{
+
+/* Variables */
+
+ u32 i;
+ u32 x, y;
+ u32 width;
+ i32 tmp1, tmp2, tmp3, tmp4;
+ u8 *tmp;
+ const u8 *clp = h264bsdClip + 512;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(residual);
+ ASSERT(blockNum < 16 + 4 + 4);
+
+ if (IS_RESIDUAL_EMPTY(residual))
+ return;
+
+ RANGE_CHECK_ARRAY(residual, -512, 511, 16);
+
+ if (blockNum < 16)
+ {
+ width = 16;
+ x = h264bsdBlockX[blockNum];
+ y = h264bsdBlockY[blockNum];
+ }
+ else
+ {
+ width = 8;
+ x = h264bsdBlockX[blockNum & 0x3];
+ y = h264bsdBlockY[blockNum & 0x3];
+ }
+
+ tmp = data + y*width + x;
+ for (i = 4; i; i--)
+ {
+ tmp1 = *residual++;
+ tmp2 = tmp[0];
+ tmp3 = *residual++;
+ tmp4 = tmp[1];
+
+ tmp[0] = clp[tmp1 + tmp2];
+
+ tmp1 = *residual++;
+ tmp2 = tmp[2];
+
+ tmp[1] = clp[tmp3 + tmp4];
+
+ tmp3 = *residual++;
+ tmp4 = tmp[3];
+
+ tmp1 = clp[tmp1 + tmp2];
+ tmp3 = clp[tmp3 + tmp4];
+ tmp[2] = (u8)tmp1;
+ tmp[3] = (u8)tmp3;
+
+ tmp += width;
+ }
+
+}
+#endif
+/*------------------------------------------------------------------------------
+
+ Function: Intra16x16VerticalPrediction
+
+ Functional description:
+ Perform intra 16x16 vertical prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void Intra16x16VerticalPrediction(u8 *data, u8 *above)
+{
+
+/* Variables */
+
+ u32 i, j;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(above);
+
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+ *data++ = above[j];
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra16x16HorizontalPrediction
+
+ Functional description:
+ Perform intra 16x16 horizontal prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void Intra16x16HorizontalPrediction(u8 *data, u8 *left)
+{
+
+/* Variables */
+
+ u32 i, j;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(left);
+
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+ *data++ = left[i];
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra16x16DcPrediction
+
+ Functional description:
+ Perform intra 16x16 DC prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void Intra16x16DcPrediction(u8 *data, u8 *above, u8 *left, u32 availableA,
+ u32 availableB)
+{
+
+/* Variables */
+
+ u32 i, tmp;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(above);
+ ASSERT(left);
+
+ if (availableA && availableB)
+ {
+ for (i = 0, tmp = 0; i < 16; i++)
+ tmp += above[i] + left[i];
+ tmp = (tmp + 16) >> 5;
+ }
+ else if (availableA)
+ {
+ for (i = 0, tmp = 0; i < 16; i++)
+ tmp += left[i];
+ tmp = (tmp + 8) >> 4;
+ }
+ else if (availableB)
+ {
+ for (i = 0, tmp = 0; i < 16; i++)
+ tmp += above[i];
+ tmp = (tmp + 8) >> 4;
+ }
+ /* neither A nor B available */
+ else
+ {
+ tmp = 128;
+ }
+ for (i = 0; i < 256; i++)
+ data[i] = (u8)tmp;
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra16x16PlanePrediction
+
+ Functional description:
+ Perform intra 16x16 plane prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void Intra16x16PlanePrediction(u8 *data, u8 *above, u8 *left)
+{
+
+/* Variables */
+
+ u32 i, j;
+ i32 a, b, c;
+ i32 tmp;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(above);
+ ASSERT(left);
+
+ a = 16 * (above[15] + left[15]);
+
+ for (i = 0, b = 0; i < 8; i++)
+ b += ((i32)i + 1) * (above[8+i] - above[6-i]);
+ b = (5 * b + 32) >> 6;
+
+ for (i = 0, c = 0; i < 7; i++)
+ c += ((i32)i + 1) * (left[8+i] - left[6-i]);
+ /* p[-1,-1] has to be accessed through above pointer */
+ c += ((i32)i + 1) * (left[8+i] - above[-1]);
+ c = (5 * c + 32) >> 6;
+
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+ tmp = (a + b * ((i32)j - 7) + c * ((i32)i - 7) + 16) >> 5;
+ data[i*16+j] = (u8)CLIP1(tmp);
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: IntraChromaDcPrediction
+
+ Functional description:
+ Perform intra chroma DC prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void IntraChromaDcPrediction(u8 *data, u8 *above, u8 *left, u32 availableA,
+ u32 availableB)
+{
+
+/* Variables */
+
+ u32 i;
+ u32 tmp1, tmp2;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(above);
+ ASSERT(left);
+
+ /* y = 0..3 */
+ if (availableA && availableB)
+ {
+ tmp1 = above[0] + above[1] + above[2] + above[3] +
+ left[0] + left[1] + left[2] + left[3];
+ tmp1 = (tmp1 + 4) >> 3;
+ tmp2 = (above[4] + above[5] + above[6] + above[7] + 2) >> 2;
+ }
+ else if (availableB)
+ {
+ tmp1 = (above[0] + above[1] + above[2] + above[3] + 2) >> 2;
+ tmp2 = (above[4] + above[5] + above[6] + above[7] + 2) >> 2;
+ }
+ else if (availableA)
+ {
+ tmp1 = (left[0] + left[1] + left[2] + left[3] + 2) >> 2;
+ tmp2 = tmp1;
+ }
+ /* neither A nor B available */
+ else
+ {
+ tmp1 = tmp2 = 128;
+ }
+
+ ASSERT(tmp1 < 256 && tmp2 < 256);
+ for (i = 4; i--;)
+ {
+ *data++ = (u8)tmp1;
+ *data++ = (u8)tmp1;
+ *data++ = (u8)tmp1;
+ *data++ = (u8)tmp1;
+ *data++ = (u8)tmp2;
+ *data++ = (u8)tmp2;
+ *data++ = (u8)tmp2;
+ *data++ = (u8)tmp2;
+ }
+
+ /* y = 4...7 */
+ if (availableA)
+ {
+ tmp1 = (left[4] + left[5] + left[6] + left[7] + 2) >> 2;
+ if (availableB)
+ {
+ tmp2 = above[4] + above[5] + above[6] + above[7] +
+ left[4] + left[5] + left[6] + left[7];
+ tmp2 = (tmp2 + 4) >> 3;
+ }
+ else
+ tmp2 = tmp1;
+ }
+ else if (availableB)
+ {
+ tmp1 = (above[0] + above[1] + above[2] + above[3] + 2) >> 2;
+ tmp2 = (above[4] + above[5] + above[6] + above[7] + 2) >> 2;
+ }
+ else
+ {
+ tmp1 = tmp2 = 128;
+ }
+
+ ASSERT(tmp1 < 256 && tmp2 < 256);
+ for (i = 4; i--;)
+ {
+ *data++ = (u8)tmp1;
+ *data++ = (u8)tmp1;
+ *data++ = (u8)tmp1;
+ *data++ = (u8)tmp1;
+ *data++ = (u8)tmp2;
+ *data++ = (u8)tmp2;
+ *data++ = (u8)tmp2;
+ *data++ = (u8)tmp2;
+ }
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: IntraChromaHorizontalPrediction
+
+ Functional description:
+ Perform intra chroma horizontal prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void IntraChromaHorizontalPrediction(u8 *data, u8 *left)
+{
+
+/* Variables */
+
+ u32 i;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(left);
+
+ for (i = 8; i--;)
+ {
+ *data++ = *left;
+ *data++ = *left;
+ *data++ = *left;
+ *data++ = *left;
+ *data++ = *left;
+ *data++ = *left;
+ *data++ = *left;
+ *data++ = *left++;
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: IntraChromaVerticalPrediction
+
+ Functional description:
+ Perform intra chroma vertical prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void IntraChromaVerticalPrediction(u8 *data, u8 *above)
+{
+
+/* Variables */
+
+ u32 i;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(above);
+
+ for (i = 8; i--;data++/*above-=8*/)
+ {
+ data[0] = *above;
+ data[8] = *above;
+ data[16] = *above;
+ data[24] = *above;
+ data[32] = *above;
+ data[40] = *above;
+ data[48] = *above;
+ data[56] = *above++;
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: IntraChromaPlanePrediction
+
+ Functional description:
+ Perform intra chroma plane prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void IntraChromaPlanePrediction(u8 *data, u8 *above, u8 *left)
+{
+
+/* Variables */
+
+ u32 i;
+ i32 a, b, c;
+ i32 tmp;
+ const u8 *clp = h264bsdClip + 512;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(above);
+ ASSERT(left);
+
+ a = 16 * (above[7] + left[7]);
+
+ b = (above[4] - above[2]) + 2 * (above[5] - above[1])
+ + 3 * (above[6] - above[0]) + 4 * (above[7] - above[-1]);
+ b = (17 * b + 16) >> 5;
+
+ /* p[-1,-1] has to be accessed through above pointer */
+ c = (left[4] - left[2]) + 2 * (left[5] - left[1])
+ + 3 * (left[6] - left[0]) + 4 * (left[7] - above[-1]);
+ c = (17 * c + 16) >> 5;
+
+ /*a += 16;*/
+ a = a - 3 * c + 16;
+ for (i = 8; i--; a += c)
+ {
+ tmp = (a - 3 * b);
+ *data++ = clp[tmp>>5];
+ tmp += b;
+ *data++ = clp[tmp>>5];
+ tmp += b;
+ *data++ = clp[tmp>>5];
+ tmp += b;
+ *data++ = clp[tmp>>5];
+ tmp += b;
+ *data++ = clp[tmp>>5];
+ tmp += b;
+ *data++ = clp[tmp>>5];
+ tmp += b;
+ *data++ = clp[tmp>>5];
+ tmp += b;
+ *data++ = clp[tmp>>5];
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Get4x4NeighbourPels
+
+ Functional description:
+ Get neighbouring pixels of a 4x4 block into 'a' and 'l'.
+
+------------------------------------------------------------------------------*/
+
+void Get4x4NeighbourPels(u8 *a, u8 *l, u8 *data, u8 *above, u8 *left,
+ u32 blockNum)
+{
+
+/* Variables */
+
+ u32 x, y;
+ u8 t1, t2;
+
+/* Code */
+
+ ASSERT(a);
+ ASSERT(l);
+ ASSERT(data);
+ ASSERT(above);
+ ASSERT(left);
+ ASSERT(blockNum < 16);
+
+ x = h264bsdBlockX[blockNum];
+ y = h264bsdBlockY[blockNum];
+
+ /* A and D */
+ if (x == 0)
+ {
+ t1 = left[y ];
+ t2 = left[y + 1];
+ l[1] = t1;
+ l[2] = t2;
+ t1 = left[y + 2];
+ t2 = left[y + 3];
+ l[3] = t1;
+ l[4] = t2;
+ }
+ else
+ {
+ t1 = data[y * 16 + x - 1 ];
+ t2 = data[y * 16 + x - 1 + 16];
+ l[1] = t1;
+ l[2] = t2;
+ t1 = data[y * 16 + x - 1 + 32];
+ t2 = data[y * 16 + x - 1 + 48];
+ l[3] = t1;
+ l[4] = t2;
+ }
+
+ /* B, C and D */
+ if (y == 0)
+ {
+ t1 = above[x ];
+ t2 = above[x ];
+ l[0] = t1;
+ a[0] = t2;
+ t1 = above[x + 1];
+ t2 = above[x + 2];
+ a[1] = t1;
+ a[2] = t2;
+ t1 = above[x + 3];
+ t2 = above[x + 4];
+ a[3] = t1;
+ a[4] = t2;
+ t1 = above[x + 5];
+ t2 = above[x + 6];
+ a[5] = t1;
+ a[6] = t2;
+ t1 = above[x + 7];
+ t2 = above[x + 8];
+ a[7] = t1;
+ a[8] = t2;
+ }
+ else
+ {
+ t1 = data[(y - 1) * 16 + x ];
+ t2 = data[(y - 1) * 16 + x + 1];
+ a[1] = t1;
+ a[2] = t2;
+ t1 = data[(y - 1) * 16 + x + 2];
+ t2 = data[(y - 1) * 16 + x + 3];
+ a[3] = t1;
+ a[4] = t2;
+ t1 = data[(y - 1) * 16 + x + 4];
+ t2 = data[(y - 1) * 16 + x + 5];
+ a[5] = t1;
+ a[6] = t2;
+ t1 = data[(y - 1) * 16 + x + 6];
+ t2 = data[(y - 1) * 16 + x + 7];
+ a[7] = t1;
+ a[8] = t2;
+
+ if (x == 0)
+ l[0] = a[0] = left[y-1];
+ else
+ l[0] = a[0] = data[(y - 1) * 16 + x - 1];
+ }
+}
+
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra4x4VerticalPrediction
+
+ Functional description:
+ Perform intra 4x4 vertical prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void Intra4x4VerticalPrediction(u8 *data, u8 *above)
+{
+
+/* Variables */
+
+ u8 t1, t2;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(above);
+
+ t1 = above[0];
+ t2 = above[1];
+ data[0] = data[4] = data[8] = data[12] = t1;
+ data[1] = data[5] = data[9] = data[13] = t2;
+ t1 = above[2];
+ t2 = above[3];
+ data[2] = data[6] = data[10] = data[14] = t1;
+ data[3] = data[7] = data[11] = data[15] = t2;
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra4x4HorizontalPrediction
+
+ Functional description:
+ Perform intra 4x4 horizontal prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void Intra4x4HorizontalPrediction(u8 *data, u8 *left)
+{
+
+/* Variables */
+
+ u8 t1, t2;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(left);
+
+ t1 = left[0];
+ t2 = left[1];
+ data[0] = data[1] = data[2] = data[3] = t1;
+ data[4] = data[5] = data[6] = data[7] = t2;
+ t1 = left[2];
+ t2 = left[3];
+ data[8] = data[9] = data[10] = data[11] = t1;
+ data[12] = data[13] = data[14] = data[15] = t2;
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra4x4DcPrediction
+
+ Functional description:
+ Perform intra 4x4 DC prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void Intra4x4DcPrediction(u8 *data, u8 *above, u8 *left, u32 availableA,
+ u32 availableB)
+{
+
+/* Variables */
+
+ u32 tmp;
+ u8 t1, t2, t3, t4;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(above);
+ ASSERT(left);
+
+ if (availableA && availableB)
+ {
+ t1 = above[0]; t2 = above[1]; t3 = above[2]; t4 = above[3];
+ tmp = t1 + t2 + t3 + t4;
+ t1 = left[0]; t2 = left[1]; t3 = left[2]; t4 = left[3];
+ tmp += t1 + t2 + t3 + t4;
+ tmp = (tmp + 4) >> 3;
+ }
+ else if (availableA)
+ {
+ t1 = left[0]; t2 = left[1]; t3 = left[2]; t4 = left[3];
+ tmp = (t1 + t2 + t3 + t4 + 2) >> 2;
+ }
+ else if (availableB)
+ {
+ t1 = above[0]; t2 = above[1]; t3 = above[2]; t4 = above[3];
+ tmp = (t1 + t2 + t3 + t4 + 2) >> 2;
+ }
+ else
+ {
+ tmp = 128;
+ }
+
+ ASSERT(tmp < 256);
+ data[0] = data[1] = data[2] = data[3] =
+ data[4] = data[5] = data[6] = data[7] =
+ data[8] = data[9] = data[10] = data[11] =
+ data[12] = data[13] = data[14] = data[15] = (u8)tmp;
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra4x4DiagonalDownLeftPrediction
+
+ Functional description:
+ Perform intra 4x4 diagonal down-left prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void Intra4x4DiagonalDownLeftPrediction(u8 *data, u8 *above)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(above);
+
+ data[ 0] = (above[0] + 2 * above[1] + above[2] + 2) >> 2;
+ data[ 1] = (above[1] + 2 * above[2] + above[3] + 2) >> 2;
+ data[ 4] = (above[1] + 2 * above[2] + above[3] + 2) >> 2;
+ data[ 2] = (above[2] + 2 * above[3] + above[4] + 2) >> 2;
+ data[ 5] = (above[2] + 2 * above[3] + above[4] + 2) >> 2;
+ data[ 8] = (above[2] + 2 * above[3] + above[4] + 2) >> 2;
+ data[ 3] = (above[3] + 2 * above[4] + above[5] + 2) >> 2;
+ data[ 6] = (above[3] + 2 * above[4] + above[5] + 2) >> 2;
+ data[ 9] = (above[3] + 2 * above[4] + above[5] + 2) >> 2;
+ data[12] = (above[3] + 2 * above[4] + above[5] + 2) >> 2;
+ data[ 7] = (above[4] + 2 * above[5] + above[6] + 2) >> 2;
+ data[10] = (above[4] + 2 * above[5] + above[6] + 2) >> 2;
+ data[13] = (above[4] + 2 * above[5] + above[6] + 2) >> 2;
+ data[11] = (above[5] + 2 * above[6] + above[7] + 2) >> 2;
+ data[14] = (above[5] + 2 * above[6] + above[7] + 2) >> 2;
+ data[15] = (above[6] + 3 * above[7] + 2) >> 2;
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra4x4DiagonalDownRightPrediction
+
+ Functional description:
+ Perform intra 4x4 diagonal down-right prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void Intra4x4DiagonalDownRightPrediction(u8 *data, u8 *above, u8 *left)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(above);
+ ASSERT(left);
+
+ data[ 0] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2;
+ data[ 5] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2;
+ data[10] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2;
+ data[15] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2;
+ data[ 1] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2;
+ data[ 6] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2;
+ data[11] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2;
+ data[ 2] = (above[0] + 2 * above[1] + above[2] + 2) >> 2;
+ data[ 7] = (above[0] + 2 * above[1] + above[2] + 2) >> 2;
+ data[ 3] = (above[1] + 2 * above[2] + above[3] + 2) >> 2;
+ data[ 4] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2;
+ data[ 9] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2;
+ data[14] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2;
+ data[ 8] = (left[0] + 2 * left[1] + left[2] + 2) >> 2;
+ data[13] = (left[0] + 2 * left[1] + left[2] + 2) >> 2;
+ data[12] = (left[1] + 2 * left[2] + left[3] + 2) >> 2;
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra4x4VerticalRightPrediction
+
+ Functional description:
+ Perform intra 4x4 vertical right prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void Intra4x4VerticalRightPrediction(u8 *data, u8 *above, u8 *left)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(above);
+ ASSERT(left);
+
+ data[ 0] = (above[-1] + above[0] + 1) >> 1;
+ data[ 9] = (above[-1] + above[0] + 1) >> 1;
+ data[ 5] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2;
+ data[14] = (above[-1] + 2 * above[0] + above[1] + 2) >> 2;
+ data[ 4] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2;
+ data[13] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2;
+ data[ 1] = (above[0] + above[1] + 1) >> 1;
+ data[10] = (above[0] + above[1] + 1) >> 1;
+ data[ 6] = (above[0] + 2 * above[1] + above[2] + 2) >> 2;
+ data[15] = (above[0] + 2 * above[1] + above[2] + 2) >> 2;
+ data[ 2] = (above[1] + above[2] + 1) >> 1;
+ data[11] = (above[1] + above[2] + 1) >> 1;
+ data[ 7] = (above[1] + 2 * above[2] + above[3] + 2) >> 2;
+ data[ 3] = (above[2] + above[3] + 1) >> 1;
+ data[ 8] = (left[1] + 2 * left[0] + left[-1] + 2) >> 2;
+ data[12] = (left[2] + 2 * left[1] + left[0] + 2) >> 2;
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra4x4HorizontalDownPrediction
+
+ Functional description:
+ Perform intra 4x4 horizontal down prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void Intra4x4HorizontalDownPrediction(u8 *data, u8 *above, u8 *left)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(above);
+ ASSERT(left);
+
+ data[ 0] = (left[-1] + left[0] + 1) >> 1;
+ data[ 6] = (left[-1] + left[0] + 1) >> 1;
+ data[ 5] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2;
+ data[11] = (left[-1] + 2 * left[0] + left[1] + 2) >> 2;
+ data[ 4] = (left[0] + left[1] + 1) >> 1;
+ data[10] = (left[0] + left[1] + 1) >> 1;
+ data[ 9] = (left[0] + 2 * left[1] + left[2] + 2) >> 2;
+ data[15] = (left[0] + 2 * left[1] + left[2] + 2) >> 2;
+ data[ 8] = (left[1] + left[2] + 1) >> 1;
+ data[14] = (left[1] + left[2] + 1) >> 1;
+ data[13] = (left[1] + 2 * left[2] + left[3] + 2) >> 2;
+ data[12] = (left[2] + left[3] + 1) >> 1;
+ data[ 1] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2;
+ data[ 7] = (above[0] + 2 * above[-1] + left[0] + 2) >> 2;
+ data[ 2] = (above[1] + 2 * above[0] + above[-1] + 2) >> 2;
+ data[ 3] = (above[2] + 2 * above[1] + above[0] + 2) >> 2;
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra4x4VerticalLeftPrediction
+
+ Functional description:
+ Perform intra 4x4 vertical left prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void Intra4x4VerticalLeftPrediction(u8 *data, u8 *above)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(above);
+
+ data[ 0] = (above[0] + above[1] + 1) >> 1;
+ data[ 1] = (above[1] + above[2] + 1) >> 1;
+ data[ 2] = (above[2] + above[3] + 1) >> 1;
+ data[ 3] = (above[3] + above[4] + 1) >> 1;
+ data[ 4] = (above[0] + 2 * above[1] + above[2] + 2) >> 2;
+ data[ 5] = (above[1] + 2 * above[2] + above[3] + 2) >> 2;
+ data[ 6] = (above[2] + 2 * above[3] + above[4] + 2) >> 2;
+ data[ 7] = (above[3] + 2 * above[4] + above[5] + 2) >> 2;
+ data[ 8] = (above[1] + above[2] + 1) >> 1;
+ data[ 9] = (above[2] + above[3] + 1) >> 1;
+ data[10] = (above[3] + above[4] + 1) >> 1;
+ data[11] = (above[4] + above[5] + 1) >> 1;
+ data[12] = (above[1] + 2 * above[2] + above[3] + 2) >> 2;
+ data[13] = (above[2] + 2 * above[3] + above[4] + 2) >> 2;
+ data[14] = (above[3] + 2 * above[4] + above[5] + 2) >> 2;
+ data[15] = (above[4] + 2 * above[5] + above[6] + 2) >> 2;
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: Intra4x4HorizontalUpPrediction
+
+ Functional description:
+ Perform intra 4x4 horizontal up prediction mode.
+
+------------------------------------------------------------------------------*/
+
+void Intra4x4HorizontalUpPrediction(u8 *data, u8 *left)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(left);
+
+ data[ 0] = (left[0] + left[1] + 1) >> 1;
+ data[ 1] = (left[0] + 2 * left[1] + left[2] + 2) >> 2;
+ data[ 2] = (left[1] + left[2] + 1) >> 1;
+ data[ 3] = (left[1] + 2 * left[2] + left[3] + 2) >> 2;
+ data[ 4] = (left[1] + left[2] + 1) >> 1;
+ data[ 5] = (left[1] + 2 * left[2] + left[3] + 2) >> 2;
+ data[ 6] = (left[2] + left[3] + 1) >> 1;
+ data[ 7] = (left[2] + 3 * left[3] + 2) >> 2;
+ data[ 8] = (left[2] + left[3] + 1) >> 1;
+ data[ 9] = (left[2] + 3 * left[3] + 2) >> 2;
+ data[10] = left[3];
+ data[11] = left[3];
+ data[12] = left[3];
+ data[13] = left[3];
+ data[14] = left[3];
+ data[15] = left[3];
+
+}
+
+#endif /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+
+ Function: Write4x4To16x16
+
+ Functional description:
+ Write a 4x4 block (data4x4) into correct position
+ in 16x16 macroblock (data).
+
+------------------------------------------------------------------------------*/
+
+void Write4x4To16x16(u8 *data, u8 *data4x4, u32 blockNum)
+{
+
+/* Variables */
+
+ u32 x, y;
+ u32 *in32, *out32;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(data4x4);
+ ASSERT(blockNum < 16);
+
+ x = h264bsdBlockX[blockNum];
+ y = h264bsdBlockY[blockNum];
+
+ data += y*16+x;
+
+ ASSERT(((u32)data&0x3) == 0);
+
+ /*lint --e(826) */
+ out32 = (u32 *)data;
+ /*lint --e(826) */
+ in32 = (u32 *)data4x4;
+
+ out32[0] = *in32++;
+ out32[4] = *in32++;
+ out32[8] = *in32++;
+ out32[12] = *in32++;
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DetermineIntra4x4PredMode
+
+ Functional description:
+ Returns the intra 4x4 prediction mode of a block based on the
+ neighbouring macroblocks and information parsed from stream.
+
+------------------------------------------------------------------------------*/
+
+u32 DetermineIntra4x4PredMode(macroblockLayer_t *pMbLayer,
+ u32 available, neighbour_t *nA, neighbour_t *nB, u32 index,
+ mbStorage_t *nMbA, mbStorage_t *nMbB)
+{
+
+/* Variables */
+
+ u32 mode1, mode2;
+ mbStorage_t *pMb;
+
+/* Code */
+
+ ASSERT(pMbLayer);
+
+ /* dc only prediction? */
+ if (!available)
+ mode1 = 2;
+ else
+ {
+ pMb = nMbA;
+ if (h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTRA4x4)
+ {
+ mode1 = pMb->intra4x4PredMode[nA->index];
+ }
+ else
+ mode1 = 2;
+
+ pMb = nMbB;
+ if (h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTRA4x4)
+ {
+ mode2 = pMb->intra4x4PredMode[nB->index];
+ }
+ else
+ mode2 = 2;
+
+ mode1 = MIN(mode1, mode2);
+ }
+
+ if (!pMbLayer->mbPred.prevIntra4x4PredModeFlag[index])
+ {
+ if (pMbLayer->mbPred.remIntra4x4PredMode[index] < mode1)
+ {
+ mode1 = pMbLayer->mbPred.remIntra4x4PredMode[index];
+ }
+ else
+ {
+ mode1 = pMbLayer->mbPred.remIntra4x4PredMode[index] + 1;
+ }
+ }
+
+ return(mode1);
+}
+
+
+/*lint +e702 */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.h
new file mode 100755
index 0000000..4652bd5
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_intra_prediction.h
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_INTRA_PREDICTION_H
+#define H264SWDEC_INTRA_PREDICTION_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_image.h"
+#include "h264bsd_macroblock_layer.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+#ifndef H264DEC_OMXDL
+u32 h264bsdIntraPrediction(mbStorage_t *pMb, macroblockLayer_t *mbLayer,
+ image_t *image, u32 mbNum, u32 constrainedIntraPred, u8 *data);
+
+u32 h264bsdIntra4x4Prediction(mbStorage_t *pMb, u8 *data,
+ macroblockLayer_t *mbLayer,
+ u8 *above, u8 *left, u32 constrainedIntraPred);
+u32 h264bsdIntra16x16Prediction(mbStorage_t *pMb, u8 *data, i32 residual[][16],
+ u8 *above, u8 *left, u32 constrainedIntraPred);
+
+u32 h264bsdIntraChromaPrediction(mbStorage_t *pMb, u8 *data, i32 residual[][16],
+ u8 *above, u8 *left, u32 predMode, u32 constrainedIntraPred);
+
+void h264bsdGetNeighbourPels(image_t *image, u8 *above, u8 *left, u32 mbNum);
+
+#else
+
+u32 h264bsdIntra4x4Prediction(mbStorage_t *pMb, u8 *data,
+ macroblockLayer_t *mbLayer,
+ u8 *pImage, u32 width,
+ u32 constrainedIntraPred, u32 block);
+
+u32 h264bsdIntra16x16Prediction(mbStorage_t *pMb, u8 *data, u8 *pImage,
+ u32 width, u32 constrainedIntraPred);
+
+u32 h264bsdIntraChromaPrediction(mbStorage_t *pMb, u8 *data, image_t *image,
+ u32 predMode, u32 constrainedIntraPred);
+
+#endif
+
+#endif /* #ifdef H264SWDEC_INTRA_PREDICTION_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.c
new file mode 100755
index 0000000..2b3e7f0
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.c
@@ -0,0 +1,1446 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdDecodeMacroblockLayer
+ h264bsdMbPartPredMode
+ h264bsdNumMbPart
+ h264bsdNumSubMbPart
+ DecodeMbPred
+ DecodeSubMbPred
+ DecodeResidual
+ DetermineNc
+ CbpIntra16x16
+ h264bsdPredModeIntra16x16
+ h264bsdDecodeMacroblock
+ ProcessResidual
+ h264bsdSubMbPartMode
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_macroblock_layer.h"
+#include "h264bsd_slice_header.h"
+#include "h264bsd_util.h"
+#include "h264bsd_vlc.h"
+#include "h264bsd_cavlc.h"
+#include "h264bsd_nal_unit.h"
+#include "h264bsd_neighbour.h"
+#include "h264bsd_transform.h"
+#include "h264bsd_intra_prediction.h"
+#include "h264bsd_inter_prediction.h"
+
+#ifdef H264DEC_OMXDL
+#include "omxtypes.h"
+#include "omxVC.h"
+#include "armVC.h"
+#endif /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+#ifdef H264DEC_OMXDL
+static const u32 chromaIndex[8] = { 256, 260, 288, 292, 320, 324, 352, 356 };
+static const u32 lumaIndex[16] = { 0, 4, 64, 68,
+ 8, 12, 72, 76,
+ 128, 132, 192, 196,
+ 136, 140, 200, 204 };
+#endif
+/* mapping of dc coefficients array to luma blocks */
+static const u32 dcCoeffIndex[16] =
+ {0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15};
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static u32 DecodeMbPred(strmData_t *pStrmData, mbPred_t *pMbPred,
+ mbType_e mbType, u32 numRefIdxActive);
+static u32 DecodeSubMbPred(strmData_t *pStrmData, subMbPred_t *pSubMbPred,
+ mbType_e mbType, u32 numRefIdxActive);
+static u32 DecodeResidual(strmData_t *pStrmData, residual_t *pResidual,
+ mbStorage_t *pMb, mbType_e mbType, u32 codedBlockPattern);
+
+#ifdef H264DEC_OMXDL
+static u32 DetermineNc(mbStorage_t *pMb, u32 blockIndex, u8 *pTotalCoeff);
+#else
+static u32 DetermineNc(mbStorage_t *pMb, u32 blockIndex, i16 *pTotalCoeff);
+#endif
+
+static u32 CbpIntra16x16(mbType_e mbType);
+#ifdef H264DEC_OMXDL
+static u32 ProcessIntra4x4Residual(mbStorage_t *pMb, u8 *data, u32 constrainedIntraPred,
+ macroblockLayer_t *mbLayer, const u8 **pSrc, image_t *image);
+static u32 ProcessChromaResidual(mbStorage_t *pMb, u8 *data, const u8 **pSrc );
+static u32 ProcessIntra16x16Residual(mbStorage_t *pMb, u8 *data, u32 constrainedIntraPred,
+ u32 intraChromaPredMode, const u8 **pSrc, image_t *image);
+
+
+#else
+static u32 ProcessResidual(mbStorage_t *pMb, i32 residualLevel[][16], u32 *);
+#endif
+
+/*------------------------------------------------------------------------------
+
+ Function name: h264bsdDecodeMacroblockLayer
+
+ Functional description:
+ Parse macroblock specific information from bit stream.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ pMb pointer to macroblock storage structure
+ sliceType type of the current slice
+ numRefIdxActive maximum reference index
+
+ Outputs:
+ pMbLayer stores the macroblock data parsed from stream
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK end of stream or error in stream
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeMacroblockLayer(strmData_t *pStrmData,
+ macroblockLayer_t *pMbLayer, mbStorage_t *pMb, u32 sliceType,
+ u32 numRefIdxActive)
+{
+
+/* Variables */
+
+ u32 tmp, i, value;
+ i32 itmp;
+ mbPartPredMode_e partMode;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pMbLayer);
+
+#ifdef H264DEC_NEON
+ h264bsdClearMbLayer(pMbLayer, ((sizeof(macroblockLayer_t) + 63) & ~0x3F));
+#else
+ H264SwDecMemset(pMbLayer, 0, sizeof(macroblockLayer_t));
+#endif
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+
+ if (IS_I_SLICE(sliceType))
+ {
+ if ((value + 6) > 31 || tmp != HANTRO_OK)
+ return(HANTRO_NOK);
+ pMbLayer->mbType = (mbType_e)(value + 6);
+ }
+ else
+ {
+ if ((value + 1) > 31 || tmp != HANTRO_OK)
+ return(HANTRO_NOK);
+ pMbLayer->mbType = (mbType_e)(value + 1);
+ }
+
+ if (pMbLayer->mbType == I_PCM)
+ {
+ i32 *level;
+ while( !h264bsdIsByteAligned(pStrmData) )
+ {
+ /* pcm_alignment_zero_bit */
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp)
+ return(HANTRO_NOK);
+ }
+
+ level = pMbLayer->residual.level[0];
+ for (i = 0; i < 384; i++)
+ {
+ value = h264bsdGetBits(pStrmData, 8);
+ if (value == END_OF_STREAM)
+ return(HANTRO_NOK);
+ *level++ = (i32)value;
+ }
+ }
+ else
+ {
+ partMode = h264bsdMbPartPredMode(pMbLayer->mbType);
+ if ( (partMode == PRED_MODE_INTER) &&
+ (h264bsdNumMbPart(pMbLayer->mbType) == 4) )
+ {
+ tmp = DecodeSubMbPred(pStrmData, &pMbLayer->subMbPred,
+ pMbLayer->mbType, numRefIdxActive);
+ }
+ else
+ {
+ tmp = DecodeMbPred(pStrmData, &pMbLayer->mbPred,
+ pMbLayer->mbType, numRefIdxActive);
+ }
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ if (partMode != PRED_MODE_INTRA16x16)
+ {
+ tmp = h264bsdDecodeExpGolombMapped(pStrmData, &value,
+ (u32)(partMode == PRED_MODE_INTRA4x4));
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pMbLayer->codedBlockPattern = value;
+ }
+ else
+ {
+ pMbLayer->codedBlockPattern = CbpIntra16x16(pMbLayer->mbType);
+ }
+
+ if ( pMbLayer->codedBlockPattern ||
+ (partMode == PRED_MODE_INTRA16x16) )
+ {
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK || (itmp < -26) || (itmp > 25) )
+ return(HANTRO_NOK);
+ pMbLayer->mbQpDelta = itmp;
+
+ tmp = DecodeResidual(pStrmData, &pMbLayer->residual, pMb,
+ pMbLayer->mbType, pMbLayer->codedBlockPattern);
+
+ pStrmData->strmBuffReadBits =
+ (u32)(pStrmData->pStrmCurrPos - pStrmData->pStrmBuffStart) * 8 +
+ pStrmData->bitPosInWord;
+
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdMbPartPredMode
+
+ Functional description:
+ Returns the prediction mode of a macroblock type
+
+------------------------------------------------------------------------------*/
+
+mbPartPredMode_e h264bsdMbPartPredMode(mbType_e mbType)
+{
+
+/* Variables */
+
+
+/* Code */
+
+ ASSERT(mbType <= 31);
+
+ if ((mbType <= P_8x8ref0))
+ return(PRED_MODE_INTER);
+ else if (mbType == I_4x4)
+ return(PRED_MODE_INTRA4x4);
+ else
+ return(PRED_MODE_INTRA16x16);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdNumMbPart
+
+ Functional description:
+ Returns the amount of macroblock partitions in a macroblock type
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdNumMbPart(mbType_e mbType)
+{
+
+/* Variables */
+
+
+/* Code */
+
+ ASSERT(h264bsdMbPartPredMode(mbType) == PRED_MODE_INTER);
+
+ switch (mbType)
+ {
+ case P_L0_16x16:
+ case P_Skip:
+ return(1);
+
+ case P_L0_L0_16x8:
+ case P_L0_L0_8x16:
+ return(2);
+
+ /* P_8x8 or P_8x8ref0 */
+ default:
+ return(4);
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdNumSubMbPart
+
+ Functional description:
+ Returns the amount of sub-partitions in a sub-macroblock type
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdNumSubMbPart(subMbType_e subMbType)
+{
+
+/* Variables */
+
+
+/* Code */
+
+ ASSERT(subMbType <= P_L0_4x4);
+
+ switch (subMbType)
+ {
+ case P_L0_8x8:
+ return(1);
+
+ case P_L0_8x4:
+ case P_L0_4x8:
+ return(2);
+
+ /* P_L0_4x4 */
+ default:
+ return(4);
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeMbPred
+
+ Functional description:
+ Parse macroblock prediction information from bit stream and store
+ in 'pMbPred'.
+
+------------------------------------------------------------------------------*/
+
+u32 DecodeMbPred(strmData_t *pStrmData, mbPred_t *pMbPred, mbType_e mbType,
+ u32 numRefIdxActive)
+{
+
+/* Variables */
+
+ u32 tmp, i, j, value;
+ i32 itmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pMbPred);
+
+ switch (h264bsdMbPartPredMode(mbType))
+ {
+ case PRED_MODE_INTER: /* PRED_MODE_INTER */
+ if (numRefIdxActive > 1)
+ {
+ for (i = h264bsdNumMbPart(mbType), j = 0; i--; j++)
+ {
+ tmp = h264bsdDecodeExpGolombTruncated(pStrmData, &value,
+ (u32)(numRefIdxActive > 2));
+ if (tmp != HANTRO_OK || value >= numRefIdxActive)
+ return(HANTRO_NOK);
+
+ pMbPred->refIdxL0[j] = value;
+ }
+ }
+
+ for (i = h264bsdNumMbPart(mbType), j = 0; i--; j++)
+ {
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pMbPred->mvdL0[j].hor = (i16)itmp;
+
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pMbPred->mvdL0[j].ver = (i16)itmp;
+ }
+ break;
+
+ case PRED_MODE_INTRA4x4:
+ for (itmp = 0, i = 0; itmp < 2; itmp++)
+ {
+ value = h264bsdShowBits32(pStrmData);
+ tmp = 0;
+ for (j = 8; j--; i++)
+ {
+ pMbPred->prevIntra4x4PredModeFlag[i] =
+ value & 0x80000000 ? HANTRO_TRUE : HANTRO_FALSE;
+ value <<= 1;
+ if (!pMbPred->prevIntra4x4PredModeFlag[i])
+ {
+ pMbPred->remIntra4x4PredMode[i] = value>>29;
+ value <<= 3;
+ tmp++;
+ }
+ }
+ if (h264bsdFlushBits(pStrmData, 8 + 3*tmp) == END_OF_STREAM)
+ return(HANTRO_NOK);
+ }
+ /* fall-through */
+
+ case PRED_MODE_INTRA16x16:
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK || value > 3)
+ return(HANTRO_NOK);
+ pMbPred->intraChromaPredMode = value;
+ break;
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeSubMbPred
+
+ Functional description:
+ Parse sub-macroblock prediction information from bit stream and
+ store in 'pMbPred'.
+
+------------------------------------------------------------------------------*/
+
+u32 DecodeSubMbPred(strmData_t *pStrmData, subMbPred_t *pSubMbPred,
+ mbType_e mbType, u32 numRefIdxActive)
+{
+
+/* Variables */
+
+ u32 tmp, i, j, value;
+ i32 itmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSubMbPred);
+ ASSERT(h264bsdMbPartPredMode(mbType) == PRED_MODE_INTER);
+
+ for (i = 0; i < 4; i++)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK || value > 3)
+ return(HANTRO_NOK);
+ pSubMbPred->subMbType[i] = (subMbType_e)value;
+ }
+
+ if ( (numRefIdxActive > 1) && (mbType != P_8x8ref0) )
+ {
+ for (i = 0; i < 4; i++)
+ {
+ tmp = h264bsdDecodeExpGolombTruncated(pStrmData, &value,
+ (u32)(numRefIdxActive > 2));
+ if (tmp != HANTRO_OK || value >= numRefIdxActive)
+ return(HANTRO_NOK);
+ pSubMbPred->refIdxL0[i] = value;
+ }
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ j = 0;
+ for (value = h264bsdNumSubMbPart(pSubMbPred->subMbType[i]);
+ value--; j++)
+ {
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSubMbPred->mvdL0[i][j].hor = (i16)itmp;
+
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSubMbPred->mvdL0[i][j].ver = (i16)itmp;
+ }
+ }
+
+ return(HANTRO_OK);
+
+}
+
+#ifdef H264DEC_OMXDL
+/*------------------------------------------------------------------------------
+
+ Function: DecodeResidual
+
+ Functional description:
+ Parse residual information from bit stream and store in 'pResidual'.
+
+------------------------------------------------------------------------------*/
+
+u32 DecodeResidual(strmData_t *pStrmData, residual_t *pResidual,
+ mbStorage_t *pMb, mbType_e mbType, u32 codedBlockPattern)
+{
+
+/* Variables */
+
+ u32 i, j;
+ u32 blockCoded;
+ u32 blockIndex;
+ u32 is16x16;
+ OMX_INT nc;
+ OMXResult omxRes;
+ OMX_U8 *pPosCoefBuf;
+
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pResidual);
+
+ pPosCoefBuf = pResidual->posCoefBuf;
+
+ /* luma DC is at index 24 */
+ if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTRA16x16)
+ {
+ nc = (OMX_INT)DetermineNc(pMb, 0, pResidual->totalCoeff);
+#ifndef H264DEC_NEON
+ omxRes = omxVCM4P10_DecodeCoeffsToPairCAVLC(
+ (const OMX_U8 **) (&pStrmData->pStrmCurrPos),
+ (OMX_S32*) (&pStrmData->bitPosInWord),
+ &pResidual->totalCoeff[24],
+ &pPosCoefBuf,
+ nc,
+ 16);
+#else
+ omxRes = armVCM4P10_DecodeCoeffsToPair(
+ (const OMX_U8 **) (&pStrmData->pStrmCurrPos),
+ (OMX_S32*) (&pStrmData->bitPosInWord),
+ &pResidual->totalCoeff[24],
+ &pPosCoefBuf,
+ nc,
+ 16);
+#endif
+ if (omxRes != OMX_Sts_NoErr)
+ return(HANTRO_NOK);
+ is16x16 = HANTRO_TRUE;
+ }
+ else
+ is16x16 = HANTRO_FALSE;
+
+ for (i = 4, blockIndex = 0; i--;)
+ {
+ /* luma cbp in bits 0-3 */
+ blockCoded = codedBlockPattern & 0x1;
+ codedBlockPattern >>= 1;
+ if (blockCoded)
+ {
+ for (j = 4; j--; blockIndex++)
+ {
+ nc = (OMX_INT)DetermineNc(pMb,blockIndex,pResidual->totalCoeff);
+ if (is16x16)
+ {
+#ifndef H264DEC_NEON
+ omxRes = omxVCM4P10_DecodeCoeffsToPairCAVLC(
+ (const OMX_U8 **) (&pStrmData->pStrmCurrPos),
+ (OMX_S32*) (&pStrmData->bitPosInWord),
+ &pResidual->totalCoeff[blockIndex],
+ &pPosCoefBuf,
+ nc,
+ 15);
+#else
+ omxRes = armVCM4P10_DecodeCoeffsToPair(
+ (const OMX_U8 **) (&pStrmData->pStrmCurrPos),
+ (OMX_S32*) (&pStrmData->bitPosInWord),
+ &pResidual->totalCoeff[blockIndex],
+ &pPosCoefBuf,
+ nc,
+ 15);
+#endif
+ }
+ else
+ {
+#ifndef H264DEC_NEON
+ omxRes = omxVCM4P10_DecodeCoeffsToPairCAVLC(
+ (const OMX_U8 **) (&pStrmData->pStrmCurrPos),
+ (OMX_S32*) (&pStrmData->bitPosInWord),
+ &pResidual->totalCoeff[blockIndex],
+ &pPosCoefBuf,
+ nc,
+ 16);
+#else
+ omxRes = armVCM4P10_DecodeCoeffsToPair(
+ (const OMX_U8 **) (&pStrmData->pStrmCurrPos),
+ (OMX_S32*) (&pStrmData->bitPosInWord),
+ &pResidual->totalCoeff[blockIndex],
+ &pPosCoefBuf,
+ nc,
+ 16);
+#endif
+ }
+ if (omxRes != OMX_Sts_NoErr)
+ return(HANTRO_NOK);
+ }
+ }
+ else
+ blockIndex += 4;
+ }
+
+ /* chroma DC block are at indices 25 and 26 */
+ blockCoded = codedBlockPattern & 0x3;
+ if (blockCoded)
+ {
+#ifndef H264DEC_NEON
+ omxRes = omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC(
+ (const OMX_U8**) (&pStrmData->pStrmCurrPos),
+ (OMX_S32*) (&pStrmData->bitPosInWord),
+ &pResidual->totalCoeff[25],
+ &pPosCoefBuf);
+#else
+ omxRes = armVCM4P10_DecodeCoeffsToPair(
+ (const OMX_U8**) (&pStrmData->pStrmCurrPos),
+ (OMX_S32*) (&pStrmData->bitPosInWord),
+ &pResidual->totalCoeff[25],
+ &pPosCoefBuf,
+ 17,
+ 4);
+#endif
+ if (omxRes != OMX_Sts_NoErr)
+ return(HANTRO_NOK);
+#ifndef H264DEC_NEON
+ omxRes = omxVCM4P10_DecodeChromaDcCoeffsToPairCAVLC(
+ (const OMX_U8**) (&pStrmData->pStrmCurrPos),
+ (OMX_S32*) (&pStrmData->bitPosInWord),
+ &pResidual->totalCoeff[26],
+ &pPosCoefBuf);
+#else
+ omxRes = armVCM4P10_DecodeCoeffsToPair(
+ (const OMX_U8**) (&pStrmData->pStrmCurrPos),
+ (OMX_S32*) (&pStrmData->bitPosInWord),
+ &pResidual->totalCoeff[26],
+ &pPosCoefBuf,
+ 17,
+ 4);
+#endif
+ if (omxRes != OMX_Sts_NoErr)
+ return(HANTRO_NOK);
+ }
+
+ /* chroma AC */
+ blockCoded = codedBlockPattern & 0x2;
+ if (blockCoded)
+ {
+ for (i = 8; i--;blockIndex++)
+ {
+ nc = (OMX_INT)DetermineNc(pMb, blockIndex, pResidual->totalCoeff);
+#ifndef H264DEC_NEON
+ omxRes = omxVCM4P10_DecodeCoeffsToPairCAVLC(
+ (const OMX_U8 **) (&pStrmData->pStrmCurrPos),
+ (OMX_S32*) (&pStrmData->bitPosInWord),
+ &pResidual->totalCoeff[blockIndex],
+ &pPosCoefBuf,
+ nc,
+ 15);
+#else
+ omxRes = armVCM4P10_DecodeCoeffsToPair(
+ (const OMX_U8 **) (&pStrmData->pStrmCurrPos),
+ (OMX_S32*) (&pStrmData->bitPosInWord),
+ &pResidual->totalCoeff[blockIndex],
+ &pPosCoefBuf,
+ nc,
+ 15);
+#endif
+ if (omxRes != OMX_Sts_NoErr)
+ return(HANTRO_NOK);
+ }
+ }
+
+ return(HANTRO_OK);
+
+}
+
+#else
+/*------------------------------------------------------------------------------
+
+ Function: DecodeResidual
+
+ Functional description:
+ Parse residual information from bit stream and store in 'pResidual'.
+
+------------------------------------------------------------------------------*/
+
+u32 DecodeResidual(strmData_t *pStrmData, residual_t *pResidual,
+ mbStorage_t *pMb, mbType_e mbType, u32 codedBlockPattern)
+{
+
+/* Variables */
+
+ u32 i, j, tmp;
+ i32 nc;
+ u32 blockCoded;
+ u32 blockIndex;
+ u32 is16x16;
+ i32 (*level)[16];
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pResidual);
+
+ level = pResidual->level;
+
+ /* luma DC is at index 24 */
+ if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTRA16x16)
+ {
+ nc = (i32)DetermineNc(pMb, 0, pResidual->totalCoeff);
+ tmp = h264bsdDecodeResidualBlockCavlc(pStrmData, level[24], nc, 16);
+ if ((tmp & 0xF) != HANTRO_OK)
+ return(tmp);
+ pResidual->totalCoeff[24] = (tmp >> 4) & 0xFF;
+ is16x16 = HANTRO_TRUE;
+ }
+ else
+ is16x16 = HANTRO_FALSE;
+
+ for (i = 4, blockIndex = 0; i--;)
+ {
+ /* luma cbp in bits 0-3 */
+ blockCoded = codedBlockPattern & 0x1;
+ codedBlockPattern >>= 1;
+ if (blockCoded)
+ {
+ for (j = 4; j--; blockIndex++)
+ {
+ nc = (i32)DetermineNc(pMb, blockIndex, pResidual->totalCoeff);
+ if (is16x16)
+ {
+ tmp = h264bsdDecodeResidualBlockCavlc(pStrmData,
+ level[blockIndex] + 1, nc, 15);
+ pResidual->coeffMap[blockIndex] = tmp >> 15;
+ }
+ else
+ {
+ tmp = h264bsdDecodeResidualBlockCavlc(pStrmData,
+ level[blockIndex], nc, 16);
+ pResidual->coeffMap[blockIndex] = tmp >> 16;
+ }
+ if ((tmp & 0xF) != HANTRO_OK)
+ return(tmp);
+ pResidual->totalCoeff[blockIndex] = (tmp >> 4) & 0xFF;
+ }
+ }
+ else
+ blockIndex += 4;
+ }
+
+ /* chroma DC block are at indices 25 and 26 */
+ blockCoded = codedBlockPattern & 0x3;
+ if (blockCoded)
+ {
+ tmp = h264bsdDecodeResidualBlockCavlc(pStrmData, level[25], -1, 4);
+ if ((tmp & 0xF) != HANTRO_OK)
+ return(tmp);
+ pResidual->totalCoeff[25] = (tmp >> 4) & 0xFF;
+ tmp = h264bsdDecodeResidualBlockCavlc(pStrmData, level[25]+4, -1, 4);
+ if ((tmp & 0xF) != HANTRO_OK)
+ return(tmp);
+ pResidual->totalCoeff[26] = (tmp >> 4) & 0xFF;
+ }
+
+ /* chroma AC */
+ blockCoded = codedBlockPattern & 0x2;
+ if (blockCoded)
+ {
+ for (i = 8; i--;blockIndex++)
+ {
+ nc = (i32)DetermineNc(pMb, blockIndex, pResidual->totalCoeff);
+ tmp = h264bsdDecodeResidualBlockCavlc(pStrmData,
+ level[blockIndex] + 1, nc, 15);
+ if ((tmp & 0xF) != HANTRO_OK)
+ return(tmp);
+ pResidual->totalCoeff[blockIndex] = (tmp >> 4) & 0xFF;
+ pResidual->coeffMap[blockIndex] = (tmp >> 15);
+ }
+ }
+
+ return(HANTRO_OK);
+
+}
+#endif
+
+/*------------------------------------------------------------------------------
+
+ Function: DetermineNc
+
+ Functional description:
+ Returns the nC of a block.
+
+------------------------------------------------------------------------------*/
+#ifdef H264DEC_OMXDL
+u32 DetermineNc(mbStorage_t *pMb, u32 blockIndex, u8 *pTotalCoeff)
+#else
+u32 DetermineNc(mbStorage_t *pMb, u32 blockIndex, i16 *pTotalCoeff)
+#endif
+{
+/*lint -e702 */
+/* Variables */
+
+ u32 tmp;
+ i32 n;
+ const neighbour_t *neighbourA, *neighbourB;
+ u8 neighbourAindex, neighbourBindex;
+
+/* Code */
+
+ ASSERT(blockIndex < 24);
+
+ /* if neighbour block belongs to current macroblock totalCoeff array
+ * mbStorage has not been set/updated yet -> use pTotalCoeff */
+ neighbourA = h264bsdNeighbour4x4BlockA(blockIndex);
+ neighbourB = h264bsdNeighbour4x4BlockB(blockIndex);
+ neighbourAindex = neighbourA->index;
+ neighbourBindex = neighbourB->index;
+ if (neighbourA->mb == MB_CURR && neighbourB->mb == MB_CURR)
+ {
+ n = (pTotalCoeff[neighbourAindex] +
+ pTotalCoeff[neighbourBindex] + 1)>>1;
+ }
+ else if (neighbourA->mb == MB_CURR)
+ {
+ n = pTotalCoeff[neighbourAindex];
+ if (h264bsdIsNeighbourAvailable(pMb, pMb->mbB))
+ {
+ n = (n + pMb->mbB->totalCoeff[neighbourBindex] + 1) >> 1;
+ }
+ }
+ else if (neighbourB->mb == MB_CURR)
+ {
+ n = pTotalCoeff[neighbourBindex];
+ if (h264bsdIsNeighbourAvailable(pMb, pMb->mbA))
+ {
+ n = (n + pMb->mbA->totalCoeff[neighbourAindex] + 1) >> 1;
+ }
+ }
+ else
+ {
+ n = tmp = 0;
+ if (h264bsdIsNeighbourAvailable(pMb, pMb->mbA))
+ {
+ n = pMb->mbA->totalCoeff[neighbourAindex];
+ tmp = 1;
+ }
+ if (h264bsdIsNeighbourAvailable(pMb, pMb->mbB))
+ {
+ if (tmp)
+ n = (n + pMb->mbB->totalCoeff[neighbourBindex] + 1) >> 1;
+ else
+ n = pMb->mbB->totalCoeff[neighbourBindex];
+ }
+ }
+ return((u32)n);
+/*lint +e702 */
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: CbpIntra16x16
+
+ Functional description:
+ Returns the coded block pattern for intra 16x16 macroblock.
+
+------------------------------------------------------------------------------*/
+
+u32 CbpIntra16x16(mbType_e mbType)
+{
+
+/* Variables */
+
+ u32 cbp;
+ u32 tmp;
+
+/* Code */
+
+ ASSERT(mbType >= I_16x16_0_0_0 && mbType <= I_16x16_3_2_1);
+
+ if (mbType >= I_16x16_0_0_1)
+ cbp = 15;
+ else
+ cbp = 0;
+
+ /* tmp is 0 for I_16x16_0_0_0 mb type */
+ /* ignore lint warning on arithmetic on enum's */
+ tmp = /*lint -e(656)*/(mbType - I_16x16_0_0_0) >> 2;
+ if (tmp > 2)
+ tmp -= 3;
+
+ cbp += tmp << 4;
+
+ return(cbp);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdPredModeIntra16x16
+
+ Functional description:
+ Returns the prediction mode for intra 16x16 macroblock.
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdPredModeIntra16x16(mbType_e mbType)
+{
+
+/* Variables */
+
+ u32 tmp;
+
+/* Code */
+
+ ASSERT(mbType >= I_16x16_0_0_0 && mbType <= I_16x16_3_2_1);
+
+ /* tmp is 0 for I_16x16_0_0_0 mb type */
+ /* ignore lint warning on arithmetic on enum's */
+ tmp = /*lint -e(656)*/(mbType - I_16x16_0_0_0);
+
+ return(tmp & 0x3);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdDecodeMacroblock
+
+ Functional description:
+ Decode one macroblock and write into output image.
+
+ Inputs:
+ pMb pointer to macroblock specific information
+ mbLayer pointer to current macroblock data from stream
+ currImage pointer to output image
+ dpb pointer to decoded picture buffer
+ qpY pointer to slice QP
+ mbNum current macroblock number
+ constrainedIntraPred flag specifying if neighbouring inter
+ macroblocks are used in intra prediction
+
+ Outputs:
+ pMb structure is updated with current macroblock
+ currImage decoded macroblock is written into output image
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK error in macroblock decoding
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeMacroblock(mbStorage_t *pMb, macroblockLayer_t *pMbLayer,
+ image_t *currImage, dpbStorage_t *dpb, i32 *qpY, u32 mbNum,
+ u32 constrainedIntraPredFlag, u8* data)
+{
+
+/* Variables */
+
+ u32 i, tmp;
+ mbType_e mbType;
+#ifdef H264DEC_OMXDL
+ const u8 *pSrc;
+#endif
+/* Code */
+
+ ASSERT(pMb);
+ ASSERT(pMbLayer);
+ ASSERT(currImage);
+ ASSERT(qpY && *qpY < 52);
+ ASSERT(mbNum < currImage->width*currImage->height);
+
+ mbType = pMbLayer->mbType;
+ pMb->mbType = mbType;
+
+ pMb->decoded++;
+
+ h264bsdSetCurrImageMbPointers(currImage, mbNum);
+
+ if (mbType == I_PCM)
+ {
+ u8 *pData = (u8*)data;
+#ifdef H264DEC_OMXDL
+ u8 *tot = pMb->totalCoeff;
+#else
+ i16 *tot = pMb->totalCoeff;
+#endif
+ i32 *lev = pMbLayer->residual.level[0];
+
+ pMb->qpY = 0;
+
+ /* if decoded flag > 1 -> mb has already been successfully decoded and
+ * written to output -> do not write again */
+ if (pMb->decoded > 1)
+ {
+ for (i = 24; i--;)
+ *tot++ = 16;
+ return HANTRO_OK;
+ }
+
+ for (i = 24; i--;)
+ {
+ *tot++ = 16;
+ for (tmp = 16; tmp--;)
+ *pData++ = (u8)(*lev++);
+ }
+ h264bsdWriteMacroblock(currImage, (u8*)data);
+
+ return(HANTRO_OK);
+ }
+ else
+ {
+#ifdef H264DEC_OMXDL
+ if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTER)
+ {
+ tmp = h264bsdInterPrediction(pMb, pMbLayer, dpb, mbNum,
+ currImage, (u8*)data);
+ if (tmp != HANTRO_OK) return (tmp);
+ }
+#endif
+ if (mbType != P_Skip)
+ {
+ H264SwDecMemcpy(pMb->totalCoeff,
+ pMbLayer->residual.totalCoeff,
+ 27*sizeof(*pMb->totalCoeff));
+
+ /* update qpY */
+ if (pMbLayer->mbQpDelta)
+ {
+ *qpY = *qpY + pMbLayer->mbQpDelta;
+ if (*qpY < 0) *qpY += 52;
+ else if (*qpY >= 52) *qpY -= 52;
+ }
+ pMb->qpY = (u32)*qpY;
+
+#ifdef H264DEC_OMXDL
+ pSrc = pMbLayer->residual.posCoefBuf;
+
+ if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTER)
+ {
+ OMXResult res;
+ u8 *p;
+ u8 *totalCoeff = pMb->totalCoeff;
+
+ for (i = 0; i < 16; i++, totalCoeff++)
+ {
+ p = data + lumaIndex[i];
+ if (*totalCoeff)
+ {
+ res = omxVCM4P10_DequantTransformResidualFromPairAndAdd(
+ &pSrc, p, 0, p, 16, 16, *qpY, *totalCoeff);
+ if (res != OMX_Sts_NoErr)
+ return (HANTRO_NOK);
+ }
+ }
+
+ }
+ else if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTRA4x4)
+ {
+ tmp = ProcessIntra4x4Residual(pMb,
+ data,
+ constrainedIntraPredFlag,
+ pMbLayer,
+ &pSrc,
+ currImage);
+ if (tmp != HANTRO_OK)
+ return (tmp);
+ }
+ else if (h264bsdMbPartPredMode(mbType) == PRED_MODE_INTRA16x16)
+ {
+ tmp = ProcessIntra16x16Residual(pMb,
+ data,
+ constrainedIntraPredFlag,
+ pMbLayer->mbPred.intraChromaPredMode,
+ &pSrc,
+ currImage);
+ if (tmp != HANTRO_OK)
+ return (tmp);
+ }
+
+ tmp = ProcessChromaResidual(pMb, data, &pSrc);
+
+#else
+ tmp = ProcessResidual(pMb, pMbLayer->residual.level,
+ pMbLayer->residual.coeffMap);
+#endif
+ if (tmp != HANTRO_OK)
+ return (tmp);
+ }
+ else
+ {
+ H264SwDecMemset(pMb->totalCoeff, 0, 27*sizeof(*pMb->totalCoeff));
+ pMb->qpY = (u32)*qpY;
+ }
+#ifdef H264DEC_OMXDL
+ /* if decoded flag > 1 -> mb has already been successfully decoded and
+ * written to output -> do not write again */
+ if (pMb->decoded > 1)
+ return HANTRO_OK;
+
+ h264bsdWriteMacroblock(currImage, data);
+#else
+ if (h264bsdMbPartPredMode(mbType) != PRED_MODE_INTER)
+ {
+ tmp = h264bsdIntraPrediction(pMb, pMbLayer, currImage, mbNum,
+ constrainedIntraPredFlag, (u8*)data);
+ if (tmp != HANTRO_OK) return (tmp);
+ }
+ else
+ {
+ tmp = h264bsdInterPrediction(pMb, pMbLayer, dpb, mbNum,
+ currImage, (u8*)data);
+ if (tmp != HANTRO_OK) return (tmp);
+ }
+#endif
+ }
+
+ return HANTRO_OK;
+}
+
+
+#ifdef H264DEC_OMXDL
+
+/*------------------------------------------------------------------------------
+
+ Function: ProcessChromaResidual
+
+ Functional description:
+ Process the residual data of chroma with
+ inverse quantization and inverse transform.
+
+------------------------------------------------------------------------------*/
+u32 ProcessChromaResidual(mbStorage_t *pMb, u8 *data, const u8 **pSrc )
+{
+ u32 i;
+ u32 chromaQp;
+ i16 *pDc;
+ i16 dc[4 + 4] = {0,0,0,0,0,0,0,0};
+ u8 *totalCoeff;
+ OMXResult result;
+ u8 *p;
+
+ /* chroma DC processing. First chroma dc block is block with index 25 */
+ chromaQp =
+ h264bsdQpC[CLIP3(0, 51, (i32)pMb->qpY + pMb->chromaQpIndexOffset)];
+
+ if (pMb->totalCoeff[25])
+ {
+ pDc = dc;
+ result = omxVCM4P10_TransformDequantChromaDCFromPair(
+ pSrc,
+ pDc,
+ (i32)chromaQp);
+ if (result != OMX_Sts_NoErr)
+ return (HANTRO_NOK);
+ }
+ if (pMb->totalCoeff[26])
+ {
+ pDc = dc+4;
+ result = omxVCM4P10_TransformDequantChromaDCFromPair(
+ pSrc,
+ pDc,
+ (i32)chromaQp);
+ if (result != OMX_Sts_NoErr)
+ return (HANTRO_NOK);
+ }
+
+ pDc = dc;
+ totalCoeff = pMb->totalCoeff + 16;
+ for (i = 0; i < 8; i++, pDc++, totalCoeff++)
+ {
+ /* chroma prediction */
+ if (*totalCoeff || *pDc)
+ {
+ p = data + chromaIndex[i];
+ result = omxVCM4P10_DequantTransformResidualFromPairAndAdd(
+ pSrc,
+ p,
+ pDc,
+ p,
+ 8,
+ 8,
+ (i32)chromaQp,
+ *totalCoeff);
+ if (result != OMX_Sts_NoErr)
+ return (HANTRO_NOK);
+ }
+ }
+
+ return(HANTRO_OK);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: ProcessIntra16x16Residual
+
+ Functional description:
+ Process the residual data of luma with
+ inverse quantization and inverse transform.
+
+------------------------------------------------------------------------------*/
+u32 ProcessIntra16x16Residual(mbStorage_t *pMb,
+ u8 *data,
+ u32 constrainedIntraPred,
+ u32 intraChromaPredMode,
+ const u8** pSrc,
+ image_t *image)
+{
+ u32 i;
+ i16 *pDc;
+ i16 dc[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ u8 *totalCoeff;
+ OMXResult result;
+ u8 *p;
+
+ totalCoeff = pMb->totalCoeff;
+
+ if (totalCoeff[24])
+ {
+ pDc = dc;
+ result = omxVCM4P10_TransformDequantLumaDCFromPair(
+ pSrc,
+ pDc,
+ (i32)pMb->qpY);
+ if (result != OMX_Sts_NoErr)
+ return (HANTRO_NOK);
+ }
+ /* Intra 16x16 pred */
+ if (h264bsdIntra16x16Prediction(pMb, data, image->luma,
+ image->width*16, constrainedIntraPred) != HANTRO_OK)
+ return(HANTRO_NOK);
+ for (i = 0; i < 16; i++, totalCoeff++)
+ {
+ p = data + lumaIndex[i];
+ pDc = &dc[dcCoeffIndex[i]];
+ if (*totalCoeff || *pDc)
+ {
+ result = omxVCM4P10_DequantTransformResidualFromPairAndAdd(
+ pSrc,
+ p,
+ pDc,
+ p,
+ 16,
+ 16,
+ (i32)pMb->qpY,
+ *totalCoeff);
+ if (result != OMX_Sts_NoErr)
+ return (HANTRO_NOK);
+ }
+ }
+
+ if (h264bsdIntraChromaPrediction(pMb, data + 256,
+ image,
+ intraChromaPredMode,
+ constrainedIntraPred) != HANTRO_OK)
+ return(HANTRO_NOK);
+
+ return HANTRO_OK;
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: ProcessIntra4x4Residual
+
+ Functional description:
+ Process the residual data of luma with
+ inverse quantization and inverse transform.
+
+------------------------------------------------------------------------------*/
+u32 ProcessIntra4x4Residual(mbStorage_t *pMb,
+ u8 *data,
+ u32 constrainedIntraPred,
+ macroblockLayer_t *mbLayer,
+ const u8 **pSrc,
+ image_t *image)
+{
+ u32 i;
+ u8 *totalCoeff;
+ OMXResult result;
+ u8 *p;
+
+ totalCoeff = pMb->totalCoeff;
+
+ for (i = 0; i < 16; i++, totalCoeff++)
+ {
+ p = data + lumaIndex[i];
+ if (h264bsdIntra4x4Prediction(pMb, p, mbLayer, image->luma,
+ image->width*16, constrainedIntraPred, i) != HANTRO_OK)
+ return(HANTRO_NOK);
+
+ if (*totalCoeff)
+ {
+ result = omxVCM4P10_DequantTransformResidualFromPairAndAdd(
+ pSrc,
+ p,
+ NULL,
+ p,
+ 16,
+ 16,
+ (i32)pMb->qpY,
+ *totalCoeff);
+ if (result != OMX_Sts_NoErr)
+ return (HANTRO_NOK);
+ }
+ }
+
+ if (h264bsdIntraChromaPrediction(pMb, data + 256,
+ image,
+ mbLayer->mbPred.intraChromaPredMode,
+ constrainedIntraPred) != HANTRO_OK)
+ return(HANTRO_NOK);
+
+ return HANTRO_OK;
+}
+
+#else /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+
+ Function: ProcessResidual
+
+ Functional description:
+ Process the residual data of one macroblock with
+ inverse quantization and inverse transform.
+
+------------------------------------------------------------------------------*/
+
+u32 ProcessResidual(mbStorage_t *pMb, i32 residualLevel[][16], u32 *coeffMap)
+{
+
+/* Variables */
+
+ u32 i;
+ u32 chromaQp;
+ i32 (*blockData)[16];
+ i32 (*blockDc)[16];
+ i16 *totalCoeff;
+ i32 *chromaDc;
+ const u32 *dcCoeffIdx;
+
+/* Code */
+
+ ASSERT(pMb);
+ ASSERT(residualLevel);
+
+ /* set pointers to DC coefficient blocks */
+ blockDc = residualLevel + 24;
+
+ blockData = residualLevel;
+ totalCoeff = pMb->totalCoeff;
+ if (h264bsdMbPartPredMode(pMb->mbType) == PRED_MODE_INTRA16x16)
+ {
+ if (totalCoeff[24])
+ {
+ h264bsdProcessLumaDc(*blockDc, pMb->qpY);
+ }
+ dcCoeffIdx = dcCoeffIndex;
+
+ for (i = 16; i--; blockData++, totalCoeff++, coeffMap++)
+ {
+ /* set dc coefficient of luma block */
+ (*blockData)[0] = (*blockDc)[*dcCoeffIdx++];
+ if ((*blockData)[0] || *totalCoeff)
+ {
+ if (h264bsdProcessBlock(*blockData, pMb->qpY, 1, *coeffMap) !=
+ HANTRO_OK)
+ return(HANTRO_NOK);
+ }
+ else
+ MARK_RESIDUAL_EMPTY(*blockData);
+ }
+ }
+ else
+ {
+ for (i = 16; i--; blockData++, totalCoeff++, coeffMap++)
+ {
+ if (*totalCoeff)
+ {
+ if (h264bsdProcessBlock(*blockData, pMb->qpY, 0, *coeffMap) !=
+ HANTRO_OK)
+ return(HANTRO_NOK);
+ }
+ else
+ MARK_RESIDUAL_EMPTY(*blockData);
+ }
+ }
+
+ /* chroma DC processing. First chroma dc block is block with index 25 */
+ chromaQp =
+ h264bsdQpC[CLIP3(0, 51, (i32)pMb->qpY + pMb->chromaQpIndexOffset)];
+ if (pMb->totalCoeff[25] || pMb->totalCoeff[26])
+ h264bsdProcessChromaDc(residualLevel[25], chromaQp);
+ chromaDc = residualLevel[25];
+ for (i = 8; i--; blockData++, totalCoeff++, coeffMap++)
+ {
+ /* set dc coefficient of chroma block */
+ (*blockData)[0] = *chromaDc++;
+ if ((*blockData)[0] || *totalCoeff)
+ {
+ if (h264bsdProcessBlock(*blockData, chromaQp, 1,*coeffMap) !=
+ HANTRO_OK)
+ return(HANTRO_NOK);
+ }
+ else
+ MARK_RESIDUAL_EMPTY(*blockData);
+ }
+
+ return(HANTRO_OK);
+}
+#endif /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdSubMbPartMode
+
+ Functional description:
+ Returns the macroblock's sub-partition mode.
+
+------------------------------------------------------------------------------*/
+
+subMbPartMode_e h264bsdSubMbPartMode(subMbType_e subMbType)
+{
+
+/* Variables */
+
+
+/* Code */
+
+ ASSERT(subMbType < 4);
+
+ return((subMbPartMode_e)subMbType);
+
+}
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.h
new file mode 100755
index 0000000..32bc340
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_macroblock_layer.h
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_MACROBLOCK_LAYER_H
+#define H264SWDEC_MACROBLOCK_LAYER_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_stream.h"
+#include "h264bsd_image.h"
+#include "h264bsd_dpb.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/* Macro to determine if a mb is an intra mb */
+#define IS_INTRA_MB(a) ((a).mbType > 5)
+
+/* Macro to determine if a mb is an I_PCM mb */
+#define IS_I_PCM_MB(a) ((a).mbType == 31)
+
+typedef enum {
+ P_Skip = 0,
+ P_L0_16x16 = 1,
+ P_L0_L0_16x8 = 2,
+ P_L0_L0_8x16 = 3,
+ P_8x8 = 4,
+ P_8x8ref0 = 5,
+ I_4x4 = 6,
+ I_16x16_0_0_0 = 7,
+ I_16x16_1_0_0 = 8,
+ I_16x16_2_0_0 = 9,
+ I_16x16_3_0_0 = 10,
+ I_16x16_0_1_0 = 11,
+ I_16x16_1_1_0 = 12,
+ I_16x16_2_1_0 = 13,
+ I_16x16_3_1_0 = 14,
+ I_16x16_0_2_0 = 15,
+ I_16x16_1_2_0 = 16,
+ I_16x16_2_2_0 = 17,
+ I_16x16_3_2_0 = 18,
+ I_16x16_0_0_1 = 19,
+ I_16x16_1_0_1 = 20,
+ I_16x16_2_0_1 = 21,
+ I_16x16_3_0_1 = 22,
+ I_16x16_0_1_1 = 23,
+ I_16x16_1_1_1 = 24,
+ I_16x16_2_1_1 = 25,
+ I_16x16_3_1_1 = 26,
+ I_16x16_0_2_1 = 27,
+ I_16x16_1_2_1 = 28,
+ I_16x16_2_2_1 = 29,
+ I_16x16_3_2_1 = 30,
+ I_PCM = 31
+} mbType_e;
+
+typedef enum {
+ P_L0_8x8 = 0,
+ P_L0_8x4 = 1,
+ P_L0_4x8 = 2,
+ P_L0_4x4 = 3
+} subMbType_e;
+
+typedef enum {
+ MB_P_16x16 = 0,
+ MB_P_16x8,
+ MB_P_8x16,
+ MB_P_8x8
+} mbPartMode_e;
+
+typedef enum {
+ MB_SP_8x8 = 0,
+ MB_SP_8x4,
+ MB_SP_4x8,
+ MB_SP_4x4
+} subMbPartMode_e;
+
+typedef enum {
+ PRED_MODE_INTRA4x4 = 0,
+ PRED_MODE_INTRA16x16 ,
+ PRED_MODE_INTER
+} mbPartPredMode_e;
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+typedef struct
+{
+ /* MvPrediction16x16 assumes that MVs are 16bits */
+ i16 hor;
+ i16 ver;
+} mv_t;
+
+typedef struct
+{
+ u32 prevIntra4x4PredModeFlag[16];
+ u32 remIntra4x4PredMode[16];
+ u32 intraChromaPredMode;
+ u32 refIdxL0[4];
+ mv_t mvdL0[4];
+} mbPred_t;
+
+typedef struct
+{
+ subMbType_e subMbType[4];
+ u32 refIdxL0[4];
+ mv_t mvdL0[4][4];
+} subMbPred_t;
+
+typedef struct
+{
+#ifdef H264DEC_OMXDL
+ u8 posCoefBuf[27*16*3];
+ u8 totalCoeff[27];
+#else
+ i16 totalCoeff[27];
+#endif
+ i32 level[26][16];
+ u32 coeffMap[24];
+} residual_t;
+
+typedef struct
+{
+ mbType_e mbType;
+ u32 codedBlockPattern;
+ i32 mbQpDelta;
+ mbPred_t mbPred;
+ subMbPred_t subMbPred;
+ residual_t residual;
+} macroblockLayer_t;
+
+typedef struct mbStorage
+{
+ mbType_e mbType;
+ u32 sliceId;
+ u32 disableDeblockingFilterIdc;
+ i32 filterOffsetA;
+ i32 filterOffsetB;
+ u32 qpY;
+ i32 chromaQpIndexOffset;
+#ifdef H264DEC_OMXDL
+ u8 totalCoeff[27];
+#else
+ i16 totalCoeff[27];
+#endif
+ u8 intra4x4PredMode[16];
+ u32 refPic[4];
+ u8* refAddr[4];
+ mv_t mv[16];
+ u32 decoded;
+ struct mbStorage *mbA;
+ struct mbStorage *mbB;
+ struct mbStorage *mbC;
+ struct mbStorage *mbD;
+} mbStorage_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeMacroblockLayer(strmData_t *pStrmData,
+ macroblockLayer_t *pMbLayer, mbStorage_t *pMb, u32 sliceType,
+ u32 numRefIdxActive);
+
+u32 h264bsdNumMbPart(mbType_e mbType);
+u32 h264bsdNumSubMbPart(subMbType_e subMbType);
+
+subMbPartMode_e h264bsdSubMbPartMode(subMbType_e subMbType);
+
+u32 h264bsdDecodeMacroblock(mbStorage_t *pMb, macroblockLayer_t *pMbLayer,
+ image_t *currImage, dpbStorage_t *dpb, i32 *qpY, u32 mbNum,
+ u32 constrainedIntraPredFlag, u8* data);
+
+u32 h264bsdPredModeIntra16x16(mbType_e mbType);
+
+mbPartPredMode_e h264bsdMbPartPredMode(mbType_e mbType);
+#ifdef H264DEC_NEON
+u32 h264bsdClearMbLayer(macroblockLayer_t *pMbLayer, u32 size);
+#endif
+
+#endif /* #ifdef H264SWDEC_MACROBLOCK_LAYER_H */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.c
new file mode 100755
index 0000000..e44c43a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.c
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdDecodeNalUnit
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_nal_unit.h"
+#include "h264bsd_util.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+
+ Function name: h264bsdDecodeNalUnit
+
+ Functional description:
+ Decode NAL unit header information
+
+ Inputs:
+ pStrmData pointer to stream data structure
+
+ Outputs:
+ pNalUnit NAL unit header information is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid NAL unit header information
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeNalUnit(strmData_t *pStrmData, nalUnit_t *pNalUnit)
+{
+
+/* Variables */
+
+ u32 tmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pNalUnit);
+ ASSERT(pStrmData->bitPosInWord == 0);
+
+ /* forbidden_zero_bit (not checked to be zero, errors ignored) */
+ tmp = h264bsdGetBits(pStrmData, 1);
+ /* Assuming that NAL unit starts from byte boundary ­> don't have to check
+ * following 7 bits for END_OF_STREAM */
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetBits(pStrmData, 2);
+ pNalUnit->nalRefIdc = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 5);
+ pNalUnit->nalUnitType = (nalUnitType_e)tmp;
+
+ /* data partitioning NAL units not supported */
+ if ( (tmp == 2) || (tmp == 3) || (tmp == 4) )
+ {
+ return(HANTRO_NOK);
+ }
+
+ /* nal_ref_idc shall not be zero for these nal_unit_types */
+ if ( ( (tmp == NAL_SEQ_PARAM_SET) || (tmp == NAL_PIC_PARAM_SET) ||
+ (tmp == NAL_CODED_SLICE_IDR) ) && (pNalUnit->nalRefIdc == 0) )
+ {
+ return(HANTRO_NOK);
+ }
+ /* nal_ref_idc shall be zero for these nal_unit_types */
+ else if ( ( (tmp == NAL_SEI) || (tmp == NAL_ACCESS_UNIT_DELIMITER) ||
+ (tmp == NAL_END_OF_SEQUENCE) || (tmp == NAL_END_OF_STREAM) ||
+ (tmp == NAL_FILLER_DATA) ) && (pNalUnit->nalRefIdc != 0) )
+ {
+ return(HANTRO_NOK);
+ }
+
+ return(HANTRO_OK);
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.h
new file mode 100755
index 0000000..38957bf
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_nal_unit.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_NAL_UNIT_H
+#define H264SWDEC_NAL_UNIT_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_stream.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/* macro to determine if NAL unit pointed by pNalUnit contains an IDR slice */
+#define IS_IDR_NAL_UNIT(pNalUnit) \
+ ((pNalUnit)->nalUnitType == NAL_CODED_SLICE_IDR)
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+typedef enum {
+ NAL_CODED_SLICE = 1,
+ NAL_CODED_SLICE_IDR = 5,
+ NAL_SEI = 6,
+ NAL_SEQ_PARAM_SET = 7,
+ NAL_PIC_PARAM_SET = 8,
+ NAL_ACCESS_UNIT_DELIMITER = 9,
+ NAL_END_OF_SEQUENCE = 10,
+ NAL_END_OF_STREAM = 11,
+ NAL_FILLER_DATA = 12,
+ NAL_MAX_TYPE_VALUE = 31
+} nalUnitType_e;
+
+typedef struct
+{
+ nalUnitType_e nalUnitType;
+ u32 nalRefIdc;
+} nalUnit_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeNalUnit(strmData_t *pStrmData, nalUnit_t *pNalUnit);
+
+#endif /* #ifdef H264SWDEC_NAL_UNIT_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.c
new file mode 100755
index 0000000..ce5eeff
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.c
@@ -0,0 +1,382 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdInitMbNeighbours
+ h264bsdGetNeighbourMb
+ h264bsdNeighbour4x4BlockA
+ h264bsdNeighbour4x4BlockB
+ h264bsdNeighbour4x4BlockC
+ h264bsdNeighbour4x4BlockD
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_neighbour.h"
+#include "h264bsd_util.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/* Following four tables indicate neighbours of each block of a macroblock.
+ * First 16 values are for luma blocks, next 4 values for Cb and last 4
+ * values for Cr. Elements of the table indicate to which macroblock the
+ * neighbour block belongs and the index of the neighbour block in question.
+ * Indexing of the blocks goes as follows
+ *
+ * Y Cb Cr
+ * 0 1 4 5 16 17 20 21
+ * 2 3 6 7 18 19 22 23
+ * 8 9 12 13
+ * 10 11 14 15
+ */
+
+/* left neighbour for each block */
+static const neighbour_t N_A_4x4B[24] = {
+ {MB_A,5}, {MB_CURR,0}, {MB_A,7}, {MB_CURR,2},
+ {MB_CURR,1}, {MB_CURR,4}, {MB_CURR,3}, {MB_CURR,6},
+ {MB_A,13}, {MB_CURR,8}, {MB_A,15}, {MB_CURR,10},
+ {MB_CURR,9}, {MB_CURR,12},{MB_CURR,11},{MB_CURR,14},
+ {MB_A,17}, {MB_CURR,16},{MB_A,19}, {MB_CURR,18},
+ {MB_A,21}, {MB_CURR,20},{MB_A,23}, {MB_CURR,22} };
+
+/* above neighbour for each block */
+static const neighbour_t N_B_4x4B[24] = {
+ {MB_B,10}, {MB_B,11}, {MB_CURR,0}, {MB_CURR,1},
+ {MB_B,14}, {MB_B,15}, {MB_CURR,4}, {MB_CURR,5},
+ {MB_CURR,2}, {MB_CURR,3}, {MB_CURR,8}, {MB_CURR,9},
+ {MB_CURR,6}, {MB_CURR,7}, {MB_CURR,12},{MB_CURR,13},
+ {MB_B,18}, {MB_B,19}, {MB_CURR,16},{MB_CURR,17},
+ {MB_B,22}, {MB_B,23}, {MB_CURR,20},{MB_CURR,21} };
+
+/* above-right neighbour for each block */
+static const neighbour_t N_C_4x4B[24] = {
+ {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_NA,4},
+ {MB_B,15}, {MB_C,10}, {MB_CURR,5}, {MB_NA,0},
+ {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_NA,12},
+ {MB_CURR,7}, {MB_NA,2}, {MB_CURR,13},{MB_NA,8},
+ {MB_B,19}, {MB_C,18}, {MB_CURR,17},{MB_NA,16},
+ {MB_B,23}, {MB_C,22}, {MB_CURR,21},{MB_NA,20} };
+
+/* above-left neighbour for each block */
+static const neighbour_t N_D_4x4B[24] = {
+ {MB_D,15}, {MB_B,10}, {MB_A,5}, {MB_CURR,0},
+ {MB_B,11}, {MB_B,14}, {MB_CURR,1}, {MB_CURR,4},
+ {MB_A,7}, {MB_CURR,2}, {MB_A,13}, {MB_CURR,8},
+ {MB_CURR,3}, {MB_CURR,6}, {MB_CURR,9}, {MB_CURR,12},
+ {MB_D,19}, {MB_B,18}, {MB_A,17}, {MB_CURR,16},
+ {MB_D,23}, {MB_B,22}, {MB_A,21}, {MB_CURR,20} };
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInitMbNeighbours
+
+ Functional description:
+ Initialize macroblock neighbours. Function sets neighbour
+ macroblock pointers in macroblock structures to point to
+ macroblocks on the left, above, above-right and above-left.
+ Pointers are set NULL if the neighbour does not fit into the
+ picture.
+
+ Inputs:
+ picWidth width of the picture in macroblocks
+ picSizeInMbs no need to clarify
+
+ Outputs:
+ pMbStorage neighbour pointers of each mbStorage structure
+ stored here
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void h264bsdInitMbNeighbours(mbStorage_t *pMbStorage, u32 picWidth,
+ u32 picSizeInMbs)
+{
+
+/* Variables */
+
+ u32 i, row, col;
+
+/* Code */
+
+ ASSERT(pMbStorage);
+ ASSERT(picWidth);
+ ASSERT(picWidth <= picSizeInMbs);
+ ASSERT(((picSizeInMbs / picWidth) * picWidth) == picSizeInMbs);
+
+ row = col = 0;
+
+ for (i = 0; i < picSizeInMbs; i++)
+ {
+
+ if (col)
+ pMbStorage[i].mbA = pMbStorage + i - 1;
+ else
+ pMbStorage[i].mbA = NULL;
+
+ if (row)
+ pMbStorage[i].mbB = pMbStorage + i - picWidth;
+ else
+ pMbStorage[i].mbB = NULL;
+
+ if (row && (col < picWidth - 1))
+ pMbStorage[i].mbC = pMbStorage + i - (picWidth - 1);
+ else
+ pMbStorage[i].mbC = NULL;
+
+ if (row && col)
+ pMbStorage[i].mbD = pMbStorage + i - (picWidth + 1);
+ else
+ pMbStorage[i].mbD = NULL;
+
+ col++;
+ if (col == picWidth)
+ {
+ col = 0;
+ row++;
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdGetNeighbourMb
+
+ Functional description:
+ Get pointer to neighbour macroblock.
+
+ Inputs:
+ pMb pointer to macroblock structure of the macroblock
+ whose neighbour is wanted
+ neighbour indicates which neighbour is wanted
+
+ Outputs:
+ none
+
+ Returns:
+ pointer to neighbour macroblock
+ NULL if not available
+
+------------------------------------------------------------------------------*/
+
+mbStorage_t* h264bsdGetNeighbourMb(mbStorage_t *pMb, neighbourMb_e neighbour)
+{
+
+/* Variables */
+
+
+/* Code */
+
+ ASSERT((neighbour <= MB_CURR) || (neighbour == MB_NA));
+
+ if (neighbour == MB_A)
+ return(pMb->mbA);
+ else if (neighbour == MB_B)
+ return(pMb->mbB);
+ else if (neighbour == MB_C)
+ return(pMb->mbC);
+ else if (neighbour == MB_D)
+ return(pMb->mbD);
+ else if (neighbour == MB_CURR)
+ return(pMb);
+ else
+ return(NULL);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdNeighbour4x4BlockA
+
+ Functional description:
+ Get left neighbour of the block. Function returns pointer to
+ the table defined in the beginning of the file.
+
+ Inputs:
+ blockIndex indicates the block whose neighbours are wanted
+
+ Outputs:
+
+ Returns:
+ pointer to neighbour structure
+
+------------------------------------------------------------------------------*/
+
+const neighbour_t* h264bsdNeighbour4x4BlockA(u32 blockIndex)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(blockIndex < 24);
+
+ return(N_A_4x4B+blockIndex);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdNeighbour4x4BlockB
+
+ Functional description:
+ Get above neighbour of the block. Function returns pointer to
+ the table defined in the beginning of the file.
+
+ Inputs:
+ blockIndex indicates the block whose neighbours are wanted
+
+ Outputs:
+
+ Returns:
+ pointer to neighbour structure
+
+------------------------------------------------------------------------------*/
+
+const neighbour_t* h264bsdNeighbour4x4BlockB(u32 blockIndex)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(blockIndex < 24);
+
+ return(N_B_4x4B+blockIndex);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdNeighbour4x4BlockC
+
+ Functional description:
+ Get above-right neighbour of the block. Function returns pointer
+ to the table defined in the beginning of the file.
+
+ Inputs:
+ blockIndex indicates the block whose neighbours are wanted
+
+ Outputs:
+
+ Returns:
+ pointer to neighbour structure
+
+------------------------------------------------------------------------------*/
+
+const neighbour_t* h264bsdNeighbour4x4BlockC(u32 blockIndex)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(blockIndex < 24);
+
+ return(N_C_4x4B+blockIndex);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdNeighbour4x4BlockD
+
+ Functional description:
+ Get above-left neighbour of the block. Function returns pointer to
+ the table defined in the beginning of the file.
+
+ Inputs:
+ blockIndex indicates the block whose neighbours are wanted
+
+ Outputs:
+
+ Returns:
+ pointer to neighbour structure
+
+------------------------------------------------------------------------------*/
+
+const neighbour_t* h264bsdNeighbour4x4BlockD(u32 blockIndex)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(blockIndex < 24);
+
+ return(N_D_4x4B+blockIndex);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdIsNeighbourAvailable
+
+ Functional description:
+ Check if neighbour macroblock is available. Neighbour macroblock
+ is considered available if it is within the picture and belongs
+ to the same slice as the current macroblock.
+
+ Inputs:
+ pMb pointer to the current macroblock
+ pNeighbour pointer to the neighbour macroblock
+
+ Outputs:
+ none
+
+ Returns:
+ TRUE neighbour is available
+ FALSE neighbour is not available
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdIsNeighbourAvailable(mbStorage_t *pMb, mbStorage_t *pNeighbour)
+{
+
+/* Variables */
+
+/* Code */
+
+ if ( (pNeighbour == NULL) || (pMb->sliceId != pNeighbour->sliceId) )
+ return(HANTRO_FALSE);
+ else
+ return(HANTRO_TRUE);
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.h
new file mode 100755
index 0000000..fce0ad1
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_neighbour.h
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_NEIGHBOUR_H
+#define H264SWDEC_NEIGHBOUR_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_macroblock_layer.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+typedef enum {
+ MB_A = 0,
+ MB_B,
+ MB_C,
+ MB_D,
+ MB_CURR,
+ MB_NA = 0xFF
+} neighbourMb_e;
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+typedef struct
+{
+ neighbourMb_e mb;
+ u8 index;
+} neighbour_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+void h264bsdInitMbNeighbours(mbStorage_t *pMbStorage, u32 picWidth,
+ u32 picSizeInMbs);
+
+mbStorage_t* h264bsdGetNeighbourMb(mbStorage_t *pMb, neighbourMb_e neighbour);
+
+u32 h264bsdIsNeighbourAvailable(mbStorage_t *pMb, mbStorage_t *pNeighbour);
+
+const neighbour_t* h264bsdNeighbour4x4BlockA(u32 blockIndex);
+const neighbour_t* h264bsdNeighbour4x4BlockB(u32 blockIndex);
+const neighbour_t* h264bsdNeighbour4x4BlockC(u32 blockIndex);
+const neighbour_t* h264bsdNeighbour4x4BlockD(u32 blockIndex);
+
+#endif /* #ifdef H264SWDEC_NEIGHBOUR_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.c
new file mode 100755
index 0000000..fb23352
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.c
@@ -0,0 +1,347 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdDecodePicOrderCnt
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_util.h"
+#include "h264bsd_pic_order_cnt.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdDecodePicOrderCnt
+
+ Functional description:
+ Compute picture order count for a picture. Function implements
+ computation of all POC types (0, 1 and 2), type is obtained from
+ sps. See standard for description of the POC types and how POC is
+ computed for each type.
+
+ Function returns the minimum of top field and bottom field pic
+ order counts.
+
+ Inputs:
+ poc pointer to previous results
+ sps pointer to sequence parameter set
+ slicHeader pointer to current slice header, frame number and
+ other params needed for POC computation
+ pNalUnit pointer to current NAL unit structrue, function needs
+ to know if this is an IDR picture and also if this is
+ a reference picture
+
+ Outputs:
+ poc results stored here for computation of next POC
+
+ Returns:
+ picture order count
+
+------------------------------------------------------------------------------*/
+
+i32 h264bsdDecodePicOrderCnt(pocStorage_t *poc, seqParamSet_t *sps,
+ sliceHeader_t *pSliceHeader, nalUnit_t *pNalUnit)
+{
+
+/* Variables */
+
+ u32 i;
+ i32 picOrderCnt;
+ u32 frameNumOffset, absFrameNum, picOrderCntCycleCnt;
+ u32 frameNumInPicOrderCntCycle;
+ i32 expectedDeltaPicOrderCntCycle;
+ u32 containsMmco5;
+
+/* Code */
+
+ ASSERT(poc);
+ ASSERT(sps);
+ ASSERT(pSliceHeader);
+ ASSERT(pNalUnit);
+ ASSERT(sps->picOrderCntType <= 2);
+
+#if 0
+ /* JanSa: I don't think this is necessary, don't see any reason to
+ * increment prevFrameNum one by one instead of one big increment.
+ * However, standard specifies that this should be done -> if someone
+ * figures out any case when the outcome would be different for step by
+ * step increment, this part of the code should be enabled */
+
+ /* if there was a gap in frame numbering and picOrderCntType is 1 or 2 ->
+ * "compute" pic order counts for non-existing frames. These are not
+ * actually computed, but process needs to be done to update the
+ * prevFrameNum and prevFrameNumOffset */
+ if ( sps->picOrderCntType > 0 &&
+ pSliceHeader->frameNum != poc->prevFrameNum &&
+ pSliceHeader->frameNum != ((poc->prevFrameNum + 1) % sps->maxFrameNum))
+ {
+
+ /* use variable i for unUsedShortTermFrameNum */
+ i = (poc->prevFrameNum + 1) % sps->maxFrameNum;
+
+ do
+ {
+ if (poc->prevFrameNum > i)
+ frameNumOffset = poc->prevFrameNumOffset + sps->maxFrameNum;
+ else
+ frameNumOffset = poc->prevFrameNumOffset;
+
+ poc->prevFrameNumOffset = frameNumOffset;
+ poc->prevFrameNum = i;
+
+ i = (i + 1) % sps->maxFrameNum;
+
+ } while (i != pSliceHeader->frameNum);
+ }
+#endif
+
+ /* check if current slice includes mmco equal to 5 */
+ containsMmco5 = HANTRO_FALSE;
+ if (pSliceHeader->decRefPicMarking.adaptiveRefPicMarkingModeFlag)
+ {
+ i = 0;
+ while (pSliceHeader->decRefPicMarking.operation[i].
+ memoryManagementControlOperation)
+ {
+ if (pSliceHeader->decRefPicMarking.operation[i].
+ memoryManagementControlOperation == 5)
+ {
+ containsMmco5 = HANTRO_TRUE;
+ break;
+ }
+ i++;
+ }
+ }
+ switch (sps->picOrderCntType)
+ {
+
+ case 0:
+ /* set prevPicOrderCnt values for IDR frame */
+ if (IS_IDR_NAL_UNIT(pNalUnit))
+ {
+ poc->prevPicOrderCntMsb = 0;
+ poc->prevPicOrderCntLsb = 0;
+ }
+
+ /* compute picOrderCntMsb (stored in picOrderCnt variable) */
+ if ( (pSliceHeader->picOrderCntLsb < poc->prevPicOrderCntLsb) &&
+ ((poc->prevPicOrderCntLsb - pSliceHeader->picOrderCntLsb) >=
+ sps->maxPicOrderCntLsb/2) )
+ {
+ picOrderCnt = poc->prevPicOrderCntMsb +
+ (i32)sps->maxPicOrderCntLsb;
+ }
+ else if ((pSliceHeader->picOrderCntLsb > poc->prevPicOrderCntLsb) &&
+ ((pSliceHeader->picOrderCntLsb - poc->prevPicOrderCntLsb) >
+ sps->maxPicOrderCntLsb/2) )
+ {
+ picOrderCnt = poc->prevPicOrderCntMsb -
+ (i32)sps->maxPicOrderCntLsb;
+ }
+ else
+ picOrderCnt = poc->prevPicOrderCntMsb;
+
+ /* standard specifies that prevPicOrderCntMsb is from previous
+ * rererence frame -> replace old value only if current frame is
+ * rererence frame */
+ if (pNalUnit->nalRefIdc)
+ poc->prevPicOrderCntMsb = picOrderCnt;
+
+ /* compute top field order cnt (stored in picOrderCnt) */
+ picOrderCnt += (i32)pSliceHeader->picOrderCntLsb;
+
+ /* if delta for bottom field is negative -> bottom will be the
+ * minimum pic order count */
+ if (pSliceHeader->deltaPicOrderCntBottom < 0)
+ picOrderCnt += pSliceHeader->deltaPicOrderCntBottom;
+
+ /* standard specifies that prevPicOrderCntLsb is from previous
+ * rererence frame -> replace old value only if current frame is
+ * rererence frame */
+ if (pNalUnit->nalRefIdc)
+ {
+ /* if current frame contains mmco5 -> modify values to be
+ * stored */
+ if (containsMmco5)
+ {
+ poc->prevPicOrderCntMsb = 0;
+ /* prevPicOrderCntLsb should be the top field picOrderCnt
+ * if previous frame included mmco5. Top field picOrderCnt
+ * for frames containing mmco5 is obtained by subtracting
+ * the picOrderCnt from original top field order count ->
+ * value is zero if top field was the minimum, i.e. delta
+ * for bottom was positive, otherwise value is
+ * -deltaPicOrderCntBottom */
+ if (pSliceHeader->deltaPicOrderCntBottom < 0)
+ poc->prevPicOrderCntLsb =
+ (u32)(-pSliceHeader->deltaPicOrderCntBottom);
+ else
+ poc->prevPicOrderCntLsb = 0;
+ picOrderCnt = 0;
+ }
+ else
+ {
+ poc->prevPicOrderCntLsb = pSliceHeader->picOrderCntLsb;
+ }
+ }
+
+ break;
+
+ case 1:
+
+ /* step 1 (in the description in the standard) */
+ if (IS_IDR_NAL_UNIT(pNalUnit))
+ frameNumOffset = 0;
+ else if (poc->prevFrameNum > pSliceHeader->frameNum)
+ frameNumOffset = poc->prevFrameNumOffset + sps->maxFrameNum;
+ else
+ frameNumOffset = poc->prevFrameNumOffset;
+
+ /* step 2 */
+ if (sps->numRefFramesInPicOrderCntCycle)
+ absFrameNum = frameNumOffset + pSliceHeader->frameNum;
+ else
+ absFrameNum = 0;
+
+ if (pNalUnit->nalRefIdc == 0 && absFrameNum > 0)
+ absFrameNum -= 1;
+
+ /* step 3 */
+ if (absFrameNum > 0)
+ {
+ picOrderCntCycleCnt =
+ (absFrameNum - 1)/sps->numRefFramesInPicOrderCntCycle;
+ frameNumInPicOrderCntCycle =
+ (absFrameNum - 1)%sps->numRefFramesInPicOrderCntCycle;
+ }
+
+ /* step 4 */
+ expectedDeltaPicOrderCntCycle = 0;
+ for (i = 0; i < sps->numRefFramesInPicOrderCntCycle; i++)
+ expectedDeltaPicOrderCntCycle += sps->offsetForRefFrame[i];
+
+ /* step 5 (picOrderCnt used to store expectedPicOrderCnt) */
+ /*lint -esym(644,picOrderCntCycleCnt) always initialized */
+ /*lint -esym(644,frameNumInPicOrderCntCycle) always initialized */
+ if (absFrameNum > 0)
+ {
+ picOrderCnt =
+ (i32)picOrderCntCycleCnt * expectedDeltaPicOrderCntCycle;
+ for (i = 0; i <= frameNumInPicOrderCntCycle; i++)
+ picOrderCnt += sps->offsetForRefFrame[i];
+ }
+ else
+ picOrderCnt = 0;
+
+ if (pNalUnit->nalRefIdc == 0)
+ picOrderCnt += sps->offsetForNonRefPic;
+
+ /* step 6 (picOrderCnt is top field order cnt if delta for bottom
+ * is positive, otherwise it is bottom field order cnt) */
+ picOrderCnt += pSliceHeader->deltaPicOrderCnt[0];
+
+ if ( (sps->offsetForTopToBottomField +
+ pSliceHeader->deltaPicOrderCnt[1]) < 0 )
+ {
+ picOrderCnt += sps->offsetForTopToBottomField +
+ pSliceHeader->deltaPicOrderCnt[1];
+ }
+
+ /* if current picture contains mmco5 -> set prevFrameNumOffset and
+ * prevFrameNum to 0 for computation of picOrderCnt of next
+ * frame, otherwise store frameNum and frameNumOffset to poc
+ * structure */
+ if (!containsMmco5)
+ {
+ poc->prevFrameNumOffset = frameNumOffset;
+ poc->prevFrameNum = pSliceHeader->frameNum;
+ }
+ else
+ {
+ poc->prevFrameNumOffset = 0;
+ poc->prevFrameNum = 0;
+ picOrderCnt = 0;
+ }
+ break;
+
+ default: /* case 2 */
+ /* derive frameNumOffset */
+ if (IS_IDR_NAL_UNIT(pNalUnit))
+ frameNumOffset = 0;
+ else if (poc->prevFrameNum > pSliceHeader->frameNum)
+ frameNumOffset = poc->prevFrameNumOffset + sps->maxFrameNum;
+ else
+ frameNumOffset = poc->prevFrameNumOffset;
+
+ /* derive picOrderCnt (type 2 has same value for top and bottom
+ * field order cnts) */
+ if (IS_IDR_NAL_UNIT(pNalUnit))
+ picOrderCnt = 0;
+ else if (pNalUnit->nalRefIdc == 0)
+ picOrderCnt =
+ 2 * (i32)(frameNumOffset + pSliceHeader->frameNum) - 1;
+ else
+ picOrderCnt =
+ 2 * (i32)(frameNumOffset + pSliceHeader->frameNum);
+
+ /* if current picture contains mmco5 -> set prevFrameNumOffset and
+ * prevFrameNum to 0 for computation of picOrderCnt of next
+ * frame, otherwise store frameNum and frameNumOffset to poc
+ * structure */
+ if (!containsMmco5)
+ {
+ poc->prevFrameNumOffset = frameNumOffset;
+ poc->prevFrameNum = pSliceHeader->frameNum;
+ }
+ else
+ {
+ poc->prevFrameNumOffset = 0;
+ poc->prevFrameNum = 0;
+ picOrderCnt = 0;
+ }
+ break;
+
+ }
+
+ /*lint -esym(644,picOrderCnt) always initialized */
+ return(picOrderCnt);
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.h
new file mode 100755
index 0000000..19741eb
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_order_cnt.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_PIC_ORDER_CNT_H
+#define H264SWDEC_PIC_ORDER_CNT_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_seq_param_set.h"
+#include "h264bsd_slice_header.h"
+#include "h264bsd_nal_unit.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/* structure to store information computed for previous picture, needed for
+ * POC computation of a picture. Two first fields for POC type 0, last two
+ * for types 1 and 2 */
+typedef struct
+{
+ u32 prevPicOrderCntLsb;
+ i32 prevPicOrderCntMsb;
+ u32 prevFrameNum;
+ u32 prevFrameNumOffset;
+} pocStorage_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+i32 h264bsdDecodePicOrderCnt(pocStorage_t *poc, seqParamSet_t *sps,
+ sliceHeader_t *sliceHeader, nalUnit_t *pNalUnit);
+
+#endif /* #ifdef H264SWDEC_PIC_ORDER_CNT_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.c
new file mode 100755
index 0000000..e04dea4
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.c
@@ -0,0 +1,335 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdDecodePicParamSet
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_pic_param_set.h"
+#include "h264bsd_util.h"
+#include "h264bsd_vlc.h"
+#include "h264bsd_cfg.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/* lookup table for ceil(log2(numSliceGroups)), i.e. number of bits needed to
+ * represent range [0, numSliceGroups)
+ *
+ * NOTE: if MAX_NUM_SLICE_GROUPS is higher than 8 this table has to be resized
+ * accordingly */
+static const u32 CeilLog2NumSliceGroups[8] = {1, 1, 2, 2, 3, 3, 3, 3};
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+
+ Function name: h264bsdDecodePicParamSet
+
+ Functional description:
+ Decode picture parameter set information from the stream.
+
+ Function allocates memory for
+ - run lengths if slice group map type is 0
+ - top-left and bottom-right arrays if map type is 2
+ - for slice group ids if map type is 6
+
+ Validity of some of the slice group mapping information depends
+ on the image dimensions which are not known here. Therefore the
+ validity has to be checked afterwards, currently in the parameter
+ set activation phase.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+
+ Outputs:
+ pPicParamSet decoded information is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK failure, invalid information or end of stream
+ MEMORY_ALLOCATION_ERROR for memory allocation failure
+
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodePicParamSet(strmData_t *pStrmData, picParamSet_t *pPicParamSet)
+{
+
+/* Variables */
+
+ u32 tmp, i, value;
+ i32 itmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pPicParamSet);
+
+
+ H264SwDecMemset(pPicParamSet, 0, sizeof(picParamSet_t));
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pPicParamSet->picParameterSetId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pPicParamSet->picParameterSetId >= MAX_NUM_PIC_PARAM_SETS)
+ {
+ EPRINT("pic_parameter_set_id");
+ return(HANTRO_NOK);
+ }
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pPicParamSet->seqParameterSetId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pPicParamSet->seqParameterSetId >= MAX_NUM_SEQ_PARAM_SETS)
+ {
+ EPRINT("seq_param_set_id");
+ return(HANTRO_NOK);
+ }
+
+ /* entropy_coding_mode_flag, shall be 0 for baseline profile */
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp)
+ {
+ EPRINT("entropy_coding_mode_flag");
+ return(HANTRO_NOK);
+ }
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicParamSet->picOrderPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+
+ /* num_slice_groups_minus1 */
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pPicParamSet->numSliceGroups = value + 1;
+ if (pPicParamSet->numSliceGroups > MAX_NUM_SLICE_GROUPS)
+ {
+ EPRINT("num_slice_groups_minus1");
+ return(HANTRO_NOK);
+ }
+
+ /* decode slice group mapping information if more than one slice groups */
+ if (pPicParamSet->numSliceGroups > 1)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pPicParamSet->sliceGroupMapType);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pPicParamSet->sliceGroupMapType > 6)
+ {
+ EPRINT("slice_group_map_type");
+ return(HANTRO_NOK);
+ }
+
+ if (pPicParamSet->sliceGroupMapType == 0)
+ {
+ ALLOCATE(pPicParamSet->runLength,
+ pPicParamSet->numSliceGroups, u32);
+ if (pPicParamSet->runLength == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+ for (i = 0; i < pPicParamSet->numSliceGroups; i++)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pPicParamSet->runLength[i] = value+1;
+ /* param values checked in CheckPps() */
+ }
+ }
+ else if (pPicParamSet->sliceGroupMapType == 2)
+ {
+ ALLOCATE(pPicParamSet->topLeft,
+ pPicParamSet->numSliceGroups - 1, u32);
+ ALLOCATE(pPicParamSet->bottomRight,
+ pPicParamSet->numSliceGroups - 1, u32);
+ if (pPicParamSet->topLeft == NULL ||
+ pPicParamSet->bottomRight == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+ for (i = 0; i < pPicParamSet->numSliceGroups - 1; i++)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pPicParamSet->topLeft[i] = value;
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pPicParamSet->bottomRight[i] = value;
+ /* param values checked in CheckPps() */
+ }
+ }
+ else if ( (pPicParamSet->sliceGroupMapType == 3) ||
+ (pPicParamSet->sliceGroupMapType == 4) ||
+ (pPicParamSet->sliceGroupMapType == 5) )
+ {
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicParamSet->sliceGroupChangeDirectionFlag =
+ (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pPicParamSet->sliceGroupChangeRate = value + 1;
+ /* param value checked in CheckPps() */
+ }
+ else if (pPicParamSet->sliceGroupMapType == 6)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pPicParamSet->picSizeInMapUnits = value + 1;
+
+ ALLOCATE(pPicParamSet->sliceGroupId,
+ pPicParamSet->picSizeInMapUnits, u32);
+ if (pPicParamSet->sliceGroupId == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+
+ /* determine number of bits needed to represent range
+ * [0, numSliceGroups) */
+ tmp = CeilLog2NumSliceGroups[pPicParamSet->numSliceGroups-1];
+
+ for (i = 0; i < pPicParamSet->picSizeInMapUnits; i++)
+ {
+ pPicParamSet->sliceGroupId[i] = h264bsdGetBits(pStrmData, tmp);
+ if ( pPicParamSet->sliceGroupId[i] >=
+ pPicParamSet->numSliceGroups )
+ {
+ EPRINT("slice_group_id");
+ return(HANTRO_NOK);
+ }
+ }
+ }
+ }
+
+ /* num_ref_idx_l0_active_minus1 */
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (value > 31)
+ {
+ EPRINT("num_ref_idx_l0_active_minus1");
+ return(HANTRO_NOK);
+ }
+ pPicParamSet->numRefIdxL0Active = value + 1;
+
+ /* num_ref_idx_l1_active_minus1 */
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (value > 31)
+ {
+ EPRINT("num_ref_idx_l1_active_minus1");
+ return(HANTRO_NOK);
+ }
+
+ /* weighted_pred_flag, this shall be 0 for baseline profile */
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp)
+ {
+ EPRINT("weighted_pred_flag");
+ return(HANTRO_NOK);
+ }
+
+ /* weighted_bipred_idc */
+ tmp = h264bsdGetBits(pStrmData, 2);
+ if (tmp > 2)
+ {
+ EPRINT("weighted_bipred_idc");
+ return(HANTRO_NOK);
+ }
+
+ /* pic_init_qp_minus26 */
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if ((itmp < -26) || (itmp > 25))
+ {
+ EPRINT("pic_init_qp_minus26");
+ return(HANTRO_NOK);
+ }
+ pPicParamSet->picInitQp = (u32)(itmp + 26);
+
+ /* pic_init_qs_minus26 */
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if ((itmp < -26) || (itmp > 25))
+ {
+ EPRINT("pic_init_qs_minus26");
+ return(HANTRO_NOK);
+ }
+
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if ((itmp < -12) || (itmp > 12))
+ {
+ EPRINT("chroma_qp_index_offset");
+ return(HANTRO_NOK);
+ }
+ pPicParamSet->chromaQpIndexOffset = itmp;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicParamSet->deblockingFilterControlPresentFlag =
+ (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicParamSet->constrainedIntraPredFlag = (tmp == 1) ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicParamSet->redundantPicCntPresentFlag = (tmp == 1) ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdRbspTrailingBits(pStrmData);
+
+ /* ignore possible errors in trailing bits of parameters sets */
+ return(HANTRO_OK);
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.h
new file mode 100755
index 0000000..6328638
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_pic_param_set.h
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_PIC_PARAM_SET_H
+#define H264SWDEC_PIC_PARAM_SET_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_stream.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/* data structure to store PPS information decoded from the stream */
+typedef struct
+{
+ u32 picParameterSetId;
+ u32 seqParameterSetId;
+ u32 picOrderPresentFlag;
+ u32 numSliceGroups;
+ u32 sliceGroupMapType;
+ u32 *runLength;
+ u32 *topLeft;
+ u32 *bottomRight;
+ u32 sliceGroupChangeDirectionFlag;
+ u32 sliceGroupChangeRate;
+ u32 picSizeInMapUnits;
+ u32 *sliceGroupId;
+ u32 numRefIdxL0Active;
+ u32 picInitQp;
+ i32 chromaQpIndexOffset;
+ u32 deblockingFilterControlPresentFlag;
+ u32 constrainedIntraPredFlag;
+ u32 redundantPicCntPresentFlag;
+} picParamSet_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodePicParamSet(strmData_t *pStrmData,
+ picParamSet_t *pPicParamSet);
+
+#endif /* #ifdef H264SWDEC_PIC_PARAM_SET_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.c
new file mode 100755
index 0000000..c948776
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.c
@@ -0,0 +1,2315 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_reconstruct.h"
+#include "h264bsd_macroblock_layer.h"
+#include "h264bsd_image.h"
+#include "h264bsd_util.h"
+
+#ifdef H264DEC_OMXDL
+#include "omxtypes.h"
+#include "omxVC.h"
+#include "armVC.h"
+#endif /* H264DEC_OMXDL */
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/* Switch off the following Lint messages for this file:
+ * Info 701: Shift left of signed quantity (int)
+ * Info 702: Shift right of signed quantity (int)
+ */
+/*lint -e701 -e702 */
+
+/* Luma fractional-sample positions
+ *
+ * G a b c H
+ * d e f g
+ * h i j k m
+ * n p q r
+ * M s N
+ *
+ * G, H, M and N are integer sample positions
+ * a-s are fractional samples that need to be interpolated.
+ */
+#ifndef H264DEC_OMXDL
+static const u32 lumaFracPos[4][4] = {
+ /* G d h n a e i p b f j q c g k r */
+ {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}, {12, 13, 14, 15}};
+#endif /* H264DEC_OMXDL */
+
+/* clipping table, defined in h264bsd_intra_prediction.c */
+extern const u8 h264bsdClip[];
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+#ifndef H264DEC_OMXDL
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterpolateChromaHor
+
+ Functional description:
+ This function performs chroma interpolation in horizontal direction.
+ Overfilling is done only if needed. Reference image (pRef) is
+ read at correct position and the predicted part is written to
+ macroblock's chrominance (predPartChroma)
+ Inputs:
+ pRef pointer to reference frame Cb top-left corner
+ x0 integer x-coordinate for prediction
+ y0 integer y-coordinate for prediction
+ width width of the reference frame chrominance in pixels
+ height height of the reference frame chrominance in pixels
+ xFrac horizontal fraction for prediction in 1/8 pixels
+ chromaPartWidth width of the predicted part in pixels
+ chromaPartHeight height of the predicted part in pixels
+ Outputs:
+ predPartChroma pointer where predicted part is written
+
+------------------------------------------------------------------------------*/
+#ifndef H264DEC_ARM11
+void h264bsdInterpolateChromaHor(
+ u8 *pRef,
+ u8 *predPartChroma,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 xFrac,
+ u32 chromaPartWidth,
+ u32 chromaPartHeight)
+{
+
+/* Variables */
+
+ u32 x, y, tmp1, tmp2, tmp3, tmp4, c, val;
+ u8 *ptrA, *cbr;
+ u32 comp;
+ u8 block[9*8*2];
+
+/* Code */
+
+ ASSERT(predPartChroma);
+ ASSERT(chromaPartWidth);
+ ASSERT(chromaPartHeight);
+ ASSERT(xFrac < 8);
+ ASSERT(pRef);
+
+ if ((x0 < 0) || ((u32)x0+chromaPartWidth+1 > width) ||
+ (y0 < 0) || ((u32)y0+chromaPartHeight > height))
+ {
+ h264bsdFillBlock(pRef, block, x0, y0, width, height,
+ chromaPartWidth + 1, chromaPartHeight, chromaPartWidth + 1);
+ pRef += width * height;
+ h264bsdFillBlock(pRef, block + (chromaPartWidth+1)*chromaPartHeight,
+ x0, y0, width, height, chromaPartWidth + 1,
+ chromaPartHeight, chromaPartWidth + 1);
+
+ pRef = block;
+ x0 = 0;
+ y0 = 0;
+ width = chromaPartWidth+1;
+ height = chromaPartHeight;
+ }
+
+ val = 8 - xFrac;
+
+ for (comp = 0; comp <= 1; comp++)
+ {
+
+ ptrA = pRef + (comp * height + (u32)y0) * width + x0;
+ cbr = predPartChroma + comp * 8 * 8;
+
+ /* 2x2 pels per iteration
+ * bilinear horizontal interpolation */
+ for (y = (chromaPartHeight >> 1); y; y--)
+ {
+ for (x = (chromaPartWidth >> 1); x; x--)
+ {
+ tmp1 = ptrA[width];
+ tmp2 = *ptrA++;
+ tmp3 = ptrA[width];
+ tmp4 = *ptrA++;
+ c = ((val * tmp1 + xFrac * tmp3) << 3) + 32;
+ c >>= 6;
+ cbr[8] = (u8)c;
+ c = ((val * tmp2 + xFrac * tmp4) << 3) + 32;
+ c >>= 6;
+ *cbr++ = (u8)c;
+ tmp1 = ptrA[width];
+ tmp2 = *ptrA;
+ c = ((val * tmp3 + xFrac * tmp1) << 3) + 32;
+ c >>= 6;
+ cbr[8] = (u8)c;
+ c = ((val * tmp4 + xFrac * tmp2) << 3) + 32;
+ c >>= 6;
+ *cbr++ = (u8)c;
+ }
+ cbr += 2*8 - chromaPartWidth;
+ ptrA += 2*width - chromaPartWidth;
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterpolateChromaVer
+
+ Functional description:
+ This function performs chroma interpolation in vertical direction.
+ Overfilling is done only if needed. Reference image (pRef) is
+ read at correct position and the predicted part is written to
+ macroblock's chrominance (predPartChroma)
+
+------------------------------------------------------------------------------*/
+
+void h264bsdInterpolateChromaVer(
+ u8 *pRef,
+ u8 *predPartChroma,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 yFrac,
+ u32 chromaPartWidth,
+ u32 chromaPartHeight)
+{
+
+/* Variables */
+
+ u32 x, y, tmp1, tmp2, tmp3, c, val;
+ u8 *ptrA, *cbr;
+ u32 comp;
+ u8 block[9*8*2];
+
+/* Code */
+
+ ASSERT(predPartChroma);
+ ASSERT(chromaPartWidth);
+ ASSERT(chromaPartHeight);
+ ASSERT(yFrac < 8);
+ ASSERT(pRef);
+
+ if ((x0 < 0) || ((u32)x0+chromaPartWidth > width) ||
+ (y0 < 0) || ((u32)y0+chromaPartHeight+1 > height))
+ {
+ h264bsdFillBlock(pRef, block, x0, y0, width, height, chromaPartWidth,
+ chromaPartHeight + 1, chromaPartWidth);
+ pRef += width * height;
+ h264bsdFillBlock(pRef, block + chromaPartWidth*(chromaPartHeight+1),
+ x0, y0, width, height, chromaPartWidth,
+ chromaPartHeight + 1, chromaPartWidth);
+
+ pRef = block;
+ x0 = 0;
+ y0 = 0;
+ width = chromaPartWidth;
+ height = chromaPartHeight+1;
+ }
+
+ val = 8 - yFrac;
+
+ for (comp = 0; comp <= 1; comp++)
+ {
+
+ ptrA = pRef + (comp * height + (u32)y0) * width + x0;
+ cbr = predPartChroma + comp * 8 * 8;
+
+ /* 2x2 pels per iteration
+ * bilinear vertical interpolation */
+ for (y = (chromaPartHeight >> 1); y; y--)
+ {
+ for (x = (chromaPartWidth >> 1); x; x--)
+ {
+ tmp3 = ptrA[width*2];
+ tmp2 = ptrA[width];
+ tmp1 = *ptrA++;
+ c = ((val * tmp2 + yFrac * tmp3) << 3) + 32;
+ c >>= 6;
+ cbr[8] = (u8)c;
+ c = ((val * tmp1 + yFrac * tmp2) << 3) + 32;
+ c >>= 6;
+ *cbr++ = (u8)c;
+ tmp3 = ptrA[width*2];
+ tmp2 = ptrA[width];
+ tmp1 = *ptrA++;
+ c = ((val * tmp2 + yFrac * tmp3) << 3) + 32;
+ c >>= 6;
+ cbr[8] = (u8)c;
+ c = ((val * tmp1 + yFrac * tmp2) << 3) + 32;
+ c >>= 6;
+ *cbr++ = (u8)c;
+ }
+ cbr += 2*8 - chromaPartWidth;
+ ptrA += 2*width - chromaPartWidth;
+ }
+ }
+
+}
+#endif
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterpolateChromaHorVer
+
+ Functional description:
+ This function performs chroma interpolation in horizontal and
+ vertical direction. Overfilling is done only if needed. Reference
+ image (ref) is read at correct position and the predicted part
+ is written to macroblock's chrominance (predPartChroma)
+
+------------------------------------------------------------------------------*/
+
+void h264bsdInterpolateChromaHorVer(
+ u8 *ref,
+ u8 *predPartChroma,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 xFrac,
+ u32 yFrac,
+ u32 chromaPartWidth,
+ u32 chromaPartHeight)
+{
+ u8 block[9*9*2];
+ u32 x, y, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, valX, valY, plus32 = 32;
+ u32 comp;
+ u8 *ptrA, *cbr;
+
+/* Code */
+
+ ASSERT(predPartChroma);
+ ASSERT(chromaPartWidth);
+ ASSERT(chromaPartHeight);
+ ASSERT(xFrac < 8);
+ ASSERT(yFrac < 8);
+ ASSERT(ref);
+
+ if ((x0 < 0) || ((u32)x0+chromaPartWidth+1 > width) ||
+ (y0 < 0) || ((u32)y0+chromaPartHeight+1 > height))
+ {
+ h264bsdFillBlock(ref, block, x0, y0, width, height,
+ chromaPartWidth + 1, chromaPartHeight + 1, chromaPartWidth + 1);
+ ref += width * height;
+ h264bsdFillBlock(ref, block + (chromaPartWidth+1)*(chromaPartHeight+1),
+ x0, y0, width, height, chromaPartWidth + 1,
+ chromaPartHeight + 1, chromaPartWidth + 1);
+
+ ref = block;
+ x0 = 0;
+ y0 = 0;
+ width = chromaPartWidth+1;
+ height = chromaPartHeight+1;
+ }
+
+ valX = 8 - xFrac;
+ valY = 8 - yFrac;
+
+ for (comp = 0; comp <= 1; comp++)
+ {
+
+ ptrA = ref + (comp * height + (u32)y0) * width + x0;
+ cbr = predPartChroma + comp * 8 * 8;
+
+ /* 2x2 pels per iteration
+ * bilinear vertical and horizontal interpolation */
+ for (y = (chromaPartHeight >> 1); y; y--)
+ {
+ tmp1 = *ptrA;
+ tmp3 = ptrA[width];
+ tmp5 = ptrA[width*2];
+ tmp1 *= valY;
+ tmp1 += tmp3 * yFrac;
+ tmp3 *= valY;
+ tmp3 += tmp5 * yFrac;
+ for (x = (chromaPartWidth >> 1); x; x--)
+ {
+ tmp2 = *++ptrA;
+ tmp4 = ptrA[width];
+ tmp6 = ptrA[width*2];
+ tmp2 *= valY;
+ tmp2 += tmp4 * yFrac;
+ tmp4 *= valY;
+ tmp4 += tmp6 * yFrac;
+ tmp1 = tmp1 * valX + plus32;
+ tmp3 = tmp3 * valX + plus32;
+ tmp1 += tmp2 * xFrac;
+ tmp1 >>= 6;
+ tmp3 += tmp4 * xFrac;
+ tmp3 >>= 6;
+ cbr[8] = (u8)tmp3;
+ *cbr++ = (u8)tmp1;
+
+ tmp1 = *++ptrA;
+ tmp3 = ptrA[width];
+ tmp5 = ptrA[width*2];
+ tmp1 *= valY;
+ tmp1 += tmp3 * yFrac;
+ tmp3 *= valY;
+ tmp3 += tmp5 * yFrac;
+ tmp2 = tmp2 * valX + plus32;
+ tmp4 = tmp4 * valX + plus32;
+ tmp2 += tmp1 * xFrac;
+ tmp2 >>= 6;
+ tmp4 += tmp3 * xFrac;
+ tmp4 >>= 6;
+ cbr[8] = (u8)tmp4;
+ *cbr++ = (u8)tmp2;
+ }
+ cbr += 2*8 - chromaPartWidth;
+ ptrA += 2*width - chromaPartWidth;
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: PredictChroma
+
+ Functional description:
+ Top level chroma prediction function that calls the appropriate
+ interpolation function. The output is written to macroblock array.
+
+------------------------------------------------------------------------------*/
+
+static void PredictChroma(
+ u8 *mbPartChroma,
+ u32 xAL,
+ u32 yAL,
+ u32 partWidth,
+ u32 partHeight,
+ mv_t *mv,
+ image_t *refPic)
+{
+
+/* Variables */
+
+ u32 xFrac, yFrac, width, height, chromaPartWidth, chromaPartHeight;
+ i32 xInt, yInt;
+ u8 *ref;
+
+/* Code */
+
+ ASSERT(mv);
+ ASSERT(refPic);
+ ASSERT(refPic->data);
+ ASSERT(refPic->width);
+ ASSERT(refPic->height);
+
+ width = 8 * refPic->width;
+ height = 8 * refPic->height;
+
+ xInt = (xAL >> 1) + (mv->hor >> 3);
+ yInt = (yAL >> 1) + (mv->ver >> 3);
+ xFrac = mv->hor & 0x7;
+ yFrac = mv->ver & 0x7;
+
+ chromaPartWidth = partWidth >> 1;
+ chromaPartHeight = partHeight >> 1;
+ ref = refPic->data + 256 * refPic->width * refPic->height;
+
+ if (xFrac && yFrac)
+ {
+ h264bsdInterpolateChromaHorVer(ref, mbPartChroma, xInt, yInt, width,
+ height, xFrac, yFrac, chromaPartWidth, chromaPartHeight);
+ }
+ else if (xFrac)
+ {
+ h264bsdInterpolateChromaHor(ref, mbPartChroma, xInt, yInt, width,
+ height, xFrac, chromaPartWidth, chromaPartHeight);
+ }
+ else if (yFrac)
+ {
+ h264bsdInterpolateChromaVer(ref, mbPartChroma, xInt, yInt, width,
+ height, yFrac, chromaPartWidth, chromaPartHeight);
+ }
+ else
+ {
+ h264bsdFillBlock(ref, mbPartChroma, xInt, yInt, width, height,
+ chromaPartWidth, chromaPartHeight, 8);
+ ref += width * height;
+ h264bsdFillBlock(ref, mbPartChroma + 8*8, xInt, yInt, width, height,
+ chromaPartWidth, chromaPartHeight, 8);
+ }
+
+}
+
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterpolateVerHalf
+
+ Functional description:
+ Function to perform vertical interpolation of pixel position 'h'
+ for a block. Overfilling is done only if needed. Reference
+ image (ref) is read at correct position and the predicted part
+ is written to macroblock array (mb)
+
+------------------------------------------------------------------------------*/
+#ifndef H264DEC_ARM11
+void h264bsdInterpolateVerHalf(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight)
+{
+ u32 p1[21*21/4+1];
+ u32 i, j;
+ i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ u8 *ptrC, *ptrV;
+ const u8 *clp = h264bsdClip + 512;
+
+ /* Code */
+
+ ASSERT(ref);
+ ASSERT(mb);
+
+ if ((x0 < 0) || ((u32)x0+partWidth > width) ||
+ (y0 < 0) || ((u32)y0+partHeight+5 > height))
+ {
+ h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height,
+ partWidth, partHeight+5, partWidth);
+
+ x0 = 0;
+ y0 = 0;
+ ref = (u8*)p1;
+ width = partWidth;
+ }
+
+ ref += (u32)y0 * width + (u32)x0;
+
+ ptrC = ref + width;
+ ptrV = ptrC + 5*width;
+
+ /* 4 pixels per iteration, interpolate using 5 vertical samples */
+ for (i = (partHeight >> 2); i; i--)
+ {
+ /* h1 = (16 + A + 16(G+M) + 4(G+M) - 4(C+R) - (C+R) + T) >> 5 */
+ for (j = partWidth; j; j--)
+ {
+ tmp4 = ptrV[-(i32)width*2];
+ tmp5 = ptrV[-(i32)width];
+ tmp1 = ptrV[width];
+ tmp2 = ptrV[width*2];
+ tmp6 = *ptrV++;
+
+ tmp7 = tmp4 + tmp1;
+ tmp2 -= (tmp7 << 2);
+ tmp2 -= tmp7;
+ tmp2 += 16;
+ tmp7 = tmp5 + tmp6;
+ tmp3 = ptrC[width*2];
+ tmp2 += (tmp7 << 4);
+ tmp2 += (tmp7 << 2);
+ tmp2 += tmp3;
+ tmp2 = clp[tmp2>>5];
+ tmp1 += 16;
+ mb[48] = (u8)tmp2;
+
+ tmp7 = tmp3 + tmp6;
+ tmp1 -= (tmp7 << 2);
+ tmp1 -= tmp7;
+ tmp7 = tmp4 + tmp5;
+ tmp2 = ptrC[width];
+ tmp1 += (tmp7 << 4);
+ tmp1 += (tmp7 << 2);
+ tmp1 += tmp2;
+ tmp1 = clp[tmp1>>5];
+ tmp6 += 16;
+ mb[32] = (u8)tmp1;
+
+ tmp7 = tmp2 + tmp5;
+ tmp6 -= (tmp7 << 2);
+ tmp6 -= tmp7;
+ tmp7 = tmp4 + tmp3;
+ tmp1 = *ptrC;
+ tmp6 += (tmp7 << 4);
+ tmp6 += (tmp7 << 2);
+ tmp6 += tmp1;
+ tmp6 = clp[tmp6>>5];
+ tmp5 += 16;
+ mb[16] = (u8)tmp6;
+
+ tmp1 += tmp4;
+ tmp5 -= (tmp1 << 2);
+ tmp5 -= tmp1;
+ tmp3 += tmp2;
+ tmp6 = ptrC[-(i32)width];
+ tmp5 += (tmp3 << 4);
+ tmp5 += (tmp3 << 2);
+ tmp5 += tmp6;
+ tmp5 = clp[tmp5>>5];
+ *mb++ = (u8)tmp5;
+ ptrC++;
+ }
+ ptrC += 4*width - partWidth;
+ ptrV += 4*width - partWidth;
+ mb += 4*16 - partWidth;
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterpolateVerQuarter
+
+ Functional description:
+ Function to perform vertical interpolation of pixel position 'd'
+ or 'n' for a block. Overfilling is done only if needed. Reference
+ image (ref) is read at correct position and the predicted part
+ is written to macroblock array (mb)
+
+------------------------------------------------------------------------------*/
+
+void h264bsdInterpolateVerQuarter(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight,
+ u32 verOffset) /* 0 for pixel d, 1 for pixel n */
+{
+ u32 p1[21*21/4+1];
+ u32 i, j;
+ i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ u8 *ptrC, *ptrV, *ptrInt;
+ const u8 *clp = h264bsdClip + 512;
+
+ /* Code */
+
+ ASSERT(ref);
+ ASSERT(mb);
+
+ if ((x0 < 0) || ((u32)x0+partWidth > width) ||
+ (y0 < 0) || ((u32)y0+partHeight+5 > height))
+ {
+ h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height,
+ partWidth, partHeight+5, partWidth);
+
+ x0 = 0;
+ y0 = 0;
+ ref = (u8*)p1;
+ width = partWidth;
+ }
+
+ ref += (u32)y0 * width + (u32)x0;
+
+ ptrC = ref + width;
+ ptrV = ptrC + 5*width;
+
+ /* Pointer to integer sample position, either M or R */
+ ptrInt = ptrC + (2+verOffset)*width;
+
+ /* 4 pixels per iteration
+ * interpolate using 5 vertical samples and average between
+ * interpolated value and integer sample value */
+ for (i = (partHeight >> 2); i; i--)
+ {
+ /* h1 = (16 + A + 16(G+M) + 4(G+M) - 4(C+R) - (C+R) + T) >> 5 */
+ for (j = partWidth; j; j--)
+ {
+ tmp4 = ptrV[-(i32)width*2];
+ tmp5 = ptrV[-(i32)width];
+ tmp1 = ptrV[width];
+ tmp2 = ptrV[width*2];
+ tmp6 = *ptrV++;
+
+ tmp7 = tmp4 + tmp1;
+ tmp2 -= (tmp7 << 2);
+ tmp2 -= tmp7;
+ tmp2 += 16;
+ tmp7 = tmp5 + tmp6;
+ tmp3 = ptrC[width*2];
+ tmp2 += (tmp7 << 4);
+ tmp2 += (tmp7 << 2);
+ tmp2 += tmp3;
+ tmp2 = clp[tmp2>>5];
+ tmp7 = ptrInt[width*2];
+ tmp1 += 16;
+ tmp2++;
+ mb[48] = (u8)((tmp2 + tmp7) >> 1);
+
+ tmp7 = tmp3 + tmp6;
+ tmp1 -= (tmp7 << 2);
+ tmp1 -= tmp7;
+ tmp7 = tmp4 + tmp5;
+ tmp2 = ptrC[width];
+ tmp1 += (tmp7 << 4);
+ tmp1 += (tmp7 << 2);
+ tmp1 += tmp2;
+ tmp1 = clp[tmp1>>5];
+ tmp7 = ptrInt[width];
+ tmp6 += 16;
+ tmp1++;
+ mb[32] = (u8)((tmp1 + tmp7) >> 1);
+
+ tmp7 = tmp2 + tmp5;
+ tmp6 -= (tmp7 << 2);
+ tmp6 -= tmp7;
+ tmp7 = tmp4 + tmp3;
+ tmp1 = *ptrC;
+ tmp6 += (tmp7 << 4);
+ tmp6 += (tmp7 << 2);
+ tmp6 += tmp1;
+ tmp6 = clp[tmp6>>5];
+ tmp7 = *ptrInt;
+ tmp5 += 16;
+ tmp6++;
+ mb[16] = (u8)((tmp6 + tmp7) >> 1);
+
+ tmp1 += tmp4;
+ tmp5 -= (tmp1 << 2);
+ tmp5 -= tmp1;
+ tmp3 += tmp2;
+ tmp6 = ptrC[-(i32)width];
+ tmp5 += (tmp3 << 4);
+ tmp5 += (tmp3 << 2);
+ tmp5 += tmp6;
+ tmp5 = clp[tmp5>>5];
+ tmp7 = ptrInt[-(i32)width];
+ tmp5++;
+ *mb++ = (u8)((tmp5 + tmp7) >> 1);
+ ptrC++;
+ ptrInt++;
+ }
+ ptrC += 4*width - partWidth;
+ ptrV += 4*width - partWidth;
+ ptrInt += 4*width - partWidth;
+ mb += 4*16 - partWidth;
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterpolateHorHalf
+
+ Functional description:
+ Function to perform horizontal interpolation of pixel position 'b'
+ for a block. Overfilling is done only if needed. Reference
+ image (ref) is read at correct position and the predicted part
+ is written to macroblock array (mb)
+
+------------------------------------------------------------------------------*/
+
+void h264bsdInterpolateHorHalf(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight)
+{
+ u32 p1[21*21/4+1];
+ u8 *ptrJ;
+ u32 x, y;
+ i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ const u8 *clp = h264bsdClip + 512;
+
+ /* Code */
+
+ ASSERT(ref);
+ ASSERT(mb);
+ ASSERT((partWidth&0x3) == 0);
+ ASSERT((partHeight&0x3) == 0);
+
+ if ((x0 < 0) || ((u32)x0+partWidth+5 > width) ||
+ (y0 < 0) || ((u32)y0+partHeight > height))
+ {
+ h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height,
+ partWidth+5, partHeight, partWidth+5);
+
+ x0 = 0;
+ y0 = 0;
+ ref = (u8*)p1;
+ width = partWidth + 5;
+ }
+
+ ref += (u32)y0 * width + (u32)x0;
+
+ ptrJ = ref + 5;
+
+ for (y = partHeight; y; y--)
+ {
+ tmp6 = *(ptrJ - 5);
+ tmp5 = *(ptrJ - 4);
+ tmp4 = *(ptrJ - 3);
+ tmp3 = *(ptrJ - 2);
+ tmp2 = *(ptrJ - 1);
+
+ /* calculate 4 pels per iteration */
+ for (x = (partWidth >> 2); x; x--)
+ {
+ /* First pixel */
+ tmp6 += 16;
+ tmp7 = tmp3 + tmp4;
+ tmp6 += (tmp7 << 4);
+ tmp6 += (tmp7 << 2);
+ tmp7 = tmp2 + tmp5;
+ tmp1 = *ptrJ++;
+ tmp6 -= (tmp7 << 2);
+ tmp6 -= tmp7;
+ tmp6 += tmp1;
+ tmp6 = clp[tmp6>>5];
+ /* Second pixel */
+ tmp5 += 16;
+ tmp7 = tmp2 + tmp3;
+ *mb++ = (u8)tmp6;
+ tmp5 += (tmp7 << 4);
+ tmp5 += (tmp7 << 2);
+ tmp7 = tmp1 + tmp4;
+ tmp6 = *ptrJ++;
+ tmp5 -= (tmp7 << 2);
+ tmp5 -= tmp7;
+ tmp5 += tmp6;
+ tmp5 = clp[tmp5>>5];
+ /* Third pixel */
+ tmp4 += 16;
+ tmp7 = tmp1 + tmp2;
+ *mb++ = (u8)tmp5;
+ tmp4 += (tmp7 << 4);
+ tmp4 += (tmp7 << 2);
+ tmp7 = tmp6 + tmp3;
+ tmp5 = *ptrJ++;
+ tmp4 -= (tmp7 << 2);
+ tmp4 -= tmp7;
+ tmp4 += tmp5;
+ tmp4 = clp[tmp4>>5];
+ /* Fourth pixel */
+ tmp3 += 16;
+ tmp7 = tmp6 + tmp1;
+ *mb++ = (u8)tmp4;
+ tmp3 += (tmp7 << 4);
+ tmp3 += (tmp7 << 2);
+ tmp7 = tmp5 + tmp2;
+ tmp4 = *ptrJ++;
+ tmp3 -= (tmp7 << 2);
+ tmp3 -= tmp7;
+ tmp3 += tmp4;
+ tmp3 = clp[tmp3>>5];
+ tmp7 = tmp4;
+ tmp4 = tmp6;
+ tmp6 = tmp2;
+ tmp2 = tmp7;
+ *mb++ = (u8)tmp3;
+ tmp3 = tmp5;
+ tmp5 = tmp1;
+ }
+ ptrJ += width - partWidth;
+ mb += 16 - partWidth;
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterpolateHorQuarter
+
+ Functional description:
+ Function to perform horizontal interpolation of pixel position 'a'
+ or 'c' for a block. Overfilling is done only if needed. Reference
+ image (ref) is read at correct position and the predicted part
+ is written to macroblock array (mb)
+
+------------------------------------------------------------------------------*/
+
+void h264bsdInterpolateHorQuarter(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight,
+ u32 horOffset) /* 0 for pixel a, 1 for pixel c */
+{
+ u32 p1[21*21/4+1];
+ u8 *ptrJ;
+ u32 x, y;
+ i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ const u8 *clp = h264bsdClip + 512;
+
+ /* Code */
+
+ ASSERT(ref);
+ ASSERT(mb);
+
+ if ((x0 < 0) || ((u32)x0+partWidth+5 > width) ||
+ (y0 < 0) || ((u32)y0+partHeight > height))
+ {
+ h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height,
+ partWidth+5, partHeight, partWidth+5);
+
+ x0 = 0;
+ y0 = 0;
+ ref = (u8*)p1;
+ width = partWidth + 5;
+ }
+
+ ref += (u32)y0 * width + (u32)x0;
+
+ ptrJ = ref + 5;
+
+ for (y = partHeight; y; y--)
+ {
+ tmp6 = *(ptrJ - 5);
+ tmp5 = *(ptrJ - 4);
+ tmp4 = *(ptrJ - 3);
+ tmp3 = *(ptrJ - 2);
+ tmp2 = *(ptrJ - 1);
+
+ /* calculate 4 pels per iteration */
+ for (x = (partWidth >> 2); x; x--)
+ {
+ /* First pixel */
+ tmp6 += 16;
+ tmp7 = tmp3 + tmp4;
+ tmp6 += (tmp7 << 4);
+ tmp6 += (tmp7 << 2);
+ tmp7 = tmp2 + tmp5;
+ tmp1 = *ptrJ++;
+ tmp6 -= (tmp7 << 2);
+ tmp6 -= tmp7;
+ tmp6 += tmp1;
+ tmp6 = clp[tmp6>>5];
+ tmp5 += 16;
+ if (!horOffset)
+ tmp6 += tmp4;
+ else
+ tmp6 += tmp3;
+ *mb++ = (u8)((tmp6 + 1) >> 1);
+ /* Second pixel */
+ tmp7 = tmp2 + tmp3;
+ tmp5 += (tmp7 << 4);
+ tmp5 += (tmp7 << 2);
+ tmp7 = tmp1 + tmp4;
+ tmp6 = *ptrJ++;
+ tmp5 -= (tmp7 << 2);
+ tmp5 -= tmp7;
+ tmp5 += tmp6;
+ tmp5 = clp[tmp5>>5];
+ tmp4 += 16;
+ if (!horOffset)
+ tmp5 += tmp3;
+ else
+ tmp5 += tmp2;
+ *mb++ = (u8)((tmp5 + 1) >> 1);
+ /* Third pixel */
+ tmp7 = tmp1 + tmp2;
+ tmp4 += (tmp7 << 4);
+ tmp4 += (tmp7 << 2);
+ tmp7 = tmp6 + tmp3;
+ tmp5 = *ptrJ++;
+ tmp4 -= (tmp7 << 2);
+ tmp4 -= tmp7;
+ tmp4 += tmp5;
+ tmp4 = clp[tmp4>>5];
+ tmp3 += 16;
+ if (!horOffset)
+ tmp4 += tmp2;
+ else
+ tmp4 += tmp1;
+ *mb++ = (u8)((tmp4 + 1) >> 1);
+ /* Fourth pixel */
+ tmp7 = tmp6 + tmp1;
+ tmp3 += (tmp7 << 4);
+ tmp3 += (tmp7 << 2);
+ tmp7 = tmp5 + tmp2;
+ tmp4 = *ptrJ++;
+ tmp3 -= (tmp7 << 2);
+ tmp3 -= tmp7;
+ tmp3 += tmp4;
+ tmp3 = clp[tmp3>>5];
+ if (!horOffset)
+ tmp3 += tmp1;
+ else
+ tmp3 += tmp6;
+ *mb++ = (u8)((tmp3 + 1) >> 1);
+ tmp3 = tmp5;
+ tmp5 = tmp1;
+ tmp7 = tmp4;
+ tmp4 = tmp6;
+ tmp6 = tmp2;
+ tmp2 = tmp7;
+ }
+ ptrJ += width - partWidth;
+ mb += 16 - partWidth;
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterpolateHorVerQuarter
+
+ Functional description:
+ Function to perform horizontal and vertical interpolation of pixel
+ position 'e', 'g', 'p' or 'r' for a block. Overfilling is done only
+ if needed. Reference image (ref) is read at correct position and
+ the predicted part is written to macroblock array (mb)
+
+------------------------------------------------------------------------------*/
+
+void h264bsdInterpolateHorVerQuarter(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight,
+ u32 horVerOffset) /* 0 for pixel e, 1 for pixel g,
+ 2 for pixel p, 3 for pixel r */
+{
+ u32 p1[21*21/4+1];
+ u8 *ptrC, *ptrJ, *ptrV;
+ u32 x, y;
+ i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ const u8 *clp = h264bsdClip + 512;
+
+ /* Code */
+
+ ASSERT(ref);
+ ASSERT(mb);
+
+ if ((x0 < 0) || ((u32)x0+partWidth+5 > width) ||
+ (y0 < 0) || ((u32)y0+partHeight+5 > height))
+ {
+ h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height,
+ partWidth+5, partHeight+5, partWidth+5);
+
+ x0 = 0;
+ y0 = 0;
+ ref = (u8*)p1;
+ width = partWidth+5;
+ }
+
+ /* Ref points to G + (-2, -2) */
+ ref += (u32)y0 * width + (u32)x0;
+
+ /* ptrJ points to either J or Q, depending on vertical offset */
+ ptrJ = ref + (((horVerOffset & 0x2) >> 1) + 2) * width + 5;
+
+ /* ptrC points to either C or D, depending on horizontal offset */
+ ptrC = ref + width + 2 + (horVerOffset & 0x1);
+
+ for (y = partHeight; y; y--)
+ {
+ tmp6 = *(ptrJ - 5);
+ tmp5 = *(ptrJ - 4);
+ tmp4 = *(ptrJ - 3);
+ tmp3 = *(ptrJ - 2);
+ tmp2 = *(ptrJ - 1);
+
+ /* Horizontal interpolation, calculate 4 pels per iteration */
+ for (x = (partWidth >> 2); x; x--)
+ {
+ /* First pixel */
+ tmp6 += 16;
+ tmp7 = tmp3 + tmp4;
+ tmp6 += (tmp7 << 4);
+ tmp6 += (tmp7 << 2);
+ tmp7 = tmp2 + tmp5;
+ tmp1 = *ptrJ++;
+ tmp6 -= (tmp7 << 2);
+ tmp6 -= tmp7;
+ tmp6 += tmp1;
+ tmp6 = clp[tmp6>>5];
+ /* Second pixel */
+ tmp5 += 16;
+ tmp7 = tmp2 + tmp3;
+ *mb++ = (u8)tmp6;
+ tmp5 += (tmp7 << 4);
+ tmp5 += (tmp7 << 2);
+ tmp7 = tmp1 + tmp4;
+ tmp6 = *ptrJ++;
+ tmp5 -= (tmp7 << 2);
+ tmp5 -= tmp7;
+ tmp5 += tmp6;
+ tmp5 = clp[tmp5>>5];
+ /* Third pixel */
+ tmp4 += 16;
+ tmp7 = tmp1 + tmp2;
+ *mb++ = (u8)tmp5;
+ tmp4 += (tmp7 << 4);
+ tmp4 += (tmp7 << 2);
+ tmp7 = tmp6 + tmp3;
+ tmp5 = *ptrJ++;
+ tmp4 -= (tmp7 << 2);
+ tmp4 -= tmp7;
+ tmp4 += tmp5;
+ tmp4 = clp[tmp4>>5];
+ /* Fourth pixel */
+ tmp3 += 16;
+ tmp7 = tmp6 + tmp1;
+ *mb++ = (u8)tmp4;
+ tmp3 += (tmp7 << 4);
+ tmp3 += (tmp7 << 2);
+ tmp7 = tmp5 + tmp2;
+ tmp4 = *ptrJ++;
+ tmp3 -= (tmp7 << 2);
+ tmp3 -= tmp7;
+ tmp3 += tmp4;
+ tmp3 = clp[tmp3>>5];
+ tmp7 = tmp4;
+ tmp4 = tmp6;
+ tmp6 = tmp2;
+ tmp2 = tmp7;
+ *mb++ = (u8)tmp3;
+ tmp3 = tmp5;
+ tmp5 = tmp1;
+ }
+ ptrJ += width - partWidth;
+ mb += 16 - partWidth;
+ }
+
+ mb -= 16*partHeight;
+ ptrV = ptrC + 5*width;
+
+ for (y = (partHeight >> 2); y; y--)
+ {
+ /* Vertical interpolation and averaging, 4 pels per iteration */
+ for (x = partWidth; x; x--)
+ {
+ tmp4 = ptrV[-(i32)width*2];
+ tmp5 = ptrV[-(i32)width];
+ tmp1 = ptrV[width];
+ tmp2 = ptrV[width*2];
+ tmp6 = *ptrV++;
+
+ tmp7 = tmp4 + tmp1;
+ tmp2 -= (tmp7 << 2);
+ tmp2 -= tmp7;
+ tmp2 += 16;
+ tmp7 = tmp5 + tmp6;
+ tmp3 = ptrC[width*2];
+ tmp2 += (tmp7 << 4);
+ tmp2 += (tmp7 << 2);
+ tmp2 += tmp3;
+ tmp7 = clp[tmp2>>5];
+ tmp2 = mb[48];
+ tmp1 += 16;
+ tmp7++;
+ mb[48] = (u8)((tmp2 + tmp7) >> 1);
+
+ tmp7 = tmp3 + tmp6;
+ tmp1 -= (tmp7 << 2);
+ tmp1 -= tmp7;
+ tmp7 = tmp4 + tmp5;
+ tmp2 = ptrC[width];
+ tmp1 += (tmp7 << 4);
+ tmp1 += (tmp7 << 2);
+ tmp1 += tmp2;
+ tmp7 = clp[tmp1>>5];
+ tmp1 = mb[32];
+ tmp6 += 16;
+ tmp7++;
+ mb[32] = (u8)((tmp1 + tmp7) >> 1);
+
+ tmp1 = *ptrC;
+ tmp7 = tmp2 + tmp5;
+ tmp6 -= (tmp7 << 2);
+ tmp6 -= tmp7;
+ tmp7 = tmp4 + tmp3;
+ tmp6 += (tmp7 << 4);
+ tmp6 += (tmp7 << 2);
+ tmp6 += tmp1;
+ tmp7 = clp[tmp6>>5];
+ tmp6 = mb[16];
+ tmp5 += 16;
+ tmp7++;
+ mb[16] = (u8)((tmp6 + tmp7) >> 1);
+
+ tmp6 = ptrC[-(i32)width];
+ tmp1 += tmp4;
+ tmp5 -= (tmp1 << 2);
+ tmp5 -= tmp1;
+ tmp3 += tmp2;
+ tmp5 += (tmp3 << 4);
+ tmp5 += (tmp3 << 2);
+ tmp5 += tmp6;
+ tmp7 = clp[tmp5>>5];
+ tmp5 = *mb;
+ tmp7++;
+ *mb++ = (u8)((tmp5 + tmp7) >> 1);
+ ptrC++;
+
+ }
+ ptrC += 4*width - partWidth;
+ ptrV += 4*width - partWidth;
+ mb += 4*16 - partWidth;
+ }
+
+}
+#endif
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterpolateMidHalf
+
+ Functional description:
+ Function to perform horizontal and vertical interpolation of pixel
+ position 'j' for a block. Overfilling is done only if needed.
+ Reference image (ref) is read at correct position and the predicted
+ part is written to macroblock array (mb)
+
+------------------------------------------------------------------------------*/
+
+void h264bsdInterpolateMidHalf(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight)
+{
+ u32 p1[21*21/4+1];
+ u32 x, y;
+ i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ i32 *ptrC, *ptrV, *b1;
+ u8 *ptrJ;
+ i32 table[21*16];
+ const u8 *clp = h264bsdClip + 512;
+
+ /* Code */
+
+ ASSERT(ref);
+ ASSERT(mb);
+
+ if ((x0 < 0) || ((u32)x0+partWidth+5 > width) ||
+ (y0 < 0) || ((u32)y0+partHeight+5 > height))
+ {
+ h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height,
+ partWidth+5, partHeight+5, partWidth+5);
+
+ x0 = 0;
+ y0 = 0;
+ ref = (u8*)p1;
+ width = partWidth+5;
+ }
+
+ ref += (u32)y0 * width + (u32)x0;
+
+ b1 = table;
+ ptrJ = ref + 5;
+
+ /* First step: calculate intermediate values for
+ * horizontal interpolation */
+ for (y = partHeight + 5; y; y--)
+ {
+ tmp6 = *(ptrJ - 5);
+ tmp5 = *(ptrJ - 4);
+ tmp4 = *(ptrJ - 3);
+ tmp3 = *(ptrJ - 2);
+ tmp2 = *(ptrJ - 1);
+
+ /* 4 pels per iteration */
+ for (x = (partWidth >> 2); x; x--)
+ {
+ /* First pixel */
+ tmp7 = tmp3 + tmp4;
+ tmp6 += (tmp7 << 4);
+ tmp6 += (tmp7 << 2);
+ tmp7 = tmp2 + tmp5;
+ tmp1 = *ptrJ++;
+ tmp6 -= (tmp7 << 2);
+ tmp6 -= tmp7;
+ tmp6 += tmp1;
+ *b1++ = tmp6;
+ /* Second pixel */
+ tmp7 = tmp2 + tmp3;
+ tmp5 += (tmp7 << 4);
+ tmp5 += (tmp7 << 2);
+ tmp7 = tmp1 + tmp4;
+ tmp6 = *ptrJ++;
+ tmp5 -= (tmp7 << 2);
+ tmp5 -= tmp7;
+ tmp5 += tmp6;
+ *b1++ = tmp5;
+ /* Third pixel */
+ tmp7 = tmp1 + tmp2;
+ tmp4 += (tmp7 << 4);
+ tmp4 += (tmp7 << 2);
+ tmp7 = tmp6 + tmp3;
+ tmp5 = *ptrJ++;
+ tmp4 -= (tmp7 << 2);
+ tmp4 -= tmp7;
+ tmp4 += tmp5;
+ *b1++ = tmp4;
+ /* Fourth pixel */
+ tmp7 = tmp6 + tmp1;
+ tmp3 += (tmp7 << 4);
+ tmp3 += (tmp7 << 2);
+ tmp7 = tmp5 + tmp2;
+ tmp4 = *ptrJ++;
+ tmp3 -= (tmp7 << 2);
+ tmp3 -= tmp7;
+ tmp3 += tmp4;
+ *b1++ = tmp3;
+ tmp7 = tmp4;
+ tmp4 = tmp6;
+ tmp6 = tmp2;
+ tmp2 = tmp7;
+ tmp3 = tmp5;
+ tmp5 = tmp1;
+ }
+ ptrJ += width - partWidth;
+ }
+
+ /* Second step: calculate vertical interpolation */
+ ptrC = table + partWidth;
+ ptrV = ptrC + 5*partWidth;
+ for (y = (partHeight >> 2); y; y--)
+ {
+ /* 4 pels per iteration */
+ for (x = partWidth; x; x--)
+ {
+ tmp4 = ptrV[-(i32)partWidth*2];
+ tmp5 = ptrV[-(i32)partWidth];
+ tmp1 = ptrV[partWidth];
+ tmp2 = ptrV[partWidth*2];
+ tmp6 = *ptrV++;
+
+ tmp7 = tmp4 + tmp1;
+ tmp2 -= (tmp7 << 2);
+ tmp2 -= tmp7;
+ tmp2 += 512;
+ tmp7 = tmp5 + tmp6;
+ tmp3 = ptrC[partWidth*2];
+ tmp2 += (tmp7 << 4);
+ tmp2 += (tmp7 << 2);
+ tmp2 += tmp3;
+ tmp7 = clp[tmp2>>10];
+ tmp1 += 512;
+ mb[48] = (u8)tmp7;
+
+ tmp7 = tmp3 + tmp6;
+ tmp1 -= (tmp7 << 2);
+ tmp1 -= tmp7;
+ tmp7 = tmp4 + tmp5;
+ tmp2 = ptrC[partWidth];
+ tmp1 += (tmp7 << 4);
+ tmp1 += (tmp7 << 2);
+ tmp1 += tmp2;
+ tmp7 = clp[tmp1>>10];
+ tmp6 += 512;
+ mb[32] = (u8)tmp7;
+
+ tmp1 = *ptrC;
+ tmp7 = tmp2 + tmp5;
+ tmp6 -= (tmp7 << 2);
+ tmp6 -= tmp7;
+ tmp7 = tmp4 + tmp3;
+ tmp6 += (tmp7 << 4);
+ tmp6 += (tmp7 << 2);
+ tmp6 += tmp1;
+ tmp7 = clp[tmp6>>10];
+ tmp5 += 512;
+ mb[16] = (u8)tmp7;
+
+ tmp6 = ptrC[-(i32)partWidth];
+ tmp1 += tmp4;
+ tmp5 -= (tmp1 << 2);
+ tmp5 -= tmp1;
+ tmp3 += tmp2;
+ tmp5 += (tmp3 << 4);
+ tmp5 += (tmp3 << 2);
+ tmp5 += tmp6;
+ tmp7 = clp[tmp5>>10];
+ *mb++ = (u8)tmp7;
+ ptrC++;
+ }
+ mb += 4*16 - partWidth;
+ ptrC += 3*partWidth;
+ ptrV += 3*partWidth;
+ }
+
+}
+
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterpolateMidVerQuarter
+
+ Functional description:
+ Function to perform horizontal and vertical interpolation of pixel
+ position 'f' or 'q' for a block. Overfilling is done only if needed.
+ Reference image (ref) is read at correct position and the predicted
+ part is written to macroblock array (mb)
+
+------------------------------------------------------------------------------*/
+
+void h264bsdInterpolateMidVerQuarter(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight,
+ u32 verOffset) /* 0 for pixel f, 1 for pixel q */
+{
+ u32 p1[21*21/4+1];
+ u32 x, y;
+ i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ i32 *ptrC, *ptrV, *ptrInt, *b1;
+ u8 *ptrJ;
+ i32 table[21*16];
+ const u8 *clp = h264bsdClip + 512;
+
+ /* Code */
+
+ ASSERT(ref);
+ ASSERT(mb);
+
+ if ((x0 < 0) || ((u32)x0+partWidth+5 > width) ||
+ (y0 < 0) || ((u32)y0+partHeight+5 > height))
+ {
+ h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height,
+ partWidth+5, partHeight+5, partWidth+5);
+
+ x0 = 0;
+ y0 = 0;
+ ref = (u8*)p1;
+ width = partWidth+5;
+ }
+
+ ref += (u32)y0 * width + (u32)x0;
+
+ b1 = table;
+ ptrJ = ref + 5;
+
+ /* First step: calculate intermediate values for
+ * horizontal interpolation */
+ for (y = partHeight + 5; y; y--)
+ {
+ tmp6 = *(ptrJ - 5);
+ tmp5 = *(ptrJ - 4);
+ tmp4 = *(ptrJ - 3);
+ tmp3 = *(ptrJ - 2);
+ tmp2 = *(ptrJ - 1);
+ for (x = (partWidth >> 2); x; x--)
+ {
+ /* First pixel */
+ tmp7 = tmp3 + tmp4;
+ tmp6 += (tmp7 << 4);
+ tmp6 += (tmp7 << 2);
+ tmp7 = tmp2 + tmp5;
+ tmp1 = *ptrJ++;
+ tmp6 -= (tmp7 << 2);
+ tmp6 -= tmp7;
+ tmp6 += tmp1;
+ *b1++ = tmp6;
+ /* Second pixel */
+ tmp7 = tmp2 + tmp3;
+ tmp5 += (tmp7 << 4);
+ tmp5 += (tmp7 << 2);
+ tmp7 = tmp1 + tmp4;
+ tmp6 = *ptrJ++;
+ tmp5 -= (tmp7 << 2);
+ tmp5 -= tmp7;
+ tmp5 += tmp6;
+ *b1++ = tmp5;
+ /* Third pixel */
+ tmp7 = tmp1 + tmp2;
+ tmp4 += (tmp7 << 4);
+ tmp4 += (tmp7 << 2);
+ tmp7 = tmp6 + tmp3;
+ tmp5 = *ptrJ++;
+ tmp4 -= (tmp7 << 2);
+ tmp4 -= tmp7;
+ tmp4 += tmp5;
+ *b1++ = tmp4;
+ /* Fourth pixel */
+ tmp7 = tmp6 + tmp1;
+ tmp3 += (tmp7 << 4);
+ tmp3 += (tmp7 << 2);
+ tmp7 = tmp5 + tmp2;
+ tmp4 = *ptrJ++;
+ tmp3 -= (tmp7 << 2);
+ tmp3 -= tmp7;
+ tmp3 += tmp4;
+ *b1++ = tmp3;
+ tmp7 = tmp4;
+ tmp4 = tmp6;
+ tmp6 = tmp2;
+ tmp2 = tmp7;
+ tmp3 = tmp5;
+ tmp5 = tmp1;
+ }
+ ptrJ += width - partWidth;
+ }
+
+ /* Second step: calculate vertical interpolation and average */
+ ptrC = table + partWidth;
+ ptrV = ptrC + 5*partWidth;
+ /* Pointer to integer sample position, either M or R */
+ ptrInt = ptrC + (2+verOffset)*partWidth;
+ for (y = (partHeight >> 2); y; y--)
+ {
+ for (x = partWidth; x; x--)
+ {
+ tmp4 = ptrV[-(i32)partWidth*2];
+ tmp5 = ptrV[-(i32)partWidth];
+ tmp1 = ptrV[partWidth];
+ tmp2 = ptrV[partWidth*2];
+ tmp6 = *ptrV++;
+
+ tmp7 = tmp4 + tmp1;
+ tmp2 -= (tmp7 << 2);
+ tmp2 -= tmp7;
+ tmp2 += 512;
+ tmp7 = tmp5 + tmp6;
+ tmp3 = ptrC[partWidth*2];
+ tmp2 += (tmp7 << 4);
+ tmp2 += (tmp7 << 2);
+ tmp7 = ptrInt[partWidth*2];
+ tmp2 += tmp3;
+ tmp2 = clp[tmp2>>10];
+ tmp7 += 16;
+ tmp7 = clp[tmp7>>5];
+ tmp1 += 512;
+ tmp2++;
+ mb[48] = (u8)((tmp7 + tmp2) >> 1);
+
+ tmp7 = tmp3 + tmp6;
+ tmp1 -= (tmp7 << 2);
+ tmp1 -= tmp7;
+ tmp7 = tmp4 + tmp5;
+ tmp2 = ptrC[partWidth];
+ tmp1 += (tmp7 << 4);
+ tmp1 += (tmp7 << 2);
+ tmp7 = ptrInt[partWidth];
+ tmp1 += tmp2;
+ tmp1 = clp[tmp1>>10];
+ tmp7 += 16;
+ tmp7 = clp[tmp7>>5];
+ tmp6 += 512;
+ tmp1++;
+ mb[32] = (u8)((tmp7 + tmp1) >> 1);
+
+ tmp1 = *ptrC;
+ tmp7 = tmp2 + tmp5;
+ tmp6 -= (tmp7 << 2);
+ tmp6 -= tmp7;
+ tmp7 = tmp4 + tmp3;
+ tmp6 += (tmp7 << 4);
+ tmp6 += (tmp7 << 2);
+ tmp7 = *ptrInt;
+ tmp6 += tmp1;
+ tmp6 = clp[tmp6>>10];
+ tmp7 += 16;
+ tmp7 = clp[tmp7>>5];
+ tmp5 += 512;
+ tmp6++;
+ mb[16] = (u8)((tmp7 + tmp6) >> 1);
+
+ tmp6 = ptrC[-(i32)partWidth];
+ tmp1 += tmp4;
+ tmp5 -= (tmp1 << 2);
+ tmp5 -= tmp1;
+ tmp3 += tmp2;
+ tmp5 += (tmp3 << 4);
+ tmp5 += (tmp3 << 2);
+ tmp7 = ptrInt[-(i32)partWidth];
+ tmp5 += tmp6;
+ tmp5 = clp[tmp5>>10];
+ tmp7 += 16;
+ tmp7 = clp[tmp7>>5];
+ tmp5++;
+ *mb++ = (u8)((tmp7 + tmp5) >> 1);
+ ptrC++;
+ ptrInt++;
+ }
+ mb += 4*16 - partWidth;
+ ptrC += 3*partWidth;
+ ptrV += 3*partWidth;
+ ptrInt += 3*partWidth;
+ }
+
+}
+
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdInterpolateMidHorQuarter
+
+ Functional description:
+ Function to perform horizontal and vertical interpolation of pixel
+ position 'i' or 'k' for a block. Overfilling is done only if needed.
+ Reference image (ref) is read at correct position and the predicted
+ part is written to macroblock array (mb)
+
+------------------------------------------------------------------------------*/
+
+void h264bsdInterpolateMidHorQuarter(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight,
+ u32 horOffset) /* 0 for pixel i, 1 for pixel k */
+{
+ u32 p1[21*21/4+1];
+ u32 x, y;
+ i32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ i32 *ptrJ, *ptrInt, *h1;
+ u8 *ptrC, *ptrV;
+ i32 table[21*16];
+ i32 tableWidth = (i32)partWidth+5;
+ const u8 *clp = h264bsdClip + 512;
+
+ /* Code */
+
+ ASSERT(ref);
+ ASSERT(mb);
+
+ if ((x0 < 0) || ((u32)x0+partWidth+5 > width) ||
+ (y0 < 0) || ((u32)y0+partHeight+5 > height))
+ {
+ h264bsdFillBlock(ref, (u8*)p1, x0, y0, width, height,
+ partWidth+5, partHeight+5, partWidth+5);
+
+ x0 = 0;
+ y0 = 0;
+ ref = (u8*)p1;
+ width = partWidth+5;
+ }
+
+ ref += (u32)y0 * width + (u32)x0;
+
+ h1 = table + tableWidth;
+ ptrC = ref + width;
+ ptrV = ptrC + 5*width;
+
+ /* First step: calculate intermediate values for
+ * vertical interpolation */
+ for (y = (partHeight >> 2); y; y--)
+ {
+ for (x = (u32)tableWidth; x; x--)
+ {
+ tmp4 = ptrV[-(i32)width*2];
+ tmp5 = ptrV[-(i32)width];
+ tmp1 = ptrV[width];
+ tmp2 = ptrV[width*2];
+ tmp6 = *ptrV++;
+
+ tmp7 = tmp4 + tmp1;
+ tmp2 -= (tmp7 << 2);
+ tmp2 -= tmp7;
+ tmp7 = tmp5 + tmp6;
+ tmp3 = ptrC[width*2];
+ tmp2 += (tmp7 << 4);
+ tmp2 += (tmp7 << 2);
+ tmp2 += tmp3;
+ h1[tableWidth*2] = tmp2;
+
+ tmp7 = tmp3 + tmp6;
+ tmp1 -= (tmp7 << 2);
+ tmp1 -= tmp7;
+ tmp7 = tmp4 + tmp5;
+ tmp2 = ptrC[width];
+ tmp1 += (tmp7 << 4);
+ tmp1 += (tmp7 << 2);
+ tmp1 += tmp2;
+ h1[tableWidth] = tmp1;
+
+ tmp1 = *ptrC;
+ tmp7 = tmp2 + tmp5;
+ tmp6 -= (tmp7 << 2);
+ tmp6 -= tmp7;
+ tmp7 = tmp4 + tmp3;
+ tmp6 += (tmp7 << 4);
+ tmp6 += (tmp7 << 2);
+ tmp6 += tmp1;
+ *h1 = tmp6;
+
+ tmp6 = ptrC[-(i32)width];
+ tmp1 += tmp4;
+ tmp5 -= (tmp1 << 2);
+ tmp5 -= tmp1;
+ tmp3 += tmp2;
+ tmp5 += (tmp3 << 4);
+ tmp5 += (tmp3 << 2);
+ tmp5 += tmp6;
+ h1[-tableWidth] = tmp5;
+ h1++;
+ ptrC++;
+ }
+ ptrC += 4*width - partWidth - 5;
+ ptrV += 4*width - partWidth - 5;
+ h1 += 3*tableWidth;
+ }
+
+ /* Second step: calculate horizontal interpolation and average */
+ ptrJ = table + 5;
+ /* Pointer to integer sample position, either G or H */
+ ptrInt = table + 2 + horOffset;
+ for (y = partHeight; y; y--)
+ {
+ tmp6 = *(ptrJ - 5);
+ tmp5 = *(ptrJ - 4);
+ tmp4 = *(ptrJ - 3);
+ tmp3 = *(ptrJ - 2);
+ tmp2 = *(ptrJ - 1);
+ for (x = (partWidth>>2); x; x--)
+ {
+ /* First pixel */
+ tmp6 += 512;
+ tmp7 = tmp3 + tmp4;
+ tmp6 += (tmp7 << 4);
+ tmp6 += (tmp7 << 2);
+ tmp7 = tmp2 + tmp5;
+ tmp1 = *ptrJ++;
+ tmp6 -= (tmp7 << 2);
+ tmp6 -= tmp7;
+ tmp7 = *ptrInt++;
+ tmp6 += tmp1;
+ tmp6 = clp[tmp6 >> 10];
+ tmp7 += 16;
+ tmp7 = clp[tmp7 >> 5];
+ tmp5 += 512;
+ tmp6++;
+ *mb++ = (u8)((tmp6 + tmp7) >> 1);
+ /* Second pixel */
+ tmp7 = tmp2 + tmp3;
+ tmp5 += (tmp7 << 4);
+ tmp5 += (tmp7 << 2);
+ tmp7 = tmp1 + tmp4;
+ tmp6 = *ptrJ++;
+ tmp5 -= (tmp7 << 2);
+ tmp5 -= tmp7;
+ tmp7 = *ptrInt++;
+ tmp5 += tmp6;
+ tmp5 = clp[tmp5 >> 10];
+ tmp7 += 16;
+ tmp7 = clp[tmp7 >> 5];
+ tmp4 += 512;
+ tmp5++;
+ *mb++ = (u8)((tmp5 + tmp7) >> 1);
+ /* Third pixel */
+ tmp7 = tmp1 + tmp2;
+ tmp4 += (tmp7 << 4);
+ tmp4 += (tmp7 << 2);
+ tmp7 = tmp6 + tmp3;
+ tmp5 = *ptrJ++;
+ tmp4 -= (tmp7 << 2);
+ tmp4 -= tmp7;
+ tmp7 = *ptrInt++;
+ tmp4 += tmp5;
+ tmp4 = clp[tmp4 >> 10];
+ tmp7 += 16;
+ tmp7 = clp[tmp7 >> 5];
+ tmp3 += 512;
+ tmp4++;
+ *mb++ = (u8)((tmp4 + tmp7) >> 1);
+ /* Fourth pixel */
+ tmp7 = tmp6 + tmp1;
+ tmp3 += (tmp7 << 4);
+ tmp3 += (tmp7 << 2);
+ tmp7 = tmp5 + tmp2;
+ tmp4 = *ptrJ++;
+ tmp3 -= (tmp7 << 2);
+ tmp3 -= tmp7;
+ tmp7 = *ptrInt++;
+ tmp3 += tmp4;
+ tmp3 = clp[tmp3 >> 10];
+ tmp7 += 16;
+ tmp7 = clp[tmp7 >> 5];
+ tmp3++;
+ *mb++ = (u8)((tmp3 + tmp7) >> 1);
+ tmp3 = tmp5;
+ tmp5 = tmp1;
+ tmp7 = tmp4;
+ tmp4 = tmp6;
+ tmp6 = tmp2;
+ tmp2 = tmp7;
+ }
+ ptrJ += 5;
+ ptrInt += 5;
+ mb += 16 - partWidth;
+ }
+
+}
+
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdPredictSamples
+
+ Functional description:
+ This function reconstructs a prediction for a macroblock partition.
+ The prediction is either copied or interpolated using the reference
+ frame and the motion vector. Both luminance and chrominance parts are
+ predicted. The prediction is stored in given macroblock array (data).
+ Inputs:
+ data pointer to macroblock array (384 bytes) for output
+ mv pointer to motion vector used for prediction
+ refPic pointer to reference picture structure
+ xA x-coordinate for current macroblock
+ yA y-coordinate for current macroblock
+ partX x-offset for partition in macroblock
+ partY y-offset for partition in macroblock
+ partWidth width of partition
+ partHeight height of partition
+ Outputs:
+ data macroblock array (16x16+8x8+8x8) where predicted
+ partition is stored at correct position
+
+------------------------------------------------------------------------------*/
+
+void h264bsdPredictSamples(
+ u8 *data,
+ mv_t *mv,
+ image_t *refPic,
+ u32 xA,
+ u32 yA,
+ u32 partX,
+ u32 partY,
+ u32 partWidth,
+ u32 partHeight)
+
+{
+
+/* Variables */
+
+ u32 xFrac, yFrac, width, height;
+ i32 xInt, yInt;
+ u8 *lumaPartData;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(mv);
+ ASSERT(partWidth);
+ ASSERT(partHeight);
+ ASSERT(refPic);
+ ASSERT(refPic->data);
+ ASSERT(refPic->width);
+ ASSERT(refPic->height);
+
+ /* luma */
+ lumaPartData = data + 16*partY + partX;
+
+ xFrac = mv->hor & 0x3;
+ yFrac = mv->ver & 0x3;
+
+ width = 16 * refPic->width;
+ height = 16 * refPic->height;
+
+ xInt = (i32)xA + (i32)partX + (mv->hor >> 2);
+ yInt = (i32)yA + (i32)partY + (mv->ver >> 2);
+
+ ASSERT(lumaFracPos[xFrac][yFrac] < 16);
+
+ switch (lumaFracPos[xFrac][yFrac])
+ {
+ case 0: /* G */
+ h264bsdFillBlock(refPic->data, lumaPartData,
+ xInt,yInt,width,height,partWidth,partHeight,16);
+ break;
+ case 1: /* d */
+ h264bsdInterpolateVerQuarter(refPic->data, lumaPartData,
+ xInt, yInt-2, width, height, partWidth, partHeight, 0);
+ break;
+ case 2: /* h */
+ h264bsdInterpolateVerHalf(refPic->data, lumaPartData,
+ xInt, yInt-2, width, height, partWidth, partHeight);
+ break;
+ case 3: /* n */
+ h264bsdInterpolateVerQuarter(refPic->data, lumaPartData,
+ xInt, yInt-2, width, height, partWidth, partHeight, 1);
+ break;
+ case 4: /* a */
+ h264bsdInterpolateHorQuarter(refPic->data, lumaPartData,
+ xInt-2, yInt, width, height, partWidth, partHeight, 0);
+ break;
+ case 5: /* e */
+ h264bsdInterpolateHorVerQuarter(refPic->data, lumaPartData,
+ xInt-2, yInt-2, width, height, partWidth, partHeight, 0);
+ break;
+ case 6: /* i */
+ h264bsdInterpolateMidHorQuarter(refPic->data, lumaPartData,
+ xInt-2, yInt-2, width, height, partWidth, partHeight, 0);
+ break;
+ case 7: /* p */
+ h264bsdInterpolateHorVerQuarter(refPic->data, lumaPartData,
+ xInt-2, yInt-2, width, height, partWidth, partHeight, 2);
+ break;
+ case 8: /* b */
+ h264bsdInterpolateHorHalf(refPic->data, lumaPartData,
+ xInt-2, yInt, width, height, partWidth, partHeight);
+ break;
+ case 9: /* f */
+ h264bsdInterpolateMidVerQuarter(refPic->data, lumaPartData,
+ xInt-2, yInt-2, width, height, partWidth, partHeight, 0);
+ break;
+ case 10: /* j */
+ h264bsdInterpolateMidHalf(refPic->data, lumaPartData,
+ xInt-2, yInt-2, width, height, partWidth, partHeight);
+ break;
+ case 11: /* q */
+ h264bsdInterpolateMidVerQuarter(refPic->data, lumaPartData,
+ xInt-2, yInt-2, width, height, partWidth, partHeight, 1);
+ break;
+ case 12: /* c */
+ h264bsdInterpolateHorQuarter(refPic->data, lumaPartData,
+ xInt-2, yInt, width, height, partWidth, partHeight, 1);
+ break;
+ case 13: /* g */
+ h264bsdInterpolateHorVerQuarter(refPic->data, lumaPartData,
+ xInt-2, yInt-2, width, height, partWidth, partHeight, 1);
+ break;
+ case 14: /* k */
+ h264bsdInterpolateMidHorQuarter(refPic->data, lumaPartData,
+ xInt-2, yInt-2, width, height, partWidth, partHeight, 1);
+ break;
+ default: /* case 15, r */
+ h264bsdInterpolateHorVerQuarter(refPic->data, lumaPartData,
+ xInt-2, yInt-2, width, height, partWidth, partHeight, 3);
+ break;
+ }
+
+ /* chroma */
+ PredictChroma(
+ data + 16*16 + (partY>>1)*8 + (partX>>1),
+ xA + partX,
+ yA + partY,
+ partWidth,
+ partHeight,
+ mv,
+ refPic);
+
+}
+
+#else /* H264DEC_OMXDL */
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdPredictSamples
+
+ Functional description:
+ This function reconstructs a prediction for a macroblock partition.
+ The prediction is either copied or interpolated using the reference
+ frame and the motion vector. Both luminance and chrominance parts are
+ predicted. The prediction is stored in given macroblock array (data).
+ Inputs:
+ data pointer to macroblock array (384 bytes) for output
+ mv pointer to motion vector used for prediction
+ refPic pointer to reference picture structure
+ xA x-coordinate for current macroblock
+ yA y-coordinate for current macroblock
+ partX x-offset for partition in macroblock
+ partY y-offset for partition in macroblock
+ partWidth width of partition
+ partHeight height of partition
+ Outputs:
+ data macroblock array (16x16+8x8+8x8) where predicted
+ partition is stored at correct position
+
+------------------------------------------------------------------------------*/
+
+/*lint -e{550} Symbol 'res' not accessed */
+void h264bsdPredictSamples(
+ u8 *data,
+ mv_t *mv,
+ image_t *refPic,
+ u32 colAndRow,
+ u32 part,
+ u8 *pFill)
+
+{
+
+/* Variables */
+
+ u32 xFrac, yFrac;
+ u32 width, height;
+ i32 xInt, yInt, x0, y0;
+ u8 *partData, *ref;
+ OMXSize roi;
+ u32 fillWidth;
+ u32 fillHeight;
+ OMXResult res;
+ u32 xA, yA;
+ u32 partX, partY;
+ u32 partWidth, partHeight;
+
+/* Code */
+
+ ASSERT(data);
+ ASSERT(mv);
+ ASSERT(refPic);
+ ASSERT(refPic->data);
+ ASSERT(refPic->width);
+ ASSERT(refPic->height);
+
+ xA = (colAndRow & 0xFFFF0000) >> 16;
+ yA = (colAndRow & 0x0000FFFF);
+
+ partX = (part & 0xFF000000) >> 24;
+ partY = (part & 0x00FF0000) >> 16;
+ partWidth = (part & 0x0000FF00) >> 8;
+ partHeight = (part & 0x000000FF);
+
+ ASSERT(partWidth);
+ ASSERT(partHeight);
+
+ /* luma */
+ partData = data + 16*partY + partX;
+
+ xFrac = mv->hor & 0x3;
+ yFrac = mv->ver & 0x3;
+
+ width = 16 * refPic->width;
+ height = 16 * refPic->height;
+
+ xInt = (i32)xA + (i32)partX + (mv->hor >> 2);
+ yInt = (i32)yA + (i32)partY + (mv->ver >> 2);
+
+ x0 = (xFrac) ? xInt-2 : xInt;
+ y0 = (yFrac) ? yInt-2 : yInt;
+
+ if (xFrac)
+ {
+ if (partWidth == 16)
+ fillWidth = 32;
+ else
+ fillWidth = 16;
+ }
+ else
+ fillWidth = (partWidth*2);
+ if (yFrac)
+ fillHeight = partHeight+5;
+ else
+ fillHeight = partHeight;
+
+
+ if ((x0 < 0) || ((u32)x0+fillWidth > width) ||
+ (y0 < 0) || ((u32)y0+fillHeight > height))
+ {
+ h264bsdFillBlock(refPic->data, (u8*)pFill, x0, y0, width, height,
+ fillWidth, fillHeight, fillWidth);
+
+ x0 = 0;
+ y0 = 0;
+ ref = pFill;
+ width = fillWidth;
+ if (yFrac)
+ ref += 2*width;
+ if (xFrac)
+ ref += 2;
+ }
+ else
+ {
+ /*lint --e(737) Loss of sign */
+ ref = refPic->data + yInt*width + xInt;
+ }
+ /* Luma interpolation */
+ roi.width = (i32)partWidth;
+ roi.height = (i32)partHeight;
+
+ res = omxVCM4P10_InterpolateLuma(ref, (i32)width, partData, 16,
+ (i32)xFrac, (i32)yFrac, roi);
+ ASSERT(res == 0);
+
+ /* Chroma */
+ width = 8 * refPic->width;
+ height = 8 * refPic->height;
+
+ x0 = ((xA + partX) >> 1) + (mv->hor >> 3);
+ y0 = ((yA + partY) >> 1) + (mv->ver >> 3);
+ xFrac = mv->hor & 0x7;
+ yFrac = mv->ver & 0x7;
+
+ ref = refPic->data + 256 * refPic->width * refPic->height;
+
+ roi.width = (i32)(partWidth >> 1);
+ fillWidth = ((partWidth >> 1) + 8) & ~0x7;
+ roi.height = (i32)(partHeight >> 1);
+ fillHeight = (partHeight >> 1) + 1;
+
+ if ((x0 < 0) || ((u32)x0+fillWidth > width) ||
+ (y0 < 0) || ((u32)y0+fillHeight > height))
+ {
+ h264bsdFillBlock(ref, pFill, x0, y0, width, height,
+ fillWidth, fillHeight, fillWidth);
+ ref += width * height;
+ h264bsdFillBlock(ref, pFill + fillWidth*fillHeight,
+ x0, y0, width, height, fillWidth,
+ fillHeight, fillWidth);
+
+ ref = pFill;
+ x0 = 0;
+ y0 = 0;
+ width = fillWidth;
+ height = fillHeight;
+ }
+
+ partData = data + 16*16 + (partY>>1)*8 + (partX>>1);
+
+ /* Chroma interpolation */
+ /*lint --e(737) Loss of sign */
+ ref += y0 * width + x0;
+ res = armVCM4P10_Interpolate_Chroma(ref, width, partData, 8,
+ (u32)roi.width, (u32)roi.height, xFrac, yFrac);
+ ASSERT(res == 0);
+ partData += 8 * 8;
+ ref += height * width;
+ res = armVCM4P10_Interpolate_Chroma(ref, width, partData, 8,
+ (u32)roi.width, (u32)roi.height, xFrac, yFrac);
+ ASSERT(res == 0);
+
+}
+
+#endif /* H264DEC_OMXDL */
+
+
+/*------------------------------------------------------------------------------
+
+ Function: FillRow1
+
+ Functional description:
+ This function gets a row of reference pels in a 'normal' case when no
+ overfilling is necessary.
+
+------------------------------------------------------------------------------*/
+
+static void FillRow1(
+ u8 *ref,
+ u8 *fill,
+ i32 left,
+ i32 center,
+ i32 right)
+{
+
+ ASSERT(ref);
+ ASSERT(fill);
+
+ H264SwDecMemcpy(fill, ref, (u32)center);
+
+ /*lint -e(715) */
+}
+
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdFillRow7
+
+ Functional description:
+ This function gets a row of reference pels when horizontal coordinate
+ is partly negative or partly greater than reference picture width
+ (overfilling some pels on left and/or right edge).
+ Inputs:
+ ref pointer to reference samples
+ left amount of pixels to overfill on left-edge
+ center amount of pixels to copy
+ right amount of pixels to overfill on right-edge
+ Outputs:
+ fill pointer where samples are stored
+
+------------------------------------------------------------------------------*/
+#ifndef H264DEC_NEON
+void h264bsdFillRow7(
+ u8 *ref,
+ u8 *fill,
+ i32 left,
+ i32 center,
+ i32 right)
+{
+ u8 tmp;
+
+ ASSERT(ref);
+ ASSERT(fill);
+
+ if (left)
+ tmp = *ref;
+
+ for ( ; left; left--)
+ /*lint -esym(644,tmp) tmp is initialized if used */
+ *fill++ = tmp;
+
+ for ( ; center; center--)
+ *fill++ = *ref++;
+
+ if (right)
+ tmp = ref[-1];
+
+ for ( ; right; right--)
+ /*lint -esym(644,tmp) tmp is initialized if used */
+ *fill++ = tmp;
+}
+#endif
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdFillBlock
+
+ Functional description:
+ This function gets a block of reference pels. It determines whether
+ overfilling is needed or not and repeatedly calls an appropriate
+ function (by using a function pointer) that fills one row the block.
+ Inputs:
+ ref pointer to reference frame
+ x0 x-coordinate for block
+ y0 y-coordinate for block
+ width width of reference frame
+ height height of reference frame
+ blockWidth width of block
+ blockHeight height of block
+ fillScanLength length of a line in output array (pixels)
+ Outputs:
+ fill pointer to array where output block is written
+
+------------------------------------------------------------------------------*/
+
+void h264bsdFillBlock(
+ u8 *ref,
+ u8 *fill,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 blockWidth,
+ u32 blockHeight,
+ u32 fillScanLength)
+
+{
+
+/* Variables */
+
+ i32 xstop, ystop;
+ void (*fp)(u8*, u8*, i32, i32, i32);
+ i32 left, x, right;
+ i32 top, y, bottom;
+
+/* Code */
+
+ ASSERT(ref);
+ ASSERT(fill);
+ ASSERT(width);
+ ASSERT(height);
+ ASSERT(fill);
+ ASSERT(blockWidth);
+ ASSERT(blockHeight);
+
+ xstop = x0 + (i32)blockWidth;
+ ystop = y0 + (i32)blockHeight;
+
+ /* Choose correct function whether overfilling on left-edge or right-edge
+ * is needed or not */
+ if (x0 >= 0 && xstop <= (i32)width)
+ fp = FillRow1;
+ else
+ fp = h264bsdFillRow7;
+
+ if (ystop < 0)
+ y0 = -(i32)blockHeight;
+
+ if (xstop < 0)
+ x0 = -(i32)blockWidth;
+
+ if (y0 > (i32)height)
+ y0 = (i32)height;
+
+ if (x0 > (i32)width)
+ x0 = (i32)width;
+
+ xstop = x0 + (i32)blockWidth;
+ ystop = y0 + (i32)blockHeight;
+
+ if (x0 > 0)
+ ref += x0;
+
+ if (y0 > 0)
+ ref += y0 * (i32)width;
+
+ left = x0 < 0 ? -x0 : 0;
+ right = xstop > (i32)width ? xstop - (i32)width : 0;
+ x = (i32)blockWidth - left - right;
+
+ top = y0 < 0 ? -y0 : 0;
+ bottom = ystop > (i32)height ? ystop - (i32)height : 0;
+ y = (i32)blockHeight - top - bottom;
+
+ /* Top-overfilling */
+ for ( ; top; top-- )
+ {
+ (*fp)(ref, fill, left, x, right);
+ fill += fillScanLength;
+ }
+
+ /* Lines inside reference image */
+ for ( ; y; y-- )
+ {
+ (*fp)(ref, fill, left, x, right);
+ ref += width;
+ fill += fillScanLength;
+ }
+
+ ref -= width;
+
+ /* Bottom-overfilling */
+ for ( ; bottom; bottom-- )
+ {
+ (*fp)(ref, fill, left, x, right);
+ fill += fillScanLength;
+ }
+}
+
+/*lint +e701 +e702 */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.h
new file mode 100755
index 0000000..5a1a140
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_reconstruct.h
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_RECONSTRUCT_H
+#define H264SWDEC_RECONSTRUCT_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_macroblock_layer.h"
+#include "h264bsd_image.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+#ifndef H264DEC_OMXDL
+void h264bsdPredictSamples(
+ u8 *data,
+ mv_t *mv,
+ image_t *refPic,
+ u32 xA,
+ u32 yA,
+ u32 partX,
+ u32 partY,
+ u32 partWidth,
+ u32 partHeight);
+#else
+void h264bsdPredictSamples(
+ u8 *data,
+ mv_t *mv,
+ image_t *refPic,
+ u32 colAndRow,/* packaged data | column | row |*/
+ u32 part, /* packaged data |partX|partY|partWidth|partHeight|*/
+ u8 *pFill);
+#endif
+
+void h264bsdFillBlock(
+ u8 * ref,
+ u8 * fill,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 blockWidth,
+ u32 blockHeight,
+ u32 fillScanLength);
+
+void h264bsdInterpolateChromaHor(
+ u8 *pRef,
+ u8 *predPartChroma,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 xFrac,
+ u32 chromaPartWidth,
+ u32 chromaPartHeight);
+
+void h264bsdInterpolateChromaVer(
+ u8 *pRef,
+ u8 *predPartChroma,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 yFrac,
+ u32 chromaPartWidth,
+ u32 chromaPartHeight);
+
+void h264bsdInterpolateChromaHorVer(
+ u8 *ref,
+ u8 *predPartChroma,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 xFrac,
+ u32 yFrac,
+ u32 chromaPartWidth,
+ u32 chromaPartHeight);
+
+void h264bsdInterpolateVerHalf(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight);
+
+void h264bsdInterpolateVerQuarter(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight,
+ u32 verOffset);
+
+void h264bsdInterpolateHorHalf(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight);
+
+void h264bsdInterpolateHorQuarter(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight,
+ u32 horOffset);
+
+void h264bsdInterpolateHorVerQuarter(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight,
+ u32 horVerOffset);
+
+void h264bsdInterpolateMidHalf(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight);
+
+void h264bsdInterpolateMidVerQuarter(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight,
+ u32 verOffset);
+
+void h264bsdInterpolateMidHorQuarter(
+ u8 *ref,
+ u8 *mb,
+ i32 x0,
+ i32 y0,
+ u32 width,
+ u32 height,
+ u32 partWidth,
+ u32 partHeight,
+ u32 horOffset);
+
+
+void h264bsdFillRow7(
+ u8 *ref,
+ u8 *fill,
+ i32 left,
+ i32 center,
+ i32 right);
+
+#endif /* #ifdef H264SWDEC_RECONSTRUCT_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.c
new file mode 100755
index 0000000..0756c47
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.c
@@ -0,0 +1,1692 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdDecodeSeiMessage
+ DecodeBufferingPeriod
+ DecodePictureTiming
+ DecodePanScanRectangle
+ DecodeFillerPayload
+ DecodeUserDataRegisteredITuTT35
+ DecodeUserDataUnregistered
+ DecodeRecoveryPoint
+ DecodeDecRefPicMarkingRepetition
+ DecodeSparePic
+ DecodeSceneInfo
+ DecodeSubSeqInfo
+ DecodeSubSeqLayerCharacteristics
+ DecodeSubSeqCharacteristics
+ DecodeFullFrameFreeze
+ DecodeFullFrameSnapshot
+ DecodeProgressiveRefinementSegmentStart
+ DecodeProgressiveRefinementSegmentEnd
+ DecodeMotionConstrainedSliceGroupSet
+ DecodeReservedSeiMessage
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_sei.h"
+#include "basetype.h"
+#include "h264bsd_util.h"
+#include "h264bsd_stream.h"
+#include "h264bsd_vlc.h"
+#include "h264bsd_seq_param_set.h"
+#include "h264bsd_slice_header.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+static const u32 numClockTS[9] = {1,1,1,2,2,3,3,2,3};
+static const u32 ceilLog2NumSliceGroups[9] = {0,1,1,2,2,3,3,3,3};
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static u32 DecodeBufferingPeriod(
+ strmData_t *pStrmData,
+ seiBufferingPeriod_t *pBufferingPeriod,
+ u32 cpbCnt,
+ u32 initialCpbRemovalDelayLength,
+ u32 nalHrdBpPresentFlag,
+ u32 vclHrdBpPresentFlag);
+
+static u32 DecodePictureTiming(
+ strmData_t *pStrmData,
+ seiPicTiming_t *pPicTiming,
+ u32 cpbRemovalDelayLength,
+ u32 dpbOutputDelayLength,
+ u32 timeOffsetLength,
+ u32 cpbDpbDelaysPresentFlag,
+ u32 picStructPresentFlag);
+
+static u32 DecodePanScanRectangle(
+ strmData_t *pStrmData,
+ seiPanScanRect_t *pPanScanRectangle);
+
+static u32 DecodeFillerPayload(strmData_t *pStrmData, u32 payloadSize);
+
+static u32 DecodeUserDataRegisteredITuTT35(
+ strmData_t *pStrmData,
+ seiUserDataRegisteredItuTT35_t *pUserDataRegisteredItuTT35,
+ u32 payloadSize);
+
+static u32 DecodeUserDataUnregistered(
+ strmData_t *pStrmData,
+ seiUserDataUnregistered_t *pUserDataUnregistered,
+ u32 payloadSize);
+
+static u32 DecodeRecoveryPoint(
+ strmData_t *pStrmData,
+ seiRecoveryPoint_t *pRecoveryPoint);
+
+static u32 DecodeDecRefPicMarkingRepetition(
+ strmData_t *pStrmData,
+ seiDecRefPicMarkingRepetition_t *pDecRefPicMarkingRepetition,
+ u32 numRefFrames);
+
+static u32 DecodeSparePic(
+ strmData_t *pStrmData,
+ seiSparePic_t *pSparePic,
+ u32 picSizeInMapUnits);
+
+static u32 DecodeSceneInfo(
+ strmData_t *pStrmData,
+ seiSceneInfo_t *pSceneInfo);
+
+static u32 DecodeSubSeqInfo(
+ strmData_t *pStrmData,
+ seiSubSeqInfo_t *pSubSeqInfo);
+
+static u32 DecodeSubSeqLayerCharacteristics(
+ strmData_t *pStrmData,
+ seiSubSeqLayerCharacteristics_t *pSubSeqLayerCharacteristics);
+
+static u32 DecodeSubSeqCharacteristics(
+ strmData_t *pStrmData,
+ seiSubSeqCharacteristics_t *pSubSeqCharacteristics);
+
+static u32 DecodeFullFrameFreeze(
+ strmData_t *pStrmData,
+ seiFullFrameFreeze_t *pFullFrameFreeze);
+
+static u32 DecodeFullFrameSnapshot(
+ strmData_t *pStrmData,
+ seiFullFrameSnapshot_t *pFullFrameSnapshot);
+
+static u32 DecodeProgressiveRefinementSegmentStart(
+ strmData_t *pStrmData,
+ seiProgressiveRefinementSegmentStart_t *pProgressiveRefinementSegmentStart);
+
+static u32 DecodeProgressiveRefinementSegmentEnd(
+ strmData_t *pStrmData,
+ seiProgressiveRefinementSegmentEnd_t *pProgressiveRefinementSegmentEnd);
+
+static u32 DecodeMotionConstrainedSliceGroupSet(
+ strmData_t *pStrmData,
+ seiMotionConstrainedSliceGroupSet_t *pMotionConstrainedSliceGroupSet,
+ u32 numSliceGroups);
+
+static u32 DecodeReservedSeiMessage(
+ strmData_t *pStrmData,
+ seiReservedSeiMessage_t *pReservedSeiMessage,
+ u32 payloadSize);
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdDecodeSeiMessage
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeSeiMessage(
+ strmData_t *pStrmData,
+ seqParamSet_t *pSeqParamSet,
+ seiMessage_t *pSeiMessage,
+ u32 numSliceGroups)
+{
+
+/* Variables */
+
+ u32 tmp, payloadType, payloadSize, status;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSeiMessage);
+
+
+ H264SwDecMemset(pSeiMessage, 0, sizeof(seiMessage_t));
+
+ do
+ {
+ payloadType = 0;
+ while((tmp = h264bsdGetBits(pStrmData, 8)) == 0xFF)
+ {
+ payloadType += 255;
+ }
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ payloadType += tmp;
+
+ payloadSize = 0;
+ while((tmp = h264bsdGetBits(pStrmData, 8)) == 0xFF)
+ {
+ payloadSize += 255;
+ }
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ payloadSize += tmp;
+
+ pSeiMessage->payloadType = payloadType;
+
+ switch (payloadType)
+ {
+ case 0:
+ ASSERT(pSeqParamSet);
+ status = DecodeBufferingPeriod(
+ pStrmData,
+ &pSeiMessage->bufferingPeriod,
+ pSeqParamSet->vuiParameters->vclHrdParameters.cpbCnt,
+ pSeqParamSet->vuiParameters->vclHrdParameters.
+ initialCpbRemovalDelayLength,
+ pSeqParamSet->vuiParameters->nalHrdParametersPresentFlag,
+ pSeqParamSet->vuiParameters->vclHrdParametersPresentFlag);
+ break;
+
+ case 1:
+ ASSERT(pSeqParamSet->vuiParametersPresentFlag);
+ status = DecodePictureTiming(
+ pStrmData,
+ &pSeiMessage->picTiming,
+ pSeqParamSet->vuiParameters->vclHrdParameters.
+ cpbRemovalDelayLength,
+ pSeqParamSet->vuiParameters->vclHrdParameters.
+ dpbOutputDelayLength,
+ pSeqParamSet->vuiParameters->vclHrdParameters.
+ timeOffsetLength,
+ pSeqParamSet->vuiParameters->nalHrdParametersPresentFlag ||
+ pSeqParamSet->vuiParameters->vclHrdParametersPresentFlag ?
+ HANTRO_TRUE : HANTRO_FALSE,
+ pSeqParamSet->vuiParameters->picStructPresentFlag);
+ break;
+
+ case 2:
+ status = DecodePanScanRectangle(
+ pStrmData,
+ &pSeiMessage->panScanRect);
+ break;
+
+ case 3:
+ status = DecodeFillerPayload(pStrmData, payloadSize);
+ break;
+
+ case 4:
+ status = DecodeUserDataRegisteredITuTT35(
+ pStrmData,
+ &pSeiMessage->userDataRegisteredItuTT35,
+ payloadSize);
+ break;
+
+ case 5:
+ status = DecodeUserDataUnregistered(
+ pStrmData,
+ &pSeiMessage->userDataUnregistered,
+ payloadSize);
+ break;
+
+ case 6:
+ status = DecodeRecoveryPoint(
+ pStrmData,
+ &pSeiMessage->recoveryPoint);
+ break;
+
+ case 7:
+ status = DecodeDecRefPicMarkingRepetition(
+ pStrmData,
+ &pSeiMessage->decRefPicMarkingRepetition,
+ pSeqParamSet->numRefFrames);
+ break;
+
+ case 8:
+ ASSERT(pSeqParamSet);
+ status = DecodeSparePic(
+ pStrmData,
+ &pSeiMessage->sparePic,
+ pSeqParamSet->picWidthInMbs * pSeqParamSet->picHeightInMbs);
+ break;
+
+ case 9:
+ status = DecodeSceneInfo(
+ pStrmData,
+ &pSeiMessage->sceneInfo);
+ break;
+
+ case 10:
+ status = DecodeSubSeqInfo(
+ pStrmData,
+ &pSeiMessage->subSeqInfo);
+ break;
+
+ case 11:
+ status = DecodeSubSeqLayerCharacteristics(
+ pStrmData,
+ &pSeiMessage->subSeqLayerCharacteristics);
+ break;
+
+ case 12:
+ status = DecodeSubSeqCharacteristics(
+ pStrmData,
+ &pSeiMessage->subSeqCharacteristics);
+ break;
+
+ case 13:
+ status = DecodeFullFrameFreeze(
+ pStrmData,
+ &pSeiMessage->fullFrameFreeze);
+ break;
+
+ case 14: /* This SEI does not contain data, what to do ??? */
+ status = HANTRO_OK;
+ break;
+
+ case 15:
+ status = DecodeFullFrameSnapshot(
+ pStrmData,
+ &pSeiMessage->fullFrameSnapshot);
+ break;
+
+ case 16:
+ status = DecodeProgressiveRefinementSegmentStart(
+ pStrmData,
+ &pSeiMessage->progressiveRefinementSegmentStart);
+ break;
+
+ case 17:
+ status = DecodeProgressiveRefinementSegmentEnd(
+ pStrmData,
+ &pSeiMessage->progressiveRefinementSegmentEnd);
+ break;
+
+ case 18:
+ ASSERT(numSliceGroups);
+ status = DecodeMotionConstrainedSliceGroupSet(
+ pStrmData,
+ &pSeiMessage->motionConstrainedSliceGroupSet,
+ numSliceGroups);
+ break;
+
+ default:
+ status = DecodeReservedSeiMessage(
+ pStrmData,
+ &pSeiMessage->reservedSeiMessage,
+ payloadSize);
+ break;
+ }
+
+ if (status != HANTRO_OK)
+ return(status);
+
+ while (!h264bsdIsByteAligned(pStrmData))
+ {
+ if (h264bsdGetBits(pStrmData, 1) != 1)
+ return(HANTRO_NOK);
+ while (!h264bsdIsByteAligned(pStrmData))
+ {
+ if (h264bsdGetBits(pStrmData, 1) != 0)
+ return(HANTRO_NOK);
+ }
+ }
+ } while (h264bsdMoreRbspData(pStrmData));
+
+ return(h264bsdRbspTrailingBits(pStrmData));
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeBufferingPeriod
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeBufferingPeriod(
+ strmData_t *pStrmData,
+ seiBufferingPeriod_t *pBufferingPeriod,
+ u32 cpbCnt,
+ u32 initialCpbRemovalDelayLength,
+ u32 nalHrdBpPresentFlag,
+ u32 vclHrdBpPresentFlag)
+{
+
+/* Variables */
+
+ u32 tmp, i;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pBufferingPeriod);
+ ASSERT(cpbCnt);
+ ASSERT(initialCpbRemovalDelayLength);
+
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pBufferingPeriod->seqParameterSetId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pBufferingPeriod->seqParameterSetId > 31)
+ return(HANTRO_NOK);
+
+ if (nalHrdBpPresentFlag)
+ {
+ for (i = 0; i < cpbCnt; i++)
+ {
+ tmp = h264bsdGetBits(pStrmData, initialCpbRemovalDelayLength);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (tmp == 0)
+ return(HANTRO_NOK);
+ pBufferingPeriod->initialCpbRemovalDelay[i] = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, initialCpbRemovalDelayLength);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pBufferingPeriod->initialCpbRemovalDelayOffset[i] = tmp;
+ }
+ }
+
+ if (vclHrdBpPresentFlag)
+ {
+ for (i = 0; i < cpbCnt; i++)
+ {
+ tmp = h264bsdGetBits(pStrmData, initialCpbRemovalDelayLength);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pBufferingPeriod->initialCpbRemovalDelay[i] = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, initialCpbRemovalDelayLength);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pBufferingPeriod->initialCpbRemovalDelayOffset[i] = tmp;
+ }
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodePictureTiming
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodePictureTiming(
+ strmData_t *pStrmData,
+ seiPicTiming_t *pPicTiming,
+ u32 cpbRemovalDelayLength,
+ u32 dpbOutputDelayLength,
+ u32 timeOffsetLength,
+ u32 cpbDpbDelaysPresentFlag,
+ u32 picStructPresentFlag)
+{
+
+/* Variables */
+
+ u32 tmp, i;
+ i32 itmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pPicTiming);
+
+
+ if (cpbDpbDelaysPresentFlag)
+ {
+ tmp = h264bsdGetBits(pStrmData, cpbRemovalDelayLength);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicTiming->cpbRemovalDelay = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, dpbOutputDelayLength);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicTiming->dpbOutputDelay = tmp;
+ }
+
+ if (picStructPresentFlag)
+ {
+ tmp = h264bsdGetBits(pStrmData, 4);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (tmp > 8)
+ return(HANTRO_NOK);
+ pPicTiming->picStruct = tmp;
+
+ for (i = 0; i < numClockTS[pPicTiming->picStruct]; i++)
+ {
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicTiming->clockTimeStampFlag[i] = tmp == 1 ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pPicTiming->clockTimeStampFlag[i])
+ {
+ tmp = h264bsdGetBits(pStrmData, 2);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicTiming->ctType[i] = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicTiming->nuitFieldBasedFlag[i] = tmp == 1 ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 5);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (tmp > 6)
+ return(HANTRO_NOK);
+ pPicTiming->countingType[i] = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicTiming->fullTimeStampFlag[i] = tmp == 1 ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicTiming->discontinuityFlag[i] = tmp == 1 ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicTiming->cntDroppedFlag[i] = tmp == 1 ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 8);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicTiming->nFrames[i] = tmp;
+
+ if (pPicTiming->fullTimeStampFlag[i])
+ {
+ tmp = h264bsdGetBits(pStrmData, 6);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (tmp > 59)
+ return(HANTRO_NOK);
+ pPicTiming->secondsValue[i] = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 6);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (tmp > 59)
+ return(HANTRO_NOK);
+ pPicTiming->minutesValue[i] = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 5);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (tmp > 23)
+ return(HANTRO_NOK);
+ pPicTiming->hoursValue[i] = tmp;
+ }
+ else
+ {
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicTiming->secondsFlag[i] = tmp == 1 ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pPicTiming->secondsFlag[i])
+ {
+ tmp = h264bsdGetBits(pStrmData, 6);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (tmp > 59)
+ return(HANTRO_NOK);
+ pPicTiming->secondsValue[i] = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicTiming->minutesFlag[i] = tmp == 1 ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pPicTiming->minutesFlag[i])
+ {
+ tmp = h264bsdGetBits(pStrmData, 6);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (tmp > 59)
+ return(HANTRO_NOK);
+ pPicTiming->minutesValue[i] = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPicTiming->hoursFlag[i] = tmp == 1 ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pPicTiming->hoursFlag[i])
+ {
+ tmp = h264bsdGetBits(pStrmData, 5);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (tmp > 23)
+ return(HANTRO_NOK);
+ pPicTiming->hoursValue[i] = tmp;
+ }
+ }
+ }
+ }
+ if (timeOffsetLength)
+ {
+ tmp = h264bsdGetBits(pStrmData, timeOffsetLength);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ itmp = (i32)tmp;
+ /* following "converts" timeOffsetLength-bit signed
+ * integer into i32 */
+ /*lint -save -e701 -e702 */
+ itmp <<= (32 - timeOffsetLength);
+ itmp >>= (32 - timeOffsetLength);
+ /*lint -restore */
+ pPicTiming->timeOffset[i] = itmp;
+ }
+ else
+ pPicTiming->timeOffset[i] = 0;
+ }
+ }
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodePanScanRectangle
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodePanScanRectangle(
+ strmData_t *pStrmData,
+ seiPanScanRect_t *pPanScanRectangle)
+{
+
+/* Variables */
+
+ u32 tmp, i;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pPanScanRectangle);
+
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pPanScanRectangle->panScanRectId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pPanScanRectangle->panScanRectCancelFlag = tmp == 1 ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ if (!pPanScanRectangle->panScanRectCancelFlag)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pPanScanRectangle->panScanCnt);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pPanScanRectangle->panScanCnt > 2)
+ return(HANTRO_NOK);
+ pPanScanRectangle->panScanCnt++;
+
+ for (i = 0; i < pPanScanRectangle->panScanCnt; i++)
+ {
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData,
+ &pPanScanRectangle->panScanRectLeftOffset[i]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData,
+ &pPanScanRectangle->panScanRectRightOffset[i]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData,
+ &pPanScanRectangle->panScanRectTopOffset[i]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData,
+ &pPanScanRectangle->panScanRectBottomOffset[i]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pPanScanRectangle->panScanRectRepetitionPeriod);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pPanScanRectangle->panScanRectRepetitionPeriod > 16384)
+ return(HANTRO_NOK);
+ if (pPanScanRectangle->panScanCnt > 1 &&
+ pPanScanRectangle->panScanRectRepetitionPeriod > 1)
+ return(HANTRO_NOK);
+ }
+
+ return(HANTRO_OK);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeFillerPayload
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeFillerPayload(strmData_t *pStrmData, u32 payloadSize)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(pStrmData);
+
+
+ if (payloadSize)
+ if (h264bsdFlushBits(pStrmData, 8 * payloadSize) == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeUserDataRegisteredITuTT35
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeUserDataRegisteredITuTT35(
+ strmData_t *pStrmData,
+ seiUserDataRegisteredItuTT35_t *pUserDataRegisteredItuTT35,
+ u32 payloadSize)
+{
+
+/* Variables */
+
+ u32 tmp, i, j;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pUserDataRegisteredItuTT35);
+ ASSERT(payloadSize);
+
+ tmp = h264bsdGetBits(pStrmData, 8);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pUserDataRegisteredItuTT35->ituTT35CountryCode = tmp;
+
+ if (pUserDataRegisteredItuTT35->ituTT35CountryCode != 0xFF)
+ i = 1;
+ else
+ {
+ tmp = h264bsdGetBits(pStrmData, 8);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pUserDataRegisteredItuTT35->ituTT35CountryCodeExtensionByte = tmp;
+ i = 2;
+ }
+
+ /* where corresponding FREE() ??? */
+ ALLOCATE(pUserDataRegisteredItuTT35->ituTT35PayloadByte,payloadSize-i,u8);
+ pUserDataRegisteredItuTT35->numPayloadBytes = payloadSize - i;
+ if (pUserDataRegisteredItuTT35->ituTT35PayloadByte == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+
+ j = 0;
+ do
+ {
+ tmp = h264bsdGetBits(pStrmData, 8);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pUserDataRegisteredItuTT35->ituTT35PayloadByte[j] = (u8)tmp;
+ i++;
+ j++;
+ } while (i < payloadSize);
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeUserDataUnregistered
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeUserDataUnregistered(
+ strmData_t *pStrmData,
+ seiUserDataUnregistered_t *pUserDataUnregistered,
+ u32 payloadSize)
+{
+
+/* Variables */
+
+ u32 i, tmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pUserDataUnregistered);
+
+
+ for (i = 0; i < 4; i++)
+ {
+ pUserDataUnregistered->uuidIsoIec11578[i] = h264bsdShowBits32(pStrmData);
+ if (h264bsdFlushBits(pStrmData,32) == END_OF_STREAM)
+ return(HANTRO_NOK);
+ }
+
+ /* where corresponding FREE() ??? */
+ ALLOCATE(pUserDataUnregistered->userDataPayloadByte, payloadSize - 16, u8);
+ if (pUserDataUnregistered->userDataPayloadByte == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+
+ pUserDataUnregistered->numPayloadBytes = payloadSize - 16;
+
+ for (i = 0; i < payloadSize - 16; i++)
+ {
+ tmp = h264bsdGetBits(pStrmData, 8);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pUserDataUnregistered->userDataPayloadByte[i] = (u8)tmp;
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeRecoveryPoint
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeRecoveryPoint(
+ strmData_t *pStrmData,
+ seiRecoveryPoint_t *pRecoveryPoint)
+{
+
+/* Variables */
+
+ u32 tmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pRecoveryPoint);
+
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pRecoveryPoint->recoveryFrameCnt);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pRecoveryPoint->exactMatchFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pRecoveryPoint->brokenLinkFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 2);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (tmp > 2)
+ return(HANTRO_NOK);
+ pRecoveryPoint->changingSliceGroupIdc = tmp;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeDecRefPicMarkingRepetition
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeDecRefPicMarkingRepetition(
+ strmData_t *pStrmData,
+ seiDecRefPicMarkingRepetition_t *pDecRefPicMarkingRepetition,
+ u32 numRefFrames)
+{
+
+/* Variables */
+
+ u32 tmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pDecRefPicMarkingRepetition);
+
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pDecRefPicMarkingRepetition->originalIdrFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pDecRefPicMarkingRepetition->originalFrameNum);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* frame_mbs_only_flag assumed always true so some field related syntax
+ * elements are skipped, see H.264 standard */
+ tmp = h264bsdDecRefPicMarking(pStrmData,
+ &pDecRefPicMarkingRepetition->decRefPicMarking, NAL_SEI, numRefFrames);
+
+ return(tmp);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeSparePic
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeSparePic(
+ strmData_t *pStrmData,
+ seiSparePic_t *pSparePic,
+ u32 picSizeInMapUnits)
+{
+
+/* Variables */
+
+ u32 tmp, i, j, mapUnitCnt;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSparePic);
+
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSparePic->targetFrameNum);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSparePic->spareFieldFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE;
+ /* do not accept fields */
+ if (pSparePic->spareFieldFlag)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSparePic->numSparePics);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSparePic->numSparePics++;
+ if (pSparePic->numSparePics > MAX_NUM_SPARE_PICS)
+ return(HANTRO_NOK);
+
+ for (i = 0; i < pSparePic->numSparePics; i++)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSparePic->deltaSpareFrameNum[i]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSparePic->spareAreaIdc[i]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pSparePic->spareAreaIdc[i] > 2)
+ return(HANTRO_NOK);
+
+ if (pSparePic->spareAreaIdc[i] == 1)
+ {
+ /* where corresponding FREE() ??? */
+ ALLOCATE(pSparePic->spareUnitFlag[i], picSizeInMapUnits, u32);
+ if (pSparePic->spareUnitFlag[i] == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+ pSparePic->zeroRunLength[i] = NULL;
+
+ for (j = 0; j < picSizeInMapUnits; j++)
+ {
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSparePic->spareUnitFlag[i][j] = tmp == 1 ?
+ HANTRO_TRUE : HANTRO_FALSE;
+ }
+ }
+ else if (pSparePic->spareAreaIdc[i] == 2)
+ {
+ /* where corresponding FREE() ??? */
+ ALLOCATE(pSparePic->zeroRunLength[i], picSizeInMapUnits, u32);
+ if (pSparePic->zeroRunLength[i] == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+ pSparePic->spareUnitFlag[i] = NULL;
+
+ for (j = 0, mapUnitCnt = 0; mapUnitCnt < picSizeInMapUnits; j++)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSparePic->zeroRunLength[i][j]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ mapUnitCnt += pSparePic->zeroRunLength[i][j] + 1;
+ }
+ }
+ }
+
+ /* set rest to null */
+ for (i = pSparePic->numSparePics; i < MAX_NUM_SPARE_PICS; i++)
+ {
+ pSparePic->spareUnitFlag[i] = NULL;
+ pSparePic->zeroRunLength[i] = NULL;
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeSceneInfo
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeSceneInfo(
+ strmData_t *pStrmData,
+ seiSceneInfo_t *pSceneInfo)
+{
+
+/* Variables */
+
+ u32 tmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSceneInfo);
+
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSceneInfo->sceneInfoPresentFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pSceneInfo->sceneInfoPresentFlag)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSceneInfo->sceneId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSceneInfo->sceneTransitionType);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pSceneInfo->sceneTransitionType > 6)
+ return(HANTRO_NOK);
+
+ if (pSceneInfo->sceneTransitionType)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSceneInfo->secondSceneId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeSubSeqInfo
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+-----------------------------------------------------------------------------*/
+
+static u32 DecodeSubSeqInfo(
+ strmData_t *pStrmData,
+ seiSubSeqInfo_t *pSubSeqInfo)
+{
+
+/* Variables */
+
+ u32 tmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSubSeqInfo);
+
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSubSeqInfo->subSeqLayerNum);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pSubSeqInfo->subSeqLayerNum > 255)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSubSeqInfo->subSeqId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pSubSeqInfo->subSeqId > 65535)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSubSeqInfo->firstRefPicFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSubSeqInfo->leadingNonRefPicFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSubSeqInfo->lastPicFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSubSeqInfo->subSeqFrameNumFlag = tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pSubSeqInfo->subSeqFrameNumFlag)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSubSeqInfo->subSeqFrameNum);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeSubSeqLayerCharacteristics
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeSubSeqLayerCharacteristics(
+ strmData_t *pStrmData,
+ seiSubSeqLayerCharacteristics_t *pSubSeqLayerCharacteristics)
+{
+
+/* Variables */
+
+ u32 tmp, i;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSubSeqLayerCharacteristics);
+
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSubSeqLayerCharacteristics->numSubSeqLayers);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSubSeqLayerCharacteristics->numSubSeqLayers++;
+ if (pSubSeqLayerCharacteristics->numSubSeqLayers > MAX_NUM_SUB_SEQ_LAYERS)
+ return(HANTRO_NOK);
+
+ for (i = 0; i < pSubSeqLayerCharacteristics->numSubSeqLayers; i++)
+ {
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSubSeqLayerCharacteristics->accurateStatisticsFlag[i] =
+ tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 16);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSubSeqLayerCharacteristics->averageBitRate[i] = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 16);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSubSeqLayerCharacteristics->averageFrameRate[i] = tmp;
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeSubSeqCharacteristics
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeSubSeqCharacteristics(
+ strmData_t *pStrmData,
+ seiSubSeqCharacteristics_t *pSubSeqCharacteristics)
+{
+
+/* Variables */
+
+ u32 tmp, i;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSubSeqCharacteristics);
+
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSubSeqCharacteristics->subSeqLayerNum);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pSubSeqCharacteristics->subSeqLayerNum > MAX_NUM_SUB_SEQ_LAYERS-1)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSubSeqCharacteristics->subSeqId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pSubSeqCharacteristics->subSeqId > 65535)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSubSeqCharacteristics->durationFlag = tmp == 1 ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pSubSeqCharacteristics->durationFlag)
+ {
+ pSubSeqCharacteristics->subSeqDuration = h264bsdShowBits32(pStrmData);
+ if (h264bsdFlushBits(pStrmData,32) == END_OF_STREAM)
+ return(HANTRO_NOK);
+ }
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSubSeqCharacteristics->averageRateFlag = tmp == 1 ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pSubSeqCharacteristics->averageRateFlag)
+ {
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSubSeqCharacteristics->accurateStatisticsFlag =
+ tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 16);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSubSeqCharacteristics->averageBitRate = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 16);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSubSeqCharacteristics->averageFrameRate = tmp;
+ }
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSubSeqCharacteristics->numReferencedSubseqs);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pSubSeqCharacteristics->numReferencedSubseqs > MAX_NUM_SUB_SEQ_LAYERS-1)
+ return(HANTRO_NOK);
+
+ for (i = 0; i < pSubSeqCharacteristics->numReferencedSubseqs; i++)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSubSeqCharacteristics->refSubSeqLayerNum[i]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSubSeqCharacteristics->refSubSeqId[i]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSubSeqCharacteristics->refSubSeqDirection[i] = tmp;
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeFullFrameFreeze
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeFullFrameFreeze(
+ strmData_t *pStrmData,
+ seiFullFrameFreeze_t *pFullFrameFreeze)
+{
+
+/* Variables */
+
+ u32 tmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pFullFrameFreeze);
+
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pFullFrameFreeze->fullFrameFreezeRepetitionPeriod);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pFullFrameFreeze->fullFrameFreezeRepetitionPeriod > 16384)
+ return(HANTRO_NOK);
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeFullFrameSnapshot
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeFullFrameSnapshot(
+ strmData_t *pStrmData,
+ seiFullFrameSnapshot_t *pFullFrameSnapshot)
+{
+
+/* Variables */
+
+ u32 tmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pFullFrameSnapshot);
+
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pFullFrameSnapshot->snapShotId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeProgressiveRefinementSegmentStart
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeProgressiveRefinementSegmentStart(
+ strmData_t *pStrmData,
+ seiProgressiveRefinementSegmentStart_t *pProgressiveRefinementSegmentStart)
+{
+
+/* Variables */
+
+ u32 tmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pProgressiveRefinementSegmentStart);
+
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pProgressiveRefinementSegmentStart->progressiveRefinementId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pProgressiveRefinementSegmentStart->numRefinementSteps);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pProgressiveRefinementSegmentStart->numRefinementSteps++;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeProgressiveRefinementSegmentEnd
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeProgressiveRefinementSegmentEnd(
+ strmData_t *pStrmData,
+ seiProgressiveRefinementSegmentEnd_t *pProgressiveRefinementSegmentEnd)
+{
+
+/* Variables */
+
+ u32 tmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pProgressiveRefinementSegmentEnd);
+
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pProgressiveRefinementSegmentEnd->progressiveRefinementId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeMotionConstrainedSliceGroupSet
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeMotionConstrainedSliceGroupSet(
+ strmData_t *pStrmData,
+ seiMotionConstrainedSliceGroupSet_t *pMotionConstrainedSliceGroupSet,
+ u32 numSliceGroups)
+{
+
+/* Variables */
+
+ u32 tmp,i;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pMotionConstrainedSliceGroupSet);
+ ASSERT(numSliceGroups < MAX_NUM_SLICE_GROUPS);
+
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pMotionConstrainedSliceGroupSet->numSliceGroupsInSet);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pMotionConstrainedSliceGroupSet->numSliceGroupsInSet++;
+ if (pMotionConstrainedSliceGroupSet->numSliceGroupsInSet > numSliceGroups)
+ return(HANTRO_NOK);
+
+ for (i = 0; i < pMotionConstrainedSliceGroupSet->numSliceGroupsInSet; i++)
+ {
+ tmp = h264bsdGetBits(pStrmData,
+ ceilLog2NumSliceGroups[numSliceGroups]);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pMotionConstrainedSliceGroupSet->sliceGroupId[i] = tmp;
+ if (pMotionConstrainedSliceGroupSet->sliceGroupId[i] >
+ pMotionConstrainedSliceGroupSet->numSliceGroupsInSet-1)
+ return(HANTRO_NOK);
+ }
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pMotionConstrainedSliceGroupSet->exactSampleValueMatchFlag =
+ tmp == 1 ? HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pMotionConstrainedSliceGroupSet->panScanRectFlag = tmp == 1 ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pMotionConstrainedSliceGroupSet->panScanRectFlag)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pMotionConstrainedSliceGroupSet->panScanRectId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeReservedSeiMessage
+
+ Functional description:
+ <++>
+ Inputs:
+ <++>
+ Outputs:
+ <++>
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeReservedSeiMessage(
+ strmData_t *pStrmData,
+ seiReservedSeiMessage_t *pReservedSeiMessage,
+ u32 payloadSize)
+{
+
+/* Variables */
+
+ u32 i, tmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pReservedSeiMessage);
+
+
+ /* where corresponding FREE() ??? */
+ ALLOCATE(pReservedSeiMessage->reservedSeiMessagePayloadByte,payloadSize,u8);
+ if (pReservedSeiMessage->reservedSeiMessagePayloadByte == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+
+ pReservedSeiMessage->numPayloadBytes = payloadSize;
+
+ for (i = 0; i < payloadSize; i++)
+ {
+ tmp = h264bsdGetBits(pStrmData,8);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pReservedSeiMessage->reservedSeiMessagePayloadByte[i] = (u8)tmp;
+ }
+
+ return(HANTRO_OK);
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.h
new file mode 100755
index 0000000..efe543a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_sei.h
@@ -0,0 +1,252 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_SEI_H
+#define H264SWDEC_SEI_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_stream.h"
+#include "h264bsd_slice_header.h"
+#include "h264bsd_seq_param_set.h"
+#include "h264bsd_vui.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+#define MAX_PAN_SCAN_CNT 32
+#define MAX_NUM_SPARE_PICS 16
+#define MAX_NUM_CLOCK_TS 3
+#define MAX_NUM_SUB_SEQ_LAYERS 256
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+typedef struct
+{
+ u32 seqParameterSetId;
+ u32 initialCpbRemovalDelay[MAX_CPB_CNT];
+ u32 initialCpbRemovalDelayOffset[MAX_CPB_CNT];
+} seiBufferingPeriod_t;
+
+typedef struct
+{
+ u32 cpbRemovalDelay;
+ u32 dpbOutputDelay;
+ u32 picStruct;
+ u32 clockTimeStampFlag[MAX_NUM_CLOCK_TS];
+ u32 clockTimeStamp[MAX_NUM_CLOCK_TS];
+ u32 ctType[MAX_NUM_CLOCK_TS];
+ u32 nuitFieldBasedFlag[MAX_NUM_CLOCK_TS];
+ u32 countingType[MAX_NUM_CLOCK_TS];
+ u32 fullTimeStampFlag[MAX_NUM_CLOCK_TS];
+ u32 discontinuityFlag[MAX_NUM_CLOCK_TS];
+ u32 cntDroppedFlag[MAX_NUM_CLOCK_TS];
+ u32 nFrames[MAX_NUM_CLOCK_TS];
+ u32 secondsFlag[MAX_NUM_CLOCK_TS];
+ u32 secondsValue[MAX_NUM_CLOCK_TS];
+ u32 minutesFlag[MAX_NUM_CLOCK_TS];
+ u32 minutesValue[MAX_NUM_CLOCK_TS];
+ u32 hoursFlag[MAX_NUM_CLOCK_TS];
+ u32 hoursValue[MAX_NUM_CLOCK_TS];
+ i32 timeOffset[MAX_NUM_CLOCK_TS];
+} seiPicTiming_t;
+
+typedef struct
+{
+ u32 panScanRectId;
+ u32 panScanRectCancelFlag;
+ u32 panScanCnt;
+ i32 panScanRectLeftOffset[MAX_PAN_SCAN_CNT];
+ i32 panScanRectRightOffset[MAX_PAN_SCAN_CNT];
+ i32 panScanRectTopOffset[MAX_PAN_SCAN_CNT];
+ i32 panScanRectBottomOffset[MAX_PAN_SCAN_CNT];
+ u32 panScanRectRepetitionPeriod;
+} seiPanScanRect_t;
+
+typedef struct
+{
+ u32 ituTT35CountryCode;
+ u32 ituTT35CountryCodeExtensionByte;
+ u8 *ituTT35PayloadByte;
+ u32 numPayloadBytes;
+} seiUserDataRegisteredItuTT35_t;
+
+typedef struct
+{
+ u32 uuidIsoIec11578[4];
+ u8 *userDataPayloadByte;
+ u32 numPayloadBytes;
+} seiUserDataUnregistered_t;
+
+typedef struct
+{
+ u32 recoveryFrameCnt;
+ u32 exactMatchFlag;
+ u32 brokenLinkFlag;
+ u32 changingSliceGroupIdc;
+} seiRecoveryPoint_t;
+
+typedef struct
+{
+ u32 originalIdrFlag;
+ u32 originalFrameNum;
+ decRefPicMarking_t decRefPicMarking;
+} seiDecRefPicMarkingRepetition_t;
+
+typedef struct
+{
+ u32 targetFrameNum;
+ u32 spareFieldFlag;
+ u32 targetBottomFieldFlag;
+ u32 numSparePics;
+ u32 deltaSpareFrameNum[MAX_NUM_SPARE_PICS];
+ u32 spareBottomFieldFlag[MAX_NUM_SPARE_PICS];
+ u32 spareAreaIdc[MAX_NUM_SPARE_PICS];
+ u32 *spareUnitFlag[MAX_NUM_SPARE_PICS];
+ u32 *zeroRunLength[MAX_NUM_SPARE_PICS];
+} seiSparePic_t;
+
+typedef struct
+{
+ u32 sceneInfoPresentFlag;
+ u32 sceneId;
+ u32 sceneTransitionType;
+ u32 secondSceneId;
+} seiSceneInfo_t;
+
+typedef struct
+{
+ u32 subSeqLayerNum;
+ u32 subSeqId;
+ u32 firstRefPicFlag;
+ u32 leadingNonRefPicFlag;
+ u32 lastPicFlag;
+ u32 subSeqFrameNumFlag;
+ u32 subSeqFrameNum;
+} seiSubSeqInfo_t;
+
+typedef struct
+{
+ u32 numSubSeqLayers;
+ u32 accurateStatisticsFlag[MAX_NUM_SUB_SEQ_LAYERS];
+ u32 averageBitRate[MAX_NUM_SUB_SEQ_LAYERS];
+ u32 averageFrameRate[MAX_NUM_SUB_SEQ_LAYERS];
+} seiSubSeqLayerCharacteristics_t;
+
+typedef struct
+{
+ u32 subSeqLayerNum;
+ u32 subSeqId;
+ u32 durationFlag;
+ u32 subSeqDuration;
+ u32 averageRateFlag;
+ u32 accurateStatisticsFlag;
+ u32 averageBitRate;
+ u32 averageFrameRate;
+ u32 numReferencedSubseqs;
+ u32 refSubSeqLayerNum[MAX_NUM_SUB_SEQ_LAYERS];
+ u32 refSubSeqId[MAX_NUM_SUB_SEQ_LAYERS];
+ u32 refSubSeqDirection[MAX_NUM_SUB_SEQ_LAYERS];
+} seiSubSeqCharacteristics_t;
+
+typedef struct
+{
+ u32 fullFrameFreezeRepetitionPeriod;
+} seiFullFrameFreeze_t;
+
+typedef struct
+{
+ u32 snapShotId;
+} seiFullFrameSnapshot_t;
+
+typedef struct
+{
+ u32 progressiveRefinementId;
+ u32 numRefinementSteps;
+} seiProgressiveRefinementSegmentStart_t;
+
+typedef struct
+{
+ u32 progressiveRefinementId;
+} seiProgressiveRefinementSegmentEnd_t;
+
+typedef struct
+{
+ u32 numSliceGroupsInSet;
+ u32 sliceGroupId[MAX_NUM_SLICE_GROUPS];
+ u32 exactSampleValueMatchFlag;
+ u32 panScanRectFlag;
+ u32 panScanRectId;
+} seiMotionConstrainedSliceGroupSet_t;
+
+typedef struct
+{
+ u8 *reservedSeiMessagePayloadByte;
+ u32 numPayloadBytes;
+} seiReservedSeiMessage_t;
+
+typedef struct
+{
+ u32 payloadType;
+ seiBufferingPeriod_t bufferingPeriod;
+ seiPicTiming_t picTiming;
+ seiPanScanRect_t panScanRect;
+ seiUserDataRegisteredItuTT35_t userDataRegisteredItuTT35;
+ seiUserDataUnregistered_t userDataUnregistered;
+ seiRecoveryPoint_t recoveryPoint;
+ seiDecRefPicMarkingRepetition_t decRefPicMarkingRepetition;
+ seiSparePic_t sparePic;
+ seiSceneInfo_t sceneInfo;
+ seiSubSeqInfo_t subSeqInfo;
+ seiSubSeqLayerCharacteristics_t subSeqLayerCharacteristics;
+ seiSubSeqCharacteristics_t subSeqCharacteristics;
+ seiFullFrameFreeze_t fullFrameFreeze;
+ seiFullFrameSnapshot_t fullFrameSnapshot;
+ seiProgressiveRefinementSegmentStart_t progressiveRefinementSegmentStart;
+ seiProgressiveRefinementSegmentEnd_t progressiveRefinementSegmentEnd;
+ seiMotionConstrainedSliceGroupSet_t motionConstrainedSliceGroupSet;
+ seiReservedSeiMessage_t reservedSeiMessage;
+} seiMessage_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeSeiMessage(
+ strmData_t *pStrmData,
+ seqParamSet_t *pSeqParamSet,
+ seiMessage_t *pSeiMessage,
+ u32 numSliceGroups);
+
+#endif /* #ifdef H264SWDEC_SEI_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.c
new file mode 100644
index 0000000..751051a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.c
@@ -0,0 +1,577 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdDecodeSeqParamSet
+ GetDpbSize
+ h264bsdCompareSeqParamSets
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_seq_param_set.h"
+#include "h264bsd_util.h"
+#include "h264bsd_vlc.h"
+#include "h264bsd_vui.h"
+#include "h264bsd_cfg.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/* enumeration to indicate invalid return value from the GetDpbSize function */
+enum {INVALID_DPB_SIZE = 0x7FFFFFFF};
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static u32 GetDpbSize(u32 picSizeInMbs, u32 levelIdc);
+
+/*------------------------------------------------------------------------------
+
+ Function name: h264bsdDecodeSeqParamSet
+
+ Functional description:
+ Decode sequence parameter set information from the stream.
+
+ Function allocates memory for offsetForRefFrame array if
+ picture order count type is 1 and numRefFramesInPicOrderCntCycle
+ is greater than zero.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+
+ Outputs:
+ pSeqParamSet decoded information is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK failure, invalid information or end of stream
+ MEMORY_ALLOCATION_ERROR for memory allocation failure
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeSeqParamSet(strmData_t *pStrmData, seqParamSet_t *pSeqParamSet)
+{
+
+/* Variables */
+
+ u32 tmp, i, value;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSeqParamSet);
+
+ H264SwDecMemset(pSeqParamSet, 0, sizeof(seqParamSet_t));
+
+ /* profile_idc */
+ tmp = h264bsdGetBits(pStrmData, 8);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (tmp != 66)
+ {
+ DEBUG(("NOT BASELINE PROFILE %d\n", tmp));
+ }
+ pSeqParamSet->profileIdc = tmp;
+
+ /* constrained_set0_flag */
+ tmp = h264bsdGetBits(pStrmData, 1);
+ /* constrained_set1_flag */
+ tmp = h264bsdGetBits(pStrmData, 1);
+ /* constrained_set2_flag */
+ tmp = h264bsdGetBits(pStrmData, 1);
+
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ /* reserved_zero_5bits, values of these bits shall be ignored */
+ tmp = h264bsdGetBits(pStrmData, 5);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetBits(pStrmData, 8);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSeqParamSet->levelIdc = tmp;
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSeqParamSet->seqParameterSetId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pSeqParamSet->seqParameterSetId >= MAX_NUM_SEQ_PARAM_SETS)
+ {
+ EPRINT("seq_param_set_id");
+ return(HANTRO_NOK);
+ }
+
+ /* log2_max_frame_num_minus4 */
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (value > 12)
+ {
+ EPRINT("log2_max_frame_num_minus4");
+ return(HANTRO_NOK);
+ }
+ /* maxFrameNum = 2^(log2_max_frame_num_minus4 + 4) */
+ pSeqParamSet->maxFrameNum = 1 << (value+4);
+
+ /* valid POC types are 0, 1 and 2 */
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (value > 2)
+ {
+ EPRINT("pic_order_cnt_type");
+ return(HANTRO_NOK);
+ }
+ pSeqParamSet->picOrderCntType = value;
+
+ if (pSeqParamSet->picOrderCntType == 0)
+ {
+ /* log2_max_pic_order_cnt_lsb_minus4 */
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (value > 12)
+ {
+ EPRINT("log2_max_pic_order_cnt_lsb_minus4");
+ return(HANTRO_NOK);
+ }
+ /* maxPicOrderCntLsb = 2^(log2_max_pic_order_cnt_lsb_minus4 + 4) */
+ pSeqParamSet->maxPicOrderCntLsb = 1 << (value+4);
+ }
+ else if (pSeqParamSet->picOrderCntType == 1)
+ {
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSeqParamSet->deltaPicOrderAlwaysZeroFlag = (tmp == 1) ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData,
+ &pSeqParamSet->offsetForNonRefPic);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData,
+ &pSeqParamSet->offsetForTopToBottomField);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSeqParamSet->numRefFramesInPicOrderCntCycle);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pSeqParamSet->numRefFramesInPicOrderCntCycle > 255)
+ {
+ EPRINT("num_ref_frames_in_pic_order_cnt_cycle");
+ return(HANTRO_NOK);
+ }
+
+ if (pSeqParamSet->numRefFramesInPicOrderCntCycle)
+ {
+ /* NOTE: This has to be freed somewhere! */
+ ALLOCATE(pSeqParamSet->offsetForRefFrame,
+ pSeqParamSet->numRefFramesInPicOrderCntCycle, i32);
+ if (pSeqParamSet->offsetForRefFrame == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+
+ for (i = 0; i < pSeqParamSet->numRefFramesInPicOrderCntCycle; i++)
+ {
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData,
+ pSeqParamSet->offsetForRefFrame + i);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+ }
+ else
+ {
+ pSeqParamSet->offsetForRefFrame = NULL;
+ }
+ }
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSeqParamSet->numRefFrames);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pSeqParamSet->numRefFrames > MAX_NUM_REF_PICS)
+ {
+ EPRINT("num_ref_frames");
+ return(HANTRO_NOK);
+ }
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSeqParamSet->gapsInFrameNumValueAllowedFlag = (tmp == 1) ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSeqParamSet->picWidthInMbs = value + 1;
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSeqParamSet->picHeightInMbs = value + 1;
+
+ /* frame_mbs_only_flag, shall be 1 for baseline profile */
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (!tmp)
+ {
+ EPRINT("frame_mbs_only_flag");
+ return(HANTRO_NOK);
+ }
+
+ /* direct_8x8_inference_flag */
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSeqParamSet->frameCroppingFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pSeqParamSet->frameCroppingFlag)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSeqParamSet->frameCropLeftOffset);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSeqParamSet->frameCropRightOffset);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSeqParamSet->frameCropTopOffset);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pSeqParamSet->frameCropBottomOffset);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* check that frame cropping params are valid, parameters shall
+ * specify non-negative area within the original picture */
+ if ( ( (i32)pSeqParamSet->frameCropLeftOffset >
+ ( 8 * (i32)pSeqParamSet->picWidthInMbs -
+ ((i32)pSeqParamSet->frameCropRightOffset + 1) ) ) ||
+ ( (i32)pSeqParamSet->frameCropTopOffset >
+ ( 8 * (i32)pSeqParamSet->picHeightInMbs -
+ ((i32)pSeqParamSet->frameCropBottomOffset + 1) ) ) )
+ {
+ EPRINT("frame_cropping");
+ return(HANTRO_NOK);
+ }
+ }
+
+ /* check that image dimensions and levelIdc match */
+ tmp = pSeqParamSet->picWidthInMbs * pSeqParamSet->picHeightInMbs;
+ value = GetDpbSize(tmp, pSeqParamSet->levelIdc);
+ if (value == INVALID_DPB_SIZE || pSeqParamSet->numRefFrames > value)
+ {
+ DEBUG(("WARNING! Invalid DPB size based on SPS Level!\n"));
+ DEBUG(("WARNING! Using num_ref_frames =%d for DPB size!\n",
+ pSeqParamSet->numRefFrames));
+ value = pSeqParamSet->numRefFrames;
+ }
+ pSeqParamSet->maxDpbSize = value;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSeqParamSet->vuiParametersPresentFlag = (tmp == 1) ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ /* VUI */
+ if (pSeqParamSet->vuiParametersPresentFlag)
+ {
+ ALLOCATE(pSeqParamSet->vuiParameters, 1, vuiParameters_t);
+ if (pSeqParamSet->vuiParameters == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+ tmp = h264bsdDecodeVuiParameters(pStrmData,
+ pSeqParamSet->vuiParameters);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ /* check numReorderFrames and maxDecFrameBuffering */
+ if (pSeqParamSet->vuiParameters->bitstreamRestrictionFlag)
+ {
+ if (pSeqParamSet->vuiParameters->numReorderFrames >
+ pSeqParamSet->vuiParameters->maxDecFrameBuffering ||
+ pSeqParamSet->vuiParameters->maxDecFrameBuffering <
+ pSeqParamSet->numRefFrames ||
+ pSeqParamSet->vuiParameters->maxDecFrameBuffering >
+ pSeqParamSet->maxDpbSize)
+ {
+ return(HANTRO_NOK);
+ }
+
+ /* standard says that "the sequence shall not require a DPB with
+ * size of more than max(1, maxDecFrameBuffering) */
+ pSeqParamSet->maxDpbSize =
+ MAX(1, pSeqParamSet->vuiParameters->maxDecFrameBuffering);
+ }
+ }
+
+ tmp = h264bsdRbspTrailingBits(pStrmData);
+
+ /* ignore possible errors in trailing bits of parameters sets */
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: GetDpbSize
+
+ Functional description:
+ Get size of the DPB in frames. Size is determined based on the
+ picture size and MaxDPB for the specified level. These determine
+ how many pictures may fit into to the buffer. However, the size
+ is also limited to a maximum of 16 frames and therefore function
+ returns the minimum of the determined size and 16.
+
+ Inputs:
+ picSizeInMbs number of macroblocks in the picture
+ levelIdc indicates the level
+
+ Outputs:
+ none
+
+ Returns:
+ size of the DPB in frames
+ INVALID_DPB_SIZE when invalid levelIdc specified or picSizeInMbs
+ is higher than supported by the level in question
+
+------------------------------------------------------------------------------*/
+
+u32 GetDpbSize(u32 picSizeInMbs, u32 levelIdc)
+{
+
+/* Variables */
+
+ u32 tmp;
+ u32 maxPicSizeInMbs;
+
+/* Code */
+
+ ASSERT(picSizeInMbs);
+
+ /* use tmp as the size of the DPB in bytes, computes as 1024 * MaxDPB
+ * (from table A-1 in Annex A) */
+ switch (levelIdc)
+ {
+ case 10:
+ tmp = 152064;
+ maxPicSizeInMbs = 99;
+ break;
+
+ case 11:
+ tmp = 345600;
+ maxPicSizeInMbs = 396;
+ break;
+
+ case 12:
+ tmp = 912384;
+ maxPicSizeInMbs = 396;
+ break;
+
+ case 13:
+ tmp = 912384;
+ maxPicSizeInMbs = 396;
+ break;
+
+ case 20:
+ tmp = 912384;
+ maxPicSizeInMbs = 396;
+ break;
+
+ case 21:
+ tmp = 1824768;
+ maxPicSizeInMbs = 792;
+ break;
+
+ case 22:
+ tmp = 3110400;
+ maxPicSizeInMbs = 1620;
+ break;
+
+ case 30:
+ tmp = 3110400;
+ maxPicSizeInMbs = 1620;
+ break;
+
+ case 31:
+ tmp = 6912000;
+ maxPicSizeInMbs = 3600;
+ break;
+
+ case 32:
+ tmp = 7864320;
+ maxPicSizeInMbs = 5120;
+ break;
+
+ case 40:
+ tmp = 12582912;
+ maxPicSizeInMbs = 8192;
+ break;
+
+ case 41:
+ tmp = 12582912;
+ maxPicSizeInMbs = 8192;
+ break;
+
+ case 42:
+ tmp = 34816*384;
+ maxPicSizeInMbs = 8704;
+ break;
+
+ case 50:
+ /* standard says 42301440 here, but corrigendum "corrects" this to
+ * 42393600 */
+ tmp = 42393600;
+ maxPicSizeInMbs = 22080;
+ break;
+
+ case 51:
+ tmp = 70778880;
+ maxPicSizeInMbs = 36864;
+ break;
+
+ default:
+ return(INVALID_DPB_SIZE);
+ }
+
+ /* this is not "correct" return value! However, it results in error in
+ * decoding and this was easiest place to check picture size */
+ if (picSizeInMbs > maxPicSizeInMbs)
+ return(INVALID_DPB_SIZE);
+
+ tmp /= (picSizeInMbs*384);
+
+ return(MIN(tmp, 16));
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: h264bsdCompareSeqParamSets
+
+ Functional description:
+ Compare two sequence parameter sets.
+
+ Inputs:
+ pSps1 pointer to a sequence parameter set
+ pSps2 pointer to another sequence parameter set
+
+ Outputs:
+ 0 sequence parameter sets are equal
+ 1 otherwise
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdCompareSeqParamSets(seqParamSet_t *pSps1, seqParamSet_t *pSps2)
+{
+
+/* Variables */
+
+ u32 i;
+
+/* Code */
+
+ ASSERT(pSps1);
+ ASSERT(pSps2);
+
+ /* first compare parameters whose existence does not depend on other
+ * parameters and only compare the rest of the params if these are equal */
+ if (pSps1->profileIdc == pSps2->profileIdc &&
+ pSps1->levelIdc == pSps2->levelIdc &&
+ pSps1->maxFrameNum == pSps2->maxFrameNum &&
+ pSps1->picOrderCntType == pSps2->picOrderCntType &&
+ pSps1->numRefFrames == pSps2->numRefFrames &&
+ pSps1->gapsInFrameNumValueAllowedFlag ==
+ pSps2->gapsInFrameNumValueAllowedFlag &&
+ pSps1->picWidthInMbs == pSps2->picWidthInMbs &&
+ pSps1->picHeightInMbs == pSps2->picHeightInMbs &&
+ pSps1->frameCroppingFlag == pSps2->frameCroppingFlag &&
+ pSps1->vuiParametersPresentFlag == pSps2->vuiParametersPresentFlag)
+ {
+ if (pSps1->picOrderCntType == 0)
+ {
+ if (pSps1->maxPicOrderCntLsb != pSps2->maxPicOrderCntLsb)
+ return 1;
+ }
+ else if (pSps1->picOrderCntType == 1)
+ {
+ if (pSps1->deltaPicOrderAlwaysZeroFlag !=
+ pSps2->deltaPicOrderAlwaysZeroFlag ||
+ pSps1->offsetForNonRefPic != pSps2->offsetForNonRefPic ||
+ pSps1->offsetForTopToBottomField !=
+ pSps2->offsetForTopToBottomField ||
+ pSps1->numRefFramesInPicOrderCntCycle !=
+ pSps2->numRefFramesInPicOrderCntCycle)
+ {
+ return 1;
+ }
+ else
+ {
+ for (i = 0; i < pSps1->numRefFramesInPicOrderCntCycle; i++)
+ if (pSps1->offsetForRefFrame[i] !=
+ pSps2->offsetForRefFrame[i])
+ {
+ return 1;
+ }
+ }
+ }
+ if (pSps1->frameCroppingFlag)
+ {
+ if (pSps1->frameCropLeftOffset != pSps2->frameCropLeftOffset ||
+ pSps1->frameCropRightOffset != pSps2->frameCropRightOffset ||
+ pSps1->frameCropTopOffset != pSps2->frameCropTopOffset ||
+ pSps1->frameCropBottomOffset != pSps2->frameCropBottomOffset)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ return 1;
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.h
new file mode 100755
index 0000000..e18df94
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_seq_param_set.h
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_SEQ_PARAM_SET_H
+#define H264SWDEC_SEQ_PARAM_SET_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_stream.h"
+#include "h264bsd_vui.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/* structure to store sequence parameter set information decoded from the
+ * stream */
+typedef struct
+{
+ u32 profileIdc;
+ u32 levelIdc;
+ u32 seqParameterSetId;
+ u32 maxFrameNum;
+ u32 picOrderCntType;
+ u32 maxPicOrderCntLsb;
+ u32 deltaPicOrderAlwaysZeroFlag;
+ i32 offsetForNonRefPic;
+ i32 offsetForTopToBottomField;
+ u32 numRefFramesInPicOrderCntCycle;
+ i32 *offsetForRefFrame;
+ u32 numRefFrames;
+ u32 gapsInFrameNumValueAllowedFlag;
+ u32 picWidthInMbs;
+ u32 picHeightInMbs;
+ u32 frameCroppingFlag;
+ u32 frameCropLeftOffset;
+ u32 frameCropRightOffset;
+ u32 frameCropTopOffset;
+ u32 frameCropBottomOffset;
+ u32 vuiParametersPresentFlag;
+ vuiParameters_t *vuiParameters;
+ u32 maxDpbSize;
+} seqParamSet_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeSeqParamSet(strmData_t *pStrmData,
+ seqParamSet_t *pSeqParamSet);
+
+u32 h264bsdCompareSeqParamSets(seqParamSet_t *pSps1, seqParamSet_t *pSps2);
+
+#endif /* #ifdef H264SWDEC_SEQ_PARAM_SET_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c
new file mode 100755
index 0000000..c288d4b
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c
@@ -0,0 +1,354 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdDecodeSliceData
+ SetMbParams
+ h264bsdMarkSliceCorrupted
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_slice_data.h"
+#include "h264bsd_util.h"
+#include "h264bsd_vlc.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static void SetMbParams(mbStorage_t *pMb, sliceHeader_t *pSlice, u32 sliceId,
+ i32 chromaQpIndexOffset);
+
+/*------------------------------------------------------------------------------
+
+ 5.1 Function name: h264bsdDecodeSliceData
+
+ Functional description:
+ Decode one slice. Function decodes stream data, i.e. macroblocks
+ and possible skip_run fields. h264bsdDecodeMacroblock function is
+ called to handle all other macroblock related processing.
+ Macroblock to slice group mapping is considered when next
+ macroblock to process is determined (h264bsdNextMbAddress function)
+ map
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ pStorage pointer to storage structure
+ currImage pointer to current processed picture, needed for
+ intra prediction of the macroblocks
+ pSliceHeader pointer to slice header of the current slice
+
+ Outputs:
+ currImage processed macroblocks are written to current image
+ pStorage mbStorage structure of each processed macroblock
+ is updated here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeSliceData(strmData_t *pStrmData, storage_t *pStorage,
+ image_t *currImage, sliceHeader_t *pSliceHeader)
+{
+
+/* Variables */
+
+ u8 mbData[384 + 15 + 32];
+ u8 *data;
+ u32 tmp;
+ u32 skipRun;
+ u32 prevSkipped;
+ u32 currMbAddr;
+ u32 moreMbs;
+ u32 mbCount;
+ i32 qpY;
+ macroblockLayer_t *mbLayer;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSliceHeader);
+ ASSERT(pStorage);
+ ASSERT(pSliceHeader->firstMbInSlice < pStorage->picSizeInMbs);
+
+ /* ensure 16-byte alignment */
+ data = (u8*)ALIGN(mbData, 16);
+
+ mbLayer = pStorage->mbLayer;
+
+ currMbAddr = pSliceHeader->firstMbInSlice;
+ skipRun = 0;
+ prevSkipped = HANTRO_FALSE;
+
+ /* increment slice index, will be one for decoding of the first slice of
+ * the picture */
+ pStorage->slice->sliceId++;
+
+ /* lastMbAddr stores address of the macroblock that was last successfully
+ * decoded, needed for error handling */
+ pStorage->slice->lastMbAddr = 0;
+
+ mbCount = 0;
+ /* initial quantization parameter for the slice is obtained as the sum of
+ * initial QP for the picture and sliceQpDelta for the current slice */
+ qpY = (i32)pStorage->activePps->picInitQp + pSliceHeader->sliceQpDelta;
+ do
+ {
+ /* primary picture and already decoded macroblock -> error */
+ if (!pSliceHeader->redundantPicCnt && pStorage->mb[currMbAddr].decoded)
+ {
+ EPRINT("Primary and already decoded");
+ return(HANTRO_NOK);
+ }
+
+ SetMbParams(pStorage->mb + currMbAddr, pSliceHeader,
+ pStorage->slice->sliceId, pStorage->activePps->chromaQpIndexOffset);
+
+ if (!IS_I_SLICE(pSliceHeader->sliceType))
+ {
+ if (!prevSkipped)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &skipRun);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ /* skip_run shall be less than or equal to number of
+ * macroblocks left */
+ if (skipRun > (pStorage->picSizeInMbs - currMbAddr))
+ {
+ EPRINT("skip_run");
+ return(HANTRO_NOK);
+ }
+ if (skipRun)
+ {
+ prevSkipped = HANTRO_TRUE;
+ H264SwDecMemset(&mbLayer->mbPred, 0, sizeof(mbPred_t));
+ /* mark current macroblock skipped */
+ mbLayer->mbType = P_Skip;
+ }
+ }
+ }
+
+ if (skipRun)
+ {
+ DEBUG(("Skipping macroblock %d\n", currMbAddr));
+ skipRun--;
+ }
+ else
+ {
+ prevSkipped = HANTRO_FALSE;
+ tmp = h264bsdDecodeMacroblockLayer(pStrmData, mbLayer,
+ pStorage->mb + currMbAddr, pSliceHeader->sliceType,
+ pSliceHeader->numRefIdxL0Active);
+ if (tmp != HANTRO_OK)
+ {
+ EPRINT("macroblock_layer");
+ return(tmp);
+ }
+ }
+
+ tmp = h264bsdDecodeMacroblock(pStorage->mb + currMbAddr, mbLayer,
+ currImage, pStorage->dpb, &qpY, currMbAddr,
+ pStorage->activePps->constrainedIntraPredFlag, data);
+ if (tmp != HANTRO_OK)
+ {
+ EPRINT("MACRO_BLOCK");
+ return(tmp);
+ }
+
+ /* increment macroblock count only for macroblocks that were decoded
+ * for the first time (redundant slices) */
+ if (pStorage->mb[currMbAddr].decoded == 1)
+ mbCount++;
+
+ /* keep on processing as long as there is stream data left or
+ * processing of macroblocks to be skipped based on the last skipRun is
+ * not finished */
+ moreMbs = (h264bsdMoreRbspData(pStrmData) || skipRun) ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ /* lastMbAddr is only updated for intra slices (all macroblocks of
+ * inter slices will be lost in case of an error) */
+ if (IS_I_SLICE(pSliceHeader->sliceType))
+ pStorage->slice->lastMbAddr = currMbAddr;
+
+ currMbAddr = h264bsdNextMbAddress(pStorage->sliceGroupMap,
+ pStorage->picSizeInMbs, currMbAddr);
+ /* data left in the buffer but no more macroblocks for current slice
+ * group -> error */
+ if (moreMbs && !currMbAddr)
+ {
+ EPRINT("Next mb address");
+ return(HANTRO_NOK);
+ }
+
+ } while (moreMbs);
+
+ if ((pStorage->slice->numDecodedMbs + mbCount) > pStorage->picSizeInMbs)
+ {
+ EPRINT("Num decoded mbs");
+ return(HANTRO_NOK);
+ }
+
+ pStorage->slice->numDecodedMbs += mbCount;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ 5.2 Function: SetMbParams
+
+ Functional description:
+ Set macroblock parameters that remain constant for this slice
+
+ Inputs:
+ pSlice pointer to current slice header
+ sliceId id of the current slice
+ chromaQpIndexOffset
+
+ Outputs:
+ pMb pointer to macroblock structure which is updated
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void SetMbParams(mbStorage_t *pMb, sliceHeader_t *pSlice, u32 sliceId,
+ i32 chromaQpIndexOffset)
+{
+
+/* Variables */
+ u32 tmp1;
+ i32 tmp2, tmp3;
+
+/* Code */
+
+ tmp1 = pSlice->disableDeblockingFilterIdc;
+ tmp2 = pSlice->sliceAlphaC0Offset;
+ tmp3 = pSlice->sliceBetaOffset;
+ pMb->sliceId = sliceId;
+ pMb->disableDeblockingFilterIdc = tmp1;
+ pMb->filterOffsetA = tmp2;
+ pMb->filterOffsetB = tmp3;
+ pMb->chromaQpIndexOffset = chromaQpIndexOffset;
+
+}
+
+/*------------------------------------------------------------------------------
+
+ 5.3 Function name: h264bsdMarkSliceCorrupted
+
+ Functional description:
+ Mark macroblocks of the slice corrupted. If lastMbAddr in the slice
+ storage is set -> picWidhtInMbs (or at least 10) macroblocks back
+ from the lastMbAddr are marked corrupted. However, if lastMbAddr
+ is not set -> all macroblocks of the slice are marked.
+
+ Inputs:
+ pStorage pointer to storage structure
+ firstMbInSlice address of the first macroblock in the slice, this
+ identifies the slice to be marked corrupted
+
+ Outputs:
+ pStorage mbStorage for the corrupted macroblocks updated
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void h264bsdMarkSliceCorrupted(storage_t *pStorage, u32 firstMbInSlice)
+{
+
+/* Variables */
+
+ u32 tmp, i;
+ u32 sliceId;
+ u32 currMbAddr;
+
+/* Code */
+
+ ASSERT(pStorage);
+ ASSERT(firstMbInSlice < pStorage->picSizeInMbs);
+
+ currMbAddr = firstMbInSlice;
+
+ sliceId = pStorage->slice->sliceId;
+
+ /* DecodeSliceData sets lastMbAddr for I slices -> if it was set, go back
+ * MAX(picWidthInMbs, 10) macroblocks and start marking from there */
+ if (pStorage->slice->lastMbAddr)
+ {
+ ASSERT(pStorage->mb[pStorage->slice->lastMbAddr].sliceId == sliceId);
+ i = pStorage->slice->lastMbAddr - 1;
+ tmp = 0;
+ while (i > currMbAddr)
+ {
+ if (pStorage->mb[i].sliceId == sliceId)
+ {
+ tmp++;
+ if (tmp >= MAX(pStorage->activeSps->picWidthInMbs, 10))
+ break;
+ }
+ i--;
+ }
+ currMbAddr = i;
+ }
+
+ do
+ {
+
+ if ( (pStorage->mb[currMbAddr].sliceId == sliceId) &&
+ (pStorage->mb[currMbAddr].decoded) )
+ {
+ pStorage->mb[currMbAddr].decoded--;
+ }
+ else
+ {
+ break;
+ }
+
+ currMbAddr = h264bsdNextMbAddress(pStorage->sliceGroupMap,
+ pStorage->picSizeInMbs, currMbAddr);
+
+ } while (currMbAddr);
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.h
new file mode 100755
index 0000000..f23d49e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_SLICE_DATA_H
+#define H264SWDEC_SLICE_DATA_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_stream.h"
+#include "h264bsd_cfg.h"
+#include "h264bsd_slice_header.h"
+#include "h264bsd_storage.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeSliceData(strmData_t *pStrmData, storage_t *pStorage,
+ image_t *currImage, sliceHeader_t *pSliceHeader);
+
+void h264bsdMarkSliceCorrupted(storage_t *pStorage, u32 firstMbInSlice);
+
+#endif /* #ifdef H264SWDEC_SLICE_DATA_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.c
new file mode 100755
index 0000000..7cbb534
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.c
@@ -0,0 +1,589 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ DecodeInterleavedMap
+ DecodeDispersedMap
+ DecodeForegroundLeftOverMap
+ DecodeBoxOutMap
+ DecodeRasterScanMap
+ DecodeWipeMap
+ h264bsdDecodeSliceGroupMap
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_slice_group_map.h"
+#include "h264bsd_cfg.h"
+#include "h264bsd_pic_param_set.h"
+#include "h264bsd_util.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static void DecodeInterleavedMap(
+ u32 *map,
+ u32 numSliceGroups,
+ u32 *runLength,
+ u32 picSize);
+
+static void DecodeDispersedMap(
+ u32 *map,
+ u32 numSliceGroups,
+ u32 picWidth,
+ u32 picHeight);
+
+static void DecodeForegroundLeftOverMap(
+ u32 *map,
+ u32 numSliceGroups,
+ u32 *topLeft,
+ u32 *bottomRight,
+ u32 picWidth,
+ u32 picHeight);
+
+static void DecodeBoxOutMap(
+ u32 *map,
+ u32 sliceGroupChangeDirectionFlag,
+ u32 unitsInSliceGroup0,
+ u32 picWidth,
+ u32 picHeight);
+
+static void DecodeRasterScanMap(
+ u32 *map,
+ u32 sliceGroupChangeDirectionFlag,
+ u32 sizeOfUpperLeftGroup,
+ u32 picSize);
+
+static void DecodeWipeMap(
+ u32 *map,
+ u32 sliceGroupChangeDirectionFlag,
+ u32 sizeOfUpperLeftGroup,
+ u32 picWidth,
+ u32 picHeight);
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeInterleavedMap
+
+ Functional description:
+ Function to decode interleaved slice group map type, i.e. slice
+ group map type 0.
+
+ Inputs:
+ map pointer to the map
+ numSliceGroups number of slice groups
+ runLength run_length[] values for each slice group
+ picSize picture size in macroblocks
+
+ Outputs:
+ map slice group map is stored here
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void DecodeInterleavedMap(
+ u32 *map,
+ u32 numSliceGroups,
+ u32 *runLength,
+ u32 picSize)
+{
+
+/* Variables */
+
+ u32 i,j, group;
+
+/* Code */
+
+ ASSERT(map);
+ ASSERT(numSliceGroups >= 1 && numSliceGroups <= MAX_NUM_SLICE_GROUPS);
+ ASSERT(runLength);
+
+ i = 0;
+
+ do {
+ for (group = 0; group < numSliceGroups && i < picSize;
+ i += runLength[group++])
+ {
+ ASSERT(runLength[group] <= picSize);
+ for (j = 0; j < runLength[group] && i + j < picSize; j++)
+ map[i+j] = group;
+ }
+ } while (i < picSize);
+
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeDispersedMap
+
+ Functional description:
+ Function to decode dispersed slice group map type, i.e. slice
+ group map type 1.
+
+ Inputs:
+ map pointer to the map
+ numSliceGroups number of slice groups
+ picWidth picture width in macroblocks
+ picHeight picture height in macroblocks
+
+ Outputs:
+ map slice group map is stored here
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void DecodeDispersedMap(
+ u32 *map,
+ u32 numSliceGroups,
+ u32 picWidth,
+ u32 picHeight)
+{
+
+/* Variables */
+
+ u32 i, picSize;
+
+/* Code */
+
+ ASSERT(map);
+ ASSERT(numSliceGroups >= 1 && numSliceGroups <= MAX_NUM_SLICE_GROUPS);
+ ASSERT(picWidth);
+ ASSERT(picHeight);
+
+ picSize = picWidth * picHeight;
+
+ for (i = 0; i < picSize; i++)
+ map[i] = ((i % picWidth) + (((i / picWidth) * numSliceGroups) >> 1)) %
+ numSliceGroups;
+
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeForegroundLeftOverMap
+
+ Functional description:
+ Function to decode foreground with left-over slice group map type,
+ i.e. slice group map type 2.
+
+ Inputs:
+ map pointer to the map
+ numSliceGroups number of slice groups
+ topLeft top_left[] values
+ bottomRight bottom_right[] values
+ picWidth picture width in macroblocks
+ picHeight picture height in macroblocks
+
+ Outputs:
+ map slice group map is stored here
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void DecodeForegroundLeftOverMap(
+ u32 *map,
+ u32 numSliceGroups,
+ u32 *topLeft,
+ u32 *bottomRight,
+ u32 picWidth,
+ u32 picHeight)
+{
+
+/* Variables */
+
+ u32 i,y,x,yTopLeft,yBottomRight,xTopLeft,xBottomRight, picSize;
+ u32 group;
+
+/* Code */
+
+ ASSERT(map);
+ ASSERT(numSliceGroups >= 1 && numSliceGroups <= MAX_NUM_SLICE_GROUPS);
+ ASSERT(topLeft);
+ ASSERT(bottomRight);
+ ASSERT(picWidth);
+ ASSERT(picHeight);
+
+ picSize = picWidth * picHeight;
+
+ for (i = 0; i < picSize; i++)
+ map[i] = numSliceGroups - 1;
+
+ for (group = numSliceGroups - 1; group--; )
+ {
+ ASSERT( topLeft[group] <= bottomRight[group] &&
+ bottomRight[group] < picSize );
+ yTopLeft = topLeft[group] / picWidth;
+ xTopLeft = topLeft[group] % picWidth;
+ yBottomRight = bottomRight[group] / picWidth;
+ xBottomRight = bottomRight[group] % picWidth;
+ ASSERT(xTopLeft <= xBottomRight);
+
+ for (y = yTopLeft; y <= yBottomRight; y++)
+ for (x = xTopLeft; x <= xBottomRight; x++)
+ map[ y * picWidth + x ] = group;
+ }
+
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeBoxOutMap
+
+ Functional description:
+ Function to decode box-out slice group map type, i.e. slice group
+ map type 3.
+
+ Inputs:
+ map pointer to the map
+ sliceGroupChangeDirectionFlag slice_group_change_direction_flag
+ unitsInSliceGroup0 mbs on slice group 0
+ picWidth picture width in macroblocks
+ picHeight picture height in macroblocks
+
+ Outputs:
+ map slice group map is stored here
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void DecodeBoxOutMap(
+ u32 *map,
+ u32 sliceGroupChangeDirectionFlag,
+ u32 unitsInSliceGroup0,
+ u32 picWidth,
+ u32 picHeight)
+{
+
+/* Variables */
+
+ u32 i, k, picSize;
+ i32 x, y, xDir, yDir, leftBound, topBound, rightBound, bottomBound;
+ u32 mapUnitVacant;
+
+/* Code */
+
+ ASSERT(map);
+ ASSERT(picWidth);
+ ASSERT(picHeight);
+
+ picSize = picWidth * picHeight;
+ ASSERT(unitsInSliceGroup0 <= picSize);
+
+ for (i = 0; i < picSize; i++)
+ map[i] = 1;
+
+ x = (picWidth - (u32)sliceGroupChangeDirectionFlag) >> 1;
+ y = (picHeight - (u32)sliceGroupChangeDirectionFlag) >> 1;
+
+ leftBound = x;
+ topBound = y;
+
+ rightBound = x;
+ bottomBound = y;
+
+ xDir = (i32)sliceGroupChangeDirectionFlag - 1;
+ yDir = (i32)sliceGroupChangeDirectionFlag;
+
+ for (k = 0; k < unitsInSliceGroup0; k += mapUnitVacant ? 1 : 0)
+ {
+ mapUnitVacant = (map[ (u32)y * picWidth + (u32)x ] == 1) ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ if (mapUnitVacant)
+ map[ (u32)y * picWidth + (u32)x ] = 0;
+
+ if (xDir == -1 && x == leftBound)
+ {
+ leftBound = MAX(leftBound - 1, 0);
+ x = leftBound;
+ xDir = 0;
+ yDir = 2 * (i32)sliceGroupChangeDirectionFlag - 1;
+ }
+ else if (xDir == 1 && x == rightBound)
+ {
+ rightBound = MIN(rightBound + 1, (i32)picWidth - 1);
+ x = rightBound;
+ xDir = 0;
+ yDir = 1 - 2 * (i32)sliceGroupChangeDirectionFlag;
+ }
+ else if (yDir == -1 && y == topBound)
+ {
+ topBound = MAX(topBound - 1, 0);
+ y = topBound;
+ xDir = 1 - 2 * (i32)sliceGroupChangeDirectionFlag;
+ yDir = 0;
+ }
+ else if (yDir == 1 && y == bottomBound)
+ {
+ bottomBound = MIN(bottomBound + 1, (i32)picHeight - 1);
+ y = bottomBound;
+ xDir = 2 * (i32)sliceGroupChangeDirectionFlag - 1;
+ yDir = 0;
+ }
+ else
+ {
+ x += xDir;
+ y += yDir;
+ }
+ }
+
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeRasterScanMap
+
+ Functional description:
+ Function to decode raster scan slice group map type, i.e. slice
+ group map type 4.
+
+ Inputs:
+ map pointer to the map
+ sliceGroupChangeDirectionFlag slice_group_change_direction_flag
+ sizeOfUpperLeftGroup mbs in upperLeftGroup
+ picSize picture size in macroblocks
+
+ Outputs:
+ map slice group map is stored here
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void DecodeRasterScanMap(
+ u32 *map,
+ u32 sliceGroupChangeDirectionFlag,
+ u32 sizeOfUpperLeftGroup,
+ u32 picSize)
+{
+
+/* Variables */
+
+ u32 i;
+
+/* Code */
+
+ ASSERT(map);
+ ASSERT(picSize);
+ ASSERT(sizeOfUpperLeftGroup <= picSize);
+
+ for (i = 0; i < picSize; i++)
+ if (i < sizeOfUpperLeftGroup)
+ map[i] = (u32)sliceGroupChangeDirectionFlag;
+ else
+ map[i] = 1 - (u32)sliceGroupChangeDirectionFlag;
+
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeWipeMap
+
+ Functional description:
+ Function to decode wipe slice group map type, i.e. slice group map
+ type 5.
+
+ Inputs:
+ sliceGroupChangeDirectionFlag slice_group_change_direction_flag
+ sizeOfUpperLeftGroup mbs in upperLeftGroup
+ picWidth picture width in macroblocks
+ picHeight picture height in macroblocks
+
+ Outputs:
+ map slice group map is stored here
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void DecodeWipeMap(
+ u32 *map,
+ u32 sliceGroupChangeDirectionFlag,
+ u32 sizeOfUpperLeftGroup,
+ u32 picWidth,
+ u32 picHeight)
+{
+
+/* Variables */
+
+ u32 i,j,k;
+
+/* Code */
+
+ ASSERT(map);
+ ASSERT(picWidth);
+ ASSERT(picHeight);
+ ASSERT(sizeOfUpperLeftGroup <= picWidth * picHeight);
+
+ k = 0;
+ for (j = 0; j < picWidth; j++)
+ for (i = 0; i < picHeight; i++)
+ if (k++ < sizeOfUpperLeftGroup)
+ map[ i * picWidth + j ] = (u32)sliceGroupChangeDirectionFlag;
+ else
+ map[ i * picWidth + j ] = 1 -
+ (u32)sliceGroupChangeDirectionFlag;
+
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdDecodeSliceGroupMap
+
+ Functional description:
+ Function to decode macroblock to slice group map. Construction
+ of different slice group map types is handled by separate
+ functions defined above. See standard for details how slice group
+ maps are computed.
+
+ Inputs:
+ pps active picture parameter set
+ sliceGroupChangeCycle slice_group_change_cycle
+ picWidth picture width in macroblocks
+ picHeight picture height in macroblocks
+
+ Outputs:
+ map slice group map is stored here
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void h264bsdDecodeSliceGroupMap(
+ u32 *map,
+ picParamSet_t *pps,
+ u32 sliceGroupChangeCycle,
+ u32 picWidth,
+ u32 picHeight)
+{
+
+/* Variables */
+
+ u32 i, picSize, unitsInSliceGroup0 = 0, sizeOfUpperLeftGroup = 0;
+
+/* Code */
+
+ ASSERT(map);
+ ASSERT(pps);
+ ASSERT(picWidth);
+ ASSERT(picHeight);
+ ASSERT(pps->sliceGroupMapType < 7);
+
+ picSize = picWidth * picHeight;
+
+ /* just one slice group -> all macroblocks belong to group 0 */
+ if (pps->numSliceGroups == 1)
+ {
+ H264SwDecMemset(map, 0, picSize * sizeof(u32));
+ return;
+ }
+
+ if (pps->sliceGroupMapType > 2 && pps->sliceGroupMapType < 6)
+ {
+ ASSERT(pps->sliceGroupChangeRate &&
+ pps->sliceGroupChangeRate <= picSize);
+
+ unitsInSliceGroup0 =
+ MIN(sliceGroupChangeCycle * pps->sliceGroupChangeRate, picSize);
+
+ if (pps->sliceGroupMapType == 4 || pps->sliceGroupMapType == 5)
+ sizeOfUpperLeftGroup = pps->sliceGroupChangeDirectionFlag ?
+ (picSize - unitsInSliceGroup0) : unitsInSliceGroup0;
+ }
+
+ switch (pps->sliceGroupMapType)
+ {
+ case 0:
+ DecodeInterleavedMap(map, pps->numSliceGroups,
+ pps->runLength, picSize);
+ break;
+
+ case 1:
+ DecodeDispersedMap(map, pps->numSliceGroups, picWidth,
+ picHeight);
+ break;
+
+ case 2:
+ DecodeForegroundLeftOverMap(map, pps->numSliceGroups,
+ pps->topLeft, pps->bottomRight, picWidth, picHeight);
+ break;
+
+ case 3:
+ DecodeBoxOutMap(map, pps->sliceGroupChangeDirectionFlag,
+ unitsInSliceGroup0, picWidth, picHeight);
+ break;
+
+ case 4:
+ DecodeRasterScanMap(map,
+ pps->sliceGroupChangeDirectionFlag, sizeOfUpperLeftGroup,
+ picSize);
+ break;
+
+ case 5:
+ DecodeWipeMap(map, pps->sliceGroupChangeDirectionFlag,
+ sizeOfUpperLeftGroup, picWidth, picHeight);
+ break;
+
+ default:
+ ASSERT(pps->sliceGroupId);
+ for (i = 0; i < picSize; i++)
+ {
+ ASSERT(pps->sliceGroupId[i] < pps->numSliceGroups);
+ map[i] = pps->sliceGroupId[i];
+ }
+ break;
+ }
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.h
new file mode 100755
index 0000000..4bcb6f2
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_group_map.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_SLICE_GROUP_MAP_H
+#define H264SWDEC_SLICE_GROUP_MAP_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_pic_param_set.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+void h264bsdDecodeSliceGroupMap(
+ u32 *map,
+ picParamSet_t *pps,
+ u32 sliceGroupChangeCycle,
+ u32 picWidth,
+ u32 picHeight);
+
+#endif /* #ifdef H264SWDEC_SLICE_GROUP_MAP_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.c
new file mode 100755
index 0000000..a7c6f64
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.c
@@ -0,0 +1,1511 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdDecodeSliceHeader
+ NumSliceGroupChangeCycleBits
+ RefPicListReordering
+ DecRefPicMarking
+ CheckPpsId
+ CheckFrameNum
+ CheckIdrPicId
+ CheckPicOrderCntLsb
+ CheckDeltaPicOrderCntBottom
+ CheckDeltaPicOrderCnt
+ CheckRedundantPicCnt
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_slice_header.h"
+#include "h264bsd_util.h"
+#include "h264bsd_vlc.h"
+#include "h264bsd_nal_unit.h"
+#include "h264bsd_dpb.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static u32 RefPicListReordering(strmData_t *, refPicListReordering_t *,
+ u32, u32);
+
+static u32 NumSliceGroupChangeCycleBits(u32 picSizeInMbs,
+ u32 sliceGroupChangeRate);
+
+static u32 DecRefPicMarking(strmData_t *pStrmData,
+ decRefPicMarking_t *pDecRefPicMarking, nalUnitType_e nalUnitType,
+ u32 numRefFrames);
+
+
+/*------------------------------------------------------------------------------
+
+ Function name: h264bsdDecodeSliceHeader
+
+ Functional description:
+ Decode slice header data from the stream.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ pSeqParamSet pointer to active sequence parameter set
+ pPicParamSet pointer to active picture parameter set
+ pNalUnit pointer to current NAL unit structure
+
+ Outputs:
+ pSliceHeader decoded data is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data or end of stream
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeSliceHeader(strmData_t *pStrmData, sliceHeader_t *pSliceHeader,
+ seqParamSet_t *pSeqParamSet, picParamSet_t *pPicParamSet,
+ nalUnit_t *pNalUnit)
+{
+
+/* Variables */
+
+ u32 tmp, i, value;
+ i32 itmp;
+ u32 picSizeInMbs;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSliceHeader);
+ ASSERT(pSeqParamSet);
+ ASSERT(pPicParamSet);
+ ASSERT( pNalUnit->nalUnitType == NAL_CODED_SLICE ||
+ pNalUnit->nalUnitType == NAL_CODED_SLICE_IDR );
+
+
+ H264SwDecMemset(pSliceHeader, 0, sizeof(sliceHeader_t));
+
+ picSizeInMbs = pSeqParamSet->picWidthInMbs * pSeqParamSet->picHeightInMbs;
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSliceHeader->firstMbInSlice = value;
+ if (value >= picSizeInMbs)
+ {
+ EPRINT("first_mb_in_slice");
+ return(HANTRO_NOK);
+ }
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSliceHeader->sliceType = value;
+ /* slice type has to be either I or P slice. P slice is not allowed when
+ * current NAL unit is an IDR NAL unit or num_ref_frames is 0 */
+ if ( !IS_I_SLICE(pSliceHeader->sliceType) &&
+ ( !IS_P_SLICE(pSliceHeader->sliceType) ||
+ IS_IDR_NAL_UNIT(pNalUnit) ||
+ !pSeqParamSet->numRefFrames ) )
+ {
+ EPRINT("slice_type");
+ return(HANTRO_NOK);
+ }
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSliceHeader->picParameterSetId = value;
+ if (pSliceHeader->picParameterSetId != pPicParamSet->picParameterSetId)
+ {
+ EPRINT("pic_parameter_set_id");
+ return(HANTRO_NOK);
+ }
+
+ /* log2(maxFrameNum) -> num bits to represent frame_num */
+ i = 0;
+ while (pSeqParamSet->maxFrameNum >> i)
+ i++;
+ i--;
+
+ tmp = h264bsdGetBits(pStrmData, i);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (IS_IDR_NAL_UNIT(pNalUnit) && tmp != 0)
+ {
+ EPRINT("frame_num");
+ return(HANTRO_NOK);
+ }
+ pSliceHeader->frameNum = tmp;
+
+ if (IS_IDR_NAL_UNIT(pNalUnit))
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSliceHeader->idrPicId = value;
+ if (value > 65535)
+ {
+ EPRINT("idr_pic_id");
+ return(HANTRO_NOK);
+ }
+ }
+
+ if (pSeqParamSet->picOrderCntType == 0)
+ {
+ /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */
+ i = 0;
+ while (pSeqParamSet->maxPicOrderCntLsb >> i)
+ i++;
+ i--;
+
+ tmp = h264bsdGetBits(pStrmData, i);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSliceHeader->picOrderCntLsb = tmp;
+
+ if (pPicParamSet->picOrderPresentFlag)
+ {
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSliceHeader->deltaPicOrderCntBottom = itmp;
+ }
+
+ /* check that picOrderCnt for IDR picture will be zero. See
+ * DecodePicOrderCnt function to understand the logic here */
+ if ( IS_IDR_NAL_UNIT(pNalUnit) &&
+ ( (pSliceHeader->picOrderCntLsb >
+ pSeqParamSet->maxPicOrderCntLsb/2) ||
+ MIN((i32)pSliceHeader->picOrderCntLsb,
+ (i32)pSliceHeader->picOrderCntLsb +
+ pSliceHeader->deltaPicOrderCntBottom) != 0 ) )
+ {
+ return(HANTRO_NOK);
+ }
+ }
+
+ if ( (pSeqParamSet->picOrderCntType == 1) &&
+ !pSeqParamSet->deltaPicOrderAlwaysZeroFlag )
+ {
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSliceHeader->deltaPicOrderCnt[0] = itmp;
+
+ if (pPicParamSet->picOrderPresentFlag)
+ {
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSliceHeader->deltaPicOrderCnt[1] = itmp;
+ }
+
+ /* check that picOrderCnt for IDR picture will be zero. See
+ * DecodePicOrderCnt function to understand the logic here */
+ if ( IS_IDR_NAL_UNIT(pNalUnit) &&
+ MIN(pSliceHeader->deltaPicOrderCnt[0],
+ pSliceHeader->deltaPicOrderCnt[0] +
+ pSeqParamSet->offsetForTopToBottomField +
+ pSliceHeader->deltaPicOrderCnt[1]) != 0)
+ {
+ return(HANTRO_NOK);
+ }
+ }
+
+ if (pPicParamSet->redundantPicCntPresentFlag)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSliceHeader->redundantPicCnt = value;
+ if (value > 127)
+ {
+ EPRINT("redundant_pic_cnt");
+ return(HANTRO_NOK);
+ }
+ }
+
+ if (IS_P_SLICE(pSliceHeader->sliceType))
+ {
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSliceHeader->numRefIdxActiveOverrideFlag = tmp;
+
+ if (pSliceHeader->numRefIdxActiveOverrideFlag)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (value > 15)
+ {
+ EPRINT("num_ref_idx_l0_active_minus1");
+ return(HANTRO_NOK);
+ }
+ pSliceHeader->numRefIdxL0Active = value + 1;
+ }
+ /* set numRefIdxL0Active from pic param set */
+ else
+ {
+ /* if value (minus1) in picture parameter set exceeds 15 it should
+ * have been overridden here */
+ if (pPicParamSet->numRefIdxL0Active > 16)
+ {
+ EPRINT("num_ref_idx_active_override_flag");
+ return(HANTRO_NOK);
+ }
+ pSliceHeader->numRefIdxL0Active = pPicParamSet->numRefIdxL0Active;
+ }
+ }
+
+ if (IS_P_SLICE(pSliceHeader->sliceType))
+ {
+ tmp = RefPicListReordering(pStrmData,
+ &pSliceHeader->refPicListReordering,
+ pSliceHeader->numRefIdxL0Active,
+ pSeqParamSet->maxFrameNum);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+
+ if (pNalUnit->nalRefIdc != 0)
+ {
+ tmp = DecRefPicMarking(pStrmData, &pSliceHeader->decRefPicMarking,
+ pNalUnit->nalUnitType, pSeqParamSet->numRefFrames);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+
+ /* decode sliceQpDelta and check that initial QP for the slice will be on
+ * the range [0, 51] */
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSliceHeader->sliceQpDelta = itmp;
+ itmp += (i32)pPicParamSet->picInitQp;
+ if ( (itmp < 0) || (itmp > 51) )
+ {
+ EPRINT("slice_qp_delta");
+ return(HANTRO_NOK);
+ }
+
+ if (pPicParamSet->deblockingFilterControlPresentFlag)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pSliceHeader->disableDeblockingFilterIdc = value;
+ if (pSliceHeader->disableDeblockingFilterIdc > 2)
+ {
+ EPRINT("disable_deblocking_filter_idc");
+ return(HANTRO_NOK);
+ }
+
+ if (pSliceHeader->disableDeblockingFilterIdc != 1)
+ {
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if ( (itmp < -6) || (itmp > 6) )
+ {
+ EPRINT("slice_alpha_c0_offset_div2");
+ return(HANTRO_NOK);
+ }
+ pSliceHeader->sliceAlphaC0Offset = itmp * 2;
+
+ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if ( (itmp < -6) || (itmp > 6) )
+ {
+ EPRINT("slice_beta_offset_div2");
+ return(HANTRO_NOK);
+ }
+ pSliceHeader->sliceBetaOffset = itmp * 2;
+ }
+ }
+
+ if ( (pPicParamSet->numSliceGroups > 1) &&
+ (pPicParamSet->sliceGroupMapType >= 3) &&
+ (pPicParamSet->sliceGroupMapType <= 5) )
+ {
+ /* set tmp to number of bits used to represent slice_group_change_cycle
+ * in the stream */
+ tmp = NumSliceGroupChangeCycleBits(picSizeInMbs,
+ pPicParamSet->sliceGroupChangeRate);
+ value = h264bsdGetBits(pStrmData, tmp);
+ if (value == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pSliceHeader->sliceGroupChangeCycle = value;
+
+ /* corresponds to tmp = Ceil(picSizeInMbs / sliceGroupChangeRate) */
+ tmp = (picSizeInMbs + pPicParamSet->sliceGroupChangeRate - 1) /
+ pPicParamSet->sliceGroupChangeRate;
+ if (pSliceHeader->sliceGroupChangeCycle > tmp)
+ {
+ EPRINT("slice_group_change_cycle");
+ return(HANTRO_NOK);
+ }
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: NumSliceGroupChangeCycleBits
+
+ Functional description:
+ Determine number of bits needed to represent
+ slice_group_change_cycle in the stream. The standard states that
+ slice_group_change_cycle is represented by
+ Ceil( Log2( (picSizeInMbs / sliceGroupChangeRate) + 1) )
+
+ bits. Division "/" in the equation is non-truncating division.
+
+ Inputs:
+ picSizeInMbs picture size in macroblocks
+ sliceGroupChangeRate
+
+ Outputs:
+ none
+
+ Returns:
+ number of bits needed
+
+------------------------------------------------------------------------------*/
+
+u32 NumSliceGroupChangeCycleBits(u32 picSizeInMbs, u32 sliceGroupChangeRate)
+{
+
+/* Variables */
+
+ u32 tmp,numBits,mask;
+
+/* Code */
+
+ ASSERT(picSizeInMbs);
+ ASSERT(sliceGroupChangeRate);
+ ASSERT(sliceGroupChangeRate <= picSizeInMbs);
+
+ /* compute (picSizeInMbs / sliceGroupChangeRate + 1), rounded up */
+ if (picSizeInMbs % sliceGroupChangeRate)
+ tmp = 2 + picSizeInMbs/sliceGroupChangeRate;
+ else
+ tmp = 1 + picSizeInMbs/sliceGroupChangeRate;
+
+ numBits = 0;
+ mask = ~0U;
+
+ /* set numBits to position of right-most non-zero bit */
+ while (tmp & (mask<<++numBits))
+ ;
+ numBits--;
+
+ /* add one more bit if value greater than 2^numBits */
+ if (tmp & ((1<<numBits)-1))
+ numBits++;
+
+ return(numBits);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: RefPicListReordering
+
+ Functional description:
+ Decode reference picture list reordering syntax elements from
+ the stream. Max number of reordering commands is numRefIdxActive.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ numRefIdxActive number of active reference indices to be used for
+ current slice
+ maxPicNum maxFrameNum from the active SPS
+
+ Outputs:
+ pRefPicListReordering decoded data is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data
+
+------------------------------------------------------------------------------*/
+
+u32 RefPicListReordering(strmData_t *pStrmData,
+ refPicListReordering_t *pRefPicListReordering, u32 numRefIdxActive,
+ u32 maxPicNum)
+{
+
+/* Variables */
+
+ u32 tmp, value, i;
+ u32 command;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pRefPicListReordering);
+ ASSERT(numRefIdxActive);
+ ASSERT(maxPicNum);
+
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ pRefPicListReordering->refPicListReorderingFlagL0 = tmp;
+
+ if (pRefPicListReordering->refPicListReorderingFlagL0)
+ {
+ i = 0;
+
+ do
+ {
+ if (i > numRefIdxActive)
+ {
+ EPRINT("Too many reordering commands");
+ return(HANTRO_NOK);
+ }
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &command);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (command > 3)
+ {
+ EPRINT("reordering_of_pic_nums_idc");
+ return(HANTRO_NOK);
+ }
+
+ pRefPicListReordering->command[i].reorderingOfPicNumsIdc = command;
+
+ if ((command == 0) || (command == 1))
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (value >= maxPicNum)
+ {
+ EPRINT("abs_diff_pic_num_minus1");
+ return(HANTRO_NOK);
+ }
+ pRefPicListReordering->command[i].absDiffPicNum = value + 1;
+ }
+ else if (command == 2)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pRefPicListReordering->command[i].longTermPicNum = value;
+ }
+ i++;
+ } while (command != 3);
+
+ /* there shall be at least one reordering command if
+ * refPicListReorderingFlagL0 was set */
+ if (i == 1)
+ {
+ EPRINT("ref_pic_list_reordering");
+ return(HANTRO_NOK);
+ }
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecRefPicMarking
+
+ Functional description:
+ Decode decoded reference picture marking syntax elements from
+ the stream.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ nalUnitType type of the current NAL unit
+ numRefFrames max number of reference frames from the active SPS
+
+ Outputs:
+ pDecRefPicMarking decoded data is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data
+
+------------------------------------------------------------------------------*/
+
+u32 DecRefPicMarking(strmData_t *pStrmData,
+ decRefPicMarking_t *pDecRefPicMarking, nalUnitType_e nalUnitType,
+ u32 numRefFrames)
+{
+
+/* Variables */
+
+ u32 tmp, value;
+ u32 i;
+ u32 operation;
+ /* variables for error checking purposes, store number of memory
+ * management operations of certain type */
+ u32 num4 = 0, num5 = 0, num6 = 0, num1to3 = 0;
+
+/* Code */
+
+ ASSERT( nalUnitType == NAL_CODED_SLICE_IDR ||
+ nalUnitType == NAL_CODED_SLICE ||
+ nalUnitType == NAL_SEI );
+
+
+ if (nalUnitType == NAL_CODED_SLICE_IDR)
+ {
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pDecRefPicMarking->noOutputOfPriorPicsFlag = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pDecRefPicMarking->longTermReferenceFlag = tmp;
+ if (!numRefFrames && pDecRefPicMarking->longTermReferenceFlag)
+ {
+ EPRINT("long_term_reference_flag");
+ return(HANTRO_NOK);
+ }
+ }
+ else
+ {
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pDecRefPicMarking->adaptiveRefPicMarkingModeFlag = tmp;
+ if (pDecRefPicMarking->adaptiveRefPicMarkingModeFlag)
+ {
+ i = 0;
+ do
+ {
+ /* see explanation of the MAX_NUM_MMC_OPERATIONS in
+ * slice_header.h */
+ if (i > (2 * numRefFrames + 2))
+ {
+ EPRINT("Too many management operations");
+ return(HANTRO_NOK);
+ }
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &operation);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (operation > 6)
+ {
+ EPRINT("memory_management_control_operation");
+ return(HANTRO_NOK);
+ }
+
+ pDecRefPicMarking->operation[i].
+ memoryManagementControlOperation = operation;
+ if ((operation == 1) || (operation == 3))
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pDecRefPicMarking->operation[i].differenceOfPicNums =
+ value + 1;
+ }
+ if (operation == 2)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pDecRefPicMarking->operation[i].longTermPicNum = value;
+ }
+ if ((operation == 3) || (operation == 6))
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ pDecRefPicMarking->operation[i].longTermFrameIdx =
+ value;
+ }
+ if (operation == 4)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ /* value shall be in range [0, numRefFrames] */
+ if (value > numRefFrames)
+ {
+ EPRINT("max_long_term_frame_idx_plus1");
+ return(HANTRO_NOK);
+ }
+ if (value == 0)
+ {
+ pDecRefPicMarking->operation[i].
+ maxLongTermFrameIdx =
+ NO_LONG_TERM_FRAME_INDICES;
+ }
+ else
+ {
+ pDecRefPicMarking->operation[i].
+ maxLongTermFrameIdx = value - 1;
+ }
+ num4++;
+ }
+ if (operation == 5)
+ {
+ num5++;
+ }
+ if (operation && operation <= 3)
+ num1to3++;
+ if (operation == 6)
+ num6++;
+
+ i++;
+ } while (operation != 0);
+
+ /* error checking */
+ if (num4 > 1 || num5 > 1 || num6 > 1 || (num1to3 && num5))
+ return(HANTRO_NOK);
+
+ }
+ }
+
+ return(HANTRO_OK);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: h264bsdCheckPpsId
+
+ Functional description:
+ Peek value of pic_parameter_set_id from the slice header. Function
+ does not modify current stream positions but copies the stream
+ data structure to tmp structure which is used while accessing
+ stream data.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+
+ Outputs:
+ picParamSetId value is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdCheckPpsId(strmData_t *pStrmData, u32 *picParamSetId)
+{
+
+/* Variables */
+
+ u32 tmp, value;
+ strmData_t tmpStrmData[1];
+
+/* Code */
+
+ ASSERT(pStrmData);
+
+ /* don't touch original stream position params */
+ *tmpStrmData = *pStrmData;
+
+ /* first_mb_in_slice */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* slice_type */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (value >= MAX_NUM_PIC_PARAM_SETS)
+ return(HANTRO_NOK);
+
+ *picParamSetId = value;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdCheckFrameNum
+
+ Functional description:
+ Peek value of frame_num from the slice header. Function does not
+ modify current stream positions but copies the stream data
+ structure to tmp structure which is used while accessing stream
+ data.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ maxFrameNum
+
+ Outputs:
+ frameNum value is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdCheckFrameNum(
+ strmData_t *pStrmData,
+ u32 maxFrameNum,
+ u32 *frameNum)
+{
+
+/* Variables */
+
+ u32 tmp, value, i;
+ strmData_t tmpStrmData[1];
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(maxFrameNum);
+ ASSERT(frameNum);
+
+ /* don't touch original stream position params */
+ *tmpStrmData = *pStrmData;
+
+ /* skip first_mb_in_slice */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* skip slice_type */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* skip pic_parameter_set_id */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* log2(maxFrameNum) -> num bits to represent frame_num */
+ i = 0;
+ while (maxFrameNum >> i)
+ i++;
+ i--;
+
+ /* frame_num */
+ tmp = h264bsdGetBits(tmpStrmData, i);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ *frameNum = tmp;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdCheckIdrPicId
+
+ Functional description:
+ Peek value of idr_pic_id from the slice header. Function does not
+ modify current stream positions but copies the stream data
+ structure to tmp structure which is used while accessing stream
+ data.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ maxFrameNum max frame number from active SPS
+ nalUnitType type of the current NAL unit
+
+ Outputs:
+ idrPicId value is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdCheckIdrPicId(
+ strmData_t *pStrmData,
+ u32 maxFrameNum,
+ nalUnitType_e nalUnitType,
+ u32 *idrPicId)
+{
+
+/* Variables */
+
+ u32 tmp, value, i;
+ strmData_t tmpStrmData[1];
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(maxFrameNum);
+ ASSERT(idrPicId);
+
+ /* nalUnitType must be equal to 5 because otherwise idrPicId is not
+ * present */
+ if (nalUnitType != NAL_CODED_SLICE_IDR)
+ return(HANTRO_NOK);
+
+ /* don't touch original stream position params */
+ *tmpStrmData = *pStrmData;
+
+ /* skip first_mb_in_slice */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* skip slice_type */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* skip pic_parameter_set_id */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* log2(maxFrameNum) -> num bits to represent frame_num */
+ i = 0;
+ while (maxFrameNum >> i)
+ i++;
+ i--;
+
+ /* skip frame_num */
+ tmp = h264bsdGetBits(tmpStrmData, i);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ /* idr_pic_id */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, idrPicId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdCheckPicOrderCntLsb
+
+ Functional description:
+ Peek value of pic_order_cnt_lsb from the slice header. Function
+ does not modify current stream positions but copies the stream
+ data structure to tmp structure which is used while accessing
+ stream data.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ pSeqParamSet pointer to active SPS
+ nalUnitType type of the current NAL unit
+
+ Outputs:
+ picOrderCntLsb value is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdCheckPicOrderCntLsb(
+ strmData_t *pStrmData,
+ seqParamSet_t *pSeqParamSet,
+ nalUnitType_e nalUnitType,
+ u32 *picOrderCntLsb)
+{
+
+/* Variables */
+
+ u32 tmp, value, i;
+ strmData_t tmpStrmData[1];
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSeqParamSet);
+ ASSERT(picOrderCntLsb);
+
+ /* picOrderCntType must be equal to 0 */
+ ASSERT(pSeqParamSet->picOrderCntType == 0);
+ ASSERT(pSeqParamSet->maxFrameNum);
+ ASSERT(pSeqParamSet->maxPicOrderCntLsb);
+
+ /* don't touch original stream position params */
+ *tmpStrmData = *pStrmData;
+
+ /* skip first_mb_in_slice */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* skip slice_type */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* skip pic_parameter_set_id */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* log2(maxFrameNum) -> num bits to represent frame_num */
+ i = 0;
+ while (pSeqParamSet->maxFrameNum >> i)
+ i++;
+ i--;
+
+ /* skip frame_num */
+ tmp = h264bsdGetBits(tmpStrmData, i);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ /* skip idr_pic_id when necessary */
+ if (nalUnitType == NAL_CODED_SLICE_IDR)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+
+ /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */
+ i = 0;
+ while (pSeqParamSet->maxPicOrderCntLsb >> i)
+ i++;
+ i--;
+
+ /* pic_order_cnt_lsb */
+ tmp = h264bsdGetBits(tmpStrmData, i);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ *picOrderCntLsb = tmp;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdCheckDeltaPicOrderCntBottom
+
+ Functional description:
+ Peek value of delta_pic_order_cnt_bottom from the slice header.
+ Function does not modify current stream positions but copies the
+ stream data structure to tmp structure which is used while
+ accessing stream data.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ pSeqParamSet pointer to active SPS
+ nalUnitType type of the current NAL unit
+
+ Outputs:
+ deltaPicOrderCntBottom value is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdCheckDeltaPicOrderCntBottom(
+ strmData_t *pStrmData,
+ seqParamSet_t *pSeqParamSet,
+ nalUnitType_e nalUnitType,
+ i32 *deltaPicOrderCntBottom)
+{
+
+/* Variables */
+
+ u32 tmp, value, i;
+ strmData_t tmpStrmData[1];
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSeqParamSet);
+ ASSERT(deltaPicOrderCntBottom);
+
+ /* picOrderCntType must be equal to 0 and picOrderPresentFlag must be TRUE
+ * */
+ ASSERT(pSeqParamSet->picOrderCntType == 0);
+ ASSERT(pSeqParamSet->maxFrameNum);
+ ASSERT(pSeqParamSet->maxPicOrderCntLsb);
+
+ /* don't touch original stream position params */
+ *tmpStrmData = *pStrmData;
+
+ /* skip first_mb_in_slice */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* skip slice_type */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* skip pic_parameter_set_id */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* log2(maxFrameNum) -> num bits to represent frame_num */
+ i = 0;
+ while (pSeqParamSet->maxFrameNum >> i)
+ i++;
+ i--;
+
+ /* skip frame_num */
+ tmp = h264bsdGetBits(tmpStrmData, i);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ /* skip idr_pic_id when necessary */
+ if (nalUnitType == NAL_CODED_SLICE_IDR)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+
+ /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */
+ i = 0;
+ while (pSeqParamSet->maxPicOrderCntLsb >> i)
+ i++;
+ i--;
+
+ /* skip pic_order_cnt_lsb */
+ tmp = h264bsdGetBits(tmpStrmData, i);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ /* delta_pic_order_cnt_bottom */
+ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, deltaPicOrderCntBottom);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdCheckDeltaPicOrderCnt
+
+ Functional description:
+ Peek values delta_pic_order_cnt[0] and delta_pic_order_cnt[1]
+ from the slice header. Function does not modify current stream
+ positions but copies the stream data structure to tmp structure
+ which is used while accessing stream data.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ pSeqParamSet pointer to active SPS
+ nalUnitType type of the current NAL unit
+ picOrderPresentFlag flag indicating if delta_pic_order_cnt[1]
+ is present in the stream
+
+ Outputs:
+ deltaPicOrderCnt values are stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdCheckDeltaPicOrderCnt(
+ strmData_t *pStrmData,
+ seqParamSet_t *pSeqParamSet,
+ nalUnitType_e nalUnitType,
+ u32 picOrderPresentFlag,
+ i32 *deltaPicOrderCnt)
+{
+
+/* Variables */
+
+ u32 tmp, value, i;
+ strmData_t tmpStrmData[1];
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSeqParamSet);
+ ASSERT(deltaPicOrderCnt);
+
+ /* picOrderCntType must be equal to 1 and deltaPicOrderAlwaysZeroFlag must
+ * be FALSE */
+ ASSERT(pSeqParamSet->picOrderCntType == 1);
+ ASSERT(!pSeqParamSet->deltaPicOrderAlwaysZeroFlag);
+ ASSERT(pSeqParamSet->maxFrameNum);
+
+ /* don't touch original stream position params */
+ *tmpStrmData = *pStrmData;
+
+ /* skip first_mb_in_slice */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* skip slice_type */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* skip pic_parameter_set_id */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* log2(maxFrameNum) -> num bits to represent frame_num */
+ i = 0;
+ while (pSeqParamSet->maxFrameNum >> i)
+ i++;
+ i--;
+
+ /* skip frame_num */
+ tmp = h264bsdGetBits(tmpStrmData, i);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ /* skip idr_pic_id when necessary */
+ if (nalUnitType == NAL_CODED_SLICE_IDR)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+
+ /* delta_pic_order_cnt[0] */
+ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &deltaPicOrderCnt[0]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* delta_pic_order_cnt[1] if present */
+ if (picOrderPresentFlag)
+ {
+ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &deltaPicOrderCnt[1]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdCheckRedundantPicCnt
+
+ Functional description:
+ Peek value of redundant_pic_cnt from the slice header. Function
+ does not modify current stream positions but copies the stream
+ data structure to tmp structure which is used while accessing
+ stream data.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ pSeqParamSet pointer to active SPS
+ pPicParamSet pointer to active PPS
+ nalUnitType type of the current NAL unit
+
+ Outputs:
+ redundantPicCnt value is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdCheckRedundantPicCnt(
+ strmData_t *pStrmData,
+ seqParamSet_t *pSeqParamSet,
+ picParamSet_t *pPicParamSet,
+ nalUnitType_e nalUnitType,
+ u32 *redundantPicCnt)
+{
+
+/* Variables */
+
+ u32 tmp, value, i;
+ i32 ivalue;
+ strmData_t tmpStrmData[1];
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSeqParamSet);
+ ASSERT(pPicParamSet);
+ ASSERT(redundantPicCnt);
+
+ /* redundant_pic_cnt_flag must be TRUE */
+ ASSERT(pPicParamSet->redundantPicCntPresentFlag);
+ ASSERT(pSeqParamSet->maxFrameNum);
+ ASSERT(pSeqParamSet->picOrderCntType > 0 ||
+ pSeqParamSet->maxPicOrderCntLsb);
+
+ /* don't touch original stream position params */
+ *tmpStrmData = *pStrmData;
+
+ /* skip first_mb_in_slice */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* skip slice_type */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* skip pic_parameter_set_id */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* log2(maxFrameNum) -> num bits to represent frame_num */
+ i = 0;
+ while (pSeqParamSet->maxFrameNum >> i)
+ i++;
+ i--;
+
+ /* skip frame_num */
+ tmp = h264bsdGetBits(tmpStrmData, i);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ /* skip idr_pic_id when necessary */
+ if (nalUnitType == NAL_CODED_SLICE_IDR)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+
+ if (pSeqParamSet->picOrderCntType == 0)
+ {
+ /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */
+ i = 0;
+ while (pSeqParamSet->maxPicOrderCntLsb >> i)
+ i++;
+ i--;
+
+ /* pic_order_cnt_lsb */
+ tmp = h264bsdGetBits(tmpStrmData, i);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ if (pPicParamSet->picOrderPresentFlag)
+ {
+ /* skip delta_pic_order_cnt_bottom */
+ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+ }
+
+ if (pSeqParamSet->picOrderCntType == 1 &&
+ !pSeqParamSet->deltaPicOrderAlwaysZeroFlag)
+ {
+ /* delta_pic_order_cnt[0] */
+ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* delta_pic_order_cnt[1] if present */
+ if (pPicParamSet->picOrderPresentFlag)
+ {
+ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+ }
+
+ /* redundant_pic_cnt */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, redundantPicCnt);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ return(HANTRO_OK);
+
+}
+
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdCheckPriorPicsFlag
+
+ Functional description:
+ Peek value of no_output_of_prior_pics_flag from the slice header.
+ Function does not modify current stream positions but copies
+ the stream data structure to tmp structure which is used while
+ accessing stream data.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ pSeqParamSet pointer to active SPS
+ pPicParamSet pointer to active PPS
+ nalUnitType type of the current NAL unit
+
+ Outputs:
+ noOutputOfPriorPicsFlag value is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data
+
+------------------------------------------------------------------------------*/
+/*lint -e715 disable lint info nalUnitType not referenced */
+u32 h264bsdCheckPriorPicsFlag(u32 * noOutputOfPriorPicsFlag,
+ const strmData_t * pStrmData,
+ const seqParamSet_t * pSeqParamSet,
+ const picParamSet_t * pPicParamSet,
+ nalUnitType_e nalUnitType)
+{
+/* Variables */
+
+ u32 tmp, value, i;
+ i32 ivalue;
+ strmData_t tmpStrmData[1];
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pSeqParamSet);
+ ASSERT(pPicParamSet);
+ ASSERT(noOutputOfPriorPicsFlag);
+
+ /* must be IDR lsice */
+ ASSERT(nalUnitType == NAL_CODED_SLICE_IDR);
+
+ /* don't touch original stream position params */
+ *tmpStrmData = *pStrmData;
+
+ /* skip first_mb_in_slice */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if(tmp != HANTRO_OK)
+ return (tmp);
+
+ /* slice_type */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if(tmp != HANTRO_OK)
+ return (tmp);
+
+ /* skip pic_parameter_set_id */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if(tmp != HANTRO_OK)
+ return (tmp);
+
+ /* log2(maxFrameNum) -> num bits to represent frame_num */
+ i = 0;
+ while(pSeqParamSet->maxFrameNum >> i)
+ i++;
+ i--;
+
+ /* skip frame_num */
+ tmp = h264bsdGetBits(tmpStrmData, i);
+ if(tmp == END_OF_STREAM)
+ return (HANTRO_NOK);
+
+ /* skip idr_pic_id */
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if(tmp != HANTRO_OK)
+ return (tmp);
+
+ if(pSeqParamSet->picOrderCntType == 0)
+ {
+ /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */
+ i = 0;
+ while(pSeqParamSet->maxPicOrderCntLsb >> i)
+ i++;
+ i--;
+
+ /* skip pic_order_cnt_lsb */
+ tmp = h264bsdGetBits(tmpStrmData, i);
+ if(tmp == END_OF_STREAM)
+ return (HANTRO_NOK);
+
+ if(pPicParamSet->picOrderPresentFlag)
+ {
+ /* skip delta_pic_order_cnt_bottom */
+ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue);
+ if(tmp != HANTRO_OK)
+ return (tmp);
+ }
+ }
+
+ if(pSeqParamSet->picOrderCntType == 1 &&
+ !pSeqParamSet->deltaPicOrderAlwaysZeroFlag)
+ {
+ /* skip delta_pic_order_cnt[0] */
+ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue);
+ if(tmp != HANTRO_OK)
+ return (tmp);
+
+ /* skip delta_pic_order_cnt[1] if present */
+ if(pPicParamSet->picOrderPresentFlag)
+ {
+ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue);
+ if(tmp != HANTRO_OK)
+ return (tmp);
+ }
+ }
+
+ /* skip redundant_pic_cnt */
+ if(pPicParamSet->redundantPicCntPresentFlag)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value);
+ if(tmp != HANTRO_OK)
+ return (tmp);
+ }
+
+ *noOutputOfPriorPicsFlag = h264bsdGetBits(tmpStrmData, 1);
+ if(*noOutputOfPriorPicsFlag == END_OF_STREAM)
+ return (HANTRO_NOK);
+
+ return (HANTRO_OK);
+
+}
+/*lint +e715 */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.h
new file mode 100755
index 0000000..198898a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_header.h
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_SLICE_HEADER_H
+#define H264SWDEC_SLICE_HEADER_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_stream.h"
+#include "h264bsd_cfg.h"
+#include "h264bsd_seq_param_set.h"
+#include "h264bsd_pic_param_set.h"
+#include "h264bsd_nal_unit.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+enum {
+ P_SLICE = 0,
+ I_SLICE = 2
+};
+
+enum {NO_LONG_TERM_FRAME_INDICES = 0xFFFF};
+
+/* macro to determine if slice is an inter slice, sliceTypes 0 and 5 */
+#define IS_P_SLICE(sliceType) (((sliceType) == P_SLICE) || \
+ ((sliceType) == P_SLICE + 5))
+
+/* macro to determine if slice is an intra slice, sliceTypes 2 and 7 */
+#define IS_I_SLICE(sliceType) (((sliceType) == I_SLICE) || \
+ ((sliceType) == I_SLICE + 5))
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/* structure to store data of one reference picture list reordering operation */
+typedef struct
+{
+ u32 reorderingOfPicNumsIdc;
+ u32 absDiffPicNum;
+ u32 longTermPicNum;
+} refPicListReorderingOperation_t;
+
+/* structure to store reference picture list reordering operations */
+typedef struct
+{
+ u32 refPicListReorderingFlagL0;
+ refPicListReorderingOperation_t command[MAX_NUM_REF_PICS+1];
+} refPicListReordering_t;
+
+/* structure to store data of one DPB memory management control operation */
+typedef struct
+{
+ u32 memoryManagementControlOperation;
+ u32 differenceOfPicNums;
+ u32 longTermPicNum;
+ u32 longTermFrameIdx;
+ u32 maxLongTermFrameIdx;
+} memoryManagementOperation_t;
+
+/* worst case scenario: all MAX_NUM_REF_PICS pictures in the buffer are
+ * short term pictures, each one of them is first marked as long term
+ * reference picture which is then marked as unused for reference.
+ * Additionally, max long-term frame index is set and current picture is
+ * marked as long term reference picture. Last position reserved for
+ * end memory_management_control_operation command */
+#define MAX_NUM_MMC_OPERATIONS (2*MAX_NUM_REF_PICS+2+1)
+
+/* structure to store decoded reference picture marking data */
+typedef struct
+{
+ u32 noOutputOfPriorPicsFlag;
+ u32 longTermReferenceFlag;
+ u32 adaptiveRefPicMarkingModeFlag;
+ memoryManagementOperation_t operation[MAX_NUM_MMC_OPERATIONS];
+} decRefPicMarking_t;
+
+/* structure to store slice header data decoded from the stream */
+typedef struct
+{
+ u32 firstMbInSlice;
+ u32 sliceType;
+ u32 picParameterSetId;
+ u32 frameNum;
+ u32 idrPicId;
+ u32 picOrderCntLsb;
+ i32 deltaPicOrderCntBottom;
+ i32 deltaPicOrderCnt[2];
+ u32 redundantPicCnt;
+ u32 numRefIdxActiveOverrideFlag;
+ u32 numRefIdxL0Active;
+ i32 sliceQpDelta;
+ u32 disableDeblockingFilterIdc;
+ i32 sliceAlphaC0Offset;
+ i32 sliceBetaOffset;
+ u32 sliceGroupChangeCycle;
+ refPicListReordering_t refPicListReordering;
+ decRefPicMarking_t decRefPicMarking;
+} sliceHeader_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeSliceHeader(strmData_t *pStrmData,
+ sliceHeader_t *pSliceHeader,
+ seqParamSet_t *pSeqParamSet,
+ picParamSet_t *pPicParamSet,
+ nalUnit_t *pNalUnit);
+
+u32 h264bsdCheckPpsId(strmData_t *pStrmData, u32 *ppsId);
+
+u32 h264bsdCheckFrameNum(
+ strmData_t *pStrmData,
+ u32 maxFrameNum,
+ u32 *frameNum);
+
+u32 h264bsdCheckIdrPicId(
+ strmData_t *pStrmData,
+ u32 maxFrameNum,
+ nalUnitType_e nalUnitType,
+ u32 *idrPicId);
+
+u32 h264bsdCheckPicOrderCntLsb(
+ strmData_t *pStrmData,
+ seqParamSet_t *pSeqParamSet,
+ nalUnitType_e nalUnitType,
+ u32 *picOrderCntLsb);
+
+u32 h264bsdCheckDeltaPicOrderCntBottom(
+ strmData_t *pStrmData,
+ seqParamSet_t *pSeqParamSet,
+ nalUnitType_e nalUnitType,
+ i32 *deltaPicOrderCntBottom);
+
+u32 h264bsdCheckDeltaPicOrderCnt(
+ strmData_t *pStrmData,
+ seqParamSet_t *pSeqParamSet,
+ nalUnitType_e nalUnitType,
+ u32 picOrderPresentFlag,
+ i32 *deltaPicOrderCnt);
+
+u32 h264bsdCheckRedundantPicCnt(
+ strmData_t *pStrmData,
+ seqParamSet_t *pSeqParamSet,
+ picParamSet_t *pPicParamSet,
+ nalUnitType_e nalUnitType,
+ u32 *redundantPicCnt);
+
+u32 h264bsdCheckPriorPicsFlag(u32 * noOutputOfPriorPicsFlag,
+ const strmData_t * pStrmData,
+ const seqParamSet_t * pSeqParamSet,
+ const picParamSet_t * pPicParamSet,
+ nalUnitType_e nalUnitType);
+
+#endif /* #ifdef H264SWDEC_SLICE_HEADER_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c
new file mode 100755
index 0000000..3234754
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.c
@@ -0,0 +1,888 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdInitStorage
+ h264bsdStoreSeqParamSet
+ h264bsdStorePicParamSet
+ h264bsdActivateParamSets
+ h264bsdResetStorage
+ h264bsdIsStartOfPicture
+ h264bsdIsEndOfPicture
+ h264bsdComputeSliceGroupMap
+ h264bsdCheckAccessUnitBoundary
+ CheckPps
+ h264bsdValidParamSets
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_storage.h"
+#include "h264bsd_util.h"
+#include "h264bsd_neighbour.h"
+#include "h264bsd_slice_group_map.h"
+#include "h264bsd_dpb.h"
+#include "h264bsd_nal_unit.h"
+#include "h264bsd_slice_header.h"
+#include "h264bsd_seq_param_set.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static u32 CheckPps(picParamSet_t *pps, seqParamSet_t *sps);
+
+/*------------------------------------------------------------------------------
+
+ Function name: h264bsdInitStorage
+
+ Functional description:
+ Initialize storage structure. Sets contents of the storage to '0'
+ except for the active parameter set ids, which are initialized
+ to invalid values.
+
+ Inputs:
+
+ Outputs:
+ pStorage initialized data stored here
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void h264bsdInitStorage(storage_t *pStorage)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(pStorage);
+
+ H264SwDecMemset(pStorage, 0, sizeof(storage_t));
+
+ pStorage->activeSpsId = MAX_NUM_SEQ_PARAM_SETS;
+ pStorage->activePpsId = MAX_NUM_PIC_PARAM_SETS;
+
+ pStorage->aub->firstCallFlag = HANTRO_TRUE;
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdStoreSeqParamSet
+
+ Functional description:
+ Store sequence parameter set into the storage. If active SPS is
+ overwritten -> check if contents changes and if it does, set
+ parameters to force reactivation of parameter sets
+
+ Inputs:
+ pStorage pointer to storage structure
+ pSeqParamSet pointer to param set to be stored
+
+ Outputs:
+ none
+
+ Returns:
+ HANTRO_OK success
+ MEMORY_ALLOCATION_ERROR failure in memory allocation
+
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdStoreSeqParamSet(storage_t *pStorage, seqParamSet_t *pSeqParamSet)
+{
+
+/* Variables */
+
+ u32 id;
+
+/* Code */
+
+ ASSERT(pStorage);
+ ASSERT(pSeqParamSet);
+ ASSERT(pSeqParamSet->seqParameterSetId < MAX_NUM_SEQ_PARAM_SETS);
+
+ id = pSeqParamSet->seqParameterSetId;
+
+ /* seq parameter set with id not used before -> allocate memory */
+ if (pStorage->sps[id] == NULL)
+ {
+ ALLOCATE(pStorage->sps[id], 1, seqParamSet_t);
+ if (pStorage->sps[id] == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+ }
+ /* sequence parameter set with id equal to id of active sps */
+ else if (id == pStorage->activeSpsId)
+ {
+ /* if seq parameter set contents changes
+ * -> overwrite and re-activate when next IDR picture decoded
+ * ids of active param sets set to invalid values to force
+ * re-activation. Memories allocated for old sps freed
+ * otherwise free memeries allocated for just decoded sps and
+ * continue */
+ if (h264bsdCompareSeqParamSets(pSeqParamSet, pStorage->activeSps) != 0)
+ {
+ FREE(pStorage->sps[id]->offsetForRefFrame);
+ FREE(pStorage->sps[id]->vuiParameters);
+ pStorage->activeSpsId = MAX_NUM_SEQ_PARAM_SETS + 1;
+ pStorage->activePpsId = MAX_NUM_PIC_PARAM_SETS + 1;
+ pStorage->activeSps = NULL;
+ pStorage->activePps = NULL;
+ }
+ else
+ {
+ FREE(pSeqParamSet->offsetForRefFrame);
+ FREE(pSeqParamSet->vuiParameters);
+ return(HANTRO_OK);
+ }
+ }
+ /* overwrite seq param set other than active one -> free memories
+ * allocated for old param set */
+ else
+ {
+ FREE(pStorage->sps[id]->offsetForRefFrame);
+ FREE(pStorage->sps[id]->vuiParameters);
+ }
+
+ *pStorage->sps[id] = *pSeqParamSet;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdStorePicParamSet
+
+ Functional description:
+ Store picture parameter set into the storage. If active PPS is
+ overwritten -> check if active SPS changes and if it does -> set
+ parameters to force reactivation of parameter sets
+
+ Inputs:
+ pStorage pointer to storage structure
+ pPicParamSet pointer to param set to be stored
+
+ Outputs:
+ none
+
+ Returns:
+ HANTRO_OK success
+ MEMORY_ALLOCATION_ERROR failure in memory allocation
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdStorePicParamSet(storage_t *pStorage, picParamSet_t *pPicParamSet)
+{
+
+/* Variables */
+
+ u32 id;
+
+/* Code */
+
+ ASSERT(pStorage);
+ ASSERT(pPicParamSet);
+ ASSERT(pPicParamSet->picParameterSetId < MAX_NUM_PIC_PARAM_SETS);
+ ASSERT(pPicParamSet->seqParameterSetId < MAX_NUM_SEQ_PARAM_SETS);
+
+ id = pPicParamSet->picParameterSetId;
+
+ /* pic parameter set with id not used before -> allocate memory */
+ if (pStorage->pps[id] == NULL)
+ {
+ ALLOCATE(pStorage->pps[id], 1, picParamSet_t);
+ if (pStorage->pps[id] == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+ }
+ /* picture parameter set with id equal to id of active pps */
+ else if (id == pStorage->activePpsId)
+ {
+ /* check whether seq param set changes, force re-activation of
+ * param set if it does. Set activeSpsId to invalid value to
+ * accomplish this */
+ if (pPicParamSet->seqParameterSetId != pStorage->activeSpsId)
+ {
+ pStorage->activePpsId = MAX_NUM_PIC_PARAM_SETS + 1;
+ }
+ /* free memories allocated for old param set */
+ FREE(pStorage->pps[id]->runLength);
+ FREE(pStorage->pps[id]->topLeft);
+ FREE(pStorage->pps[id]->bottomRight);
+ FREE(pStorage->pps[id]->sliceGroupId);
+ }
+ /* overwrite pic param set other than active one -> free memories
+ * allocated for old param set */
+ else
+ {
+ FREE(pStorage->pps[id]->runLength);
+ FREE(pStorage->pps[id]->topLeft);
+ FREE(pStorage->pps[id]->bottomRight);
+ FREE(pStorage->pps[id]->sliceGroupId);
+ }
+
+ *pStorage->pps[id] = *pPicParamSet;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdActivateParamSets
+
+ Functional description:
+ Activate certain SPS/PPS combination. This function shall be
+ called in the beginning of each picture. Picture parameter set
+ can be changed as wanted, but sequence parameter set may only be
+ changed when the starting picture is an IDR picture.
+
+ When new SPS is activated the function allocates memory for
+ macroblock storages and slice group map and (re-)initializes the
+ decoded picture buffer. If this is not the first activation the old
+ allocations are freed and FreeDpb called before new allocations.
+
+ Inputs:
+ pStorage pointer to storage data structure
+ ppsId identifies the PPS to be activated, SPS id obtained
+ from the PPS
+ isIdr flag to indicate if the picture is an IDR picture
+
+ Outputs:
+ none
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK non-existing or invalid param set combination,
+ trying to change SPS with non-IDR picture
+ MEMORY_ALLOCATION_ERROR failure in memory allocation
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdActivateParamSets(storage_t *pStorage, u32 ppsId, u32 isIdr)
+{
+
+/* Variables */
+
+ u32 tmp;
+ u32 flag;
+
+/* Code */
+
+ ASSERT(pStorage);
+ ASSERT(ppsId < MAX_NUM_PIC_PARAM_SETS);
+
+ /* check that pps and corresponding sps exist */
+ if ( (pStorage->pps[ppsId] == NULL) ||
+ (pStorage->sps[pStorage->pps[ppsId]->seqParameterSetId] == NULL) )
+ {
+ return(HANTRO_NOK);
+ }
+
+ /* check that pps parameters do not violate picture size constraints */
+ tmp = CheckPps(pStorage->pps[ppsId],
+ pStorage->sps[pStorage->pps[ppsId]->seqParameterSetId]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* first activation part1 */
+ if (pStorage->activePpsId == MAX_NUM_PIC_PARAM_SETS)
+ {
+ pStorage->activePpsId = ppsId;
+ pStorage->activePps = pStorage->pps[ppsId];
+ pStorage->activeSpsId = pStorage->activePps->seqParameterSetId;
+ pStorage->activeSps = pStorage->sps[pStorage->activeSpsId];
+ pStorage->picSizeInMbs =
+ pStorage->activeSps->picWidthInMbs *
+ pStorage->activeSps->picHeightInMbs;
+
+ pStorage->currImage->width = pStorage->activeSps->picWidthInMbs;
+ pStorage->currImage->height = pStorage->activeSps->picHeightInMbs;
+
+ pStorage->pendingActivation = HANTRO_TRUE;
+ }
+ /* first activation part2 */
+ else if (pStorage->pendingActivation)
+ {
+ pStorage->pendingActivation = HANTRO_FALSE;
+
+ FREE(pStorage->mb);
+ FREE(pStorage->sliceGroupMap);
+
+ ALLOCATE(pStorage->mb, pStorage->picSizeInMbs, mbStorage_t);
+ ALLOCATE(pStorage->sliceGroupMap, pStorage->picSizeInMbs, u32);
+ if (pStorage->mb == NULL || pStorage->sliceGroupMap == NULL)
+ return(MEMORY_ALLOCATION_ERROR);
+
+ H264SwDecMemset(pStorage->mb, 0,
+ pStorage->picSizeInMbs * sizeof(mbStorage_t));
+
+ h264bsdInitMbNeighbours(pStorage->mb,
+ pStorage->activeSps->picWidthInMbs,
+ pStorage->picSizeInMbs);
+
+ /* dpb output reordering disabled if
+ * 1) application set noReordering flag
+ * 2) POC type equal to 2
+ * 3) num_reorder_frames in vui equal to 0 */
+ if ( pStorage->noReordering ||
+ pStorage->activeSps->picOrderCntType == 2 ||
+ (pStorage->activeSps->vuiParametersPresentFlag &&
+ pStorage->activeSps->vuiParameters->bitstreamRestrictionFlag &&
+ !pStorage->activeSps->vuiParameters->numReorderFrames) )
+ flag = HANTRO_TRUE;
+ else
+ flag = HANTRO_FALSE;
+
+ tmp = h264bsdResetDpb(pStorage->dpb,
+ pStorage->activeSps->picWidthInMbs *
+ pStorage->activeSps->picHeightInMbs,
+ pStorage->activeSps->maxDpbSize,
+ pStorage->activeSps->numRefFrames,
+ pStorage->activeSps->maxFrameNum,
+ flag);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+ else if (ppsId != pStorage->activePpsId)
+ {
+ /* sequence parameter set shall not change but before an IDR picture */
+ if (pStorage->pps[ppsId]->seqParameterSetId != pStorage->activeSpsId)
+ {
+ DEBUG(("SEQ PARAM SET CHANGING...\n"));
+ if (isIdr)
+ {
+ pStorage->activePpsId = ppsId;
+ pStorage->activePps = pStorage->pps[ppsId];
+ pStorage->activeSpsId = pStorage->activePps->seqParameterSetId;
+ pStorage->activeSps = pStorage->sps[pStorage->activeSpsId];
+ pStorage->picSizeInMbs =
+ pStorage->activeSps->picWidthInMbs *
+ pStorage->activeSps->picHeightInMbs;
+
+ pStorage->currImage->width = pStorage->activeSps->picWidthInMbs;
+ pStorage->currImage->height =
+ pStorage->activeSps->picHeightInMbs;
+
+ pStorage->pendingActivation = HANTRO_TRUE;
+ }
+ else
+ {
+ DEBUG(("TRYING TO CHANGE SPS IN NON-IDR SLICE\n"));
+ return(HANTRO_NOK);
+ }
+ }
+ else
+ {
+ pStorage->activePpsId = ppsId;
+ pStorage->activePps = pStorage->pps[ppsId];
+ }
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdResetStorage
+
+ Functional description:
+ Reset contents of the storage. This should be called before
+ processing of new image is started.
+
+ Inputs:
+ pStorage pointer to storage structure
+
+ Outputs:
+ none
+
+ Returns:
+ none
+
+
+------------------------------------------------------------------------------*/
+
+void h264bsdResetStorage(storage_t *pStorage)
+{
+
+/* Variables */
+
+ u32 i;
+
+/* Code */
+
+ ASSERT(pStorage);
+
+ pStorage->slice->numDecodedMbs = 0;
+ pStorage->slice->sliceId = 0;
+
+ for (i = 0; i < pStorage->picSizeInMbs; i++)
+ {
+ pStorage->mb[i].sliceId = 0;
+ pStorage->mb[i].decoded = 0;
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdIsStartOfPicture
+
+ Functional description:
+ Determine if the decoder is in the start of a picture. This
+ information is needed to decide if h264bsdActivateParamSets and
+ h264bsdCheckGapsInFrameNum functions should be called. Function
+ considers that new picture is starting if no slice headers
+ have been successfully decoded for the current access unit.
+
+ Inputs:
+ pStorage pointer to storage structure
+
+ Outputs:
+ none
+
+ Returns:
+ HANTRO_TRUE new picture is starting
+ HANTRO_FALSE not starting
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdIsStartOfPicture(storage_t *pStorage)
+{
+
+/* Variables */
+
+
+/* Code */
+
+ if (pStorage->validSliceInAccessUnit == HANTRO_FALSE)
+ return(HANTRO_TRUE);
+ else
+ return(HANTRO_FALSE);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdIsEndOfPicture
+
+ Functional description:
+ Determine if the decoder is in the end of a picture. This
+ information is needed to determine when deblocking filtering
+ and reference picture marking processes should be performed.
+
+ If the decoder is processing primary slices the return value
+ is determined by checking the value of numDecodedMbs in the
+ storage. On the other hand, if the decoder is processing
+ redundant slices the numDecodedMbs may not contain valid
+ informationa and each macroblock has to be checked separately.
+
+ Inputs:
+ pStorage pointer to storage structure
+
+ Outputs:
+ none
+
+ Returns:
+ HANTRO_TRUE end of picture
+ HANTRO_FALSE noup
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdIsEndOfPicture(storage_t *pStorage)
+{
+
+/* Variables */
+
+ u32 i, tmp;
+
+/* Code */
+
+ /* primary picture */
+ if (!pStorage->sliceHeader[0].redundantPicCnt)
+ {
+ if (pStorage->slice->numDecodedMbs == pStorage->picSizeInMbs)
+ return(HANTRO_TRUE);
+ }
+ else
+ {
+ for (i = 0, tmp = 0; i < pStorage->picSizeInMbs; i++)
+ tmp += pStorage->mb[i].decoded ? 1 : 0;
+
+ if (tmp == pStorage->picSizeInMbs)
+ return(HANTRO_TRUE);
+ }
+
+ return(HANTRO_FALSE);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdComputeSliceGroupMap
+
+ Functional description:
+ Compute slice group map. Just call h264bsdDecodeSliceGroupMap with
+ appropriate parameters.
+
+ Inputs:
+ pStorage pointer to storage structure
+ sliceGroupChangeCycle
+
+ Outputs:
+ none
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+
+void h264bsdComputeSliceGroupMap(storage_t *pStorage, u32 sliceGroupChangeCycle)
+{
+
+/* Variables */
+
+
+/* Code */
+
+ h264bsdDecodeSliceGroupMap(pStorage->sliceGroupMap,
+ pStorage->activePps, sliceGroupChangeCycle,
+ pStorage->activeSps->picWidthInMbs,
+ pStorage->activeSps->picHeightInMbs);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdCheckAccessUnitBoundary
+
+ Functional description:
+ Check if next NAL unit starts a new access unit. Following
+ conditions specify start of a new access unit:
+
+ -NAL unit types 6-11, 13-18 (e.g. SPS, PPS)
+
+ following conditions checked only for slice NAL units, values
+ compared to ones obtained from previous slice:
+
+ -NAL unit type differs (slice / IDR slice)
+ -frame_num differs
+ -nal_ref_idc differs and one of the values is 0
+ -POC information differs
+ -both are IDR slices and idr_pic_id differs
+
+ Inputs:
+ strm pointer to stream data structure
+ nuNext pointer to NAL unit structure
+ storage pointer to storage structure
+
+ Outputs:
+ accessUnitBoundaryFlag the result is stored here, TRUE for
+ access unit boundary, FALSE otherwise
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK failure, invalid stream data
+ PARAM_SET_ERROR invalid param set usage
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdCheckAccessUnitBoundary(
+ strmData_t *strm,
+ nalUnit_t *nuNext,
+ storage_t *storage,
+ u32 *accessUnitBoundaryFlag)
+{
+
+/* Variables */
+
+ u32 tmp, ppsId, frameNum, idrPicId, picOrderCntLsb;
+ i32 deltaPicOrderCntBottom, deltaPicOrderCnt[2];
+ seqParamSet_t *sps;
+ picParamSet_t *pps;
+
+/* Code */
+
+ ASSERT(strm);
+ ASSERT(nuNext);
+ ASSERT(storage);
+ ASSERT(storage->sps);
+ ASSERT(storage->pps);
+
+ /* initialize default output to FALSE */
+ *accessUnitBoundaryFlag = HANTRO_FALSE;
+
+ if ( ( (nuNext->nalUnitType > 5) && (nuNext->nalUnitType < 12) ) ||
+ ( (nuNext->nalUnitType > 12) && (nuNext->nalUnitType <= 18) ) )
+ {
+ *accessUnitBoundaryFlag = HANTRO_TRUE;
+ return(HANTRO_OK);
+ }
+ else if ( nuNext->nalUnitType != NAL_CODED_SLICE &&
+ nuNext->nalUnitType != NAL_CODED_SLICE_IDR )
+ {
+ return(HANTRO_OK);
+ }
+
+ /* check if this is the very first call to this function */
+ if (storage->aub->firstCallFlag)
+ {
+ *accessUnitBoundaryFlag = HANTRO_TRUE;
+ storage->aub->firstCallFlag = HANTRO_FALSE;
+ }
+
+ /* get picture parameter set id */
+ tmp = h264bsdCheckPpsId(strm, &ppsId);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ /* store sps and pps in separate pointers just to make names shorter */
+ pps = storage->pps[ppsId];
+ if ( pps == NULL || storage->sps[pps->seqParameterSetId] == NULL ||
+ (storage->activeSpsId != MAX_NUM_SEQ_PARAM_SETS &&
+ pps->seqParameterSetId != storage->activeSpsId &&
+ nuNext->nalUnitType != NAL_CODED_SLICE_IDR) )
+ return(PARAM_SET_ERROR);
+ sps = storage->sps[pps->seqParameterSetId];
+
+ if (storage->aub->nuPrev->nalRefIdc != nuNext->nalRefIdc &&
+ (storage->aub->nuPrev->nalRefIdc == 0 || nuNext->nalRefIdc == 0))
+ *accessUnitBoundaryFlag = HANTRO_TRUE;
+
+ if ((storage->aub->nuPrev->nalUnitType == NAL_CODED_SLICE_IDR &&
+ nuNext->nalUnitType != NAL_CODED_SLICE_IDR) ||
+ (storage->aub->nuPrev->nalUnitType != NAL_CODED_SLICE_IDR &&
+ nuNext->nalUnitType == NAL_CODED_SLICE_IDR))
+ *accessUnitBoundaryFlag = HANTRO_TRUE;
+
+ tmp = h264bsdCheckFrameNum(strm, sps->maxFrameNum, &frameNum);
+ if (tmp != HANTRO_OK)
+ return(HANTRO_NOK);
+
+ if (storage->aub->prevFrameNum != frameNum)
+ {
+ storage->aub->prevFrameNum = frameNum;
+ *accessUnitBoundaryFlag = HANTRO_TRUE;
+ }
+
+ if (nuNext->nalUnitType == NAL_CODED_SLICE_IDR)
+ {
+ tmp = h264bsdCheckIdrPicId(strm, sps->maxFrameNum, nuNext->nalUnitType,
+ &idrPicId);
+ if (tmp != HANTRO_OK)
+ return(HANTRO_NOK);
+
+ if (storage->aub->nuPrev->nalUnitType == NAL_CODED_SLICE_IDR &&
+ storage->aub->prevIdrPicId != idrPicId)
+ *accessUnitBoundaryFlag = HANTRO_TRUE;
+
+ storage->aub->prevIdrPicId = idrPicId;
+ }
+
+ if (sps->picOrderCntType == 0)
+ {
+ tmp = h264bsdCheckPicOrderCntLsb(strm, sps, nuNext->nalUnitType,
+ &picOrderCntLsb);
+ if (tmp != HANTRO_OK)
+ return(HANTRO_NOK);
+
+ if (storage->aub->prevPicOrderCntLsb != picOrderCntLsb)
+ {
+ storage->aub->prevPicOrderCntLsb = picOrderCntLsb;
+ *accessUnitBoundaryFlag = HANTRO_TRUE;
+ }
+
+ if (pps->picOrderPresentFlag)
+ {
+ tmp = h264bsdCheckDeltaPicOrderCntBottom(strm, sps,
+ nuNext->nalUnitType, &deltaPicOrderCntBottom);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ if (storage->aub->prevDeltaPicOrderCntBottom !=
+ deltaPicOrderCntBottom)
+ {
+ storage->aub->prevDeltaPicOrderCntBottom =
+ deltaPicOrderCntBottom;
+ *accessUnitBoundaryFlag = HANTRO_TRUE;
+ }
+ }
+ }
+ else if (sps->picOrderCntType == 1 && !sps->deltaPicOrderAlwaysZeroFlag)
+ {
+ tmp = h264bsdCheckDeltaPicOrderCnt(strm, sps, nuNext->nalUnitType,
+ pps->picOrderPresentFlag, deltaPicOrderCnt);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ if (storage->aub->prevDeltaPicOrderCnt[0] != deltaPicOrderCnt[0])
+ {
+ storage->aub->prevDeltaPicOrderCnt[0] = deltaPicOrderCnt[0];
+ *accessUnitBoundaryFlag = HANTRO_TRUE;
+ }
+
+ if (pps->picOrderPresentFlag)
+ if (storage->aub->prevDeltaPicOrderCnt[1] != deltaPicOrderCnt[1])
+ {
+ storage->aub->prevDeltaPicOrderCnt[1] = deltaPicOrderCnt[1];
+ *accessUnitBoundaryFlag = HANTRO_TRUE;
+ }
+ }
+
+ *storage->aub->nuPrev = *nuNext;
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: CheckPps
+
+ Functional description:
+ Check picture parameter set. Contents of the picture parameter
+ set information that depends on the image dimensions is checked
+ against the dimensions in the sps.
+
+ Inputs:
+ pps pointer to picture paramter set
+ sps pointer to sequence parameter set
+
+ Outputs:
+ none
+
+ Returns:
+ HANTRO_OK everything ok
+ HANTRO_NOK invalid data in picture parameter set
+
+------------------------------------------------------------------------------*/
+u32 CheckPps(picParamSet_t *pps, seqParamSet_t *sps)
+{
+
+ u32 i;
+ u32 picSize;
+
+ picSize = sps->picWidthInMbs * sps->picHeightInMbs;
+
+ /* check slice group params */
+ if (pps->numSliceGroups > 1)
+ {
+ if (pps->sliceGroupMapType == 0)
+ {
+ ASSERT(pps->runLength);
+ for (i = 0; i < pps->numSliceGroups; i++)
+ {
+ if (pps->runLength[i] > picSize)
+ return(HANTRO_NOK);
+ }
+ }
+ else if (pps->sliceGroupMapType == 2)
+ {
+ ASSERT(pps->topLeft);
+ ASSERT(pps->bottomRight);
+ for (i = 0; i < pps->numSliceGroups-1; i++)
+ {
+ if (pps->topLeft[i] > pps->bottomRight[i] ||
+ pps->bottomRight[i] >= picSize)
+ return(HANTRO_NOK);
+
+ if ( (pps->topLeft[i] % sps->picWidthInMbs) >
+ (pps->bottomRight[i] % sps->picWidthInMbs) )
+ return(HANTRO_NOK);
+ }
+ }
+ else if (pps->sliceGroupMapType > 2 && pps->sliceGroupMapType < 6)
+ {
+ if (pps->sliceGroupChangeRate > picSize)
+ return(HANTRO_NOK);
+ }
+ else if (pps->sliceGroupMapType == 6 &&
+ pps->picSizeInMapUnits < picSize)
+ return(HANTRO_NOK);
+ }
+
+ return(HANTRO_OK);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdValidParamSets
+
+ Functional description:
+ Check if any valid SPS/PPS combination exists in the storage.
+ Function tries each PPS in the buffer and checks if corresponding
+ SPS exists and calls CheckPps to determine if the PPS conforms
+ to image dimensions of the SPS.
+
+ Inputs:
+ pStorage pointer to storage structure
+
+ Outputs:
+ HANTRO_OK there is at least one valid combination
+ HANTRO_NOK no valid combinations found
+
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdValidParamSets(storage_t *pStorage)
+{
+
+/* Variables */
+
+ u32 i;
+
+/* Code */
+
+ ASSERT(pStorage);
+
+ for (i = 0; i < MAX_NUM_PIC_PARAM_SETS; i++)
+ {
+ if ( pStorage->pps[i] &&
+ pStorage->sps[pStorage->pps[i]->seqParameterSetId] &&
+ CheckPps(pStorage->pps[i],
+ pStorage->sps[pStorage->pps[i]->seqParameterSetId]) ==
+ HANTRO_OK)
+ {
+ return(HANTRO_OK);
+ }
+ }
+
+ return(HANTRO_NOK);
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.h
new file mode 100755
index 0000000..ba3b2da
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_storage.h
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_STORAGE_H
+#define H264SWDEC_STORAGE_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_cfg.h"
+#include "h264bsd_seq_param_set.h"
+#include "h264bsd_pic_param_set.h"
+#include "h264bsd_macroblock_layer.h"
+#include "h264bsd_nal_unit.h"
+#include "h264bsd_slice_header.h"
+#include "h264bsd_seq_param_set.h"
+#include "h264bsd_dpb.h"
+#include "h264bsd_pic_order_cnt.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+typedef struct
+{
+ u32 sliceId;
+ u32 numDecodedMbs;
+ u32 lastMbAddr;
+} sliceStorage_t;
+
+/* structure to store parameters needed for access unit boundary checking */
+typedef struct
+{
+ nalUnit_t nuPrev[1];
+ u32 prevFrameNum;
+ u32 prevIdrPicId;
+ u32 prevPicOrderCntLsb;
+ i32 prevDeltaPicOrderCntBottom;
+ i32 prevDeltaPicOrderCnt[2];
+ u32 firstCallFlag;
+} aubCheck_t;
+
+/* storage data structure, holds all data of a decoder instance */
+typedef struct
+{
+ /* active paramet set ids and pointers */
+ u32 oldSpsId;
+ u32 activePpsId;
+ u32 activeSpsId;
+ picParamSet_t *activePps;
+ seqParamSet_t *activeSps;
+ seqParamSet_t *sps[MAX_NUM_SEQ_PARAM_SETS];
+ picParamSet_t *pps[MAX_NUM_PIC_PARAM_SETS];
+
+ /* current slice group map, recomputed for each slice */
+ u32 *sliceGroupMap;
+
+ u32 picSizeInMbs;
+
+ /* this flag is set after all macroblocks of a picture successfully
+ * decoded -> redundant slices not decoded */
+ u32 skipRedundantSlices;
+ u32 picStarted;
+
+ /* flag to indicate if current access unit contains any valid slices */
+ u32 validSliceInAccessUnit;
+
+ /* store information needed for handling of slice decoding */
+ sliceStorage_t slice[1];
+
+ /* number of concealed macroblocks in the current image */
+ u32 numConcealedMbs;
+
+ /* picId given by application */
+ u32 currentPicId;
+
+ /* macroblock specific storages, size determined by image dimensions */
+ mbStorage_t *mb;
+
+ /* flag to store noOutputReordering flag set by the application */
+ u32 noReordering;
+
+ /* DPB */
+ dpbStorage_t dpb[1];
+
+ /* structure to store picture order count related information */
+ pocStorage_t poc[1];
+
+ /* access unit boundary checking related data */
+ aubCheck_t aub[1];
+
+ /* current processed image */
+ image_t currImage[1];
+
+ /* last valid NAL unit header is stored here */
+ nalUnit_t prevNalUnit[1];
+
+ /* slice header, second structure used as a temporary storage while
+ * decoding slice header, first one stores last successfully decoded
+ * slice header */
+ sliceHeader_t sliceHeader[2];
+
+ /* fields to store old stream buffer pointers, needed when only part of
+ * a stream buffer is processed by h264bsdDecode function */
+ u32 prevBufNotFinished;
+ u8 *prevBufPointer;
+ u32 prevBytesConsumed;
+ strmData_t strm[1];
+
+ /* macroblock layer structure, there is no need to store this but it
+ * would have increased the stack size excessively and needed to be
+ * allocated from head -> easiest to put it here */
+ macroblockLayer_t *mbLayer;
+
+ u32 pendingActivation; /* Activate parameter sets after returning
+ HEADERS_RDY to the user */
+ u32 intraConcealmentFlag; /* 0 gray picture for corrupted intra
+ 1 previous frame used if available */
+} storage_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+void h264bsdInitStorage(storage_t *pStorage);
+void h264bsdResetStorage(storage_t *pStorage);
+u32 h264bsdIsStartOfPicture(storage_t *pStorage);
+u32 h264bsdIsEndOfPicture(storage_t *pStorage);
+u32 h264bsdStoreSeqParamSet(storage_t *pStorage, seqParamSet_t *pSeqParamSet);
+u32 h264bsdStorePicParamSet(storage_t *pStorage, picParamSet_t *pPicParamSet);
+u32 h264bsdActivateParamSets(storage_t *pStorage, u32 ppsId, u32 isIdr);
+void h264bsdComputeSliceGroupMap(storage_t *pStorage,
+ u32 sliceGroupChangeCycle);
+
+u32 h264bsdCheckAccessUnitBoundary(
+ strmData_t *strm,
+ nalUnit_t *nuNext,
+ storage_t *storage,
+ u32 *accessUnitBoundaryFlag);
+
+u32 h264bsdValidParamSets(storage_t *pStorage);
+
+#endif /* #ifdef H264SWDEC_STORAGE_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.c
new file mode 100755
index 0000000..20d1083
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.c
@@ -0,0 +1,242 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdGetBits
+ h264bsdShowBits32
+ h264bsdFlushBits
+ h264bsdIsByteAligned
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_util.h"
+#include "h264bsd_stream.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdGetBits
+
+ Functional description:
+ Read and remove bits from the stream buffer.
+
+ Input:
+ pStrmData pointer to stream data structure
+ numBits number of bits to read
+
+ Output:
+ none
+
+ Returns:
+ bits read from stream
+ END_OF_STREAM if not enough bits left
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdGetBits(strmData_t *pStrmData, u32 numBits)
+{
+
+ u32 out;
+
+ ASSERT(pStrmData);
+ ASSERT(numBits < 32);
+
+ out = h264bsdShowBits32(pStrmData) >> (32 - numBits);
+
+ if (h264bsdFlushBits(pStrmData, numBits) == HANTRO_OK)
+ {
+ return(out);
+ }
+ else
+ {
+ return(END_OF_STREAM);
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdShowBits32
+
+ Functional description:
+ Read 32 bits from the stream buffer. Buffer is left as it is, i.e.
+ no bits are removed. First bit read from the stream is the MSB of
+ the return value. If there is not enough bits in the buffer ->
+ bits beyong the end of the stream are set to '0' in the return
+ value.
+
+ Input:
+ pStrmData pointer to stream data structure
+
+ Output:
+ none
+
+ Returns:
+ bits read from stream
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdShowBits32(strmData_t *pStrmData)
+{
+
+ i32 bits, shift;
+ u32 out;
+ u8 *pStrm;
+
+ ASSERT(pStrmData);
+ ASSERT(pStrmData->pStrmCurrPos);
+ ASSERT(pStrmData->bitPosInWord < 8);
+ ASSERT(pStrmData->bitPosInWord ==
+ (pStrmData->strmBuffReadBits & 0x7));
+
+ pStrm = pStrmData->pStrmCurrPos;
+
+ /* number of bits left in the buffer */
+ bits = (i32)pStrmData->strmBuffSize*8 - (i32)pStrmData->strmBuffReadBits;
+
+ /* at least 32-bits in the buffer */
+ if (bits >= 32)
+ {
+ u32 bitPosInWord = pStrmData->bitPosInWord;
+ out = ((u32)pStrm[0] << 24) | ((u32)pStrm[1] << 16) |
+ ((u32)pStrm[2] << 8) | ((u32)pStrm[3]);
+
+ if (bitPosInWord)
+ {
+ u32 byte = (u32)pStrm[4];
+ u32 tmp = (8-bitPosInWord);
+ out <<= bitPosInWord;
+ out |= byte>>tmp;
+ }
+ return (out);
+ }
+ /* at least one bit in the buffer */
+ else if (bits > 0)
+ {
+ shift = (i32)(24 + pStrmData->bitPosInWord);
+ out = (u32)(*pStrm++) << shift;
+ bits -= (i32)(8 - pStrmData->bitPosInWord);
+ while (bits > 0)
+ {
+ shift -= 8;
+ out |= (u32)(*pStrm++) << shift;
+ bits -= 8;
+ }
+ return (out);
+ }
+ else
+ return (0);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdFlushBits
+
+ Functional description:
+ Remove bits from the stream buffer
+
+ Input:
+ pStrmData pointer to stream data structure
+ numBits number of bits to remove
+
+ Output:
+ none
+
+ Returns:
+ HANTRO_OK success
+ END_OF_STREAM not enough bits left
+
+------------------------------------------------------------------------------*/
+#ifndef H264DEC_NEON
+u32 h264bsdFlushBits(strmData_t *pStrmData, u32 numBits)
+{
+
+ ASSERT(pStrmData);
+ ASSERT(pStrmData->pStrmBuffStart);
+ ASSERT(pStrmData->pStrmCurrPos);
+ ASSERT(pStrmData->bitPosInWord < 8);
+ ASSERT(pStrmData->bitPosInWord == (pStrmData->strmBuffReadBits & 0x7));
+
+ pStrmData->strmBuffReadBits += numBits;
+ pStrmData->bitPosInWord = pStrmData->strmBuffReadBits & 0x7;
+ if ( (pStrmData->strmBuffReadBits ) <= (8*pStrmData->strmBuffSize) )
+ {
+ pStrmData->pStrmCurrPos = pStrmData->pStrmBuffStart +
+ (pStrmData->strmBuffReadBits >> 3);
+ return(HANTRO_OK);
+ }
+ else
+ return(END_OF_STREAM);
+
+}
+#endif
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdIsByteAligned
+
+ Functional description:
+ Check if current stream position is byte aligned.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+
+ Outputs:
+ none
+
+ Returns:
+ TRUE stream is byte aligned
+ FALSE stream is not byte aligned
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdIsByteAligned(strmData_t *pStrmData)
+{
+
+/* Variables */
+
+/* Code */
+
+ if (!pStrmData->bitPosInWord)
+ return(HANTRO_TRUE);
+ else
+ return(HANTRO_FALSE);
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.h
new file mode 100755
index 0000000..4404b66
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_stream.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_STREAM_H
+#define H264SWDEC_STREAM_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+typedef struct
+{
+ u8 *pStrmBuffStart; /* pointer to start of stream buffer */
+ u8 *pStrmCurrPos; /* current read address in stream buffer */
+ u32 bitPosInWord; /* bit position in stream buffer byte */
+ u32 strmBuffSize; /* size of stream buffer (bytes) */
+ u32 strmBuffReadBits; /* number of bits read from stream buffer */
+} strmData_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdGetBits(strmData_t *pStrmData, u32 numBits);
+
+u32 h264bsdShowBits32(strmData_t *pStrmData);
+
+u32 h264bsdFlushBits(strmData_t *pStrmData, u32 numBits);
+
+u32 h264bsdIsByteAligned(strmData_t *);
+
+#endif /* #ifdef H264SWDEC_STREAM_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.c
new file mode 100755
index 0000000..4eb6dd0
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.c
@@ -0,0 +1,402 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdProcessBlock
+ h264bsdProcessLumaDc
+ h264bsdProcessChromaDc
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_transform.h"
+#include "h264bsd_util.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/* Switch off the following Lint messages for this file:
+ * Info 701: Shift left of signed quantity (int)
+ * Info 702: Shift right of signed quantity (int)
+ */
+/*lint -e701 -e702 */
+
+/* LevelScale function */
+static const i32 levelScale[6][3] = {
+ {10,13,16}, {11,14,18}, {13,16,20}, {14,18,23}, {16,20,25}, {18,23,29}};
+
+/* qp % 6 as a function of qp */
+static const u8 qpMod6[52] = {0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,
+ 0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3};
+
+/* qp / 6 as a function of qp */
+static const u8 qpDiv6[52] = {0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,
+ 4,4,4,4,4,4,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7,8,8,8,8};
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdProcessBlock
+
+ Functional description:
+ Function performs inverse zig-zag scan, inverse scaling and
+ inverse transform for a luma or a chroma residual block
+
+ Inputs:
+ data pointer to data to be processed
+ qp quantization parameter
+ skip skip processing of data[0], set to non-zero value
+ if dc coeff hanled separately
+ coeffMap 16 lsb's indicate which coeffs are non-zero,
+ bit 0 (lsb) for coeff 0, bit 1 for coeff 1 etc.
+
+ Outputs:
+ data processed data
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK processed data not in valid range [-512, 511]
+
+------------------------------------------------------------------------------*/
+u32 h264bsdProcessBlock(i32 *data, u32 qp, u32 skip, u32 coeffMap)
+{
+
+/* Variables */
+
+ i32 tmp0, tmp1, tmp2, tmp3;
+ i32 d1, d2, d3;
+ u32 row,col;
+ u32 qpDiv;
+ i32 *ptr;
+
+/* Code */
+
+ qpDiv = qpDiv6[qp];
+ tmp1 = levelScale[qpMod6[qp]][0] << qpDiv;
+ tmp2 = levelScale[qpMod6[qp]][1] << qpDiv;
+ tmp3 = levelScale[qpMod6[qp]][2] << qpDiv;
+
+ if (!skip)
+ data[0] = (data[0] * tmp1);
+
+ /* at least one of the rows 1, 2 or 3 contain non-zero coeffs, mask takes
+ * the scanning order into account */
+ if (coeffMap & 0xFF9C)
+ {
+ /* do the zig-zag scan and inverse quantization */
+ d1 = data[1];
+ d2 = data[14];
+ d3 = data[15];
+ data[1] = (d1 * tmp2);
+ data[14] = (d2 * tmp2);
+ data[15] = (d3 * tmp3);
+
+ d1 = data[2];
+ d2 = data[5];
+ d3 = data[4];
+ data[4] = (d1 * tmp2);
+ data[2] = (d2 * tmp1);
+ data[5] = (d3 * tmp3);
+
+ d1 = data[8];
+ d2 = data[3];
+ d3 = data[6];
+ tmp0 = (d1 * tmp2);
+ data[8] = (d2 * tmp1);
+ data[3] = (d3 * tmp2);
+ d1 = data[7];
+ d2 = data[12];
+ d3 = data[9];
+ data[6] = (d1 * tmp2);
+ data[7] = (d2 * tmp3);
+ data[12] = (d3 * tmp2);
+ data[9] = tmp0;
+
+ d1 = data[10];
+ d2 = data[11];
+ d3 = data[13];
+ data[13] = (d1 * tmp3);
+ data[10] = (d2 * tmp1);
+ data[11] = (d3 * tmp2);
+
+ /* horizontal transform */
+ for (row = 4, ptr = data; row--; ptr += 4)
+ {
+ tmp0 = ptr[0] + ptr[2];
+ tmp1 = ptr[0] - ptr[2];
+ tmp2 = (ptr[1] >> 1) - ptr[3];
+ tmp3 = ptr[1] + (ptr[3] >> 1);
+ ptr[0] = tmp0 + tmp3;
+ ptr[1] = tmp1 + tmp2;
+ ptr[2] = tmp1 - tmp2;
+ ptr[3] = tmp0 - tmp3;
+ }
+
+ /*lint +e661 +e662*/
+ /* then vertical transform */
+ for (col = 4; col--; data++)
+ {
+ tmp0 = data[0] + data[8];
+ tmp1 = data[0] - data[8];
+ tmp2 = (data[4] >> 1) - data[12];
+ tmp3 = data[4] + (data[12] >> 1);
+ data[0 ] = (tmp0 + tmp3 + 32)>>6;
+ data[4 ] = (tmp1 + tmp2 + 32)>>6;
+ data[8 ] = (tmp1 - tmp2 + 32)>>6;
+ data[12] = (tmp0 - tmp3 + 32)>>6;
+ /* check that each value is in the range [-512,511] */
+ if (((u32)(data[0] + 512) > 1023) ||
+ ((u32)(data[4] + 512) > 1023) ||
+ ((u32)(data[8] + 512) > 1023) ||
+ ((u32)(data[12] + 512) > 1023) )
+ return(HANTRO_NOK);
+ }
+ }
+ else /* rows 1, 2 and 3 are zero */
+ {
+ /* only dc-coeff is non-zero, i.e. coeffs at original positions
+ * 1, 5 and 6 are zero */
+ if ((coeffMap & 0x62) == 0)
+ {
+ tmp0 = (data[0] + 32) >> 6;
+ /* check that value is in the range [-512,511] */
+ if ((u32)(tmp0 + 512) > 1023)
+ return(HANTRO_NOK);
+ data[0] = data[1] = data[2] = data[3] = data[4] = data[5] =
+ data[6] = data[7] = data[8] = data[9] = data[10] =
+ data[11] = data[12] = data[13] = data[14] = data[15] =
+ tmp0;
+ }
+ else /* at least one of the coeffs 1, 5 or 6 is non-zero */
+ {
+ data[1] = (data[1] * tmp2);
+ data[2] = (data[5] * tmp1);
+ data[3] = (data[6] * tmp2);
+ tmp0 = data[0] + data[2];
+ tmp1 = data[0] - data[2];
+ tmp2 = (data[1] >> 1) - data[3];
+ tmp3 = data[1] + (data[3] >> 1);
+ data[0] = (tmp0 + tmp3 + 32)>>6;
+ data[1] = (tmp1 + tmp2 + 32)>>6;
+ data[2] = (tmp1 - tmp2 + 32)>>6;
+ data[3] = (tmp0 - tmp3 + 32)>>6;
+ data[4] = data[8] = data[12] = data[0];
+ data[5] = data[9] = data[13] = data[1];
+ data[6] = data[10] = data[14] = data[2];
+ data[7] = data[11] = data[15] = data[3];
+ /* check that each value is in the range [-512,511] */
+ if (((u32)(data[0] + 512) > 1023) ||
+ ((u32)(data[1] + 512) > 1023) ||
+ ((u32)(data[2] + 512) > 1023) ||
+ ((u32)(data[3] + 512) > 1023) )
+ return(HANTRO_NOK);
+ }
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdProcessLumaDc
+
+ Functional description:
+ Function performs inverse zig-zag scan, inverse transform and
+ inverse scaling for a luma DC coefficients block
+
+ Inputs:
+ data pointer to data to be processed
+ qp quantization parameter
+
+ Outputs:
+ data processed data
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+void h264bsdProcessLumaDc(i32 *data, u32 qp)
+{
+
+/* Variables */
+
+ i32 tmp0, tmp1, tmp2, tmp3;
+ u32 row,col;
+ u32 qpMod, qpDiv;
+ i32 levScale;
+ i32 *ptr;
+
+/* Code */
+
+ qpMod = qpMod6[qp];
+ qpDiv = qpDiv6[qp];
+
+ /* zig-zag scan */
+ tmp0 = data[2];
+ data[2] = data[5];
+ data[5] = data[4];
+ data[4] = tmp0;
+
+ tmp0 = data[8];
+ data[8] = data[3];
+ data[3] = data[6];
+ data[6] = data[7];
+ data[7] = data[12];
+ data[12] = data[9];
+ data[9] = tmp0;
+
+ tmp0 = data[10];
+ data[10] = data[11];
+ data[11] = data[13];
+ data[13] = tmp0;
+
+ /* horizontal transform */
+ for (row = 4, ptr = data; row--; ptr += 4)
+ {
+ tmp0 = ptr[0] + ptr[2];
+ tmp1 = ptr[0] - ptr[2];
+ tmp2 = ptr[1] - ptr[3];
+ tmp3 = ptr[1] + ptr[3];
+ ptr[0] = tmp0 + tmp3;
+ ptr[1] = tmp1 + tmp2;
+ ptr[2] = tmp1 - tmp2;
+ ptr[3] = tmp0 - tmp3;
+ }
+
+ /*lint +e661 +e662*/
+ /* then vertical transform and inverse scaling */
+ levScale = levelScale[ qpMod ][0];
+ if (qp >= 12)
+ {
+ levScale <<= (qpDiv-2);
+ for (col = 4; col--; data++)
+ {
+ tmp0 = data[0] + data[8 ];
+ tmp1 = data[0] - data[8 ];
+ tmp2 = data[4] - data[12];
+ tmp3 = data[4] + data[12];
+ data[0 ] = ((tmp0 + tmp3)*levScale);
+ data[4 ] = ((tmp1 + tmp2)*levScale);
+ data[8 ] = ((tmp1 - tmp2)*levScale);
+ data[12] = ((tmp0 - tmp3)*levScale);
+ }
+ }
+ else
+ {
+ i32 tmp;
+ tmp = ((1 - qpDiv) == 0) ? 1 : 2;
+ for (col = 4; col--; data++)
+ {
+ tmp0 = data[0] + data[8 ];
+ tmp1 = data[0] - data[8 ];
+ tmp2 = data[4] - data[12];
+ tmp3 = data[4] + data[12];
+ data[0 ] = ((tmp0 + tmp3)*levScale+tmp) >> (2-qpDiv);
+ data[4 ] = ((tmp1 + tmp2)*levScale+tmp) >> (2-qpDiv);
+ data[8 ] = ((tmp1 - tmp2)*levScale+tmp) >> (2-qpDiv);
+ data[12] = ((tmp0 - tmp3)*levScale+tmp) >> (2-qpDiv);
+ }
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdProcessChromaDc
+
+ Functional description:
+ Function performs inverse transform and inverse scaling for a
+ chroma DC coefficients block
+
+ Inputs:
+ data pointer to data to be processed
+ qp quantization parameter
+
+ Outputs:
+ data processed data
+
+ Returns:
+ none
+
+------------------------------------------------------------------------------*/
+void h264bsdProcessChromaDc(i32 *data, u32 qp)
+{
+
+/* Variables */
+
+ i32 tmp0, tmp1, tmp2, tmp3;
+ u32 qpDiv;
+ i32 levScale;
+ u32 levShift;
+
+/* Code */
+
+ qpDiv = qpDiv6[qp];
+ levScale = levelScale[ qpMod6[qp] ][0];
+
+ if (qp >= 6)
+ {
+ levScale <<= (qpDiv-1);
+ levShift = 0;
+ }
+ else
+ {
+ levShift = 1;
+ }
+
+ tmp0 = data[0] + data[2];
+ tmp1 = data[0] - data[2];
+ tmp2 = data[1] - data[3];
+ tmp3 = data[1] + data[3];
+ data[0] = ((tmp0 + tmp3) * levScale) >> levShift;
+ data[1] = ((tmp0 - tmp3) * levScale) >> levShift;
+ data[2] = ((tmp1 + tmp2) * levScale) >> levShift;
+ data[3] = ((tmp1 - tmp2) * levScale) >> levShift;
+ tmp0 = data[4] + data[6];
+ tmp1 = data[4] - data[6];
+ tmp2 = data[5] - data[7];
+ tmp3 = data[5] + data[7];
+ data[4] = ((tmp0 + tmp3) * levScale) >> levShift;
+ data[5] = ((tmp0 - tmp3) * levScale) >> levShift;
+ data[6] = ((tmp1 + tmp2) * levScale) >> levShift;
+ data[7] = ((tmp1 - tmp2) * levScale) >> levShift;
+
+}
+
+/*lint +e701 +e702 */
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.h
new file mode 100755
index 0000000..4f41a23
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_transform.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_TRANSFORM_H
+#define H264SWDEC_TRANSFORM_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdProcessBlock(i32 *data, u32 qp, u32 skip, u32 coeffMap);
+void h264bsdProcessLumaDc(i32 *data, u32 qp);
+void h264bsdProcessChromaDc(i32 *data, u32 qp);
+
+#endif /* #ifdef H264SWDEC_TRANSFORM_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c
new file mode 100755
index 0000000..53b2fd8
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.c
@@ -0,0 +1,286 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdCountLeadingZeros
+ h264bsdRbspTrailingBits
+ h264bsdMoreRbspData
+ h264bsdNextMbAddress
+ h264bsdSetCurrImageMbPointers
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_util.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/* look-up table for expected values of stuffing bits */
+static const u32 stuffingTable[8] = {0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80};
+
+/* look-up table for chroma quantization parameter as a function of luma QP */
+const u32 h264bsdQpC[52] = {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,29,30,31,32,32,33,34,34,35,35,36,36,37,37,37,
+ 38,38,38,39,39,39,39};
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+
+ 5.1 Function: h264bsdCountLeadingZeros
+
+ Functional description:
+ Count leading zeros in a code word. Code word is assumed to be
+ right-aligned, last bit of the code word in the lsb of the value.
+
+ Inputs:
+ value code word
+ length number of bits in the code word
+
+ Outputs:
+ none
+
+ Returns:
+ number of leading zeros in the code word
+
+------------------------------------------------------------------------------*/
+#ifndef H264DEC_NEON
+u32 h264bsdCountLeadingZeros(u32 value, u32 length)
+{
+
+/* Variables */
+
+ u32 zeros = 0;
+ u32 mask = 1 << (length - 1);
+
+/* Code */
+
+ ASSERT(length <= 32);
+
+ while (mask && !(value & mask))
+ {
+ zeros++;
+ mask >>= 1;
+ }
+ return(zeros);
+
+}
+#endif
+/*------------------------------------------------------------------------------
+
+ 5.2 Function: h264bsdRbspTrailingBits
+
+ Functional description:
+ Check Raw Byte Stream Payload (RBSP) trailing bits, i.e. stuffing.
+ Rest of the current byte (whole byte if allready byte aligned)
+ in the stream buffer shall contain a '1' bit followed by zero or
+ more '0' bits.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+
+ Outputs:
+ none
+
+ Returns:
+ HANTRO_OK RBSP trailing bits found
+ HANTRO_NOK otherwise
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdRbspTrailingBits(strmData_t *pStrmData)
+{
+
+/* Variables */
+
+ u32 stuffing;
+ u32 stuffingLength;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pStrmData->bitPosInWord < 8);
+
+ stuffingLength = 8 - pStrmData->bitPosInWord;
+
+ stuffing = h264bsdGetBits(pStrmData, stuffingLength);
+ if (stuffing == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ if (stuffing != stuffingTable[stuffingLength - 1])
+ return(HANTRO_NOK);
+ else
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ 5.3 Function: h264bsdMoreRbspData
+
+ Functional description:
+ Check if there is more data in the current RBSP. The standard
+ defines this function so that there is more data if
+ -more than 8 bits left or
+ -last bits are not RBSP trailing bits
+
+ Inputs:
+ pStrmData pointer to stream data structure
+
+ Outputs:
+ none
+
+ Returns:
+ HANTRO_TRUE there is more data
+ HANTRO_FALSE no more data
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdMoreRbspData(strmData_t *pStrmData)
+{
+
+/* Variables */
+
+ u32 bits;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pStrmData->strmBuffReadBits <= 8 * pStrmData->strmBuffSize);
+
+ bits = pStrmData->strmBuffSize * 8 - pStrmData->strmBuffReadBits;
+
+ if (bits == 0)
+ return(HANTRO_FALSE);
+
+ if ( (bits > 8) ||
+ ((h264bsdShowBits32(pStrmData)>>(32-bits)) != (1 << (bits-1))) )
+ return(HANTRO_TRUE);
+ else
+ return(HANTRO_FALSE);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ 5.4 Function: h264bsdNextMbAddress
+
+ Functional description:
+ Get address of the next macroblock in the current slice group.
+
+ Inputs:
+ pSliceGroupMap slice group for each macroblock
+ picSizeInMbs size of the picture
+ currMbAddr where to start
+
+ Outputs:
+ none
+
+ Returns:
+ address of the next macroblock
+ 0 if none of the following macroblocks belong to same slice
+ group as currMbAddr
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdNextMbAddress(u32 *pSliceGroupMap, u32 picSizeInMbs, u32 currMbAddr)
+{
+
+/* Variables */
+
+ u32 i, sliceGroup, tmp;
+
+/* Code */
+
+ ASSERT(pSliceGroupMap);
+ ASSERT(picSizeInMbs);
+ ASSERT(currMbAddr < picSizeInMbs);
+
+ sliceGroup = pSliceGroupMap[currMbAddr];
+
+ i = currMbAddr + 1;
+ tmp = pSliceGroupMap[i];
+ while ((i < picSizeInMbs) && (tmp != sliceGroup))
+ {
+ i++;
+ tmp = pSliceGroupMap[i];
+ }
+
+ if (i == picSizeInMbs)
+ i = 0;
+
+ return(i);
+
+}
+
+
+/*------------------------------------------------------------------------------
+
+ 5.5 Function: h264bsdSetCurrImageMbPointers
+
+ Functional description:
+ Set luma and chroma pointers in image_t for current MB
+
+ Inputs:
+ image Current image
+ mbNum number of current MB
+
+ Outputs:
+ none
+
+ Returns:
+ none
+------------------------------------------------------------------------------*/
+void h264bsdSetCurrImageMbPointers(image_t *image, u32 mbNum)
+{
+ u32 width, height;
+ u32 picSize;
+ u32 row, col;
+ u32 tmp;
+
+ width = image->width;
+ height = image->height;
+ row = mbNum / width;
+ col = mbNum % width;
+
+ tmp = row * width;
+ picSize = width * height;
+
+ image->luma = (u8*)(image->data + col * 16 + tmp * 256);
+ image->cb = (u8*)(image->data + picSize * 256 + tmp * 64 + col * 8);
+ image->cr = (u8*)(image->cb + picSize * 64);
+}
+
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h
new file mode 100755
index 0000000..cb3adda
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_util.h
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_UTIL_H
+#define H264SWDEC_UTIL_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#ifdef _ASSERT_USED
+#include <assert.h>
+#endif
+
+#include "H264SwDecApi.h"
+
+#if defined(_RANGE_CHECK) || defined(_DEBUG_PRINT) || defined(_ERROR_PRINT)
+#include <stdio.h>
+#endif
+
+#include "basetype.h"
+#include "h264bsd_stream.h"
+#include "h264bsd_image.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+#define HANTRO_OK 0
+#define HANTRO_NOK 1
+
+#define HANTRO_TRUE (1)
+#define HANTRO_FALSE (0)
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define MEMORY_ALLOCATION_ERROR 0xFFFF
+#define PARAM_SET_ERROR 0xFFF0
+
+/* value to be returned by GetBits if stream buffer is empty */
+#define END_OF_STREAM 0xFFFFFFFFU
+
+#define EMPTY_RESIDUAL_INDICATOR 0xFFFFFF
+
+/* macro to mark a residual block empty, i.e. contain zero coefficients */
+#define MARK_RESIDUAL_EMPTY(residual) ((residual)[0] = EMPTY_RESIDUAL_INDICATOR)
+/* macro to check if residual block is empty */
+#define IS_RESIDUAL_EMPTY(residual) ((residual)[0] == EMPTY_RESIDUAL_INDICATOR)
+
+/* macro for assertion, used only if compiler flag _ASSERT_USED is defined */
+#ifdef _ASSERT_USED
+#define ASSERT(expr) assert(expr)
+#else
+#define ASSERT(expr)
+#endif
+
+/* macro for range checking an value, used only if compiler flag _RANGE_CHECK
+ * is defined */
+#ifdef _RANGE_CHECK
+#define RANGE_CHECK(value, minBound, maxBound) \
+{ \
+ if ((value) < (minBound) || (value) > (maxBound)) \
+ fprintf(stderr, "Warning: Value exceeds given limit(s)!\n"); \
+}
+#else
+#define RANGE_CHECK(value, minBound, maxBound)
+#endif
+
+/* macro for range checking an array, used only if compiler flag _RANGE_CHECK
+ * is defined */
+#ifdef _RANGE_CHECK
+#define RANGE_CHECK_ARRAY(array, minBound, maxBound, length) \
+{ \
+ i32 i; \
+ for (i = 0; i < (length); i++) \
+ if ((array)[i] < (minBound) || (array)[i] > (maxBound)) \
+ fprintf(stderr,"Warning: Value [%d] exceeds given limit(s)!\n",i); \
+}
+#else
+#define RANGE_CHECK_ARRAY(array, minBound, maxBound, length)
+#endif
+
+/* macro for debug printing, used only if compiler flag _DEBUG_PRINT is
+ * defined */
+#ifdef _DEBUG_PRINT
+#define DEBUG(args) printf args
+#else
+#define DEBUG(args)
+#endif
+
+/* macro for error printing, used only if compiler flag _ERROR_PRINT is
+ * defined */
+#ifdef _ERROR_PRINT
+#define EPRINT(msg) fprintf(stderr,"ERROR: %s\n",msg)
+#else
+#define EPRINT(msg)
+#endif
+
+/* macro to get smaller of two values */
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+/* macro to get greater of two values */
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+/* macro to get absolute value */
+#define ABS(a) (((a) < 0) ? -(a) : (a))
+
+/* macro to clip a value z, so that x <= z =< y */
+#define CLIP3(x,y,z) (((z) < (x)) ? (x) : (((z) > (y)) ? (y) : (z)))
+
+/* macro to clip a value z, so that 0 <= z =< 255 */
+#define CLIP1(z) (((z) < 0) ? 0 : (((z) > 255) ? 255 : (z)))
+
+/* macro to allocate memory */
+#define ALLOCATE(ptr, count, type) \
+{ \
+ (ptr) = H264SwDecMalloc((count) * sizeof(type)); \
+}
+
+/* macro to free allocated memory */
+#define FREE(ptr) \
+{ \
+ H264SwDecFree((ptr)); (ptr) = NULL; \
+}
+
+#define ALIGN(ptr, bytePos) \
+ (ptr + ( ((bytePos - (int)ptr) & (bytePos - 1)) / sizeof(*ptr) ))
+
+extern const u32 h264bsdQpC[52];
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+#ifndef H264DEC_NEON
+u32 h264bsdCountLeadingZeros(u32 value, u32 length);
+#else
+u32 h264bsdCountLeadingZeros(u32 value);
+#endif
+u32 h264bsdRbspTrailingBits(strmData_t *strmData);
+
+u32 h264bsdMoreRbspData(strmData_t *strmData);
+
+u32 h264bsdNextMbAddress(u32 *pSliceGroupMap, u32 picSizeInMbs, u32 currMbAddr);
+
+void h264bsdSetCurrImageMbPointers(image_t *image, u32 mbNum);
+
+#endif /* #ifdef H264SWDEC_UTIL_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.c
new file mode 100755
index 0000000..060f35e
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.c
@@ -0,0 +1,391 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdDecodeExpGolombUnsigned
+ h264bsdDecodeExpGolombSigned
+ h264bsdDecodeExpGolombMapped
+ h264bsdDecodeExpGolombTruncated
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_vlc.h"
+#include "basetype.h"
+#include "h264bsd_stream.h"
+#include "h264bsd_util.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+/* definition of special code num, this along with the return value is used
+ * to handle code num in the range [0, 2^32] in the DecodeExpGolombUnsigned
+ * function */
+#define BIG_CODE_NUM 0xFFFFFFFFU
+
+/* Mapping tables for coded_block_pattern, used for decoding of mapped
+ * Exp-Golomb codes */
+static const u8 codedBlockPatternIntra4x4[48] = {
+ 47,31,15,0,23,27,29,30,7,11,13,14,39,43,45,46,16,3,5,10,12,19,21,26,28,35,
+ 37,42,44,1,2,4,8,17,18,20,24,6,9,22,25,32,33,34,36,40,38,41};
+
+static const u8 codedBlockPatternInter[48] = {
+ 0,16,1,2,4,8,32,3,5,10,12,15,47,7,11,13,14,6,9,31,35,37,42,44,33,34,36,40,
+ 39,43,45,46,17,18,20,24,19,21,26,28,23,27,29,30,22,25,38,41};
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+
+ 5.1 Function: h264bsdDecodeExpGolombUnsigned
+
+ Functional description:
+ Decode unsigned Exp-Golomb code. This is the same as codeNum used
+ in other Exp-Golomb code mappings. Code num (i.e. the decoded
+ symbol) is determined as
+
+ codeNum = 2^leadingZeros - 1 + GetBits(leadingZeros)
+
+ Normal decoded symbols are in the range [0, 2^32 - 2]. Symbol
+ 2^32-1 is indicated by BIG_CODE_NUM with return value HANTRO_OK
+ while symbol 2^32 is indicated by BIG_CODE_NUM with return value
+ HANTRO_NOK. These two symbols are special cases with code length
+ of 65, i.e. 32 '0' bits, a '1' bit, and either 0 or 1 represented
+ by 32 bits.
+
+ Symbol 2^32 is out of unsigned 32-bit range but is needed for
+ DecodeExpGolombSigned to express value -2^31.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+
+ Outputs:
+ codeNum decoded code word is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK failure, no valid code word found, note exception
+ with BIG_CODE_NUM
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeExpGolombUnsigned(strmData_t *pStrmData, u32 *codeNum)
+{
+
+/* Variables */
+
+ u32 bits, numZeros;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(codeNum);
+
+ bits = h264bsdShowBits32(pStrmData);
+
+ /* first bit is 1 -> code length 1 */
+ if (bits >= 0x80000000)
+ {
+ h264bsdFlushBits(pStrmData, 1);
+ *codeNum = 0;
+ return(HANTRO_OK);
+ }
+ /* second bit is 1 -> code length 3 */
+ else if (bits >= 0x40000000)
+ {
+ if (h264bsdFlushBits(pStrmData, 3) == END_OF_STREAM)
+ return(HANTRO_NOK);
+ *codeNum = 1 + ((bits >> 29) & 0x1);
+ return(HANTRO_OK);
+ }
+ /* third bit is 1 -> code length 5 */
+ else if (bits >= 0x20000000)
+ {
+ if (h264bsdFlushBits(pStrmData, 5) == END_OF_STREAM)
+ return(HANTRO_NOK);
+ *codeNum = 3 + ((bits >> 27) & 0x3);
+ return(HANTRO_OK);
+ }
+ /* fourth bit is 1 -> code length 7 */
+ else if (bits >= 0x10000000)
+ {
+ if (h264bsdFlushBits(pStrmData, 7) == END_OF_STREAM)
+ return(HANTRO_NOK);
+ *codeNum = 7 + ((bits >> 25) & 0x7);
+ return(HANTRO_OK);
+ }
+ /* other code lengths */
+ else
+ {
+#ifndef H264DEC_NEON
+ numZeros = 4 + h264bsdCountLeadingZeros(bits, 28);
+#else
+ numZeros = h264bsdCountLeadingZeros(bits);
+#endif
+ /* all 32 bits are zero */
+ if (numZeros == 32)
+ {
+ *codeNum = 0;
+ h264bsdFlushBits(pStrmData,32);
+ bits = h264bsdGetBits(pStrmData, 1);
+ /* check 33rd bit, must be 1 */
+ if (bits == 1)
+ {
+ /* cannot use h264bsdGetBits, limited to 31 bits */
+ bits = h264bsdShowBits32(pStrmData);
+ if (h264bsdFlushBits(pStrmData, 32) == END_OF_STREAM)
+ return(HANTRO_NOK);
+ /* code num 2^32 - 1, needed for unsigned mapping */
+ if (bits == 0)
+ {
+ *codeNum = BIG_CODE_NUM;
+ return(HANTRO_OK);
+ }
+ /* code num 2^32, needed for unsigned mapping
+ * (results in -2^31) */
+ else if (bits == 1)
+ {
+ *codeNum = BIG_CODE_NUM;
+ return(HANTRO_NOK);
+ }
+ }
+ /* if more zeros than 32, it is an error */
+ return(HANTRO_NOK);
+ }
+ else
+ h264bsdFlushBits(pStrmData,numZeros+1);
+
+ bits = h264bsdGetBits(pStrmData, numZeros);
+ if (bits == END_OF_STREAM)
+ return(HANTRO_NOK);
+
+ *codeNum = (1 << numZeros) - 1 + bits;
+
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ 5.2 Function: h264bsdDecodeExpGolombSigned
+
+ Functional description:
+ Decode signed Exp-Golomb code. Code num is determined by
+ h264bsdDecodeExpGolombUnsigned and then mapped to signed
+ representation as
+
+ symbol = (-1)^(codeNum+1) * (codeNum+1)/2
+
+ Signed symbols shall be in the range [-2^31, 2^31 - 1]. Symbol
+ -2^31 is obtained when codeNum is 2^32, which cannot be expressed
+ by unsigned 32-bit value. This is signaled as a special case from
+ the h264bsdDecodeExpGolombUnsigned by setting codeNum to
+ BIG_CODE_NUM and returning HANTRO_NOK status.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+
+ Outputs:
+ value decoded code word is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK failure, no valid code word found
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeExpGolombSigned(strmData_t *pStrmData, i32 *value)
+{
+
+/* Variables */
+
+ u32 status, codeNum = 0;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(value);
+
+ status = h264bsdDecodeExpGolombUnsigned(pStrmData, &codeNum);
+
+ if (codeNum == BIG_CODE_NUM)
+ {
+ /* BIG_CODE_NUM and HANTRO_OK status means codeNum 2^32-1 which would
+ * result in signed integer valued 2^31 (i.e. out of 32-bit signed
+ * integer range) */
+ if (status == HANTRO_OK)
+ return(HANTRO_NOK);
+ /* BIG_CODE_NUM and HANTRO_NOK status means codeNum 2^32 which results
+ * in signed integer valued -2^31 */
+ else
+ {
+ *value = (i32)(2147483648U);
+ return (HANTRO_OK);
+ }
+ }
+ else if (status == HANTRO_OK)
+ {
+ /* (-1)^(codeNum+1) results in positive sign if codeNum is odd,
+ * negative when it is even. (codeNum+1)/2 is obtained as
+ * (codeNum+1)>>1 when value is positive and as (-codeNum)>>1 for
+ * negative value */
+ /*lint -e702 */
+ *value = (codeNum & 0x1) ? (i32)((codeNum + 1) >> 1) :
+ -(i32)((codeNum + 1) >> 1);
+ /*lint +e702 */
+ return(HANTRO_OK);
+ }
+
+ return(HANTRO_NOK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ 5.3 Function: h264bsdDecodeExpGolombMapped
+
+ Functional description:
+ Decode mapped Exp-Golomb code. Code num is determined by
+ h264bsdDecodeExpGolombUnsigned and then mapped to codedBlockPattern
+ either for intra or inter macroblock. The mapping is implemented by
+ look-up tables defined in the beginning of the file.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ isIntra flag to indicate if intra or inter mapping is to
+ be used
+
+ Outputs:
+ value decoded code word is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK failure, no valid code word found
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeExpGolombMapped(strmData_t *pStrmData, u32 *value,
+ u32 isIntra)
+{
+
+/* Variables */
+
+ u32 status, codeNum;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(value);
+
+ status = h264bsdDecodeExpGolombUnsigned(pStrmData, &codeNum);
+
+ if (status != HANTRO_OK)
+ return (HANTRO_NOK);
+ else
+ {
+ /* range of valid codeNums [0,47] */
+ if (codeNum > 47)
+ return (HANTRO_NOK);
+ if (isIntra)
+ *value = codedBlockPatternIntra4x4[codeNum];
+ else
+ *value = codedBlockPatternInter[codeNum];
+ return(HANTRO_OK);
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+ 5.4 Function: h264bsdDecodeExpGolombTruncated
+
+ Functional description:
+ Decode truncated Exp-Golomb code. greaterThanOne flag indicates
+ the range of the symbol to be decoded as follows:
+ FALSE -> [0,1]
+ TRUE -> [0,2^32-1]
+
+ If flag is false the decoding is performed by reading one bit
+ from the stream with h264bsdGetBits and mapping this to decoded
+ symbol as
+ symbol = bit ? 0 : 1
+
+ Otherwise, i.e. when flag is TRUE, code num is determined by
+ h264bsdDecodeExpGolombUnsigned and this is used as the decoded
+ symbol.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+ greaterThanOne flag to indicate if range is wider than [0,1]
+
+ Outputs:
+ value decoded code word is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK failure, no valid code word found
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeExpGolombTruncated(
+ strmData_t *pStrmData,
+ u32 *value,
+ u32 greaterThanOne)
+{
+
+/* Variables */
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(value);
+
+ if (greaterThanOne)
+ {
+ return(h264bsdDecodeExpGolombUnsigned(pStrmData, value));
+ }
+ else
+ {
+ *value = h264bsdGetBits(pStrmData,1);
+ if (*value == END_OF_STREAM)
+ return (HANTRO_NOK);
+ *value ^= 0x1;
+ }
+
+ return (HANTRO_OK);
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.h
new file mode 100755
index 0000000..4c16773
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vlc.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_VLC_H
+#define H264SWDEC_VLC_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_stream.h"
+#include "h264bsd_transform.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeExpGolombUnsigned(strmData_t *pStrmData, u32 *value);
+
+u32 h264bsdDecodeExpGolombSigned(strmData_t *pStrmData, i32 *value);
+
+u32 h264bsdDecodeExpGolombMapped(strmData_t *pStrmData, u32 *value,
+ u32 isIntra);
+
+u32 h264bsdDecodeExpGolombTruncated(strmData_t *pStrmData, u32 *value,
+ u32 greaterThanOne);
+
+#endif /* #ifdef H264SWDEC_VLC_H */
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.c
new file mode 100755
index 0000000..4a9335a
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.c
@@ -0,0 +1,490 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. External compiler flags
+ 3. Module defines
+ 4. Local function prototypes
+ 5. Functions
+ h264bsdDecodeVuiParameters
+ DecodeHrdParameters
+
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "h264bsd_vui.h"
+#include "basetype.h"
+#include "h264bsd_vlc.h"
+#include "h264bsd_stream.h"
+#include "h264bsd_util.h"
+
+/*------------------------------------------------------------------------------
+ 2. External compiler flags
+--------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------
+ 3. Module defines
+------------------------------------------------------------------------------*/
+
+#define MAX_DPB_SIZE 16
+#define MAX_BR 240000 /* for level 5.1 */
+#define MAX_CPB 240000 /* for level 5.1 */
+
+/*------------------------------------------------------------------------------
+ 4. Local function prototypes
+------------------------------------------------------------------------------*/
+
+static u32 DecodeHrdParameters(
+ strmData_t *pStrmData,
+ hrdParameters_t *pHrdParameters);
+
+/*------------------------------------------------------------------------------
+
+ Function: h264bsdDecodeVuiParameters
+
+ Functional description:
+ Decode VUI parameters from the stream. See standard for details.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+
+ Outputs:
+ pVuiParameters decoded information is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data or end of stream
+
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeVuiParameters(strmData_t *pStrmData,
+ vuiParameters_t *pVuiParameters)
+{
+
+/* Variables */
+
+ u32 tmp;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pVuiParameters);
+
+ H264SwDecMemset(pVuiParameters, 0, sizeof(vuiParameters_t));
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->aspectRatioPresentFlag = (tmp == 1) ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pVuiParameters->aspectRatioPresentFlag)
+ {
+ tmp = h264bsdGetBits(pStrmData, 8);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->aspectRatioIdc = tmp;
+
+ if (pVuiParameters->aspectRatioIdc == ASPECT_RATIO_EXTENDED_SAR)
+ {
+ tmp = h264bsdGetBits(pStrmData, 16);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->sarWidth = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 16);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->sarHeight = tmp;
+ }
+ }
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->overscanInfoPresentFlag = (tmp == 1) ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pVuiParameters->overscanInfoPresentFlag)
+ {
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->overscanAppropriateFlag = (tmp == 1) ?
+ HANTRO_TRUE : HANTRO_FALSE;
+ }
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->videoSignalTypePresentFlag = (tmp == 1) ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pVuiParameters->videoSignalTypePresentFlag)
+ {
+ tmp = h264bsdGetBits(pStrmData, 3);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->videoFormat = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->videoFullRangeFlag = (tmp == 1) ?
+ HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->colourDescriptionPresentFlag =
+ (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pVuiParameters->colourDescriptionPresentFlag)
+ {
+ tmp = h264bsdGetBits(pStrmData, 8);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->colourPrimaries = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 8);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->transferCharacteristics = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 8);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->matrixCoefficients = tmp;
+ }
+ else
+ {
+ pVuiParameters->colourPrimaries = 2;
+ pVuiParameters->transferCharacteristics = 2;
+ pVuiParameters->matrixCoefficients = 2;
+ }
+ }
+ else
+ {
+ pVuiParameters->videoFormat = 5;
+ pVuiParameters->colourPrimaries = 2;
+ pVuiParameters->transferCharacteristics = 2;
+ pVuiParameters->matrixCoefficients = 2;
+ }
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->chromaLocInfoPresentFlag =
+ (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pVuiParameters->chromaLocInfoPresentFlag)
+ {
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pVuiParameters->chromaSampleLocTypeTopField);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pVuiParameters->chromaSampleLocTypeTopField > 5)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pVuiParameters->chromaSampleLocTypeBottomField);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pVuiParameters->chromaSampleLocTypeBottomField > 5)
+ return(HANTRO_NOK);
+ }
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->timingInfoPresentFlag =
+ (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pVuiParameters->timingInfoPresentFlag)
+ {
+ tmp = h264bsdShowBits32(pStrmData);
+ if (h264bsdFlushBits(pStrmData, 32) == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (tmp == 0)
+ return(HANTRO_NOK);
+ pVuiParameters->numUnitsInTick = tmp;
+
+ tmp = h264bsdShowBits32(pStrmData);
+ if (h264bsdFlushBits(pStrmData, 32) == END_OF_STREAM)
+ return(HANTRO_NOK);
+ if (tmp == 0)
+ return(HANTRO_NOK);
+ pVuiParameters->timeScale = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->fixedFrameRateFlag =
+ (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+ }
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->nalHrdParametersPresentFlag =
+ (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pVuiParameters->nalHrdParametersPresentFlag)
+ {
+ tmp = DecodeHrdParameters(pStrmData, &pVuiParameters->nalHrdParameters);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+ else
+ {
+ pVuiParameters->nalHrdParameters.cpbCnt = 1;
+ /* MaxBR and MaxCPB should be the values correspondig to the levelIdc
+ * in the SPS containing these VUI parameters. However, these values
+ * are not used anywhere and maximum for any level will be used here */
+ pVuiParameters->nalHrdParameters.bitRateValue[0] = 1200 * MAX_BR + 1;
+ pVuiParameters->nalHrdParameters.cpbSizeValue[0] = 1200 * MAX_CPB + 1;
+ pVuiParameters->nalHrdParameters.initialCpbRemovalDelayLength = 24;
+ pVuiParameters->nalHrdParameters.cpbRemovalDelayLength = 24;
+ pVuiParameters->nalHrdParameters.dpbOutputDelayLength = 24;
+ pVuiParameters->nalHrdParameters.timeOffsetLength = 24;
+ }
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->vclHrdParametersPresentFlag =
+ (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pVuiParameters->vclHrdParametersPresentFlag)
+ {
+ tmp = DecodeHrdParameters(pStrmData, &pVuiParameters->vclHrdParameters);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+ else
+ {
+ pVuiParameters->vclHrdParameters.cpbCnt = 1;
+ /* MaxBR and MaxCPB should be the values correspondig to the levelIdc
+ * in the SPS containing these VUI parameters. However, these values
+ * are not used anywhere and maximum for any level will be used here */
+ pVuiParameters->vclHrdParameters.bitRateValue[0] = 1000 * MAX_BR + 1;
+ pVuiParameters->vclHrdParameters.cpbSizeValue[0] = 1000 * MAX_CPB + 1;
+ pVuiParameters->vclHrdParameters.initialCpbRemovalDelayLength = 24;
+ pVuiParameters->vclHrdParameters.cpbRemovalDelayLength = 24;
+ pVuiParameters->vclHrdParameters.dpbOutputDelayLength = 24;
+ pVuiParameters->vclHrdParameters.timeOffsetLength = 24;
+ }
+
+ if (pVuiParameters->nalHrdParametersPresentFlag ||
+ pVuiParameters->vclHrdParametersPresentFlag)
+ {
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->lowDelayHrdFlag =
+ (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+ }
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->picStructPresentFlag =
+ (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->bitstreamRestrictionFlag =
+ (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+
+ if (pVuiParameters->bitstreamRestrictionFlag)
+ {
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pVuiParameters->motionVectorsOverPicBoundariesFlag =
+ (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pVuiParameters->maxBytesPerPicDenom);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pVuiParameters->maxBytesPerPicDenom > 16)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pVuiParameters->maxBitsPerMbDenom);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pVuiParameters->maxBitsPerMbDenom > 16)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pVuiParameters->log2MaxMvLengthHorizontal);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pVuiParameters->log2MaxMvLengthHorizontal > 16)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pVuiParameters->log2MaxMvLengthVertical);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pVuiParameters->log2MaxMvLengthVertical > 16)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pVuiParameters->numReorderFrames);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pVuiParameters->maxDecFrameBuffering);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ }
+ else
+ {
+ pVuiParameters->motionVectorsOverPicBoundariesFlag = HANTRO_TRUE;
+ pVuiParameters->maxBytesPerPicDenom = 2;
+ pVuiParameters->maxBitsPerMbDenom = 1;
+ pVuiParameters->log2MaxMvLengthHorizontal = 16;
+ pVuiParameters->log2MaxMvLengthVertical = 16;
+ pVuiParameters->numReorderFrames = MAX_DPB_SIZE;
+ pVuiParameters->maxDecFrameBuffering = MAX_DPB_SIZE;
+ }
+
+ return(HANTRO_OK);
+
+}
+
+/*------------------------------------------------------------------------------
+
+ Function: DecodeHrdParameters
+
+ Functional description:
+ Decode HRD parameters from the stream. See standard for details.
+
+ Inputs:
+ pStrmData pointer to stream data structure
+
+ Outputs:
+ pHrdParameters decoded information is stored here
+
+ Returns:
+ HANTRO_OK success
+ HANTRO_NOK invalid stream data
+
+------------------------------------------------------------------------------*/
+
+static u32 DecodeHrdParameters(
+ strmData_t *pStrmData,
+ hrdParameters_t *pHrdParameters)
+{
+
+/* Variables */
+
+ u32 tmp, i;
+
+/* Code */
+
+ ASSERT(pStrmData);
+ ASSERT(pHrdParameters);
+
+
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pHrdParameters->cpbCnt);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ /* cpbCount = cpb_cnt_minus1 + 1 */
+ pHrdParameters->cpbCnt++;
+ if (pHrdParameters->cpbCnt > MAX_CPB_CNT)
+ return(HANTRO_NOK);
+
+ tmp = h264bsdGetBits(pStrmData, 4);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pHrdParameters->bitRateScale = tmp;
+
+ tmp = h264bsdGetBits(pStrmData, 4);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pHrdParameters->cpbSizeScale = tmp;
+
+ for (i = 0; i < pHrdParameters->cpbCnt; i++)
+ {
+ /* bit_rate_value_minus1 in the range [0, 2^32 - 2] */
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pHrdParameters->bitRateValue[i]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pHrdParameters->bitRateValue[i] > 4294967294U)
+ return(HANTRO_NOK);
+ pHrdParameters->bitRateValue[i]++;
+ /* this may result in overflow, but this value is not used for
+ * anything */
+ pHrdParameters->bitRateValue[i] *=
+ 1 << (6 + pHrdParameters->bitRateScale);
+
+ /* cpb_size_value_minus1 in the range [0, 2^32 - 2] */
+ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
+ &pHrdParameters->cpbSizeValue[i]);
+ if (tmp != HANTRO_OK)
+ return(tmp);
+ if (pHrdParameters->cpbSizeValue[i] > 4294967294U)
+ return(HANTRO_NOK);
+ pHrdParameters->cpbSizeValue[i]++;
+ /* this may result in overflow, but this value is not used for
+ * anything */
+ pHrdParameters->cpbSizeValue[i] *=
+ 1 << (4 + pHrdParameters->cpbSizeScale);
+
+ tmp = h264bsdGetBits(pStrmData, 1);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pHrdParameters->cbrFlag[i] = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
+ }
+
+ tmp = h264bsdGetBits(pStrmData, 5);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pHrdParameters->initialCpbRemovalDelayLength = tmp + 1;
+
+ tmp = h264bsdGetBits(pStrmData, 5);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pHrdParameters->cpbRemovalDelayLength = tmp + 1;
+
+ tmp = h264bsdGetBits(pStrmData, 5);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pHrdParameters->dpbOutputDelayLength = tmp + 1;
+
+ tmp = h264bsdGetBits(pStrmData, 5);
+ if (tmp == END_OF_STREAM)
+ return(HANTRO_NOK);
+ pHrdParameters->timeOffsetLength = tmp;
+
+ return(HANTRO_OK);
+
+}
+
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.h b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.h
new file mode 100755
index 0000000..05d52a4
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_vui.h
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------------
+
+ Table of contents
+
+ 1. Include headers
+ 2. Module defines
+ 3. Data types
+ 4. Function prototypes
+
+------------------------------------------------------------------------------*/
+
+#ifndef H264SWDEC_VUI_H
+#define H264SWDEC_VUI_H
+
+/*------------------------------------------------------------------------------
+ 1. Include headers
+------------------------------------------------------------------------------*/
+
+#include "basetype.h"
+#include "h264bsd_stream.h"
+
+/*------------------------------------------------------------------------------
+ 2. Module defines
+------------------------------------------------------------------------------*/
+
+#define MAX_CPB_CNT 32
+
+/*------------------------------------------------------------------------------
+ 3. Data types
+------------------------------------------------------------------------------*/
+
+/* enumerated sample aspect ratios, ASPECT_RATIO_M_N means M:N */
+enum
+{
+ ASPECT_RATIO_UNSPECIFIED = 0,
+ ASPECT_RATIO_1_1,
+ ASPECT_RATIO_12_11,
+ ASPECT_RATIO_10_11,
+ ASPECT_RATIO_16_11,
+ ASPECT_RATIO_40_33,
+ ASPECT_RATIO_24_11,
+ ASPECT_RATIO_20_11,
+ ASPECT_RATIO_32_11,
+ ASPECT_RATIO_80_33,
+ ASPECT_RATIO_18_11,
+ ASPECT_RATIO_15_11,
+ ASPECT_RATIO_64_33,
+ ASPECT_RATIO_160_99,
+ ASPECT_RATIO_EXTENDED_SAR = 255
+};
+
+/* structure to store Hypothetical Reference Decoder (HRD) parameters */
+typedef struct
+{
+ u32 cpbCnt;
+ u32 bitRateScale;
+ u32 cpbSizeScale;
+ u32 bitRateValue[MAX_CPB_CNT];
+ u32 cpbSizeValue[MAX_CPB_CNT];
+ u32 cbrFlag[MAX_CPB_CNT];
+ u32 initialCpbRemovalDelayLength;
+ u32 cpbRemovalDelayLength;
+ u32 dpbOutputDelayLength;
+ u32 timeOffsetLength;
+} hrdParameters_t;
+
+/* storage for VUI parameters */
+typedef struct
+{
+ u32 aspectRatioPresentFlag;
+ u32 aspectRatioIdc;
+ u32 sarWidth;
+ u32 sarHeight;
+ u32 overscanInfoPresentFlag;
+ u32 overscanAppropriateFlag;
+ u32 videoSignalTypePresentFlag;
+ u32 videoFormat;
+ u32 videoFullRangeFlag;
+ u32 colourDescriptionPresentFlag;
+ u32 colourPrimaries;
+ u32 transferCharacteristics;
+ u32 matrixCoefficients;
+ u32 chromaLocInfoPresentFlag;
+ u32 chromaSampleLocTypeTopField;
+ u32 chromaSampleLocTypeBottomField;
+ u32 timingInfoPresentFlag;
+ u32 numUnitsInTick;
+ u32 timeScale;
+ u32 fixedFrameRateFlag;
+ u32 nalHrdParametersPresentFlag;
+ hrdParameters_t nalHrdParameters;
+ u32 vclHrdParametersPresentFlag;
+ hrdParameters_t vclHrdParameters;
+ u32 lowDelayHrdFlag;
+ u32 picStructPresentFlag;
+ u32 bitstreamRestrictionFlag;
+ u32 motionVectorsOverPicBoundariesFlag;
+ u32 maxBytesPerPicDenom;
+ u32 maxBitsPerMbDenom;
+ u32 log2MaxMvLengthHorizontal;
+ u32 log2MaxMvLengthVertical;
+ u32 numReorderFrames;
+ u32 maxDecFrameBuffering;
+} vuiParameters_t;
+
+/*------------------------------------------------------------------------------
+ 4. Function prototypes
+------------------------------------------------------------------------------*/
+
+u32 h264bsdDecodeVuiParameters(strmData_t *pStrmData,
+ vuiParameters_t *pVuiParameters);
+
+#endif /* #ifdef H264SWDEC_VUI_H */
+
diff --git a/media/libstagefright/codecs/vorbis/Android.mk b/media/libstagefright/codecs/vorbis/Android.mk
new file mode 100644
index 0000000..2e43120
--- /dev/null
+++ b/media/libstagefright/codecs/vorbis/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/vorbis/dec/Android.mk b/media/libstagefright/codecs/vorbis/dec/Android.mk
new file mode 100644
index 0000000..fca70b7
--- /dev/null
+++ b/media/libstagefright/codecs/vorbis/dec/Android.mk
@@ -0,0 +1,20 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ SoftVorbis.cpp
+
+LOCAL_C_INCLUDES := \
+ external/tremolo \
+ frameworks/base/media/libstagefright/include \
+ frameworks/native/include/media/openmax \
+
+LOCAL_SHARED_LIBRARIES := \
+ libvorbisidec libstagefright libstagefright_omx \
+ libstagefright_foundation libutils
+
+LOCAL_MODULE := libstagefright_soft_vorbisdec
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
new file mode 100644
index 0000000..ac88107
--- /dev/null
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SoftVorbis"
+#include <utils/Log.h>
+
+#include "SoftVorbis.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaDefs.h>
+
+extern "C" {
+ #include <Tremolo/codec_internal.h>
+
+ int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
+ int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
+ int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
+}
+
+namespace android {
+
+template<class T>
+static void InitOMXParams(T *params) {
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+SoftVorbis::SoftVorbis(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SimpleSoftOMXComponent(name, callbacks, appData, component),
+ mInputBufferCount(0),
+ mState(NULL),
+ mVi(NULL),
+ mAnchorTimeUs(0),
+ mNumFramesOutput(0),
+ mNumFramesLeftOnPage(-1),
+ mOutputPortSettingsChange(NONE) {
+ initPorts();
+ CHECK_EQ(initDecoder(), (status_t)OK);
+}
+
+SoftVorbis::~SoftVorbis() {
+ if (mState != NULL) {
+ vorbis_dsp_clear(mState);
+ delete mState;
+ mState = NULL;
+ }
+
+ if (mVi != NULL) {
+ vorbis_info_clear(mVi);
+ delete mVi;
+ mVi = NULL;
+ }
+}
+
+void SoftVorbis::initPorts() {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+
+ def.nPortIndex = 0;
+ def.eDir = OMX_DirInput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = 8192;
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 1;
+
+ def.format.audio.cMIMEType =
+ const_cast<char *>(MEDIA_MIMETYPE_AUDIO_VORBIS);
+
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
+
+ addPort(def);
+
+ def.nPortIndex = 1;
+ def.eDir = OMX_DirOutput;
+ def.nBufferCountMin = kNumBuffers;
+ def.nBufferCountActual = def.nBufferCountMin;
+ def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t);
+ def.bEnabled = OMX_TRUE;
+ def.bPopulated = OMX_FALSE;
+ def.eDomain = OMX_PortDomainAudio;
+ def.bBuffersContiguous = OMX_FALSE;
+ def.nBufferAlignment = 2;
+
+ def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
+ def.format.audio.pNativeRender = NULL;
+ def.format.audio.bFlagErrorConcealment = OMX_FALSE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+
+ addPort(def);
+}
+
+status_t SoftVorbis::initDecoder() {
+ return OK;
+}
+
+OMX_ERRORTYPE SoftVorbis::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamAudioVorbis:
+ {
+ OMX_AUDIO_PARAM_VORBISTYPE *vorbisParams =
+ (OMX_AUDIO_PARAM_VORBISTYPE *)params;
+
+ if (vorbisParams->nPortIndex != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ vorbisParams->nBitRate = 0;
+ vorbisParams->nMinBitRate = 0;
+ vorbisParams->nMaxBitRate = 0;
+ vorbisParams->nAudioBandWidth = 0;
+ vorbisParams->nQuality = 3;
+ vorbisParams->bManaged = OMX_FALSE;
+ vorbisParams->bDownmix = OMX_FALSE;
+
+ if (!isConfigured()) {
+ vorbisParams->nChannels = 1;
+ vorbisParams->nSampleRate = 44100;
+ } else {
+ vorbisParams->nChannels = mVi->channels;
+ vorbisParams->nSampleRate = mVi->rate;
+ vorbisParams->nBitRate = mVi->bitrate_nominal;
+ vorbisParams->nMinBitRate = mVi->bitrate_lower;
+ vorbisParams->nMaxBitRate = mVi->bitrate_upper;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioPcm:
+ {
+ OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ pcmParams->eNumData = OMX_NumericalDataSigned;
+ pcmParams->eEndian = OMX_EndianBig;
+ pcmParams->bInterleaved = OMX_TRUE;
+ pcmParams->nBitPerSample = 16;
+ pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
+ pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+ pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+
+ if (!isConfigured()) {
+ pcmParams->nChannels = 1;
+ pcmParams->nSamplingRate = 44100;
+ } else {
+ pcmParams->nChannels = mVi->channels;
+ pcmParams->nSamplingRate = mVi->rate;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalGetParameter(index, params);
+ }
+}
+
+OMX_ERRORTYPE SoftVorbis::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamStandardComponentRole:
+ {
+ const OMX_PARAM_COMPONENTROLETYPE *roleParams =
+ (const OMX_PARAM_COMPONENTROLETYPE *)params;
+
+ if (strncmp((const char *)roleParams->cRole,
+ "audio_decoder.vorbis",
+ OMX_MAX_STRINGNAME_SIZE - 1)) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ case OMX_IndexParamAudioVorbis:
+ {
+ const OMX_AUDIO_PARAM_VORBISTYPE *vorbisParams =
+ (const OMX_AUDIO_PARAM_VORBISTYPE *)params;
+
+ if (vorbisParams->nPortIndex != 0) {
+ return OMX_ErrorUndefined;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ }
+}
+
+bool SoftVorbis::isConfigured() const {
+ return mInputBufferCount >= 2;
+}
+
+static void makeBitReader(
+ const void *data, size_t size,
+ ogg_buffer *buf, ogg_reference *ref, oggpack_buffer *bits) {
+ buf->data = (uint8_t *)data;
+ buf->size = size;
+ buf->refcount = 1;
+ buf->ptr.owner = NULL;
+
+ ref->buffer = buf;
+ ref->begin = 0;
+ ref->length = size;
+ ref->next = NULL;
+
+ oggpack_readinit(bits, ref);
+}
+
+void SoftVorbis::onQueueFilled(OMX_U32 portIndex) {
+ List<BufferInfo *> &inQueue = getPortQueue(0);
+ List<BufferInfo *> &outQueue = getPortQueue(1);
+
+ if (mOutputPortSettingsChange != NONE) {
+ return;
+ }
+
+ if (portIndex == 0 && mInputBufferCount < 2) {
+ BufferInfo *info = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *header = info->mHeader;
+
+ const uint8_t *data = header->pBuffer + header->nOffset;
+ size_t size = header->nFilledLen;
+
+ ogg_buffer buf;
+ ogg_reference ref;
+ oggpack_buffer bits;
+
+ makeBitReader(
+ (const uint8_t *)data + 7, size - 7,
+ &buf, &ref, &bits);
+
+ if (mInputBufferCount == 0) {
+ CHECK(mVi == NULL);
+ mVi = new vorbis_info;
+ vorbis_info_init(mVi);
+
+ CHECK_EQ(0, _vorbis_unpack_info(mVi, &bits));
+ } else {
+ CHECK_EQ(0, _vorbis_unpack_books(mVi, &bits));
+
+ CHECK(mState == NULL);
+ mState = new vorbis_dsp_state;
+ CHECK_EQ(0, vorbis_dsp_init(mState, mVi));
+
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+ }
+
+ inQueue.erase(inQueue.begin());
+ info->mOwnedByUs = false;
+ notifyEmptyBufferDone(header);
+
+ ++mInputBufferCount;
+
+ return;
+ }
+
+ while (!inQueue.empty() && !outQueue.empty()) {
+ BufferInfo *inInfo = *inQueue.begin();
+ OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
+
+ BufferInfo *outInfo = *outQueue.begin();
+ OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
+
+ if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
+ inQueue.erase(inQueue.begin());
+ inInfo->mOwnedByUs = false;
+ notifyEmptyBufferDone(inHeader);
+
+ outHeader->nFilledLen = 0;
+ outHeader->nFlags = OMX_BUFFERFLAG_EOS;
+
+ outQueue.erase(outQueue.begin());
+ outInfo->mOwnedByUs = false;
+ notifyFillBufferDone(outHeader);
+ return;
+ }
+
+ int32_t numPageSamples;
+ CHECK_GE(inHeader->nFilledLen, sizeof(numPageSamples));
+ memcpy(&numPageSamples,
+ inHeader->pBuffer
+ + inHeader->nOffset + inHeader->nFilledLen - 4,
+ sizeof(numPageSamples));
+
+ if (numPageSamples >= 0) {
+ mNumFramesLeftOnPage = numPageSamples;
+ }
+
+ if (inHeader->nOffset == 0) {
+ mAnchorTimeUs = inHeader->nTimeStamp;
+ mNumFramesOutput = 0;
+ }
+
+ inHeader->nFilledLen -= sizeof(numPageSamples);;
+
+ ogg_buffer buf;
+ buf.data = inHeader->pBuffer + inHeader->nOffset;
+ buf.size = inHeader->nFilledLen;
+ buf.refcount = 1;
+ buf.ptr.owner = NULL;
+
+ ogg_reference ref;
+ ref.buffer = &buf;
+ ref.begin = 0;
+ ref.length = buf.size;
+ ref.next = NULL;
+
+ ogg_packet pack;
+ pack.packet = &ref;
+ pack.bytes = ref.length;
+ pack.b_o_s = 0;
+ pack.e_o_s = 0;
+ pack.granulepos = 0;
+ pack.packetno = 0;
+
+ int numFrames = 0;
+
+ int err = vorbis_dsp_synthesis(mState, &pack, 1);
+ if (err != 0) {
+ ALOGW("vorbis_dsp_synthesis returned %d", err);
+ } else {
+ numFrames = vorbis_dsp_pcmout(
+ mState, (int16_t *)outHeader->pBuffer,
+ kMaxNumSamplesPerBuffer);
+
+ if (numFrames < 0) {
+ ALOGE("vorbis_dsp_pcmout returned %d", numFrames);
+ numFrames = 0;
+ }
+ }
+
+ if (mNumFramesLeftOnPage >= 0) {
+ if (numFrames > mNumFramesLeftOnPage) {
+ ALOGV("discarding %d frames at end of page",
+ numFrames - mNumFramesLeftOnPage);
+ numFrames = mNumFramesLeftOnPage;
+ }
+ mNumFramesLeftOnPage -= numFrames;
+ }
+
+ outHeader->nFilledLen = numFrames * sizeof(int16_t) * mVi->channels;
+ outHeader->nOffset = 0;
+ outHeader->nFlags = 0;
+
+ outHeader->nTimeStamp =
+ mAnchorTimeUs
+ + (mNumFramesOutput * 1000000ll) / mVi->rate;
+
+ mNumFramesOutput += numFrames;
+
+ inInfo->mOwnedByUs = false;
+ inQueue.erase(inQueue.begin());
+ inInfo = NULL;
+ notifyEmptyBufferDone(inHeader);
+ inHeader = NULL;
+
+ outInfo->mOwnedByUs = false;
+ outQueue.erase(outQueue.begin());
+ outInfo = NULL;
+ notifyFillBufferDone(outHeader);
+ outHeader = NULL;
+
+ ++mInputBufferCount;
+ }
+}
+
+void SoftVorbis::onPortFlushCompleted(OMX_U32 portIndex) {
+ if (portIndex == 0 && mState != NULL) {
+ // Make sure that the next buffer output does not still
+ // depend on fragments from the last one decoded.
+
+ mNumFramesOutput = 0;
+ vorbis_dsp_restart(mState);
+ }
+}
+
+void SoftVorbis::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
+ if (portIndex != 1) {
+ return;
+ }
+
+ switch (mOutputPortSettingsChange) {
+ case NONE:
+ break;
+
+ case AWAITING_DISABLED:
+ {
+ CHECK(!enabled);
+ mOutputPortSettingsChange = AWAITING_ENABLED;
+ break;
+ }
+
+ default:
+ {
+ CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
+ CHECK(enabled);
+ mOutputPortSettingsChange = NONE;
+ break;
+ }
+ }
+}
+
+} // namespace android
+
+android::SoftOMXComponent *createSoftOMXComponent(
+ const char *name, const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData, OMX_COMPONENTTYPE **component) {
+ return new android::SoftVorbis(name, callbacks, appData, component);
+}
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h
new file mode 100644
index 0000000..e252f55
--- /dev/null
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SOFT_VORBIS_H_
+
+#define SOFT_VORBIS_H_
+
+#include "SimpleSoftOMXComponent.h"
+
+struct vorbis_dsp_state;
+struct vorbis_info;
+
+namespace android {
+
+struct SoftVorbis : public SimpleSoftOMXComponent {
+ SoftVorbis(const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+protected:
+ virtual ~SoftVorbis();
+
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual void onQueueFilled(OMX_U32 portIndex);
+ virtual void onPortFlushCompleted(OMX_U32 portIndex);
+ virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled);
+
+private:
+ enum {
+ kNumBuffers = 4,
+ kMaxNumSamplesPerBuffer = 8192 * 2
+ };
+
+ size_t mInputBufferCount;
+
+ vorbis_dsp_state *mState;
+ vorbis_info *mVi;
+
+ int64_t mAnchorTimeUs;
+ int64_t mNumFramesOutput;
+ int32_t mNumFramesLeftOnPage;
+
+ enum {
+ NONE,
+ AWAITING_DISABLED,
+ AWAITING_ENABLED
+ } mOutputPortSettingsChange;
+
+ void initPorts();
+ status_t initDecoder();
+ bool isConfigured() const;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftVorbis);
+};
+
+} // namespace android
+
+#endif // SOFT_VORBIS_H_
+
diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk
new file mode 100644
index 0000000..59a64ba
--- /dev/null
+++ b/media/libstagefright/colorconversion/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ ColorConverter.cpp \
+ SoftwareRenderer.cpp
+
+LOCAL_C_INCLUDES := \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/hardware/msm7k
+
+LOCAL_MODULE:= libstagefright_color_conversion
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
new file mode 100644
index 0000000..597167f
--- /dev/null
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -0,0 +1,524 @@
+/*
+ * 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 "ColorConverter"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/ColorConverter.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+ColorConverter::ColorConverter(
+ OMX_COLOR_FORMATTYPE from, OMX_COLOR_FORMATTYPE to)
+ : mSrcFormat(from),
+ mDstFormat(to),
+ mClip(NULL) {
+}
+
+ColorConverter::~ColorConverter() {
+ delete[] mClip;
+ mClip = NULL;
+}
+
+bool ColorConverter::isValid() const {
+ if (mDstFormat != OMX_COLOR_Format16bitRGB565) {
+ return false;
+ }
+
+ switch (mSrcFormat) {
+ case OMX_COLOR_FormatYUV420Planar:
+ case OMX_COLOR_FormatCbYCrY:
+ case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+ColorConverter::BitmapParams::BitmapParams(
+ void *bits,
+ size_t width, size_t height,
+ size_t cropLeft, size_t cropTop,
+ size_t cropRight, size_t cropBottom)
+ : mBits(bits),
+ mWidth(width),
+ mHeight(height),
+ mCropLeft(cropLeft),
+ mCropTop(cropTop),
+ mCropRight(cropRight),
+ mCropBottom(cropBottom) {
+}
+
+size_t ColorConverter::BitmapParams::cropWidth() const {
+ return mCropRight - mCropLeft + 1;
+}
+
+size_t ColorConverter::BitmapParams::cropHeight() const {
+ return mCropBottom - mCropTop + 1;
+}
+
+status_t ColorConverter::convert(
+ const void *srcBits,
+ size_t srcWidth, size_t srcHeight,
+ size_t srcCropLeft, size_t srcCropTop,
+ size_t srcCropRight, size_t srcCropBottom,
+ void *dstBits,
+ size_t dstWidth, size_t dstHeight,
+ size_t dstCropLeft, size_t dstCropTop,
+ size_t dstCropRight, size_t dstCropBottom) {
+ if (mDstFormat != OMX_COLOR_Format16bitRGB565) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ BitmapParams src(
+ const_cast<void *>(srcBits),
+ srcWidth, srcHeight,
+ srcCropLeft, srcCropTop, srcCropRight, srcCropBottom);
+
+ BitmapParams dst(
+ dstBits,
+ dstWidth, dstHeight,
+ dstCropLeft, dstCropTop, dstCropRight, dstCropBottom);
+
+ status_t err;
+
+ switch (mSrcFormat) {
+ case OMX_COLOR_FormatYUV420Planar:
+ err = convertYUV420Planar(src, dst);
+ break;
+
+ case OMX_COLOR_FormatCbYCrY:
+ err = convertCbYCrY(src, dst);
+ break;
+
+ case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
+ err = convertQCOMYUV420SemiPlanar(src, dst);
+ break;
+
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ err = convertYUV420SemiPlanar(src, dst);
+ break;
+
+ case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
+ err = convertTIYUV420PackedSemiPlanar(src, dst);
+ break;
+
+ default:
+ {
+ CHECK(!"Should not be here. Unknown color conversion.");
+ break;
+ }
+ }
+
+ return err;
+}
+
+status_t ColorConverter::convertCbYCrY(
+ const BitmapParams &src, const BitmapParams &dst) {
+ // XXX Untested
+
+ uint8_t *kAdjustedClip = initClip();
+
+ if (!((src.mCropLeft & 1) == 0
+ && src.cropWidth() == dst.cropWidth()
+ && src.cropHeight() == dst.cropHeight())) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ uint16_t *dst_ptr = (uint16_t *)dst.mBits
+ + dst.mCropTop * dst.mWidth + dst.mCropLeft;
+
+ const uint8_t *src_ptr = (const uint8_t *)src.mBits
+ + (src.mCropTop * dst.mWidth + src.mCropLeft) * 2;
+
+ for (size_t y = 0; y < src.cropHeight(); ++y) {
+ for (size_t x = 0; x < src.cropWidth(); x += 2) {
+ signed y1 = (signed)src_ptr[2 * x + 1] - 16;
+ signed y2 = (signed)src_ptr[2 * x + 3] - 16;
+ signed u = (signed)src_ptr[2 * x] - 128;
+ signed v = (signed)src_ptr[2 * x + 2] - 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[r1] >> 3) << 11)
+ | ((kAdjustedClip[g1] >> 2) << 5)
+ | (kAdjustedClip[b1] >> 3);
+
+ uint32_t rgb2 =
+ ((kAdjustedClip[r2] >> 3) << 11)
+ | ((kAdjustedClip[g2] >> 2) << 5)
+ | (kAdjustedClip[b2] >> 3);
+
+ if (x + 1 < src.cropWidth()) {
+ *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1;
+ } else {
+ dst_ptr[x] = rgb1;
+ }
+ }
+
+ src_ptr += src.mWidth * 2;
+ dst_ptr += dst.mWidth;
+ }
+
+ return OK;
+}
+
+status_t ColorConverter::convertYUV420Planar(
+ const BitmapParams &src, const BitmapParams &dst) {
+ if (!((src.mCropLeft & 1) == 0
+ && src.cropWidth() == dst.cropWidth()
+ && src.cropHeight() == dst.cropHeight())) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ uint8_t *kAdjustedClip = initClip();
+
+ uint16_t *dst_ptr = (uint16_t *)dst.mBits
+ + dst.mCropTop * dst.mWidth + dst.mCropLeft;
+
+ const uint8_t *src_y =
+ (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft;
+
+ const uint8_t *src_u =
+ (const uint8_t *)src_y + src.mWidth * src.mHeight
+ + src.mCropTop * (src.mWidth / 2) + src.mCropLeft / 2;
+
+ const uint8_t *src_v =
+ src_u + (src.mWidth / 2) * (src.mHeight / 2);
+
+ for (size_t y = 0; y < src.cropHeight(); ++y) {
+ for (size_t x = 0; x < src.cropWidth(); x += 2) {
+ // B = 1.164 * (Y - 16) + 2.018 * (U - 128)
+ // G = 1.164 * (Y - 16) - 0.813 * (V - 128) - 0.391 * (U - 128)
+ // R = 1.164 * (Y - 16) + 1.596 * (V - 128)
+
+ // B = 298/256 * (Y - 16) + 517/256 * (U - 128)
+ // G = .................. - 208/256 * (V - 128) - 100/256 * (U - 128)
+ // R = .................. + 409/256 * (V - 128)
+
+ // min_B = (298 * (- 16) + 517 * (- 128)) / 256 = -277
+ // min_G = (298 * (- 16) - 208 * (255 - 128) - 100 * (255 - 128)) / 256 = -172
+ // min_R = (298 * (- 16) + 409 * (- 128)) / 256 = -223
+
+ // max_B = (298 * (255 - 16) + 517 * (255 - 128)) / 256 = 534
+ // max_G = (298 * (255 - 16) - 208 * (- 128) - 100 * (- 128)) / 256 = 432
+ // max_R = (298 * (255 - 16) + 409 * (255 - 128)) / 256 = 481
+
+ // clip range -278 .. 535
+
+ signed y1 = (signed)src_y[x] - 16;
+ signed y2 = (signed)src_y[x + 1] - 16;
+
+ signed u = (signed)src_u[x / 2] - 128;
+ signed v = (signed)src_v[x / 2] - 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[r1] >> 3) << 11)
+ | ((kAdjustedClip[g1] >> 2) << 5)
+ | (kAdjustedClip[b1] >> 3);
+
+ uint32_t rgb2 =
+ ((kAdjustedClip[r2] >> 3) << 11)
+ | ((kAdjustedClip[g2] >> 2) << 5)
+ | (kAdjustedClip[b2] >> 3);
+
+ if (x + 1 < src.cropWidth()) {
+ *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1;
+ } else {
+ dst_ptr[x] = rgb1;
+ }
+ }
+
+ src_y += src.mWidth;
+
+ if (y & 1) {
+ src_u += src.mWidth / 2;
+ src_v += src.mWidth / 2;
+ }
+
+ dst_ptr += dst.mWidth;
+ }
+
+ return OK;
+}
+
+status_t ColorConverter::convertQCOMYUV420SemiPlanar(
+ const BitmapParams &src, const BitmapParams &dst) {
+ uint8_t *kAdjustedClip = initClip();
+
+ if (!((src.mCropLeft & 1) == 0
+ && src.cropWidth() == dst.cropWidth()
+ && src.cropHeight() == dst.cropHeight())) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ uint16_t *dst_ptr = (uint16_t *)dst.mBits
+ + dst.mCropTop * dst.mWidth + dst.mCropLeft;
+
+ const uint8_t *src_y =
+ (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft;
+
+ const uint8_t *src_u =
+ (const uint8_t *)src_y + src.mWidth * src.mHeight
+ + src.mCropTop * src.mWidth + src.mCropLeft;
+
+ for (size_t y = 0; y < src.cropHeight(); ++y) {
+ for (size_t x = 0; x < src.cropWidth(); x += 2) {
+ signed y1 = (signed)src_y[x] - 16;
+ signed y2 = (signed)src_y[x + 1] - 16;
+
+ signed u = (signed)src_u[x & ~1] - 128;
+ signed v = (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);
+
+ if (x + 1 < src.cropWidth()) {
+ *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1;
+ } else {
+ dst_ptr[x] = rgb1;
+ }
+ }
+
+ src_y += src.mWidth;
+
+ if (y & 1) {
+ src_u += src.mWidth;
+ }
+
+ dst_ptr += dst.mWidth;
+ }
+
+ return OK;
+}
+
+status_t ColorConverter::convertYUV420SemiPlanar(
+ const BitmapParams &src, const BitmapParams &dst) {
+ // XXX Untested
+
+ uint8_t *kAdjustedClip = initClip();
+
+ if (!((src.mCropLeft & 1) == 0
+ && src.cropWidth() == dst.cropWidth()
+ && src.cropHeight() == dst.cropHeight())) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ uint16_t *dst_ptr = (uint16_t *)dst.mBits
+ + dst.mCropTop * dst.mWidth + dst.mCropLeft;
+
+ const uint8_t *src_y =
+ (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft;
+
+ const uint8_t *src_u =
+ (const uint8_t *)src_y + src.mWidth * src.mHeight
+ + src.mCropTop * src.mWidth + src.mCropLeft;
+
+ for (size_t y = 0; y < src.cropHeight(); ++y) {
+ for (size_t x = 0; x < src.cropWidth(); 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);
+
+ if (x + 1 < src.cropWidth()) {
+ *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1;
+ } else {
+ dst_ptr[x] = rgb1;
+ }
+ }
+
+ src_y += src.mWidth;
+
+ if (y & 1) {
+ src_u += src.mWidth;
+ }
+
+ dst_ptr += dst.mWidth;
+ }
+
+ return OK;
+}
+
+status_t ColorConverter::convertTIYUV420PackedSemiPlanar(
+ const BitmapParams &src, const BitmapParams &dst) {
+ uint8_t *kAdjustedClip = initClip();
+
+ if (!((src.mCropLeft & 1) == 0
+ && src.cropWidth() == dst.cropWidth()
+ && src.cropHeight() == dst.cropHeight())) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ uint16_t *dst_ptr = (uint16_t *)dst.mBits
+ + dst.mCropTop * dst.mWidth + dst.mCropLeft;
+
+ const uint8_t *src_y = (const uint8_t *)src.mBits;
+
+ const uint8_t *src_u =
+ (const uint8_t *)src_y + src.mWidth * (src.mHeight - src.mCropTop / 2);
+
+ for (size_t y = 0; y < src.cropHeight(); ++y) {
+ for (size_t x = 0; x < src.cropWidth(); x += 2) {
+ signed y1 = (signed)src_y[x] - 16;
+ signed y2 = (signed)src_y[x + 1] - 16;
+
+ signed u = (signed)src_u[x & ~1] - 128;
+ signed v = (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[r1] >> 3) << 11)
+ | ((kAdjustedClip[g1] >> 2) << 5)
+ | (kAdjustedClip[b1] >> 3);
+
+ uint32_t rgb2 =
+ ((kAdjustedClip[r2] >> 3) << 11)
+ | ((kAdjustedClip[g2] >> 2) << 5)
+ | (kAdjustedClip[b2] >> 3);
+
+ if (x + 1 < src.cropWidth()) {
+ *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1;
+ } else {
+ dst_ptr[x] = rgb1;
+ }
+ }
+
+ src_y += src.mWidth;
+
+ if (y & 1) {
+ src_u += src.mWidth;
+ }
+
+ dst_ptr += dst.mWidth;
+ }
+
+ return OK;
+}
+
+uint8_t *ColorConverter::initClip() {
+ static const signed kClipMin = -278;
+ static const signed kClipMax = 535;
+
+ if (mClip == NULL) {
+ mClip = new uint8_t[kClipMax - kClipMin + 1];
+
+ for (signed i = kClipMin; i <= kClipMax; ++i) {
+ mClip[i - kClipMin] = (i < 0) ? 0 : (i > 255) ? 255 : (uint8_t)i;
+ }
+ }
+
+ return &mClip[-kClipMin];
+}
+
+} // namespace android
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
new file mode 100644
index 0000000..059d6b9
--- /dev/null
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -0,0 +1,230 @@
+/*
+ * 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 "SoftwareRenderer"
+#include <utils/Log.h>
+
+#include "../include/SoftwareRenderer.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MetaData.h>
+#include <system/window.h>
+#include <ui/GraphicBufferMapper.h>
+#include <gui/ISurfaceTexture.h>
+
+namespace android {
+
+SoftwareRenderer::SoftwareRenderer(
+ const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta)
+ : mConverter(NULL),
+ mYUVMode(None),
+ mNativeWindow(nativeWindow) {
+ int32_t tmp;
+ CHECK(meta->findInt32(kKeyColorFormat, &tmp));
+ mColorFormat = (OMX_COLOR_FORMATTYPE)tmp;
+
+ CHECK(meta->findInt32(kKeyWidth, &mWidth));
+ CHECK(meta->findInt32(kKeyHeight, &mHeight));
+
+ if (!meta->findRect(
+ kKeyCropRect,
+ &mCropLeft, &mCropTop, &mCropRight, &mCropBottom)) {
+ mCropLeft = mCropTop = 0;
+ mCropRight = mWidth - 1;
+ mCropBottom = mHeight - 1;
+ }
+
+ mCropWidth = mCropRight - mCropLeft + 1;
+ mCropHeight = mCropBottom - mCropTop + 1;
+
+ int32_t rotationDegrees;
+ if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
+ rotationDegrees = 0;
+ }
+
+ int halFormat;
+ size_t bufWidth, bufHeight;
+
+ switch (mColorFormat) {
+ case OMX_COLOR_FormatYUV420Planar:
+ case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
+ {
+ halFormat = HAL_PIXEL_FORMAT_YV12;
+ bufWidth = (mCropWidth + 1) & ~1;
+ bufHeight = (mCropHeight + 1) & ~1;
+ break;
+ }
+
+ default:
+ halFormat = HAL_PIXEL_FORMAT_RGB_565;
+ bufWidth = mCropWidth;
+ bufHeight = mCropHeight;
+
+ mConverter = new ColorConverter(
+ mColorFormat, OMX_COLOR_Format16bitRGB565);
+ CHECK(mConverter->isValid());
+ break;
+ }
+
+ CHECK(mNativeWindow != NULL);
+ CHECK(mCropWidth > 0);
+ CHECK(mCropHeight > 0);
+ CHECK(mConverter == NULL || mConverter->isValid());
+
+ CHECK_EQ(0,
+ native_window_set_usage(
+ mNativeWindow.get(),
+ GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
+ | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP));
+
+ CHECK_EQ(0,
+ native_window_set_scaling_mode(
+ mNativeWindow.get(),
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW));
+
+ // Width must be multiple of 32???
+ CHECK_EQ(0, native_window_set_buffers_geometry(
+ mNativeWindow.get(),
+ bufWidth,
+ bufHeight,
+ halFormat));
+
+ uint32_t transform;
+ switch (rotationDegrees) {
+ case 0: transform = 0; break;
+ case 90: transform = HAL_TRANSFORM_ROT_90; break;
+ case 180: transform = HAL_TRANSFORM_ROT_180; break;
+ case 270: transform = HAL_TRANSFORM_ROT_270; break;
+ default: transform = 0; break;
+ }
+
+ if (transform) {
+ CHECK_EQ(0, native_window_set_buffers_transform(
+ mNativeWindow.get(), transform));
+ }
+}
+
+SoftwareRenderer::~SoftwareRenderer() {
+ delete mConverter;
+ mConverter = NULL;
+}
+
+static int ALIGN(int x, int y) {
+ // y must be a power of 2.
+ return (x + y - 1) & ~(y - 1);
+}
+
+void SoftwareRenderer::render(
+ const void *data, size_t size, void *platformPrivate) {
+ ANativeWindowBuffer *buf;
+ int err;
+ if ((err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf)) != 0) {
+ ALOGW("Surface::dequeueBuffer returned error %d", err);
+ return;
+ }
+
+ CHECK_EQ(0, mNativeWindow->lockBuffer(mNativeWindow.get(), buf));
+
+ GraphicBufferMapper &mapper = GraphicBufferMapper::get();
+
+ Rect bounds(mCropWidth, mCropHeight);
+
+ void *dst;
+ CHECK_EQ(0, mapper.lock(
+ buf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst));
+
+ if (mConverter) {
+ mConverter->convert(
+ data,
+ mWidth, mHeight,
+ mCropLeft, mCropTop, mCropRight, mCropBottom,
+ dst,
+ buf->stride, buf->height,
+ 0, 0, mCropWidth - 1, mCropHeight - 1);
+ } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar) {
+ const uint8_t *src_y = (const uint8_t *)data;
+ const uint8_t *src_u = (const uint8_t *)data + mWidth * mHeight;
+ const uint8_t *src_v = src_u + (mWidth / 2 * mHeight / 2);
+
+ uint8_t *dst_y = (uint8_t *)dst;
+ size_t dst_y_size = buf->stride * buf->height;
+ size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
+ size_t dst_c_size = dst_c_stride * buf->height / 2;
+ uint8_t *dst_v = dst_y + dst_y_size;
+ uint8_t *dst_u = dst_v + dst_c_size;
+
+ for (int y = 0; y < mCropHeight; ++y) {
+ memcpy(dst_y, src_y, mCropWidth);
+
+ src_y += mWidth;
+ dst_y += buf->stride;
+ }
+
+ for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
+ memcpy(dst_u, src_u, (mCropWidth + 1) / 2);
+ memcpy(dst_v, src_v, (mCropWidth + 1) / 2);
+
+ src_u += mWidth / 2;
+ src_v += mWidth / 2;
+ dst_u += dst_c_stride;
+ dst_v += dst_c_stride;
+ }
+ } else {
+ CHECK_EQ(mColorFormat, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar);
+
+ const uint8_t *src_y =
+ (const uint8_t *)data;
+
+ const uint8_t *src_uv =
+ (const uint8_t *)data + mWidth * (mHeight - mCropTop / 2);
+
+ uint8_t *dst_y = (uint8_t *)dst;
+
+ size_t dst_y_size = buf->stride * buf->height;
+ size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
+ size_t dst_c_size = dst_c_stride * buf->height / 2;
+ uint8_t *dst_v = dst_y + dst_y_size;
+ uint8_t *dst_u = dst_v + dst_c_size;
+
+ for (int y = 0; y < mCropHeight; ++y) {
+ memcpy(dst_y, src_y, mCropWidth);
+
+ src_y += mWidth;
+ dst_y += buf->stride;
+ }
+
+ for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
+ size_t tmp = (mCropWidth + 1) / 2;
+ for (size_t x = 0; x < tmp; ++x) {
+ dst_u[x] = src_uv[2 * x];
+ dst_v[x] = src_uv[2 * x + 1];
+ }
+
+ src_uv += mWidth;
+ dst_u += dst_c_stride;
+ dst_v += dst_c_stride;
+ }
+ }
+
+ CHECK_EQ(0, mapper.unlock(buf->handle));
+
+ if ((err = mNativeWindow->queueBuffer(mNativeWindow.get(), buf)) != 0) {
+ ALOGW("Surface::queueBuffer returned error %d", err);
+ }
+ buf = NULL;
+}
+
+} // namespace android
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/ABitReader.cpp b/media/libstagefright/foundation/ABitReader.cpp
new file mode 100644
index 0000000..5499c32
--- /dev/null
+++ b/media/libstagefright/foundation/ABitReader.cpp
@@ -0,0 +1,102 @@
+/*
+ * 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(n, 32u);
+
+ while (mNumBitsLeft + n > 32) {
+ mNumBitsLeft -= 8;
+ --mData;
+ ++mSize;
+ }
+
+ mReservoir = (mReservoir >> n) | (x << (32 - n));
+ mNumBitsLeft += n;
+}
+
+size_t ABitReader::numBitsLeft() const {
+ return mSize * 8 + mNumBitsLeft;
+}
+
+const uint8_t *ABitReader::data() const {
+ return mData - (mNumBitsLeft + 7) / 8;
+}
+
+} // 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/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/AHierarchicalStateMachine.cpp b/media/libstagefright/foundation/AHierarchicalStateMachine.cpp
new file mode 100644
index 0000000..40c5a3c
--- /dev/null
+++ b/media/libstagefright/foundation/AHierarchicalStateMachine.cpp
@@ -0,0 +1,113 @@
+/*
+ * 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 <media/stagefright/foundation/AHierarchicalStateMachine.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+AState::AState(const sp<AState> &parentState)
+ : mParentState(parentState) {
+}
+
+AState::~AState() {
+}
+
+sp<AState> AState::parentState() {
+ return mParentState;
+}
+
+void AState::stateEntered() {
+}
+
+void AState::stateExited() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+AHierarchicalStateMachine::AHierarchicalStateMachine() {
+}
+
+AHierarchicalStateMachine::~AHierarchicalStateMachine() {
+}
+
+void AHierarchicalStateMachine::onMessageReceived(const sp<AMessage> &msg) {
+ sp<AState> save = mState;
+
+ sp<AState> cur = mState;
+ while (cur != NULL && !cur->onMessageReceived(msg)) {
+ // If you claim not to have handled the message you shouldn't
+ // have called setState...
+ CHECK(save == mState);
+
+ cur = cur->parentState();
+ }
+
+ if (cur != NULL) {
+ return;
+ }
+
+ ALOGW("Warning message %s unhandled in root state.",
+ msg->debugString().c_str());
+}
+
+void AHierarchicalStateMachine::changeState(const sp<AState> &state) {
+ if (state == mState) {
+ // Quick exit for the easy case.
+ return;
+ }
+
+ Vector<sp<AState> > A;
+ sp<AState> cur = mState;
+ for (;;) {
+ A.push(cur);
+ if (cur == NULL) {
+ break;
+ }
+ cur = cur->parentState();
+ }
+
+ Vector<sp<AState> > B;
+ cur = state;
+ for (;;) {
+ B.push(cur);
+ if (cur == NULL) {
+ break;
+ }
+ cur = cur->parentState();
+ }
+
+ // Remove the common tail.
+ while (A.size() > 0 && B.size() > 0 && A.top() == B.top()) {
+ A.pop();
+ B.pop();
+ }
+
+ mState = state;
+
+ for (size_t i = 0; i < A.size(); ++i) {
+ A.editItemAt(i)->stateExited();
+ }
+
+ for (size_t i = B.size(); i-- > 0;) {
+ B.editItemAt(i)->stateEntered();
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
new file mode 100644
index 0000000..a5b316d
--- /dev/null
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -0,0 +1,222 @@
+/*
+ * 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),
+ mThreadId(NULL) {
+ }
+
+ virtual status_t readyToRun() {
+ mThreadId = androidGetThreadId();
+
+ return Thread::readyToRun();
+ }
+
+ virtual bool threadLoop() {
+ return mLooper->loop();
+ }
+
+ bool isCurrentThread() const {
+ return mThreadId == androidGetThreadId();
+ }
+
+protected:
+ virtual ~LooperThread() {}
+
+private:
+ ALooper *mLooper;
+ android_thread_id_t mThreadId;
+
+ 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();
+}
+
+void ALooper::setName(const char *name) {
+ mName = name;
+}
+
+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(
+ mName.empty() ? "ALooper" : mName.c_str(), 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->isCurrentThread()) {
+ // If not running locally and this thread _is_ the looper thread,
+ // the loop() function will return and never be called again.
+ 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);
+
+ // NOTE: It's important to note that at this point our "ALooper" object
+ // may no longer exist (its final reference may have gone away while
+ // delivering the message). We have made sure, however, that loop()
+ // won't be called again.
+
+ return true;
+}
+
+} // namespace android
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp
new file mode 100644
index 0000000..dff931d
--- /dev/null
+++ b/media/libstagefright/foundation/ALooperRoster.cpp
@@ -0,0 +1,189 @@
+/*
+ * 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),
+ mNextReplyID(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);
+
+ if (index < 0) {
+ return;
+ }
+
+ const HandlerInfo &info = mHandlers.valueAt(index);
+
+ sp<AHandler> handler = info.mHandler.promote();
+
+ if (handler != NULL) {
+ handler->setID(0);
+ }
+
+ mHandlers.removeItemsAt(index);
+}
+
+status_t ALooperRoster::postMessage(
+ const sp<AMessage> &msg, int64_t delayUs) {
+ Mutex::Autolock autoLock(mLock);
+ return postMessage_l(msg, delayUs);
+}
+
+status_t ALooperRoster::postMessage_l(
+ const sp<AMessage> &msg, int64_t delayUs) {
+ ssize_t index = mHandlers.indexOfKey(msg->target());
+
+ if (index < 0) {
+ ALOGW("failed to post message. Target handler not registered.");
+ return -ENOENT;
+ }
+
+ const HandlerInfo &info = mHandlers.valueAt(index);
+
+ sp<ALooper> looper = info.mLooper.promote();
+
+ if (looper == NULL) {
+ ALOGW("failed to post message. "
+ "Target handler %d still registered, but object gone.",
+ msg->target());
+
+ mHandlers.removeItemsAt(index);
+ return -ENOENT;
+ }
+
+ looper->post(msg, delayUs);
+
+ return OK;
+}
+
+void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
+ sp<AHandler> handler;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+
+ ssize_t index = mHandlers.indexOfKey(msg->target());
+
+ if (index < 0) {
+ ALOGW("failed to deliver message. Target handler not registered.");
+ return;
+ }
+
+ const HandlerInfo &info = mHandlers.valueAt(index);
+ handler = info.mHandler.promote();
+
+ if (handler == NULL) {
+ ALOGW("failed to deliver message. "
+ "Target handler %d registered, but object gone.",
+ msg->target());
+
+ 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;
+}
+
+status_t ALooperRoster::postAndAwaitResponse(
+ const sp<AMessage> &msg, sp<AMessage> *response) {
+ Mutex::Autolock autoLock(mLock);
+
+ uint32_t replyID = mNextReplyID++;
+
+ msg->setInt32("replyID", replyID);
+
+ status_t err = postMessage_l(msg, 0 /* delayUs */);
+
+ if (err != OK) {
+ response->clear();
+ return err;
+ }
+
+ ssize_t index;
+ while ((index = mReplies.indexOfKey(replyID)) < 0) {
+ mRepliesCondition.wait(mLock);
+ }
+
+ *response = mReplies.valueAt(index);
+ mReplies.removeItemsAt(index);
+
+ return OK;
+}
+
+void ALooperRoster::postReply(uint32_t replyID, const sp<AMessage> &reply) {
+ Mutex::Autolock autoLock(mLock);
+
+ CHECK(mReplies.indexOfKey(replyID) < 0);
+ mReplies.add(replyID, reply);
+ mRepliesCondition.broadcast();
+}
+
+} // namespace android
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
new file mode 100644
index 0000000..8b01ac6
--- /dev/null
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -0,0 +1,586 @@
+/*
+ * 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 "ABuffer.h"
+#include "ADebug.h"
+#include "ALooperRoster.h"
+#include "AString.h"
+
+#include <binder/Parcel.h>
+
+namespace android {
+
+extern ALooperRoster gLooperRoster;
+
+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:
+ case kTypeBuffer:
+ {
+ 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::setObjectInternal(
+ const char *name, const sp<RefBase> &obj, Type type) {
+ Item *item = allocateItem(name);
+ item->mType = type;
+
+ if (obj != NULL) { obj->incStrong(this); }
+ item->u.refValue = obj.get();
+}
+
+void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
+ setObjectInternal(name, obj, kTypeObject);
+}
+
+void AMessage::setBuffer(const char *name, const sp<ABuffer> &buffer) {
+ setObjectInternal(name, sp<RefBase>(buffer), kTypeBuffer);
+}
+
+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();
+}
+
+void AMessage::setRect(
+ const char *name,
+ int32_t left, int32_t top, int32_t right, int32_t bottom) {
+ Item *item = allocateItem(name);
+ item->mType = kTypeRect;
+
+ item->u.rectValue.mLeft = left;
+ item->u.rectValue.mTop = top;
+ item->u.rectValue.mRight = right;
+ item->u.rectValue.mBottom = bottom;
+}
+
+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::findBuffer(const char *name, sp<ABuffer> *buf) const {
+ const Item *item = findItem(name, kTypeBuffer);
+ if (item) {
+ *buf = (ABuffer *)(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;
+}
+
+bool AMessage::findRect(
+ const char *name,
+ int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const {
+ const Item *item = findItem(name, kTypeRect);
+ if (item == NULL) {
+ return false;
+ }
+
+ *left = item->u.rectValue.mLeft;
+ *top = item->u.rectValue.mTop;
+ *right = item->u.rectValue.mRight;
+ *bottom = item->u.rectValue.mBottom;
+
+ return true;
+}
+
+void AMessage::post(int64_t delayUs) {
+ gLooperRoster.postMessage(this, delayUs);
+}
+
+status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
+ return gLooperRoster.postAndAwaitResponse(this, response);
+}
+
+void AMessage::postReply(uint32_t replyID) {
+ gLooperRoster.postReply(replyID, this);
+}
+
+bool AMessage::senderAwaitsResponse(uint32_t *replyID) const {
+ int32_t tmp;
+ bool found = findInt32("replyID", &tmp);
+
+ if (!found) {
+ return false;
+ }
+
+ *replyID = static_cast<uint32_t>(tmp);
+
+ return true;
+}
+
+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 kTypeBuffer:
+ {
+ to->u.refValue = from->u.refValue;
+ to->u.refValue->incStrong(msg.get());
+ break;
+ }
+
+ case kTypeMessage:
+ {
+ sp<AMessage> copy =
+ static_cast<AMessage *>(from->u.refValue)->dup();
+
+ to->u.refValue = copy.get();
+ 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 kTypeBuffer:
+ tmp = StringPrintf(
+ "ABuffer *%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;
+ case kTypeRect:
+ tmp = StringPrintf(
+ "Rect %s(%d, %d, %d, %d)",
+ item.mName,
+ item.u.rectValue.mLeft,
+ item.u.rectValue.mTop,
+ item.u.rectValue.mRight,
+ item.u.rectValue.mBottom);
+ break;
+ default:
+ TRESPASS();
+ }
+
+ appendIndent(&s, indent);
+ s.append(" ");
+ s.append(tmp);
+ s.append("\n");
+ }
+
+ appendIndent(&s, indent);
+ s.append("}");
+
+ return s;
+}
+
+// static
+sp<AMessage> AMessage::FromParcel(const Parcel &parcel) {
+ int32_t what = parcel.readInt32();
+ sp<AMessage> msg = new AMessage(what);
+
+ msg->mNumItems = static_cast<size_t>(parcel.readInt32());
+
+ for (size_t i = 0; i < msg->mNumItems; ++i) {
+ Item *item = &msg->mItems[i];
+
+ item->mName = AAtomizer::Atomize(parcel.readCString());
+ item->mType = static_cast<Type>(parcel.readInt32());
+
+ switch (item->mType) {
+ case kTypeInt32:
+ {
+ item->u.int32Value = parcel.readInt32();
+ break;
+ }
+
+ case kTypeInt64:
+ {
+ item->u.int64Value = parcel.readInt64();
+ break;
+ }
+
+ case kTypeSize:
+ {
+ item->u.sizeValue = static_cast<size_t>(parcel.readInt32());
+ break;
+ }
+
+ case kTypeFloat:
+ {
+ item->u.floatValue = parcel.readFloat();
+ break;
+ }
+
+ case kTypeDouble:
+ {
+ item->u.doubleValue = parcel.readDouble();
+ break;
+ }
+
+ case kTypeString:
+ {
+ item->u.stringValue = new AString(parcel.readCString());
+ break;
+ }
+
+ case kTypeMessage:
+ {
+ sp<AMessage> subMsg = AMessage::FromParcel(parcel);
+ subMsg->incStrong(msg.get());
+
+ item->u.refValue = subMsg.get();
+ break;
+ }
+
+ default:
+ {
+ ALOGE("This type of object cannot cross process boundaries.");
+ TRESPASS();
+ }
+ }
+ }
+
+ return msg;
+}
+
+void AMessage::writeToParcel(Parcel *parcel) const {
+ parcel->writeInt32(static_cast<int32_t>(mWhat));
+ parcel->writeInt32(static_cast<int32_t>(mNumItems));
+
+ for (size_t i = 0; i < mNumItems; ++i) {
+ const Item &item = mItems[i];
+
+ parcel->writeCString(item.mName);
+ parcel->writeInt32(static_cast<int32_t>(item.mType));
+
+ switch (item.mType) {
+ case kTypeInt32:
+ {
+ parcel->writeInt32(item.u.int32Value);
+ break;
+ }
+
+ case kTypeInt64:
+ {
+ parcel->writeInt64(item.u.int64Value);
+ break;
+ }
+
+ case kTypeSize:
+ {
+ parcel->writeInt32(static_cast<int32_t>(item.u.sizeValue));
+ break;
+ }
+
+ case kTypeFloat:
+ {
+ parcel->writeFloat(item.u.floatValue);
+ break;
+ }
+
+ case kTypeDouble:
+ {
+ parcel->writeDouble(item.u.doubleValue);
+ break;
+ }
+
+ case kTypeString:
+ {
+ parcel->writeCString(item.u.stringValue->c_str());
+ break;
+ }
+
+ case kTypeMessage:
+ {
+ static_cast<AMessage *>(item.u.refValue)->writeToParcel(parcel);
+ break;
+ }
+
+ default:
+ {
+ ALOGE("This type of object cannot cross process boundaries.");
+ TRESPASS();
+ }
+ }
+ }
+}
+
+size_t AMessage::countEntries() const {
+ return mNumItems;
+}
+
+const char *AMessage::getEntryNameAt(size_t index, Type *type) const {
+ if (index >= mNumItems) {
+ *type = kTypeInt32;
+
+ return NULL;
+ }
+
+ *type = mItems[index].mType;
+
+ return mItems[index].mName;
+}
+
+} // namespace android
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
new file mode 100644
index 0000000..dee786d
--- /dev/null
+++ b/media/libstagefright/foundation/AString.cpp
@@ -0,0 +1,341 @@
+/*
+ * 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));
+}
+
+bool AString::endsWith(const char *suffix) const {
+ size_t suffixLen = strlen(suffix);
+
+ if (mSize < suffixLen) {
+ return false;
+ }
+
+ return !strcmp(mData + mSize - suffixLen, suffix);
+}
+
+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..d5025a1
--- /dev/null
+++ b/media/libstagefright/foundation/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ AAtomizer.cpp \
+ ABitReader.cpp \
+ ABuffer.cpp \
+ AHandler.cpp \
+ AHierarchicalStateMachine.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 \
+ libutils \
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE:= libstagefright_foundation
+
+
+
+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..16c1ca5
--- /dev/null
+++ b/media/libstagefright/foundation/hexdump.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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 "hexdump"
+#include <utils/Log.h>
+
+#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('.');
+ }
+ }
+
+ ALOGI("%s", line.c_str());
+
+ offset += 16;
+ }
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/httplive/Android.mk b/media/libstagefright/httplive/Android.mk
new file mode 100644
index 0000000..90cb448
--- /dev/null
+++ b/media/libstagefright/httplive/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ LiveDataSource.cpp \
+ LiveSession.cpp \
+ M3UParser.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/external/openssl/include
+
+LOCAL_MODULE:= libstagefright_httplive
+
+ifeq ($(TARGET_ARCH),arm)
+ LOCAL_CFLAGS += -Wno-psabi
+endif
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/httplive/LiveDataSource.cpp b/media/libstagefright/httplive/LiveDataSource.cpp
new file mode 100644
index 0000000..7560642
--- /dev/null
+++ b/media/libstagefright/httplive/LiveDataSource.cpp
@@ -0,0 +1,173 @@
+/*
+ * 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 "LiveDataSource"
+#include <utils/Log.h>
+
+#include "LiveDataSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+#define SAVE_BACKUP 0
+
+namespace android {
+
+LiveDataSource::LiveDataSource()
+ : mOffset(0),
+ mFinalResult(OK),
+ mBackupFile(NULL) {
+#if SAVE_BACKUP
+ mBackupFile = fopen("/data/misc/backup.ts", "wb");
+ CHECK(mBackupFile != NULL);
+#endif
+}
+
+LiveDataSource::~LiveDataSource() {
+ if (mBackupFile != NULL) {
+ fclose(mBackupFile);
+ mBackupFile = NULL;
+ }
+}
+
+status_t LiveDataSource::initCheck() const {
+ return OK;
+}
+
+size_t LiveDataSource::countQueuedBuffers() {
+ Mutex::Autolock autoLock(mLock);
+
+ return mBufferQueue.size();
+}
+
+ssize_t LiveDataSource::readAtNonBlocking(
+ off64_t offset, void *data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (offset != mOffset) {
+ ALOGE("Attempt at reading non-sequentially from LiveDataSource.");
+ return -EPIPE;
+ }
+
+ size_t totalAvailable = 0;
+ for (List<sp<ABuffer> >::iterator it = mBufferQueue.begin();
+ it != mBufferQueue.end(); ++it) {
+ sp<ABuffer> buffer = *it;
+
+ totalAvailable += buffer->size();
+
+ if (totalAvailable >= size) {
+ break;
+ }
+ }
+
+ if (totalAvailable < size) {
+ return mFinalResult == OK ? -EWOULDBLOCK : mFinalResult;
+ }
+
+ return readAt_l(offset, data, size);
+}
+
+ssize_t LiveDataSource::readAt(off64_t offset, void *data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+ return readAt_l(offset, data, size);
+}
+
+ssize_t LiveDataSource::readAt_l(off64_t offset, void *data, size_t size) {
+ if (offset != mOffset) {
+ ALOGE("Attempt at reading non-sequentially from LiveDataSource.");
+ return -EPIPE;
+ }
+
+ size_t sizeDone = 0;
+
+ while (sizeDone < size) {
+ while (mBufferQueue.empty() && mFinalResult == OK) {
+ mCondition.wait(mLock);
+ }
+
+ if (mBufferQueue.empty()) {
+ if (sizeDone > 0) {
+ mOffset += sizeDone;
+ return sizeDone;
+ }
+
+ return mFinalResult;
+ }
+
+ sp<ABuffer> buffer = *mBufferQueue.begin();
+
+ size_t copy = size - sizeDone;
+
+ if (copy > buffer->size()) {
+ copy = buffer->size();
+ }
+
+ memcpy((uint8_t *)data + sizeDone, buffer->data(), copy);
+
+ sizeDone += copy;
+
+ buffer->setRange(buffer->offset() + copy, buffer->size() - copy);
+
+ if (buffer->size() == 0) {
+ mBufferQueue.erase(mBufferQueue.begin());
+ }
+ }
+
+ mOffset += sizeDone;
+
+ return sizeDone;
+}
+
+void LiveDataSource::queueBuffer(const sp<ABuffer> &buffer) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mFinalResult != OK) {
+ return;
+ }
+
+#if SAVE_BACKUP
+ if (mBackupFile != NULL) {
+ CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mBackupFile),
+ buffer->size());
+ }
+#endif
+
+ mBufferQueue.push_back(buffer);
+ mCondition.broadcast();
+}
+
+void LiveDataSource::queueEOS(status_t finalResult) {
+ CHECK_NE(finalResult, (status_t)OK);
+
+ Mutex::Autolock autoLock(mLock);
+
+ mFinalResult = finalResult;
+ mCondition.broadcast();
+}
+
+void LiveDataSource::reset() {
+ Mutex::Autolock autoLock(mLock);
+
+ // XXX FIXME: If we've done a partial read and waiting for more buffers,
+ // we'll mix old and new data...
+
+ mFinalResult = OK;
+ mBufferQueue.clear();
+}
+
+} // namespace android
diff --git a/media/libstagefright/httplive/LiveDataSource.h b/media/libstagefright/httplive/LiveDataSource.h
new file mode 100644
index 0000000..b7be637
--- /dev/null
+++ b/media/libstagefright/httplive/LiveDataSource.h
@@ -0,0 +1,64 @@
+/*
+ * 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_DATA_SOURCE_H_
+
+#define LIVE_DATA_SOURCE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/DataSource.h>
+#include <utils/threads.h>
+#include <utils/List.h>
+
+namespace android {
+
+struct ABuffer;
+
+struct LiveDataSource : public DataSource {
+ LiveDataSource();
+
+ virtual status_t initCheck() const;
+
+ virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+ ssize_t readAtNonBlocking(off64_t offset, void *data, size_t size);
+
+ void queueBuffer(const sp<ABuffer> &buffer);
+ void queueEOS(status_t finalResult);
+ void reset();
+
+ size_t countQueuedBuffers();
+
+protected:
+ virtual ~LiveDataSource();
+
+private:
+ Mutex mLock;
+ Condition mCondition;
+
+ off64_t mOffset;
+ List<sp<ABuffer> > mBufferQueue;
+ status_t mFinalResult;
+
+ FILE *mBackupFile;
+
+ ssize_t readAt_l(off64_t offset, void *data, size_t size);
+
+ DISALLOW_EVIL_CONSTRUCTORS(LiveDataSource);
+};
+
+} // namespace android
+
+#endif // LIVE_DATA_SOURCE_H_
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
new file mode 100644
index 0000000..0cddd2e
--- /dev/null
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -0,0 +1,943 @@
+/*
+ * 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 "LiveSession"
+#include <utils/Log.h>
+
+#include "include/LiveSession.h"
+
+#include "LiveDataSource.h"
+
+#include "include/M3UParser.h"
+#include "include/HTTPBase.h"
+
+#include <cutils/properties.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
+#include <media/stagefright/MediaErrors.h>
+
+#include <ctype.h>
+#include <openssl/aes.h>
+#include <openssl/md5.h>
+
+namespace android {
+
+LiveSession::LiveSession(uint32_t flags, bool uidValid, uid_t uid)
+ : mFlags(flags),
+ mUIDValid(uidValid),
+ mUID(uid),
+ mDataSource(new LiveDataSource),
+ mHTTPDataSource(
+ HTTPBase::Create(
+ (mFlags & kFlagIncognito)
+ ? HTTPBase::kFlagIncognito
+ : 0)),
+ mPrevBandwidthIndex(-1),
+ mLastPlaylistFetchTimeUs(-1),
+ mSeqNumber(-1),
+ mSeekTimeUs(-1),
+ mNumRetries(0),
+ mDurationUs(-1),
+ mSeekDone(false),
+ mDisconnectPending(false),
+ mMonitorQueueGeneration(0),
+ mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY) {
+ if (mUIDValid) {
+ mHTTPDataSource->setUID(mUID);
+ }
+}
+
+LiveSession::~LiveSession() {
+}
+
+sp<DataSource> LiveSession::getDataSource() {
+ return mDataSource;
+}
+
+void LiveSession::connect(
+ const char *url, const KeyedVector<String8, String8> *headers) {
+ sp<AMessage> msg = new AMessage(kWhatConnect, id());
+ msg->setString("url", url);
+
+ if (headers != NULL) {
+ msg->setPointer(
+ "headers",
+ new KeyedVector<String8, String8>(*headers));
+ }
+
+ msg->post();
+}
+
+void LiveSession::disconnect() {
+ Mutex::Autolock autoLock(mLock);
+ mDisconnectPending = true;
+
+ mHTTPDataSource->disconnect();
+
+ (new AMessage(kWhatDisconnect, id()))->post();
+}
+
+void LiveSession::seekTo(int64_t timeUs) {
+ Mutex::Autolock autoLock(mLock);
+ mSeekDone = false;
+
+ sp<AMessage> msg = new AMessage(kWhatSeek, id());
+ msg->setInt64("timeUs", timeUs);
+ msg->post();
+
+ while (!mSeekDone) {
+ mCondition.wait(mLock);
+ }
+}
+
+void LiveSession::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatConnect:
+ onConnect(msg);
+ break;
+
+ case kWhatDisconnect:
+ onDisconnect();
+ break;
+
+ case kWhatMonitorQueue:
+ {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+
+ if (generation != mMonitorQueueGeneration) {
+ // Stale event
+ break;
+ }
+
+ onMonitorQueue();
+ break;
+ }
+
+ case kWhatSeek:
+ onSeek(msg);
+ break;
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+// static
+int LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) {
+ if (a->mBandwidth < b->mBandwidth) {
+ return -1;
+ } else if (a->mBandwidth == b->mBandwidth) {
+ return 0;
+ }
+
+ return 1;
+}
+
+void LiveSession::onConnect(const sp<AMessage> &msg) {
+ AString url;
+ CHECK(msg->findString("url", &url));
+
+ KeyedVector<String8, String8> *headers = NULL;
+ if (!msg->findPointer("headers", (void **)&headers)) {
+ mExtraHeaders.clear();
+ } else {
+ mExtraHeaders = *headers;
+
+ delete headers;
+ headers = NULL;
+ }
+
+ if (!(mFlags & kFlagIncognito)) {
+ ALOGI("onConnect '%s'", url.c_str());
+ } else {
+ ALOGI("onConnect <URL suppressed>");
+ }
+
+ mMasterURL = url;
+
+ bool dummy;
+ sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &dummy);
+
+ if (playlist == NULL) {
+ ALOGE("unable to fetch master playlist '%s'.", url.c_str());
+
+ mDataSource->queueEOS(ERROR_IO);
+ return;
+ }
+
+ if (playlist->isVariantPlaylist()) {
+ for (size_t i = 0; i < playlist->size(); ++i) {
+ BandwidthItem item;
+
+ sp<AMessage> meta;
+ playlist->itemAt(i, &item.mURI, &meta);
+
+ unsigned long bandwidth;
+ CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
+
+ mBandwidthItems.push(item);
+ }
+
+ CHECK_GT(mBandwidthItems.size(), 0u);
+
+ mBandwidthItems.sort(SortByBandwidth);
+ }
+
+ postMonitorQueue();
+}
+
+void LiveSession::onDisconnect() {
+ ALOGI("onDisconnect");
+
+ mDataSource->queueEOS(ERROR_END_OF_STREAM);
+
+ Mutex::Autolock autoLock(mLock);
+ mDisconnectPending = false;
+}
+
+status_t LiveSession::fetchFile(
+ const char *url, sp<ABuffer> *out,
+ int64_t range_offset, int64_t range_length) {
+ *out = NULL;
+
+ sp<DataSource> source;
+
+ if (!strncasecmp(url, "file://", 7)) {
+ source = new FileSource(url + 7);
+ } else if (strncasecmp(url, "http://", 7)
+ && strncasecmp(url, "https://", 8)) {
+ return ERROR_UNSUPPORTED;
+ } else {
+ {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mDisconnectPending) {
+ return ERROR_IO;
+ }
+ }
+
+ KeyedVector<String8, String8> headers = mExtraHeaders;
+ if (range_offset > 0 || range_length >= 0) {
+ headers.add(
+ String8("Range"),
+ String8(
+ StringPrintf(
+ "bytes=%lld-%s",
+ range_offset,
+ range_length < 0
+ ? "" : StringPrintf("%lld", range_offset + range_length - 1).c_str()).c_str()));
+ }
+ status_t err = mHTTPDataSource->connect(url, &headers);
+
+ if (err != OK) {
+ return err;
+ }
+
+ source = mHTTPDataSource;
+ }
+
+ off64_t size;
+ status_t err = source->getSize(&size);
+
+ if (err != OK) {
+ size = 65536;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(size);
+ buffer->setRange(0, 0);
+
+ for (;;) {
+ size_t bufferRemaining = buffer->capacity() - buffer->size();
+
+ if (bufferRemaining == 0) {
+ bufferRemaining = 32768;
+
+ ALOGV("increasing download buffer to %d bytes",
+ buffer->size() + bufferRemaining);
+
+ sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
+ memcpy(copy->data(), buffer->data(), buffer->size());
+ copy->setRange(0, buffer->size());
+
+ buffer = copy;
+ }
+
+ size_t maxBytesToRead = bufferRemaining;
+ if (range_length >= 0) {
+ int64_t bytesLeftInRange = range_length - buffer->size();
+ if (bytesLeftInRange < maxBytesToRead) {
+ maxBytesToRead = bytesLeftInRange;
+
+ if (bytesLeftInRange == 0) {
+ break;
+ }
+ }
+ }
+
+ ssize_t n = source->readAt(
+ buffer->size(), buffer->data() + buffer->size(),
+ maxBytesToRead);
+
+ if (n < 0) {
+ return n;
+ }
+
+ if (n == 0) {
+ break;
+ }
+
+ buffer->setRange(0, buffer->size() + (size_t)n);
+ }
+
+ *out = buffer;
+
+ return OK;
+}
+
+sp<M3UParser> LiveSession::fetchPlaylist(const char *url, bool *unchanged) {
+ *unchanged = false;
+
+ sp<ABuffer> buffer;
+ status_t err = fetchFile(url, &buffer);
+
+ if (err != OK) {
+ return NULL;
+ }
+
+ // MD5 functionality is not available on the simulator, treat all
+ // playlists as changed.
+
+#if defined(HAVE_ANDROID_OS)
+ uint8_t hash[16];
+
+ MD5_CTX m;
+ MD5_Init(&m);
+ MD5_Update(&m, buffer->data(), buffer->size());
+
+ MD5_Final(hash, &m);
+
+ if (mPlaylist != NULL && !memcmp(hash, mPlaylistHash, 16)) {
+ // playlist unchanged
+
+ if (mRefreshState != THIRD_UNCHANGED_RELOAD_ATTEMPT) {
+ mRefreshState = (RefreshState)(mRefreshState + 1);
+ }
+
+ *unchanged = true;
+
+ ALOGV("Playlist unchanged, refresh state is now %d",
+ (int)mRefreshState);
+
+ return NULL;
+ }
+
+ memcpy(mPlaylistHash, hash, sizeof(hash));
+
+ mRefreshState = INITIAL_MINIMUM_RELOAD_DELAY;
+#endif
+
+ sp<M3UParser> playlist =
+ new M3UParser(url, buffer->data(), buffer->size());
+
+ if (playlist->initCheck() != OK) {
+ ALOGE("failed to parse .m3u8 playlist");
+
+ return NULL;
+ }
+
+ return playlist;
+}
+
+static double uniformRand() {
+ return (double)rand() / RAND_MAX;
+}
+
+size_t LiveSession::getBandwidthIndex() {
+ if (mBandwidthItems.size() == 0) {
+ return 0;
+ }
+
+#if 1
+ int32_t bandwidthBps;
+ if (mHTTPDataSource != NULL
+ && mHTTPDataSource->estimateBandwidth(&bandwidthBps)) {
+ ALOGV("bandwidth estimated at %.2f kbps", bandwidthBps / 1024.0f);
+ } else {
+ ALOGV("no bandwidth estimate.");
+ return 0; // Pick the lowest bandwidth stream by default.
+ }
+
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.httplive.max-bw", value, NULL)) {
+ char *end;
+ long maxBw = strtoul(value, &end, 10);
+ if (end > value && *end == '\0') {
+ if (maxBw > 0 && bandwidthBps > maxBw) {
+ ALOGV("bandwidth capped to %ld bps", maxBw);
+ bandwidthBps = maxBw;
+ }
+ }
+ }
+
+ // Consider only 80% of the available bandwidth usable.
+ bandwidthBps = (bandwidthBps * 8) / 10;
+
+ // Pick the highest bandwidth stream below or equal to estimated bandwidth.
+
+ size_t index = mBandwidthItems.size() - 1;
+ while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth
+ > (size_t)bandwidthBps) {
+ --index;
+ }
+#elif 0
+ // Change bandwidth at random()
+ size_t index = uniformRand() * mBandwidthItems.size();
+#elif 0
+ // There's a 50% chance to stay on the current bandwidth and
+ // a 50% chance to switch to the next higher bandwidth (wrapping around
+ // to lowest)
+ const size_t kMinIndex = 0;
+
+ size_t index;
+ if (mPrevBandwidthIndex < 0) {
+ index = kMinIndex;
+ } else if (uniformRand() < 0.5) {
+ index = (size_t)mPrevBandwidthIndex;
+ } else {
+ index = mPrevBandwidthIndex + 1;
+ if (index == mBandwidthItems.size()) {
+ index = kMinIndex;
+ }
+ }
+#elif 0
+ // Pick the highest bandwidth stream below or equal to 1.2 Mbit/sec
+
+ size_t index = mBandwidthItems.size() - 1;
+ while (index > 0 && mBandwidthItems.itemAt(index).mBandwidth > 1200000) {
+ --index;
+ }
+#else
+ size_t index = mBandwidthItems.size() - 1; // Highest bandwidth stream
+#endif
+
+ return index;
+}
+
+bool LiveSession::timeToRefreshPlaylist(int64_t nowUs) const {
+ if (mPlaylist == NULL) {
+ CHECK_EQ((int)mRefreshState, (int)INITIAL_MINIMUM_RELOAD_DELAY);
+ return true;
+ }
+
+ int32_t targetDurationSecs;
+ CHECK(mPlaylist->meta()->findInt32("target-duration", &targetDurationSecs));
+
+ int64_t targetDurationUs = targetDurationSecs * 1000000ll;
+
+ int64_t minPlaylistAgeUs;
+
+ switch (mRefreshState) {
+ case INITIAL_MINIMUM_RELOAD_DELAY:
+ {
+ size_t n = mPlaylist->size();
+ if (n > 0) {
+ sp<AMessage> itemMeta;
+ CHECK(mPlaylist->itemAt(n - 1, NULL /* uri */, &itemMeta));
+
+ int64_t itemDurationUs;
+ CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
+
+ minPlaylistAgeUs = itemDurationUs;
+ break;
+ }
+
+ // fall through
+ }
+
+ case FIRST_UNCHANGED_RELOAD_ATTEMPT:
+ {
+ minPlaylistAgeUs = targetDurationUs / 2;
+ break;
+ }
+
+ case SECOND_UNCHANGED_RELOAD_ATTEMPT:
+ {
+ minPlaylistAgeUs = (targetDurationUs * 3) / 2;
+ break;
+ }
+
+ case THIRD_UNCHANGED_RELOAD_ATTEMPT:
+ {
+ minPlaylistAgeUs = targetDurationUs * 3;
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+
+ return mLastPlaylistFetchTimeUs + minPlaylistAgeUs <= nowUs;
+}
+
+void LiveSession::onDownloadNext() {
+ size_t bandwidthIndex = getBandwidthIndex();
+
+rinse_repeat:
+ int64_t nowUs = ALooper::GetNowUs();
+
+ if (mLastPlaylistFetchTimeUs < 0
+ || (ssize_t)bandwidthIndex != mPrevBandwidthIndex
+ || (!mPlaylist->isComplete() && timeToRefreshPlaylist(nowUs))) {
+ AString url;
+ if (mBandwidthItems.size() > 0) {
+ url = mBandwidthItems.editItemAt(bandwidthIndex).mURI;
+ } else {
+ url = mMasterURL;
+ }
+
+ bool firstTime = (mPlaylist == NULL);
+
+ if ((ssize_t)bandwidthIndex != mPrevBandwidthIndex) {
+ // If we switch bandwidths, do not pay any heed to whether
+ // playlists changed since the last time...
+ mPlaylist.clear();
+ }
+
+ bool unchanged;
+ sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &unchanged);
+ if (playlist == NULL) {
+ if (unchanged) {
+ // We succeeded in fetching the playlist, but it was
+ // unchanged from the last time we tried.
+ } else {
+ ALOGE("failed to load playlist at url '%s'", url.c_str());
+ mDataSource->queueEOS(ERROR_IO);
+ return;
+ }
+ } else {
+ mPlaylist = playlist;
+ }
+
+ if (firstTime) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (!mPlaylist->isComplete()) {
+ mDurationUs = -1;
+ } else {
+ mDurationUs = 0;
+ for (size_t i = 0; i < mPlaylist->size(); ++i) {
+ sp<AMessage> itemMeta;
+ CHECK(mPlaylist->itemAt(
+ i, NULL /* uri */, &itemMeta));
+
+ int64_t itemDurationUs;
+ CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
+
+ mDurationUs += itemDurationUs;
+ }
+ }
+ }
+
+ mLastPlaylistFetchTimeUs = ALooper::GetNowUs();
+ }
+
+ int32_t firstSeqNumberInPlaylist;
+ if (mPlaylist->meta() == NULL || !mPlaylist->meta()->findInt32(
+ "media-sequence", &firstSeqNumberInPlaylist)) {
+ firstSeqNumberInPlaylist = 0;
+ }
+
+ bool seekDiscontinuity = false;
+ bool explicitDiscontinuity = false;
+ bool bandwidthChanged = false;
+
+ if (mSeekTimeUs >= 0) {
+ if (mPlaylist->isComplete()) {
+ size_t index = 0;
+ int64_t segmentStartUs = 0;
+ while (index < mPlaylist->size()) {
+ sp<AMessage> itemMeta;
+ CHECK(mPlaylist->itemAt(
+ index, NULL /* uri */, &itemMeta));
+
+ int64_t itemDurationUs;
+ CHECK(itemMeta->findInt64("durationUs", &itemDurationUs));
+
+ if (mSeekTimeUs < segmentStartUs + itemDurationUs) {
+ break;
+ }
+
+ segmentStartUs += itemDurationUs;
+ ++index;
+ }
+
+ if (index < mPlaylist->size()) {
+ int32_t newSeqNumber = firstSeqNumberInPlaylist + index;
+
+ if (newSeqNumber != mSeqNumber) {
+ ALOGI("seeking to seq no %d", newSeqNumber);
+
+ mSeqNumber = newSeqNumber;
+
+ mDataSource->reset();
+
+ // reseting the data source will have had the
+ // side effect of discarding any previously queued
+ // bandwidth change discontinuity.
+ // Therefore we'll need to treat these seek
+ // discontinuities as involving a bandwidth change
+ // even if they aren't directly.
+ seekDiscontinuity = true;
+ bandwidthChanged = true;
+ }
+ }
+ }
+
+ mSeekTimeUs = -1;
+
+ Mutex::Autolock autoLock(mLock);
+ mSeekDone = true;
+ mCondition.broadcast();
+ }
+
+ if (mSeqNumber < 0) {
+ mSeqNumber = firstSeqNumberInPlaylist;
+ }
+
+ int32_t lastSeqNumberInPlaylist =
+ firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1;
+
+ if (mSeqNumber < firstSeqNumberInPlaylist
+ || mSeqNumber > lastSeqNumberInPlaylist) {
+ if (mPrevBandwidthIndex != (ssize_t)bandwidthIndex) {
+ // Go back to the previous bandwidth.
+
+ ALOGI("new bandwidth does not have the sequence number "
+ "we're looking for, switching back to previous bandwidth");
+
+ mLastPlaylistFetchTimeUs = -1;
+ bandwidthIndex = mPrevBandwidthIndex;
+ goto rinse_repeat;
+ }
+
+ if (!mPlaylist->isComplete() && mNumRetries < kMaxNumRetries) {
+ ++mNumRetries;
+
+ if (mSeqNumber > lastSeqNumberInPlaylist) {
+ mLastPlaylistFetchTimeUs = -1;
+ postMonitorQueue(3000000ll);
+ return;
+ }
+
+ // we've missed the boat, let's start from the lowest sequence
+ // number available and signal a discontinuity.
+
+ ALOGI("We've missed the boat, restarting playback.");
+ mSeqNumber = lastSeqNumberInPlaylist;
+ explicitDiscontinuity = true;
+
+ // fall through
+ } else {
+ ALOGE("Cannot find sequence number %d in playlist "
+ "(contains %d - %d)",
+ mSeqNumber, firstSeqNumberInPlaylist,
+ firstSeqNumberInPlaylist + mPlaylist->size() - 1);
+
+ mDataSource->queueEOS(ERROR_END_OF_STREAM);
+ return;
+ }
+ }
+
+ mNumRetries = 0;
+
+ AString uri;
+ sp<AMessage> itemMeta;
+ CHECK(mPlaylist->itemAt(
+ mSeqNumber - firstSeqNumberInPlaylist,
+ &uri,
+ &itemMeta));
+
+ int32_t val;
+ if (itemMeta->findInt32("discontinuity", &val) && val != 0) {
+ explicitDiscontinuity = true;
+ }
+
+ int64_t range_offset, range_length;
+ if (!itemMeta->findInt64("range-offset", &range_offset)
+ || !itemMeta->findInt64("range-length", &range_length)) {
+ range_offset = 0;
+ range_length = -1;
+ }
+
+ sp<ABuffer> buffer;
+ status_t err = fetchFile(uri.c_str(), &buffer, range_offset, range_length);
+ if (err != OK) {
+ ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str());
+ mDataSource->queueEOS(err);
+ return;
+ }
+
+ CHECK(buffer != NULL);
+
+ err = decryptBuffer(mSeqNumber - firstSeqNumberInPlaylist, buffer);
+
+ if (err != OK) {
+ ALOGE("decryptBuffer failed w/ error %d", err);
+
+ mDataSource->queueEOS(err);
+ return;
+ }
+
+ if (buffer->size() == 0 || buffer->data()[0] != 0x47) {
+ // Not a transport stream???
+
+ ALOGE("This doesn't look like a transport stream...");
+
+ mBandwidthItems.removeAt(bandwidthIndex);
+
+ if (mBandwidthItems.isEmpty()) {
+ mDataSource->queueEOS(ERROR_UNSUPPORTED);
+ return;
+ }
+
+ ALOGI("Retrying with a different bandwidth stream.");
+
+ mLastPlaylistFetchTimeUs = -1;
+ bandwidthIndex = getBandwidthIndex();
+ mPrevBandwidthIndex = bandwidthIndex;
+ mSeqNumber = -1;
+
+ goto rinse_repeat;
+ }
+
+ if ((size_t)mPrevBandwidthIndex != bandwidthIndex) {
+ bandwidthChanged = true;
+ }
+
+ if (mPrevBandwidthIndex < 0) {
+ // Don't signal a bandwidth change at the very beginning of
+ // playback.
+ bandwidthChanged = false;
+ }
+
+ if (seekDiscontinuity || explicitDiscontinuity || bandwidthChanged) {
+ // Signal discontinuity.
+
+ ALOGI("queueing discontinuity (seek=%d, explicit=%d, bandwidthChanged=%d)",
+ seekDiscontinuity, explicitDiscontinuity, bandwidthChanged);
+
+ sp<ABuffer> tmp = new ABuffer(188);
+ memset(tmp->data(), 0, tmp->size());
+
+ // signal a 'hard' discontinuity for explicit or bandwidthChanged.
+ tmp->data()[1] = (explicitDiscontinuity || bandwidthChanged) ? 1 : 0;
+
+ mDataSource->queueBuffer(tmp);
+ }
+
+ mDataSource->queueBuffer(buffer);
+
+ mPrevBandwidthIndex = bandwidthIndex;
+ ++mSeqNumber;
+
+ postMonitorQueue();
+}
+
+void LiveSession::onMonitorQueue() {
+ if (mSeekTimeUs >= 0
+ || mDataSource->countQueuedBuffers() < kMaxNumQueuedFragments) {
+ onDownloadNext();
+ } else {
+ postMonitorQueue(1000000ll);
+ }
+}
+
+status_t LiveSession::decryptBuffer(
+ size_t playlistIndex, const sp<ABuffer> &buffer) {
+ sp<AMessage> itemMeta;
+ bool found = false;
+ AString method;
+
+ for (ssize_t i = playlistIndex; i >= 0; --i) {
+ AString uri;
+ CHECK(mPlaylist->itemAt(i, &uri, &itemMeta));
+
+ if (itemMeta->findString("cipher-method", &method)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ method = "NONE";
+ }
+
+ if (method == "NONE") {
+ return OK;
+ } else if (!(method == "AES-128")) {
+ ALOGE("Unsupported cipher method '%s'", method.c_str());
+ return ERROR_UNSUPPORTED;
+ }
+
+ AString keyURI;
+ if (!itemMeta->findString("cipher-uri", &keyURI)) {
+ ALOGE("Missing key uri");
+ return ERROR_MALFORMED;
+ }
+
+ ssize_t index = mAESKeyForURI.indexOfKey(keyURI);
+
+ sp<ABuffer> key;
+ if (index >= 0) {
+ key = mAESKeyForURI.valueAt(index);
+ } else {
+ key = new ABuffer(16);
+
+ sp<HTTPBase> keySource =
+ HTTPBase::Create(
+ (mFlags & kFlagIncognito)
+ ? HTTPBase::kFlagIncognito
+ : 0);
+
+ if (mUIDValid) {
+ keySource->setUID(mUID);
+ }
+
+ status_t err =
+ keySource->connect(
+ keyURI.c_str(),
+ mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
+
+ if (err == OK) {
+ size_t offset = 0;
+ while (offset < 16) {
+ ssize_t n = keySource->readAt(
+ offset, key->data() + offset, 16 - offset);
+ if (n <= 0) {
+ err = ERROR_IO;
+ break;
+ }
+
+ offset += n;
+ }
+ }
+
+ if (err != OK) {
+ ALOGE("failed to fetch cipher key from '%s'.", keyURI.c_str());
+ return ERROR_IO;
+ }
+
+ mAESKeyForURI.add(keyURI, key);
+ }
+
+ AES_KEY aes_key;
+ if (AES_set_decrypt_key(key->data(), 128, &aes_key) != 0) {
+ ALOGE("failed to set AES decryption key.");
+ return UNKNOWN_ERROR;
+ }
+
+ unsigned char aes_ivec[16];
+
+ AString iv;
+ if (itemMeta->findString("cipher-iv", &iv)) {
+ if ((!iv.startsWith("0x") && !iv.startsWith("0X"))
+ || iv.size() != 16 * 2 + 2) {
+ ALOGE("malformed cipher IV '%s'.", iv.c_str());
+ return ERROR_MALFORMED;
+ }
+
+ memset(aes_ivec, 0, sizeof(aes_ivec));
+ for (size_t i = 0; i < 16; ++i) {
+ char c1 = tolower(iv.c_str()[2 + 2 * i]);
+ char c2 = tolower(iv.c_str()[3 + 2 * i]);
+ if (!isxdigit(c1) || !isxdigit(c2)) {
+ ALOGE("malformed cipher IV '%s'.", iv.c_str());
+ return ERROR_MALFORMED;
+ }
+ uint8_t nibble1 = isdigit(c1) ? c1 - '0' : c1 - 'a' + 10;
+ uint8_t nibble2 = isdigit(c2) ? c2 - '0' : c2 - 'a' + 10;
+
+ aes_ivec[i] = nibble1 << 4 | nibble2;
+ }
+ } else {
+ memset(aes_ivec, 0, sizeof(aes_ivec));
+ aes_ivec[15] = mSeqNumber & 0xff;
+ aes_ivec[14] = (mSeqNumber >> 8) & 0xff;
+ aes_ivec[13] = (mSeqNumber >> 16) & 0xff;
+ aes_ivec[12] = (mSeqNumber >> 24) & 0xff;
+ }
+
+ AES_cbc_encrypt(
+ buffer->data(), buffer->data(), buffer->size(),
+ &aes_key, aes_ivec, AES_DECRYPT);
+
+ // hexdump(buffer->data(), buffer->size());
+
+ size_t n = buffer->size();
+ CHECK_GT(n, 0u);
+
+ size_t pad = buffer->data()[n - 1];
+
+ CHECK_GT(pad, 0u);
+ CHECK_LE(pad, 16u);
+ CHECK_GE((size_t)n, pad);
+ for (size_t i = 0; i < pad; ++i) {
+ CHECK_EQ((unsigned)buffer->data()[n - 1 - i], pad);
+ }
+
+ n -= pad;
+
+ buffer->setRange(buffer->offset(), n);
+
+ return OK;
+}
+
+void LiveSession::postMonitorQueue(int64_t delayUs) {
+ sp<AMessage> msg = new AMessage(kWhatMonitorQueue, id());
+ msg->setInt32("generation", ++mMonitorQueueGeneration);
+ msg->post(delayUs);
+}
+
+void LiveSession::onSeek(const sp<AMessage> &msg) {
+ int64_t timeUs;
+ CHECK(msg->findInt64("timeUs", &timeUs));
+
+ mSeekTimeUs = timeUs;
+ postMonitorQueue();
+}
+
+status_t LiveSession::getDuration(int64_t *durationUs) {
+ Mutex::Autolock autoLock(mLock);
+ *durationUs = mDurationUs;
+
+ return OK;
+}
+
+bool LiveSession::isSeekable() {
+ int64_t durationUs;
+ return getDuration(&durationUs) == OK && durationUs >= 0;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
new file mode 100644
index 0000000..7d3cf05
--- /dev/null
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -0,0 +1,542 @@
+/*
+ * 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 "M3UParser"
+#include <utils/Log.h>
+
+#include "include/M3UParser.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.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),
+ mIsComplete(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;
+}
+
+bool M3UParser::isComplete() const {
+ return mIsComplete;
+}
+
+sp<AMessage> M3UParser::meta() {
+ return mMeta;
+}
+
+size_t M3UParser::size() {
+ return mItems.size();
+}
+
+bool M3UParser::itemAt(size_t index, AString *uri, sp<AMessage> *meta) {
+ if (uri) {
+ uri->clear();
+ }
+
+ if (meta) {
+ *meta = NULL;
+ }
+
+ if (index >= mItems.size()) {
+ return false;
+ }
+
+ if (uri) {
+ *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)
+ && strncasecmp("https://", baseURL, 8)
+ && strncasecmp("file://", baseURL, 7)) {
+ // Base URL must be absolute
+ return false;
+ }
+
+ if (!strncasecmp("http://", url, 7) || !strncasecmp("https://", url, 8)) {
+ // "url" is already an absolute URL, ignore base URL.
+ out->setTo(url);
+
+ ALOGV("base:'%s', url:'%s' => '%s'", baseURL, url, out->c_str());
+
+ return true;
+ }
+
+ if (url[0] == '/') {
+ // URL is an absolute path.
+
+ char *protocolEnd = strstr(baseURL, "//") + 2;
+ char *pathStart = strchr(protocolEnd, '/');
+
+ if (pathStart != NULL) {
+ out->setTo(baseURL, pathStart - baseURL);
+ } else {
+ out->setTo(baseURL);
+ }
+
+ out->append(url);
+ } else {
+ // URL is a relative path
+
+ size_t n = strlen(baseURL);
+ if (baseURL[n - 1] == '/') {
+ out->setTo(baseURL);
+ out->append(url);
+ } else {
+ const char *slashPos = strrchr(baseURL, '/');
+
+ if (slashPos > &baseURL[6]) {
+ out->setTo(baseURL, slashPos - baseURL);
+ } else {
+ out->setTo(baseURL);
+ }
+
+ out->append("/");
+ out->append(url);
+ }
+ }
+
+ ALOGV("base:'%s', url:'%s' => '%s'", baseURL, url, out->c_str());
+
+ 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;
+ uint64_t segmentRangeOffset = 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);
+ }
+
+ // ALOGI("#%s#", line.c_str());
+
+ if (line.empty()) {
+ offset = offsetLF + 1;
+ continue;
+ }
+
+ 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("#EXT-X-KEY")) {
+ if (mIsVariantPlaylist) {
+ return ERROR_MALFORMED;
+ }
+ err = parseCipherInfo(line, &itemMeta, mBaseURI);
+ } else if (line.startsWith("#EXT-X-ENDLIST")) {
+ mIsComplete = true;
+ } else if (line.startsWith("#EXTINF")) {
+ if (mIsVariantPlaylist) {
+ return ERROR_MALFORMED;
+ }
+ err = parseMetaDataDuration(line, &itemMeta, "durationUs");
+ } else if (line.startsWith("#EXT-X-DISCONTINUITY")) {
+ if (mIsVariantPlaylist) {
+ return ERROR_MALFORMED;
+ }
+ if (itemMeta == NULL) {
+ itemMeta = new AMessage;
+ }
+ itemMeta->setInt32("discontinuity", true);
+ } else if (line.startsWith("#EXT-X-STREAM-INF")) {
+ if (mMeta != NULL) {
+ return ERROR_MALFORMED;
+ }
+ mIsVariantPlaylist = true;
+ err = parseStreamInf(line, &itemMeta);
+ } else if (line.startsWith("#EXT-X-BYTERANGE")) {
+ if (mIsVariantPlaylist) {
+ return ERROR_MALFORMED;
+ }
+
+ uint64_t length, offset;
+ err = parseByteRange(line, segmentRangeOffset, &length, &offset);
+
+ if (err == OK) {
+ if (itemMeta == NULL) {
+ itemMeta = new AMessage;
+ }
+
+ itemMeta->setInt64("range-offset", offset);
+ itemMeta->setInt64("range-length", length);
+
+ segmentRangeOffset = offset + length;
+ }
+ }
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ if (!line.startsWith("#")) {
+ if (!mIsVariantPlaylist) {
+ int64_t durationUs;
+ if (itemMeta == NULL
+ || !itemMeta->findInt64("durationUs", &durationUs)) {
+ 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::parseMetaDataDuration(
+ const AString &line, sp<AMessage> *meta, const char *key) {
+ ssize_t colonPos = line.find(":");
+
+ if (colonPos < 0) {
+ return ERROR_MALFORMED;
+ }
+
+ double x;
+ status_t err = ParseDouble(line.c_str() + colonPos + 1, &x);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (meta->get() == NULL) {
+ *meta = new AMessage;
+ }
+ (*meta)->setInt64(key, (int64_t)x * 1E6);
+
+ return OK;
+}
+
+// static
+status_t M3UParser::parseStreamInf(
+ const AString &line, sp<AMessage> *meta) {
+ ssize_t colonPos = line.find(":");
+
+ if (colonPos < 0) {
+ return ERROR_MALFORMED;
+ }
+
+ size_t offset = colonPos + 1;
+
+ while (offset < line.size()) {
+ ssize_t end = line.find(",", offset);
+ if (end < 0) {
+ end = line.size();
+ }
+
+ AString attr(line, offset, end - offset);
+ attr.trim();
+
+ offset = end + 1;
+
+ ssize_t equalPos = attr.find("=");
+ if (equalPos < 0) {
+ continue;
+ }
+
+ AString key(attr, 0, equalPos);
+ key.trim();
+
+ AString val(attr, equalPos + 1, attr.size() - equalPos - 1);
+ val.trim();
+
+ ALOGV("key=%s value=%s", key.c_str(), val.c_str());
+
+ if (!strcasecmp("bandwidth", key.c_str())) {
+ const char *s = val.c_str();
+ char *end;
+ unsigned long x = strtoul(s, &end, 10);
+
+ if (end == s || *end != '\0') {
+ // malformed
+ continue;
+ }
+
+ if (meta->get() == NULL) {
+ *meta = new AMessage;
+ }
+ (*meta)->setInt32("bandwidth", x);
+ }
+ }
+
+ return OK;
+}
+
+// Find the next occurence of the character "what" at or after "offset",
+// but ignore occurences between quotation marks.
+// Return the index of the occurrence or -1 if not found.
+static ssize_t FindNextUnquoted(
+ const AString &line, char what, size_t offset) {
+ CHECK_NE((int)what, (int)'"');
+
+ bool quoted = false;
+ while (offset < line.size()) {
+ char c = line.c_str()[offset];
+
+ if (c == '"') {
+ quoted = !quoted;
+ } else if (c == what && !quoted) {
+ return offset;
+ }
+
+ ++offset;
+ }
+
+ return -1;
+}
+
+// static
+status_t M3UParser::parseCipherInfo(
+ const AString &line, sp<AMessage> *meta, const AString &baseURI) {
+ ssize_t colonPos = line.find(":");
+
+ if (colonPos < 0) {
+ return ERROR_MALFORMED;
+ }
+
+ size_t offset = colonPos + 1;
+
+ while (offset < line.size()) {
+ ssize_t end = FindNextUnquoted(line, ',', offset);
+ if (end < 0) {
+ end = line.size();
+ }
+
+ AString attr(line, offset, end - offset);
+ attr.trim();
+
+ offset = end + 1;
+
+ ssize_t equalPos = attr.find("=");
+ if (equalPos < 0) {
+ continue;
+ }
+
+ AString key(attr, 0, equalPos);
+ key.trim();
+
+ AString val(attr, equalPos + 1, attr.size() - equalPos - 1);
+ val.trim();
+
+ ALOGV("key=%s value=%s", key.c_str(), val.c_str());
+
+ key.tolower();
+
+ if (key == "method" || key == "uri" || key == "iv") {
+ if (meta->get() == NULL) {
+ *meta = new AMessage;
+ }
+
+ if (key == "uri") {
+ if (val.size() >= 2
+ && val.c_str()[0] == '"'
+ && val.c_str()[val.size() - 1] == '"') {
+ // Remove surrounding quotes.
+ AString tmp(val, 1, val.size() - 2);
+ val = tmp;
+ }
+
+ AString absURI;
+ if (MakeURL(baseURI.c_str(), val.c_str(), &absURI)) {
+ val = absURI;
+ } else {
+ ALOGE("failed to make absolute url for '%s'.",
+ val.c_str());
+ }
+ }
+
+ key.insert(AString("cipher-"), 0);
+
+ (*meta)->setString(key.c_str(), val.c_str(), val.size());
+ }
+ }
+
+ return OK;
+}
+
+// static
+status_t M3UParser::parseByteRange(
+ const AString &line, uint64_t curOffset,
+ uint64_t *length, uint64_t *offset) {
+ ssize_t colonPos = line.find(":");
+
+ if (colonPos < 0) {
+ return ERROR_MALFORMED;
+ }
+
+ ssize_t atPos = line.find("@", colonPos + 1);
+
+ AString lenStr;
+ if (atPos < 0) {
+ lenStr = AString(line, colonPos + 1, line.size() - colonPos - 1);
+ } else {
+ lenStr = AString(line, colonPos + 1, atPos - colonPos - 1);
+ }
+
+ lenStr.trim();
+
+ const char *s = lenStr.c_str();
+ char *end;
+ *length = strtoull(s, &end, 10);
+
+ if (s == end || *end != '\0') {
+ return ERROR_MALFORMED;
+ }
+
+ if (atPos >= 0) {
+ AString offStr = AString(line, atPos + 1, line.size() - atPos - 1);
+ offStr.trim();
+
+ const char *s = offStr.c_str();
+ *offset = strtoull(s, &end, 10);
+
+ if (s == end || *end != '\0') {
+ return ERROR_MALFORMED;
+ }
+ } else {
+ *offset = curOffset;
+ }
+
+ 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;
+}
+
+// static
+status_t M3UParser::ParseDouble(const char *s, double *x) {
+ char *end;
+ double dval = strtod(s, &end);
+
+ if (end == s || (*end != '\0' && *end != ',')) {
+ return ERROR_MALFORMED;
+ }
+
+ *x = dval;
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/id3/Android.mk b/media/libstagefright/id3/Android.mk
new file mode 100644
index 0000000..ff35d4a
--- /dev/null
+++ b/media/libstagefright/id3/Android.mk
@@ -0,0 +1,28 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ ID3.cpp
+
+LOCAL_MODULE := libstagefright_id3
+
+include $(BUILD_STATIC_LIBRARY)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ testid3.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright libutils libbinder libstagefright_foundation
+
+LOCAL_STATIC_LIBRARIES := \
+ libstagefright_id3
+
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_MODULE := testid3
+
+include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
new file mode 100644
index 0000000..ca14054
--- /dev/null
+++ b/media/libstagefright/id3/ID3.cpp
@@ -0,0 +1,850 @@
+/*
+ * 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 "ID3"
+#include <utils/Log.h>
+
+#include "../include/ID3.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/Utils.h>
+#include <utils/String8.h>
+#include <byteswap.h>
+
+namespace android {
+
+static const size_t kMaxMetadataSize = 3 * 1024 * 1024;
+
+ID3::ID3(const sp<DataSource> &source)
+ : mIsValid(false),
+ mData(NULL),
+ mSize(0),
+ mFirstFrameOffset(0),
+ mVersion(ID3_UNKNOWN) {
+ mIsValid = parseV2(source);
+
+ if (!mIsValid) {
+ mIsValid = parseV1(source);
+ }
+}
+
+ID3::~ID3() {
+ if (mData) {
+ free(mData);
+ mData = NULL;
+ }
+}
+
+bool ID3::isValid() const {
+ return mIsValid;
+}
+
+ID3::Version ID3::version() const {
+ return mVersion;
+}
+
+// static
+bool ID3::ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x) {
+ *x = 0;
+ for (int32_t i = 0; i < 4; ++i) {
+ if (encoded[i] & 0x80) {
+ return false;
+ }
+
+ *x = ((*x) << 7) | encoded[i];
+ }
+
+ return true;
+}
+
+bool ID3::parseV2(const sp<DataSource> &source) {
+struct id3_header {
+ char id[3];
+ uint8_t version_major;
+ uint8_t version_minor;
+ uint8_t flags;
+ uint8_t enc_size[4];
+ };
+
+ id3_header header;
+ if (source->readAt(
+ 0, &header, sizeof(header)) != (ssize_t)sizeof(header)) {
+ return false;
+ }
+
+ if (memcmp(header.id, "ID3", 3)) {
+ return false;
+ }
+
+ if (header.version_major == 0xff || header.version_minor == 0xff) {
+ return false;
+ }
+
+ if (header.version_major == 2) {
+ if (header.flags & 0x3f) {
+ // We only support the 2 high bits, if any of the lower bits are
+ // set, we cannot guarantee to understand the tag format.
+ return false;
+ }
+
+ if (header.flags & 0x40) {
+ // No compression scheme has been decided yet, ignore the
+ // tag if compression is indicated.
+
+ return false;
+ }
+ } else if (header.version_major == 3) {
+ if (header.flags & 0x1f) {
+ // We only support the 3 high bits, if any of the lower bits are
+ // set, we cannot guarantee to understand the tag format.
+ return false;
+ }
+ } else if (header.version_major == 4) {
+ if (header.flags & 0x0f) {
+ // The lower 4 bits are undefined in this spec.
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ size_t size;
+ if (!ParseSyncsafeInteger(header.enc_size, &size)) {
+ return false;
+ }
+
+ if (size > kMaxMetadataSize) {
+ ALOGE("skipping huge ID3 metadata of size %d", size);
+ return false;
+ }
+
+ mData = (uint8_t *)malloc(size);
+
+ if (mData == NULL) {
+ return false;
+ }
+
+ mSize = size;
+
+ if (source->readAt(sizeof(header), mData, mSize) != (ssize_t)mSize) {
+ free(mData);
+ mData = NULL;
+
+ return false;
+ }
+
+ if (header.version_major == 4) {
+ void *copy = malloc(size);
+ memcpy(copy, mData, size);
+
+ bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
+ if (!success) {
+ memcpy(mData, copy, size);
+ mSize = size;
+
+ success = removeUnsynchronizationV2_4(true /* iTunesHack */);
+
+ if (success) {
+ ALOGV("Had to apply the iTunes hack to parse this ID3 tag");
+ }
+ }
+
+ free(copy);
+ copy = NULL;
+
+ if (!success) {
+ free(mData);
+ mData = NULL;
+
+ return false;
+ }
+ } else if (header.flags & 0x80) {
+ ALOGV("removing unsynchronization");
+
+ removeUnsynchronization();
+ }
+
+ mFirstFrameOffset = 0;
+ if (header.version_major == 3 && (header.flags & 0x40)) {
+ // Version 2.3 has an optional extended header.
+
+ if (mSize < 4) {
+ free(mData);
+ mData = NULL;
+
+ return false;
+ }
+
+ size_t extendedHeaderSize = U32_AT(&mData[0]) + 4;
+
+ if (extendedHeaderSize > mSize) {
+ free(mData);
+ mData = NULL;
+
+ return false;
+ }
+
+ mFirstFrameOffset = extendedHeaderSize;
+
+ uint16_t extendedFlags = 0;
+ if (extendedHeaderSize >= 6) {
+ extendedFlags = U16_AT(&mData[4]);
+
+ if (extendedHeaderSize >= 10) {
+ size_t paddingSize = U32_AT(&mData[6]);
+
+ if (mFirstFrameOffset + paddingSize > mSize) {
+ free(mData);
+ mData = NULL;
+
+ return false;
+ }
+
+ mSize -= paddingSize;
+ }
+
+ if (extendedFlags & 0x8000) {
+ ALOGV("have crc");
+ }
+ }
+ } else if (header.version_major == 4 && (header.flags & 0x40)) {
+ // Version 2.4 has an optional extended header, that's different
+ // from Version 2.3's...
+
+ if (mSize < 4) {
+ free(mData);
+ mData = NULL;
+
+ return false;
+ }
+
+ size_t ext_size;
+ if (!ParseSyncsafeInteger(mData, &ext_size)) {
+ free(mData);
+ mData = NULL;
+
+ return false;
+ }
+
+ if (ext_size < 6 || ext_size > mSize) {
+ free(mData);
+ mData = NULL;
+
+ return false;
+ }
+
+ mFirstFrameOffset = ext_size;
+ }
+
+ if (header.version_major == 2) {
+ mVersion = ID3_V2_2;
+ } else if (header.version_major == 3) {
+ mVersion = ID3_V2_3;
+ } else {
+ CHECK_EQ(header.version_major, 4);
+ mVersion = ID3_V2_4;
+ }
+
+ return true;
+}
+
+void ID3::removeUnsynchronization() {
+ for (size_t i = 0; i + 1 < mSize; ++i) {
+ if (mData[i] == 0xff && mData[i + 1] == 0x00) {
+ memmove(&mData[i + 1], &mData[i + 2], mSize - i - 2);
+ --mSize;
+ }
+ }
+}
+
+static void WriteSyncsafeInteger(uint8_t *dst, size_t x) {
+ for (size_t i = 0; i < 4; ++i) {
+ dst[3 - i] = (x & 0x7f);
+ x >>= 7;
+ }
+}
+
+bool ID3::removeUnsynchronizationV2_4(bool iTunesHack) {
+ size_t oldSize = mSize;
+
+ size_t offset = 0;
+ while (offset + 10 <= mSize) {
+ if (!memcmp(&mData[offset], "\0\0\0\0", 4)) {
+ break;
+ }
+
+ size_t dataSize;
+ if (iTunesHack) {
+ dataSize = U32_AT(&mData[offset + 4]);
+ } else if (!ParseSyncsafeInteger(&mData[offset + 4], &dataSize)) {
+ return false;
+ }
+
+ if (offset + dataSize + 10 > mSize) {
+ return false;
+ }
+
+ uint16_t flags = U16_AT(&mData[offset + 8]);
+ uint16_t prevFlags = flags;
+
+ if (flags & 1) {
+ // Strip data length indicator
+
+ memmove(&mData[offset + 10], &mData[offset + 14], mSize - offset - 14);
+ mSize -= 4;
+ dataSize -= 4;
+
+ flags &= ~1;
+ }
+
+ if (flags & 2) {
+ // Unsynchronization added.
+
+ for (size_t i = 0; i + 1 < dataSize; ++i) {
+ if (mData[offset + 10 + i] == 0xff
+ && mData[offset + 11 + i] == 0x00) {
+ memmove(&mData[offset + 11 + i], &mData[offset + 12 + i],
+ mSize - offset - 12 - i);
+ --mSize;
+ --dataSize;
+ }
+ }
+
+ flags &= ~2;
+ }
+
+ if (flags != prevFlags || iTunesHack) {
+ WriteSyncsafeInteger(&mData[offset + 4], dataSize);
+ mData[offset + 8] = flags >> 8;
+ mData[offset + 9] = flags & 0xff;
+ }
+
+ offset += 10 + dataSize;
+ }
+
+ memset(&mData[mSize], 0, oldSize - mSize);
+
+ return true;
+}
+
+ID3::Iterator::Iterator(const ID3 &parent, const char *id)
+ : mParent(parent),
+ mID(NULL),
+ mOffset(mParent.mFirstFrameOffset),
+ mFrameData(NULL),
+ mFrameSize(0) {
+ if (id) {
+ mID = strdup(id);
+ }
+
+ findFrame();
+}
+
+ID3::Iterator::~Iterator() {
+ if (mID) {
+ free(mID);
+ mID = NULL;
+ }
+}
+
+bool ID3::Iterator::done() const {
+ return mFrameData == NULL;
+}
+
+void ID3::Iterator::next() {
+ if (mFrameData == NULL) {
+ return;
+ }
+
+ mOffset += mFrameSize;
+
+ findFrame();
+}
+
+void ID3::Iterator::getID(String8 *id) const {
+ id->setTo("");
+
+ if (mFrameData == NULL) {
+ return;
+ }
+
+ if (mParent.mVersion == ID3_V2_2) {
+ id->setTo((const char *)&mParent.mData[mOffset], 3);
+ } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
+ id->setTo((const char *)&mParent.mData[mOffset], 4);
+ } else {
+ CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
+
+ switch (mOffset) {
+ case 3:
+ id->setTo("TT2");
+ break;
+ case 33:
+ id->setTo("TP1");
+ break;
+ case 63:
+ id->setTo("TAL");
+ break;
+ case 93:
+ id->setTo("TYE");
+ break;
+ case 97:
+ id->setTo("COM");
+ break;
+ case 126:
+ id->setTo("TRK");
+ break;
+ case 127:
+ id->setTo("TCO");
+ break;
+ default:
+ CHECK(!"should not be here.");
+ break;
+ }
+ }
+}
+
+static void convertISO8859ToString8(
+ const uint8_t *data, size_t size,
+ String8 *s) {
+ size_t utf8len = 0;
+ for (size_t i = 0; i < size; ++i) {
+ if (data[i] == '\0') {
+ size = i;
+ break;
+ } else if (data[i] < 0x80) {
+ ++utf8len;
+ } else {
+ utf8len += 2;
+ }
+ }
+
+ if (utf8len == size) {
+ // Only ASCII characters present.
+
+ s->setTo((const char *)data, size);
+ return;
+ }
+
+ char *tmp = new char[utf8len];
+ char *ptr = tmp;
+ for (size_t i = 0; i < size; ++i) {
+ if (data[i] == '\0') {
+ break;
+ } else if (data[i] < 0x80) {
+ *ptr++ = data[i];
+ } else if (data[i] < 0xc0) {
+ *ptr++ = 0xc2;
+ *ptr++ = data[i];
+ } else {
+ *ptr++ = 0xc3;
+ *ptr++ = data[i] - 64;
+ }
+ }
+
+ s->setTo(tmp, utf8len);
+
+ delete[] tmp;
+ tmp = NULL;
+}
+
+// the 2nd argument is used to get the data following the \0 in a comment field
+void ID3::Iterator::getString(String8 *id, String8 *comment) const {
+ getstring(id, false);
+ if (comment != NULL) {
+ getstring(comment, true);
+ }
+}
+
+// comment fields (COM/COMM) contain an initial short descriptor, followed by \0,
+// followed by more data. The data following the \0 can be retrieved by setting
+// "otherdata" to true.
+void ID3::Iterator::getstring(String8 *id, bool otherdata) const {
+ id->setTo("");
+
+ const uint8_t *frameData = mFrameData;
+ if (frameData == NULL) {
+ return;
+ }
+
+ uint8_t encoding = *frameData;
+
+ if (mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1) {
+ if (mOffset == 126 || mOffset == 127) {
+ // Special treatment for the track number and genre.
+ char tmp[16];
+ sprintf(tmp, "%d", (int)*frameData);
+
+ id->setTo(tmp);
+ return;
+ }
+
+ convertISO8859ToString8(frameData, mFrameSize, id);
+ return;
+ }
+
+ size_t n = mFrameSize - getHeaderLength() - 1;
+ if (otherdata) {
+ // skip past the encoding, language, and the 0 separator
+ frameData += 4;
+ int32_t i = n - 4;
+ while(--i >= 0 && *++frameData != 0) ;
+ int skipped = (frameData - mFrameData);
+ if (skipped >= n) {
+ return;
+ }
+ n -= skipped;
+ }
+
+ if (encoding == 0x00) {
+ // ISO 8859-1
+ convertISO8859ToString8(frameData + 1, n, id);
+ } else if (encoding == 0x03) {
+ // UTF-8
+ id->setTo((const char *)(frameData + 1), n);
+ } else if (encoding == 0x02) {
+ // UTF-16 BE, no byte order mark.
+ // API wants number of characters, not number of bytes...
+ int len = n / 2;
+ const char16_t *framedata = (const char16_t *) (frameData + 1);
+ char16_t *framedatacopy = NULL;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ framedatacopy = new char16_t[len];
+ for (int i = 0; i < len; i++) {
+ framedatacopy[i] = bswap_16(framedata[i]);
+ }
+ framedata = framedatacopy;
+#endif
+ id->setTo(framedata, len);
+ if (framedatacopy != NULL) {
+ delete[] framedatacopy;
+ }
+ } else {
+ // UCS-2
+ // API wants number of characters, not number of bytes...
+ int len = n / 2;
+ const char16_t *framedata = (const char16_t *) (frameData + 1);
+ char16_t *framedatacopy = NULL;
+ if (*framedata == 0xfffe) {
+ // endianness marker doesn't match host endianness, convert
+ framedatacopy = new char16_t[len];
+ for (int i = 0; i < len; i++) {
+ framedatacopy[i] = bswap_16(framedata[i]);
+ }
+ framedata = framedatacopy;
+ }
+ // If the string starts with an endianness marker, skip it
+ if (*framedata == 0xfeff) {
+ framedata++;
+ len--;
+ }
+ id->setTo(framedata, len);
+ if (framedatacopy != NULL) {
+ delete[] framedatacopy;
+ }
+ }
+}
+
+const uint8_t *ID3::Iterator::getData(size_t *length) const {
+ *length = 0;
+
+ if (mFrameData == NULL) {
+ return NULL;
+ }
+
+ *length = mFrameSize - getHeaderLength();
+
+ return mFrameData;
+}
+
+size_t ID3::Iterator::getHeaderLength() const {
+ if (mParent.mVersion == ID3_V2_2) {
+ return 6;
+ } else if (mParent.mVersion == ID3_V2_3 || mParent.mVersion == ID3_V2_4) {
+ return 10;
+ } else {
+ CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
+ return 0;
+ }
+}
+
+void ID3::Iterator::findFrame() {
+ for (;;) {
+ mFrameData = NULL;
+ mFrameSize = 0;
+
+ if (mParent.mVersion == ID3_V2_2) {
+ if (mOffset + 6 > mParent.mSize) {
+ return;
+ }
+
+ if (!memcmp(&mParent.mData[mOffset], "\0\0\0", 3)) {
+ return;
+ }
+
+ mFrameSize =
+ (mParent.mData[mOffset + 3] << 16)
+ | (mParent.mData[mOffset + 4] << 8)
+ | mParent.mData[mOffset + 5];
+
+ mFrameSize += 6;
+
+ if (mOffset + mFrameSize > mParent.mSize) {
+ ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
+ mOffset, mFrameSize, mParent.mSize - mOffset - 6);
+ return;
+ }
+
+ mFrameData = &mParent.mData[mOffset + 6];
+
+ if (!mID) {
+ break;
+ }
+
+ char id[4];
+ memcpy(id, &mParent.mData[mOffset], 3);
+ id[3] = '\0';
+
+ if (!strcmp(id, mID)) {
+ break;
+ }
+ } else if (mParent.mVersion == ID3_V2_3
+ || mParent.mVersion == ID3_V2_4) {
+ if (mOffset + 10 > mParent.mSize) {
+ return;
+ }
+
+ if (!memcmp(&mParent.mData[mOffset], "\0\0\0\0", 4)) {
+ return;
+ }
+
+ size_t baseSize;
+ if (mParent.mVersion == ID3_V2_4) {
+ if (!ParseSyncsafeInteger(
+ &mParent.mData[mOffset + 4], &baseSize)) {
+ return;
+ }
+ } else {
+ baseSize = U32_AT(&mParent.mData[mOffset + 4]);
+ }
+
+ mFrameSize = 10 + baseSize;
+
+ if (mOffset + mFrameSize > mParent.mSize) {
+ ALOGV("partial frame at offset %d (size = %d, bytes-remaining = %d)",
+ mOffset, mFrameSize, mParent.mSize - mOffset - 10);
+ return;
+ }
+
+ uint16_t flags = U16_AT(&mParent.mData[mOffset + 8]);
+
+ if ((mParent.mVersion == ID3_V2_4 && (flags & 0x000c))
+ || (mParent.mVersion == ID3_V2_3 && (flags & 0x00c0))) {
+ // Compression or encryption are not supported at this time.
+ // Per-frame unsynchronization and data-length indicator
+ // have already been taken care of.
+
+ ALOGV("Skipping unsupported frame (compression, encryption "
+ "or per-frame unsynchronization flagged");
+
+ mOffset += mFrameSize;
+ continue;
+ }
+
+ mFrameData = &mParent.mData[mOffset + 10];
+
+ if (!mID) {
+ break;
+ }
+
+ char id[5];
+ memcpy(id, &mParent.mData[mOffset], 4);
+ id[4] = '\0';
+
+ if (!strcmp(id, mID)) {
+ break;
+ }
+ } else {
+ CHECK(mParent.mVersion == ID3_V1 || mParent.mVersion == ID3_V1_1);
+
+ if (mOffset >= mParent.mSize) {
+ return;
+ }
+
+ mFrameData = &mParent.mData[mOffset];
+
+ switch (mOffset) {
+ case 3:
+ case 33:
+ case 63:
+ mFrameSize = 30;
+ break;
+ case 93:
+ mFrameSize = 4;
+ break;
+ case 97:
+ if (mParent.mVersion == ID3_V1) {
+ mFrameSize = 30;
+ } else {
+ mFrameSize = 29;
+ }
+ break;
+ case 126:
+ mFrameSize = 1;
+ break;
+ case 127:
+ mFrameSize = 1;
+ break;
+ default:
+ CHECK(!"Should not be here, invalid offset.");
+ break;
+ }
+
+ if (!mID) {
+ break;
+ }
+
+ String8 id;
+ getID(&id);
+
+ if (id == mID) {
+ break;
+ }
+ }
+
+ mOffset += mFrameSize;
+ }
+}
+
+static size_t StringSize(const uint8_t *start, uint8_t encoding) {
+ if (encoding == 0x00 || encoding == 0x03) {
+ // ISO 8859-1 or UTF-8
+ return strlen((const char *)start) + 1;
+ }
+
+ // UCS-2
+ size_t n = 0;
+ while (start[n] != '\0' || start[n + 1] != '\0') {
+ n += 2;
+ }
+
+ return n;
+}
+
+const void *
+ID3::getAlbumArt(size_t *length, String8 *mime) const {
+ *length = 0;
+ mime->setTo("");
+
+ Iterator it(
+ *this,
+ (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) ? "APIC" : "PIC");
+
+ while (!it.done()) {
+ size_t size;
+ const uint8_t *data = it.getData(&size);
+
+ if (mVersion == ID3_V2_3 || mVersion == ID3_V2_4) {
+ uint8_t encoding = data[0];
+ mime->setTo((const char *)&data[1]);
+ size_t mimeLen = strlen((const char *)&data[1]) + 1;
+
+ uint8_t picType = data[1 + mimeLen];
+#if 0
+ if (picType != 0x03) {
+ // Front Cover Art
+ it.next();
+ continue;
+ }
+#endif
+
+ size_t descLen = StringSize(&data[2 + mimeLen], encoding);
+
+ *length = size - 2 - mimeLen - descLen;
+
+ return &data[2 + mimeLen + descLen];
+ } else {
+ uint8_t encoding = data[0];
+
+ if (!memcmp(&data[1], "PNG", 3)) {
+ mime->setTo("image/png");
+ } else if (!memcmp(&data[1], "JPG", 3)) {
+ mime->setTo("image/jpeg");
+ } else if (!memcmp(&data[1], "-->", 3)) {
+ mime->setTo("text/plain");
+ } else {
+ return NULL;
+ }
+
+#if 0
+ uint8_t picType = data[4];
+ if (picType != 0x03) {
+ // Front Cover Art
+ it.next();
+ continue;
+ }
+#endif
+
+ size_t descLen = StringSize(&data[5], encoding);
+
+ *length = size - 5 - descLen;
+
+ return &data[5 + descLen];
+ }
+ }
+
+ return NULL;
+}
+
+bool ID3::parseV1(const sp<DataSource> &source) {
+ const size_t V1_TAG_SIZE = 128;
+
+ off64_t size;
+ if (source->getSize(&size) != OK || size < (off64_t)V1_TAG_SIZE) {
+ return false;
+ }
+
+ mData = (uint8_t *)malloc(V1_TAG_SIZE);
+ if (source->readAt(size - V1_TAG_SIZE, mData, V1_TAG_SIZE)
+ != (ssize_t)V1_TAG_SIZE) {
+ free(mData);
+ mData = NULL;
+
+ return false;
+ }
+
+ if (memcmp("TAG", mData, 3)) {
+ free(mData);
+ mData = NULL;
+
+ return false;
+ }
+
+ mSize = V1_TAG_SIZE;
+ mFirstFrameOffset = 3;
+
+ if (mData[V1_TAG_SIZE - 3] != 0) {
+ mVersion = ID3_V1;
+ } else {
+ mVersion = ID3_V1_1;
+ }
+
+ return true;
+}
+
+} // namespace android
diff --git a/media/libstagefright/id3/testid3.cpp b/media/libstagefright/id3/testid3.cpp
new file mode 100644
index 0000000..bc4572c
--- /dev/null
+++ b/media/libstagefright/id3/testid3.cpp
@@ -0,0 +1,164 @@
+/*
+ * 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/ID3.h"
+
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <dirent.h>
+
+#include <binder/ProcessState.h>
+#include <media/stagefright/FileSource.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+#define MAXPATHLEN 256
+
+using namespace android;
+
+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;
+ }
+}
+
+void scanFile(const char *path) {
+ sp<FileSource> file = new FileSource(path);
+ CHECK_EQ(file->initCheck(), (status_t)OK);
+
+ ID3 tag(file);
+ if (!tag.isValid()) {
+ printf("FAIL %s\n", path);
+ } else {
+ printf("SUCCESS %s\n", path);
+
+ ID3::Iterator it(tag, NULL);
+ while (!it.done()) {
+ String8 id;
+ it.getID(&id);
+
+ CHECK(id.length() > 0);
+ if (id[0] == 'T') {
+ String8 text;
+ it.getString(&text);
+
+ printf(" found text frame '%s': %s\n", id.string(), text.string());
+ } else {
+ printf(" found frame '%s'.\n", id.string());
+ }
+
+ it.next();
+ }
+
+ size_t dataSize;
+ String8 mime;
+ const void *data = tag.getAlbumArt(&dataSize, &mime);
+
+ if (data) {
+ printf("found album art: size=%d mime='%s'\n", dataSize,
+ mime.string());
+
+ hexdump(data, dataSize > 128 ? 128 : dataSize);
+ }
+ }
+}
+
+void scan(const char *path) {
+ struct stat st;
+ if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
+ scanFile(path);
+ return;
+ }
+
+ DIR *dir = opendir(path);
+
+ if (dir == NULL) {
+ return;
+ }
+
+ rewinddir(dir);
+
+ struct dirent *ent;
+ while ((ent = readdir(dir)) != NULL) {
+ if (!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name)) {
+ continue;
+ }
+
+ char newPath[MAXPATHLEN];
+ strcpy(newPath, path);
+ strcat(newPath, "/");
+ strcat(newPath, ent->d_name);
+
+ if (ent->d_type == DT_DIR) {
+ scan(newPath);
+ } else if (ent->d_type == DT_REG) {
+ size_t len = strlen(ent->d_name);
+
+ if (len >= 4
+ && !strcasecmp(ent->d_name + len - 4, ".mp3")) {
+ scanFile(newPath);
+ }
+ }
+ }
+
+ closedir(dir);
+ dir = NULL;
+}
+
+int main(int argc, char **argv) {
+ android::ProcessState::self()->startThreadPool();
+
+ DataSource::RegisterDefaultSniffers();
+
+ for (int i = 1; i < argc; ++i) {
+ scan(argv[i]);
+ }
+
+ return 0;
+}
diff --git a/media/libstagefright/include/AACEncoder.h b/media/libstagefright/include/AACEncoder.h
new file mode 100644
index 0000000..3d5fc60
--- /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;
+
+ 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/AACExtractor.h b/media/libstagefright/include/AACExtractor.h
new file mode 100644
index 0000000..e98ca82
--- /dev/null
+++ b/media/libstagefright/include/AACExtractor.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_EXTRACTOR_H_
+
+#define AAC_EXTRACTOR_H_
+
+#include <media/stagefright/MediaExtractor.h>
+
+#include <utils/Vector.h>
+
+namespace android {
+
+struct AMessage;
+class String8;
+
+class AACExtractor : public MediaExtractor {
+public:
+ AACExtractor(const sp<DataSource> &source, const sp<AMessage> &meta);
+
+ 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 ~AACExtractor();
+
+private:
+ sp<DataSource> mDataSource;
+ sp<MetaData> mMeta;
+ status_t mInitCheck;
+
+ Vector<uint64_t> mOffsetVector;
+ int64_t mFrameDurationUs;
+
+ AACExtractor(const AACExtractor &);
+ AACExtractor &operator=(const AACExtractor &);
+};
+
+bool SniffAAC(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
+} // namespace android
+
+#endif // AAC_EXTRACTOR_H_
diff --git a/media/libstagefright/include/AMRExtractor.h b/media/libstagefright/include/AMRExtractor.h
new file mode 100644
index 0000000..4a1c827
--- /dev/null
+++ b/media/libstagefright/include/AMRExtractor.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef AMR_EXTRACTOR_H_
+
+#define AMR_EXTRACTOR_H_
+
+#include <utils/Errors.h>
+#include <media/stagefright/MediaExtractor.h>
+
+namespace android {
+
+struct AMessage;
+class String8;
+#define OFFSET_TABLE_LEN 300
+
+class AMRExtractor : public MediaExtractor {
+public:
+ AMRExtractor(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 ~AMRExtractor();
+
+private:
+ sp<DataSource> mDataSource;
+ sp<MetaData> mMeta;
+ status_t mInitCheck;
+ bool mIsWide;
+
+ off64_t mOffsetTable[OFFSET_TABLE_LEN]; //5 min
+ size_t mOffsetTableLength;
+
+ AMRExtractor(const AMRExtractor &);
+ AMRExtractor &operator=(const AMRExtractor &);
+};
+
+bool SniffAMR(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
+} // namespace android
+
+#endif // AMR_EXTRACTOR_H_
diff --git a/media/libstagefright/include/AVCEncoder.h b/media/libstagefright/include/AVCEncoder.h
new file mode 100644
index 0000000..83e1f97
--- /dev/null
+++ b/media/libstagefright/include/AVCEncoder.h
@@ -0,0 +1,91 @@
+/*
+ * 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;
+ int64_t mPrevTimestampUs;
+ 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/AVIExtractor.h b/media/libstagefright/include/AVIExtractor.h
new file mode 100644
index 0000000..ff5dcb5
--- /dev/null
+++ b/media/libstagefright/include/AVIExtractor.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 AVI_EXTRACTOR_H_
+
+#define AVI_EXTRACTOR_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct AVIExtractor : public MediaExtractor {
+ AVIExtractor(const sp<DataSource> &dataSource);
+
+ 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 ~AVIExtractor();
+
+private:
+ struct AVISource;
+ struct MP3Splitter;
+
+ struct SampleInfo {
+ uint32_t mOffset;
+ bool mIsKey;
+ };
+
+ struct Track {
+ sp<MetaData> mMeta;
+ Vector<SampleInfo> mSamples;
+ uint32_t mRate;
+ uint32_t mScale;
+
+ // If bytes per sample == 0, each chunk represents a single sample,
+ // otherwise each chunk should me a multiple of bytes-per-sample in
+ // size.
+ uint32_t mBytesPerSample;
+
+ enum Kind {
+ AUDIO,
+ VIDEO,
+ OTHER
+
+ } mKind;
+
+ size_t mNumSyncSamples;
+ size_t mThumbnailSampleSize;
+ ssize_t mThumbnailSampleIndex;
+ size_t mMaxSampleSize;
+
+ // If mBytesPerSample > 0:
+ double mAvgChunkSize;
+ size_t mFirstChunkSize;
+ };
+
+ sp<DataSource> mDataSource;
+ status_t mInitCheck;
+ Vector<Track> mTracks;
+
+ off64_t mMovieOffset;
+ bool mFoundIndex;
+ bool mOffsetsAreAbsolute;
+
+ ssize_t parseChunk(off64_t offset, off64_t size, int depth = 0);
+ status_t parseStreamHeader(off64_t offset, size_t size);
+ status_t parseStreamFormat(off64_t offset, size_t size);
+ status_t parseIndex(off64_t offset, size_t size);
+
+ status_t parseHeaders();
+
+ status_t getSampleInfo(
+ size_t trackIndex, size_t sampleIndex,
+ off64_t *offset, size_t *size, bool *isKey,
+ int64_t *sampleTimeUs);
+
+ status_t getSampleTime(
+ size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs);
+
+ status_t getSampleIndexAtTime(
+ size_t trackIndex,
+ int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
+ size_t *sampleIndex) const;
+
+ status_t addMPEG4CodecSpecificData(size_t trackIndex);
+ status_t addH264CodecSpecificData(size_t trackIndex);
+
+ static bool IsCorrectChunkType(
+ ssize_t trackIndex, Track::Kind kind, uint32_t chunkType);
+
+ DISALLOW_EVIL_CONSTRUCTORS(AVIExtractor);
+};
+
+class String8;
+struct AMessage;
+
+bool SniffAVI(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
+} // namespace android
+
+#endif // AVI_EXTRACTOR_H_
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
new file mode 100644
index 0000000..06e9468
--- /dev/null
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -0,0 +1,327 @@
+/*
+ * 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.
+ */
+
+#ifndef AWESOME_PLAYER_H_
+
+#define AWESOME_PLAYER_H_
+
+#include "HTTPBase.h"
+#include "TimedEventQueue.h"
+
+#include <media/MediaPlayerInterface.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/TimeSource.h>
+#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
+
+namespace android {
+
+struct AudioPlayer;
+struct DataSource;
+struct MediaBuffer;
+struct MediaExtractor;
+struct MediaSource;
+struct NuCachedSource2;
+struct ISurfaceTexture;
+
+class DrmManagerClinet;
+class DecryptHandle;
+
+class TimedTextDriver;
+struct WVMExtractor;
+
+struct AwesomeRenderer : public RefBase {
+ AwesomeRenderer() {}
+
+ virtual void render(MediaBuffer *buffer) = 0;
+
+private:
+ AwesomeRenderer(const AwesomeRenderer &);
+ AwesomeRenderer &operator=(const AwesomeRenderer &);
+};
+
+struct AwesomePlayer {
+ AwesomePlayer();
+ ~AwesomePlayer();
+
+ void setListener(const wp<MediaPlayerBase> &listener);
+ void setUID(uid_t uid);
+
+ status_t setDataSource(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers = NULL);
+
+ status_t setDataSource(int fd, int64_t offset, int64_t length);
+
+ status_t setDataSource(const sp<IStreamSource> &source);
+
+ void reset();
+
+ status_t prepare();
+ status_t prepare_l();
+ status_t prepareAsync();
+ status_t prepareAsync_l();
+
+ status_t play();
+ status_t pause();
+
+ bool isPlaying() const;
+
+ status_t setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture);
+ void setAudioSink(const sp<MediaPlayerBase::AudioSink> &audioSink);
+ status_t setLooping(bool shouldLoop);
+
+ status_t getDuration(int64_t *durationUs);
+ status_t getPosition(int64_t *positionUs);
+
+ status_t setParameter(int key, const Parcel &request);
+ status_t getParameter(int key, Parcel *reply);
+ status_t invoke(const Parcel &request, Parcel *reply);
+ status_t setCacheStatCollectFreq(const Parcel &request);
+
+ status_t seekTo(int64_t timeUs);
+
+ // This is a mask of MediaExtractor::Flags.
+ uint32_t flags() const;
+
+ void postAudioEOS(int64_t delayUs = 0ll);
+ void postAudioSeekComplete();
+
+ status_t dump(int fd, const Vector<String16> &args) const;
+
+private:
+ friend struct AwesomeEvent;
+ friend struct PreviewPlayer;
+
+ enum {
+ PLAYING = 0x01,
+ LOOPING = 0x02,
+ FIRST_FRAME = 0x04,
+ PREPARING = 0x08,
+ PREPARED = 0x10,
+ AT_EOS = 0x20,
+ PREPARE_CANCELLED = 0x40,
+ CACHE_UNDERRUN = 0x80,
+ AUDIO_AT_EOS = 0x0100,
+ VIDEO_AT_EOS = 0x0200,
+ AUTO_LOOPING = 0x0400,
+
+ // We are basically done preparing but are currently buffering
+ // sufficient data to begin playback and finish the preparation phase
+ // for good.
+ PREPARING_CONNECTED = 0x0800,
+
+ // We're triggering a single video event to display the first frame
+ // after the seekpoint.
+ SEEK_PREVIEW = 0x1000,
+
+ AUDIO_RUNNING = 0x2000,
+ AUDIOPLAYER_STARTED = 0x4000,
+
+ INCOGNITO = 0x8000,
+
+ TEXT_RUNNING = 0x10000,
+ TEXTPLAYER_INITIALIZED = 0x20000,
+
+ SLOW_DECODER_HACK = 0x40000,
+ };
+
+ mutable Mutex mLock;
+ Mutex mMiscStateLock;
+ mutable Mutex mStatsLock;
+ Mutex mAudioLock;
+
+ OMXClient mClient;
+ TimedEventQueue mQueue;
+ bool mQueueStarted;
+ wp<MediaPlayerBase> mListener;
+ bool mUIDValid;
+ uid_t mUID;
+
+ sp<ANativeWindow> mNativeWindow;
+ sp<MediaPlayerBase::AudioSink> mAudioSink;
+
+ SystemTimeSource mSystemTimeSource;
+ TimeSource *mTimeSource;
+
+ String8 mUri;
+ KeyedVector<String8, String8> mUriHeaders;
+
+ sp<DataSource> mFileSource;
+
+ sp<MediaSource> mVideoTrack;
+ sp<MediaSource> mVideoSource;
+ sp<AwesomeRenderer> mVideoRenderer;
+ bool mVideoRendererIsPreview;
+
+ sp<MediaSource> mAudioTrack;
+ sp<MediaSource> mAudioSource;
+ AudioPlayer *mAudioPlayer;
+ int64_t mDurationUs;
+
+ int32_t mDisplayWidth;
+ int32_t mDisplayHeight;
+
+ uint32_t mFlags;
+ uint32_t mExtractorFlags;
+ uint32_t mSinceLastDropped;
+
+ int64_t mTimeSourceDeltaUs;
+ int64_t mVideoTimeUs;
+
+ enum SeekType {
+ NO_SEEK,
+ SEEK,
+ SEEK_VIDEO_ONLY
+ };
+ SeekType mSeeking;
+
+ bool mSeekNotificationSent;
+ int64_t mSeekTimeUs;
+
+ int64_t mBitrate; // total bitrate of the file (in bps) or -1 if unknown.
+
+ bool mWatchForAudioSeekComplete;
+ bool mWatchForAudioEOS;
+
+ sp<TimedEventQueue::Event> mVideoEvent;
+ bool mVideoEventPending;
+ sp<TimedEventQueue::Event> mStreamDoneEvent;
+ bool mStreamDoneEventPending;
+ sp<TimedEventQueue::Event> mBufferingEvent;
+ bool mBufferingEventPending;
+ sp<TimedEventQueue::Event> mCheckAudioStatusEvent;
+ bool mAudioStatusEventPending;
+ sp<TimedEventQueue::Event> mVideoLagEvent;
+ bool mVideoLagEventPending;
+
+ sp<TimedEventQueue::Event> mAsyncPrepareEvent;
+ Condition mPreparedCondition;
+ bool mIsAsyncPrepare;
+ status_t mPrepareResult;
+ status_t mStreamDoneStatus;
+
+ void postVideoEvent_l(int64_t delayUs = -1);
+ void postBufferingEvent_l();
+ void postStreamDoneEvent_l(status_t status);
+ void postCheckAudioStatusEvent(int64_t delayUs);
+ void postVideoLagEvent_l();
+ status_t play_l();
+
+ MediaBuffer *mVideoBuffer;
+
+ sp<HTTPBase> mConnectingDataSource;
+ sp<NuCachedSource2> mCachedSource;
+
+ DrmManagerClient *mDrmManagerClient;
+ sp<DecryptHandle> mDecryptHandle;
+
+ int64_t mLastVideoTimeUs;
+ TimedTextDriver *mTextDriver;
+ mutable Mutex mTimedTextLock;
+
+ sp<WVMExtractor> mWVMExtractor;
+
+ status_t setDataSource_l(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers = NULL);
+
+ status_t setDataSource_l(const sp<DataSource> &dataSource);
+ status_t setDataSource_l(const sp<MediaExtractor> &extractor);
+ void reset_l();
+ status_t seekTo_l(int64_t timeUs);
+ status_t pause_l(bool at_eos = false);
+ void initRenderer_l();
+ void notifyVideoSize_l();
+ void seekAudioIfNecessary_l();
+
+ void cancelPlayerEvents(bool keepNotifications = false);
+
+ void setAudioSource(sp<MediaSource> source);
+ status_t initAudioDecoder();
+
+ void setVideoSource(sp<MediaSource> source);
+ status_t initVideoDecoder(uint32_t flags = 0);
+
+ void addTextSource(const sp<MediaSource>& source);
+
+ void onStreamDone();
+
+ void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0);
+
+ void onVideoEvent();
+ void onBufferingUpdate();
+ void onCheckAudioStatus();
+ void onPrepareAsyncEvent();
+ void abortPrepare(status_t err);
+ void finishAsyncPrepare_l();
+ void onVideoLagUpdate();
+
+ bool getCachedDuration_l(int64_t *durationUs, bool *eos);
+
+ status_t finishSetDataSource_l();
+
+ static bool ContinuePreparation(void *cookie);
+
+ bool getBitrate(int64_t *bitrate);
+
+ void finishSeekIfNecessary(int64_t videoTimeUs);
+ void ensureCacheIsFetching_l();
+
+ status_t startAudioPlayer_l(bool sendErrorNotification = true);
+
+ void shutdownVideoDecoder_l();
+ status_t setNativeWindow_l(const sp<ANativeWindow> &native);
+
+ bool isStreamingHTTP() const;
+ void sendCacheStats();
+ void checkDrmStatus(const sp<DataSource>& dataSource);
+
+ enum FlagMode {
+ SET,
+ CLEAR,
+ ASSIGN
+ };
+ void modifyFlags(unsigned value, FlagMode mode);
+
+ struct TrackStat {
+ String8 mMIME;
+ String8 mDecoderName;
+ };
+
+ // protected by mStatsLock
+ struct Stats {
+ int mFd;
+ String8 mURI;
+ int64_t mBitrate;
+ ssize_t mAudioTrackIndex;
+ ssize_t mVideoTrackIndex;
+ int64_t mNumVideoFramesDecoded;
+ int64_t mNumVideoFramesDropped;
+ int32_t mVideoWidth;
+ int32_t mVideoHeight;
+ uint32_t mFlags;
+ Vector<TrackStat> mTracks;
+ } mStats;
+
+ AwesomePlayer(const AwesomePlayer &);
+ AwesomePlayer &operator=(const AwesomePlayer &);
+};
+
+} // namespace android
+
+#endif // AWESOME_PLAYER_H_
diff --git a/media/libstagefright/include/ChromiumHTTPDataSource.h b/media/libstagefright/include/ChromiumHTTPDataSource.h
new file mode 100644
index 0000000..82e08fd
--- /dev/null
+++ b/media/libstagefright/include/ChromiumHTTPDataSource.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 CHROME_HTTP_DATA_SOURCE_H_
+
+#define CHROME_HTTP_DATA_SOURCE_H_
+
+#include <media/stagefright/foundation/AString.h>
+#include <utils/threads.h>
+
+#include "HTTPBase.h"
+
+namespace android {
+
+struct SfDelegate;
+
+struct ChromiumHTTPDataSource : public HTTPBase {
+ ChromiumHTTPDataSource(uint32_t flags = 0);
+
+ virtual status_t connect(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers = NULL,
+ off64_t offset = 0);
+
+ virtual void disconnect();
+
+ virtual status_t initCheck() const;
+
+ virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+ virtual status_t getSize(off64_t *size);
+ virtual uint32_t flags();
+
+ virtual sp<DecryptHandle> DrmInitialization(const char *mime);
+
+ virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
+
+ virtual String8 getUri();
+
+ virtual String8 getMIMEType() const;
+
+ virtual status_t reconnectAtOffset(off64_t offset);
+
+protected:
+ virtual ~ChromiumHTTPDataSource();
+
+private:
+ friend struct SfDelegate;
+
+ enum State {
+ DISCONNECTED,
+ CONNECTING,
+ CONNECTED,
+ READING,
+ DISCONNECTING
+ };
+
+ const uint32_t mFlags;
+
+ mutable Mutex mLock;
+ Condition mCondition;
+
+ State mState;
+
+ SfDelegate *mDelegate;
+
+ AString mURI;
+ KeyedVector<String8, String8> mHeaders;
+
+ off64_t mCurrentOffset;
+
+ // Any connection error or the result of a read operation
+ // (for the lattter this is the number of bytes read, if successful).
+ ssize_t mIOResult;
+
+ int64_t mContentSize;
+
+ String8 mContentType;
+
+ sp<DecryptHandle> mDecryptHandle;
+ DrmManagerClient *mDrmManagerClient;
+
+ void disconnect_l();
+
+ status_t connect_l(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset);
+
+ static void InitiateRead(
+ ChromiumHTTPDataSource *me, void *data, size_t size);
+
+ void initiateRead(void *data, size_t size);
+
+ void onConnectionEstablished(
+ int64_t contentSize, const char *contentType);
+
+ void onConnectionFailed(status_t err);
+ void onReadCompleted(ssize_t size);
+ void onDisconnectComplete();
+
+ void clearDRMState_l();
+
+ DISALLOW_EVIL_CONSTRUCTORS(ChromiumHTTPDataSource);
+};
+
+} // namespace android
+
+#endif // CHROME_HTTP_DATA_SOURCE_H_
diff --git a/media/libstagefright/include/DRMExtractor.h b/media/libstagefright/include/DRMExtractor.h
new file mode 100644
index 0000000..b4e4afb
--- /dev/null
+++ b/media/libstagefright/include/DRMExtractor.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 DRM_EXTRACTOR_H_
+
+#define DRM_EXTRACTOR_H_
+
+#include <media/stagefright/MediaExtractor.h>
+#include <drm/DrmManagerClient.h>
+
+namespace android {
+
+struct AMessage;
+class DataSource;
+class SampleTable;
+class String8;
+class DecryptHandle;
+
+class DRMExtractor : public MediaExtractor {
+public:
+ DRMExtractor(const sp<DataSource> &source, const char *mime);
+
+ 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 ~DRMExtractor();
+
+private:
+ sp<DataSource> mDataSource;
+
+ sp<MediaExtractor> mOriginalExtractor;
+ sp<DecryptHandle> mDecryptHandle;
+ DrmManagerClient* mDrmManagerClient;
+
+ DRMExtractor(const DRMExtractor &);
+ DRMExtractor &operator=(const DRMExtractor &);
+};
+
+bool SniffDRM(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
+} // namespace android
+
+#endif // DRM_EXTRACTOR_H_
+
diff --git a/media/libstagefright/include/DataUriSource.h b/media/libstagefright/include/DataUriSource.h
new file mode 100644
index 0000000..d223c06
--- /dev/null
+++ b/media/libstagefright/include/DataUriSource.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 DATA_URI_SOURCE_H_
+
+#define DATA_URI_SOURCE_H_
+
+#include <stdio.h>
+
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/foundation/AString.h>
+
+namespace android {
+
+class DataUriSource : public DataSource {
+public:
+ DataUriSource(const char *uri);
+
+ virtual status_t initCheck() const {
+ return mInited;
+ }
+
+ virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+
+ virtual status_t getSize(off64_t *size) {
+ if (mInited != OK) {
+ return mInited;
+ }
+
+ *size = mData.size();
+ return OK;
+ }
+
+ virtual String8 getUri() {
+ return mDataUri;
+ }
+
+ virtual String8 getMIMEType() const {
+ return mMimeType;
+ }
+
+protected:
+ virtual ~DataUriSource() {
+ // Nothing to delete.
+ }
+
+private:
+ const String8 mDataUri;
+
+ String8 mMimeType;
+ // Use AString because individual bytes may not be valid UTF8 chars.
+ AString mData;
+ status_t mInited;
+
+ // Disallow copy and assign.
+ DataUriSource(const DataUriSource &);
+ DataUriSource &operator=(const DataUriSource &);
+};
+
+} // namespace android
+
+#endif // DATA_URI_SOURCE_H_
diff --git a/media/libstagefright/include/ESDS.h b/media/libstagefright/include/ESDS.h
new file mode 100644
index 0000000..3a79951
--- /dev/null
+++ b/media/libstagefright/include/ESDS.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifndef ESDS_H_
+
+#define ESDS_H_
+
+#include <stdint.h>
+
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+class ESDS {
+public:
+ ESDS(const void *data, size_t size);
+ ~ESDS();
+
+ status_t InitCheck() const;
+
+ status_t getObjectTypeIndication(uint8_t *objectTypeIndication) const;
+ status_t getCodecSpecificInfo(const void **data, size_t *size) const;
+
+private:
+ enum {
+ kTag_ESDescriptor = 0x03,
+ kTag_DecoderConfigDescriptor = 0x04,
+ kTag_DecoderSpecificInfo = 0x05
+ };
+
+ uint8_t *mData;
+ size_t mSize;
+
+ status_t mInitCheck;
+
+ size_t mDecoderSpecificOffset;
+ size_t mDecoderSpecificLength;
+ uint8_t mObjectTypeIndication;
+
+ status_t skipDescriptorHeader(
+ size_t offset, size_t size,
+ uint8_t *tag, size_t *data_offset, size_t *data_size) const;
+
+ status_t parse();
+ status_t parseESDescriptor(size_t offset, size_t size);
+ status_t parseDecoderConfigDescriptor(size_t offset, size_t size);
+
+ ESDS(const ESDS &);
+ ESDS &operator=(const ESDS &);
+};
+
+} // namespace android
+#endif // ESDS_H_
diff --git a/media/libstagefright/include/FLACExtractor.h b/media/libstagefright/include/FLACExtractor.h
new file mode 100644
index 0000000..ded91c2
--- /dev/null
+++ b/media/libstagefright/include/FLACExtractor.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 FLAC_EXTRACTOR_H_
+#define FLAC_EXTRACTOR_H_
+
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class FLACParser;
+
+class FLACExtractor : public MediaExtractor {
+
+public:
+ // Extractor assumes ownership of source
+ FLACExtractor(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 ~FLACExtractor();
+
+private:
+ sp<DataSource> mDataSource;
+ sp<FLACParser> mParser;
+ status_t mInitCheck;
+ sp<MetaData> mFileMetadata;
+
+ // There is only one track
+ sp<MetaData> mTrackMetadata;
+
+ status_t init();
+
+ FLACExtractor(const FLACExtractor &);
+ FLACExtractor &operator=(const FLACExtractor &);
+
+};
+
+bool SniffFLAC(const sp<DataSource> &source, String8 *mimeType,
+ float *confidence, sp<AMessage> *);
+
+} // namespace android
+
+#endif // FLAC_EXTRACTOR_H_
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
new file mode 100644
index 0000000..b8e10f7
--- /dev/null
+++ b/media/libstagefright/include/HTTPBase.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 HTTP_BASE_H_
+
+#define HTTP_BASE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct HTTPBase : public DataSource {
+ enum Flags {
+ // Don't log any URLs.
+ kFlagIncognito = 1
+ };
+
+ HTTPBase();
+
+ virtual status_t connect(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers = NULL,
+ off64_t offset = 0) = 0;
+
+ virtual void disconnect() = 0;
+
+ // Returns true if bandwidth could successfully be estimated,
+ // false otherwise.
+ virtual bool estimateBandwidth(int32_t *bandwidth_bps);
+
+ virtual status_t getEstimatedBandwidthKbps(int32_t *kbps);
+
+ virtual status_t setBandwidthStatCollectFreq(int32_t freqMs);
+
+ void setUID(uid_t uid);
+ bool getUID(uid_t *uid) const;
+
+ static sp<HTTPBase> Create(uint32_t flags = 0);
+
+ static void RegisterSocketUserTag(int sockfd, uid_t uid, uint32_t kTag);
+ static void UnRegisterSocketUserTag(int sockfd);
+
+protected:
+ void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
+
+private:
+ struct BandwidthEntry {
+ int64_t mDelayUs;
+ size_t mNumBytes;
+ };
+
+ Mutex mLock;
+
+ List<BandwidthEntry> mBandwidthHistory;
+ size_t mNumBandwidthHistoryItems;
+ int64_t mTotalTransferTimeUs;
+ size_t mTotalTransferBytes;
+
+ enum {
+ kMinBandwidthCollectFreqMs = 1000, // 1 second
+ kMaxBandwidthCollectFreqMs = 60000, // one minute
+ };
+
+ int64_t mPrevBandwidthMeasureTimeUs;
+ int32_t mPrevEstimatedBandWidthKbps;
+ int32_t mBandWidthCollectFreqMs;
+
+ bool mUIDValid;
+ uid_t mUID;
+
+ DISALLOW_EVIL_CONSTRUCTORS(HTTPBase);
+};
+
+} // namespace android
+
+#endif // HTTP_BASE_H_
diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h
new file mode 100644
index 0000000..8714008
--- /dev/null
+++ b/media/libstagefright/include/ID3.h
@@ -0,0 +1,95 @@
+/*
+ * 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 ID3_H_
+
+#define ID3_H_
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct DataSource;
+struct String8;
+
+struct ID3 {
+ enum Version {
+ ID3_UNKNOWN,
+ ID3_V1,
+ ID3_V1_1,
+ ID3_V2_2,
+ ID3_V2_3,
+ ID3_V2_4,
+ };
+
+ ID3(const sp<DataSource> &source);
+ ~ID3();
+
+ bool isValid() const;
+
+ Version version() const;
+
+ const void *getAlbumArt(size_t *length, String8 *mime) const;
+
+ struct Iterator {
+ Iterator(const ID3 &parent, const char *id);
+ ~Iterator();
+
+ bool done() const;
+ void getID(String8 *id) const;
+ void getString(String8 *s, String8 *ss = NULL) const;
+ const uint8_t *getData(size_t *length) const;
+ void next();
+
+ private:
+ const ID3 &mParent;
+ char *mID;
+ size_t mOffset;
+
+ const uint8_t *mFrameData;
+ size_t mFrameSize;
+
+ void findFrame();
+
+ size_t getHeaderLength() const;
+ void getstring(String8 *s, bool secondhalf) const;
+
+ Iterator(const Iterator &);
+ Iterator &operator=(const Iterator &);
+ };
+
+private:
+ bool mIsValid;
+ uint8_t *mData;
+ size_t mSize;
+ size_t mFirstFrameOffset;
+ Version mVersion;
+
+ bool parseV1(const sp<DataSource> &source);
+ bool parseV2(const sp<DataSource> &source);
+ void removeUnsynchronization();
+ bool removeUnsynchronizationV2_4(bool iTunesHack);
+
+ static bool ParseSyncsafeInteger(const uint8_t encoded[4], size_t *x);
+
+ ID3(const ID3 &);
+ ID3 &operator=(const ID3 &);
+};
+
+} // namespace android
+
+#endif // ID3_H_
+
diff --git a/media/libstagefright/include/LiveSession.h b/media/libstagefright/include/LiveSession.h
new file mode 100644
index 0000000..3a11612
--- /dev/null
+++ b/media/libstagefright/include/LiveSession.h
@@ -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.
+ */
+
+#ifndef LIVE_SESSION_H_
+
+#define LIVE_SESSION_H_
+
+#include <media/stagefright/foundation/AHandler.h>
+
+#include <utils/String8.h>
+
+namespace android {
+
+struct ABuffer;
+struct DataSource;
+struct LiveDataSource;
+struct M3UParser;
+struct HTTPBase;
+
+struct LiveSession : public AHandler {
+ enum Flags {
+ // Don't log any URLs.
+ kFlagIncognito = 1,
+ };
+ LiveSession(uint32_t flags = 0, bool uidValid = false, uid_t uid = 0);
+
+ sp<DataSource> getDataSource();
+
+ void connect(
+ const char *url,
+ const KeyedVector<String8, String8> *headers = NULL);
+
+ void disconnect();
+
+ // Blocks until seek is complete.
+ void seekTo(int64_t timeUs);
+
+ status_t getDuration(int64_t *durationUs);
+ bool isSeekable();
+
+protected:
+ virtual ~LiveSession();
+
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+ enum {
+ kMaxNumQueuedFragments = 3,
+ kMaxNumRetries = 5,
+ };
+
+ enum {
+ kWhatConnect = 'conn',
+ kWhatDisconnect = 'disc',
+ kWhatMonitorQueue = 'moni',
+ kWhatSeek = 'seek',
+ };
+
+ struct BandwidthItem {
+ AString mURI;
+ unsigned long mBandwidth;
+ };
+
+ uint32_t mFlags;
+ bool mUIDValid;
+ uid_t mUID;
+
+ sp<LiveDataSource> mDataSource;
+
+ sp<HTTPBase> mHTTPDataSource;
+
+ AString mMasterURL;
+ KeyedVector<String8, String8> mExtraHeaders;
+
+ Vector<BandwidthItem> mBandwidthItems;
+
+ KeyedVector<AString, sp<ABuffer> > mAESKeyForURI;
+
+ ssize_t mPrevBandwidthIndex;
+ int64_t mLastPlaylistFetchTimeUs;
+ sp<M3UParser> mPlaylist;
+ int32_t mSeqNumber;
+ int64_t mSeekTimeUs;
+ int32_t mNumRetries;
+
+ Mutex mLock;
+ Condition mCondition;
+ int64_t mDurationUs;
+ bool mSeekDone;
+ bool mDisconnectPending;
+
+ int32_t mMonitorQueueGeneration;
+
+ enum RefreshState {
+ INITIAL_MINIMUM_RELOAD_DELAY,
+ FIRST_UNCHANGED_RELOAD_ATTEMPT,
+ SECOND_UNCHANGED_RELOAD_ATTEMPT,
+ THIRD_UNCHANGED_RELOAD_ATTEMPT
+ };
+ RefreshState mRefreshState;
+
+ uint8_t mPlaylistHash[16];
+
+ void onConnect(const sp<AMessage> &msg);
+ void onDisconnect();
+ void onDownloadNext();
+ void onMonitorQueue();
+ void onSeek(const sp<AMessage> &msg);
+
+ status_t fetchFile(
+ const char *url, sp<ABuffer> *out,
+ int64_t range_offset = 0, int64_t range_length = -1);
+
+ sp<M3UParser> fetchPlaylist(const char *url, bool *unchanged);
+ size_t getBandwidthIndex();
+
+ status_t decryptBuffer(
+ size_t playlistIndex, const sp<ABuffer> &buffer);
+
+ void postMonitorQueue(int64_t delayUs = 0);
+
+ bool timeToRefreshPlaylist(int64_t nowUs) const;
+
+ static int SortByBandwidth(const BandwidthItem *, const BandwidthItem *);
+
+ DISALLOW_EVIL_CONSTRUCTORS(LiveSession);
+};
+
+} // namespace android
+
+#endif // LIVE_SESSION_H_
diff --git a/media/libstagefright/include/M3UParser.h b/media/libstagefright/include/M3UParser.h
new file mode 100644
index 0000000..e30d6fd
--- /dev/null
+++ b/media/libstagefright/include/M3UParser.h
@@ -0,0 +1,87 @@
+/*
+ * 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;
+ bool isComplete() 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;
+ bool mIsComplete;
+
+ 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 parseMetaDataDuration(
+ const AString &line, sp<AMessage> *meta, const char *key);
+
+ static status_t parseStreamInf(
+ const AString &line, sp<AMessage> *meta);
+
+ static status_t parseCipherInfo(
+ const AString &line, sp<AMessage> *meta, const AString &baseURI);
+
+ static status_t parseByteRange(
+ const AString &line, uint64_t curOffset,
+ uint64_t *length, uint64_t *offset);
+
+ static status_t ParseInt32(const char *s, int32_t *x);
+ static status_t ParseDouble(const char *s, double *x);
+
+ DISALLOW_EVIL_CONSTRUCTORS(M3UParser);
+};
+
+} // namespace android
+
+#endif // M3U_PARSER_H_
diff --git a/media/libstagefright/include/M4vH263Encoder.h b/media/libstagefright/include/M4vH263Encoder.h
new file mode 100644
index 0000000..dbe9fd0
--- /dev/null
+++ b/media/libstagefright/include/M4vH263Encoder.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 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;
+ int64_t mPrevTimestampUs;
+ 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/MP3Extractor.h b/media/libstagefright/include/MP3Extractor.h
new file mode 100644
index 0000000..c83d9e8
--- /dev/null
+++ b/media/libstagefright/include/MP3Extractor.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+#ifndef MP3_EXTRACTOR_H_
+
+#define MP3_EXTRACTOR_H_
+
+#include <utils/Errors.h>
+#include <media/stagefright/MediaExtractor.h>
+
+namespace android {
+
+struct AMessage;
+class DataSource;
+struct MP3Seeker;
+class String8;
+
+class MP3Extractor : public MediaExtractor {
+public:
+ // Extractor assumes ownership of "source".
+ MP3Extractor(const sp<DataSource> &source, const sp<AMessage> &meta);
+
+ 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();
+
+private:
+ status_t mInitCheck;
+
+ sp<DataSource> mDataSource;
+ off64_t mFirstFramePos;
+ sp<MetaData> mMeta;
+ uint32_t mFixedHeader;
+ sp<MP3Seeker> mSeeker;
+
+ MP3Extractor(const MP3Extractor &);
+ MP3Extractor &operator=(const MP3Extractor &);
+};
+
+bool SniffMP3(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *meta);
+
+} // namespace android
+
+#endif // MP3_EXTRACTOR_H_
diff --git a/media/libstagefright/include/MP3Seeker.h b/media/libstagefright/include/MP3Seeker.h
new file mode 100644
index 0000000..599542e
--- /dev/null
+++ b/media/libstagefright/include/MP3Seeker.h
@@ -0,0 +1,46 @@
+/*
+ * 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 MP3_SEEKER_H_
+
+#define MP3_SEEKER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct MP3Seeker : public RefBase {
+ MP3Seeker() {}
+
+ virtual bool getDuration(int64_t *durationUs) = 0;
+
+ // Given a request seek time in "*timeUs", find the byte offset closest
+ // to that position and return it in "*pos". Update "*timeUs" to reflect
+ // the actual time that seekpoint represents.
+ virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos) = 0;
+
+protected:
+ virtual ~MP3Seeker() {}
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(MP3Seeker);
+};
+
+} // namespace android
+
+#endif // MP3_SEEKER_H_
+
diff --git a/media/libstagefright/include/MPEG2PSExtractor.h b/media/libstagefright/include/MPEG2PSExtractor.h
new file mode 100644
index 0000000..fb76564
--- /dev/null
+++ b/media/libstagefright/include/MPEG2PSExtractor.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 MPEG2_PS_EXTRACTOR_H_
+
+#define MPEG2_PS_EXTRACTOR_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <utils/threads.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+struct ABuffer;
+struct AMessage;
+struct Track;
+struct String8;
+
+struct MPEG2PSExtractor : public MediaExtractor {
+ MPEG2PSExtractor(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;
+
+protected:
+ virtual ~MPEG2PSExtractor();
+
+private:
+ struct Track;
+ struct WrappedTrack;
+
+ mutable Mutex mLock;
+ sp<DataSource> mDataSource;
+
+ off64_t mOffset;
+ status_t mFinalResult;
+ sp<ABuffer> mBuffer;
+ KeyedVector<unsigned, sp<Track> > mTracks;
+ bool mScanning;
+
+ bool mProgramStreamMapValid;
+ KeyedVector<unsigned, unsigned> mStreamTypeByESID;
+
+ status_t feedMore();
+
+ status_t dequeueChunk();
+ ssize_t dequeuePack();
+ ssize_t dequeueSystemHeader();
+ ssize_t dequeuePES();
+
+ DISALLOW_EVIL_CONSTRUCTORS(MPEG2PSExtractor);
+};
+
+bool SniffMPEG2PS(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
+} // namespace android
+
+#endif // MPEG2_PS_EXTRACTOR_H_
+
diff --git a/media/libstagefright/include/MPEG2TSExtractor.h b/media/libstagefright/include/MPEG2TSExtractor.h
new file mode 100644
index 0000000..fe74a42
--- /dev/null
+++ b/media/libstagefright/include/MPEG2TSExtractor.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 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 AMessage;
+struct AnotherPacketSource;
+struct ATSParser;
+struct DataSource;
+struct MPEG2TSSource;
+struct String8;
+struct LiveSession;
+
+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;
+
+ void setLiveSession(const sp<LiveSession> &liveSession);
+ void seekTo(int64_t seekTimeUs);
+
+private:
+ friend struct MPEG2TSSource;
+
+ mutable Mutex mLock;
+
+ sp<DataSource> mDataSource;
+ sp<LiveSession> mLiveSession;
+
+ sp<ATSParser> mParser;
+
+ Vector<sp<AnotherPacketSource> > mSourceImpls;
+
+ off64_t mOffset;
+
+ void init();
+ status_t feedMore();
+
+ DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSExtractor);
+};
+
+bool SniffMPEG2TS(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
+} // namespace android
+
+#endif // MPEG2_TS_EXTRACTOR_H_
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
new file mode 100644
index 0000000..5c549e0
--- /dev/null
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+#ifndef MPEG4_EXTRACTOR_H_
+
+#define MPEG4_EXTRACTOR_H_
+
+#include <media/stagefright/MediaExtractor.h>
+#include <utils/Vector.h>
+#include <utils/String8.h>
+
+namespace android {
+
+struct AMessage;
+class DataSource;
+class SampleTable;
+class String8;
+
+class MPEG4Extractor : public MediaExtractor {
+public:
+ // Extractor assumes ownership of "source".
+ MPEG4Extractor(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();
+
+ // for DRM
+ virtual char* getDrmTrackInfo(size_t trackID, int *len);
+
+protected:
+ virtual ~MPEG4Extractor();
+
+private:
+ struct Track {
+ Track *next;
+ sp<MetaData> meta;
+ uint32_t timescale;
+ sp<SampleTable> sampleTable;
+ bool includes_expensive_metadata;
+ bool skipTrack;
+ };
+
+ sp<DataSource> mDataSource;
+ status_t mInitCheck;
+ bool mHasVideo;
+
+ Track *mFirstTrack, *mLastTrack;
+
+ sp<MetaData> mFileMetaData;
+
+ Vector<uint32_t> mPath;
+ String8 mLastCommentMean;
+ String8 mLastCommentName;
+ String8 mLastCommentData;
+
+ status_t readMetaData();
+ status_t parseChunk(off64_t *offset, int depth);
+ status_t parseMetaData(off64_t offset, size_t size);
+
+ status_t updateAudioTrackInfoFromESDS_MPEG4Audio(
+ const void *esds_data, size_t esds_size);
+
+ static status_t verifyTrack(Track *track);
+
+ struct SINF {
+ SINF *next;
+ uint16_t trackID;
+ uint8_t IPMPDescriptorID;
+ ssize_t len;
+ char *IPMPData;
+ };
+
+ SINF *mFirstSINF;
+
+ bool mIsDrm;
+ status_t parseDrmSINF(off64_t *offset, off64_t data_offset);
+
+ status_t parseTrackHeader(off64_t data_offset, off64_t data_size);
+
+ Track *findTrackByMimePrefix(const char *mimePrefix);
+
+ MPEG4Extractor(const MPEG4Extractor &);
+ MPEG4Extractor &operator=(const MPEG4Extractor &);
+};
+
+bool SniffMPEG4(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
+} // namespace android
+
+#endif // MPEG4_EXTRACTOR_H_
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
new file mode 100644
index 0000000..c27a29b
--- /dev/null
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -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.
+ */
+
+#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,
+ const char *cacheConfig = NULL,
+ bool disconnectAtHighwatermark = false);
+
+ virtual status_t initCheck() const;
+
+ virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+
+ virtual status_t getSize(off64_t *size);
+ virtual uint32_t flags();
+
+ virtual sp<DecryptHandle> DrmInitialization(const char* mime);
+ virtual void getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client);
+ virtual String8 getUri();
+
+ virtual String8 getMIMEType() const;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ size_t cachedSize();
+ size_t approxDataRemaining(status_t *finalStatus);
+
+ void resumeFetchingIfNecessary();
+
+ // The following methods are supported only if the
+ // data source is HTTP-based; otherwise, ERROR_UNSUPPORTED
+ // is returned.
+ status_t getEstimatedBandwidthKbps(int32_t *kbps);
+ status_t setCacheStatCollectFreq(int32_t freqMs);
+
+ static void RemoveCacheSpecificHeaders(
+ KeyedVector<String8, String8> *headers,
+ String8 *cacheConfig,
+ bool *disconnectAtHighwatermark);
+
+protected:
+ virtual ~NuCachedSource2();
+
+private:
+ friend struct AHandlerReflector<NuCachedSource2>;
+
+ enum {
+ kPageSize = 65536,
+ kDefaultHighWaterThreshold = 20 * 1024 * 1024,
+ kDefaultLowWaterThreshold = 4 * 1024 * 1024,
+
+ // Read data after a 15 sec timeout whether we're actively
+ // fetching or not.
+ kDefaultKeepAliveIntervalUs = 15000000,
+ };
+
+ enum {
+ kWhatFetchMore = 'fetc',
+ kWhatRead = 'read',
+ };
+
+ enum {
+ kMaxNumRetries = 10,
+ };
+
+ sp<DataSource> mSource;
+ sp<AHandlerReflector<NuCachedSource2> > mReflector;
+ sp<ALooper> mLooper;
+
+ Mutex mSerializer;
+ Mutex mLock;
+ Condition mCondition;
+
+ PageCache *mCache;
+ off64_t mCacheOffset;
+ status_t mFinalStatus;
+ off64_t mLastAccessPos;
+ sp<AMessage> mAsyncResult;
+ bool mFetching;
+ int64_t mLastFetchTimeUs;
+
+ int32_t mNumRetriesLeft;
+
+ size_t mHighwaterThresholdBytes;
+ size_t mLowwaterThresholdBytes;
+
+ // If the keep-alive interval is 0, keep-alives are disabled.
+ int64_t mKeepAliveIntervalUs;
+
+ bool mDisconnectAtHighwatermark;
+
+ void onMessageReceived(const sp<AMessage> &msg);
+ void onFetch();
+ void onRead(const sp<AMessage> &msg);
+
+ void fetchInternal();
+ ssize_t readInternal(off64_t offset, void *data, size_t size);
+ status_t seekInternal_l(off64_t offset);
+
+ size_t approxDataRemaining_l(status_t *finalStatus);
+
+ void restartPrefetcherIfNecessary_l(
+ bool ignoreLowWaterThreshold = false, bool force = false);
+
+ void updateCacheParamsFromSystemProperty();
+ void updateCacheParamsFromString(const char *s);
+
+ DISALLOW_EVIL_CONSTRUCTORS(NuCachedSource2);
+};
+
+} // namespace android
+
+#endif // NU_CACHED_SOURCE_2_H_
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
new file mode 100644
index 0000000..2c87b34
--- /dev/null
+++ b/media/libstagefright/include/OMX.h
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_OMX_H_
+#define ANDROID_OMX_H_
+
+#include <media/IOMX.h>
+#include <utils/threads.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+struct OMXMaster;
+class OMXNodeInstance;
+
+class OMX : public BnOMX,
+ public IBinder::DeathRecipient {
+public:
+ OMX();
+
+ virtual bool livesLocally(node_id node, pid_t pid);
+
+ virtual status_t listNodes(List<ComponentInfo> *list);
+
+ virtual status_t allocateNode(
+ const char *name, const sp<IOMXObserver> &observer, node_id *node);
+
+ virtual status_t freeNode(node_id node);
+
+ virtual status_t sendCommand(
+ node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param);
+
+ virtual status_t getParameter(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size);
+
+ virtual status_t setParameter(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size);
+
+ virtual status_t getConfig(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size);
+
+ virtual status_t setConfig(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size);
+
+ virtual status_t getState(
+ node_id node, OMX_STATETYPE* state);
+
+ virtual status_t enableGraphicBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable);
+
+ virtual status_t getGraphicBufferUsage(
+ node_id node, OMX_U32 port_index, OMX_U32* usage);
+
+ virtual status_t storeMetaDataInBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable);
+
+ virtual status_t useBuffer(
+ node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+ buffer_id *buffer);
+
+ virtual status_t useGraphicBuffer(
+ node_id node, OMX_U32 port_index,
+ const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer);
+
+ virtual status_t allocateBuffer(
+ node_id node, OMX_U32 port_index, size_t size,
+ buffer_id *buffer, void **buffer_data);
+
+ virtual status_t allocateBufferWithBackup(
+ node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+ buffer_id *buffer);
+
+ virtual status_t freeBuffer(
+ node_id node, OMX_U32 port_index, buffer_id buffer);
+
+ virtual status_t fillBuffer(node_id node, buffer_id buffer);
+
+ virtual status_t emptyBuffer(
+ node_id node,
+ buffer_id buffer,
+ OMX_U32 range_offset, OMX_U32 range_length,
+ OMX_U32 flags, OMX_TICKS timestamp);
+
+ virtual status_t getExtensionIndex(
+ node_id node,
+ const char *parameter_name,
+ OMX_INDEXTYPE *index);
+
+ virtual void binderDied(const wp<IBinder> &the_late_who);
+
+ OMX_ERRORTYPE OnEvent(
+ node_id node,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ 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);
+
+ OMX_ERRORTYPE OnFillBufferDone(
+ node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
+
+ void invalidateNodeID(node_id node);
+
+protected:
+ virtual ~OMX();
+
+private:
+ struct CallbackDispatcherThread;
+ struct CallbackDispatcher;
+
+ 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);
+
+ OMX(const OMX &);
+ OMX &operator=(const OMX &);
+};
+
+} // namespace android
+
+#endif // ANDROID_OMX_H_
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
new file mode 100644
index 0000000..47ca579
--- /dev/null
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+#ifndef OMX_NODE_INSTANCE_H_
+
+#define OMX_NODE_INSTANCE_H_
+
+#include "OMX.h"
+
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class IOMXObserver;
+struct OMXMaster;
+
+struct OMXNodeInstance {
+ OMXNodeInstance(
+ OMX *owner, const sp<IOMXObserver> &observer);
+
+ void setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle);
+
+ OMX *owner();
+ sp<IOMXObserver> observer();
+ OMX::node_id nodeID();
+
+ status_t freeNode(OMXMaster *master);
+
+ status_t sendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param);
+ status_t getParameter(OMX_INDEXTYPE index, void *params, size_t size);
+
+ status_t setParameter(
+ OMX_INDEXTYPE index, const void *params, size_t size);
+
+ status_t getConfig(OMX_INDEXTYPE index, void *params, size_t size);
+ status_t setConfig(OMX_INDEXTYPE index, const void *params, size_t size);
+
+ status_t getState(OMX_STATETYPE* state);
+
+ status_t enableGraphicBuffers(OMX_U32 portIndex, OMX_BOOL enable);
+
+ status_t getGraphicBufferUsage(OMX_U32 portIndex, OMX_U32* usage);
+
+ status_t storeMetaDataInBuffers(OMX_U32 portIndex, OMX_BOOL enable);
+
+ status_t useBuffer(
+ OMX_U32 portIndex, const sp<IMemory> &params,
+ OMX::buffer_id *buffer);
+
+ status_t useGraphicBuffer(
+ OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
+ OMX::buffer_id *buffer);
+
+ status_t allocateBuffer(
+ OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
+ void **buffer_data);
+
+ status_t allocateBufferWithBackup(
+ OMX_U32 portIndex, const sp<IMemory> &params,
+ OMX::buffer_id *buffer);
+
+ status_t freeBuffer(OMX_U32 portIndex, OMX::buffer_id buffer);
+
+ status_t fillBuffer(OMX::buffer_id buffer);
+
+ status_t emptyBuffer(
+ OMX::buffer_id buffer,
+ OMX_U32 rangeOffset, OMX_U32 rangeLength,
+ OMX_U32 flags, OMX_TICKS timestamp);
+
+ status_t getExtensionIndex(
+ const char *parameterName, OMX_INDEXTYPE *index);
+
+ void onMessage(const omx_message &msg);
+ void onObserverDied(OMXMaster *master);
+ void onGetHandleFailed();
+
+ static OMX_CALLBACKTYPE kCallbacks;
+
+private:
+ Mutex mLock;
+
+ OMX *mOwner;
+ OMX::node_id mNodeID;
+ OMX_HANDLETYPE mHandle;
+ sp<IOMXObserver> mObserver;
+ bool mDying;
+
+ struct ActiveBuffer {
+ OMX_U32 mPortIndex;
+ OMX::buffer_id mID;
+ };
+ Vector<ActiveBuffer> mActiveBuffers;
+
+ ~OMXNodeInstance();
+
+ void addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id);
+ void removeActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id);
+ void freeActiveBuffers();
+ status_t useGraphicBuffer2_l(
+ OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
+ OMX::buffer_id *buffer);
+ static OMX_ERRORTYPE OnEvent(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData);
+
+ static OMX_ERRORTYPE OnEmptyBufferDone(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
+
+ static OMX_ERRORTYPE OnFillBufferDone(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
+
+ OMXNodeInstance(const OMXNodeInstance &);
+ OMXNodeInstance &operator=(const OMXNodeInstance &);
+};
+
+} // namespace android
+
+#endif // OMX_NODE_INSTANCE_H_
diff --git a/media/libstagefright/include/OggExtractor.h b/media/libstagefright/include/OggExtractor.h
new file mode 100644
index 0000000..e97c8cd
--- /dev/null
+++ b/media/libstagefright/include/OggExtractor.h
@@ -0,0 +1,66 @@
+/*
+ * 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 OGG_EXTRACTOR_H_
+
+#define OGG_EXTRACTOR_H_
+
+#include <utils/Errors.h>
+#include <media/stagefright/MediaExtractor.h>
+
+namespace android {
+
+struct AMessage;
+class DataSource;
+class String8;
+
+struct MyVorbisExtractor;
+struct OggSource;
+
+struct OggExtractor : public MediaExtractor {
+ OggExtractor(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 ~OggExtractor();
+
+private:
+ friend struct OggSource;
+
+ sp<DataSource> mDataSource;
+ status_t mInitCheck;
+
+ MyVorbisExtractor *mImpl;
+
+ OggExtractor(const OggExtractor &);
+ OggExtractor &operator=(const OggExtractor &);
+};
+
+bool SniffOgg(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
+void parseVorbisComment(
+ const sp<MetaData> &fileMeta, const char *comment, size_t commentLength);
+
+} // namespace android
+
+#endif // OGG_EXTRACTOR_H_
diff --git a/media/libstagefright/include/SampleIterator.h b/media/libstagefright/include/SampleIterator.h
new file mode 100644
index 0000000..b5a043c
--- /dev/null
+++ b/media/libstagefright/include/SampleIterator.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.
+ */
+
+#include <utils/Vector.h>
+
+namespace android {
+
+struct SampleTable;
+
+struct SampleIterator {
+ SampleIterator(SampleTable *table);
+
+ status_t seekTo(uint32_t sampleIndex);
+
+ uint32_t getChunkIndex() const { return mCurrentChunkIndex; }
+ uint32_t getDescIndex() const { return mChunkDesc; }
+ off64_t getSampleOffset() const { return mCurrentSampleOffset; }
+ size_t getSampleSize() const { return mCurrentSampleSize; }
+ uint32_t getSampleTime() const { return mCurrentSampleTime; }
+
+ status_t getSampleSizeDirect(
+ uint32_t sampleIndex, size_t *size);
+
+private:
+ SampleTable *mTable;
+
+ bool mInitialized;
+
+ uint32_t mSampleToChunkIndex;
+ uint32_t mFirstChunk;
+ uint32_t mFirstChunkSampleIndex;
+ uint32_t mStopChunk;
+ uint32_t mStopChunkSampleIndex;
+ uint32_t mSamplesPerChunk;
+ uint32_t mChunkDesc;
+
+ uint32_t mCurrentChunkIndex;
+ off64_t mCurrentChunkOffset;
+ Vector<size_t> mCurrentChunkSampleSizes;
+
+ uint32_t mTimeToSampleIndex;
+ uint32_t mTTSSampleIndex;
+ uint32_t mTTSSampleTime;
+ uint32_t mTTSCount;
+ uint32_t mTTSDuration;
+
+ uint32_t mCurrentSampleIndex;
+ off64_t mCurrentSampleOffset;
+ size_t mCurrentSampleSize;
+ uint32_t mCurrentSampleTime;
+
+ void reset();
+ status_t findChunkRange(uint32_t sampleIndex);
+ status_t getChunkOffset(uint32_t chunk, off64_t *offset);
+ status_t findSampleTime(uint32_t sampleIndex, uint32_t *time);
+
+ SampleIterator(const SampleIterator &);
+ SampleIterator &operator=(const SampleIterator &);
+};
+
+} // namespace android
+
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
new file mode 100644
index 0000000..847dff7
--- /dev/null
+++ b/media/libstagefright/include/SampleTable.h
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ */
+
+#ifndef SAMPLE_TABLE_H_
+
+#define SAMPLE_TABLE_H_
+
+#include <sys/types.h>
+#include <stdint.h>
+
+#include <media/stagefright/MediaErrors.h>
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class DataSource;
+struct SampleIterator;
+
+class SampleTable : public RefBase {
+public:
+ SampleTable(const sp<DataSource> &source);
+
+ bool isValid() const;
+
+ // type can be 'stco' or 'co64'.
+ status_t setChunkOffsetParams(
+ uint32_t type, off64_t data_offset, size_t data_size);
+
+ status_t setSampleToChunkParams(off64_t data_offset, size_t data_size);
+
+ // type can be 'stsz' or 'stz2'.
+ status_t setSampleSizeParams(
+ uint32_t type, off64_t data_offset, size_t data_size);
+
+ status_t setTimeToSampleParams(off64_t data_offset, size_t data_size);
+
+ status_t setCompositionTimeToSampleParams(
+ off64_t data_offset, size_t data_size);
+
+ status_t setSyncSampleParams(off64_t data_offset, size_t data_size);
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ uint32_t countChunkOffsets() const;
+
+ uint32_t countSamples() const;
+
+ status_t getMaxSampleSize(size_t *size);
+
+ status_t getMetaDataForSample(
+ uint32_t sampleIndex,
+ off64_t *offset,
+ size_t *size,
+ uint32_t *compositionTime,
+ bool *isSyncSample = NULL);
+
+ enum {
+ kFlagBefore,
+ kFlagAfter,
+ kFlagClosest
+ };
+ 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:
+ ~SampleTable();
+
+private:
+ struct CompositionDeltaLookup;
+
+ static const uint32_t kChunkOffsetType32;
+ static const uint32_t kChunkOffsetType64;
+ static const uint32_t kSampleSizeType32;
+ static const uint32_t kSampleSizeTypeCompact;
+
+ sp<DataSource> mDataSource;
+ Mutex mLock;
+
+ off64_t mChunkOffsetOffset;
+ uint32_t mChunkOffsetType;
+ uint32_t mNumChunkOffsets;
+
+ off64_t mSampleToChunkOffset;
+ uint32_t mNumSampleToChunkOffsets;
+
+ off64_t mSampleSizeOffset;
+ uint32_t mSampleSizeFieldSize;
+ uint32_t mDefaultSampleSize;
+ uint32_t mNumSampleSizes;
+
+ uint32_t mTimeToSampleCount;
+ uint32_t *mTimeToSample;
+
+ struct SampleTimeEntry {
+ uint32_t mSampleIndex;
+ uint32_t mCompositionTime;
+ };
+ SampleTimeEntry *mSampleTimeEntries;
+
+ uint32_t *mCompositionTimeDeltaEntries;
+ size_t mNumCompositionTimeDeltaEntries;
+ CompositionDeltaLookup *mCompositionDeltaLookup;
+
+ off64_t mSyncSampleOffset;
+ uint32_t mNumSyncSamples;
+ uint32_t *mSyncSamples;
+ size_t mLastSyncSampleIndex;
+
+ SampleIterator *mSampleIterator;
+
+ struct SampleToChunkEntry {
+ uint32_t startChunk;
+ uint32_t samplesPerChunk;
+ uint32_t chunkDesc;
+ };
+ SampleToChunkEntry *mSampleToChunkEntries;
+
+ friend struct SampleIterator;
+
+ status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
+ uint32_t getCompositionTimeOffset(uint32_t sampleIndex);
+
+ static int CompareIncreasingTime(const void *, const void *);
+
+ void buildSampleEntriesTable();
+
+ SampleTable(const SampleTable &);
+ SampleTable &operator=(const SampleTable &);
+};
+
+} // namespace android
+
+#endif // SAMPLE_TABLE_H_
diff --git a/media/libstagefright/include/SimpleSoftOMXComponent.h b/media/libstagefright/include/SimpleSoftOMXComponent.h
new file mode 100644
index 0000000..50cd275
--- /dev/null
+++ b/media/libstagefright/include/SimpleSoftOMXComponent.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SIMPLE_SOFT_OMX_COMPONENT_H_
+
+#define SIMPLE_SOFT_OMX_COMPONENT_H_
+
+#include "SoftOMXComponent.h"
+
+#include <media/stagefright/foundation/AHandlerReflector.h>
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct ALooper;
+
+struct SimpleSoftOMXComponent : public SoftOMXComponent {
+ SimpleSoftOMXComponent(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+ virtual void prepareForDestruction();
+
+ void onMessageReceived(const sp<AMessage> &msg);
+
+protected:
+ struct BufferInfo {
+ OMX_BUFFERHEADERTYPE *mHeader;
+ bool mOwnedByUs;
+ };
+
+ struct PortInfo {
+ OMX_PARAM_PORTDEFINITIONTYPE mDef;
+ Vector<BufferInfo> mBuffers;
+ List<BufferInfo *> mQueue;
+
+ enum {
+ NONE,
+ DISABLING,
+ ENABLING,
+ } mTransition;
+ };
+
+ void addPort(const OMX_PARAM_PORTDEFINITIONTYPE &def);
+
+ virtual OMX_ERRORTYPE internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual void onQueueFilled(OMX_U32 portIndex);
+ List<BufferInfo *> &getPortQueue(OMX_U32 portIndex);
+
+ virtual void onPortFlushCompleted(OMX_U32 portIndex);
+ virtual void onPortEnableCompleted(OMX_U32 portIndex, bool enabled);
+
+ PortInfo *editPortInfo(OMX_U32 portIndex);
+
+private:
+ enum {
+ kWhatSendCommand,
+ kWhatEmptyThisBuffer,
+ kWhatFillThisBuffer,
+ };
+
+ Mutex mLock;
+
+ sp<ALooper> mLooper;
+ sp<AHandlerReflector<SimpleSoftOMXComponent> > mHandler;
+
+ OMX_STATETYPE mState;
+ OMX_STATETYPE mTargetState;
+
+ Vector<PortInfo> mPorts;
+
+ bool isSetParameterAllowed(
+ OMX_INDEXTYPE index, const OMX_PTR params) const;
+
+ virtual OMX_ERRORTYPE sendCommand(
+ OMX_COMMANDTYPE cmd, OMX_U32 param, OMX_PTR data);
+
+ virtual OMX_ERRORTYPE getParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE setParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual OMX_ERRORTYPE useBuffer(
+ OMX_BUFFERHEADERTYPE **buffer,
+ OMX_U32 portIndex,
+ OMX_PTR appPrivate,
+ OMX_U32 size,
+ OMX_U8 *ptr);
+
+ virtual OMX_ERRORTYPE allocateBuffer(
+ OMX_BUFFERHEADERTYPE **buffer,
+ OMX_U32 portIndex,
+ OMX_PTR appPrivate,
+ OMX_U32 size);
+
+ virtual OMX_ERRORTYPE freeBuffer(
+ OMX_U32 portIndex,
+ OMX_BUFFERHEADERTYPE *buffer);
+
+ virtual OMX_ERRORTYPE emptyThisBuffer(
+ OMX_BUFFERHEADERTYPE *buffer);
+
+ virtual OMX_ERRORTYPE fillThisBuffer(
+ OMX_BUFFERHEADERTYPE *buffer);
+
+ virtual OMX_ERRORTYPE getState(OMX_STATETYPE *state);
+
+ void onSendCommand(OMX_COMMANDTYPE cmd, OMX_U32 param);
+ void onChangeState(OMX_STATETYPE state);
+ void onPortEnable(OMX_U32 portIndex, bool enable);
+ void onPortFlush(OMX_U32 portIndex, bool sendFlushComplete);
+
+ void checkTransitions();
+
+ DISALLOW_EVIL_CONSTRUCTORS(SimpleSoftOMXComponent);
+};
+
+} // namespace android
+
+#endif // SIMPLE_SOFT_OMX_COMPONENT_H_
diff --git a/media/libstagefright/include/SoftOMXComponent.h b/media/libstagefright/include/SoftOMXComponent.h
new file mode 100644
index 0000000..a808611
--- /dev/null
+++ b/media/libstagefright/include/SoftOMXComponent.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SOFT_OMX_COMPONENT_H_
+
+#define SOFT_OMX_COMPONENT_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AString.h>
+#include <utils/RefBase.h>
+
+#include <OMX_Component.h>
+
+namespace android {
+
+struct SoftOMXComponent : public RefBase {
+ SoftOMXComponent(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+ virtual OMX_ERRORTYPE initCheck() const;
+
+ void setLibHandle(void *libHandle);
+ void *libHandle() const;
+
+ virtual void prepareForDestruction() {}
+
+protected:
+ virtual ~SoftOMXComponent();
+
+ const char *name() const;
+
+ void notify(
+ OMX_EVENTTYPE event,
+ OMX_U32 data1, OMX_U32 data2, OMX_PTR data);
+
+ void notifyEmptyBufferDone(OMX_BUFFERHEADERTYPE *header);
+ void notifyFillBufferDone(OMX_BUFFERHEADERTYPE *header);
+
+ virtual OMX_ERRORTYPE sendCommand(
+ OMX_COMMANDTYPE cmd, OMX_U32 param, OMX_PTR data);
+
+ virtual OMX_ERRORTYPE getParameter(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE setParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual OMX_ERRORTYPE getConfig(
+ OMX_INDEXTYPE index, OMX_PTR params);
+
+ virtual OMX_ERRORTYPE setConfig(
+ OMX_INDEXTYPE index, const OMX_PTR params);
+
+ virtual OMX_ERRORTYPE getExtensionIndex(
+ const char *name, OMX_INDEXTYPE *index);
+
+ virtual OMX_ERRORTYPE useBuffer(
+ OMX_BUFFERHEADERTYPE **buffer,
+ OMX_U32 portIndex,
+ OMX_PTR appPrivate,
+ OMX_U32 size,
+ OMX_U8 *ptr);
+
+ virtual OMX_ERRORTYPE allocateBuffer(
+ OMX_BUFFERHEADERTYPE **buffer,
+ OMX_U32 portIndex,
+ OMX_PTR appPrivate,
+ OMX_U32 size);
+
+ virtual OMX_ERRORTYPE freeBuffer(
+ OMX_U32 portIndex,
+ OMX_BUFFERHEADERTYPE *buffer);
+
+ virtual OMX_ERRORTYPE emptyThisBuffer(
+ OMX_BUFFERHEADERTYPE *buffer);
+
+ virtual OMX_ERRORTYPE fillThisBuffer(
+ OMX_BUFFERHEADERTYPE *buffer);
+
+ virtual OMX_ERRORTYPE getState(OMX_STATETYPE *state);
+
+private:
+ AString mName;
+ const OMX_CALLBACKTYPE *mCallbacks;
+ OMX_COMPONENTTYPE *mComponent;
+
+ void *mLibHandle;
+
+ static OMX_ERRORTYPE SendCommandWrapper(
+ OMX_HANDLETYPE component,
+ OMX_COMMANDTYPE cmd,
+ OMX_U32 param,
+ OMX_PTR data);
+
+ static OMX_ERRORTYPE GetParameterWrapper(
+ OMX_HANDLETYPE component,
+ OMX_INDEXTYPE index,
+ OMX_PTR params);
+
+ static OMX_ERRORTYPE SetParameterWrapper(
+ OMX_HANDLETYPE component,
+ OMX_INDEXTYPE index,
+ OMX_PTR params);
+
+ static OMX_ERRORTYPE GetConfigWrapper(
+ OMX_HANDLETYPE component,
+ OMX_INDEXTYPE index,
+ OMX_PTR params);
+
+ static OMX_ERRORTYPE SetConfigWrapper(
+ OMX_HANDLETYPE component,
+ OMX_INDEXTYPE index,
+ OMX_PTR params);
+
+ static OMX_ERRORTYPE GetExtensionIndexWrapper(
+ OMX_HANDLETYPE component,
+ OMX_STRING name,
+ OMX_INDEXTYPE *index);
+
+ static OMX_ERRORTYPE UseBufferWrapper(
+ OMX_HANDLETYPE component,
+ OMX_BUFFERHEADERTYPE **buffer,
+ OMX_U32 portIndex,
+ OMX_PTR appPrivate,
+ OMX_U32 size,
+ OMX_U8 *ptr);
+
+ static OMX_ERRORTYPE AllocateBufferWrapper(
+ OMX_HANDLETYPE component,
+ OMX_BUFFERHEADERTYPE **buffer,
+ OMX_U32 portIndex,
+ OMX_PTR appPrivate,
+ OMX_U32 size);
+
+ static OMX_ERRORTYPE FreeBufferWrapper(
+ OMX_HANDLETYPE component,
+ OMX_U32 portIndex,
+ OMX_BUFFERHEADERTYPE *buffer);
+
+ static OMX_ERRORTYPE EmptyThisBufferWrapper(
+ OMX_HANDLETYPE component,
+ OMX_BUFFERHEADERTYPE *buffer);
+
+ static OMX_ERRORTYPE FillThisBufferWrapper(
+ OMX_HANDLETYPE component,
+ OMX_BUFFERHEADERTYPE *buffer);
+
+ static OMX_ERRORTYPE GetStateWrapper(
+ OMX_HANDLETYPE component,
+ OMX_STATETYPE *state);
+
+ DISALLOW_EVIL_CONSTRUCTORS(SoftOMXComponent);
+};
+
+} // namespace android
+
+#endif // SOFT_OMX_COMPONENT_H_
diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h
new file mode 100644
index 0000000..7ab0042
--- /dev/null
+++ b/media/libstagefright/include/SoftwareRenderer.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef SOFTWARE_RENDERER_H_
+
+#define SOFTWARE_RENDERER_H_
+
+#include <media/stagefright/ColorConverter.h>
+#include <utils/RefBase.h>
+#include <system/window.h>
+
+namespace android {
+
+struct MetaData;
+
+class SoftwareRenderer {
+public:
+ SoftwareRenderer(
+ const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta);
+
+ ~SoftwareRenderer();
+
+ void render(
+ const void *data, size_t size, void *platformPrivate);
+
+private:
+ enum YUVMode {
+ None,
+ };
+
+ OMX_COLOR_FORMATTYPE mColorFormat;
+ ColorConverter *mConverter;
+ YUVMode mYUVMode;
+ sp<ANativeWindow> mNativeWindow;
+ int32_t mWidth, mHeight;
+ int32_t mCropLeft, mCropTop, mCropRight, mCropBottom;
+ int32_t mCropWidth, mCropHeight;
+
+ SoftwareRenderer(const SoftwareRenderer &);
+ SoftwareRenderer &operator=(const SoftwareRenderer &);
+};
+
+} // namespace android
+
+#endif // SOFTWARE_RENDERER_H_
diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libstagefright/include/StagefrightMetadataRetriever.h
new file mode 100644
index 0000000..b02ed0e
--- /dev/null
+++ b/media/libstagefright/include/StagefrightMetadataRetriever.h
@@ -0,0 +1,64 @@
+/*
+ * 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 STAGEFRIGHT_METADATA_RETRIEVER_H_
+
+#define STAGEFRIGHT_METADATA_RETRIEVER_H_
+
+#include <media/MediaMetadataRetrieverInterface.h>
+
+#include <media/stagefright/OMXClient.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+struct DataSource;
+class MediaExtractor;
+
+struct StagefrightMetadataRetriever : public MediaMetadataRetrieverInterface {
+ StagefrightMetadataRetriever();
+ virtual ~StagefrightMetadataRetriever();
+
+ virtual status_t setDataSource(
+ const char *url,
+ const KeyedVector<String8, String8> *headers);
+
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
+
+ virtual VideoFrame *getFrameAtTime(int64_t timeUs, int option);
+ virtual MediaAlbumArt *extractAlbumArt();
+ virtual const char *extractMetadata(int keyCode);
+
+private:
+ OMXClient mClient;
+ sp<DataSource> mSource;
+ sp<MediaExtractor> mExtractor;
+
+ bool mParsedMetaData;
+ KeyedVector<int, String8> mMetaData;
+ MediaAlbumArt *mAlbumArt;
+
+ void parseMetaData();
+
+ StagefrightMetadataRetriever(const StagefrightMetadataRetriever &);
+
+ StagefrightMetadataRetriever &operator=(
+ const StagefrightMetadataRetriever &);
+};
+
+} // namespace android
+
+#endif // STAGEFRIGHT_METADATA_RETRIEVER_H_
diff --git a/media/libstagefright/include/ThrottledSource.h b/media/libstagefright/include/ThrottledSource.h
new file mode 100644
index 0000000..7fe7c06
--- /dev/null
+++ b/media/libstagefright/include/ThrottledSource.h
@@ -0,0 +1,57 @@
+/*
+ * 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(off64_t offset, void *data, size_t size);
+
+ virtual status_t getSize(off64_t *size);
+ virtual uint32_t flags();
+
+ virtual String8 getMIMEType() const {
+ return mSource->getMIMEType();
+ }
+
+
+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/TimedEventQueue.h b/media/libstagefright/include/TimedEventQueue.h
new file mode 100644
index 0000000..11f844c
--- /dev/null
+++ b/media/libstagefright/include/TimedEventQueue.h
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+#ifndef TIMED_EVENT_QUEUE_H_
+
+#define TIMED_EVENT_QUEUE_H_
+
+#include <pthread.h>
+
+#include <utils/List.h>
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct TimedEventQueue {
+
+ typedef int32_t event_id;
+
+ struct Event : public RefBase {
+ Event()
+ : mEventID(0) {
+ }
+
+ virtual ~Event() {}
+
+ event_id eventID() {
+ return mEventID;
+ }
+
+ protected:
+ virtual void fire(TimedEventQueue *queue, int64_t now_us) = 0;
+
+ private:
+ friend class TimedEventQueue;
+
+ event_id mEventID;
+
+ void setEventID(event_id id) {
+ mEventID = id;
+ }
+
+ Event(const Event &);
+ Event &operator=(const Event &);
+ };
+
+ TimedEventQueue();
+ ~TimedEventQueue();
+
+ // Start executing the event loop.
+ void start();
+
+ // Stop executing the event loop, if flush is false, any pending
+ // events are discarded, otherwise the queue will stop (and this call
+ // return) once all pending events have been handled.
+ void stop(bool flush = false);
+
+ // Posts an event to the front of the queue (after all events that
+ // have previously been posted to the front but before timed events).
+ event_id postEvent(const sp<Event> &event);
+
+ event_id postEventToBack(const sp<Event> &event);
+
+ // It is an error to post an event with a negative delay.
+ event_id postEventWithDelay(const sp<Event> &event, int64_t delay_us);
+
+ // If the event is to be posted at a time that has already passed,
+ // it will fire as soon as possible.
+ event_id postTimedEvent(const sp<Event> &event, int64_t realtime_us);
+
+ // Returns true iff event is currently in the queue and has been
+ // successfully cancelled. In this case the event will have been
+ // removed from the queue and won't fire.
+ bool cancelEvent(event_id id);
+
+ // Cancel any pending event that satisfies the predicate.
+ // If stopAfterFirstMatch is true, only cancels the first event
+ // satisfying the predicate (if any).
+ void cancelEvents(
+ bool (*predicate)(void *cookie, const sp<Event> &event),
+ void *cookie,
+ bool stopAfterFirstMatch = false);
+
+ static int64_t getRealTimeUs();
+
+private:
+ struct QueueItem {
+ sp<Event> event;
+ int64_t realtime_us;
+ };
+
+ struct StopEvent : public TimedEventQueue::Event {
+ virtual void fire(TimedEventQueue *queue, int64_t now_us) {
+ queue->mStopped = true;
+ }
+ };
+
+ pthread_t mThread;
+ List<QueueItem> mQueue;
+ Mutex mLock;
+ Condition mQueueNotEmptyCondition;
+ Condition mQueueHeadChangedCondition;
+ event_id mNextEventID;
+
+ bool mRunning;
+ bool mStopped;
+
+ static void *ThreadWrapper(void *me);
+ void threadEntry();
+
+ sp<Event> removeEventFromQueue_l(event_id id);
+
+ TimedEventQueue(const TimedEventQueue &);
+ TimedEventQueue &operator=(const TimedEventQueue &);
+};
+
+} // namespace android
+
+#endif // TIMED_EVENT_QUEUE_H_
diff --git a/media/libstagefright/include/VBRISeeker.h b/media/libstagefright/include/VBRISeeker.h
new file mode 100644
index 0000000..1a2bf9f
--- /dev/null
+++ b/media/libstagefright/include/VBRISeeker.h
@@ -0,0 +1,50 @@
+/*
+ * 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 VBRI_SEEKER_H_
+
+#define VBRI_SEEKER_H_
+
+#include "include/MP3Seeker.h"
+
+#include <utils/Vector.h>
+
+namespace android {
+
+struct DataSource;
+
+struct VBRISeeker : public MP3Seeker {
+ static sp<VBRISeeker> CreateFromSource(
+ const sp<DataSource> &source, off64_t post_id3_pos);
+
+ virtual bool getDuration(int64_t *durationUs);
+ virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos);
+
+private:
+ off64_t mBasePos;
+ int64_t mDurationUs;
+ Vector<uint32_t> mSegments;
+
+ VBRISeeker();
+
+ DISALLOW_EVIL_CONSTRUCTORS(VBRISeeker);
+};
+
+} // namespace android
+
+#endif // VBRI_SEEKER_H_
+
+
diff --git a/media/libstagefright/include/WAVExtractor.h b/media/libstagefright/include/WAVExtractor.h
new file mode 100644
index 0000000..c567ccd
--- /dev/null
+++ b/media/libstagefright/include/WAVExtractor.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#ifndef WAV_EXTRACTOR_H_
+
+#define WAV_EXTRACTOR_H_
+
+#include <utils/Errors.h>
+#include <media/stagefright/MediaExtractor.h>
+
+namespace android {
+
+struct AMessage;
+class DataSource;
+class String8;
+
+class WAVExtractor : public MediaExtractor {
+public:
+ // Extractor assumes ownership of "source".
+ WAVExtractor(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 ~WAVExtractor();
+
+private:
+ sp<DataSource> mDataSource;
+ status_t mInitCheck;
+ bool mValidFormat;
+ uint16_t mWaveFormat;
+ uint16_t mNumChannels;
+ uint32_t mChannelMask;
+ uint32_t mSampleRate;
+ uint16_t mBitsPerSample;
+ off64_t mDataOffset;
+ size_t mDataSize;
+ sp<MetaData> mTrackMeta;
+
+ status_t init();
+
+ WAVExtractor(const WAVExtractor &);
+ WAVExtractor &operator=(const WAVExtractor &);
+};
+
+bool SniffWAV(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
+} // namespace android
+
+#endif // WAV_EXTRACTOR_H_
+
diff --git a/media/libstagefright/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h
new file mode 100644
index 0000000..3c3ca89
--- /dev/null
+++ b/media/libstagefright/include/WVMExtractor.h
@@ -0,0 +1,86 @@
+/*
+ * 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 WVM_EXTRACTOR_H_
+
+#define WVM_EXTRACTOR_H_
+
+#include <media/stagefright/MediaExtractor.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+struct AMessage;
+class String8;
+class DataSource;
+
+class WVMLoadableExtractor : public MediaExtractor {
+public:
+ WVMLoadableExtractor() {}
+ virtual ~WVMLoadableExtractor() {}
+
+ virtual int64_t getCachedDurationUs(status_t *finalStatus) = 0;
+ virtual void setAdaptiveStreamingMode(bool adaptive) = 0;
+ virtual void setUID(uid_t uid) = 0;
+};
+
+class WVMExtractor : public MediaExtractor {
+public:
+ WVMExtractor(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();
+
+ // Return the amount of data cached from the current
+ // playback positiion (in us).
+ // While more data is still being fetched *finalStatus == OK,
+ // Once fetching is completed (no more data available), *finalStatus != OK
+ // If fetching completed normally (i.e. reached EOS instead of IO error)
+ // *finalStatus == ERROR_END_OF_STREAM
+ int64_t getCachedDurationUs(status_t *finalStatus);
+
+ // Set to use adaptive streaming mode by the WV component.
+ // If adaptive == true, adaptive streaming mode will be used.
+ // Default mode is non-adaptive streaming mode.
+ // Should set to use adaptive streaming mode only if widevine:// protocol
+ // is used.
+ void setAdaptiveStreamingMode(bool adaptive);
+
+ void setUID(uid_t uid);
+
+ static bool getVendorLibHandle();
+
+protected:
+ virtual ~WVMExtractor();
+
+private:
+ sp<DataSource> mDataSource;
+ sp<WVMLoadableExtractor> mImpl;
+
+ WVMExtractor(const WVMExtractor &);
+ WVMExtractor &operator=(const WVMExtractor &);
+};
+
+bool SniffWVM(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
+} // namespace android
+
+#endif // DRM_EXTRACTOR_H_
+
diff --git a/media/libstagefright/include/XINGSeeker.h b/media/libstagefright/include/XINGSeeker.h
new file mode 100644
index 0000000..c408576
--- /dev/null
+++ b/media/libstagefright/include/XINGSeeker.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 XING_SEEKER_H_
+
+#define XING_SEEKER_H_
+
+#include "include/MP3Seeker.h"
+
+namespace android {
+
+struct DataSource;
+
+struct XINGSeeker : public MP3Seeker {
+ static sp<XINGSeeker> CreateFromSource(
+ const sp<DataSource> &source, off64_t first_frame_pos);
+
+ virtual bool getDuration(int64_t *durationUs);
+ virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos);
+
+ virtual int32_t getEncoderDelay();
+ virtual int32_t getEncoderPadding();
+
+private:
+ int64_t mFirstFramePos;
+ int64_t mDurationUs;
+ int32_t mSizeBytes;
+ int32_t mEncoderDelay;
+ int32_t mEncoderPadding;
+
+ // TOC entries in XING header. Skip the first one since it's always 0.
+ unsigned char mTOC[99];
+ bool mTOCValid;
+
+ XINGSeeker();
+
+ DISALLOW_EVIL_CONSTRUCTORS(XINGSeeker);
+};
+
+} // namespace android
+
+#endif // XING_SEEKER_H_
+
diff --git a/media/libstagefright/include/avc_utils.h b/media/libstagefright/include/avc_utils.h
new file mode 100644
index 0000000..e418822
--- /dev/null
+++ b/media/libstagefright/include/avc_utils.h
@@ -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.
+ */
+
+#ifndef AVC_UTILS_H_
+
+#define AVC_UTILS_H_
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+struct ABitReader;
+
+enum {
+ kAVCProfileBaseline = 0x42,
+ kAVCProfileMain = 0x4d,
+ kAVCProfileExtended = 0x58,
+ kAVCProfileHigh = 0x64,
+ kAVCProfileHigh10 = 0x6e,
+ kAVCProfileHigh422 = 0x7a,
+ kAVCProfileHigh444 = 0xf4,
+ kAVCProfileCAVLC444Intra = 0x2c
+};
+
+void FindAVCDimensions(
+ const sp<ABuffer> &seqParamSet, int32_t *width, int32_t *height);
+
+unsigned parseUE(ABitReader *br);
+
+status_t getNextNALUnit(
+ const uint8_t **_data, size_t *_size,
+ const uint8_t **nalStart, size_t *nalSize,
+ bool startCodeFollows = false);
+
+struct MetaData;
+sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit);
+
+bool IsIDR(const sp<ABuffer> &accessUnit);
+bool IsAVCReferenceFrame(const sp<ABuffer> &accessUnit);
+
+const char *AVCProfileToString(uint8_t profile);
+
+sp<MetaData> MakeAACCodecSpecificData(
+ unsigned profile, unsigned sampling_freq_index,
+ unsigned channel_configuration);
+
+// Given an MPEG4 video VOL-header chunk (starting with 0x00 0x00 0x01 0x2?)
+// parse it and fill in dimensions, returns true iff successful.
+bool ExtractDimensionsFromVOLHeader(
+ const uint8_t *data, size_t size, int32_t *width, int32_t *height);
+
+bool GetMPEGAudioFrameSize(
+ uint32_t header, size_t *frame_size,
+ int *out_sampling_rate = NULL, int *out_channels = NULL,
+ int *out_bitrate = NULL, int *out_num_samples = NULL);
+
+} // namespace android
+
+#endif // AVC_UTILS_H_
diff --git a/media/libstagefright/matroska/Android.mk b/media/libstagefright/matroska/Android.mk
new file mode 100644
index 0000000..2cccb4f
--- /dev/null
+++ b/media/libstagefright/matroska/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ MatroskaExtractor.cpp
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/external/libvpx/mkvparser \
+ $(TOP)/frameworks/native/include/media/openmax \
+
+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..a0db719
--- /dev/null
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -0,0 +1,898 @@
+/*
+ * 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/foundation/ADebug.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.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) {
+ off64_t size;
+ if (mSource->getSize(&size) != OK) {
+ *total = -1;
+ *available = (long long)((1ull << 63) - 1);
+
+ return 0;
+ }
+
+ if (total) {
+ *total = size;
+ }
+
+ if (available) {
+ *available = size;
+ }
+
+ return 0;
+ }
+
+private:
+ sp<DataSource> mSource;
+
+ DataSourceReader(const DataSourceReader &);
+ DataSourceReader &operator=(const DataSourceReader &);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct BlockIterator {
+ BlockIterator(MatroskaExtractor *extractor, unsigned long trackNum);
+
+ bool eos() const;
+
+ void advance();
+ void reset();
+
+ void seek(
+ int64_t seekTimeUs, bool seekToKeyFrame,
+ int64_t *actualFrameTimeUs);
+
+ const mkvparser::Block *block() const;
+ int64_t blockTimeUs() const;
+
+private:
+ MatroskaExtractor *mExtractor;
+ unsigned long mTrackNum;
+
+ const mkvparser::Cluster *mCluster;
+ const mkvparser::BlockEntry *mBlockEntry;
+ long mBlockEntryIndex;
+
+ void advance_l();
+
+ 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);
+
+protected:
+ virtual ~MatroskaSource();
+
+private:
+ enum Type {
+ AVC,
+ AAC,
+ OTHER
+ };
+
+ sp<MatroskaExtractor> mExtractor;
+ size_t mTrackIndex;
+ Type mType;
+ bool mIsAudio;
+ BlockIterator mBlockIter;
+ size_t mNALSizeLen; // for type AVC
+
+ List<MediaBuffer *> mPendingFrames;
+
+ status_t advance();
+
+ status_t readBlock();
+ void clearPendingFrames();
+
+ MatroskaSource(const MatroskaSource &);
+ MatroskaSource &operator=(const MatroskaSource &);
+};
+
+MatroskaSource::MatroskaSource(
+ const sp<MatroskaExtractor> &extractor, size_t index)
+ : mExtractor(extractor),
+ mTrackIndex(index),
+ mType(OTHER),
+ mIsAudio(false),
+ mBlockIter(mExtractor.get(),
+ mExtractor->mTracks.itemAt(index).mTrackNum),
+ mNALSizeLen(0) {
+ sp<MetaData> meta = mExtractor->mTracks.itemAt(index).mMeta;
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ mIsAudio = !strncasecmp("audio/", mime, 6);
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ mType = AVC;
+
+ uint32_t dummy;
+ const uint8_t *avcc;
+ size_t avccSize;
+ CHECK(meta->findData(
+ kKeyAVCC, &dummy, (const void **)&avcc, &avccSize));
+
+ CHECK_GE(avccSize, 5u);
+
+ mNALSizeLen = 1 + (avcc[4] & 3);
+ ALOGV("mNALSizeLen = %d", mNALSizeLen);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+ mType = AAC;
+ }
+}
+
+MatroskaSource::~MatroskaSource() {
+ clearPendingFrames();
+}
+
+status_t MatroskaSource::start(MetaData *params) {
+ mBlockIter.reset();
+
+ return OK;
+}
+
+status_t MatroskaSource::stop() {
+ clearPendingFrames();
+
+ return OK;
+}
+
+sp<MetaData> MatroskaSource::getFormat() {
+ return mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+BlockIterator::BlockIterator(
+ MatroskaExtractor *extractor, unsigned long trackNum)
+ : mExtractor(extractor),
+ mTrackNum(trackNum),
+ mCluster(NULL),
+ mBlockEntry(NULL),
+ mBlockEntryIndex(0) {
+ reset();
+}
+
+bool BlockIterator::eos() const {
+ return mCluster == NULL || mCluster->EOS();
+}
+
+void BlockIterator::advance() {
+ Mutex::Autolock autoLock(mExtractor->mLock);
+ advance_l();
+}
+
+void BlockIterator::advance_l() {
+ for (;;) {
+ long res = mCluster->GetEntry(mBlockEntryIndex, mBlockEntry);
+ ALOGV("GetEntry returned %ld", res);
+
+ long long pos;
+ long len;
+ if (res < 0) {
+ // Need to parse this cluster some more
+
+ CHECK_EQ(res, mkvparser::E_BUFFER_NOT_FULL);
+
+ res = mCluster->Parse(pos, len);
+ ALOGV("Parse returned %ld", res);
+
+ if (res < 0) {
+ // I/O error
+
+ ALOGE("Cluster::Parse returned result %ld", res);
+
+ mCluster = NULL;
+ break;
+ }
+
+ continue;
+ } else if (res == 0) {
+ // We're done with this cluster
+
+ const mkvparser::Cluster *nextCluster;
+ res = mExtractor->mSegment->ParseNext(
+ mCluster, nextCluster, pos, len);
+ ALOGV("ParseNext returned %ld", res);
+
+ if (res > 0) {
+ // EOF
+
+ mCluster = NULL;
+ break;
+ }
+
+ CHECK_EQ(res, 0);
+ CHECK(nextCluster != NULL);
+ CHECK(!nextCluster->EOS());
+
+ mCluster = nextCluster;
+
+ res = mCluster->Parse(pos, len);
+ ALOGV("Parse (2) returned %ld", res);
+ CHECK_GE(res, 0);
+
+ mBlockEntryIndex = 0;
+ continue;
+ }
+
+ CHECK(mBlockEntry != NULL);
+ CHECK(mBlockEntry->GetBlock() != NULL);
+ ++mBlockEntryIndex;
+
+ if (mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
+ break;
+ }
+ }
+}
+
+void BlockIterator::reset() {
+ Mutex::Autolock autoLock(mExtractor->mLock);
+
+ mCluster = mExtractor->mSegment->GetFirst();
+ mBlockEntry = NULL;
+ mBlockEntryIndex = 0;
+
+ do {
+ advance_l();
+ } while (!eos() && block()->GetTrackNumber() != mTrackNum);
+}
+
+void BlockIterator::seek(
+ int64_t seekTimeUs, bool seekToKeyFrame,
+ int64_t *actualFrameTimeUs) {
+ Mutex::Autolock autoLock(mExtractor->mLock);
+
+ *actualFrameTimeUs = -1ll;
+
+ int64_t seekTimeNs = seekTimeUs * 1000ll;
+
+ mCluster = mExtractor->mSegment->FindCluster(seekTimeNs);
+ mBlockEntry = NULL;
+ mBlockEntryIndex = 0;
+
+ long prevKeyFrameBlockEntryIndex = -1;
+
+ for (;;) {
+ advance_l();
+
+ if (eos()) {
+ break;
+ }
+
+ if (block()->GetTrackNumber() != mTrackNum) {
+ continue;
+ }
+
+ if (block()->IsKey()) {
+ prevKeyFrameBlockEntryIndex = mBlockEntryIndex - 1;
+ }
+
+ int64_t timeNs = block()->GetTime(mCluster);
+
+ if (timeNs >= seekTimeNs) {
+ *actualFrameTimeUs = (timeNs + 500ll) / 1000ll;
+ break;
+ }
+ }
+
+ if (eos()) {
+ return;
+ }
+
+ if (seekToKeyFrame && !block()->IsKey()) {
+ CHECK_GE(prevKeyFrameBlockEntryIndex, 0);
+ mBlockEntryIndex = prevKeyFrameBlockEntryIndex;
+ advance_l();
+ }
+}
+
+const mkvparser::Block *BlockIterator::block() const {
+ CHECK(!eos());
+
+ return mBlockEntry->GetBlock();
+}
+
+int64_t BlockIterator::blockTimeUs() const {
+ return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+static unsigned U24_AT(const uint8_t *ptr) {
+ return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
+}
+
+static size_t clz(uint8_t x) {
+ size_t numLeadingZeroes = 0;
+
+ while (!(x & 0x80)) {
+ ++numLeadingZeroes;
+ x = x << 1;
+ }
+
+ return numLeadingZeroes;
+}
+
+void MatroskaSource::clearPendingFrames() {
+ while (!mPendingFrames.empty()) {
+ MediaBuffer *frame = *mPendingFrames.begin();
+ mPendingFrames.erase(mPendingFrames.begin());
+
+ frame->release();
+ frame = NULL;
+ }
+}
+
+status_t MatroskaSource::readBlock() {
+ CHECK(mPendingFrames.empty());
+
+ if (mBlockIter.eos()) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ const mkvparser::Block *block = mBlockIter.block();
+
+ int64_t timeUs = mBlockIter.blockTimeUs();
+
+ for (int i = 0; i < block->GetFrameCount(); ++i) {
+ const mkvparser::Block::Frame &frame = block->GetFrame(i);
+
+ MediaBuffer *mbuf = new MediaBuffer(frame.len);
+ mbuf->meta_data()->setInt64(kKeyTime, timeUs);
+ mbuf->meta_data()->setInt32(kKeyIsSyncFrame, block->IsKey());
+
+ long n = frame.Read(mExtractor->mReader, (unsigned char *)mbuf->data());
+ if (n != 0) {
+ mPendingFrames.clear();
+
+ mBlockIter.advance();
+ return ERROR_IO;
+ }
+
+ mPendingFrames.push_back(mbuf);
+ }
+
+ mBlockIter.advance();
+
+ return OK;
+}
+
+status_t MatroskaSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ int64_t targetSampleTimeUs = -1ll;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)
+ && !mExtractor->isLiveStreaming()) {
+ clearPendingFrames();
+
+ // Apparently keyframe indication in audio tracks is unreliable,
+ // fortunately in all our currently supported audio encodings every
+ // frame is effectively a keyframe.
+ int64_t actualFrameTimeUs;
+ mBlockIter.seek(seekTimeUs, !mIsAudio, &actualFrameTimeUs);
+
+ if (mode == ReadOptions::SEEK_CLOSEST) {
+ targetSampleTimeUs = actualFrameTimeUs;
+ }
+ }
+
+ while (mPendingFrames.empty()) {
+ status_t err = readBlock();
+
+ if (err != OK) {
+ clearPendingFrames();
+
+ return err;
+ }
+ }
+
+ MediaBuffer *frame = *mPendingFrames.begin();
+ mPendingFrames.erase(mPendingFrames.begin());
+
+ if (mType != AVC) {
+ if (targetSampleTimeUs >= 0ll) {
+ frame->meta_data()->setInt64(
+ kKeyTargetTime, targetSampleTimeUs);
+ }
+
+ *out = frame;
+
+ return OK;
+ }
+
+ // Each input frame contains one or more NAL fragments, each fragment
+ // is prefixed by mNALSizeLen bytes giving the fragment length,
+ // followed by a corresponding number of bytes containing the fragment.
+ // We output all these fragments into a single large buffer separated
+ // by startcodes (0x00 0x00 0x00 0x01).
+
+ const uint8_t *srcPtr =
+ (const uint8_t *)frame->data() + frame->range_offset();
+
+ size_t srcSize = frame->range_length();
+
+ size_t dstSize = 0;
+ MediaBuffer *buffer = NULL;
+ uint8_t *dstPtr = NULL;
+
+ for (int32_t pass = 0; pass < 2; ++pass) {
+ size_t srcOffset = 0;
+ size_t dstOffset = 0;
+ while (srcOffset + mNALSizeLen <= srcSize) {
+ size_t NALsize;
+ switch (mNALSizeLen) {
+ case 1: NALsize = srcPtr[srcOffset]; break;
+ case 2: NALsize = U16_AT(srcPtr + srcOffset); break;
+ case 3: NALsize = U24_AT(srcPtr + srcOffset); break;
+ case 4: NALsize = U32_AT(srcPtr + srcOffset); break;
+ default:
+ TRESPASS();
+ }
+
+ if (srcOffset + mNALSizeLen + NALsize > srcSize) {
+ break;
+ }
+
+ if (pass == 1) {
+ memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4);
+
+ memcpy(&dstPtr[dstOffset + 4],
+ &srcPtr[srcOffset + mNALSizeLen],
+ NALsize);
+ }
+
+ dstOffset += 4; // 0x00 00 00 01
+ dstOffset += NALsize;
+
+ srcOffset += mNALSizeLen + NALsize;
+ }
+
+ if (srcOffset < srcSize) {
+ // There were trailing bytes or not enough data to complete
+ // a fragment.
+
+ frame->release();
+ frame = NULL;
+
+ return ERROR_MALFORMED;
+ }
+
+ if (pass == 0) {
+ dstSize = dstOffset;
+
+ buffer = new MediaBuffer(dstSize);
+
+ int64_t timeUs;
+ CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
+ int32_t isSync;
+ CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
+
+ buffer->meta_data()->setInt64(kKeyTime, timeUs);
+ buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
+
+ dstPtr = (uint8_t *)buffer->data();
+ }
+ }
+
+ frame->release();
+ frame = NULL;
+
+ if (targetSampleTimeUs >= 0ll) {
+ buffer->meta_data()->setInt64(
+ kKeyTargetTime, targetSampleTimeUs);
+ }
+
+ *out = buffer;
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
+ : mDataSource(source),
+ mReader(new DataSourceReader(mDataSource)),
+ mSegment(NULL),
+ mExtractedThumbnails(false),
+ mIsWebm(false) {
+ off64_t size;
+ mIsLiveStreaming =
+ (mDataSource->flags()
+ & (DataSource::kWantsPrefetching
+ | DataSource::kIsCachingDataSource))
+ && mDataSource->getSize(&size) != OK;
+
+ mkvparser::EBMLHeader ebmlHeader;
+ long long pos;
+ if (ebmlHeader.Parse(mReader, pos) < 0) {
+ return;
+ }
+
+ if (ebmlHeader.m_docType && !strcmp("webm", ebmlHeader.m_docType)) {
+ mIsWebm = true;
+ }
+
+ long long ret =
+ mkvparser::Segment::CreateInstance(mReader, pos, mSegment);
+
+ if (ret) {
+ CHECK(mSegment == NULL);
+ return;
+ }
+
+ if (isLiveStreaming()) {
+ ret = mSegment->ParseHeaders();
+ CHECK_EQ(ret, 0);
+
+ long len;
+ ret = mSegment->LoadCluster(pos, len);
+ CHECK_EQ(ret, 0);
+ } else {
+ ret = mSegment->Load();
+ }
+
+ if (ret < 0) {
+ delete mSegment;
+ mSegment = NULL;
+ return;
+ }
+
+#if 0
+ const mkvparser::SegmentInfo *info = mSegment->GetInfo();
+ ALOGI("muxing app: %s, writing app: %s",
+ info->GetMuxingAppAsUTF8(),
+ info->GetWritingAppAsUTF8());
+#endif
+
+ 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
+ && !isLiveStreaming()) {
+ findThumbnails();
+ mExtractedThumbnails = true;
+ }
+
+ return mTracks.itemAt(index).mMeta;
+}
+
+bool MatroskaExtractor::isLiveStreaming() const {
+ return mIsLiveStreaming;
+}
+
+static void addESDSFromCodecPrivate(
+ const sp<MetaData> &meta,
+ bool isAudio, const void *priv, size_t privSize) {
+ static const uint8_t kStaticESDS[] = {
+ 0x03, 22,
+ 0x00, 0x00, // ES_ID
+ 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+ 0x04, 17,
+ 0x40, // ObjectTypeIndication
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ 0x05,
+ // CodecSpecificInfo (with size prefix) follows
+ };
+
+ // Make sure all sizes can be coded in a single byte.
+ CHECK(privSize + 22 - 2 < 128);
+ size_t esdsSize = sizeof(kStaticESDS) + privSize + 1;
+ uint8_t *esds = new uint8_t[esdsSize];
+ memcpy(esds, kStaticESDS, sizeof(kStaticESDS));
+ uint8_t *ptr = esds + sizeof(kStaticESDS);
+ *ptr++ = privSize;
+ memcpy(ptr, priv, privSize);
+
+ // Increment by codecPrivateSize less 2 bytes that are accounted for
+ // already in lengths of 22/17
+ esds[1] += privSize - 2;
+ esds[6] += privSize - 2;
+
+ // Set ObjectTypeIndication.
+ esds[7] = isAudio ? 0x40 // Audio ISO/IEC 14496-3
+ : 0x20; // Visual ISO/IEC 14496-2
+
+ 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);
+
+ if (track == NULL) {
+ // Apparently this is currently valid (if unexpected) behaviour
+ // of the mkv parser lib.
+ continue;
+ }
+
+ const char *const codecID = track->GetCodecId();
+ ALOGV("codec id = %s", codecID);
+ ALOGV("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_MPEG4/ISO/ASP", codecID)) {
+ if (codecPrivateSize > 0) {
+ meta->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+ addESDSFromCodecPrivate(
+ meta, false, codecPrivate, codecPrivateSize);
+ } else {
+ ALOGW("%s is detected, but does not have configuration.",
+ codecID);
+ continue;
+ }
+ } else if (!strcmp("V_VP8", codecID)) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VPX);
+ } else {
+ ALOGW("%s is not supported.", codecID);
+ 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);
+
+ addESDSFromCodecPrivate(
+ meta, true, codecPrivate, codecPrivateSize);
+ } else if (!strcmp("A_VORBIS", codecID)) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
+
+ addVorbisCodecInfo(meta, codecPrivate, codecPrivateSize);
+ } else if (!strcmp("A_MPEG/L3", codecID)) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+ } else {
+ ALOGW("%s is not supported.", codecID);
+ 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(this, 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 = 0;
+ for (int i = 0; i < iter.block()->GetFrameCount(); ++i) {
+ blockSize += iter.block()->GetFrame(i).len;
+ }
+
+ 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,
+ mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA);
+
+ return meta;
+}
+
+uint32_t MatroskaExtractor::flags() const {
+ uint32_t x = CAN_PAUSE;
+ if (!isLiveStreaming()) {
+ x |= CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK;
+ }
+
+ return x;
+}
+
+bool SniffMatroska(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
+ 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..1294b4f
--- /dev/null
+++ b/media/libstagefright/matroska/MatroskaExtractor.h
@@ -0,0 +1,88 @@
+/*
+ * 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>
+#include <utils/threads.h>
+
+namespace mkvparser {
+struct Segment;
+};
+
+namespace android {
+
+struct AMessage;
+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();
+
+ virtual uint32_t flags() const;
+
+protected:
+ virtual ~MatroskaExtractor();
+
+private:
+ friend struct MatroskaSource;
+ friend struct BlockIterator;
+
+ struct TrackInfo {
+ unsigned long mTrackNum;
+ sp<MetaData> mMeta;
+ };
+
+ Mutex mLock;
+ Vector<TrackInfo> mTracks;
+
+ sp<DataSource> mDataSource;
+ DataSourceReader *mReader;
+ mkvparser::Segment *mSegment;
+ bool mExtractedThumbnails;
+ bool mIsLiveStreaming;
+ bool mIsWebm;
+
+ void addTracks();
+ void findThumbnails();
+
+ bool isLiveStreaming() const;
+
+ MatroskaExtractor(const MatroskaExtractor &);
+ MatroskaExtractor &operator=(const MatroskaExtractor &);
+};
+
+bool SniffMatroska(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
+
+} // namespace android
+
+#endif // MATROSKA_EXTRACTOR_H_
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
new file mode 100644
index 0000000..3f4de1f
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -0,0 +1,1012 @@
+/*
+ * 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 "ATSParser"
+#include <utils/Log.h>
+
+#include "ATSParser.h"
+
+#include "AnotherPacketSource.h"
+#include "ESQueue.h"
+#include "include/avc_utils.h"
+
+#include <media/stagefright/foundation/ABitReader.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 <media/IStreamSource.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+// I want the expression "y" evaluated even if verbose logging is off.
+#define MY_LOGV(x, y) \
+ do { unsigned tmp = y; ALOGV(x, tmp); } while (0)
+
+static const size_t kTSPacketSize = 188;
+
+struct ATSParser::Program : public RefBase {
+ Program(ATSParser *parser, unsigned programNumber, unsigned programMapPID);
+
+ bool parsePID(
+ unsigned pid, unsigned payload_unit_start_indicator,
+ ABitReader *br, status_t *err);
+
+ void signalDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra);
+
+ void signalEOS(status_t finalResult);
+
+ sp<MediaSource> getSource(SourceType type);
+
+ int64_t convertPTSToTimestamp(uint64_t PTS);
+
+ bool PTSTimeDeltaEstablished() const {
+ return mFirstPTSValid;
+ }
+
+ unsigned number() const { return mProgramNumber; }
+
+ void updateProgramMapPID(unsigned programMapPID) {
+ mProgramMapPID = programMapPID;
+ }
+
+private:
+ ATSParser *mParser;
+ unsigned mProgramNumber;
+ unsigned mProgramMapPID;
+ KeyedVector<unsigned, sp<Stream> > mStreams;
+ bool mFirstPTSValid;
+ uint64_t mFirstPTS;
+
+ status_t parseProgramMap(ABitReader *br);
+
+ DISALLOW_EVIL_CONSTRUCTORS(Program);
+};
+
+struct ATSParser::Stream : public RefBase {
+ Stream(Program *program, unsigned elementaryPID, unsigned streamType);
+
+ unsigned type() const { return mStreamType; }
+ unsigned pid() const { return mElementaryPID; }
+ void setPID(unsigned pid) { mElementaryPID = pid; }
+
+ status_t parse(
+ unsigned payload_unit_start_indicator,
+ ABitReader *br);
+
+ void signalDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra);
+
+ void signalEOS(status_t finalResult);
+
+ sp<MediaSource> getSource(SourceType type);
+
+protected:
+ virtual ~Stream();
+
+private:
+ Program *mProgram;
+ unsigned mElementaryPID;
+ unsigned mStreamType;
+
+ sp<ABuffer> mBuffer;
+ sp<AnotherPacketSource> mSource;
+ bool mPayloadStarted;
+
+ ElementaryStreamQueue *mQueue;
+
+ status_t flush();
+ status_t parsePES(ABitReader *br);
+
+ void onPayloadData(
+ unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
+ const uint8_t *data, size_t size);
+
+ void extractAACFrames(const sp<ABuffer> &buffer);
+
+ bool isAudio() const;
+ bool isVideo() const;
+
+ DISALLOW_EVIL_CONSTRUCTORS(Stream);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+ATSParser::Program::Program(
+ ATSParser *parser, unsigned programNumber, unsigned programMapPID)
+ : mParser(parser),
+ mProgramNumber(programNumber),
+ mProgramMapPID(programMapPID),
+ mFirstPTSValid(false),
+ mFirstPTS(0) {
+ ALOGV("new program number %u", programNumber);
+}
+
+bool ATSParser::Program::parsePID(
+ unsigned pid, unsigned payload_unit_start_indicator,
+ ABitReader *br, status_t *err) {
+ *err = OK;
+
+ if (pid == mProgramMapPID) {
+ if (payload_unit_start_indicator) {
+ unsigned skip = br->getBits(8);
+ br->skipBits(skip * 8);
+ }
+
+ *err = parseProgramMap(br);
+
+ return true;
+ }
+
+ ssize_t index = mStreams.indexOfKey(pid);
+ if (index < 0) {
+ return false;
+ }
+
+ *err = mStreams.editValueAt(index)->parse(
+ payload_unit_start_indicator, br);
+
+ return true;
+}
+
+void ATSParser::Program::signalDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra) {
+ for (size_t i = 0; i < mStreams.size(); ++i) {
+ mStreams.editValueAt(i)->signalDiscontinuity(type, extra);
+ }
+}
+
+void ATSParser::Program::signalEOS(status_t finalResult) {
+ for (size_t i = 0; i < mStreams.size(); ++i) {
+ mStreams.editValueAt(i)->signalEOS(finalResult);
+ }
+}
+
+struct StreamInfo {
+ unsigned mType;
+ unsigned mPID;
+};
+
+status_t ATSParser::Program::parseProgramMap(ABitReader *br) {
+ unsigned table_id = br->getBits(8);
+ ALOGV(" table_id = %u", table_id);
+ CHECK_EQ(table_id, 0x02u);
+
+ unsigned section_syntax_indicator = br->getBits(1);
+ ALOGV(" section_syntax_indicator = %u", section_syntax_indicator);
+ CHECK_EQ(section_syntax_indicator, 1u);
+
+ CHECK_EQ(br->getBits(1), 0u);
+ MY_LOGV(" reserved = %u", br->getBits(2));
+
+ unsigned section_length = br->getBits(12);
+ ALOGV(" section_length = %u", section_length);
+ CHECK_EQ(section_length & 0xc00, 0u);
+ CHECK_LE(section_length, 1021u);
+
+ MY_LOGV(" program_number = %u", br->getBits(16));
+ MY_LOGV(" reserved = %u", br->getBits(2));
+ MY_LOGV(" version_number = %u", br->getBits(5));
+ MY_LOGV(" current_next_indicator = %u", br->getBits(1));
+ MY_LOGV(" section_number = %u", br->getBits(8));
+ MY_LOGV(" last_section_number = %u", br->getBits(8));
+ MY_LOGV(" reserved = %u", br->getBits(3));
+ MY_LOGV(" PCR_PID = 0x%04x", br->getBits(13));
+ MY_LOGV(" reserved = %u", br->getBits(4));
+
+ unsigned program_info_length = br->getBits(12);
+ ALOGV(" program_info_length = %u", program_info_length);
+ CHECK_EQ(program_info_length & 0xc00, 0u);
+
+ br->skipBits(program_info_length * 8); // skip descriptors
+
+ Vector<StreamInfo> infos;
+
+ // 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);
+ ALOGV(" stream_type = 0x%02x", streamType);
+
+ MY_LOGV(" reserved = %u", br->getBits(3));
+
+ unsigned elementaryPID = br->getBits(13);
+ ALOGV(" elementary_PID = 0x%04x", elementaryPID);
+
+ MY_LOGV(" reserved = %u", br->getBits(4));
+
+ unsigned ES_info_length = br->getBits(12);
+ ALOGV(" ES_info_length = %u", ES_info_length);
+ CHECK_EQ(ES_info_length & 0xc00, 0u);
+
+ 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) {
+ MY_LOGV(" tag = 0x%02x", br->getBits(8));
+
+ unsigned descLength = br->getBits(8);
+ ALOGV(" len = %u", descLength);
+
+ CHECK_GE(info_bytes_remaining, 2 + descLength);
+
+ br->skipBits(descLength * 8);
+
+ info_bytes_remaining -= descLength + 2;
+ }
+ CHECK_EQ(info_bytes_remaining, 0u);
+#endif
+
+ StreamInfo info;
+ info.mType = streamType;
+ info.mPID = elementaryPID;
+ infos.push(info);
+
+ infoBytesRemaining -= 5 + ES_info_length;
+ }
+
+ CHECK_EQ(infoBytesRemaining, 0u);
+ MY_LOGV(" CRC = 0x%08x", br->getBits(32));
+
+ bool PIDsChanged = false;
+ for (size_t i = 0; i < infos.size(); ++i) {
+ StreamInfo &info = infos.editItemAt(i);
+
+ ssize_t index = mStreams.indexOfKey(info.mPID);
+
+ if (index >= 0 && mStreams.editValueAt(index)->type() != info.mType) {
+ ALOGI("uh oh. stream PIDs have changed.");
+ PIDsChanged = true;
+ break;
+ }
+ }
+
+ if (PIDsChanged) {
+#if 0
+ ALOGI("before:");
+ for (size_t i = 0; i < mStreams.size(); ++i) {
+ sp<Stream> stream = mStreams.editValueAt(i);
+
+ ALOGI("PID 0x%08x => type 0x%02x", stream->pid(), stream->type());
+ }
+
+ ALOGI("after:");
+ for (size_t i = 0; i < infos.size(); ++i) {
+ StreamInfo &info = infos.editItemAt(i);
+
+ ALOGI("PID 0x%08x => type 0x%02x", info.mPID, info.mType);
+ }
+#endif
+
+ // The only case we can recover from is if we have two streams
+ // and they switched PIDs.
+
+ bool success = false;
+
+ if (mStreams.size() == 2 && infos.size() == 2) {
+ const StreamInfo &info1 = infos.itemAt(0);
+ const StreamInfo &info2 = infos.itemAt(1);
+
+ sp<Stream> s1 = mStreams.editValueAt(0);
+ sp<Stream> s2 = mStreams.editValueAt(1);
+
+ bool caseA =
+ info1.mPID == s1->pid() && info1.mType == s2->type()
+ && info2.mPID == s2->pid() && info2.mType == s1->type();
+
+ bool caseB =
+ info1.mPID == s2->pid() && info1.mType == s1->type()
+ && info2.mPID == s1->pid() && info2.mType == s2->type();
+
+ if (caseA || caseB) {
+ unsigned pid1 = s1->pid();
+ unsigned pid2 = s2->pid();
+ s1->setPID(pid2);
+ s2->setPID(pid1);
+
+ mStreams.clear();
+ mStreams.add(s1->pid(), s1);
+ mStreams.add(s2->pid(), s2);
+
+ success = true;
+ }
+ }
+
+ if (!success) {
+ ALOGI("Stream PIDs changed and we cannot recover.");
+ return ERROR_MALFORMED;
+ }
+ }
+
+ for (size_t i = 0; i < infos.size(); ++i) {
+ StreamInfo &info = infos.editItemAt(i);
+
+ ssize_t index = mStreams.indexOfKey(info.mPID);
+
+ if (index < 0) {
+ sp<Stream> stream = new Stream(this, info.mPID, info.mType);
+ mStreams.add(info.mPID, stream);
+ }
+ }
+
+ return OK;
+}
+
+sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
+ size_t index = (type == AUDIO) ? 0 : 0;
+
+ for (size_t i = 0; i < mStreams.size(); ++i) {
+ sp<MediaSource> source = mStreams.editValueAt(i)->getSource(type);
+ if (source != NULL) {
+ if (index == 0) {
+ return source;
+ }
+ --index;
+ }
+ }
+
+ return NULL;
+}
+
+int64_t ATSParser::Program::convertPTSToTimestamp(uint64_t PTS) {
+ if (!(mParser->mFlags & TS_TIMESTAMPS_ARE_ABSOLUTE)) {
+ if (!mFirstPTSValid) {
+ mFirstPTSValid = true;
+ mFirstPTS = PTS;
+ PTS = 0;
+ } else if (PTS < mFirstPTS) {
+ PTS = 0;
+ } else {
+ PTS -= mFirstPTS;
+ }
+ }
+
+ return (PTS * 100) / 9;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ATSParser::Stream::Stream(
+ Program *program, unsigned elementaryPID, unsigned streamType)
+ : mProgram(program),
+ mElementaryPID(elementaryPID),
+ mStreamType(streamType),
+ mPayloadStarted(false),
+ mQueue(NULL) {
+ switch (mStreamType) {
+ case STREAMTYPE_H264:
+ mQueue = new ElementaryStreamQueue(ElementaryStreamQueue::H264);
+ break;
+ case STREAMTYPE_MPEG2_AUDIO_ADTS:
+ mQueue = new ElementaryStreamQueue(ElementaryStreamQueue::AAC);
+ break;
+ case STREAMTYPE_MPEG1_AUDIO:
+ case STREAMTYPE_MPEG2_AUDIO:
+ mQueue = new ElementaryStreamQueue(
+ ElementaryStreamQueue::MPEG_AUDIO);
+ break;
+
+ case STREAMTYPE_MPEG1_VIDEO:
+ case STREAMTYPE_MPEG2_VIDEO:
+ mQueue = new ElementaryStreamQueue(
+ ElementaryStreamQueue::MPEG_VIDEO);
+ break;
+
+ case STREAMTYPE_MPEG4_VIDEO:
+ mQueue = new ElementaryStreamQueue(
+ ElementaryStreamQueue::MPEG4_VIDEO);
+ break;
+
+ default:
+ break;
+ }
+
+ ALOGV("new stream PID 0x%02x, type 0x%02x", elementaryPID, streamType);
+
+ if (mQueue != NULL) {
+ mBuffer = new ABuffer(192 * 1024);
+ mBuffer->setRange(0, 0);
+ }
+}
+
+ATSParser::Stream::~Stream() {
+ delete mQueue;
+ mQueue = NULL;
+}
+
+status_t ATSParser::Stream::parse(
+ unsigned payload_unit_start_indicator, ABitReader *br) {
+ if (mQueue == NULL) {
+ return OK;
+ }
+
+ 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.
+
+ status_t err = flush();
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ mPayloadStarted = true;
+ }
+
+ if (!mPayloadStarted) {
+ return OK;
+ }
+
+ size_t payloadSizeBits = br->numBitsLeft();
+ CHECK_EQ(payloadSizeBits % 8, 0u);
+
+ size_t neededSize = mBuffer->size() + payloadSizeBits / 8;
+ if (mBuffer->capacity() < neededSize) {
+ // Increment in multiples of 64K.
+ neededSize = (neededSize + 65535) & ~65535;
+
+ ALOGI("resizing buffer to %d bytes", neededSize);
+
+ sp<ABuffer> newBuffer = new ABuffer(neededSize);
+ memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
+ newBuffer->setRange(0, mBuffer->size());
+ mBuffer = newBuffer;
+ }
+
+ memcpy(mBuffer->data() + mBuffer->size(), br->data(), payloadSizeBits / 8);
+ mBuffer->setRange(0, mBuffer->size() + payloadSizeBits / 8);
+
+ return OK;
+}
+
+bool ATSParser::Stream::isVideo() const {
+ switch (mStreamType) {
+ case STREAMTYPE_H264:
+ case STREAMTYPE_MPEG1_VIDEO:
+ case STREAMTYPE_MPEG2_VIDEO:
+ case STREAMTYPE_MPEG4_VIDEO:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ATSParser::Stream::isAudio() const {
+ switch (mStreamType) {
+ case STREAMTYPE_MPEG1_AUDIO:
+ case STREAMTYPE_MPEG2_AUDIO:
+ case STREAMTYPE_MPEG2_AUDIO_ADTS:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+void ATSParser::Stream::signalDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra) {
+ if (mQueue == NULL) {
+ return;
+ }
+
+ mPayloadStarted = false;
+ mBuffer->setRange(0, 0);
+
+ bool clearFormat = false;
+ if (isAudio()) {
+ if (type & DISCONTINUITY_AUDIO_FORMAT) {
+ clearFormat = true;
+ }
+ } else {
+ if (type & DISCONTINUITY_VIDEO_FORMAT) {
+ clearFormat = true;
+ }
+ }
+
+ mQueue->clear(clearFormat);
+
+ if (type & DISCONTINUITY_TIME) {
+ uint64_t resumeAtPTS;
+ if (extra != NULL
+ && extra->findInt64(
+ IStreamListener::kKeyResumeAtPTS,
+ (int64_t *)&resumeAtPTS)) {
+ int64_t resumeAtMediaTimeUs =
+ mProgram->convertPTSToTimestamp(resumeAtPTS);
+
+ extra->setInt64("resume-at-mediatimeUs", resumeAtMediaTimeUs);
+ }
+ }
+
+ if (mSource != NULL) {
+ mSource->queueDiscontinuity(type, extra);
+ }
+}
+
+void ATSParser::Stream::signalEOS(status_t finalResult) {
+ if (mSource != NULL) {
+ mSource->signalEOS(finalResult);
+ }
+}
+
+status_t ATSParser::Stream::parsePES(ABitReader *br) {
+ unsigned packet_startcode_prefix = br->getBits(24);
+
+ ALOGV("packet_startcode_prefix = 0x%08x", packet_startcode_prefix);
+
+ if (packet_startcode_prefix != 1) {
+ ALOGV("Supposedly payload_unit_start=1 unit does not start "
+ "with startcode.");
+
+ return ERROR_MALFORMED;
+ }
+
+ CHECK_EQ(packet_startcode_prefix, 0x000001u);
+
+ unsigned stream_id = br->getBits(8);
+ ALOGV("stream_id = 0x%02x", stream_id);
+
+ unsigned PES_packet_length = br->getBits(16);
+ ALOGV("PES_packet_length = %u", 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);
+
+ MY_LOGV("PES_scrambling_control = %u", br->getBits(2));
+ MY_LOGV("PES_priority = %u", br->getBits(1));
+ MY_LOGV("data_alignment_indicator = %u", br->getBits(1));
+ MY_LOGV("copyright = %u", br->getBits(1));
+ MY_LOGV("original_or_copy = %u", br->getBits(1));
+
+ unsigned PTS_DTS_flags = br->getBits(2);
+ ALOGV("PTS_DTS_flags = %u", PTS_DTS_flags);
+
+ unsigned ESCR_flag = br->getBits(1);
+ ALOGV("ESCR_flag = %u", ESCR_flag);
+
+ unsigned ES_rate_flag = br->getBits(1);
+ ALOGV("ES_rate_flag = %u", ES_rate_flag);
+
+ unsigned DSM_trick_mode_flag = br->getBits(1);
+ ALOGV("DSM_trick_mode_flag = %u", DSM_trick_mode_flag);
+
+ unsigned additional_copy_info_flag = br->getBits(1);
+ ALOGV("additional_copy_info_flag = %u", additional_copy_info_flag);
+
+ MY_LOGV("PES_CRC_flag = %u", br->getBits(1));
+ MY_LOGV("PES_extension_flag = %u", br->getBits(1));
+
+ unsigned PES_header_data_length = br->getBits(8);
+ ALOGV("PES_header_data_length = %u", 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);
+
+ ALOGV("PTS = %llu", PTS);
+ // ALOGI("PTS = %.2f secs", PTS / 90000.0f);
+
+ 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);
+
+ ALOGV("DTS = %llu", 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);
+
+ ALOGV("ESCR = %llu", ESCR);
+ MY_LOGV("ESCR_extension = %u", 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);
+ MY_LOGV("ES_rate = %u", br->getBits(22));
+ CHECK_EQ(br->getBits(1), 1u);
+
+ optional_bytes_remaining -= 3;
+ }
+
+ br->skipBits(optional_bytes_remaining * 8);
+
+ // ES data follows.
+
+ 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;
+
+ if (br->numBitsLeft() < dataLength * 8) {
+ ALOGE("PES packet does not carry enough data to contain "
+ "payload. (numBitsLeft = %d, required = %d)",
+ br->numBitsLeft(), dataLength * 8);
+
+ return ERROR_MALFORMED;
+ }
+
+ CHECK_GE(br->numBitsLeft(), dataLength * 8);
+
+ onPayloadData(
+ PTS_DTS_flags, PTS, DTS, br->data(), dataLength);
+
+ br->skipBits(dataLength * 8);
+ } else {
+ onPayloadData(
+ PTS_DTS_flags, PTS, DTS,
+ br->data(), br->numBitsLeft() / 8);
+
+ size_t payloadSizeBits = br->numBitsLeft();
+ CHECK_EQ(payloadSizeBits % 8, 0u);
+
+ ALOGV("There's %d bytes of payload.", payloadSizeBits / 8);
+ }
+ } 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);
+ }
+
+ return OK;
+}
+
+status_t ATSParser::Stream::flush() {
+ if (mBuffer->size() == 0) {
+ return OK;
+ }
+
+ ALOGV("flushing stream 0x%04x size = %d", mElementaryPID, mBuffer->size());
+
+ ABitReader br(mBuffer->data(), mBuffer->size());
+
+ status_t err = parsePES(&br);
+
+ mBuffer->setRange(0, 0);
+
+ return err;
+}
+
+void ATSParser::Stream::onPayloadData(
+ unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
+ const uint8_t *data, size_t size) {
+ ALOGV("onPayloadData mStreamType=0x%02x", mStreamType);
+
+ int64_t timeUs = 0ll; // no presentation timestamp available.
+ if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
+ timeUs = mProgram->convertPTSToTimestamp(PTS);
+ }
+
+ status_t err = mQueue->appendData(data, size, timeUs);
+
+ if (err != OK) {
+ return;
+ }
+
+ sp<ABuffer> accessUnit;
+ while ((accessUnit = mQueue->dequeueAccessUnit()) != NULL) {
+ if (mSource == NULL) {
+ sp<MetaData> meta = mQueue->getFormat();
+
+ if (meta != NULL) {
+ ALOGV("Stream PID 0x%08x of type 0x%02x now has data.",
+ mElementaryPID, mStreamType);
+
+ mSource = new AnotherPacketSource(meta);
+ mSource->queueAccessUnit(accessUnit);
+ }
+ } else if (mQueue->getFormat() != NULL) {
+ // After a discontinuity we invalidate the queue's format
+ // and won't enqueue any access units to the source until
+ // the queue has reestablished the new format.
+
+ if (mSource->getFormat() == NULL) {
+ mSource->setFormat(mQueue->getFormat());
+ }
+ mSource->queueAccessUnit(accessUnit);
+ }
+ }
+}
+
+sp<MediaSource> ATSParser::Stream::getSource(SourceType type) {
+ switch (type) {
+ case VIDEO:
+ {
+ if (isVideo()) {
+ return mSource;
+ }
+ break;
+ }
+
+ case AUDIO:
+ {
+ if (isAudio()) {
+ return mSource;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ATSParser::ATSParser(uint32_t flags)
+ : mFlags(flags) {
+}
+
+ATSParser::~ATSParser() {
+}
+
+status_t ATSParser::feedTSPacket(const void *data, size_t size) {
+ CHECK_EQ(size, kTSPacketSize);
+
+ ABitReader br((const uint8_t *)data, kTSPacketSize);
+ return parseTS(&br);
+}
+
+void ATSParser::signalDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra) {
+ for (size_t i = 0; i < mPrograms.size(); ++i) {
+ mPrograms.editItemAt(i)->signalDiscontinuity(type, extra);
+ }
+}
+
+void ATSParser::signalEOS(status_t finalResult) {
+ CHECK_NE(finalResult, (status_t)OK);
+
+ for (size_t i = 0; i < mPrograms.size(); ++i) {
+ mPrograms.editItemAt(i)->signalEOS(finalResult);
+ }
+}
+
+void ATSParser::parseProgramAssociationTable(ABitReader *br) {
+ unsigned table_id = br->getBits(8);
+ ALOGV(" table_id = %u", table_id);
+ CHECK_EQ(table_id, 0x00u);
+
+ unsigned section_syntax_indictor = br->getBits(1);
+ ALOGV(" section_syntax_indictor = %u", section_syntax_indictor);
+ CHECK_EQ(section_syntax_indictor, 1u);
+
+ CHECK_EQ(br->getBits(1), 0u);
+ MY_LOGV(" reserved = %u", br->getBits(2));
+
+ unsigned section_length = br->getBits(12);
+ ALOGV(" section_length = %u", section_length);
+ CHECK_EQ(section_length & 0xc00, 0u);
+
+ MY_LOGV(" transport_stream_id = %u", br->getBits(16));
+ MY_LOGV(" reserved = %u", br->getBits(2));
+ MY_LOGV(" version_number = %u", br->getBits(5));
+ MY_LOGV(" current_next_indicator = %u", br->getBits(1));
+ MY_LOGV(" section_number = %u", br->getBits(8));
+ MY_LOGV(" last_section_number = %u", 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);
+ ALOGV(" program_number = %u", program_number);
+
+ MY_LOGV(" reserved = %u", br->getBits(3));
+
+ if (program_number == 0) {
+ MY_LOGV(" network_PID = 0x%04x", br->getBits(13));
+ } else {
+ unsigned programMapPID = br->getBits(13);
+
+ ALOGV(" program_map_PID = 0x%04x", programMapPID);
+
+ bool found = false;
+ for (size_t index = 0; index < mPrograms.size(); ++index) {
+ const sp<Program> &program = mPrograms.itemAt(index);
+
+ if (program->number() == program_number) {
+ program->updateProgramMapPID(programMapPID);
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ mPrograms.push(
+ new Program(this, program_number, programMapPID));
+ }
+ }
+ }
+
+ MY_LOGV(" CRC = 0x%08x", br->getBits(32));
+}
+
+status_t 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 OK;
+ }
+
+ bool handled = false;
+ for (size_t i = 0; i < mPrograms.size(); ++i) {
+ status_t err;
+ if (mPrograms.editItemAt(i)->parsePID(
+ PID, payload_unit_start_indicator, br, &err)) {
+ if (err != OK) {
+ return err;
+ }
+
+ handled = true;
+ break;
+ }
+ }
+
+ if (!handled) {
+ ALOGV("PID 0x%04x not handled.", PID);
+ }
+
+ return OK;
+}
+
+void ATSParser::parseAdaptationField(ABitReader *br) {
+ unsigned adaptation_field_length = br->getBits(8);
+ if (adaptation_field_length > 0) {
+ br->skipBits(adaptation_field_length * 8); // XXX
+ }
+}
+
+status_t ATSParser::parseTS(ABitReader *br) {
+ ALOGV("---");
+
+ unsigned sync_byte = br->getBits(8);
+ CHECK_EQ(sync_byte, 0x47u);
+
+ MY_LOGV("transport_error_indicator = %u", br->getBits(1));
+
+ unsigned payload_unit_start_indicator = br->getBits(1);
+ ALOGV("payload_unit_start_indicator = %u", payload_unit_start_indicator);
+
+ MY_LOGV("transport_priority = %u", br->getBits(1));
+
+ unsigned PID = br->getBits(13);
+ ALOGV("PID = 0x%04x", PID);
+
+ MY_LOGV("transport_scrambling_control = %u", br->getBits(2));
+
+ unsigned adaptation_field_control = br->getBits(2);
+ ALOGV("adaptation_field_control = %u", adaptation_field_control);
+
+ unsigned continuity_counter = br->getBits(4);
+ ALOGV("continuity_counter = %u", continuity_counter);
+
+ // ALOGI("PID = 0x%04x, continuity_counter = %u", PID, continuity_counter);
+
+ if (adaptation_field_control == 2 || adaptation_field_control == 3) {
+ parseAdaptationField(br);
+ }
+
+ if (adaptation_field_control == 1 || adaptation_field_control == 3) {
+ return parsePID(br, PID, payload_unit_start_indicator);
+ }
+
+ return OK;
+}
+
+sp<MediaSource> ATSParser::getSource(SourceType type) {
+ int which = -1; // any
+
+ for (size_t i = 0; i < mPrograms.size(); ++i) {
+ const sp<Program> &program = mPrograms.editItemAt(i);
+
+ if (which >= 0 && (int)program->number() != which) {
+ continue;
+ }
+
+ sp<MediaSource> source = program->getSource(type);
+
+ if (source != NULL) {
+ return source;
+ }
+ }
+
+ return NULL;
+}
+
+bool ATSParser::PTSTimeDeltaEstablished() {
+ if (mPrograms.isEmpty()) {
+ return false;
+ }
+
+ return mPrograms.editItemAt(0)->PTSTimeDeltaEstablished();
+}
+
+} // namespace android
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
new file mode 100644
index 0000000..c8038d1
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -0,0 +1,114 @@
+/*
+ * 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 <media/stagefright/foundation/AMessage.h>
+#include <utils/Vector.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABitReader;
+struct ABuffer;
+struct MediaSource;
+
+struct ATSParser : public RefBase {
+ enum DiscontinuityType {
+ DISCONTINUITY_NONE = 0,
+ DISCONTINUITY_TIME = 1,
+ DISCONTINUITY_AUDIO_FORMAT = 2,
+ DISCONTINUITY_VIDEO_FORMAT = 4,
+
+ DISCONTINUITY_SEEK = DISCONTINUITY_TIME,
+
+ // For legacy reasons this also implies a time discontinuity.
+ DISCONTINUITY_FORMATCHANGE =
+ DISCONTINUITY_AUDIO_FORMAT
+ | DISCONTINUITY_VIDEO_FORMAT
+ | DISCONTINUITY_TIME,
+ };
+
+ enum Flags {
+ // The 90kHz clock (PTS/DTS) is absolute, i.e. PTS=0 corresponds to
+ // a media time of 0.
+ // If this flag is _not_ specified, the first PTS encountered in a
+ // program of this stream will be assumed to correspond to media time 0
+ // instead.
+ TS_TIMESTAMPS_ARE_ABSOLUTE = 1
+ };
+
+ ATSParser(uint32_t flags = 0);
+
+ status_t feedTSPacket(const void *data, size_t size);
+
+ void signalDiscontinuity(
+ DiscontinuityType type, const sp<AMessage> &extra);
+
+ void signalEOS(status_t finalResult);
+
+ enum SourceType {
+ VIDEO,
+ AUDIO
+ };
+ sp<MediaSource> getSource(SourceType type);
+
+ bool PTSTimeDeltaEstablished();
+
+ enum {
+ // From ISO/IEC 13818-1: 2000 (E), Table 2-29
+ STREAMTYPE_RESERVED = 0x00,
+ STREAMTYPE_MPEG1_VIDEO = 0x01,
+ STREAMTYPE_MPEG2_VIDEO = 0x02,
+ STREAMTYPE_MPEG1_AUDIO = 0x03,
+ STREAMTYPE_MPEG2_AUDIO = 0x04,
+ STREAMTYPE_MPEG2_AUDIO_ADTS = 0x0f,
+ STREAMTYPE_MPEG4_VIDEO = 0x10,
+ STREAMTYPE_H264 = 0x1b,
+ };
+
+protected:
+ virtual ~ATSParser();
+
+private:
+ struct Program;
+ struct Stream;
+
+ uint32_t mFlags;
+ Vector<sp<Program> > mPrograms;
+
+ void parseProgramAssociationTable(ABitReader *br);
+ void parseProgramMap(ABitReader *br);
+ void parsePES(ABitReader *br);
+
+ status_t parsePID(
+ ABitReader *br, unsigned PID,
+ unsigned payload_unit_start_indicator);
+
+ void parseAdaptationField(ABitReader *br);
+ status_t 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..eaa139d
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ AnotherPacketSource.cpp \
+ ATSParser.cpp \
+ ESQueue.cpp \
+ MPEG2PSExtractor.cpp \
+ MPEG2TSExtractor.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax
+
+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..e1ac53c
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -0,0 +1,222 @@
+/*
+ * 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)
+ : mIsAudio(false),
+ mFormat(meta),
+ mEOSResult(OK) {
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (!strncasecmp("audio/", mime, 6)) {
+ mIsAudio = true;
+ } else {
+ CHECK(!strncasecmp("video/", mime, 6));
+ }
+}
+
+void AnotherPacketSource::setFormat(const sp<MetaData> &meta) {
+ CHECK(mFormat == NULL);
+ mFormat = meta;
+}
+
+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::dequeueAccessUnit(sp<ABuffer> *buffer) {
+ buffer->clear();
+
+ Mutex::Autolock autoLock(mLock);
+ while (mEOSResult == OK && mBuffers.empty()) {
+ mCondition.wait(mLock);
+ }
+
+ if (!mBuffers.empty()) {
+ *buffer = *mBuffers.begin();
+ mBuffers.erase(mBuffers.begin());
+
+ int32_t discontinuity;
+ if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) {
+ if (wasFormatChange(discontinuity)) {
+ mFormat.clear();
+ }
+
+ return INFO_DISCONTINUITY;
+ }
+
+ return OK;
+ }
+
+ return mEOSResult;
+}
+
+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();
+ mBuffers.erase(mBuffers.begin());
+
+ int32_t discontinuity;
+ if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
+ if (wasFormatChange(discontinuity)) {
+ mFormat.clear();
+ }
+
+ return INFO_DISCONTINUITY;
+ } else {
+ int64_t timeUs;
+ CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
+
+ MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
+
+ mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
+
+ int32_t scrambling;
+ if (buffer->meta()->findInt32("scrambling", &scrambling)
+ && scrambling != 0) {
+ mediaBuffer->meta_data()->setInt32(kKeyScrambling, scrambling);
+ }
+
+ *out = mediaBuffer;
+ return OK;
+ }
+ }
+
+ return mEOSResult;
+}
+
+bool AnotherPacketSource::wasFormatChange(
+ int32_t discontinuityType) const {
+ if (mIsAudio) {
+ return (discontinuityType & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0;
+ }
+
+ return (discontinuityType & ATSParser::DISCONTINUITY_VIDEO_FORMAT) != 0;
+}
+
+void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
+ int32_t damaged;
+ if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
+ // LOG(VERBOSE) << "discarding damaged AU";
+ return;
+ }
+
+ int64_t timeUs;
+ CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
+ ALOGV("queueAccessUnit timeUs=%lld us (%.2f secs)", timeUs, timeUs / 1E6);
+
+ Mutex::Autolock autoLock(mLock);
+ mBuffers.push_back(buffer);
+ mCondition.signal();
+}
+
+void AnotherPacketSource::queueDiscontinuity(
+ ATSParser::DiscontinuityType type,
+ const sp<AMessage> &extra) {
+ Mutex::Autolock autoLock(mLock);
+
+ // Leave only discontinuities in the queue.
+ List<sp<ABuffer> >::iterator it = mBuffers.begin();
+ while (it != mBuffers.end()) {
+ sp<ABuffer> oldBuffer = *it;
+
+ int32_t oldDiscontinuityType;
+ if (!oldBuffer->meta()->findInt32(
+ "discontinuity", &oldDiscontinuityType)) {
+ it = mBuffers.erase(it);
+ continue;
+ }
+
+ ++it;
+ }
+
+ mEOSResult = OK;
+
+ sp<ABuffer> buffer = new ABuffer(0);
+ buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
+ buffer->meta()->setMessage("extra", extra);
+
+ 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;
+}
+
+status_t AnotherPacketSource::nextBufferTime(int64_t *timeUs) {
+ *timeUs = 0;
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (mBuffers.empty()) {
+ return mEOSResult != OK ? mEOSResult : -EWOULDBLOCK;
+ }
+
+ sp<ABuffer> buffer = *mBuffers.begin();
+ CHECK(buffer->meta()->findInt64("timeUs", timeUs));
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
new file mode 100644
index 0000000..c99f7f2
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -0,0 +1,77 @@
+/*
+ * 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>
+
+#include "ATSParser.h"
+
+namespace android {
+
+struct ABuffer;
+
+struct AnotherPacketSource : public MediaSource {
+ AnotherPacketSource(const sp<MetaData> &meta);
+
+ void setFormat(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);
+
+ status_t nextBufferTime(int64_t *timeUs);
+
+ void queueAccessUnit(const sp<ABuffer> &buffer);
+
+ void queueDiscontinuity(
+ ATSParser::DiscontinuityType type, const sp<AMessage> &extra);
+
+ void signalEOS(status_t result);
+
+ status_t dequeueAccessUnit(sp<ABuffer> *buffer);
+
+protected:
+ virtual ~AnotherPacketSource();
+
+private:
+ Mutex mLock;
+ Condition mCondition;
+
+ bool mIsAudio;
+ sp<MetaData> mFormat;
+ List<sp<ABuffer> > mBuffers;
+ status_t mEOSResult;
+
+ bool wasFormatChange(int32_t discontinuityType) const;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AnotherPacketSource);
+};
+
+
+} // namespace android
+
+#endif // ANOTHER_PACKET_SOURCE_H_
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
new file mode 100644
index 0000000..7fd99a8
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -0,0 +1,954 @@
+/*
+ * 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 "ESQueue"
+#include <media/stagefright/foundation/ADebug.h>
+
+#include "ESQueue.h"
+
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/ABitReader.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include "include/avc_utils.h"
+
+namespace android {
+
+ElementaryStreamQueue::ElementaryStreamQueue(Mode mode)
+ : mMode(mode) {
+}
+
+sp<MetaData> ElementaryStreamQueue::getFormat() {
+ return mFormat;
+}
+
+void ElementaryStreamQueue::clear(bool clearFormat) {
+ if (mBuffer != NULL) {
+ mBuffer->setRange(0, 0);
+ }
+
+ mRangeInfos.clear();
+
+ if (clearFormat) {
+ mFormat.clear();
+ }
+}
+
+static bool IsSeeminglyValidADTSHeader(const uint8_t *ptr, size_t size) {
+ if (size < 3) {
+ // Not enough data to verify header.
+ return false;
+ }
+
+ if (ptr[0] != 0xff || (ptr[1] >> 4) != 0x0f) {
+ return false;
+ }
+
+ unsigned layer = (ptr[1] >> 1) & 3;
+
+ if (layer != 0) {
+ return false;
+ }
+
+ unsigned ID = (ptr[1] >> 3) & 1;
+ unsigned profile_ObjectType = ptr[2] >> 6;
+
+ if (ID == 1 && profile_ObjectType == 3) {
+ // MPEG-2 profile 3 is reserved.
+ return false;
+ }
+
+ return true;
+}
+
+static bool IsSeeminglyValidMPEGAudioHeader(const uint8_t *ptr, size_t size) {
+ if (size < 3) {
+ // Not enough data to verify header.
+ return false;
+ }
+
+ if (ptr[0] != 0xff || (ptr[1] >> 5) != 0x07) {
+ return false;
+ }
+
+ unsigned ID = (ptr[1] >> 3) & 3;
+
+ if (ID == 1) {
+ return false; // reserved
+ }
+
+ unsigned layer = (ptr[1] >> 1) & 3;
+
+ if (layer == 0) {
+ return false; // reserved
+ }
+
+ unsigned bitrateIndex = (ptr[2] >> 4);
+
+ if (bitrateIndex == 0x0f) {
+ return false; // reserved
+ }
+
+ unsigned samplingRateIndex = (ptr[2] >> 2) & 3;
+
+ if (samplingRateIndex == 3) {
+ return false; // reserved
+ }
+
+ return true;
+}
+
+status_t ElementaryStreamQueue::appendData(
+ const void *data, size_t size, int64_t timeUs) {
+ if (mBuffer == NULL || mBuffer->size() == 0) {
+ switch (mMode) {
+ case H264:
+ case MPEG_VIDEO:
+ {
+#if 0
+ if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
+ return ERROR_MALFORMED;
+ }
+#else
+ uint8_t *ptr = (uint8_t *)data;
+
+ ssize_t startOffset = -1;
+ for (size_t i = 0; i + 3 < size; ++i) {
+ if (!memcmp("\x00\x00\x00\x01", &ptr[i], 4)) {
+ startOffset = i;
+ break;
+ }
+ }
+
+ if (startOffset < 0) {
+ return ERROR_MALFORMED;
+ }
+
+ if (startOffset > 0) {
+ ALOGI("found something resembling an H.264/MPEG syncword at "
+ "offset %ld",
+ startOffset);
+ }
+
+ data = &ptr[startOffset];
+ size -= startOffset;
+#endif
+ break;
+ }
+
+ case MPEG4_VIDEO:
+ {
+#if 0
+ if (size < 3 || memcmp("\x00\x00\x01", data, 3)) {
+ return ERROR_MALFORMED;
+ }
+#else
+ uint8_t *ptr = (uint8_t *)data;
+
+ ssize_t startOffset = -1;
+ for (size_t i = 0; i + 2 < size; ++i) {
+ if (!memcmp("\x00\x00\x01", &ptr[i], 3)) {
+ startOffset = i;
+ break;
+ }
+ }
+
+ if (startOffset < 0) {
+ return ERROR_MALFORMED;
+ }
+
+ if (startOffset > 0) {
+ ALOGI("found something resembling an H.264/MPEG syncword at "
+ "offset %ld",
+ startOffset);
+ }
+
+ data = &ptr[startOffset];
+ size -= startOffset;
+#endif
+ break;
+ }
+
+ case AAC:
+ {
+ uint8_t *ptr = (uint8_t *)data;
+
+#if 0
+ if (size < 2 || ptr[0] != 0xff || (ptr[1] >> 4) != 0x0f) {
+ return ERROR_MALFORMED;
+ }
+#else
+ ssize_t startOffset = -1;
+ for (size_t i = 0; i < size; ++i) {
+ if (IsSeeminglyValidADTSHeader(&ptr[i], size - i)) {
+ startOffset = i;
+ break;
+ }
+ }
+
+ if (startOffset < 0) {
+ return ERROR_MALFORMED;
+ }
+
+ if (startOffset > 0) {
+ ALOGI("found something resembling an AAC syncword at offset %ld",
+ startOffset);
+ }
+
+ data = &ptr[startOffset];
+ size -= startOffset;
+#endif
+ break;
+ }
+
+ case MPEG_AUDIO:
+ {
+ uint8_t *ptr = (uint8_t *)data;
+
+ ssize_t startOffset = -1;
+ for (size_t i = 0; i < size; ++i) {
+ if (IsSeeminglyValidMPEGAudioHeader(&ptr[i], size - i)) {
+ startOffset = i;
+ break;
+ }
+ }
+
+ if (startOffset < 0) {
+ return ERROR_MALFORMED;
+ }
+
+ if (startOffset > 0) {
+ ALOGI("found something resembling an MPEG audio "
+ "syncword at offset %ld",
+ startOffset);
+ }
+
+ data = &ptr[startOffset];
+ size -= startOffset;
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+ }
+
+ size_t neededSize = (mBuffer == NULL ? 0 : mBuffer->size()) + size;
+ if (mBuffer == NULL || neededSize > mBuffer->capacity()) {
+ neededSize = (neededSize + 65535) & ~65535;
+
+ ALOGV("resizing buffer to size %d", neededSize);
+
+ sp<ABuffer> buffer = new ABuffer(neededSize);
+ if (mBuffer != NULL) {
+ memcpy(buffer->data(), mBuffer->data(), mBuffer->size());
+ buffer->setRange(0, mBuffer->size());
+ } else {
+ buffer->setRange(0, 0);
+ }
+
+ mBuffer = buffer;
+ }
+
+ memcpy(mBuffer->data() + mBuffer->size(), data, size);
+ mBuffer->setRange(0, mBuffer->size() + size);
+
+ RangeInfo info;
+ info.mLength = size;
+ info.mTimestampUs = timeUs;
+ mRangeInfos.push_back(info);
+
+#if 0
+ if (mMode == AAC) {
+ ALOGI("size = %d, timeUs = %.2f secs", size, timeUs / 1E6);
+ hexdump(data, size);
+ }
+#endif
+
+ return OK;
+}
+
+sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnit() {
+ switch (mMode) {
+ case H264:
+ return dequeueAccessUnitH264();
+ case AAC:
+ return dequeueAccessUnitAAC();
+ case MPEG_VIDEO:
+ return dequeueAccessUnitMPEGVideo();
+ case MPEG4_VIDEO:
+ return dequeueAccessUnitMPEG4Video();
+ default:
+ CHECK_EQ((unsigned)mMode, (unsigned)MPEG_AUDIO);
+ return dequeueAccessUnitMPEGAudio();
+ }
+}
+
+sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitAAC() {
+ Vector<size_t> ranges;
+ Vector<size_t> frameOffsets;
+ Vector<size_t> frameSizes;
+ size_t auSize = 0;
+
+ size_t offset = 0;
+ while (offset + 7 <= mBuffer->size()) {
+ ABitReader bits(mBuffer->data() + offset, mBuffer->size() - offset);
+
+ // adts_fixed_header
+
+ CHECK_EQ(bits.getBits(12), 0xfffu);
+ bits.skipBits(3); // ID, layer
+ bool protection_absent = bits.getBits(1) != 0;
+
+ if (mFormat == NULL) {
+ unsigned profile = bits.getBits(2);
+ CHECK_NE(profile, 3u);
+ unsigned sampling_freq_index = bits.getBits(4);
+ bits.getBits(1); // private_bit
+ unsigned channel_configuration = bits.getBits(3);
+ CHECK_NE(channel_configuration, 0u);
+ bits.skipBits(2); // original_copy, home
+
+ mFormat = MakeAACCodecSpecificData(
+ profile, sampling_freq_index, channel_configuration);
+
+ int32_t sampleRate;
+ int32_t numChannels;
+ CHECK(mFormat->findInt32(kKeySampleRate, &sampleRate));
+ CHECK(mFormat->findInt32(kKeyChannelCount, &numChannels));
+
+ ALOGI("found AAC codec config (%d Hz, %d channels)",
+ sampleRate, numChannels);
+ } else {
+ // profile_ObjectType, sampling_frequency_index, private_bits,
+ // channel_configuration, original_copy, home
+ bits.skipBits(12);
+ }
+
+ // adts_variable_header
+
+ // copyright_identification_bit, copyright_identification_start
+ bits.skipBits(2);
+
+ unsigned aac_frame_length = bits.getBits(13);
+
+ bits.skipBits(11); // adts_buffer_fullness
+
+ unsigned number_of_raw_data_blocks_in_frame = bits.getBits(2);
+
+ if (number_of_raw_data_blocks_in_frame != 0) {
+ // To be implemented.
+ TRESPASS();
+ }
+
+ if (offset + aac_frame_length > mBuffer->size()) {
+ break;
+ }
+
+ size_t headerSize = protection_absent ? 7 : 9;
+
+ ranges.push(aac_frame_length);
+ frameOffsets.push(offset + headerSize);
+ frameSizes.push(aac_frame_length - headerSize);
+ auSize += aac_frame_length - headerSize;
+
+ offset += aac_frame_length;
+ }
+
+ if (offset == 0) {
+ return NULL;
+ }
+
+ int64_t timeUs = -1;
+
+ for (size_t i = 0; i < ranges.size(); ++i) {
+ int64_t tmpUs = fetchTimestamp(ranges.itemAt(i));
+
+ if (i == 0) {
+ timeUs = tmpUs;
+ }
+ }
+
+ sp<ABuffer> accessUnit = new ABuffer(auSize);
+ size_t dstOffset = 0;
+ for (size_t i = 0; i < frameOffsets.size(); ++i) {
+ size_t frameOffset = frameOffsets.itemAt(i);
+
+ memcpy(accessUnit->data() + dstOffset,
+ mBuffer->data() + frameOffset,
+ frameSizes.itemAt(i));
+
+ dstOffset += frameSizes.itemAt(i);
+ }
+
+ memmove(mBuffer->data(), mBuffer->data() + offset,
+ mBuffer->size() - offset);
+ mBuffer->setRange(0, mBuffer->size() - offset);
+
+ if (timeUs >= 0) {
+ accessUnit->meta()->setInt64("timeUs", timeUs);
+ } else {
+ ALOGW("no time for AAC access unit");
+ }
+
+ return accessUnit;
+}
+
+int64_t ElementaryStreamQueue::fetchTimestamp(size_t size) {
+ int64_t timeUs = -1;
+ bool first = true;
+
+ while (size > 0) {
+ CHECK(!mRangeInfos.empty());
+
+ RangeInfo *info = &*mRangeInfos.begin();
+
+ if (first) {
+ timeUs = info->mTimestampUs;
+ first = false;
+ }
+
+ if (info->mLength > size) {
+ info->mLength -= size;
+
+ if (first) {
+ info->mTimestampUs = -1;
+ }
+
+ size = 0;
+ } else {
+ size -= info->mLength;
+
+ mRangeInfos.erase(mRangeInfos.begin());
+ info = NULL;
+ }
+ }
+
+ if (timeUs == 0ll) {
+ ALOGV("Returning 0 timestamp");
+ }
+
+ return timeUs;
+}
+
+struct NALPosition {
+ size_t nalOffset;
+ size_t nalSize;
+};
+
+sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() {
+ const uint8_t *data = mBuffer->data();
+ size_t size = mBuffer->size();
+
+ Vector<NALPosition> nals;
+
+ size_t totalSize = 0;
+
+ status_t err;
+ const uint8_t *nalStart;
+ size_t nalSize;
+ bool foundSlice = false;
+ while ((err = getNextNALUnit(&data, &size, &nalStart, &nalSize)) == OK) {
+ CHECK_GT(nalSize, 0u);
+
+ unsigned nalType = nalStart[0] & 0x1f;
+ bool flush = false;
+
+ if (nalType == 1 || nalType == 5) {
+ if (foundSlice) {
+ ABitReader br(nalStart + 1, nalSize);
+ unsigned first_mb_in_slice = parseUE(&br);
+
+ if (first_mb_in_slice == 0) {
+ // This slice starts a new frame.
+
+ flush = true;
+ }
+ }
+
+ foundSlice = true;
+ } else if ((nalType == 9 || nalType == 7) && foundSlice) {
+ // Access unit delimiter and SPS will be associated with the
+ // next frame.
+
+ flush = true;
+ }
+
+ if (flush) {
+ // The access unit will contain all nal units up to, but excluding
+ // the current one, separated by 0x00 0x00 0x00 0x01 startcodes.
+
+ size_t auSize = 4 * nals.size() + totalSize;
+ sp<ABuffer> accessUnit = new ABuffer(auSize);
+
+#if !LOG_NDEBUG
+ AString out;
+#endif
+
+ size_t dstOffset = 0;
+ for (size_t i = 0; i < nals.size(); ++i) {
+ const NALPosition &pos = nals.itemAt(i);
+
+ unsigned nalType = mBuffer->data()[pos.nalOffset] & 0x1f;
+
+#if !LOG_NDEBUG
+ char tmp[128];
+ sprintf(tmp, "0x%02x", nalType);
+ if (i > 0) {
+ out.append(", ");
+ }
+ out.append(tmp);
+#endif
+
+ memcpy(accessUnit->data() + dstOffset, "\x00\x00\x00\x01", 4);
+
+ memcpy(accessUnit->data() + dstOffset + 4,
+ mBuffer->data() + pos.nalOffset,
+ pos.nalSize);
+
+ dstOffset += pos.nalSize + 4;
+ }
+
+ ALOGV("accessUnit contains nal types %s", out.c_str());
+
+ const NALPosition &pos = nals.itemAt(nals.size() - 1);
+ size_t nextScan = pos.nalOffset + pos.nalSize;
+
+ memmove(mBuffer->data(),
+ mBuffer->data() + nextScan,
+ mBuffer->size() - nextScan);
+
+ mBuffer->setRange(0, mBuffer->size() - nextScan);
+
+ int64_t timeUs = fetchTimestamp(nextScan);
+ CHECK_GE(timeUs, 0ll);
+
+ accessUnit->meta()->setInt64("timeUs", timeUs);
+
+ if (mFormat == NULL) {
+ mFormat = MakeAVCCodecSpecificData(accessUnit);
+ }
+
+ return accessUnit;
+ }
+
+ NALPosition pos;
+ pos.nalOffset = nalStart - mBuffer->data();
+ pos.nalSize = nalSize;
+
+ nals.push(pos);
+
+ totalSize += nalSize;
+ }
+ CHECK_EQ(err, (status_t)-EAGAIN);
+
+ return NULL;
+}
+
+sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitMPEGAudio() {
+ const uint8_t *data = mBuffer->data();
+ size_t size = mBuffer->size();
+
+ if (size < 4) {
+ return NULL;
+ }
+
+ uint32_t header = U32_AT(data);
+
+ size_t frameSize;
+ int samplingRate, numChannels, bitrate, numSamples;
+ CHECK(GetMPEGAudioFrameSize(
+ header, &frameSize, &samplingRate, &numChannels,
+ &bitrate, &numSamples));
+
+ if (size < frameSize) {
+ return NULL;
+ }
+
+ unsigned layer = 4 - ((header >> 17) & 3);
+
+ sp<ABuffer> accessUnit = new ABuffer(frameSize);
+ memcpy(accessUnit->data(), data, frameSize);
+
+ memmove(mBuffer->data(),
+ mBuffer->data() + frameSize,
+ mBuffer->size() - frameSize);
+
+ mBuffer->setRange(0, mBuffer->size() - frameSize);
+
+ int64_t timeUs = fetchTimestamp(frameSize);
+ CHECK_GE(timeUs, 0ll);
+
+ accessUnit->meta()->setInt64("timeUs", timeUs);
+
+ if (mFormat == NULL) {
+ mFormat = new MetaData;
+
+ switch (layer) {
+ case 1:
+ mFormat->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I);
+ break;
+ case 2:
+ mFormat->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
+ break;
+ case 3:
+ mFormat->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+ break;
+ default:
+ TRESPASS();
+ }
+
+ mFormat->setInt32(kKeySampleRate, samplingRate);
+ mFormat->setInt32(kKeyChannelCount, numChannels);
+ }
+
+ return accessUnit;
+}
+
+static void EncodeSize14(uint8_t **_ptr, size_t size) {
+ CHECK_LE(size, 0x3fff);
+
+ uint8_t *ptr = *_ptr;
+
+ *ptr++ = 0x80 | (size >> 7);
+ *ptr++ = size & 0x7f;
+
+ *_ptr = ptr;
+}
+
+static sp<ABuffer> MakeMPEGVideoESDS(const sp<ABuffer> &csd) {
+ sp<ABuffer> esds = new ABuffer(csd->size() + 25);
+
+ uint8_t *ptr = esds->data();
+ *ptr++ = 0x03;
+ EncodeSize14(&ptr, 22 + csd->size());
+
+ *ptr++ = 0x00; // ES_ID
+ *ptr++ = 0x00;
+
+ *ptr++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+ *ptr++ = 0x04;
+ EncodeSize14(&ptr, 16 + csd->size());
+
+ *ptr++ = 0x40; // Audio ISO/IEC 14496-3
+
+ for (size_t i = 0; i < 12; ++i) {
+ *ptr++ = 0x00;
+ }
+
+ *ptr++ = 0x05;
+ EncodeSize14(&ptr, csd->size());
+
+ memcpy(ptr, csd->data(), csd->size());
+
+ return esds;
+}
+
+sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitMPEGVideo() {
+ const uint8_t *data = mBuffer->data();
+ size_t size = mBuffer->size();
+
+ bool sawPictureStart = false;
+ int pprevStartCode = -1;
+ int prevStartCode = -1;
+ int currentStartCode = -1;
+
+ size_t offset = 0;
+ while (offset + 3 < size) {
+ if (memcmp(&data[offset], "\x00\x00\x01", 3)) {
+ ++offset;
+ continue;
+ }
+
+ pprevStartCode = prevStartCode;
+ prevStartCode = currentStartCode;
+ currentStartCode = data[offset + 3];
+
+ if (currentStartCode == 0xb3 && mFormat == NULL) {
+ memmove(mBuffer->data(), mBuffer->data() + offset, size - offset);
+ size -= offset;
+ (void)fetchTimestamp(offset);
+ offset = 0;
+ mBuffer->setRange(0, size);
+ }
+
+ if ((prevStartCode == 0xb3 && currentStartCode != 0xb5)
+ || (pprevStartCode == 0xb3 && prevStartCode == 0xb5)) {
+ // seqHeader without/with extension
+
+ if (mFormat == NULL) {
+ CHECK_GE(size, 7u);
+
+ unsigned width =
+ (data[4] << 4) | data[5] >> 4;
+
+ unsigned height =
+ ((data[5] & 0x0f) << 8) | data[6];
+
+ mFormat = new MetaData;
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG2);
+ mFormat->setInt32(kKeyWidth, width);
+ mFormat->setInt32(kKeyHeight, height);
+
+ ALOGI("found MPEG2 video codec config (%d x %d)", width, height);
+
+ sp<ABuffer> csd = new ABuffer(offset);
+ memcpy(csd->data(), data, offset);
+
+ memmove(mBuffer->data(),
+ mBuffer->data() + offset,
+ mBuffer->size() - offset);
+
+ mBuffer->setRange(0, mBuffer->size() - offset);
+ size -= offset;
+ (void)fetchTimestamp(offset);
+ offset = 0;
+
+ // hexdump(csd->data(), csd->size());
+
+ sp<ABuffer> esds = MakeMPEGVideoESDS(csd);
+ mFormat->setData(
+ kKeyESDS, kTypeESDS, esds->data(), esds->size());
+
+ return NULL;
+ }
+ }
+
+ if (mFormat != NULL && currentStartCode == 0x00) {
+ // Picture start
+
+ if (!sawPictureStart) {
+ sawPictureStart = true;
+ } else {
+ sp<ABuffer> accessUnit = new ABuffer(offset);
+ memcpy(accessUnit->data(), data, offset);
+
+ memmove(mBuffer->data(),
+ mBuffer->data() + offset,
+ mBuffer->size() - offset);
+
+ mBuffer->setRange(0, mBuffer->size() - offset);
+
+ int64_t timeUs = fetchTimestamp(offset);
+ CHECK_GE(timeUs, 0ll);
+
+ offset = 0;
+
+ accessUnit->meta()->setInt64("timeUs", timeUs);
+
+ ALOGV("returning MPEG video access unit at time %lld us",
+ timeUs);
+
+ // hexdump(accessUnit->data(), accessUnit->size());
+
+ return accessUnit;
+ }
+ }
+
+ ++offset;
+ }
+
+ return NULL;
+}
+
+static ssize_t getNextChunkSize(
+ const uint8_t *data, size_t size) {
+ static const char kStartCode[] = "\x00\x00\x01";
+
+ if (size < 3) {
+ return -EAGAIN;
+ }
+
+ if (memcmp(kStartCode, data, 3)) {
+ TRESPASS();
+ }
+
+ size_t offset = 3;
+ while (offset + 2 < size) {
+ if (!memcmp(&data[offset], kStartCode, 3)) {
+ return offset;
+ }
+
+ ++offset;
+ }
+
+ return -EAGAIN;
+}
+
+sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitMPEG4Video() {
+ uint8_t *data = mBuffer->data();
+ size_t size = mBuffer->size();
+
+ enum {
+ SKIP_TO_VISUAL_OBJECT_SEQ_START,
+ EXPECT_VISUAL_OBJECT_START,
+ EXPECT_VO_START,
+ EXPECT_VOL_START,
+ WAIT_FOR_VOP_START,
+ SKIP_TO_VOP_START,
+
+ } state;
+
+ if (mFormat == NULL) {
+ state = SKIP_TO_VISUAL_OBJECT_SEQ_START;
+ } else {
+ state = SKIP_TO_VOP_START;
+ }
+
+ int32_t width = -1, height = -1;
+
+ size_t offset = 0;
+ ssize_t chunkSize;
+ while ((chunkSize = getNextChunkSize(
+ &data[offset], size - offset)) > 0) {
+ bool discard = false;
+
+ unsigned chunkType = data[offset + 3];
+
+ switch (state) {
+ case SKIP_TO_VISUAL_OBJECT_SEQ_START:
+ {
+ if (chunkType == 0xb0) {
+ // Discard anything before this marker.
+
+ state = EXPECT_VISUAL_OBJECT_START;
+ } else {
+ discard = true;
+ }
+ break;
+ }
+
+ case EXPECT_VISUAL_OBJECT_START:
+ {
+ CHECK_EQ(chunkType, 0xb5);
+ state = EXPECT_VO_START;
+ break;
+ }
+
+ case EXPECT_VO_START:
+ {
+ CHECK_LE(chunkType, 0x1f);
+ state = EXPECT_VOL_START;
+ break;
+ }
+
+ case EXPECT_VOL_START:
+ {
+ CHECK((chunkType & 0xf0) == 0x20);
+
+ CHECK(ExtractDimensionsFromVOLHeader(
+ &data[offset], chunkSize,
+ &width, &height));
+
+ state = WAIT_FOR_VOP_START;
+ break;
+ }
+
+ case WAIT_FOR_VOP_START:
+ {
+ if (chunkType == 0xb3 || chunkType == 0xb6) {
+ // group of VOP or VOP start.
+
+ mFormat = new MetaData;
+ mFormat->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+
+ mFormat->setInt32(kKeyWidth, width);
+ mFormat->setInt32(kKeyHeight, height);
+
+ ALOGI("found MPEG4 video codec config (%d x %d)",
+ width, height);
+
+ sp<ABuffer> csd = new ABuffer(offset);
+ memcpy(csd->data(), data, offset);
+
+ // hexdump(csd->data(), csd->size());
+
+ sp<ABuffer> esds = MakeMPEGVideoESDS(csd);
+ mFormat->setData(
+ kKeyESDS, kTypeESDS,
+ esds->data(), esds->size());
+
+ discard = true;
+ state = SKIP_TO_VOP_START;
+ }
+
+ break;
+ }
+
+ case SKIP_TO_VOP_START:
+ {
+ if (chunkType == 0xb6) {
+ offset += chunkSize;
+
+ sp<ABuffer> accessUnit = new ABuffer(offset);
+ memcpy(accessUnit->data(), data, offset);
+
+ memmove(data, &data[offset], size - offset);
+ size -= offset;
+ mBuffer->setRange(0, size);
+
+ int64_t timeUs = fetchTimestamp(offset);
+ CHECK_GE(timeUs, 0ll);
+
+ offset = 0;
+
+ accessUnit->meta()->setInt64("timeUs", timeUs);
+
+ ALOGV("returning MPEG4 video access unit at time %lld us",
+ timeUs);
+
+ // hexdump(accessUnit->data(), accessUnit->size());
+
+ return accessUnit;
+ } else if (chunkType != 0xb3) {
+ offset += chunkSize;
+ discard = true;
+ }
+
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+
+ if (discard) {
+ (void)fetchTimestamp(offset);
+ memmove(data, &data[offset], size - offset);
+ size -= offset;
+ offset = 0;
+ mBuffer->setRange(0, size);
+ } else {
+ offset += chunkSize;
+ }
+ }
+
+ return NULL;
+}
+
+} // namespace android
diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/ESQueue.h
new file mode 100644
index 0000000..4035ed3
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/ESQueue.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 ES_QUEUE_H_
+
+#define ES_QUEUE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Errors.h>
+#include <utils/List.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABuffer;
+struct MetaData;
+
+struct ElementaryStreamQueue {
+ enum Mode {
+ H264,
+ AAC,
+ MPEG_AUDIO,
+ MPEG_VIDEO,
+ MPEG4_VIDEO,
+ };
+ ElementaryStreamQueue(Mode mode);
+
+ status_t appendData(const void *data, size_t size, int64_t timeUs);
+ void clear(bool clearFormat);
+
+ sp<ABuffer> dequeueAccessUnit();
+
+ sp<MetaData> getFormat();
+
+private:
+ struct RangeInfo {
+ int64_t mTimestampUs;
+ size_t mLength;
+ };
+
+ Mode mMode;
+
+ sp<ABuffer> mBuffer;
+ List<RangeInfo> mRangeInfos;
+
+ sp<MetaData> mFormat;
+
+ sp<ABuffer> dequeueAccessUnitH264();
+ sp<ABuffer> dequeueAccessUnitAAC();
+ sp<ABuffer> dequeueAccessUnitMPEGAudio();
+ sp<ABuffer> dequeueAccessUnitMPEGVideo();
+ sp<ABuffer> dequeueAccessUnitMPEG4Video();
+
+ // consume a logical (compressed) access unit of size "size",
+ // returns its timestamp in us (or -1 if no time information).
+ int64_t fetchTimestamp(size_t size);
+
+ DISALLOW_EVIL_CONSTRUCTORS(ElementaryStreamQueue);
+};
+
+} // namespace android
+
+#endif // ES_QUEUE_H_
diff --git a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
new file mode 100644
index 0000000..dd714c9
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
@@ -0,0 +1,715 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "MPEG2PSExtractor"
+#include <utils/Log.h>
+
+#include "include/MPEG2PSExtractor.h"
+
+#include "AnotherPacketSource.h"
+#include "ESQueue.h"
+
+#include <media/stagefright/foundation/ABitReader.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/DataSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+#include <utils/String8.h>
+
+namespace android {
+
+struct MPEG2PSExtractor::Track : public MediaSource {
+ Track(MPEG2PSExtractor *extractor,
+ unsigned stream_id, unsigned stream_type);
+
+ 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 ~Track();
+
+private:
+ friend struct MPEG2PSExtractor;
+
+ MPEG2PSExtractor *mExtractor;
+
+ unsigned mStreamID;
+ unsigned mStreamType;
+ ElementaryStreamQueue *mQueue;
+ sp<AnotherPacketSource> mSource;
+
+ status_t appendPESData(
+ unsigned PTS_DTS_flags,
+ uint64_t PTS, uint64_t DTS,
+ const uint8_t *data, size_t size);
+
+ DISALLOW_EVIL_CONSTRUCTORS(Track);
+};
+
+struct MPEG2PSExtractor::WrappedTrack : public MediaSource {
+ WrappedTrack(const sp<MPEG2PSExtractor> &extractor, const sp<Track> &track);
+
+ 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 ~WrappedTrack();
+
+private:
+ sp<MPEG2PSExtractor> mExtractor;
+ sp<MPEG2PSExtractor::Track> mTrack;
+
+ DISALLOW_EVIL_CONSTRUCTORS(WrappedTrack);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+MPEG2PSExtractor::MPEG2PSExtractor(const sp<DataSource> &source)
+ : mDataSource(source),
+ mOffset(0),
+ mFinalResult(OK),
+ mBuffer(new ABuffer(0)),
+ mScanning(true),
+ mProgramStreamMapValid(false) {
+ for (size_t i = 0; i < 500; ++i) {
+ if (feedMore() != OK) {
+ break;
+ }
+ }
+
+ // Remove all tracks that were unable to determine their format.
+ for (size_t i = mTracks.size(); i-- > 0;) {
+ if (mTracks.valueAt(i)->getFormat() == NULL) {
+ mTracks.removeItemsAt(i);
+ }
+ }
+
+ mScanning = false;
+}
+
+MPEG2PSExtractor::~MPEG2PSExtractor() {
+}
+
+size_t MPEG2PSExtractor::countTracks() {
+ return mTracks.size();
+}
+
+sp<MediaSource> MPEG2PSExtractor::getTrack(size_t index) {
+ if (index >= mTracks.size()) {
+ return NULL;
+ }
+
+ return new WrappedTrack(this, mTracks.valueAt(index));
+}
+
+sp<MetaData> MPEG2PSExtractor::getTrackMetaData(size_t index, uint32_t flags) {
+ if (index >= mTracks.size()) {
+ return NULL;
+ }
+
+ return mTracks.valueAt(index)->getFormat();
+}
+
+sp<MetaData> MPEG2PSExtractor::getMetaData() {
+ sp<MetaData> meta = new MetaData;
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2PS);
+
+ return meta;
+}
+
+uint32_t MPEG2PSExtractor::flags() const {
+ return CAN_PAUSE;
+}
+
+status_t MPEG2PSExtractor::feedMore() {
+ Mutex::Autolock autoLock(mLock);
+
+ // How much data we're reading at a time
+ static const size_t kChunkSize = 8192;
+
+ for (;;) {
+ status_t err = dequeueChunk();
+
+ if (err == -EAGAIN && mFinalResult == OK) {
+ memmove(mBuffer->base(), mBuffer->data(), mBuffer->size());
+ mBuffer->setRange(0, mBuffer->size());
+
+ if (mBuffer->size() + kChunkSize > mBuffer->capacity()) {
+ size_t newCapacity = mBuffer->capacity() + kChunkSize;
+ sp<ABuffer> newBuffer = new ABuffer(newCapacity);
+ memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
+ newBuffer->setRange(0, mBuffer->size());
+ mBuffer = newBuffer;
+ }
+
+ ssize_t n = mDataSource->readAt(
+ mOffset, mBuffer->data() + mBuffer->size(), kChunkSize);
+
+ if (n < (ssize_t)kChunkSize) {
+ mFinalResult = (n < 0) ? (status_t)n : ERROR_END_OF_STREAM;
+ return mFinalResult;
+ }
+
+ mBuffer->setRange(mBuffer->offset(), mBuffer->size() + n);
+ mOffset += n;
+ } else if (err != OK) {
+ mFinalResult = err;
+ return err;
+ } else {
+ return OK;
+ }
+ }
+}
+
+status_t MPEG2PSExtractor::dequeueChunk() {
+ if (mBuffer->size() < 4) {
+ return -EAGAIN;
+ }
+
+ if (memcmp("\x00\x00\x01", mBuffer->data(), 3)) {
+ return ERROR_MALFORMED;
+ }
+
+ unsigned chunkType = mBuffer->data()[3];
+
+ ssize_t res;
+
+ switch (chunkType) {
+ case 0xba:
+ {
+ res = dequeuePack();
+ break;
+ }
+
+ case 0xbb:
+ {
+ res = dequeueSystemHeader();
+ break;
+ }
+
+ default:
+ {
+ res = dequeuePES();
+ break;
+ }
+ }
+
+ if (res > 0) {
+ if (mBuffer->size() < (size_t)res) {
+ return -EAGAIN;
+ }
+
+ mBuffer->setRange(mBuffer->offset() + res, mBuffer->size() - res);
+ res = OK;
+ }
+
+ return res;
+}
+
+ssize_t MPEG2PSExtractor::dequeuePack() {
+ // 32 + 2 + 3 + 1 + 15 + 1 + 15+ 1 + 9 + 1 + 22 + 1 + 1 | +5
+
+ if (mBuffer->size() < 14) {
+ return -EAGAIN;
+ }
+
+ unsigned pack_stuffing_length = mBuffer->data()[13] & 7;
+
+ return pack_stuffing_length + 14;
+}
+
+ssize_t MPEG2PSExtractor::dequeueSystemHeader() {
+ if (mBuffer->size() < 6) {
+ return -EAGAIN;
+ }
+
+ unsigned header_length = U16_AT(mBuffer->data() + 4);
+
+ return header_length + 6;
+}
+
+ssize_t MPEG2PSExtractor::dequeuePES() {
+ if (mBuffer->size() < 6) {
+ return -EAGAIN;
+ }
+
+ unsigned PES_packet_length = U16_AT(mBuffer->data() + 4);
+ CHECK_NE(PES_packet_length, 0u);
+
+ size_t n = PES_packet_length + 6;
+
+ if (mBuffer->size() < n) {
+ return -EAGAIN;
+ }
+
+ ABitReader br(mBuffer->data(), n);
+
+ unsigned packet_startcode_prefix = br.getBits(24);
+
+ ALOGV("packet_startcode_prefix = 0x%08x", packet_startcode_prefix);
+
+ if (packet_startcode_prefix != 1) {
+ ALOGV("Supposedly payload_unit_start=1 unit does not start "
+ "with startcode.");
+
+ return ERROR_MALFORMED;
+ }
+
+ CHECK_EQ(packet_startcode_prefix, 0x000001u);
+
+ unsigned stream_id = br.getBits(8);
+ ALOGV("stream_id = 0x%02x", stream_id);
+
+ /* unsigned PES_packet_length = */br.getBits(16);
+
+ if (stream_id == 0xbc) {
+ // program_stream_map
+
+ if (!mScanning) {
+ return n;
+ }
+
+ mStreamTypeByESID.clear();
+
+ /* unsigned current_next_indicator = */br.getBits(1);
+ /* unsigned reserved = */br.getBits(2);
+ /* unsigned program_stream_map_version = */br.getBits(5);
+ /* unsigned reserved = */br.getBits(7);
+ /* unsigned marker_bit = */br.getBits(1);
+ unsigned program_stream_info_length = br.getBits(16);
+
+ size_t offset = 0;
+ while (offset < program_stream_info_length) {
+ if (offset + 2 > program_stream_info_length) {
+ return ERROR_MALFORMED;
+ }
+
+ unsigned descriptor_tag = br.getBits(8);
+ unsigned descriptor_length = br.getBits(8);
+
+ ALOGI("found descriptor tag 0x%02x of length %u",
+ descriptor_tag, descriptor_length);
+
+ if (offset + 2 + descriptor_length > program_stream_info_length) {
+ return ERROR_MALFORMED;
+ }
+
+ br.skipBits(8 * descriptor_length);
+
+ offset += 2 + descriptor_length;
+ }
+
+ unsigned elementary_stream_map_length = br.getBits(16);
+
+ offset = 0;
+ while (offset < elementary_stream_map_length) {
+ if (offset + 4 > elementary_stream_map_length) {
+ return ERROR_MALFORMED;
+ }
+
+ unsigned stream_type = br.getBits(8);
+ unsigned elementary_stream_id = br.getBits(8);
+
+ ALOGI("elementary stream id 0x%02x has stream type 0x%02x",
+ elementary_stream_id, stream_type);
+
+ mStreamTypeByESID.add(elementary_stream_id, stream_type);
+
+ unsigned elementary_stream_info_length = br.getBits(16);
+
+ if (offset + 4 + elementary_stream_info_length
+ > elementary_stream_map_length) {
+ return ERROR_MALFORMED;
+ }
+
+ offset += 4 + elementary_stream_info_length;
+ }
+
+ /* unsigned CRC32 = */br.getBits(32);
+
+ mProgramStreamMapValid = true;
+ } else if (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);
+
+ /* unsigned PES_scrambling_control = */br.getBits(2);
+ /* unsigned PES_priority = */br.getBits(1);
+ /* unsigned data_alignment_indicator = */br.getBits(1);
+ /* unsigned copyright = */br.getBits(1);
+ /* unsigned original_or_copy = */br.getBits(1);
+
+ unsigned PTS_DTS_flags = br.getBits(2);
+ ALOGV("PTS_DTS_flags = %u", PTS_DTS_flags);
+
+ unsigned ESCR_flag = br.getBits(1);
+ ALOGV("ESCR_flag = %u", ESCR_flag);
+
+ unsigned ES_rate_flag = br.getBits(1);
+ ALOGV("ES_rate_flag = %u", ES_rate_flag);
+
+ unsigned DSM_trick_mode_flag = br.getBits(1);
+ ALOGV("DSM_trick_mode_flag = %u", DSM_trick_mode_flag);
+
+ unsigned additional_copy_info_flag = br.getBits(1);
+ ALOGV("additional_copy_info_flag = %u", additional_copy_info_flag);
+
+ /* unsigned PES_CRC_flag = */br.getBits(1);
+ /* PES_extension_flag = */br.getBits(1);
+
+ unsigned PES_header_data_length = br.getBits(8);
+ ALOGV("PES_header_data_length = %u", 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);
+
+ ALOGV("PTS = %llu", PTS);
+ // ALOGI("PTS = %.2f secs", PTS / 90000.0f);
+
+ 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);
+
+ ALOGV("DTS = %llu", 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);
+
+ ALOGV("ESCR = %llu", ESCR);
+ /* unsigned 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);
+ /* unsigned ES_rate = */br.getBits(22);
+ CHECK_EQ(br.getBits(1), 1u);
+
+ optional_bytes_remaining -= 3;
+ }
+
+ br.skipBits(optional_bytes_remaining * 8);
+
+ // ES data follows.
+
+ CHECK_GE(PES_packet_length, PES_header_data_length + 3);
+
+ unsigned dataLength =
+ PES_packet_length - 3 - PES_header_data_length;
+
+ if (br.numBitsLeft() < dataLength * 8) {
+ ALOGE("PES packet does not carry enough data to contain "
+ "payload. (numBitsLeft = %d, required = %d)",
+ br.numBitsLeft(), dataLength * 8);
+
+ return ERROR_MALFORMED;
+ }
+
+ CHECK_GE(br.numBitsLeft(), dataLength * 8);
+
+ ssize_t index = mTracks.indexOfKey(stream_id);
+ if (index < 0 && mScanning) {
+ unsigned streamType;
+
+ ssize_t streamTypeIndex;
+ if (mProgramStreamMapValid
+ && (streamTypeIndex =
+ mStreamTypeByESID.indexOfKey(stream_id)) >= 0) {
+ streamType = mStreamTypeByESID.valueAt(streamTypeIndex);
+ } else if ((stream_id & ~0x1f) == 0xc0) {
+ // ISO/IEC 13818-3 or ISO/IEC 11172-3 or ISO/IEC 13818-7
+ // or ISO/IEC 14496-3 audio
+ streamType = ATSParser::STREAMTYPE_MPEG2_AUDIO;
+ } else if ((stream_id & ~0x0f) == 0xe0) {
+ // ISO/IEC 13818-2 or ISO/IEC 11172-2 or ISO/IEC 14496-2 video
+ streamType = ATSParser::STREAMTYPE_MPEG2_VIDEO;
+ } else {
+ streamType = ATSParser::STREAMTYPE_RESERVED;
+ }
+
+ index = mTracks.add(
+ stream_id, new Track(this, stream_id, streamType));
+ }
+
+ status_t err = OK;
+
+ if (index >= 0) {
+ err =
+ mTracks.editValueAt(index)->appendPESData(
+ PTS_DTS_flags, PTS, DTS, br.data(), dataLength);
+ }
+
+ br.skipBits(dataLength * 8);
+
+ if (err != OK) {
+ return err;
+ }
+ } 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);
+ }
+
+ return n;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MPEG2PSExtractor::Track::Track(
+ MPEG2PSExtractor *extractor, unsigned stream_id, unsigned stream_type)
+ : mExtractor(extractor),
+ mStreamID(stream_id),
+ mStreamType(stream_type),
+ mQueue(NULL) {
+ bool supported = true;
+ ElementaryStreamQueue::Mode mode;
+
+ switch (mStreamType) {
+ case ATSParser::STREAMTYPE_H264:
+ mode = ElementaryStreamQueue::H264;
+ break;
+ case ATSParser::STREAMTYPE_MPEG2_AUDIO_ADTS:
+ mode = ElementaryStreamQueue::AAC;
+ break;
+ case ATSParser::STREAMTYPE_MPEG1_AUDIO:
+ case ATSParser::STREAMTYPE_MPEG2_AUDIO:
+ mode = ElementaryStreamQueue::MPEG_AUDIO;
+ break;
+
+ case ATSParser::STREAMTYPE_MPEG1_VIDEO:
+ case ATSParser::STREAMTYPE_MPEG2_VIDEO:
+ mode = ElementaryStreamQueue::MPEG_VIDEO;
+ break;
+
+ case ATSParser::STREAMTYPE_MPEG4_VIDEO:
+ mode = ElementaryStreamQueue::MPEG4_VIDEO;
+ break;
+
+ default:
+ supported = false;
+ break;
+ }
+
+ if (supported) {
+ mQueue = new ElementaryStreamQueue(mode);
+ } else {
+ ALOGI("unsupported stream ID 0x%02x", stream_id);
+ }
+}
+
+MPEG2PSExtractor::Track::~Track() {
+ delete mQueue;
+ mQueue = NULL;
+}
+
+status_t MPEG2PSExtractor::Track::start(MetaData *params) {
+ if (mSource == NULL) {
+ return NO_INIT;
+ }
+
+ return mSource->start(params);
+}
+
+status_t MPEG2PSExtractor::Track::stop() {
+ if (mSource == NULL) {
+ return NO_INIT;
+ }
+
+ return mSource->stop();
+}
+
+sp<MetaData> MPEG2PSExtractor::Track::getFormat() {
+ if (mSource == NULL) {
+ return NULL;
+ }
+
+ return mSource->getFormat();
+}
+
+status_t MPEG2PSExtractor::Track::read(
+ MediaBuffer **buffer, const ReadOptions *options) {
+ if (mSource == NULL) {
+ return NO_INIT;
+ }
+
+ status_t finalResult;
+ while (!mSource->hasBufferAvailable(&finalResult)) {
+ if (finalResult != OK) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ status_t err = mExtractor->feedMore();
+
+ if (err != OK) {
+ mSource->signalEOS(err);
+ }
+ }
+
+ return mSource->read(buffer, options);
+}
+
+status_t MPEG2PSExtractor::Track::appendPESData(
+ unsigned PTS_DTS_flags,
+ uint64_t PTS, uint64_t DTS,
+ const uint8_t *data, size_t size) {
+ if (mQueue == NULL) {
+ return OK;
+ }
+
+ int64_t timeUs;
+ if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
+ timeUs = (PTS * 100) / 9;
+ } else {
+ timeUs = 0;
+ }
+
+ status_t err = mQueue->appendData(data, size, timeUs);
+
+ if (err != OK) {
+ return err;
+ }
+
+ sp<ABuffer> accessUnit;
+ while ((accessUnit = mQueue->dequeueAccessUnit()) != NULL) {
+ if (mSource == NULL) {
+ sp<MetaData> meta = mQueue->getFormat();
+
+ if (meta != NULL) {
+ ALOGV("Stream ID 0x%02x now has data.", mStreamID);
+
+ mSource = new AnotherPacketSource(meta);
+ mSource->queueAccessUnit(accessUnit);
+ }
+ } else if (mQueue->getFormat() != NULL) {
+ mSource->queueAccessUnit(accessUnit);
+ }
+ }
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MPEG2PSExtractor::WrappedTrack::WrappedTrack(
+ const sp<MPEG2PSExtractor> &extractor, const sp<Track> &track)
+ : mExtractor(extractor),
+ mTrack(track) {
+}
+
+MPEG2PSExtractor::WrappedTrack::~WrappedTrack() {
+}
+
+status_t MPEG2PSExtractor::WrappedTrack::start(MetaData *params) {
+ return mTrack->start(params);
+}
+
+status_t MPEG2PSExtractor::WrappedTrack::stop() {
+ return mTrack->stop();
+}
+
+sp<MetaData> MPEG2PSExtractor::WrappedTrack::getFormat() {
+ return mTrack->getFormat();
+}
+
+status_t MPEG2PSExtractor::WrappedTrack::read(
+ MediaBuffer **buffer, const ReadOptions *options) {
+ return mTrack->read(buffer, options);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool SniffMPEG2PS(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
+ uint8_t header[5];
+ if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
+ return false;
+ }
+
+ if (memcmp("\x00\x00\x01\xba", header, 4) || (header[4] >> 6) != 1) {
+ return false;
+ }
+
+ *confidence = 0.25f; // Slightly larger than .mp3 extractor's confidence
+
+ mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2PS);
+
+ return true;
+}
+
+} // namespace android
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
new file mode 100644
index 0000000..e1589b4
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -0,0 +1,266 @@
+/*
+ * 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 "include/LiveSession.h"
+#include "include/NuCachedSource2.h"
+
+#include <media/stagefright/foundation/ADebug.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 {
+
+static const size_t kTSPacketSize = 188;
+
+struct MPEG2TSSource : public MediaSource {
+ MPEG2TSSource(
+ const sp<MPEG2TSExtractor> &extractor,
+ const sp<AnotherPacketSource> &impl,
+ bool seekable);
+
+ 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;
+
+ // If there are both audio and video streams, only the video stream
+ // will be seekable, otherwise the single stream will be seekable.
+ bool mSeekable;
+
+ DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource);
+};
+
+MPEG2TSSource::MPEG2TSSource(
+ const sp<MPEG2TSExtractor> &extractor,
+ const sp<AnotherPacketSource> &impl,
+ bool seekable)
+ : mExtractor(extractor),
+ mImpl(impl),
+ mSeekable(seekable) {
+}
+
+status_t MPEG2TSSource::start(MetaData *params) {
+ return mImpl->start(params);
+}
+
+status_t MPEG2TSSource::stop() {
+ return mImpl->stop();
+}
+
+sp<MetaData> MPEG2TSSource::getFormat() {
+ sp<MetaData> meta = mImpl->getFormat();
+
+ int64_t durationUs;
+ if (mExtractor->mLiveSession != NULL
+ && mExtractor->mLiveSession->getDuration(&durationUs) == OK) {
+ meta->setInt64(kKeyDuration, durationUs);
+ }
+
+ return meta;
+}
+
+status_t MPEG2TSSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode seekMode;
+ if (mSeekable && options && options->getSeekTo(&seekTimeUs, &seekMode)) {
+ mExtractor->seekTo(seekTimeUs);
+ }
+
+ 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;
+ }
+
+ bool seekable = true;
+ if (mSourceImpls.size() > 1) {
+ CHECK_EQ(mSourceImpls.size(), 2u);
+
+ sp<MetaData> meta = mSourceImpls.editItemAt(index)->getFormat();
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (!strncasecmp("audio/", mime, 6)) {
+ seekable = false;
+ }
+ }
+
+ return new MPEG2TSSource(this, mSourceImpls.editItemAt(index), seekable);
+}
+
+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;
+ int numPacketsParsed = 0;
+
+ while (feedMore() == OK) {
+ ATSParser::SourceType type;
+ if (haveAudio && haveVideo) {
+ break;
+ }
+ if (!haveVideo) {
+ sp<AnotherPacketSource> impl =
+ (AnotherPacketSource *)mParser->getSource(
+ ATSParser::VIDEO).get();
+
+ if (impl != NULL) {
+ haveVideo = true;
+ mSourceImpls.push(impl);
+ }
+ }
+
+ if (!haveAudio) {
+ sp<AnotherPacketSource> impl =
+ (AnotherPacketSource *)mParser->getSource(
+ ATSParser::AUDIO).get();
+
+ if (impl != NULL) {
+ haveAudio = true;
+ mSourceImpls.push(impl);
+ }
+ }
+
+ if (++numPacketsParsed > 10000) {
+ break;
+ }
+ }
+
+ ALOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo);
+}
+
+status_t MPEG2TSExtractor::feedMore() {
+ Mutex::Autolock autoLock(mLock);
+
+ 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 += n;
+ return mParser->feedTSPacket(packet, kTSPacketSize);
+}
+
+void MPEG2TSExtractor::setLiveSession(const sp<LiveSession> &liveSession) {
+ Mutex::Autolock autoLock(mLock);
+
+ mLiveSession = liveSession;
+}
+
+void MPEG2TSExtractor::seekTo(int64_t seekTimeUs) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mLiveSession == NULL) {
+ return;
+ }
+
+ mLiveSession->seekTo(seekTimeUs);
+}
+
+uint32_t MPEG2TSExtractor::flags() const {
+ Mutex::Autolock autoLock(mLock);
+
+ uint32_t flags = CAN_PAUSE;
+
+ if (mLiveSession != NULL && mLiveSession->isSeekable()) {
+ flags |= CAN_SEEK_FORWARD | CAN_SEEK_BACKWARD | CAN_SEEK;
+ }
+
+ return flags;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool SniffMPEG2TS(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
+ for (int i = 0; i < 5; ++i) {
+ char header;
+ if (source->readAt(kTSPacketSize * i, &header, 1) != 1
+ || header != 0x47) {
+ return false;
+ }
+ }
+
+ *confidence = 0.1f;
+ mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+
+ return true;
+}
+
+} // namespace android
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
new file mode 100644
index 0000000..d20ecb6
--- /dev/null
+++ b/media/libstagefright/omx/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ OMX.cpp \
+ OMXMaster.cpp \
+ OMXNodeInstance.cpp \
+ SimpleSoftOMXComponent.cpp \
+ SoftOMXComponent.cpp \
+ SoftOMXPlugin.cpp \
+
+LOCAL_C_INCLUDES += \
+ frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/hardware \
+ $(TOP)/frameworks/native/include/media/openmax
+
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libmedia \
+ libutils \
+ libui \
+ libcutils \
+ libstagefright_foundation \
+ libdl
+
+LOCAL_MODULE:= libstagefright_omx
+
+include $(BUILD_SHARED_LIBRARY)
+
+################################################################################
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
new file mode 100644
index 0000000..f11fcd2
--- /dev/null
+++ b/media/libstagefright/omx/OMX.cpp
@@ -0,0 +1,470 @@
+/*
+ * 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 "OMX"
+#include <utils/Log.h>
+
+#include <dlfcn.h>
+
+#include "../include/OMX.h"
+
+#include "../include/OMXNodeInstance.h"
+
+#include <binder/IMemory.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <utils/threads.h>
+
+#include "OMXMaster.h"
+
+#include <OMX_Component.h>
+
+namespace android {
+
+////////////////////////////////////////////////////////////////////////////////
+
+// This provides the underlying Thread used by CallbackDispatcher.
+// Note that deriving CallbackDispatcher from Thread does not work.
+
+struct OMX::CallbackDispatcherThread : public Thread {
+ CallbackDispatcherThread(CallbackDispatcher *dispatcher)
+ : mDispatcher(dispatcher) {
+ }
+
+private:
+ CallbackDispatcher *mDispatcher;
+
+ bool threadLoop();
+
+ CallbackDispatcherThread(const CallbackDispatcherThread &);
+ CallbackDispatcherThread &operator=(const CallbackDispatcherThread &);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct OMX::CallbackDispatcher : public RefBase {
+ CallbackDispatcher(OMXNodeInstance *owner);
+
+ void post(const omx_message &msg);
+
+ bool loop();
+
+protected:
+ virtual ~CallbackDispatcher();
+
+private:
+ Mutex mLock;
+
+ OMXNodeInstance *mOwner;
+ bool mDone;
+ Condition mQueueChanged;
+ List<omx_message> mQueue;
+
+ sp<CallbackDispatcherThread> mThread;
+
+ void dispatch(const omx_message &msg);
+
+ CallbackDispatcher(const CallbackDispatcher &);
+ CallbackDispatcher &operator=(const CallbackDispatcher &);
+};
+
+OMX::CallbackDispatcher::CallbackDispatcher(OMXNodeInstance *owner)
+ : mOwner(owner),
+ mDone(false) {
+ mThread = new CallbackDispatcherThread(this);
+ mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND);
+}
+
+OMX::CallbackDispatcher::~CallbackDispatcher() {
+ {
+ Mutex::Autolock autoLock(mLock);
+
+ mDone = true;
+ mQueueChanged.signal();
+ }
+
+ // A join on self can happen if the last ref to CallbackDispatcher
+ // is released within the CallbackDispatcherThread loop
+ status_t status = mThread->join();
+ if (status != WOULD_BLOCK) {
+ // Other than join to self, the only other error return codes are
+ // whatever readyToRun() returns, and we don't override that
+ CHECK_EQ(status, (status_t)NO_ERROR);
+ }
+}
+
+void OMX::CallbackDispatcher::post(const omx_message &msg) {
+ Mutex::Autolock autoLock(mLock);
+
+ mQueue.push_back(msg);
+ mQueueChanged.signal();
+}
+
+void OMX::CallbackDispatcher::dispatch(const omx_message &msg) {
+ if (mOwner == NULL) {
+ ALOGV("Would have dispatched a message to a node that's already gone.");
+ return;
+ }
+ mOwner->onMessage(msg);
+}
+
+bool OMX::CallbackDispatcher::loop() {
+ for (;;) {
+ omx_message msg;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+ while (!mDone && mQueue.empty()) {
+ mQueueChanged.wait(mLock);
+ }
+
+ if (mDone) {
+ break;
+ }
+
+ msg = *mQueue.begin();
+ mQueue.erase(mQueue.begin());
+ }
+
+ dispatch(msg);
+ }
+
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool OMX::CallbackDispatcherThread::threadLoop() {
+ return mDispatcher->loop();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+OMX::OMX()
+ : mMaster(new OMXMaster),
+ mNodeCounter(0) {
+}
+
+OMX::~OMX() {
+ delete mMaster;
+ mMaster = NULL;
+}
+
+void OMX::binderDied(const wp<IBinder> &the_late_who) {
+ OMXNodeInstance *instance;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+
+ ssize_t index = mLiveNodes.indexOfKey(the_late_who);
+ CHECK(index >= 0);
+
+ instance = mLiveNodes.editValueAt(index);
+ mLiveNodes.removeItemsAt(index);
+
+ index = mDispatchers.indexOfKey(instance->nodeID());
+ CHECK(index >= 0);
+ mDispatchers.removeItemsAt(index);
+
+ invalidateNodeID_l(instance->nodeID());
+ }
+
+ instance->onObserverDied(mMaster);
+}
+
+bool OMX::livesLocally(node_id node, pid_t pid) {
+ return pid == getpid();
+}
+
+status_t OMX::listNodes(List<ComponentInfo> *list) {
+ list->clear();
+
+ OMX_U32 index = 0;
+ char componentName[256];
+ while (mMaster->enumerateComponents(
+ componentName, sizeof(componentName), index) == OMX_ErrorNone) {
+ list->push_back(ComponentInfo());
+ ComponentInfo &info = *--list->end();
+
+ info.mName = componentName;
+
+ Vector<String8> roles;
+ OMX_ERRORTYPE err =
+ mMaster->getRolesOfComponent(componentName, &roles);
+
+ if (err == OMX_ErrorNone) {
+ for (OMX_U32 i = 0; i < roles.size(); ++i) {
+ info.mRoles.push_back(roles[i]);
+ }
+ }
+
+ ++index;
+ }
+
+ return OK;
+}
+
+status_t OMX::allocateNode(
+ const char *name, const sp<IOMXObserver> &observer, node_id *node) {
+ Mutex::Autolock autoLock(mLock);
+
+ *node = 0;
+
+ OMXNodeInstance *instance = new OMXNodeInstance(this, observer);
+
+ OMX_COMPONENTTYPE *handle;
+ OMX_ERRORTYPE err = mMaster->makeComponentInstance(
+ name, &OMXNodeInstance::kCallbacks,
+ instance, &handle);
+
+ if (err != OMX_ErrorNone) {
+ ALOGV("FAILED to allocate omx component '%s'", name);
+
+ instance->onGetHandleFailed();
+
+ return UNKNOWN_ERROR;
+ }
+
+ *node = makeNodeID(instance);
+ mDispatchers.add(*node, new CallbackDispatcher(instance));
+
+ instance->setHandle(*node, handle);
+
+ mLiveNodes.add(observer->asBinder(), instance);
+ observer->asBinder()->linkToDeath(this);
+
+ return OK;
+}
+
+status_t OMX::freeNode(node_id node) {
+ OMXNodeInstance *instance = findInstance(node);
+
+ ssize_t index = mLiveNodes.indexOfKey(instance->observer()->asBinder());
+ CHECK(index >= 0);
+ mLiveNodes.removeItemsAt(index);
+
+ instance->observer()->asBinder()->unlinkToDeath(this);
+
+ status_t err = instance->freeNode(mMaster);
+
+ {
+ Mutex::Autolock autoLock(mLock);
+ index = mDispatchers.indexOfKey(node);
+ CHECK(index >= 0);
+ mDispatchers.removeItemsAt(index);
+ }
+
+ return err;
+}
+
+status_t OMX::sendCommand(
+ node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
+ return findInstance(node)->sendCommand(cmd, param);
+}
+
+status_t OMX::getParameter(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size) {
+ return findInstance(node)->getParameter(
+ index, params, size);
+}
+
+status_t OMX::setParameter(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size) {
+ return findInstance(node)->setParameter(
+ index, params, size);
+}
+
+status_t OMX::getConfig(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size) {
+ return findInstance(node)->getConfig(
+ index, params, size);
+}
+
+status_t OMX::setConfig(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size) {
+ return findInstance(node)->setConfig(
+ index, params, size);
+}
+
+status_t OMX::getState(
+ node_id node, OMX_STATETYPE* state) {
+ return findInstance(node)->getState(
+ state);
+}
+
+status_t OMX::enableGraphicBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+ return findInstance(node)->enableGraphicBuffers(port_index, enable);
+}
+
+status_t OMX::getGraphicBufferUsage(
+ node_id node, OMX_U32 port_index, OMX_U32* usage) {
+ return findInstance(node)->getGraphicBufferUsage(port_index, usage);
+}
+
+status_t OMX::storeMetaDataInBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+ return findInstance(node)->storeMetaDataInBuffers(port_index, enable);
+}
+
+status_t OMX::useBuffer(
+ node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+ buffer_id *buffer) {
+ return findInstance(node)->useBuffer(
+ port_index, params, buffer);
+}
+
+status_t OMX::useGraphicBuffer(
+ node_id node, OMX_U32 port_index,
+ const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
+ return findInstance(node)->useGraphicBuffer(
+ port_index, graphicBuffer, buffer);
+}
+
+status_t OMX::allocateBuffer(
+ node_id node, OMX_U32 port_index, size_t size,
+ buffer_id *buffer, void **buffer_data) {
+ return findInstance(node)->allocateBuffer(
+ port_index, size, buffer, buffer_data);
+}
+
+status_t OMX::allocateBufferWithBackup(
+ node_id node, OMX_U32 port_index, const sp<IMemory> &params,
+ buffer_id *buffer) {
+ return findInstance(node)->allocateBufferWithBackup(
+ port_index, params, buffer);
+}
+
+status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
+ return findInstance(node)->freeBuffer(
+ port_index, buffer);
+}
+
+status_t OMX::fillBuffer(node_id node, buffer_id buffer) {
+ return findInstance(node)->fillBuffer(buffer);
+}
+
+status_t OMX::emptyBuffer(
+ node_id node,
+ buffer_id buffer,
+ OMX_U32 range_offset, OMX_U32 range_length,
+ OMX_U32 flags, OMX_TICKS timestamp) {
+ return findInstance(node)->emptyBuffer(
+ buffer, range_offset, range_length, flags, timestamp);
+}
+
+status_t OMX::getExtensionIndex(
+ node_id node,
+ const char *parameter_name,
+ OMX_INDEXTYPE *index) {
+ return findInstance(node)->getExtensionIndex(
+ parameter_name, index);
+}
+
+OMX_ERRORTYPE OMX::OnEvent(
+ node_id node,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData) {
+ ALOGV("OnEvent(%d, %ld, %ld)", eEvent, nData1, nData2);
+
+ omx_message msg;
+ msg.type = omx_message::EVENT;
+ msg.node = node;
+ msg.u.event_data.event = eEvent;
+ msg.u.event_data.data1 = nData1;
+ msg.u.event_data.data2 = nData2;
+
+ findDispatcher(node)->post(msg);
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OMX::OnEmptyBufferDone(
+ node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
+ ALOGV("OnEmptyBufferDone buffer=%p", pBuffer);
+
+ omx_message msg;
+ msg.type = omx_message::EMPTY_BUFFER_DONE;
+ msg.node = node;
+ msg.u.buffer_data.buffer = pBuffer;
+
+ findDispatcher(node)->post(msg);
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OMX::OnFillBufferDone(
+ node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) {
+ ALOGV("OnFillBufferDone buffer=%p", pBuffer);
+
+ omx_message msg;
+ msg.type = omx_message::FILL_BUFFER_DONE;
+ msg.node = node;
+ msg.u.extended_buffer_data.buffer = pBuffer;
+ msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
+ msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
+ msg.u.extended_buffer_data.flags = pBuffer->nFlags;
+ msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
+ msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate;
+ msg.u.extended_buffer_data.data_ptr = pBuffer->pBuffer;
+
+ findDispatcher(node)->post(msg);
+
+ return OMX_ErrorNone;
+}
+
+OMX::node_id OMX::makeNodeID(OMXNodeInstance *instance) {
+ // mLock is already held.
+
+ node_id node = (node_id)++mNodeCounter;
+ mNodeIDToInstance.add(node, instance);
+
+ return node;
+}
+
+OMXNodeInstance *OMX::findInstance(node_id node) {
+ Mutex::Autolock autoLock(mLock);
+
+ ssize_t index = mNodeIDToInstance.indexOfKey(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);
+}
+
+void OMX::invalidateNodeID_l(node_id node) {
+ // mLock is held.
+ mNodeIDToInstance.removeItem(node);
+}
+
+} // namespace android
diff --git a/media/libstagefright/omx/OMXMaster.cpp b/media/libstagefright/omx/OMXMaster.cpp
new file mode 100644
index 0000000..6b6d0ab
--- /dev/null
+++ b/media/libstagefright/omx/OMXMaster.cpp
@@ -0,0 +1,202 @@
+/*
+ * 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 "OMXMaster"
+#include <utils/Log.h>
+
+#include "OMXMaster.h"
+
+#include "SoftOMXPlugin.h"
+
+#include <dlfcn.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+OMXMaster::OMXMaster()
+ : mVendorLibHandle(NULL) {
+ addVendorPlugin();
+ addPlugin(new SoftOMXPlugin);
+}
+
+OMXMaster::~OMXMaster() {
+ clearPlugins();
+
+ if (mVendorLibHandle != NULL) {
+ dlclose(mVendorLibHandle);
+ mVendorLibHandle = NULL;
+ }
+}
+
+void OMXMaster::addVendorPlugin() {
+ addPlugin("libstagefrighthw.so");
+}
+
+void OMXMaster::addPlugin(const char *libname) {
+ mVendorLibHandle = dlopen(libname, RTLD_NOW);
+
+ if (mVendorLibHandle == NULL) {
+ return;
+ }
+
+ typedef OMXPluginBase *(*CreateOMXPluginFunc)();
+ CreateOMXPluginFunc createOMXPlugin =
+ (CreateOMXPluginFunc)dlsym(
+ mVendorLibHandle, "createOMXPlugin");
+ if (!createOMXPlugin)
+ createOMXPlugin = (CreateOMXPluginFunc)dlsym(
+ mVendorLibHandle, "_ZN7android15createOMXPluginEv");
+
+ if (createOMXPlugin) {
+ addPlugin((*createOMXPlugin)());
+ }
+}
+
+void OMXMaster::addPlugin(OMXPluginBase *plugin) {
+ Mutex::Autolock autoLock(mLock);
+
+ mPlugins.push_back(plugin);
+
+ OMX_U32 index = 0;
+
+ char name[128];
+ OMX_ERRORTYPE err;
+ while ((err = plugin->enumerateComponents(
+ name, sizeof(name), index++)) == OMX_ErrorNone) {
+ String8 name8(name);
+
+ if (mPluginByComponentName.indexOfKey(name8) >= 0) {
+ ALOGE("A component of name '%s' already exists, ignoring this one.",
+ name8.string());
+
+ continue;
+ }
+
+ mPluginByComponentName.add(name8, plugin);
+ }
+
+ if (err != OMX_ErrorNoMore) {
+ ALOGE("OMX plugin failed w/ error 0x%08x after registering %d "
+ "components", err, mPluginByComponentName.size());
+ }
+}
+
+void OMXMaster::clearPlugins() {
+ Mutex::Autolock autoLock(mLock);
+
+ typedef void (*DestroyOMXPluginFunc)(OMXPluginBase*);
+ DestroyOMXPluginFunc destroyOMXPlugin =
+ (DestroyOMXPluginFunc)dlsym(
+ mVendorLibHandle, "destroyOMXPlugin");
+
+ mPluginByComponentName.clear();
+
+ for (List<OMXPluginBase *>::iterator it = mPlugins.begin();
+ it != mPlugins.end(); ++it) {
+ if (destroyOMXPlugin)
+ destroyOMXPlugin(*it);
+ else
+ delete *it;
+ *it = NULL;
+ }
+
+ mPlugins.clear();
+}
+
+OMX_ERRORTYPE OMXMaster::makeComponentInstance(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component) {
+ Mutex::Autolock autoLock(mLock);
+
+ *component = NULL;
+
+ ssize_t index = mPluginByComponentName.indexOfKey(String8(name));
+
+ if (index < 0) {
+ return OMX_ErrorInvalidComponentName;
+ }
+
+ OMXPluginBase *plugin = mPluginByComponentName.valueAt(index);
+ OMX_ERRORTYPE err =
+ plugin->makeComponentInstance(name, callbacks, appData, component);
+
+ if (err != OMX_ErrorNone) {
+ return err;
+ }
+
+ mPluginByInstance.add(*component, plugin);
+
+ return err;
+}
+
+OMX_ERRORTYPE OMXMaster::destroyComponentInstance(
+ OMX_COMPONENTTYPE *component) {
+ Mutex::Autolock autoLock(mLock);
+
+ ssize_t index = mPluginByInstance.indexOfKey(component);
+
+ if (index < 0) {
+ return OMX_ErrorBadParameter;
+ }
+
+ OMXPluginBase *plugin = mPluginByInstance.valueAt(index);
+ mPluginByInstance.removeItemsAt(index);
+
+ return plugin->destroyComponentInstance(component);
+}
+
+OMX_ERRORTYPE OMXMaster::enumerateComponents(
+ OMX_STRING name,
+ size_t size,
+ OMX_U32 index) {
+ Mutex::Autolock autoLock(mLock);
+
+ size_t numComponents = mPluginByComponentName.size();
+
+ if (index >= numComponents) {
+ return OMX_ErrorNoMore;
+ }
+
+ const String8 &name8 = mPluginByComponentName.keyAt(index);
+
+ CHECK(size >= 1 + name8.size());
+ strcpy(name, name8.string());
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE OMXMaster::getRolesOfComponent(
+ const char *name,
+ Vector<String8> *roles) {
+ Mutex::Autolock autoLock(mLock);
+
+ roles->clear();
+
+ ssize_t index = mPluginByComponentName.indexOfKey(String8(name));
+
+ if (index < 0) {
+ return OMX_ErrorInvalidComponentName;
+ }
+
+ OMXPluginBase *plugin = mPluginByComponentName.valueAt(index);
+ return plugin->getRolesOfComponent(name, roles);
+}
+
+} // namespace android
diff --git a/media/libstagefright/omx/OMXMaster.h b/media/libstagefright/omx/OMXMaster.h
new file mode 100644
index 0000000..6069741
--- /dev/null
+++ b/media/libstagefright/omx/OMXMaster.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#ifndef OMX_MASTER_H_
+
+#define OMX_MASTER_H_
+
+#include <OMXPluginBase.h>
+
+#include <utils/threads.h>
+#include <utils/KeyedVector.h>
+#include <utils/List.h>
+#include <utils/String8.h>
+
+namespace android {
+
+struct OMXMaster : public OMXPluginBase {
+ OMXMaster();
+ virtual ~OMXMaster();
+
+ virtual OMX_ERRORTYPE makeComponentInstance(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+ virtual OMX_ERRORTYPE destroyComponentInstance(
+ OMX_COMPONENTTYPE *component);
+
+ virtual OMX_ERRORTYPE enumerateComponents(
+ OMX_STRING name,
+ size_t size,
+ OMX_U32 index);
+
+ virtual OMX_ERRORTYPE getRolesOfComponent(
+ const char *name,
+ Vector<String8> *roles);
+
+private:
+ Mutex mLock;
+ List<OMXPluginBase *> mPlugins;
+ KeyedVector<String8, OMXPluginBase *> mPluginByComponentName;
+ KeyedVector<OMX_COMPONENTTYPE *, OMXPluginBase *> mPluginByInstance;
+
+ void *mVendorLibHandle;
+
+ void addVendorPlugin();
+ void addPlugin(const char *libname);
+ void addPlugin(OMXPluginBase *plugin);
+ void clearPlugins();
+
+ OMXMaster(const OMXMaster &);
+ OMXMaster &operator=(const OMXMaster &);
+};
+
+} // namespace android
+
+#endif // OMX_MASTER_H_
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
new file mode 100644
index 0000000..bff3def
--- /dev/null
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -0,0 +1,757 @@
+/*
+ * 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 "OMXNodeInstance"
+#include <utils/Log.h>
+
+#include "../include/OMXNodeInstance.h"
+#include "OMXMaster.h"
+
+#include <OMX_Component.h>
+
+#include <binder/IMemory.h>
+#include <HardwareAPI.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+struct BufferMeta {
+ BufferMeta(const sp<IMemory> &mem, bool is_backup = false)
+ : mMem(mem),
+ mIsBackup(is_backup) {
+ }
+
+ BufferMeta(size_t size)
+ : mSize(size),
+ mIsBackup(false) {
+ }
+
+ BufferMeta(const sp<GraphicBuffer> &graphicBuffer)
+ : mGraphicBuffer(graphicBuffer),
+ mIsBackup(false) {
+ }
+
+ void CopyFromOMX(const OMX_BUFFERHEADERTYPE *header) {
+ if (!mIsBackup) {
+ return;
+ }
+
+ memcpy((OMX_U8 *)mMem->pointer() + header->nOffset,
+ header->pBuffer + header->nOffset,
+ header->nFilledLen);
+ }
+
+ void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
+ if (!mIsBackup) {
+ return;
+ }
+
+ memcpy(header->pBuffer + header->nOffset,
+ (const OMX_U8 *)mMem->pointer() + header->nOffset,
+ header->nFilledLen);
+ }
+
+private:
+ sp<GraphicBuffer> mGraphicBuffer;
+ sp<IMemory> mMem;
+ size_t mSize;
+ bool mIsBackup;
+
+ BufferMeta(const BufferMeta &);
+ BufferMeta &operator=(const BufferMeta &);
+};
+
+// static
+OMX_CALLBACKTYPE OMXNodeInstance::kCallbacks = {
+ &OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
+};
+
+OMXNodeInstance::OMXNodeInstance(
+ OMX *owner, const sp<IOMXObserver> &observer)
+ : mOwner(owner),
+ mNodeID(NULL),
+ mHandle(NULL),
+ mObserver(observer),
+ mDying(false) {
+}
+
+OMXNodeInstance::~OMXNodeInstance() {
+ CHECK(mHandle == NULL);
+}
+
+void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
+ CHECK(mHandle == NULL);
+ mNodeID = node_id;
+ mHandle = handle;
+}
+
+OMX *OMXNodeInstance::owner() {
+ return mOwner;
+}
+
+sp<IOMXObserver> OMXNodeInstance::observer() {
+ return mObserver;
+}
+
+OMX::node_id OMXNodeInstance::nodeID() {
+ return mNodeID;
+}
+
+static status_t StatusFromOMXError(OMX_ERRORTYPE err) {
+ switch (err) {
+ case OMX_ErrorNone:
+ return OK;
+ case OMX_ErrorUnsupportedSetting:
+ return ERROR_UNSUPPORTED;
+ default:
+ return UNKNOWN_ERROR;
+ }
+}
+
+status_t OMXNodeInstance::freeNode(OMXMaster *master) {
+ static int32_t kMaxNumIterations = 10;
+
+ // Transition the node from its current state all the way down
+ // to "Loaded".
+ // This ensures that all active buffers are properly freed even
+ // for components that don't do this themselves on a call to
+ // "FreeHandle".
+
+ // The code below may trigger some more events to be dispatched
+ // by the OMX component - we want to ignore them as our client
+ // does not expect them.
+ mDying = true;
+
+ OMX_STATETYPE state;
+ CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone);
+ switch (state) {
+ case OMX_StateExecuting:
+ {
+ ALOGV("forcing Executing->Idle");
+ sendCommand(OMX_CommandStateSet, OMX_StateIdle);
+ OMX_ERRORTYPE err;
+ int32_t iteration = 0;
+ while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
+ && state != OMX_StateIdle
+ && state != OMX_StateInvalid) {
+ if (++iteration > kMaxNumIterations) {
+ ALOGE("component failed to enter Idle state, aborting.");
+ state = OMX_StateInvalid;
+ break;
+ }
+
+ usleep(100000);
+ }
+ CHECK_EQ(err, OMX_ErrorNone);
+
+ if (state == OMX_StateInvalid) {
+ break;
+ }
+
+ // fall through
+ }
+
+ case OMX_StateIdle:
+ {
+ ALOGV("forcing Idle->Loaded");
+ sendCommand(OMX_CommandStateSet, OMX_StateLoaded);
+
+ freeActiveBuffers();
+
+ OMX_ERRORTYPE err;
+ int32_t iteration = 0;
+ while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
+ && state != OMX_StateLoaded
+ && state != OMX_StateInvalid) {
+ if (++iteration > kMaxNumIterations) {
+ ALOGE("component failed to enter Loaded state, aborting.");
+ state = OMX_StateInvalid;
+ break;
+ }
+
+ ALOGV("waiting for Loaded state...");
+ usleep(100000);
+ }
+ CHECK_EQ(err, OMX_ErrorNone);
+
+ // fall through
+ }
+
+ case OMX_StateLoaded:
+ case OMX_StateInvalid:
+ break;
+
+ default:
+ CHECK(!"should not be here, unknown state.");
+ break;
+ }
+
+ ALOGV("calling destroyComponentInstance");
+ OMX_ERRORTYPE err = master->destroyComponentInstance(
+ static_cast<OMX_COMPONENTTYPE *>(mHandle));
+ ALOGV("destroyComponentInstance returned err %d", err);
+
+ mHandle = NULL;
+
+ if (err != OMX_ErrorNone) {
+ ALOGE("FreeHandle FAILED with error 0x%08x.", err);
+ }
+
+ mOwner->invalidateNodeID(mNodeID);
+ mNodeID = NULL;
+
+ ALOGV("OMXNodeInstance going away.");
+ delete this;
+
+ return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::sendCommand(
+ OMX_COMMANDTYPE cmd, OMX_S32 param) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
+ return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::getParameter(
+ OMX_INDEXTYPE index, void *params, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
+
+ return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::setParameter(
+ OMX_INDEXTYPE index, const void *params, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_ERRORTYPE err = OMX_SetParameter(
+ mHandle, index, const_cast<void *>(params));
+
+ return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::getConfig(
+ OMX_INDEXTYPE index, void *params, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
+ return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::setConfig(
+ OMX_INDEXTYPE index, const void *params, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_ERRORTYPE err = OMX_SetConfig(
+ mHandle, index, const_cast<void *>(params));
+
+ return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::getState(OMX_STATETYPE* state) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_ERRORTYPE err = OMX_GetState(mHandle, state);
+
+ return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::enableGraphicBuffers(
+ OMX_U32 portIndex, OMX_BOOL enable) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_INDEXTYPE index;
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(
+ mHandle,
+ const_cast<OMX_STRING>("OMX.google.android.index.enableAndroidNativeBuffers"),
+ &index);
+
+ if (err != OMX_ErrorNone) {
+ ALOGE("OMX_GetExtensionIndex failed");
+
+ return StatusFromOMXError(err);
+ }
+
+ OMX_VERSIONTYPE ver;
+ ver.s.nVersionMajor = 1;
+ ver.s.nVersionMinor = 0;
+ ver.s.nRevision = 0;
+ ver.s.nStep = 0;
+ EnableAndroidNativeBuffersParams params = {
+ sizeof(EnableAndroidNativeBuffersParams), ver, portIndex, enable,
+ };
+
+ err = OMX_SetParameter(mHandle, index, &params);
+
+ if (err != OMX_ErrorNone) {
+ ALOGE("OMX_EnableAndroidNativeBuffers failed with error %d (0x%08x)",
+ err, err);
+
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+status_t OMXNodeInstance::getGraphicBufferUsage(
+ OMX_U32 portIndex, OMX_U32* usage) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_INDEXTYPE index;
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(
+ mHandle,
+ const_cast<OMX_STRING>(
+ "OMX.google.android.index.getAndroidNativeBufferUsage"),
+ &index);
+
+ if (err != OMX_ErrorNone) {
+ ALOGE("OMX_GetExtensionIndex failed");
+
+ return StatusFromOMXError(err);
+ }
+
+ OMX_VERSIONTYPE ver;
+ ver.s.nVersionMajor = 1;
+ ver.s.nVersionMinor = 0;
+ ver.s.nRevision = 0;
+ ver.s.nStep = 0;
+ GetAndroidNativeBufferUsageParams params = {
+ sizeof(GetAndroidNativeBufferUsageParams), ver, portIndex, 0,
+ };
+
+ err = OMX_GetParameter(mHandle, index, &params);
+
+ if (err != OMX_ErrorNone) {
+ ALOGE("OMX_GetAndroidNativeBufferUsage failed with error %d (0x%08x)",
+ err, err);
+ return UNKNOWN_ERROR;
+ }
+
+ *usage = params.nUsage;
+
+ return OK;
+}
+
+status_t OMXNodeInstance::storeMetaDataInBuffers(
+ OMX_U32 portIndex,
+ OMX_BOOL enable) {
+ Mutex::Autolock autolock(mLock);
+
+ OMX_INDEXTYPE index;
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.storeMetaDataInBuffers");
+
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
+ if (err != OMX_ErrorNone) {
+ ALOGE("OMX_GetExtensionIndex %s failed", name);
+ return StatusFromOMXError(err);
+ }
+
+ StoreMetaDataInBuffersParams params;
+ memset(&params, 0, sizeof(params));
+ params.nSize = sizeof(params);
+
+ // Version: 1.0.0.0
+ params.nVersion.s.nVersionMajor = 1;
+
+ params.nPortIndex = portIndex;
+ params.bStoreMetaData = enable;
+ if ((err = OMX_SetParameter(mHandle, index, &params)) != OMX_ErrorNone) {
+ ALOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err);
+ return UNKNOWN_ERROR;
+ }
+ return err;
+}
+
+status_t OMXNodeInstance::useBuffer(
+ OMX_U32 portIndex, const sp<IMemory> &params,
+ OMX::buffer_id *buffer) {
+ Mutex::Autolock autoLock(mLock);
+
+ BufferMeta *buffer_meta = new BufferMeta(params);
+
+ OMX_BUFFERHEADERTYPE *header;
+
+ OMX_ERRORTYPE err = OMX_UseBuffer(
+ mHandle, &header, portIndex, buffer_meta,
+ params->size(), static_cast<OMX_U8 *>(params->pointer()));
+
+ if (err != OMX_ErrorNone) {
+ ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
+
+ delete buffer_meta;
+ buffer_meta = NULL;
+
+ *buffer = 0;
+
+ return UNKNOWN_ERROR;
+ }
+
+ CHECK_EQ(header->pAppPrivate, buffer_meta);
+
+ *buffer = header;
+
+ addActiveBuffer(portIndex, *buffer);
+
+ return OK;
+}
+
+status_t OMXNodeInstance::useGraphicBuffer2_l(
+ OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
+ OMX::buffer_id *buffer) {
+
+ // port definition
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 0;
+ def.nVersion.s.nRevision = 0;
+ def.nVersion.s.nStep = 0;
+ def.nPortIndex = portIndex;
+ OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def);
+ if (err != OMX_ErrorNone)
+ {
+ ALOGE("%s::%d:Error getting OMX_IndexParamPortDefinition", __FUNCTION__, __LINE__);
+ return err;
+ }
+
+ BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
+
+ OMX_BUFFERHEADERTYPE *header = NULL;
+ OMX_U8* bufferHandle = const_cast<OMX_U8*>(
+ reinterpret_cast<const OMX_U8*>(graphicBuffer->handle));
+
+ err = OMX_UseBuffer(
+ mHandle,
+ &header,
+ portIndex,
+ bufferMeta,
+ def.nBufferSize,
+ bufferHandle);
+
+ if (err != OMX_ErrorNone) {
+ ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
+ delete bufferMeta;
+ bufferMeta = NULL;
+ *buffer = 0;
+ return UNKNOWN_ERROR;
+ }
+
+ CHECK_EQ(header->pBuffer, bufferHandle);
+ CHECK_EQ(header->pAppPrivate, bufferMeta);
+
+ *buffer = header;
+
+ addActiveBuffer(portIndex, *buffer);
+
+ return OK;
+}
+
+// XXX: This function is here for backwards compatibility. Once the OMX
+// implementations have been updated this can be removed and useGraphicBuffer2
+// can be renamed to useGraphicBuffer.
+status_t OMXNodeInstance::useGraphicBuffer(
+ OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
+ OMX::buffer_id *buffer) {
+ Mutex::Autolock autoLock(mLock);
+
+ // See if the newer version of the extension is present.
+ OMX_INDEXTYPE index;
+ if (OMX_GetExtensionIndex(
+ mHandle,
+ const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer2"),
+ &index) == OMX_ErrorNone) {
+ return useGraphicBuffer2_l(portIndex, graphicBuffer, buffer);
+ }
+
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(
+ mHandle,
+ const_cast<OMX_STRING>("OMX.google.android.index.useAndroidNativeBuffer"),
+ &index);
+
+ if (err != OMX_ErrorNone) {
+ ALOGE("OMX_GetExtensionIndex failed");
+
+ return StatusFromOMXError(err);
+ }
+
+ BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
+
+ OMX_BUFFERHEADERTYPE *header;
+
+ OMX_VERSIONTYPE ver;
+ ver.s.nVersionMajor = 1;
+ ver.s.nVersionMinor = 0;
+ ver.s.nRevision = 0;
+ ver.s.nStep = 0;
+ UseAndroidNativeBufferParams params = {
+ sizeof(UseAndroidNativeBufferParams), ver, portIndex, bufferMeta,
+ &header, graphicBuffer,
+ };
+
+ err = OMX_SetParameter(mHandle, index, &params);
+
+ if (err != OMX_ErrorNone) {
+ ALOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err,
+ err);
+
+ delete bufferMeta;
+ bufferMeta = NULL;
+
+ *buffer = 0;
+
+ return UNKNOWN_ERROR;
+ }
+
+ CHECK_EQ(header->pAppPrivate, bufferMeta);
+
+ *buffer = header;
+
+ addActiveBuffer(portIndex, *buffer);
+
+ return OK;
+}
+
+status_t OMXNodeInstance::allocateBuffer(
+ OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
+ void **buffer_data) {
+ Mutex::Autolock autoLock(mLock);
+
+ BufferMeta *buffer_meta = new BufferMeta(size);
+
+ OMX_BUFFERHEADERTYPE *header;
+
+ OMX_ERRORTYPE err = OMX_AllocateBuffer(
+ mHandle, &header, portIndex, buffer_meta, size);
+
+ if (err != OMX_ErrorNone) {
+ ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
+
+ delete buffer_meta;
+ buffer_meta = NULL;
+
+ *buffer = 0;
+
+ return UNKNOWN_ERROR;
+ }
+
+ CHECK_EQ(header->pAppPrivate, buffer_meta);
+
+ *buffer = header;
+ *buffer_data = header->pBuffer;
+
+ addActiveBuffer(portIndex, *buffer);
+
+ return OK;
+}
+
+status_t OMXNodeInstance::allocateBufferWithBackup(
+ OMX_U32 portIndex, const sp<IMemory> &params,
+ OMX::buffer_id *buffer) {
+ Mutex::Autolock autoLock(mLock);
+
+ BufferMeta *buffer_meta = new BufferMeta(params, true);
+
+ OMX_BUFFERHEADERTYPE *header;
+
+ OMX_ERRORTYPE err = OMX_AllocateBuffer(
+ mHandle, &header, portIndex, buffer_meta, params->size());
+
+ if (err != OMX_ErrorNone) {
+ ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
+
+ delete buffer_meta;
+ buffer_meta = NULL;
+
+ *buffer = 0;
+
+ return UNKNOWN_ERROR;
+ }
+
+ CHECK_EQ(header->pAppPrivate, buffer_meta);
+
+ *buffer = header;
+
+ addActiveBuffer(portIndex, *buffer);
+
+ return OK;
+}
+
+status_t OMXNodeInstance::freeBuffer(
+ OMX_U32 portIndex, OMX::buffer_id buffer) {
+ Mutex::Autolock autoLock(mLock);
+
+ removeActiveBuffer(portIndex, buffer);
+
+ OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
+ BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
+
+ OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
+
+ delete buffer_meta;
+ buffer_meta = NULL;
+
+ return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::fillBuffer(OMX::buffer_id buffer) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
+ header->nFilledLen = 0;
+ header->nOffset = 0;
+ header->nFlags = 0;
+
+ OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
+
+ return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::emptyBuffer(
+ OMX::buffer_id buffer,
+ OMX_U32 rangeOffset, OMX_U32 rangeLength,
+ OMX_U32 flags, OMX_TICKS timestamp) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer;
+ header->nFilledLen = rangeLength;
+ header->nOffset = rangeOffset;
+ header->nFlags = flags;
+ header->nTimeStamp = timestamp;
+
+ BufferMeta *buffer_meta =
+ static_cast<BufferMeta *>(header->pAppPrivate);
+ buffer_meta->CopyToOMX(header);
+
+ OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
+
+ return StatusFromOMXError(err);
+}
+
+status_t OMXNodeInstance::getExtensionIndex(
+ const char *parameterName, OMX_INDEXTYPE *index) {
+ Mutex::Autolock autoLock(mLock);
+
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(
+ mHandle, const_cast<char *>(parameterName), index);
+
+ return StatusFromOMXError(err);
+}
+
+void OMXNodeInstance::onMessage(const omx_message &msg) {
+ if (msg.type == omx_message::FILL_BUFFER_DONE) {
+ OMX_BUFFERHEADERTYPE *buffer =
+ static_cast<OMX_BUFFERHEADERTYPE *>(
+ msg.u.extended_buffer_data.buffer);
+
+ BufferMeta *buffer_meta =
+ static_cast<BufferMeta *>(buffer->pAppPrivate);
+
+ buffer_meta->CopyFromOMX(buffer);
+ }
+
+ mObserver->onMessage(msg);
+}
+
+void OMXNodeInstance::onObserverDied(OMXMaster *master) {
+ ALOGE("!!! Observer died. Quickly, do something, ... anything...");
+
+ // Try to force shutdown of the node and hope for the best.
+ freeNode(master);
+}
+
+void OMXNodeInstance::onGetHandleFailed() {
+ delete this;
+}
+
+// static
+OMX_ERRORTYPE OMXNodeInstance::OnEvent(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_EVENTTYPE eEvent,
+ OMX_IN OMX_U32 nData1,
+ OMX_IN OMX_U32 nData2,
+ OMX_IN OMX_PTR pEventData) {
+ OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
+ if (instance->mDying) {
+ return OMX_ErrorNone;
+ }
+ return instance->owner()->OnEvent(
+ instance->nodeID(), eEvent, nData1, nData2, pEventData);
+}
+
+// static
+OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
+ OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
+ if (instance->mDying) {
+ return OMX_ErrorNone;
+ }
+ return instance->owner()->OnEmptyBufferDone(instance->nodeID(), pBuffer);
+}
+
+// static
+OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
+ OMX_IN OMX_HANDLETYPE hComponent,
+ OMX_IN OMX_PTR pAppData,
+ OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
+ OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
+ if (instance->mDying) {
+ return OMX_ErrorNone;
+ }
+ return instance->owner()->OnFillBufferDone(instance->nodeID(), pBuffer);
+}
+
+void OMXNodeInstance::addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id) {
+ ActiveBuffer active;
+ active.mPortIndex = portIndex;
+ active.mID = id;
+ mActiveBuffers.push(active);
+}
+
+void OMXNodeInstance::removeActiveBuffer(
+ OMX_U32 portIndex, OMX::buffer_id id) {
+ bool found = false;
+ for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
+ if (mActiveBuffers[i].mPortIndex == portIndex
+ && mActiveBuffers[i].mID == id) {
+ found = true;
+ mActiveBuffers.removeItemsAt(i);
+ break;
+ }
+ }
+
+ if (!found) {
+ ALOGW("Attempt to remove an active buffer we know nothing about...");
+ }
+}
+
+void OMXNodeInstance::freeActiveBuffers() {
+ // Make sure to count down here, as freeBuffer will in turn remove
+ // the active buffer from the vector...
+ for (size_t i = mActiveBuffers.size(); i--;) {
+ freeBuffer(mActiveBuffers[i].mPortIndex, mActiveBuffers[i].mID);
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
new file mode 100644
index 0000000..c79e01f
--- /dev/null
+++ b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
@@ -0,0 +1,645 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SimpleSoftOMXComponent"
+#include <utils/Log.h>
+
+#include "include/SimpleSoftOMXComponent.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+namespace android {
+
+SimpleSoftOMXComponent::SimpleSoftOMXComponent(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : SoftOMXComponent(name, callbacks, appData, component),
+ mLooper(new ALooper),
+ mHandler(new AHandlerReflector<SimpleSoftOMXComponent>(this)),
+ mState(OMX_StateLoaded),
+ mTargetState(OMX_StateLoaded) {
+ mLooper->setName(name);
+ mLooper->registerHandler(mHandler);
+
+ mLooper->start(
+ false, // runOnCallingThread
+ false, // canCallJava
+ ANDROID_PRIORITY_FOREGROUND);
+}
+
+void SimpleSoftOMXComponent::prepareForDestruction() {
+ // The looper's queue may still contain messages referencing this
+ // object. Make sure those are flushed before returning so that
+ // a subsequent dlunload() does not pull out the rug from under us.
+
+ mLooper->unregisterHandler(mHandler->id());
+ mLooper->stop();
+}
+
+OMX_ERRORTYPE SimpleSoftOMXComponent::sendCommand(
+ OMX_COMMANDTYPE cmd, OMX_U32 param, OMX_PTR data) {
+ CHECK(data == NULL);
+
+ sp<AMessage> msg = new AMessage(kWhatSendCommand, mHandler->id());
+ msg->setInt32("cmd", cmd);
+ msg->setInt32("param", param);
+ msg->post();
+
+ return OMX_ErrorNone;
+}
+
+bool SimpleSoftOMXComponent::isSetParameterAllowed(
+ OMX_INDEXTYPE index, const OMX_PTR params) const {
+ if (mState == OMX_StateLoaded) {
+ return true;
+ }
+
+ OMX_U32 portIndex;
+
+ switch (index) {
+ case OMX_IndexParamPortDefinition:
+ {
+ portIndex = ((OMX_PARAM_PORTDEFINITIONTYPE *)params)->nPortIndex;
+ break;
+ }
+
+ case OMX_IndexParamAudioPcm:
+ {
+ portIndex = ((OMX_AUDIO_PARAM_PCMMODETYPE *)params)->nPortIndex;
+ break;
+ }
+
+ case OMX_IndexParamAudioAac:
+ {
+ portIndex = ((OMX_AUDIO_PARAM_AACPROFILETYPE *)params)->nPortIndex;
+ break;
+ }
+
+ default:
+ return false;
+ }
+
+ CHECK(portIndex < mPorts.size());
+
+ return !mPorts.itemAt(portIndex).mDef.bEnabled;
+}
+
+OMX_ERRORTYPE SimpleSoftOMXComponent::getParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ Mutex::Autolock autoLock(mLock);
+ return internalGetParameter(index, params);
+}
+
+OMX_ERRORTYPE SimpleSoftOMXComponent::setParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ Mutex::Autolock autoLock(mLock);
+
+ CHECK(isSetParameterAllowed(index, params));
+
+ return internalSetParameter(index, params);
+}
+
+OMX_ERRORTYPE SimpleSoftOMXComponent::internalGetParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE *defParams =
+ (OMX_PARAM_PORTDEFINITIONTYPE *)params;
+
+ if (defParams->nPortIndex >= mPorts.size()
+ || defParams->nSize
+ != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
+ return OMX_ErrorUndefined;
+ }
+
+ const PortInfo *port =
+ &mPorts.itemAt(defParams->nPortIndex);
+
+ memcpy(defParams, &port->mDef, sizeof(port->mDef));
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return OMX_ErrorUnsupportedIndex;
+ }
+}
+
+OMX_ERRORTYPE SimpleSoftOMXComponent::internalSetParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ switch (index) {
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE *defParams =
+ (OMX_PARAM_PORTDEFINITIONTYPE *)params;
+
+ if (defParams->nPortIndex >= mPorts.size()
+ || defParams->nSize
+ != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
+ return OMX_ErrorUndefined;
+ }
+
+ PortInfo *port =
+ &mPorts.editItemAt(defParams->nPortIndex);
+
+ if (defParams->nBufferSize != port->mDef.nBufferSize) {
+ CHECK_GE(defParams->nBufferSize, port->mDef.nBufferSize);
+ port->mDef.nBufferSize = defParams->nBufferSize;
+ }
+
+ if (defParams->nBufferCountActual
+ != port->mDef.nBufferCountActual) {
+ CHECK_GE(defParams->nBufferCountActual,
+ port->mDef.nBufferCountMin);
+
+ port->mDef.nBufferCountActual = defParams->nBufferCountActual;
+ }
+
+ return OMX_ErrorNone;
+ }
+
+ default:
+ return OMX_ErrorUnsupportedIndex;
+ }
+}
+
+OMX_ERRORTYPE SimpleSoftOMXComponent::useBuffer(
+ OMX_BUFFERHEADERTYPE **header,
+ OMX_U32 portIndex,
+ OMX_PTR appPrivate,
+ OMX_U32 size,
+ OMX_U8 *ptr) {
+ Mutex::Autolock autoLock(mLock);
+ CHECK_LT(portIndex, mPorts.size());
+
+ *header = new OMX_BUFFERHEADERTYPE;
+ (*header)->nSize = sizeof(OMX_BUFFERHEADERTYPE);
+ (*header)->nVersion.s.nVersionMajor = 1;
+ (*header)->nVersion.s.nVersionMinor = 0;
+ (*header)->nVersion.s.nRevision = 0;
+ (*header)->nVersion.s.nStep = 0;
+ (*header)->pBuffer = ptr;
+ (*header)->nAllocLen = size;
+ (*header)->nFilledLen = 0;
+ (*header)->nOffset = 0;
+ (*header)->pAppPrivate = appPrivate;
+ (*header)->pPlatformPrivate = NULL;
+ (*header)->pInputPortPrivate = NULL;
+ (*header)->pOutputPortPrivate = NULL;
+ (*header)->hMarkTargetComponent = NULL;
+ (*header)->pMarkData = NULL;
+ (*header)->nTickCount = 0;
+ (*header)->nTimeStamp = 0;
+ (*header)->nFlags = 0;
+ (*header)->nOutputPortIndex = portIndex;
+ (*header)->nInputPortIndex = portIndex;
+
+ PortInfo *port = &mPorts.editItemAt(portIndex);
+
+ CHECK(mState == OMX_StateLoaded || port->mDef.bEnabled == OMX_FALSE);
+
+ CHECK_LT(port->mBuffers.size(), port->mDef.nBufferCountActual);
+
+ port->mBuffers.push();
+
+ BufferInfo *buffer =
+ &port->mBuffers.editItemAt(port->mBuffers.size() - 1);
+
+ buffer->mHeader = *header;
+ buffer->mOwnedByUs = false;
+
+ if (port->mBuffers.size() == port->mDef.nBufferCountActual) {
+ port->mDef.bPopulated = OMX_TRUE;
+ checkTransitions();
+ }
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SimpleSoftOMXComponent::allocateBuffer(
+ OMX_BUFFERHEADERTYPE **header,
+ OMX_U32 portIndex,
+ OMX_PTR appPrivate,
+ OMX_U32 size) {
+ OMX_U8 *ptr = new OMX_U8[size];
+
+ OMX_ERRORTYPE err =
+ useBuffer(header, portIndex, appPrivate, size, ptr);
+
+ if (err != OMX_ErrorNone) {
+ delete[] ptr;
+ ptr = NULL;
+
+ return err;
+ }
+
+ CHECK((*header)->pPlatformPrivate == NULL);
+ (*header)->pPlatformPrivate = ptr;
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SimpleSoftOMXComponent::freeBuffer(
+ OMX_U32 portIndex,
+ OMX_BUFFERHEADERTYPE *header) {
+ Mutex::Autolock autoLock(mLock);
+
+ CHECK_LT(portIndex, mPorts.size());
+
+ PortInfo *port = &mPorts.editItemAt(portIndex);
+
+#if 0 // XXX
+ CHECK((mState == OMX_StateIdle && mTargetState == OMX_StateLoaded)
+ || port->mDef.bEnabled == OMX_FALSE);
+#endif
+
+ bool found = false;
+ for (size_t i = 0; i < port->mBuffers.size(); ++i) {
+ BufferInfo *buffer = &port->mBuffers.editItemAt(i);
+
+ if (buffer->mHeader == header) {
+ CHECK(!buffer->mOwnedByUs);
+
+ if (header->pPlatformPrivate != NULL) {
+ // This buffer's data was allocated by us.
+ CHECK(header->pPlatformPrivate == header->pBuffer);
+
+ delete[] header->pBuffer;
+ header->pBuffer = NULL;
+ }
+
+ delete header;
+ header = NULL;
+
+ port->mBuffers.removeAt(i);
+ port->mDef.bPopulated = OMX_FALSE;
+
+ checkTransitions();
+
+ found = true;
+ break;
+ }
+ }
+
+ CHECK(found);
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SimpleSoftOMXComponent::emptyThisBuffer(
+ OMX_BUFFERHEADERTYPE *buffer) {
+ sp<AMessage> msg = new AMessage(kWhatEmptyThisBuffer, mHandler->id());
+ msg->setPointer("header", buffer);
+ msg->post();
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SimpleSoftOMXComponent::fillThisBuffer(
+ OMX_BUFFERHEADERTYPE *buffer) {
+ sp<AMessage> msg = new AMessage(kWhatFillThisBuffer, mHandler->id());
+ msg->setPointer("header", buffer);
+ msg->post();
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SimpleSoftOMXComponent::getState(OMX_STATETYPE *state) {
+ Mutex::Autolock autoLock(mLock);
+
+ *state = mState;
+
+ return OMX_ErrorNone;
+}
+
+void SimpleSoftOMXComponent::onMessageReceived(const sp<AMessage> &msg) {
+ Mutex::Autolock autoLock(mLock);
+ uint32_t msgType = msg->what();
+ ALOGV("msgType = %d", msgType);
+ switch (msgType) {
+ case kWhatSendCommand:
+ {
+ int32_t cmd, param;
+ CHECK(msg->findInt32("cmd", &cmd));
+ CHECK(msg->findInt32("param", &param));
+
+ onSendCommand((OMX_COMMANDTYPE)cmd, (OMX_U32)param);
+ break;
+ }
+
+ case kWhatEmptyThisBuffer:
+ case kWhatFillThisBuffer:
+ {
+ OMX_BUFFERHEADERTYPE *header;
+ CHECK(msg->findPointer("header", (void **)&header));
+
+ CHECK(mState == OMX_StateExecuting && mTargetState == mState);
+
+ bool found = false;
+ size_t portIndex = (kWhatEmptyThisBuffer == msgType)?
+ header->nInputPortIndex: header->nOutputPortIndex;
+ PortInfo *port = &mPorts.editItemAt(portIndex);
+
+ for (size_t j = 0; j < port->mBuffers.size(); ++j) {
+ BufferInfo *buffer = &port->mBuffers.editItemAt(j);
+
+ if (buffer->mHeader == header) {
+ CHECK(!buffer->mOwnedByUs);
+
+ buffer->mOwnedByUs = true;
+
+ CHECK((msgType == kWhatEmptyThisBuffer
+ && port->mDef.eDir == OMX_DirInput)
+ || (port->mDef.eDir == OMX_DirOutput));
+
+ port->mQueue.push_back(buffer);
+ onQueueFilled(portIndex);
+
+ found = true;
+ break;
+ }
+ }
+
+ CHECK(found);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+void SimpleSoftOMXComponent::onSendCommand(
+ OMX_COMMANDTYPE cmd, OMX_U32 param) {
+ switch (cmd) {
+ case OMX_CommandStateSet:
+ {
+ onChangeState((OMX_STATETYPE)param);
+ break;
+ }
+
+ case OMX_CommandPortEnable:
+ case OMX_CommandPortDisable:
+ {
+ onPortEnable(param, cmd == OMX_CommandPortEnable);
+ break;
+ }
+
+ case OMX_CommandFlush:
+ {
+ onPortFlush(param, true /* sendFlushComplete */);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+void SimpleSoftOMXComponent::onChangeState(OMX_STATETYPE state) {
+ // We shouldn't be in a state transition already.
+ CHECK_EQ((int)mState, (int)mTargetState);
+
+ switch (mState) {
+ case OMX_StateLoaded:
+ CHECK_EQ((int)state, (int)OMX_StateIdle);
+ break;
+ case OMX_StateIdle:
+ CHECK(state == OMX_StateLoaded || state == OMX_StateExecuting);
+ break;
+ case OMX_StateExecuting:
+ {
+ CHECK_EQ((int)state, (int)OMX_StateIdle);
+
+ for (size_t i = 0; i < mPorts.size(); ++i) {
+ onPortFlush(i, false /* sendFlushComplete */);
+ }
+
+ mState = OMX_StateIdle;
+ notify(OMX_EventCmdComplete, OMX_CommandStateSet, state, NULL);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+
+ mTargetState = state;
+
+ checkTransitions();
+}
+
+void SimpleSoftOMXComponent::onPortEnable(OMX_U32 portIndex, bool enable) {
+ CHECK_LT(portIndex, mPorts.size());
+
+ PortInfo *port = &mPorts.editItemAt(portIndex);
+ CHECK_EQ((int)port->mTransition, (int)PortInfo::NONE);
+ CHECK(port->mDef.bEnabled == !enable);
+
+ if (!enable) {
+ port->mDef.bEnabled = OMX_FALSE;
+ port->mTransition = PortInfo::DISABLING;
+
+ for (size_t i = 0; i < port->mBuffers.size(); ++i) {
+ BufferInfo *buffer = &port->mBuffers.editItemAt(i);
+
+ if (buffer->mOwnedByUs) {
+ buffer->mOwnedByUs = false;
+
+ if (port->mDef.eDir == OMX_DirInput) {
+ notifyEmptyBufferDone(buffer->mHeader);
+ } else {
+ CHECK_EQ(port->mDef.eDir, OMX_DirOutput);
+ notifyFillBufferDone(buffer->mHeader);
+ }
+ }
+ }
+
+ port->mQueue.clear();
+ } else {
+ port->mTransition = PortInfo::ENABLING;
+ }
+
+ checkTransitions();
+}
+
+void SimpleSoftOMXComponent::onPortFlush(
+ OMX_U32 portIndex, bool sendFlushComplete) {
+ if (portIndex == OMX_ALL) {
+ for (size_t i = 0; i < mPorts.size(); ++i) {
+ onPortFlush(i, sendFlushComplete);
+ }
+
+ if (sendFlushComplete) {
+ notify(OMX_EventCmdComplete, OMX_CommandFlush, OMX_ALL, NULL);
+ }
+
+ return;
+ }
+
+ CHECK_LT(portIndex, mPorts.size());
+
+ PortInfo *port = &mPorts.editItemAt(portIndex);
+ CHECK_EQ((int)port->mTransition, (int)PortInfo::NONE);
+
+ for (size_t i = 0; i < port->mBuffers.size(); ++i) {
+ BufferInfo *buffer = &port->mBuffers.editItemAt(i);
+
+ if (!buffer->mOwnedByUs) {
+ continue;
+ }
+
+ buffer->mHeader->nFilledLen = 0;
+ buffer->mHeader->nOffset = 0;
+ buffer->mHeader->nFlags = 0;
+
+ buffer->mOwnedByUs = false;
+
+ if (port->mDef.eDir == OMX_DirInput) {
+ notifyEmptyBufferDone(buffer->mHeader);
+ } else {
+ CHECK_EQ(port->mDef.eDir, OMX_DirOutput);
+
+ notifyFillBufferDone(buffer->mHeader);
+ }
+ }
+
+ port->mQueue.clear();
+
+ if (sendFlushComplete) {
+ notify(OMX_EventCmdComplete, OMX_CommandFlush, portIndex, NULL);
+
+ onPortFlushCompleted(portIndex);
+ }
+}
+
+void SimpleSoftOMXComponent::checkTransitions() {
+ if (mState != mTargetState) {
+ bool transitionComplete = true;
+
+ if (mState == OMX_StateLoaded) {
+ CHECK_EQ((int)mTargetState, (int)OMX_StateIdle);
+
+ for (size_t i = 0; i < mPorts.size(); ++i) {
+ const PortInfo &port = mPorts.itemAt(i);
+ if (port.mDef.bEnabled == OMX_FALSE) {
+ continue;
+ }
+
+ if (port.mDef.bPopulated == OMX_FALSE) {
+ transitionComplete = false;
+ break;
+ }
+ }
+ } else if (mTargetState == OMX_StateLoaded) {
+ CHECK_EQ((int)mState, (int)OMX_StateIdle);
+
+ for (size_t i = 0; i < mPorts.size(); ++i) {
+ const PortInfo &port = mPorts.itemAt(i);
+ if (port.mDef.bEnabled == OMX_FALSE) {
+ continue;
+ }
+
+ size_t n = port.mBuffers.size();
+
+ if (n > 0) {
+ CHECK_LE(n, port.mDef.nBufferCountActual);
+
+ if (n == port.mDef.nBufferCountActual) {
+ CHECK_EQ((int)port.mDef.bPopulated, (int)OMX_TRUE);
+ } else {
+ CHECK_EQ((int)port.mDef.bPopulated, (int)OMX_FALSE);
+ }
+
+ transitionComplete = false;
+ break;
+ }
+ }
+ }
+
+ if (transitionComplete) {
+ mState = mTargetState;
+
+ notify(OMX_EventCmdComplete, OMX_CommandStateSet, mState, NULL);
+ }
+ }
+
+ for (size_t i = 0; i < mPorts.size(); ++i) {
+ PortInfo *port = &mPorts.editItemAt(i);
+
+ if (port->mTransition == PortInfo::DISABLING) {
+ if (port->mBuffers.empty()) {
+ ALOGV("Port %d now disabled.", i);
+
+ port->mTransition = PortInfo::NONE;
+ notify(OMX_EventCmdComplete, OMX_CommandPortDisable, i, NULL);
+
+ onPortEnableCompleted(i, false /* enabled */);
+ }
+ } else if (port->mTransition == PortInfo::ENABLING) {
+ if (port->mDef.bPopulated == OMX_TRUE) {
+ ALOGV("Port %d now enabled.", i);
+
+ port->mTransition = PortInfo::NONE;
+ port->mDef.bEnabled = OMX_TRUE;
+ notify(OMX_EventCmdComplete, OMX_CommandPortEnable, i, NULL);
+
+ onPortEnableCompleted(i, true /* enabled */);
+ }
+ }
+ }
+}
+
+void SimpleSoftOMXComponent::addPort(const OMX_PARAM_PORTDEFINITIONTYPE &def) {
+ CHECK_EQ(def.nPortIndex, mPorts.size());
+
+ mPorts.push();
+ PortInfo *info = &mPorts.editItemAt(mPorts.size() - 1);
+ info->mDef = def;
+ info->mTransition = PortInfo::NONE;
+}
+
+void SimpleSoftOMXComponent::onQueueFilled(OMX_U32 portIndex) {
+}
+
+void SimpleSoftOMXComponent::onPortFlushCompleted(OMX_U32 portIndex) {
+}
+
+void SimpleSoftOMXComponent::onPortEnableCompleted(
+ OMX_U32 portIndex, bool enabled) {
+}
+
+List<SimpleSoftOMXComponent::BufferInfo *> &
+SimpleSoftOMXComponent::getPortQueue(OMX_U32 portIndex) {
+ CHECK_LT(portIndex, mPorts.size());
+ return mPorts.editItemAt(portIndex).mQueue;
+}
+
+SimpleSoftOMXComponent::PortInfo *SimpleSoftOMXComponent::editPortInfo(
+ OMX_U32 portIndex) {
+ CHECK_LT(portIndex, mPorts.size());
+ return &mPorts.editItemAt(portIndex);
+}
+
+} // namespace android
diff --git a/media/libstagefright/omx/SoftOMXComponent.cpp b/media/libstagefright/omx/SoftOMXComponent.cpp
new file mode 100644
index 0000000..b1c34dc
--- /dev/null
+++ b/media/libstagefright/omx/SoftOMXComponent.cpp
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SoftOMXComponent"
+#include <utils/Log.h>
+
+#include "include/SoftOMXComponent.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+SoftOMXComponent::SoftOMXComponent(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component)
+ : mName(name),
+ mCallbacks(callbacks),
+ mComponent(new OMX_COMPONENTTYPE),
+ mLibHandle(NULL) {
+ mComponent->nSize = sizeof(*mComponent);
+ mComponent->nVersion.s.nVersionMajor = 1;
+ mComponent->nVersion.s.nVersionMinor = 0;
+ mComponent->nVersion.s.nRevision = 0;
+ mComponent->nVersion.s.nStep = 0;
+ mComponent->pComponentPrivate = this;
+ mComponent->pApplicationPrivate = appData;
+
+ mComponent->GetComponentVersion = NULL;
+ mComponent->SendCommand = SendCommandWrapper;
+ mComponent->GetParameter = GetParameterWrapper;
+ mComponent->SetParameter = SetParameterWrapper;
+ mComponent->GetConfig = GetConfigWrapper;
+ mComponent->SetConfig = SetConfigWrapper;
+ mComponent->GetExtensionIndex = GetExtensionIndexWrapper;
+ mComponent->GetState = GetStateWrapper;
+ mComponent->ComponentTunnelRequest = NULL;
+ mComponent->UseBuffer = UseBufferWrapper;
+ mComponent->AllocateBuffer = AllocateBufferWrapper;
+ mComponent->FreeBuffer = FreeBufferWrapper;
+ mComponent->EmptyThisBuffer = EmptyThisBufferWrapper;
+ mComponent->FillThisBuffer = FillThisBufferWrapper;
+ mComponent->SetCallbacks = NULL;
+ mComponent->ComponentDeInit = NULL;
+ mComponent->UseEGLImage = NULL;
+ mComponent->ComponentRoleEnum = NULL;
+
+ *component = mComponent;
+}
+
+SoftOMXComponent::~SoftOMXComponent() {
+ delete mComponent;
+ mComponent = NULL;
+}
+
+void SoftOMXComponent::setLibHandle(void *libHandle) {
+ CHECK(libHandle != NULL);
+ mLibHandle = libHandle;
+}
+
+void *SoftOMXComponent::libHandle() const {
+ return mLibHandle;
+}
+
+OMX_ERRORTYPE SoftOMXComponent::initCheck() const {
+ return OMX_ErrorNone;
+}
+
+const char *SoftOMXComponent::name() const {
+ return mName.c_str();
+}
+
+void SoftOMXComponent::notify(
+ OMX_EVENTTYPE event,
+ OMX_U32 data1, OMX_U32 data2, OMX_PTR data) {
+ (*mCallbacks->EventHandler)(
+ mComponent,
+ mComponent->pApplicationPrivate,
+ event,
+ data1,
+ data2,
+ data);
+}
+
+void SoftOMXComponent::notifyEmptyBufferDone(OMX_BUFFERHEADERTYPE *header) {
+ (*mCallbacks->EmptyBufferDone)(
+ mComponent, mComponent->pApplicationPrivate, header);
+}
+
+void SoftOMXComponent::notifyFillBufferDone(OMX_BUFFERHEADERTYPE *header) {
+ (*mCallbacks->FillBufferDone)(
+ mComponent, mComponent->pApplicationPrivate, header);
+}
+
+// static
+OMX_ERRORTYPE SoftOMXComponent::SendCommandWrapper(
+ OMX_HANDLETYPE component,
+ OMX_COMMANDTYPE cmd,
+ OMX_U32 param,
+ OMX_PTR data) {
+ SoftOMXComponent *me =
+ (SoftOMXComponent *)
+ ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
+
+ return me->sendCommand(cmd, param, data);
+}
+
+// static
+OMX_ERRORTYPE SoftOMXComponent::GetParameterWrapper(
+ OMX_HANDLETYPE component,
+ OMX_INDEXTYPE index,
+ OMX_PTR params) {
+ SoftOMXComponent *me =
+ (SoftOMXComponent *)
+ ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
+
+ return me->getParameter(index, params);
+}
+
+// static
+OMX_ERRORTYPE SoftOMXComponent::SetParameterWrapper(
+ OMX_HANDLETYPE component,
+ OMX_INDEXTYPE index,
+ OMX_PTR params) {
+ SoftOMXComponent *me =
+ (SoftOMXComponent *)
+ ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
+
+ return me->setParameter(index, params);
+}
+
+// static
+OMX_ERRORTYPE SoftOMXComponent::GetConfigWrapper(
+ OMX_HANDLETYPE component,
+ OMX_INDEXTYPE index,
+ OMX_PTR params) {
+ SoftOMXComponent *me =
+ (SoftOMXComponent *)
+ ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
+
+ return me->getConfig(index, params);
+}
+
+// static
+OMX_ERRORTYPE SoftOMXComponent::SetConfigWrapper(
+ OMX_HANDLETYPE component,
+ OMX_INDEXTYPE index,
+ OMX_PTR params) {
+ SoftOMXComponent *me =
+ (SoftOMXComponent *)
+ ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
+
+ return me->setConfig(index, params);
+}
+
+// static
+OMX_ERRORTYPE SoftOMXComponent::GetExtensionIndexWrapper(
+ OMX_HANDLETYPE component,
+ OMX_STRING name,
+ OMX_INDEXTYPE *index) {
+ SoftOMXComponent *me =
+ (SoftOMXComponent *)
+ ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
+
+ return me->getExtensionIndex(name, index);
+}
+
+// static
+OMX_ERRORTYPE SoftOMXComponent::UseBufferWrapper(
+ OMX_HANDLETYPE component,
+ OMX_BUFFERHEADERTYPE **buffer,
+ OMX_U32 portIndex,
+ OMX_PTR appPrivate,
+ OMX_U32 size,
+ OMX_U8 *ptr) {
+ SoftOMXComponent *me =
+ (SoftOMXComponent *)
+ ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
+
+ return me->useBuffer(buffer, portIndex, appPrivate, size, ptr);
+}
+
+// static
+OMX_ERRORTYPE SoftOMXComponent::AllocateBufferWrapper(
+ OMX_HANDLETYPE component,
+ OMX_BUFFERHEADERTYPE **buffer,
+ OMX_U32 portIndex,
+ OMX_PTR appPrivate,
+ OMX_U32 size) {
+ SoftOMXComponent *me =
+ (SoftOMXComponent *)
+ ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
+
+ return me->allocateBuffer(buffer, portIndex, appPrivate, size);
+}
+
+// static
+OMX_ERRORTYPE SoftOMXComponent::FreeBufferWrapper(
+ OMX_HANDLETYPE component,
+ OMX_U32 portIndex,
+ OMX_BUFFERHEADERTYPE *buffer) {
+ SoftOMXComponent *me =
+ (SoftOMXComponent *)
+ ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
+
+ return me->freeBuffer(portIndex, buffer);
+}
+
+// static
+OMX_ERRORTYPE SoftOMXComponent::EmptyThisBufferWrapper(
+ OMX_HANDLETYPE component,
+ OMX_BUFFERHEADERTYPE *buffer) {
+ SoftOMXComponent *me =
+ (SoftOMXComponent *)
+ ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
+
+ return me->emptyThisBuffer(buffer);
+}
+
+// static
+OMX_ERRORTYPE SoftOMXComponent::FillThisBufferWrapper(
+ OMX_HANDLETYPE component,
+ OMX_BUFFERHEADERTYPE *buffer) {
+ SoftOMXComponent *me =
+ (SoftOMXComponent *)
+ ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
+
+ return me->fillThisBuffer(buffer);
+}
+
+// static
+OMX_ERRORTYPE SoftOMXComponent::GetStateWrapper(
+ OMX_HANDLETYPE component,
+ OMX_STATETYPE *state) {
+ SoftOMXComponent *me =
+ (SoftOMXComponent *)
+ ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
+
+ return me->getState(state);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+OMX_ERRORTYPE SoftOMXComponent::sendCommand(
+ OMX_COMMANDTYPE cmd, OMX_U32 param, OMX_PTR data) {
+ return OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE SoftOMXComponent::getParameter(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ return OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE SoftOMXComponent::setParameter(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ return OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE SoftOMXComponent::getConfig(
+ OMX_INDEXTYPE index, OMX_PTR params) {
+ return OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE SoftOMXComponent::setConfig(
+ OMX_INDEXTYPE index, const OMX_PTR params) {
+ return OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE SoftOMXComponent::getExtensionIndex(
+ const char *name, OMX_INDEXTYPE *index) {
+ return OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE SoftOMXComponent::useBuffer(
+ OMX_BUFFERHEADERTYPE **buffer,
+ OMX_U32 portIndex,
+ OMX_PTR appPrivate,
+ OMX_U32 size,
+ OMX_U8 *ptr) {
+ return OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE SoftOMXComponent::allocateBuffer(
+ OMX_BUFFERHEADERTYPE **buffer,
+ OMX_U32 portIndex,
+ OMX_PTR appPrivate,
+ OMX_U32 size) {
+ return OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE SoftOMXComponent::freeBuffer(
+ OMX_U32 portIndex,
+ OMX_BUFFERHEADERTYPE *buffer) {
+ return OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE SoftOMXComponent::emptyThisBuffer(
+ OMX_BUFFERHEADERTYPE *buffer) {
+ return OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE SoftOMXComponent::fillThisBuffer(
+ OMX_BUFFERHEADERTYPE *buffer) {
+ return OMX_ErrorUndefined;
+}
+
+OMX_ERRORTYPE SoftOMXComponent::getState(OMX_STATETYPE *state) {
+ return OMX_ErrorUndefined;
+}
+
+} // namespace android
diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp
new file mode 100644
index 0000000..99ffe7d
--- /dev/null
+++ b/media/libstagefright/omx/SoftOMXPlugin.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SoftOMXPlugin"
+#include <utils/Log.h>
+
+#include "SoftOMXPlugin.h"
+#include "include/SoftOMXComponent.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+
+#include <dlfcn.h>
+
+namespace android {
+
+static const struct {
+ const char *mName;
+ const char *mLibNameSuffix;
+ const char *mRole;
+
+} kComponents[] = {
+ { "OMX.google.aac.decoder", "aacdec", "audio_decoder.aac" },
+ { "OMX.google.aac.encoder", "aacenc", "audio_encoder.aac" },
+ { "OMX.google.amrnb.decoder", "amrdec", "audio_decoder.amrnb" },
+ { "OMX.google.amrnb.encoder", "amrnbenc", "audio_encoder.amrnb" },
+ { "OMX.google.amrwb.decoder", "amrdec", "audio_decoder.amrwb" },
+ { "OMX.google.amrwb.encoder", "amrwbenc", "audio_encoder.amrwb" },
+ { "OMX.google.h264.decoder", "h264dec", "video_decoder.avc" },
+ { "OMX.google.g711.alaw.decoder", "g711dec", "audio_decoder.g711alaw" },
+ { "OMX.google.g711.mlaw.decoder", "g711dec", "audio_decoder.g711mlaw" },
+ { "OMX.google.h263.decoder", "mpeg4dec", "video_decoder.h263" },
+ { "OMX.google.mpeg4.decoder", "mpeg4dec", "video_decoder.mpeg4" },
+ { "OMX.google.mp3.decoder", "mp3dec", "audio_decoder.mp3" },
+ { "OMX.google.vorbis.decoder", "vorbisdec", "audio_decoder.vorbis" },
+ { "OMX.google.vpx.decoder", "vpxdec", "video_decoder.vpx" },
+};
+
+static const size_t kNumComponents =
+ sizeof(kComponents) / sizeof(kComponents[0]);
+
+SoftOMXPlugin::SoftOMXPlugin() {
+}
+
+OMX_ERRORTYPE SoftOMXPlugin::makeComponentInstance(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component) {
+ ALOGV("makeComponentInstance '%s'", name);
+
+ for (size_t i = 0; i < kNumComponents; ++i) {
+ if (strcmp(name, kComponents[i].mName)) {
+ continue;
+ }
+
+ AString libName = "libstagefright_soft_";
+ libName.append(kComponents[i].mLibNameSuffix);
+ libName.append(".so");
+
+ void *libHandle = dlopen(libName.c_str(), RTLD_NOW);
+
+ if (libHandle == NULL) {
+ ALOGE("unable to dlopen %s", libName.c_str());
+
+ return OMX_ErrorComponentNotFound;
+ }
+
+ typedef SoftOMXComponent *(*CreateSoftOMXComponentFunc)(
+ const char *, const OMX_CALLBACKTYPE *,
+ OMX_PTR, OMX_COMPONENTTYPE **);
+
+ CreateSoftOMXComponentFunc createSoftOMXComponent =
+ (CreateSoftOMXComponentFunc)dlsym(
+ libHandle,
+ "_Z22createSoftOMXComponentPKcPK16OMX_CALLBACKTYPE"
+ "PvPP17OMX_COMPONENTTYPE");
+
+ if (createSoftOMXComponent == NULL) {
+ dlclose(libHandle);
+ libHandle = NULL;
+
+ return OMX_ErrorComponentNotFound;
+ }
+
+ sp<SoftOMXComponent> codec =
+ (*createSoftOMXComponent)(name, callbacks, appData, component);
+
+ if (codec == NULL) {
+ dlclose(libHandle);
+ libHandle = NULL;
+
+ return OMX_ErrorInsufficientResources;
+ }
+
+ OMX_ERRORTYPE err = codec->initCheck();
+ if (err != OMX_ErrorNone) {
+ dlclose(libHandle);
+ libHandle = NULL;
+
+ return err;
+ }
+
+ codec->incStrong(this);
+ codec->setLibHandle(libHandle);
+
+ return OMX_ErrorNone;
+ }
+
+ return OMX_ErrorInvalidComponentName;
+}
+
+OMX_ERRORTYPE SoftOMXPlugin::destroyComponentInstance(
+ OMX_COMPONENTTYPE *component) {
+ SoftOMXComponent *me =
+ (SoftOMXComponent *)
+ ((OMX_COMPONENTTYPE *)component)->pComponentPrivate;
+
+ me->prepareForDestruction();
+
+ void *libHandle = me->libHandle();
+
+ CHECK_EQ(me->getStrongCount(), 1);
+ me->decStrong(this);
+ me = NULL;
+
+ dlclose(libHandle);
+ libHandle = NULL;
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftOMXPlugin::enumerateComponents(
+ OMX_STRING name,
+ size_t size,
+ OMX_U32 index) {
+ if (index >= kNumComponents) {
+ return OMX_ErrorNoMore;
+ }
+
+ strcpy(name, kComponents[index].mName);
+
+ return OMX_ErrorNone;
+}
+
+OMX_ERRORTYPE SoftOMXPlugin::getRolesOfComponent(
+ const char *name,
+ Vector<String8> *roles) {
+ for (size_t i = 0; i < kNumComponents; ++i) {
+ if (strcmp(name, kComponents[i].mName)) {
+ continue;
+ }
+
+ roles->clear();
+ roles->push(String8(kComponents[i].mRole));
+
+ return OMX_ErrorNone;
+ }
+
+ return OMX_ErrorInvalidComponentName;
+}
+
+} // namespace android
diff --git a/media/libstagefright/omx/SoftOMXPlugin.h b/media/libstagefright/omx/SoftOMXPlugin.h
new file mode 100644
index 0000000..c89cd87
--- /dev/null
+++ b/media/libstagefright/omx/SoftOMXPlugin.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 SOFT_OMX_PLUGIN_H_
+
+#define SOFT_OMX_PLUGIN_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <OMXPluginBase.h>
+
+namespace android {
+
+struct SoftOMXPlugin : public OMXPluginBase {
+ SoftOMXPlugin();
+
+ virtual OMX_ERRORTYPE makeComponentInstance(
+ const char *name,
+ const OMX_CALLBACKTYPE *callbacks,
+ OMX_PTR appData,
+ OMX_COMPONENTTYPE **component);
+
+ virtual OMX_ERRORTYPE destroyComponentInstance(
+ OMX_COMPONENTTYPE *component);
+
+ virtual OMX_ERRORTYPE enumerateComponents(
+ OMX_STRING name,
+ size_t size,
+ OMX_U32 index);
+
+ virtual OMX_ERRORTYPE getRolesOfComponent(
+ const char *name,
+ Vector<String8> *roles);
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(SoftOMXPlugin);
+};
+
+} // namespace android
+
+#endif // SOFT_OMX_PLUGIN_H_
diff --git a/media/libstagefright/omx/tests/Android.mk b/media/libstagefright/omx/tests/Android.mk
new file mode 100644
index 0000000..6aa7470
--- /dev/null
+++ b/media/libstagefright/omx/tests/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES = \
+ OMXHarness.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright libbinder libmedia libutils libstagefright_foundation
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax
+
+LOCAL_MODULE := omx_tests
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
new file mode 100644
index 0000000..fab1771
--- /dev/null
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -0,0 +1,855 @@
+/*
+ * 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 "OMXHarness"
+#include <utils/Log.h>
+
+#include "OMXHarness.h"
+
+#include <sys/time.h>
+
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryDealer.h>
+#include <media/IMediaPlayerService.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXCodec.h>
+
+#define DEFAULT_TIMEOUT 500000
+
+namespace android {
+
+static int64_t getNowUs() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ return (int64_t)tv.tv_usec + tv.tv_sec * 1000000;
+}
+
+Harness::Harness()
+ : mInitCheck(NO_INIT) {
+ mInitCheck = initOMX();
+}
+
+Harness::~Harness() {
+}
+
+status_t Harness::initCheck() const {
+ return mInitCheck;
+}
+
+status_t Harness::initOMX() {
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<IBinder> binder = sm->getService(String16("media.player"));
+ sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
+ mOMX = service->getOMX();
+
+ return mOMX != 0 ? OK : NO_INIT;
+}
+
+void Harness::onMessage(const omx_message &msg) {
+ Mutex::Autolock autoLock(mLock);
+ mMessageQueue.push_back(msg);
+ mMessageAddedCondition.signal();
+}
+
+status_t Harness::dequeueMessageForNode(
+ IOMX::node_id node, omx_message *msg, int64_t timeoutUs) {
+ return dequeueMessageForNodeIgnoringBuffers(
+ node, NULL, NULL, msg, timeoutUs);
+}
+
+// static
+bool Harness::handleBufferMessage(
+ const omx_message &msg,
+ Vector<Buffer> *inputBuffers,
+ Vector<Buffer> *outputBuffers) {
+ switch (msg.type) {
+ case omx_message::EMPTY_BUFFER_DONE:
+ {
+ if (inputBuffers) {
+ for (size_t i = 0; i < inputBuffers->size(); ++i) {
+ if ((*inputBuffers)[i].mID == msg.u.buffer_data.buffer) {
+ inputBuffers->editItemAt(i).mFlags &= ~kBufferBusy;
+ return true;
+ }
+ }
+ CHECK(!"should not be here");
+ }
+ break;
+ }
+
+ case omx_message::FILL_BUFFER_DONE:
+ {
+ if (outputBuffers) {
+ for (size_t i = 0; i < outputBuffers->size(); ++i) {
+ if ((*outputBuffers)[i].mID == msg.u.buffer_data.buffer) {
+ outputBuffers->editItemAt(i).mFlags &= ~kBufferBusy;
+ return true;
+ }
+ }
+ CHECK(!"should not be here");
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+status_t Harness::dequeueMessageForNodeIgnoringBuffers(
+ IOMX::node_id node,
+ Vector<Buffer> *inputBuffers,
+ Vector<Buffer> *outputBuffers,
+ omx_message *msg, int64_t timeoutUs) {
+ int64_t finishBy = getNowUs() + timeoutUs;
+
+ for (;;) {
+ Mutex::Autolock autoLock(mLock);
+ List<omx_message>::iterator it = mMessageQueue.begin();
+ while (it != mMessageQueue.end()) {
+ if ((*it).node == node) {
+ if (handleBufferMessage(*it, inputBuffers, outputBuffers)) {
+ it = mMessageQueue.erase(it);
+ continue;
+ }
+
+ *msg = *it;
+ mMessageQueue.erase(it);
+
+ return OK;
+ }
+
+ ++it;
+ }
+
+ status_t err = (timeoutUs < 0)
+ ? mMessageAddedCondition.wait(mLock)
+ : mMessageAddedCondition.waitRelative(
+ mLock, (finishBy - getNowUs()) * 1000);
+
+ if (err == TIMED_OUT) {
+ return err;
+ }
+ CHECK_EQ(err, (status_t)OK);
+ }
+}
+
+status_t Harness::getPortDefinition(
+ IOMX::node_id node, OMX_U32 portIndex,
+ OMX_PARAM_PORTDEFINITIONTYPE *def) {
+ def->nSize = sizeof(*def);
+ def->nVersion.s.nVersionMajor = 1;
+ def->nVersion.s.nVersionMinor = 0;
+ def->nVersion.s.nRevision = 0;
+ def->nVersion.s.nStep = 0;
+ def->nPortIndex = portIndex;
+ return mOMX->getParameter(
+ node, OMX_IndexParamPortDefinition, def, sizeof(*def));
+}
+
+#define EXPECT(condition, info) \
+ if (!(condition)) { \
+ ALOGE(info); printf("\n * " info "\n"); return UNKNOWN_ERROR; \
+ }
+
+#define EXPECT_SUCCESS(err, info) \
+ EXPECT((err) == OK, info " failed")
+
+status_t Harness::allocatePortBuffers(
+ const sp<MemoryDealer> &dealer,
+ IOMX::node_id node, OMX_U32 portIndex,
+ Vector<Buffer> *buffers) {
+ buffers->clear();
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ status_t err = getPortDefinition(node, portIndex, &def);
+ EXPECT_SUCCESS(err, "getPortDefinition");
+
+ for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
+ Buffer buffer;
+ buffer.mMemory = dealer->allocate(def.nBufferSize);
+ buffer.mFlags = 0;
+ CHECK(buffer.mMemory != NULL);
+
+ err = mOMX->allocateBufferWithBackup(
+ node, portIndex, buffer.mMemory, &buffer.mID);
+ EXPECT_SUCCESS(err, "allocateBuffer");
+
+ buffers->push(buffer);
+ }
+
+ return OK;
+}
+
+status_t Harness::setRole(IOMX::node_id node, const char *role) {
+ OMX_PARAM_COMPONENTROLETYPE params;
+ params.nSize = sizeof(params);
+ params.nVersion.s.nVersionMajor = 1;
+ params.nVersion.s.nVersionMinor = 0;
+ params.nVersion.s.nRevision = 0;
+ params.nVersion.s.nStep = 0;
+ strncpy((char *)params.cRole, role, OMX_MAX_STRINGNAME_SIZE - 1);
+ params.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
+
+ return mOMX->setParameter(
+ node, OMX_IndexParamStandardComponentRole,
+ &params, sizeof(params));
+}
+
+struct NodeReaper {
+ NodeReaper(const sp<Harness> &harness, IOMX::node_id node)
+ : mHarness(harness),
+ mNode(node) {
+ }
+
+ ~NodeReaper() {
+ if (mNode != 0) {
+ mHarness->mOMX->freeNode(mNode);
+ mNode = 0;
+ }
+ }
+
+ void disarm() {
+ mNode = 0;
+ }
+
+private:
+ sp<Harness> mHarness;
+ IOMX::node_id mNode;
+
+ NodeReaper(const NodeReaper &);
+ NodeReaper &operator=(const NodeReaper &);
+};
+
+static sp<MediaExtractor> CreateExtractorFromURI(const char *uri) {
+ sp<DataSource> source = DataSource::CreateFromURI(uri);
+
+ if (source == NULL) {
+ return NULL;
+ }
+
+ return MediaExtractor::Create(source);
+}
+
+static sp<MediaSource> MakeSource(
+ const char *uri,
+ const char *mimeType) {
+ sp<MediaExtractor> extractor = CreateExtractorFromURI(uri);
+
+ if (extractor == NULL) {
+ return NULL;
+ }
+
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+ const char *trackMIME;
+ CHECK(meta->findCString(kKeyMIMEType, &trackMIME));
+
+ if (!strcasecmp(trackMIME, mimeType)) {
+ return extractor->getTrack(i);
+ }
+ }
+
+ return NULL;
+}
+
+status_t Harness::testStateTransitions(
+ const char *componentName, const char *componentRole) {
+ if (strncmp(componentName, "OMX.", 4)) {
+ // Non-OMX components, i.e. software decoders won't execute this
+ // test.
+ return OK;
+ }
+
+ sp<MemoryDealer> dealer = new MemoryDealer(16 * 1024 * 1024, "OMXHarness");
+ IOMX::node_id node;
+
+ status_t err =
+ mOMX->allocateNode(componentName, this, &node);
+ EXPECT_SUCCESS(err, "allocateNode");
+
+ NodeReaper reaper(this, node);
+
+ err = setRole(node, componentRole);
+ EXPECT_SUCCESS(err, "setRole");
+
+ // Initiate transition Loaded->Idle
+ err = mOMX->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle);
+ EXPECT_SUCCESS(err, "sendCommand(go-to-Idle)");
+
+ omx_message msg;
+ err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ // Make sure node doesn't just transition to idle before we are done
+ // allocating all input and output buffers.
+ EXPECT(err == TIMED_OUT,
+ "Component must not transition from loaded to idle before "
+ "all input and output buffers are allocated.");
+
+ // Now allocate buffers.
+ Vector<Buffer> inputBuffers;
+ err = allocatePortBuffers(dealer, node, 0, &inputBuffers);
+ EXPECT_SUCCESS(err, "allocatePortBuffers(input)");
+
+ err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ CHECK_EQ(err, (status_t)TIMED_OUT);
+
+ Vector<Buffer> outputBuffers;
+ err = allocatePortBuffers(dealer, node, 1, &outputBuffers);
+ EXPECT_SUCCESS(err, "allocatePortBuffers(output)");
+
+ err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ EXPECT(err == OK
+ && msg.type == omx_message::EVENT
+ && msg.u.event_data.event == OMX_EventCmdComplete
+ && msg.u.event_data.data1 == OMX_CommandStateSet
+ && msg.u.event_data.data2 == OMX_StateIdle,
+ "Component did not properly transition to idle state "
+ "after all input and output buffers were allocated.");
+
+ // Initiate transition Idle->Executing
+ err = mOMX->sendCommand(node, OMX_CommandStateSet, OMX_StateExecuting);
+ EXPECT_SUCCESS(err, "sendCommand(go-to-Executing)");
+
+ err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ EXPECT(err == OK
+ && msg.type == omx_message::EVENT
+ && msg.u.event_data.event == OMX_EventCmdComplete
+ && msg.u.event_data.data1 == OMX_CommandStateSet
+ && msg.u.event_data.data2 == OMX_StateExecuting,
+ "Component did not properly transition from idle to "
+ "executing state.");
+
+ for (size_t i = 0; i < outputBuffers.size(); ++i) {
+ err = mOMX->fillBuffer(node, outputBuffers[i].mID);
+ EXPECT_SUCCESS(err, "fillBuffer");
+
+ outputBuffers.editItemAt(i).mFlags |= kBufferBusy;
+ }
+
+ err = mOMX->sendCommand(node, OMX_CommandFlush, 1);
+ EXPECT_SUCCESS(err, "sendCommand(flush-output-port)");
+
+ err = dequeueMessageForNodeIgnoringBuffers(
+ node, &inputBuffers, &outputBuffers, &msg, DEFAULT_TIMEOUT);
+ EXPECT(err == OK
+ && msg.type == omx_message::EVENT
+ && msg.u.event_data.event == OMX_EventCmdComplete
+ && msg.u.event_data.data1 == OMX_CommandFlush
+ && msg.u.event_data.data2 == 1,
+ "Component did not properly acknowledge flushing the output port.");
+
+ for (size_t i = 0; i < outputBuffers.size(); ++i) {
+ EXPECT((outputBuffers[i].mFlags & kBufferBusy) == 0,
+ "Not all output buffers have been returned to us by the time "
+ "we received the flush-complete notification.");
+ }
+
+ for (size_t i = 0; i < outputBuffers.size(); ++i) {
+ err = mOMX->fillBuffer(node, outputBuffers[i].mID);
+ EXPECT_SUCCESS(err, "fillBuffer");
+
+ outputBuffers.editItemAt(i).mFlags |= kBufferBusy;
+ }
+
+ // Initiate transition Executing->Idle
+ err = mOMX->sendCommand(node, OMX_CommandStateSet, OMX_StateIdle);
+ EXPECT_SUCCESS(err, "sendCommand(go-to-Idle)");
+
+ err = dequeueMessageForNodeIgnoringBuffers(
+ node, &inputBuffers, &outputBuffers, &msg, DEFAULT_TIMEOUT);
+ EXPECT(err == OK
+ && msg.type == omx_message::EVENT
+ && msg.u.event_data.event == OMX_EventCmdComplete
+ && msg.u.event_data.data1 == OMX_CommandStateSet
+ && msg.u.event_data.data2 == OMX_StateIdle,
+ "Component did not properly transition to from executing to "
+ "idle state.");
+
+ for (size_t i = 0; i < inputBuffers.size(); ++i) {
+ EXPECT((inputBuffers[i].mFlags & kBufferBusy) == 0,
+ "Not all input buffers have been returned to us by the "
+ "time we received the transition-to-idle complete "
+ "notification.");
+ }
+
+ for (size_t i = 0; i < outputBuffers.size(); ++i) {
+ EXPECT((outputBuffers[i].mFlags & kBufferBusy) == 0,
+ "Not all output buffers have been returned to us by the "
+ "time we received the transition-to-idle complete "
+ "notification.");
+ }
+
+ // Initiate transition Idle->Loaded
+ err = mOMX->sendCommand(node, OMX_CommandStateSet, OMX_StateLoaded);
+ EXPECT_SUCCESS(err, "sendCommand(go-to-Loaded)");
+
+ // Make sure node doesn't just transition to loaded before we are done
+ // freeing all input and output buffers.
+ err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ CHECK_EQ(err, (status_t)TIMED_OUT);
+
+ for (size_t i = 0; i < inputBuffers.size(); ++i) {
+ err = mOMX->freeBuffer(node, 0, inputBuffers[i].mID);
+ EXPECT_SUCCESS(err, "freeBuffer");
+ }
+
+ err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ CHECK_EQ(err, (status_t)TIMED_OUT);
+
+ for (size_t i = 0; i < outputBuffers.size(); ++i) {
+ err = mOMX->freeBuffer(node, 1, outputBuffers[i].mID);
+ EXPECT_SUCCESS(err, "freeBuffer");
+ }
+
+ err = dequeueMessageForNode(node, &msg, DEFAULT_TIMEOUT);
+ EXPECT(err == OK
+ && msg.type == omx_message::EVENT
+ && msg.u.event_data.event == OMX_EventCmdComplete
+ && msg.u.event_data.data1 == OMX_CommandStateSet
+ && msg.u.event_data.data2 == OMX_StateLoaded,
+ "Component did not properly transition to from idle to "
+ "loaded state after freeing all input and output buffers.");
+
+ err = mOMX->freeNode(node);
+ EXPECT_SUCCESS(err, "freeNode");
+
+ reaper.disarm();
+
+ node = 0;
+
+ return OK;
+}
+
+static const char *GetMimeFromComponentRole(const char *componentRole) {
+ struct RoleToMime {
+ const char *mRole;
+ const char *mMime;
+ };
+ const RoleToMime kRoleToMime[] = {
+ { "video_decoder.avc", "video/avc" },
+ { "video_decoder.mpeg4", "video/mp4v-es" },
+ { "video_decoder.h263", "video/3gpp" },
+ { "video_decoder.vpx", "video/x-vnd.on2.vp8" },
+
+ // we appear to use this as a synonym to amrnb.
+ { "audio_decoder.amr", "audio/3gpp" },
+
+ { "audio_decoder.amrnb", "audio/3gpp" },
+ { "audio_decoder.amrwb", "audio/amr-wb" },
+ { "audio_decoder.aac", "audio/mp4a-latm" },
+ { "audio_decoder.mp3", "audio/mpeg" },
+ { "audio_decoder.vorbis", "audio/vorbis" },
+ { "audio_decoder.g711alaw", MEDIA_MIMETYPE_AUDIO_G711_ALAW },
+ { "audio_decoder.g711mlaw", MEDIA_MIMETYPE_AUDIO_G711_MLAW },
+ };
+
+ for (size_t i = 0; i < sizeof(kRoleToMime) / sizeof(kRoleToMime[0]); ++i) {
+ if (!strcmp(componentRole, kRoleToMime[i].mRole)) {
+ return kRoleToMime[i].mMime;
+ }
+ }
+
+ return NULL;
+}
+
+static const char *GetURLForMime(const char *mime) {
+ struct MimeToURL {
+ const char *mMime;
+ const char *mURL;
+ };
+ static const MimeToURL kMimeToURL[] = {
+ { "video/avc",
+ "file:///sdcard/media_api/video/H264_500_AAC_128.3gp" },
+ { "video/mp4v-es", "file:///sdcard/media_api/video/MPEG4_320_AAC_64.mp4" },
+ { "video/3gpp",
+ "file:///sdcard/media_api/video/H263_500_AMRNB_12.3gp" },
+ { "audio/3gpp",
+ "file:///sdcard/media_api/video/H263_500_AMRNB_12.3gp" },
+ { "audio/amr-wb", NULL },
+ { "audio/mp4a-latm",
+ "file:///sdcard/media_api/video/H263_56_AAC_24.3gp" },
+ { "audio/mpeg",
+ "file:///sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_CBR.mp3" },
+ { "audio/vorbis", NULL },
+ { "video/x-vnd.on2.vp8",
+ "file:///sdcard/media_api/video/big-buck-bunny_trailer.webm" },
+ { MEDIA_MIMETYPE_AUDIO_G711_ALAW, "file:///sdcard/M1F1-Alaw-AFsp.wav" },
+ { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
+ "file:///sdcard/M1F1-mulaw-AFsp.wav" },
+ };
+
+ for (size_t i = 0; i < sizeof(kMimeToURL) / sizeof(kMimeToURL[0]); ++i) {
+ if (!strcasecmp(kMimeToURL[i].mMime, mime)) {
+ return kMimeToURL[i].mURL;
+ }
+ }
+
+ return NULL;
+}
+
+static sp<MediaSource> CreateSourceForMime(const char *mime) {
+ const char *url = GetURLForMime(mime);
+ CHECK(url != NULL);
+
+ sp<MediaExtractor> extractor = CreateExtractorFromURI(url);
+
+ if (extractor == NULL) {
+ return NULL;
+ }
+
+ for (size_t i = 0; i < extractor->countTracks(); ++i) {
+ sp<MetaData> meta = extractor->getTrackMetaData(i);
+ CHECK(meta != NULL);
+
+ const char *trackMime;
+ CHECK(meta->findCString(kKeyMIMEType, &trackMime));
+
+ if (!strcasecmp(mime, trackMime)) {
+ return extractor->getTrack(i);
+ }
+ }
+
+ return NULL;
+}
+
+static double uniform_rand() {
+ return (double)rand() / RAND_MAX;
+}
+
+static bool CloseEnough(int64_t time1Us, int64_t time2Us) {
+#if 0
+ int64_t diff = time1Us - time2Us;
+ if (diff < 0) {
+ diff = -diff;
+ }
+
+ return diff <= 50000;
+#else
+ return time1Us == time2Us;
+#endif
+}
+
+status_t Harness::testSeek(
+ const char *componentName, const char *componentRole) {
+ bool isEncoder =
+ !strncmp(componentRole, "audio_encoder.", 14)
+ || !strncmp(componentRole, "video_encoder.", 14);
+
+ if (isEncoder) {
+ // Not testing seek behaviour for encoders.
+
+ printf(" * Not testing seek functionality for encoders.\n");
+ return OK;
+ }
+
+ const char *mime = GetMimeFromComponentRole(componentRole);
+
+ if (!mime) {
+ ALOGI("Cannot perform seek test with this componentRole (%s)",
+ componentRole);
+
+ return OK;
+ }
+
+ sp<MediaSource> source = CreateSourceForMime(mime);
+
+ sp<MediaSource> seekSource = CreateSourceForMime(mime);
+ if (source == NULL || seekSource == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ CHECK_EQ(seekSource->start(), (status_t)OK);
+
+ sp<MediaSource> codec = OMXCodec::Create(
+ mOMX, source->getFormat(), false /* createEncoder */,
+ source, componentName);
+
+ CHECK(codec != NULL);
+
+ CHECK_EQ(codec->start(), (status_t)OK);
+
+ int64_t durationUs;
+ CHECK(source->getFormat()->findInt64(kKeyDuration, &durationUs));
+
+ ALOGI("stream duration is %lld us (%.2f secs)",
+ durationUs, durationUs / 1E6);
+
+ static const int32_t kNumIterations = 5000;
+
+ // We are always going to seek beyond EOS in the first iteration (i == 0)
+ // followed by a linear read for the second iteration (i == 1).
+ // After that it's all random.
+ for (int32_t i = 0; i < kNumIterations; ++i) {
+ int64_t requestedSeekTimeUs;
+ int64_t actualSeekTimeUs;
+ MediaSource::ReadOptions options;
+
+ double r = uniform_rand();
+
+ if ((i == 1) || (i > 0 && r < 0.5)) {
+ // 50% chance of just continuing to decode from last position.
+
+ requestedSeekTimeUs = -1;
+
+ ALOGI("requesting linear read");
+ } else {
+ if (i == 0 || r < 0.55) {
+ // 5% chance of seeking beyond end of stream.
+
+ requestedSeekTimeUs = durationUs;
+
+ ALOGI("requesting seek beyond EOF");
+ } else {
+ requestedSeekTimeUs =
+ (int64_t)(uniform_rand() * durationUs);
+
+ ALOGI("requesting seek to %lld us (%.2f secs)",
+ requestedSeekTimeUs, requestedSeekTimeUs / 1E6);
+ }
+
+ MediaBuffer *buffer = NULL;
+ options.setSeekTo(
+ requestedSeekTimeUs, MediaSource::ReadOptions::SEEK_NEXT_SYNC);
+
+ if (seekSource->read(&buffer, &options) != OK) {
+ CHECK(buffer == NULL);
+ actualSeekTimeUs = -1;
+ } else {
+ CHECK(buffer != NULL);
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &actualSeekTimeUs));
+ CHECK(actualSeekTimeUs >= 0);
+
+ buffer->release();
+ buffer = NULL;
+ }
+
+ ALOGI("nearest keyframe is at %lld us (%.2f secs)",
+ actualSeekTimeUs, actualSeekTimeUs / 1E6);
+ }
+
+ status_t err;
+ MediaBuffer *buffer;
+ for (;;) {
+ err = codec->read(&buffer, &options);
+ options.clearSeekTo();
+ if (err == INFO_FORMAT_CHANGED) {
+ CHECK(buffer == NULL);
+ continue;
+ }
+ if (err == OK) {
+ CHECK(buffer != NULL);
+ if (buffer->range_length() == 0) {
+ buffer->release();
+ buffer = NULL;
+ continue;
+ }
+ } else {
+ CHECK(buffer == NULL);
+ }
+
+ break;
+ }
+
+ if (requestedSeekTimeUs < 0) {
+ // Linear read.
+ if (err != OK) {
+ CHECK(buffer == NULL);
+ } else {
+ CHECK(buffer != NULL);
+ buffer->release();
+ buffer = NULL;
+ }
+ } else if (actualSeekTimeUs < 0) {
+ EXPECT(err != OK,
+ "We attempted to seek beyond EOS and expected "
+ "ERROR_END_OF_STREAM to be returned, but instead "
+ "we got a valid buffer.");
+ EXPECT(err == ERROR_END_OF_STREAM,
+ "We attempted to seek beyond EOS and expected "
+ "ERROR_END_OF_STREAM to be returned, but instead "
+ "we found some other error.");
+ CHECK_EQ(err, (status_t)ERROR_END_OF_STREAM);
+ CHECK(buffer == NULL);
+ } else {
+ EXPECT(err == OK,
+ "Expected a valid buffer to be returned from "
+ "OMXCodec::read.");
+ CHECK(buffer != NULL);
+
+ int64_t bufferTimeUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &bufferTimeUs));
+ if (!CloseEnough(bufferTimeUs, actualSeekTimeUs)) {
+ printf("\n * Attempted seeking to %lld us (%.2f secs)",
+ requestedSeekTimeUs, requestedSeekTimeUs / 1E6);
+ printf("\n * Nearest keyframe is at %lld us (%.2f secs)",
+ actualSeekTimeUs, actualSeekTimeUs / 1E6);
+ printf("\n * Returned buffer was at %lld us (%.2f secs)\n\n",
+ bufferTimeUs, bufferTimeUs / 1E6);
+
+ buffer->release();
+ buffer = NULL;
+
+ CHECK_EQ(codec->stop(), (status_t)OK);
+
+ return UNKNOWN_ERROR;
+ }
+
+ buffer->release();
+ buffer = NULL;
+ }
+ }
+
+ CHECK_EQ(codec->stop(), (status_t)OK);
+
+ return OK;
+}
+
+status_t Harness::test(
+ const char *componentName, const char *componentRole) {
+ printf("testing %s [%s] ... ", componentName, componentRole);
+ ALOGI("testing %s [%s].", componentName, componentRole);
+
+ status_t err1 = testStateTransitions(componentName, componentRole);
+ status_t err2 = testSeek(componentName, componentRole);
+
+ if (err1 != OK) {
+ return err1;
+ }
+
+ return err2;
+}
+
+status_t Harness::testAll() {
+ List<IOMX::ComponentInfo> componentInfos;
+ status_t err = mOMX->listNodes(&componentInfos);
+ EXPECT_SUCCESS(err, "listNodes");
+
+ for (List<IOMX::ComponentInfo>::iterator it = componentInfos.begin();
+ it != componentInfos.end(); ++it) {
+ const IOMX::ComponentInfo &info = *it;
+ const char *componentName = info.mName.string();
+
+ if (strncmp(componentName, "OMX.google.", 11)) {
+ continue;
+ }
+
+ for (List<String8>::const_iterator role_it = info.mRoles.begin();
+ role_it != info.mRoles.end(); ++role_it) {
+ const char *componentRole = (*role_it).string();
+
+ err = test(componentName, componentRole);
+
+ if (err == OK) {
+ printf("OK\n");
+ }
+ }
+ }
+
+ return OK;
+}
+
+} // namespace android
+
+static void usage(const char *me) {
+ fprintf(stderr, "usage: %s\n"
+ " -h(elp) Show this information\n"
+ " -s(eed) Set the random seed\n"
+ " [ component role ]\n\n"
+ "When launched without specifying a specific component "
+ "and role, tool will test all available OMX components "
+ "in all their supported roles. To determine available "
+ "component names, use \"stagefright -l\"\n"
+ "It's also a good idea to run a separate \"adb logcat\""
+ " for additional debug and progress information.", me);
+
+ exit(0);
+}
+
+int main(int argc, char **argv) {
+ using namespace android;
+
+ android::ProcessState::self()->startThreadPool();
+ DataSource::RegisterDefaultSniffers();
+
+ const char *me = argv[0];
+
+ unsigned long seed = 0xdeadbeef;
+
+ int res;
+ while ((res = getopt(argc, argv, "hs:")) >= 0) {
+ switch (res) {
+ case 's':
+ {
+ char *end;
+ unsigned long x = strtoul(optarg, &end, 10);
+
+ if (*end != '\0' || end == optarg) {
+ fprintf(stderr, "Malformed seed.\n");
+ return 1;
+ }
+
+ seed = x;
+ break;
+ }
+
+ case '?':
+ fprintf(stderr, "\n");
+ // fall through
+
+ case 'h':
+ default:
+ {
+ usage(me);
+ exit(1);
+ break;
+ }
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ printf("To reproduce the conditions for this test, launch "
+ "with \"%s -s %lu\"\n", me, seed);
+
+ srand(seed);
+
+ sp<Harness> h = new Harness;
+ CHECK_EQ(h->initCheck(), (status_t)OK);
+
+ if (argc == 0) {
+ h->testAll();
+ } else if (argc == 2) {
+ if (h->test(argv[0], argv[1]) == OK) {
+ printf("OK\n");
+ }
+ }
+
+ return 0;
+}
diff --git a/media/libstagefright/omx/tests/OMXHarness.h b/media/libstagefright/omx/tests/OMXHarness.h
new file mode 100644
index 0000000..bb8fd0c
--- /dev/null
+++ b/media/libstagefright/omx/tests/OMXHarness.h
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+#ifndef OMX_HARNESS_H_
+
+#define OMX_HARNESS_H_
+
+#include <media/IOMX.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+#include <OMX_Component.h>
+
+namespace android {
+
+class MemoryDealer;
+
+struct Harness : public BnOMXObserver {
+ enum BufferFlags {
+ kBufferBusy = 1
+ };
+ struct Buffer {
+ IOMX::buffer_id mID;
+ sp<IMemory> mMemory;
+ uint32_t mFlags;
+ };
+
+ Harness();
+
+ status_t initCheck() const;
+
+ status_t dequeueMessageForNode(
+ IOMX::node_id node, omx_message *msg, int64_t timeoutUs = -1);
+
+ status_t dequeueMessageForNodeIgnoringBuffers(
+ IOMX::node_id node,
+ Vector<Buffer> *inputBuffers,
+ Vector<Buffer> *outputBuffers,
+ omx_message *msg, int64_t timeoutUs = -1);
+
+ status_t getPortDefinition(
+ IOMX::node_id node, OMX_U32 portIndex,
+ OMX_PARAM_PORTDEFINITIONTYPE *def);
+
+ status_t allocatePortBuffers(
+ const sp<MemoryDealer> &dealer,
+ IOMX::node_id node, OMX_U32 portIndex,
+ Vector<Buffer> *buffers);
+
+ status_t setRole(IOMX::node_id node, const char *role);
+
+ status_t testStateTransitions(
+ const char *componentName, const char *componentRole);
+
+ status_t testSeek(
+ const char *componentName, const char *componentRole);
+
+ status_t test(
+ const char *componentName, const char *componentRole);
+
+ status_t testAll();
+
+ virtual void onMessage(const omx_message &msg);
+
+protected:
+ virtual ~Harness();
+
+private:
+ friend struct NodeReaper;
+
+ Mutex mLock;
+
+ status_t mInitCheck;
+ sp<IOMX> mOMX;
+ List<omx_message> mMessageQueue;
+ Condition mMessageAddedCondition;
+
+ status_t initOMX();
+
+ bool handleBufferMessage(
+ const omx_message &msg,
+ Vector<Buffer> *inputBuffers,
+ Vector<Buffer> *outputBuffers);
+
+ Harness(const Harness &);
+ Harness &operator=(const Harness &);
+};
+
+} // namespace android
+
+#endif // OMX_HARNESS_H_
diff --git a/media/libstagefright/rtsp/AAMRAssembler.cpp b/media/libstagefright/rtsp/AAMRAssembler.cpp
new file mode 100644
index 0000000..fb8abc5
--- /dev/null
+++ b/media/libstagefright/rtsp/AAMRAssembler.cpp
@@ -0,0 +1,234 @@
+/*
+ * 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 "AAMRAssembler"
+#include <utils/Log.h>
+
+#include "AAMRAssembler.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 <media/stagefright/Utils.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 (len == keyLen && !strncmp(s, key, keyLen)) {
+ value->setTo("1");
+ return true;
+ }
+
+ if (colonPos == NULL) {
+ return false;
+ }
+
+ s = colonPos + 1;
+ }
+}
+
+AAMRAssembler::AAMRAssembler(
+ const sp<AMessage> &notify, bool isWide, const AString &params)
+ : mIsWide(isWide),
+ mNotifyMsg(notify),
+ mNextExpectedSeqNoValid(false),
+ mNextExpectedSeqNo(0) {
+ AString value;
+ CHECK(GetAttribute(params.c_str(), "octet-align", &value) && value == "1");
+ CHECK(!GetAttribute(params.c_str(), "crc", &value) || value == "0");
+ CHECK(!GetAttribute(params.c_str(), "interleaving", &value));
+}
+
+AAMRAssembler::~AAMRAssembler() {
+}
+
+ARTPAssembler::AssemblyStatus AAMRAssembler::assembleMore(
+ const sp<ARTPSource> &source) {
+ return addPacket(source);
+}
+
+static size_t getFrameSize(bool isWide, unsigned FT) {
+ static const size_t kFrameSizeNB[9] = {
+ 95, 103, 118, 134, 148, 159, 204, 244, 39
+ };
+ static const size_t kFrameSizeWB[10] = {
+ 132, 177, 253, 285, 317, 365, 397, 461, 477, 40
+ };
+
+ if (FT == 15) {
+ return 1;
+ }
+
+ size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
+
+ // Round up bits to bytes and add 1 for the header byte.
+ frameSize = (frameSize + 7) / 8 + 1;
+
+ return frameSize;
+}
+
+ARTPAssembler::AssemblyStatus AAMRAssembler::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) {
+ ALOGV("Not the sequence number I expected");
+
+ return WRONG_SEQUENCE_NUMBER;
+ }
+
+ // hexdump(buffer->data(), buffer->size());
+
+ if (buffer->size() < 1) {
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ ALOGV("AMR packet too short.");
+
+ return MALFORMED_PACKET;
+ }
+
+ unsigned payloadHeader = buffer->data()[0];
+ unsigned CMR = payloadHeader >> 4;
+ CHECK_EQ(payloadHeader & 0x0f, 0u); // RR
+
+ Vector<uint8_t> tableOfContents;
+
+ size_t offset = 1;
+ size_t totalSize = 0;
+ for (;;) {
+ if (offset >= buffer->size()) {
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ ALOGV("Unable to parse TOC.");
+
+ return MALFORMED_PACKET;
+ }
+
+ uint8_t toc = buffer->data()[offset++];
+
+ unsigned FT = (toc >> 3) & 0x0f;
+ if ((toc & 3) != 0
+ || (mIsWide && FT > 9 && FT != 15)
+ || (!mIsWide && FT > 8 && FT != 15)) {
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ ALOGV("Illegal TOC entry.");
+
+ return MALFORMED_PACKET;
+ }
+
+ totalSize += getFrameSize(mIsWide, (toc >> 3) & 0x0f);
+
+ tableOfContents.push(toc);
+
+ if (0 == (toc & 0x80)) {
+ break;
+ }
+ }
+
+ sp<ABuffer> accessUnit = new ABuffer(totalSize);
+ CopyTimes(accessUnit, buffer);
+
+ size_t dstOffset = 0;
+ for (size_t i = 0; i < tableOfContents.size(); ++i) {
+ uint8_t toc = tableOfContents[i];
+
+ size_t frameSize = getFrameSize(mIsWide, (toc >> 3) & 0x0f);
+
+ if (offset + frameSize - 1 > buffer->size()) {
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ ALOGV("AMR packet too short.");
+
+ return MALFORMED_PACKET;
+ }
+
+ accessUnit->data()[dstOffset++] = toc;
+ memcpy(accessUnit->data() + dstOffset,
+ buffer->data() + offset, frameSize - 1);
+
+ offset += frameSize - 1;
+ dstOffset += frameSize - 1;
+ }
+
+ sp<AMessage> msg = mNotifyMsg->dup();
+ msg->setBuffer("access-unit", accessUnit);
+ msg->post();
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ return OK;
+}
+
+void AAMRAssembler::packetLost() {
+ CHECK(mNextExpectedSeqNoValid);
+ ++mNextExpectedSeqNo;
+}
+
+void AAMRAssembler::onByeReceived() {
+ sp<AMessage> msg = mNotifyMsg->dup();
+ msg->setInt32("eos", true);
+ msg->post();
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/AAMRAssembler.h b/media/libstagefright/rtsp/AAMRAssembler.h
new file mode 100644
index 0000000..d55e109
--- /dev/null
+++ b/media/libstagefright/rtsp/AAMRAssembler.h
@@ -0,0 +1,59 @@
+/*
+ * 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_AMR_ASSEMBLER_H_
+
+#define A_AMR_ASSEMBLER_H_
+
+#include "ARTPAssembler.h"
+
+#include <utils/List.h>
+
+#include <stdint.h>
+
+namespace android {
+
+struct AMessage;
+struct AString;
+
+struct AAMRAssembler : public ARTPAssembler {
+ AAMRAssembler(
+ const sp<AMessage> &notify, bool isWide,
+ const AString &params);
+
+protected:
+ virtual ~AAMRAssembler();
+
+ virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source);
+ virtual void onByeReceived();
+ virtual void packetLost();
+
+private:
+ bool mIsWide;
+
+ sp<AMessage> mNotifyMsg;
+ bool mNextExpectedSeqNoValid;
+ uint32_t mNextExpectedSeqNo;
+
+ AssemblyStatus addPacket(const sp<ARTPSource> &source);
+
+ DISALLOW_EVIL_CONSTRUCTORS(AAMRAssembler);
+};
+
+} // namespace android
+
+#endif // A_AMR_ASSEMBLER_H_
+
diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
new file mode 100644
index 0000000..7ea132e
--- /dev/null
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -0,0 +1,376 @@
+/*
+ * 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 "AAVCAssembler"
+#include <utils/Log.h>
+
+#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>
+
+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) {
+ ALOGV("Not the sequence number I expected");
+
+ return WRONG_SEQUENCE_NUMBER;
+ }
+
+ const uint8_t *data = buffer->data();
+ size_t size = buffer->size();
+
+ if (size < 1 || (data[0] & 0x80)) {
+ // Corrupt.
+
+ ALOGV("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 {
+ ALOGV("Ignoring unsupported buffer (nalType=%d)", nalType);
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ return MALFORMED_PACKET;
+ }
+}
+
+void AAVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) {
+ ALOGV("addSingleNALUnit of size %d", buffer->size());
+#if !LOG_NDEBUG
+ 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) {
+ ALOGV("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) {
+ ALOGV("Discarding malformed STAP-A packet.");
+ return false;
+ }
+
+ sp<ABuffer> unit = new ABuffer(nalSize);
+ memcpy(unit->data(), &data[2], nalSize);
+
+ CopyTimes(unit, buffer);
+
+ addSingleNALUnit(unit);
+
+ data += 2 + nalSize;
+ size -= 2 + nalSize;
+ }
+
+ if (size != 0) {
+ ALOGV("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) {
+ ALOGV("Ignoring malformed FU buffer (size = %d)", size);
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+ return MALFORMED_PACKET;
+ }
+
+ if (!(data[1] & 0x80)) {
+ // Start bit not set on the first buffer.
+
+ ALOGV("Start bit not set on first buffer");
+
+ 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.
+
+ ALOGV("Grrr. This isn't fragmented at all.");
+
+ complete = true;
+ } else {
+ List<sp<ABuffer> >::iterator it = ++queue->begin();
+ while (it != queue->end()) {
+ ALOGV("sequence length %d", totalCount);
+
+ const sp<ABuffer> &buffer = *it;
+
+ const uint8_t *data = buffer->data();
+ size_t size = buffer->size();
+
+ if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
+ ALOGV("sequence not complete, expected seqNo %d, got %d",
+ expectedSeqNo, (uint32_t)buffer->int32Data());
+
+ return WRONG_SEQUENCE_NUMBER;
+ }
+
+ if (size < 2
+ || data[0] != indicator
+ || (data[1] & 0x1f) != nalType
+ || (data[1] & 0x80)) {
+ ALOGV("Ignoring malformed FU buffer.");
+
+ // 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);
+ CopyTimes(unit, *queue->begin());
+
+ 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;
+
+ ALOGV("piece #%d/%d", i + 1, totalCount);
+#if !LOG_NDEBUG
+ 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);
+
+ ALOGV("successfully assembled a NAL unit from fragments.");
+
+ return OK;
+}
+
+void AAVCAssembler::submitAccessUnit() {
+ CHECK(!mNALUnits.empty());
+
+ ALOGV("Access unit complete (%d nal units)", mNALUnits.size());
+
+ 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();
+ }
+
+ CopyTimes(accessUnit, *mNALUnits.begin());
+
+#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->setBuffer("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);
+ ALOGV("packetLost (expected %d)", mNextExpectedSeqNo);
+
+ ++mNextExpectedSeqNo;
+
+ mAccessUnitDamaged = true;
+}
+
+void AAVCAssembler::onByeReceived() {
+ sp<AMessage> msg = mNotifyMsg->dup();
+ msg->setInt32("eos", true);
+ msg->post();
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/AAVCAssembler.h b/media/libstagefright/rtsp/AAVCAssembler.h
new file mode 100644
index 0000000..bf389ec
--- /dev/null
+++ b/media/libstagefright/rtsp/AAVCAssembler.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 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 onByeReceived();
+ 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/AH263Assembler.cpp b/media/libstagefright/rtsp/AH263Assembler.cpp
new file mode 100644
index 0000000..ded70fa
--- /dev/null
+++ b/media/libstagefright/rtsp/AH263Assembler.cpp
@@ -0,0 +1,187 @@
+/*
+ * 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 "AH263Assembler.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 <media/stagefright/Utils.h>
+
+namespace android {
+
+AH263Assembler::AH263Assembler(const sp<AMessage> &notify)
+ : mNotifyMsg(notify),
+ mAccessUnitRTPTime(0),
+ mNextExpectedSeqNoValid(false),
+ mNextExpectedSeqNo(0),
+ mAccessUnitDamaged(false) {
+}
+
+AH263Assembler::~AH263Assembler() {
+}
+
+ARTPAssembler::AssemblyStatus AH263Assembler::assembleMore(
+ const sp<ARTPSource> &source) {
+ AssemblyStatus status = addPacket(source);
+ if (status == MALFORMED_PACKET) {
+ mAccessUnitDamaged = true;
+ }
+ return status;
+}
+
+ARTPAssembler::AssemblyStatus AH263Assembler::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;
+
+ // hexdump(buffer->data(), buffer->size());
+
+ if (buffer->size() < 2) {
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ return MALFORMED_PACKET;
+ }
+
+ unsigned payloadHeader = U16_AT(buffer->data());
+ CHECK_EQ(payloadHeader >> 11, 0u); // RR=0
+ unsigned P = (payloadHeader >> 10) & 1;
+ CHECK_EQ((payloadHeader >> 9) & 1, 0u); // V=0
+ CHECK_EQ((payloadHeader >> 3) & 0x3f, 0u); // PLEN=0
+ CHECK_EQ(payloadHeader & 7, 0u); // PEBIT=0
+
+ if (P) {
+ buffer->data()[0] = 0x00;
+ buffer->data()[1] = 0x00;
+ } else {
+ buffer->setRange(buffer->offset() + 2, buffer->size() - 2);
+ }
+
+ mPackets.push_back(buffer);
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ return OK;
+}
+
+void AH263Assembler::submitAccessUnit() {
+ CHECK(!mPackets.empty());
+
+#if VERBOSE
+ LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " packets)";
+#endif
+
+ size_t totalSize = 0;
+ List<sp<ABuffer> >::iterator it = mPackets.begin();
+ while (it != mPackets.end()) {
+ const sp<ABuffer> &unit = *it;
+
+ totalSize += unit->size();
+ ++it;
+ }
+
+ sp<ABuffer> accessUnit = new ABuffer(totalSize);
+ size_t offset = 0;
+ it = mPackets.begin();
+ while (it != mPackets.end()) {
+ const sp<ABuffer> &unit = *it;
+
+ memcpy((uint8_t *)accessUnit->data() + offset,
+ unit->data(), unit->size());
+
+ offset += unit->size();
+
+ ++it;
+ }
+
+ CopyTimes(accessUnit, *mPackets.begin());
+
+#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->setBuffer("access-unit", accessUnit);
+ msg->post();
+}
+
+void AH263Assembler::packetLost() {
+ CHECK(mNextExpectedSeqNoValid);
+ ++mNextExpectedSeqNo;
+
+ mAccessUnitDamaged = true;
+}
+
+void AH263Assembler::onByeReceived() {
+ sp<AMessage> msg = mNotifyMsg->dup();
+ msg->setInt32("eos", true);
+ msg->post();
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/rtsp/AH263Assembler.h b/media/libstagefright/rtsp/AH263Assembler.h
new file mode 100644
index 0000000..2b6c625
--- /dev/null
+++ b/media/libstagefright/rtsp/AH263Assembler.h
@@ -0,0 +1,57 @@
+/*
+ * 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_H263_ASSEMBLER_H_
+
+#define A_H263_ASSEMBLER_H_
+
+#include "ARTPAssembler.h"
+
+#include <utils/List.h>
+
+#include <stdint.h>
+
+namespace android {
+
+struct AMessage;
+
+struct AH263Assembler : public ARTPAssembler {
+ AH263Assembler(const sp<AMessage> &notify);
+
+protected:
+ virtual ~AH263Assembler();
+
+ virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source);
+ virtual void onByeReceived();
+ 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(AH263Assembler);
+};
+
+} // namespace android
+
+#endif // A_H263_ASSEMBLER_H_
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
new file mode 100644
index 0000000..24c2f30
--- /dev/null
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
@@ -0,0 +1,591 @@
+/*
+ * 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 "AMPEG4AudioAssembler"
+
+#include "AMPEG4AudioAssembler.h"
+
+#include "ARTPSource.h"
+
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/ABitReader.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+
+#include <ctype.h>
+
+namespace android {
+
+static bool GetAttribute(const char *s, const char *key, AString *value) {
+ value->clear();
+
+ size_t keyLen = strlen(key);
+
+ for (;;) {
+ while (isspace(*s)) {
+ ++s;
+ }
+
+ 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 status_t parseAudioObjectType(
+ ABitReader *bits, unsigned *audioObjectType) {
+ *audioObjectType = bits->getBits(5);
+ if ((*audioObjectType) == 31) {
+ *audioObjectType = 32 + bits->getBits(6);
+ }
+
+ return OK;
+}
+
+static status_t parseGASpecificConfig(
+ ABitReader *bits,
+ unsigned audioObjectType, unsigned channelConfiguration) {
+ unsigned frameLengthFlag = bits->getBits(1);
+ unsigned dependsOnCoreCoder = bits->getBits(1);
+ if (dependsOnCoreCoder) {
+ /* unsigned coreCoderDelay = */bits->getBits(1);
+ }
+ unsigned extensionFlag = bits->getBits(1);
+
+ if (!channelConfiguration) {
+ // program_config_element
+ return ERROR_UNSUPPORTED; // XXX to be implemented
+ }
+
+ if (audioObjectType == 6 || audioObjectType == 20) {
+ /* unsigned layerNr = */bits->getBits(3);
+ }
+
+ if (extensionFlag) {
+ if (audioObjectType == 22) {
+ /* unsigned numOfSubFrame = */bits->getBits(5);
+ /* unsigned layerLength = */bits->getBits(11);
+ } else if (audioObjectType == 17 || audioObjectType == 19
+ || audioObjectType == 20 || audioObjectType == 23) {
+ /* unsigned aacSectionDataResilienceFlag = */bits->getBits(1);
+ /* unsigned aacScalefactorDataResilienceFlag = */bits->getBits(1);
+ /* unsigned aacSpectralDataResilienceFlag = */bits->getBits(1);
+ }
+
+ unsigned extensionFlag3 = bits->getBits(1);
+ CHECK_EQ(extensionFlag3, 0u); // TBD in version 3
+ }
+
+ return OK;
+}
+
+static status_t parseAudioSpecificConfig(ABitReader *bits, sp<ABuffer> *asc) {
+ const uint8_t *dataStart = bits->data();
+ size_t totalNumBits = bits->numBitsLeft();
+
+ unsigned audioObjectType;
+ CHECK_EQ(parseAudioObjectType(bits, &audioObjectType), (status_t)OK);
+
+ unsigned samplingFreqIndex = bits->getBits(4);
+ if (samplingFreqIndex == 0x0f) {
+ /* unsigned samplingFrequency = */bits->getBits(24);
+ }
+
+ unsigned channelConfiguration = bits->getBits(4);
+
+ unsigned extensionAudioObjectType = 0;
+ unsigned sbrPresent = 0;
+
+ if (audioObjectType == 5) {
+ extensionAudioObjectType = audioObjectType;
+ sbrPresent = 1;
+ unsigned extensionSamplingFreqIndex = bits->getBits(4);
+ if (extensionSamplingFreqIndex == 0x0f) {
+ /* unsigned extensionSamplingFrequency = */bits->getBits(24);
+ }
+ CHECK_EQ(parseAudioObjectType(bits, &audioObjectType), (status_t)OK);
+ }
+
+ CHECK((audioObjectType >= 1 && audioObjectType <= 4)
+ || (audioObjectType >= 6 && audioObjectType <= 7)
+ || audioObjectType == 17
+ || (audioObjectType >= 19 && audioObjectType <= 23));
+
+ CHECK_EQ(parseGASpecificConfig(
+ bits, audioObjectType, channelConfiguration), (status_t)OK);
+
+ if (audioObjectType == 17
+ || (audioObjectType >= 19 && audioObjectType <= 27)) {
+ unsigned epConfig = bits->getBits(2);
+ if (epConfig == 2 || epConfig == 3) {
+ // ErrorProtectionSpecificConfig
+ return ERROR_UNSUPPORTED; // XXX to be implemented
+
+ if (epConfig == 3) {
+ unsigned directMapping = bits->getBits(1);
+ CHECK_EQ(directMapping, 1u);
+ }
+ }
+ }
+
+ if (extensionAudioObjectType != 5 && bits->numBitsLeft() >= 16) {
+ size_t numBitsLeftAtStart = bits->numBitsLeft();
+
+ unsigned syncExtensionType = bits->getBits(11);
+ if (syncExtensionType == 0x2b7) {
+ ALOGI("found syncExtension");
+
+ CHECK_EQ(parseAudioObjectType(bits, &extensionAudioObjectType),
+ (status_t)OK);
+
+ sbrPresent = bits->getBits(1);
+
+ if (sbrPresent == 1) {
+ unsigned extensionSamplingFreqIndex = bits->getBits(4);
+ if (extensionSamplingFreqIndex == 0x0f) {
+ /* unsigned extensionSamplingFrequency = */bits->getBits(24);
+ }
+ }
+
+ size_t numBitsInExtension =
+ numBitsLeftAtStart - bits->numBitsLeft();
+
+ if (numBitsInExtension & 7) {
+ // Apparently an extension is always considered an even
+ // multiple of 8 bits long.
+
+ ALOGI("Skipping %d bits after sync extension",
+ 8 - (numBitsInExtension & 7));
+
+ bits->skipBits(8 - (numBitsInExtension & 7));
+ }
+ } else {
+ bits->putBits(syncExtensionType, 11);
+ }
+ }
+
+ if (asc != NULL) {
+ size_t bitpos = totalNumBits & 7;
+
+ ABitReader bs(dataStart, (totalNumBits + 7) / 8);
+
+ totalNumBits -= bits->numBitsLeft();
+
+ size_t numBytes = (totalNumBits + 7) / 8;
+
+ *asc = new ABuffer(numBytes);
+
+ if (bitpos & 7) {
+ bs.skipBits(8 - (bitpos & 7));
+ }
+
+ uint8_t *dstPtr = (*asc)->data();
+ while (numBytes > 0) {
+ *dstPtr++ = bs.getBits(8);
+ --numBytes;
+ }
+ }
+
+ return OK;
+}
+
+static status_t parseStreamMuxConfig(
+ ABitReader *bits,
+ unsigned *numSubFrames,
+ unsigned *frameLengthType,
+ ssize_t *fixedFrameLength,
+ bool *otherDataPresent,
+ unsigned *otherDataLenBits) {
+ unsigned audioMuxVersion = bits->getBits(1);
+
+ unsigned audioMuxVersionA = 0;
+ if (audioMuxVersion == 1) {
+ audioMuxVersionA = bits->getBits(1);
+ }
+
+ CHECK_EQ(audioMuxVersionA, 0u); // otherwise future spec
+
+ if (audioMuxVersion != 0) {
+ return ERROR_UNSUPPORTED; // XXX to be implemented;
+ }
+ CHECK_EQ(audioMuxVersion, 0u); // XXX to be implemented
+
+ unsigned allStreamsSameTimeFraming = bits->getBits(1);
+ CHECK_EQ(allStreamsSameTimeFraming, 1u); // There's only one stream.
+
+ *numSubFrames = bits->getBits(6);
+ unsigned numProgram = bits->getBits(4);
+ CHECK_EQ(numProgram, 0u); // disabled in RTP LATM
+
+ unsigned numLayer = bits->getBits(3);
+ CHECK_EQ(numLayer, 0u); // disabled in RTP LATM
+
+ if (audioMuxVersion == 0) {
+ // AudioSpecificConfig
+ CHECK_EQ(parseAudioSpecificConfig(bits, NULL /* asc */), (status_t)OK);
+ } else {
+ TRESPASS(); // XXX to be implemented
+ }
+
+ *frameLengthType = bits->getBits(3);
+ *fixedFrameLength = -1;
+
+ switch (*frameLengthType) {
+ case 0:
+ {
+ /* unsigned bufferFullness = */bits->getBits(8);
+
+ // The "coreFrameOffset" does not apply since there's only
+ // a single layer.
+ break;
+ }
+
+ case 1:
+ {
+ *fixedFrameLength = bits->getBits(9);
+ break;
+ }
+
+ case 2:
+ {
+ // reserved
+ TRESPASS();
+ break;
+ }
+
+ case 3:
+ case 4:
+ case 5:
+ {
+ /* unsigned CELPframeLengthTableIndex = */bits->getBits(6);
+ break;
+ }
+
+ case 6:
+ case 7:
+ {
+ /* unsigned HVXCframeLengthTableIndex = */bits->getBits(1);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ *otherDataPresent = bits->getBits(1);
+ *otherDataLenBits = 0;
+ if (*otherDataPresent) {
+ if (audioMuxVersion == 1) {
+ TRESPASS(); // XXX to be implemented
+ } else {
+ *otherDataLenBits = 0;
+
+ unsigned otherDataLenEsc;
+ do {
+ (*otherDataLenBits) <<= 8;
+ otherDataLenEsc = bits->getBits(1);
+ unsigned otherDataLenTmp = bits->getBits(8);
+ (*otherDataLenBits) += otherDataLenTmp;
+ } while (otherDataLenEsc);
+ }
+ }
+
+ unsigned crcCheckPresent = bits->getBits(1);
+ if (crcCheckPresent) {
+ /* unsigned crcCheckSum = */bits->getBits(8);
+ }
+
+ return OK;
+}
+
+sp<ABuffer> AMPEG4AudioAssembler::removeLATMFraming(const sp<ABuffer> &buffer) {
+ CHECK(!mMuxConfigPresent); // XXX to be implemented
+
+ sp<ABuffer> out = new ABuffer(buffer->size());
+ out->setRange(0, 0);
+
+ size_t offset = 0;
+ uint8_t *ptr = buffer->data();
+
+ for (size_t i = 0; i <= mNumSubFrames; ++i) {
+ // parse PayloadLengthInfo
+
+ unsigned payloadLength = 0;
+
+ switch (mFrameLengthType) {
+ case 0:
+ {
+ unsigned muxSlotLengthBytes = 0;
+ unsigned tmp;
+ do {
+ CHECK_LT(offset, buffer->size());
+ tmp = ptr[offset++];
+ muxSlotLengthBytes += tmp;
+ } while (tmp == 0xff);
+
+ payloadLength = muxSlotLengthBytes;
+ break;
+ }
+
+ case 2:
+ {
+ // reserved
+
+ TRESPASS();
+ break;
+ }
+
+ default:
+ {
+ CHECK_GE(mFixedFrameLength, 0);
+
+ payloadLength = mFixedFrameLength;
+ break;
+ }
+ }
+
+ CHECK_LE(offset + payloadLength, buffer->size());
+
+ memcpy(out->data() + out->size(), &ptr[offset], payloadLength);
+ out->setRange(0, out->size() + payloadLength);
+
+ offset += payloadLength;
+
+ if (mOtherDataPresent) {
+ // We want to stay byte-aligned.
+
+ CHECK((mOtherDataLenBits % 8) == 0);
+ CHECK_LE(offset + (mOtherDataLenBits / 8), buffer->size());
+ offset += mOtherDataLenBits / 8;
+ }
+ }
+
+ if (offset < buffer->size()) {
+ ALOGI("ignoring %d bytes of trailing data", buffer->size() - offset);
+ }
+ CHECK_LE(offset, buffer->size());
+
+ return out;
+}
+
+AMPEG4AudioAssembler::AMPEG4AudioAssembler(
+ const sp<AMessage> &notify, const AString &params)
+ : mNotifyMsg(notify),
+ mMuxConfigPresent(false),
+ mAccessUnitRTPTime(0),
+ mNextExpectedSeqNoValid(false),
+ mNextExpectedSeqNo(0),
+ mAccessUnitDamaged(false) {
+ AString val;
+ if (!GetAttribute(params.c_str(), "cpresent", &val)) {
+ mMuxConfigPresent = true;
+ } else if (val == "0") {
+ mMuxConfigPresent = false;
+ } else {
+ CHECK(val == "1");
+ mMuxConfigPresent = true;
+ }
+
+ CHECK(GetAttribute(params.c_str(), "config", &val));
+
+ sp<ABuffer> config = decodeHex(val);
+ CHECK(config != NULL);
+
+ ABitReader bits(config->data(), config->size());
+ status_t err = parseStreamMuxConfig(
+ &bits, &mNumSubFrames, &mFrameLengthType,
+ &mFixedFrameLength,
+ &mOtherDataPresent, &mOtherDataLenBits);
+
+ CHECK_EQ(err, (status_t)NO_ERROR);
+}
+
+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
+
+ size_t totalSize = 0;
+ List<sp<ABuffer> >::iterator it = mPackets.begin();
+ while (it != mPackets.end()) {
+ const sp<ABuffer> &unit = *it;
+
+ totalSize += unit->size();
+ ++it;
+ }
+
+ sp<ABuffer> accessUnit = new ABuffer(totalSize);
+ size_t offset = 0;
+ it = mPackets.begin();
+ while (it != mPackets.end()) {
+ const sp<ABuffer> &unit = *it;
+
+ memcpy((uint8_t *)accessUnit->data() + offset,
+ unit->data(), unit->size());
+
+ ++it;
+ }
+
+ accessUnit = removeLATMFraming(accessUnit);
+ CopyTimes(accessUnit, *mPackets.begin());
+
+#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->setBuffer("access-unit", accessUnit);
+ msg->post();
+}
+
+void AMPEG4AudioAssembler::packetLost() {
+ CHECK(mNextExpectedSeqNoValid);
+ ++mNextExpectedSeqNo;
+
+ mAccessUnitDamaged = true;
+}
+
+void AMPEG4AudioAssembler::onByeReceived() {
+ sp<AMessage> msg = mNotifyMsg->dup();
+ msg->setInt32("eos", true);
+ msg->post();
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.h b/media/libstagefright/rtsp/AMPEG4AudioAssembler.h
new file mode 100644
index 0000000..1361cd2
--- /dev/null
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.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 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 AString;
+
+struct AMPEG4AudioAssembler : public ARTPAssembler {
+ AMPEG4AudioAssembler(
+ const sp<AMessage> &notify, const AString &params);
+
+protected:
+ virtual ~AMPEG4AudioAssembler();
+
+ virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source);
+ virtual void onByeReceived();
+ virtual void packetLost();
+
+private:
+ sp<AMessage> mNotifyMsg;
+
+ bool mMuxConfigPresent;
+ unsigned mNumSubFrames;
+ unsigned mFrameLengthType;
+ ssize_t mFixedFrameLength;
+ bool mOtherDataPresent;
+ unsigned mOtherDataLenBits;
+
+ uint32_t mAccessUnitRTPTime;
+ bool mNextExpectedSeqNoValid;
+ uint32_t mNextExpectedSeqNo;
+ bool mAccessUnitDamaged;
+ List<sp<ABuffer> > mPackets;
+
+ AssemblyStatus addPacket(const sp<ARTPSource> &source);
+ void submitAccessUnit();
+
+ sp<ABuffer> removeLATMFraming(const sp<ABuffer> &buffer);
+
+ DISALLOW_EVIL_CONSTRUCTORS(AMPEG4AudioAssembler);
+};
+
+} // namespace android
+
+#endif // A_MPEG4_AUDIO_ASSEMBLER_H_
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
new file mode 100644
index 0000000..687d72b
--- /dev/null
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
@@ -0,0 +1,399 @@
+/*
+ * 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 "AMPEG4ElementaryAssembler"
+#include <utils/Log.h>
+
+#include "AMPEG4ElementaryAssembler.h"
+
+#include "ARTPSource.h"
+
+#include <media/stagefright/foundation/ABitReader.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/Utils.h>
+
+#include <ctype.h>
+#include <stdint.h>
+
+namespace android {
+
+static bool GetAttribute(const char *s, const char *key, AString *value) {
+ value->clear();
+
+ size_t keyLen = strlen(key);
+
+ for (;;) {
+ while (isspace(*s)) {
+ ++s;
+ }
+
+ const char *colonPos = strchr(s, ';');
+
+ size_t len =
+ (colonPos == NULL) ? strlen(s) : colonPos - s;
+
+ if (len >= keyLen + 1 && s[keyLen] == '='
+ && !strncasecmp(s, key, keyLen)) {
+ value->setTo(&s[keyLen + 1], len - keyLen - 1);
+ return true;
+ }
+
+ if (colonPos == NULL) {
+ return false;
+ }
+
+ s = colonPos + 1;
+ }
+}
+
+static bool GetIntegerAttribute(
+ const char *s, const char *key, unsigned *x) {
+ *x = 0;
+
+ AString val;
+ if (!GetAttribute(s, key, &val)) {
+ return false;
+ }
+
+ s = val.c_str();
+ char *end;
+ unsigned y = strtoul(s, &end, 10);
+
+ if (end == s || *end != '\0') {
+ return false;
+ }
+
+ *x = y;
+
+ return true;
+}
+
+// static
+AMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler(
+ const sp<AMessage> &notify, const AString &desc, const AString &params)
+ : mNotifyMsg(notify),
+ mIsGeneric(false),
+ mParams(params),
+ mSizeLength(0),
+ mIndexLength(0),
+ mIndexDeltaLength(0),
+ mCTSDeltaLength(0),
+ mDTSDeltaLength(0),
+ mRandomAccessIndication(false),
+ mStreamStateIndication(0),
+ mAuxiliaryDataSizeLength(0),
+ mHasAUHeader(false),
+ mAccessUnitRTPTime(0),
+ mNextExpectedSeqNoValid(false),
+ mNextExpectedSeqNo(0),
+ mAccessUnitDamaged(false) {
+ mIsGeneric = !strncasecmp(desc.c_str(),"mpeg4-generic/", 14);
+
+ if (mIsGeneric) {
+ AString value;
+ CHECK(GetAttribute(params.c_str(), "mode", &value));
+
+ if (!GetIntegerAttribute(params.c_str(), "sizeLength", &mSizeLength)) {
+ mSizeLength = 0;
+ }
+
+ if (!GetIntegerAttribute(
+ params.c_str(), "indexLength", &mIndexLength)) {
+ mIndexLength = 0;
+ }
+
+ if (!GetIntegerAttribute(
+ params.c_str(), "indexDeltaLength", &mIndexDeltaLength)) {
+ mIndexDeltaLength = 0;
+ }
+
+ if (!GetIntegerAttribute(
+ params.c_str(), "CTSDeltaLength", &mCTSDeltaLength)) {
+ mCTSDeltaLength = 0;
+ }
+
+ if (!GetIntegerAttribute(
+ params.c_str(), "DTSDeltaLength", &mDTSDeltaLength)) {
+ mDTSDeltaLength = 0;
+ }
+
+ unsigned x;
+ if (!GetIntegerAttribute(
+ params.c_str(), "randomAccessIndication", &x)) {
+ mRandomAccessIndication = false;
+ } else {
+ CHECK(x == 0 || x == 1);
+ mRandomAccessIndication = (x != 0);
+ }
+
+ if (!GetIntegerAttribute(
+ params.c_str(), "streamStateIndication",
+ &mStreamStateIndication)) {
+ mStreamStateIndication = 0;
+ }
+
+ if (!GetIntegerAttribute(
+ params.c_str(), "auxiliaryDataSizeLength",
+ &mAuxiliaryDataSizeLength)) {
+ mAuxiliaryDataSizeLength = 0;
+ }
+
+ mHasAUHeader =
+ mSizeLength > 0
+ || mIndexLength > 0
+ || mIndexDeltaLength > 0
+ || mCTSDeltaLength > 0
+ || mDTSDeltaLength > 0
+ || mRandomAccessIndication
+ || mStreamStateIndication > 0;
+ }
+}
+
+AMPEG4ElementaryAssembler::~AMPEG4ElementaryAssembler() {
+}
+
+struct AUHeader {
+ unsigned mSize;
+ unsigned mSerial;
+};
+
+ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::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) {
+ ALOGV("Not the sequence number I expected");
+
+ 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;
+
+ if (!mIsGeneric) {
+ mPackets.push_back(buffer);
+ } else {
+ // hexdump(buffer->data(), buffer->size());
+
+ CHECK_GE(buffer->size(), 2u);
+ unsigned AU_headers_length = U16_AT(buffer->data()); // in bits
+
+ CHECK_GE(buffer->size(), 2 + (AU_headers_length + 7) / 8);
+
+ List<AUHeader> headers;
+
+ ABitReader bits(buffer->data() + 2, buffer->size() - 2);
+ unsigned numBitsLeft = AU_headers_length;
+
+ unsigned AU_serial = 0;
+ for (;;) {
+ if (numBitsLeft < mSizeLength) { break; }
+
+ unsigned AU_size = bits.getBits(mSizeLength);
+ numBitsLeft -= mSizeLength;
+
+ size_t n = headers.empty() ? mIndexLength : mIndexDeltaLength;
+ if (numBitsLeft < n) { break; }
+
+ unsigned AU_index = bits.getBits(n);
+ numBitsLeft -= n;
+
+ if (headers.empty()) {
+ AU_serial = AU_index;
+ } else {
+ AU_serial += 1 + AU_index;
+ }
+
+ if (mCTSDeltaLength > 0) {
+ if (numBitsLeft < 1) {
+ break;
+ }
+ --numBitsLeft;
+ if (bits.getBits(1)) {
+ if (numBitsLeft < mCTSDeltaLength) {
+ break;
+ }
+ bits.skipBits(mCTSDeltaLength);
+ numBitsLeft -= mCTSDeltaLength;
+ }
+ }
+
+ if (mDTSDeltaLength > 0) {
+ if (numBitsLeft < 1) {
+ break;
+ }
+ --numBitsLeft;
+ if (bits.getBits(1)) {
+ if (numBitsLeft < mDTSDeltaLength) {
+ break;
+ }
+ bits.skipBits(mDTSDeltaLength);
+ numBitsLeft -= mDTSDeltaLength;
+ }
+ }
+
+ if (mRandomAccessIndication) {
+ if (numBitsLeft < 1) {
+ break;
+ }
+ bits.skipBits(1);
+ --numBitsLeft;
+ }
+
+ if (mStreamStateIndication > 0) {
+ if (numBitsLeft < mStreamStateIndication) {
+ break;
+ }
+ bits.skipBits(mStreamStateIndication);
+ }
+
+ AUHeader header;
+ header.mSize = AU_size;
+ header.mSerial = AU_serial;
+ headers.push_back(header);
+ }
+
+ size_t offset = 2 + (AU_headers_length + 7) / 8;
+
+ if (mAuxiliaryDataSizeLength > 0) {
+ ABitReader bits(buffer->data() + offset, buffer->size() - offset);
+
+ unsigned auxSize = bits.getBits(mAuxiliaryDataSizeLength);
+
+ offset += (mAuxiliaryDataSizeLength + auxSize + 7) / 8;
+ }
+
+ for (List<AUHeader>::iterator it = headers.begin();
+ it != headers.end(); ++it) {
+ const AUHeader &header = *it;
+
+ CHECK_LE(offset + header.mSize, buffer->size());
+
+ sp<ABuffer> accessUnit = new ABuffer(header.mSize);
+ memcpy(accessUnit->data(), buffer->data() + offset, header.mSize);
+
+ offset += header.mSize;
+
+ CopyTimes(accessUnit, buffer);
+ mPackets.push_back(accessUnit);
+ }
+
+ CHECK_EQ(offset, buffer->size());
+ }
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ return OK;
+}
+
+void AMPEG4ElementaryAssembler::submitAccessUnit() {
+ CHECK(!mPackets.empty());
+
+ ALOGV("Access unit complete (%d nal units)", mPackets.size());
+
+ size_t totalSize = 0;
+ for (List<sp<ABuffer> >::iterator it = mPackets.begin();
+ it != mPackets.end(); ++it) {
+ totalSize += (*it)->size();
+ }
+
+ sp<ABuffer> accessUnit = new ABuffer(totalSize);
+ size_t offset = 0;
+ for (List<sp<ABuffer> >::iterator it = mPackets.begin();
+ it != mPackets.end(); ++it) {
+ sp<ABuffer> nal = *it;
+ memcpy(accessUnit->data() + offset, nal->data(), nal->size());
+ offset += nal->size();
+ }
+
+ CopyTimes(accessUnit, *mPackets.begin());
+
+#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->setBuffer("access-unit", accessUnit);
+ msg->post();
+}
+
+ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::assembleMore(
+ const sp<ARTPSource> &source) {
+ AssemblyStatus status = addPacket(source);
+ if (status == MALFORMED_PACKET) {
+ mAccessUnitDamaged = true;
+ }
+ return status;
+}
+
+void AMPEG4ElementaryAssembler::packetLost() {
+ CHECK(mNextExpectedSeqNoValid);
+ ALOGV("packetLost (expected %d)", mNextExpectedSeqNo);
+
+ ++mNextExpectedSeqNo;
+
+ mAccessUnitDamaged = true;
+}
+
+void AMPEG4ElementaryAssembler::onByeReceived() {
+ sp<AMessage> msg = mNotifyMsg->dup();
+ msg->setInt32("eos", true);
+ msg->post();
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h
new file mode 100644
index 0000000..794bbcc
--- /dev/null
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h
@@ -0,0 +1,74 @@
+/*
+ * 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_ELEM_ASSEMBLER_H_
+
+#define A_MPEG4_ELEM_ASSEMBLER_H_
+
+#include "ARTPAssembler.h"
+
+#include <media/stagefright/foundation/AString.h>
+
+#include <utils/List.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABuffer;
+struct AMessage;
+
+struct AMPEG4ElementaryAssembler : public ARTPAssembler {
+ AMPEG4ElementaryAssembler(
+ const sp<AMessage> &notify, const AString &desc,
+ const AString &params);
+
+protected:
+ virtual ~AMPEG4ElementaryAssembler();
+
+ virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source);
+ virtual void onByeReceived();
+ virtual void packetLost();
+
+private:
+ sp<AMessage> mNotifyMsg;
+ bool mIsGeneric;
+ AString mParams;
+
+ unsigned mSizeLength;
+ unsigned mIndexLength;
+ unsigned mIndexDeltaLength;
+ unsigned mCTSDeltaLength;
+ unsigned mDTSDeltaLength;
+ bool mRandomAccessIndication;
+ unsigned mStreamStateIndication;
+ unsigned mAuxiliaryDataSizeLength;
+ bool mHasAUHeader;
+
+ 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(AMPEG4ElementaryAssembler);
+};
+
+} // namespace android
+
+#endif // A_MPEG4_ELEM_ASSEMBLER_H_
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
new file mode 100644
index 0000000..6cf1301
--- /dev/null
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -0,0 +1,579 @@
+/*
+ * 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 "APacketSource"
+#include <utils/Log.h>
+
+#include "APacketSource.h"
+
+#include "ARawAudioAssembler.h"
+#include "ASessionDescription.h"
+
+#include "avc_utils.h"
+
+#include <ctype.h>
+
+#include <media/stagefright/foundation/ABitReader.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/MediaDefs.h>
+#include <media/stagefright/MediaErrors.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 (;;) {
+ while (isspace(*s)) {
+ ++s;
+ }
+
+ 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, int32_t *width, int32_t *height) {
+ *width = 0;
+ *height = 0;
+
+ AString val;
+ if (!GetAttribute(params, "profile-level-id", &val)) {
+ return NULL;
+ }
+
+ 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;
+
+ if (!GetAttribute(params, "sprop-parameter-sets", &val)) {
+ return NULL;
+ }
+
+ 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();
+
+ if (i == 0) {
+ FindAVCDimensions(nal, width, height);
+ ALOGI("dimensions %dx%d", *width, *height);
+ }
+ }
+
+ *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;
+}
+
+// From mpeg4-generic configuration data.
+sp<ABuffer> MakeAACCodecSpecificData2(const char *params) {
+ AString val;
+ unsigned long objectType;
+ if (GetAttribute(params, "objectType", &val)) {
+ const char *s = val.c_str();
+ char *end;
+ objectType = strtoul(s, &end, 10);
+ CHECK(end > s && *end == '\0');
+ } else {
+ objectType = 0x40; // Audio ISO/IEC 14496-3
+ }
+
+ CHECK(GetAttribute(params, "config", &val));
+
+ sp<ABuffer> config = decodeHex(val);
+ CHECK(config != NULL);
+
+ // Make sure size fits into a single byte and doesn't have to
+ // be encoded.
+ CHECK_LT(20 + config->size(), 128u);
+
+ const uint8_t *data = config->data();
+
+ 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) + config->size());
+ uint8_t *dst = csd->data();
+ *dst++ = 0x03;
+ *dst++ = 20 + config->size();
+ *dst++ = 0x00; // ES_ID
+ *dst++ = 0x00;
+ *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
+ *dst++ = 0x04;
+ *dst++ = 15 + config->size();
+ *dst++ = objectType;
+ for (int i = 0; i < 12; ++i) { *dst++ = 0x00; }
+ *dst++ = 0x05;
+ *dst++ = config->size();
+ memcpy(dst, config->data(), config->size());
+
+ // hexdump(csd->data(), csd->size());
+
+ return csd;
+}
+
+static size_t GetSizeWidth(size_t x) {
+ size_t n = 1;
+ while (x > 127) {
+ ++n;
+ x >>= 7;
+ }
+ return n;
+}
+
+static uint8_t *EncodeSize(uint8_t *dst, size_t x) {
+ while (x > 127) {
+ *dst++ = (x & 0x7f) | 0x80;
+ x >>= 7;
+ }
+ *dst++ = x;
+ return dst;
+}
+
+static bool ExtractDimensionsMPEG4Config(
+ const sp<ABuffer> &config, int32_t *width, int32_t *height) {
+ *width = 0;
+ *height = 0;
+
+ const uint8_t *ptr = config->data();
+ size_t offset = 0;
+ bool foundVOL = false;
+ while (offset + 3 < config->size()) {
+ if (memcmp("\x00\x00\x01", &ptr[offset], 3)
+ || (ptr[offset + 3] & 0xf0) != 0x20) {
+ ++offset;
+ continue;
+ }
+
+ foundVOL = true;
+ break;
+ }
+
+ if (!foundVOL) {
+ return false;
+ }
+
+ return ExtractDimensionsFromVOLHeader(
+ &ptr[offset], config->size() - offset, width, height);
+}
+
+static sp<ABuffer> MakeMPEG4VideoCodecSpecificData(
+ const char *params, int32_t *width, int32_t *height) {
+ *width = 0;
+ *height = 0;
+
+ AString val;
+ CHECK(GetAttribute(params, "config", &val));
+
+ sp<ABuffer> config = decodeHex(val);
+ CHECK(config != NULL);
+
+ if (!ExtractDimensionsMPEG4Config(config, width, height)) {
+ return NULL;
+ }
+
+ ALOGI("VOL dimensions = %dx%d", *width, *height);
+
+ size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
+ size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
+ size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
+
+ sp<ABuffer> csd = new ABuffer(len3);
+ uint8_t *dst = csd->data();
+ *dst++ = 0x03;
+ dst = EncodeSize(dst, len2 + 3);
+ *dst++ = 0x00; // ES_ID
+ *dst++ = 0x00;
+ *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+ *dst++ = 0x04;
+ dst = EncodeSize(dst, len1 + 13);
+ *dst++ = 0x01; // Video ISO/IEC 14496-2 Simple Profile
+ for (size_t i = 0; i < 12; ++i) {
+ *dst++ = 0x00;
+ }
+
+ *dst++ = 0x05;
+ dst = EncodeSize(dst, config->size());
+ memcpy(dst, config->data(), config->size());
+ dst += config->size();
+
+ // hexdump(csd->data(), csd->size());
+
+ return csd;
+}
+
+APacketSource::APacketSource(
+ const sp<ASessionDescription> &sessionDesc, size_t index)
+ : mInitCheck(NO_INIT),
+ mFormat(new MetaData) {
+ 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);
+ }
+
+ mInitCheck = OK;
+ if (!strncmp(desc.c_str(), "H264/", 5)) {
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+
+ int32_t width, height;
+ if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
+ width = -1;
+ height = -1;
+ }
+
+ int32_t encWidth, encHeight;
+ sp<ABuffer> codecSpecificData =
+ MakeAVCCodecSpecificData(params.c_str(), &encWidth, &encHeight);
+
+ if (codecSpecificData != NULL) {
+ if (width < 0) {
+ // If no explicit width/height given in the sdp, use the dimensions
+ // extracted from the first sequence parameter set.
+ width = encWidth;
+ height = encHeight;
+ }
+
+ mFormat->setData(
+ kKeyAVCC, 0,
+ codecSpecificData->data(), codecSpecificData->size());
+ } else if (width < 0) {
+ mInitCheck = ERROR_UNSUPPORTED;
+ return;
+ }
+
+ mFormat->setInt32(kKeyWidth, width);
+ mFormat->setInt32(kKeyHeight, height);
+ } else if (!strncmp(desc.c_str(), "H263-2000/", 10)
+ || !strncmp(desc.c_str(), "H263-1998/", 10)) {
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+
+ int32_t width, height;
+ if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
+ mInitCheck = ERROR_UNSUPPORTED;
+ return;
+ }
+
+ mFormat->setInt32(kKeyWidth, width);
+ mFormat->setInt32(kKeyHeight, height);
+ } else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) {
+ 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 if (!strncmp(desc.c_str(), "AMR/", 4)) {
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
+
+ int32_t sampleRate, numChannels;
+ ASessionDescription::ParseFormatDesc(
+ desc.c_str(), &sampleRate, &numChannels);
+
+ mFormat->setInt32(kKeySampleRate, sampleRate);
+ mFormat->setInt32(kKeyChannelCount, numChannels);
+
+ if (sampleRate != 8000 || numChannels != 1) {
+ mInitCheck = ERROR_UNSUPPORTED;
+ }
+ } else if (!strncmp(desc.c_str(), "AMR-WB/", 7)) {
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
+
+ int32_t sampleRate, numChannels;
+ ASessionDescription::ParseFormatDesc(
+ desc.c_str(), &sampleRate, &numChannels);
+
+ mFormat->setInt32(kKeySampleRate, sampleRate);
+ mFormat->setInt32(kKeyChannelCount, numChannels);
+
+ if (sampleRate != 16000 || numChannels != 1) {
+ mInitCheck = ERROR_UNSUPPORTED;
+ }
+ } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)) {
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+
+ int32_t width, height;
+ if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
+ width = -1;
+ height = -1;
+ }
+
+ int32_t encWidth, encHeight;
+ sp<ABuffer> codecSpecificData =
+ MakeMPEG4VideoCodecSpecificData(
+ params.c_str(), &encWidth, &encHeight);
+
+ if (codecSpecificData != NULL) {
+ mFormat->setData(
+ kKeyESDS, 0,
+ codecSpecificData->data(), codecSpecificData->size());
+
+ if (width < 0) {
+ width = encWidth;
+ height = encHeight;
+ }
+ } else if (width < 0) {
+ mInitCheck = ERROR_UNSUPPORTED;
+ return;
+ }
+
+ mFormat->setInt32(kKeyWidth, width);
+ mFormat->setInt32(kKeyHeight, height);
+ } else if (!strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) {
+ AString val;
+ if (!GetAttribute(params.c_str(), "mode", &val)
+ || (strcasecmp(val.c_str(), "AAC-lbr")
+ && strcasecmp(val.c_str(), "AAC-hbr"))) {
+ mInitCheck = ERROR_UNSUPPORTED;
+ return;
+ }
+
+ 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 =
+ MakeAACCodecSpecificData2(params.c_str());
+
+ mFormat->setData(
+ kKeyESDS, 0,
+ codecSpecificData->data(), codecSpecificData->size());
+ } else if (ARawAudioAssembler::Supports(desc.c_str())) {
+ ARawAudioAssembler::MakeFormat(desc.c_str(), mFormat);
+ } else {
+ mInitCheck = ERROR_UNSUPPORTED;
+ }
+}
+
+APacketSource::~APacketSource() {
+}
+
+status_t APacketSource::initCheck() const {
+ return mInitCheck;
+}
+
+sp<MetaData> APacketSource::getFormat() {
+ return mFormat;
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/APacketSource.h b/media/libstagefright/rtsp/APacketSource.h
new file mode 100644
index 0000000..530e537
--- /dev/null
+++ b/media/libstagefright/rtsp/APacketSource.h
@@ -0,0 +1,50 @@
+/*
+ * 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/MetaData.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ASessionDescription;
+
+struct APacketSource : public RefBase {
+ APacketSource(const sp<ASessionDescription> &sessionDesc, size_t index);
+
+ status_t initCheck() const;
+
+ virtual sp<MetaData> getFormat();
+
+protected:
+ virtual ~APacketSource();
+
+private:
+ status_t mInitCheck;
+
+ sp<MetaData> mFormat;
+
+ 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..a897c10
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPAssembler.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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::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;
+ }
+ }
+ }
+}
+
+// static
+void ARTPAssembler::CopyTimes(const sp<ABuffer> &to, const sp<ABuffer> &from) {
+ uint32_t rtpTime;
+ CHECK(from->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+ to->meta()->setInt32("rtp-time", rtpTime);
+
+ // Copy the seq number.
+ to->setInt32Data(from->int32Data());
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/ARTPAssembler.h b/media/libstagefright/rtsp/ARTPAssembler.h
new file mode 100644
index 0000000..70ea186
--- /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);
+ virtual void onByeReceived() = 0;
+
+protected:
+ virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source) = 0;
+ virtual void packetLost() = 0;
+
+ static void CopyTimes(const sp<ABuffer> &to, const sp<ABuffer> &from);
+
+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..44988a3
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -0,0 +1,674 @@
+/*
+ * 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 "ARTPConnection"
+#include <utils/Log.h>
+
+#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 <media/stagefright/foundation/hexdump.h>
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+namespace android {
+
+static const size_t kMaxUDPSize = 1500;
+
+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;
+ KeyedVector<uint32_t, sp<ARTPSource> > mSources;
+
+ int64_t mNumRTCPPacketsReceived;
+ int64_t mNumRTPPacketsReceived;
+ struct sockaddr_in mRemoteRTCPAddr;
+
+ bool mIsInjected;
+};
+
+ARTPConnection::ARTPConnection(uint32_t flags)
+ : mFlags(flags),
+ mPollEventPending(false),
+ mLastReceiverReportTimeUs(-1) {
+}
+
+ARTPConnection::~ARTPConnection() {
+}
+
+void ARTPConnection::addStream(
+ int rtpSocket, int rtcpSocket,
+ const sp<ASessionDescription> &sessionDesc,
+ size_t index,
+ const sp<AMessage> &notify,
+ bool injected) {
+ 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->setInt32("injected", injected);
+ 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 = htonl(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;
+ }
+
+ case kWhatInjectPacket:
+ {
+ onInjectPacket(msg);
+ 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;
+
+ int32_t injected;
+ CHECK(msg->findInt32("injected", &injected));
+
+ info->mIsInjected = injected;
+
+ 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));
+
+ info->mNumRTCPPacketsReceived = 0;
+ info->mNumRTPPacketsReceived = 0;
+ memset(&info->mRemoteRTCPAddr, 0, sizeof(info->mRemoteRTCPAddr));
+
+ if (!injected) {
+ 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()) {
+ return;
+ }
+
+ 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) {
+ if ((*it).mIsInjected) {
+ continue;
+ }
+
+ FD_SET(it->mRTPSocket, &rs);
+ FD_SET(it->mRTCPSocket, &rs);
+
+ if (it->mRTPSocket > maxSocket) {
+ maxSocket = it->mRTPSocket;
+ }
+ if (it->mRTCPSocket > maxSocket) {
+ maxSocket = it->mRTCPSocket;
+ }
+ }
+
+ if (maxSocket == -1) {
+ return;
+ }
+
+ int res = select(maxSocket + 1, &rs, NULL, NULL, &tv);
+
+ if (res > 0) {
+ List<StreamInfo>::iterator it = mStreams.begin();
+ while (it != mStreams.end()) {
+ if ((*it).mIsInjected) {
+ ++it;
+ continue;
+ }
+
+ status_t err = OK;
+ if (FD_ISSET(it->mRTPSocket, &rs)) {
+ err = receive(&*it, true);
+ }
+ if (err == OK && FD_ISSET(it->mRTCPSocket, &rs)) {
+ err = receive(&*it, false);
+ }
+
+ if (err == -ECONNRESET) {
+ // socket failure, this stream is dead, Jim.
+
+ ALOGW("failed to receive RTP/RTCP datagram.");
+ it = mStreams.erase(it);
+ continue;
+ }
+
+ ++it;
+ }
+ }
+
+ int64_t nowUs = ALooper::GetNowUs();
+ if (mLastReceiverReportTimeUs <= 0
+ || mLastReceiverReportTimeUs + 5000000ll <= nowUs) {
+ sp<ABuffer> buffer = new ABuffer(kMaxUDPSize);
+ List<StreamInfo>::iterator it = mStreams.begin();
+ while (it != mStreams.end()) {
+ StreamInfo *s = &*it;
+
+ if (s->mIsInjected) {
+ ++it;
+ continue;
+ }
+
+ if (s->mNumRTCPPacketsReceived == 0) {
+ // We have never received any RTCP packets on this stream,
+ // we don't even know where to send a report.
+ ++it;
+ continue;
+ }
+
+ buffer->setRange(0, 0);
+
+ for (size_t i = 0; i < s->mSources.size(); ++i) {
+ sp<ARTPSource> source = s->mSources.valueAt(i);
+
+ source->addReceiverReport(buffer);
+
+ if (mFlags & kRegularlyRequestFIR) {
+ source->addFIR(buffer);
+ }
+ }
+
+ if (buffer->size() > 0) {
+ ALOGV("Sending RR...");
+
+ ssize_t n;
+ do {
+ n = sendto(
+ s->mRTCPSocket, buffer->data(), buffer->size(), 0,
+ (const struct sockaddr *)&s->mRemoteRTCPAddr,
+ sizeof(s->mRemoteRTCPAddr));
+ } while (n < 0 && errno == EINTR);
+
+ if (n <= 0) {
+ ALOGW("failed to send RTCP receiver report (%s).",
+ n == 0 ? "connection gone" : strerror(errno));
+
+ it = mStreams.erase(it);
+ continue;
+ }
+
+ CHECK_EQ(n, (ssize_t)buffer->size());
+
+ mLastReceiverReportTimeUs = nowUs;
+ }
+
+ ++it;
+ }
+ }
+
+ if (!mStreams.empty()) {
+ postPollEvent();
+ }
+}
+
+status_t ARTPConnection::receive(StreamInfo *s, bool receiveRTP) {
+ ALOGV("receiving %s", receiveRTP ? "RTP" : "RTCP");
+
+ CHECK(!s->mIsInjected);
+
+ sp<ABuffer> buffer = new ABuffer(65536);
+
+ socklen_t remoteAddrLen =
+ (!receiveRTP && s->mNumRTCPPacketsReceived == 0)
+ ? sizeof(s->mRemoteRTCPAddr) : 0;
+
+ ssize_t nbytes;
+ do {
+ nbytes = recvfrom(
+ receiveRTP ? s->mRTPSocket : s->mRTCPSocket,
+ buffer->data(),
+ buffer->capacity(),
+ 0,
+ remoteAddrLen > 0 ? (struct sockaddr *)&s->mRemoteRTCPAddr : NULL,
+ remoteAddrLen > 0 ? &remoteAddrLen : NULL);
+ } while (nbytes < 0 && errno == EINTR);
+
+ if (nbytes <= 0) {
+ return -ECONNRESET;
+ }
+
+ buffer->setRange(0, nbytes);
+
+ // ALOGI("received %d bytes.", buffer->size());
+
+ 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) {
+ if (s->mNumRTPPacketsReceived++ == 0) {
+ sp<AMessage> notify = s->mNotifyMsg->dup();
+ notify->setInt32("first-rtp", true);
+ notify->post();
+ }
+
+ 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 = findSource(s, srcId);
+
+ 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]));
+ buffer->setRange(payloadOffset, size - payloadOffset);
+
+ source->processRTPPacket(buffer);
+
+ return OK;
+}
+
+status_t ARTPConnection::parseRTCP(StreamInfo *s, const sp<ABuffer> &buffer) {
+ if (s->mNumRTCPPacketsReceived++ == 0) {
+ sp<AMessage> notify = s->mNotifyMsg->dup();
+ notify->setInt32("first-rtcp", true);
+ notify->post();
+ }
+
+ 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;
+ }
+
+ case 201: // RR
+ case 202: // SDES
+ case 204: // APP
+ break;
+
+ case 205: // TSFB (transport layer specific feedback)
+ case 206: // PSFB (payload specific feedback)
+ // hexdump(data, headerLength);
+ break;
+
+ case 203:
+ {
+ parseBYE(s, data, headerLength);
+ break;
+ }
+
+ default:
+ {
+ ALOGW("Unknown RTCP packet type %u of size %d",
+ (unsigned)data[1], headerLength);
+ break;
+ }
+ }
+
+ data += headerLength;
+ size -= headerLength;
+ }
+
+ return OK;
+}
+
+status_t ARTPConnection::parseBYE(
+ StreamInfo *s, const uint8_t *data, size_t size) {
+ size_t SC = data[0] & 0x3f;
+
+ if (SC == 0 || size < (4 + SC * 4)) {
+ // Packet too short for the minimal BYE header.
+ return -1;
+ }
+
+ uint32_t id = u32at(&data[4]);
+
+ sp<ARTPSource> source = findSource(s, id);
+
+ source->byeReceived();
+
+ 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 0
+ ALOGI("XXX timeUpdate: ssrc=0x%08x, rtpTime %u == ntpTime %.3f",
+ id,
+ rtpTime,
+ (ntpTime >> 32) + (double)(ntpTime & 0xffffffff) / (1ll << 32));
+#endif
+
+ sp<ARTPSource> source = findSource(s, id);
+
+ source->timeUpdate(rtpTime, ntpTime);
+
+ return 0;
+}
+
+sp<ARTPSource> ARTPConnection::findSource(StreamInfo *info, uint32_t srcId) {
+ sp<ARTPSource> source;
+ ssize_t index = info->mSources.indexOfKey(srcId);
+ if (index < 0) {
+ index = info->mSources.size();
+
+ source = new ARTPSource(
+ srcId, info->mSessionDesc, info->mIndex, info->mNotifyMsg);
+
+ info->mSources.add(srcId, source);
+ } else {
+ source = info->mSources.valueAt(index);
+ }
+
+ return source;
+}
+
+void ARTPConnection::injectPacket(int index, const sp<ABuffer> &buffer) {
+ sp<AMessage> msg = new AMessage(kWhatInjectPacket, id());
+ msg->setInt32("index", index);
+ msg->setBuffer("buffer", buffer);
+ msg->post();
+}
+
+void ARTPConnection::onInjectPacket(const sp<AMessage> &msg) {
+ int32_t index;
+ CHECK(msg->findInt32("index", &index));
+
+ sp<ABuffer> buffer;
+ CHECK(msg->findBuffer("buffer", &buffer));
+
+ List<StreamInfo>::iterator it = mStreams.begin();
+ while (it != mStreams.end()
+ && it->mRTPSocket != index && it->mRTCPSocket != index) {
+ ++it;
+ }
+
+ if (it == mStreams.end()) {
+ TRESPASS();
+ }
+
+ StreamInfo *s = &*it;
+
+ status_t err;
+ if (it->mRTPSocket == index) {
+ err = parseRTP(s, buffer);
+ } else {
+ err = parseRTCP(s, buffer);
+ }
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/rtsp/ARTPConnection.h b/media/libstagefright/rtsp/ARTPConnection.h
new file mode 100644
index 0000000..edbcc35
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPConnection.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_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 {
+ enum Flags {
+ kRegularlyRequestFIR = 2,
+ };
+
+ ARTPConnection(uint32_t flags = 0);
+
+ void addStream(
+ int rtpSocket, int rtcpSocket,
+ const sp<ASessionDescription> &sessionDesc, size_t index,
+ const sp<AMessage> &notify,
+ bool injected);
+
+ void removeStream(int rtpSocket, int rtcpSocket);
+
+ void injectPacket(int index, const sp<ABuffer> &buffer);
+
+ // 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,
+ kWhatInjectPacket,
+ };
+
+ static const int64_t kSelectTimeoutUs;
+
+ uint32_t mFlags;
+
+ struct StreamInfo;
+ List<StreamInfo> mStreams;
+
+ bool mPollEventPending;
+ int64_t mLastReceiverReportTimeUs;
+
+ void onAddStream(const sp<AMessage> &msg);
+ void onRemoveStream(const sp<AMessage> &msg);
+ void onPollStreams();
+ void onInjectPacket(const sp<AMessage> &msg);
+ void onSendReceiverReports();
+
+ 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);
+ status_t parseBYE(StreamInfo *info, const uint8_t *data, size_t size);
+
+ sp<ARTPSource> findSource(StreamInfo *info, uint32_t id);
+
+ void postPollEvent();
+
+ DISALLOW_EVIL_CONSTRUCTORS(ARTPConnection);
+};
+
+} // namespace android
+
+#endif // A_RTP_CONNECTION_H_
diff --git a/media/libstagefright/rtsp/ARTPSession.cpp b/media/libstagefright/rtsp/ARTPSession.cpp
new file mode 100644
index 0000000..ba4e33c
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPSession.cpp
@@ -0,0 +1,242 @@
+/*
+ * 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 "ARTPSession"
+#include <utils/Log.h>
+
+#include "ARTPSession.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 <ctype.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#include "APacketSource.h"
+#include "ARTPConnection.h"
+#include "ASessionDescription.h"
+
+namespace android {
+
+ARTPSession::ARTPSession()
+ : mInitCheck(NO_INIT) {
+}
+
+status_t ARTPSession::setup(const sp<ASessionDescription> &desc) {
+ CHECK_EQ(mInitCheck, (status_t)NO_INIT);
+
+ mDesc = desc;
+
+ mRTPConn = new ARTPConnection(ARTPConnection::kRegularlyRequestFIR);
+
+ looper()->registerHandler(mRTPConn);
+
+ for (size_t i = 1; i < mDesc->countTracks(); ++i) {
+ AString connection;
+ if (!mDesc->findAttribute(i, "c=", &connection)) {
+ // No per-stream connection information, try global fallback.
+ if (!mDesc->findAttribute(0, "c=", &connection)) {
+ ALOGE("Unable to find connection attribute.");
+ return mInitCheck;
+ }
+ }
+ if (!(connection == "IN IP4 127.0.0.1")) {
+ ALOGE("We only support localhost connections for now.");
+ return mInitCheck;
+ }
+
+ unsigned port;
+ if (!validateMediaFormat(i, &port) || (port & 1) != 0) {
+ ALOGE("Invalid media format.");
+ return mInitCheck;
+ }
+
+ sp<APacketSource> source = new APacketSource(mDesc, i);
+ if (source->initCheck() != OK) {
+ ALOGE("Unsupported format.");
+ return mInitCheck;
+ }
+
+ int rtpSocket = MakeUDPSocket(port);
+ int rtcpSocket = MakeUDPSocket(port + 1);
+
+ mTracks.push(TrackInfo());
+ TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1);
+ info->mRTPSocket = rtpSocket;
+ info->mRTCPSocket = rtcpSocket;
+
+ sp<AMessage> notify = new AMessage(kWhatAccessUnitComplete, id());
+ notify->setSize("track-index", mTracks.size() - 1);
+
+ mRTPConn->addStream(
+ rtpSocket, rtcpSocket, mDesc, i, notify, false /* injected */);
+
+ info->mPacketSource = source;
+ }
+
+ mInitCheck = OK;
+
+ return OK;
+}
+
+// static
+int ARTPSession::MakeUDPSocket(unsigned port) {
+ int s = socket(AF_INET, SOCK_DGRAM, 0);
+ CHECK_GE(s, 0);
+
+ 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);
+
+ CHECK_EQ(0, bind(s, (const struct sockaddr *)&addr, sizeof(addr)));
+
+ return s;
+}
+
+ARTPSession::~ARTPSession() {
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ TrackInfo *info = &mTracks.editItemAt(i);
+
+ info->mPacketSource->signalEOS(UNKNOWN_ERROR);
+
+ close(info->mRTPSocket);
+ close(info->mRTCPSocket);
+ }
+}
+
+void ARTPSession::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatAccessUnitComplete:
+ {
+ int32_t firstRTCP;
+ if (msg->findInt32("first-rtcp", &firstRTCP)) {
+ // There won't be an access unit here, it's just a notification
+ // that the data communication worked since we got the first
+ // rtcp packet.
+ break;
+ }
+
+ size_t trackIndex;
+ CHECK(msg->findSize("track-index", &trackIndex));
+
+ int32_t eos;
+ if (msg->findInt32("eos", &eos) && eos) {
+ TrackInfo *info = &mTracks.editItemAt(trackIndex);
+ info->mPacketSource->signalEOS(ERROR_END_OF_STREAM);
+ break;
+ }
+
+ sp<ABuffer> accessUnit;
+ CHECK(msg->findBuffer("access-unit", &accessUnit));
+
+ uint64_t ntpTime;
+ CHECK(accessUnit->meta()->findInt64(
+ "ntp-time", (int64_t *)&ntpTime));
+
+#if 0
+#if 0
+ printf("access unit complete size=%d\tntp-time=0x%016llx\n",
+ accessUnit->size(), ntpTime);
+#else
+ ALOGI("access unit complete, size=%d, ntp-time=%llu",
+ accessUnit->size(), ntpTime);
+ hexdump(accessUnit->data(), accessUnit->size());
+#endif
+#endif
+
+#if 0
+ CHECK_GE(accessUnit->size(), 5u);
+ CHECK(!memcmp("\x00\x00\x00\x01", accessUnit->data(), 4));
+ unsigned x = accessUnit->data()[4];
+
+ ALOGI("access unit complete: nalType=0x%02x, nalRefIdc=0x%02x",
+ x & 0x1f, (x & 0x60) >> 5);
+#endif
+
+ accessUnit->meta()->setInt64("ntp-time", ntpTime);
+ accessUnit->meta()->setInt64("timeUs", 0);
+
+#if 0
+ int32_t damaged;
+ if (accessUnit->meta()->findInt32("damaged", &damaged)
+ && damaged != 0) {
+ ALOGI("ignoring damaged AU");
+ } else
+#endif
+ {
+ TrackInfo *info = &mTracks.editItemAt(trackIndex);
+ info->mPacketSource->queueAccessUnit(accessUnit);
+ }
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+bool ARTPSession::validateMediaFormat(size_t index, unsigned *port) const {
+ AString format;
+ mDesc->getFormat(index, &format);
+
+ ssize_t i = format.find(" ");
+ if (i < 0) {
+ return false;
+ }
+
+ ++i;
+ size_t j = i;
+ while (isdigit(format.c_str()[j])) {
+ ++j;
+ }
+ if (format.c_str()[j] != ' ') {
+ return false;
+ }
+
+ AString portString(format, i, j - i);
+
+ char *end;
+ unsigned long x = strtoul(portString.c_str(), &end, 10);
+ if (end == portString.c_str() || *end != '\0') {
+ return false;
+ }
+
+ if (x == 0 || x > 65535) {
+ return false;
+ }
+
+ *port = x;
+
+ return true;
+}
+
+size_t ARTPSession::countTracks() {
+ return mTracks.size();
+}
+
+sp<MediaSource> ARTPSession::trackAt(size_t index) {
+ CHECK_LT(index, mTracks.size());
+ return mTracks.editItemAt(index).mPacketSource;
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/ARTPSession.h b/media/libstagefright/rtsp/ARTPSession.h
new file mode 100644
index 0000000..9bff74c
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPSession.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 A_RTP_SESSION_H_
+
+#define A_RTP_SESSION_H_
+
+#include <media/stagefright/foundation/AHandler.h>
+
+namespace android {
+
+struct APacketSource;
+struct ARTPConnection;
+struct ASessionDescription;
+struct MediaSource;
+
+struct ARTPSession : public AHandler {
+ ARTPSession();
+
+ status_t setup(const sp<ASessionDescription> &desc);
+
+ size_t countTracks();
+ sp<MediaSource> trackAt(size_t index);
+
+protected:
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+ virtual ~ARTPSession();
+
+private:
+ enum {
+ kWhatAccessUnitComplete = 'accu'
+ };
+
+ struct TrackInfo {
+ int mRTPSocket;
+ int mRTCPSocket;
+
+ sp<APacketSource> mPacketSource;
+ };
+
+ status_t mInitCheck;
+ sp<ASessionDescription> mDesc;
+ sp<ARTPConnection> mRTPConn;
+
+ Vector<TrackInfo> mTracks;
+
+ bool validateMediaFormat(size_t index, unsigned *port) const;
+ static int MakeUDPSocket(unsigned port);
+
+ DISALLOW_EVIL_CONSTRUCTORS(ARTPSession);
+};
+
+} // namespace android
+
+#endif // A_RTP_SESSION_H_
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
new file mode 100644
index 0000000..ed68790
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -0,0 +1,275 @@
+/*
+ * 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 "ARTPSource"
+#include <utils/Log.h>
+
+#include "ARTPSource.h"
+
+#include "AAMRAssembler.h"
+#include "AAVCAssembler.h"
+#include "AH263Assembler.h"
+#include "AMPEG4AudioAssembler.h"
+#include "AMPEG4ElementaryAssembler.h"
+#include "ARawAudioAssembler.h"
+#include "ASessionDescription.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+namespace android {
+
+static const uint32_t kSourceID = 0xdeadbeef;
+
+ARTPSource::ARTPSource(
+ uint32_t id,
+ const sp<ASessionDescription> &sessionDesc, size_t index,
+ const sp<AMessage> &notify)
+ : mID(id),
+ mHighestSeqNumber(0),
+ mNumBuffersReceived(0),
+ mLastNTPTime(0),
+ mLastNTPTimeUpdateUs(0),
+ mIssueFIRRequests(false),
+ mLastFIRRequestUs(-1),
+ mNextFIRSeqNo((rand() * 256.0) / RAND_MAX),
+ mNotify(notify) {
+ unsigned long PT;
+ AString desc;
+ AString params;
+ sessionDesc->getFormatType(index, &PT, &desc, &params);
+
+ if (!strncmp(desc.c_str(), "H264/", 5)) {
+ mAssembler = new AAVCAssembler(notify);
+ mIssueFIRRequests = true;
+ } else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) {
+ mAssembler = new AMPEG4AudioAssembler(notify, params);
+ } else if (!strncmp(desc.c_str(), "H263-1998/", 10)
+ || !strncmp(desc.c_str(), "H263-2000/", 10)) {
+ mAssembler = new AH263Assembler(notify);
+ mIssueFIRRequests = true;
+ } else if (!strncmp(desc.c_str(), "AMR/", 4)) {
+ mAssembler = new AAMRAssembler(notify, false /* isWide */, params);
+ } else if (!strncmp(desc.c_str(), "AMR-WB/", 7)) {
+ mAssembler = new AAMRAssembler(notify, true /* isWide */, params);
+ } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)
+ || !strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) {
+ mAssembler = new AMPEG4ElementaryAssembler(notify, desc, params);
+ mIssueFIRRequests = true;
+ } else if (ARawAudioAssembler::Supports(desc.c_str())) {
+ mAssembler = new ARawAudioAssembler(notify, desc.c_str(), params);
+ } 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) && mAssembler != NULL) {
+ mAssembler->onPacketReceived(this);
+ }
+}
+
+void ARTPSource::timeUpdate(uint32_t rtpTime, uint64_t ntpTime) {
+ mLastNTPTime = ntpTime;
+ mLastNTPTimeUpdateUs = ALooper::GetNowUs();
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("time-update", true);
+ notify->setInt32("rtp-time", rtpTime);
+ notify->setInt64("ntp-time", ntpTime);
+ notify->post();
+}
+
+bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
+ uint32_t seqNum = (uint32_t)buffer->int32Data();
+
+ 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) {
+ ALOGW("Discarding duplicate buffer");
+ return false;
+ }
+
+ mQueue.insert(it, buffer);
+
+ return true;
+}
+
+void ARTPSource::byeReceived() {
+ mAssembler->onByeReceived();
+}
+
+void ARTPSource::addFIR(const sp<ABuffer> &buffer) {
+ if (!mIssueFIRRequests) {
+ return;
+ }
+
+ int64_t nowUs = ALooper::GetNowUs();
+ if (mLastFIRRequestUs >= 0 && mLastFIRRequestUs + 5000000ll > nowUs) {
+ // Send FIR requests at most every 5 secs.
+ return;
+ }
+
+ mLastFIRRequestUs = nowUs;
+
+ if (buffer->size() + 20 > buffer->capacity()) {
+ ALOGW("RTCP buffer too small to accomodate FIR.");
+ return;
+ }
+
+ uint8_t *data = buffer->data() + buffer->size();
+
+ data[0] = 0x80 | 4;
+ data[1] = 206; // PSFB
+ data[2] = 0;
+ data[3] = 4;
+ data[4] = kSourceID >> 24;
+ data[5] = (kSourceID >> 16) & 0xff;
+ data[6] = (kSourceID >> 8) & 0xff;
+ data[7] = kSourceID & 0xff;
+
+ data[8] = 0x00; // SSRC of media source (unused)
+ data[9] = 0x00;
+ data[10] = 0x00;
+ data[11] = 0x00;
+
+ data[12] = mID >> 24;
+ data[13] = (mID >> 16) & 0xff;
+ data[14] = (mID >> 8) & 0xff;
+ data[15] = mID & 0xff;
+
+ data[16] = mNextFIRSeqNo++; // Seq Nr.
+
+ data[17] = 0x00; // Reserved
+ data[18] = 0x00;
+ data[19] = 0x00;
+
+ buffer->setRange(buffer->offset(), buffer->size() + 20);
+
+ ALOGV("Added FIR request.");
+}
+
+void ARTPSource::addReceiverReport(const sp<ABuffer> &buffer) {
+ if (buffer->size() + 32 > buffer->capacity()) {
+ ALOGW("RTCP buffer too small to accomodate RR.");
+ return;
+ }
+
+ uint8_t *data = buffer->data() + buffer->size();
+
+ data[0] = 0x80 | 1;
+ data[1] = 201; // RR
+ data[2] = 0;
+ data[3] = 7;
+ data[4] = kSourceID >> 24;
+ data[5] = (kSourceID >> 16) & 0xff;
+ data[6] = (kSourceID >> 8) & 0xff;
+ data[7] = kSourceID & 0xff;
+
+ data[8] = mID >> 24;
+ data[9] = (mID >> 16) & 0xff;
+ data[10] = (mID >> 8) & 0xff;
+ data[11] = mID & 0xff;
+
+ data[12] = 0x00; // fraction lost
+
+ data[13] = 0x00; // cumulative lost
+ data[14] = 0x00;
+ data[15] = 0x00;
+
+ data[16] = mHighestSeqNumber >> 24;
+ data[17] = (mHighestSeqNumber >> 16) & 0xff;
+ data[18] = (mHighestSeqNumber >> 8) & 0xff;
+ data[19] = mHighestSeqNumber & 0xff;
+
+ data[20] = 0x00; // Interarrival jitter
+ data[21] = 0x00;
+ data[22] = 0x00;
+ data[23] = 0x00;
+
+ uint32_t LSR = 0;
+ uint32_t DLSR = 0;
+ if (mLastNTPTime != 0) {
+ LSR = (mLastNTPTime >> 16) & 0xffffffff;
+
+ DLSR = (uint32_t)
+ ((ALooper::GetNowUs() - mLastNTPTimeUpdateUs) * 65536.0 / 1E6);
+ }
+
+ data[24] = LSR >> 24;
+ data[25] = (LSR >> 16) & 0xff;
+ data[26] = (LSR >> 8) & 0xff;
+ data[27] = LSR & 0xff;
+
+ data[28] = DLSR >> 24;
+ data[29] = (DLSR >> 16) & 0xff;
+ data[30] = (DLSR >> 8) & 0xff;
+ data[31] = DLSR & 0xff;
+
+ buffer->setRange(buffer->offset(), buffer->size() + 32);
+}
+
+} // namespace android
+
+
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
new file mode 100644
index 0000000..b70f94e
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -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.
+ */
+
+#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);
+ void byeReceived();
+
+ List<sp<ABuffer> > *queue() { return &mQueue; }
+
+ void addReceiverReport(const sp<ABuffer> &buffer);
+ void addFIR(const sp<ABuffer> &buffer);
+
+private:
+ uint32_t mID;
+ uint32_t mHighestSeqNumber;
+ int32_t mNumBuffersReceived;
+
+ List<sp<ABuffer> > mQueue;
+ sp<ARTPAssembler> mAssembler;
+
+ uint64_t mLastNTPTime;
+ int64_t mLastNTPTimeUpdateUs;
+
+ bool mIssueFIRRequests;
+ int64_t mLastFIRRequestUs;
+ uint8_t mNextFIRSeqNo;
+
+ sp<AMessage> mNotify;
+
+ bool queuePacket(const sp<ABuffer> &buffer);
+
+ DISALLOW_EVIL_CONSTRUCTORS(ARTPSource);
+};
+
+} // namespace android
+
+#endif // A_RTP_SOURCE_H_
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
new file mode 100644
index 0000000..0d07043
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -0,0 +1,836 @@
+/*
+ * 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 "ARTPWriter"
+#include <utils/Log.h>
+
+#include "ARTPWriter.h"
+
+#include <fcntl.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/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/ByteOrder.h>
+
+#define PT 97
+#define PT_STR "97"
+
+namespace android {
+
+// static const size_t kMaxPacketSize = 65507; // maximum payload in UDP over IP
+static const size_t kMaxPacketSize = 1500;
+
+static int UniformRand(int limit) {
+ return ((double)rand() * limit) / RAND_MAX;
+}
+
+ARTPWriter::ARTPWriter(int fd)
+ : mFlags(0),
+ mFd(dup(fd)),
+ mLooper(new ALooper),
+ mReflector(new AHandlerReflector<ARTPWriter>(this)) {
+ CHECK_GE(fd, 0);
+
+ mLooper->setName("rtp writer");
+ mLooper->registerHandler(mReflector);
+ mLooper->start();
+
+ mSocket = socket(AF_INET, SOCK_DGRAM, 0);
+ CHECK_GE(mSocket, 0);
+
+ memset(mRTPAddr.sin_zero, 0, sizeof(mRTPAddr.sin_zero));
+ mRTPAddr.sin_family = AF_INET;
+
+#if 1
+ mRTPAddr.sin_addr.s_addr = INADDR_ANY;
+#else
+ mRTPAddr.sin_addr.s_addr = inet_addr("172.19.18.246");
+#endif
+
+ mRTPAddr.sin_port = htons(5634);
+ CHECK_EQ(0, ntohs(mRTPAddr.sin_port) & 1);
+
+ mRTCPAddr = mRTPAddr;
+ mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1);
+
+#if LOG_TO_FILES
+ mRTPFd = open(
+ "/data/misc/rtpout.bin",
+ O_WRONLY | O_CREAT | O_TRUNC,
+ 0644);
+ CHECK_GE(mRTPFd, 0);
+
+ mRTCPFd = open(
+ "/data/misc/rtcpout.bin",
+ O_WRONLY | O_CREAT | O_TRUNC,
+ 0644);
+ CHECK_GE(mRTCPFd, 0);
+#endif
+}
+
+ARTPWriter::~ARTPWriter() {
+#if LOG_TO_FILES
+ close(mRTCPFd);
+ mRTCPFd = -1;
+
+ close(mRTPFd);
+ mRTPFd = -1;
+#endif
+
+ close(mSocket);
+ mSocket = -1;
+
+ close(mFd);
+ mFd = -1;
+}
+
+status_t ARTPWriter::addSource(const sp<MediaSource> &source) {
+ mSource = source;
+ return OK;
+}
+
+bool ARTPWriter::reachedEOS() {
+ Mutex::Autolock autoLock(mLock);
+ return (mFlags & kFlagEOS) != 0;
+}
+
+status_t ARTPWriter::start(MetaData *params) {
+ Mutex::Autolock autoLock(mLock);
+ if (mFlags & kFlagStarted) {
+ return INVALID_OPERATION;
+ }
+
+ mFlags &= ~kFlagEOS;
+ mSourceID = rand();
+ mSeqNo = UniformRand(65536);
+ mRTPTimeBase = rand();
+ mNumRTPSent = 0;
+ mNumRTPOctetsSent = 0;
+ mLastRTPTime = 0;
+ mLastNTPTime = 0;
+ mNumSRsSent = 0;
+
+ const char *mime;
+ CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
+
+ mMode = INVALID;
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ mMode = H264;
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) {
+ mMode = H263;
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
+ mMode = AMR_NB;
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
+ mMode = AMR_WB;
+ } else {
+ TRESPASS();
+ }
+
+ (new AMessage(kWhatStart, mReflector->id()))->post();
+
+ while (!(mFlags & kFlagStarted)) {
+ mCondition.wait(mLock);
+ }
+
+ return OK;
+}
+
+status_t ARTPWriter::stop() {
+ Mutex::Autolock autoLock(mLock);
+ if (!(mFlags & kFlagStarted)) {
+ return OK;
+ }
+
+ (new AMessage(kWhatStop, mReflector->id()))->post();
+
+ while (mFlags & kFlagStarted) {
+ mCondition.wait(mLock);
+ }
+ return OK;
+}
+
+status_t ARTPWriter::pause() {
+ return OK;
+}
+
+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);
+ }
+}
+
+void ARTPWriter::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatStart:
+ {
+ CHECK_EQ(mSource->start(), (status_t)OK);
+
+#if 0
+ if (mMode == H264) {
+ MediaBuffer *buffer;
+ CHECK_EQ(mSource->read(&buffer), (status_t)OK);
+
+ StripStartcode(buffer);
+ makeH264SPropParamSets(buffer);
+ buffer->release();
+ buffer = NULL;
+ }
+
+ dumpSessionDesc();
+#endif
+
+ {
+ Mutex::Autolock autoLock(mLock);
+ mFlags |= kFlagStarted;
+ mCondition.signal();
+ }
+
+ (new AMessage(kWhatRead, mReflector->id()))->post();
+ (new AMessage(kWhatSendSR, mReflector->id()))->post();
+ break;
+ }
+
+ case kWhatStop:
+ {
+ CHECK_EQ(mSource->stop(), (status_t)OK);
+
+ sendBye();
+
+ {
+ Mutex::Autolock autoLock(mLock);
+ mFlags &= ~kFlagStarted;
+ mCondition.signal();
+ }
+ break;
+ }
+
+ case kWhatRead:
+ {
+ {
+ Mutex::Autolock autoLock(mLock);
+ if (!(mFlags & kFlagStarted)) {
+ break;
+ }
+ }
+
+ onRead(msg);
+ break;
+ }
+
+ case kWhatSendSR:
+ {
+ {
+ Mutex::Autolock autoLock(mLock);
+ if (!(mFlags & kFlagStarted)) {
+ break;
+ }
+ }
+
+ onSendSR(msg);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+void ARTPWriter::onRead(const sp<AMessage> &msg) {
+ MediaBuffer *mediaBuf;
+ status_t err = mSource->read(&mediaBuf);
+
+ if (err != OK) {
+ ALOGI("reached EOS.");
+
+ Mutex::Autolock autoLock(mLock);
+ mFlags |= kFlagEOS;
+ return;
+ }
+
+ if (mediaBuf->range_length() > 0) {
+ ALOGV("read buffer of size %d", mediaBuf->range_length());
+
+ if (mMode == H264) {
+ StripStartcode(mediaBuf);
+ sendAVCData(mediaBuf);
+ } else if (mMode == H263) {
+ sendH263Data(mediaBuf);
+ } else if (mMode == AMR_NB || mMode == AMR_WB) {
+ sendAMRData(mediaBuf);
+ }
+ }
+
+ mediaBuf->release();
+ mediaBuf = NULL;
+
+ msg->post();
+}
+
+void ARTPWriter::onSendSR(const sp<AMessage> &msg) {
+ sp<ABuffer> buffer = new ABuffer(65536);
+ buffer->setRange(0, 0);
+
+ addSR(buffer);
+ addSDES(buffer);
+
+ send(buffer, true /* isRTCP */);
+
+ ++mNumSRsSent;
+ msg->post(3000000);
+}
+
+void ARTPWriter::send(const sp<ABuffer> &buffer, bool isRTCP) {
+ ssize_t n = sendto(
+ mSocket, buffer->data(), buffer->size(), 0,
+ (const struct sockaddr *)(isRTCP ? &mRTCPAddr : &mRTPAddr),
+ sizeof(mRTCPAddr));
+
+ CHECK_EQ(n, (ssize_t)buffer->size());
+
+#if LOG_TO_FILES
+ int fd = isRTCP ? mRTCPFd : mRTPFd;
+
+ uint32_t ms = tolel(ALooper::GetNowUs() / 1000ll);
+ uint32_t length = tolel(buffer->size());
+ write(fd, &ms, sizeof(ms));
+ write(fd, &length, sizeof(length));
+ write(fd, buffer->data(), buffer->size());
+#endif
+}
+
+void ARTPWriter::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 ARTPWriter::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 = "someone@somewhere";
+ 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);
+}
+
+// static
+uint64_t ARTPWriter::GetNowNTP() {
+ uint64_t nowUs = ALooper::GetNowUs();
+
+ 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 ARTPWriter::dumpSessionDesc() {
+ AString sdp;
+ sdp = "v=0\r\n";
+
+ sdp.append("o=- ");
+
+ uint64_t ntp = GetNowNTP();
+ 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\r\n"
+ "c=IN IP4 ");
+
+ struct in_addr addr;
+ addr.s_addr = ntohl(INADDR_LOOPBACK);
+
+ sdp.append(inet_ntoa(addr));
+
+ sdp.append(
+ "\r\n"
+ "t=0 0\r\n"
+ "a=range:npt=now-\r\n");
+
+ sp<MetaData> meta = mSource->getFormat();
+
+ if (mMode == H264 || mMode == H263) {
+ sdp.append("m=video ");
+ } else {
+ sdp.append("m=audio ");
+ }
+
+ sdp.append(StringPrintf("%d", ntohs(mRTPAddr.sin_port)));
+ sdp.append(
+ " RTP/AVP " PT_STR "\r\n"
+ "b=AS 320000\r\n"
+ "a=rtpmap:" PT_STR " ");
+
+ if (mMode == H264) {
+ sdp.append("H264/90000");
+ } else if (mMode == H263) {
+ sdp.append("H263-1998/90000");
+ } else if (mMode == AMR_NB || mMode == AMR_WB) {
+ int32_t sampleRate, numChannels;
+ CHECK(mSource->getFormat()->findInt32(kKeySampleRate, &sampleRate));
+ CHECK(mSource->getFormat()->findInt32(kKeyChannelCount, &numChannels));
+
+ CHECK_EQ(numChannels, 1);
+ CHECK_EQ(sampleRate, (mMode == AMR_NB) ? 8000 : 16000);
+
+ sdp.append(mMode == AMR_NB ? "AMR" : "AMR-WB");
+ sdp.append(StringPrintf("/%d/%d", sampleRate, numChannels));
+ } else {
+ TRESPASS();
+ }
+
+ sdp.append("\r\n");
+
+ if (mMode == H264 || mMode == H263) {
+ int32_t width, height;
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+
+ 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");
+ }
+
+ if (mMode == H264) {
+ sdp.append(
+ "a=fmtp:" PT_STR " profile-level-id=");
+ sdp.append(mProfileLevel);
+ sdp.append(";sprop-parameter-sets=");
+
+ sdp.append(mSeqParamSet);
+ sdp.append(",");
+ sdp.append(mPicParamSet);
+ sdp.append(";packetization-mode=1\r\n");
+ } else if (mMode == AMR_NB || mMode == AMR_WB) {
+ sdp.append("a=fmtp:" PT_STR " octed-align\r\n");
+ }
+
+ ALOGI("%s", sdp.c_str());
+}
+
+void ARTPWriter::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);
+
+ size_t startCodePos = 0;
+ while (startCodePos + 3 < size
+ && memcmp(kStartCode, &data[startCodePos], 4)) {
+ ++startCodePos;
+ }
+
+ CHECK_LT(startCodePos + 3, size);
+
+ CHECK_EQ((unsigned)data[0], 0x67u);
+
+ mProfileLevel =
+ StringPrintf("%02X%02X%02X", data[1], data[2], data[3]);
+
+ encodeBase64(data, startCodePos, &mSeqParamSet);
+
+ encodeBase64(&data[startCodePos + 4], size - startCodePos - 4,
+ &mPicParamSet);
+}
+
+void ARTPWriter::sendBye() {
+ sp<ABuffer> buffer = new ABuffer(8);
+ uint8_t *data = buffer->data();
+ *data++ = (2 << 6) | 1;
+ *data++ = 203;
+ *data++ = 0;
+ *data++ = 1;
+ *data++ = mSourceID >> 24;
+ *data++ = (mSourceID >> 16) & 0xff;
+ *data++ = (mSourceID >> 8) & 0xff;
+ *data++ = mSourceID & 0xff;
+ buffer->setRange(0, 8);
+
+ send(buffer, true /* isRTCP */);
+}
+
+void ARTPWriter::sendAVCData(MediaBuffer *mediaBuf) {
+ // 12 bytes RTP header + 2 bytes for the FU-indicator and FU-header.
+ CHECK_GE(kMaxPacketSize, 12u + 2u);
+
+ 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();
+
+ sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
+ if (mediaBuf->range_length() + 12 <= buffer->capacity()) {
+ // The data fits into a single packet
+ 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[4] = rtpTime >> 24;
+ data[5] = (rtpTime >> 16) & 0xff;
+ data[6] = (rtpTime >> 8) & 0xff;
+ data[7] = rtpTime & 0xff;
+ data[8] = mSourceID >> 24;
+ data[9] = (mSourceID >> 16) & 0xff;
+ data[10] = (mSourceID >> 8) & 0xff;
+ data[11] = mSourceID & 0xff;
+
+ memcpy(&data[12],
+ mediaData, mediaBuf->range_length());
+
+ buffer->setRange(0, mediaBuf->range_length() + 12);
+
+ send(buffer, false /* isRTCP */);
+
+ ++mSeqNo;
+ ++mNumRTPSent;
+ mNumRTPOctetsSent += buffer->size() - 12;
+ } else {
+ // FU-A
+
+ unsigned nalType = mediaData[0];
+ size_t offset = 1;
+
+ bool firstPacket = true;
+ while (offset < mediaBuf->range_length()) {
+ size_t size = mediaBuf->range_length() - offset;
+ bool lastPacket = true;
+ if (size + 12 + 2 > buffer->capacity()) {
+ lastPacket = false;
+ size = buffer->capacity() - 12 - 2;
+ }
+
+ uint8_t *data = buffer->data();
+ data[0] = 0x80;
+ data[1] = (lastPacket ? (1 << 7) : 0x00) | PT; // M-bit
+ data[2] = (mSeqNo >> 8) & 0xff;
+ data[3] = mSeqNo & 0xff;
+ data[4] = rtpTime >> 24;
+ data[5] = (rtpTime >> 16) & 0xff;
+ data[6] = (rtpTime >> 8) & 0xff;
+ data[7] = rtpTime & 0xff;
+ data[8] = mSourceID >> 24;
+ data[9] = (mSourceID >> 16) & 0xff;
+ data[10] = (mSourceID >> 8) & 0xff;
+ data[11] = mSourceID & 0xff;
+
+ data[12] = 28 | (nalType & 0xe0);
+
+ CHECK(!firstPacket || !lastPacket);
+
+ data[13] =
+ (firstPacket ? 0x80 : 0x00)
+ | (lastPacket ? 0x40 : 0x00)
+ | (nalType & 0x1f);
+
+ memcpy(&data[14], &mediaData[offset], size);
+
+ buffer->setRange(0, 14 + size);
+
+ send(buffer, false /* isRTCP */);
+
+ ++mSeqNo;
+ ++mNumRTPSent;
+ mNumRTPOctetsSent += buffer->size() - 12;
+
+ firstPacket = false;
+ offset += size;
+ }
+ }
+
+ mLastRTPTime = rtpTime;
+ mLastNTPTime = GetNowNTP();
+}
+
+void ARTPWriter::sendH263Data(MediaBuffer *mediaBuf) {
+ CHECK_GE(kMaxPacketSize, 12u + 2u);
+
+ 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();
+
+ // hexdump(mediaData, mediaBuf->range_length());
+
+ CHECK_EQ((unsigned)mediaData[0], 0u);
+ CHECK_EQ((unsigned)mediaData[1], 0u);
+
+ size_t offset = 2;
+ size_t size = mediaBuf->range_length();
+
+ while (offset < size) {
+ sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
+ // CHECK_LE(mediaBuf->range_length() -2 + 14, buffer->capacity());
+
+ size_t remaining = size - offset;
+ bool lastPacket = (remaining + 14 <= buffer->capacity());
+ if (!lastPacket) {
+ remaining = buffer->capacity() - 14;
+ }
+
+ uint8_t *data = buffer->data();
+ data[0] = 0x80;
+ data[1] = (lastPacket ? 0x80 : 0x00) | PT; // M-bit
+ data[2] = (mSeqNo >> 8) & 0xff;
+ data[3] = mSeqNo & 0xff;
+ data[4] = rtpTime >> 24;
+ data[5] = (rtpTime >> 16) & 0xff;
+ data[6] = (rtpTime >> 8) & 0xff;
+ data[7] = rtpTime & 0xff;
+ data[8] = mSourceID >> 24;
+ data[9] = (mSourceID >> 16) & 0xff;
+ data[10] = (mSourceID >> 8) & 0xff;
+ data[11] = mSourceID & 0xff;
+
+ data[12] = (offset == 2) ? 0x04 : 0x00; // P=?, V=0
+ data[13] = 0x00; // PLEN = PEBIT = 0
+
+ memcpy(&data[14], &mediaData[offset], remaining);
+ offset += remaining;
+
+ buffer->setRange(0, remaining + 14);
+
+ send(buffer, false /* isRTCP */);
+
+ ++mSeqNo;
+ ++mNumRTPSent;
+ mNumRTPOctetsSent += buffer->size() - 12;
+ }
+
+ mLastRTPTime = rtpTime;
+ mLastNTPTime = GetNowNTP();
+}
+
+static size_t getFrameSize(bool isWide, unsigned FT) {
+ static const size_t kFrameSizeNB[8] = {
+ 95, 103, 118, 134, 148, 159, 204, 244
+ };
+ static const size_t kFrameSizeWB[9] = {
+ 132, 177, 253, 285, 317, 365, 397, 461, 477
+ };
+
+ size_t frameSize = isWide ? kFrameSizeWB[FT] : kFrameSizeNB[FT];
+
+ // Round up bits to bytes and add 1 for the header byte.
+ frameSize = (frameSize + 7) / 8 + 1;
+
+ return frameSize;
+}
+
+void ARTPWriter::sendAMRData(MediaBuffer *mediaBuf) {
+ const uint8_t *mediaData =
+ (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
+
+ size_t mediaLength = mediaBuf->range_length();
+
+ CHECK_GE(kMaxPacketSize, 12u + 1u + mediaLength);
+
+ const bool isWide = (mMode == AMR_WB);
+
+ int64_t timeUs;
+ CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs));
+ uint32_t rtpTime = mRTPTimeBase + (timeUs / (isWide ? 250 : 125));
+
+ // hexdump(mediaData, mediaLength);
+
+ Vector<uint8_t> tableOfContents;
+ size_t srcOffset = 0;
+ while (srcOffset < mediaLength) {
+ uint8_t toc = mediaData[srcOffset];
+
+ unsigned FT = (toc >> 3) & 0x0f;
+ CHECK((isWide && FT <= 8) || (!isWide && FT <= 7));
+
+ tableOfContents.push(toc);
+ srcOffset += getFrameSize(isWide, FT);
+ }
+ CHECK_EQ(srcOffset, mediaLength);
+
+ sp<ABuffer> buffer = new ABuffer(kMaxPacketSize);
+ CHECK_LE(mediaLength + 12 + 1, buffer->capacity());
+
+ // The data fits into a single packet
+ uint8_t *data = buffer->data();
+ data[0] = 0x80;
+ data[1] = PT;
+ if (mNumRTPSent == 0) {
+ // Signal start of talk-spurt.
+ data[1] |= 0x80; // M-bit
+ }
+ data[2] = (mSeqNo >> 8) & 0xff;
+ data[3] = mSeqNo & 0xff;
+ data[4] = rtpTime >> 24;
+ data[5] = (rtpTime >> 16) & 0xff;
+ data[6] = (rtpTime >> 8) & 0xff;
+ data[7] = rtpTime & 0xff;
+ data[8] = mSourceID >> 24;
+ data[9] = (mSourceID >> 16) & 0xff;
+ data[10] = (mSourceID >> 8) & 0xff;
+ data[11] = mSourceID & 0xff;
+
+ data[12] = 0xf0; // CMR=15, RR=0
+
+ size_t dstOffset = 13;
+
+ for (size_t i = 0; i < tableOfContents.size(); ++i) {
+ uint8_t toc = tableOfContents[i];
+
+ if (i + 1 < tableOfContents.size()) {
+ toc |= 0x80;
+ } else {
+ toc &= ~0x80;
+ }
+
+ data[dstOffset++] = toc;
+ }
+
+ srcOffset = 0;
+ for (size_t i = 0; i < tableOfContents.size(); ++i) {
+ uint8_t toc = tableOfContents[i];
+ unsigned FT = (toc >> 3) & 0x0f;
+ size_t frameSize = getFrameSize(isWide, FT);
+
+ ++srcOffset; // skip toc
+ memcpy(&data[dstOffset], &mediaData[srcOffset], frameSize - 1);
+ srcOffset += frameSize - 1;
+ dstOffset += frameSize - 1;
+ }
+
+ buffer->setRange(0, dstOffset);
+
+ send(buffer, false /* isRTCP */);
+
+ ++mSeqNo;
+ ++mNumRTPSent;
+ mNumRTPOctetsSent += buffer->size() - 12;
+
+ mLastRTPTime = rtpTime;
+ mLastNTPTime = GetNowNTP();
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/rtsp/ARTPWriter.h b/media/libstagefright/rtsp/ARTPWriter.h
new file mode 100644
index 0000000..fdc8d23
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPWriter.h
@@ -0,0 +1,128 @@
+/*
+ * 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_WRITER_H_
+
+#define A_RTP_WRITER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AHandlerReflector.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/base64.h>
+#include <media/stagefright/MediaWriter.h>
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#define LOG_TO_FILES 0
+
+namespace android {
+
+struct ABuffer;
+struct MediaBuffer;
+
+struct ARTPWriter : public MediaWriter {
+ ARTPWriter(int fd);
+
+ virtual status_t addSource(const sp<MediaSource> &source);
+ virtual bool reachedEOS();
+ virtual status_t start(MetaData *params);
+ virtual status_t stop();
+ virtual status_t pause();
+
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+protected:
+ virtual ~ARTPWriter();
+
+private:
+ enum {
+ kWhatStart = 'strt',
+ kWhatStop = 'stop',
+ kWhatRead = 'read',
+ kWhatSendSR = 'sr ',
+ };
+
+ enum {
+ kFlagStarted = 1,
+ kFlagEOS = 2,
+ };
+
+ Mutex mLock;
+ Condition mCondition;
+ uint32_t mFlags;
+
+ int mFd;
+
+#if LOG_TO_FILES
+ int mRTPFd;
+ int mRTCPFd;
+#endif
+
+ sp<MediaSource> mSource;
+ sp<ALooper> mLooper;
+ sp<AHandlerReflector<ARTPWriter> > mReflector;
+
+ int mSocket;
+ struct sockaddr_in mRTPAddr;
+ struct sockaddr_in mRTCPAddr;
+
+ AString mProfileLevel;
+ AString mSeqParamSet;
+ AString mPicParamSet;
+
+ uint32_t mSourceID;
+ uint32_t mSeqNo;
+ uint32_t mRTPTimeBase;
+ uint32_t mNumRTPSent;
+ uint32_t mNumRTPOctetsSent;
+ uint32_t mLastRTPTime;
+ uint64_t mLastNTPTime;
+
+ int32_t mNumSRsSent;
+
+ enum {
+ INVALID,
+ H264,
+ H263,
+ AMR_NB,
+ AMR_WB,
+ } mMode;
+
+ static uint64_t GetNowNTP();
+
+ void onRead(const sp<AMessage> &msg);
+ void onSendSR(const sp<AMessage> &msg);
+
+ void addSR(const sp<ABuffer> &buffer);
+ void addSDES(const sp<ABuffer> &buffer);
+
+ void makeH264SPropParamSets(MediaBuffer *buffer);
+ void dumpSessionDesc();
+
+ void sendBye();
+ void sendAVCData(MediaBuffer *mediaBuf);
+ void sendH263Data(MediaBuffer *mediaBuf);
+ void sendAMRData(MediaBuffer *mediaBuf);
+
+ void send(const sp<ABuffer> &buffer, bool isRTCP);
+
+ DISALLOW_EVIL_CONSTRUCTORS(ARTPWriter);
+};
+
+} // namespace android
+
+#endif // A_RTP_WRITER_H_
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
new file mode 100644
index 0000000..539a888
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -0,0 +1,1057 @@
+/*
+ * 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 "ARTSPConnection"
+#include <utils/Log.h>
+
+#include "ARTSPConnection.h"
+
+#include <cutils/properties.h>
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/base64.h>
+#include <media/stagefright/MediaErrors.h>
+
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <openssl/md5.h>
+#include <sys/socket.h>
+
+#include "HTTPBase.h"
+
+namespace android {
+
+// static
+const int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll;
+
+ARTSPConnection::ARTSPConnection(bool uidValid, uid_t uid)
+ : mUIDValid(uidValid),
+ mUID(uid),
+ mState(DISCONNECTED),
+ mAuthType(NONE),
+ mSocket(-1),
+ mConnectionID(0),
+ mNextCSeq(0),
+ mReceiveResponseEventPending(false) {
+ MakeUserAgent(&mUserAgent);
+}
+
+ARTSPConnection::~ARTSPConnection() {
+ if (mSocket >= 0) {
+ ALOGE("Connection is still open, closing the socket.");
+ if (mUIDValid) {
+ HTTPBase::UnRegisterSocketUserTag(mSocket);
+ }
+ 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::observeBinaryData(const sp<AMessage> &reply) {
+ sp<AMessage> msg = new AMessage(kWhatObserveBinaryData, id());
+ 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;
+
+ case kWhatObserveBinaryData:
+ {
+ CHECK(msg->findMessage("reply", &mObserveBinaryMessage));
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+// static
+bool ARTSPConnection::ParseURL(
+ const char *url, AString *host, unsigned *port, AString *path,
+ AString *user, AString *pass) {
+ host->clear();
+ *port = 0;
+ path->clear();
+ user->clear();
+ pass->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);
+ }
+
+ ssize_t atPos = host->find("@");
+
+ if (atPos >= 0) {
+ // Split of user:pass@ from hostname.
+
+ AString userPass(*host, 0, atPos);
+ host->erase(0, atPos + 1);
+
+ ssize_t colonPos = userPass.find(":");
+
+ if (colonPos < 0) {
+ *user = userPass;
+ } else {
+ user->setTo(userPass, 0, colonPos);
+ pass->setTo(userPass, colonPos + 1, userPass.size() - colonPos - 1);
+ }
+ }
+
+ const 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;
+}
+
+static status_t MakeSocketBlocking(int s, bool blocking) {
+ // Make socket non-blocking.
+ int flags = fcntl(s, F_GETFL, 0);
+
+ if (flags == -1) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (blocking) {
+ flags &= ~O_NONBLOCK;
+ } else {
+ flags |= O_NONBLOCK;
+ }
+
+ flags = fcntl(s, F_SETFL, flags);
+
+ return flags == -1 ? UNKNOWN_ERROR : OK;
+}
+
+void ARTSPConnection::onConnect(const sp<AMessage> &msg) {
+ ++mConnectionID;
+
+ if (mState != DISCONNECTED) {
+ if (mUIDValid) {
+ HTTPBase::UnRegisterSocketUserTag(mSocket);
+ }
+ close(mSocket);
+ mSocket = -1;
+
+ flushPendingRequests();
+ }
+
+ mState = CONNECTING;
+
+ AString url;
+ CHECK(msg->findString("url", &url));
+
+ sp<AMessage> reply;
+ CHECK(msg->findMessage("reply", &reply));
+
+ AString host, path;
+ unsigned port;
+ if (!ParseURL(url.c_str(), &host, &port, &path, &mUser, &mPass)
+ || (mUser.size() > 0 && mPass.size() == 0)) {
+ // If we have a user name but no password we have to give up
+ // right here, since we currently have no way of asking the user
+ // for this information.
+
+ ALOGE("Malformed rtsp url %s", url.c_str());
+
+ reply->setInt32("result", ERROR_MALFORMED);
+ reply->post();
+
+ mState = DISCONNECTED;
+ return;
+ }
+
+ if (mUser.size() > 0) {
+ ALOGV("user = '%s', pass = '%s'", mUser.c_str(), mPass.c_str());
+ }
+
+ struct hostent *ent = gethostbyname(host.c_str());
+ if (ent == NULL) {
+ ALOGE("Unknown host %s", host.c_str());
+
+ reply->setInt32("result", -ENOENT);
+ reply->post();
+
+ mState = DISCONNECTED;
+ return;
+ }
+
+ mSocket = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (mUIDValid) {
+ HTTPBase::RegisterSocketUserTag(mSocket, mUID,
+ (uint32_t)*(uint32_t*) "RTSP");
+ }
+
+ MakeSocketBlocking(mSocket, false);
+
+ 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));
+
+ 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;
+
+ if (mUIDValid) {
+ HTTPBase::UnRegisterSocketUserTag(mSocket);
+ }
+ close(mSocket);
+ mSocket = -1;
+ } else {
+ reply->setInt32("result", OK);
+ mState = CONNECTED;
+ mNextCSeq = 1;
+
+ postReceiveReponseEvent();
+ }
+
+ reply->post();
+}
+
+void ARTSPConnection::performDisconnect() {
+ if (mUIDValid) {
+ HTTPBase::UnRegisterSocketUserTag(mSocket);
+ }
+ close(mSocket);
+ mSocket = -1;
+
+ flushPendingRequests();
+
+ mUser.clear();
+ mPass.clear();
+ mAuthType = NONE;
+ mNonce.clear();
+
+ mState = DISCONNECTED;
+}
+
+void ARTSPConnection::onDisconnect(const sp<AMessage> &msg) {
+ if (mState == CONNECTED || mState == CONNECTING) {
+ performDisconnect();
+ }
+
+ sp<AMessage> reply;
+ CHECK(msg->findMessage("reply", &reply));
+
+ reply->setInt32("result", OK);
+
+ 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) {
+ ALOGE("err = %d (%s)", err, strerror(err));
+
+ reply->setInt32("result", -err);
+
+ mState = DISCONNECTED;
+ if (mUIDValid) {
+ HTTPBase::UnRegisterSocketUserTag(mSocket);
+ }
+ 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));
+
+ // Just in case we need to re-issue the request with proper authentication
+ // later, stash it away.
+ reply->setString("original-request", request.c_str(), request.size());
+
+ addAuthentication(&request);
+ addUserAgent(&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);
+
+ ALOGV("request: '%s'", request.c_str());
+
+ size_t numBytesSent = 0;
+ while (numBytesSent < request.size()) {
+ ssize_t n =
+ send(mSocket, request.c_str() + numBytesSent,
+ request.size() - numBytesSent, 0);
+
+ if (n < 0 && errno == EINTR) {
+ continue;
+ }
+
+ if (n <= 0) {
+ performDisconnect();
+
+ if (n == 0) {
+ // Server closed the connection.
+ ALOGE("Server unexpectedly closed the connection.");
+
+ reply->setInt32("result", ERROR_IO);
+ reply->post();
+ } else {
+ ALOGE("Error sending rtsp request. (%s)", strerror(errno));
+ reply->setInt32("result", -errno);
+ reply->post();
+ }
+
+ return;
+ }
+
+ 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) {
+ MakeSocketBlocking(mSocket, true);
+
+ bool success = receiveRTSPReponse();
+
+ MakeSocketBlocking(mSocket, false);
+
+ if (!success) {
+ // 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;
+}
+
+status_t ARTSPConnection::receive(void *data, size_t size) {
+ size_t offset = 0;
+ while (offset < size) {
+ ssize_t n = recv(mSocket, (uint8_t *)data + offset, size - offset, 0);
+
+ if (n < 0 && errno == EINTR) {
+ continue;
+ }
+
+ if (n <= 0) {
+ performDisconnect();
+
+ if (n == 0) {
+ // Server closed the connection.
+ ALOGE("Server unexpectedly closed the connection.");
+ return ERROR_IO;
+ } else {
+ ALOGE("Error reading rtsp response. (%s)", strerror(errno));
+ return -errno;
+ }
+ }
+
+ offset += (size_t)n;
+ }
+
+ return OK;
+}
+
+bool ARTSPConnection::receiveLine(AString *line) {
+ line->clear();
+
+ bool sawCR = false;
+ for (;;) {
+ char c;
+ if (receive(&c, 1) != OK) {
+ return false;
+ }
+
+ if (sawCR && c == '\n') {
+ line->erase(line->size() - 1, 1);
+ return true;
+ }
+
+ line->append(&c, 1);
+
+ if (c == '$' && line->size() == 1) {
+ // Special-case for interleaved binary data.
+ return true;
+ }
+
+ sawCR = (c == '\r');
+ }
+}
+
+sp<ABuffer> ARTSPConnection::receiveBinaryData() {
+ uint8_t x[3];
+ if (receive(x, 3) != OK) {
+ return NULL;
+ }
+
+ sp<ABuffer> buffer = new ABuffer((x[1] << 8) | x[2]);
+ if (receive(buffer->data(), buffer->size()) != OK) {
+ return NULL;
+ }
+
+ buffer->meta()->setInt32("index", (int32_t)x[0]);
+
+ return buffer;
+}
+
+static bool IsRTSPVersion(const AString &s) {
+ return s == "RTSP/1.0";
+}
+
+bool ARTSPConnection::receiveRTSPReponse() {
+ AString statusLine;
+
+ if (!receiveLine(&statusLine)) {
+ return false;
+ }
+
+ if (statusLine == "$") {
+ sp<ABuffer> buffer = receiveBinaryData();
+
+ if (buffer == NULL) {
+ return false;
+ }
+
+ if (mObserveBinaryMessage != NULL) {
+ sp<AMessage> notify = mObserveBinaryMessage->dup();
+ notify->setBuffer("buffer", buffer);
+ notify->post();
+ } else {
+ ALOGW("received binary data, but no one cares.");
+ }
+
+ return true;
+ }
+
+ sp<ARTSPResponse> response = new ARTSPResponse;
+ response->mStatusLine = statusLine;
+
+ ALOGI("status: %s", response->mStatusLine.c_str());
+
+ ssize_t space1 = response->mStatusLine.find(" ");
+ if (space1 < 0) {
+ return false;
+ }
+ ssize_t space2 = response->mStatusLine.find(" ", space1 + 1);
+ if (space2 < 0) {
+ return false;
+ }
+
+ bool isRequest = false;
+
+ if (!IsRTSPVersion(AString(response->mStatusLine, 0, space1))) {
+ CHECK(IsRTSPVersion(
+ AString(
+ response->mStatusLine,
+ space2 + 1,
+ response->mStatusLine.size() - space2 - 1)));
+
+ isRequest = true;
+
+ response->mStatusCode = 0;
+ } else {
+ 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;
+ ssize_t lastDictIndex = -1;
+ for (;;) {
+ if (!receiveLine(&line)) {
+ break;
+ }
+
+ if (line.empty()) {
+ break;
+ }
+
+ ALOGV("line: '%s'", line.c_str());
+
+ if (line.c_str()[0] == ' ' || line.c_str()[0] == '\t') {
+ // Support for folded header values.
+
+ if (lastDictIndex < 0) {
+ // First line cannot be a continuation of the previous one.
+ return false;
+ }
+
+ AString &value = response->mHeaders.editValueAt(lastDictIndex);
+ value.append(line);
+
+ continue;
+ }
+
+ 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);
+
+ lastDictIndex = response->mHeaders.add(key, line);
+ }
+
+ for (size_t i = 0; i < response->mHeaders.size(); ++i) {
+ response->mHeaders.editValueAt(i).trim();
+ }
+
+ 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);
+
+ if (receive(response->mContent->data(), contentLength) != OK) {
+ return false;
+ }
+ }
+
+ if (response->mStatusCode == 401) {
+ if (mAuthType == NONE && mUser.size() > 0
+ && parseAuthMethod(response)) {
+ ssize_t i;
+ CHECK_EQ((status_t)OK, findPendingRequest(response, &i));
+ CHECK_GE(i, 0);
+
+ sp<AMessage> reply = mPendingRequests.valueAt(i);
+ mPendingRequests.removeItemsAt(i);
+
+ AString request;
+ CHECK(reply->findString("original-request", &request));
+
+ sp<AMessage> msg = new AMessage(kWhatSendRequest, id());
+ msg->setMessage("reply", reply);
+ msg->setString("request", request.c_str(), request.size());
+
+ ALOGI("re-sending request with authentication headers...");
+ onSendRequest(msg);
+
+ return true;
+ }
+ }
+
+ return isRequest
+ ? handleServerRequest(response)
+ : notifyResponseListener(response);
+}
+
+bool ARTSPConnection::handleServerRequest(const sp<ARTSPResponse> &request) {
+ // Implementation of server->client requests is optional for all methods
+ // but we do need to respond, even if it's just to say that we don't
+ // support the method.
+
+ ssize_t space1 = request->mStatusLine.find(" ");
+ CHECK_GE(space1, 0);
+
+ AString response;
+ response.append("RTSP/1.0 501 Not Implemented\r\n");
+
+ ssize_t i = request->mHeaders.indexOfKey("cseq");
+
+ if (i >= 0) {
+ AString value = request->mHeaders.valueAt(i);
+
+ unsigned long cseq;
+ if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) {
+ return false;
+ }
+
+ response.append("CSeq: ");
+ response.append(cseq);
+ response.append("\r\n");
+ }
+
+ response.append("\r\n");
+
+ size_t numBytesSent = 0;
+ while (numBytesSent < response.size()) {
+ ssize_t n =
+ send(mSocket, response.c_str() + numBytesSent,
+ response.size() - numBytesSent, 0);
+
+ if (n < 0 && errno == EINTR) {
+ continue;
+ }
+
+ if (n <= 0) {
+ if (n == 0) {
+ // Server closed the connection.
+ ALOGE("Server unexpectedly closed the connection.");
+ } else {
+ ALOGE("Error sending rtsp response (%s).", strerror(errno));
+ }
+
+ performDisconnect();
+
+ return false;
+ }
+
+ numBytesSent += (size_t)n;
+ }
+
+ return true;
+}
+
+// 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;
+}
+
+status_t ARTSPConnection::findPendingRequest(
+ const sp<ARTSPResponse> &response, ssize_t *index) const {
+ *index = 0;
+
+ ssize_t i = response->mHeaders.indexOfKey("cseq");
+
+ if (i < 0) {
+ // This is an unsolicited server->client message.
+ return OK;
+ }
+
+ AString value = response->mHeaders.valueAt(i);
+
+ unsigned long cseq;
+ if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) {
+ return ERROR_MALFORMED;
+ }
+
+ i = mPendingRequests.indexOfKey(cseq);
+
+ if (i < 0) {
+ return -ENOENT;
+ }
+
+ *index = i;
+
+ return OK;
+}
+
+bool ARTSPConnection::notifyResponseListener(
+ const sp<ARTSPResponse> &response) {
+ ssize_t i;
+ status_t err = findPendingRequest(response, &i);
+
+ if (err == OK && i < 0) {
+ // An unsolicited server response is not a problem.
+ return true;
+ }
+
+ if (err != OK) {
+ return false;
+ }
+
+ sp<AMessage> reply = mPendingRequests.valueAt(i);
+ mPendingRequests.removeItemsAt(i);
+
+ reply->setInt32("result", OK);
+ reply->setObject("response", response);
+ reply->post();
+
+ return true;
+}
+
+bool ARTSPConnection::parseAuthMethod(const sp<ARTSPResponse> &response) {
+ ssize_t i = response->mHeaders.indexOfKey("www-authenticate");
+
+ if (i < 0) {
+ return false;
+ }
+
+ AString value = response->mHeaders.valueAt(i);
+
+ if (!strncmp(value.c_str(), "Basic", 5)) {
+ mAuthType = BASIC;
+ } else {
+#if !defined(HAVE_ANDROID_OS)
+ // We don't have access to the MD5 implementation on the simulator,
+ // so we won't support digest authentication.
+ return false;
+#endif
+
+ 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);
+ }
+
+ return true;
+}
+
+#if defined(HAVE_ANDROID_OS)
+static 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);
+ }
+}
+#endif
+
+static void GetMethodAndURL(
+ const AString &request, AString *method, AString *url) {
+ ssize_t space1 = request.find(" ");
+ CHECK_GE(space1, 0);
+
+ ssize_t space2 = request.find(" ", space1 + 1);
+ CHECK_GE(space2, 0);
+
+ method->setTo(request, 0, space1);
+ url->setTo(request, space1 + 1, space2 - space1);
+}
+
+void ARTSPConnection::addAuthentication(AString *request) {
+ if (mAuthType == NONE) {
+ return;
+ }
+
+ // Find the boundary between headers and the body.
+ ssize_t i = request->find("\r\n\r\n");
+ CHECK_GE(i, 0);
+
+ if (mAuthType == BASIC) {
+ AString tmp;
+ tmp.append(mUser);
+ tmp.append(":");
+ tmp.append(mPass);
+
+ AString out;
+ encodeBase64(tmp.c_str(), tmp.size(), &out);
+
+ AString fragment;
+ fragment.append("Authorization: Basic ");
+ fragment.append(out);
+ fragment.append("\r\n");
+
+ request->insert(fragment, i + 2);
+
+ return;
+ }
+
+#if defined(HAVE_ANDROID_OS)
+ CHECK_EQ((int)mAuthType, (int)DIGEST);
+
+ AString method, url;
+ GetMethodAndURL(*request, &method, &url);
+
+ AString A1;
+ A1.append(mUser);
+ A1.append(":");
+ A1.append("Streaming Server");
+ A1.append(":");
+ A1.append(mPass);
+
+ 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);
+
+ AString fragment;
+ fragment.append("Authorization: Digest ");
+ fragment.append("nonce=\"");
+ fragment.append(mNonce);
+ fragment.append("\", ");
+ fragment.append("username=\"");
+ fragment.append(mUser);
+ fragment.append("\", ");
+ fragment.append("uri=\"");
+ fragment.append(url);
+ fragment.append("\", ");
+ fragment.append("response=\"");
+ fragment.append(digest);
+ fragment.append("\"");
+ fragment.append("\r\n");
+
+ request->insert(fragment, i + 2);
+#endif
+}
+
+// static
+void ARTSPConnection::MakeUserAgent(AString *userAgent) {
+ userAgent->clear();
+ userAgent->setTo("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");
+ userAgent->append(value);
+ userAgent->append(")\r\n");
+}
+
+void ARTSPConnection::addUserAgent(AString *request) const {
+ // Find the boundary between headers and the body.
+ ssize_t i = request->find("\r\n\r\n");
+ CHECK_GE(i, 0);
+
+ request->insert(mUserAgent, i + 2);
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/ARTSPConnection.h b/media/libstagefright/rtsp/ARTSPConnection.h
new file mode 100644
index 0000000..68f2d59
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTSPConnection.h
@@ -0,0 +1,132 @@
+/*
+ * 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(bool uidValid = false, uid_t uid = 0);
+
+ void connect(const char *url, const sp<AMessage> &reply);
+ void disconnect(const sp<AMessage> &reply);
+
+ void sendRequest(const char *request, const sp<AMessage> &reply);
+
+ void observeBinaryData(const sp<AMessage> &reply);
+
+ static bool ParseURL(
+ const char *url, AString *host, unsigned *port, AString *path,
+ AString *user, AString *pass);
+
+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',
+ kWhatObserveBinaryData = 'obin',
+ };
+
+ enum AuthType {
+ NONE,
+ BASIC,
+ DIGEST
+ };
+
+ static const int64_t kSelectTimeoutUs;
+
+ bool mUIDValid;
+ uid_t mUID;
+ State mState;
+ AString mUser, mPass;
+ AuthType mAuthType;
+ AString mNonce;
+ int mSocket;
+ int32_t mConnectionID;
+ int32_t mNextCSeq;
+ bool mReceiveResponseEventPending;
+
+ KeyedVector<int32_t, sp<AMessage> > mPendingRequests;
+
+ sp<AMessage> mObserveBinaryMessage;
+
+ AString mUserAgent;
+
+ void performDisconnect();
+
+ 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();
+ status_t receive(void *data, size_t size);
+ bool receiveLine(AString *line);
+ sp<ABuffer> receiveBinaryData();
+ bool notifyResponseListener(const sp<ARTSPResponse> &response);
+
+ bool parseAuthMethod(const sp<ARTSPResponse> &response);
+ void addAuthentication(AString *request);
+
+ void addUserAgent(AString *request) const;
+
+ status_t findPendingRequest(
+ const sp<ARTSPResponse> &response, ssize_t *index) const;
+
+ bool handleServerRequest(const sp<ARTSPResponse> &request);
+
+ static bool ParseSingleUnsignedLong(
+ const char *from, unsigned long *x);
+
+ static void MakeUserAgent(AString *userAgent);
+
+ DISALLOW_EVIL_CONSTRUCTORS(ARTSPConnection);
+};
+
+} // namespace android
+
+#endif // A_RTSP_CONNECTION_H_
diff --git a/media/libstagefright/rtsp/ARawAudioAssembler.cpp b/media/libstagefright/rtsp/ARawAudioAssembler.cpp
new file mode 100644
index 0000000..0da5dd2
--- /dev/null
+++ b/media/libstagefright/rtsp/ARawAudioAssembler.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ARawAudioAssembler"
+#include <utils/Log.h>
+
+#include "ARawAudioAssembler.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/hexdump.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+ARawAudioAssembler::ARawAudioAssembler(
+ const sp<AMessage> &notify, const char *desc, const AString &params)
+ : mNotifyMsg(notify),
+ mNextExpectedSeqNoValid(false),
+ mNextExpectedSeqNo(0) {
+}
+
+ARawAudioAssembler::~ARawAudioAssembler() {
+}
+
+ARTPAssembler::AssemblyStatus ARawAudioAssembler::assembleMore(
+ const sp<ARTPSource> &source) {
+ return addPacket(source);
+}
+
+ARTPAssembler::AssemblyStatus ARawAudioAssembler::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) {
+ ALOGV("Not the sequence number I expected");
+
+ return WRONG_SEQUENCE_NUMBER;
+ }
+
+ // hexdump(buffer->data(), buffer->size());
+
+ if (buffer->size() < 1) {
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ ALOGV("raw audio packet too short.");
+
+ return MALFORMED_PACKET;
+ }
+
+ sp<AMessage> msg = mNotifyMsg->dup();
+ msg->setBuffer("access-unit", buffer);
+ msg->post();
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ return OK;
+}
+
+void ARawAudioAssembler::packetLost() {
+ CHECK(mNextExpectedSeqNoValid);
+ ++mNextExpectedSeqNo;
+}
+
+void ARawAudioAssembler::onByeReceived() {
+ sp<AMessage> msg = mNotifyMsg->dup();
+ msg->setInt32("eos", true);
+ msg->post();
+}
+
+// static
+bool ARawAudioAssembler::Supports(const char *desc) {
+ return !strncmp(desc, "PCMU/", 5)
+ || !strncmp(desc, "PCMA/", 5);
+}
+
+// static
+void ARawAudioAssembler::MakeFormat(
+ const char *desc, const sp<MetaData> &format) {
+ if (!strncmp(desc, "PCMU/", 5)) {
+ format->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_MLAW);
+ } else if (!strncmp(desc, "PCMA/", 5)) {
+ format->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_ALAW);
+ } else {
+ TRESPASS();
+ }
+
+ int32_t sampleRate, numChannels;
+ ASessionDescription::ParseFormatDesc(
+ desc, &sampleRate, &numChannels);
+
+ format->setInt32(kKeySampleRate, sampleRate);
+ format->setInt32(kKeyChannelCount, numChannels);
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/rtsp/ARawAudioAssembler.h b/media/libstagefright/rtsp/ARawAudioAssembler.h
new file mode 100644
index 0000000..ed7af08
--- /dev/null
+++ b/media/libstagefright/rtsp/ARawAudioAssembler.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_RAW_AUDIO_ASSEMBLER_H_
+
+#define A_RAW_AUDIO_ASSEMBLER_H_
+
+#include "ARTPAssembler.h"
+
+namespace android {
+
+struct AMessage;
+struct AString;
+struct MetaData;
+
+struct ARawAudioAssembler : public ARTPAssembler {
+ ARawAudioAssembler(
+ const sp<AMessage> &notify,
+ const char *desc, const AString &params);
+
+ static bool Supports(const char *desc);
+
+ static void MakeFormat(
+ const char *desc, const sp<MetaData> &format);
+
+protected:
+ virtual ~ARawAudioAssembler();
+
+ virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source);
+ virtual void onByeReceived();
+ virtual void packetLost();
+
+private:
+ bool mIsWide;
+
+ sp<AMessage> mNotifyMsg;
+ bool mNextExpectedSeqNoValid;
+ uint32_t mNextExpectedSeqNo;
+
+ AssemblyStatus addPacket(const sp<ARTPSource> &source);
+
+ DISALLOW_EVIL_CONSTRUCTORS(ARawAudioAssembler);
+};
+
+} // namespace android
+
+#endif // A_RAW_AUDIO_ASSEMBLER_H_
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
new file mode 100644
index 0000000..a9b3330
--- /dev/null
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -0,0 +1,336 @@
+/*
+ * 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 "ASessionDescription"
+#include <utils/Log.h>
+
+#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);
+
+ size_t i = 0;
+ for (;;) {
+ ssize_t eolPos = desc.find("\n", i);
+
+ if (eolPos < 0) {
+ break;
+ }
+
+ AString line;
+ if ((size_t)eolPos > i && desc.c_str()[eolPos - 1] == '\r') {
+ // We accept both '\n' and '\r\n' line endings, if it's
+ // the latter, strip the '\r' as well.
+ line.setTo(desc, i, eolPos - i - 1);
+ } else {
+ line.setTo(desc, i, eolPos - i);
+ }
+
+ if (line.empty()) {
+ i = eolPos + 1;
+ continue;
+ }
+
+ if (line.size() < 2 || line.c_str()[1] != '=') {
+ return false;
+ }
+
+ ALOGI("%s", line.c_str());
+
+ 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();
+
+ ALOGV("adding '%s' => '%s'", key.c_str(), value.c_str());
+
+ mTracks.editItemAt(mTracks.size() - 1).add(key, value);
+ break;
+ }
+
+ case 'm':
+ {
+ ALOGV("new section '%s'",
+ AString(line, 2, line.size() - 2).c_str());
+
+ mTracks.push(Attribs());
+ mFormats.push(AString(line, 2, line.size() - 2));
+ break;
+ }
+
+ default:
+ {
+ AString key, value;
+
+ ssize_t equalPos = line.find("=");
+
+ key = AString(line, 0, equalPos + 1);
+ value = AString(line, equalPos + 1, line.size() - equalPos - 1);
+
+ key.trim();
+ value.trim();
+
+ ALOGV("adding '%s' => '%s'", key.c_str(), value.c_str());
+
+ mTracks.editItemAt(mTracks.size() - 1).add(key, value);
+ break;
+ }
+ }
+
+ i = eolPos + 1;
+ }
+
+ 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);
+
+ const 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();
+ }
+}
+
+bool ASessionDescription::getDimensions(
+ size_t index, unsigned long PT,
+ int32_t *width, int32_t *height) const {
+ *width = 0;
+ *height = 0;
+
+ char key[20];
+ sprintf(key, "a=framesize:%lu", PT);
+ AString value;
+ if (!findAttribute(index, key, &value)) {
+ return false;
+ }
+
+ 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');
+
+ return true;
+}
+
+bool ASessionDescription::getDurationUs(int64_t *durationUs) const {
+ *durationUs = 0;
+
+ CHECK(mIsValid);
+
+ AString value;
+ if (!findAttribute(0, "a=range", &value)) {
+ return false;
+ }
+
+ if (strncmp(value.c_str(), "npt=", 4)) {
+ return false;
+ }
+
+ float from, to;
+ if (!parseNTPRange(value.c_str() + 4, &from, &to)) {
+ return false;
+ }
+
+ *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;
+ }
+}
+
+// static
+bool ASessionDescription::parseNTPRange(
+ const char *s, float *npt1, float *npt2) {
+ if (s[0] == '-') {
+ return false; // no start time available.
+ }
+
+ if (!strncmp("now", s, 3)) {
+ return false; // no absolute start time available
+ }
+
+ char *end;
+ *npt1 = strtof(s, &end);
+
+ if (end == s || *end != '-') {
+ // Failed to parse float or trailing "dash".
+ return false;
+ }
+
+ s = end + 1; // skip the dash.
+
+ if (!strncmp("now", s, 3)) {
+ return false; // no absolute end time available
+ }
+
+ *npt2 = strtof(s, &end);
+
+ if (end == s || *end != '\0') {
+ return false;
+ }
+
+ return *npt2 > *npt1;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/rtsp/ASessionDescription.h b/media/libstagefright/rtsp/ASessionDescription.h
new file mode 100644
index 0000000..b462983
--- /dev/null
+++ b/media/libstagefright/rtsp/ASessionDescription.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_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;
+
+ bool 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;
+
+ // parses strings of the form
+ // npt := npt-time "-" npt-time? | "-" npt-time
+ // npt-time := "now" | [0-9]+("." [0-9]*)?
+ //
+ // Returns true iff both "npt1" and "npt2" times were available,
+ // i.e. we have a fixed duration, otherwise this is live streaming.
+ static bool parseNTPRange(const char *s, float *npt1, float *npt2);
+
+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..e0fe59b
--- /dev/null
+++ b/media/libstagefright/rtsp/Android.mk
@@ -0,0 +1,56 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ AAMRAssembler.cpp \
+ AAVCAssembler.cpp \
+ AH263Assembler.cpp \
+ AMPEG4AudioAssembler.cpp \
+ AMPEG4ElementaryAssembler.cpp \
+ APacketSource.cpp \
+ ARawAudioAssembler.cpp \
+ ARTPAssembler.cpp \
+ ARTPConnection.cpp \
+ ARTPSource.cpp \
+ ARTPWriter.cpp \
+ ARTSPConnection.cpp \
+ ASessionDescription.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/base/media/libstagefright/include \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/external/openssl/include
+
+LOCAL_MODULE:= libstagefright_rtsp
+
+ifeq ($(TARGET_ARCH),arm)
+ LOCAL_CFLAGS += -Wno-psabi
+endif
+
+include $(BUILD_STATIC_LIBRARY)
+
+################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ rtp_test.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libstagefright liblog libutils libbinder libstagefright_foundation
+
+LOCAL_STATIC_LIBRARIES := \
+ libstagefright_rtsp
+
+LOCAL_C_INCLUDES:= \
+ frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE_TAGS := debug
+
+LOCAL_MODULE:= rtp_test
+
+# include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
new file mode 100644
index 0000000..deee30f
--- /dev/null
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -0,0 +1,1522 @@
+/*
+ * 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_
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MyHandler"
+#include <utils/Log.h>
+
+#include "APacketSource.h"
+#include "ARTPConnection.h"
+#include "ARTSPConnection.h"
+#include "ASessionDescription.h"
+
+#include <ctype.h>
+#include <cutils/properties.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>
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#include "HTTPBase.h"
+
+// If no access units are received within 5 secs, assume that the rtp
+// stream has ended and signal end of stream.
+static int64_t kAccessUnitTimeoutUs = 10000000ll;
+
+// If no access units arrive for the first 10 secs after starting the
+// stream, assume none ever will and signal EOS or switch transports.
+static int64_t kStartupTimeoutUs = 10000000ll;
+
+static int64_t kDefaultKeepAliveTimeoutUs = 60000000ll;
+
+namespace android {
+
+static void MakeUserAgentString(AString *s) {
+ s->setTo("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");
+ s->append(value);
+ s->append(")");
+}
+
+static bool GetAttribute(const char *s, const char *key, AString *value) {
+ value->clear();
+
+ size_t keyLen = strlen(key);
+
+ for (;;) {
+ while (isspace(*s)) {
+ ++s;
+ }
+
+ 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 MyHandler : public AHandler {
+ enum {
+ kWhatConnected = 'conn',
+ kWhatDisconnected = 'disc',
+ kWhatSeekDone = 'sdon',
+
+ kWhatAccessUnit = 'accU',
+ kWhatEOS = 'eos!',
+ kWhatSeekDiscontinuity = 'seeD',
+ kWhatNormalPlayTimeMapping = 'nptM',
+ };
+
+ MyHandler(
+ const char *url,
+ const sp<AMessage> &notify,
+ bool uidValid = false, uid_t uid = 0)
+ : mNotify(notify),
+ mUIDValid(uidValid),
+ mUID(uid),
+ mNetLooper(new ALooper),
+ mConn(new ARTSPConnection(mUIDValid, mUID)),
+ mRTPConn(new ARTPConnection),
+ mOriginalSessionURL(url),
+ mSessionURL(url),
+ mSetupTracksSuccessful(false),
+ mSeekPending(false),
+ mFirstAccessUnit(true),
+ mAllTracksHaveTime(false),
+ mNTPAnchorUs(-1),
+ mMediaAnchorUs(-1),
+ mLastMediaTimeUs(0),
+ mNumAccessUnitsReceived(0),
+ mCheckPending(false),
+ mCheckGeneration(0),
+ mTryTCPInterleaving(false),
+ mTryFakeRTCP(false),
+ mReceivedFirstRTCPPacket(false),
+ mReceivedFirstRTPPacket(false),
+ mSeekable(false),
+ mKeepAliveTimeoutUs(kDefaultKeepAliveTimeoutUs),
+ mKeepAliveGeneration(0) {
+ mNetLooper->setName("rtsp net");
+ mNetLooper->start(false /* runOnCallingThread */,
+ false /* canCallJava */,
+ PRIORITY_HIGHEST);
+
+ // Strip any authentication info from the session url, we don't
+ // want to transmit user/pass in cleartext.
+ AString host, path, user, pass;
+ unsigned port;
+ CHECK(ARTSPConnection::ParseURL(
+ mSessionURL.c_str(), &host, &port, &path, &user, &pass));
+
+ if (user.size() > 0) {
+ mSessionURL.clear();
+ mSessionURL.append("rtsp://");
+ mSessionURL.append(host);
+ mSessionURL.append(":");
+ mSessionURL.append(StringPrintf("%u", port));
+ mSessionURL.append(path);
+
+ ALOGI("rewritten session url: '%s'", mSessionURL.c_str());
+ }
+
+ mSessionHost = host;
+ }
+
+ void connect() {
+ looper()->registerHandler(mConn);
+ (1 ? mNetLooper : looper())->registerHandler(mRTPConn);
+
+ sp<AMessage> notify = new AMessage('biny', id());
+ mConn->observeBinaryData(notify);
+
+ sp<AMessage> reply = new AMessage('conn', id());
+ mConn->connect(mOriginalSessionURL.c_str(), reply);
+ }
+
+ void disconnect() {
+ (new AMessage('abor', id()))->post();
+ }
+
+ void seek(int64_t timeUs) {
+ sp<AMessage> msg = new AMessage('seek', id());
+ msg->setInt64("time", timeUs);
+ msg->post();
+ }
+
+ static void addRR(const sp<ABuffer> &buf) {
+ uint8_t *ptr = buf->data() + buf->size();
+ ptr[0] = 0x80 | 0;
+ ptr[1] = 201; // RR
+ ptr[2] = 0;
+ ptr[3] = 1;
+ ptr[4] = 0xde; // SSRC
+ ptr[5] = 0xad;
+ ptr[6] = 0xbe;
+ ptr[7] = 0xef;
+
+ buf->setRange(0, buf->size() + 8);
+ }
+
+ static void addSDES(int s, const sp<ABuffer> &buffer) {
+ struct sockaddr_in addr;
+ socklen_t addrSize = sizeof(addr);
+ CHECK_EQ(0, getsockname(s, (sockaddr *)&addr, &addrSize));
+
+ uint8_t *data = buffer->data() + buffer->size();
+ data[0] = 0x80 | 1;
+ data[1] = 202; // SDES
+ data[4] = 0xde; // SSRC
+ data[5] = 0xad;
+ data[6] = 0xbe;
+ data[7] = 0xef;
+
+ size_t offset = 8;
+
+ data[offset++] = 1; // CNAME
+
+ AString cname = "stagefright@";
+ cname.append(inet_ntoa(addr.sin_addr));
+ data[offset++] = cname.size();
+
+ memcpy(&data[offset], cname.c_str(), cname.size());
+ offset += cname.size();
+
+ data[offset++] = 6; // TOOL
+
+ AString tool;
+ MakeUserAgentString(&tool);
+
+ data[offset++] = tool.size();
+
+ memcpy(&data[offset], tool.c_str(), tool.size());
+ offset += tool.size();
+
+ 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);
+ }
+
+ // In case we're behind NAT, fire off two UDP packets to the remote
+ // rtp/rtcp ports to poke a hole into the firewall for future incoming
+ // packets. We're going to send an RR/SDES RTCP packet to both of them.
+ bool pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) {
+ struct sockaddr_in addr;
+ memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
+ addr.sin_family = AF_INET;
+
+ AString source;
+ AString server_port;
+ if (!GetAttribute(transport.c_str(),
+ "source",
+ &source)) {
+ ALOGW("Missing 'source' field in Transport response. Using "
+ "RTSP endpoint address.");
+
+ struct hostent *ent = gethostbyname(mSessionHost.c_str());
+ if (ent == NULL) {
+ ALOGE("Failed to look up address of session host '%s'",
+ mSessionHost.c_str());
+
+ return false;
+ }
+
+ addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
+ } else {
+ addr.sin_addr.s_addr = inet_addr(source.c_str());
+ }
+
+ if (!GetAttribute(transport.c_str(),
+ "server_port",
+ &server_port)) {
+ ALOGI("Missing 'server_port' field in Transport response.");
+ return false;
+ }
+
+ int rtpPort, rtcpPort;
+ if (sscanf(server_port.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2
+ || rtpPort <= 0 || rtpPort > 65535
+ || rtcpPort <=0 || rtcpPort > 65535
+ || rtcpPort != rtpPort + 1) {
+ ALOGE("Server picked invalid RTP/RTCP port pair %s,"
+ " RTP port must be even, RTCP port must be one higher.",
+ server_port.c_str());
+
+ return false;
+ }
+
+ if (rtpPort & 1) {
+ ALOGW("Server picked an odd RTP port, it should've picked an "
+ "even one, we'll let it pass for now, but this may break "
+ "in the future.");
+ }
+
+ if (addr.sin_addr.s_addr == INADDR_NONE) {
+ return true;
+ }
+
+ if (IN_LOOPBACK(ntohl(addr.sin_addr.s_addr))) {
+ // No firewalls to traverse on the loopback interface.
+ return true;
+ }
+
+ // Make up an RR/SDES RTCP packet.
+ sp<ABuffer> buf = new ABuffer(65536);
+ buf->setRange(0, 0);
+ addRR(buf);
+ addSDES(rtpSocket, buf);
+
+ addr.sin_port = htons(rtpPort);
+
+ ssize_t n = sendto(
+ rtpSocket, buf->data(), buf->size(), 0,
+ (const sockaddr *)&addr, sizeof(addr));
+
+ if (n < (ssize_t)buf->size()) {
+ ALOGE("failed to poke a hole for RTP packets");
+ return false;
+ }
+
+ addr.sin_port = htons(rtcpPort);
+
+ n = sendto(
+ rtcpSocket, buf->data(), buf->size(), 0,
+ (const sockaddr *)&addr, sizeof(addr));
+
+ if (n < (ssize_t)buf->size()) {
+ ALOGE("failed to poke a hole for RTCP packets");
+ return false;
+ }
+
+ ALOGV("successfully poked holes.");
+
+ return true;
+ }
+
+ virtual void onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case 'conn':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ ALOGI("connection request completed with result %d (%s)",
+ 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);
+ } else {
+ (new AMessage('disc', id()))->post();
+ }
+ break;
+ }
+
+ case 'disc':
+ {
+ ++mKeepAliveGeneration;
+
+ int32_t reconnect;
+ if (msg->findInt32("reconnect", &reconnect) && reconnect) {
+ sp<AMessage> reply = new AMessage('conn', id());
+ mConn->connect(mOriginalSessionURL.c_str(), reply);
+ } else {
+ (new AMessage('quit', id()))->post();
+ }
+ break;
+ }
+
+ case 'desc':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ ALOGI("DESCRIBE completed with result %d (%s)",
+ 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;
+ }
+
+ if (response->mStatusCode != 200) {
+ result = UNKNOWN_ERROR;
+ } else {
+ mSessionDesc = new ASessionDescription;
+
+ mSessionDesc->setTo(
+ response->mContent->data(),
+ response->mContent->size());
+
+ if (!mSessionDesc->isValid()) {
+ ALOGE("Failed to parse session description.");
+ result = ERROR_MALFORMED;
+ } else {
+ 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;
+ }
+ }
+
+ if (!mBaseURL.startsWith("rtsp://")) {
+ // Some misbehaving servers specify a relative
+ // URL in one of the locations above, combine
+ // it with the absolute session URL to get
+ // something usable...
+
+ ALOGW("Server specified a non-absolute base URL"
+ ", combining it with the session URL to "
+ "get something usable...");
+
+ AString tmp;
+ CHECK(MakeURL(
+ mSessionURL.c_str(),
+ mBaseURL.c_str(),
+ &tmp));
+
+ mBaseURL = tmp;
+ }
+
+ if (mSessionDesc->countTracks() < 2) {
+ // There's no actual tracks in this session.
+ // The first "track" is merely session meta
+ // data.
+
+ ALOGW("Session doesn't contain any playable "
+ "tracks. Aborting.");
+ result = ERROR_UNSUPPORTED;
+ } else {
+ setupTrack(1);
+ }
+ }
+ }
+ }
+
+ if (result != OK) {
+ sp<AMessage> reply = new AMessage('disc', id());
+ mConn->disconnect(reply);
+ }
+ break;
+ }
+
+ case 'setu':
+ {
+ size_t index;
+ CHECK(msg->findSize("index", &index));
+
+ TrackInfo *track = NULL;
+ size_t trackIndex;
+ if (msg->findSize("track-index", &trackIndex)) {
+ track = &mTracks.editItemAt(trackIndex);
+ }
+
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ ALOGI("SETUP(%d) completed with result %d (%s)",
+ index, result, strerror(-result));
+
+ if (result == OK) {
+ CHECK(track != NULL);
+
+ sp<RefBase> obj;
+ CHECK(msg->findObject("response", &obj));
+ sp<ARTSPResponse> response =
+ static_cast<ARTSPResponse *>(obj.get());
+
+ if (response->mStatusCode != 200) {
+ result = UNKNOWN_ERROR;
+ } else {
+ ssize_t i = response->mHeaders.indexOfKey("session");
+ CHECK_GE(i, 0);
+
+ mSessionID = response->mHeaders.valueAt(i);
+
+ mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
+ AString timeoutStr;
+ if (GetAttribute(
+ mSessionID.c_str(), "timeout", &timeoutStr)) {
+ char *end;
+ unsigned long timeoutSecs =
+ strtoul(timeoutStr.c_str(), &end, 10);
+
+ if (end == timeoutStr.c_str() || *end != '\0') {
+ ALOGW("server specified malformed timeout '%s'",
+ timeoutStr.c_str());
+
+ mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
+ } else if (timeoutSecs < 15) {
+ ALOGW("server specified too short a timeout "
+ "(%lu secs), using default.",
+ timeoutSecs);
+
+ mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
+ } else {
+ mKeepAliveTimeoutUs = timeoutSecs * 1000000ll;
+
+ ALOGI("server specified timeout of %lu secs.",
+ timeoutSecs);
+ }
+ }
+
+ 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);
+
+ i = response->mHeaders.indexOfKey("transport");
+ CHECK_GE(i, 0);
+
+ if (!track->mUsingInterleavedTCP) {
+ AString transport = response->mHeaders.valueAt(i);
+
+ // We are going to continue even if we were
+ // unable to poke a hole into the firewall...
+ pokeAHole(
+ track->mRTPSocket,
+ track->mRTCPSocket,
+ transport);
+ }
+
+ mRTPConn->addStream(
+ track->mRTPSocket, track->mRTCPSocket,
+ mSessionDesc, index,
+ notify, track->mUsingInterleavedTCP);
+
+ mSetupTracksSuccessful = true;
+ }
+ }
+
+ if (result != OK) {
+ if (track) {
+ if (!track->mUsingInterleavedTCP) {
+ // Clear the tag
+ if (mUIDValid) {
+ HTTPBase::UnRegisterSocketUserTag(track->mRTPSocket);
+ HTTPBase::UnRegisterSocketUserTag(track->mRTCPSocket);
+ }
+
+ close(track->mRTPSocket);
+ close(track->mRTCPSocket);
+ }
+
+ mTracks.removeItemsAt(trackIndex);
+ }
+ }
+
+ ++index;
+ if (index < mSessionDesc->countTracks()) {
+ setupTrack(index);
+ } else if (mSetupTracksSuccessful) {
+ ++mKeepAliveGeneration;
+ postKeepAlive();
+
+ 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));
+
+ ALOGI("PLAY completed with result %d (%s)",
+ 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 != 200) {
+ result = UNKNOWN_ERROR;
+ } else {
+ parsePlayResponse(response);
+
+ sp<AMessage> timeout = new AMessage('tiou', id());
+ timeout->post(kStartupTimeoutUs);
+ }
+ }
+
+ if (result != OK) {
+ sp<AMessage> reply = new AMessage('disc', id());
+ mConn->disconnect(reply);
+ }
+
+ break;
+ }
+
+ case 'aliv':
+ {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+
+ if (generation != mKeepAliveGeneration) {
+ // obsolete event.
+ break;
+ }
+
+ AString request;
+ request.append("OPTIONS ");
+ 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('opts', id());
+ reply->setInt32("generation", mKeepAliveGeneration);
+ mConn->sendRequest(request.c_str(), reply);
+ break;
+ }
+
+ case 'opts':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ ALOGI("OPTIONS completed with result %d (%s)",
+ result, strerror(-result));
+
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+
+ if (generation != mKeepAliveGeneration) {
+ // obsolete event.
+ break;
+ }
+
+ postKeepAlive();
+ break;
+ }
+
+ case 'abor':
+ {
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ TrackInfo *info = &mTracks.editItemAt(i);
+
+ if (!mFirstAccessUnit) {
+ postQueueEOS(i, ERROR_END_OF_STREAM);
+ }
+
+ if (!info->mUsingInterleavedTCP) {
+ mRTPConn->removeStream(info->mRTPSocket, info->mRTCPSocket);
+
+ // Clear the tag
+ if (mUIDValid) {
+ HTTPBase::UnRegisterSocketUserTag(info->mRTPSocket);
+ HTTPBase::UnRegisterSocketUserTag(info->mRTCPSocket);
+ }
+
+ close(info->mRTPSocket);
+ close(info->mRTCPSocket);
+ }
+ }
+ mTracks.clear();
+ mSetupTracksSuccessful = false;
+ mSeekPending = false;
+ mFirstAccessUnit = true;
+ mAllTracksHaveTime = false;
+ mNTPAnchorUs = -1;
+ mMediaAnchorUs = -1;
+ mNumAccessUnitsReceived = 0;
+ mReceivedFirstRTCPPacket = false;
+ mReceivedFirstRTPPacket = false;
+ mSeekable = false;
+
+ sp<AMessage> reply = new AMessage('tear', id());
+
+ int32_t reconnect;
+ if (msg->findInt32("reconnect", &reconnect) && reconnect) {
+ reply->setInt32("reconnect", true);
+ }
+
+ 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));
+
+ ALOGI("TEARDOWN completed with result %d (%s)",
+ result, strerror(-result));
+
+ sp<AMessage> reply = new AMessage('disc', id());
+
+ int32_t reconnect;
+ if (msg->findInt32("reconnect", &reconnect) && reconnect) {
+ reply->setInt32("reconnect", true);
+ }
+
+ mConn->disconnect(reply);
+ break;
+ }
+
+ case 'quit':
+ {
+ sp<AMessage> msg = mNotify->dup();
+ msg->setInt32("what", kWhatDisconnected);
+ msg->setInt32("result", UNKNOWN_ERROR);
+ msg->post();
+ break;
+ }
+
+ case 'chek':
+ {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+ if (generation != mCheckGeneration) {
+ // This is an outdated message. Ignore.
+ break;
+ }
+
+ if (mNumAccessUnitsReceived == 0) {
+#if 1
+ ALOGI("stream ended? aborting.");
+ (new AMessage('abor', id()))->post();
+ break;
+#else
+ ALOGI("haven't seen an AU in a looong time.");
+#endif
+ }
+
+ mNumAccessUnitsReceived = 0;
+ msg->post(kAccessUnitTimeoutUs);
+ break;
+ }
+
+ case 'accu':
+ {
+ int32_t timeUpdate;
+ if (msg->findInt32("time-update", &timeUpdate) && timeUpdate) {
+ size_t trackIndex;
+ CHECK(msg->findSize("track-index", &trackIndex));
+
+ uint32_t rtpTime;
+ uint64_t ntpTime;
+ CHECK(msg->findInt32("rtp-time", (int32_t *)&rtpTime));
+ CHECK(msg->findInt64("ntp-time", (int64_t *)&ntpTime));
+
+ onTimeUpdate(trackIndex, rtpTime, ntpTime);
+ break;
+ }
+
+ int32_t first;
+ if (msg->findInt32("first-rtcp", &first)) {
+ mReceivedFirstRTCPPacket = true;
+ break;
+ }
+
+ if (msg->findInt32("first-rtp", &first)) {
+ mReceivedFirstRTPPacket = true;
+ break;
+ }
+
+ ++mNumAccessUnitsReceived;
+ postAccessUnitTimeoutCheck();
+
+ size_t trackIndex;
+ CHECK(msg->findSize("track-index", &trackIndex));
+
+ if (trackIndex >= mTracks.size()) {
+ ALOGV("late packets ignored.");
+ break;
+ }
+
+ TrackInfo *track = &mTracks.editItemAt(trackIndex);
+
+ int32_t eos;
+ if (msg->findInt32("eos", &eos)) {
+ ALOGI("received BYE on track index %d", trackIndex);
+#if 0
+ track->mPacketSource->signalEOS(ERROR_END_OF_STREAM);
+#endif
+ return;
+ }
+
+ sp<ABuffer> accessUnit;
+ CHECK(msg->findBuffer("access-unit", &accessUnit));
+
+ uint32_t seqNum = (uint32_t)accessUnit->int32Data();
+
+ if (mSeekPending) {
+ ALOGV("we're seeking, dropping stale packet.");
+ break;
+ }
+
+ if (seqNum < track->mFirstSeqNumInSegment) {
+ ALOGV("dropping stale access-unit (%d < %d)",
+ seqNum, track->mFirstSeqNumInSegment);
+ break;
+ }
+
+ if (track->mNewSegment) {
+ track->mNewSegment = false;
+ }
+
+ onAccessUnitComplete(trackIndex, accessUnit);
+ break;
+ }
+
+ case 'seek':
+ {
+ if (!mSeekable) {
+ ALOGW("This is a live stream, ignoring seek request.");
+
+ sp<AMessage> msg = mNotify->dup();
+ msg->setInt32("what", kWhatSeekDone);
+ msg->post();
+ break;
+ }
+
+ int64_t timeUs;
+ CHECK(msg->findInt64("time", &timeUs));
+
+ mSeekPending = true;
+
+ // Disable the access unit timeout until we resumed
+ // playback again.
+ mCheckPending = true;
+ ++mCheckGeneration;
+
+ AString request = "PAUSE ";
+ 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('see1', id());
+ reply->setInt64("time", timeUs);
+ mConn->sendRequest(request.c_str(), reply);
+ break;
+ }
+
+ case 'see1':
+ {
+ // Session is paused now.
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ TrackInfo *info = &mTracks.editItemAt(i);
+
+ postQueueSeekDiscontinuity(i);
+
+ info->mRTPAnchor = 0;
+ info->mNTPAnchorUs = -1;
+ }
+
+ mAllTracksHaveTime = false;
+ mNTPAnchorUs = -1;
+
+ int64_t timeUs;
+ CHECK(msg->findInt64("time", &timeUs));
+
+ 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(
+ StringPrintf(
+ "Range: npt=%lld-\r\n", timeUs / 1000000ll));
+
+ request.append("\r\n");
+
+ sp<AMessage> reply = new AMessage('see2', id());
+ mConn->sendRequest(request.c_str(), reply);
+ break;
+ }
+
+ case 'see2':
+ {
+ CHECK(mSeekPending);
+
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ ALOGI("PLAY completed with result %d (%s)",
+ result, strerror(-result));
+
+ mCheckPending = false;
+ postAccessUnitTimeoutCheck();
+
+ if (result == OK) {
+ sp<RefBase> obj;
+ CHECK(msg->findObject("response", &obj));
+ sp<ARTSPResponse> response =
+ static_cast<ARTSPResponse *>(obj.get());
+
+ if (response->mStatusCode != 200) {
+ result = UNKNOWN_ERROR;
+ } else {
+ parsePlayResponse(response);
+
+ ssize_t i = response->mHeaders.indexOfKey("rtp-info");
+ CHECK_GE(i, 0);
+
+ ALOGV("rtp-info: %s", response->mHeaders.valueAt(i).c_str());
+
+ ALOGI("seek completed.");
+ }
+ }
+
+ if (result != OK) {
+ ALOGE("seek failed, aborting.");
+ (new AMessage('abor', id()))->post();
+ }
+
+ mSeekPending = false;
+
+ sp<AMessage> msg = mNotify->dup();
+ msg->setInt32("what", kWhatSeekDone);
+ msg->post();
+ break;
+ }
+
+ case 'biny':
+ {
+ sp<ABuffer> buffer;
+ CHECK(msg->findBuffer("buffer", &buffer));
+
+ int32_t index;
+ CHECK(buffer->meta()->findInt32("index", &index));
+
+ mRTPConn->injectPacket(index, buffer);
+ break;
+ }
+
+ case 'tiou':
+ {
+ if (!mReceivedFirstRTCPPacket) {
+ if (mReceivedFirstRTPPacket && !mTryFakeRTCP) {
+ ALOGW("We received RTP packets but no RTCP packets, "
+ "using fake timestamps.");
+
+ mTryFakeRTCP = true;
+
+ mReceivedFirstRTCPPacket = true;
+
+ fakeTimestamps();
+ } else if (!mReceivedFirstRTPPacket && !mTryTCPInterleaving) {
+ ALOGW("Never received any data, switching transports.");
+
+ mTryTCPInterleaving = true;
+
+ sp<AMessage> msg = new AMessage('abor', id());
+ msg->setInt32("reconnect", true);
+ msg->post();
+ } else {
+ ALOGW("Never received any data, disconnecting.");
+ (new AMessage('abor', id()))->post();
+ }
+ } else {
+ if (!mAllTracksHaveTime) {
+ ALOGW("We received some RTCP packets, but time "
+ "could not be established on all tracks, now "
+ "using fake timestamps");
+
+ fakeTimestamps();
+ }
+ }
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+ }
+
+ void postKeepAlive() {
+ sp<AMessage> msg = new AMessage('aliv', id());
+ msg->setInt32("generation", mKeepAliveGeneration);
+ msg->post((mKeepAliveTimeoutUs * 9) / 10);
+ }
+
+ void postAccessUnitTimeoutCheck() {
+ if (mCheckPending) {
+ return;
+ }
+
+ mCheckPending = true;
+ sp<AMessage> check = new AMessage('chek', id());
+ check->setInt32("generation", mCheckGeneration);
+ check->post(kAccessUnitTimeoutUs);
+ }
+
+ static void SplitString(
+ const AString &s, const char *separator, List<AString> *items) {
+ items->clear();
+ size_t start = 0;
+ while (start < s.size()) {
+ ssize_t offset = s.find(separator, start);
+
+ if (offset < 0) {
+ items->push_back(AString(s, start, s.size() - start));
+ break;
+ }
+
+ items->push_back(AString(s, start, offset - start));
+ start = offset + strlen(separator);
+ }
+ }
+
+ void parsePlayResponse(const sp<ARTSPResponse> &response) {
+ mSeekable = false;
+
+ ssize_t i = response->mHeaders.indexOfKey("range");
+ if (i < 0) {
+ // Server doesn't even tell use what range it is going to
+ // play, therefore we won't support seeking.
+ return;
+ }
+
+ AString range = response->mHeaders.valueAt(i);
+ ALOGV("Range: %s", range.c_str());
+
+ AString val;
+ CHECK(GetAttribute(range.c_str(), "npt", &val));
+
+ float npt1, npt2;
+ if (!ASessionDescription::parseNTPRange(val.c_str(), &npt1, &npt2)) {
+ // This is a live stream and therefore not seekable.
+
+ ALOGI("This is a live stream");
+ return;
+ }
+
+ i = response->mHeaders.indexOfKey("rtp-info");
+ CHECK_GE(i, 0);
+
+ AString rtpInfo = response->mHeaders.valueAt(i);
+ List<AString> streamInfos;
+ SplitString(rtpInfo, ",", &streamInfos);
+
+ int n = 1;
+ for (List<AString>::iterator it = streamInfos.begin();
+ it != streamInfos.end(); ++it) {
+ (*it).trim();
+ ALOGV("streamInfo[%d] = %s", n, (*it).c_str());
+
+ CHECK(GetAttribute((*it).c_str(), "url", &val));
+
+ size_t trackIndex = 0;
+ while (trackIndex < mTracks.size()
+ && !(val == mTracks.editItemAt(trackIndex).mURL)) {
+ ++trackIndex;
+ }
+ CHECK_LT(trackIndex, mTracks.size());
+
+ CHECK(GetAttribute((*it).c_str(), "seq", &val));
+
+ char *end;
+ unsigned long seq = strtoul(val.c_str(), &end, 10);
+
+ TrackInfo *info = &mTracks.editItemAt(trackIndex);
+ info->mFirstSeqNumInSegment = seq;
+ info->mNewSegment = true;
+
+ CHECK(GetAttribute((*it).c_str(), "rtptime", &val));
+
+ uint32_t rtpTime = strtoul(val.c_str(), &end, 10);
+
+ ALOGV("track #%d: rtpTime=%u <=> npt=%.2f", n, rtpTime, npt1);
+
+ info->mNormalPlayTimeRTP = rtpTime;
+ info->mNormalPlayTimeUs = (int64_t)(npt1 * 1E6);
+
+ if (!mFirstAccessUnit) {
+ postNormalPlayTimeMapping(
+ trackIndex,
+ info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
+ }
+
+ ++n;
+ }
+
+ mSeekable = true;
+ }
+
+ sp<MetaData> getTrackFormat(size_t index, int32_t *timeScale) {
+ CHECK_GE(index, 0u);
+ CHECK_LT(index, mTracks.size());
+
+ const TrackInfo &info = mTracks.itemAt(index);
+
+ *timeScale = info.mTimeScale;
+
+ return info.mPacketSource->getFormat();
+ }
+
+ size_t countTracks() const {
+ return mTracks.size();
+ }
+
+private:
+ struct TrackInfo {
+ AString mURL;
+ int mRTPSocket;
+ int mRTCPSocket;
+ bool mUsingInterleavedTCP;
+ uint32_t mFirstSeqNumInSegment;
+ bool mNewSegment;
+
+ uint32_t mRTPAnchor;
+ int64_t mNTPAnchorUs;
+ int32_t mTimeScale;
+
+ uint32_t mNormalPlayTimeRTP;
+ int64_t mNormalPlayTimeUs;
+
+ sp<APacketSource> mPacketSource;
+
+ // Stores packets temporarily while no notion of time
+ // has been established yet.
+ List<sp<ABuffer> > mPackets;
+ };
+
+ sp<AMessage> mNotify;
+ bool mUIDValid;
+ uid_t mUID;
+ sp<ALooper> mNetLooper;
+ sp<ARTSPConnection> mConn;
+ sp<ARTPConnection> mRTPConn;
+ sp<ASessionDescription> mSessionDesc;
+ AString mOriginalSessionURL; // This one still has user:pass@
+ AString mSessionURL;
+ AString mSessionHost;
+ AString mBaseURL;
+ AString mSessionID;
+ bool mSetupTracksSuccessful;
+ bool mSeekPending;
+ bool mFirstAccessUnit;
+
+ bool mAllTracksHaveTime;
+ int64_t mNTPAnchorUs;
+ int64_t mMediaAnchorUs;
+ int64_t mLastMediaTimeUs;
+
+ int64_t mNumAccessUnitsReceived;
+ bool mCheckPending;
+ int32_t mCheckGeneration;
+ bool mTryTCPInterleaving;
+ bool mTryFakeRTCP;
+ bool mReceivedFirstRTCPPacket;
+ bool mReceivedFirstRTPPacket;
+ bool mSeekable;
+ int64_t mKeepAliveTimeoutUs;
+ int32_t mKeepAliveGeneration;
+
+ Vector<TrackInfo> mTracks;
+
+ void setupTrack(size_t index) {
+ sp<APacketSource> source =
+ new APacketSource(mSessionDesc, index);
+
+ if (source->initCheck() != OK) {
+ ALOGW("Unsupported format. Ignoring track #%d.", index);
+
+ sp<AMessage> reply = new AMessage('setu', id());
+ reply->setSize("index", index);
+ reply->setInt32("result", ERROR_UNSUPPORTED);
+ reply->post();
+ return;
+ }
+
+ 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);
+ info->mURL = trackURL;
+ info->mPacketSource = source;
+ info->mUsingInterleavedTCP = false;
+ info->mFirstSeqNumInSegment = 0;
+ info->mNewSegment = true;
+ info->mRTPAnchor = 0;
+ info->mNTPAnchorUs = -1;
+ info->mNormalPlayTimeRTP = 0;
+ info->mNormalPlayTimeUs = 0ll;
+
+ unsigned long PT;
+ AString formatDesc;
+ AString formatParams;
+ mSessionDesc->getFormatType(index, &PT, &formatDesc, &formatParams);
+
+ int32_t timescale;
+ int32_t numChannels;
+ ASessionDescription::ParseFormatDesc(
+ formatDesc.c_str(), &timescale, &numChannels);
+
+ info->mTimeScale = timescale;
+
+ ALOGV("track #%d URL=%s", mTracks.size(), trackURL.c_str());
+
+ AString request = "SETUP ";
+ request.append(trackURL);
+ request.append(" RTSP/1.0\r\n");
+
+ if (mTryTCPInterleaving) {
+ size_t interleaveIndex = 2 * (mTracks.size() - 1);
+ info->mUsingInterleavedTCP = true;
+ info->mRTPSocket = interleaveIndex;
+ info->mRTCPSocket = interleaveIndex + 1;
+
+ request.append("Transport: RTP/AVP/TCP;interleaved=");
+ request.append(interleaveIndex);
+ request.append("-");
+ request.append(interleaveIndex + 1);
+ } else {
+ unsigned rtpPort;
+ ARTPConnection::MakePortPair(
+ &info->mRTPSocket, &info->mRTCPSocket, &rtpPort);
+
+ if (mUIDValid) {
+ HTTPBase::RegisterSocketUserTag(info->mRTPSocket, mUID,
+ (uint32_t)*(uint32_t*) "RTP_");
+ HTTPBase::RegisterSocketUserTag(info->mRTCPSocket, mUID,
+ (uint32_t)*(uint32_t*) "RTP_");
+ }
+
+ 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 {
+ const char *slashPos = strrchr(baseURL, '/');
+
+ if (slashPos > &baseURL[6]) {
+ out->setTo(baseURL, slashPos - baseURL);
+ } else {
+ out->setTo(baseURL);
+ }
+
+ out->append("/");
+ out->append(url);
+ }
+
+ return true;
+ }
+
+ void fakeTimestamps() {
+ mNTPAnchorUs = -1ll;
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ onTimeUpdate(i, 0, 0ll);
+ }
+ }
+
+ void onTimeUpdate(int32_t trackIndex, uint32_t rtpTime, uint64_t ntpTime) {
+ ALOGV("onTimeUpdate track %d, rtpTime = 0x%08x, ntpTime = 0x%016llx",
+ trackIndex, rtpTime, ntpTime);
+
+ int64_t ntpTimeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
+
+ TrackInfo *track = &mTracks.editItemAt(trackIndex);
+
+ track->mRTPAnchor = rtpTime;
+ track->mNTPAnchorUs = ntpTimeUs;
+
+ if (mNTPAnchorUs < 0) {
+ mNTPAnchorUs = ntpTimeUs;
+ mMediaAnchorUs = mLastMediaTimeUs;
+ }
+
+ if (!mAllTracksHaveTime) {
+ bool allTracksHaveTime = true;
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ TrackInfo *track = &mTracks.editItemAt(i);
+ if (track->mNTPAnchorUs < 0) {
+ allTracksHaveTime = false;
+ break;
+ }
+ }
+ if (allTracksHaveTime) {
+ mAllTracksHaveTime = true;
+ ALOGI("Time now established for all tracks.");
+ }
+ }
+ }
+
+ void onAccessUnitComplete(
+ int32_t trackIndex, const sp<ABuffer> &accessUnit) {
+ ALOGV("onAccessUnitComplete track %d", trackIndex);
+
+ if (mFirstAccessUnit) {
+ sp<AMessage> msg = mNotify->dup();
+ msg->setInt32("what", kWhatConnected);
+ msg->post();
+
+ if (mSeekable) {
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ TrackInfo *info = &mTracks.editItemAt(i);
+
+ postNormalPlayTimeMapping(
+ i,
+ info->mNormalPlayTimeRTP, info->mNormalPlayTimeUs);
+ }
+ }
+
+ mFirstAccessUnit = false;
+ }
+
+ TrackInfo *track = &mTracks.editItemAt(trackIndex);
+
+ if (!mAllTracksHaveTime) {
+ ALOGV("storing accessUnit, no time established yet");
+ track->mPackets.push_back(accessUnit);
+ return;
+ }
+
+ while (!track->mPackets.empty()) {
+ sp<ABuffer> accessUnit = *track->mPackets.begin();
+ track->mPackets.erase(track->mPackets.begin());
+
+ if (addMediaTimestamp(trackIndex, track, accessUnit)) {
+ postQueueAccessUnit(trackIndex, accessUnit);
+ }
+ }
+
+ if (addMediaTimestamp(trackIndex, track, accessUnit)) {
+ postQueueAccessUnit(trackIndex, accessUnit);
+ }
+ }
+
+ bool addMediaTimestamp(
+ int32_t trackIndex, const TrackInfo *track,
+ const sp<ABuffer> &accessUnit) {
+ uint32_t rtpTime;
+ CHECK(accessUnit->meta()->findInt32(
+ "rtp-time", (int32_t *)&rtpTime));
+
+ int64_t relRtpTimeUs =
+ (((int64_t)rtpTime - (int64_t)track->mRTPAnchor) * 1000000ll)
+ / track->mTimeScale;
+
+ int64_t ntpTimeUs = track->mNTPAnchorUs + relRtpTimeUs;
+
+ int64_t mediaTimeUs = mMediaAnchorUs + ntpTimeUs - mNTPAnchorUs;
+
+ if (mediaTimeUs > mLastMediaTimeUs) {
+ mLastMediaTimeUs = mediaTimeUs;
+ }
+
+ if (mediaTimeUs < 0) {
+ ALOGV("dropping early accessUnit.");
+ return false;
+ }
+
+ ALOGV("track %d rtpTime=%d mediaTimeUs = %lld us (%.2f secs)",
+ trackIndex, rtpTime, mediaTimeUs, mediaTimeUs / 1E6);
+
+ accessUnit->meta()->setInt64("timeUs", mediaTimeUs);
+
+ return true;
+ }
+
+ void postQueueAccessUnit(
+ size_t trackIndex, const sp<ABuffer> &accessUnit) {
+ sp<AMessage> msg = mNotify->dup();
+ msg->setInt32("what", kWhatAccessUnit);
+ msg->setSize("trackIndex", trackIndex);
+ msg->setBuffer("accessUnit", accessUnit);
+ msg->post();
+ }
+
+ void postQueueEOS(size_t trackIndex, status_t finalResult) {
+ sp<AMessage> msg = mNotify->dup();
+ msg->setInt32("what", kWhatEOS);
+ msg->setSize("trackIndex", trackIndex);
+ msg->setInt32("finalResult", finalResult);
+ msg->post();
+ }
+
+ void postQueueSeekDiscontinuity(size_t trackIndex) {
+ sp<AMessage> msg = mNotify->dup();
+ msg->setInt32("what", kWhatSeekDiscontinuity);
+ msg->setSize("trackIndex", trackIndex);
+ msg->post();
+ }
+
+ void postNormalPlayTimeMapping(
+ size_t trackIndex, uint32_t rtpTime, int64_t nptUs) {
+ sp<AMessage> msg = mNotify->dup();
+ msg->setInt32("what", kWhatNormalPlayTimeMapping);
+ msg->setSize("trackIndex", trackIndex);
+ msg->setInt32("rtpTime", rtpTime);
+ msg->setInt64("nptUs", nptUs);
+ msg->post();
+ }
+
+ 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/UDPPusher.cpp b/media/libstagefright/rtsp/UDPPusher.cpp
new file mode 100644
index 0000000..47ea6f1
--- /dev/null
+++ b/media/libstagefright/rtsp/UDPPusher.cpp
@@ -0,0 +1,150 @@
+/*
+ * 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 "UDPPusher"
+#include <utils/Log.h>
+
+#include "UDPPusher.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <utils/ByteOrder.h>
+
+#include <sys/socket.h>
+
+namespace android {
+
+UDPPusher::UDPPusher(const char *filename, unsigned port)
+ : mFile(fopen(filename, "rb")),
+ mFirstTimeMs(0),
+ mFirstTimeUs(0) {
+ CHECK(mFile != NULL);
+
+ mSocket = socket(AF_INET, SOCK_DGRAM, 0);
+
+ 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 = 0;
+
+ CHECK_EQ(0, bind(mSocket, (const struct sockaddr *)&addr, sizeof(addr)));
+
+ memset(mRemoteAddr.sin_zero, 0, sizeof(mRemoteAddr.sin_zero));
+ mRemoteAddr.sin_family = AF_INET;
+ mRemoteAddr.sin_addr.s_addr = INADDR_ANY;
+ mRemoteAddr.sin_port = htons(port);
+}
+
+UDPPusher::~UDPPusher() {
+ close(mSocket);
+ mSocket = -1;
+
+ fclose(mFile);
+ mFile = NULL;
+}
+
+void UDPPusher::start() {
+ uint32_t timeMs;
+ CHECK_EQ(fread(&timeMs, 1, sizeof(timeMs), mFile), sizeof(timeMs));
+ mFirstTimeMs = fromlel(timeMs);
+ mFirstTimeUs = ALooper::GetNowUs();
+
+ (new AMessage(kWhatPush, id()))->post();
+}
+
+bool UDPPusher::onPush() {
+ uint32_t length;
+ if (fread(&length, 1, sizeof(length), mFile) < sizeof(length)) {
+ ALOGI("No more data to push.");
+ return false;
+ }
+
+ length = fromlel(length);
+
+ CHECK_GT(length, 0u);
+
+ sp<ABuffer> buffer = new ABuffer(length);
+ if (fread(buffer->data(), 1, length, mFile) < length) {
+ ALOGE("File truncated?.");
+ return false;
+ }
+
+ ssize_t n = sendto(
+ mSocket, buffer->data(), buffer->size(), 0,
+ (const struct sockaddr *)&mRemoteAddr, sizeof(mRemoteAddr));
+
+ CHECK_EQ(n, (ssize_t)buffer->size());
+
+ uint32_t timeMs;
+ if (fread(&timeMs, 1, sizeof(timeMs), mFile) < sizeof(timeMs)) {
+ ALOGI("No more data to push.");
+ return false;
+ }
+
+ timeMs = fromlel(timeMs);
+ CHECK_GE(timeMs, mFirstTimeMs);
+
+ timeMs -= mFirstTimeMs;
+ int64_t whenUs = mFirstTimeUs + timeMs * 1000ll;
+ int64_t nowUs = ALooper::GetNowUs();
+ (new AMessage(kWhatPush, id()))->post(whenUs - nowUs);
+
+ return true;
+}
+
+void UDPPusher::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatPush:
+ {
+ if (!onPush() && !(ntohs(mRemoteAddr.sin_port) & 1)) {
+ ALOGI("emulating BYE packet");
+
+ sp<ABuffer> buffer = new ABuffer(8);
+ uint8_t *data = buffer->data();
+ *data++ = (2 << 6) | 1;
+ *data++ = 203;
+ *data++ = 0;
+ *data++ = 1;
+ *data++ = 0x8f;
+ *data++ = 0x49;
+ *data++ = 0xc0;
+ *data++ = 0xd0;
+ buffer->setRange(0, 8);
+
+ struct sockaddr_in tmp = mRemoteAddr;
+ tmp.sin_port = htons(ntohs(mRemoteAddr.sin_port) | 1);
+
+ ssize_t n = sendto(
+ mSocket, buffer->data(), buffer->size(), 0,
+ (const struct sockaddr *)&tmp,
+ sizeof(tmp));
+
+ CHECK_EQ(n, (ssize_t)buffer->size());
+ }
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/rtsp/UDPPusher.h b/media/libstagefright/rtsp/UDPPusher.h
new file mode 100644
index 0000000..2bde533
--- /dev/null
+++ b/media/libstagefright/rtsp/UDPPusher.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 UDP_PUSHER_H_
+
+#define UDP_PUSHER_H_
+
+#include <media/stagefright/foundation/AHandler.h>
+
+#include <stdio.h>
+#include <arpa/inet.h>
+
+namespace android {
+
+struct UDPPusher : public AHandler {
+ UDPPusher(const char *filename, unsigned port);
+
+ void start();
+
+protected:
+ virtual ~UDPPusher();
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+ enum {
+ kWhatPush = 'push'
+ };
+
+ FILE *mFile;
+ int mSocket;
+ struct sockaddr_in mRemoteAddr;
+
+ uint32_t mFirstTimeMs;
+ int64_t mFirstTimeUs;
+
+ bool onPush();
+
+ DISALLOW_EVIL_CONSTRUCTORS(UDPPusher);
+};
+
+} // namespace android
+
+#endif // UDP_PUSHER_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_
diff --git a/media/libstagefright/rtsp/rtp_test.cpp b/media/libstagefright/rtsp/rtp_test.cpp
new file mode 100644
index 0000000..d43cd2a
--- /dev/null
+++ b/media/libstagefright/rtsp/rtp_test.cpp
@@ -0,0 +1,230 @@
+/*
+ * 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 "rtp_test"
+#include <utils/Log.h>
+
+#include <binder/ProcessState.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/foundation/base64.h>
+
+#include "ARTPSession.h"
+#include "ASessionDescription.h"
+#include "UDPPusher.h"
+
+using namespace android;
+
+int main(int argc, char **argv) {
+ android::ProcessState::self()->startThreadPool();
+
+ DataSource::RegisterDefaultSniffers();
+
+ const char *rtpFilename = NULL;
+ const char *rtcpFilename = NULL;
+
+ if (argc == 3) {
+ rtpFilename = argv[1];
+ rtcpFilename = argv[2];
+ } else if (argc != 1) {
+ fprintf(stderr, "usage: %s [ rtpFilename rtcpFilename ]\n", argv[0]);
+ return 1;
+ }
+
+#if 0
+ static const uint8_t kSPS[] = {
+ 0x67, 0x42, 0x80, 0x0a, 0xe9, 0x02, 0x83, 0xe4, 0x20, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x0e, 0xa6, 0x00, 0x80
+ };
+ static const uint8_t kPPS[] = {
+ 0x68, 0xce, 0x3c, 0x80
+ };
+ AString out1, out2;
+ encodeBase64(kSPS, sizeof(kSPS), &out1);
+ encodeBase64(kPPS, sizeof(kPPS), &out2);
+ printf("params=%s,%s\n", out1.c_str(), out2.c_str());
+#endif
+
+ sp<ALooper> looper = new ALooper;
+
+ sp<UDPPusher> rtp_pusher;
+ sp<UDPPusher> rtcp_pusher;
+
+ if (rtpFilename != NULL) {
+ rtp_pusher = new UDPPusher(rtpFilename, 5434);
+ looper->registerHandler(rtp_pusher);
+
+ rtcp_pusher = new UDPPusher(rtcpFilename, 5435);
+ looper->registerHandler(rtcp_pusher);
+ }
+
+ sp<ARTPSession> session = new ARTPSession;
+ looper->registerHandler(session);
+
+#if 0
+ // My H264 SDP
+ static const char *raw =
+ "v=0\r\n"
+ "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
+ "s=QuickTime\r\n"
+ "t=0 0\r\n"
+ "a=range:npt=0-315\r\n"
+ "a=isma-compliance:2,2.0,2\r\n"
+ "m=video 5434 RTP/AVP 97\r\n"
+ "c=IN IP4 127.0.0.1\r\n"
+ "b=AS:30\r\n"
+ "a=rtpmap:97 H264/90000\r\n"
+ "a=fmtp:97 packetization-mode=1;profile-level-id=42000C;"
+ "sprop-parameter-sets=Z0IADJZUCg+I,aM44gA==\r\n"
+ "a=mpeg4-esid:201\r\n"
+ "a=cliprect:0,0,240,320\r\n"
+ "a=framesize:97 320-240\r\n";
+#elif 0
+ // My H263 SDP
+ static const char *raw =
+ "v=0\r\n"
+ "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
+ "s=QuickTime\r\n"
+ "t=0 0\r\n"
+ "a=range:npt=0-315\r\n"
+ "a=isma-compliance:2,2.0,2\r\n"
+ "m=video 5434 RTP/AVP 97\r\n"
+ "c=IN IP4 127.0.0.1\r\n"
+ "b=AS:30\r\n"
+ "a=rtpmap:97 H263-1998/90000\r\n"
+ "a=cliprect:0,0,240,320\r\n"
+ "a=framesize:97 320-240\r\n";
+#elif 0
+ // My AMR SDP
+ static const char *raw =
+ "v=0\r\n"
+ "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
+ "s=QuickTime\r\n"
+ "t=0 0\r\n"
+ "a=range:npt=0-315\r\n"
+ "a=isma-compliance:2,2.0,2\r\n"
+ "m=audio 5434 RTP/AVP 97\r\n"
+ "c=IN IP4 127.0.0.1\r\n"
+ "b=AS:30\r\n"
+ "a=rtpmap:97 AMR/8000/1\r\n"
+ "a=fmtp:97 octet-align\r\n";
+#elif 1
+ // GTalk's H264 SDP
+ static const char *raw =
+ "v=0\r\n"
+ "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
+ "s=QuickTime\r\n"
+ "t=0 0\r\n"
+ "a=range:npt=now-\r\n"
+ "m=video 5434 RTP/AVP 96\r\n"
+ "c=IN IP4 127.0.0.1\r\n"
+ "b=AS:320000\r\n"
+ "a=rtpmap:96 H264/90000\r\n"
+ "a=fmtp:96 packetization-mode=1;profile-level-id=42001E;"
+ "sprop-parameter-sets=Z0IAHpZUBaHogA==,aM44gA==\r\n"
+ "a=cliprect:0,0,480,270\r\n"
+ "a=framesize:96 720-480\r\n";
+#else
+ // sholes H264 SDP
+ static const char *raw =
+ "v=0\r\n"
+ "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
+ "s=QuickTime\r\n"
+ "t=0 0\r\n"
+ "a=range:npt=now-\r\n"
+ "m=video 5434 RTP/AVP 96\r\n"
+ "c=IN IP4 127.0.0.1\r\n"
+ "b=AS:320000\r\n"
+ "a=rtpmap:96 H264/90000\r\n"
+ "a=fmtp:96 packetization-mode=1;profile-level-id=42001E;"
+ "sprop-parameter-sets=Z0KACukCg+QgAAB9AAAOpgCA,aM48gA==\r\n"
+ "a=cliprect:0,0,240,320\r\n"
+ "a=framesize:96 320-240\r\n";
+#endif
+
+ sp<ASessionDescription> desc = new ASessionDescription;
+ CHECK(desc->setTo(raw, strlen(raw)));
+
+ CHECK_EQ(session->setup(desc), (status_t)OK);
+
+ if (rtp_pusher != NULL) {
+ rtp_pusher->start();
+ }
+
+ if (rtcp_pusher != NULL) {
+ rtcp_pusher->start();
+ }
+
+ looper->start(false /* runOnCallingThread */);
+
+ CHECK_EQ(session->countTracks(), 1u);
+ sp<MediaSource> source = session->trackAt(0);
+
+ OMXClient client;
+ CHECK_EQ(client.connect(), (status_t)OK);
+
+ sp<MediaSource> decoder = OMXCodec::Create(
+ client.interface(),
+ source->getFormat(), false /* createEncoder */,
+ source,
+ NULL,
+ 0); // OMXCodec::kPreferSoftwareCodecs);
+ CHECK(decoder != NULL);
+
+ CHECK_EQ(decoder->start(), (status_t)OK);
+
+ for (;;) {
+ MediaBuffer *buffer;
+ status_t err = decoder->read(&buffer);
+
+ if (err != OK) {
+ if (err == INFO_FORMAT_CHANGED) {
+ int32_t width, height;
+ CHECK(decoder->getFormat()->findInt32(kKeyWidth, &width));
+ CHECK(decoder->getFormat()->findInt32(kKeyHeight, &height));
+ printf("INFO_FORMAT_CHANGED %d x %d\n", width, height);
+ continue;
+ }
+
+ ALOGE("decoder returned error 0x%08x", err);
+ break;
+ }
+
+#if 1
+ if (buffer->range_length() != 0) {
+ int64_t timeUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+
+ printf("decoder returned frame of size %d at time %.2f secs\n",
+ buffer->range_length(), timeUs / 1E6);
+ }
+#endif
+
+ buffer->release();
+ buffer = NULL;
+ }
+
+ CHECK_EQ(decoder->stop(), (status_t)OK);
+
+ looper->stop();
+
+ return 0;
+}
diff --git a/media/libstagefright/tests/Android.mk b/media/libstagefright/tests/Android.mk
new file mode 100644
index 0000000..656a630
--- /dev/null
+++ b/media/libstagefright/tests/Android.mk
@@ -0,0 +1,54 @@
+# Build the unit tests.
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_MODULE := SurfaceMediaSource_test
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+ SurfaceMediaSource_test.cpp \
+ DummyRecorder.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+ libEGL \
+ libGLESv2 \
+ libandroid \
+ libbinder \
+ libcutils \
+ libgui \
+ libmedia \
+ libstagefright \
+ libstagefright_omx \
+ libstagefright_foundation \
+ libstlport \
+ libui \
+ libutils \
+
+LOCAL_STATIC_LIBRARIES := \
+ libgtest \
+ libgtest_main \
+
+LOCAL_C_INCLUDES := \
+ bionic \
+ bionic/libstdc++/include \
+ external/gtest/include \
+ external/stlport/stlport \
+ frameworks/base/media/libstagefright \
+ frameworks/base/media/libstagefright/include \
+ $(TOP)/frameworks/native/include/media/openmax \
+
+include $(BUILD_EXECUTABLE)
+
+endif
+
+# Include subdirectory makefiles
+# ============================================================
+
+# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
+# team really wants is to build the stuff defined by this makefile.
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/media/libstagefright/tests/DummyRecorder.cpp b/media/libstagefright/tests/DummyRecorder.cpp
new file mode 100644
index 0000000..ac37b28
--- /dev/null
+++ b/media/libstagefright/tests/DummyRecorder.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "DummyRecorder"
+// #define LOG_NDEBUG 0
+
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+#include "DummyRecorder.h"
+
+#include <utils/Log.h>
+
+namespace android {
+
+// static
+void *DummyRecorder::threadWrapper(void *pthis) {
+ ALOGV("ThreadWrapper: %p", pthis);
+ DummyRecorder *writer = static_cast<DummyRecorder *>(pthis);
+ writer->readFromSource();
+ return NULL;
+}
+
+
+status_t DummyRecorder::start() {
+ ALOGV("Start");
+ mStarted = true;
+
+ mSource->start();
+
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ int err = pthread_create(&mThread, &attr, threadWrapper, this);
+ pthread_attr_destroy(&attr);
+
+ if (err) {
+ ALOGE("Error creating thread!");
+ return -ENODEV;
+ }
+ return OK;
+}
+
+
+status_t DummyRecorder::stop() {
+ ALOGV("Stop");
+ mStarted = false;
+
+ mSource->stop();
+ void *dummy;
+ pthread_join(mThread, &dummy);
+ status_t err = (status_t) dummy;
+
+ ALOGV("Ending the reading thread");
+ return err;
+}
+
+// pretend to read the source buffers
+void DummyRecorder::readFromSource() {
+ ALOGV("ReadFromSource");
+ if (!mStarted) {
+ return;
+ }
+
+ status_t err = OK;
+ MediaBuffer *buffer;
+ ALOGV("A fake writer accessing the frames");
+ while (mStarted && (err = mSource->read(&buffer)) == OK){
+ // if not getting a valid buffer from source, then exit
+ if (buffer == NULL) {
+ return;
+ }
+ buffer->release();
+ buffer = NULL;
+ }
+}
+
+
+} // end of namespace android
diff --git a/media/libstagefright/tests/DummyRecorder.h b/media/libstagefright/tests/DummyRecorder.h
new file mode 100644
index 0000000..1cbea1b
--- /dev/null
+++ b/media/libstagefright/tests/DummyRecorder.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 DUMMY_RECORDER_H_
+#define DUMMY_RECORDER_H_
+
+#include <pthread.h>
+#include <utils/String8.h>
+#include <media/stagefright/foundation/ABase.h>
+
+
+namespace android {
+
+class MediaSource;
+class MediaBuffer;
+
+class DummyRecorder {
+ public:
+ // The media source from which this will receive frames
+ sp<MediaSource> mSource;
+ bool mStarted;
+ pthread_t mThread;
+
+ status_t start();
+ status_t stop();
+
+ // actual entry point for the thread
+ void readFromSource();
+
+ // static function to wrap the actual thread entry point
+ static void *threadWrapper(void *pthis);
+
+ DummyRecorder(const sp<MediaSource> &source) : mSource(source)
+ , mStarted(false) {}
+ ~DummyRecorder( ) {}
+
+ private:
+
+ DISALLOW_EVIL_CONSTRUCTORS(DummyRecorder);
+};
+
+} // end of namespace android
+#endif
+
+
diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
new file mode 100644
index 0000000..fe77cf7
--- /dev/null
+++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
@@ -0,0 +1,937 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SurfaceMediaSource_test"
+
+#include <gtest/gtest.h>
+#include <utils/String8.h>
+#include <utils/Errors.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <media/stagefright/SurfaceMediaSource.h>
+#include <media/mediarecorder.h>
+
+#include <ui/GraphicBuffer.h>
+#include <gui/SurfaceTextureClient.h>
+#include <gui/ISurfaceComposer.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+
+#include <binder/ProcessState.h>
+#include <ui/FramebufferNativeWindow.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#include <OMX_Component.h>
+
+#include "DummyRecorder.h"
+
+
+namespace android {
+
+class GLTest : public ::testing::Test {
+protected:
+
+ GLTest():
+ mEglDisplay(EGL_NO_DISPLAY),
+ mEglSurface(EGL_NO_SURFACE),
+ mEglContext(EGL_NO_CONTEXT) {
+ }
+
+ virtual void SetUp() {
+ ALOGV("GLTest::SetUp()");
+ mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
+
+ EGLint majorVersion;
+ EGLint minorVersion;
+ EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ RecordProperty("EglVersionMajor", majorVersion);
+ RecordProperty("EglVersionMajor", minorVersion);
+
+ EGLint numConfigs = 0;
+ EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig,
+ 1, &numConfigs));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS");
+ if (displaySecsEnv != NULL) {
+ mDisplaySecs = atoi(displaySecsEnv);
+ if (mDisplaySecs < 0) {
+ mDisplaySecs = 0;
+ }
+ } else {
+ mDisplaySecs = 0;
+ }
+
+ if (mDisplaySecs > 0) {
+ mComposerClient = new SurfaceComposerClient;
+ ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
+
+ mSurfaceControl = mComposerClient->createSurface(
+ String8("Test Surface"), 0,
+ getSurfaceWidth(), getSurfaceHeight(),
+ PIXEL_FORMAT_RGB_888, 0);
+
+ ASSERT_TRUE(mSurfaceControl != NULL);
+ ASSERT_TRUE(mSurfaceControl->isValid());
+
+ SurfaceComposerClient::openGlobalTransaction();
+ ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
+ ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
+ SurfaceComposerClient::closeGlobalTransaction();
+
+ sp<ANativeWindow> window = mSurfaceControl->getSurface();
+ mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
+ window.get(), NULL);
+ } else {
+ ALOGV("No actual display. Choosing EGLSurface based on SurfaceMediaSource");
+ sp<ISurfaceTexture> sms = new SurfaceMediaSource(
+ getSurfaceWidth(), getSurfaceHeight());
+ sp<SurfaceTextureClient> stc = new SurfaceTextureClient(sms);
+ sp<ANativeWindow> window = stc;
+
+ mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
+ window.get(), NULL);
+ }
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
+
+ mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT,
+ getContextAttribs());
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
+
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+ mEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ EGLint w, h;
+ EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ RecordProperty("EglSurfaceWidth", w);
+ RecordProperty("EglSurfaceHeight", h);
+
+ glViewport(0, 0, w, h);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ }
+
+ virtual void TearDown() {
+ // Display the result
+ if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) {
+ eglSwapBuffers(mEglDisplay, mEglSurface);
+ sleep(mDisplaySecs);
+ }
+
+ if (mComposerClient != NULL) {
+ mComposerClient->dispose();
+ }
+ if (mEglContext != EGL_NO_CONTEXT) {
+ eglDestroyContext(mEglDisplay, mEglContext);
+ }
+ if (mEglSurface != EGL_NO_SURFACE) {
+ eglDestroySurface(mEglDisplay, mEglSurface);
+ }
+ if (mEglDisplay != EGL_NO_DISPLAY) {
+ eglTerminate(mEglDisplay);
+ }
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ }
+
+ virtual EGLint const* getConfigAttribs() {
+ ALOGV("GLTest getConfigAttribs");
+ static EGLint sDefaultConfigAttribs[] = {
+ EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 16,
+ EGL_STENCIL_SIZE, 8,
+ EGL_NONE };
+
+ return sDefaultConfigAttribs;
+ }
+
+ virtual EGLint const* getContextAttribs() {
+ static EGLint sDefaultContextAttribs[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE };
+
+ return sDefaultContextAttribs;
+ }
+
+ virtual EGLint getSurfaceWidth() {
+ return 512;
+ }
+
+ virtual EGLint getSurfaceHeight() {
+ return 512;
+ }
+
+ void loadShader(GLenum shaderType, const char* pSource, GLuint* outShader) {
+ GLuint shader = glCreateShader(shaderType);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ if (shader) {
+ glShaderSource(shader, 1, &pSource, NULL);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ glCompileShader(shader);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ GLint compiled = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ if (!compiled) {
+ GLint infoLen = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ if (infoLen) {
+ char* buf = (char*) malloc(infoLen);
+ if (buf) {
+ glGetShaderInfoLog(shader, infoLen, NULL, buf);
+ printf("Shader compile log:\n%s\n", buf);
+ free(buf);
+ FAIL();
+ }
+ } else {
+ char* buf = (char*) malloc(0x1000);
+ if (buf) {
+ glGetShaderInfoLog(shader, 0x1000, NULL, buf);
+ printf("Shader compile log:\n%s\n", buf);
+ free(buf);
+ FAIL();
+ }
+ }
+ glDeleteShader(shader);
+ shader = 0;
+ }
+ }
+ ASSERT_TRUE(shader != 0);
+ *outShader = shader;
+ }
+
+ void createProgram(const char* pVertexSource, const char* pFragmentSource,
+ GLuint* outPgm) {
+ GLuint vertexShader, fragmentShader;
+ {
+ SCOPED_TRACE("compiling vertex shader");
+ loadShader(GL_VERTEX_SHADER, pVertexSource, &vertexShader);
+ if (HasFatalFailure()) {
+ return;
+ }
+ }
+ {
+ SCOPED_TRACE("compiling fragment shader");
+ loadShader(GL_FRAGMENT_SHADER, pFragmentSource, &fragmentShader);
+ if (HasFatalFailure()) {
+ return;
+ }
+ }
+
+ GLuint program = glCreateProgram();
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ if (program) {
+ glAttachShader(program, vertexShader);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ glAttachShader(program, fragmentShader);
+ ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+ glLinkProgram(program);
+ GLint linkStatus = GL_FALSE;
+ glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+ if (linkStatus != GL_TRUE) {
+ GLint bufLength = 0;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
+ if (bufLength) {
+ char* buf = (char*) malloc(bufLength);
+ if (buf) {
+ glGetProgramInfoLog(program, bufLength, NULL, buf);
+ printf("Program link log:\n%s\n", buf);
+ free(buf);
+ FAIL();
+ }
+ }
+ glDeleteProgram(program);
+ program = 0;
+ }
+ }
+ glDeleteShader(vertexShader);
+ glDeleteShader(fragmentShader);
+ ASSERT_TRUE(program != 0);
+ *outPgm = program;
+ }
+
+ static int abs(int value) {
+ return value > 0 ? value : -value;
+ }
+
+ ::testing::AssertionResult checkPixel(int x, int y, int r,
+ int g, int b, int a, int tolerance=2) {
+ GLubyte pixel[4];
+ String8 msg;
+ glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+ GLenum err = glGetError();
+ if (err != GL_NO_ERROR) {
+ msg += String8::format("error reading pixel: %#x", err);
+ while ((err = glGetError()) != GL_NO_ERROR) {
+ msg += String8::format(", %#x", err);
+ }
+ fprintf(stderr, "pixel check failure: %s\n", msg.string());
+ return ::testing::AssertionFailure(
+ ::testing::Message(msg.string()));
+ }
+ if (r >= 0 && abs(r - int(pixel[0])) > tolerance) {
+ msg += String8::format("r(%d isn't %d)", pixel[0], r);
+ }
+ if (g >= 0 && abs(g - int(pixel[1])) > tolerance) {
+ if (!msg.isEmpty()) {
+ msg += " ";
+ }
+ msg += String8::format("g(%d isn't %d)", pixel[1], g);
+ }
+ if (b >= 0 && abs(b - int(pixel[2])) > tolerance) {
+ if (!msg.isEmpty()) {
+ msg += " ";
+ }
+ msg += String8::format("b(%d isn't %d)", pixel[2], b);
+ }
+ if (a >= 0 && abs(a - int(pixel[3])) > tolerance) {
+ if (!msg.isEmpty()) {
+ msg += " ";
+ }
+ msg += String8::format("a(%d isn't %d)", pixel[3], a);
+ }
+ if (!msg.isEmpty()) {
+ fprintf(stderr, "pixel check failure: %s\n", msg.string());
+ return ::testing::AssertionFailure(
+ ::testing::Message(msg.string()));
+ } else {
+ return ::testing::AssertionSuccess();
+ }
+ }
+
+ int mDisplaySecs;
+ sp<SurfaceComposerClient> mComposerClient;
+ sp<SurfaceControl> mSurfaceControl;
+
+ EGLDisplay mEglDisplay;
+ EGLSurface mEglSurface;
+ EGLContext mEglContext;
+ EGLConfig mGlConfig;
+};
+
+///////////////////////////////////////////////////////////////////////
+// Class for the NON-GL tests
+///////////////////////////////////////////////////////////////////////
+class SurfaceMediaSourceTest : public ::testing::Test {
+public:
+
+ SurfaceMediaSourceTest( ): mYuvTexWidth(176), mYuvTexHeight(144) { }
+ void oneBufferPass(int width, int height );
+ void oneBufferPassNoFill(int width, int height );
+ static void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) ;
+ static void fillYV12BufferRect(uint8_t* buf, int w, int h,
+ int stride, const android_native_rect_t& rect) ;
+protected:
+
+ virtual void SetUp() {
+ android::ProcessState::self()->startThreadPool();
+ mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight);
+ mSMS->setSynchronousMode(true);
+ // Manual cast is required to avoid constructor ambiguity
+ mSTC = new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >( mSMS));
+ mANW = mSTC;
+ }
+
+ virtual void TearDown() {
+ mSMS.clear();
+ mSTC.clear();
+ mANW.clear();
+ }
+
+ const int mYuvTexWidth;
+ const int mYuvTexHeight;
+
+ sp<SurfaceMediaSource> mSMS;
+ sp<SurfaceTextureClient> mSTC;
+ sp<ANativeWindow> mANW;
+};
+
+///////////////////////////////////////////////////////////////////////
+// Class for the GL tests
+///////////////////////////////////////////////////////////////////////
+class SurfaceMediaSourceGLTest : public GLTest {
+public:
+
+ SurfaceMediaSourceGLTest( ): mYuvTexWidth(176), mYuvTexHeight(144) { }
+ virtual EGLint const* getConfigAttribs();
+ void oneBufferPassGL(int num = 0);
+ static sp<MediaRecorder> setUpMediaRecorder(int fileDescriptor, int videoSource,
+ int outputFormat, int videoEncoder, int width, int height, int fps);
+protected:
+
+ virtual void SetUp() {
+ ALOGV("SMS-GLTest::SetUp()");
+ android::ProcessState::self()->startThreadPool();
+ mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight);
+ mSTC = new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >( mSMS));
+ mANW = mSTC;
+
+ // Doing the setup related to the GL Side
+ GLTest::SetUp();
+ }
+
+ virtual void TearDown() {
+ mSMS.clear();
+ mSTC.clear();
+ mANW.clear();
+ GLTest::TearDown();
+ }
+
+ void setUpEGLSurfaceFromMediaRecorder(sp<MediaRecorder>& mr);
+
+ const int mYuvTexWidth;
+ const int mYuvTexHeight;
+
+ sp<SurfaceMediaSource> mSMS;
+ sp<SurfaceTextureClient> mSTC;
+ sp<ANativeWindow> mANW;
+};
+
+/////////////////////////////////////////////////////////////////////
+// Methods in SurfaceMediaSourceGLTest
+/////////////////////////////////////////////////////////////////////
+EGLint const* SurfaceMediaSourceGLTest::getConfigAttribs() {
+ ALOGV("SurfaceMediaSourceGLTest getConfigAttribs");
+ static EGLint sDefaultConfigAttribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_RECORDABLE_ANDROID, EGL_TRUE,
+ EGL_NONE };
+
+ return sDefaultConfigAttribs;
+}
+
+// One pass of dequeuing and queuing a GLBuffer
+void SurfaceMediaSourceGLTest::oneBufferPassGL(int num) {
+ int d = num % 50;
+ float f = 0.2f; // 0.1f * d;
+
+ glClearColor(0, 0.3, 0, 0.6);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(4 + d, 4 + d, 4, 4);
+ glClearColor(1.0 - f, f, f, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glScissor(24 + d, 48 + d, 4, 4);
+ glClearColor(f, 1.0 - f, f, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glScissor(37 + d, 17 + d, 4, 4);
+ glClearColor(f, f, 1.0 - f, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // The following call dequeues and queues the buffer
+ eglSwapBuffers(mEglDisplay, mEglSurface);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ glDisable(GL_SCISSOR_TEST);
+}
+
+// Set up the MediaRecorder which runs in the same process as mediaserver
+sp<MediaRecorder> SurfaceMediaSourceGLTest::setUpMediaRecorder(int fd, int videoSource,
+ int outputFormat, int videoEncoder, int width, int height, int fps) {
+ sp<MediaRecorder> mr = new MediaRecorder();
+ mr->setVideoSource(videoSource);
+ mr->setOutputFormat(outputFormat);
+ mr->setVideoEncoder(videoEncoder);
+ mr->setOutputFile(fd, 0, 0);
+ mr->setVideoSize(width, height);
+ mr->setVideoFrameRate(fps);
+ mr->prepare();
+ ALOGV("Starting MediaRecorder...");
+ CHECK_EQ((status_t)OK, mr->start());
+ return mr;
+}
+
+// query the mediarecorder for a surfacemeidasource and create an egl surface with that
+void SurfaceMediaSourceGLTest::setUpEGLSurfaceFromMediaRecorder(sp<MediaRecorder>& mr) {
+ sp<ISurfaceTexture> iST = mr->querySurfaceMediaSourceFromMediaServer();
+ mSTC = new SurfaceTextureClient(iST);
+ mANW = mSTC;
+
+ mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
+ mANW.get(), NULL);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, mEglSurface) ;
+
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+ mEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Methods in SurfaceMediaSourceTest
+/////////////////////////////////////////////////////////////////////
+
+// One pass of dequeuing and queuing the buffer. Fill it in with
+// cpu YV12 buffer
+void SurfaceMediaSourceTest::oneBufferPass(int width, int height ) {
+ ANativeWindowBuffer* anb;
+ ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+ ASSERT_TRUE(anb != NULL);
+
+ sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
+
+ // Fill the buffer with the a checkerboard pattern
+ uint8_t* img = NULL;
+ buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+ SurfaceMediaSourceTest::fillYV12Buffer(img, width, height, buf->getStride());
+ buf->unlock();
+
+ ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+}
+
+// Dequeuing and queuing the buffer without really filling it in.
+void SurfaceMediaSourceTest::oneBufferPassNoFill(int width, int height ) {
+ ANativeWindowBuffer* anb;
+ ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+ ASSERT_TRUE(anb != NULL);
+
+ sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+ // ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
+ // We do not fill the buffer in. Just queue it back.
+ ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+}
+
+// Fill a YV12 buffer with a multi-colored checkerboard pattern
+void SurfaceMediaSourceTest::fillYV12Buffer(uint8_t* buf, int w, int h, int stride) {
+ const int blockWidth = w > 16 ? w / 16 : 1;
+ const int blockHeight = h > 16 ? h / 16 : 1;
+ const int yuvTexOffsetY = 0;
+ int yuvTexStrideY = stride;
+ int yuvTexOffsetV = yuvTexStrideY * h;
+ int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
+ int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
+ int yuvTexStrideU = yuvTexStrideV;
+ for (int x = 0; x < w; x++) {
+ for (int y = 0; y < h; y++) {
+ int parityX = (x / blockWidth) & 1;
+ int parityY = (y / blockHeight) & 1;
+ unsigned char intensity = (parityX ^ parityY) ? 63 : 191;
+ buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity;
+ if (x < w / 2 && y < h / 2) {
+ buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity;
+ if (x * 2 < w / 2 && y * 2 < h / 2) {
+ buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] =
+ buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] =
+ buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] =
+ buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] =
+ intensity;
+ }
+ }
+ }
+ }
+}
+
+// Fill a YV12 buffer with red outside a given rectangle and green inside it.
+void SurfaceMediaSourceTest::fillYV12BufferRect(uint8_t* buf, int w,
+ int h, int stride, const android_native_rect_t& rect) {
+ const int yuvTexOffsetY = 0;
+ int yuvTexStrideY = stride;
+ int yuvTexOffsetV = yuvTexStrideY * h;
+ int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
+ int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
+ int yuvTexStrideU = yuvTexStrideV;
+ for (int x = 0; x < w; x++) {
+ for (int y = 0; y < h; y++) {
+ bool inside = rect.left <= x && x < rect.right &&
+ rect.top <= y && y < rect.bottom;
+ buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64;
+ if (x < w / 2 && y < h / 2) {
+ bool inside = rect.left <= 2*x && 2*x < rect.right &&
+ rect.top <= 2*y && 2*y < rect.bottom;
+ buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16;
+ buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] =
+ inside ? 16 : 255;
+ }
+ }
+ }
+} ///////// End of class SurfaceMediaSourceTest
+
+///////////////////////////////////////////////////////////////////
+// Class to imitate the recording /////////////////////////////
+// ////////////////////////////////////////////////////////////////
+struct SimpleDummyRecorder {
+ sp<MediaSource> mSource;
+
+ SimpleDummyRecorder
+ (const sp<MediaSource> &source): mSource(source) {}
+
+ status_t start() { return mSource->start();}
+ status_t stop() { return mSource->stop();}
+
+ // fakes reading from a media source
+ status_t readFromSource() {
+ MediaBuffer *buffer;
+ status_t err = mSource->read(&buffer);
+ if (err != OK) {
+ return err;
+ }
+ buffer->release();
+ buffer = NULL;
+ return OK;
+ }
+};
+///////////////////////////////////////////////////////////////////
+// TESTS
+// SurfaceMediaSourceTest class contains tests that fill the buffers
+// using the cpu calls
+// SurfaceMediaSourceGLTest class contains tests that fill the buffers
+// using the GL calls.
+// TODO: None of the tests actually verify the encoded images.. so at this point,
+// these are mostly functionality tests + visual inspection
+//////////////////////////////////////////////////////////////////////
+
+// Just pass one buffer from the native_window to the SurfaceMediaSource
+// Dummy Encoder
+static int testId = 1;
+TEST_F(SurfaceMediaSourceTest, DISABLED_DummyEncodingFromCpuFilledYV12BufferNpotOneBufferPass) {
+ ALOGV("Test # %d", testId++);
+ ALOGV("Testing OneBufferPass ******************************");
+
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
+ oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+}
+
+// Pass the buffer with the wrong height and weight and should not be accepted
+// Dummy Encoder
+TEST_F(SurfaceMediaSourceTest, DISABLED_DummyEncodingFromCpuFilledYV12BufferNpotWrongSizeBufferPass) {
+ ALOGV("Test # %d", testId++);
+ ALOGV("Testing Wrong size BufferPass ******************************");
+
+ // setting the client side buffer size different than the server size
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
+ 10, 10));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
+
+ ANativeWindowBuffer* anb;
+
+ // Note: make sure we get an ERROR back when dequeuing!
+ ASSERT_NE(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+}
+
+// pass multiple buffers from the native_window the SurfaceMediaSource
+// Dummy Encoder
+TEST_F(SurfaceMediaSourceTest, DISABLED_DummyEncodingFromCpuFilledYV12BufferNpotMultiBufferPass) {
+ ALOGV("Test # %d", testId++);
+ ALOGV("Testing MultiBufferPass, Dummy Recorder *********************");
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
+
+ SimpleDummyRecorder writer(mSMS);
+ writer.start();
+
+ int32_t nFramesCount = 0;
+ while (nFramesCount < 300) {
+ oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+
+ ASSERT_EQ(NO_ERROR, writer.readFromSource());
+
+ nFramesCount++;
+ }
+ writer.stop();
+}
+
+// Delayed pass of multiple buffers from the native_window the SurfaceMediaSource
+// Dummy Encoder
+TEST_F(SurfaceMediaSourceTest, DISABLED_DummyLagEncodingFromCpuFilledYV12BufferNpotMultiBufferPass) {
+ ALOGV("Test # %d", testId++);
+ ALOGV("Testing MultiBufferPass, Dummy Recorder Lagging **************");
+
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
+
+ SimpleDummyRecorder writer(mSMS);
+ writer.start();
+
+ int32_t nFramesCount = 1;
+ const int FRAMES_LAG = mSMS->getBufferCount() - 1;
+ while (nFramesCount <= 300) {
+ oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+ // Forcing the writer to lag behind a few frames
+ if (nFramesCount > FRAMES_LAG) {
+ ASSERT_EQ(NO_ERROR, writer.readFromSource());
+ }
+ nFramesCount++;
+ }
+ writer.stop();
+}
+
+// pass multiple buffers from the native_window the SurfaceMediaSource
+// A dummy writer (MULTITHREADED) is used to simulate actual MPEG4Writer
+TEST_F(SurfaceMediaSourceTest, DISABLED_DummyThreadedEncodingFromCpuFilledYV12BufferNpotMultiBufferPass) {
+ ALOGV("Test # %d", testId++);
+ ALOGV("Testing MultiBufferPass, Dummy Recorder Multi-Threaded **********");
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
+
+ DummyRecorder writer(mSMS);
+ writer.start();
+
+ int32_t nFramesCount = 0;
+ while (nFramesCount <= 300) {
+ oneBufferPass(mYuvTexWidth, mYuvTexHeight);
+
+ nFramesCount++;
+ }
+ writer.stop();
+}
+
+// Test to examine actual encoding using mediarecorder
+// We use the mediaserver to create a mediarecorder and send
+// it back to us. So SurfaceMediaSource lives in the same process
+// as the mediaserver.
+// Very close to the actual camera, except that the
+// buffers are filled and queueud by the CPU instead of GL.
+TEST_F(SurfaceMediaSourceTest, DISABLED_EncodingFromCpuYV12BufferNpotWriteMediaServer) {
+ ALOGV("Test # %d", testId++);
+ ALOGV("************** Testing the whole pipeline with actual MediaRecorder ***********");
+ ALOGV("************** SurfaceMediaSource is same process as mediaserver ***********");
+
+ const char *fileName = "/sdcard/outputSurfEncMSource.mp4";
+ int fd = open(fileName, O_RDWR | O_CREAT, 0744);
+ if (fd < 0) {
+ ALOGE("ERROR: Could not open the the file %s, fd = %d !!", fileName, fd);
+ }
+ CHECK(fd >= 0);
+
+ sp<MediaRecorder> mr = SurfaceMediaSourceGLTest::setUpMediaRecorder(fd,
+ VIDEO_SOURCE_GRALLOC_BUFFER,
+ OUTPUT_FORMAT_MPEG_4, VIDEO_ENCODER_H264, mYuvTexWidth,
+ mYuvTexHeight, 30);
+ // get the reference to the surfacemediasource living in
+ // mediaserver that is created by stagefrightrecorder
+ sp<ISurfaceTexture> iST = mr->querySurfaceMediaSourceFromMediaServer();
+ mSTC = new SurfaceTextureClient(iST);
+ mANW = mSTC;
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
+ ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
+ HAL_PIXEL_FORMAT_YV12));
+
+ int32_t nFramesCount = 0;
+ while (nFramesCount <= 300) {
+ oneBufferPassNoFill(mYuvTexWidth, mYuvTexHeight);
+ nFramesCount++;
+ ALOGV("framesCount = %d", nFramesCount);
+ }
+
+ ASSERT_EQ(NO_ERROR, native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU));
+ ALOGV("Stopping MediaRecorder...");
+ CHECK_EQ((status_t)OK, mr->stop());
+ mr.clear();
+ close(fd);
+}
+
+//////////////////////////////////////////////////////////////////////
+// GL tests
+/////////////////////////////////////////////////////////////////////
+
+// Test to examine whether we can choose the Recordable Android GLConfig
+// DummyRecorder used- no real encoding here
+TEST_F(SurfaceMediaSourceGLTest, ChooseAndroidRecordableEGLConfigDummyWriter) {
+ ALOGV("Test # %d", testId++);
+ ALOGV("Verify creating a surface w/ right config + dummy writer*********");
+
+ mSMS = new SurfaceMediaSource(mYuvTexWidth, mYuvTexHeight);
+ mSTC = new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >( mSMS));
+ mANW = mSTC;
+
+ DummyRecorder writer(mSMS);
+ writer.start();
+
+ mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
+ mANW.get(), NULL);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, mEglSurface) ;
+
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+ mEglContext));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ int32_t nFramesCount = 0;
+ while (nFramesCount <= 300) {
+ oneBufferPassGL();
+ nFramesCount++;
+ ALOGV("framesCount = %d", nFramesCount);
+ }
+
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ eglDestroySurface(mEglDisplay, mEglSurface);
+ mEglSurface = EGL_NO_SURFACE;
+
+ writer.stop();
+}
+// Test to examine whether we can render GL buffers in to the surface
+// created with the native window handle
+TEST_F(SurfaceMediaSourceGLTest, RenderingToRecordableEGLSurfaceWorks) {
+ ALOGV("Test # %d", testId++);
+ ALOGV("RenderingToRecordableEGLSurfaceWorks *********************");
+ // Do the producer side of things
+ glClearColor(0.6, 0.6, 0.6, 0.6);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(4, 4, 4, 4);
+ glClearColor(1.0, 0.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glScissor(24, 48, 4, 4);
+ glClearColor(0.0, 1.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glScissor(37, 17, 4, 4);
+ glClearColor(0.0, 0.0, 1.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(63, 0, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
+
+ EXPECT_TRUE(checkPixel( 4, 7, 255, 0, 0, 255));
+ EXPECT_TRUE(checkPixel(25, 51, 0, 255, 0, 255));
+ EXPECT_TRUE(checkPixel(40, 19, 0, 0, 255, 255));
+ EXPECT_TRUE(checkPixel(29, 51, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 5, 32, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(13, 8, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(46, 3, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(30, 33, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 6, 52, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(55, 33, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(16, 29, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 1, 30, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(41, 37, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(46, 29, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel(15, 25, 153, 153, 153, 153));
+ EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
+}
+
+// Test to examine the actual encoding with GL buffers
+// Actual encoder, Actual GL Buffers Filled SurfaceMediaSource
+// The same pattern is rendered every frame
+TEST_F(SurfaceMediaSourceGLTest, EncodingFromGLRgbaSameImageEachBufNpotWrite) {
+ ALOGV("Test # %d", testId++);
+ ALOGV("************** Testing the whole pipeline with actual Recorder ***********");
+ ALOGV("************** GL Filling the buffers ***********");
+ // Note: No need to set the colorformat for the buffers. The colorformat is
+ // in the GRAlloc buffers itself.
+
+ const char *fileName = "/sdcard/outputSurfEncMSourceGL.mp4";
+ int fd = open(fileName, O_RDWR | O_CREAT, 0744);
+ if (fd < 0) {
+ ALOGE("ERROR: Could not open the the file %s, fd = %d !!", fileName, fd);
+ }
+ CHECK(fd >= 0);
+
+ sp<MediaRecorder> mr = setUpMediaRecorder(fd, VIDEO_SOURCE_GRALLOC_BUFFER,
+ OUTPUT_FORMAT_MPEG_4, VIDEO_ENCODER_H264, mYuvTexWidth, mYuvTexHeight, 30);
+
+ // get the reference to the surfacemediasource living in
+ // mediaserver that is created by stagefrightrecorder
+ setUpEGLSurfaceFromMediaRecorder(mr);
+
+ int32_t nFramesCount = 0;
+ while (nFramesCount <= 300) {
+ oneBufferPassGL();
+ nFramesCount++;
+ ALOGV("framesCount = %d", nFramesCount);
+ }
+
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ eglDestroySurface(mEglDisplay, mEglSurface);
+ mEglSurface = EGL_NO_SURFACE;
+
+ ALOGV("Stopping MediaRecorder...");
+ CHECK_EQ((status_t)OK, mr->stop());
+ mr.clear();
+ close(fd);
+}
+
+// Test to examine the actual encoding from the GL Buffers
+// Actual encoder, Actual GL Buffers Filled SurfaceMediaSource
+// A different pattern is rendered every frame
+TEST_F(SurfaceMediaSourceGLTest, EncodingFromGLRgbaDiffImageEachBufNpotWrite) {
+ ALOGV("Test # %d", testId++);
+ ALOGV("************** Testing the whole pipeline with actual Recorder ***********");
+ ALOGV("************** Diff GL Filling the buffers ***********");
+ // Note: No need to set the colorformat for the buffers. The colorformat is
+ // in the GRAlloc buffers itself.
+
+ const char *fileName = "/sdcard/outputSurfEncMSourceGLDiff.mp4";
+ int fd = open(fileName, O_RDWR | O_CREAT, 0744);
+ if (fd < 0) {
+ ALOGE("ERROR: Could not open the the file %s, fd = %d !!", fileName, fd);
+ }
+ CHECK(fd >= 0);
+
+ sp<MediaRecorder> mr = setUpMediaRecorder(fd, VIDEO_SOURCE_GRALLOC_BUFFER,
+ OUTPUT_FORMAT_MPEG_4, VIDEO_ENCODER_H264, mYuvTexWidth, mYuvTexHeight, 30);
+
+ // get the reference to the surfacemediasource living in
+ // mediaserver that is created by stagefrightrecorder
+ setUpEGLSurfaceFromMediaRecorder(mr);
+
+ int32_t nFramesCount = 0;
+ while (nFramesCount <= 300) {
+ oneBufferPassGL(nFramesCount);
+ nFramesCount++;
+ ALOGV("framesCount = %d", nFramesCount);
+ }
+
+ EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT));
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ eglDestroySurface(mEglDisplay, mEglSurface);
+ mEglSurface = EGL_NO_SURFACE;
+
+ ALOGV("Stopping MediaRecorder...");
+ CHECK_EQ((status_t)OK, mr->stop());
+ mr.clear();
+ close(fd);
+}
+} // namespace android
diff --git a/media/libstagefright/timedtext/Android.mk b/media/libstagefright/timedtext/Android.mk
new file mode 100644
index 0000000..58ef9e3
--- /dev/null
+++ b/media/libstagefright/timedtext/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ TextDescriptions.cpp \
+ TimedTextDriver.cpp \
+ TimedText3GPPSource.cpp \
+ TimedTextSource.cpp \
+ TimedTextSRTSource.cpp \
+ TimedTextPlayer.cpp
+
+LOCAL_CFLAGS += -Wno-multichar
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/base/include/media/stagefright/timedtext \
+ $(TOP)/frameworks/base/media/libstagefright
+
+LOCAL_MODULE:= libstagefright_timedtext
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/timedtext/TextDescriptions.cpp b/media/libstagefright/timedtext/TextDescriptions.cpp
new file mode 100644
index 0000000..f9c1fe0
--- /dev/null
+++ b/media/libstagefright/timedtext/TextDescriptions.cpp
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "TextDescriptions.h"
+#include <media/stagefright/Utils.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+TextDescriptions::TextDescriptions() {
+}
+
+status_t TextDescriptions::getParcelOfDescriptions(
+ const uint8_t *data, ssize_t size,
+ uint32_t flags, int timeMs, Parcel *parcel) {
+ parcel->freeData();
+
+ if (flags & IN_BAND_TEXT_3GPP) {
+ if (flags & GLOBAL_DESCRIPTIONS) {
+ return extract3GPPGlobalDescriptions(data, size, parcel, 0);
+ } else if (flags & LOCAL_DESCRIPTIONS) {
+ return extract3GPPLocalDescriptions(data, size, timeMs, parcel, 0);
+ }
+ } else if (flags & OUT_OF_BAND_TEXT_SRT) {
+ if (flags & LOCAL_DESCRIPTIONS) {
+ return extractSRTLocalDescriptions(data, size, timeMs, parcel);
+ }
+ }
+
+ return ERROR_UNSUPPORTED;
+}
+
+// Parse the SRT text sample, and store the timing and text sample in a Parcel.
+// The Parcel will be sent to MediaPlayer.java through event, and will be
+// parsed in TimedText.java.
+status_t TextDescriptions::extractSRTLocalDescriptions(
+ const uint8_t *data, ssize_t size, int timeMs, Parcel *parcel) {
+ parcel->writeInt32(KEY_LOCAL_SETTING);
+ parcel->writeInt32(KEY_START_TIME);
+ parcel->writeInt32(timeMs);
+
+ parcel->writeInt32(KEY_STRUCT_TEXT);
+ // write the size of the text sample
+ parcel->writeInt32(size);
+ // write the text sample as a byte array
+ parcel->writeInt32(size);
+ parcel->write(data, size);
+
+ return OK;
+}
+
+// Extract the local 3GPP display descriptions. 3GPP local descriptions
+// are appended to the text sample if any. The descriptions could include
+// information such as text styles, highlights, karaoke and so on. They
+// are contained in different boxes, such as 'styl' box contains text
+// styles, and 'krok' box contains karaoke timing and positions.
+status_t TextDescriptions::extract3GPPLocalDescriptions(
+ const uint8_t *data, ssize_t size,
+ int timeMs, Parcel *parcel, int depth) {
+ if (depth == 0) {
+ parcel->writeInt32(KEY_LOCAL_SETTING);
+
+ // write start time to display this text sample
+ parcel->writeInt32(KEY_START_TIME);
+ parcel->writeInt32(timeMs);
+
+ ssize_t textLen = (*data) << 8 | (*(data + 1));
+
+ // write text sample length and text sample itself
+ parcel->writeInt32(KEY_STRUCT_TEXT);
+ parcel->writeInt32(textLen);
+ parcel->writeInt32(textLen);
+ parcel->write(data + 2, textLen);
+
+ if (size > textLen) {
+ data += (textLen + 2);
+ size -= (textLen + 2);
+ } else {
+ return OK;
+ }
+ }
+
+ const uint8_t *tmpData = data;
+ ssize_t chunkSize = U32_AT(tmpData);
+ uint32_t chunkType = U32_AT(tmpData + 4);
+
+ if (chunkSize <= 0) {
+ return OK;
+ }
+
+ tmpData += 8;
+
+ switch(chunkType) {
+ // 'styl' box specifies the style of the text.
+ case FOURCC('s', 't', 'y', 'l'):
+ {
+ uint16_t count = U16_AT(tmpData);
+
+ tmpData += 2;
+
+ for (int i = 0; i < count; i++) {
+ parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
+ parcel->writeInt32(KEY_START_CHAR);
+ parcel->writeInt32(U16_AT(tmpData));
+
+ parcel->writeInt32(KEY_END_CHAR);
+ parcel->writeInt32(U16_AT(tmpData + 2));
+
+ parcel->writeInt32(KEY_FONT_ID);
+ parcel->writeInt32(U16_AT(tmpData + 4));
+
+ parcel->writeInt32(KEY_STYLE_FLAGS);
+ parcel->writeInt32(*(tmpData + 6));
+
+ parcel->writeInt32(KEY_FONT_SIZE);
+ parcel->writeInt32(*(tmpData + 7));
+
+ parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
+ uint32_t rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
+ | *(tmpData + 10) << 8 | *(tmpData + 11);
+ parcel->writeInt32(rgba);
+
+ tmpData += 12;
+ }
+
+ break;
+ }
+ // 'krok' box. The number of highlight events is specified, and each
+ // event is specified by a starting and ending char offset and an end
+ // time for the event.
+ case FOURCC('k', 'r', 'o', 'k'):
+ {
+
+ parcel->writeInt32(KEY_STRUCT_KARAOKE_LIST);
+
+ int startTime = U32_AT(tmpData);
+ uint16_t count = U16_AT(tmpData + 4);
+ parcel->writeInt32(count);
+
+ tmpData += 6;
+ int lastEndTime = 0;
+
+ for (int i = 0; i < count; i++) {
+ parcel->writeInt32(startTime + lastEndTime);
+
+ lastEndTime = U32_AT(tmpData);
+ parcel->writeInt32(lastEndTime);
+
+ parcel->writeInt32(U16_AT(tmpData + 4));
+ parcel->writeInt32(U16_AT(tmpData + 6));
+
+ tmpData += 8;
+ }
+
+ break;
+ }
+ // 'hlit' box specifies highlighted text
+ case FOURCC('h', 'l', 'i', 't'):
+ {
+ parcel->writeInt32(KEY_STRUCT_HIGHLIGHT_LIST);
+
+ // the start char offset to highlight
+ parcel->writeInt32(U16_AT(tmpData));
+ // the last char offset to highlight
+ parcel->writeInt32(U16_AT(tmpData + 2));
+
+ break;
+ }
+ // 'hclr' box specifies the RGBA color: 8 bits each of
+ // red, green, blue, and an alpha(transparency) value
+ case FOURCC('h', 'c', 'l', 'r'):
+ {
+ parcel->writeInt32(KEY_HIGHLIGHT_COLOR_RGBA);
+
+ uint32_t rgba = *(tmpData) << 24 | *(tmpData + 1) << 16
+ | *(tmpData + 2) << 8 | *(tmpData + 3);
+ parcel->writeInt32(rgba);
+
+ break;
+ }
+ // 'dlay' box specifies a delay after a scroll in and/or
+ // before scroll out.
+ case FOURCC('d', 'l', 'a', 'y'):
+ {
+ parcel->writeInt32(KEY_SCROLL_DELAY);
+
+ uint32_t delay = *(tmpData) << 24 | *(tmpData + 1) << 16
+ | *(tmpData + 2) << 8 | *(tmpData + 3);
+ parcel->writeInt32(delay);
+
+ break;
+ }
+ // 'href' box for hyper text link
+ case FOURCC('h', 'r', 'e', 'f'):
+ {
+ parcel->writeInt32(KEY_STRUCT_HYPER_TEXT_LIST);
+
+ // the start offset of the text to be linked
+ parcel->writeInt32(U16_AT(tmpData));
+ // the end offset of the text
+ parcel->writeInt32(U16_AT(tmpData + 2));
+
+ // the number of bytes in the following URL
+ int len = *(tmpData + 4);
+ parcel->writeInt32(len);
+
+ // the linked-to URL
+ parcel->writeInt32(len);
+ parcel->write(tmpData + 5, len);
+
+ tmpData += (5 + len);
+
+ // the number of bytes in the following "alt" string
+ len = *tmpData;
+ parcel->writeInt32(len);
+
+ // an "alt" string for user display
+ parcel->writeInt32(len);
+ parcel->write(tmpData + 1, len);
+
+ break;
+ }
+ // 'tbox' box to indicate the position of the text with values
+ // of top, left, bottom and right
+ case FOURCC('t', 'b', 'o', 'x'):
+ {
+ parcel->writeInt32(KEY_STRUCT_TEXT_POS);
+ parcel->writeInt32(U16_AT(tmpData));
+ parcel->writeInt32(U16_AT(tmpData + 2));
+ parcel->writeInt32(U16_AT(tmpData + 4));
+ parcel->writeInt32(U16_AT(tmpData + 6));
+
+ break;
+ }
+ // 'blnk' to specify the char range to be blinked
+ case FOURCC('b', 'l', 'n', 'k'):
+ {
+ parcel->writeInt32(KEY_STRUCT_BLINKING_TEXT_LIST);
+
+ // start char offset
+ parcel->writeInt32(U16_AT(tmpData));
+ // end char offset
+ parcel->writeInt32(U16_AT(tmpData + 2));
+
+ break;
+ }
+ // 'twrp' box specifies text wrap behavior. If the value if 0x00,
+ // then no wrap. If it's 0x01, then automatic 'soft' wrap is enabled.
+ // 0x02-0xff are reserved.
+ case FOURCC('t', 'w', 'r', 'p'):
+ {
+ parcel->writeInt32(KEY_WRAP_TEXT);
+ parcel->writeInt32(*tmpData);
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ if (size > chunkSize) {
+ data += chunkSize;
+ size -= chunkSize;
+ // continue to parse next box
+ return extract3GPPLocalDescriptions(data, size, 0, parcel, 1);
+ }
+
+ return OK;
+}
+
+// To extract box 'tx3g' defined in 3GPP TS 26.245, and store it in a Parcel
+status_t TextDescriptions::extract3GPPGlobalDescriptions(
+ const uint8_t *data, ssize_t size, Parcel *parcel, int depth) {
+
+ ssize_t chunkSize = U32_AT(data);
+ uint32_t chunkType = U32_AT(data + 4);
+ const uint8_t *tmpData = data;
+ tmpData += 8;
+
+ if (size < chunkSize) {
+ return OK;
+ }
+
+ if (depth == 0) {
+ parcel->writeInt32(KEY_GLOBAL_SETTING);
+ }
+ switch(chunkType) {
+ case FOURCC('t', 'x', '3', 'g'):
+ {
+ tmpData += 8; // skip the first 8 bytes
+ parcel->writeInt32(KEY_DISPLAY_FLAGS);
+ parcel->writeInt32(U32_AT(tmpData));
+
+ parcel->writeInt32(KEY_STRUCT_JUSTIFICATION);
+ parcel->writeInt32(tmpData[4]);
+ parcel->writeInt32(tmpData[5]);
+
+ parcel->writeInt32(KEY_BACKGROUND_COLOR_RGBA);
+ uint32_t rgba = *(tmpData + 6) << 24 | *(tmpData + 7) << 16
+ | *(tmpData + 8) << 8 | *(tmpData + 9);
+ parcel->writeInt32(rgba);
+
+ tmpData += 10;
+ parcel->writeInt32(KEY_STRUCT_TEXT_POS);
+ parcel->writeInt32(U16_AT(tmpData));
+ parcel->writeInt32(U16_AT(tmpData + 2));
+ parcel->writeInt32(U16_AT(tmpData + 4));
+ parcel->writeInt32(U16_AT(tmpData + 6));
+
+ tmpData += 8;
+ parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
+ parcel->writeInt32(KEY_START_CHAR);
+ parcel->writeInt32(U16_AT(tmpData));
+
+ parcel->writeInt32(KEY_END_CHAR);
+ parcel->writeInt32(U16_AT(tmpData + 2));
+
+ parcel->writeInt32(KEY_FONT_ID);
+ parcel->writeInt32(U16_AT(tmpData + 4));
+
+ parcel->writeInt32(KEY_STYLE_FLAGS);
+ parcel->writeInt32(*(tmpData + 6));
+
+ parcel->writeInt32(KEY_FONT_SIZE);
+ parcel->writeInt32(*(tmpData + 7));
+
+ parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
+ rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
+ | *(tmpData + 10) << 8 | *(tmpData + 11);
+ parcel->writeInt32(rgba);
+
+ tmpData += 12;
+ parcel->writeInt32(KEY_STRUCT_FONT_LIST);
+ uint16_t count = U16_AT(tmpData);
+ parcel->writeInt32(count);
+
+ tmpData += 2;
+ for (int i = 0; i < count; i++) {
+ // font ID
+ parcel->writeInt32(U16_AT(tmpData));
+
+ // font name length
+ parcel->writeInt32(*(tmpData + 2));
+
+ int len = *(tmpData + 2);
+
+ parcel->write(tmpData + 3, len);
+ tmpData += 3 + len;
+ }
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ data += chunkSize;
+ size -= chunkSize;
+
+ if (size > 0) {
+ // continue to extract next 'tx3g'
+ return extract3GPPGlobalDescriptions(data, size, parcel, 1);
+ }
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/timedtext/TextDescriptions.h b/media/libstagefright/timedtext/TextDescriptions.h
new file mode 100644
index 0000000..0144917
--- /dev/null
+++ b/media/libstagefright/timedtext/TextDescriptions.h
@@ -0,0 +1,84 @@
+ /*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 TEXT_DESCRIPTIONS_H_
+
+#define TEXT_DESCRIPTIONS_H_
+
+#include <binder/Parcel.h>
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+
+class TextDescriptions {
+public:
+ enum {
+ IN_BAND_TEXT_3GPP = 0x01,
+ OUT_OF_BAND_TEXT_SRT = 0x02,
+
+ GLOBAL_DESCRIPTIONS = 0x100,
+ LOCAL_DESCRIPTIONS = 0x200,
+ };
+
+ static status_t getParcelOfDescriptions(
+ const uint8_t *data, ssize_t size,
+ uint32_t flags, int timeMs, Parcel *parcel);
+private:
+ TextDescriptions();
+
+ enum {
+ // These keys must be in sync with the keys in TimedText.java
+ KEY_DISPLAY_FLAGS = 1, // int
+ KEY_STYLE_FLAGS = 2, // int
+ KEY_BACKGROUND_COLOR_RGBA = 3, // int
+ KEY_HIGHLIGHT_COLOR_RGBA = 4, // int
+ KEY_SCROLL_DELAY = 5, // int
+ KEY_WRAP_TEXT = 6, // int
+ KEY_START_TIME = 7, // int
+ KEY_STRUCT_BLINKING_TEXT_LIST = 8, // List<CharPos>
+ KEY_STRUCT_FONT_LIST = 9, // List<Font>
+ KEY_STRUCT_HIGHLIGHT_LIST = 10, // List<CharPos>
+ KEY_STRUCT_HYPER_TEXT_LIST = 11, // List<HyperText>
+ KEY_STRUCT_KARAOKE_LIST = 12, // List<Karaoke>
+ KEY_STRUCT_STYLE_LIST = 13, // List<Style>
+ KEY_STRUCT_TEXT_POS = 14, // TextPos
+ KEY_STRUCT_JUSTIFICATION = 15, // Justification
+ KEY_STRUCT_TEXT = 16, // Text
+
+ KEY_GLOBAL_SETTING = 101,
+ KEY_LOCAL_SETTING = 102,
+ KEY_START_CHAR = 103,
+ KEY_END_CHAR = 104,
+ KEY_FONT_ID = 105,
+ KEY_FONT_SIZE = 106,
+ KEY_TEXT_COLOR_RGBA = 107,
+ };
+
+ static status_t extractSRTLocalDescriptions(
+ const uint8_t *data, ssize_t size,
+ int timeMs, Parcel *parcel);
+ static status_t extract3GPPGlobalDescriptions(
+ const uint8_t *data, ssize_t size,
+ Parcel *parcel, int depth);
+ static status_t extract3GPPLocalDescriptions(
+ const uint8_t *data, ssize_t size,
+ int timeMs, Parcel *parcel, int depth);
+
+ DISALLOW_EVIL_CONSTRUCTORS(TextDescriptions);
+};
+
+} // namespace android
+#endif // TEXT_DESCRIPTIONS_H_
diff --git a/media/libstagefright/timedtext/TimedText3GPPSource.cpp b/media/libstagefright/timedtext/TimedText3GPPSource.cpp
new file mode 100644
index 0000000..4854121
--- /dev/null
+++ b/media/libstagefright/timedtext/TimedText3GPPSource.cpp
@@ -0,0 +1,119 @@
+ /*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "TimedText3GPPSource"
+#include <utils/Log.h>
+
+#include <binder/Parcel.h>
+#include <media/stagefright/foundation/ADebug.h> // CHECK_XX macro
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h> // for MEDIA_MIMETYPE_xxx
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+#include "TimedText3GPPSource.h"
+#include "TextDescriptions.h"
+
+namespace android {
+
+TimedText3GPPSource::TimedText3GPPSource(const sp<MediaSource>& mediaSource)
+ : mSource(mediaSource) {
+}
+
+TimedText3GPPSource::~TimedText3GPPSource() {
+}
+
+status_t TimedText3GPPSource::read(
+ int64_t *startTimeUs, int64_t *endTimeUs, Parcel *parcel,
+ const MediaSource::ReadOptions *options) {
+ MediaBuffer *textBuffer = NULL;
+ status_t err = mSource->read(&textBuffer, options);
+ if (err != OK) {
+ return err;
+ }
+ CHECK(textBuffer != NULL);
+ textBuffer->meta_data()->findInt64(kKeyTime, startTimeUs);
+ CHECK_GE(*startTimeUs, 0);
+ extractAndAppendLocalDescriptions(*startTimeUs, textBuffer, parcel);
+ textBuffer->release();
+ // endTimeUs is a dummy parameter for 3gpp timed text format.
+ // Set a negative value to it to mark it is unavailable.
+ *endTimeUs = -1;
+ return OK;
+}
+
+// Each text sample consists of a string of text, optionally with sample
+// modifier description. The modifier description could specify a new
+// text style for the string of text. These descriptions are present only
+// if they are needed. This method is used to extract the modifier
+// description and append it at the end of the text.
+status_t TimedText3GPPSource::extractAndAppendLocalDescriptions(
+ int64_t timeUs, const MediaBuffer *textBuffer, Parcel *parcel) {
+ const void *data;
+ size_t size = 0;
+ int32_t flag = TextDescriptions::LOCAL_DESCRIPTIONS;
+
+ const char *mime;
+ CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
+ CHECK(strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0);
+
+ data = textBuffer->data();
+ size = textBuffer->size();
+
+ if (size > 0) {
+ parcel->freeData();
+ flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
+ return TextDescriptions::getParcelOfDescriptions(
+ (const uint8_t *)data, size, flag, timeUs / 1000, parcel);
+ }
+ return OK;
+}
+
+// To extract and send the global text descriptions for all the text samples
+// in the text track or text file.
+// TODO: send error message to application via notifyListener()...?
+status_t TimedText3GPPSource::extractGlobalDescriptions(Parcel *parcel) {
+ const void *data;
+ size_t size = 0;
+ int32_t flag = TextDescriptions::GLOBAL_DESCRIPTIONS;
+
+ const char *mime;
+ CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
+ CHECK(strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0);
+
+ uint32_t type;
+ // get the 'tx3g' box content. This box contains the text descriptions
+ // used to render the text track
+ if (!mSource->getFormat()->findData(
+ kKeyTextFormatData, &type, &data, &size)) {
+ return ERROR_MALFORMED;
+ }
+
+ if (size > 0) {
+ flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
+ return TextDescriptions::getParcelOfDescriptions(
+ (const uint8_t *)data, size, flag, 0, parcel);
+ }
+ return OK;
+}
+
+sp<MetaData> TimedText3GPPSource::getFormat() {
+ return mSource->getFormat();
+}
+
+} // namespace android
diff --git a/media/libstagefright/timedtext/TimedText3GPPSource.h b/media/libstagefright/timedtext/TimedText3GPPSource.h
new file mode 100644
index 0000000..4170940
--- /dev/null
+++ b/media/libstagefright/timedtext/TimedText3GPPSource.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 TIMED_TEXT_3GPP_SOURCE_H_
+#define TIMED_TEXT_3GPP_SOURCE_H_
+
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+
+#include "TimedTextSource.h"
+
+namespace android {
+
+class MediaBuffer;
+class Parcel;
+
+class TimedText3GPPSource : public TimedTextSource {
+public:
+ TimedText3GPPSource(const sp<MediaSource>& mediaSource);
+ virtual status_t start() { return mSource->start(); }
+ virtual status_t stop() { return mSource->stop(); }
+ virtual status_t read(
+ int64_t *startTimeUs,
+ int64_t *endTimeUs,
+ Parcel *parcel,
+ const MediaSource::ReadOptions *options = NULL);
+ virtual status_t extractGlobalDescriptions(Parcel *parcel);
+ virtual sp<MetaData> getFormat();
+
+protected:
+ virtual ~TimedText3GPPSource();
+
+private:
+ sp<MediaSource> mSource;
+
+ status_t extractAndAppendLocalDescriptions(
+ int64_t timeUs, const MediaBuffer *textBuffer, Parcel *parcel);
+
+ DISALLOW_EVIL_CONSTRUCTORS(TimedText3GPPSource);
+};
+
+} // namespace android
+
+#endif // TIMED_TEXT_3GPP_SOURCE_H_
diff --git a/media/libstagefright/timedtext/TimedTextDriver.cpp b/media/libstagefright/timedtext/TimedTextDriver.cpp
new file mode 100644
index 0000000..8ee15f8
--- /dev/null
+++ b/media/libstagefright/timedtext/TimedTextDriver.cpp
@@ -0,0 +1,222 @@
+ /*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "TimedTextDriver"
+#include <utils/Log.h>
+
+#include <binder/IPCThreadState.h>
+
+#include <media/mediaplayer.h>
+#include <media/MediaPlayerInterface.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 <media/stagefright/Utils.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/timedtext/TimedTextDriver.h>
+
+#include "TextDescriptions.h"
+#include "TimedTextPlayer.h"
+#include "TimedTextSource.h"
+
+namespace android {
+
+TimedTextDriver::TimedTextDriver(
+ const wp<MediaPlayerBase> &listener)
+ : mLooper(new ALooper),
+ mListener(listener),
+ mState(UNINITIALIZED) {
+ mLooper->setName("TimedTextDriver");
+ mLooper->start();
+ mPlayer = new TimedTextPlayer(listener);
+ mLooper->registerHandler(mPlayer);
+}
+
+TimedTextDriver::~TimedTextDriver() {
+ mTextSourceVector.clear();
+ mLooper->stop();
+}
+
+status_t TimedTextDriver::selectTrack_l(int32_t index) {
+ if (index >= (int)(mTextSourceVector.size())) {
+ return BAD_VALUE;
+ }
+
+ sp<TimedTextSource> source;
+ source = mTextSourceVector.itemAt(index);
+ mPlayer->setDataSource(source);
+ if (mState == UNINITIALIZED) {
+ mState = PAUSED;
+ }
+ mCurrentTrackIndex = index;
+ return OK;
+}
+
+status_t TimedTextDriver::start() {
+ Mutex::Autolock autoLock(mLock);
+ switch (mState) {
+ case UNINITIALIZED:
+ return INVALID_OPERATION;
+ case PLAYING:
+ return OK;
+ case PAUSED:
+ mPlayer->start();
+ break;
+ default:
+ TRESPASS();
+ }
+ mState = PLAYING;
+ return OK;
+}
+
+// TODO: Test if pause() works properly.
+// Scenario 1: start - pause - resume
+// Scenario 2: start - seek
+// Scenario 3: start - pause - seek - resume
+status_t TimedTextDriver::pause() {
+ Mutex::Autolock autoLock(mLock);
+ switch (mState) {
+ case UNINITIALIZED:
+ return INVALID_OPERATION;
+ case PLAYING:
+ mPlayer->pause();
+ break;
+ case PAUSED:
+ return OK;
+ default:
+ TRESPASS();
+ }
+ mState = PAUSED;
+ return OK;
+}
+
+status_t TimedTextDriver::selectTrack(int32_t index) {
+ status_t ret = OK;
+ Mutex::Autolock autoLock(mLock);
+ switch (mState) {
+ case UNINITIALIZED:
+ case PAUSED:
+ ret = selectTrack_l(index);
+ break;
+ case PLAYING:
+ mPlayer->pause();
+ ret = selectTrack_l(index);
+ if (ret != OK) {
+ break;
+ }
+ mPlayer->start();
+ break;
+ defaut:
+ TRESPASS();
+ }
+ return ret;
+}
+
+status_t TimedTextDriver::unselectTrack(int32_t index) {
+ if (mCurrentTrackIndex != index) {
+ return INVALID_OPERATION;
+ }
+ status_t err = pause();
+ if (err != OK) {
+ return err;
+ }
+ Mutex::Autolock autoLock(mLock);
+ mState = UNINITIALIZED;
+ return OK;
+}
+
+status_t TimedTextDriver::seekToAsync(int64_t timeUs) {
+ mPlayer->seekToAsync(timeUs);
+ return OK;
+}
+
+status_t TimedTextDriver::addInBandTextSource(
+ const sp<MediaSource>& mediaSource) {
+ sp<TimedTextSource> source =
+ TimedTextSource::CreateTimedTextSource(mediaSource);
+ if (source == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+ Mutex::Autolock autoLock(mLock);
+ mTextSourceVector.add(source);
+ return OK;
+}
+
+status_t TimedTextDriver::addOutOfBandTextSource(
+ const char *uri, const char *mimeType) {
+ // TODO: Define "TimedTextSource::CreateFromURI(uri)"
+ // and move below lines there..?
+
+ // To support local subtitle file only for now
+ if (strncasecmp("file://", uri, 7)) {
+ return ERROR_UNSUPPORTED;
+ }
+ sp<DataSource> dataSource =
+ DataSource::CreateFromURI(uri);
+ if (dataSource == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ sp<TimedTextSource> source;
+ if (strcasecmp(mimeType, MEDIA_MIMETYPE_TEXT_SUBRIP) == 0) {
+ source = TimedTextSource::CreateTimedTextSource(
+ dataSource, TimedTextSource::OUT_OF_BAND_FILE_SRT);
+ }
+
+ if (source == NULL) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ Mutex::Autolock autoLock(mLock);
+ mTextSourceVector.add(source);
+ return OK;
+}
+
+status_t TimedTextDriver::addOutOfBandTextSource(
+ int fd, off64_t offset, size_t length, const char *mimeType) {
+ // Not supported yet. This requires DataSource::sniff to detect various text
+ // formats such as srt/smi/ttml.
+ return ERROR_UNSUPPORTED;
+}
+
+void TimedTextDriver::getTrackInfo(Parcel *parcel) {
+ Mutex::Autolock autoLock(mLock);
+ Vector<sp<TimedTextSource> >::const_iterator iter;
+ parcel->writeInt32(mTextSourceVector.size());
+ for (iter = mTextSourceVector.begin();
+ iter != mTextSourceVector.end(); ++iter) {
+ sp<MetaData> meta = (*iter)->getFormat();
+ if (meta != NULL) {
+ // There are two fields.
+ parcel->writeInt32(2);
+
+ // track type.
+ parcel->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT);
+
+ const char *lang = "und";
+ meta->findCString(kKeyMediaLanguage, &lang);
+ parcel->writeString16(String16(lang));
+ } else {
+ parcel->writeInt32(0);
+ }
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/timedtext/TimedTextPlayer.cpp b/media/libstagefright/timedtext/TimedTextPlayer.cpp
new file mode 100644
index 0000000..917c62a
--- /dev/null
+++ b/media/libstagefright/timedtext/TimedTextPlayer.cpp
@@ -0,0 +1,212 @@
+ /*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "TimedTextPlayer"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/timedtext/TimedTextDriver.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/MediaPlayerInterface.h>
+
+#include "TimedTextPlayer.h"
+
+#include "TimedTextSource.h"
+
+namespace android {
+
+static const int64_t kAdjustmentProcessingTimeUs = 100000ll;
+static const int64_t kWaitTimeUsToRetryRead = 100000ll;
+
+TimedTextPlayer::TimedTextPlayer(const wp<MediaPlayerBase> &listener)
+ : mListener(listener),
+ mSource(NULL),
+ mSendSubtitleGeneration(0) {
+}
+
+TimedTextPlayer::~TimedTextPlayer() {
+ if (mSource != NULL) {
+ mSource->stop();
+ mSource.clear();
+ mSource = NULL;
+ }
+}
+
+void TimedTextPlayer::start() {
+ sp<AMessage> msg = new AMessage(kWhatSeek, id());
+ msg->setInt64("seekTimeUs", -1);
+ msg->post();
+}
+
+void TimedTextPlayer::pause() {
+ (new AMessage(kWhatPause, id()))->post();
+}
+
+void TimedTextPlayer::seekToAsync(int64_t timeUs) {
+ sp<AMessage> msg = new AMessage(kWhatSeek, id());
+ msg->setInt64("seekTimeUs", timeUs);
+ msg->post();
+}
+
+void TimedTextPlayer::setDataSource(sp<TimedTextSource> source) {
+ sp<AMessage> msg = new AMessage(kWhatSetSource, id());
+ msg->setObject("source", source);
+ msg->post();
+}
+
+void TimedTextPlayer::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatPause: {
+ mSendSubtitleGeneration++;
+ break;
+ }
+ case kWhatSeek: {
+ int64_t seekTimeUs = 0;
+ msg->findInt64("seekTimeUs", &seekTimeUs);
+ if (seekTimeUs < 0) {
+ sp<MediaPlayerBase> listener = mListener.promote();
+ if (listener != NULL) {
+ int32_t positionMs = 0;
+ listener->getCurrentPosition(&positionMs);
+ seekTimeUs = positionMs * 1000ll;
+ }
+ }
+ doSeekAndRead(seekTimeUs);
+ break;
+ }
+ case kWhatSendSubtitle: {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+ if (generation != mSendSubtitleGeneration) {
+ // Drop obsolete msg.
+ break;
+ }
+ sp<RefBase> obj;
+ msg->findObject("subtitle", &obj);
+ if (obj != NULL) {
+ sp<ParcelEvent> parcelEvent;
+ parcelEvent = static_cast<ParcelEvent*>(obj.get());
+ notifyListener(&(parcelEvent->parcel));
+ } else {
+ notifyListener();
+ }
+ doRead();
+ break;
+ }
+ case kWhatSetSource: {
+ sp<RefBase> obj;
+ msg->findObject("source", &obj);
+ if (obj == NULL) break;
+ if (mSource != NULL) {
+ mSource->stop();
+ }
+ mSource = static_cast<TimedTextSource*>(obj.get());
+ status_t err = mSource->start();
+ if (err != OK) {
+ notifyError(err);
+ break;
+ }
+ Parcel parcel;
+ err = mSource->extractGlobalDescriptions(&parcel);
+ if (err != OK) {
+ notifyError(err);
+ break;
+ }
+ notifyListener(&parcel);
+ break;
+ }
+ }
+}
+
+void TimedTextPlayer::doSeekAndRead(int64_t seekTimeUs) {
+ MediaSource::ReadOptions options;
+ options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
+ doRead(&options);
+}
+
+void TimedTextPlayer::doRead(MediaSource::ReadOptions* options) {
+ int64_t startTimeUs = 0;
+ int64_t endTimeUs = 0;
+ sp<ParcelEvent> parcelEvent = new ParcelEvent();
+ status_t err = mSource->read(&startTimeUs, &endTimeUs,
+ &(parcelEvent->parcel), options);
+ if (err == WOULD_BLOCK) {
+ postTextEventDelayUs(NULL, kWaitTimeUsToRetryRead);
+ return;
+ } else if (err != OK) {
+ notifyError(err);
+ return;
+ }
+
+ postTextEvent(parcelEvent, startTimeUs);
+ if (endTimeUs > 0) {
+ CHECK_GE(endTimeUs, startTimeUs);
+ // send an empty timed text to clear the subtitle when it reaches to the
+ // end time.
+ postTextEvent(NULL, endTimeUs);
+ }
+}
+
+void TimedTextPlayer::postTextEvent(const sp<ParcelEvent>& parcel, int64_t timeUs) {
+ sp<MediaPlayerBase> listener = mListener.promote();
+ if (listener != NULL) {
+ int64_t positionUs, delayUs;
+ int32_t positionMs = 0;
+ listener->getCurrentPosition(&positionMs);
+ positionUs = positionMs * 1000ll;
+
+ if (timeUs <= positionUs + kAdjustmentProcessingTimeUs) {
+ delayUs = 0;
+ } else {
+ delayUs = timeUs - positionUs - kAdjustmentProcessingTimeUs;
+ }
+ postTextEventDelayUs(parcel, delayUs);
+ }
+}
+
+void TimedTextPlayer::postTextEventDelayUs(const sp<ParcelEvent>& parcel, int64_t delayUs) {
+ sp<MediaPlayerBase> listener = mListener.promote();
+ if (listener != NULL) {
+ sp<AMessage> msg = new AMessage(kWhatSendSubtitle, id());
+ msg->setInt32("generation", mSendSubtitleGeneration);
+ if (parcel != NULL) {
+ msg->setObject("subtitle", parcel);
+ }
+ msg->post(delayUs);
+ }
+}
+
+void TimedTextPlayer::notifyError(int error) {
+ sp<MediaPlayerBase> listener = mListener.promote();
+ if (listener != NULL) {
+ listener->sendEvent(MEDIA_INFO, MEDIA_INFO_TIMED_TEXT_ERROR, error);
+ }
+}
+
+void TimedTextPlayer::notifyListener(const Parcel *parcel) {
+ sp<MediaPlayerBase> listener = mListener.promote();
+ if (listener != NULL) {
+ if (parcel != NULL && (parcel->dataSize() > 0)) {
+ listener->sendEvent(MEDIA_TIMED_TEXT, 0, 0, parcel);
+ } else { // send an empty timed text to clear the screen
+ listener->sendEvent(MEDIA_TIMED_TEXT);
+ }
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/timedtext/TimedTextPlayer.h b/media/libstagefright/timedtext/TimedTextPlayer.h
new file mode 100644
index 0000000..47aff03
--- /dev/null
+++ b/media/libstagefright/timedtext/TimedTextPlayer.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 TIMEDTEXT_PLAYER_H_
+#define TIMEDTEXT_PLAYER_H_
+
+#include <binder/Parcel.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/RefBase.h>
+
+#include "TimedTextSource.h"
+
+namespace android {
+
+class AMessage;
+class MediaPlayerBase;
+class TimedTextDriver;
+class TimedTextSource;
+
+class TimedTextPlayer : public AHandler {
+public:
+ TimedTextPlayer(const wp<MediaPlayerBase> &listener);
+
+ virtual ~TimedTextPlayer();
+
+ void start();
+ void pause();
+ void seekToAsync(int64_t timeUs);
+ void setDataSource(sp<TimedTextSource> source);
+
+protected:
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+ enum {
+ kWhatPause = 'paus',
+ kWhatSeek = 'seek',
+ kWhatSendSubtitle = 'send',
+ kWhatSetSource = 'ssrc',
+ };
+
+ // To add Parcel into an AMessage as an object, it should be 'RefBase'.
+ struct ParcelEvent : public RefBase {
+ Parcel parcel;
+ };
+
+ wp<MediaPlayerBase> mListener;
+ sp<TimedTextSource> mSource;
+ int32_t mSendSubtitleGeneration;
+
+ void doSeekAndRead(int64_t seekTimeUs);
+ void doRead(MediaSource::ReadOptions* options = NULL);
+ void onTextEvent();
+ void postTextEvent(const sp<ParcelEvent>& parcel = NULL, int64_t timeUs = -1);
+ void postTextEventDelayUs(const sp<ParcelEvent>& parcel = NULL, int64_t delayUs = -1);
+ void notifyError(int error = 0);
+ void notifyListener(const Parcel *parcel = NULL);
+
+ DISALLOW_EVIL_CONSTRUCTORS(TimedTextPlayer);
+};
+
+} // namespace android
+
+#endif // TIMEDTEXT_PLAYER_H_
diff --git a/media/libstagefright/timedtext/TimedTextSRTSource.cpp b/media/libstagefright/timedtext/TimedTextSRTSource.cpp
new file mode 100644
index 0000000..7b1f7f6
--- /dev/null
+++ b/media/libstagefright/timedtext/TimedTextSRTSource.cpp
@@ -0,0 +1,286 @@
+ /*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "TimedTextSRTSource"
+#include <utils/Log.h>
+
+#include <binder/Parcel.h>
+#include <media/stagefright/foundation/ADebug.h> // for CHECK_xx
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaDefs.h> // for MEDIA_MIMETYPE_xxx
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+#include "TimedTextSRTSource.h"
+#include "TextDescriptions.h"
+
+namespace android {
+
+TimedTextSRTSource::TimedTextSRTSource(const sp<DataSource>& dataSource)
+ : mSource(dataSource),
+ mMetaData(new MetaData),
+ mIndex(0) {
+}
+
+TimedTextSRTSource::~TimedTextSRTSource() {
+}
+
+status_t TimedTextSRTSource::start() {
+ status_t err = scanFile();
+ if (err != OK) {
+ reset();
+ }
+ // TODO: Need to detect the language, because SRT doesn't give language
+ // information explicitly.
+ mMetaData->setCString(kKeyMediaLanguage, "");
+ return err;
+}
+
+void TimedTextSRTSource::reset() {
+ mMetaData->clear();
+ mTextVector.clear();
+ mIndex = 0;
+}
+
+status_t TimedTextSRTSource::stop() {
+ reset();
+ return OK;
+}
+
+status_t TimedTextSRTSource::read(
+ int64_t *startTimeUs,
+ int64_t *endTimeUs,
+ Parcel *parcel,
+ const MediaSource::ReadOptions *options) {
+ AString text;
+ status_t err = getText(options, &text, startTimeUs, endTimeUs);
+ if (err != OK) {
+ return err;
+ }
+
+ CHECK_GE(*startTimeUs, 0);
+ extractAndAppendLocalDescriptions(*startTimeUs, text, parcel);
+ return OK;
+}
+
+status_t TimedTextSRTSource::scanFile() {
+ off64_t offset = 0;
+ int64_t startTimeUs;
+ bool endOfFile = false;
+
+ while (!endOfFile) {
+ TextInfo info;
+ status_t err = getNextSubtitleInfo(&offset, &startTimeUs, &info);
+ switch (err) {
+ case OK:
+ mTextVector.add(startTimeUs, info);
+ break;
+ case ERROR_END_OF_STREAM:
+ endOfFile = true;
+ break;
+ default:
+ return err;
+ }
+ }
+ if (mTextVector.isEmpty()) {
+ return ERROR_MALFORMED;
+ }
+ return OK;
+}
+
+/* SRT format:
+ * Subtitle number
+ * Start time --> End time
+ * Text of subtitle (one or more lines)
+ * Blank lines
+ *
+ * .srt file example:
+ * 1
+ * 00:00:20,000 --> 00:00:24,400
+ * Altocumulus clouds occr between six thousand
+ *
+ * 2
+ * 00:00:24,600 --> 00:00:27,800
+ * and twenty thousand feet above ground level.
+ */
+status_t TimedTextSRTSource::getNextSubtitleInfo(
+ off64_t *offset, int64_t *startTimeUs, TextInfo *info) {
+ AString data;
+ status_t err;
+
+ // To skip blank lines.
+ do {
+ if ((err = readNextLine(offset, &data)) != OK) {
+ return err;
+ }
+ data.trim();
+ } while (data.empty());
+
+ // Just ignore the first non-blank line which is subtitle sequence number.
+ if ((err = readNextLine(offset, &data)) != OK) {
+ return err;
+ }
+ int hour1, hour2, min1, min2, sec1, sec2, msec1, msec2;
+ // the start time format is: hours:minutes:seconds,milliseconds
+ // 00:00:24,600 --> 00:00:27,800
+ if (sscanf(data.c_str(), "%02d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d",
+ &hour1, &min1, &sec1, &msec1, &hour2, &min2, &sec2, &msec2) != 8) {
+ return ERROR_MALFORMED;
+ }
+
+ *startTimeUs = ((hour1 * 3600 + min1 * 60 + sec1) * 1000 + msec1) * 1000ll;
+ info->endTimeUs = ((hour2 * 3600 + min2 * 60 + sec2) * 1000 + msec2) * 1000ll;
+ if (info->endTimeUs <= *startTimeUs) {
+ return ERROR_MALFORMED;
+ }
+
+ info->offset = *offset;
+ bool needMoreData = true;
+ while (needMoreData) {
+ if ((err = readNextLine(offset, &data)) != OK) {
+ if (err == ERROR_END_OF_STREAM) {
+ needMoreData = false;
+ } else {
+ return err;
+ }
+ }
+
+ if (needMoreData) {
+ data.trim();
+ if (data.empty()) {
+ // it's an empty line used to separate two subtitles
+ needMoreData = false;
+ }
+ }
+ }
+ info->textLen = *offset - info->offset;
+ return OK;
+}
+
+status_t TimedTextSRTSource::readNextLine(off64_t *offset, AString *data) {
+ data->clear();
+ while (true) {
+ ssize_t readSize;
+ char character;
+ if ((readSize = mSource->readAt(*offset, &character, 1)) < 1) {
+ if (readSize == 0) {
+ return ERROR_END_OF_STREAM;
+ }
+ return ERROR_IO;
+ }
+
+ (*offset)++;
+
+ // a line could end with CR, LF or CR + LF
+ if (character == 10) {
+ break;
+ } else if (character == 13) {
+ if ((readSize = mSource->readAt(*offset, &character, 1)) < 1) {
+ if (readSize == 0) { // end of the stream
+ return OK;
+ }
+ return ERROR_IO;
+ }
+
+ (*offset)++;
+ if (character != 10) {
+ (*offset)--;
+ }
+ break;
+ }
+ data->append(character);
+ }
+ return OK;
+}
+
+status_t TimedTextSRTSource::getText(
+ const MediaSource::ReadOptions *options,
+ AString *text, int64_t *startTimeUs, int64_t *endTimeUs) {
+ text->clear();
+ int64_t seekTimeUs;
+ MediaSource::ReadOptions::SeekMode mode;
+ if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
+ int64_t lastEndTimeUs =
+ mTextVector.valueAt(mTextVector.size() - 1).endTimeUs;
+ int64_t firstStartTimeUs = mTextVector.keyAt(0);
+ if (seekTimeUs < 0 || seekTimeUs > lastEndTimeUs) {
+ return ERROR_OUT_OF_RANGE;
+ } else if (seekTimeUs < firstStartTimeUs) {
+ mIndex = 0;
+ } else {
+ // binary search
+ ssize_t low = 0;
+ ssize_t high = mTextVector.size() - 1;
+ ssize_t mid = 0;
+ int64_t currTimeUs;
+
+ while (low <= high) {
+ mid = low + (high - low)/2;
+ currTimeUs = mTextVector.keyAt(mid);
+ const int diff = currTimeUs - seekTimeUs;
+
+ if (diff == 0) {
+ break;
+ } else if (diff < 0) {
+ low = mid + 1;
+ } else {
+ if ((high == mid + 1)
+ && (seekTimeUs < mTextVector.keyAt(high))) {
+ break;
+ }
+ high = mid - 1;
+ }
+ }
+ mIndex = mid;
+ }
+ }
+ const TextInfo &info = mTextVector.valueAt(mIndex);
+ *startTimeUs = mTextVector.keyAt(mIndex);
+ *endTimeUs = info.endTimeUs;
+ mIndex++;
+
+ char *str = new char[info.textLen];
+ if (mSource->readAt(info.offset, str, info.textLen) < info.textLen) {
+ delete[] str;
+ return ERROR_IO;
+ }
+ text->append(str, info.textLen);
+ delete[] str;
+ return OK;
+}
+
+status_t TimedTextSRTSource::extractAndAppendLocalDescriptions(
+ int64_t timeUs, const AString &text, Parcel *parcel) {
+ const void *data = text.c_str();
+ size_t size = text.size();
+ int32_t flag = TextDescriptions::LOCAL_DESCRIPTIONS |
+ TextDescriptions::OUT_OF_BAND_TEXT_SRT;
+
+ if (size > 0) {
+ return TextDescriptions::getParcelOfDescriptions(
+ (const uint8_t *)data, size, flag, timeUs / 1000, parcel);
+ }
+ return OK;
+}
+
+sp<MetaData> TimedTextSRTSource::getFormat() {
+ return mMetaData;
+}
+
+} // namespace android
diff --git a/media/libstagefright/timedtext/TimedTextSRTSource.h b/media/libstagefright/timedtext/TimedTextSRTSource.h
new file mode 100644
index 0000000..e1371b8
--- /dev/null
+++ b/media/libstagefright/timedtext/TimedTextSRTSource.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 TIMED_TEXT_SRT_SOURCE_H_
+#define TIMED_TEXT_SRT_SOURCE_H_
+
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/Compat.h> // off64_t
+
+#include "TimedTextSource.h"
+
+namespace android {
+
+class AString;
+class DataSource;
+class MediaBuffer;
+class Parcel;
+
+class TimedTextSRTSource : public TimedTextSource {
+public:
+ TimedTextSRTSource(const sp<DataSource>& dataSource);
+ virtual status_t start();
+ virtual status_t stop();
+ virtual status_t read(
+ int64_t *startTimeUs,
+ int64_t *endTimeUs,
+ Parcel *parcel,
+ const MediaSource::ReadOptions *options = NULL);
+ virtual sp<MetaData> getFormat();
+
+protected:
+ virtual ~TimedTextSRTSource();
+
+private:
+ sp<DataSource> mSource;
+ sp<MetaData> mMetaData;
+
+ struct TextInfo {
+ int64_t endTimeUs;
+ // The offset of the text in the original file.
+ off64_t offset;
+ int textLen;
+ };
+
+ int mIndex;
+ KeyedVector<int64_t, TextInfo> mTextVector;
+
+ void reset();
+ status_t scanFile();
+ status_t getNextSubtitleInfo(
+ off64_t *offset, int64_t *startTimeUs, TextInfo *info);
+ status_t readNextLine(off64_t *offset, AString *data);
+ status_t getText(
+ const MediaSource::ReadOptions *options,
+ AString *text, int64_t *startTimeUs, int64_t *endTimeUs);
+ status_t extractAndAppendLocalDescriptions(
+ int64_t timeUs, const AString &text, Parcel *parcel);
+
+ DISALLOW_EVIL_CONSTRUCTORS(TimedTextSRTSource);
+};
+
+} // namespace android
+
+#endif // TIMED_TEXT_SRT_SOURCE_H_
diff --git a/media/libstagefright/timedtext/TimedTextSource.cpp b/media/libstagefright/timedtext/TimedTextSource.cpp
new file mode 100644
index 0000000..953f7b5
--- /dev/null
+++ b/media/libstagefright/timedtext/TimedTextSource.cpp
@@ -0,0 +1,66 @@
+ /*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "TimedTextSource"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h> // CHECK_XX macro
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaDefs.h> // for MEDIA_MIMETYPE_xxx
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+#include "TimedTextSource.h"
+
+#include "TimedText3GPPSource.h"
+#include "TimedTextSRTSource.h"
+
+namespace android {
+
+// static
+sp<TimedTextSource> TimedTextSource::CreateTimedTextSource(
+ const sp<MediaSource>& mediaSource) {
+ const char *mime;
+ CHECK(mediaSource->getFormat()->findCString(kKeyMIMEType, &mime));
+ if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) == 0) {
+ return new TimedText3GPPSource(mediaSource);
+ }
+ ALOGE("Unsupported mime type for subtitle. : %s", mime);
+ return NULL;
+}
+
+// static
+sp<TimedTextSource> TimedTextSource::CreateTimedTextSource(
+ const sp<DataSource>& dataSource, FileType filetype) {
+ switch(filetype) {
+ case OUT_OF_BAND_FILE_SRT:
+ return new TimedTextSRTSource(dataSource);
+ case OUT_OF_BAND_FILE_SMI:
+ // TODO: Implement for SMI.
+ ALOGE("Supporting SMI is not implemented yet");
+ break;
+ default:
+ ALOGE("Undefined subtitle format. : %d", filetype);
+ }
+ return NULL;
+}
+
+sp<MetaData> TimedTextSource::getFormat() {
+ return NULL;
+}
+
+} // namespace android
diff --git a/media/libstagefright/timedtext/TimedTextSource.h b/media/libstagefright/timedtext/TimedTextSource.h
new file mode 100644
index 0000000..756cc31
--- /dev/null
+++ b/media/libstagefright/timedtext/TimedTextSource.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 TIMED_TEXT_SOURCE_H_
+#define TIMED_TEXT_SOURCE_H_
+
+#include <media/stagefright/foundation/ABase.h> // for DISALLOW_XXX macro.
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h> // for MediaSource::ReadOptions
+#include <utils/RefBase.h>
+
+namespace android {
+
+class DataSource;
+class MetaData;
+class Parcel;
+
+class TimedTextSource : public RefBase {
+ public:
+ enum FileType {
+ OUT_OF_BAND_FILE_SRT = 1,
+ OUT_OF_BAND_FILE_SMI = 2,
+ };
+ static sp<TimedTextSource> CreateTimedTextSource(
+ const sp<MediaSource>& source);
+ static sp<TimedTextSource> CreateTimedTextSource(
+ const sp<DataSource>& source, FileType filetype);
+ TimedTextSource() {}
+ virtual status_t start() = 0;
+ virtual status_t stop() = 0;
+ // Returns subtitle parcel and its start time.
+ virtual status_t read(
+ int64_t *startTimeUs,
+ int64_t *endTimeUs,
+ Parcel *parcel,
+ const MediaSource::ReadOptions *options = NULL) = 0;
+ virtual status_t extractGlobalDescriptions(Parcel *parcel) {
+ return INVALID_OPERATION;
+ }
+ virtual sp<MetaData> getFormat();
+
+ protected:
+ virtual ~TimedTextSource() { }
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(TimedTextSource);
+};
+
+} // namespace android
+
+#endif // TIMED_TEXT_SOURCE_H_
diff --git a/media/libstagefright/yuv/Android.mk b/media/libstagefright/yuv/Android.mk
new file mode 100644
index 0000000..a4253f6
--- /dev/null
+++ b/media/libstagefright/yuv/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ YUVImage.cpp \
+ YUVCanvas.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils
+
+LOCAL_MODULE:= libstagefright_yuv
+
+
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/yuv/YUVCanvas.cpp b/media/libstagefright/yuv/YUVCanvas.cpp
new file mode 100644
index 0000000..4c9fee8
--- /dev/null
+++ b/media/libstagefright/yuv/YUVCanvas.cpp
@@ -0,0 +1,111 @@
+/*
+ * 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 "YUVCanvas"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/YUVCanvas.h>
+#include <media/stagefright/YUVImage.h>
+#include <ui/Rect.h>
+
+namespace android {
+
+YUVCanvas::YUVCanvas(YUVImage &yuvImage)
+ : mYUVImage(yuvImage) {
+}
+
+YUVCanvas::~YUVCanvas() {
+}
+
+void YUVCanvas::FillYUV(uint8_t yValue, uint8_t uValue, uint8_t vValue) {
+ for (int32_t y = 0; y < mYUVImage.height(); ++y) {
+ for (int32_t x = 0; x < mYUVImage.width(); ++x) {
+ mYUVImage.setPixelValue(x, y, yValue, uValue, vValue);
+ }
+ }
+}
+
+void YUVCanvas::FillYUVRectangle(const Rect& rect,
+ uint8_t yValue, uint8_t uValue, uint8_t vValue) {
+ for (int32_t y = rect.top; y < rect.bottom; ++y) {
+ for (int32_t x = rect.left; x < rect.right; ++x) {
+ mYUVImage.setPixelValue(x, y, yValue, uValue, vValue);
+ }
+ }
+}
+
+void YUVCanvas::CopyImageRect(
+ const Rect& srcRect,
+ int32_t destStartX, int32_t destStartY,
+ const YUVImage &srcImage) {
+
+ // Try fast copy first
+ if (YUVImage::fastCopyRectangle(
+ srcRect,
+ destStartX, destStartY,
+ srcImage, mYUVImage)) {
+ return;
+ }
+
+ int32_t srcStartX = srcRect.left;
+ int32_t srcStartY = srcRect.top;
+ for (int32_t offsetY = 0; offsetY < srcRect.height(); ++offsetY) {
+ for (int32_t offsetX = 0; offsetX < srcRect.width(); ++offsetX) {
+ int32_t srcX = srcStartX + offsetX;
+ int32_t srcY = srcStartY + offsetY;
+
+ int32_t destX = destStartX + offsetX;
+ int32_t destY = destStartY + offsetY;
+
+ uint8_t yValue;
+ uint8_t uValue;
+ uint8_t vValue;
+
+ srcImage.getPixelValue(srcX, srcY, &yValue, &uValue, &vValue);
+ mYUVImage.setPixelValue(destX, destY, yValue, uValue, vValue);
+ }
+ }
+}
+
+void YUVCanvas::downsample(
+ int32_t srcOffsetX, int32_t srcOffsetY,
+ int32_t skipX, int32_t skipY,
+ const YUVImage &srcImage) {
+ // TODO: Add a low pass filter for downsampling.
+
+ // Check that srcImage is big enough to fill mYUVImage.
+ CHECK((srcOffsetX + (mYUVImage.width() - 1) * skipX) < srcImage.width());
+ CHECK((srcOffsetY + (mYUVImage.height() - 1) * skipY) < srcImage.height());
+
+ uint8_t yValue;
+ uint8_t uValue;
+ uint8_t vValue;
+
+ int32_t srcY = srcOffsetY;
+ for (int32_t y = 0; y < mYUVImage.height(); ++y) {
+ int32_t srcX = srcOffsetX;
+ for (int32_t x = 0; x < mYUVImage.width(); ++x) {
+ srcImage.getPixelValue(srcX, srcY, &yValue, &uValue, &vValue);
+ mYUVImage.setPixelValue(x, y, yValue, uValue, vValue);
+
+ srcX += skipX;
+ }
+ srcY += skipY;
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/yuv/YUVImage.cpp b/media/libstagefright/yuv/YUVImage.cpp
new file mode 100644
index 0000000..7b9000b
--- /dev/null
+++ b/media/libstagefright/yuv/YUVImage.cpp
@@ -0,0 +1,413 @@
+/*
+ * 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 "YUVImage"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/YUVImage.h>
+#include <ui/Rect.h>
+
+namespace android {
+
+YUVImage::YUVImage(YUVFormat yuvFormat, int32_t width, int32_t height) {
+ mYUVFormat = yuvFormat;
+ mWidth = width;
+ mHeight = height;
+
+ size_t numberOfBytes = bufferSize(yuvFormat, width, height);
+ uint8_t *buffer = new uint8_t[numberOfBytes];
+ mBuffer = buffer;
+ mOwnBuffer = true;
+
+ initializeYUVPointers();
+}
+
+YUVImage::YUVImage(YUVFormat yuvFormat, int32_t width, int32_t height, uint8_t *buffer) {
+ mYUVFormat = yuvFormat;
+ mWidth = width;
+ mHeight = height;
+ mBuffer = buffer;
+ mOwnBuffer = false;
+
+ initializeYUVPointers();
+}
+
+//static
+size_t YUVImage::bufferSize(YUVFormat yuvFormat, int32_t width, int32_t height) {
+ int32_t numberOfPixels = width*height;
+ size_t numberOfBytes = 0;
+ if (yuvFormat == YUV420Planar || yuvFormat == YUV420SemiPlanar) {
+ // Y takes numberOfPixels bytes and U/V take numberOfPixels/4 bytes each.
+ numberOfBytes = (size_t)(numberOfPixels + (numberOfPixels >> 1));
+ } else {
+ ALOGE("Format not supported");
+ }
+ return numberOfBytes;
+}
+
+bool YUVImage::initializeYUVPointers() {
+ int32_t numberOfPixels = mWidth * mHeight;
+
+ if (mYUVFormat == YUV420Planar) {
+ mYdata = (uint8_t *)mBuffer;
+ mUdata = mYdata + numberOfPixels;
+ mVdata = mUdata + (numberOfPixels >> 2);
+ } else if (mYUVFormat == YUV420SemiPlanar) {
+ // U and V channels are interleaved as VUVUVU.
+ // So V data starts at the end of Y channel and
+ // U data starts right after V's start.
+ mYdata = (uint8_t *)mBuffer;
+ mVdata = mYdata + numberOfPixels;
+ mUdata = mVdata + 1;
+ } else {
+ ALOGE("Format not supported");
+ return false;
+ }
+ return true;
+}
+
+YUVImage::~YUVImage() {
+ if (mOwnBuffer) delete[] mBuffer;
+}
+
+bool YUVImage::getOffsets(int32_t x, int32_t y,
+ int32_t *yOffset, int32_t *uOffset, int32_t *vOffset) const {
+ *yOffset = y*mWidth + x;
+
+ int32_t uvOffset = (y >> 1) * (mWidth >> 1) + (x >> 1);
+ if (mYUVFormat == YUV420Planar) {
+ *uOffset = uvOffset;
+ *vOffset = uvOffset;
+ } else if (mYUVFormat == YUV420SemiPlanar) {
+ // Since U and V channels are interleaved, offsets need
+ // to be doubled.
+ *uOffset = 2*uvOffset;
+ *vOffset = 2*uvOffset;
+ } else {
+ ALOGE("Format not supported");
+ return false;
+ }
+
+ return true;
+}
+
+bool YUVImage::getOffsetIncrementsPerDataRow(
+ int32_t *yDataOffsetIncrement,
+ int32_t *uDataOffsetIncrement,
+ int32_t *vDataOffsetIncrement) const {
+ *yDataOffsetIncrement = mWidth;
+
+ int32_t uvDataOffsetIncrement = mWidth >> 1;
+
+ if (mYUVFormat == YUV420Planar) {
+ *uDataOffsetIncrement = uvDataOffsetIncrement;
+ *vDataOffsetIncrement = uvDataOffsetIncrement;
+ } else if (mYUVFormat == YUV420SemiPlanar) {
+ // Since U and V channels are interleaved, offsets need
+ // to be doubled.
+ *uDataOffsetIncrement = 2*uvDataOffsetIncrement;
+ *vDataOffsetIncrement = 2*uvDataOffsetIncrement;
+ } else {
+ ALOGE("Format not supported");
+ return false;
+ }
+
+ return true;
+}
+
+uint8_t* YUVImage::getYAddress(int32_t offset) const {
+ return mYdata + offset;
+}
+
+uint8_t* YUVImage::getUAddress(int32_t offset) const {
+ return mUdata + offset;
+}
+
+uint8_t* YUVImage::getVAddress(int32_t offset) const {
+ return mVdata + offset;
+}
+
+bool YUVImage::getYUVAddresses(int32_t x, int32_t y,
+ uint8_t **yAddr, uint8_t **uAddr, uint8_t **vAddr) const {
+ int32_t yOffset;
+ int32_t uOffset;
+ int32_t vOffset;
+ if (!getOffsets(x, y, &yOffset, &uOffset, &vOffset)) return false;
+
+ *yAddr = getYAddress(yOffset);
+ *uAddr = getUAddress(uOffset);
+ *vAddr = getVAddress(vOffset);
+
+ return true;
+}
+
+bool YUVImage::validPixel(int32_t x, int32_t y) const {
+ return (x >= 0 && x < mWidth &&
+ y >= 0 && y < mHeight);
+}
+
+bool YUVImage::getPixelValue(int32_t x, int32_t y,
+ uint8_t *yPtr, uint8_t *uPtr, uint8_t *vPtr) const {
+ CHECK(validPixel(x, y));
+
+ uint8_t *yAddr;
+ uint8_t *uAddr;
+ uint8_t *vAddr;
+ if (!getYUVAddresses(x, y, &yAddr, &uAddr, &vAddr)) return false;
+
+ *yPtr = *yAddr;
+ *uPtr = *uAddr;
+ *vPtr = *vAddr;
+
+ return true;
+}
+
+bool YUVImage::setPixelValue(int32_t x, int32_t y,
+ uint8_t yValue, uint8_t uValue, uint8_t vValue) {
+ CHECK(validPixel(x, y));
+
+ uint8_t *yAddr;
+ uint8_t *uAddr;
+ uint8_t *vAddr;
+ if (!getYUVAddresses(x, y, &yAddr, &uAddr, &vAddr)) return false;
+
+ *yAddr = yValue;
+ *uAddr = uValue;
+ *vAddr = vValue;
+
+ return true;
+}
+
+void YUVImage::fastCopyRectangle420Planar(
+ const Rect& srcRect,
+ int32_t destStartX, int32_t destStartY,
+ const YUVImage &srcImage, YUVImage &destImage) {
+ CHECK(srcImage.mYUVFormat == YUV420Planar);
+ CHECK(destImage.mYUVFormat == YUV420Planar);
+
+ int32_t srcStartX = srcRect.left;
+ int32_t srcStartY = srcRect.top;
+ int32_t width = srcRect.width();
+ int32_t height = srcRect.height();
+
+ // Get source and destination start addresses
+ uint8_t *ySrcAddrBase;
+ uint8_t *uSrcAddrBase;
+ uint8_t *vSrcAddrBase;
+ srcImage.getYUVAddresses(srcStartX, srcStartY,
+ &ySrcAddrBase, &uSrcAddrBase, &vSrcAddrBase);
+
+ uint8_t *yDestAddrBase;
+ uint8_t *uDestAddrBase;
+ uint8_t *vDestAddrBase;
+ destImage.getYUVAddresses(destStartX, destStartY,
+ &yDestAddrBase, &uDestAddrBase, &vDestAddrBase);
+
+ // Get source and destination offset increments incurred in going
+ // from one data row to next.
+ int32_t ySrcOffsetIncrement;
+ int32_t uSrcOffsetIncrement;
+ int32_t vSrcOffsetIncrement;
+ srcImage.getOffsetIncrementsPerDataRow(
+ &ySrcOffsetIncrement, &uSrcOffsetIncrement, &vSrcOffsetIncrement);
+
+ int32_t yDestOffsetIncrement;
+ int32_t uDestOffsetIncrement;
+ int32_t vDestOffsetIncrement;
+ destImage.getOffsetIncrementsPerDataRow(
+ &yDestOffsetIncrement, &uDestOffsetIncrement, &vDestOffsetIncrement);
+
+ // Copy Y
+ {
+ size_t numberOfYBytesPerRow = (size_t) width;
+ uint8_t *ySrcAddr = ySrcAddrBase;
+ uint8_t *yDestAddr = yDestAddrBase;
+ for (int32_t offsetY = 0; offsetY < height; ++offsetY) {
+ memcpy(yDestAddr, ySrcAddr, numberOfYBytesPerRow);
+
+ ySrcAddr += ySrcOffsetIncrement;
+ yDestAddr += yDestOffsetIncrement;
+ }
+ }
+
+ // Copy U
+ {
+ size_t numberOfUBytesPerRow = (size_t) (width >> 1);
+ uint8_t *uSrcAddr = uSrcAddrBase;
+ uint8_t *uDestAddr = uDestAddrBase;
+ // Every other row has an entry for U/V channel values. Hence only
+ // go half the height.
+ for (int32_t offsetY = 0; offsetY < (height >> 1); ++offsetY) {
+ memcpy(uDestAddr, uSrcAddr, numberOfUBytesPerRow);
+
+ uSrcAddr += uSrcOffsetIncrement;
+ uDestAddr += uDestOffsetIncrement;
+ }
+ }
+
+ // Copy V
+ {
+ size_t numberOfVBytesPerRow = (size_t) (width >> 1);
+ uint8_t *vSrcAddr = vSrcAddrBase;
+ uint8_t *vDestAddr = vDestAddrBase;
+ // Every other pixel row has a U/V data row. Hence only go half the height.
+ for (int32_t offsetY = 0; offsetY < (height >> 1); ++offsetY) {
+ memcpy(vDestAddr, vSrcAddr, numberOfVBytesPerRow);
+
+ vSrcAddr += vSrcOffsetIncrement;
+ vDestAddr += vDestOffsetIncrement;
+ }
+ }
+}
+
+void YUVImage::fastCopyRectangle420SemiPlanar(
+ const Rect& srcRect,
+ int32_t destStartX, int32_t destStartY,
+ const YUVImage &srcImage, YUVImage &destImage) {
+ CHECK(srcImage.mYUVFormat == YUV420SemiPlanar);
+ CHECK(destImage.mYUVFormat == YUV420SemiPlanar);
+
+ int32_t srcStartX = srcRect.left;
+ int32_t srcStartY = srcRect.top;
+ int32_t width = srcRect.width();
+ int32_t height = srcRect.height();
+
+ // Get source and destination start addresses
+ uint8_t *ySrcAddrBase;
+ uint8_t *uSrcAddrBase;
+ uint8_t *vSrcAddrBase;
+ srcImage.getYUVAddresses(srcStartX, srcStartY,
+ &ySrcAddrBase, &uSrcAddrBase, &vSrcAddrBase);
+
+ uint8_t *yDestAddrBase;
+ uint8_t *uDestAddrBase;
+ uint8_t *vDestAddrBase;
+ destImage.getYUVAddresses(destStartX, destStartY,
+ &yDestAddrBase, &uDestAddrBase, &vDestAddrBase);
+
+ // Get source and destination offset increments incurred in going
+ // from one data row to next.
+ int32_t ySrcOffsetIncrement;
+ int32_t uSrcOffsetIncrement;
+ int32_t vSrcOffsetIncrement;
+ srcImage.getOffsetIncrementsPerDataRow(
+ &ySrcOffsetIncrement, &uSrcOffsetIncrement, &vSrcOffsetIncrement);
+
+ int32_t yDestOffsetIncrement;
+ int32_t uDestOffsetIncrement;
+ int32_t vDestOffsetIncrement;
+ destImage.getOffsetIncrementsPerDataRow(
+ &yDestOffsetIncrement, &uDestOffsetIncrement, &vDestOffsetIncrement);
+
+ // Copy Y
+ {
+ size_t numberOfYBytesPerRow = (size_t) width;
+ uint8_t *ySrcAddr = ySrcAddrBase;
+ uint8_t *yDestAddr = yDestAddrBase;
+ for (int32_t offsetY = 0; offsetY < height; ++offsetY) {
+ memcpy(yDestAddr, ySrcAddr, numberOfYBytesPerRow);
+
+ ySrcAddr = ySrcAddr + ySrcOffsetIncrement;
+ yDestAddr = yDestAddr + yDestOffsetIncrement;
+ }
+ }
+
+ // Copy UV
+ {
+ // UV are interleaved. So number of UV bytes per row is 2*(width/2).
+ size_t numberOfUVBytesPerRow = (size_t) width;
+ uint8_t *vSrcAddr = vSrcAddrBase;
+ uint8_t *vDestAddr = vDestAddrBase;
+ // Every other pixel row has a U/V data row. Hence only go half the height.
+ for (int32_t offsetY = 0; offsetY < (height >> 1); ++offsetY) {
+ memcpy(vDestAddr, vSrcAddr, numberOfUVBytesPerRow);
+
+ vSrcAddr += vSrcOffsetIncrement;
+ vDestAddr += vDestOffsetIncrement;
+ }
+ }
+}
+
+// static
+bool YUVImage::fastCopyRectangle(
+ const Rect& srcRect,
+ int32_t destStartX, int32_t destStartY,
+ const YUVImage &srcImage, YUVImage &destImage) {
+ if (srcImage.mYUVFormat == destImage.mYUVFormat) {
+ if (srcImage.mYUVFormat == YUV420Planar) {
+ fastCopyRectangle420Planar(
+ srcRect,
+ destStartX, destStartY,
+ srcImage, destImage);
+ } else if (srcImage.mYUVFormat == YUV420SemiPlanar) {
+ fastCopyRectangle420SemiPlanar(
+ srcRect,
+ destStartX, destStartY,
+ srcImage, destImage);
+ }
+ return true;
+ }
+ return false;
+}
+
+uint8_t clamp(uint8_t v, uint8_t minValue, uint8_t maxValue) {
+ CHECK(maxValue >= minValue);
+
+ if (v < minValue) return minValue;
+ else if (v > maxValue) return maxValue;
+ else return v;
+}
+
+void YUVImage::yuv2rgb(uint8_t yValue, uint8_t uValue, uint8_t vValue,
+ uint8_t *r, uint8_t *g, uint8_t *b) const {
+ *r = yValue + (1.370705 * (vValue-128));
+ *g = yValue - (0.698001 * (vValue-128)) - (0.337633 * (uValue-128));
+ *b = yValue + (1.732446 * (uValue-128));
+
+ *r = clamp(*r, 0, 255);
+ *g = clamp(*g, 0, 255);
+ *b = clamp(*b, 0, 255);
+}
+
+bool YUVImage::writeToPPM(const char *filename) const {
+ FILE *fp = fopen(filename, "w");
+ if (fp == NULL) {
+ return false;
+ }
+ fprintf(fp, "P3\n");
+ fprintf(fp, "%d %d\n", mWidth, mHeight);
+ fprintf(fp, "255\n");
+ for (int32_t y = 0; y < mHeight; ++y) {
+ for (int32_t x = 0; x < mWidth; ++x) {
+ uint8_t yValue;
+ uint8_t uValue;
+ uint8_t vValue;
+ getPixelValue(x, y, &yValue, &uValue, & vValue);
+
+ uint8_t rValue;
+ uint8_t gValue;
+ uint8_t bValue;
+ yuv2rgb(yValue, uValue, vValue, &rValue, &gValue, &bValue);
+
+ fprintf(fp, "%d %d %d\n", (int32_t)rValue, (int32_t)gValue, (int32_t)bValue);
+ }
+ }
+ fclose(fp);
+ return true;
+}
+
+} // namespace android
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
new file mode 100644
index 0000000..4e9b4cf
--- /dev/null
+++ b/media/mediaserver/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ main_mediaserver.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libaudioflinger \
+ libcameraservice \
+ libmediaplayerservice \
+ libutils \
+ libbinder
+
+# FIXME The duplicate audioflinger is temporary
+LOCAL_C_INCLUDES := \
+ frameworks/native/services/audioflinger \
+ frameworks/base/services/audioflinger \
+ frameworks/base/services/camera/libcameraservice \
+ frameworks/base/media/libmediaplayerservice
+
+LOCAL_MODULE:= mediaserver
+
+include $(BUILD_EXECUTABLE)
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
new file mode 100644
index 0000000..6b1abb1
--- /dev/null
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -0,0 +1,45 @@
+/*
+**
+** 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.
+*/
+
+#define LOG_TAG "mediaserver"
+//#define LOG_NDEBUG 0
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+// from LOCAL_C_INCLUDES
+#include "AudioFlinger.h"
+#include "CameraService.h"
+#include "MediaPlayerService.h"
+#include "AudioPolicyService.h"
+
+using namespace android;
+
+int main(int argc, char** argv)
+{
+ sp<ProcessState> proc(ProcessState::self());
+ sp<IServiceManager> sm = defaultServiceManager();
+ ALOGI("ServiceManager: %p", sm.get());
+ AudioFlinger::instantiate();
+ MediaPlayerService::instantiate();
+ CameraService::instantiate();
+ AudioPolicyService::instantiate();
+ ProcessState::self()->startThreadPool();
+ IPCThreadState::self()->joinThreadPool();
+}
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk
new file mode 100644
index 0000000..fc7fc4f
--- /dev/null
+++ b/media/mtp/Android.mk
@@ -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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ MtpDataPacket.cpp \
+ MtpDebug.cpp \
+ MtpDevice.cpp \
+ MtpEventPacket.cpp \
+ MtpDeviceInfo.cpp \
+ MtpObjectInfo.cpp \
+ MtpPacket.cpp \
+ MtpProperty.cpp \
+ MtpRequestPacket.cpp \
+ MtpResponsePacket.cpp \
+ MtpServer.cpp \
+ MtpStorageInfo.cpp \
+ MtpStringBuffer.cpp \
+ MtpStorage.cpp \
+ MtpUtils.cpp \
+
+LOCAL_MODULE:= libmtp
+
+LOCAL_CFLAGS := -DMTP_DEVICE -DMTP_HOST
+
+# Needed for <bionic_time.h>
+LOCAL_C_INCLUDES := bionic/libc/private
+
+LOCAL_SHARED_LIBRARIES := libutils libcutils libusbhost libbinder
+
+include $(BUILD_SHARED_LIBRARY)
+
+ifeq ($(HOST_OS),linux)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ MtpDataPacket.cpp \
+ MtpDebug.cpp \
+ MtpDevice.cpp \
+ MtpEventPacket.cpp \
+ MtpDeviceInfo.cpp \
+ MtpObjectInfo.cpp \
+ MtpPacket.cpp \
+ MtpProperty.cpp \
+ MtpRequestPacket.cpp \
+ MtpResponsePacket.cpp \
+ MtpStorageInfo.cpp \
+ MtpStringBuffer.cpp \
+ MtpStorage.cpp \
+ MtpUtils.cpp \
+
+LOCAL_MODULE:= libmtp
+
+LOCAL_CFLAGS := -DMTP_HOST
+
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+endif
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
new file mode 100644
index 0000000..930f0b0
--- /dev/null
+++ b/media/mtp/MtpDataPacket.cpp
@@ -0,0 +1,490 @@
+/*
+ * 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 "MtpDataPacket"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include <usbhost/usbhost.h>
+
+#include "MtpDataPacket.h"
+#include "MtpStringBuffer.h"
+
+#define MTP_BUFFER_SIZE 16384
+
+namespace android {
+
+MtpDataPacket::MtpDataPacket()
+ : MtpPacket(MTP_BUFFER_SIZE), // MAX_USBFS_BUFFER_SIZE
+ mOffset(MTP_CONTAINER_HEADER_SIZE)
+{
+}
+
+MtpDataPacket::~MtpDataPacket() {
+}
+
+void MtpDataPacket::reset() {
+ MtpPacket::reset();
+ mOffset = MTP_CONTAINER_HEADER_SIZE;
+}
+
+void MtpDataPacket::setOperationCode(MtpOperationCode code) {
+ MtpPacket::putUInt16(MTP_CONTAINER_CODE_OFFSET, code);
+}
+
+void MtpDataPacket::setTransactionID(MtpTransactionID id) {
+ MtpPacket::putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id);
+}
+
+uint16_t MtpDataPacket::getUInt16() {
+ int offset = mOffset;
+ uint16_t result = (uint16_t)mBuffer[offset] | ((uint16_t)mBuffer[offset + 1] << 8);
+ mOffset += 2;
+ return result;
+}
+
+uint32_t MtpDataPacket::getUInt32() {
+ int offset = mOffset;
+ uint32_t result = (uint32_t)mBuffer[offset] | ((uint32_t)mBuffer[offset + 1] << 8) |
+ ((uint32_t)mBuffer[offset + 2] << 16) | ((uint32_t)mBuffer[offset + 3] << 24);
+ mOffset += 4;
+ return result;
+}
+
+uint64_t MtpDataPacket::getUInt64() {
+ int offset = mOffset;
+ uint64_t result = (uint64_t)mBuffer[offset] | ((uint64_t)mBuffer[offset + 1] << 8) |
+ ((uint64_t)mBuffer[offset + 2] << 16) | ((uint64_t)mBuffer[offset + 3] << 24) |
+ ((uint64_t)mBuffer[offset + 4] << 32) | ((uint64_t)mBuffer[offset + 5] << 40) |
+ ((uint64_t)mBuffer[offset + 6] << 48) | ((uint64_t)mBuffer[offset + 7] << 56);
+ mOffset += 8;
+ return result;
+}
+
+void MtpDataPacket::getUInt128(uint128_t& value) {
+ value[0] = getUInt32();
+ value[1] = getUInt32();
+ value[2] = getUInt32();
+ value[3] = getUInt32();
+}
+
+void MtpDataPacket::getString(MtpStringBuffer& string)
+{
+ string.readFromPacket(this);
+}
+
+Int8List* MtpDataPacket::getAInt8() {
+ Int8List* result = new Int8List;
+ int count = getUInt32();
+ for (int i = 0; i < count; i++)
+ result->push(getInt8());
+ return result;
+}
+
+UInt8List* MtpDataPacket::getAUInt8() {
+ UInt8List* result = new UInt8List;
+ int count = getUInt32();
+ for (int i = 0; i < count; i++)
+ result->push(getUInt8());
+ return result;
+}
+
+Int16List* MtpDataPacket::getAInt16() {
+ Int16List* result = new Int16List;
+ int count = getUInt32();
+ for (int i = 0; i < count; i++)
+ result->push(getInt16());
+ return result;
+}
+
+UInt16List* MtpDataPacket::getAUInt16() {
+ UInt16List* result = new UInt16List;
+ int count = getUInt32();
+ for (int i = 0; i < count; i++)
+ result->push(getUInt16());
+ return result;
+}
+
+Int32List* MtpDataPacket::getAInt32() {
+ Int32List* result = new Int32List;
+ int count = getUInt32();
+ for (int i = 0; i < count; i++)
+ result->push(getInt32());
+ return result;
+}
+
+UInt32List* MtpDataPacket::getAUInt32() {
+ UInt32List* result = new UInt32List;
+ int count = getUInt32();
+ for (int i = 0; i < count; i++)
+ result->push(getUInt32());
+ return result;
+}
+
+Int64List* MtpDataPacket::getAInt64() {
+ Int64List* result = new Int64List;
+ int count = getUInt32();
+ for (int i = 0; i < count; i++)
+ result->push(getInt64());
+ return result;
+}
+
+UInt64List* MtpDataPacket::getAUInt64() {
+ UInt64List* result = new UInt64List;
+ int count = getUInt32();
+ for (int i = 0; i < count; i++)
+ result->push(getUInt64());
+ return result;
+}
+
+void MtpDataPacket::putInt8(int8_t value) {
+ allocate(mOffset + 1);
+ mBuffer[mOffset++] = (uint8_t)value;
+ if (mPacketSize < mOffset)
+ mPacketSize = mOffset;
+}
+
+void MtpDataPacket::putUInt8(uint8_t value) {
+ allocate(mOffset + 1);
+ mBuffer[mOffset++] = (uint8_t)value;
+ if (mPacketSize < mOffset)
+ mPacketSize = mOffset;
+}
+
+void MtpDataPacket::putInt16(int16_t value) {
+ allocate(mOffset + 2);
+ mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
+ if (mPacketSize < mOffset)
+ mPacketSize = mOffset;
+}
+
+void MtpDataPacket::putUInt16(uint16_t value) {
+ allocate(mOffset + 2);
+ mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
+ if (mPacketSize < mOffset)
+ mPacketSize = mOffset;
+}
+
+void MtpDataPacket::putInt32(int32_t value) {
+ allocate(mOffset + 4);
+ mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
+ if (mPacketSize < mOffset)
+ mPacketSize = mOffset;
+}
+
+void MtpDataPacket::putUInt32(uint32_t value) {
+ allocate(mOffset + 4);
+ mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
+ if (mPacketSize < mOffset)
+ mPacketSize = mOffset;
+}
+
+void MtpDataPacket::putInt64(int64_t value) {
+ allocate(mOffset + 8);
+ mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF);
+ if (mPacketSize < mOffset)
+ mPacketSize = mOffset;
+}
+
+void MtpDataPacket::putUInt64(uint64_t value) {
+ allocate(mOffset + 8);
+ mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF);
+ mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF);
+ if (mPacketSize < mOffset)
+ mPacketSize = mOffset;
+}
+
+void MtpDataPacket::putInt128(const int128_t& value) {
+ putInt32(value[0]);
+ putInt32(value[1]);
+ putInt32(value[2]);
+ putInt32(value[3]);
+}
+
+void MtpDataPacket::putUInt128(const uint128_t& value) {
+ putUInt32(value[0]);
+ putUInt32(value[1]);
+ putUInt32(value[2]);
+ putUInt32(value[3]);
+}
+
+void MtpDataPacket::putInt128(int64_t value) {
+ putInt64(value);
+ putInt64(value < 0 ? -1 : 0);
+}
+
+void MtpDataPacket::putUInt128(uint64_t value) {
+ putUInt64(value);
+ putUInt64(0);
+}
+
+void MtpDataPacket::putAInt8(const int8_t* values, int count) {
+ putUInt32(count);
+ for (int i = 0; i < count; i++)
+ putInt8(*values++);
+}
+
+void MtpDataPacket::putAUInt8(const uint8_t* values, int count) {
+ putUInt32(count);
+ for (int i = 0; i < count; i++)
+ putUInt8(*values++);
+}
+
+void MtpDataPacket::putAInt16(const int16_t* values, int count) {
+ putUInt32(count);
+ for (int i = 0; i < count; i++)
+ putInt16(*values++);
+}
+
+void MtpDataPacket::putAUInt16(const uint16_t* values, int count) {
+ putUInt32(count);
+ for (int i = 0; i < count; i++)
+ putUInt16(*values++);
+}
+
+void MtpDataPacket::putAUInt16(const UInt16List* values) {
+ size_t count = (values ? values->size() : 0);
+ putUInt32(count);
+ for (size_t i = 0; i < count; i++)
+ putUInt16((*values)[i]);
+}
+
+void MtpDataPacket::putAInt32(const int32_t* values, int count) {
+ putUInt32(count);
+ for (int i = 0; i < count; i++)
+ putInt32(*values++);
+}
+
+void MtpDataPacket::putAUInt32(const uint32_t* values, int count) {
+ putUInt32(count);
+ for (int i = 0; i < count; i++)
+ putUInt32(*values++);
+}
+
+void MtpDataPacket::putAUInt32(const UInt32List* list) {
+ if (!list) {
+ putEmptyArray();
+ } else {
+ size_t size = list->size();
+ putUInt32(size);
+ for (size_t i = 0; i < size; i++)
+ putUInt32((*list)[i]);
+ }
+}
+
+void MtpDataPacket::putAInt64(const int64_t* values, int count) {
+ putUInt32(count);
+ for (int i = 0; i < count; i++)
+ putInt64(*values++);
+}
+
+void MtpDataPacket::putAUInt64(const uint64_t* values, int count) {
+ putUInt32(count);
+ for (int i = 0; i < count; i++)
+ putUInt64(*values++);
+}
+
+void MtpDataPacket::putString(const MtpStringBuffer& string) {
+ string.writeToPacket(this);
+}
+
+void MtpDataPacket::putString(const char* s) {
+ MtpStringBuffer string(s);
+ string.writeToPacket(this);
+}
+
+void MtpDataPacket::putString(const uint16_t* string) {
+ int count = 0;
+ for (int i = 0; i < 256; i++) {
+ if (string[i])
+ count++;
+ else
+ break;
+ }
+ putUInt8(count > 0 ? count + 1 : 0);
+ for (int i = 0; i < count; i++)
+ putUInt16(string[i]);
+ // only terminate with zero if string is not empty
+ if (count > 0)
+ putUInt16(0);
+}
+
+#ifdef MTP_DEVICE
+int MtpDataPacket::read(int fd) {
+ int ret = ::read(fd, mBuffer, MTP_BUFFER_SIZE);
+ if (ret < MTP_CONTAINER_HEADER_SIZE)
+ return -1;
+ mPacketSize = ret;
+ mOffset = MTP_CONTAINER_HEADER_SIZE;
+ return ret;
+}
+
+int MtpDataPacket::write(int fd) {
+ MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
+ MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
+ int ret = ::write(fd, mBuffer, mPacketSize);
+ return (ret < 0 ? ret : 0);
+}
+
+int MtpDataPacket::writeData(int fd, void* data, uint32_t length) {
+ allocate(length);
+ memcpy(mBuffer + MTP_CONTAINER_HEADER_SIZE, data, length);
+ length += MTP_CONTAINER_HEADER_SIZE;
+ MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);
+ MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
+ int ret = ::write(fd, mBuffer, length);
+ return (ret < 0 ? ret : 0);
+}
+
+#endif // MTP_DEVICE
+
+#ifdef MTP_HOST
+int MtpDataPacket::read(struct usb_request *request) {
+ // first read the header
+ request->buffer = mBuffer;
+ request->buffer_length = mBufferSize;
+ int length = transfer(request);
+ if (length >= MTP_CONTAINER_HEADER_SIZE) {
+ // look at the length field to see if the data spans multiple packets
+ uint32_t totalLength = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET);
+ allocate(totalLength);
+ while (totalLength > length) {
+ request->buffer = mBuffer + length;
+ request->buffer_length = totalLength - length;
+ int ret = transfer(request);
+ if (ret >= 0)
+ length += ret;
+ else {
+ length = ret;
+ break;
+ }
+ }
+ }
+ if (length >= 0)
+ mPacketSize = length;
+ return length;
+}
+
+int MtpDataPacket::readData(struct usb_request *request, void* buffer, int length) {
+ int read = 0;
+ while (read < length) {
+ request->buffer = (char *)buffer + read;
+ request->buffer_length = length - read;
+ int ret = transfer(request);
+ if (ret < 0) {
+ return ret;
+ }
+ read += ret;
+ }
+ return read;
+}
+
+// Queue a read request. Call readDataWait to wait for result
+int MtpDataPacket::readDataAsync(struct usb_request *req) {
+ if (usb_request_queue(req)) {
+ ALOGE("usb_endpoint_queue failed, errno: %d", errno);
+ return -1;
+ }
+ return 0;
+}
+
+// Wait for result of readDataAsync
+int MtpDataPacket::readDataWait(struct usb_device *device) {
+ struct usb_request *req = usb_request_wait(device);
+ return (req ? req->actual_length : -1);
+}
+
+int MtpDataPacket::readDataHeader(struct usb_request *request) {
+ request->buffer = mBuffer;
+ request->buffer_length = request->max_packet_size;
+ int length = transfer(request);
+ if (length >= 0)
+ mPacketSize = length;
+ return length;
+}
+
+int MtpDataPacket::writeDataHeader(struct usb_request *request, uint32_t length) {
+ MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);
+ MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
+ request->buffer = mBuffer;
+ request->buffer_length = MTP_CONTAINER_HEADER_SIZE;
+ int ret = transfer(request);
+ return (ret < 0 ? ret : 0);
+}
+
+int MtpDataPacket::write(struct usb_request *request) {
+ MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
+ MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
+
+ // send header separately from data
+ request->buffer = mBuffer;
+ request->buffer_length = MTP_CONTAINER_HEADER_SIZE;
+ int ret = transfer(request);
+ if (ret == MTP_CONTAINER_HEADER_SIZE) {
+ request->buffer = mBuffer + MTP_CONTAINER_HEADER_SIZE;
+ request->buffer_length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
+ ret = transfer(request);
+ }
+ return (ret < 0 ? ret : 0);
+}
+
+int MtpDataPacket::write(struct usb_request *request, void* buffer, uint32_t length) {
+ request->buffer = buffer;
+ request->buffer_length = length;
+ int ret = transfer(request);
+ return (ret < 0 ? ret : 0);
+}
+
+#endif // MTP_HOST
+
+void* MtpDataPacket::getData(int& outLength) const {
+ int length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
+ if (length > 0) {
+ void* result = malloc(length);
+ if (result) {
+ memcpy(result, mBuffer + MTP_CONTAINER_HEADER_SIZE, length);
+ outLength = length;
+ return result;
+ }
+ }
+ outLength = 0;
+ return NULL;
+}
+
+} // namespace android
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
new file mode 100644
index 0000000..2b81063
--- /dev/null
+++ b/media/mtp/MtpDataPacket.h
@@ -0,0 +1,124 @@
+/*
+ * 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 _MTP_DATA_PACKET_H
+#define _MTP_DATA_PACKET_H
+
+#include "MtpPacket.h"
+#include "mtp.h"
+
+struct usb_device;
+struct usb_request;
+
+namespace android {
+
+class MtpStringBuffer;
+
+class MtpDataPacket : public MtpPacket {
+private:
+ // current offset for get/put methods
+ int mOffset;
+
+public:
+ MtpDataPacket();
+ virtual ~MtpDataPacket();
+
+ virtual void reset();
+
+ void setOperationCode(MtpOperationCode code);
+ void setTransactionID(MtpTransactionID id);
+
+ inline const uint8_t* getData() const { return mBuffer + MTP_CONTAINER_HEADER_SIZE; }
+ inline uint8_t getUInt8() { return (uint8_t)mBuffer[mOffset++]; }
+ inline int8_t getInt8() { return (int8_t)mBuffer[mOffset++]; }
+ uint16_t getUInt16();
+ inline int16_t getInt16() { return (int16_t)getUInt16(); }
+ uint32_t getUInt32();
+ inline int32_t getInt32() { return (int32_t)getUInt32(); }
+ uint64_t getUInt64();
+ inline int64_t getInt64() { return (int64_t)getUInt64(); }
+ void getUInt128(uint128_t& value);
+ inline void getInt128(int128_t& value) { getUInt128((uint128_t&)value); }
+ void getString(MtpStringBuffer& string);
+
+ Int8List* getAInt8();
+ UInt8List* getAUInt8();
+ Int16List* getAInt16();
+ UInt16List* getAUInt16();
+ Int32List* getAInt32();
+ UInt32List* getAUInt32();
+ Int64List* getAInt64();
+ UInt64List* getAUInt64();
+
+ void putInt8(int8_t value);
+ void putUInt8(uint8_t value);
+ void putInt16(int16_t value);
+ void putUInt16(uint16_t value);
+ void putInt32(int32_t value);
+ void putUInt32(uint32_t value);
+ void putInt64(int64_t value);
+ void putUInt64(uint64_t value);
+ void putInt128(const int128_t& value);
+ void putUInt128(const uint128_t& value);
+ void putInt128(int64_t value);
+ void putUInt128(uint64_t value);
+
+ void putAInt8(const int8_t* values, int count);
+ void putAUInt8(const uint8_t* values, int count);
+ void putAInt16(const int16_t* values, int count);
+ void putAUInt16(const uint16_t* values, int count);
+ void putAUInt16(const UInt16List* values);
+ void putAInt32(const int32_t* values, int count);
+ void putAUInt32(const uint32_t* values, int count);
+ void putAUInt32(const UInt32List* list);
+ void putAInt64(const int64_t* values, int count);
+ void putAUInt64(const uint64_t* values, int count);
+ void putString(const MtpStringBuffer& string);
+ void putString(const char* string);
+ void putString(const uint16_t* string);
+ inline void putEmptyString() { putUInt8(0); }
+ inline void putEmptyArray() { putUInt32(0); }
+
+
+#ifdef MTP_DEVICE
+ // fill our buffer with data from the given file descriptor
+ int read(int fd);
+
+ // write our data to the given file descriptor
+ int write(int fd);
+ int writeData(int fd, void* data, uint32_t length);
+#endif
+
+#ifdef MTP_HOST
+ int read(struct usb_request *request);
+ int readData(struct usb_request *request, void* buffer, int length);
+ int readDataAsync(struct usb_request *req);
+ int readDataWait(struct usb_device *device);
+ int readDataHeader(struct usb_request *ep);
+
+ int writeDataHeader(struct usb_request *ep, uint32_t length);
+ int write(struct usb_request *ep);
+ int write(struct usb_request *ep, void* buffer, uint32_t length);
+#endif
+
+ inline bool hasData() const { return mPacketSize > MTP_CONTAINER_HEADER_SIZE; }
+ inline uint32_t getContainerLength() const { return MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET); }
+ void* getData(int& outLength) const;
+};
+
+}; // namespace android
+
+#endif // _MTP_DATA_PACKET_H
diff --git a/media/mtp/MtpDatabase.h b/media/mtp/MtpDatabase.h
new file mode 100644
index 0000000..4e6ac7a
--- /dev/null
+++ b/media/mtp/MtpDatabase.h
@@ -0,0 +1,113 @@
+/*
+ * 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 _MTP_DATABASE_H
+#define _MTP_DATABASE_H
+
+#include "MtpTypes.h"
+
+namespace android {
+
+class MtpDataPacket;
+class MtpProperty;
+class MtpObjectInfo;
+
+class MtpDatabase {
+public:
+ virtual ~MtpDatabase() {}
+
+ // called from SendObjectInfo to reserve a database entry for the incoming file
+ virtual MtpObjectHandle beginSendObject(const char* path,
+ MtpObjectFormat format,
+ MtpObjectHandle parent,
+ MtpStorageID storage,
+ uint64_t size,
+ time_t modified) = 0;
+
+ // called to report success or failure of the SendObject file transfer
+ // success should signal a notification of the new object's creation,
+ // failure should remove the database entry created in beginSendObject
+ virtual void endSendObject(const char* path,
+ MtpObjectHandle handle,
+ MtpObjectFormat format,
+ bool succeeded) = 0;
+
+ virtual MtpObjectHandleList* getObjectList(MtpStorageID storageID,
+ MtpObjectFormat format,
+ MtpObjectHandle parent) = 0;
+
+ virtual int getNumObjects(MtpStorageID storageID,
+ MtpObjectFormat format,
+ MtpObjectHandle parent) = 0;
+
+ // callee should delete[] the results from these
+ // results can be NULL
+ virtual MtpObjectFormatList* getSupportedPlaybackFormats() = 0;
+ virtual MtpObjectFormatList* getSupportedCaptureFormats() = 0;
+ virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format) = 0;
+ virtual MtpDevicePropertyList* getSupportedDeviceProperties() = 0;
+
+ virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle handle,
+ MtpObjectProperty property,
+ MtpDataPacket& packet) = 0;
+
+ virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle handle,
+ MtpObjectProperty property,
+ MtpDataPacket& packet) = 0;
+
+ virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty property,
+ MtpDataPacket& packet) = 0;
+
+ virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty property,
+ MtpDataPacket& packet) = 0;
+
+ virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty property) = 0;
+
+ virtual MtpResponseCode getObjectPropertyList(MtpObjectHandle handle,
+ uint32_t format, uint32_t property,
+ int groupCode, int depth,
+ MtpDataPacket& packet) = 0;
+
+ virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
+ MtpObjectInfo& info) = 0;
+
+ virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) = 0;
+
+ virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
+ MtpString& outFilePath,
+ int64_t& outFileLength,
+ MtpObjectFormat& outFormat) = 0;
+
+ virtual MtpResponseCode deleteFile(MtpObjectHandle handle) = 0;
+
+ virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle) = 0;
+
+ virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
+ MtpObjectHandleList* references) = 0;
+
+ virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property,
+ MtpObjectFormat format) = 0;
+
+ virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property) = 0;
+
+ virtual void sessionStarted() = 0;
+
+ virtual void sessionEnded() = 0;
+};
+
+}; // namespace android
+
+#endif // _MTP_DATABASE_H
diff --git a/media/mtp/MtpDebug.cpp b/media/mtp/MtpDebug.cpp
new file mode 100644
index 0000000..9f3037d
--- /dev/null
+++ b/media/mtp/MtpDebug.cpp
@@ -0,0 +1,402 @@
+/*
+ * 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 "MtpDebug.h"
+
+namespace android {
+
+struct CodeEntry {
+ const char* name;
+ uint16_t code;
+};
+
+static const CodeEntry sOperationCodes[] = {
+ { "MTP_OPERATION_GET_DEVICE_INFO", 0x1001 },
+ { "MTP_OPERATION_OPEN_SESSION", 0x1002 },
+ { "MTP_OPERATION_CLOSE_SESSION", 0x1003 },
+ { "MTP_OPERATION_GET_STORAGE_IDS", 0x1004 },
+ { "MTP_OPERATION_GET_STORAGE_INFO", 0x1005 },
+ { "MTP_OPERATION_GET_NUM_OBJECTS", 0x1006 },
+ { "MTP_OPERATION_GET_OBJECT_HANDLES", 0x1007 },
+ { "MTP_OPERATION_GET_OBJECT_INFO", 0x1008 },
+ { "MTP_OPERATION_GET_OBJECT", 0x1009 },
+ { "MTP_OPERATION_GET_THUMB", 0x100A },
+ { "MTP_OPERATION_DELETE_OBJECT", 0x100B },
+ { "MTP_OPERATION_SEND_OBJECT_INFO", 0x100C },
+ { "MTP_OPERATION_SEND_OBJECT", 0x100D },
+ { "MTP_OPERATION_INITIATE_CAPTURE", 0x100E },
+ { "MTP_OPERATION_FORMAT_STORE", 0x100F },
+ { "MTP_OPERATION_RESET_DEVICE", 0x1010 },
+ { "MTP_OPERATION_SELF_TEST", 0x1011 },
+ { "MTP_OPERATION_SET_OBJECT_PROTECTION", 0x1012 },
+ { "MTP_OPERATION_POWER_DOWN", 0x1013 },
+ { "MTP_OPERATION_GET_DEVICE_PROP_DESC", 0x1014 },
+ { "MTP_OPERATION_GET_DEVICE_PROP_VALUE", 0x1015 },
+ { "MTP_OPERATION_SET_DEVICE_PROP_VALUE", 0x1016 },
+ { "MTP_OPERATION_RESET_DEVICE_PROP_VALUE", 0x1017 },
+ { "MTP_OPERATION_TERMINATE_OPEN_CAPTURE", 0x1018 },
+ { "MTP_OPERATION_MOVE_OBJECT", 0x1019 },
+ { "MTP_OPERATION_COPY_OBJECT", 0x101A },
+ { "MTP_OPERATION_GET_PARTIAL_OBJECT", 0x101B },
+ { "MTP_OPERATION_INITIATE_OPEN_CAPTURE", 0x101C },
+ { "MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED", 0x9801 },
+ { "MTP_OPERATION_GET_OBJECT_PROP_DESC", 0x9802 },
+ { "MTP_OPERATION_GET_OBJECT_PROP_VALUE", 0x9803 },
+ { "MTP_OPERATION_SET_OBJECT_PROP_VALUE", 0x9804 },
+ { "MTP_OPERATION_GET_OBJECT_PROP_LIST", 0x9805 },
+ { "MTP_OPERATION_SET_OBJECT_PROP_LIST", 0x9806 },
+ { "MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC", 0x9807 },
+ { "MTP_OPERATION_SEND_OBJECT_PROP_LIST", 0x9808 },
+ { "MTP_OPERATION_GET_OBJECT_REFERENCES", 0x9810 },
+ { "MTP_OPERATION_SET_OBJECT_REFERENCES", 0x9811 },
+ { "MTP_OPERATION_SKIP", 0x9820 },
+ // android extensions
+ { "MTP_OPERATION_GET_PARTIAL_OBJECT_64", 0x95C1 },
+ { "MTP_OPERATION_SEND_PARTIAL_OBJECT", 0x95C2 },
+ { "MTP_OPERATION_TRUNCATE_OBJECT", 0x95C3 },
+ { "MTP_OPERATION_BEGIN_EDIT_OBJECT", 0x95C4 },
+ { "MTP_OPERATION_END_EDIT_OBJECT", 0x95C5 },
+ { 0, 0 },
+};
+
+static const CodeEntry sFormatCodes[] = {
+ { "MTP_FORMAT_UNDEFINED", 0x3000 },
+ { "MTP_FORMAT_ASSOCIATION", 0x3001 },
+ { "MTP_FORMAT_SCRIPT", 0x3002 },
+ { "MTP_FORMAT_EXECUTABLE", 0x3003 },
+ { "MTP_FORMAT_TEXT", 0x3004 },
+ { "MTP_FORMAT_HTML", 0x3005 },
+ { "MTP_FORMAT_DPOF", 0x3006 },
+ { "MTP_FORMAT_AIFF", 0x3007 },
+ { "MTP_FORMAT_WAV", 0x3008 },
+ { "MTP_FORMAT_MP3", 0x3009 },
+ { "MTP_FORMAT_AVI", 0x300A },
+ { "MTP_FORMAT_MPEG", 0x300B },
+ { "MTP_FORMAT_ASF", 0x300C },
+ { "MTP_FORMAT_DEFINED", 0x3800 },
+ { "MTP_FORMAT_EXIF_JPEG", 0x3801 },
+ { "MTP_FORMAT_TIFF_EP", 0x3802 },
+ { "MTP_FORMAT_FLASHPIX", 0x3803 },
+ { "MTP_FORMAT_BMP", 0x3804 },
+ { "MTP_FORMAT_CIFF", 0x3805 },
+ { "MTP_FORMAT_GIF", 0x3807 },
+ { "MTP_FORMAT_JFIF", 0x3808 },
+ { "MTP_FORMAT_CD", 0x3809 },
+ { "MTP_FORMAT_PICT", 0x380A },
+ { "MTP_FORMAT_PNG", 0x380B },
+ { "MTP_FORMAT_TIFF", 0x380D },
+ { "MTP_FORMAT_TIFF_IT", 0x380E },
+ { "MTP_FORMAT_JP2", 0x380F },
+ { "MTP_FORMAT_JPX", 0x3810 },
+ { "MTP_FORMAT_UNDEFINED_FIRMWARE", 0xB802 },
+ { "MTP_FORMAT_WINDOWS_IMAGE_FORMAT", 0xB881 },
+ { "MTP_FORMAT_UNDEFINED_AUDIO", 0xB900 },
+ { "MTP_FORMAT_WMA", 0xB901 },
+ { "MTP_FORMAT_OGG", 0xB902 },
+ { "MTP_FORMAT_AAC", 0xB903 },
+ { "MTP_FORMAT_AUDIBLE", 0xB904 },
+ { "MTP_FORMAT_FLAC", 0xB906 },
+ { "MTP_FORMAT_UNDEFINED_VIDEO", 0xB980 },
+ { "MTP_FORMAT_WMV", 0xB981 },
+ { "MTP_FORMAT_MP4_CONTAINER", 0xB982 },
+ { "MTP_FORMAT_MP2", 0xB983 },
+ { "MTP_FORMAT_3GP_CONTAINER", 0xB984 },
+ { "MTP_FORMAT_UNDEFINED_COLLECTION", 0xBA00 },
+ { "MTP_FORMAT_ABSTRACT_MULTIMEDIA_ALBUM", 0xBA01 },
+ { "MTP_FORMAT_ABSTRACT_IMAGE_ALBUM", 0xBA02 },
+ { "MTP_FORMAT_ABSTRACT_AUDIO_ALBUM", 0xBA03 },
+ { "MTP_FORMAT_ABSTRACT_VIDEO_ALBUM", 0xBA04 },
+ { "MTP_FORMAT_ABSTRACT_AV_PLAYLIST", 0xBA05 },
+ { "MTP_FORMAT_ABSTRACT_CONTACT_GROUP", 0xBA06 },
+ { "MTP_FORMAT_ABSTRACT_MESSAGE_FOLDER", 0xBA07 },
+ { "MTP_FORMAT_ABSTRACT_CHAPTERED_PRODUCTION", 0xBA08 },
+ { "MTP_FORMAT_ABSTRACT_AUDIO_PLAYLIST", 0xBA09 },
+ { "MTP_FORMAT_ABSTRACT_VIDEO_PLAYLIST", 0xBA0A },
+ { "MTP_FORMAT_ABSTRACT_MEDIACAST", 0xBA0B },
+ { "MTP_FORMAT_WPL_PLAYLIST", 0xBA10 },
+ { "MTP_FORMAT_M3U_PLAYLIST", 0xBA11 },
+ { "MTP_FORMAT_MPL_PLAYLIST", 0xBA12 },
+ { "MTP_FORMAT_ASX_PLAYLIST", 0xBA13 },
+ { "MTP_FORMAT_PLS_PLAYLIST", 0xBA14 },
+ { "MTP_FORMAT_UNDEFINED_DOCUMENT", 0xBA80 },
+ { "MTP_FORMAT_ABSTRACT_DOCUMENT", 0xBA81 },
+ { "MTP_FORMAT_XML_DOCUMENT", 0xBA82 },
+ { "MTP_FORMAT_MS_WORD_DOCUMENT", 0xBA83 },
+ { "MTP_FORMAT_MHT_COMPILED_HTML_DOCUMENT", 0xBA84 },
+ { "MTP_FORMAT_MS_EXCEL_SPREADSHEET", 0xBA85 },
+ { "MTP_FORMAT_MS_POWERPOINT_PRESENTATION", 0xBA86 },
+ { "MTP_FORMAT_UNDEFINED_MESSAGE", 0xBB00 },
+ { "MTP_FORMAT_ABSTRACT_MESSSAGE", 0xBB01 },
+ { "MTP_FORMAT_UNDEFINED_CONTACT", 0xBB80 },
+ { "MTP_FORMAT_ABSTRACT_CONTACT", 0xBB81 },
+ { "MTP_FORMAT_VCARD_2", 0xBB82 },
+ { 0, 0 },
+};
+
+static const CodeEntry sObjectPropCodes[] = {
+ { "MTP_PROPERTY_STORAGE_ID", 0xDC01 },
+ { "MTP_PROPERTY_OBJECT_FORMAT", 0xDC02 },
+ { "MTP_PROPERTY_PROTECTION_STATUS", 0xDC03 },
+ { "MTP_PROPERTY_OBJECT_SIZE", 0xDC04 },
+ { "MTP_PROPERTY_ASSOCIATION_TYPE", 0xDC05 },
+ { "MTP_PROPERTY_ASSOCIATION_DESC", 0xDC06 },
+ { "MTP_PROPERTY_OBJECT_FILE_NAME", 0xDC07 },
+ { "MTP_PROPERTY_DATE_CREATED", 0xDC08 },
+ { "MTP_PROPERTY_DATE_MODIFIED", 0xDC09 },
+ { "MTP_PROPERTY_KEYWORDS", 0xDC0A },
+ { "MTP_PROPERTY_PARENT_OBJECT", 0xDC0B },
+ { "MTP_PROPERTY_ALLOWED_FOLDER_CONTENTS", 0xDC0C },
+ { "MTP_PROPERTY_HIDDEN", 0xDC0D },
+ { "MTP_PROPERTY_SYSTEM_OBJECT", 0xDC0E },
+ { "MTP_PROPERTY_PERSISTENT_UID", 0xDC41 },
+ { "MTP_PROPERTY_SYNC_ID", 0xDC42 },
+ { "MTP_PROPERTY_PROPERTY_BAG", 0xDC43 },
+ { "MTP_PROPERTY_NAME", 0xDC44 },
+ { "MTP_PROPERTY_CREATED_BY", 0xDC45 },
+ { "MTP_PROPERTY_ARTIST", 0xDC46 },
+ { "MTP_PROPERTY_DATE_AUTHORED", 0xDC47 },
+ { "MTP_PROPERTY_DESCRIPTION", 0xDC48 },
+ { "MTP_PROPERTY_URL_REFERENCE", 0xDC49 },
+ { "MTP_PROPERTY_LANGUAGE_LOCALE", 0xDC4A },
+ { "MTP_PROPERTY_COPYRIGHT_INFORMATION", 0xDC4B },
+ { "MTP_PROPERTY_SOURCE", 0xDC4C },
+ { "MTP_PROPERTY_ORIGIN_LOCATION", 0xDC4D },
+ { "MTP_PROPERTY_DATE_ADDED", 0xDC4E },
+ { "MTP_PROPERTY_NON_CONSUMABLE", 0xDC4F },
+ { "MTP_PROPERTY_CORRUPT_UNPLAYABLE", 0xDC50 },
+ { "MTP_PROPERTY_PRODUCER_SERIAL_NUMBER", 0xDC51 },
+ { "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_FORMAT", 0xDC81 },
+ { "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_SIZE", 0xDC82 },
+ { "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_HEIGHT", 0xDC83 },
+ { "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_WIDTH", 0xDC84 },
+ { "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DURATION", 0xDC85 },
+ { "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DATA", 0xDC86 },
+ { "MTP_PROPERTY_WIDTH", 0xDC87 },
+ { "MTP_PROPERTY_HEIGHT", 0xDC88 },
+ { "MTP_PROPERTY_DURATION", 0xDC89 },
+ { "MTP_PROPERTY_RATING", 0xDC8A },
+ { "MTP_PROPERTY_TRACK", 0xDC8B },
+ { "MTP_PROPERTY_GENRE", 0xDC8C },
+ { "MTP_PROPERTY_CREDITS", 0xDC8D },
+ { "MTP_PROPERTY_LYRICS", 0xDC8E },
+ { "MTP_PROPERTY_SUBSCRIPTION_CONTENT_ID", 0xDC8F },
+ { "MTP_PROPERTY_PRODUCED_BY", 0xDC90 },
+ { "MTP_PROPERTY_USE_COUNT", 0xDC91 },
+ { "MTP_PROPERTY_SKIP_COUNT", 0xDC92 },
+ { "MTP_PROPERTY_LAST_ACCESSED", 0xDC93 },
+ { "MTP_PROPERTY_PARENTAL_RATING", 0xDC94 },
+ { "MTP_PROPERTY_META_GENRE", 0xDC95 },
+ { "MTP_PROPERTY_COMPOSER", 0xDC96 },
+ { "MTP_PROPERTY_EFFECTIVE_RATING", 0xDC97 },
+ { "MTP_PROPERTY_SUBTITLE", 0xDC98 },
+ { "MTP_PROPERTY_ORIGINAL_RELEASE_DATE", 0xDC99 },
+ { "MTP_PROPERTY_ALBUM_NAME", 0xDC9A },
+ { "MTP_PROPERTY_ALBUM_ARTIST", 0xDC9B },
+ { "MTP_PROPERTY_MOOD", 0xDC9C },
+ { "MTP_PROPERTY_DRM_STATUS", 0xDC9D },
+ { "MTP_PROPERTY_SUB_DESCRIPTION", 0xDC9E },
+ { "MTP_PROPERTY_IS_CROPPED", 0xDCD1 },
+ { "MTP_PROPERTY_IS_COLOUR_CORRECTED", 0xDCD2 },
+ { "MTP_PROPERTY_IMAGE_BIT_DEPTH", 0xDCD3 },
+ { "MTP_PROPERTY_F_NUMBER", 0xDCD4 },
+ { "MTP_PROPERTY_EXPOSURE_TIME", 0xDCD5 },
+ { "MTP_PROPERTY_EXPOSURE_INDEX", 0xDCD6 },
+ { "MTP_PROPERTY_TOTAL_BITRATE", 0xDE91 },
+ { "MTP_PROPERTY_BITRATE_TYPE", 0xDE92 },
+ { "MTP_PROPERTY_SAMPLE_RATE", 0xDE93 },
+ { "MTP_PROPERTY_NUMBER_OF_CHANNELS", 0xDE94 },
+ { "MTP_PROPERTY_AUDIO_BIT_DEPTH", 0xDE95 },
+ { "MTP_PROPERTY_SCAN_TYPE", 0xDE97 },
+ { "MTP_PROPERTY_AUDIO_WAVE_CODEC", 0xDE99 },
+ { "MTP_PROPERTY_AUDIO_BITRATE", 0xDE9A },
+ { "MTP_PROPERTY_VIDEO_FOURCC_CODEC", 0xDE9B },
+ { "MTP_PROPERTY_VIDEO_BITRATE", 0xDE9C },
+ { "MTP_PROPERTY_FRAMES_PER_THOUSAND_SECONDS", 0xDE9D },
+ { "MTP_PROPERTY_KEYFRAME_DISTANCE", 0xDE9E },
+ { "MTP_PROPERTY_BUFFER_SIZE", 0xDE9F },
+ { "MTP_PROPERTY_ENCODING_QUALITY", 0xDEA0 },
+ { "MTP_PROPERTY_ENCODING_PROFILE", 0xDEA1 },
+ { "MTP_PROPERTY_DISPLAY_NAME", 0xDCE0 },
+ { "MTP_PROPERTY_BODY_TEXT", 0xDCE1 },
+ { "MTP_PROPERTY_SUBJECT", 0xDCE2 },
+ { "MTP_PROPERTY_PRIORITY", 0xDCE3 },
+ { "MTP_PROPERTY_GIVEN_NAME", 0xDD00 },
+ { "MTP_PROPERTY_MIDDLE_NAMES", 0xDD01 },
+ { "MTP_PROPERTY_FAMILY_NAME", 0xDD02 },
+ { "MTP_PROPERTY_PREFIX", 0xDD03 },
+ { "MTP_PROPERTY_SUFFIX", 0xDD04 },
+ { "MTP_PROPERTY_PHONETIC_GIVEN_NAME", 0xDD05 },
+ { "MTP_PROPERTY_PHONETIC_FAMILY_NAME", 0xDD06 },
+ { "MTP_PROPERTY_EMAIL_PRIMARY", 0xDD07 },
+ { "MTP_PROPERTY_EMAIL_PERSONAL_1", 0xDD08 },
+ { "MTP_PROPERTY_EMAIL_PERSONAL_2", 0xDD09 },
+ { "MTP_PROPERTY_EMAIL_BUSINESS_1", 0xDD0A },
+ { "MTP_PROPERTY_EMAIL_BUSINESS_2", 0xDD0B },
+ { "MTP_PROPERTY_EMAIL_OTHERS", 0xDD0C },
+ { "MTP_PROPERTY_PHONE_NUMBER_PRIMARY", 0xDD0D },
+ { "MTP_PROPERTY_PHONE_NUMBER_PERSONAL", 0xDD0E },
+ { "MTP_PROPERTY_PHONE_NUMBER_PERSONAL_2", 0xDD0F },
+ { "MTP_PROPERTY_PHONE_NUMBER_BUSINESS", 0xDD10 },
+ { "MTP_PROPERTY_PHONE_NUMBER_BUSINESS_2", 0xDD11 },
+ { "MTP_PROPERTY_PHONE_NUMBER_MOBILE", 0xDD12 },
+ { "MTP_PROPERTY_PHONE_NUMBER_MOBILE_2", 0xDD13 },
+ { "MTP_PROPERTY_FAX_NUMBER_PRIMARY", 0xDD14 },
+ { "MTP_PROPERTY_FAX_NUMBER_PERSONAL", 0xDD15 },
+ { "MTP_PROPERTY_FAX_NUMBER_BUSINESS", 0xDD16 },
+ { "MTP_PROPERTY_PAGER_NUMBER", 0xDD17 },
+ { "MTP_PROPERTY_PHONE_NUMBER_OTHERS", 0xDD18 },
+ { "MTP_PROPERTY_PRIMARY_WEB_ADDRESS", 0xDD19 },
+ { "MTP_PROPERTY_PERSONAL_WEB_ADDRESS", 0xDD1A },
+ { "MTP_PROPERTY_BUSINESS_WEB_ADDRESS", 0xDD1B },
+ { "MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS", 0xDD1C },
+ { "MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_2", 0xDD1D },
+ { "MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_3", 0xDD1E },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_FULL", 0xDD1F },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_1", 0xDD20 },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_2", 0xDD21 },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_CITY", 0xDD22 },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_REGION", 0xDD23 },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE", 0xDD24 },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_COUNTRY", 0xDD25 },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_FULL", 0xDD26 },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_1", 0xDD27 },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_2", 0xDD28 },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_CITY", 0xDD29 },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_REGION", 0xDD2A },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE", 0xDD2B },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_COUNTRY", 0xDD2C },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_FULL", 0xDD2D },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_1", 0xDD2E },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_2", 0xDD2F },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_CITY", 0xDD30 },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_REGION", 0xDD31 },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_POSTAL_CODE", 0xDD32 },
+ { "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_COUNTRY", 0xDD33 },
+ { "MTP_PROPERTY_ORGANIZATION_NAME", 0xDD34 },
+ { "MTP_PROPERTY_PHONETIC_ORGANIZATION_NAME", 0xDD35 },
+ { "MTP_PROPERTY_ROLE", 0xDD36 },
+ { "MTP_PROPERTY_BIRTHDATE", 0xDD37 },
+ { "MTP_PROPERTY_MESSAGE_TO", 0xDD40 },
+ { "MTP_PROPERTY_MESSAGE_CC", 0xDD41 },
+ { "MTP_PROPERTY_MESSAGE_BCC", 0xDD42 },
+ { "MTP_PROPERTY_MESSAGE_READ", 0xDD43 },
+ { "MTP_PROPERTY_MESSAGE_RECEIVED_TIME", 0xDD44 },
+ { "MTP_PROPERTY_MESSAGE_SENDER", 0xDD45 },
+ { "MTP_PROPERTY_ACTIVITY_BEGIN_TIME", 0xDD50 },
+ { "MTP_PROPERTY_ACTIVITY_END_TIME", 0xDD51 },
+ { "MTP_PROPERTY_ACTIVITY_LOCATION", 0xDD52 },
+ { "MTP_PROPERTY_ACTIVITY_REQUIRED_ATTENDEES", 0xDD54 },
+ { "MTP_PROPERTY_ACTIVITY_OPTIONAL_ATTENDEES", 0xDD55 },
+ { "MTP_PROPERTY_ACTIVITY_RESOURCES", 0xDD56 },
+ { "MTP_PROPERTY_ACTIVITY_ACCEPTED", 0xDD57 },
+ { "MTP_PROPERTY_ACTIVITY_TENTATIVE", 0xDD58 },
+ { "MTP_PROPERTY_ACTIVITY_DECLINED", 0xDD59 },
+ { "MTP_PROPERTY_ACTIVITY_REMAINDER_TIME", 0xDD5A },
+ { "MTP_PROPERTY_ACTIVITY_OWNER", 0xDD5B },
+ { "MTP_PROPERTY_ACTIVITY_STATUS", 0xDD5C },
+ { "MTP_PROPERTY_OWNER", 0xDD5D },
+ { "MTP_PROPERTY_EDITOR", 0xDD5E },
+ { "MTP_PROPERTY_WEBMASTER", 0xDD5F },
+ { "MTP_PROPERTY_URL_SOURCE", 0xDD60 },
+ { "MTP_PROPERTY_URL_DESTINATION", 0xDD61 },
+ { "MTP_PROPERTY_TIME_BOOKMARK", 0xDD62 },
+ { "MTP_PROPERTY_OBJECT_BOOKMARK", 0xDD63 },
+ { "MTP_PROPERTY_BYTE_BOOKMARK", 0xDD64 },
+ { "MTP_PROPERTY_LAST_BUILD_DATE", 0xDD70 },
+ { "MTP_PROPERTY_TIME_TO_LIVE", 0xDD71 },
+ { "MTP_PROPERTY_MEDIA_GUID", 0xDD72 },
+ { 0, 0 },
+};
+
+static const CodeEntry sDevicePropCodes[] = {
+ { "MTP_DEVICE_PROPERTY_UNDEFINED", 0x5000 },
+ { "MTP_DEVICE_PROPERTY_BATTERY_LEVEL", 0x5001 },
+ { "MTP_DEVICE_PROPERTY_FUNCTIONAL_MODE", 0x5002 },
+ { "MTP_DEVICE_PROPERTY_IMAGE_SIZE", 0x5003 },
+ { "MTP_DEVICE_PROPERTY_COMPRESSION_SETTING", 0x5004 },
+ { "MTP_DEVICE_PROPERTY_WHITE_BALANCE", 0x5005 },
+ { "MTP_DEVICE_PROPERTY_RGB_GAIN", 0x5006 },
+ { "MTP_DEVICE_PROPERTY_F_NUMBER", 0x5007 },
+ { "MTP_DEVICE_PROPERTY_FOCAL_LENGTH", 0x5008 },
+ { "MTP_DEVICE_PROPERTY_FOCUS_DISTANCE", 0x5009 },
+ { "MTP_DEVICE_PROPERTY_FOCUS_MODE", 0x500A },
+ { "MTP_DEVICE_PROPERTY_EXPOSURE_METERING_MODE", 0x500B },
+ { "MTP_DEVICE_PROPERTY_FLASH_MODE", 0x500C },
+ { "MTP_DEVICE_PROPERTY_EXPOSURE_TIME", 0x500D },
+ { "MTP_DEVICE_PROPERTY_EXPOSURE_PROGRAM_MODE", 0x500E },
+ { "MTP_DEVICE_PROPERTY_EXPOSURE_INDEX", 0x500F },
+ { "MTP_DEVICE_PROPERTY_EXPOSURE_BIAS_COMPENSATION", 0x5010 },
+ { "MTP_DEVICE_PROPERTY_DATETIME", 0x5011 },
+ { "MTP_DEVICE_PROPERTY_CAPTURE_DELAY", 0x5012 },
+ { "MTP_DEVICE_PROPERTY_STILL_CAPTURE_MODE", 0x5013 },
+ { "MTP_DEVICE_PROPERTY_CONTRAST", 0x5014 },
+ { "MTP_DEVICE_PROPERTY_SHARPNESS", 0x5015 },
+ { "MTP_DEVICE_PROPERTY_DIGITAL_ZOOM", 0x5016 },
+ { "MTP_DEVICE_PROPERTY_EFFECT_MODE", 0x5017 },
+ { "MTP_DEVICE_PROPERTY_BURST_NUMBER", 0x5018 },
+ { "MTP_DEVICE_PROPERTY_BURST_INTERVAL", 0x5019 },
+ { "MTP_DEVICE_PROPERTY_TIMELAPSE_NUMBER", 0x501A },
+ { "MTP_DEVICE_PROPERTY_TIMELAPSE_INTERVAL", 0x501B },
+ { "MTP_DEVICE_PROPERTY_FOCUS_METERING_MODE", 0x501C },
+ { "MTP_DEVICE_PROPERTY_UPLOAD_URL", 0x501D },
+ { "MTP_DEVICE_PROPERTY_ARTIST", 0x501E },
+ { "MTP_DEVICE_PROPERTY_COPYRIGHT_INFO", 0x501F },
+ { "MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER", 0xD401 },
+ { "MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME", 0xD402 },
+ { "MTP_DEVICE_PROPERTY_VOLUME", 0xD403 },
+ { "MTP_DEVICE_PROPERTY_SUPPORTED_FORMATS_ORDERED", 0xD404 },
+ { "MTP_DEVICE_PROPERTY_DEVICE_ICON", 0xD405 },
+ { "MTP_DEVICE_PROPERTY_PLAYBACK_RATE", 0xD410 },
+ { "MTP_DEVICE_PROPERTY_PLAYBACK_OBJECT", 0xD411 },
+ { "MTP_DEVICE_PROPERTY_PLAYBACK_CONTAINER_INDEX", 0xD412 },
+ { "MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO", 0xD406 },
+ { "MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE", 0xD407 },
+ { 0, 0 },
+};
+
+static const char* getCodeName(uint16_t code, const CodeEntry* table) {
+ const CodeEntry* entry = table;
+ while (entry->name) {
+ if (entry->code == code)
+ return entry->name;
+ entry++;
+ }
+ return "UNKNOWN";
+}
+
+const char* MtpDebug::getOperationCodeName(MtpOperationCode code) {
+ return getCodeName(code, sOperationCodes);
+}
+
+const char* MtpDebug::getFormatCodeName(MtpObjectFormat code) {
+ if (code == 0)
+ return "NONE";
+ return getCodeName(code, sFormatCodes);
+}
+
+const char* MtpDebug::getObjectPropCodeName(MtpPropertyCode code) {
+ if (code == 0)
+ return "NONE";
+ return getCodeName(code, sObjectPropCodes);
+}
+
+const char* MtpDebug::getDevicePropCodeName(MtpPropertyCode code) {
+ if (code == 0)
+ return "NONE";
+ return getCodeName(code, sDevicePropCodes);
+}
+
+} // namespace android
diff --git a/media/mtp/MtpDebug.h b/media/mtp/MtpDebug.h
new file mode 100644
index 0000000..5b53e31
--- /dev/null
+++ b/media/mtp/MtpDebug.h
@@ -0,0 +1,37 @@
+/*
+ * 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 _MTP_DEBUG_H
+#define _MTP_DEBUG_H
+
+// #define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "MtpTypes.h"
+
+namespace android {
+
+class MtpDebug {
+public:
+ static const char* getOperationCodeName(MtpOperationCode code);
+ static const char* getFormatCodeName(MtpObjectFormat code);
+ static const char* getObjectPropCodeName(MtpPropertyCode code);
+ static const char* getDevicePropCodeName(MtpPropertyCode code);
+};
+
+}; // namespace android
+
+#endif // _MTP_DEBUG_H
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
new file mode 100644
index 0000000..bf7795c
--- /dev/null
+++ b/media/mtp/MtpDevice.cpp
@@ -0,0 +1,835 @@
+/*
+ * 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 "MtpDevice"
+
+#include "MtpDebug.h"
+#include "MtpDevice.h"
+#include "MtpDeviceInfo.h"
+#include "MtpObjectInfo.h"
+#include "MtpProperty.h"
+#include "MtpStorageInfo.h"
+#include "MtpStringBuffer.h"
+#include "MtpUtils.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <endian.h>
+
+#include <usbhost/usbhost.h>
+
+namespace android {
+
+#if 0
+static bool isMtpDevice(uint16_t vendor, uint16_t product) {
+ // Sandisk Sansa Fuze
+ if (vendor == 0x0781 && product == 0x74c2)
+ return true;
+ // Samsung YP-Z5
+ if (vendor == 0x04e8 && product == 0x503c)
+ return true;
+ return false;
+}
+#endif
+
+MtpDevice* MtpDevice::open(const char* deviceName, int fd) {
+ struct usb_device *device = usb_device_new(deviceName, fd);
+ if (!device) {
+ ALOGE("usb_device_new failed for %s", deviceName);
+ return NULL;
+ }
+
+ struct usb_descriptor_header* desc;
+ struct usb_descriptor_iter iter;
+
+ usb_descriptor_iter_init(device, &iter);
+
+ while ((desc = usb_descriptor_iter_next(&iter)) != NULL) {
+ if (desc->bDescriptorType == USB_DT_INTERFACE) {
+ struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc;
+
+ if (interface->bInterfaceClass == USB_CLASS_STILL_IMAGE &&
+ interface->bInterfaceSubClass == 1 && // Still Image Capture
+ interface->bInterfaceProtocol == 1) // Picture Transfer Protocol (PIMA 15470)
+ {
+ char* manufacturerName = usb_device_get_manufacturer_name(device);
+ char* productName = usb_device_get_product_name(device);
+ ALOGD("Found camera: \"%s\" \"%s\"\n", manufacturerName, productName);
+ free(manufacturerName);
+ free(productName);
+ } else if (interface->bInterfaceClass == 0xFF &&
+ interface->bInterfaceSubClass == 0xFF &&
+ interface->bInterfaceProtocol == 0) {
+ char* interfaceName = usb_device_get_string(device, interface->iInterface);
+ if (!interfaceName) {
+ continue;
+ } else if (strcmp(interfaceName, "MTP")) {
+ free(interfaceName);
+ continue;
+ }
+ free(interfaceName);
+
+ // Looks like an android style MTP device
+ char* manufacturerName = usb_device_get_manufacturer_name(device);
+ char* productName = usb_device_get_product_name(device);
+ ALOGD("Found MTP device: \"%s\" \"%s\"\n", manufacturerName, productName);
+ free(manufacturerName);
+ free(productName);
+ }
+#if 0
+ else {
+ // look for special cased devices based on vendor/product ID
+ // we are doing this mainly for testing purposes
+ uint16_t vendor = usb_device_get_vendor_id(device);
+ uint16_t product = usb_device_get_product_id(device);
+ if (!isMtpDevice(vendor, product)) {
+ // not an MTP or PTP device
+ continue;
+ }
+ // request MTP OS string and descriptor
+ // some music players need to see this before entering MTP mode.
+ char buffer[256];
+ memset(buffer, 0, sizeof(buffer));
+ int ret = usb_device_control_transfer(device,
+ USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_STANDARD,
+ USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) | 0xEE,
+ 0, buffer, sizeof(buffer), 0);
+ printf("usb_device_control_transfer returned %d errno: %d\n", ret, errno);
+ if (ret > 0) {
+ printf("got MTP string %s\n", buffer);
+ ret = usb_device_control_transfer(device,
+ USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_VENDOR, 1,
+ 0, 4, buffer, sizeof(buffer), 0);
+ printf("OS descriptor got %d\n", ret);
+ } else {
+ printf("no MTP string\n");
+ }
+ }
+#endif
+ // if we got here, then we have a likely MTP or PTP device
+
+ // interface should be followed by three endpoints
+ struct usb_endpoint_descriptor *ep;
+ struct usb_endpoint_descriptor *ep_in_desc = NULL;
+ struct usb_endpoint_descriptor *ep_out_desc = NULL;
+ struct usb_endpoint_descriptor *ep_intr_desc = NULL;
+ for (int i = 0; i < 3; i++) {
+ ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
+ if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) {
+ ALOGE("endpoints not found\n");
+ usb_device_close(device);
+ return NULL;
+ }
+ if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
+ if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+ ep_in_desc = ep;
+ else
+ ep_out_desc = ep;
+ } else if (ep->bmAttributes == USB_ENDPOINT_XFER_INT &&
+ ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
+ ep_intr_desc = ep;
+ }
+ }
+ if (!ep_in_desc || !ep_out_desc || !ep_intr_desc) {
+ ALOGE("endpoints not found\n");
+ usb_device_close(device);
+ return NULL;
+ }
+
+ if (usb_device_claim_interface(device, interface->bInterfaceNumber)) {
+ ALOGE("usb_device_claim_interface failed errno: %d\n", errno);
+ usb_device_close(device);
+ return NULL;
+ }
+
+ MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber,
+ ep_in_desc, ep_out_desc, ep_intr_desc);
+ mtpDevice->initialize();
+ return mtpDevice;
+ }
+ }
+
+ usb_device_close(device);
+ ALOGE("device not found");
+ return NULL;
+}
+
+MtpDevice::MtpDevice(struct usb_device* device, int interface,
+ const struct usb_endpoint_descriptor *ep_in,
+ const struct usb_endpoint_descriptor *ep_out,
+ const struct usb_endpoint_descriptor *ep_intr)
+ : mDevice(device),
+ mInterface(interface),
+ mRequestIn1(NULL),
+ mRequestIn2(NULL),
+ mRequestOut(NULL),
+ mRequestIntr(NULL),
+ mDeviceInfo(NULL),
+ mSessionID(0),
+ mTransactionID(0),
+ mReceivedResponse(false)
+{
+ mRequestIn1 = usb_request_new(device, ep_in);
+ mRequestIn2 = usb_request_new(device, ep_in);
+ mRequestOut = usb_request_new(device, ep_out);
+ mRequestIntr = usb_request_new(device, ep_intr);
+}
+
+MtpDevice::~MtpDevice() {
+ close();
+ for (int i = 0; i < mDeviceProperties.size(); i++)
+ delete mDeviceProperties[i];
+ usb_request_free(mRequestIn1);
+ usb_request_free(mRequestIn2);
+ usb_request_free(mRequestOut);
+ usb_request_free(mRequestIntr);
+}
+
+void MtpDevice::initialize() {
+ openSession();
+ mDeviceInfo = getDeviceInfo();
+ if (mDeviceInfo) {
+ if (mDeviceInfo->mDeviceProperties) {
+ int count = mDeviceInfo->mDeviceProperties->size();
+ for (int i = 0; i < count; i++) {
+ MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
+ MtpProperty* property = getDevicePropDesc(propCode);
+ if (property)
+ mDeviceProperties.push(property);
+ }
+ }
+ }
+}
+
+void MtpDevice::close() {
+ if (mDevice) {
+ usb_device_release_interface(mDevice, mInterface);
+ usb_device_close(mDevice);
+ mDevice = NULL;
+ }
+}
+
+void MtpDevice::print() {
+ if (mDeviceInfo) {
+ mDeviceInfo->print();
+
+ if (mDeviceInfo->mDeviceProperties) {
+ ALOGI("***** DEVICE PROPERTIES *****\n");
+ int count = mDeviceInfo->mDeviceProperties->size();
+ for (int i = 0; i < count; i++) {
+ MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
+ MtpProperty* property = getDevicePropDesc(propCode);
+ if (property) {
+ property->print();
+ delete property;
+ }
+ }
+ }
+ }
+
+ if (mDeviceInfo->mPlaybackFormats) {
+ ALOGI("***** OBJECT PROPERTIES *****\n");
+ int count = mDeviceInfo->mPlaybackFormats->size();
+ for (int i = 0; i < count; i++) {
+ MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i];
+ ALOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format));
+ MtpObjectPropertyList* props = getObjectPropsSupported(format);
+ if (props) {
+ for (int j = 0; j < props->size(); j++) {
+ MtpObjectProperty prop = (*props)[j];
+ MtpProperty* property = getObjectPropDesc(prop, format);
+ if (property) {
+ property->print();
+ delete property;
+ } else {
+ ALOGE("could not fetch property: %s",
+ MtpDebug::getObjectPropCodeName(prop));
+ }
+ }
+ }
+ }
+ }
+}
+
+const char* MtpDevice::getDeviceName() {
+ if (mDevice)
+ return usb_device_get_name(mDevice);
+ else
+ return "???";
+}
+
+bool MtpDevice::openSession() {
+ Mutex::Autolock autoLock(mMutex);
+
+ mSessionID = 0;
+ mTransactionID = 0;
+ MtpSessionID newSession = 1;
+ mRequest.reset();
+ mRequest.setParameter(1, newSession);
+ if (!sendRequest(MTP_OPERATION_OPEN_SESSION))
+ return false;
+ MtpResponseCode ret = readResponse();
+ if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN)
+ newSession = mResponse.getParameter(1);
+ else if (ret != MTP_RESPONSE_OK)
+ return false;
+
+ mSessionID = newSession;
+ mTransactionID = 1;
+ return true;
+}
+
+bool MtpDevice::closeSession() {
+ // FIXME
+ return true;
+}
+
+MtpDeviceInfo* MtpDevice::getDeviceInfo() {
+ Mutex::Autolock autoLock(mMutex);
+
+ mRequest.reset();
+ if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO))
+ return NULL;
+ if (!readData())
+ return NULL;
+ MtpResponseCode ret = readResponse();
+ if (ret == MTP_RESPONSE_OK) {
+ MtpDeviceInfo* info = new MtpDeviceInfo;
+ info->read(mData);
+ return info;
+ }
+ return NULL;
+}
+
+MtpStorageIDList* MtpDevice::getStorageIDs() {
+ Mutex::Autolock autoLock(mMutex);
+
+ mRequest.reset();
+ if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS))
+ return NULL;
+ if (!readData())
+ return NULL;
+ MtpResponseCode ret = readResponse();
+ if (ret == MTP_RESPONSE_OK) {
+ return mData.getAUInt32();
+ }
+ return NULL;
+}
+
+MtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) {
+ Mutex::Autolock autoLock(mMutex);
+
+ mRequest.reset();
+ mRequest.setParameter(1, storageID);
+ if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO))
+ return NULL;
+ if (!readData())
+ return NULL;
+ MtpResponseCode ret = readResponse();
+ if (ret == MTP_RESPONSE_OK) {
+ MtpStorageInfo* info = new MtpStorageInfo(storageID);
+ info->read(mData);
+ return info;
+ }
+ return NULL;
+}
+
+MtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID,
+ MtpObjectFormat format, MtpObjectHandle parent) {
+ Mutex::Autolock autoLock(mMutex);
+
+ mRequest.reset();
+ mRequest.setParameter(1, storageID);
+ mRequest.setParameter(2, format);
+ mRequest.setParameter(3, parent);
+ if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES))
+ return NULL;
+ if (!readData())
+ return NULL;
+ MtpResponseCode ret = readResponse();
+ if (ret == MTP_RESPONSE_OK) {
+ return mData.getAUInt32();
+ }
+ return NULL;
+}
+
+MtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
+ Mutex::Autolock autoLock(mMutex);
+
+ // FIXME - we might want to add some caching here
+
+ mRequest.reset();
+ mRequest.setParameter(1, handle);
+ if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO))
+ return NULL;
+ if (!readData())
+ return NULL;
+ MtpResponseCode ret = readResponse();
+ if (ret == MTP_RESPONSE_OK) {
+ MtpObjectInfo* info = new MtpObjectInfo(handle);
+ info->read(mData);
+ return info;
+ }
+ return NULL;
+}
+
+void* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) {
+ Mutex::Autolock autoLock(mMutex);
+
+ mRequest.reset();
+ mRequest.setParameter(1, handle);
+ if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
+ MtpResponseCode ret = readResponse();
+ if (ret == MTP_RESPONSE_OK) {
+ return mData.getData(outLength);
+ }
+ }
+ outLength = 0;
+ return NULL;
+}
+
+MtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) {
+ Mutex::Autolock autoLock(mMutex);
+
+ mRequest.reset();
+ MtpObjectHandle parent = info->mParent;
+ if (parent == 0)
+ parent = MTP_PARENT_ROOT;
+
+ mRequest.setParameter(1, info->mStorageID);
+ mRequest.setParameter(2, info->mParent);
+
+ mData.putUInt32(info->mStorageID);
+ mData.putUInt16(info->mFormat);
+ mData.putUInt16(info->mProtectionStatus);
+ mData.putUInt32(info->mCompressedSize);
+ mData.putUInt16(info->mThumbFormat);
+ mData.putUInt32(info->mThumbCompressedSize);
+ mData.putUInt32(info->mThumbPixWidth);
+ mData.putUInt32(info->mThumbPixHeight);
+ mData.putUInt32(info->mImagePixWidth);
+ mData.putUInt32(info->mImagePixHeight);
+ mData.putUInt32(info->mImagePixDepth);
+ mData.putUInt32(info->mParent);
+ mData.putUInt16(info->mAssociationType);
+ mData.putUInt32(info->mAssociationDesc);
+ mData.putUInt32(info->mSequenceNumber);
+ mData.putString(info->mName);
+
+ char created[100], modified[100];
+ formatDateTime(info->mDateCreated, created, sizeof(created));
+ formatDateTime(info->mDateModified, modified, sizeof(modified));
+
+ mData.putString(created);
+ mData.putString(modified);
+ if (info->mKeywords)
+ mData.putString(info->mKeywords);
+ else
+ mData.putEmptyString();
+
+ if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
+ MtpResponseCode ret = readResponse();
+ if (ret == MTP_RESPONSE_OK) {
+ info->mStorageID = mResponse.getParameter(1);
+ info->mParent = mResponse.getParameter(2);
+ info->mHandle = mResponse.getParameter(3);
+ return info->mHandle;
+ }
+ }
+ return (MtpObjectHandle)-1;
+}
+
+bool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) {
+ Mutex::Autolock autoLock(mMutex);
+
+ int remaining = info->mCompressedSize;
+ mRequest.reset();
+ mRequest.setParameter(1, info->mHandle);
+ if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
+ // send data header
+ writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
+
+ char buffer[65536];
+ while (remaining > 0) {
+ int count = read(srcFD, buffer, sizeof(buffer));
+ if (count > 0) {
+ int written = mData.write(mRequestOut, buffer, count);
+ // FIXME check error
+ remaining -= count;
+ } else {
+ break;
+ }
+ }
+ }
+ MtpResponseCode ret = readResponse();
+ return (remaining == 0 && ret == MTP_RESPONSE_OK);
+}
+
+bool MtpDevice::deleteObject(MtpObjectHandle handle) {
+ Mutex::Autolock autoLock(mMutex);
+
+ mRequest.reset();
+ mRequest.setParameter(1, handle);
+ if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) {
+ MtpResponseCode ret = readResponse();
+ if (ret == MTP_RESPONSE_OK)
+ return true;
+ }
+ return false;
+}
+
+MtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) {
+ MtpObjectInfo* info = getObjectInfo(handle);
+ if (info) {
+ MtpObjectHandle parent = info->mParent;
+ delete info;
+ return parent;
+ } else {
+ return -1;
+ }
+}
+
+MtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) {
+ MtpObjectInfo* info = getObjectInfo(handle);
+ if (info) {
+ MtpObjectHandle storageId = info->mStorageID;
+ delete info;
+ return storageId;
+ } else {
+ return -1;
+ }
+}
+
+MtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) {
+ Mutex::Autolock autoLock(mMutex);
+
+ mRequest.reset();
+ mRequest.setParameter(1, format);
+ if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED))
+ return NULL;
+ if (!readData())
+ return NULL;
+ MtpResponseCode ret = readResponse();
+ if (ret == MTP_RESPONSE_OK) {
+ return mData.getAUInt16();
+ }
+ return NULL;
+
+}
+
+MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
+ Mutex::Autolock autoLock(mMutex);
+
+ mRequest.reset();
+ mRequest.setParameter(1, code);
+ if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC))
+ return NULL;
+ if (!readData())
+ return NULL;
+ MtpResponseCode ret = readResponse();
+ if (ret == MTP_RESPONSE_OK) {
+ MtpProperty* property = new MtpProperty;
+ property->read(mData);
+ return property;
+ }
+ return NULL;
+}
+
+MtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) {
+ Mutex::Autolock autoLock(mMutex);
+
+ mRequest.reset();
+ mRequest.setParameter(1, code);
+ mRequest.setParameter(2, format);
+ if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC))
+ return NULL;
+ if (!readData())
+ return NULL;
+ MtpResponseCode ret = readResponse();
+ if (ret == MTP_RESPONSE_OK) {
+ MtpProperty* property = new MtpProperty;
+ property->read(mData);
+ return property;
+ }
+ return NULL;
+}
+
+bool MtpDevice::readObject(MtpObjectHandle handle,
+ bool (* callback)(void* data, int offset, int length, void* clientData),
+ int objectSize, void* clientData) {
+ Mutex::Autolock autoLock(mMutex);
+ bool result = false;
+
+ mRequest.reset();
+ mRequest.setParameter(1, handle);
+ if (sendRequest(MTP_OPERATION_GET_OBJECT)
+ && mData.readDataHeader(mRequestIn1)) {
+ uint32_t length = mData.getContainerLength();
+ if (length - MTP_CONTAINER_HEADER_SIZE != objectSize) {
+ ALOGE("readObject error objectSize: %d, length: %d",
+ objectSize, length);
+ goto fail;
+ }
+ length -= MTP_CONTAINER_HEADER_SIZE;
+ uint32_t remaining = length;
+ int offset = 0;
+
+ int initialDataLength = 0;
+ void* initialData = mData.getData(initialDataLength);
+ if (initialData) {
+ if (initialDataLength > 0) {
+ if (!callback(initialData, 0, initialDataLength, clientData))
+ goto fail;
+ remaining -= initialDataLength;
+ offset += initialDataLength;
+ }
+ free(initialData);
+ }
+
+ // USB reads greater than 16K don't work
+ char buffer1[16384], buffer2[16384];
+ mRequestIn1->buffer = buffer1;
+ mRequestIn2->buffer = buffer2;
+ struct usb_request* req = mRequestIn1;
+ void* writeBuffer = NULL;
+ int writeLength = 0;
+
+ while (remaining > 0 || writeBuffer) {
+ if (remaining > 0) {
+ // queue up a read request
+ req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
+ if (mData.readDataAsync(req)) {
+ ALOGE("readDataAsync failed");
+ goto fail;
+ }
+ } else {
+ req = NULL;
+ }
+
+ if (writeBuffer) {
+ // write previous buffer
+ if (!callback(writeBuffer, offset, writeLength, clientData)) {
+ ALOGE("write failed");
+ // wait for pending read before failing
+ if (req)
+ mData.readDataWait(mDevice);
+ goto fail;
+ }
+ offset += writeLength;
+ writeBuffer = NULL;
+ }
+
+ // wait for read to complete
+ if (req) {
+ int read = mData.readDataWait(mDevice);
+ if (read < 0)
+ goto fail;
+
+ if (read > 0) {
+ writeBuffer = req->buffer;
+ writeLength = read;
+ remaining -= read;
+ req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
+ } else {
+ writeBuffer = NULL;
+ }
+ }
+ }
+
+ MtpResponseCode response = readResponse();
+ if (response == MTP_RESPONSE_OK)
+ result = true;
+ }
+
+fail:
+ return result;
+}
+
+
+// reads the object's data and writes it to the specified file path
+bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
+ ALOGD("readObject: %s", destPath);
+ int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC);
+ if (fd < 0) {
+ ALOGE("open failed for %s", destPath);
+ return false;
+ }
+
+ fchown(fd, getuid(), group);
+ // set permissions
+ int mask = umask(0);
+ fchmod(fd, perm);
+ umask(mask);
+
+ Mutex::Autolock autoLock(mMutex);
+ bool result = false;
+
+ mRequest.reset();
+ mRequest.setParameter(1, handle);
+ if (sendRequest(MTP_OPERATION_GET_OBJECT)
+ && mData.readDataHeader(mRequestIn1)) {
+ uint32_t length = mData.getContainerLength();
+ if (length < MTP_CONTAINER_HEADER_SIZE)
+ goto fail;
+ length -= MTP_CONTAINER_HEADER_SIZE;
+ uint32_t remaining = length;
+
+ int initialDataLength = 0;
+ void* initialData = mData.getData(initialDataLength);
+ if (initialData) {
+ if (initialDataLength > 0) {
+ if (write(fd, initialData, initialDataLength) != initialDataLength) {
+ free(initialData);
+ goto fail;
+ }
+ remaining -= initialDataLength;
+ }
+ free(initialData);
+ }
+
+ // USB reads greater than 16K don't work
+ char buffer1[16384], buffer2[16384];
+ mRequestIn1->buffer = buffer1;
+ mRequestIn2->buffer = buffer2;
+ struct usb_request* req = mRequestIn1;
+ void* writeBuffer = NULL;
+ int writeLength = 0;
+
+ while (remaining > 0 || writeBuffer) {
+ if (remaining > 0) {
+ // queue up a read request
+ req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
+ if (mData.readDataAsync(req)) {
+ ALOGE("readDataAsync failed");
+ goto fail;
+ }
+ } else {
+ req = NULL;
+ }
+
+ if (writeBuffer) {
+ // write previous buffer
+ if (write(fd, writeBuffer, writeLength) != writeLength) {
+ ALOGE("write failed");
+ // wait for pending read before failing
+ if (req)
+ mData.readDataWait(mDevice);
+ goto fail;
+ }
+ writeBuffer = NULL;
+ }
+
+ // wait for read to complete
+ if (req) {
+ int read = mData.readDataWait(mDevice);
+ if (read < 0)
+ goto fail;
+
+ if (read > 0) {
+ writeBuffer = req->buffer;
+ writeLength = read;
+ remaining -= read;
+ req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
+ } else {
+ writeBuffer = NULL;
+ }
+ }
+ }
+
+ MtpResponseCode response = readResponse();
+ if (response == MTP_RESPONSE_OK)
+ result = true;
+ }
+
+fail:
+ ::close(fd);
+ return result;
+}
+
+bool MtpDevice::sendRequest(MtpOperationCode operation) {
+ ALOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
+ mReceivedResponse = false;
+ mRequest.setOperationCode(operation);
+ if (mTransactionID > 0)
+ mRequest.setTransactionID(mTransactionID++);
+ int ret = mRequest.write(mRequestOut);
+ mRequest.dump();
+ return (ret > 0);
+}
+
+bool MtpDevice::sendData() {
+ ALOGV("sendData\n");
+ mData.setOperationCode(mRequest.getOperationCode());
+ mData.setTransactionID(mRequest.getTransactionID());
+ int ret = mData.write(mRequestOut);
+ mData.dump();
+ return (ret > 0);
+}
+
+bool MtpDevice::readData() {
+ mData.reset();
+ int ret = mData.read(mRequestIn1);
+ ALOGV("readData returned %d\n", ret);
+ if (ret >= MTP_CONTAINER_HEADER_SIZE) {
+ if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
+ ALOGD("got response packet instead of data packet");
+ // we got a response packet rather than data
+ // copy it to mResponse
+ mResponse.copyFrom(mData);
+ mReceivedResponse = true;
+ return false;
+ }
+ mData.dump();
+ return true;
+ }
+ else {
+ ALOGV("readResponse failed\n");
+ return false;
+ }
+}
+
+bool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
+ mData.setOperationCode(operation);
+ mData.setTransactionID(mRequest.getTransactionID());
+ return (!mData.writeDataHeader(mRequestOut, dataLength));
+}
+
+MtpResponseCode MtpDevice::readResponse() {
+ ALOGV("readResponse\n");
+ if (mReceivedResponse) {
+ mReceivedResponse = false;
+ return mResponse.getResponseCode();
+ }
+ int ret = mResponse.read(mRequestIn1);
+ // handle zero length packets, which might occur if the data transfer
+ // ends on a packet boundary
+ if (ret == 0)
+ ret = mResponse.read(mRequestIn1);
+ if (ret >= MTP_CONTAINER_HEADER_SIZE) {
+ mResponse.dump();
+ return mResponse.getResponseCode();
+ } else {
+ ALOGD("readResponse failed\n");
+ return -1;
+ }
+}
+
+} // namespace android
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
new file mode 100644
index 0000000..b69203e
--- /dev/null
+++ b/media/mtp/MtpDevice.h
@@ -0,0 +1,116 @@
+/*
+ * 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 _MTP_DEVICE_H
+#define _MTP_DEVICE_H
+
+#include "MtpRequestPacket.h"
+#include "MtpDataPacket.h"
+#include "MtpResponsePacket.h"
+#include "MtpTypes.h"
+
+#include <utils/threads.h>
+
+struct usb_device;
+struct usb_request;
+struct usb_endpoint_descriptor;
+
+namespace android {
+
+class MtpDeviceInfo;
+class MtpObjectInfo;
+class MtpStorageInfo;
+
+class MtpDevice {
+private:
+ struct usb_device* mDevice;
+ int mInterface;
+ struct usb_request* mRequestIn1;
+ struct usb_request* mRequestIn2;
+ struct usb_request* mRequestOut;
+ struct usb_request* mRequestIntr;
+ MtpDeviceInfo* mDeviceInfo;
+ MtpPropertyList mDeviceProperties;
+
+ // current session ID
+ MtpSessionID mSessionID;
+ // current transaction ID
+ MtpTransactionID mTransactionID;
+
+ MtpRequestPacket mRequest;
+ MtpDataPacket mData;
+ MtpResponsePacket mResponse;
+ // set to true if we received a response packet instead of a data packet
+ bool mReceivedResponse;
+
+ // to ensure only one MTP transaction at a time
+ Mutex mMutex;
+
+public:
+ MtpDevice(struct usb_device* device, int interface,
+ const struct usb_endpoint_descriptor *ep_in,
+ const struct usb_endpoint_descriptor *ep_out,
+ const struct usb_endpoint_descriptor *ep_intr);
+
+ static MtpDevice* open(const char* deviceName, int fd);
+
+ virtual ~MtpDevice();
+
+ void initialize();
+ void close();
+ void print();
+ const char* getDeviceName();
+
+ bool openSession();
+ bool closeSession();
+
+ MtpDeviceInfo* getDeviceInfo();
+ MtpStorageIDList* getStorageIDs();
+ MtpStorageInfo* getStorageInfo(MtpStorageID storageID);
+ MtpObjectHandleList* getObjectHandles(MtpStorageID storageID, MtpObjectFormat format,
+ MtpObjectHandle parent);
+ MtpObjectInfo* getObjectInfo(MtpObjectHandle handle);
+ void* getThumbnail(MtpObjectHandle handle, int& outLength);
+ MtpObjectHandle sendObjectInfo(MtpObjectInfo* info);
+ bool sendObject(MtpObjectInfo* info, int srcFD);
+ bool deleteObject(MtpObjectHandle handle);
+ MtpObjectHandle getParent(MtpObjectHandle handle);
+ MtpObjectHandle getStorageID(MtpObjectHandle handle);
+
+ MtpObjectPropertyList* getObjectPropsSupported(MtpObjectFormat format);
+
+ MtpProperty* getDevicePropDesc(MtpDeviceProperty code);
+ MtpProperty* getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format);
+
+ bool readObject(MtpObjectHandle handle,
+ bool (* callback)(void* data, int offset,
+ int length, void* clientData),
+ int objectSize, void* clientData);
+ bool readObject(MtpObjectHandle handle, const char* destPath, int group,
+ int perm);
+
+private:
+ bool sendRequest(MtpOperationCode operation);
+ bool sendData();
+ bool readData();
+ bool writeDataHeader(MtpOperationCode operation, int dataLength);
+ MtpResponseCode readResponse();
+
+};
+
+}; // namespace android
+
+#endif // _MTP_DEVICE_H
diff --git a/media/mtp/MtpDeviceInfo.cpp b/media/mtp/MtpDeviceInfo.cpp
new file mode 100644
index 0000000..108e2b8
--- /dev/null
+++ b/media/mtp/MtpDeviceInfo.cpp
@@ -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.
+ */
+
+#define LOG_TAG "MtpDeviceInfo"
+
+#include "MtpDebug.h"
+#include "MtpDataPacket.h"
+#include "MtpDeviceInfo.h"
+#include "MtpStringBuffer.h"
+
+namespace android {
+
+MtpDeviceInfo::MtpDeviceInfo()
+ : mStandardVersion(0),
+ mVendorExtensionID(0),
+ mVendorExtensionVersion(0),
+ mVendorExtensionDesc(NULL),
+ mFunctionalCode(0),
+ mOperations(NULL),
+ mEvents(NULL),
+ mDeviceProperties(NULL),
+ mCaptureFormats(NULL),
+ mPlaybackFormats(NULL),
+ mManufacturer(NULL),
+ mModel(NULL),
+ mVersion(NULL),
+ mSerial(NULL)
+{
+}
+
+MtpDeviceInfo::~MtpDeviceInfo() {
+ if (mVendorExtensionDesc)
+ free(mVendorExtensionDesc);
+ delete mOperations;
+ delete mEvents;
+ delete mDeviceProperties;
+ delete mCaptureFormats;
+ delete mPlaybackFormats;
+ if (mManufacturer)
+ free(mManufacturer);
+ if (mModel)
+ free(mModel);
+ if (mVersion)
+ free(mVersion);
+ if (mSerial)
+ free(mSerial);
+}
+
+void MtpDeviceInfo::read(MtpDataPacket& packet) {
+ MtpStringBuffer string;
+
+ // read the device info
+ mStandardVersion = packet.getUInt16();
+ mVendorExtensionID = packet.getUInt32();
+ mVendorExtensionVersion = packet.getUInt16();
+
+ packet.getString(string);
+ mVendorExtensionDesc = strdup((const char *)string);
+
+ mFunctionalCode = packet.getUInt16();
+ mOperations = packet.getAUInt16();
+ mEvents = packet.getAUInt16();
+ mDeviceProperties = packet.getAUInt16();
+ mCaptureFormats = packet.getAUInt16();
+ mPlaybackFormats = packet.getAUInt16();
+
+ packet.getString(string);
+ mManufacturer = strdup((const char *)string);
+ packet.getString(string);
+ mModel = strdup((const char *)string);
+ packet.getString(string);
+ mVersion = strdup((const char *)string);
+ packet.getString(string);
+ mSerial = strdup((const char *)string);
+}
+
+void MtpDeviceInfo::print() {
+ ALOGV("Device Info:\n\tmStandardVersion: %d\n\tmVendorExtensionID: %d\n\tmVendorExtensionVersiony: %d\n",
+ mStandardVersion, mVendorExtensionID, mVendorExtensionVersion);
+ ALOGV("\tmVendorExtensionDesc: %s\n\tmFunctionalCode: %d\n\tmManufacturer: %s\n\tmModel: %s\n\tmVersion: %s\n\tmSerial: %s\n",
+ mVendorExtensionDesc, mFunctionalCode, mManufacturer, mModel, mVersion, mSerial);
+}
+
+} // namespace android
diff --git a/media/mtp/MtpDeviceInfo.h b/media/mtp/MtpDeviceInfo.h
new file mode 100644
index 0000000..2abaa10
--- /dev/null
+++ b/media/mtp/MtpDeviceInfo.h
@@ -0,0 +1,54 @@
+/*
+ * 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 _MTP_DEVICE_INFO_H
+#define _MTP_DEVICE_INFO_H
+
+struct stat;
+
+namespace android {
+
+class MtpDataPacket;
+
+class MtpDeviceInfo {
+public:
+ uint16_t mStandardVersion;
+ uint32_t mVendorExtensionID;
+ uint16_t mVendorExtensionVersion;
+ char* mVendorExtensionDesc;
+ uint16_t mFunctionalCode;
+ UInt16List* mOperations;
+ UInt16List* mEvents;
+ MtpDevicePropertyList* mDeviceProperties;
+ MtpObjectFormatList* mCaptureFormats;
+ MtpObjectFormatList* mPlaybackFormats;
+ char* mManufacturer;
+ char* mModel;
+ char* mVersion;
+ char* mSerial;
+
+public:
+ MtpDeviceInfo();
+ virtual ~MtpDeviceInfo();
+
+ void read(MtpDataPacket& packet);
+
+ void print();
+};
+
+}; // namespace android
+
+#endif // _MTP_DEVICE_INFO_H
diff --git a/media/mtp/MtpEventPacket.cpp b/media/mtp/MtpEventPacket.cpp
new file mode 100644
index 0000000..d2fca42
--- /dev/null
+++ b/media/mtp/MtpEventPacket.cpp
@@ -0,0 +1,70 @@
+/*
+ * 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 "MtpEventPacket"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#ifdef MTP_DEVICE
+#include <linux/usb/f_mtp.h>
+#endif
+
+#include "MtpEventPacket.h"
+
+#include <usbhost/usbhost.h>
+
+namespace android {
+
+MtpEventPacket::MtpEventPacket()
+ : MtpPacket(512)
+{
+}
+
+MtpEventPacket::~MtpEventPacket() {
+}
+
+#ifdef MTP_DEVICE
+int MtpEventPacket::write(int fd) {
+ struct mtp_event event;
+
+ putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
+ putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_EVENT);
+
+ event.data = mBuffer;
+ event.length = mPacketSize;
+ int ret = ::ioctl(fd, MTP_SEND_EVENT, (unsigned long)&event);
+ return (ret < 0 ? ret : 0);
+}
+#endif
+
+#ifdef MTP_HOST
+int MtpEventPacket::read(struct usb_request *request) {
+ request->buffer = mBuffer;
+ request->buffer_length = mBufferSize;
+ int ret = transfer(request);
+ if (ret >= 0)
+ mPacketSize = ret;
+ else
+ mPacketSize = 0;
+ return ret;
+}
+#endif
+
+} // namespace android
+
diff --git a/media/mtp/MtpEventPacket.h b/media/mtp/MtpEventPacket.h
new file mode 100644
index 0000000..660baad
--- /dev/null
+++ b/media/mtp/MtpEventPacket.h
@@ -0,0 +1,48 @@
+/*
+ * 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 _MTP_EVENT_PACKET_H
+#define _MTP_EVENT_PACKET_H
+
+#include "MtpPacket.h"
+#include "mtp.h"
+
+namespace android {
+
+class MtpEventPacket : public MtpPacket {
+
+public:
+ MtpEventPacket();
+ virtual ~MtpEventPacket();
+
+#ifdef MTP_DEVICE
+ // write our data to the given file descriptor
+ int write(int fd);
+#endif
+
+#ifdef MTP_HOST
+ // read our buffer with the given request
+ int read(struct usb_request *request);
+#endif
+
+ inline MtpEventCode getEventCode() const { return getContainerCode(); }
+ inline void setEventCode(MtpEventCode code)
+ { return setContainerCode(code); }
+};
+
+}; // namespace android
+
+#endif // _MTP_EVENT_PACKET_H
diff --git a/media/mtp/MtpObjectInfo.cpp b/media/mtp/MtpObjectInfo.cpp
new file mode 100644
index 0000000..cd15343
--- /dev/null
+++ b/media/mtp/MtpObjectInfo.cpp
@@ -0,0 +1,108 @@
+/*
+ * 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 "MtpObjectInfo"
+
+#include "MtpDebug.h"
+#include "MtpDataPacket.h"
+#include "MtpObjectInfo.h"
+#include "MtpStringBuffer.h"
+#include "MtpUtils.h"
+
+namespace android {
+
+MtpObjectInfo::MtpObjectInfo(MtpObjectHandle handle)
+ : mHandle(handle),
+ mStorageID(0),
+ mFormat(0),
+ mProtectionStatus(0),
+ mCompressedSize(0),
+ mThumbFormat(0),
+ mThumbCompressedSize(0),
+ mThumbPixWidth(0),
+ mThumbPixHeight(0),
+ mImagePixWidth(0),
+ mImagePixHeight(0),
+ mImagePixDepth(0),
+ mParent(0),
+ mAssociationType(0),
+ mAssociationDesc(0),
+ mSequenceNumber(0),
+ mName(NULL),
+ mDateCreated(0),
+ mDateModified(0),
+ mKeywords(NULL)
+{
+}
+
+MtpObjectInfo::~MtpObjectInfo() {
+ if (mName)
+ free(mName);
+ if (mKeywords)
+ free(mKeywords);
+}
+
+void MtpObjectInfo::read(MtpDataPacket& packet) {
+ MtpStringBuffer string;
+ time_t time;
+
+ mStorageID = packet.getUInt32();
+ mFormat = packet.getUInt16();
+ mProtectionStatus = packet.getUInt16();
+ mCompressedSize = packet.getUInt32();
+ mThumbFormat = packet.getUInt16();
+ mThumbCompressedSize = packet.getUInt32();
+ mThumbPixWidth = packet.getUInt32();
+ mThumbPixHeight = packet.getUInt32();
+ mImagePixWidth = packet.getUInt32();
+ mImagePixHeight = packet.getUInt32();
+ mImagePixDepth = packet.getUInt32();
+ mParent = packet.getUInt32();
+ mAssociationType = packet.getUInt16();
+ mAssociationDesc = packet.getUInt32();
+ mSequenceNumber = packet.getUInt32();
+
+ packet.getString(string);
+ mName = strdup((const char *)string);
+
+ packet.getString(string);
+ if (parseDateTime((const char*)string, time))
+ mDateCreated = time;
+
+ packet.getString(string);
+ if (parseDateTime((const char*)string, time))
+ mDateModified = time;
+
+ packet.getString(string);
+ mKeywords = strdup((const char *)string);
+}
+
+void MtpObjectInfo::print() {
+ ALOGD("MtpObject Info %08X: %s\n", mHandle, mName);
+ ALOGD(" mStorageID: %08X mFormat: %04X mProtectionStatus: %d\n",
+ mStorageID, mFormat, mProtectionStatus);
+ ALOGD(" mCompressedSize: %d mThumbFormat: %04X mThumbCompressedSize: %d\n",
+ mCompressedSize, mFormat, mThumbCompressedSize);
+ ALOGD(" mThumbPixWidth: %d mThumbPixHeight: %d\n", mThumbPixWidth, mThumbPixHeight);
+ ALOGD(" mImagePixWidth: %d mImagePixHeight: %d mImagePixDepth: %d\n",
+ mImagePixWidth, mImagePixHeight, mImagePixDepth);
+ ALOGD(" mParent: %08X mAssociationType: %04X mAssociationDesc: %04X\n",
+ mParent, mAssociationType, mAssociationDesc);
+ ALOGD(" mSequenceNumber: %d mDateCreated: %ld mDateModified: %ld mKeywords: %s\n",
+ mSequenceNumber, mDateCreated, mDateModified, mKeywords);
+}
+
+} // namespace android
diff --git a/media/mtp/MtpObjectInfo.h b/media/mtp/MtpObjectInfo.h
new file mode 100644
index 0000000..c7a449c
--- /dev/null
+++ b/media/mtp/MtpObjectInfo.h
@@ -0,0 +1,60 @@
+/*
+ * 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 _MTP_OBJECT_INFO_H
+#define _MTP_OBJECT_INFO_H
+
+#include "MtpTypes.h"
+
+namespace android {
+
+class MtpDataPacket;
+
+class MtpObjectInfo {
+public:
+ MtpObjectHandle mHandle;
+ MtpStorageID mStorageID;
+ MtpObjectFormat mFormat;
+ uint16_t mProtectionStatus;
+ uint32_t mCompressedSize;
+ MtpObjectFormat mThumbFormat;
+ uint32_t mThumbCompressedSize;
+ uint32_t mThumbPixWidth;
+ uint32_t mThumbPixHeight;
+ uint32_t mImagePixWidth;
+ uint32_t mImagePixHeight;
+ uint32_t mImagePixDepth;
+ MtpObjectHandle mParent;
+ uint16_t mAssociationType;
+ uint32_t mAssociationDesc;
+ uint32_t mSequenceNumber;
+ char* mName;
+ time_t mDateCreated;
+ time_t mDateModified;
+ char* mKeywords;
+
+public:
+ MtpObjectInfo(MtpObjectHandle handle);
+ virtual ~MtpObjectInfo();
+
+ void read(MtpDataPacket& packet);
+
+ void print();
+};
+
+}; // namespace android
+
+#endif // _MTP_OBJECT_INFO_H
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
new file mode 100644
index 0000000..dd07843
--- /dev/null
+++ b/media/mtp/MtpPacket.cpp
@@ -0,0 +1,166 @@
+/*
+ * 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 "MtpPacket"
+
+#include "MtpDebug.h"
+#include "MtpPacket.h"
+#include "mtp.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <usbhost/usbhost.h>
+
+namespace android {
+
+MtpPacket::MtpPacket(int bufferSize)
+ : mBuffer(NULL),
+ mBufferSize(bufferSize),
+ mAllocationIncrement(bufferSize),
+ mPacketSize(0)
+{
+ mBuffer = (uint8_t *)malloc(bufferSize);
+ if (!mBuffer) {
+ ALOGE("out of memory!");
+ abort();
+ }
+}
+
+MtpPacket::~MtpPacket() {
+ if (mBuffer)
+ free(mBuffer);
+}
+
+void MtpPacket::reset() {
+ allocate(MTP_CONTAINER_HEADER_SIZE);
+ mPacketSize = MTP_CONTAINER_HEADER_SIZE;
+ memset(mBuffer, 0, mBufferSize);
+}
+
+void MtpPacket::allocate(int length) {
+ if (length > mBufferSize) {
+ int newLength = length + mAllocationIncrement;
+ mBuffer = (uint8_t *)realloc(mBuffer, newLength);
+ if (!mBuffer) {
+ ALOGE("out of memory!");
+ abort();
+ }
+ mBufferSize = newLength;
+ }
+}
+
+void MtpPacket::dump() {
+#define DUMP_BYTES_PER_ROW 16
+ char buffer[500];
+ char* bufptr = buffer;
+
+ for (int i = 0; i < mPacketSize; i++) {
+ sprintf(bufptr, "%02X ", mBuffer[i]);
+ bufptr += strlen(bufptr);
+ if (i % DUMP_BYTES_PER_ROW == (DUMP_BYTES_PER_ROW - 1)) {
+ ALOGV("%s", buffer);
+ bufptr = buffer;
+ }
+ }
+ if (bufptr != buffer) {
+ // print last line
+ ALOGV("%s", buffer);
+ }
+ ALOGV("\n");
+}
+
+void MtpPacket::copyFrom(const MtpPacket& src) {
+ int length = src.mPacketSize;
+ allocate(length);
+ mPacketSize = length;
+ memcpy(mBuffer, src.mBuffer, length);
+}
+
+uint16_t MtpPacket::getUInt16(int offset) const {
+ return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
+}
+
+uint32_t MtpPacket::getUInt32(int offset) const {
+ return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
+ ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset];
+}
+
+void MtpPacket::putUInt16(int offset, uint16_t value) {
+ mBuffer[offset++] = (uint8_t)(value & 0xFF);
+ mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
+}
+
+void MtpPacket::putUInt32(int offset, uint32_t value) {
+ mBuffer[offset++] = (uint8_t)(value & 0xFF);
+ mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
+ mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
+ mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
+}
+
+uint16_t MtpPacket::getContainerCode() const {
+ return getUInt16(MTP_CONTAINER_CODE_OFFSET);
+}
+
+void MtpPacket::setContainerCode(uint16_t code) {
+ putUInt16(MTP_CONTAINER_CODE_OFFSET, code);
+}
+
+uint16_t MtpPacket::getContainerType() const {
+ return getUInt16(MTP_CONTAINER_TYPE_OFFSET);
+}
+
+MtpTransactionID MtpPacket::getTransactionID() const {
+ return getUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET);
+}
+
+void MtpPacket::setTransactionID(MtpTransactionID id) {
+ putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id);
+}
+
+uint32_t MtpPacket::getParameter(int index) const {
+ if (index < 1 || index > 5) {
+ ALOGE("index %d out of range in MtpPacket::getParameter", index);
+ return 0;
+ }
+ return getUInt32(MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t));
+}
+
+void MtpPacket::setParameter(int index, uint32_t value) {
+ if (index < 1 || index > 5) {
+ ALOGE("index %d out of range in MtpPacket::setParameter", index);
+ return;
+ }
+ int offset = MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t);
+ if (mPacketSize < offset + sizeof(uint32_t))
+ mPacketSize = offset + sizeof(uint32_t);
+ putUInt32(offset, value);
+}
+
+#ifdef MTP_HOST
+int MtpPacket::transfer(struct usb_request* request) {
+ int result = usb_device_bulk_transfer(request->dev,
+ request->endpoint,
+ request->buffer,
+ request->buffer_length,
+ 0);
+ request->actual_length = result;
+ return result;
+}
+#endif
+
+} // namespace android
diff --git a/media/mtp/MtpPacket.h b/media/mtp/MtpPacket.h
new file mode 100644
index 0000000..0ffb1d3
--- /dev/null
+++ b/media/mtp/MtpPacket.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 _MTP_PACKET_H
+#define _MTP_PACKET_H
+
+#include "MtpTypes.h"
+
+struct usb_request;
+
+namespace android {
+
+class MtpPacket {
+
+protected:
+ uint8_t* mBuffer;
+ // current size of the buffer
+ int mBufferSize;
+ // number of bytes to add when resizing the buffer
+ int mAllocationIncrement;
+ // size of the data in the packet
+ int mPacketSize;
+
+public:
+ MtpPacket(int bufferSize);
+ virtual ~MtpPacket();
+
+ // sets packet size to the default container size and sets buffer to zero
+ virtual void reset();
+
+ void allocate(int length);
+ void dump();
+ void copyFrom(const MtpPacket& src);
+
+ uint16_t getContainerCode() const;
+ void setContainerCode(uint16_t code);
+
+ uint16_t getContainerType() const;
+
+ MtpTransactionID getTransactionID() const;
+ void setTransactionID(MtpTransactionID id);
+
+ uint32_t getParameter(int index) const;
+ void setParameter(int index, uint32_t value);
+
+#ifdef MTP_HOST
+ int transfer(struct usb_request* request);
+#endif
+
+protected:
+ uint16_t getUInt16(int offset) const;
+ uint32_t getUInt32(int offset) const;
+ void putUInt16(int offset, uint16_t value);
+ void putUInt32(int offset, uint32_t value);
+};
+
+}; // namespace android
+
+#endif // _MTP_PACKET_H
diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp
new file mode 100644
index 0000000..64dd45b
--- /dev/null
+++ b/media/mtp/MtpProperty.cpp
@@ -0,0 +1,534 @@
+/*
+ * 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 "MtpProperty"
+
+#include "MtpDataPacket.h"
+#include "MtpDebug.h"
+#include "MtpProperty.h"
+#include "MtpStringBuffer.h"
+#include "MtpUtils.h"
+
+namespace android {
+
+MtpProperty::MtpProperty()
+ : mCode(0),
+ mType(0),
+ mWriteable(false),
+ mDefaultArrayLength(0),
+ mDefaultArrayValues(NULL),
+ mCurrentArrayLength(0),
+ mCurrentArrayValues(NULL),
+ mGroupCode(0),
+ mFormFlag(kFormNone),
+ mEnumLength(0),
+ mEnumValues(NULL)
+{
+ memset(&mDefaultValue, 0, sizeof(mDefaultValue));
+ memset(&mCurrentValue, 0, sizeof(mCurrentValue));
+ memset(&mMinimumValue, 0, sizeof(mMinimumValue));
+ memset(&mMaximumValue, 0, sizeof(mMaximumValue));
+}
+
+MtpProperty::MtpProperty(MtpPropertyCode propCode,
+ MtpDataType type,
+ bool writeable,
+ int defaultValue)
+ : mCode(propCode),
+ mType(type),
+ mWriteable(writeable),
+ mDefaultArrayLength(0),
+ mDefaultArrayValues(NULL),
+ mCurrentArrayLength(0),
+ mCurrentArrayValues(NULL),
+ mGroupCode(0),
+ mFormFlag(kFormNone),
+ mEnumLength(0),
+ mEnumValues(NULL)
+{
+ memset(&mDefaultValue, 0, sizeof(mDefaultValue));
+ memset(&mCurrentValue, 0, sizeof(mCurrentValue));
+ memset(&mMinimumValue, 0, sizeof(mMinimumValue));
+ memset(&mMaximumValue, 0, sizeof(mMaximumValue));
+
+ if (defaultValue) {
+ switch (type) {
+ case MTP_TYPE_INT8:
+ mDefaultValue.u.i8 = defaultValue;
+ break;
+ case MTP_TYPE_UINT8:
+ mDefaultValue.u.u8 = defaultValue;
+ break;
+ case MTP_TYPE_INT16:
+ mDefaultValue.u.i16 = defaultValue;
+ break;
+ case MTP_TYPE_UINT16:
+ mDefaultValue.u.u16 = defaultValue;
+ break;
+ case MTP_TYPE_INT32:
+ mDefaultValue.u.i32 = defaultValue;
+ break;
+ case MTP_TYPE_UINT32:
+ mDefaultValue.u.u32 = defaultValue;
+ break;
+ case MTP_TYPE_INT64:
+ mDefaultValue.u.i64 = defaultValue;
+ break;
+ case MTP_TYPE_UINT64:
+ mDefaultValue.u.u64 = defaultValue;
+ break;
+ default:
+ ALOGE("unknown type %04X in MtpProperty::MtpProperty", type);
+ }
+ }
+}
+
+MtpProperty::~MtpProperty() {
+ if (mType == MTP_TYPE_STR) {
+ // free all strings
+ free(mDefaultValue.str);
+ free(mCurrentValue.str);
+ free(mMinimumValue.str);
+ free(mMaximumValue.str);
+ if (mDefaultArrayValues) {
+ for (int i = 0; i < mDefaultArrayLength; i++)
+ free(mDefaultArrayValues[i].str);
+ }
+ if (mCurrentArrayValues) {
+ for (int i = 0; i < mCurrentArrayLength; i++)
+ free(mCurrentArrayValues[i].str);
+ }
+ if (mEnumValues) {
+ for (int i = 0; i < mEnumLength; i++)
+ free(mEnumValues[i].str);
+ }
+ }
+ delete[] mDefaultArrayValues;
+ delete[] mCurrentArrayValues;
+ delete[] mEnumValues;
+}
+
+void MtpProperty::read(MtpDataPacket& packet) {
+ mCode = packet.getUInt16();
+ bool deviceProp = isDeviceProperty();
+ mType = packet.getUInt16();
+ mWriteable = (packet.getUInt8() == 1);
+ switch (mType) {
+ case MTP_TYPE_AINT8:
+ case MTP_TYPE_AUINT8:
+ case MTP_TYPE_AINT16:
+ case MTP_TYPE_AUINT16:
+ case MTP_TYPE_AINT32:
+ case MTP_TYPE_AUINT32:
+ case MTP_TYPE_AINT64:
+ case MTP_TYPE_AUINT64:
+ case MTP_TYPE_AINT128:
+ case MTP_TYPE_AUINT128:
+ mDefaultArrayValues = readArrayValues(packet, mDefaultArrayLength);
+ if (deviceProp)
+ mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);
+ break;
+ default:
+ readValue(packet, mDefaultValue);
+ if (deviceProp)
+ readValue(packet, mCurrentValue);
+ }
+ if (!deviceProp)
+ mGroupCode = packet.getUInt32();
+ mFormFlag = packet.getUInt8();
+
+ if (mFormFlag == kFormRange) {
+ readValue(packet, mMinimumValue);
+ readValue(packet, mMaximumValue);
+ readValue(packet, mStepSize);
+ } else if (mFormFlag == kFormEnum) {
+ mEnumLength = packet.getUInt16();
+ mEnumValues = new MtpPropertyValue[mEnumLength];
+ for (int i = 0; i < mEnumLength; i++)
+ readValue(packet, mEnumValues[i]);
+ }
+}
+
+void MtpProperty::write(MtpDataPacket& packet) {
+ bool deviceProp = isDeviceProperty();
+
+ packet.putUInt16(mCode);
+ packet.putUInt16(mType);
+ packet.putUInt8(mWriteable ? 1 : 0);
+
+ switch (mType) {
+ case MTP_TYPE_AINT8:
+ case MTP_TYPE_AUINT8:
+ case MTP_TYPE_AINT16:
+ case MTP_TYPE_AUINT16:
+ case MTP_TYPE_AINT32:
+ case MTP_TYPE_AUINT32:
+ case MTP_TYPE_AINT64:
+ case MTP_TYPE_AUINT64:
+ case MTP_TYPE_AINT128:
+ case MTP_TYPE_AUINT128:
+ writeArrayValues(packet, mDefaultArrayValues, mDefaultArrayLength);
+ if (deviceProp)
+ writeArrayValues(packet, mCurrentArrayValues, mCurrentArrayLength);
+ break;
+ default:
+ writeValue(packet, mDefaultValue);
+ if (deviceProp)
+ writeValue(packet, mCurrentValue);
+ }
+ packet.putUInt32(mGroupCode);
+ if (!deviceProp)
+ packet.putUInt8(mFormFlag);
+ if (mFormFlag == kFormRange) {
+ writeValue(packet, mMinimumValue);
+ writeValue(packet, mMaximumValue);
+ writeValue(packet, mStepSize);
+ } else if (mFormFlag == kFormEnum) {
+ packet.putUInt16(mEnumLength);
+ for (int i = 0; i < mEnumLength; i++)
+ writeValue(packet, mEnumValues[i]);
+ }
+}
+
+void MtpProperty::setDefaultValue(const uint16_t* string) {
+ free(mDefaultValue.str);
+ if (string) {
+ MtpStringBuffer buffer(string);
+ mDefaultValue.str = strdup(buffer);
+ }
+ else
+ mDefaultValue.str = NULL;
+}
+
+void MtpProperty::setCurrentValue(const uint16_t* string) {
+ free(mCurrentValue.str);
+ if (string) {
+ MtpStringBuffer buffer(string);
+ mCurrentValue.str = strdup(buffer);
+ }
+ else
+ mCurrentValue.str = NULL;
+}
+
+void MtpProperty::setFormRange(int min, int max, int step) {
+ mFormFlag = kFormRange;
+ switch (mType) {
+ case MTP_TYPE_INT8:
+ mMinimumValue.u.i8 = min;
+ mMaximumValue.u.i8 = max;
+ mStepSize.u.i8 = step;
+ break;
+ case MTP_TYPE_UINT8:
+ mMinimumValue.u.u8 = min;
+ mMaximumValue.u.u8 = max;
+ mStepSize.u.u8 = step;
+ break;
+ case MTP_TYPE_INT16:
+ mMinimumValue.u.i16 = min;
+ mMaximumValue.u.i16 = max;
+ mStepSize.u.i16 = step;
+ break;
+ case MTP_TYPE_UINT16:
+ mMinimumValue.u.u16 = min;
+ mMaximumValue.u.u16 = max;
+ mStepSize.u.u16 = step;
+ break;
+ case MTP_TYPE_INT32:
+ mMinimumValue.u.i32 = min;
+ mMaximumValue.u.i32 = max;
+ mStepSize.u.i32 = step;
+ break;
+ case MTP_TYPE_UINT32:
+ mMinimumValue.u.u32 = min;
+ mMaximumValue.u.u32 = max;
+ mStepSize.u.u32 = step;
+ break;
+ case MTP_TYPE_INT64:
+ mMinimumValue.u.i64 = min;
+ mMaximumValue.u.i64 = max;
+ mStepSize.u.i64 = step;
+ break;
+ case MTP_TYPE_UINT64:
+ mMinimumValue.u.u64 = min;
+ mMaximumValue.u.u64 = max;
+ mStepSize.u.u64 = step;
+ break;
+ default:
+ ALOGE("unsupported type for MtpProperty::setRange");
+ break;
+ }
+}
+
+void MtpProperty::setFormEnum(const int* values, int count) {
+ mFormFlag = kFormEnum;
+ delete[] mEnumValues;
+ mEnumValues = new MtpPropertyValue[count];
+ mEnumLength = count;
+
+ for (int i = 0; i < count; i++) {
+ int value = *values++;
+ switch (mType) {
+ case MTP_TYPE_INT8:
+ mEnumValues[i].u.i8 = value;
+ break;
+ case MTP_TYPE_UINT8:
+ mEnumValues[i].u.u8 = value;
+ break;
+ case MTP_TYPE_INT16:
+ mEnumValues[i].u.i16 = value;
+ break;
+ case MTP_TYPE_UINT16:
+ mEnumValues[i].u.u16 = value;
+ break;
+ case MTP_TYPE_INT32:
+ mEnumValues[i].u.i32 = value;
+ break;
+ case MTP_TYPE_UINT32:
+ mEnumValues[i].u.u32 = value;
+ break;
+ case MTP_TYPE_INT64:
+ mEnumValues[i].u.i64 = value;
+ break;
+ case MTP_TYPE_UINT64:
+ mEnumValues[i].u.u64 = value;
+ break;
+ default:
+ ALOGE("unsupported type for MtpProperty::setEnum");
+ break;
+ }
+ }
+}
+
+void MtpProperty::setFormDateTime() {
+ mFormFlag = kFormDateTime;
+}
+
+void MtpProperty::print() {
+ MtpString buffer;
+ bool deviceProp = isDeviceProperty();
+ if (deviceProp)
+ ALOGI(" %s (%04X)", MtpDebug::getDevicePropCodeName(mCode), mCode);
+ else
+ ALOGI(" %s (%04X)", MtpDebug::getObjectPropCodeName(mCode), mCode);
+ ALOGI(" type %04X", mType);
+ ALOGI(" writeable %s", (mWriteable ? "true" : "false"));
+ buffer = " default value: ";
+ print(mDefaultValue, buffer);
+ ALOGI("%s", (const char *)buffer);
+ if (deviceProp) {
+ buffer = " current value: ";
+ print(mCurrentValue, buffer);
+ ALOGI("%s", (const char *)buffer);
+ }
+ switch (mFormFlag) {
+ case kFormNone:
+ break;
+ case kFormRange:
+ buffer = " Range (";
+ print(mMinimumValue, buffer);
+ buffer += ", ";
+ print(mMaximumValue, buffer);
+ buffer += ", ";
+ print(mStepSize, buffer);
+ buffer += ")";
+ ALOGI("%s", (const char *)buffer);
+ break;
+ case kFormEnum:
+ buffer = " Enum { ";
+ for (int i = 0; i < mEnumLength; i++) {
+ print(mEnumValues[i], buffer);
+ buffer += " ";
+ }
+ buffer += "}";
+ ALOGI("%s", (const char *)buffer);
+ break;
+ case kFormDateTime:
+ ALOGI(" DateTime\n");
+ break;
+ default:
+ ALOGI(" form %d\n", mFormFlag);
+ break;
+ }
+}
+
+void MtpProperty::print(MtpPropertyValue& value, MtpString& buffer) {
+ switch (mType) {
+ case MTP_TYPE_INT8:
+ buffer.appendFormat("%d", value.u.i8);
+ break;
+ case MTP_TYPE_UINT8:
+ buffer.appendFormat("%d", value.u.u8);
+ break;
+ case MTP_TYPE_INT16:
+ buffer.appendFormat("%d", value.u.i16);
+ break;
+ case MTP_TYPE_UINT16:
+ buffer.appendFormat("%d", value.u.u16);
+ break;
+ case MTP_TYPE_INT32:
+ buffer.appendFormat("%d", value.u.i32);
+ break;
+ case MTP_TYPE_UINT32:
+ buffer.appendFormat("%d", value.u.u32);
+ break;
+ case MTP_TYPE_INT64:
+ buffer.appendFormat("%lld", value.u.i64);
+ break;
+ case MTP_TYPE_UINT64:
+ buffer.appendFormat("%lld", value.u.u64);
+ break;
+ case MTP_TYPE_INT128:
+ buffer.appendFormat("%08X%08X%08X%08X", value.u.i128[0], value.u.i128[1],
+ value.u.i128[2], value.u.i128[3]);
+ break;
+ case MTP_TYPE_UINT128:
+ buffer.appendFormat("%08X%08X%08X%08X", value.u.u128[0], value.u.u128[1],
+ value.u.u128[2], value.u.u128[3]);
+ break;
+ case MTP_TYPE_STR:
+ buffer.appendFormat("%s", value.str);
+ break;
+ default:
+ ALOGE("unsupported type for MtpProperty::print\n");
+ break;
+ }
+}
+
+void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
+ MtpStringBuffer stringBuffer;
+
+ switch (mType) {
+ case MTP_TYPE_INT8:
+ case MTP_TYPE_AINT8:
+ value.u.i8 = packet.getInt8();
+ break;
+ case MTP_TYPE_UINT8:
+ case MTP_TYPE_AUINT8:
+ value.u.u8 = packet.getUInt8();
+ break;
+ case MTP_TYPE_INT16:
+ case MTP_TYPE_AINT16:
+ value.u.i16 = packet.getInt16();
+ break;
+ case MTP_TYPE_UINT16:
+ case MTP_TYPE_AUINT16:
+ value.u.u16 = packet.getUInt16();
+ break;
+ case MTP_TYPE_INT32:
+ case MTP_TYPE_AINT32:
+ value.u.i32 = packet.getInt32();
+ break;
+ case MTP_TYPE_UINT32:
+ case MTP_TYPE_AUINT32:
+ value.u.u32 = packet.getUInt32();
+ break;
+ case MTP_TYPE_INT64:
+ case MTP_TYPE_AINT64:
+ value.u.i64 = packet.getInt64();
+ break;
+ case MTP_TYPE_UINT64:
+ case MTP_TYPE_AUINT64:
+ value.u.u64 = packet.getUInt64();
+ break;
+ case MTP_TYPE_INT128:
+ case MTP_TYPE_AINT128:
+ packet.getInt128(value.u.i128);
+ break;
+ case MTP_TYPE_UINT128:
+ case MTP_TYPE_AUINT128:
+ packet.getUInt128(value.u.u128);
+ break;
+ case MTP_TYPE_STR:
+ packet.getString(stringBuffer);
+ value.str = strdup(stringBuffer);
+ break;
+ default:
+ ALOGE("unknown type %04X in MtpProperty::readValue", mType);
+ }
+}
+
+void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) {
+ MtpStringBuffer stringBuffer;
+
+ switch (mType) {
+ case MTP_TYPE_INT8:
+ case MTP_TYPE_AINT8:
+ packet.putInt8(value.u.i8);
+ break;
+ case MTP_TYPE_UINT8:
+ case MTP_TYPE_AUINT8:
+ packet.putUInt8(value.u.u8);
+ break;
+ case MTP_TYPE_INT16:
+ case MTP_TYPE_AINT16:
+ packet.putInt16(value.u.i16);
+ break;
+ case MTP_TYPE_UINT16:
+ case MTP_TYPE_AUINT16:
+ packet.putUInt16(value.u.u16);
+ break;
+ case MTP_TYPE_INT32:
+ case MTP_TYPE_AINT32:
+ packet.putInt32(value.u.i32);
+ break;
+ case MTP_TYPE_UINT32:
+ case MTP_TYPE_AUINT32:
+ packet.putUInt32(value.u.u32);
+ break;
+ case MTP_TYPE_INT64:
+ case MTP_TYPE_AINT64:
+ packet.putInt64(value.u.i64);
+ break;
+ case MTP_TYPE_UINT64:
+ case MTP_TYPE_AUINT64:
+ packet.putUInt64(value.u.u64);
+ break;
+ case MTP_TYPE_INT128:
+ case MTP_TYPE_AINT128:
+ packet.putInt128(value.u.i128);
+ break;
+ case MTP_TYPE_UINT128:
+ case MTP_TYPE_AUINT128:
+ packet.putUInt128(value.u.u128);
+ break;
+ case MTP_TYPE_STR:
+ if (value.str)
+ packet.putString(value.str);
+ else
+ packet.putEmptyString();
+ break;
+ default:
+ ALOGE("unknown type %04X in MtpProperty::writeValue", mType);
+ }
+}
+
+MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, int& length) {
+ length = packet.getUInt32();
+ if (length == 0)
+ return NULL;
+ MtpPropertyValue* result = new MtpPropertyValue[length];
+ for (int i = 0; i < length; i++)
+ readValue(packet, result[i]);
+ return result;
+}
+
+void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, int length) {
+ packet.putUInt32(length);
+ for (int i = 0; i < length; i++)
+ writeValue(packet, values[i]);
+}
+
+} // namespace android
diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h
new file mode 100644
index 0000000..06ca56e
--- /dev/null
+++ b/media/mtp/MtpProperty.h
@@ -0,0 +1,114 @@
+/*
+ * 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 _MTP_PROPERTY_H
+#define _MTP_PROPERTY_H
+
+#include "MtpTypes.h"
+
+namespace android {
+
+class MtpDataPacket;
+
+struct MtpPropertyValue {
+ union {
+ int8_t i8;
+ uint8_t u8;
+ int16_t i16;
+ uint16_t u16;
+ int32_t i32;
+ uint32_t u32;
+ int64_t i64;
+ uint64_t u64;
+ int128_t i128;
+ uint128_t u128;
+ } u;
+ // string in UTF8 format
+ char* str;
+};
+
+class MtpProperty {
+public:
+ MtpPropertyCode mCode;
+ MtpDataType mType;
+ bool mWriteable;
+ MtpPropertyValue mDefaultValue;
+ MtpPropertyValue mCurrentValue;
+
+ // for array types
+ int mDefaultArrayLength;
+ MtpPropertyValue* mDefaultArrayValues;
+ int mCurrentArrayLength;
+ MtpPropertyValue* mCurrentArrayValues;
+
+ enum {
+ kFormNone = 0,
+ kFormRange = 1,
+ kFormEnum = 2,
+ kFormDateTime = 3,
+ };
+
+ uint32_t mGroupCode;
+ uint8_t mFormFlag;
+
+ // for range form
+ MtpPropertyValue mMinimumValue;
+ MtpPropertyValue mMaximumValue;
+ MtpPropertyValue mStepSize;
+
+ // for enum form
+ int mEnumLength;
+ MtpPropertyValue* mEnumValues;
+
+public:
+ MtpProperty();
+ MtpProperty(MtpPropertyCode propCode,
+ MtpDataType type,
+ bool writeable = false,
+ int defaultValue = 0);
+ virtual ~MtpProperty();
+
+ inline MtpPropertyCode getPropertyCode() const { return mCode; }
+
+ void read(MtpDataPacket& packet);
+ void write(MtpDataPacket& packet);
+
+ void setDefaultValue(const uint16_t* string);
+ void setCurrentValue(const uint16_t* string);
+
+ void setFormRange(int min, int max, int step);
+ void setFormEnum(const int* values, int count);
+ void setFormDateTime();
+
+ void print();
+ void print(MtpPropertyValue& value, MtpString& buffer);
+
+ inline bool isDeviceProperty() const {
+ return ( ((mCode & 0xF000) == 0x5000)
+ || ((mCode & 0xF800) == 0xD000));
+ }
+
+private:
+ void readValue(MtpDataPacket& packet, MtpPropertyValue& value);
+ void writeValue(MtpDataPacket& packet, MtpPropertyValue& value);
+ MtpPropertyValue* readArrayValues(MtpDataPacket& packet, int& length);
+ void writeArrayValues(MtpDataPacket& packet,
+ MtpPropertyValue* values, int length);
+};
+
+}; // namespace android
+
+#endif // _MTP_PROPERTY_H
diff --git a/media/mtp/MtpRequestPacket.cpp b/media/mtp/MtpRequestPacket.cpp
new file mode 100644
index 0000000..0e58e01
--- /dev/null
+++ b/media/mtp/MtpRequestPacket.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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 "MtpRequestPacket"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "MtpRequestPacket.h"
+
+#include <usbhost/usbhost.h>
+
+namespace android {
+
+MtpRequestPacket::MtpRequestPacket()
+ : MtpPacket(512)
+{
+}
+
+MtpRequestPacket::~MtpRequestPacket() {
+}
+
+#ifdef MTP_DEVICE
+int MtpRequestPacket::read(int fd) {
+ int ret = ::read(fd, mBuffer, mBufferSize);
+ if (ret >= 0)
+ mPacketSize = ret;
+ else
+ mPacketSize = 0;
+ return ret;
+}
+#endif
+
+#ifdef MTP_HOST
+ // write our buffer to the given endpoint (host mode)
+int MtpRequestPacket::write(struct usb_request *request)
+{
+ putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
+ putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_COMMAND);
+ request->buffer = mBuffer;
+ request->buffer_length = mPacketSize;
+ return transfer(request);
+}
+#endif
+
+} // namespace android
diff --git a/media/mtp/MtpRequestPacket.h b/media/mtp/MtpRequestPacket.h
new file mode 100644
index 0000000..1201f11
--- /dev/null
+++ b/media/mtp/MtpRequestPacket.h
@@ -0,0 +1,50 @@
+/*
+ * 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 _MTP_REQUEST_PACKET_H
+#define _MTP_REQUEST_PACKET_H
+
+#include "MtpPacket.h"
+#include "mtp.h"
+
+struct usb_request;
+
+namespace android {
+
+class MtpRequestPacket : public MtpPacket {
+
+public:
+ MtpRequestPacket();
+ virtual ~MtpRequestPacket();
+
+#ifdef MTP_DEVICE
+ // fill our buffer with data from the given file descriptor
+ int read(int fd);
+#endif
+
+#ifdef MTP_HOST
+ // write our buffer to the given endpoint
+ int write(struct usb_request *request);
+#endif
+
+ inline MtpOperationCode getOperationCode() const { return getContainerCode(); }
+ inline void setOperationCode(MtpOperationCode code)
+ { return setContainerCode(code); }
+};
+
+}; // namespace android
+
+#endif // _MTP_REQUEST_PACKET_H
diff --git a/media/mtp/MtpResponsePacket.cpp b/media/mtp/MtpResponsePacket.cpp
new file mode 100644
index 0000000..c2b41e4
--- /dev/null
+++ b/media/mtp/MtpResponsePacket.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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 "MtpResponsePacket"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "MtpResponsePacket.h"
+
+#include <usbhost/usbhost.h>
+
+namespace android {
+
+MtpResponsePacket::MtpResponsePacket()
+ : MtpPacket(512)
+{
+}
+
+MtpResponsePacket::~MtpResponsePacket() {
+}
+
+#ifdef MTP_DEVICE
+int MtpResponsePacket::write(int fd) {
+ putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
+ putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_RESPONSE);
+ int ret = ::write(fd, mBuffer, mPacketSize);
+ return (ret < 0 ? ret : 0);
+}
+#endif
+
+#ifdef MTP_HOST
+int MtpResponsePacket::read(struct usb_request *request) {
+ request->buffer = mBuffer;
+ request->buffer_length = mBufferSize;
+ int ret = transfer(request);
+ if (ret >= 0)
+ mPacketSize = ret;
+ else
+ mPacketSize = 0;
+ return ret;
+}
+#endif
+
+} // namespace android
+
diff --git a/media/mtp/MtpResponsePacket.h b/media/mtp/MtpResponsePacket.h
new file mode 100644
index 0000000..592ad4a
--- /dev/null
+++ b/media/mtp/MtpResponsePacket.h
@@ -0,0 +1,48 @@
+/*
+ * 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 _MTP_RESPONSE_PACKET_H
+#define _MTP_RESPONSE_PACKET_H
+
+#include "MtpPacket.h"
+#include "mtp.h"
+
+namespace android {
+
+class MtpResponsePacket : public MtpPacket {
+
+public:
+ MtpResponsePacket();
+ virtual ~MtpResponsePacket();
+
+#ifdef MTP_DEVICE
+ // write our data to the given file descriptor
+ int write(int fd);
+#endif
+
+#ifdef MTP_HOST
+ // read our buffer with the given request
+ int read(struct usb_request *request);
+#endif
+
+ inline MtpResponseCode getResponseCode() const { return getContainerCode(); }
+ inline void setResponseCode(MtpResponseCode code)
+ { return setContainerCode(code); }
+};
+
+}; // namespace android
+
+#endif // _MTP_RESPONSE_PACKET_H
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
new file mode 100644
index 0000000..5606187
--- /dev/null
+++ b/media/mtp/MtpServer.cpp
@@ -0,0 +1,1210 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include <cutils/properties.h>
+
+#define LOG_TAG "MtpServer"
+
+#include "MtpDebug.h"
+#include "MtpDatabase.h"
+#include "MtpObjectInfo.h"
+#include "MtpProperty.h"
+#include "MtpServer.h"
+#include "MtpStorage.h"
+#include "MtpStringBuffer.h"
+
+#include <linux/usb/f_mtp.h>
+
+namespace android {
+
+static const MtpOperationCode kSupportedOperationCodes[] = {
+ MTP_OPERATION_GET_DEVICE_INFO,
+ MTP_OPERATION_OPEN_SESSION,
+ MTP_OPERATION_CLOSE_SESSION,
+ MTP_OPERATION_GET_STORAGE_IDS,
+ MTP_OPERATION_GET_STORAGE_INFO,
+ MTP_OPERATION_GET_NUM_OBJECTS,
+ MTP_OPERATION_GET_OBJECT_HANDLES,
+ MTP_OPERATION_GET_OBJECT_INFO,
+ MTP_OPERATION_GET_OBJECT,
+ MTP_OPERATION_GET_THUMB,
+ MTP_OPERATION_DELETE_OBJECT,
+ MTP_OPERATION_SEND_OBJECT_INFO,
+ MTP_OPERATION_SEND_OBJECT,
+// MTP_OPERATION_INITIATE_CAPTURE,
+// MTP_OPERATION_FORMAT_STORE,
+// MTP_OPERATION_RESET_DEVICE,
+// MTP_OPERATION_SELF_TEST,
+// MTP_OPERATION_SET_OBJECT_PROTECTION,
+// MTP_OPERATION_POWER_DOWN,
+ MTP_OPERATION_GET_DEVICE_PROP_DESC,
+ MTP_OPERATION_GET_DEVICE_PROP_VALUE,
+ MTP_OPERATION_SET_DEVICE_PROP_VALUE,
+ MTP_OPERATION_RESET_DEVICE_PROP_VALUE,
+// MTP_OPERATION_TERMINATE_OPEN_CAPTURE,
+// MTP_OPERATION_MOVE_OBJECT,
+// MTP_OPERATION_COPY_OBJECT,
+ MTP_OPERATION_GET_PARTIAL_OBJECT,
+// MTP_OPERATION_INITIATE_OPEN_CAPTURE,
+ MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED,
+ MTP_OPERATION_GET_OBJECT_PROP_DESC,
+ MTP_OPERATION_GET_OBJECT_PROP_VALUE,
+ MTP_OPERATION_SET_OBJECT_PROP_VALUE,
+ MTP_OPERATION_GET_OBJECT_PROP_LIST,
+// MTP_OPERATION_SET_OBJECT_PROP_LIST,
+// MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC,
+// MTP_OPERATION_SEND_OBJECT_PROP_LIST,
+ MTP_OPERATION_GET_OBJECT_REFERENCES,
+ MTP_OPERATION_SET_OBJECT_REFERENCES,
+// MTP_OPERATION_SKIP,
+ // Android extension for direct file IO
+ MTP_OPERATION_GET_PARTIAL_OBJECT_64,
+ MTP_OPERATION_SEND_PARTIAL_OBJECT,
+ MTP_OPERATION_TRUNCATE_OBJECT,
+ MTP_OPERATION_BEGIN_EDIT_OBJECT,
+ MTP_OPERATION_END_EDIT_OBJECT,
+};
+
+static const MtpEventCode kSupportedEventCodes[] = {
+ MTP_EVENT_OBJECT_ADDED,
+ MTP_EVENT_OBJECT_REMOVED,
+ MTP_EVENT_STORE_ADDED,
+ MTP_EVENT_STORE_REMOVED,
+};
+
+MtpServer::MtpServer(int fd, MtpDatabase* database, bool ptp,
+ int fileGroup, int filePerm, int directoryPerm)
+ : mFD(fd),
+ mDatabase(database),
+ mPtp(ptp),
+ mFileGroup(fileGroup),
+ mFilePermission(filePerm),
+ mDirectoryPermission(directoryPerm),
+ mSessionID(0),
+ mSessionOpen(false),
+ mSendObjectHandle(kInvalidObjectHandle),
+ mSendObjectFormat(0),
+ mSendObjectFileSize(0)
+{
+}
+
+MtpServer::~MtpServer() {
+}
+
+void MtpServer::addStorage(MtpStorage* storage) {
+ Mutex::Autolock autoLock(mMutex);
+
+ mStorages.push(storage);
+ sendStoreAdded(storage->getStorageID());
+}
+
+void MtpServer::removeStorage(MtpStorage* storage) {
+ Mutex::Autolock autoLock(mMutex);
+
+ for (int i = 0; i < mStorages.size(); i++) {
+ if (mStorages[i] == storage) {
+ mStorages.removeAt(i);
+ sendStoreRemoved(storage->getStorageID());
+ break;
+ }
+ }
+}
+
+MtpStorage* MtpServer::getStorage(MtpStorageID id) {
+ if (id == 0)
+ return mStorages[0];
+ for (int i = 0; i < mStorages.size(); i++) {
+ MtpStorage* storage = mStorages[i];
+ if (storage->getStorageID() == id)
+ return storage;
+ }
+ return NULL;
+}
+
+bool MtpServer::hasStorage(MtpStorageID id) {
+ if (id == 0 || id == 0xFFFFFFFF)
+ return mStorages.size() > 0;
+ return (getStorage(id) != NULL);
+}
+
+void MtpServer::run() {
+ int fd = mFD;
+
+ ALOGV("MtpServer::run fd: %d\n", fd);
+
+ while (1) {
+ int ret = mRequest.read(fd);
+ if (ret < 0) {
+ ALOGV("request read returned %d, errno: %d", ret, errno);
+ if (errno == ECANCELED) {
+ // return to top of loop and wait for next command
+ continue;
+ }
+ break;
+ }
+ MtpOperationCode operation = mRequest.getOperationCode();
+ MtpTransactionID transaction = mRequest.getTransactionID();
+
+ ALOGV("operation: %s", MtpDebug::getOperationCodeName(operation));
+ mRequest.dump();
+
+ // FIXME need to generalize this
+ bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO
+ || operation == MTP_OPERATION_SET_OBJECT_REFERENCES
+ || operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE
+ || operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE);
+ if (dataIn) {
+ int ret = mData.read(fd);
+ if (ret < 0) {
+ ALOGE("data read returned %d, errno: %d", ret, errno);
+ if (errno == ECANCELED) {
+ // return to top of loop and wait for next command
+ continue;
+ }
+ break;
+ }
+ ALOGV("received data:");
+ mData.dump();
+ } else {
+ mData.reset();
+ }
+
+ if (handleRequest()) {
+ if (!dataIn && mData.hasData()) {
+ mData.setOperationCode(operation);
+ mData.setTransactionID(transaction);
+ ALOGV("sending data:");
+ mData.dump();
+ ret = mData.write(fd);
+ if (ret < 0) {
+ ALOGE("request write returned %d, errno: %d", ret, errno);
+ if (errno == ECANCELED) {
+ // return to top of loop and wait for next command
+ continue;
+ }
+ break;
+ }
+ }
+
+ mResponse.setTransactionID(transaction);
+ ALOGV("sending response %04X", mResponse.getResponseCode());
+ ret = mResponse.write(fd);
+ mResponse.dump();
+ if (ret < 0) {
+ ALOGE("request write returned %d, errno: %d", ret, errno);
+ if (errno == ECANCELED) {
+ // return to top of loop and wait for next command
+ continue;
+ }
+ break;
+ }
+ } else {
+ ALOGV("skipping response\n");
+ }
+ }
+
+ // commit any open edits
+ int count = mObjectEditList.size();
+ for (int i = 0; i < count; i++) {
+ ObjectEdit* edit = mObjectEditList[i];
+ commitEdit(edit);
+ delete edit;
+ }
+ mObjectEditList.clear();
+
+ if (mSessionOpen)
+ mDatabase->sessionEnded();
+ close(fd);
+ mFD = -1;
+}
+
+void MtpServer::sendObjectAdded(MtpObjectHandle handle) {
+ ALOGV("sendObjectAdded %d\n", handle);
+ sendEvent(MTP_EVENT_OBJECT_ADDED, handle);
+}
+
+void MtpServer::sendObjectRemoved(MtpObjectHandle handle) {
+ ALOGV("sendObjectRemoved %d\n", handle);
+ sendEvent(MTP_EVENT_OBJECT_REMOVED, handle);
+}
+
+void MtpServer::sendStoreAdded(MtpStorageID id) {
+ ALOGV("sendStoreAdded %08X\n", id);
+ sendEvent(MTP_EVENT_STORE_ADDED, id);
+}
+
+void MtpServer::sendStoreRemoved(MtpStorageID id) {
+ ALOGV("sendStoreRemoved %08X\n", id);
+ sendEvent(MTP_EVENT_STORE_REMOVED, id);
+}
+
+void MtpServer::sendEvent(MtpEventCode code, uint32_t param1) {
+ if (mSessionOpen) {
+ mEvent.setEventCode(code);
+ mEvent.setTransactionID(mRequest.getTransactionID());
+ mEvent.setParameter(1, param1);
+ int ret = mEvent.write(mFD);
+ ALOGV("mEvent.write returned %d\n", ret);
+ }
+}
+
+void MtpServer::addEditObject(MtpObjectHandle handle, MtpString& path,
+ uint64_t size, MtpObjectFormat format, int fd) {
+ ObjectEdit* edit = new ObjectEdit(handle, path, size, format, fd);
+ mObjectEditList.add(edit);
+}
+
+MtpServer::ObjectEdit* MtpServer::getEditObject(MtpObjectHandle handle) {
+ int count = mObjectEditList.size();
+ for (int i = 0; i < count; i++) {
+ ObjectEdit* edit = mObjectEditList[i];
+ if (edit->mHandle == handle) return edit;
+ }
+ return NULL;
+}
+
+void MtpServer::removeEditObject(MtpObjectHandle handle) {
+ int count = mObjectEditList.size();
+ for (int i = 0; i < count; i++) {
+ ObjectEdit* edit = mObjectEditList[i];
+ if (edit->mHandle == handle) {
+ delete edit;
+ mObjectEditList.removeAt(i);
+ return;
+ }
+ }
+ ALOGE("ObjectEdit not found in removeEditObject");
+}
+
+void MtpServer::commitEdit(ObjectEdit* edit) {
+ mDatabase->endSendObject((const char *)edit->mPath, edit->mHandle, edit->mFormat, true);
+}
+
+
+bool MtpServer::handleRequest() {
+ Mutex::Autolock autoLock(mMutex);
+
+ MtpOperationCode operation = mRequest.getOperationCode();
+ MtpResponseCode response;
+
+ mResponse.reset();
+
+ if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) {
+ // FIXME - need to delete mSendObjectHandle from the database
+ ALOGE("expected SendObject after SendObjectInfo");
+ mSendObjectHandle = kInvalidObjectHandle;
+ }
+
+ switch (operation) {
+ case MTP_OPERATION_GET_DEVICE_INFO:
+ response = doGetDeviceInfo();
+ break;
+ case MTP_OPERATION_OPEN_SESSION:
+ response = doOpenSession();
+ break;
+ case MTP_OPERATION_CLOSE_SESSION:
+ response = doCloseSession();
+ break;
+ case MTP_OPERATION_GET_STORAGE_IDS:
+ response = doGetStorageIDs();
+ break;
+ case MTP_OPERATION_GET_STORAGE_INFO:
+ response = doGetStorageInfo();
+ break;
+ case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED:
+ response = doGetObjectPropsSupported();
+ break;
+ case MTP_OPERATION_GET_OBJECT_HANDLES:
+ response = doGetObjectHandles();
+ break;
+ case MTP_OPERATION_GET_NUM_OBJECTS:
+ response = doGetNumObjects();
+ break;
+ case MTP_OPERATION_GET_OBJECT_REFERENCES:
+ response = doGetObjectReferences();
+ break;
+ case MTP_OPERATION_SET_OBJECT_REFERENCES:
+ response = doSetObjectReferences();
+ break;
+ case MTP_OPERATION_GET_OBJECT_PROP_VALUE:
+ response = doGetObjectPropValue();
+ break;
+ case MTP_OPERATION_SET_OBJECT_PROP_VALUE:
+ response = doSetObjectPropValue();
+ break;
+ case MTP_OPERATION_GET_DEVICE_PROP_VALUE:
+ response = doGetDevicePropValue();
+ break;
+ case MTP_OPERATION_SET_DEVICE_PROP_VALUE:
+ response = doSetDevicePropValue();
+ break;
+ case MTP_OPERATION_RESET_DEVICE_PROP_VALUE:
+ response = doResetDevicePropValue();
+ break;
+ case MTP_OPERATION_GET_OBJECT_PROP_LIST:
+ response = doGetObjectPropList();
+ break;
+ case MTP_OPERATION_GET_OBJECT_INFO:
+ response = doGetObjectInfo();
+ break;
+ case MTP_OPERATION_GET_OBJECT:
+ response = doGetObject();
+ break;
+ case MTP_OPERATION_GET_THUMB:
+ response = doGetThumb();
+ break;
+ case MTP_OPERATION_GET_PARTIAL_OBJECT:
+ case MTP_OPERATION_GET_PARTIAL_OBJECT_64:
+ response = doGetPartialObject(operation);
+ break;
+ case MTP_OPERATION_SEND_OBJECT_INFO:
+ response = doSendObjectInfo();
+ break;
+ case MTP_OPERATION_SEND_OBJECT:
+ response = doSendObject();
+ break;
+ case MTP_OPERATION_DELETE_OBJECT:
+ response = doDeleteObject();
+ break;
+ case MTP_OPERATION_GET_OBJECT_PROP_DESC:
+ response = doGetObjectPropDesc();
+ break;
+ case MTP_OPERATION_GET_DEVICE_PROP_DESC:
+ response = doGetDevicePropDesc();
+ break;
+ case MTP_OPERATION_SEND_PARTIAL_OBJECT:
+ response = doSendPartialObject();
+ break;
+ case MTP_OPERATION_TRUNCATE_OBJECT:
+ response = doTruncateObject();
+ break;
+ case MTP_OPERATION_BEGIN_EDIT_OBJECT:
+ response = doBeginEditObject();
+ break;
+ case MTP_OPERATION_END_EDIT_OBJECT:
+ response = doEndEditObject();
+ break;
+ default:
+ ALOGE("got unsupported command %s", MtpDebug::getOperationCodeName(operation));
+ response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
+ break;
+ }
+
+ if (response == MTP_RESPONSE_TRANSACTION_CANCELLED)
+ return false;
+ mResponse.setResponseCode(response);
+ return true;
+}
+
+MtpResponseCode MtpServer::doGetDeviceInfo() {
+ MtpStringBuffer string;
+ char prop_value[PROPERTY_VALUE_MAX];
+
+ MtpObjectFormatList* playbackFormats = mDatabase->getSupportedPlaybackFormats();
+ MtpObjectFormatList* captureFormats = mDatabase->getSupportedCaptureFormats();
+ MtpDevicePropertyList* deviceProperties = mDatabase->getSupportedDeviceProperties();
+
+ // fill in device info
+ mData.putUInt16(MTP_STANDARD_VERSION);
+ if (mPtp) {
+ mData.putUInt32(0);
+ } else {
+ // MTP Vendor Extension ID
+ mData.putUInt32(6);
+ }
+ mData.putUInt16(MTP_STANDARD_VERSION);
+ if (mPtp) {
+ // no extensions
+ string.set("");
+ } else {
+ // MTP extensions
+ string.set("microsoft.com: 1.0; android.com: 1.0;");
+ }
+ mData.putString(string); // MTP Extensions
+ mData.putUInt16(0); //Functional Mode
+ mData.putAUInt16(kSupportedOperationCodes,
+ sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported
+ mData.putAUInt16(kSupportedEventCodes,
+ sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported
+ mData.putAUInt16(deviceProperties); // Device Properties Supported
+ mData.putAUInt16(captureFormats); // Capture Formats
+ mData.putAUInt16(playbackFormats); // Playback Formats
+
+ property_get("ro.product.manufacturer", prop_value, "unknown manufacturer");
+ string.set(prop_value);
+ mData.putString(string); // Manufacturer
+
+ property_get("ro.product.model", prop_value, "MTP Device");
+ string.set(prop_value);
+ mData.putString(string); // Model
+ string.set("1.0");
+ mData.putString(string); // Device Version
+
+ property_get("ro.serialno", prop_value, "????????");
+ string.set(prop_value);
+ mData.putString(string); // Serial Number
+
+ delete playbackFormats;
+ delete captureFormats;
+ delete deviceProperties;
+
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doOpenSession() {
+ if (mSessionOpen) {
+ mResponse.setParameter(1, mSessionID);
+ return MTP_RESPONSE_SESSION_ALREADY_OPEN;
+ }
+ mSessionID = mRequest.getParameter(1);
+ mSessionOpen = true;
+
+ mDatabase->sessionStarted();
+
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doCloseSession() {
+ if (!mSessionOpen)
+ return MTP_RESPONSE_SESSION_NOT_OPEN;
+ mSessionID = 0;
+ mSessionOpen = false;
+ mDatabase->sessionEnded();
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doGetStorageIDs() {
+ if (!mSessionOpen)
+ return MTP_RESPONSE_SESSION_NOT_OPEN;
+
+ int count = mStorages.size();
+ mData.putUInt32(count);
+ for (int i = 0; i < count; i++)
+ mData.putUInt32(mStorages[i]->getStorageID());
+
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doGetStorageInfo() {
+ MtpStringBuffer string;
+
+ if (!mSessionOpen)
+ return MTP_RESPONSE_SESSION_NOT_OPEN;
+ MtpStorageID id = mRequest.getParameter(1);
+ MtpStorage* storage = getStorage(id);
+ if (!storage)
+ return MTP_RESPONSE_INVALID_STORAGE_ID;
+
+ mData.putUInt16(storage->getType());
+ mData.putUInt16(storage->getFileSystemType());
+ mData.putUInt16(storage->getAccessCapability());
+ mData.putUInt64(storage->getMaxCapacity());
+ mData.putUInt64(storage->getFreeSpace());
+ mData.putUInt32(1024*1024*1024); // Free Space in Objects
+ string.set(storage->getDescription());
+ mData.putString(string);
+ mData.putEmptyString(); // Volume Identifier
+
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doGetObjectPropsSupported() {
+ if (!mSessionOpen)
+ return MTP_RESPONSE_SESSION_NOT_OPEN;
+ MtpObjectFormat format = mRequest.getParameter(1);
+ MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format);
+ mData.putAUInt16(properties);
+ delete properties;
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doGetObjectHandles() {
+ if (!mSessionOpen)
+ return MTP_RESPONSE_SESSION_NOT_OPEN;
+ MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage
+ MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats
+ MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent
+ // 0x00000000 for all objects
+
+ if (!hasStorage(storageID))
+ return MTP_RESPONSE_INVALID_STORAGE_ID;
+
+ MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent);
+ mData.putAUInt32(handles);
+ delete handles;
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doGetNumObjects() {
+ if (!mSessionOpen)
+ return MTP_RESPONSE_SESSION_NOT_OPEN;
+ MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage
+ MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats
+ MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent
+ // 0x00000000 for all objects
+ if (!hasStorage(storageID))
+ return MTP_RESPONSE_INVALID_STORAGE_ID;
+
+ int count = mDatabase->getNumObjects(storageID, format, parent);
+ if (count >= 0) {
+ mResponse.setParameter(1, count);
+ return MTP_RESPONSE_OK;
+ } else {
+ mResponse.setParameter(1, 0);
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ }
+}
+
+MtpResponseCode MtpServer::doGetObjectReferences() {
+ if (!mSessionOpen)
+ return MTP_RESPONSE_SESSION_NOT_OPEN;
+ if (!hasStorage())
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ MtpObjectHandle handle = mRequest.getParameter(1);
+
+ // FIXME - check for invalid object handle
+ MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle);
+ if (handles) {
+ mData.putAUInt32(handles);
+ delete handles;
+ } else {
+ mData.putEmptyArray();
+ }
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doSetObjectReferences() {
+ if (!mSessionOpen)
+ return MTP_RESPONSE_SESSION_NOT_OPEN;
+ if (!hasStorage())
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ MtpStorageID handle = mRequest.getParameter(1);
+
+ MtpObjectHandleList* references = mData.getAUInt32();
+ MtpResponseCode result = mDatabase->setObjectReferences(handle, references);
+ delete references;
+ return result;
+}
+
+MtpResponseCode MtpServer::doGetObjectPropValue() {
+ if (!hasStorage())
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ MtpObjectProperty property = mRequest.getParameter(2);
+ ALOGV("GetObjectPropValue %d %s\n", handle,
+ MtpDebug::getObjectPropCodeName(property));
+
+ return mDatabase->getObjectPropertyValue(handle, property, mData);
+}
+
+MtpResponseCode MtpServer::doSetObjectPropValue() {
+ if (!hasStorage())
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ MtpObjectProperty property = mRequest.getParameter(2);
+ ALOGV("SetObjectPropValue %d %s\n", handle,
+ MtpDebug::getObjectPropCodeName(property));
+
+ return mDatabase->setObjectPropertyValue(handle, property, mData);
+}
+
+MtpResponseCode MtpServer::doGetDevicePropValue() {
+ MtpDeviceProperty property = mRequest.getParameter(1);
+ ALOGV("GetDevicePropValue %s\n",
+ MtpDebug::getDevicePropCodeName(property));
+
+ return mDatabase->getDevicePropertyValue(property, mData);
+}
+
+MtpResponseCode MtpServer::doSetDevicePropValue() {
+ MtpDeviceProperty property = mRequest.getParameter(1);
+ ALOGV("SetDevicePropValue %s\n",
+ MtpDebug::getDevicePropCodeName(property));
+
+ return mDatabase->setDevicePropertyValue(property, mData);
+}
+
+MtpResponseCode MtpServer::doResetDevicePropValue() {
+ MtpDeviceProperty property = mRequest.getParameter(1);
+ ALOGV("ResetDevicePropValue %s\n",
+ MtpDebug::getDevicePropCodeName(property));
+
+ return mDatabase->resetDeviceProperty(property);
+}
+
+MtpResponseCode MtpServer::doGetObjectPropList() {
+ if (!hasStorage())
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ // use uint32_t so we can support 0xFFFFFFFF
+ uint32_t format = mRequest.getParameter(2);
+ uint32_t property = mRequest.getParameter(3);
+ int groupCode = mRequest.getParameter(4);
+ int depth = mRequest.getParameter(5);
+ ALOGV("GetObjectPropList %d format: %s property: %s group: %d depth: %d\n",
+ handle, MtpDebug::getFormatCodeName(format),
+ MtpDebug::getObjectPropCodeName(property), groupCode, depth);
+
+ return mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData);
+}
+
+MtpResponseCode MtpServer::doGetObjectInfo() {
+ if (!hasStorage())
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ MtpObjectInfo info(handle);
+ MtpResponseCode result = mDatabase->getObjectInfo(handle, info);
+ if (result == MTP_RESPONSE_OK) {
+ char date[20];
+
+ mData.putUInt32(info.mStorageID);
+ mData.putUInt16(info.mFormat);
+ mData.putUInt16(info.mProtectionStatus);
+
+ // if object is being edited the database size may be out of date
+ uint32_t size = info.mCompressedSize;
+ ObjectEdit* edit = getEditObject(handle);
+ if (edit)
+ size = (edit->mSize > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)edit->mSize);
+ mData.putUInt32(size);
+
+ mData.putUInt16(info.mThumbFormat);
+ mData.putUInt32(info.mThumbCompressedSize);
+ mData.putUInt32(info.mThumbPixWidth);
+ mData.putUInt32(info.mThumbPixHeight);
+ mData.putUInt32(info.mImagePixWidth);
+ mData.putUInt32(info.mImagePixHeight);
+ mData.putUInt32(info.mImagePixDepth);
+ mData.putUInt32(info.mParent);
+ mData.putUInt16(info.mAssociationType);
+ mData.putUInt32(info.mAssociationDesc);
+ mData.putUInt32(info.mSequenceNumber);
+ mData.putString(info.mName);
+ mData.putEmptyString(); // date created
+ formatDateTime(info.mDateModified, date, sizeof(date));
+ mData.putString(date); // date modified
+ mData.putEmptyString(); // keywords
+ }
+ return result;
+}
+
+MtpResponseCode MtpServer::doGetObject() {
+ if (!hasStorage())
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ MtpString pathBuf;
+ int64_t fileLength;
+ MtpObjectFormat format;
+ int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format);
+ if (result != MTP_RESPONSE_OK)
+ return result;
+
+ const char* filePath = (const char *)pathBuf;
+ mtp_file_range mfr;
+ mfr.fd = open(filePath, O_RDONLY);
+ if (mfr.fd < 0) {
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+ mfr.offset = 0;
+ mfr.length = fileLength;
+ mfr.command = mRequest.getOperationCode();
+ mfr.transaction_id = mRequest.getTransactionID();
+
+ // then transfer the file
+ int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
+ ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret);
+ close(mfr.fd);
+ if (ret < 0) {
+ if (errno == ECANCELED)
+ return MTP_RESPONSE_TRANSACTION_CANCELLED;
+ else
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doGetThumb() {
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ size_t thumbSize;
+ void* thumb = mDatabase->getThumbnail(handle, thumbSize);
+ if (thumb) {
+ // send data
+ mData.setOperationCode(mRequest.getOperationCode());
+ mData.setTransactionID(mRequest.getTransactionID());
+ mData.writeData(mFD, thumb, thumbSize);
+ free(thumb);
+ return MTP_RESPONSE_OK;
+ } else {
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+}
+
+MtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) {
+ if (!hasStorage())
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ uint64_t offset;
+ uint32_t length;
+ offset = mRequest.getParameter(2);
+ if (operation == MTP_OPERATION_GET_PARTIAL_OBJECT_64) {
+ // android extension with 64 bit offset
+ uint64_t offset2 = mRequest.getParameter(3);
+ offset = offset | (offset2 << 32);
+ length = mRequest.getParameter(4);
+ } else {
+ // standard GetPartialObject
+ length = mRequest.getParameter(3);
+ }
+ MtpString pathBuf;
+ int64_t fileLength;
+ MtpObjectFormat format;
+ int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format);
+ if (result != MTP_RESPONSE_OK)
+ return result;
+ if (offset + length > fileLength)
+ length = fileLength - offset;
+
+ const char* filePath = (const char *)pathBuf;
+ mtp_file_range mfr;
+ mfr.fd = open(filePath, O_RDONLY);
+ if (mfr.fd < 0) {
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+ mfr.offset = offset;
+ mfr.length = length;
+ mfr.command = mRequest.getOperationCode();
+ mfr.transaction_id = mRequest.getTransactionID();
+ mResponse.setParameter(1, length);
+
+ // transfer the file
+ int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
+ ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret);
+ close(mfr.fd);
+ if (ret < 0) {
+ if (errno == ECANCELED)
+ return MTP_RESPONSE_TRANSACTION_CANCELLED;
+ else
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doSendObjectInfo() {
+ MtpString path;
+ MtpStorageID storageID = mRequest.getParameter(1);
+ MtpStorage* storage = getStorage(storageID);
+ MtpObjectHandle parent = mRequest.getParameter(2);
+ if (!storage)
+ return MTP_RESPONSE_INVALID_STORAGE_ID;
+
+ // special case the root
+ if (parent == MTP_PARENT_ROOT) {
+ path = storage->getPath();
+ parent = 0;
+ } else {
+ int64_t length;
+ MtpObjectFormat format;
+ int result = mDatabase->getObjectFilePath(parent, path, length, format);
+ if (result != MTP_RESPONSE_OK)
+ return result;
+ if (format != MTP_FORMAT_ASSOCIATION)
+ return MTP_RESPONSE_INVALID_PARENT_OBJECT;
+ }
+
+ // read only the fields we need
+ mData.getUInt32(); // storage ID
+ MtpObjectFormat format = mData.getUInt16();
+ mData.getUInt16(); // protection status
+ mSendObjectFileSize = mData.getUInt32();
+ mData.getUInt16(); // thumb format
+ mData.getUInt32(); // thumb compressed size
+ mData.getUInt32(); // thumb pix width
+ mData.getUInt32(); // thumb pix height
+ mData.getUInt32(); // image pix width
+ mData.getUInt32(); // image pix height
+ mData.getUInt32(); // image bit depth
+ mData.getUInt32(); // parent
+ uint16_t associationType = mData.getUInt16();
+ uint32_t associationDesc = mData.getUInt32(); // association desc
+ mData.getUInt32(); // sequence number
+ MtpStringBuffer name, created, modified;
+ mData.getString(name); // file name
+ mData.getString(created); // date created
+ mData.getString(modified); // date modified
+ // keywords follow
+
+ ALOGV("name: %s format: %04X\n", (const char *)name, format);
+ time_t modifiedTime;
+ if (!parseDateTime(modified, modifiedTime))
+ modifiedTime = 0;
+
+ if (path[path.size() - 1] != '/')
+ path += "/";
+ path += (const char *)name;
+
+ // check space first
+ if (mSendObjectFileSize > storage->getFreeSpace())
+ return MTP_RESPONSE_STORAGE_FULL;
+ uint64_t maxFileSize = storage->getMaxFileSize();
+ // check storage max file size
+ if (maxFileSize != 0) {
+ // if mSendObjectFileSize is 0xFFFFFFFF, then all we know is the file size
+ // is >= 0xFFFFFFFF
+ if (mSendObjectFileSize > maxFileSize || mSendObjectFileSize == 0xFFFFFFFF)
+ return MTP_RESPONSE_OBJECT_TOO_LARGE;
+ }
+
+ ALOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID);
+ MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path,
+ format, parent, storageID, mSendObjectFileSize, modifiedTime);
+ if (handle == kInvalidObjectHandle) {
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+
+ if (format == MTP_FORMAT_ASSOCIATION) {
+ mode_t mask = umask(0);
+ int ret = mkdir((const char *)path, mDirectoryPermission);
+ umask(mask);
+ if (ret && ret != -EEXIST)
+ return MTP_RESPONSE_GENERAL_ERROR;
+ chown((const char *)path, getuid(), mFileGroup);
+
+ // SendObject does not get sent for directories, so call endSendObject here instead
+ mDatabase->endSendObject(path, handle, MTP_FORMAT_ASSOCIATION, MTP_RESPONSE_OK);
+ } else {
+ mSendObjectFilePath = path;
+ // save the handle for the SendObject call, which should follow
+ mSendObjectHandle = handle;
+ mSendObjectFormat = format;
+ }
+
+ mResponse.setParameter(1, storageID);
+ mResponse.setParameter(2, parent);
+ mResponse.setParameter(3, handle);
+
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doSendObject() {
+ if (!hasStorage())
+ return MTP_RESPONSE_GENERAL_ERROR;
+ MtpResponseCode result = MTP_RESPONSE_OK;
+ mode_t mask;
+ int ret, initialData;
+
+ if (mSendObjectHandle == kInvalidObjectHandle) {
+ ALOGE("Expected SendObjectInfo before SendObject");
+ result = MTP_RESPONSE_NO_VALID_OBJECT_INFO;
+ goto done;
+ }
+
+ // read the header, and possibly some data
+ ret = mData.read(mFD);
+ if (ret < MTP_CONTAINER_HEADER_SIZE) {
+ result = MTP_RESPONSE_GENERAL_ERROR;
+ goto done;
+ }
+ initialData = ret - MTP_CONTAINER_HEADER_SIZE;
+
+ mtp_file_range mfr;
+ mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC);
+ if (mfr.fd < 0) {
+ result = MTP_RESPONSE_GENERAL_ERROR;
+ goto done;
+ }
+ fchown(mfr.fd, getuid(), mFileGroup);
+ // set permissions
+ mask = umask(0);
+ fchmod(mfr.fd, mFilePermission);
+ umask(mask);
+
+ if (initialData > 0)
+ ret = write(mfr.fd, mData.getData(), initialData);
+
+ if (mSendObjectFileSize - initialData > 0) {
+ mfr.offset = initialData;
+ if (mSendObjectFileSize == 0xFFFFFFFF) {
+ // tell driver to read until it receives a short packet
+ mfr.length = 0xFFFFFFFF;
+ } else {
+ mfr.length = mSendObjectFileSize - initialData;
+ }
+
+ ALOGV("receiving %s\n", (const char *)mSendObjectFilePath);
+ // transfer the file
+ ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
+ ALOGV("MTP_RECEIVE_FILE returned %d\n", ret);
+ }
+ close(mfr.fd);
+
+ if (ret < 0) {
+ unlink(mSendObjectFilePath);
+ if (errno == ECANCELED)
+ result = MTP_RESPONSE_TRANSACTION_CANCELLED;
+ else
+ result = MTP_RESPONSE_GENERAL_ERROR;
+ }
+
+done:
+ // reset so we don't attempt to send the data back
+ mData.reset();
+
+ mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat,
+ result == MTP_RESPONSE_OK);
+ mSendObjectHandle = kInvalidObjectHandle;
+ mSendObjectFormat = 0;
+ return result;
+}
+
+static void deleteRecursive(const char* path) {
+ char pathbuf[PATH_MAX];
+ int pathLength = strlen(path);
+ if (pathLength >= sizeof(pathbuf) - 1) {
+ ALOGE("path too long: %s\n", path);
+ }
+ strcpy(pathbuf, path);
+ if (pathbuf[pathLength - 1] != '/') {
+ pathbuf[pathLength++] = '/';
+ }
+ char* fileSpot = pathbuf + pathLength;
+ int pathRemaining = sizeof(pathbuf) - pathLength - 1;
+
+ DIR* dir = opendir(path);
+ if (!dir) {
+ ALOGE("opendir %s failed: %s", path, strerror(errno));
+ return;
+ }
+
+ struct dirent* entry;
+ while ((entry = readdir(dir))) {
+ const char* name = entry->d_name;
+
+ // ignore "." and ".."
+ if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
+ continue;
+ }
+
+ int nameLength = strlen(name);
+ if (nameLength > pathRemaining) {
+ ALOGE("path %s/%s too long\n", path, name);
+ continue;
+ }
+ strcpy(fileSpot, name);
+
+ int type = entry->d_type;
+ if (entry->d_type == DT_DIR) {
+ deleteRecursive(pathbuf);
+ rmdir(pathbuf);
+ } else {
+ unlink(pathbuf);
+ }
+ }
+ closedir(dir);
+}
+
+static void deletePath(const char* path) {
+ struct stat statbuf;
+ if (stat(path, &statbuf) == 0) {
+ if (S_ISDIR(statbuf.st_mode)) {
+ deleteRecursive(path);
+ rmdir(path);
+ } else {
+ unlink(path);
+ }
+ } else {
+ ALOGE("deletePath stat failed for %s: %s", path, strerror(errno));
+ }
+}
+
+MtpResponseCode MtpServer::doDeleteObject() {
+ if (!hasStorage())
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ MtpObjectFormat format = mRequest.getParameter(2);
+ // FIXME - support deleting all objects if handle is 0xFFFFFFFF
+ // FIXME - implement deleting objects by format
+
+ MtpString filePath;
+ int64_t fileLength;
+ int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format);
+ if (result == MTP_RESPONSE_OK) {
+ ALOGV("deleting %s", (const char *)filePath);
+ result = mDatabase->deleteFile(handle);
+ // Don't delete the actual files unless the database deletion is allowed
+ if (result == MTP_RESPONSE_OK) {
+ deletePath((const char *)filePath);
+ }
+ }
+
+ return result;
+}
+
+MtpResponseCode MtpServer::doGetObjectPropDesc() {
+ MtpObjectProperty propCode = mRequest.getParameter(1);
+ MtpObjectFormat format = mRequest.getParameter(2);
+ ALOGV("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode),
+ MtpDebug::getFormatCodeName(format));
+ MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format);
+ if (!property)
+ return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
+ property->write(mData);
+ delete property;
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doGetDevicePropDesc() {
+ MtpDeviceProperty propCode = mRequest.getParameter(1);
+ ALOGV("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode));
+ MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode);
+ if (!property)
+ return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+ property->write(mData);
+ delete property;
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doSendPartialObject() {
+ if (!hasStorage())
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ uint64_t offset = mRequest.getParameter(2);
+ uint64_t offset2 = mRequest.getParameter(3);
+ offset = offset | (offset2 << 32);
+ uint32_t length = mRequest.getParameter(4);
+
+ ObjectEdit* edit = getEditObject(handle);
+ if (!edit) {
+ ALOGE("object not open for edit in doSendPartialObject");
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+
+ // can't start writing past the end of the file
+ if (offset > edit->mSize) {
+ ALOGD("writing past end of object, offset: %lld, edit->mSize: %lld", offset, edit->mSize);
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+
+ const char* filePath = (const char *)edit->mPath;
+ ALOGV("receiving partial %s %lld %lld\n", filePath, offset, length);
+
+ // read the header, and possibly some data
+ int ret = mData.read(mFD);
+ if (ret < MTP_CONTAINER_HEADER_SIZE)
+ return MTP_RESPONSE_GENERAL_ERROR;
+ int initialData = ret - MTP_CONTAINER_HEADER_SIZE;
+
+ if (initialData > 0) {
+ ret = write(edit->mFD, mData.getData(), initialData);
+ offset += initialData;
+ length -= initialData;
+ }
+
+ if (length > 0) {
+ mtp_file_range mfr;
+ mfr.fd = edit->mFD;
+ mfr.offset = offset;
+ mfr.length = length;
+
+ // transfer the file
+ ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
+ ALOGV("MTP_RECEIVE_FILE returned %d", ret);
+ }
+ if (ret < 0) {
+ mResponse.setParameter(1, 0);
+ if (errno == ECANCELED)
+ return MTP_RESPONSE_TRANSACTION_CANCELLED;
+ else
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+
+ // reset so we don't attempt to send this back
+ mData.reset();
+ mResponse.setParameter(1, length);
+ uint64_t end = offset + length;
+ if (end > edit->mSize) {
+ edit->mSize = end;
+ }
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doTruncateObject() {
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ ObjectEdit* edit = getEditObject(handle);
+ if (!edit) {
+ ALOGE("object not open for edit in doTruncateObject");
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+
+ uint64_t offset = mRequest.getParameter(2);
+ uint64_t offset2 = mRequest.getParameter(3);
+ offset |= (offset2 << 32);
+ if (ftruncate(edit->mFD, offset) != 0) {
+ return MTP_RESPONSE_GENERAL_ERROR;
+ } else {
+ edit->mSize = offset;
+ return MTP_RESPONSE_OK;
+ }
+}
+
+MtpResponseCode MtpServer::doBeginEditObject() {
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ if (getEditObject(handle)) {
+ ALOGE("object already open for edit in doBeginEditObject");
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+
+ MtpString path;
+ int64_t fileLength;
+ MtpObjectFormat format;
+ int result = mDatabase->getObjectFilePath(handle, path, fileLength, format);
+ if (result != MTP_RESPONSE_OK)
+ return result;
+
+ int fd = open((const char *)path, O_RDWR | O_EXCL);
+ if (fd < 0) {
+ ALOGE("open failed for %s in doBeginEditObject (%d)", (const char *)path, errno);
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+
+ addEditObject(handle, path, fileLength, format, fd);
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MtpServer::doEndEditObject() {
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ ObjectEdit* edit = getEditObject(handle);
+ if (!edit) {
+ ALOGE("object not open for edit in doEndEditObject");
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+
+ commitEdit(edit);
+ removeEditObject(handle);
+ return MTP_RESPONSE_OK;
+}
+
+} // namespace android
diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h
new file mode 100644
index 0000000..dfa8258
--- /dev/null
+++ b/media/mtp/MtpServer.h
@@ -0,0 +1,154 @@
+/*
+ * 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 _MTP_SERVER_H
+#define _MTP_SERVER_H
+
+#include "MtpRequestPacket.h"
+#include "MtpDataPacket.h"
+#include "MtpResponsePacket.h"
+#include "MtpEventPacket.h"
+#include "mtp.h"
+#include "MtpUtils.h"
+
+#include <utils/threads.h>
+
+namespace android {
+
+class MtpDatabase;
+class MtpStorage;
+
+class MtpServer {
+
+private:
+ // file descriptor for MTP kernel driver
+ int mFD;
+
+ MtpDatabase* mDatabase;
+
+ // appear as a PTP device
+ bool mPtp;
+
+ // group to own new files and folders
+ int mFileGroup;
+ // permissions for new files and directories
+ int mFilePermission;
+ int mDirectoryPermission;
+
+ // current session ID
+ MtpSessionID mSessionID;
+ // true if we have an open session and mSessionID is valid
+ bool mSessionOpen;
+
+ MtpRequestPacket mRequest;
+ MtpDataPacket mData;
+ MtpResponsePacket mResponse;
+ MtpEventPacket mEvent;
+
+ MtpStorageList mStorages;
+
+ // handle for new object, set by SendObjectInfo and used by SendObject
+ MtpObjectHandle mSendObjectHandle;
+ MtpObjectFormat mSendObjectFormat;
+ MtpString mSendObjectFilePath;
+ size_t mSendObjectFileSize;
+
+ Mutex mMutex;
+
+ // represents an MTP object that is being edited using the android extensions
+ // for direct editing (BeginEditObject, SendPartialObject, TruncateObject and EndEditObject)
+ class ObjectEdit {
+ public:
+ MtpObjectHandle mHandle;
+ MtpString mPath;
+ uint64_t mSize;
+ MtpObjectFormat mFormat;
+ int mFD;
+
+ ObjectEdit(MtpObjectHandle handle, const char* path, uint64_t size,
+ MtpObjectFormat format, int fd)
+ : mHandle(handle), mPath(path), mSize(size), mFormat(format), mFD(fd) {
+ }
+
+ virtual ~ObjectEdit() {
+ close(mFD);
+ }
+ };
+ Vector<ObjectEdit*> mObjectEditList;
+
+public:
+ MtpServer(int fd, MtpDatabase* database, bool ptp,
+ int fileGroup, int filePerm, int directoryPerm);
+ virtual ~MtpServer();
+
+ MtpStorage* getStorage(MtpStorageID id);
+ inline bool hasStorage() { return mStorages.size() > 0; }
+ bool hasStorage(MtpStorageID id);
+ void addStorage(MtpStorage* storage);
+ void removeStorage(MtpStorage* storage);
+
+ void run();
+
+ void sendObjectAdded(MtpObjectHandle handle);
+ void sendObjectRemoved(MtpObjectHandle handle);
+
+private:
+ void sendStoreAdded(MtpStorageID id);
+ void sendStoreRemoved(MtpStorageID id);
+ void sendEvent(MtpEventCode code, uint32_t param1);
+
+ void addEditObject(MtpObjectHandle handle, MtpString& path,
+ uint64_t size, MtpObjectFormat format, int fd);
+ ObjectEdit* getEditObject(MtpObjectHandle handle);
+ void removeEditObject(MtpObjectHandle handle);
+ void commitEdit(ObjectEdit* edit);
+
+ bool handleRequest();
+
+ MtpResponseCode doGetDeviceInfo();
+ MtpResponseCode doOpenSession();
+ MtpResponseCode doCloseSession();
+ MtpResponseCode doGetStorageIDs();
+ MtpResponseCode doGetStorageInfo();
+ MtpResponseCode doGetObjectPropsSupported();
+ MtpResponseCode doGetObjectHandles();
+ MtpResponseCode doGetNumObjects();
+ MtpResponseCode doGetObjectReferences();
+ MtpResponseCode doSetObjectReferences();
+ MtpResponseCode doGetObjectPropValue();
+ MtpResponseCode doSetObjectPropValue();
+ MtpResponseCode doGetDevicePropValue();
+ MtpResponseCode doSetDevicePropValue();
+ MtpResponseCode doResetDevicePropValue();
+ MtpResponseCode doGetObjectPropList();
+ MtpResponseCode doGetObjectInfo();
+ MtpResponseCode doGetObject();
+ MtpResponseCode doGetThumb();
+ MtpResponseCode doGetPartialObject(MtpOperationCode operation);
+ MtpResponseCode doSendObjectInfo();
+ MtpResponseCode doSendObject();
+ MtpResponseCode doDeleteObject();
+ MtpResponseCode doGetObjectPropDesc();
+ MtpResponseCode doGetDevicePropDesc();
+ MtpResponseCode doSendPartialObject();
+ MtpResponseCode doTruncateObject();
+ MtpResponseCode doBeginEditObject();
+ MtpResponseCode doEndEditObject();
+};
+
+}; // namespace android
+
+#endif // _MTP_SERVER_H
diff --git a/media/mtp/MtpStorage.cpp b/media/mtp/MtpStorage.cpp
new file mode 100644
index 0000000..d77ca72
--- /dev/null
+++ b/media/mtp/MtpStorage.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 "MtpStorage"
+
+#include "MtpDebug.h"
+#include "MtpDatabase.h"
+#include "MtpStorage.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <limits.h>
+
+namespace android {
+
+MtpStorage::MtpStorage(MtpStorageID id, const char* filePath,
+ const char* description, uint64_t reserveSpace,
+ bool removable, uint64_t maxFileSize)
+ : mStorageID(id),
+ mFilePath(filePath),
+ mDescription(description),
+ mMaxCapacity(0),
+ mMaxFileSize(maxFileSize),
+ mReserveSpace(reserveSpace),
+ mRemovable(removable)
+{
+ ALOGV("MtpStorage id: %d path: %s\n", id, filePath);
+}
+
+MtpStorage::~MtpStorage() {
+}
+
+int MtpStorage::getType() const {
+ return (mRemovable ? MTP_STORAGE_REMOVABLE_RAM : MTP_STORAGE_FIXED_RAM);
+}
+
+int MtpStorage::getFileSystemType() const {
+ return MTP_STORAGE_FILESYSTEM_HIERARCHICAL;
+}
+
+int MtpStorage::getAccessCapability() const {
+ return MTP_STORAGE_READ_WRITE;
+}
+
+uint64_t MtpStorage::getMaxCapacity() {
+ if (mMaxCapacity == 0) {
+ struct statfs stat;
+ if (statfs(getPath(), &stat))
+ return -1;
+ mMaxCapacity = (uint64_t)stat.f_blocks * (uint64_t)stat.f_bsize;
+ }
+ return mMaxCapacity;
+}
+
+uint64_t MtpStorage::getFreeSpace() {
+ struct statfs stat;
+ if (statfs(getPath(), &stat))
+ return -1;
+ uint64_t freeSpace = (uint64_t)stat.f_bavail * (uint64_t)stat.f_bsize;
+ return (freeSpace > mReserveSpace ? freeSpace - mReserveSpace : 0);
+}
+
+const char* MtpStorage::getDescription() const {
+ return (const char *)mDescription;
+}
+
+} // namespace android
diff --git a/media/mtp/MtpStorage.h b/media/mtp/MtpStorage.h
new file mode 100644
index 0000000..e5a2e57
--- /dev/null
+++ b/media/mtp/MtpStorage.h
@@ -0,0 +1,59 @@
+/*
+ * 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 _MTP_STORAGE_H
+#define _MTP_STORAGE_H
+
+#include "MtpTypes.h"
+#include "mtp.h"
+
+namespace android {
+
+class MtpDatabase;
+
+class MtpStorage {
+
+private:
+ MtpStorageID mStorageID;
+ MtpString mFilePath;
+ MtpString mDescription;
+ uint64_t mMaxCapacity;
+ uint64_t mMaxFileSize;
+ // amount of free space to leave unallocated
+ uint64_t mReserveSpace;
+ bool mRemovable;
+
+public:
+ MtpStorage(MtpStorageID id, const char* filePath,
+ const char* description, uint64_t reserveSpace,
+ bool removable, uint64_t maxFileSize);
+ virtual ~MtpStorage();
+
+ inline MtpStorageID getStorageID() const { return mStorageID; }
+ int getType() const;
+ int getFileSystemType() const;
+ int getAccessCapability() const;
+ uint64_t getMaxCapacity();
+ uint64_t getFreeSpace();
+ const char* getDescription() const;
+ inline const char* getPath() const { return (const char *)mFilePath; }
+ inline bool isRemovable() const { return mRemovable; }
+ inline uint64_t getMaxFileSize() const { return mMaxFileSize; }
+};
+
+}; // namespace android
+
+#endif // _MTP_STORAGE_H
diff --git a/media/mtp/MtpStorageInfo.cpp b/media/mtp/MtpStorageInfo.cpp
new file mode 100644
index 0000000..dcd37cd
--- /dev/null
+++ b/media/mtp/MtpStorageInfo.cpp
@@ -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.
+ */
+
+#define LOG_TAG "MtpStorageInfo"
+
+#include "MtpDebug.h"
+#include "MtpDataPacket.h"
+#include "MtpStorageInfo.h"
+#include "MtpStringBuffer.h"
+
+namespace android {
+
+MtpStorageInfo::MtpStorageInfo(MtpStorageID id)
+ : mStorageID(id),
+ mStorageType(0),
+ mFileSystemType(0),
+ mAccessCapability(0),
+ mMaxCapacity(0),
+ mFreeSpaceBytes(0),
+ mFreeSpaceObjects(0),
+ mStorageDescription(NULL),
+ mVolumeIdentifier(NULL)
+{
+}
+
+MtpStorageInfo::~MtpStorageInfo() {
+ if (mStorageDescription)
+ free(mStorageDescription);
+ if (mVolumeIdentifier)
+ free(mVolumeIdentifier);
+}
+
+void MtpStorageInfo::read(MtpDataPacket& packet) {
+ MtpStringBuffer string;
+
+ // read the device info
+ mStorageType = packet.getUInt16();
+ mFileSystemType = packet.getUInt16();
+ mAccessCapability = packet.getUInt16();
+ mMaxCapacity = packet.getUInt64();
+ mFreeSpaceBytes = packet.getUInt64();
+ mFreeSpaceObjects = packet.getUInt32();
+
+ packet.getString(string);
+ mStorageDescription = strdup((const char *)string);
+ packet.getString(string);
+ mVolumeIdentifier = strdup((const char *)string);
+}
+
+void MtpStorageInfo::print() {
+ ALOGD("Storage Info %08X:\n\tmStorageType: %d\n\tmFileSystemType: %d\n\tmAccessCapability: %d\n",
+ mStorageID, mStorageType, mFileSystemType, mAccessCapability);
+ ALOGD("\tmMaxCapacity: %lld\n\tmFreeSpaceBytes: %lld\n\tmFreeSpaceObjects: %d\n",
+ mMaxCapacity, mFreeSpaceBytes, mFreeSpaceObjects);
+ ALOGD("\tmStorageDescription: %s\n\tmVolumeIdentifier: %s\n",
+ mStorageDescription, mVolumeIdentifier);
+}
+
+} // namespace android
diff --git a/media/mtp/MtpStorageInfo.h b/media/mtp/MtpStorageInfo.h
new file mode 100644
index 0000000..2cb626e
--- /dev/null
+++ b/media/mtp/MtpStorageInfo.h
@@ -0,0 +1,49 @@
+/*
+ * 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 _MTP_STORAGE_INFO_H
+#define _MTP_STORAGE_INFO_H
+
+#include "MtpTypes.h"
+
+namespace android {
+
+class MtpDataPacket;
+
+class MtpStorageInfo {
+public:
+ MtpStorageID mStorageID;
+ uint16_t mStorageType;
+ uint16_t mFileSystemType;
+ uint16_t mAccessCapability;
+ uint64_t mMaxCapacity;
+ uint64_t mFreeSpaceBytes;
+ uint32_t mFreeSpaceObjects;
+ char* mStorageDescription;
+ char* mVolumeIdentifier;
+
+public:
+ MtpStorageInfo(MtpStorageID id);
+ virtual ~MtpStorageInfo();
+
+ void read(MtpDataPacket& packet);
+
+ void print();
+};
+
+}; // namespace android
+
+#endif // _MTP_STORAGE_INFO_H
diff --git a/media/mtp/MtpStringBuffer.cpp b/media/mtp/MtpStringBuffer.cpp
new file mode 100644
index 0000000..fe8cf04
--- /dev/null
+++ b/media/mtp/MtpStringBuffer.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.
+ */
+
+#define LOG_TAG "MtpStringBuffer"
+
+#include <string.h>
+
+#include "MtpDataPacket.h"
+#include "MtpStringBuffer.h"
+
+namespace android {
+
+MtpStringBuffer::MtpStringBuffer()
+ : mCharCount(0),
+ mByteCount(1)
+{
+ mBuffer[0] = 0;
+}
+
+MtpStringBuffer::MtpStringBuffer(const char* src)
+ : mCharCount(0),
+ mByteCount(1)
+{
+ set(src);
+}
+
+MtpStringBuffer::MtpStringBuffer(const uint16_t* src)
+ : mCharCount(0),
+ mByteCount(1)
+{
+ set(src);
+}
+
+MtpStringBuffer::MtpStringBuffer(const MtpStringBuffer& src)
+ : mCharCount(src.mCharCount),
+ mByteCount(src.mByteCount)
+{
+ memcpy(mBuffer, src.mBuffer, mByteCount);
+}
+
+
+MtpStringBuffer::~MtpStringBuffer() {
+}
+
+void MtpStringBuffer::set(const char* src) {
+ int length = strlen(src);
+ if (length >= sizeof(mBuffer))
+ length = sizeof(mBuffer) - 1;
+ memcpy(mBuffer, src, length);
+
+ // count the characters
+ int count = 0;
+ char ch;
+ while ((ch = *src++) != 0) {
+ if ((ch & 0x80) == 0) {
+ // single byte character
+ } else if ((ch & 0xE0) == 0xC0) {
+ // two byte character
+ if (! *src++) {
+ // last character was truncated, so ignore last byte
+ length--;
+ break;
+ }
+ } else if ((ch & 0xF0) == 0xE0) {
+ // 3 byte char
+ if (! *src++) {
+ // last character was truncated, so ignore last byte
+ length--;
+ break;
+ }
+ if (! *src++) {
+ // last character was truncated, so ignore last two bytes
+ length -= 2;
+ break;
+ }
+ }
+ count++;
+ }
+
+ mByteCount = length + 1;
+ mBuffer[length] = 0;
+ mCharCount = count;
+}
+
+void MtpStringBuffer::set(const uint16_t* src) {
+ int count = 0;
+ uint16_t ch;
+ uint8_t* dest = mBuffer;
+
+ while ((ch = *src++) != 0 && count < 255) {
+ if (ch >= 0x0800) {
+ *dest++ = (uint8_t)(0xE0 | (ch >> 12));
+ *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));
+ *dest++ = (uint8_t)(0x80 | (ch & 0x3F));
+ } else if (ch >= 0x80) {
+ *dest++ = (uint8_t)(0xC0 | (ch >> 6));
+ *dest++ = (uint8_t)(0x80 | (ch & 0x3F));
+ } else {
+ *dest++ = ch;
+ }
+ count++;
+ }
+ *dest++ = 0;
+ mCharCount = count;
+ mByteCount = dest - mBuffer;
+}
+
+void MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
+ int count = packet->getUInt8();
+ uint8_t* dest = mBuffer;
+ for (int i = 0; i < count; i++) {
+ uint16_t ch = packet->getUInt16();
+ if (ch >= 0x0800) {
+ *dest++ = (uint8_t)(0xE0 | (ch >> 12));
+ *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));
+ *dest++ = (uint8_t)(0x80 | (ch & 0x3F));
+ } else if (ch >= 0x80) {
+ *dest++ = (uint8_t)(0xC0 | (ch >> 6));
+ *dest++ = (uint8_t)(0x80 | (ch & 0x3F));
+ } else {
+ *dest++ = ch;
+ }
+ }
+ *dest++ = 0;
+ mCharCount = count;
+ mByteCount = dest - mBuffer;
+}
+
+void MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const {
+ int count = mCharCount;
+ const uint8_t* src = mBuffer;
+ packet->putUInt8(count > 0 ? count + 1 : 0);
+
+ // expand utf8 to 16 bit chars
+ for (int i = 0; i < count; i++) {
+ uint16_t ch;
+ uint16_t ch1 = *src++;
+ if ((ch1 & 0x80) == 0) {
+ // single byte character
+ ch = ch1;
+ } else if ((ch1 & 0xE0) == 0xC0) {
+ // two byte character
+ uint16_t ch2 = *src++;
+ ch = ((ch1 & 0x1F) << 6) | (ch2 & 0x3F);
+ } else {
+ // three byte character
+ uint16_t ch2 = *src++;
+ uint16_t ch3 = *src++;
+ ch = ((ch1 & 0x0F) << 12) | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F);
+ }
+ packet->putUInt16(ch);
+ }
+ // only terminate with zero if string is not empty
+ if (count > 0)
+ packet->putUInt16(0);
+}
+
+} // namespace android
diff --git a/media/mtp/MtpStringBuffer.h b/media/mtp/MtpStringBuffer.h
new file mode 100644
index 0000000..cbc8307
--- /dev/null
+++ b/media/mtp/MtpStringBuffer.h
@@ -0,0 +1,57 @@
+/*
+ * 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 _MTP_STRING_BUFFER_H
+#define _MTP_STRING_BUFFER_H
+
+#include <stdint.h>
+
+namespace android {
+
+class MtpDataPacket;
+
+// Represents a utf8 string, with a maximum of 255 characters
+class MtpStringBuffer {
+
+private:
+ // mBuffer contains string in UTF8 format
+ // maximum 3 bytes/character, with 1 extra for zero termination
+ uint8_t mBuffer[255 * 3 + 1];
+ int mCharCount;
+ int mByteCount;
+
+public:
+ MtpStringBuffer();
+ MtpStringBuffer(const char* src);
+ MtpStringBuffer(const uint16_t* src);
+ MtpStringBuffer(const MtpStringBuffer& src);
+ virtual ~MtpStringBuffer();
+
+ void set(const char* src);
+ void set(const uint16_t* src);
+
+ void readFromPacket(MtpDataPacket* packet);
+ void writeToPacket(MtpDataPacket* packet) const;
+
+ inline int getCharCount() const { return mCharCount; }
+ inline int getByteCount() const { return mByteCount; }
+
+ inline operator const char*() const { return (const char *)mBuffer; }
+};
+
+}; // namespace android
+
+#endif // _MTP_STRING_BUFFER_H
diff --git a/media/mtp/MtpTypes.h b/media/mtp/MtpTypes.h
new file mode 100644
index 0000000..720c854
--- /dev/null
+++ b/media/mtp/MtpTypes.h
@@ -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.
+ */
+
+#ifndef _MTP_TYPES_H
+#define _MTP_TYPES_H
+
+#include <stdint.h>
+#include "utils/String8.h"
+#include "utils/Vector.h"
+
+namespace android {
+
+typedef int32_t int128_t[4];
+typedef uint32_t uint128_t[4];
+
+typedef uint16_t MtpOperationCode;
+typedef uint16_t MtpResponseCode;
+typedef uint16_t MtpEventCode;
+typedef uint32_t MtpSessionID;
+typedef uint32_t MtpStorageID;
+typedef uint32_t MtpTransactionID;
+typedef uint16_t MtpPropertyCode;
+typedef uint16_t MtpDataType;
+typedef uint16_t MtpObjectFormat;
+typedef MtpPropertyCode MtpDeviceProperty;
+typedef MtpPropertyCode MtpObjectProperty;
+
+// object handles are unique across all storage but only within a single session.
+// object handles cannot be reused after an object is deleted.
+// values 0x00000000 and 0xFFFFFFFF are reserved for special purposes.
+typedef uint32_t MtpObjectHandle;
+
+// Special values
+#define MTP_PARENT_ROOT 0xFFFFFFFF // parent is root of the storage
+#define kInvalidObjectHandle 0xFFFFFFFF
+
+class MtpStorage;
+class MtpDevice;
+class MtpProperty;
+
+typedef Vector<MtpStorage *> MtpStorageList;
+typedef Vector<MtpDevice*> MtpDeviceList;
+typedef Vector<MtpProperty*> MtpPropertyList;
+
+typedef Vector<uint8_t> UInt8List;
+typedef Vector<uint16_t> UInt16List;
+typedef Vector<uint32_t> UInt32List;
+typedef Vector<uint64_t> UInt64List;
+typedef Vector<int8_t> Int8List;
+typedef Vector<int16_t> Int16List;
+typedef Vector<int32_t> Int32List;
+typedef Vector<int64_t> Int64List;
+
+typedef UInt16List MtpObjectPropertyList;
+typedef UInt16List MtpDevicePropertyList;
+typedef UInt16List MtpObjectFormatList;
+typedef UInt32List MtpObjectHandleList;
+typedef UInt16List MtpObjectPropertyList;
+typedef UInt32List MtpStorageIDList;
+
+typedef String8 MtpString;
+
+}; // namespace android
+
+#endif // _MTP_TYPES_H
diff --git a/media/mtp/MtpUtils.cpp b/media/mtp/MtpUtils.cpp
new file mode 100644
index 0000000..6ec8876
--- /dev/null
+++ b/media/mtp/MtpUtils.cpp
@@ -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.
+ */
+
+#define LOG_TAG "MtpUtils"
+
+#include <stdio.h>
+#include <time.h>
+
+#include <cutils/tztime.h>
+#include "MtpUtils.h"
+
+namespace android {
+
+/*
+DateTime strings follow a compatible subset of the definition found in ISO 8601, and
+take the form of a Unicode string formatted as: "YYYYMMDDThhmmss.s". In this
+representation, YYYY shall be replaced by the year, MM replaced by the month (01-12),
+DD replaced by the day (01-31), T is a constant character 'T' delimiting time from date,
+hh is replaced by the hour (00-23), mm is replaced by the minute (00-59), and ss by the
+second (00-59). The ".s" is optional, and represents tenths of a second.
+*/
+
+bool parseDateTime(const char* dateTime, time_t& outSeconds) {
+ int year, month, day, hour, minute, second;
+ struct tm tm;
+
+ if (sscanf(dateTime, "%04d%02d%02dT%02d%02d%02d",
+ &year, &month, &day, &hour, &minute, &second) != 6)
+ return false;
+ const char* tail = dateTime + 15;
+ // skip optional tenth of second
+ if (tail[0] == '.' && tail[1])
+ tail += 2;
+ //FIXME - support +/-hhmm
+ bool useUTC = (tail[0] == 'Z');
+
+ // hack to compute timezone
+ time_t dummy;
+ localtime_r(&dummy, &tm);
+
+ tm.tm_sec = second;
+ tm.tm_min = minute;
+ tm.tm_hour = hour;
+ tm.tm_mday = day;
+ tm.tm_mon = month - 1; // mktime uses months in 0 - 11 range
+ tm.tm_year = year - 1900;
+ tm.tm_wday = 0;
+ tm.tm_isdst = -1;
+ if (useUTC)
+ outSeconds = mktime(&tm);
+ else
+ outSeconds = mktime_tz(&tm, tm.tm_zone);
+
+ return true;
+}
+
+void formatDateTime(time_t seconds, char* buffer, int bufferLength) {
+ struct tm tm;
+
+ localtime_r(&seconds, &tm);
+ snprintf(buffer, bufferLength, "%04d%02d%02dT%02d%02d%02d",
+ tm.tm_year + 1900,
+ tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
+ tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
+
+} // namespace android
diff --git a/media/mtp/MtpUtils.h b/media/mtp/MtpUtils.h
new file mode 100644
index 0000000..61f9055
--- /dev/null
+++ b/media/mtp/MtpUtils.h
@@ -0,0 +1,29 @@
+/*
+ * 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 _MTP_UTILS_H
+#define _MTP_UTILS_H
+
+#include <stdint.h>
+
+namespace android {
+
+bool parseDateTime(const char* dateTime, time_t& outSeconds);
+void formatDateTime(time_t seconds, char* buffer, int bufferLength);
+
+}; // namespace android
+
+#endif // _MTP_UTILS_H
diff --git a/media/mtp/mtp.h b/media/mtp/mtp.h
new file mode 100644
index 0000000..d270df5
--- /dev/null
+++ b/media/mtp/mtp.h
@@ -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.
+ */
+
+#ifndef _MTP_H
+#define _MTP_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define MTP_STANDARD_VERSION 100
+
+// Container Types
+#define MTP_CONTAINER_TYPE_UNDEFINED 0
+#define MTP_CONTAINER_TYPE_COMMAND 1
+#define MTP_CONTAINER_TYPE_DATA 2
+#define MTP_CONTAINER_TYPE_RESPONSE 3
+#define MTP_CONTAINER_TYPE_EVENT 4
+
+// Container Offsets
+#define MTP_CONTAINER_LENGTH_OFFSET 0
+#define MTP_CONTAINER_TYPE_OFFSET 4
+#define MTP_CONTAINER_CODE_OFFSET 6
+#define MTP_CONTAINER_TRANSACTION_ID_OFFSET 8
+#define MTP_CONTAINER_PARAMETER_OFFSET 12
+#define MTP_CONTAINER_HEADER_SIZE 12
+
+// MTP Data Types
+#define MTP_TYPE_UNDEFINED 0x0000 // Undefined
+#define MTP_TYPE_INT8 0x0001 // Signed 8-bit integer
+#define MTP_TYPE_UINT8 0x0002 // Unsigned 8-bit integer
+#define MTP_TYPE_INT16 0x0003 // Signed 16-bit integer
+#define MTP_TYPE_UINT16 0x0004 // Unsigned 16-bit integer
+#define MTP_TYPE_INT32 0x0005 // Signed 32-bit integer
+#define MTP_TYPE_UINT32 0x0006 // Unsigned 32-bit integer
+#define MTP_TYPE_INT64 0x0007 // Signed 64-bit integer
+#define MTP_TYPE_UINT64 0x0008 // Unsigned 64-bit integer
+#define MTP_TYPE_INT128 0x0009 // Signed 128-bit integer
+#define MTP_TYPE_UINT128 0x000A // Unsigned 128-bit integer
+#define MTP_TYPE_AINT8 0x4001 // Array of signed 8-bit integers
+#define MTP_TYPE_AUINT8 0x4002 // Array of unsigned 8-bit integers
+#define MTP_TYPE_AINT16 0x4003 // Array of signed 16-bit integers
+#define MTP_TYPE_AUINT16 0x4004 // Array of unsigned 16-bit integers
+#define MTP_TYPE_AINT32 0x4005 // Array of signed 32-bit integers
+#define MTP_TYPE_AUINT32 0x4006 // Array of unsigned 32-bit integers
+#define MTP_TYPE_AINT64 0x4007 // Array of signed 64-bit integers
+#define MTP_TYPE_AUINT64 0x4008 // Array of unsigned 64-bit integers
+#define MTP_TYPE_AINT128 0x4009 // Array of signed 128-bit integers
+#define MTP_TYPE_AUINT128 0x400A // Array of unsigned 128-bit integers
+#define MTP_TYPE_STR 0xFFFF // Variable-length Unicode string
+
+// MTP Format Codes
+#define MTP_FORMAT_UNDEFINED 0x3000 // Undefined object
+#define MTP_FORMAT_ASSOCIATION 0x3001 // Association (for example, a folder)
+#define MTP_FORMAT_SCRIPT 0x3002 // Device model-specific script
+#define MTP_FORMAT_EXECUTABLE 0x3003 // Device model-specific binary executable
+#define MTP_FORMAT_TEXT 0x3004 // Text file
+#define MTP_FORMAT_HTML 0x3005 // Hypertext Markup Language file (text)
+#define MTP_FORMAT_DPOF 0x3006 // Digital Print Order Format file (text)
+#define MTP_FORMAT_AIFF 0x3007 // Audio clip
+#define MTP_FORMAT_WAV 0x3008 // Audio clip
+#define MTP_FORMAT_MP3 0x3009 // Audio clip
+#define MTP_FORMAT_AVI 0x300A // Video clip
+#define MTP_FORMAT_MPEG 0x300B // Video clip
+#define MTP_FORMAT_ASF 0x300C // Microsoft Advanced Streaming Format (video)
+#define MTP_FORMAT_DEFINED 0x3800 // Unknown image object
+#define MTP_FORMAT_EXIF_JPEG 0x3801 // Exchangeable File Format, JEIDA standard
+#define MTP_FORMAT_TIFF_EP 0x3802 // Tag Image File Format for Electronic Photography
+#define MTP_FORMAT_FLASHPIX 0x3803 // Structured Storage Image Format
+#define MTP_FORMAT_BMP 0x3804 // Microsoft Windows Bitmap file
+#define MTP_FORMAT_CIFF 0x3805 // Canon Camera Image File Format
+#define MTP_FORMAT_GIF 0x3807 // Graphics Interchange Format
+#define MTP_FORMAT_JFIF 0x3808 // JPEG File Interchange Format
+#define MTP_FORMAT_CD 0x3809 // PhotoCD Image Pac
+#define MTP_FORMAT_PICT 0x380A // Quickdraw Image Format
+#define MTP_FORMAT_PNG 0x380B // Portable Network Graphics
+#define MTP_FORMAT_TIFF 0x380D // Tag Image File Format
+#define MTP_FORMAT_TIFF_IT 0x380E // Tag Image File Format for Information Technology (graphic arts)
+#define MTP_FORMAT_JP2 0x380F // JPEG2000 Baseline File Format
+#define MTP_FORMAT_JPX 0x3810 // JPEG2000 Extended File Format
+#define MTP_FORMAT_UNDEFINED_FIRMWARE 0xB802
+#define MTP_FORMAT_WINDOWS_IMAGE_FORMAT 0xB881
+#define MTP_FORMAT_UNDEFINED_AUDIO 0xB900
+#define MTP_FORMAT_WMA 0xB901
+#define MTP_FORMAT_OGG 0xB902
+#define MTP_FORMAT_AAC 0xB903
+#define MTP_FORMAT_AUDIBLE 0xB904
+#define MTP_FORMAT_FLAC 0xB906
+#define MTP_FORMAT_UNDEFINED_VIDEO 0xB980
+#define MTP_FORMAT_WMV 0xB981
+#define MTP_FORMAT_MP4_CONTAINER 0xB982 // ISO 14496-1
+#define MTP_FORMAT_MP2 0xB983
+#define MTP_FORMAT_3GP_CONTAINER 0xB984 // 3GPP file format. Details: http://www.3gpp.org/ftp/Specs/html-info/26244.htm (page title - \u201cTransparent end-to-end packet switched streaming service, 3GPP file format\u201d).
+#define MTP_FORMAT_UNDEFINED_COLLECTION 0xBA00
+#define MTP_FORMAT_ABSTRACT_MULTIMEDIA_ALBUM 0xBA01
+#define MTP_FORMAT_ABSTRACT_IMAGE_ALBUM 0xBA02
+#define MTP_FORMAT_ABSTRACT_AUDIO_ALBUM 0xBA03
+#define MTP_FORMAT_ABSTRACT_VIDEO_ALBUM 0xBA04
+#define MTP_FORMAT_ABSTRACT_AV_PLAYLIST 0xBA05
+#define MTP_FORMAT_ABSTRACT_CONTACT_GROUP 0xBA06
+#define MTP_FORMAT_ABSTRACT_MESSAGE_FOLDER 0xBA07
+#define MTP_FORMAT_ABSTRACT_CHAPTERED_PRODUCTION 0xBA08
+#define MTP_FORMAT_ABSTRACT_AUDIO_PLAYLIST 0xBA09
+#define MTP_FORMAT_ABSTRACT_VIDEO_PLAYLIST 0xBA0A
+#define MTP_FORMAT_ABSTRACT_MEDIACAST 0xBA0B // For use with mediacasts; references multimedia enclosures of RSS feeds or episodic content
+#define MTP_FORMAT_WPL_PLAYLIST 0xBA10
+#define MTP_FORMAT_M3U_PLAYLIST 0xBA11
+#define MTP_FORMAT_MPL_PLAYLIST 0xBA12
+#define MTP_FORMAT_ASX_PLAYLIST 0xBA13
+#define MTP_FORMAT_PLS_PLAYLIST 0xBA14
+#define MTP_FORMAT_UNDEFINED_DOCUMENT 0xBA80
+#define MTP_FORMAT_ABSTRACT_DOCUMENT 0xBA81
+#define MTP_FORMAT_XML_DOCUMENT 0xBA82
+#define MTP_FORMAT_MS_WORD_DOCUMENT 0xBA83
+#define MTP_FORMAT_MHT_COMPILED_HTML_DOCUMENT 0xBA84
+#define MTP_FORMAT_MS_EXCEL_SPREADSHEET 0xBA85
+#define MTP_FORMAT_MS_POWERPOINT_PRESENTATION 0xBA86
+#define MTP_FORMAT_UNDEFINED_MESSAGE 0xBB00
+#define MTP_FORMAT_ABSTRACT_MESSSAGE 0xBB01
+#define MTP_FORMAT_UNDEFINED_CONTACT 0xBB80
+#define MTP_FORMAT_ABSTRACT_CONTACT 0xBB81
+#define MTP_FORMAT_VCARD_2 0xBB82
+
+// MTP Object Property Codes
+#define MTP_PROPERTY_STORAGE_ID 0xDC01
+#define MTP_PROPERTY_OBJECT_FORMAT 0xDC02
+#define MTP_PROPERTY_PROTECTION_STATUS 0xDC03
+#define MTP_PROPERTY_OBJECT_SIZE 0xDC04
+#define MTP_PROPERTY_ASSOCIATION_TYPE 0xDC05
+#define MTP_PROPERTY_ASSOCIATION_DESC 0xDC06
+#define MTP_PROPERTY_OBJECT_FILE_NAME 0xDC07
+#define MTP_PROPERTY_DATE_CREATED 0xDC08
+#define MTP_PROPERTY_DATE_MODIFIED 0xDC09
+#define MTP_PROPERTY_KEYWORDS 0xDC0A
+#define MTP_PROPERTY_PARENT_OBJECT 0xDC0B
+#define MTP_PROPERTY_ALLOWED_FOLDER_CONTENTS 0xDC0C
+#define MTP_PROPERTY_HIDDEN 0xDC0D
+#define MTP_PROPERTY_SYSTEM_OBJECT 0xDC0E
+#define MTP_PROPERTY_PERSISTENT_UID 0xDC41
+#define MTP_PROPERTY_SYNC_ID 0xDC42
+#define MTP_PROPERTY_PROPERTY_BAG 0xDC43
+#define MTP_PROPERTY_NAME 0xDC44
+#define MTP_PROPERTY_CREATED_BY 0xDC45
+#define MTP_PROPERTY_ARTIST 0xDC46
+#define MTP_PROPERTY_DATE_AUTHORED 0xDC47
+#define MTP_PROPERTY_DESCRIPTION 0xDC48
+#define MTP_PROPERTY_URL_REFERENCE 0xDC49
+#define MTP_PROPERTY_LANGUAGE_LOCALE 0xDC4A
+#define MTP_PROPERTY_COPYRIGHT_INFORMATION 0xDC4B
+#define MTP_PROPERTY_SOURCE 0xDC4C
+#define MTP_PROPERTY_ORIGIN_LOCATION 0xDC4D
+#define MTP_PROPERTY_DATE_ADDED 0xDC4E
+#define MTP_PROPERTY_NON_CONSUMABLE 0xDC4F
+#define MTP_PROPERTY_CORRUPT_UNPLAYABLE 0xDC50
+#define MTP_PROPERTY_PRODUCER_SERIAL_NUMBER 0xDC51
+#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_FORMAT 0xDC81
+#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_SIZE 0xDC82
+#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_HEIGHT 0xDC83
+#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_WIDTH 0xDC84
+#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DURATION 0xDC85
+#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DATA 0xDC86
+#define MTP_PROPERTY_WIDTH 0xDC87
+#define MTP_PROPERTY_HEIGHT 0xDC88
+#define MTP_PROPERTY_DURATION 0xDC89
+#define MTP_PROPERTY_RATING 0xDC8A
+#define MTP_PROPERTY_TRACK 0xDC8B
+#define MTP_PROPERTY_GENRE 0xDC8C
+#define MTP_PROPERTY_CREDITS 0xDC8D
+#define MTP_PROPERTY_LYRICS 0xDC8E
+#define MTP_PROPERTY_SUBSCRIPTION_CONTENT_ID 0xDC8F
+#define MTP_PROPERTY_PRODUCED_BY 0xDC90
+#define MTP_PROPERTY_USE_COUNT 0xDC91
+#define MTP_PROPERTY_SKIP_COUNT 0xDC92
+#define MTP_PROPERTY_LAST_ACCESSED 0xDC93
+#define MTP_PROPERTY_PARENTAL_RATING 0xDC94
+#define MTP_PROPERTY_META_GENRE 0xDC95
+#define MTP_PROPERTY_COMPOSER 0xDC96
+#define MTP_PROPERTY_EFFECTIVE_RATING 0xDC97
+#define MTP_PROPERTY_SUBTITLE 0xDC98
+#define MTP_PROPERTY_ORIGINAL_RELEASE_DATE 0xDC99
+#define MTP_PROPERTY_ALBUM_NAME 0xDC9A
+#define MTP_PROPERTY_ALBUM_ARTIST 0xDC9B
+#define MTP_PROPERTY_MOOD 0xDC9C
+#define MTP_PROPERTY_DRM_STATUS 0xDC9D
+#define MTP_PROPERTY_SUB_DESCRIPTION 0xDC9E
+#define MTP_PROPERTY_IS_CROPPED 0xDCD1
+#define MTP_PROPERTY_IS_COLOUR_CORRECTED 0xDCD2
+#define MTP_PROPERTY_IMAGE_BIT_DEPTH 0xDCD3
+#define MTP_PROPERTY_F_NUMBER 0xDCD4
+#define MTP_PROPERTY_EXPOSURE_TIME 0xDCD5
+#define MTP_PROPERTY_EXPOSURE_INDEX 0xDCD6
+#define MTP_PROPERTY_TOTAL_BITRATE 0xDE91
+#define MTP_PROPERTY_BITRATE_TYPE 0xDE92
+#define MTP_PROPERTY_SAMPLE_RATE 0xDE93
+#define MTP_PROPERTY_NUMBER_OF_CHANNELS 0xDE94
+#define MTP_PROPERTY_AUDIO_BIT_DEPTH 0xDE95
+#define MTP_PROPERTY_SCAN_TYPE 0xDE97
+#define MTP_PROPERTY_AUDIO_WAVE_CODEC 0xDE99
+#define MTP_PROPERTY_AUDIO_BITRATE 0xDE9A
+#define MTP_PROPERTY_VIDEO_FOURCC_CODEC 0xDE9B
+#define MTP_PROPERTY_VIDEO_BITRATE 0xDE9C
+#define MTP_PROPERTY_FRAMES_PER_THOUSAND_SECONDS 0xDE9D
+#define MTP_PROPERTY_KEYFRAME_DISTANCE 0xDE9E
+#define MTP_PROPERTY_BUFFER_SIZE 0xDE9F
+#define MTP_PROPERTY_ENCODING_QUALITY 0xDEA0
+#define MTP_PROPERTY_ENCODING_PROFILE 0xDEA1
+#define MTP_PROPERTY_DISPLAY_NAME 0xDCE0
+#define MTP_PROPERTY_BODY_TEXT 0xDCE1
+#define MTP_PROPERTY_SUBJECT 0xDCE2
+#define MTP_PROPERTY_PRIORITY 0xDCE3
+#define MTP_PROPERTY_GIVEN_NAME 0xDD00
+#define MTP_PROPERTY_MIDDLE_NAMES 0xDD01
+#define MTP_PROPERTY_FAMILY_NAME 0xDD02
+#define MTP_PROPERTY_PREFIX 0xDD03
+#define MTP_PROPERTY_SUFFIX 0xDD04
+#define MTP_PROPERTY_PHONETIC_GIVEN_NAME 0xDD05
+#define MTP_PROPERTY_PHONETIC_FAMILY_NAME 0xDD06
+#define MTP_PROPERTY_EMAIL_PRIMARY 0xDD07
+#define MTP_PROPERTY_EMAIL_PERSONAL_1 0xDD08
+#define MTP_PROPERTY_EMAIL_PERSONAL_2 0xDD09
+#define MTP_PROPERTY_EMAIL_BUSINESS_1 0xDD0A
+#define MTP_PROPERTY_EMAIL_BUSINESS_2 0xDD0B
+#define MTP_PROPERTY_EMAIL_OTHERS 0xDD0C
+#define MTP_PROPERTY_PHONE_NUMBER_PRIMARY 0xDD0D
+#define MTP_PROPERTY_PHONE_NUMBER_PERSONAL 0xDD0E
+#define MTP_PROPERTY_PHONE_NUMBER_PERSONAL_2 0xDD0F
+#define MTP_PROPERTY_PHONE_NUMBER_BUSINESS 0xDD10
+#define MTP_PROPERTY_PHONE_NUMBER_BUSINESS_2 0xDD11
+#define MTP_PROPERTY_PHONE_NUMBER_MOBILE 0xDD12
+#define MTP_PROPERTY_PHONE_NUMBER_MOBILE_2 0xDD13
+#define MTP_PROPERTY_FAX_NUMBER_PRIMARY 0xDD14
+#define MTP_PROPERTY_FAX_NUMBER_PERSONAL 0xDD15
+#define MTP_PROPERTY_FAX_NUMBER_BUSINESS 0xDD16
+#define MTP_PROPERTY_PAGER_NUMBER 0xDD17
+#define MTP_PROPERTY_PHONE_NUMBER_OTHERS 0xDD18
+#define MTP_PROPERTY_PRIMARY_WEB_ADDRESS 0xDD19
+#define MTP_PROPERTY_PERSONAL_WEB_ADDRESS 0xDD1A
+#define MTP_PROPERTY_BUSINESS_WEB_ADDRESS 0xDD1B
+#define MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS 0xDD1C
+#define MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_2 0xDD1D
+#define MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_3 0xDD1E
+#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_FULL 0xDD1F
+#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_1 0xDD20
+#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_2 0xDD21
+#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_CITY 0xDD22
+#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_REGION 0xDD23
+#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE 0xDD24
+#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_COUNTRY 0xDD25
+#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_FULL 0xDD26
+#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_1 0xDD27
+#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_2 0xDD28
+#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_CITY 0xDD29
+#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_REGION 0xDD2A
+#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE 0xDD2B
+#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_COUNTRY 0xDD2C
+#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_FULL 0xDD2D
+#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_1 0xDD2E
+#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_2 0xDD2F
+#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_CITY 0xDD30
+#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_REGION 0xDD31
+#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_POSTAL_CODE 0xDD32
+#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_COUNTRY 0xDD33
+#define MTP_PROPERTY_ORGANIZATION_NAME 0xDD34
+#define MTP_PROPERTY_PHONETIC_ORGANIZATION_NAME 0xDD35
+#define MTP_PROPERTY_ROLE 0xDD36
+#define MTP_PROPERTY_BIRTHDATE 0xDD37
+#define MTP_PROPERTY_MESSAGE_TO 0xDD40
+#define MTP_PROPERTY_MESSAGE_CC 0xDD41
+#define MTP_PROPERTY_MESSAGE_BCC 0xDD42
+#define MTP_PROPERTY_MESSAGE_READ 0xDD43
+#define MTP_PROPERTY_MESSAGE_RECEIVED_TIME 0xDD44
+#define MTP_PROPERTY_MESSAGE_SENDER 0xDD45
+#define MTP_PROPERTY_ACTIVITY_BEGIN_TIME 0xDD50
+#define MTP_PROPERTY_ACTIVITY_END_TIME 0xDD51
+#define MTP_PROPERTY_ACTIVITY_LOCATION 0xDD52
+#define MTP_PROPERTY_ACTIVITY_REQUIRED_ATTENDEES 0xDD54
+#define MTP_PROPERTY_ACTIVITY_OPTIONAL_ATTENDEES 0xDD55
+#define MTP_PROPERTY_ACTIVITY_RESOURCES 0xDD56
+#define MTP_PROPERTY_ACTIVITY_ACCEPTED 0xDD57
+#define MTP_PROPERTY_ACTIVITY_TENTATIVE 0xDD58
+#define MTP_PROPERTY_ACTIVITY_DECLINED 0xDD59
+#define MTP_PROPERTY_ACTIVITY_REMAINDER_TIME 0xDD5A
+#define MTP_PROPERTY_ACTIVITY_OWNER 0xDD5B
+#define MTP_PROPERTY_ACTIVITY_STATUS 0xDD5C
+#define MTP_PROPERTY_OWNER 0xDD5D
+#define MTP_PROPERTY_EDITOR 0xDD5E
+#define MTP_PROPERTY_WEBMASTER 0xDD5F
+#define MTP_PROPERTY_URL_SOURCE 0xDD60
+#define MTP_PROPERTY_URL_DESTINATION 0xDD61
+#define MTP_PROPERTY_TIME_BOOKMARK 0xDD62
+#define MTP_PROPERTY_OBJECT_BOOKMARK 0xDD63
+#define MTP_PROPERTY_BYTE_BOOKMARK 0xDD64
+#define MTP_PROPERTY_LAST_BUILD_DATE 0xDD70
+#define MTP_PROPERTY_TIME_TO_LIVE 0xDD71
+#define MTP_PROPERTY_MEDIA_GUID 0xDD72
+
+// MTP Device Property Codes
+#define MTP_DEVICE_PROPERTY_UNDEFINED 0x5000
+#define MTP_DEVICE_PROPERTY_BATTERY_LEVEL 0x5001
+#define MTP_DEVICE_PROPERTY_FUNCTIONAL_MODE 0x5002
+#define MTP_DEVICE_PROPERTY_IMAGE_SIZE 0x5003
+#define MTP_DEVICE_PROPERTY_COMPRESSION_SETTING 0x5004
+#define MTP_DEVICE_PROPERTY_WHITE_BALANCE 0x5005
+#define MTP_DEVICE_PROPERTY_RGB_GAIN 0x5006
+#define MTP_DEVICE_PROPERTY_F_NUMBER 0x5007
+#define MTP_DEVICE_PROPERTY_FOCAL_LENGTH 0x5008
+#define MTP_DEVICE_PROPERTY_FOCUS_DISTANCE 0x5009
+#define MTP_DEVICE_PROPERTY_FOCUS_MODE 0x500A
+#define MTP_DEVICE_PROPERTY_EXPOSURE_METERING_MODE 0x500B
+#define MTP_DEVICE_PROPERTY_FLASH_MODE 0x500C
+#define MTP_DEVICE_PROPERTY_EXPOSURE_TIME 0x500D
+#define MTP_DEVICE_PROPERTY_EXPOSURE_PROGRAM_MODE 0x500E
+#define MTP_DEVICE_PROPERTY_EXPOSURE_INDEX 0x500F
+#define MTP_DEVICE_PROPERTY_EXPOSURE_BIAS_COMPENSATION 0x5010
+#define MTP_DEVICE_PROPERTY_DATETIME 0x5011
+#define MTP_DEVICE_PROPERTY_CAPTURE_DELAY 0x5012
+#define MTP_DEVICE_PROPERTY_STILL_CAPTURE_MODE 0x5013
+#define MTP_DEVICE_PROPERTY_CONTRAST 0x5014
+#define MTP_DEVICE_PROPERTY_SHARPNESS 0x5015
+#define MTP_DEVICE_PROPERTY_DIGITAL_ZOOM 0x5016
+#define MTP_DEVICE_PROPERTY_EFFECT_MODE 0x5017
+#define MTP_DEVICE_PROPERTY_BURST_NUMBER 0x5018
+#define MTP_DEVICE_PROPERTY_BURST_INTERVAL 0x5019
+#define MTP_DEVICE_PROPERTY_TIMELAPSE_NUMBER 0x501A
+#define MTP_DEVICE_PROPERTY_TIMELAPSE_INTERVAL 0x501B
+#define MTP_DEVICE_PROPERTY_FOCUS_METERING_MODE 0x501C
+#define MTP_DEVICE_PROPERTY_UPLOAD_URL 0x501D
+#define MTP_DEVICE_PROPERTY_ARTIST 0x501E
+#define MTP_DEVICE_PROPERTY_COPYRIGHT_INFO 0x501F
+#define MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER 0xD401
+#define MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME 0xD402
+#define MTP_DEVICE_PROPERTY_VOLUME 0xD403
+#define MTP_DEVICE_PROPERTY_SUPPORTED_FORMATS_ORDERED 0xD404
+#define MTP_DEVICE_PROPERTY_DEVICE_ICON 0xD405
+#define MTP_DEVICE_PROPERTY_PLAYBACK_RATE 0xD410
+#define MTP_DEVICE_PROPERTY_PLAYBACK_OBJECT 0xD411
+#define MTP_DEVICE_PROPERTY_PLAYBACK_CONTAINER_INDEX 0xD412
+#define MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO 0xD406
+#define MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE 0xD407
+
+// MTP Operation Codes
+#define MTP_OPERATION_GET_DEVICE_INFO 0x1001
+#define MTP_OPERATION_OPEN_SESSION 0x1002
+#define MTP_OPERATION_CLOSE_SESSION 0x1003
+#define MTP_OPERATION_GET_STORAGE_IDS 0x1004
+#define MTP_OPERATION_GET_STORAGE_INFO 0x1005
+#define MTP_OPERATION_GET_NUM_OBJECTS 0x1006
+#define MTP_OPERATION_GET_OBJECT_HANDLES 0x1007
+#define MTP_OPERATION_GET_OBJECT_INFO 0x1008
+#define MTP_OPERATION_GET_OBJECT 0x1009
+#define MTP_OPERATION_GET_THUMB 0x100A
+#define MTP_OPERATION_DELETE_OBJECT 0x100B
+#define MTP_OPERATION_SEND_OBJECT_INFO 0x100C
+#define MTP_OPERATION_SEND_OBJECT 0x100D
+#define MTP_OPERATION_INITIATE_CAPTURE 0x100E
+#define MTP_OPERATION_FORMAT_STORE 0x100F
+#define MTP_OPERATION_RESET_DEVICE 0x1010
+#define MTP_OPERATION_SELF_TEST 0x1011
+#define MTP_OPERATION_SET_OBJECT_PROTECTION 0x1012
+#define MTP_OPERATION_POWER_DOWN 0x1013
+#define MTP_OPERATION_GET_DEVICE_PROP_DESC 0x1014
+#define MTP_OPERATION_GET_DEVICE_PROP_VALUE 0x1015
+#define MTP_OPERATION_SET_DEVICE_PROP_VALUE 0x1016
+#define MTP_OPERATION_RESET_DEVICE_PROP_VALUE 0x1017
+#define MTP_OPERATION_TERMINATE_OPEN_CAPTURE 0x1018
+#define MTP_OPERATION_MOVE_OBJECT 0x1019
+#define MTP_OPERATION_COPY_OBJECT 0x101A
+#define MTP_OPERATION_GET_PARTIAL_OBJECT 0x101B
+#define MTP_OPERATION_INITIATE_OPEN_CAPTURE 0x101C
+#define MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED 0x9801
+#define MTP_OPERATION_GET_OBJECT_PROP_DESC 0x9802
+#define MTP_OPERATION_GET_OBJECT_PROP_VALUE 0x9803
+#define MTP_OPERATION_SET_OBJECT_PROP_VALUE 0x9804
+#define MTP_OPERATION_GET_OBJECT_PROP_LIST 0x9805
+#define MTP_OPERATION_SET_OBJECT_PROP_LIST 0x9806
+#define MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC 0x9807
+#define MTP_OPERATION_SEND_OBJECT_PROP_LIST 0x9808
+#define MTP_OPERATION_GET_OBJECT_REFERENCES 0x9810
+#define MTP_OPERATION_SET_OBJECT_REFERENCES 0x9811
+#define MTP_OPERATION_SKIP 0x9820
+
+// Android extensions for direct file IO
+
+// Same as GetPartialObject, but with 64 bit offset
+#define MTP_OPERATION_GET_PARTIAL_OBJECT_64 0x95C1
+// Same as GetPartialObject64, but copying host to device
+#define MTP_OPERATION_SEND_PARTIAL_OBJECT 0x95C2
+// Truncates file to 64 bit length
+#define MTP_OPERATION_TRUNCATE_OBJECT 0x95C3
+// Must be called before using SendPartialObject and TruncateObject
+#define MTP_OPERATION_BEGIN_EDIT_OBJECT 0x95C4
+// Called to commit changes made by SendPartialObject and TruncateObject
+#define MTP_OPERATION_END_EDIT_OBJECT 0x95C5
+
+// MTP Response Codes
+#define MTP_RESPONSE_UNDEFINED 0x2000
+#define MTP_RESPONSE_OK 0x2001
+#define MTP_RESPONSE_GENERAL_ERROR 0x2002
+#define MTP_RESPONSE_SESSION_NOT_OPEN 0x2003
+#define MTP_RESPONSE_INVALID_TRANSACTION_ID 0x2004
+#define MTP_RESPONSE_OPERATION_NOT_SUPPORTED 0x2005
+#define MTP_RESPONSE_PARAMETER_NOT_SUPPORTED 0x2006
+#define MTP_RESPONSE_INCOMPLETE_TRANSFER 0x2007
+#define MTP_RESPONSE_INVALID_STORAGE_ID 0x2008
+#define MTP_RESPONSE_INVALID_OBJECT_HANDLE 0x2009
+#define MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED 0x200A
+#define MTP_RESPONSE_INVALID_OBJECT_FORMAT_CODE 0x200B
+#define MTP_RESPONSE_STORAGE_FULL 0x200C
+#define MTP_RESPONSE_OBJECT_WRITE_PROTECTED 0x200D
+#define MTP_RESPONSE_STORE_READ_ONLY 0x200E
+#define MTP_RESPONSE_ACCESS_DENIED 0x200F
+#define MTP_RESPONSE_NO_THUMBNAIL_PRESENT 0x2010
+#define MTP_RESPONSE_SELF_TEST_FAILED 0x2011
+#define MTP_RESPONSE_PARTIAL_DELETION 0x2012
+#define MTP_RESPONSE_STORE_NOT_AVAILABLE 0x2013
+#define MTP_RESPONSE_SPECIFICATION_BY_FORMAT_UNSUPPORTED 0x2014
+#define MTP_RESPONSE_NO_VALID_OBJECT_INFO 0x2015
+#define MTP_RESPONSE_INVALID_CODE_FORMAT 0x2016
+#define MTP_RESPONSE_UNKNOWN_VENDOR_CODE 0x2017
+#define MTP_RESPONSE_CAPTURE_ALREADY_TERMINATED 0x2018
+#define MTP_RESPONSE_DEVICE_BUSY 0x2019
+#define MTP_RESPONSE_INVALID_PARENT_OBJECT 0x201A
+#define MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT 0x201B
+#define MTP_RESPONSE_INVALID_DEVICE_PROP_VALUE 0x201C
+#define MTP_RESPONSE_INVALID_PARAMETER 0x201D
+#define MTP_RESPONSE_SESSION_ALREADY_OPEN 0x201E
+#define MTP_RESPONSE_TRANSACTION_CANCELLED 0x201F
+#define MTP_RESPONSE_SPECIFICATION_OF_DESTINATION_UNSUPPORTED 0x2020
+#define MTP_RESPONSE_INVALID_OBJECT_PROP_CODE 0xA801
+#define MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT 0xA802
+#define MTP_RESPONSE_INVALID_OBJECT_PROP_VALUE 0xA803
+#define MTP_RESPONSE_INVALID_OBJECT_REFERENCE 0xA804
+#define MTP_RESPONSE_GROUP_NOT_SUPPORTED 0xA805
+#define MTP_RESPONSE_INVALID_DATASET 0xA806
+#define MTP_RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED 0xA807
+#define MTP_RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED 0xA808
+#define MTP_RESPONSE_OBJECT_TOO_LARGE 0xA809
+#define MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED 0xA80A
+
+// MTP Event Codes
+#define MTP_EVENT_UNDEFINED 0x4000
+#define MTP_EVENT_CANCEL_TRANSACTION 0x4001
+#define MTP_EVENT_OBJECT_ADDED 0x4002
+#define MTP_EVENT_OBJECT_REMOVED 0x4003
+#define MTP_EVENT_STORE_ADDED 0x4004
+#define MTP_EVENT_STORE_REMOVED 0x4005
+#define MTP_EVENT_DEVICE_PROP_CHANGED 0x4006
+#define MTP_EVENT_OBJECT_INFO_CHANGED 0x4007
+#define MTP_EVENT_DEVICE_INFO_CHANGED 0x4008
+#define MTP_EVENT_REQUEST_OBJECT_TRANSFER 0x4009
+#define MTP_EVENT_STORE_FULL 0x400A
+#define MTP_EVENT_DEVICE_RESET 0x400B
+#define MTP_EVENT_STORAGE_INFO_CHANGED 0x400C
+#define MTP_EVENT_CAPTURE_COMPLETE 0x400D
+#define MTP_EVENT_UNREPORTED_STATUS 0x400E
+#define MTP_EVENT_OBJECT_PROP_CHANGED 0xC801
+#define MTP_EVENT_OBJECT_PROP_DESC_CHANGED 0xC802
+#define MTP_EVENT_OBJECT_REFERENCES_CHANGED 0xC803
+
+// Storage Type
+#define MTP_STORAGE_FIXED_ROM 0x0001
+#define MTP_STORAGE_REMOVABLE_ROM 0x0002
+#define MTP_STORAGE_FIXED_RAM 0x0003
+#define MTP_STORAGE_REMOVABLE_RAM 0x0004
+
+// Storage File System
+#define MTP_STORAGE_FILESYSTEM_FLAT 0x0001
+#define MTP_STORAGE_FILESYSTEM_HIERARCHICAL 0x0002
+#define MTP_STORAGE_FILESYSTEM_DCF 0x0003
+
+// Storage Access Capability
+#define MTP_STORAGE_READ_WRITE 0x0000
+#define MTP_STORAGE_READ_ONLY_WITHOUT_DELETE 0x0001
+#define MTP_STORAGE_READ_ONLY_WITH_DELETE 0x0002
+
+// Association Type
+#define MTP_ASSOCIATION_TYPE_UNDEFINED 0x0000
+#define MTP_ASSOCIATION_TYPE_GENERIC_FOLDER 0x0001
+
+#endif // _MTP_H
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
new file mode 100644
index 0000000..257f62c
--- /dev/null
+++ b/services/audioflinger/Android.mk
@@ -0,0 +1,39 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ AudioFlinger.cpp \
+ AudioMixer.cpp.arm \
+ AudioResampler.cpp.arm \
+ AudioPolicyService.cpp \
+ ServiceUtilities.cpp
+# AudioResamplerSinc.cpp.arm
+# AudioResamplerCubic.cpp.arm
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, audio-effects) \
+ $(call include-path-for, audio-utils)
+
+# FIXME keep libmedia_native but remove libmedia after split
+LOCAL_SHARED_LIBRARIES := \
+ libaudioutils \
+ libcommon_time_client \
+ libcutils \
+ libutils \
+ libbinder \
+ libmedia \
+ libmedia_native \
+ libhardware \
+ libhardware_legacy \
+ libeffects \
+ libdl \
+ libpowermanager
+
+LOCAL_STATIC_LIBRARIES := \
+ libcpustats \
+ libmedia_helper
+
+LOCAL_MODULE:= libaudioflinger
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audioflinger/AudioBufferProvider.h b/services/audioflinger/AudioBufferProvider.h
new file mode 100644
index 0000000..43e4de7
--- /dev/null
+++ b/services/audioflinger/AudioBufferProvider.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 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_BUFFER_PROVIDER_H
+#define ANDROID_AUDIO_BUFFER_PROVIDER_H
+
+#include <utils/Errors.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class AudioBufferProvider
+{
+public:
+
+ struct Buffer {
+ Buffer() : raw(NULL), frameCount(0) { }
+ union {
+ void* raw;
+ short* i16;
+ int8_t* i8;
+ };
+ size_t frameCount;
+ };
+
+ virtual ~AudioBufferProvider() {}
+
+ // value representing an invalid presentation timestamp
+ static const int64_t kInvalidPTS = 0x7FFFFFFFFFFFFFFFLL; // <stdint.h> is too painful
+
+ // pts is the local time when the next sample yielded by getNextBuffer
+ // will be rendered.
+ // Pass kInvalidPTS if the PTS is unknown or not applicable.
+ virtual status_t getNextBuffer(Buffer* buffer, int64_t pts = kInvalidPTS) = 0;
+
+ virtual void releaseBuffer(Buffer* buffer) = 0;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_AUDIO_BUFFER_PROVIDER_H
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
new file mode 100644
index 0000000..c5ad0f5
--- /dev/null
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -0,0 +1,8144 @@
+/*
+**
+** 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_TAG "AudioFlinger"
+//#define LOG_NDEBUG 0
+
+#include <math.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <utils/String16.h>
+#include <utils/threads.h>
+#include <utils/Atomic.h>
+
+#include <cutils/bitops.h>
+#include <cutils/properties.h>
+#include <cutils/compiler.h>
+
+#undef ADD_BATTERY_DATA
+
+#ifdef ADD_BATTERY_DATA
+#include <media/IMediaPlayerService.h>
+#include <media/IMediaDeathNotifier.h>
+#endif
+
+#include <private/media/AudioTrackShared.h>
+#include <private/media/AudioEffectShared.h>
+
+#include <system/audio.h>
+#include <hardware/audio.h>
+
+#include "AudioMixer.h"
+#include "AudioFlinger.h"
+#include "ServiceUtilities.h"
+
+#include <media/EffectsFactoryApi.h>
+#include <audio_effects/effect_visualizer.h>
+#include <audio_effects/effect_ns.h>
+#include <audio_effects/effect_aec.h>
+
+#include <audio_utils/primitives.h>
+
+#include <powermanager/PowerManager.h>
+
+// #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds
+#ifdef DEBUG_CPU_USAGE
+#include <cpustats/CentralTendencyStatistics.h>
+#include <cpustats/ThreadCpuUsage.h>
+#endif
+
+#include <common_time/cc_helper.h>
+#include <common_time/local_clock.h>
+
+// ----------------------------------------------------------------------------
+
+
+namespace android {
+
+static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
+static const char kHardwareLockedString[] = "Hardware lock is taken\n";
+
+static const float MAX_GAIN = 4096.0f;
+static const uint32_t MAX_GAIN_INT = 0x1000;
+
+// retry counts for buffer fill timeout
+// 50 * ~20msecs = 1 second
+static const int8_t kMaxTrackRetries = 50;
+static const int8_t kMaxTrackStartupRetries = 50;
+// allow less retry attempts on direct output thread.
+// direct outputs can be a scarce resource in audio hardware and should
+// be released as quickly as possible.
+static const int8_t kMaxTrackRetriesDirect = 2;
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleepUs = 20000;
+
+// don't warn about blocked writes or record buffer overflows more often than this
+static const nsecs_t kWarningThrottleNs = seconds(5);
+
+// RecordThread loop sleep time upon application overrun or audio HAL read error
+static const int kRecordThreadSleepUs = 5000;
+
+// maximum time to wait for setParameters to complete
+static const nsecs_t kSetParametersTimeoutNs = seconds(2);
+
+// minimum sleep time for the mixer thread loop when tracks are active but in underrun
+static const uint32_t kMinThreadSleepTimeUs = 5000;
+// maximum divider applied to the active sleep time in the mixer thread loop
+static const uint32_t kMaxThreadSleepTimeShift = 2;
+
+nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
+
+// ----------------------------------------------------------------------------
+
+#ifdef ADD_BATTERY_DATA
+// To collect the amplifier usage
+static void addBatteryData(uint32_t params) {
+ sp<IMediaPlayerService> service = IMediaDeathNotifier::getMediaPlayerService();
+ if (service == NULL) {
+ // it already logged
+ return;
+ }
+
+ service->addBatteryData(params);
+}
+#endif
+
+static int load_audio_interface(const char *if_name, const hw_module_t **mod,
+ audio_hw_device_t **dev)
+{
+ int rc;
+
+ rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod);
+ if (rc)
+ goto out;
+
+ rc = audio_hw_device_open(*mod, dev);
+ ALOGE_IF(rc, "couldn't open audio hw device in %s.%s (%s)",
+ AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
+ if (rc)
+ goto out;
+
+ return 0;
+
+out:
+ *mod = NULL;
+ *dev = NULL;
+ return rc;
+}
+
+static const char * const audio_interfaces[] = {
+ "primary",
+ "a2dp",
+ "usb",
+};
+#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::AudioFlinger()
+ : BnAudioFlinger(),
+ mPrimaryHardwareDev(NULL),
+ mHardwareStatus(AUDIO_HW_IDLE), // see also onFirstRef()
+ mMasterVolume(1.0f),
+ mMasterVolumeSupportLvl(MVS_NONE),
+ mMasterMute(false),
+ mNextUniqueId(1),
+ mMode(AUDIO_MODE_INVALID),
+ mBtNrecIsOff(false)
+{
+}
+
+void AudioFlinger::onFirstRef()
+{
+ int rc = 0;
+
+ Mutex::Autolock _l(mLock);
+
+ /* TODO: move all this work into an Init() function */
+ char val_str[PROPERTY_VALUE_MAX] = { 0 };
+ if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
+ uint32_t int_val;
+ if (1 == sscanf(val_str, "%u", &int_val)) {
+ mStandbyTimeInNsecs = milliseconds(int_val);
+ ALOGI("Using %u mSec as standby time.", int_val);
+ } else {
+ mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
+ ALOGI("Using default %u mSec as standby time.",
+ (uint32_t)(mStandbyTimeInNsecs / 1000000));
+ }
+ }
+
+ for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
+ const hw_module_t *mod;
+ audio_hw_device_t *dev;
+
+ rc = load_audio_interface(audio_interfaces[i], &mod, &dev);
+ if (rc)
+ continue;
+
+ ALOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i],
+ mod->name, mod->id);
+ mAudioHwDevs.push(dev);
+
+ if (mPrimaryHardwareDev == NULL) {
+ mPrimaryHardwareDev = dev;
+ ALOGI("Using '%s' (%s.%s) as the primary audio interface",
+ mod->name, mod->id, audio_interfaces[i]);
+ }
+ }
+
+ if (mPrimaryHardwareDev == NULL) {
+ ALOGE("Primary audio interface not found");
+ // proceed, all later accesses to mPrimaryHardwareDev verify it's safe with initCheck()
+ }
+
+ // Currently (mPrimaryHardwareDev == NULL) == (mAudioHwDevs.size() == 0), but the way the
+ // primary HW dev is selected can change so these conditions might not always be equivalent.
+ // When that happens, re-visit all the code that assumes this.
+
+ AutoMutex lock(mHardwareLock);
+
+ // Determine the level of master volume support the primary audio HAL has,
+ // and set the initial master volume at the same time.
+ float initialVolume = 1.0;
+ mMasterVolumeSupportLvl = MVS_NONE;
+ if (0 == mPrimaryHardwareDev->init_check(mPrimaryHardwareDev)) {
+ audio_hw_device_t *dev = mPrimaryHardwareDev;
+
+ mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
+ if ((NULL != dev->get_master_volume) &&
+ (NO_ERROR == dev->get_master_volume(dev, &initialVolume))) {
+ mMasterVolumeSupportLvl = MVS_FULL;
+ } else {
+ mMasterVolumeSupportLvl = MVS_SETONLY;
+ initialVolume = 1.0;
+ }
+
+ mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+ if ((NULL == dev->set_master_volume) ||
+ (NO_ERROR != dev->set_master_volume(dev, initialVolume))) {
+ mMasterVolumeSupportLvl = MVS_NONE;
+ }
+ mHardwareStatus = AUDIO_HW_IDLE;
+ }
+
+ // Set the mode for each audio HAL, and try to set the initial volume (if
+ // supported) for all of the non-primary audio HALs.
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+
+ mHardwareStatus = AUDIO_HW_INIT;
+ rc = dev->init_check(dev);
+ mHardwareStatus = AUDIO_HW_IDLE;
+ if (rc == 0) {
+ mMode = AUDIO_MODE_NORMAL; // assigned multiple times with same value
+ mHardwareStatus = AUDIO_HW_SET_MODE;
+ dev->set_mode(dev, mMode);
+
+ if ((dev != mPrimaryHardwareDev) &&
+ (NULL != dev->set_master_volume)) {
+ mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+ dev->set_master_volume(dev, initialVolume);
+ }
+
+ mHardwareStatus = AUDIO_HW_IDLE;
+ }
+ }
+
+ mMasterVolumeSW = (MVS_NONE == mMasterVolumeSupportLvl)
+ ? initialVolume
+ : 1.0;
+ mMasterVolume = initialVolume;
+ mHardwareStatus = AUDIO_HW_IDLE;
+}
+
+AudioFlinger::~AudioFlinger()
+{
+
+ while (!mRecordThreads.isEmpty()) {
+ // closeInput() will remove first entry from mRecordThreads
+ closeInput(mRecordThreads.keyAt(0));
+ }
+ while (!mPlaybackThreads.isEmpty()) {
+ // closeOutput() will remove first entry from mPlaybackThreads
+ closeOutput(mPlaybackThreads.keyAt(0));
+ }
+
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ // no mHardwareLock needed, as there are no other references to this
+ audio_hw_device_close(mAudioHwDevs[i]);
+ }
+}
+
+audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices)
+{
+ /* first matching HW device is returned */
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ if ((dev->get_supported_devices(dev) & devices) == devices)
+ return dev;
+ }
+ return NULL;
+}
+
+status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ result.append("Clients:\n");
+ for (size_t i = 0; i < mClients.size(); ++i) {
+ sp<Client> client = mClients.valueAt(i).promote();
+ if (client != 0) {
+ snprintf(buffer, SIZE, " pid: %d\n", client->pid());
+ result.append(buffer);
+ }
+ }
+
+ result.append("Global session refs:\n");
+ result.append(" session pid count\n");
+ for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
+ AudioSessionRef *r = mAudioSessionRefs[i];
+ snprintf(buffer, SIZE, " %7d %3d %3d\n", r->mSessionid, r->mPid, r->mCnt);
+ result.append(buffer);
+ }
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+
+status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ hardware_call_state hardwareStatus = mHardwareStatus;
+
+ snprintf(buffer, SIZE, "Hardware status: %d\n"
+ "Standby Time mSec: %u\n",
+ hardwareStatus,
+ (uint32_t)(mStandbyTimeInNsecs / 1000000));
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ snprintf(buffer, SIZE, "Permission Denial: "
+ "can't dump AudioFlinger from pid=%d, uid=%d\n",
+ IPCThreadState::self()->getCallingPid(),
+ IPCThreadState::self()->getCallingUid());
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+static bool tryLock(Mutex& mutex)
+{
+ bool locked = false;
+ for (int i = 0; i < kDumpLockRetries; ++i) {
+ if (mutex.tryLock() == NO_ERROR) {
+ locked = true;
+ break;
+ }
+ usleep(kDumpLockSleepUs);
+ }
+ return locked;
+}
+
+status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
+{
+ if (!dumpAllowed()) {
+ dumpPermissionDenial(fd, args);
+ } else {
+ // get state of hardware lock
+ bool hardwareLocked = tryLock(mHardwareLock);
+ if (!hardwareLocked) {
+ String8 result(kHardwareLockedString);
+ write(fd, result.string(), result.size());
+ } else {
+ mHardwareLock.unlock();
+ }
+
+ bool locked = tryLock(mLock);
+
+ // failed to lock - AudioFlinger is probably deadlocked
+ if (!locked) {
+ String8 result(kDeadlockedString);
+ write(fd, result.string(), result.size());
+ }
+
+ dumpClients(fd, args);
+ dumpInternals(fd, args);
+
+ // dump playback threads
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ mPlaybackThreads.valueAt(i)->dump(fd, args);
+ }
+
+ // dump record threads
+ for (size_t i = 0; i < mRecordThreads.size(); i++) {
+ mRecordThreads.valueAt(i)->dump(fd, args);
+ }
+
+ // dump all hardware devs
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ dev->dump(dev, fd);
+ }
+ if (locked) mLock.unlock();
+ }
+ return NO_ERROR;
+}
+
+sp<AudioFlinger::Client> AudioFlinger::registerPid_l(pid_t pid)
+{
+ // If pid is already in the mClients wp<> map, then use that entry
+ // (for which promote() is always != 0), otherwise create a new entry and Client.
+ sp<Client> client = mClients.valueFor(pid).promote();
+ if (client == 0) {
+ client = new Client(this, pid);
+ mClients.add(pid, client);
+ }
+
+ return client;
+}
+
+// IAudioFlinger interface
+
+
+sp<IAudioTrack> AudioFlinger::createTrack(
+ pid_t pid,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ IAudioFlinger::track_flags_t flags,
+ const sp<IMemory>& sharedBuffer,
+ audio_io_handle_t output,
+ int *sessionId,
+ status_t *status)
+{
+ sp<PlaybackThread::Track> track;
+ sp<TrackHandle> trackHandle;
+ sp<Client> client;
+ status_t lStatus;
+ int lSessionId;
+
+ // client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
+ // but if someone uses binder directly they could bypass that and cause us to crash
+ if (uint32_t(streamType) >= AUDIO_STREAM_CNT) {
+ ALOGE("createTrack() invalid stream type %d", streamType);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+
+ {
+ Mutex::Autolock _l(mLock);
+ PlaybackThread *thread = checkPlaybackThread_l(output);
+ PlaybackThread *effectThread = NULL;
+ if (thread == NULL) {
+ ALOGE("unknown output thread");
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+
+ client = registerPid_l(pid);
+
+ ALOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
+ if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
+ if (mPlaybackThreads.keyAt(i) != output) {
+ // prevent same audio session on different output threads
+ uint32_t sessions = t->hasAudioSession(*sessionId);
+ if (sessions & PlaybackThread::TRACK_SESSION) {
+ ALOGE("createTrack() session ID %d already in use", *sessionId);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ // check if an effect with same session ID is waiting for a track to be created
+ if (sessions & PlaybackThread::EFFECT_SESSION) {
+ effectThread = t.get();
+ }
+ }
+ }
+ lSessionId = *sessionId;
+ } else {
+ // if no audio session id is provided, create one here
+ lSessionId = nextUniqueId();
+ if (sessionId != NULL) {
+ *sessionId = lSessionId;
+ }
+ }
+ ALOGV("createTrack() lSessionId: %d", lSessionId);
+
+ bool isTimed = (flags & IAudioFlinger::TRACK_TIMED) != 0;
+ track = thread->createTrack_l(client, streamType, sampleRate, format,
+ channelMask, frameCount, sharedBuffer, lSessionId, isTimed, &lStatus);
+
+ // move effect chain to this output thread if an effect on same session was waiting
+ // for a track to be created
+ if (lStatus == NO_ERROR && effectThread != NULL) {
+ Mutex::Autolock _dl(thread->mLock);
+ Mutex::Autolock _sl(effectThread->mLock);
+ moveEffectChain_l(lSessionId, effectThread, thread, true);
+ }
+ }
+ if (lStatus == NO_ERROR) {
+ trackHandle = new TrackHandle(track);
+ } else {
+ // remove local strong reference to Client before deleting the Track so that the Client
+ // destructor is called by the TrackBase destructor with mLock held
+ client.clear();
+ track.clear();
+ }
+
+Exit:
+ if (status != NULL) {
+ *status = lStatus;
+ }
+ return trackHandle;
+}
+
+uint32_t AudioFlinger::sampleRate(audio_io_handle_t output) const
+{
+ Mutex::Autolock _l(mLock);
+ PlaybackThread *thread = checkPlaybackThread_l(output);
+ if (thread == NULL) {
+ ALOGW("sampleRate() unknown thread %d", output);
+ return 0;
+ }
+ return thread->sampleRate();
+}
+
+int AudioFlinger::channelCount(audio_io_handle_t output) const
+{
+ Mutex::Autolock _l(mLock);
+ PlaybackThread *thread = checkPlaybackThread_l(output);
+ if (thread == NULL) {
+ ALOGW("channelCount() unknown thread %d", output);
+ return 0;
+ }
+ return thread->channelCount();
+}
+
+audio_format_t AudioFlinger::format(audio_io_handle_t output) const
+{
+ Mutex::Autolock _l(mLock);
+ PlaybackThread *thread = checkPlaybackThread_l(output);
+ if (thread == NULL) {
+ ALOGW("format() unknown thread %d", output);
+ return AUDIO_FORMAT_INVALID;
+ }
+ return thread->format();
+}
+
+size_t AudioFlinger::frameCount(audio_io_handle_t output) const
+{
+ Mutex::Autolock _l(mLock);
+ PlaybackThread *thread = checkPlaybackThread_l(output);
+ if (thread == NULL) {
+ ALOGW("frameCount() unknown thread %d", output);
+ return 0;
+ }
+ return thread->frameCount();
+}
+
+uint32_t AudioFlinger::latency(audio_io_handle_t output) const
+{
+ Mutex::Autolock _l(mLock);
+ PlaybackThread *thread = checkPlaybackThread_l(output);
+ if (thread == NULL) {
+ ALOGW("latency() unknown thread %d", output);
+ return 0;
+ }
+ return thread->latency();
+}
+
+status_t AudioFlinger::setMasterVolume(float value)
+{
+ status_t ret = initCheck();
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+
+ // check calling permissions
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+
+ float swmv = value;
+
+ // when hw supports master volume, don't scale in sw mixer
+ if (MVS_NONE != mMasterVolumeSupportLvl) {
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ AutoMutex lock(mHardwareLock);
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+
+ mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+ if (NULL != dev->set_master_volume) {
+ dev->set_master_volume(dev, value);
+ }
+ mHardwareStatus = AUDIO_HW_IDLE;
+ }
+
+ swmv = 1.0;
+ }
+
+ Mutex::Autolock _l(mLock);
+ mMasterVolume = value;
+ mMasterVolumeSW = swmv;
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++)
+ mPlaybackThreads.valueAt(i)->setMasterVolume(swmv);
+
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::setMode(audio_mode_t mode)
+{
+ status_t ret = initCheck();
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+
+ // check calling permissions
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ if (uint32_t(mode) >= AUDIO_MODE_CNT) {
+ ALOGW("Illegal value: setMode(%d)", mode);
+ return BAD_VALUE;
+ }
+
+ { // scope for the lock
+ AutoMutex lock(mHardwareLock);
+ mHardwareStatus = AUDIO_HW_SET_MODE;
+ ret = mPrimaryHardwareDev->set_mode(mPrimaryHardwareDev, mode);
+ mHardwareStatus = AUDIO_HW_IDLE;
+ }
+
+ if (NO_ERROR == ret) {
+ Mutex::Autolock _l(mLock);
+ mMode = mode;
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++)
+ mPlaybackThreads.valueAt(i)->setMode(mode);
+ }
+
+ return ret;
+}
+
+status_t AudioFlinger::setMicMute(bool state)
+{
+ status_t ret = initCheck();
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+
+ // check calling permissions
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+
+ AutoMutex lock(mHardwareLock);
+ mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
+ ret = mPrimaryHardwareDev->set_mic_mute(mPrimaryHardwareDev, state);
+ mHardwareStatus = AUDIO_HW_IDLE;
+ return ret;
+}
+
+bool AudioFlinger::getMicMute() const
+{
+ status_t ret = initCheck();
+ if (ret != NO_ERROR) {
+ return false;
+ }
+
+ bool state = AUDIO_MODE_INVALID;
+ AutoMutex lock(mHardwareLock);
+ mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
+ mPrimaryHardwareDev->get_mic_mute(mPrimaryHardwareDev, &state);
+ mHardwareStatus = AUDIO_HW_IDLE;
+ return state;
+}
+
+status_t AudioFlinger::setMasterMute(bool muted)
+{
+ // check calling permissions
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+
+ Mutex::Autolock _l(mLock);
+ // This is an optimization, so PlaybackThread doesn't have to look at the one from AudioFlinger
+ mMasterMute = muted;
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++)
+ mPlaybackThreads.valueAt(i)->setMasterMute(muted);
+
+ return NO_ERROR;
+}
+
+float AudioFlinger::masterVolume() const
+{
+ Mutex::Autolock _l(mLock);
+ return masterVolume_l();
+}
+
+float AudioFlinger::masterVolumeSW() const
+{
+ Mutex::Autolock _l(mLock);
+ return masterVolumeSW_l();
+}
+
+bool AudioFlinger::masterMute() const
+{
+ Mutex::Autolock _l(mLock);
+ return masterMute_l();
+}
+
+float AudioFlinger::masterVolume_l() const
+{
+ if (MVS_FULL == mMasterVolumeSupportLvl) {
+ float ret_val;
+ AutoMutex lock(mHardwareLock);
+
+ mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
+ ALOG_ASSERT((NULL != mPrimaryHardwareDev) &&
+ (NULL != mPrimaryHardwareDev->get_master_volume),
+ "can't get master volume");
+
+ mPrimaryHardwareDev->get_master_volume(mPrimaryHardwareDev, &ret_val);
+ mHardwareStatus = AUDIO_HW_IDLE;
+ return ret_val;
+ }
+
+ return mMasterVolume;
+}
+
+status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
+ audio_io_handle_t output)
+{
+ // check calling permissions
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ ALOGE("setStreamVolume() invalid stream %d", stream);
+ return BAD_VALUE;
+ }
+
+ AutoMutex lock(mLock);
+ PlaybackThread *thread = NULL;
+ if (output) {
+ thread = checkPlaybackThread_l(output);
+ if (thread == NULL) {
+ return BAD_VALUE;
+ }
+ }
+
+ mStreamTypes[stream].volume = value;
+
+ if (thread == NULL) {
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
+ }
+ } else {
+ thread->setStreamVolume(stream, value);
+ }
+
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
+{
+ // check calling permissions
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT ||
+ uint32_t(stream) == AUDIO_STREAM_ENFORCED_AUDIBLE) {
+ ALOGE("setStreamMute() invalid stream %d", stream);
+ return BAD_VALUE;
+ }
+
+ AutoMutex lock(mLock);
+ mStreamTypes[stream].mute = muted;
+ for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+ mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
+
+ return NO_ERROR;
+}
+
+float AudioFlinger::streamVolume(audio_stream_type_t stream, audio_io_handle_t output) const
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ return 0.0f;
+ }
+
+ AutoMutex lock(mLock);
+ float volume;
+ if (output) {
+ PlaybackThread *thread = checkPlaybackThread_l(output);
+ if (thread == NULL) {
+ return 0.0f;
+ }
+ volume = thread->streamVolume(stream);
+ } else {
+ volume = streamVolume_l(stream);
+ }
+
+ return volume;
+}
+
+bool AudioFlinger::streamMute(audio_stream_type_t stream) const
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ return true;
+ }
+
+ AutoMutex lock(mLock);
+ return streamMute_l(stream);
+}
+
+status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
+{
+ ALOGV("setParameters(): io %d, keyvalue %s, tid %d, calling pid %d",
+ ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
+ // check calling permissions
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+
+ // ioHandle == 0 means the parameters are global to the audio hardware interface
+ if (ioHandle == 0) {
+ status_t final_result = NO_ERROR;
+ {
+ AutoMutex lock(mHardwareLock);
+ mHardwareStatus = AUDIO_HW_SET_PARAMETER;
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ status_t result = dev->set_parameters(dev, keyValuePairs.string());
+ final_result = result ?: final_result;
+ }
+ mHardwareStatus = AUDIO_HW_IDLE;
+ }
+ // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
+ AudioParameter param = AudioParameter(keyValuePairs);
+ String8 value;
+ if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {
+ Mutex::Autolock _l(mLock);
+ bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);
+ if (mBtNrecIsOff != btNrecIsOff) {
+ for (size_t i = 0; i < mRecordThreads.size(); i++) {
+ sp<RecordThread> thread = mRecordThreads.valueAt(i);
+ RecordThread::RecordTrack *track = thread->track();
+ if (track != NULL) {
+ audio_devices_t device = (audio_devices_t)(
+ thread->device() & AUDIO_DEVICE_IN_ALL);
+ bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;
+ thread->setEffectSuspended(FX_IID_AEC,
+ suspend,
+ track->sessionId());
+ thread->setEffectSuspended(FX_IID_NS,
+ suspend,
+ track->sessionId());
+ }
+ }
+ mBtNrecIsOff = btNrecIsOff;
+ }
+ }
+ return final_result;
+ }
+
+ // hold a strong ref on thread in case closeOutput() or closeInput() is called
+ // and the thread is exited once the lock is released
+ sp<ThreadBase> thread;
+ {
+ Mutex::Autolock _l(mLock);
+ thread = checkPlaybackThread_l(ioHandle);
+ if (thread == NULL) {
+ thread = checkRecordThread_l(ioHandle);
+ } else if (thread == primaryPlaybackThread_l()) {
+ // indicate output device change to all input threads for pre processing
+ AudioParameter param = AudioParameter(keyValuePairs);
+ int value;
+ if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) &&
+ (value != 0)) {
+ for (size_t i = 0; i < mRecordThreads.size(); i++) {
+ mRecordThreads.valueAt(i)->setParameters(keyValuePairs);
+ }
+ }
+ }
+ }
+ if (thread != 0) {
+ return thread->setParameters(keyValuePairs);
+ }
+ return BAD_VALUE;
+}
+
+String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& keys) const
+{
+// ALOGV("getParameters() io %d, keys %s, tid %d, calling pid %d",
+// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
+
+ if (ioHandle == 0) {
+ String8 out_s8;
+
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ char *s;
+ {
+ AutoMutex lock(mHardwareLock);
+ mHardwareStatus = AUDIO_HW_GET_PARAMETER;
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ s = dev->get_parameters(dev, keys.string());
+ mHardwareStatus = AUDIO_HW_IDLE;
+ }
+ out_s8 += String8(s ? s : "");
+ free(s);
+ }
+ return out_s8;
+ }
+
+ Mutex::Autolock _l(mLock);
+
+ PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
+ if (playbackThread != NULL) {
+ return playbackThread->getParameters(keys);
+ }
+ RecordThread *recordThread = checkRecordThread_l(ioHandle);
+ if (recordThread != NULL) {
+ return recordThread->getParameters(keys);
+ }
+ return String8("");
+}
+
+size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount) const
+{
+ status_t ret = initCheck();
+ if (ret != NO_ERROR) {
+ return 0;
+ }
+
+ AutoMutex lock(mHardwareLock);
+ mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
+ size_t size = mPrimaryHardwareDev->get_input_buffer_size(mPrimaryHardwareDev, sampleRate, format, channelCount);
+ mHardwareStatus = AUDIO_HW_IDLE;
+ return size;
+}
+
+unsigned int AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const
+{
+ if (ioHandle == 0) {
+ return 0;
+ }
+
+ Mutex::Autolock _l(mLock);
+
+ RecordThread *recordThread = checkRecordThread_l(ioHandle);
+ if (recordThread != NULL) {
+ return recordThread->getInputFramesLost();
+ }
+ return 0;
+}
+
+status_t AudioFlinger::setVoiceVolume(float value)
+{
+ status_t ret = initCheck();
+ if (ret != NO_ERROR) {
+ return ret;
+ }
+
+ // check calling permissions
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+
+ AutoMutex lock(mHardwareLock);
+ mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
+ ret = mPrimaryHardwareDev->set_voice_volume(mPrimaryHardwareDev, value);
+ mHardwareStatus = AUDIO_HW_IDLE;
+
+ return ret;
+}
+
+status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
+ audio_io_handle_t output) const
+{
+ status_t status;
+
+ Mutex::Autolock _l(mLock);
+
+ PlaybackThread *playbackThread = checkPlaybackThread_l(output);
+ if (playbackThread != NULL) {
+ return playbackThread->getRenderPosition(halFrames, dspFrames);
+ }
+
+ return BAD_VALUE;
+}
+
+void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
+{
+
+ Mutex::Autolock _l(mLock);
+
+ pid_t pid = IPCThreadState::self()->getCallingPid();
+ if (mNotificationClients.indexOfKey(pid) < 0) {
+ sp<NotificationClient> notificationClient = new NotificationClient(this,
+ client,
+ pid);
+ ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
+
+ mNotificationClients.add(pid, notificationClient);
+
+ sp<IBinder> binder = client->asBinder();
+ binder->linkToDeath(notificationClient);
+
+ // the config change is always sent from playback or record threads to avoid deadlock
+ // with AudioSystem::gLock
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
+ }
+
+ for (size_t i = 0; i < mRecordThreads.size(); i++) {
+ mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
+ }
+ }
+}
+
+void AudioFlinger::removeNotificationClient(pid_t pid)
+{
+ Mutex::Autolock _l(mLock);
+
+ mNotificationClients.removeItem(pid);
+
+ ALOGV("%d died, releasing its sessions", pid);
+ size_t num = mAudioSessionRefs.size();
+ bool removed = false;
+ for (size_t i = 0; i< num; ) {
+ AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
+ ALOGV(" pid %d @ %d", ref->mPid, i);
+ if (ref->mPid == pid) {
+ ALOGV(" removing entry for pid %d session %d", pid, ref->mSessionid);
+ mAudioSessionRefs.removeAt(i);
+ delete ref;
+ removed = true;
+ num--;
+ } else {
+ i++;
+ }
+ }
+ if (removed) {
+ purgeStaleEffects_l();
+ }
+}
+
+// audioConfigChanged_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2)
+{
+ size_t size = mNotificationClients.size();
+ for (size_t i = 0; i < size; i++) {
+ mNotificationClients.valueAt(i)->audioFlingerClient()->ioConfigChanged(event, ioHandle,
+ param2);
+ }
+}
+
+// removeClient_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::removeClient_l(pid_t pid)
+{
+ ALOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
+ mClients.removeItem(pid);
+}
+
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+ uint32_t device, type_t type)
+ : Thread(false),
+ mType(type),
+ mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0),
+ // mChannelMask
+ mChannelCount(0),
+ mFrameSize(1), mFormat(AUDIO_FORMAT_INVALID),
+ mParamStatus(NO_ERROR),
+ mStandby(false), mId(id),
+ mDevice(device),
+ mDeathRecipient(new PMDeathRecipient(this))
+{
+}
+
+AudioFlinger::ThreadBase::~ThreadBase()
+{
+ mParamCond.broadcast();
+ // do not lock the mutex in destructor
+ releaseWakeLock_l();
+ if (mPowerManager != 0) {
+ sp<IBinder> binder = mPowerManager->asBinder();
+ binder->unlinkToDeath(mDeathRecipient);
+ }
+}
+
+void AudioFlinger::ThreadBase::exit()
+{
+ ALOGV("ThreadBase::exit");
+ {
+ // This lock prevents the following race in thread (uniprocessor for illustration):
+ // if (!exitPending()) {
+ // // context switch from here to exit()
+ // // exit() calls requestExit(), what exitPending() observes
+ // // exit() calls signal(), which is dropped since no waiters
+ // // context switch back from exit() to here
+ // mWaitWorkCV.wait(...);
+ // // now thread is hung
+ // }
+ AutoMutex lock(mLock);
+ requestExit();
+ mWaitWorkCV.signal();
+ }
+ // When Thread::requestExitAndWait is made virtual and this method is renamed to
+ // "virtual status_t requestExitAndWait()", replace by "return Thread::requestExitAndWait();"
+ requestExitAndWait();
+}
+
+status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
+{
+ status_t status;
+
+ ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
+ Mutex::Autolock _l(mLock);
+
+ mNewParameters.add(keyValuePairs);
+ mWaitWorkCV.signal();
+ // wait condition with timeout in case the thread loop has exited
+ // before the request could be processed
+ if (mParamCond.waitRelative(mLock, kSetParametersTimeoutNs) == NO_ERROR) {
+ status = mParamStatus;
+ mWaitWorkCV.signal();
+ } else {
+ status = TIMED_OUT;
+ }
+ return status;
+}
+
+void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
+{
+ Mutex::Autolock _l(mLock);
+ sendConfigEvent_l(event, param);
+}
+
+// sendConfigEvent_l() must be called with ThreadBase::mLock held
+void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
+{
+ ConfigEvent configEvent;
+ configEvent.mEvent = event;
+ configEvent.mParam = param;
+ mConfigEvents.add(configEvent);
+ ALOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
+ mWaitWorkCV.signal();
+}
+
+void AudioFlinger::ThreadBase::processConfigEvents()
+{
+ mLock.lock();
+ while (!mConfigEvents.isEmpty()) {
+ ALOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
+ ConfigEvent configEvent = mConfigEvents[0];
+ mConfigEvents.removeAt(0);
+ // release mLock before locking AudioFlinger mLock: lock order is always
+ // AudioFlinger then ThreadBase to avoid cross deadlock
+ mLock.unlock();
+ mAudioFlinger->mLock.lock();
+ audioConfigChanged_l(configEvent.mEvent, configEvent.mParam);
+ mAudioFlinger->mLock.unlock();
+ mLock.lock();
+ }
+ mLock.unlock();
+}
+
+status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ bool locked = tryLock(mLock);
+ if (!locked) {
+ snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
+ write(fd, buffer, strlen(buffer));
+ }
+
+ snprintf(buffer, SIZE, "io handle: %d\n", mId);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "TID: %d\n", getTid());
+ result.append(buffer);
+ snprintf(buffer, SIZE, "standby: %d\n", mStandby);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "Channel Mask: 0x%08x\n", mChannelMask);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "Format: %d\n", mFormat);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "Frame size: %u\n", mFrameSize);
+ result.append(buffer);
+
+ snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
+ result.append(buffer);
+ result.append(" Index Command");
+ for (size_t i = 0; i < mNewParameters.size(); ++i) {
+ snprintf(buffer, SIZE, "\n %02d ", i);
+ result.append(buffer);
+ result.append(mNewParameters[i]);
+ }
+
+ snprintf(buffer, SIZE, "\n\nPending config events: \n");
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Index event param\n");
+ result.append(buffer);
+ for (size_t i = 0; i < mConfigEvents.size(); i++) {
+ snprintf(buffer, SIZE, " %02d %02d %d\n", i, mConfigEvents[i].mEvent, mConfigEvents[i].mParam);
+ result.append(buffer);
+ }
+ result.append("\n");
+
+ write(fd, result.string(), result.size());
+
+ if (locked) {
+ mLock.unlock();
+ }
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
+ write(fd, buffer, strlen(buffer));
+
+ for (size_t i = 0; i < mEffectChains.size(); ++i) {
+ sp<EffectChain> chain = mEffectChains[i];
+ if (chain != 0) {
+ chain->dump(fd, args);
+ }
+ }
+ return NO_ERROR;
+}
+
+void AudioFlinger::ThreadBase::acquireWakeLock()
+{
+ Mutex::Autolock _l(mLock);
+ acquireWakeLock_l();
+}
+
+void AudioFlinger::ThreadBase::acquireWakeLock_l()
+{
+ if (mPowerManager == 0) {
+ // use checkService() to avoid blocking if power service is not up yet
+ sp<IBinder> binder =
+ defaultServiceManager()->checkService(String16("power"));
+ if (binder == 0) {
+ ALOGW("Thread %s cannot connect to the power manager service", mName);
+ } else {
+ mPowerManager = interface_cast<IPowerManager>(binder);
+ binder->linkToDeath(mDeathRecipient);
+ }
+ }
+ if (mPowerManager != 0) {
+ sp<IBinder> binder = new BBinder();
+ status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
+ binder,
+ String16(mName));
+ if (status == NO_ERROR) {
+ mWakeLockToken = binder;
+ }
+ ALOGV("acquireWakeLock_l() %s status %d", mName, status);
+ }
+}
+
+void AudioFlinger::ThreadBase::releaseWakeLock()
+{
+ Mutex::Autolock _l(mLock);
+ releaseWakeLock_l();
+}
+
+void AudioFlinger::ThreadBase::releaseWakeLock_l()
+{
+ if (mWakeLockToken != 0) {
+ ALOGV("releaseWakeLock_l() %s", mName);
+ if (mPowerManager != 0) {
+ mPowerManager->releaseWakeLock(mWakeLockToken, 0);
+ }
+ mWakeLockToken.clear();
+ }
+}
+
+void AudioFlinger::ThreadBase::clearPowerManager()
+{
+ Mutex::Autolock _l(mLock);
+ releaseWakeLock_l();
+ mPowerManager.clear();
+}
+
+void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who)
+{
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ thread->clearPowerManager();
+ }
+ ALOGW("power manager service died !!!");
+}
+
+void AudioFlinger::ThreadBase::setEffectSuspended(
+ const effect_uuid_t *type, bool suspend, int sessionId)
+{
+ Mutex::Autolock _l(mLock);
+ setEffectSuspended_l(type, suspend, sessionId);
+}
+
+void AudioFlinger::ThreadBase::setEffectSuspended_l(
+ const effect_uuid_t *type, bool suspend, int sessionId)
+{
+ sp<EffectChain> chain = getEffectChain_l(sessionId);
+ if (chain != 0) {
+ if (type != NULL) {
+ chain->setEffectSuspended_l(type, suspend);
+ } else {
+ chain->setEffectSuspendedAll_l(suspend);
+ }
+ }
+
+ updateSuspendedSessions_l(type, suspend, sessionId);
+}
+
+void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain)
+{
+ ssize_t index = mSuspendedSessions.indexOfKey(chain->sessionId());
+ if (index < 0) {
+ return;
+ }
+
+ KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects =
+ mSuspendedSessions.editValueAt(index);
+
+ for (size_t i = 0; i < sessionEffects.size(); i++) {
+ sp<SuspendedSessionDesc> desc = sessionEffects.valueAt(i);
+ for (int j = 0; j < desc->mRefCount; j++) {
+ if (sessionEffects.keyAt(i) == EffectChain::kKeyForSuspendAll) {
+ chain->setEffectSuspendedAll_l(true);
+ } else {
+ ALOGV("checkSuspendOnAddEffectChain_l() suspending effects %08x",
+ desc->mType.timeLow);
+ chain->setEffectSuspended_l(&desc->mType, true);
+ }
+ }
+ }
+}
+
+void AudioFlinger::ThreadBase::updateSuspendedSessions_l(const effect_uuid_t *type,
+ bool suspend,
+ int sessionId)
+{
+ ssize_t index = mSuspendedSessions.indexOfKey(sessionId);
+
+ KeyedVector <int, sp<SuspendedSessionDesc> > sessionEffects;
+
+ if (suspend) {
+ if (index >= 0) {
+ sessionEffects = mSuspendedSessions.editValueAt(index);
+ } else {
+ mSuspendedSessions.add(sessionId, sessionEffects);
+ }
+ } else {
+ if (index < 0) {
+ return;
+ }
+ sessionEffects = mSuspendedSessions.editValueAt(index);
+ }
+
+
+ int key = EffectChain::kKeyForSuspendAll;
+ if (type != NULL) {
+ key = type->timeLow;
+ }
+ index = sessionEffects.indexOfKey(key);
+
+ sp<SuspendedSessionDesc> desc;
+ if (suspend) {
+ if (index >= 0) {
+ desc = sessionEffects.valueAt(index);
+ } else {
+ desc = new SuspendedSessionDesc();
+ if (type != NULL) {
+ memcpy(&desc->mType, type, sizeof(effect_uuid_t));
+ }
+ sessionEffects.add(key, desc);
+ ALOGV("updateSuspendedSessions_l() suspend adding effect %08x", key);
+ }
+ desc->mRefCount++;
+ } else {
+ if (index < 0) {
+ return;
+ }
+ desc = sessionEffects.valueAt(index);
+ if (--desc->mRefCount == 0) {
+ ALOGV("updateSuspendedSessions_l() restore removing effect %08x", key);
+ sessionEffects.removeItemsAt(index);
+ if (sessionEffects.isEmpty()) {
+ ALOGV("updateSuspendedSessions_l() restore removing session %d",
+ sessionId);
+ mSuspendedSessions.removeItem(sessionId);
+ }
+ }
+ }
+ if (!sessionEffects.isEmpty()) {
+ mSuspendedSessions.replaceValueFor(sessionId, sessionEffects);
+ }
+}
+
+void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
+ bool enabled,
+ int sessionId)
+{
+ Mutex::Autolock _l(mLock);
+ checkSuspendOnEffectEnabled_l(effect, enabled, sessionId);
+}
+
+void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
+ bool enabled,
+ int sessionId)
+{
+ if (mType != RECORD) {
+ // suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
+ // another session. This gives the priority to well behaved effect control panels
+ // and applications not using global effects.
+ if (sessionId != AUDIO_SESSION_OUTPUT_MIX) {
+ setEffectSuspended_l(NULL, enabled, AUDIO_SESSION_OUTPUT_MIX);
+ }
+ }
+
+ sp<EffectChain> chain = getEffectChain_l(sessionId);
+ if (chain != 0) {
+ chain->checkSuspendOnEffectEnabled(effect, enabled);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
+ AudioStreamOut* output,
+ audio_io_handle_t id,
+ uint32_t device,
+ type_t type)
+ : ThreadBase(audioFlinger, id, device, type),
+ mMixBuffer(NULL), mSuspended(0), mBytesWritten(0),
+ // Assumes constructor is called by AudioFlinger with it's mLock held,
+ // but it would be safer to explicitly pass initial masterMute as parameter
+ mMasterMute(audioFlinger->masterMute_l()),
+ // mStreamTypes[] initialized in constructor body
+ mOutput(output),
+ // Assumes constructor is called by AudioFlinger with it's mLock held,
+ // but it would be safer to explicitly pass initial masterVolume as parameter
+ mMasterVolume(audioFlinger->masterVolumeSW_l()),
+ mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
+ mMixerStatus(MIXER_IDLE),
+ mPrevMixerStatus(MIXER_IDLE),
+ standbyDelay(AudioFlinger::mStandbyTimeInNsecs)
+{
+ snprintf(mName, kNameLength, "AudioOut_%X", id);
+
+ readOutputParameters();
+
+ // mStreamTypes[AUDIO_STREAM_CNT] is initialized by stream_type_t default constructor
+ // There is no AUDIO_STREAM_MIN, and ++ operator does not compile
+ for (audio_stream_type_t stream = (audio_stream_type_t) 0; stream < AUDIO_STREAM_CNT;
+ stream = (audio_stream_type_t) (stream + 1)) {
+ mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);
+ mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
+ // initialized by stream_type_t default constructor
+ // mStreamTypes[stream].valid = true;
+ }
+ // mStreamTypes[AUDIO_STREAM_CNT] exists but isn't explicitly initialized here,
+ // because mAudioFlinger doesn't have one to copy from
+}
+
+AudioFlinger::PlaybackThread::~PlaybackThread()
+{
+ delete [] mMixBuffer;
+}
+
+status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
+{
+ dumpInternals(fd, args);
+ dumpTracks(fd, args);
+ dumpEffectChains(fd, args);
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
+ result.append(buffer);
+ result.append(" Name Clien Typ Fmt Chn mask Session Buf S M F SRate LeftV RighV Serv User Main buf Aux Buf\n");
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ sp<Track> track = mTracks[i];
+ if (track != 0) {
+ track->dump(buffer, SIZE);
+ result.append(buffer);
+ }
+ }
+
+ snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
+ result.append(buffer);
+ result.append(" Name Clien Typ Fmt Chn mask Session Buf S M F SRate LeftV RighV Serv User Main buf Aux Buf\n");
+ for (size_t i = 0; i < mActiveTracks.size(); ++i) {
+ sp<Track> track = mActiveTracks[i].promote();
+ if (track != 0) {
+ track->dump(buffer, SIZE);
+ result.append(buffer);
+ }
+ }
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
+ result.append(buffer);
+ snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+
+ dumpBase(fd, args);
+
+ return NO_ERROR;
+}
+
+// Thread virtuals
+status_t AudioFlinger::PlaybackThread::readyToRun()
+{
+ status_t status = initCheck();
+ if (status == NO_ERROR) {
+ ALOGI("AudioFlinger's thread %p ready to run", this);
+ } else {
+ ALOGE("No working audio driver found.");
+ }
+ return status;
+}
+
+void AudioFlinger::PlaybackThread::onFirstRef()
+{
+ run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
+}
+
+// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
+sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
+ const sp<AudioFlinger::Client>& client,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ const sp<IMemory>& sharedBuffer,
+ int sessionId,
+ bool isTimed,
+ status_t *status)
+{
+ sp<Track> track;
+ status_t lStatus;
+
+ if (mType == DIRECT) {
+ if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
+ if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
+ ALOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelMask 0x%08x \""
+ "for output %p with format %d",
+ sampleRate, format, channelMask, mOutput, mFormat);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ }
+ } else {
+ // Resampler implementation limits input sampling rate to 2 x output sampling rate.
+ if (sampleRate > mSampleRate*2) {
+ ALOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ }
+
+ lStatus = initCheck();
+ if (lStatus != NO_ERROR) {
+ ALOGE("Audio driver not initialized.");
+ goto Exit;
+ }
+
+ { // scope for mLock
+ Mutex::Autolock _l(mLock);
+
+ // all tracks in same audio session must share the same routing strategy otherwise
+ // conflicts will happen when tracks are moved from one output to another by audio policy
+ // manager
+ uint32_t strategy = AudioSystem::getStrategyForStream(streamType);
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ sp<Track> t = mTracks[i];
+ if (t != 0 && !t->isOutputTrack()) {
+ uint32_t actual = AudioSystem::getStrategyForStream(t->streamType());
+ if (sessionId == t->sessionId() && strategy != actual) {
+ ALOGE("createTrack_l() mismatched strategy; expected %u but found %u",
+ strategy, actual);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ }
+ }
+
+ if (!isTimed) {
+ track = new Track(this, client, streamType, sampleRate, format,
+ channelMask, frameCount, sharedBuffer, sessionId);
+ } else {
+ track = TimedTrack::create(this, client, streamType, sampleRate, format,
+ channelMask, frameCount, sharedBuffer, sessionId);
+ }
+ if (track == NULL || track->getCblk() == NULL || track->name() < 0) {
+ lStatus = NO_MEMORY;
+ goto Exit;
+ }
+ mTracks.add(track);
+
+ sp<EffectChain> chain = getEffectChain_l(sessionId);
+ if (chain != 0) {
+ ALOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
+ track->setMainBuffer(chain->inBuffer());
+ chain->setStrategy(AudioSystem::getStrategyForStream(track->streamType()));
+ chain->incTrackCnt();
+ }
+
+ // invalidate track immediately if the stream type was moved to another thread since
+ // createTrack() was called by the client process.
+ if (!mStreamTypes[streamType].valid) {
+ ALOGW("createTrack_l() on thread %p: invalidating track on stream %d",
+ this, streamType);
+ android_atomic_or(CBLK_INVALID_ON, &track->mCblk->flags);
+ }
+ }
+ lStatus = NO_ERROR;
+
+Exit:
+ if (status) {
+ *status = lStatus;
+ }
+ return track;
+}
+
+uint32_t AudioFlinger::PlaybackThread::latency() const
+{
+ Mutex::Autolock _l(mLock);
+ if (initCheck() == NO_ERROR) {
+ return mOutput->stream->get_latency(mOutput->stream);
+ } else {
+ return 0;
+ }
+}
+
+void AudioFlinger::PlaybackThread::setMasterVolume(float value)
+{
+ Mutex::Autolock _l(mLock);
+ mMasterVolume = value;
+}
+
+void AudioFlinger::PlaybackThread::setMasterMute(bool muted)
+{
+ Mutex::Autolock _l(mLock);
+ setMasterMute_l(muted);
+}
+
+void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
+{
+ Mutex::Autolock _l(mLock);
+ mStreamTypes[stream].volume = value;
+}
+
+void AudioFlinger::PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
+{
+ Mutex::Autolock _l(mLock);
+ mStreamTypes[stream].mute = muted;
+}
+
+float AudioFlinger::PlaybackThread::streamVolume(audio_stream_type_t stream) const
+{
+ Mutex::Autolock _l(mLock);
+ return mStreamTypes[stream].volume;
+}
+
+// addTrack_l() must be called with ThreadBase::mLock held
+status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
+{
+ status_t status = ALREADY_EXISTS;
+
+ // set retry count for buffer fill
+ track->mRetryCount = kMaxTrackStartupRetries;
+ if (mActiveTracks.indexOf(track) < 0) {
+ // the track is newly added, make sure it fills up all its
+ // buffers before playing. This is to ensure the client will
+ // effectively get the latency it requested.
+ track->mFillingUpStatus = Track::FS_FILLING;
+ track->mResetDone = false;
+ mActiveTracks.add(track);
+ if (track->mainBuffer() != mMixBuffer) {
+ sp<EffectChain> chain = getEffectChain_l(track->sessionId());
+ if (chain != 0) {
+ ALOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), track->sessionId());
+ chain->incActiveTrackCnt();
+ }
+ }
+
+ status = NO_ERROR;
+ }
+
+ ALOGV("mWaitWorkCV.broadcast");
+ mWaitWorkCV.broadcast();
+
+ return status;
+}
+
+// destroyTrack_l() must be called with ThreadBase::mLock held
+void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
+{
+ track->mState = TrackBase::TERMINATED;
+ if (mActiveTracks.indexOf(track) < 0) {
+ removeTrack_l(track);
+ }
+}
+
+void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track)
+{
+ mTracks.remove(track);
+ deleteTrackName_l(track->name());
+ sp<EffectChain> chain = getEffectChain_l(track->sessionId());
+ if (chain != 0) {
+ chain->decTrackCnt();
+ }
+}
+
+String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
+{
+ String8 out_s8 = String8("");
+ char *s;
+
+ Mutex::Autolock _l(mLock);
+ if (initCheck() != NO_ERROR) {
+ return out_s8;
+ }
+
+ s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
+ out_s8 = String8(s);
+ free(s);
+ return out_s8;
+}
+
+// audioConfigChanged_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
+ AudioSystem::OutputDescriptor desc;
+ void *param2 = NULL;
+
+ ALOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
+
+ switch (event) {
+ case AudioSystem::OUTPUT_OPENED:
+ case AudioSystem::OUTPUT_CONFIG_CHANGED:
+ desc.channels = mChannelMask;
+ desc.samplingRate = mSampleRate;
+ desc.format = mFormat;
+ desc.frameCount = mFrameCount;
+ desc.latency = latency();
+ param2 = &desc;
+ break;
+
+ case AudioSystem::STREAM_CONFIG_CHANGED:
+ param2 = &param;
+ case AudioSystem::OUTPUT_CLOSED:
+ default:
+ break;
+ }
+ mAudioFlinger->audioConfigChanged_l(event, mId, param2);
+}
+
+void AudioFlinger::PlaybackThread::readOutputParameters()
+{
+ mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
+ mChannelMask = mOutput->stream->common.get_channels(&mOutput->stream->common);
+ mChannelCount = (uint16_t)popcount(mChannelMask);
+ mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
+ mFrameSize = audio_stream_frame_size(&mOutput->stream->common);
+ mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize;
+
+ // FIXME - Current mixer implementation only supports stereo output: Always
+ // Allocate a stereo buffer even if HW output is mono.
+ delete[] mMixBuffer;
+ mMixBuffer = new int16_t[mFrameCount * 2];
+ memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
+
+ // force reconfiguration of effect chains and engines to take new buffer size and audio
+ // parameters into account
+ // Note that mLock is not held when readOutputParameters() is called from the constructor
+ // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
+ // matter.
+ // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
+ Vector< sp<EffectChain> > effectChains = mEffectChains;
+ for (size_t i = 0; i < effectChains.size(); i ++) {
+ mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
+ }
+}
+
+status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
+{
+ if (halFrames == NULL || dspFrames == NULL) {
+ return BAD_VALUE;
+ }
+ Mutex::Autolock _l(mLock);
+ if (initCheck() != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+ *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
+
+ return mOutput->stream->get_render_position(mOutput->stream, dspFrames);
+}
+
+uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
+{
+ Mutex::Autolock _l(mLock);
+ uint32_t result = 0;
+ if (getEffectChain_l(sessionId) != 0) {
+ result = EFFECT_SESSION;
+ }
+
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ sp<Track> track = mTracks[i];
+ if (sessionId == track->sessionId() &&
+ !(track->mCblk->flags & CBLK_INVALID_MSK)) {
+ result |= TRACK_SESSION;
+ break;
+ }
+ }
+
+ return result;
+}
+
+uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
+{
+ // session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
+ // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
+ if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
+ return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
+ }
+ for (size_t i = 0; i < mTracks.size(); i++) {
+ sp<Track> track = mTracks[i];
+ if (sessionId == track->sessionId() &&
+ !(track->mCblk->flags & CBLK_INVALID_MSK)) {
+ return AudioSystem::getStrategyForStream(track->streamType());
+ }
+ }
+ return AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
+}
+
+
+AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::getOutput() const
+{
+ Mutex::Autolock _l(mLock);
+ return mOutput;
+}
+
+AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
+{
+ Mutex::Autolock _l(mLock);
+ AudioStreamOut *output = mOutput;
+ mOutput = NULL;
+ return output;
+}
+
+// this method must always be called either with ThreadBase mLock held or inside the thread loop
+audio_stream_t* AudioFlinger::PlaybackThread::stream()
+{
+ if (mOutput == NULL) {
+ return NULL;
+ }
+ return &mOutput->stream->common;
+}
+
+uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs()
+{
+ // A2DP output latency is not due only to buffering capacity. It also reflects encoding,
+ // decoding and transfer time. So sleeping for half of the latency would likely cause
+ // underruns
+ if (audio_is_a2dp_device((audio_devices_t)mDevice)) {
+ return (uint32_t)((uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000);
+ } else {
+ return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
+ audio_io_handle_t id, uint32_t device, type_t type)
+ : PlaybackThread(audioFlinger, output, id, device, type)
+{
+ mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
+ // FIXME - Current mixer implementation only supports stereo output
+ if (mChannelCount == 1) {
+ ALOGE("Invalid audio hardware channel count");
+ }
+}
+
+AudioFlinger::MixerThread::~MixerThread()
+{
+ delete mAudioMixer;
+}
+
+class CpuStats {
+public:
+ CpuStats();
+ void sample(const String8 &title);
+#ifdef DEBUG_CPU_USAGE
+private:
+ ThreadCpuUsage mCpuUsage; // instantaneous thread CPU usage in wall clock ns
+ CentralTendencyStatistics mWcStats; // statistics on thread CPU usage in wall clock ns
+
+ CentralTendencyStatistics mHzStats; // statistics on thread CPU usage in cycles
+
+ int mCpuNum; // thread's current CPU number
+ int mCpukHz; // frequency of thread's current CPU in kHz
+#endif
+};
+
+CpuStats::CpuStats()
+#ifdef DEBUG_CPU_USAGE
+ : mCpuNum(-1), mCpukHz(-1)
+#endif
+{
+}
+
+void CpuStats::sample(const String8 &title) {
+#ifdef DEBUG_CPU_USAGE
+ // get current thread's delta CPU time in wall clock ns
+ double wcNs;
+ bool valid = mCpuUsage.sampleAndEnable(wcNs);
+
+ // record sample for wall clock statistics
+ if (valid) {
+ mWcStats.sample(wcNs);
+ }
+
+ // get the current CPU number
+ int cpuNum = sched_getcpu();
+
+ // get the current CPU frequency in kHz
+ int cpukHz = mCpuUsage.getCpukHz(cpuNum);
+
+ // check if either CPU number or frequency changed
+ if (cpuNum != mCpuNum || cpukHz != mCpukHz) {
+ mCpuNum = cpuNum;
+ mCpukHz = cpukHz;
+ // ignore sample for purposes of cycles
+ valid = false;
+ }
+
+ // if no change in CPU number or frequency, then record sample for cycle statistics
+ if (valid && mCpukHz > 0) {
+ double cycles = wcNs * cpukHz * 0.000001;
+ mHzStats.sample(cycles);
+ }
+
+ unsigned n = mWcStats.n();
+ // mCpuUsage.elapsed() is expensive, so don't call it every loop
+ if ((n & 127) == 1) {
+ long long elapsed = mCpuUsage.elapsed();
+ if (elapsed >= DEBUG_CPU_USAGE * 1000000000LL) {
+ double perLoop = elapsed / (double) n;
+ double perLoop100 = perLoop * 0.01;
+ double perLoop1k = perLoop * 0.001;
+ double mean = mWcStats.mean();
+ double stddev = mWcStats.stddev();
+ double minimum = mWcStats.minimum();
+ double maximum = mWcStats.maximum();
+ double meanCycles = mHzStats.mean();
+ double stddevCycles = mHzStats.stddev();
+ double minCycles = mHzStats.minimum();
+ double maxCycles = mHzStats.maximum();
+ mCpuUsage.resetElapsed();
+ mWcStats.reset();
+ mHzStats.reset();
+ ALOGD("CPU usage for %s over past %.1f secs\n"
+ " (%u mixer loops at %.1f mean ms per loop):\n"
+ " us per mix loop: mean=%.0f stddev=%.0f min=%.0f max=%.0f\n"
+ " %% of wall: mean=%.1f stddev=%.1f min=%.1f max=%.1f\n"
+ " MHz: mean=%.1f, stddev=%.1f, min=%.1f max=%.1f",
+ title.string(),
+ elapsed * .000000001, n, perLoop * .000001,
+ mean * .001,
+ stddev * .001,
+ minimum * .001,
+ maximum * .001,
+ mean / perLoop100,
+ stddev / perLoop100,
+ minimum / perLoop100,
+ maximum / perLoop100,
+ meanCycles / perLoop1k,
+ stddevCycles / perLoop1k,
+ minCycles / perLoop1k,
+ maxCycles / perLoop1k);
+
+ }
+ }
+#endif
+};
+
+void AudioFlinger::PlaybackThread::checkSilentMode_l()
+{
+ if (!mMasterMute) {
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("ro.audio.silent", value, "0") > 0) {
+ char *endptr;
+ unsigned long ul = strtoul(value, &endptr, 0);
+ if (*endptr == '\0' && ul != 0) {
+ ALOGD("Silence is golden");
+ // The setprop command will not allow a property to be changed after
+ // the first time it is set, so we don't have to worry about un-muting.
+ setMasterMute_l(true);
+ }
+ }
+ }
+}
+
+bool AudioFlinger::PlaybackThread::threadLoop()
+{
+ Vector< sp<Track> > tracksToRemove;
+
+ standbyTime = systemTime();
+
+ // MIXER
+ nsecs_t lastWarning = 0;
+if (mType == MIXER) {
+ longStandbyExit = false;
+}
+
+ // DUPLICATING
+ // FIXME could this be made local to while loop?
+ writeFrames = 0;
+
+ cacheParameters_l();
+ sleepTime = idleSleepTime;
+
+if (mType == MIXER) {
+ sleepTimeShift = 0;
+}
+
+ CpuStats cpuStats;
+ const String8 myName(String8::format("thread %p type %d TID %d", this, mType, gettid()));
+
+ acquireWakeLock();
+
+ while (!exitPending())
+ {
+ cpuStats.sample(myName);
+
+ Vector< sp<EffectChain> > effectChains;
+
+ processConfigEvents();
+
+ { // scope for mLock
+
+ Mutex::Autolock _l(mLock);
+
+ if (checkForNewParameters_l()) {
+ cacheParameters_l();
+ }
+
+ saveOutputTracks();
+
+ // put audio hardware into standby after short delay
+ if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
+ mSuspended > 0)) {
+ if (!mStandby) {
+
+ threadLoop_standby();
+
+ mStandby = true;
+ mBytesWritten = 0;
+ }
+
+ if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
+ // we're about to wait, flush the binder command buffer
+ IPCThreadState::self()->flushCommands();
+
+ clearOutputTracks();
+
+ if (exitPending()) break;
+
+ releaseWakeLock_l();
+ // wait until we have something to do...
+ ALOGV("%s going to sleep", myName.string());
+ mWaitWorkCV.wait(mLock);
+ ALOGV("%s waking up", myName.string());
+ acquireWakeLock_l();
+
+ mPrevMixerStatus = MIXER_IDLE;
+
+ checkSilentMode_l();
+
+ standbyTime = systemTime() + standbyDelay;
+ sleepTime = idleSleepTime;
+ if (mType == MIXER) {
+ sleepTimeShift = 0;
+ }
+
+ continue;
+ }
+ }
+
+ mixer_state newMixerStatus = prepareTracks_l(&tracksToRemove);
+ // Shift in the new status; this could be a queue if it's
+ // useful to filter the mixer status over several cycles.
+ mPrevMixerStatus = mMixerStatus;
+ mMixerStatus = newMixerStatus;
+
+ // prevent any changes in effect chain list and in each effect chain
+ // during mixing and effect process as the audio buffers could be deleted
+ // or modified if an effect is created or deleted
+ lockEffectChains_l(effectChains);
+ }
+
+ if (CC_LIKELY(mMixerStatus == MIXER_TRACKS_READY)) {
+ threadLoop_mix();
+ } else {
+ threadLoop_sleepTime();
+ }
+
+ if (mSuspended > 0) {
+ sleepTime = suspendSleepTimeUs();
+ }
+
+ // only process effects if we're going to write
+ if (sleepTime == 0) {
+ for (size_t i = 0; i < effectChains.size(); i ++) {
+ effectChains[i]->process_l();
+ }
+ }
+
+ // enable changes in effect chain
+ unlockEffectChains(effectChains);
+
+ // sleepTime == 0 means we must write to audio hardware
+ if (sleepTime == 0) {
+
+ threadLoop_write();
+
+if (mType == MIXER) {
+ // write blocked detection
+ nsecs_t now = systemTime();
+ nsecs_t delta = now - mLastWriteTime;
+ if (!mStandby && delta > maxPeriod) {
+ mNumDelayedWrites++;
+ if ((now - lastWarning) > kWarningThrottleNs) {
+ ALOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
+ ns2ms(delta), mNumDelayedWrites, this);
+ lastWarning = now;
+ }
+ // FIXME this is broken: longStandbyExit should be handled out of the if() and with
+ // a different threshold. Or completely removed for what it is worth anyway...
+ if (mStandby) {
+ longStandbyExit = true;
+ }
+ }
+}
+
+ mStandby = false;
+ } else {
+ usleep(sleepTime);
+ }
+
+ // finally let go of removed track(s), without the lock held
+ // since we can't guarantee the destructors won't acquire that
+ // same lock.
+ tracksToRemove.clear();
+
+ // FIXME I don't understand the need for this here;
+ // it was in the original code but maybe the
+ // assignment in saveOutputTracks() makes this unnecessary?
+ clearOutputTracks();
+
+ // Effect chains will be actually deleted here if they were removed from
+ // mEffectChains list during mixing or effects processing
+ effectChains.clear();
+
+ // FIXME Note that the above .clear() is no longer necessary since effectChains
+ // is now local to this block, but will keep it for now (at least until merge done).
+ }
+
+if (mType == MIXER || mType == DIRECT) {
+ // put output stream into standby mode
+ if (!mStandby) {
+ mOutput->stream->common.standby(&mOutput->stream->common);
+ }
+}
+if (mType == DUPLICATING) {
+ // for DuplicatingThread, standby mode is handled by the outputTracks
+}
+
+ releaseWakeLock();
+
+ ALOGV("Thread %p type %d exiting", this, mType);
+ return false;
+}
+
+// shared by MIXER and DIRECT, overridden by DUPLICATING
+void AudioFlinger::PlaybackThread::threadLoop_write()
+{
+ // FIXME rewrite to reduce number of system calls
+ mLastWriteTime = systemTime();
+ mInWrite = true;
+ mBytesWritten += mixBufferSize;
+ int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
+ if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
+ mNumWrites++;
+ mInWrite = false;
+}
+
+// shared by MIXER and DIRECT, overridden by DUPLICATING
+void AudioFlinger::PlaybackThread::threadLoop_standby()
+{
+ ALOGV("Audio hardware entering standby, mixer %p, suspend count %u", this, mSuspended);
+ mOutput->stream->common.standby(&mOutput->stream->common);
+}
+
+void AudioFlinger::MixerThread::threadLoop_mix()
+{
+ // obtain the presentation timestamp of the next output buffer
+ int64_t pts;
+ status_t status = INVALID_OPERATION;
+
+ if (NULL != mOutput->stream->get_next_write_timestamp) {
+ status = mOutput->stream->get_next_write_timestamp(
+ mOutput->stream, &pts);
+ }
+
+ if (status != NO_ERROR) {
+ pts = AudioBufferProvider::kInvalidPTS;
+ }
+
+ // mix buffers...
+ mAudioMixer->process(pts);
+ // increase sleep time progressively when application underrun condition clears.
+ // Only increase sleep time if the mixer is ready for two consecutive times to avoid
+ // that a steady state of alternating ready/not ready conditions keeps the sleep time
+ // such that we would underrun the audio HAL.
+ if ((sleepTime == 0) && (sleepTimeShift > 0)) {
+ sleepTimeShift--;
+ }
+ sleepTime = 0;
+ standbyTime = systemTime() + standbyDelay;
+ //TODO: delay standby when effects have a tail
+}
+
+void AudioFlinger::MixerThread::threadLoop_sleepTime()
+{
+ // If no tracks are ready, sleep once for the duration of an output
+ // buffer size, then write 0s to the output
+ if (sleepTime == 0) {
+ if (mMixerStatus == MIXER_TRACKS_ENABLED) {
+ sleepTime = activeSleepTime >> sleepTimeShift;
+ if (sleepTime < kMinThreadSleepTimeUs) {
+ sleepTime = kMinThreadSleepTimeUs;
+ }
+ // reduce sleep time in case of consecutive application underruns to avoid
+ // starving the audio HAL. As activeSleepTimeUs() is larger than a buffer
+ // duration we would end up writing less data than needed by the audio HAL if
+ // the condition persists.
+ if (sleepTimeShift < kMaxThreadSleepTimeShift) {
+ sleepTimeShift++;
+ }
+ } else {
+ sleepTime = idleSleepTime;
+ }
+ } else if (mBytesWritten != 0 ||
+ (mMixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
+ memset (mMixBuffer, 0, mixBufferSize);
+ sleepTime = 0;
+ ALOGV_IF((mBytesWritten == 0 && (mMixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
+ }
+ // TODO add standby time extension fct of effect tail
+}
+
+// prepareTracks_l() must be called with ThreadBase::mLock held
+AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
+ Vector< sp<Track> > *tracksToRemove)
+{
+
+ mixer_state mixerStatus = MIXER_IDLE;
+ // find out which tracks need to be processed
+ size_t count = mActiveTracks.size();
+ size_t mixedTracks = 0;
+ size_t tracksWithEffect = 0;
+
+ float masterVolume = mMasterVolume;
+ bool masterMute = mMasterMute;
+
+ if (masterMute) {
+ masterVolume = 0;
+ }
+ // Delegate master volume control to effect in output mix effect chain if needed
+ sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
+ if (chain != 0) {
+ uint32_t v = (uint32_t)(masterVolume * (1 << 24));
+ chain->setVolume_l(&v, &v);
+ masterVolume = (float)((v + (1 << 23)) >> 24);
+ chain.clear();
+ }
+
+ for (size_t i=0 ; i<count ; i++) {
+ sp<Track> t = mActiveTracks[i].promote();
+ if (t == 0) continue;
+
+ // this const just means the local variable doesn't change
+ Track* const track = t.get();
+ audio_track_cblk_t* cblk = track->cblk();
+
+ // The first time a track is added we wait
+ // for all its buffers to be filled before processing it
+ int name = track->name();
+ // make sure that we have enough frames to mix one full buffer.
+ // enforce this condition only once to enable draining the buffer in case the client
+ // app does not call stop() and relies on underrun to stop:
+ // hence the test on (mPrevMixerStatus == MIXER_TRACKS_READY) meaning the track was mixed
+ // during last round
+ uint32_t minFrames = 1;
+ if (!track->isStopped() && !track->isPausing() &&
+ (mPrevMixerStatus == MIXER_TRACKS_READY)) {
+ if (t->sampleRate() == (int)mSampleRate) {
+ minFrames = mFrameCount;
+ } else {
+ // +1 for rounding and +1 for additional sample needed for interpolation
+ minFrames = (mFrameCount * t->sampleRate()) / mSampleRate + 1 + 1;
+ // add frames already consumed but not yet released by the resampler
+ // because cblk->framesReady() will include these frames
+ minFrames += mAudioMixer->getUnreleasedFrames(track->name());
+ // the minimum track buffer size is normally twice the number of frames necessary
+ // to fill one buffer and the resampler should not leave more than one buffer worth
+ // of unreleased frames after each pass, but just in case...
+ ALOG_ASSERT(minFrames <= cblk->frameCount);
+ }
+ }
+ if ((track->framesReady() >= minFrames) && track->isReady() &&
+ !track->isPaused() && !track->isTerminated())
+ {
+ //ALOGV("track %d u=%08x, s=%08x [OK] on thread %p", name, cblk->user, cblk->server, this);
+
+ mixedTracks++;
+
+ // track->mainBuffer() != mMixBuffer means there is an effect chain
+ // connected to the track
+ chain.clear();
+ if (track->mainBuffer() != mMixBuffer) {
+ chain = getEffectChain_l(track->sessionId());
+ // Delegate volume control to effect in track effect chain if needed
+ if (chain != 0) {
+ tracksWithEffect++;
+ } else {
+ ALOGW("prepareTracks_l(): track %d attached to effect but no chain found on session %d",
+ name, track->sessionId());
+ }
+ }
+
+
+ int param = AudioMixer::VOLUME;
+ if (track->mFillingUpStatus == Track::FS_FILLED) {
+ // no ramp for the first volume setting
+ track->mFillingUpStatus = Track::FS_ACTIVE;
+ if (track->mState == TrackBase::RESUMING) {
+ track->mState = TrackBase::ACTIVE;
+ param = AudioMixer::RAMP_VOLUME;
+ }
+ mAudioMixer->setParameter(name, AudioMixer::RESAMPLE, AudioMixer::RESET, NULL);
+ } else if (cblk->server != 0) {
+ // If the track is stopped before the first frame was mixed,
+ // do not apply ramp
+ param = AudioMixer::RAMP_VOLUME;
+ }
+
+ // compute volume for this track
+ uint32_t vl, vr, va;
+ if (track->isMuted() || track->isPausing() ||
+ mStreamTypes[track->streamType()].mute) {
+ vl = vr = va = 0;
+ if (track->isPausing()) {
+ track->setPaused();
+ }
+ } else {
+
+ // read original volumes with volume control
+ float typeVolume = mStreamTypes[track->streamType()].volume;
+ float v = masterVolume * typeVolume;
+ uint32_t vlr = cblk->getVolumeLR();
+ vl = vlr & 0xFFFF;
+ vr = vlr >> 16;
+ // track volumes come from shared memory, so can't be trusted and must be clamped
+ if (vl > MAX_GAIN_INT) {
+ ALOGV("Track left volume out of range: %04X", vl);
+ vl = MAX_GAIN_INT;
+ }
+ if (vr > MAX_GAIN_INT) {
+ ALOGV("Track right volume out of range: %04X", vr);
+ vr = MAX_GAIN_INT;
+ }
+ // now apply the master volume and stream type volume
+ vl = (uint32_t)(v * vl) << 12;
+ vr = (uint32_t)(v * vr) << 12;
+ // assuming master volume and stream type volume each go up to 1.0,
+ // vl and vr are now in 8.24 format
+
+ uint16_t sendLevel = cblk->getSendLevel_U4_12();
+ // send level comes from shared memory and so may be corrupt
+ if (sendLevel > MAX_GAIN_INT) {
+ ALOGV("Track send level out of range: %04X", sendLevel);
+ sendLevel = MAX_GAIN_INT;
+ }
+ va = (uint32_t)(v * sendLevel);
+ }
+ // Delegate volume control to effect in track effect chain if needed
+ if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
+ // Do not ramp volume if volume is controlled by effect
+ param = AudioMixer::VOLUME;
+ track->mHasVolumeController = true;
+ } else {
+ // force no volume ramp when volume controller was just disabled or removed
+ // from effect chain to avoid volume spike
+ if (track->mHasVolumeController) {
+ param = AudioMixer::VOLUME;
+ }
+ track->mHasVolumeController = false;
+ }
+
+ // Convert volumes from 8.24 to 4.12 format
+ // This additional clamping is needed in case chain->setVolume_l() overshot
+ vl = (vl + (1 << 11)) >> 12;
+ if (vl > MAX_GAIN_INT) vl = MAX_GAIN_INT;
+ vr = (vr + (1 << 11)) >> 12;
+ if (vr > MAX_GAIN_INT) vr = MAX_GAIN_INT;
+
+ if (va > MAX_GAIN_INT) va = MAX_GAIN_INT; // va is uint32_t, so no need to check for -
+
+ // XXX: these things DON'T need to be done each time
+ mAudioMixer->setBufferProvider(name, track);
+ mAudioMixer->enable(name);
+
+ mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, (void *)vl);
+ mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, (void *)vr);
+ mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, (void *)va);
+ mAudioMixer->setParameter(
+ name,
+ AudioMixer::TRACK,
+ AudioMixer::FORMAT, (void *)track->format());
+ mAudioMixer->setParameter(
+ name,
+ AudioMixer::TRACK,
+ AudioMixer::CHANNEL_MASK, (void *)track->channelMask());
+ mAudioMixer->setParameter(
+ name,
+ AudioMixer::RESAMPLE,
+ AudioMixer::SAMPLE_RATE,
+ (void *)(cblk->sampleRate));
+ mAudioMixer->setParameter(
+ name,
+ AudioMixer::TRACK,
+ AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
+ mAudioMixer->setParameter(
+ name,
+ AudioMixer::TRACK,
+ AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
+
+ // reset retry count
+ track->mRetryCount = kMaxTrackRetries;
+
+ // If one track is ready, set the mixer ready if:
+ // - the mixer was not ready during previous round OR
+ // - no other track is not ready
+ if (mPrevMixerStatus != MIXER_TRACKS_READY ||
+ mixerStatus != MIXER_TRACKS_ENABLED) {
+ mixerStatus = MIXER_TRACKS_READY;
+ }
+ } else {
+ //ALOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", name, cblk->user, cblk->server, this);
+ if (track->isStopped()) {
+ track->reset();
+ }
+ if (track->isTerminated() || track->isStopped() || track->isPaused()) {
+ // We have consumed all the buffers of this track.
+ // Remove it from the list of active tracks.
+ tracksToRemove->add(track);
+ } else {
+ // No buffers for this track. Give it a few chances to
+ // fill a buffer, then remove it from active list.
+ if (--(track->mRetryCount) <= 0) {
+ ALOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", name, this);
+ tracksToRemove->add(track);
+ // indicate to client process that the track was disabled because of underrun
+ android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
+ // If one track is not ready, mark the mixer also not ready if:
+ // - the mixer was ready during previous round OR
+ // - no other track is ready
+ } else if (mPrevMixerStatus == MIXER_TRACKS_READY ||
+ mixerStatus != MIXER_TRACKS_READY) {
+ mixerStatus = MIXER_TRACKS_ENABLED;
+ }
+ }
+ mAudioMixer->disable(name);
+ }
+ }
+
+ // remove all the tracks that need to be...
+ count = tracksToRemove->size();
+ if (CC_UNLIKELY(count)) {
+ for (size_t i=0 ; i<count ; i++) {
+ const sp<Track>& track = tracksToRemove->itemAt(i);
+ mActiveTracks.remove(track);
+ if (track->mainBuffer() != mMixBuffer) {
+ chain = getEffectChain_l(track->sessionId());
+ if (chain != 0) {
+ ALOGV("stopping track on chain %p for session Id: %d", chain.get(), track->sessionId());
+ chain->decActiveTrackCnt();
+ }
+ }
+ if (track->isTerminated()) {
+ removeTrack_l(track);
+ }
+ }
+ }
+
+ // mix buffer must be cleared if all tracks are connected to an
+ // effect chain as in this case the mixer will not write to
+ // mix buffer and track effects will accumulate into it
+ if (mixedTracks != 0 && mixedTracks == tracksWithEffect) {
+ memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
+ }
+
+ return mixerStatus;
+}
+
+/*
+The derived values that are cached:
+ - mixBufferSize from frame count * frame size
+ - activeSleepTime from activeSleepTimeUs()
+ - idleSleepTime from idleSleepTimeUs()
+ - standbyDelay from mActiveSleepTimeUs (DIRECT only)
+ - maxPeriod from frame count and sample rate (MIXER only)
+
+The parameters that affect these derived values are:
+ - frame count
+ - frame size
+ - sample rate
+ - device type: A2DP or not
+ - device latency
+ - format: PCM or not
+ - active sleep time
+ - idle sleep time
+*/
+
+void AudioFlinger::PlaybackThread::cacheParameters_l()
+{
+ mixBufferSize = mFrameCount * mFrameSize;
+ activeSleepTime = activeSleepTimeUs();
+ idleSleepTime = idleSleepTimeUs();
+}
+
+void AudioFlinger::MixerThread::invalidateTracks(audio_stream_type_t streamType)
+{
+ ALOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
+ this, streamType, mTracks.size());
+ Mutex::Autolock _l(mLock);
+
+ size_t size = mTracks.size();
+ for (size_t i = 0; i < size; i++) {
+ sp<Track> t = mTracks[i];
+ if (t->streamType() == streamType) {
+ android_atomic_or(CBLK_INVALID_ON, &t->mCblk->flags);
+ t->mCblk->cv.signal();
+ }
+ }
+}
+
+void AudioFlinger::PlaybackThread::setStreamValid(audio_stream_type_t streamType, bool valid)
+{
+ ALOGV ("PlaybackThread::setStreamValid() thread %p, streamType %d, valid %d",
+ this, streamType, valid);
+ Mutex::Autolock _l(mLock);
+
+ mStreamTypes[streamType].valid = valid;
+}
+
+// getTrackName_l() must be called with ThreadBase::mLock held
+int AudioFlinger::MixerThread::getTrackName_l()
+{
+ return mAudioMixer->getTrackName();
+}
+
+// deleteTrackName_l() must be called with ThreadBase::mLock held
+void AudioFlinger::MixerThread::deleteTrackName_l(int name)
+{
+ ALOGV("remove track (%d) and delete from mixer", name);
+ mAudioMixer->deleteTrackName(name);
+}
+
+// checkForNewParameters_l() must be called with ThreadBase::mLock held
+bool AudioFlinger::MixerThread::checkForNewParameters_l()
+{
+ bool reconfig = false;
+
+ while (!mNewParameters.isEmpty()) {
+ status_t status = NO_ERROR;
+ String8 keyValuePair = mNewParameters[0];
+ AudioParameter param = AudioParameter(keyValuePair);
+ int value;
+
+ if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
+ reconfig = true;
+ }
+ if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
+ if ((audio_format_t) value != AUDIO_FORMAT_PCM_16_BIT) {
+ status = BAD_VALUE;
+ } else {
+ reconfig = true;
+ }
+ }
+ if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
+ if (value != AUDIO_CHANNEL_OUT_STEREO) {
+ status = BAD_VALUE;
+ } else {
+ reconfig = true;
+ }
+ }
+ if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
+ // do not accept frame count changes if tracks are open as the track buffer
+ // size depends on frame count and correct behavior would not be guaranteed
+ // if frame count is changed after track creation
+ if (!mTracks.isEmpty()) {
+ status = INVALID_OPERATION;
+ } else {
+ reconfig = true;
+ }
+ }
+ if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
+#ifdef ADD_BATTERY_DATA
+ // when changing the audio output device, call addBatteryData to notify
+ // the change
+ if ((int)mDevice != value) {
+ uint32_t params = 0;
+ // check whether speaker is on
+ if (value & AUDIO_DEVICE_OUT_SPEAKER) {
+ params |= IMediaPlayerService::kBatteryDataSpeakerOn;
+ }
+
+ int deviceWithoutSpeaker
+ = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER;
+ // check if any other device (except speaker) is on
+ if (value & deviceWithoutSpeaker ) {
+ params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn;
+ }
+
+ if (params != 0) {
+ addBatteryData(params);
+ }
+ }
+#endif
+
+ // forward device change to effects that have requested to be
+ // aware of attached audio device.
+ mDevice = (uint32_t)value;
+ for (size_t i = 0; i < mEffectChains.size(); i++) {
+ mEffectChains[i]->setDevice_l(mDevice);
+ }
+ }
+
+ if (status == NO_ERROR) {
+ status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
+ keyValuePair.string());
+ if (!mStandby && status == INVALID_OPERATION) {
+ mOutput->stream->common.standby(&mOutput->stream->common);
+ mStandby = true;
+ mBytesWritten = 0;
+ status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
+ keyValuePair.string());
+ }
+ if (status == NO_ERROR && reconfig) {
+ delete mAudioMixer;
+ // for safety in case readOutputParameters() accesses mAudioMixer (it doesn't)
+ mAudioMixer = NULL;
+ readOutputParameters();
+ mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
+ for (size_t i = 0; i < mTracks.size() ; i++) {
+ int name = getTrackName_l();
+ if (name < 0) break;
+ mTracks[i]->mName = name;
+ // limit track sample rate to 2 x new output sample rate
+ if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
+ mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
+ }
+ }
+ sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
+ }
+ }
+
+ mNewParameters.removeAt(0);
+
+ mParamStatus = status;
+ mParamCond.signal();
+ // wait for condition with time out in case the thread calling ThreadBase::setParameters()
+ // already timed out waiting for the status and will never signal the condition.
+ mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
+ }
+ return reconfig;
+}
+
+status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ PlaybackThread::dumpInternals(fd, args);
+
+ snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
+{
+ return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
+}
+
+uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs()
+{
+ return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
+}
+
+void AudioFlinger::MixerThread::cacheParameters_l()
+{
+ PlaybackThread::cacheParameters_l();
+
+ // FIXME: Relaxed timing because of a certain device that can't meet latency
+ // Should be reduced to 2x after the vendor fixes the driver issue
+ // increase threshold again due to low power audio mode. The way this warning
+ // threshold is calculated and its usefulness should be reconsidered anyway.
+ maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
+}
+
+// ----------------------------------------------------------------------------
+AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
+ AudioStreamOut* output, audio_io_handle_t id, uint32_t device)
+ : PlaybackThread(audioFlinger, output, id, device, DIRECT)
+ // mLeftVolFloat, mRightVolFloat
+ // mLeftVolShort, mRightVolShort
+{
+}
+
+AudioFlinger::DirectOutputThread::~DirectOutputThread()
+{
+}
+
+AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prepareTracks_l(
+ Vector< sp<Track> > *tracksToRemove
+)
+{
+ sp<Track> trackToRemove;
+
+ mixer_state mixerStatus = MIXER_IDLE;
+
+ // find out which tracks need to be processed
+ if (mActiveTracks.size() != 0) {
+ sp<Track> t = mActiveTracks[0].promote();
+ // The track died recently
+ if (t == 0) return MIXER_IDLE;
+
+ Track* const track = t.get();
+ audio_track_cblk_t* cblk = track->cblk();
+
+ // The first time a track is added we wait
+ // for all its buffers to be filled before processing it
+ if (cblk->framesReady() && track->isReady() &&
+ !track->isPaused() && !track->isTerminated())
+ {
+ //ALOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
+
+ if (track->mFillingUpStatus == Track::FS_FILLED) {
+ track->mFillingUpStatus = Track::FS_ACTIVE;
+ mLeftVolFloat = mRightVolFloat = 0;
+ mLeftVolShort = mRightVolShort = 0;
+ if (track->mState == TrackBase::RESUMING) {
+ track->mState = TrackBase::ACTIVE;
+ rampVolume = true;
+ }
+ } else if (cblk->server != 0) {
+ // If the track is stopped before the first frame was mixed,
+ // do not apply ramp
+ rampVolume = true;
+ }
+ // compute volume for this track
+ float left, right;
+ if (track->isMuted() || mMasterMute || track->isPausing() ||
+ mStreamTypes[track->streamType()].mute) {
+ left = right = 0;
+ if (track->isPausing()) {
+ track->setPaused();
+ }
+ } else {
+ float typeVolume = mStreamTypes[track->streamType()].volume;
+ float v = mMasterVolume * typeVolume;
+ uint32_t vlr = cblk->getVolumeLR();
+ float v_clamped = v * (vlr & 0xFFFF);
+ if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+ left = v_clamped/MAX_GAIN;
+ v_clamped = v * (vlr >> 16);
+ if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+ right = v_clamped/MAX_GAIN;
+ }
+
+ if (left != mLeftVolFloat || right != mRightVolFloat) {
+ mLeftVolFloat = left;
+ mRightVolFloat = right;
+
+ // If audio HAL implements volume control,
+ // force software volume to nominal value
+ if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
+ left = 1.0f;
+ right = 1.0f;
+ }
+
+ // Convert volumes from float to 8.24
+ uint32_t vl = (uint32_t)(left * (1 << 24));
+ uint32_t vr = (uint32_t)(right * (1 << 24));
+
+ // Delegate volume control to effect in track effect chain if needed
+ // only one effect chain can be present on DirectOutputThread, so if
+ // there is one, the track is connected to it
+ if (!mEffectChains.isEmpty()) {
+ // Do not ramp volume if volume is controlled by effect
+ if (mEffectChains[0]->setVolume_l(&vl, &vr)) {
+ rampVolume = false;
+ }
+ }
+
+ // Convert volumes from 8.24 to 4.12 format
+ uint32_t v_clamped = (vl + (1 << 11)) >> 12;
+ if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
+ leftVol = (uint16_t)v_clamped;
+ v_clamped = (vr + (1 << 11)) >> 12;
+ if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
+ rightVol = (uint16_t)v_clamped;
+ } else {
+ leftVol = mLeftVolShort;
+ rightVol = mRightVolShort;
+ rampVolume = false;
+ }
+
+ // reset retry count
+ track->mRetryCount = kMaxTrackRetriesDirect;
+ mActiveTrack = t;
+ mixerStatus = MIXER_TRACKS_READY;
+ } else {
+ //ALOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
+ if (track->isStopped()) {
+ track->reset();
+ }
+ if (track->isTerminated() || track->isStopped() || track->isPaused()) {
+ // We have consumed all the buffers of this track.
+ // Remove it from the list of active tracks.
+ trackToRemove = track;
+ } else {
+ // No buffers for this track. Give it a few chances to
+ // fill a buffer, then remove it from active list.
+ if (--(track->mRetryCount) <= 0) {
+ ALOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
+ trackToRemove = track;
+ } else {
+ mixerStatus = MIXER_TRACKS_ENABLED;
+ }
+ }
+ }
+ }
+
+ // FIXME merge this with similar code for removing multiple tracks
+ // remove all the tracks that need to be...
+ if (CC_UNLIKELY(trackToRemove != 0)) {
+ tracksToRemove->add(trackToRemove);
+ mActiveTracks.remove(trackToRemove);
+ if (!mEffectChains.isEmpty()) {
+ ALOGV("stopping track on chain %p for session Id: %d", mEffectChains[0].get(),
+ trackToRemove->sessionId());
+ mEffectChains[0]->decActiveTrackCnt();
+ }
+ if (trackToRemove->isTerminated()) {
+ removeTrack_l(trackToRemove);
+ }
+ }
+
+ return mixerStatus;
+}
+
+void AudioFlinger::DirectOutputThread::threadLoop_mix()
+{
+ AudioBufferProvider::Buffer buffer;
+ size_t frameCount = mFrameCount;
+ int8_t *curBuf = (int8_t *)mMixBuffer;
+ // output audio to hardware
+ while (frameCount) {
+ buffer.frameCount = frameCount;
+ mActiveTrack->getNextBuffer(&buffer);
+ if (CC_UNLIKELY(buffer.raw == NULL)) {
+ memset(curBuf, 0, frameCount * mFrameSize);
+ break;
+ }
+ memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
+ frameCount -= buffer.frameCount;
+ curBuf += buffer.frameCount * mFrameSize;
+ mActiveTrack->releaseBuffer(&buffer);
+ }
+ sleepTime = 0;
+ standbyTime = systemTime() + standbyDelay;
+ mActiveTrack.clear();
+
+ // apply volume
+
+ // Do not apply volume on compressed audio
+ if (!audio_is_linear_pcm(mFormat)) {
+ return;
+ }
+
+ // convert to signed 16 bit before volume calculation
+ if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
+ size_t count = mFrameCount * mChannelCount;
+ uint8_t *src = (uint8_t *)mMixBuffer + count-1;
+ int16_t *dst = mMixBuffer + count-1;
+ while (count--) {
+ *dst-- = (int16_t)(*src--^0x80) << 8;
+ }
+ }
+
+ frameCount = mFrameCount;
+ int16_t *out = mMixBuffer;
+ if (rampVolume) {
+ if (mChannelCount == 1) {
+ int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
+ int32_t vlInc = d / (int32_t)frameCount;
+ int32_t vl = ((int32_t)mLeftVolShort << 16);
+ do {
+ out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
+ out++;
+ vl += vlInc;
+ } while (--frameCount);
+
+ } else {
+ int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
+ int32_t vlInc = d / (int32_t)frameCount;
+ d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
+ int32_t vrInc = d / (int32_t)frameCount;
+ int32_t vl = ((int32_t)mLeftVolShort << 16);
+ int32_t vr = ((int32_t)mRightVolShort << 16);
+ do {
+ out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
+ out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
+ out += 2;
+ vl += vlInc;
+ vr += vrInc;
+ } while (--frameCount);
+ }
+ } else {
+ if (mChannelCount == 1) {
+ do {
+ out[0] = clamp16(mul(out[0], leftVol) >> 12);
+ out++;
+ } while (--frameCount);
+ } else {
+ do {
+ out[0] = clamp16(mul(out[0], leftVol) >> 12);
+ out[1] = clamp16(mul(out[1], rightVol) >> 12);
+ out += 2;
+ } while (--frameCount);
+ }
+ }
+
+ // convert back to unsigned 8 bit after volume calculation
+ if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
+ size_t count = mFrameCount * mChannelCount;
+ int16_t *src = mMixBuffer;
+ uint8_t *dst = (uint8_t *)mMixBuffer;
+ while (count--) {
+ *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
+ }
+ }
+
+ mLeftVolShort = leftVol;
+ mRightVolShort = rightVol;
+}
+
+void AudioFlinger::DirectOutputThread::threadLoop_sleepTime()
+{
+ if (sleepTime == 0) {
+ if (mMixerStatus == MIXER_TRACKS_ENABLED) {
+ sleepTime = activeSleepTime;
+ } else {
+ sleepTime = idleSleepTime;
+ }
+ } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
+ memset (mMixBuffer, 0, mFrameCount * mFrameSize);
+ sleepTime = 0;
+ }
+}
+
+// getTrackName_l() must be called with ThreadBase::mLock held
+int AudioFlinger::DirectOutputThread::getTrackName_l()
+{
+ return 0;
+}
+
+// deleteTrackName_l() must be called with ThreadBase::mLock held
+void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
+{
+}
+
+// checkForNewParameters_l() must be called with ThreadBase::mLock held
+bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
+{
+ bool reconfig = false;
+
+ while (!mNewParameters.isEmpty()) {
+ status_t status = NO_ERROR;
+ String8 keyValuePair = mNewParameters[0];
+ AudioParameter param = AudioParameter(keyValuePair);
+ int value;
+
+ if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
+ // do not accept frame count changes if tracks are open as the track buffer
+ // size depends on frame count and correct behavior would not be garantied
+ // if frame count is changed after track creation
+ if (!mTracks.isEmpty()) {
+ status = INVALID_OPERATION;
+ } else {
+ reconfig = true;
+ }
+ }
+ if (status == NO_ERROR) {
+ status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
+ keyValuePair.string());
+ if (!mStandby && status == INVALID_OPERATION) {
+ mOutput->stream->common.standby(&mOutput->stream->common);
+ mStandby = true;
+ mBytesWritten = 0;
+ status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
+ keyValuePair.string());
+ }
+ if (status == NO_ERROR && reconfig) {
+ readOutputParameters();
+ sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
+ }
+ }
+
+ mNewParameters.removeAt(0);
+
+ mParamStatus = status;
+ mParamCond.signal();
+ // wait for condition with time out in case the thread calling ThreadBase::setParameters()
+ // already timed out waiting for the status and will never signal the condition.
+ mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
+ }
+ return reconfig;
+}
+
+uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
+{
+ uint32_t time;
+ if (audio_is_linear_pcm(mFormat)) {
+ time = PlaybackThread::activeSleepTimeUs();
+ } else {
+ time = 10000;
+ }
+ return time;
+}
+
+uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
+{
+ uint32_t time;
+ if (audio_is_linear_pcm(mFormat)) {
+ time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
+ } else {
+ time = 10000;
+ }
+ return time;
+}
+
+uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs()
+{
+ uint32_t time;
+ if (audio_is_linear_pcm(mFormat)) {
+ time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
+ } else {
+ time = 10000;
+ }
+ return time;
+}
+
+void AudioFlinger::DirectOutputThread::cacheParameters_l()
+{
+ PlaybackThread::cacheParameters_l();
+
+ // use shorter standby delay as on normal output to release
+ // hardware resources as soon as possible
+ standbyDelay = microseconds(activeSleepTime*2);
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
+ AudioFlinger::MixerThread* mainThread, audio_io_handle_t id)
+ : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device(), DUPLICATING),
+ mWaitTimeMs(UINT_MAX)
+{
+ addOutputTrack(mainThread);
+}
+
+AudioFlinger::DuplicatingThread::~DuplicatingThread()
+{
+ for (size_t i = 0; i < mOutputTracks.size(); i++) {
+ mOutputTracks[i]->destroy();
+ }
+}
+
+void AudioFlinger::DuplicatingThread::threadLoop_mix()
+{
+ // mix buffers...
+ if (outputsReady(outputTracks)) {
+ mAudioMixer->process(AudioBufferProvider::kInvalidPTS);
+ } else {
+ memset(mMixBuffer, 0, mixBufferSize);
+ }
+ sleepTime = 0;
+ writeFrames = mFrameCount;
+}
+
+void AudioFlinger::DuplicatingThread::threadLoop_sleepTime()
+{
+ if (sleepTime == 0) {
+ if (mMixerStatus == MIXER_TRACKS_ENABLED) {
+ sleepTime = activeSleepTime;
+ } else {
+ sleepTime = idleSleepTime;
+ }
+ } else if (mBytesWritten != 0) {
+ // flush remaining overflow buffers in output tracks
+ for (size_t i = 0; i < outputTracks.size(); i++) {
+ if (outputTracks[i]->isActive()) {
+ sleepTime = 0;
+ writeFrames = 0;
+ memset(mMixBuffer, 0, mixBufferSize);
+ break;
+ }
+ }
+ }
+}
+
+void AudioFlinger::DuplicatingThread::threadLoop_write()
+{
+ standbyTime = systemTime() + standbyDelay;
+ for (size_t i = 0; i < outputTracks.size(); i++) {
+ outputTracks[i]->write(mMixBuffer, writeFrames);
+ }
+ mBytesWritten += mixBufferSize;
+}
+
+void AudioFlinger::DuplicatingThread::threadLoop_standby()
+{
+ // DuplicatingThread implements standby by stopping all tracks
+ for (size_t i = 0; i < outputTracks.size(); i++) {
+ outputTracks[i]->stop();
+ }
+}
+
+void AudioFlinger::DuplicatingThread::saveOutputTracks()
+{
+ outputTracks = mOutputTracks;
+}
+
+void AudioFlinger::DuplicatingThread::clearOutputTracks()
+{
+ outputTracks.clear();
+}
+
+void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
+{
+ Mutex::Autolock _l(mLock);
+ // FIXME explain this formula
+ int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
+ OutputTrack *outputTrack = new OutputTrack(thread,
+ this,
+ mSampleRate,
+ mFormat,
+ mChannelMask,
+ frameCount);
+ if (outputTrack->cblk() != NULL) {
+ thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
+ mOutputTracks.add(outputTrack);
+ ALOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
+ updateWaitTime_l();
+ }
+}
+
+void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
+{
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mOutputTracks.size(); i++) {
+ if (mOutputTracks[i]->thread() == thread) {
+ mOutputTracks[i]->destroy();
+ mOutputTracks.removeAt(i);
+ updateWaitTime_l();
+ return;
+ }
+ }
+ ALOGV("removeOutputTrack(): unkonwn thread: %p", thread);
+}
+
+// caller must hold mLock
+void AudioFlinger::DuplicatingThread::updateWaitTime_l()
+{
+ mWaitTimeMs = UINT_MAX;
+ for (size_t i = 0; i < mOutputTracks.size(); i++) {
+ sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
+ if (strong != 0) {
+ uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
+ if (waitTimeMs < mWaitTimeMs) {
+ mWaitTimeMs = waitTimeMs;
+ }
+ }
+ }
+}
+
+
+bool AudioFlinger::DuplicatingThread::outputsReady(const SortedVector< sp<OutputTrack> > &outputTracks)
+{
+ for (size_t i = 0; i < outputTracks.size(); i++) {
+ sp<ThreadBase> thread = outputTracks[i]->thread().promote();
+ if (thread == 0) {
+ ALOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
+ return false;
+ }
+ PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ if (playbackThread->standby() && !playbackThread->isSuspended()) {
+ ALOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
+ return false;
+ }
+ }
+ return true;
+}
+
+uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
+{
+ return (mWaitTimeMs * 1000) / 2;
+}
+
+void AudioFlinger::DuplicatingThread::cacheParameters_l()
+{
+ // updateWaitTime_l() sets mWaitTimeMs, which affects activeSleepTimeUs(), so call it first
+ updateWaitTime_l();
+
+ MixerThread::cacheParameters_l();
+}
+
+// ----------------------------------------------------------------------------
+
+// TrackBase constructor must be called with AudioFlinger::mLock held
+AudioFlinger::ThreadBase::TrackBase::TrackBase(
+ ThreadBase *thread,
+ const sp<Client>& client,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ const sp<IMemory>& sharedBuffer,
+ int sessionId)
+ : RefBase(),
+ mThread(thread),
+ mClient(client),
+ mCblk(NULL),
+ // mBuffer
+ // mBufferEnd
+ mFrameCount(0),
+ mState(IDLE),
+ mFormat(format),
+ mStepServerFailed(false),
+ mSessionId(sessionId)
+ // mChannelCount
+ // mChannelMask
+{
+ ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
+
+ // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
+ size_t size = sizeof(audio_track_cblk_t);
+ uint8_t channelCount = popcount(channelMask);
+ size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
+ if (sharedBuffer == 0) {
+ size += bufferSize;
+ }
+
+ if (client != NULL) {
+ mCblkMemory = client->heap()->allocate(size);
+ if (mCblkMemory != 0) {
+ mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
+ if (mCblk != NULL) { // construct the shared structure in-place.
+ new(mCblk) audio_track_cblk_t();
+ // clear all buffers
+ mCblk->frameCount = frameCount;
+ mCblk->sampleRate = sampleRate;
+ mChannelCount = channelCount;
+ mChannelMask = channelMask;
+ if (sharedBuffer == 0) {
+ mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
+ memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
+ // Force underrun condition to avoid false underrun callback until first data is
+ // written to buffer (other flags are cleared)
+ mCblk->flags = CBLK_UNDERRUN_ON;
+ } else {
+ mBuffer = sharedBuffer->pointer();
+ }
+ mBufferEnd = (uint8_t *)mBuffer + bufferSize;
+ }
+ } else {
+ ALOGE("not enough memory for AudioTrack size=%u", size);
+ client->heap()->dump("AudioTrack");
+ return;
+ }
+ } else {
+ mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
+ // construct the shared structure in-place.
+ new(mCblk) audio_track_cblk_t();
+ // clear all buffers
+ mCblk->frameCount = frameCount;
+ mCblk->sampleRate = sampleRate;
+ mChannelCount = channelCount;
+ mChannelMask = channelMask;
+ mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
+ memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
+ // Force underrun condition to avoid false underrun callback until first data is
+ // written to buffer (other flags are cleared)
+ mCblk->flags = CBLK_UNDERRUN_ON;
+ mBufferEnd = (uint8_t *)mBuffer + bufferSize;
+ }
+}
+
+AudioFlinger::ThreadBase::TrackBase::~TrackBase()
+{
+ if (mCblk != NULL) {
+ if (mClient == 0) {
+ delete mCblk;
+ } else {
+ mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
+ }
+ }
+ mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
+ if (mClient != 0) {
+ // Client destructor must run with AudioFlinger mutex locked
+ Mutex::Autolock _l(mClient->audioFlinger()->mLock);
+ // If the client's reference count drops to zero, the associated destructor
+ // must run with AudioFlinger lock held. Thus the explicit clear() rather than
+ // relying on the automatic clear() at end of scope.
+ mClient.clear();
+ }
+}
+
+// AudioBufferProvider interface
+// getNextBuffer() = 0;
+// This implementation of releaseBuffer() is used by Track and RecordTrack, but not TimedTrack
+void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+{
+ buffer->raw = NULL;
+ mFrameCount = buffer->frameCount;
+ (void) step(); // ignore return value of step()
+ buffer->frameCount = 0;
+}
+
+bool AudioFlinger::ThreadBase::TrackBase::step() {
+ bool result;
+ audio_track_cblk_t* cblk = this->cblk();
+
+ result = cblk->stepServer(mFrameCount);
+ if (!result) {
+ ALOGV("stepServer failed acquiring cblk mutex");
+ mStepServerFailed = true;
+ }
+ return result;
+}
+
+void AudioFlinger::ThreadBase::TrackBase::reset() {
+ audio_track_cblk_t* cblk = this->cblk();
+
+ cblk->user = 0;
+ cblk->server = 0;
+ cblk->userBase = 0;
+ cblk->serverBase = 0;
+ mStepServerFailed = false;
+ ALOGV("TrackBase::reset");
+}
+
+int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
+ return (int)mCblk->sampleRate;
+}
+
+void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
+ audio_track_cblk_t* cblk = this->cblk();
+ size_t frameSize = cblk->frameSize;
+ int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*frameSize;
+ int8_t *bufferEnd = bufferStart + frames * frameSize;
+
+ // Check validity of returned pointer in case the track control block would have been corrupted.
+ if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
+ ((unsigned long)bufferStart & (unsigned long)(frameSize - 1))) {
+ ALOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \
+ server %d, serverBase %d, user %d, userBase %d",
+ bufferStart, bufferEnd, mBuffer, mBufferEnd,
+ cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
+ return NULL;
+ }
+
+ return bufferStart;
+}
+
+// ----------------------------------------------------------------------------
+
+// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
+AudioFlinger::PlaybackThread::Track::Track(
+ PlaybackThread *thread,
+ const sp<Client>& client,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ const sp<IMemory>& sharedBuffer,
+ int sessionId)
+ : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId),
+ mMute(false),
+ // mFillingUpStatus ?
+ // mRetryCount initialized later when needed
+ mSharedBuffer(sharedBuffer),
+ mStreamType(streamType),
+ mName(-1), // see note below
+ mMainBuffer(thread->mixBuffer()),
+ mAuxBuffer(NULL),
+ mAuxEffectId(0), mHasVolumeController(false)
+{
+ if (mCblk != NULL) {
+ // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
+ // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
+ mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t);
+ // to avoid leaking a track name, do not allocate one unless there is an mCblk
+ mName = thread->getTrackName_l();
+ if (mName < 0) {
+ ALOGE("no more track names available");
+ }
+ }
+ ALOGV("Track constructor name %d, calling pid %d", mName, IPCThreadState::self()->getCallingPid());
+}
+
+AudioFlinger::PlaybackThread::Track::~Track()
+{
+ ALOGV("PlaybackThread::Track destructor");
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ Mutex::Autolock _l(thread->mLock);
+ mState = TERMINATED;
+ }
+}
+
+void AudioFlinger::PlaybackThread::Track::destroy()
+{
+ // NOTE: destroyTrack_l() can remove a strong reference to this Track
+ // by removing it from mTracks vector, so there is a risk that this Tracks's
+ // destructor is called. As the destructor needs to lock mLock,
+ // we must acquire a strong reference on this Track before locking mLock
+ // here so that the destructor is called only when exiting this function.
+ // On the other hand, as long as Track::destroy() is only called by
+ // TrackHandle destructor, the TrackHandle still holds a strong ref on
+ // this Track with its member mTrack.
+ sp<Track> keep(this);
+ { // scope for mLock
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ if (!isOutputTrack()) {
+ if (mState == ACTIVE || mState == RESUMING) {
+ AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
+
+#ifdef ADD_BATTERY_DATA
+ // to track the speaker usage
+ addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
+#endif
+ }
+ AudioSystem::releaseOutput(thread->id());
+ }
+ Mutex::Autolock _l(thread->mLock);
+ PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ playbackThread->destroyTrack_l(this);
+ }
+ }
+}
+
+void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
+{
+ uint32_t vlr = mCblk->getVolumeLR();
+ snprintf(buffer, size, " %05d %05d %03u %03u 0x%08x %05u %04u %1d %1d %1d %05u %05u %05u 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ mName - AudioMixer::TRACK0,
+ (mClient == 0) ? getpid_cached : mClient->pid(),
+ mStreamType,
+ mFormat,
+ mChannelMask,
+ mSessionId,
+ mFrameCount,
+ mState,
+ mMute,
+ mFillingUpStatus,
+ mCblk->sampleRate,
+ vlr & 0xFFFF,
+ vlr >> 16,
+ mCblk->server,
+ mCblk->user,
+ (int)mMainBuffer,
+ (int)mAuxBuffer);
+}
+
+// AudioBufferProvider interface
+status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(
+ AudioBufferProvider::Buffer* buffer, int64_t pts)
+{
+ audio_track_cblk_t* cblk = this->cblk();
+ uint32_t framesReady;
+ uint32_t framesReq = buffer->frameCount;
+
+ // Check if last stepServer failed, try to step now
+ if (mStepServerFailed) {
+ if (!step()) goto getNextBuffer_exit;
+ ALOGV("stepServer recovered");
+ mStepServerFailed = false;
+ }
+
+ framesReady = cblk->framesReady();
+
+ if (CC_LIKELY(framesReady)) {
+ uint32_t s = cblk->server;
+ uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
+
+ bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
+ if (framesReq > framesReady) {
+ framesReq = framesReady;
+ }
+ if (s + framesReq > bufferEnd) {
+ framesReq = bufferEnd - s;
+ }
+
+ buffer->raw = getBuffer(s, framesReq);
+ if (buffer->raw == NULL) goto getNextBuffer_exit;
+
+ buffer->frameCount = framesReq;
+ return NO_ERROR;
+ }
+
+getNextBuffer_exit:
+ buffer->raw = NULL;
+ buffer->frameCount = 0;
+ ALOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
+ return NOT_ENOUGH_DATA;
+}
+
+uint32_t AudioFlinger::PlaybackThread::Track::framesReady() const {
+ return mCblk->framesReady();
+}
+
+bool AudioFlinger::PlaybackThread::Track::isReady() const {
+ if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) return true;
+
+ if (framesReady() >= mCblk->frameCount ||
+ (mCblk->flags & CBLK_FORCEREADY_MSK)) {
+ mFillingUpStatus = FS_FILLED;
+ android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
+ return true;
+ }
+ return false;
+}
+
+status_t AudioFlinger::PlaybackThread::Track::start(pid_t tid)
+{
+ status_t status = NO_ERROR;
+ ALOGV("start(%d), calling pid %d session %d tid %d",
+ mName, IPCThreadState::self()->getCallingPid(), mSessionId, tid);
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ Mutex::Autolock _l(thread->mLock);
+ track_state state = mState;
+ // here the track could be either new, or restarted
+ // in both cases "unstop" the track
+ if (mState == PAUSED) {
+ mState = TrackBase::RESUMING;
+ ALOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
+ } else {
+ mState = TrackBase::ACTIVE;
+ ALOGV("? => ACTIVE (%d) on thread %p", mName, this);
+ }
+
+ if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
+ thread->mLock.unlock();
+ status = AudioSystem::startOutput(thread->id(), mStreamType, mSessionId);
+ thread->mLock.lock();
+
+#ifdef ADD_BATTERY_DATA
+ // to track the speaker usage
+ if (status == NO_ERROR) {
+ addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStart);
+ }
+#endif
+ }
+ if (status == NO_ERROR) {
+ PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ playbackThread->addTrack_l(this);
+ } else {
+ mState = state;
+ }
+ } else {
+ status = BAD_VALUE;
+ }
+ return status;
+}
+
+void AudioFlinger::PlaybackThread::Track::stop()
+{
+ ALOGV("stop(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ Mutex::Autolock _l(thread->mLock);
+ track_state state = mState;
+ if (mState > STOPPED) {
+ mState = STOPPED;
+ // If the track is not active (PAUSED and buffers full), flush buffers
+ PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+ reset();
+ }
+ ALOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
+ }
+ if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
+ thread->mLock.unlock();
+ AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
+ thread->mLock.lock();
+
+#ifdef ADD_BATTERY_DATA
+ // to track the speaker usage
+ addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
+#endif
+ }
+ }
+}
+
+void AudioFlinger::PlaybackThread::Track::pause()
+{
+ ALOGV("pause(%d), calling pid %d", mName, IPCThreadState::self()->getCallingPid());
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ Mutex::Autolock _l(thread->mLock);
+ if (mState == ACTIVE || mState == RESUMING) {
+ mState = PAUSING;
+ ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
+ if (!isOutputTrack()) {
+ thread->mLock.unlock();
+ AudioSystem::stopOutput(thread->id(), mStreamType, mSessionId);
+ thread->mLock.lock();
+
+#ifdef ADD_BATTERY_DATA
+ // to track the speaker usage
+ addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
+#endif
+ }
+ }
+ }
+}
+
+void AudioFlinger::PlaybackThread::Track::flush()
+{
+ ALOGV("flush(%d)", mName);
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ Mutex::Autolock _l(thread->mLock);
+ if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
+ return;
+ }
+ // No point remaining in PAUSED state after a flush => go to
+ // STOPPED state
+ mState = STOPPED;
+
+ // do not reset the track if it is still in the process of being stopped or paused.
+ // this will be done by prepareTracks_l() when the track is stopped.
+ PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+ reset();
+ }
+ }
+}
+
+void AudioFlinger::PlaybackThread::Track::reset()
+{
+ // Do not reset twice to avoid discarding data written just after a flush and before
+ // the audioflinger thread detects the track is stopped.
+ if (!mResetDone) {
+ TrackBase::reset();
+ // Force underrun condition to avoid false underrun callback until first data is
+ // written to buffer
+ android_atomic_and(~CBLK_FORCEREADY_MSK, &mCblk->flags);
+ android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
+ mFillingUpStatus = FS_FILLING;
+ mResetDone = true;
+ }
+}
+
+void AudioFlinger::PlaybackThread::Track::mute(bool muted)
+{
+ mMute = muted;
+}
+
+status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
+{
+ status_t status = DEAD_OBJECT;
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ status = playbackThread->attachAuxEffect(this, EffectId);
+ }
+ return status;
+}
+
+void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
+{
+ mAuxEffectId = EffectId;
+ mAuxBuffer = buffer;
+}
+
+// timed audio tracks
+
+sp<AudioFlinger::PlaybackThread::TimedTrack>
+AudioFlinger::PlaybackThread::TimedTrack::create(
+ PlaybackThread *thread,
+ const sp<Client>& client,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ const sp<IMemory>& sharedBuffer,
+ int sessionId) {
+ if (!client->reserveTimedTrack())
+ return NULL;
+
+ return new TimedTrack(
+ thread, client, streamType, sampleRate, format, channelMask, frameCount,
+ sharedBuffer, sessionId);
+}
+
+AudioFlinger::PlaybackThread::TimedTrack::TimedTrack(
+ PlaybackThread *thread,
+ const sp<Client>& client,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ const sp<IMemory>& sharedBuffer,
+ int sessionId)
+ : Track(thread, client, streamType, sampleRate, format, channelMask,
+ frameCount, sharedBuffer, sessionId),
+ mTimedSilenceBuffer(NULL),
+ mTimedSilenceBufferSize(0),
+ mTimedAudioOutputOnTime(false),
+ mMediaTimeTransformValid(false)
+{
+ LocalClock lc;
+ mLocalTimeFreq = lc.getLocalFreq();
+
+ mLocalTimeToSampleTransform.a_zero = 0;
+ mLocalTimeToSampleTransform.b_zero = 0;
+ mLocalTimeToSampleTransform.a_to_b_numer = sampleRate;
+ mLocalTimeToSampleTransform.a_to_b_denom = mLocalTimeFreq;
+ LinearTransform::reduce(&mLocalTimeToSampleTransform.a_to_b_numer,
+ &mLocalTimeToSampleTransform.a_to_b_denom);
+}
+
+AudioFlinger::PlaybackThread::TimedTrack::~TimedTrack() {
+ mClient->releaseTimedTrack();
+ delete [] mTimedSilenceBuffer;
+}
+
+status_t AudioFlinger::PlaybackThread::TimedTrack::allocateTimedBuffer(
+ size_t size, sp<IMemory>* buffer) {
+
+ Mutex::Autolock _l(mTimedBufferQueueLock);
+
+ trimTimedBufferQueue_l();
+
+ // lazily initialize the shared memory heap for timed buffers
+ if (mTimedMemoryDealer == NULL) {
+ const int kTimedBufferHeapSize = 512 << 10;
+
+ mTimedMemoryDealer = new MemoryDealer(kTimedBufferHeapSize,
+ "AudioFlingerTimed");
+ if (mTimedMemoryDealer == NULL)
+ return NO_MEMORY;
+ }
+
+ sp<IMemory> newBuffer = mTimedMemoryDealer->allocate(size);
+ if (newBuffer == NULL) {
+ newBuffer = mTimedMemoryDealer->allocate(size);
+ if (newBuffer == NULL)
+ return NO_MEMORY;
+ }
+
+ *buffer = newBuffer;
+ return NO_ERROR;
+}
+
+// caller must hold mTimedBufferQueueLock
+void AudioFlinger::PlaybackThread::TimedTrack::trimTimedBufferQueue_l() {
+ int64_t mediaTimeNow;
+ {
+ Mutex::Autolock mttLock(mMediaTimeTransformLock);
+ if (!mMediaTimeTransformValid)
+ return;
+
+ int64_t targetTimeNow;
+ status_t res = (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME)
+ ? mCCHelper.getCommonTime(&targetTimeNow)
+ : mCCHelper.getLocalTime(&targetTimeNow);
+
+ if (OK != res)
+ return;
+
+ if (!mMediaTimeTransform.doReverseTransform(targetTimeNow,
+ &mediaTimeNow)) {
+ return;
+ }
+ }
+
+ size_t trimIndex;
+ for (trimIndex = 0; trimIndex < mTimedBufferQueue.size(); trimIndex++) {
+ if (mTimedBufferQueue[trimIndex].pts() > mediaTimeNow)
+ break;
+ }
+
+ if (trimIndex) {
+ mTimedBufferQueue.removeItemsAt(0, trimIndex);
+ }
+}
+
+status_t AudioFlinger::PlaybackThread::TimedTrack::queueTimedBuffer(
+ const sp<IMemory>& buffer, int64_t pts) {
+
+ {
+ Mutex::Autolock mttLock(mMediaTimeTransformLock);
+ if (!mMediaTimeTransformValid)
+ return INVALID_OPERATION;
+ }
+
+ Mutex::Autolock _l(mTimedBufferQueueLock);
+
+ mTimedBufferQueue.add(TimedBuffer(buffer, pts));
+
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::PlaybackThread::TimedTrack::setMediaTimeTransform(
+ const LinearTransform& xform, TimedAudioTrack::TargetTimeline target) {
+
+ ALOGV("%s az=%lld bz=%lld n=%d d=%u tgt=%d", __PRETTY_FUNCTION__,
+ xform.a_zero, xform.b_zero, xform.a_to_b_numer, xform.a_to_b_denom,
+ target);
+
+ if (!(target == TimedAudioTrack::LOCAL_TIME ||
+ target == TimedAudioTrack::COMMON_TIME)) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mMediaTimeTransformLock);
+ mMediaTimeTransform = xform;
+ mMediaTimeTransformTarget = target;
+ mMediaTimeTransformValid = true;
+
+ return NO_ERROR;
+}
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+// implementation of getNextBuffer for tracks whose buffers have timestamps
+status_t AudioFlinger::PlaybackThread::TimedTrack::getNextBuffer(
+ AudioBufferProvider::Buffer* buffer, int64_t pts)
+{
+ if (pts == AudioBufferProvider::kInvalidPTS) {
+ buffer->raw = 0;
+ buffer->frameCount = 0;
+ return INVALID_OPERATION;
+ }
+
+ Mutex::Autolock _l(mTimedBufferQueueLock);
+
+ while (true) {
+
+ // if we have no timed buffers, then fail
+ if (mTimedBufferQueue.isEmpty()) {
+ buffer->raw = 0;
+ buffer->frameCount = 0;
+ return NOT_ENOUGH_DATA;
+ }
+
+ TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
+
+ // calculate the PTS of the head of the timed buffer queue expressed in
+ // local time
+ int64_t headLocalPTS;
+ {
+ Mutex::Autolock mttLock(mMediaTimeTransformLock);
+
+ ALOG_ASSERT(mMediaTimeTransformValid, "media time transform invalid");
+
+ if (mMediaTimeTransform.a_to_b_denom == 0) {
+ // the transform represents a pause, so yield silence
+ timedYieldSilence(buffer->frameCount, buffer);
+ return NO_ERROR;
+ }
+
+ int64_t transformedPTS;
+ if (!mMediaTimeTransform.doForwardTransform(head.pts(),
+ &transformedPTS)) {
+ // the transform failed. this shouldn't happen, but if it does
+ // then just drop this buffer
+ ALOGW("timedGetNextBuffer transform failed");
+ buffer->raw = 0;
+ buffer->frameCount = 0;
+ mTimedBufferQueue.removeAt(0);
+ return NO_ERROR;
+ }
+
+ if (mMediaTimeTransformTarget == TimedAudioTrack::COMMON_TIME) {
+ if (OK != mCCHelper.commonTimeToLocalTime(transformedPTS,
+ &headLocalPTS)) {
+ buffer->raw = 0;
+ buffer->frameCount = 0;
+ return INVALID_OPERATION;
+ }
+ } else {
+ headLocalPTS = transformedPTS;
+ }
+ }
+
+ // adjust the head buffer's PTS to reflect the portion of the head buffer
+ // that has already been consumed
+ int64_t effectivePTS = headLocalPTS +
+ ((head.position() / mCblk->frameSize) * mLocalTimeFreq / sampleRate());
+
+ // Calculate the delta in samples between the head of the input buffer
+ // queue and the start of the next output buffer that will be written.
+ // If the transformation fails because of over or underflow, it means
+ // that the sample's position in the output stream is so far out of
+ // whack that it should just be dropped.
+ int64_t sampleDelta;
+ if (llabs(effectivePTS - pts) >= (static_cast<int64_t>(1) << 31)) {
+ ALOGV("*** head buffer is too far from PTS: dropped buffer");
+ mTimedBufferQueue.removeAt(0);
+ continue;
+ }
+ if (!mLocalTimeToSampleTransform.doForwardTransform(
+ (effectivePTS - pts) << 32, &sampleDelta)) {
+ ALOGV("*** too late during sample rate transform: dropped buffer");
+ mTimedBufferQueue.removeAt(0);
+ continue;
+ }
+
+ ALOGV("*** %s head.pts=%lld head.pos=%d pts=%lld sampleDelta=[%d.%08x]",
+ __PRETTY_FUNCTION__, head.pts(), head.position(), pts,
+ static_cast<int32_t>((sampleDelta >= 0 ? 0 : 1) + (sampleDelta >> 32)),
+ static_cast<uint32_t>(sampleDelta & 0xFFFFFFFF));
+
+ // if the delta between the ideal placement for the next input sample and
+ // the current output position is within this threshold, then we will
+ // concatenate the next input samples to the previous output
+ const int64_t kSampleContinuityThreshold =
+ (static_cast<int64_t>(sampleRate()) << 32) / 10;
+
+ // if this is the first buffer of audio that we're emitting from this track
+ // then it should be almost exactly on time.
+ const int64_t kSampleStartupThreshold = 1LL << 32;
+
+ if ((mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleContinuityThreshold) ||
+ (!mTimedAudioOutputOnTime && llabs(sampleDelta) <= kSampleStartupThreshold)) {
+ // the next input is close enough to being on time, so concatenate it
+ // with the last output
+ timedYieldSamples(buffer);
+
+ ALOGV("*** on time: head.pos=%d frameCount=%u", head.position(), buffer->frameCount);
+ return NO_ERROR;
+ } else if (sampleDelta > 0) {
+ // the gap between the current output position and the proper start of
+ // the next input sample is too big, so fill it with silence
+ uint32_t framesUntilNextInput = (sampleDelta + 0x80000000) >> 32;
+
+ timedYieldSilence(framesUntilNextInput, buffer);
+ ALOGV("*** silence: frameCount=%u", buffer->frameCount);
+ return NO_ERROR;
+ } else {
+ // the next input sample is late
+ uint32_t lateFrames = static_cast<uint32_t>(-((sampleDelta + 0x80000000) >> 32));
+ size_t onTimeSamplePosition =
+ head.position() + lateFrames * mCblk->frameSize;
+
+ if (onTimeSamplePosition > head.buffer()->size()) {
+ // all the remaining samples in the head are too late, so
+ // drop it and move on
+ ALOGV("*** too late: dropped buffer");
+ mTimedBufferQueue.removeAt(0);
+ continue;
+ } else {
+ // skip over the late samples
+ head.setPosition(onTimeSamplePosition);
+
+ // yield the available samples
+ timedYieldSamples(buffer);
+
+ ALOGV("*** late: head.pos=%d frameCount=%u", head.position(), buffer->frameCount);
+ return NO_ERROR;
+ }
+ }
+ }
+}
+
+// Yield samples from the timed buffer queue head up to the given output
+// buffer's capacity.
+//
+// Caller must hold mTimedBufferQueueLock
+void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSamples(
+ AudioBufferProvider::Buffer* buffer) {
+
+ const TimedBuffer& head = mTimedBufferQueue[0];
+
+ buffer->raw = (static_cast<uint8_t*>(head.buffer()->pointer()) +
+ head.position());
+
+ uint32_t framesLeftInHead = ((head.buffer()->size() - head.position()) /
+ mCblk->frameSize);
+ size_t framesRequested = buffer->frameCount;
+ buffer->frameCount = min(framesLeftInHead, framesRequested);
+
+ mTimedAudioOutputOnTime = true;
+}
+
+// Yield samples of silence up to the given output buffer's capacity
+//
+// Caller must hold mTimedBufferQueueLock
+void AudioFlinger::PlaybackThread::TimedTrack::timedYieldSilence(
+ uint32_t numFrames, AudioBufferProvider::Buffer* buffer) {
+
+ // lazily allocate a buffer filled with silence
+ if (mTimedSilenceBufferSize < numFrames * mCblk->frameSize) {
+ delete [] mTimedSilenceBuffer;
+ mTimedSilenceBufferSize = numFrames * mCblk->frameSize;
+ mTimedSilenceBuffer = new uint8_t[mTimedSilenceBufferSize];
+ memset(mTimedSilenceBuffer, 0, mTimedSilenceBufferSize);
+ }
+
+ buffer->raw = mTimedSilenceBuffer;
+ size_t framesRequested = buffer->frameCount;
+ buffer->frameCount = min(numFrames, framesRequested);
+
+ mTimedAudioOutputOnTime = false;
+}
+
+// AudioBufferProvider interface
+void AudioFlinger::PlaybackThread::TimedTrack::releaseBuffer(
+ AudioBufferProvider::Buffer* buffer) {
+
+ Mutex::Autolock _l(mTimedBufferQueueLock);
+
+ // If the buffer which was just released is part of the buffer at the head
+ // of the queue, be sure to update the amt of the buffer which has been
+ // consumed. If the buffer being returned is not part of the head of the
+ // queue, its either because the buffer is part of the silence buffer, or
+ // because the head of the timed queue was trimmed after the mixer called
+ // getNextBuffer but before the mixer called releaseBuffer.
+ if ((buffer->raw != mTimedSilenceBuffer) && mTimedBufferQueue.size()) {
+ TimedBuffer& head = mTimedBufferQueue.editItemAt(0);
+
+ void* start = head.buffer()->pointer();
+ void* end = (char *) head.buffer()->pointer() + head.buffer()->size();
+
+ if ((buffer->raw >= start) && (buffer->raw <= end)) {
+ head.setPosition(head.position() +
+ (buffer->frameCount * mCblk->frameSize));
+ if (static_cast<size_t>(head.position()) >= head.buffer()->size()) {
+ mTimedBufferQueue.removeAt(0);
+ }
+ }
+ }
+
+ buffer->raw = 0;
+ buffer->frameCount = 0;
+}
+
+uint32_t AudioFlinger::PlaybackThread::TimedTrack::framesReady() const {
+ Mutex::Autolock _l(mTimedBufferQueueLock);
+
+ uint32_t frames = 0;
+ for (size_t i = 0; i < mTimedBufferQueue.size(); i++) {
+ const TimedBuffer& tb = mTimedBufferQueue[i];
+ frames += (tb.buffer()->size() - tb.position()) / mCblk->frameSize;
+ }
+
+ return frames;
+}
+
+AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer()
+ : mPTS(0), mPosition(0) {}
+
+AudioFlinger::PlaybackThread::TimedTrack::TimedBuffer::TimedBuffer(
+ const sp<IMemory>& buffer, int64_t pts)
+ : mBuffer(buffer), mPTS(pts), mPosition(0) {}
+
+// ----------------------------------------------------------------------------
+
+// RecordTrack constructor must be called with AudioFlinger::mLock held
+AudioFlinger::RecordThread::RecordTrack::RecordTrack(
+ RecordThread *thread,
+ const sp<Client>& client,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ int sessionId)
+ : TrackBase(thread, client, sampleRate, format,
+ channelMask, frameCount, 0 /*sharedBuffer*/, sessionId),
+ mOverflow(false)
+{
+ if (mCblk != NULL) {
+ ALOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
+ if (format == AUDIO_FORMAT_PCM_16_BIT) {
+ mCblk->frameSize = mChannelCount * sizeof(int16_t);
+ } else if (format == AUDIO_FORMAT_PCM_8_BIT) {
+ mCblk->frameSize = mChannelCount * sizeof(int8_t);
+ } else {
+ mCblk->frameSize = sizeof(int8_t);
+ }
+ }
+}
+
+AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
+{
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ AudioSystem::releaseInput(thread->id());
+ }
+}
+
+// AudioBufferProvider interface
+status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts)
+{
+ audio_track_cblk_t* cblk = this->cblk();
+ uint32_t framesAvail;
+ uint32_t framesReq = buffer->frameCount;
+
+ // Check if last stepServer failed, try to step now
+ if (mStepServerFailed) {
+ if (!step()) goto getNextBuffer_exit;
+ ALOGV("stepServer recovered");
+ mStepServerFailed = false;
+ }
+
+ framesAvail = cblk->framesAvailable_l();
+
+ if (CC_LIKELY(framesAvail)) {
+ uint32_t s = cblk->server;
+ uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
+
+ if (framesReq > framesAvail) {
+ framesReq = framesAvail;
+ }
+ if (s + framesReq > bufferEnd) {
+ framesReq = bufferEnd - s;
+ }
+
+ buffer->raw = getBuffer(s, framesReq);
+ if (buffer->raw == NULL) goto getNextBuffer_exit;
+
+ buffer->frameCount = framesReq;
+ return NO_ERROR;
+ }
+
+getNextBuffer_exit:
+ buffer->raw = NULL;
+ buffer->frameCount = 0;
+ return NOT_ENOUGH_DATA;
+}
+
+status_t AudioFlinger::RecordThread::RecordTrack::start(pid_t tid)
+{
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ RecordThread *recordThread = (RecordThread *)thread.get();
+ return recordThread->start(this, tid);
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+void AudioFlinger::RecordThread::RecordTrack::stop()
+{
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ RecordThread *recordThread = (RecordThread *)thread.get();
+ recordThread->stop(this);
+ TrackBase::reset();
+ // Force overrun condition to avoid false overrun callback until first data is
+ // read from buffer
+ android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
+ }
+}
+
+void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
+{
+ snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x\n",
+ (mClient == 0) ? getpid_cached : mClient->pid(),
+ mFormat,
+ mChannelMask,
+ mSessionId,
+ mFrameCount,
+ mState,
+ mCblk->sampleRate,
+ mCblk->server,
+ mCblk->user);
+}
+
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
+ PlaybackThread *playbackThread,
+ DuplicatingThread *sourceThread,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount)
+ : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, NULL, 0),
+ mActive(false), mSourceThread(sourceThread)
+{
+
+ if (mCblk != NULL) {
+ mCblk->flags |= CBLK_DIRECTION_OUT;
+ mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
+ mOutBuffer.frameCount = 0;
+ playbackThread->mTracks.add(this);
+ ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, " \
+ "mCblk->frameCount %d, mCblk->sampleRate %d, mChannelMask 0x%08x mBufferEnd %p",
+ mCblk, mBuffer, mCblk->buffers,
+ mCblk->frameCount, mCblk->sampleRate, mChannelMask, mBufferEnd);
+ } else {
+ ALOGW("Error creating output track on thread %p", playbackThread);
+ }
+}
+
+AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
+{
+ clearBufferQueue();
+}
+
+status_t AudioFlinger::PlaybackThread::OutputTrack::start(pid_t tid)
+{
+ status_t status = Track::start(tid);
+ if (status != NO_ERROR) {
+ return status;
+ }
+
+ mActive = true;
+ mRetryCount = 127;
+ return status;
+}
+
+void AudioFlinger::PlaybackThread::OutputTrack::stop()
+{
+ Track::stop();
+ clearBufferQueue();
+ mOutBuffer.frameCount = 0;
+ mActive = false;
+}
+
+bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
+{
+ Buffer *pInBuffer;
+ Buffer inBuffer;
+ uint32_t channelCount = mChannelCount;
+ bool outputBufferFull = false;
+ inBuffer.frameCount = frames;
+ inBuffer.i16 = data;
+
+ uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
+
+ if (!mActive && frames != 0) {
+ start(0);
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ MixerThread *mixerThread = (MixerThread *)thread.get();
+ if (mCblk->frameCount > frames){
+ if (mBufferQueue.size() < kMaxOverFlowBuffers) {
+ uint32_t startFrames = (mCblk->frameCount - frames);
+ pInBuffer = new Buffer;
+ pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
+ pInBuffer->frameCount = startFrames;
+ pInBuffer->i16 = pInBuffer->mBuffer;
+ memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
+ mBufferQueue.add(pInBuffer);
+ } else {
+ ALOGW ("OutputTrack::write() %p no more buffers in queue", this);
+ }
+ }
+ }
+ }
+
+ while (waitTimeLeftMs) {
+ // First write pending buffers, then new data
+ if (mBufferQueue.size()) {
+ pInBuffer = mBufferQueue.itemAt(0);
+ } else {
+ pInBuffer = &inBuffer;
+ }
+
+ if (pInBuffer->frameCount == 0) {
+ break;
+ }
+
+ if (mOutBuffer.frameCount == 0) {
+ mOutBuffer.frameCount = pInBuffer->frameCount;
+ nsecs_t startTime = systemTime();
+ if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)NO_MORE_BUFFERS) {
+ ALOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
+ outputBufferFull = true;
+ break;
+ }
+ uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
+ if (waitTimeLeftMs >= waitTimeMs) {
+ waitTimeLeftMs -= waitTimeMs;
+ } else {
+ waitTimeLeftMs = 0;
+ }
+ }
+
+ uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
+ memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
+ mCblk->stepUser(outFrames);
+ pInBuffer->frameCount -= outFrames;
+ pInBuffer->i16 += outFrames * channelCount;
+ mOutBuffer.frameCount -= outFrames;
+ mOutBuffer.i16 += outFrames * channelCount;
+
+ if (pInBuffer->frameCount == 0) {
+ if (mBufferQueue.size()) {
+ mBufferQueue.removeAt(0);
+ delete [] pInBuffer->mBuffer;
+ delete pInBuffer;
+ ALOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
+ } else {
+ break;
+ }
+ }
+ }
+
+ // If we could not write all frames, allocate a buffer and queue it for next time.
+ if (inBuffer.frameCount) {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0 && !thread->standby()) {
+ if (mBufferQueue.size() < kMaxOverFlowBuffers) {
+ pInBuffer = new Buffer;
+ pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
+ pInBuffer->frameCount = inBuffer.frameCount;
+ pInBuffer->i16 = pInBuffer->mBuffer;
+ memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
+ mBufferQueue.add(pInBuffer);
+ ALOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
+ } else {
+ ALOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
+ }
+ }
+ }
+
+ // Calling write() with a 0 length buffer, means that no more data will be written:
+ // If no more buffers are pending, fill output track buffer to make sure it is started
+ // by output mixer.
+ if (frames == 0 && mBufferQueue.size() == 0) {
+ if (mCblk->user < mCblk->frameCount) {
+ frames = mCblk->frameCount - mCblk->user;
+ pInBuffer = new Buffer;
+ pInBuffer->mBuffer = new int16_t[frames * channelCount];
+ pInBuffer->frameCount = frames;
+ pInBuffer->i16 = pInBuffer->mBuffer;
+ memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
+ mBufferQueue.add(pInBuffer);
+ } else if (mActive) {
+ stop();
+ }
+ }
+
+ return outputBufferFull;
+}
+
+status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
+{
+ int active;
+ status_t result;
+ audio_track_cblk_t* cblk = mCblk;
+ uint32_t framesReq = buffer->frameCount;
+
+// ALOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
+ buffer->frameCount = 0;
+
+ uint32_t framesAvail = cblk->framesAvailable();
+
+
+ if (framesAvail == 0) {
+ Mutex::Autolock _l(cblk->lock);
+ goto start_loop_here;
+ while (framesAvail == 0) {
+ active = mActive;
+ if (CC_UNLIKELY(!active)) {
+ ALOGV("Not active and NO_MORE_BUFFERS");
+ return NO_MORE_BUFFERS;
+ }
+ result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
+ if (result != NO_ERROR) {
+ return NO_MORE_BUFFERS;
+ }
+ // read the server count again
+ start_loop_here:
+ framesAvail = cblk->framesAvailable_l();
+ }
+ }
+
+// if (framesAvail < framesReq) {
+// return NO_MORE_BUFFERS;
+// }
+
+ if (framesReq > framesAvail) {
+ framesReq = framesAvail;
+ }
+
+ uint32_t u = cblk->user;
+ uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
+
+ if (u + framesReq > bufferEnd) {
+ framesReq = bufferEnd - u;
+ }
+
+ buffer->frameCount = framesReq;
+ buffer->raw = (void *)cblk->buffer(u);
+ return NO_ERROR;
+}
+
+
+void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
+{
+ size_t size = mBufferQueue.size();
+
+ for (size_t i = 0; i < size; i++) {
+ Buffer *pBuffer = mBufferQueue.itemAt(i);
+ delete [] pBuffer->mBuffer;
+ delete pBuffer;
+ }
+ mBufferQueue.clear();
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
+ : RefBase(),
+ mAudioFlinger(audioFlinger),
+ // FIXME should be a "k" constant not hard-coded, in .h or ro. property, see 4 lines below
+ mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
+ mPid(pid),
+ mTimedTrackCount(0)
+{
+ // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
+}
+
+// Client destructor must be called with AudioFlinger::mLock held
+AudioFlinger::Client::~Client()
+{
+ mAudioFlinger->removeClient_l(mPid);
+}
+
+sp<MemoryDealer> AudioFlinger::Client::heap() const
+{
+ return mMemoryDealer;
+}
+
+// Reserve one of the limited slots for a timed audio track associated
+// with this client
+bool AudioFlinger::Client::reserveTimedTrack()
+{
+ const int kMaxTimedTracksPerClient = 4;
+
+ Mutex::Autolock _l(mTimedTrackLock);
+
+ if (mTimedTrackCount >= kMaxTimedTracksPerClient) {
+ ALOGW("can not create timed track - pid %d has exceeded the limit",
+ mPid);
+ return false;
+ }
+
+ mTimedTrackCount++;
+ return true;
+}
+
+// Release a slot for a timed audio track
+void AudioFlinger::Client::releaseTimedTrack()
+{
+ Mutex::Autolock _l(mTimedTrackLock);
+ mTimedTrackCount--;
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
+ const sp<IAudioFlingerClient>& client,
+ pid_t pid)
+ : mAudioFlinger(audioFlinger), mPid(pid), mAudioFlingerClient(client)
+{
+}
+
+AudioFlinger::NotificationClient::~NotificationClient()
+{
+}
+
+void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
+{
+ sp<NotificationClient> keep(this);
+ mAudioFlinger->removeNotificationClient(mPid);
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
+ : BnAudioTrack(),
+ mTrack(track)
+{
+}
+
+AudioFlinger::TrackHandle::~TrackHandle() {
+ // just stop the track on deletion, associated resources
+ // will be freed from the main thread once all pending buffers have
+ // been played. Unless it's not in the active track list, in which
+ // case we free everything now...
+ mTrack->destroy();
+}
+
+sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
+ return mTrack->getCblk();
+}
+
+status_t AudioFlinger::TrackHandle::start(pid_t tid) {
+ return mTrack->start(tid);
+}
+
+void AudioFlinger::TrackHandle::stop() {
+ mTrack->stop();
+}
+
+void AudioFlinger::TrackHandle::flush() {
+ mTrack->flush();
+}
+
+void AudioFlinger::TrackHandle::mute(bool e) {
+ mTrack->mute(e);
+}
+
+void AudioFlinger::TrackHandle::pause() {
+ mTrack->pause();
+}
+
+status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
+{
+ return mTrack->attachAuxEffect(EffectId);
+}
+
+status_t AudioFlinger::TrackHandle::allocateTimedBuffer(size_t size,
+ sp<IMemory>* buffer) {
+ if (!mTrack->isTimedTrack())
+ return INVALID_OPERATION;
+
+ PlaybackThread::TimedTrack* tt =
+ reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
+ return tt->allocateTimedBuffer(size, buffer);
+}
+
+status_t AudioFlinger::TrackHandle::queueTimedBuffer(const sp<IMemory>& buffer,
+ int64_t pts) {
+ if (!mTrack->isTimedTrack())
+ return INVALID_OPERATION;
+
+ PlaybackThread::TimedTrack* tt =
+ reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
+ return tt->queueTimedBuffer(buffer, pts);
+}
+
+status_t AudioFlinger::TrackHandle::setMediaTimeTransform(
+ const LinearTransform& xform, int target) {
+
+ if (!mTrack->isTimedTrack())
+ return INVALID_OPERATION;
+
+ PlaybackThread::TimedTrack* tt =
+ reinterpret_cast<PlaybackThread::TimedTrack*>(mTrack.get());
+ return tt->setMediaTimeTransform(
+ xform, static_cast<TimedAudioTrack::TargetTimeline>(target));
+}
+
+status_t AudioFlinger::TrackHandle::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ return BnAudioTrack::onTransact(code, data, reply, flags);
+}
+
+// ----------------------------------------------------------------------------
+
+sp<IAudioRecord> AudioFlinger::openRecord(
+ pid_t pid,
+ audio_io_handle_t input,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ IAudioFlinger::track_flags_t flags,
+ int *sessionId,
+ status_t *status)
+{
+ sp<RecordThread::RecordTrack> recordTrack;
+ sp<RecordHandle> recordHandle;
+ sp<Client> client;
+ status_t lStatus;
+ RecordThread *thread;
+ size_t inFrameCount;
+ int lSessionId;
+
+ // check calling permissions
+ if (!recordingAllowed()) {
+ lStatus = PERMISSION_DENIED;
+ goto Exit;
+ }
+
+ // add client to list
+ { // scope for mLock
+ Mutex::Autolock _l(mLock);
+ thread = checkRecordThread_l(input);
+ if (thread == NULL) {
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+
+ client = registerPid_l(pid);
+
+ // If no audio session id is provided, create one here
+ if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
+ lSessionId = *sessionId;
+ } else {
+ lSessionId = nextUniqueId();
+ if (sessionId != NULL) {
+ *sessionId = lSessionId;
+ }
+ }
+ // create new record track. The record track uses one track in mHardwareMixerThread by convention.
+ recordTrack = thread->createRecordTrack_l(client,
+ sampleRate,
+ format,
+ channelMask,
+ frameCount,
+ lSessionId,
+ &lStatus);
+ }
+ if (lStatus != NO_ERROR) {
+ // remove local strong reference to Client before deleting the RecordTrack so that the Client
+ // destructor is called by the TrackBase destructor with mLock held
+ client.clear();
+ recordTrack.clear();
+ goto Exit;
+ }
+
+ // return to handle to client
+ recordHandle = new RecordHandle(recordTrack);
+ lStatus = NO_ERROR;
+
+Exit:
+ if (status) {
+ *status = lStatus;
+ }
+ return recordHandle;
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
+ : BnAudioRecord(),
+ mRecordTrack(recordTrack)
+{
+}
+
+AudioFlinger::RecordHandle::~RecordHandle() {
+ stop();
+}
+
+sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
+ return mRecordTrack->getCblk();
+}
+
+status_t AudioFlinger::RecordHandle::start(pid_t tid) {
+ ALOGV("RecordHandle::start()");
+ return mRecordTrack->start(tid);
+}
+
+void AudioFlinger::RecordHandle::stop() {
+ ALOGV("RecordHandle::stop()");
+ mRecordTrack->stop();
+}
+
+status_t AudioFlinger::RecordHandle::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ return BnAudioRecord::onTransact(code, data, reply, flags);
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
+ AudioStreamIn *input,
+ uint32_t sampleRate,
+ uint32_t channels,
+ audio_io_handle_t id,
+ uint32_t device) :
+ ThreadBase(audioFlinger, id, device, RECORD),
+ mInput(input), mTrack(NULL), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL),
+ // mRsmpInIndex and mInputBytes set by readInputParameters()
+ mReqChannelCount(popcount(channels)),
+ mReqSampleRate(sampleRate)
+ // mBytesRead is only meaningful while active, and so is cleared in start()
+ // (but might be better to also clear here for dump?)
+{
+ snprintf(mName, kNameLength, "AudioIn_%X", id);
+
+ readInputParameters();
+}
+
+
+AudioFlinger::RecordThread::~RecordThread()
+{
+ delete[] mRsmpInBuffer;
+ delete mResampler;
+ delete[] mRsmpOutBuffer;
+}
+
+void AudioFlinger::RecordThread::onFirstRef()
+{
+ run(mName, PRIORITY_URGENT_AUDIO);
+}
+
+status_t AudioFlinger::RecordThread::readyToRun()
+{
+ status_t status = initCheck();
+ ALOGW_IF(status != NO_ERROR,"RecordThread %p could not initialize", this);
+ return status;
+}
+
+bool AudioFlinger::RecordThread::threadLoop()
+{
+ AudioBufferProvider::Buffer buffer;
+ sp<RecordTrack> activeTrack;
+ Vector< sp<EffectChain> > effectChains;
+
+ nsecs_t lastWarning = 0;
+
+ acquireWakeLock();
+
+ // start recording
+ while (!exitPending()) {
+
+ processConfigEvents();
+
+ { // scope for mLock
+ Mutex::Autolock _l(mLock);
+ checkForNewParameters_l();
+ if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
+ if (!mStandby) {
+ mInput->stream->common.standby(&mInput->stream->common);
+ mStandby = true;
+ }
+
+ if (exitPending()) break;
+
+ releaseWakeLock_l();
+ ALOGV("RecordThread: loop stopping");
+ // go to sleep
+ mWaitWorkCV.wait(mLock);
+ ALOGV("RecordThread: loop starting");
+ acquireWakeLock_l();
+ continue;
+ }
+ if (mActiveTrack != 0) {
+ if (mActiveTrack->mState == TrackBase::PAUSING) {
+ if (!mStandby) {
+ mInput->stream->common.standby(&mInput->stream->common);
+ mStandby = true;
+ }
+ mActiveTrack.clear();
+ mStartStopCond.broadcast();
+ } else if (mActiveTrack->mState == TrackBase::RESUMING) {
+ if (mReqChannelCount != mActiveTrack->channelCount()) {
+ mActiveTrack.clear();
+ mStartStopCond.broadcast();
+ } else if (mBytesRead != 0) {
+ // record start succeeds only if first read from audio input
+ // succeeds
+ if (mBytesRead > 0) {
+ mActiveTrack->mState = TrackBase::ACTIVE;
+ } else {
+ mActiveTrack.clear();
+ }
+ mStartStopCond.broadcast();
+ }
+ mStandby = false;
+ }
+ }
+ lockEffectChains_l(effectChains);
+ }
+
+ if (mActiveTrack != 0) {
+ if (mActiveTrack->mState != TrackBase::ACTIVE &&
+ mActiveTrack->mState != TrackBase::RESUMING) {
+ unlockEffectChains(effectChains);
+ usleep(kRecordThreadSleepUs);
+ continue;
+ }
+ for (size_t i = 0; i < effectChains.size(); i ++) {
+ effectChains[i]->process_l();
+ }
+
+ buffer.frameCount = mFrameCount;
+ if (CC_LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
+ size_t framesOut = buffer.frameCount;
+ if (mResampler == NULL) {
+ // no resampling
+ while (framesOut) {
+ size_t framesIn = mFrameCount - mRsmpInIndex;
+ if (framesIn) {
+ int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
+ int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
+ if (framesIn > framesOut)
+ framesIn = framesOut;
+ mRsmpInIndex += framesIn;
+ framesOut -= framesIn;
+ if ((int)mChannelCount == mReqChannelCount ||
+ mFormat != AUDIO_FORMAT_PCM_16_BIT) {
+ memcpy(dst, src, framesIn * mFrameSize);
+ } else {
+ int16_t *src16 = (int16_t *)src;
+ int16_t *dst16 = (int16_t *)dst;
+ if (mChannelCount == 1) {
+ while (framesIn--) {
+ *dst16++ = *src16;
+ *dst16++ = *src16++;
+ }
+ } else {
+ while (framesIn--) {
+ *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
+ src16 += 2;
+ }
+ }
+ }
+ }
+ if (framesOut && mFrameCount == mRsmpInIndex) {
+ if (framesOut == mFrameCount &&
+ ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) {
+ mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes);
+ framesOut = 0;
+ } else {
+ mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
+ mRsmpInIndex = 0;
+ }
+ if (mBytesRead < 0) {
+ ALOGE("Error reading audio input");
+ if (mActiveTrack->mState == TrackBase::ACTIVE) {
+ // Force input into standby so that it tries to
+ // recover at next read attempt
+ mInput->stream->common.standby(&mInput->stream->common);
+ usleep(kRecordThreadSleepUs);
+ }
+ mRsmpInIndex = mFrameCount;
+ framesOut = 0;
+ buffer.frameCount = 0;
+ }
+ }
+ }
+ } else {
+ // resampling
+
+ memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
+ // alter output frame count as if we were expecting stereo samples
+ if (mChannelCount == 1 && mReqChannelCount == 1) {
+ framesOut >>= 1;
+ }
+ mResampler->resample(mRsmpOutBuffer, framesOut, this);
+ // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
+ // are 32 bit aligned which should be always true.
+ if (mChannelCount == 2 && mReqChannelCount == 1) {
+ ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
+ // the resampler always outputs stereo samples: do post stereo to mono conversion
+ int16_t *src = (int16_t *)mRsmpOutBuffer;
+ int16_t *dst = buffer.i16;
+ while (framesOut--) {
+ *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
+ src += 2;
+ }
+ } else {
+ ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
+ }
+
+ }
+ mActiveTrack->releaseBuffer(&buffer);
+ mActiveTrack->overflow();
+ }
+ // client isn't retrieving buffers fast enough
+ else {
+ if (!mActiveTrack->setOverflow()) {
+ nsecs_t now = systemTime();
+ if ((now - lastWarning) > kWarningThrottleNs) {
+ ALOGW("RecordThread: buffer overflow");
+ lastWarning = now;
+ }
+ }
+ // Release the processor for a while before asking for a new buffer.
+ // This will give the application more chance to read from the buffer and
+ // clear the overflow.
+ usleep(kRecordThreadSleepUs);
+ }
+ }
+ // enable changes in effect chain
+ unlockEffectChains(effectChains);
+ effectChains.clear();
+ }
+
+ if (!mStandby) {
+ mInput->stream->common.standby(&mInput->stream->common);
+ }
+ mActiveTrack.clear();
+
+ mStartStopCond.broadcast();
+
+ releaseWakeLock();
+
+ ALOGV("RecordThread %p exiting", this);
+ return false;
+}
+
+
+sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
+ const sp<AudioFlinger::Client>& client,
+ uint32_t sampleRate,
+ audio_format_t format,
+ int channelMask,
+ int frameCount,
+ int sessionId,
+ status_t *status)
+{
+ sp<RecordTrack> track;
+ status_t lStatus;
+
+ lStatus = initCheck();
+ if (lStatus != NO_ERROR) {
+ ALOGE("Audio driver not initialized.");
+ goto Exit;
+ }
+
+ { // scope for mLock
+ Mutex::Autolock _l(mLock);
+
+ track = new RecordTrack(this, client, sampleRate,
+ format, channelMask, frameCount, sessionId);
+
+ if (track->getCblk() == 0) {
+ lStatus = NO_MEMORY;
+ goto Exit;
+ }
+
+ mTrack = track.get();
+ // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
+ bool suspend = audio_is_bluetooth_sco_device(
+ (audio_devices_t)(mDevice & AUDIO_DEVICE_IN_ALL)) && mAudioFlinger->btNrecIsOff();
+ setEffectSuspended_l(FX_IID_AEC, suspend, sessionId);
+ setEffectSuspended_l(FX_IID_NS, suspend, sessionId);
+ }
+ lStatus = NO_ERROR;
+
+Exit:
+ if (status) {
+ *status = lStatus;
+ }
+ return track;
+}
+
+status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack, pid_t tid)
+{
+ ALOGV("RecordThread::start tid=%d", tid);
+ sp<ThreadBase> strongMe = this;
+ status_t status = NO_ERROR;
+ {
+ AutoMutex lock(mLock);
+ if (mActiveTrack != 0) {
+ if (recordTrack != mActiveTrack.get()) {
+ status = -EBUSY;
+ } else if (mActiveTrack->mState == TrackBase::PAUSING) {
+ mActiveTrack->mState = TrackBase::ACTIVE;
+ }
+ return status;
+ }
+
+ recordTrack->mState = TrackBase::IDLE;
+ mActiveTrack = recordTrack;
+ mLock.unlock();
+ status_t status = AudioSystem::startInput(mId);
+ mLock.lock();
+ if (status != NO_ERROR) {
+ mActiveTrack.clear();
+ return status;
+ }
+ mRsmpInIndex = mFrameCount;
+ mBytesRead = 0;
+ if (mResampler != NULL) {
+ mResampler->reset();
+ }
+ mActiveTrack->mState = TrackBase::RESUMING;
+ // signal thread to start
+ ALOGV("Signal record thread");
+ mWaitWorkCV.signal();
+ // do not wait for mStartStopCond if exiting
+ if (exitPending()) {
+ mActiveTrack.clear();
+ status = INVALID_OPERATION;
+ goto startError;
+ }
+ mStartStopCond.wait(mLock);
+ if (mActiveTrack == 0) {
+ ALOGV("Record failed to start");
+ status = BAD_VALUE;
+ goto startError;
+ }
+ ALOGV("Record started OK");
+ return status;
+ }
+startError:
+ AudioSystem::stopInput(mId);
+ return status;
+}
+
+void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
+ ALOGV("RecordThread::stop");
+ sp<ThreadBase> strongMe = this;
+ {
+ AutoMutex lock(mLock);
+ if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
+ mActiveTrack->mState = TrackBase::PAUSING;
+ // do not wait for mStartStopCond if exiting
+ if (exitPending()) {
+ return;
+ }
+ mStartStopCond.wait(mLock);
+ // if we have been restarted, recordTrack == mActiveTrack.get() here
+ if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
+ mLock.unlock();
+ AudioSystem::stopInput(mId);
+ mLock.lock();
+ ALOGV("Record stopped OK");
+ }
+ }
+ }
+}
+
+status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
+ result.append(buffer);
+
+ if (mActiveTrack != 0) {
+ result.append("Active Track:\n");
+ result.append(" Clien Fmt Chn mask Session Buf S SRate Serv User\n");
+ mActiveTrack->dump(buffer, SIZE);
+ result.append(buffer);
+
+ snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != NULL));
+ result.append(buffer);
+ snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
+ result.append(buffer);
+
+
+ } else {
+ result.append("No record client\n");
+ }
+ write(fd, result.string(), result.size());
+
+ dumpBase(fd, args);
+ dumpEffectChains(fd, args);
+
+ return NO_ERROR;
+}
+
+// AudioBufferProvider interface
+status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts)
+{
+ size_t framesReq = buffer->frameCount;
+ size_t framesReady = mFrameCount - mRsmpInIndex;
+ int channelCount;
+
+ if (framesReady == 0) {
+ mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
+ if (mBytesRead < 0) {
+ ALOGE("RecordThread::getNextBuffer() Error reading audio input");
+ if (mActiveTrack->mState == TrackBase::ACTIVE) {
+ // Force input into standby so that it tries to
+ // recover at next read attempt
+ mInput->stream->common.standby(&mInput->stream->common);
+ usleep(kRecordThreadSleepUs);
+ }
+ buffer->raw = NULL;
+ buffer->frameCount = 0;
+ return NOT_ENOUGH_DATA;
+ }
+ mRsmpInIndex = 0;
+ framesReady = mFrameCount;
+ }
+
+ if (framesReq > framesReady) {
+ framesReq = framesReady;
+ }
+
+ if (mChannelCount == 1 && mReqChannelCount == 2) {
+ channelCount = 1;
+ } else {
+ channelCount = 2;
+ }
+ buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
+ buffer->frameCount = framesReq;
+ return NO_ERROR;
+}
+
+// AudioBufferProvider interface
+void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+{
+ mRsmpInIndex += buffer->frameCount;
+ buffer->frameCount = 0;
+}
+
+bool AudioFlinger::RecordThread::checkForNewParameters_l()
+{
+ bool reconfig = false;
+
+ while (!mNewParameters.isEmpty()) {
+ status_t status = NO_ERROR;
+ String8 keyValuePair = mNewParameters[0];
+ AudioParameter param = AudioParameter(keyValuePair);
+ int value;
+ audio_format_t reqFormat = mFormat;
+ int reqSamplingRate = mReqSampleRate;
+ int reqChannelCount = mReqChannelCount;
+
+ if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
+ reqSamplingRate = value;
+ reconfig = true;
+ }
+ if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
+ reqFormat = (audio_format_t) value;
+ reconfig = true;
+ }
+ if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
+ reqChannelCount = popcount(value);
+ reconfig = true;
+ }
+ if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
+ // do not accept frame count changes if tracks are open as the track buffer
+ // size depends on frame count and correct behavior would not be guaranteed
+ // if frame count is changed after track creation
+ if (mActiveTrack != 0) {
+ status = INVALID_OPERATION;
+ } else {
+ reconfig = true;
+ }
+ }
+ if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
+ // forward device change to effects that have requested to be
+ // aware of attached audio device.
+ for (size_t i = 0; i < mEffectChains.size(); i++) {
+ mEffectChains[i]->setDevice_l(value);
+ }
+ // store input device and output device but do not forward output device to audio HAL.
+ // Note that status is ignored by the caller for output device
+ // (see AudioFlinger::setParameters()
+ if (value & AUDIO_DEVICE_OUT_ALL) {
+ mDevice &= (uint32_t)~(value & AUDIO_DEVICE_OUT_ALL);
+ status = BAD_VALUE;
+ } else {
+ mDevice &= (uint32_t)~(value & AUDIO_DEVICE_IN_ALL);
+ // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
+ if (mTrack != NULL) {
+ bool suspend = audio_is_bluetooth_sco_device(
+ (audio_devices_t)value) && mAudioFlinger->btNrecIsOff();
+ setEffectSuspended_l(FX_IID_AEC, suspend, mTrack->sessionId());
+ setEffectSuspended_l(FX_IID_NS, suspend, mTrack->sessionId());
+ }
+ }
+ mDevice |= (uint32_t)value;
+ }
+ if (status == NO_ERROR) {
+ status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
+ if (status == INVALID_OPERATION) {
+ mInput->stream->common.standby(&mInput->stream->common);
+ status = mInput->stream->common.set_parameters(&mInput->stream->common,
+ keyValuePair.string());
+ }
+ if (reconfig) {
+ if (status == BAD_VALUE &&
+ reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
+ reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
+ ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
+ popcount(mInput->stream->common.get_channels(&mInput->stream->common)) <= FCC_2 &&
+ (reqChannelCount <= FCC_2)) {
+ status = NO_ERROR;
+ }
+ if (status == NO_ERROR) {
+ readInputParameters();
+ sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
+ }
+ }
+ }
+
+ mNewParameters.removeAt(0);
+
+ mParamStatus = status;
+ mParamCond.signal();
+ // wait for condition with time out in case the thread calling ThreadBase::setParameters()
+ // already timed out waiting for the status and will never signal the condition.
+ mWaitWorkCV.waitRelative(mLock, kSetParametersTimeoutNs);
+ }
+ return reconfig;
+}
+
+String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
+{
+ char *s;
+ String8 out_s8 = String8();
+
+ Mutex::Autolock _l(mLock);
+ if (initCheck() != NO_ERROR) {
+ return out_s8;
+ }
+
+ s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
+ out_s8 = String8(s);
+ free(s);
+ return out_s8;
+}
+
+void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
+ AudioSystem::OutputDescriptor desc;
+ void *param2 = NULL;
+
+ switch (event) {
+ case AudioSystem::INPUT_OPENED:
+ case AudioSystem::INPUT_CONFIG_CHANGED:
+ desc.channels = mChannelMask;
+ desc.samplingRate = mSampleRate;
+ desc.format = mFormat;
+ desc.frameCount = mFrameCount;
+ desc.latency = 0;
+ param2 = &desc;
+ break;
+
+ case AudioSystem::INPUT_CLOSED:
+ default:
+ break;
+ }
+ mAudioFlinger->audioConfigChanged_l(event, mId, param2);
+}
+
+void AudioFlinger::RecordThread::readInputParameters()
+{
+ delete mRsmpInBuffer;
+ // mRsmpInBuffer is always assigned a new[] below
+ delete mRsmpOutBuffer;
+ mRsmpOutBuffer = NULL;
+ delete mResampler;
+ mResampler = NULL;
+
+ mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
+ mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
+ mChannelCount = (uint16_t)popcount(mChannelMask);
+ mFormat = mInput->stream->common.get_format(&mInput->stream->common);
+ mFrameSize = audio_stream_frame_size(&mInput->stream->common);
+ mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
+ mFrameCount = mInputBytes / mFrameSize;
+ mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
+
+ if (mSampleRate != mReqSampleRate && mChannelCount <= FCC_2 && mReqChannelCount <= FCC_2)
+ {
+ int channelCount;
+ // optimization: if mono to mono, use the resampler in stereo to stereo mode to avoid
+ // stereo to mono post process as the resampler always outputs stereo.
+ if (mChannelCount == 1 && mReqChannelCount == 2) {
+ channelCount = 1;
+ } else {
+ channelCount = 2;
+ }
+ mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
+ mResampler->setSampleRate(mSampleRate);
+ mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
+ mRsmpOutBuffer = new int32_t[mFrameCount * 2];
+
+ // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
+ if (mChannelCount == 1 && mReqChannelCount == 1) {
+ mFrameCount >>= 1;
+ }
+
+ }
+ mRsmpInIndex = mFrameCount;
+}
+
+unsigned int AudioFlinger::RecordThread::getInputFramesLost()
+{
+ Mutex::Autolock _l(mLock);
+ if (initCheck() != NO_ERROR) {
+ return 0;
+ }
+
+ return mInput->stream->get_input_frames_lost(mInput->stream);
+}
+
+uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId)
+{
+ Mutex::Autolock _l(mLock);
+ uint32_t result = 0;
+ if (getEffectChain_l(sessionId) != 0) {
+ result = EFFECT_SESSION;
+ }
+
+ if (mTrack != NULL && sessionId == mTrack->sessionId()) {
+ result |= TRACK_SESSION;
+ }
+
+ return result;
+}
+
+AudioFlinger::RecordThread::RecordTrack* AudioFlinger::RecordThread::track()
+{
+ Mutex::Autolock _l(mLock);
+ return mTrack;
+}
+
+AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::getInput() const
+{
+ Mutex::Autolock _l(mLock);
+ return mInput;
+}
+
+AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
+{
+ Mutex::Autolock _l(mLock);
+ AudioStreamIn *input = mInput;
+ mInput = NULL;
+ return input;
+}
+
+// this method must always be called either with ThreadBase mLock held or inside the thread loop
+audio_stream_t* AudioFlinger::RecordThread::stream()
+{
+ if (mInput == NULL) {
+ return NULL;
+ }
+ return &mInput->stream->common;
+}
+
+
+// ----------------------------------------------------------------------------
+
+audio_io_handle_t AudioFlinger::openOutput(uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ audio_format_t *pFormat,
+ uint32_t *pChannels,
+ uint32_t *pLatencyMs,
+ audio_policy_output_flags_t flags)
+{
+ status_t status;
+ PlaybackThread *thread = NULL;
+ uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+ audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT;
+ uint32_t channels = pChannels ? *pChannels : 0;
+ uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
+ audio_stream_out_t *outStream;
+ audio_hw_device_t *outHwDev;
+
+ ALOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
+ pDevices ? *pDevices : 0,
+ samplingRate,
+ format,
+ channels,
+ flags);
+
+ if (pDevices == NULL || *pDevices == 0) {
+ return 0;
+ }
+
+ Mutex::Autolock _l(mLock);
+
+ outHwDev = findSuitableHwDev_l(*pDevices);
+ if (outHwDev == NULL)
+ return 0;
+
+ mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
+ status = outHwDev->open_output_stream(outHwDev, *pDevices, &format,
+ &channels, &samplingRate, &outStream);
+ mHardwareStatus = AUDIO_HW_IDLE;
+ ALOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
+ outStream,
+ samplingRate,
+ format,
+ channels,
+ status);
+
+ if (outStream != NULL) {
+ AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
+ audio_io_handle_t id = nextUniqueId();
+
+ if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
+ (format != AUDIO_FORMAT_PCM_16_BIT) ||
+ (channels != AUDIO_CHANNEL_OUT_STEREO)) {
+ thread = new DirectOutputThread(this, output, id, *pDevices);
+ ALOGV("openOutput() created direct output: ID %d thread %p", id, thread);
+ } else {
+ thread = new MixerThread(this, output, id, *pDevices);
+ ALOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
+ }
+ mPlaybackThreads.add(id, thread);
+
+ if (pSamplingRate != NULL) *pSamplingRate = samplingRate;
+ if (pFormat != NULL) *pFormat = format;
+ if (pChannels != NULL) *pChannels = channels;
+ if (pLatencyMs != NULL) *pLatencyMs = thread->latency();
+
+ // notify client processes of the new output creation
+ thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
+ return id;
+ }
+
+ return 0;
+}
+
+audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
+ audio_io_handle_t output2)
+{
+ Mutex::Autolock _l(mLock);
+ MixerThread *thread1 = checkMixerThread_l(output1);
+ MixerThread *thread2 = checkMixerThread_l(output2);
+
+ if (thread1 == NULL || thread2 == NULL) {
+ ALOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
+ return 0;
+ }
+
+ audio_io_handle_t id = nextUniqueId();
+ DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
+ thread->addOutputTrack(thread2);
+ mPlaybackThreads.add(id, thread);
+ // notify client processes of the new output creation
+ thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
+ return id;
+}
+
+status_t AudioFlinger::closeOutput(audio_io_handle_t output)
+{
+ // keep strong reference on the playback thread so that
+ // it is not destroyed while exit() is executed
+ sp<PlaybackThread> thread;
+ {
+ Mutex::Autolock _l(mLock);
+ thread = checkPlaybackThread_l(output);
+ if (thread == NULL) {
+ return BAD_VALUE;
+ }
+
+ ALOGV("closeOutput() %d", output);
+
+ if (thread->type() == ThreadBase::MIXER) {
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ if (mPlaybackThreads.valueAt(i)->type() == ThreadBase::DUPLICATING) {
+ DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
+ dupThread->removeOutputTrack((MixerThread *)thread.get());
+ }
+ }
+ }
+ audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, NULL);
+ mPlaybackThreads.removeItem(output);
+ }
+ thread->exit();
+ // The thread entity (active unit of execution) is no longer running here,
+ // but the ThreadBase container still exists.
+
+ if (thread->type() != ThreadBase::DUPLICATING) {
+ AudioStreamOut *out = thread->clearOutput();
+ ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
+ // from now on thread->mOutput is NULL
+ out->hwDev->close_output_stream(out->hwDev, out->stream);
+ delete out;
+ }
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
+{
+ Mutex::Autolock _l(mLock);
+ PlaybackThread *thread = checkPlaybackThread_l(output);
+
+ if (thread == NULL) {
+ return BAD_VALUE;
+ }
+
+ ALOGV("suspendOutput() %d", output);
+ thread->suspend();
+
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
+{
+ Mutex::Autolock _l(mLock);
+ PlaybackThread *thread = checkPlaybackThread_l(output);
+
+ if (thread == NULL) {
+ return BAD_VALUE;
+ }
+
+ ALOGV("restoreOutput() %d", output);
+
+ thread->restore();
+
+ return NO_ERROR;
+}
+
+audio_io_handle_t AudioFlinger::openInput(uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ audio_format_t *pFormat,
+ uint32_t *pChannels,
+ audio_in_acoustics_t acoustics)
+{
+ status_t status;
+ RecordThread *thread = NULL;
+ uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+ audio_format_t format = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT;
+ uint32_t channels = pChannels ? *pChannels : 0;
+ uint32_t reqSamplingRate = samplingRate;
+ audio_format_t reqFormat = format;
+ uint32_t reqChannels = channels;
+ audio_stream_in_t *inStream;
+ audio_hw_device_t *inHwDev;
+
+ if (pDevices == NULL || *pDevices == 0) {
+ return 0;
+ }
+
+ Mutex::Autolock _l(mLock);
+
+ inHwDev = findSuitableHwDev_l(*pDevices);
+ if (inHwDev == NULL)
+ return 0;
+
+ status = inHwDev->open_input_stream(inHwDev, *pDevices, &format,
+ &channels, &samplingRate,
+ acoustics,
+ &inStream);
+ ALOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
+ inStream,
+ samplingRate,
+ format,
+ channels,
+ acoustics,
+ status);
+
+ // If the input could not be opened with the requested parameters and we can handle the conversion internally,
+ // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
+ // or stereo to mono conversions on 16 bit PCM inputs.
+ if (inStream == NULL && status == BAD_VALUE &&
+ reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&
+ (samplingRate <= 2 * reqSamplingRate) &&
+ (popcount(channels) <= FCC_2) && (popcount(reqChannels) <= FCC_2)) {
+ ALOGV("openInput() reopening with proposed sampling rate and channels");
+ status = inHwDev->open_input_stream(inHwDev, *pDevices, &format,
+ &channels, &samplingRate,
+ acoustics,
+ &inStream);
+ }
+
+ if (inStream != NULL) {
+ AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
+
+ audio_io_handle_t id = nextUniqueId();
+ // Start record thread
+ // RecorThread require both input and output device indication to forward to audio
+ // pre processing modules
+ uint32_t device = (*pDevices) | primaryOutputDevice_l();
+ thread = new RecordThread(this,
+ input,
+ reqSamplingRate,
+ reqChannels,
+ id,
+ device);
+ mRecordThreads.add(id, thread);
+ ALOGV("openInput() created record thread: ID %d thread %p", id, thread);
+ if (pSamplingRate != NULL) *pSamplingRate = reqSamplingRate;
+ if (pFormat != NULL) *pFormat = format;
+ if (pChannels != NULL) *pChannels = reqChannels;
+
+ input->stream->common.standby(&input->stream->common);
+
+ // notify client processes of the new input creation
+ thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
+ return id;
+ }
+
+ return 0;
+}
+
+status_t AudioFlinger::closeInput(audio_io_handle_t input)
+{
+ // keep strong reference on the record thread so that
+ // it is not destroyed while exit() is executed
+ sp<RecordThread> thread;
+ {
+ Mutex::Autolock _l(mLock);
+ thread = checkRecordThread_l(input);
+ if (thread == NULL) {
+ return BAD_VALUE;
+ }
+
+ ALOGV("closeInput() %d", input);
+ audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, NULL);
+ mRecordThreads.removeItem(input);
+ }
+ thread->exit();
+ // The thread entity (active unit of execution) is no longer running here,
+ // but the ThreadBase container still exists.
+
+ AudioStreamIn *in = thread->clearInput();
+ ALOG_ASSERT(in != NULL, "in shouldn't be NULL");
+ // from now on thread->mInput is NULL
+ in->hwDev->close_input_stream(in->hwDev, in->stream);
+ delete in;
+
+ return NO_ERROR;
+}
+
+status_t AudioFlinger::setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output)
+{
+ Mutex::Autolock _l(mLock);
+ MixerThread *dstThread = checkMixerThread_l(output);
+ if (dstThread == NULL) {
+ ALOGW("setStreamOutput() bad output id %d", output);
+ return BAD_VALUE;
+ }
+
+ ALOGV("setStreamOutput() stream %d to output %d", stream, output);
+ audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
+
+ dstThread->setStreamValid(stream, true);
+
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+ if (thread != dstThread && thread->type() != ThreadBase::DIRECT) {
+ MixerThread *srcThread = (MixerThread *)thread;
+ srcThread->setStreamValid(stream, false);
+ srcThread->invalidateTracks(stream);
+ }
+ }
+
+ return NO_ERROR;
+}
+
+
+int AudioFlinger::newAudioSessionId()
+{
+ return nextUniqueId();
+}
+
+void AudioFlinger::acquireAudioSessionId(int audioSession)
+{
+ Mutex::Autolock _l(mLock);
+ pid_t caller = IPCThreadState::self()->getCallingPid();
+ ALOGV("acquiring %d from %d", audioSession, caller);
+ size_t num = mAudioSessionRefs.size();
+ for (size_t i = 0; i< num; i++) {
+ AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
+ if (ref->mSessionid == audioSession && ref->mPid == caller) {
+ ref->mCnt++;
+ ALOGV(" incremented refcount to %d", ref->mCnt);
+ return;
+ }
+ }
+ mAudioSessionRefs.push(new AudioSessionRef(audioSession, caller));
+ ALOGV(" added new entry for %d", audioSession);
+}
+
+void AudioFlinger::releaseAudioSessionId(int audioSession)
+{
+ Mutex::Autolock _l(mLock);
+ pid_t caller = IPCThreadState::self()->getCallingPid();
+ ALOGV("releasing %d from %d", audioSession, caller);
+ size_t num = mAudioSessionRefs.size();
+ for (size_t i = 0; i< num; i++) {
+ AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
+ if (ref->mSessionid == audioSession && ref->mPid == caller) {
+ ref->mCnt--;
+ ALOGV(" decremented refcount to %d", ref->mCnt);
+ if (ref->mCnt == 0) {
+ mAudioSessionRefs.removeAt(i);
+ delete ref;
+ purgeStaleEffects_l();
+ }
+ return;
+ }
+ }
+ ALOGW("session id %d not found for pid %d", audioSession, caller);
+}
+
+void AudioFlinger::purgeStaleEffects_l() {
+
+ ALOGV("purging stale effects");
+
+ Vector< sp<EffectChain> > chains;
+
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
+ for (size_t j = 0; j < t->mEffectChains.size(); j++) {
+ sp<EffectChain> ec = t->mEffectChains[j];
+ if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
+ chains.push(ec);
+ }
+ }
+ }
+ for (size_t i = 0; i < mRecordThreads.size(); i++) {
+ sp<RecordThread> t = mRecordThreads.valueAt(i);
+ for (size_t j = 0; j < t->mEffectChains.size(); j++) {
+ sp<EffectChain> ec = t->mEffectChains[j];
+ chains.push(ec);
+ }
+ }
+
+ for (size_t i = 0; i < chains.size(); i++) {
+ sp<EffectChain> ec = chains[i];
+ int sessionid = ec->sessionId();
+ sp<ThreadBase> t = ec->mThread.promote();
+ if (t == 0) {
+ continue;
+ }
+ size_t numsessionrefs = mAudioSessionRefs.size();
+ bool found = false;
+ for (size_t k = 0; k < numsessionrefs; k++) {
+ AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
+ if (ref->mSessionid == sessionid) {
+ ALOGV(" session %d still exists for %d with %d refs",
+ sessionid, ref->mPid, ref->mCnt);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ // remove all effects from the chain
+ while (ec->mEffects.size()) {
+ sp<EffectModule> effect = ec->mEffects[0];
+ effect->unPin();
+ Mutex::Autolock _l (t->mLock);
+ t->removeEffect_l(effect);
+ for (size_t j = 0; j < effect->mHandles.size(); j++) {
+ sp<EffectHandle> handle = effect->mHandles[j].promote();
+ if (handle != 0) {
+ handle->mEffect.clear();
+ if (handle->mHasControl && handle->mEnabled) {
+ t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
+ }
+ }
+ }
+ AudioSystem::unregisterEffect(effect->id());
+ }
+ }
+ }
+ return;
+}
+
+// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
+AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
+{
+ return mPlaybackThreads.valueFor(output).get();
+}
+
+// checkMixerThread_l() must be called with AudioFlinger::mLock held
+AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
+{
+ PlaybackThread *thread = checkPlaybackThread_l(output);
+ return thread != NULL && thread->type() != ThreadBase::DIRECT ? (MixerThread *) thread : NULL;
+}
+
+// checkRecordThread_l() must be called with AudioFlinger::mLock held
+AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
+{
+ return mRecordThreads.valueFor(input).get();
+}
+
+uint32_t AudioFlinger::nextUniqueId()
+{
+ return android_atomic_inc(&mNextUniqueId);
+}
+
+AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
+{
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+ AudioStreamOut *output = thread->getOutput();
+ if (output != NULL && output->hwDev == mPrimaryHardwareDev) {
+ return thread;
+ }
+ }
+ return NULL;
+}
+
+uint32_t AudioFlinger::primaryOutputDevice_l() const
+{
+ PlaybackThread *thread = primaryPlaybackThread_l();
+
+ if (thread == NULL) {
+ return 0;
+ }
+
+ return thread->device();
+}
+
+
+// ----------------------------------------------------------------------------
+// Effect management
+// ----------------------------------------------------------------------------
+
+
+status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
+{
+ Mutex::Autolock _l(mLock);
+ return EffectQueryNumberEffects(numEffects);
+}
+
+status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
+{
+ Mutex::Autolock _l(mLock);
+ return EffectQueryEffect(index, descriptor);
+}
+
+status_t AudioFlinger::getEffectDescriptor(const effect_uuid_t *pUuid,
+ effect_descriptor_t *descriptor) const
+{
+ Mutex::Autolock _l(mLock);
+ return EffectGetDescriptor(pUuid, descriptor);
+}
+
+
+sp<IEffect> AudioFlinger::createEffect(pid_t pid,
+ effect_descriptor_t *pDesc,
+ const sp<IEffectClient>& effectClient,
+ int32_t priority,
+ audio_io_handle_t io,
+ int sessionId,
+ status_t *status,
+ int *id,
+ int *enabled)
+{
+ status_t lStatus = NO_ERROR;
+ sp<EffectHandle> handle;
+ effect_descriptor_t desc;
+
+ ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d",
+ pid, effectClient.get(), priority, sessionId, io);
+
+ if (pDesc == NULL) {
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+
+ // check audio settings permission for global effects
+ if (sessionId == AUDIO_SESSION_OUTPUT_MIX && !settingsAllowed()) {
+ lStatus = PERMISSION_DENIED;
+ goto Exit;
+ }
+
+ // Session AUDIO_SESSION_OUTPUT_STAGE is reserved for output stage effects
+ // that can only be created by audio policy manager (running in same process)
+ if (sessionId == AUDIO_SESSION_OUTPUT_STAGE && getpid_cached != pid) {
+ lStatus = PERMISSION_DENIED;
+ goto Exit;
+ }
+
+ if (io == 0) {
+ if (sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
+ // output must be specified by AudioPolicyManager when using session
+ // AUDIO_SESSION_OUTPUT_STAGE
+ lStatus = BAD_VALUE;
+ goto Exit;
+ } else if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
+ // if the output returned by getOutputForEffect() is removed before we lock the
+ // mutex below, the call to checkPlaybackThread_l(io) below will detect it
+ // and we will exit safely
+ io = AudioSystem::getOutputForEffect(&desc);
+ }
+ }
+
+ {
+ Mutex::Autolock _l(mLock);
+
+
+ if (!EffectIsNullUuid(&pDesc->uuid)) {
+ // if uuid is specified, request effect descriptor
+ lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
+ if (lStatus < 0) {
+ ALOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
+ goto Exit;
+ }
+ } else {
+ // if uuid is not specified, look for an available implementation
+ // of the required type in effect factory
+ if (EffectIsNullUuid(&pDesc->type)) {
+ ALOGW("createEffect() no effect type");
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ uint32_t numEffects = 0;
+ effect_descriptor_t d;
+ d.flags = 0; // prevent compiler warning
+ bool found = false;
+
+ lStatus = EffectQueryNumberEffects(&numEffects);
+ if (lStatus < 0) {
+ ALOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
+ goto Exit;
+ }
+ for (uint32_t i = 0; i < numEffects; i++) {
+ lStatus = EffectQueryEffect(i, &desc);
+ if (lStatus < 0) {
+ ALOGW("createEffect() error %d from EffectQueryEffect", lStatus);
+ continue;
+ }
+ if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
+ // If matching type found save effect descriptor. If the session is
+ // 0 and the effect is not auxiliary, continue enumeration in case
+ // an auxiliary version of this effect type is available
+ found = true;
+ memcpy(&d, &desc, sizeof(effect_descriptor_t));
+ if (sessionId != AUDIO_SESSION_OUTPUT_MIX ||
+ (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ break;
+ }
+ }
+ }
+ if (!found) {
+ lStatus = BAD_VALUE;
+ ALOGW("createEffect() effect not found");
+ goto Exit;
+ }
+ // For same effect type, chose auxiliary version over insert version if
+ // connect to output mix (Compliance to OpenSL ES)
+ if (sessionId == AUDIO_SESSION_OUTPUT_MIX &&
+ (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
+ memcpy(&desc, &d, sizeof(effect_descriptor_t));
+ }
+ }
+
+ // Do not allow auxiliary effects on a session different from 0 (output mix)
+ if (sessionId != AUDIO_SESSION_OUTPUT_MIX &&
+ (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ lStatus = INVALID_OPERATION;
+ goto Exit;
+ }
+
+ // check recording permission for visualizer
+ if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
+ !recordingAllowed()) {
+ lStatus = PERMISSION_DENIED;
+ goto Exit;
+ }
+
+ // return effect descriptor
+ memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
+
+ // If output is not specified try to find a matching audio session ID in one of the
+ // output threads.
+ // If output is 0 here, sessionId is neither SESSION_OUTPUT_STAGE nor SESSION_OUTPUT_MIX
+ // because of code checking output when entering the function.
+ // Note: io is never 0 when creating an effect on an input
+ if (io == 0) {
+ // look for the thread where the specified audio session is present
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
+ io = mPlaybackThreads.keyAt(i);
+ break;
+ }
+ }
+ if (io == 0) {
+ for (size_t i = 0; i < mRecordThreads.size(); i++) {
+ if (mRecordThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
+ io = mRecordThreads.keyAt(i);
+ break;
+ }
+ }
+ }
+ // If no output thread contains the requested session ID, default to
+ // first output. The effect chain will be moved to the correct output
+ // thread when a track with the same session ID is created
+ if (io == 0 && mPlaybackThreads.size()) {
+ io = mPlaybackThreads.keyAt(0);
+ }
+ ALOGV("createEffect() got io %d for effect %s", io, desc.name);
+ }
+ ThreadBase *thread = checkRecordThread_l(io);
+ if (thread == NULL) {
+ thread = checkPlaybackThread_l(io);
+ if (thread == NULL) {
+ ALOGE("createEffect() unknown output thread");
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ }
+
+ sp<Client> client = registerPid_l(pid);
+
+ // create effect on selected output thread
+ handle = thread->createEffect_l(client, effectClient, priority, sessionId,
+ &desc, enabled, &lStatus);
+ if (handle != 0 && id != NULL) {
+ *id = handle->id();
+ }
+ }
+
+Exit:
+ if (status != NULL) {
+ *status = lStatus;
+ }
+ return handle;
+}
+
+status_t AudioFlinger::moveEffects(int sessionId, audio_io_handle_t srcOutput,
+ audio_io_handle_t dstOutput)
+{
+ ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
+ sessionId, srcOutput, dstOutput);
+ Mutex::Autolock _l(mLock);
+ if (srcOutput == dstOutput) {
+ ALOGW("moveEffects() same dst and src outputs %d", dstOutput);
+ return NO_ERROR;
+ }
+ PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
+ if (srcThread == NULL) {
+ ALOGW("moveEffects() bad srcOutput %d", srcOutput);
+ return BAD_VALUE;
+ }
+ PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
+ if (dstThread == NULL) {
+ ALOGW("moveEffects() bad dstOutput %d", dstOutput);
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock _dl(dstThread->mLock);
+ Mutex::Autolock _sl(srcThread->mLock);
+ moveEffectChain_l(sessionId, srcThread, dstThread, false);
+
+ return NO_ERROR;
+}
+
+// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
+status_t AudioFlinger::moveEffectChain_l(int sessionId,
+ AudioFlinger::PlaybackThread *srcThread,
+ AudioFlinger::PlaybackThread *dstThread,
+ bool reRegister)
+{
+ ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
+ sessionId, srcThread, dstThread);
+
+ sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
+ if (chain == 0) {
+ ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
+ sessionId, srcThread);
+ return INVALID_OPERATION;
+ }
+
+ // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
+ // so that a new chain is created with correct parameters when first effect is added. This is
+ // otherwise unnecessary as removeEffect_l() will remove the chain when last effect is
+ // removed.
+ srcThread->removeEffectChain_l(chain);
+
+ // transfer all effects one by one so that new effect chain is created on new thread with
+ // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
+ audio_io_handle_t dstOutput = dstThread->id();
+ sp<EffectChain> dstChain;
+ uint32_t strategy = 0; // prevent compiler warning
+ sp<EffectModule> effect = chain->getEffectFromId_l(0);
+ while (effect != 0) {
+ srcThread->removeEffect_l(effect);
+ dstThread->addEffect_l(effect);
+ // removeEffect_l() has stopped the effect if it was active so it must be restarted
+ if (effect->state() == EffectModule::ACTIVE ||
+ effect->state() == EffectModule::STOPPING) {
+ effect->start();
+ }
+ // if the move request is not received from audio policy manager, the effect must be
+ // re-registered with the new strategy and output
+ if (dstChain == 0) {
+ dstChain = effect->chain().promote();
+ if (dstChain == 0) {
+ ALOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
+ srcThread->addEffect_l(effect);
+ return NO_INIT;
+ }
+ strategy = dstChain->strategy();
+ }
+ if (reRegister) {
+ AudioSystem::unregisterEffect(effect->id());
+ AudioSystem::registerEffect(&effect->desc(),
+ dstOutput,
+ strategy,
+ sessionId,
+ effect->id());
+ }
+ effect = chain->getEffectFromId_l(0);
+ }
+
+ return NO_ERROR;
+}
+
+
+// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
+sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
+ const sp<AudioFlinger::Client>& client,
+ const sp<IEffectClient>& effectClient,
+ int32_t priority,
+ int sessionId,
+ effect_descriptor_t *desc,
+ int *enabled,
+ status_t *status
+ )
+{
+ sp<EffectModule> effect;
+ sp<EffectHandle> handle;
+ status_t lStatus;
+ sp<EffectChain> chain;
+ bool chainCreated = false;
+ bool effectCreated = false;
+ bool effectRegistered = false;
+
+ lStatus = initCheck();
+ if (lStatus != NO_ERROR) {
+ ALOGW("createEffect_l() Audio driver not initialized.");
+ goto Exit;
+ }
+
+ // Do not allow effects with session ID 0 on direct output or duplicating threads
+ // TODO: add rule for hw accelerated effects on direct outputs with non PCM format
+ if (sessionId == AUDIO_SESSION_OUTPUT_MIX && mType != MIXER) {
+ ALOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
+ desc->name, sessionId);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+ // Only Pre processor effects are allowed on input threads and only on input threads
+ if ((mType == RECORD) != ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC)) {
+ ALOGW("createEffect_l() effect %s (flags %08x) created on wrong thread type %d",
+ desc->name, desc->flags, mType);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
+
+ ALOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
+
+ { // scope for mLock
+ Mutex::Autolock _l(mLock);
+
+ // check for existing effect chain with the requested audio session
+ chain = getEffectChain_l(sessionId);
+ if (chain == 0) {
+ // create a new chain for this session
+ ALOGV("createEffect_l() new effect chain for session %d", sessionId);
+ chain = new EffectChain(this, sessionId);
+ addEffectChain_l(chain);
+ chain->setStrategy(getStrategyForSession_l(sessionId));
+ chainCreated = true;
+ } else {
+ effect = chain->getEffectFromDesc_l(desc);
+ }
+
+ ALOGV("createEffect_l() got effect %p on chain %p", effect.get(), chain.get());
+
+ if (effect == 0) {
+ int id = mAudioFlinger->nextUniqueId();
+ // Check CPU and memory usage
+ lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
+ if (lStatus != NO_ERROR) {
+ goto Exit;
+ }
+ effectRegistered = true;
+ // create a new effect module if none present in the chain
+ effect = new EffectModule(this, chain, desc, id, sessionId);
+ lStatus = effect->status();
+ if (lStatus != NO_ERROR) {
+ goto Exit;
+ }
+ lStatus = chain->addEffect_l(effect);
+ if (lStatus != NO_ERROR) {
+ goto Exit;
+ }
+ effectCreated = true;
+
+ effect->setDevice(mDevice);
+ effect->setMode(mAudioFlinger->getMode());
+ }
+ // create effect handle and connect it to effect module
+ handle = new EffectHandle(effect, client, effectClient, priority);
+ lStatus = effect->addHandle(handle);
+ if (enabled != NULL) {
+ *enabled = (int)effect->isEnabled();
+ }
+ }
+
+Exit:
+ if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
+ Mutex::Autolock _l(mLock);
+ if (effectCreated) {
+ chain->removeEffect_l(effect);
+ }
+ if (effectRegistered) {
+ AudioSystem::unregisterEffect(effect->id());
+ }
+ if (chainCreated) {
+ removeEffectChain_l(chain);
+ }
+ handle.clear();
+ }
+
+ if (status != NULL) {
+ *status = lStatus;
+ }
+ return handle;
+}
+
+sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId)
+{
+ sp<EffectChain> chain = getEffectChain_l(sessionId);
+ return chain != 0 ? chain->getEffectFromId_l(effectId) : 0;
+}
+
+// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
+// PlaybackThread::mLock held
+status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
+{
+ // check for existing effect chain with the requested audio session
+ int sessionId = effect->sessionId();
+ sp<EffectChain> chain = getEffectChain_l(sessionId);
+ bool chainCreated = false;
+
+ if (chain == 0) {
+ // create a new chain for this session
+ ALOGV("addEffect_l() new effect chain for session %d", sessionId);
+ chain = new EffectChain(this, sessionId);
+ addEffectChain_l(chain);
+ chain->setStrategy(getStrategyForSession_l(sessionId));
+ chainCreated = true;
+ }
+ ALOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
+
+ if (chain->getEffectFromId_l(effect->id()) != 0) {
+ ALOGW("addEffect_l() %p effect %s already present in chain %p",
+ this, effect->desc().name, chain.get());
+ return BAD_VALUE;
+ }
+
+ status_t status = chain->addEffect_l(effect);
+ if (status != NO_ERROR) {
+ if (chainCreated) {
+ removeEffectChain_l(chain);
+ }
+ return status;
+ }
+
+ effect->setDevice(mDevice);
+ effect->setMode(mAudioFlinger->getMode());
+ return NO_ERROR;
+}
+
+void AudioFlinger::ThreadBase::removeEffect_l(const sp<EffectModule>& effect) {
+
+ ALOGV("removeEffect_l() %p effect %p", this, effect.get());
+ effect_descriptor_t desc = effect->desc();
+ if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ detachAuxEffect_l(effect->id());
+ }
+
+ sp<EffectChain> chain = effect->chain().promote();
+ if (chain != 0) {
+ // remove effect chain if removing last effect
+ if (chain->removeEffect_l(effect) == 0) {
+ removeEffectChain_l(chain);
+ }
+ } else {
+ ALOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get());
+ }
+}
+
+void AudioFlinger::ThreadBase::lockEffectChains_l(
+ Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+{
+ effectChains = mEffectChains;
+ for (size_t i = 0; i < mEffectChains.size(); i++) {
+ mEffectChains[i]->lock();
+ }
+}
+
+void AudioFlinger::ThreadBase::unlockEffectChains(
+ const Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+{
+ for (size_t i = 0; i < effectChains.size(); i++) {
+ effectChains[i]->unlock();
+ }
+}
+
+sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(int sessionId)
+{
+ Mutex::Autolock _l(mLock);
+ return getEffectChain_l(sessionId);
+}
+
+sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(int sessionId)
+{
+ size_t size = mEffectChains.size();
+ for (size_t i = 0; i < size; i++) {
+ if (mEffectChains[i]->sessionId() == sessionId) {
+ return mEffectChains[i];
+ }
+ }
+ return 0;
+}
+
+void AudioFlinger::ThreadBase::setMode(audio_mode_t mode)
+{
+ Mutex::Autolock _l(mLock);
+ size_t size = mEffectChains.size();
+ for (size_t i = 0; i < size; i++) {
+ mEffectChains[i]->setMode_l(mode);
+ }
+}
+
+void AudioFlinger::ThreadBase::disconnectEffect(const sp<EffectModule>& effect,
+ const wp<EffectHandle>& handle,
+ bool unpinIfLast) {
+
+ Mutex::Autolock _l(mLock);
+ ALOGV("disconnectEffect() %p effect %p", this, effect.get());
+ // delete the effect module if removing last handle on it
+ if (effect->removeHandle(handle) == 0) {
+ if (!effect->isPinned() || unpinIfLast) {
+ removeEffect_l(effect);
+ AudioSystem::unregisterEffect(effect->id());
+ }
+ }
+}
+
+status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
+{
+ int session = chain->sessionId();
+ int16_t *buffer = mMixBuffer;
+ bool ownsBuffer = false;
+
+ ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
+ if (session > 0) {
+ // Only one effect chain can be present in direct output thread and it uses
+ // the mix buffer as input
+ if (mType != DIRECT) {
+ size_t numSamples = mFrameCount * mChannelCount;
+ buffer = new int16_t[numSamples];
+ memset(buffer, 0, numSamples * sizeof(int16_t));
+ ALOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
+ ownsBuffer = true;
+ }
+
+ // Attach all tracks with same session ID to this chain.
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ sp<Track> track = mTracks[i];
+ if (session == track->sessionId()) {
+ ALOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
+ track->setMainBuffer(buffer);
+ chain->incTrackCnt();
+ }
+ }
+
+ // indicate all active tracks in the chain
+ for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
+ sp<Track> track = mActiveTracks[i].promote();
+ if (track == 0) continue;
+ if (session == track->sessionId()) {
+ ALOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
+ chain->incActiveTrackCnt();
+ }
+ }
+ }
+
+ chain->setInBuffer(buffer, ownsBuffer);
+ chain->setOutBuffer(mMixBuffer);
+ // Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
+ // chains list in order to be processed last as it contains output stage effects
+ // Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
+ // session AUDIO_SESSION_OUTPUT_STAGE to be processed
+ // after track specific effects and before output stage
+ // It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and
+ // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX
+ // Effect chain for other sessions are inserted at beginning of effect
+ // chains list to be processed before output mix effects. Relative order between other
+ // sessions is not important
+ size_t size = mEffectChains.size();
+ size_t i = 0;
+ for (i = 0; i < size; i++) {
+ if (mEffectChains[i]->sessionId() < session) break;
+ }
+ mEffectChains.insertAt(chain, i);
+ checkSuspendOnAddEffectChain_l(chain);
+
+ return NO_ERROR;
+}
+
+size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
+{
+ int session = chain->sessionId();
+
+ ALOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
+
+ for (size_t i = 0; i < mEffectChains.size(); i++) {
+ if (chain == mEffectChains[i]) {
+ mEffectChains.removeAt(i);
+ // detach all active tracks from the chain
+ for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
+ sp<Track> track = mActiveTracks[i].promote();
+ if (track == 0) continue;
+ if (session == track->sessionId()) {
+ ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d",
+ chain.get(), session);
+ chain->decActiveTrackCnt();
+ }
+ }
+
+ // detach all tracks with same session ID from this chain
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ sp<Track> track = mTracks[i];
+ if (session == track->sessionId()) {
+ track->setMainBuffer(mMixBuffer);
+ chain->decTrackCnt();
+ }
+ }
+ break;
+ }
+ }
+ return mEffectChains.size();
+}
+
+status_t AudioFlinger::PlaybackThread::attachAuxEffect(
+ const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
+{
+ Mutex::Autolock _l(mLock);
+ return attachAuxEffect_l(track, EffectId);
+}
+
+status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
+ const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
+{
+ status_t status = NO_ERROR;
+
+ if (EffectId == 0) {
+ track->setAuxBuffer(0, NULL);
+ } else {
+ // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
+ sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
+ if (effect != 0) {
+ if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
+ } else {
+ status = INVALID_OPERATION;
+ }
+ } else {
+ status = BAD_VALUE;
+ }
+ }
+ return status;
+}
+
+void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
+{
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ sp<Track> track = mTracks[i];
+ if (track->auxEffectId() == effectId) {
+ attachAuxEffect_l(track, 0);
+ }
+ }
+}
+
+status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
+{
+ // only one chain per input thread
+ if (mEffectChains.size() != 0) {
+ return INVALID_OPERATION;
+ }
+ ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
+
+ chain->setInBuffer(NULL);
+ chain->setOutBuffer(NULL);
+
+ checkSuspendOnAddEffectChain_l(chain);
+
+ mEffectChains.add(chain);
+
+ return NO_ERROR;
+}
+
+size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
+{
+ ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
+ ALOGW_IF(mEffectChains.size() != 1,
+ "removeEffectChain_l() %p invalid chain size %d on thread %p",
+ chain.get(), mEffectChains.size(), this);
+ if (mEffectChains.size() == 1) {
+ mEffectChains.removeAt(0);
+ }
+ return 0;
+}
+
+// ----------------------------------------------------------------------------
+// EffectModule implementation
+// ----------------------------------------------------------------------------
+
+#undef LOG_TAG
+#define LOG_TAG "AudioFlinger::EffectModule"
+
+AudioFlinger::EffectModule::EffectModule(ThreadBase *thread,
+ const wp<AudioFlinger::EffectChain>& chain,
+ effect_descriptor_t *desc,
+ int id,
+ int sessionId)
+ : mThread(thread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),
+ mStatus(NO_INIT), mState(IDLE), mSuspended(false)
+{
+ ALOGV("Constructor %p", this);
+ int lStatus;
+ if (thread == NULL) {
+ return;
+ }
+
+ memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
+
+ // create effect engine from effect factory
+ mStatus = EffectCreate(&desc->uuid, sessionId, thread->id(), &mEffectInterface);
+
+ if (mStatus != NO_ERROR) {
+ return;
+ }
+ lStatus = init();
+ if (lStatus < 0) {
+ mStatus = lStatus;
+ goto Error;
+ }
+
+ if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
+ mPinned = true;
+ }
+ ALOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
+ return;
+Error:
+ EffectRelease(mEffectInterface);
+ mEffectInterface = NULL;
+ ALOGV("Constructor Error %d", mStatus);
+}
+
+AudioFlinger::EffectModule::~EffectModule()
+{
+ ALOGV("Destructor %p", this);
+ if (mEffectInterface != NULL) {
+ if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
+ (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ audio_stream_t *stream = thread->stream();
+ if (stream != NULL) {
+ stream->remove_audio_effect(stream, mEffectInterface);
+ }
+ }
+ }
+ // release effect engine
+ EffectRelease(mEffectInterface);
+ }
+}
+
+status_t AudioFlinger::EffectModule::addHandle(const sp<EffectHandle>& handle)
+{
+ status_t status;
+
+ Mutex::Autolock _l(mLock);
+ int priority = handle->priority();
+ size_t size = mHandles.size();
+ sp<EffectHandle> h;
+ size_t i;
+ for (i = 0; i < size; i++) {
+ h = mHandles[i].promote();
+ if (h == 0) continue;
+ if (h->priority() <= priority) break;
+ }
+ // if inserted in first place, move effect control from previous owner to this handle
+ if (i == 0) {
+ bool enabled = false;
+ if (h != 0) {
+ enabled = h->enabled();
+ h->setControl(false/*hasControl*/, true /*signal*/, enabled /*enabled*/);
+ }
+ handle->setControl(true /*hasControl*/, false /*signal*/, enabled /*enabled*/);
+ status = NO_ERROR;
+ } else {
+ status = ALREADY_EXISTS;
+ }
+ ALOGV("addHandle() %p added handle %p in position %d", this, handle.get(), i);
+ mHandles.insertAt(handle, i);
+ return status;
+}
+
+size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle)
+{
+ Mutex::Autolock _l(mLock);
+ size_t size = mHandles.size();
+ size_t i;
+ for (i = 0; i < size; i++) {
+ if (mHandles[i] == handle) break;
+ }
+ if (i == size) {
+ return size;
+ }
+ ALOGV("removeHandle() %p removed handle %p in position %d", this, handle.unsafe_get(), i);
+
+ bool enabled = false;
+ EffectHandle *hdl = handle.unsafe_get();
+ if (hdl != NULL) {
+ ALOGV("removeHandle() unsafe_get OK");
+ enabled = hdl->enabled();
+ }
+ mHandles.removeAt(i);
+ size = mHandles.size();
+ // if removed from first place, move effect control from this handle to next in line
+ if (i == 0 && size != 0) {
+ sp<EffectHandle> h = mHandles[0].promote();
+ if (h != 0) {
+ h->setControl(true /*hasControl*/, true /*signal*/ , enabled /*enabled*/);
+ }
+ }
+
+ // Prevent calls to process() and other functions on effect interface from now on.
+ // The effect engine will be released by the destructor when the last strong reference on
+ // this object is released which can happen after next process is called.
+ if (size == 0 && !mPinned) {
+ mState = DESTROYED;
+ }
+
+ return size;
+}
+
+sp<AudioFlinger::EffectHandle> AudioFlinger::EffectModule::controlHandle()
+{
+ Mutex::Autolock _l(mLock);
+ return mHandles.size() != 0 ? mHandles[0].promote() : 0;
+}
+
+void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle, bool unpinIfLast)
+{
+ ALOGV("disconnect() %p handle %p", this, handle.unsafe_get());
+ // keep a strong reference on this EffectModule to avoid calling the
+ // destructor before we exit
+ sp<EffectModule> keep(this);
+ {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ thread->disconnectEffect(keep, handle, unpinIfLast);
+ }
+ }
+}
+
+void AudioFlinger::EffectModule::updateState() {
+ Mutex::Autolock _l(mLock);
+
+ switch (mState) {
+ case RESTART:
+ reset_l();
+ // FALL THROUGH
+
+ case STARTING:
+ // clear auxiliary effect input buffer for next accumulation
+ if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ memset(mConfig.inputCfg.buffer.raw,
+ 0,
+ mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
+ }
+ start_l();
+ mState = ACTIVE;
+ break;
+ case STOPPING:
+ stop_l();
+ mDisableWaitCnt = mMaxDisableWaitCnt;
+ mState = STOPPED;
+ break;
+ case STOPPED:
+ // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
+ // turn off sequence.
+ if (--mDisableWaitCnt == 0) {
+ reset_l();
+ mState = IDLE;
+ }
+ break;
+ default: //IDLE , ACTIVE, DESTROYED
+ break;
+ }
+}
+
+void AudioFlinger::EffectModule::process()
+{
+ Mutex::Autolock _l(mLock);
+
+ if (mState == DESTROYED || mEffectInterface == NULL ||
+ mConfig.inputCfg.buffer.raw == NULL ||
+ mConfig.outputCfg.buffer.raw == NULL) {
+ return;
+ }
+
+ if (isProcessEnabled()) {
+ // do 32 bit to 16 bit conversion for auxiliary effect input buffer
+ if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ ditherAndClamp(mConfig.inputCfg.buffer.s32,
+ mConfig.inputCfg.buffer.s32,
+ mConfig.inputCfg.buffer.frameCount/2);
+ }
+
+ // do the actual processing in the effect engine
+ int ret = (*mEffectInterface)->process(mEffectInterface,
+ &mConfig.inputCfg.buffer,
+ &mConfig.outputCfg.buffer);
+
+ // force transition to IDLE state when engine is ready
+ if (mState == STOPPED && ret == -ENODATA) {
+ mDisableWaitCnt = 1;
+ }
+
+ // clear auxiliary effect input buffer for next accumulation
+ if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ memset(mConfig.inputCfg.buffer.raw, 0,
+ mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
+ }
+ } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
+ mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
+ // If an insert effect is idle and input buffer is different from output buffer,
+ // accumulate input onto output
+ sp<EffectChain> chain = mChain.promote();
+ if (chain != 0 && chain->activeTrackCnt() != 0) {
+ size_t frameCnt = mConfig.inputCfg.buffer.frameCount * 2; //always stereo here
+ int16_t *in = mConfig.inputCfg.buffer.s16;
+ int16_t *out = mConfig.outputCfg.buffer.s16;
+ for (size_t i = 0; i < frameCnt; i++) {
+ out[i] = clamp16((int32_t)out[i] + (int32_t)in[i]);
+ }
+ }
+ }
+}
+
+void AudioFlinger::EffectModule::reset_l()
+{
+ if (mEffectInterface == NULL) {
+ return;
+ }
+ (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
+}
+
+status_t AudioFlinger::EffectModule::configure()
+{
+ uint32_t channels;
+ if (mEffectInterface == NULL) {
+ return NO_INIT;
+ }
+
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread == 0) {
+ return DEAD_OBJECT;
+ }
+
+ // TODO: handle configuration of effects replacing track process
+ if (thread->channelCount() == 1) {
+ channels = AUDIO_CHANNEL_OUT_MONO;
+ } else {
+ channels = AUDIO_CHANNEL_OUT_STEREO;
+ }
+
+ if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
+ } else {
+ mConfig.inputCfg.channels = channels;
+ }
+ mConfig.outputCfg.channels = channels;
+ mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+ mConfig.inputCfg.samplingRate = thread->sampleRate();
+ mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
+ mConfig.inputCfg.bufferProvider.cookie = NULL;
+ mConfig.inputCfg.bufferProvider.getBuffer = NULL;
+ mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
+ mConfig.outputCfg.bufferProvider.cookie = NULL;
+ mConfig.outputCfg.bufferProvider.getBuffer = NULL;
+ mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
+ mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+ // Insert effect:
+ // - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
+ // always overwrites output buffer: input buffer == output buffer
+ // - in other sessions:
+ // last effect in the chain accumulates in output buffer: input buffer != output buffer
+ // other effect: overwrites output buffer: input buffer == output buffer
+ // Auxiliary effect:
+ // accumulates in output buffer: input buffer != output buffer
+ // Therefore: accumulate <=> input buffer != output buffer
+ if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
+ mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+ } else {
+ mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
+ }
+ mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
+ mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
+ mConfig.inputCfg.buffer.frameCount = thread->frameCount();
+ mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
+
+ ALOGV("configure() %p thread %p buffer %p framecount %d",
+ this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
+
+ status_t cmdStatus;
+ uint32_t size = sizeof(int);
+ status_t status = (*mEffectInterface)->command(mEffectInterface,
+ EFFECT_CMD_SET_CONFIG,
+ sizeof(effect_config_t),
+ &mConfig,
+ &size,
+ &cmdStatus);
+ if (status == 0) {
+ status = cmdStatus;
+ }
+
+ mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
+ (1000 * mConfig.outputCfg.buffer.frameCount);
+
+ return status;
+}
+
+status_t AudioFlinger::EffectModule::init()
+{
+ Mutex::Autolock _l(mLock);
+ if (mEffectInterface == NULL) {
+ return NO_INIT;
+ }
+ status_t cmdStatus;
+ uint32_t size = sizeof(status_t);
+ status_t status = (*mEffectInterface)->command(mEffectInterface,
+ EFFECT_CMD_INIT,
+ 0,
+ NULL,
+ &size,
+ &cmdStatus);
+ if (status == 0) {
+ status = cmdStatus;
+ }
+ return status;
+}
+
+status_t AudioFlinger::EffectModule::start()
+{
+ Mutex::Autolock _l(mLock);
+ return start_l();
+}
+
+status_t AudioFlinger::EffectModule::start_l()
+{
+ if (mEffectInterface == NULL) {
+ return NO_INIT;
+ }
+ status_t cmdStatus;
+ uint32_t size = sizeof(status_t);
+ status_t status = (*mEffectInterface)->command(mEffectInterface,
+ EFFECT_CMD_ENABLE,
+ 0,
+ NULL,
+ &size,
+ &cmdStatus);
+ if (status == 0) {
+ status = cmdStatus;
+ }
+ if (status == 0 &&
+ ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
+ (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ audio_stream_t *stream = thread->stream();
+ if (stream != NULL) {
+ stream->add_audio_effect(stream, mEffectInterface);
+ }
+ }
+ }
+ return status;
+}
+
+status_t AudioFlinger::EffectModule::stop()
+{
+ Mutex::Autolock _l(mLock);
+ return stop_l();
+}
+
+status_t AudioFlinger::EffectModule::stop_l()
+{
+ if (mEffectInterface == NULL) {
+ return NO_INIT;
+ }
+ status_t cmdStatus;
+ uint32_t size = sizeof(status_t);
+ status_t status = (*mEffectInterface)->command(mEffectInterface,
+ EFFECT_CMD_DISABLE,
+ 0,
+ NULL,
+ &size,
+ &cmdStatus);
+ if (status == 0) {
+ status = cmdStatus;
+ }
+ if (status == 0 &&
+ ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
+ (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) {
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ audio_stream_t *stream = thread->stream();
+ if (stream != NULL) {
+ stream->remove_audio_effect(stream, mEffectInterface);
+ }
+ }
+ }
+ return status;
+}
+
+status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData)
+{
+ Mutex::Autolock _l(mLock);
+// ALOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
+
+ if (mState == DESTROYED || mEffectInterface == NULL) {
+ return NO_INIT;
+ }
+ status_t status = (*mEffectInterface)->command(mEffectInterface,
+ cmdCode,
+ cmdSize,
+ pCmdData,
+ replySize,
+ pReplyData);
+ if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
+ uint32_t size = (replySize == NULL) ? 0 : *replySize;
+ for (size_t i = 1; i < mHandles.size(); i++) {
+ sp<EffectHandle> h = mHandles[i].promote();
+ if (h != 0) {
+ h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
+ }
+ }
+ }
+ return status;
+}
+
+status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
+{
+
+ Mutex::Autolock _l(mLock);
+ ALOGV("setEnabled %p enabled %d", this, enabled);
+
+ if (enabled != isEnabled()) {
+ status_t status = AudioSystem::setEffectEnabled(mId, enabled);
+ if (enabled && status != NO_ERROR) {
+ return status;
+ }
+
+ switch (mState) {
+ // going from disabled to enabled
+ case IDLE:
+ mState = STARTING;
+ break;
+ case STOPPED:
+ mState = RESTART;
+ break;
+ case STOPPING:
+ mState = ACTIVE;
+ break;
+
+ // going from enabled to disabled
+ case RESTART:
+ mState = STOPPED;
+ break;
+ case STARTING:
+ mState = IDLE;
+ break;
+ case ACTIVE:
+ mState = STOPPING;
+ break;
+ case DESTROYED:
+ return NO_ERROR; // simply ignore as we are being destroyed
+ }
+ for (size_t i = 1; i < mHandles.size(); i++) {
+ sp<EffectHandle> h = mHandles[i].promote();
+ if (h != 0) {
+ h->setEnabled(enabled);
+ }
+ }
+ }
+ return NO_ERROR;
+}
+
+bool AudioFlinger::EffectModule::isEnabled() const
+{
+ switch (mState) {
+ case RESTART:
+ case STARTING:
+ case ACTIVE:
+ return true;
+ case IDLE:
+ case STOPPING:
+ case STOPPED:
+ case DESTROYED:
+ default:
+ return false;
+ }
+}
+
+bool AudioFlinger::EffectModule::isProcessEnabled() const
+{
+ switch (mState) {
+ case RESTART:
+ case ACTIVE:
+ case STOPPING:
+ case STOPPED:
+ return true;
+ case IDLE:
+ case STARTING:
+ case DESTROYED:
+ default:
+ return false;
+ }
+}
+
+status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
+{
+ Mutex::Autolock _l(mLock);
+ status_t status = NO_ERROR;
+
+ // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
+ // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
+ if (isProcessEnabled() &&
+ ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
+ (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
+ status_t cmdStatus;
+ uint32_t volume[2];
+ uint32_t *pVolume = NULL;
+ uint32_t size = sizeof(volume);
+ volume[0] = *left;
+ volume[1] = *right;
+ if (controller) {
+ pVolume = volume;
+ }
+ status = (*mEffectInterface)->command(mEffectInterface,
+ EFFECT_CMD_SET_VOLUME,
+ size,
+ volume,
+ &size,
+ pVolume);
+ if (controller && status == NO_ERROR && size == sizeof(volume)) {
+ *left = volume[0];
+ *right = volume[1];
+ }
+ }
+ return status;
+}
+
+status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
+{
+ Mutex::Autolock _l(mLock);
+ status_t status = NO_ERROR;
+ if (device && (mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
+ // audio pre processing modules on RecordThread can receive both output and
+ // input device indication in the same call
+ uint32_t dev = device & AUDIO_DEVICE_OUT_ALL;
+ if (dev) {
+ status_t cmdStatus;
+ uint32_t size = sizeof(status_t);
+
+ status = (*mEffectInterface)->command(mEffectInterface,
+ EFFECT_CMD_SET_DEVICE,
+ sizeof(uint32_t),
+ &dev,
+ &size,
+ &cmdStatus);
+ if (status == NO_ERROR) {
+ status = cmdStatus;
+ }
+ }
+ dev = device & AUDIO_DEVICE_IN_ALL;
+ if (dev) {
+ status_t cmdStatus;
+ uint32_t size = sizeof(status_t);
+
+ status_t status2 = (*mEffectInterface)->command(mEffectInterface,
+ EFFECT_CMD_SET_INPUT_DEVICE,
+ sizeof(uint32_t),
+ &dev,
+ &size,
+ &cmdStatus);
+ if (status2 == NO_ERROR) {
+ status2 = cmdStatus;
+ }
+ if (status == NO_ERROR) {
+ status = status2;
+ }
+ }
+ }
+ return status;
+}
+
+status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
+{
+ Mutex::Autolock _l(mLock);
+ status_t status = NO_ERROR;
+ if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
+ status_t cmdStatus;
+ uint32_t size = sizeof(status_t);
+ status = (*mEffectInterface)->command(mEffectInterface,
+ EFFECT_CMD_SET_AUDIO_MODE,
+ sizeof(audio_mode_t),
+ &mode,
+ &size,
+ &cmdStatus);
+ if (status == NO_ERROR) {
+ status = cmdStatus;
+ }
+ }
+ return status;
+}
+
+void AudioFlinger::EffectModule::setSuspended(bool suspended)
+{
+ Mutex::Autolock _l(mLock);
+ mSuspended = suspended;
+}
+
+bool AudioFlinger::EffectModule::suspended() const
+{
+ Mutex::Autolock _l(mLock);
+ return mSuspended;
+}
+
+status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
+ result.append(buffer);
+
+ bool locked = tryLock(mLock);
+ // failed to lock - AudioFlinger is probably deadlocked
+ if (!locked) {
+ result.append("\t\tCould not lock Fx mutex:\n");
+ }
+
+ result.append("\t\tSession Status State Engine:\n");
+ snprintf(buffer, SIZE, "\t\t%05d %03d %03d 0x%08x\n",
+ mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
+ result.append(buffer);
+
+ result.append("\t\tDescriptor:\n");
+ snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+ mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
+ mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],mDescriptor.uuid.node[2],
+ mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+ mDescriptor.type.timeLow, mDescriptor.type.timeMid, mDescriptor.type.timeHiAndVersion,
+ mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],mDescriptor.type.node[2],
+ mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\t- apiVersion: %08X\n\t\t- flags: %08X\n",
+ mDescriptor.apiVersion,
+ mDescriptor.flags);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\t- name: %s\n",
+ mDescriptor.name);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
+ mDescriptor.implementor);
+ result.append(buffer);
+
+ result.append("\t\t- Input configuration:\n");
+ result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
+ snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
+ (uint32_t)mConfig.inputCfg.buffer.raw,
+ mConfig.inputCfg.buffer.frameCount,
+ mConfig.inputCfg.samplingRate,
+ mConfig.inputCfg.channels,
+ mConfig.inputCfg.format);
+ result.append(buffer);
+
+ result.append("\t\t- Output configuration:\n");
+ result.append("\t\t\tBuffer Frames Smp rate Channels Format\n");
+ snprintf(buffer, SIZE, "\t\t\t0x%08x %05d %05d %08x %d\n",
+ (uint32_t)mConfig.outputCfg.buffer.raw,
+ mConfig.outputCfg.buffer.frameCount,
+ mConfig.outputCfg.samplingRate,
+ mConfig.outputCfg.channels,
+ mConfig.outputCfg.format);
+ result.append(buffer);
+
+ snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
+ result.append(buffer);
+ result.append("\t\t\tPid Priority Ctrl Locked client server\n");
+ for (size_t i = 0; i < mHandles.size(); ++i) {
+ sp<EffectHandle> handle = mHandles[i].promote();
+ if (handle != 0) {
+ handle->dump(buffer, SIZE);
+ result.append(buffer);
+ }
+ }
+
+ result.append("\n");
+
+ write(fd, result.string(), result.length());
+
+ if (locked) {
+ mLock.unlock();
+ }
+
+ return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+// EffectHandle implementation
+// ----------------------------------------------------------------------------
+
+#undef LOG_TAG
+#define LOG_TAG "AudioFlinger::EffectHandle"
+
+AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
+ const sp<AudioFlinger::Client>& client,
+ const sp<IEffectClient>& effectClient,
+ int32_t priority)
+ : BnEffect(),
+ mEffect(effect), mEffectClient(effectClient), mClient(client), mCblk(NULL),
+ mPriority(priority), mHasControl(false), mEnabled(false)
+{
+ ALOGV("constructor %p", this);
+
+ if (client == 0) {
+ return;
+ }
+ int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
+ mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
+ if (mCblkMemory != 0) {
+ mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
+
+ if (mCblk != NULL) {
+ new(mCblk) effect_param_cblk_t();
+ mBuffer = (uint8_t *)mCblk + bufOffset;
+ }
+ } else {
+ ALOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE + sizeof(effect_param_cblk_t));
+ return;
+ }
+}
+
+AudioFlinger::EffectHandle::~EffectHandle()
+{
+ ALOGV("Destructor %p", this);
+ disconnect(false);
+ ALOGV("Destructor DONE %p", this);
+}
+
+status_t AudioFlinger::EffectHandle::enable()
+{
+ ALOGV("enable %p", this);
+ if (!mHasControl) return INVALID_OPERATION;
+ if (mEffect == 0) return DEAD_OBJECT;
+
+ if (mEnabled) {
+ return NO_ERROR;
+ }
+
+ mEnabled = true;
+
+ sp<ThreadBase> thread = mEffect->thread().promote();
+ if (thread != 0) {
+ thread->checkSuspendOnEffectEnabled(mEffect, true, mEffect->sessionId());
+ }
+
+ // checkSuspendOnEffectEnabled() can suspend this same effect when enabled
+ if (mEffect->suspended()) {
+ return NO_ERROR;
+ }
+
+ status_t status = mEffect->setEnabled(true);
+ if (status != NO_ERROR) {
+ if (thread != 0) {
+ thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
+ }
+ mEnabled = false;
+ }
+ return status;
+}
+
+status_t AudioFlinger::EffectHandle::disable()
+{
+ ALOGV("disable %p", this);
+ if (!mHasControl) return INVALID_OPERATION;
+ if (mEffect == 0) return DEAD_OBJECT;
+
+ if (!mEnabled) {
+ return NO_ERROR;
+ }
+ mEnabled = false;
+
+ if (mEffect->suspended()) {
+ return NO_ERROR;
+ }
+
+ status_t status = mEffect->setEnabled(false);
+
+ sp<ThreadBase> thread = mEffect->thread().promote();
+ if (thread != 0) {
+ thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
+ }
+
+ return status;
+}
+
+void AudioFlinger::EffectHandle::disconnect()
+{
+ disconnect(true);
+}
+
+void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
+{
+ ALOGV("disconnect(%s)", unpinIfLast ? "true" : "false");
+ if (mEffect == 0) {
+ return;
+ }
+ mEffect->disconnect(this, unpinIfLast);
+
+ if (mHasControl && mEnabled) {
+ sp<ThreadBase> thread = mEffect->thread().promote();
+ if (thread != 0) {
+ thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
+ }
+ }
+
+ // release sp on module => module destructor can be called now
+ mEffect.clear();
+ if (mClient != 0) {
+ if (mCblk != NULL) {
+ // unlike ~TrackBase(), mCblk is never a local new, so don't delete
+ mCblk->~effect_param_cblk_t(); // destroy our shared-structure.
+ }
+ mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
+ // Client destructor must run with AudioFlinger mutex locked
+ Mutex::Autolock _l(mClient->audioFlinger()->mLock);
+ mClient.clear();
+ }
+}
+
+status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData)
+{
+// ALOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
+// cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
+
+ // only get parameter command is permitted for applications not controlling the effect
+ if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
+ return INVALID_OPERATION;
+ }
+ if (mEffect == 0) return DEAD_OBJECT;
+ if (mClient == 0) return INVALID_OPERATION;
+
+ // handle commands that are not forwarded transparently to effect engine
+ if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
+ // No need to trylock() here as this function is executed in the binder thread serving a particular client process:
+ // no risk to block the whole media server process or mixer threads is we are stuck here
+ Mutex::Autolock _l(mCblk->lock);
+ if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
+ mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
+ mCblk->serverIndex = 0;
+ mCblk->clientIndex = 0;
+ return BAD_VALUE;
+ }
+ status_t status = NO_ERROR;
+ while (mCblk->serverIndex < mCblk->clientIndex) {
+ int reply;
+ uint32_t rsize = sizeof(int);
+ int *p = (int *)(mBuffer + mCblk->serverIndex);
+ int size = *p++;
+ if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
+ ALOGW("command(): invalid parameter block size");
+ break;
+ }
+ effect_param_t *param = (effect_param_t *)p;
+ if (param->psize == 0 || param->vsize == 0) {
+ ALOGW("command(): null parameter or value size");
+ mCblk->serverIndex += size;
+ continue;
+ }
+ uint32_t psize = sizeof(effect_param_t) +
+ ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
+ param->vsize;
+ status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
+ psize,
+ p,
+ &rsize,
+ &reply);
+ // stop at first error encountered
+ if (ret != NO_ERROR) {
+ status = ret;
+ *(int *)pReplyData = reply;
+ break;
+ } else if (reply != NO_ERROR) {
+ *(int *)pReplyData = reply;
+ break;
+ }
+ mCblk->serverIndex += size;
+ }
+ mCblk->serverIndex = 0;
+ mCblk->clientIndex = 0;
+ return status;
+ } else if (cmdCode == EFFECT_CMD_ENABLE) {
+ *(int *)pReplyData = NO_ERROR;
+ return enable();
+ } else if (cmdCode == EFFECT_CMD_DISABLE) {
+ *(int *)pReplyData = NO_ERROR;
+ return disable();
+ }
+
+ return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+}
+
+void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
+{
+ ALOGV("setControl %p control %d", this, hasControl);
+
+ mHasControl = hasControl;
+ mEnabled = enabled;
+
+ if (signal && mEffectClient != 0) {
+ mEffectClient->controlStatusChanged(hasControl);
+ }
+}
+
+void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t replySize,
+ void *pReplyData)
+{
+ if (mEffectClient != 0) {
+ mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+ }
+}
+
+
+
+void AudioFlinger::EffectHandle::setEnabled(bool enabled)
+{
+ if (mEffectClient != 0) {
+ mEffectClient->enableStatusChanged(enabled);
+ }
+}
+
+status_t AudioFlinger::EffectHandle::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ return BnEffect::onTransact(code, data, reply, flags);
+}
+
+
+void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
+{
+ bool locked = mCblk != NULL && tryLock(mCblk->lock);
+
+ snprintf(buffer, size, "\t\t\t%05d %05d %01u %01u %05u %05u\n",
+ (mClient == 0) ? getpid_cached : mClient->pid(),
+ mPriority,
+ mHasControl,
+ !locked,
+ mCblk ? mCblk->clientIndex : 0,
+ mCblk ? mCblk->serverIndex : 0
+ );
+
+ if (locked) {
+ mCblk->lock.unlock();
+ }
+}
+
+#undef LOG_TAG
+#define LOG_TAG "AudioFlinger::EffectChain"
+
+AudioFlinger::EffectChain::EffectChain(ThreadBase *thread,
+ int sessionId)
+ : mThread(thread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
+ mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
+ mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX)
+{
+ mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC);
+ if (thread == NULL) {
+ return;
+ }
+ mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
+ thread->frameCount();
+}
+
+AudioFlinger::EffectChain::~EffectChain()
+{
+ if (mOwnInBuffer) {
+ delete mInBuffer;
+ }
+
+}
+
+// getEffectFromDesc_l() must be called with ThreadBase::mLock held
+sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(effect_descriptor_t *descriptor)
+{
+ size_t size = mEffects.size();
+
+ for (size_t i = 0; i < size; i++) {
+ if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
+ return mEffects[i];
+ }
+ }
+ return 0;
+}
+
+// getEffectFromId_l() must be called with ThreadBase::mLock held
+sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
+{
+ size_t size = mEffects.size();
+
+ for (size_t i = 0; i < size; i++) {
+ // by convention, return first effect if id provided is 0 (0 is never a valid id)
+ if (id == 0 || mEffects[i]->id() == id) {
+ return mEffects[i];
+ }
+ }
+ return 0;
+}
+
+// getEffectFromType_l() must be called with ThreadBase::mLock held
+sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
+ const effect_uuid_t *type)
+{
+ size_t size = mEffects.size();
+
+ for (size_t i = 0; i < size; i++) {
+ if (memcmp(&mEffects[i]->desc().type, type, sizeof(effect_uuid_t)) == 0) {
+ return mEffects[i];
+ }
+ }
+ return 0;
+}
+
+// Must be called with EffectChain::mLock locked
+void AudioFlinger::EffectChain::process_l()
+{
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread == 0) {
+ ALOGW("process_l(): cannot promote mixer thread");
+ return;
+ }
+ bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
+ (mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
+ // always process effects unless no more tracks are on the session and the effect tail
+ // has been rendered
+ bool doProcess = true;
+ if (!isGlobalSession) {
+ bool tracksOnSession = (trackCnt() != 0);
+
+ if (!tracksOnSession && mTailBufferCount == 0) {
+ doProcess = false;
+ }
+
+ if (activeTrackCnt() == 0) {
+ // if no track is active and the effect tail has not been rendered,
+ // the input buffer must be cleared here as the mixer process will not do it
+ if (tracksOnSession || mTailBufferCount > 0) {
+ size_t numSamples = thread->frameCount() * thread->channelCount();
+ memset(mInBuffer, 0, numSamples * sizeof(int16_t));
+ if (mTailBufferCount > 0) {
+ mTailBufferCount--;
+ }
+ }
+ }
+ }
+
+ size_t size = mEffects.size();
+ if (doProcess) {
+ for (size_t i = 0; i < size; i++) {
+ mEffects[i]->process();
+ }
+ }
+ for (size_t i = 0; i < size; i++) {
+ mEffects[i]->updateState();
+ }
+}
+
+// addEffect_l() must be called with PlaybackThread::mLock held
+status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
+{
+ effect_descriptor_t desc = effect->desc();
+ uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
+
+ Mutex::Autolock _l(mLock);
+ effect->setChain(this);
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread == 0) {
+ return NO_INIT;
+ }
+ effect->setThread(thread);
+
+ if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ // Auxiliary effects are inserted at the beginning of mEffects vector as
+ // they are processed first and accumulated in chain input buffer
+ mEffects.insertAt(effect, 0);
+
+ // the input buffer for auxiliary effect contains mono samples in
+ // 32 bit format. This is to avoid saturation in AudoMixer
+ // accumulation stage. Saturation is done in EffectModule::process() before
+ // calling the process in effect engine
+ size_t numSamples = thread->frameCount();
+ int32_t *buffer = new int32_t[numSamples];
+ memset(buffer, 0, numSamples * sizeof(int32_t));
+ effect->setInBuffer((int16_t *)buffer);
+ // auxiliary effects output samples to chain input buffer for further processing
+ // by insert effects
+ effect->setOutBuffer(mInBuffer);
+ } else {
+ // Insert effects are inserted at the end of mEffects vector as they are processed
+ // after track and auxiliary effects.
+ // Insert effect order as a function of indicated preference:
+ // if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
+ // another effect is present
+ // else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
+ // last effect claiming first position
+ // else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
+ // first effect claiming last position
+ // else if EFFECT_FLAG_INSERT_ANY insert after first or before last
+ // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
+ // already present
+
+ size_t size = mEffects.size();
+ size_t idx_insert = size;
+ ssize_t idx_insert_first = -1;
+ ssize_t idx_insert_last = -1;
+
+ for (size_t i = 0; i < size; i++) {
+ effect_descriptor_t d = mEffects[i]->desc();
+ uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
+ uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
+ if (iMode == EFFECT_FLAG_TYPE_INSERT) {
+ // check invalid effect chaining combinations
+ if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
+ iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
+ ALOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
+ return INVALID_OPERATION;
+ }
+ // remember position of first insert effect and by default
+ // select this as insert position for new effect
+ if (idx_insert == size) {
+ idx_insert = i;
+ }
+ // remember position of last insert effect claiming
+ // first position
+ if (iPref == EFFECT_FLAG_INSERT_FIRST) {
+ idx_insert_first = i;
+ }
+ // remember position of first insert effect claiming
+ // last position
+ if (iPref == EFFECT_FLAG_INSERT_LAST &&
+ idx_insert_last == -1) {
+ idx_insert_last = i;
+ }
+ }
+ }
+
+ // modify idx_insert from first position if needed
+ if (insertPref == EFFECT_FLAG_INSERT_LAST) {
+ if (idx_insert_last != -1) {
+ idx_insert = idx_insert_last;
+ } else {
+ idx_insert = size;
+ }
+ } else {
+ if (idx_insert_first != -1) {
+ idx_insert = idx_insert_first + 1;
+ }
+ }
+
+ // always read samples from chain input buffer
+ effect->setInBuffer(mInBuffer);
+
+ // if last effect in the chain, output samples to chain
+ // output buffer, otherwise to chain input buffer
+ if (idx_insert == size) {
+ if (idx_insert != 0) {
+ mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
+ mEffects[idx_insert-1]->configure();
+ }
+ effect->setOutBuffer(mOutBuffer);
+ } else {
+ effect->setOutBuffer(mInBuffer);
+ }
+ mEffects.insertAt(effect, idx_insert);
+
+ ALOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
+ }
+ effect->configure();
+ return NO_ERROR;
+}
+
+// removeEffect_l() must be called with PlaybackThread::mLock held
+size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
+{
+ Mutex::Autolock _l(mLock);
+ size_t size = mEffects.size();
+ uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
+
+ for (size_t i = 0; i < size; i++) {
+ if (effect == mEffects[i]) {
+ // calling stop here will remove pre-processing effect from the audio HAL.
+ // This is safe as we hold the EffectChain mutex which guarantees that we are not in
+ // the middle of a read from audio HAL
+ if (mEffects[i]->state() == EffectModule::ACTIVE ||
+ mEffects[i]->state() == EffectModule::STOPPING) {
+ mEffects[i]->stop();
+ }
+ if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
+ delete[] effect->inBuffer();
+ } else {
+ if (i == size - 1 && i != 0) {
+ mEffects[i - 1]->setOutBuffer(mOutBuffer);
+ mEffects[i - 1]->configure();
+ }
+ }
+ mEffects.removeAt(i);
+ ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
+ break;
+ }
+ }
+
+ return mEffects.size();
+}
+
+// setDevice_l() must be called with PlaybackThread::mLock held
+void AudioFlinger::EffectChain::setDevice_l(uint32_t device)
+{
+ size_t size = mEffects.size();
+ for (size_t i = 0; i < size; i++) {
+ mEffects[i]->setDevice(device);
+ }
+}
+
+// setMode_l() must be called with PlaybackThread::mLock held
+void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
+{
+ size_t size = mEffects.size();
+ for (size_t i = 0; i < size; i++) {
+ mEffects[i]->setMode(mode);
+ }
+}
+
+// setVolume_l() must be called with PlaybackThread::mLock held
+bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
+{
+ uint32_t newLeft = *left;
+ uint32_t newRight = *right;
+ bool hasControl = false;
+ int ctrlIdx = -1;
+ size_t size = mEffects.size();
+
+ // first update volume controller
+ for (size_t i = size; i > 0; i--) {
+ if (mEffects[i - 1]->isProcessEnabled() &&
+ (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
+ ctrlIdx = i - 1;
+ hasControl = true;
+ break;
+ }
+ }
+
+ if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
+ if (hasControl) {
+ *left = mNewLeftVolume;
+ *right = mNewRightVolume;
+ }
+ return hasControl;
+ }
+
+ mVolumeCtrlIdx = ctrlIdx;
+ mLeftVolume = newLeft;
+ mRightVolume = newRight;
+
+ // second get volume update from volume controller
+ if (ctrlIdx >= 0) {
+ mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
+ mNewLeftVolume = newLeft;
+ mNewRightVolume = newRight;
+ }
+ // then indicate volume to all other effects in chain.
+ // Pass altered volume to effects before volume controller
+ // and requested volume to effects after controller
+ uint32_t lVol = newLeft;
+ uint32_t rVol = newRight;
+
+ for (size_t i = 0; i < size; i++) {
+ if ((int)i == ctrlIdx) continue;
+ // this also works for ctrlIdx == -1 when there is no volume controller
+ if ((int)i > ctrlIdx) {
+ lVol = *left;
+ rVol = *right;
+ }
+ mEffects[i]->setVolume(&lVol, &rVol, false);
+ }
+ *left = newLeft;
+ *right = newRight;
+
+ return hasControl;
+}
+
+status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
+ result.append(buffer);
+
+ bool locked = tryLock(mLock);
+ // failed to lock - AudioFlinger is probably deadlocked
+ if (!locked) {
+ result.append("\tCould not lock mutex:\n");
+ }
+
+ result.append("\tNum fx In buffer Out buffer Active tracks:\n");
+ snprintf(buffer, SIZE, "\t%02d 0x%08x 0x%08x %d\n",
+ mEffects.size(),
+ (uint32_t)mInBuffer,
+ (uint32_t)mOutBuffer,
+ mActiveTrackCnt);
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+
+ for (size_t i = 0; i < mEffects.size(); ++i) {
+ sp<EffectModule> effect = mEffects[i];
+ if (effect != 0) {
+ effect->dump(fd, args);
+ }
+ }
+
+ if (locked) {
+ mLock.unlock();
+ }
+
+ return NO_ERROR;
+}
+
+// must be called with ThreadBase::mLock held
+void AudioFlinger::EffectChain::setEffectSuspended_l(
+ const effect_uuid_t *type, bool suspend)
+{
+ sp<SuspendedEffectDesc> desc;
+ // use effect type UUID timelow as key as there is no real risk of identical
+ // timeLow fields among effect type UUIDs.
+ ssize_t index = mSuspendedEffects.indexOfKey(type->timeLow);
+ if (suspend) {
+ if (index >= 0) {
+ desc = mSuspendedEffects.valueAt(index);
+ } else {
+ desc = new SuspendedEffectDesc();
+ memcpy(&desc->mType, type, sizeof(effect_uuid_t));
+ mSuspendedEffects.add(type->timeLow, desc);
+ ALOGV("setEffectSuspended_l() add entry for %08x", type->timeLow);
+ }
+ if (desc->mRefCount++ == 0) {
+ sp<EffectModule> effect = getEffectIfEnabled(type);
+ if (effect != 0) {
+ desc->mEffect = effect;
+ effect->setSuspended(true);
+ effect->setEnabled(false);
+ }
+ }
+ } else {
+ if (index < 0) {
+ return;
+ }
+ desc = mSuspendedEffects.valueAt(index);
+ if (desc->mRefCount <= 0) {
+ ALOGW("setEffectSuspended_l() restore refcount should not be 0 %d", desc->mRefCount);
+ desc->mRefCount = 1;
+ }
+ if (--desc->mRefCount == 0) {
+ ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
+ if (desc->mEffect != 0) {
+ sp<EffectModule> effect = desc->mEffect.promote();
+ if (effect != 0) {
+ effect->setSuspended(false);
+ sp<EffectHandle> handle = effect->controlHandle();
+ if (handle != 0) {
+ effect->setEnabled(handle->enabled());
+ }
+ }
+ desc->mEffect.clear();
+ }
+ mSuspendedEffects.removeItemsAt(index);
+ }
+ }
+}
+
+// must be called with ThreadBase::mLock held
+void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
+{
+ sp<SuspendedEffectDesc> desc;
+
+ ssize_t index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
+ if (suspend) {
+ if (index >= 0) {
+ desc = mSuspendedEffects.valueAt(index);
+ } else {
+ desc = new SuspendedEffectDesc();
+ mSuspendedEffects.add((int)kKeyForSuspendAll, desc);
+ ALOGV("setEffectSuspendedAll_l() add entry for 0");
+ }
+ if (desc->mRefCount++ == 0) {
+ Vector< sp<EffectModule> > effects;
+ getSuspendEligibleEffects(effects);
+ for (size_t i = 0; i < effects.size(); i++) {
+ setEffectSuspended_l(&effects[i]->desc().type, true);
+ }
+ }
+ } else {
+ if (index < 0) {
+ return;
+ }
+ desc = mSuspendedEffects.valueAt(index);
+ if (desc->mRefCount <= 0) {
+ ALOGW("setEffectSuspendedAll_l() restore refcount should not be 0 %d", desc->mRefCount);
+ desc->mRefCount = 1;
+ }
+ if (--desc->mRefCount == 0) {
+ Vector<const effect_uuid_t *> types;
+ for (size_t i = 0; i < mSuspendedEffects.size(); i++) {
+ if (mSuspendedEffects.keyAt(i) == (int)kKeyForSuspendAll) {
+ continue;
+ }
+ types.add(&mSuspendedEffects.valueAt(i)->mType);
+ }
+ for (size_t i = 0; i < types.size(); i++) {
+ setEffectSuspended_l(types[i], false);
+ }
+ ALOGV("setEffectSuspendedAll_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
+ mSuspendedEffects.removeItem((int)kKeyForSuspendAll);
+ }
+ }
+}
+
+
+// The volume effect is used for automated tests only
+#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_
+
+bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
+{
+ // auxiliary effects and visualizer are never suspended on output mix
+ if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
+ (((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
+ (memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) ||
+ (memcmp(&desc.type, SL_IID_VOLUME, sizeof(effect_uuid_t)) == 0))) {
+ return false;
+ }
+ return true;
+}
+
+void AudioFlinger::EffectChain::getSuspendEligibleEffects(Vector< sp<AudioFlinger::EffectModule> > &effects)
+{
+ effects.clear();
+ for (size_t i = 0; i < mEffects.size(); i++) {
+ if (isEffectEligibleForSuspend(mEffects[i]->desc())) {
+ effects.add(mEffects[i]);
+ }
+ }
+}
+
+sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
+ const effect_uuid_t *type)
+{
+ sp<EffectModule> effect = getEffectFromType_l(type);
+ return effect != 0 && effect->isEnabled() ? effect : 0;
+}
+
+void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
+ bool enabled)
+{
+ ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
+ if (enabled) {
+ if (index < 0) {
+ // if the effect is not suspend check if all effects are suspended
+ index = mSuspendedEffects.indexOfKey((int)kKeyForSuspendAll);
+ if (index < 0) {
+ return;
+ }
+ if (!isEffectEligibleForSuspend(effect->desc())) {
+ return;
+ }
+ setEffectSuspended_l(&effect->desc().type, enabled);
+ index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
+ if (index < 0) {
+ ALOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
+ return;
+ }
+ }
+ ALOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
+ effect->desc().type.timeLow);
+ sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
+ // if effect is requested to suspended but was not yet enabled, supend it now.
+ if (desc->mEffect == 0) {
+ desc->mEffect = effect;
+ effect->setEnabled(false);
+ effect->setSuspended(true);
+ }
+ } else {
+ if (index < 0) {
+ return;
+ }
+ ALOGV("checkSuspendOnEffectEnabled() disable restoring fx %08x",
+ effect->desc().type.timeLow);
+ sp<SuspendedEffectDesc> desc = mSuspendedEffects.valueAt(index);
+ desc->mEffect.clear();
+ effect->setSuspended(false);
+ }
+}
+
+#undef LOG_TAG
+#define LOG_TAG "AudioFlinger"
+
+// ----------------------------------------------------------------------------
+
+status_t AudioFlinger::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ return BnAudioFlinger::onTransact(code, data, reply, flags);
+}
+
+}; // namespace android
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
new file mode 100644
index 0000000..795807d
--- /dev/null
+++ b/services/audioflinger/AudioFlinger.h
@@ -0,0 +1,1689 @@
+/*
+**
+** 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_FLINGER_H
+#define ANDROID_AUDIO_FLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include <common_time/cc_helper.h>
+
+#include <media/IAudioFlinger.h>
+#include <media/IAudioFlingerClient.h>
+#include <media/IAudioTrack.h>
+#include <media/IAudioRecord.h>
+#include <media/AudioSystem.h>
+#include <media/AudioTrack.h>
+
+#include <utils/Atomic.h>
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <utils/SortedVector.h>
+#include <utils/TypeHelpers.h>
+#include <utils/Vector.h>
+
+#include <binder/BinderService.h>
+#include <binder/MemoryDealer.h>
+
+#include <system/audio.h>
+#include <hardware/audio.h>
+
+#include "AudioBufferProvider.h"
+
+#include <powermanager/IPowerManager.h>
+
+namespace android {
+
+class audio_track_cblk_t;
+class effect_param_cblk_t;
+class AudioMixer;
+class AudioBuffer;
+class AudioResampler;
+
+// ----------------------------------------------------------------------------
+
+// AudioFlinger has a hard-coded upper limit of 2 channels for capture and playback.
+// There is support for > 2 channel tracks down-mixed to 2 channel output via a down-mix effect.
+// Adding full support for > 2 channel capture or playback would require more than simply changing
+// this #define. There is an independent hard-coded upper limit in AudioMixer;
+// removing that AudioMixer limit would be necessary but insufficient to support > 2 channels.
+// The macro FCC_2 highlights some (but not all) places where there is are 2-channel assumptions.
+// Search also for "2", "left", "right", "[0]", "[1]", ">> 16", "<< 16", etc.
+#define FCC_2 2 // FCC_2 = Fixed Channel Count 2
+
+static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3);
+
+class AudioFlinger :
+ public BinderService<AudioFlinger>,
+ public BnAudioFlinger
+{
+ friend class BinderService<AudioFlinger>; // for AudioFlinger()
+public:
+ static const char* getServiceName() { return "media.audio_flinger"; }
+
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ // IAudioFlinger interface, in binder opcode order
+ virtual sp<IAudioTrack> createTrack(
+ pid_t pid,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ IAudioFlinger::track_flags_t flags,
+ const sp<IMemory>& sharedBuffer,
+ audio_io_handle_t output,
+ int *sessionId,
+ status_t *status);
+
+ virtual sp<IAudioRecord> openRecord(
+ pid_t pid,
+ audio_io_handle_t input,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ IAudioFlinger::track_flags_t flags,
+ int *sessionId,
+ status_t *status);
+
+ virtual uint32_t sampleRate(audio_io_handle_t output) const;
+ virtual int channelCount(audio_io_handle_t output) const;
+ virtual audio_format_t format(audio_io_handle_t output) const;
+ virtual size_t frameCount(audio_io_handle_t output) const;
+ virtual uint32_t latency(audio_io_handle_t output) const;
+
+ virtual status_t setMasterVolume(float value);
+ virtual status_t setMasterMute(bool muted);
+
+ virtual float masterVolume() const;
+ virtual float masterVolumeSW() const;
+ virtual bool masterMute() const;
+
+ virtual status_t setStreamVolume(audio_stream_type_t stream, float value,
+ audio_io_handle_t output);
+ virtual status_t setStreamMute(audio_stream_type_t stream, bool muted);
+
+ virtual float streamVolume(audio_stream_type_t stream,
+ audio_io_handle_t output) const;
+ virtual bool streamMute(audio_stream_type_t stream) const;
+
+ virtual status_t setMode(audio_mode_t mode);
+
+ virtual status_t setMicMute(bool state);
+ virtual bool getMicMute() const;
+
+ virtual status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
+ virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const;
+
+ virtual void registerClient(const sp<IAudioFlingerClient>& client);
+
+ virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount) const;
+
+ virtual audio_io_handle_t openOutput(uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ audio_format_t *pFormat,
+ uint32_t *pChannels,
+ uint32_t *pLatencyMs,
+ audio_policy_output_flags_t flags);
+
+ virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
+ audio_io_handle_t output2);
+
+ virtual status_t closeOutput(audio_io_handle_t output);
+
+ virtual status_t suspendOutput(audio_io_handle_t output);
+
+ virtual status_t restoreOutput(audio_io_handle_t output);
+
+ virtual audio_io_handle_t openInput(uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ audio_format_t *pFormat,
+ uint32_t *pChannels,
+ audio_in_acoustics_t acoustics);
+
+ virtual status_t closeInput(audio_io_handle_t input);
+
+ virtual status_t setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output);
+
+ virtual status_t setVoiceVolume(float volume);
+
+ virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
+ audio_io_handle_t output) const;
+
+ virtual unsigned int getInputFramesLost(audio_io_handle_t ioHandle) const;
+
+ virtual int newAudioSessionId();
+
+ virtual void acquireAudioSessionId(int audioSession);
+
+ virtual void releaseAudioSessionId(int audioSession);
+
+ virtual status_t queryNumberEffects(uint32_t *numEffects) const;
+
+ virtual status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor) const;
+
+ virtual status_t getEffectDescriptor(const effect_uuid_t *pUuid,
+ effect_descriptor_t *descriptor) const;
+
+ virtual sp<IEffect> createEffect(pid_t pid,
+ effect_descriptor_t *pDesc,
+ const sp<IEffectClient>& effectClient,
+ int32_t priority,
+ audio_io_handle_t io,
+ int sessionId,
+ status_t *status,
+ int *id,
+ int *enabled);
+
+ virtual status_t moveEffects(int sessionId, audio_io_handle_t srcOutput,
+ audio_io_handle_t dstOutput);
+
+ virtual status_t onTransact(
+ uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags);
+
+ // end of IAudioFlinger interface
+
+private:
+ audio_mode_t getMode() const { return mMode; }
+
+ bool btNrecIsOff() const { return mBtNrecIsOff; }
+
+ AudioFlinger();
+ virtual ~AudioFlinger();
+
+ // call in any IAudioFlinger method that accesses mPrimaryHardwareDev
+ status_t initCheck() const { return mPrimaryHardwareDev == NULL ? NO_INIT : NO_ERROR; }
+
+ // RefBase
+ virtual void onFirstRef();
+
+ audio_hw_device_t* findSuitableHwDev_l(uint32_t devices);
+ void purgeStaleEffects_l();
+
+ // standby delay for MIXER and DUPLICATING playback threads is read from property
+ // ro.audio.flinger_standbytime_ms or defaults to kDefaultStandbyTimeInNsecs
+ static nsecs_t mStandbyTimeInNsecs;
+
+ // Internal dump utilites.
+ status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
+ status_t dumpClients(int fd, const Vector<String16>& args);
+ status_t dumpInternals(int fd, const Vector<String16>& args);
+
+ // --- Client ---
+ class Client : public RefBase {
+ public:
+ Client(const sp<AudioFlinger>& audioFlinger, pid_t pid);
+ virtual ~Client();
+ sp<MemoryDealer> heap() const;
+ pid_t pid() const { return mPid; }
+ sp<AudioFlinger> audioFlinger() const { return mAudioFlinger; }
+
+ bool reserveTimedTrack();
+ void releaseTimedTrack();
+
+ private:
+ Client(const Client&);
+ Client& operator = (const Client&);
+ const sp<AudioFlinger> mAudioFlinger;
+ const sp<MemoryDealer> mMemoryDealer;
+ const pid_t mPid;
+
+ Mutex mTimedTrackLock;
+ int mTimedTrackCount;
+ };
+
+ // --- Notification Client ---
+ class NotificationClient : public IBinder::DeathRecipient {
+ public:
+ NotificationClient(const sp<AudioFlinger>& audioFlinger,
+ const sp<IAudioFlingerClient>& client,
+ pid_t pid);
+ virtual ~NotificationClient();
+
+ sp<IAudioFlingerClient> audioFlingerClient() const { return mAudioFlingerClient; }
+
+ // IBinder::DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+
+ private:
+ NotificationClient(const NotificationClient&);
+ NotificationClient& operator = (const NotificationClient&);
+
+ const sp<AudioFlinger> mAudioFlinger;
+ const pid_t mPid;
+ const sp<IAudioFlingerClient> mAudioFlingerClient;
+ };
+
+ class TrackHandle;
+ class RecordHandle;
+ class RecordThread;
+ class PlaybackThread;
+ class MixerThread;
+ class DirectOutputThread;
+ class DuplicatingThread;
+ class Track;
+ class RecordTrack;
+ class EffectModule;
+ class EffectHandle;
+ class EffectChain;
+ struct AudioStreamOut;
+ struct AudioStreamIn;
+
+ class ThreadBase : public Thread {
+ public:
+
+ enum type_t {
+ MIXER, // Thread class is MixerThread
+ DIRECT, // Thread class is DirectOutputThread
+ DUPLICATING, // Thread class is DuplicatingThread
+ RECORD // Thread class is RecordThread
+ };
+
+ ThreadBase (const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id, uint32_t device, type_t type);
+ virtual ~ThreadBase();
+
+ status_t dumpBase(int fd, const Vector<String16>& args);
+ status_t dumpEffectChains(int fd, const Vector<String16>& args);
+
+ void clearPowerManager();
+
+ // base for record and playback
+ class TrackBase : public AudioBufferProvider, public RefBase {
+
+ public:
+ enum track_state {
+ IDLE,
+ TERMINATED,
+ // These are order-sensitive; do not change order without reviewing the impact.
+ // In particular there are assumptions about > STOPPED.
+ STOPPED,
+ RESUMING,
+ ACTIVE,
+ PAUSING,
+ PAUSED
+ };
+
+ TrackBase(ThreadBase *thread,
+ const sp<Client>& client,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ const sp<IMemory>& sharedBuffer,
+ int sessionId);
+ virtual ~TrackBase();
+
+ virtual status_t start(pid_t tid) = 0;
+ virtual void stop() = 0;
+ sp<IMemory> getCblk() const { return mCblkMemory; }
+ audio_track_cblk_t* cblk() const { return mCblk; }
+ int sessionId() const { return mSessionId; }
+
+ protected:
+ TrackBase(const TrackBase&);
+ TrackBase& operator = (const TrackBase&);
+
+ // AudioBufferProvider interface
+ virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts) = 0;
+ virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+
+ audio_format_t format() const {
+ return mFormat;
+ }
+
+ int channelCount() const { return mChannelCount; }
+
+ uint32_t channelMask() const { return mChannelMask; }
+
+ int sampleRate() const; // FIXME inline after cblk sr moved
+
+ void* getBuffer(uint32_t offset, uint32_t frames) const;
+
+ bool isStopped() const {
+ return mState == STOPPED;
+ }
+
+ bool isTerminated() const {
+ return mState == TERMINATED;
+ }
+
+ bool step();
+ void reset();
+
+ const wp<ThreadBase> mThread;
+ /*const*/ sp<Client> mClient; // see explanation at ~TrackBase() why not const
+ sp<IMemory> mCblkMemory;
+ audio_track_cblk_t* mCblk;
+ void* mBuffer;
+ void* mBufferEnd;
+ uint32_t mFrameCount;
+ // we don't really need a lock for these
+ track_state mState;
+ const audio_format_t mFormat;
+ bool mStepServerFailed;
+ const int mSessionId;
+ uint8_t mChannelCount;
+ uint32_t mChannelMask;
+ };
+
+ class ConfigEvent {
+ public:
+ ConfigEvent() : mEvent(0), mParam(0) {}
+
+ int mEvent;
+ int mParam;
+ };
+
+ class PMDeathRecipient : public IBinder::DeathRecipient {
+ public:
+ PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
+ virtual ~PMDeathRecipient() {}
+
+ // IBinder::DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+
+ private:
+ PMDeathRecipient(const PMDeathRecipient&);
+ PMDeathRecipient& operator = (const PMDeathRecipient&);
+
+ wp<ThreadBase> mThread;
+ };
+
+ virtual status_t initCheck() const = 0;
+ type_t type() const { return mType; }
+ uint32_t sampleRate() const { return mSampleRate; }
+ int channelCount() const { return mChannelCount; }
+ audio_format_t format() const { return mFormat; }
+ size_t frameCount() const { return mFrameCount; }
+ void wakeUp() { mWaitWorkCV.broadcast(); }
+ // Should be "virtual status_t requestExitAndWait()" and override same
+ // method in Thread, but Thread::requestExitAndWait() is not yet virtual.
+ void exit();
+ virtual bool checkForNewParameters_l() = 0;
+ virtual status_t setParameters(const String8& keyValuePairs);
+ virtual String8 getParameters(const String8& keys) = 0;
+ virtual void audioConfigChanged_l(int event, int param = 0) = 0;
+ void sendConfigEvent(int event, int param = 0);
+ void sendConfigEvent_l(int event, int param = 0);
+ void processConfigEvents();
+ audio_io_handle_t id() const { return mId;}
+ bool standby() const { return mStandby; }
+ uint32_t device() const { return mDevice; }
+ virtual audio_stream_t* stream() = 0;
+
+ sp<EffectHandle> createEffect_l(
+ const sp<AudioFlinger::Client>& client,
+ const sp<IEffectClient>& effectClient,
+ int32_t priority,
+ int sessionId,
+ effect_descriptor_t *desc,
+ int *enabled,
+ status_t *status);
+ void disconnectEffect(const sp< EffectModule>& effect,
+ const wp<EffectHandle>& handle,
+ bool unpinIfLast);
+
+ // return values for hasAudioSession (bit field)
+ enum effect_state {
+ EFFECT_SESSION = 0x1, // the audio session corresponds to at least one
+ // effect
+ TRACK_SESSION = 0x2 // the audio session corresponds to at least one
+ // track
+ };
+
+ // get effect chain corresponding to session Id.
+ sp<EffectChain> getEffectChain(int sessionId);
+ // same as getEffectChain() but must be called with ThreadBase mutex locked
+ sp<EffectChain> getEffectChain_l(int sessionId);
+ // add an effect chain to the chain list (mEffectChains)
+ virtual status_t addEffectChain_l(const sp<EffectChain>& chain) = 0;
+ // remove an effect chain from the chain list (mEffectChains)
+ virtual size_t removeEffectChain_l(const sp<EffectChain>& chain) = 0;
+ // lock all effect chains Mutexes. Must be called before releasing the
+ // ThreadBase mutex before processing the mixer and effects. This guarantees the
+ // integrity of the chains during the process.
+ // Also sets the parameter 'effectChains' to current value of mEffectChains.
+ void lockEffectChains_l(Vector< sp<EffectChain> >& effectChains);
+ // unlock effect chains after process
+ void unlockEffectChains(const Vector< sp<EffectChain> >& effectChains);
+ // set audio mode to all effect chains
+ void setMode(audio_mode_t mode);
+ // get effect module with corresponding ID on specified audio session
+ sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId);
+ // add and effect module. Also creates the effect chain is none exists for
+ // the effects audio session
+ status_t addEffect_l(const sp< EffectModule>& effect);
+ // remove and effect module. Also removes the effect chain is this was the last
+ // effect
+ void removeEffect_l(const sp< EffectModule>& effect);
+ // detach all tracks connected to an auxiliary effect
+ virtual void detachAuxEffect_l(int effectId) {}
+ // returns either EFFECT_SESSION if effects on this audio session exist in one
+ // chain, or TRACK_SESSION if tracks on this audio session exist, or both
+ virtual uint32_t hasAudioSession(int sessionId) = 0;
+ // the value returned by default implementation is not important as the
+ // strategy is only meaningful for PlaybackThread which implements this method
+ virtual uint32_t getStrategyForSession_l(int sessionId) { return 0; }
+
+ // suspend or restore effect according to the type of effect passed. a NULL
+ // type pointer means suspend all effects in the session
+ void setEffectSuspended(const effect_uuid_t *type,
+ bool suspend,
+ int sessionId = AUDIO_SESSION_OUTPUT_MIX);
+ // check if some effects must be suspended/restored when an effect is enabled
+ // or disabled
+ void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
+ bool enabled,
+ int sessionId = AUDIO_SESSION_OUTPUT_MIX);
+ void checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
+ bool enabled,
+ int sessionId = AUDIO_SESSION_OUTPUT_MIX);
+ mutable Mutex mLock;
+
+ protected:
+
+ // entry describing an effect being suspended in mSuspendedSessions keyed vector
+ class SuspendedSessionDesc : public RefBase {
+ public:
+ SuspendedSessionDesc() : mRefCount(0) {}
+
+ int mRefCount; // number of active suspend requests
+ effect_uuid_t mType; // effect type UUID
+ };
+
+ void acquireWakeLock();
+ void acquireWakeLock_l();
+ void releaseWakeLock();
+ void releaseWakeLock_l();
+ void setEffectSuspended_l(const effect_uuid_t *type,
+ bool suspend,
+ int sessionId = AUDIO_SESSION_OUTPUT_MIX);
+ // updated mSuspendedSessions when an effect suspended or restored
+ void updateSuspendedSessions_l(const effect_uuid_t *type,
+ bool suspend,
+ int sessionId);
+ // check if some effects must be suspended when an effect chain is added
+ void checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain);
+
+ friend class AudioFlinger; // for mEffectChains
+
+ const type_t mType;
+
+ // Used by parameters, config events, addTrack_l, exit
+ Condition mWaitWorkCV;
+
+ const sp<AudioFlinger> mAudioFlinger;
+ uint32_t mSampleRate;
+ size_t mFrameCount;
+ uint32_t mChannelMask;
+ uint16_t mChannelCount;
+ size_t mFrameSize;
+ audio_format_t mFormat;
+
+ // Parameter sequence by client: binder thread calling setParameters():
+ // 1. Lock mLock
+ // 2. Append to mNewParameters
+ // 3. mWaitWorkCV.signal
+ // 4. mParamCond.waitRelative with timeout
+ // 5. read mParamStatus
+ // 6. mWaitWorkCV.signal
+ // 7. Unlock
+ //
+ // Parameter sequence by server: threadLoop calling checkForNewParameters_l():
+ // 1. Lock mLock
+ // 2. If there is an entry in mNewParameters proceed ...
+ // 2. Read first entry in mNewParameters
+ // 3. Process
+ // 4. Remove first entry from mNewParameters
+ // 5. Set mParamStatus
+ // 6. mParamCond.signal
+ // 7. mWaitWorkCV.wait with timeout (this is to avoid overwriting mParamStatus)
+ // 8. Unlock
+ Condition mParamCond;
+ Vector<String8> mNewParameters;
+ status_t mParamStatus;
+
+ Vector<ConfigEvent> mConfigEvents;
+ bool mStandby;
+ const audio_io_handle_t mId;
+ Vector< sp<EffectChain> > mEffectChains;
+ uint32_t mDevice; // output device for PlaybackThread
+ // input + output devices for RecordThread
+ static const int kNameLength = 16; // prctl(PR_SET_NAME) limit
+ char mName[kNameLength];
+ sp<IPowerManager> mPowerManager;
+ sp<IBinder> mWakeLockToken;
+ const sp<PMDeathRecipient> mDeathRecipient;
+ // list of suspended effects per session and per type. The first vector is
+ // keyed by session ID, the second by type UUID timeLow field
+ KeyedVector< int, KeyedVector< int, sp<SuspendedSessionDesc> > > mSuspendedSessions;
+ };
+
+ struct stream_type_t {
+ stream_type_t()
+ : volume(1.0f),
+ mute(false),
+ valid(true)
+ {
+ }
+ float volume;
+ bool mute;
+ bool valid;
+ };
+
+ // --- PlaybackThread ---
+ class PlaybackThread : public ThreadBase {
+ public:
+
+ enum mixer_state {
+ MIXER_IDLE, // no active tracks
+ MIXER_TRACKS_ENABLED, // at least one active track, but no track has any data ready
+ MIXER_TRACKS_READY // at least one active track, and at least one track has data
+ // standby mode does not have an enum value
+ // suspend by audio policy manager is orthogonal to mixer state
+ };
+
+ // playback track
+ class Track : public TrackBase {
+ public:
+ Track( PlaybackThread *thread,
+ const sp<Client>& client,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ const sp<IMemory>& sharedBuffer,
+ int sessionId);
+ virtual ~Track();
+
+ void dump(char* buffer, size_t size);
+ virtual status_t start(pid_t tid);
+ virtual void stop();
+ void pause();
+
+ void flush();
+ void destroy();
+ void mute(bool);
+ int name() const {
+ return mName;
+ }
+
+ audio_stream_type_t streamType() const {
+ return mStreamType;
+ }
+ status_t attachAuxEffect(int EffectId);
+ void setAuxBuffer(int EffectId, int32_t *buffer);
+ int32_t *auxBuffer() const { return mAuxBuffer; }
+ void setMainBuffer(int16_t *buffer) { mMainBuffer = buffer; }
+ int16_t *mainBuffer() const { return mMainBuffer; }
+ int auxEffectId() const { return mAuxEffectId; }
+
+ protected:
+ // for numerous
+ friend class PlaybackThread;
+ friend class MixerThread;
+ friend class DirectOutputThread;
+
+ Track(const Track&);
+ Track& operator = (const Track&);
+
+ // AudioBufferProvider interface
+ virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts = kInvalidPTS);
+ // releaseBuffer() not overridden
+
+ virtual uint32_t framesReady() const;
+
+ bool isMuted() const { return mMute; }
+ bool isPausing() const {
+ return mState == PAUSING;
+ }
+ bool isPaused() const {
+ return mState == PAUSED;
+ }
+ bool isReady() const;
+ void setPaused() { mState = PAUSED; }
+ void reset();
+
+ bool isOutputTrack() const {
+ return (mStreamType == AUDIO_STREAM_CNT);
+ }
+
+ public:
+ virtual bool isTimedTrack() const { return false; }
+ protected:
+
+ // we don't really need a lock for these
+ volatile bool mMute;
+ // FILLED state is used for suppressing volume ramp at begin of playing
+ enum {FS_FILLING, FS_FILLED, FS_ACTIVE};
+ mutable uint8_t mFillingUpStatus;
+ int8_t mRetryCount;
+ const sp<IMemory> mSharedBuffer;
+ bool mResetDone;
+ const audio_stream_type_t mStreamType;
+ int mName;
+ int16_t *mMainBuffer;
+ int32_t *mAuxBuffer;
+ int mAuxEffectId;
+ bool mHasVolumeController;
+ }; // end of Track
+
+ class TimedTrack : public Track {
+ public:
+ static sp<TimedTrack> create(PlaybackThread *thread,
+ const sp<Client>& client,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ const sp<IMemory>& sharedBuffer,
+ int sessionId);
+ ~TimedTrack();
+
+ class TimedBuffer {
+ public:
+ TimedBuffer();
+ TimedBuffer(const sp<IMemory>& buffer, int64_t pts);
+ const sp<IMemory>& buffer() const { return mBuffer; }
+ int64_t pts() const { return mPTS; }
+ int position() const { return mPosition; }
+ void setPosition(int pos) { mPosition = pos; }
+ private:
+ sp<IMemory> mBuffer;
+ int64_t mPTS;
+ int mPosition;
+ };
+
+ virtual bool isTimedTrack() const { return true; }
+
+ virtual uint32_t framesReady() const;
+
+ // AudioBufferProvider interface
+ virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts);
+ virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+
+ void timedYieldSamples(AudioBufferProvider::Buffer* buffer);
+ void timedYieldSilence(uint32_t numFrames,
+ AudioBufferProvider::Buffer* buffer);
+
+ status_t allocateTimedBuffer(size_t size,
+ sp<IMemory>* buffer);
+ status_t queueTimedBuffer(const sp<IMemory>& buffer,
+ int64_t pts);
+ status_t setMediaTimeTransform(const LinearTransform& xform,
+ TimedAudioTrack::TargetTimeline target);
+ void trimTimedBufferQueue_l();
+
+ private:
+ TimedTrack(PlaybackThread *thread,
+ const sp<Client>& client,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ const sp<IMemory>& sharedBuffer,
+ int sessionId);
+
+ uint64_t mLocalTimeFreq;
+ LinearTransform mLocalTimeToSampleTransform;
+ sp<MemoryDealer> mTimedMemoryDealer;
+ Vector<TimedBuffer> mTimedBufferQueue;
+ uint8_t* mTimedSilenceBuffer;
+ uint32_t mTimedSilenceBufferSize;
+ mutable Mutex mTimedBufferQueueLock;
+ bool mTimedAudioOutputOnTime;
+ CCHelper mCCHelper;
+
+ Mutex mMediaTimeTransformLock;
+ LinearTransform mMediaTimeTransform;
+ bool mMediaTimeTransformValid;
+ TimedAudioTrack::TargetTimeline mMediaTimeTransformTarget;
+ };
+
+
+ // playback track
+ class OutputTrack : public Track {
+ public:
+
+ class Buffer: public AudioBufferProvider::Buffer {
+ public:
+ int16_t *mBuffer;
+ };
+
+ OutputTrack(PlaybackThread *thread,
+ DuplicatingThread *sourceThread,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount);
+ virtual ~OutputTrack();
+
+ virtual status_t start(pid_t tid);
+ virtual void stop();
+ bool write(int16_t* data, uint32_t frames);
+ bool bufferQueueEmpty() const { return mBufferQueue.size() == 0; }
+ bool isActive() const { return mActive; }
+ const wp<ThreadBase>& thread() const { return mThread; }
+
+ private:
+
+ enum {
+ NO_MORE_BUFFERS = 0x80000001, // same in AudioTrack.h, ok to be different value
+ };
+
+ status_t obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs);
+ void clearBufferQueue();
+
+ // Maximum number of pending buffers allocated by OutputTrack::write()
+ static const uint8_t kMaxOverFlowBuffers = 10;
+
+ Vector < Buffer* > mBufferQueue;
+ AudioBufferProvider::Buffer mOutBuffer;
+ bool mActive;
+ DuplicatingThread* const mSourceThread; // for waitTimeMs() in write()
+ }; // end of OutputTrack
+
+ PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
+ audio_io_handle_t id, uint32_t device, type_t type);
+ virtual ~PlaybackThread();
+
+ status_t dump(int fd, const Vector<String16>& args);
+
+ // Thread virtuals
+ virtual status_t readyToRun();
+ virtual bool threadLoop();
+
+ // RefBase
+ virtual void onFirstRef();
+
+protected:
+ // Code snippets that were lifted up out of threadLoop()
+ virtual void threadLoop_mix() = 0;
+ virtual void threadLoop_sleepTime() = 0;
+ virtual void threadLoop_write();
+ virtual void threadLoop_standby();
+
+ // prepareTracks_l reads and writes mActiveTracks, and also returns the
+ // pending set of tracks to remove via Vector 'tracksToRemove'. The caller is
+ // responsible for clearing or destroying this Vector later on, when it
+ // is safe to do so. That will drop the final ref count and destroy the tracks.
+ virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove) = 0;
+
+public:
+
+ virtual status_t initCheck() const { return (mOutput == NULL) ? NO_INIT : NO_ERROR; }
+
+ // return estimated latency in milliseconds, as reported by HAL
+ uint32_t latency() const;
+
+ void setMasterVolume(float value);
+ void setMasterMute(bool muted);
+
+ void setStreamVolume(audio_stream_type_t stream, float value);
+ void setStreamMute(audio_stream_type_t stream, bool muted);
+
+ float streamVolume(audio_stream_type_t stream) const;
+
+ sp<Track> createTrack_l(
+ const sp<AudioFlinger::Client>& client,
+ audio_stream_type_t streamType,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ const sp<IMemory>& sharedBuffer,
+ int sessionId,
+ bool isTimed,
+ status_t *status);
+
+ AudioStreamOut* getOutput() const;
+ AudioStreamOut* clearOutput();
+ virtual audio_stream_t* stream();
+
+ void suspend() { mSuspended++; }
+ void restore() { if (mSuspended > 0) mSuspended--; }
+ bool isSuspended() const { return (mSuspended > 0); }
+ virtual String8 getParameters(const String8& keys);
+ virtual void audioConfigChanged_l(int event, int param = 0);
+ status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
+ int16_t *mixBuffer() const { return mMixBuffer; };
+
+ virtual void detachAuxEffect_l(int effectId);
+ status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track> track,
+ int EffectId);
+ status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track> track,
+ int EffectId);
+
+ virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
+ virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
+ virtual uint32_t hasAudioSession(int sessionId);
+ virtual uint32_t getStrategyForSession_l(int sessionId);
+
+ void setStreamValid(audio_stream_type_t streamType, bool valid);
+
+ protected:
+ int16_t* mMixBuffer;
+ uint32_t mSuspended; // suspend count, > 0 means suspended
+ int mBytesWritten;
+ private:
+ // mMasterMute is in both PlaybackThread and in AudioFlinger. When a
+ // PlaybackThread needs to find out if master-muted, it checks it's local
+ // copy rather than the one in AudioFlinger. This optimization saves a lock.
+ bool mMasterMute;
+ void setMasterMute_l(bool muted) { mMasterMute = muted; }
+ protected:
+ SortedVector< wp<Track> > mActiveTracks;
+
+ // Allocate a track name. Returns name >= 0 if successful, -1 on failure.
+ virtual int getTrackName_l() = 0;
+ virtual void deleteTrackName_l(int name) = 0;
+ virtual uint32_t activeSleepTimeUs();
+ virtual uint32_t idleSleepTimeUs() = 0;
+ virtual uint32_t suspendSleepTimeUs() = 0;
+
+ // Code snippets that are temporarily lifted up out of threadLoop() until the merge
+ void checkSilentMode_l();
+
+ // Non-trivial for DUPLICATING only
+ virtual void saveOutputTracks() { }
+ virtual void clearOutputTracks() { }
+
+ // Cache various calculated values, at threadLoop() entry and after a parameter change
+ virtual void cacheParameters_l();
+
+ private:
+
+ friend class AudioFlinger; // for numerous
+
+ PlaybackThread(const Client&);
+ PlaybackThread& operator = (const PlaybackThread&);
+
+ status_t addTrack_l(const sp<Track>& track);
+ void destroyTrack_l(const sp<Track>& track);
+ void removeTrack_l(const sp<Track>& track);
+
+ void readOutputParameters();
+
+ virtual status_t dumpInternals(int fd, const Vector<String16>& args);
+ status_t dumpTracks(int fd, const Vector<String16>& args);
+
+ SortedVector< sp<Track> > mTracks;
+ // mStreamTypes[] uses 1 additional stream type internally for the OutputTrack used by DuplicatingThread
+ stream_type_t mStreamTypes[AUDIO_STREAM_CNT + 1];
+ AudioStreamOut *mOutput;
+ float mMasterVolume;
+ nsecs_t mLastWriteTime;
+ int mNumWrites;
+ int mNumDelayedWrites;
+ bool mInWrite;
+
+ // FIXME rename these former local variables of threadLoop to standard "m" names
+ nsecs_t standbyTime;
+ size_t mixBufferSize;
+
+ // cached copies of activeSleepTimeUs() and idleSleepTimeUs() made by cacheParameters_l()
+ uint32_t activeSleepTime;
+ uint32_t idleSleepTime;
+
+ uint32_t sleepTime;
+
+ // mixer status returned by prepareTracks_l()
+ mixer_state mMixerStatus; // current cycle
+ mixer_state mPrevMixerStatus; // previous cycle
+
+ // FIXME move these declarations into the specific sub-class that needs them
+ // MIXER only
+ bool longStandbyExit;
+ uint32_t sleepTimeShift;
+
+ // same as AudioFlinger::mStandbyTimeInNsecs except for DIRECT which uses a shorter value
+ nsecs_t standbyDelay;
+
+ // MIXER only
+ nsecs_t maxPeriod;
+
+ // DUPLICATING only
+ uint32_t writeFrames;
+ };
+
+ class MixerThread : public PlaybackThread {
+ public:
+ MixerThread (const sp<AudioFlinger>& audioFlinger,
+ AudioStreamOut* output,
+ audio_io_handle_t id,
+ uint32_t device,
+ type_t type = MIXER);
+ virtual ~MixerThread();
+
+ // Thread virtuals
+
+ void invalidateTracks(audio_stream_type_t streamType);
+ virtual bool checkForNewParameters_l();
+ virtual status_t dumpInternals(int fd, const Vector<String16>& args);
+
+ protected:
+ virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
+ virtual int getTrackName_l();
+ virtual void deleteTrackName_l(int name);
+ virtual uint32_t idleSleepTimeUs();
+ virtual uint32_t suspendSleepTimeUs();
+ virtual void cacheParameters_l();
+
+ // threadLoop snippets
+ virtual void threadLoop_mix();
+ virtual void threadLoop_sleepTime();
+
+ AudioMixer* mAudioMixer;
+ };
+
+ class DirectOutputThread : public PlaybackThread {
+ public:
+
+ DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
+ audio_io_handle_t id, uint32_t device);
+ virtual ~DirectOutputThread();
+
+ // Thread virtuals
+
+ virtual bool checkForNewParameters_l();
+
+ protected:
+ virtual int getTrackName_l();
+ virtual void deleteTrackName_l(int name);
+ virtual uint32_t activeSleepTimeUs();
+ virtual uint32_t idleSleepTimeUs();
+ virtual uint32_t suspendSleepTimeUs();
+ virtual void cacheParameters_l();
+
+ // threadLoop snippets
+ virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
+ virtual void threadLoop_mix();
+ virtual void threadLoop_sleepTime();
+
+ // volumes last sent to audio HAL with stream->set_volume()
+ // FIXME use standard representation and names
+ float mLeftVolFloat;
+ float mRightVolFloat;
+ uint16_t mLeftVolShort;
+ uint16_t mRightVolShort;
+
+ // FIXME rename these former local variables of threadLoop to standard names
+ // next 3 were local to the while !exitingPending loop
+ bool rampVolume;
+ uint16_t leftVol;
+ uint16_t rightVol;
+
+private:
+ // prepareTracks_l() tells threadLoop_mix() the name of the single active track
+ sp<Track> mActiveTrack;
+ };
+
+ class DuplicatingThread : public MixerThread {
+ public:
+ DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread,
+ audio_io_handle_t id);
+ virtual ~DuplicatingThread();
+
+ // Thread virtuals
+ void addOutputTrack(MixerThread* thread);
+ void removeOutputTrack(MixerThread* thread);
+ uint32_t waitTimeMs() { return mWaitTimeMs; }
+ protected:
+ virtual uint32_t activeSleepTimeUs();
+
+ private:
+ bool outputsReady(const SortedVector< sp<OutputTrack> > &outputTracks);
+ protected:
+ // threadLoop snippets
+ virtual void threadLoop_mix();
+ virtual void threadLoop_sleepTime();
+ virtual void threadLoop_write();
+ virtual void threadLoop_standby();
+ virtual void cacheParameters_l();
+
+ private:
+ // called from threadLoop, addOutputTrack, removeOutputTrack
+ virtual void updateWaitTime_l();
+ protected:
+ virtual void saveOutputTracks();
+ virtual void clearOutputTracks();
+ private:
+
+ uint32_t mWaitTimeMs;
+ SortedVector < sp<OutputTrack> > outputTracks;
+ SortedVector < sp<OutputTrack> > mOutputTracks;
+ };
+
+ PlaybackThread *checkPlaybackThread_l(audio_io_handle_t output) const;
+ MixerThread *checkMixerThread_l(audio_io_handle_t output) const;
+ RecordThread *checkRecordThread_l(audio_io_handle_t input) const;
+ // no range check, AudioFlinger::mLock held
+ bool streamMute_l(audio_stream_type_t stream) const
+ { return mStreamTypes[stream].mute; }
+ // no range check, doesn't check per-thread stream volume, AudioFlinger::mLock held
+ float streamVolume_l(audio_stream_type_t stream) const
+ { return mStreamTypes[stream].volume; }
+ void audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2);
+
+ // allocate an audio_io_handle_t, session ID, or effect ID
+ uint32_t nextUniqueId();
+
+ status_t moveEffectChain_l(int sessionId,
+ PlaybackThread *srcThread,
+ PlaybackThread *dstThread,
+ bool reRegister);
+ // return thread associated with primary hardware device, or NULL
+ PlaybackThread *primaryPlaybackThread_l() const;
+ uint32_t primaryOutputDevice_l() const;
+
+ // server side of the client's IAudioTrack
+ class TrackHandle : public android::BnAudioTrack {
+ public:
+ TrackHandle(const sp<PlaybackThread::Track>& track);
+ virtual ~TrackHandle();
+ virtual sp<IMemory> getCblk() const;
+ virtual status_t start(pid_t tid);
+ virtual void stop();
+ virtual void flush();
+ virtual void mute(bool);
+ virtual void pause();
+ virtual status_t attachAuxEffect(int effectId);
+ virtual status_t allocateTimedBuffer(size_t size,
+ sp<IMemory>* buffer);
+ virtual status_t queueTimedBuffer(const sp<IMemory>& buffer,
+ int64_t pts);
+ virtual status_t setMediaTimeTransform(const LinearTransform& xform,
+ int target);
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+ private:
+ const sp<PlaybackThread::Track> mTrack;
+ };
+
+ void removeClient_l(pid_t pid);
+ void removeNotificationClient(pid_t pid);
+
+
+ // record thread
+ class RecordThread : public ThreadBase, public AudioBufferProvider
+ {
+ public:
+
+ // record track
+ class RecordTrack : public TrackBase {
+ public:
+ RecordTrack(RecordThread *thread,
+ const sp<Client>& client,
+ uint32_t sampleRate,
+ audio_format_t format,
+ uint32_t channelMask,
+ int frameCount,
+ int sessionId);
+ virtual ~RecordTrack();
+
+ virtual status_t start(pid_t tid);
+ virtual void stop();
+
+ bool overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
+ bool setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; }
+
+ void dump(char* buffer, size_t size);
+
+ private:
+ friend class AudioFlinger; // for mState
+
+ RecordTrack(const RecordTrack&);
+ RecordTrack& operator = (const RecordTrack&);
+
+ // AudioBufferProvider interface
+ virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts = kInvalidPTS);
+ // releaseBuffer() not overridden
+
+ bool mOverflow;
+ };
+
+
+ RecordThread(const sp<AudioFlinger>& audioFlinger,
+ AudioStreamIn *input,
+ uint32_t sampleRate,
+ uint32_t channels,
+ audio_io_handle_t id,
+ uint32_t device);
+ virtual ~RecordThread();
+
+ // Thread
+ virtual bool threadLoop();
+ virtual status_t readyToRun();
+
+ // RefBase
+ virtual void onFirstRef();
+
+ virtual status_t initCheck() const { return (mInput == NULL) ? NO_INIT : NO_ERROR; }
+ sp<AudioFlinger::RecordThread::RecordTrack> createRecordTrack_l(
+ const sp<AudioFlinger::Client>& client,
+ uint32_t sampleRate,
+ audio_format_t format,
+ int channelMask,
+ int frameCount,
+ int sessionId,
+ status_t *status);
+
+ status_t start(RecordTrack* recordTrack);
+ status_t start(RecordTrack* recordTrack, pid_t tid);
+ void stop(RecordTrack* recordTrack);
+ status_t dump(int fd, const Vector<String16>& args);
+ AudioStreamIn* getInput() const;
+ AudioStreamIn* clearInput();
+ virtual audio_stream_t* stream();
+
+ // AudioBufferProvider interface
+ virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts);
+ virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+
+ virtual bool checkForNewParameters_l();
+ virtual String8 getParameters(const String8& keys);
+ virtual void audioConfigChanged_l(int event, int param = 0);
+ void readInputParameters();
+ virtual unsigned int getInputFramesLost();
+
+ virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
+ virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
+ virtual uint32_t hasAudioSession(int sessionId);
+ RecordTrack* track();
+
+ private:
+ RecordThread();
+ AudioStreamIn *mInput;
+ RecordTrack* mTrack;
+ sp<RecordTrack> mActiveTrack;
+ Condition mStartStopCond;
+ AudioResampler *mResampler;
+ int32_t *mRsmpOutBuffer;
+ int16_t *mRsmpInBuffer;
+ size_t mRsmpInIndex;
+ size_t mInputBytes;
+ const int mReqChannelCount;
+ const uint32_t mReqSampleRate;
+ ssize_t mBytesRead;
+ };
+
+ // server side of the client's IAudioRecord
+ class RecordHandle : public android::BnAudioRecord {
+ public:
+ RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack);
+ virtual ~RecordHandle();
+ virtual sp<IMemory> getCblk() const;
+ virtual status_t start(pid_t tid);
+ virtual void stop();
+ virtual status_t onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+ private:
+ const sp<RecordThread::RecordTrack> mRecordTrack;
+ };
+
+ //--- Audio Effect Management
+
+ // EffectModule and EffectChain classes both have their own mutex to protect
+ // state changes or resource modifications. Always respect the following order
+ // if multiple mutexes must be acquired to avoid cross deadlock:
+ // AudioFlinger -> ThreadBase -> EffectChain -> EffectModule
+
+ // The EffectModule class is a wrapper object controlling the effect engine implementation
+ // in the effect library. It prevents concurrent calls to process() and command() functions
+ // from different client threads. It keeps a list of EffectHandle objects corresponding
+ // to all client applications using this effect and notifies applications of effect state,
+ // control or parameter changes. It manages the activation state machine to send appropriate
+ // reset, enable, disable commands to effect engine and provide volume
+ // ramping when effects are activated/deactivated.
+ // When controlling an auxiliary effect, the EffectModule also provides an input buffer used by
+ // the attached track(s) to accumulate their auxiliary channel.
+ class EffectModule: public RefBase {
+ public:
+ EffectModule(ThreadBase *thread,
+ const wp<AudioFlinger::EffectChain>& chain,
+ effect_descriptor_t *desc,
+ int id,
+ int sessionId);
+ virtual ~EffectModule();
+
+ enum effect_state {
+ IDLE,
+ RESTART,
+ STARTING,
+ ACTIVE,
+ STOPPING,
+ STOPPED,
+ DESTROYED
+ };
+
+ int id() const { return mId; }
+ void process();
+ void updateState();
+ status_t command(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData);
+
+ void reset_l();
+ status_t configure();
+ status_t init();
+ effect_state state() const {
+ return mState;
+ }
+ uint32_t status() {
+ return mStatus;
+ }
+ int sessionId() const {
+ return mSessionId;
+ }
+ status_t setEnabled(bool enabled);
+ bool isEnabled() const;
+ bool isProcessEnabled() const;
+
+ void setInBuffer(int16_t *buffer) { mConfig.inputCfg.buffer.s16 = buffer; }
+ int16_t *inBuffer() { return mConfig.inputCfg.buffer.s16; }
+ void setOutBuffer(int16_t *buffer) { mConfig.outputCfg.buffer.s16 = buffer; }
+ int16_t *outBuffer() { return mConfig.outputCfg.buffer.s16; }
+ void setChain(const wp<EffectChain>& chain) { mChain = chain; }
+ void setThread(const wp<ThreadBase>& thread) { mThread = thread; }
+ const wp<ThreadBase>& thread() { return mThread; }
+
+ status_t addHandle(const sp<EffectHandle>& handle);
+ void disconnect(const wp<EffectHandle>& handle, bool unpinIfLast);
+ size_t removeHandle (const wp<EffectHandle>& handle);
+
+ effect_descriptor_t& desc() { return mDescriptor; }
+ wp<EffectChain>& chain() { return mChain; }
+
+ status_t setDevice(uint32_t device);
+ status_t setVolume(uint32_t *left, uint32_t *right, bool controller);
+ status_t setMode(audio_mode_t mode);
+ status_t start();
+ status_t stop();
+ void setSuspended(bool suspended);
+ bool suspended() const;
+
+ sp<EffectHandle> controlHandle();
+
+ bool isPinned() const { return mPinned; }
+ void unPin() { mPinned = false; }
+
+ status_t dump(int fd, const Vector<String16>& args);
+
+ protected:
+ friend class AudioFlinger; // for mHandles
+ bool mPinned;
+
+ // Maximum time allocated to effect engines to complete the turn off sequence
+ static const uint32_t MAX_DISABLE_TIME_MS = 10000;
+
+ EffectModule(const EffectModule&);
+ EffectModule& operator = (const EffectModule&);
+
+ status_t start_l();
+ status_t stop_l();
+
+mutable Mutex mLock; // mutex for process, commands and handles list protection
+ wp<ThreadBase> mThread; // parent thread
+ wp<EffectChain> mChain; // parent effect chain
+ int mId; // this instance unique ID
+ int mSessionId; // audio session ID
+ effect_descriptor_t mDescriptor;// effect descriptor received from effect engine
+ effect_config_t mConfig; // input and output audio configuration
+ effect_handle_t mEffectInterface; // Effect module C API
+ status_t mStatus; // initialization status
+ effect_state mState; // current activation state
+ Vector< wp<EffectHandle> > mHandles; // list of client handles
+ // First handle in mHandles has highest priority and controls the effect module
+ uint32_t mMaxDisableWaitCnt; // maximum grace period before forcing an effect off after
+ // sending disable command.
+ uint32_t mDisableWaitCnt; // current process() calls count during disable period.
+ bool mSuspended; // effect is suspended: temporarily disabled by framework
+ };
+
+ // The EffectHandle class implements the IEffect interface. It provides resources
+ // to receive parameter updates, keeps track of effect control
+ // ownership and state and has a pointer to the EffectModule object it is controlling.
+ // There is one EffectHandle object for each application controlling (or using)
+ // an effect module.
+ // The EffectHandle is obtained by calling AudioFlinger::createEffect().
+ class EffectHandle: public android::BnEffect {
+ public:
+
+ EffectHandle(const sp<EffectModule>& effect,
+ const sp<AudioFlinger::Client>& client,
+ const sp<IEffectClient>& effectClient,
+ int32_t priority);
+ virtual ~EffectHandle();
+
+ // IEffect
+ virtual status_t enable();
+ virtual status_t disable();
+ virtual status_t command(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData);
+ virtual void disconnect();
+ private:
+ void disconnect(bool unpinIfLast);
+ public:
+ virtual sp<IMemory> getCblk() const { return mCblkMemory; }
+ virtual status_t onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags);
+
+
+ // Give or take control of effect module
+ // - hasControl: true if control is given, false if removed
+ // - signal: true client app should be signaled of change, false otherwise
+ // - enabled: state of the effect when control is passed
+ void setControl(bool hasControl, bool signal, bool enabled);
+ void commandExecuted(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t replySize,
+ void *pReplyData);
+ void setEnabled(bool enabled);
+ bool enabled() const { return mEnabled; }
+
+ // Getters
+ int id() const { return mEffect->id(); }
+ int priority() const { return mPriority; }
+ bool hasControl() const { return mHasControl; }
+ sp<EffectModule> effect() const { return mEffect; }
+
+ void dump(char* buffer, size_t size);
+
+ protected:
+ friend class AudioFlinger; // for mEffect, mHasControl, mEnabled
+ EffectHandle(const EffectHandle&);
+ EffectHandle& operator =(const EffectHandle&);
+
+ sp<EffectModule> mEffect; // pointer to controlled EffectModule
+ sp<IEffectClient> mEffectClient; // callback interface for client notifications
+ /*const*/ sp<Client> mClient; // client for shared memory allocation, see disconnect()
+ sp<IMemory> mCblkMemory; // shared memory for control block
+ effect_param_cblk_t* mCblk; // control block for deferred parameter setting via shared memory
+ uint8_t* mBuffer; // pointer to parameter area in shared memory
+ int mPriority; // client application priority to control the effect
+ bool mHasControl; // true if this handle is controlling the effect
+ bool mEnabled; // cached enable state: needed when the effect is
+ // restored after being suspended
+ };
+
+ // the EffectChain class represents a group of effects associated to one audio session.
+ // There can be any number of EffectChain objects per output mixer thread (PlaybackThread).
+ // The EffecChain with session ID 0 contains global effects applied to the output mix.
+ // Effects in this chain can be insert or auxiliary. Effects in other chains (attached to tracks)
+ // are insert only. The EffectChain maintains an ordered list of effect module, the order corresponding
+ // in the effect process order. When attached to a track (session ID != 0), it also provide it's own
+ // input buffer used by the track as accumulation buffer.
+ class EffectChain: public RefBase {
+ public:
+ EffectChain(const wp<ThreadBase>& wThread, int sessionId);
+ EffectChain(ThreadBase *thread, int sessionId);
+ virtual ~EffectChain();
+
+ // special key used for an entry in mSuspendedEffects keyed vector
+ // corresponding to a suspend all request.
+ static const int kKeyForSuspendAll = 0;
+
+ // minimum duration during which we force calling effect process when last track on
+ // a session is stopped or removed to allow effect tail to be rendered
+ static const int kProcessTailDurationMs = 1000;
+
+ void process_l();
+
+ void lock() {
+ mLock.lock();
+ }
+ void unlock() {
+ mLock.unlock();
+ }
+
+ status_t addEffect_l(const sp<EffectModule>& handle);
+ size_t removeEffect_l(const sp<EffectModule>& handle);
+
+ int sessionId() const { return mSessionId; }
+ void setSessionId(int sessionId) { mSessionId = sessionId; }
+
+ sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor);
+ sp<EffectModule> getEffectFromId_l(int id);
+ sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type);
+ bool setVolume_l(uint32_t *left, uint32_t *right);
+ void setDevice_l(uint32_t device);
+ void setMode_l(audio_mode_t mode);
+
+ void setInBuffer(int16_t *buffer, bool ownsBuffer = false) {
+ mInBuffer = buffer;
+ mOwnInBuffer = ownsBuffer;
+ }
+ int16_t *inBuffer() const {
+ return mInBuffer;
+ }
+ void setOutBuffer(int16_t *buffer) {
+ mOutBuffer = buffer;
+ }
+ int16_t *outBuffer() const {
+ return mOutBuffer;
+ }
+
+ void incTrackCnt() { android_atomic_inc(&mTrackCnt); }
+ void decTrackCnt() { android_atomic_dec(&mTrackCnt); }
+ int32_t trackCnt() const { return mTrackCnt;}
+
+ void incActiveTrackCnt() { android_atomic_inc(&mActiveTrackCnt);
+ mTailBufferCount = mMaxTailBuffers; }
+ void decActiveTrackCnt() { android_atomic_dec(&mActiveTrackCnt); }
+ int32_t activeTrackCnt() const { return mActiveTrackCnt;}
+
+ uint32_t strategy() const { return mStrategy; }
+ void setStrategy(uint32_t strategy)
+ { mStrategy = strategy; }
+
+ // suspend effect of the given type
+ void setEffectSuspended_l(const effect_uuid_t *type,
+ bool suspend);
+ // suspend all eligible effects
+ void setEffectSuspendedAll_l(bool suspend);
+ // check if effects should be suspend or restored when a given effect is enable or disabled
+ void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
+ bool enabled);
+
+ status_t dump(int fd, const Vector<String16>& args);
+
+ protected:
+ friend class AudioFlinger; // for mThread, mEffects
+ EffectChain(const EffectChain&);
+ EffectChain& operator =(const EffectChain&);
+
+ class SuspendedEffectDesc : public RefBase {
+ public:
+ SuspendedEffectDesc() : mRefCount(0) {}
+
+ int mRefCount;
+ effect_uuid_t mType;
+ wp<EffectModule> mEffect;
+ };
+
+ // get a list of effect modules to suspend when an effect of the type
+ // passed is enabled.
+ void getSuspendEligibleEffects(Vector< sp<EffectModule> > &effects);
+
+ // get an effect module if it is currently enable
+ sp<EffectModule> getEffectIfEnabled(const effect_uuid_t *type);
+ // true if the effect whose descriptor is passed can be suspended
+ // OEMs can modify the rules implemented in this method to exclude specific effect
+ // types or implementations from the suspend/restore mechanism.
+ bool isEffectEligibleForSuspend(const effect_descriptor_t& desc);
+
+ wp<ThreadBase> mThread; // parent mixer thread
+ Mutex mLock; // mutex protecting effect list
+ Vector< sp<EffectModule> > mEffects; // list of effect modules
+ int mSessionId; // audio session ID
+ int16_t *mInBuffer; // chain input buffer
+ int16_t *mOutBuffer; // chain output buffer
+ volatile int32_t mActiveTrackCnt; // number of active tracks connected
+ volatile int32_t mTrackCnt; // number of tracks connected
+ int32_t mTailBufferCount; // current effect tail buffer count
+ int32_t mMaxTailBuffers; // maximum effect tail buffers
+ bool mOwnInBuffer; // true if the chain owns its input buffer
+ int mVolumeCtrlIdx; // index of insert effect having control over volume
+ uint32_t mLeftVolume; // previous volume on left channel
+ uint32_t mRightVolume; // previous volume on right channel
+ uint32_t mNewLeftVolume; // new volume on left channel
+ uint32_t mNewRightVolume; // new volume on right channel
+ uint32_t mStrategy; // strategy for this effect chain
+ // mSuspendedEffects lists all effects currently suspended in the chain.
+ // Use effect type UUID timelow field as key. There is no real risk of identical
+ // timeLow fields among effect type UUIDs.
+ // Updated by updateSuspendedSessions_l() only.
+ KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects;
+ };
+
+ // AudioStreamOut and AudioStreamIn are immutable, so their fields are const.
+ // For emphasis, we could also make all pointers to them be "const *",
+ // but that would clutter the code unnecessarily.
+
+ struct AudioStreamOut {
+ audio_hw_device_t* const hwDev;
+ audio_stream_out_t* const stream;
+
+ AudioStreamOut(audio_hw_device_t *dev, audio_stream_out_t *out) :
+ hwDev(dev), stream(out) {}
+ };
+
+ struct AudioStreamIn {
+ audio_hw_device_t* const hwDev;
+ audio_stream_in_t* const stream;
+
+ AudioStreamIn(audio_hw_device_t *dev, audio_stream_in_t *in) :
+ hwDev(dev), stream(in) {}
+ };
+
+ // for mAudioSessionRefs only
+ struct AudioSessionRef {
+ AudioSessionRef(int sessionid, pid_t pid) :
+ mSessionid(sessionid), mPid(pid), mCnt(1) {}
+ const int mSessionid;
+ const pid_t mPid;
+ int mCnt;
+ };
+
+ enum master_volume_support {
+ // MVS_NONE:
+ // Audio HAL has no support for master volume, either setting or
+ // getting. All master volume control must be implemented in SW by the
+ // AudioFlinger mixing core.
+ MVS_NONE,
+
+ // MVS_SETONLY:
+ // Audio HAL has support for setting master volume, but not for getting
+ // master volume (original HAL design did not include a getter).
+ // AudioFlinger needs to keep track of the last set master volume in
+ // addition to needing to set an initial, default, master volume at HAL
+ // load time.
+ MVS_SETONLY,
+
+ // MVS_FULL:
+ // Audio HAL has support both for setting and getting master volume.
+ // AudioFlinger should send all set and get master volume requests
+ // directly to the HAL.
+ MVS_FULL,
+ };
+
+ mutable Mutex mLock;
+
+ DefaultKeyedVector< pid_t, wp<Client> > mClients; // see ~Client()
+
+ mutable Mutex mHardwareLock;
+
+ // These two fields are immutable after onFirstRef(), so no lock needed to access
+ audio_hw_device_t* mPrimaryHardwareDev; // mAudioHwDevs[0] or NULL
+ Vector<audio_hw_device_t*> mAudioHwDevs;
+
+ // for dump, indicates which hardware operation is currently in progress (but not stream ops)
+ enum hardware_call_state {
+ AUDIO_HW_IDLE = 0, // no operation in progress
+ AUDIO_HW_INIT, // init_check
+ AUDIO_HW_OUTPUT_OPEN, // open_output_stream
+ AUDIO_HW_OUTPUT_CLOSE, // unused
+ AUDIO_HW_INPUT_OPEN, // unused
+ AUDIO_HW_INPUT_CLOSE, // unused
+ AUDIO_HW_STANDBY, // unused
+ AUDIO_HW_SET_MASTER_VOLUME, // set_master_volume
+ AUDIO_HW_GET_ROUTING, // unused
+ AUDIO_HW_SET_ROUTING, // unused
+ AUDIO_HW_GET_MODE, // unused
+ AUDIO_HW_SET_MODE, // set_mode
+ AUDIO_HW_GET_MIC_MUTE, // get_mic_mute
+ AUDIO_HW_SET_MIC_MUTE, // set_mic_mute
+ AUDIO_HW_SET_VOICE_VOLUME, // set_voice_volume
+ AUDIO_HW_SET_PARAMETER, // set_parameters
+ AUDIO_HW_GET_INPUT_BUFFER_SIZE, // get_input_buffer_size
+ AUDIO_HW_GET_MASTER_VOLUME, // get_master_volume
+ AUDIO_HW_GET_PARAMETER, // get_parameters
+ };
+
+ mutable hardware_call_state mHardwareStatus; // for dump only
+
+
+ DefaultKeyedVector< audio_io_handle_t, sp<PlaybackThread> > mPlaybackThreads;
+ stream_type_t mStreamTypes[AUDIO_STREAM_CNT];
+
+ // both are protected by mLock
+ float mMasterVolume;
+ float mMasterVolumeSW;
+ master_volume_support mMasterVolumeSupportLvl;
+ bool mMasterMute;
+
+ DefaultKeyedVector< audio_io_handle_t, sp<RecordThread> > mRecordThreads;
+
+ DefaultKeyedVector< pid_t, sp<NotificationClient> > mNotificationClients;
+ volatile int32_t mNextUniqueId; // updated by android_atomic_inc
+ audio_mode_t mMode;
+ bool mBtNrecIsOff;
+
+ // protected by mLock
+ Vector<AudioSessionRef*> mAudioSessionRefs;
+
+ float masterVolume_l() const;
+ float masterVolumeSW_l() const { return mMasterVolumeSW; }
+ bool masterMute_l() const { return mMasterMute; }
+
+private:
+ sp<Client> registerPid_l(pid_t pid); // always returns non-0
+
+};
+
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_AUDIO_FLINGER_H
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
new file mode 100644
index 0000000..3f4c19a
--- /dev/null
+++ b/services/audioflinger/AudioMixer.cpp
@@ -0,0 +1,1155 @@
+/*
+**
+** 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_TAG "AudioMixer"
+//#define LOG_NDEBUG 0
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include <cutils/bitops.h>
+#include <cutils/compiler.h>
+#include <utils/Debug.h>
+
+#include <system/audio.h>
+
+#include <audio_utils/primitives.h>
+#include <common_time/local_clock.h>
+#include <common_time/cc_helper.h>
+
+#include "AudioMixer.h"
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate, uint32_t maxNumTracks)
+ : mTrackNames(0), mConfiguredNames((1 << maxNumTracks) - 1), mSampleRate(sampleRate)
+{
+ // AudioMixer is not yet capable of multi-channel beyond stereo
+ COMPILE_TIME_ASSERT_FUNCTION_SCOPE(2 == MAX_NUM_CHANNELS);
+
+ ALOG_ASSERT(maxNumTracks <= MAX_NUM_TRACKS, "maxNumTracks %u > MAX_NUM_TRACKS %u",
+ maxNumTracks, MAX_NUM_TRACKS);
+
+ LocalClock lc;
+
+ mState.enabledTracks= 0;
+ mState.needsChanged = 0;
+ mState.frameCount = frameCount;
+ mState.hook = process__nop;
+ mState.outputTemp = NULL;
+ mState.resampleTemp = NULL;
+ // mState.reserved
+
+ // FIXME Most of the following initialization is probably redundant since
+ // tracks[i] should only be referenced if (mTrackNames & (1 << i)) != 0
+ // and mTrackNames is initially 0. However, leave it here until that's verified.
+ track_t* t = mState.tracks;
+ for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
+ t->needs = 0;
+ t->volume[0] = UNITY_GAIN;
+ t->volume[1] = UNITY_GAIN;
+ // no initialization needed
+ // t->prevVolume[0]
+ // t->prevVolume[1]
+ t->volumeInc[0] = 0;
+ t->volumeInc[1] = 0;
+ t->auxLevel = 0;
+ t->auxInc = 0;
+ // no initialization needed
+ // t->prevAuxLevel
+ // t->frameCount
+ t->channelCount = 2;
+ t->enabled = false;
+ t->format = 16;
+ t->channelMask = AUDIO_CHANNEL_OUT_STEREO;
+ t->bufferProvider = NULL;
+ t->buffer.raw = NULL;
+ // t->buffer.frameCount
+ t->hook = NULL;
+ t->in = NULL;
+ t->resampler = NULL;
+ t->sampleRate = mSampleRate;
+ t->mainBuffer = NULL;
+ t->auxBuffer = NULL;
+ t->localTimeFreq = lc.getLocalFreq();
+ t++;
+ }
+}
+
+AudioMixer::~AudioMixer()
+{
+ track_t* t = mState.tracks;
+ for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
+ delete t->resampler;
+ t++;
+ }
+ delete [] mState.outputTemp;
+ delete [] mState.resampleTemp;
+}
+
+int AudioMixer::getTrackName()
+{
+ uint32_t names = (~mTrackNames) & mConfiguredNames;
+ if (names != 0) {
+ int n = __builtin_ctz(names);
+ ALOGV("add track (%d)", n);
+ mTrackNames |= 1 << n;
+ return TRACK0 + n;
+ }
+ return -1;
+}
+
+void AudioMixer::invalidateState(uint32_t mask)
+{
+ if (mask) {
+ mState.needsChanged |= mask;
+ mState.hook = process__validate;
+ }
+ }
+
+void AudioMixer::deleteTrackName(int name)
+{
+ name -= TRACK0;
+ ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
+ ALOGV("deleteTrackName(%d)", name);
+ track_t& track(mState.tracks[ name ]);
+ if (track.enabled) {
+ track.enabled = false;
+ invalidateState(1<<name);
+ }
+ if (track.resampler != NULL) {
+ // delete the resampler
+ delete track.resampler;
+ track.resampler = NULL;
+ track.sampleRate = mSampleRate;
+ invalidateState(1<<name);
+ }
+ track.volumeInc[0] = 0;
+ track.volumeInc[1] = 0;
+ mTrackNames &= ~(1<<name);
+}
+
+void AudioMixer::enable(int name)
+{
+ name -= TRACK0;
+ ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
+ track_t& track = mState.tracks[name];
+
+ if (!track.enabled) {
+ track.enabled = true;
+ ALOGV("enable(%d)", name);
+ invalidateState(1 << name);
+ }
+}
+
+void AudioMixer::disable(int name)
+{
+ name -= TRACK0;
+ ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
+ track_t& track = mState.tracks[name];
+
+ if (track.enabled) {
+ track.enabled = false;
+ ALOGV("disable(%d)", name);
+ invalidateState(1 << name);
+ }
+}
+
+void AudioMixer::setParameter(int name, int target, int param, void *value)
+{
+ name -= TRACK0;
+ ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
+ track_t& track = mState.tracks[name];
+
+ int valueInt = (int)value;
+ int32_t *valueBuf = (int32_t *)value;
+
+ switch (target) {
+
+ case TRACK:
+ switch (param) {
+ case CHANNEL_MASK: {
+ uint32_t mask = (uint32_t)value;
+ if (track.channelMask != mask) {
+ uint32_t channelCount = popcount(mask);
+ ALOG_ASSERT((channelCount <= MAX_NUM_CHANNELS) && (channelCount),
+ "bad channel count %u", channelCount);
+ track.channelMask = mask;
+ track.channelCount = channelCount;
+ ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
+ invalidateState(1 << name);
+ }
+ } break;
+ case MAIN_BUFFER:
+ if (track.mainBuffer != valueBuf) {
+ track.mainBuffer = valueBuf;
+ ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
+ invalidateState(1 << name);
+ }
+ break;
+ case AUX_BUFFER:
+ if (track.auxBuffer != valueBuf) {
+ track.auxBuffer = valueBuf;
+ ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
+ invalidateState(1 << name);
+ }
+ break;
+ default:
+ LOG_FATAL("bad param");
+ }
+ break;
+
+ case RESAMPLE:
+ switch (param) {
+ case SAMPLE_RATE:
+ ALOG_ASSERT(valueInt > 0, "bad sample rate %d", valueInt);
+ if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
+ ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
+ uint32_t(valueInt));
+ invalidateState(1 << name);
+ }
+ break;
+ case RESET:
+ track.resetResampler();
+ invalidateState(1 << name);
+ break;
+ default:
+ LOG_FATAL("bad param");
+ }
+ break;
+
+ case RAMP_VOLUME:
+ case VOLUME:
+ switch (param) {
+ case VOLUME0:
+ case VOLUME1:
+ if (track.volume[param-VOLUME0] != valueInt) {
+ ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
+ track.prevVolume[param-VOLUME0] = track.volume[param-VOLUME0] << 16;
+ track.volume[param-VOLUME0] = valueInt;
+ if (target == VOLUME) {
+ track.prevVolume[param-VOLUME0] = valueInt << 16;
+ track.volumeInc[param-VOLUME0] = 0;
+ } else {
+ int32_t d = (valueInt<<16) - track.prevVolume[param-VOLUME0];
+ int32_t volInc = d / int32_t(mState.frameCount);
+ track.volumeInc[param-VOLUME0] = volInc;
+ if (volInc == 0) {
+ track.prevVolume[param-VOLUME0] = valueInt << 16;
+ }
+ }
+ invalidateState(1 << name);
+ }
+ break;
+ case AUXLEVEL:
+ //ALOG_ASSERT(0 <= valueInt && valueInt <= MAX_GAIN_INT, "bad aux level %d", valueInt);
+ if (track.auxLevel != valueInt) {
+ ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
+ track.prevAuxLevel = track.auxLevel << 16;
+ track.auxLevel = valueInt;
+ if (target == VOLUME) {
+ track.prevAuxLevel = valueInt << 16;
+ track.auxInc = 0;
+ } else {
+ int32_t d = (valueInt<<16) - track.prevAuxLevel;
+ int32_t volInc = d / int32_t(mState.frameCount);
+ track.auxInc = volInc;
+ if (volInc == 0) {
+ track.prevAuxLevel = valueInt << 16;
+ }
+ }
+ invalidateState(1 << name);
+ }
+ break;
+ default:
+ LOG_FATAL("bad param");
+ }
+ break;
+
+ default:
+ LOG_FATAL("bad target");
+ }
+}
+
+bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
+{
+ if (value!=devSampleRate || resampler) {
+ if (sampleRate != value) {
+ sampleRate = value;
+ if (resampler == NULL) {
+ resampler = AudioResampler::create(
+ format, channelCount, devSampleRate);
+ resampler->setLocalTimeFreq(localTimeFreq);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+inline
+void AudioMixer::track_t::adjustVolumeRamp(bool aux)
+{
+ for (uint32_t i=0 ; i<MAX_NUM_CHANNELS ; i++) {
+ if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
+ ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
+ volumeInc[i] = 0;
+ prevVolume[i] = volume[i]<<16;
+ }
+ }
+ if (aux) {
+ if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
+ ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
+ auxInc = 0;
+ prevAuxLevel = auxLevel<<16;
+ }
+ }
+}
+
+size_t AudioMixer::getUnreleasedFrames(int name) const
+{
+ name -= TRACK0;
+ if (uint32_t(name) < MAX_NUM_TRACKS) {
+ return mState.tracks[name].getUnreleasedFrames();
+ }
+ return 0;
+}
+
+void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider)
+{
+ name -= TRACK0;
+ ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
+ mState.tracks[name].bufferProvider = bufferProvider;
+}
+
+
+
+void AudioMixer::process(int64_t pts)
+{
+ mState.hook(&mState, pts);
+}
+
+
+void AudioMixer::process__validate(state_t* state, int64_t pts)
+{
+ ALOGW_IF(!state->needsChanged,
+ "in process__validate() but nothing's invalid");
+
+ uint32_t changed = state->needsChanged;
+ state->needsChanged = 0; // clear the validation flag
+
+ // recompute which tracks are enabled / disabled
+ uint32_t enabled = 0;
+ uint32_t disabled = 0;
+ while (changed) {
+ const int i = 31 - __builtin_clz(changed);
+ const uint32_t mask = 1<<i;
+ changed &= ~mask;
+ track_t& t = state->tracks[i];
+ (t.enabled ? enabled : disabled) |= mask;
+ }
+ state->enabledTracks &= ~disabled;
+ state->enabledTracks |= enabled;
+
+ // compute everything we need...
+ int countActiveTracks = 0;
+ bool all16BitsStereoNoResample = true;
+ bool resampling = false;
+ bool volumeRamp = false;
+ uint32_t en = state->enabledTracks;
+ while (en) {
+ const int i = 31 - __builtin_clz(en);
+ en &= ~(1<<i);
+
+ countActiveTracks++;
+ track_t& t = state->tracks[i];
+ uint32_t n = 0;
+ n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
+ n |= NEEDS_FORMAT_16;
+ n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
+ if (t.auxLevel != 0 && t.auxBuffer != NULL) {
+ n |= NEEDS_AUX_ENABLED;
+ }
+
+ if (t.volumeInc[0]|t.volumeInc[1]) {
+ volumeRamp = true;
+ } else if (!t.doesResample() && t.volumeRL == 0) {
+ n |= NEEDS_MUTE_ENABLED;
+ }
+ t.needs = n;
+
+ if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
+ t.hook = track__nop;
+ } else {
+ if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
+ all16BitsStereoNoResample = false;
+ }
+ if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
+ all16BitsStereoNoResample = false;
+ resampling = true;
+ t.hook = track__genericResample;
+ } else {
+ if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
+ t.hook = track__16BitsMono;
+ all16BitsStereoNoResample = false;
+ }
+ if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
+ t.hook = track__16BitsStereo;
+ }
+ }
+ }
+ }
+
+ // select the processing hooks
+ state->hook = process__nop;
+ if (countActiveTracks) {
+ if (resampling) {
+ if (!state->outputTemp) {
+ state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
+ }
+ if (!state->resampleTemp) {
+ state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
+ }
+ state->hook = process__genericResampling;
+ } else {
+ if (state->outputTemp) {
+ delete [] state->outputTemp;
+ state->outputTemp = NULL;
+ }
+ if (state->resampleTemp) {
+ delete [] state->resampleTemp;
+ state->resampleTemp = NULL;
+ }
+ state->hook = process__genericNoResampling;
+ if (all16BitsStereoNoResample && !volumeRamp) {
+ if (countActiveTracks == 1) {
+ state->hook = process__OneTrack16BitsStereoNoResampling;
+ }
+ }
+ }
+ }
+
+ ALOGV("mixer configuration change: %d activeTracks (%08x) "
+ "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
+ countActiveTracks, state->enabledTracks,
+ all16BitsStereoNoResample, resampling, volumeRamp);
+
+ state->hook(state, pts);
+
+ // Now that the volume ramp has been done, set optimal state and
+ // track hooks for subsequent mixer process
+ if (countActiveTracks) {
+ bool allMuted = true;
+ uint32_t en = state->enabledTracks;
+ while (en) {
+ const int i = 31 - __builtin_clz(en);
+ en &= ~(1<<i);
+ track_t& t = state->tracks[i];
+ if (!t.doesResample() && t.volumeRL == 0)
+ {
+ t.needs |= NEEDS_MUTE_ENABLED;
+ t.hook = track__nop;
+ } else {
+ allMuted = false;
+ }
+ }
+ if (allMuted) {
+ state->hook = process__nop;
+ } else if (all16BitsStereoNoResample) {
+ if (countActiveTracks == 1) {
+ state->hook = process__OneTrack16BitsStereoNoResampling;
+ }
+ }
+ }
+}
+
+
+void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
+{
+ t->resampler->setSampleRate(t->sampleRate);
+
+ // ramp gain - resample to temp buffer and scale/mix in 2nd step
+ if (aux != NULL) {
+ // always resample with unity gain when sending to auxiliary buffer to be able
+ // to apply send level after resampling
+ // TODO: modify each resampler to support aux channel?
+ t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
+ memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
+ t->resampler->resample(temp, outFrameCount, t->bufferProvider);
+ if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
+ volumeRampStereo(t, out, outFrameCount, temp, aux);
+ } else {
+ volumeStereo(t, out, outFrameCount, temp, aux);
+ }
+ } else {
+ if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
+ t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
+ memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
+ t->resampler->resample(temp, outFrameCount, t->bufferProvider);
+ volumeRampStereo(t, out, outFrameCount, temp, aux);
+ }
+
+ // constant gain
+ else {
+ t->resampler->setVolume(t->volume[0], t->volume[1]);
+ t->resampler->resample(out, outFrameCount, t->bufferProvider);
+ }
+ }
+}
+
+void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
+{
+}
+
+void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
+{
+ int32_t vl = t->prevVolume[0];
+ int32_t vr = t->prevVolume[1];
+ const int32_t vlInc = t->volumeInc[0];
+ const int32_t vrInc = t->volumeInc[1];
+
+ //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+ // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
+ // (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+ // ramp volume
+ if (CC_UNLIKELY(aux != NULL)) {
+ int32_t va = t->prevAuxLevel;
+ const int32_t vaInc = t->auxInc;
+ int32_t l;
+ int32_t r;
+
+ do {
+ l = (*temp++ >> 12);
+ r = (*temp++ >> 12);
+ *out++ += (vl >> 16) * l;
+ *out++ += (vr >> 16) * r;
+ *aux++ += (va >> 17) * (l + r);
+ vl += vlInc;
+ vr += vrInc;
+ va += vaInc;
+ } while (--frameCount);
+ t->prevAuxLevel = va;
+ } else {
+ do {
+ *out++ += (vl >> 16) * (*temp++ >> 12);
+ *out++ += (vr >> 16) * (*temp++ >> 12);
+ vl += vlInc;
+ vr += vrInc;
+ } while (--frameCount);
+ }
+ t->prevVolume[0] = vl;
+ t->prevVolume[1] = vr;
+ t->adjustVolumeRamp(aux != NULL);
+}
+
+void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
+{
+ const int16_t vl = t->volume[0];
+ const int16_t vr = t->volume[1];
+
+ if (CC_UNLIKELY(aux != NULL)) {
+ const int16_t va = t->auxLevel;
+ do {
+ int16_t l = (int16_t)(*temp++ >> 12);
+ int16_t r = (int16_t)(*temp++ >> 12);
+ out[0] = mulAdd(l, vl, out[0]);
+ int16_t a = (int16_t)(((int32_t)l + r) >> 1);
+ out[1] = mulAdd(r, vr, out[1]);
+ out += 2;
+ aux[0] = mulAdd(a, va, aux[0]);
+ aux++;
+ } while (--frameCount);
+ } else {
+ do {
+ int16_t l = (int16_t)(*temp++ >> 12);
+ int16_t r = (int16_t)(*temp++ >> 12);
+ out[0] = mulAdd(l, vl, out[0]);
+ out[1] = mulAdd(r, vr, out[1]);
+ out += 2;
+ } while (--frameCount);
+ }
+}
+
+void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
+{
+ const int16_t *in = static_cast<const int16_t *>(t->in);
+
+ if (CC_UNLIKELY(aux != NULL)) {
+ int32_t l;
+ int32_t r;
+ // ramp gain
+ if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
+ int32_t vl = t->prevVolume[0];
+ int32_t vr = t->prevVolume[1];
+ int32_t va = t->prevAuxLevel;
+ const int32_t vlInc = t->volumeInc[0];
+ const int32_t vrInc = t->volumeInc[1];
+ const int32_t vaInc = t->auxInc;
+ // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+ // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
+ // (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+ do {
+ l = (int32_t)*in++;
+ r = (int32_t)*in++;
+ *out++ += (vl >> 16) * l;
+ *out++ += (vr >> 16) * r;
+ *aux++ += (va >> 17) * (l + r);
+ vl += vlInc;
+ vr += vrInc;
+ va += vaInc;
+ } while (--frameCount);
+
+ t->prevVolume[0] = vl;
+ t->prevVolume[1] = vr;
+ t->prevAuxLevel = va;
+ t->adjustVolumeRamp(true);
+ }
+
+ // constant gain
+ else {
+ const uint32_t vrl = t->volumeRL;
+ const int16_t va = (int16_t)t->auxLevel;
+ do {
+ uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+ int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
+ in += 2;
+ out[0] = mulAddRL(1, rl, vrl, out[0]);
+ out[1] = mulAddRL(0, rl, vrl, out[1]);
+ out += 2;
+ aux[0] = mulAdd(a, va, aux[0]);
+ aux++;
+ } while (--frameCount);
+ }
+ } else {
+ // ramp gain
+ if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
+ int32_t vl = t->prevVolume[0];
+ int32_t vr = t->prevVolume[1];
+ const int32_t vlInc = t->volumeInc[0];
+ const int32_t vrInc = t->volumeInc[1];
+
+ // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+ // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
+ // (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+ do {
+ *out++ += (vl >> 16) * (int32_t) *in++;
+ *out++ += (vr >> 16) * (int32_t) *in++;
+ vl += vlInc;
+ vr += vrInc;
+ } while (--frameCount);
+
+ t->prevVolume[0] = vl;
+ t->prevVolume[1] = vr;
+ t->adjustVolumeRamp(false);
+ }
+
+ // constant gain
+ else {
+ const uint32_t vrl = t->volumeRL;
+ do {
+ uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+ in += 2;
+ out[0] = mulAddRL(1, rl, vrl, out[0]);
+ out[1] = mulAddRL(0, rl, vrl, out[1]);
+ out += 2;
+ } while (--frameCount);
+ }
+ }
+ t->in = in;
+}
+
+void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
+{
+ const int16_t *in = static_cast<int16_t const *>(t->in);
+
+ if (CC_UNLIKELY(aux != NULL)) {
+ // ramp gain
+ if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
+ int32_t vl = t->prevVolume[0];
+ int32_t vr = t->prevVolume[1];
+ int32_t va = t->prevAuxLevel;
+ const int32_t vlInc = t->volumeInc[0];
+ const int32_t vrInc = t->volumeInc[1];
+ const int32_t vaInc = t->auxInc;
+
+ // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+ // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
+ // (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+ do {
+ int32_t l = *in++;
+ *out++ += (vl >> 16) * l;
+ *out++ += (vr >> 16) * l;
+ *aux++ += (va >> 16) * l;
+ vl += vlInc;
+ vr += vrInc;
+ va += vaInc;
+ } while (--frameCount);
+
+ t->prevVolume[0] = vl;
+ t->prevVolume[1] = vr;
+ t->prevAuxLevel = va;
+ t->adjustVolumeRamp(true);
+ }
+ // constant gain
+ else {
+ const int16_t vl = t->volume[0];
+ const int16_t vr = t->volume[1];
+ const int16_t va = (int16_t)t->auxLevel;
+ do {
+ int16_t l = *in++;
+ out[0] = mulAdd(l, vl, out[0]);
+ out[1] = mulAdd(l, vr, out[1]);
+ out += 2;
+ aux[0] = mulAdd(l, va, aux[0]);
+ aux++;
+ } while (--frameCount);
+ }
+ } else {
+ // ramp gain
+ if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
+ int32_t vl = t->prevVolume[0];
+ int32_t vr = t->prevVolume[1];
+ const int32_t vlInc = t->volumeInc[0];
+ const int32_t vrInc = t->volumeInc[1];
+
+ // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+ // t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
+ // (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+ do {
+ int32_t l = *in++;
+ *out++ += (vl >> 16) * l;
+ *out++ += (vr >> 16) * l;
+ vl += vlInc;
+ vr += vrInc;
+ } while (--frameCount);
+
+ t->prevVolume[0] = vl;
+ t->prevVolume[1] = vr;
+ t->adjustVolumeRamp(false);
+ }
+ // constant gain
+ else {
+ const int16_t vl = t->volume[0];
+ const int16_t vr = t->volume[1];
+ do {
+ int16_t l = *in++;
+ out[0] = mulAdd(l, vl, out[0]);
+ out[1] = mulAdd(l, vr, out[1]);
+ out += 2;
+ } while (--frameCount);
+ }
+ }
+ t->in = in;
+}
+
+// no-op case
+void AudioMixer::process__nop(state_t* state, int64_t pts)
+{
+ uint32_t e0 = state->enabledTracks;
+ size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
+ while (e0) {
+ // process by group of tracks with same output buffer to
+ // avoid multiple memset() on same buffer
+ uint32_t e1 = e0, e2 = e0;
+ int i = 31 - __builtin_clz(e1);
+ track_t& t1 = state->tracks[i];
+ e2 &= ~(1<<i);
+ while (e2) {
+ i = 31 - __builtin_clz(e2);
+ e2 &= ~(1<<i);
+ track_t& t2 = state->tracks[i];
+ if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
+ e1 &= ~(1<<i);
+ }
+ }
+ e0 &= ~(e1);
+
+ memset(t1.mainBuffer, 0, bufSize);
+
+ while (e1) {
+ i = 31 - __builtin_clz(e1);
+ e1 &= ~(1<<i);
+ t1 = state->tracks[i];
+ size_t outFrames = state->frameCount;
+ while (outFrames) {
+ t1.buffer.frameCount = outFrames;
+ int64_t outputPTS = calculateOutputPTS(
+ t1, pts, state->frameCount - outFrames);
+ t1.bufferProvider->getNextBuffer(&t1.buffer, outputPTS);
+ if (t1.buffer.raw == NULL) break;
+ outFrames -= t1.buffer.frameCount;
+ t1.bufferProvider->releaseBuffer(&t1.buffer);
+ }
+ }
+ }
+}
+
+// generic code without resampling
+void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts)
+{
+ int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
+
+ // acquire each track's buffer
+ uint32_t enabledTracks = state->enabledTracks;
+ uint32_t e0 = enabledTracks;
+ while (e0) {
+ const int i = 31 - __builtin_clz(e0);
+ e0 &= ~(1<<i);
+ track_t& t = state->tracks[i];
+ t.buffer.frameCount = state->frameCount;
+ t.bufferProvider->getNextBuffer(&t.buffer, pts);
+ t.frameCount = t.buffer.frameCount;
+ t.in = t.buffer.raw;
+ // t.in == NULL can happen if the track was flushed just after having
+ // been enabled for mixing.
+ if (t.in == NULL)
+ enabledTracks &= ~(1<<i);
+ }
+
+ e0 = enabledTracks;
+ while (e0) {
+ // process by group of tracks with same output buffer to
+ // optimize cache use
+ uint32_t e1 = e0, e2 = e0;
+ int j = 31 - __builtin_clz(e1);
+ track_t& t1 = state->tracks[j];
+ e2 &= ~(1<<j);
+ while (e2) {
+ j = 31 - __builtin_clz(e2);
+ e2 &= ~(1<<j);
+ track_t& t2 = state->tracks[j];
+ if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
+ e1 &= ~(1<<j);
+ }
+ }
+ e0 &= ~(e1);
+ // this assumes output 16 bits stereo, no resampling
+ int32_t *out = t1.mainBuffer;
+ size_t numFrames = 0;
+ do {
+ memset(outTemp, 0, sizeof(outTemp));
+ e2 = e1;
+ while (e2) {
+ const int i = 31 - __builtin_clz(e2);
+ e2 &= ~(1<<i);
+ track_t& t = state->tracks[i];
+ size_t outFrames = BLOCKSIZE;
+ int32_t *aux = NULL;
+ if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
+ aux = t.auxBuffer + numFrames;
+ }
+ while (outFrames) {
+ size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
+ if (inFrames) {
+ t.hook(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
+ t.frameCount -= inFrames;
+ outFrames -= inFrames;
+ if (CC_UNLIKELY(aux != NULL)) {
+ aux += inFrames;
+ }
+ }
+ if (t.frameCount == 0 && outFrames) {
+ t.bufferProvider->releaseBuffer(&t.buffer);
+ t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
+ int64_t outputPTS = calculateOutputPTS(
+ t, pts, numFrames + (BLOCKSIZE - outFrames));
+ t.bufferProvider->getNextBuffer(&t.buffer, outputPTS);
+ t.in = t.buffer.raw;
+ if (t.in == NULL) {
+ enabledTracks &= ~(1<<i);
+ e1 &= ~(1<<i);
+ break;
+ }
+ t.frameCount = t.buffer.frameCount;
+ }
+ }
+ }
+ ditherAndClamp(out, outTemp, BLOCKSIZE);
+ out += BLOCKSIZE;
+ numFrames += BLOCKSIZE;
+ } while (numFrames < state->frameCount);
+ }
+
+ // release each track's buffer
+ e0 = enabledTracks;
+ while (e0) {
+ const int i = 31 - __builtin_clz(e0);
+ e0 &= ~(1<<i);
+ track_t& t = state->tracks[i];
+ t.bufferProvider->releaseBuffer(&t.buffer);
+ }
+}
+
+
+// generic code with resampling
+void AudioMixer::process__genericResampling(state_t* state, int64_t pts)
+{
+ // this const just means that local variable outTemp doesn't change
+ int32_t* const outTemp = state->outputTemp;
+ const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
+
+ size_t numFrames = state->frameCount;
+
+ uint32_t e0 = state->enabledTracks;
+ while (e0) {
+ // process by group of tracks with same output buffer
+ // to optimize cache use
+ uint32_t e1 = e0, e2 = e0;
+ int j = 31 - __builtin_clz(e1);
+ track_t& t1 = state->tracks[j];
+ e2 &= ~(1<<j);
+ while (e2) {
+ j = 31 - __builtin_clz(e2);
+ e2 &= ~(1<<j);
+ track_t& t2 = state->tracks[j];
+ if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
+ e1 &= ~(1<<j);
+ }
+ }
+ e0 &= ~(e1);
+ int32_t *out = t1.mainBuffer;
+ memset(outTemp, 0, size);
+ while (e1) {
+ const int i = 31 - __builtin_clz(e1);
+ e1 &= ~(1<<i);
+ track_t& t = state->tracks[i];
+ int32_t *aux = NULL;
+ if (CC_UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED)) {
+ aux = t.auxBuffer;
+ }
+
+ // this is a little goofy, on the resampling case we don't
+ // acquire/release the buffers because it's done by
+ // the resampler.
+ if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
+ t.resampler->setPTS(pts);
+ t.hook(&t, outTemp, numFrames, state->resampleTemp, aux);
+ } else {
+
+ size_t outFrames = 0;
+
+ while (outFrames < numFrames) {
+ t.buffer.frameCount = numFrames - outFrames;
+ int64_t outputPTS = calculateOutputPTS(t, pts, outFrames);
+ t.bufferProvider->getNextBuffer(&t.buffer, outputPTS);
+ t.in = t.buffer.raw;
+ // t.in == NULL can happen if the track was flushed just after having
+ // been enabled for mixing.
+ if (t.in == NULL) break;
+
+ if (CC_UNLIKELY(aux != NULL)) {
+ aux += outFrames;
+ }
+ t.hook(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
+ outFrames += t.buffer.frameCount;
+ t.bufferProvider->releaseBuffer(&t.buffer);
+ }
+ }
+ }
+ ditherAndClamp(out, outTemp, numFrames);
+ }
+}
+
+// one track, 16 bits stereo without resampling is the most common case
+void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state,
+ int64_t pts)
+{
+ // This method is only called when state->enabledTracks has exactly
+ // one bit set. The asserts below would verify this, but are commented out
+ // since the whole point of this method is to optimize performance.
+ //ALOG_ASSERT(0 != state->enabledTracks, "no tracks enabled");
+ const int i = 31 - __builtin_clz(state->enabledTracks);
+ //ALOG_ASSERT((1 << i) == state->enabledTracks, "more than 1 track enabled");
+ const track_t& t = state->tracks[i];
+
+ AudioBufferProvider::Buffer& b(t.buffer);
+
+ int32_t* out = t.mainBuffer;
+ size_t numFrames = state->frameCount;
+
+ const int16_t vl = t.volume[0];
+ const int16_t vr = t.volume[1];
+ const uint32_t vrl = t.volumeRL;
+ while (numFrames) {
+ b.frameCount = numFrames;
+ int64_t outputPTS = calculateOutputPTS(t, pts, out - t.mainBuffer);
+ t.bufferProvider->getNextBuffer(&b, outputPTS);
+ const int16_t *in = b.i16;
+
+ // in == NULL can happen if the track was flushed just after having
+ // been enabled for mixing.
+ if (in == NULL || ((unsigned long)in & 3)) {
+ memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
+ ALOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
+ in, i, t.channelCount, t.needs);
+ return;
+ }
+ size_t outFrames = b.frameCount;
+
+ if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
+ // volume is boosted, so we might need to clamp even though
+ // we process only one track.
+ do {
+ uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+ in += 2;
+ int32_t l = mulRL(1, rl, vrl) >> 12;
+ int32_t r = mulRL(0, rl, vrl) >> 12;
+ // clamping...
+ l = clamp16(l);
+ r = clamp16(r);
+ *out++ = (r<<16) | (l & 0xFFFF);
+ } while (--outFrames);
+ } else {
+ do {
+ uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
+ in += 2;
+ int32_t l = mulRL(1, rl, vrl) >> 12;
+ int32_t r = mulRL(0, rl, vrl) >> 12;
+ *out++ = (r<<16) | (l & 0xFFFF);
+ } while (--outFrames);
+ }
+ numFrames -= b.frameCount;
+ t.bufferProvider->releaseBuffer(&b);
+ }
+}
+
+#if 0
+// 2 tracks is also a common case
+// NEVER used in current implementation of process__validate()
+// only use if the 2 tracks have the same output buffer
+void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state,
+ int64_t pts)
+{
+ int i;
+ uint32_t en = state->enabledTracks;
+
+ i = 31 - __builtin_clz(en);
+ const track_t& t0 = state->tracks[i];
+ AudioBufferProvider::Buffer& b0(t0.buffer);
+
+ en &= ~(1<<i);
+ i = 31 - __builtin_clz(en);
+ const track_t& t1 = state->tracks[i];
+ AudioBufferProvider::Buffer& b1(t1.buffer);
+
+ const int16_t *in0;
+ const int16_t vl0 = t0.volume[0];
+ const int16_t vr0 = t0.volume[1];
+ size_t frameCount0 = 0;
+
+ const int16_t *in1;
+ const int16_t vl1 = t1.volume[0];
+ const int16_t vr1 = t1.volume[1];
+ size_t frameCount1 = 0;
+
+ //FIXME: only works if two tracks use same buffer
+ int32_t* out = t0.mainBuffer;
+ size_t numFrames = state->frameCount;
+ const int16_t *buff = NULL;
+
+
+ while (numFrames) {
+
+ if (frameCount0 == 0) {
+ b0.frameCount = numFrames;
+ int64_t outputPTS = calculateOutputPTS(t0, pts,
+ out - t0.mainBuffer);
+ t0.bufferProvider->getNextBuffer(&b0, outputPTS);
+ if (b0.i16 == NULL) {
+ if (buff == NULL) {
+ buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
+ }
+ in0 = buff;
+ b0.frameCount = numFrames;
+ } else {
+ in0 = b0.i16;
+ }
+ frameCount0 = b0.frameCount;
+ }
+ if (frameCount1 == 0) {
+ b1.frameCount = numFrames;
+ int64_t outputPTS = calculateOutputPTS(t1, pts,
+ out - t0.mainBuffer);
+ t1.bufferProvider->getNextBuffer(&b1, outputPTS);
+ if (b1.i16 == NULL) {
+ if (buff == NULL) {
+ buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
+ }
+ in1 = buff;
+ b1.frameCount = numFrames;
+ } else {
+ in1 = b1.i16;
+ }
+ frameCount1 = b1.frameCount;
+ }
+
+ size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
+
+ numFrames -= outFrames;
+ frameCount0 -= outFrames;
+ frameCount1 -= outFrames;
+
+ do {
+ int32_t l0 = *in0++;
+ int32_t r0 = *in0++;
+ l0 = mul(l0, vl0);
+ r0 = mul(r0, vr0);
+ int32_t l = *in1++;
+ int32_t r = *in1++;
+ l = mulAdd(l, vl1, l0) >> 12;
+ r = mulAdd(r, vr1, r0) >> 12;
+ // clamping...
+ l = clamp16(l);
+ r = clamp16(r);
+ *out++ = (r<<16) | (l & 0xFFFF);
+ } while (--outFrames);
+
+ if (frameCount0 == 0) {
+ t0.bufferProvider->releaseBuffer(&b0);
+ }
+ if (frameCount1 == 0) {
+ t1.bufferProvider->releaseBuffer(&b1);
+ }
+ }
+
+ delete [] buff;
+}
+#endif
+
+int64_t AudioMixer::calculateOutputPTS(const track_t& t, int64_t basePTS,
+ int outputFrameIndex)
+{
+ if (AudioBufferProvider::kInvalidPTS == basePTS)
+ return AudioBufferProvider::kInvalidPTS;
+
+ return basePTS + ((outputFrameIndex * t.localTimeFreq) / t.sampleRate);
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h
new file mode 100644
index 0000000..856450c
--- /dev/null
+++ b/services/audioflinger/AudioMixer.h
@@ -0,0 +1,235 @@
+/*
+**
+** 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_MIXER_H
+#define ANDROID_AUDIO_MIXER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "AudioBufferProvider.h"
+#include "AudioResampler.h"
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class AudioMixer
+{
+public:
+ AudioMixer(size_t frameCount, uint32_t sampleRate,
+ uint32_t maxNumTracks = MAX_NUM_TRACKS);
+
+ /*virtual*/ ~AudioMixer(); // non-virtual saves a v-table, restore if sub-classed
+
+ static const uint32_t MAX_NUM_TRACKS = 32;
+ static const uint32_t MAX_NUM_CHANNELS = 2;
+
+ static const uint16_t UNITY_GAIN = 0x1000;
+
+ enum { // names
+
+ // track names (MAX_NUM_TRACKS units)
+ TRACK0 = 0x1000,
+
+ // 0x2000 is unused
+
+ // setParameter targets
+ TRACK = 0x3000,
+ RESAMPLE = 0x3001,
+ RAMP_VOLUME = 0x3002, // ramp to new volume
+ VOLUME = 0x3003, // don't ramp
+
+ // set Parameter names
+ // for target TRACK
+ CHANNEL_MASK = 0x4000,
+ FORMAT = 0x4001,
+ MAIN_BUFFER = 0x4002,
+ AUX_BUFFER = 0x4003,
+ // for target RESAMPLE
+ SAMPLE_RATE = 0x4100,
+ RESET = 0x4101,
+ // for target RAMP_VOLUME and VOLUME (8 channels max)
+ VOLUME0 = 0x4200,
+ VOLUME1 = 0x4201,
+ AUXLEVEL = 0x4210,
+ };
+
+
+ // For all APIs with "name": TRACK0 <= name < TRACK0 + MAX_NUM_TRACKS
+
+ // Allocate a track name. Returns new track name if successful, -1 on failure.
+ int getTrackName();
+
+ // Free an allocated track by name
+ void deleteTrackName(int name);
+
+ // Enable or disable an allocated track by name
+ void enable(int name);
+ void disable(int name);
+
+ void setParameter(int name, int target, int param, void *value);
+
+ void setBufferProvider(int name, AudioBufferProvider* bufferProvider);
+ void process(int64_t pts);
+
+ uint32_t trackNames() const { return mTrackNames; }
+
+ size_t getUnreleasedFrames(int name) const;
+
+private:
+
+ enum {
+ NEEDS_CHANNEL_COUNT__MASK = 0x00000003,
+ NEEDS_FORMAT__MASK = 0x000000F0,
+ NEEDS_MUTE__MASK = 0x00000100,
+ NEEDS_RESAMPLE__MASK = 0x00001000,
+ NEEDS_AUX__MASK = 0x00010000,
+ };
+
+ enum {
+ NEEDS_CHANNEL_1 = 0x00000000,
+ NEEDS_CHANNEL_2 = 0x00000001,
+
+ NEEDS_FORMAT_16 = 0x00000010,
+
+ NEEDS_MUTE_DISABLED = 0x00000000,
+ NEEDS_MUTE_ENABLED = 0x00000100,
+
+ NEEDS_RESAMPLE_DISABLED = 0x00000000,
+ NEEDS_RESAMPLE_ENABLED = 0x00001000,
+
+ NEEDS_AUX_DISABLED = 0x00000000,
+ NEEDS_AUX_ENABLED = 0x00010000,
+ };
+
+ struct state_t;
+ struct track_t;
+
+ typedef void (*hook_t)(track_t* t, int32_t* output, size_t numOutFrames, int32_t* temp, int32_t* aux);
+ static const int BLOCKSIZE = 16; // 4 cache lines
+
+ struct track_t {
+ uint32_t needs;
+
+ union {
+ int16_t volume[MAX_NUM_CHANNELS]; // [0]3.12 fixed point
+ int32_t volumeRL;
+ };
+
+ int32_t prevVolume[MAX_NUM_CHANNELS];
+
+ // 16-byte boundary
+
+ int32_t volumeInc[MAX_NUM_CHANNELS];
+ int32_t auxInc;
+ int32_t prevAuxLevel;
+
+ // 16-byte boundary
+
+ int16_t auxLevel; // 0 <= auxLevel <= MAX_GAIN_INT, but signed for mul performance
+ uint16_t frameCount;
+
+ uint8_t channelCount; // 1 or 2, redundant with (needs & NEEDS_CHANNEL_COUNT__MASK)
+ uint8_t format; // always 16
+ uint16_t enabled; // actually bool
+ uint32_t channelMask; // currently under-used
+
+ AudioBufferProvider* bufferProvider;
+
+ // 16-byte boundary
+
+ mutable AudioBufferProvider::Buffer buffer; // 8 bytes
+
+ hook_t hook;
+ const void* in; // current location in buffer
+
+ // 16-byte boundary
+
+ AudioResampler* resampler;
+ uint32_t sampleRate;
+ int32_t* mainBuffer;
+ int32_t* auxBuffer;
+
+ // 16-byte boundary
+
+ uint64_t localTimeFreq;
+
+ int64_t padding;
+
+ // 16-byte boundary
+
+ bool setResampler(uint32_t sampleRate, uint32_t devSampleRate);
+ bool doesResample() const { return resampler != NULL; }
+ void resetResampler() { if (resampler != NULL) resampler->reset(); }
+ void adjustVolumeRamp(bool aux);
+ size_t getUnreleasedFrames() const { return resampler != NULL ?
+ resampler->getUnreleasedFrames() : 0; };
+ };
+
+ // pad to 32-bytes to fill cache line
+ struct state_t {
+ uint32_t enabledTracks;
+ uint32_t needsChanged;
+ size_t frameCount;
+ void (*hook)(state_t* state, int64_t pts); // one of process__*, never NULL
+ int32_t *outputTemp;
+ int32_t *resampleTemp;
+ int32_t reserved[2];
+ // FIXME allocate dynamically to save some memory when maxNumTracks < MAX_NUM_TRACKS
+ track_t tracks[MAX_NUM_TRACKS]; __attribute__((aligned(32)));
+ };
+
+ // bitmask of allocated track names, where bit 0 corresponds to TRACK0 etc.
+ uint32_t mTrackNames;
+
+ // bitmask of configured track names; ~0 if maxNumTracks == MAX_NUM_TRACKS,
+ // but will have fewer bits set if maxNumTracks < MAX_NUM_TRACKS
+ const uint32_t mConfiguredNames;
+
+ const uint32_t mSampleRate;
+
+ state_t mState __attribute__((aligned(32)));
+
+ void invalidateState(uint32_t mask);
+
+ static void track__genericResample(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+ static void track__nop(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+ static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+ static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+ static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
+ static void volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
+
+ static void process__validate(state_t* state, int64_t pts);
+ static void process__nop(state_t* state, int64_t pts);
+ static void process__genericNoResampling(state_t* state, int64_t pts);
+ static void process__genericResampling(state_t* state, int64_t pts);
+ static void process__OneTrack16BitsStereoNoResampling(state_t* state,
+ int64_t pts);
+#if 0
+ static void process__TwoTracks16BitsStereoNoResampling(state_t* state,
+ int64_t pts);
+#endif
+
+ static int64_t calculateOutputPTS(const track_t& t, int64_t basePTS,
+ int outputFrameIndex);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_AUDIO_MIXER_H
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
new file mode 100644
index 0000000..c23eb04
--- /dev/null
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -0,0 +1,1510 @@
+/*
+ * 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 "AudioPolicyService"
+//#define LOG_NDEBUG 0
+
+#undef __STRICT_ANSI__
+#define __STDINT_LIMITS
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+
+#include <sys/time.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+#include <cutils/properties.h>
+#include <binder/IPCThreadState.h>
+#include <utils/String16.h>
+#include <utils/threads.h>
+#include "AudioPolicyService.h"
+#include "ServiceUtilities.h"
+#include <cutils/properties.h>
+#include <hardware_legacy/power.h>
+#include <media/AudioEffect.h>
+#include <media/EffectsFactoryApi.h>
+
+#include <hardware/hardware.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+#include <hardware/audio_policy.h>
+#include <audio_effects/audio_effects_conf.h>
+
+namespace android {
+
+static const char kDeadlockedString[] = "AudioPolicyService may be deadlocked\n";
+static const char kCmdDeadlockedString[] = "AudioPolicyService command thread may be deadlocked\n";
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleepUs = 20000;
+
+namespace {
+ extern struct audio_policy_service_ops aps_ops;
+};
+
+// ----------------------------------------------------------------------------
+
+AudioPolicyService::AudioPolicyService()
+ : BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)
+{
+ char value[PROPERTY_VALUE_MAX];
+ const struct hw_module_t *module;
+ int forced_val;
+ int rc;
+
+ Mutex::Autolock _l(mLock);
+
+ // start tone playback thread
+ mTonePlaybackThread = new AudioCommandThread(String8(""));
+ // start audio commands thread
+ mAudioCommandThread = new AudioCommandThread(String8("ApmCommand"));
+
+ /* instantiate the audio policy manager */
+ rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
+ if (rc)
+ return;
+
+ rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
+ ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
+ if (rc)
+ return;
+
+ rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
+ &mpAudioPolicy);
+ ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
+ if (rc)
+ return;
+
+ rc = mpAudioPolicy->init_check(mpAudioPolicy);
+ ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
+ if (rc)
+ return;
+
+ property_get("ro.camera.sound.forced", value, "0");
+ forced_val = strtol(value, NULL, 0);
+ mpAudioPolicy->set_can_mute_enforced_audible(mpAudioPolicy, !forced_val);
+
+ ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);
+
+ // load audio pre processing modules
+ if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
+ loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
+ } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
+ loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
+ }
+}
+
+AudioPolicyService::~AudioPolicyService()
+{
+ mTonePlaybackThread->exit();
+ mTonePlaybackThread.clear();
+ mAudioCommandThread->exit();
+ mAudioCommandThread.clear();
+
+
+ // release audio pre processing resources
+ for (size_t i = 0; i < mInputSources.size(); i++) {
+ delete mInputSources.valueAt(i);
+ }
+ mInputSources.clear();
+
+ for (size_t i = 0; i < mInputs.size(); i++) {
+ mInputs.valueAt(i)->mEffects.clear();
+ delete mInputs.valueAt(i);
+ }
+ mInputs.clear();
+
+ if (mpAudioPolicy != NULL && mpAudioPolicyDev != NULL)
+ mpAudioPolicyDev->destroy_audio_policy(mpAudioPolicyDev, mpAudioPolicy);
+ if (mpAudioPolicyDev != NULL)
+ audio_policy_dev_close(mpAudioPolicyDev);
+}
+
+status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
+ audio_policy_dev_state_t state,
+ const char *device_address)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ if (!audio_is_output_device(device) && !audio_is_input_device(device)) {
+ return BAD_VALUE;
+ }
+ if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE &&
+ state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
+ return BAD_VALUE;
+ }
+
+ ALOGV("setDeviceConnectionState() tid %d", gettid());
+ Mutex::Autolock _l(mLock);
+ return mpAudioPolicy->set_device_connection_state(mpAudioPolicy, device,
+ state, device_address);
+}
+
+audio_policy_dev_state_t AudioPolicyService::getDeviceConnectionState(
+ audio_devices_t device,
+ const char *device_address)
+{
+ if (mpAudioPolicy == NULL) {
+ return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
+ }
+ return mpAudioPolicy->get_device_connection_state(mpAudioPolicy, device,
+ device_address);
+}
+
+status_t AudioPolicyService::setPhoneState(audio_mode_t state)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ if (uint32_t(state) >= AUDIO_MODE_CNT) {
+ return BAD_VALUE;
+ }
+
+ ALOGV("setPhoneState() tid %d", gettid());
+
+ // TODO: check if it is more appropriate to do it in platform specific policy manager
+ AudioSystem::setMode(state);
+
+ Mutex::Autolock _l(mLock);
+ mpAudioPolicy->set_phone_state(mpAudioPolicy, state);
+ return NO_ERROR;
+}
+
+status_t AudioPolicyService::setForceUse(audio_policy_force_use_t usage,
+ audio_policy_forced_cfg_t config)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
+ return BAD_VALUE;
+ }
+ if (config < 0 || config >= AUDIO_POLICY_FORCE_CFG_CNT) {
+ return BAD_VALUE;
+ }
+ ALOGV("setForceUse() tid %d", gettid());
+ Mutex::Autolock _l(mLock);
+ mpAudioPolicy->set_force_use(mpAudioPolicy, usage, config);
+ return NO_ERROR;
+}
+
+audio_policy_forced_cfg_t AudioPolicyService::getForceUse(audio_policy_force_use_t usage)
+{
+ if (mpAudioPolicy == NULL) {
+ return AUDIO_POLICY_FORCE_NONE;
+ }
+ if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
+ return AUDIO_POLICY_FORCE_NONE;
+ }
+ return mpAudioPolicy->get_force_use(mpAudioPolicy, usage);
+}
+
+audio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream,
+ uint32_t samplingRate,
+ audio_format_t format,
+ uint32_t channels,
+ audio_policy_output_flags_t flags)
+{
+ if (mpAudioPolicy == NULL) {
+ return 0;
+ }
+ ALOGV("getOutput() tid %d", gettid());
+ Mutex::Autolock _l(mLock);
+ return mpAudioPolicy->get_output(mpAudioPolicy, stream, samplingRate, format, channels, flags);
+}
+
+status_t AudioPolicyService::startOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int session)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ ALOGV("startOutput() tid %d", gettid());
+ Mutex::Autolock _l(mLock);
+ return mpAudioPolicy->start_output(mpAudioPolicy, output, stream, session);
+}
+
+status_t AudioPolicyService::stopOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int session)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ ALOGV("stopOutput() tid %d", gettid());
+ Mutex::Autolock _l(mLock);
+ return mpAudioPolicy->stop_output(mpAudioPolicy, output, stream, session);
+}
+
+void AudioPolicyService::releaseOutput(audio_io_handle_t output)
+{
+ if (mpAudioPolicy == NULL) {
+ return;
+ }
+ ALOGV("releaseOutput() tid %d", gettid());
+ Mutex::Autolock _l(mLock);
+ mpAudioPolicy->release_output(mpAudioPolicy, output);
+}
+
+audio_io_handle_t AudioPolicyService::getInput(audio_source_t inputSource,
+ uint32_t samplingRate,
+ audio_format_t format,
+ uint32_t channels,
+ audio_in_acoustics_t acoustics,
+ int audioSession)
+{
+ if (mpAudioPolicy == NULL) {
+ return 0;
+ }
+ // already checked by client, but double-check in case the client wrapper is bypassed
+ if (uint32_t(inputSource) >= AUDIO_SOURCE_CNT) {
+ return 0;
+ }
+ Mutex::Autolock _l(mLock);
+ audio_io_handle_t input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
+ format, channels, acoustics);
+
+ if (input == 0) {
+ return input;
+ }
+ // create audio pre processors according to input source
+ ssize_t index = mInputSources.indexOfKey(inputSource);
+ if (index < 0) {
+ return input;
+ }
+ ssize_t idx = mInputs.indexOfKey(input);
+ InputDesc *inputDesc;
+ if (idx < 0) {
+ inputDesc = new InputDesc(audioSession);
+ mInputs.add(input, inputDesc);
+ } else {
+ inputDesc = mInputs.valueAt(idx);
+ }
+
+ Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
+ for (size_t i = 0; i < effects.size(); i++) {
+ EffectDesc *effect = effects[i];
+ sp<AudioEffect> fx = new AudioEffect(NULL, &effect->mUuid, -1, 0, 0, audioSession, input);
+ status_t status = fx->initCheck();
+ if (status != NO_ERROR && status != ALREADY_EXISTS) {
+ ALOGW("Failed to create Fx %s on input %d", effect->mName, input);
+ // fx goes out of scope and strong ref on AudioEffect is released
+ continue;
+ }
+ for (size_t j = 0; j < effect->mParams.size(); j++) {
+ fx->setParameter(effect->mParams[j]);
+ }
+ inputDesc->mEffects.add(fx);
+ }
+ setPreProcessorEnabled(inputDesc, true);
+ return input;
+}
+
+status_t AudioPolicyService::startInput(audio_io_handle_t input)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+
+ return mpAudioPolicy->start_input(mpAudioPolicy, input);
+}
+
+status_t AudioPolicyService::stopInput(audio_io_handle_t input)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+
+ return mpAudioPolicy->stop_input(mpAudioPolicy, input);
+}
+
+void AudioPolicyService::releaseInput(audio_io_handle_t input)
+{
+ if (mpAudioPolicy == NULL) {
+ return;
+ }
+ Mutex::Autolock _l(mLock);
+ mpAudioPolicy->release_input(mpAudioPolicy, input);
+
+ ssize_t index = mInputs.indexOfKey(input);
+ if (index < 0) {
+ return;
+ }
+ InputDesc *inputDesc = mInputs.valueAt(index);
+ setPreProcessorEnabled(inputDesc, false);
+ delete inputDesc;
+ mInputs.removeItemsAt(index);
+}
+
+status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream,
+ int indexMin,
+ int indexMax)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ return BAD_VALUE;
+ }
+ mpAudioPolicy->init_stream_volume(mpAudioPolicy, stream, indexMin, indexMax);
+ return NO_ERROR;
+}
+
+status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream,
+ int index,
+ audio_devices_t device)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ if (!settingsAllowed()) {
+ return PERMISSION_DENIED;
+ }
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ return BAD_VALUE;
+ }
+
+ if (mpAudioPolicy->set_stream_volume_index_for_device) {
+ return mpAudioPolicy->set_stream_volume_index_for_device(mpAudioPolicy,
+ stream,
+ index,
+ device);
+ } else {
+ return mpAudioPolicy->set_stream_volume_index(mpAudioPolicy, stream, index);
+ }
+}
+
+status_t AudioPolicyService::getStreamVolumeIndex(audio_stream_type_t stream,
+ int *index,
+ audio_devices_t device)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ return BAD_VALUE;
+ }
+ if (mpAudioPolicy->get_stream_volume_index_for_device) {
+ return mpAudioPolicy->get_stream_volume_index_for_device(mpAudioPolicy,
+ stream,
+ index,
+ device);
+ } else {
+ return mpAudioPolicy->get_stream_volume_index(mpAudioPolicy, stream, index);
+ }
+}
+
+uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream)
+{
+ if (mpAudioPolicy == NULL) {
+ return 0;
+ }
+ return mpAudioPolicy->get_strategy_for_stream(mpAudioPolicy, stream);
+}
+
+//audio policy: use audio_device_t appropriately
+
+audio_devices_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream)
+{
+ if (mpAudioPolicy == NULL) {
+ return (audio_devices_t)0;
+ }
+ return mpAudioPolicy->get_devices_for_stream(mpAudioPolicy, stream);
+}
+
+audio_io_handle_t AudioPolicyService::getOutputForEffect(effect_descriptor_t *desc)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ return mpAudioPolicy->get_output_for_effect(mpAudioPolicy, desc);
+}
+
+status_t AudioPolicyService::registerEffect(effect_descriptor_t *desc,
+ audio_io_handle_t io,
+ uint32_t strategy,
+ int session,
+ int id)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ return mpAudioPolicy->register_effect(mpAudioPolicy, desc, io, strategy, session, id);
+}
+
+status_t AudioPolicyService::unregisterEffect(int id)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ return mpAudioPolicy->unregister_effect(mpAudioPolicy, id);
+}
+
+status_t AudioPolicyService::setEffectEnabled(int id, bool enabled)
+{
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ return mpAudioPolicy->set_effect_enabled(mpAudioPolicy, id, enabled);
+}
+
+bool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
+{
+ if (mpAudioPolicy == NULL) {
+ return 0;
+ }
+ Mutex::Autolock _l(mLock);
+ return mpAudioPolicy->is_stream_active(mpAudioPolicy, stream, inPastMs);
+}
+
+status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count)
+{
+
+ if (mpAudioPolicy == NULL) {
+ *count = 0;
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ status_t status = NO_ERROR;
+
+ size_t index;
+ for (index = 0; index < mInputs.size(); index++) {
+ if (mInputs.valueAt(index)->mSessionId == audioSession) {
+ break;
+ }
+ }
+ if (index == mInputs.size()) {
+ *count = 0;
+ return BAD_VALUE;
+ }
+ Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects;
+
+ for (size_t i = 0; i < effects.size(); i++) {
+ effect_descriptor_t desc = effects[i]->descriptor();
+ if (i < *count) {
+ memcpy(descriptors + i, &desc, sizeof(effect_descriptor_t));
+ }
+ }
+ if (effects.size() > *count) {
+ status = NO_MEMORY;
+ }
+ *count = effects.size();
+ return status;
+}
+
+void AudioPolicyService::binderDied(const wp<IBinder>& who) {
+ ALOGW("binderDied() %p, tid %d, calling pid %d", who.unsafe_get(), gettid(),
+ IPCThreadState::self()->getCallingPid());
+}
+
+static bool tryLock(Mutex& mutex)
+{
+ bool locked = false;
+ for (int i = 0; i < kDumpLockRetries; ++i) {
+ if (mutex.tryLock() == NO_ERROR) {
+ locked = true;
+ break;
+ }
+ usleep(kDumpLockSleepUs);
+ }
+ return locked;
+}
+
+status_t AudioPolicyService::dumpInternals(int fd)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpAudioPolicy);
+ result.append(buffer);
+ snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
+ result.append(buffer);
+ snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
+ result.append(buffer);
+
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
+{
+ if (!dumpAllowed()) {
+ dumpPermissionDenial(fd);
+ } else {
+ bool locked = tryLock(mLock);
+ if (!locked) {
+ String8 result(kDeadlockedString);
+ write(fd, result.string(), result.size());
+ }
+
+ dumpInternals(fd);
+ if (mAudioCommandThread != 0) {
+ mAudioCommandThread->dump(fd);
+ }
+ if (mTonePlaybackThread != 0) {
+ mTonePlaybackThread->dump(fd);
+ }
+
+ if (mpAudioPolicy) {
+ mpAudioPolicy->dump(mpAudioPolicy, fd);
+ }
+
+ if (locked) mLock.unlock();
+ }
+ return NO_ERROR;
+}
+
+status_t AudioPolicyService::dumpPermissionDenial(int fd)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ snprintf(buffer, SIZE, "Permission Denial: "
+ "can't dump AudioPolicyService from pid=%d, uid=%d\n",
+ IPCThreadState::self()->getCallingPid(),
+ IPCThreadState::self()->getCallingUid());
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+void AudioPolicyService::setPreProcessorEnabled(const InputDesc *inputDesc, bool enabled)
+{
+ const Vector<sp<AudioEffect> > &fxVector = inputDesc->mEffects;
+ for (size_t i = 0; i < fxVector.size(); i++) {
+ fxVector.itemAt(i)->setEnabled(enabled);
+ }
+}
+
+status_t AudioPolicyService::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ return BnAudioPolicyService::onTransact(code, data, reply, flags);
+}
+
+
+// ----------- AudioPolicyService::AudioCommandThread implementation ----------
+
+AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name)
+ : Thread(false), mName(name)
+{
+ mpToneGenerator = NULL;
+}
+
+
+AudioPolicyService::AudioCommandThread::~AudioCommandThread()
+{
+ if (mName != "" && !mAudioCommands.isEmpty()) {
+ release_wake_lock(mName.string());
+ }
+ mAudioCommands.clear();
+ delete mpToneGenerator;
+}
+
+void AudioPolicyService::AudioCommandThread::onFirstRef()
+{
+ if (mName != "") {
+ run(mName.string(), ANDROID_PRIORITY_AUDIO);
+ } else {
+ run("AudioCommand", ANDROID_PRIORITY_AUDIO);
+ }
+}
+
+bool AudioPolicyService::AudioCommandThread::threadLoop()
+{
+ nsecs_t waitTime = INT64_MAX;
+
+ mLock.lock();
+ while (!exitPending())
+ {
+ while (!mAudioCommands.isEmpty()) {
+ nsecs_t curTime = systemTime();
+ // commands are sorted by increasing time stamp: execute them from index 0 and up
+ if (mAudioCommands[0]->mTime <= curTime) {
+ AudioCommand *command = mAudioCommands[0];
+ mAudioCommands.removeAt(0);
+ mLastCommand = *command;
+
+ switch (command->mCommand) {
+ case START_TONE: {
+ mLock.unlock();
+ ToneData *data = (ToneData *)command->mParam;
+ ALOGV("AudioCommandThread() processing start tone %d on stream %d",
+ data->mType, data->mStream);
+ delete mpToneGenerator;
+ mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
+ mpToneGenerator->startTone(data->mType);
+ delete data;
+ mLock.lock();
+ }break;
+ case STOP_TONE: {
+ mLock.unlock();
+ ALOGV("AudioCommandThread() processing stop tone");
+ if (mpToneGenerator != NULL) {
+ mpToneGenerator->stopTone();
+ delete mpToneGenerator;
+ mpToneGenerator = NULL;
+ }
+ mLock.lock();
+ }break;
+ case SET_VOLUME: {
+ VolumeData *data = (VolumeData *)command->mParam;
+ ALOGV("AudioCommandThread() processing set volume stream %d, \
+ volume %f, output %d", data->mStream, data->mVolume, data->mIO);
+ command->mStatus = AudioSystem::setStreamVolume(data->mStream,
+ data->mVolume,
+ data->mIO);
+ if (command->mWaitStatus) {
+ command->mCond.signal();
+ mWaitWorkCV.wait(mLock);
+ }
+ delete data;
+ }break;
+ case SET_PARAMETERS: {
+ ParametersData *data = (ParametersData *)command->mParam;
+ ALOGV("AudioCommandThread() processing set parameters string %s, io %d",
+ data->mKeyValuePairs.string(), data->mIO);
+ command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
+ if (command->mWaitStatus) {
+ command->mCond.signal();
+ mWaitWorkCV.wait(mLock);
+ }
+ delete data;
+ }break;
+ case SET_VOICE_VOLUME: {
+ VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
+ ALOGV("AudioCommandThread() processing set voice volume volume %f",
+ data->mVolume);
+ command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
+ if (command->mWaitStatus) {
+ command->mCond.signal();
+ mWaitWorkCV.wait(mLock);
+ }
+ delete data;
+ }break;
+ default:
+ ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
+ }
+ delete command;
+ waitTime = INT64_MAX;
+ } else {
+ waitTime = mAudioCommands[0]->mTime - curTime;
+ break;
+ }
+ }
+ // release delayed commands wake lock
+ if (mName != "" && mAudioCommands.isEmpty()) {
+ release_wake_lock(mName.string());
+ }
+ ALOGV("AudioCommandThread() going to sleep");
+ mWaitWorkCV.waitRelative(mLock, waitTime);
+ ALOGV("AudioCommandThread() waking up");
+ }
+ mLock.unlock();
+ return false;
+}
+
+status_t AudioPolicyService::AudioCommandThread::dump(int fd)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+
+ bool locked = tryLock(mLock);
+ if (!locked) {
+ String8 result2(kCmdDeadlockedString);
+ write(fd, result2.string(), result2.size());
+ }
+
+ snprintf(buffer, SIZE, "- Commands:\n");
+ result = String8(buffer);
+ result.append(" Command Time Wait pParam\n");
+ for (size_t i = 0; i < mAudioCommands.size(); i++) {
+ mAudioCommands[i]->dump(buffer, SIZE);
+ result.append(buffer);
+ }
+ result.append(" Last Command\n");
+ mLastCommand.dump(buffer, SIZE);
+ result.append(buffer);
+
+ write(fd, result.string(), result.size());
+
+ if (locked) mLock.unlock();
+
+ return NO_ERROR;
+}
+
+void AudioPolicyService::AudioCommandThread::startToneCommand(ToneGenerator::tone_type type,
+ audio_stream_type_t stream)
+{
+ AudioCommand *command = new AudioCommand();
+ command->mCommand = START_TONE;
+ ToneData *data = new ToneData();
+ data->mType = type;
+ data->mStream = stream;
+ command->mParam = (void *)data;
+ command->mWaitStatus = false;
+ Mutex::Autolock _l(mLock);
+ insertCommand_l(command);
+ ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
+ mWaitWorkCV.signal();
+}
+
+void AudioPolicyService::AudioCommandThread::stopToneCommand()
+{
+ AudioCommand *command = new AudioCommand();
+ command->mCommand = STOP_TONE;
+ command->mParam = NULL;
+ command->mWaitStatus = false;
+ Mutex::Autolock _l(mLock);
+ insertCommand_l(command);
+ ALOGV("AudioCommandThread() adding tone stop");
+ mWaitWorkCV.signal();
+}
+
+status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,
+ float volume,
+ audio_io_handle_t output,
+ int delayMs)
+{
+ status_t status = NO_ERROR;
+
+ AudioCommand *command = new AudioCommand();
+ command->mCommand = SET_VOLUME;
+ VolumeData *data = new VolumeData();
+ data->mStream = stream;
+ data->mVolume = volume;
+ data->mIO = output;
+ command->mParam = data;
+ if (delayMs == 0) {
+ command->mWaitStatus = true;
+ } else {
+ command->mWaitStatus = false;
+ }
+ Mutex::Autolock _l(mLock);
+ insertCommand_l(command, delayMs);
+ ALOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d",
+ stream, volume, output);
+ mWaitWorkCV.signal();
+ if (command->mWaitStatus) {
+ command->mCond.wait(mLock);
+ status = command->mStatus;
+ mWaitWorkCV.signal();
+ }
+ return status;
+}
+
+status_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_handle_t ioHandle,
+ const char *keyValuePairs,
+ int delayMs)
+{
+ status_t status = NO_ERROR;
+
+ AudioCommand *command = new AudioCommand();
+ command->mCommand = SET_PARAMETERS;
+ ParametersData *data = new ParametersData();
+ data->mIO = ioHandle;
+ data->mKeyValuePairs = String8(keyValuePairs);
+ command->mParam = data;
+ if (delayMs == 0) {
+ command->mWaitStatus = true;
+ } else {
+ command->mWaitStatus = false;
+ }
+ Mutex::Autolock _l(mLock);
+ insertCommand_l(command, delayMs);
+ ALOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d",
+ keyValuePairs, ioHandle, delayMs);
+ mWaitWorkCV.signal();
+ if (command->mWaitStatus) {
+ command->mCond.wait(mLock);
+ status = command->mStatus;
+ mWaitWorkCV.signal();
+ }
+ return status;
+}
+
+status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
+{
+ status_t status = NO_ERROR;
+
+ AudioCommand *command = new AudioCommand();
+ command->mCommand = SET_VOICE_VOLUME;
+ VoiceVolumeData *data = new VoiceVolumeData();
+ data->mVolume = volume;
+ command->mParam = data;
+ if (delayMs == 0) {
+ command->mWaitStatus = true;
+ } else {
+ command->mWaitStatus = false;
+ }
+ Mutex::Autolock _l(mLock);
+ insertCommand_l(command, delayMs);
+ ALOGV("AudioCommandThread() adding set voice volume volume %f", volume);
+ mWaitWorkCV.signal();
+ if (command->mWaitStatus) {
+ command->mCond.wait(mLock);
+ status = command->mStatus;
+ mWaitWorkCV.signal();
+ }
+ return status;
+}
+
+// insertCommand_l() must be called with mLock held
+void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
+{
+ ssize_t i; // not size_t because i will count down to -1
+ Vector <AudioCommand *> removedCommands;
+
+ command->mTime = systemTime() + milliseconds(delayMs);
+
+ // acquire wake lock to make sure delayed commands are processed
+ if (mName != "" && mAudioCommands.isEmpty()) {
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
+ }
+
+ // check same pending commands with later time stamps and eliminate them
+ for (i = mAudioCommands.size()-1; i >= 0; i--) {
+ AudioCommand *command2 = mAudioCommands[i];
+ // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
+ if (command2->mTime <= command->mTime) break;
+ if (command2->mCommand != command->mCommand) continue;
+
+ switch (command->mCommand) {
+ case SET_PARAMETERS: {
+ ParametersData *data = (ParametersData *)command->mParam;
+ ParametersData *data2 = (ParametersData *)command2->mParam;
+ if (data->mIO != data2->mIO) break;
+ ALOGV("Comparing parameter command %s to new command %s",
+ data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
+ AudioParameter param = AudioParameter(data->mKeyValuePairs);
+ AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
+ for (size_t j = 0; j < param.size(); j++) {
+ String8 key;
+ String8 value;
+ param.getAt(j, key, value);
+ for (size_t k = 0; k < param2.size(); k++) {
+ String8 key2;
+ String8 value2;
+ param2.getAt(k, key2, value2);
+ if (key2 == key) {
+ param2.remove(key2);
+ ALOGV("Filtering out parameter %s", key2.string());
+ break;
+ }
+ }
+ }
+ // if all keys have been filtered out, remove the command.
+ // otherwise, update the key value pairs
+ if (param2.size() == 0) {
+ removedCommands.add(command2);
+ } else {
+ data2->mKeyValuePairs = param2.toString();
+ }
+ } break;
+
+ case SET_VOLUME: {
+ VolumeData *data = (VolumeData *)command->mParam;
+ VolumeData *data2 = (VolumeData *)command2->mParam;
+ if (data->mIO != data2->mIO) break;
+ if (data->mStream != data2->mStream) break;
+ ALOGV("Filtering out volume command on output %d for stream %d",
+ data->mIO, data->mStream);
+ removedCommands.add(command2);
+ } break;
+ case START_TONE:
+ case STOP_TONE:
+ default:
+ break;
+ }
+ }
+
+ // remove filtered commands
+ for (size_t j = 0; j < removedCommands.size(); j++) {
+ // removed commands always have time stamps greater than current command
+ for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
+ if (mAudioCommands[k] == removedCommands[j]) {
+ ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
+ mAudioCommands.removeAt(k);
+ break;
+ }
+ }
+ }
+ removedCommands.clear();
+
+ // insert command at the right place according to its time stamp
+ ALOGV("inserting command: %d at index %d, num commands %d",
+ command->mCommand, (int)i+1, mAudioCommands.size());
+ mAudioCommands.insertAt(command, i + 1);
+}
+
+void AudioPolicyService::AudioCommandThread::exit()
+{
+ ALOGV("AudioCommandThread::exit");
+ {
+ AutoMutex _l(mLock);
+ requestExit();
+ mWaitWorkCV.signal();
+ }
+ requestExitAndWait();
+}
+
+void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
+{
+ snprintf(buffer, size, " %02d %06d.%03d %01u %p\n",
+ mCommand,
+ (int)ns2s(mTime),
+ (int)ns2ms(mTime)%1000,
+ mWaitStatus,
+ mParam);
+}
+
+/******* helpers for the service_ops callbacks defined below *********/
+void AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
+ const char *keyValuePairs,
+ int delayMs)
+{
+ mAudioCommandThread->parametersCommand(ioHandle, keyValuePairs,
+ delayMs);
+}
+
+int AudioPolicyService::setStreamVolume(audio_stream_type_t stream,
+ float volume,
+ audio_io_handle_t output,
+ int delayMs)
+{
+ return (int)mAudioCommandThread->volumeCommand(stream, volume,
+ output, delayMs);
+}
+
+int AudioPolicyService::startTone(audio_policy_tone_t tone,
+ audio_stream_type_t stream)
+{
+ if (tone != AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION)
+ ALOGE("startTone: illegal tone requested (%d)", tone);
+ if (stream != AUDIO_STREAM_VOICE_CALL)
+ ALOGE("startTone: illegal stream (%d) requested for tone %d", stream,
+ tone);
+ mTonePlaybackThread->startToneCommand(ToneGenerator::TONE_SUP_CALL_WAITING,
+ AUDIO_STREAM_VOICE_CALL);
+ return 0;
+}
+
+int AudioPolicyService::stopTone()
+{
+ mTonePlaybackThread->stopToneCommand();
+ return 0;
+}
+
+int AudioPolicyService::setVoiceVolume(float volume, int delayMs)
+{
+ return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
+}
+
+// ----------------------------------------------------------------------------
+// Audio pre-processing configuration
+// ----------------------------------------------------------------------------
+
+/*static*/ const char * const AudioPolicyService::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
+ MIC_SRC_TAG,
+ VOICE_UL_SRC_TAG,
+ VOICE_DL_SRC_TAG,
+ VOICE_CALL_SRC_TAG,
+ CAMCORDER_SRC_TAG,
+ VOICE_REC_SRC_TAG,
+ VOICE_COMM_SRC_TAG
+};
+
+// returns the audio_source_t enum corresponding to the input source name or
+// AUDIO_SOURCE_CNT is no match found
+audio_source_t AudioPolicyService::inputSourceNameToEnum(const char *name)
+{
+ int i;
+ for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
+ if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
+ ALOGV("inputSourceNameToEnum found source %s %d", name, i);
+ break;
+ }
+ }
+ return (audio_source_t)i;
+}
+
+size_t AudioPolicyService::growParamSize(char *param,
+ size_t size,
+ size_t *curSize,
+ size_t *totSize)
+{
+ // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
+ size_t pos = ((*curSize - 1 ) / size + 1) * size;
+
+ if (pos + size > *totSize) {
+ while (pos + size > *totSize) {
+ *totSize += ((*totSize + 7) / 8) * 4;
+ }
+ param = (char *)realloc(param, *totSize);
+ }
+ *curSize = pos + size;
+ return pos;
+}
+
+size_t AudioPolicyService::readParamValue(cnode *node,
+ char *param,
+ size_t *curSize,
+ size_t *totSize)
+{
+ if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
+ size_t pos = growParamSize(param, sizeof(short), curSize, totSize);
+ *(short *)((char *)param + pos) = (short)atoi(node->value);
+ ALOGV("readParamValue() reading short %d", *(short *)((char *)param + pos));
+ return sizeof(short);
+ } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
+ size_t pos = growParamSize(param, sizeof(int), curSize, totSize);
+ *(int *)((char *)param + pos) = atoi(node->value);
+ ALOGV("readParamValue() reading int %d", *(int *)((char *)param + pos));
+ return sizeof(int);
+ } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
+ size_t pos = growParamSize(param, sizeof(float), curSize, totSize);
+ *(float *)((char *)param + pos) = (float)atof(node->value);
+ ALOGV("readParamValue() reading float %f",*(float *)((char *)param + pos));
+ return sizeof(float);
+ } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
+ size_t pos = growParamSize(param, sizeof(bool), curSize, totSize);
+ if (strncmp(node->value, "false", strlen("false") + 1) == 0) {
+ *(bool *)((char *)param + pos) = false;
+ } else {
+ *(bool *)((char *)param + pos) = true;
+ }
+ ALOGV("readParamValue() reading bool %s",*(bool *)((char *)param + pos) ? "true" : "false");
+ return sizeof(bool);
+ } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
+ size_t len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
+ if (*curSize + len + 1 > *totSize) {
+ *totSize = *curSize + len + 1;
+ param = (char *)realloc(param, *totSize);
+ }
+ strncpy(param + *curSize, node->value, len);
+ *curSize += len;
+ param[*curSize] = '\0';
+ ALOGV("readParamValue() reading string %s", param + *curSize - len);
+ return len;
+ }
+ ALOGW("readParamValue() unknown param type %s", node->name);
+ return 0;
+}
+
+effect_param_t *AudioPolicyService::loadEffectParameter(cnode *root)
+{
+ cnode *param;
+ cnode *value;
+ size_t curSize = sizeof(effect_param_t);
+ size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
+ effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
+
+ param = config_find(root, PARAM_TAG);
+ value = config_find(root, VALUE_TAG);
+ if (param == NULL && value == NULL) {
+ // try to parse simple parameter form {int int}
+ param = root->first_child;
+ if (param != NULL) {
+ // Note: that a pair of random strings is read as 0 0
+ int *ptr = (int *)fx_param->data;
+ int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
+ ALOGW("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
+ *ptr++ = atoi(param->name);
+ *ptr = atoi(param->value);
+ fx_param->psize = sizeof(int);
+ fx_param->vsize = sizeof(int);
+ return fx_param;
+ }
+ }
+ if (param == NULL || value == NULL) {
+ ALOGW("loadEffectParameter() invalid parameter description %s", root->name);
+ goto error;
+ }
+
+ fx_param->psize = 0;
+ param = param->first_child;
+ while (param) {
+ ALOGV("loadEffectParameter() reading param of type %s", param->name);
+ size_t size = readParamValue(param, (char *)fx_param, &curSize, &totSize);
+ if (size == 0) {
+ goto error;
+ }
+ fx_param->psize += size;
+ param = param->next;
+ }
+
+ // align start of value field on 32 bit boundary
+ curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
+
+ fx_param->vsize = 0;
+ value = value->first_child;
+ while (value) {
+ ALOGV("loadEffectParameter() reading value of type %s", value->name);
+ size_t size = readParamValue(value, (char *)fx_param, &curSize, &totSize);
+ if (size == 0) {
+ goto error;
+ }
+ fx_param->vsize += size;
+ value = value->next;
+ }
+
+ return fx_param;
+
+error:
+ delete fx_param;
+ return NULL;
+}
+
+void AudioPolicyService::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
+{
+ cnode *node = root->first_child;
+ while (node) {
+ ALOGV("loadEffectParameters() loading param %s", node->name);
+ effect_param_t *param = loadEffectParameter(node);
+ if (param == NULL) {
+ node = node->next;
+ continue;
+ }
+ params.add(param);
+ node = node->next;
+ }
+}
+
+AudioPolicyService::InputSourceDesc *AudioPolicyService::loadInputSource(
+ cnode *root,
+ const Vector <EffectDesc *>& effects)
+{
+ cnode *node = root->first_child;
+ if (node == NULL) {
+ ALOGW("loadInputSource() empty element %s", root->name);
+ return NULL;
+ }
+ InputSourceDesc *source = new InputSourceDesc();
+ while (node) {
+ size_t i;
+ for (i = 0; i < effects.size(); i++) {
+ if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
+ ALOGV("loadInputSource() found effect %s in list", node->name);
+ break;
+ }
+ }
+ if (i == effects.size()) {
+ ALOGV("loadInputSource() effect %s not in list", node->name);
+ node = node->next;
+ continue;
+ }
+ EffectDesc *effect = new EffectDesc(*effects[i]); // deep copy
+ loadEffectParameters(node, effect->mParams);
+ ALOGV("loadInputSource() adding effect %s uuid %08x", effect->mName, effect->mUuid.timeLow);
+ source->mEffects.add(effect);
+ node = node->next;
+ }
+ if (source->mEffects.size() == 0) {
+ ALOGW("loadInputSource() no valid effects found in source %s", root->name);
+ delete source;
+ return NULL;
+ }
+ return source;
+}
+
+status_t AudioPolicyService::loadInputSources(cnode *root, const Vector <EffectDesc *>& effects)
+{
+ cnode *node = config_find(root, PREPROCESSING_TAG);
+ if (node == NULL) {
+ return -ENOENT;
+ }
+ node = node->first_child;
+ while (node) {
+ audio_source_t source = inputSourceNameToEnum(node->name);
+ if (source == AUDIO_SOURCE_CNT) {
+ ALOGW("loadInputSources() invalid input source %s", node->name);
+ node = node->next;
+ continue;
+ }
+ ALOGV("loadInputSources() loading input source %s", node->name);
+ InputSourceDesc *desc = loadInputSource(node, effects);
+ if (desc == NULL) {
+ node = node->next;
+ continue;
+ }
+ mInputSources.add(source, desc);
+ node = node->next;
+ }
+ return NO_ERROR;
+}
+
+AudioPolicyService::EffectDesc *AudioPolicyService::loadEffect(cnode *root)
+{
+ cnode *node = config_find(root, UUID_TAG);
+ if (node == NULL) {
+ return NULL;
+ }
+ effect_uuid_t uuid;
+ if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
+ ALOGW("loadEffect() invalid uuid %s", node->value);
+ return NULL;
+ }
+ return new EffectDesc(root->name, uuid);
+}
+
+status_t AudioPolicyService::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
+{
+ cnode *node = config_find(root, EFFECTS_TAG);
+ if (node == NULL) {
+ return -ENOENT;
+ }
+ node = node->first_child;
+ while (node) {
+ ALOGV("loadEffects() loading effect %s", node->name);
+ EffectDesc *effect = loadEffect(node);
+ if (effect == NULL) {
+ node = node->next;
+ continue;
+ }
+ effects.add(effect);
+ node = node->next;
+ }
+ return NO_ERROR;
+}
+
+status_t AudioPolicyService::loadPreProcessorConfig(const char *path)
+{
+ cnode *root;
+ char *data;
+
+ data = (char *)load_file(path, NULL);
+ if (data == NULL) {
+ return -ENODEV;
+ }
+ root = config_node("", "");
+ config_load(root, data);
+
+ Vector <EffectDesc *> effects;
+ loadEffects(root, effects);
+ loadInputSources(root, effects);
+
+ config_free(root);
+ free(root);
+ free(data);
+
+ return NO_ERROR;
+}
+
+/* implementation of the interface to the policy manager */
+extern "C" {
+
+static audio_io_handle_t aps_open_output(void *service,
+ uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ audio_format_t *pFormat,
+ uint32_t *pChannels,
+ uint32_t *pLatencyMs,
+ audio_policy_output_flags_t flags)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0) {
+ ALOGW("%s: could not get AudioFlinger", __func__);
+ return 0;
+ }
+
+ return af->openOutput(pDevices, pSamplingRate, pFormat, pChannels,
+ pLatencyMs, flags);
+}
+
+static audio_io_handle_t aps_open_dup_output(void *service,
+ audio_io_handle_t output1,
+ audio_io_handle_t output2)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0) {
+ ALOGW("%s: could not get AudioFlinger", __func__);
+ return 0;
+ }
+ return af->openDuplicateOutput(output1, output2);
+}
+
+static int aps_close_output(void *service, audio_io_handle_t output)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0)
+ return PERMISSION_DENIED;
+
+ return af->closeOutput(output);
+}
+
+static int aps_suspend_output(void *service, audio_io_handle_t output)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0) {
+ ALOGW("%s: could not get AudioFlinger", __func__);
+ return PERMISSION_DENIED;
+ }
+
+ return af->suspendOutput(output);
+}
+
+static int aps_restore_output(void *service, audio_io_handle_t output)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0) {
+ ALOGW("%s: could not get AudioFlinger", __func__);
+ return PERMISSION_DENIED;
+ }
+
+ return af->restoreOutput(output);
+}
+
+static audio_io_handle_t aps_open_input(void *service,
+ uint32_t *pDevices,
+ uint32_t *pSamplingRate,
+ audio_format_t *pFormat,
+ uint32_t *pChannels,
+ audio_in_acoustics_t acoustics)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0) {
+ ALOGW("%s: could not get AudioFlinger", __func__);
+ return 0;
+ }
+
+ return af->openInput(pDevices, pSamplingRate, pFormat, pChannels,
+ acoustics);
+}
+
+static int aps_close_input(void *service, audio_io_handle_t input)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0)
+ return PERMISSION_DENIED;
+
+ return af->closeInput(input);
+}
+
+static int aps_set_stream_output(void *service, audio_stream_type_t stream,
+ audio_io_handle_t output)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0)
+ return PERMISSION_DENIED;
+
+ return af->setStreamOutput(stream, output);
+}
+
+static int aps_move_effects(void *service, int session,
+ audio_io_handle_t src_output,
+ audio_io_handle_t dst_output)
+{
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af == 0)
+ return PERMISSION_DENIED;
+
+ return af->moveEffects(session, src_output, dst_output);
+}
+
+static char * aps_get_parameters(void *service, audio_io_handle_t io_handle,
+ const char *keys)
+{
+ String8 result = AudioSystem::getParameters(io_handle, String8(keys));
+ return strdup(result.string());
+}
+
+static void aps_set_parameters(void *service, audio_io_handle_t io_handle,
+ const char *kv_pairs, int delay_ms)
+{
+ AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
+
+ audioPolicyService->setParameters(io_handle, kv_pairs, delay_ms);
+}
+
+static int aps_set_stream_volume(void *service, audio_stream_type_t stream,
+ float volume, audio_io_handle_t output,
+ int delay_ms)
+{
+ AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
+
+ return audioPolicyService->setStreamVolume(stream, volume, output,
+ delay_ms);
+}
+
+static int aps_start_tone(void *service, audio_policy_tone_t tone,
+ audio_stream_type_t stream)
+{
+ AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
+
+ return audioPolicyService->startTone(tone, stream);
+}
+
+static int aps_stop_tone(void *service)
+{
+ AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
+
+ return audioPolicyService->stopTone();
+}
+
+static int aps_set_voice_volume(void *service, float volume, int delay_ms)
+{
+ AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
+
+ return audioPolicyService->setVoiceVolume(volume, delay_ms);
+}
+
+}; // extern "C"
+
+namespace {
+ struct audio_policy_service_ops aps_ops = {
+ open_output : aps_open_output,
+ open_duplicate_output : aps_open_dup_output,
+ close_output : aps_close_output,
+ suspend_output : aps_suspend_output,
+ restore_output : aps_restore_output,
+ open_input : aps_open_input,
+ close_input : aps_close_input,
+ set_stream_volume : aps_set_stream_volume,
+ set_stream_output : aps_set_stream_output,
+ set_parameters : aps_set_parameters,
+ get_parameters : aps_get_parameters,
+ start_tone : aps_start_tone,
+ stop_tone : aps_stop_tone,
+ set_voice_volume : aps_set_voice_volume,
+ move_effects : aps_move_effects,
+ };
+}; // namespace <unnamed>
+
+}; // namespace android
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
new file mode 100644
index 0000000..9ed905d
--- /dev/null
+++ b/services/audioflinger/AudioPolicyService.h
@@ -0,0 +1,324 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_AUDIOPOLICYSERVICE_H
+#define ANDROID_AUDIOPOLICYSERVICE_H
+
+#include <cutils/misc.h>
+#include <cutils/config_utils.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <utils/SortedVector.h>
+#include <binder/BinderService.h>
+#include <system/audio.h>
+#include <system/audio_policy.h>
+#include <hardware/audio_policy.h>
+#include <media/IAudioPolicyService.h>
+#include <media/ToneGenerator.h>
+#include <media/AudioEffect.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class AudioPolicyService :
+ public BinderService<AudioPolicyService>,
+ public BnAudioPolicyService,
+// public AudioPolicyClientInterface,
+ public IBinder::DeathRecipient
+{
+ friend class BinderService<AudioPolicyService>;
+
+public:
+ // for BinderService
+ static const char *getServiceName() { return "media.audio_policy"; }
+
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ //
+ // BnAudioPolicyService (see AudioPolicyInterface for method descriptions)
+ //
+
+ virtual status_t setDeviceConnectionState(audio_devices_t device,
+ audio_policy_dev_state_t state,
+ const char *device_address);
+ virtual audio_policy_dev_state_t getDeviceConnectionState(
+ audio_devices_t device,
+ const char *device_address);
+ virtual status_t setPhoneState(audio_mode_t state);
+ virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
+ virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
+ virtual audio_io_handle_t getOutput(audio_stream_type_t stream,
+ uint32_t samplingRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ uint32_t channels = 0,
+ audio_policy_output_flags_t flags =
+ AUDIO_POLICY_OUTPUT_FLAG_NONE);
+ virtual status_t startOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int session = 0);
+ virtual status_t stopOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int session = 0);
+ virtual void releaseOutput(audio_io_handle_t output);
+ virtual audio_io_handle_t getInput(audio_source_t inputSource,
+ uint32_t samplingRate = 0,
+ audio_format_t format = AUDIO_FORMAT_DEFAULT,
+ uint32_t channels = 0,
+ audio_in_acoustics_t acoustics =
+ (audio_in_acoustics_t)0 /*AUDIO_IN_ACOUSTICS_NONE*/,
+ int audioSession = 0);
+ virtual status_t startInput(audio_io_handle_t input);
+ virtual status_t stopInput(audio_io_handle_t input);
+ virtual void releaseInput(audio_io_handle_t input);
+ virtual status_t initStreamVolume(audio_stream_type_t stream,
+ int indexMin,
+ int indexMax);
+ virtual status_t setStreamVolumeIndex(audio_stream_type_t stream,
+ int index,
+ audio_devices_t device);
+ virtual status_t getStreamVolumeIndex(audio_stream_type_t stream,
+ int *index,
+ audio_devices_t device);
+
+ virtual uint32_t getStrategyForStream(audio_stream_type_t stream);
+ virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream);
+
+ virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
+ virtual status_t registerEffect(effect_descriptor_t *desc,
+ audio_io_handle_t io,
+ uint32_t strategy,
+ int session,
+ int id);
+ virtual status_t unregisterEffect(int id);
+ virtual status_t setEffectEnabled(int id, bool enabled);
+ virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
+
+ virtual status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count);
+ virtual status_t onTransact(
+ uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags);
+
+ // IBinder::DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+
+ //
+ // Helpers for the struct audio_policy_service_ops implementation.
+ // This is used by the audio policy manager for certain operations that
+ // are implemented by the policy service.
+ //
+ virtual void setParameters(audio_io_handle_t ioHandle,
+ const char *keyValuePairs,
+ int delayMs);
+
+ virtual status_t setStreamVolume(audio_stream_type_t stream,
+ float volume,
+ audio_io_handle_t output,
+ int delayMs = 0);
+ virtual status_t startTone(audio_policy_tone_t tone, audio_stream_type_t stream);
+ virtual status_t stopTone();
+ virtual status_t setVoiceVolume(float volume, int delayMs = 0);
+
+private:
+ AudioPolicyService();
+ virtual ~AudioPolicyService();
+
+ status_t dumpInternals(int fd);
+
+ // Thread used for tone playback and to send audio config commands to audio flinger
+ // For tone playback, using a separate thread is necessary to avoid deadlock with mLock because startTone()
+ // and stopTone() are normally called with mLock locked and requesting a tone start or stop will cause
+ // calls to AudioPolicyService and an attempt to lock mLock.
+ // For audio config commands, it is necessary because audio flinger requires that the calling process (user)
+ // has permission to modify audio settings.
+ class AudioCommandThread : public Thread {
+ class AudioCommand;
+ public:
+
+ // commands for tone AudioCommand
+ enum {
+ START_TONE,
+ STOP_TONE,
+ SET_VOLUME,
+ SET_PARAMETERS,
+ SET_VOICE_VOLUME
+ };
+
+ AudioCommandThread (String8 name);
+ virtual ~AudioCommandThread();
+
+ status_t dump(int fd);
+
+ // Thread virtuals
+ virtual void onFirstRef();
+ virtual bool threadLoop();
+
+ void exit();
+ void startToneCommand(ToneGenerator::tone_type type,
+ audio_stream_type_t stream);
+ void stopToneCommand();
+ status_t volumeCommand(audio_stream_type_t stream, float volume,
+ audio_io_handle_t output, int delayMs = 0);
+ status_t parametersCommand(audio_io_handle_t ioHandle,
+ const char *keyValuePairs, int delayMs = 0);
+ status_t voiceVolumeCommand(float volume, int delayMs = 0);
+ void insertCommand_l(AudioCommand *command, int delayMs = 0);
+
+ private:
+ // descriptor for requested tone playback event
+ class AudioCommand {
+
+ public:
+ AudioCommand()
+ : mCommand(-1) {}
+
+ void dump(char* buffer, size_t size);
+
+ int mCommand; // START_TONE, STOP_TONE ...
+ nsecs_t mTime; // time stamp
+ Condition mCond; // condition for status return
+ status_t mStatus; // command status
+ bool mWaitStatus; // true if caller is waiting for status
+ void *mParam; // command parameter (ToneData, VolumeData, ParametersData)
+ };
+
+ class ToneData {
+ public:
+ ToneGenerator::tone_type mType; // tone type (START_TONE only)
+ audio_stream_type_t mStream; // stream type (START_TONE only)
+ };
+
+ class VolumeData {
+ public:
+ audio_stream_type_t mStream;
+ float mVolume;
+ audio_io_handle_t mIO;
+ };
+
+ class ParametersData {
+ public:
+ audio_io_handle_t mIO;
+ String8 mKeyValuePairs;
+ };
+
+ class VoiceVolumeData {
+ public:
+ float mVolume;
+ };
+
+ Mutex mLock;
+ Condition mWaitWorkCV;
+ Vector <AudioCommand *> mAudioCommands; // list of pending commands
+ ToneGenerator *mpToneGenerator; // the tone generator
+ AudioCommand mLastCommand; // last processed command (used by dump)
+ String8 mName; // string used by wake lock fo delayed commands
+ };
+
+ class EffectDesc {
+ public:
+ EffectDesc(const char *name, const effect_uuid_t& uuid) :
+ mName(strdup(name)),
+ mUuid(uuid) { }
+ EffectDesc(const EffectDesc& orig) :
+ mName(strdup(orig.mName)),
+ mUuid(orig.mUuid) {
+ // deep copy mParams
+ for (size_t k = 0; k < orig.mParams.size(); k++) {
+ effect_param_t *origParam = orig.mParams[k];
+ // psize and vsize are rounded up to an int boundary for allocation
+ size_t origSize = sizeof(effect_param_t) +
+ ((origParam->psize + 3) & ~3) +
+ ((origParam->vsize + 3) & ~3);
+ effect_param_t *dupParam = (effect_param_t *) malloc(origSize);
+ memcpy(dupParam, origParam, origSize);
+ // This works because the param buffer allocation is also done by
+ // multiples of 4 bytes originally. In theory we should memcpy only
+ // the actual param size, that is without rounding vsize.
+ mParams.add(dupParam);
+ }
+ }
+ /*virtual*/ ~EffectDesc() {
+ free(mName);
+ for (size_t k = 0; k < mParams.size(); k++) {
+ free(mParams[k]);
+ }
+ }
+ char *mName;
+ effect_uuid_t mUuid;
+ Vector <effect_param_t *> mParams;
+ };
+
+ class InputSourceDesc {
+ public:
+ InputSourceDesc() {}
+ /*virtual*/ ~InputSourceDesc() {
+ for (size_t j = 0; j < mEffects.size(); j++) {
+ delete mEffects[j];
+ }
+ }
+ Vector <EffectDesc *> mEffects;
+ };
+
+
+ class InputDesc {
+ public:
+ InputDesc(int session) : mSessionId(session) {}
+ /*virtual*/ ~InputDesc() {}
+ const int mSessionId;
+ Vector< sp<AudioEffect> >mEffects;
+ };
+
+ static const char * const kInputSourceNames[AUDIO_SOURCE_CNT -1];
+
+ void setPreProcessorEnabled(const InputDesc *inputDesc, bool enabled);
+ status_t loadPreProcessorConfig(const char *path);
+ status_t loadEffects(cnode *root, Vector <EffectDesc *>& effects);
+ EffectDesc *loadEffect(cnode *root);
+ status_t loadInputSources(cnode *root, const Vector <EffectDesc *>& effects);
+ audio_source_t inputSourceNameToEnum(const char *name);
+ InputSourceDesc *loadInputSource(cnode *root, const Vector <EffectDesc *>& effects);
+ void loadEffectParameters(cnode *root, Vector <effect_param_t *>& params);
+ effect_param_t *loadEffectParameter(cnode *root);
+ size_t readParamValue(cnode *node,
+ char *param,
+ size_t *curSize,
+ size_t *totSize);
+ size_t growParamSize(char *param,
+ size_t size,
+ size_t *curSize,
+ size_t *totSize);
+
+ // Internal dump utilities.
+ status_t dumpPermissionDenial(int fd);
+
+
+ mutable Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing
+ // device connection state or routing
+ sp<AudioCommandThread> mAudioCommandThread; // audio commands thread
+ sp<AudioCommandThread> mTonePlaybackThread; // tone playback thread
+ struct audio_policy_device *mpAudioPolicyDev;
+ struct audio_policy *mpAudioPolicy;
+ KeyedVector< audio_source_t, InputSourceDesc* > mInputSources;
+ KeyedVector< audio_io_handle_t, InputDesc* > mInputs;
+};
+
+}; // namespace android
+
+#endif // ANDROID_AUDIOPOLICYSERVICE_H
diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
new file mode 100644
index 0000000..fbb54cf
--- /dev/null
+++ b/services/audioflinger/AudioResampler.cpp
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 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_TAG "AudioResampler"
+//#define LOG_NDEBUG 0
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include "AudioResampler.h"
+#if 0
+#include "AudioResamplerSinc.h"
+#include "AudioResamplerCubic.h"
+#endif
+
+#ifdef __arm__
+#include <machine/cpu-features.h>
+#endif
+
+namespace android {
+
+#ifdef __ARM_HAVE_HALFWORD_MULTIPLY // optimized asm option
+ #define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1
+#endif // __ARM_HAVE_HALFWORD_MULTIPLY
+// ----------------------------------------------------------------------------
+
+class AudioResamplerOrder1 : public AudioResampler {
+public:
+ AudioResamplerOrder1(int bitDepth, int inChannelCount, int32_t sampleRate) :
+ AudioResampler(bitDepth, inChannelCount, sampleRate), mX0L(0), mX0R(0) {
+ }
+ virtual void resample(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider);
+private:
+ // number of bits used in interpolation multiply - 15 bits avoids overflow
+ static const int kNumInterpBits = 15;
+
+ // bits to shift the phase fraction down to avoid overflow
+ static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits;
+
+ void init() {}
+ void resampleMono16(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider);
+ void resampleStereo16(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider);
+#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
+ void AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
+ size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
+ uint32_t &phaseFraction, uint32_t phaseIncrement);
+ void AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
+ size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
+ uint32_t &phaseFraction, uint32_t phaseIncrement);
+#endif // ASM_ARM_RESAMP1
+
+ static inline int32_t Interp(int32_t x0, int32_t x1, uint32_t f) {
+ return x0 + (((x1 - x0) * (int32_t)(f >> kPreInterpShift)) >> kNumInterpBits);
+ }
+ static inline void Advance(size_t* index, uint32_t* frac, uint32_t inc) {
+ *frac += inc;
+ *index += (size_t)(*frac >> kNumPhaseBits);
+ *frac &= kPhaseMask;
+ }
+ int mX0L;
+ int mX0R;
+};
+
+// ----------------------------------------------------------------------------
+AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount,
+ int32_t sampleRate, int quality) {
+
+ // can only create low quality resample now
+ AudioResampler* resampler;
+
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("af.resampler.quality", value, 0)) {
+ quality = atoi(value);
+ ALOGD("forcing AudioResampler quality to %d", quality);
+ }
+
+ if (quality == DEFAULT)
+ quality = LOW_QUALITY;
+
+ switch (quality) {
+ default:
+ case LOW_QUALITY:
+ ALOGV("Create linear Resampler");
+ resampler = new AudioResamplerOrder1(bitDepth, inChannelCount, sampleRate);
+ break;
+#if 0
+ case MED_QUALITY:
+ ALOGV("Create cubic Resampler");
+ resampler = new AudioResamplerCubic(bitDepth, inChannelCount, sampleRate);
+ break;
+ case HIGH_QUALITY:
+ ALOGV("Create sinc Resampler");
+ resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate);
+ break;
+#endif
+ }
+
+ // initialize resampler
+ resampler->init();
+ return resampler;
+}
+
+AudioResampler::AudioResampler(int bitDepth, int inChannelCount,
+ int32_t sampleRate) :
+ mBitDepth(bitDepth), mChannelCount(inChannelCount),
+ mSampleRate(sampleRate), mInSampleRate(sampleRate), mInputIndex(0),
+ mPhaseFraction(0), mLocalTimeFreq(0),
+ mPTS(AudioBufferProvider::kInvalidPTS) {
+ // sanity check on format
+ if ((bitDepth != 16) ||(inChannelCount < 1) || (inChannelCount > 2)) {
+ ALOGE("Unsupported sample format, %d bits, %d channels", bitDepth,
+ inChannelCount);
+ // ALOG_ASSERT(0);
+ }
+
+ // initialize common members
+ mVolume[0] = mVolume[1] = 0;
+ mBuffer.frameCount = 0;
+
+}
+
+AudioResampler::~AudioResampler() {
+}
+
+void AudioResampler::setSampleRate(int32_t inSampleRate) {
+ mInSampleRate = inSampleRate;
+ mPhaseIncrement = (uint32_t)((kPhaseMultiplier * inSampleRate) / mSampleRate);
+}
+
+void AudioResampler::setVolume(int16_t left, int16_t right) {
+ // TODO: Implement anti-zipper filter
+ mVolume[0] = left;
+ mVolume[1] = right;
+}
+
+void AudioResampler::setLocalTimeFreq(uint64_t freq) {
+ mLocalTimeFreq = freq;
+}
+
+void AudioResampler::setPTS(int64_t pts) {
+ mPTS = pts;
+}
+
+int64_t AudioResampler::calculateOutputPTS(int outputFrameIndex) {
+
+ if (mPTS == AudioBufferProvider::kInvalidPTS) {
+ return AudioBufferProvider::kInvalidPTS;
+ } else {
+ return mPTS + ((outputFrameIndex * mLocalTimeFreq) / mSampleRate);
+ }
+}
+
+void AudioResampler::reset() {
+ mInputIndex = 0;
+ mPhaseFraction = 0;
+ mBuffer.frameCount = 0;
+}
+
+// ----------------------------------------------------------------------------
+
+void AudioResamplerOrder1::resample(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider) {
+
+ // should never happen, but we overflow if it does
+ // ALOG_ASSERT(outFrameCount < 32767);
+
+ // select the appropriate resampler
+ switch (mChannelCount) {
+ case 1:
+ resampleMono16(out, outFrameCount, provider);
+ break;
+ case 2:
+ resampleStereo16(out, outFrameCount, provider);
+ break;
+ }
+}
+
+void AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider) {
+
+ int32_t vl = mVolume[0];
+ int32_t vr = mVolume[1];
+
+ size_t inputIndex = mInputIndex;
+ uint32_t phaseFraction = mPhaseFraction;
+ uint32_t phaseIncrement = mPhaseIncrement;
+ size_t outputIndex = 0;
+ size_t outputSampleCount = outFrameCount * 2;
+ size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
+
+ // ALOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d",
+ // outFrameCount, inputIndex, phaseFraction, phaseIncrement);
+
+ while (outputIndex < outputSampleCount) {
+
+ // buffer is empty, fetch a new one
+ while (mBuffer.frameCount == 0) {
+ mBuffer.frameCount = inFrameCount;
+ provider->getNextBuffer(&mBuffer,
+ calculateOutputPTS(outputIndex / 2));
+ if (mBuffer.raw == NULL) {
+ goto resampleStereo16_exit;
+ }
+
+ // ALOGE("New buffer fetched: %d frames", mBuffer.frameCount);
+ if (mBuffer.frameCount > inputIndex) break;
+
+ inputIndex -= mBuffer.frameCount;
+ mX0L = mBuffer.i16[mBuffer.frameCount*2-2];
+ mX0R = mBuffer.i16[mBuffer.frameCount*2-1];
+ provider->releaseBuffer(&mBuffer);
+ // mBuffer.frameCount == 0 now so we reload a new buffer
+ }
+
+ int16_t *in = mBuffer.i16;
+
+ // handle boundary case
+ while (inputIndex == 0) {
+ // ALOGE("boundary case");
+ out[outputIndex++] += vl * Interp(mX0L, in[0], phaseFraction);
+ out[outputIndex++] += vr * Interp(mX0R, in[1], phaseFraction);
+ Advance(&inputIndex, &phaseFraction, phaseIncrement);
+ if (outputIndex == outputSampleCount)
+ break;
+ }
+
+ // process input samples
+ // ALOGE("general case");
+
+#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
+ if (inputIndex + 2 < mBuffer.frameCount) {
+ int32_t* maxOutPt;
+ int32_t maxInIdx;
+
+ maxOutPt = out + (outputSampleCount - 2); // 2 because 2 frames per loop
+ maxInIdx = mBuffer.frameCount - 2;
+ AsmStereo16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr,
+ phaseFraction, phaseIncrement);
+ }
+#endif // ASM_ARM_RESAMP1
+
+ while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) {
+ out[outputIndex++] += vl * Interp(in[inputIndex*2-2],
+ in[inputIndex*2], phaseFraction);
+ out[outputIndex++] += vr * Interp(in[inputIndex*2-1],
+ in[inputIndex*2+1], phaseFraction);
+ Advance(&inputIndex, &phaseFraction, phaseIncrement);
+ }
+
+ // ALOGE("loop done - outputIndex=%d, inputIndex=%d", outputIndex, inputIndex);
+
+ // if done with buffer, save samples
+ if (inputIndex >= mBuffer.frameCount) {
+ inputIndex -= mBuffer.frameCount;
+
+ // ALOGE("buffer done, new input index %d", inputIndex);
+
+ mX0L = mBuffer.i16[mBuffer.frameCount*2-2];
+ mX0R = mBuffer.i16[mBuffer.frameCount*2-1];
+ provider->releaseBuffer(&mBuffer);
+
+ // verify that the releaseBuffer resets the buffer frameCount
+ // ALOG_ASSERT(mBuffer.frameCount == 0);
+ }
+ }
+
+ // ALOGE("output buffer full - outputIndex=%d, inputIndex=%d", outputIndex, inputIndex);
+
+resampleStereo16_exit:
+ // save state
+ mInputIndex = inputIndex;
+ mPhaseFraction = phaseFraction;
+}
+
+void AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider) {
+
+ int32_t vl = mVolume[0];
+ int32_t vr = mVolume[1];
+
+ size_t inputIndex = mInputIndex;
+ uint32_t phaseFraction = mPhaseFraction;
+ uint32_t phaseIncrement = mPhaseIncrement;
+ size_t outputIndex = 0;
+ size_t outputSampleCount = outFrameCount * 2;
+ size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
+
+ // ALOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d",
+ // outFrameCount, inputIndex, phaseFraction, phaseIncrement);
+ while (outputIndex < outputSampleCount) {
+ // buffer is empty, fetch a new one
+ while (mBuffer.frameCount == 0) {
+ mBuffer.frameCount = inFrameCount;
+ provider->getNextBuffer(&mBuffer,
+ calculateOutputPTS(outputIndex / 2));
+ if (mBuffer.raw == NULL) {
+ mInputIndex = inputIndex;
+ mPhaseFraction = phaseFraction;
+ goto resampleMono16_exit;
+ }
+ // ALOGE("New buffer fetched: %d frames", mBuffer.frameCount);
+ if (mBuffer.frameCount > inputIndex) break;
+
+ inputIndex -= mBuffer.frameCount;
+ mX0L = mBuffer.i16[mBuffer.frameCount-1];
+ provider->releaseBuffer(&mBuffer);
+ // mBuffer.frameCount == 0 now so we reload a new buffer
+ }
+ int16_t *in = mBuffer.i16;
+
+ // handle boundary case
+ while (inputIndex == 0) {
+ // ALOGE("boundary case");
+ int32_t sample = Interp(mX0L, in[0], phaseFraction);
+ out[outputIndex++] += vl * sample;
+ out[outputIndex++] += vr * sample;
+ Advance(&inputIndex, &phaseFraction, phaseIncrement);
+ if (outputIndex == outputSampleCount)
+ break;
+ }
+
+ // process input samples
+ // ALOGE("general case");
+
+#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
+ if (inputIndex + 2 < mBuffer.frameCount) {
+ int32_t* maxOutPt;
+ int32_t maxInIdx;
+
+ maxOutPt = out + (outputSampleCount - 2);
+ maxInIdx = (int32_t)mBuffer.frameCount - 2;
+ AsmMono16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr,
+ phaseFraction, phaseIncrement);
+ }
+#endif // ASM_ARM_RESAMP1
+
+ while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) {
+ int32_t sample = Interp(in[inputIndex-1], in[inputIndex],
+ phaseFraction);
+ out[outputIndex++] += vl * sample;
+ out[outputIndex++] += vr * sample;
+ Advance(&inputIndex, &phaseFraction, phaseIncrement);
+ }
+
+
+ // ALOGE("loop done - outputIndex=%d, inputIndex=%d", outputIndex, inputIndex);
+
+ // if done with buffer, save samples
+ if (inputIndex >= mBuffer.frameCount) {
+ inputIndex -= mBuffer.frameCount;
+
+ // ALOGE("buffer done, new input index %d", inputIndex);
+
+ mX0L = mBuffer.i16[mBuffer.frameCount-1];
+ provider->releaseBuffer(&mBuffer);
+
+ // verify that the releaseBuffer resets the buffer frameCount
+ // ALOG_ASSERT(mBuffer.frameCount == 0);
+ }
+ }
+
+ // ALOGE("output buffer full - outputIndex=%d, inputIndex=%d", outputIndex, inputIndex);
+
+resampleMono16_exit:
+ // save state
+ mInputIndex = inputIndex;
+ mPhaseFraction = phaseFraction;
+}
+
+#ifdef ASM_ARM_RESAMP1 // asm optimisation for ResamplerOrder1
+
+/*******************************************************************
+*
+* AsmMono16Loop
+* asm optimized monotonic loop version; one loop is 2 frames
+* Input:
+* in : pointer on input samples
+* maxOutPt : pointer on first not filled
+* maxInIdx : index on first not used
+* outputIndex : pointer on current output index
+* out : pointer on output buffer
+* inputIndex : pointer on current input index
+* vl, vr : left and right gain
+* phaseFraction : pointer on current phase fraction
+* phaseIncrement
+* Ouput:
+* outputIndex :
+* out : updated buffer
+* inputIndex : index of next to use
+* phaseFraction : phase fraction for next interpolation
+*
+*******************************************************************/
+__attribute__((noinline))
+void AudioResamplerOrder1::AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
+ size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
+ uint32_t &phaseFraction, uint32_t phaseIncrement)
+{
+#define MO_PARAM5 "36" // offset of parameter 5 (outputIndex)
+
+ asm(
+ "stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n"
+ // get parameters
+ " ldr r6, [sp, #" MO_PARAM5 " + 20]\n" // &phaseFraction
+ " ldr r6, [r6]\n" // phaseFraction
+ " ldr r7, [sp, #" MO_PARAM5 " + 8]\n" // &inputIndex
+ " ldr r7, [r7]\n" // inputIndex
+ " ldr r8, [sp, #" MO_PARAM5 " + 4]\n" // out
+ " ldr r0, [sp, #" MO_PARAM5 " + 0]\n" // &outputIndex
+ " ldr r0, [r0]\n" // outputIndex
+ " add r8, r0, asl #2\n" // curOut
+ " ldr r9, [sp, #" MO_PARAM5 " + 24]\n" // phaseIncrement
+ " ldr r10, [sp, #" MO_PARAM5 " + 12]\n" // vl
+ " ldr r11, [sp, #" MO_PARAM5 " + 16]\n" // vr
+
+ // r0 pin, x0, Samp
+
+ // r1 in
+ // r2 maxOutPt
+ // r3 maxInIdx
+
+ // r4 x1, i1, i3, Out1
+ // r5 out0
+
+ // r6 frac
+ // r7 inputIndex
+ // r8 curOut
+
+ // r9 inc
+ // r10 vl
+ // r11 vr
+
+ // r12
+ // r13 sp
+ // r14
+
+ // the following loop works on 2 frames
+
+ "1:\n"
+ " cmp r8, r2\n" // curOut - maxCurOut
+ " bcs 2f\n"
+
+#define MO_ONE_FRAME \
+ " add r0, r1, r7, asl #1\n" /* in + inputIndex */\
+ " ldrsh r4, [r0]\n" /* in[inputIndex] */\
+ " ldr r5, [r8]\n" /* out[outputIndex] */\
+ " ldrsh r0, [r0, #-2]\n" /* in[inputIndex-1] */\
+ " bic r6, r6, #0xC0000000\n" /* phaseFraction & ... */\
+ " sub r4, r4, r0\n" /* in[inputIndex] - in[inputIndex-1] */\
+ " mov r4, r4, lsl #2\n" /* <<2 */\
+ " smulwt r4, r4, r6\n" /* (x1-x0)*.. */\
+ " add r6, r6, r9\n" /* phaseFraction + phaseIncrement */\
+ " add r0, r0, r4\n" /* x0 - (..) */\
+ " mla r5, r0, r10, r5\n" /* vl*interp + out[] */\
+ " ldr r4, [r8, #4]\n" /* out[outputIndex+1] */\
+ " str r5, [r8], #4\n" /* out[outputIndex++] = ... */\
+ " mla r4, r0, r11, r4\n" /* vr*interp + out[] */\
+ " add r7, r7, r6, lsr #30\n" /* inputIndex + phaseFraction>>30 */\
+ " str r4, [r8], #4\n" /* out[outputIndex++] = ... */
+
+ MO_ONE_FRAME // frame 1
+ MO_ONE_FRAME // frame 2
+
+ " cmp r7, r3\n" // inputIndex - maxInIdx
+ " bcc 1b\n"
+ "2:\n"
+
+ " bic r6, r6, #0xC0000000\n" // phaseFraction & ...
+ // save modified values
+ " ldr r0, [sp, #" MO_PARAM5 " + 20]\n" // &phaseFraction
+ " str r6, [r0]\n" // phaseFraction
+ " ldr r0, [sp, #" MO_PARAM5 " + 8]\n" // &inputIndex
+ " str r7, [r0]\n" // inputIndex
+ " ldr r0, [sp, #" MO_PARAM5 " + 4]\n" // out
+ " sub r8, r0\n" // curOut - out
+ " asr r8, #2\n" // new outputIndex
+ " ldr r0, [sp, #" MO_PARAM5 " + 0]\n" // &outputIndex
+ " str r8, [r0]\n" // save outputIndex
+
+ " ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}\n"
+ );
+}
+
+/*******************************************************************
+*
+* AsmStereo16Loop
+* asm optimized stereo loop version; one loop is 2 frames
+* Input:
+* in : pointer on input samples
+* maxOutPt : pointer on first not filled
+* maxInIdx : index on first not used
+* outputIndex : pointer on current output index
+* out : pointer on output buffer
+* inputIndex : pointer on current input index
+* vl, vr : left and right gain
+* phaseFraction : pointer on current phase fraction
+* phaseIncrement
+* Ouput:
+* outputIndex :
+* out : updated buffer
+* inputIndex : index of next to use
+* phaseFraction : phase fraction for next interpolation
+*
+*******************************************************************/
+__attribute__((noinline))
+void AudioResamplerOrder1::AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
+ size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
+ uint32_t &phaseFraction, uint32_t phaseIncrement)
+{
+#define ST_PARAM5 "40" // offset of parameter 5 (outputIndex)
+ asm(
+ "stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n"
+ // get parameters
+ " ldr r6, [sp, #" ST_PARAM5 " + 20]\n" // &phaseFraction
+ " ldr r6, [r6]\n" // phaseFraction
+ " ldr r7, [sp, #" ST_PARAM5 " + 8]\n" // &inputIndex
+ " ldr r7, [r7]\n" // inputIndex
+ " ldr r8, [sp, #" ST_PARAM5 " + 4]\n" // out
+ " ldr r0, [sp, #" ST_PARAM5 " + 0]\n" // &outputIndex
+ " ldr r0, [r0]\n" // outputIndex
+ " add r8, r0, asl #2\n" // curOut
+ " ldr r9, [sp, #" ST_PARAM5 " + 24]\n" // phaseIncrement
+ " ldr r10, [sp, #" ST_PARAM5 " + 12]\n" // vl
+ " ldr r11, [sp, #" ST_PARAM5 " + 16]\n" // vr
+
+ // r0 pin, x0, Samp
+
+ // r1 in
+ // r2 maxOutPt
+ // r3 maxInIdx
+
+ // r4 x1, i1, i3, out1
+ // r5 out0
+
+ // r6 frac
+ // r7 inputIndex
+ // r8 curOut
+
+ // r9 inc
+ // r10 vl
+ // r11 vr
+
+ // r12 temporary
+ // r13 sp
+ // r14
+
+ "3:\n"
+ " cmp r8, r2\n" // curOut - maxCurOut
+ " bcs 4f\n"
+
+#define ST_ONE_FRAME \
+ " bic r6, r6, #0xC0000000\n" /* phaseFraction & ... */\
+\
+ " add r0, r1, r7, asl #2\n" /* in + 2*inputIndex */\
+\
+ " ldrsh r4, [r0]\n" /* in[2*inputIndex] */\
+ " ldr r5, [r8]\n" /* out[outputIndex] */\
+ " ldrsh r12, [r0, #-4]\n" /* in[2*inputIndex-2] */\
+ " sub r4, r4, r12\n" /* in[2*InputIndex] - in[2*InputIndex-2] */\
+ " mov r4, r4, lsl #2\n" /* <<2 */\
+ " smulwt r4, r4, r6\n" /* (x1-x0)*.. */\
+ " add r12, r12, r4\n" /* x0 - (..) */\
+ " mla r5, r12, r10, r5\n" /* vl*interp + out[] */\
+ " ldr r4, [r8, #4]\n" /* out[outputIndex+1] */\
+ " str r5, [r8], #4\n" /* out[outputIndex++] = ... */\
+\
+ " ldrsh r12, [r0, #+2]\n" /* in[2*inputIndex+1] */\
+ " ldrsh r0, [r0, #-2]\n" /* in[2*inputIndex-1] */\
+ " sub r12, r12, r0\n" /* in[2*InputIndex] - in[2*InputIndex-2] */\
+ " mov r12, r12, lsl #2\n" /* <<2 */\
+ " smulwt r12, r12, r6\n" /* (x1-x0)*.. */\
+ " add r12, r0, r12\n" /* x0 - (..) */\
+ " mla r4, r12, r11, r4\n" /* vr*interp + out[] */\
+ " str r4, [r8], #4\n" /* out[outputIndex++] = ... */\
+\
+ " add r6, r6, r9\n" /* phaseFraction + phaseIncrement */\
+ " add r7, r7, r6, lsr #30\n" /* inputIndex + phaseFraction>>30 */
+
+ ST_ONE_FRAME // frame 1
+ ST_ONE_FRAME // frame 1
+
+ " cmp r7, r3\n" // inputIndex - maxInIdx
+ " bcc 3b\n"
+ "4:\n"
+
+ " bic r6, r6, #0xC0000000\n" // phaseFraction & ...
+ // save modified values
+ " ldr r0, [sp, #" ST_PARAM5 " + 20]\n" // &phaseFraction
+ " str r6, [r0]\n" // phaseFraction
+ " ldr r0, [sp, #" ST_PARAM5 " + 8]\n" // &inputIndex
+ " str r7, [r0]\n" // inputIndex
+ " ldr r0, [sp, #" ST_PARAM5 " + 4]\n" // out
+ " sub r8, r0\n" // curOut - out
+ " asr r8, #2\n" // new outputIndex
+ " ldr r0, [sp, #" ST_PARAM5 " + 0]\n" // &outputIndex
+ " str r8, [r0]\n" // save outputIndex
+
+ " ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, pc}\n"
+ );
+}
+
+#endif // ASM_ARM_RESAMP1
+
+
+// ----------------------------------------------------------------------------
+
+} // namespace android
diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h
new file mode 100644
index 0000000..1610e00
--- /dev/null
+++ b/services/audioflinger/AudioResampler.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 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_RESAMPLER_H
+#define ANDROID_AUDIO_RESAMPLER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "AudioBufferProvider.h"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class AudioResampler {
+public:
+ // Determines quality of SRC.
+ // LOW_QUALITY: linear interpolator (1st order)
+ // MED_QUALITY: cubic interpolator (3rd order)
+ // HIGH_QUALITY: fixed multi-tap FIR (e.g. 48KHz->44.1KHz)
+ // NOTE: high quality SRC will only be supported for
+ // certain fixed rate conversions. Sample rate cannot be
+ // changed dynamically.
+ enum src_quality {
+ DEFAULT=0,
+ LOW_QUALITY=1,
+ MED_QUALITY=2,
+ HIGH_QUALITY=3
+ };
+
+ static AudioResampler* create(int bitDepth, int inChannelCount,
+ int32_t sampleRate, int quality=DEFAULT);
+
+ virtual ~AudioResampler();
+
+ virtual void init() = 0;
+ virtual void setSampleRate(int32_t inSampleRate);
+ virtual void setVolume(int16_t left, int16_t right);
+ virtual void setLocalTimeFreq(uint64_t freq);
+
+ // set the PTS of the next buffer output by the resampler
+ virtual void setPTS(int64_t pts);
+
+ virtual void resample(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider) = 0;
+
+ virtual void reset();
+ virtual size_t getUnreleasedFrames() const { return mInputIndex; }
+
+protected:
+ // number of bits for phase fraction - 30 bits allows nearly 2x downsampling
+ static const int kNumPhaseBits = 30;
+
+ // phase mask for fraction
+ static const uint32_t kPhaseMask = (1LU<<kNumPhaseBits)-1;
+
+ // multiplier to calculate fixed point phase increment
+ static const double kPhaseMultiplier = 1L << kNumPhaseBits;
+
+ AudioResampler(int bitDepth, int inChannelCount, int32_t sampleRate);
+
+ // prevent copying
+ AudioResampler(const AudioResampler&);
+ AudioResampler& operator=(const AudioResampler&);
+
+ int64_t calculateOutputPTS(int outputFrameIndex);
+
+ const int32_t mBitDepth;
+ const int32_t mChannelCount;
+ const int32_t mSampleRate;
+ int32_t mInSampleRate;
+ AudioBufferProvider::Buffer mBuffer;
+ union {
+ int16_t mVolume[2];
+ uint32_t mVolumeRL;
+ };
+ int16_t mTargetVolume[2];
+ size_t mInputIndex;
+ int32_t mPhaseIncrement;
+ uint32_t mPhaseFraction;
+ uint64_t mLocalTimeFreq;
+ int64_t mPTS;
+};
+
+// ----------------------------------------------------------------------------
+}
+; // namespace android
+
+#endif // ANDROID_AUDIO_RESAMPLER_H
diff --git a/services/audioflinger/AudioResamplerCubic.cpp b/services/audioflinger/AudioResamplerCubic.cpp
new file mode 100644
index 0000000..18e59e9
--- /dev/null
+++ b/services/audioflinger/AudioResamplerCubic.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 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_TAG "AudioSRC"
+
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+
+#include "AudioResampler.h"
+#include "AudioResamplerCubic.h"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+void AudioResamplerCubic::init() {
+ memset(&left, 0, sizeof(state));
+ memset(&right, 0, sizeof(state));
+}
+
+void AudioResamplerCubic::resample(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider) {
+
+ // should never happen, but we overflow if it does
+ // ALOG_ASSERT(outFrameCount < 32767);
+
+ // select the appropriate resampler
+ switch (mChannelCount) {
+ case 1:
+ resampleMono16(out, outFrameCount, provider);
+ break;
+ case 2:
+ resampleStereo16(out, outFrameCount, provider);
+ break;
+ }
+}
+
+void AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider) {
+
+ int32_t vl = mVolume[0];
+ int32_t vr = mVolume[1];
+
+ size_t inputIndex = mInputIndex;
+ uint32_t phaseFraction = mPhaseFraction;
+ uint32_t phaseIncrement = mPhaseIncrement;
+ size_t outputIndex = 0;
+ size_t outputSampleCount = outFrameCount * 2;
+ size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
+
+ // fetch first buffer
+ if (mBuffer.frameCount == 0) {
+ mBuffer.frameCount = inFrameCount;
+ provider->getNextBuffer(&mBuffer, mPTS);
+ if (mBuffer.raw == NULL)
+ return;
+ // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
+ }
+ int16_t *in = mBuffer.i16;
+
+ while (outputIndex < outputSampleCount) {
+ int32_t sample;
+ int32_t x;
+
+ // calculate output sample
+ x = phaseFraction >> kPreInterpShift;
+ out[outputIndex++] += vl * interp(&left, x);
+ out[outputIndex++] += vr * interp(&right, x);
+ // out[outputIndex++] += vr * in[inputIndex*2];
+
+ // increment phase
+ phaseFraction += phaseIncrement;
+ uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits);
+ phaseFraction &= kPhaseMask;
+
+ // time to fetch another sample
+ while (indexIncrement--) {
+
+ inputIndex++;
+ if (inputIndex == mBuffer.frameCount) {
+ inputIndex = 0;
+ provider->releaseBuffer(&mBuffer);
+ mBuffer.frameCount = inFrameCount;
+ provider->getNextBuffer(&mBuffer,
+ calculateOutputPTS(outputIndex / 2));
+ if (mBuffer.raw == NULL)
+ goto save_state; // ugly, but efficient
+ in = mBuffer.i16;
+ // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount);
+ }
+
+ // advance sample state
+ advance(&left, in[inputIndex*2]);
+ advance(&right, in[inputIndex*2+1]);
+ }
+ }
+
+save_state:
+ // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
+ mInputIndex = inputIndex;
+ mPhaseFraction = phaseFraction;
+}
+
+void AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider) {
+
+ int32_t vl = mVolume[0];
+ int32_t vr = mVolume[1];
+
+ size_t inputIndex = mInputIndex;
+ uint32_t phaseFraction = mPhaseFraction;
+ uint32_t phaseIncrement = mPhaseIncrement;
+ size_t outputIndex = 0;
+ size_t outputSampleCount = outFrameCount * 2;
+ size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
+
+ // fetch first buffer
+ if (mBuffer.frameCount == 0) {
+ mBuffer.frameCount = inFrameCount;
+ provider->getNextBuffer(&mBuffer, mPTS);
+ if (mBuffer.raw == NULL)
+ return;
+ // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount);
+ }
+ int16_t *in = mBuffer.i16;
+
+ while (outputIndex < outputSampleCount) {
+ int32_t sample;
+ int32_t x;
+
+ // calculate output sample
+ x = phaseFraction >> kPreInterpShift;
+ sample = interp(&left, x);
+ out[outputIndex++] += vl * sample;
+ out[outputIndex++] += vr * sample;
+
+ // increment phase
+ phaseFraction += phaseIncrement;
+ uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits);
+ phaseFraction &= kPhaseMask;
+
+ // time to fetch another sample
+ while (indexIncrement--) {
+
+ inputIndex++;
+ if (inputIndex == mBuffer.frameCount) {
+ inputIndex = 0;
+ provider->releaseBuffer(&mBuffer);
+ mBuffer.frameCount = inFrameCount;
+ provider->getNextBuffer(&mBuffer,
+ calculateOutputPTS(outputIndex / 2));
+ if (mBuffer.raw == NULL)
+ goto save_state; // ugly, but efficient
+ // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
+ in = mBuffer.i16;
+ }
+
+ // advance sample state
+ advance(&left, in[inputIndex]);
+ }
+ }
+
+save_state:
+ // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
+ mInputIndex = inputIndex;
+ mPhaseFraction = phaseFraction;
+}
+
+// ----------------------------------------------------------------------------
+}
+; // namespace android
diff --git a/services/audioflinger/AudioResamplerCubic.h b/services/audioflinger/AudioResamplerCubic.h
new file mode 100644
index 0000000..892785a
--- /dev/null
+++ b/services/audioflinger/AudioResamplerCubic.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 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_RESAMPLER_CUBIC_H
+#define ANDROID_AUDIO_RESAMPLER_CUBIC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+
+#include "AudioResampler.h"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class AudioResamplerCubic : public AudioResampler {
+public:
+ AudioResamplerCubic(int bitDepth, int inChannelCount, int32_t sampleRate) :
+ AudioResampler(bitDepth, inChannelCount, sampleRate) {
+ }
+ virtual void resample(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider);
+private:
+ // number of bits used in interpolation multiply - 14 bits avoids overflow
+ static const int kNumInterpBits = 14;
+
+ // bits to shift the phase fraction down to avoid overflow
+ static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits;
+ typedef struct {
+ int32_t a, b, c, y0, y1, y2, y3;
+ } state;
+ void init();
+ void resampleMono16(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider);
+ void resampleStereo16(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider);
+ static inline int32_t interp(state* p, int32_t x) {
+ return (((((p->a * x >> 14) + p->b) * x >> 14) + p->c) * x >> 14) + p->y1;
+ }
+ static inline void advance(state* p, int16_t in) {
+ p->y0 = p->y1;
+ p->y1 = p->y2;
+ p->y2 = p->y3;
+ p->y3 = in;
+ p->a = (3 * (p->y1 - p->y2) - p->y0 + p->y3) >> 1;
+ p->b = (p->y2 << 1) + p->y0 - (((5 * p->y1 + p->y3)) >> 1);
+ p->c = (p->y2 - p->y0) >> 1;
+ }
+ state left, right;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif /*ANDROID_AUDIO_RESAMPLER_CUBIC_H*/
diff --git a/services/audioflinger/AudioResamplerSinc.cpp b/services/audioflinger/AudioResamplerSinc.cpp
new file mode 100644
index 0000000..76662d8
--- /dev/null
+++ b/services/audioflinger/AudioResamplerSinc.cpp
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 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 <string.h>
+#include "AudioResamplerSinc.h"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+
+/*
+ * These coeficients are computed with the "fir" utility found in
+ * tools/resampler_tools
+ * TODO: A good optimization would be to transpose this matrix, to take
+ * better advantage of the data-cache.
+ */
+const int32_t AudioResamplerSinc::mFirCoefsUp[] = {
+ 0x7fffffff, 0x7f15d078, 0x7c5e0da6, 0x77ecd867, 0x71e2e251, 0x6a6c304a, 0x61be7269, 0x58170412, 0x4db8ab05, 0x42e92ea6, 0x37eee214, 0x2d0e3bb1, 0x22879366, 0x18951e95, 0x0f693d0d, 0x072d2621,
+ 0x00000000, 0xf9f66655, 0xf51a5fd7, 0xf16bbd84, 0xeee0d9ac, 0xed67a922, 0xece70de6, 0xed405897, 0xee50e505, 0xeff3be30, 0xf203370f, 0xf45a6741, 0xf6d67d53, 0xf957db66, 0xfbc2f647, 0xfe00f2b9,
+ 0x00000000, 0x01b37218, 0x0313a0c6, 0x041d930d, 0x04d28057, 0x053731b0, 0x05534dff, 0x05309bfd, 0x04da440d, 0x045c1aee, 0x03c1fcdd, 0x03173ef5, 0x02663ae8, 0x01b7f736, 0x0113ec79, 0x007fe6a9,
+ 0x00000000, 0xff96b229, 0xff44f99f, 0xff0a86be, 0xfee5f803, 0xfed518fd, 0xfed521fd, 0xfee2f4fd, 0xfefb54f8, 0xff1b159b, 0xff3f4203, 0xff6539e0, 0xff8ac502, 0xffae1ddd, 0xffcdf3f9, 0xffe96798,
+ 0x00000000, 0x00119de6, 0x001e6b7e, 0x0026cb7a, 0x002b4830, 0x002c83d6, 0x002b2a82, 0x0027e67a, 0x002356f9, 0x001e098e, 0x001875e4, 0x0012fbbe, 0x000de2d1, 0x00095c10, 0x00058414, 0x00026636,
+ 0x00000000, 0xfffe44a9, 0xfffd206d, 0xfffc7b7f, 0xfffc3c8f, 0xfffc4ac2, 0xfffc8f2b, 0xfffcf5c4, 0xfffd6df3, 0xfffdeab2, 0xfffe6275, 0xfffececf, 0xffff2c07, 0xffff788c, 0xffffb471, 0xffffe0f2,
+ 0x00000000, 0x000013e6, 0x00001f03, 0x00002396, 0x00002399, 0x000020b6, 0x00001c3c, 0x00001722, 0x00001216, 0x00000d81, 0x0000099c, 0x0000067c, 0x00000419, 0x0000025f, 0x00000131, 0x00000070,
+ 0x00000000, 0xffffffc7, 0xffffffb3, 0xffffffb3, 0xffffffbe, 0xffffffcd, 0xffffffdb, 0xffffffe7, 0xfffffff0, 0xfffffff7, 0xfffffffb, 0xfffffffe, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000 // this one is needed for lerping the last coefficient
+};
+
+/*
+ * These coefficients are optimized for 48KHz -> 44.1KHz (stop-band at 22.050KHz)
+ * It's possible to use the above coefficient for any down-sampling
+ * at the expense of a slower processing loop (we can interpolate
+ * these coefficient from the above by "Stretching" them in time).
+ */
+const int32_t AudioResamplerSinc::mFirCoefsDown[] = {
+ 0x7fffffff, 0x7f55e46d, 0x7d5b4c60, 0x7a1b4b98, 0x75a7fb14, 0x7019f0bd, 0x698f875a, 0x622bfd59, 0x5a167256, 0x5178cc54, 0x487e8e6c, 0x3f53aae8, 0x36235ad4, 0x2d17047b, 0x245539ab, 0x1c00d540,
+ 0x14383e57, 0x0d14d5ca, 0x06aa910b, 0x0107c38b, 0xfc351654, 0xf835abae, 0xf5076b45, 0xf2a37202, 0xf0fe9faa, 0xf00a3bbd, 0xefb4aa81, 0xefea2b05, 0xf0959716, 0xf1a11e83, 0xf2f6f7a0, 0xf481fff4,
+ 0xf62e48ce, 0xf7e98ca5, 0xf9a38b4c, 0xfb4e4bfa, 0xfcde456f, 0xfe4a6d30, 0xff8c2fdf, 0x009f5555, 0x0181d393, 0x0233940f, 0x02b62f06, 0x030ca07d, 0x033afa62, 0x03461725, 0x03334f83, 0x030835fa,
+ 0x02ca59cc, 0x027f12d1, 0x022b570d, 0x01d39a49, 0x017bb78f, 0x0126e414, 0x00d7aaaf, 0x008feec7, 0x0050f584, 0x001b73e3, 0xffefa063, 0xffcd46ed, 0xffb3ddcd, 0xffa29aaa, 0xff988691, 0xff949066,
+ 0xff959d24, 0xff9a959e, 0xffa27195, 0xffac4011, 0xffb72d2b, 0xffc28569, 0xffcdb706, 0xffd85171, 0xffe20364, 0xffea97e9, 0xfff1f2b2, 0xfff80c06, 0xfffcec92, 0x0000a955, 0x00035fd8, 0x000532cf,
+ 0x00064735, 0x0006c1f9, 0x0006c62d, 0x000673ba, 0x0005e68f, 0x00053630, 0x000475a3, 0x0003b397, 0x0002fac1, 0x00025257, 0x0001be9e, 0x0001417a, 0x0000dafd, 0x000089eb, 0x00004c28, 0x00001f1d,
+ 0x00000000, 0xffffec10, 0xffffe0be, 0xffffdbc5, 0xffffdb39, 0xffffdd8b, 0xffffe182, 0xffffe638, 0xffffeb0a, 0xffffef8f, 0xfffff38b, 0xfffff6e3, 0xfffff993, 0xfffffba6, 0xfffffd30, 0xfffffe4a,
+ 0xffffff09, 0xffffff85, 0xffffffd1, 0xfffffffb, 0x0000000f, 0x00000016, 0x00000015, 0x00000012, 0x0000000d, 0x00000009, 0x00000006, 0x00000003, 0x00000002, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000000 // this one is needed for lerping the last coefficient
+};
+
+// ----------------------------------------------------------------------------
+
+static inline
+int32_t mulRL(int left, int32_t in, uint32_t vRL)
+{
+#if defined(__arm__) && !defined(__thumb__)
+ int32_t out;
+ if (left) {
+ asm( "smultb %[out], %[in], %[vRL] \n"
+ : [out]"=r"(out)
+ : [in]"%r"(in), [vRL]"r"(vRL)
+ : );
+ } else {
+ asm( "smultt %[out], %[in], %[vRL] \n"
+ : [out]"=r"(out)
+ : [in]"%r"(in), [vRL]"r"(vRL)
+ : );
+ }
+ return out;
+#else
+ if (left) {
+ return int16_t(in>>16) * int16_t(vRL&0xFFFF);
+ } else {
+ return int16_t(in>>16) * int16_t(vRL>>16);
+ }
+#endif
+}
+
+static inline
+int32_t mulAdd(int16_t in, int32_t v, int32_t a)
+{
+#if defined(__arm__) && !defined(__thumb__)
+ int32_t out;
+ asm( "smlawb %[out], %[v], %[in], %[a] \n"
+ : [out]"=r"(out)
+ : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
+ : );
+ return out;
+#else
+ return a + in * (v>>16);
+ // improved precision
+ // return a + in * (v>>16) + ((in * (v & 0xffff)) >> 16);
+#endif
+}
+
+static inline
+int32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a)
+{
+#if defined(__arm__) && !defined(__thumb__)
+ int32_t out;
+ if (left) {
+ asm( "smlawb %[out], %[v], %[inRL], %[a] \n"
+ : [out]"=r"(out)
+ : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
+ : );
+ } else {
+ asm( "smlawt %[out], %[v], %[inRL], %[a] \n"
+ : [out]"=r"(out)
+ : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
+ : );
+ }
+ return out;
+#else
+ if (left) {
+ return a + (int16_t(inRL&0xFFFF) * (v>>16));
+ //improved precision
+ // return a + (int16_t(inRL&0xFFFF) * (v>>16)) + ((int16_t(inRL&0xFFFF) * (v & 0xffff)) >> 16);
+ } else {
+ return a + (int16_t(inRL>>16) * (v>>16));
+ }
+#endif
+}
+
+// ----------------------------------------------------------------------------
+
+AudioResamplerSinc::AudioResamplerSinc(int bitDepth,
+ int inChannelCount, int32_t sampleRate)
+ : AudioResampler(bitDepth, inChannelCount, sampleRate),
+ mState(0)
+{
+ /*
+ * Layout of the state buffer for 32 tap:
+ *
+ * "present" sample beginning of 2nd buffer
+ * v v
+ * 0 01 2 23 3
+ * 0 F0 0 F0 F
+ * [pppppppppppppppInnnnnnnnnnnnnnnnpppppppppppppppInnnnnnnnnnnnnnnn]
+ * ^ ^ head
+ *
+ * p = past samples, convoluted with the (p)ositive side of sinc()
+ * n = future samples, convoluted with the (n)egative side of sinc()
+ * r = extra space for implementing the ring buffer
+ *
+ */
+
+ const size_t numCoefs = 2*halfNumCoefs;
+ const size_t stateSize = numCoefs * inChannelCount * 2;
+ mState = new int16_t[stateSize];
+ memset(mState, 0, sizeof(int16_t)*stateSize);
+ mImpulse = mState + (halfNumCoefs-1)*inChannelCount;
+ mRingFull = mImpulse + (numCoefs+1)*inChannelCount;
+}
+
+AudioResamplerSinc::~AudioResamplerSinc()
+{
+ delete [] mState;
+}
+
+void AudioResamplerSinc::init() {
+}
+
+void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider)
+{
+ mFirCoefs = (mInSampleRate <= mSampleRate) ? mFirCoefsUp : mFirCoefsDown;
+
+ // select the appropriate resampler
+ switch (mChannelCount) {
+ case 1:
+ resample<1>(out, outFrameCount, provider);
+ break;
+ case 2:
+ resample<2>(out, outFrameCount, provider);
+ break;
+ }
+}
+
+
+template<int CHANNELS>
+void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider)
+{
+ int16_t* impulse = mImpulse;
+ uint32_t vRL = mVolumeRL;
+ size_t inputIndex = mInputIndex;
+ uint32_t phaseFraction = mPhaseFraction;
+ uint32_t phaseIncrement = mPhaseIncrement;
+ size_t outputIndex = 0;
+ size_t outputSampleCount = outFrameCount * 2;
+ size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
+
+ while (outputIndex < outputSampleCount) {
+ // buffer is empty, fetch a new one
+ while (mBuffer.frameCount == 0) {
+ mBuffer.frameCount = inFrameCount;
+ provider->getNextBuffer(&mBuffer,
+ calculateOutputPTS(outputIndex / 2));
+ if (mBuffer.raw == NULL) {
+ goto resample_exit;
+ }
+ const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
+ if (phaseIndex == 1) {
+ // read one frame
+ read<CHANNELS>(impulse, phaseFraction, mBuffer.i16, inputIndex);
+ } else if (phaseIndex == 2) {
+ // read 2 frames
+ read<CHANNELS>(impulse, phaseFraction, mBuffer.i16, inputIndex);
+ inputIndex++;
+ if (inputIndex >= mBuffer.frameCount) {
+ inputIndex -= mBuffer.frameCount;
+ provider->releaseBuffer(&mBuffer);
+ } else {
+ read<CHANNELS>(impulse, phaseFraction, mBuffer.i16, inputIndex);
+ }
+ }
+ }
+ int16_t *in = mBuffer.i16;
+ const size_t frameCount = mBuffer.frameCount;
+
+ // Always read-in the first samples from the input buffer
+ int16_t* head = impulse + halfNumCoefs*CHANNELS;
+ head[0] = in[inputIndex*CHANNELS + 0];
+ if (CHANNELS == 2)
+ head[1] = in[inputIndex*CHANNELS + 1];
+
+ // handle boundary case
+ int32_t l, r;
+ while (outputIndex < outputSampleCount) {
+ filterCoefficient<CHANNELS>(l, r, phaseFraction, impulse);
+ out[outputIndex++] += 2 * mulRL(1, l, vRL);
+ out[outputIndex++] += 2 * mulRL(0, r, vRL);
+
+ phaseFraction += phaseIncrement;
+ const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
+ if (phaseIndex == 1) {
+ inputIndex++;
+ if (inputIndex >= frameCount)
+ break; // need a new buffer
+ read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
+ } else if (phaseIndex == 2) { // maximum value
+ inputIndex++;
+ if (inputIndex >= frameCount)
+ break; // 0 frame available, 2 frames needed
+ // read first frame
+ read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
+ inputIndex++;
+ if (inputIndex >= frameCount)
+ break; // 0 frame available, 1 frame needed
+ // read second frame
+ read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
+ }
+ }
+
+ // if done with buffer, save samples
+ if (inputIndex >= frameCount) {
+ inputIndex -= frameCount;
+ provider->releaseBuffer(&mBuffer);
+ }
+ }
+
+resample_exit:
+ mImpulse = impulse;
+ mInputIndex = inputIndex;
+ mPhaseFraction = phaseFraction;
+}
+
+template<int CHANNELS>
+/***
+* read()
+*
+* This function reads only one frame from input buffer and writes it in
+* state buffer
+*
+**/
+void AudioResamplerSinc::read(
+ int16_t*& impulse, uint32_t& phaseFraction,
+ const int16_t* in, size_t inputIndex)
+{
+ const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
+ impulse += CHANNELS;
+ phaseFraction -= 1LU<<kNumPhaseBits;
+ if (impulse >= mRingFull) {
+ const size_t stateSize = (halfNumCoefs*2)*CHANNELS;
+ memcpy(mState, mState+stateSize, sizeof(int16_t)*stateSize);
+ impulse -= stateSize;
+ }
+ int16_t* head = impulse + halfNumCoefs*CHANNELS;
+ head[0] = in[inputIndex*CHANNELS + 0];
+ if (CHANNELS == 2)
+ head[1] = in[inputIndex*CHANNELS + 1];
+}
+
+template<int CHANNELS>
+void AudioResamplerSinc::filterCoefficient(
+ int32_t& l, int32_t& r, uint32_t phase, const int16_t *samples)
+{
+ // compute the index of the coefficient on the positive side and
+ // negative side
+ uint32_t indexP = (phase & cMask) >> cShift;
+ uint16_t lerpP = (phase & pMask) >> pShift;
+ uint32_t indexN = (-phase & cMask) >> cShift;
+ uint16_t lerpN = (-phase & pMask) >> pShift;
+ if ((indexP == 0) && (lerpP == 0)) {
+ indexN = cMask >> cShift;
+ lerpN = pMask >> pShift;
+ }
+
+ l = 0;
+ r = 0;
+ const int32_t* coefs = mFirCoefs;
+ const int16_t *sP = samples;
+ const int16_t *sN = samples+CHANNELS;
+ for (unsigned int i=0 ; i<halfNumCoefs/4 ; i++) {
+ interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
+ interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
+ sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
+ interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
+ interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
+ sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
+ interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
+ interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
+ sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
+ interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
+ interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
+ sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
+ }
+}
+
+template<int CHANNELS>
+void AudioResamplerSinc::interpolate(
+ int32_t& l, int32_t& r,
+ const int32_t* coefs, int16_t lerp, const int16_t* samples)
+{
+ int32_t c0 = coefs[0];
+ int32_t c1 = coefs[1];
+ int32_t sinc = mulAdd(lerp, (c1-c0)<<1, c0);
+ if (CHANNELS == 2) {
+ uint32_t rl = *reinterpret_cast<const uint32_t*>(samples);
+ l = mulAddRL(1, rl, sinc, l);
+ r = mulAddRL(0, rl, sinc, r);
+ } else {
+ r = l = mulAdd(samples[0], sinc, l);
+ }
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
diff --git a/services/audioflinger/AudioResamplerSinc.h b/services/audioflinger/AudioResamplerSinc.h
new file mode 100644
index 0000000..f0a07b8
--- /dev/null
+++ b/services/audioflinger/AudioResamplerSinc.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 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_RESAMPLER_SINC_H
+#define ANDROID_AUDIO_RESAMPLER_SINC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+
+#include "AudioResampler.h"
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class AudioResamplerSinc : public AudioResampler {
+public:
+ AudioResamplerSinc(int bitDepth, int inChannelCount, int32_t sampleRate);
+
+ virtual ~AudioResamplerSinc();
+
+ virtual void resample(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider);
+private:
+ void init();
+
+ template<int CHANNELS>
+ void resample(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider);
+
+ template<int CHANNELS>
+ inline void filterCoefficient(
+ int32_t& l, int32_t& r, uint32_t phase, const int16_t *samples);
+
+ template<int CHANNELS>
+ inline void interpolate(
+ int32_t& l, int32_t& r,
+ const int32_t* coefs, int16_t lerp, const int16_t* samples);
+
+ template<int CHANNELS>
+ inline void read(int16_t*& impulse, uint32_t& phaseFraction,
+ const int16_t* in, size_t inputIndex);
+
+ int16_t *mState;
+ int16_t *mImpulse;
+ int16_t *mRingFull;
+
+ const int32_t * mFirCoefs;
+ static const int32_t mFirCoefsDown[];
+ static const int32_t mFirCoefsUp[];
+
+ // ----------------------------------------------------------------------------
+ static const int32_t RESAMPLE_FIR_NUM_COEF = 8;
+ static const int32_t RESAMPLE_FIR_LERP_INT_BITS = 4;
+
+ // we have 16 coefs samples per zero-crossing
+ static const int coefsBits = RESAMPLE_FIR_LERP_INT_BITS; // 4
+ static const int cShift = kNumPhaseBits - coefsBits; // 26
+ static const uint32_t cMask = ((1<<coefsBits)-1) << cShift; // 0xf<<26 = 3c00 0000
+
+ // and we use 15 bits to interpolate between these samples
+ // this cannot change because the mul below rely on it.
+ static const int pLerpBits = 15;
+ static const int pShift = kNumPhaseBits - coefsBits - pLerpBits; // 11
+ static const uint32_t pMask = ((1<<pLerpBits)-1) << pShift; // 0x7fff << 11
+
+ // number of zero-crossing on each side
+ static const unsigned int halfNumCoefs = RESAMPLE_FIR_NUM_COEF;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif /*ANDROID_AUDIO_RESAMPLER_SINC_H*/
diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp
new file mode 100644
index 0000000..6a58852
--- /dev/null
+++ b/services/audioflinger/ServiceUtilities.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/PermissionCache.h>
+#include "ServiceUtilities.h"
+
+namespace android {
+
+// This optimization assumes mediaserver process doesn't fork, which it doesn't
+const pid_t getpid_cached = getpid();
+
+bool recordingAllowed() {
+ if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
+ static const String16 sRecordAudio("android.permission.RECORD_AUDIO");
+ // don't use PermissionCache; this is not a system permission
+ bool ok = checkCallingPermission(sRecordAudio);
+ if (!ok) ALOGE("Request requires android.permission.RECORD_AUDIO");
+ return ok;
+}
+
+bool settingsAllowed() {
+ if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
+ static const String16 sAudioSettings("android.permission.MODIFY_AUDIO_SETTINGS");
+ // don't use PermissionCache; this is not a system permission
+ bool ok = checkCallingPermission(sAudioSettings);
+ if (!ok) ALOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
+ return ok;
+}
+
+bool dumpAllowed() {
+ // don't optimize for same pid, since mediaserver never dumps itself
+ static const String16 sDump("android.permission.DUMP");
+ // OK to use PermissionCache; this is a system permission
+ bool ok = PermissionCache::checkCallingPermission(sDump);
+ // convention is for caller to dump an error message to fd instead of logging here
+ //if (!ok) ALOGE("Request requires android.permission.DUMP");
+ return ok;
+}
+
+} // namespace android
diff --git a/services/audioflinger/ServiceUtilities.h b/services/audioflinger/ServiceUtilities.h
new file mode 100644
index 0000000..f77ec5b
--- /dev/null
+++ b/services/audioflinger/ServiceUtilities.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <unistd.h>
+
+namespace android {
+
+extern const pid_t getpid_cached;
+
+bool recordingAllowed();
+bool settingsAllowed();
+bool dumpAllowed();
+
+}
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
new file mode 100644
index 0000000..3cae1f5
--- /dev/null
+++ b/services/camera/libcameraservice/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+
+#
+# libcameraservice
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ CameraService.cpp
+
+LOCAL_SHARED_LIBRARIES:= \
+ libui \
+ libutils \
+ libbinder \
+ libcutils \
+ libmedia \
+ libmedia_native \
+ libcamera_client \
+ libgui \
+ libhardware
+
+LOCAL_MODULE:= libcameraservice
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h
new file mode 100644
index 0000000..87a0802
--- /dev/null
+++ b/services/camera/libcameraservice/CameraHardwareInterface.h
@@ -0,0 +1,696 @@
+/*
+ * 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_HARDWARE_CAMERA_HARDWARE_INTERFACE_H
+#define ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H
+
+#include <binder/IMemory.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <utils/RefBase.h>
+#include <ui/GraphicBuffer.h>
+#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
+#include <system/window.h>
+#include <hardware/camera.h>
+
+namespace android {
+
+typedef void (*notify_callback)(int32_t msgType,
+ int32_t ext1,
+ int32_t ext2,
+ void* user);
+
+typedef void (*data_callback)(int32_t msgType,
+ const sp<IMemory> &dataPtr,
+ camera_frame_metadata_t *metadata,
+ void* user);
+
+typedef void (*data_callback_timestamp)(nsecs_t timestamp,
+ int32_t msgType,
+ const sp<IMemory> &dataPtr,
+ void *user);
+
+/**
+ * CameraHardwareInterface.h defines the interface to the
+ * camera hardware abstraction layer, used for setting and getting
+ * parameters, live previewing, and taking pictures.
+ *
+ * It is a referenced counted interface with RefBase as its base class.
+ * CameraService calls openCameraHardware() to retrieve a strong pointer to the
+ * instance of this interface and may be called multiple times. The
+ * following steps describe a typical sequence:
+ *
+ * -# After CameraService calls openCameraHardware(), getParameters() and
+ * setParameters() are used to initialize the camera instance.
+ * CameraService calls getPreviewHeap() to establish access to the
+ * preview heap so it can be registered with SurfaceFlinger for
+ * efficient display updating while in preview mode.
+ * -# startPreview() is called. The camera instance then periodically
+ * sends the message CAMERA_MSG_PREVIEW_FRAME (if enabled) each time
+ * a new preview frame is available. If data callback code needs to use
+ * this memory after returning, it must copy the data.
+ *
+ * Prior to taking a picture, CameraService calls autofocus(). When auto
+ * focusing has completed, the camera instance sends a CAMERA_MSG_FOCUS notification,
+ * which informs the application whether focusing was successful. The camera instance
+ * only sends this message once and it is up to the application to call autoFocus()
+ * again if refocusing is desired.
+ *
+ * CameraService calls takePicture() to request the camera instance take a
+ * picture. At this point, if a shutter, postview, raw, and/or compressed callback
+ * is desired, the corresponding message must be enabled. As with CAMERA_MSG_PREVIEW_FRAME,
+ * any memory provided in a data callback must be copied if it's needed after returning.
+ */
+
+class CameraHardwareInterface : public virtual RefBase {
+public:
+ CameraHardwareInterface(const char *name)
+ {
+ mDevice = 0;
+ mName = name;
+ }
+
+ ~CameraHardwareInterface()
+ {
+ ALOGI("Destroying camera %s", mName.string());
+ if(mDevice) {
+ int rc = mDevice->common.close(&mDevice->common);
+ if (rc != OK)
+ ALOGE("Could not close camera %s: %d", mName.string(), rc);
+ }
+ }
+
+ status_t initialize(hw_module_t *module)
+ {
+ ALOGI("Opening camera %s", mName.string());
+ int rc = module->methods->open(module, mName.string(),
+ (hw_device_t **)&mDevice);
+ if (rc != OK) {
+ ALOGE("Could not open camera %s: %d", mName.string(), rc);
+ return rc;
+ }
+ initHalPreviewWindow();
+ return rc;
+ }
+
+ /** Set the ANativeWindow to which preview frames are sent */
+ status_t setPreviewWindow(const sp<ANativeWindow>& buf)
+ {
+ ALOGV("%s(%s) buf %p", __FUNCTION__, mName.string(), buf.get());
+
+ if (mDevice->ops->set_preview_window) {
+ mPreviewWindow = buf;
+ mHalPreviewWindow.user = this;
+ ALOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p", __FUNCTION__,
+ &mHalPreviewWindow, mHalPreviewWindow.user);
+ return mDevice->ops->set_preview_window(mDevice,
+ buf.get() ? &mHalPreviewWindow.nw : 0);
+ }
+ return INVALID_OPERATION;
+ }
+
+ /** Set the notification and data callbacks */
+ void setCallbacks(notify_callback notify_cb,
+ data_callback data_cb,
+ data_callback_timestamp data_cb_timestamp,
+ void* user)
+ {
+ mNotifyCb = notify_cb;
+ mDataCb = data_cb;
+ mDataCbTimestamp = data_cb_timestamp;
+ mCbUser = user;
+
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+
+ if (mDevice->ops->set_callbacks) {
+ mDevice->ops->set_callbacks(mDevice,
+ __notify_cb,
+ __data_cb,
+ __data_cb_timestamp,
+ __get_memory,
+ this);
+ }
+ }
+
+ /**
+ * The following three functions all take a msgtype,
+ * which is a bitmask of the messages defined in
+ * include/ui/Camera.h
+ */
+
+ /**
+ * Enable a message, or set of messages.
+ */
+ void enableMsgType(int32_t msgType)
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->enable_msg_type)
+ mDevice->ops->enable_msg_type(mDevice, msgType);
+ }
+
+ /**
+ * Disable a message, or a set of messages.
+ *
+ * Once received a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), camera hal
+ * should not rely on its client to call releaseRecordingFrame() to release
+ * video recording frames sent out by the cameral hal before and after the
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME) call. Camera hal clients must not
+ * modify/access any video recording frame after calling
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME).
+ */
+ void disableMsgType(int32_t msgType)
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->disable_msg_type)
+ mDevice->ops->disable_msg_type(mDevice, msgType);
+ }
+
+ /**
+ * Query whether a message, or a set of messages, is enabled.
+ * Note that this is operates as an AND, if any of the messages
+ * queried are off, this will return false.
+ */
+ int msgTypeEnabled(int32_t msgType)
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->msg_type_enabled)
+ return mDevice->ops->msg_type_enabled(mDevice, msgType);
+ return false;
+ }
+
+ /**
+ * Start preview mode.
+ */
+ status_t startPreview()
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->start_preview)
+ return mDevice->ops->start_preview(mDevice);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Stop a previously started preview.
+ */
+ void stopPreview()
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->stop_preview)
+ mDevice->ops->stop_preview(mDevice);
+ }
+
+ /**
+ * Returns true if preview is enabled.
+ */
+ int previewEnabled()
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->preview_enabled)
+ return mDevice->ops->preview_enabled(mDevice);
+ return false;
+ }
+
+ /**
+ * Request the camera hal to store meta data or real YUV data in
+ * the video buffers send out via CAMERA_MSG_VIDEO_FRRAME for a
+ * recording session. If it is not called, the default camera
+ * hal behavior is to store real YUV data in the video buffers.
+ *
+ * This method should be called before startRecording() in order
+ * to be effective.
+ *
+ * If meta data is stored in the video buffers, it is up to the
+ * receiver of the video buffers to interpret the contents and
+ * to find the actual frame data with the help of the meta data
+ * in the buffer. How this is done is outside of the scope of
+ * this method.
+ *
+ * Some camera hal may not support storing meta data in the video
+ * buffers, but all camera hal should support storing real YUV data
+ * in the video buffers. If the camera hal does not support storing
+ * the meta data in the video buffers when it is requested to do
+ * do, INVALID_OPERATION must be returned. It is very useful for
+ * the camera hal to pass meta data rather than the actual frame
+ * data directly to the video encoder, since the amount of the
+ * uncompressed frame data can be very large if video size is large.
+ *
+ * @param enable if true to instruct the camera hal to store
+ * meta data in the video buffers; false to instruct
+ * the camera hal to store real YUV data in the video
+ * buffers.
+ *
+ * @return OK on success.
+ */
+
+ status_t storeMetaDataInBuffers(int enable)
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->store_meta_data_in_buffers)
+ return mDevice->ops->store_meta_data_in_buffers(mDevice, enable);
+ return enable ? INVALID_OPERATION: OK;
+ }
+
+ /**
+ * Start record mode. When a record image is available a CAMERA_MSG_VIDEO_FRAME
+ * message is sent with the corresponding frame. Every record frame must be released
+ * by a cameral hal client via releaseRecordingFrame() before the client calls
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME). After the client calls
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is camera hal's responsibility
+ * to manage the life-cycle of the video recording frames, and the client must
+ * not modify/access any video recording frames.
+ */
+ status_t startRecording()
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->start_recording)
+ return mDevice->ops->start_recording(mDevice);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Stop a previously started recording.
+ */
+ void stopRecording()
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->stop_recording)
+ mDevice->ops->stop_recording(mDevice);
+ }
+
+ /**
+ * Returns true if recording is enabled.
+ */
+ int recordingEnabled()
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->recording_enabled)
+ return mDevice->ops->recording_enabled(mDevice);
+ return false;
+ }
+
+ /**
+ * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
+ *
+ * It is camera hal client's responsibility to release video recording
+ * frames sent out by the camera hal before the camera hal receives
+ * a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives
+ * the call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is camera hal's
+ * responsibility of managing the life-cycle of the video recording
+ * frames.
+ */
+ void releaseRecordingFrame(const sp<IMemory>& mem)
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->release_recording_frame) {
+ ssize_t offset;
+ size_t size;
+ sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+ void *data = ((uint8_t *)heap->base()) + offset;
+ return mDevice->ops->release_recording_frame(mDevice, data);
+ }
+ }
+
+ /**
+ * Start auto focus, the notification callback routine is called
+ * with CAMERA_MSG_FOCUS once when focusing is complete. autoFocus()
+ * will be called again if another auto focus is needed.
+ */
+ status_t autoFocus()
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->auto_focus)
+ return mDevice->ops->auto_focus(mDevice);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Cancels auto-focus function. If the auto-focus is still in progress,
+ * this function will cancel it. Whether the auto-focus is in progress
+ * or not, this function will return the focus position to the default.
+ * If the camera does not support auto-focus, this is a no-op.
+ */
+ status_t cancelAutoFocus()
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->cancel_auto_focus)
+ return mDevice->ops->cancel_auto_focus(mDevice);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Take a picture.
+ */
+ status_t takePicture()
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->take_picture)
+ return mDevice->ops->take_picture(mDevice);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Cancel a picture that was started with takePicture. Calling this
+ * method when no picture is being taken is a no-op.
+ */
+ status_t cancelPicture()
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->cancel_picture)
+ return mDevice->ops->cancel_picture(mDevice);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Set the camera parameters. This returns BAD_VALUE if any parameter is
+ * invalid or not supported. */
+ status_t setParameters(const CameraParameters &params)
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->set_parameters)
+ return mDevice->ops->set_parameters(mDevice,
+ params.flatten().string());
+ return INVALID_OPERATION;
+ }
+
+ /** Return the camera parameters. */
+ CameraParameters getParameters() const
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ CameraParameters parms;
+ if (mDevice->ops->get_parameters) {
+ char *temp = mDevice->ops->get_parameters(mDevice);
+ String8 str_parms(temp);
+ if (mDevice->ops->put_parameters)
+ mDevice->ops->put_parameters(mDevice, temp);
+ else
+ free(temp);
+ parms.unflatten(str_parms);
+ }
+ return parms;
+ }
+
+ /**
+ * Send command to camera driver.
+ */
+ status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->send_command)
+ return mDevice->ops->send_command(mDevice, cmd, arg1, arg2);
+ return INVALID_OPERATION;
+ }
+
+ /**
+ * Release the hardware resources owned by this object. Note that this is
+ * *not* done in the destructor.
+ */
+ void release() {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->release)
+ mDevice->ops->release(mDevice);
+ }
+
+ /**
+ * Dump state of the camera hardware
+ */
+ status_t dump(int fd, const Vector<String16>& args) const
+ {
+ ALOGV("%s(%s)", __FUNCTION__, mName.string());
+ if (mDevice->ops->dump)
+ return mDevice->ops->dump(mDevice, fd);
+ return OK; // It's fine if the HAL doesn't implement dump()
+ }
+
+private:
+ camera_device_t *mDevice;
+ String8 mName;
+
+ static void __notify_cb(int32_t msg_type, int32_t ext1,
+ int32_t ext2, void *user)
+ {
+ ALOGV("%s", __FUNCTION__);
+ CameraHardwareInterface *__this =
+ static_cast<CameraHardwareInterface *>(user);
+ __this->mNotifyCb(msg_type, ext1, ext2, __this->mCbUser);
+ }
+
+ static void __data_cb(int32_t msg_type,
+ const camera_memory_t *data, unsigned int index,
+ camera_frame_metadata_t *metadata,
+ void *user)
+ {
+ ALOGV("%s", __FUNCTION__);
+ CameraHardwareInterface *__this =
+ static_cast<CameraHardwareInterface *>(user);
+ sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(data->handle));
+ if (index >= mem->mNumBufs) {
+ ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__,
+ index, mem->mNumBufs);
+ return;
+ }
+ __this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser);
+ }
+
+ static void __data_cb_timestamp(nsecs_t timestamp, int32_t msg_type,
+ const camera_memory_t *data, unsigned index,
+ void *user)
+ {
+ ALOGV("%s", __FUNCTION__);
+ CameraHardwareInterface *__this =
+ static_cast<CameraHardwareInterface *>(user);
+ // Start refcounting the heap object from here on. When the clients
+ // drop all references, it will be destroyed (as well as the enclosed
+ // MemoryHeapBase.
+ sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(data->handle));
+ if (index >= mem->mNumBufs) {
+ ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__,
+ index, mem->mNumBufs);
+ return;
+ }
+ __this->mDataCbTimestamp(timestamp, msg_type, mem->mBuffers[index], __this->mCbUser);
+ }
+
+ // This is a utility class that combines a MemoryHeapBase and a MemoryBase
+ // in one. Since we tend to use them in a one-to-one relationship, this is
+ // handy.
+
+ class CameraHeapMemory : public RefBase {
+ public:
+ CameraHeapMemory(int fd, size_t buf_size, uint_t num_buffers = 1) :
+ mBufSize(buf_size),
+ mNumBufs(num_buffers)
+ {
+ mHeap = new MemoryHeapBase(fd, buf_size * num_buffers);
+ commonInitialization();
+ }
+
+ CameraHeapMemory(size_t buf_size, uint_t num_buffers = 1) :
+ mBufSize(buf_size),
+ mNumBufs(num_buffers)
+ {
+ mHeap = new MemoryHeapBase(buf_size * num_buffers);
+ commonInitialization();
+ }
+
+ void commonInitialization()
+ {
+ handle.data = mHeap->base();
+ handle.size = mBufSize * mNumBufs;
+ handle.handle = this;
+
+ mBuffers = new sp<MemoryBase>[mNumBufs];
+ for (uint_t i = 0; i < mNumBufs; i++)
+ mBuffers[i] = new MemoryBase(mHeap,
+ i * mBufSize,
+ mBufSize);
+
+ handle.release = __put_memory;
+ }
+
+ virtual ~CameraHeapMemory()
+ {
+ delete [] mBuffers;
+ }
+
+ size_t mBufSize;
+ uint_t mNumBufs;
+ sp<MemoryHeapBase> mHeap;
+ sp<MemoryBase> *mBuffers;
+
+ camera_memory_t handle;
+ };
+
+ static camera_memory_t* __get_memory(int fd, size_t buf_size, uint_t num_bufs,
+ void *user __attribute__((unused)))
+ {
+ CameraHeapMemory *mem;
+ if (fd < 0)
+ mem = new CameraHeapMemory(buf_size, num_bufs);
+ else
+ mem = new CameraHeapMemory(fd, buf_size, num_bufs);
+ mem->incStrong(mem);
+ return &mem->handle;
+ }
+
+ static void __put_memory(camera_memory_t *data)
+ {
+ if (!data)
+ return;
+
+ CameraHeapMemory *mem = static_cast<CameraHeapMemory *>(data->handle);
+ mem->decStrong(mem);
+ }
+
+ static ANativeWindow *__to_anw(void *user)
+ {
+ CameraHardwareInterface *__this =
+ reinterpret_cast<CameraHardwareInterface *>(user);
+ return __this->mPreviewWindow.get();
+ }
+#define anw(n) __to_anw(((struct camera_preview_window *)n)->user)
+
+ static int __dequeue_buffer(struct preview_stream_ops* w,
+ buffer_handle_t** buffer, int *stride)
+ {
+ int rc;
+ ANativeWindow *a = anw(w);
+ ANativeWindowBuffer* anb;
+ rc = a->dequeueBuffer(a, &anb);
+ if (!rc) {
+ *buffer = &anb->handle;
+ *stride = anb->stride;
+ }
+ return rc;
+ }
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof(((type *) 0)->member) *__mptr = (ptr); \
+ (type *) ((char *) __mptr - (char *)(&((type *)0)->member)); })
+#endif
+
+ static int __lock_buffer(struct preview_stream_ops* w,
+ buffer_handle_t* buffer)
+ {
+ ANativeWindow *a = anw(w);
+ return a->lockBuffer(a,
+ container_of(buffer, ANativeWindowBuffer, handle));
+ }
+
+ static int __enqueue_buffer(struct preview_stream_ops* w,
+ buffer_handle_t* buffer)
+ {
+ ANativeWindow *a = anw(w);
+ return a->queueBuffer(a,
+ container_of(buffer, ANativeWindowBuffer, handle));
+ }
+
+ static int __cancel_buffer(struct preview_stream_ops* w,
+ buffer_handle_t* buffer)
+ {
+ ANativeWindow *a = anw(w);
+ return a->cancelBuffer(a,
+ container_of(buffer, ANativeWindowBuffer, handle));
+ }
+
+ static int __set_buffer_count(struct preview_stream_ops* w, int count)
+ {
+ ANativeWindow *a = anw(w);
+ return native_window_set_buffer_count(a, count);
+ }
+
+ static int __set_buffers_geometry(struct preview_stream_ops* w,
+ int width, int height, int format)
+ {
+ ANativeWindow *a = anw(w);
+ return native_window_set_buffers_geometry(a,
+ width, height, format);
+ }
+
+ static int __set_crop(struct preview_stream_ops *w,
+ int left, int top, int right, int bottom)
+ {
+ ANativeWindow *a = anw(w);
+ android_native_rect_t crop;
+ crop.left = left;
+ crop.top = top;
+ crop.right = right;
+ crop.bottom = bottom;
+ return native_window_set_crop(a, &crop);
+ }
+
+ static int __set_timestamp(struct preview_stream_ops *w,
+ int64_t timestamp) {
+ ANativeWindow *a = anw(w);
+ return native_window_set_buffers_timestamp(a, timestamp);
+ }
+
+ static int __set_usage(struct preview_stream_ops* w, int usage)
+ {
+ ANativeWindow *a = anw(w);
+ return native_window_set_usage(a, usage);
+ }
+
+ static int __set_swap_interval(struct preview_stream_ops *w, int interval)
+ {
+ ANativeWindow *a = anw(w);
+ return a->setSwapInterval(a, interval);
+ }
+
+ static int __get_min_undequeued_buffer_count(
+ const struct preview_stream_ops *w,
+ int *count)
+ {
+ ANativeWindow *a = anw(w);
+ return a->query(a, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, count);
+ }
+
+ void initHalPreviewWindow()
+ {
+ mHalPreviewWindow.nw.cancel_buffer = __cancel_buffer;
+ mHalPreviewWindow.nw.lock_buffer = __lock_buffer;
+ mHalPreviewWindow.nw.dequeue_buffer = __dequeue_buffer;
+ mHalPreviewWindow.nw.enqueue_buffer = __enqueue_buffer;
+ mHalPreviewWindow.nw.set_buffer_count = __set_buffer_count;
+ mHalPreviewWindow.nw.set_buffers_geometry = __set_buffers_geometry;
+ mHalPreviewWindow.nw.set_crop = __set_crop;
+ mHalPreviewWindow.nw.set_timestamp = __set_timestamp;
+ mHalPreviewWindow.nw.set_usage = __set_usage;
+ mHalPreviewWindow.nw.set_swap_interval = __set_swap_interval;
+
+ mHalPreviewWindow.nw.get_min_undequeued_buffer_count =
+ __get_min_undequeued_buffer_count;
+ }
+
+ sp<ANativeWindow> mPreviewWindow;
+
+ struct camera_preview_window {
+ struct preview_stream_ops nw;
+ void *user;
+ };
+
+ struct camera_preview_window mHalPreviewWindow;
+
+ notify_callback mNotifyCb;
+ data_callback mDataCb;
+ data_callback_timestamp mDataCbTimestamp;
+ void *mCbUser;
+};
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/CameraHardwareStub.cpp b/services/camera/libcameraservice/CameraHardwareStub.cpp
new file mode 100644
index 0000000..cdfb2f5
--- /dev/null
+++ b/services/camera/libcameraservice/CameraHardwareStub.cpp
@@ -0,0 +1,410 @@
+/*
+**
+** 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.
+*/
+
+#define LOG_TAG "CameraHardwareStub"
+#include <utils/Log.h>
+
+#include "CameraHardwareStub.h"
+#include <utils/threads.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "CannedJpeg.h"
+
+namespace android {
+
+CameraHardwareStub::CameraHardwareStub()
+ : mParameters(),
+ mPreviewHeap(0),
+ mRawHeap(0),
+ mFakeCamera(0),
+ mPreviewFrameSize(0),
+ mNotifyCb(0),
+ mDataCb(0),
+ mDataCbTimestamp(0),
+ mCallbackCookie(0),
+ mMsgEnabled(0),
+ mCurrentPreviewFrame(0)
+{
+ initDefaultParameters();
+}
+
+void CameraHardwareStub::initDefaultParameters()
+{
+ CameraParameters p;
+
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240");
+ p.setPreviewSize(320, 240);
+ p.setPreviewFrameRate(15);
+ p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);
+
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");
+ p.setPictureSize(320, 240);
+ p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
+
+ if (setParameters(p) != NO_ERROR) {
+ ALOGE("Failed to set default parameters?!");
+ }
+}
+
+void CameraHardwareStub::initHeapLocked()
+{
+ // Create raw heap.
+ int picture_width, picture_height;
+ mParameters.getPictureSize(&picture_width, &picture_height);
+ mRawHeap = new MemoryHeapBase(picture_width * picture_height * 3 / 2);
+
+ int preview_width, preview_height;
+ mParameters.getPreviewSize(&preview_width, &preview_height);
+ ALOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);
+
+ // Note that we enforce yuv420sp in setParameters().
+ int how_big = preview_width * preview_height * 3 / 2;
+
+ // If we are being reinitialized to the same size as before, no
+ // work needs to be done.
+ if (how_big == mPreviewFrameSize)
+ return;
+
+ mPreviewFrameSize = how_big;
+
+ // Make a new mmap'ed heap that can be shared across processes.
+ // use code below to test with pmem
+ mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount);
+ // Make an IMemory for each frame so that we can reuse them in callbacks.
+ for (int i = 0; i < kBufferCount; i++) {
+ mBuffers[i] = new MemoryBase(mPreviewHeap, i * mPreviewFrameSize, mPreviewFrameSize);
+ }
+
+ // Recreate the fake camera to reflect the current size.
+ delete mFakeCamera;
+ mFakeCamera = new FakeCamera(preview_width, preview_height);
+}
+
+CameraHardwareStub::~CameraHardwareStub()
+{
+ delete mFakeCamera;
+ mFakeCamera = 0; // paranoia
+}
+
+status_t CameraHardwareStub::setPreviewWindow(const sp<ANativeWindow>& buf)
+{
+ return NO_ERROR;
+}
+
+sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const
+{
+ return mRawHeap;
+}
+
+void CameraHardwareStub::setCallbacks(notify_callback notify_cb,
+ data_callback data_cb,
+ data_callback_timestamp data_cb_timestamp,
+ void* user)
+{
+ Mutex::Autolock lock(mLock);
+ mNotifyCb = notify_cb;
+ mDataCb = data_cb;
+ mDataCbTimestamp = data_cb_timestamp;
+ mCallbackCookie = user;
+}
+
+void CameraHardwareStub::enableMsgType(int32_t msgType)
+{
+ Mutex::Autolock lock(mLock);
+ mMsgEnabled |= msgType;
+}
+
+void CameraHardwareStub::disableMsgType(int32_t msgType)
+{
+ Mutex::Autolock lock(mLock);
+ mMsgEnabled &= ~msgType;
+}
+
+bool CameraHardwareStub::msgTypeEnabled(int32_t msgType)
+{
+ Mutex::Autolock lock(mLock);
+ return (mMsgEnabled & msgType);
+}
+
+// ---------------------------------------------------------------------------
+
+int CameraHardwareStub::previewThread()
+{
+ mLock.lock();
+ // the attributes below can change under our feet...
+
+ int previewFrameRate = mParameters.getPreviewFrameRate();
+
+ // Find the offset within the heap of the current buffer.
+ ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;
+
+ sp<MemoryHeapBase> heap = mPreviewHeap;
+
+ // this assumes the internal state of fake camera doesn't change
+ // (or is thread safe)
+ FakeCamera* fakeCamera = mFakeCamera;
+
+ sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
+
+ mLock.unlock();
+
+ // TODO: here check all the conditions that could go wrong
+ if (buffer != 0) {
+ // Calculate how long to wait between frames.
+ int delay = (int)(1000000.0f / float(previewFrameRate));
+
+ // This is always valid, even if the client died -- the memory
+ // is still mapped in our process.
+ void *base = heap->base();
+
+ // Fill the current frame with the fake camera.
+ uint8_t *frame = ((uint8_t *)base) + offset;
+ fakeCamera->getNextFrameAsYuv420(frame);
+
+ //ALOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
+
+ // Notify the client of a new frame.
+ if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
+ mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, NULL, mCallbackCookie);
+
+ // Advance the buffer pointer.
+ mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
+
+ // Wait for it...
+ usleep(delay);
+ }
+
+ return NO_ERROR;
+}
+
+status_t CameraHardwareStub::startPreview()
+{
+ Mutex::Autolock lock(mLock);
+ if (mPreviewThread != 0) {
+ // already running
+ return INVALID_OPERATION;
+ }
+ mPreviewThread = new PreviewThread(this);
+ return NO_ERROR;
+}
+
+void CameraHardwareStub::stopPreview()
+{
+ sp<PreviewThread> previewThread;
+
+ { // scope for the lock
+ Mutex::Autolock lock(mLock);
+ previewThread = mPreviewThread;
+ }
+
+ // don't hold the lock while waiting for the thread to quit
+ if (previewThread != 0) {
+ previewThread->requestExitAndWait();
+ }
+
+ Mutex::Autolock lock(mLock);
+ mPreviewThread.clear();
+}
+
+bool CameraHardwareStub::previewEnabled() {
+ return mPreviewThread != 0;
+}
+
+status_t CameraHardwareStub::startRecording()
+{
+ return UNKNOWN_ERROR;
+}
+
+void CameraHardwareStub::stopRecording()
+{
+}
+
+bool CameraHardwareStub::recordingEnabled()
+{
+ return false;
+}
+
+void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+int CameraHardwareStub::beginAutoFocusThread(void *cookie)
+{
+ CameraHardwareStub *c = (CameraHardwareStub *)cookie;
+ return c->autoFocusThread();
+}
+
+int CameraHardwareStub::autoFocusThread()
+{
+ if (mMsgEnabled & CAMERA_MSG_FOCUS)
+ mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
+ return NO_ERROR;
+}
+
+status_t CameraHardwareStub::autoFocus()
+{
+ Mutex::Autolock lock(mLock);
+ if (createThread(beginAutoFocusThread, this) == false)
+ return UNKNOWN_ERROR;
+ return NO_ERROR;
+}
+
+status_t CameraHardwareStub::cancelAutoFocus()
+{
+ return NO_ERROR;
+}
+
+/*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
+{
+ CameraHardwareStub *c = (CameraHardwareStub *)cookie;
+ return c->pictureThread();
+}
+
+int CameraHardwareStub::pictureThread()
+{
+ if (mMsgEnabled & CAMERA_MSG_SHUTTER)
+ mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
+
+ if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
+ //FIXME: use a canned YUV image!
+ // In the meantime just make another fake camera picture.
+ int w, h;
+ mParameters.getPictureSize(&w, &h);
+ sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2);
+ FakeCamera cam(w, h);
+ cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base());
+ mDataCb(CAMERA_MSG_RAW_IMAGE, mem, NULL, mCallbackCookie);
+ }
+
+ if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
+ sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
+ sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
+ memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
+ mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL, mCallbackCookie);
+ }
+ return NO_ERROR;
+}
+
+status_t CameraHardwareStub::takePicture()
+{
+ stopPreview();
+ if (createThread(beginPictureThread, this) == false)
+ return UNKNOWN_ERROR;
+ return NO_ERROR;
+}
+
+status_t CameraHardwareStub::cancelPicture()
+{
+ return NO_ERROR;
+}
+
+status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ AutoMutex lock(&mLock);
+ if (mFakeCamera != 0) {
+ mFakeCamera->dump(fd);
+ mParameters.dump(fd, args);
+ snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false");
+ result.append(buffer);
+ } else {
+ result.append("No camera client yet.\n");
+ }
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+status_t CameraHardwareStub::setParameters(const CameraParameters& params)
+{
+ Mutex::Autolock lock(mLock);
+ // XXX verify params
+
+ if (strcmp(params.getPreviewFormat(),
+ CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) {
+ ALOGE("Only yuv420sp preview is supported");
+ return -1;
+ }
+
+ if (strcmp(params.getPictureFormat(),
+ CameraParameters::PIXEL_FORMAT_JPEG) != 0) {
+ ALOGE("Only jpeg still pictures are supported");
+ return -1;
+ }
+
+ int w, h;
+ params.getPictureSize(&w, &h);
+ if (w != kCannedJpegWidth && h != kCannedJpegHeight) {
+ ALOGE("Still picture size must be size of canned JPEG (%dx%d)",
+ kCannedJpegWidth, kCannedJpegHeight);
+ return -1;
+ }
+
+ mParameters = params;
+ initHeapLocked();
+
+ return NO_ERROR;
+}
+
+CameraParameters CameraHardwareStub::getParameters() const
+{
+ Mutex::Autolock lock(mLock);
+ return mParameters;
+}
+
+status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1,
+ int32_t arg2)
+{
+ return BAD_VALUE;
+}
+
+void CameraHardwareStub::release()
+{
+}
+
+sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
+{
+ return new CameraHardwareStub();
+}
+
+static CameraInfo sCameraInfo[] = {
+ {
+ CAMERA_FACING_BACK,
+ 90, /* orientation */
+ }
+};
+
+extern "C" int HAL_getNumberOfCameras()
+{
+ return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
+}
+
+extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
+{
+ memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
+}
+
+extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId)
+{
+ return CameraHardwareStub::createInstance();
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/CameraHardwareStub.h b/services/camera/libcameraservice/CameraHardwareStub.h
new file mode 100644
index 0000000..c6d8756
--- /dev/null
+++ b/services/camera/libcameraservice/CameraHardwareStub.h
@@ -0,0 +1,126 @@
+/*
+**
+** 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_HARDWARE_CAMERA_HARDWARE_STUB_H
+#define ANDROID_HARDWARE_CAMERA_HARDWARE_STUB_H
+
+#include "FakeCamera.h"
+#include <utils/threads.h>
+#include <camera/CameraHardwareInterface.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class CameraHardwareStub : public CameraHardwareInterface {
+public:
+ virtual status_t setPreviewWindow(const sp<ANativeWindow>& buf);
+ virtual sp<IMemoryHeap> getRawHeap() const;
+
+ virtual void setCallbacks(notify_callback notify_cb,
+ data_callback data_cb,
+ data_callback_timestamp data_cb_timestamp,
+ void* user);
+
+ virtual void enableMsgType(int32_t msgType);
+ virtual void disableMsgType(int32_t msgType);
+ virtual bool msgTypeEnabled(int32_t msgType);
+
+ virtual status_t startPreview();
+ virtual void stopPreview();
+ virtual bool previewEnabled();
+
+ virtual status_t startRecording();
+ virtual void stopRecording();
+ virtual bool recordingEnabled();
+ virtual void releaseRecordingFrame(const sp<IMemory>& mem);
+
+ virtual status_t autoFocus();
+ virtual status_t cancelAutoFocus();
+ virtual status_t takePicture();
+ virtual status_t cancelPicture();
+ virtual status_t dump(int fd, const Vector<String16>& args) const;
+ virtual status_t setParameters(const CameraParameters& params);
+ virtual CameraParameters getParameters() const;
+ virtual status_t sendCommand(int32_t command, int32_t arg1,
+ int32_t arg2);
+ virtual void release();
+
+ static sp<CameraHardwareInterface> createInstance();
+
+private:
+ CameraHardwareStub();
+ virtual ~CameraHardwareStub();
+
+ static const int kBufferCount = 4;
+
+ class PreviewThread : public Thread {
+ CameraHardwareStub* mHardware;
+ public:
+ PreviewThread(CameraHardwareStub* hw) :
+ Thread(false), mHardware(hw) { }
+ virtual void onFirstRef() {
+ run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
+ }
+ virtual bool threadLoop() {
+ mHardware->previewThread();
+ // loop until we need to quit
+ return true;
+ }
+ };
+
+ void initDefaultParameters();
+ void initHeapLocked();
+
+ int previewThread();
+
+ static int beginAutoFocusThread(void *cookie);
+ int autoFocusThread();
+
+ static int beginPictureThread(void *cookie);
+ int pictureThread();
+
+ mutable Mutex mLock;
+
+ CameraParameters mParameters;
+
+ sp<MemoryHeapBase> mPreviewHeap;
+ sp<MemoryHeapBase> mRawHeap;
+ sp<MemoryBase> mBuffers[kBufferCount];
+
+ FakeCamera *mFakeCamera;
+ bool mPreviewRunning;
+ int mPreviewFrameSize;
+
+ // protected by mLock
+ sp<PreviewThread> mPreviewThread;
+
+ notify_callback mNotifyCb;
+ data_callback mDataCb;
+ data_callback_timestamp mDataCbTimestamp;
+ void *mCallbackCookie;
+
+ int32_t mMsgEnabled;
+
+ // only used from PreviewThread
+ int mCurrentPreviewFrame;
+};
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
new file mode 100644
index 0000000..22836e3
--- /dev/null
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -0,0 +1,1380 @@
+/*
+**
+** 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 "CameraService"
+//#define LOG_NDEBUG 0
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <time.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <cutils/atomic.h>
+#include <cutils/properties.h>
+#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
+#include <hardware/hardware.h>
+#include <media/AudioSystem.h>
+#include <media/mediaplayer.h>
+#include <utils/Condition.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/String16.h>
+
+#include "CameraService.h"
+#include "CameraHardwareInterface.h"
+
+namespace android {
+
+#define WAIT_RELEASE_TIMEOUT 250 // 250ms
+
+// ----------------------------------------------------------------------------
+// Logging support -- this is for debugging only
+// Use "adb shell dumpsys media.camera -v 1" to change it.
+static volatile int32_t gLogLevel = 0;
+
+#define LOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__);
+#define LOG2(...) ALOGD_IF(gLogLevel >= 2, __VA_ARGS__);
+
+static void setLogLevel(int level) {
+ android_atomic_write(level, &gLogLevel);
+}
+
+// ----------------------------------------------------------------------------
+
+static int getCallingPid() {
+ return IPCThreadState::self()->getCallingPid();
+}
+
+static int getCallingUid() {
+ return IPCThreadState::self()->getCallingUid();
+}
+
+static long long getTimeInMs() {
+ struct timeval t;
+ t.tv_sec = t.tv_usec = 0;
+ gettimeofday(&t, NULL);
+ return t.tv_sec * 1000LL + t.tv_usec / 1000;
+}
+
+// ----------------------------------------------------------------------------
+
+// This is ugly and only safe if we never re-create the CameraService, but
+// should be ok for now.
+static CameraService *gCameraService;
+
+CameraService::CameraService()
+:mSoundRef(0), mModule(0)
+{
+ ALOGI("CameraService started (pid=%d)", getpid());
+ gCameraService = this;
+}
+
+void CameraService::onFirstRef()
+{
+ BnCameraService::onFirstRef();
+
+ if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
+ (const hw_module_t **)&mModule) < 0) {
+ ALOGE("Could not load camera HAL module");
+ mNumberOfCameras = 0;
+ }
+ else {
+ mNumberOfCameras = mModule->get_number_of_cameras();
+ if (mNumberOfCameras > MAX_CAMERAS) {
+ ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
+ mNumberOfCameras, MAX_CAMERAS);
+ mNumberOfCameras = MAX_CAMERAS;
+ }
+ for (int i = 0; i < mNumberOfCameras; i++) {
+ setCameraFree(i);
+ }
+ }
+}
+
+CameraService::~CameraService() {
+ for (int i = 0; i < mNumberOfCameras; i++) {
+ if (mBusy[i]) {
+ ALOGE("camera %d is still in use in destructor!", i);
+ }
+ }
+
+ gCameraService = NULL;
+}
+
+int32_t CameraService::getNumberOfCameras() {
+ return mNumberOfCameras;
+}
+
+status_t CameraService::getCameraInfo(int cameraId,
+ struct CameraInfo* cameraInfo) {
+ if (!mModule) {
+ return NO_INIT;
+ }
+
+ if (cameraId < 0 || cameraId >= mNumberOfCameras) {
+ return BAD_VALUE;
+ }
+
+ struct camera_info info;
+ status_t rc = mModule->get_camera_info(cameraId, &info);
+ cameraInfo->facing = info.facing;
+ cameraInfo->orientation = info.orientation;
+ return rc;
+}
+
+sp<ICamera> CameraService::connect(
+ const sp<ICameraClient>& cameraClient, int cameraId, bool force, bool keep) {
+ int callingPid = getCallingPid();
+ sp<CameraHardwareInterface> hardware = NULL;
+
+ LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
+
+ if (!mModule) {
+ ALOGE("Camera HAL module not loaded");
+ return NULL;
+ }
+
+ sp<Client> client;
+ if (cameraId < 0 || cameraId >= mNumberOfCameras) {
+ ALOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
+ callingPid, cameraId);
+ return NULL;
+ }
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("sys.secpolicy.camera.disabled", value, "0");
+ if (strcmp(value, "1") == 0) {
+ // Camera is disabled by DevicePolicyManager.
+ ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid);
+ return NULL;
+ }
+
+ if (keep && !checkCallingPermission(String16("android.permission.KEEP_CAMERA"))) {
+ ALOGE("connect X (pid %d) rejected (no KEEP_CAMERA permission).", callingPid);
+ return NULL;
+ }
+
+ Mutex::Autolock lock(mServiceLock);
+ // Check if there is an existing client.
+ client = mClient[cameraId].promote();
+ if (client != 0 &&
+ cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
+ LOG1("connect X (pid %d) (the same client)", callingPid);
+ return client;
+ }
+
+ if (!force) {
+ if (mClient[cameraId].promote() != 0) {
+ ALOGW("connect X (pid %d) rejected (existing client).", callingPid);
+ return NULL;
+ }
+ mClient[cameraId].clear();
+ if (mBusy[cameraId]) {
+ ALOGW("connect X (pid %d) rejected (camera %d is still busy).",
+ callingPid, cameraId);
+ return NULL;
+ }
+ } else { // force == true
+ int i = 0;
+ long long start_time = getTimeInMs();
+ while (i < mNumberOfCameras) {
+ if (getTimeInMs() - start_time >= 3000LL) {
+ ALOGE("connect X (pid %d) rejected (timeout 3s)", callingPid);
+ return NULL;
+ }
+
+ client = mClient[i].promote();
+ if (client != 0) {
+ if (client->keep()) {
+ ALOGW("connect X (pid %d) rejected (existing client wants to keeps the camera)",
+ callingPid);
+ return NULL;
+ } else {
+ ALOGW("New client (pid %d, id=%d). Disconnect the existing client (id=%d).",
+ callingPid, cameraId, i);
+ // Do not hold mServiceLock because disconnect will try to get it.
+ mServiceLock.unlock();
+ client->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0, &i);
+ client->waitRelease(WAIT_RELEASE_TIMEOUT);
+ client->disconnectInternal(false);
+ mServiceLock.lock();
+ // Restart from the first client because a new client may have connected
+ // when mServiceLock is unlocked.
+ i = 0;
+ continue;
+ }
+ }
+
+ if (mBusy[i]) {
+ // Give the client a chance to release the hardware.
+ mServiceLock.unlock();
+ usleep(10 * 1000);
+ mServiceLock.lock();
+ i = 0; // Restart from the first client
+ continue;
+ }
+
+ i++;
+ }
+ }
+
+ struct camera_info info;
+ if (mModule->get_camera_info(cameraId, &info) != OK) {
+ ALOGE("Invalid camera id %d", cameraId);
+ return NULL;
+ }
+
+ char camera_device_name[10];
+ snprintf(camera_device_name, sizeof(camera_device_name), "%d", cameraId);
+
+ hardware = new CameraHardwareInterface(camera_device_name);
+ if (hardware->initialize(&mModule->common) != OK) {
+ hardware.clear();
+ return NULL;
+ }
+
+ client = new Client(this, cameraClient, hardware, cameraId, info.facing,
+ callingPid, keep);
+ // We need to clear the hardware here. After the destructor of mServiceLock
+ // finishes, a new client may connect and disconnect this client. If this
+ // reference is not cleared, the destructor of CameraHardwareInterface
+ // cannot run. The new client will not be able to connect.
+ hardware.clear();
+ mClient[cameraId] = client;
+ LOG1("CameraService::connect X (id %d)", cameraId);
+ return client;
+}
+
+void CameraService::removeClient(const sp<ICameraClient>& cameraClient) {
+ int callingPid = getCallingPid();
+ LOG1("CameraService::removeClient E (pid %d)", callingPid);
+
+ for (int i = 0; i < mNumberOfCameras; i++) {
+ // Declare this before the lock to make absolutely sure the
+ // destructor won't be called with the lock held.
+ sp<Client> client;
+
+ Mutex::Autolock lock(mServiceLock);
+
+ // This happens when we have already disconnected (or this is
+ // just another unused camera).
+ if (mClient[i] == 0) continue;
+
+ // Promote mClient. It can fail if we are called from this path:
+ // Client::~Client() -> disconnect() -> removeClient().
+ client = mClient[i].promote();
+
+ if (client == 0) {
+ mClient[i].clear();
+ continue;
+ }
+
+ if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
+ // Found our camera, clear and leave.
+ LOG1("removeClient: clear camera %d", i);
+ mClient[i].clear();
+ break;
+ }
+ }
+
+ LOG1("CameraService::removeClient X (pid %d)", callingPid);
+}
+
+sp<CameraService::Client> CameraService::getClientById(int cameraId) {
+ if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
+ return mClient[cameraId].promote();
+}
+
+status_t CameraService::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+ // Permission checks
+ switch (code) {
+ case BnCameraService::CONNECT:
+ const int pid = getCallingPid();
+ const int self_pid = getpid();
+ if (pid != self_pid) {
+ // we're called from a different process, do the real check
+ if (!checkCallingPermission(
+ String16("android.permission.CAMERA"))) {
+ const int uid = getCallingUid();
+ ALOGE("Permission Denial: "
+ "can't use the camera pid=%d, uid=%d", pid, uid);
+ return PERMISSION_DENIED;
+ }
+ }
+ break;
+ }
+
+ return BnCameraService::onTransact(code, data, reply, flags);
+}
+
+// The reason we need this busy bit is a new CameraService::connect() request
+// may come in while the previous Client's destructor has not been run or is
+// still running. If the last strong reference of the previous Client is gone
+// but the destructor has not been finished, we should not allow the new Client
+// to be created because we need to wait for the previous Client to tear down
+// the hardware first.
+void CameraService::setCameraBusy(int cameraId) {
+ android_atomic_write(1, &mBusy[cameraId]);
+}
+
+void CameraService::setCameraFree(int cameraId) {
+ android_atomic_write(0, &mBusy[cameraId]);
+}
+
+// We share the media players for shutter and recording sound for all clients.
+// A reference count is kept to determine when we will actually release the
+// media players.
+
+MediaPlayer* CameraService::newMediaPlayer(const char *file) {
+ MediaPlayer* mp = new MediaPlayer();
+ if (mp->setDataSource(file, NULL) == NO_ERROR) {
+ mp->setAudioStreamType(AUDIO_STREAM_ENFORCED_AUDIBLE);
+ mp->prepare();
+ } else {
+ ALOGE("Failed to load CameraService sounds: %s", file);
+ return NULL;
+ }
+ return mp;
+}
+
+void CameraService::loadSound() {
+ Mutex::Autolock lock(mSoundLock);
+ LOG1("CameraService::loadSound ref=%d", mSoundRef);
+ if (mSoundRef++) return;
+
+ mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
+ mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
+}
+
+void CameraService::releaseSound() {
+ Mutex::Autolock lock(mSoundLock);
+ LOG1("CameraService::releaseSound ref=%d", mSoundRef);
+ if (--mSoundRef) return;
+
+ for (int i = 0; i < NUM_SOUNDS; i++) {
+ if (mSoundPlayer[i] != 0) {
+ mSoundPlayer[i]->disconnect();
+ mSoundPlayer[i].clear();
+ }
+ }
+}
+
+void CameraService::playSound(sound_kind kind) {
+ LOG1("playSound(%d)", kind);
+ Mutex::Autolock lock(mSoundLock);
+ sp<MediaPlayer> player = mSoundPlayer[kind];
+ if (player != 0) {
+ player->seekTo(0);
+ player->start();
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+CameraService::Client::Client(const sp<CameraService>& cameraService,
+ const sp<ICameraClient>& cameraClient,
+ const sp<CameraHardwareInterface>& hardware,
+ int cameraId, int cameraFacing, int clientPid, bool keep) {
+ int callingPid = getCallingPid();
+ LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);
+
+ mCameraService = cameraService;
+ mCameraClient = cameraClient;
+ mHardware = hardware;
+ mCameraId = cameraId;
+ mCameraFacing = cameraFacing;
+ mClientPid = clientPid;
+ mKeep = keep;
+ mMsgEnabled = 0;
+ mSurface = 0;
+ mPreviewWindow = 0;
+ mHardware->setCallbacks(notifyCallback,
+ dataCallback,
+ dataCallbackTimestamp,
+ (void *)cameraId);
+
+ // Enable zoom, error, focus, and metadata messages by default
+ enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
+ CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
+
+ // Callback is disabled by default
+ mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
+ mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
+ mPlayShutterSound = true;
+ cameraService->setCameraBusy(cameraId);
+ cameraService->loadSound();
+ LOG1("Client::Client X (pid %d, id %d)", callingPid, cameraId);
+}
+
+// tear down the client
+CameraService::Client::~Client() {
+ int callingPid = getCallingPid();
+ LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);
+
+ // set mClientPid to let disconnet() tear down the hardware
+ mClientPid = callingPid;
+ disconnect();
+ mCameraService->releaseSound();
+ LOG1("Client::~Client X (pid %d, this %p)", callingPid, this);
+}
+
+// ----------------------------------------------------------------------------
+
+status_t CameraService::Client::checkPid() const {
+ int callingPid = getCallingPid();
+ if (callingPid == mClientPid) return NO_ERROR;
+
+ ALOGW("attempt to use a locked camera from a different process"
+ " (old pid %d, new pid %d)", mClientPid, callingPid);
+ return EBUSY;
+}
+
+status_t CameraService::Client::checkPidAndHardware() const {
+ status_t result = checkPid();
+ if (result != NO_ERROR) return result;
+ if (mHardware == 0) {
+ ALOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
+ return INVALID_OPERATION;
+ }
+ return NO_ERROR;
+}
+
+status_t CameraService::Client::lock() {
+ int callingPid = getCallingPid();
+ LOG1("lock (pid %d)", callingPid);
+ Mutex::Autolock lock(mLock);
+
+ // lock camera to this client if the the camera is unlocked
+ if (mClientPid == 0) {
+ mClientPid = callingPid;
+ return NO_ERROR;
+ }
+
+ // returns NO_ERROR if the client already owns the camera, EBUSY otherwise
+ return checkPid();
+}
+
+status_t CameraService::Client::unlock() {
+ int callingPid = getCallingPid();
+ LOG1("unlock (pid %d)", callingPid);
+ Mutex::Autolock lock(mLock);
+
+ // allow anyone to use camera (after they lock the camera)
+ status_t result = checkPid();
+ if (result == NO_ERROR) {
+ if (mHardware->recordingEnabled()) {
+ ALOGE("Not allowed to unlock camera during recording.");
+ return INVALID_OPERATION;
+ }
+ mClientPid = 0;
+ LOG1("clear mCameraClient (pid %d)", callingPid);
+ // we need to remove the reference to ICameraClient so that when the app
+ // goes away, the reference count goes to 0.
+ mCameraClient.clear();
+ }
+ return result;
+}
+
+// connect a new client to the camera
+status_t CameraService::Client::connect(const sp<ICameraClient>& client) {
+ int callingPid = getCallingPid();
+ LOG1("connect E (pid %d)", callingPid);
+ Mutex::Autolock lock(mLock);
+
+ if (mClientPid != 0 && checkPid() != NO_ERROR) {
+ ALOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
+ mClientPid, callingPid);
+ return EBUSY;
+ }
+
+ if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {
+ LOG1("Connect to the same client");
+ return NO_ERROR;
+ }
+
+ mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
+ mClientPid = callingPid;
+ mCameraClient = client;
+
+ LOG1("connect X (pid %d)", callingPid);
+ return NO_ERROR;
+}
+
+static void disconnectWindow(const sp<ANativeWindow>& window) {
+ if (window != 0) {
+ status_t result = native_window_api_disconnect(window.get(),
+ NATIVE_WINDOW_API_CAMERA);
+ if (result != NO_ERROR) {
+ ALOGW("native_window_api_disconnect failed: %s (%d)", strerror(-result),
+ result);
+ }
+ }
+}
+
+void CameraService::Client::disconnect() {
+ disconnectInternal(true);
+}
+
+void CameraService::Client::disconnectInternal(bool needCheckPid) {
+ int callingPid = getCallingPid();
+ LOG1("disconnectInternal E (pid %d)", callingPid);
+ Mutex::Autolock lock(mLock);
+
+ if (needCheckPid) {
+ if (checkPid() != NO_ERROR) {
+ ALOGW("different client - don't disconnect");
+ return;
+ }
+
+ if (mClientPid <= 0) {
+ LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
+ return;
+ }
+ }
+
+ // Make sure disconnect() is done once and once only, whether it is called
+ // from the user directly, or called by the destructor.
+ if (mHardware == 0) return;
+
+ LOG1("hardware teardown");
+ // Before destroying mHardware, we must make sure it's in the
+ // idle state.
+ // Turn off all messages.
+ disableMsgType(CAMERA_MSG_ALL_MSGS);
+ mHardware->stopPreview();
+ mHardware->cancelPicture();
+ // Release the hardware resources.
+ mHardware->release();
+
+ // Release the held ANativeWindow resources.
+ if (mPreviewWindow != 0) {
+ disconnectWindow(mPreviewWindow);
+ mPreviewWindow = 0;
+ mHardware->setPreviewWindow(mPreviewWindow);
+ }
+ mHardware.clear();
+
+ mCameraService->removeClient(mCameraClient);
+ mCameraService->setCameraFree(mCameraId);
+ mReleaseCondition.signal();
+
+ LOG1("disconnectInternal X (pid %d)", callingPid);
+}
+
+void CameraService::Client::waitRelease(int ms) {
+ Mutex::Autolock lock(mLock);
+ if (mHardware != 0) {
+ mReleaseCondition.waitRelative(mLock, ms * 1000000);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+status_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder,
+ const sp<ANativeWindow>& window) {
+ Mutex::Autolock lock(mLock);
+ status_t result = checkPidAndHardware();
+ if (result != NO_ERROR) return result;
+
+ // return if no change in surface.
+ if (binder == mSurface) {
+ return NO_ERROR;
+ }
+
+ if (window != 0) {
+ result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
+ if (result != NO_ERROR) {
+ ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result),
+ result);
+ return result;
+ }
+ }
+
+ // If preview has been already started, register preview buffers now.
+ if (mHardware->previewEnabled()) {
+ if (window != 0) {
+ native_window_set_scaling_mode(window.get(),
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+ native_window_set_buffers_transform(window.get(), mOrientation);
+ result = mHardware->setPreviewWindow(window);
+ }
+ }
+
+ if (result == NO_ERROR) {
+ // Everything has succeeded. Disconnect the old window and remember the
+ // new window.
+ disconnectWindow(mPreviewWindow);
+ mSurface = binder;
+ mPreviewWindow = window;
+ } else {
+ // Something went wrong after we connected to the new window, so
+ // disconnect here.
+ disconnectWindow(window);
+ }
+
+ return result;
+}
+
+// set the Surface that the preview will use
+status_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) {
+ LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
+
+ sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);
+ sp<ANativeWindow> window(surface);
+ return setPreviewWindow(binder, window);
+}
+
+// set the SurfaceTexture that the preview will use
+status_t CameraService::Client::setPreviewTexture(
+ const sp<ISurfaceTexture>& surfaceTexture) {
+ LOG1("setPreviewTexture(%p) (pid %d)", surfaceTexture.get(),
+ getCallingPid());
+
+ sp<IBinder> binder;
+ sp<ANativeWindow> window;
+ if (surfaceTexture != 0) {
+ binder = surfaceTexture->asBinder();
+ window = new SurfaceTextureClient(surfaceTexture);
+ }
+ return setPreviewWindow(binder, window);
+}
+
+// set the preview callback flag to affect how the received frames from
+// preview are handled.
+void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
+ LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) return;
+
+ mPreviewCallbackFlag = callback_flag;
+ if (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
+ enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+ } else {
+ disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+ }
+}
+
+// start preview mode
+status_t CameraService::Client::startPreview() {
+ LOG1("startPreview (pid %d)", getCallingPid());
+ return startCameraMode(CAMERA_PREVIEW_MODE);
+}
+
+// start recording mode
+status_t CameraService::Client::startRecording() {
+ LOG1("startRecording (pid %d)", getCallingPid());
+ return startCameraMode(CAMERA_RECORDING_MODE);
+}
+
+// start preview or recording
+status_t CameraService::Client::startCameraMode(camera_mode mode) {
+ LOG1("startCameraMode(%d)", mode);
+ Mutex::Autolock lock(mLock);
+ status_t result = checkPidAndHardware();
+ if (result != NO_ERROR) return result;
+
+ switch(mode) {
+ case CAMERA_PREVIEW_MODE:
+ if (mSurface == 0 && mPreviewWindow == 0) {
+ LOG1("mSurface is not set yet.");
+ // still able to start preview in this case.
+ }
+ return startPreviewMode();
+ case CAMERA_RECORDING_MODE:
+ if (mSurface == 0 && mPreviewWindow == 0) {
+ ALOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
+ return INVALID_OPERATION;
+ }
+ return startRecordingMode();
+ default:
+ return UNKNOWN_ERROR;
+ }
+}
+
+status_t CameraService::Client::startPreviewMode() {
+ LOG1("startPreviewMode");
+ status_t result = NO_ERROR;
+
+ // if preview has been enabled, nothing needs to be done
+ if (mHardware->previewEnabled()) {
+ return NO_ERROR;
+ }
+
+ if (mPreviewWindow != 0) {
+ native_window_set_scaling_mode(mPreviewWindow.get(),
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+ native_window_set_buffers_transform(mPreviewWindow.get(),
+ mOrientation);
+ }
+ mHardware->setPreviewWindow(mPreviewWindow);
+ result = mHardware->startPreview();
+
+ return result;
+}
+
+status_t CameraService::Client::startRecordingMode() {
+ LOG1("startRecordingMode");
+ status_t result = NO_ERROR;
+
+ // if recording has been enabled, nothing needs to be done
+ if (mHardware->recordingEnabled()) {
+ return NO_ERROR;
+ }
+
+ // if preview has not been started, start preview first
+ if (!mHardware->previewEnabled()) {
+ result = startPreviewMode();
+ if (result != NO_ERROR) {
+ return result;
+ }
+ }
+
+ // start recording mode
+ enableMsgType(CAMERA_MSG_VIDEO_FRAME);
+ mCameraService->playSound(SOUND_RECORDING);
+ result = mHardware->startRecording();
+ if (result != NO_ERROR) {
+ ALOGE("mHardware->startRecording() failed with status %d", result);
+ }
+ return result;
+}
+
+// stop preview mode
+void CameraService::Client::stopPreview() {
+ LOG1("stopPreview (pid %d)", getCallingPid());
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) return;
+
+
+ disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+ mHardware->stopPreview();
+
+ mPreviewBuffer.clear();
+}
+
+// stop recording mode
+void CameraService::Client::stopRecording() {
+ LOG1("stopRecording (pid %d)", getCallingPid());
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) return;
+
+ mCameraService->playSound(SOUND_RECORDING);
+ disableMsgType(CAMERA_MSG_VIDEO_FRAME);
+ mHardware->stopRecording();
+
+ mPreviewBuffer.clear();
+}
+
+// release a recording frame
+void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) return;
+ mHardware->releaseRecordingFrame(mem);
+}
+
+status_t CameraService::Client::storeMetaDataInBuffers(bool enabled)
+{
+ LOG1("storeMetaDataInBuffers: %s", enabled? "true": "false");
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) {
+ return UNKNOWN_ERROR;
+ }
+ return mHardware->storeMetaDataInBuffers(enabled);
+}
+
+bool CameraService::Client::previewEnabled() {
+ LOG1("previewEnabled (pid %d)", getCallingPid());
+
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) return false;
+ return mHardware->previewEnabled();
+}
+
+bool CameraService::Client::recordingEnabled() {
+ LOG1("recordingEnabled (pid %d)", getCallingPid());
+
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) return false;
+ return mHardware->recordingEnabled();
+}
+
+status_t CameraService::Client::autoFocus() {
+ LOG1("autoFocus (pid %d)", getCallingPid());
+
+ Mutex::Autolock lock(mLock);
+ status_t result = checkPidAndHardware();
+ if (result != NO_ERROR) return result;
+
+ return mHardware->autoFocus();
+}
+
+status_t CameraService::Client::cancelAutoFocus() {
+ LOG1("cancelAutoFocus (pid %d)", getCallingPid());
+
+ Mutex::Autolock lock(mLock);
+ status_t result = checkPidAndHardware();
+ if (result != NO_ERROR) return result;
+
+ return mHardware->cancelAutoFocus();
+}
+
+// take a picture - image is returned in callback
+status_t CameraService::Client::takePicture(int msgType) {
+ LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);
+
+ Mutex::Autolock lock(mLock);
+ status_t result = checkPidAndHardware();
+ if (result != NO_ERROR) return result;
+
+ if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
+ (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
+ ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
+ " cannot be both enabled");
+ return BAD_VALUE;
+ }
+
+ // We only accept picture related message types
+ // and ignore other types of messages for takePicture().
+ int picMsgType = msgType
+ & (CAMERA_MSG_SHUTTER |
+ CAMERA_MSG_POSTVIEW_FRAME |
+ CAMERA_MSG_RAW_IMAGE |
+ CAMERA_MSG_RAW_IMAGE_NOTIFY |
+ CAMERA_MSG_COMPRESSED_IMAGE);
+
+ enableMsgType(picMsgType);
+
+ return mHardware->takePicture();
+}
+
+// set preview/capture parameters - key/value pairs
+status_t CameraService::Client::setParameters(const String8& params) {
+ LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
+
+ Mutex::Autolock lock(mLock);
+ status_t result = checkPidAndHardware();
+ if (result != NO_ERROR) return result;
+
+ CameraParameters p(params);
+ return mHardware->setParameters(p);
+}
+
+// get preview/capture parameters - key/value pairs
+String8 CameraService::Client::getParameters() const {
+ Mutex::Autolock lock(mLock);
+ if (checkPidAndHardware() != NO_ERROR) return String8();
+
+ String8 params(mHardware->getParameters().flatten());
+ LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
+ return params;
+}
+
+// enable shutter sound
+status_t CameraService::Client::enableShutterSound(bool enable) {
+ LOG1("enableShutterSound (pid %d)", getCallingPid());
+
+ status_t result = checkPidAndHardware();
+ if (result != NO_ERROR) return result;
+
+ if (enable) {
+ mPlayShutterSound = true;
+ return OK;
+ }
+
+ // Disabling shutter sound may not be allowed. In that case only
+ // allow the mediaserver process to disable the sound.
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.camera.sound.forced", value, "0");
+ if (strcmp(value, "0") != 0) {
+ // Disabling shutter sound is not allowed. Deny if the current
+ // process is not mediaserver.
+ if (getCallingPid() != getpid()) {
+ ALOGE("Failed to disable shutter sound. Permission denied (pid %d)", getCallingPid());
+ return PERMISSION_DENIED;
+ }
+ }
+
+ mPlayShutterSound = false;
+ return OK;
+}
+
+status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
+ LOG1("sendCommand (pid %d)", getCallingPid());
+ int orientation;
+ Mutex::Autolock lock(mLock);
+ status_t result = checkPidAndHardware();
+ if (result != NO_ERROR) return result;
+
+ if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
+ // Mirror the preview if the camera is front-facing.
+ orientation = getOrientation(arg1, mCameraFacing == CAMERA_FACING_FRONT);
+ if (orientation == -1) return BAD_VALUE;
+
+ if (mOrientation != orientation) {
+ mOrientation = orientation;
+ if (mPreviewWindow != 0) {
+ native_window_set_buffers_transform(mPreviewWindow.get(),
+ mOrientation);
+ }
+ }
+ return OK;
+ } else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) {
+ switch (arg1) {
+ case 0:
+ enableShutterSound(false);
+ break;
+ case 1:
+ enableShutterSound(true);
+ break;
+ default:
+ return BAD_VALUE;
+ }
+ return OK;
+ } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) {
+ mCameraService->playSound(SOUND_RECORDING);
+ } else if (cmd == CAMERA_CMD_PING) {
+ // If mHardware is 0, checkPidAndHardware will return error.
+ return OK;
+ }
+
+ return mHardware->sendCommand(cmd, arg1, arg2);
+}
+
+// ----------------------------------------------------------------------------
+
+void CameraService::Client::enableMsgType(int32_t msgType) {
+ android_atomic_or(msgType, &mMsgEnabled);
+ mHardware->enableMsgType(msgType);
+}
+
+void CameraService::Client::disableMsgType(int32_t msgType) {
+ android_atomic_and(~msgType, &mMsgEnabled);
+ mHardware->disableMsgType(msgType);
+}
+
+#define CHECK_MESSAGE_INTERVAL 10 // 10ms
+bool CameraService::Client::lockIfMessageWanted(int32_t msgType) {
+ int sleepCount = 0;
+ while (mMsgEnabled & msgType) {
+ if (mLock.tryLock() == NO_ERROR) {
+ if (sleepCount > 0) {
+ LOG1("lockIfMessageWanted(%d): waited for %d ms",
+ msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
+ }
+ return true;
+ }
+ if (sleepCount++ == 0) {
+ LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
+ }
+ usleep(CHECK_MESSAGE_INTERVAL * 1000);
+ }
+ ALOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
+ return false;
+}
+
+// ----------------------------------------------------------------------------
+
+// Converts from a raw pointer to the client to a strong pointer during a
+// hardware callback. This requires the callbacks only happen when the client
+// is still alive.
+sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user) {
+ sp<Client> client = gCameraService->getClientById((int) user);
+
+ // This could happen if the Client is in the process of shutting down (the
+ // last strong reference is gone, but the destructor hasn't finished
+ // stopping the hardware).
+ if (client == 0) return NULL;
+
+ // The checks below are not necessary and are for debugging only.
+ if (client->mCameraService.get() != gCameraService) {
+ ALOGE("mismatch service!");
+ return NULL;
+ }
+
+ if (client->mHardware == 0) {
+ ALOGE("mHardware == 0: callback after disconnect()?");
+ return NULL;
+ }
+
+ return client;
+}
+
+// Callback messages can be dispatched to internal handlers or pass to our
+// client's callback functions, depending on the message type.
+//
+// notifyCallback:
+// CAMERA_MSG_SHUTTER handleShutter
+// (others) c->notifyCallback
+// dataCallback:
+// CAMERA_MSG_PREVIEW_FRAME handlePreviewData
+// CAMERA_MSG_POSTVIEW_FRAME handlePostview
+// CAMERA_MSG_RAW_IMAGE handleRawPicture
+// CAMERA_MSG_COMPRESSED_IMAGE handleCompressedPicture
+// (others) c->dataCallback
+// dataCallbackTimestamp
+// (others) c->dataCallbackTimestamp
+//
+// NOTE: the *Callback functions grab mLock of the client before passing
+// control to handle* functions. So the handle* functions must release the
+// lock before calling the ICameraClient's callbacks, so those callbacks can
+// invoke methods in the Client class again (For example, the preview frame
+// callback may want to releaseRecordingFrame). The handle* functions must
+// release the lock after all accesses to member variables, so it must be
+// handled very carefully.
+
+void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,
+ int32_t ext2, void* user) {
+ LOG2("notifyCallback(%d)", msgType);
+
+ sp<Client> client = getClientFromCookie(user);
+ if (client == 0) return;
+ if (!client->lockIfMessageWanted(msgType)) return;
+
+ switch (msgType) {
+ case CAMERA_MSG_SHUTTER:
+ // ext1 is the dimension of the yuv picture.
+ client->handleShutter();
+ break;
+ default:
+ client->handleGenericNotify(msgType, ext1, ext2);
+ break;
+ }
+}
+
+void CameraService::Client::dataCallback(int32_t msgType,
+ const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
+ LOG2("dataCallback(%d)", msgType);
+
+ sp<Client> client = getClientFromCookie(user);
+ if (client == 0) return;
+ if (!client->lockIfMessageWanted(msgType)) return;
+
+ if (dataPtr == 0 && metadata == NULL) {
+ ALOGE("Null data returned in data callback");
+ client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+ return;
+ }
+
+ switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) {
+ case CAMERA_MSG_PREVIEW_FRAME:
+ client->handlePreviewData(msgType, dataPtr, metadata);
+ break;
+ case CAMERA_MSG_POSTVIEW_FRAME:
+ client->handlePostview(dataPtr);
+ break;
+ case CAMERA_MSG_RAW_IMAGE:
+ client->handleRawPicture(dataPtr);
+ break;
+ case CAMERA_MSG_COMPRESSED_IMAGE:
+ client->handleCompressedPicture(dataPtr);
+ break;
+ default:
+ client->handleGenericData(msgType, dataPtr, metadata);
+ break;
+ }
+}
+
+void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
+ int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
+ LOG2("dataCallbackTimestamp(%d)", msgType);
+
+ sp<Client> client = getClientFromCookie(user);
+ if (client == 0) return;
+ if (!client->lockIfMessageWanted(msgType)) return;
+
+ if (dataPtr == 0) {
+ ALOGE("Null data returned in data with timestamp callback");
+ client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+ return;
+ }
+
+ client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
+}
+
+// snapshot taken callback
+void CameraService::Client::handleShutter(void) {
+ if (mPlayShutterSound) {
+ mCameraService->playSound(SOUND_SHUTTER);
+ }
+
+ sp<ICameraClient> c = mCameraClient;
+ if (c != 0) {
+ mLock.unlock();
+ c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
+ if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
+ }
+ disableMsgType(CAMERA_MSG_SHUTTER);
+
+ mLock.unlock();
+}
+
+// preview callback - frame buffer update
+void CameraService::Client::handlePreviewData(int32_t msgType,
+ const sp<IMemory>& mem,
+ camera_frame_metadata_t *metadata) {
+ ssize_t offset;
+ size_t size;
+ sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+
+ // local copy of the callback flags
+ int flags = mPreviewCallbackFlag;
+
+ // is callback enabled?
+ if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
+ // If the enable bit is off, the copy-out and one-shot bits are ignored
+ LOG2("frame callback is disabled");
+ mLock.unlock();
+ return;
+ }
+
+ // hold a strong pointer to the client
+ sp<ICameraClient> c = mCameraClient;
+
+ // clear callback flags if no client or one-shot mode
+ if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
+ LOG2("Disable preview callback");
+ mPreviewCallbackFlag &= ~(CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
+ CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
+ CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
+ disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+ }
+
+ if (c != 0) {
+ // Is the received frame copied out or not?
+ if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
+ LOG2("frame is copied");
+ copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata);
+ } else {
+ LOG2("frame is forwarded");
+ mLock.unlock();
+ c->dataCallback(msgType, mem, metadata);
+ }
+ } else {
+ mLock.unlock();
+ }
+}
+
+// picture callback - postview image ready
+void CameraService::Client::handlePostview(const sp<IMemory>& mem) {
+ disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
+
+ sp<ICameraClient> c = mCameraClient;
+ mLock.unlock();
+ if (c != 0) {
+ c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL);
+ }
+}
+
+// picture callback - raw image ready
+void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) {
+ disableMsgType(CAMERA_MSG_RAW_IMAGE);
+
+ ssize_t offset;
+ size_t size;
+ sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+
+ sp<ICameraClient> c = mCameraClient;
+ mLock.unlock();
+ if (c != 0) {
+ c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL);
+ }
+}
+
+// picture callback - compressed picture ready
+void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {
+ disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
+
+ sp<ICameraClient> c = mCameraClient;
+ mLock.unlock();
+ if (c != 0) {
+ c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
+ }
+}
+
+
+void CameraService::Client::handleGenericNotify(int32_t msgType,
+ int32_t ext1, int32_t ext2) {
+ sp<ICameraClient> c = mCameraClient;
+ mLock.unlock();
+ if (c != 0) {
+ c->notifyCallback(msgType, ext1, ext2);
+ }
+}
+
+void CameraService::Client::handleGenericData(int32_t msgType,
+ const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) {
+ sp<ICameraClient> c = mCameraClient;
+ mLock.unlock();
+ if (c != 0) {
+ c->dataCallback(msgType, dataPtr, metadata);
+ }
+}
+
+void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp,
+ int32_t msgType, const sp<IMemory>& dataPtr) {
+ sp<ICameraClient> c = mCameraClient;
+ mLock.unlock();
+ if (c != 0) {
+ c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+ }
+}
+
+void CameraService::Client::copyFrameAndPostCopiedFrame(
+ int32_t msgType, const sp<ICameraClient>& client,
+ const sp<IMemoryHeap>& heap, size_t offset, size_t size,
+ camera_frame_metadata_t *metadata) {
+ LOG2("copyFrameAndPostCopiedFrame");
+ // It is necessary to copy out of pmem before sending this to
+ // the callback. For efficiency, reuse the same MemoryHeapBase
+ // provided it's big enough. Don't allocate the memory or
+ // perform the copy if there's no callback.
+ // hold the preview lock while we grab a reference to the preview buffer
+ sp<MemoryHeapBase> previewBuffer;
+
+ if (mPreviewBuffer == 0) {
+ mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+ } else if (size > mPreviewBuffer->virtualSize()) {
+ mPreviewBuffer.clear();
+ mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+ }
+ if (mPreviewBuffer == 0) {
+ ALOGE("failed to allocate space for preview buffer");
+ mLock.unlock();
+ return;
+ }
+ previewBuffer = mPreviewBuffer;
+
+ memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);
+
+ sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
+ if (frame == 0) {
+ ALOGE("failed to allocate space for frame callback");
+ mLock.unlock();
+ return;
+ }
+
+ mLock.unlock();
+ client->dataCallback(msgType, frame, metadata);
+}
+
+int CameraService::Client::getOrientation(int degrees, bool mirror) {
+ if (!mirror) {
+ if (degrees == 0) return 0;
+ else if (degrees == 90) return HAL_TRANSFORM_ROT_90;
+ else if (degrees == 180) return HAL_TRANSFORM_ROT_180;
+ else if (degrees == 270) return HAL_TRANSFORM_ROT_270;
+ } else { // Do mirror (horizontal flip)
+ if (degrees == 0) { // FLIP_H and ROT_0
+ return HAL_TRANSFORM_FLIP_H;
+ } else if (degrees == 90) { // FLIP_H and ROT_90
+ return HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90;
+ } else if (degrees == 180) { // FLIP_H and ROT_180
+ return HAL_TRANSFORM_FLIP_V;
+ } else if (degrees == 270) { // FLIP_H and ROT_270
+ return HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90;
+ }
+ }
+ ALOGE("Invalid setDisplayOrientation degrees=%d", degrees);
+ return -1;
+}
+
+// Whether the client wants to keep the camera from taking
+bool CameraService::Client::keep() const {
+ return mKeep;
+}
+
+// ----------------------------------------------------------------------------
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleep = 60000;
+
+static bool tryLock(Mutex& mutex)
+{
+ bool locked = false;
+ for (int i = 0; i < kDumpLockRetries; ++i) {
+ if (mutex.tryLock() == NO_ERROR) {
+ locked = true;
+ break;
+ }
+ usleep(kDumpLockSleep);
+ }
+ return locked;
+}
+
+status_t CameraService::dump(int fd, const Vector<String16>& args) {
+ static const char* kDeadlockedString = "CameraService may be deadlocked\n";
+
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+ snprintf(buffer, SIZE, "Permission Denial: "
+ "can't dump CameraService from pid=%d, uid=%d\n",
+ getCallingPid(),
+ getCallingUid());
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+ } else {
+ bool locked = tryLock(mServiceLock);
+ // failed to lock - CameraService is probably deadlocked
+ if (!locked) {
+ String8 result(kDeadlockedString);
+ write(fd, result.string(), result.size());
+ }
+
+ bool hasClient = false;
+ for (int i = 0; i < mNumberOfCameras; i++) {
+ sp<Client> client = mClient[i].promote();
+ if (client == 0) continue;
+ hasClient = true;
+ sprintf(buffer, "Client[%d] (%p) PID: %d\n",
+ i,
+ client->getCameraClient()->asBinder().get(),
+ client->mClientPid);
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+ client->mHardware->dump(fd, args);
+ }
+ if (!hasClient) {
+ result.append("No camera client yet.\n");
+ write(fd, result.string(), result.size());
+ }
+
+ if (locked) mServiceLock.unlock();
+
+ // change logging level
+ int n = args.size();
+ for (int i = 0; i + 1 < n; i++) {
+ if (args[i] == String16("-v")) {
+ String8 levelStr(args[i+1]);
+ int level = atoi(levelStr.string());
+ sprintf(buffer, "Set Log Level to %d", level);
+ result.append(buffer);
+ setLogLevel(level);
+ }
+ }
+ }
+ return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
new file mode 100644
index 0000000..457c79b
--- /dev/null
+++ b/services/camera/libcameraservice/CameraService.h
@@ -0,0 +1,231 @@
+/*
+**
+** 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_SERVERS_CAMERA_CAMERASERVICE_H
+#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
+
+#include <binder/BinderService.h>
+#include <camera/ICameraService.h>
+#include <hardware/camera.h>
+
+/* This needs to be increased if we can have more cameras */
+#define MAX_CAMERAS 2
+
+namespace android {
+
+class MemoryHeapBase;
+class MediaPlayer;
+class CameraHardwareInterface;
+
+class CameraService :
+ public BinderService<CameraService>,
+ public BnCameraService
+{
+ class Client;
+ friend class BinderService<CameraService>;
+public:
+ static char const* getServiceName() { return "media.camera"; }
+
+ CameraService();
+ virtual ~CameraService();
+
+ virtual int32_t getNumberOfCameras();
+ virtual status_t getCameraInfo(int cameraId,
+ struct CameraInfo* cameraInfo);
+ virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId,
+ bool force, bool keep);
+ virtual void removeClient(const sp<ICameraClient>& cameraClient);
+ virtual sp<Client> getClientById(int cameraId);
+
+ virtual status_t dump(int fd, const Vector<String16>& args);
+ virtual status_t onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags);
+ virtual void onFirstRef();
+
+ enum sound_kind {
+ SOUND_SHUTTER = 0,
+ SOUND_RECORDING = 1,
+ NUM_SOUNDS
+ };
+
+ void loadSound();
+ void playSound(sound_kind kind);
+ void releaseSound();
+
+private:
+ Mutex mServiceLock;
+ wp<Client> mClient[MAX_CAMERAS]; // protected by mServiceLock
+ int mNumberOfCameras;
+
+ // atomics to record whether the hardware is allocated to some client.
+ volatile int32_t mBusy[MAX_CAMERAS];
+ void setCameraBusy(int cameraId);
+ void setCameraFree(int cameraId);
+
+ // sounds
+ MediaPlayer* newMediaPlayer(const char *file);
+
+ Mutex mSoundLock;
+ sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS];
+ int mSoundRef; // reference count (release all MediaPlayer when 0)
+
+ class Client : public BnCamera
+ {
+ public:
+ // ICamera interface (see ICamera for details)
+ virtual void disconnect();
+ virtual status_t connect(const sp<ICameraClient>& client);
+ virtual status_t lock();
+ virtual status_t unlock();
+ virtual status_t setPreviewDisplay(const sp<Surface>& surface);
+ virtual status_t setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture);
+ virtual void setPreviewCallbackFlag(int flag);
+ virtual status_t startPreview();
+ virtual void stopPreview();
+ virtual bool previewEnabled();
+ virtual status_t storeMetaDataInBuffers(bool enabled);
+ virtual status_t startRecording();
+ virtual void stopRecording();
+ virtual bool recordingEnabled();
+ virtual void releaseRecordingFrame(const sp<IMemory>& mem);
+ virtual status_t autoFocus();
+ virtual status_t cancelAutoFocus();
+ virtual status_t takePicture(int msgType);
+ virtual status_t setParameters(const String8& params);
+ virtual String8 getParameters() const;
+ virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+ private:
+ friend class CameraService;
+ Client(const sp<CameraService>& cameraService,
+ const sp<ICameraClient>& cameraClient,
+ const sp<CameraHardwareInterface>& hardware,
+ int cameraId,
+ int cameraFacing,
+ int clientPid,
+ bool keep);
+ ~Client();
+
+ // return our camera client
+ const sp<ICameraClient>& getCameraClient() { return mCameraClient; }
+
+ // check whether the calling process matches mClientPid.
+ status_t checkPid() const;
+ status_t checkPidAndHardware() const; // also check mHardware != 0
+
+ // these are internal functions used to set up preview buffers
+ status_t registerPreviewBuffers();
+
+ // camera operation mode
+ enum camera_mode {
+ CAMERA_PREVIEW_MODE = 0, // frame automatically released
+ CAMERA_RECORDING_MODE = 1, // frame has to be explicitly released by releaseRecordingFrame()
+ };
+ // these are internal functions used for preview/recording
+ status_t startCameraMode(camera_mode mode);
+ status_t startPreviewMode();
+ status_t startRecordingMode();
+
+ // internal function used by sendCommand to enable/disable shutter sound.
+ status_t enableShutterSound(bool enable);
+
+ // these are static callback functions
+ static void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
+ static void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata, void* user);
+ static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user);
+ // convert client from cookie
+ static sp<Client> getClientFromCookie(void* user);
+ // handlers for messages
+ void handleShutter(void);
+ void handlePreviewData(int32_t msgType, const sp<IMemory>& mem,
+ camera_frame_metadata_t *metadata);
+ void handlePostview(const sp<IMemory>& mem);
+ void handleRawPicture(const sp<IMemory>& mem);
+ void handleCompressedPicture(const sp<IMemory>& mem);
+ void handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2);
+ void handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata);
+ void handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
+
+ void copyFrameAndPostCopiedFrame(
+ int32_t msgType,
+ const sp<ICameraClient>& client,
+ const sp<IMemoryHeap>& heap,
+ size_t offset, size_t size,
+ camera_frame_metadata_t *metadata);
+
+ int getOrientation(int orientation, bool mirror);
+
+ status_t setPreviewWindow(
+ const sp<IBinder>& binder,
+ const sp<ANativeWindow>& window);
+
+ void disconnectInternal(bool needCheckPid);
+ bool keep() const;
+ void waitRelease(int ms);
+
+
+ // these are initialized in the constructor.
+ sp<CameraService> mCameraService; // immutable after constructor
+ sp<ICameraClient> mCameraClient;
+ int mCameraId; // immutable after constructor
+ int mCameraFacing; // immutable after constructor
+ pid_t mClientPid;
+ // Client wants to keep the camera from taking by other clients.
+ bool mKeep;
+ sp<CameraHardwareInterface> mHardware; // cleared after disconnect()
+ int mPreviewCallbackFlag;
+ int mOrientation; // Current display orientation
+ bool mPlayShutterSound;
+
+ // Ensures atomicity among the public methods
+ mutable Mutex mLock;
+ // This will get notified when the hardware is released.
+ Condition mReleaseCondition;
+ // This is a binder of Surface or SurfaceTexture.
+ sp<IBinder> mSurface;
+ sp<ANativeWindow> mPreviewWindow;
+
+ // If the user want us to return a copy of the preview frame (instead
+ // of the original one), we allocate mPreviewBuffer and reuse it if possible.
+ sp<MemoryHeapBase> mPreviewBuffer;
+
+ // We need to avoid the deadlock when the incoming command thread and
+ // the CameraHardwareInterface callback thread both want to grab mLock.
+ // An extra flag is used to tell the callback thread that it should stop
+ // trying to deliver the callback messages if the client is not
+ // interested in it anymore. For example, if the client is calling
+ // stopPreview(), the preview frame messages do not need to be delivered
+ // anymore.
+
+ // This function takes the same parameter as the enableMsgType() and
+ // disableMsgType() functions in CameraHardwareInterface.
+ void enableMsgType(int32_t msgType);
+ void disableMsgType(int32_t msgType);
+ volatile int32_t mMsgEnabled;
+
+ // This function keeps trying to grab mLock, or give up if the message
+ // is found to be disabled. It returns true if mLock is grabbed.
+ bool lockIfMessageWanted(int32_t msgType);
+ };
+
+ camera_module_t *mModule;
+};
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/CannedJpeg.h b/services/camera/libcameraservice/CannedJpeg.h
new file mode 100644
index 0000000..6dd99c1
--- /dev/null
+++ b/services/camera/libcameraservice/CannedJpeg.h
@@ -0,0 +1,750 @@
+/*
+ * 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.
+ */
+
+const int kCannedJpegWidth = 320;
+const int kCannedJpegHeight = 240;
+const int kCannedJpegSize = 8733;
+
+const char kCannedJpeg[] = {
+ 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
+ 0x01, 0x01, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0xff, 0xe1, 0x00, 0x66,
+ 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x49, 0x49, 0x2a, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x1a, 0x01, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x3e, 0x00, 0x00, 0x00, 0x1b, 0x01, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x46, 0x00, 0x00, 0x00, 0x28, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x31, 0x01, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x50, 0x61, 0x69, 0x6e, 0x74, 0x2e, 0x4e, 0x45, 0x54, 0x20, 0x76, 0x33,
+ 0x2e, 0x33, 0x36, 0x00, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02,
+ 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x05,
+ 0x08, 0x05, 0x05, 0x04, 0x04, 0x05, 0x0a, 0x07, 0x07, 0x06, 0x08, 0x0c,
+ 0x0a, 0x0c, 0x0c, 0x0b, 0x0a, 0x0b, 0x0b, 0x0d, 0x0e, 0x12, 0x10, 0x0d,
+ 0x0e, 0x11, 0x0e, 0x0b, 0x0b, 0x10, 0x16, 0x10, 0x11, 0x13, 0x14, 0x15,
+ 0x15, 0x15, 0x0c, 0x0f, 0x17, 0x18, 0x16, 0x14, 0x18, 0x12, 0x14, 0x15,
+ 0x14, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05,
+ 0x09, 0x05, 0x05, 0x09, 0x14, 0x0d, 0x0b, 0x0d, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0xff, 0xc0,
+ 0x00, 0x11, 0x08, 0x00, 0xf0, 0x01, 0x40, 0x03, 0x01, 0x22, 0x00, 0x02,
+ 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00, 0x1f, 0x00, 0x00, 0x01,
+ 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0xff, 0xc4, 0x00, 0xb5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03,
+ 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01,
+ 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
+ 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
+ 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82,
+ 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29,
+ 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
+ 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
+ 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
+ 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
+ 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
+ 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
+ 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3,
+ 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
+ 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc4, 0x00, 0x1f, 0x01, 0x00, 0x03,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0xff, 0xc4, 0x00, 0xb5, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04,
+ 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00,
+ 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51,
+ 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1,
+ 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a,
+ 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
+ 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75,
+ 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+ 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2,
+ 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5,
+ 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
+ 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5,
+ 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00,
+ 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0xf9, 0xd2, 0xa3, 0x95, 0xbb,
+ 0x54, 0x84, 0xe0, 0x66, 0xa0, 0x27, 0x27, 0x35, 0xed, 0x9e, 0x50, 0x95,
+ 0x2c, 0x4b, 0xc6, 0x6a, 0x35, 0x1b, 0x8e, 0x2a, 0x70, 0x30, 0x28, 0x00,
+ 0xa8, 0xe5, 0x6e, 0x71, 0x52, 0x31, 0xda, 0x33, 0x50, 0x13, 0x93, 0x40,
+ 0x09, 0x52, 0xc6, 0xb8, 0x19, 0xf5, 0xa6, 0x2a, 0xee, 0x6c, 0x54, 0xd4,
+ 0x00, 0x54, 0x52, 0x36, 0x5b, 0x1e, 0x95, 0x23, 0xb6, 0xd5, 0xcd, 0x41,
+ 0x40, 0x05, 0x4c, 0x8b, 0xb5, 0x7d, 0xea, 0x34, 0x5d, 0xcd, 0xed, 0x53,
+ 0x50, 0x01, 0x50, 0xbb, 0x6e, 0x6f, 0x6a, 0x91, 0xdb, 0x6a, 0xfb, 0xd4,
+ 0x34, 0x00, 0x54, 0xe8, 0xbb, 0x57, 0x15, 0x1c, 0x6b, 0x96, 0xcf, 0xa5,
+ 0x4b, 0x40, 0x05, 0x42, 0xcd, 0xb9, 0xb3, 0x4f, 0x91, 0xb0, 0x31, 0xeb,
+ 0x51, 0x50, 0x02, 0x81, 0x93, 0x53, 0xa8, 0xda, 0x31, 0x51, 0xc4, 0xbc,
+ 0xe6, 0xa4, 0xa0, 0x00, 0x9c, 0x0a, 0x81, 0x8e, 0xe3, 0x9a, 0x92, 0x56,
+ 0xe3, 0x15, 0x15, 0x00, 0x28, 0x19, 0x38, 0xa9, 0xc0, 0xc0, 0xc5, 0x47,
+ 0x12, 0xf7, 0xa9, 0x28, 0x00, 0x27, 0x00, 0x9a, 0x80, 0x9c, 0x9c, 0xd3,
+ 0xe5, 0x6e, 0xd5, 0x1d, 0x00, 0x2a, 0x8d, 0xc7, 0x15, 0x3d, 0x32, 0x35,
+ 0xc0, 0xcf, 0xad, 0x3e, 0x80, 0x11, 0x8e, 0xd1, 0x9a, 0x82, 0x9f, 0x23,
+ 0x64, 0xe3, 0xd2, 0x99, 0x40, 0x0e, 0x45, 0xdc, 0xde, 0xd5, 0x35, 0x36,
+ 0x35, 0xc2, 0xfb, 0x9a, 0x75, 0x00, 0x35, 0xdb, 0x6a, 0xfb, 0xd4, 0x34,
+ 0xe9, 0x1b, 0x73, 0x7b, 0x0a, 0x6d, 0x00, 0x3e, 0x35, 0xcb, 0x7b, 0x0a,
+ 0x96, 0x91, 0x17, 0x6a, 0xd2, 0xd0, 0x03, 0x64, 0x6c, 0x2f, 0xb9, 0xa8,
+ 0x69, 0xce, 0xdb, 0x9a, 0x9b, 0xd6, 0x80, 0x1f, 0x12, 0xe4, 0xe7, 0xd2,
+ 0xa5, 0xa4, 0x51, 0xb4, 0x62, 0x97, 0xa5, 0x00, 0x67, 0xc9, 0xad, 0xd8,
+ 0x91, 0x81, 0x72, 0x9f, 0x9d, 0x47, 0xfd, 0xb3, 0x65, 0xff, 0x00, 0x3f,
+ 0x29, 0x5f, 0xa0, 0x1f, 0xf0, 0xe9, 0x6f, 0x09, 0x7f, 0xd0, 0xfb, 0xad,
+ 0x7f, 0xe0, 0x24, 0x34, 0x7f, 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43,
+ 0xee, 0xb5, 0xff, 0x00, 0x80, 0x90, 0xd7, 0x3f, 0xb7, 0x87, 0x73, 0x6f,
+ 0x63, 0x33, 0xe0, 0x28, 0xf5, 0x9b, 0x11, 0xc9, 0xb9, 0x4c, 0xfd, 0x69,
+ 0xff, 0x00, 0xdb, 0x96, 0x1f, 0xf3, 0xf5, 0x1f, 0xe7, 0x5f, 0x7d, 0x7f,
+ 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5, 0xff, 0x00, 0x80,
+ 0x90, 0xd1, 0xff, 0x00, 0x0e, 0x96, 0xf0, 0x97, 0xfd, 0x0f, 0xba, 0xd7,
+ 0xfe, 0x02, 0x43, 0x47, 0xb7, 0x87, 0x70, 0xf6, 0x33, 0x3e, 0x02, 0x93,
+ 0x5b, 0xb1, 0x3c, 0x0b, 0x94, 0xc7, 0xd6, 0x99, 0xfd, 0xb3, 0x65, 0xff,
+ 0x00, 0x3f, 0x29, 0xf9, 0xd7, 0xe8, 0x07, 0xfc, 0x3a, 0x5b, 0xc2, 0x5f,
+ 0xf4, 0x3e, 0xeb, 0x5f, 0xf8, 0x09, 0x0d, 0x1f, 0xf0, 0xe9, 0x6f, 0x09,
+ 0x7f, 0xd0, 0xfb, 0xad, 0x7f, 0xe0, 0x24, 0x34, 0xbd, 0xbc, 0x03, 0xd8,
+ 0xcc, 0xf8, 0x0e, 0x3d, 0x6a, 0xc1, 0x47, 0x37, 0x29, 0x9f, 0xad, 0x3b,
+ 0xfb, 0x72, 0xc3, 0xfe, 0x7e, 0xa3, 0xfc, 0xeb, 0xef, 0xaf, 0xf8, 0x74,
+ 0xb7, 0x84, 0xbf, 0xe8, 0x7d, 0xd6, 0xbf, 0xf0, 0x12, 0x1a, 0x3f, 0xe1,
+ 0xd2, 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff, 0x00, 0xc0, 0x48,
+ 0x69, 0xfb, 0x78, 0x77, 0x0f, 0x63, 0x33, 0xe0, 0x19, 0x35, 0xbb, 0x26,
+ 0x3c, 0x5c, 0xa6, 0x3e, 0xb4, 0xdf, 0xed, 0x9b, 0x2f, 0xf9, 0xf9, 0x4a,
+ 0xfd, 0x00, 0xff, 0x00, 0x87, 0x4b, 0x78, 0x4b, 0xfe, 0x87, 0xdd, 0x6b,
+ 0xff, 0x00, 0x01, 0x21, 0xa3, 0xfe, 0x1d, 0x2d, 0xe1, 0x2f, 0xfa, 0x1f,
+ 0x75, 0xaf, 0xfc, 0x04, 0x86, 0x97, 0xb7, 0x80, 0x7b, 0x19, 0x9f, 0x01,
+ 0xa6, 0xb5, 0x60, 0xab, 0xff, 0x00, 0x1f, 0x51, 0xe7, 0xeb, 0x4e, 0xfe,
+ 0xdc, 0xb0, 0xff, 0x00, 0x9f, 0xa8, 0xff, 0x00, 0x3a, 0xfb, 0xeb, 0xfe,
+ 0x1d, 0x2d, 0xe1, 0x2f, 0xfa, 0x1f, 0x75, 0xaf, 0xfc, 0x04, 0x86, 0x8f,
+ 0xf8, 0x74, 0xb7, 0x84, 0xbf, 0xe8, 0x7d, 0xd6, 0xbf, 0xf0, 0x12, 0x1a,
+ 0x3d, 0xbc, 0x03, 0xd8, 0xcc, 0xf8, 0x05, 0xf5, 0xab, 0x26, 0x6f, 0xf8,
+ 0xf9, 0x4c, 0x7d, 0x69, 0xbf, 0xdb, 0x36, 0x5f, 0xf3, 0xf2, 0x9f, 0x9d,
+ 0x7e, 0x80, 0x7f, 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5,
+ 0xff, 0x00, 0x80, 0x90, 0xd1, 0xff, 0x00, 0x0e, 0x96, 0xf0, 0x97, 0xfd,
+ 0x0f, 0xba, 0xd7, 0xfe, 0x02, 0x43, 0x47, 0xb7, 0x80, 0x7b, 0x19, 0x9f,
+ 0x02, 0x26, 0xb5, 0x60, 0xab, 0x8f, 0xb5, 0x47, 0xf9, 0xd2, 0xff, 0x00,
+ 0x6e, 0x58, 0x7f, 0xcf, 0xd4, 0x7f, 0x9d, 0x7d, 0xf5, 0xff, 0x00, 0x0e,
+ 0x96, 0xf0, 0x97, 0xfd, 0x0f, 0xba, 0xd7, 0xfe, 0x02, 0x43, 0x47, 0xfc,
+ 0x3a, 0x5b, 0xc2, 0x5f, 0xf4, 0x3e, 0xeb, 0x5f, 0xf8, 0x09, 0x0d, 0x1e,
+ 0xde, 0x01, 0xec, 0x66, 0x7c, 0x00, 0xda, 0xd5, 0x93, 0x1c, 0xfd, 0xa5,
+ 0x3f, 0x3a, 0x4f, 0xed, 0x8b, 0x2f, 0xf9, 0xf9, 0x4f, 0xce, 0xbf, 0x40,
+ 0x3f, 0xe1, 0xd2, 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff, 0x00,
+ 0xc0, 0x48, 0x68, 0xff, 0x00, 0x87, 0x4b, 0x78, 0x4b, 0xfe, 0x87, 0xdd,
+ 0x6b, 0xff, 0x00, 0x01, 0x21, 0xa7, 0xed, 0xe1, 0xdc, 0x3d, 0x8c, 0xcf,
+ 0x81, 0x57, 0x5a, 0xb0, 0x51, 0x8f, 0xb5, 0x47, 0xf9, 0xd1, 0xfd, 0xb9,
+ 0x61, 0xff, 0x00, 0x3f, 0x49, 0xf9, 0xd7, 0xdf, 0x5f, 0xf0, 0xe9, 0x6f,
+ 0x09, 0x7f, 0xd0, 0xfb, 0xad, 0x7f, 0xe0, 0x24, 0x34, 0x7f, 0xc3, 0xa5,
+ 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5, 0xff, 0x00, 0x80, 0x90, 0xd2,
+ 0xf6, 0xf0, 0x0f, 0x63, 0x33, 0xe0, 0x06, 0xd6, 0xac, 0x98, 0xe7, 0xed,
+ 0x29, 0xf9, 0xd2, 0x0d, 0x62, 0xcb, 0xfe, 0x7e, 0x53, 0xf3, 0xaf, 0xd0,
+ 0x0f, 0xf8, 0x74, 0xb7, 0x84, 0xbf, 0xe8, 0x7d, 0xd6, 0xbf, 0xf0, 0x12,
+ 0x1a, 0x3f, 0xe1, 0xd2, 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff,
+ 0x00, 0xc0, 0x48, 0x69, 0xfb, 0x78, 0x77, 0x0f, 0x63, 0x33, 0xe0, 0x51,
+ 0xad, 0xd8, 0x01, 0x8f, 0xb5, 0x47, 0xf9, 0xd0, 0x75, 0xcb, 0x0c, 0x7f,
+ 0xc7, 0xca, 0x7e, 0x75, 0xf7, 0xd7, 0xfc, 0x3a, 0x5b, 0xc2, 0x5f, 0xf4,
+ 0x3e, 0xeb, 0x5f, 0xf8, 0x09, 0x0d, 0x1f, 0xf0, 0xe9, 0x6f, 0x09, 0x7f,
+ 0xd0, 0xfb, 0xad, 0x7f, 0xe0, 0x24, 0x34, 0x7b, 0x78, 0x77, 0x0f, 0x63,
+ 0x33, 0xf3, 0xfc, 0xeb, 0x36, 0x44, 0xff, 0x00, 0xc7, 0xca, 0x7e, 0x74,
+ 0xa3, 0x58, 0xb1, 0x24, 0x66, 0xe5, 0x31, 0xf5, 0xaf, 0xbf, 0xff, 0x00,
+ 0xe1, 0xd2, 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff, 0x00, 0xc0,
+ 0x48, 0x68, 0xff, 0x00, 0x87, 0x4b, 0x78, 0x4b, 0xfe, 0x87, 0xdd, 0x6b,
+ 0xff, 0x00, 0x01, 0x21, 0xa3, 0xdb, 0xc3, 0xb8, 0x7b, 0x19, 0x9f, 0x02,
+ 0xff, 0x00, 0x6d, 0xd8, 0x7f, 0xcf, 0xd4, 0x7f, 0x9d, 0x07, 0x5c, 0xb1,
+ 0x03, 0x8b, 0x94, 0xcf, 0xd6, 0xbe, 0xfa, 0xff, 0x00, 0x87, 0x4b, 0x78,
+ 0x4b, 0xfe, 0x87, 0xdd, 0x6b, 0xff, 0x00, 0x01, 0x21, 0xa3, 0xfe, 0x1d,
+ 0x2d, 0xe1, 0x2f, 0xfa, 0x1f, 0x75, 0xaf, 0xfc, 0x04, 0x86, 0x8f, 0x6f,
+ 0x0e, 0xe1, 0xec, 0x66, 0x7e, 0x7f, 0xff, 0x00, 0x6c, 0xd9, 0x7f, 0xcf,
+ 0xca, 0x7e, 0x74, 0xab, 0xac, 0x58, 0xe7, 0x9b, 0x94, 0xc7, 0xd6, 0xbe,
+ 0xff, 0x00, 0xff, 0x00, 0x87, 0x4b, 0x78, 0x4b, 0xfe, 0x87, 0xdd, 0x6b,
+ 0xff, 0x00, 0x01, 0x21, 0xa3, 0xfe, 0x1d, 0x2d, 0xe1, 0x2f, 0xfa, 0x1f,
+ 0x75, 0xaf, 0xfc, 0x04, 0x86, 0x8f, 0x6f, 0x0e, 0xe1, 0xec, 0x66, 0x7c,
+ 0x0b, 0xfd, 0xb9, 0x61, 0xff, 0x00, 0x3f, 0x51, 0xfe, 0x74, 0x8d, 0xae,
+ 0x58, 0xed, 0x38, 0xb9, 0x4c, 0xfd, 0x6b, 0xef, 0xbf, 0xf8, 0x74, 0xb7,
+ 0x84, 0xbf, 0xe8, 0x7d, 0xd6, 0xbf, 0xf0, 0x12, 0x1a, 0x3f, 0xe1, 0xd2,
+ 0xde, 0x12, 0xff, 0x00, 0xa1, 0xf7, 0x5a, 0xff, 0x00, 0xc0, 0x48, 0x68,
+ 0xf6, 0xf0, 0xee, 0x1e, 0xc6, 0x67, 0xe7, 0xff, 0x00, 0xf6, 0xc5, 0x97,
+ 0xfc, 0xfc, 0xa7, 0xe7, 0x4e, 0x4d, 0x62, 0xc7, 0x77, 0x37, 0x29, 0xf9,
+ 0xd7, 0xdf, 0xdf, 0xf0, 0xe9, 0x6f, 0x09, 0x7f, 0xd0, 0xfb, 0xad, 0x7f,
+ 0xe0, 0x24, 0x34, 0x7f, 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee,
+ 0xb5, 0xff, 0x00, 0x80, 0x90, 0xd1, 0xed, 0xe1, 0xdc, 0x3d, 0x8c, 0xcf,
+ 0x81, 0x7f, 0xb7, 0x2c, 0x3f, 0xe7, 0xea, 0x3f, 0xce, 0x91, 0xf5, 0xcb,
+ 0x1c, 0x71, 0x72, 0x9f, 0x9d, 0x7d, 0xf7, 0xff, 0x00, 0x0e, 0x96, 0xf0,
+ 0x97, 0xfd, 0x0f, 0xba, 0xd7, 0xfe, 0x02, 0x43, 0x47, 0xfc, 0x3a, 0x5b,
+ 0xc2, 0x5f, 0xf4, 0x3e, 0xeb, 0x5f, 0xf8, 0x09, 0x0d, 0x1e, 0xde, 0x1d,
+ 0xc3, 0xd8, 0xcc, 0xfc, 0xff, 0x00, 0xfe, 0xd9, 0xb2, 0xff, 0x00, 0x9f,
+ 0x94, 0xfc, 0xe9, 0xd1, 0xeb, 0x36, 0x20, 0xe4, 0xdc, 0xa7, 0xe7, 0x5f,
+ 0x7f, 0x7f, 0xc3, 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5, 0xff,
+ 0x00, 0x80, 0x90, 0xd1, 0xff, 0x00, 0x0e, 0x96, 0xf0, 0x97, 0xfd, 0x0f,
+ 0xba, 0xd7, 0xfe, 0x02, 0x43, 0x47, 0xb7, 0x87, 0x70, 0xf6, 0x33, 0x3e,
+ 0x05, 0xfe, 0xdc, 0xb0, 0xff, 0x00, 0x9f, 0xa8, 0xff, 0x00, 0x3a, 0x6c,
+ 0x9a, 0xdd, 0x89, 0x18, 0x17, 0x29, 0xf9, 0xd7, 0xdf, 0x9f, 0xf0, 0xe9,
+ 0x6f, 0x09, 0x7f, 0xd0, 0xfb, 0xad, 0x7f, 0xe0, 0x24, 0x34, 0x7f, 0xc3,
+ 0xa5, 0xbc, 0x25, 0xff, 0x00, 0x43, 0xee, 0xb5, 0xff, 0x00, 0x80, 0x90,
+ 0xd1, 0xed, 0xe1, 0xdc, 0x3d, 0x8c, 0xcf, 0xbc, 0xa8, 0xa2, 0x8a, 0xf3,
+ 0x0e, 0xf0, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a,
+ 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a,
+ 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0xa0, 0xbb, 0xbd, 0xb7, 0xb0,
+ 0x88, 0x49, 0x73, 0x3c, 0x56, 0xf1, 0x96, 0x0a, 0x1e, 0x57, 0x0a, 0x09,
+ 0x3d, 0x06, 0x4f, 0x7a, 0x9e, 0x95, 0xd3, 0x76, 0xea, 0x01, 0x45, 0x14,
+ 0x53, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a, 0x82, 0xda, 0xf6, 0xde,
+ 0xf0, 0xca, 0x2d, 0xe7, 0x8a, 0x73, 0x13, 0x98, 0xe4, 0xf2, 0xdc, 0x36,
+ 0xc6, 0x1d, 0x54, 0xe3, 0xa1, 0xf6, 0xa4, 0xda, 0x4e, 0xcc, 0x09, 0xe8,
+ 0xa2, 0x8a, 0x60, 0x14, 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14,
+ 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14,
+ 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x02, 0xb8,
+ 0x51, 0x45, 0x14, 0x05, 0xc2, 0x8a, 0x28, 0xa0, 0x2e, 0x14, 0x51, 0x45,
+ 0x01, 0x70, 0xa2, 0x8a, 0x28, 0x18, 0x51, 0x45, 0x14, 0x0a, 0xe1, 0x45,
+ 0x14, 0x50, 0x17, 0x0a, 0x28, 0xa2, 0x80, 0xb9, 0xca, 0xfc, 0x4a, 0xf0,
+ 0x52, 0x78, 0xef, 0xc2, 0xb7, 0x1a, 0x76, 0xef, 0x2e, 0xe5, 0x4f, 0x9d,
+ 0x6c, 0xe4, 0xe0, 0x09, 0x00, 0x38, 0xcf, 0xb1, 0xc9, 0x1f, 0x8e, 0x7b,
+ 0x57, 0x3d, 0xf0, 0x5b, 0xc7, 0x53, 0x6b, 0xba, 0x6c, 0xda, 0x16, 0xaa,
+ 0x5a, 0x3d, 0x73, 0x4a, 0xfd, 0xd4, 0x8b, 0x2f, 0xdf, 0x91, 0x01, 0xc0,
+ 0x27, 0xdc, 0x1e, 0x0f, 0xe0, 0x7b, 0xd7, 0xa3, 0x5c, 0xdc, 0xc5, 0x67,
+ 0x04, 0x93, 0xcf, 0x2a, 0x43, 0x0c, 0x60, 0xb3, 0xc9, 0x23, 0x05, 0x55,
+ 0x1e, 0xa4, 0x9e, 0x95, 0xf3, 0x47, 0xc4, 0x8f, 0x1f, 0xe9, 0x36, 0xdf,
+ 0x10, 0xed, 0x3c, 0x41, 0xe1, 0x39, 0x99, 0xaf, 0xa1, 0xe2, 0xea, 0x42,
+ 0x98, 0x82, 0x72, 0x38, 0xe3, 0x90, 0x4e, 0x46, 0x41, 0xe9, 0x9c, 0x0c,
+ 0x7a, 0xd7, 0xc4, 0x67, 0x98, 0x9a, 0x59, 0x3e, 0x26, 0x9e, 0x64, 0xa6,
+ 0x93, 0x7e, 0xec, 0xe3, 0x7d, 0x65, 0x1e, 0xe9, 0x77, 0x8b, 0xd7, 0xd3,
+ 0x4b, 0x99, 0x4d, 0xa8, 0xbe, 0x63, 0xe9, 0xca, 0x2b, 0xe4, 0x3d, 0x73,
+ 0xe3, 0x3f, 0x8b, 0xb5, 0xc6, 0x6d, 0xfa, 0xb4, 0x96, 0x71, 0x9e, 0x91,
+ 0x59, 0x0f, 0x28, 0x0f, 0xc4, 0x7c, 0xdf, 0x99, 0xae, 0x56, 0xe7, 0x5a,
+ 0xd4, 0x6f, 0x18, 0xb5, 0xc5, 0xfd, 0xd4, 0xec, 0x7b, 0xc9, 0x33, 0x31,
+ 0xfd, 0x4d, 0x78, 0x75, 0xf8, 0xfb, 0x0b, 0x07, 0x6a, 0x14, 0x65, 0x25,
+ 0xe6, 0xd2, 0xff, 0x00, 0x32, 0x1d, 0x75, 0xd1, 0x1f, 0x73, 0x51, 0x5f,
+ 0x0b, 0xdb, 0xea, 0xf7, 0xf6, 0xad, 0xba, 0x0b, 0xdb, 0x88, 0x58, 0x77,
+ 0x8e, 0x56, 0x53, 0xfa, 0x1a, 0xe9, 0xf4, 0x5f, 0x8b, 0xfe, 0x2e, 0xd0,
+ 0xd9, 0x7c, 0xad, 0x66, 0x7b, 0x84, 0x1f, 0xf2, 0xce, 0xec, 0xf9, 0xc0,
+ 0xff, 0x00, 0xdf, 0x59, 0x23, 0xf0, 0x34, 0xa8, 0x71, 0xf6, 0x1a, 0x4e,
+ 0xd5, 0xa8, 0x4a, 0x2b, 0xc9, 0xa7, 0xfe, 0x40, 0xab, 0xae, 0xa8, 0xfa,
+ 0x13, 0xe2, 0xff, 0x00, 0x8f, 0xcf, 0x82, 0xfc, 0x3e, 0x21, 0xb3, 0x6d,
+ 0xda, 0xcd, 0xfe, 0x62, 0xb5, 0x45, 0xe5, 0x97, 0xb1, 0x7c, 0x7b, 0x67,
+ 0x8f, 0x72, 0x3d, 0xea, 0x5f, 0x84, 0x7e, 0x05, 0x6f, 0x04, 0x78, 0x60,
+ 0x2d, 0xd1, 0x2d, 0xa9, 0xde, 0xb0, 0x9e, 0xe8, 0x93, 0x9d, 0xad, 0x8e,
+ 0x17, 0xf0, 0x1d, 0x4f, 0xa9, 0x35, 0xe2, 0x5e, 0x13, 0xf8, 0x89, 0x61,
+ 0xac, 0xfc, 0x49, 0x8f, 0xc4, 0x3e, 0x30, 0x76, 0xcc, 0x68, 0x16, 0xd8,
+ 0x43, 0x19, 0x68, 0x61, 0x61, 0xd0, 0x91, 0x92, 0x40, 0x1c, 0x9e, 0x33,
+ 0xc9, 0xcd, 0x7d, 0x3b, 0x63, 0x7f, 0x6d, 0xaa, 0x5a, 0x45, 0x75, 0x69,
+ 0x3c, 0x77, 0x36, 0xd2, 0x8d, 0xc9, 0x2c, 0x4c, 0x19, 0x58, 0x7b, 0x11,
+ 0x5e, 0xde, 0x4d, 0x8b, 0xa3, 0x9d, 0xe3, 0x2a, 0x66, 0x1c, 0xe9, 0xf2,
+ 0x5e, 0x30, 0x8f, 0x58, 0xae, 0xb2, 0x6b, 0xbc, 0xbf, 0x05, 0xa1, 0x50,
+ 0x6a, 0x6f, 0x98, 0xb1, 0x45, 0x14, 0x57, 0xdc, 0x9b, 0x5c, 0x28, 0xa2,
+ 0x8a, 0x02, 0xe1, 0x45, 0x14, 0x50, 0x17, 0x0a, 0x28, 0xa2, 0x80, 0xb8,
+ 0x51, 0x45, 0x14, 0x05, 0xc2, 0x8a, 0x28, 0xa0, 0x2e, 0x14, 0x51, 0x45,
+ 0x01, 0x70, 0xa2, 0x8a, 0x28, 0x0b, 0x8d, 0xcd, 0x19, 0xa6, 0xe4, 0x51,
+ 0x91, 0x55, 0x62, 0x47, 0x66, 0x8c, 0xd3, 0x72, 0x28, 0xc8, 0xa2, 0xc0,
+ 0x3b, 0x34, 0x66, 0x9b, 0x91, 0x46, 0x45, 0x16, 0x01, 0xd9, 0xa3, 0x34,
+ 0xdc, 0x8a, 0x32, 0x28, 0xb0, 0x0e, 0xcd, 0x19, 0xa6, 0xe4, 0x52, 0xe4,
+ 0x51, 0x60, 0xb8, 0xb9, 0xa3, 0x34, 0xdc, 0x8a, 0x32, 0x28, 0xb0, 0x0e,
+ 0xdd, 0x46, 0x69, 0xb9, 0x14, 0x64, 0x51, 0x60, 0x1d, 0x9a, 0xa7, 0xac,
+ 0x6b, 0x16, 0x9a, 0x0e, 0x9b, 0x71, 0xa8, 0x5f, 0x4c, 0x20, 0xb5, 0x81,
+ 0x37, 0xbb, 0x9e, 0xc3, 0xd0, 0x7a, 0x93, 0xd0, 0x0a, 0xb5, 0x91, 0x5f,
+ 0x39, 0xfe, 0xd1, 0x1e, 0x37, 0x7d, 0x4b, 0x5a, 0x4f, 0x0f, 0x5b, 0x48,
+ 0x45, 0xa5, 0x96, 0x1e, 0x70, 0xa7, 0xef, 0xca, 0x46, 0x40, 0x3f, 0xee,
+ 0x83, 0xf9, 0x93, 0xe9, 0x5e, 0x06, 0x79, 0x9a, 0xc3, 0x27, 0xc1, 0x4b,
+ 0x12, 0xd5, 0xe5, 0xb4, 0x57, 0x76, 0xff, 0x00, 0xab, 0xbf, 0x24, 0x44,
+ 0xe5, 0xca, 0xae, 0x72, 0xbf, 0x12, 0xbe, 0x2a, 0xea, 0x3e, 0x3e, 0xbd,
+ 0x78, 0xd5, 0x9e, 0xd3, 0x48, 0x46, 0xfd, 0xd5, 0xa2, 0x9f, 0xbd, 0xe8,
+ 0xcf, 0xea, 0x7f, 0x41, 0xdb, 0xd4, 0xc3, 0xe0, 0x5f, 0x85, 0x1a, 0xd7,
+ 0x8f, 0xed, 0xe6, 0xb9, 0xb1, 0xf2, 0x2d, 0xed, 0x22, 0x6d, 0x86, 0x7b,
+ 0x96, 0x21, 0x59, 0xb1, 0x9c, 0x0c, 0x02, 0x4f, 0x51, 0xf9, 0xd7, 0x19,
+ 0x5e, 0xcd, 0xf0, 0x73, 0xe3, 0x16, 0x97, 0xe1, 0x0d, 0x06, 0x4d, 0x23,
+ 0x57, 0x49, 0x63, 0x44, 0x95, 0xa5, 0x86, 0x78, 0x53, 0x78, 0x21, 0xba,
+ 0xab, 0x0e, 0xb9, 0xcf, 0x7f, 0x7f, 0x6a, 0xfc, 0x1b, 0x2e, 0xa9, 0x87,
+ 0xcd, 0xb3, 0x2f, 0x69, 0x9c, 0xd5, 0x6a, 0x2e, 0xfa, 0xde, 0xda, 0xf4,
+ 0x57, 0xe8, 0xbf, 0xe1, 0x8e, 0x48, 0xda, 0x52, 0xf7, 0x8f, 0x30, 0xf1,
+ 0x57, 0x85, 0x75, 0x0f, 0x06, 0xeb, 0x12, 0x69, 0xba, 0x94, 0x42, 0x3b,
+ 0x84, 0x01, 0x83, 0x21, 0xca, 0xba, 0x9e, 0x8c, 0xa7, 0xb8, 0xac, 0x8a,
+ 0xed, 0x3e, 0x2c, 0xf8, 0xee, 0x1f, 0x1f, 0xf8, 0x9c, 0x5e, 0xda, 0xc2,
+ 0xf0, 0xda, 0x41, 0x08, 0x82, 0x2f, 0x33, 0x01, 0xd8, 0x02, 0x49, 0x63,
+ 0xe9, 0xc9, 0x3c, 0x57, 0x17, 0x5e, 0x26, 0x3e, 0x9e, 0x1e, 0x96, 0x2a,
+ 0xa4, 0x30, 0xb2, 0xe6, 0xa6, 0x9b, 0xb3, 0xee, 0x88, 0x76, 0xbe, 0x81,
+ 0x5a, 0x1a, 0x06, 0x83, 0x7b, 0xe2, 0x7d, 0x5e, 0xdf, 0x4d, 0xd3, 0xe2,
+ 0xf3, 0xae, 0xa7, 0x38, 0x55, 0xce, 0x00, 0x00, 0x64, 0x92, 0x7b, 0x00,
+ 0x39, 0xac, 0xfa, 0xea, 0x3e, 0x1b, 0x78, 0xc1, 0x7c, 0x0d, 0xe2, 0xcb,
+ 0x5d, 0x52, 0x58, 0x4c, 0xf6, 0xe1, 0x5a, 0x39, 0x51, 0x3e, 0xf6, 0xd6,
+ 0x18, 0x24, 0x7b, 0x8e, 0x0d, 0x67, 0x83, 0x85, 0x1a, 0x98, 0x8a, 0x70,
+ 0xc4, 0x4b, 0x96, 0x0d, 0xae, 0x67, 0xd9, 0x5f, 0x50, 0x56, 0xbe, 0xa6,
+ 0x97, 0x8d, 0x7e, 0x0e, 0xeb, 0xde, 0x06, 0xd3, 0x17, 0x50, 0xbb, 0x36,
+ 0xf7, 0x56, 0x99, 0x0b, 0x24, 0x96, 0xae, 0x4f, 0x96, 0x4f, 0x4d, 0xc0,
+ 0x81, 0xc1, 0x3c, 0x66, 0xa9, 0xfc, 0x3e, 0xf8, 0x93, 0xaa, 0x78, 0x03,
+ 0x50, 0x0f, 0x6c, 0xe6, 0x7b, 0x07, 0x6f, 0xdf, 0xd9, 0x3b, 0x7c, 0x8e,
+ 0x3d, 0x47, 0xa3, 0x7b, 0xfe, 0x79, 0xaf, 0x45, 0xf8, 0xad, 0xf1, 0xb3,
+ 0x47, 0xf1, 0x27, 0x85, 0x26, 0xd2, 0x34, 0x84, 0x9a, 0x67, 0xbb, 0x2b,
+ 0xe6, 0xcb, 0x34, 0x7b, 0x04, 0x6a, 0x18, 0x36, 0x07, 0xa9, 0xc8, 0x1e,
+ 0xd5, 0xe1, 0x95, 0xf4, 0x39, 0xab, 0xc2, 0x65, 0x79, 0x84, 0x67, 0x93,
+ 0x55, 0x6d, 0x24, 0x9d, 0xd3, 0xbd, 0x9f, 0x55, 0x7e, 0xaa, 0xd6, 0xbe,
+ 0xfb, 0xd8, 0xb9, 0x5a, 0x32, 0xf7, 0x59, 0xf6, 0xef, 0x86, 0xbc, 0x49,
+ 0x63, 0xe2, 0xbd, 0x1a, 0xdf, 0x53, 0xd3, 0xe5, 0xf3, 0x2d, 0xe6, 0x1d,
+ 0xfe, 0xf2, 0x1e, 0xea, 0xc3, 0xb1, 0x15, 0xa9, 0x9a, 0xf9, 0x7b, 0xe0,
+ 0x27, 0x8d, 0xe4, 0xf0, 0xef, 0x8a, 0x53, 0x4a, 0x9e, 0x43, 0xfd, 0x9f,
+ 0xa9, 0x30, 0x8f, 0x69, 0x3c, 0x24, 0xdf, 0xc0, 0xc3, 0xeb, 0xf7, 0x7f,
+ 0x11, 0xe9, 0x5f, 0x4f, 0xe4, 0x57, 0xee, 0x3c, 0x3f, 0x9b, 0xc7, 0x39,
+ 0xc1, 0x2a, 0xed, 0x5a, 0x6b, 0x49, 0x2f, 0x3f, 0xf2, 0x7b, 0xfe, 0x1d,
+ 0x0e, 0xb8, 0x4f, 0x99, 0x5c, 0x76, 0x4d, 0x19, 0xa6, 0xe4, 0x51, 0x91,
+ 0x5f, 0x4b, 0x62, 0xc7, 0x64, 0xd1, 0x9a, 0x6e, 0x45, 0x19, 0x14, 0x58,
+ 0x2e, 0x3b, 0x34, 0x66, 0x9b, 0x91, 0x46, 0x45, 0x16, 0x0b, 0x8e, 0xcd,
+ 0x19, 0xa6, 0xe4, 0x51, 0x91, 0x45, 0x80, 0x76, 0x68, 0xcd, 0x37, 0x34,
+ 0x64, 0x51, 0x60, 0xb8, 0xec, 0xd1, 0x9a, 0x6e, 0x45, 0x19, 0x14, 0x58,
+ 0x07, 0x64, 0xd1, 0x9a, 0x6e, 0x45, 0x19, 0x14, 0x58, 0x06, 0x6e, 0xa3,
+ 0x75, 0x37, 0x34, 0x66, 0xae, 0xc4, 0x5c, 0x76, 0xea, 0x37, 0x53, 0x73,
+ 0x46, 0x68, 0xb0, 0x5c, 0x76, 0xea, 0x37, 0x53, 0x73, 0x46, 0x68, 0xb0,
+ 0x5c, 0x76, 0xea, 0x37, 0x53, 0x72, 0x28, 0xcd, 0x16, 0x0b, 0x8e, 0xdd,
+ 0x46, 0xea, 0x6e, 0x68, 0xcd, 0x16, 0x0b, 0x8e, 0xdd, 0x46, 0xea, 0x6e,
+ 0x68, 0xcd, 0x16, 0x0b, 0x8e, 0xdd, 0x46, 0xea, 0xc4, 0xf1, 0x57, 0x8c,
+ 0x34, 0xaf, 0x06, 0x69, 0xff, 0x00, 0x6b, 0xd5, 0x2e, 0x44, 0x28, 0xc7,
+ 0x08, 0x8a, 0x37, 0x3c, 0x87, 0xd1, 0x47, 0x7f, 0xe5, 0x5c, 0x0d, 0x9f,
+ 0xed, 0x1f, 0xe1, 0xcb, 0x8b, 0xc1, 0x14, 0xd6, 0x97, 0xf6, 0xb0, 0x93,
+ 0x81, 0x3b, 0xa2, 0xb0, 0x1e, 0xe4, 0x06, 0x27, 0xf2, 0xcd, 0x78, 0xf8,
+ 0xac, 0xdf, 0x2f, 0xc0, 0xd4, 0x54, 0x71, 0x35, 0xa3, 0x19, 0x3e, 0x8d,
+ 0xfe, 0x7d, 0xbe, 0x64, 0xb9, 0x25, 0xb9, 0xeb, 0x05, 0xf6, 0x82, 0x4f,
+ 0x41, 0x5f, 0x10, 0xeb, 0x7a, 0x93, 0xeb, 0x3a, 0xcd, 0xf5, 0xfc, 0x84,
+ 0x97, 0xb9, 0x9d, 0xe6, 0x39, 0xff, 0x00, 0x69, 0x89, 0xfe, 0xb5, 0xf6,
+ 0xad, 0x8e, 0xa1, 0x6b, 0xab, 0x58, 0xc5, 0x75, 0x69, 0x34, 0x77, 0x36,
+ 0xb3, 0x2e, 0xe4, 0x91, 0x0e, 0x55, 0x85, 0x78, 0x5f, 0xfc, 0x2d, 0x5f,
+ 0x87, 0x3f, 0xf4, 0x25, 0x27, 0xfe, 0x00, 0xdb, 0xff, 0x00, 0x8d, 0x7c,
+ 0x67, 0x18, 0xe1, 0xa8, 0x63, 0x61, 0x87, 0x55, 0x31, 0x31, 0xa7, 0x1f,
+ 0x79, 0xab, 0xdd, 0xf3, 0x7c, 0x3a, 0xab, 0x76, 0xfd, 0x4c, 0xea, 0x59,
+ 0xdb, 0x53, 0xc4, 0x68, 0xaf, 0x6e, 0xff, 0x00, 0x85, 0xab, 0xf0, 0xe7,
+ 0xfe, 0x84, 0xa4, 0xff, 0x00, 0xc0, 0x1b, 0x7f, 0xf1, 0xa3, 0xfe, 0x16,
+ 0xaf, 0xc3, 0x9f, 0xfa, 0x12, 0x93, 0xff, 0x00, 0x00, 0x6d, 0xff, 0x00,
+ 0xc6, 0xbf, 0x33, 0xfe, 0xc5, 0xc0, 0xff, 0x00, 0xd0, 0x7c, 0x3e, 0xe9,
+ 0x7f, 0x91, 0x8f, 0x2a, 0xee, 0x78, 0x8d, 0x15, 0xed, 0xdf, 0xf0, 0xb5,
+ 0x7e, 0x1c, 0xff, 0x00, 0xd0, 0x94, 0x9f, 0xf8, 0x03, 0x6f, 0xfe, 0x34,
+ 0x7f, 0xc2, 0xd5, 0xf8, 0x73, 0xff, 0x00, 0x42, 0x52, 0x7f, 0xe0, 0x0d,
+ 0xbf, 0xf8, 0xd1, 0xfd, 0x8b, 0x81, 0xff, 0x00, 0xa0, 0xf8, 0x7d, 0xd2,
+ 0xff, 0x00, 0x20, 0xe5, 0x5d, 0xcf, 0x11, 0xa2, 0xbd, 0xbb, 0xfe, 0x16,
+ 0xaf, 0xc3, 0x9f, 0xfa, 0x12, 0x93, 0xff, 0x00, 0x00, 0x6d, 0xff, 0x00,
+ 0xc6, 0x8f, 0xf8, 0x5a, 0xbf, 0x0e, 0x7f, 0xe8, 0x4a, 0x4f, 0xfc, 0x01,
+ 0xb7, 0xff, 0x00, 0x1a, 0x3f, 0xb1, 0x70, 0x3f, 0xf4, 0x1f, 0x0f, 0xba,
+ 0x5f, 0xe4, 0x1c, 0xab, 0xb9, 0xe2, 0x34, 0x57, 0xb7, 0x7f, 0xc2, 0xd5,
+ 0xf8, 0x73, 0xff, 0x00, 0x42, 0x52, 0x7f, 0xe0, 0x0d, 0xbf, 0xf8, 0xd1,
+ 0xff, 0x00, 0x0b, 0x57, 0xe1, 0xcf, 0xfd, 0x09, 0x49, 0xff, 0x00, 0x80,
+ 0x36, 0xff, 0x00, 0xe3, 0x47, 0xf6, 0x2e, 0x07, 0xfe, 0x83, 0xe1, 0xf7,
+ 0x4b, 0xfc, 0x83, 0x95, 0x77, 0x3c, 0x52, 0x09, 0xde, 0xda, 0x78, 0xe6,
+ 0x89, 0x8a, 0x49, 0x1b, 0x07, 0x56, 0x1d, 0x41, 0x07, 0x20, 0xd7, 0xdb,
+ 0xfa, 0x5d, 0xf0, 0xd4, 0x74, 0xdb, 0x4b, 0xb0, 0x30, 0x27, 0x85, 0x25,
+ 0x03, 0xfd, 0xe5, 0x07, 0xfa, 0xd7, 0x85, 0xff, 0x00, 0xc2, 0xd5, 0xf8,
+ 0x73, 0xff, 0x00, 0x42, 0x52, 0x7f, 0xe0, 0x0d, 0xbf, 0xf8, 0xd7, 0xb6,
+ 0x69, 0x1a, 0x95, 0xa5, 0xc7, 0x87, 0xec, 0xaf, 0xe1, 0x55, 0xb3, 0xb1,
+ 0x7b, 0x54, 0x99, 0x11, 0xf0, 0x82, 0x28, 0xca, 0x02, 0x01, 0xec, 0x30,
+ 0x3f, 0x0e, 0x2b, 0xf4, 0x7e, 0x0e, 0xc2, 0xd0, 0xc1, 0xce, 0xbc, 0x69,
+ 0x62, 0x63, 0x51, 0x34, 0x9b, 0x4a, 0xfa, 0x5a, 0xfa, 0xeb, 0xea, 0x6d,
+ 0x4e, 0xca, 0xfa, 0x9a, 0x5b, 0xa8, 0xdd, 0x5e, 0x57, 0xab, 0xfe, 0xd1,
+ 0x3e, 0x1b, 0xd3, 0xaf, 0x1a, 0x0b, 0x68, 0x6e, 0xf5, 0x15, 0x53, 0x83,
+ 0x34, 0x28, 0xaa, 0x87, 0xe9, 0xb8, 0x82, 0x7f, 0x2a, 0xeb, 0xbc, 0x1b,
+ 0xf1, 0x07, 0x45, 0xf1, 0xcd, 0xbb, 0xbe, 0x99, 0x70, 0x7c, 0xe8, 0xc6,
+ 0x64, 0xb6, 0x98, 0x6d, 0x91, 0x07, 0xa9, 0x1d, 0xc7, 0xb8, 0xc8, 0xaf,
+ 0xb7, 0xc3, 0xe7, 0x19, 0x76, 0x2a, 0xb7, 0xd5, 0xe8, 0x56, 0x8c, 0xa7,
+ 0xd9, 0x3f, 0xcb, 0xbf, 0xc8, 0xd1, 0x49, 0x3d, 0x2e, 0x74, 0xdb, 0xa8,
+ 0xcd, 0x37, 0x34, 0x64, 0x57, 0xb2, 0x55, 0xc7, 0x6e, 0xa3, 0x75, 0x37,
+ 0x34, 0x66, 0x8b, 0x05, 0xc7, 0x6e, 0xa3, 0x75, 0x37, 0x34, 0x66, 0x8b,
+ 0x05, 0xc7, 0x6e, 0xa3, 0x75, 0x37, 0x34, 0x66, 0x8b, 0x05, 0xc7, 0x6e,
+ 0xa3, 0x75, 0x37, 0x34, 0x64, 0x51, 0x60, 0xb8, 0xed, 0xd4, 0x6e, 0xa6,
+ 0xe4, 0x51, 0x9a, 0x2c, 0x17, 0x1b, 0x9a, 0x33, 0x51, 0xee, 0xa3, 0x75,
+ 0x55, 0x88, 0xb9, 0x26, 0x68, 0xcd, 0x47, 0xba, 0x8d, 0xd4, 0x58, 0x2e,
+ 0x49, 0x9a, 0x33, 0x51, 0xee, 0xa3, 0x75, 0x16, 0x15, 0xc9, 0x32, 0x28,
+ 0xa8, 0xf7, 0x51, 0xba, 0x8b, 0x0e, 0xe4, 0x99, 0xa3, 0x35, 0x1e, 0xea,
+ 0x37, 0x51, 0x60, 0xb9, 0x26, 0x68, 0xcd, 0x47, 0xba, 0x8c, 0xd3, 0xb0,
+ 0x5c, 0xf9, 0x7b, 0xe3, 0xb6, 0xaf, 0x3e, 0xa5, 0xf1, 0x0e, 0xf2, 0xde,
+ 0x47, 0x26, 0x1b, 0x24, 0x48, 0x62, 0x4e, 0xc0, 0x15, 0x0c, 0x4f, 0xe2,
+ 0x58, 0xfe, 0x95, 0xe7, 0x95, 0xda, 0x7c, 0x64, 0xff, 0x00, 0x92, 0x97,
+ 0xad, 0xff, 0x00, 0xbf, 0x1f, 0xfe, 0x8a, 0x4a, 0xe2, 0xeb, 0xf9, 0x47,
+ 0x3a, 0x9c, 0xaa, 0x66, 0x78, 0x99, 0x49, 0xdd, 0xf3, 0xcb, 0xf0, 0x6d,
+ 0x23, 0x92, 0x5b, 0x9e, 0xf7, 0xfb, 0x34, 0xeb, 0x13, 0xcd, 0x67, 0xac,
+ 0xe9, 0xb2, 0x39, 0x6b, 0x78, 0x1a, 0x39, 0xa2, 0x04, 0xfd, 0xd2, 0xdb,
+ 0x83, 0x0f, 0xc7, 0x68, 0xfd, 0x6b, 0xc1, 0x2b, 0xda, 0xff, 0x00, 0x66,
+ 0x73, 0x8b, 0xed, 0x7f, 0xfe, 0xb9, 0xc3, 0xfc, 0xde, 0xbc, 0x52, 0xbd,
+ 0x8c, 0xd2, 0x72, 0x9e, 0x4b, 0x97, 0x39, 0x3b, 0xdb, 0xda, 0xaf, 0x92,
+ 0x92, 0xb1, 0x4f, 0xe1, 0x41, 0x45, 0x14, 0x57, 0xc6, 0x90, 0x14, 0x51,
+ 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x14, 0x51, 0x45, 0x00, 0x15, 0xef,
+ 0x7f, 0x13, 0xf5, 0x89, 0xf4, 0xef, 0x82, 0xbe, 0x19, 0xb6, 0x81, 0xca,
+ 0x0b, 0xc8, 0x2d, 0x62, 0x94, 0x83, 0xd5, 0x04, 0x3b, 0x88, 0xfc, 0x48,
+ 0x15, 0xe0, 0x95, 0xed, 0x7f, 0x17, 0x0f, 0xfc, 0x5a, 0x5f, 0x05, 0xff,
+ 0x00, 0xd7, 0x38, 0x3f, 0xf4, 0x45, 0x7d, 0x96, 0x47, 0x39, 0x43, 0x03,
+ 0x98, 0x4a, 0x2e, 0xcf, 0x91, 0x7e, 0x32, 0xb3, 0xfc, 0x0a, 0x8e, 0xcc,
+ 0xf1, 0x4a, 0xe9, 0xbe, 0x1a, 0x6a, 0xf3, 0xe8, 0xbe, 0x3a, 0xd1, 0x67,
+ 0x81, 0xca, 0x99, 0x2e, 0x52, 0x07, 0x00, 0xfd, 0xe4, 0x76, 0x0a, 0xc0,
+ 0xfe, 0x07, 0xf4, 0xae, 0x66, 0xb6, 0x3c, 0x1b, 0xff, 0x00, 0x23, 0x7e,
+ 0x87, 0xff, 0x00, 0x5f, 0xd0, 0x7f, 0xe8, 0xc5, 0xaf, 0x9b, 0xc0, 0xce,
+ 0x54, 0xf1, 0x54, 0xa7, 0x07, 0x66, 0xa4, 0xbf, 0x31, 0x2d, 0xcf, 0xb4,
+ 0x33, 0x46, 0x6a, 0x3d, 0xd4, 0x6e, 0xaf, 0xeb, 0x9b, 0x1d, 0x57, 0x24,
+ 0xcd, 0x19, 0xa8, 0xf7, 0x51, 0xba, 0x8b, 0x0e, 0xe4, 0x99, 0xa3, 0x35,
+ 0x1e, 0xea, 0x37, 0x51, 0x60, 0xb9, 0x26, 0x68, 0xcd, 0x47, 0xba, 0x8d,
+ 0xd4, 0x58, 0x2e, 0x49, 0x9a, 0x33, 0x51, 0xee, 0xa3, 0x75, 0x16, 0x15,
+ 0xc9, 0x33, 0x46, 0x6a, 0x3d, 0xd4, 0x6e, 0xa2, 0xc3, 0xb8, 0xdd, 0xd4,
+ 0x9b, 0xa9, 0xbb, 0xa8, 0xdd, 0x5a, 0x19, 0xdc, 0x7e, 0xea, 0x4d, 0xd4,
+ 0xdd, 0xd4, 0x6e, 0xa0, 0x57, 0x1f, 0xba, 0x8d, 0xd4, 0xcd, 0xd4, 0x6e,
+ 0xa0, 0x77, 0x1f, 0xba, 0x8d, 0xd4, 0xcd, 0xd4, 0x6e, 0xa4, 0x2b, 0x8f,
+ 0xdd, 0x49, 0xba, 0x9b, 0xba, 0x8d, 0xd4, 0xc2, 0xe3, 0xb7, 0x52, 0xee,
+ 0xa6, 0x6e, 0xa3, 0x75, 0x20, 0xb9, 0xf2, 0x9f, 0xc6, 0x3f, 0xf9, 0x29,
+ 0x5a, 0xdf, 0xfb, 0xf1, 0xff, 0x00, 0xe8, 0xb4, 0xae, 0x32, 0xbb, 0x2f,
+ 0x8c, 0x5c, 0xfc, 0x49, 0xd6, 0xff, 0x00, 0xdf, 0x8f, 0xff, 0x00, 0x45,
+ 0xa5, 0x71, 0xb5, 0xfc, 0x99, 0x9c, 0x7f, 0xc8, 0xcb, 0x13, 0xfe, 0x39,
+ 0xff, 0x00, 0xe9, 0x4c, 0xc1, 0xee, 0x7b, 0x57, 0xec, 0xd2, 0x71, 0x7d,
+ 0xaf, 0x7f, 0xd7, 0x38, 0x7f, 0x9b, 0xd7, 0x8a, 0xd7, 0xb4, 0x7e, 0xcd,
+ 0x67, 0x17, 0xda, 0xf7, 0xfd, 0x73, 0x87, 0xf9, 0xbd, 0x78, 0xbd, 0x7b,
+ 0x19, 0x97, 0xfc, 0x89, 0x32, 0xef, 0xfb, 0x8b, 0xff, 0x00, 0xa5, 0x21,
+ 0xbd, 0x90, 0x51, 0x45, 0x15, 0xf2, 0x02, 0x0a, 0x28, 0xa2, 0x80, 0x0a,
+ 0x28, 0xa2, 0x80, 0x0a, 0x28, 0xa2, 0x80, 0x0a, 0xf6, 0xaf, 0x8b, 0x47,
+ 0x3f, 0x09, 0x7c, 0x17, 0xff, 0x00, 0x5c, 0xe0, 0xff, 0x00, 0xd1, 0x15,
+ 0xe2, 0xb5, 0xed, 0x1f, 0x16, 0x4f, 0xfc, 0x5a, 0x6f, 0x06, 0x7f, 0xd7,
+ 0x38, 0x3f, 0xf4, 0x45, 0x7d, 0x7e, 0x4d, 0xff, 0x00, 0x22, 0xfc, 0xc3,
+ 0xfc, 0x11, 0xff, 0x00, 0xd2, 0x90, 0xd6, 0xcc, 0xf1, 0x7a, 0xd8, 0xf0,
+ 0x67, 0xfc, 0x8e, 0x1a, 0x17, 0xfd, 0x7f, 0xc1, 0xff, 0x00, 0xa3, 0x16,
+ 0xb1, 0xeb, 0x63, 0xc1, 0xdf, 0xf2, 0x37, 0x68, 0x7f, 0xf5, 0xfd, 0x07,
+ 0xfe, 0x8c, 0x5a, 0xf9, 0xbc, 0x27, 0xfb, 0xcd, 0x3f, 0xf1, 0x2f, 0xcc,
+ 0x48, 0xfb, 0x2b, 0x75, 0x1b, 0xa9, 0x9b, 0xa8, 0xdd, 0x5f, 0xd8, 0x16,
+ 0x37, 0xb8, 0xfd, 0xd4, 0x6e, 0xa6, 0x6e, 0xa3, 0x75, 0x20, 0xb8, 0xed,
+ 0xd4, 0xbb, 0xa9, 0x9b, 0xa8, 0xdd, 0x4c, 0x2e, 0x3f, 0x75, 0x26, 0xea,
+ 0x6e, 0xea, 0x37, 0x52, 0x0b, 0x8f, 0xdd, 0x49, 0xba, 0x9b, 0xba, 0x8d,
+ 0xd4, 0xec, 0x3b, 0x8f, 0xdd, 0x49, 0xba, 0x9b, 0xba, 0x8d, 0xd4, 0x0a,
+ 0xe4, 0x74, 0x53, 0x33, 0x4b, 0x93, 0x57, 0x63, 0x3b, 0x8e, 0xa2, 0x9b,
+ 0x9a, 0x4c, 0xd1, 0x60, 0xb8, 0xfa, 0x29, 0x99, 0xa3, 0x34, 0x58, 0x2e,
+ 0x3f, 0x34, 0x53, 0x33, 0x4b, 0x93, 0x45, 0x82, 0xe3, 0xa8, 0xcd, 0x33,
+ 0x34, 0x66, 0x8b, 0x05, 0xc7, 0xd1, 0x4d, 0xc9, 0xa3, 0x26, 0x8b, 0x05,
+ 0xcf, 0x96, 0x3e, 0x30, 0x7f, 0xc9, 0x48, 0xd6, 0xbf, 0xdf, 0x8f, 0xff,
+ 0x00, 0x45, 0xa5, 0x71, 0xb5, 0xdd, 0xfc, 0x6c, 0xd3, 0xa6, 0xb1, 0xf8,
+ 0x85, 0x7f, 0x2c, 0x8a, 0x44, 0x77, 0x4b, 0x1c, 0xd1, 0xb7, 0x66, 0x1b,
+ 0x02, 0x9f, 0xd5, 0x4d, 0x70, 0x95, 0xfc, 0x97, 0x9d, 0x42, 0x50, 0xcc,
+ 0xf1, 0x31, 0x92, 0xb7, 0xbf, 0x2f, 0xfd, 0x29, 0x90, 0x7b, 0x3f, 0xec,
+ 0xdb, 0xff, 0x00, 0x1f, 0xba, 0xef, 0xfd, 0x73, 0x87, 0xf9, 0xbd, 0x78,
+ 0xc5, 0x7b, 0x87, 0xec, 0xe3, 0xa7, 0x4d, 0x1c, 0x3a, 0xd5, 0xf3, 0x29,
+ 0x58, 0x24, 0x31, 0xc2, 0x8d, 0xfd, 0xe2, 0x37, 0x16, 0xfc, 0xb2, 0x3f,
+ 0x3a, 0xf0, 0xfa, 0xf6, 0x73, 0x58, 0x4a, 0x19, 0x26, 0x5b, 0xcc, 0xad,
+ 0x7f, 0x6a, 0xff, 0x00, 0xf2, 0x64, 0x01, 0x45, 0x14, 0x57, 0xc6, 0x00,
+ 0x51, 0x45, 0x14, 0x00, 0x51, 0x45, 0x14, 0x00, 0x51, 0x45, 0x14, 0x00,
+ 0x57, 0xb3, 0xfc, 0x57, 0xff, 0x00, 0x92, 0x51, 0xe0, 0xdf, 0xfa, 0xe7,
+ 0x07, 0xfe, 0x88, 0xaf, 0x18, 0xaf, 0x70, 0xf8, 0x9b, 0xa7, 0x4d, 0x79,
+ 0xf0, 0x77, 0xc3, 0x37, 0x11, 0x29, 0x74, 0xb5, 0x8a, 0xd9, 0xe4, 0xc7,
+ 0x65, 0x30, 0xed, 0xcf, 0xe6, 0x40, 0xfc, 0x6b, 0xec, 0xf2, 0x38, 0x4a,
+ 0x78, 0x0c, 0xc1, 0x45, 0x5f, 0xdc, 0x5f, 0x84, 0xae, 0xc0, 0xf0, 0xfa,
+ 0xd8, 0xf0, 0x6f, 0xfc, 0x8d, 0xfa, 0x1f, 0xfd, 0x7f, 0x41, 0xff, 0x00,
+ 0xa3, 0x16, 0xb1, 0xeb, 0xa2, 0xf8, 0x79, 0xa7, 0x4d, 0xaa, 0x78, 0xdf,
+ 0x45, 0x86, 0x15, 0x2c, 0xcb, 0x75, 0x1c, 0xad, 0x8e, 0xca, 0x8c, 0x18,
+ 0x9f, 0xc8, 0x57, 0xcd, 0x60, 0x61, 0x29, 0xe2, 0xe9, 0x46, 0x2a, 0xed,
+ 0xca, 0x3f, 0x9a, 0x03, 0xeb, 0x9c, 0xd1, 0x4c, 0xcd, 0x2e, 0x4d, 0x7f,
+ 0x60, 0x58, 0xbb, 0x8e, 0xa2, 0x99, 0x9a, 0x33, 0x45, 0x82, 0xe3, 0xe8,
+ 0xa6, 0x66, 0x8c, 0xd1, 0x60, 0xb8, 0xfa, 0x29, 0x99, 0xa5, 0xc9, 0xa2,
+ 0xc1, 0x71, 0xd9, 0xa2, 0x9b, 0x93, 0x49, 0x9a, 0x2c, 0x17, 0x1f, 0x45,
+ 0x33, 0x34, 0x66, 0x8b, 0x05, 0xc6, 0x6e, 0xa3, 0x75, 0x30, 0x90, 0x3a,
+ 0x9c, 0x51, 0x9a, 0xd2, 0xc6, 0x57, 0x1f, 0xba, 0x8d, 0xd4, 0xda, 0x4c,
+ 0xd1, 0x60, 0xb8, 0xfd, 0xd4, 0x6e, 0xa6, 0x02, 0x0f, 0x43, 0x9a, 0x37,
+ 0x01, 0xdf, 0x14, 0x58, 0x2e, 0x3f, 0x75, 0x1b, 0xa9, 0xb4, 0x94, 0x58,
+ 0x2e, 0x3f, 0x75, 0x1b, 0xa9, 0xb4, 0x80, 0x83, 0xd0, 0xe6, 0x8b, 0x05,
+ 0xc7, 0xee, 0xa3, 0x75, 0x30, 0x90, 0x3a, 0x9c, 0x51, 0x9a, 0x2c, 0x17,
+ 0x31, 0x3c, 0x5d, 0xe0, 0xcd, 0x2f, 0xc6, 0xb6, 0x2b, 0x6f, 0xa8, 0xc4,
+ 0x4b, 0x26, 0x4c, 0x53, 0xc6, 0x71, 0x24, 0x64, 0xf5, 0xc1, 0xfe, 0x87,
+ 0x8a, 0xe0, 0x6d, 0x3f, 0x67, 0x7d, 0x32, 0x2b, 0xb0, 0xf7, 0x1a, 0xad,
+ 0xcc, 0xf6, 0xe0, 0xe7, 0xca, 0x58, 0xd5, 0x09, 0x1e, 0x85, 0xb2, 0x7f,
+ 0x95, 0x7a, 0xd5, 0x25, 0x78, 0x38, 0xcc, 0x87, 0x2c, 0xcc, 0x2b, 0x2a,
+ 0xf8, 0x9a, 0x2a, 0x52, 0xef, 0xaa, 0xfb, 0xec, 0xd5, 0xfe, 0x77, 0x0b,
+ 0x95, 0xf4, 0xad, 0x32, 0xd3, 0x44, 0xb0, 0x86, 0xca, 0xc6, 0x05, 0xb7,
+ 0xb6, 0x88, 0x61, 0x23, 0x4e, 0x83, 0xfc, 0x4f, 0xbd, 0x7c, 0x6b, 0x5f,
+ 0x69, 0x57, 0xc5, 0xb5, 0xf9, 0x8f, 0x88, 0xb0, 0x8d, 0x38, 0xe0, 0xe1,
+ 0x05, 0x64, 0xb9, 0xec, 0x97, 0xfd, 0xb8, 0x34, 0x14, 0x51, 0x45, 0x7e,
+ 0x32, 0x30, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a, 0x28, 0x00, 0xa2, 0x8a,
+ 0x28, 0x00, 0xaf, 0xad, 0xfc, 0x2b, 0x04, 0x57, 0x9e, 0x06, 0xd1, 0xad,
+ 0xe7, 0x8d, 0x66, 0x86, 0x4d, 0x3a, 0x04, 0x78, 0xdc, 0x65, 0x58, 0x18,
+ 0xd7, 0x20, 0x8a, 0xf9, 0x22, 0xbe, 0xba, 0xf0, 0x67, 0xfc, 0x89, 0xfa,
+ 0x17, 0xfd, 0x78, 0x41, 0xff, 0x00, 0xa2, 0xd6, 0xbf, 0x5c, 0xf0, 0xee,
+ 0x2a, 0x58, 0x9c, 0x42, 0x7b, 0x72, 0xaf, 0xcc, 0x47, 0x05, 0xab, 0x7e,
+ 0xcf, 0x7a, 0x4d, 0xdd, 0xdb, 0x4b, 0x65, 0xa8, 0x4f, 0x63, 0x13, 0x1c,
+ 0xf9, 0x25, 0x04, 0x80, 0x7b, 0x02, 0x48, 0x3f, 0x9e, 0x6b, 0xaf, 0xf0,
+ 0x57, 0xc3, 0xcd, 0x27, 0xc0, 0xd1, 0xb9, 0xb3, 0x47, 0x9a, 0xee, 0x41,
+ 0xb6, 0x4b, 0xa9, 0xb0, 0x5c, 0x8f, 0x41, 0xe8, 0x3d, 0x87, 0xe3, 0x5d,
+ 0x36, 0x69, 0x6b, 0xf5, 0x7c, 0x37, 0x0f, 0xe5, 0x78, 0x3a, 0xff, 0x00,
+ 0x59, 0xa1, 0x41, 0x46, 0x7d, 0xf5, 0xd3, 0xd1, 0x6c, 0xbe, 0x49, 0x0a,
+ 0xe3, 0xb7, 0x51, 0xba, 0x99, 0x9a, 0x03, 0x03, 0xde, 0xbd, 0xfb, 0x05,
+ 0xc7, 0xee, 0xa3, 0x75, 0x30, 0x90, 0x06, 0x4f, 0x14, 0x51, 0x60, 0xb8,
+ 0xfd, 0xd4, 0x6e, 0xa6, 0xd1, 0x45, 0x82, 0xe3, 0xb7, 0x51, 0xba, 0x98,
+ 0x08, 0x3d, 0x0e, 0x68, 0x24, 0x0e, 0xf4, 0x58, 0x2e, 0x3f, 0x75, 0x1b,
+ 0xa9, 0x94, 0xb4, 0x58, 0x2e, 0x3b, 0x75, 0x1b, 0xa9, 0x99, 0xa0, 0x10,
+ 0x7a, 0x1a, 0x2c, 0x17, 0x31, 0x62, 0xbd, 0x91, 0x46, 0xf7, 0x90, 0x3e,
+ 0xd3, 0xf7, 0x1b, 0xa9, 0xad, 0x58, 0xa5, 0x13, 0x46, 0xae, 0xbd, 0x08,
+ 0xac, 0x3f, 0x38, 0xff, 0x00, 0x71, 0x3f, 0xef, 0x91, 0x56, 0x52, 0xf1,
+ 0xe3, 0x48, 0x55, 0x42, 0x80, 0x7a, 0x80, 0x3d, 0xeb, 0xb2, 0x70, 0xbe,
+ 0xc7, 0x9d, 0x4e, 0xaf, 0x2e, 0xec, 0xd6, 0xcd, 0x36, 0x59, 0x44, 0x31,
+ 0xb3, 0xb7, 0x41, 0x49, 0xba, 0xb3, 0x1e, 0xf2, 0x49, 0x12, 0x65, 0x60,
+ 0x08, 0x1d, 0x01, 0x1e, 0xf5, 0x84, 0x61, 0xcc, 0x75, 0x4e, 0xa7, 0x22,
+ 0x1b, 0x2d, 0xec, 0x8c, 0x0b, 0xa4, 0x81, 0x37, 0x1f, 0xb8, 0xbd, 0x7e,
+ 0xb4, 0xb1, 0x5e, 0xc8, 0xa0, 0x3b, 0xb8, 0x7d, 0xa7, 0xee, 0x37, 0x5f,
+ 0xad, 0x57, 0xf3, 0x8f, 0xf7, 0x13, 0xfe, 0xf9, 0x14, 0x79, 0xc7, 0xfb,
+ 0x89, 0xff, 0x00, 0x7c, 0x8a, 0xeb, 0xe5, 0x56, 0xb5, 0x8e, 0x0e, 0x77,
+ 0x7b, 0xdc, 0xdd, 0x8e, 0x41, 0x2a, 0x2b, 0xaf, 0x42, 0x33, 0x4e, 0xac,
+ 0xa8, 0xef, 0x1d, 0x3c, 0x85, 0x00, 0x05, 0x3d, 0x40, 0x1e, 0xe6, 0xb4,
+ 0x77, 0x57, 0x24, 0xa3, 0xca, 0x77, 0xc2, 0x7c, 0xe8, 0x74, 0x92, 0x08,
+ 0xd1, 0x99, 0x8f, 0x00, 0x66, 0xb2, 0xa5, 0xbd, 0x91, 0x81, 0x74, 0x70,
+ 0x99, 0x38, 0xd8, 0x3a, 0xfd, 0x69, 0xd2, 0x5e, 0x3b, 0xf9, 0xea, 0x40,
+ 0x2a, 0x3a, 0x02, 0x3d, 0xc5, 0x55, 0xf3, 0x8f, 0xf7, 0x13, 0xfe, 0xf9,
+ 0x15, 0xbc, 0x21, 0x6d, 0xce, 0x6a, 0x95, 0x6f, 0xa2, 0x64, 0xf1, 0x5e,
+ 0x48, 0xa3, 0x7b, 0x48, 0x1f, 0x69, 0xfb, 0x8d, 0xd4, 0xd6, 0xac, 0x52,
+ 0x89, 0xa3, 0x57, 0x5e, 0x86, 0xb0, 0xfc, 0xe3, 0xfd, 0xc4, 0xff, 0x00,
+ 0xbe, 0x45, 0x59, 0x4b, 0xc7, 0x8d, 0x61, 0x0a, 0x14, 0x03, 0xd4, 0x01,
+ 0xef, 0x44, 0xe1, 0x7d, 0x85, 0x4e, 0xaf, 0x2e, 0xec, 0xd6, 0xcd, 0x15,
+ 0x1e, 0xea, 0x5d, 0xd5, 0xcd, 0x63, 0xba, 0xe3, 0xeb, 0xc0, 0xbc, 0x71,
+ 0xf0, 0x57, 0x55, 0x83, 0x57, 0x9e, 0xe7, 0x44, 0x85, 0x6f, 0x6c, 0xa6,
+ 0x72, 0xe2, 0x25, 0x70, 0xaf, 0x16, 0x4e, 0x76, 0xe0, 0x91, 0x91, 0xe9,
+ 0x8a, 0xf7, 0xad, 0xd4, 0x66, 0xbe, 0x7f, 0x39, 0xc8, 0xf0, 0x99, 0xe5,
+ 0x18, 0xd2, 0xc4, 0xdd, 0x72, 0xbb, 0xa6, 0xb7, 0x5d, 0xfb, 0xef, 0xe8,
+ 0x17, 0xb1, 0xf2, 0xc5, 0xff, 0x00, 0xc3, 0x5f, 0x12, 0xe9, 0x96, 0x53,
+ 0x5d, 0xdd, 0x69, 0x52, 0x43, 0x6f, 0x0a, 0x97, 0x92, 0x42, 0xe8, 0x42,
+ 0x81, 0xd4, 0xf0, 0x6b, 0x99, 0xaf, 0xaa, 0xfe, 0x21, 0x9c, 0xf8, 0x1f,
+ 0x5c, 0xff, 0x00, 0xaf, 0x47, 0xfe, 0x55, 0xf2, 0xa5, 0x7e, 0x01, 0xc5,
+ 0x59, 0x1e, 0x1f, 0x22, 0xc4, 0x53, 0xa3, 0x87, 0x93, 0x92, 0x94, 0x6f,
+ 0xef, 0x5b, 0xbd, 0xba, 0x24, 0x5a, 0x77, 0x0a, 0xe9, 0xec, 0xbe, 0x19,
+ 0xf8, 0x9b, 0x51, 0xb3, 0x86, 0xea, 0xdb, 0x49, 0x92, 0x5b, 0x79, 0x90,
+ 0x49, 0x1b, 0x87, 0x40, 0x19, 0x48, 0xc8, 0x3d, 0x6b, 0x98, 0xaf, 0xac,
+ 0x3c, 0x08, 0x71, 0xe0, 0xad, 0x0b, 0xfe, 0xbc, 0xa1, 0xff, 0x00, 0xd0,
+ 0x05, 0x57, 0x0a, 0xe4, 0x58, 0x7c, 0xf6, 0xbd, 0x5a, 0x58, 0x89, 0x4a,
+ 0x2a, 0x2a, 0xfe, 0xed, 0xbb, 0xdb, 0xaa, 0x60, 0xdd, 0x8f, 0x9e, 0xdb,
+ 0xe1, 0x4f, 0x8a, 0xd1, 0x4b, 0x1d, 0x1a, 0x50, 0x00, 0xc9, 0x3e, 0x62,
+ 0x7f, 0xf1, 0x55, 0xc9, 0xd7, 0xd9, 0x17, 0x4d, 0xfe, 0x8d, 0x37, 0xfb,
+ 0x87, 0xf9, 0x57, 0xc6, 0xf5, 0xd1, 0xc5, 0x9c, 0x3d, 0x86, 0xc8, 0x5d,
+ 0x05, 0x87, 0x9c, 0xa5, 0xcf, 0xcd, 0x7e, 0x6b, 0x74, 0xb6, 0xd6, 0x4b,
+ 0xb8, 0x27, 0x70, 0xae, 0x87, 0x47, 0xf0, 0x07, 0x88, 0x35, 0xfb, 0x04,
+ 0xbd, 0xb0, 0xd3, 0x64, 0xb9, 0xb5, 0x72, 0x42, 0xc8, 0xae, 0xa0, 0x12,
+ 0x0e, 0x0f, 0x53, 0xeb, 0x5c, 0xf5, 0x7d, 0x27, 0xf0, 0x54, 0xe3, 0xe1,
+ 0xed, 0x8f, 0xfd, 0x74, 0x97, 0xff, 0x00, 0x43, 0x35, 0xe7, 0x70, 0xbe,
+ 0x4f, 0x43, 0x3c, 0xc6, 0xcb, 0x0d, 0x5e, 0x4d, 0x25, 0x16, 0xf4, 0xb5,
+ 0xee, 0x9a, 0x5d, 0x53, 0xee, 0x0d, 0xd8, 0xf3, 0x1f, 0x0d, 0x7c, 0x12,
+ 0xd7, 0xb5, 0x3d, 0x42, 0x31, 0xa9, 0x40, 0x34, 0xdb, 0x20, 0xc0, 0xc8,
+ 0xee, 0xea, 0xce, 0x47, 0x70, 0xa0, 0x13, 0xcf, 0xb9, 0xe2, 0xbe, 0x87,
+ 0xb7, 0x82, 0x3b, 0x4b, 0x78, 0xa0, 0x89, 0x42, 0x45, 0x12, 0x84, 0x45,
+ 0x1d, 0x80, 0x18, 0x02, 0x97, 0x34, 0x9b, 0xab, 0xfa, 0x07, 0x25, 0xe1,
+ 0xfc, 0x1e, 0x45, 0x09, 0x47, 0x0d, 0x76, 0xe5, 0xbb, 0x7a, 0xbd, 0x36,
+ 0x5a, 0x24, 0xad, 0xf2, 0x22, 0xf7, 0x24, 0xcd, 0x19, 0xa8, 0xf7, 0x51,
+ 0xba, 0xbe, 0x96, 0xc1, 0x71, 0xd2, 0x48, 0x22, 0x46, 0x76, 0xe0, 0x0e,
+ 0x6b, 0x2a, 0x5b, 0xd9, 0x18, 0x17, 0x47, 0x11, 0xe4, 0xe3, 0x60, 0xeb,
+ 0xf5, 0xa7, 0x49, 0x78, 0xef, 0xe7, 0xa9, 0x00, 0xa8, 0xe8, 0x08, 0xf7,
+ 0x02, 0xaa, 0xf9, 0xc7, 0xfb, 0x89, 0xff, 0x00, 0x7c, 0x8a, 0xe9, 0x84,
+ 0x2d, 0xb9, 0xc5, 0x56, 0xaf, 0x36, 0x89, 0x93, 0xc5, 0x7b, 0x22, 0x8d,
+ 0xef, 0x20, 0x7d, 0xa7, 0xee, 0x37, 0x53, 0x5a, 0xd1, 0x4a, 0x26, 0x8d,
+ 0x5d, 0x7a, 0x1a, 0xc2, 0xf3, 0x8f, 0xf7, 0x13, 0xfe, 0xf9, 0x15, 0x65,
+ 0x2f, 0x1e, 0x34, 0x84, 0x28, 0x50, 0x09, 0xe4, 0x01, 0xef, 0x44, 0xe1,
+ 0x7d, 0x85, 0x4e, 0xaf, 0x2e, 0xec, 0xd6, 0xa6, 0xcb, 0x28, 0x86, 0x36,
+ 0x76, 0xe8, 0x29, 0x37, 0x56, 0x63, 0xde, 0x3c, 0x89, 0x30, 0x60, 0xa4,
+ 0x0e, 0x80, 0x8f, 0x7a, 0xc2, 0x30, 0xe6, 0x3a, 0xa7, 0x53, 0x91, 0x0d,
+ 0x96, 0xf6, 0x46, 0x05, 0xd2, 0x40, 0x9b, 0x8f, 0xdc, 0x5e, 0xa3, 0xde,
+ 0x96, 0x2b, 0xd9, 0x14, 0x07, 0x77, 0x0f, 0xb4, 0xfd, 0xc6, 0xeb, 0xf5,
+ 0xaa, 0xfe, 0x71, 0xfe, 0xe2, 0x7f, 0xdf, 0x22, 0x8f, 0x38, 0xff, 0x00,
+ 0x71, 0x3f, 0xef, 0x91, 0x5d, 0x7c, 0xaa, 0xd6, 0xb1, 0xc1, 0xce, 0xef,
+ 0x7b, 0x9b, 0xb1, 0xc8, 0x25, 0x45, 0x75, 0xe8, 0x46, 0x69, 0xd5, 0x95,
+ 0x1d, 0xe3, 0xa0, 0x81, 0x46, 0x02, 0x9e, 0xa0, 0x0f, 0x72, 0x2b, 0x4b,
+ 0x35, 0xc9, 0x28, 0xf2, 0x9d, 0xf0, 0xa9, 0xce, 0x85, 0x92, 0x41, 0x1a,
+ 0x33, 0xb7, 0x40, 0x32, 0x6b, 0x2a, 0x5b, 0xd9, 0x1c, 0x17, 0x47, 0x09,
+ 0x93, 0x8d, 0x83, 0xaf, 0xd6, 0x9d, 0x25, 0xe3, 0xbf, 0x9e, 0xa4, 0x02,
+ 0xa3, 0xa0, 0x23, 0xdc, 0x55, 0x5f, 0x38, 0xff, 0x00, 0x71, 0x3f, 0xef,
+ 0x91, 0x5b, 0xc2, 0x16, 0xdc, 0xe6, 0xa9, 0x57, 0x9b, 0x44, 0xc8, 0xea,
+ 0x70, 0xa4, 0x88, 0x30, 0x09, 0xff, 0x00, 0xf5, 0xd3, 0x4d, 0xbb, 0x09,
+ 0x84, 0x59, 0x1b, 0xbd, 0x7b, 0x56, 0x95, 0xb4, 0x66, 0x18, 0x42, 0x13,
+ 0x92, 0x3d, 0x2a, 0xe5, 0x2b, 0x23, 0x2a, 0x70, 0x72, 0x6d, 0x32, 0x7a,
+ 0xc8, 0x2a, 0x40, 0x9f, 0x20, 0x8f, 0xff, 0x00, 0x5d, 0x6a, 0xe6, 0xa3,
+ 0xb9, 0x8c, 0xcf, 0x09, 0x40, 0x40, 0x27, 0xd6, 0xb1, 0x83, 0xe5, 0x3a,
+ 0x6a, 0x47, 0x99, 0x5c, 0xc7, 0xa2, 0xa5, 0x5b, 0x76, 0x69, 0x8c, 0x59,
+ 0x1b, 0xbf, 0x4a, 0x3e, 0xce, 0xde, 0x7f, 0x95, 0x91, 0xbb, 0xd7, 0xb5,
+ 0x74, 0xdd, 0x1c, 0x3c, 0xac, 0x7a, 0xa9, 0x2d, 0x6f, 0x80, 0x7f, 0xcb,
+ 0x1a, 0xd6, 0xa8, 0x6d, 0xe3, 0x30, 0xc2, 0xa8, 0x48, 0x24, 0x77, 0x15,
+ 0x26, 0x6b, 0x9a, 0x6f, 0x99, 0x9d, 0xf4, 0xe3, 0xca, 0x8c, 0xb6, 0x52,
+ 0x1a, 0xe3, 0x20, 0xff, 0x00, 0x96, 0x15, 0x5e, 0xb6, 0x2e, 0x23, 0x33,
+ 0x44, 0xc8, 0x08, 0x04, 0xd6, 0x67, 0xd9, 0xdb, 0xcf, 0xf2, 0xb2, 0x37,
+ 0x7a, 0xf6, 0xad, 0xa1, 0x24, 0xd1, 0xcb, 0x52, 0x0e, 0x2d, 0x58, 0x8a,
+ 0xa7, 0x0a, 0x48, 0x83, 0x00, 0x9f, 0xff, 0x00, 0x5d, 0x34, 0xdb, 0xb2,
+ 0xcc, 0x22, 0xc8, 0xdd, 0xeb, 0xda, 0xb4, 0xad, 0xa3, 0x30, 0xc2, 0xaa,
+ 0x4e, 0x48, 0xf4, 0xa2, 0x52, 0xb2, 0x0a, 0x70, 0x72, 0x6d, 0x32, 0x7a,
+ 0x29, 0xa4, 0xd1, 0x9a, 0xe5, 0xb1, 0xde, 0x3a, 0x8a, 0x6e, 0x73, 0x41,
+ 0x34, 0x58, 0x0e, 0x7f, 0xe2, 0x1f, 0xfc, 0x88, 0xfa, 0xe7, 0xfd, 0x7a,
+ 0xbf, 0xf2, 0xaf, 0x95, 0xab, 0xeb, 0x2f, 0x18, 0x58, 0x4b, 0xaa, 0xf8,
+ 0x57, 0x56, 0xb4, 0x80, 0x6e, 0x9a, 0x6b, 0x69, 0x15, 0x17, 0xd5, 0xb6,
+ 0x9c, 0x0f, 0xce, 0xbe, 0x4e, 0x65, 0x2a, 0x48, 0x20, 0x82, 0x38, 0x20,
+ 0xf6, 0xaf, 0xc1, 0x7c, 0x46, 0x84, 0x96, 0x32, 0x84, 0xed, 0xa3, 0x8b,
+ 0x5f, 0x73, 0xff, 0x00, 0x82, 0x8d, 0x20, 0x25, 0x7d, 0x5d, 0xe0, 0x5f,
+ 0xf9, 0x12, 0xf4, 0x2f, 0xfa, 0xf2, 0x87, 0xff, 0x00, 0x40, 0x15, 0xf2,
+ 0x9a, 0x23, 0x48, 0xea, 0x88, 0xa5, 0x9d, 0x8e, 0x02, 0x81, 0x92, 0x4d,
+ 0x7d, 0x69, 0xe1, 0x8b, 0x19, 0x34, 0xbf, 0x0d, 0xe9, 0x76, 0x73, 0x71,
+ 0x2c, 0x16, 0xd1, 0xc6, 0xe3, 0xd0, 0x85, 0x00, 0xd5, 0x78, 0x73, 0x09,
+ 0x3c, 0x56, 0x22, 0x76, 0xd1, 0x45, 0x2f, 0xc7, 0xfe, 0x00, 0x4c, 0xd0,
+ 0xba, 0xff, 0x00, 0x8f, 0x69, 0xbf, 0xdc, 0x3f, 0xca, 0xbe, 0x39, 0xaf,
+ 0xb1, 0xe5, 0x5f, 0x32, 0x27, 0x4c, 0xe3, 0x72, 0x91, 0x9a, 0xf9, 0x03,
+ 0x50, 0xb1, 0x9b, 0x4c, 0xbe, 0xb8, 0xb4, 0x9d, 0x0a, 0x4d, 0x04, 0x86,
+ 0x37, 0x53, 0xd8, 0x83, 0x8a, 0xed, 0xf1, 0x22, 0x12, 0xff, 0x00, 0x65,
+ 0x9d, 0xb4, 0xf7, 0xd7, 0xfe, 0x92, 0x10, 0x2b, 0xd7, 0xd2, 0x5f, 0x05,
+ 0xbf, 0xe4, 0x9f, 0x58, 0xff, 0x00, 0xd7, 0x49, 0x7f, 0xf4, 0x33, 0x5f,
+ 0x36, 0xd7, 0xd3, 0x9f, 0x0a, 0x74, 0xe9, 0xb4, 0xbf, 0x01, 0xe9, 0x91,
+ 0x4e, 0xa5, 0x24, 0x75, 0x69, 0x76, 0x9e, 0xa0, 0x33, 0x12, 0x3f, 0x42,
+ 0x2b, 0xc3, 0xf0, 0xf6, 0x12, 0x96, 0x69, 0x52, 0x49, 0x68, 0xa0, 0xff,
+ 0x00, 0x19, 0x44, 0x72, 0xd8, 0xeb, 0xe8, 0xa6, 0xe6, 0x8c, 0xd7, 0xf4,
+ 0x3d, 0x8c, 0x87, 0x51, 0x4d, 0xcd, 0x19, 0xa2, 0xc0, 0x65, 0xb2, 0x90,
+ 0xd7, 0x19, 0x04, 0x7f, 0xfb, 0x42, 0xab, 0xd6, 0xc5, 0xc4, 0x66, 0x68,
+ 0x59, 0x07, 0x04, 0xfa, 0xd6, 0x67, 0xd9, 0xdb, 0xcf, 0xf2, 0xb2, 0x37,
+ 0x7a, 0xf6, 0xae, 0xa8, 0x4a, 0xe8, 0xe0, 0xa9, 0x07, 0x16, 0xac, 0x45,
+ 0x53, 0x85, 0x24, 0x41, 0x80, 0x4f, 0xff, 0x00, 0xae, 0x9a, 0x6d, 0xd9,
+ 0x66, 0x11, 0x64, 0x6e, 0xf5, 0xed, 0x5a, 0x76, 0xd1, 0x98, 0x21, 0x0a,
+ 0x48, 0x27, 0xda, 0x89, 0x4a, 0xc8, 0x29, 0xc1, 0xc9, 0xb4, 0xc9, 0xab,
+ 0x20, 0xa9, 0x02, 0x7c, 0x82, 0x3f, 0xfd, 0x75, 0xab, 0x9a, 0x8a, 0xe6,
+ 0x33, 0x34, 0x45, 0x41, 0xc1, 0xf7, 0xac, 0x60, 0xf9, 0x4e, 0x9a, 0x91,
+ 0xe6, 0x46, 0x45, 0x15, 0x28, 0xb7, 0x66, 0x98, 0xc5, 0x91, 0xb8, 0x77,
+ 0xed, 0x47, 0xd9, 0xdb, 0xcf, 0xf2, 0xb2, 0x37, 0x7a, 0xf6, 0xae, 0x9b,
+ 0xa3, 0x87, 0x95, 0x8f, 0x55, 0x25, 0xad, 0xf0, 0x0f, 0xf9, 0x63, 0x5a,
+ 0xd5, 0x0d, 0xba, 0x18, 0x61, 0x54, 0x24, 0x12, 0x3d, 0x2a, 0x4c, 0xd7,
+ 0x34, 0xdf, 0x33, 0x3b, 0xe9, 0xc7, 0x95, 0x19, 0x6c, 0xa4, 0x35, 0xc6,
+ 0x41, 0xff, 0x00, 0x2c, 0x2a, 0xbd, 0x6c, 0x5c, 0x46, 0x66, 0x85, 0x90,
+ 0x1c, 0x13, 0xeb, 0x59, 0x9f, 0x67, 0x6f, 0x3f, 0xca, 0xc8, 0xdd, 0xfa,
+ 0x56, 0xd0, 0x92, 0x68, 0xe5, 0xa9, 0x06, 0x9a, 0xb1, 0xa0, 0xd6, 0xc1,
+ 0xae, 0x04, 0xb9, 0x39, 0x1d, 0xaa, 0x6a, 0x28, 0xae, 0x76, 0xdb, 0x3a,
+ 0xd2, 0xb6, 0xc1, 0x45, 0x14, 0x52, 0x19, 0x0a, 0xdb, 0x05, 0xb8, 0x32,
+ 0xe4, 0xe4, 0xf6, 0xa3, 0xec, 0xc3, 0xed, 0x1e, 0x6e, 0x4e, 0x7d, 0x2a,
+ 0x6a, 0x2a, 0xb9, 0x99, 0x3c, 0xa8, 0x28, 0xa2, 0x8a, 0x92, 0x82, 0xa1,
+ 0xfb, 0x30, 0xfb, 0x47, 0x9b, 0x93, 0x9f, 0x4a, 0x9a, 0x8a, 0x69, 0xd8,
+ 0x4d, 0x5f, 0x72, 0x16, 0xb6, 0x0d, 0x70, 0x25, 0xc9, 0xc8, 0xed, 0x53,
+ 0x51, 0x45, 0x0d, 0xb6, 0x09, 0x5b, 0x60, 0xa2, 0x8a, 0x29, 0x0c, 0x28,
+ 0xa2, 0x8a, 0x00, 0x2b, 0x83, 0xf1, 0x57, 0xc1, 0xdd, 0x1b, 0xc4, 0xb7,
+ 0xaf, 0x79, 0x1b, 0xcb, 0xa7, 0x5d, 0x48, 0x73, 0x21, 0x80, 0x02, 0x8e,
+ 0x7d, 0x4a, 0x9e, 0xff, 0x00, 0x42, 0x2b, 0xbc, 0xa2, 0xbc, 0xfc, 0x76,
+ 0x5f, 0x85, 0xcc, 0xa9, 0xfb, 0x1c, 0x5d, 0x35, 0x38, 0xf9, 0xfe, 0x8f,
+ 0x75, 0xf2, 0x1a, 0x6d, 0x1c, 0x3f, 0x84, 0xbe, 0x11, 0xe8, 0xde, 0x16,
+ 0xbb, 0x4b, 0xc2, 0xd2, 0x5f, 0xde, 0x27, 0x29, 0x24, 0xf8, 0xda, 0x87,
+ 0xd5, 0x54, 0x77, 0xf7, 0x39, 0xae, 0xe2, 0x8a, 0x29, 0xe0, 0xb0, 0x18,
+ 0x5c, 0xba, 0x97, 0xb1, 0xc2, 0x53, 0x50, 0x8f, 0x97, 0xeb, 0xd5, 0xfc,
+ 0xc2, 0xed, 0x85, 0x71, 0xfe, 0x31, 0xf8, 0x5f, 0xa4, 0x78, 0xc6, 0x6f,
+ 0xb4, 0xcd, 0xe6, 0x5a, 0x5e, 0xe3, 0x06, 0xe2, 0x0c, 0x65, 0xc7, 0x6d,
+ 0xc0, 0xf5, 0xfe, 0x7e, 0xf5, 0xd8, 0x51, 0x55, 0x8c, 0xc1, 0x61, 0xf1,
+ 0xf4, 0x9d, 0x0c, 0x54, 0x14, 0xe2, 0xfa, 0x3f, 0xeb, 0x46, 0x17, 0x68,
+ 0xf3, 0xbf, 0x0f, 0x7c, 0x11, 0xd1, 0x74, 0x6b, 0xc4, 0xb9, 0xb9, 0x96,
+ 0x5d, 0x49, 0xd0, 0xe5, 0x63, 0x94, 0x05, 0x8f, 0x3e, 0xa5, 0x47, 0x5f,
+ 0xc4, 0xe3, 0xda, 0xbd, 0x13, 0xa5, 0x14, 0x56, 0x38, 0x1c, 0xb7, 0x07,
+ 0x96, 0x41, 0xd3, 0xc1, 0xd3, 0x50, 0x4f, 0x7b, 0x75, 0xf5, 0x7b, 0xb0,
+ 0x6d, 0xb0, 0xa2, 0x8a, 0x2b, 0xd3, 0x10, 0x51, 0x45, 0x14, 0x00, 0x54,
+ 0x3f, 0x66, 0x1f, 0x68, 0xf3, 0x72, 0x73, 0xe9, 0x53, 0x51, 0x4d, 0x3b,
+ 0x09, 0xab, 0xee, 0x42, 0xd6, 0xc1, 0xae, 0x04, 0xb9, 0x39, 0x1d, 0xaa,
+ 0x6a, 0x28, 0xa1, 0xb6, 0xc1, 0x2b, 0x6c, 0x14, 0x51, 0x45, 0x21, 0x90,
+ 0xad, 0xb0, 0x5b, 0x83, 0x2e, 0x4e, 0x4f, 0x6a, 0x3e, 0xcc, 0x3e, 0xd1,
+ 0xe6, 0xe4, 0xe7, 0xd2, 0xa6, 0xa2, 0xab, 0x99, 0x93, 0xca, 0x82, 0x8a,
+ 0x28, 0xa9, 0x28, 0x2a, 0x1f, 0xb3, 0x0f, 0xb4, 0x79, 0xb9, 0x39, 0xf4,
+ 0xa9, 0xa8, 0xa6, 0x9d, 0x84, 0xd5, 0xf7, 0x3e, 0x20, 0xff, 0x00, 0x87,
+ 0xa6, 0xf8, 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xa3,
+ 0xfe, 0x1e, 0x9b, 0xe1, 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a,
+ 0xbe, 0x17, 0xfe, 0xc6, 0xb2, 0xff, 0x00, 0x9f, 0x64, 0xa7, 0x47, 0xa2,
+ 0x59, 0x31, 0xe6, 0xd9, 0x31, 0x45, 0x8e, 0x9e, 0x44, 0x7d, 0xcd, 0xff,
+ 0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa, 0xc7, 0xfe, 0x05, 0x45,
+ 0x47, 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb, 0x1f, 0xf8, 0x15,
+ 0x15, 0x7c, 0x3b, 0xfd, 0x87, 0x61, 0xff, 0x00, 0x3e, 0xb1, 0xfe, 0x54,
+ 0xd9, 0x34, 0x6b, 0x05, 0x1c, 0x5b, 0x47, 0x9f, 0xa5, 0x16, 0x0e, 0x44,
+ 0x7d, 0xc9, 0xff, 0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa, 0xc7,
+ 0xfe, 0x05, 0x45, 0x47, 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb,
+ 0x1f, 0xf8, 0x15, 0x15, 0x7c, 0x2f, 0xfd, 0x8d, 0x65, 0xff, 0x00, 0x3e,
+ 0xc9, 0xf9, 0x53, 0xe3, 0xd1, 0x2c, 0x4f, 0x26, 0xd9, 0x31, 0xf4, 0xa2,
+ 0xc1, 0xc8, 0x8f, 0xb9, 0x7f, 0xe1, 0xe9, 0xbe, 0x16, 0xff, 0x00, 0xa1,
+ 0x1f, 0x58, 0xff, 0x00, 0xc0, 0xa8, 0xa8, 0xff, 0x00, 0x87, 0xa6, 0xf8,
+ 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xaf, 0x87, 0x7f,
+ 0xb0, 0xec, 0x3f, 0xe7, 0xd6, 0x3f, 0xca, 0x99, 0x26, 0x8d, 0x62, 0x38,
+ 0x16, 0xc9, 0x9a, 0x2c, 0x1c, 0x88, 0xfb, 0x97, 0xfe, 0x1e, 0x9b, 0xe1,
+ 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a, 0x8f, 0xf8, 0x7a, 0x6f,
+ 0x85, 0xbf, 0xe8, 0x47, 0xd6, 0x3f, 0xf0, 0x2a, 0x2a, 0xf8, 0x5f, 0xfb,
+ 0x1a, 0xcb, 0xfe, 0x7d, 0x93, 0xf2, 0xa9, 0x23, 0xd1, 0x2c, 0x48, 0xc9,
+ 0xb6, 0x4f, 0xca, 0x8b, 0x07, 0x22, 0x3e, 0xe4, 0xff, 0x00, 0x87, 0xa6,
+ 0xf8, 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xa3, 0xfe,
+ 0x1e, 0x9b, 0xe1, 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a, 0xbe,
+ 0x1d, 0xfe, 0xc3, 0xb0, 0xff, 0x00, 0x9f, 0x58, 0xff, 0x00, 0x2a, 0x64,
+ 0x9a, 0x35, 0x88, 0x38, 0x16, 0xc9, 0xf9, 0x51, 0x60, 0xe4, 0x47, 0xdc,
+ 0xbf, 0xf0, 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac, 0x7f, 0xe0, 0x54,
+ 0x54, 0x7f, 0xc3, 0xd3, 0x7c, 0x2d, 0xff, 0x00, 0x42, 0x3e, 0xb1, 0xff,
+ 0x00, 0x81, 0x51, 0x57, 0xc2, 0xff, 0x00, 0xd8, 0xd6, 0x5f, 0xf3, 0xec,
+ 0x9f, 0x95, 0x48, 0x9a, 0x1d, 0x89, 0x19, 0x36, 0xc9, 0xf9, 0x51, 0x60,
+ 0xe4, 0x47, 0xdc, 0x9f, 0xf0, 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac,
+ 0x7f, 0xe0, 0x54, 0x54, 0x7f, 0xc3, 0xd3, 0x7c, 0x2d, 0xff, 0x00, 0x42,
+ 0x3e, 0xb1, 0xff, 0x00, 0x81, 0x51, 0x57, 0xc3, 0xbf, 0xd8, 0x76, 0x1f,
+ 0xf3, 0xeb, 0x1f, 0xe5, 0x51, 0xbe, 0x8d, 0x63, 0x9c, 0x0b, 0x64, 0xfc,
+ 0xa8, 0xb0, 0x72, 0x23, 0xee, 0x6f, 0xf8, 0x7a, 0x6f, 0x85, 0xbf, 0xe8,
+ 0x47, 0xd6, 0x3f, 0xf0, 0x2a, 0x2a, 0x3f, 0xe1, 0xe9, 0xbe, 0x16, 0xff,
+ 0x00, 0xa1, 0x1f, 0x58, 0xff, 0x00, 0xc0, 0xa8, 0xab, 0xe1, 0x7f, 0xec,
+ 0x7b, 0x2f, 0xf9, 0xf6, 0x4f, 0xca, 0x9b, 0x2e, 0x9d, 0xa7, 0xdb, 0xed,
+ 0x53, 0x67, 0xe6, 0xc8, 0xc0, 0x90, 0xb1, 0xae, 0x4e, 0x3d, 0x68, 0xb0,
+ 0x72, 0x23, 0xee, 0xaf, 0xf8, 0x7a, 0x6f, 0x85, 0xbf, 0xe8, 0x47, 0xd6,
+ 0x3f, 0xf0, 0x2a, 0x2a, 0x3f, 0xe1, 0xe9, 0xbe, 0x16, 0xff, 0x00, 0xa1,
+ 0x1f, 0x58, 0xff, 0x00, 0xc0, 0xa8, 0xab, 0xe1, 0x1f, 0x23, 0x4b, 0xd8,
+ 0x1b, 0xec, 0x44, 0x8d, 0xbb, 0x9b, 0x09, 0xf7, 0x06, 0x48, 0xc9, 0xe7,
+ 0xd8, 0xfe, 0x54, 0x3d, 0x9e, 0x9e, 0x2e, 0x04, 0x66, 0xcb, 0x60, 0x27,
+ 0x68, 0x72, 0xbf, 0x29, 0x3f, 0x5c, 0xd1, 0x60, 0xe4, 0x47, 0xdd, 0xdf,
+ 0xf0, 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac, 0x7f, 0xe0, 0x54, 0x54,
+ 0x7f, 0xc3, 0xd3, 0x7c, 0x2d, 0xff, 0x00, 0x42, 0x3e, 0xb1, 0xff, 0x00,
+ 0x81, 0x51, 0x57, 0xc1, 0x82, 0xdf, 0x4e, 0x1b, 0xb7, 0xd9, 0x98, 0x88,
+ 0x19, 0xda, 0xeb, 0xc9, 0xe7, 0x1c, 0x73, 0xea, 0x45, 0x4d, 0x1d, 0x9e,
+ 0x9a, 0x46, 0x0d, 0x91, 0x12, 0x02, 0x41, 0x8c, 0xaf, 0xcd, 0x9c, 0x67,
+ 0xd7, 0xd2, 0x8b, 0x07, 0x22, 0x3e, 0xed, 0xff, 0x00, 0x87, 0xa6, 0xf8,
+ 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xa3, 0xfe, 0x1e,
+ 0x9b, 0xe1, 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a, 0xbe, 0x16,
+ 0xb7, 0xd3, 0xf4, 0xeb, 0x86, 0x65, 0xfb, 0x1f, 0x96, 0xea, 0x01, 0x2b,
+ 0x22, 0xe0, 0xe0, 0xf7, 0xa7, 0x36, 0x8f, 0x62, 0x49, 0xc5, 0xb2, 0x62,
+ 0x8b, 0x07, 0x22, 0x3e, 0xe7, 0xff, 0x00, 0x87, 0xa6, 0xf8, 0x5b, 0xfe,
+ 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xa3, 0xfe, 0x1e, 0x9b, 0xe1,
+ 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a, 0x8a, 0xbe, 0x17, 0xfe, 0xc6,
+ 0xb2, 0x3f, 0xf2, 0xec, 0x95, 0x30, 0xd0, 0xec, 0x40, 0xff, 0x00, 0x8f,
+ 0x64, 0xa2, 0xc1, 0xc8, 0x8f, 0xb8, 0xbf, 0xe1, 0xe9, 0xbe, 0x16, 0xff,
+ 0x00, 0xa1, 0x1f, 0x58, 0xff, 0x00, 0xc0, 0xa8, 0xa8, 0xff, 0x00, 0x87,
+ 0xa6, 0xf8, 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2, 0xaf,
+ 0x87, 0x7f, 0xb1, 0x2c, 0x07, 0xfc, 0xba, 0xc7, 0xf9, 0x54, 0x27, 0x47,
+ 0xb2, 0x27, 0xfe, 0x3d, 0x92, 0x8b, 0x07, 0x22, 0x3e, 0xe8, 0xff, 0x00,
+ 0x87, 0xa6, 0xf8, 0x5b, 0xfe, 0x84, 0x7d, 0x63, 0xff, 0x00, 0x02, 0xa2,
+ 0xa3, 0xfe, 0x1e, 0x9b, 0xe1, 0x6f, 0xfa, 0x11, 0xf5, 0x8f, 0xfc, 0x0a,
+ 0x8a, 0xbe, 0x17, 0x1a, 0x2d, 0x91, 0x38, 0xfb, 0x32, 0x54, 0xdf, 0xd8,
+ 0x76, 0x1f, 0xf3, 0xea, 0x9f, 0x95, 0x16, 0x0e, 0x44, 0x7d, 0xc5, 0xff,
+ 0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa, 0xc7, 0xfe, 0x05, 0x45,
+ 0x47, 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb, 0x1f, 0xf8, 0x15,
+ 0x15, 0x7c, 0x3a, 0x74, 0x4b, 0x00, 0x33, 0xf6, 0x58, 0xff, 0x00, 0x2a,
+ 0x84, 0xe8, 0xd6, 0x5f, 0xf3, 0xec, 0x94, 0x58, 0x39, 0x11, 0xf7, 0x47,
+ 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb, 0x1f, 0xf8, 0x15, 0x15,
+ 0x1f, 0xf0, 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac, 0x7f, 0xe0, 0x54,
+ 0x55, 0xf0, 0xc2, 0xe8, 0xb6, 0x4c, 0x40, 0xfb, 0x32, 0x54, 0xbf, 0xd8,
+ 0x76, 0x1f, 0xf3, 0xea, 0x94, 0x58, 0x39, 0x11, 0xf7, 0x17, 0xfc, 0x3d,
+ 0x37, 0xc2, 0xdf, 0xf4, 0x23, 0xeb, 0x1f, 0xf8, 0x15, 0x15, 0x1f, 0xf0,
+ 0xf4, 0xdf, 0x0b, 0x7f, 0xd0, 0x8f, 0xac, 0x7f, 0xe0, 0x54, 0x55, 0xf0,
+ 0xe3, 0x68, 0xb6, 0x0a, 0x09, 0xfb, 0x2c, 0x7f, 0x95, 0x45, 0xfd, 0x8d,
+ 0x65, 0xff, 0x00, 0x3e, 0xc9, 0x45, 0x83, 0x91, 0x1f, 0x74, 0x7f, 0xc3,
+ 0xd3, 0x7c, 0x2d, 0xff, 0x00, 0x42, 0x3e, 0xb1, 0xff, 0x00, 0x81, 0x51,
+ 0x51, 0xff, 0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa, 0xc7, 0xfe,
+ 0x05, 0x45, 0x5f, 0x0c, 0x26, 0x89, 0x64, 0xcd, 0xff, 0x00, 0x1e, 0xc9,
+ 0x52, 0xff, 0x00, 0x61, 0xd8, 0x7f, 0xcf, 0xac, 0x7f, 0x95, 0x16, 0x0e,
+ 0x44, 0x7d, 0xc5, 0xff, 0x00, 0x0f, 0x4d, 0xf0, 0xb7, 0xfd, 0x08, 0xfa,
+ 0xc7, 0xfe, 0x05, 0x45, 0x47, 0xfc, 0x3d, 0x37, 0xc2, 0xdf, 0xf4, 0x23,
+ 0xeb, 0x1f, 0xf8, 0x15, 0x15, 0x7c, 0x38, 0xfa, 0x2d, 0x82, 0xaf, 0xfc,
+ 0x7a, 0xc7, 0xf9, 0x54, 0x5f, 0xd8, 0xd6, 0x5f, 0xf3, 0xec, 0x94, 0x58,
+ 0x39, 0x11, 0x72, 0xa7, 0x45, 0xda, 0xb8, 0xa8, 0xe3, 0x5c, 0xb6, 0x7d,
+ 0x2a, 0x5a, 0xa2, 0xc2, 0xa1, 0x66, 0xdc, 0xd9, 0xa7, 0xc8, 0xd8, 0x18,
+ 0xf5, 0xa8, 0xa8, 0x01, 0x40, 0xc9, 0xa9, 0xd4, 0x6d, 0x18, 0xa8, 0xe2,
+ 0x5e, 0x73, 0x52, 0x50, 0x00, 0x4e, 0x05, 0x40, 0xc7, 0x71, 0xcd, 0x49,
+ 0x2b, 0x71, 0x8a, 0x8a, 0x80, 0x14, 0x0c, 0x9c, 0x54, 0xe0, 0x60, 0x62,
+ 0xa3, 0x89, 0x7b, 0xd4, 0x94, 0x00, 0x13, 0x80, 0x4d, 0x40, 0x4e, 0x4e,
+ 0x69, 0xf2, 0xb7, 0x6a, 0x8e, 0x80, 0x15, 0x46, 0xe3, 0x8a, 0x9e, 0x99,
+ 0x1a, 0xe0, 0x67, 0xd6, 0x9f, 0x40, 0x08, 0xc7, 0x68, 0xcd, 0x41, 0x4f,
+ 0x91, 0xb2, 0x71, 0xe9, 0x4c, 0xa0, 0x07, 0x22, 0xee, 0x6f, 0x6a, 0x27,
+ 0xb5, 0x59, 0xa4, 0x49, 0x37, 0xbc, 0x6e, 0xbc, 0x06, 0x43, 0x8c, 0x8f,
+ 0x43, 0xed, 0x52, 0x46, 0xb8, 0x5f, 0x73, 0x4e, 0xa0, 0x0a, 0xa6, 0xca,
+ 0x38, 0xa2, 0x95, 0x41, 0x6f, 0xde, 0x2e, 0xc3, 0xcf, 0x6c, 0x93, 0xff,
+ 0x00, 0xb3, 0x1a, 0x87, 0xec, 0x60, 0xca, 0xae, 0xd2, 0x48, 0xe1, 0x4e,
+ 0x42, 0x12, 0x36, 0x83, 0xf9, 0x55, 0xa9, 0x1b, 0x73, 0x7b, 0x0a, 0x6d,
+ 0x00, 0x57, 0x8b, 0x49, 0xb7, 0x0c, 0xfb, 0x53, 0xcb, 0x0c, 0x00, 0x21,
+ 0x38, 0xe8, 0x72, 0x0f, 0xd6, 0xa6, 0x5d, 0x39, 0x17, 0x90, 0xf2, 0x79,
+ 0x99, 0x2c, 0x64, 0x27, 0x2c, 0x4e, 0xdc, 0x7e, 0x82, 0xac, 0xa2, 0xed,
+ 0x5a, 0x5a, 0x00, 0xad, 0x1d, 0xaa, 0xdb, 0x16, 0x6f, 0x31, 0xe5, 0x91,
+ 0xc0, 0x05, 0xe4, 0x39, 0x38, 0x1d, 0xbf, 0x5a, 0x5a, 0x73, 0xb6, 0xe6,
+ 0xa6, 0xf5, 0xa0, 0x07, 0xc4, 0xb9, 0x39, 0xf4, 0xa9, 0x69, 0x14, 0x6d,
+ 0x18, 0xa5, 0xe9, 0x40, 0x0c, 0x95, 0xb0, 0x31, 0x51, 0x52, 0xb1, 0xdc,
+ 0x49, 0xa0, 0x0c, 0x9c, 0x50, 0x03, 0xe2, 0x5e, 0xf5, 0x25, 0x00, 0x60,
+ 0x62, 0x82, 0x70, 0x33, 0x40, 0x11, 0xca, 0xdd, 0xaa, 0x3a, 0x52, 0x72,
+ 0x73, 0x42, 0x8d, 0xc4, 0x0a, 0x00, 0x92, 0x25, 0xc0, 0xcd, 0x3e, 0x8e,
+ 0x94, 0x8c, 0x76, 0x82, 0x68, 0x02, 0x39, 0x5b, 0x27, 0x1e, 0x94, 0xca,
+ 0x3a, 0xd3, 0x91, 0x77, 0x35, 0x00, 0x49, 0x1a, 0xe1, 0x7d, 0xcd, 0x3a,
+ 0x8a, 0x47, 0x6d, 0xab, 0x40, 0x11, 0xc8, 0xd9, 0x6f, 0x61, 0x4c, 0xa2,
+ 0x9d, 0x1a, 0xee, 0x6f, 0x61, 0x40, 0x1f, 0xff, 0xd9
+};
diff --git a/services/camera/libcameraservice/FakeCamera.cpp b/services/camera/libcameraservice/FakeCamera.cpp
new file mode 100644
index 0000000..f3a6a67
--- /dev/null
+++ b/services/camera/libcameraservice/FakeCamera.cpp
@@ -0,0 +1,433 @@
+/*
+**
+** 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.
+*/
+
+#define LOG_TAG "FakeCamera"
+#include <utils/Log.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <utils/String8.h>
+
+#include "FakeCamera.h"
+
+
+namespace android {
+
+// TODO: All this rgb to yuv should probably be in a util class.
+
+// TODO: I think something is wrong in this class because the shadow is kBlue
+// and the square color should alternate between kRed and kGreen. However on the
+// emulator screen these are all shades of gray. Y seems ok but the U and V are
+// probably not.
+
+static int tables_initialized = 0;
+uint8_t *gYTable, *gCbTable, *gCrTable;
+
+static int
+clamp(int x)
+{
+ if (x > 255) return 255;
+ if (x < 0) return 0;
+ return x;
+}
+
+/* the equation used by the video code to translate YUV to RGB looks like this
+ *
+ * Y = (Y0 - 16)*k0
+ * Cb = Cb0 - 128
+ * Cr = Cr0 - 128
+ *
+ * G = ( Y - k1*Cr - k2*Cb )
+ * R = ( Y + k3*Cr )
+ * B = ( Y + k4*Cb )
+ *
+ */
+
+static const double k0 = 1.164;
+static const double k1 = 0.813;
+static const double k2 = 0.391;
+static const double k3 = 1.596;
+static const double k4 = 2.018;
+
+/* let's try to extract the value of Y
+ *
+ * G + k1/k3*R + k2/k4*B = Y*( 1 + k1/k3 + k2/k4 )
+ *
+ * Y = ( G + k1/k3*R + k2/k4*B ) / (1 + k1/k3 + k2/k4)
+ * Y0 = ( G0 + k1/k3*R0 + k2/k4*B0 ) / ((1 + k1/k3 + k2/k4)*k0) + 16
+ *
+ * let define:
+ * kYr = k1/k3
+ * kYb = k2/k4
+ * kYy = k0 * ( 1 + kYr + kYb )
+ *
+ * we have:
+ * Y = ( G + kYr*R + kYb*B )
+ * Y0 = clamp[ Y/kYy + 16 ]
+ */
+
+static const double kYr = k1/k3;
+static const double kYb = k2/k4;
+static const double kYy = k0*( 1. + kYr + kYb );
+
+static void
+initYtab( void )
+{
+ const int imax = (int)( (kYr + kYb)*(31 << 2) + (61 << 3) + 0.1 );
+ int i;
+
+ gYTable = (uint8_t *)malloc(imax);
+
+ for(i=0; i<imax; i++) {
+ int x = (int)(i/kYy + 16.5);
+ if (x < 16) x = 16;
+ else if (x > 235) x = 235;
+ gYTable[i] = (uint8_t) x;
+ }
+}
+
+/*
+ * the source is RGB565, so adjust for 8-bit range of input values:
+ *
+ * G = (pixels >> 3) & 0xFC;
+ * R = (pixels >> 8) & 0xF8;
+ * B = (pixels & 0x1f) << 3;
+ *
+ * R2 = (pixels >> 11) R = R2*8
+ * B2 = (pixels & 0x1f) B = B2*8
+ *
+ * kYr*R = kYr2*R2 => kYr2 = kYr*8
+ * kYb*B = kYb2*B2 => kYb2 = kYb*8
+ *
+ * we want to use integer multiplications:
+ *
+ * SHIFT1 = 9
+ *
+ * (ALPHA*R2) >> SHIFT1 == R*kYr => ALPHA = kYr*8*(1 << SHIFT1)
+ *
+ * ALPHA = kYr*(1 << (SHIFT1+3))
+ * BETA = kYb*(1 << (SHIFT1+3))
+ */
+
+static const int SHIFT1 = 9;
+static const int ALPHA = (int)( kYr*(1 << (SHIFT1+3)) + 0.5 );
+static const int BETA = (int)( kYb*(1 << (SHIFT1+3)) + 0.5 );
+
+/*
+ * now let's try to get the values of Cb and Cr
+ *
+ * R-B = (k3*Cr - k4*Cb)
+ *
+ * k3*Cr = k4*Cb + (R-B)
+ * k4*Cb = k3*Cr - (R-B)
+ *
+ * R-G = (k1+k3)*Cr + k2*Cb
+ * = (k1+k3)*Cr + k2/k4*(k3*Cr - (R-B)/k0)
+ * = (k1 + k3 + k2*k3/k4)*Cr - k2/k4*(R-B)
+ *
+ * kRr*Cr = (R-G) + kYb*(R-B)
+ *
+ * Cr = ((R-G) + kYb*(R-B))/kRr
+ * Cr0 = clamp(Cr + 128)
+ */
+
+static const double kRr = (k1 + k3 + k2*k3/k4);
+
+static void
+initCrtab( void )
+{
+ uint8_t *pTable;
+ int i;
+
+ gCrTable = (uint8_t *)malloc(768*2);
+
+ pTable = gCrTable + 384;
+ for(i=-384; i<384; i++)
+ pTable[i] = (uint8_t) clamp( i/kRr + 128.5 );
+}
+
+/*
+ * B-G = (k2 + k4)*Cb + k1*Cr
+ * = (k2 + k4)*Cb + k1/k3*(k4*Cb + (R-B))
+ * = (k2 + k4 + k1*k4/k3)*Cb + k1/k3*(R-B)
+ *
+ * kBb*Cb = (B-G) - kYr*(R-B)
+ *
+ * Cb = ((B-G) - kYr*(R-B))/kBb
+ * Cb0 = clamp(Cb + 128)
+ *
+ */
+
+static const double kBb = (k2 + k4 + k1*k4/k3);
+
+static void
+initCbtab( void )
+{
+ uint8_t *pTable;
+ int i;
+
+ gCbTable = (uint8_t *)malloc(768*2);
+
+ pTable = gCbTable + 384;
+ for(i=-384; i<384; i++)
+ pTable[i] = (uint8_t) clamp( i/kBb + 128.5 );
+}
+
+/*
+ * SHIFT2 = 16
+ *
+ * DELTA = kYb*(1 << SHIFT2)
+ * GAMMA = kYr*(1 << SHIFT2)
+ */
+
+static const int SHIFT2 = 16;
+static const int DELTA = kYb*(1 << SHIFT2);
+static const int GAMMA = kYr*(1 << SHIFT2);
+
+int32_t ccrgb16toyuv_wo_colorkey(uint8_t *rgb16, uint8_t *yuv420,
+ uint32_t *param, uint8_t *table[])
+{
+ uint16_t *inputRGB = (uint16_t*)rgb16;
+ uint8_t *outYUV = yuv420;
+ int32_t width_dst = param[0];
+ int32_t height_dst = param[1];
+ int32_t pitch_dst = param[2];
+ int32_t mheight_dst = param[3];
+ int32_t pitch_src = param[4];
+ uint8_t *y_tab = table[0];
+ uint8_t *cb_tab = table[1];
+ uint8_t *cr_tab = table[2];
+
+ int32_t size16 = pitch_dst*mheight_dst;
+ int32_t i,j,count;
+ int32_t ilimit,jlimit;
+ uint8_t *tempY,*tempU,*tempV;
+ uint16_t pixels;
+ int tmp;
+uint32_t temp;
+
+ tempY = outYUV;
+ tempU = outYUV + (height_dst * pitch_dst);
+ tempV = tempU + 1;
+
+ jlimit = height_dst;
+ ilimit = width_dst;
+
+ for(j=0; j<jlimit; j+=1)
+ {
+ for (i=0; i<ilimit; i+=2)
+ {
+ int32_t G_ds = 0, B_ds = 0, R_ds = 0;
+ uint8_t y0, y1, u, v;
+
+ pixels = inputRGB[i];
+ temp = (BETA*(pixels & 0x001F) + ALPHA*(pixels>>11) );
+ y0 = y_tab[(temp>>SHIFT1) + ((pixels>>3) & 0x00FC)];
+
+ G_ds += (pixels>>1) & 0x03E0;
+ B_ds += (pixels<<5) & 0x03E0;
+ R_ds += (pixels>>6) & 0x03E0;
+
+ pixels = inputRGB[i+1];
+ temp = (BETA*(pixels & 0x001F) + ALPHA*(pixels>>11) );
+ y1 = y_tab[(temp>>SHIFT1) + ((pixels>>3) & 0x00FC)];
+
+ G_ds += (pixels>>1) & 0x03E0;
+ B_ds += (pixels<<5) & 0x03E0;
+ R_ds += (pixels>>6) & 0x03E0;
+
+ R_ds >>= 1;
+ B_ds >>= 1;
+ G_ds >>= 1;
+
+ tmp = R_ds - B_ds;
+
+ u = cb_tab[(((B_ds-G_ds)<<SHIFT2) - GAMMA*tmp)>>(SHIFT2+2)];
+ v = cr_tab[(((R_ds-G_ds)<<SHIFT2) + DELTA*tmp)>>(SHIFT2+2)];
+
+ tempY[0] = y0;
+ tempY[1] = y1;
+ tempY += 2;
+
+ if ((j&1) == 0) {
+ tempU[0] = u;
+ tempV[0] = v;
+ tempU += 2;
+ tempV += 2;
+ }
+ }
+
+ inputRGB += pitch_src;
+ }
+
+ return 1;
+}
+
+#define min(a,b) ((a)<(b)?(a):(b))
+#define max(a,b) ((a)>(b)?(a):(b))
+
+static void convert_rgb16_to_yuv420(uint8_t *rgb, uint8_t *yuv, int width, int height)
+{
+ if (!tables_initialized) {
+ initYtab();
+ initCrtab();
+ initCbtab();
+ tables_initialized = 1;
+ }
+
+ uint32_t param[6];
+ param[0] = (uint32_t) width;
+ param[1] = (uint32_t) height;
+ param[2] = (uint32_t) width;
+ param[3] = (uint32_t) height;
+ param[4] = (uint32_t) width;
+ param[5] = (uint32_t) 0;
+
+ uint8_t *table[3];
+ table[0] = gYTable;
+ table[1] = gCbTable + 384;
+ table[2] = gCrTable + 384;
+
+ ccrgb16toyuv_wo_colorkey(rgb, yuv, param, table);
+}
+
+const int FakeCamera::kRed;
+const int FakeCamera::kGreen;
+const int FakeCamera::kBlue;
+
+FakeCamera::FakeCamera(int width, int height)
+ : mTmpRgb16Buffer(0)
+{
+ setSize(width, height);
+}
+
+FakeCamera::~FakeCamera()
+{
+ delete[] mTmpRgb16Buffer;
+}
+
+void FakeCamera::setSize(int width, int height)
+{
+ mWidth = width;
+ mHeight = height;
+ mCounter = 0;
+ mCheckX = 0;
+ mCheckY = 0;
+
+ // This will cause it to be reallocated on the next call
+ // to getNextFrameAsYuv420().
+ delete[] mTmpRgb16Buffer;
+ mTmpRgb16Buffer = 0;
+}
+
+void FakeCamera::getNextFrameAsRgb565(uint16_t *buffer)
+{
+ int size = mWidth / 10;
+
+ drawCheckerboard(buffer, size);
+
+ int x = ((mCounter*3)&255);
+ if(x>128) x = 255 - x;
+ int y = ((mCounter*5)&255);
+ if(y>128) y = 255 - y;
+
+ drawSquare(buffer, x*size/32, y*size/32, (size*5)>>1, (mCounter&0x100)?kRed:kGreen, kBlue);
+
+ mCounter++;
+}
+
+void FakeCamera::getNextFrameAsYuv420(uint8_t *buffer)
+{
+ if (mTmpRgb16Buffer == 0)
+ mTmpRgb16Buffer = new uint16_t[mWidth * mHeight];
+
+ getNextFrameAsRgb565(mTmpRgb16Buffer);
+ convert_rgb16_to_yuv420((uint8_t*)mTmpRgb16Buffer, buffer, mWidth, mHeight);
+}
+
+void FakeCamera::drawSquare(uint16_t *dst, int x, int y, int size, int color, int shadow)
+{
+ int square_xstop, square_ystop, shadow_xstop, shadow_ystop;
+
+ square_xstop = min(mWidth, x+size);
+ square_ystop = min(mHeight, y+size);
+ shadow_xstop = min(mWidth, x+size+(size/4));
+ shadow_ystop = min(mHeight, y+size+(size/4));
+
+ // Do the shadow.
+ uint16_t *sh = &dst[(y+(size/4))*mWidth];
+ for (int j = y + (size/4); j < shadow_ystop; j++) {
+ for (int i = x + (size/4); i < shadow_xstop; i++) {
+ sh[i] &= shadow;
+ }
+ sh += mWidth;
+ }
+
+ // Draw the square.
+ uint16_t *sq = &dst[y*mWidth];
+ for (int j = y; j < square_ystop; j++) {
+ for (int i = x; i < square_xstop; i++) {
+ sq[i] = color;
+ }
+ sq += mWidth;
+ }
+}
+
+void FakeCamera::drawCheckerboard(uint16_t *dst, int size)
+{
+ bool black = true;
+
+ if((mCheckX/size)&1)
+ black = false;
+ if((mCheckY/size)&1)
+ black = !black;
+
+ int county = mCheckY%size;
+ int checkxremainder = mCheckX%size;
+
+ for(int y=0;y<mHeight;y++) {
+ int countx = checkxremainder;
+ bool current = black;
+ for(int x=0;x<mWidth;x++) {
+ dst[y*mWidth+x] = current?0:0xffff;
+ if(countx++ >= size) {
+ countx=0;
+ current = !current;
+ }
+ }
+ if(county++ >= size) {
+ county=0;
+ black = !black;
+ }
+ }
+ mCheckX += 3;
+ mCheckY++;
+}
+
+
+void FakeCamera::dump(int fd) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ snprintf(buffer, 255, " width x height (%d x %d), counter (%d), check x-y coordinate(%d, %d)\n", mWidth, mHeight, mCounter, mCheckX, mCheckY);
+ result.append(buffer);
+ ::write(fd, result.string(), result.size());
+}
+
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/FakeCamera.h b/services/camera/libcameraservice/FakeCamera.h
new file mode 100644
index 0000000..724de20
--- /dev/null
+++ b/services/camera/libcameraservice/FakeCamera.h
@@ -0,0 +1,67 @@
+/*
+**
+** 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_HARDWARE_FAKECAMERA_H
+#define ANDROID_HARDWARE_FAKECAMERA_H
+
+#include <sys/types.h>
+#include <stdint.h>
+
+namespace android {
+
+/*
+ * FakeCamera is used in the CameraHardwareStub to provide a fake video feed
+ * when the system does not have a camera in hardware.
+ * The fake video is a moving black and white checkerboard background with a
+ * bouncing gray square in the foreground.
+ * This class is not thread-safe.
+ *
+ * TODO: Since the major methods provides a raw/uncompressed video feed, rename
+ * this class to RawVideoSource.
+ */
+
+class FakeCamera {
+public:
+ FakeCamera(int width, int height);
+ ~FakeCamera();
+
+ void setSize(int width, int height);
+ void getNextFrameAsYuv420(uint8_t *buffer);
+ // Write to the fd a string representing the current state.
+ void dump(int fd) const;
+
+private:
+ // TODO: remove the uint16_t buffer param everywhere since it is a field of
+ // this class.
+ void getNextFrameAsRgb565(uint16_t *buffer);
+
+ void drawSquare(uint16_t *buffer, int x, int y, int size, int color, int shadow);
+ void drawCheckerboard(uint16_t *buffer, int size);
+
+ static const int kRed = 0xf800;
+ static const int kGreen = 0x07c0;
+ static const int kBlue = 0x003e;
+
+ int mWidth, mHeight;
+ int mCounter;
+ int mCheckX, mCheckY;
+ uint16_t *mTmpRgb16Buffer;
+};
+
+}; // namespace android
+
+#endif // ANDROID_HARDWARE_FAKECAMERA_H
diff --git a/services/camera/tests/CameraServiceTest/Android.mk b/services/camera/tests/CameraServiceTest/Android.mk
new file mode 100644
index 0000000..cf7302a
--- /dev/null
+++ b/services/camera/tests/CameraServiceTest/Android.mk
@@ -0,0 +1,26 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= CameraServiceTest.cpp
+
+LOCAL_MODULE:= CameraServiceTest
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_C_INCLUDES += \
+ frameworks/base/libs
+
+LOCAL_CFLAGS :=
+
+LOCAL_SHARED_LIBRARIES += \
+ libbinder \
+ libcutils \
+ libutils \
+ libui \
+ libcamera_client \
+ libgui
+
+# Disable it because the ISurface interface may change, and before we have a
+# chance to fix this test, we don't want to break normal builds.
+#include $(BUILD_EXECUTABLE)
diff --git a/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
new file mode 100644
index 0000000..e417b79
--- /dev/null
+++ b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
@@ -0,0 +1,924 @@
+/*
+ * 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 "CameraServiceTest"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
+#include <ui/GraphicBuffer.h>
+#include <camera/ICamera.h>
+#include <camera/ICameraClient.h>
+#include <camera/ICameraService.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <utils/KeyedVector.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+using namespace android;
+
+//
+// Assertion and Logging utilities
+//
+#define INFO(...) \
+ do { \
+ printf(__VA_ARGS__); \
+ printf("\n"); \
+ ALOGD(__VA_ARGS__); \
+ } while(0)
+
+void assert_fail(const char *file, int line, const char *func, const char *expr) {
+ INFO("assertion failed at file %s, line %d, function %s:",
+ file, line, func);
+ INFO("%s", expr);
+ abort();
+}
+
+void assert_eq_fail(const char *file, int line, const char *func,
+ const char *expr, int actual) {
+ INFO("assertion failed at file %s, line %d, function %s:",
+ file, line, func);
+ INFO("(expected) %s != (actual) %d", expr, actual);
+ abort();
+}
+
+#define ASSERT(e) \
+ do { \
+ if (!(e)) \
+ assert_fail(__FILE__, __LINE__, __func__, #e); \
+ } while(0)
+
+#define ASSERT_EQ(expected, actual) \
+ do { \
+ int _x = (actual); \
+ if (_x != (expected)) \
+ assert_eq_fail(__FILE__, __LINE__, __func__, #expected, _x); \
+ } while(0)
+
+//
+// Holder service for pass objects between processes.
+//
+class IHolder : public IInterface {
+protected:
+ enum {
+ HOLDER_PUT = IBinder::FIRST_CALL_TRANSACTION,
+ HOLDER_GET,
+ HOLDER_CLEAR
+ };
+public:
+ DECLARE_META_INTERFACE(Holder);
+
+ virtual void put(sp<IBinder> obj) = 0;
+ virtual sp<IBinder> get() = 0;
+ virtual void clear() = 0;
+};
+
+class BnHolder : public BnInterface<IHolder> {
+ virtual status_t onTransact(uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+class BpHolder : public BpInterface<IHolder> {
+public:
+ BpHolder(const sp<IBinder>& impl)
+ : BpInterface<IHolder>(impl) {
+ }
+
+ virtual void put(sp<IBinder> obj) {
+ Parcel data, reply;
+ data.writeStrongBinder(obj);
+ remote()->transact(HOLDER_PUT, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+
+ virtual sp<IBinder> get() {
+ Parcel data, reply;
+ remote()->transact(HOLDER_GET, data, &reply);
+ return reply.readStrongBinder();
+ }
+
+ virtual void clear() {
+ Parcel data, reply;
+ remote()->transact(HOLDER_CLEAR, data, &reply);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(Holder, "CameraServiceTest.Holder");
+
+status_t BnHolder::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+ switch(code) {
+ case HOLDER_PUT: {
+ put(data.readStrongBinder());
+ return NO_ERROR;
+ } break;
+ case HOLDER_GET: {
+ reply->writeStrongBinder(get());
+ return NO_ERROR;
+ } break;
+ case HOLDER_CLEAR: {
+ clear();
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+class HolderService : public BnHolder {
+ virtual void put(sp<IBinder> obj) {
+ mObj = obj;
+ }
+ virtual sp<IBinder> get() {
+ return mObj;
+ }
+ virtual void clear() {
+ mObj.clear();
+ }
+private:
+ sp<IBinder> mObj;
+};
+
+//
+// A mock CameraClient
+//
+class MCameraClient : public BnCameraClient {
+public:
+ virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2);
+ virtual void dataCallback(int32_t msgType, const sp<IMemory>& data);
+ virtual void dataCallbackTimestamp(nsecs_t timestamp,
+ int32_t msgType, const sp<IMemory>& data);
+
+ // new functions
+ void clearStat();
+ enum OP { EQ, GE, LE, GT, LT };
+ void assertNotify(int32_t msgType, OP op, int count);
+ void assertData(int32_t msgType, OP op, int count);
+ void waitNotify(int32_t msgType, OP op, int count);
+ void waitData(int32_t msgType, OP op, int count);
+ void assertDataSize(int32_t msgType, OP op, int dataSize);
+
+ void setReleaser(ICamera *releaser) {
+ mReleaser = releaser;
+ }
+private:
+ Mutex mLock;
+ Condition mCond;
+ DefaultKeyedVector<int32_t, int> mNotifyCount;
+ DefaultKeyedVector<int32_t, int> mDataCount;
+ DefaultKeyedVector<int32_t, int> mDataSize;
+ bool test(OP op, int v1, int v2);
+ void assertTest(OP op, int v1, int v2);
+
+ ICamera *mReleaser;
+};
+
+void MCameraClient::clearStat() {
+ Mutex::Autolock _l(mLock);
+ mNotifyCount.clear();
+ mDataCount.clear();
+ mDataSize.clear();
+}
+
+bool MCameraClient::test(OP op, int v1, int v2) {
+ switch (op) {
+ case EQ: return v1 == v2;
+ case GT: return v1 > v2;
+ case LT: return v1 < v2;
+ case GE: return v1 >= v2;
+ case LE: return v1 <= v2;
+ default: ASSERT(0); break;
+ }
+ return false;
+}
+
+void MCameraClient::assertTest(OP op, int v1, int v2) {
+ if (!test(op, v1, v2)) {
+ ALOGE("assertTest failed: op=%d, v1=%d, v2=%d", op, v1, v2);
+ ASSERT(0);
+ }
+}
+
+void MCameraClient::assertNotify(int32_t msgType, OP op, int count) {
+ Mutex::Autolock _l(mLock);
+ int v = mNotifyCount.valueFor(msgType);
+ assertTest(op, v, count);
+}
+
+void MCameraClient::assertData(int32_t msgType, OP op, int count) {
+ Mutex::Autolock _l(mLock);
+ int v = mDataCount.valueFor(msgType);
+ assertTest(op, v, count);
+}
+
+void MCameraClient::assertDataSize(int32_t msgType, OP op, int dataSize) {
+ Mutex::Autolock _l(mLock);
+ int v = mDataSize.valueFor(msgType);
+ assertTest(op, v, dataSize);
+}
+
+void MCameraClient::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) {
+ INFO("%s", __func__);
+ Mutex::Autolock _l(mLock);
+ ssize_t i = mNotifyCount.indexOfKey(msgType);
+ if (i < 0) {
+ mNotifyCount.add(msgType, 1);
+ } else {
+ ++mNotifyCount.editValueAt(i);
+ }
+ mCond.signal();
+}
+
+void MCameraClient::dataCallback(int32_t msgType, const sp<IMemory>& data) {
+ INFO("%s", __func__);
+ int dataSize = data->size();
+ INFO("data type = %d, size = %d", msgType, dataSize);
+ Mutex::Autolock _l(mLock);
+ ssize_t i = mDataCount.indexOfKey(msgType);
+ if (i < 0) {
+ mDataCount.add(msgType, 1);
+ mDataSize.add(msgType, dataSize);
+ } else {
+ ++mDataCount.editValueAt(i);
+ mDataSize.editValueAt(i) = dataSize;
+ }
+ mCond.signal();
+
+ if (msgType == CAMERA_MSG_VIDEO_FRAME) {
+ ASSERT(mReleaser != NULL);
+ mReleaser->releaseRecordingFrame(data);
+ }
+}
+
+void MCameraClient::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+ const sp<IMemory>& data) {
+ dataCallback(msgType, data);
+}
+
+void MCameraClient::waitNotify(int32_t msgType, OP op, int count) {
+ INFO("waitNotify: %d, %d, %d", msgType, op, count);
+ Mutex::Autolock _l(mLock);
+ while (true) {
+ int v = mNotifyCount.valueFor(msgType);
+ if (test(op, v, count)) {
+ break;
+ }
+ mCond.wait(mLock);
+ }
+}
+
+void MCameraClient::waitData(int32_t msgType, OP op, int count) {
+ INFO("waitData: %d, %d, %d", msgType, op, count);
+ Mutex::Autolock _l(mLock);
+ while (true) {
+ int v = mDataCount.valueFor(msgType);
+ if (test(op, v, count)) {
+ break;
+ }
+ mCond.wait(mLock);
+ }
+}
+
+//
+// A mock Surface
+//
+class MSurface : public BnSurface {
+public:
+ virtual status_t registerBuffers(const BufferHeap& buffers);
+ virtual void postBuffer(ssize_t offset);
+ virtual void unregisterBuffers();
+ virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage);
+ virtual status_t setBufferCount(int bufferCount);
+
+ // new functions
+ void clearStat();
+ void waitUntil(int c0, int c1, int c2);
+
+private:
+ // check callback count
+ Condition mCond;
+ Mutex mLock;
+ int registerBuffersCount;
+ int postBufferCount;
+ int unregisterBuffersCount;
+};
+
+status_t MSurface::registerBuffers(const BufferHeap& buffers) {
+ INFO("%s", __func__);
+ Mutex::Autolock _l(mLock);
+ ++registerBuffersCount;
+ mCond.signal();
+ return NO_ERROR;
+}
+
+void MSurface::postBuffer(ssize_t offset) {
+ // INFO("%s", __func__);
+ Mutex::Autolock _l(mLock);
+ ++postBufferCount;
+ mCond.signal();
+}
+
+void MSurface::unregisterBuffers() {
+ INFO("%s", __func__);
+ Mutex::Autolock _l(mLock);
+ ++unregisterBuffersCount;
+ mCond.signal();
+}
+
+sp<GraphicBuffer> MSurface::requestBuffer(int bufferIdx, int usage) {
+ INFO("%s", __func__);
+ return NULL;
+}
+
+status_t MSurface::setBufferCount(int bufferCount) {
+ INFO("%s", __func__);
+ return NULL;
+}
+
+void MSurface::clearStat() {
+ Mutex::Autolock _l(mLock);
+ registerBuffersCount = 0;
+ postBufferCount = 0;
+ unregisterBuffersCount = 0;
+}
+
+void MSurface::waitUntil(int c0, int c1, int c2) {
+ INFO("waitUntil: %d %d %d", c0, c1, c2);
+ Mutex::Autolock _l(mLock);
+ while (true) {
+ if (registerBuffersCount >= c0 &&
+ postBufferCount >= c1 &&
+ unregisterBuffersCount >= c2) {
+ break;
+ }
+ mCond.wait(mLock);
+ }
+}
+
+//
+// Utilities to use the Holder service
+//
+sp<IHolder> getHolder() {
+ sp<IServiceManager> sm = defaultServiceManager();
+ ASSERT(sm != 0);
+ sp<IBinder> binder = sm->getService(String16("CameraServiceTest.Holder"));
+ ASSERT(binder != 0);
+ sp<IHolder> holder = interface_cast<IHolder>(binder);
+ ASSERT(holder != 0);
+ return holder;
+}
+
+void putTempObject(sp<IBinder> obj) {
+ INFO("%s", __func__);
+ getHolder()->put(obj);
+}
+
+sp<IBinder> getTempObject() {
+ INFO("%s", __func__);
+ return getHolder()->get();
+}
+
+void clearTempObject() {
+ INFO("%s", __func__);
+ getHolder()->clear();
+}
+
+//
+// Get a Camera Service
+//
+sp<ICameraService> getCameraService() {
+ sp<IServiceManager> sm = defaultServiceManager();
+ ASSERT(sm != 0);
+ sp<IBinder> binder = sm->getService(String16("media.camera"));
+ ASSERT(binder != 0);
+ sp<ICameraService> cs = interface_cast<ICameraService>(binder);
+ ASSERT(cs != 0);
+ return cs;
+}
+
+int getNumberOfCameras() {
+ sp<ICameraService> cs = getCameraService();
+ return cs->getNumberOfCameras();
+}
+
+//
+// Various Connect Tests
+//
+void testConnect(int cameraId) {
+ INFO("%s", __func__);
+ sp<ICameraService> cs = getCameraService();
+ sp<MCameraClient> cc = new MCameraClient();
+ sp<ICamera> c = cs->connect(cc, cameraId);
+ ASSERT(c != 0);
+ c->disconnect();
+}
+
+void testAllowConnectOnceOnly(int cameraId) {
+ INFO("%s", __func__);
+ sp<ICameraService> cs = getCameraService();
+ // Connect the first client.
+ sp<MCameraClient> cc = new MCameraClient();
+ sp<ICamera> c = cs->connect(cc, cameraId);
+ ASSERT(c != 0);
+ // Same client -- ok.
+ ASSERT(cs->connect(cc, cameraId) != 0);
+ // Different client -- not ok.
+ sp<MCameraClient> cc2 = new MCameraClient();
+ ASSERT(cs->connect(cc2, cameraId) == 0);
+ c->disconnect();
+}
+
+void testReconnectFailed() {
+ INFO("%s", __func__);
+ sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+ sp<MCameraClient> cc = new MCameraClient();
+ ASSERT(c->connect(cc) != NO_ERROR);
+}
+
+void testReconnectSuccess() {
+ INFO("%s", __func__);
+ sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+ sp<MCameraClient> cc = new MCameraClient();
+ ASSERT(c->connect(cc) == NO_ERROR);
+ c->disconnect();
+}
+
+void testLockFailed() {
+ INFO("%s", __func__);
+ sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+ ASSERT(c->lock() != NO_ERROR);
+}
+
+void testLockUnlockSuccess() {
+ INFO("%s", __func__);
+ sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+ ASSERT(c->lock() == NO_ERROR);
+ ASSERT(c->unlock() == NO_ERROR);
+}
+
+void testLockSuccess() {
+ INFO("%s", __func__);
+ sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+ ASSERT(c->lock() == NO_ERROR);
+ c->disconnect();
+}
+
+//
+// Run the connect tests in another process.
+//
+const char *gExecutable;
+
+struct FunctionTableEntry {
+ const char *name;
+ void (*func)();
+};
+
+FunctionTableEntry function_table[] = {
+#define ENTRY(x) {#x, &x}
+ ENTRY(testReconnectFailed),
+ ENTRY(testReconnectSuccess),
+ ENTRY(testLockUnlockSuccess),
+ ENTRY(testLockFailed),
+ ENTRY(testLockSuccess),
+#undef ENTRY
+};
+
+void runFunction(const char *tag) {
+ INFO("runFunction: %s", tag);
+ int entries = sizeof(function_table) / sizeof(function_table[0]);
+ for (int i = 0; i < entries; i++) {
+ if (strcmp(function_table[i].name, tag) == 0) {
+ (*function_table[i].func)();
+ return;
+ }
+ }
+ ASSERT(0);
+}
+
+void runInAnotherProcess(const char *tag) {
+ pid_t pid = fork();
+ if (pid == 0) {
+ execlp(gExecutable, gExecutable, tag, NULL);
+ ASSERT(0);
+ } else {
+ int status;
+ ASSERT_EQ(pid, wait(&status));
+ ASSERT_EQ(0, status);
+ }
+}
+
+void testReconnect(int cameraId) {
+ INFO("%s", __func__);
+ sp<ICameraService> cs = getCameraService();
+ sp<MCameraClient> cc = new MCameraClient();
+ sp<ICamera> c = cs->connect(cc, cameraId);
+ ASSERT(c != 0);
+ // Reconnect to the same client -- ok.
+ ASSERT(c->connect(cc) == NO_ERROR);
+ // Reconnect to a different client (but the same pid) -- ok.
+ sp<MCameraClient> cc2 = new MCameraClient();
+ ASSERT(c->connect(cc2) == NO_ERROR);
+ c->disconnect();
+ cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+}
+
+void testLockUnlock(int cameraId) {
+ sp<ICameraService> cs = getCameraService();
+ sp<MCameraClient> cc = new MCameraClient();
+ sp<ICamera> c = cs->connect(cc, cameraId);
+ ASSERT(c != 0);
+ // We can lock as many times as we want.
+ ASSERT(c->lock() == NO_ERROR);
+ ASSERT(c->lock() == NO_ERROR);
+ // Lock from a different process -- not ok.
+ putTempObject(c->asBinder());
+ runInAnotherProcess("testLockFailed");
+ // Unlock then lock from a different process -- ok.
+ ASSERT(c->unlock() == NO_ERROR);
+ runInAnotherProcess("testLockUnlockSuccess");
+ // Unlock then lock from a different process -- ok.
+ runInAnotherProcess("testLockSuccess");
+ clearTempObject();
+}
+
+void testReconnectFromAnotherProcess(int cameraId) {
+ INFO("%s", __func__);
+
+ sp<ICameraService> cs = getCameraService();
+ sp<MCameraClient> cc = new MCameraClient();
+ sp<ICamera> c = cs->connect(cc, cameraId);
+ ASSERT(c != 0);
+ // Reconnect from a different process -- not ok.
+ putTempObject(c->asBinder());
+ runInAnotherProcess("testReconnectFailed");
+ // Unlock then reconnect from a different process -- ok.
+ ASSERT(c->unlock() == NO_ERROR);
+ runInAnotherProcess("testReconnectSuccess");
+ clearTempObject();
+}
+
+// We need to flush the command buffer after the reference
+// to ICamera is gone. The sleep is for the server to run
+// the destructor for it.
+static void flushCommands() {
+ IPCThreadState::self()->flushCommands();
+ usleep(200000); // 200ms
+}
+
+// Run a test case
+#define RUN(class_name, cameraId) do { \
+ { \
+ INFO(#class_name); \
+ class_name instance; \
+ instance.init(cameraId); \
+ instance.run(); \
+ } \
+ flushCommands(); \
+} while(0)
+
+// Base test case after the the camera is connected.
+class AfterConnect {
+public:
+ void init(int cameraId) {
+ cs = getCameraService();
+ cc = new MCameraClient();
+ c = cs->connect(cc, cameraId);
+ ASSERT(c != 0);
+ }
+
+protected:
+ sp<ICameraService> cs;
+ sp<MCameraClient> cc;
+ sp<ICamera> c;
+
+ ~AfterConnect() {
+ c->disconnect();
+ c.clear();
+ cc.clear();
+ cs.clear();
+ }
+};
+
+class TestSetPreviewDisplay : public AfterConnect {
+public:
+ void run() {
+ sp<MSurface> surface = new MSurface();
+ ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+ c->disconnect();
+ cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+ }
+};
+
+class TestStartPreview : public AfterConnect {
+public:
+ void run() {
+ sp<MSurface> surface = new MSurface();
+ ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+
+ ASSERT(c->startPreview() == NO_ERROR);
+ ASSERT(c->previewEnabled() == true);
+
+ surface->waitUntil(1, 10, 0); // needs 1 registerBuffers and 10 postBuffer
+ surface->clearStat();
+
+ sp<MSurface> another_surface = new MSurface();
+ c->setPreviewDisplay(another_surface); // just to make sure unregisterBuffers
+ // is called.
+ surface->waitUntil(0, 0, 1); // needs unregisterBuffers
+
+ cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+ }
+};
+
+class TestStartPreviewWithoutDisplay : public AfterConnect {
+public:
+ void run() {
+ ASSERT(c->startPreview() == NO_ERROR);
+ ASSERT(c->previewEnabled() == true);
+ c->disconnect();
+ cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+ }
+};
+
+// Base test case after the the camera is connected and the preview is started.
+class AfterStartPreview : public AfterConnect {
+public:
+ void init(int cameraId) {
+ AfterConnect::init(cameraId);
+ surface = new MSurface();
+ ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+ ASSERT(c->startPreview() == NO_ERROR);
+ }
+
+protected:
+ sp<MSurface> surface;
+
+ ~AfterStartPreview() {
+ surface.clear();
+ }
+};
+
+class TestAutoFocus : public AfterStartPreview {
+public:
+ void run() {
+ cc->assertNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 0);
+ c->autoFocus();
+ cc->waitNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 1);
+ c->disconnect();
+ cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+ }
+};
+
+class TestStopPreview : public AfterStartPreview {
+public:
+ void run() {
+ ASSERT(c->previewEnabled() == true);
+ c->stopPreview();
+ ASSERT(c->previewEnabled() == false);
+ c->disconnect();
+ cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+ }
+};
+
+class TestTakePicture: public AfterStartPreview {
+public:
+ void run() {
+ ASSERT(c->takePicture() == NO_ERROR);
+ cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
+ cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
+ cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
+ c->stopPreview();
+ c->disconnect();
+ cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+ }
+};
+
+class TestTakeMultiplePictures: public AfterStartPreview {
+public:
+ void run() {
+ for (int i = 0; i < 10; i++) {
+ cc->clearStat();
+ ASSERT(c->takePicture() == NO_ERROR);
+ cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
+ cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
+ cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
+ }
+ c->disconnect();
+ cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+ }
+};
+
+class TestGetParameters: public AfterStartPreview {
+public:
+ void run() {
+ String8 param_str = c->getParameters();
+ INFO("%s", static_cast<const char*>(param_str));
+ }
+};
+
+static bool getNextSize(const char **ptrS, int *w, int *h) {
+ const char *s = *ptrS;
+
+ // skip over ','
+ if (*s == ',') s++;
+
+ // remember start position in p
+ const char *p = s;
+ while (*s != '\0' && *s != 'x') {
+ s++;
+ }
+ if (*s == '\0') return false;
+
+ // get the width
+ *w = atoi(p);
+
+ // skip over 'x'
+ ASSERT(*s == 'x');
+ p = s + 1;
+ while (*s != '\0' && *s != ',') {
+ s++;
+ }
+
+ // get the height
+ *h = atoi(p);
+ *ptrS = s;
+ return true;
+}
+
+class TestPictureSize : public AfterStartPreview {
+public:
+ void checkOnePicture(int w, int h) {
+ const float rate = 0.9; // byte per pixel limit
+ int pixels = w * h;
+
+ CameraParameters param(c->getParameters());
+ param.setPictureSize(w, h);
+ // disable thumbnail to get more accurate size.
+ param.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, 0);
+ param.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, 0);
+ c->setParameters(param.flatten());
+
+ cc->clearStat();
+ ASSERT(c->takePicture() == NO_ERROR);
+ cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
+ //cc->assertDataSize(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, pixels*3/2);
+ cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
+ cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::LT,
+ int(pixels * rate));
+ cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::GT, 0);
+ cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+ }
+
+ void run() {
+ CameraParameters param(c->getParameters());
+ int w, h;
+ const char *s = param.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES);
+ while (getNextSize(&s, &w, &h)) {
+ ALOGD("checking picture size %dx%d", w, h);
+ checkOnePicture(w, h);
+ }
+ }
+};
+
+class TestPreviewCallbackFlag : public AfterConnect {
+public:
+ void run() {
+ sp<MSurface> surface = new MSurface();
+ ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+
+ // Try all flag combinations.
+ for (int v = 0; v < 8; v++) {
+ ALOGD("TestPreviewCallbackFlag: flag=%d", v);
+ usleep(100000); // sleep a while to clear the in-flight callbacks.
+ cc->clearStat();
+ c->setPreviewCallbackFlag(v);
+ ASSERT(c->previewEnabled() == false);
+ ASSERT(c->startPreview() == NO_ERROR);
+ ASSERT(c->previewEnabled() == true);
+ sleep(2);
+ c->stopPreview();
+ if ((v & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) == 0) {
+ cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 0);
+ } else {
+ if ((v & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) == 0) {
+ cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 10);
+ } else {
+ cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 1);
+ }
+ }
+ }
+ }
+};
+
+class TestRecording : public AfterConnect {
+public:
+ void run() {
+ ASSERT(c->recordingEnabled() == false);
+ sp<MSurface> surface = new MSurface();
+ ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+ c->setPreviewCallbackFlag(CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
+ cc->setReleaser(c.get());
+ c->startRecording();
+ ASSERT(c->recordingEnabled() == true);
+ sleep(2);
+ c->stopRecording();
+ usleep(100000); // sleep a while to clear the in-flight callbacks.
+ cc->setReleaser(NULL);
+ cc->assertData(CAMERA_MSG_VIDEO_FRAME, MCameraClient::GE, 10);
+ }
+};
+
+class TestPreviewSize : public AfterStartPreview {
+public:
+ void checkOnePicture(int w, int h) {
+ int size = w*h*3/2; // should read from parameters
+
+ c->stopPreview();
+
+ CameraParameters param(c->getParameters());
+ param.setPreviewSize(w, h);
+ c->setPreviewCallbackFlag(CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
+ c->setParameters(param.flatten());
+
+ c->startPreview();
+
+ cc->clearStat();
+ cc->waitData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 1);
+ cc->assertDataSize(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, size);
+ }
+
+ void run() {
+ CameraParameters param(c->getParameters());
+ int w, h;
+ const char *s = param.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES);
+ while (getNextSize(&s, &w, &h)) {
+ ALOGD("checking preview size %dx%d", w, h);
+ checkOnePicture(w, h);
+ }
+ }
+};
+
+void runHolderService() {
+ defaultServiceManager()->addService(
+ String16("CameraServiceTest.Holder"), new HolderService());
+ ProcessState::self()->startThreadPool();
+}
+
+int main(int argc, char **argv)
+{
+ if (argc != 1) {
+ runFunction(argv[1]);
+ return 0;
+ }
+ INFO("CameraServiceTest start");
+ gExecutable = argv[0];
+ runHolderService();
+ int n = getNumberOfCameras();
+ INFO("%d Cameras available", n);
+
+ for (int id = 0; id < n; id++) {
+ INFO("Testing camera %d", id);
+ testConnect(id); flushCommands();
+ testAllowConnectOnceOnly(id); flushCommands();
+ testReconnect(id); flushCommands();
+ testLockUnlock(id); flushCommands();
+ testReconnectFromAnotherProcess(id); flushCommands();
+
+ RUN(TestSetPreviewDisplay, id);
+ RUN(TestStartPreview, id);
+ RUN(TestStartPreviewWithoutDisplay, id);
+ RUN(TestAutoFocus, id);
+ RUN(TestStopPreview, id);
+ RUN(TestTakePicture, id);
+ RUN(TestTakeMultiplePictures, id);
+ RUN(TestGetParameters, id);
+ RUN(TestPictureSize, id);
+ RUN(TestPreviewCallbackFlag, id);
+ RUN(TestRecording, id);
+ RUN(TestPreviewSize, id);
+ }
+
+ INFO("CameraServiceTest finished");
+}